|
|
1.1 ! root 1: /* Floppy drive emulation */ ! 2: ! 3: ! 4: #include "ioMem.h" ! 5: #include "ioMemTables.h" ! 6: #include "m68000.h" ! 7: #include "configuration.h" ! 8: #include "sysReg.h" ! 9: #include "dma.h" ! 10: #include "floppy.h" ! 11: #include "cycInt.h" ! 12: #include "file.h" ! 13: #include "statusbar.h" ! 14: ! 15: ! 16: #define LOG_FLP_REG_LEVEL LOG_DEBUG ! 17: #define LOG_FLP_CMD_LEVEL LOG_DEBUG ! 18: ! 19: #define IO_SEG_MASK 0x1FFFF ! 20: ! 21: ! 22: /* Controller */ ! 23: struct { ! 24: Uint8 sra; /* Status Register A (ro) */ ! 25: Uint8 srb; /* Status Register B (ro) */ ! 26: Uint8 dor; /* Digital Output Register (rw) */ ! 27: Uint8 msr; /* Main Status Register (ro) */ ! 28: Uint8 dsr; /* Data Rate Select Register (wo) */ ! 29: Uint8 fifo[16]; /* Data FIFO (rw) */ ! 30: Uint8 din; /* Digital Input Register (wo) */ ! 31: Uint8 ccr; /* Configuration Control Register (ro) */ ! 32: Uint8 ctrl; /* External Control (rw) */ ! 33: ! 34: Uint8 st[4]; /* Internal Status Registers */ ! 35: Uint8 pcn; /* Cylinder Number */ ! 36: ! 37: Uint8 sel; ! 38: Uint8 eis; ! 39: } flp; ! 40: ! 41: Uint8 floppy_select = 0; ! 42: ! 43: /* Drives */ ! 44: struct { ! 45: Uint8 cyl; ! 46: Uint8 head; ! 47: Uint8 sector; ! 48: Uint8 blocksize; ! 49: ! 50: FILE* dsk; ! 51: Uint32 floppysize; ! 52: ! 53: bool spinning; ! 54: ! 55: bool protected; ! 56: bool inserted; ! 57: bool connected; ! 58: } flpdrv[FLP_MAX_DRIVES]; ! 59: ! 60: ! 61: /* Register bits */ ! 62: ! 63: #define SRA_INT 0x80 ! 64: #define SRA_DRV1_N 0x40 ! 65: #define SRA_STEP 0x20 ! 66: #define SRA_TRK0_N 0x10 ! 67: #define SRA_HDSEL 0x08 ! 68: #define SRA_INDEX_N 0x04 ! 69: #define SRA_WP_N 0x02 ! 70: #define SRA_DIR 0x01 ! 71: ! 72: #define SRB_ALL1 0xC0 ! 73: #define SRB_DRVSEL0_N 0x20 ! 74: #define SRB_W_TOGGLE 0x10 ! 75: #define SRB_R_TOGGLE 0x08 ! 76: #define SRB_W_ENABLE 0x04 ! 77: #define SRB_MOTEN_MASK 0x03 ! 78: ! 79: #define DOR_MOT3EN 0x80 ! 80: #define DOR_MOT2EN 0x40 ! 81: #define DOR_MOT1EN 0x20 ! 82: #define DOR_MOT0EN 0x10 ! 83: #define DOR_MOTEN_MASK 0xF0 ! 84: #define DOR_DMA_N 0x08 ! 85: #define DOR_RESET_N 0x04 ! 86: #define DOR_SEL_MSK 0x03 ! 87: ! 88: #define STAT_RQM 0x80 ! 89: #define STAT_DIO 0x40 /* read = 1 */ ! 90: #define STAT_NONDMA 0x20 ! 91: #define STAT_CMDBSY 0x10 ! 92: #define STAT_DRV3BSY 0x08 ! 93: #define STAT_DRV2BSY 0x04 ! 94: #define STAT_DRV1BSY 0x02 ! 95: #define STAT_DRV0BSY 0x01 ! 96: #define STAT_BSY_MASK 0x0F ! 97: ! 98: #define DSR_RESET 0x80 ! 99: #define DSR_PDOWN 0x40 ! 100: #define DSR_0 0x20 ! 101: #define DSR_PRE_MASK 0x1C ! 102: #define DSR_RATE_MASK 0x03 ! 103: ! 104: #define DIR_DSKCHG 0x80 ! 105: #define DIR_HIDENS_N 0x01 ! 106: ! 107: #define CCR_RATE_MASK 0x03 ! 108: ! 109: #define CTRL_EJECT 0x80 ! 110: #define CTRL_82077 0x40 ! 111: #define CTRL_DRV_ID 0x04 ! 112: #define CTRL_MEDIA_ID1 0x02 ! 113: #define CTRL_MEDIA_ID0 0x01 ! 114: ! 115: ! 116: /* Functions */ ! 117: void floppy_reset(bool hard); ! 118: Uint8 floppy_fifo_read(void); ! 119: void floppy_fifo_write(Uint8 val); ! 120: Uint8 floppy_dor_read(void); ! 121: void floppy_dor_write(Uint8 val); ! 122: Uint8 floppy_sra_read(void); ! 123: ! 124: ! 125: void FLP_StatA_Read(void) { // 0x02014100 ! 126: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = floppy_sra_read(); ! 127: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Status A read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 128: } ! 129: ! 130: void FLP_StatB_Read(void) { // 0x02014101 ! 131: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = flp.srb|SRB_ALL1; ! 132: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Status B read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 133: } ! 134: ! 135: void FLP_DataOut_Read(void) { // 0x02014102 ! 136: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = floppy_dor_read(); ! 137: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Data out read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 138: } ! 139: ! 140: void FLP_DataOut_Write(void) { ! 141: floppy_dor_write(IoMem[IoAccessCurrentAddress & IO_SEG_MASK]); ! 142: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Data out write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 143: } ! 144: ! 145: void FLP_Status_Read(void) { // 0x02014104 ! 146: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = flp.msr; ! 147: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Main status read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 148: } ! 149: ! 150: void FLP_DataRate_Write(void) { ! 151: flp.dsr = IoMem[IoAccessCurrentAddress & IO_SEG_MASK]; ! 152: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Data rate write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 153: ! 154: if (flp.dsr&DSR_RESET) { ! 155: floppy_reset(false); ! 156: flp.dsr&=~DSR_RESET; ! 157: } ! 158: } ! 159: ! 160: void FLP_FIFO_Read(void) { // 0x02014105 ! 161: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = floppy_fifo_read(); ! 162: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] FIFO read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 163: } ! 164: ! 165: void FLP_FIFO_Write(void) { ! 166: Uint8 val = IoMem[IoAccessCurrentAddress & IO_SEG_MASK]; ! 167: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] FIFO write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 168: ! 169: floppy_fifo_write(val); ! 170: } ! 171: ! 172: void FLP_DataIn_Read(void) { // 0x02014107 ! 173: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = flp.din; ! 174: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Data in read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 175: } ! 176: ! 177: void FLP_Configuration_Write(void) { ! 178: flp.ccr = IoMem[IoAccessCurrentAddress & IO_SEG_MASK]; ! 179: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Configuration write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 180: } ! 181: ! 182: void FLP_Control_Read(void) { // 0x02014108 ! 183: Uint8 val; ! 184: if (ConfigureParams.System.nMachineType==NEXT_CUBE030) ! 185: val=flp.ctrl&~CTRL_DRV_ID; ! 186: else ! 187: val=flp.ctrl; ! 188: ! 189: IoMem[IoAccessCurrentAddress & IO_SEG_MASK] = val; ! 190: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Control read at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 191: } ! 192: ! 193: void FLP_Select_Write(void) { ! 194: Uint8 val; ! 195: val = IoMem[IoAccessCurrentAddress & IO_SEG_MASK]; ! 196: Log_Printf(LOG_DEBUG,"[Floppy] Select write at $%08x val=$%02x PC=$%08x\n", IoAccessCurrentAddress, IoMem[IoAccessCurrentAddress & IO_SEG_MASK], m68k_getpc()); ! 197: ! 198: if (ConfigureParams.System.nMachineType!=NEXT_CUBE030) { ! 199: set_floppy_select(val&CTRL_82077,false); ! 200: } ! 201: ! 202: if (val&CTRL_EJECT) { ! 203: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Ejecting floppy disk"); ! 204: Floppy_Eject(-1); ! 205: } ! 206: } ! 207: ! 208: void set_floppy_select(Uint8 sel, bool osp) { ! 209: if (sel) { ! 210: Log_Printf(LOG_WARN,"[%s] Selecting floppy controller",osp?"OSP":"Floppy"); ! 211: floppy_select = 1; ! 212: } else { ! 213: Log_Printf(LOG_FLP_REG_LEVEL,"[%s] Selecting SCSI controller",osp?"OSP":"Floppy"); ! 214: floppy_select = 0; ! 215: } ! 216: } ! 217: ! 218: enum { ! 219: FLP_STATE_WRITE, ! 220: FLP_STATE_READ, ! 221: FLP_STATE_FORMAT, ! 222: FLP_STATE_INTERRUPT, ! 223: FLP_STATE_DONE ! 224: } flp_io_state; ! 225: ! 226: int flp_sector_counter = 0; ! 227: int flp_io_drv = 0; ! 228: ! 229: ! 230: /* Internal registers */ ! 231: ! 232: #define ST0_IC 0xC0 /* Interrupt Code (0 = normal termination) */ ! 233: #define ST0_SE 0x20 /* Seek End */ ! 234: #define ST0_EC 0x10 /* Equipment Check */ ! 235: #define ST0_H 0x04 /* Head Address */ ! 236: #define ST0_DS 0x03 /* Drive Select */ ! 237: ! 238: #define ST1_EN 0x80 /* End of Cylinder */ ! 239: #define ST1_DE 0x20 /* Data Error */ ! 240: #define ST1_OR 0x10 /* Overrun/Underrun */ ! 241: #define ST1_ND 0x04 /* No Data */ ! 242: #define ST1_NW 0x02 /* Not writable */ ! 243: #define ST1_MA 0x01 /* Missing Address Mark */ ! 244: ! 245: #define ST2_CM 0x40 /* Control Mark */ ! 246: #define ST2_DD 0x20 /* Data Error in Data Field */ ! 247: #define ST2_WC 0x10 /* Wrong Cylinder */ ! 248: #define ST2_BC 0x02 /* Bad Cylinder */ ! 249: #define ST2_MD 0x01 /* Missing Data Address Mark */ ! 250: ! 251: #define ST3_WP 0x40 /* Write Protected */ ! 252: #define ST3_T0 0x10 /* Track 0 */ ! 253: #define ST3_HD 0x04 /* Head Address */ ! 254: #define ST3_DS 0x03 /* Drive Select */ ! 255: ! 256: ! 257: #define IC_NORMAL 0x00 ! 258: #define IC_ABNORMAL 0x40 ! 259: #define IC_INV_CMD 0x80 ! 260: ! 261: ! 262: ! 263: void floppy_reset(bool hard) { ! 264: Log_Printf(LOG_WARN,"[Floppy] Reset."); ! 265: ! 266: flp.sra &= ~(SRA_INT|SRA_STEP|SRA_HDSEL|SRA_DIR); ! 267: flp.srb &= ~(SRB_R_TOGGLE|SRB_W_TOGGLE); ! 268: flp.msr |= STAT_RQM; ! 269: flp.msr &= ~STAT_DIO; ! 270: ! 271: if (hard) { ! 272: flp_io_state = FLP_STATE_DONE; ! 273: flp.dor &= ~DOR_RESET_N; ! 274: flp.srb &= ~(SRB_MOTEN_MASK|SRB_DRVSEL0_N); ! 275: flp.din &= ~DIR_HIDENS_N; ! 276: flp.st[0]=flp.st[1]=flp.st[2]=flp.st[3]=0; ! 277: flp.pcn=0; ! 278: } else { ! 279: /* Single poll interrupt after reset (FIXME: delay should be 250 ms) */ ! 280: flp_io_state = FLP_STATE_INTERRUPT; ! 281: CycInt_AddRelativeInterrupt(1000000, INT_CPU_CYCLE, INTERRUPT_FLP_IO); ! 282: } ! 283: } ! 284: ! 285: /* Floppy commands */ ! 286: ! 287: #define CMD_MT_MSK 0x80 ! 288: #define CMD_MFM_MSK 0x40 ! 289: #define CMD_SK_MSK 0x20 ! 290: #define CMD_OPCODE_MSK 0x1F ! 291: ! 292: #define CMD_READ 0x06 ! 293: #define CMD_READ_DEL 0x0C ! 294: #define CMD_WRITE 0x05 ! 295: #define CMD_WRITE_DEL 0x09 ! 296: #define CMD_READ_TRK 0x02 ! 297: #define CMD_VERIFY 0x16 ! 298: #define CMD_VERSION 0x10 ! 299: #define CMD_FORMAT 0x0D ! 300: #define CMD_SCAN_E 0x11 ! 301: #define CMD_SCAN_LE 0x19 ! 302: #define CMD_SCAN_HE 0x1D ! 303: #define CMD_RECAL 0x07 ! 304: #define CMD_INTSTAT 0x08 ! 305: #define CMD_SPECIFY 0x03 ! 306: #define CMD_DRV_STATUS 0x04 ! 307: #define CMD_SEEK 0x0F ! 308: #define CMD_CONFIGURE 0x13 ! 309: #define CMD_DUMPREG 0x0E ! 310: #define CMD_READ_ID 0x0A ! 311: #define CMD_PERPEND 0x12 ! 312: #define CMD_LOCK 0x14 ! 313: ! 314: Uint8 cmd_data_size[] = { ! 315: 0,0,8,2,1,8,8,1, ! 316: 0,8,1,0,8,5,0,2, ! 317: 0,8,1,3,0,0,8,0, ! 318: 0,8,0,0,0,8,0,0 ! 319: }; ! 320: ! 321: bool cmd_phase = false; ! 322: int cmd_size = 0; ! 323: int cmd_limit = 0; ! 324: Uint8 command; ! 325: Uint8 cmd_data[8]; ! 326: ! 327: int result_size = 0; ! 328: ! 329: void floppy_interrupt(void) { ! 330: Log_Printf(LOG_FLP_CMD_LEVEL,"[Floppy] Interrupt."); ! 331: ! 332: if (result_size>0) { ! 333: /* Go to result phase */ ! 334: flp.msr |= (STAT_RQM|STAT_DIO); ! 335: } else { ! 336: flp.msr |= STAT_RQM; ! 337: } ! 338: ! 339: flp.msr &= ~(STAT_BSY_MASK); ! 340: flp.sra |= SRA_INT; ! 341: set_interrupt(INT_PHONE, SET_INT); ! 342: } ! 343: ! 344: /* -- Helpers -- */ ! 345: ! 346: /* Geometry */ ! 347: #define SIZE_720K 737280 ! 348: #define SIZE_1440K 1474560 ! 349: #define SIZE_2880K 2949120 ! 350: ! 351: #define NUM_CYLINDERS 80 ! 352: #define TRACKS_PER_CYL 2 ! 353: ! 354: Uint32 physical_to_logical_sector(Uint8 c, Uint8 h, Uint8 s, int drive) { ! 355: Uint32 disksize = flpdrv[drive].floppysize; ! 356: Uint32 blocksize = 0x80<<flpdrv[drive].blocksize; ! 357: Uint32 spt = disksize/blocksize/TRACKS_PER_CYL/NUM_CYLINDERS; ! 358: ! 359: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Geometry: Cylinders: %i, Tracks per cylinder: %i, Sectors per track: %i, Blocksize: %i", ! 360: NUM_CYLINDERS,TRACKS_PER_CYL,spt,blocksize); ! 361: ! 362: if (s>spt) { ! 363: Log_Printf(LOG_WARN, "[Floppy] Geometry error: sector (%i) beyond limit (%i)!",s,spt); ! 364: flp.st[0] |= IC_ABNORMAL; ! 365: flp.st[1] |= ST1_EN; ! 366: } ! 367: ! 368: return (((c*TRACKS_PER_CYL)+h)*spt)+s-1; ! 369: } ! 370: ! 371: void check_blocksize(int drive, Uint8 blocksize) { ! 372: if (blocksize!=flpdrv[drive].blocksize) { ! 373: Log_Printf(LOG_WARN, "[Floppy] Geometry error: Blocksize not supported (%i)!",blocksize); ! 374: flp.st[0] |= IC_ABNORMAL; ! 375: flp.st[1] |= ST1_ND; ! 376: } ! 377: } ! 378: ! 379: void check_protection(int drive) { ! 380: if (flpdrv[drive].protected) { ! 381: Log_Printf(LOG_WARN, "[Floppy] Protection error: Disk is read-only!"); ! 382: flp.st[0] |= IC_ABNORMAL; ! 383: flp.st[1] |= ST1_NW; ! 384: } ! 385: } ! 386: ! 387: void floppy_seek_track(Uint8 c, Uint8 h, int drive) { ! 388: if (c>(NUM_CYLINDERS-1)) /* CHECK: does this cause an error? */ ! 389: c=(NUM_CYLINDERS-1); ! 390: ! 391: flp.st[0] |= ST0_SE; ! 392: flpdrv[drive].cyl = c; ! 393: flpdrv[drive].head = h; ! 394: } ! 395: ! 396: /* Media IDs for control register */ ! 397: #define MEDIA_ID_NONE 0 ! 398: #define MEDIA_ID_720K 3 ! 399: #define MEDIA_ID_1440K 2 ! 400: #define MEDIA_ID_2880K 1 ! 401: #define MEDIA_ID_MSK 3 ! 402: ! 403: Uint8 get_media_id(int drive) { ! 404: if (!flpdrv[drive].inserted) { ! 405: return MEDIA_ID_NONE; ! 406: } else { ! 407: switch (flpdrv[drive].floppysize) { ! 408: case SIZE_720K: return MEDIA_ID_720K; ! 409: case SIZE_1440K: return MEDIA_ID_1440K; ! 410: case SIZE_2880K: return MEDIA_ID_2880K; ! 411: default: return MEDIA_ID_NONE; ! 412: } ! 413: } ! 414: } ! 415: ! 416: /* Validate data rate */ ! 417: #define CCR_RATE250 0x02 ! 418: #define CCR_RATE500 0x00 ! 419: #define CCR_RATE1000 0x03 ! 420: ! 421: void check_data_rate(int drive) { ! 422: switch (flpdrv[drive].floppysize) { ! 423: case SIZE_720K: ! 424: if ((flp.ccr&CCR_RATE_MASK)==CCR_RATE250) { ! 425: return; ! 426: } ! 427: break; ! 428: case SIZE_1440K: ! 429: if ((flp.ccr&CCR_RATE_MASK)==CCR_RATE500) { ! 430: return; ! 431: } ! 432: break; ! 433: case SIZE_2880K: ! 434: if ((flp.ccr&CCR_RATE_MASK)==CCR_RATE1000) { ! 435: return; ! 436: } ! 437: break; ! 438: ! 439: default: ! 440: break; ! 441: } ! 442: Log_Printf(LOG_WARN, "[Floppy] Invalid data rate %02X",flp.ccr&CCR_RATE_MASK); ! 443: flp.st[0] |= IC_ABNORMAL; ! 444: flp.st[1] |= ST1_ND; ! 445: } ! 446: ! 447: void send_rw_status(int drive) { ! 448: flp.st[0] |= drive|(flpdrv[drive].head<<2); ! 449: flp.fifo[0] = flp.st[0]; ! 450: flp.fifo[1] = flp.st[1]; ! 451: flp.fifo[2] = flp.st[2]; ! 452: flp.fifo[3] = flpdrv[drive].cyl; ! 453: flp.fifo[4] = flpdrv[drive].head; ! 454: flp.fifo[5] = flpdrv[drive].sector; ! 455: flp.fifo[6] = flpdrv[drive].blocksize; ! 456: result_size = 7; ! 457: } ! 458: ! 459: /* -- Floppy commands -- */ ! 460: ! 461: void floppy_read(void) { ! 462: int drive = cmd_data[0]&0x03; ! 463: int head = (cmd_data[0]&0x04)>>2; ! 464: Uint8 c = cmd_data[1]; ! 465: Uint8 h = cmd_data[2]; ! 466: Uint8 s = cmd_data[3]; ! 467: Uint8 bs = cmd_data[4]; ! 468: ! 469: Uint32 sector_size, num_sectors, logical_sec; ! 470: ! 471: flp.st[0] = flp.st[1] = flp.st[2] = 0; ! 472: ! 473: /* If implied seek is enabled, seek track */ ! 474: if (flp.eis) { ! 475: floppy_seek_track(c, h, drive); ! 476: } ! 477: /* Set start sector */ ! 478: flpdrv[drive].sector = s; ! 479: ! 480: /* Match actual track with specified track */ ! 481: if (flpdrv[drive].cyl!=c || flpdrv[drive].head!=h || flpdrv[drive].head!=head) { ! 482: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Read: track mismatch!"); ! 483: flp.st[0]|=IC_ABNORMAL; ! 484: flp.st[2]|=ST2_WC; ! 485: } ! 486: /* Validate blocksize */ ! 487: check_blocksize(drive,bs); ! 488: sector_size = 0x80<<bs; ! 489: ! 490: /* Validate data rate */ ! 491: check_data_rate(drive); ! 492: ! 493: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Read: Cylinder=%i, Head=%i, Sector=%i, Blocksize=%i", ! 494: flpdrv[drive].cyl,flpdrv[drive].head,flpdrv[drive].sector,sector_size); ! 495: ! 496: /* Get sector transfer count and logical sector offset */ ! 497: num_sectors = cmd_data[5]-cmd_data[3]+1; ! 498: logical_sec = physical_to_logical_sector(flpdrv[drive].cyl,flpdrv[drive].head,flpdrv[drive].sector,drive); ! 499: ! 500: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Read %i sectors at offset %i",num_sectors,logical_sec); ! 501: ! 502: if (flp.st[0]&IC_ABNORMAL) { ! 503: send_rw_status(drive); ! 504: flp_io_state = FLP_STATE_INTERRUPT; ! 505: } else { ! 506: flp_buffer.size = 0; ! 507: flp_buffer.limit = sector_size; ! 508: flp_sector_counter = num_sectors; ! 509: flp_io_drv = drive; ! 510: flp_io_state = FLP_STATE_READ; ! 511: } ! 512: CycInt_AddRelativeInterrupt(1000, INT_CPU_CYCLE, INTERRUPT_FLP_IO); ! 513: } ! 514: ! 515: void floppy_write(void) { ! 516: int drive = cmd_data[0]&0x03; ! 517: int head = (cmd_data[0]&0x04)>>2; ! 518: Uint8 c = cmd_data[1]; ! 519: Uint8 h = cmd_data[2]; ! 520: Uint8 s = cmd_data[3]; ! 521: Uint8 bs = cmd_data[4]; ! 522: ! 523: Uint32 sector_size, num_sectors, logical_sec; ! 524: ! 525: flp.st[0] = flp.st[1] = flp.st[2] = 0; ! 526: ! 527: /* If implied seek is enabled, seek track */ ! 528: if (flp.eis) { ! 529: floppy_seek_track(c, h, drive); ! 530: } ! 531: /* Set start sector */ ! 532: flpdrv[drive].sector = s; ! 533: ! 534: /* Match actual track with specified track */ ! 535: if (flpdrv[drive].cyl!=c || flpdrv[drive].head!=h || flpdrv[drive].head!=head) { ! 536: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Write: track mismatch!"); ! 537: flp.st[0]|=IC_ABNORMAL; ! 538: flp.st[2]|=ST2_WC; ! 539: } ! 540: /* Validate blocksize */ ! 541: check_blocksize(drive,bs); ! 542: sector_size = 0x80<<bs; ! 543: ! 544: /* Validate data rate */ ! 545: check_data_rate(drive); ! 546: ! 547: /* Check protection */ ! 548: check_protection(drive); ! 549: ! 550: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Write: Cylinder=%i, Head=%i, Sector=%i, Blocksize=%i", ! 551: flpdrv[drive].cyl,flpdrv[drive].head,flpdrv[drive].sector,sector_size); ! 552: ! 553: /* Get sector transfer count and logical sector offset */ ! 554: num_sectors = cmd_data[5]-cmd_data[3]+1; ! 555: logical_sec = physical_to_logical_sector(flpdrv[drive].cyl,flpdrv[drive].head,flpdrv[drive].sector,drive); ! 556: ! 557: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Write %i sectors at offset %i",num_sectors,logical_sec); ! 558: ! 559: if (flp.st[0]&IC_ABNORMAL) { ! 560: send_rw_status(drive); ! 561: flp_io_state = FLP_STATE_INTERRUPT; ! 562: } else { ! 563: flp_buffer.size = 0; ! 564: flp_buffer.limit = sector_size; ! 565: flp_sector_counter = num_sectors; ! 566: flp_io_drv = drive; ! 567: flp_io_state = FLP_STATE_WRITE; ! 568: } ! 569: CycInt_AddRelativeInterrupt(1000, INT_CPU_CYCLE, INTERRUPT_FLP_IO); ! 570: } ! 571: ! 572: void floppy_format(void) { ! 573: int drive = cmd_data[0]&0x03; ! 574: int head = (cmd_data[0]&0x04)>>2; ! 575: ! 576: flp.st[0] = flp.st[1] = flp.st[2] = 0; ! 577: ! 578: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Format: Cylinder=%i, Head=%i",flpdrv[drive].cyl,head); ! 579: ! 580: /* Validate data rate */ ! 581: check_data_rate(drive); ! 582: ! 583: /* Check protection */ ! 584: check_protection(drive); ! 585: ! 586: if (flp.st[0]&IC_ABNORMAL) { ! 587: send_rw_status(drive); ! 588: flp_io_state = FLP_STATE_INTERRUPT; ! 589: } else { ! 590: flp_buffer.size = 0; ! 591: flp_buffer.limit = 4; ! 592: flp_io_drv = drive; ! 593: flp_io_state = FLP_STATE_FORMAT; ! 594: CycInt_AddRelativeInterrupt(100000, INT_CPU_CYCLE, INTERRUPT_FLP_IO); ! 595: } ! 596: } ! 597: ! 598: void floppy_read_id(void) { ! 599: int drive = cmd_data[0]&0x03; ! 600: int head = (cmd_data[0]&0x04)>>2; ! 601: ! 602: Uint32 sec_size = 0x80<<flpdrv[drive].blocksize; ! 603: ! 604: if (flpdrv[drive].head!=head) ! 605: abort(); ! 606: ! 607: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Read ID: Cylinder=%i, Head=%i, Sector=%i, Blocksize=%i", ! 608: flpdrv[drive].cyl,flpdrv[drive].head,flpdrv[drive].sector,sec_size); ! 609: ! 610: flp.st[0] = flp.st[1] = flp.st[2] = 0; ! 611: ! 612: check_data_rate(drive); /* check data rate */ ! 613: send_rw_status(drive); ! 614: ! 615: flp_io_state = FLP_STATE_INTERRUPT; ! 616: CycInt_AddRelativeInterrupt(1000, INT_CPU_CYCLE, INTERRUPT_FLP_IO); ! 617: } ! 618: ! 619: void floppy_recalibrate(void) { ! 620: int drive = cmd_data[0]&0x03; ! 621: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Drive = %i",drive); ! 622: ! 623: if (flpdrv[drive].connected) { ! 624: flp.msr |= (1<<drive); /* drive busy */ ! 625: flp.dor &= 0xFC; /* CHECK: really needed? */ ! 626: flp.dor |= drive; ! 627: flpdrv[drive].cyl = flp.pcn = 0; ! 628: ! 629: flp.st[0] = flp.st[1] = flp.st[2] = 0; ! 630: ! 631: /* Done */ ! 632: flp.st[0] = IC_NORMAL|ST0_SE; ! 633: flp.sra &= ~SRA_TRK0_N; ! 634: ! 635: flp_io_state = FLP_STATE_INTERRUPT; ! 636: CycInt_AddRelativeInterrupt(1000000, INT_CPU_CYCLE, INTERRUPT_FLP_IO); ! 637: } ! 638: } ! 639: ! 640: void floppy_seek(Uint8 relative) { ! 641: int drive = cmd_data[0]&0x03; ! 642: int head = (cmd_data[0]&0x04)>>2; ! 643: flp.st[0] = flp.st[1] = flp.st[2] = 0; ! 644: ! 645: if (relative) { ! 646: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Relative seek: Head %i: %i cylinders",head,0); ! 647: abort(); ! 648: } else { ! 649: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Seek: Head %i to cylinder %i",head,flpdrv[drive].cyl); ! 650: flp.st[0] = IC_NORMAL; ! 651: ! 652: floppy_seek_track(cmd_data[1], head, drive); ! 653: if (!(flp.st[0]&IC_ABNORMAL)) { ! 654: flp.pcn = flpdrv[drive].cyl; ! 655: } ! 656: } ! 657: ! 658: flp_io_state = FLP_STATE_INTERRUPT; ! 659: CycInt_AddRelativeInterrupt(1000000, INT_CPU_CYCLE, INTERRUPT_FLP_IO); ! 660: } ! 661: ! 662: void floppy_interrupt_status(void) { ! 663: /* Release interrupt */ ! 664: set_interrupt(INT_PHONE, RELEASE_INT); ! 665: flp.sra &= ~SRA_INT; ! 666: /* Go to result phase */ ! 667: flp.msr |= (STAT_RQM|STAT_DIO); ! 668: /* Return data */ ! 669: flp.fifo[0] = flp.st[0]; ! 670: flp.fifo[1] = flp.pcn; ! 671: result_size = 2; ! 672: } ! 673: ! 674: void floppy_specify(void) { ! 675: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Specify: %02X %02X",cmd_data[0],cmd_data[1]); ! 676: ! 677: if (cmd_data[1]&0x01) { ! 678: Log_Printf(LOG_WARN, "[Floppy] Specify: Non-DMA mode"); ! 679: } else { ! 680: Log_Printf(LOG_WARN, "[Floppy] Specify: DMA mode"); ! 681: } ! 682: flp.msr |= STAT_RQM; ! 683: } ! 684: ! 685: void floppy_configure(void) { ! 686: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Configure: %02X %02X %02X",cmd_data[0],cmd_data[1],cmd_data[2]); ! 687: ! 688: flp.eis = cmd_data[1]&0x40; /* Enable or disable implied seek */ ! 689: ! 690: if (cmd_data[1]&0x10) { ! 691: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Configure: disable polling"); ! 692: if (CycInt_InterruptActive(INTERRUPT_FLP_IO)) { ! 693: Log_Printf(LOG_WARN, "[Floppy] Disable pending reset poll interrupt"); ! 694: CycInt_RemovePendingInterrupt(INTERRUPT_FLP_IO); ! 695: } ! 696: } ! 697: if (cmd_data[2]) { ! 698: abort(); ! 699: } ! 700: flp.msr |= STAT_RQM; ! 701: } ! 702: ! 703: void floppy_perpendicular(void) { ! 704: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Perpendicular: %02X",cmd_data[0]); ! 705: flp.msr |= STAT_RQM; ! 706: } ! 707: ! 708: void floppy_unimplemented(void) { ! 709: flp.st[0] = IC_INV_CMD; ! 710: ! 711: flp.fifo[0] = flp.st[0]; ! 712: result_size = 1; ! 713: ! 714: flp_io_state = FLP_STATE_INTERRUPT; ! 715: CycInt_AddRelativeInterrupt(10000, INT_CPU_CYCLE, INTERRUPT_FLP_IO); ! 716: } ! 717: ! 718: void floppy_execute_cmd(void) { ! 719: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Executing %02X",command); ! 720: ! 721: switch (command&CMD_OPCODE_MSK) { ! 722: case CMD_READ: ! 723: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Read"); ! 724: floppy_read(); ! 725: break; ! 726: case CMD_READ_DEL: ! 727: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Read and delete"); ! 728: abort(); ! 729: break; ! 730: case CMD_WRITE: ! 731: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Write"); ! 732: floppy_write(); ! 733: break; ! 734: case CMD_WRITE_DEL: ! 735: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Write and delete"); ! 736: abort(); ! 737: break; ! 738: case CMD_READ_TRK: ! 739: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Read track"); ! 740: abort(); ! 741: break; ! 742: case CMD_VERIFY: ! 743: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Verify"); ! 744: abort(); ! 745: break; ! 746: case CMD_VERSION: ! 747: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Version"); ! 748: abort(); ! 749: break; ! 750: case CMD_FORMAT: ! 751: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Format"); ! 752: floppy_format(); ! 753: break; ! 754: case CMD_SCAN_E: ! 755: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Scan equal"); ! 756: abort(); ! 757: break; ! 758: case CMD_SCAN_LE: ! 759: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Scan lower or equal"); ! 760: abort(); ! 761: break; ! 762: case CMD_SCAN_HE: ! 763: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Scan higher or equal"); ! 764: abort(); ! 765: break; ! 766: case CMD_RECAL: ! 767: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Recalibrate"); ! 768: floppy_recalibrate(); ! 769: break; ! 770: case CMD_INTSTAT: ! 771: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Interrupt status"); ! 772: floppy_interrupt_status(); ! 773: break; ! 774: case CMD_SPECIFY: ! 775: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Specify"); ! 776: floppy_specify(); ! 777: break; ! 778: case CMD_DRV_STATUS: ! 779: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Drive status"); ! 780: abort(); ! 781: break; ! 782: case CMD_SEEK: ! 783: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Seek"); ! 784: floppy_seek(command&0x80); ! 785: break; ! 786: case CMD_CONFIGURE: ! 787: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Configure"); ! 788: floppy_configure(); ! 789: break; ! 790: case CMD_DUMPREG: ! 791: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Dump register"); ! 792: abort(); ! 793: break; ! 794: case CMD_READ_ID: ! 795: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Read ID"); ! 796: floppy_read_id(); ! 797: break; ! 798: case CMD_PERPEND: ! 799: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Perpendicular"); ! 800: floppy_perpendicular(); ! 801: break; ! 802: case CMD_LOCK: ! 803: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Command: Lock"); ! 804: abort(); ! 805: break; ! 806: ! 807: default: ! 808: Log_Printf(LOG_WARN, "[Floppy] Command: Unknown"); ! 809: floppy_unimplemented(); ! 810: break; ! 811: } ! 812: Statusbar_BlinkLed(DEVICE_LED_FD); ! 813: } ! 814: ! 815: void floppy_fifo_write(Uint8 val) { ! 816: ! 817: flp.msr &= ~STAT_RQM; ! 818: ! 819: if (!cmd_phase) { ! 820: cmd_phase = true; ! 821: command = val; ! 822: cmd_limit = cmd_size = cmd_data_size[val&CMD_OPCODE_MSK]; ! 823: flp.msr |= STAT_RQM; ! 824: } else if (cmd_size>0) { ! 825: cmd_data[cmd_limit-cmd_size]=val; ! 826: cmd_size--; ! 827: flp.msr |= STAT_RQM; ! 828: } ! 829: ! 830: if (cmd_size==0) { ! 831: cmd_phase = false; ! 832: floppy_execute_cmd(); ! 833: } ! 834: } ! 835: ! 836: Uint8 floppy_fifo_read(void) { ! 837: int i; ! 838: Uint8 val; ! 839: if (result_size>0) { ! 840: val = flp.fifo[0]; ! 841: for (i=0; i<(16-1); i++) ! 842: flp.fifo[i]=flp.fifo[i+1]; ! 843: flp.fifo[16-1] = 0x00; ! 844: result_size--; ! 845: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] FIFO reading byte, val=%02x", val); ! 846: } else { ! 847: Log_Printf(LOG_WARN,"[Floppy] FIFO is emtpy!"); ! 848: val = 0; ! 849: } ! 850: ! 851: if (result_size==0) { ! 852: flp.msr |= STAT_RQM; ! 853: flp.msr &= ~STAT_DIO; ! 854: /* FIXME: does this really belong here? */ ! 855: set_interrupt(INT_PHONE, RELEASE_INT); ! 856: flp.sra &= ~SRA_INT; ! 857: } ! 858: ! 859: return val; ! 860: } ! 861: ! 862: void floppy_dor_write(Uint8 val) { ! 863: if ((val&DOR_SEL_MSK)!=flp.sel) { ! 864: Log_Printf(LOG_FLP_CMD_LEVEL,"[Floppy] Selecting drive %i.",val&DOR_SEL_MSK); ! 865: } ! 866: flp.sel = val&DOR_SEL_MSK; ! 867: ! 868: flp.dor &= ~DOR_SEL_MSK; ! 869: flp.dor |= flp.sel; ! 870: ! 871: ! 872: if (!(val&DOR_RESET_N)) { ! 873: flp.dor &= ~DOR_RESET_N; ! 874: floppy_reset(false); ! 875: } else { ! 876: flp.dor |= DOR_RESET_N; ! 877: Log_Printf(LOG_FLP_REG_LEVEL,"[Floppy] Clear reset state."); ! 878: } ! 879: if (flpdrv[flp.sel].connected) { ! 880: flp.ctrl &= ~CTRL_DRV_ID; ! 881: ! 882: if (val&(0x10<<flp.sel)) { /* motor enable */ ! 883: Log_Printf(LOG_FLP_CMD_LEVEL,"[Floppy] Starting motor of drive %i.",flp.sel); ! 884: flp.ctrl &= ~MEDIA_ID_MSK; ! 885: flp.ctrl |= get_media_id(flp.sel); ! 886: flpdrv[flp.sel].spinning = true; ! 887: } else { ! 888: Log_Printf(LOG_FLP_CMD_LEVEL,"[Floppy] Stopping motor of drive %i.",flp.sel); ! 889: flp.ctrl &= ~MEDIA_ID_MSK; /* CHECK: really delete ID? */ ! 890: flpdrv[flp.sel].spinning = false; ! 891: } ! 892: } else { ! 893: flp.ctrl |= CTRL_DRV_ID; ! 894: } ! 895: } ! 896: ! 897: Uint8 floppy_dor_read(void) { ! 898: int i; ! 899: Uint8 val = flp.dor&~DOR_MOTEN_MASK; /* clear motor bits */ ! 900: for (i=0; i<FLP_MAX_DRIVES; i++) { ! 901: if (flpdrv[i].spinning) { /* set motor bit if motor is on */ ! 902: val |= 0x10<<i; ! 903: } ! 904: } ! 905: return val; ! 906: } ! 907: ! 908: Uint8 floppy_sra_read(void) { ! 909: Uint8 val = flp.sra; ! 910: if (!flpdrv[flp.sel].protected) { ! 911: val|=SRA_WP_N; ! 912: } ! 913: return val; ! 914: } ! 915: ! 916: ! 917: /* -- Floppy I/O functions -- */ ! 918: ! 919: void floppy_rw_nodata(void) { ! 920: Log_Printf(LOG_WARN, "[Floppy] Write: No more data from DMA. Stopping."); ! 921: /* Stop transfer */ ! 922: flp_sector_counter=0; ! 923: flp.st[0] |= IC_ABNORMAL; ! 924: flp.st[1] |= ST1_OR; ! 925: send_rw_status(flp_io_drv); ! 926: } ! 927: ! 928: void floppy_format_done(void) { ! 929: int drive = flp_io_drv; ! 930: ! 931: Log_Printf(LOG_WARN, "[Floppy] Format: No more data from DMA. Done."); ! 932: ! 933: flp.st[0] = IC_NORMAL; ! 934: send_rw_status(drive); ! 935: } ! 936: ! 937: void floppy_read_sector(void) { ! 938: int drive = flp_io_drv; ! 939: ! 940: /* Read from image */ ! 941: Uint32 sec_size = 0x80<<flpdrv[drive].blocksize; ! 942: Uint32 logical_sec = physical_to_logical_sector(flpdrv[drive].cyl,flpdrv[drive].head,flpdrv[drive].sector,drive); ! 943: ! 944: if (flp.st[0]&IC_ABNORMAL) { ! 945: Log_Printf(LOG_WARN, "[Floppy] Read error. Bad sector offset (%i).",logical_sec); ! 946: flp_sector_counter=0; /* stop the transfer */ ! 947: flp_io_state = FLP_STATE_INTERRUPT; ! 948: send_rw_status(drive); ! 949: return; ! 950: } else { ! 951: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Read sector at offset %i",logical_sec); ! 952: ! 953: flp_buffer.size = flp_buffer.limit = sec_size; ! 954: fseek(flpdrv[drive].dsk, logical_sec*sec_size, SEEK_SET); ! 955: fread(flp_buffer.data, flp_buffer.size, 1, flpdrv[drive].dsk); ! 956: flpdrv[drive].sector++; ! 957: flp_sector_counter--; ! 958: } ! 959: ! 960: if (flp_sector_counter==0) { ! 961: flp.st[0] = IC_ABNORMAL; /* Strange behavior of NeXT hardware */ ! 962: flp.st[1] |= ST1_EN; ! 963: send_rw_status(drive); ! 964: } ! 965: } ! 966: ! 967: void floppy_write_sector(void) { ! 968: int drive = flp_io_drv; ! 969: ! 970: /* Write to image */ ! 971: Uint32 sec_size = 0x80<<flpdrv[drive].blocksize; ! 972: Uint32 logical_sec = physical_to_logical_sector(flpdrv[drive].cyl,flpdrv[drive].head,flpdrv[drive].sector,drive); ! 973: ! 974: if (flp.st[0]&IC_ABNORMAL) { ! 975: Log_Printf(LOG_WARN, "[Floppy] Write error. Bad sector offset (%i).",logical_sec); ! 976: flp_sector_counter=0; /* stop the transfer */ ! 977: flp_io_state = FLP_STATE_INTERRUPT; ! 978: send_rw_status(drive); ! 979: return; ! 980: } else { ! 981: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Write sector at offset %i",logical_sec); ! 982: ! 983: fseek(flpdrv[drive].dsk, logical_sec*sec_size, SEEK_SET); ! 984: fwrite(flp_buffer.data, flp_buffer.size, 1, flpdrv[drive].dsk); ! 985: flp_buffer.size = 0; ! 986: flp_buffer.limit = sec_size; ! 987: flpdrv[drive].sector++; ! 988: flp_sector_counter--; ! 989: } ! 990: ! 991: if (flp_sector_counter==0) { ! 992: flp.st[0] = IC_ABNORMAL; /* Strange behavior of NeXT hardware */ ! 993: flp.st[1] |= ST1_EN; ! 994: send_rw_status(drive); ! 995: } ! 996: } ! 997: ! 998: void floppy_format_sector(void) { ! 999: int drive = flp_io_drv; ! 1000: Uint8 c = flp_buffer.data[0]; ! 1001: Uint8 h = flp_buffer.data[1]; ! 1002: Uint8 s = flp_buffer.data[2]; ! 1003: Uint8 bs = flp_buffer.data[3]; ! 1004: ! 1005: if (c!=flpdrv[drive].cyl || h!=flpdrv[drive].head || bs!=flpdrv[drive].blocksize) { ! 1006: Log_Printf(LOG_WARN, "[Floppy] Format error. Bad sector data. Stopping."); ! 1007: flp_io_state = FLP_STATE_INTERRUPT; /* This is a hack */ ! 1008: floppy_format_done(); ! 1009: flp_buffer.size = 0; ! 1010: return; ! 1011: } ! 1012: flpdrv[drive].sector = s; ! 1013: ! 1014: /* Erase data */ ! 1015: Uint32 sec_size = 0x80<<bs; ! 1016: Uint32 logical_sec = physical_to_logical_sector(flpdrv[drive].cyl,flpdrv[drive].head,flpdrv[drive].sector,drive); ! 1017: flp_buffer.size = sec_size; ! 1018: memset(flp_buffer.data, 0, flp_buffer.size); ! 1019: ! 1020: if (flp.st[0]&IC_ABNORMAL) { ! 1021: Log_Printf(LOG_WARN, "[Floppy] Format error. Bad sector offset (%i).",logical_sec); ! 1022: flp_buffer.size = flp_buffer.limit = 0; ! 1023: send_rw_status(drive); ! 1024: } else { ! 1025: Log_Printf(LOG_FLP_CMD_LEVEL, "[Floppy] Format sector at offset %i (%i/%i/%i), blocksize: %i", ! 1026: logical_sec,c,h,s,sec_size); ! 1027: fseek(flpdrv[drive].dsk, logical_sec*sec_size, SEEK_SET); ! 1028: fwrite(flp_buffer.data, flp_buffer.size, 1, flpdrv[drive].dsk); ! 1029: flp_buffer.size = 0; ! 1030: flp_buffer.limit = 4; ! 1031: } ! 1032: } ! 1033: ! 1034: ! 1035: Uint32 old_size; ! 1036: ! 1037: void FLP_IO_Handler(void) { ! 1038: CycInt_AcknowledgeInterrupt(); ! 1039: ! 1040: switch (flp_io_state) { ! 1041: case FLP_STATE_WRITE: ! 1042: if (flp_buffer.size==flp_buffer.limit) { ! 1043: floppy_write_sector(); ! 1044: if (flp_sector_counter==0) { /* done */ ! 1045: flp_io_state = FLP_STATE_INTERRUPT; ! 1046: } ! 1047: } else if (flp_buffer.size<flp_buffer.limit) { /* loop in filling mode */ ! 1048: old_size = flp_buffer.size; ! 1049: dma_esp_read_memory(); ! 1050: if (flp_buffer.size==old_size) { ! 1051: floppy_rw_nodata(); ! 1052: flp_io_state = FLP_STATE_INTERRUPT; ! 1053: break; ! 1054: } ! 1055: } ! 1056: break; ! 1057: ! 1058: case FLP_STATE_READ: ! 1059: if (flp_buffer.size==0 && flp_sector_counter>0) { ! 1060: floppy_read_sector(); ! 1061: } ! 1062: if (flp_buffer.size>0) { /* loop in draining mode */ ! 1063: old_size = flp_buffer.size; ! 1064: dma_esp_write_memory(); ! 1065: if (flp_buffer.size==old_size) { ! 1066: floppy_rw_nodata(); ! 1067: flp_io_state = FLP_STATE_INTERRUPT; ! 1068: break; ! 1069: } ! 1070: } ! 1071: if (flp_buffer.size==0 && flp_sector_counter==0) { /* done */ ! 1072: flp_io_state = FLP_STATE_INTERRUPT; ! 1073: } ! 1074: break; ! 1075: ! 1076: case FLP_STATE_FORMAT: ! 1077: if (flp_buffer.size<flp_buffer.limit) { ! 1078: old_size = flp_buffer.size; ! 1079: dma_esp_read_memory(); ! 1080: if (flp_buffer.size==old_size) { ! 1081: floppy_format_done(); ! 1082: flp_io_state = FLP_STATE_INTERRUPT; ! 1083: break; ! 1084: } ! 1085: } else if (flp_buffer.size==flp_buffer.limit) { ! 1086: floppy_format_sector(); ! 1087: } ! 1088: break; ! 1089: ! 1090: case FLP_STATE_INTERRUPT: ! 1091: floppy_interrupt(); ! 1092: /* fall through */ ! 1093: ! 1094: case FLP_STATE_DONE: ! 1095: return; ! 1096: ! 1097: default: ! 1098: return; ! 1099: } ! 1100: ! 1101: CycInt_AddRelativeInterrupt(2000, INT_CPU_CYCLE, INTERRUPT_FLP_IO); ! 1102: } ! 1103: ! 1104: ! 1105: /* Initialize/Uninitialize floppy disks */ ! 1106: ! 1107: void Floppy_Init(void) { ! 1108: Log_Printf(LOG_WARN, "Loading floppy disks:"); ! 1109: int i; ! 1110: ! 1111: for (i=0; i<FLP_MAX_DRIVES; i++) { ! 1112: flpdrv[i].spinning=false; ! 1113: /* Check if files exist. */ ! 1114: if (ConfigureParams.Floppy.drive[i].bDriveConnected) { ! 1115: flpdrv[i].connected=true; ! 1116: if (ConfigureParams.Floppy.drive[i].bDiskInserted && ! 1117: File_Exists(ConfigureParams.Floppy.drive[i].szImageName)) { ! 1118: Floppy_Insert(i); ! 1119: } else { ! 1120: flpdrv[i].dsk = NULL; ! 1121: flpdrv[i].inserted=false; ! 1122: } ! 1123: } else { ! 1124: flpdrv[i].connected=false; ! 1125: } ! 1126: } ! 1127: ! 1128: floppy_reset(true); ! 1129: } ! 1130: ! 1131: void Floppy_Uninit(void) { ! 1132: if (flpdrv[0].dsk) ! 1133: File_Close(flpdrv[0].dsk); ! 1134: if (flpdrv[1].dsk) { ! 1135: File_Close(flpdrv[1].dsk); ! 1136: } ! 1137: flpdrv[0].dsk = flpdrv[1].dsk = NULL; ! 1138: flpdrv[0].inserted = flpdrv[1].inserted = false; ! 1139: } ! 1140: ! 1141: Uint32 Floppy_CheckSize(int drive) { ! 1142: Uint32 size = File_Length(ConfigureParams.Floppy.drive[drive].szImageName); ! 1143: ! 1144: switch (size) { ! 1145: case SIZE_720K: ! 1146: case SIZE_1440K: ! 1147: case SIZE_2880K: ! 1148: return size; ! 1149: ! 1150: default: ! 1151: Log_Printf(LOG_WARN, "Floppy Disk%i: Invalid size (%i byte)\n",drive,size); ! 1152: return 0; ! 1153: } ! 1154: } ! 1155: ! 1156: int Floppy_Insert(int drive) { ! 1157: Uint32 size; ! 1158: ! 1159: /* Check floppy size. */ ! 1160: size = Floppy_CheckSize(drive); ! 1161: if (size) { ! 1162: flpdrv[drive].floppysize = size; ! 1163: flpdrv[drive].blocksize = 2; /* 512 byte */ ! 1164: } else { ! 1165: flpdrv[drive].dsk = NULL; ! 1166: flpdrv[drive].inserted=false; ! 1167: flpdrv[drive].floppysize = 0; ! 1168: return 1; /* bad size, do not insert */ ! 1169: } ! 1170: ! 1171: if (ConfigureParams.Floppy.drive[drive].bWriteProtected) { ! 1172: flpdrv[drive].dsk = File_Open(ConfigureParams.Floppy.drive[drive].szImageName, "rb"); ! 1173: flpdrv[drive].protected=true; ! 1174: } else { ! 1175: flpdrv[drive].dsk = File_Open(ConfigureParams.Floppy.drive[drive].szImageName, "rb+"); ! 1176: flpdrv[drive].protected=false; ! 1177: } ! 1178: ! 1179: flpdrv[drive].inserted=true; ! 1180: flpdrv[drive].spinning=false; ! 1181: ! 1182: Log_Printf(LOG_WARN, "Floppy Disk%i: %s, %iK\n",drive, ! 1183: ConfigureParams.Floppy.drive[drive].szImageName,flpdrv[drive].floppysize/1024); ! 1184: ! 1185: Statusbar_AddMessage("Inserting floppy disk.", 0); ! 1186: ! 1187: return 0; ! 1188: } ! 1189: ! 1190: void Floppy_Eject(int drive) { ! 1191: if (drive<0) { /* Called from emulator, else called from GUI */ ! 1192: drive=flp.sel; ! 1193: ! 1194: Statusbar_AddMessage("Ejecting floppy disk.", 0); ! 1195: } ! 1196: ! 1197: Log_Printf(LOG_WARN, "Unloading floppy disk %i",drive); ! 1198: Log_Printf(LOG_WARN, "Floppy disk %i: Eject",drive); ! 1199: ! 1200: File_Close(flpdrv[drive].dsk); ! 1201: flpdrv[drive].floppysize = 0; ! 1202: flpdrv[drive].blocksize = 0; ! 1203: flpdrv[drive].dsk=NULL; ! 1204: flpdrv[drive].inserted=false; ! 1205: flpdrv[drive].spinning=false; ! 1206: ! 1207: ConfigureParams.Floppy.drive[drive].bDiskInserted=false; ! 1208: ConfigureParams.Floppy.drive[drive].szImageName[0]='\0'; ! 1209: } ! 1210: ! 1211: void Floppy_Reset(void) { ! 1212: Floppy_Uninit(); ! 1213: Floppy_Init(); ! 1214: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.