26 |
26 |
#include <string.h>
|
27 |
27 |
#include <inttypes.h>
|
28 |
28 |
|
29 |
|
#include "cpu.h"
|
30 |
29 |
#include "vl.h"
|
31 |
30 |
|
32 |
31 |
/********************************************************/
|
... | ... | |
218 |
217 |
|
219 |
218 |
static void fdctrl_reset (int do_irq);
|
220 |
219 |
static void fdctrl_reset_fifo (void);
|
221 |
|
static int fdctrl_transfer_handler (uint32_t addr, int size, int *irq);
|
222 |
|
static int fdctrl_misc_handler (int duknwo);
|
|
220 |
static int fdctrl_transfer_handler (void *opaque, target_ulong addr, int size);
|
223 |
221 |
static void fdctrl_raise_irq (uint8_t status);
|
224 |
222 |
|
225 |
223 |
static uint32_t fdctrl_read_statusB (CPUState *env, uint32_t reg);
|
... | ... | |
310 |
308 |
fdctrl.config = 0x40; /* Implicit seek, polling & FIFO enabled */
|
311 |
309 |
if (fdctrl.dma_chann != -1) {
|
312 |
310 |
fdctrl.dma_en = 1;
|
313 |
|
DMA_register_channel(dma_chann, &fdctrl_transfer_handler,
|
314 |
|
&fdctrl_misc_handler);
|
|
311 |
DMA_register_channel(dma_chann, fdctrl_transfer_handler, &fdctrl);
|
315 |
312 |
} else {
|
316 |
313 |
fdctrl.dma_en = 0;
|
317 |
314 |
}
|
... | ... | |
721 |
718 |
* recall us...
|
722 |
719 |
*/
|
723 |
720 |
DMA_hold_DREQ(fdctrl.dma_chann);
|
|
721 |
DMA_schedule(fdctrl.dma_chann);
|
724 |
722 |
return;
|
725 |
723 |
}
|
726 |
724 |
}
|
... | ... | |
749 |
747 |
}
|
750 |
748 |
|
751 |
749 |
/* handlers for DMA transfers */
|
752 |
|
static int fdctrl_transfer_handler (uint32_t addr, int size, int *irq)
|
|
750 |
/* XXX: the partial transfer logic seems to be broken */
|
|
751 |
static int fdctrl_transfer_handler (void *opaque, target_ulong addr, int size)
|
753 |
752 |
{
|
754 |
753 |
fdrive_t *cur_drv, *drv0, *drv1;
|
755 |
|
void *orig;
|
756 |
754 |
int len;
|
757 |
755 |
uint8_t status0 = 0x00, status1 = 0x00, status2 = 0x00;
|
|
756 |
uint8_t tmpbuf[FD_SECTOR_LEN];
|
758 |
757 |
|
759 |
758 |
fdctrl_reset_irq();
|
760 |
759 |
if (!(fdctrl.state & FD_CTRL_BUSY)) {
|
... | ... | |
764 |
763 |
drv0 = &fdctrl.drives[fdctrl.bootsel];
|
765 |
764 |
drv1 = &fdctrl.drives[1 - fdctrl.bootsel];
|
766 |
765 |
cur_drv = fdctrl.cur_drv == 0 ? drv0 : drv1;
|
767 |
|
// *irq = fdctrl.irq_lvl;
|
768 |
|
*irq = -1;
|
769 |
766 |
if (fdctrl.data_dir == FD_DIR_SCANE || fdctrl.data_dir == FD_DIR_SCANL ||
|
770 |
767 |
fdctrl.data_dir == FD_DIR_SCANH)
|
771 |
768 |
status2 = 0x04;
|
... | ... | |
779 |
776 |
fdctrl.data_len, fdctrl.cur_drv, cur_drv->head,
|
780 |
777 |
cur_drv->track, cur_drv->sect, fd_sector(cur_drv),
|
781 |
778 |
fd_sector(cur_drv) * 512);
|
782 |
|
if (len < FD_SECTOR_LEN) {
|
783 |
|
memset(&fdctrl.fifo[FD_SECTOR_LEN - len], 0,
|
784 |
|
FD_SECTOR_LEN - len - 1);
|
785 |
|
orig = fdctrl.fifo;
|
786 |
|
} else {
|
787 |
|
orig = (void *)(addr + fdctrl.data_pos);
|
788 |
|
}
|
789 |
779 |
if (fdctrl.data_dir != FD_DIR_WRITE) {
|
790 |
780 |
/* READ & SCAN commands */
|
791 |
781 |
if (cur_drv->bs == NULL) {
|
792 |
782 |
fdctrl_stop_transfer(0x40, 0x00, 0x00);
|
793 |
783 |
goto transfer_error;
|
794 |
784 |
}
|
795 |
|
|
796 |
|
if (bdrv_read(cur_drv->bs, fd_sector(cur_drv), orig, 1) < 0) {
|
|
785 |
if (bdrv_read(cur_drv->bs, fd_sector(cur_drv), tmpbuf, 1) < 0) {
|
797 |
786 |
FLOPPY_DPRINTF("Floppy: error getting sector %d\n",
|
798 |
787 |
fd_sector(cur_drv));
|
799 |
788 |
/* Sure, image size is too small... */
|
800 |
|
memset((void *)(addr + fdctrl.data_pos), 0, FD_SECTOR_LEN);
|
|
789 |
memset(tmpbuf, 0, FD_SECTOR_LEN);
|
801 |
790 |
}
|
802 |
791 |
if (fdctrl.data_dir == FD_DIR_READ) {
|
|
792 |
cpu_physical_memory_write(addr + fdctrl.data_pos,
|
|
793 |
tmpbuf, len);
|
803 |
794 |
if (len < FD_SECTOR_LEN) {
|
804 |
|
memcpy((void *)(addr + fdctrl.data_pos),
|
805 |
|
fdctrl.fifo, FD_SECTOR_LEN);
|
|
795 |
memcpy(&fdctrl.fifo[0], tmpbuf + len, FD_SECTOR_LEN - len);
|
|
796 |
memset(&fdctrl.fifo[FD_SECTOR_LEN - len], 0, len);
|
806 |
797 |
}
|
807 |
798 |
} else {
|
808 |
799 |
int ret;
|
809 |
|
ret = memcmp((void *)(addr + fdctrl.data_pos),
|
810 |
|
fdctrl.fifo, FD_SECTOR_LEN);
|
|
800 |
/* XXX: what to do if not enough data ? */
|
|
801 |
cpu_physical_memory_read(addr + fdctrl.data_pos,
|
|
802 |
fdctrl.fifo, len);
|
|
803 |
if (len < FD_SECTOR_LEN) {
|
|
804 |
memset(&fdctrl.fifo[len], 0, FD_SECTOR_LEN - len);
|
|
805 |
}
|
|
806 |
ret = memcmp(tmpbuf, fdctrl.fifo, FD_SECTOR_LEN);
|
811 |
807 |
if (ret == 0) {
|
812 |
808 |
status2 = 0x08;
|
813 |
809 |
goto end_transfer;
|
... | ... | |
820 |
816 |
}
|
821 |
817 |
} else {
|
822 |
818 |
/* WRITE commands */
|
|
819 |
cpu_physical_memory_read(addr + fdctrl.data_pos, tmpbuf, len);
|
|
820 |
if (len < FD_SECTOR_LEN) {
|
|
821 |
memset(tmpbuf + len, 0, FD_SECTOR_LEN - len);
|
|
822 |
}
|
823 |
823 |
if (cur_drv->bs == NULL ||
|
824 |
|
bdrv_write(cur_drv->bs, fd_sector(cur_drv), orig, 1) < 0) {
|
|
824 |
bdrv_write(cur_drv->bs, fd_sector(cur_drv), tmpbuf, 1) < 0) {
|
825 |
825 |
FLOPPY_ERROR("writting sector %d\n", fd_sector(cur_drv));
|
826 |
826 |
fdctrl_stop_transfer(0x60, 0x00, 0x00);
|
827 |
827 |
goto transfer_error;
|
... | ... | |
871 |
871 |
return fdctrl.data_pos;
|
872 |
872 |
}
|
873 |
873 |
|
874 |
|
/* Unused... */
|
875 |
|
static int fdctrl_misc_handler (int duknwo)
|
876 |
|
{
|
877 |
|
return -1;
|
878 |
|
}
|
879 |
|
|
880 |
874 |
/* Data register : 0x05 */
|
881 |
875 |
static uint32_t fdctrl_read_data (CPUState *env, uint32_t reg)
|
882 |
876 |
{
|