Cleanup and locking for the IDE driver.

This commit is contained in:
Ali Mashtizadeh 2014-07-25 01:43:23 -07:00
parent ff2be2e406
commit b8b91d3e33
5 changed files with 51 additions and 32 deletions

View File

@ -1,4 +1,5 @@
#include <stdbool.h>
#include <stdint.h>
#include <sys/kassert.h>

View File

@ -1,4 +1,5 @@
#include <stdbool.h>
#include <stdint.h>
#include <sys/spinlock.h>
@ -23,7 +24,7 @@ Console_Init()
Console_Puts("Castor Operating System\n");
Spinlock_Init(&consoleLock, "Console");
Spinlock_Init(&consoleLock, "Console Lock");
}
/*

View File

@ -5,6 +5,7 @@
#include <sys/kassert.h>
#include <sys/kmem.h>
#include <sys/spinlock.h>
#include <sys/disk.h>
#include "ioport.h"
@ -57,6 +58,7 @@ typedef struct IDE
{
uint16_t base; // Base Port
uint16_t devctl; // Device Control
Spinlock lock;
} IDE;
typedef struct IDEDrive
@ -75,23 +77,26 @@ int IDE_Write(Disk *disk, void *buf, SGArray *sga, DiskCB, void *arg);
int IDE_Flush(Disk *disk, void *buf, SGArray *sga, DiskCB, void *arg);
int IDE_ReadOne(IDEDrive *drive, void *buf, uint64_t off, uint64_t len);
IDE primary;
IDEDrive primaryDrives[2];
void
IDE_Init()
{
IDE ide;
ASSERT(sizeof(ATAIdentifyDevice) == 512);
ide.base = IDE_PRIMARY_BASE;
ide.devctl = IDE_PRIMARY_DEVCTL;
primary.base = IDE_PRIMARY_BASE;
primary.devctl = IDE_PRIMARY_DEVCTL;
Spinlock_Init(&primary.lock, "IDE Primary Controller Lock");
if (!IDE_HasController(&ide)) {
if (!IDE_HasController(&primary)) {
kprintf("IDE: No controller detected\n");
return;
}
IDE_Reset(&ide);
IDE_Identify(&ide, 0);
IDE_Identify(&ide, 1);
IDE_Reset(&primary);
IDE_Identify(&primary, 0);
IDE_Identify(&primary, 1);
}
bool
@ -207,13 +212,18 @@ IDE_Identify(IDE *ide, int drive)
kprintf("IDE: Drive %d %llu Sectors (%llu MBs)\n",
drive, ident.lbaSectors, ident.lbaSectors / 2048ULL);
primaryDrives[drive].ide = &primary;
primaryDrives[drive].drive = drive;
primaryDrives[drive].lba48 = (ident.lbaSectors > (1 << 24));
primaryDrives[drive].size = ident.lbaSectors;
// Register Disk
Disk *disk = PAlloc_AllocPage();
if (!disk) {
Panic("IDE: No memory!\n");
}
disk->handle = 0;
disk->handle = &primaryDrives[drive];
disk->ctrlNo = 0;
disk->diskNo = drive;
disk->sectorSize = IDE_SECTOR_SIZE;
@ -231,6 +241,8 @@ IDEWaitForBusy(IDE *ide)
{
uint8_t status;
ASSERT(Spinlock_IsHeld(&ide->lock));
while (1) {
status = inb(ide->base + IDE_STATUS);
if ((status & IDE_STATUS_BSY) == 0)
@ -245,21 +257,15 @@ IDE_Read(Disk *disk, void *buf, SGArray *sga, DiskCB cb, void *arg)
{
int i;
int status;
IDE ide;
IDEDrive idedrive;
IDEDrive *idedrive;
ide.base = IDE_PRIMARY_BASE;
ide.devctl = IDE_PRIMARY_DEVCTL;
idedrive.ide = &ide;
idedrive.drive = disk->diskNo;
idedrive.lba48 = true;
idedrive.size = disk->sectorCount;
idedrive = disk->handle;
for (i = 0; i < sga->len; i++) {
status = IDE_ReadOne(&idedrive,
status = IDE_ReadOne(idedrive,
buf,
sga->entries[i].offset,
sga->entries[i].length / disk->sectorSize);
sga->entries[i].length / 512);
buf += sga->entries[i].offset;
if (status < 0)
return status;
@ -278,25 +284,23 @@ int
IDE_Flush(Disk *disk, void *buf, SGArray *sga, DiskCB cb, void *arg)
{
uint8_t driveCode;
IDE ide;
IDEDrive idedrive;
IDE *ide;
IDEDrive *idedrive;
ide.base = IDE_PRIMARY_BASE;
ide.devctl = IDE_PRIMARY_DEVCTL;
idedrive.ide = &ide;
idedrive.drive = disk->diskNo;
idedrive.lba48 = true;
idedrive.size = disk->sectorCount;
idedrive = disk->handle;
ide = idedrive->ide;
if (idedrive.drive == 0)
if (idedrive->drive == 0)
driveCode = 0xA0;
else
driveCode = 0xB0;
outb(ide.base + IDE_DRIVE, driveCode);
outb(ide.base + IDE_COMMAND, IDE_CMD_FLUSH);
Spinlock_Lock(&ide->lock);
outb(ide->base + IDE_DRIVE, driveCode);
outb(ide->base + IDE_COMMAND, IDE_CMD_FLUSH);
IDEWaitForBusy(&ide);
IDEWaitForBusy(ide);
Spinlock_Unlock(&ide->lock);
return 0;
}
@ -320,6 +324,7 @@ IDE_ReadOne(IDEDrive *drive, void *buf, uint64_t off, uint64_t len)
ASSERT(len < 0x10000);
Spinlock_Lock(&ide->lock);
outb(ide->base + IDE_DRIVE, driveCode);
if (lba48) {
outb(ide->base + IDE_SECTORCOUNT, len >> 8);
@ -339,6 +344,7 @@ IDE_ReadOne(IDEDrive *drive, void *buf, uint64_t off, uint64_t len)
status = IDEWaitForBusy(ide);
if ((status & IDE_STATUS_ERR) != 0) {
Spinlock_Unlock(&ide->lock);
kprintf("IDE: Error trying read from drive %d\n", drive->drive);
return -1;
}
@ -349,6 +355,7 @@ IDE_ReadOne(IDEDrive *drive, void *buf, uint64_t off, uint64_t len)
uint8_t *b = buf + sectors * IDE_SECTOR_SIZE;
insw(ide->base, b, 256);
}
Spinlock_Unlock(&ide->lock);
return 0;
}
@ -370,6 +377,7 @@ IDE_WriteOne(IDEDrive *drive, void *buf, uint64_t off, uint64_t len)
ASSERT(len < 0x10000);
Spinlock_Lock(&ide->lock);
outb(ide->base + IDE_DRIVE, driveCode);
outb(ide->base + IDE_SECTORCOUNT, len >> 8);
outb(ide->base + IDE_LBALOW, off >> 24);
@ -389,9 +397,11 @@ IDE_WriteOne(IDEDrive *drive, void *buf, uint64_t off, uint64_t len)
}
if ((status & IDE_STATUS_ERR) != 0) {
Spinlock_Unlock(&ide->lock);
kprintf("IDE: Error trying write from drive %d\n", drive);
return;
}
Spinlock_Unlock(&ide->lock);
// XXX: Loop on outw(ide->base, b + sectorOffset);

View File

@ -25,6 +25,7 @@ void Spinlock_Init(Spinlock *lock, const char *name);
void Spinlock_Destroy(Spinlock *lock);
void Spinlock_Lock(Spinlock *lock);
void Spinlock_Unlock(Spinlock *lock);
bool Spinlock_IsHeld(Spinlock *lock);
#endif /* __SPINLOCK_H__ */

View File

@ -67,6 +67,12 @@ Spinlock_Unlock(Spinlock *lock)
Critical_Exit();
}
bool
Spinlock_IsHeld(Spinlock *lock)
{
return (lock->cpu == CPU()) && (lock->lock == 1);
}
void
Debug_Spinlocks(int argc, const char *argv[])
{