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;
}
/* 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)
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)
{
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,
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;
} 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) {
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 */
}
/* 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");
}
/* 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;
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;
}
/* 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;
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 */
}
/* 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;
}
/* 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 */
}
/* 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;
}
/* 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;
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;
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;
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;
#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,
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);
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,
{
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;
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;
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;
{
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;
}
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;
}
}
-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;
}
}
-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;
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
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;
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;
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;
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;
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;
}
}
-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);
}