Commit 746d6de7fef4c92f31c8e70c826ee63b2b6936b9
1 parent
678803ab
FDC fix 2/10 (Hervé Poussineau):
- Extract seeking to next sector handling in a function. Add a sector seek in PIO read and write modes git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4282 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
48 additions
and
33 deletions
hw/fdc.c
| ... | ... | @@ -974,6 +974,40 @@ static void fdctrl_unimplemented (fdctrl_t *fdctrl, int direction) |
| 974 | 974 | #endif |
| 975 | 975 | } |
| 976 | 976 | |
| 977 | +/* Seek to next sector */ | |
| 978 | +static int fdctrl_seek_to_next_sect (fdctrl_t *fdctrl, fdrive_t *cur_drv) | |
| 979 | +{ | |
| 980 | + FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d)\n", | |
| 981 | + cur_drv->head, cur_drv->track, cur_drv->sect, | |
| 982 | + fd_sector(cur_drv)); | |
| 983 | + /* XXX: cur_drv->sect >= cur_drv->last_sect should be an | |
| 984 | + error in fact */ | |
| 985 | + if (cur_drv->sect >= cur_drv->last_sect || | |
| 986 | + cur_drv->sect == fdctrl->eot) { | |
| 987 | + cur_drv->sect = 1; | |
| 988 | + if (FD_MULTI_TRACK(fdctrl->data_state)) { | |
| 989 | + if (cur_drv->head == 0 && | |
| 990 | + (cur_drv->flags & FDISK_DBL_SIDES) != 0) { | |
| 991 | + cur_drv->head = 1; | |
| 992 | + } else { | |
| 993 | + cur_drv->head = 0; | |
| 994 | + cur_drv->track++; | |
| 995 | + if ((cur_drv->flags & FDISK_DBL_SIDES) == 0) | |
| 996 | + return 0; | |
| 997 | + } | |
| 998 | + } else { | |
| 999 | + cur_drv->track++; | |
| 1000 | + return 0; | |
| 1001 | + } | |
| 1002 | + FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n", | |
| 1003 | + cur_drv->head, cur_drv->track, | |
| 1004 | + cur_drv->sect, fd_sector(cur_drv)); | |
| 1005 | + } else { | |
| 1006 | + cur_drv->sect++; | |
| 1007 | + } | |
| 1008 | + return 1; | |
| 1009 | +} | |
| 1010 | + | |
| 977 | 1011 | /* Callback for transfer end (stop or abort) */ |
| 978 | 1012 | static void fdctrl_stop_transfer (fdctrl_t *fdctrl, uint8_t status0, |
| 979 | 1013 | uint8_t status1, uint8_t status2) |
| ... | ... | @@ -1196,35 +1230,8 @@ static int fdctrl_transfer_handler (void *opaque, int nchan, |
| 1196 | 1230 | rel_pos = fdctrl->data_pos % FD_SECTOR_LEN; |
| 1197 | 1231 | if (rel_pos == 0) { |
| 1198 | 1232 | /* Seek to next sector */ |
| 1199 | - FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d) (%d)\n", | |
| 1200 | - cur_drv->head, cur_drv->track, cur_drv->sect, | |
| 1201 | - fd_sector(cur_drv), | |
| 1202 | - fdctrl->data_pos - len); | |
| 1203 | - /* XXX: cur_drv->sect >= cur_drv->last_sect should be an | |
| 1204 | - error in fact */ | |
| 1205 | - if (cur_drv->sect >= cur_drv->last_sect || | |
| 1206 | - cur_drv->sect == fdctrl->eot) { | |
| 1207 | - cur_drv->sect = 1; | |
| 1208 | - if (FD_MULTI_TRACK(fdctrl->data_state)) { | |
| 1209 | - if (cur_drv->head == 0 && | |
| 1210 | - (cur_drv->flags & FDISK_DBL_SIDES) != 0) { | |
| 1211 | - cur_drv->head = 1; | |
| 1212 | - } else { | |
| 1213 | - cur_drv->head = 0; | |
| 1214 | - cur_drv->track++; | |
| 1215 | - if ((cur_drv->flags & FDISK_DBL_SIDES) == 0) | |
| 1216 | - break; | |
| 1217 | - } | |
| 1218 | - } else { | |
| 1219 | - cur_drv->track++; | |
| 1220 | - break; | |
| 1221 | - } | |
| 1222 | - FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n", | |
| 1223 | - cur_drv->head, cur_drv->track, | |
| 1224 | - cur_drv->sect, fd_sector(cur_drv)); | |
| 1225 | - } else { | |
| 1226 | - cur_drv->sect++; | |
| 1227 | - } | |
| 1233 | + if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) | |
| 1234 | + break; | |
| 1228 | 1235 | } |
| 1229 | 1236 | } |
| 1230 | 1237 | end_transfer: |
| ... | ... | @@ -1250,7 +1257,7 @@ static uint32_t fdctrl_read_data (fdctrl_t *fdctrl) |
| 1250 | 1257 | { |
| 1251 | 1258 | fdrive_t *cur_drv; |
| 1252 | 1259 | uint32_t retval = 0; |
| 1253 | - int pos, len; | |
| 1260 | + int pos; | |
| 1254 | 1261 | |
| 1255 | 1262 | cur_drv = get_cur_drv(fdctrl); |
| 1256 | 1263 | fdctrl->state &= ~FD_CTRL_SLEEP; |
| ... | ... | @@ -1262,9 +1269,12 @@ static uint32_t fdctrl_read_data (fdctrl_t *fdctrl) |
| 1262 | 1269 | if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) { |
| 1263 | 1270 | pos %= FD_SECTOR_LEN; |
| 1264 | 1271 | if (pos == 0) { |
| 1265 | - len = fdctrl->data_len - fdctrl->data_pos; | |
| 1266 | - if (len > FD_SECTOR_LEN) | |
| 1267 | - len = FD_SECTOR_LEN; | |
| 1272 | + if (fdctrl->data_pos != 0) | |
| 1273 | + if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) { | |
| 1274 | + FLOPPY_DPRINTF("error seeking to next sector %d\n", | |
| 1275 | + fd_sector(cur_drv)); | |
| 1276 | + return 0; | |
| 1277 | + } | |
| 1268 | 1278 | bdrv_read(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1); |
| 1269 | 1279 | } |
| 1270 | 1280 | } |
| ... | ... | @@ -1707,6 +1717,11 @@ static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) |
| 1707 | 1717 | if (fdctrl->data_pos % FD_SECTOR_LEN == (FD_SECTOR_LEN - 1) || |
| 1708 | 1718 | fdctrl->data_pos == fdctrl->data_len) { |
| 1709 | 1719 | bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1); |
| 1720 | + if (!fdctrl_seek_to_next_sect(fdctrl, cur_drv)) { | |
| 1721 | + FLOPPY_DPRINTF("error seeking to next sector %d\n", | |
| 1722 | + fd_sector(cur_drv)); | |
| 1723 | + return; | |
| 1724 | + } | |
| 1710 | 1725 | } |
| 1711 | 1726 | /* Switch from transfer mode to status mode |
| 1712 | 1727 | * then from status mode to command mode | ... | ... |