Merge into main the new state of the operating system/kernel #1
6
Makefile
6
Makefile
@ -17,7 +17,8 @@ $(BUILD_DIR)/idt.o \
|
|||||||
$(BUILD_DIR)/pci.o \
|
$(BUILD_DIR)/pci.o \
|
||||||
$(BUILD_DIR)/pic.o \
|
$(BUILD_DIR)/pic.o \
|
||||||
$(BUILD_DIR)/string.o \
|
$(BUILD_DIR)/string.o \
|
||||||
$(BUILD_DIR)/pcidevice.o
|
$(BUILD_DIR)/pcidevice.o \
|
||||||
|
$(BUILD_DIR)/atapiDevice.o
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -108,3 +109,6 @@ $(BUILD_DIR)/pci.o:
|
|||||||
|
|
||||||
$(BUILD_DIR)/pcidevice.o:
|
$(BUILD_DIR)/pcidevice.o:
|
||||||
$(CPP) -c $(SRC_DIR)/kernel/pci/pciDevice.cpp -o $(BUILD_DIR)/pcidevice.o $(CFLAGS) -fno-exceptions -fno-rtti
|
$(CPP) -c $(SRC_DIR)/kernel/pci/pciDevice.cpp -o $(BUILD_DIR)/pcidevice.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||||
|
|
||||||
|
$(BUILD_DIR)/atapiDevice.o:
|
||||||
|
$(CPP) -c $(SRC_DIR)/kernel/drivers/atapi/atapiDevice.cpp -o $(BUILD_DIR)/atapiDevice.o $(CFLAGS) -fno-exceptions -fno-rtti
|
||||||
|
@ -19,6 +19,10 @@ Multiboot information can be read by the kernel.
|
|||||||
|
|
||||||
![PCI enumeration](screenshots/PCIBusEnumeration.png) \
|
![PCI enumeration](screenshots/PCIBusEnumeration.png) \
|
||||||
Enumerating the PCI bus
|
Enumerating the PCI bus
|
||||||
|
|
||||||
|
![ATAPI CD-ROM Identification](screenshots/CD-ROM_Identify.png) \
|
||||||
|
Correctly identified our ATAPI device 🎉
|
||||||
|
|
||||||
________________________
|
________________________
|
||||||
|
|
||||||
### The goal
|
### The goal
|
||||||
|
BIN
screenshots/CD-ROM_Identify.png
(Stored with Git LFS)
Normal file
BIN
screenshots/CD-ROM_Identify.png
(Stored with Git LFS)
Normal file
Binary file not shown.
131
src/kernel/drivers/ata/ataDevice.cpp
Normal file
131
src/kernel/drivers/ata/ataDevice.cpp
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
#include "atapiDevice.h"
|
||||||
|
#define IS_BIT_SET(x, bit) ((x >> bit & 0x1) == 1)
|
||||||
|
|
||||||
|
void ATA_DEVICE::Soft_Reset(uint8_t DEVICE_CHANNEL,DEVICE_DRIVE drive){
|
||||||
|
printf("Soft reseting drive...\n");
|
||||||
|
outb(channels[DEVICE_CHANNEL].base + 7 , 0x4);
|
||||||
|
// wait a bit..
|
||||||
|
for(int i = 0 ; i < 1000000; i++){
|
||||||
|
asm volatile("NOP");
|
||||||
|
}
|
||||||
|
outb(channels[DEVICE_CHANNEL].base + 7 , 0x0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ATA_DEVICE::Identify(uint8_t DEVICE_CHANNEL,DEVICE_DRIVE drive ){
|
||||||
|
// lets ignore which port we actually want to check for now !
|
||||||
|
|
||||||
|
/*
|
||||||
|
THE STEPS INVOLVED
|
||||||
|
|
||||||
|
1. Select the target drive by sending master (0x0A) or slave (0x0B) to the
|
||||||
|
drive select IO port
|
||||||
|
|
||||||
|
2. Set the Sectorcount, LBAlo, LBAmid and LBAhi IO ports to 0
|
||||||
|
|
||||||
|
3. Send the identify command (0xEC) to the command IO port
|
||||||
|
|
||||||
|
4. Read the status port
|
||||||
|
4.2 If the value is 0x0 the drive does not exist
|
||||||
|
4.3 If it has any other value continue
|
||||||
|
5. poll the status port until bit 7 is clear.
|
||||||
|
6. Check if the LBAmid and LBAhi ports are non-zero
|
||||||
|
6.2. If non-zero stop polling this is not an ATA device
|
||||||
|
6.3 If zero continue
|
||||||
|
|
||||||
|
7. poll status port until bit 3 is set or bit 0 is set
|
||||||
|
|
||||||
|
8. if err is clear, read the data from the data port
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// Assuming Master here
|
||||||
|
// Select the target drive
|
||||||
|
outb(0x176, 0x0A); // on the primary bus select the master drive
|
||||||
|
|
||||||
|
// Set the Sectorcount, LBAlo, LBAmid and LBAhi IO ports to 0
|
||||||
|
outb(0x172, 0);
|
||||||
|
|
||||||
|
outb(0x173, 0);
|
||||||
|
|
||||||
|
outb(0x174, 0);
|
||||||
|
|
||||||
|
outb(0x175, 0);
|
||||||
|
|
||||||
|
// send the identify command;
|
||||||
|
outb(0x177, 0xA1);
|
||||||
|
|
||||||
|
// read the status port
|
||||||
|
uint8_t status = inb(0x177);
|
||||||
|
if( status == 0x00){
|
||||||
|
printf("No drive\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(true){
|
||||||
|
status = inb(0x177);
|
||||||
|
|
||||||
|
if( status & (~8))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Is this an ATA device?\n");
|
||||||
|
uint8_t LBAmid = inb(0x174);
|
||||||
|
uint8_t LBAhi = inb(0x175);
|
||||||
|
|
||||||
|
printf("LBAmid: 0x%x, LBAhi: 0x%x\n", LBAmid, LBAhi);
|
||||||
|
|
||||||
|
|
||||||
|
if( LBAhi != 0x0 || LBAmid != 0x0){
|
||||||
|
printf("Not ATA device.. Stopping..\n");
|
||||||
|
// return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(true){
|
||||||
|
status = inb(0x177);
|
||||||
|
printf( "Status bit: 0x%x\n", status);
|
||||||
|
if ( IS_BIT_SET(status, 3)){
|
||||||
|
printf("Status: ready!\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if( IS_BIT_SET(status, 0)){
|
||||||
|
printf("Status: error!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( IS_BIT_SET(status, 0) == false){
|
||||||
|
// READ DATA
|
||||||
|
|
||||||
|
uint16_t deviceIdentify [256];
|
||||||
|
|
||||||
|
for (int i= 0; i < 256; i++){
|
||||||
|
uint8_t data = inb(0x170);
|
||||||
|
uint8_t data2 = inb(0x170);
|
||||||
|
|
||||||
|
deviceIdentify[i] = (uint16_t) ( (uint16_t) data << 8 | (uint16_t) data2 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
printf("Data received!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Error bit was set!\n");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ATA_DEVICE::Read(uint8_t DEVICE_CHANNEL, DEVICE_DRIVE drive) {
|
||||||
|
printf("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ATA_DEVICE::Write(uint8_t DEVICE_CHANNEL, DEVICE_DRIVE drive) {
|
||||||
|
printf("Not implemented");
|
||||||
|
}
|
29
src/kernel/drivers/ata/ataDevice.h
Normal file
29
src/kernel/drivers/ata/ataDevice.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "../io.h"
|
||||||
|
#include "../ide/ideCommands.h"
|
||||||
|
#include "../ide/sampleIDE.definitions.h"
|
||||||
|
|
||||||
|
#include "../tty/kterm.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This first driver wil make use of IO ports.
|
||||||
|
* Doing so means reading or writing from disk is going
|
||||||
|
* to be very cpu intensive.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum DEVICE_DRIVE{
|
||||||
|
MASTER = 0xA0,
|
||||||
|
SLAVE = 0xB0
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
namespace ATA_DEVICE
|
||||||
|
{
|
||||||
|
void Identify ( uint8_t, DEVICE_DRIVE );
|
||||||
|
void Read ( uint8_t, DEVICE_DRIVE );
|
||||||
|
void Write ( uint8_t, DEVICE_DRIVE );
|
||||||
|
void Soft_Reset ( uint8_t, DEVICE_DRIVE );
|
||||||
|
|
||||||
|
};
|
145
src/kernel/drivers/atapi/atapiDevice.cpp
Normal file
145
src/kernel/drivers/atapi/atapiDevice.cpp
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
#include "atapiDevice.h"
|
||||||
|
#define IS_BIT_SET(x, bit) ((x >> bit & 0x1) == 1)
|
||||||
|
|
||||||
|
bool isPacketDevice(){
|
||||||
|
|
||||||
|
uint8_t LBAmid = inb(0x174);
|
||||||
|
uint8_t LBAhi = inb(0x175);
|
||||||
|
|
||||||
|
printf(" LBAmid: 0x%x, LBAhi: 0x%x");
|
||||||
|
return LBAmid == 0x14 && LBAhi == 0xEB;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ATAPI_DEVICE::Identify(uint8_t DEVICE_CHANNEL,DEVICE_DRIVE drive ){
|
||||||
|
// lets ignore which port we actually want to check for now !
|
||||||
|
|
||||||
|
/* THE STEPS INVOLVED
|
||||||
|
|
||||||
|
1. Select the target drive by sending master (0x0A) or slave (0x0B) to the
|
||||||
|
drive select IO port
|
||||||
|
|
||||||
|
2. Set the Sectorcount, LBAlo, LBAmid and LBAhi IO ports to 0
|
||||||
|
|
||||||
|
3. Send the identify command (0xEC) to the command IO port
|
||||||
|
|
||||||
|
4. Read the status port
|
||||||
|
4.2 If the value is 0x0 the drive does not exist
|
||||||
|
4.3 If it has any other value continue
|
||||||
|
5. poll the status port until bit 7 is clear.
|
||||||
|
6. Check if the LBAmid and LBAhi ports are non-zero
|
||||||
|
6.2. If non-zero stop polling this is not an ATA device
|
||||||
|
6.3 If zero continue
|
||||||
|
|
||||||
|
7. poll status port until bit 3 is set or bit 0 is set
|
||||||
|
|
||||||
|
8. if err is clear, read the data from the data port
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Select the target drive
|
||||||
|
outb(0x176, 0xA0); // on the secondary bus select the master drive
|
||||||
|
outb(0x170 + 0x206 , 0x0); // write 0 to the controlport for some reason
|
||||||
|
|
||||||
|
outb(0x176, 0xA0);
|
||||||
|
// read the status port
|
||||||
|
uint8_t status = inb(0x177);
|
||||||
|
printf("status after drive select: 0x%x\n",status);
|
||||||
|
if( status == 0x00){
|
||||||
|
printf("No drive\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
outb(0x176, 0xA0);
|
||||||
|
|
||||||
|
|
||||||
|
// Set the Sectorcount, LBAlo, LBAmid and LBAhi IO ports to 0
|
||||||
|
outb(0x172, 0);
|
||||||
|
|
||||||
|
outb(0x173, 0);
|
||||||
|
|
||||||
|
outb(0x174, 0);
|
||||||
|
|
||||||
|
outb(0x175, 0);
|
||||||
|
|
||||||
|
// send the identify command;
|
||||||
|
printf("command sent!\n");
|
||||||
|
outb(0x177, 0xA1);
|
||||||
|
|
||||||
|
// read the status port
|
||||||
|
uint8_t status2 = inb(0x177);
|
||||||
|
if( status2 == 0x00){
|
||||||
|
printf("No drive\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
printf("Waiting until ready...\n");
|
||||||
|
|
||||||
|
while(((status2 & 0x80 == 0x80)
|
||||||
|
&& (status2 & 0x01) != 0x01)
|
||||||
|
) status2 = inb(0x177);
|
||||||
|
|
||||||
|
|
||||||
|
if(status2 & 0x01){
|
||||||
|
printf("Error!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// READ DATA
|
||||||
|
|
||||||
|
uint16_t deviceIdentify [256] ={0};
|
||||||
|
|
||||||
|
for (int i= 0; i < 256; i++){
|
||||||
|
uint16_t data;
|
||||||
|
asm volatile ( "in %1, %0"
|
||||||
|
: "=a"(data)
|
||||||
|
: "Nd"(0x170) );
|
||||||
|
|
||||||
|
|
||||||
|
deviceIdentify[i] = data ;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Model-label (ASCII hex):\n");
|
||||||
|
for(int i = 27; i < 47; i++){
|
||||||
|
printf(" %x ",deviceIdentify[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nSerial number (ASCII hex):\n");
|
||||||
|
for (int i = 10; i < 19; i++){
|
||||||
|
printf(" %x ", deviceIdentify[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nFirmware revision (ASCII hex):\n");
|
||||||
|
for (int i = 23; i < 26; i++){
|
||||||
|
printf(" %x ", deviceIdentify[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nConfiguration: %x\n", deviceIdentify[0]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
printf("\nData received!\n");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ATAPI_DEVICE::Read(uint8_t DEVICE_CHANNEL, DEVICE_DRIVE drive) {
|
||||||
|
printf("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ATAPI_DEVICE::Write(uint8_t DEVICE_CHANNEL, DEVICE_DRIVE drive) {
|
||||||
|
printf("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
29
src/kernel/drivers/atapi/atapiDevice.h
Normal file
29
src/kernel/drivers/atapi/atapiDevice.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "../../io.h"
|
||||||
|
#include "../../ide/ideCommands.h"
|
||||||
|
#include "../../ide/sampleIDE.definitions.h"
|
||||||
|
|
||||||
|
#include "../../tty/kterm.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This first driver wil make use of IO ports.
|
||||||
|
* Doing so means reading or writing from disk is going
|
||||||
|
* to be very cpu intensive.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum DEVICE_DRIVE{
|
||||||
|
MASTER = 0xA0,
|
||||||
|
SLAVE = 0xB0
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
namespace ATAPI_DEVICE
|
||||||
|
{
|
||||||
|
bool isPacketDevice();
|
||||||
|
void Identify ( uint8_t, DEVICE_DRIVE );
|
||||||
|
void Read ( uint8_t, DEVICE_DRIVE );
|
||||||
|
void Write ( uint8_t, DEVICE_DRIVE );
|
||||||
|
|
||||||
|
};
|
@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#define IS_BIT_SET(x, bit) ((x >> bit & 0x1) == 1)
|
#define IS_BIT_SET(x, bit) ((x >> bit & 0x1) == 1)
|
||||||
|
|
||||||
|
IDEChannelRegisters channels[2];
|
||||||
|
IDE_DEVICE ide_devices[4];
|
||||||
|
|
||||||
inline void CheckProgIF(uint8_t ProgIF){
|
inline void CheckProgIF(uint8_t ProgIF){
|
||||||
if( IS_BIT_SET(ProgIF, 0) ) // Is the 0th bit set
|
if( IS_BIT_SET(ProgIF, 0) ) // Is the 0th bit set
|
||||||
|
@ -5,11 +5,8 @@ struct IDEChannelRegisters{
|
|||||||
unsigned short ctrl; // Control Base
|
unsigned short ctrl; // Control Base
|
||||||
unsigned short bmide; // Bus Master IDE
|
unsigned short bmide; // Bus Master IDE
|
||||||
unsigned char nIEN; // IEN (no interrupt)
|
unsigned char nIEN; // IEN (no interrupt)
|
||||||
}channels[2];
|
};
|
||||||
|
|
||||||
extern unsigned char ide_buf[2048];
|
|
||||||
extern unsigned char ide_irq_invoked;
|
|
||||||
extern unsigned char atapi_packet[12];
|
|
||||||
|
|
||||||
struct IDE_DEVICE {
|
struct IDE_DEVICE {
|
||||||
unsigned char Reserved; // 0 (Empty) or 1 (This device exists).
|
unsigned char Reserved; // 0 (Empty) or 1 (This device exists).
|
||||||
@ -19,7 +16,14 @@ struct IDE_DEVICE {
|
|||||||
unsigned short Signature; // Drive Signature
|
unsigned short Signature; // Drive Signature
|
||||||
unsigned short Capabilities; // Features.
|
unsigned short Capabilities; // Features.
|
||||||
unsigned int CommandSets; // Command Sets Supported.
|
unsigned int CommandSets; // Command Sets Supported.
|
||||||
unsigned int Size; // Size in Sectors
|
unsigned int Size; // Size in Sectors (NOTE: Seems unused nowadays as i've only seen the value be zero
|
||||||
unsigned char Model[41]; // Model in string.
|
unsigned char Model[41]; // Model in string.
|
||||||
} ide_devices[4];
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
extern IDEChannelRegisters channels[2];
|
||||||
|
extern IDE_DEVICE ide_devices[4];
|
||||||
|
extern unsigned char ide_buf[2048];
|
||||||
|
extern unsigned char ide_irq_invoked;
|
||||||
|
extern unsigned char atapi_packet[12];
|
||||||
|
@ -71,6 +71,33 @@ extern "C" void kernel_main (void);
|
|||||||
|
|
||||||
TestIDEController();
|
TestIDEController();
|
||||||
|
|
||||||
|
int devNumber = 0 ;
|
||||||
|
for ( auto device : ide_devices){
|
||||||
|
if (!device.Reserved)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
printf("Device %d\n" , devNumber);
|
||||||
|
printf (" Device on Channel: (0x%x) %s\n" ,device.Channel, device.Channel == 0 ? "Primary" : "Secondary");
|
||||||
|
printf (" Device drive:(0x%x) %s\n" , device.Drive, device.Drive? "Slave" : "Master");
|
||||||
|
printf (" Device Type:(0x%x) %s\n" , device.Type, device.Type ? "ATAPI" : "ATA");
|
||||||
|
devNumber ++;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ATAPI_DEVICE::isPacketDevice();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ATAPI_DEVICE::Identify(ATA_SECONDARY, DEVICE_DRIVE::MASTER);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
while (true){
|
while (true){
|
||||||
//Read time indefinetely
|
//Read time indefinetely
|
||||||
|
@ -20,6 +20,8 @@ extern "C"{
|
|||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
#include "ide/ide.h"
|
#include "ide/ide.h"
|
||||||
|
#include "drivers/atapi/atapiDevice.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit)))
|
#define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit)))
|
||||||
|
Loading…
Reference in New Issue
Block a user