diff options
| author | Harley Travis <harleytravis123@outlook.com> | 2026-05-27 18:04:13 -0500 |
|---|---|---|
| committer | Harley Travis <harleytravis123@outlook.com> | 2026-05-27 18:04:13 -0500 |
| commit | 32673d5872a2c77c2cc70a14a1e50cd440bc0180 (patch) | |
| tree | 568fb469e295bbb69d166765d4712c21f77568fc /KFloppy.HC | |
| parent | b223d23c0165fccf014a4e8c0ed1a21425be7100 (diff) | |
| download | templeos-floppy-driver-32673d5872a2c77c2cc70a14a1e50cd440bc0180.tar.gz | |
Refactor source code and create an "installer"
I have moved some source files into subdirectories for ease of
installation. I have also added an installer script to automatically
place driver files into their respective system directories.
Diffstat (limited to 'KFloppy.HC')
| -rw-r--r-- | KFloppy.HC | 482 |
1 files changed, 0 insertions, 482 deletions
diff --git a/KFloppy.HC b/KFloppy.HC deleted file mode 100644 index 16b6bd3..0000000 --- a/KFloppy.HC +++ /dev/null @@ -1,482 +0,0 @@ -/* - New, (hopefully) Less Messy Floppy Driver - Copyright (C) 2025-2026 Harley Travis <yoshi128k@gmail.com>. - This software (including source code) is licensed under the BSD Zero Clause - License. See the Copying.TXT file 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, buf_lo); // buf low byte - Sleep(1); - OutU8(0x04, buf_hi); // 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 - // 2nd param: - // Implied seek on, FIFO on, Drive polling disabled, threshold = 12 - FDCSendCmd(base, 0b01011011); - 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); - 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 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); -} |
