Annotation of embedaddon/smartmontools/dev_areca.cpp, revision 1.1.1.2
1.1 misho 1: /*
2: * dev_areca.cpp
3: *
4: * Home page of code is: http://smartmontools.sourceforge.net
5: *
6: * Copyright (C) 2012 Hank Wu <hank@areca.com.tw>
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, see <http://www.gnu.org/licenses/>.
15: *
16: */
17:
18: #include "config.h"
19: #include "int64.h"
20:
21: #include "dev_interface.h"
22: #include "dev_areca.h"
23:
1.1.1.2 ! misho 24: const char * dev_areca_cpp_cvsid = "$Id: dev_areca.cpp 3835 2013-07-20 18:37:19Z chrfranke $"
1.1 misho 25: DEV_ARECA_H_CVSID;
26:
27: #include "atacmds.h"
28: #include "scsicmds.h"
29:
30: #include <errno.h>
31:
32: #if 0 // For debugging areca code
33: static void dumpdata(unsigned char *block, int len)
34: {
35: int ln = (len / 16) + 1; // total line#
36: unsigned char c;
37: int pos = 0;
38:
39: printf(" Address = %p, Length = (0x%x)%d\n", block, len, len);
40: printf(" 0 1 2 3 4 5 6 7 8 9 A B C D E F ASCII \n");
41: printf("=====================================================================\n");
42:
43: for ( int l = 0; l < ln && len; l++ )
44: {
45: // printf the line# and the HEX data
46: // if a line data length < 16 then append the space to the tail of line to reach 16 chars
47: printf("%02X | ", l);
48: for ( pos = 0; pos < 16 && len; pos++, len-- )
49: {
50: c = block[l*16+pos];
51: printf("%02X ", c);
52: }
53:
54: if ( pos < 16 )
55: {
56: for ( int loop = pos; loop < 16; loop++ )
57: {
58: printf(" ");
59: }
60: }
61:
62: // print ASCII char
63: for ( int loop = 0; loop < pos; loop++ )
64: {
65: c = block[l*16+loop];
66: if ( c >= 0x20 && c <= 0x7F )
67: {
68: printf("%c", c);
69: }
70: else
71: {
72: printf(".");
73: }
74: }
75: printf("\n");
76: }
77: printf("=====================================================================\n");
78: }
79: #endif
80:
81: generic_areca_device::generic_areca_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
82: : smart_device(intf, dev_name, "areca", "areca"),
83: m_disknum(disknum),
84: m_encnum(encnum)
85: {
86: set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
87: }
88:
89: generic_areca_device::~generic_areca_device() throw()
90: {
91:
92: }
93:
94: // PURPOSE
95: // This is an interface routine meant to isolate the OS dependent
96: // parts of the code, and to provide a debugging interface. Each
97: // different port and OS needs to provide it's own interface. This
98: // is the Windows interface to the Areca "arcmsr" driver. It allows ATA
99: // commands to be passed through the SCSI driver.
100: // DETAILED DESCRIPTION OF ARGUMENTS
101: // fd: is the file descriptor provided by open()
102: // disknum is the disk number (0 to 127) in the RAID array
103: // command: defines the different operations.
104: // select: additional input data if needed (which log, which type of
105: // self-test).
106: // data: location to write output data, if needed (512 bytes).
107: // Note: not all commands use all arguments.
108: // RETURN VALUES
109: // -1 if the command failed
110: // 0 if the command succeeded,
111: // STATUS_CHECK routine:
112: // -1 if the command failed
113: // 0 if the command succeeded and disk SMART status is "OK"
114: // 1 if the command succeeded and disk SMART status is "FAILING"
115: int generic_areca_device::arcmsr_command_handler(unsigned long arcmsr_cmd, unsigned char *data, int data_len)
116: {
117: unsigned int cmds[] =
118: {
119: ARCMSR_IOCTL_READ_RQBUFFER,
120: ARCMSR_IOCTL_WRITE_WQBUFFER,
121: ARCMSR_IOCTL_CLEAR_RQBUFFER,
122: ARCMSR_IOCTL_CLEAR_WQBUFFER,
123: ARCMSR_IOCTL_RETURN_CODE_3F
124: };
125:
126: int ioctlreturn = 0;
127: sSRB_BUFFER sBuf;
128: struct scsi_cmnd_io iop;
129: int dir = DXFER_TO_DEVICE;
130:
131: UINT8 cdb[10]={0};
132: UINT8 sense[32]={0};
133:
134: unsigned char *areca_return_packet;
135: int total = 0;
136: int expected = -1;
137: unsigned char return_buff[2048]={0};
138: unsigned char *ptr = &return_buff[0];
139:
140: memset((unsigned char *)&sBuf, 0, sizeof(sBuf));
141: memset(&iop, 0, sizeof(iop));
142:
143: sBuf.srbioctl.HeaderLength = sizeof(sARCMSR_IO_HDR);
144: memcpy(sBuf.srbioctl.Signature, ARECA_SIG_STR, strlen(ARECA_SIG_STR));
145: sBuf.srbioctl.Timeout = 10000;
146: sBuf.srbioctl.ControlCode = cmds[arcmsr_cmd];
147:
148: if(arcmsr_cmd >= ARCMSR_CMD_TOTAL)
149: {
150: return -1;
151: }
152:
153: switch ( arcmsr_cmd )
154: {
155: // command for writing data to driver
156: case ARCMSR_WRITE_WQBUFFER:
157: if ( data && data_len )
158: {
159: sBuf.srbioctl.Length = data_len;
160: memcpy((unsigned char *)sBuf.ioctldatabuffer, (unsigned char *)data, data_len);
161: }
162: // commands for clearing related buffer of driver
163: case ARCMSR_CLEAR_RQBUFFER:
164: case ARCMSR_CLEAR_WQBUFFER:
165: cdb[0] = 0x3B; //SCSI_WRITE_BUF command;
166: break;
167: // command for reading data from driver
168: case ARCMSR_READ_RQBUFFER:
169: // command for identifying driver
170: case ARCMSR_RETURN_CODE_3F:
171: cdb[0] = 0x3C; //SCSI_READ_BUF command;
172: dir = DXFER_FROM_DEVICE;
173: break;
174: default:
175: // unknown arcmsr commands
176: return -1;
177: }
178:
179: cdb[1] = 0x01;
180: cdb[2] = 0xf0;
181: cdb[5] = cmds[arcmsr_cmd] >> 24;
182: cdb[6] = cmds[arcmsr_cmd] >> 16;
183: cdb[7] = cmds[arcmsr_cmd] >> 8;
184: cdb[8] = cmds[arcmsr_cmd] & 0x0F;
185:
186: iop.dxfer_dir = dir;
187: iop.dxfer_len = sizeof(sBuf);
188: iop.dxferp = (unsigned char *)&sBuf;
189: iop.cmnd = cdb;
190: iop.cmnd_len = sizeof(cdb);
191: iop.sensep = sense;
192: iop.max_sense_len = sizeof(sense);
193: iop.timeout = SCSI_TIMEOUT_DEFAULT;
194:
195: while ( 1 )
196: {
197: ioctlreturn = arcmsr_do_scsi_io(&iop);
198: if(ioctlreturn || iop.scsi_status)
199: {
200: break;
201: }
202:
203: if ( arcmsr_cmd != ARCMSR_READ_RQBUFFER )
204: {
205: // if succeeded, just returns the length of outgoing data
206: return data_len;
207: }
208:
209: if ( sBuf.srbioctl.Length )
210: {
211: memcpy(ptr, &sBuf.ioctldatabuffer[0], sBuf.srbioctl.Length);
212: ptr += sBuf.srbioctl.Length;
213: total += sBuf.srbioctl.Length;
214: // the returned bytes enough to compute payload length ?
215: if ( expected < 0 && total >= 5 )
216: {
217: areca_return_packet = (unsigned char *)&return_buff[0];
218: if ( areca_return_packet[0] == 0x5E &&
219: areca_return_packet[1] == 0x01 &&
220: areca_return_packet[2] == 0x61 )
221: {
222: // valid header, let's compute the returned payload length,
223: // we expected the total length is
224: // payload + 3 bytes header + 2 bytes length + 1 byte checksum
225: expected = areca_return_packet[4] * 256 + areca_return_packet[3] + 6;
226: }
227: }
228:
229: if ( total >= 7 && total >= expected )
230: {
231: //printf("total bytes received = %d, expected length = %d\n", total, expected);
232:
233: // ------ Okay! we received enough --------
234: break;
235: }
236: }
237: }
238:
239: // Deal with the different error cases
240: if ( arcmsr_cmd == ARCMSR_RETURN_CODE_3F )
241: {
242: // Silence the ARCMSR_IOCTL_RETURN_CODE_3F's error, no pout(...)
243: return -4;
244: }
245:
246: if ( ioctlreturn )
247: {
248: pout("do_scsi_cmnd_io with write buffer failed code = %x\n", ioctlreturn);
249: return -2;
250: }
251:
252: if ( iop.scsi_status )
253: {
254: pout("io_hdr.scsi_status with write buffer failed code = %x\n", iop.scsi_status);
255: return -3;
256: }
257:
258: if ( data )
259: {
260: memcpy(data, return_buff, total);
261: }
262:
263: return total;
264: }
265:
266: bool generic_areca_device::arcmsr_probe()
267: {
268: if(!is_open())
269: {
270: open();
271: }
272:
273: if(arcmsr_command_handler(ARCMSR_RETURN_CODE_3F, NULL, 0) != 0)
274: {
275: return false;
276: }
277: return true;
278: }
279:
280: int generic_areca_device::arcmsr_ui_handler(unsigned char *areca_packet, int areca_packet_len, unsigned char *result)
281: {
282: int expected = 0;
283: unsigned char return_buff[2048];
284: unsigned char cs = 0;
285: int cs_pos = 0;
286:
287: // ----- ADD CHECKSUM -----
288: cs_pos = areca_packet_len - 1;
289: for(int i = 3; i < cs_pos; i++)
290: {
291: areca_packet[cs_pos] += areca_packet[i];
292: }
293:
294: if(!arcmsr_lock())
295: {
296: return -1;
297: }
298: expected = arcmsr_command_handler(ARCMSR_CLEAR_RQBUFFER, NULL, 0);
299: if (expected==-3) {
300: return set_err(EIO);
301: }
302: expected = arcmsr_command_handler(ARCMSR_CLEAR_WQBUFFER, NULL, 0);
303: expected = arcmsr_command_handler(ARCMSR_WRITE_WQBUFFER, areca_packet, areca_packet_len);
304: if ( expected > 0 )
305: {
306: expected = arcmsr_command_handler(ARCMSR_READ_RQBUFFER, return_buff, sizeof(return_buff));
307: }
308:
309: if ( expected < 0 )
310: {
311: return -1;
312: }
313:
314: if(!arcmsr_unlock())
315: {
316: return -1;
317: }
318:
319: // ----- VERIFY THE CHECKSUM -----
320: cs = 0;
321: for ( int loop = 3; loop < expected - 1; loop++ )
322: {
323: cs += return_buff[loop];
324: }
325:
326: if ( return_buff[expected - 1] != cs )
327: {
328: return -1;
329: }
330:
331: memcpy(result, return_buff, expected);
332:
333: return expected;
334: }
335:
336: int generic_areca_device::arcmsr_get_controller_type()
337: {
338: int expected = 0;
339: unsigned char return_buff[2048];
340: unsigned char areca_packet[] = {0x5E, 0x01, 0x61, 0x01, 0x00, 0x23, 0x00};
341:
342: memset(return_buff, 0, sizeof(return_buff));
343: expected = arcmsr_ui_handler(areca_packet, sizeof(areca_packet), return_buff);
344: if ( expected < 0 )
345: {
346: return -1;
347: }
348:
349: return return_buff[0xc2];
350: }
351:
352: int generic_areca_device::arcmsr_get_dev_type()
353: {
354: int expected = 0;
355: unsigned char return_buff[2048];
356: int ctlr_type = -1;
357: int encnum = get_encnum();
358: int disknum = get_disknum();
1.1.1.2 ! misho 359: unsigned char areca_packet[] = {0x5E, 0x01, 0x61, 0x03, 0x00, 0x22,
! 360: (unsigned char)(disknum - 1), (unsigned char)(encnum - 1), 0x00};
1.1 misho 361:
362: memset(return_buff, 0, sizeof(return_buff));
363: expected = arcmsr_ui_handler(areca_packet, sizeof(areca_packet), return_buff);
364: if ( expected < 0 )
365: {
366: return -1;
367: }
368:
369: ctlr_type = arcmsr_get_controller_type();
370:
371: if( ctlr_type < 0 )
372: {
373: return ctlr_type;
374: }
375:
376: if( ctlr_type == 0x02/* SATA Controllers */ ||
377: (ctlr_type == 0x03 /* SAS Controllers */ && return_buff[0x52] & 0x01 /* SATA devices behind SAS Controller */) )
378: {
379: // SATA device
380: return 1;
381: }
382:
383: // SAS device
384: return 0;
385: }
386:
387: bool generic_areca_device::arcmsr_ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
388: {
389: // ATA input registers
390: typedef struct _ATA_INPUT_REGISTERS
391: {
392: unsigned char features;
393: unsigned char sector_count;
394: unsigned char sector_number;
395: unsigned char cylinder_low;
396: unsigned char cylinder_high;
397: unsigned char device_head;
398: unsigned char command;
399: unsigned char reserved[8];
400: unsigned char data[512]; // [in/out] buffer for outgoing/incoming data
401: } sATA_INPUT_REGISTERS;
402:
403: // ATA output registers
404: // Note: The output registers is re-sorted for areca internal use only
405: typedef struct _ATA_OUTPUT_REGISTERS
406: {
407: unsigned char error;
408: unsigned char status;
409: unsigned char sector_count;
410: unsigned char sector_number;
411: unsigned char cylinder_low;
412: unsigned char cylinder_high;
413: } sATA_OUTPUT_REGISTERS;
414:
415: // Areca packet format for outgoing:
416: // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
417: // B[3~4] : 2 bytes command length + variant data length, little endian
418: // B[5] : 1 bytes areca defined command code, ATA passthrough command code is 0x1c
419: // B[6~last-1] : variant bytes payload data
420: // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
421: //
422: //
423: // header 3 bytes length 2 bytes cmd 1 byte payload data x bytes cs 1 byte
424: // +--------------------------------------------------------------------------------+
425: // + 0x5E 0x01 0x61 | 0x00 0x00 | 0x1c | .................... | 0x00 |
426: // +--------------------------------------------------------------------------------+
427: //
428:
429: //Areca packet format for incoming:
430: // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
431: // B[3~4] : 2 bytes payload length, little endian
432: // B[5~last-1] : variant bytes returned payload data
433: // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
434: //
435: //
436: // header 3 bytes length 2 bytes payload data x bytes cs 1 byte
437: // +-------------------------------------------------------------------+
438: // + 0x5E 0x01 0x61 | 0x00 0x00 | .................... | 0x00 |
439: // +-------------------------------------------------------------------+
440: unsigned char areca_packet[640];
441: int areca_packet_len = sizeof(areca_packet);
442: unsigned char return_buff[2048];
443: int expected = 0;
444:
445: sATA_INPUT_REGISTERS *ata_cmd;
446:
447: // For debugging
448: #if 0
449: memset(sInq, 0, sizeof(sInq));
450: scsiStdInquiry(fd, (unsigned char *)sInq, (int)sizeof(sInq));
451: dumpdata((unsigned char *)sInq, sizeof(sInq));
452: #endif
453: memset(areca_packet, 0, areca_packet_len);
454:
455: // ----- BEGIN TO SETUP HEADERS -------
456: areca_packet[0] = 0x5E;
457: areca_packet[1] = 0x01;
458: areca_packet[2] = 0x61;
459: areca_packet[3] = (unsigned char)((areca_packet_len - 6) & 0xff);
460: areca_packet[4] = (unsigned char)(((areca_packet_len - 6) >> 8) & 0xff);
461: areca_packet[5] = 0x1c; // areca defined code for ATA passthrough command
462:
463: // ----- BEGIN TO SETUP PAYLOAD DATA -----
464: memcpy(&areca_packet[7], "SmrT", 4); // areca defined password
465: ata_cmd = (sATA_INPUT_REGISTERS *)&areca_packet[12];
466:
467: // Set registers
468: {
469: const ata_in_regs & r = in.in_regs;
470: ata_cmd->features = r.features;
471: ata_cmd->sector_count = r.sector_count;
472: ata_cmd->sector_number = r.lba_low;
473: ata_cmd->cylinder_low = r.lba_mid;
474: ata_cmd->cylinder_high = r.lba_high;
475: ata_cmd->device_head = r.device;
476: ata_cmd->command = r.command;
477: }
478: bool readdata = false;
479: if (in.direction == ata_cmd_in::data_in) {
480: readdata = true;
481: // the command will read data
482: areca_packet[6] = 0x13;
483: }
484: else if ( in.direction == ata_cmd_in::no_data )
485: {
486: // the commands will return no data
487: areca_packet[6] = 0x15;
488: }
489: else if (in.direction == ata_cmd_in::data_out)
490: {
491: // the commands will write data
492: memcpy(ata_cmd->data, in.buffer, in.size);
493: areca_packet[6] = 0x14;
494: }
495: else {
496: // COMMAND NOT SUPPORTED VIA ARECA IOCTL INTERFACE
497: return set_err(ENOSYS);
498: }
499:
500: areca_packet[11] = get_disknum() - 1; // disk#
501: areca_packet[19] = get_encnum() - 1; // enc#
502:
503: // ----- BEGIN TO SEND TO ARECA DRIVER ------
504: expected = arcmsr_ui_handler(areca_packet, areca_packet_len, return_buff);
505: if ( expected < 0 )
506: {
507: return set_err(EIO);
508: }
509:
510: sATA_OUTPUT_REGISTERS *ata_out = (sATA_OUTPUT_REGISTERS *)&return_buff[5] ;
511: if ( ata_out->status )
512: {
513: if ( in.in_regs.command == ATA_IDENTIFY_DEVICE
514: && !nonempty((unsigned char *)in.buffer, in.size))
515: {
516: return set_err(ENODEV, "No drive on port %d", get_disknum());
517: }
518: }
519:
520: // returns with data
521: if (readdata)
522: {
523: memcpy(in.buffer, &return_buff[7], in.size);
524: }
525:
526: // Return register values
527: {
528: ata_out_regs & r = out.out_regs;
529: r.error = ata_out->error;
530: r.sector_count = ata_out->sector_count;
531: r.lba_low = ata_out->sector_number;
532: r.lba_mid = ata_out->cylinder_low;
533: r.lba_high = ata_out->cylinder_high;
534: r.status = ata_out->status;
535: }
536: return true;
537: }
538:
539: bool generic_areca_device::arcmsr_scsi_pass_through(struct scsi_cmnd_io * iop)
540: {
541: // Areca packet format for outgoing:
542: // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
543: // B[3~4] : 2 bytes command length + variant data length, little endian
544: // B[5] : 1 bytes areca defined command code
545: // B[6~last-1] : variant bytes payload data
546: // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
547: //
548: //
549: // header 3 bytes length 2 bytes cmd 1 byte payload data x bytes cs 1 byte
550: // +--------------------------------------------------------------------------------+
551: // + 0x5E 0x01 0x61 | 0x00 0x00 | 0x1c | .................... | 0x00 |
552: // +--------------------------------------------------------------------------------+
553: //
554:
555: //Areca packet format for incoming:
556: // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
557: // B[3~4] : 2 bytes payload length, little endian
558: // B[5~last-1] : variant bytes returned payload data
559: // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
560: //
561: //
562: // header 3 bytes length 2 bytes payload data x bytes cs 1 byte
563: // +-------------------------------------------------------------------+
564: // + 0x5E 0x01 0x61 | 0x00 0x00 | .................... | 0x00 |
565: // +-------------------------------------------------------------------+
566: unsigned char areca_packet[640];
567: int areca_packet_len = sizeof(areca_packet);
568: unsigned char return_buff[2048];
569: int expected = 0;
570:
571: if (iop->cmnd_len > 16) {
572: set_err(EINVAL, "cmnd_len too large");
573: return false;
574: }
575:
576: memset(areca_packet, 0, areca_packet_len);
577:
578: // ----- BEGIN TO SETUP HEADERS -------
579: areca_packet[0] = 0x5E;
580: areca_packet[1] = 0x01;
581: areca_packet[2] = 0x61;
582: areca_packet[3] = (unsigned char)((areca_packet_len - 6) & 0xff);
583: areca_packet[4] = (unsigned char)(((areca_packet_len - 6) >> 8) & 0xff);
584: areca_packet[5] = 0x1c;
585:
586: // ----- BEGIN TO SETUP PAYLOAD DATA -----
587: areca_packet[6] = 0x16; // scsi pass through
588: memcpy(&areca_packet[7], "SmrT", 4); // areca defined password
589: areca_packet[12] = iop->cmnd_len; // cdb length
590: memcpy( &areca_packet[35], iop->cmnd, iop->cmnd_len); // cdb
591: areca_packet[15] = (unsigned char)iop->dxfer_len; // 15(LSB) ~ 18(MSB): data length ( max=512 bytes)
592: areca_packet[16] = (unsigned char)(iop->dxfer_len >> 8);
593: areca_packet[17] = (unsigned char)(iop->dxfer_len >> 16);
594: areca_packet[18] = (unsigned char)(iop->dxfer_len >> 24);
595: if(iop->dxfer_dir == DXFER_TO_DEVICE)
596: {
597: areca_packet[13] |= 0x01;
598: memcpy(&areca_packet[67], iop->dxferp, iop->dxfer_len);
599: }
600: else if (iop->dxfer_dir == DXFER_FROM_DEVICE)
601: {
602: }
603: else if( iop->dxfer_dir == DXFER_NONE)
604: {
605: }
606: else {
607: // COMMAND NOT SUPPORTED VIA ARECA IOCTL INTERFACE
608: return set_err(ENOSYS);
609: }
610:
611: areca_packet[11] = get_disknum() - 1; // disk#
612: areca_packet[19] = get_encnum() - 1; // enc#
613:
614: // ----- BEGIN TO SEND TO ARECA DRIVER ------
615: expected = arcmsr_ui_handler(areca_packet, areca_packet_len, return_buff);
1.1.1.2 ! misho 616:
! 617: if (expected < 0)
! 618: return set_err(EIO, "arcmsr_scsi_pass_through: I/O error");
! 619: if (expected < 15) // 7 bytes if port is empty
! 620: return set_err(EIO, "arcmsr_scsi_pass_through: missing data (%d bytes, expected %d)", expected, 15);
1.1 misho 621:
622: int scsi_status = return_buff[5];
623: int in_data_len = return_buff[11] | return_buff[12] << 8 | return_buff[13] << 16 | return_buff[14] << 24;
624:
625: if (iop->dxfer_dir == DXFER_FROM_DEVICE)
626: {
627: memset(iop->dxferp, 0, iop->dxfer_len); // need?
628: memcpy(iop->dxferp, &return_buff[15], in_data_len);
629: }
630:
631: if(scsi_status == 0xE1 /* Underrun, actual data length < requested data length */)
632: {
633: // don't care, just ignore
634: scsi_status = 0x0;
635: }
636:
637: if(scsi_status != 0x00 && scsi_status != SCSI_STATUS_CHECK_CONDITION)
638: {
639: return set_err(EIO);
640: }
641:
642: if(scsi_status == SCSI_STATUS_CHECK_CONDITION)
643: {
644: // check condition
645: iop->scsi_status = SCSI_STATUS_CHECK_CONDITION;
646: iop->resp_sense_len = 4;
647: iop->sensep[0] = return_buff[7];
648: iop->sensep[1] = return_buff[8];
649: iop->sensep[2] = return_buff[9];
650: iop->sensep[3] = return_buff[10];
651: }
652:
653: return true;
654: }
655:
656: /////////////////////////////////////////////////////////////
657: areca_ata_device::areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
658: : smart_device(intf, dev_name, "areca", "areca")
659: {
660: set_encnum(encnum);
661: set_disknum(disknum);
662: set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
663: }
664:
665: areca_ata_device::~areca_ata_device() throw()
666: {
667:
668: }
669:
670: bool areca_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
671: {
672: if (!ata_cmd_is_supported(in,
673: ata_device::supports_data_out |
674: ata_device::supports_output_regs |
675: //ata_device::supports_multi_sector | // TODO
676: ata_device::supports_48bit_hi_null,
677: "Areca")
678: )
679: return false;
680:
681: return arcmsr_ata_pass_through(in, out);
682: }
683:
684: /////////////////////////////////////////////////////////////
685: areca_scsi_device::areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
686: : smart_device(intf, dev_name, "areca", "areca")
687: {
688: set_encnum(encnum);
689: set_disknum(disknum);
690: set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
691: }
692:
693: areca_scsi_device::~areca_scsi_device() throw()
694: {
695:
696: }
697:
698: bool areca_scsi_device::scsi_pass_through(struct scsi_cmnd_io * iop)
699: {
700: return arcmsr_scsi_pass_through(iop);
701: }
702:
703:
704:
705:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>