⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 reader.cc

📁 Test some scsi command for usb mass storage
💻 CC
字号:
/*******************************************************************
 * scsicmd.cc -- Test some scsi command for usb mass storage
 * using the SPC-3 and SBC-2
 * using the bulk only protocol.
 * using the DosUsb driver.
 *******************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <dos.h>
#include <dpmi.h>
#include <sys/farptr.h>
#include <sys/segments.h>
#include <sys/movedata.h>

#include "public.h"
#include "x86int.h"
#include "dosmem.h"

#include "usb.h"
#include "bulk.h"
#include "scsi.h"

DOS_MEM urb(URB_LENGTH);
DOS_MEM device_request(SETUP_REQUEST_LENGTH);
DOS_MEM cbw(CBW_LENGTH);
DOS_MEM buffer(BUFFER_LENGTH);

int i, j;
WORD wLen;
//BYTE bPacketSize;
//char sManufacturer[32], sProduct[32], sSerialNumber[32];
BYTE devAddr, inEndpoint, outEndpoint;
BYTE bTemp, *pByte;
DWORD dwTag, dwTemp;

X86_REGS inregs;

// ==========================================
/**********************************
 * Clear URB
 **********************************/
void initURB(void) {
  int i;

  for (i = 0; i < URB_LENGTH; i++)
    urb.SetBYTE(0, i);
}
/**************************************************
 * Control Transaction -- Send a request to device
 *
 * You have to fill device_request before calling
 * this function.
 * Data returned from device will store in buffer.
 ***************************************************/
void bulkCmdProc(int bufLen, int actualLen) {
  initURB();
  urb.SetBYTE(0x2d, URB_TRANSACTION_TOKEN);  // control
  urb.SetBYTE(devAddr, URB_DEV_ADD);
  urb.SetWORD(buffer.GetSegment(), URB_BUFFER_SEG);
  urb.SetWORD(buffer.GetOffset(), URB_BUFFER_OFF);
  urb.SetWORD(bufLen, URB_BUFFER_LENGTH);
  urb.SetWORD(actualLen, URB_ACTUAL_LENGTH);
  urb.SetWORD(device_request.GetSegment(), URB_SETUP_BUFFER_SEG);
  urb.SetWORD(device_request.GetOffset(), URB_SETUP_BUFFER_OFF);

  for (j = 0; j < buffer.GetLength(); j++) buffer.SetBYTE(1, j);

  inregs.x.ds = urb.GetSegment();
  inregs.x.dx = urb.GetOffset();
  x86_int(0x65, &inregs);  // call DosUsb
}
/*****************************************************
 * Reset command
 *
 * See USB mass storage class -- Bulk-Inly Transport
 *****************************************************/
void bulkReset(void) {
  device_request.SetBYTE(BULK_GET_MAX_LUN, SR_REQUEST_TYPE);
  device_request.SetBYTE(REQ_BULK_RESET, SR_REQUEST);
  device_request.SetWORD(0, SR_VALUE);
  device_request.SetWORD(0, SR_INDEX);     // interface number
  device_request.SetWORD(0, SR_LENGTH);

  bulkCmdProc(0, 8);
  return;
}
/*****************************************************
 * Get max. Logical Unit Number
 *
 * See USB mass storage class -- Bulk-Inly Transport
 * Return max. LUN
 *****************************************************/
int bulkMaxLun(void) {
  device_request.SetBYTE(BULK_GET_MAX_LUN, SR_REQUEST_TYPE);
  device_request.SetBYTE(REQ_BULK_GET_MAX_LUN, SR_REQUEST);
  device_request.SetWORD(0, SR_VALUE);
  device_request.SetWORD(0, SR_INDEX);     // interface number
  device_request.SetWORD(1, SR_LENGTH);
  bulkCmdProc(1, 8);
  return buffer.GetBYTE(0);
}
// ======================================
/*****************************************************
 * Clear CBW(Command Block Wrapper)
 *
 * See USB mass storage class -- Bulk-Inly Transport
 *****************************************************/
void initCBW(void) {
  int i;

  for (i = 0; i < CBW_LENGTH; i++)
    cbw.SetBYTE(0, i);
}
/****************************************************
 * OUT Transaction -- Send a SCSI command to device
 ****************************************************/
