4 * Home page of code is: http://www.smartmontools.org
6 * Copyright (C) 2012 Hank Wu <hank@areca.com.tw>
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)
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/>.
21 #include "dev_interface.h"
22 #include "dev_areca.h"
24 const char * dev_areca_cpp_cvsid
= "$Id: dev_areca.cpp 4582 2017-11-03 20:54:56Z chrfranke $"
32 #if 0 // For debugging areca code
33 static void dumpdata(unsigned char *block
, int len
)
35 int ln
= (len
/ 16) + 1; // total line#
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");
43 for ( int l
= 0; l
< ln
&& len
; l
++ )
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
48 for ( pos
= 0; pos
< 16 && len
; pos
++, len
-- )
56 for ( int loop
= pos
; loop
< 16; loop
++ )
63 for ( int loop
= 0; loop
< pos
; loop
++ )
66 if ( c
>= 0x20 && c
<= 0x7F )
77 printf("=====================================================================\n");
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"),
86 set_info().info_name
= strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name
, disknum
, encnum
);
89 generic_areca_device::~generic_areca_device() throw()
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
106 // data: location to write output data, if needed (512 bytes).
107 // Note: not all commands use all arguments.
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
)
117 if (arcmsr_cmd
>= ARCMSR_CMD_TOTAL
)
120 static const unsigned int cmds
[ARCMSR_CMD_TOTAL
] =
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
131 struct scsi_cmnd_io iop
;
132 int dir
= DXFER_TO_DEVICE
;
137 unsigned char *areca_return_packet
;
140 unsigned char return_buff
[2048]={0};
141 unsigned char *ptr
= &return_buff
[0];
143 memset((unsigned char *)&sBuf
, 0, sizeof(sBuf
));
144 memset(&iop
, 0, sizeof(iop
));
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
];
151 switch ( arcmsr_cmd
)
153 // command for writing data to driver
154 case ARCMSR_WRITE_WQBUFFER
:
155 if ( data
&& data_len
)
157 sBuf
.srbioctl
.Length
= data_len
;
158 memcpy((unsigned char *)sBuf
.ioctldatabuffer
, (unsigned char *)data
, data_len
);
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;
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
;
174 // unknown arcmsr commands
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;
186 iop
.dxfer_len
= sizeof(sBuf
);
187 iop
.dxferp
= (unsigned char *)&sBuf
;
189 iop
.cmnd_len
= sizeof(cdb
);
191 iop
.max_sense_len
= sizeof(sense
);
192 iop
.timeout
= SCSI_TIMEOUT_DEFAULT
;
196 ioctlreturn
= arcmsr_do_scsi_io(&iop
);
197 if(ioctlreturn
|| iop
.scsi_status
)
202 if ( arcmsr_cmd
!= ARCMSR_READ_RQBUFFER
)
204 // if succeeded, just returns the length of outgoing data
208 if ( sBuf
.srbioctl
.Length
)
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 )
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 )
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;
228 if ( total
>= 7 && total
>= expected
)
230 //printf("total bytes received = %d, expected length = %d\n", total, expected);
232 // ------ Okay! we received enough --------
238 // Deal with the different error cases
239 if ( arcmsr_cmd
== ARCMSR_RETURN_CODE_3F
)
241 // Silence the ARCMSR_IOCTL_RETURN_CODE_3F's error, no pout(...)
247 pout("do_scsi_cmnd_io with write buffer failed code = %x\n", ioctlreturn
);
251 if ( iop
.scsi_status
)
253 pout("io_hdr.scsi_status with write buffer failed code = %x\n", iop
.scsi_status
);
259 memcpy(data
, return_buff
, total
);
265 bool generic_areca_device::arcmsr_probe()
272 if(arcmsr_command_handler(ARCMSR_RETURN_CODE_3F
, NULL
, 0) != 0)
279 int generic_areca_device::arcmsr_ui_handler(unsigned char *areca_packet
, int areca_packet_len
, unsigned char *result
)
282 unsigned char return_buff
[2048];
283 unsigned char cs
= 0;
286 // ----- ADD CHECKSUM -----
287 cs_pos
= areca_packet_len
- 1;
288 for(int i
= 3; i
< cs_pos
; i
++)
290 areca_packet
[cs_pos
] += areca_packet
[i
];
297 expected
= arcmsr_command_handler(ARCMSR_CLEAR_RQBUFFER
, NULL
, 0);
301 arcmsr_command_handler(ARCMSR_CLEAR_WQBUFFER
, NULL
, 0);
302 expected
= arcmsr_command_handler(ARCMSR_WRITE_WQBUFFER
, areca_packet
, areca_packet_len
);
305 expected
= arcmsr_command_handler(ARCMSR_READ_RQBUFFER
, return_buff
, sizeof(return_buff
));
308 if ( expected
< 3 + 1 ) // Prefix + Checksum
318 // ----- VERIFY THE CHECKSUM -----
320 for ( int loop
= 3; loop
< expected
- 1; loop
++ )
322 cs
+= return_buff
[loop
];
325 if ( return_buff
[expected
- 1] != cs
)
330 memcpy(result
, return_buff
, expected
);
335 int generic_areca_device::arcmsr_get_controller_type()
338 unsigned char return_buff
[2048];
339 unsigned char areca_packet
[] = {0x5E, 0x01, 0x61, 0x01, 0x00, 0x23, 0x00};
341 memset(return_buff
, 0, sizeof(return_buff
));
342 expected
= arcmsr_ui_handler(areca_packet
, sizeof(areca_packet
), return_buff
);
348 return return_buff
[0xc2];
351 int generic_areca_device::arcmsr_get_dev_type()
354 unsigned char return_buff
[2048];
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};
361 memset(return_buff
, 0, sizeof(return_buff
));
362 expected
= arcmsr_ui_handler(areca_packet
, sizeof(areca_packet
), return_buff
);
368 ctlr_type
= arcmsr_get_controller_type();
375 if( ctlr_type
== 0x02/* SATA Controllers */ ||
376 (ctlr_type
== 0x03 /* SAS Controllers */ && return_buff
[0x52] & 0x01 /* SATA devices behind SAS Controller */) )
386 bool generic_areca_device::arcmsr_ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
388 // ATA input registers
389 typedef struct _ATA_INPUT_REGISTERS
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
;
402 // ATA output registers
403 // Note: The output registers is re-sorted for areca internal use only
404 typedef struct _ATA_OUTPUT_REGISTERS
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
;
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])
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 // +--------------------------------------------------------------------------------+
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])
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];
444 sATA_INPUT_REGISTERS
*ata_cmd
;
448 memset(sInq
, 0, sizeof(sInq
));
449 scsiStdInquiry(fd
, (unsigned char *)sInq
, (int)sizeof(sInq
));
450 dumpdata((unsigned char *)sInq
, sizeof(sInq
));
452 memset(areca_packet
, 0, areca_packet_len
);
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
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];
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
;
477 bool readdata
= false;
478 if (in
.direction
== ata_cmd_in::data_in
) {
480 // the command will read data
481 areca_packet
[6] = 0x13;
483 else if ( in
.direction
== ata_cmd_in::no_data
)
485 // the commands will return no data
486 areca_packet
[6] = 0x15;
488 else if (in
.direction
== ata_cmd_in::data_out
)
490 // the commands will write data
491 memcpy(ata_cmd
->data
, in
.buffer
, in
.size
);
492 areca_packet
[6] = 0x14;
495 // COMMAND NOT SUPPORTED VIA ARECA IOCTL INTERFACE
496 return set_err(ENOSYS
);
499 areca_packet
[11] = get_disknum() - 1; // disk#
500 areca_packet
[19] = get_encnum() - 1; // enc#
502 // ----- BEGIN TO SEND TO ARECA DRIVER ------
503 expected
= arcmsr_ui_handler(areca_packet
, areca_packet_len
, return_buff
);
509 sATA_OUTPUT_REGISTERS
*ata_out
= (sATA_OUTPUT_REGISTERS
*)&return_buff
[5] ;
510 if ( ata_out
->status
)
512 if ( in
.in_regs
.command
== ATA_IDENTIFY_DEVICE
513 && !nonempty((unsigned char *)in
.buffer
, in
.size
))
515 return set_err(ENODEV
, "No drive on port %d", get_disknum());
522 memcpy(in
.buffer
, &return_buff
[7], in
.size
);
525 // Return register values
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
;
538 bool generic_areca_device::arcmsr_scsi_pass_through(struct scsi_cmnd_io
* iop
)
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])
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 // +--------------------------------------------------------------------------------+
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])
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];
570 if (iop
->cmnd_len
> 16) {
571 set_err(EINVAL
, "cmnd_len too large");
575 memset(areca_packet
, 0, areca_packet_len
);
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;
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
)
596 areca_packet
[13] |= 0x01;
597 memcpy(&areca_packet
[67], iop
->dxferp
, iop
->dxfer_len
);
599 else if (iop
->dxfer_dir
== DXFER_FROM_DEVICE
)
602 else if( iop
->dxfer_dir
== DXFER_NONE
)
606 // COMMAND NOT SUPPORTED VIA ARECA IOCTL INTERFACE
607 return set_err(ENOSYS
);
610 areca_packet
[11] = get_disknum() - 1; // disk#
611 areca_packet
[19] = get_encnum() - 1; // enc#
613 // ----- BEGIN TO SEND TO ARECA DRIVER ------
614 expected
= arcmsr_ui_handler(areca_packet
, areca_packet_len
, return_buff
);
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);
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;
624 if (iop
->dxfer_dir
== DXFER_FROM_DEVICE
)
626 memset(iop
->dxferp
, 0, iop
->dxfer_len
); // need?
627 memcpy(iop
->dxferp
, &return_buff
[15], in_data_len
);
630 if(scsi_status
== 0xE1 /* Underrun, actual data length < requested data length */)
632 // don't care, just ignore
636 if(scsi_status
!= 0x00 && scsi_status
!= SCSI_STATUS_CHECK_CONDITION
)
641 if(scsi_status
== SCSI_STATUS_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];
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")
660 set_disknum(disknum
);
661 set_info().info_name
= strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name
, disknum
, encnum
);
664 areca_ata_device::~areca_ata_device() throw()
669 bool areca_ata_device::ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
)
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
,
680 return arcmsr_ata_pass_through(in
, out
);
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")
688 set_disknum(disknum
);
689 set_info().info_name
= strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name
, disknum
, encnum
);
692 areca_scsi_device::~areca_scsi_device() throw()
697 bool areca_scsi_device::scsi_pass_through(struct scsi_cmnd_io
* iop
)
699 return arcmsr_scsi_pass_through(iop
);