Floppy Disk Stuff is hard... also screw bitwise funtions

This commit is contained in:
Tyler McGurrin 2025-06-04 08:31:51 -04:00
parent 8af8000bcf
commit cfb28351f1
3 changed files with 311 additions and 38 deletions

View File

@ -7,6 +7,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include <arch/i686/io.h>
#include <arch/i686/irq.h>
#include <dri/serial.h>
@ -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,11 +64,18 @@ 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);
}
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()
@ -86,19 +96,213 @@ int Floppy_Check_Busy()
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;
// cylinder = (LBA / sects per track / heads)
*cylinderOut = (lba / disk->sectors) / disk->heads;
// head = (LBA / sects per track % heads)
*headOut = (lba / disk->sectors) % disk->heads;
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);
}
// 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);
}
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, &sector);
// 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.");
}
}

View File

@ -6,6 +6,9 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#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,7 +19,28 @@ 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 */
@ -30,7 +54,7 @@ enum FLOPPY_IO {
enum FLOPPY_DOR_MASK {
FLOPPY_DOR_MASK_DRIVE0 = 0, //00000000 = here for completeness sake
FLOPPY_DOR_MASK_DRIVE0 = 0, //00000000
FLOPPY_DOR_MASK_DRIVE1 = 1, //00000001
FLOPPY_DOR_MASK_DRIVE2 = 2, //00000010
FLOPPY_DOR_MASK_DRIVE3 = 3, //00000011
@ -54,3 +78,48 @@ enum FLOPPY_MSR_MASK {
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
};

View File

@ -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"