]> git.proxmox.com Git - mirror_smartmontools-debian.git/blame - os_freebsd.cpp
import smartmontools 7.0
[mirror_smartmontools-debian.git] / os_freebsd.cpp
CommitLineData
832b75ed
GG
1/*
2 * os_freebsd.c
3 *
a86ec89e 4 * Home page of code is: http://www.smartmontools.org
832b75ed 5 *
a86ec89e 6 * Copyright (C) 2003-10 Eduard Martinescu
832b75ed 7 *
ff28b140 8 * SPDX-License-Identifier: GPL-2.0-or-later
832b75ed
GG
9 */
10
ff28b140 11#include <sys/param.h>
832b75ed
GG
12#include <stdio.h>
13#include <sys/types.h>
14#include <dirent.h>
15#include <fcntl.h>
16#include <err.h>
cfbba5b9 17#include <errno.h>
832b75ed
GG
18#include <camlib.h>
19#include <cam/scsi/scsi_message.h>
2127e193 20#include <cam/scsi/scsi_pass.h>
1953ff6d
GG
21#if defined(__DragonFly__)
22#include <sys/nata.h>
23#else
832b75ed 24#include <sys/ata.h>
1953ff6d 25#endif
832b75ed
GG
26#include <sys/stat.h>
27#include <unistd.h>
832b75ed 28#include <glob.h>
832b75ed 29#include <stddef.h>
2127e193
GI
30#include <paths.h>
31#include <sys/utsname.h>
832b75ed
GG
32
33#include "config.h"
ff28b140 34
a86ec89e
GI
35// set by /usr/include/sys/ata.h, suppress warning
36#undef ATA_READ_LOG_EXT
832b75ed
GG
37#include "atacmds.h"
38#include "scsicmds.h"
a37e7145 39#include "cciss.h"
832b75ed
GG
40#include "utility.h"
41#include "os_freebsd.h"
42
2127e193
GI
43#include "dev_interface.h"
44#include "dev_ata_cmd_set.h"
ee38a438 45#include "dev_areca.h"
2127e193
GI
46
47#define USBDEV "/dev/usb"
54965743
GI
48#if defined(__FreeBSD_version)
49
50// This way we define one variable for the GNU/kFreeBSD and FreeBSD
51#define FREEBSDVER __FreeBSD_version
52#else
53#define FREEBSDVER __FreeBSD_kernel_version
54#endif
55
56#if (FREEBSDVER >= 800000)
57#include <libusb20_desc.h>
58#include <libusb20.h>
cfbba5b9
GI
59#elif defined(__DragonFly__)
60#include <bus/usb/usb.h>
61#include <bus/usb/usbhid.h>
54965743
GI
62#else
63#include <dev/usb/usb.h>
64#include <dev/usb/usbhid.h>
65#endif
832b75ed 66
a86ec89e
GI
67// based on "/sys/dev/nvme/nvme.h" from FreeBSD kernel sources
68#include "freebsd_nvme_ioctl.h" // NVME_PASSTHROUGH_CMD, nvme_completion_is_error
69
eb07ddf2
GI
70#define CONTROLLER_3WARE_9000_CHAR 0x01
71#define CONTROLLER_3WARE_678K_CHAR 0x02
a37e7145 72
eb07ddf2
GI
73#ifndef PATHINQ_SETTINGS_SIZE
74#define PATHINQ_SETTINGS_SIZE 128
75#endif
832b75ed 76
ff28b140
TL
77const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 4848 2018-12-05 18:30:46Z chrfranke $" \
78ATACMDS_H_CVSID CCISS_H_CVSID CONFIG_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
54965743 79
832b75ed
GG
80#define NO_RETURN 0
81#define BAD_SMART 1
82#define NO_DISK_3WARE 2
83#define BAD_KERNEL 3
84#define MAX_MSG 3
85
86// Utility function for printing warnings
87void printwarning(int msgNo, const char* extra) {
54965743 88
a86ec89e
GI
89 if (msgNo >= 0 && msgNo <= MAX_MSG) {
90 static int printed[] = {0,0,0,0};
91 if (!printed[msgNo]) {
54965743 92
a86ec89e
GI
93 static const char* message[]={
94 "The SMART RETURN STATUS return value (smartmontools -H option/Directive)\n can not be retrieved with this version of ATAng, please do not rely on this value\nYou should update to at least 5.2\n",
54965743 95
a86ec89e
GI
96 "Error SMART Status command failed\nPlease get assistance from \n" PACKAGE_HOMEPAGE "\nRegister values returned from SMART Status command are:\n",
97
98 "You must specify a DISK # for 3ware drives with -d 3ware,<n> where <n> begins with 1 for first disk drive\n",
99
100 "ATA support is not provided for this kernel version. Please ugrade to a recent 5-CURRENT kernel (post 09/01/2003 or so)\n"
101 };
832b75ed 102
832b75ed
GG
103 printed[msgNo] = 1;
104 pout("%s", message[msgNo]);
105 if (extra)
106 pout("%s",extra);
107 }
108 }
109 return;
110}
111
2127e193 112// Interface to ATA devices behind 3ware escalade RAID controller cards. See os_linux.c
832b75ed 113
2127e193
GI
114#define BUFFER_LEN_678K_CHAR ( sizeof(struct twe_usercommand) ) // 520
115#define BUFFER_LEN_9000_CHAR ( sizeof(TW_OSLI_IOCTL_NO_DATA_BUF) + sizeof(TWE_Command) ) // 2048
116#define TW_IOCTL_BUFFER_SIZE ( MAX(BUFFER_LEN_678K_CHAR, BUFFER_LEN_9000_CHAR) )
4d59bff9 117
2127e193
GI
118#ifndef ATA_DEVICE
119#define ATA_DEVICE "/dev/ata"
832b75ed 120#endif
832b75ed 121
d008864d
GI
122#define ARGUSED(x) ((void)(x))
123
ee38a438 124extern unsigned char failuretest_permissive;
832b75ed 125
2127e193 126/////////////////////////////////////////////////////////////////////////////
832b75ed 127
2127e193 128namespace os_freebsd { // No need to publish anything, name provided for Doxygen
832b75ed 129
2127e193
GI
130/////////////////////////////////////////////////////////////////////////////
131/// Implement shared open/close routines with old functions.
832b75ed 132
2127e193
GI
133class freebsd_smart_device
134: virtual public /*implements*/ smart_device
135{
136public:
d2e702cf 137 explicit freebsd_smart_device()
2127e193 138 : smart_device(never_called),
d2e702cf 139 m_fd(-1) { }
832b75ed 140
2127e193 141 virtual ~freebsd_smart_device() throw();
832b75ed 142
2127e193 143 virtual bool is_open() const;
832b75ed 144
2127e193 145 virtual bool open();
832b75ed 146
2127e193 147 virtual bool close();
832b75ed 148
2127e193
GI
149protected:
150 /// Return filedesc for derived classes.
151 int get_fd() const
152 { return m_fd; }
832b75ed 153
eb07ddf2
GI
154 void set_fd(int fd)
155 { m_fd = fd; }
156
2127e193
GI
157private:
158 int m_fd; ///< filedesc, -1 if not open.
2127e193 159};
832b75ed 160
54965743
GI
161#ifdef __GLIBC__
162static inline void * reallocf(void *ptr, size_t size) {
163 void *rv = realloc(ptr, size);
f4ebf3d1 164 if((rv == NULL) && (size != 0))
54965743
GI
165 free(ptr);
166 return rv;
167 }
168#endif
2127e193
GI
169
170freebsd_smart_device::~freebsd_smart_device() throw()
a37e7145 171{
2127e193
GI
172 if (m_fd >= 0)
173 os_freebsd::freebsd_smart_device::close();
a37e7145
GG
174}
175
2127e193
GI
176// migration from the old_style
177unsigned char m_controller_type;
178unsigned char m_controller_port;
832b75ed 179
2127e193
GI
180// examples for smartctl
181static const char smartctl_examples[] =
54965743 182 "=================================================== SMARTCTL EXAMPLES =====\n\n"
2127e193
GI
183 " smartctl -a /dev/ad0 (Prints all SMART information)\n\n"
184 " smartctl --smart=on --offlineauto=on --saveauto=on /dev/ad0\n"
185 " (Enables SMART on first disk)\n\n"
186 " smartctl -t long /dev/ad0 (Executes extended disk self-test)\n\n"
187 " smartctl --attributes --log=selftest --quietmode=errorsonly /dev/ad0\n"
188 " (Prints Self-Test & Attribute errors)\n"
189 " (Prints Self-Test & Attribute errors)\n\n"
190 " smartctl -a --device=3ware,2 /dev/twa0\n"
191 " smartctl -a --device=3ware,2 /dev/twe0\n"
ee38a438 192 " smartctl -a --device=3ware,2 /dev/tws0\n"
2127e193
GI
193 " (Prints all SMART information for ATA disk on\n"
194 " third port of first 3ware RAID controller)\n"
54965743
GI
195 " smartctl -a --device=cciss,0 /dev/ciss0\n"
196 " (Prints all SMART information for first disk \n"
197 " on Common Interface for SCSI-3 Support driver)\n"
f4e463df
GI
198 " smartctl -a --device=areca,3/1 /dev/arcmsr0\n"
199 " (Prints all SMART information for 3rd disk in the 1st enclosure \n"
d008864d 200 " on first ARECA RAID controller)\n"
54965743 201
2127e193 202 ;
832b75ed 203
2127e193
GI
204bool freebsd_smart_device::is_open() const
205{
206 return (m_fd >= 0);
207}
832b75ed 208
832b75ed 209
2127e193
GI
210bool freebsd_smart_device::open()
211{
2127e193 212 const char *dev = get_dev_name();
eb07ddf2
GI
213 if ((m_fd = ::open(dev,O_RDONLY))<0) {
214 set_err(errno);
2127e193
GI
215 return false;
216 }
217 return true;
218}
219
220bool freebsd_smart_device::close()
221{
2127e193 222 int failed = 0;
2127e193 223 // close device, if open
eb07ddf2
GI
224 if (is_open())
225 failed=::close(get_fd());
226
227 set_fd(-1);
54965743 228
54965743 229 if(failed) return false;
eb07ddf2 230 else return true;
2127e193
GI
231}
232
233/////////////////////////////////////////////////////////////////////////////
a23d5117 234/// Implement standard ATA support
2127e193
GI
235
236class freebsd_ata_device
a23d5117 237: public /*implements*/ ata_device,
2127e193
GI
238 public /*extends*/ freebsd_smart_device
239{
240public:
241 freebsd_ata_device(smart_interface * intf, const char * dev_name, const char * req_type);
a23d5117 242 virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
2127e193 243
2127e193 244protected:
d008864d 245 virtual int do_cmd(struct ata_ioc_request* request, bool is_48bit_cmd);
2127e193
GI
246};
247
248freebsd_ata_device::freebsd_ata_device(smart_interface * intf, const char * dev_name, const char * req_type)
249: smart_device(intf, dev_name, "ata", req_type),
d2e702cf 250 freebsd_smart_device()
2127e193
GI
251{
252}
253
d008864d 254int freebsd_ata_device::do_cmd( struct ata_ioc_request* request, bool is_48bit_cmd)
eb07ddf2 255{
ee38a438 256 int fd = get_fd(), ret;
d008864d 257 ARGUSED(is_48bit_cmd); // no support for 48 bit commands in the IOCATAREQUEST
ee38a438
GI
258 ret = ioctl(fd, IOCATAREQUEST, request);
259 if (ret) set_err(errno);
260 return ret;
eb07ddf2
GI
261}
262
a23d5117
GI
263
264
265bool freebsd_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
266{
d008864d
GI
267 bool ata_48bit = false; // no ata_48bit_support via IOCATAREQUEST
268 if(!strcmp("atacam",get_dev_type())) // enable for atacam interface
269 ata_48bit = true;
270
7f0798ef
GI
271 if (!ata_cmd_is_ok(in,
272 true, // data_out_support
273 true, // multi_sector_support
d008864d 274 ata_48bit)
ee38a438
GI
275 ) {
276 set_err(ENOSYS, "48-bit ATA commands not implemented for legacy controllers");
277 return false;
278 }
a23d5117
GI
279
280 struct ata_ioc_request request;
281 bzero(&request,sizeof(struct ata_ioc_request));
282
283 request.timeout=SCSI_TIMEOUT_DEFAULT;
284 request.u.ata.command=in.in_regs.command;
285 request.u.ata.feature=in.in_regs.features;
286
287 request.u.ata.count = in.in_regs.sector_count_16;
288 request.u.ata.lba = in.in_regs.lba_48;
289
290 switch (in.direction) {
291 case ata_cmd_in::no_data:
292 request.flags=ATA_CMD_CONTROL;
293 break;
294 case ata_cmd_in::data_in:
d008864d 295 request.flags=ATA_CMD_READ | ATA_CMD_CONTROL;
a23d5117
GI
296 request.data=(char *)in.buffer;
297 request.count=in.size;
298 break;
299 case ata_cmd_in::data_out:
d008864d 300 request.flags=ATA_CMD_WRITE | ATA_CMD_CONTROL;
a23d5117
GI
301 request.data=(char *)in.buffer;
302 request.count=in.size;
303 break;
304 default:
305 return set_err(ENOSYS);
306 }
d008864d
GI
307
308 clear_err();
a23d5117 309 errno = 0;
d008864d 310 if (do_cmd(&request, in.in_regs.is_48bit_cmd()))
ee38a438 311 return false;
a23d5117
GI
312 if (request.error)
313 return set_err(EIO, "request failed, error code 0x%02x", request.error);
314
315 out.out_regs.error = request.error;
316 out.out_regs.sector_count_16 = request.u.ata.count;
317 out.out_regs.lba_48 = request.u.ata.lba;
318
a23d5117
GI
319 return true;
320}
321
eb07ddf2
GI
322#if FREEBSDVER > 800100
323class freebsd_atacam_device : public freebsd_ata_device
324{
325public:
326 freebsd_atacam_device(smart_interface * intf, const char * dev_name, const char * req_type)
327 : smart_device(intf, dev_name, "atacam", req_type), freebsd_ata_device(intf, dev_name, req_type)
328 {}
329
330 virtual bool open();
331 virtual bool close();
332
333protected:
334 int m_fd;
335 struct cam_device *m_camdev;
336
d008864d 337 virtual int do_cmd( struct ata_ioc_request* request , bool is_48bit_cmd);
eb07ddf2
GI
338};
339
340bool freebsd_atacam_device::open(){
341 const char *dev = get_dev_name();
342
343 if ((m_camdev = cam_open_device(dev, O_RDWR)) == NULL) {
344 set_err(errno);
345 return false;
346 }
347 set_fd(m_camdev->fd);
348 return true;
349}
350
351bool freebsd_atacam_device::close(){
352 cam_close_device(m_camdev);
353 set_fd(-1);
354 return true;
355}
356
d008864d 357int freebsd_atacam_device::do_cmd( struct ata_ioc_request* request, bool is_48bit_cmd)
eb07ddf2
GI
358{
359 union ccb ccb;
360 int camflags;
361
ee38a438
GI
362 // 48bit commands are broken in ATACAM before r242422/HEAD
363 // and may cause system hang
f9e10201
JD
364 // First version with working support should be FreeBSD 9.2.0/RELEASE
365
366#if (FREEBSDVER < 902001)
ee38a438
GI
367 if(!strcmp("ata",m_camdev->sim_name) && is_48bit_cmd) {
368 set_err(ENOSYS, "48-bit ATA commands not implemented for legacy controllers");
369 return -1;
370 }
f9e10201 371#endif
ee38a438 372
eb07ddf2
GI
373 memset(&ccb, 0, sizeof(ccb));
374
375 if (request->count == 0)
376 camflags = CAM_DIR_NONE;
d008864d 377 else if (request->flags & ATA_CMD_READ)
eb07ddf2
GI
378 camflags = CAM_DIR_IN;
379 else
380 camflags = CAM_DIR_OUT;
381
382 cam_fill_ataio(&ccb.ataio,
383 0,
384 NULL,
385 camflags,
386 MSG_SIMPLE_Q_TAG,
387 (u_int8_t*)request->data,
388 request->count,
389 request->timeout * 1000); // timeout in seconds
390
ee38a438
GI
391 ccb.ataio.cmd.flags = CAM_ATAIO_NEEDRESULT |
392 (is_48bit_cmd ? CAM_ATAIO_48BIT : 0);
eb07ddf2 393 // ata_28bit_cmd
eb07ddf2
GI
394 ccb.ataio.cmd.command = request->u.ata.command;
395 ccb.ataio.cmd.features = request->u.ata.feature;
396 ccb.ataio.cmd.lba_low = request->u.ata.lba;
397 ccb.ataio.cmd.lba_mid = request->u.ata.lba >> 8;
398 ccb.ataio.cmd.lba_high = request->u.ata.lba >> 16;
d008864d
GI
399 // ata_48bit cmd
400 ccb.ataio.cmd.lba_low_exp = request->u.ata.lba >> 24;
401 ccb.ataio.cmd.lba_mid_exp = request->u.ata.lba >> 32;
402 ccb.ataio.cmd.lba_high_exp = request->u.ata.lba >> 40;
eb07ddf2
GI
403 ccb.ataio.cmd.device = 0x40 | ((request->u.ata.lba >> 24) & 0x0f);
404 ccb.ataio.cmd.sector_count = request->u.ata.count;
d008864d 405 ccb.ataio.cmd.sector_count_exp = request->u.ata.count >> 8;;
eb07ddf2
GI
406
407 ccb.ccb_h.flags |= CAM_DEV_QFRZDIS;
408
409 if (cam_send_ccb(m_camdev, &ccb) < 0) {
ee38a438 410 set_err(EIO, "cam_send_ccb failed");
eb07ddf2
GI
411 return -1;
412 }
413
cfbba5b9 414 if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
d2e702cf
GI
415 if(scsi_debugmode > 0)
416 cam_error_print(m_camdev, &ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
ee38a438 417 set_err(EIO);
cfbba5b9
GI
418 return -1;
419 }
eb07ddf2 420
d008864d
GI
421 request->u.ata.lba =
422 ((u_int64_t)(ccb.ataio.res.lba_low)) |
423 ((u_int64_t)(ccb.ataio.res.lba_mid) << 8) |
424 ((u_int64_t)(ccb.ataio.res.lba_high) << 16) |
425 ((u_int64_t)(ccb.ataio.res.lba_low_exp) << 24) |
426 ((u_int64_t)(ccb.ataio.res.lba_mid_exp) << 32) |
427 ((u_int64_t)(ccb.ataio.res.lba_high_exp) << 40);
428
429 request->u.ata.count = ccb.ataio.res.sector_count | (ccb.ataio.res.sector_count_exp << 8);
430 request->error = ccb.ataio.res.error;
431
cfbba5b9 432 return 0;
eb07ddf2
GI
433}
434
435#endif
436
a86ec89e
GI
437/////////////////////////////////////////////////////////////////////////////
438/// NVMe support
439
440class freebsd_nvme_device
441: public /*implements*/ nvme_device,
442 public /*extends*/ freebsd_smart_device
443{
444public:
445 freebsd_nvme_device(smart_interface * intf, const char * dev_name,
446 const char * req_type, unsigned nsid);
447
448 virtual bool open();
449
450 virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out);
451};
452
453freebsd_nvme_device::freebsd_nvme_device(smart_interface * intf, const char * dev_name,
454 const char * req_type, unsigned nsid)
455: smart_device(intf, dev_name, "nvme", req_type),
456 nvme_device(nsid),
457 freebsd_smart_device()
458{
459}
460
461bool freebsd_nvme_device::open()
462{
463 const char *dev = get_dev_name();
464 if (!strnstr(dev, NVME_CTRLR_PREFIX, strlen(NVME_CTRLR_PREFIX))) {
465 set_err(EINVAL, "NVMe controller controller/namespace ids must begin with '%s'",
466 NVME_CTRLR_PREFIX);
467 return false;
468 }
469
470 int nsid = -1, ctrlid = -1;
471 char tmp;
472
473 if(sscanf(dev, NVME_CTRLR_PREFIX"%d%c", &ctrlid, &tmp) == 1)
474 {
475 if(ctrlid < 0) {
476 set_err(EINVAL, "Invalid NVMe controller number");
477 return false;
478 }
479 nsid = 0xFFFFFFFF; // broadcast id
480 }
ff28b140 481 else if (sscanf(dev, NVME_CTRLR_PREFIX"%d" NVME_NS_PREFIX "%d%c",
a86ec89e
GI
482 &ctrlid, &nsid, &tmp) == 2)
483 {
484 if(ctrlid < 0 || nsid < 0) {
485 set_err(EINVAL, "Invalid NVMe controller/namespace number");
486 return false;
487 }
488 }
489 else {
490 set_err(EINVAL, "Invalid NVMe controller/namespace syntax");
491 return false;
492 }
493
494 // we should always open controller, not namespace device
495 char full_path[64];
496 snprintf(full_path, sizeof(full_path), NVME_CTRLR_PREFIX"%d", ctrlid);
497
498 int fd;
499 if ((fd = ::open(full_path, O_RDWR))<0) {
500 set_err(errno);
501 return false;
502 }
503 set_fd(fd);
504
505 if (!get_nsid()) {
506 set_nsid(nsid);
507 }
508
509 return true;
510}
511
512bool freebsd_nvme_device::nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out)
513{
514 // nvme_passthru_cmd pt;
515 struct nvme_pt_command pt;
ff28b140 516 struct nvme_completion *cp_p;
a86ec89e
GI
517 memset(&pt, 0, sizeof(pt));
518
ff28b140
TL
519#if __FreeBSD_version >= 1200058 && __FreeBSD_version < 1200081
520 pt.cmd.opc_fuse = NVME_CMD_SET_OPC(in.opcode);
521#else
522 pt.cmd.opc = in.opcode;
523#endif
a86ec89e
GI
524 pt.cmd.opc = in.opcode;
525 pt.cmd.nsid = in.nsid;
526 pt.buf = in.buffer;
527 pt.len = in.size;
528 pt.cmd.cdw10 = in.cdw10;
529 pt.cmd.cdw11 = in.cdw11;
530 pt.cmd.cdw12 = in.cdw12;
531 pt.cmd.cdw13 = in.cdw13;
532 pt.cmd.cdw14 = in.cdw14;
533 pt.cmd.cdw15 = in.cdw15;
534 pt.is_read = 1; // should we use in.direction()?
535
536 int status = ioctl(get_fd(), NVME_PASSTHROUGH_CMD, &pt);
537
538 if (status < 0)
539 return set_err(errno, "NVME_PASSTHROUGH_CMD: %s", strerror(errno));
540
ff28b140
TL
541 cp_p = &pt.cpl;
542 out.result=cp_p->cdw0; // Command specific result (DW0)
543
544 if (nvme_completion_is_error(cp_p)) { /* ignore DNR and More bits */
545 uint16_t nvme_status = ((cp_p->status.sct << 8) | cp_p->status.sc) & 0x3ff;
a86ec89e 546
ff28b140
TL
547 return set_nvme_err(out, nvme_status);
548 }
a86ec89e
GI
549
550 return true;
551}
552
2127e193 553/////////////////////////////////////////////////////////////////////////////
ee38a438 554/// Implement AMCC/3ware RAID support
2127e193
GI
555
556class freebsd_escalade_device
ee38a438 557: public /*implements*/ ata_device,
2127e193
GI
558 public /*extends*/ freebsd_smart_device
559{
560public:
561 freebsd_escalade_device(smart_interface * intf, const char * dev_name,
562 int escalade_type, int disknum);
563
564protected:
ee38a438 565 virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
eb07ddf2 566 virtual bool open();
2127e193
GI
567
568private:
569 int m_escalade_type; ///< Type string for escalade_command_interface().
570 int m_disknum; ///< Disk number.
571};
572
573freebsd_escalade_device::freebsd_escalade_device(smart_interface * intf, const char * dev_name,
574 int escalade_type, int disknum)
575: smart_device(intf, dev_name, "3ware", "3ware"),
d2e702cf 576 freebsd_smart_device(),
2127e193
GI
577 m_escalade_type(escalade_type), m_disknum(disknum)
578{
579 set_info().info_name = strprintf("%s [3ware_disk_%02d]", dev_name, disknum);
580}
581
eb07ddf2
GI
582bool freebsd_escalade_device::open()
583{
584 const char *dev = get_dev_name();
585 int fd;
586
587 if ((fd = ::open(dev,O_RDWR))<0) {
588 set_err(errno);
589 return false;
590 }
591 set_fd(fd);
592 return true;
593}
594
ee38a438 595bool freebsd_escalade_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
2127e193 596{
54965743
GI
597 // to hold true file descriptor
598 int fd = get_fd();
2127e193 599
ee38a438
GI
600 if (!ata_cmd_is_ok(in,
601 true, // data_out_support
602 false, // TODO: multi_sector_support
603 true) // ata_48bit_support
604 )
605 return false;
606
2127e193
GI
607 struct twe_usercommand* cmd_twe = NULL;
608 TW_OSLI_IOCTL_NO_DATA_BUF* cmd_twa = NULL;
609 TWE_Command_ATA* ata = NULL;
610
611 // Used by both the SCSI and char interfaces
612 char ioctl_buffer[TW_IOCTL_BUFFER_SIZE];
613
614 if (m_disknum < 0) {
615 printwarning(NO_DISK_3WARE,NULL);
ff28b140 616 return false;
2127e193
GI
617 }
618
2127e193
GI
619 memset(ioctl_buffer, 0, TW_IOCTL_BUFFER_SIZE);
620
621 if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR) {
622 cmd_twa = (TW_OSLI_IOCTL_NO_DATA_BUF*)ioctl_buffer;
623 cmd_twa->pdata = ((TW_OSLI_IOCTL_WITH_PAYLOAD*)cmd_twa)->payload.data_buf;
ee38a438
GI
624 cmd_twa->driver_pkt.buffer_length = in.size;
625 // using "old" packet format to speak with SATA devices
2127e193
GI
626 ata = (TWE_Command_ATA*)&cmd_twa->cmd_pkt.command.cmd_pkt_7k;
627 } else if (m_escalade_type==CONTROLLER_3WARE_678K_CHAR) {
628 cmd_twe = (struct twe_usercommand*)ioctl_buffer;
629 ata = &cmd_twe->tu_command.ata;
630 } else {
ee38a438
GI
631 return set_err(ENOSYS,
632 "Unrecognized escalade_type %d in linux_3ware_command_interface(disk %d)\n"
633 "Please contact " PACKAGE_BUGREPORT "\n", (int)m_escalade_type, m_disknum);
2127e193
GI
634 }
635
636 ata->opcode = TWE_OP_ATA_PASSTHROUGH;
637
638 // Same for (almost) all commands - but some reset below
639 ata->request_id = 0xFF;
640 ata->unit = m_disknum;
ee38a438 641 ata->status = 0;
2127e193 642 ata->flags = 0x1;
ee38a438
GI
643 ata->size = 0x5; // TODO: multisector support
644 // Set registers
645 {
646 const ata_in_regs_48bit & r = in.in_regs;
647 ata->features = r.features_16;
648 ata->sector_count = r.sector_count_16;
649 ata->sector_num = r.lba_low_16;
650 ata->cylinder_lo = r.lba_mid_16;
651 ata->cylinder_hi = r.lba_high_16;
652 ata->drive_head = r.device;
653 ata->command = r.command;
654 }
54965743 655
2127e193
GI
656 // Is this a command that reads or returns 512 bytes?
657 // passthru->param values are:
658 // 0x0 - non data command without TFR write check,
659 // 0x8 - non data command with TFR write check,
660 // 0xD - data command that returns data to host from device
661 // 0xF - data command that writes data from host to device
662 // passthru->size values are 0x5 for non-data and 0x07 for data
ee38a438
GI
663 bool readdata = false;
664 if (in.direction == ata_cmd_in::data_in) {
2127e193 665 if (m_escalade_type==CONTROLLER_3WARE_678K_CHAR) {
ee38a438 666 cmd_twe->tu_data = in.buffer;
2127e193
GI
667 cmd_twe->tu_size = 512;
668 }
ee38a438
GI
669
670 readdata=true;
671 ata->sgl_offset = 0x5;
2127e193 672 ata->param = 0xD;
2127e193
GI
673 // For 64-bit to work correctly, up the size of the command packet
674 // in dwords by 1 to account for the 64-bit single sgl 'address'
675 // field. Note that this doesn't agree with the typedefs but it's
676 // right (agree with kernel driver behavior/typedefs).
ee38a438 677 // if (sizeof(long)==8)
2127e193
GI
678 // ata->size++;
679 }
ee38a438 680 else if (in.direction == ata_cmd_in::no_data) {
2127e193 681 // Non data command -- but doesn't use large sector
ee38a438
GI
682 // count register values.
683 ata->sgl_offset = 0x0;
2127e193
GI
684 ata->param = 0x8;
685 ata->sector_count = 0x0;
686 }
ee38a438
GI
687 else if (in.direction == ata_cmd_in::data_out) {
688 ata->sgl_offset = 0x5;
689 ata->param = 0xF; // PIO data write
690 if (m_escalade_type==CONTROLLER_3WARE_678K_CHAR) {
691 cmd_twe->tu_data = in.buffer;
692 cmd_twe->tu_size = 512;
693 }
694 else if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR) {
695 memcpy(cmd_twa->pdata, in.buffer, in.size);
696 }
697 }
698 else
699 return set_err(EINVAL);
54965743 700
ee38a438
GI
701 // 3WARE controller can NOT have packet device internally
702 if (in.in_regs.command == ATA_IDENTIFY_PACKET_DEVICE) {
703 return set_err(ENODEV, "No drive on port %d", m_disknum);
2127e193
GI
704 }
705
706 // Now send the command down through an ioctl()
ee38a438 707 int ioctlreturn;
2127e193 708 if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR) {
eb07ddf2 709 ioctlreturn=ioctl(fd,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH,cmd_twa);
2127e193 710 } else {
eb07ddf2 711 ioctlreturn=ioctl(fd,TWEIO_COMMAND,cmd_twe);
2127e193
GI
712 }
713
714 // Deal with the different error cases
715 if (ioctlreturn) {
ee38a438 716 return set_err(EIO);
2127e193 717 }
54965743 718
2127e193
GI
719 // See if the ATA command failed. Now that we have returned from
720 // the ioctl() call, if passthru is valid, then:
721 // - ata->status contains the 3ware controller STATUS
722 // - ata->command contains the ATA STATUS register
723 // - ata->features contains the ATA ERROR register
724 //
725 // Check bits 0 (error bit) and 5 (device fault) of the ATA STATUS
726 // If bit 0 (error bit) is set, then ATA ERROR register is valid.
727 // While we *might* decode the ATA ERROR register, at the moment it
728 // doesn't make much sense: we don't care in detail why the error
729 // happened.
54965743 730
2127e193 731 if (ata->status || (ata->command & 0x21)) {
ee38a438
GI
732 if (scsi_debugmode)
733 pout("Command failed, ata.status=(0x%2.2x), ata.command=(0x%2.2x), ata.flags=(0x%2.2x)\n",ata->status,ata->command,ata->flags);
734 return set_err(EIO);
2127e193 735 }
54965743 736
2127e193
GI
737 // If this is a read data command, copy data to output buffer
738 if (readdata) {
739 if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR)
ee38a438
GI
740 memcpy(in.buffer, cmd_twa->pdata, in.size);
741 else if(m_escalade_type==CONTROLLER_3WARE_678K_CHAR) {
742 memcpy(in.buffer, cmd_twe->tu_data, in.size); // untested
743 }
2127e193 744 }
ee38a438
GI
745 // Return register values
746 if (ata) {
747 ata_out_regs_48bit & r = out.out_regs;
748 r.error = ata->features;
749 r.sector_count_16 = ata->sector_count;
750 r.lba_low_16 = ata->sector_num;
751 r.lba_mid_16 = ata->cylinder_lo;
752 r.lba_high_16 = ata->cylinder_hi;
753 r.device = ata->drive_head;
754 r.status = ata->command;
2127e193 755 }
2127e193 756 // look for nonexistent devices/ports
ee38a438
GI
757 if (in.in_regs.command == ATA_IDENTIFY_DEVICE
758 && !nonempty((unsigned char *)in.buffer, in.size)) {
759 return set_err(ENODEV, "No drive on port %d", m_disknum);
2127e193 760 }
ee38a438 761 return true;
2127e193
GI
762}
763
764
765/////////////////////////////////////////////////////////////////////////////
766/// Implement Highpoint RAID support with old functions
767
768class freebsd_highpoint_device
769: public /*implements*/ ata_device_with_command_set,
770 public /*extends*/ freebsd_smart_device
771{
772public:
773 freebsd_highpoint_device(smart_interface * intf, const char * dev_name,
774 unsigned char controller, unsigned char channel, unsigned char port);
775
776protected:
777 virtual int ata_command_interface(smart_command_set command, int select, char * data);
eb07ddf2 778 virtual bool open();
2127e193
GI
779
780private:
781 unsigned char m_hpt_data[3]; ///< controller/channel/port
782};
783
784
785freebsd_highpoint_device::freebsd_highpoint_device(smart_interface * intf, const char * dev_name,
786 unsigned char controller, unsigned char channel, unsigned char port)
787: smart_device(intf, dev_name, "hpt", "hpt"),
d2e702cf 788 freebsd_smart_device()
2127e193
GI
789{
790 m_hpt_data[0] = controller; m_hpt_data[1] = channel; m_hpt_data[2] = port;
791 set_info().info_name = strprintf("%s [hpt_disk_%u/%u/%u]", dev_name, m_hpt_data[0], m_hpt_data[1], m_hpt_data[2]);
792}
793
eb07ddf2
GI
794bool freebsd_highpoint_device::open()
795{
796 const char *dev = get_dev_name();
797 int fd;
798
799 if ((fd = ::open(dev,O_RDWR))<0) {
800 set_err(errno);
801 return false;
802 }
803 set_fd(fd);
804 return true;
805}
806
2127e193
GI
807int freebsd_highpoint_device::ata_command_interface(smart_command_set command, int select, char * data)
808{
54965743 809 int fd=get_fd();
2127e193 810 int ids[2];
2127e193
GI
811 HPT_IOCTL_PARAM param;
812 HPT_CHANNEL_INFO_V2 info;
813 unsigned char* buff[512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER)];
814 PHPT_PASS_THROUGH_HEADER pide_pt_hdr, pide_pt_hdr_out;
815
2127e193
GI
816 // get internal deviceid
817 ids[0] = m_hpt_data[0] - 1;
818 ids[1] = m_hpt_data[1] - 1;
819
820 memset(&param, 0, sizeof(HPT_IOCTL_PARAM));
821
822 param.magic = HPT_IOCTL_MAGIC;
823 param.ctrl_code = HPT_IOCTL_GET_CHANNEL_INFO_V2;
824 param.in = (unsigned char *)ids;
825 param.in_size = sizeof(unsigned int) * 2;
826 param.out = (unsigned char *)&info;
827 param.out_size = sizeof(HPT_CHANNEL_INFO_V2);
828
829 if (m_hpt_data[2]==1) {
830 param.ctrl_code = HPT_IOCTL_GET_CHANNEL_INFO;
831 param.out_size = sizeof(HPT_CHANNEL_INFO);
832 }
eb07ddf2 833 if (ioctl(fd, HPT_DO_IOCONTROL, &param)!=0 ||
2127e193
GI
834 info.devices[m_hpt_data[2]-1]==0) {
835 return -1;
836 }
837
838 // perform smart action
839 memset(buff, 0, 512 + 2 * sizeof(HPT_PASS_THROUGH_HEADER));
840 pide_pt_hdr = (PHPT_PASS_THROUGH_HEADER)buff;
841
842 pide_pt_hdr->lbamid = 0x4f;
843 pide_pt_hdr->lbahigh = 0xc2;
844 pide_pt_hdr->command = ATA_SMART_CMD;
845 pide_pt_hdr->id = info.devices[m_hpt_data[2] - 1];
846
847 switch (command){
848 case READ_VALUES:
849 pide_pt_hdr->feature=ATA_SMART_READ_VALUES;
850 pide_pt_hdr->protocol=HPT_READ;
851 break;
852 case READ_THRESHOLDS:
853 pide_pt_hdr->feature=ATA_SMART_READ_THRESHOLDS;
854 pide_pt_hdr->protocol=HPT_READ;
855 break;
856 case READ_LOG:
857 pide_pt_hdr->feature=ATA_SMART_READ_LOG_SECTOR;
858 pide_pt_hdr->lbalow=select;
859 pide_pt_hdr->protocol=HPT_READ;
860 break;
861 case IDENTIFY:
862 pide_pt_hdr->command=ATA_IDENTIFY_DEVICE;
863 pide_pt_hdr->protocol=HPT_READ;
864 break;
865 case ENABLE:
866 pide_pt_hdr->feature=ATA_SMART_ENABLE;
867 break;
868 case DISABLE:
869 pide_pt_hdr->feature=ATA_SMART_DISABLE;
870 break;
871 case AUTO_OFFLINE:
872 pide_pt_hdr->feature=ATA_SMART_AUTO_OFFLINE;
873 pide_pt_hdr->sectorcount=select;
874 break;
875 case AUTOSAVE:
876 pide_pt_hdr->feature=ATA_SMART_AUTOSAVE;
877 pide_pt_hdr->sectorcount=select;
878 break;
879 case IMMEDIATE_OFFLINE:
880 pide_pt_hdr->feature=ATA_SMART_IMMEDIATE_OFFLINE;
881 pide_pt_hdr->lbalow=select;
882 break;
883 case STATUS_CHECK:
884 case STATUS:
885 pide_pt_hdr->feature=ATA_SMART_STATUS;
886 break;
887 case CHECK_POWER_MODE:
888 pide_pt_hdr->command=ATA_CHECK_POWER_MODE;
889 break;
890 case WRITE_LOG:
891 memcpy(buff+sizeof(HPT_PASS_THROUGH_HEADER), data, 512);
892 pide_pt_hdr->feature=ATA_SMART_WRITE_LOG_SECTOR;
893 pide_pt_hdr->lbalow=select;
894 pide_pt_hdr->protocol=HPT_WRITE;
895 break;
896 default:
897 pout("Unrecognized command %d in highpoint_command_interface()\n"
898 "Please contact " PACKAGE_BUGREPORT "\n", command);
899 errno=ENOSYS;
900 return -1;
901 }
902 if (pide_pt_hdr->protocol!=0) {
903 pide_pt_hdr->sectors = 1;
904 pide_pt_hdr->sectorcount = 1;
905 }
906
907 memset(&param, 0, sizeof(HPT_IOCTL_PARAM));
908
909 param.magic = HPT_IOCTL_MAGIC;
910 param.ctrl_code = HPT_IOCTL_IDE_PASS_THROUGH;
911 param.in = (unsigned char *)buff;
912 param.in_size = sizeof(HPT_PASS_THROUGH_HEADER) + (pide_pt_hdr->protocol==HPT_READ ? 0 : pide_pt_hdr->sectors * 512);
913 param.out = (unsigned char *)buff+param.in_size;
914 param.out_size = sizeof(HPT_PASS_THROUGH_HEADER) + (pide_pt_hdr->protocol==HPT_READ ? pide_pt_hdr->sectors * 512 : 0);
915
916 pide_pt_hdr_out = (PHPT_PASS_THROUGH_HEADER)param.out;
917
eb07ddf2 918 if ((ioctl(fd, HPT_DO_IOCONTROL, &param)!=0) ||
2127e193
GI
919 (pide_pt_hdr_out->command & 1)) {
920 return -1;
921 }
922
54965743
GI
923 if (command==STATUS_CHECK)
924 {
2127e193
GI
925 unsigned const char normal_lo=0x4f, normal_hi=0xc2;
926 unsigned const char failed_lo=0xf4, failed_hi=0x2c;
927 unsigned char low,high;
928
929 high = pide_pt_hdr_out->lbahigh;
930 low = pide_pt_hdr_out->lbamid;
931
932 // Cyl low and Cyl high unchanged means "Good SMART status"
933 if (low==normal_lo && high==normal_hi)
934 return 0;
935
936 // These values mean "Bad SMART status"
937 if (low==failed_lo && high==failed_hi)
938 return 1;
939
940 // We haven't gotten output that makes sense; print out some debugging info
941 char buf[512];
ee38a438
GI
942 snprintf(buf, sizeof(buf),
943 "CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
2127e193
GI
944 (int)pide_pt_hdr_out->command,
945 (int)pide_pt_hdr_out->feature,
946 (int)pide_pt_hdr_out->sectorcount,
947 (int)pide_pt_hdr_out->lbalow,
948 (int)pide_pt_hdr_out->lbamid,
949 (int)pide_pt_hdr_out->lbahigh,
950 (int)pide_pt_hdr_out->sectors);
951 printwarning(BAD_SMART,buf);
952 }
953 else if (command==CHECK_POWER_MODE)
954 data[0] = pide_pt_hdr_out->sectorcount & 0xff;
955 else if (pide_pt_hdr->protocol==HPT_READ)
54965743
GI
956 memcpy(data, (unsigned char *)buff + 2 * sizeof(HPT_PASS_THROUGH_HEADER),
957 pide_pt_hdr->sectors * 512);
2127e193
GI
958 return 0;
959}
960
961
962/////////////////////////////////////////////////////////////////////////////
e165493d 963/// Standard SCSI support
2127e193
GI
964
965class freebsd_scsi_device
966: public /*implements*/ scsi_device,
967 public /*extends*/ freebsd_smart_device
968{
969public:
970 freebsd_scsi_device(smart_interface * intf, const char * dev_name, const char * req_type);
971
972 virtual smart_device * autodetect_open();
973
974 virtual bool scsi_pass_through(scsi_cmnd_io * iop);
eb07ddf2
GI
975
976 virtual bool open();
977
978 virtual bool close();
979
980private:
eb07ddf2 981 struct cam_device *m_camdev;
2127e193
GI
982};
983
eb07ddf2
GI
984bool freebsd_scsi_device::open(){
985 const char *dev = get_dev_name();
986
987 if ((m_camdev = cam_open_device(dev, O_RDWR)) == NULL) {
988 set_err(errno);
989 return false;
990 }
991 set_fd(m_camdev->fd);
992 return true;
993}
994
995bool freebsd_scsi_device::close(){
996 cam_close_device(m_camdev);
997 set_fd(-1);
998 return true;
999}
1000
2127e193
GI
1001freebsd_scsi_device::freebsd_scsi_device(smart_interface * intf,
1002 const char * dev_name, const char * req_type)
1003: smart_device(intf, dev_name, "scsi", req_type),
a86ec89e
GI
1004 freebsd_smart_device(),
1005 m_camdev(0)
2127e193
GI
1006{
1007}
1008
eb07ddf2
GI
1009
1010bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_io * iop)
2127e193 1011{
2127e193 1012 union ccb *ccb;
54965743 1013
d2e702cf 1014 if (scsi_debugmode) {
54965743
GI
1015 unsigned int k;
1016 const unsigned char * ucp = iop->cmnd;
1017 const char * np;
1018
1019 np = scsi_get_opcode_name(ucp[0]);
1020 pout(" [%s: ", np ? np : "<unknown opcode>");
1021 for (k = 0; k < iop->cmnd_len; ++k)
1022 pout("%02x ", ucp[k]);
d2e702cf 1023 if ((scsi_debugmode > 1) &&
54965743
GI
1024 (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) {
1025 int trunc = (iop->dxfer_len > 256) ? 1 : 0;
1026
1027 pout("]\n Outgoing data, len=%d%s:\n", (int)iop->dxfer_len,
1028 (trunc ? " [only first 256 bytes shown]" : ""));
1029 dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
1030 }
1031 else
d2e702cf 1032 pout("]\n");
54965743 1033 }
2127e193 1034
eb07ddf2 1035 if(m_camdev==NULL) {
d2e702cf
GI
1036 if (scsi_debugmode)
1037 pout(" error: camdev=0!\n");
1038 return set_err(ENOTTY);
2127e193
GI
1039 }
1040
eb07ddf2 1041 if (!(ccb = cam_getccb(m_camdev))) {
d2e702cf
GI
1042 if (scsi_debugmode)
1043 pout(" error allocating ccb\n");
1044 return set_err(ENOMEM);
2127e193 1045 }
d2e702cf 1046
d008864d
GI
1047 // mfi SAT layer is known to be buggy
1048 if(!strcmp("mfi",m_camdev->sim_name)) {
1049 if (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12 || iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16) {
1050 // Controller does not return ATA output registers in SAT sense data
1051 if (iop->cmnd[2] & (1 << 5)) // chk_cond
1052 return set_err(ENOSYS, "ATA return descriptor not supported by controller firmware");
1053 }
1054 // SMART WRITE LOG SECTOR causing media errors
ee38a438
GI
1055 if ((iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16
1056 && iop->cmnd[14] == ATA_SMART_CMD && iop->cmnd[3]==0 &&
1057 iop->cmnd[4] == ATA_SMART_WRITE_LOG_SECTOR) ||
1058 (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12
1059 && iop->cmnd[9] == ATA_SMART_CMD && iop->cmnd[3] == ATA_SMART_WRITE_LOG_SECTOR))
1060 {
1061 if(!failuretest_permissive)
1062 return set_err(ENOSYS, "SMART WRITE LOG SECTOR may cause problems, try with -T permissive to force");
1063 }
d008864d 1064 }
2127e193
GI
1065 // clear out structure, except for header that was filled in for us
1066 bzero(&(&ccb->ccb_h)[1],
54965743 1067 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
2127e193
GI
1068
1069 cam_fill_csio(&ccb->csio,
d2e702cf
GI
1070 /* retries */ 1,
1071 /* cbfcnp */ NULL,
54965743
GI
1072 /* flags */ (iop->dxfer_dir == DXFER_NONE ? CAM_DIR_NONE :(iop->dxfer_dir == DXFER_FROM_DEVICE ? CAM_DIR_IN : CAM_DIR_OUT)),
1073 /* tagaction */ MSG_SIMPLE_Q_TAG,
1074 /* dataptr */ iop->dxferp,
1075 /* datalen */ iop->dxfer_len,
1076 /* senselen */ iop->max_sense_len,
1077 /* cdblen */ iop->cmnd_len,
ff28b140 1078 /* timeout (converted to seconds) */ iop->timeout*1000);
2127e193
GI
1079 memcpy(ccb->csio.cdb_io.cdb_bytes,iop->cmnd,iop->cmnd_len);
1080
eb07ddf2 1081 if (cam_send_ccb(m_camdev,ccb) < 0) {
d2e702cf
GI
1082 if (scsi_debugmode) {
1083 pout(" error sending SCSI ccb\n");
1084 cam_error_print(m_camdev,ccb,CAM_ESF_ALL,CAM_EPF_ALL,stderr);
1085 }
2127e193 1086 cam_freeccb(ccb);
d2e702cf
GI
1087 return set_err(EIO);
1088 }
1089
1090 if (scsi_debugmode) {
1091 pout(" CAM status=0x%x, SCSI status=0x%x, resid=0x%x\n",
1092 ccb->ccb_h.status, ccb->csio.scsi_status, ccb->csio.resid);
1093 if ((scsi_debugmode > 1) && (DXFER_FROM_DEVICE == iop->dxfer_dir)) {
1094 int trunc, len;
1095
1096 len = iop->dxfer_len - ccb->csio.resid;
1097 trunc = (len > 256) ? 1 : 0;
1098 if (len > 0) {
1099 pout(" Incoming data, len=%d%s:\n", len,
1100 (trunc ? " [only first 256 bytes shown]" : ""));
1101 dStrHex(iop->dxferp, (trunc ? 256 : len), 1);
1102 }
1103 else
1104 pout(" Incoming data trimmed to nothing by resid\n");
1105 }
2127e193
GI
1106 }
1107
54965743 1108 if (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_SCSI_STATUS_ERROR)) {
d2e702cf
GI
1109 if (scsi_debugmode)
1110 cam_error_print(m_camdev,ccb,CAM_ESF_ALL,CAM_EPF_ALL,stderr);
2127e193 1111 cam_freeccb(ccb);
d2e702cf 1112 return set_err(EIO);
2127e193
GI
1113 }
1114
d2e702cf
GI
1115 iop->resid = ccb->csio.resid;
1116 iop->scsi_status = ccb->csio.scsi_status;
1117 if (iop->sensep && (ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0) {
1118 if (scsi_debugmode)
1119 pout(" sense_len=0x%x, sense_resid=0x%x\n",
1120 ccb->csio.sense_len, ccb->csio.sense_resid);
d008864d 1121 iop->resp_sense_len = ccb->csio.sense_len - ccb->csio.sense_resid;
d2e702cf
GI
1122 /* Some SCSI controller device drivers miscalculate the sense_resid
1123 field so cap resp_sense_len on max_sense_len. */
1124 if (iop->resp_sense_len > iop->max_sense_len)
1125 iop->resp_sense_len = iop->max_sense_len;
1126 if (iop->resp_sense_len > 0) {
1127 memcpy(iop->sensep, &(ccb->csio.sense_data), iop->resp_sense_len);
1128 if (scsi_debugmode) {
1129 if (scsi_debugmode > 1) {
1130 pout(" >>> Sense buffer, len=%zu:\n", iop->resp_sense_len);
1131 dStrHex(iop->sensep, iop->resp_sense_len, 1);
1132 }
1133 if ((iop->sensep[0] & 0x7f) > 0x71)
1134 pout(" status=0x%x: [desc] sense_key=0x%x asc=0x%x ascq=0x%x\n",
1135 iop->scsi_status, iop->sensep[1] & 0xf,
1136 iop->sensep[2], iop->sensep[3]);
1137 else
1138 pout(" status=0x%x: sense_key=0x%x asc=0x%x ascq=0x%x\n",
1139 iop->scsi_status, iop->sensep[2] & 0xf,
1140 iop->sensep[12], iop->sensep[13]);
1141 }
1142 }
1143 else if (scsi_debugmode)
1144 pout(" status=0x%x\n", iop->scsi_status);
2127e193 1145 }
d2e702cf
GI
1146 else if (scsi_debugmode)
1147 pout(" status=0x%x\n", iop->scsi_status);
2127e193
GI
1148
1149 cam_freeccb(ccb);
54965743 1150
ee38a438
GI
1151 // mfip replacing PDT of the device so response does not make a sense
1152 // this sets PDT to 00h - direct-access block device
1153 if((!strcmp("mfi", m_camdev->sim_name) || !strcmp("mpt", m_camdev->sim_name))
1154 && iop->cmnd[0] == INQUIRY) {
d2e702cf
GI
1155 if (scsi_debugmode) {
1156 pout(" device on %s controller, patching PDT\n", m_camdev->sim_name);
ee38a438
GI
1157 }
1158 iop->dxferp[0] = iop->dxferp[0] & 0xe0;
1159 }
1160
2127e193
GI
1161 return true;
1162}
1163
1164
d008864d
GI
1165/////////////////////////////////////////////////////////////////////////////
1166/// Areca RAID support
1167
ee38a438
GI
1168///////////////////////////////////////////////////////////////////
1169// SATA(ATA) device behind Areca RAID Controller
1170class freebsd_areca_ata_device
1171: public /*implements*/ areca_ata_device,
d008864d
GI
1172 public /*extends*/ freebsd_smart_device
1173{
1174public:
ee38a438
GI
1175 freebsd_areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1);
1176 virtual smart_device * autodetect_open();
1177 virtual bool arcmsr_lock();
1178 virtual bool arcmsr_unlock();
1179 virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop);
1180};
d008864d 1181
ee38a438
GI
1182///////////////////////////////////////////////////////////////////
1183// SAS(SCSI) device behind Areca RAID Controller
1184class freebsd_areca_scsi_device
1185: public /*implements*/ areca_scsi_device,
1186 public /*extends*/ freebsd_smart_device
1187{
1188public:
1189 freebsd_areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1);
1190 virtual smart_device * autodetect_open();
1191 virtual bool arcmsr_lock();
1192 virtual bool arcmsr_unlock();
1193 virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop);
d008864d
GI
1194};
1195
1196
ee38a438
GI
1197// Areca RAID Controller(SATA Disk)
1198freebsd_areca_ata_device::freebsd_areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
1199: smart_device(intf, dev_name, "areca", "areca"),
d2e702cf 1200 freebsd_smart_device()
ee38a438
GI
1201{
1202 set_disknum(disknum);
1203 set_encnum(encnum);
1204 set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
1205}
1206
1207
1208smart_device * freebsd_areca_ata_device::autodetect_open()
d008864d 1209{
ee38a438 1210 // autodetect device type
a86ec89e 1211 int is_ata = arcmsr_get_dev_type();
ee38a438
GI
1212 if(is_ata < 0)
1213 {
1214 set_err(EIO);
1215 return this;
1216 }
1217
1218 if(is_ata == 1)
1219 {
1220 // SATA device
1221 return this;
1222 }
1223
1224 // SAS device
1225 smart_device_auto_ptr newdev(new freebsd_areca_scsi_device(smi(), get_dev_name(), get_disknum(), get_encnum()));
1226 close();
1227 delete this;
1228 newdev->open(); // TODO: Can possibly pass open fd
1229
1230 return newdev.release();
1231}
1232
1233int freebsd_areca_ata_device::arcmsr_do_scsi_io(struct scsi_cmnd_io * iop)
d008864d 1234{
ee38a438
GI
1235 int ioctlreturn = 0;
1236
1237 if(!is_open()) {
1238 if(!open()){
1239 }
1240 }
d008864d 1241
ee38a438
GI
1242 ioctlreturn = ioctl(get_fd(), ((sSRB_BUFFER *)(iop->dxferp))->srbioctl.ControlCode, iop->dxferp);
1243 if (ioctlreturn)
1244 {
1245 // errors found
1246 return -1;
1247 }
d008864d 1248
ee38a438
GI
1249 return ioctlreturn;
1250}
d008864d 1251
ee38a438 1252bool freebsd_areca_ata_device::arcmsr_lock()
d008864d 1253{
ee38a438 1254 return true;
d008864d
GI
1255}
1256
1257
ee38a438 1258bool freebsd_areca_ata_device::arcmsr_unlock()
d008864d 1259{
ee38a438 1260 return true;
d008864d
GI
1261}
1262
1263
ee38a438
GI
1264// Areca RAID Controller(SAS Device)
1265freebsd_areca_scsi_device::freebsd_areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
d008864d 1266: smart_device(intf, dev_name, "areca", "areca"),
d2e702cf 1267 freebsd_smart_device()
d008864d 1268{
ee38a438
GI
1269 set_disknum(disknum);
1270 set_encnum(encnum);
f4e463df 1271 set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
d008864d
GI
1272}
1273
ee38a438
GI
1274smart_device * freebsd_areca_scsi_device::autodetect_open()
1275{
1276 return this;
1277}
1278
1279int freebsd_areca_scsi_device::arcmsr_do_scsi_io(struct scsi_cmnd_io * iop)
1280{
1281 int ioctlreturn = 0;
1282
1283 if(!is_open()) {
1284 if(!open()){
1285 }
1286 }
1287 ioctlreturn = ioctl(get_fd(), ((sSRB_BUFFER *)(iop->dxferp))->srbioctl.ControlCode, iop->dxferp);
1288 if (ioctlreturn)
1289 {
1290 // errors found
1291 return -1;
1292 }
1293
1294 return ioctlreturn;
1295}
1296
1297bool freebsd_areca_scsi_device::arcmsr_lock()
d008864d 1298{
ee38a438 1299 return true;
d008864d
GI
1300}
1301
1302
ee38a438
GI
1303bool freebsd_areca_scsi_device::arcmsr_unlock()
1304{
1305 return true;
1306}
1307
d008864d 1308
2127e193
GI
1309/////////////////////////////////////////////////////////////////////////////
1310/// Implement CCISS RAID support with old functions
1311
1312class freebsd_cciss_device
1313: public /*implements*/ scsi_device,
1314 public /*extends*/ freebsd_smart_device
1315{
1316public:
1317 freebsd_cciss_device(smart_interface * intf, const char * name, unsigned char disknum);
1318
1319 virtual bool scsi_pass_through(scsi_cmnd_io * iop);
eb07ddf2 1320 virtual bool open();
2127e193
GI
1321
1322private:
1323 unsigned char m_disknum; ///< Disk number.
1324};
1325
eb07ddf2
GI
1326bool freebsd_cciss_device::open()
1327{
1328 const char *dev = get_dev_name();
1329 int fd;
eb07ddf2
GI
1330 if ((fd = ::open(dev,O_RDWR))<0) {
1331 set_err(errno);
1332 return false;
1333 }
1334 set_fd(fd);
1335 return true;
1336}
2127e193
GI
1337
1338freebsd_cciss_device::freebsd_cciss_device(smart_interface * intf,
1339 const char * dev_name, unsigned char disknum)
1340: smart_device(intf, dev_name, "cciss", "cciss"),
d2e702cf 1341 freebsd_smart_device(),
2127e193
GI
1342 m_disknum(disknum)
1343{
1344 set_info().info_name = strprintf("%s [cciss_disk_%02d]", dev_name, disknum);
1345}
1346
1347bool freebsd_cciss_device::scsi_pass_through(scsi_cmnd_io * iop)
1348{
cfbba5b9 1349 int status = cciss_io_interface(get_fd(), m_disknum, iop, scsi_debugmode);
eb07ddf2
GI
1350 if (status < 0)
1351 return set_err(-status);
1352 return true;
eb07ddf2 1353 // not reached
2127e193
GI
1354 return true;
1355}
1356
1357
1358/////////////////////////////////////////////////////////////////////////////
1359/// SCSI open with autodetection support
1360
1361smart_device * freebsd_scsi_device::autodetect_open()
1362{
1363 // Open device
1364 if (!open())
1365 return this;
1366
1367 // No Autodetection if device type was specified by user
1368 if (*get_req_type())
1369 return this;
1370
1371 // The code below is based on smartd.cpp:SCSIFilterKnown()
1372
1373 // Get INQUIRY
1374 unsigned char req_buff[64] = {0, };
1375 int req_len = 36;
1376 if (scsiStdInquiry(this, req_buff, req_len)) {
1377 // Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices
1378 // watch this spot ... other devices could lock up here
1379 req_len = 64;
1380 if (scsiStdInquiry(this, req_buff, req_len)) {
1381 // device doesn't like INQUIRY commands
1382 close();
1383 set_err(EIO, "INQUIRY failed");
1384 return this;
1385 }
1386 }
1387
1388 int avail_len = req_buff[4] + 5;
1389 int len = (avail_len < req_len ? avail_len : req_len);
1390 if (len < 36)
54965743 1391 return this;
2127e193
GI
1392
1393 // Use INQUIRY to detect type
2127e193 1394
bed94269 1395 // 3ware ?
ee38a438
GI
1396 if (!memcmp(req_buff + 8, "3ware", 5) || !memcmp(req_buff + 8, "AMCC", 4) ||
1397 !strcmp("tws",m_camdev->sim_name) || !strcmp("twa",m_camdev->sim_name)) {
bed94269 1398 close();
ee38a438
GI
1399 set_err(EINVAL, "3ware/LSI controller, please try adding '-d 3ware,N',\n"
1400 "you may need to replace %s with /dev/twaN, /dev/tweN or /dev/twsN", get_dev_name());
bed94269
GI
1401 return this;
1402 }
1403
d008864d 1404 // SAT or USB, skip MFI controllers because of bugs
bed94269
GI
1405 {
1406 smart_device * newdev = smi()->autodetect_sat_device(this, req_buff, len);
d008864d 1407 if (newdev) {
2127e193 1408 // NOTE: 'this' is now owned by '*newdev'
d008864d
GI
1409 if(!strcmp("mfi",m_camdev->sim_name)) {
1410 newdev->close();
1411 newdev->set_err(ENOSYS, "SATA device detected,\n"
1412 "MegaRAID SAT layer is reportedly buggy, use '-d sat' to try anyhow");
1413 }
2127e193 1414 return newdev;
d008864d 1415 }
2127e193 1416 }
2127e193
GI
1417
1418 // Nothing special found
1419 return this;
1420}
1421
1422
1423/////////////////////////////////////////////////////////////////////////////
1424/// Implement platform interface with old functions.
1425
1426class freebsd_smart_interface
1427: public /*implements*/ smart_interface
1428{
1429public:
54965743 1430 virtual std::string get_os_version_str();
2127e193 1431
54965743 1432 virtual std::string get_app_examples(const char * appname);
2127e193
GI
1433
1434 virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
1435 const char * pattern = 0);
1436
1437protected:
1438 virtual ata_device * get_ata_device(const char * name, const char * type);
1439
eb07ddf2
GI
1440#if FREEBSDVER > 800100
1441 virtual ata_device * get_atacam_device(const char * name, const char * type);
1442#endif
1443
2127e193 1444 virtual scsi_device * get_scsi_device(const char * name, const char * type);
a86ec89e
GI
1445
1446 virtual nvme_device * get_nvme_device(const char * name, const char * type,
1447 unsigned nsid);
2127e193
GI
1448
1449 virtual smart_device * autodetect_smart_device(const char * name);
1450
1451 virtual smart_device * get_custom_smart_device(const char * name, const char * type);
1452
54965743 1453 virtual std::string get_valid_custom_dev_types_str();
ff28b140
TL
1454private:
1455 bool get_nvme_devlist(smart_device_list & devlist, const char * type);
2127e193
GI
1456};
1457
1458
1459//////////////////////////////////////////////////////////////////////
54965743
GI
1460
1461std::string freebsd_smart_interface::get_os_version_str()
2127e193 1462{
54965743
GI
1463 struct utsname osname;
1464 uname(&osname);
1465 return strprintf("%s %s %s", osname.sysname, osname.release, osname.machine);
2127e193
GI
1466}
1467
54965743 1468std::string freebsd_smart_interface::get_app_examples(const char * appname)
2127e193
GI
1469{
1470 if (!strcmp(appname, "smartctl"))
1471 return smartctl_examples;
54965743 1472 return "";
2127e193
GI
1473}
1474
1475ata_device * freebsd_smart_interface::get_ata_device(const char * name, const char * type)
1476{
1477 return new freebsd_ata_device(this, name, type);
1478}
1479
eb07ddf2
GI
1480#if FREEBSDVER > 800100
1481ata_device * freebsd_smart_interface::get_atacam_device(const char * name, const char * type)
2127e193 1482{
eb07ddf2 1483 return new freebsd_atacam_device(this, name, type);
2127e193 1484}
eb07ddf2 1485#endif
832b75ed 1486
eb07ddf2
GI
1487scsi_device * freebsd_smart_interface::get_scsi_device(const char * name, const char * type)
1488{
1489 return new freebsd_scsi_device(this, name, type);
832b75ed
GG
1490}
1491
a86ec89e
GI
1492nvme_device * freebsd_smart_interface::get_nvme_device(const char * name, const char * type,
1493 unsigned nsid)
1494{
1495 return new freebsd_nvme_device(this, name, type, nsid);
1496}
1497
54965743
GI
1498// we are using CAM subsystem XPT enumerator to found all CAM (scsi/usb/ada/...)
1499// devices on system despite of it's names
2127e193
GI
1500//
1501// If any errors occur, leave errno set as it was returned by the
1502// system call, and return <0.
1503//
eb07ddf2
GI
1504// arguments:
1505// names: resulting array
1506// show_all - export duplicate device name or not
1507//
2127e193
GI
1508// Return values:
1509// -1: error
1510// >=0: number of discovered devices
832b75ed 1511
cfbba5b9
GI
1512bool get_dev_names_cam(std::vector<std::string> & names, bool show_all)
1513{
1514 int fd;
2127e193
GI
1515 if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
1516 if (errno == ENOENT) /* There are no CAM device on this computer */
1517 return 0;
cfbba5b9 1518 int serrno = errno;
2127e193 1519 pout("%s control device couldn't opened: %s\n", XPT_DEVICE, strerror(errno));
cfbba5b9
GI
1520 errno = serrno;
1521 return false;
832b75ed 1522 }
2127e193 1523
cfbba5b9 1524 union ccb ccb;
2127e193
GI
1525 bzero(&ccb, sizeof(union ccb));
1526
1527 ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
1528 ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1529 ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1530
1531 ccb.ccb_h.func_code = XPT_DEV_MATCH;
cfbba5b9 1532 int bufsize = sizeof(struct dev_match_result) * MAX_NUM_DEV;
2127e193 1533 ccb.cdm.match_buf_len = bufsize;
cfbba5b9 1534 // TODO: Use local buffer instead of malloc() if possible
2127e193 1535 ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
a7e8ffec
GI
1536 bzero(ccb.cdm.matches,bufsize); // clear ccb.cdm.matches structure
1537
2127e193 1538 if (ccb.cdm.matches == NULL) {
cfbba5b9
GI
1539 close(fd);
1540 throw std::bad_alloc();
2127e193
GI
1541 }
1542 ccb.cdm.num_matches = 0;
2127e193
GI
1543 ccb.cdm.num_patterns = 0;
1544 ccb.cdm.pattern_buf_len = 0;
1545
1546 /*
1547 * We do the ioctl multiple times if necessary, in case there are
1548 * more than MAX_NUM_DEV nodes in the EDT.
1549 */
cfbba5b9
GI
1550 int skip_device = 0, skip_bus = 0, changed = 0; // TODO: bool
1551 std::string devname;
2127e193
GI
1552 do {
1553 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
cfbba5b9 1554 int serrno = errno;
2127e193 1555 pout("error sending CAMIOCOMMAND ioctl: %s\n", strerror(errno));
cfbba5b9
GI
1556 free(ccb.cdm.matches);
1557 close(fd);
1558 errno = serrno;
1559 return false;
832b75ed 1560 }
2127e193
GI
1561
1562 if ((ccb.ccb_h.status != CAM_REQ_CMP)
54965743
GI
1563 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
1564 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
2127e193 1565 pout("got CAM error %#x, CDM error %d\n", ccb.ccb_h.status, ccb.cdm.status);
cfbba5b9
GI
1566 free(ccb.cdm.matches);
1567 close(fd);
1568 errno = ENXIO;
1569 return false;
832b75ed 1570 }
2127e193 1571
cfbba5b9 1572 for (unsigned i = 0; i < ccb.cdm.num_matches; i++) {
2127e193
GI
1573 struct device_match_result *dev_result;
1574 struct periph_match_result *periph_result;
1575
1576 if (ccb.cdm.matches[i].type == DEV_MATCH_BUS) {
a86ec89e
GI
1577 struct bus_match_result *bus_result;
1578
2127e193
GI
1579 bus_result = &ccb.cdm.matches[i].result.bus_result;
1580
d008864d 1581 if (strcmp(bus_result->dev_name,"xpt") == 0) /* skip XPT bus at all */
54965743 1582 skip_bus = 1;
2127e193
GI
1583 else
1584 skip_bus = 0;
1585 changed = 1;
1586 } else if (ccb.cdm.matches[i].type == DEV_MATCH_DEVICE) {
1587 dev_result = &ccb.cdm.matches[i].result.device_result;
1588
1589 if (dev_result->flags & DEV_RESULT_UNCONFIGURED || skip_bus == 1)
1590 skip_device = 1;
1591 else
1592 skip_device = 0;
eb07ddf2 1593
54965743
GI
1594 // /* Shall we skip non T_DIRECT devices ? */
1595 // if (dev_result->inq_data.device != T_DIRECT)
1596 // skip_device = 1;
2127e193 1597 changed = 1;
eb07ddf2
GI
1598 } else if (ccb.cdm.matches[i].type == DEV_MATCH_PERIPH &&
1599 (skip_device == 0 || show_all)) {
2127e193 1600 /* One device may be populated as many peripherals (pass0 & da0 for example).
ee38a438 1601 * We are searching for best name
2127e193
GI
1602 */
1603 periph_result = &ccb.cdm.matches[i].result.periph_result;
ee38a438
GI
1604 /* Prefer non-"pass" names */
1605 if (devname.empty() || strncmp(periph_result->periph_name, "pass", 4) != 0) {
1606 devname = strprintf("%s%s%d", _PATH_DEV, periph_result->periph_name, periph_result->unit_number);
1607 }
2127e193
GI
1608 changed = 0;
1609 };
cfbba5b9
GI
1610 if ((changed == 1 || show_all) && !devname.empty()) {
1611 names.push_back(devname);
1612 devname.erase();
2127e193
GI
1613 changed = 0;
1614 };
1615 }
1616
cfbba5b9 1617 } while ((ccb.ccb_h.status == CAM_REQ_CMP) && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
2127e193 1618
cfbba5b9
GI
1619 if (!devname.empty())
1620 names.push_back(devname);
2127e193 1621
2127e193 1622 free(ccb.cdm.matches);
cfbba5b9
GI
1623 close(fd);
1624 return true;
832b75ed 1625}
832b75ed 1626
2127e193
GI
1627// we are using ATA subsystem enumerator to found all ATA devices on system
1628// despite of it's names
1629//
1630// If any errors occur, leave errno set as it was returned by the
1631// system call, and return <0.
832b75ed 1632
2127e193
GI
1633// Return values:
1634// -1: error
1635// >=0: number of discovered devices
1636int get_dev_names_ata(char*** names) {
1637 struct ata_ioc_devices devices;
1638 int fd=-1,maxchannel,serrno=-1,n=0;
1639 char **mp = NULL;
1640
1641 *names=NULL;
1642
1643 if ((fd = open(ATA_DEVICE, O_RDWR)) < 0) {
1644 if (errno == ENOENT) /* There are no ATA device on this computer */
1645 return 0;
1646 serrno = errno;
1647 pout("%s control device can't be opened: %s\n", ATA_DEVICE, strerror(errno));
1648 n = -1;
1649 goto end;
1650 };
54965743 1651
2127e193
GI
1652 if (ioctl(fd, IOCATAGMAXCHANNEL, &maxchannel) < 0) {
1653 serrno = errno;
1654 pout("ioctl(IOCATAGMAXCHANNEL) on /dev/ata failed: %s\n", strerror(errno));
1655 n = -1;
1656 goto end;
1657 };
1658
1659 // allocate space for up to MAX_NUM_DEV number of ATA devices
1660 mp = (char **)calloc(MAX_NUM_DEV, sizeof(char*));
1661 if (mp == NULL) {
1662 serrno=errno;
1663 pout("Out of memory constructing scan device list (on line %d)\n", __LINE__);
1664 n = -1;
1665 goto end;
1666 };
1667
1668 for (devices.channel = 0; devices.channel < maxchannel && n < MAX_NUM_DEV; devices.channel++) {
1669 int j;
54965743 1670
2127e193
GI
1671 if (ioctl(fd, IOCATADEVICES, &devices) < 0) {
1672 if (errno == ENXIO)
1673 continue; /* such channel not exist */
1674 pout("ioctl(IOCATADEVICES) on %s channel %d failed: %s\n", ATA_DEVICE, devices.channel, strerror(errno));
1675 n = -1;
1676 goto end;
1677 };
1678 for (j=0;j<=1 && n<MAX_NUM_DEV;j++) {
1679 if (devices.name[j][0] != '\0') {
1680 asprintf(mp+n, "%s%s", _PATH_DEV, devices.name[j]);
1681 if (mp[n] == NULL) {
1682 pout("Out of memory constructing scan ATA device list (on line %d)\n", __LINE__);
1683 n = -1;
1684 goto end;
1685 };
2127e193
GI
1686 n++;
1687 };
1688 };
a86ec89e
GI
1689 };
1690 if (n <= 0)
1691 goto end;
2127e193 1692 mp = (char **)reallocf(mp,n*(sizeof (char*))); // shrink to correct size
a86ec89e 1693 if (mp == NULL) {
f4ebf3d1
GI
1694 serrno=errno;
1695 pout("Out of memory constructing scan device list (on line %d)\n", __LINE__);
1696 n = -1;
1697 goto end;
1698 };
54965743 1699
2127e193
GI
1700end:
1701 if (fd>=0)
1702 close(fd);
1703 if (n <= 0) {
1704 free(mp);
1705 mp = NULL;
832b75ed 1706 }
832b75ed 1707
2127e193 1708 *names=mp;
832b75ed 1709
2127e193
GI
1710 if (serrno>-1)
1711 errno=serrno;
1712 return n;
1713}
832b75ed 1714
2127e193
GI
1715
1716
1717bool freebsd_smart_interface::scan_smart_devices(smart_device_list & devlist,
1718 const char * type, const char * pattern /*= 0*/)
1719{
1720 if (pattern) {
1721 set_err(EINVAL, "DEVICESCAN with pattern not implemented yet");
1722 return false;
832b75ed
GG
1723 }
1724
ff28b140
TL
1725#ifdef WITH_NVME_DEVICESCAN // TODO: Remove when NVMe support is no longer EXPERIMENTAL
1726 bool scan_nvme = !type || !strcmp(type, "nvme");
1727#else
1728 bool scan_nvme = type && !strcmp(type, "nvme");
1729#endif
1730
2127e193
GI
1731 // Make namelists
1732 char * * atanames = 0; int numata = 0;
1733 if (!type || !strcmp(type, "ata")) {
1734 numata = get_dev_names_ata(&atanames);
1735 if (numata < 0) {
1736 set_err(ENOMEM);
1737 return false;
832b75ed 1738 }
2127e193
GI
1739 }
1740
cfbba5b9 1741 std::vector<std::string> scsinames;
eb07ddf2 1742 if (!type || !strcmp(type, "scsi")) { // do not export duplicated names
cfbba5b9
GI
1743 if (!get_dev_names_cam(scsinames, false)) {
1744 set_err(errno);
2127e193 1745 return false;
832b75ed 1746 }
832b75ed
GG
1747 }
1748
2127e193
GI
1749 // Add to devlist
1750 int i;
1751 if (type==NULL)
1752 type="";
1753 for (i = 0; i < numata; i++) {
1754 ata_device * atadev = get_ata_device(atanames[i], type);
1755 if (atadev)
bed94269 1756 devlist.push_back(atadev);
a7e8ffec 1757 free(atanames[i]);
2127e193 1758 }
a7e8ffec 1759 if(numata) free(atanames);
832b75ed 1760
cfbba5b9 1761 for (i = 0; i < (int)scsinames.size(); i++) {
54965743 1762 if(!*type) { // try USB autodetection if no type specified
cfbba5b9 1763 smart_device * smartdev = autodetect_smart_device(scsinames[i].c_str());
54965743 1764 if(smartdev)
bed94269 1765 devlist.push_back(smartdev);
54965743
GI
1766 }
1767 else {
cfbba5b9 1768 scsi_device * scsidev = get_scsi_device(scsinames[i].c_str(), type);
54965743 1769 if (scsidev)
bed94269 1770 devlist.push_back(scsidev);
54965743 1771 }
832b75ed 1772 }
ff28b140
TL
1773
1774 if (scan_nvme)
1775 get_nvme_devlist(devlist, type);
2127e193 1776 return true;
832b75ed
GG
1777}
1778
ff28b140
TL
1779bool freebsd_smart_interface::get_nvme_devlist(smart_device_list & devlist,
1780 const char * type)
1781{
1782 char ctrlpath[64];
1783
1784 for (int ctrlr = 0;; ctrlr++) {
1785 sprintf(ctrlpath, "%s%d", NVME_CTRLR_PREFIX, ctrlr);
1786 int fd = ::open(ctrlpath, O_RDWR);
1787 if (fd < 0)
1788 break;
1789 ::close(fd);
1790 nvme_device * nvmedev = get_nvme_device(ctrlpath, type, 0);
1791 if (nvmedev)
1792 devlist.push_back(nvmedev);
1793 else
1794 break;
1795 }
1796 return true;
1797}
2127e193 1798
54965743 1799#if (FREEBSDVER < 800000) // without this build fail on FreeBSD 8
2127e193 1800static char done[USB_MAX_DEVICES];
2127e193
GI
1801
1802static int usbdevinfo(int f, int a, int rec, int busno, unsigned short & vendor_id,
54965743
GI
1803 unsigned short & product_id, unsigned short & version)
1804{
832b75ed 1805
54965743
GI
1806 struct usb_device_info di;
1807 int e, p, i;
1808 char devname[256];
832b75ed 1809
54965743
GI
1810 snprintf(devname, sizeof(devname),"umass%d",busno);
1811
1812 di.udi_addr = a;
1813 e = ioctl(f, USB_DEVICEINFO, &di);
1814 if (e) {
1815 if (errno != ENXIO)
1816 printf("addr %d: I/O error\n", a);
1817 return 0;
1818 }
1819 done[a] = 1;
1820
1821 // list devices
1822 for (i = 0; i < USB_MAX_DEVNAMES; i++) {
1823 if (di.udi_devnames[i][0]) {
1824 if(strcmp(di.udi_devnames[i],devname)==0) {
1825 // device found!
1826 vendor_id = di.udi_vendorNo;
1827 product_id = di.udi_productNo;
1828 version = di.udi_releaseNo;
1829 return 1;
1830 // FIXME
1831 }
1832 }
1833 }
1834 if (!rec)
1835 return 0;
1836 for (p = 0; p < di.udi_nports; p++) {
1837 int s = di.udi_ports[p];
1838 if (s >= USB_MAX_DEVICES) {
1839 continue;
1840 }
1841 if (s == 0)
1842 printf("addr 0 should never happen!\n");
1843 else {
1844 if(usbdevinfo(f, s, 1, busno, vendor_id, product_id, version)) return 1;
1845 }
1846 }
1847 return 0;
1848}
1849#endif
832b75ed 1850
832b75ed 1851
2127e193 1852static int usbdevlist(int busno,unsigned short & vendor_id,
54965743 1853 unsigned short & product_id, unsigned short & version)
2127e193 1854{
54965743
GI
1855#if (FREEBSDVER >= 800000) // libusb2 interface
1856 struct libusb20_device *pdev = NULL;
1857 struct libusb20_backend *pbe;
1858 uint32_t matches = 0;
1859 char buf[128]; // do not change!
1860 char devname[128];
1861 uint8_t n;
1862 struct LIBUSB20_DEVICE_DESC_DECODED *pdesc;
1863
1864 pbe = libusb20_be_alloc_default();
1865
1866 while ((pdev = libusb20_be_device_foreach(pbe, pdev))) {
1867 matches++;
1868
1869 if (libusb20_dev_open(pdev, 0)) {
1870 warnx("libusb20_dev_open: could not open device");
1871 return 0;
2127e193 1872 }
54965743
GI
1873
1874 pdesc=libusb20_dev_get_device_desc(pdev);
1875
1876 snprintf(devname, sizeof(devname),"umass%d:",busno);
1877 for (n = 0; n != 255; n++) {
1878 if (libusb20_dev_get_iface_desc(pdev, n, buf, sizeof(buf)))
1879 break;
1880 if (buf[0] == 0)
1881 continue;
1882 if(strncmp(buf,devname,strlen(devname))==0){
1883 // found!
1884 vendor_id = pdesc->idVendor;
1885 product_id = pdesc->idProduct;
1886 version = pdesc->bcdDevice;
1887 libusb20_dev_close(pdev);
1888 libusb20_be_free(pbe);
1889 return 1;
1890 }
1891 }
1892
1893 libusb20_dev_close(pdev);
1894 }
1895
1896 if (matches == 0) {
1897 printf("No device match or lack of permissions.\n");
1898 }
1899
1900 libusb20_be_free(pbe);
1901
1902 return false;
1903#else // freebsd < 8.0 USB stack, ioctl interface
1904
a86ec89e 1905 int i, a, rc;
54965743
GI
1906 char buf[50];
1907 int ncont;
1908
1909 for (ncont = 0, i = 0; i < 10; i++) {
1910 snprintf(buf, sizeof(buf), "%s%d", USBDEV, i);
a86ec89e 1911 int f = open(buf, O_RDONLY);
54965743
GI
1912 if (f >= 0) {
1913 memset(done, 0, sizeof done);
1914 for (a = 1; a < USB_MAX_DEVICES; a++) {
1915 if (!done[a]) {
1916 rc = usbdevinfo(f, a, 1, busno,vendor_id, product_id, version);
1917 if(rc) return 1;
1918 }
1919
1920 }
1921 close(f);
1922 } else {
1923 if (errno == ENOENT || errno == ENXIO)
1924 continue;
1925 warn("%s", buf);
1926 }
1927 ncont++;
1928 }
1929 return 0;
1930#endif
2127e193
GI
1931}
1932
2127e193
GI
1933smart_device * freebsd_smart_interface::autodetect_smart_device(const char * name)
1934{
2127e193 1935 unsigned short vendor_id = 0, product_id = 0, version = 0;
eb07ddf2
GI
1936 struct cam_device *cam_dev;
1937 union ccb ccb;
1938 int bus=-1;
a86ec89e 1939 int i;
d008864d 1940 const char * test_name = name;
54965743 1941
f9e10201
JD
1942 memset(&ccb, 0, sizeof(ccb));
1943
eb07ddf2 1944 // if dev_name null, or string length zero
a86ec89e 1945 if (!name || !*name)
d008864d
GI
1946 return 0;
1947
1948 // Dereference symlinks
1949 struct stat st;
1950 std::string pathbuf;
1951 if (!lstat(name, &st) && S_ISLNK(st.st_mode)) {
1952 char * p = realpath(name, (char *)0);
1953 if (p) {
1954 pathbuf = p;
1955 free(p);
1956 test_name = pathbuf.c_str();
1957 }
1958 }
eb07ddf2
GI
1959
1960 // check ATA bus
1961 char * * atanames = 0; int numata = 0;
1962 numata = get_dev_names_ata(&atanames);
1963 if (numata > 0) {
1964 // check ATA/ATAPI devices
1965 for (i = 0; i < numata; i++) {
d008864d 1966 if(!strcmp(atanames[i],test_name)) {
a86ec89e 1967 for (int c = i; c < numata; c++) free(atanames[c]);
a7e8ffec 1968 free(atanames);
d008864d 1969 return new freebsd_ata_device(this, test_name, "");
eb07ddf2 1970 }
a7e8ffec 1971 else free(atanames[i]);
832b75ed 1972 }
a7e8ffec 1973 if(numata) free(atanames);
832b75ed 1974 }
eb07ddf2
GI
1975 else {
1976 if (numata < 0)
1977 pout("Unable to get ATA device list\n");
1978 }
1979
1980 // check CAM
cfbba5b9
GI
1981 std::vector<std::string> scsinames;
1982 if (!get_dev_names_cam(scsinames, true))
1983 pout("Unable to get CAM device list\n");
1984 else if (!scsinames.empty()) {
eb07ddf2 1985 // check all devices on CAM bus
cfbba5b9 1986 for (i = 0; i < (int)scsinames.size(); i++) {
d008864d 1987 if(strcmp(scsinames[i].c_str(), test_name)==0)
eb07ddf2 1988 { // our disk device is CAM
3d17a85c
GI
1989 if(strncmp(scsinames[i].c_str(), "/dev/pmp", strlen("/dev/pmp")) == 0) {
1990 pout("Skipping port multiplier [%s]\n", scsinames[i].c_str());
1991 set_err(EINVAL);
1992 return 0;
1993 }
d008864d 1994 if ((cam_dev = cam_open_device(test_name, O_RDWR)) == NULL) {
eb07ddf2
GI
1995 // open failure
1996 set_err(errno);
d008864d 1997 return 0;
eb07ddf2 1998 }
eb07ddf2
GI
1999 // zero the payload
2000 bzero(&(&ccb.ccb_h)[1], PATHINQ_SETTINGS_SIZE);
2001 ccb.ccb_h.func_code = XPT_PATH_INQ; // send PATH_INQ to the device
2002 if (ioctl(cam_dev->fd, CAMIOCOMMAND, &ccb) == -1) {
2003 warn("Get Transfer Settings CCB failed\n"
2004 "%s", strerror(errno));
2005 cam_close_device(cam_dev);
2006 return 0;
2007 }
2008 // now check if we are working with USB device, see umass.c
2009 if(strcmp(ccb.cpi.dev_name,"umass-sim") == 0) { // USB device found
2010 usbdevlist(bus,vendor_id, product_id, version);
2011 int bus=ccb.cpi.unit_number; // unit_number will match umass number
2012 cam_close_device(cam_dev);
2013 if(usbdevlist(bus,vendor_id, product_id, version)){
2014 const char * usbtype = get_usb_dev_type_by_id(vendor_id, product_id, version);
f4ebf3d1 2015 if (usbtype)
ff28b140 2016 return get_scsi_passthrough_device(usbtype, new freebsd_scsi_device(this, test_name, ""));
eb07ddf2 2017 }
d008864d 2018 return 0;
eb07ddf2
GI
2019 }
2020#if FREEBSDVER > 800100
2021 // check if we have ATA device connected to CAM (ada)
2022 if(ccb.cpi.protocol == PROTO_ATA){
2023 cam_close_device(cam_dev);
d008864d 2024 return new freebsd_atacam_device(this, test_name, "");
eb07ddf2
GI
2025 }
2026#endif
2027 // close cam device, we don`t need it anymore
2028 cam_close_device(cam_dev);
2029 // handle as usual scsi
d008864d 2030 return new freebsd_scsi_device(this, test_name, "");
eb07ddf2
GI
2031 }
2032 }
eb07ddf2 2033 }
d008864d
GI
2034 // device is LSI raid supported by mfi driver
2035 if(!strncmp("/dev/mfid", test_name, strlen("/dev/mfid")))
2036 set_err(EINVAL, "To monitor disks on LSI RAID load mfip.ko module and run 'smartctl -a /dev/passX' to show SMART information");
a86ec89e
GI
2037
2038 // form /dev/nvme* or nvme*
2039 if(!strncmp("/dev/nvme", test_name, strlen("/dev/nvme")))
2040 return new freebsd_nvme_device(this, name, "", 0 /* use default nsid */);
ff28b140
TL
2041 if(!strncmp("/dev/nvd", test_name, strlen("/dev/nvd")))
2042 set_err(EINVAL, "To monitor NVMe disks use /dev/nvme* device names");
a86ec89e 2043
eb07ddf2 2044 // device type unknown
2127e193
GI
2045 return 0;
2046}
2047
2048
2049smart_device * freebsd_smart_interface::get_custom_smart_device(const char * name, const char * type)
2050{
a86ec89e 2051 int disknum = -1, n1 = -1, n2 = -1;
eb07ddf2 2052
2127e193 2053 if (sscanf(type, "3ware,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) {
a86ec89e
GI
2054 // 3Ware ?
2055 static const char * fbsd_dev_twe_ctrl = "/dev/twe";
2056 static const char * fbsd_dev_twa_ctrl = "/dev/twa";
2057 static const char * fbsd_dev_tws_ctrl = "/dev/tws";
2058 int contr = -1;
2059
2127e193
GI
2060 if (n2 != (int)strlen(type)) {
2061 set_err(EINVAL, "Option -d 3ware,N requires N to be a non-negative integer");
2062 return 0;
2063 }
2064 if (!(0 <= disknum && disknum <= 127)) {
2065 set_err(EINVAL, "Option -d 3ware,N (N=%d) must have 0 <= N <= 127", disknum);
2066 return 0;
2067 }
eb07ddf2
GI
2068
2069 // guess 3ware device type based on device name
ee38a438
GI
2070 if (str_starts_with(name, fbsd_dev_twa_ctrl) ||
2071 str_starts_with(name, fbsd_dev_tws_ctrl) ) {
eb07ddf2
GI
2072 contr=CONTROLLER_3WARE_9000_CHAR;
2073 }
2074 if (!strncmp(fbsd_dev_twe_ctrl, name, strlen(fbsd_dev_twe_ctrl))){
2075 contr=CONTROLLER_3WARE_678K_CHAR;
2076 }
2077
2078 if(contr == -1){
ee38a438
GI
2079 set_err(EINVAL, "3ware controller type unknown, use %sX, %sX or %sX devices",
2080 fbsd_dev_twe_ctrl, fbsd_dev_twa_ctrl, fbsd_dev_tws_ctrl);
eb07ddf2
GI
2081 return 0;
2082 }
54965743 2083 return new freebsd_escalade_device(this, name, contr, disknum);
ee38a438 2084 }
2127e193
GI
2085
2086 // Highpoint ?
2087 int controller = -1, channel = -1; disknum = 1;
2088 n1 = n2 = -1; int n3 = -1;
2089 if (sscanf(type, "hpt,%n%d/%d%n/%d%n", &n1, &controller, &channel, &n2, &disknum, &n3) >= 2 || n1 == 4) {
2090 int len = strlen(type);
2091 if (!(n2 == len || n3 == len)) {
2092 set_err(EINVAL, "Option '-d hpt,L/M/N' supports 2-3 items");
2093 return 0;
2094 }
2095 if (!(1 <= controller && controller <= 8)) {
2096 set_err(EINVAL, "Option '-d hpt,L/M/N' invalid controller id L supplied");
2097 return 0;
2098 }
3d17a85c 2099 if (!(1 <= channel && channel <= 128)) {
2127e193
GI
2100 set_err(EINVAL, "Option '-d hpt,L/M/N' invalid channel number M supplied");
2101 return 0;
2102 }
2103 if (!(1 <= disknum && disknum <= 15)) {
2104 set_err(EINVAL, "Option '-d hpt,L/M/N' invalid pmport number N supplied");
2105 return 0;
2106 }
2107 return new freebsd_highpoint_device(this, name, controller, channel, disknum);
832b75ed
GG
2108 }
2109
2127e193
GI
2110 // CCISS ?
2111 disknum = n1 = n2 = -1;
2112 if (sscanf(type, "cciss,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) {
2113 if (n2 != (int)strlen(type)) {
2114 set_err(EINVAL, "Option -d cciss,N requires N to be a non-negative integer");
2115 return 0;
2116 }
e9583e0c
GI
2117 if (!(0 <= disknum && disknum <= 127)) {
2118 set_err(EINVAL, "Option -d cciss,N (N=%d) must have 0 <= N <= 127", disknum);
2127e193
GI
2119 return 0;
2120 }
ee38a438 2121 return get_sat_device("sat,auto", new freebsd_cciss_device(this, name, disknum));
832b75ed 2122 }
eb07ddf2
GI
2123#if FREEBSDVER > 800100
2124 // adaX devices ?
2125 if(!strcmp(type,"atacam"))
2126 return new freebsd_atacam_device(this, name, "");
2127#endif
d008864d
GI
2128 // Areca?
2129 disknum = n1 = n2 = -1;
f4e463df
GI
2130 int encnum = 1;
2131 if (sscanf(type, "areca,%n%d/%d%n", &n1, &disknum, &encnum, &n2) >= 1 || n1 == 6) {
2132 if (!(1 <= disknum && disknum <= 128)) {
2133 set_err(EINVAL, "Option -d areca,N/E (N=%d) must have 1 <= N <= 128", disknum);
d008864d
GI
2134 return 0;
2135 }
f4e463df
GI
2136 if (!(1 <= encnum && encnum <= 8)) {
2137 set_err(EINVAL, "Option -d areca,N/E (E=%d) must have 1 <= E <= 8", encnum);
d008864d
GI
2138 return 0;
2139 }
ee38a438 2140 return new freebsd_areca_ata_device(this, name, disknum, encnum);
d008864d 2141 }
832b75ed 2142
2127e193 2143 return 0;
832b75ed
GG
2144}
2145
54965743 2146std::string freebsd_smart_interface::get_valid_custom_dev_types_str()
2127e193 2147{
f4e463df 2148 return "3ware,N, hpt,L/M/N, cciss,N, areca,N/E"
eb07ddf2
GI
2149#if FREEBSDVER > 800100
2150 ", atacam"
2151#endif
2152 ;
2127e193
GI
2153}
2154
2127e193
GI
2155} // namespace
2156
2127e193
GI
2157/////////////////////////////////////////////////////////////////////////////
2158/// Initialize platform interface and register with smi()
2159
2160void smart_interface::init()
2161{
2162 static os_freebsd::freebsd_smart_interface the_interface;
2163 smart_interface::set(&the_interface);
832b75ed 2164}