mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-09-06 18:05:37 +00:00
-----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:
commit
ae533a46a1
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
397
hw/dma/i8257.c
397
hw/dma/i8257.c
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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
42
include/hw/isa/i8257.h
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue