#include <pci/hd.h>
#include <sys/video.h>
#include <sys/drives.h>
#include <sys/io.h>
#include <lib/kmalloc.h>
struct driveInfo *hdd0;
struct driveInfo *hdd1;
struct driveInfo *hdd2;
struct driveInfo *hdd3;
void initHardDisk() {
hdd0 = (struct driveInfo *)kmalloc(sizeof(struct driveInfo),-2);
hdd1 = (struct driveInfo *)kmalloc(sizeof(struct driveInfo),-2);
hdd2 = (struct driveInfo *)kmalloc(sizeof(struct driveInfo),-2);
hdd3 = (struct driveInfo *)kmalloc(sizeof(struct driveInfo),-2);
hdd0->hdPort = 0x1F7;
hdd0->hdDev = 0x40;
hdd1->hdPort = 0x1F7;
hdd1->hdDev = 0x50;
hdd2->hdPort = 0x177;
hdd2->hdDev = 0x40;
hdd3->hdPort = 0x177;
hdd3->hdDev = 0x50;
if (!initDrive(hdd0)) {
addDrive(1,1,hdd0,hdRead,hdWrite,0x0);
}
if (!initDrive(hdd1)) {
addDrive(2,1,hdd1,hdRead,hdWrite,0x0);
}
if (!initDrive(hdd2)) {
addDrive(3,1,hdd2,hdRead,hdWrite,0x0);
}
if (!initDrive(hdd3)) {
addDrive(4,1,hdd3,hdRead,hdWrite,0x0);
}
return;
}
int initDrive(struct driveInfo *hdd) {
char retVal = 0x0;
long counter = 0x0;
short *tmp = 0x0;
for (counter = 1000000;counter >= 0;counter--) {
retVal = inportByte(hdd->hdPort) & 0x80;
if (!retVal) goto ready;
}
kprintf("Error Initializing Drive\n");
return(1);
ready:
hdd->hdPort--;
outportByte(hdd->hdPort,hdd->hdDev);
hdd->hdPort++;
outportByte(hdd->hdPort,0xEC);
for (counter = 1000000;counter >= 0;counter--) {
retVal = inportByte(hdd->hdPort);
if ((retVal & 1) != 0x0) {
kprintf("Error Drive Not Available\n");
return(1);
}
if ((retVal & 8) != 0x0) {
goto go;
}
}
kprintf("Time Out Waiting On Drive\n");
return(1);
go:
hdd->hdPort -= 7;
tmp = (short *)hdd->hdSector;
for (counter = 0;counter < (512/2);counter++) {
tmp[counter] = inportWord(hdd->hdPort);
}
retVal = hdd->hdSector[0x5E] & 127;
switch (retVal) {
case 0:
hdd->hdShift = 3;
hdd->hdMulti = 8;
case 2:
hdd->hdShift = 1;
hdd->hdMulti = retVal;
break;
case 4:
hdd->hdShift = 2;
hdd->hdMulti = retVal;
break;
case 8:
hdd->hdShift = 3;
hdd->hdMulti = retVal;
break;
case 16:
hdd->hdShift = 4;
hdd->hdMulti = retVal;
break;
case 32:
hdd->hdShift = 5;
hdd->hdMulti = retVal;
break;
case 64:
hdd->hdShift = 6;
hdd->hdMulti = retVal;
break;
default:
kprintf("Error BLOCK Mode Unavailable: [%i]\n",retVal);
return(1);
}
hdd->hdPort += 2;
outportByte(hdd->hdPort,retVal);
hdd->hdPort += 4;
outportByte(hdd->hdPort,hdd->hdDev);
hdd->hdPort++;
outportByte(hdd->hdPort,0xC6);
//retVal--; //I'm Not Sure Why He Was Doing This
hdd->hdMask = retVal;
hdd->hdSize = (hdd->hdSector[0x7B] * 256 * 256 * 256) + (hdd->hdSector[0x7A] * 256 * 256) + (hdd->hdSector[0x79] * 256) + hdd->hdSector[0x78];
hdd->hdEnable = 1;
kprintf("Drive: [0x%X/0x%X], Size: [%iSectors/%iKBytes]\n",hdd->hdPort,hdd->hdDev,hdd->hdSize,((hdd->hdSize*512)/1024));
return(0);
}
void hdWrite(struct driveInfo *hdd,long startSector,long sectorCount,void *baseAddr) {
long counter = 0x0;
long retVal = 0x0;
short transactionCount = 0x0;
short *tmp = (short *)baseAddr;
if (hdd->hdEnable == 0x0) {
kprintf("Invalid Drive\n");
return;
}
if ((sectorCount >> hdd->hdShift) == 0x0) {
hdd->hdCalc = sectorCount; //hdd->hdMask;
transactionCount = 1;
}
else {
hdd->hdCalc = hdd->hdMulti;
transactionCount = sectorCount >> hdd->hdShift;
}
for (;transactionCount > 0;transactionCount--) {
for (counter = 1000000;counter >= 0;counter--) {
retVal = inportByte(hdd->hdPort) & 0x80;
if (!retVal) goto ready;
}
kprintf("Time Out Waiting On Drive\n");
return;
ready:
hdd->hdPort -= 5;
outportByte(hdd->hdPort,hdd->hdCalc);
hdd->hdPort++;
outportByte(hdd->hdPort,(startSector & 0xFF));
hdd->hdPort++;
retVal = startSector >> 8;
outportByte(hdd->hdPort,(retVal & 0xFF));
hdd->hdPort++;
retVal >>= 8;
outportByte(hdd->hdPort,(retVal & 0xFF));
hdd->hdPort++;
retVal >>= 8;
retVal &= 0x0F;
retVal |= hdd->hdDev;
outportByte(hdd->hdPort,(retVal & 0xFF));
hdd->hdPort++;
outportByte(hdd->hdPort,0xC5);
for (counter = 1000000;counter >= 0;counter--) {
retVal = inportByte(hdd->hdPort);
if ((retVal & 1) != 0x0) {
kprintf("HD Write Error\n");
return;
}
if ((retVal & 8) != 0x0) {
goto go;
}
}
kprintf("Time Out Waiting On Drive\n");
return;
go:
hdd->hdPort -= 7;
for (counter = 0;counter < (hdd->hdCalc << 8);counter++) {
outportWord(hdd->hdPort,tmp[counter]);
}
hdd->hdPort += 7;
startSector += hdd->hdCalc;
}
return;
}
void hdRead(struct driveInfo *hdd,long startSector,long sectorCount,void *baseAddr) {
long counter = 0x0;
long retVal = 0x0;
short transactionCount = 0x0;
short *tmp = (short *)baseAddr;
kprintf("Moo\n");
if (hdd->hdEnable == 0x0) {
kprintf("Invalid Drive\n");
return;
}
if ((sectorCount >> hdd->hdShift) == 0x0) {
hdd->hdCalc = sectorCount;//(hdd->hdMask);
transactionCount = 1;
}
else {
hdd->hdCalc = hdd->hdMulti;
transactionCount = sectorCount >> hdd->hdShift;
}
for (;transactionCount > 0;transactionCount--) {
for (counter = 1000000;counter >= 0;counter--) {
retVal = inportByte(hdd->hdPort) & 0x80;
if (!retVal) goto ready;
}
kprintf("Time Out Waiting On Drive\n");
return;
ready:
hdd->hdPort -= 5;
outportByte(hdd->hdPort,hdd->hdCalc);
hdd->hdPort++;
outportByte(hdd->hdPort,(startSector & 0xFF));
hdd->hdPort++;
retVal = startSector >> 8;
outportByte(hdd->hdPort,(retVal & 0xFF));
hdd->hdPort++;
retVal >>= 8;
outportByte(hdd->hdPort,(retVal & 0xFF));
hdd->hdPort++;
retVal >>= 8;
retVal &= 0x0F;
retVal |= hdd->hdDev;
outportByte(hdd->hdPort,(retVal & 0xFF));
hdd->hdPort++;
outportByte(hdd->hdPort,0xC4);
for (counter = 1000000;counter >= 0;counter--) {
retVal = inportByte(hdd->hdPort);
if ((retVal & 1) != 0x0) {
kprintf("HD Write Error\n");
return;
}
if ((retVal & 8) != 0x0) {
goto go;
}
}
kprintf("Time Out Waiting On Drive\n");
return;
go:
hdd->hdPort -= 7;
for (counter = 0;counter < (hdd->hdCalc << 8);counter++) {
tmp[counter] = inportWord(hdd->hdPort);
}
hdd->hdPort += 7;
startSector += hdd->hdCalc;
}
return;
}