From b8b91d3e33a1706c9270d8d396d04d86af50b865 Mon Sep 17 00:00:00 2001 From: Ali Mashtizadeh Date: Fri, 25 Jul 2014 01:43:23 -0700 Subject: [PATCH] Cleanup and locking for the IDE driver. --- sys/amd64/critical.c | 1 + sys/dev/console.c | 3 +- sys/dev/x86/ide.c | 72 ++++++++++++++++++++++++------------------ sys/include/spinlock.h | 1 + sys/kern/spinlock.c | 6 ++++ 5 files changed, 51 insertions(+), 32 deletions(-) diff --git a/sys/amd64/critical.c b/sys/amd64/critical.c index 2cf1f30..0a79e37 100644 --- a/sys/amd64/critical.c +++ b/sys/amd64/critical.c @@ -1,4 +1,5 @@ +#include #include #include diff --git a/sys/dev/console.c b/sys/dev/console.c index 0c6b371..8272f8d 100644 --- a/sys/dev/console.c +++ b/sys/dev/console.c @@ -1,4 +1,5 @@ +#include #include #include @@ -23,7 +24,7 @@ Console_Init() Console_Puts("Castor Operating System\n"); - Spinlock_Init(&consoleLock, "Console"); + Spinlock_Init(&consoleLock, "Console Lock"); } /* diff --git a/sys/dev/x86/ide.c b/sys/dev/x86/ide.c index d6ab76a..2f2ee33 100644 --- a/sys/dev/x86/ide.c +++ b/sys/dev/x86/ide.c @@ -5,6 +5,7 @@ #include #include +#include #include #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); diff --git a/sys/include/spinlock.h b/sys/include/spinlock.h index 85606ec..495879a 100644 --- a/sys/include/spinlock.h +++ b/sys/include/spinlock.h @@ -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__ */ diff --git a/sys/kern/spinlock.c b/sys/kern/spinlock.c index 1835df3..93fb38f 100644 --- a/sys/kern/spinlock.c +++ b/sys/kern/spinlock.c @@ -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[]) {