Annotation of embedaddon/smartmontools/dev_areca.cpp, revision 1.1
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:
! 24: const char * dev_areca_cpp_cvsid = "$Id: dev_areca.cpp 3664 2012-10-24 21:07:11Z chrfranke $"
! 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>