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