Floppy Disk Stuff is hard... also screw bitwise funtions
This commit is contained in:
parent
8af8000bcf
commit
cfb28351f1
@ -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()
|
||||
@ -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;
|
||||
|
||||
// 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, §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.");
|
||||
}
|
||||
|
||||
}
|
||||
@ -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
|
||||
};
|
||||
@ -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"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user