File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / smartmontools / dev_areca.cpp
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 14 07:54:03 2013 UTC (10 years, 8 months ago) by misho
Branches: smartmontools, elwix, MAIN
CVS tags: v6_2, HEAD
v 6.2

    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.2 2013/10/14 07:54:03 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,
  360:     (unsigned char)(disknum - 1), (unsigned char)(encnum - 1), 0x00};
  361: 
  362:   memset(return_buff, 0, sizeof(return_buff));
  363:   expected = arcmsr_ui_handler(areca_packet, sizeof(areca_packet), return_buff);
  364:   if ( expected < 0 )
  365:   {
  366:     return -1;
  367:   }
  368: 
  369:   ctlr_type = arcmsr_get_controller_type();
  370: 
  371:   if( ctlr_type < 0 )
  372:   {
  373:     return ctlr_type;
  374:   }
  375: 
  376:   if( ctlr_type == 0x02/* SATA Controllers */ ||
  377:      (ctlr_type == 0x03 /* SAS Controllers */ && return_buff[0x52] & 0x01 /* SATA devices behind SAS Controller */) )
  378:   {
  379:     // SATA device
  380:     return 1;
  381:   }
  382: 
  383:   // SAS device
  384:   return 0;
  385: }
  386: 
  387: bool generic_areca_device::arcmsr_ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
  388: {
  389:   // ATA input registers
  390:   typedef struct _ATA_INPUT_REGISTERS
  391:   {
  392:     unsigned char features;
  393:     unsigned char sector_count;
  394:     unsigned char sector_number;
  395:     unsigned char cylinder_low;
  396:     unsigned char cylinder_high;
  397:     unsigned char device_head;
  398:     unsigned char command;
  399:     unsigned char reserved[8];
  400:     unsigned char data[512]; // [in/out] buffer for outgoing/incoming data
  401:   } sATA_INPUT_REGISTERS;
  402: 
  403:   // ATA output registers
  404:   // Note: The output registers is re-sorted for areca internal use only
  405:   typedef struct _ATA_OUTPUT_REGISTERS
  406:   {
  407:     unsigned char error;
  408:     unsigned char status;
  409:     unsigned char sector_count;
  410:     unsigned char sector_number;
  411:     unsigned char cylinder_low;
  412:     unsigned char cylinder_high;
  413:   } sATA_OUTPUT_REGISTERS;
  414: 
  415:   // Areca packet format for outgoing:
  416:   // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
  417:   // B[3~4] : 2 bytes command length + variant data length, little endian
  418:   // B[5]   : 1 bytes areca defined command code, ATA passthrough command code is 0x1c
  419:   // B[6~last-1] : variant bytes payload data
  420:   // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
  421:   //
  422:   //
  423:   //   header 3 bytes  length 2 bytes   cmd 1 byte    payload data x bytes  cs 1 byte
  424:   // +--------------------------------------------------------------------------------+
  425:   // + 0x5E 0x01 0x61 |   0x00 0x00   |     0x1c   | .................... |   0x00    |
  426:   // +--------------------------------------------------------------------------------+
  427:   //
  428: 
  429:   //Areca packet format for incoming:
  430:   // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
  431:   // B[3~4] : 2 bytes payload length, little endian
  432:   // B[5~last-1] : variant bytes returned payload data
  433:   // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
  434:   //
  435:   //
  436:   //   header 3 bytes  length 2 bytes   payload data x bytes  cs 1 byte
  437:   // +-------------------------------------------------------------------+
  438:   // + 0x5E 0x01 0x61 |   0x00 0x00   | .................... |   0x00    |
  439:   // +-------------------------------------------------------------------+
  440:   unsigned char    areca_packet[640];
  441:   int areca_packet_len = sizeof(areca_packet);
  442:   unsigned char return_buff[2048];
  443:   int expected = 0;
  444: 
  445:   sATA_INPUT_REGISTERS *ata_cmd;
  446: 
  447:   // For debugging
  448: #if 0
  449:   memset(sInq, 0, sizeof(sInq));
  450:   scsiStdInquiry(fd, (unsigned char *)sInq, (int)sizeof(sInq));
  451:   dumpdata((unsigned char *)sInq, sizeof(sInq));
  452: #endif
  453:   memset(areca_packet, 0, areca_packet_len);
  454: 
  455:   // ----- BEGIN TO SETUP HEADERS -------
  456:   areca_packet[0] = 0x5E;
  457:   areca_packet[1] = 0x01;
  458:   areca_packet[2] = 0x61;
  459:   areca_packet[3] = (unsigned char)((areca_packet_len - 6) & 0xff);
  460:   areca_packet[4] = (unsigned char)(((areca_packet_len - 6) >> 8) & 0xff);
  461:   areca_packet[5] = 0x1c;  // areca defined code for ATA passthrough command
  462: 
  463:   // ----- BEGIN TO SETUP PAYLOAD DATA -----
  464:   memcpy(&areca_packet[7], "SmrT", 4);  // areca defined password
  465:   ata_cmd = (sATA_INPUT_REGISTERS *)&areca_packet[12];
  466: 
  467:   // Set registers
  468:   {
  469:     const ata_in_regs & r = in.in_regs;
  470:     ata_cmd->features      = r.features;
  471:     ata_cmd->sector_count  = r.sector_count;
  472:     ata_cmd->sector_number = r.lba_low;
  473:     ata_cmd->cylinder_low  = r.lba_mid;
  474:     ata_cmd->cylinder_high = r.lba_high;
  475:     ata_cmd->device_head   = r.device;
  476:     ata_cmd->command       = r.command;
  477:   }
  478:   bool readdata = false;
  479:   if (in.direction == ata_cmd_in::data_in) {
  480:       readdata = true;
  481:       // the command will read data
  482:       areca_packet[6] = 0x13;
  483:   }
  484:   else if ( in.direction == ata_cmd_in::no_data )
  485:   {
  486:     // the commands will return no data
  487:     areca_packet[6] = 0x15;
  488:   }
  489:   else if (in.direction == ata_cmd_in::data_out)
  490:   {
  491:     // the commands will write data
  492:     memcpy(ata_cmd->data, in.buffer, in.size);
  493:     areca_packet[6] = 0x14;
  494:   }
  495:   else {
  496:       // COMMAND NOT SUPPORTED VIA ARECA IOCTL INTERFACE
  497:       return set_err(ENOSYS);
  498:   }
  499: 
  500:   areca_packet[11] = get_disknum() - 1;  // disk#
  501:   areca_packet[19] = get_encnum() - 1;   // enc#
  502: 
  503:   // ----- BEGIN TO SEND TO ARECA DRIVER ------
  504:   expected = arcmsr_ui_handler(areca_packet, areca_packet_len, return_buff);
  505:   if ( expected < 0 )
  506:   {
  507:     return set_err(EIO);
  508:   }
  509: 
  510:   sATA_OUTPUT_REGISTERS *ata_out = (sATA_OUTPUT_REGISTERS *)&return_buff[5] ;
  511:   if ( ata_out->status )
  512:   {
  513:     if ( in.in_regs.command == ATA_IDENTIFY_DEVICE
  514:      && !nonempty((unsigned char *)in.buffer, in.size))
  515:      {
  516:         return set_err(ENODEV, "No drive on port %d", get_disknum());
  517:      }
  518:   }
  519: 
  520:   // returns with data
  521:   if (readdata)
  522:   {
  523:     memcpy(in.buffer, &return_buff[7], in.size);
  524:   }
  525: 
  526:   // Return register values
  527:   {
  528:     ata_out_regs & r = out.out_regs;
  529:     r.error          = ata_out->error;
  530:     r.sector_count   = ata_out->sector_count;
  531:     r.lba_low        = ata_out->sector_number;
  532:     r.lba_mid        = ata_out->cylinder_low;
  533:     r.lba_high       = ata_out->cylinder_high;
  534:     r.status         = ata_out->status;
  535:   }
  536:   return true;
  537: }
  538: 
  539: bool generic_areca_device::arcmsr_scsi_pass_through(struct scsi_cmnd_io * iop)
  540: {
  541:   // Areca packet format for outgoing:
  542:   // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
  543:   // B[3~4] : 2 bytes command length + variant data length, little endian
  544:   // B[5]   : 1 bytes areca defined command code
  545:   // B[6~last-1] : variant bytes payload data
  546:   // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
  547:   //
  548:   //
  549:   //   header 3 bytes  length 2 bytes   cmd 1 byte    payload data x bytes  cs 1 byte
  550:   // +--------------------------------------------------------------------------------+
  551:   // + 0x5E 0x01 0x61 |   0x00 0x00   |     0x1c   | .................... |   0x00    |
  552:   // +--------------------------------------------------------------------------------+
  553:   //
  554: 
  555:   //Areca packet format for incoming:
  556:   // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
  557:   // B[3~4] : 2 bytes payload length, little endian
  558:   // B[5~last-1] : variant bytes returned payload data
  559:   // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
  560:   //
  561:   //
  562:   //   header 3 bytes  length 2 bytes   payload data x bytes  cs 1 byte
  563:   // +-------------------------------------------------------------------+
  564:   // + 0x5E 0x01 0x61 |   0x00 0x00   | .................... |   0x00    |
  565:   // +-------------------------------------------------------------------+
  566:   unsigned char    areca_packet[640];
  567:   int areca_packet_len = sizeof(areca_packet);
  568:   unsigned char return_buff[2048];
  569:   int expected = 0;
  570: 
  571:   if (iop->cmnd_len > 16) {
  572:     set_err(EINVAL, "cmnd_len too large");
  573:     return false;
  574:   }
  575: 
  576:   memset(areca_packet, 0, areca_packet_len);
  577: 
  578:   // ----- BEGIN TO SETUP HEADERS -------
  579:   areca_packet[0] = 0x5E;
  580:   areca_packet[1] = 0x01;
  581:   areca_packet[2] = 0x61;
  582:   areca_packet[3] = (unsigned char)((areca_packet_len - 6) & 0xff);
  583:   areca_packet[4] = (unsigned char)(((areca_packet_len - 6) >> 8) & 0xff);
  584:   areca_packet[5] = 0x1c;
  585: 
  586:   // ----- BEGIN TO SETUP PAYLOAD DATA -----
  587:   areca_packet[6] = 0x16; // scsi pass through
  588:   memcpy(&areca_packet[7], "SmrT", 4);  // areca defined password
  589:   areca_packet[12] = iop->cmnd_len; // cdb length
  590:   memcpy( &areca_packet[35], iop->cmnd, iop->cmnd_len); // cdb
  591:   areca_packet[15] = (unsigned char)iop->dxfer_len; // 15(LSB) ~ 18(MSB): data length ( max=512 bytes)
  592:   areca_packet[16] = (unsigned char)(iop->dxfer_len >> 8);
  593:   areca_packet[17] = (unsigned char)(iop->dxfer_len >> 16);
  594:   areca_packet[18] = (unsigned char)(iop->dxfer_len >> 24);
  595:   if(iop->dxfer_dir == DXFER_TO_DEVICE)
  596:   {
  597:     areca_packet[13] |= 0x01;
  598:     memcpy(&areca_packet[67], iop->dxferp, iop->dxfer_len);
  599:   }
  600:   else if (iop->dxfer_dir == DXFER_FROM_DEVICE)
  601:   {
  602:   }
  603:   else if( iop->dxfer_dir == DXFER_NONE)
  604:   {
  605:   }
  606:   else {
  607:     // COMMAND NOT SUPPORTED VIA ARECA IOCTL INTERFACE
  608:     return set_err(ENOSYS);
  609:   }
  610: 
  611:   areca_packet[11] = get_disknum() - 1;  // disk#
  612:   areca_packet[19] = get_encnum() - 1;   // enc#
  613: 
  614:   // ----- BEGIN TO SEND TO ARECA DRIVER ------
  615:   expected = arcmsr_ui_handler(areca_packet, areca_packet_len, return_buff);
  616: 
  617:   if (expected < 0)
  618:     return set_err(EIO, "arcmsr_scsi_pass_through: I/O error");
  619:   if (expected < 15) // 7 bytes if port is empty
  620:     return set_err(EIO, "arcmsr_scsi_pass_through: missing data (%d bytes, expected %d)", expected, 15);
  621: 
  622:   int scsi_status = return_buff[5];
  623:   int in_data_len = return_buff[11] | return_buff[12] << 8 | return_buff[13] << 16 | return_buff[14] << 24;
  624: 
  625:   if (iop->dxfer_dir == DXFER_FROM_DEVICE)
  626:   {
  627:     memset(iop->dxferp, 0, iop->dxfer_len); // need?
  628:     memcpy(iop->dxferp, &return_buff[15], in_data_len);
  629:   }
  630: 
  631:   if(scsi_status == 0xE1 /* Underrun, actual data length < requested data length */)
  632:   {
  633:       // don't care, just ignore
  634:       scsi_status = 0x0;
  635:   }
  636: 
  637:   if(scsi_status != 0x00 && scsi_status != SCSI_STATUS_CHECK_CONDITION)
  638:   {
  639:     return set_err(EIO);
  640:   }
  641: 
  642:   if(scsi_status == SCSI_STATUS_CHECK_CONDITION)
  643:   {
  644:     // check condition
  645:     iop->scsi_status = SCSI_STATUS_CHECK_CONDITION;
  646:     iop->resp_sense_len = 4;
  647:     iop->sensep[0] = return_buff[7];
  648:     iop->sensep[1] = return_buff[8];
  649:     iop->sensep[2] = return_buff[9];
  650:     iop->sensep[3] = return_buff[10];
  651:   }
  652: 
  653:   return true;
  654: }
  655: 
  656: /////////////////////////////////////////////////////////////
  657: areca_ata_device::areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
  658: : smart_device(intf, dev_name, "areca", "areca")
  659: {
  660:   set_encnum(encnum);
  661:   set_disknum(disknum);
  662:   set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
  663: }
  664: 
  665: areca_ata_device::~areca_ata_device() throw()
  666: {
  667: 
  668: }
  669: 
  670: bool areca_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
  671: {
  672:   if (!ata_cmd_is_supported(in,
  673:     ata_device::supports_data_out |
  674:     ata_device::supports_output_regs |
  675:   //ata_device::supports_multi_sector | // TODO
  676:     ata_device::supports_48bit_hi_null,
  677:     "Areca")
  678:   )
  679:     return false;
  680: 
  681:   return arcmsr_ata_pass_through(in, out);
  682: }
  683: 
  684: /////////////////////////////////////////////////////////////
  685: areca_scsi_device::areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
  686: : smart_device(intf, dev_name, "areca", "areca")
  687: {
  688:   set_encnum(encnum);
  689:   set_disknum(disknum);
  690:   set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
  691: }
  692: 
  693: areca_scsi_device::~areca_scsi_device() throw()
  694: {
  695: 
  696: }
  697: 
  698: bool areca_scsi_device::scsi_pass_through(struct scsi_cmnd_io * iop)
  699: {
  700:   return arcmsr_scsi_pass_through(iop);
  701: }
  702: 
  703: 
  704: 
  705: 

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