File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / smartmontools / dev_areca.cpp
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 01:17:35 2013 UTC (10 years, 11 months ago) by misho
Branches: smartmontools, elwix, MAIN
CVS tags: v6_1p0, v6_1, HEAD
6.1

    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,v 1.1.1.1 2013/07/22 01:17:35 misho Exp $"
   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
   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: 
   89: generic_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"
  115: int generic_areca_device::arcmsr_command_handler(unsigned long arcmsr_cmd, unsigned char *data, int data_len)
  116: {
  117:   unsigned int cmds[] =
  118:   {
  119:     ARCMSR_IOCTL_READ_RQBUFFER,
  120:     ARCMSR_IOCTL_WRITE_WQBUFFER,
  121:     ARCMSR_IOCTL_CLEAR_RQBUFFER,
  122:     ARCMSR_IOCTL_CLEAR_WQBUFFER,
  123:     ARCMSR_IOCTL_RETURN_CODE_3F
  124:   };
  125: 
  126:   int ioctlreturn = 0;
  127:   sSRB_BUFFER sBuf;
  128:   struct scsi_cmnd_io iop;
  129:   int dir = DXFER_TO_DEVICE;
  130: 
  131:   UINT8 cdb[10]={0};
  132:   UINT8 sense[32]={0};
  133: 
  134:   unsigned char *areca_return_packet;
  135:   int total = 0;
  136:   int expected = -1;
  137:   unsigned char return_buff[2048]={0};
  138:   unsigned char *ptr = &return_buff[0];
  139: 
  140:   memset((unsigned char *)&sBuf, 0, sizeof(sBuf));
  141:   memset(&iop, 0, sizeof(iop));
  142: 
  143:   sBuf.srbioctl.HeaderLength = sizeof(sARCMSR_IO_HDR);
  144:   memcpy(sBuf.srbioctl.Signature, ARECA_SIG_STR, strlen(ARECA_SIG_STR));
  145:   sBuf.srbioctl.Timeout = 10000;
  146:   sBuf.srbioctl.ControlCode = cmds[arcmsr_cmd];
  147: 
  148:   if(arcmsr_cmd >= ARCMSR_CMD_TOTAL)
  149:   {
  150:       return -1;
  151:   }
  152: 
  153:   switch ( arcmsr_cmd )
  154:   {
  155:   // command for writing data to driver
  156:   case ARCMSR_WRITE_WQBUFFER:
  157:     if ( data && data_len )
  158:     {
  159:       sBuf.srbioctl.Length = data_len;
  160:       memcpy((unsigned char *)sBuf.ioctldatabuffer, (unsigned char *)data, data_len);
  161:     }
  162:     // commands for clearing related buffer of driver
  163:   case ARCMSR_CLEAR_RQBUFFER:
  164:   case ARCMSR_CLEAR_WQBUFFER:
  165:     cdb[0] = 0x3B; //SCSI_WRITE_BUF command;
  166:     break;
  167:   // command for reading data from driver
  168:   case ARCMSR_READ_RQBUFFER:
  169:   // command for identifying driver
  170:   case ARCMSR_RETURN_CODE_3F:
  171:     cdb[0] = 0x3C; //SCSI_READ_BUF command;
  172:     dir = DXFER_FROM_DEVICE;
  173:     break;
  174:   default:
  175:     // unknown arcmsr commands
  176:     return -1;
  177:   }
  178: 
  179:   cdb[1] = 0x01;
  180:   cdb[2] = 0xf0;
  181:   cdb[5] = cmds[arcmsr_cmd] >> 24;
  182:   cdb[6] = cmds[arcmsr_cmd] >> 16;
  183:   cdb[7] = cmds[arcmsr_cmd] >> 8;
  184:   cdb[8] = cmds[arcmsr_cmd] & 0x0F;
  185: 
  186:   iop.dxfer_dir = dir;
  187:   iop.dxfer_len = sizeof(sBuf);
  188:   iop.dxferp = (unsigned char *)&sBuf;
  189:   iop.cmnd = cdb;
  190:   iop.cmnd_len = sizeof(cdb);
  191:   iop.sensep = sense;
  192:   iop.max_sense_len = sizeof(sense);
  193:   iop.timeout = SCSI_TIMEOUT_DEFAULT;
  194: 
  195:   while ( 1 )
  196:   {
  197:     ioctlreturn = arcmsr_do_scsi_io(&iop);
  198:     if(ioctlreturn || iop.scsi_status)
  199:     {
  200:       break;
  201:     }
  202: 
  203:     if ( arcmsr_cmd != ARCMSR_READ_RQBUFFER )
  204:     {
  205:       // if succeeded, just returns the length of outgoing data
  206:       return data_len;
  207:     }
  208: 
  209:     if ( sBuf.srbioctl.Length )
  210:     {
  211:       memcpy(ptr, &sBuf.ioctldatabuffer[0], sBuf.srbioctl.Length);
  212:       ptr += sBuf.srbioctl.Length;
  213:       total += sBuf.srbioctl.Length;
  214:       // the returned bytes enough to compute payload length ?
  215:       if ( expected < 0 && total >= 5 )
  216:       {
  217:         areca_return_packet = (unsigned char *)&return_buff[0];
  218:         if ( areca_return_packet[0] == 0x5E &&
  219:            areca_return_packet[1] == 0x01 &&
  220:            areca_return_packet[2] == 0x61 )
  221:         {
  222:           // valid header, let's compute the returned payload length,
  223:           // we expected the total length is
  224:           // payload + 3 bytes header + 2 bytes length + 1 byte checksum
  225:           expected = areca_return_packet[4] * 256 + areca_return_packet[3] + 6;
  226:         }
  227:       }
  228: 
  229:       if ( total >= 7 && total >= expected )
  230:       {
  231:         //printf("total bytes received = %d, expected length = %d\n", total, expected);
  232: 
  233:         // ------ Okay! we received enough --------
  234:         break;
  235:       }
  236:     }
  237:   }
  238: 
  239:   // Deal with the different error cases
  240:   if ( arcmsr_cmd == ARCMSR_RETURN_CODE_3F )
  241:   {
  242:     // Silence the ARCMSR_IOCTL_RETURN_CODE_3F's error, no pout(...)
  243:     return -4;
  244:   }
  245: 
  246:   if ( ioctlreturn )
  247:   {
  248:     pout("do_scsi_cmnd_io with write buffer failed code = %x\n", ioctlreturn);
  249:     return -2;
  250:   }
  251: 
  252:   if ( iop.scsi_status )
  253:   {
  254:     pout("io_hdr.scsi_status with write buffer failed code = %x\n", iop.scsi_status);
  255:     return -3;
  256:   }
  257: 
  258:   if ( data )
  259:   {
  260:     memcpy(data, return_buff, total);
  261:   }
  262: 
  263:   return total;
  264: }
  265: 
  266: bool generic_areca_device::arcmsr_probe()
  267: {
  268:   if(!is_open())
  269:   {
  270:     open();
  271:   }
  272: 
  273:   if(arcmsr_command_handler(ARCMSR_RETURN_CODE_3F, NULL, 0) != 0)
  274:   {
  275:     return false;
  276:   }
  277:   return true;
  278: }
  279: 
  280: int generic_areca_device::arcmsr_ui_handler(unsigned char *areca_packet, int areca_packet_len, unsigned char *result)
  281: {
  282:   int expected = 0;
  283:   unsigned char return_buff[2048];
  284:   unsigned char cs = 0;
  285:   int cs_pos = 0;
  286: 
  287:   // ----- ADD CHECKSUM -----
  288:   cs_pos = areca_packet_len - 1;
  289:   for(int i = 3; i < cs_pos; i++)
  290:   {
  291:       areca_packet[cs_pos] += areca_packet[i];
  292:   }
  293: 
  294:   if(!arcmsr_lock())
  295:   {
  296:     return -1;
  297:   }
  298:   expected = arcmsr_command_handler(ARCMSR_CLEAR_RQBUFFER, NULL, 0);
  299:   if (expected==-3) {
  300:     return set_err(EIO);
  301:   }
  302:   expected = arcmsr_command_handler(ARCMSR_CLEAR_WQBUFFER, NULL, 0);
  303:   expected = arcmsr_command_handler(ARCMSR_WRITE_WQBUFFER, areca_packet, areca_packet_len);
  304:   if ( expected > 0 )
  305:   {
  306:     expected = arcmsr_command_handler(ARCMSR_READ_RQBUFFER, return_buff, sizeof(return_buff));
  307:   }
  308: 
  309:   if ( expected < 0 )
  310:   {
  311:     return -1;
  312:   }
  313: 
  314:   if(!arcmsr_unlock())
  315:   {
  316:     return -1;
  317:   }
  318: 
  319:   // ----- VERIFY THE CHECKSUM -----
  320:   cs = 0;
  321:   for ( int loop = 3; loop < expected - 1; loop++ )
  322:   {
  323:       cs += return_buff[loop];
  324:   }
  325: 
  326:   if ( return_buff[expected - 1] != cs )
  327:   {
  328:     return -1;
  329:   }
  330: 
  331:   memcpy(result, return_buff, expected);
  332: 
  333:   return expected;
  334: }
  335: 
  336: int generic_areca_device::arcmsr_get_controller_type()
  337: {
  338:   int expected = 0;
  339:   unsigned char return_buff[2048];
  340:   unsigned char areca_packet[] = {0x5E, 0x01, 0x61, 0x01, 0x00, 0x23, 0x00};
  341: 
  342:   memset(return_buff, 0, sizeof(return_buff));
  343:   expected = arcmsr_ui_handler(areca_packet, sizeof(areca_packet), return_buff);
  344:   if ( expected < 0 )
  345:   {
  346:     return -1;
  347:   }
  348: 
  349:   return return_buff[0xc2];
  350: }
  351: 
  352: int generic_areca_device::arcmsr_get_dev_type()
  353: {
  354:   int expected = 0;
  355:   unsigned char return_buff[2048];
  356:   int ctlr_type = -1;
  357:   int encnum = get_encnum();
  358:   int disknum = get_disknum();
  359:   unsigned char areca_packet[] = {0x5E, 0x01, 0x61, 0x03, 0x00, 0x22, disknum - 1, encnum - 1, 0x00};
  360: 
  361:   memset(return_buff, 0, sizeof(return_buff));
  362:   expected = arcmsr_ui_handler(areca_packet, sizeof(areca_packet), return_buff);
  363:   if ( expected < 0 )
  364:   {
  365:     return -1;
  366:   }
  367: 
  368:   ctlr_type = arcmsr_get_controller_type();
  369: 
  370:   if( ctlr_type < 0 )
  371:   {
  372:     return ctlr_type;
  373:   }
  374: 
  375:   if( ctlr_type == 0x02/* SATA Controllers */ ||
  376:      (ctlr_type == 0x03 /* SAS Controllers */ && return_buff[0x52] & 0x01 /* SATA devices behind SAS Controller */) )
  377:   {
  378:     // SATA device
  379:     return 1;
  380:   }
  381: 
  382:   // SAS device
  383:   return 0;
  384: }
  385: 
  386: bool generic_areca_device::arcmsr_ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
  387: {
  388:   // ATA input registers
  389:   typedef struct _ATA_INPUT_REGISTERS
  390:   {
  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;
  401: 
  402:   // ATA output registers
  403:   // Note: The output registers is re-sorted for areca internal use only
  404:   typedef struct _ATA_OUTPUT_REGISTERS
  405:   {
  406:     unsigned char error;
  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;
  413: 
  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])
  420:   //
  421:   //
  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:   // +--------------------------------------------------------------------------------+
  426:   //
  427: 
  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])
  433:   //
  434:   //
  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];
  442:   int expected = 0;
  443: 
  444:   sATA_INPUT_REGISTERS *ata_cmd;
  445: 
  446:   // For debugging
  447: #if 0
  448:   memset(sInq, 0, sizeof(sInq));
  449:   scsiStdInquiry(fd, (unsigned char *)sInq, (int)sizeof(sInq));
  450:   dumpdata((unsigned char *)sInq, sizeof(sInq));
  451: #endif
  452:   memset(areca_packet, 0, areca_packet_len);
  453: 
  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
  461: 
  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];
  465: 
  466:   // Set registers
  467:   {
  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;
  476:   }
  477:   bool readdata = false;
  478:   if (in.direction == ata_cmd_in::data_in) {
  479:       readdata = true;
  480:       // the command will read data
  481:       areca_packet[6] = 0x13;
  482:   }
  483:   else if ( in.direction == ata_cmd_in::no_data )
  484:   {
  485:     // the commands will return no data
  486:     areca_packet[6] = 0x15;
  487:   }
  488:   else if (in.direction == ata_cmd_in::data_out)
  489:   {
  490:     // the commands will write data
  491:     memcpy(ata_cmd->data, in.buffer, in.size);
  492:     areca_packet[6] = 0x14;
  493:   }
  494:   else {
  495:       // COMMAND NOT SUPPORTED VIA ARECA IOCTL INTERFACE
  496:       return set_err(ENOSYS);
  497:   }
  498: 
  499:   areca_packet[11] = get_disknum() - 1;  // disk#
  500:   areca_packet[19] = get_encnum() - 1;   // enc#
  501: 
  502:   // ----- BEGIN TO SEND TO ARECA DRIVER ------
  503:   expected = arcmsr_ui_handler(areca_packet, areca_packet_len, return_buff);
  504:   if ( expected < 0 )
  505:   {
  506:     return set_err(EIO);
  507:   }
  508: 
  509:   sATA_OUTPUT_REGISTERS *ata_out = (sATA_OUTPUT_REGISTERS *)&return_buff[5] ;
  510:   if ( ata_out->status )
  511:   {
  512:     if ( in.in_regs.command == ATA_IDENTIFY_DEVICE
  513:      && !nonempty((unsigned char *)in.buffer, in.size))
  514:      {
  515:         return set_err(ENODEV, "No drive on port %d", get_disknum());
  516:      }
  517:   }
  518: 
  519:   // returns with data
  520:   if (readdata)
  521:   {
  522:     memcpy(in.buffer, &return_buff[7], in.size);
  523:   }
  524: 
  525:   // Return register values
  526:   {
  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;
  534:   }
  535:   return true;
  536: }
  537: 
  538: bool generic_areca_device::arcmsr_scsi_pass_through(struct scsi_cmnd_io * iop)
  539: {
  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])
  546:   //
  547:   //
  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:   // +--------------------------------------------------------------------------------+
  552:   //
  553: 
  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])
  559:   //
  560:   //
  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];
  568:   int expected = 0;
  569: 
  570:   if (iop->cmnd_len > 16) {
  571:     set_err(EINVAL, "cmnd_len too large");
  572:     return false;
  573:   }
  574: 
  575:   memset(areca_packet, 0, areca_packet_len);
  576: 
  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;
  584: 
  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)
  595:   {
  596:     areca_packet[13] |= 0x01;
  597:     memcpy(&areca_packet[67], iop->dxferp, iop->dxfer_len);
  598:   }
  599:   else if (iop->dxfer_dir == DXFER_FROM_DEVICE)
  600:   {
  601:   }
  602:   else if( iop->dxfer_dir == DXFER_NONE)
  603:   {
  604:   }
  605:   else {
  606:     // COMMAND NOT SUPPORTED VIA ARECA IOCTL INTERFACE
  607:     return set_err(ENOSYS);
  608:   }
  609: 
  610:   areca_packet[11] = get_disknum() - 1;  // disk#
  611:   areca_packet[19] = get_encnum() - 1;   // enc#
  612: 
  613:   // ----- BEGIN TO SEND TO ARECA DRIVER ------
  614:   expected = arcmsr_ui_handler(areca_packet, areca_packet_len, return_buff);
  615:   if ( expected < 0 )
  616:   {
  617:     return set_err(EIO);
  618:   }
  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: /////////////////////////////////////////////////////////////
  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: 
  663: areca_ata_device::~areca_ata_device() throw()
  664: {
  665: 
  666: }
  667: 
  668: bool 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: /////////////////////////////////////////////////////////////
  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: 
  691: areca_scsi_device::~areca_scsi_device() throw()
  692: {
  693: 
  694: }
  695: 
  696: bool areca_scsi_device::scsi_pass_through(struct scsi_cmnd_io * iop)
  697: {
  698:   return arcmsr_scsi_pass_through(iop);
  699: }
  700: 
  701: 
  702: 
  703: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>