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