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