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