1: /*
2: * os_freebsd.c
3: *
4: * Home page of code is: http://smartmontools.sourceforge.net
5: *
6: * Copyright (C) 2003-10 Eduard Martinescu <smartmontools-support@lists.sourceforge.net>
7: *
8: * This program is free software; you can redistribute it and/or modify
9: * it under the terms of the GNU General Public License as published by
10: * the Free Software Foundation; either version 2, or (at your option)
11: * any later version.
12: *
13: * You should have received a copy of the GNU General Public License
14: * (for example COPYING); if not, write to the Free
15: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16: */
17:
18: #include <stdio.h>
19: #include <sys/types.h>
20: #include <dirent.h>
21: #include <fcntl.h>
22: #include <err.h>
23: #include <errno.h>
24: #include <camlib.h>
25: #include <cam/scsi/scsi_message.h>
26: #include <cam/scsi/scsi_pass.h>
27: #if defined(__DragonFly__)
28: #include <sys/nata.h>
29: #else
30: #include <sys/ata.h>
31: #endif
32: #include <sys/stat.h>
33: #include <unistd.h>
34: #include <glob.h>
35: #include <stddef.h>
36: #include <paths.h>
37: #include <sys/utsname.h>
38:
39: #include "config.h"
40: #include "int64.h"
41: #include "atacmds.h"
42: #include "scsicmds.h"
43: #include "cciss.h"
44: #include "utility.h"
45: #include "os_freebsd.h"
46:
47: #include "dev_interface.h"
48: #include "dev_ata_cmd_set.h"
49:
50: #define USBDEV "/dev/usb"
51: #if defined(__FreeBSD_version)
52:
53: // This way we define one variable for the GNU/kFreeBSD and FreeBSD
54: #define FREEBSDVER __FreeBSD_version
55: #else
56: #define FREEBSDVER __FreeBSD_kernel_version
57: #endif
58:
59: #if (FREEBSDVER >= 800000)
60: #include <libusb20_desc.h>
61: #include <libusb20.h>
62: #elif defined(__DragonFly__)
63: #include <bus/usb/usb.h>
64: #include <bus/usb/usbhid.h>
65: #else
66: #include <dev/usb/usb.h>
67: #include <dev/usb/usbhid.h>
68: #endif
69:
70: #define CONTROLLER_3WARE_9000_CHAR 0x01
71: #define CONTROLLER_3WARE_678K_CHAR 0x02
72:
73: #ifndef PATHINQ_SETTINGS_SIZE
74: #define PATHINQ_SETTINGS_SIZE 128
75: #endif
76:
77: const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp,v 1.1.1.1 2012/02/21 16:32:16 misho Exp $" \
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"
197: " smartctl -a --device=areca,1 /dev/arcmsr0\n"
198: " (Prints all SMART information for first disk \n"
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: /////////////////////////////////////////////////////////////////////////////
934: /// Implement standard SCSI support with old functions
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: }
1016:
1017: // clear out structure, except for header that was filled in for us
1018: bzero(&(&ccb->ccb_h)[1],
1019: sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
1020:
1021: cam_fill_csio(&ccb->csio,
1022: /*retrires*/ 1,
1023: /*cbfcnp*/ NULL,
1024: /* flags */ (iop->dxfer_dir == DXFER_NONE ? CAM_DIR_NONE :(iop->dxfer_dir == DXFER_FROM_DEVICE ? CAM_DIR_IN : CAM_DIR_OUT)),
1025: /* tagaction */ MSG_SIMPLE_Q_TAG,
1026: /* dataptr */ iop->dxferp,
1027: /* datalen */ iop->dxfer_len,
1028: /* senselen */ iop->max_sense_len,
1029: /* cdblen */ iop->cmnd_len,
1030: /* timout (converted to seconds) */ iop->timeout*1000);
1031: memcpy(ccb->csio.cdb_io.cdb_bytes,iop->cmnd,iop->cmnd_len);
1032:
1033: if (cam_send_ccb(m_camdev,ccb) < 0) {
1034: warn("error sending SCSI ccb");
1035: cam_error_print(m_camdev,ccb,CAM_ESF_ALL,CAM_EPF_ALL,stderr);
1036: cam_freeccb(ccb);
1037: return -EIO;
1038: }
1039:
1040: if (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) && ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_SCSI_STATUS_ERROR)) {
1041: cam_error_print(m_camdev,ccb,CAM_ESF_ALL,CAM_EPF_ALL,stderr);
1042: cam_freeccb(ccb);
1043: return -EIO;
1044: }
1045:
1046: if (iop->sensep) {
1047: memcpy(iop->sensep,&(ccb->csio.sense_data),sizeof(struct scsi_sense_data));
1048: iop->resp_sense_len = sizeof(struct scsi_sense_data);
1049: }
1050:
1051: iop->scsi_status = ccb->csio.scsi_status;
1052:
1053: cam_freeccb(ccb);
1054:
1055: if (report > 0) {
1056: int trunc;
1057:
1058: pout(" status=0\n");
1059: trunc = (iop->dxfer_len > 256) ? 1 : 0;
1060:
1061: pout(" Incoming data, len=%d%s:\n", (int)iop->dxfer_len,
1062: (trunc ? " [only first 256 bytes shown]" : ""));
1063: dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
1064: }
1065:
1066: return true;
1067: }
1068:
1069:
1070: /////////////////////////////////////////////////////////////////////////////
1071: /// Areca RAID support
1072:
1073: class freebsd_areca_device
1074: : public /*implements*/ ata_device,
1075: public /*extends*/ freebsd_smart_device
1076: {
1077: public:
1078: freebsd_areca_device(smart_interface * intf, const char * dev_name, int disknum);
1079:
1080: protected:
1081: virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
1082:
1083: private:
1084: int m_disknum; ///< Disk number.
1085: };
1086:
1087:
1088: // PURPOSE
1089: // This is an interface routine meant to isolate the OS dependent
1090: // parts of the code, and to provide a debugging interface. Each
1091: // different port and OS needs to provide it's own interface. This
1092: // is the linux interface to the Areca "arcmsr" driver. It allows ATA
1093: // commands to be passed through the SCSI driver.
1094: // DETAILED DESCRIPTION OF ARGUMENTS
1095: // fd: is the file descriptor provided by open()
1096: // disknum is the disk number (0 to 15) in the RAID array
1097: // command: defines the different operations.
1098: // select: additional input data if needed (which log, which type of
1099: // self-test).
1100: // data: location to write output data, if needed (512 bytes).
1101: // Note: not all commands use all arguments.
1102: // RETURN VALUES
1103: // -1 if the command failed
1104: // 0 if the command succeeded,
1105: // STATUS_CHECK routine:
1106: // -1 if the command failed
1107: // 0 if the command succeeded and disk SMART status is "OK"
1108: // 1 if the command succeeded and disk SMART status is "FAILING"
1109:
1110:
1111: /*FunctionCode*/
1112: #define FUNCTION_READ_RQBUFFER 0x0801
1113: #define FUNCTION_WRITE_WQBUFFER 0x0802
1114: #define FUNCTION_CLEAR_RQBUFFER 0x0803
1115: #define FUNCTION_CLEAR_WQBUFFER 0x0804
1116:
1117: /* ARECA IO CONTROL CODE*/
1118: #define ARCMSR_IOCTL_READ_RQBUFFER _IOWR('F', FUNCTION_READ_RQBUFFER, sSRB_BUFFER)
1119: #define ARCMSR_IOCTL_WRITE_WQBUFFER _IOWR('F', FUNCTION_WRITE_WQBUFFER, sSRB_BUFFER)
1120: #define ARCMSR_IOCTL_CLEAR_RQBUFFER _IOWR('F', FUNCTION_CLEAR_RQBUFFER, sSRB_BUFFER)
1121: #define ARCMSR_IOCTL_CLEAR_WQBUFFER _IOWR('F', FUNCTION_CLEAR_WQBUFFER, sSRB_BUFFER)
1122: #define ARECA_SIG_STR "ARCMSR"
1123:
1124:
1125:
1126: // The SRB_IO_CONTROL & SRB_BUFFER structures are used to communicate(to/from) to areca driver
1127: typedef struct _SRB_IO_CONTROL
1128: {
1129: unsigned int HeaderLength;
1130: unsigned char Signature[8];
1131: unsigned int Timeout;
1132: unsigned int ControlCode;
1133: unsigned int ReturnCode;
1134: unsigned int Length;
1135: } sSRB_IO_CONTROL;
1136:
1137: typedef struct _SRB_BUFFER
1138: {
1139: sSRB_IO_CONTROL srbioctl;
1140: unsigned char ioctldatabuffer[1032]; // the buffer to put the command data to/from firmware
1141: } sSRB_BUFFER;
1142:
1143:
1144: // For debugging areca code
1145:
1146: static void areca_dumpdata(unsigned char *block, int len)
1147: {
1148: int ln = (len / 16) + 1; // total line#
1149: unsigned char c;
1150: int pos = 0;
1151:
1152: printf(" Address = %p, Length = (0x%x)%d\n", block, len, len);
1153: printf(" 0 1 2 3 4 5 6 7 8 9 A B C D E F ASCII \n");
1154: printf("=====================================================================\n");
1155:
1156: for ( int l = 0; l < ln && len; l++ )
1157: {
1158: // printf the line# and the HEX data
1159: // if a line data length < 16 then append the space to the tail of line to reach 16 chars
1160: printf("%02X | ", l);
1161: for ( pos = 0; pos < 16 && len; pos++, len-- )
1162: {
1163: c = block[l*16+pos];
1164: printf("%02X ", c);
1165: }
1166:
1167: if ( pos < 16 )
1168: {
1169: for ( int loop = pos; loop < 16; loop++ )
1170: {
1171: printf(" ");
1172: }
1173: }
1174:
1175: // print ASCII char
1176: for ( int loop = 0; loop < pos; loop++ )
1177: {
1178: c = block[l*16+loop];
1179: if ( c >= 0x20 && c <= 0x7F )
1180: {
1181: printf("%c", c);
1182: }
1183: else
1184: {
1185: printf(".");
1186: }
1187: }
1188: printf("\n");
1189: }
1190: printf("=====================================================================\n");
1191: }
1192:
1193:
1194: static int arcmsr_command_handler(int fd, unsigned long arcmsr_cmd, unsigned char *data, int data_len, void *ext_data /* reserved for further use */)
1195: {
1196: ARGUSED(ext_data);
1197:
1198: int ioctlreturn = 0;
1199: sSRB_BUFFER sBuf;
1200:
1201: unsigned char *areca_return_packet;
1202: int total = 0;
1203: int expected = -1;
1204: unsigned char return_buff[2048];
1205: unsigned char *ptr = &return_buff[0];
1206: memset(return_buff, 0, sizeof(return_buff));
1207:
1208: memset((unsigned char *)&sBuf, 0, sizeof(sBuf));
1209:
1210:
1211: sBuf.srbioctl.HeaderLength = sizeof(sSRB_IO_CONTROL);
1212: memcpy(sBuf.srbioctl.Signature, ARECA_SIG_STR, strlen(ARECA_SIG_STR));
1213: sBuf.srbioctl.Timeout = 10000;
1214: sBuf.srbioctl.ControlCode = ARCMSR_IOCTL_READ_RQBUFFER;
1215:
1216: switch ( arcmsr_cmd )
1217: {
1218: // command for writing data to driver
1219: case ARCMSR_IOCTL_WRITE_WQBUFFER:
1220: if ( data && data_len )
1221: {
1222: sBuf.srbioctl.Length = data_len;
1223: memcpy((unsigned char *)sBuf.ioctldatabuffer, (unsigned char *)data, data_len);
1224: }
1225: // commands for clearing related buffer of driver
1226: case ARCMSR_IOCTL_CLEAR_RQBUFFER:
1227: case ARCMSR_IOCTL_CLEAR_WQBUFFER:
1228: break;
1229: // command for reading data from driver
1230: case ARCMSR_IOCTL_READ_RQBUFFER:
1231: break;
1232: default:
1233: // unknown arcmsr commands
1234: return -1;
1235: }
1236:
1237:
1238: while ( 1 )
1239: {
1240: ioctlreturn = ioctl(fd,arcmsr_cmd,&sBuf);
1241: if ( ioctlreturn )
1242: {
1243: // errors found
1244: break;
1245: }
1246:
1247: if ( arcmsr_cmd != ARCMSR_IOCTL_READ_RQBUFFER )
1248: {
1249: // if succeeded, just returns the length of outgoing data
1250: return data_len;
1251: }
1252:
1253: if ( sBuf.srbioctl.Length )
1254: {
1255: if(ata_debugmode)
1256: areca_dumpdata(&sBuf.ioctldatabuffer[0], sBuf.srbioctl.Length);
1257: memcpy(ptr, &sBuf.ioctldatabuffer[0], sBuf.srbioctl.Length);
1258: ptr += sBuf.srbioctl.Length;
1259: total += sBuf.srbioctl.Length;
1260: // the returned bytes enough to compute payload length ?
1261: if ( expected < 0 && total >= 5 )
1262: {
1263: areca_return_packet = (unsigned char *)&return_buff[0];
1264: if ( areca_return_packet[0] == 0x5E &&
1265: areca_return_packet[1] == 0x01 &&
1266: areca_return_packet[2] == 0x61 )
1267: {
1268: // valid header, let's compute the returned payload length,
1269: // we expected the total length is
1270: // payload + 3 bytes header + 2 bytes length + 1 byte checksum
1271: expected = areca_return_packet[4] * 256 + areca_return_packet[3] + 6;
1272: }
1273: }
1274:
1275: if ( total >= 7 && total >= expected )
1276: {
1277: //printf("total bytes received = %d, expected length = %d\n", total, expected);
1278:
1279: // ------ Okay! we received enough --------
1280: break;
1281: }
1282: }
1283: }
1284:
1285: // Deal with the different error cases
1286: if ( ioctlreturn )
1287: {
1288: pout("ioctl write buffer failed code = %x\n", ioctlreturn);
1289: return -2;
1290: }
1291:
1292:
1293: if ( data )
1294: {
1295: memcpy(data, return_buff, total);
1296: }
1297:
1298: return total;
1299: }
1300:
1301:
1302: freebsd_areca_device::freebsd_areca_device(smart_interface * intf, const char * dev_name, int disknum)
1303: : smart_device(intf, dev_name, "areca", "areca"),
1304: freebsd_smart_device("ATA"),
1305: m_disknum(disknum)
1306: {
1307: set_info().info_name = strprintf("%s [areca_%02d]", dev_name, disknum);
1308: }
1309:
1310: // Areca RAID Controller
1311: // int freebsd_areca_device::ata_command_interface(smart_command_set command, int select, char * data)
1312: bool freebsd_areca_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
1313: {
1314: if (!ata_cmd_is_ok(in,
1315: true, // data_out_support
1316: false, // TODO: multi_sector_support
1317: true) // ata_48bit_support
1318: )
1319: return false;
1320:
1321: // ATA input registers
1322: typedef struct _ATA_INPUT_REGISTERS
1323: {
1324: unsigned char features;
1325: unsigned char sector_count;
1326: unsigned char sector_number;
1327: unsigned char cylinder_low;
1328: unsigned char cylinder_high;
1329: unsigned char device_head;
1330: unsigned char command;
1331: unsigned char reserved[8];
1332: unsigned char data[512]; // [in/out] buffer for outgoing/incoming data
1333: } sATA_INPUT_REGISTERS;
1334:
1335: // ATA output registers
1336: // Note: The output registers is re-sorted for areca internal use only
1337: typedef struct _ATA_OUTPUT_REGISTERS
1338: {
1339: unsigned char error;
1340: unsigned char status;
1341: unsigned char sector_count;
1342: unsigned char sector_number;
1343: unsigned char cylinder_low;
1344: unsigned char cylinder_high;
1345: }sATA_OUTPUT_REGISTERS;
1346:
1347: // Areca packet format for outgoing:
1348: // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
1349: // B[3~4] : 2 bytes command length + variant data length, little endian
1350: // B[5] : 1 bytes areca defined command code, ATA passthrough command code is 0x1c
1351: // B[6~last-1] : variant bytes payload data
1352: // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
1353: //
1354: //
1355: // header 3 bytes length 2 bytes cmd 1 byte payload data x bytes cs 1 byte
1356: // +--------------------------------------------------------------------------------+
1357: // + 0x5E 0x01 0x61 | 0x00 0x00 | 0x1c | .................... | 0x00 |
1358: // +--------------------------------------------------------------------------------+
1359: //
1360:
1361: //Areca packet format for incoming:
1362: // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
1363: // B[3~4] : 2 bytes payload length, little endian
1364: // B[5~last-1] : variant bytes returned payload data
1365: // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
1366: //
1367: //
1368: // header 3 bytes length 2 bytes payload data x bytes cs 1 byte
1369: // +-------------------------------------------------------------------+
1370: // + 0x5E 0x01 0x61 | 0x00 0x00 | .................... | 0x00 |
1371: // +-------------------------------------------------------------------+
1372: unsigned char areca_packet[640];
1373: int areca_packet_len = sizeof(areca_packet);
1374: unsigned char cs = 0;
1375:
1376: sATA_INPUT_REGISTERS *ata_cmd;
1377:
1378: // For debugging
1379: memset(areca_packet, 0, areca_packet_len);
1380:
1381: // ----- BEGIN TO SETUP HEADERS -------
1382: areca_packet[0] = 0x5E;
1383: areca_packet[1] = 0x01;
1384: areca_packet[2] = 0x61;
1385: areca_packet[3] = (unsigned char)((areca_packet_len - 6) & 0xff);
1386: areca_packet[4] = (unsigned char)(((areca_packet_len - 6) >> 8) & 0xff);
1387: areca_packet[5] = 0x1c; // areca defined code for ATA passthrough command
1388:
1389: // ----- BEGIN TO SETUP PAYLOAD DATA -----
1390: memcpy(&areca_packet[7], "SmrT", 4); // areca defined password
1391: ata_cmd = (sATA_INPUT_REGISTERS *)&areca_packet[12];
1392:
1393: // Set registers
1394: {
1395: const ata_in_regs_48bit & r = in.in_regs;
1396: ata_cmd->features = r.features_16;
1397: ata_cmd->sector_count = r.sector_count_16;
1398: ata_cmd->sector_number = r.lba_low_16;
1399: ata_cmd->cylinder_low = r.lba_mid_16;
1400: ata_cmd->cylinder_high = r.lba_high_16;
1401: ata_cmd->device_head = r.device;
1402: ata_cmd->command = r.command;
1403: }
1404: bool readdata = false;
1405: if (in.direction == ata_cmd_in::data_in) {
1406: readdata = true;
1407: // the command will read data
1408: areca_packet[6] = 0x13;
1409: }
1410: else if ( in.direction == ata_cmd_in::no_data )
1411: {
1412: // the commands will return no data
1413: areca_packet[6] = 0x15;
1414: }
1415: else if (in.direction == ata_cmd_in::data_out)
1416: {
1417: // the commands will write data
1418: memcpy(ata_cmd->data, in.buffer, in.size);
1419: areca_packet[6] = 0x14;
1420: }
1421: else {
1422: // COMMAND NOT SUPPORTED VIA ARECA IOCTL INTERFACE
1423: return set_err(ENOTSUP, "DATA OUT not supported for this Areca controller type");
1424: }
1425:
1426: areca_packet[11] = m_disknum - 1; // drive number
1427:
1428: // ----- BEGIN TO SETUP CHECKSUM -----
1429: for ( int loop = 3; loop < areca_packet_len - 1; loop++ )
1430: {
1431: cs += areca_packet[loop];
1432: }
1433: areca_packet[areca_packet_len-1] = cs;
1434:
1435: // ----- BEGIN TO SEND TO ARECA DRIVER ------
1436: int expected = 0;
1437: unsigned char return_buff[2048];
1438: memset(return_buff, 0, sizeof(return_buff));
1439:
1440: expected = arcmsr_command_handler(get_fd(), ARCMSR_IOCTL_CLEAR_RQBUFFER, NULL, 0, NULL);
1441: if (expected==-3) {
1442: return set_err(EIO);
1443: }
1444:
1445: expected = arcmsr_command_handler(get_fd(), ARCMSR_IOCTL_CLEAR_WQBUFFER, NULL, 0, NULL);
1446: expected = arcmsr_command_handler(get_fd(), ARCMSR_IOCTL_WRITE_WQBUFFER, areca_packet, areca_packet_len, NULL);
1447: if ( expected > 0 )
1448: {
1449: expected = arcmsr_command_handler(get_fd(), ARCMSR_IOCTL_READ_RQBUFFER, return_buff, sizeof(return_buff), NULL);
1450: }
1451: if ( expected < 0 )
1452: {
1453: return -1;
1454: }
1455:
1456: // ----- VERIFY THE CHECKSUM -----
1457: cs = 0;
1458: for ( int loop = 3; loop < expected - 1; loop++ )
1459: {
1460: cs += return_buff[loop];
1461: }
1462:
1463: if ( return_buff[expected - 1] != cs )
1464: {
1465: return set_err(EIO);
1466: }
1467:
1468: sATA_OUTPUT_REGISTERS *ata_out = (sATA_OUTPUT_REGISTERS *)&return_buff[5] ;
1469: if ( ata_out->status )
1470: {
1471: if ( in.in_regs.command == ATA_IDENTIFY_DEVICE
1472: && !nonempty((unsigned char *)in.buffer, in.size))
1473: {
1474: return set_err(ENODEV, "No drive on port %d", m_disknum);
1475: }
1476: }
1477:
1478: // returns with data
1479: if (readdata)
1480: {
1481: memcpy(in.buffer, &return_buff[7], in.size);
1482: }
1483:
1484: // Return register values
1485: {
1486: ata_out_regs_48bit & r = out.out_regs;
1487: r.error = ata_out->error;
1488: r.sector_count_16 = ata_out->sector_count;
1489: r.lba_low_16 = ata_out->sector_number;
1490: r.lba_mid_16 = ata_out->cylinder_low;
1491: r.lba_high_16 = ata_out->cylinder_high;
1492: r.status = ata_out->status;
1493: }
1494: return true;
1495: }
1496:
1497:
1498:
1499: /////////////////////////////////////////////////////////////////////////////
1500: /// Implement CCISS RAID support with old functions
1501:
1502: class freebsd_cciss_device
1503: : public /*implements*/ scsi_device,
1504: public /*extends*/ freebsd_smart_device
1505: {
1506: public:
1507: freebsd_cciss_device(smart_interface * intf, const char * name, unsigned char disknum);
1508:
1509: virtual bool scsi_pass_through(scsi_cmnd_io * iop);
1510: virtual bool open();
1511:
1512: private:
1513: unsigned char m_disknum; ///< Disk number.
1514: };
1515:
1516: bool freebsd_cciss_device::open()
1517: {
1518: const char *dev = get_dev_name();
1519: int fd;
1520: if ((fd = ::open(dev,O_RDWR))<0) {
1521: set_err(errno);
1522: return false;
1523: }
1524: set_fd(fd);
1525: return true;
1526: }
1527:
1528: freebsd_cciss_device::freebsd_cciss_device(smart_interface * intf,
1529: const char * dev_name, unsigned char disknum)
1530: : smart_device(intf, dev_name, "cciss", "cciss"),
1531: freebsd_smart_device("SCSI"),
1532: m_disknum(disknum)
1533: {
1534: set_info().info_name = strprintf("%s [cciss_disk_%02d]", dev_name, disknum);
1535: }
1536:
1537: bool freebsd_cciss_device::scsi_pass_through(scsi_cmnd_io * iop)
1538: {
1539: int status = cciss_io_interface(get_fd(), m_disknum, iop, scsi_debugmode);
1540: if (status < 0)
1541: return set_err(-status);
1542: return true;
1543: // not reached
1544: return true;
1545: }
1546:
1547:
1548: /////////////////////////////////////////////////////////////////////////////
1549: /// SCSI open with autodetection support
1550:
1551: smart_device * freebsd_scsi_device::autodetect_open()
1552: {
1553: // Open device
1554: if (!open())
1555: return this;
1556:
1557: // No Autodetection if device type was specified by user
1558: if (*get_req_type())
1559: return this;
1560:
1561: // The code below is based on smartd.cpp:SCSIFilterKnown()
1562:
1563: // Get INQUIRY
1564: unsigned char req_buff[64] = {0, };
1565: int req_len = 36;
1566: if (scsiStdInquiry(this, req_buff, req_len)) {
1567: // Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices
1568: // watch this spot ... other devices could lock up here
1569: req_len = 64;
1570: if (scsiStdInquiry(this, req_buff, req_len)) {
1571: // device doesn't like INQUIRY commands
1572: close();
1573: set_err(EIO, "INQUIRY failed");
1574: return this;
1575: }
1576: }
1577:
1578: int avail_len = req_buff[4] + 5;
1579: int len = (avail_len < req_len ? avail_len : req_len);
1580: if (len < 36)
1581: return this;
1582:
1583: // Use INQUIRY to detect type
1584:
1585: // 3ware ?
1586: if (!memcmp(req_buff + 8, "3ware", 5) || !memcmp(req_buff + 8, "AMCC", 4)) {
1587: close();
1588: set_err(EINVAL, "AMCC/3ware controller, please try adding '-d 3ware,N',\n"
1589: "you may need to replace %s with /dev/twaN or /dev/tweN", get_dev_name());
1590: return this;
1591: }
1592:
1593: // SAT or USB ?
1594: {
1595: smart_device * newdev = smi()->autodetect_sat_device(this, req_buff, len);
1596: if (newdev)
1597: // NOTE: 'this' is now owned by '*newdev'
1598: return newdev;
1599: }
1600:
1601: // Nothing special found
1602: return this;
1603: }
1604:
1605:
1606: /////////////////////////////////////////////////////////////////////////////
1607: /// Implement platform interface with old functions.
1608:
1609: class freebsd_smart_interface
1610: : public /*implements*/ smart_interface
1611: {
1612: public:
1613: virtual std::string get_os_version_str();
1614:
1615: virtual std::string get_app_examples(const char * appname);
1616:
1617: virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
1618: const char * pattern = 0);
1619:
1620: protected:
1621: virtual ata_device * get_ata_device(const char * name, const char * type);
1622:
1623: #if FREEBSDVER > 800100
1624: virtual ata_device * get_atacam_device(const char * name, const char * type);
1625: #endif
1626:
1627: virtual scsi_device * get_scsi_device(const char * name, const char * type);
1628:
1629: virtual smart_device * autodetect_smart_device(const char * name);
1630:
1631: virtual smart_device * get_custom_smart_device(const char * name, const char * type);
1632:
1633: virtual std::string get_valid_custom_dev_types_str();
1634: };
1635:
1636:
1637: //////////////////////////////////////////////////////////////////////
1638:
1639: std::string freebsd_smart_interface::get_os_version_str()
1640: {
1641: struct utsname osname;
1642: uname(&osname);
1643: return strprintf("%s %s %s", osname.sysname, osname.release, osname.machine);
1644: }
1645:
1646: std::string freebsd_smart_interface::get_app_examples(const char * appname)
1647: {
1648: if (!strcmp(appname, "smartctl"))
1649: return smartctl_examples;
1650: return "";
1651: }
1652:
1653: ata_device * freebsd_smart_interface::get_ata_device(const char * name, const char * type)
1654: {
1655: return new freebsd_ata_device(this, name, type);
1656: }
1657:
1658: #if FREEBSDVER > 800100
1659: ata_device * freebsd_smart_interface::get_atacam_device(const char * name, const char * type)
1660: {
1661: return new freebsd_atacam_device(this, name, type);
1662: }
1663: #endif
1664:
1665: scsi_device * freebsd_smart_interface::get_scsi_device(const char * name, const char * type)
1666: {
1667: return new freebsd_scsi_device(this, name, type);
1668: }
1669:
1670: // we are using CAM subsystem XPT enumerator to found all CAM (scsi/usb/ada/...)
1671: // devices on system despite of it's names
1672: //
1673: // If any errors occur, leave errno set as it was returned by the
1674: // system call, and return <0.
1675: //
1676: // arguments:
1677: // names: resulting array
1678: // show_all - export duplicate device name or not
1679: //
1680: // Return values:
1681: // -1: error
1682: // >=0: number of discovered devices
1683:
1684: bool get_dev_names_cam(std::vector<std::string> & names, bool show_all)
1685: {
1686: int fd;
1687: if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
1688: if (errno == ENOENT) /* There are no CAM device on this computer */
1689: return 0;
1690: int serrno = errno;
1691: pout("%s control device couldn't opened: %s\n", XPT_DEVICE, strerror(errno));
1692: errno = serrno;
1693: return false;
1694: }
1695:
1696: union ccb ccb;
1697: bzero(&ccb, sizeof(union ccb));
1698:
1699: ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
1700: ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
1701: ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
1702:
1703: ccb.ccb_h.func_code = XPT_DEV_MATCH;
1704: int bufsize = sizeof(struct dev_match_result) * MAX_NUM_DEV;
1705: ccb.cdm.match_buf_len = bufsize;
1706: // TODO: Use local buffer instead of malloc() if possible
1707: ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
1708: bzero(ccb.cdm.matches,bufsize); // clear ccb.cdm.matches structure
1709:
1710: if (ccb.cdm.matches == NULL) {
1711: close(fd);
1712: throw std::bad_alloc();
1713: }
1714: ccb.cdm.num_matches = 0;
1715: ccb.cdm.num_patterns = 0;
1716: ccb.cdm.pattern_buf_len = 0;
1717:
1718: /*
1719: * We do the ioctl multiple times if necessary, in case there are
1720: * more than MAX_NUM_DEV nodes in the EDT.
1721: */
1722: int skip_device = 0, skip_bus = 0, changed = 0; // TODO: bool
1723: std::string devname;
1724: do {
1725: if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
1726: int serrno = errno;
1727: pout("error sending CAMIOCOMMAND ioctl: %s\n", strerror(errno));
1728: free(ccb.cdm.matches);
1729: close(fd);
1730: errno = serrno;
1731: return false;
1732: }
1733:
1734: if ((ccb.ccb_h.status != CAM_REQ_CMP)
1735: || ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
1736: && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
1737: pout("got CAM error %#x, CDM error %d\n", ccb.ccb_h.status, ccb.cdm.status);
1738: free(ccb.cdm.matches);
1739: close(fd);
1740: errno = ENXIO;
1741: return false;
1742: }
1743:
1744: for (unsigned i = 0; i < ccb.cdm.num_matches; i++) {
1745: struct bus_match_result *bus_result;
1746: struct device_match_result *dev_result;
1747: struct periph_match_result *periph_result;
1748:
1749: if (ccb.cdm.matches[i].type == DEV_MATCH_BUS) {
1750: bus_result = &ccb.cdm.matches[i].result.bus_result;
1751:
1752: if (strcmp(bus_result->dev_name,"ata") == 0 /* ATAPICAM devices will be probed as ATA devices, skip'em there */
1753: || strcmp(bus_result->dev_name,"xpt") == 0) /* skip XPT bus at all */
1754: skip_bus = 1;
1755: else
1756: skip_bus = 0;
1757: changed = 1;
1758: } else if (ccb.cdm.matches[i].type == DEV_MATCH_DEVICE) {
1759: dev_result = &ccb.cdm.matches[i].result.device_result;
1760:
1761: if (dev_result->flags & DEV_RESULT_UNCONFIGURED || skip_bus == 1)
1762: skip_device = 1;
1763: else
1764: skip_device = 0;
1765:
1766: // /* Shall we skip non T_DIRECT devices ? */
1767: // if (dev_result->inq_data.device != T_DIRECT)
1768: // skip_device = 1;
1769: changed = 1;
1770: } else if (ccb.cdm.matches[i].type == DEV_MATCH_PERIPH &&
1771: (skip_device == 0 || show_all)) {
1772: /* One device may be populated as many peripherals (pass0 & da0 for example).
1773: * We are searching for latest name
1774: */
1775: periph_result = &ccb.cdm.matches[i].result.periph_result;
1776: devname = strprintf("%s%s%d", _PATH_DEV, periph_result->periph_name, periph_result->unit_number);
1777: changed = 0;
1778: };
1779: if ((changed == 1 || show_all) && !devname.empty()) {
1780: names.push_back(devname);
1781: devname.erase();
1782: changed = 0;
1783: };
1784: }
1785:
1786: } while ((ccb.ccb_h.status == CAM_REQ_CMP) && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
1787:
1788: if (!devname.empty())
1789: names.push_back(devname);
1790:
1791: free(ccb.cdm.matches);
1792: close(fd);
1793: return true;
1794: }
1795:
1796: // we are using ATA subsystem enumerator to found all ATA devices on system
1797: // despite of it's names
1798: //
1799: // If any errors occur, leave errno set as it was returned by the
1800: // system call, and return <0.
1801:
1802: // Return values:
1803: // -1: error
1804: // >=0: number of discovered devices
1805: int get_dev_names_ata(char*** names) {
1806: struct ata_ioc_devices devices;
1807: int fd=-1,maxchannel,serrno=-1,n=0;
1808: char **mp = NULL;
1809:
1810: *names=NULL;
1811:
1812: if ((fd = open(ATA_DEVICE, O_RDWR)) < 0) {
1813: if (errno == ENOENT) /* There are no ATA device on this computer */
1814: return 0;
1815: serrno = errno;
1816: pout("%s control device can't be opened: %s\n", ATA_DEVICE, strerror(errno));
1817: n = -1;
1818: goto end;
1819: };
1820:
1821: if (ioctl(fd, IOCATAGMAXCHANNEL, &maxchannel) < 0) {
1822: serrno = errno;
1823: pout("ioctl(IOCATAGMAXCHANNEL) on /dev/ata failed: %s\n", strerror(errno));
1824: n = -1;
1825: goto end;
1826: };
1827:
1828: // allocate space for up to MAX_NUM_DEV number of ATA devices
1829: mp = (char **)calloc(MAX_NUM_DEV, sizeof(char*));
1830: if (mp == NULL) {
1831: serrno=errno;
1832: pout("Out of memory constructing scan device list (on line %d)\n", __LINE__);
1833: n = -1;
1834: goto end;
1835: };
1836:
1837: for (devices.channel = 0; devices.channel < maxchannel && n < MAX_NUM_DEV; devices.channel++) {
1838: int j;
1839:
1840: if (ioctl(fd, IOCATADEVICES, &devices) < 0) {
1841: if (errno == ENXIO)
1842: continue; /* such channel not exist */
1843: pout("ioctl(IOCATADEVICES) on %s channel %d failed: %s\n", ATA_DEVICE, devices.channel, strerror(errno));
1844: n = -1;
1845: goto end;
1846: };
1847: for (j=0;j<=1 && n<MAX_NUM_DEV;j++) {
1848: if (devices.name[j][0] != '\0') {
1849: asprintf(mp+n, "%s%s", _PATH_DEV, devices.name[j]);
1850: if (mp[n] == NULL) {
1851: pout("Out of memory constructing scan ATA device list (on line %d)\n", __LINE__);
1852: n = -1;
1853: goto end;
1854: };
1855: bytes+=1+strlen(mp[n]);
1856: n++;
1857: };
1858: };
1859: };
1860: mp = (char **)reallocf(mp,n*(sizeof (char*))); // shrink to correct size
1861: if (mp == NULL && n > 0 ) { // reallocf never fail for size=0, but may return NULL
1862: serrno=errno;
1863: pout("Out of memory constructing scan device list (on line %d)\n", __LINE__);
1864: n = -1;
1865: goto end;
1866: };
1867: bytes += (n)*(sizeof(char*)); // and set allocated byte count
1868:
1869: end:
1870: if (fd>=0)
1871: close(fd);
1872: if (n <= 0) {
1873: free(mp);
1874: mp = NULL;
1875: }
1876:
1877: *names=mp;
1878:
1879: if (serrno>-1)
1880: errno=serrno;
1881: return n;
1882: }
1883:
1884:
1885:
1886: bool freebsd_smart_interface::scan_smart_devices(smart_device_list & devlist,
1887: const char * type, const char * pattern /*= 0*/)
1888: {
1889: if (pattern) {
1890: set_err(EINVAL, "DEVICESCAN with pattern not implemented yet");
1891: return false;
1892: }
1893:
1894: // Make namelists
1895: char * * atanames = 0; int numata = 0;
1896: if (!type || !strcmp(type, "ata")) {
1897: numata = get_dev_names_ata(&atanames);
1898: if (numata < 0) {
1899: set_err(ENOMEM);
1900: return false;
1901: }
1902: }
1903:
1904: std::vector<std::string> scsinames;
1905: if (!type || !strcmp(type, "scsi")) { // do not export duplicated names
1906: if (!get_dev_names_cam(scsinames, false)) {
1907: set_err(errno);
1908: return false;
1909: }
1910: }
1911:
1912: // Add to devlist
1913: int i;
1914: if (type==NULL)
1915: type="";
1916: for (i = 0; i < numata; i++) {
1917: ata_device * atadev = get_ata_device(atanames[i], type);
1918: if (atadev)
1919: devlist.push_back(atadev);
1920: free(atanames[i]);
1921: }
1922: if(numata) free(atanames);
1923:
1924: for (i = 0; i < (int)scsinames.size(); i++) {
1925: if(!*type) { // try USB autodetection if no type specified
1926: smart_device * smartdev = autodetect_smart_device(scsinames[i].c_str());
1927: if(smartdev)
1928: devlist.push_back(smartdev);
1929: }
1930: else {
1931: scsi_device * scsidev = get_scsi_device(scsinames[i].c_str(), type);
1932: if (scsidev)
1933: devlist.push_back(scsidev);
1934: }
1935: }
1936: return true;
1937: }
1938:
1939:
1940: #if (FREEBSDVER < 800000) // without this build fail on FreeBSD 8
1941: static char done[USB_MAX_DEVICES];
1942:
1943: static int usbdevinfo(int f, int a, int rec, int busno, unsigned short & vendor_id,
1944: unsigned short & product_id, unsigned short & version)
1945: {
1946:
1947: struct usb_device_info di;
1948: int e, p, i;
1949: char devname[256];
1950:
1951: snprintf(devname, sizeof(devname),"umass%d",busno);
1952:
1953: di.udi_addr = a;
1954: e = ioctl(f, USB_DEVICEINFO, &di);
1955: if (e) {
1956: if (errno != ENXIO)
1957: printf("addr %d: I/O error\n", a);
1958: return 0;
1959: }
1960: done[a] = 1;
1961:
1962: // list devices
1963: for (i = 0; i < USB_MAX_DEVNAMES; i++) {
1964: if (di.udi_devnames[i][0]) {
1965: if(strcmp(di.udi_devnames[i],devname)==0) {
1966: // device found!
1967: vendor_id = di.udi_vendorNo;
1968: product_id = di.udi_productNo;
1969: version = di.udi_releaseNo;
1970: return 1;
1971: // FIXME
1972: }
1973: }
1974: }
1975: if (!rec)
1976: return 0;
1977: for (p = 0; p < di.udi_nports; p++) {
1978: int s = di.udi_ports[p];
1979: if (s >= USB_MAX_DEVICES) {
1980: continue;
1981: }
1982: if (s == 0)
1983: printf("addr 0 should never happen!\n");
1984: else {
1985: if(usbdevinfo(f, s, 1, busno, vendor_id, product_id, version)) return 1;
1986: }
1987: }
1988: return 0;
1989: }
1990: #endif
1991:
1992:
1993: static int usbdevlist(int busno,unsigned short & vendor_id,
1994: unsigned short & product_id, unsigned short & version)
1995: {
1996: #if (FREEBSDVER >= 800000) // libusb2 interface
1997: struct libusb20_device *pdev = NULL;
1998: struct libusb20_backend *pbe;
1999: uint32_t matches = 0;
2000: char buf[128]; // do not change!
2001: char devname[128];
2002: uint8_t n;
2003: struct LIBUSB20_DEVICE_DESC_DECODED *pdesc;
2004:
2005: pbe = libusb20_be_alloc_default();
2006:
2007: while ((pdev = libusb20_be_device_foreach(pbe, pdev))) {
2008: matches++;
2009:
2010: if (libusb20_dev_open(pdev, 0)) {
2011: warnx("libusb20_dev_open: could not open device");
2012: return 0;
2013: }
2014:
2015: pdesc=libusb20_dev_get_device_desc(pdev);
2016:
2017: snprintf(devname, sizeof(devname),"umass%d:",busno);
2018: for (n = 0; n != 255; n++) {
2019: if (libusb20_dev_get_iface_desc(pdev, n, buf, sizeof(buf)))
2020: break;
2021: if (buf[0] == 0)
2022: continue;
2023: if(strncmp(buf,devname,strlen(devname))==0){
2024: // found!
2025: vendor_id = pdesc->idVendor;
2026: product_id = pdesc->idProduct;
2027: version = pdesc->bcdDevice;
2028: libusb20_dev_close(pdev);
2029: libusb20_be_free(pbe);
2030: return 1;
2031: }
2032: }
2033:
2034: libusb20_dev_close(pdev);
2035: }
2036:
2037: if (matches == 0) {
2038: printf("No device match or lack of permissions.\n");
2039: }
2040:
2041: libusb20_be_free(pbe);
2042:
2043: return false;
2044: #else // freebsd < 8.0 USB stack, ioctl interface
2045:
2046: int i, f, a, rc;
2047: char buf[50];
2048: int ncont;
2049:
2050: for (ncont = 0, i = 0; i < 10; i++) {
2051: snprintf(buf, sizeof(buf), "%s%d", USBDEV, i);
2052: f = open(buf, O_RDONLY);
2053: if (f >= 0) {
2054: memset(done, 0, sizeof done);
2055: for (a = 1; a < USB_MAX_DEVICES; a++) {
2056: if (!done[a]) {
2057: rc = usbdevinfo(f, a, 1, busno,vendor_id, product_id, version);
2058: if(rc) return 1;
2059: }
2060:
2061: }
2062: close(f);
2063: } else {
2064: if (errno == ENOENT || errno == ENXIO)
2065: continue;
2066: warn("%s", buf);
2067: }
2068: ncont++;
2069: }
2070: return 0;
2071: #endif
2072: }
2073:
2074: smart_device * freebsd_smart_interface::autodetect_smart_device(const char * name)
2075: {
2076: unsigned short vendor_id = 0, product_id = 0, version = 0;
2077: struct cam_device *cam_dev;
2078: union ccb ccb;
2079: int bus=-1;
2080: int i,c;
2081: int len;
2082:
2083: // if dev_name null, or string length zero
2084: if (!name || !(len = strlen(name)))
2085: return 0;
2086:
2087: // check ATA bus
2088: char * * atanames = 0; int numata = 0;
2089: numata = get_dev_names_ata(&atanames);
2090: if (numata > 0) {
2091: // check ATA/ATAPI devices
2092: for (i = 0; i < numata; i++) {
2093: if(!strcmp(atanames[i],name)) {
2094: for (c = i; c < numata; c++) free(atanames[c]);
2095: free(atanames);
2096: return new freebsd_ata_device(this, name, "");
2097: }
2098: else free(atanames[i]);
2099: }
2100: if(numata) free(atanames);
2101: }
2102: else {
2103: if (numata < 0)
2104: pout("Unable to get ATA device list\n");
2105: }
2106:
2107: // check CAM
2108: std::vector<std::string> scsinames;
2109: if (!get_dev_names_cam(scsinames, true))
2110: pout("Unable to get CAM device list\n");
2111: else if (!scsinames.empty()) {
2112: // check all devices on CAM bus
2113: for (i = 0; i < (int)scsinames.size(); i++) {
2114: if(strcmp(scsinames[i].c_str(), name)==0)
2115: { // our disk device is CAM
2116: if ((cam_dev = cam_open_device(name, O_RDWR)) == NULL) {
2117: // open failure
2118: set_err(errno);
2119: return 0;
2120: }
2121:
2122: // zero the payload
2123: bzero(&(&ccb.ccb_h)[1], PATHINQ_SETTINGS_SIZE);
2124: ccb.ccb_h.func_code = XPT_PATH_INQ; // send PATH_INQ to the device
2125: if (ioctl(cam_dev->fd, CAMIOCOMMAND, &ccb) == -1) {
2126: warn("Get Transfer Settings CCB failed\n"
2127: "%s", strerror(errno));
2128: cam_close_device(cam_dev);
2129: return 0;
2130: }
2131: // now check if we are working with USB device, see umass.c
2132: if(strcmp(ccb.cpi.dev_name,"umass-sim") == 0) { // USB device found
2133: usbdevlist(bus,vendor_id, product_id, version);
2134: int bus=ccb.cpi.unit_number; // unit_number will match umass number
2135: cam_close_device(cam_dev);
2136: if(usbdevlist(bus,vendor_id, product_id, version)){
2137: const char * usbtype = get_usb_dev_type_by_id(vendor_id, product_id, version);
2138: if (usbtype)
2139: return get_sat_device(usbtype, new freebsd_scsi_device(this, name, ""));
2140: }
2141: return 0;
2142: }
2143: #if FREEBSDVER > 800100
2144: // check if we have ATA device connected to CAM (ada)
2145: if(ccb.cpi.protocol == PROTO_ATA){
2146: cam_close_device(cam_dev);
2147: return new freebsd_atacam_device(this, name, "");
2148: }
2149: #endif
2150: // close cam device, we don`t need it anymore
2151: cam_close_device(cam_dev);
2152: // handle as usual scsi
2153: return new freebsd_scsi_device(this, name, "");
2154: }
2155: }
2156: }
2157: // device is LSI raid supported by mfi driver
2158: if(!strncmp("/dev/mfid", name, strlen("/dev/mfid")))
2159: set_err(EINVAL, "To monitor disks on LSI RAID load mfip.ko module and run 'smartctl -a /dev/passX' to show SMART information");
2160: // device type unknown
2161: return 0;
2162: }
2163:
2164:
2165: smart_device * freebsd_smart_interface::get_custom_smart_device(const char * name, const char * type)
2166: {
2167: // 3Ware ?
2168: static const char * fbsd_dev_twe_ctrl = "/dev/twe";
2169: static const char * fbsd_dev_twa_ctrl = "/dev/twa";
2170: int disknum = -1, n1 = -1, n2 = -1, contr = -1;
2171:
2172: if (sscanf(type, "3ware,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) {
2173: if (n2 != (int)strlen(type)) {
2174: set_err(EINVAL, "Option -d 3ware,N requires N to be a non-negative integer");
2175: return 0;
2176: }
2177: if (!(0 <= disknum && disknum <= 127)) {
2178: set_err(EINVAL, "Option -d 3ware,N (N=%d) must have 0 <= N <= 127", disknum);
2179: return 0;
2180: }
2181:
2182: // guess 3ware device type based on device name
2183: if (!strncmp(fbsd_dev_twa_ctrl, name, strlen(fbsd_dev_twa_ctrl))){
2184: contr=CONTROLLER_3WARE_9000_CHAR;
2185: }
2186: if (!strncmp(fbsd_dev_twe_ctrl, name, strlen(fbsd_dev_twe_ctrl))){
2187: contr=CONTROLLER_3WARE_678K_CHAR;
2188: }
2189:
2190: if(contr == -1){
2191: set_err(EINVAL, "3ware controller type unknown, use %sX or %sX devices",
2192: fbsd_dev_twe_ctrl, fbsd_dev_twa_ctrl);
2193: return 0;
2194: }
2195: return new freebsd_escalade_device(this, name, contr, disknum);
2196: }
2197:
2198: // Highpoint ?
2199: int controller = -1, channel = -1; disknum = 1;
2200: n1 = n2 = -1; int n3 = -1;
2201: if (sscanf(type, "hpt,%n%d/%d%n/%d%n", &n1, &controller, &channel, &n2, &disknum, &n3) >= 2 || n1 == 4) {
2202: int len = strlen(type);
2203: if (!(n2 == len || n3 == len)) {
2204: set_err(EINVAL, "Option '-d hpt,L/M/N' supports 2-3 items");
2205: return 0;
2206: }
2207: if (!(1 <= controller && controller <= 8)) {
2208: set_err(EINVAL, "Option '-d hpt,L/M/N' invalid controller id L supplied");
2209: return 0;
2210: }
2211: if (!(1 <= channel && channel <= 16)) {
2212: set_err(EINVAL, "Option '-d hpt,L/M/N' invalid channel number M supplied");
2213: return 0;
2214: }
2215: if (!(1 <= disknum && disknum <= 15)) {
2216: set_err(EINVAL, "Option '-d hpt,L/M/N' invalid pmport number N supplied");
2217: return 0;
2218: }
2219: return new freebsd_highpoint_device(this, name, controller, channel, disknum);
2220: }
2221:
2222: // CCISS ?
2223: disknum = n1 = n2 = -1;
2224: if (sscanf(type, "cciss,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) {
2225: if (n2 != (int)strlen(type)) {
2226: set_err(EINVAL, "Option -d cciss,N requires N to be a non-negative integer");
2227: return 0;
2228: }
2229: if (!(0 <= disknum && disknum <= 127)) {
2230: set_err(EINVAL, "Option -d cciss,N (N=%d) must have 0 <= N <= 127", disknum);
2231: return 0;
2232: }
2233: return new freebsd_cciss_device(this, name, disknum);
2234: }
2235: #if FREEBSDVER > 800100
2236: // adaX devices ?
2237: if(!strcmp(type,"atacam"))
2238: return new freebsd_atacam_device(this, name, "");
2239: #endif
2240: // Areca?
2241: disknum = n1 = n2 = -1;
2242: if (sscanf(type, "areca,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) {
2243: if (n2 != (int)strlen(type)) {
2244: set_err(EINVAL, "Option -d areca,N requires N to be a non-negative integer");
2245: return 0;
2246: }
2247: if (!(1 <= disknum && disknum <= 24)) {
2248: set_err(EINVAL, "Option -d areca,N (N=%d) must have 1 <= N <= 24", disknum);
2249: return 0;
2250: }
2251: return new freebsd_areca_device(this, name, disknum);
2252: }
2253:
2254: return 0;
2255: }
2256:
2257: std::string freebsd_smart_interface::get_valid_custom_dev_types_str()
2258: {
2259: return "3ware,N, hpt,L/M/N, cciss,N, areca,N"
2260: #if FREEBSDVER > 800100
2261: ", atacam"
2262: #endif
2263: ;
2264: }
2265:
2266: } // namespace
2267:
2268: /////////////////////////////////////////////////////////////////////////////
2269: /// Initialize platform interface and register with smi()
2270:
2271: void smart_interface::init()
2272: {
2273: static os_freebsd::freebsd_smart_interface the_interface;
2274: smart_interface::set(&the_interface);
2275: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>