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