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