mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 19:22:45 +00:00 
			
		
		
		
	Merge Disk namespace into the IDEDiskDevice class.
This commit is contained in:
		
							parent
							
								
									cba05ce75e
								
							
						
					
					
						commit
						b8264e7d47
					
				
					 10 changed files with 231 additions and 244 deletions
				
			
		|  | @ -1,5 +1,6 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include "Assertions.h" | ||||||
| #include "Types.h" | #include "Types.h" | ||||||
| 
 | 
 | ||||||
| #ifdef SERENITY | #ifdef SERENITY | ||||||
|  |  | ||||||
							
								
								
									
										194
									
								
								Kernel/Disk.cpp
									
										
									
									
									
								
							
							
						
						
									
										194
									
								
								Kernel/Disk.cpp
									
										
									
									
									
								
							|  | @ -1,194 +0,0 @@ | ||||||
| #include "types.h" |  | ||||||
| #include "Process.h" |  | ||||||
| #include "VGA.h" |  | ||||||
| #include "Disk.h" |  | ||||||
| #include "kmalloc.h" |  | ||||||
| #include "StdLib.h" |  | ||||||
| #include "IO.h" |  | ||||||
| #include "i386.h" |  | ||||||
| #include "PIC.h" |  | ||||||
| #include <AK/Lock.h> |  | ||||||
| 
 |  | ||||||
| //#define DISK_DEBUG
 |  | ||||||
| 
 |  | ||||||
| extern "C" void handle_interrupt(); |  | ||||||
| 
 |  | ||||||
