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