static struct unix_proto_data *unix_data_alloc(void) { struct unix_proto_data *upd; clr_irq(); for (upd = unix_datas; upd <= last_unix_data; ++upd) { if (!upd->refcnt) { /* unix domain socket not yet in itialised - bgm */ upd->refcnt = -1; set_irq(); upd->socket = NULL; upd->sockaddr_len = 0; upd->sockaddr_un.sun_family = 0; #if 0 upd->buf = NULL; #endif upd->bp_head = upd->bp_tail = 0; upd->inode = NULL; upd->peerupd = NULL; upd->sem = 0; return upd; } } set_irq(); return NULL; }
void wangpc_wdc_device::wangpcbus_aiowc_w(address_space &space, offs_t offset, UINT16 mem_mask, UINT16 data) { if (sad(offset) && ACCESSING_BITS_0_7) { switch (offset & 0x7f) { case 0x02/2: // TODO command register break; case 0xfc/2: device_reset(); break; case 0xfe/2: { bool irq = (m_irq == ASSERT_LINE); bool changed = ((m_option & 0x0e) != (data & 0x0e)); if (irq && changed) set_irq(CLEAR_LINE); m_option = data & 0xff; if (irq && changed) set_irq(ASSERT_LINE); } break; } } }
void ide_controller_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { switch(id) { case TID_DELAYED_INTERRUPT: status &= ~IDE_STATUS_BUSY; set_irq(ASSERT_LINE); break; case TID_DELAYED_INTERRUPT_BUFFER_READY: status &= ~IDE_STATUS_BUSY; status |= IDE_STATUS_BUFFER_READY; set_irq(ASSERT_LINE); break; case TID_RESET_CALLBACK: reset(); break; case TID_SECURITY_ERROR_DONE: /* clear error state */ status &= ~IDE_STATUS_ERROR; status |= IDE_STATUS_DRIVE_READY; break; case TID_READ_SECTOR_DONE_CALLBACK: read_sector_done(); break; case TID_WRITE_SECTOR_DONE_CALLBACK: write_sector_done(); break; } }
void ide_controller_device::write_sector_done() { ide_device_interface *dev = slot[cur_drive]->dev(); int lba = dev->lba_address(), count = 0; /* now do the write */ count = dev->write_sector(lba, buffer); /* by default, mark the buffer ready and the seek complete */ status |= IDE_STATUS_BUFFER_READY; status |= IDE_STATUS_SEEK_COMPLETE; /* and clear the busy adn error flags */ status &= ~IDE_STATUS_ERROR; status &= ~IDE_STATUS_BUSY; /* if we succeeded, advance to the next sector and set the nice bits */ if (count == 1) { /* advance the pointers, unless this is the last sector */ /* Gauntlet: Dark Legacy checks to make sure we stop on the last sector */ if (sector_count != 1) next_sector(); /* clear the error value */ error = IDE_ERROR_NONE; /* signal an interrupt */ if (--sectors_until_int == 0 || sector_count == 1) { sectors_until_int = ((command == IDE_COMMAND_WRITE_MULTIPLE_BLOCK) ? block_count : 1); set_irq(ASSERT_LINE); } /* signal an interrupt if there's more data needed */ if (sector_count > 0) sector_count--; if (sector_count == 0) status &= ~IDE_STATUS_BUFFER_READY; /* keep going for DMA */ if (dma_active && sector_count != 0) { set_dmarq(1); } } /* if we got an error, we need to report it */ else { /* set the error flag and the error */ status |= IDE_STATUS_ERROR; error = IDE_ERROR_BAD_SECTOR; /* signal an interrupt */ set_irq(ASSERT_LINE); } }
void ata_flash_pccard_device::process_command() { m_buffer_size = IDE_DISK_SECTOR_SIZE; switch (m_command) { case IDE_COMMAND_TAITO_GNET_UNLOCK_1: //LOGPRINT(("IDE GNET Unlock 1\n")); m_sector_count = 1; m_status |= IDE_STATUS_DRDY; set_irq(ASSERT_LINE); break; case IDE_COMMAND_TAITO_GNET_UNLOCK_2: //LOGPRINT(("IDE GNET Unlock 2\n")); /* mark the buffer ready */ m_status |= IDE_STATUS_DRQ; set_irq(ASSERT_LINE); break; case IDE_COMMAND_TAITO_GNET_UNLOCK_3: //LOGPRINT(("IDE GNET Unlock 3\n")); /* key check */ if (m_feature == m_key[0] && m_sector_count == m_key[1] && m_sector_number == m_key[2] && m_cylinder_low == m_key[3] && m_cylinder_high == m_key[4]) { m_gnetreadlock = 0; } else { m_status &= ~IDE_STATUS_DRDY; } set_irq(ASSERT_LINE); break; default: if (m_gnetreadlock) { m_status |= IDE_STATUS_ERR; m_error = IDE_ERROR_NONE; m_status &= ~IDE_STATUS_DRDY; break; } ide_hdd_device::process_command(); break; } }
void ata_mass_storage_device::finished_command() { switch (m_command) { case IDE_COMMAND_IDENTIFY_DEVICE: if (m_can_identify_device) { for( int w = 0; w < 256; w++ ) { m_buffer[w * 2] = m_identify_buffer[ w ] & 0xff; m_buffer[(w * 2) + 1] = m_identify_buffer[ w ] >> 8; } m_status |= IDE_STATUS_DRQ; } else { m_status |= IDE_STATUS_ERR; m_error = IDE_ERROR_NONE; } set_irq(ASSERT_LINE); break; case IDE_COMMAND_SET_CONFIG: set_geometry(m_sector_count,(m_device_head & IDE_DEVICE_HEAD_HS) + 1); set_irq(ASSERT_LINE); break; case IDE_COMMAND_READ_SECTORS: case IDE_COMMAND_READ_SECTORS_NORETRY: case IDE_COMMAND_READ_MULTIPLE: case IDE_COMMAND_VERIFY_SECTORS: case IDE_COMMAND_VERIFY_SECTORS_NORETRY: case IDE_COMMAND_READ_DMA: finished_read(); break; case IDE_COMMAND_WRITE_SECTORS: case IDE_COMMAND_WRITE_SECTORS_NORETRY: case IDE_COMMAND_WRITE_MULTIPLE: case IDE_COMMAND_WRITE_DMA: finished_write(); break; case IDE_COMMAND_RECALIBRATE: set_irq(ASSERT_LINE); break; default: ata_hle_device::finished_command(); break; }
static void run_timer_list(void) { register struct timer_list *timer; clr_irq(); while ((timer = tl_list.tl_next) && timer->tl_expires <= jiffies) { detach_timer(timer); set_irq(); timer->tl_function(timer->tl_data); clr_irq(); } set_irq(); }
void ym3802_device::transmit_clk() { if(m_reg[REG_TCR] & 0x01) // Tx Enable { if(!m_tx_fifo.empty()) { if (is_transmit_register_empty()) { transmit_register_setup(m_tx_fifo.front()); // start to send first byte in FIFO m_tx_fifo.pop(); // and remove it from the FIFO if(m_tx_fifo.empty()) set_irq(IRQ_FIFOTX_EMPTY); } } /* if diserial has bits to send, make them so */ if (!is_transmit_register_empty()) { uint8_t data = transmit_register_get_data_bit(); m_tx_busy = true; m_txd_handler(data); } if (m_tx_fifo.empty() && is_transmit_register_empty()) m_tx_busy = false; } }
BOOL init_harddisk() { set_irq(IRQ_HD, (u32)&do_harddisk_read); /* 设置中断处理程序 */ enable_irq(IRQ_HD); /* 通知8259A开启硬盘中断 */ return TRUE; }
UINT16 wangpc_wdc_device::wangpcbus_iorc_r(address_space &space, offs_t offset, UINT16 mem_mask) { UINT16 data = 0xffff; if (sad(offset)) { switch (offset & 0x7f) { case 0x00/2: data = m_status; break; case 0x02/2: // TODO operation status register break; case 0x04/2: set_irq(CLEAR_LINE); break; case 0xfe/2: data = 0xff00 | (m_irq << 7) | OPTION_ID; break; } } return data; }
void wangpc_wdc_device::device_reset() { m_status = 0; m_option = 0; set_irq(CLEAR_LINE); }
void el2_3c503_device::eop_w(int state) { if((m_regs.streg & 0x08) && (state == ASSERT_LINE)) { m_regs.streg |= 0x10; m_regs.streg &= ~0x08; if(!(m_regs.gacfr & 0x40)) set_irq(ASSERT_LINE); } }
void init_keyboard(void) { set_irq(IRQ_KEYBOARD, (u32)&do_keyboard); /* 设置中断处理程序 */ enable_irq(IRQ_KEYBOARD); /* 通知8259A开启键盘中断 */ init_queue(&kb_queue); /* 初始化缓存区队列 */ b_shift_l = FALSE; b_shift_r = FALSE; b_leading_e0 = FALSE; }
void UPD765A::reset() { shift_to_idle(); // CANCEL_EVENT(); phase_id = drq_id = lost_id = result7_id = -1; seek_id[0] = seek_id[1] = seek_id[2] = seek_id[3] = -1; set_irq(false); set_drq(false); }
void UPD765A::close_disk(int drv) { if(drv < MAX_DRIVE && disk[drv]->inserted) { disk[drv]->close(); #ifdef _FDC_DEBUG_LOG emu->out_debug_log("FDC: Disk Ejected (Drive=%d)\n", drv); #endif if(raise_irq_when_media_changed) { fdc[drv].result = (drv & DRIVE_MASK) | ST0_AI; set_irq(true); } } }
void UPD765A::open_disk(int drv, _TCHAR path[], int bank) { if(drv < MAX_DRIVE) { disk[drv]->open(path, bank); if(disk[drv]->changed) { #ifdef _FDC_DEBUG_LOG emu->out_debug_log("FDC: Disk Changed (Drive=%d)\n", drv); #endif if(raise_irq_when_media_changed) { fdc[drv].result = (drv & DRIVE_MASK) | ST0_AI; set_irq(true); } } } }
void ym3802_device::midi_clk() { if(m_midi_counter_base > 1) // counter is not guaranteed to work if set to 0 or 1. { if(m_midi_counter == 0) { m_midi_counter = m_midi_counter_base; // reload timer if(m_reg[REG_IMR] & 0x08) // if IRQ1 is set to MIDI clock detect set_irq(IRQ_MIDI_CLK); if(m_click_counter_base != 0) { m_click_counter--; if(m_click_counter == 0) { m_click_counter = m_click_counter_base; if(!(m_reg[REG_IMR] & 0x08)) // if IRQ1 is set to click counter set_irq(IRQ_CLICK); } } } else m_midi_counter--; } }
void UPD765A::shift_to_result7_event() { #ifdef UPD765A_NO_ST1_EN_OR_FOR_RESULT7 // for NEC PC-9801 (XANADU) result &= ~(ST1_EN | ST1_OR); #endif buffer[0] = (result & 0xf8) | (hdue & 7); buffer[1] = uint8(result >> 8); buffer[2] = uint8(result >> 16); buffer[3] = id[0]; buffer[4] = id[1]; buffer[5] = id[2]; buffer[6] = id[3]; set_irq(true); shift_to_result(7); }
void device_setup(void) { register struct gendisk *p; chr_dev_init(); blk_dev_init(); set_irq(); for (p = gendisk_head; p; p = p->next) setup_dev(p); #ifdef CONFIG_BLK_DEV_RAM rd_load(); #endif }
UINT16 wangpc_mvc_device::wangpcbus_iorc_r(address_space &space, offs_t offset, UINT16 mem_mask) { UINT16 data = 0xffff; if (sad(offset)) { switch (offset & 0x7f) { case 0xfe/2: data = 0xff00 | (m_irq << 7) | OPTION_ID; set_irq(CLEAR_LINE); break; } } return data; }
void cdp1879_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { advance_seconds(); // comparator IRQ bool new_state = true; for (int i = R_CNT_SECONDS; i <= R_CNT_HOURS; i++) { if(m_regs[i] != m_regs[i + 6]) { new_state = false; break; } } if (!m_comparator_state && new_state) // positive-edge-triggered set_irq(7); m_comparator_state = new_state; }
void UPD765A::seek_event(int drv) { int trk = fdc[drv].track; if(drv >= MAX_DRIVE) { fdc[drv].result = (drv & DRIVE_MASK) | ST0_SE | ST0_NR | ST0_AT; } else if(force_ready || disk[drv]->inserted) { fdc[drv].result = (drv & DRIVE_MASK) | ST0_SE; } else { #ifdef UPD765A_NO_ST0_AT_FOR_SEEK // for NEC PC-100 fdc[drv].result = (drv & DRIVE_MASK) | ST0_SE | ST0_NR; #else fdc[drv].result = (drv & DRIVE_MASK) | ST0_SE | ST0_NR | ST0_AT; #endif } set_irq(true); seekstat &= ~(1 << drv); // reset dsch flag disk[drv]->changed = false; }
void UPD765A::initialize() { // initialize d88 handler for(int i = 0; i < 4; i++) { disk[i] = new DISK(emu); } // initialize fdc memset(fdc, 0, sizeof(fdc)); memset(buffer, 0, sizeof(buffer)); phase = prevphase = PHASE_IDLE; status = S_RQM; seekstat = 0; bufptr = buffer; // temporary phase_id = drq_id = lost_id = result7_id = -1; seek_id[0] = seek_id[1] = seek_id[2] = seek_id[3] = -1; no_dma_mode = false; motor_on = false; // motor off force_ready = false; reset_signal = true; irq_masked = drq_masked = false; set_irq(false); set_drq(false); #ifdef UPD765A_EXT_DRVSEL hdu = 0; #else set_hdu(0); #endif // index hole event if(outputs_index.count) { register_event(this, EVENT_INDEX, 4, true, NULL); prev_index = false; } }
void wangpc_mvc_device::device_reset() { m_option = 0; set_irq(CLEAR_LINE); }
int wait_for_keypress(void) { set_irq(); return chq_getch(&ttys[0].inq, 0, 1); }
void gf1_device::update_volume_ramps() { int x; for(x=0;x<32;x++) { if(!(m_voice[x].vol_ramp_ctrl & 0x01)) // if ramping is enabled { m_voice[x].vol_count++; if(m_voice[x].vol_count % volume_ramp_table[(m_voice[x].vol_ramp_rate & 0xc0)>>6] == 0) { // increase/decrease volume if(m_voice[x].vol_ramp_ctrl & 0x40) { //m_voice[x].current_vol = (m_voice[x].current_vol & 0xf000) | ((m_voice[x].current_vol & 0x0ff0) + ((m_voice[x].vol_ramp_rate & 0x0f)<<8)); m_voice[x].current_vol -= ((m_voice[x].vol_ramp_rate & 0x3f) << 4); if(m_voice[x].current_vol <= (m_voice[x].vol_ramp_start << 8)) // end of ramp? { if(m_voice[x].vol_ramp_ctrl & 0x08) { if(m_voice[x].vol_ramp_ctrl & 0x10) { m_voice[x].vol_ramp_ctrl &= ~0x40; // change direction and continue m_voice[x].current_vol = (m_voice[x].vol_ramp_start << 8); } else m_voice[x].current_vol = (m_voice[x].vol_ramp_end << 8); } else { m_voice[x].vol_ramp_ctrl |= 0x01; // stop volume ramp m_voice[x].current_vol = (m_voice[x].vol_ramp_start << 8); } if(m_voice[x].vol_ramp_ctrl & 0x20) set_irq(IRQ_VOLUME_RAMP,x); } } else { //m_voice[x].current_vol = (m_voice[x].current_vol & 0xf000) | ((m_voice[x].current_vol & 0x0ff0) - ((m_voice[x].vol_ramp_rate & 0x0f)<<8)); m_voice[x].current_vol += ((m_voice[x].vol_ramp_rate & 0x3f) << 4); if(m_voice[x].current_vol >= (m_voice[x].vol_ramp_end << 8)) // end of ramp? { if(m_voice[x].vol_ramp_ctrl & 0x08) { if(m_voice[x].vol_ramp_ctrl & 0x10) { m_voice[x].vol_ramp_ctrl |= 0x40; // change direction and continue m_voice[x].current_vol = (m_voice[x].vol_ramp_end << 8); } else m_voice[x].current_vol = (m_voice[x].vol_ramp_start << 8); } else { m_voice[x].vol_ramp_ctrl |= 0x01; // stop volume ramp m_voice[x].current_vol = (m_voice[x].vol_ramp_end << 8); } if(m_voice[x].vol_ramp_ctrl & 0x20) set_irq(IRQ_VOLUME_RAMP,x); } } } } }
int wait_for_keypress(void) { set_irq(); return chq_wait_rd(&ttys[0].inq, 0); }
void ide_controller_device::handle_command(UINT8 _command) { UINT8 key[5]; ide_device_interface *dev = slot[cur_drive]->dev(); /* implicitly clear interrupts & dmarq here */ set_irq(CLEAR_LINE); set_dmarq(0); command = _command; switch (command) { case IDE_COMMAND_READ_MULTIPLE: case IDE_COMMAND_READ_MULTIPLE_NORETRY: LOGPRINT(("IDE Read multiple: C=%d H=%d S=%d LBA=%d count=%d\n", dev->cur_cylinder, dev->cur_head, dev->cur_sector, dev->lba_address(), sector_count)); /* reset the buffer */ buffer_offset = 0; sectors_until_int = 1; dma_active = 0; verify_only = 0; /* start the read going */ read_first_sector(); break; case IDE_COMMAND_READ_MULTIPLE_BLOCK: LOGPRINT(("IDE Read multiple block: C=%d H=%d S=%d LBA=%d count=%d\n", dev->cur_cylinder, dev->cur_head, dev->cur_sector, dev->lba_address(), sector_count)); /* reset the buffer */ buffer_offset = 0; sectors_until_int = 1; dma_active = 0; verify_only = 0; /* start the read going */ read_first_sector(); break; case IDE_COMMAND_VERIFY_MULTIPLE: case IDE_COMMAND_VERIFY_NORETRY: LOGPRINT(("IDE Read verify multiple with/without retries: C=%d H=%d S=%d LBA=%d count=%d\n", dev->cur_cylinder, dev->cur_head, dev->cur_sector, dev->lba_address(), sector_count)); /* reset the buffer */ buffer_offset = 0; sectors_until_int = 1; dma_active = 0; verify_only = 1; /* start the read going */ read_first_sector(); break; case IDE_COMMAND_READ_DMA: LOGPRINT(("IDE Read multiple DMA: C=%d H=%d S=%d LBA=%d count=%d\n", dev->cur_cylinder, dev->cur_head, dev->cur_sector, dev->lba_address(), sector_count)); /* reset the buffer */ buffer_offset = 0; sectors_until_int = sector_count; dma_active = 1; verify_only = 0; /* start the read going */ read_first_sector(); break; case IDE_COMMAND_WRITE_MULTIPLE: case IDE_COMMAND_WRITE_MULTIPLE_NORETRY: LOGPRINT(("IDE Write multiple: C=%d H=%d S=%d LBA=%d count=%d\n", dev->cur_cylinder, dev->cur_head, dev->cur_sector, dev->lba_address(), sector_count)); /* reset the buffer */ buffer_offset = 0; sectors_until_int = 1; dma_active = 0; /* mark the buffer ready */ status |= IDE_STATUS_BUFFER_READY; break; case IDE_COMMAND_WRITE_MULTIPLE_BLOCK: LOGPRINT(("IDE Write multiple block: C=%d H=%d S=%d LBA=%d count=%d\n", dev->cur_cylinder, dev->cur_head, dev->cur_sector, dev->lba_address(), sector_count)); /* reset the buffer */ buffer_offset = 0; sectors_until_int = 1; dma_active = 0; /* mark the buffer ready */ status |= IDE_STATUS_BUFFER_READY; break; case IDE_COMMAND_WRITE_DMA: LOGPRINT(("IDE Write multiple DMA: C=%d H=%d S=%d LBA=%d count=%d\n", dev->cur_cylinder, dev->cur_head, dev->cur_sector, dev->lba_address(), sector_count)); /* reset the buffer */ buffer_offset = 0; sectors_until_int = sector_count; dma_active = 1; /* start the read going */ set_dmarq(1); break; case IDE_COMMAND_SECURITY_UNLOCK: LOGPRINT(("IDE Security Unlock\n")); /* reset the buffer */ buffer_offset = 0; sectors_until_int = 0; dma_active = 0; /* mark the buffer ready */ status |= IDE_STATUS_BUFFER_READY; set_irq(ASSERT_LINE); break; case IDE_COMMAND_GET_INFO: LOGPRINT(("IDE Read features\n")); /* reset the buffer */ buffer_offset = 0; sector_count = 1; /* build the features page */ memcpy(buffer, slot[cur_drive]->dev()->get_features(), sizeof(buffer)); /* indicate everything is ready */ status |= IDE_STATUS_BUFFER_READY; status |= IDE_STATUS_SEEK_COMPLETE; status |= IDE_STATUS_DRIVE_READY; /* and clear the busy adn error flags */ status &= ~IDE_STATUS_ERROR; status &= ~IDE_STATUS_BUSY; /* clear the error too */ error = IDE_ERROR_NONE; /* signal an interrupt */ signal_delayed_interrupt(MINIMUM_COMMAND_TIME, 1); break; case IDE_COMMAND_DIAGNOSTIC: error = IDE_ERROR_DEFAULT; /* signal an interrupt */ signal_delayed_interrupt(MINIMUM_COMMAND_TIME, 0); break; case IDE_COMMAND_RECALIBRATE: /* clear the error too */ error = IDE_ERROR_NONE; /* signal an interrupt */ signal_delayed_interrupt(MINIMUM_COMMAND_TIME, 0); break; case IDE_COMMAND_IDLE: /* clear the error too */ error = IDE_ERROR_NONE; /* for timeout disabled value is 0 */ sector_count = 0; /* signal an interrupt */ set_irq(ASSERT_LINE); break; case IDE_COMMAND_SET_CONFIG: LOGPRINT(("IDE Set configuration (%d heads, %d sectors)\n", dev->cur_head + 1, sector_count)); status &= ~IDE_STATUS_ERROR; error = IDE_ERROR_NONE; dev->set_geometry(sector_count,dev->cur_head + 1); /* signal an interrupt */ signal_delayed_interrupt(MINIMUM_COMMAND_TIME, 0); break; case IDE_COMMAND_UNKNOWN_F9: /* only used by Killer Instinct AFAICT */ LOGPRINT(("IDE unknown command (F9)\n")); /* signal an interrupt */ set_irq(ASSERT_LINE); break; case IDE_COMMAND_SET_FEATURES: LOGPRINT(("IDE Set features (%02X %02X %02X %02X %02X)\n", precomp_offset, sector_count & 0xff, dev->cur_sector, dev->cur_cylinder & 0xff, dev->cur_cylinder >> 8)); /* signal an interrupt */ signal_delayed_interrupt(MINIMUM_COMMAND_TIME, 0); break; case IDE_COMMAND_SET_BLOCK_COUNT: LOGPRINT(("IDE Set block count (%02X)\n", sector_count)); block_count = sector_count; // judge dredd wants 'drive ready' on this command status |= IDE_STATUS_DRIVE_READY; /* signal an interrupt */ set_irq(ASSERT_LINE); break; case IDE_COMMAND_TAITO_GNET_UNLOCK_1: LOGPRINT(("IDE GNET Unlock 1\n")); sector_count = 1; status |= IDE_STATUS_DRIVE_READY; status &= ~IDE_STATUS_ERROR; set_irq(ASSERT_LINE); break; case IDE_COMMAND_TAITO_GNET_UNLOCK_2: LOGPRINT(("IDE GNET Unlock 2\n")); /* reset the buffer */ buffer_offset = 0; sectors_until_int = 0; dma_active = 0; /* mark the buffer ready */ status |= IDE_STATUS_BUFFER_READY; set_irq(ASSERT_LINE); break; case IDE_COMMAND_TAITO_GNET_UNLOCK_3: LOGPRINT(("IDE GNET Unlock 3\n")); /* key check */ dev->read_key(key); if ((precomp_offset == key[0]) && (sector_count == key[1]) && (dev->cur_sector == key[2]) && (dev->cur_cylinder == (((UINT16)key[4]<<8)|key[3]))) { gnetreadlock= 0; } /* update flags */ status |= IDE_STATUS_DRIVE_READY; status &= ~IDE_STATUS_ERROR; set_irq(ASSERT_LINE); break; case IDE_COMMAND_SEEK: /* cur_cylinder, cur_sector and cur_head are all already set in this case so no need so that implements actual seek */ /* clear the error too */ error = IDE_ERROR_NONE; /* for timeout disabled value is 0 */ sector_count = 0; /* signal an interrupt */ set_irq(ASSERT_LINE); break; default: LOGPRINT(("IDE unknown command (%02X)\n", command)); status |= IDE_STATUS_ERROR; error = IDE_ERROR_UNKNOWN_COMMAND; set_irq(ASSERT_LINE); //debugger_break(device->machine()); break; } }
void ide_controller_device::read_sector_done() { ide_device_interface *dev = slot[cur_drive]->dev(); int lba = dev->lba_address(), count = 0; /* GNET readlock check */ if (gnetreadlock) { status &= ~IDE_STATUS_ERROR; status &= ~IDE_STATUS_BUSY; return; } /* now do the read */ count = dev->read_sector(lba, buffer); /* by default, mark the buffer ready and the seek complete */ if (!verify_only) status |= IDE_STATUS_BUFFER_READY; status |= IDE_STATUS_SEEK_COMPLETE; /* and clear the busy and error flags */ status &= ~IDE_STATUS_ERROR; status &= ~IDE_STATUS_BUSY; /* if we succeeded, advance to the next sector and set the nice bits */ if (count == 1) { /* advance the pointers, unless this is the last sector */ /* Gauntlet: Dark Legacy checks to make sure we stop on the last sector */ if (sector_count != 1) next_sector(); /* clear the error value */ error = IDE_ERROR_NONE; /* signal an interrupt */ if (!verify_only) sectors_until_int--; if (sectors_until_int == 0 || sector_count == 1) { sectors_until_int = ((command == IDE_COMMAND_READ_MULTIPLE_BLOCK) ? block_count : 1); set_irq(ASSERT_LINE); } /* handle DMA */ if (dma_active) set_dmarq(1); /* if we're just verifying we can read the next sector */ if (verify_only) read_buffer_empty(); } /* if we got an error, we need to report it */ else { /* set the error flag and the error */ status |= IDE_STATUS_ERROR; error = IDE_ERROR_BAD_SECTOR; /* signal an interrupt */ set_irq(ASSERT_LINE); } }
Virtio::Virtio(hw::PCI_Device& dev) : _pcidev(dev), _virtio_device_id(dev.product_id() + 0x1040) { INFO("Virtio","Attaching to PCI addr 0x%x",_pcidev.pci_addr()); /** PCI Device discovery. Virtio std. §4.1.2 */ /** Match vendor ID and Device ID : §4.1.2.2 */ if (_pcidev.vendor_id() != hw::PCI_Device::VENDOR_VIRTIO) panic("This is not a Virtio device"); CHECK(true, "Vendor ID is VIRTIO"); bool _STD_ID = _virtio_device_id >= 0x1040 and _virtio_device_id < 0x107f; bool _LEGACY_ID = _pcidev.product_id() >= 0x1000 and _pcidev.product_id() <= 0x103f; CHECK(_STD_ID or _LEGACY_ID, "Device ID 0x%x is in a valid range (%s)", _pcidev.product_id(), _STD_ID ? ">= Virtio 1.0" : (_LEGACY_ID ? "Virtio LEGACY" : "INVALID")); assert(_STD_ID or _LEGACY_ID); /** Match Device revision ID. Virtio Std. §4.1.2.2 */ bool rev_id_ok = ((_LEGACY_ID and _pcidev.rev_id() == 0) or (_STD_ID and _pcidev.rev_id() > 0)); CHECK(rev_id_ok and version_supported(_pcidev.rev_id()), "Device Revision ID (0x%x) supported", _pcidev.rev_id()); assert(rev_id_ok); // We'll try to continue if it's newer than supported. // Probe PCI resources and fetch I/O-base for device _pcidev.probe_resources(); _iobase=_pcidev.iobase(); CHECK(_iobase, "Unit has valid I/O base (0x%x)", _iobase); /** Device initialization. Virtio Std. v.1, sect. 3.1: */ // 1. Reset device reset(); INFO2("[*] Reset device"); // 2. Set ACKNOWLEGE status bit, and // 3. Set DRIVER status bit hw::outp(_iobase + VIRTIO_PCI_STATUS, hw::inp(_iobase + VIRTIO_PCI_STATUS) | VIRTIO_CONFIG_S_ACKNOWLEDGE | VIRTIO_CONFIG_S_DRIVER); // THE REMAINING STEPS MUST BE DONE IN A SUBCLASS // 4. Negotiate features (Read, write, read) // => In the subclass (i.e. Only the Nic driver knows if it wants a mac) // 5. @todo IF >= Virtio 1.0, set FEATURES_OK status bit // 6. @todo IF >= Virtio 1.0, Re-read Device Status to ensure features are OK // 7. Device specifig setup. // Where the standard isn't clear, we'll do our best to separate work // between this class and subclasses. //Fetch IRQ from PCI resource set_irq(); CHECK(_irq, "Unit has IRQ %i", _irq); INFO("Virtio","Enabling IRQ Handler"); enable_irq_handler(); INFO("Virtio", "Initialization complete"); // It would be nice if we new that all queues were the same size. // Then we could pass this size on to the device-specific constructor // But, it seems there aren't any guarantees in the standard. // @note this is "the Legacy interface" according to Virtio std. 4.1.4.8. // uint32_t queue_size = hw::inpd(_iobase + 0x0C); /* printf(queue_size > 0 and queue_size != PCI_WTF ? "\t [x] Queue Size : 0x%lx \n" : "\t [ ] No qeuue Size? : 0x%lx \n" ,queue_size); */ }