void scsiCmdProc(void) {
  initURB();
  urb.SetBYTE(0xe1, URB_TRANSACTION_TOKEN);   // out
  urb.SetBYTE(devAddr, URB_DEV_ADD);
  urb.SetBYTE(outEndpoint, URB_END_POINT);
  urb.SetWORD(cbw.GetSegment(), URB_BUFFER_SEG);
  urb.SetWORD(cbw.GetOffset(), URB_BUFFER_OFF);
  urb.SetWORD(31, URB_BUFFER_LENGTH);
  urb.SetWORD(31, URB_ACTUAL_LENGTH);

  inregs.x.ds = urb.GetSegment();
  inregs.x.dx = urb.GetOffset();
  x86_int(0x65, &inregs);  // call DosUsb
}
/******************************************
 * SCSI Command -- INQUIRY
 *
 * See SCSI Primary Commands - 3(SPC-3)
 ******************************************/
void scsiInquiry(void) {
  initCBW();
  cbw.SetDWORD(0x43425355, CBW_SIGNATURE);
  cbw.SetDWORD(++dwTag, CBW_TAG);
  cbw.SetDWORD(0x24, CBW_DATA_TRANSFER_LENGTH);
  cbw.SetBYTE(0x80, CBW_FLAGS);
  cbw.SetBYTE(0, CBW_LUN);
  cbw.SetBYTE(6, CBW_CB_LENGTH);

  cbw.SetBYTE(SCSI_INQUIRY, CBW_CDB);
  cbw.SetDWORD(0x24, CBW_CDB + 4);

  scsiCmdProc();
}
/******************************************
 * SCSI Command -- READ(10)
 *
 * See SCSI Block Commands - 2(SBC-2)
 ******************************************/
void scsiRead10(DWORD dwLba) {
  pByte = (BYTE *)&dwLba;
  initCBW();
  cbw.SetDWORD(0x43425355, CBW_SIGNATURE);
  cbw.SetDWORD(++dwTag, CBW_TAG);
  cbw.SetDWORD(512, CBW_DATA_TRANSFER_LENGTH); // 512 bytes
  cbw.SetBYTE(0x80, CBW_FLAGS);                // Data in
  cbw.SetBYTE(10, CBW_CB_LENGTH);

  cbw.SetBYTE(SCSI_READ10, CBW_CDB);     // operation code
  cbw.SetBYTE(pByte[3], CBW_CDB + 2);    // LBA
  cbw.SetBYTE(pByte[2], CBW_CDB + 3);
  cbw.SetBYTE(pByte[1], CBW_CDB + 4);
  cbw.SetBYTE(pByte[0], CBW_CDB + 5);

  cbw.SetBYTE(1, CBW_CDB + 8);           // transfer length

  scsiCmdProc();
}
/******************************************
 * SCSI Command -- READ CAPACITY (10)
 *
 * See SCSI Block Commands - 2(SBC-2)
 ******************************************/
void scsiReadCapacity10(void) {
  initCBW();
  cbw.SetDWORD(0x43425355, CBW_SIGNATURE);
  cbw.SetDWORD(++dwTag, CBW_TAG);
  cbw.SetDWORD(8, CBW_DATA_TRANSFER_LENGTH);    // 8 bytes
  cbw.SetBYTE(0x80, CBW_FLAGS);                 // data in
  cbw.SetBYTE(0, CBW_LUN);
  cbw.SetBYTE(10, CBW_CB_LENGTH);
  
  cbw.SetBYTE(SCSI_READ_CAPACITY10, CBW_CDB);  // OPERATION CODE

  scsiCmdProc();
}
/******************************************
 * SCSI Command -- REQUEST SENSE
 *
 * See SCSI Primary Commands - 3(SPC-3)
 ******************************************/
void scsiRequestSense(void) {
  initCBW();
  cbw.SetDWORD(0x43425355, CBW_SIGNATURE);
  cbw.SetDWORD(++dwTag, CBW_TAG);
  cbw.SetDWORD(0x12, CBW_DATA_TRANSFER_LENGTH);    // 8 bytes
  cbw.SetBYTE(0x80, CBW_FLAGS);                 // data in
  cbw.SetBYTE(0, CBW_LUN);
  cbw.SetBYTE(12, CBW_CB_LENGTH);
  
  cbw.SetBYTE(SCSI_REQUEST_SENSE, CBW_CDB);  // OPERATION CODE
  cbw.SetBYTE(0x12, CBW_CDB + 4);  // OPERATION CODE

  scsiCmdProc();
}
/******************************************
 * SCSI Command -- TEST UNIT READY
 *
 * See SCSI Primary Commands - 3(SPC-3)
 ******************************************/
void scsiTestUnitReady(void) {
  initCBW();
  cbw.SetDWORD(0x43425355, CBW_SIGNATURE);
  cbw.SetDWORD(++dwTag, CBW_TAG);
  cbw.SetDWORD(0, CBW_DATA_TRANSFER_LENGTH);    // 8 bytes
  cbw.SetBYTE(0x80, CBW_FLAGS);                 // data in
  cbw.SetBYTE(0, CBW_LUN);
  cbw.SetBYTE(6, CBW_CB_LENGTH);
  
  cbw.SetBYTE(SCSI_TEST_UNIT_READY, CBW_CDB);  // OPERATION CODE

  scsiCmdProc();
}
// ========================================
/*****************************************************
 * IN Transaction -- Get data returned from device
 *                   after SCSI command
 *****************************************************/
