]> git.proxmox.com Git - mirror_smartmontools-debian.git/blob - os_freebsd.cpp
Updated changelog
[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 3335 2011-05-21 17:32:16Z samm2 $" \
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 bzero(ccb.cdm.matches,bufsize); // clear ccb.cdm.matches structure
1271
1272 if (ccb.cdm.matches == NULL) {
1273 close(fd);
1274 throw std::bad_alloc();
1275 }
1276 ccb.cdm.num_matches = 0;
1277 ccb.cdm.num_patterns = 0;
1278 ccb.cdm.pattern_buf_len = 0;
1279
1280 /*
1281 * We do the ioctl multiple times if necessary, in case there are
1282 * more than MAX_NUM_DEV nodes in the EDT.
1283 */
1284 int skip_device = 0, skip_bus = 0, changed = 0; // TODO: bool
1285 std::string devname;
1286 do {
1287 if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1288 int serrno = errno;
1289 pout("error sending CAMIOCOMMAND ioctl: %s\n", strerror(errno));
1290 free(ccb.cdm.matches);
1291 close(fd);
1292 errno = serrno;
1293 return false;
1294 }
1295
1296 if ((ccb.ccb_h.status != CAM_REQ_CMP)
1297 || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
1298 && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
1299 pout("got CAM error %#x, CDM error %d\n", ccb.ccb_h.status, ccb.cdm.status);
1300 free(ccb.cdm.matches);
1301 close(fd);
1302 errno = ENXIO;
1303 return false;
1304 }
1305
1306 for (unsigned i = 0; i < ccb.cdm.num_matches; i++) {
1307 struct bus_match_result *bus_result;
1308 struct device_match_result *dev_result;
1309 struct periph_match_result *periph_result;
1310
1311 if (ccb.cdm.matches[i].type == DEV_MATCH_BUS) {
1312 bus_result = &ccb.cdm.matches[i].result.bus_result;
1313
1314 if (strcmp(bus_result->dev_name,"ata") == 0 /* ATAPICAM devices will be probed as ATA devices, skip'em there */
1315 || strcmp(bus_result->dev_name,"xpt") == 0) /* skip XPT bus at all */
1316 skip_bus = 1;
1317 else
1318 skip_bus = 0;
1319 changed = 1;
1320 } else if (ccb.cdm.matches[i].type == DEV_MATCH_DEVICE) {
1321 dev_result = &ccb.cdm.matches[i].result.device_result;
1322
1323 if (dev_result->flags & DEV_RESULT_UNCONFIGURED || skip_bus == 1)
1324 skip_device = 1;
1325 else
1326 skip_device = 0;
1327
1328 // /* Shall we skip non T_DIRECT devices ? */
1329 // if (dev_result->inq_data.device != T_DIRECT)
1330 // skip_device = 1;
1331 changed = 1;
1332 } else if (ccb.cdm.matches[i].type == DEV_MATCH_PERIPH &&
1333 (skip_device == 0 || show_all)) {
1334 /* One device may be populated as many peripherals (pass0 & da0 for example).
1335 * We are searching for latest name
1336 */
1337 periph_result = &ccb.cdm.matches[i].result.periph_result;
1338 devname = strprintf("%s%s%d", _PATH_DEV, periph_result->periph_name, periph_result->unit_number);
1339 changed = 0;
1340 };
1341 if ((changed == 1 || show_all) && !devname.empty()) {
1342 names.push_back(devname);
1343 devname.erase();
1344 changed = 0;
1345 };
1346 }
1347
1348 } while ((ccb.ccb_h.status == CAM_REQ_CMP) && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
1349
1350 if (!devname.empty())
1351 names.push_back(devname);
1352
1353 free(ccb.cdm.matches);
1354 close(fd);
1355 return true;
1356 }
1357
1358 // we are using ATA subsystem enumerator to found all ATA devices on system
1359 // despite of it's names
1360 //
1361 // If any errors occur, leave errno set as it was returned by the
1362 // system call, and return <0.
1363
1364 // Return values:
1365 // -1: error
1366 // >=0: number of discovered devices
1367 int get_dev_names_ata(char*** names) {
1368 struct ata_ioc_devices devices;
1369 int fd=-1,maxchannel,serrno=-1,n=0;
1370 char **mp = NULL;
1371
1372 *names=NULL;
1373
1374 if ((fd = open(ATA_DEVICE, O_RDWR)) < 0) {
1375 if (errno == ENOENT) /* There are no ATA device on this computer */
1376 return 0;
1377 serrno = errno;
1378 pout("%s control device can't be opened: %s\n", ATA_DEVICE, strerror(errno));
1379 n = -1;
1380 goto end;
1381 };
1382
1383 if (ioctl(fd, IOCATAGMAXCHANNEL, &maxchannel) < 0) {
1384 serrno = errno;
1385 pout("ioctl(IOCATAGMAXCHANNEL) on /dev/ata failed: %s\n", strerror(errno));
1386 n = -1;
1387 goto end;
1388 };
1389
1390 // allocate space for up to MAX_NUM_DEV number of ATA devices
1391 mp = (char **)calloc(MAX_NUM_DEV, sizeof(char*));
1392 if (mp == NULL) {
1393 serrno=errno;
1394 pout("Out of memory constructing scan device list (on line %d)\n", __LINE__);
1395 n = -1;
1396 goto end;
1397 };
1398
1399 for (devices.channel = 0; devices.channel < maxchannel && n < MAX_NUM_DEV; devices.channel++) {
1400 int j;
1401
1402 if (ioctl(fd, IOCATADEVICES, &devices) < 0) {
1403 if (errno == ENXIO)
1404 continue; /* such channel not exist */
1405 pout("ioctl(IOCATADEVICES) on %s channel %d failed: %s\n", ATA_DEVICE, devices.channel, strerror(errno));
1406 n = -1;
1407 goto end;
1408 };
1409 for (j=0;j<=1 && n<MAX_NUM_DEV;j++) {
1410 if (devices.name[j][0] != '\0') {
1411 asprintf(mp+n, "%s%s", _PATH_DEV, devices.name[j]);
1412 if (mp[n] == NULL) {
1413 pout("Out of memory constructing scan ATA device list (on line %d)\n", __LINE__);
1414 n = -1;
1415 goto end;
1416 };
1417 bytes+=1+strlen(mp[n]);
1418 n++;
1419 };
1420 };
1421 };
1422 mp = (char **)reallocf(mp,n*(sizeof (char*))); // shrink to correct size
1423 if (mp == NULL && n > 0 ) { // reallocf never fail for size=0, but may return NULL
1424 serrno=errno;
1425 pout("Out of memory constructing scan device list (on line %d)\n", __LINE__);
1426 n = -1;
1427 goto end;
1428 };
1429 bytes += (n)*(sizeof(char*)); // and set allocated byte count
1430
1431 end:
1432 if (fd>=0)
1433 close(fd);
1434 if (n <= 0) {
1435 free(mp);
1436 mp = NULL;
1437 }
1438
1439 *names=mp;
1440
1441 if (serrno>-1)
1442 errno=serrno;
1443 return n;
1444 }
1445
1446
1447
1448 bool freebsd_smart_interface::scan_smart_devices(smart_device_list & devlist,
1449 const char * type, const char * pattern /*= 0*/)
1450 {
1451 if (pattern) {
1452 set_err(EINVAL, "DEVICESCAN with pattern not implemented yet");
1453 return false;
1454 }
1455
1456 // Make namelists
1457 char * * atanames = 0; int numata = 0;
1458 if (!type || !strcmp(type, "ata")) {
1459 numata = get_dev_names_ata(&atanames);
1460 if (numata < 0) {
1461 set_err(ENOMEM);
1462 return false;
1463 }
1464 }
1465
1466 std::vector<std::string> scsinames;
1467 if (!type || !strcmp(type, "scsi")) { // do not export duplicated names
1468 if (!get_dev_names_cam(scsinames, false)) {
1469 set_err(errno);
1470 return false;
1471 }
1472 }
1473
1474 // Add to devlist
1475 int i;
1476 if (type==NULL)
1477 type="";
1478 for (i = 0; i < numata; i++) {
1479 ata_device * atadev = get_ata_device(atanames[i], type);
1480 if (atadev)
1481 devlist.push_back(atadev);
1482 free(atanames[i]);
1483 }
1484 if(numata) free(atanames);
1485
1486 for (i = 0; i < (int)scsinames.size(); i++) {
1487 if(!*type) { // try USB autodetection if no type specified
1488 smart_device * smartdev = autodetect_smart_device(scsinames[i].c_str());
1489 if(smartdev)
1490 devlist.push_back(smartdev);
1491 }
1492 else {
1493 scsi_device * scsidev = get_scsi_device(scsinames[i].c_str(), type);
1494 if (scsidev)
1495 devlist.push_back(scsidev);
1496 }
1497 }
1498 return true;
1499 }
1500
1501
1502 #if (FREEBSDVER < 800000) // without this build fail on FreeBSD 8
1503 static char done[USB_MAX_DEVICES];
1504
1505 static int usbdevinfo(int f, int a, int rec, int busno, unsigned short & vendor_id,
1506 unsigned short & product_id, unsigned short & version)
1507 {
1508
1509 struct usb_device_info di;
1510 int e, p, i;
1511 char devname[256];
1512
1513 snprintf(devname, sizeof(devname),"umass%d",busno);
1514
1515 di.udi_addr = a;
1516 e = ioctl(f, USB_DEVICEINFO, &di);
1517 if (e) {
1518 if (errno != ENXIO)
1519 printf("addr %d: I/O error\n", a);
1520 return 0;
1521 }
1522 done[a] = 1;
1523
1524 // list devices
1525 for (i = 0; i < USB_MAX_DEVNAMES; i++) {
1526 if (di.udi_devnames[i][0]) {
1527 if(strcmp(di.udi_devnames[i],devname)==0) {
1528 // device found!
1529 vendor_id = di.udi_vendorNo;
1530 product_id = di.udi_productNo;
1531 version = di.udi_releaseNo;
1532 return 1;
1533 // FIXME
1534 }
1535 }
1536 }
1537 if (!rec)
1538 return 0;
1539 for (p = 0; p < di.udi_nports; p++) {
1540 int s = di.udi_ports[p];
1541 if (s >= USB_MAX_DEVICES) {
1542 continue;
1543 }
1544 if (s == 0)
1545 printf("addr 0 should never happen!\n");
1546 else {
1547 if(usbdevinfo(f, s, 1, busno, vendor_id, product_id, version)) return 1;
1548 }
1549 }
1550 return 0;
1551 }
1552 #endif
1553
1554
1555 static int usbdevlist(int busno,unsigned short & vendor_id,
1556 unsigned short & product_id, unsigned short & version)
1557 {
1558 #if (FREEBSDVER >= 800000) // libusb2 interface
1559 struct libusb20_device *pdev = NULL;
1560 struct libusb20_backend *pbe;
1561 uint32_t matches = 0;
1562 char buf[128]; // do not change!
1563 char devname[128];
1564 uint8_t n;
1565 struct LIBUSB20_DEVICE_DESC_DECODED *pdesc;
1566
1567 pbe = libusb20_be_alloc_default();
1568
1569 while ((pdev = libusb20_be_device_foreach(pbe, pdev))) {
1570 matches++;
1571
1572 if (libusb20_dev_open(pdev, 0)) {
1573 warnx("libusb20_dev_open: could not open device");
1574 return 0;
1575 }
1576
1577 pdesc=libusb20_dev_get_device_desc(pdev);
1578
1579 snprintf(devname, sizeof(devname),"umass%d:",busno);
1580 for (n = 0; n != 255; n++) {
1581 if (libusb20_dev_get_iface_desc(pdev, n, buf, sizeof(buf)))
1582 break;
1583 if (buf[0] == 0)
1584 continue;
1585 if(strncmp(buf,devname,strlen(devname))==0){
1586 // found!
1587 vendor_id = pdesc->idVendor;
1588 product_id = pdesc->idProduct;
1589 version = pdesc->bcdDevice;
1590 libusb20_dev_close(pdev);
1591 libusb20_be_free(pbe);
1592 return 1;
1593 }
1594 }
1595
1596 libusb20_dev_close(pdev);
1597 }
1598
1599 if (matches == 0) {
1600 printf("No device match or lack of permissions.\n");
1601 }
1602
1603 libusb20_be_free(pbe);
1604
1605 return false;
1606 #else // freebsd < 8.0 USB stack, ioctl interface
1607
1608 int i, f, a, rc;
1609 char buf[50];
1610 int ncont;
1611
1612 for (ncont = 0, i = 0; i < 10; i++) {
1613 snprintf(buf, sizeof(buf), "%s%d", USBDEV, i);
1614 f = open(buf, O_RDONLY);
1615 if (f >= 0) {
1616 memset(done, 0, sizeof done);
1617 for (a = 1; a < USB_MAX_DEVICES; a++) {
1618 if (!done[a]) {
1619 rc = usbdevinfo(f, a, 1, busno,vendor_id, product_id, version);
1620 if(rc) return 1;
1621 }
1622
1623 }
1624 close(f);
1625 } else {
1626 if (errno == ENOENT || errno == ENXIO)
1627 continue;
1628 warn("%s", buf);
1629 }
1630 ncont++;
1631 }
1632 return 0;
1633 #endif
1634 }
1635
1636 smart_device * freebsd_smart_interface::autodetect_smart_device(const char * name)
1637 {
1638 unsigned short vendor_id = 0, product_id = 0, version = 0;
1639 struct cam_device *cam_dev;
1640 union ccb ccb;
1641 int bus=-1;
1642 int i,c;
1643 int len;
1644
1645 // if dev_name null, or string length zero
1646 if (!name || !(len = strlen(name)))
1647 return false;
1648
1649 // check ATA bus
1650 char * * atanames = 0; int numata = 0;
1651 numata = get_dev_names_ata(&atanames);
1652 if (numata > 0) {
1653 // check ATA/ATAPI devices
1654 for (i = 0; i < numata; i++) {
1655 if(!strcmp(atanames[i],name)) {
1656 for (c = i; c < numata; c++) free(atanames[c]);
1657 free(atanames);
1658 return new freebsd_ata_device(this, name, "");
1659 }
1660 else free(atanames[i]);
1661 }
1662 if(numata) free(atanames);
1663 }
1664 else {
1665 if (numata < 0)
1666 pout("Unable to get ATA device list\n");
1667 }
1668
1669 // check CAM
1670 std::vector<std::string> scsinames;
1671 if (!get_dev_names_cam(scsinames, true))
1672 pout("Unable to get CAM device list\n");
1673 else if (!scsinames.empty()) {
1674 // check all devices on CAM bus
1675 for (i = 0; i < (int)scsinames.size(); i++) {
1676 if(strcmp(scsinames[i].c_str(), name)==0)
1677 { // our disk device is CAM
1678 if ((cam_dev = cam_open_device(name, O_RDWR)) == NULL) {
1679 // open failure
1680 set_err(errno);
1681 return false;
1682 }
1683
1684 // zero the payload
1685 bzero(&(&ccb.ccb_h)[1], PATHINQ_SETTINGS_SIZE);
1686 ccb.ccb_h.func_code = XPT_PATH_INQ; // send PATH_INQ to the device
1687 if (ioctl(cam_dev->fd, CAMIOCOMMAND, &ccb) == -1) {
1688 warn("Get Transfer Settings CCB failed\n"
1689 "%s", strerror(errno));
1690 cam_close_device(cam_dev);
1691 return 0;
1692 }
1693 // now check if we are working with USB device, see umass.c
1694 if(strcmp(ccb.cpi.dev_name,"umass-sim") == 0) { // USB device found
1695 usbdevlist(bus,vendor_id, product_id, version);
1696 int bus=ccb.cpi.unit_number; // unit_number will match umass number
1697 cam_close_device(cam_dev);
1698 if(usbdevlist(bus,vendor_id, product_id, version)){
1699 const char * usbtype = get_usb_dev_type_by_id(vendor_id, product_id, version);
1700 if (usbtype)
1701 return get_sat_device(usbtype, new freebsd_scsi_device(this, name, ""));
1702 }
1703 return false;
1704 }
1705 #if FREEBSDVER > 800100
1706 // check if we have ATA device connected to CAM (ada)
1707 if(ccb.cpi.protocol == PROTO_ATA){
1708 cam_close_device(cam_dev);
1709 return new freebsd_atacam_device(this, name, "");
1710 }
1711 #endif
1712 // close cam device, we don`t need it anymore
1713 cam_close_device(cam_dev);
1714 // handle as usual scsi
1715 return new freebsd_scsi_device(this, name, "");
1716 }
1717 }
1718 }
1719 // device type unknown
1720 return 0;
1721 }
1722
1723
1724 smart_device * freebsd_smart_interface::get_custom_smart_device(const char * name, const char * type)
1725 {
1726 // 3Ware ?
1727 static const char * fbsd_dev_twe_ctrl = "/dev/twe";
1728 static const char * fbsd_dev_twa_ctrl = "/dev/twa";
1729 int disknum = -1, n1 = -1, n2 = -1, contr = -1;
1730
1731 if (sscanf(type, "3ware,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) {
1732 if (n2 != (int)strlen(type)) {
1733 set_err(EINVAL, "Option -d 3ware,N requires N to be a non-negative integer");
1734 return 0;
1735 }
1736 if (!(0 <= disknum && disknum <= 127)) {
1737 set_err(EINVAL, "Option -d 3ware,N (N=%d) must have 0 <= N <= 127", disknum);
1738 return 0;
1739 }
1740
1741 // guess 3ware device type based on device name
1742 if (!strncmp(fbsd_dev_twa_ctrl, name, strlen(fbsd_dev_twa_ctrl))){
1743 contr=CONTROLLER_3WARE_9000_CHAR;
1744 }
1745 if (!strncmp(fbsd_dev_twe_ctrl, name, strlen(fbsd_dev_twe_ctrl))){
1746 contr=CONTROLLER_3WARE_678K_CHAR;
1747 }
1748
1749 if(contr == -1){
1750 set_err(EINVAL, "3ware controller type unknown, use %sX or %sX devices",
1751 fbsd_dev_twe_ctrl, fbsd_dev_twa_ctrl);
1752 return 0;
1753 }
1754 return new freebsd_escalade_device(this, name, contr, disknum);
1755 }
1756
1757 // Highpoint ?
1758 int controller = -1, channel = -1; disknum = 1;
1759 n1 = n2 = -1; int n3 = -1;
1760 if (sscanf(type, "hpt,%n%d/%d%n/%d%n", &n1, &controller, &channel, &n2, &disknum, &n3) >= 2 || n1 == 4) {
1761 int len = strlen(type);
1762 if (!(n2 == len || n3 == len)) {
1763 set_err(EINVAL, "Option '-d hpt,L/M/N' supports 2-3 items");
1764 return 0;
1765 }
1766 if (!(1 <= controller && controller <= 8)) {
1767 set_err(EINVAL, "Option '-d hpt,L/M/N' invalid controller id L supplied");
1768 return 0;
1769 }
1770 if (!(1 <= channel && channel <= 8)) {
1771 set_err(EINVAL, "Option '-d hpt,L/M/N' invalid channel number M supplied");
1772 return 0;
1773 }
1774 if (!(1 <= disknum && disknum <= 15)) {
1775 set_err(EINVAL, "Option '-d hpt,L/M/N' invalid pmport number N supplied");
1776 return 0;
1777 }
1778 return new freebsd_highpoint_device(this, name, controller, channel, disknum);
1779 }
1780
1781 // CCISS ?
1782 disknum = n1 = n2 = -1;
1783 if (sscanf(type, "cciss,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) {
1784 if (n2 != (int)strlen(type)) {
1785 set_err(EINVAL, "Option -d cciss,N requires N to be a non-negative integer");
1786 return 0;
1787 }
1788 if (!(0 <= disknum && disknum <= 127)) {
1789 set_err(EINVAL, "Option -d cciss,N (N=%d) must have 0 <= N <= 127", disknum);
1790 return 0;
1791 }
1792 return new freebsd_cciss_device(this, name, disknum);
1793 }
1794 #if FREEBSDVER > 800100
1795 // adaX devices ?
1796 if(!strcmp(type,"atacam"))
1797 return new freebsd_atacam_device(this, name, "");
1798 #endif
1799
1800 return 0;
1801 }
1802
1803 std::string freebsd_smart_interface::get_valid_custom_dev_types_str()
1804 {
1805 return "3ware,N, hpt,L/M/N, cciss,N"
1806 #if FREEBSDVER > 800100
1807 ", atacam"
1808 #endif
1809 ;
1810 }
1811
1812 } // namespace
1813
1814 /////////////////////////////////////////////////////////////////////////////
1815 /// Initialize platform interface and register with smi()
1816
1817 void smart_interface::init()
1818 {
1819 static os_freebsd::freebsd_smart_interface the_interface;
1820 smart_interface::set(&the_interface);
1821 }