Commit 890fa6bebbb540b9761aafc3fe37b87e26578346

Authored by bellard
1 parent a4c4785b

floppy fixes (initial patch by Mike Nordell)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1101 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 32 additions and 23 deletions
hw/fdc.c
1 1 /*
2   - * QEMU Floppy disk emulator
  2 + * QEMU Floppy disk emulator (Intel 82078)
3 3 *
4 4 * Copyright (c) 2003 Jocelyn Mayer
5 5 *
... ... @@ -382,6 +382,7 @@ struct fdctrl_t {
382 382 uint8_t data_state;
383 383 uint8_t data_dir;
384 384 uint8_t int_status;
  385 + uint8_t eot; /* last wanted sector */
385 386 /* States kept only to be returned back */
386 387 /* Timers state */
387 388 uint8_t timer0;
... ... @@ -762,7 +763,7 @@ static void fdctrl_unimplemented (fdctrl_t *fdctrl)
762 763 fdrive_t *cur_drv;
763 764  
764 765 cur_drv = get_cur_drv(fdctrl);
765   - fdctrl->fifo[0] = 0x60 | (cur_drv->head << 1) | fdctrl->cur_drv;
  766 + fdctrl->fifo[0] = 0x60 | (cur_drv->head << 2) | fdctrl->cur_drv;
766 767 fdctrl->fifo[1] = 0x00;
767 768 fdctrl->fifo[2] = 0x00;
768 769 fdctrl_set_fifo(fdctrl, 3, 1);
... ... @@ -782,8 +783,8 @@ static void fdctrl_stop_transfer (fdctrl_t *fdctrl, uint8_t status0,
782 783 cur_drv = get_cur_drv(fdctrl);
783 784 FLOPPY_DPRINTF("transfer status: %02x %02x %02x (%02x)\n",
784 785 status0, status1, status2,
785   - status0 | (cur_drv->head << 1) | fdctrl->cur_drv);
786   - fdctrl->fifo[0] = status0 | (cur_drv->head << 1) | fdctrl->cur_drv;
  786 + status0 | (cur_drv->head << 2) | fdctrl->cur_drv);
  787 + fdctrl->fifo[0] = status0 | (cur_drv->head << 2) | fdctrl->cur_drv;
787 788 fdctrl->fifo[1] = status1;
788 789 fdctrl->fifo[2] = status2;
789 790 fdctrl->fifo[3] = cur_drv->track;
... ... @@ -810,7 +811,7 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction)
810 811 kt = fdctrl->fifo[2];
811 812 kh = fdctrl->fifo[3];
812 813 ks = fdctrl->fifo[4];
813   - FLOPPY_DPRINTF("Start tranfert at %d %d %02x %02x (%d)\n",
  814 + FLOPPY_DPRINTF("Start tranfer at %d %d %02x %02x (%d)\n",
814 815 fdctrl->cur_drv, kh, kt, ks,
815 816 _fd_sector(kh, kt, ks, cur_drv->last_sect));
816 817 did_seek = 0;
... ... @@ -864,6 +865,7 @@ static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction)
864 865 tmp += cur_drv->last_sect;
865 866 fdctrl->data_len *= tmp;
866 867 }
  868 + fdctrl->eot = fdctrl->fifo[6];
867 869 if (fdctrl->dma_en) {
868 870 int dma_mode;
869 871 /* DMA transfer are enabled. Check if DMA channel is well programmed */
... ... @@ -924,14 +926,14 @@ static int fdctrl_transfer_handler (void *opaque, target_ulong addr, int size)
924 926 status2 = 0x04;
925 927 if (size > fdctrl->data_len)
926 928 size = fdctrl->data_len;
927   - if (cur_drv->bs == NULL) {
  929 + if (cur_drv->bs == NULL) {
928 930 if (fdctrl->data_dir == FD_DIR_WRITE)
929 931 fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
930 932 else
931 933 fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
932 934 len = 0;
933   - goto transfer_error;
934   - }
  935 + goto transfer_error;
  936 + }
935 937 rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
936 938 for (start_pos = fdctrl->data_pos; fdctrl->data_pos < size;) {
937 939 len = size - fdctrl->data_pos;
... ... @@ -952,7 +954,7 @@ static int fdctrl_transfer_handler (void *opaque, target_ulong addr, int size)
952 954 /* Sure, image size is too small... */
953 955 memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
954 956 }
955   - }
  957 + }
956 958 switch (fdctrl->data_dir) {
957 959 case FD_DIR_READ:
958 960 /* READ commands */
... ... @@ -968,7 +970,7 @@ static int fdctrl_transfer_handler (void *opaque, target_ulong addr, int size)
968 970 FLOPPY_ERROR("writting sector %d\n", fd_sector(cur_drv));
969 971 fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
970 972 goto transfer_error;
971   - }
  973 + }
