trunk/src/emu/machine/upd765.c
| r19281 | r19282 | |
| 150 | 150 | flopi[i].sub_state = IDLE; |
| 151 | 151 | flopi[i].live = false; |
| 152 | 152 | flopi[i].ready = !ready_polled; |
| 153 | | flopi[i].irq = floppy_info::IRQ_NONE; |
| 153 | flopi[i].st0 = i; |
| 154 | flopi[i].st0_filled = false; |
| 154 | 155 | } |
| 155 | 156 | data_irq = false; |
| 156 | | polled_irq = false; |
| 157 | other_irq = false; |
| 157 | 158 | internal_drq = false; |
| 158 | 159 | fifo_pos = 0; |
| 159 | 160 | command_pos = 0; |
| r19281 | r19282 | |
| 167 | 168 | cur_live.next_state = -1; |
| 168 | 169 | cur_live.fi = NULL; |
| 169 | 170 | tc_done = false; |
| 170 | | st0 = st1 = st2 = st3 = 0x00; |
| 171 | st1 = st2 = st3 = 0x00; |
| 171 | 172 | |
| 172 | 173 | check_irq(); |
| 173 | 174 | if(ready_polled) |
| r19281 | r19282 | |
| 1196 | 1197 | } |
| 1197 | 1198 | |
| 1198 | 1199 | case C_SENSE_INTERRUPT_STATUS: { |
| 1200 | // Documentation is somewhat contradictory w.r.t polling |
| 1201 | // and irq. PC bios, especially 5150, requires that only |
| 1202 | // one irq happens. That's also wait the ns82077a doc |
| 1203 | // says it does. OTOH, a number of docs says you need to |
| 1204 | // call SIS 4 times, once per drive... |
| 1205 | // |
| 1206 | // There's also the interaction with the seek irq. The |
| 1207 | // somewhat borderline tf20 code seems to think that |
| 1208 | // essentially ignoring the polling irq should work. |
| 1209 | // |
| 1210 | // And the pc98 expects to be able to accumulate irq reasons |
| 1211 | // for different drives and things to work. |
| 1212 | // |
| 1213 | // Current hypothesis: |
| 1214 | // - each drive has its own st0 and irq trigger |
| 1215 | // - SIS drops the irq always, but also returns the first full st0 it finds |
| 1216 | |
| 1199 | 1217 | main_phase = PHASE_RESULT; |
| 1200 | 1218 | |
| 1201 | 1219 | int fid; |
| 1202 | | for(fid=0; fid<4 && flopi[fid].irq == floppy_info::IRQ_NONE; fid++); |
| 1220 | for(fid=0; fid<4 && !flopi[fid].st0_filled; fid++); |
| 1203 | 1221 | if(fid == 4) { |
| 1204 | | st0 = ST0_UNK; |
| 1205 | | result[0] = st0; |
| 1222 | result[0] = ST0_UNK; |
| 1206 | 1223 | result_pos = 1; |
| 1207 | 1224 | logerror("%s: command sense interrupt status (%02x)\n", tag(), result[0]); |
| 1208 | 1225 | break; |
| 1209 | 1226 | } |
| 1227 | |
| 1210 | 1228 | floppy_info &fi = flopi[fid]; |
| 1211 | | if(fi.irq == floppy_info::IRQ_POLLED) { |
| 1212 | | // Documentation is somewhat contradictory w.r.t polling |
| 1213 | | // and irq. PC bios, especially 5150, requires that only |
| 1214 | | // one irq happens. That's also wait the ns82077a doc |
| 1215 | | // says it does. OTOH, a number of docs says you need to |
| 1216 | | // call SIS 4 times, once per drive... |
| 1217 | | // |
| 1218 | | // There's also the interaction with the seek irq. The |
| 1219 | | // somewhat borderline tf20 code seems to think that |
| 1220 | | // essentially ignoring the polling irq should work. |
| 1221 | | // |
| 1222 | | // So at that point the best bet seems to drop the |
| 1223 | | // "polled" irq as soon as a SIS happens, and override any |
| 1224 | | // polled-in-waiting information when a seek irq happens |
| 1225 | | // for a given floppy. |
| 1229 | fi.st0_filled = false; |
| 1226 | 1230 | |
| 1227 | | st0 = ST0_ABRT | fid; |
| 1228 | | } |
| 1229 | | fi.irq = floppy_info::IRQ_NONE; |
| 1231 | result[0] = fi.st0; |
| 1232 | result[1] = fi.pcn; |
| 1230 | 1233 | |
| 1231 | | polled_irq = false; |
| 1232 | | |
| 1233 | | result[0] = st0; |
| 1234 | | result[1] = fi.pcn; |
| 1235 | 1234 | logerror("%s: command sense interrupt status (fid=%d %02x %02x)\n", tag(), fid, result[0], result[1]); |
| 1236 | 1235 | result_pos = 2; |
| 1237 | 1236 | |
| 1237 | other_irq = false; |
| 1238 | 1238 | check_irq(); |
| 1239 | 1239 | break; |
| 1240 | 1240 | } |
| r19281 | r19282 | |
| 1267 | 1267 | if(data_completion) |
| 1268 | 1268 | data_irq = true; |
| 1269 | 1269 | else |
| 1270 | | fi.irq = floppy_info::IRQ_SEEK; |
| 1270 | other_irq = true; |
| 1271 | fi.st0_filled = true; |
| 1271 | 1272 | check_irq(); |
| 1272 | 1273 | } |
| 1273 | 1274 | |
| r19281 | r19282 | |
| 1337 | 1338 | if(done) |
| 1338 | 1339 | fi.pcn = 0; |
| 1339 | 1340 | else if(!fi.counter) { |
| 1340 | | st0 = ST0_FAIL|ST0_SE|ST0_EC; |
| 1341 | fi.st0 = ST0_FAIL|ST0_SE|ST0_EC | fi.id; |
| 1341 | 1342 | command_end(fi, false); |
| 1342 | 1343 | return; |
| 1343 | 1344 | } |
| r19281 | r19282 | |
| 1347 | 1348 | break; |
| 1348 | 1349 | } |
| 1349 | 1350 | if(done) { |
| 1350 | | st0 = ST0_SE; |
| 1351 | fi.st0 = ST0_SE | fi.id; |
| 1351 | 1352 | command_end(fi, false); |
| 1352 | 1353 | return; |
| 1353 | 1354 | } |
| r19281 | r19282 | |
| 1382 | 1383 | command[8], |
| 1383 | 1384 | cur_rate); |
| 1384 | 1385 | |
| 1385 | | st0 = command[1] & 7; |
| 1386 | fi.st0 = command[1] & 7; |
| 1386 | 1387 | st1 = ST1_MA; |
| 1387 | 1388 | st2 = 0x00; |
| 1388 | 1389 | |
| r19281 | r19282 | |
| 1400 | 1401 | fi.sub_state = SEEK_DONE; |
| 1401 | 1402 | break; |
| 1402 | 1403 | } |
| 1403 | | st0 |= ST0_SE; |
| 1404 | fi.st0 |= ST0_SE; |
| 1404 | 1405 | if(fi.dev) { |
| 1405 | 1406 | fi.dev->dir_w(fi.pcn > command[2] ? 1 : 0); |
| 1406 | 1407 | fi.dev->stp_w(0); |
| r19281 | r19282 | |
| 1439 | 1440 | |
| 1440 | 1441 | case SCAN_ID: |
| 1441 | 1442 | if(cur_live.crc) { |
| 1442 | | st0 |= ST0_FAIL; |
| 1443 | fi.st0 |= ST0_FAIL; |
| 1443 | 1444 | st1 |= ST1_DE|ST1_ND; |
| 1444 | 1445 | fi.sub_state = COMMAND_DONE; |
| 1445 | 1446 | break; |
| r19281 | r19282 | |
| 1451 | 1452 | st2 |= ST2_WC|ST2_BC; |
| 1452 | 1453 | else |
| 1453 | 1454 | st2 |= ST2_WC; |
| 1454 | | st0 |= ST0_FAIL; |
| 1455 | fi.st0 |= ST0_FAIL; |
| 1455 | 1456 | fi.sub_state = COMMAND_DONE; |
| 1456 | 1457 | break; |
| 1457 | 1458 | } |
| r19281 | r19282 | |
| 1471 | 1472 | return; |
| 1472 | 1473 | |
| 1473 | 1474 | case SCAN_ID_FAILED: |
| 1474 | | st0 |= ST0_FAIL; |
| 1475 | fi.st0 |= ST0_FAIL; |
| 1475 | 1476 | st1 |= ST1_ND; |
| 1476 | 1477 | fi.sub_state = COMMAND_DONE; |
| 1477 | 1478 | break; |
| 1478 | 1479 | |
| 1479 | 1480 | case SECTOR_READ: { |
| 1480 | 1481 | if(st2 & ST2_MD) { |
| 1481 | | st0 |= ST0_FAIL; |
| 1482 | fi.st0 |= ST0_FAIL; |
| 1482 | 1483 | fi.sub_state = COMMAND_DONE; |
| 1483 | 1484 | break; |
| 1484 | 1485 | } |
| 1485 | 1486 | if(cur_live.crc) { |
| 1486 | | st0 |= ST0_FAIL; |
| 1487 | fi.st0 |= ST0_FAIL; |
| 1487 | 1488 | st1 |= ST1_DE; |
| 1488 | 1489 | st2 |= ST2_CM; |
| 1489 | 1490 | fi.sub_state = COMMAND_DONE; |
| r19281 | r19282 | |
| 1507 | 1508 | command[2]++; |
| 1508 | 1509 | } |
| 1509 | 1510 | if(!tc_done && done) { |
| 1510 | | st0 |= ST0_FAIL; |
| 1511 | fi.st0 |= ST0_FAIL; |
| 1511 | 1512 | st1 |= ST1_EN; |
| 1512 | 1513 | } |
| 1513 | 1514 | } |
| r19281 | r19282 | |
| 1521 | 1522 | |
| 1522 | 1523 | case COMMAND_DONE: |
| 1523 | 1524 | main_phase = PHASE_RESULT; |
| 1524 | | result[0] = st0; |
| 1525 | result[0] = fi.st0; |
| 1525 | 1526 | result[1] = st1; |
| 1526 | 1527 | result[2] = st2; |
| 1527 | 1528 | result[3] = command[2]; |
| r19281 | r19282 | |
| 1563 | 1564 | if(fi.dev) |
| 1564 | 1565 | fi.dev->ss_w(command[1] & 4 ? 1 : 0); |
| 1565 | 1566 | |
| 1566 | | st0 = command[1] & 7; |
| 1567 | fi.st0 = command[1] & 7; |
| 1567 | 1568 | st1 = ST1_MA; |
| 1568 | 1569 | st2 = 0x00; |
| 1569 | 1570 | |
| r19281 | r19282 | |
| 1586 | 1587 | return; |
| 1587 | 1588 | } |
| 1588 | 1589 | if(cur_live.crc) { |
| 1589 | | st0 |= ST0_FAIL; |
| 1590 | fi.st0 |= ST0_FAIL; |
| 1590 | 1591 | st1 |= ST1_DE|ST1_ND; |
| 1591 | 1592 | fi.sub_state = COMMAND_DONE; |
| 1592 | 1593 | break; |
| r19281 | r19282 | |
| 1599 | 1600 | return; |
| 1600 | 1601 | |
| 1601 | 1602 | case SCAN_ID_FAILED: |
| 1602 | | st0 |= ST0_FAIL; |
| 1603 | fi.st0 |= ST0_FAIL; |
| 1603 | 1604 | st1 |= ST1_ND; |
| 1604 | 1605 | fi.sub_state = COMMAND_DONE; |
| 1605 | 1606 | break; |
| r19281 | r19282 | |
| 1623 | 1624 | command[2]++; |
| 1624 | 1625 | } |
| 1625 | 1626 | if(!tc_done && done) { |
| 1626 | | st0 |= ST0_FAIL; |
| 1627 | fi.st0 |= ST0_FAIL; |
| 1627 | 1628 | st1 |= ST1_EN; |
| 1628 | 1629 | } |
| 1629 | 1630 | } |
| r19281 | r19282 | |
| 1637 | 1638 | |
| 1638 | 1639 | case COMMAND_DONE: |
| 1639 | 1640 | main_phase = PHASE_RESULT; |
| 1640 | | result[0] = st0; |
| 1641 | result[0] = fi.st0; |
| 1641 | 1642 | result[1] = st1; |
| 1642 | 1643 | result[2] = st2; |
| 1643 | 1644 | result[3] = command[2]; |
| r19281 | r19282 | |
| 1846 | 1847 | if(fi.dev) |
| 1847 | 1848 | fi.dev->ss_w(command[1] & 4 ? 1 : 0); |
| 1848 | 1849 | |
| 1849 | | st0 = command[1] & 7; |
| 1850 | fi.st0 = command[1] & 7; |
| 1850 | 1851 | st1 = 0x00; |
| 1851 | 1852 | st2 = 0x00; |
| 1852 | 1853 | |
| r19281 | r19282 | |
| 1868 | 1869 | |
| 1869 | 1870 | case SCAN_ID: |
| 1870 | 1871 | if(cur_live.crc) { |
| 1871 | | st0 |= ST0_FAIL; |
| 1872 | fi.st0 |= ST0_FAIL; |
| 1872 | 1873 | st1 |= ST1_MA|ST1_DE|ST1_ND; |
| 1873 | 1874 | } |
| 1874 | 1875 | fi.sub_state = COMMAND_DONE; |
| 1875 | 1876 | break; |
| 1876 | 1877 | |
| 1877 | 1878 | case SCAN_ID_FAILED: |
| 1878 | | st0 |= ST0_FAIL; |
| 1879 | fi.st0 |= ST0_FAIL; |
| 1879 | 1880 | st1 |= ST1_ND|ST1_MA; |
| 1880 | 1881 | fi.sub_state = COMMAND_DONE; |
| 1881 | 1882 | break; |
| 1882 | 1883 | |
| 1883 | 1884 | case COMMAND_DONE: |
| 1884 | 1885 | main_phase = PHASE_RESULT; |
| 1885 | | result[0] = st0; |
| 1886 | result[0] = fi.st0; |
| 1886 | 1887 | result[1] = st1; |
| 1887 | 1888 | result[2] = st2; |
| 1888 | 1889 | result[3] = cur_live.idbuf[0]; |
| r19281 | r19282 | |
| 1903 | 1904 | void upd765_family_device::check_irq() |
| 1904 | 1905 | { |
| 1905 | 1906 | bool old_irq = cur_irq; |
| 1906 | | cur_irq = data_irq || polled_irq || internal_drq; |
| 1907 | | for(int i=0; i<4; i++) |
| 1908 | | cur_irq = cur_irq || flopi[i].irq == floppy_info::IRQ_SEEK; |
| 1907 | cur_irq = data_irq || other_irq || internal_drq; |
| 1909 | 1908 | cur_irq = cur_irq && (dor & 4) && (dor & 8); |
| 1910 | 1909 | if(cur_irq != old_irq && !intrq_cb.isnull()) { |
| 1911 | 1910 | logerror("%s: irq = %d\n", tag(), cur_irq); |
| r19281 | r19282 | |
| 1969 | 1968 | if(ready != flopi[fid].ready) { |
| 1970 | 1969 | logerror("%s: polled %d : %d -> %d\n", tag(), fid, flopi[fid].ready, ready); |
| 1971 | 1970 | flopi[fid].ready = ready; |
| 1972 | | if(flopi[fid].irq == floppy_info::IRQ_NONE) { |
| 1973 | | flopi[fid].irq = floppy_info::IRQ_POLLED; |
| 1974 | | polled_irq = true; |
| 1971 | if(!flopi[fid].st0_filled) { |
| 1972 | flopi[fid].st0 = ST0_ABRT | fid; |
| 1973 | flopi[fid].st0_filled = true; |
| 1974 | other_irq = true; |
| 1975 | 1975 | changed = true; |
| 1976 | 1976 | } |
| 1977 | 1977 | } |
| 1978 | 1978 | } |
| 1979 | | if(changed) |
| 1980 | | check_irq(); |
| 1979 | |
| 1980 | check_irq(); |
| 1981 | 1981 | } |
| 1982 | 1982 | |
| 1983 | 1983 | void upd765_family_device::index_callback(floppy_image_device *floppy, int state) |
trunk/src/emu/machine/upd765.h
| r19281 | r19282 | |
| 250 | 250 | }; |
| 251 | 251 | |
| 252 | 252 | struct floppy_info { |
| 253 | | enum { IRQ_NONE, IRQ_SEEK, IRQ_POLLED }; |
| 253 | enum { IRQ_NONE, IRQ_POLLED, IRQ_SEEK, IRQ_DONE }; |
| 254 | 254 | emu_timer *tm; |
| 255 | 255 | floppy_image_device *dev; |
| 256 | 256 | int id; |
| 257 | 257 | int main_state, sub_state; |
| 258 | 258 | int dir, counter; |
| 259 | | UINT8 pcn; |
| 260 | | int irq; |
| 259 | UINT8 pcn, st0; |
| 260 | bool st0_filled; |
| 261 | 261 | bool live, index, ready; |
| 262 | 262 | }; |
| 263 | 263 | |
| r19281 | r19282 | |
| 287 | 287 | |
| 288 | 288 | live_info cur_live, checkpoint_live; |
| 289 | 289 | line_cb intrq_cb, drq_cb; |
| 290 | | bool cur_irq, polled_irq, data_irq, drq, internal_drq, tc, tc_done, locked, mfm; |
| 290 | bool cur_irq, other_irq, data_irq, drq, internal_drq, tc, tc_done, locked, mfm; |
| 291 | 291 | floppy_info flopi[4]; |
| 292 | 292 | |
| 293 | 293 | int fifo_pos, fifo_expected, command_pos, result_pos; |
| 294 | 294 | bool fifo_write; |
| 295 | 295 | UINT8 dor, dsr, msr, fifo[16], command[16], result[16]; |
| 296 | | UINT8 st0, st1, st2, st3; |
| 296 | UINT8 st1, st2, st3; |
| 297 | 297 | UINT8 fifocfg, dor_reset; |
| 298 | 298 | UINT8 precomp, perpmode; |
| 299 | 299 | UINT16 spec; |