void getData(void) {
  initURB();
  for (j = 0; j < buffer.GetLength(); j++) buffer.SetBYTE(0, j);
  urb.SetBYTE(0x69, URB_TRANSACTION_TOKEN);   // in
  urb.SetBYTE(devAddr, URB_DEV_ADD);
  urb.SetBYTE(inEndpoint, URB_END_POINT);
  urb.SetWORD(buffer.GetSegment(), URB_BUFFER_SEG);
  urb.SetWORD(buffer.GetOffset(), URB_BUFFER_OFF);
  urb.SetWORD(64, URB_BUFFER_LENGTH);
  urb.SetWORD(64, URB_ACTUAL_LENGTH);

  inregs.x.ds = urb.GetSegment();
  inregs.x.dx = urb.GetOffset();
  x86_int(0x65, &inregs);  // call DosUsb
}
/**************************************************
 * Show the meaning of status after calling DOSUSB
 **************************************************/
void showStatus(BYTE bStatus) {
  printf("Completion code:");
  switch (bStatus) {
    case 0:
      printf("No Error");
      break;
    case 0x44:
      printf("CRC/Data Toggle Mismatch/Device Not Responding/PID Check Failure/Inexpected PID");
      break;
    case 0x42:
      printf("Bit Stuffing");
      break;
    case 0x40:
      printf("Stall");
      break;
    case 0x50:
      printf("Data Overrun");
      break;
    case 0x20:
      printf("Buffer Overrun");
      break;
    case 0xa0:
      printf("Buffer Underrun");
      break;
    case 0x88:
      printf("Not Accessed");
      break;
    default:
      printf("Unknown status: 0X02x", bStatus);
      break;
  }
}
/*****************************************************
 * Get and Show CSW(Command Status Wrapper)
 *
 * See USB mass storage class -- Bulk-Inly Transport
 *****************************************************/
void getCSW(void) {
  getData();
  printf("\nActual length: %d", urb.GetWORD(URB_ACTUAL_LENGTH));
  printf("\nGet CSW: Error Code: %d    ", urb.GetBYTE(URB_ERROR_CODE));
  showStatus(urb.GetBYTE(URB_STATUS));
  printf("\nSignature: 0X%08x   Tag: 0X%08x",
         buffer.GetDWORD(0), buffer.GetDWORD(4));
  printf("\nCSWDataResidue: 0X%08x    CSWStatus: 0X%02x",
         buffer.GetDWORD(8), buffer.GetDWORD(12));
}
/*****************************************************
 * Show data returned from device after SCSI INQUIRY
 *****************************************************/
void showInquiryResult(void) {
  j = urb.GetBYTE(URB_ACTUAL_LENGTH);
  bTemp = buffer.GetBYTE(0);
  printf("\nInquiry: URB_Actual_Length = %d\n", j);
  printf("\nPeripheral Qualifier: %d  Peripheral device type: %d",
         (bTemp & 0xe0) >> 5, (bTemp & 0x1f));
  printf("\nRemovable medium bit: %d   Version: 0X%02x",
         (buffer.GetBYTE(1)==0?0:1), buffer.GetBYTE(2));
         //(buffer.GetBYTE(1) >> 7), buffer.GetBYTE(2));
  bTemp = buffer.GetBYTE(3);
  printf("\nNormal ACA supported: %d    Hierarchical support bit: %d",
         ((bTemp & 0x20) >> 5), ((bTemp & 0x10) >> 4));
  printf("\nResponse Data Format: %d", bTemp & 0x0f);
  printf("\nAdditional Length: %d", buffer.GetBYTE(4));
  bTemp = buffer.GetBYTE(5);
  printf("\nSCC supported: %d  Access Control Coordinator: %d",
         (bTemp & 0x80) >> 7, (bTemp & 0x40) >> 6);
  printf("\nTarget port group support: %d", (bTemp & 0x30) >> 4);
  printf("\nThirty-Party Copy: %d   PROTECT: %d\n",
         (bTemp & 0x08) >> 3, (bTemp & 0x01));
  
  for (i = 8; i < j; i++) {
    if (buffer.GetBYTE(i) != 0) {
        putch(buffer.GetBYTE(i));
    }
  }
}
/**********************************************
 * Show data of sector in HEX
 **********************************************/
