[GOOD] BUILD 0.1.0.450 DATE 8/29/2011 AT 10:30 AM
==================================================== + Changed 'align 0x4' line above multiboot header in loader.asm to 'align 4' + Removed -e option for echo in build.sh + Modified build.sh for linux + Fixed triple fault when enabling paging + Fixed page faults at memory manager initialization + Fixed 'mem' console function + Added more info about page fault at crash screen + Added Panic() macro + Added verbose mode for memory manager [ BAD] BUILD 0.1.0.390 DATE 8/27/2011 AT 10:54 PM ==================================================== + Added stdlib routines, separated in different files + Rewritten physical memory manager + Added virtual mem manager + Added memory allocation/freeing + Added memory library + Added temporary allocation (at end of kernel), until paging is started - Removed functionality from debug console function 'mem' - Removed system.h, the one remaining function now in stdio.h
This commit is contained in:
63
Kernel/drivers/cmos/cmos.c
Normal file
63
Kernel/drivers/cmos/cmos.c
Normal file
@ -0,0 +1,63 @@
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include "cmos.h"
|
||||
|
||||
uint8 CmosRead (uint8 address)
|
||||
{
|
||||
outportb(0x70, address); iowait();
|
||||
return inportb(0x71);
|
||||
}
|
||||
|
||||
void CmosWrite (uint8 address, uint8 val)
|
||||
{
|
||||
outportb(0x70, address); iowait();
|
||||
outportb(0x71, val);
|
||||
}
|
||||
|
||||
void CmosSetRTC (const Time* time)
|
||||
{
|
||||
unsigned char BCD = ((CmosRead(0x0b)&4)==0) ? 1 : 0;
|
||||
unsigned char ampm = ((CmosRead(0x0b)&2)==0) ? 1 : 0;
|
||||
|
||||
uint8 year = time->Year % 100;
|
||||
uint8 century = time->Year / 100;
|
||||
|
||||
CmosWrite (0, (BCD) ? (time->Second%10) | (time->Second/10*16) : time->Second); // Seconds
|
||||
CmosWrite (2, (BCD) ? (time->Minute%10) | (time->Minute/10*16) : time->Minute); // Minutes
|
||||
|
||||
if (ampm && time->Hour > 12) // Hours
|
||||
CmosWrite (4, (BCD) ? (((time->Hour - 12) % 10) | ((time->Hour - 12)/10*16) | 0x80) : (time->Hour | 0x80) );
|
||||
|
||||
else if (ampm && time->Hour == 0) // Midnight convention: 12 PM = 00:00
|
||||
CmosWrite (4, (BCD) ? 0x92 : 0x8C);
|
||||
|
||||
else CmosWrite (4, (BCD) ? (time->Hour%10) | (time->Hour/10*16) : time->Hour); // 24h / AM
|
||||
|
||||
CmosWrite (7, (BCD) ? (time->Day%10) | (time->Day/10*16) : time->Day); // Day
|
||||
CmosWrite (8, (BCD) ? (time->Month%10) | (time->Month/10*16) : time->Month); // Month
|
||||
CmosWrite (9, (BCD) ? (year%10) | (year/10*16) : year); // Year
|
||||
CmosWrite (0x32, (BCD) ? (century%10) | (century/10*16) : century); // Century
|
||||
}
|
||||
|
||||
void CmosGetRTC(Time* tim)
|
||||
{
|
||||
unsigned char BCD = ((CmosRead(0x0b)&4)==0) ? 1 : 0;
|
||||
unsigned char am_pm = ((CmosRead(0x0b)&2)==0) ? 1 : 0;
|
||||
|
||||
tim->Second = (BCD) ? (CmosRead(0x00)%16) + 10*(CmosRead(0x00)/16): CmosRead(0x00);
|
||||
tim->Minute = (BCD) ? (CmosRead(0x02)%16) + 10*(CmosRead(0x02)/16): CmosRead(0x02);
|
||||
|
||||
// Time is PM
|
||||
if (am_pm && (CmosRead(0x04)&80)) {
|
||||
tim->Hour = (BCD) ? ((CmosRead(0x04)-0x80)%16) + 10*((CmosRead(0x04)-0x80)/16): CmosRead(0x04)-0x80;
|
||||
tim->Hour += 12;
|
||||
}
|
||||
// 24Hour format, or AM
|
||||
else tim->Hour = (BCD) ? (CmosRead(0x04)%16) + 10*(CmosRead(0x04)/16): CmosRead(0x04);
|
||||
|
||||
tim->WeekDay = (BCD) ? (CmosRead(0x06)%16) + 10*(CmosRead(0x06)/16): CmosRead(0x06);
|
||||
tim->Day = (BCD) ? (CmosRead(0x07)%16) + 10*(CmosRead(0x07)/16): CmosRead(0x07);
|
||||
tim->Month = (BCD) ? (CmosRead(0x08)%16) + 10*(CmosRead(0x08)/16): CmosRead(0x08);
|
||||
tim->Year = (BCD) ? (CmosRead(0x09)%16) + 10*(CmosRead(0x09)/16): CmosRead(0x09);
|
||||
tim->Year += 100 * ((BCD) ? (CmosRead(0x32)%16) + 10*(CmosRead(0x32)/16): CmosRead(0x32));
|
||||
}
|
12
Kernel/drivers/cmos/cmos.h
Normal file
12
Kernel/drivers/cmos/cmos.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef __CMOS__H
|
||||
#define __CMOS__H
|
||||
|
||||
#include <types.h>
|
||||
#include <time.h>
|
||||
|
||||
extern uint8 CmosRead (uint8 address);
|
||||
extern void CmosWrite (uint8 address, uint8 val);
|
||||
extern void CmosSetRTC (const Time* time);
|
||||
extern void CmosGetRTC(Time* tim);
|
||||
|
||||
#endif
|
111
Kernel/drivers/dma/dma.c
Normal file
111
Kernel/drivers/dma/dma.c
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* dma.c
|
||||
*
|
||||
* Created on: Aug 20, 2011
|
||||
* Author: Tiberiu
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "dma.h"
|
||||
|
||||
void DmaSetAddress (uint8 channel, uint8 low, uint8 high)
|
||||
{
|
||||
uint16 port = 0;
|
||||
|
||||
switch (channel)
|
||||
{
|
||||
case 0: port = DmaRegisterChannel0Address; break;
|
||||
case 1: port = DmaRegisterChannel1Address; break;
|
||||
case 2: port = DmaRegisterChannel2Address; break;
|
||||
case 3: port = DmaRegisterChannel3Address; break;
|
||||
case 4: port = DmaRegisterChannel4Address; break;
|
||||
case 5: port = DmaRegisterChannel5Address; break;
|
||||
case 6: port = DmaRegisterChannel6Address; break;
|
||||
case 7: port = DmaRegisterChannel7Address; break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
outportb(port, low); iowait();
|
||||
outportb(port, high);
|
||||
}
|
||||
|
||||
void DmaSetCount (uint8 channel, uint8 low, uint8 high)
|
||||
{
|
||||
uint16 port = 0;
|
||||
|
||||
switch (channel)
|
||||
{
|
||||
case 0: port = DmaRegisterChannel0Count; break;
|
||||
case 1: port = DmaRegisterChannel1Count; break;
|
||||
case 2: port = DmaRegisterChannel2Count; break;
|
||||
case 3: port = DmaRegisterChannel3Count; break;
|
||||
case 4: port = DmaRegisterChannel4Count; break;
|
||||
case 5: port = DmaRegisterChannel5Count; break;
|
||||
case 6: port = DmaRegisterChannel6Count; break;
|
||||
case 7: port = DmaRegisterChannel7Count; break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
outportb(port, low); iowait();
|
||||
outportb(port, high);
|
||||
}
|
||||
|
||||
void DmaSetExternalPageRegisters (uint8 channel, uint8 val)
|
||||
{
|
||||
uint16 port = 0;
|
||||
|
||||
switch (channel)
|
||||
{
|
||||
case 1: port = DmaRegisterChannel1PageAddress; break;
|
||||
case 2: port = DmaRegisterChannel2PageAddress; break;
|
||||
case 3: port = DmaRegisterChannel3PageAddress; break;
|
||||
case 5: port = DmaRegisterChannel5PageAddress; break;
|
||||
case 6: port = DmaRegisterChannel6PageAddress; break;
|
||||
case 7: port = DmaRegisterChannel7PageAddress; break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
outportb(port, val);
|
||||
}
|
||||
|
||||
void DmaResetFlipFlop (uint8 channel)
|
||||
{
|
||||
uint16 port = (channel < 4) ? DmaRegisterFlipFlopReset : 2*DmaRegisterFlipFlopReset+0xC0;
|
||||
outportb(port, 0);
|
||||
}
|
||||
|
||||
void DmaReset ()
|
||||
{
|
||||
outportb(DmaRegisterMasterReset, 0);
|
||||
}
|
||||
|
||||
void DmaUnmaskAll()
|
||||
{
|
||||
outportb(DmaRegisterMaskReset, 0);
|
||||
}
|
||||
|
||||
void DmaMaskChannel(uint8 channel)
|
||||
{
|
||||
if (channel >= 8) return;
|
||||
uint16 port = (channel < 4) ? (DmaRegisterSingleChannelMask) : (2*DmaRegisterSingleChannelMask + 0xC0);
|
||||
|
||||
outportb(port, channel%4 | 4);
|
||||
}
|
||||
|
||||
void DmaUnmaskChannel (uint8 channel)
|
||||
{
|
||||
if (channel >= 8) return;
|
||||
uint16 port = (channel < 4) ? (DmaRegisterSingleChannelMask) : (2*DmaRegisterSingleChannelMask + 0xC0);
|
||||
|
||||
outportb(port, channel%4);
|
||||
}
|
||||
|
||||
void DmaSetMode (uint8 channel, uint8 mode)
|
||||
{
|
||||
if (channel >= 8) return;
|
||||
uint16 port = (channel < 4) ? (DmaRegisterMode) : (2*DmaRegisterMode + 0xC0);
|
||||
|
||||
DmaMaskChannel(channel);
|
||||
outportb(port, (channel%4) | mode );
|
||||
DmaUnmaskAll();
|
||||
}
|
80
Kernel/drivers/dma/dma.h
Normal file
80
Kernel/drivers/dma/dma.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* dma.h
|
||||
*
|
||||
* Created on: Aug 20, 2011
|
||||
* Author: Tiberiu
|
||||
*/
|
||||
|
||||
#ifndef DMA_H_
|
||||
#define DMA_H_
|
||||
|
||||
#include <types.h>
|
||||
|
||||
enum DmaRegisters
|
||||
{
|
||||
DmaRegisterStatus = 0x08,
|
||||
DmaRegisterCommand = 0x08,
|
||||
DmaRegisterRequest = 0x09,
|
||||
DmaRegisterSingleChannelMask = 0x0A,
|
||||
DmaRegisterMode = 0x0B,
|
||||
DmaRegisterFlipFlopReset = 0x0C,
|
||||
DmaRegisterIntermediate = 0x0D,
|
||||
DmaRegisterMasterReset = 0x0D,
|
||||
DmaRegisterMaskReset = 0x0E,
|
||||
DmaRegisterMultichannelMask = 0x0F,
|
||||
|
||||
DmaRegisterChannel0Address = 0x00,
|
||||
DmaRegisterChannel1Address = 0x02,
|
||||
DmaRegisterChannel2Address = 0x04,
|
||||
DmaRegisterChannel3Address = 0x06,
|
||||
DmaRegisterChannel4Address = 0xC0,
|
||||
DmaRegisterChannel5Address = 0xC4,
|
||||
DmaRegisterChannel6Address = 0xC8,
|
||||
DmaRegisterChannel7Address = 0xCC,
|
||||
|
||||
DmaRegisterChannel0Count = 0x01,
|
||||
DmaRegisterChannel1Count = 0x03,
|
||||
DmaRegisterChannel2Count = 0x05,
|
||||
DmaRegisterChannel3Count = 0x07,
|
||||
DmaRegisterChannel4Count = 0xC2,
|
||||
DmaRegisterChannel5Count = 0xC6,
|
||||
DmaRegisterChannel6Count = 0xCA,
|
||||
DmaRegisterChannel7Count = 0xCE,
|
||||
|
||||
DmaRegisterChannel1PageAddress = 0x83,
|
||||
DmaRegisterChannel2PageAddress = 0x81,
|
||||
DmaRegisterChannel3PageAddress = 0x82,
|
||||
DmaRegisterChannel5PageAddress = 0x8B,
|
||||
DmaRegisterChannel6PageAddress = 0x89,
|
||||
DmaRegisterChannel7PageAddress = 0x8A
|
||||
};
|
||||
|
||||
enum DmaModes
|
||||
{
|
||||
DmaModeChannelMask = 0x3,
|
||||
|
||||
DmaModeSelfTest = 0,
|
||||
DmaModeWrite = 0x8,
|
||||
DmaModeRead = 0x4,
|
||||
DmaModeAutoReinit = 0x10,
|
||||
DmaModeDown = 0x20,
|
||||
|
||||
DmaModeTransferOnDemand = 0,
|
||||
DmaModeTransferSingleDma = 0x40,
|
||||
DmaModeTransferBlockDma = 0x80,
|
||||
DmaModeTransferCascade = 0xC0
|
||||
};
|
||||
|
||||
extern void DmaSetAddress (uint8 channel, uint8 low, uint8 high);
|
||||
extern void DmaSetCount (uint8 channel, uint8 low, uint8 high);
|
||||
extern void DmaSetExternalPageRegisters (uint8 channel, uint8 val);
|
||||
extern void DmaSetMode (uint8 channel, uint8 mode);
|
||||
|
||||
extern void DmaResetFlipFlop (uint8 channel);
|
||||
extern void DmaReset ();
|
||||
|
||||
extern void DmaMaskChannel(uint8 channel);
|
||||
extern void DmaUnmaskChannel (uint8 channel);
|
||||
extern void DmaUnmaskAll ();
|
||||
|
||||
#endif /* DMA_H_ */
|
34
Kernel/drivers/drivers.c
Normal file
34
Kernel/drivers/drivers.c
Normal file
@ -0,0 +1,34 @@
|
||||
#include "drivers.h"
|
||||
#include "cmos/cmos.h"
|
||||
#include "pit/pit.h"
|
||||
#include "floppy/floppy.h"
|
||||
#include "time.h"
|
||||
#include "../hal/cpu/irq.h"
|
||||
#include <debugio.h>
|
||||
|
||||
void DriversInstall_Clock()
|
||||
{
|
||||
// Set up PIT
|
||||
PitSetFrequency(PIT_FREQUENCY);
|
||||
|
||||
// Update internal clock
|
||||
Time time;
|
||||
CmosGetRTC(&time);
|
||||
|
||||
TimeSetInternalTime(TimeConvertToTimeSystem(time));
|
||||
|
||||
Log("%#[Drivers] %#Read RTC time: ", ColorWhite, ColorLightGray);
|
||||
Log("%#%u/%u/%u %u:%u:%u.%u\n", ColorLightCyan, time.Month, time.Day,
|
||||
time.Year, time.Hour, time.Minute, time.Second, time.Milisecond);
|
||||
}
|
||||
|
||||
|
||||
void DriversInstall()
|
||||
{
|
||||
// Install clock
|
||||
DriversInstall_Clock();
|
||||
|
||||
// Install fdc
|
||||
IrqInstallHandler(6, FloppyIrqHandler);
|
||||
FloppyInitialize();
|
||||
}
|
6
Kernel/drivers/drivers.h
Normal file
6
Kernel/drivers/drivers.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef __DRIVERS__H
|
||||
#define __DRIVERS__H
|
||||
|
||||
extern void DriversInstall();
|
||||
|
||||
#endif
|
384
Kernel/drivers/floppy/floppy.c
Normal file
384
Kernel/drivers/floppy/floppy.c
Normal file
@ -0,0 +1,384 @@
|
||||
/*
|
||||
* floppy.c
|
||||
*
|
||||
* Created on: Aug 20, 2011
|
||||
* Author: Tiberiu
|
||||
*/
|
||||
|
||||
#include <debugio.h>
|
||||
#include <stdio.h>
|
||||
#include <types.h>
|
||||
#include <time.h>
|
||||
#include <storage.h>
|
||||
#include "floppy.h"
|
||||
#include "../dma/dma.h"
|
||||
#include "../cmos/cmos.h"
|
||||
|
||||
FloppyType fdTypes[] = {
|
||||
/* Sectors
|
||||
* | Sectors per track
|
||||
* | | Heads
|
||||
* | | | Tracks
|
||||
* | | | | Gap1
|
||||
* | | | | | Data rate
|
||||
* | | | | | | Spec1
|
||||
* | | | | | | | SRT HLT HUT Motor Spinup time
|
||||
* | | | | | | | | | | | Motor Spindown time
|
||||
* | | | | | | | | | | | | Interrupt timeout
|
||||
* | | | | | | | | | | | | | Disk type name string*/
|
||||
{ 0, 0,0, 0,0x00,0x00,0x00,0x00,0x00,0x00, 0, 0, 0, "none"},
|
||||
{ 720, 9,2,40,0x2A,0x01,0xDF,0x0C,0x04,0x00,1000,1000,3000, "5.25\" 360k"},
|
||||
{ 2400,15,2,80,0x1B,0x00,0xDF,0x0A,0x08,0x00, 400,1000,3000, "5.25\" 1.2M"},
|
||||
{ 1440, 9,2,80,0x2A,0x02,0xDF,0x0F,0x04,0x00,1000,1000,3000, "3.5\" 720k"},
|
||||
{ 2880,18,2,80,0x1B,0x00,0xCF,0x0C,0x08,0x00, 400,1000,3000, "3.5\" 1.44M"},
|
||||
//{ 2880,18,2,80,0x1B,0x00,0xCF,0x0C,0x08,0x00,2000,3000,3000, "3.5\" 1.44M"},
|
||||
{ 5760,36,2,80,0x1B,0x03,0xAF,0x0A,0x0F,0x00, 400,1000,3000, "3.5\" 2.88M AMI BIOS"},
|
||||
{ 5760,36,2,80,0x1B,0x03,0xAF,0x0A,0x0F,0x00, 400,1000,3000, "3.5\" 2.88M"},
|
||||
};
|
||||
|
||||
int8 fd0, fd1;
|
||||
|
||||
/**************************************
|
||||
* IRQ handler etc *
|
||||
**************************************/
|
||||
volatile uint8 FloppyIrqFired;
|
||||
void FloppyIrqHandler(_RegsStack32* UNUSED(r))
|
||||
{
|
||||
FloppyIrqFired = 1;
|
||||
}
|
||||
|
||||
void FloppyWaitIrq()
|
||||
{
|
||||
TimerStart(fdTypes[4].InterruptTimeout);
|
||||
|
||||
while (!FloppyIrqFired && !TimerIsDone());
|
||||
|
||||
if (!FloppyIrqFired) {
|
||||
Error("%#[Floppy] %#Irq timeout [%ums] !\n", ColorBrown, ColorLightRed, fdTypes[4].InterruptTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************
|
||||
* Installation *
|
||||
**************************************/
|
||||
void FloppyInitialize()
|
||||
{
|
||||
// Detect drives
|
||||
uint8 fd = CmosRead(0x10);
|
||||
fd0 = fd >> 4;
|
||||
fd1 = fd & 0xf;
|
||||
|
||||
if (fd0 > 6) fd0 = 0;
|
||||
if (fd1 > 6) fd1 = 0;
|
||||
|
||||
if (!fd0 && !fd1) {
|
||||
Error("%#[Floppy] %#No supported floppy drives found.", ColorBrown, ColorLightRed);
|
||||
outportb(FloppyRegisterDigitalOutput, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
Log("%#[Floppy] %#Detected floppy drives:", ColorBrown, ColorLightGray);
|
||||
if (fd0) Log(" %#fd0=%#%s", ColorLightCyan, Color(ColorCyan, ColorWhite), fdTypes[fd0].Name);
|
||||
if (fd1) Log(" %#fd1=%#%s", ColorLightCyan, Color(ColorCyan, ColorWhite), fdTypes[fd1].Name);
|
||||
Log("\n");
|
||||
|
||||
|
||||
// Reset floppy controller
|
||||
FloppyReset();
|
||||
|
||||
// Configure and lock
|
||||
FloppyConfigure();
|
||||
FloppySendCommand(FloppyCommandLock | 0x80);
|
||||
FloppyReadData();
|
||||
|
||||
// Enable perpendicular mode for 3.5" ED floppies
|
||||
if (fd0 > 4)
|
||||
{
|
||||
FloppySendCommand(FloppyCommandPerpendicularMode);
|
||||
FloppySendCommand(1);
|
||||
}
|
||||
if (fd1 > 4)
|
||||
{
|
||||
FloppySendCommand(FloppyCommandPerpendicularMode);
|
||||
FloppySendCommand(2);
|
||||
}
|
||||
|
||||
// Initialize DMA
|
||||
FloppyInitDma();
|
||||
}
|
||||
|
||||
void FloppyInitDma()
|
||||
{
|
||||
DmaMaskChannel(2);
|
||||
DmaResetFlipFlop(2);
|
||||
DmaSetAddress(2, 0, 0x10);
|
||||
DmaResetFlipFlop(2);
|
||||
DmaSetCount(2, 0xff, 0x23);
|
||||
DmaSetExternalPageRegisters(2,0);
|
||||
DmaUnmaskChannel(2);
|
||||
}
|
||||
|
||||
|
||||
/**************************************
|
||||
* Controller reset *
|
||||
**************************************/
|
||||
void FloppyReset()
|
||||
{
|
||||
FloppyIrqFired = 0; int32 i = 0;
|
||||
|
||||
Log("%#[Floppy] %#Resetting...\n", ColorBrown, ColorLightGray);
|
||||
|
||||
// Clear reset bit from DOR
|
||||
outportb(FloppyRegisterDigitalOutput, 0);
|
||||
for (i = 0; i < 1000; i++);
|
||||
outportb(FloppyRegisterDigitalOutput, 4|8);
|
||||
|
||||
// Wait for IRQ6
|
||||
FloppyWaitIrq(fd0);
|
||||
|
||||
// Recalibrate every drive
|
||||
if (fd0)
|
||||
{
|
||||
FloppyMotor(0,1);
|
||||
FloppySelectDrive(0);
|
||||
FloppyRecalibrate(0);
|
||||
FloppyMotor(0,0);
|
||||
}
|
||||
|
||||
if (fd1)
|
||||
{
|
||||
FloppyMotor(1,1);
|
||||
FloppySelectDrive(1);
|
||||
FloppyRecalibrate(1);
|
||||
FloppyMotor(1,0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* Configure floppy controller *
|
||||
**************************************/
|
||||
void FloppyConfigure()
|
||||
{
|
||||
FloppySendCommand(FloppyCommandConfigure);
|
||||
FloppySendCommand(0);
|
||||
FloppySendCommand(1<<6 | 7);
|
||||
FloppySendCommand(0);
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* Base commands *
|
||||
**************************************/
|
||||
void FloppySendCommand (uint8 command)
|
||||
{
|
||||
int32 t;
|
||||
for (t = 0; t < 5000 && ((inportb(FloppyRegisterMainStatus) & FloppyMsrRQM) == 0); t++) ;
|
||||
|
||||
outportb (FloppyRegisterFIFO, command);
|
||||
|
||||
}
|
||||
|
||||
uint8 FloppyReadData ()
|
||||
{
|
||||
int32 t;
|
||||
for (t = 0; t < 5000 && ((inportb(FloppyRegisterMainStatus) & FloppyMsrRQM) == 0); t++) ;
|
||||
|
||||
return inportb (FloppyRegisterFIFO);
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* Sense interrupt *
|
||||
**************************************/
|
||||
void FloppySenseInterrupt(uint8 *st0, uint8 *cyl)
|
||||
{
|
||||
FloppySendCommand(FloppyCommandSenseInterrupt);
|
||||
*st0 = FloppyReadData();
|
||||
*cyl = FloppyReadData();
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* Specify *
|
||||
**************************************/
|
||||
void FloppySpecify (uint8 fd)
|
||||
{
|
||||
FloppySendCommand(FloppyCommandSpecify);
|
||||
FloppySendCommand((fdTypes[fd].SRT << 4) | fdTypes[fd].HUT);
|
||||
FloppySendCommand(fdTypes[fd].HLT << 1);
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* Motor on/off *
|
||||
**************************************/
|
||||
void FloppyMotor (uint8 fd_number, uint8 status)
|
||||
{
|
||||
if (fd_number >= 2) return;
|
||||
|
||||
uint8 fd = (fd_number == 0) ? fd0 : fd1;
|
||||
uint8 temp = inportb(FloppyRegisterDigitalOutput);
|
||||
|
||||
// Turn motor on/off
|
||||
if (status) temp |= 0x1<<(4+fd_number);
|
||||
else temp &= ~(0x1<<(4+fd_number));
|
||||
outportb(FloppyRegisterDigitalOutput, temp);
|
||||
|
||||
// Wait for spinup/spindown
|
||||
if (status) TimerStart(fdTypes[fd].Spinup);
|
||||
else TimerStart(fdTypes[fd].Spindown);
|
||||
|
||||
Log("%#[Floppy] %#Waiting for motor...\n", ColorBrown, ColorLightGray);
|
||||
while (!TimerIsDone());
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* Select drive *
|
||||
**************************************/
|
||||
void FloppySelectDrive(uint8 number)
|
||||
{
|
||||
if (number >= 2) return;
|
||||
uint8 fd = (number == 0) ? fd0 : fd1;
|
||||
|
||||
// Set CCR
|
||||
outportb(FloppyRegisterConfigurationControl, fdTypes[fd].DataRate);
|
||||
|
||||
// Specify
|
||||
FloppySpecify(fd);
|
||||
|
||||
// Select drive
|
||||
uint8 dor = inportb(FloppyRegisterDigitalOutput);
|
||||
dor = (dor & ~0xFF) | number;
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* RECALIBRATE *
|
||||
* motor must be on, drive selected *
|
||||
**************************************/
|
||||
void FloppyRecalibrate(uint8 fd_number)
|
||||
{
|
||||
if (fd_number >= 2) return;
|
||||
|
||||
uint8 st0, cyl, timeout = 10;
|
||||
do {
|
||||
Log("%#[Floppy] %#Recalibrating: attempt %u/10\n", ColorBrown, ColorLightGray, 11-timeout);
|
||||
FloppyIrqFired = 0;
|
||||
FloppySendCommand(FloppyCommandRecalibrate);
|
||||
FloppySendCommand(fd_number);
|
||||
FloppyWaitIrq();
|
||||
|
||||
FloppySenseInterrupt(&st0, &cyl);
|
||||
|
||||
timeout--;
|
||||
} while((st0 & 0x20) == 0 && timeout > 0);
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* SEEK *
|
||||
* motor must be on, drive selected *
|
||||
**************************************/
|
||||
void FloppySeek(uint8 fd_number, uint8 cylinder, uint8 head)
|
||||
{
|
||||
if (fd_number >= 2) return;
|
||||
|
||||
uint8 st0, cyl, timeout = 10;
|
||||
do {
|
||||
Log("%#[Floppy] %#Seeking: attempt %u/10\n", ColorBrown, ColorLightGray, 11-timeout);
|
||||
FloppyIrqFired = 0;
|
||||
FloppySendCommand(FloppyCommandSeek);
|
||||
FloppySendCommand(head<<2 | fd_number);
|
||||
FloppySendCommand(cylinder);
|
||||
FloppyWaitIrq();
|
||||
|
||||
FloppySenseInterrupt(&st0, &cyl);
|
||||
|
||||
timeout--;
|
||||
} while(cyl != cylinder && timeout > 0);
|
||||
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* READ/WRITE *
|
||||
* motor must be on, drive selected *
|
||||
**************************************/
|
||||
void FloppyRW(uint8 isWrite, uint8 fd_number, uint8 head, uint8 cylinder, uint8 sector)
|
||||
{
|
||||
if (fd_number >= 2) return;
|
||||
uint8 fd = (fd_number == 0) ? fd0 : fd1;
|
||||
|
||||
uint8 timeout = 10;
|
||||
uint8 result[7], i, error;
|
||||
do
|
||||
{
|
||||
error = 0;
|
||||
Log("%#[Floppy] %#Read/write operation: attempt %u/10\n", ColorBrown, ColorLightGray, 11-timeout);
|
||||
FloppyIrqFired = 0;
|
||||
|
||||
if (isWrite) FloppySendCommand(FloppyCommandWriteData | FloppyModeMultitrack | FloppyModeMagneticEncoding);
|
||||
else FloppySendCommand(FloppyCommandReadData | FloppyModeMultitrack | FloppyModeMagneticEncoding);
|
||||
|
||||
FloppySendCommand(head<<2 | fd_number);
|
||||
FloppySendCommand(cylinder);
|
||||
FloppySendCommand(head);
|
||||
FloppySendCommand(sector);
|
||||
FloppySendCommand(2);
|
||||
FloppySendCommand(fdTypes[fd].SectorsPerTrack);
|
||||
FloppySendCommand(fdTypes[fd].Gap);
|
||||
FloppySendCommand(0xff);
|
||||
|
||||
FloppyWaitIrq();
|
||||
|
||||
for (i = 0; i < 7; i++)
|
||||
result[i] = FloppyReadData();
|
||||
|
||||
// Disk is write protected, don't try again
|
||||
if (result[1] & 2)
|
||||
{
|
||||
Error("%#[Floppy] %#Error: disk is write protected!\n", ColorBrown, ColorLightRed);
|
||||
return;
|
||||
}
|
||||
|
||||
// Any other error - try again
|
||||
if (result[0] & 0xC8) error = 1;
|
||||
if (result[1] & 0xB5) error = 1;
|
||||
if (result[2] & 0x77) error = 1;
|
||||
if (result[6] & 0x02) error = 1;
|
||||
|
||||
timeout--;
|
||||
} while (timeout > 0 && !error);
|
||||
}
|
||||
|
||||
uint32 FloppyRead(uint8 drive, uint32 lba)
|
||||
{
|
||||
if (drive >= 2) return 0;
|
||||
uint8 fd = (drive == 0) ? fd0 : fd1;
|
||||
|
||||
// Convert LBA to CHS
|
||||
uint32 cyl=0, head=0, sect=1;
|
||||
ConvertLbaToChs(fdTypes[fd].SectorsPerTrack, lba, &cyl, &head, §);
|
||||
Log("%#[Floppy] %#Converted LBA=%u to Cyl=%u Head=%u Sect=%u\n", ColorBrown, ColorLightGray, lba, cyl, head, sect);
|
||||
|
||||
FloppyInitDma();
|
||||
|
||||
// Reset drive if necessary
|
||||
if ((inportb(FloppyRegisterMainStatus) & 0xC0) != 0x80)
|
||||
FloppyReset();
|
||||
|
||||
// Start motor, select drive
|
||||
FloppyMotor(drive, 1);
|
||||
FloppySelectDrive(drive);
|
||||
|
||||
// Seek to correct location
|
||||
FloppySeek(drive, cyl, head);
|
||||
|
||||
// Start DMA read
|
||||
DmaMaskChannel(2);
|
||||
DmaSetMode(2, 0x46);
|
||||
DmaUnmaskChannel(2);
|
||||
|
||||
FloppyRW(0, drive, head, cyl, sect);
|
||||
|
||||
FloppyMotor(drive, 0);
|
||||
|
||||
return 0x1000;
|
||||
}
|
||||
|
||||
// Log("%#[Drivers] %#Initializing blah blah %d...", ColorWhite, ColorLightGray,PIT_FREQUENCY);
|
86
Kernel/drivers/floppy/floppy.h
Normal file
86
Kernel/drivers/floppy/floppy.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* floppy.h
|
||||
*
|
||||
* Created on: Aug 20, 2011
|
||||
* Author: Tiberiu
|
||||
*/
|
||||
|
||||
#ifndef FLOPPY_H_
|
||||
#define FLOPPY_H_
|
||||
|
||||
#include <types.h>
|
||||
|
||||
enum FloppyRegisters
|
||||
{
|
||||
FloppyRegisterStatusA = 0x3F0, // read-only
|
||||
FloppyRegisterStatusB = 0x3F1, // read-only
|
||||
FloppyRegisterDigitalOutput = 0x3F2,
|
||||
FloppyRegisterTapeDrive = 0x3F3,
|
||||
FloppyRegisterMainStatus = 0x3F4, // read-only
|
||||
FloppyRegisterDatarateSelect = 0x3F4, // write-only
|
||||
FloppyRegisterFIFO = 0x3F5,
|
||||
FloppyRegisterDigitalInput = 0x3F7, // read-only
|
||||
FloppyRegisterConfigurationControl = 0x3F7 // write-only
|
||||
};
|
||||
|
||||
enum FloppyCommands
|
||||
{
|
||||
FloppyCommandReadTrack = 2, // generates IRQ6
|
||||
FloppyCommandSpecify = 3, // * set drive parameters
|
||||
FloppyCommandSenseDriveStatus = 4,
|
||||
FloppyCommandWriteData = 5, // * write to the disk
|
||||
FloppyCommandReadData = 6, // * read from the disk
|
||||
FloppyCommandRecalibrate = 7, // * seek to cylinder 0
|
||||
FloppyCommandSenseInterrupt = 8, // * ack IRQ6, get status of last command
|
||||
FloppyCommandWriteDeletedData = 9,
|
||||
FloppyCommandReadID = 10, // generates IRQ6
|
||||
FloppyCommandReadDeletedData = 12,
|
||||
FloppyCommandFormatTrack = 13, // *
|
||||
FloppyCommandSeek = 15, // * seek both heads to cylinder X
|
||||
FloppyCommandVersion = 16, // * used during initialization, once
|
||||
FloppyCommandScanEqual = 17,
|
||||
FloppyCommandPerpendicularMode = 18, // * used during initialization, once, maybe
|
||||
FloppyCommandConfigure = 19, // * set controller parameters
|
||||
FloppyCommandLock = 20, // * protect controller params from a reset
|
||||
FloppyCommandVerify = 22,
|
||||
FloppyCommandScanLowOrEqual = 25,
|
||||
FloppyCommandScanHighOrEqual = 29,
|
||||
|
||||
FloppyModeMultitrack = 0x80,
|
||||
FloppyModeMagneticEncoding = 0x40, // always set for read/write/verify/format
|
||||
FloppyModeSkip = 0x20
|
||||
};
|
||||
|
||||
enum FloppyMSRMasks
|
||||
{
|
||||
FloppyMsrRQM = 0x80,
|
||||
FloppyMsrDIO = 0x40,
|
||||
FloppyMsrNDMA = 0x20,
|
||||
FloppyMsrBusy = 0x10
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32 Size, SectorsPerTrack, Heads, Tracks;
|
||||
uint8 Gap, DataRate, Spec1, SRT, HLT, HUT;
|
||||
uint32 Spinup, Spindown, InterruptTimeout;
|
||||
string Name;
|
||||
} FloppyType;
|
||||
|
||||
extern void FloppyInitialize();
|
||||
extern void FloppyIrqHandler(_RegsStack32 *r);
|
||||
extern void FloppyWaitIrq();
|
||||
extern void FloppyInitDma();
|
||||
|
||||
extern void FloppyReset();
|
||||
extern void FloppyConfigure();
|
||||
extern void FloppySendCommand (uint8 command);
|
||||
extern uint8 FloppyReadData ();
|
||||
extern void FloppySenseInterrupt(uint8 *st0, uint8 *cyl);
|
||||
extern void FloppySpecify (uint8 fd);
|
||||
extern void FloppyMotor (uint8 fd_number, uint8 status);
|
||||
extern void FloppySelectDrive(uint8 number);
|
||||
extern void FloppyRecalibrate(uint8 fd_number);
|
||||
extern void FloppyRW(uint8 isWrite, uint8 fd_number, uint8 head, uint8 cylinder, uint8 sector);
|
||||
extern uint32 FloppyRead(uint8 drive, uint32 lba);
|
||||
|
||||
#endif /* FLOPPY_H_ */
|
13
Kernel/drivers/pit/pit.c
Normal file
13
Kernel/drivers/pit/pit.c
Normal file
@ -0,0 +1,13 @@
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "pit.h"
|
||||
|
||||
void PitSetFrequency(uint32 frequency)
|
||||
{
|
||||
uint32 divisor = 1193180 / frequency; // Calculate the divisor
|
||||
outportb(0x43, 0x36); // Set our command byte 0x36
|
||||
outportb(0x40, divisor & 0xff); // Set low byte
|
||||
outportb(0x40, divisor>>8); // Set high byte
|
||||
|
||||
TimeSetInternalFrequency(frequency);
|
||||
}
|
7
Kernel/drivers/pit/pit.h
Normal file
7
Kernel/drivers/pit/pit.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef __PIT__H
|
||||
#define __PIT__H
|
||||
|
||||
extern void PitSetFrequency(uint32 frequency);
|
||||
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user