From caed880216f3572b5f33691f46c934e1d0faccb2 Mon Sep 17 00:00:00 2001 From: bellard Date: Sun, 14 Mar 2004 21:40:43 +0000 Subject: removable device support - io port API change git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@659 c046a42c-6fe2-441c-8c8c-71466251a162 --- hw/fdc.c | 134 +++++++++++++++++++++++-------------------------- hw/ide.c | 170 +++++++++++++++++++++++++++++++++------------------------------ 2 files changed, 151 insertions(+), 153 deletions(-) diff --git a/hw/fdc.c b/hw/fdc.c index 819e2f7b39..d3c885401f 100644 --- a/hw/fdc.c +++ b/hw/fdc.c @@ -85,12 +85,14 @@ typedef struct fdrive_t { uint8_t ro; /* Is read-only */ } fdrive_t; -static void fd_init (fdrive_t *drv) +static void fd_init (fdrive_t *drv, BlockDriverState *bs) { /* Drive */ - drv->bs = NULL; -// drv->drive = FDRIVE_DRV_288; - drv->drive = FDRIVE_DRV_144; + drv->bs = bs; + if (bs) + drv->drive = FDRIVE_DRV_144; + else + drv->drive = FDRIVE_DRV_NONE; drv->motor = 0; drv->perpendicular = 0; drv->rv = 0; @@ -157,13 +159,17 @@ static void fd_recalibrate (fdrive_t *drv) } /* Revalidate a disk drive after a disk change */ -static void fd_revalidate (fdrive_t *drv, int ro) +static void fd_revalidate (fdrive_t *drv) { int64_t nb_sectors; FLOPPY_DPRINTF("revalidate\n"); drv->rv = 0; - if (drv->bs != NULL) { + /* if no drive present, cannot do more */ + if (!drv->bs) + return; + + if (bdrv_is_inserted(drv->bs)) { bdrv_get_geometry(drv->bs, &nb_sectors); #if 1 if (nb_sectors > 2880) @@ -186,14 +192,21 @@ static void fd_revalidate (fdrive_t *drv, int ro) drv->max_track = 80; #endif } + drv->ro = bdrv_is_read_only(drv->bs); } else { drv->disk = FDRIVE_DISK_NONE; drv->last_sect = 1; /* Avoid eventual divide by 0 bugs */ + drv->ro = 0; } - drv->ro = ro; drv->rv = 1; } +static void fd_change_cb (void *opaque) +{ + fdrive_t *drv = opaque; + fd_revalidate(drv); +} + /* Motor control */ static void fd_start (fdrive_t *drv) { @@ -220,16 +233,16 @@ static void fdctrl_reset_fifo (void); static int fdctrl_transfer_handler (void *opaque, target_ulong addr, int size); static void fdctrl_raise_irq (uint8_t status); -static uint32_t fdctrl_read_statusB (CPUState *env, uint32_t reg); -static uint32_t fdctrl_read_dor (CPUState *env, uint32_t reg); -static void fdctrl_write_dor (CPUState *env, uint32_t reg, uint32_t value); -static uint32_t fdctrl_read_tape (CPUState *env, uint32_t reg); -static void fdctrl_write_tape (CPUState *env, uint32_t reg, uint32_t value); -static uint32_t fdctrl_read_main_status (CPUState *env, uint32_t reg); -static void fdctrl_write_rate (CPUState *env, uint32_t reg, uint32_t value); -static uint32_t fdctrl_read_data (CPUState *env, uint32_t reg); -static void fdctrl_write_data (CPUState *env, uint32_t reg, uint32_t value); -static uint32_t fdctrl_read_dir (CPUState *env, uint32_t reg); +static uint32_t fdctrl_read_statusB (void *opaque, uint32_t reg); +static uint32_t fdctrl_read_dor (void *opaque, uint32_t reg); +static void fdctrl_write_dor (void *opaque, uint32_t reg, uint32_t value); +static uint32_t fdctrl_read_tape (void *opaque, uint32_t reg); +static void fdctrl_write_tape (void *opaque, uint32_t reg, uint32_t value); +static uint32_t fdctrl_read_main_status (void *opaque, uint32_t reg); +static void fdctrl_write_rate (void *opaque, uint32_t reg, uint32_t value); +static uint32_t fdctrl_read_data (void *opaque, uint32_t reg); +static void fdctrl_write_data (void *opaque, uint32_t reg, uint32_t value); +static uint32_t fdctrl_read_dir (void *opaque, uint32_t reg); enum { FD_CTRL_ACTIVE = 0x01, @@ -295,7 +308,7 @@ typedef struct fdctrl_t { static fdctrl_t fdctrl; void fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped, uint32_t base, - char boot_device) + BlockDriverState **fds) { // int io_mem; int i; @@ -312,8 +325,11 @@ void fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped, uint32_t base, } else { fdctrl.dma_en = 0; } - for (i = 0; i < MAX_FD; i++) - fd_init(&fdctrl.drives[i]); + for (i = 0; i < MAX_FD; i++) { + fd_init(&fdctrl.drives[i], fds[i]); + if (fds[i]) + bdrv_set_change_cb(fds[i], fd_change_cb, &fdctrl.drives[i]); + } fdctrl_reset(0); fdctrl.state = FD_CTRL_ACTIVE; if (mem_mapped) { @@ -323,51 +339,27 @@ void fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped, uint32_t base, cpu_register_physical_memory(base, 0x08, io_mem); #endif } else { - register_ioport_read(base + 0x01, 1, fdctrl_read_statusB, 1); - register_ioport_read(base + 0x02, 1, fdctrl_read_dor, 1); - register_ioport_write(base + 0x02, 1, fdctrl_write_dor, 1); - register_ioport_read(base + 0x03, 1, fdctrl_read_tape, 1); - register_ioport_write(base + 0x03, 1, fdctrl_write_tape, 1); - register_ioport_read(base + 0x04, 1, fdctrl_read_main_status, 1); - register_ioport_write(base + 0x04, 1, fdctrl_write_rate, 1); - register_ioport_read(base + 0x05, 1, fdctrl_read_data, 1); - register_ioport_write(base + 0x05, 1, fdctrl_write_data, 1); - register_ioport_read(base + 0x07, 1, fdctrl_read_dir, 1); + register_ioport_read(base + 0x01, 1, 1, fdctrl_read_statusB, NULL); + register_ioport_read(base + 0x02, 1, 1, fdctrl_read_dor, NULL); + register_ioport_write(base + 0x02, 1, 1, fdctrl_write_dor, NULL); + register_ioport_read(base + 0x03, 1, 1, fdctrl_read_tape, NULL); + register_ioport_write(base + 0x03, 1, 1, fdctrl_write_tape, NULL); + register_ioport_read(base + 0x04, 1, 1, fdctrl_read_main_status, NULL); + register_ioport_write(base + 0x04, 1, 1, fdctrl_write_rate, NULL); + register_ioport_read(base + 0x05, 1, 1, fdctrl_read_data, NULL); + register_ioport_write(base + 0x05, 1, 1, fdctrl_write_data, NULL); + register_ioport_read(base + 0x07, 1, 1, fdctrl_read_dir, NULL); } - if (boot_device == 'b') - fdctrl.bootsel = 1; - else - fdctrl.bootsel = 0; -#if defined (TARGET_I386) - cmos_register_fd(fdctrl.drives[0].drive, fdctrl.drives[1].drive); -#endif -} - -int fdctrl_disk_change (int idx, const unsigned char *filename, int ro) -{ - fdrive_t *drv; + fdctrl.bootsel = 0; - if (idx < 0 || idx > 1) - return -1; - FLOPPY_DPRINTF("disk %d change: %s (%s)\n", idx, filename, - ro == 0 ? "rw" : "ro"); - drv = &fdctrl.drives[idx]; - if (fd_table[idx] != NULL) { - bdrv_close(fd_table[idx]); - fd_table[idx] = NULL; + for (i = 0; i < MAX_FD; i++) { + fd_revalidate(&fdctrl.drives[i]); } - fd_table[idx] = bdrv_open(filename, ro); - drv->bs = fd_table[idx]; - if (fd_table[idx] == NULL) - return -1; - fd_revalidate(drv, ro); -#if 0 - fd_recalibrate(drv); - fdctrl_reset_fifo(); - fdctrl_raise_irq(0x20); -#endif +} - return 0; +int fdctrl_get_drive_type(int drive_num) +{ + return fdctrl.drives[drive_num].drive; } /* Change IRQ state */ @@ -411,7 +403,7 @@ static void fdctrl_reset (int do_irq) } /* Status B register : 0x01 (read-only) */ -static uint32_t fdctrl_read_statusB (CPUState *env, uint32_t reg) +static uint32_t fdctrl_read_statusB (void *opaque, uint32_t reg) { fdctrl_reset_irq(); FLOPPY_DPRINTF("status register: 0x00\n"); @@ -420,7 +412,7 @@ static uint32_t fdctrl_read_statusB (CPUState *env, uint32_t reg) } /* Digital output register : 0x02 */ -static uint32_t fdctrl_read_dor (CPUState *env, uint32_t reg) +static uint32_t fdctrl_read_dor (void *opaque, uint32_t reg) { fdrive_t *cur_drv, *drv0, *drv1; uint32_t retval = 0; @@ -442,7 +434,7 @@ static uint32_t fdctrl_read_dor (CPUState *env, uint32_t reg) return retval; } -static void fdctrl_write_dor (CPUState *env, uint32_t reg, uint32_t value) +static void fdctrl_write_dor (void *opaque, uint32_t reg, uint32_t value) { fdrive_t *drv0, *drv1; @@ -489,7 +481,7 @@ static void fdctrl_write_dor (CPUState *env, uint32_t reg, uint32_t value) } /* Tape drive register : 0x03 */ -static uint32_t fdctrl_read_tape (CPUState *env, uint32_t reg) +static uint32_t fdctrl_read_tape (void *opaque, uint32_t reg) { uint32_t retval = 0; @@ -502,7 +494,7 @@ static uint32_t fdctrl_read_tape (CPUState *env, uint32_t reg) return retval; } -static void fdctrl_write_tape (CPUState *env, uint32_t reg, uint32_t value) +static void fdctrl_write_tape (void *opaque, uint32_t reg, uint32_t value) { fdctrl_reset_irq(); /* Reset mode */ @@ -517,7 +509,7 @@ static void fdctrl_write_tape (CPUState *env, uint32_t reg, uint32_t value) } /* Main status register : 0x04 (read) */ -static uint32_t fdctrl_read_main_status (CPUState *env, uint32_t reg) +static uint32_t fdctrl_read_main_status (void *opaque, uint32_t reg) { uint32_t retval = 0; @@ -541,7 +533,7 @@ static uint32_t fdctrl_read_main_status (CPUState *env, uint32_t reg) } /* Data select rate register : 0x04 (write) */ -static void fdctrl_write_rate (CPUState *env, uint32_t reg, uint32_t value) +static void fdctrl_write_rate (void *opaque, uint32_t reg, uint32_t value) { fdctrl_reset_irq(); /* Reset mode */ @@ -566,7 +558,7 @@ static void fdctrl_write_rate (CPUState *env, uint32_t reg, uint32_t value) } /* Digital input register : 0x07 (read-only) */ -static uint32_t fdctrl_read_dir (CPUState *env, uint32_t reg) +static uint32_t fdctrl_read_dir (void *opaque, uint32_t reg) { fdrive_t *drv0, *drv1; uint32_t retval = 0; @@ -872,7 +864,7 @@ transfer_error: } /* Data register : 0x05 */ -static uint32_t fdctrl_read_data (CPUState *env, uint32_t reg) +static uint32_t fdctrl_read_data (void *opaque, uint32_t reg) { fdrive_t *cur_drv, *drv0, *drv1; uint32_t retval = 0; @@ -914,7 +906,7 @@ static uint32_t fdctrl_read_data (CPUState *env, uint32_t reg) return retval; } -static void fdctrl_write_data (CPUState *env, uint32_t reg, uint32_t value) +static void fdctrl_write_data (void *opaque, uint32_t reg, uint32_t value) { fdrive_t *cur_drv, *drv0, *drv1; diff --git a/hw/ide.c b/hw/ide.c index 82e8fba884..a132d1c52a 100644 --- a/hw/ide.c +++ b/hw/ide.c @@ -314,10 +314,10 @@ struct IDEState; typedef void EndTransferFunc(struct IDEState *); +/* NOTE: IDEState represents in fact one drive */ typedef struct IDEState { /* ide config */ int is_cdrom; - int cdrom_locked; int cylinders, heads, sectors; int64_t nb_sectors; int mult_sectors; @@ -351,14 +351,6 @@ typedef struct IDEState { uint8_t io_buffer[MAX_MULT_SECTORS*512 + 4]; } IDEState; -IDEState ide_state[MAX_DISKS]; -IDEState *ide_table[0x400 >> 3]; - -static inline IDEState *get_ide_interface(uint32_t addr) -{ - return ide_table[addr >> 3]; -} - static void padstr(char *str, const char *src, int len) { int i, v; @@ -815,7 +807,7 @@ static void ide_atapi_cmd(IDEState *s) #endif switch(s->io_buffer[0]) { case GPCMD_TEST_UNIT_READY: - if (s->bs) { + if (bdrv_is_inserted(s->bs)) { ide_atapi_cmd_ok(s); } else { ide_atapi_cmd_error(s, SENSE_NOT_READY, @@ -867,7 +859,7 @@ static void ide_atapi_cmd(IDEState *s) buf[12] = 0x70; buf[13] = 3 << 5; buf[14] = (1 << 0) | (1 << 3) | (1 << 5); - if (s->cdrom_locked) + if (bdrv_is_locked(s->bs)) buf[6] |= 1 << 1; buf[15] = 0x00; cpu_to_ube16(&buf[16], 706); @@ -907,8 +899,8 @@ static void ide_atapi_cmd(IDEState *s) ide_atapi_cmd_reply(s, 18, max_len); break; case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL: - if (s->bs) { - s->cdrom_locked = packet[4] & 1; + if (bdrv_is_inserted(s->bs)) { + bdrv_set_locked(s->bs, packet[4] & 1); ide_atapi_cmd_ok(s); } else { ide_atapi_cmd_error(s, SENSE_NOT_READY, @@ -920,7 +912,7 @@ static void ide_atapi_cmd(IDEState *s) { int nb_sectors, lba; - if (!s->bs) { + if (!bdrv_is_inserted(s->bs)) { ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); break; @@ -945,7 +937,7 @@ static void ide_atapi_cmd(IDEState *s) case GPCMD_SEEK: { int lba; - if (!s->bs) { + if (!bdrv_is_inserted(s->bs)) { ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); break; @@ -965,7 +957,10 @@ static void ide_atapi_cmd(IDEState *s) start = packet[4] & 1; eject = (packet[4] >> 1) & 1; - /* XXX: currently none implemented */ + if (eject && !start) { + /* eject the disk */ + bdrv_close(s->bs); + } ide_atapi_cmd_ok(s); } break; @@ -986,7 +981,7 @@ static void ide_atapi_cmd(IDEState *s) { int format, msf, start_track, len; - if (!s->bs) { + if (!bdrv_is_inserted(s->bs)) { ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); break; @@ -1019,7 +1014,7 @@ static void ide_atapi_cmd(IDEState *s) } break; case GPCMD_READ_CDVD_CAPACITY: - if (!s->bs) { + if (!bdrv_is_inserted(s->bs)) { ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); break; @@ -1051,9 +1046,20 @@ static void ide_atapi_cmd(IDEState *s) } } -static void ide_ioport_write(CPUState *env, uint32_t addr, uint32_t val) +/* called when the inserted state of the media has changed */ +static void cdrom_change_cb(void *opaque) { - IDEState *ide_if = get_ide_interface(addr); + IDEState *s = opaque; + int64_t nb_sectors; + + /* XXX: send interrupt too */ + bdrv_get_geometry(s->bs, &nb_sectors); + s->nb_sectors = nb_sectors; +} + +static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) +{ + IDEState *ide_if = opaque; IDEState *s = ide_if->cur_drive; int unit, n; @@ -1210,9 +1216,9 @@ static void ide_ioport_write(CPUState *env, uint32_t addr, uint32_t val) } } -static uint32_t ide_ioport_read(CPUState *env, uint32_t addr1) +static uint32_t ide_ioport_read(void *opaque, uint32_t addr1) { - IDEState *s = get_ide_interface(addr1)->cur_drive; + IDEState *s = ((IDEState *)opaque)->cur_drive; uint32_t addr; int ret; @@ -1251,9 +1257,9 @@ static uint32_t ide_ioport_read(CPUState *env, uint32_t addr1) return ret; } -static uint32_t ide_status_read(CPUState *env, uint32_t addr) +static uint32_t ide_status_read(void *opaque, uint32_t addr) { - IDEState *s = get_ide_interface(addr)->cur_drive; + IDEState *s = ((IDEState *)opaque)->cur_drive; int ret; ret = s->status; #ifdef DEBUG_IDE @@ -1262,9 +1268,9 @@ static uint32_t ide_status_read(CPUState *env, uint32_t addr) return ret; } -static void ide_cmd_write(CPUState *env, uint32_t addr, uint32_t val) +static void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val) { - IDEState *ide_if = get_ide_interface(addr); + IDEState *ide_if = opaque; IDEState *s; int i; @@ -1297,9 +1303,9 @@ static void ide_cmd_write(CPUState *env, uint32_t addr, uint32_t val) ide_if[1].cmd = val; } -static void ide_data_writew(CPUState *env, uint32_t addr, uint32_t val) +static void ide_data_writew(void *opaque, uint32_t addr, uint32_t val) { - IDEState *s = get_ide_interface(addr)->cur_drive; + IDEState *s = ((IDEState *)opaque)->cur_drive; uint8_t *p; p = s->data_ptr; @@ -1310,9 +1316,9 @@ static void ide_data_writew(CPUState *env, uint32_t addr, uint32_t val) s->end_transfer_func(s); } -static uint32_t ide_data_readw(CPUState *env, uint32_t addr) +static uint32_t ide_data_readw(void *opaque, uint32_t addr) { - IDEState *s = get_ide_interface(addr)->cur_drive; + IDEState *s = ((IDEState *)opaque)->cur_drive; uint8_t *p; int ret; p = s->data_ptr; @@ -1324,9 +1330,9 @@ static uint32_t ide_data_readw(CPUState *env, uint32_t addr) return ret; } -static void ide_data_writel(CPUState *env, uint32_t addr, uint32_t val) +static void ide_data_writel(void *opaque, uint32_t addr, uint32_t val) { - IDEState *s = get_ide_interface(addr)->cur_drive; + IDEState *s = ((IDEState *)opaque)->cur_drive; uint8_t *p; p = s->data_ptr; @@ -1337,9 +1343,9 @@ static void ide_data_writel(CPUState *env, uint32_t addr, uint32_t val) s->end_transfer_func(s); } -static uint32_t ide_data_readl(CPUState *env, uint32_t addr) +static uint32_t ide_data_readl(void *opaque, uint32_t addr) { - IDEState *s = get_ide_interface(addr)->cur_drive; + IDEState *s = ((IDEState *)opaque)->cur_drive; uint8_t *p; int ret; @@ -1407,64 +1413,64 @@ static void ide_guess_geometry(IDEState *s) } } -void ide_init(void) +void ide_init(int iobase, int iobase2, int irq, + BlockDriverState *hd0, BlockDriverState *hd1) { - IDEState *s; - int i, cylinders, iobase, iobase2; + IDEState *s, *ide_state; + int i, cylinders, heads, secs; int64_t nb_sectors; - static const int ide_iobase[2] = { 0x1f0, 0x170 }; - static const int ide_iobase2[2] = { 0x3f6, 0x376 }; - static const int ide_irq[2] = { 14, 15 }; - for(i = 0; i < MAX_DISKS; i++) { - s = &ide_state[i]; - s->bs = bs_table[i]; + ide_state = qemu_mallocz(sizeof(IDEState) * 2); + if (!ide_state) + return; + + for(i = 0; i < 2; i++) { + s = ide_state + i; + if (i == 0) + s->bs = hd0; + else + s->bs = hd1; if (s->bs) { bdrv_get_geometry(s->bs, &nb_sectors); s->nb_sectors = nb_sectors; - ide_guess_geometry(s); - if (s->cylinders == 0) { - /* if no geometry, use a LBA compatible one */ - cylinders = nb_sectors / (16 * 63); - if (cylinders > 16383) - cylinders = 16383; - else if (cylinders < 2) - cylinders = 2; + /* if a geometry hint is available, use it */ + bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs); + if (cylinders != 0) { s->cylinders = cylinders; - s->heads = 16; - s->sectors = 63; + s->heads = heads; + s->sectors = secs; + } else { + ide_guess_geometry(s); + if (s->cylinders == 0) { + /* if no geometry, use a LBA compatible one */ + cylinders = nb_sectors / (16 * 63); + if (cylinders > 16383) + cylinders = 16383; + else if (cylinders < 2) + cylinders = 2; + s->cylinders = cylinders; + s->heads = 16; + s->sectors = 63; + } + } + if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) { + s->is_cdrom = 1; + bdrv_set_change_cb(s->bs, cdrom_change_cb, s); } } - s->irq = ide_irq[i >> 1]; + s->irq = irq; ide_reset(s); } - for(i = 0; i < (MAX_DISKS / 2); i++) { - iobase = ide_iobase[i]; - iobase2 = ide_iobase2[i]; - ide_table[iobase >> 3] = &ide_state[2 * i]; - if (ide_iobase2[i]) - ide_table[iobase2 >> 3] = &ide_state[2 * i]; - register_ioport_write(iobase, 8, ide_ioport_write, 1); - register_ioport_read(iobase, 8, ide_ioport_read, 1); - register_ioport_read(iobase2, 1, ide_status_read, 1); - register_ioport_write(iobase2, 1, ide_cmd_write, 1); - - /* data ports */ - register_ioport_write(iobase, 2, ide_data_writew, 2); - register_ioport_read(iobase, 2, ide_data_readw, 2); - register_ioport_write(iobase, 4, ide_data_writel, 4); - register_ioport_read(iobase, 4, ide_data_readl, 4); + register_ioport_write(iobase, 8, 1, ide_ioport_write, ide_state); + register_ioport_read(iobase, 8, 1, ide_ioport_read, ide_state); + if (iobase2) { + register_ioport_read(iobase2, 1, 1, ide_status_read, ide_state); + register_ioport_write(iobase2, 1, 1, ide_cmd_write, ide_state); } -} - -void ide_set_geometry(int n, int cyls, int heads, int secs) -{ - ide_state[n].cylinders = cyls; - ide_state[n].heads = heads; - ide_state[n].sectors = secs; -} - -void ide_set_cdrom(int n, int is_cdrom) -{ - ide_state[n].is_cdrom = is_cdrom; + + /* data ports */ + register_ioport_write(iobase, 2, 2, ide_data_writew, ide_state); + register_ioport_read(iobase, 2, 2, ide_data_readw, ide_state); + register_ioport_write(iobase, 4, 4, ide_data_writel, ide_state); + register_ioport_read(iobase, 4, 4, ide_data_readl, ide_state); } -- cgit v1.2.3