Fix spelling errors in first posts (yikes).
This commit is contained in:
parent
adeb3cf394
commit
80e734855c
|
@ -111,13 +111,14 @@ On top of the things mentioned above, we use the limine protocol to:
|
|||
Following boot we immediately initialize the global descriptor table (GDT) and
|
||||
interrupt descriptor table (IDT). The **GDT** is mostly irrelevant for x86-64,
|
||||
however it was interesting trying to get it to work with the sysret function
|
||||
which expects two copies of the user-space segment descriptors to allow returing
|
||||
to 32bit code from a 64 bit OS. Right now the system doesn't support 32 bit code
|
||||
(and likely never will) so we just duplicate the 64 bit code segment.
|
||||
which expects two copies of the user-space segment descriptors to allow
|
||||
returning to 32bit code from a 64 bit OS. Right now the system doesn't support
|
||||
32 bit code (and likely never will) so we just duplicate the 64 bit code
|
||||
segment.
|
||||
|
||||
The **IDT** is fairly straightforward and barebones for now. I slowly add more
|
||||
debugging information to faults as I run into them and it is useful. One of the
|
||||
biggest improvements was setting up a seperate kernel stack for Page Faults and
|
||||
biggest improvements was setting up a separate kernel stack for Page Faults and
|
||||
General Protection Faults. That way if I broke memory related to the current
|
||||
stack frame I get useful debugging information rather than an immediate triple
|
||||
fault. I also recently added some very sloppy stack unwind code so I can more
|
||||
|
@ -153,9 +154,9 @@ earlier than they need to be it is obvious because things break.
|
|||
|
||||
For **virtual memory management** I keep the higher half (kernel) mappings
|
||||
identical in each address space. Most of the kernel mappings are already
|
||||
availble from the bootloader but some are added for heaps and additional stacks.
|
||||
available from the bootloader but some are added for heaps and additional stacks.
|
||||
For user memory we maintain a tree of the mapped in objects to ensure that none
|
||||
intersect. Right now the tree is innefficient because it doesn't self balance
|
||||
intersect. Right now the tree is inefficient because it doesn't self balance
|
||||
and most objects are inserted in ascending order (i.e. it is essentially a
|
||||
linked list).
|
||||
|
||||
|
@ -213,7 +214,7 @@ The kernel provides APIs to:
|
|||
* Allocate memory and map it into an address space.
|
||||
* Communicate with other processes using Endpoints, Ports, and Channels.
|
||||
* Register IRQ handlers.
|
||||
* Manage Capabilites.
|
||||
* Manage Capabilities.
|
||||
* Print debug information to the VM output.
|
||||
|
||||
### IPC
|
||||
|
|
|
@ -110,7 +110,7 @@ The short story is that we are looking for the device with the right [class
|
|||
code](https://wiki.osdev.org/PCI#Class_Codes) - Class Code 0x1 (Storage Device),
|
||||
Subclass 0x6 (SATA Controller), Subtype 0x1 (AHCI).
|
||||
|
||||
Once we have the correct configuration space we cn read the address at offset
|
||||
Once we have the correct configuration space we can read the address at offset
|
||||
0x24 (called the ABAR for AHCI Base Address) which points to the start of the
|
||||
GHC registers.
|
||||
|
||||
|
@ -319,7 +319,7 @@ type and any errors from the interrupt since we aren't sending any commands.
|
|||
|
||||
Something I'm not sure about is that as soon as we enable interrupts we seem to
|
||||
receive a FIS from the device with an error bit set. Both the hard drive and the
|
||||
optical drive on qemu send a FIS with error bit 0x1 set. Additionally the status
|
||||
optical drive on QEMU send a FIS with error bit 0x1 set. Additionally the status
|
||||
field is set to 0x30 for the hard drive and 0x70 for the optical drive.
|
||||
|
||||
I was able to find a [OSDev Forum
|
||||
|
@ -328,7 +328,7 @@ referencing that this behavior is caused by the reset sending an EXECUTE DEVICE
|
|||
DIAGNOSTIC command (0x90) to the device. It notes that this is largely
|
||||
undocumented behavior but at least this information offers some clarity on the
|
||||
outputs. Reading the ATA Command Set section 7.9.4 we can see that the command
|
||||
ouputs code 0x01 to the error bits when `Device 0 passed, Device 1 passed or not
|
||||
outputs code 0x01 to the error bits when `Device 0 passed, Device 1 passed or not
|
||||
present`. According a footnote we can "See the appropriate transport standard
|
||||
for the definition of device 0 and device 1." I really thought I was already
|
||||
looking at the "appropriate transport standard" but alas. All that to say we'll
|
||||
|
@ -340,7 +340,7 @@ Now that the AHCI ports are initialized and can handle an interrupt, we can send
|
|||
commands to them. To start with lets send the IDENTIFY DEVICE command to each
|
||||
device. This command asks the device to send 512 bytes of information about
|
||||
itself back to us. These bytes contain 40 years of certified-crufty backwards
|
||||
compatability. I mean just feast your eyes on the number of retired and obsolete
|
||||
compatibility. I mean just feast your eyes on the number of retired and obsolete
|
||||
fields in just the first page of the spec.
|
||||
|
||||
![IDENTIFY DEVICE Response](images/IDENTIFY_DEVICE.png)
|
||||
|
@ -350,7 +350,7 @@ and sector count from the drive. To do so we need to figure out how to send a
|
|||
command to the device. To be honest I feel like the specs fall down here in
|
||||
actually explaining this. The trick is to send a Register Host to Device FIS in one
|
||||
of the command slots. This FIS type has a field for the command as well as some
|
||||
common parameters such as lba and count. In retrospect it is fairly clear once
|
||||
common parameters such as LBA and count. In retrospect it is fairly clear once
|
||||
you are aware of it, but if you are just reading the SATA spec and looking at
|
||||
the possible commands, making the logical jump to the Register Host To Device
|
||||
FIS feels damn near impossible.
|
||||
|
@ -379,7 +379,7 @@ Device FIS is as follows:
|
|||
![Register Host to Device FIS Layout](images/RegisterHostToDeviceFIS.png)
|
||||
|
||||
We don't need to initialize most of the fields here because the IDENTIFY_DEVICE
|
||||
call doesn't rely on an lba or sector count. One of the keys is setting the high
|
||||
call doesn't rely on an LBA or sector count. One of the keys is setting the high
|
||||
bit "C" in the byte that contains PM Port which indicates to the HBA that this
|
||||
FIS contains a new command (I spent a while trying to figure out why this wasn't
|
||||
working without that). The code for this is relatively straightforward.
|
||||
|
@ -429,9 +429,9 @@ port_struct_->command_issue |= (1 << slot);
|
|||
```
|
||||
|
||||
But wait! How will we know when this command has completed? We somehow need to
|
||||
wait until we receive an interrupt for this command to proccess the data it
|
||||
wait until we receive an interrupt for this command to process the data it
|
||||
sent. To handle this we can add a semaphore for each port command slot to allow
|
||||
signalling when we recieve a completion interrupt for that command. I think it
|
||||
signalling when we receive a completion interrupt for that command. I think it
|
||||
might make sense to have some sort of callback instead so we can pass errors
|
||||
back to the caller instead of just a completion signal. However I'm not sure
|
||||
what type of errors exist that are resolvable by the caller so for now this
|
||||
|
@ -469,7 +469,7 @@ void AhciPort::HandleIrq() {
|
|||
}
|
||||
```
|
||||
|
||||
Ok now that we have retrieved the information from the drive we can parse it.
|
||||
OK now that we have retrieved the information from the drive we can parse it.
|
||||
For the sector size, the default is 512 bytes which we will use unless the
|
||||
`LOGICAL SECTOR SIZE SUPPORTED` bit is set in double word 106, bit 12. If that
|
||||
is set we can check the double words at 117 and 118 to get the 32 bit sector
|
||||
|
@ -531,7 +531,7 @@ that truly only a mother could love:
|
|||
|
||||
![Register Host to Device Layout LBA](images/RegisterHostToDeviceFISLBA.png)
|
||||
|
||||
That asside we simply update the FIS construction to set the command, LBA, and
|
||||
That aside we simply update the FIS construction to set the command, LBA, and
|
||||
sector count. Following that we set the PRDT values (although we still only use
|
||||
one slot).
|
||||
|
||||
|
|
Loading…
Reference in New Issue