diff options
| author | Harley Travis <harleytravis123@outlook.com> | 2026-05-23 23:55:17 -0500 |
|---|---|---|
| committer | Harley Travis <harleytravis123@outlook.com> | 2026-05-23 23:55:17 -0500 |
| commit | ba700f0759a59551159e90aff2bd6d547c27179b (patch) | |
| tree | 1c5e98679d0f76be4466b72c1142f3304e3a97d5 /NewFloppy.HC | |
| parent | 04d039d43164f48f5266d32e783d11f166b6161c (diff) | |
TOSFloppy_2025-04-20T2103-0500.zip2025-04-20
This was the second and final Discord release of the TempleOS floppy
disk controller driver, released April 20, 2025.
This release saw mainly structure changes, plus the addition of a
license file (the code, at this point, is licensed under Do What The
Fuck You Want To Public License, version 2.0).
Diffstat (limited to 'NewFloppy.HC')
| -rw-r--r-- | NewFloppy.HC | 477 |
1 files changed, 0 insertions, 477 deletions
diff --git a/NewFloppy.HC b/NewFloppy.HC deleted file mode 100644 index 9e67467..0000000 --- a/NewFloppy.HC +++ /dev/null @@ -1,477 +0,0 @@ -/* - New, (hopefully) Less Messy Floppy Driver - Copyright (C) 2025 Yoshi128k. - Licensed under version 2 of the Do What The Fuck You Want To Public License - See COPYING for details. -*/ - -Bool FDCIrq = FALSE; - -U0 FDCDMAInit(U16 len) -{ - U64 /*buf_lo, buf_hi, page,*/ cnt_lo, cnt_hi; - -// buf_lo = &FDC_DMA & 0xFF; -// buf_hi = &FDC_DMA >> 8; -// page = &FDC_DMA >> 16; - cnt_lo = (len - 1) & 0xFF; - cnt_hi = (len - 1) >> 8; - - OutU8(0x0A, 6); // mask ch 0 and 2 - Sleep(1); - OutU8(0x0C, -1); // reset flip flop - Sleep(1); - OutU8(0x04, 0x75); // buf low byte - Sleep(1); - OutU8(0x04, 0x9F); // buf high byte - Sleep(1); - OutU8(0x0C, -1); // reset flip flop again - Sleep(1); - OutU8(0x05, cnt_lo); // cntr low byte - Sleep(1); - OutU8(0x05, cnt_hi); // cntr high byte - Sleep(1); - OutU8(0x81, 0); // page - Sleep(1); - OutU8(0x0A, 2); // unmask ch 0 and 2 - Sleep(1); -} - -U0 FDCDMAPrepWrite() -{ - OutU8(0x0A, 6); // mask ch 0 and 2 - Sleep(1); - OutU8(0x0B, 0x5A); // single xfer, addr inc, auto init, write, ch 2 - Sleep(1); - OutU8(0x0A, 2); // unmask ch 0 and 2 - Sleep(1); -} - -U0 FDCDMAPrepRead() -{ - OutU8(0x0A, 6); // mask ch 0 and 2 - Sleep(1); - OutU8(0x0B, 0x56); // single xfer, addr inc, auto init, read, ch 2 - Sleep(1); - OutU8(0x0A, 2); // unmask ch 0 and 2 - Sleep(1); -} - -interrupt U0 FDCIrqHandler() { - OutU8(0x20, 0x20); // EOI - FDCIrq = TRUE; -} - -U16 fdc_base = 0x03F0; - -static U8 *fd_types[8] = { - "none", - "360kB 5.25\"", - "1.2MB 5.25\"", - "720kB 3.5\"", - - "1.44MB 3.5\"", - "2.88MB 3.5\"", - "unknown type", - "unknown type" -}; - -U0 CMOSGetFloppyDrives() -{ - OutU8(0x70, 0x10); - Sleep(1); - - U64 drives = InU8(0x71); - - AdamLog("Floppy Drive 0: %s\n", fd_types[drives >> 4]); - AdamLog("Floppy Drive 1: %s\n", fd_types[drives & 0xF]); -} - -U0 FDCSendCmd(U16 base, U8 cmd) -{ - // Send a command to the floppy controller - - // 60 sec timeout - U64 i; - for (i = 0; i < 600; i++) { - Sleep(10); - if (0x80 & InU8(base + FDC_MSR_DSR)) { - OutU8(base + FDC_DATA, cmd); - Sleep(1); - return; - } - } - AdamErr("FDC Command TimeOut"); -} - -U8 FDCReadData(U16 base) -{ - // Read data from the floppy controller - - // 60 sec timeout - U64 i; - for (i=0;i<600;i++) { - Sleep(10); - if (0x80 & InU8(base + FDC_MSR_DSR)) { - return InU8(base + FDC_DATA); - } - } - AdamErr("FDC Read TimeOut"); -} - -U0 FDCCheckInt(U16 base, U8 *st0, U8 *cyl) -{ - FDCSendCmd(base, FDC_SENSE_INTR); - - *st0 = FDCReadData(base); - *cyl = FDCReadData(base); -} - -I16 fdc_mtr_ticks = 0; -U8 fdc_mtr_state = FDC_MOTOR_OFF; - -U0 FDCMotorOff(U16 base) -{ - OutU8(base + FDC_DOR, 0x0C); - fdc_mtr_state = FDC_MOTOR_OFF; -} - -U0 FDCMotorPwrOffTimer() -{ - // You're supposed to run this function as a separate CTask. It will exit when the motor - // exits the "wait" state (either because it has turned off or because something needs it to be on). - // The driver only spawns this when the motor is moved from "on" to "wait". - while (fdc_mtr_state == FDC_MOTOR_WAIT) { - // Sanity check for if something wants the motor on at the last second - if (fdc_mtr_state == FDC_MOTOR_ON) break; - - Sleep(500); - - fdc_mtr_ticks -= 50; - if (fdc_mtr_ticks <= 0) { - FDCMotorOff(fdc_base); - } - Yield; // Give control back to the scheduler - } -} - -U0 FDCMotorCtrl(U16 base, Bool onoff) -{ - U64 prev_mtr_state; - if (onoff) { - if (!fdc_mtr_state) { - // Turn on motor - OutU8(base + FDC_DOR, 0x1C); - Sleep(500); // Wait 500 ms to allow drive to spin up - } - fdc_mtr_state = FDC_MOTOR_ON; - } else { - prev_mtr_state = fdc_mtr_state; - if (fdc_mtr_state == FDC_MOTOR_WAIT) { - AdamLog("FDC: Motor PowerOff Already Pending\n"); - } - fdc_mtr_ticks = 300; // 3 sec timeout before motor turns off - fdc_mtr_state = FDC_MOTOR_WAIT; - // Only spawn the timer task of the motor is currently on; infinitely-looping tasks peg the CPU - if (prev_mtr_state != FDC_MOTOR_WAIT) Spawn(&FDCMotorPwrOffTimer,,"FDCMotorPwrOffTimer"); - } -} - -I8 FDCRecalibrate(U16 base) -{ - FDCIrq = FALSE; - - U64 i; - U8 st0, cyl; - - FDCMotorCtrl(base, FDC_MOTOR_ON); - - for (i=0;i<10;i++) { - FDCSendCmd(base, FDC_RECALIBRATE); - FDCSendCmd(base, 0); - - // Wait for an interrupt, then get the status - while (!FDCIrq) Yield; - FDCCheckInt(base, &st0, &cyl); - AdamLog("ST0: %d Cyl: %d\n",st0,cyl); - - if (st0 & 0xC0) { - static U8 * status[4] = {0, "error", "invalid", "drive"}; - AdamLog("Calibration Status: %s\n", status[st0 >> 6]); - } - - if (!cyl) { - FDCMotorCtrl(base, FDC_MOTOR_OFF); - return 0; - } - } - - AdamErr("FDC ReCalibrate TimeOut"); - FDCMotorCtrl(base, FDC_MOTOR_OFF); - return -1; -} - -I8 FDCReset(U16 base) -{ - FDCIrq = FALSE; - - OutU8(base + FDC_DOR, 0x00); - Sleep(1); - OutU8(base + FDC_DOR, 0x0C); - Sleep(1); - - while (!FDCIrq) Yield; - - // Ignore this - U64 i, lck; - U8 st0, cyl; - for (i=0;i<4;i++) { - FDCCheckInt(base, &st0, &cyl); - } - - // Set xfer rate to 500kbps - OutU8(base + FDC_CCR_DIR, 0x00); - Sleep(1); - - // Set the mechanical params and disable DMA (Terry didn't use it) - FDCSendCmd(base, FDC_SPECIFY); - FDCSendCmd(base, 0b10000000); // SRT = 8 (8 ms), HUT = 0 (256 ms) - FDCSendCmd(base, 0b00011110); // HLT = 15 (30 ms), NDMA = 0 (DMA enabled) - - // Configure the FIFO - FDCSendCmd(base, FDC_CONFIGURE); - FDCSendCmd(base, 0x00); // 1st param is a 0 - FDCSendCmd(base, 0b01011011); // 2nd param: Implied seek on, FIFO on, Drive polling disabled, threshold = 12 - FDCSendCmd(base, 0x00); // 3rd param: write precomp = 0 - - // Lock the configuration - FDCSendCmd(base, 0x94); - lck = FDCReadData(base); // Result: lock status - - // contingency - if (FDCRecalibrate(base)) return -1; - - return 0; -} - -I8 FDCSeek(U16 base, U8 cyli, U8 head) -{ - U64 i; - U8 st0, cyl; - FDCIrq = FALSE; - - FDCMotorCtrl(base, FDC_MOTOR_ON); - - for (i=0;i<10;i++) { - // Attempt to move to given cyl - // 1: X X X X X HD D1 D0 - // 2: Cyl No - FDCSendCmd(base, FDC_SEEK); - FDCSendCmd(base, head<<2); - FDCSendCmd(base, cyli); - - while (!FDCIrq) Yield; - FDCCheckInt(base, &st0, &cyl); - AdamLog("ST0: %d Cyl: %d\n",st0,cyl); - - if (st0 & 0xC0) { - static U8 * status[4] = {0, "error", "invalid", "drive"}; - AdamLog("Seek Status: %s\n", status[st0 >> 6]); - } - - if (cyl == cyli) { - FDCMotorCtrl(base, FDC_MOTOR_OFF); - return 0; - } - } - - AdamErr("FDC Seek TimeOut"); - FDCMotorCtrl(base, FDC_MOTOR_OFF); - return -1; -} - -U0 FDCRead(U16 base, U8 cyl, U8 head, U8 sect, U8 trklen) -{ - // Read data from disk (single-track) - static U8 flags; - flags = 0x40; // Multi-track off, MFM modulation - static U64 cmd; - cmd = FDC_READ_DATA | flags; - FDCIrq = FALSE; - - U64 st0, st1, st2, rcyl, rhd, rsect, rsectsize; - - FDCMotorCtrl(base, FDC_MOTOR_ON); - - AdamLog("Cmd: %d\nParams: %d %d %d %d %d %d %d %d\n",cmd,head<<2,cyl,head,sect,2,trklen,0x1B,0xFF); - - // Prepare the DMA controller - AdamLog("Preparing DMA\n"); - FDCDMAInit(512*(trklen - sect + 1)); - FDCDMAPrepRead(); - - FDCSendCmd(base, cmd); - FDCSendCmd(base, head << 2); // Drive 0, specified head - FDCSendCmd(base, cyl); - FDCSendCmd(base, head); - FDCSendCmd(base, sect); - FDCSendCmd(base, 2); // Sector size = 2 = 512 bytes - FDCSendCmd(base, trklen); // Track Length/Max Sector No. - FDCSendCmd(base, 0x1B); // GAP3 Length = 27 (3.5") - FDCSendCmd(base, 0xFF); // Data Length (irrelevant) - - // Wait for xfer to complete - while (!FDCIrq) Yield; - - st0 = FDCReadData(base); - st1 = FDCReadData(base); - st2 = FDCReadData(base); - rcyl = FDCReadData(base); - rhd = FDCReadData(base); - rsect = FDCReadData(base); - rsectsize = FDCReadData(base); - - AdamLog("Read Results:\nST0: %d\nST1: %d\nST2: %d\nCyl: %d\nHead: %d\nSect: %d\nSect Size: %d\n",st0,st1,st2,rcyl,rhd,rsect,rsectsize); - - FDCMotorCtrl(base, FDC_MOTOR_OFF); -} - - -U0 FDCReadMulti(U16 base, U8 cyl, U8 head, U8 sect, U8 trklen) -{ - // Read data from disk (multi-track) - static U8 flags; - flags = 0xC0; // Multi-track on, MFM modulation - static U64 cmd; - cmd = FDC_READ_DATA | flags; - FDCIrq = FALSE; - - U64 st0, st1, st2, rcyl, rhd, rsect, rsectsize; - - FDCMotorCtrl(base, FDC_MOTOR_ON); - - AdamLog("Cmd: %d\nParams: %d %d %d %d %d %d %d %d\n",cmd,head<<2,cyl,head,sect,2,trklen,0x1B,0xFF); - - // Prepare the DMA controller - AdamLog("Preparing DMA\n"); - FDCDMAInit(512*(trklen - sect + 1)*2); - FDCDMAPrepRead(); - - FDCSendCmd(base, cmd); - FDCSendCmd(base, head << 2); // Drive 0, specified head - FDCSendCmd(base, cyl); - FDCSendCmd(base, head); - FDCSendCmd(base, sect); - FDCSendCmd(base, 2); // Sector size = 2 = 512 bytes - FDCSendCmd(base, trklen); // Track Length/Max Sector No. - FDCSendCmd(base, 0x1B); // GAP3 Length = 27 (3.5") - FDCSendCmd(base, 0xFF); // Data Length (irrelevant) - - // Wait for the xfer to complete - while (!FDCIrq) Yield; - - st0 = FDCReadData(base); - st1 = FDCReadData(base); - st2 = FDCReadData(base); - rcyl = FDCReadData(base); - rhd = FDCReadData(base); - rsect = FDCReadData(base); - rsectsize = FDCReadData(base); - - AdamLog("Read Results:\nST0: %d\nST1: %d\nST2: %d\nCyl: %d\nHead: %d\nSect: %d\nSect Size: %d\n",st0,st1,st2,rcyl,rhd,rsect,rsectsize); - - FDCMotorCtrl(base, FDC_MOTOR_OFF); -} - -U0 FDCWrite(U16 base, U8 cyl, U8 head, U8 sect, U8 trklen) -{ - // Write data to disk (single-track) - static U8 flags; - flags = 0x40; // Multi-track off, MFM modulation - static U64 cmd; - cmd = FDC_WRITE_DATA | flags; - FDCIrq = FALSE; - - U64 st0, st1, st2, rcyl, rhd, rsect, rsectsize; - - FDCMotorCtrl(base, FDC_MOTOR_ON); - - AdamLog("Cmd: %d\nParams: %d %d %d %d %d %d %d %d\n",cmd,head<<2,cyl,head,sect,2,trklen,0x1B,0xFF); - - // Prepare the DMA controller - AdamLog("Preparing DMA\n"); - FDCDMAInit(512*(trklen - sect + 1)); - FDCDMAPrepWrite(); - - FDCSendCmd(base, cmd); - FDCSendCmd(base, head << 2); // Drive 0, specified head - FDCSendCmd(base, cyl); - FDCSendCmd(base, head); - FDCSendCmd(base, sect); - FDCSendCmd(base, 2); // Sector size = 2 = 512 bytes - FDCSendCmd(base, trklen); // Track Length/Max Sector No. - FDCSendCmd(base, 0x1B); // GAP3 Length = 27 (3.5") - FDCSendCmd(base, 0xFF); // Data Length (irrelevant) - - // Wait for xfer to complete - while (!FDCIrq) Yield; - - st0 = FDCReadData(base); - st1 = FDCReadData(base); - st2 = FDCReadData(base); - rcyl = FDCReadData(base); - rhd = FDCReadData(base); - rsect = FDCReadData(base); - rsectsize = FDCReadData(base); - - AdamLog("Read Results:\nST0: %d\nST1: %d\nST2: %d\nCyl: %d\nHead: %d\nSect: %d\nSect Size: %d\n",st0,st1,st2,rcyl,rhd,rsect,rsectsize); - - FDCMotorCtrl(base, FDC_MOTOR_OFF); -} - - -U0 FDCWriteMulti(U16 base, U8 cyl, U8 head, U8 sect, U8 trklen) -{ - // Write data to disk (multi-track) - static U8 flags; - flags = 0xC0; // Multi-track on, MFM modulation - static U64 cmd; - cmd = FDC_WRITE_DATA | flags; - FDCIrq = FALSE; - - U64 st0, st1, st2, rcyl, rhd, rsect, rsectsize; - - FDCMotorCtrl(base, FDC_MOTOR_ON); - - AdamLog("Cmd: %d\nParams: %d %d %d %d %d %d %d %d\n",cmd,head<<2,cyl,head,sect,2,trklen,0x1B,0xFF); - - // Prepare the DMA controller - AdamLog("Preparing DMA\n"); - FDCDMAInit(512*(trklen - sect + 1)*2); - FDCDMAPrepRead(); - - FDCSendCmd(base, cmd); - FDCSendCmd(base, head << 2); // Drive 0, specified head - FDCSendCmd(base, cyl); - FDCSendCmd(base, head); - FDCSendCmd(base, sect); - FDCSendCmd(base, 2); // Sector size = 2 = 512 bytes - FDCSendCmd(base, trklen); // Track Length/Max Sector No. - FDCSendCmd(base, 0x1B); // GAP3 Length = 27 (3.5") - FDCSendCmd(base, 0xFF); // Data Length (irrelevant) - - // Wait for the xfer to complete - while (!FDCIrq) Yield; - - st0 = FDCReadData(base); - st1 = FDCReadData(base); - st2 = FDCReadData(base); - rcyl = FDCReadData(base); - rhd = FDCReadData(base); - rsect = FDCReadData(base); - rsectsize = FDCReadData(base); - - AdamLog("Read Results:\nST0: %d\nST1: %d\nST2: %d\nCyl: %d\nHead: %d\nSect: %d\nSect Size: %d\n",st0,st1,st2,rcyl,rhd,rsect,rsectsize); - - FDCMotorCtrl(base, FDC_MOTOR_OFF); -}
\ No newline at end of file |
