-----BEGIN PGP SIGNATURE-----

Version: GnuPG v1
 
 iQIcBAABAgAGBQJWsmNCAAoJEH3vgQaq/DkOQAEP/AwDY/JkKRQuTA2j8xvqxsrF
 ilzQhjvGva1WBU8iKP4L0ILvMbjzNrQh4LE31amY0Er+TDjRfqZkz7vc+/6cQ3uY
 FzXVKYySHbO3hbcamarr+sYu+T7D/6o4uvH04Vj0VDYiGJWcfKitBq2nfXbB55WW
 M9AgKLyMwvRPjfHu9Hp8BIIvQbQvzCnz0lB6q2Bzb4Gb/zR6qmXXXSLsTwXnfmD+
 LDLi/sN/hhdX2yMqNpDmNDqmGoX+NsK2C2AN0X9uEvQ0ePUcIScI338GfP9OeCGs
 To55rYGhyGCYdhEIGh8qdY47r87KrNxFtZXCMcv+oBbXuPIlpxZNESc+b5hzsWFp
 nAJq2FqVH0e69RDV/jl0TviNE8FO2auOZroD/VwWpY6Pk2rhYVUbc6dN13R69Bs5
 iGNEOBC1UI8eFOEEEoyHE+IHXCRodGUpDGa1oNzYvsPir1LKXoYqwwMjMCzDUUMA
 DEPdhQdj7Q9VzYI8GtTEuysunPfOGrjBsaMXvOgJMbU1wZqvqQU4gw5itJGeLGNC
 oc6yfIhmkv8j5N5l3qBzIOcU0iJGRlX2Z8pMPKjtvuLkkw6TBAm2Jal7Xkx8C3TX
 AGXE05khcq8y8wD3jtZJfpLlSkJoJpcD1BaAxig1H1t8hrtntUNnAQ9OfUnAuAZ5
 yjN4MOqG+rPelBqEaMMj
 =UnwI
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/jnsnow/tags/ide-pull-request' into staging

# gpg: Signature made Wed 03 Feb 2016 20:29:54 GMT using RSA key ID AAFC390E
# gpg: Good signature from "John Snow (John Huston) <jsnow@redhat.com>"

* remotes/jnsnow/tags/ide-pull-request:
  dma: remove now useless DMA_* functions
  sb16: use IsaDma interface instead of global DMA_* functions
  gus: use IsaDma interface instead of global DMA_* functions
  cs4231a: use IsaDma interface instead of global DMA_* functions
  fdc: use IsaDma interface instead of global DMA_* functions
  sparc64: disable floppy DMA
  sparc: disable floppy DMA
  magnum: disable floppy DMA for now
  i8257: implement the IsaDma interface
  isa: add an ISA DMA interface, and store it within the ISA bus
  i8257: move state definition to new independent header
  i8257: QOM'ify
  i8257: add missing const
  i8257: make the DMA running method per controller
  i8257: rename functions to start with i8257_ prefix
  i8257: rename struct dma_regs to I8257Regs
  i8257: rename struct dma_cont to I8257State
  i8257: pass ISA bus to DMA_init() function
  i82374: device only existed as ISA device, so simplify device
  fdc: fix detection under Linux

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2016-02-04 12:50:43 +00:00
commit ae533a46a1
16 changed files with 473 additions and 318 deletions

View File

