static void format_track(omti8621_state *state, const UINT8 * cdb) { UINT8 lun = get_lun(cdb); UINT32 disk_addr = get_disk_address(state, cdb); UINT32 disk_track = get_disk_track(state, cdb); if (state->diskaddr_ecc_error == disk_addr) { // reset previous ECC error state->diskaddr_ecc_error = 0; } if (state->diskaddr_format_bad_track == disk_track) { // reset previous bad track formatting state->diskaddr_format_bad_track = 0; } if (state->alternate_track_address[0] == disk_track) { // reset source of alternate track address state->alternate_track_address[0] = 0; } if (state->alternate_track_address[1] == disk_track) { // reset alternate track address state->alternate_track_address[1] = 0; } if (check_disk_address(state, cdb) ) { if ((cdb[5] & 0x40) == 0) { memset(state->sector_buffer, 0x6C, OMTI_DISK_SECTOR_SIZE * state->disk[lun]->sectors); } write_sectors_to_disk(state, disk_addr, state->disk[lun]->sectors, lun); } }
void omti8621_device::format_track(const UINT8 * cdb) { UINT8 lun = get_lun(cdb); UINT32 disk_addr = get_disk_address(cdb); UINT32 disk_track = get_disk_track(cdb); if (diskaddr_ecc_error == disk_addr) { // reset previous ECC error diskaddr_ecc_error = 0; } if (diskaddr_format_bad_track == disk_track) { // reset previous bad track formatting diskaddr_format_bad_track = 0; } if (alternate_track_address[0] == disk_track) { // reset source of alternate track address alternate_track_address[0] = 0; } if (alternate_track_address[1] == disk_track) { // reset alternate track address alternate_track_address[1] = 0; } if (check_disk_address(cdb) ) { if ((cdb[5] & 0x40) == 0) { memset(§or_buffer[0], 0x6C, OMTI_DISK_SECTOR_SIZE * our_disks[lun]->m_sectors); } write_sectors_to_disk(disk_addr, our_disks[lun]->m_sectors, lun); } }
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); } } }
UINT32 omti8621_device::get_disk_address(const UINT8 * cdb) { UINT8 lun = get_lun(cdb); UINT16 sector = cdb[2] & 0x3f; return get_disk_track(cdb) * our_disks[lun]->m_sectors + sector; }
UINT32 omti8621_device::get_disk_track(const UINT8 * cdb) { UINT8 lun = get_lun(cdb); UINT16 head = cdb[1] & 0x1f; UINT32 cylinder = cdb[3] + ((cdb[2] & 0xc0) << 2) + ((cdb[1] & 0x80) << 3); return cylinder * our_disks[lun]->m_heads + head; }
int main(int argc,char *argv[]) { int rp, pr, dev; char *cp; char host[49]; char tmpb[CMD_BUF_SIZE]; pname = argv[0]; printf("%s: Compiled %s %s\n",pname,__DATE__,__TIME__); if (argc > 1) dev = strtoul(argv[1],&cp,0); do_open(dev); show_dev(1); bzero((void *) host,49); gethostname(host,48); while (True) { sprintf(prompt,"%s:Icv196.%d[%02d]",host,get_lun(),cmdindx+1); printf("%s",prompt); cmdbuf = &(history[cmdindx][0]); bzero((void *) tmpb,CMD_BUF_SIZE); if (fgets(tmpb,CMD_BUF_SIZE,stdin) == NULL) break; cp = &(tmpb[0]); pr = 0; /* Dont print a history */ rp = 0; /* Dont repeat a command */ while ((*cp == '-') || (*cp == '+') || (*cp == '.') || (*cp == '!')) { pr = 1; /* Print command on */ if (*cp == '!') { cp++; cmdindx = strtoul(cp,&cp,0) -1; if (cmdindx >= HISTORIES) cmdindx = 0; if (cmdindx < 0) cmdindx = HISTORIES -1; rp = 1; break; } if (*cp == '-') { if (--cmdindx < 0) cmdindx = HISTORIES -1; cmdbuf = &(history[cmdindx][0]); } if (*cp == '+') { if (++cmdindx >= HISTORIES) cmdindx = 0; cmdbuf = &(history[cmdindx][0]); } if (*cp == '.') { rp = 1; break; } cp++; } if (pr) { printf("{%s}\t ",cmdbuf); fflush(stdout); if (!rp) continue; } if (!rp) strcpy(cmdbuf,tmpb); bzero((void *) val_bufs,sizeof(val_bufs)); GetAtoms(cmdbuf); DoCmd(0); if ((!rp) && (++cmdindx >= HISTORIES)) cmdindx = 0; } exit(0); }
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); } } }
static UINT32 get_disk_address(const omti8621_state *state, const UINT8 * cdb) { UINT8 lun = get_lun(cdb); UINT16 sector = cdb[2] & 0x3f; return get_disk_track(state, cdb) * state->disk[lun]->sectors + sector; }
static UINT32 get_disk_track(const omti8621_state *state, const UINT8 * cdb) { UINT8 lun = get_lun(cdb); UINT16 head = cdb[1] & 0x1f; UINT32 cylinder = cdb[3] + ((cdb[2] & 0xc0) << 2) + ((cdb[1] & 0x80) << 3); return cylinder * state->disk[lun]->heads + head; }