void callback8271() { int diff=i8271.params[0]-i8271.curtrack[curdrive]; fdctime=0; // printf("Callback 8271 - command %02X\n",i8271.command); switch (i8271.command) { case 0x0B: /*Write*/ if (!i8271.phase) { i8271.curtrack[curdrive]=i8271.params[0]; disc_writesector(curdrive,i8271.cursector,i8271.params[0],(i8271.drvout&0x20)?1:0,0); i8271.phase=1; i8271.status=0x8C; i8271.result=0; NMI8271(); return; } i8271.sectorsleft--; if (!i8271.sectorsleft) { i8271.status=0x18; i8271.result=0; NMI8271(); setspindown8271(); verify8271=0; return; } i8271.cursector++; disc_writesector(curdrive,i8271.cursector,i8271.params[0],(i8271.drvout&0x20)?1:0,0); byte=0; i8271.status=0x8C; i8271.result=0; NMI8271(); break; case 0x13: /*Read*/ case 0x1F: /*Verify*/ if (!i8271.phase) { // printf("Seek to %i\n",i8271.params[0]); i8271.curtrack[curdrive]=i8271.params[0]; // i8271.realtrack+=diff; // disc_seek(0,i8271.realtrack); // printf("Re-seeking - track now %i %i\n",i8271.curtrack,i8271.realtrack); disc_readsector(curdrive,i8271.cursector,i8271.params[0],(i8271.drvout&0x20)?1:0,0); i8271.phase=1; return; } i8271.sectorsleft--; if (!i8271.sectorsleft) { i8271.status=0x18; i8271.result=0; NMI8271(); setspindown8271(); verify8271=0; return; } i8271.cursector++; disc_readsector(curdrive,i8271.cursector,i8271.params[0],(i8271.drvout&0x20)?1:0,0); byte=0; break; case 0x1B: /*Read ID*/ // printf("Read ID callback %i\n",i8271.phase); if (!i8271.phase) { i8271.curtrack[curdrive]=i8271.params[0]; // i8271.realtrack+=diff; // disc_seek(0,i8271.realtrack); disc_readaddress(curdrive,i8271.params[0],(i8271.drvout&0x20)?1:0,0); i8271.phase=1; return; } // printf("Read ID track %i %i\n",i8271.params[0],i8271.sectorsleft); i8271.sectorsleft--; if (!i8271.sectorsleft) { i8271.status=0x18; i8271.result=0; NMI8271(); // printf("8271 : ID read done!\n"); setspindown8271(); return; } i8271.cursector++; disc_readaddress(curdrive,i8271.params[0],(i8271.drvout&0x20)?1:0,0); byte=0; break; case 0x23: /*Format*/ if (!i8271.phase) { i8271.curtrack[curdrive]=i8271.params[0]; disc_writesector(curdrive,i8271.cursector,i8271.params[0],(i8271.drvout&0x20)?1:0,0); i8271.phase=1; i8271.status=0x8C; i8271.result=0; NMI8271(); return; } if (i8271.phase==2) { i8271.status=0x18; i8271.result=0; NMI8271(); setspindown8271(); verify8271=0; return; } disc_format(curdrive,i8271.params[0],(i8271.drvout&0x20)?1:0,0); i8271.phase=2; break; case 0x29: /*Seek*/ i8271.curtrack[curdrive]=i8271.params[0]; // i8271.realtrack+=diff; i8271.status=0x18; i8271.result=0; NMI8271(); // disc_seek(0,i8271.realtrack); // printf("Seek done!\n"); setspindown8271(); break; case 0xFF: break; default: break; printf("Unknown 8271 command %02X 3\n",i8271.command); dumpregs(); exit(-1); } }
void fdc_write(uint16_t addr, uint8_t val, void *priv) { // pclog("Write FDC %04X %02X %04X:%04X %i %02X %i rate=%i %i\n",addr,val,cs>>4,pc,ins,fdc.st0,ins,fdc.rate, fdc.data_ready); int drive; switch (addr&7) { case 1: return; case 2: /*DOR*/ // if (val == 0xD && (cs >> 4) == 0xFC81600 && ins > 769619936) output = 3; // printf("DOR was %02X\n",fdc.dor); if (fdc.pcjr) { if ((fdc.dor & 0x40) && !(val & 0x40)) { fdc.watchdog_timer = 1000 * TIMER_USEC; fdc.watchdog_count = 1000; picintc(1 << 6); // pclog("watchdog set %i %i\n", fdc.watchdog_timer, TIMER_USEC); } if ((val & 0x80) && !(fdc.dor & 0x80)) { timer_process(); disctime = 128 * (1 << TIMER_SHIFT); timer_update_outstanding(); discint=-1; fdc_reset(); } motoron = val & 0x01; fdc.drive = 0; /* if (motoron) output = 3; else output = 0;*/ } else { if (val&4) { fdc.stat=0x80; fdc.pnum=fdc.ptot=0; } if ((val&4) && !(fdc.dor&4)) { timer_process(); disctime = 128 * (1 << TIMER_SHIFT); timer_update_outstanding(); discint=-1; fdc_reset(); } timer_process(); motoron = (val & 0xf0) ? 1 : 0; timer_update_outstanding(); fdc.drive = val & 3; } fdc.dor=val; // printf("DOR now %02X\n",val); return; case 3: /* TDR */ if (fdc.enh_mode) { drive = (fdc.dor & 1) ^ fdd_swap; fdc.rwc[drive] = (val & 0x30) >> 4; } return; case 4: if (val & 0x80) { timer_process(); disctime = 128 * (1 << TIMER_SHIFT); timer_update_outstanding(); discint=-1; fdc_reset(); } return; case 5: /*Command register*/ if ((fdc.stat & 0xf0) == 0xb0) { if (fdc.pcjr || !fdc.fifo) { fdc.dat = val; fdc.stat &= ~0x80; } else { fdc_fifo_buf_write(val); if (fdc.fifobufpos == 0) fdc.stat &= ~0x80; } break; } // if (fdc.inread) // rpclog("c82c711_fdc_write : writing while inread! %02X\n", val); // rpclog("Write command reg %i %i\n",fdc.pnum, fdc.ptot); if (fdc.pnum==fdc.ptot) { fdc.tc = 0; fdc.data_ready = 0; fdc.command=val; // pclog("Starting FDC command %02X\n",fdc.command); switch (fdc.command&0x1F) { case 1: /*Mode*/ if (!fdc.is_nsc) goto bad_command; fdc.pnum=0; fdc.ptot=4; fdc.stat=0x90; fdc.pos=0; fdc.format_state = 0; break; case 2: /*Read track*/ fdc.pnum=0; fdc.ptot=8; fdc.stat=0x90; fdc.pos=0; break; case 3: /*Specify*/ fdc.pnum=0; fdc.ptot=2; fdc.stat=0x90; break; case 4: /*Sense drive status*/ fdc.pnum=0; fdc.ptot=1; fdc.stat=0x90; break; case 5: /*Write data*/ // printf("Write data!\n"); fdc.pnum=0; fdc.ptot=8; fdc.stat=0x90; fdc.pos=0; // readflash=1; break; case 6: /*Read data*/ fdc.pnum=0; fdc.ptot=8; fdc.stat=0x90; fdc.pos=0; break; case 7: /*Recalibrate*/ fdc.pnum=0; fdc.ptot=1; fdc.stat=0x90; break; case 8: /*Sense interrupt status*/ // printf("Sense interrupt status %i\n",curdrive); fdc.lastdrive = fdc.drive; // fdc.stat = 0x10 | (fdc.stat & 0xf); // fdc_time=1024; discint = 8; fdc.pos = 0; fdc_callback(); break; case 10: /*Read sector ID*/ fdc.pnum=0; fdc.ptot=1; fdc.stat=0x90; fdc.pos=0; break; case 0x0d: /*Format track*/ fdc.pnum=0; fdc.ptot=5; fdc.stat=0x90; fdc.pos=0; fdc.format_state = 0; break; case 15: /*Seek*/ fdc.pnum=0; fdc.ptot=2; fdc.stat=0x90; break; case 0x0e: /*Dump registers*/ fdc.lastdrive = fdc.drive; discint = 0x0e; fdc.pos = 0; fdc_callback(); break; case 0x10: /*Get version*/ fdc.lastdrive = fdc.drive; discint = 0x10; fdc.pos = 0; fdc_callback(); break; case 0x12: /*Set perpendicular mode*/ fdc.pnum=0; fdc.ptot=1; fdc.stat=0x90; fdc.pos=0; break; case 0x13: /*Configure*/ fdc.pnum=0; fdc.ptot=3; fdc.stat=0x90; fdc.pos=0; break; case 0x14: /*Unlock*/ case 0x94: /*Lock*/ fdc.lastdrive = fdc.drive; discint = fdc.command; fdc.pos = 0; fdc_callback(); break; case 0x18: if (!fdc.is_nsc) goto bad_command; fdc.lastdrive = fdc.drive; discint = 0x10; fdc.pos = 0; fdc_callback(); /* fdc.stat = 0x10; discint = 0xfc; fdc_callback(); */ break; default: bad_command: // fatal("Bad FDC command %02X\n",val); // dumpregs(); // exit(-1); fdc.stat=0x10; discint=0xfc; timer_process(); disctime = 200 * (1 << TIMER_SHIFT); timer_update_outstanding(); break; } } else { fdc.params[fdc.pnum++]=val; if (fdc.pnum==fdc.ptot) { // pclog("Got all params %02X\n", fdc.command); fdc.stat=0x30; discint=fdc.command&0x1F; timer_process(); disctime = 1024 * (1 << TIMER_SHIFT); timer_update_outstanding(); // fdc.drive = fdc.params[0] & 3; disc_drivesel = fdc.drive & 1; fdc_reset_stat = 0; disc_set_drivesel(fdc.drive & 1); switch (discint) { case 2: /*Read a track*/ fdc_rate(fdc.drive); fdc.head=fdc.params[2]; fdc.sector=fdc.params[3]; fdc.eot[fdc.drive] = fdc.params[5]; if (fdc.config & 0x40) fdd_seek(fdc.drive, fdc.params[1] - fdc.track[fdc.drive]); fdc.track[fdc.drive]=fdc.params[1]; // pclog("Read a track track=%i head=%i sector=%i eot=%i\n", fdc.track[fdc.drive], fdc.head, fdc.sector, fdc.eot[fdc.drive]); disc_readsector(fdc.drive, SECTOR_FIRST, fdc.track[fdc.drive], fdc.head, fdc.rate, fdc.params[4]); disctime = 0; readflash = 1; fdc.inread = 1; break; case 3: /*Specify*/ fdc.stat=0x80; fdc.specify[0] = fdc.params[0]; fdc.specify[1] = fdc.params[1]; fdc.dma = (fdc.specify[1] & 1) ^ 1; disctime = 0; break; case 5: /*Write data*/ fdc_rate(fdc.drive); fdc.head=fdc.params[2]; fdc.sector=fdc.params[3]; fdc.eot[fdc.drive] = fdc.params[5]; if (fdc.config & 0x40) fdd_seek(fdc.drive, fdc.params[1] - fdc.track[fdc.drive]); fdc.track[fdc.drive]=fdc.params[1]; fdc.rw_track = fdc.params[1]; disc_writesector(fdc.drive, fdc.sector, fdc.track[fdc.drive], fdc.head, fdc.rate, fdc.params[4]); disctime = 0; fdc.written = 0; readflash = 1; fdc.pos = 0; if (fdc.pcjr) fdc.stat = 0xb0; // ioc_fiq(IOC_FIQ_DISC_DATA); break; case 6: /*Read data*/ fdc_rate(fdc.drive); fdc.head=fdc.params[2]; fdc.sector=fdc.params[3]; fdc.eot[fdc.drive] = fdc.params[5]; if (fdc.config & 0x40) fdd_seek(fdc.drive, fdc.params[1] - fdc.track[fdc.drive]); fdc.track[fdc.drive]=fdc.params[1]; fdc.rw_track = fdc.params[1]; disc_readsector(fdc.drive, fdc.sector, fdc.track[fdc.drive], fdc.head, fdc.rate, fdc.params[4]); disctime = 0; readflash = 1; fdc.inread = 1; break; case 7: /*Recalibrate*/ fdc.stat = 1 << fdc.drive; disctime = 0; fdd_seek(fdc.drive, SEEK_RECALIBRATE); break; case 0x0d: /*Format*/ fdc_rate(fdc.drive); fdc.head = (fdc.params[0] & 4) ? 1 : 0; fdc.format_state = 1; fdc.pos = 0; fdc.stat = 0x30; break; case 0xf: /*Seek*/ fdc.stat = 1 << fdc.drive; fdc.head = (fdc.params[0] & 4) ? 1 : 0; disctime = 0; fdd_seek(fdc.drive, fdc.params[1] - fdc.track[fdc.drive]); // pclog("Seek to %i\n", fdc.params[1]); break; case 10: /*Read sector ID*/ fdc_rate(fdc.drive); disctime = 0; fdc.head = (fdc.params[0] & 4) ? 1 : 0; // pclog("Read sector ID %i %i\n", fdc.rate, fdc.drive); disc_readaddress(fdc.drive, fdc.track[fdc.drive], fdc.head, fdc.rate); break; } } } return; case 7: if (!AT) return; fdc.rate=val&3; disc_3f7=val; return; }