@ -70,6 +70,7 @@ typedef struct CSState {
uint32_t irq;
uint32_t dma;
uint32_t port;
IsaDma *isa_dma;
int shift;
int dma_running;
int audio_free;
@ -265,6 +266,7 @@ static void cs_reset_voices (CSState *s, uint32_t val)
{
int xtal;
struct audsettings as;
IsaDmaClass *k = ISADMA_GET_CLASS(s->isa_dma);
#ifdef DEBUG_XLAW
if (val == 0 || val == 32)
@ -328,7 +330,7 @@ static void cs_reset_voices (CSState *s, uint32_t val)
if (s->dregs[Interface_Configuration] & PEN) {
if (!s->dma_running) {
DMA_hold_DREQ (s->dma);
k->hold_DREQ(s->isa_dma, s->dma);
AUD_set_active_out (s->voice, 1);
s->transferred = 0;
}
@ -336,7 +338,7 @@ static void cs_reset_voices (CSState *s, uint32_t val)
}
else {
if (s->dma_running) {
DMA_release_DREQ (s->dma);
k->release_DREQ(s->isa_dma, s->dma);
AUD_set_active_out (s->voice, 0);
}
s->dma_running = 0;
@ -345,7 +347,7 @@ static void cs_reset_voices (CSState *s, uint32_t val)
error:
if (s->dma_running) {
DMA_release_DREQ (s->dma);
k->release_DREQ(s->isa_dma, s->dma);
AUD_set_active_out (s->voice, 0);
}
}
@ -453,7 +455,8 @@ static void cs_write (void *opaque, hwaddr addr,
}
else {
if (s->dma_running) {
DMA_release_DREQ (s->dma);
IsaDmaClass *k = ISADMA_GET_CLASS(s->isa_dma);
k->release_DREQ(s->isa_dma, s->dma);
AUD_set_active_out (s->voice, 0);
s->dma_running = 0;
}
@ -518,6 +521,7 @@ static int cs_write_audio (CSState *s, int nchan, int dma_pos,
{
int temp, net;
uint8_t tmpbuf[4096];
IsaDmaClass *k = ISADMA_GET_CLASS(s->isa_dma);
temp = len;
net = 0;
@ -532,7 +536,7 @@ static int cs_write_audio (CSState *s, int nchan, int dma_pos,
to_copy = sizeof (tmpbuf);
}
copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
copied = k->read_memory(s->isa_dma, nchan, tmpbuf, dma_pos, to_copy);
if (s->tab) {
int i;
int16_t linbuf[4096];
@ -600,7 +604,8 @@ static int cs4231a_pre_load (void *opaque)
CSState *s = opaque;
if (s->dma_running) {
DMA_release_DREQ (s->dma);
IsaDmaClass *k = ISADMA_GET_CLASS(s->isa_dma);
k->release_DREQ(s->isa_dma, s->dma);
AUD_set_active_out (s->voice, 0);
}
s->dma_running = 0;
@ -656,13 +661,15 @@ static void cs4231a_realizefn (DeviceState *dev, Error **errp)
{
ISADevice *d = ISA_DEVICE (dev);
CSState *s = CS4231A (dev);
IsaDmaClass *k;
isa_init_irq (d, &s->pic, s->irq);
s->isa_dma = isa_get_dma(isa_bus_from_device(d), s->dma);
k = ISADMA_GET_CLASS(s->isa_dma);
k->register_channel(s->isa_dma, s->dma, cs_dma_read, s);
isa_register_ioport (d, &s->ioports, s->port);
DMA_register_channel (s->dma, cs_dma_read, s);
AUD_register_card ("cs4231a", &s->card);
}

View File

@ -58,6 +58,7 @@ typedef struct GUSState {
SWVoiceOut *voice;
int64_t last_ticks;
qemu_irq pic;
IsaDma *isa_dma;
} GUSState;
static uint32_t gus_readb(void *opaque, uint32_t nport)
@ -168,34 +169,36 @@ void GUS_irqclear (GUSEmuState *emu, int hwirq)
#endif
}
void GUS_dmarequest (GUSEmuState *der)
void GUS_dmarequest (GUSEmuState *emu)
{
/* GUSState *s = (GUSState *) der; */
GUSState *s = emu->opaque;
IsaDmaClass *k = ISADMA_GET_CLASS(s->isa_dma);
ldebug ("dma request %d\n", der->gusdma);
DMA_hold_DREQ (der->gusdma);
k->hold_DREQ(s->isa_dma, s->emu.gusdma);
}
static int GUS_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
{
GUSState *s = opaque;
IsaDmaClass *k = ISADMA_GET_CLASS(s->isa_dma);
char tmpbuf[4096];
int pos = dma_pos, mode, left = dma_len - dma_pos;
ldebug ("read DMA %#x %d\n", dma_pos, dma_len);
mode = DMA_get_channel_mode (s->emu.gusdma);
mode = k->has_autoinitialization(s->isa_dma, s->emu.gusdma);
while (left) {
int to_copy = audio_MIN ((size_t) left, sizeof (tmpbuf));
int copied;
ldebug ("left=%d to_copy=%d pos=%d\n", left, to_copy, pos);
copied = DMA_read_memory (nchan, tmpbuf, pos, to_copy);
copied = k->read_memory(s->isa_dma, nchan, tmpbuf, pos, to_copy);
gus_dma_transferdata (&s->emu, tmpbuf, copied, left == copied);
left -= copied;
pos += copied;
}
if (((mode >> 4) & 1) == 0) {
DMA_release_DREQ (s->emu.gusdma);
k->release_DREQ(s->isa_dma, s->emu.gusdma);
}
return dma_len;
}
@ -232,6 +235,7 @@ static void gus_realizefn (DeviceState *dev, Error **errp)
{
ISADevice *d = ISA_DEVICE(dev);
GUSState *s = GUS (dev);
IsaDmaClass *k;
struct audsettings as;
AUD_register_card ("gus", &s->card);
@ -264,7 +268,9 @@ static void gus_realizefn (DeviceState *dev, Error **errp)
isa_register_portio_list (d, (s->port + 0x100) & 0xf00,
gus_portio_list2, s, "gus");
DMA_register_channel (s->emu.gusdma, GUS_read_DMA, s);
s->isa_dma = isa_get_dma(isa_bus_from_device(d), s->emu.gusdma);
k = ISADMA_GET_CLASS(s->isa_dma);
k->register_channel(s->isa_dma, s->emu.gusdma, GUS_read_DMA, s);
s->emu.himemaddr = s->himem;
s->emu.gusdatapos = s->emu.himemaddr + 1024 * 1024 + 32;
s->emu.opaque = s;

View File

@ -56,6 +56,8 @@ typedef struct SB16State {
uint32_t hdma;
uint32_t port;
uint32_t ver;
IsaDma *isa_dma;
IsaDma *isa_hdma;
int in_index;
int out_data_len;
@ -166,16 +168,18 @@ static void speaker (SB16State *s, int on)
static void control (SB16State *s, int hold)
{
int dma = s->use_hdma ? s->hdma : s->dma;
IsaDma *isa_dma = s->use_hdma ? s->isa_hdma : s->isa_dma;
IsaDmaClass *k = ISADMA_GET_CLASS(isa_dma);
s->dma_running = hold;
ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
if (hold) {
DMA_hold_DREQ (dma);
k->hold_DREQ(isa_dma, dma);
AUD_set_active_out (s->voice, 1);
}
else {
DMA_release_DREQ (dma);
k->release_DREQ(isa_dma, dma);
AUD_set_active_out (s->voice, 0);
}
}
@ -1137,6 +1141,8 @@ static uint32_t mixer_read(void *opaque, uint32_t nport)
static int write_audio (SB16State *s, int nchan, int dma_pos,
int dma_len, int len)
{
IsaDma *isa_dma = nchan == s->dma ? s->isa_dma : s->isa_hdma;
IsaDmaClass *k = ISADMA_GET_CLASS(isa_dma);
int temp, net;
uint8_t tmpbuf[4096];
@ -1153,7 +1159,7 @@ static int write_audio (SB16State *s, int nchan, int dma_pos,
to_copy = sizeof (tmpbuf);
}
copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
copied = k->read_memory(isa_dma, nchan, tmpbuf, dma_pos, to_copy);
copied = AUD_write (s->voice, tmpbuf, copied);
temp -= copied;
@ -1355,6 +1361,7 @@ static void sb16_realizefn (DeviceState *dev, Error **errp)
{
ISADevice *isadev = ISA_DEVICE (dev);
SB16State *s = SB16 (dev);
IsaDmaClass *k;
isa_init_irq (isadev, &s->pic, s->irq);
@ -1373,8 +1380,14 @@ static void sb16_realizefn (DeviceState *dev, Error **errp)
isa_register_portio_list (isadev, s->port, sb16_ioport_list, s, "sb16");
DMA_register_channel (s->hdma, SB_read_DMA, s);
DMA_register_channel (s->dma, SB_read_DMA, s);
s->isa_hdma = isa_get_dma(isa_bus_from_device(isadev), s->hdma);
k = ISADMA_GET_CLASS(s->isa_hdma);
k->register_channel(s->isa_hdma, s->hdma, SB_read_DMA, s);
s->isa_dma = isa_get_dma(isa_bus_from_device(isadev), s->dma);
k = ISADMA_GET_CLASS(s->isa_dma);
k->register_channel(s->isa_dma, s->dma, SB_read_DMA, s);
s->can_write = 1;
AUD_register_card ("sb16", &s->card);

View File

@ -179,6 +179,21 @@ typedef struct FDrive {
static FloppyDriveType get_fallback_drive_type(FDrive *drv);
/* Hack: FD_SEEK is expected to work on empty drives. However, QEMU
* currently goes through some pains to keep seeks within the bounds
* established by last_sect and max_track. Correcting this is difficult,
* as refactoring FDC code tends to expose nasty bugs in the Linux kernel.
*
* For now: allow empty drives to have large bounds so we can seek around,
* with the understanding that when a diskette is inserted, the bounds will
* properly tighten to match the geometry of that inserted medium.
*/
static void fd_empty_seek_hack(FDrive *drv)
{
drv->last_sect = 0xFF;
drv->max_track = 0xFF;
}
static void fd_init(FDrive *drv)
{
/* Drive */
@ -394,6 +409,7 @@ static void fd_revalidate(FDrive *drv)
if (!blk_is_inserted(drv->blk)) {
FLOPPY_DPRINTF("No disk in drive\n");
drv->disk = FLOPPY_DRIVE_TYPE_NONE;
fd_empty_seek_hack(drv);
} else if (!drv->media_validated) {
rc = pick_geometry(drv);
if (rc) {
@ -628,6 +644,7 @@ struct FDCtrl {
QEMUTimer *result_timer;
int dma_chann;
uint8_t phase;
IsaDma *dma;
/* Controller's identification */
uint8_t version;
/* HW */
@ -1413,7 +1430,8 @@ static void fdctrl_stop_transfer(FDCtrl *fdctrl, uint8_t status0,
fdctrl->fifo[6] = FD_SECTOR_SC;
fdctrl->data_dir = FD_DIR_READ;
if (!(fdctrl->msr & FD_MSR_NONDMA)) {
DMA_release_DREQ(fdctrl->dma_chann);
IsaDmaClass *k = ISADMA_GET_CLASS(fdctrl->dma);
k->release_DREQ(fdctrl->dma, fdctrl->dma_chann);
}
fdctrl->msr |= FD_MSR_RQM | FD_MSR_DIO;
fdctrl->msr &= ~FD_MSR_NONDMA;
@ -1499,27 +1517,43 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
}
fdctrl->eot = fdctrl->fifo[6];
if (fdctrl->dor & FD_DOR_DMAEN) {
int dma_mode;
IsaDmaTransferMode dma_mode;
IsaDmaClass *k = ISADMA_GET_CLASS(fdctrl->dma);
bool dma_mode_ok;
/* DMA transfer are enabled. Check if DMA channel is well programmed */
dma_mode = DMA_get_channel_mode(fdctrl->dma_chann);
dma_mode = (dma_mode >> 2) & 3;
dma_mode = k->get_transfer_mode(fdctrl->dma, fdctrl->dma_chann);
FLOPPY_DPRINTF("dma_mode=%d direction=%d (%d - %d)\n",
dma_mode, direction,
(128 << fdctrl->fifo[5]) *
(cur_drv->last_sect - ks + 1), fdctrl->data_len);
if (((direction == FD_DIR_SCANE || direction == FD_DIR_SCANL ||
direction == FD_DIR_SCANH) && dma_mode == 0) ||
(direction == FD_DIR_WRITE && dma_mode == 2) ||
(direction == FD_DIR_READ && dma_mode == 1) ||
(direction == FD_DIR_VERIFY)) {
switch (direction) {
case FD_DIR_SCANE:
case FD_DIR_SCANL:
case FD_DIR_SCANH:
dma_mode_ok = (dma_mode == ISADMA_TRANSFER_VERIFY);
break;
case FD_DIR_WRITE:
dma_mode_ok = (dma_mode == ISADMA_TRANSFER_WRITE);
break;
case FD_DIR_READ:
dma_mode_ok = (dma_mode == ISADMA_TRANSFER_READ);
break;
case FD_DIR_VERIFY:
dma_mode_ok = true;
break;
default:
dma_mode_ok = false;
break;
}
if (dma_mode_ok) {
/* No access is allowed until DMA transfer has completed */
fdctrl->msr &= ~FD_MSR_RQM;
if (direction != FD_DIR_VERIFY) {
/* Now, we just have to wait for the DMA controller to
* recall us...
*/
DMA_hold_DREQ(fdctrl->dma_chann);
DMA_schedule();
k->hold_DREQ(fdctrl->dma, fdctrl->dma_chann);
k->schedule(fdctrl->dma);
} else {
/* Start transfer */
fdctrl_transfer_handler(fdctrl, fdctrl->dma_chann, 0,
@ -1558,12 +1592,14 @@ static int fdctrl_transfer_handler (void *opaque, int nchan,
FDrive *cur_drv;
int len, start_pos, rel_pos;
uint8_t status0 = 0x00, status1 = 0x00, status2 = 0x00;
IsaDmaClass *k;
fdctrl = opaque;
if (fdctrl->msr & FD_MSR_RQM) {
FLOPPY_DPRINTF("Not in DMA transfer mode !\n");
return 0;
}
k = ISADMA_GET_CLASS(fdctrl->dma);
cur_drv = get_cur_drv(fdctrl);
if (fdctrl->data_dir == FD_DIR_SCANE || fdctrl->data_dir == FD_DIR_SCANL ||
fdctrl->data_dir == FD_DIR_SCANH)
@ -1602,8 +1638,8 @@ static int fdctrl_transfer_handler (void *opaque, int nchan,
switch (fdctrl->data_dir) {
case FD_DIR_READ:
/* READ commands */
DMA_write_memory (nchan, fdctrl->fifo + rel_pos,
fdctrl->data_pos, len);
k->write_memory(fdctrl->dma, nchan, fdctrl->fifo + rel_pos,
fdctrl->data_pos, len);
break;
case FD_DIR_WRITE:
/* WRITE commands */
@ -1617,8 +1653,8 @@ static int fdctrl_transfer_handler (void *opaque, int nchan,
goto transfer_error;
}
DMA_read_memory (nchan, fdctrl->fifo + rel_pos,
fdctrl->data_pos, len);
k->read_memory(fdctrl->dma, nchan, fdctrl->fifo + rel_pos,
fdctrl->data_pos, len);
if (blk_write(cur_drv->blk, fd_sector(cur_drv),
fdctrl->fifo, 1) < 0) {
FLOPPY_DPRINTF("error writing sector %d\n",
@ -1635,7 +1671,8 @@ static int fdctrl_transfer_handler (void *opaque, int nchan,
{
uint8_t tmpbuf[FD_SECTOR_LEN];
int ret;
DMA_read_memory (nchan, tmpbuf, fdctrl->data_pos, len);
k->read_memory(fdctrl->dma, nchan, tmpbuf, fdctrl->data_pos,
len);
ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len);
if (ret == 0) {
status2 = FD_SR2_SEH;
@ -2425,7 +2462,11 @@ static void fdctrl_realize_common(FDCtrl *fdctrl, Error **errp)
fdctrl->num_floppies = MAX_FD;
if (fdctrl->dma_chann != -1) {
DMA_register_channel(fdctrl->dma_chann, &fdctrl_transfer_handler, fdctrl);
IsaDmaClass *k;
assert(fdctrl->dma);
k = ISADMA_GET_CLASS(fdctrl->dma);
k->register_channel(fdctrl->dma, fdctrl->dma_chann,
&fdctrl_transfer_handler, fdctrl);
}
fdctrl_connect_drives(fdctrl, errp);
}
@ -2448,6 +2489,10 @@ static void isabus_fdc_realize(DeviceState *dev, Error **errp)
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);
assert(fdctrl->dma);
}
qdev_set_legacy_instance_id(dev, isa->iobase, 2);
fdctrl_realize_common(fdctrl, &err);
@ -2476,6 +2521,8 @@ static void sun4m_fdc_initfn(Object *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);

View File

@ -25,6 +25,9 @@
#include "qemu/osdep.h"
#include "hw/isa/isa.h"
#define TYPE_I82374 "i82374"
#define I82374(obj) OBJECT_CHECK(I82374State, (obj), TYPE_I82374)
//#define DEBUG_I82374
#ifdef DEBUG_I82374
@ -38,6 +41,9 @@ do {} while (0)
do { fprintf(stderr, "i82374 ERROR: " fmt , ## __VA_ARGS__); } while (0)
typedef struct I82374State {
ISADevice parent_obj;
uint32_t iobase;
uint8_t commands[8];
PortioList port_list;
} I82374State;
@ -99,32 +105,6 @@ static uint32_t i82374_read_descriptor(void *opaque, uint32_t nport)
return val;
}
static void i82374_realize(I82374State *s, Error **errp)
{
DMA_init(1);
memset(s->commands, 0, sizeof(s->commands));
}
#define TYPE_I82374 "i82374"
#define I82374(obj) OBJECT_CHECK(ISAi82374State, (obj), TYPE_I82374)
typedef struct ISAi82374State {
ISADevice parent_obj;
uint32_t iobase;
I82374State state;
} ISAi82374State;
static const VMStateDescription vmstate_isa_i82374 = {
.name = "isa-i82374",
.version_id = 0,
.minimum_version_id = 0,
.fields = (VMStateField[]) {
VMSTATE_STRUCT(state, ISAi82374State, 0, vmstate_i82374, I82374State),
VMSTATE_END_OF_LIST()
},
};
static const MemoryRegionPortio i82374_portio_list[] = {
{ 0x0A, 1, 1, .read = i82374_read_isr, },
{ 0x10, 8, 1, .write = i82374_write_command, },
@ -134,21 +114,21 @@ static const MemoryRegionPortio i82374_portio_list[] = {
PORTIO_END_OF_LIST(),
};
static void i82374_isa_realize(DeviceState *dev, Error **errp)
static void i82374_realize(DeviceState *dev, Error **errp)
{
ISAi82374State *isa = I82374(dev);
I82374State *s = &isa->state;
I82374State *s = I82374(dev);
portio_list_init(&s->port_list, OBJECT(isa), i82374_portio_list, s,
portio_list_init(&s->port_list, OBJECT(s), i82374_portio_list, s,
"i82374");
portio_list_add(&s->port_list, isa_address_space_io(&isa->parent_obj),
isa->iobase);
portio_list_add(&s->port_list, isa_address_space_io(&s->parent_obj),
s->iobase);
i82374_realize(s, errp);
DMA_init(isa_bus_from_device(ISA_DEVICE(dev)), 1);
memset(s->commands, 0, sizeof(s->commands));
}
static Property i82374_properties[] = {
DEFINE_PROP_UINT32("iobase", ISAi82374State, iobase, 0x400),
DEFINE_PROP_UINT32("iobase", I82374State, iobase, 0x400),
DEFINE_PROP_END_OF_LIST()
};
@ -156,21 +136,21 @@ static void i82374_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = i82374_isa_realize;
dc->vmsd = &vmstate_isa_i82374;
dc->realize = i82374_realize;
dc->vmsd = &vmstate_i82374;
dc->props = i82374_properties;
}
static const TypeInfo i82374_isa_info = {
static const TypeInfo i82374_info = {
.name = TYPE_I82374,
.parent = TYPE_ISA_DEVICE,
.instance_size = sizeof(ISAi82374State),
.instance_size = sizeof(I82374State),
.class_init = i82374_class_init,
};
static void i82374_register_types(void)
{
type_register_static(&i82374_isa_info);
type_register_static(&i82374_info);
}
type_init(i82374_register_types)

View File

@ -24,9 +24,13 @@
#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/isa/isa.h"
#include "hw/isa/i8257.h"
#include "qemu/main-loop.h"
#include "trace.h"
#define I8257(obj) \
OBJECT_CHECK(I8257State, (obj), TYPE_I8257)
/* #define DEBUG_DMA */
#define dolog(...) fprintf (stderr, "dma: " __VA_ARGS__)
@ -38,32 +42,9 @@
#define ldebug(...)
#endif
struct dma_regs {
int now[2];
uint16_t base[2];
uint8_t mode;
uint8_t page;
uint8_t pageh;
uint8_t dack;
uint8_t eop;
DMA_transfer_handler transfer_handler;
void *opaque;
};
#define ADDR 0
#define COUNT 1
static struct dma_cont {
uint8_t status;
uint8_t command;
uint8_t mask;
uint8_t flip_flop;
int dshift;
struct dma_regs regs[4];
MemoryRegion channel_io;
MemoryRegion cont_io;
} dma_controllers[2];
enum {
CMD_MEMORY_TO_MEMORY = 0x01,
CMD_FIXED_ADDRESS = 0x02,
@ -79,13 +60,13 @@ enum {
};
static void DMA_run (void);
static void i8257_dma_run(void *opaque);
static int channels[8] = {-1, 2, 3, 1, -1, -1, -1, 0};
static const int channels[8] = {-1, 2, 3, 1, -1, -1, -1, 0};
static void write_page (void *opaque, uint32_t nport, uint32_t data)
static void i8257_write_page(void *opaque, uint32_t nport, uint32_t data)
{
struct dma_cont *d = opaque;
I8257State *d = opaque;
int ichan;
ichan = channels[nport & 7];
@ -96,9 +77,9 @@ static void write_page (void *opaque, uint32_t nport, uint32_t data)
d->regs[ichan].page = data;
}
static void write_pageh (void *opaque, uint32_t nport, uint32_t data)
static void i8257_write_pageh(void *opaque, uint32_t nport, uint32_t data)
{
struct dma_cont *d = opaque;
I8257State *d = opaque;
int ichan;
ichan = channels[nport & 7];
@ -109,9 +90,9 @@ static void write_pageh (void *opaque, uint32_t nport, uint32_t data)
d->regs[ichan].pageh = data;
}
static uint32_t read_page (void *opaque, uint32_t nport)
static uint32_t i8257_read_page(void *opaque, uint32_t nport)
{
struct dma_cont *d = opaque;
I8257State *d = opaque;
int ichan;
ichan = channels[nport & 7];
@ -122,9 +103,9 @@ static uint32_t read_page (void *opaque, uint32_t nport)
return d->regs[ichan].page;
}
static uint32_t read_pageh (void *opaque, uint32_t nport)
static uint32_t i8257_read_pageh(void *opaque, uint32_t nport)
{
struct dma_cont *d = opaque;
I8257State *d = opaque;
int ichan;
ichan = channels[nport & 7];
@ -135,16 +116,16 @@ static uint32_t read_pageh (void *opaque, uint32_t nport)
return d->regs[ichan].pageh;
}
static inline void init_chan (struct dma_cont *d, int ichan)
static inline void i8257_init_chan(I8257State *d, int ichan)
{
struct dma_regs *r;
I8257Regs *r;
r = d->regs + ichan;
r->now[ADDR] = r->base[ADDR] << d->dshift;
r->now[COUNT] = 0;
}
static inline int getff (struct dma_cont *d)
static inline int i8257_getff(I8257State *d)
{
int ff;
@ -153,11 +134,11 @@ static inline int getff (struct dma_cont *d)
return ff;
}
static uint64_t read_chan(void *opaque, hwaddr nport, unsigned size)
static uint64_t i8257_read_chan(void *opaque, hwaddr nport, unsigned size)
{
struct dma_cont *d = opaque;
I8257State *d = opaque;
int ichan, nreg, iport, ff, val, dir;
struct dma_regs *r;
I8257Regs *r;
iport = (nport >> d->dshift) & 0x0f;
ichan = iport >> 1;
@ -165,7 +146,7 @@ static uint64_t read_chan(void *opaque, hwaddr nport, unsigned size)
r = d->regs + ichan;
dir = ((r->mode >> 5) & 1) ? -1 : 1;
ff = getff (d);
ff = i8257_getff(d);
if (nreg)
val = (r->base[COUNT] << d->dshift) - r->now[COUNT];
else
@ -175,29 +156,29 @@ static uint64_t read_chan(void *opaque, hwaddr nport, unsigned size)
return (val >> (d->dshift + (ff << 3))) & 0xff;
}
static void write_chan(void *opaque, hwaddr nport, uint64_t data,
unsigned size)
static void i8257_write_chan(void *opaque, hwaddr nport, uint64_t data,
unsigned int size)
{
struct dma_cont *d = opaque;
I8257State *d = opaque;
int iport, ichan, nreg;
struct dma_regs *r;
I8257Regs *r;
iport = (nport >> d->dshift) & 0x0f;
ichan = iport >> 1;
nreg = iport & 1;
r = d->regs + ichan;
if (getff (d)) {
if (i8257_getff(d)) {
r->base[nreg] = (r->base[nreg] & 0xff) | ((data << 8) & 0xff00);
init_chan (d, ichan);
i8257_init_chan(d, ichan);
} else {
r->base[nreg] = (r->base[nreg] & 0xff00) | (data & 0xff);
}
}
static void write_cont(void *opaque, hwaddr nport, uint64_t data,
unsigned size)
static void i8257_write_cont(void *opaque, hwaddr nport, uint64_t data,
unsigned int size)
{
struct dma_cont *d = opaque;
I8257State *d = opaque;
int iport, ichan = 0;
iport = (nport >> d->dshift) & 0x0f;
@ -219,7 +200,7 @@ static void write_cont(void *opaque, hwaddr nport, uint64_t data,
d->status &= ~(1 << (ichan + 4));
}
d->status &= ~(1 << ichan);
DMA_run();
i8257_dma_run(d);
break;
case 0x02: /* single mask */
@ -227,7 +208,7 @@ static void write_cont(void *opaque, hwaddr nport, uint64_t data,
d->mask |= 1 << (data & 3);
else
d->mask &= ~(1 << (data & 3));
DMA_run();
i8257_dma_run(d);
break;
case 0x03: /* mode */
@ -262,12 +243,12 @@ static void write_cont(void *opaque, hwaddr nport, uint64_t data,
case 0x06: /* clear mask for all channels */
d->mask = 0;
DMA_run();
i8257_dma_run(d);
break;
case 0x07: /* write mask for all channels */
d->mask = data;
DMA_run();
i8257_dma_run(d);
break;
default:
@ -283,9 +264,9 @@ static void write_cont(void *opaque, hwaddr nport, uint64_t data,
#endif
}
static uint64_t read_cont(void *opaque, hwaddr nport, unsigned size)
static uint64_t i8257_read_cont(void *opaque, hwaddr nport, unsigned size)
{
struct dma_cont *d = opaque;
I8257State *d = opaque;
int iport, val;
iport = (nport >> d->dshift) & 0x0f;
@ -306,37 +287,43 @@ static uint64_t read_cont(void *opaque, hwaddr nport, unsigned size)
return val;
}
int DMA_get_channel_mode (int nchan)
static IsaDmaTransferMode i8257_dma_get_transfer_mode(IsaDma *obj, int nchan)
{
return dma_controllers[nchan > 3].regs[nchan & 3].mode;
I8257State *d = I8257(obj);
return (d->regs[nchan & 3].mode >> 2) & 3;
}
void DMA_hold_DREQ (int nchan)
static bool i8257_dma_has_autoinitialization(IsaDma *obj, int nchan)
{
int ncont, ichan;
I8257State *d = I8257(obj);
return (d->regs[nchan & 3].mode >> 4) & 1;
}
static void i8257_dma_hold_DREQ(IsaDma *obj, int nchan)
{
I8257State *d = I8257(obj);
int ichan;
ncont = nchan > 3;
ichan = nchan & 3;
linfo ("held cont=%d chan=%d\n", ncont, ichan);
dma_controllers[ncont].status |= 1 << (ichan + 4);
DMA_run();
d->status |= 1 << (ichan + 4);
i8257_dma_run(d);
}
void DMA_release_DREQ (int nchan)
static void i8257_dma_release_DREQ(IsaDma *obj, int nchan)
{
int ncont, ichan;
I8257State *d = I8257(obj);
int ichan;
ncont = nchan > 3;
ichan = nchan & 3;
linfo ("released cont=%d chan=%d\n", ncont, ichan);
dma_controllers[ncont].status &= ~(1 << (ichan + 4));
DMA_run();
d->status &= ~(1 << (ichan + 4));
i8257_dma_run(d);
}
static void channel_run (int ncont, int ichan)
static void i8257_channel_run(I8257State *d, int ichan)
{
int ncont = d->dshift;
int n;
struct dma_regs *r = &dma_controllers[ncont].regs[ichan];
I8257Regs *r = &d->regs[ichan];
#ifdef DEBUG_DMA
int dir, opmode;
@ -357,70 +344,58 @@ static void channel_run (int ncont, int ichan)
ldebug ("dma_pos %d size %d\n", n, (r->base[COUNT] + 1) << ncont);
}
static QEMUBH *dma_bh;
static bool dma_bh_scheduled;
static void DMA_run (void)
static void i8257_dma_run(void *opaque)
{
struct dma_cont *d;
int icont, ichan;
I8257State *d = opaque;
int ichan;
int rearm = 0;
static int running = 0;
if (running) {
if (d->running) {
rearm = 1;
goto out;
} else {
running = 1;
d->running = 1;
}
d = dma_controllers;
for (ichan = 0; ichan < 4; ichan++) {
int mask;
for (icont = 0; icont < 2; icont++, d++) {
for (ichan = 0; ichan < 4; ichan++) {
int mask;
mask = 1 << ichan;
mask = 1 << ichan;
if ((0 == (d->mask & mask)) && (0 != (d->status & (mask << 4)))) {
channel_run (icont, ichan);
rearm = 1;
}
if ((0 == (d->mask & mask)) && (0 != (d->status & (mask << 4)))) {
i8257_channel_run(d, ichan);
rearm = 1;
}
}
running = 0;
d->running = 0;
out:
if (rearm) {
qemu_bh_schedule_idle(dma_bh);
dma_bh_scheduled = true;
qemu_bh_schedule_idle(d->dma_bh);
d->dma_bh_scheduled = true;
}
}
static void DMA_run_bh(void *unused)
static void i8257_dma_register_channel(IsaDma *obj, int nchan,
DMA_transfer_handler transfer_handler,
void *opaque)
{
dma_bh_scheduled = false;
DMA_run();
}
I8257State *d = I8257(obj);
I8257Regs *r;
int ichan;
void DMA_register_channel (int nchan,
DMA_transfer_handler transfer_handler,
void *opaque)
{
struct dma_regs *r;
int ichan, ncont;
ncont = nchan > 3;
ichan = nchan & 3;
r = dma_controllers[ncont].regs + ichan;
r = d->regs + ichan;
r->transfer_handler = transfer_handler;
r->opaque = opaque;
}
int DMA_read_memory (int nchan, void *buf, int pos, int len)
static int i8257_dma_read_memory(IsaDma *obj, int nchan, void *buf, int pos,
int len)
{
struct dma_regs *r = &dma_controllers[nchan > 3].regs[nchan & 3];
I8257State *d = I8257(obj);
I8257Regs *r = &d->regs[nchan & 3];
hwaddr addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR];
if (r->mode & 0x20) {
@ -440,9 +415,11 @@ int DMA_read_memory (int nchan, void *buf, int pos, int len)
return len;
}
int DMA_write_memory (int nchan, void *buf, int pos, int len)
static int i8257_dma_write_memory(IsaDma *obj, int nchan, void *buf, int pos,
int len)
{
struct dma_regs *r = &dma_controllers[nchan > 3].regs[nchan & 3];
I8257State *s = I8257(obj);
I8257Regs *r = &s->regs[nchan & 3];
hwaddr addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR];
if (r->mode & 0x20) {
@ -465,20 +442,22 @@ int DMA_write_memory (int nchan, void *buf, int pos, int len)
/* request the emulator to transfer a new DMA memory block ASAP (even
* if the idle bottom half would not have exited the iothread yet).
*/
void DMA_schedule(void)
static void i8257_dma_schedule(IsaDma *obj)
{
if (dma_bh_scheduled) {
I8257State *d = I8257(obj);
if (d->dma_bh_scheduled) {
qemu_notify_event();
}
}
static void dma_reset(void *opaque)
static void i8257_reset(DeviceState *dev)
{
struct dma_cont *d = opaque;
write_cont(d, (0x05 << d->dshift), 0, 1);
I8257State *d = I8257(dev);
i8257_write_cont(d, (0x05 << d->dshift), 0, 1);
}
static int dma_phony_handler (void *opaque, int nchan, int dma_pos, int dma_len)
static int i8257_phony_handler(void *opaque, int nchan, int dma_pos,
int dma_len)
{
trace_i8257_unregistered_dma(nchan, dma_pos, dma_len);
return dma_pos;
@ -486,8 +465,8 @@ static int dma_phony_handler (void *opaque, int nchan, int dma_pos, int dma_len)
static const MemoryRegionOps channel_io_ops = {
.read = read_chan,
.write = write_chan,
.read = i8257_read_chan,
.write = i8257_write_chan,
.endianness = DEVICE_NATIVE_ENDIAN,
.impl = {
.min_access_size = 1,
@ -497,21 +476,21 @@ static const MemoryRegionOps channel_io_ops = {
/* IOport from page_base */
static const MemoryRegionPortio page_portio_list[] = {
{ 0x01, 3, 1, .write = write_page, .read = read_page, },
{ 0x07, 1, 1, .write = write_page, .read = read_page, },
{ 0x01, 3, 1, .write = i8257_write_page, .read = i8257_read_page, },
{ 0x07, 1, 1, .write = i8257_write_page, .read = i8257_read_page, },
PORTIO_END_OF_LIST(),
};
/* IOport from pageh_base */
static const MemoryRegionPortio pageh_portio_list[] = {
{ 0x01, 3, 1, .write = write_pageh, .read = read_pageh, },
{ 0x07, 3, 1, .write = write_pageh, .read = read_pageh, },
{ 0x01, 3, 1, .write = i8257_write_pageh, .read = i8257_read_pageh, },
{ 0x07, 3, 1, .write = i8257_write_pageh, .read = i8257_read_pageh, },
PORTIO_END_OF_LIST(),
};
static const MemoryRegionOps cont_io_ops = {
.read = read_cont,
.write = write_cont,
.read = i8257_read_cont,
.write = i8257_write_cont,
.endianness = DEVICE_NATIVE_ENDIAN,
.impl = {
.min_access_size = 1,
@ -519,82 +498,142 @@ static const MemoryRegionOps cont_io_ops = {
},
};
/* dshift = 0: 8 bit DMA, 1 = 16 bit DMA */
static void dma_init2(struct dma_cont *d, int base, int dshift,
int page_base, int pageh_base)
{
int i;
d->dshift = dshift;
memory_region_init_io(&d->channel_io, NULL, &channel_io_ops, d,
"dma-chan", 8 << d->dshift);
memory_region_add_subregion(isa_address_space_io(NULL),
base, &d->channel_io);
isa_register_portio_list(NULL, page_base, page_portio_list, d,
"dma-page");
if (pageh_base >= 0) {
isa_register_portio_list(NULL, pageh_base, pageh_portio_list, d,
"dma-pageh");
}
memory_region_init_io(&d->cont_io, NULL, &cont_io_ops, d, "dma-cont",
8 << d->dshift);
memory_region_add_subregion(isa_address_space_io(NULL),
base + (8 << d->dshift), &d->cont_io);
qemu_register_reset(dma_reset, d);
dma_reset(d);
for (i = 0; i < ARRAY_SIZE (d->regs); ++i) {
d->regs[i].transfer_handler = dma_phony_handler;
}
}
static const VMStateDescription vmstate_dma_regs = {
static const VMStateDescription vmstate_i8257_regs = {
.name = "dma_regs",
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_INT32_ARRAY(now, struct dma_regs, 2),
VMSTATE_UINT16_ARRAY(base, struct dma_regs, 2),
VMSTATE_UINT8(mode, struct dma_regs),
VMSTATE_UINT8(page, struct dma_regs),
VMSTATE_UINT8(pageh, struct dma_regs),
VMSTATE_UINT8(dack, struct dma_regs),
VMSTATE_UINT8(eop, struct dma_regs),
VMSTATE_INT32_ARRAY(now, I8257Regs, 2),
VMSTATE_UINT16_ARRAY(base, I8257Regs, 2),
VMSTATE_UINT8(mode, I8257Regs),
VMSTATE_UINT8(page, I8257Regs),
VMSTATE_UINT8(pageh, I8257Regs),
VMSTATE_UINT8(dack, I8257Regs),
VMSTATE_UINT8(eop, I8257Regs),
VMSTATE_END_OF_LIST()
}
};
static int dma_post_load(void *opaque, int version_id)
static int i8257_post_load(void *opaque, int version_id)
{
DMA_run();
I8257State *d = opaque;
i8257_dma_run(d);
return 0;
}
static const VMStateDescription vmstate_dma = {
static const VMStateDescription vmstate_i8257 = {
.name = "dma",
.version_id = 1,
.minimum_version_id = 1,
.post_load = dma_post_load,
.post_load = i8257_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINT8(command, struct dma_cont),
VMSTATE_UINT8(mask, struct dma_cont),
VMSTATE_UINT8(flip_flop, struct dma_cont),
VMSTATE_INT32(dshift, struct dma_cont),
VMSTATE_STRUCT_ARRAY(regs, struct dma_cont, 4, 1, vmstate_dma_regs, struct dma_regs),
VMSTATE_UINT8(command, I8257State),
VMSTATE_UINT8(mask, I8257State),
VMSTATE_UINT8(flip_flop, I8257State),
VMSTATE_INT32(dshift, I8257State),
VMSTATE_STRUCT_ARRAY(regs, I8257State, 4, 1, vmstate_i8257_regs,
I8257Regs),
VMSTATE_END_OF_LIST()
}
};
void DMA_init(int high_page_enable)
static void i8257_realize(DeviceState *dev, Error **errp)
{
dma_init2(&dma_controllers[0], 0x00, 0, 0x80, high_page_enable ? 0x480 : -1);
dma_init2(&dma_controllers[1], 0xc0, 1, 0x88, high_page_enable ? 0x488 : -1);
vmstate_register (NULL, 0, &vmstate_dma, &dma_controllers[0]);
vmstate_register (NULL, 1, &vmstate_dma, &dma_controllers[1]);
ISADevice *isa = ISA_DEVICE(dev);
I8257State *d = I8257(dev);
int i;
dma_bh = qemu_bh_new(DMA_run_bh, NULL);
memory_region_init_io(&d->channel_io, NULL, &channel_io_ops, d,
"dma-chan", 8 << d->dshift);
memory_region_add_subregion(isa_address_space_io(isa),
d->base, &d->channel_io);
isa_register_portio_list(isa, d->page_base, page_portio_list, d,
"dma-page");
if (d->pageh_base >= 0) {
isa_register_portio_list(isa, d->pageh_base, pageh_portio_list, d,
"dma-pageh");
}
memory_region_init_io(&d->cont_io, OBJECT(isa), &cont_io_ops, d,
"dma-cont", 8 << d->dshift);
memory_region_add_subregion(isa_address_space_io(isa),
d->base + (8 << d->dshift), &d->cont_io);
for (i = 0; i < ARRAY_SIZE(d->regs); ++i) {
d->regs[i].transfer_handler = i8257_phony_handler;
}
d->dma_bh = qemu_bh_new(i8257_dma_run, d);
}
static Property i8257_properties[] = {
DEFINE_PROP_INT32("base", I8257State, base, 0x00),
DEFINE_PROP_INT32("page-base", I8257State, page_base, 0x80),
DEFINE_PROP_INT32("pageh-base", I8257State, pageh_base, 0x480),
DEFINE_PROP_INT32("dshift", I8257State, dshift, 0),
DEFINE_PROP_END_OF_LIST()
};
static void i8257_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
IsaDmaClass *idc = ISADMA_CLASS(klass);
dc->realize = i8257_realize;
dc->reset = i8257_reset;
dc->vmsd = &vmstate_i8257;
dc->props = i8257_properties;
idc->get_transfer_mode = i8257_dma_get_transfer_mode;
idc->has_autoinitialization = i8257_dma_has_autoinitialization;
idc->read_memory = i8257_dma_read_memory;
idc->write_memory = i8257_dma_write_memory;
idc->hold_DREQ = i8257_dma_hold_DREQ;
idc->release_DREQ = i8257_dma_release_DREQ;
idc->schedule = i8257_dma_schedule;
idc->register_channel = i8257_dma_register_channel;
}
static const TypeInfo i8257_info = {
.name = TYPE_I8257,
.parent = TYPE_ISA_DEVICE,
.instance_size = sizeof(I8257State),
.class_init = i8257_class_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_ISADMA },
{ }
}
};
static void i8257_register_types(void)
{
type_register_static(&i8257_info);
}
type_init(i8257_register_types)
void DMA_init(ISABus *bus, int high_page_enable)
{
ISADevice *isa1, *isa2;
DeviceState *d;
isa1 = isa_create(bus, TYPE_I8257);
d = DEVICE(isa1);
qdev_prop_set_int32(d, "base", 0x00);
qdev_prop_set_int32(d, "page-base", 0x80);
qdev_prop_set_int32(d, "pageh-base", high_page_enable ? 0x480 : -1);
qdev_prop_set_int32(d, "dshift", 0);
qdev_init_nofail(d);
isa2 = isa_create(bus, TYPE_I8257);
d = DEVICE(isa2);
qdev_prop_set_int32(d, "base", 0xc0);
qdev_prop_set_int32(d, "page-base", 0x88);
qdev_prop_set_int32(d, "pageh-base", high_page_enable ? 0x488 : -1);
qdev_prop_set_int32(d, "dshift", 1);
qdev_init_nofail(d);
isa_bus_dma(bus, ISADMA(isa1), ISADMA(isa2));
}

View File

@ -1542,7 +1542,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
port92 = isa_create_simple(isa_bus, "port92");
port92_init(port92, &a20_line[1]);
DMA_init(0);
DMA_init(isa_bus, 0);
for(i = 0; i < MAX_FD; i++) {
fd[i] = drive_get(IF_FLOPPY, 0, i);

View File

@ -37,6 +37,12 @@ static void isa_bus_class_init(ObjectClass *klass, void *data)
k->get_fw_dev_path = isabus_get_fw_dev_path;
}
static const TypeInfo isa_dma_info = {
.name = TYPE_ISADMA,
.parent = TYPE_INTERFACE,
.class_size = sizeof(IsaDmaClass),
};
static const TypeInfo isa_bus_info = {
.name = TYPE_ISA_BUS,
.parent = TYPE_BUS,
@ -90,6 +96,20 @@ void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq)
dev->nirqs++;
}
void isa_bus_dma(ISABus *bus, IsaDma *dma8, IsaDma *dma16)
{
assert(bus && dma8 && dma16);
assert(!bus->dma[0] && !bus->dma[1]);
bus->dma[0] = dma8;
bus->dma[1] = dma16;
}
IsaDma *isa_get_dma(ISABus *bus, int nchan)
{
assert(bus);
return bus->dma[nchan > 3 ? 1 : 0];
}
static inline void isa_init_ioport(ISADevice *dev, uint16_t ioport)
{
if (dev && (dev->ioport_id == 0 || ioport < dev->ioport_id)) {
@ -223,6 +243,7 @@ static const TypeInfo isa_device_type_info = {
static void isabus_register_types(void)
{
type_register_static(&isa_dma_info);
type_register_static(&isa_bus_info);
type_register_static(&isabus_bridge_info);
type_register_static(&isa_device_type_info);

View File

@ -366,7 +366,7 @@ static void mips_fulong2e_init(MachineState *machine)
/* init other devices */
pit = pit_init(isa_bus, 0x40, 0, NULL);
DMA_init(0);
DMA_init(isa_bus, 0);
/* Super I/O */
isa_create_simple(isa_bus, "i8042");

View File

@ -225,7 +225,7 @@ static void mips_jazz_init(MachineState *machine,
/* ISA devices */
i8259 = i8259_init(isa_bus, env->irq[4]);
isa_bus_irqs(isa_bus, i8259);
DMA_init(0);
DMA_init(isa_bus, 0);
pit = pit_init(isa_bus, 0x40, 0, NULL);
pcspk_init(isa_bus, pit);
@ -297,7 +297,8 @@ static void mips_jazz_init(MachineState *machine,
for (n = 0; n < MAX_FD; n++) {
fds[n] = drive_get(IF_FLOPPY, 0, n);
}
fdctrl_init_sysbus(qdev_get_gpio_in(rc4030, 1), 0, 0x80003000, fds);
/* FIXME: we should enable DMA with a custom IsaDma device */
fdctrl_init_sysbus(qdev_get_gpio_in(rc4030, 1), -1, 0x80003000, fds);
/* Real time clock */
rtc_init(isa_bus, 1980, NULL);

View File

@ -1166,7 +1166,7 @@ void mips_malta_init(MachineState *machine)
smbus_eeprom_init(smbus, 8, smbus_eeprom_buf, smbus_eeprom_size);
g_free(smbus_eeprom_buf);
pit = pit_init(isa_bus, 0x40, 0, NULL);
DMA_init(0);
DMA_init(isa_bus, 0);
/* Super I/O */
isa_create_simple(isa_bus, "i8042");

View File

@ -96,29 +96,7 @@ struct sun4m_hwdef {
uint8_t nvram_machine_id;
};
int DMA_get_channel_mode (int nchan)
{
return 0;
}
int DMA_read_memory (int nchan, void *buf, int pos, int size)
{
return 0;
}
int DMA_write_memory (int nchan, void *buf, int pos, int size)
{
return 0;
}
void DMA_hold_DREQ (int nchan) {}
void DMA_release_DREQ (int nchan) {}
void DMA_schedule(void) {}
void DMA_init(int high_page_enable)
{
}
void DMA_register_channel (int nchan,
DMA_transfer_handler transfer_handler,
void *opaque)
void DMA_init(ISABus *bus, int high_page_enable)
{
}

View File

@ -99,29 +99,7 @@ typedef struct EbusState {
MemoryRegion bar1;
} EbusState;
int DMA_get_channel_mode (int nchan)
{
return 0;
}
int DMA_read_memory (int nchan, void *buf, int pos, int size)
{
return 0;
}
int DMA_write_memory (int nchan, void *buf, int pos, int size)
{
return 0;
}
void DMA_hold_DREQ (int nchan) {}
void DMA_release_DREQ (int nchan) {}
void DMA_schedule(void) {}
void DMA_init(int high_page_enable)
{
}
void DMA_register_channel (int nchan,
DMA_transfer_handler transfer_handler,
void *opaque)
void DMA_init(ISABus *bus, int high_page_enable)
{
}
@ -816,6 +794,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
qemu_irq *ivec_irqs, *pbm_irqs;
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
DriveInfo *fd[MAX_FD];
DeviceState *dev;
FWCfgState *fw_cfg;
/* init CPUs */
@ -852,10 +831,22 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
pci_cmd646_ide_init(pci_bus, hd, 1);
isa_create_simple(isa_bus, "i8042");
/* Floppy */
for(i = 0; i < MAX_FD; i++) {
fd[i] = drive_get(IF_FLOPPY, 0, i);
}
fdctrl_init_isa(isa_bus, fd);
dev = DEVICE(isa_create(isa_bus, TYPE_ISA_FDC));
if (fd[0]) {
qdev_prop_set_drive(dev, "driveA", blk_by_legacy_dinfo(fd[0]),
&error_abort);
}
if (fd[1]) {
qdev_prop_set_drive(dev, "driveB", blk_by_legacy_dinfo(fd[1]),
&error_abort);
}
qdev_prop_set_uint32(dev, "dma", -1);
qdev_init_nofail(dev);
/* Map NVRAM into I/O (ebus) space */
nvram = m48t59_init(NULL, 0, 0, NVRAM_SIZE, 1968, 59);

42
include/hw/isa/i8257.h Normal file
View File

@ -0,0 +1,42 @@
#ifndef HW_I8257_H
#define HW_I8257_H
#define TYPE_I8257 "i8257"
typedef struct I8257Regs {
int now[2];
uint16_t base[2];
uint8_t mode;
uint8_t page;
uint8_t pageh;
uint8_t dack;
uint8_t eop;
DMA_transfer_handler transfer_handler;
void *opaque;
} I8257Regs;
typedef struct I8257State {
/* <private> */
ISADevice parent_obj;
/* <public> */
int32_t base;
int32_t page_base;
int32_t pageh_base;
int32_t dshift;
uint8_t status;
uint8_t command;
uint8_t mask;
uint8_t flip_flop;
I8257Regs regs[4];
MemoryRegion channel_io;
MemoryRegion cont_io;
QEMUBH *dma_bh;
bool dma_bh_scheduled;
int running;
} I8257State;
#endif

View File

@ -34,6 +34,41 @@ static inline uint16_t applesmc_port(void)
return 0;
}
#define TYPE_ISADMA "isa-dma"
#define ISADMA_CLASS(klass) \
OBJECT_CLASS_CHECK(IsaDmaClass, (klass), TYPE_ISADMA)
#define ISADMA_GET_CLASS(obj) \
OBJECT_GET_CLASS(IsaDmaClass, (obj), TYPE_ISADMA)
#define ISADMA(obj) \
INTERFACE_CHECK(IsaDma, (obj), TYPE_ISADMA)
struct IsaDma {
Object parent;
};
typedef enum {
ISADMA_TRANSFER_VERIFY,
ISADMA_TRANSFER_READ,
ISADMA_TRANSFER_WRITE,
ISADMA_TRANSFER_ILLEGAL,
} IsaDmaTransferMode;
typedef struct IsaDmaClass {
InterfaceClass parent;
IsaDmaTransferMode (*get_transfer_mode)(IsaDma *obj, int nchan);
bool (*has_autoinitialization)(IsaDma *obj, int nchan);
int (*read_memory)(IsaDma *obj, int nchan, void *buf, int pos, int len);
int (*write_memory)(IsaDma *obj, int nchan, void *buf, int pos, int len);
void (*hold_DREQ)(IsaDma *obj, int nchan);
void (*release_DREQ)(IsaDma *obj, int nchan);
void (*schedule)(IsaDma *obj);
void (*register_channel)(IsaDma *obj, int nchan,
DMA_transfer_handler transfer_handler,
void *opaque);
} IsaDmaClass;
typedef struct ISADeviceClass {
DeviceClass parent_class;
} ISADeviceClass;
@ -46,6 +81,7 @@ struct ISABus {
MemoryRegion *address_space;
MemoryRegion *address_space_io;
qemu_irq *irqs;
IsaDma *dma[2];
};
struct ISADevice {
@ -63,6 +99,8 @@ ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space,
void isa_bus_irqs(ISABus *bus, qemu_irq *irqs);
qemu_irq isa_get_irq(ISADevice *dev, int isairq);
void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq);
void isa_bus_dma(ISABus *bus, IsaDma *dma8, IsaDma *dma16);
IsaDma *isa_get_dma(ISABus *bus, int nchan);
MemoryRegion *isa_address_space(ISADevice *dev);
MemoryRegion *isa_address_space_io(ISADevice *dev);
ISADevice *isa_create(ISABus *bus, const char *name);
@ -106,15 +144,6 @@ static inline ISABus *isa_bus_from_device(ISADevice *d)
return ISA_BUS(qdev_get_parent_bus(DEVICE(d)));
}
/* dma.c */
int DMA_get_channel_mode (int nchan);
int DMA_read_memory (int nchan, void *buf, int pos, int size);
int DMA_write_memory (int nchan, void *buf, int pos, int size);
void DMA_hold_DREQ (int nchan);
void DMA_release_DREQ (int nchan);
void DMA_schedule(void);
void DMA_init(int high_page_enable);
void DMA_register_channel (int nchan,
DMA_transfer_handler transfer_handler,
void *opaque);
/* i8257.c */
void DMA_init(ISABus *bus, int high_page_enable);
#endif

View File

@ -33,6 +33,7 @@ typedef struct I2CBus I2CBus;
typedef struct I2SCodec I2SCodec;
typedef struct ISABus ISABus;
typedef struct ISADevice ISADevice;
typedef struct IsaDma IsaDma;
typedef struct LoadStateEntry LoadStateEntry;
typedef struct MACAddr MACAddr;
typedef struct MachineClass MachineClass;