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