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