CTAOS v5
This commit is contained in:
18
SysCore/hal/floppy/compile.bat
Normal file
18
SysCore/hal/floppy/compile.bat
Normal file
@ -0,0 +1,18 @@
|
||||
@echo off
|
||||
rem The name of the loader assembly file (without extension, must be .asm):
|
||||
set loader_name=loader
|
||||
|
||||
rem NASM and DJGPP executable paths:
|
||||
set nasm_path=C:\nasm
|
||||
set djgpp_path=C:\DJGPP\bin
|
||||
set objpath=../../objects
|
||||
set incpath=../../include
|
||||
|
||||
@echo on
|
||||
%djgpp_path%\gcc.exe -Wall -O -fstrength-reduce -fomit-frame-pointer -nostdinc -fno-builtin -I%incpath% -c -o %objpath%/floppy.o floppy.c
|
||||
|
||||
@echo off
|
||||
@echo .
|
||||
@echo Done!
|
||||
|
||||
@pause
|
356
SysCore/hal/floppy/floppy.c
Normal file
356
SysCore/hal/floppy/floppy.c
Normal file
@ -0,0 +1,356 @@
|
||||
/***** floppy.c ******************************************************
|
||||
* (c) 2010 CTA Systems Inc. All rights reserved. Glory To God *
|
||||
* *
|
||||
* Floppy Drive I/O Routines *
|
||||
* ========================= *
|
||||
* *
|
||||
************************************************************ cta os */
|
||||
#include "../irq/irq.h"
|
||||
#include "../dma/dma.h"
|
||||
#include <system.h>
|
||||
#include <conio.h>
|
||||
|
||||
|
||||
// Used ports:
|
||||
// ***********
|
||||
// Digital Output Register (DOR): 0x3f2
|
||||
// Main Status Register (MSR): 0x3f4
|
||||
// Data Register (FIFO): 0x3f5
|
||||
// Configuration Control Register (CTRL): 0x3f7
|
||||
|
||||
unsigned char floppy_drives_installed;
|
||||
volatile unsigned char i86_floppy_new_interrupt;
|
||||
struct {
|
||||
unsigned char type;
|
||||
unsigned char data_rate;
|
||||
unsigned char step_rate_time;
|
||||
unsigned char head_load_time;
|
||||
unsigned char head_unload_time;
|
||||
unsigned char sectors_per_track;
|
||||
} fd[2];
|
||||
|
||||
|
||||
// Initialize DMA
|
||||
unsigned char i86_floppy_initialize_dma(unsigned char* buffer, unsigned length)
|
||||
{
|
||||
union { unsigned char byt[4]; // Low[0], Mid[1], Hi[2]
|
||||
unsigned long l;
|
||||
} a, c;
|
||||
|
||||
a.l = (unsigned) buffer;
|
||||
c.l = (unsigned) length-1;
|
||||
|
||||
// Check for buffer issues
|
||||
if ((a.l >> 24) || (c.l >> 16) || (((a.l & 0xffff)+c.l) >> 16)) return 0;
|
||||
|
||||
i86_dma_reset();
|
||||
i86_dma_mask_channel(2); // Mask channel 2
|
||||
i86_dma_reset_flipflop(1); // FlipFlop reset on DMA1
|
||||
|
||||
i86_dma_set_address(2, a.byt[0], a.byt[1]); // Buffer address
|
||||
i86_dma_reset_flipflop(1); // FlipFlop reset on DMA2
|
||||
|
||||
i86_dma_set_count(2, c.byt[0], c.byt[1]); // Set count
|
||||
i86_dma_set_read(2);
|
||||
i86_dma_unmask_all();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
inline void i86_floppy_disable_controller() {
|
||||
outportb (0x3F2, 0);
|
||||
}
|
||||
|
||||
inline void i86_floppy_enable_controller() {
|
||||
outportb (0x3F2, 4 | 8);
|
||||
}
|
||||
|
||||
|
||||
inline unsigned char i86_floppy_send_command (unsigned char command)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 750; i++)
|
||||
if (inportb(0x3F4) & 128) {
|
||||
outportb(0x3F5, command); return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
inline unsigned char i86_floppy_read_data ()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 750; i++)
|
||||
if (inportb(0x3F4) & 0x80)
|
||||
return inportb(0x3F5);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
inline void i86_floppy_check_int(unsigned* st0, unsigned* cyl)
|
||||
{
|
||||
i86_floppy_send_command(0x8);
|
||||
*st0 = i86_floppy_read_data();
|
||||
*cyl = i86_floppy_read_data();
|
||||
}
|
||||
|
||||
|
||||
extern unsigned i86_pit_get_tick_count();
|
||||
extern unsigned i86_pit_get_frequency();
|
||||
|
||||
|
||||
inline unsigned char i86_floppy_wait()
|
||||
{
|
||||
unsigned temp = i86_pit_get_tick_count();
|
||||
unsigned freq = i86_pit_get_frequency();
|
||||
|
||||
while (i86_floppy_new_interrupt==0)
|
||||
if (temp + (3*freq) == i86_pit_get_frequency()) return 0; // timeout
|
||||
|
||||
i86_floppy_new_interrupt = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void i86_floppy_motor (unsigned char drive, unsigned char on)
|
||||
{
|
||||
if (drive >= floppy_drives_installed) return;
|
||||
|
||||
// Read DOR register
|
||||
unsigned char dor = inportb(0x3F2);
|
||||
|
||||
// Un/set selected drive motor
|
||||
if (on) dor |= drive << 4;
|
||||
else dor &= ~(drive << 4);
|
||||
|
||||
// Write DOR
|
||||
outportb (0x3F2, dor);
|
||||
|
||||
// Wait a fifth of a second for motor to turn on
|
||||
unsigned temp = i86_pit_get_tick_count();
|
||||
unsigned freq = i86_pit_get_frequency();
|
||||
while (temp + (freq/5) > i86_pit_get_tick_count());
|
||||
}
|
||||
|
||||
|
||||
void i86_floppy_handler(ISR_stack_regs *r)
|
||||
{
|
||||
i86_floppy_new_interrupt = 1;
|
||||
}
|
||||
|
||||
|
||||
void i86_floppy_drive_data (unsigned char drv, unsigned char dma)
|
||||
{
|
||||
unsigned data = 0;
|
||||
if (drv >= floppy_drives_installed) return;
|
||||
|
||||
outportb(0x3F7, fd[drv].data_rate);
|
||||
|
||||
i86_floppy_send_command (0x3);
|
||||
|
||||
data = ((fd[drv].step_rate_time & 0xf) << 4) | (fd[drv].head_unload_time & 0xf);
|
||||
i86_floppy_send_command (data);
|
||||
|
||||
data = (fd[drv].head_load_time <<1 ) | (dma) ? 1 : 0;
|
||||
i86_floppy_send_command (data);
|
||||
}
|
||||
|
||||
|
||||
inline void i86_floppy_select(unsigned char drive)
|
||||
{
|
||||
if (drive >= floppy_drives_installed) return;
|
||||
|
||||
// Send mechanical drive data
|
||||
i86_floppy_drive_data(drive, 1);
|
||||
|
||||
// Select drive in DOR register
|
||||
outportb (0x3F2, 4 | 8 | drive);
|
||||
|
||||
}
|
||||
|
||||
|
||||
unsigned char i86_floppy_calibrate(unsigned drive)
|
||||
{
|
||||
unsigned st0, cyl;
|
||||
|
||||
if (drive >= floppy_drives_installed) return 0;
|
||||
|
||||
i86_floppy_motor (drive, 1);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 15; i++) {
|
||||
i86_floppy_new_interrupt = 0;
|
||||
i86_floppy_send_command(0x7);
|
||||
i86_floppy_send_command(drive);
|
||||
i86_floppy_wait();
|
||||
i86_floppy_check_int(&st0, &cyl);
|
||||
|
||||
if (!cyl) {
|
||||
i86_floppy_motor(drive, 0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
i86_floppy_motor(drive, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void i86_floppy_reset()
|
||||
{
|
||||
unsigned st0, cyl;
|
||||
|
||||
i86_floppy_new_interrupt = 0;
|
||||
i86_floppy_disable_controller();
|
||||
i86_floppy_enable_controller();
|
||||
i86_floppy_wait();
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 4; i++)
|
||||
i86_floppy_check_int(&st0, &cyl);
|
||||
|
||||
unsigned char drive;
|
||||
for (drive = 0; drive < floppy_drives_installed; drive++) {
|
||||
i86_floppy_drive_data(drive, 1);
|
||||
i86_floppy_calibrate(drive);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void i86_floppy_read_sector_imp (unsigned* where, unsigned char drive, unsigned char head, unsigned char track, unsigned char sector)
|
||||
{
|
||||
unsigned st0, cyl;
|
||||
|
||||
i86_floppy_select (drive);
|
||||
i86_floppy_initialize_dma((unsigned char*) where, 512);
|
||||
i86_dma_set_read(2);
|
||||
|
||||
i86_floppy_new_interrupt = 0;
|
||||
|
||||
i86_floppy_send_command(0x06 | 0x80 | 0x40 );
|
||||
i86_floppy_send_command(head<<2 | drive);
|
||||
i86_floppy_send_command(track);
|
||||
i86_floppy_send_command(head);
|
||||
i86_floppy_send_command(sector);
|
||||
i86_floppy_send_command(0x02);
|
||||
i86_floppy_send_command( ((sector+1) >= fd[drive].sectors_per_track) ? fd[drive].sectors_per_track : sector+1);
|
||||
i86_floppy_send_command(0x1b);
|
||||
i86_floppy_send_command(0xff);
|
||||
|
||||
i86_floppy_wait();
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 7; i++) i86_floppy_read_data();
|
||||
|
||||
i86_floppy_check_int (&st0, &cyl);
|
||||
}
|
||||
|
||||
|
||||
unsigned char i86_floppy_seek (unsigned drive, unsigned cyl, unsigned head)
|
||||
{
|
||||
unsigned st0, cyl0;
|
||||
|
||||
if (drive >= floppy_drives_installed) return 0;
|
||||
|
||||
i86_floppy_select (drive);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 20; i++) {
|
||||
i86_floppy_new_interrupt = 0;
|
||||
i86_floppy_send_command (0xF);
|
||||
i86_floppy_send_command ( (head) << 2 | drive);
|
||||
i86_floppy_send_command (cyl);
|
||||
|
||||
i86_floppy_wait();
|
||||
i86_floppy_check_int(&st0, &cyl0);
|
||||
|
||||
if (cyl0 == cyl) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
inline void i86_floppy_lba_to_chs (int lba, unsigned char drive, unsigned char *head, unsigned char *track, unsigned char *sectors)
|
||||
{
|
||||
*head = (lba % (fd[drive].sectors_per_track * 2)) / fd[drive].sectors_per_track;
|
||||
*track = lba / (fd[drive].sectors_per_track * 2);
|
||||
*sectors = lba % fd[drive].sectors_per_track + 1;
|
||||
}
|
||||
|
||||
extern unsigned char i86_cmos_read_floppy_drives();
|
||||
const char* types[] = {
|
||||
"Nonexistant", "5.25\", unsupported.", "5.25\", unsupported.",
|
||||
"3.5\", 720kb", "3.5\", 1.44mb", "3.5\", 2.88 mb"};
|
||||
|
||||
void i86_floppy_install()
|
||||
{
|
||||
unsigned char temp = i86_cmos_read_floppy_drives();
|
||||
int i;
|
||||
|
||||
// Set fd0 and fd1 types
|
||||
fd[1].type = temp & 0xf;
|
||||
fd[0].type = temp >> 4;
|
||||
|
||||
// SRT = 16 - (ms * datarate / 500000);
|
||||
// HLT = ms * datarate / 1000000
|
||||
// HUT = ms * datarate / 8000000
|
||||
|
||||
// Set up
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (fd[i].type >= 3) floppy_drives_installed++; // 5.25" drives unsupported
|
||||
if (fd[i].type == 3) { // 720 kb, DD
|
||||
fd[i].data_rate = 2; // speed = 250 kbps
|
||||
fd[i].step_rate_time = 12; // 16 - (ms * 250000 / 500000), ms = 8
|
||||
fd[i].head_load_time = 7;
|
||||
fd[i].head_unload_time = 7;
|
||||
fd[i].sectors_per_track = 9;
|
||||
}
|
||||
else if (fd[i].type == 4) { // 1.44 MB, HD
|
||||
fd[i].data_rate = 0; // speed = 500 kbps
|
||||
fd[i].step_rate_time = 8;
|
||||
fd[i].head_load_time = 15;
|
||||
fd[i].head_unload_time = 15;
|
||||
fd[i].sectors_per_track = 18;
|
||||
}
|
||||
else if (fd[i].type == 5) { // 2.88 MB, ED
|
||||
fd[i].data_rate = 3; // speed = 1000 kbps;
|
||||
fd[i].step_rate_time = 0;
|
||||
fd[i].head_load_time = 30;
|
||||
fd[i].head_unload_time = 30;
|
||||
fd[i].sectors_per_track = 36;
|
||||
}
|
||||
}
|
||||
if (floppy_drives_installed == 0) return; // No drives to set
|
||||
|
||||
// Install handler
|
||||
i86_irq_install_handler(6, i86_floppy_handler);
|
||||
i86_floppy_reset();
|
||||
}
|
||||
|
||||
|
||||
unsigned char i86_floppy_driver_enabled()
|
||||
{
|
||||
return (floppy_drives_installed>0);
|
||||
}
|
||||
|
||||
|
||||
unsigned* i86_read_sector (unsigned* where, unsigned char drive, int sectorLBA)
|
||||
{
|
||||
if (drive >= floppy_drives_installed) return 0;
|
||||
if ((unsigned)(where) > (0xFFFF - 513)) return 0;
|
||||
|
||||
// convert lba to chs
|
||||
unsigned head, track, sector;
|
||||
i86_floppy_lba_to_chs(sectorLBA, drive, (unsigned char*)&head, (unsigned char*)&track, (unsigned char*) §or);
|
||||
|
||||
// start motor
|
||||
i86_floppy_motor(drive, 1);
|
||||
if (!i86_floppy_seek(drive, track, head)) return 0;
|
||||
|
||||
i86_floppy_read_sector_imp(where, drive, head, track, sector);
|
||||
i86_floppy_motor(drive, 0);
|
||||
|
||||
return (unsigned*)where;
|
||||
}
|
19
SysCore/hal/floppy/floppy.h
Normal file
19
SysCore/hal/floppy/floppy.h
Normal file
@ -0,0 +1,19 @@
|
||||
/***** floppy.h ******************************************************
|
||||
* (c) 2010 CTA Systems Inc. All rights reserved. Glory To God *
|
||||
* *
|
||||
* Floppy Drive I/O Routines *
|
||||
* ========================= *
|
||||
* *
|
||||
************************************************************ cta os */
|
||||
|
||||
extern unsigned char i86_floppy_initialize_dma(unsigned char* buffer, unsigned length);
|
||||
extern void i86_floppy_motor (unsigned char drive, unsigned char on);
|
||||
extern void i86_floppy_handler(ISR_stack_regs *r);
|
||||
extern void i86_floppy_drive_data (unsigned char drv, unsigned char dma);
|
||||
extern unsigned char i86_floppy_calibrate(unsigned drive);
|
||||
extern void i86_floppy_reset();
|
||||
extern void i86_floppy_read_sector_imp (unsigned* where, unsigned char drive, unsigned char head, unsigned char track, unsigned char sector);
|
||||
extern unsigned char i86_floppy_seek (unsigned drive, unsigned cyl, unsigned head);
|
||||
extern void i86_floppy_install();
|
||||
extern unsigned char i86_floppy_driver_enabled();
|
||||
extern unsigned* i86_read_sector (unsigned* where, unsigned char drive, int sectorLBA);
|
Reference in New Issue
Block a user