Annotation of previous/src/floppy.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.