2013-10-31

2013-10-31 FAT and ATA drivers

So I've migrated the ATA driver from the DriveAccess kernel, it's nothing special, but it can read hard drives on an ATA interface (IDE) and also interpret standard partition tables to allow devices to specify the partition and resolve blocks relative to it.

I've also migrated much of the FAT file-system driver, but with modifications to implement the LookupFile() function which will (in future) allow the file locking system to work.

I did work out that with 32 (I think) FAT directory entries in a 512-byte block, using a uint32 to uniquely identify each directory on the FAT volume does actually limit me to partitions of 128Gb in size.  This is something I will have to address at some point.

I've created mountlists for the two hard drives that the emulated system has (one hardfile for Grub and a "hardfolder" for the kernel and other files) and I'm using these to mount the hard drives:

dos_mount
(
 "DH0:",
 &dvrata_driver,
 "PARTITION=0",
 &fat_driver,
 ""
);

dos_mount
(
 "DH1:",
 &dvrata_driver,
 "UNIT=1,PARTITION=0",
 &fat_driver,
 ""
);


I've fixed up a bug where the path splitting function was splitting on a semi-colon rather than a colon, and written file-system functions to open a file from a FileID (basically a pointer to the Directory Entry), to seek to a location within a file (with each seek reading and caching the current block), and to read a section of a file (using the seek function to actually perform the read).

The FAT Filesystem context contains the following data:

uint32 DirSectorNumber;
uint32 DirEntryNumber;
tFAT_DirectoryEntry DirectoryEntry;
uint32 FilePointer;
uint32 FirstCluster;
uint32 FileLength;
uint32 CurrentCluster;
uint32 CachedBlockNum;
uint8* CachedBlock;

and finally a small snippet of code which loads and prints a test text file to the output:

int32 lTestFile = dos_openFile( "DH1:test.txt", 0 );
uint32 lReadSize = 256;
uint8* lBuffer = kmalloc(lReadSize);
uint32 lDataRead;
while( ( lDataRead = dos_read( lTestFile, lBuffer, lReadSize ) ) == lReadSize )
{
 kernel_write( 1, lBuffer, lDataRead );
}
kfree( lBuffer );

All in all, it works.  It's mounting the device, reading the FAT parameters from the disk via the block device, looking up a file by path and opening it, and reading the content of the file.  It's a really big step forward to have the Octopus kernel able to load files, and with Bochs capable of taking a folder from the host OS and presenting it to the emulated OS as a FAT filesystem, it'll make some bits of testing a LOT easier.


2013-10-28

2013-10-28 - Keyboard Handler Complete

The kernel now has a keyboard driver, the driver is being loaded into the list of Dos Devices as KBD:, KBD: is being opened as file number 0 (which corresponds with the standard input device).  The C library file functions are wired up to the kernel functions (using the function lookup mechanism) and the CLI uses the C library functions for its input and output.

At some point, the CLI could easily be extracted and made into a program with minimal changes.

Now, just to carefully enable ... the ... IRQ ... handler ... and ... BANG!  :(  General Protection Fault.

Ok, there may have been a few last issues with the interrupt handler, but with those fixed, the console is receiving key-presses  from the keyboard via the Dos layer, file descriptor table, kernel API, and the C library.

One thing I still need to address is when in the process the system converts scan codes into ASCII codes.  In fact, the C library only deals with characters in the stream rather actual key-presses with key-down and key-up which some programs will need, so I guess I'll need to add some API for that.  We'll leave that for another day though.

2013-10-22

2013-10-22 Keyboard Handler Progress

Still working through the keyboard handler and updating it for Octopus.  I've settled on the basic functions that a character device needs to expose so the keyboard handler now looks like a character device.

I've also made use of the stub functions for process_lock() and process_unlock() to allow the keyboard read() function to block until some keyboard data is available.  Currently process_lock() just does a spinlock as I haven't migrated the multi-tasking code yet, but as the keyboard is an interrupt-based device it doesn't hang the kernel forever.

The DOS layer has its list of DOSDevices into which the keyboard is being registered, and the interrupt system has a list of interrupt handlers into which a handler for IRQ 1 is being added.

A logical consequence of the way that the object-orientated device drivers are now working, I've had to enhance the interrupt handler so that a pointer to some kind of context object (the object instance, the state, whatever you want to call it) gets passed in when the interrupt is registered, and then gets passed back to the interrupt handler when the interrupt occurs.  In the case of the keyboard handler, this is a "keyboard context" object that contains, amongst other things, the keyboard input buffer itself.

I can see how this interrupt context will be really useful for all the other interrupt handlers, and I'm kind of annoyed that I didn't think of it when writing the original DriveAccess kernel as it would have made life a lot simpler.

2013-10-09

2013-10-09 DOS Layer ... still

I'm still working through the DOS layer that I built for the DriveAccess kernel and updating it to be more complete.

Previously, the DOS layer only supported block devices and file systems so could only load and save files.  Now I'm adding character devices into it to support keyboards, mice, serial ports, parallel ports and whatnot.

Once it's all in, I can add the keyboard handler as a character device called "KBD:", then open it as stdin which will allow the console to work.

Once the character device for the keyboard is working, it'll be trivial to migrate the various file systems (FAT) and block device drivers (ATA and RAM) from DriveAccess into Octopus so that I can get files loading and saving via the C library.