Annotation of embedaddon/smartmontools/dev_areca.cpp, revision 1.1.1.2

1.1       misho       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: 
1.1.1.2 ! misho      24: const char * dev_areca_cpp_cvsid = "$Id: dev_areca.cpp 3835 2013-07-20 18:37:19Z chrfranke $"
1.1       misho      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();
1.1.1.2 ! misho     359:   unsigned char areca_packet[] = {0x5E, 0x01, 0x61, 0x03, 0x00, 0x22,
        !           360:     (unsigned char)(disknum - 1), (unsigned char)(encnum - 1), 0x00};
1.1       misho     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);
1.1.1.2 ! misho     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);
1.1       misho     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>