smartmontools  SVN Rev 4057
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: 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 
24 const char * dev_areca_cpp_cvsid = "$Id: dev_areca.cpp 3872 2014-02-03 21:07:51Z chrfranke $"
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 
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
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
163  cdb[0] = 0x3B; //SCSI_WRITE_BUF command;
164  break;
165  // command for reading data from driver
167  // command for identifying driver
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);
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 
265 {
266  if(!is_open())
267  {
268  open();
269  }
270 
272  {
273  return false;
274  }
275  return true;
276 }
277 
278 int 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 
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 
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 
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  {
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 
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);
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);
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
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 /////////////////////////////////////////////////////////////
655 areca_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 
664 {
665 
666 }
667 
669 {
670  if (!ata_cmd_is_supported(in,
673  //ata_device::supports_multi_sector | // TODO
675  "Areca")
676  )
677  return false;
678 
679  return arcmsr_ata_pass_through(in, out);
680 }
681 
682 /////////////////////////////////////////////////////////////
683 areca_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 
692 {
693 
694 }
695 
697 {
698  return arcmsr_scsi_pass_through(iop);
699 }
700 
701 
702 
703 
virtual int arcmsr_ui_handler(unsigned char *areca_packet, int areca_packet_len, unsigned char *result)
Definition: dev_areca.cpp:278
virtual bool arcmsr_scsi_pass_through(scsi_cmnd_io *iop)
Definition: dev_areca.cpp:537
#define SCSI_STATUS_CHECK_CONDITION
Definition: scsicmds.h:260
UINT8 * sensep
Definition: scsicmds.h:124
void set_disknum(int disknum)
Definition: dev_areca.h:125
ata_register error
ata_register lba_mid
#define DXFER_FROM_DEVICE
Definition: scsicmds.h:113
virtual bool open()=0
Open device, return false on error.
#define DEV_ARECA_H_CVSID
Definition: dev_areca.h:21
virtual int arcmsr_command_handler(unsigned long arcmsr_cmd, unsigned char *data, int data_len)
Definition: dev_areca.cpp:115
unsigned int HeaderLength
Definition: dev_areca.h:83
unsigned char ioctldatabuffer[1032]
Definition: dev_areca.h:94
ata_register sector_count
unsigned timeout
Definition: scsicmds.h:127
ATA Input registers (for 28-bit commands)
device_info & set_info()
R/W access to device info struct.
virtual int arcmsr_get_dev_type()
Definition: dev_areca.cpp:350
void * buffer
Pointer to data buffer.
size_t resp_sense_len
Definition: scsicmds.h:128
u8 scsi_status
Definition: megaraid.h:83
#define ATA_IDENTIFY_DEVICE
Definition: atacmds.h:72
virtual bool arcmsr_lock()=0
ata_register lba_mid
bool nonempty(const void *data, int size)
Definition: utility.cpp:695
virtual bool arcmsr_unlock()=0
bool ata_cmd_is_supported(const ata_cmd_in &in, unsigned flags, const char *type=0)
Check command input parameters.
ata_in_regs_48bit in_regs
Input registers.
UINT8 * dxferp
Definition: scsicmds.h:122
ata_out_regs_48bit out_regs
Output registers.
unsigned char Signature[8]
Definition: dev_areca.h:84
UINT8 * cmnd
Definition: scsicmds.h:118
ptr_t data
Definition: megaraid.h:94
enum ata_cmd_in::@27 direction
I/O direction.
#define ARECA_SIG_STR
Definition: dev_areca.h:37
virtual bool scsi_pass_through(scsi_cmnd_io *iop)
SCSI pass through.
Definition: dev_areca.cpp:696
virtual bool is_open() const =0
Return true if device is open.
u8 cdb[16]
Definition: megaraid.h:100
The platform interface abstraction.
virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io *iop)=0
void pout(const char *fmt,...)
Definition: smartctl.cpp:1091
size_t max_sense_len
Definition: scsicmds.h:126
ata_register status
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out)
ATA pass through.
Definition: dev_areca.cpp:668
int dxfer_dir
Definition: scsicmds.h:120
const char * dev_areca_cpp_cvsid
Definition: dev_areca.cpp:24
void set_encnum(int encnum)
Definition: dev_areca.h:128
unsigned size
Size of buffer.
ata_register lba_low
unsigned int ControlCode
Definition: dev_areca.h:86
ata_register features
#define DXFER_NONE
Definition: scsicmds.h:112
#define DXFER_TO_DEVICE
Definition: scsicmds.h:114
virtual bool arcmsr_probe()
Definition: dev_areca.cpp:264
ata_register device
Base class for all devices.
Definition: dev_interface.h:38
ata_register lba_high
size_t cmnd_len
Definition: scsicmds.h:119
ata_register sector_count
sARCMSR_IO_HDR srbioctl
Definition: dev_areca.h:93
unsigned int Length
Definition: dev_areca.h:88
ata_register command
UINT8 scsi_status
Definition: scsicmds.h:129
ATA pass through input parameters.
int scsiStdInquiry(scsi_device *device, UINT8 *pBuf, int bufLen)
Definition: scsicmds.cpp:780
std::string strprintf(const char *fmt,...)
Definition: utility.cpp:787
ata_register lba_low
unsigned int Timeout
Definition: dev_areca.h:85
ata_register lba_high
size_t dxfer_len
Definition: scsicmds.h:123
virtual int arcmsr_get_controller_type()
Definition: dev_areca.cpp:334
virtual bool arcmsr_ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out)
Definition: dev_areca.cpp:385
std::string info_name
Informal name.
Definition: dev_interface.h:52
struct _ARCMSR_IO_HDR sARCMSR_IO_HDR
unsigned char UINT8
Definition: scsicmds.h:107
bool set_err(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
ATA Output registers (for 28-bit commands)
ATA pass through output parameters.
#define SCSI_TIMEOUT_DEFAULT
Definition: scsicmds.h:309