void test_execute_Inquiry(char* path, int evpd, int page_code) { struct sg_io_hdr* p_hdr = init_io_hdr(); set_xfer_data(p_hdr, data_buffer, BLOCK_LEN * 256); set_sense_data(p_hdr, sense_buffer, SENSE_LEN); int status = 0; int fd = open(path, O_RDWR); if (fd > 0) { status = execute_Inquiry(fd, page_code, evpd, p_hdr); printf("the return status is %d\n", status); if (status != 0) { show_sense_buffer(p_hdr); } else { show_vendor(p_hdr); show_product(p_hdr); show_product_rev(p_hdr); } } else { printf("failed to open sg file %s\n", path); } close(fd); destroy_io_hdr(p_hdr); }
UINT8 omti8621_device::check_disk_address(const UINT8 *cdb) { UINT8 sense_code = OMTI_SENSE_CODE_NO_ERROR; UINT8 lun = get_lun(cdb); UINT16 head = cdb[1] & 0x1f; UINT16 sector = cdb[2] & 0x3f; UINT32 cylinder = cdb[3] + ((cdb[2] & 0xc0) << 2) + ((cdb[1] & 0x80) << 3); UINT8 block_count = cdb[4]; omti_disk_image_device *disk = our_disks[lun]; UINT32 disk_track = cylinder * disk->m_heads + head; UINT32 disk_addr = (disk_track * disk->m_sectors) + sector; if (block_count > OMTI_MAX_BLOCK_COUNT) { LOG(("########### check_disk_address: unexpected block count %x", block_count)); sense_code = OMTI_SENSE_CODE_ILLEGAL_ADDRESS | OMTI_SENSE_CODE_ADDRESS_VALID; } if (lun > OMTI_MAX_LUN) { sense_code = OMTI_SENSE_CODE_DRIVE_NOT_READY; } else if (!disk->m_image->exists()) { sense_code = OMTI_SENSE_CODE_DRIVE_NOT_READY; } else if (sector >= OMTI_MAX_BLOCK_COUNT) { sense_code = OMTI_SENSE_CODE_ILLEGAL_ADDRESS | OMTI_SENSE_CODE_ADDRESS_VALID; } else if (head >= disk->m_heads) { sense_code = OMTI_SENSE_CODE_ILLEGAL_ADDRESS | OMTI_SENSE_CODE_ADDRESS_VALID; } else if (cylinder >= disk->m_cylinders) { sense_code = OMTI_SENSE_CODE_ILLEGAL_ADDRESS | OMTI_SENSE_CODE_ADDRESS_VALID; } else if ( disk_track == diskaddr_format_bad_track && disk_track != 0) { sense_code = OMTI_SENSE_CODE_BAD_TRACK; } else if (disk_addr == diskaddr_ecc_error && disk_addr != 0) { sense_code = OMTI_SENSE_CODE_ECC_ERROR; } else if (disk_track == alternate_track_address[1] && disk_track != 0) { sense_code = OMTI_SENSE_CODE_ALTERNATE_TRACK; } if (sense_code == OMTI_SENSE_CODE_NO_ERROR) { clear_sense_data(); } else { command_status |= OMTI_COMMAND_STATUS_ERROR; set_sense_data(sense_code, cdb); } return sense_code == OMTI_SENSE_CODE_NO_ERROR; }
void omti8621_device::do_command(const UINT8 cdb[], const UINT16 cdb_length) { UINT8 lun = get_lun(cdb); omti_disk_image_device *disk = our_disks[lun]; int command_duration = 0; // ms log_command( cdb, cdb_length); // default to read status and status is successful completion omti_state = OMTI_STATE_STATUS; status_port |= OMTI_STATUS_IO | OMTI_STATUS_CD; command_status = lun ? OMTI_COMMAND_STATUS_LUN : 0; if (mask_port & OMTI_MASK_INTE) { set_interrupt(CLEAR_LINE); } if (!disk->m_image->exists()) { command_status |= OMTI_COMMAND_STATUS_ERROR; // no such drive } switch (cdb[0]) { case OMTI_CMD_TEST_DRIVE_READY: // 0x00 if (!disk->m_image->exists()) { set_sense_data(OMTI_SENSE_CODE_DRIVE_NOT_READY, cdb); } break; case OMTI_CMD_RECALIBRATE: // 0x01 break; case OMTI_CMD_REQUEST_SENSE: // 0x03 set_data_transfer(sense_data, sizeof(sense_data)); break; case OMTI_CMD_READ_VERIFY: // 0x05 check_disk_address(cdb); break; case OMTI_CMD_FORMAT_TRACK: // 0x06 format_track(cdb); break; case OMTI_CMD_FORMAT_BAD_TRACK: // 0x07 diskaddr_format_bad_track = get_disk_address(cdb); break; case OMTI_CMD_READ: // 0x08 if (check_disk_address(cdb)) { // read data from controller read_sectors_from_disk(get_disk_address(cdb), cdb[4], lun); set_data_transfer(§or_buffer[0], OMTI_DISK_SECTOR_SIZE*cdb[4]); } break; case OMTI_CMD_WRITE: // 0x0A log_data(); if (check_disk_address(cdb)) { write_sectors_to_disk(get_disk_address(cdb), cdb[4], lun); } break; case OMTI_CMD_SEEK: // 0x0B check_disk_address(cdb); break; case OMTI_CMD_READ_SECTOR_BUFFER: // 0x0E set_data_transfer(§or_buffer[0], OMTI_DISK_SECTOR_SIZE*cdb[4]); break; case OMTI_CMD_WRITE_SECTOR_BUFFER: // 0x0F log_data(); break; case OMTI_CMD_COPY: // 0x20 if (check_disk_address(cdb) && check_disk_address(cdb+4)) { // copy sectors copy_sectors (get_disk_address(cdb+4), get_disk_address(cdb), cdb[4], lun); } break; case OMTI_CMD_READ_ESDI_DEFECT_LIST: // 0x37 set_esdi_defect_list(get_lun(cdb), cdb[1] & 0x1f); set_data_transfer(disk->m_esdi_defect_list, sizeof(disk->m_esdi_defect_list)); break; #if 0 // this command seems unused by Domain/OS, and it's unclear what the intent of the code is (it makes some versions of GCC quite unhappy) case OMTI_CMD_ASSIGN_ALTERNATE_TRACK: // 0x11 log_data(); alternate_track_address[0] = get_disk_track(cdb); alternate_track_address[1] = get_disk_track(alternate_track_buffer-1); break; #endif case OMTI_CMD_READ_DATA_TO_BUFFER: // 0x1E if (check_disk_address(cdb)) { // read data from controller read_sectors_from_disk (get_disk_address(cdb), cdb[4], lun); // Domain/OS doesn't expect zero access time command_duration += 1; // 1 ms is enough, average time would be 30 ms) } break; case OMTI_CMD_WRITE_DATA_FROM_BUFFER: // 0x1F log_data(); if (check_disk_address(cdb)) { write_sectors_to_disk(get_disk_address(cdb), cdb[4], lun); } break; case OMTI_CMD_RAM_DIAGNOSTICS: // 0xE0 break; case OMTI_CMD_CONTROLLER_INT_DIAGNOSTIC: // 0xE4 break; case OMTI_CMD_READ_LONG: // 0xE5 if (check_disk_address(cdb)) { // read data from controller read_sectors_from_disk(get_disk_address(cdb), cdb[4], lun); set_data_transfer(§or_buffer[0], OMTI_DISK_SECTOR_SIZE+6); } break; case OMTI_CMD_WRITE_LONG: // 0xE6 log_data(); if (check_disk_address(cdb)) { UINT32 diskaddr = get_disk_address(cdb); write_sectors_to_disk(diskaddr, cdb[4], lun); // this will spoil the ECC code diskaddr_ecc_error = diskaddr; } break; case OMTI_CMD_READ_CONFIGURATION: // 0xEC set_configuration_data(get_lun(cdb)); set_data_transfer(disk->m_config_data, sizeof(disk->m_config_data)); break; case OMTI_CMD_INVALID_COMMAND: // 0xFF set_sense_data(OMTI_SENSE_CODE_INVALID_COMMAND, cdb); command_status |= OMTI_COMMAND_STATUS_ERROR; break; default: LOG(("do_command: UNEXPECTED command %02x",cdb[0])); set_sense_data(OMTI_SENSE_CODE_INVALID_COMMAND, cdb); command_status |= OMTI_COMMAND_STATUS_ERROR; break; } if (mask_port & OMTI_MASK_INTE) { // if (omti_state != OMTI_STATE_STATUS) { // LOG(("do_command: UNEXPECTED omti_state %02x",omti_state)); // } status_port |= OMTI_STATUS_IREQ; if (command_duration == 0) { set_interrupt(ASSERT_LINE); } else { // FIXME: should delay omti_state and status_port as well m_timer->adjust(attotime::from_msec(command_duration), 0); } } }
void set_sense_type(struct rts51x_chip *chip, unsigned int lun, int sense_type) { switch (sense_type) { case SENSE_TYPE_MEDIA_CHANGE: set_sense_data(chip, lun, CUR_ERR, 0x06, 0, 0x28, 0, 0, 0); break; case SENSE_TYPE_MEDIA_NOT_PRESENT: set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x3A, 0, 0, 0); break; case SENSE_TYPE_MEDIA_LBA_OVER_RANGE: set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x21, 0, 0, 0); break; case SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT: set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x25, 0, 0, 0); break; case SENSE_TYPE_MEDIA_WRITE_PROTECT: set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x27, 0, 0, 0); break; case SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR: set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x11, 0, 0, 0); break; case SENSE_TYPE_MEDIA_WRITE_ERR: set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x02, 0, 0); break; case SENSE_TYPE_MEDIA_INVALID_CMD_FIELD: set_sense_data(chip, lun, CUR_ERR, ILGAL_REQ, 0, ASC_INVLD_CDB, ASCQ_INVLD_CDB, CDB_ILLEGAL, 1); break; case SENSE_TYPE_FORMAT_IN_PROGRESS: set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, 0, 0); break; case SENSE_TYPE_FORMAT_CMD_FAILED: set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x31, 0x01, 0, 0); break; #ifdef SUPPORT_MAGIC_GATE case SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB: set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x02, 0, 0); break; case SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN: set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x00, 0, 0); break; case SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM: set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x30, 0x00, 0, 0); break; case SENSE_TYPE_MG_WRITE_ERR: set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x00, 0, 0); break; #endif #ifdef SUPPORT_SD_LOCK case SENSE_TYPE_MEDIA_READ_FORBIDDEN: set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x11, 0x13, 0, 0); break; #endif case SENSE_TYPE_NO_SENSE: default: set_sense_data(chip, lun, CUR_ERR, 0, 0, 0, 0, 0, 0); break; } }
static void do_command(omti8621_state *state, const UINT8 cdb[], const UINT16 cdb_length) { UINT8 lun = get_lun(cdb); disk_data *disk = state->disk[lun]; int command_duration = 0; // ms log_command( state, cdb, cdb_length); // default to read status and status is successful completion state->omti_state = OMTI_STATE_STATUS; state->status_port |= OMTI_STATUS_IO | OMTI_STATUS_CD; state->command_status = lun ? OMTI_COMMAND_STATUS_LUN : 0; if (state->mask_port & OMTI_MASK_INTE) { set_interrupt(state, CLEAR_LINE); } if (!disk->image->exists()) { state->command_status |= OMTI_COMMAND_STATUS_ERROR; // no such drive } switch (cdb[0]) { case OMTI_CMD_TEST_DRIVE_READY: // 0x00 if (!disk->image->exists()) { set_sense_data(state, OMTI_SENSE_CODE_DRIVE_NOT_READY, cdb); } break; case OMTI_CMD_RECALIBRATE: // 0x01 break; case OMTI_CMD_REQUEST_SENSE: // 0x03 set_data_transfer(state, state->sense_data, sizeof(state->sense_data)); break; case OMTI_CMD_READ_VERIFY: // 0x05 check_disk_address(state, cdb); break; case OMTI_CMD_FORMAT_TRACK: // 0x06 format_track(state, cdb); break; case OMTI_CMD_FORMAT_BAD_TRACK: // 0x07 state->diskaddr_format_bad_track = get_disk_address(state, cdb); break; case OMTI_CMD_READ: // 0x08 if (check_disk_address(state, cdb)) { // read data from controller read_sectors_from_disk(state, get_disk_address(state, cdb), cdb[4], lun); set_data_transfer(state, state->sector_buffer, OMTI_DISK_SECTOR_SIZE*cdb[4]); } break; case OMTI_CMD_WRITE: // 0x0A log_data(state); if (check_disk_address(state, cdb)) { write_sectors_to_disk(state, get_disk_address(state, cdb), cdb[4], lun); } break; case OMTI_CMD_SEEK: // 0x0B check_disk_address(state, cdb); break; case OMTI_CMD_READ_SECTOR_BUFFER: // 0x0E set_data_transfer(state, state->sector_buffer, OMTI_DISK_SECTOR_SIZE*cdb[4]); break; case OMTI_CMD_WRITE_SECTOR_BUFFER: // 0x0F log_data(state); break; case OMTI_CMD_COPY: // 0x20 if (check_disk_address(state, cdb) && check_disk_address(state, cdb+4)) { // copy sectors copy_sectors (state, get_disk_address(state, cdb+4), get_disk_address(state, cdb), cdb[4], lun); } break; case OMTI_CMD_READ_ESDI_DEFECT_LIST: // 0x37 set_esdi_defect_list(state, get_lun(cdb), cdb[1] & 0x1f); set_data_transfer(state, disk->esdi_defect_list, sizeof(disk->esdi_defect_list)); break; case OMTI_CMD_ASSIGN_ALTERNATE_TRACK: // 0x11 log_data(state); state->alternate_track_address[0] = get_disk_track(state, cdb); state->alternate_track_address[1] = get_disk_track(state, state->alternate_track_buffer-1);; break; case OMTI_CMD_READ_DATA_TO_BUFFER: // 0x1E if (check_disk_address(state, cdb)) { // read data from controller read_sectors_from_disk (state, get_disk_address(state, cdb), cdb[4], lun); // Domain/OS doesn't expect zero access time command_duration += 1; // 1 ms is enough, average time would be 30 ms) } break; case OMTI_CMD_WRITE_DATA_FROM_BUFFER: // 0x1F log_data(state); if (check_disk_address(state, cdb)) { write_sectors_to_disk(state, get_disk_address(state, cdb), cdb[4], lun); } break; case OMTI_CMD_RAM_DIAGNOSTICS: // 0xE0 break; case OMTI_CMD_CONTROLLER_INT_DIAGNOSTIC: // 0xE4 break; case OMTI_CMD_READ_LONG: // 0xE5 if (check_disk_address(state, cdb)) { // read data from controller read_sectors_from_disk(state, get_disk_address(state, cdb), cdb[4], lun); set_data_transfer(state, state->sector_buffer, OMTI_DISK_SECTOR_SIZE+6); } break; case OMTI_CMD_WRITE_LONG: // 0xE6 log_data(state); if (check_disk_address(state, cdb)) { UINT32 diskaddr = get_disk_address(state, cdb); write_sectors_to_disk(state, diskaddr, cdb[4], lun); // this will spoil the ECC code state->diskaddr_ecc_error = diskaddr; } break; case OMTI_CMD_READ_CONFIGURATION: // 0xEC set_configuration_data(state, get_lun(cdb)); set_data_transfer(state, disk->config_data, sizeof(disk->config_data)); break; case OMTI_CMD_INVALID_COMMAND: // 0xFF set_sense_data(state, OMTI_SENSE_CODE_INVALID_COMMAND, cdb); state->command_status |= OMTI_COMMAND_STATUS_ERROR; break; default: LOG(("do_command: UNEXPECTED command %02x",cdb[0])); set_sense_data(state, OMTI_SENSE_CODE_INVALID_COMMAND, cdb); state->command_status |= OMTI_COMMAND_STATUS_ERROR; break; } if (state->mask_port & OMTI_MASK_INTE) { // if (state->omti_state != OMTI_STATE_STATUS) { // LOG(("do_command: UNEXPECTED omti_state %02x",state->omti_state)); // } state->status_port |= OMTI_STATUS_IREQ; if (command_duration == 0) { set_interrupt(state, ASSERT_LINE); } else { // FIXME: should delay state->omti_state and state->status_port as well state->device->machine().scheduler().timer_set(attotime::from_msec(command_duration), FUNC(set_interrupt_caba), 0, state); } } }
void show_serial_number(struct sg_io_hdr *hdr) { unsigned char *buffer = hdr->dxferp; int i; printf("serial number: "); for (i=0x80, } #endif #define SENSE_LEN 32 #define BLOCK_LEN 1 unsigned char sense_buffer[SENSE_LEN]; unsigned char data_buffer[BLOCK_LEN*256]; void test_execute_Inquiry(char * path, int evpd, int page_code) { struct sg_io_hdr * p_hdr = init_io_hdr(); set_xfer_data(p_hdr, data_buffer, BLOCK_LEN*256); set_sense_data(p_hdr, sense_buffer, SENSE_LEN); int status = 0; int fd = open(path, O_RDWR); if (fd>0) { status = execute_Inquiry(fd, page_code, evpd, p_hdr); printf("the return status is %d\n", status); if (status!=0) { show_sense_buffer(p_hdr); } else{ show_vendor(p_hdr); show_product(p_hdr); show_product_rev(p_hdr); show_xfer_data(p_hdr); } } else { printf("failed to open sg file %s\n", path); } close(fd); destroy_io_hdr(p_hdr); } void test_cmds(char *path, int evpd, int page_code) { struct sg_io_hdr * p_hdr = init_io_hdr(); set_xfer_data(p_hdr, data_buffer, BLOCK_LEN*256); set_sense_data(p_hdr, sense_buffer, SENSE_LEN); int status = 0; int fd = open(path, O_RDWR); if (fd>0) { status = execute_Inquiry(fd, page_code, evpd, p_hdr); printf("the return status is %d\n", status); //show_sense_buffer(p_hdr); show_xfer_data(p_hdr); } else { printf("failed to open sg file %s\n", path); } close(fd); destroy_io_hdr(p_hdr); } void get_rpm(char *path, int evpd, int page_code) { struct sg_io_hdr * p_hdr = init_io_hdr(); set_xfer_data(p_hdr, data_buffer, BLOCK_LEN*256); set_sense_data(p_hdr, sense_buffer, SENSE_LEN); int status = 0; unsigned char *xfer; int pdt, rpm; int fd = open(path, O_RDWR); if (fd>0) { status = execute_Inquiry(fd, page_code, evpd, p_hdr); printf("the return status is %d\n", status); //show_sense_buffer(p_hdr); //show_xfer_data(p_hdr); // ๅ่ไปฃ็ sg3_utils: sg_vpd.c : decode_b1_vpd() xfer = p_hdr->dxferp; pdt = (int)xfer[0]; switch (pdt) { case 0: if (p_hdr->dxfer_len < 64) { printf("xfer is too short!\n"); } else { rpm = (xfer[4]<<8) | xfer[5]; printf("rpm of %s: %d rpm\n", path, rpm); } break; default: printf("unknown pdt\n"); break; } } else { printf("failed to open sg file %s\n", path); } close(fd); destroy_io_hdr(p_hdr); } int main(int argc, char * argv[]) { //test_execute_Inquiry(argv[1], 0, 0); //test_cmds(argv[1], 1, 0x86); get_rpm(argv[1], 1, 0xb1); // rpm // tested: // 0x80,0x83 return 0; }