ide: Enable byte&word access to DMA address register
PATCH 1/1 ide: Enable byte&word access to DMA address register
According to the specs, also byte- and word-wise access to the busmaster DMA address register is allowed. Patch below fixes the IDE emulation in this regard (avoiding to touch the existing common case of 32-bit access) and makes our guest happy.
--- hw/ide.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
hw/ide.c +25 -0
@@ -2838,6 +2838,29 @@ static void bmdma_writeb(void *opaque, u } } +static uint32_t bmdma_addr_readb (void *opaque,uint32_t addr) +{ +BMDMAState *bm = opaque; +uint32_t val; + val = (bm->addr >> ((addr &3 ) *8 )) &0xff ; +#ifdef DEBUG_IDE +printf ("%s: 0x%08x\n" , __func__, val); +#endif +return val; +} + +static void bmdma_addr_writeb (void *opaque,uint32_t addr,uint32_t val) +{ +BMDMAState *bm = opaque; +int shift = (addr &3 ) *8 ; +#ifdef DEBUG_IDE +printf ("%s: 0x%08x\n" , __func__, val); +#endif + bm->addr &= ~(0xFF << shift); + bm->addr |= (val &0xfc ) << shift; + bm->cur_addr = bm->addr; +} +static uint32_t bmdma_addr_readl (void *opaque,uint32_t addr) {BMDMAState *bm = opaque;
@@ -2876,6 +2899,8 @@ static void bmdma_map(PCIDevice *pci_devregister_ioport_write (addr +1 ,3 ,1 , bmdma_writeb, bm);register_ioport_read (addr,4 ,1 , bmdma_readb, bm); +register_ioport_write (addr +4 ,4 ,1 , bmdma_addr_writeb, bm); +register_ioport_read (addr +4 ,4 ,1 , bmdma_addr_readb, bm);register_ioport_write (addr +4 ,4 ,4 , bmdma_addr_writel, bm);register_ioport_read (addr +4 ,4 ,4 , bmdma_addr_readl, bm); addr +=8 ;
Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2 Corporate Competence Center Embedded Linux
Quoted 28 lines · Jan Kiszka
According to the specs, also byte- and word-wise access to the busmaster DMA address register is allowed. Patch below fixes the IDE emulation in this regard (avoiding to touch the existing common case of 32-bit access) and makes our guest happy.
Signed-off-by Jan Kiszka <[email protected]>--- hw/ide.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)Index:
b/hw/ide.c
===================================================================hw/ide.c +10
-0@@ -2838,6 +2838,29 @@ static void bmdma_writeb(void *opaque, u } } +static uint32_t bmdma_addr_readb (void *opaque,uint32_t addr) +{ +BMDMAState *bm = opaque; +uint32_t val; + val = (bm->addr >> ((addr &3 ) *8 )) &0xff ; +#ifdef DEBUG_IDE +printf ("%s: 0x%08x\n" , __func__, val); +#endif +return val; +}
hw/ide.c static void bmdma_writeb(void *opaque, u · line 2860
Quoted 10 lines
hw/ide.c +10
-0+ +static void bmdma_addr_writeb (void *opaque,uint32_t addr,uint32_t val) +{ +BMDMAState *bm = opaque; +int shift = (addr &3 ) *8 ; +#ifdef DEBUG_IDE +printf ("%s: 0x%08x\n" , __func__, val); +#endif + bm->addr &= ~(0xFF << shift); + bm->addr |= (val &0xfc ) << shift;
Are you sure it is correct? If you want to make sure the 2 lowest bits are 0, it should be instead:
bm->addr |= ((val & 0xFF) << shift) & ~3;
Quoted 8 lines
hw/ide.c +3
-0+ bm->cur_addr = bm->addr; +} +static uint32_t bmdma_addr_readl (void *opaque,uint32_t addr) {BMDMAState *bm = opaque;
hw/ide.c static void bmdma_map(PCIDevice *pci_dev · line 2906
Quoted 8 lines
hw/ide.c +2
-0@@ -2876,6 +2899,8 @@ static void bmdma_map(PCIDevice *pci_devregister_ioport_write (addr +1 ,3 ,1 , bmdma_writeb, bm);register_ioport_read (addr,4 ,1 , bmdma_readb, bm); +register_ioport_write (addr +4 ,4 ,1 , bmdma_addr_writeb, bm); +register_ioport_read (addr +4 ,4 ,1 , bmdma_addr_readb, bm);register_ioport_write (addr +4 ,4 ,4 , bmdma_addr_writel, bm);register_ioport_read (addr +4 ,4 ,4 , bmdma_addr_readl, bm); addr +=8 ;
Otherwise, looks ok. Are word accesses supported? If yes it may be nice to implement bmdma_addr_writew and bmdma_addr_readw at the same time.
Signature · 4 lines
.''`. Aurelien Jarno | GPG: 1024D/F1BCDB73 : :' : Debian developer | Electrical Engineer `. `' [email protected] | [email protected] `- people.debian.org/~aurel32 | www.aurel32.net
Quoted 43 lines · Aurelien Jarno
Quoted 28 lines · Jan Kiszka
According to the specs, also byte- and word-wise access to the busmaster DMA address register is allowed. Patch below fixes the IDE emulation in this regard (avoiding to touch the existing common case of 32-bit access) and makes our guest happy.
Signed-off-by Jan Kiszka <[email protected]>--- hw/ide.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)Index:
b/hw/ide.c
===================================================================hw/ide.c +10
-0@@ -2838,6 +2838,29 @@ static void bmdma_writeb(void *opaque, u } } +static uint32_t bmdma_addr_readb (void *opaque,uint32_t addr) +{ +BMDMAState *bm = opaque; +uint32_t val; + val = (bm->addr >> ((addr &3 ) *8 )) &0xff ; +#ifdef DEBUG_IDE +printf ("%s: 0x%08x\n" , __func__, val); +#endif +return val; +}hw/ide.c static void bmdma_writeb(void *opaque, u · line 2860
Quoted 10 lines
hw/ide.c +10
-0+ +static void bmdma_addr_writeb (void *opaque,uint32_t addr,uint32_t val) +{ +BMDMAState *bm = opaque; +int shift = (addr &3 ) *8 ; +#ifdef DEBUG_IDE +printf ("%s: 0x%08x\n" , __func__, val); +#endif + bm->addr &= ~(0xFF << shift); + bm->addr |= (val &0xfc ) << shift;Are you sure it is correct? If you want to make sure the 2 lowest bits are 0, it should be instead:
Quoted 1 line
bm->addr |= ((val & 0xFF) << shift) & ~3;
Oh, oh, oh. Of course. I just wonder why my colleague was able to work with it despite of this bug. Looks like we have been lucky. Find corrected patch below.
Quoted 11 lines
Quoted 11 lines
hw/ide.c +3
-0+ bm->cur_addr = bm->addr; +} +static uint32_t bmdma_addr_readl (void *opaque,uint32_t addr) {BMDMAState *bm = opaque;@@ -2876,6 +2899,8 @@ static void bmdma_map(PCIDevice *pci_devregister_ioport_write (addr +1 ,3 ,1 , bmdma_writeb, bm);register_ioport_read (addr,4 ,1 , bmdma_readb, bm);
Quoted 9 lines
hw/ide.c static void bmdma_map(PCIDevice *pci_dev · line 2906
Quoted 6 lines
hw/ide.c +2
-0+register_ioport_write (addr +4 ,4 ,1 , bmdma_addr_writeb, bm); +register_ioport_read (addr +4 ,4 ,1 , bmdma_addr_readb, bm);register_ioport_write (addr +4 ,4 ,4 , bmdma_addr_writel, bm);register_ioport_read (addr +4 ,4 ,4 , bmdma_addr_readl, bm); addr +=8 ;Otherwise, looks ok. Are word accesses supported? If yes it may be nice to implement
bmdma_addr_writewandbmdma_addr_readwat the same time.
Yes, word access is supported, the default handler will simply call twice into our byte handler.
Thanks!
Jan
--- hw/ide.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
hw/ide.c +25 -0
@@ -2838,6 +2838,29 @@ static void bmdma_writeb(void *opaque, u } } +static uint32_t bmdma_addr_readb (void *opaque,uint32_t addr) +{ +BMDMAState *bm = opaque; +uint32_t val; + val = (bm->addr >> ((addr &3 ) *8 )) &0xff ; +#ifdef DEBUG_IDE +printf ("%s: 0x%08x\n" , __func__, val); +#endif +return val; +} + +static void bmdma_addr_writeb (void *opaque,uint32_t addr,uint32_t val) +{ +BMDMAState *bm = opaque; +int shift = (addr &3 ) *8 ; +#ifdef DEBUG_IDE +printf ("%s: 0x%08x\n" , __func__, val); +#endif + bm->addr &= ~(0xFF << shift); + bm->addr |= ((val &0xFF ) << shift) & ~3 ; + bm->cur_addr = bm->addr; +} +static uint32_t bmdma_addr_readl (void *opaque,uint32_t addr) {BMDMAState *bm = opaque;
@@ -2876,6 +2899,8 @@ static void bmdma_map(PCIDevice *pci_devregister_ioport_write (addr +1 ,3 ,1 , bmdma_writeb, bm);register_ioport_read (addr,4 ,1 , bmdma_readb, bm); +register_ioport_write (addr +4 ,4 ,1 , bmdma_addr_writeb, bm); +register_ioport_read (addr +4 ,4 ,1 , bmdma_addr_readb, bm);register_ioport_write (addr +4 ,4 ,4 , bmdma_addr_writel, bm);register_ioport_read (addr +4 ,4 ,4 , bmdma_addr_readl, bm); addr +=8 ;