From cfb28351f1ec11fabb7ac049ab5dfc124aebc382 Mon Sep 17 00:00:00 2001 From: Tyler McGurrin Date: Wed, 4 Jun 2025 08:31:51 -0400 Subject: [PATCH] Floppy Disk Stuff is hard... also screw bitwise funtions --- src/kernel/dri/disk/floppy.c | 232 ++++++++++++++++++++++++++++++++--- src/kernel/dri/disk/floppy.h | 115 +++++++++++++---- src/libs/version.h | 2 +- 3 files changed, 311 insertions(+), 38 deletions(-) diff --git a/src/kernel/dri/disk/floppy.c b/src/kernel/dri/disk/floppy.c index 964160b..313ca42 100644 --- a/src/kernel/dri/disk/floppy.c +++ b/src/kernel/dri/disk/floppy.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -15,6 +16,8 @@ extern uint16_t DEBUG_COM_PORT; volatile int FloppyIRQRecived = 0; +int _CurrentDrive; + // Honestly dont care that most of this is hard-coded, im just done with this shit void Floppy_Handler() @@ -61,14 +64,21 @@ void Floppy_DMA_Write() outb(0x0a, 0x02); //unmask dma channel 2 } -void Floppy_Write_DOR(uint8_t command ) +void Floppy_Write_DOR(uint8_t value) { // Write the DOR - outb(FLOPPY_DOR, command); - Serial_Printf(DEBUG_COM_PORT, "Wrote %u To Floppy DOR.\n", command); + outb(FLOPPY_DOR, value); + Serial_Printf(DEBUG_COM_PORT, "FLOPPY:> Wrote %u To DOR.\n", value); } -uint8_t Floppy_Read_Status() +void Floppy_Write_CCR(uint8_t value) +{ + // write the configuation control + outb (FLOPPY_CTRL, value); + Serial_Printf(DEBUG_COM_PORT, "FLOPPY:> Wrote %u To CCR.\n", value); +} + +uint8_t Floppy_Read_Status() { // Returns MSR (simple innit? return inb(FLOPPY_MSR); @@ -83,22 +93,216 @@ int Floppy_Check_Busy() return 0; } -void Floppy_Send_Command (uint8_t command) +void Floppy_Send_Command(uint8_t command) { // Wait for DOR then send command + Serial_Printf(DEBUG_COM_PORT, "FLOPPY:> Sending Command %u To Drive\n", command); for(int i = 0; i < 500; i++) if(Floppy_Read_Status() & FLOPPY_MSR_MASK_DATAREG) return outb(FLOPPY_FIFO, command); } -// LBA2CHS Lives Forever! Might move it later on tho -void Floppy_LBA2CHS(FLOPPY_DISK* disk, uint32_t lba, uint16_t* cylinderOut, uint16_t* sectorOut, uint16_t* headOut) { - // sector = (LBA % sectors per track + 1) - *sectorOut = lba % disk->sectors +1; +uint8_t Floppy_Read_Data() +{ + // same as above function but returns data register for reading + for(int i = 0; i < 500; i++) + if( Floppy_Read_Status() & FLOPPY_MSR_MASK_DATAREG) + return inb(FLOPPY_FIFO); +} - // cylinder = (LBA / sects per track / heads) - *cylinderOut = (lba / disk->sectors) / disk->heads; +// Complicated ass driver. +// I mean... could be worse? +void Floppy_Read_Sector_CHS(uint8_t head, uint8_t track, uint8_t sector) +{ + uint32_t st0, cyl; + + // set the DMA for read transfer + Floppy_DMA_Read(); + + // read in a sector + Floppy_Send_Command(FLOPPY_CMD_READ_SECT | FLOPPY_CMD_EXT_MULTITRACK | FLOPPY_CMD_EXT_SKIP | FLOPPY_CMD_EXT_DENSITY); + Floppy_Send_Command(head << 2 | _CurrentDrive); + Floppy_Send_Command(track); + Floppy_Send_Command(head); + Floppy_Send_Command(sector); + Floppy_Send_Command(FLOPPY_SECTOR_DTL_512); + Floppy_Send_Command((( sector + 1 ) >= FLOPPY_SECTORS_PER_TRACK ) ? FLOPPY_SECTORS_PER_TRACK : sector + 1); + Floppy_Send_Command(FLOPPY_GAP3_LENGTH_3_5); + Floppy_Send_Command(0xff); + + // wait for irq + Floppy_IRQ_Wait(); + + // read status info + for (int j=0; j<7; j++) Floppy_Read_Data(); + + // let Floppy Controller know we handled interrupt + Floppy_Check_INT(&st0,&cyl); +} - // head = (LBA / sects per track % heads) - *headOut = (lba / disk->sectors) % disk->heads; -} \ No newline at end of file +void Floppy_Drive_Data(uint32_t stepr, uint32_t loadt, uint32_t unloadt, bool dma) +{ + uint32_t data = 0; + + Floppy_Send_Command(FLOPPY_CMD_SPECIFY); + + data = ( (stepr & 0xf) << 4) | (unloadt & 0xf); + Floppy_Send_Command(data); + + data = (loadt) << 1 | (dma==true) ? 1 : 0; + Floppy_Send_Command(data); +} + +int Floppy_Calibrate(uint32_t drive) +{ + uint32_t st0, cyl; + + if (drive >= 4) + return -2; + + // turn on the motor + Floppy_Motor_Control(true); + + for (int i = 0; i < 10; i++) { + + // send command + Floppy_Send_Command(FLOPPY_CMD_CALIBRATE); + Floppy_Send_Command(drive); + Floppy_IRQ_Wait(); + Floppy_Check_INT(&st0, &cyl); + + // did we fine cylinder 0? if so, we are done + if (!cyl) { + + Floppy_Motor_Control(false); + return 0; + } + } + + Floppy_Motor_Control(false); + return -1; +} + +void Floppy_Check_INT(uint32_t* st0, uint32_t* cyl1) +{ + // Checks Drive Info Post-Interupt + Floppy_Send_Command(FLOPPY_CMD_CHECK_INT); + + *st0 = Floppy_Read_Data(); + *cyl1 = Floppy_Read_Data(); +} + +int Floppy_Seek(uint32_t cyl, uint32_t head) +{ + uint32_t st0, cyl0; + + if (_CurrentDrive >= 4) + return -1; + + for (int i = 0; i < 10; i++ ) { + + // send the command + Floppy_Send_Command(FLOPPY_CMD_SEEK); + Floppy_Send_Command((head) << 2 | _CurrentDrive); + Floppy_Send_Command(cyl); + + // wait for IRQ + Floppy_IRQ_Wait(); + Floppy_Check_INT(&st0,&cyl0); + + // found the cylinder? + if ( cyl0 == cyl) + return 0; + } + + return -1; +} + +void Floppy_Disable_Controller() +{ + Floppy_Write_DOR(0); +} + +void Floppy_Enable_Controller() +{ + Floppy_Write_DOR(FLOPPY_DOR_MASK_RESET | FLOPPY_DOR_MASK_DMA); +} + +void Floppy_Reset() +{ + uint32_t st0, cyl; + + // reset the controller + Floppy_Disable_Controller(); + Floppy_Enable_Controller(); + Floppy_IRQ_Wait(); + + // send CHECK_INT/SENSE INTERRUPT command to all drives + for (int i=0; i<4; i++) + Floppy_Check_INT(&st0,&cyl); + + // transfer speed 500kb/s + Floppy_Write_CCR(0); + + // pass mechanical drive info. steprate=3ms, unload time=240ms, load time=16ms + Floppy_Drive_Data(3,16,240,true); + + // calibrate the disk + Floppy_Calibrate( _CurrentDrive ); +} + +void Floppy_Init() +{ + // initialize the DMA + Floppy_Init_DMA(); + + // reset the fdc + Floppy_Reset(); + + // set drive information + Floppy_Drive_Data(13, 1, 0xf, true); +} + +void Floppy_LBA2CHS(int lba,int *head,int *track,int *sector) +{ + *head = ( lba % ( FLOPPY_SECTORS_PER_TRACK * 2 ) ) / ( FLOPPY_SECTORS_PER_TRACK ); + *track = lba / ( FLOPPY_SECTORS_PER_TRACK * 2 ); + *sector = lba % FLOPPY_SECTORS_PER_TRACK + 1; +} + +uint8_t* Floppy_Read_Sector(int sectorLBA) +{ + if (_CurrentDrive >= 4) + return 0; + + // convert LBA sector to CHS + int head=0, track=0, sector=1; + Floppy_LBA2CHS(sectorLBA, &head, &track, §or); + + // turn motor on and seek to track + Floppy_Motor_Control(true); + if (Floppy_Seek(track, head) != 0) + return 0; + + // read sector and turn motor off + Floppy_Read_Sector_CHS(head, track, sector); + Floppy_Motor_Control(false); + + // this is a bit hackish, but ofc i dont care. (also still need to implement DMA lolololololol) + // return (uint8_t*) DMA_BUFFER; +} + +void Floppy_Motor_Control(bool enable) +{ + if(enable == true) { + outb (FLOPPY_DOR, FLOPPY_DOR_MASK_DRIVE0_MOTOR | FLOPPY_DOR_MASK_RESET); + Serial_Printf(DEBUG_COM_PORT, "Starting FDD Motor."); + int i; + while(i >= 500) i++; + } + else { + outb (FLOPPY_DOR, FLOPPY_DOR_MASK_DRIVE0_MOTOR | FLOPPY_DOR_MASK_RESET); + Serial_Printf(DEBUG_COM_PORT, "Stopping FDD Motor."); + } + +} diff --git a/src/kernel/dri/disk/floppy.h b/src/kernel/dri/disk/floppy.h index 4bfc3e2..077ed2c 100644 --- a/src/kernel/dri/disk/floppy.h +++ b/src/kernel/dri/disk/floppy.h @@ -6,6 +6,9 @@ #pragma once #include +#include + +#define FLOPPY_SECTORS_PER_TRACK 18 // Yes this makes it ONLY work with 3.5 inch drives, honestly i dont give a fuck typedef struct { uint8_t id; @@ -16,41 +19,107 @@ typedef struct { void Floppy_Handler(); void Floppy_Drive_Init(uint8_t drive); - +void Floppy_IRQ_Wait(); +void Floppy_Init_DMA(); +void Floppy_DMA_Read(); +void Floppy_DMA_Write(); +void Floppy_Write_DOR(uint8_t value); +void Floppy_Write_CCR(uint8_t value); +void Floppy_Send_Command(uint8_t command); +void Floppy_LBA2CHS(int lba,int *head,int *track,int *sector); +void Floppy_Read_Sector_CHS(uint8_t head, uint8_t track, uint8_t sector); +void Floppy_Drive_Data(uint32_t stepr, uint32_t loadt, uint32_t unloadt, bool dma); +void Floppy_Check_INT(uint32_t* st0, uint32_t* cyl1); +void Floppy_Disable_Controller(); +void Floppy_Enable_Controller(); +void Floppy_Reset(); +void Floppy_Init(); +void Floppy_Motor_Control(bool enable); +uint8_t Floppy_Read_Status(); +uint8_t Floppy_Read_Data(); +uint8_t* Floppy_Read_Sector(int sectorLBA); +int Floppy_Check_Busy(); +int Floppy_Calibrate(uint32_t drive); +int Floppy_Seek(uint32_t cyl, uint32_t head); /* When i Said i was Rewriting this POS i meant it */ enum FLOPPY_IO { - FLOPPY_DOR = 0x3f2, - FLOPPY_MSR = 0x3f4, - FLOPPY_FIFO = 0x3f5, //data register - FLOPPY_CTRL = 0x3f7 + FLOPPY_DOR = 0x3f2, + FLOPPY_MSR = 0x3f4, + FLOPPY_FIFO = 0x3f5, //data register + FLOPPY_CTRL = 0x3f7 }; enum FLOPPY_DOR_MASK { - FLOPPY_DOR_MASK_DRIVE0 = 0, //00000000 = here for completeness sake - FLOPPY_DOR_MASK_DRIVE1 = 1, //00000001 - FLOPPY_DOR_MASK_DRIVE2 = 2, //00000010 - FLOPPY_DOR_MASK_DRIVE3 = 3, //00000011 - FLOPPY_DOR_MASK_RESET = 4, //00000100 - FLOPPY_DOR_MASK_DMA = 8, //00001000 - FLOPPY_DOR_MASK_DRIVE0_MOTOR = 16, //00010000 - FLOPPY_DOR_MASK_DRIVE1_MOTOR = 32, //00100000 - FLOPPY_DOR_MASK_DRIVE2_MOTOR = 64, //01000000 - FLOPPY_DOR_MASK_DRIVE3_MOTOR = 128 //10000000 + FLOPPY_DOR_MASK_DRIVE0 = 0, //00000000 + FLOPPY_DOR_MASK_DRIVE1 = 1, //00000001 + FLOPPY_DOR_MASK_DRIVE2 = 2, //00000010 + FLOPPY_DOR_MASK_DRIVE3 = 3, //00000011 + FLOPPY_DOR_MASK_RESET = 4, //00000100 + FLOPPY_DOR_MASK_DMA = 8, //00001000 + FLOPPY_DOR_MASK_DRIVE0_MOTOR = 16, //00010000 + FLOPPY_DOR_MASK_DRIVE1_MOTOR = 32, //00100000 + FLOPPY_DOR_MASK_DRIVE2_MOTOR = 64, //01000000 + FLOPPY_DOR_MASK_DRIVE3_MOTOR = 128 //10000000 }; enum FLOPPY_MSR_MASK { - FLOPPY_MSR_MASK_DRIVE1_POS_MODE = 1, //00000001 - FLOPPY_MSR_MASK_DRIVE2_POS_MODE = 2, //00000010 - FLOPPY_MSR_MASK_DRIVE3_POS_MODE = 4, //00000100 - FLOPPY_MSR_MASK_DRIVE4_POS_MODE = 8, //00001000 - FLOPPY_MSR_MASK_BUSY = 16, //00010000 - FLOPPY_MSR_MASK_DMA = 32, //00100000 - FLOPPY_MSR_MASK_DATAIO = 64, //01000000 - FLOPPY_MSR_MASK_DATAREG = 128 //10000000 + FLOPPY_MSR_MASK_DRIVE1_POS_MODE = 1, //00000001 + FLOPPY_MSR_MASK_DRIVE2_POS_MODE = 2, //00000010 + FLOPPY_MSR_MASK_DRIVE3_POS_MODE = 4, //00000100 + FLOPPY_MSR_MASK_DRIVE4_POS_MODE = 8, //00001000 + FLOPPY_MSR_MASK_BUSY = 16, //00010000 + FLOPPY_MSR_MASK_DMA = 32, //00100000 + FLOPPY_MSR_MASK_DATAIO = 64, //01000000 + FLOPPY_MSR_MASK_DATAREG = 128 //10000000 }; +// Yes i know i know 0b numbers are nonstandard (fuck off) +enum FLOPPY_CCR_SPEEDS { + + FLOPPY_CCR_SPEED_500K = 0b00, + FLOPPY_CCR_SPEED_250K = 0b10, + FLOPPY_CCR_SPEED_300K = 0b01, + FLOPPY_CCR_SPEED_1M = 0b11 +}; + +enum FLOPPY_CMD { + + FLOPPY_CMD_READ_TRACK = 2, + FLOPPY_CMD_SPECIFY = 3, + FLOPPY_CMD_CHECK_STAT = 4, + FLOPPY_CMD_WRITE_SECT = 5, + FLOPPY_CMD_READ_SECT = 6, + FLOPPY_CMD_CALIBRATE = 7, + FLOPPY_CMD_CHECK_INT = 8, + FLOPPY_CMD_WRITE_DEL_S = 9, + FLOPPY_CMD_READ_ID_S = 0xa, + FLOPPY_CMD_READ_DEL_S = 0xc, + FLOPPY_CMD_FORMAT_TRACK = 0xd, + FLOPPY_CMD_SEEK = 0xf +}; + +enum FLOPPY_CMD_EXT { + + FLOPPY_CMD_EXT_SKIP = 0x20, //00100000 + FLOPPY_CMD_EXT_DENSITY = 0x40, //01000000 + FLOPPY_CMD_EXT_MULTITRACK = 0x80 //10000000 +}; + +enum FLOPPY_GAP3_LENGTH { + + FLOPPY_GAP3_LENGTH_STD = 42, + FLOPPY_GAP3_LENGTH_5_14 = 32, + FLOPPY_GAP3_LENGTH_3_5 = 27 +}; + +enum FLOPPY_SECTOR_DTL { + FLOPPY_SECTOR_DTL_128 = 0, + FLOPPY_SECTOR_DTL_256 = 1, + FLOPPY_SECTOR_DTL_512 = 2, + FLOPPY_SECTOR_DTL_1024 = 4 +}; \ No newline at end of file diff --git a/src/libs/version.h b/src/libs/version.h index 265b173..e04efe7 100644 --- a/src/libs/version.h +++ b/src/libs/version.h @@ -6,5 +6,5 @@ #pragma once #define LOGO " _ _____ _ __________________\n / | / / | / | / / _/_ __/ ____/\n / |/ / /| | / |/ // / / / / __/ \n / /| / ___ |/ /| // / / / / /___ \n/_/ |_/_/ |_/_/ |_/___/ /_/ /_____/ \n" -#define VERSION "RD-00027" +#define VERSION "RD-00028" #define BOOTLOGO " _ ______ ____ ____ ______\n / | / / __ )/ __ \\/ __ /_ __/\n / |/ / __ / / / / / / // / \n / /| / /_/ / /_/ / /_/ // / \n/_/ |_/_____/\\____/\\____//_/ \n"