972 974 break;
973 975 default:
974 976 /* SCAN commands */
... ... @@ -994,30 +996,34 @@ static int fdctrl_transfer_handler (void *opaque, target_ulong addr, int size)
994 996 rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
995 997 if (rel_pos == 0) {
996 998 /* Seek to next sector */
997   - cur_drv->sect++;
998 999 FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d) (%d)\n",
999 1000 cur_drv->head, cur_drv->track, cur_drv->sect,
1000 1001 fd_sector(cur_drv),
1001 1002 fdctrl->data_pos - size);
1002   - if (cur_drv->sect > cur_drv->last_sect) {
  1003 + /* XXX: cur_drv->sect >= cur_drv->last_sect should be an
  1004 + error in fact */
  1005 + if (cur_drv->sect >= cur_drv->last_sect ||
  1006 + cur_drv->sect == fdctrl->eot) {
1003 1007 cur_drv->sect = 1;
1004 1008 if (FD_MULTI_TRACK(fdctrl->data_state)) {
1005 1009 if (cur_drv->head == 0 &&
1006 1010 (cur_drv->flags & FDISK_DBL_SIDES) != 0) {
1007   - cur_drv->head = 1;
1008   - } else {
1009   - cur_drv->head = 0;
  1011 + cur_drv->head = 1;
  1012 + } else {
  1013 + cur_drv->head = 0;
1010 1014 cur_drv->track++;
1011 1015 if ((cur_drv->flags & FDISK_DBL_SIDES) == 0)
1012 1016 break;
  1017 + }
  1018 + } else {
  1019 + cur_drv->track++;
  1020 + break;
1013 1021 }
1014   - } else {
1015   - cur_drv->track++;
1016   - break;
1017   - }
1018 1022 FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n",
1019 1023 cur_drv->head, cur_drv->track,
1020 1024 cur_drv->sect, fd_sector(cur_drv));
  1025 + } else {
  1026 + cur_drv->sect++;
1021 1027 }
1022 1028 }
1023 1029 }
... ... @@ -1033,7 +1039,7 @@ end_transfer:
1033 1039 status0 |= 0x20;
1034 1040 fdctrl->data_len -= len;
1035 1041 // if (fdctrl->data_len == 0)
1036   - fdctrl_stop_transfer(fdctrl, status0, status1, status2);
  1042 + fdctrl_stop_transfer(fdctrl, status0, status1, status2);
1037 1043 transfer_error:
1038 1044  
1039 1045 return len;
... ... @@ -1066,7 +1072,7 @@ static uint32_t fdctrl_read_data (fdctrl_t *fdctrl)
1066 1072 retval = fdctrl->fifo[pos];
1067 1073 if (++fdctrl->data_pos == fdctrl->data_len) {
1068 1074 fdctrl->data_pos = 0;
1069   - /* Switch from transfert mode to status mode
  1075 + /* Switch from transfer mode to status mode
1070 1076 * then from status mode to command mode
1071 1077 */
1072 1078 if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) {
... ... @@ -1170,7 +1176,7 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value)
1170 1176 bdrv_write(cur_drv->bs, fd_sector(cur_drv),
1171 1177 fdctrl->fifo, FD_SECTOR_LEN);
1172 1178 }
1173   - /* Switch from transfert mode to status mode
  1179 + /* Switch from transfer mode to status mode
1174 1180 * then from status mode to command mode
1175 1181 */
1176 1182 if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA)
... ... @@ -1510,7 +1516,9 @@ enqueue:
1510 1516 /* 1 Byte status back */
1511 1517 fdctrl->fifo[0] = (cur_drv->ro << 6) |
1512 1518 (cur_drv->track == 0 ? 0x10 : 0x00) |
1513   - fdctrl->cur_drv;
  1519 + (cur_drv->head << 2) |
  1520 + fdctrl->cur_drv |
  1521 + 0x28;
1514 1522 fdctrl_set_fifo(fdctrl, 1, 0);
1515 1523 break;
1516 1524 case 0x07:
... ... @@ -1581,6 +1589,7 @@ enqueue:
1581 1589 /* READ_ID */
1582 1590 FLOPPY_DPRINTF("treat READ_ID command\n");
1583 1591 /* XXX: should set main status register to busy */
  1592 + cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
1584 1593 qemu_mod_timer(fdctrl->result_timer,
1585 1594 qemu_get_clock(vm_clock) + (ticks_per_sec / 50));
1586 1595 break;
... ...