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