Annotation of previous/src/floppy.c, revision 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.