void showData(void) {
  printf("\nActual Length of Data: %d\n", urb.GetWORD(URB_ACTUAL_LENGTH));
  if (urb.GetWORD(URB_ACTUAL_LENGTH) > 0)
    for (j = 0; j < 64; j++) {
      printf("%02x ", (UBYTE)buffer.GetBYTE(j));
    }
}
// main program
int main() {
  devAddr     = 1;  // device address according to Device Descriptor
  inEndpoint  = 2;
  outEndpoint = 1;
  dwTag = 0;
  
  bulkReset();
  // ******************************************
  printf("\n\n***1st setp: Get max. LUN***");
  i = bulkMaxLun();
  if (urb.GetBYTE(URB_ERROR_CODE) == 1) {
    printf("\n\nInvalid Device Address.\n");
    exit(1);
  }
  if (urb.GetBYTE(URB_STATUS) > 1) {
    printf("\n\nDevice does not response.\n");
    exit(1);
  }
  printf("\nActual Length: %d", urb.GetWORD(URB_ACTUAL_LENGTH));
  printf("\nLogical Unit: %d", i + 1);
  printf("\nPress any key to continue......");
  getch();
  // *************************************************
  printf("\n\n***2nd setp: SCSI INQUIRY command***");
  scsiInquiry();
  printf("\nError Code: %d    ", urb.GetBYTE(URB_ERROR_CODE));
  showStatus(urb.GetBYTE(URB_STATUS));
  // get INQUIRY result
  getData();
  printf("\nGet Inquiry Result: Error Code: %d    ", urb.GetBYTE(URB_ERROR_CODE));
  showStatus(urb.GetBYTE(URB_STATUS));
  showInquiryResult();
  getCSW();
  printf("\nPress any key to continue......");
  getch();
  // **********************************************
  printf("\n\n***3th step: SCSI request sense***");
  scsiRequestSense();
  printf("\nError Code: %d    ", urb.GetBYTE(URB_ERROR_CODE));
  showStatus(urb.GetBYTE(URB_STATUS));
  getData();
  wLen = urb.GetWORD(URB_ACTUAL_LENGTH);
  printf("\nActual length: %d", wLen);
  printf("\nValid: %d  Response Code: 0X%02x",
         ((buffer.GetBYTE(0) & 0x80) == 0?0:1), (buffer.GetBYTE(0) &0x7f));
  printf("\nSense Key: 0x%02x   Addition Sense length: %d",
         (buffer.GetBYTE(2) & 0x0f), buffer.GetBYTE(7));
  getCSW();
  printf("\nPress any key to continue......");
  getch();
  // *************************************************
  printf("\n\n***4th step: SCSI Test unit ready***");
  scsiTestUnitReady();
  printf("\nError Code: %d    ", urb.GetBYTE(URB_ERROR_CODE));
  showStatus(urb.GetBYTE(URB_STATUS));
  getCSW();
  printf("\nPress any key to continue......");
  getch();
  // *******************************************
  printf("\n\n***5th step: get capacity***");
  scsiReadCapacity10();
  printf("\nError Code: %d    ", urb.GetBYTE(URB_ERROR_CODE));
  showStatus(urb.GetBYTE(URB_STATUS));
  getData();
  printf("\nActual length: %d", urb.GetWORD(URB_ACTUAL_LENGTH));
  pByte = (BYTE *)&dwTemp;
  *pByte = buffer.GetBYTE(3);
  *(pByte + 1) = buffer.GetBYTE(2);
  *(pByte + 2) = buffer.GetBYTE(1);
  *(pByte + 3) = buffer.GetBYTE(0);
  printf("\nLBA: 0X%08x",  dwTemp);
  pByte = (BYTE *)&dwTemp;
  *pByte = buffer.GetBYTE(7);
  *(pByte + 1) = buffer.GetBYTE(6);
  *(pByte + 2) = buffer.GetBYTE(5);
  *(pByte + 3) = buffer.GetBYTE(4);
  printf("   Capacity: 0X%08x",  dwTemp);
  getCSW();
  printf("\nPress any key to continue......");
  getch();
  // *********************************************
  printf("\n\n***6th step: SCSI READ(10) command***");
  scsiRead10(0);
  printf("\nError Code: %d    ", urb.GetBYTE(URB_ERROR_CODE));
  showStatus(urb.GetBYTE(URB_STATUS));

  for (j = 0; j < buffer.GetLength(); j++) buffer.SetBYTE(0, j);
  i = 0;
  while (i < 8) {
    getData();
    if (urb.GetBYTE(URB_STATUS) == 0) {
      i++;
      showData();
      printf("\nPress any to continue...");
      getch();
    } else if ((UBYTE)urb.GetBYTE(URB_STATUS) != 0X88) {
      break;
    }
  }
  getCSW();
  return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -