FDC Pull request
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE+ber27ys35W+dsvQfe+BBqr8OQ4FAmDV0fkACgkQfe+BBqr8 OQ500Q/+Je+3aSFDOcy9msCgN8+leahVtkp1rfbhdpUqXAyZ8v6FyZhKeBtqI3ZO yTpKNMqi1t/E3CSL/5dxbd5Hd48s0fx7thmrIhavfQJiElOAcv2elbWvJPA57sif zb1HtCVbU1ZXmW+nfMRFZxbwluZQkHhJfuYPXpaTQ1sF/HM3UHDcZxFtTGlEK9AD W+lZk7Z72sC58ckGtnMMeU/P0Bw76O/bs48nFkfegKc0YOTHcHt0YyEQ9Pe23ANI xSvIHZ+grDu2CWoD6RW30IcC7pds9ipkguLyvCS2+VVKvjb2i4QLrbAKB+Hgzmk2 lSFej+77FeobmyRMgpy7r4bHP239fcKT+IwtWYDHcLk5OpGJKoN2fkg2Y1bR7LH5 iQdnhsYIJj8IC3tzkb1nJQrNN2QzNE1YjV4rjBCPhBLW1lsjkjgtNg/0MVu2lfJe Q0XF7fwNCVFHptRhAPYii2mS+rnPWJdg12Svb9hB7xX7KgQEXBz23L8yy6ve1a37 9i8vOKU9J3wB53Z83wHh6oeKn5AL8hSD2nR0TJyLLrZmkMK7ZueMit7G8MN8xipQ 0lteY/Im5TfjieE2kZ9q7QC+KjYfJVjzL3AZtpF0rJJvRa4V7rbS6EGCq/5D4lX2 kwmyF6jvE03ms/rnt/CPD2vLH/u9h7u7bAlNqMXuK5dg21fki3A= =Tp1A -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/jsnow-gitlab/tags/floppy-pull-request' into staging FDC Pull request # gpg: Signature made Fri 25 Jun 2021 13:54:17 BST # gpg: using RSA key F9B7ABDBBCACDF95BE76CBD07DEF8106AAFC390E # gpg: Good signature from "John Snow (John Huston) <jsnow@redhat.com>" [full] # Primary key fingerprint: FAEB 9711 A12C F475 812F 18F2 88A9 064D 1835 61EB # Subkey fingerprint: F9B7 ABDB BCAC DF95 BE76 CBD0 7DEF 8106 AAFC 390E * remotes/jsnow-gitlab/tags/floppy-pull-request: hw/block/fdc: Add description to floppy controllers hw/block/fdc: Extract SysBus floppy controllers to fdc-sysbus.c hw/block/fdc: Extract ISA floppy controllers to fdc-isa.c hw/block/fdc: Declare shared prototypes in fdc-internal.h hw/block/fdc: Replace disabled fprintf() by trace event hw/isa/Kconfig: Fix missing dependency ISA_SUPERIO -> FDC Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
271fc190b3
@ -1669,6 +1669,9 @@ M: John Snow <jsnow@redhat.com>
|
||||
L: qemu-block@nongnu.org
|
||||
S: Supported
|
||||
F: hw/block/fdc.c
|
||||
F: hw/block/fdc-internal.h
|
||||
F: hw/block/fdc-isa.c
|
||||
F: hw/block/fdc-sysbus.c
|
||||
F: include/hw/block/fdc.h
|
||||
F: tests/qtest/fdc-test.c
|
||||
T: git https://gitlab.com/jsnow/qemu.git ide
|
||||
|
@ -1,8 +1,14 @@
|
||||
config FDC
|
||||
bool
|
||||
# FIXME: there is no separate file for the MMIO floppy disk controller, so
|
||||
# select ISA_BUS here instead of polluting each board that requires one
|
||||
select ISA_BUS
|
||||
|
||||
config FDC_ISA
|
||||
bool
|
||||
depends on ISA_BUS
|
||||
select FDC
|
||||
|
||||
config FDC_SYSBUS
|
||||
bool
|
||||
select FDC
|
||||
|
||||
config SSI_M25P80
|
||||
bool
|
||||
|
158
hw/block/fdc-internal.h
Normal file
158
hw/block/fdc-internal.h
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* QEMU Floppy disk emulator (Intel 82078)
|
||||
*
|
||||
* Copyright (c) 2003, 2007 Jocelyn Mayer
|
||||
* Copyright (c) 2008 Hervé Poussineau
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef HW_BLOCK_FDC_INTERNAL_H
|
||||
#define HW_BLOCK_FDC_INTERNAL_H
|
||||
|
||||
#include "exec/memory.h"
|
||||
#include "exec/ioport.h"
|
||||
#include "hw/block/block.h"
|
||||
#include "hw/block/fdc.h"
|
||||
#include "qapi/qapi-types-block.h"
|
||||
|
||||
typedef struct FDCtrl FDCtrl;
|
||||
|
||||
/* Floppy bus emulation */
|
||||
|
||||
typedef struct FloppyBus {
|
||||
BusState bus;
|
||||
FDCtrl *fdc;
|
||||
} FloppyBus;
|
||||
|
||||
/* Floppy disk drive emulation */
|
||||
|
||||
typedef enum FDriveRate {
|
||||
FDRIVE_RATE_500K = 0x00, /* 500 Kbps */
|
||||
FDRIVE_RATE_300K = 0x01, /* 300 Kbps */
|
||||
FDRIVE_RATE_250K = 0x02, /* 250 Kbps */
|
||||
FDRIVE_RATE_1M = 0x03, /* 1 Mbps */
|
||||
} FDriveRate;
|
||||
|
||||
typedef enum FDriveSize {
|
||||
FDRIVE_SIZE_UNKNOWN,
|
||||
FDRIVE_SIZE_350,
|
||||
FDRIVE_SIZE_525,
|
||||
} FDriveSize;
|
||||
|
||||
typedef struct FDFormat {
|
||||
FloppyDriveType drive;
|
||||
uint8_t last_sect;
|
||||
uint8_t max_track;
|
||||
uint8_t max_head;
|
||||
FDriveRate rate;
|
||||
} FDFormat;
|
||||
|
||||
typedef enum FDiskFlags {
|
||||
FDISK_DBL_SIDES = 0x01,
|
||||
} FDiskFlags;
|
||||
|
||||
typedef struct FDrive {
|
||||
FDCtrl *fdctrl;
|
||||
BlockBackend *blk;
|
||||
BlockConf *conf;
|
||||
/* Drive status */
|
||||
FloppyDriveType drive; /* CMOS drive type */
|
||||
uint8_t perpendicular; /* 2.88 MB access mode */
|
||||
/* Position */
|
||||
uint8_t head;
|
||||
uint8_t track;
|
||||
uint8_t sect;
|
||||
/* Media */
|
||||
FloppyDriveType disk; /* Current disk type */
|
||||
FDiskFlags flags;
|
||||
uint8_t last_sect; /* Nb sector per track */
|
||||
uint8_t max_track; /* Nb of tracks */
|
||||
uint16_t bps; /* Bytes per sector */
|
||||
uint8_t ro; /* Is read-only */
|
||||
uint8_t media_changed; /* Is media changed */
|
||||
uint8_t media_rate; /* Data rate of medium */
|
||||
|
||||
bool media_validated; /* Have we validated the media? */
|
||||
} FDrive;
|
||||
|
||||
struct FDCtrl {
|
||||
MemoryRegion iomem;
|
||||
qemu_irq irq;
|
||||
/* Controller state */
|
||||
QEMUTimer *result_timer;
|
||||
int dma_chann;
|
||||
uint8_t phase;
|
||||
IsaDma *dma;
|
||||
/* Controller's identification */
|
||||
uint8_t version;
|
||||
/* HW */
|
||||
uint8_t sra;
|
||||
uint8_t srb;
|
||||
uint8_t dor;
|
||||
uint8_t dor_vmstate; /* only used as temp during vmstate */
|
||||
uint8_t tdr;
|
||||
uint8_t dsr;
|
||||
uint8_t msr;
|
||||
uint8_t cur_drv;
|
||||
uint8_t status0;
|
||||
uint8_t status1;
|
||||
uint8_t status2;
|
||||
/* Command FIFO */
|
||||
uint8_t *fifo;
|
||||
int32_t fifo_size;
|
||||
uint32_t data_pos;
|
||||
uint32_t data_len;
|
||||
uint8_t data_state;
|
||||
uint8_t data_dir;
|
||||
uint8_t eot; /* last wanted sector */
|
||||
/* States kept only to be returned back */
|
||||
/* precompensation */
|
||||
uint8_t precomp_trk;
|
||||
uint8_t config;
|
||||
uint8_t lock;
|
||||
/* Power down config (also with status regB access mode */
|
||||
uint8_t pwrd;
|
||||
/* Floppy drives */
|
||||
FloppyBus bus;
|
||||
uint8_t num_floppies;
|
||||
FDrive drives[MAX_FD];
|
||||
struct {
|
||||
FloppyDriveType type;
|
||||
} qdev_for_drives[MAX_FD];
|
||||
int reset_sensei;
|
||||
FloppyDriveType fallback; /* type=auto failure fallback */
|
||||
/* Timers state */
|
||||
uint8_t timer0;
|
||||
uint8_t timer1;
|
||||
PortioList portio_list;
|
||||
};
|
||||
|
||||
extern const FDFormat fd_formats[];
|
||||
extern const VMStateDescription vmstate_fdc;
|
||||
|
||||
uint32_t fdctrl_read(void *opaque, uint32_t reg);
|
||||
void fdctrl_write(void *opaque, uint32_t reg, uint32_t value);
|
||||
void fdctrl_reset(FDCtrl *fdctrl, int do_irq);
|
||||
void fdctrl_realize_common(DeviceState *dev, FDCtrl *fdctrl, Error **errp);
|
||||
|
||||
int fdctrl_transfer_handler(void *opaque, int nchan, int dma_pos, int dma_len);
|
||||
|
||||
void fdctrl_init_drives(FloppyBus *bus, DriveInfo **fds);
|
||||
|
||||
#endif
|
320
hw/block/fdc-isa.c
Normal file
320
hw/block/fdc-isa.c
Normal file
@ -0,0 +1,320 @@
|
||||
/*
|
||||
* QEMU Floppy disk emulator (Intel 82078)
|
||||
*
|
||||
* Copyright (c) 2003, 2007 Jocelyn Mayer
|
||||
* Copyright (c) 2008 Hervé Poussineau
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
/*
|
||||
* The controller is used in Sun4m systems in a slightly different
|
||||
* way. There are changes in DOR register and DMA is not available.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/block/fdc.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "hw/acpi/aml-build.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/isa/isa.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/qdev-properties-system.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "hw/block/block.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
#include "trace.h"
|
||||
#include "qom/object.h"
|
||||
#include "fdc-internal.h"
|
||||
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(FDCtrlISABus, ISA_FDC)
|
||||
|
||||
struct FDCtrlISABus {
|
||||
/*< private >*/
|
||||
ISADevice parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
uint32_t iobase;
|
||||
uint32_t irq;
|
||||
uint32_t dma;
|
||||
struct FDCtrl state;
|
||||
int32_t bootindexA;
|
||||
int32_t bootindexB;
|
||||
};
|
||||
|
||||
static void fdctrl_external_reset_isa(DeviceState *d)
|
||||
{
|
||||
FDCtrlISABus *isa = ISA_FDC(d);
|
||||
FDCtrl *s = &isa->state;
|
||||
|
||||
fdctrl_reset(s, 0);
|
||||
}
|
||||
|
||||
void isa_fdc_init_drives(ISADevice *fdc, DriveInfo **fds)
|
||||
{
|
||||
fdctrl_init_drives(&ISA_FDC(fdc)->state.bus, fds);
|
||||
}
|
||||
|
||||
static const MemoryRegionPortio fdc_portio_list[] = {
|
||||
{ 1, 5, 1, .read = fdctrl_read, .write = fdctrl_write },
|
||||
{ 7, 1, 1, .read = fdctrl_read, .write = fdctrl_write },
|
||||
PORTIO_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void isabus_fdc_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
ISADevice *isadev = ISA_DEVICE(dev);
|
||||
FDCtrlISABus *isa = ISA_FDC(dev);
|
||||
FDCtrl *fdctrl = &isa->state;
|
||||
Error *err = NULL;
|
||||
|
||||
isa_register_portio_list(isadev, &fdctrl->portio_list,
|
||||
isa->iobase, fdc_portio_list, fdctrl,
|
||||
"fdc");
|
||||
|
||||
isa_init_irq(isadev, &fdctrl->irq, isa->irq);
|
||||
fdctrl->dma_chann = isa->dma;
|
||||
if (fdctrl->dma_chann != -1) {
|
||||
IsaDmaClass *k;
|
||||
fdctrl->dma = isa_get_dma(isa_bus_from_device(isadev), isa->dma);
|
||||
if (!fdctrl->dma) {
|
||||
error_setg(errp, "ISA controller does not support DMA");
|
||||
return;
|
||||
}
|
||||
k = ISADMA_GET_CLASS(fdctrl->dma);
|
||||
k->register_channel(fdctrl->dma, fdctrl->dma_chann,
|
||||
&fdctrl_transfer_handler, fdctrl);
|
||||
}
|
||||
|
||||
qdev_set_legacy_instance_id(dev, isa->iobase, 2);
|
||||
|
||||
fdctrl_realize_common(dev, fdctrl, &err);
|
||||
if (err != NULL) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
FloppyDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i)
|
||||
{
|
||||
FDCtrlISABus *isa = ISA_FDC(fdc);
|
||||
|
||||
return isa->state.drives[i].drive;
|
||||
}
|
||||
|
||||
static void isa_fdc_get_drive_max_chs(FloppyDriveType type, uint8_t *maxc,
|
||||
uint8_t *maxh, uint8_t *maxs)
|
||||
{
|
||||
const FDFormat *fdf;
|
||||
|
||||
*maxc = *maxh = *maxs = 0;
|
||||
for (fdf = fd_formats; fdf->drive != FLOPPY_DRIVE_TYPE_NONE; fdf++) {
|
||||
if (fdf->drive != type) {
|
||||
continue;
|
||||
}
|
||||
if (*maxc < fdf->max_track) {
|
||||
*maxc = fdf->max_track;
|
||||
}
|
||||
if (*maxh < fdf->max_head) {
|
||||
*maxh = fdf->max_head;
|
||||
}
|
||||
if (*maxs < fdf->last_sect) {
|
||||
*maxs = fdf->last_sect;
|
||||
}
|
||||
}
|
||||
(*maxc)--;
|
||||
}
|
||||
|
||||
static Aml *build_fdinfo_aml(int idx, FloppyDriveType type)
|
||||
{
|
||||
Aml *dev, *fdi;
|
||||
uint8_t maxc, maxh, maxs;
|
||||
|
||||
isa_fdc_get_drive_max_chs(type, &maxc, &maxh, &maxs);
|
||||
|
||||
dev = aml_device("FLP%c", 'A' + idx);
|
||||
|
||||
aml_append(dev, aml_name_decl("_ADR", aml_int(idx)));
|
||||
|
||||
fdi = aml_package(16);
|
||||
aml_append(fdi, aml_int(idx)); /* Drive Number */
|
||||
aml_append(fdi,
|
||||
aml_int(cmos_get_fd_drive_type(type))); /* Device Type */
|
||||
/*
|
||||
* the values below are the limits of the drive, and are thus independent
|
||||
* of the inserted media
|
||||
*/
|
||||
aml_append(fdi, aml_int(maxc)); /* Maximum Cylinder Number */
|
||||
aml_append(fdi, aml_int(maxs)); /* Maximum Sector Number */
|
||||
aml_append(fdi, aml_int(maxh)); /* Maximum Head Number */
|
||||
/*
|
||||
* SeaBIOS returns the below values for int 0x13 func 0x08 regardless of
|
||||
* the drive type, so shall we
|
||||
*/
|
||||
aml_append(fdi, aml_int(0xAF)); /* disk_specify_1 */
|
||||
aml_append(fdi, aml_int(0x02)); /* disk_specify_2 */
|
||||
aml_append(fdi, aml_int(0x25)); /* disk_motor_wait */
|
||||
aml_append(fdi, aml_int(0x02)); /* disk_sector_siz */
|
||||
aml_append(fdi, aml_int(0x12)); /* disk_eot */
|
||||
aml_append(fdi, aml_int(0x1B)); /* disk_rw_gap */
|
||||
aml_append(fdi, aml_int(0xFF)); /* disk_dtl */
|
||||
aml_append(fdi, aml_int(0x6C)); /* disk_formt_gap */
|
||||
aml_append(fdi, aml_int(0xF6)); /* disk_fill */
|
||||
aml_append(fdi, aml_int(0x0F)); /* disk_head_sttl */
|
||||
aml_append(fdi, aml_int(0x08)); /* disk_motor_strt */
|
||||
|
||||
aml_append(dev, aml_name_decl("_FDI", fdi));
|
||||
return dev;
|
||||
}
|
||||
|
||||
int cmos_get_fd_drive_type(FloppyDriveType fd0)
|
||||
{
|
||||
int val;
|
||||
|
||||
switch (fd0) {
|
||||
case FLOPPY_DRIVE_TYPE_144:
|
||||
/* 1.44 Mb 3"5 drive */
|
||||
val = 4;
|
||||
break;
|
||||
case FLOPPY_DRIVE_TYPE_288:
|
||||
/* 2.88 Mb 3"5 drive */
|
||||
val = 5;
|
||||
break;
|
||||
case FLOPPY_DRIVE_TYPE_120:
|
||||
/* 1.2 Mb 5"5 drive */
|
||||
val = 2;
|
||||
break;
|
||||
case FLOPPY_DRIVE_TYPE_NONE:
|
||||
default:
|
||||
val = 0;
|
||||
break;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static void fdc_isa_build_aml(ISADevice *isadev, Aml *scope)
|
||||
{
|
||||
Aml *dev;
|
||||
Aml *crs;
|
||||
int i;
|
||||
|
||||
#define ACPI_FDE_MAX_FD 4
|
||||
uint32_t fde_buf[5] = {
|
||||
0, 0, 0, 0, /* presence of floppy drives #0 - #3 */
|
||||
cpu_to_le32(2) /* tape presence (2 == never present) */
|
||||
};
|
||||
|
||||
crs = aml_resource_template();
|
||||
aml_append(crs, aml_io(AML_DECODE16, 0x03F2, 0x03F2, 0x00, 0x04));
|
||||
aml_append(crs, aml_io(AML_DECODE16, 0x03F7, 0x03F7, 0x00, 0x01));
|
||||
aml_append(crs, aml_irq_no_flags(6));
|
||||
aml_append(crs,
|
||||
aml_dma(AML_COMPATIBILITY, AML_NOTBUSMASTER, AML_TRANSFER8, 2));
|
||||
|
||||
dev = aml_device("FDC0");
|
||||
aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0700")));
|
||||
aml_append(dev, aml_name_decl("_CRS", crs));
|
||||
|
||||
for (i = 0; i < MIN(MAX_FD, ACPI_FDE_MAX_FD); i++) {
|
||||
FloppyDriveType type = isa_fdc_get_drive_type(isadev, i);
|
||||
|
||||
if (type < FLOPPY_DRIVE_TYPE_NONE) {
|
||||
fde_buf[i] = cpu_to_le32(1); /* drive present */
|
||||
aml_append(dev, build_fdinfo_aml(i, type));
|
||||
}
|
||||
}
|
||||
aml_append(dev, aml_name_decl("_FDE",
|
||||
aml_buffer(sizeof(fde_buf), (uint8_t *)fde_buf)));
|
||||
|
||||
aml_append(scope, dev);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_isa_fdc = {
|
||||
.name = "fdc",
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_STRUCT(state, FDCtrlISABus, 0, vmstate_fdc, FDCtrl),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static Property isa_fdc_properties[] = {
|
||||
DEFINE_PROP_UINT32("iobase", FDCtrlISABus, iobase, 0x3f0),
|
||||
DEFINE_PROP_UINT32("irq", FDCtrlISABus, irq, 6),
|
||||
DEFINE_PROP_UINT32("dma", FDCtrlISABus, dma, 2),
|
||||
DEFINE_PROP_SIGNED("fdtypeA", FDCtrlISABus, state.qdev_for_drives[0].type,
|
||||
FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
|
||||
FloppyDriveType),
|
||||
DEFINE_PROP_SIGNED("fdtypeB", FDCtrlISABus, state.qdev_for_drives[1].type,
|
||||
FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
|
||||
FloppyDriveType),
|
||||
DEFINE_PROP_SIGNED("fallback", FDCtrlISABus, state.fallback,
|
||||
FLOPPY_DRIVE_TYPE_288, qdev_prop_fdc_drive_type,
|
||||
FloppyDriveType),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void isabus_fdc_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
ISADeviceClass *isa = ISA_DEVICE_CLASS(klass);
|
||||
|
||||
dc->desc = "virtual floppy controller";
|
||||
dc->realize = isabus_fdc_realize;
|
||||
dc->fw_name = "fdc";
|
||||
dc->reset = fdctrl_external_reset_isa;
|
||||
dc->vmsd = &vmstate_isa_fdc;
|
||||
isa->build_aml = fdc_isa_build_aml;
|
||||
device_class_set_props(dc, isa_fdc_properties);
|
||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||
}
|
||||
|
||||
static void isabus_fdc_instance_init(Object *obj)
|
||||
{
|
||||
FDCtrlISABus *isa = ISA_FDC(obj);
|
||||
|
||||
device_add_bootindex_property(obj, &isa->bootindexA,
|
||||
"bootindexA", "/floppy@0",
|
||||
DEVICE(obj));
|
||||
device_add_bootindex_property(obj, &isa->bootindexB,
|
||||
"bootindexB", "/floppy@1",
|
||||
DEVICE(obj));
|
||||
}
|
||||
|
||||
static const TypeInfo isa_fdc_info = {
|
||||
.name = TYPE_ISA_FDC,
|
||||
.parent = TYPE_ISA_DEVICE,
|
||||
.instance_size = sizeof(FDCtrlISABus),
|
||||
.class_init = isabus_fdc_class_init,
|
||||
.instance_init = isabus_fdc_instance_init,
|
||||
};
|
||||
|
||||
static void isa_fdc_register_types(void)
|
||||
{
|
||||
type_register_static(&isa_fdc_info);
|
||||
}
|
||||
|
||||
type_init(isa_fdc_register_types)
|
251
hw/block/fdc-sysbus.c
Normal file
251
hw/block/fdc-sysbus.c
Normal file
@ -0,0 +1,251 @@
|
||||
/*
|
||||
* QEMU Floppy disk emulator (Intel 82078)
|
||||
*
|
||||
* Copyright (c) 2003, 2007 Jocelyn Mayer
|
||||
* Copyright (c) 2008 Hervé Poussineau
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qom/object.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/block/fdc.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "fdc-internal.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define TYPE_SYSBUS_FDC "base-sysbus-fdc"
|
||||
typedef struct FDCtrlSysBusClass FDCtrlSysBusClass;
|
||||
typedef struct FDCtrlSysBus FDCtrlSysBus;
|
||||
DECLARE_OBJ_CHECKERS(FDCtrlSysBus, FDCtrlSysBusClass,
|
||||
SYSBUS_FDC, TYPE_SYSBUS_FDC)
|
||||
|
||||
struct FDCtrlSysBusClass {
|
||||
/*< private >*/
|
||||
SysBusDeviceClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
bool use_strict_io;
|
||||
};
|
||||
|
||||
struct FDCtrlSysBus {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
struct FDCtrl state;
|
||||
};
|
||||
|
||||
static uint64_t fdctrl_read_mem(void *opaque, hwaddr reg, unsigned ize)
|
||||
{
|
||||
return fdctrl_read(opaque, (uint32_t)reg);
|
||||
}
|
||||
|
||||
static void fdctrl_write_mem(void *opaque, hwaddr reg,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
fdctrl_write(opaque, (uint32_t)reg, value);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps fdctrl_mem_ops = {
|
||||
.read = fdctrl_read_mem,
|
||||
.write = fdctrl_write_mem,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static const MemoryRegionOps fdctrl_mem_strict_ops = {
|
||||
.read = fdctrl_read_mem,
|
||||
.write = fdctrl_write_mem,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 1,
|
||||
.max_access_size = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static void fdctrl_external_reset_sysbus(DeviceState *d)
|
||||
{
|
||||
FDCtrlSysBus *sys = SYSBUS_FDC(d);
|
||||
FDCtrl *s = &sys->state;
|
||||
|
||||
fdctrl_reset(s, 0);
|
||||
}
|
||||
|
||||
static void fdctrl_handle_tc(void *opaque, int irq, int level)
|
||||
{
|
||||
trace_fdctrl_tc_pulse(level);
|
||||
}
|
||||
|
||||
void fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
|
||||
hwaddr mmio_base, DriveInfo **fds)
|
||||
{
|
||||
FDCtrl *fdctrl;
|
||||
DeviceState *dev;
|
||||
SysBusDevice *sbd;
|
||||
FDCtrlSysBus *sys;
|
||||
|
||||
dev = qdev_new("sysbus-fdc");
|
||||
sys = SYSBUS_FDC(dev);
|
||||
fdctrl = &sys->state;
|
||||
fdctrl->dma_chann = dma_chann; /* FIXME */
|
||||
sbd = SYS_BUS_DEVICE(dev);
|
||||
sysbus_realize_and_unref(sbd, &error_fatal);
|
||||
sysbus_connect_irq(sbd, 0, irq);
|
||||
sysbus_mmio_map(sbd, 0, mmio_base);
|
||||
|
||||
fdctrl_init_drives(&sys->state.bus, fds);
|
||||
}
|
||||
|
||||
void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base,
|
||||
DriveInfo **fds, qemu_irq *fdc_tc)
|
||||
{
|
||||
DeviceState *dev;
|
||||
FDCtrlSysBus *sys;
|
||||
|
||||
dev = qdev_new("sun-fdtwo");
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
sys = SYSBUS_FDC(dev);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(sys), 0, irq);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(sys), 0, io_base);
|
||||
*fdc_tc = qdev_get_gpio_in(dev, 0);
|
||||
|
||||
fdctrl_init_drives(&sys->state.bus, fds);
|
||||
}
|
||||
|
||||
static void sysbus_fdc_common_instance_init(Object *obj)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
FDCtrlSysBusClass *sbdc = SYSBUS_FDC_GET_CLASS(obj);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
FDCtrlSysBus *sys = SYSBUS_FDC(obj);
|
||||
FDCtrl *fdctrl = &sys->state;
|
||||
|
||||
qdev_set_legacy_instance_id(dev, 0 /* io */, 2); /* FIXME */
|
||||
|
||||
memory_region_init_io(&fdctrl->iomem, obj,
|
||||
sbdc->use_strict_io ? &fdctrl_mem_strict_ops
|
||||
: &fdctrl_mem_ops,
|
||||
fdctrl, "fdc", 0x08);
|
||||
sysbus_init_mmio(sbd, &fdctrl->iomem);
|
||||
|
||||
sysbus_init_irq(sbd, &fdctrl->irq);
|
||||
qdev_init_gpio_in(dev, fdctrl_handle_tc, 1);
|
||||
}
|
||||
|
||||
static void sysbus_fdc_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
FDCtrlSysBus *sys = SYSBUS_FDC(dev);
|
||||
FDCtrl *fdctrl = &sys->state;
|
||||
|
||||
fdctrl_realize_common(dev, fdctrl, errp);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_sysbus_fdc = {
|
||||
.name = "fdc",
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_STRUCT(state, FDCtrlSysBus, 0, vmstate_fdc, FDCtrl),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static void sysbus_fdc_common_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = sysbus_fdc_realize;
|
||||
dc->reset = fdctrl_external_reset_sysbus;
|
||||
dc->vmsd = &vmstate_sysbus_fdc;
|
||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo sysbus_fdc_common_typeinfo = {
|
||||
.name = TYPE_SYSBUS_FDC,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(FDCtrlSysBus),
|
||||
.instance_init = sysbus_fdc_common_instance_init,
|
||||
.abstract = true,
|
||||
.class_init = sysbus_fdc_common_class_init,
|
||||
.class_size = sizeof(FDCtrlSysBusClass),
|
||||
};
|
||||
|
||||
static Property sysbus_fdc_properties[] = {
|
||||
DEFINE_PROP_SIGNED("fdtypeA", FDCtrlSysBus, state.qdev_for_drives[0].type,
|
||||
FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
|
||||
FloppyDriveType),
|
||||
DEFINE_PROP_SIGNED("fdtypeB", FDCtrlSysBus, state.qdev_for_drives[1].type,
|
||||
FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
|
||||
FloppyDriveType),
|
||||
DEFINE_PROP_SIGNED("fallback", FDCtrlSysBus, state.fallback,
|
||||
FLOPPY_DRIVE_TYPE_144, qdev_prop_fdc_drive_type,
|
||||
FloppyDriveType),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void sysbus_fdc_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->desc = "virtual floppy controller";
|
||||
device_class_set_props(dc, sysbus_fdc_properties);
|
||||
}
|
||||
|
||||
static const TypeInfo sysbus_fdc_typeinfo = {
|
||||
.name = "sysbus-fdc",
|
||||
.parent = TYPE_SYSBUS_FDC,
|
||||
.class_init = sysbus_fdc_class_init,
|
||||
};
|
||||
|
||||
static Property sun4m_fdc_properties[] = {
|
||||
DEFINE_PROP_SIGNED("fdtype", FDCtrlSysBus, state.qdev_for_drives[0].type,
|
||||
FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
|
||||
FloppyDriveType),
|
||||
DEFINE_PROP_SIGNED("fallback", FDCtrlSysBus, state.fallback,
|
||||
FLOPPY_DRIVE_TYPE_144, qdev_prop_fdc_drive_type,
|
||||
FloppyDriveType),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void sun4m_fdc_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
FDCtrlSysBusClass *sbdc = SYSBUS_FDC_CLASS(klass);
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
sbdc->use_strict_io = true;
|
||||
dc->desc = "virtual floppy controller";
|
||||
device_class_set_props(dc, sun4m_fdc_properties);
|
||||
}
|
||||
|
||||
static const TypeInfo sun4m_fdc_typeinfo = {
|
||||
.name = "sun-fdtwo",
|
||||
.parent = TYPE_SYSBUS_FDC,
|
||||
.class_init = sun4m_fdc_class_init,
|
||||
};
|
||||
|
||||
static void sysbus_fdc_register_types(void)
|
||||
{
|
||||
type_register_static(&sysbus_fdc_common_typeinfo);
|
||||
type_register_static(&sysbus_fdc_typeinfo);
|
||||
type_register_static(&sun4m_fdc_typeinfo);
|
||||
}
|
||||
|
||||
type_init(sysbus_fdc_register_types)
|
621
hw/block/fdc.c
621
hw/block/fdc.c
@ -32,12 +32,10 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "hw/acpi/aml-build.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/isa/isa.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/qdev-properties-system.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "hw/block/block.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
@ -48,6 +46,7 @@
|
||||
#include "qemu/module.h"
|
||||
#include "trace.h"
|
||||
#include "qom/object.h"
|
||||
#include "fdc-internal.h"
|
||||
|
||||
/********************************************************/
|
||||
/* debug Floppy devices */
|
||||
@ -68,15 +67,8 @@
|
||||
#define TYPE_FLOPPY_BUS "floppy-bus"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(FloppyBus, FLOPPY_BUS)
|
||||
|
||||
typedef struct FDCtrl FDCtrl;
|
||||
typedef struct FDrive FDrive;
|
||||
static FDrive *get_drv(FDCtrl *fdctrl, int unit);
|
||||
|
||||
struct FloppyBus {
|
||||
BusState bus;
|
||||
FDCtrl *fdc;
|
||||
};
|
||||
|
||||
static const TypeInfo floppy_bus_info = {
|
||||
.name = TYPE_FLOPPY_BUS,
|
||||
.parent = TYPE_BUS,
|
||||
@ -93,32 +85,11 @@ static void floppy_bus_create(FDCtrl *fdc, FloppyBus *bus, DeviceState *dev)
|
||||
/********************************************************/
|
||||
/* Floppy drive emulation */
|
||||
|
||||
typedef enum FDriveRate {
|
||||
FDRIVE_RATE_500K = 0x00, /* 500 Kbps */
|
||||
FDRIVE_RATE_300K = 0x01, /* 300 Kbps */
|
||||
FDRIVE_RATE_250K = 0x02, /* 250 Kbps */
|
||||
FDRIVE_RATE_1M = 0x03, /* 1 Mbps */
|
||||
} FDriveRate;
|
||||
|
||||
typedef enum FDriveSize {
|
||||
FDRIVE_SIZE_UNKNOWN,
|
||||
FDRIVE_SIZE_350,
|
||||
FDRIVE_SIZE_525,
|
||||
} FDriveSize;
|
||||
|
||||
typedef struct FDFormat {
|
||||
FloppyDriveType drive;
|
||||
uint8_t last_sect;
|
||||
uint8_t max_track;
|
||||
uint8_t max_head;
|
||||
FDriveRate rate;
|
||||
} FDFormat;
|
||||
|
||||
/* In many cases, the total sector size of a format is enough to uniquely
|
||||
* identify it. However, there are some total sector collisions between
|
||||
* formats of different physical size, and these are noted below by
|
||||
* highlighting the total sector size for entries with collisions. */
|
||||
static const FDFormat fd_formats[] = {
|
||||
const FDFormat fd_formats[] = {
|
||||
/* First entry is default format */
|
||||
/* 1.44 MB 3"1/2 floppy disks */
|
||||
{ FLOPPY_DRIVE_TYPE_144, 18, 80, 1, FDRIVE_RATE_500K, }, /* 3.5" 2880 */
|
||||
@ -186,35 +157,6 @@ static FDriveSize drive_size(FloppyDriveType drive)
|
||||
#define FD_SECTOR_SC 2 /* Sector size code */
|
||||
#define FD_RESET_SENSEI_COUNT 4 /* Number of sense interrupts on RESET */
|
||||
|
||||
/* Floppy disk drive emulation */
|
||||
typedef enum FDiskFlags {
|
||||
FDISK_DBL_SIDES = 0x01,
|
||||
} FDiskFlags;
|
||||
|
||||
struct FDrive {
|
||||
FDCtrl *fdctrl;
|
||||
BlockBackend *blk;
|
||||
BlockConf *conf;
|
||||
/* Drive status */
|
||||
FloppyDriveType drive; /* CMOS drive type */
|
||||
uint8_t perpendicular; /* 2.88 MB access mode */
|
||||
/* Position */
|
||||
uint8_t head;
|
||||
uint8_t track;
|
||||
uint8_t sect;
|
||||
/* Media */
|
||||
FloppyDriveType disk; /* Current disk type */
|
||||
FDiskFlags flags;
|
||||
uint8_t last_sect; /* Nb sector per track */
|
||||
uint8_t max_track; /* Nb of tracks */
|
||||
uint16_t bps; /* Bytes per sector */
|
||||
uint8_t ro; /* Is read-only */
|
||||
uint8_t media_changed; /* Is media changed */
|
||||
uint8_t media_rate; /* Data rate of medium */
|
||||
|
||||
bool media_validated; /* Have we validated the media? */
|
||||
};
|
||||
|
||||
|
||||
static FloppyDriveType get_fallback_drive_type(FDrive *drv);
|
||||
|
||||
@ -626,10 +568,7 @@ static const TypeInfo floppy_drive_info = {
|
||||
/********************************************************/
|
||||
/* Intel 82078 floppy disk controller emulation */
|
||||
|
||||
static void fdctrl_reset(FDCtrl *fdctrl, int do_irq);
|
||||
static void fdctrl_to_command_phase(FDCtrl *fdctrl);
|
||||
static int fdctrl_transfer_handler (void *opaque, int nchan,
|
||||
int dma_pos, int dma_len);
|
||||
static void fdctrl_raise_irq(FDCtrl *fdctrl);
|
||||
static FDrive *get_cur_drv(FDCtrl *fdctrl);
|
||||
|
||||
@ -828,88 +767,12 @@ enum {
|
||||
#define FD_MULTI_TRACK(state) ((state) & FD_STATE_MULTI)
|
||||
#define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT)
|
||||
|
||||
struct FDCtrl {
|
||||
MemoryRegion iomem;
|
||||
qemu_irq irq;
|
||||
/* Controller state */
|
||||
QEMUTimer *result_timer;
|
||||
int dma_chann;
|
||||
uint8_t phase;
|
||||
IsaDma *dma;
|
||||
/* Controller's identification */
|
||||
uint8_t version;
|
||||
/* HW */
|
||||
uint8_t sra;
|
||||
uint8_t srb;
|
||||
uint8_t dor;
|
||||
uint8_t dor_vmstate; /* only used as temp during vmstate */
|
||||
uint8_t tdr;
|
||||
uint8_t dsr;
|
||||
uint8_t msr;
|
||||
uint8_t cur_drv;
|
||||
uint8_t status0;
|
||||
uint8_t status1;
|
||||
uint8_t status2;
|
||||
/* Command FIFO */
|
||||
uint8_t *fifo;
|
||||
int32_t fifo_size;
|
||||
uint32_t data_pos;
|
||||
uint32_t data_len;
|
||||
uint8_t data_state;
|
||||
uint8_t data_dir;
|
||||
uint8_t eot; /* last wanted sector */
|
||||
/* States kept only to be returned back */
|
||||
/* precompensation */
|
||||
uint8_t precomp_trk;
|
||||
uint8_t config;
|
||||
uint8_t lock;
|
||||
/* Power down config (also with status regB access mode */
|
||||
uint8_t pwrd;
|
||||
/* Floppy drives */
|
||||
FloppyBus bus;
|
||||
uint8_t num_floppies;
|
||||
FDrive drives[MAX_FD];
|
||||
struct {
|
||||
FloppyDriveType type;
|
||||
} qdev_for_drives[MAX_FD];
|
||||
int reset_sensei;
|
||||
FloppyDriveType fallback; /* type=auto failure fallback */
|
||||
/* Timers state */
|
||||
uint8_t timer0;
|
||||
uint8_t timer1;
|
||||
PortioList portio_list;
|
||||
};
|
||||
|
||||
static FloppyDriveType get_fallback_drive_type(FDrive *drv)
|
||||
{
|
||||
return drv->fdctrl->fallback;
|
||||
}
|
||||
|
||||
#define TYPE_SYSBUS_FDC "base-sysbus-fdc"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(FDCtrlSysBus, SYSBUS_FDC)
|
||||
|
||||
struct FDCtrlSysBus {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
struct FDCtrl state;
|
||||
};
|
||||
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(FDCtrlISABus, ISA_FDC)
|
||||
|
||||
struct FDCtrlISABus {
|
||||
ISADevice parent_obj;
|
||||
|
||||
uint32_t iobase;
|
||||
uint32_t irq;
|
||||
uint32_t dma;
|
||||
struct FDCtrl state;
|
||||
int32_t bootindexA;
|
||||
int32_t bootindexB;
|
||||
};
|
||||
|
||||
static uint32_t fdctrl_read (void *opaque, uint32_t reg)
|
||||
uint32_t fdctrl_read(void *opaque, uint32_t reg)
|
||||
{
|
||||
FDCtrl *fdctrl = opaque;
|
||||
uint32_t retval;
|
||||
@ -946,7 +809,7 @@ static uint32_t fdctrl_read (void *opaque, uint32_t reg)
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value)
|
||||
void fdctrl_write(void *opaque, uint32_t reg, uint32_t value)
|
||||
{
|
||||
FDCtrl *fdctrl = opaque;
|
||||
|
||||
@ -973,34 +836,6 @@ static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value)
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t fdctrl_read_mem (void *opaque, hwaddr reg,
|
||||
unsigned ize)
|
||||
{
|
||||
return fdctrl_read(opaque, (uint32_t)reg);
|
||||
}
|
||||
|
||||
static void fdctrl_write_mem (void *opaque, hwaddr reg,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
fdctrl_write(opaque, (uint32_t)reg, value);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps fdctrl_mem_ops = {
|
||||
.read = fdctrl_read_mem,
|
||||
.write = fdctrl_write_mem,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static const MemoryRegionOps fdctrl_mem_strict_ops = {
|
||||
.read = fdctrl_read_mem,
|
||||
.write = fdctrl_write_mem,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 1,
|
||||
.max_access_size = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static bool fdrive_media_changed_needed(void *opaque)
|
||||
{
|
||||
FDrive *drive = opaque;
|
||||
@ -1178,7 +1013,7 @@ static const VMStateDescription vmstate_fdc_phase = {
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_fdc = {
|
||||
const VMStateDescription vmstate_fdc = {
|
||||
.name = "fdc",
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
@ -1224,32 +1059,6 @@ static const VMStateDescription vmstate_fdc = {
|
||||
}
|
||||
};
|
||||
|
||||
static void fdctrl_external_reset_sysbus(DeviceState *d)
|
||||
{
|
||||
FDCtrlSysBus *sys = SYSBUS_FDC(d);
|
||||
FDCtrl *s = &sys->state;
|
||||
|
||||
fdctrl_reset(s, 0);
|
||||
}
|
||||
|
||||
static void fdctrl_external_reset_isa(DeviceState *d)
|
||||
{
|
||||
FDCtrlISABus *isa = ISA_FDC(d);
|
||||
FDCtrl *s = &isa->state;
|
||||
|
||||
fdctrl_reset(s, 0);
|
||||
}
|
||||
|
||||
static void fdctrl_handle_tc(void *opaque, int irq, int level)
|
||||
{
|
||||
//FDCtrl *s = opaque;
|
||||
|
||||
if (level) {
|
||||
// XXX
|
||||
FLOPPY_DPRINTF("TC pulsed\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Change IRQ state */
|
||||
static void fdctrl_reset_irq(FDCtrl *fdctrl)
|
||||
{
|
||||
@ -1273,7 +1082,7 @@ static void fdctrl_raise_irq(FDCtrl *fdctrl)
|
||||
}
|
||||
|
||||
/* Reset controller */
|
||||
static void fdctrl_reset(FDCtrl *fdctrl, int do_irq)
|
||||
void fdctrl_reset(FDCtrl *fdctrl, int do_irq)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -1752,8 +1561,7 @@ static void fdctrl_start_transfer_del(FDCtrl *fdctrl, int direction)
|
||||
}
|
||||
|
||||
/* handlers for DMA transfers */
|
||||
static int fdctrl_transfer_handler (void *opaque, int nchan,
|
||||
int dma_pos, int dma_len)
|
||||
int fdctrl_transfer_handler(void *opaque, int nchan, int dma_pos, int dma_len)
|
||||
{
|
||||
FDCtrl *fdctrl;
|
||||
FDrive *cur_drv;
|
||||
@ -2489,7 +2297,7 @@ static void fdctrl_result_timer(void *opaque)
|
||||
|
||||
/* Init functions */
|
||||
|
||||
static void fdctrl_init_drives(FloppyBus *bus, DriveInfo **fds)
|
||||
void fdctrl_init_drives(FloppyBus *bus, DriveInfo **fds)
|
||||
{
|
||||
DeviceState *dev;
|
||||
int i;
|
||||
@ -2506,49 +2314,7 @@ static void fdctrl_init_drives(FloppyBus *bus, DriveInfo **fds)
|
||||
}
|
||||
}
|
||||
|
||||
void isa_fdc_init_drives(ISADevice *fdc, DriveInfo **fds)
|
||||
{
|
||||
fdctrl_init_drives(&ISA_FDC(fdc)->state.bus, fds);
|
||||
}
|
||||
|
||||
void fdctrl_init_sysbus(qemu_irq irq, int dma_chann,
|
||||
hwaddr mmio_base, DriveInfo **fds)
|
||||
{
|
||||
FDCtrl *fdctrl;
|
||||
DeviceState *dev;
|
||||
SysBusDevice *sbd;
|
||||
FDCtrlSysBus *sys;
|
||||
|
||||
dev = qdev_new("sysbus-fdc");
|
||||
sys = SYSBUS_FDC(dev);
|
||||
fdctrl = &sys->state;
|
||||
fdctrl->dma_chann = dma_chann; /* FIXME */
|
||||
sbd = SYS_BUS_DEVICE(dev);
|
||||
sysbus_realize_and_unref(sbd, &error_fatal);
|
||||
sysbus_connect_irq(sbd, 0, irq);
|
||||
sysbus_mmio_map(sbd, 0, mmio_base);
|
||||
|
||||
fdctrl_init_drives(&sys->state.bus, fds);
|
||||
}
|
||||
|
||||
void sun4m_fdctrl_init(qemu_irq irq, hwaddr io_base,
|
||||
DriveInfo **fds, qemu_irq *fdc_tc)
|
||||
{
|
||||
DeviceState *dev;
|
||||
FDCtrlSysBus *sys;
|
||||
|
||||
dev = qdev_new("sun-fdtwo");
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
sys = SYSBUS_FDC(dev);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(sys), 0, irq);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(sys), 0, io_base);
|
||||
*fdc_tc = qdev_get_gpio_in(dev, 0);
|
||||
|
||||
fdctrl_init_drives(&sys->state.bus, fds);
|
||||
}
|
||||
|
||||
static void fdctrl_realize_common(DeviceState *dev, FDCtrl *fdctrl,
|
||||
Error **errp)
|
||||
void fdctrl_realize_common(DeviceState *dev, FDCtrl *fdctrl, Error **errp)
|
||||
{
|
||||
int i, j;
|
||||
FDrive *drive;
|
||||
@ -2582,14 +2348,6 @@ static void fdctrl_realize_common(DeviceState *dev, FDCtrl *fdctrl,
|
||||
fdctrl->config = FD_CONFIG_EIS | FD_CONFIG_EFIFO; /* Implicit seek, polling & FIFO enabled */
|
||||
fdctrl->num_floppies = MAX_FD;
|
||||
|
||||
if (fdctrl->dma_chann != -1) {
|
||||
IsaDmaClass *k;
|
||||
assert(fdctrl->dma);
|
||||
k = ISADMA_GET_CLASS(fdctrl->dma);
|
||||
k->register_channel(fdctrl->dma, fdctrl->dma_chann,
|
||||
&fdctrl_transfer_handler, fdctrl);
|
||||
}
|
||||
|
||||
floppy_bus_create(fdctrl, &fdctrl->bus, dev);
|
||||
|
||||
for (i = 0; i < MAX_FD; i++) {
|
||||
@ -2600,369 +2358,8 @@ static void fdctrl_realize_common(DeviceState *dev, FDCtrl *fdctrl,
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionPortio fdc_portio_list[] = {
|
||||
{ 1, 5, 1, .read = fdctrl_read, .write = fdctrl_write },
|
||||
{ 7, 1, 1, .read = fdctrl_read, .write = fdctrl_write },
|
||||
PORTIO_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void isabus_fdc_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
ISADevice *isadev = ISA_DEVICE(dev);
|
||||
FDCtrlISABus *isa = ISA_FDC(dev);
|
||||
FDCtrl *fdctrl = &isa->state;
|
||||
Error *err = NULL;
|
||||
|
||||
isa_register_portio_list(isadev, &fdctrl->portio_list,
|
||||
isa->iobase, fdc_portio_list, fdctrl,
|
||||
"fdc");
|
||||
|
||||
isa_init_irq(isadev, &fdctrl->irq, isa->irq);
|
||||
fdctrl->dma_chann = isa->dma;
|
||||
if (fdctrl->dma_chann != -1) {
|
||||
fdctrl->dma = isa_get_dma(isa_bus_from_device(isadev), isa->dma);
|
||||
if (!fdctrl->dma) {
|
||||
error_setg(errp, "ISA controller does not support DMA");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
qdev_set_legacy_instance_id(dev, isa->iobase, 2);
|
||||
fdctrl_realize_common(dev, fdctrl, &err);
|
||||
if (err != NULL) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void sysbus_fdc_initfn(Object *obj)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
FDCtrlSysBus *sys = SYSBUS_FDC(obj);
|
||||
FDCtrl *fdctrl = &sys->state;
|
||||
|
||||
fdctrl->dma_chann = -1;
|
||||
|
||||
memory_region_init_io(&fdctrl->iomem, obj, &fdctrl_mem_ops, fdctrl,
|
||||
"fdc", 0x08);
|
||||
sysbus_init_mmio(sbd, &fdctrl->iomem);
|
||||
}
|
||||
|
||||
static void sun4m_fdc_initfn(Object *obj)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
FDCtrlSysBus *sys = SYSBUS_FDC(obj);
|
||||
FDCtrl *fdctrl = &sys->state;
|
||||
|
||||
fdctrl->dma_chann = -1;
|
||||
|
||||
memory_region_init_io(&fdctrl->iomem, obj, &fdctrl_mem_strict_ops,
|
||||
fdctrl, "fdctrl", 0x08);
|
||||
sysbus_init_mmio(sbd, &fdctrl->iomem);
|
||||
}
|
||||
|
||||
static void sysbus_fdc_common_initfn(Object *obj)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
FDCtrlSysBus *sys = SYSBUS_FDC(obj);
|
||||
FDCtrl *fdctrl = &sys->state;
|
||||
|
||||
qdev_set_legacy_instance_id(dev, 0 /* io */, 2); /* FIXME */
|
||||
|
||||
sysbus_init_irq(sbd, &fdctrl->irq);
|
||||
qdev_init_gpio_in(dev, fdctrl_handle_tc, 1);
|
||||
}
|
||||
|
||||
static void sysbus_fdc_common_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
FDCtrlSysBus *sys = SYSBUS_FDC(dev);
|
||||
FDCtrl *fdctrl = &sys->state;
|
||||
|
||||
fdctrl_realize_common(dev, fdctrl, errp);
|
||||
}
|
||||
|
||||
FloppyDriveType isa_fdc_get_drive_type(ISADevice *fdc, int i)
|
||||
{
|
||||
FDCtrlISABus *isa = ISA_FDC(fdc);
|
||||
|
||||
return isa->state.drives[i].drive;
|
||||
}
|
||||
|
||||
static void isa_fdc_get_drive_max_chs(FloppyDriveType type, uint8_t *maxc,
|
||||
uint8_t *maxh, uint8_t *maxs)
|
||||
{
|
||||
const FDFormat *fdf;
|
||||
|
||||
*maxc = *maxh = *maxs = 0;
|
||||
for (fdf = fd_formats; fdf->drive != FLOPPY_DRIVE_TYPE_NONE; fdf++) {
|
||||
if (fdf->drive != type) {
|
||||
continue;
|
||||
}
|
||||
if (*maxc < fdf->max_track) {
|
||||
*maxc = fdf->max_track;
|
||||
}
|
||||
if (*maxh < fdf->max_head) {
|
||||
*maxh = fdf->max_head;
|
||||
}
|
||||
if (*maxs < fdf->last_sect) {
|
||||
*maxs = fdf->last_sect;
|
||||
}
|
||||
}
|
||||
(*maxc)--;
|
||||
}
|
||||
|
||||
static Aml *build_fdinfo_aml(int idx, FloppyDriveType type)
|
||||
{
|
||||
Aml *dev, *fdi;
|
||||
uint8_t maxc, maxh, maxs;
|
||||
|
||||
isa_fdc_get_drive_max_chs(type, &maxc, &maxh, &maxs);
|
||||
|
||||
dev = aml_device("FLP%c", 'A' + idx);
|
||||
|
||||
aml_append(dev, aml_name_decl("_ADR", aml_int(idx)));
|
||||
|
||||
fdi = aml_package(16);
|
||||
aml_append(fdi, aml_int(idx)); /* Drive Number */
|
||||
aml_append(fdi,
|
||||
aml_int(cmos_get_fd_drive_type(type))); /* Device Type */
|
||||
/*
|
||||
* the values below are the limits of the drive, and are thus independent
|
||||
* of the inserted media
|
||||
*/
|
||||
aml_append(fdi, aml_int(maxc)); /* Maximum Cylinder Number */
|
||||
aml_append(fdi, aml_int(maxs)); /* Maximum Sector Number */
|
||||
aml_append(fdi, aml_int(maxh)); /* Maximum Head Number */
|
||||
/*
|
||||
* SeaBIOS returns the below values for int 0x13 func 0x08 regardless of
|
||||
* the drive type, so shall we
|
||||
*/
|
||||
aml_append(fdi, aml_int(0xAF)); /* disk_specify_1 */
|
||||
aml_append(fdi, aml_int(0x02)); /* disk_specify_2 */
|
||||
aml_append(fdi, aml_int(0x25)); /* disk_motor_wait */
|
||||
aml_append(fdi, aml_int(0x02)); /* disk_sector_siz */
|
||||
aml_append(fdi, aml_int(0x12)); /* disk_eot */
|
||||
aml_append(fdi, aml_int(0x1B)); /* disk_rw_gap */
|
||||
aml_append(fdi, aml_int(0xFF)); /* disk_dtl */
|
||||
aml_append(fdi, aml_int(0x6C)); /* disk_formt_gap */
|
||||
aml_append(fdi, aml_int(0xF6)); /* disk_fill */
|
||||
aml_append(fdi, aml_int(0x0F)); /* disk_head_sttl */
|
||||
aml_append(fdi, aml_int(0x08)); /* disk_motor_strt */
|
||||
|
||||
aml_append(dev, aml_name_decl("_FDI", fdi));
|
||||
return dev;
|
||||
}
|
||||
|
||||
int cmos_get_fd_drive_type(FloppyDriveType fd0)
|
||||
{
|
||||
int val;
|
||||
|
||||
switch (fd0) {
|
||||
case FLOPPY_DRIVE_TYPE_144:
|
||||
/* 1.44 Mb 3"5 drive */
|
||||
val = 4;
|
||||
break;
|
||||
case FLOPPY_DRIVE_TYPE_288:
|
||||
/* 2.88 Mb 3"5 drive */
|
||||
val = 5;
|
||||
break;
|
||||
case FLOPPY_DRIVE_TYPE_120:
|
||||
/* 1.2 Mb 5"5 drive */
|
||||
val = 2;
|
||||
break;
|
||||
case FLOPPY_DRIVE_TYPE_NONE:
|
||||
default:
|
||||
val = 0;
|
||||
break;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static void fdc_isa_build_aml(ISADevice *isadev, Aml *scope)
|
||||
{
|
||||
Aml *dev;
|
||||
Aml *crs;
|
||||
int i;
|
||||
|
||||
#define ACPI_FDE_MAX_FD 4
|
||||
uint32_t fde_buf[5] = {
|
||||
0, 0, 0, 0, /* presence of floppy drives #0 - #3 */
|
||||
cpu_to_le32(2) /* tape presence (2 == never present) */
|
||||
};
|
||||
|
||||
crs = aml_resource_template();
|
||||
aml_append(crs, aml_io(AML_DECODE16, 0x03F2, 0x03F2, 0x00, 0x04));
|
||||
aml_append(crs, aml_io(AML_DECODE16, 0x03F7, 0x03F7, 0x00, 0x01));
|
||||
aml_append(crs, aml_irq_no_flags(6));
|
||||
aml_append(crs,
|
||||
aml_dma(AML_COMPATIBILITY, AML_NOTBUSMASTER, AML_TRANSFER8, 2));
|
||||
|
||||
dev = aml_device("FDC0");
|
||||
aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0700")));
|
||||
aml_append(dev, aml_name_decl("_CRS", crs));
|
||||
|
||||
for (i = 0; i < MIN(MAX_FD, ACPI_FDE_MAX_FD); i++) {
|
||||
FloppyDriveType type = isa_fdc_get_drive_type(isadev, i);
|
||||
|
||||
if (type < FLOPPY_DRIVE_TYPE_NONE) {
|
||||
fde_buf[i] = cpu_to_le32(1); /* drive present */
|
||||
aml_append(dev, build_fdinfo_aml(i, type));
|
||||
}
|
||||
}
|
||||
aml_append(dev, aml_name_decl("_FDE",
|
||||
aml_buffer(sizeof(fde_buf), (uint8_t *)fde_buf)));
|
||||
|
||||
aml_append(scope, dev);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_isa_fdc ={
|
||||
.name = "fdc",
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_STRUCT(state, FDCtrlISABus, 0, vmstate_fdc, FDCtrl),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static Property isa_fdc_properties[] = {
|
||||
DEFINE_PROP_UINT32("iobase", FDCtrlISABus, iobase, 0x3f0),
|
||||
DEFINE_PROP_UINT32("irq", FDCtrlISABus, irq, 6),
|
||||
DEFINE_PROP_UINT32("dma", FDCtrlISABus, dma, 2),
|
||||
DEFINE_PROP_SIGNED("fdtypeA", FDCtrlISABus, state.qdev_for_drives[0].type,
|
||||
FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
|
||||
FloppyDriveType),
|
||||
DEFINE_PROP_SIGNED("fdtypeB", FDCtrlISABus, state.qdev_for_drives[1].type,
|
||||
FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
|
||||
FloppyDriveType),
|
||||
DEFINE_PROP_SIGNED("fallback", FDCtrlISABus, state.fallback,
|
||||
FLOPPY_DRIVE_TYPE_288, qdev_prop_fdc_drive_type,
|
||||
FloppyDriveType),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void isabus_fdc_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
ISADeviceClass *isa = ISA_DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = isabus_fdc_realize;
|
||||
dc->fw_name = "fdc";
|
||||
dc->reset = fdctrl_external_reset_isa;
|
||||
dc->vmsd = &vmstate_isa_fdc;
|
||||
isa->build_aml = fdc_isa_build_aml;
|
||||
device_class_set_props(dc, isa_fdc_properties);
|
||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||
}
|
||||
|
||||
static void isabus_fdc_instance_init(Object *obj)
|
||||
{
|
||||
FDCtrlISABus *isa = ISA_FDC(obj);
|
||||
|
||||
device_add_bootindex_property(obj, &isa->bootindexA,
|
||||
"bootindexA", "/floppy@0",
|
||||
DEVICE(obj));
|
||||
device_add_bootindex_property(obj, &isa->bootindexB,
|
||||
"bootindexB", "/floppy@1",
|
||||
DEVICE(obj));
|
||||
}
|
||||
|
||||
static const TypeInfo isa_fdc_info = {
|
||||
.name = TYPE_ISA_FDC,
|
||||
.parent = TYPE_ISA_DEVICE,
|
||||
.instance_size = sizeof(FDCtrlISABus),
|
||||
.class_init = isabus_fdc_class_init,
|
||||
.instance_init = isabus_fdc_instance_init,
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_sysbus_fdc ={
|
||||
.name = "fdc",
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_STRUCT(state, FDCtrlSysBus, 0, vmstate_fdc, FDCtrl),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static Property sysbus_fdc_properties[] = {
|
||||
DEFINE_PROP_SIGNED("fdtypeA", FDCtrlSysBus, state.qdev_for_drives[0].type,
|
||||
FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
|
||||
FloppyDriveType),
|
||||
DEFINE_PROP_SIGNED("fdtypeB", FDCtrlSysBus, state.qdev_for_drives[1].type,
|
||||
FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
|
||||
FloppyDriveType),
|
||||
DEFINE_PROP_SIGNED("fallback", FDCtrlSysBus, state.fallback,
|
||||
FLOPPY_DRIVE_TYPE_144, qdev_prop_fdc_drive_type,
|
||||
FloppyDriveType),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void sysbus_fdc_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
device_class_set_props(dc, sysbus_fdc_properties);
|
||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo sysbus_fdc_info = {
|
||||
.name = "sysbus-fdc",
|
||||
.parent = TYPE_SYSBUS_FDC,
|
||||
.instance_init = sysbus_fdc_initfn,
|
||||
.class_init = sysbus_fdc_class_init,
|
||||
};
|
||||
|
||||
static Property sun4m_fdc_properties[] = {
|
||||
DEFINE_PROP_SIGNED("fdtype", FDCtrlSysBus, state.qdev_for_drives[0].type,
|
||||
FLOPPY_DRIVE_TYPE_AUTO, qdev_prop_fdc_drive_type,
|
||||
FloppyDriveType),
|
||||
DEFINE_PROP_SIGNED("fallback", FDCtrlSysBus, state.fallback,
|
||||
FLOPPY_DRIVE_TYPE_144, qdev_prop_fdc_drive_type,
|
||||
FloppyDriveType),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void sun4m_fdc_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
device_class_set_props(dc, sun4m_fdc_properties);
|
||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo sun4m_fdc_info = {
|
||||
.name = "sun-fdtwo",
|
||||
.parent = TYPE_SYSBUS_FDC,
|
||||
.instance_init = sun4m_fdc_initfn,
|
||||
.class_init = sun4m_fdc_class_init,
|
||||
};
|
||||
|
||||
static void sysbus_fdc_common_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->realize = sysbus_fdc_common_realize;
|
||||
dc->reset = fdctrl_external_reset_sysbus;
|
||||
dc->vmsd = &vmstate_sysbus_fdc;
|
||||
}
|
||||
|
||||
static const TypeInfo sysbus_fdc_type_info = {
|
||||
.name = TYPE_SYSBUS_FDC,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(FDCtrlSysBus),
|
||||
.instance_init = sysbus_fdc_common_initfn,
|
||||
.abstract = true,
|
||||
.class_init = sysbus_fdc_common_class_init,
|
||||
};
|
||||
|
||||
static void fdc_register_types(void)
|
||||
{
|
||||
type_register_static(&isa_fdc_info);
|
||||
type_register_static(&sysbus_fdc_type_info);
|
||||
type_register_static(&sysbus_fdc_info);
|
||||
type_register_static(&sun4m_fdc_info);
|
||||
type_register_static(&floppy_bus_info);
|
||||
type_register_static(&floppy_drive_info);
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ softmmu_ss.add(files(
|
||||
))
|
||||
softmmu_ss.add(when: 'CONFIG_ECC', if_true: files('ecc.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_FDC', if_true: files('fdc.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_FDC_ISA', if_true: files('fdc-isa.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_FDC_SYSBUS', if_true: files('fdc-sysbus.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_NAND', if_true: files('nand.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_ONENAND', if_true: files('onenand.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_PFLASH_CFI01', if_true: files('pflash_cfi01.c'))
|
||||
|
@ -4,6 +4,9 @@
|
||||
fdc_ioport_read(uint8_t reg, uint8_t value) "read reg 0x%02x val 0x%02x"
|
||||
fdc_ioport_write(uint8_t reg, uint8_t value) "write reg 0x%02x val 0x%02x"
|
||||
|
||||
# fdc-sysbus.c
|
||||
fdctrl_tc_pulse(int level) "TC pulse: %u"
|
||||
|
||||
# pflash_cfi01.c
|
||||
# pflash_cfi02.c
|
||||
pflash_chip_erase_invalid(const char *name, uint64_t offset) "%s: chip erase: invalid address 0x%" PRIx64
|
||||
|
@ -24,7 +24,7 @@ config PC
|
||||
imply VGA_PCI
|
||||
imply VIRTIO_VGA
|
||||
imply NVDIMM
|
||||
select FDC
|
||||
select FDC_ISA
|
||||
select I8259
|
||||
select I8254
|
||||
select PCKBD
|
||||
|
@ -17,6 +17,7 @@ config ISA_SUPERIO
|
||||
bool
|
||||
select ISA_BUS
|
||||
select PCKBD
|
||||
select FDC_ISA
|
||||
|
||||
config PC87312
|
||||
bool
|
||||
@ -27,7 +28,7 @@ config PC87312
|
||||
select MC146818RTC
|
||||
select SERIAL_ISA
|
||||
select PARALLEL
|
||||
select FDC
|
||||
select FDC_ISA
|
||||
select IDE_ISA
|
||||
|
||||
config PIIX3
|
||||
@ -46,7 +47,7 @@ config VT82C686
|
||||
select ISA_SUPERIO
|
||||
select ACPI_SMBUS
|
||||
select SERIAL_ISA
|
||||
select FDC
|
||||
select FDC_ISA
|
||||
select USB_UHCI
|
||||
select APM
|
||||
|
||||
@ -55,7 +56,7 @@ config SMC37C669
|
||||
select ISA_SUPERIO
|
||||
select SERIAL_ISA
|
||||
select PARALLEL
|
||||
select FDC
|
||||
select FDC_ISA
|
||||
|
||||
config LPC_ICH9
|
||||
bool
|
||||
|
@ -20,7 +20,7 @@ config JAZZ
|
||||
select G364FB
|
||||
select DP8393X
|
||||
select ESP
|
||||
select FDC
|
||||
select FDC_SYSBUS
|
||||
select MC146818RTC
|
||||
select PCKBD
|
||||
select SERIAL
|
||||
|
@ -8,7 +8,7 @@ config SUN4M
|
||||
select UNIMP
|
||||
select ESCC
|
||||
select ESP
|
||||
select FDC
|
||||
select FDC_SYSBUS
|
||||
select SLAVIO
|
||||
select LANCE
|
||||
select M48T59
|
||||
|
@ -6,7 +6,7 @@ config SUN4U
|
||||
imply PARALLEL
|
||||
select M48T59
|
||||
select ISA_BUS
|
||||
select FDC
|
||||
select FDC_ISA
|
||||
select SERIAL_ISA
|
||||
select PCI_SABRE
|
||||
select IDE_CMD646
|
||||
|
Loading…
Reference in New Issue
Block a user