@@ -52,6 +52,8 @@
/********************************************************/
/* Floppy drive emulation */
+#define MAX_FD 4
+
#define GET_CUR_DRV(fdctrl) ((fdctrl)->cur_drv)
#define SET_CUR_DRV(fdctrl, drive) ((fdctrl)->cur_drv = (drive))
@@ -424,11 +426,6 @@
};
enum {
-#if MAX_FD == 4
- FD_DOR_SELMASK = 0x03,
-#else
- FD_DOR_SELMASK = 0x01,
-#endif
FD_DOR_nRESET = 0x04,
FD_DOR_DMAEN = 0x08,
FD_DOR_MOTEN0 = 0x10,
@@ -437,13 +434,8 @@
FD_DOR_MOTEN3 = 0x80,
};
-enum {
-#if MAX_FD == 4
- FD_TDR_BOOTSEL = 0x0c,
-#else
- FD_TDR_BOOTSEL = 0x04,
-#endif
-};
+#define FD_DOR_SELMASK(fdctrl) (fdctrl->max_fd - 1)
+#define FD_TDR_BOOTSEL(fdctrl) ((fdctrl->max_fd - 1) << 2)
enum {
FD_DSR_DRATEMASK= 0x03,
@@ -473,6 +465,8 @@
struct fdctrl_t {
/* Controller's identification */
uint8_t version;
+ /* Max drives (must be 2 or 4) */
+ uint8_t max_fd;
/* HW */
qemu_irq irq;
int dma_chann;
@@ -637,7 +631,6 @@
static void fdc_save (QEMUFile *f, void *opaque)
{
fdctrl_t *s = opaque;
- uint8_t tmp;
int i;
uint8_t dor = s->dor | GET_CUR_DRV(s);
@@ -666,9 +659,8 @@
qemu_put_8s(f, &s->lock);
qemu_put_8s(f, &s->pwrd);
- tmp = MAX_FD;
- qemu_put_8s(f, &tmp);
- for (i = 0; i < MAX_FD; i++)
+ qemu_put_8s(f, &s->max_fd);
+ for (i = 0; i < s->max_fd; i++)
fd_save(f, &s->drives[i]);
}
@@ -694,8 +686,8 @@
qemu_get_8s(f, &s->sra);
qemu_get_8s(f, &s->srb);
qemu_get_8s(f, &s->dor);
- SET_CUR_DRV(s, s->dor & FD_DOR_SELMASK);
- s->dor &= ~FD_DOR_SELMASK;
+ SET_CUR_DRV(s, s->dor & FD_DOR_SELMASK(s));
+ s->dor &= ~FD_DOR_SELMASK(s);
qemu_get_8s(f, &s->tdr);
qemu_get_8s(f, &s->dsr);
qemu_get_8s(f, &s->msr);
@@ -718,10 +710,10 @@
qemu_get_8s(f, &s->pwrd);
qemu_get_8s(f, &n);
- if (n > MAX_FD)
+ if (n > MAX_FD || n != s->max_fd)
return -EINVAL;
- for (i = 0; i < n; i++) {
+ for (i = 0; i < s->max_fd; i++) {
ret = fd_load(f, &s->drives[i]);
if (ret != 0)
break;
@@ -803,7 +795,7 @@
fdctrl->data_len = 0;
fdctrl->data_state = 0;
fdctrl->data_dir = FD_DIR_WRITE;
- for (i = 0; i < MAX_FD; i++)
+ for (i = 0; i < fdctrl->max_fd; i++)
fd_recalibrate(&fdctrl->drives[i]);
fdctrl_reset_fifo(fdctrl);
if (do_irq) {
@@ -814,12 +806,12 @@
static inline fdrive_t *drv0 (fdctrl_t *fdctrl)
{
- return &fdctrl->drives[(fdctrl->tdr & FD_TDR_BOOTSEL) >> 2];
+ return &fdctrl->drives[(fdctrl->tdr & FD_TDR_BOOTSEL(fdctrl)) >> 2];
}
static inline fdrive_t *drv1 (fdctrl_t *fdctrl)
{
- if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (1 << 2))
+ if ((fdctrl->tdr & FD_TDR_BOOTSEL(fdctrl)) < (1 << 2))
return &fdctrl->drives[1];
else
return &fdctrl->drives[0];
@@ -828,7 +820,9 @@
#if MAX_FD == 4
static inline fdrive_t *drv2 (fdctrl_t *fdctrl)
{
- if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (2 << 2))
+ if (fdctrl->max_fd != 4)
+ return NULL;
+ else if ((fdctrl->tdr & FD_TDR_BOOTSEL(fdctrl)) < (2 << 2))
return &fdctrl->drives[2];
else
return &fdctrl->drives[1];
@@ -836,7 +830,9 @@
static inline fdrive_t *drv3 (fdctrl_t *fdctrl)
{
- if ((fdctrl->tdr & FD_TDR_BOOTSEL) < (3 << 2))
+ if (fdctrl->max_fd != 4)
+ return NULL;
+ else if ((fdctrl->tdr & FD_TDR_BOOTSEL(fdctrl)) < (3 << 2))
return &fdctrl->drives[3];
else
return &fdctrl->drives[2];
@@ -921,7 +917,7 @@
}
}
/* Selected drive */
- fdctrl->cur_drv = value & FD_DOR_SELMASK;
+ fdctrl->cur_drv = value & FD_DOR_SELMASK(fdctrl);
fdctrl->dor = value;
}
@@ -945,7 +941,7 @@
}
FLOPPY_DPRINTF("tape drive register set to 0x%02x\n", value);
/* Disk boot selection indicator */
- fdctrl->tdr = value & FD_TDR_BOOTSEL;
+ fdctrl->tdr = value & FD_TDR_BOOTSEL(fdctrl);
/* Tape indicators: never allow */
}
@@ -1004,8 +1000,8 @@
if (fdctrl_media_changed(drv0(fdctrl))
|| fdctrl_media_changed(drv1(fdctrl))
#if MAX_FD == 4
- || fdctrl_media_changed(drv2(fdctrl))
- || fdctrl_media_changed(drv3(fdctrl))
+ || (fdctrl->max_fd == 4 && fdctrl_media_changed(drv2(fdctrl)))
+ || (fdctrl->max_fd == 4 && fdctrl_media_changed(drv3(fdctrl)))
#endif
)
retval |= FD_DIR_DSKCHG;
@@ -1109,7 +1105,7 @@
uint8_t kh, kt, ks;
int did_seek = 0;
- SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
+ SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK(fdctrl));
cur_drv = get_cur_drv(fdctrl);
kt = fdctrl->fifo[2];
kh = fdctrl->fifo[3];
@@ -1379,7 +1375,7 @@
fdrive_t *cur_drv;
uint8_t kh, kt, ks;
- SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
+ SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK(fdctrl));
cur_drv = get_cur_drv(fdctrl);
kt = fdctrl->fifo[6];
kh = fdctrl->fifo[7];
@@ -1451,11 +1447,15 @@
fdctrl->fifo[0] = drv0(fdctrl)->track;
fdctrl->fifo[1] = drv1(fdctrl)->track;
#if MAX_FD == 4
- fdctrl->fifo[2] = drv2(fdctrl)->track;
- fdctrl->fifo[3] = drv3(fdctrl)->track;
+ if (fdctrl->max_fd == 4) {
+ fdctrl->fifo[2] = drv2(fdctrl)->track;
+ fdctrl->fifo[3] = drv3(fdctrl)->track;
+ } else
#else
- fdctrl->fifo[2] = 0;
- fdctrl->fifo[3] = 0;
+ {
+ fdctrl->fifo[2] = 0;
+ fdctrl->fifo[3] = 0;
+ }
#endif
/* timers */
fdctrl->fifo[4] = fdctrl->timer0;
@@ -1489,8 +1489,10 @@
drv0(fdctrl)->track = fdctrl->fifo[3];
drv1(fdctrl)->track = fdctrl->fifo[4];
#if MAX_FD == 4
- drv2(fdctrl)->track = fdctrl->fifo[5];
- drv3(fdctrl)->track = fdctrl->fifo[6];
+ if (fdctrl->max_fd == 4) {
+ drv2(fdctrl)->track = fdctrl->fifo[5];
+ drv3(fdctrl)->track = fdctrl->fifo[6];
+ }
#endif
/* timers */
fdctrl->timer0 = fdctrl->fifo[7];
@@ -1514,11 +1516,15 @@
fdctrl->fifo[2] = drv0(fdctrl)->track;
fdctrl->fifo[3] = drv1(fdctrl)->track;
#if MAX_FD == 4
- fdctrl->fifo[4] = drv2(fdctrl)->track;
- fdctrl->fifo[5] = drv3(fdctrl)->track;
+ if (fdctrl->max_fd == 4) {
+ fdctrl->fifo[4] = drv2(fdctrl)->track;
+ fdctrl->fifo[5] = drv3(fdctrl)->track;
+ } else
#else
- fdctrl->fifo[4] = 0;
- fdctrl->fifo[5] = 0;
+ {
+ fdctrl->fifo[4] = 0;
+ fdctrl->fifo[5] = 0;
+ }
#endif
/* timers */
fdctrl->fifo[6] = fdctrl->timer0;
@@ -1548,7 +1554,7 @@
{
fdrive_t *cur_drv;
- SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
+ SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK(fdctrl));
cur_drv = get_cur_drv(fdctrl);
fdctrl->data_state |= FD_STATE_FORMAT;
if (fdctrl->fifo[0] & 0x80)
@@ -1589,7 +1595,7 @@
{
fdrive_t *cur_drv;
- SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
+ SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK(fdctrl));
cur_drv = get_cur_drv(fdctrl);
cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
/* 1 Byte status back */
@@ -1605,7 +1611,7 @@
{
fdrive_t *cur_drv;
- SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
+ SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK(fdctrl));
cur_drv = get_cur_drv(fdctrl);
fd_recalibrate(cur_drv);
fdctrl_reset_fifo(fdctrl);
@@ -1639,7 +1645,7 @@
{
fdrive_t *cur_drv;
- SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
+ SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK(fdctrl));
cur_drv = get_cur_drv(fdctrl);
fdctrl_reset_fifo(fdctrl);
if (fdctrl->fifo[2] > cur_drv->max_track) {
@@ -1708,7 +1714,7 @@
{
fdrive_t *cur_drv;
- SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
+ SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK(fdctrl));
cur_drv = get_cur_drv(fdctrl);
if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) {
cur_drv->track = cur_drv->max_track - 1;
@@ -1724,7 +1730,7 @@
{
fdrive_t *cur_drv;
- SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK);
+ SET_CUR_DRV(fdctrl, fdctrl->fifo[1] & FD_DOR_SELMASK(fdctrl));
cur_drv = get_cur_drv(fdctrl);
if (fdctrl->fifo[2] > cur_drv->track) {
cur_drv->track = 0;
@@ -1865,7 +1871,7 @@
{
unsigned int i;
- for (i = 0; i < MAX_FD; i++) {
+ for (i = 0; i < fdctrl->max_fd; i++) {
fd_init(&fdctrl->drives[i], fds[i]);
fd_revalidate(&fdctrl->drives[i]);
}
@@ -1873,15 +1879,21 @@
fdctrl_t *fdctrl_init_isa(int isairq, int dma_chann,
uint32_t io_base,
- BlockDriverState **fds)
+ BlockDriverState **fds, uint8_t max_fd)
{
fdctrl_t *fdctrl;
ISADevice *dev;
+ if (max_fd > MAX_FD) {
+ hw_error("fdctrl_init_isa: invalid max_fd");
+ }
+
dev = isa_create_simple("isa-fdc", io_base, 0, isairq, -1);
fdctrl = &(DO_UPCAST(fdctrl_isabus_t, busdev, dev)->state);
fdctrl->dma_chann = dma_chann;
+ fdctrl->max_fd = max_fd;
+
DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl);
fdctrl_connect_drives(fdctrl, fds);
@@ -1891,12 +1903,16 @@
fdctrl_t *fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
target_phys_addr_t mmio_base,
- BlockDriverState **fds)
+ BlockDriverState **fds, uint8_t max_fd)
{
fdctrl_t *fdctrl;
DeviceState *dev;
fdctrl_sysbus_t *sys;
+ if (max_fd > MAX_FD) {
+ hw_error("fdctrl_init_sysbus: invalid max_fd");
+ }
+
dev = qdev_create(NULL, "sysbus-fdc");
qdev_init(dev);
sys = DO_UPCAST(fdctrl_sysbus_t, busdev.qdev, dev);
@@ -1905,6 +1921,8 @@
sysbus_mmio_map(&sys->busdev, 0, mmio_base);
fdctrl->dma_chann = dma_chann;
+ fdctrl->max_fd = max_fd;
+
DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl);
fdctrl_connect_drives(fdctrl, fds);
@@ -1912,12 +1930,17 @@
}
fdctrl_t *sun4m_fdctrl_init (qemu_irq irq, target_phys_addr_t io_base,
- BlockDriverState **fds, qemu_irq *fdc_tc)
+ BlockDriverState **fds, uint8_t max_fd,
+ qemu_irq *fdc_tc)
{
DeviceState *dev;
fdctrl_sysbus_t *sys;
fdctrl_t *fdctrl;
+ if (max_fd > MAX_FD) {
+ hw_error("sun4m_fdctrl_init: invalid max_fd");
+ }
+
dev = qdev_create(NULL, "SUNW,fdtwo");
qdev_init(dev);
sys = DO_UPCAST(fdctrl_sysbus_t, busdev.qdev, dev);
@@ -1927,6 +1950,7 @@
*fdc_tc = qdev_get_gpio_in(dev, 0);
fdctrl->dma_chann = -1;
+ fdctrl->max_fd = max_fd;
fdctrl_connect_drives(fdctrl, fds);
@@ -1,14 +1,13 @@
/* fdc.c */
-#define MAX_FD 2
-
typedef struct fdctrl_t fdctrl_t;
fdctrl_t *fdctrl_init_isa(int isairq, int dma_chann,
uint32_t io_base,
- BlockDriverState **fds);
+ BlockDriverState **fds, uint8_t max_fd);
fdctrl_t *fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
target_phys_addr_t mmio_base,
- BlockDriverState **fds);
+ BlockDriverState **fds, uint8_t max_fd);
fdctrl_t *sun4m_fdctrl_init (qemu_irq irq, target_phys_addr_t io_base,
- BlockDriverState **fds, qemu_irq *fdc_tc);
+ BlockDriverState **fds, uint8_t max_fd,
+ qemu_irq *fdc_tc);
int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num);
@@ -113,6 +113,8 @@
#define MAGNUM_BIOS_SIZE_MAX 0x7e000
#define MAGNUM_BIOS_SIZE (BIOS_SIZE < MAGNUM_BIOS_SIZE_MAX ? BIOS_SIZE : MAGNUM_BIOS_SIZE_MAX)
+#define MAX_FD 2
+
static
void mips_jazz_init (ram_addr_t ram_size,
const char *cpu_model,
@@ -238,7 +240,7 @@
DriveInfo *dinfo = drive_get(IF_FLOPPY, 0, n);
fds[n] = dinfo ? dinfo->bdrv : NULL;
}
- fdctrl_init_sysbus(rc4030[1], 0, 0x80003000, fds);
+ fdctrl_init_sysbus(rc4030[1], 0, 0x80003000, fds, MAX_FD);
/* Real time clock */
rtc_init(0x70, i8259[8], 1980);
@@ -55,6 +55,7 @@
#define ENVP_ENTRY_SIZE 256
#define MAX_IDE_BUS 2
+#define MAX_FD 2
typedef struct {
uint32_t leds;
@@ -932,7 +933,7 @@
dinfo = drive_get(IF_FLOPPY, 0, i);
fd[i] = dinfo ? dinfo->bdrv : NULL;
}
- floppy_controller = fdctrl_init_isa(6, 2, 0x3f0, fd);
+ floppy_controller = fdctrl_init_isa(6, 2, 0x3f0, fd, MAX_FD);
/* Sound card */
#ifdef HAS_AUDIO
@@ -58,6 +58,7 @@
#define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2)
#define MAX_IDE_BUS 2
+#define MAX_FD 2
static fdctrl_t *floppy_controller;
static RTCState *rtc_state;
@@ -1382,7 +1383,7 @@
dinfo = drive_get(IF_FLOPPY, 0, i);
fd[i] = dinfo ? dinfo->bdrv : NULL;
}
- floppy_controller = fdctrl_init_isa(6, 2, 0x3f0, fd);
+ floppy_controller = fdctrl_init_isa(6, 2, 0x3f0, fd, MAX_FD);
cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd);
@@ -41,6 +41,7 @@
#define MAX_CPUS 1
#define MAX_IDE_BUS 2
+#define MAX_FD 2
#define BIOS_SIZE (1024 * 1024)
#define BIOS_FILENAME "ppc_rom.bin"
@@ -719,7 +720,7 @@
dinfo = drive_get(IF_FLOPPY, 0, i);
fd[i] = dinfo ? dinfo->bdrv : NULL;
}
- fdctrl_init_isa(6, 2, 0x3f0, fd);
+ fdctrl_init_isa(6, 2, 0x3f0, fd, MAX_FD);
/* Register speaker port */
register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL);
@@ -81,6 +81,7 @@
#define PROM_SIZE_MAX (1024 * 1024)
#define PROM_VADDR 0xffd00000
#define PROM_FILENAME "openbios-sparc32"
+#define MAX_FD 2
#define CFG_ADDR 0xd00000510ULL
#define FW_CFG_SUN4M_DEPTH (FW_CFG_ARCH_LOCAL + 0x00)
@@ -827,7 +828,7 @@
if (dinfo)
fd[0] = dinfo->bdrv;
- sun4m_fdctrl_init(slavio_irq[22], hwdef->fd_base, fd,
+ sun4m_fdctrl_init(slavio_irq[22], hwdef->fd_base, fd, MAX_FD,
&fdc_tc);
}
@@ -1611,7 +1612,7 @@
if (dinfo)
fd[0] = dinfo->bdrv;
- sun4m_fdctrl_init(slavio_irq[1], hwdef->fd_base, fd,
+ sun4m_fdctrl_init(slavio_irq[1], hwdef->fd_base, fd, MAX_FD,
&fdc_tc);
}
@@ -55,6 +55,7 @@
#define PROM_FILENAME "openbios-sparc64"
#define NVRAM_SIZE 0x2000
#define MAX_IDE_BUS 2
+#define MAX_FD 2
#define BIOS_CFG_IOPORT 0x510
#define FW_CFG_SPARC64_WIDTH (FW_CFG_ARCH_LOCAL + 0x00)
#define FW_CFG_SPARC64_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01)
@@ -622,7 +623,7 @@
dinfo = drive_get(IF_FLOPPY, 0, i);
fd[i] = dinfo ? dinfo->bdrv : NULL;
}
- fdctrl_init_isa(6, 2, 0x3f0, fd);
+ fdctrl_init_isa(6, 2, 0x3f0, fd, MAX_FD);
/* FIXME: wire up interrupts. */
nvram = m48t59_init(NULL/*8*/, 0, 0x0074, NVRAM_SIZE, 59);