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