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