| namespace Disk { |  | ||||||
| 
 |  | ||||||
| ide_drive_t drive[4]; |  | ||||||
| static volatile bool interrupted; |  | ||||||
| 
 |  | ||||||
| #define IRQ_FIXED_DISK           14 |  | ||||||
| 
 |  | ||||||
| extern "C" void ide_ISR(); |  | ||||||
| 
 |  | ||||||
| asm( |  | ||||||
|     ".globl ide_ISR \n" |  | ||||||
|     "ide_ISR: \n" |  | ||||||
|     "    pusha\n" |  | ||||||
|     "    pushw %ds\n" |  | ||||||
|     "    pushw %es\n" |  | ||||||
|     "    pushw %ss\n" |  | ||||||
|     "    pushw %ss\n" |  | ||||||
|     "    popw %ds\n" |  | ||||||
|     "    popw %es\n" |  | ||||||
|     "    call handle_interrupt\n" |  | ||||||
|     "    popw %es\n" |  | ||||||
|     "    popw %ds\n" |  | ||||||
|     "    popa\n" |  | ||||||
|     "    iret\n" |  | ||||||
| ); |  | ||||||
| 
 |  | ||||||
| static void enableIRQ() |  | ||||||
| { |  | ||||||
|     PIC::enable(IRQ_FIXED_DISK); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void disableIRQ() |  | ||||||
| { |  | ||||||
|     PIC::disable(IRQ_FIXED_DISK); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool waitForInterrupt() |  | ||||||
| { |  | ||||||
| #ifdef DISK_DEBUG |  | ||||||
|     kprintf("disk: waiting for interrupt...\n"); |  | ||||||
| #endif |  | ||||||
|     // FIXME: Add timeout.
 |  | ||||||
|     while (!interrupted) { |  | ||||||
|         sched_yield(); |  | ||||||
|     } |  | ||||||
| #ifdef DISK_DEBUG |  | ||||||
|     kprintf("disk: got interrupt!\n"); |  | ||||||
| #endif |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void interrupt() |  | ||||||
| { |  | ||||||
|     IRQHandlerScope scope(IRQ_FIXED_DISK); |  | ||||||
| #ifdef DISK_DEBUG |  | ||||||
|     BYTE status = IO::in8(0x1f7); |  | ||||||
|     kprintf("disk:interrupt: DRQ=%u BUSY=%u DRDY=%u\n", (status & DRQ) != 0, (status & BUSY) != 0, (status & DRDY) != 0); |  | ||||||
| #endif |  | ||||||
|     interrupted = true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static SpinLock* s_diskLock; |  | ||||||
| 
 |  | ||||||
| void initialize() |  | ||||||
| { |  | ||||||
|     s_diskLock = new SpinLock; |  | ||||||
|     disableIRQ(); |  | ||||||
|     interrupted = false; |  | ||||||
|     registerInterruptHandler(IRQ_VECTOR_BASE + IRQ_FIXED_DISK, ide_ISR); |  | ||||||
| 
 |  | ||||||
|     while (IO::in8(IDE0_STATUS) & BUSY); |  | ||||||
| 
 |  | ||||||
|     IO::out8(0x1F6, 0xA0); // 0xB0 for 2nd device
 |  | ||||||
|     IO::out8(IDE0_COMMAND, IDENTIFY_DRIVE); |  | ||||||
| 
 |  | ||||||
|     enableIRQ(); |  | ||||||
|     waitForInterrupt(); |  | ||||||
| 
 |  | ||||||
|     ByteBuffer wbuf = ByteBuffer::createUninitialized(512); |  | ||||||
|     ByteBuffer bbuf = ByteBuffer::createUninitialized(512); |  | ||||||
|     BYTE* b = bbuf.pointer(); |  | ||||||
|     WORD* w = (WORD*)wbuf.pointer(); |  | ||||||
|     const WORD* wbufbase = (WORD*)wbuf.pointer(); |  | ||||||
| 
 |  | ||||||
|     for (DWORD i = 0; i < 256; ++i) { |  | ||||||
|         WORD data = IO::in16(IDE0_DATA); |  | ||||||
|         *(w++) = data; |  | ||||||
|         *(b++) = MSB(data); |  | ||||||
|         *(b++) = LSB(data); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // "Unpad" the device name string.
 |  | ||||||
|     for (DWORD i = 93; i > 54 && bbuf[i] == ' '; --i) |  | ||||||
|         bbuf[i] = 0; |  | ||||||
| 
 |  | ||||||
|     drive[0].cylinders = wbufbase[1]; |  | ||||||
|     drive[0].heads = wbufbase[3]; |  | ||||||
|     drive[0].sectors_per_track = wbufbase[6]; |  | ||||||
| 
 |  | ||||||
|     kprintf( |  | ||||||
|         "ide0: Master=\"%s\", C/H/Spt=%u/%u/%u\n", |  | ||||||
|         bbuf.pointer() + 54, |  | ||||||
|         drive[0].cylinders, |  | ||||||
|         drive[0].heads, |  | ||||||
|         drive[0].sectors_per_track |  | ||||||
|     ); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct CHS { |  | ||||||
|     DWORD cylinder; |  | ||||||
|     WORD head; |  | ||||||
|     WORD sector; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static CHS lba2chs(BYTE drive_index, DWORD lba) |  | ||||||
| { |  | ||||||
|     ide_drive_t& d = drive[drive_index]; |  | ||||||
|     CHS chs; |  | ||||||
|     chs.cylinder = lba / (d.sectors_per_track * d.heads); |  | ||||||
|     chs.head = (lba / d.sectors_per_track) % d.heads; |  | ||||||
|     chs.sector = (lba % d.sectors_per_track) + 1; |  | ||||||
|     return chs; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool readSectors(DWORD startSector, WORD count, BYTE* outbuf) |  | ||||||
| { |  | ||||||
|     LOCKER(*s_diskLock); |  | ||||||
| #ifdef DISK_DEBUG |  | ||||||
|     kprintf("%s: Disk::readSectors request (%u sector(s) @ %u)\n", |  | ||||||
|             current->name().characters(), |  | ||||||
|             count, |  | ||||||
|             startSector); |  | ||||||
| #endif |  | ||||||
|     disableIRQ(); |  | ||||||
| 
 |  | ||||||
|     CHS chs = lba2chs(IDE0_DISK0, startSector); |  | ||||||
| 
 |  | ||||||
|     while (IO::in8(IDE0_STATUS) & BUSY); |  | ||||||
| 
 |  | ||||||
| #ifdef DISK_DEBUG |  | ||||||
|     kprintf("ide0: Reading %u sector(s) @ LBA %u (%u/%u/%u)\n", count, startSector, chs.cylinder, chs.head, chs.sector); |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|     IO::out8(0x1F2, count == 256 ? 0 : LSB(count)); |  | ||||||
|     IO::out8(0x1F3, chs.sector); |  | ||||||
|     IO::out8(0x1F4, LSB(chs.cylinder)); |  | ||||||
|     IO::out8(0x1F5, MSB(chs.cylinder)); |  | ||||||
| 
 |  | ||||||
|     IO::out8(0x1F6, 0xA0 | chs.head); /* 0xB0 for 2nd device */ |  | ||||||
| 
 |  | ||||||
|     IO::out8(0x3F6, 0x08); |  | ||||||
|     while (!(IO::in8(IDE0_STATUS) & DRDY)); |  | ||||||
| 
 |  | ||||||
|     IO::out8(IDE0_COMMAND, READ_SECTORS); |  | ||||||
|     interrupted = false; |  | ||||||
|     enableIRQ(); |  | ||||||
|     waitForInterrupt(); |  | ||||||
| 
 |  | ||||||
|     BYTE status = IO::in8(0x1f7); |  | ||||||
|     if (status & DRQ) { |  | ||||||
| #ifdef DISK_DEBUG |  | ||||||
|         kprintf("Retrieving %u bytes (status=%b), outbuf=%p...\n", count * 512, status, outbuf); |  | ||||||
| #endif |  | ||||||
|         for (DWORD i = 0; i < (count * 512); i += 2) { |  | ||||||
|             WORD w = IO::in16(IDE0_DATA); |  | ||||||
|             outbuf[i] = LSB(w); |  | ||||||
|             outbuf[i+1] = MSB(w); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| extern "C" void handle_interrupt() |  | ||||||
| { |  | ||||||
|     Disk::interrupt(); |  | ||||||
| } |  | ||||||
|  | @ -1,34 +0,0 @@ | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include "types.h" |  | ||||||
| 
 |  | ||||||
| #define IDE0_DATA        0x1F0 |  | ||||||
| #define IDE0_STATUS      0x1F7 |  | ||||||
| #define IDE0_COMMAND     0x1F7 |  | ||||||
| #define BUSY             0x80 |  | ||||||
| #define DRDY             0x40 |  | ||||||
| #define DRQ              0x08 |  | ||||||
| #define IDENTIFY_DRIVE   0xEC |  | ||||||
| #define READ_SECTORS     0x21 |  | ||||||
| 
 |  | ||||||
| #define IDE0_DISK0       0 |  | ||||||
| #define IDE0_DISK1       1 |  | ||||||
| #define IDE1_DISK0       2 |  | ||||||
| #define IDE1_DISK1       3 |  | ||||||
| 
 |  | ||||||
| typedef struct |  | ||||||
| { |  | ||||||
|     WORD cylinders; |  | ||||||
|     WORD heads; |  | ||||||
|     WORD sectors_per_track; |  | ||||||
| } ide_drive_t; |  | ||||||
| 
 |  | ||||||
| extern void ide_init(); |  | ||||||
| extern ide_drive_t drive[4]; |  | ||||||
| 
 |  | ||||||
| namespace Disk { |  | ||||||
| 
 |  | ||||||
| void initialize(); |  | ||||||
| bool readSectors(DWORD sectorIndex, WORD count, BYTE* buffer); |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
|  | @ -1,5 +1,35 @@ | ||||||
| #include "IDEDiskDevice.h" | #include "IDEDiskDevice.h" | ||||||
| #include "Disk.h" | #include "types.h" | ||||||
|  | #include "Process.h" | ||||||
|  | #include "StdLib.h" | ||||||
|  | #include "IO.h" | ||||||
|  | #include "Scheduler.h" | ||||||
|  | #include "PIC.h" | ||||||
|  | #include <AK/Lock.h> | ||||||
|  | 
 | ||||||
|  | //#define DISK_DEBUG
 | ||||||
|  | 
 | ||||||
|  | #define IRQ_FIXED_DISK 14 | ||||||
|  | 
 | ||||||
|  | #define IDE0_DATA        0x1F0 | ||||||
|  | #define IDE0_STATUS      0x1F7 | ||||||
|  | #define IDE0_COMMAND     0x1F7 | ||||||
|  | 
 | ||||||
|  | enum IDECommand : byte { | ||||||
|  |     IDENTIFY_DRIVE = 0xEC, | ||||||
|  |     READ_SECTORS = 0x21, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | enum IDEStatus : byte { | ||||||
|  |     BUSY = (1 << 7), | ||||||
|  |     DRDY = (1 << 6), | ||||||
|  |     DF   = (1 << 5), | ||||||
|  |     SRV  = (1 << 4), | ||||||
|  |     DRQ  = (1 << 3), | ||||||
|  |     CORR = (1 << 2), | ||||||
|  |     IDX  = (1 << 1), | ||||||
|  |     ERR  = (1 << 0), | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| RetainPtr<IDEDiskDevice> IDEDiskDevice::create() | RetainPtr<IDEDiskDevice> IDEDiskDevice::create() | ||||||
| { | { | ||||||
|  | @ -7,7 +37,9 @@ RetainPtr<IDEDiskDevice> IDEDiskDevice::create() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| IDEDiskDevice::IDEDiskDevice() | IDEDiskDevice::IDEDiskDevice() | ||||||
|  |     : IRQHandler(IRQ_FIXED_DISK) | ||||||
| { | { | ||||||
|  |     initialize(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| IDEDiskDevice::~IDEDiskDevice() | IDEDiskDevice::~IDEDiskDevice() | ||||||
|  | @ -26,7 +58,7 @@ unsigned IDEDiskDevice::blockSize() const | ||||||
| 
 | 
 | ||||||
| bool IDEDiskDevice::readBlock(unsigned index, byte* out) const | bool IDEDiskDevice::readBlock(unsigned index, byte* out) const | ||||||
| { | { | ||||||
|     Disk::readSectors(index, 1, out); |     const_cast<IDEDiskDevice&>(*this).read_sectors(index, 1, out); | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -39,3 +71,153 @@ bool IDEDiskDevice::writeBlock(unsigned index, const byte* data) | ||||||
|     return false; |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #ifdef DISK_DEBUG | ||||||
|  | static void print_ide_status(byte status) | ||||||
|  | { | ||||||
|  |     kprintf("DRQ=%u BUSY=%u DRDY=%u SRV=%u DF=%u CORR=%u IDX=%u ERR=%u\n", | ||||||
|  |             (status & DRQ) != 0, | ||||||
|  |             (status & BUSY) != 0, | ||||||
|  |             (status & DRDY) != 0, | ||||||
|  |             (status & SRV) != 0, | ||||||
|  |             (status & DF) != 0, | ||||||
|  |             (status & CORR) != 0, | ||||||
|  |             (status & IDX) != 0, | ||||||
|  |             (status & ERR) != 0); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | bool IDEDiskDevice::wait_for_irq() | ||||||
|  | { | ||||||
|  | #ifdef DISK_DEBUG | ||||||
|  |     kprintf("disk: waiting for interrupt...\n"); | ||||||
|  | #endif | ||||||
|  |     // FIXME: Add timeout.
 | ||||||
|  |     while (!m_interrupted) { | ||||||
|  |         // FIXME: Put this process into a Blocked state instead, it's stupid to wake up just to check a flag.
 | ||||||
|  |         Scheduler::yield(); | ||||||
|  |     } | ||||||
|  | #ifdef DISK_DEBUG | ||||||
|  |     kprintf("disk: got interrupt!\n"); | ||||||
|  | #endif | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IDEDiskDevice::handleIRQ() | ||||||
|  | { | ||||||
|  | #ifdef DISK_DEBUG | ||||||
|  |     byte status = IO::in8(0x1f7); | ||||||
|  |     kprintf("disk:interrupt: DRQ=%u BUSY=%u DRDY=%u\n", (status & DRQ) != 0, (status & BUSY) != 0, (status & DRDY) != 0); | ||||||
|  | #endif | ||||||
|  |     m_interrupted = true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IDEDiskDevice::initialize() | ||||||
|  | { | ||||||
|  |     byte status; | ||||||
|  | 
 | ||||||
|  |     status = IO::in8(IDE0_STATUS); | ||||||
|  | #ifdef DISK_DEBUG | ||||||
|  |     kprintf("initial status: "); | ||||||
|  |     print_ide_status(status); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |     m_interrupted = false; | ||||||
|  | 
 | ||||||
|  |     while (IO::in8(IDE0_STATUS) & BUSY); | ||||||
|  | 
 | ||||||
|  |     enableIRQ(); | ||||||
|  | 
 | ||||||
|  |     IO::out8(0x1F6, 0xA0); // 0xB0 for 2nd device
 | ||||||
|  |     IO::out8(0x3F6, 0xA0); // 0xB0 for 2nd device
 | ||||||
|  |     IO::out8(IDE0_COMMAND, IDENTIFY_DRIVE); | ||||||
|  | 
 | ||||||
|  |     enableIRQ(); | ||||||
|  |     wait_for_irq(); | ||||||
|  | 
 | ||||||
|  |     ByteBuffer wbuf = ByteBuffer::createUninitialized(512); | ||||||
|  |     ByteBuffer bbuf = ByteBuffer::createUninitialized(512); | ||||||
|  |     byte* b = bbuf.pointer(); | ||||||
|  |     word* w = (word*)wbuf.pointer(); | ||||||
|  |     const word* wbufbase = (word*)wbuf.pointer(); | ||||||
|  | 
 | ||||||
|  |     for (dword i = 0; i < 256; ++i) { | ||||||
|  |         word data = IO::in16(IDE0_DATA); | ||||||
|  |         *(w++) = data; | ||||||
|  |         *(b++) = MSB(data); | ||||||
|  |         *(b++) = LSB(data); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // "Unpad" the device name string.
 | ||||||
|  |     for (dword i = 93; i > 54 && bbuf[i] == ' '; --i) | ||||||
|  |         bbuf[i] = 0; | ||||||
|  | 
 | ||||||
|  |     m_cylinders = wbufbase[1]; | ||||||
|  |     m_heads = wbufbase[3]; | ||||||
|  |     m_sectors_per_track = wbufbase[6]; | ||||||
|  | 
 | ||||||
|  |     kprintf( | ||||||
|  |         "ide0: Master=\"%s\", C/H/Spt=%u/%u/%u\n", | ||||||
|  |         bbuf.pointer() + 54, | ||||||
|  |         m_cylinders, | ||||||
|  |         m_heads, | ||||||
|  |         m_sectors_per_track | ||||||
|  |     ); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | IDEDiskDevice::CHS IDEDiskDevice::lba_to_chs(dword lba) const | ||||||
|  | { | ||||||
|  |     CHS chs; | ||||||
|  |     chs.cylinder = lba / (m_sectors_per_track * m_heads); | ||||||
|  |     chs.head = (lba / m_sectors_per_track) % m_heads; | ||||||
|  |     chs.sector = (lba % m_sectors_per_track) + 1; | ||||||
|  |     return chs; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool IDEDiskDevice::read_sectors(dword start_sector, word count, byte* outbuf) | ||||||
|  | { | ||||||
|  |     LOCKER(m_lock); | ||||||
|  | #ifdef DISK_DEBUG | ||||||
|  |     kprintf("%s: Disk::read_sectors request (%u sector(s) @ %u)\n", | ||||||
|  |             current->name().characters(), | ||||||
|  |             count, | ||||||
|  |             start_sector); | ||||||
|  | #endif | ||||||
|  |     disableIRQ(); | ||||||
|  | 
 | ||||||
|  |     auto chs = lba_to_chs(start_sector); | ||||||
|  | 
 | ||||||
|  |     while (IO::in8(IDE0_STATUS) & BUSY); | ||||||
|  | 
 | ||||||
|  | #ifdef DISK_DEBUG | ||||||
|  |     kprintf("ide0: Reading %u sector(s) @ LBA %u (%u/%u/%u)\n", count, start_sector, chs.cylinder, chs.head, chs.sector); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |     IO::out8(0x1F2, count == 256 ? 0 : LSB(count)); | ||||||
|  |     IO::out8(0x1F3, chs.sector); | ||||||
|  |     IO::out8(0x1F4, LSB(chs.cylinder)); | ||||||
|  |     IO::out8(0x1F5, MSB(chs.cylinder)); | ||||||
|  | 
 | ||||||
|  |     IO::out8(0x1F6, 0xA0 | chs.head); /* 0xB0 for 2nd device */ | ||||||
|  | 
 | ||||||
|  |     IO::out8(0x3F6, 0x08); | ||||||
|  |     while (!(IO::in8(IDE0_STATUS) & DRDY)); | ||||||
|  | 
 | ||||||
|  |     IO::out8(IDE0_COMMAND, READ_SECTORS); | ||||||
|  |     m_interrupted = false; | ||||||
|  |     enableIRQ(); | ||||||
|  |     wait_for_irq(); | ||||||
|  | 
 | ||||||
|  |     byte status = IO::in8(0x1f7); | ||||||
|  |     if (status & DRQ) { | ||||||
|  | #ifdef DISK_DEBUG | ||||||
|  |         kprintf("Retrieving %u bytes (status=%b), outbuf=%p...\n", count * 512, status, outbuf); | ||||||
|  | #endif | ||||||
|  |         for (dword i = 0; i < (count * 512); i += 2) { | ||||||
|  |             word w = IO::in16(IDE0_DATA); | ||||||
|  |             outbuf[i] = LSB(w); | ||||||
|  |             outbuf[i+1] = MSB(w); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -1,13 +1,16 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include <AK/Lock.h> | ||||||
| #include <AK/RetainPtr.h> | #include <AK/RetainPtr.h> | ||||||
| #include <VirtualFileSystem/DiskDevice.h> | #include <VirtualFileSystem/DiskDevice.h> | ||||||
|  | #include "IRQHandler.h" | ||||||
| 
 | 
 | ||||||
| class IDEDiskDevice final : public DiskDevice { | class IDEDiskDevice final : public IRQHandler, public DiskDevice { | ||||||
| public: | public: | ||||||
|     static RetainPtr<IDEDiskDevice> create(); |     static RetainPtr<IDEDiskDevice> create(); | ||||||
|     virtual ~IDEDiskDevice(); |     virtual ~IDEDiskDevice() override; | ||||||
| 
 | 
 | ||||||
|  |     // ^DiskDevice
 | ||||||
|     virtual unsigned blockSize() const override; |     virtual unsigned blockSize() const override; | ||||||
|     virtual bool readBlock(unsigned index, byte*) const override; |     virtual bool readBlock(unsigned index, byte*) const override; | ||||||
|     virtual bool writeBlock(unsigned index, const byte*) override; |     virtual bool writeBlock(unsigned index, const byte*) override; | ||||||
|  | @ -16,6 +19,28 @@ protected: | ||||||
|     IDEDiskDevice(); |     IDEDiskDevice(); | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|  |     // ^IRQHandler
 | ||||||
|  |     virtual void handleIRQ() override; | ||||||
|  | 
 | ||||||
|  |     // ^DiskDevice
 | ||||||
|     virtual const char* className() const override; |     virtual const char* className() const override; | ||||||
|  | 
 | ||||||
|  |     struct CHS { | ||||||
|  |         dword cylinder; | ||||||
|  |         word head; | ||||||
|  |         word sector; | ||||||
|  |     }; | ||||||
|  |     CHS lba_to_chs(dword) const; | ||||||
|  | 
 | ||||||
|  |     void initialize(); | ||||||
|  |     bool wait_for_irq(); | ||||||
|  |     bool read_sectors(dword start_sector, word count, byte* outbuf); | ||||||
|  | 
 | ||||||
|  |     SpinLock m_lock; | ||||||
|  |     word m_cylinders { 0 }; | ||||||
|  |     word m_heads { 0 }; | ||||||
|  |     word m_sectors_per_track { 0 }; | ||||||
|  |     mutable volatile bool m_interrupted { false }; | ||||||
|  | 
 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,7 +11,6 @@ KERNEL_OBJS = \ | ||||||
|        CMOS.o \
 |        CMOS.o \
 | ||||||
|        PIC.o \
 |        PIC.o \
 | ||||||
|        Syscall.o \
 |        Syscall.o \
 | ||||||
|        Disk.o \
 |  | ||||||
|        IDEDiskDevice.o \
 |        IDEDiskDevice.o \
 | ||||||
|        MemoryManager.o \
 |        MemoryManager.o \
 | ||||||
|        Console.o \
 |        Console.o \
 | ||||||
|  |  | ||||||
|  | @ -100,4 +100,13 @@ word getISR() | ||||||
|     return (isr1 << 8) | isr0; |     return (isr1 << 8) | isr0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | word get_irr() | ||||||
|  | { | ||||||
|  |     IO::out8(PIC0_CTL, 0x0a); | ||||||
|  |     IO::out8(PIC1_CTL, 0x0a); | ||||||
|  |     byte irr0 = IO::in8(PIC0_CTL); | ||||||
|  |     byte irr1 = IO::in8(PIC1_CTL); | ||||||
|  |     return (irr1 << 8) | irr0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ void disable(BYTE number); | ||||||
| void eoi(BYTE number); | void eoi(BYTE number); | ||||||
| void initialize(); | void initialize(); | ||||||
| word getISR(); | word getISR(); | ||||||
|  | word get_irr(); | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -38,12 +38,12 @@ void gdt_free_entry(word entry) | ||||||
|     s_gdt_freelist->append(entry); |     s_gdt_freelist->append(entry); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| extern "C" void handleIRQ(); | extern "C" void handle_irq(); | ||||||
| extern "C" void commonIRQEntry(); | extern "C" void asm_irq_entry(); | ||||||
| 
 | 
 | ||||||
| asm( | asm( | ||||||
|     ".globl commonIRQEntry\n" |     ".globl asm_irq_entry\n" | ||||||
|     "commonIRQEntry: \n" |     "asm_irq_entry: \n" | ||||||
|     "    pusha\n" |     "    pusha\n" | ||||||
|     "    pushw %ds\n" |     "    pushw %ds\n" | ||||||
|     "    pushw %es\n" |     "    pushw %es\n" | ||||||
|  | @ -51,7 +51,7 @@ asm( | ||||||
|     "    pushw %ss\n" |     "    pushw %ss\n" | ||||||
|     "    popw %ds\n" |     "    popw %ds\n" | ||||||
|     "    popw %es\n" |     "    popw %es\n" | ||||||
|     "    call handleIRQ\n" |     "    call handle_irq\n" | ||||||
|     "    popw %es\n" |     "    popw %es\n" | ||||||
|     "    popw %ds\n" |     "    popw %ds\n" | ||||||
|     "    popa\n" |     "    popa\n" | ||||||
|  | @ -349,8 +349,7 @@ void registerIRQHandler(byte irq, IRQHandler& handler) | ||||||
| { | { | ||||||
|     ASSERT(!s_irqHandler[irq]); |     ASSERT(!s_irqHandler[irq]); | ||||||
|     s_irqHandler[irq] = &handler; |     s_irqHandler[irq] = &handler; | ||||||
|     kprintf("irq handler for %u: %p\n", irq, &handler); |     registerInterruptHandler(IRQ_VECTOR_BASE + irq, asm_irq_entry); | ||||||
|     registerInterruptHandler(IRQ_VECTOR_BASE + irq, commonIRQEntry); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void unregisterIRQHandler(byte irq, IRQHandler& handler) | void unregisterIRQHandler(byte irq, IRQHandler& handler) | ||||||
|  | @ -433,7 +432,7 @@ void load_task_register(WORD selector) | ||||||
|     asm("ltr %0"::"r"(selector)); |     asm("ltr %0"::"r"(selector)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void handleIRQ() | void handle_irq() | ||||||
| { | { | ||||||
|     WORD isr = PIC::getISR(); |     WORD isr = PIC::getISR(); | ||||||
|     if (!isr) { |     if (!isr) { | ||||||
|  | @ -443,6 +442,8 @@ void handleIRQ() | ||||||
| 
 | 
 | ||||||
|     byte irq = 0; |     byte irq = 0; | ||||||
|     for (byte i = 0; i < 16; ++i) { |     for (byte i = 0; i < 16; ++i) { | ||||||
|  |         if (i == 2) | ||||||
|  |             continue; | ||||||
|         if (isr & (1 << i)) { |         if (isr & (1 << i)) { | ||||||
|             irq = i; |             irq = i; | ||||||
|             break; |             break; | ||||||
|  |  | ||||||
|  | @ -6,7 +6,6 @@ | ||||||
| #include "Keyboard.h" | #include "Keyboard.h" | ||||||
| #include "Process.h" | #include "Process.h" | ||||||
| #include "system.h" | #include "system.h" | ||||||
| #include "Disk.h" |  | ||||||
| #include "PIC.h" | #include "PIC.h" | ||||||
| #include "StdLib.h" | #include "StdLib.h" | ||||||
| #include "Syscall.h" | #include "Syscall.h" | ||||||
|  | @ -176,8 +175,6 @@ static void init_stage2() | ||||||
| { | { | ||||||
|     Syscall::initialize(); |     Syscall::initialize(); | ||||||
| 
 | 
 | ||||||
|     Disk::initialize(); |  | ||||||
| 
 |  | ||||||
| #ifdef TEST_VFS | #ifdef TEST_VFS | ||||||
|     auto vfs = make<VirtualFileSystem>(); |     auto vfs = make<VirtualFileSystem>(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling