Merge into main the new state of the operating system/kernel #1
							
								
								
									
										95
									
								
								src/kernel/ide/ide.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								src/kernel/ide/ide.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,95 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <stdint.h> 
 | 
			
		||||
#include "../pci/pciDevice.h"
 | 
			
		||||
#include "../tty/kterm.h"
 | 
			
		||||
#include "ideCommands.h"
 | 
			
		||||
#include "sampleIDE.h"
 | 
			
		||||
 | 
			
		||||
#define IS_BIT_SET(x, bit) ((x >> bit & 0x1) == 1) 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline void CheckProgIF(uint8_t ProgIF){
 | 
			
		||||
    if( IS_BIT_SET(ProgIF, 0) ) // Is the 0th bit set
 | 
			
		||||
    {
 | 
			
		||||
        printf ("Primary Channel is in PCI native mode\n");
 | 
			
		||||
    } else{
 | 
			
		||||
        printf("Primary Channel is in Compatibility mode\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if( IS_BIT_SET(ProgIF, 1)){
 | 
			
		||||
        printf("Bit 0 can be modified\n");
 | 
			
		||||
    }else{
 | 
			
		||||
        printf("Bit 0 cannot be modified\n");
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if( IS_BIT_SET(ProgIF, 2)){
 | 
			
		||||
        printf("Secondary channel is in PCI native mode\n");
 | 
			
		||||
    }else{
 | 
			
		||||
        printf("Secondary channel is in Compatibility mode\n");
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if( IS_BIT_SET(ProgIF, 3)){
 | 
			
		||||
        printf("Bit 2 can be modified\n");
 | 
			
		||||
    }else{
 | 
			
		||||
        printf("Bit 2 cannot be modified\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    if( IS_BIT_SET(ProgIF , 7)){
 | 
			
		||||
        printf("This is a bus master IDE Controller\n");
 | 
			
		||||
    } else{
 | 
			
		||||
        printf("This controller doesn't support DMA!\n");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void TestIDEController(){
 | 
			
		||||
    // Do stuff
 | 
			
		||||
    printf("Testing IDE controllers\n");
 | 
			
		||||
 | 
			
		||||
    // NOTE: Testing done with a hard coded known PCI addres 
 | 
			
		||||
    // Of an intel PIIX3 IDE Controller
 | 
			
		||||
    int bus = 0;
 | 
			
		||||
    int device =1  , function = 1;
 | 
			
		||||
    PCIBusAddress IDEControllerPCIAddress = PCIBusAddress{bus,device, function};
 | 
			
		||||
 | 
			
		||||
    uint8_t ProgIF = GetProgIF(IDEControllerPCIAddress);
 | 
			
		||||
    printf( "ProgIF: 0x%x\n" ,ProgIF);
 | 
			
		||||
 | 
			
		||||
    //CheckProgIF(ProgIF);
 | 
			
		||||
 | 
			
		||||
    // For this test will just assume all bits are set 
 | 
			
		||||
    // the CheckProgIF can check but on the test machine all bits are set anyways
 | 
			
		||||
 | 
			
		||||
    uint32_t BAR0,BAR1,BAR2,BAR3, BAR4;
 | 
			
		||||
 | 
			
		||||
    BAR0 = ReadBAR(IDEControllerPCIAddress, 0); 
 | 
			
		||||
 | 
			
		||||
    BAR1 = ReadBAR(IDEControllerPCIAddress, 1);
 | 
			
		||||
 | 
			
		||||
    BAR2 = ReadBAR(IDEControllerPCIAddress, 2);
 | 
			
		||||
 | 
			
		||||
    BAR3 = ReadBAR(IDEControllerPCIAddress, 3);
 | 
			
		||||
 | 
			
		||||
    BAR4 = ReadBAR(IDEControllerPCIAddress, 4);
 | 
			
		||||
 | 
			
		||||
    // All bars are return 0xffffff for some as of yet mysterious reason!
 | 
			
		||||
    printf( "BAR 0: 0x%x\n", BAR0);
 | 
			
		||||
 | 
			
		||||
    printf( "BAR 1: 0x%x\n", BAR1);
 | 
			
		||||
 | 
			
		||||
    printf( "BAR 2: 0x%x\n", BAR2);
 | 
			
		||||
 | 
			
		||||
    printf( "BAR 3: 0x%x\n", BAR3);
 | 
			
		||||
 | 
			
		||||
    printf( "BAR 4: 0x%x\n", BAR4);
 | 
			
		||||
 | 
			
		||||
    init_IDE(BAR0, BAR1, BAR2, BAR3, BAR4);
 | 
			
		||||
    
 | 
			
		||||
    // Read Something from disc
 | 
			
		||||
    unsigned int maxByteCount = 20 ;
 | 
			
		||||
    void* MDA_buffer = (void*)0xC0000000;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										86
									
								
								src/kernel/ide/ideCommands.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/kernel/ide/ideCommands.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,86 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// Commands
 | 
			
		||||
#define ATA_CMD_READ_PIO          0x20
 | 
			
		||||
#define ATA_CMD_READ_PIO_EXT      0x24
 | 
			
		||||
#define ATA_CMD_READ_DMA          0xC8
 | 
			
		||||
#define ATA_CMD_READ_DMA_EXT      0x25
 | 
			
		||||
#define ATA_CMD_WRITE_PIO         0x30
 | 
			
		||||
#define ATA_CMD_WRITE_PIO_EXT     0x34
 | 
			
		||||
#define ATA_CMD_WRITE_DMA         0xCA
 | 
			
		||||
#define ATA_CMD_WRITE_DMA_EXT     0x35
 | 
			
		||||
#define ATA_CMD_CACHE_FLUSH       0xE7
 | 
			
		||||
#define ATA_CMD_CACHE_FLUSH_EXT   0xEA
 | 
			
		||||
#define ATA_CMD_PACKET            0xA0
 | 
			
		||||
#define ATA_CMD_IDENTIFY_PACKET   0xA1
 | 
			
		||||
#define ATA_CMD_IDENTIFY          0xEC
 | 
			
		||||
 | 
			
		||||
#define ATAPI_CMD_READ       0xA8
 | 
			
		||||
#define ATAPI_CMD_EJECT      0x1B
 | 
			
		||||
 | 
			
		||||
#define ATA_IDENT_DEVICETYPE   0
 | 
			
		||||
#define ATA_IDENT_CYLINDERS    2
 | 
			
		||||
#define ATA_IDENT_HEADS        6
 | 
			
		||||
#define ATA_IDENT_SECTORS      12
 | 
			
		||||
#define ATA_IDENT_SERIAL       20
 | 
			
		||||
#define ATA_IDENT_MODEL        54
 | 
			
		||||
#define ATA_IDENT_CAPABILITIES 98
 | 
			
		||||
#define ATA_IDENT_FIELDVALID   106
 | 
			
		||||
#define ATA_IDENT_MAX_LBA      120
 | 
			
		||||
#define ATA_IDENT_COMMANDSETS  164
 | 
			
		||||
#define ATA_IDENT_MAX_LBA_EXT  200
 | 
			
		||||
 | 
			
		||||
#define IDE_ATA        0x00
 | 
			
		||||
#define IDE_ATAPI      0x01
 | 
			
		||||
 
 | 
			
		||||
#define ATA_MASTER     0x00
 | 
			
		||||
#define ATA_SLAVE      0x01
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define ATA_REG_DATA       0x00
 | 
			
		||||
#define ATA_REG_ERROR      0x01
 | 
			
		||||
#define ATA_REG_FEATURES   0x01
 | 
			
		||||
#define ATA_REG_SECCOUNT0  0x02
 | 
			
		||||
#define ATA_REG_LBA0       0x03
 | 
			
		||||
#define ATA_REG_LBA1       0x04
 | 
			
		||||
#define ATA_REG_LBA2       0x05
 | 
			
		||||
#define ATA_REG_HDDEVSEL   0x06
 | 
			
		||||
#define ATA_REG_COMMAND    0x07
 | 
			
		||||
#define ATA_REG_STATUS     0x07
 | 
			
		||||
#define ATA_REG_SECCOUNT1  0x08
 | 
			
		||||
#define ATA_REG_LBA3       0x09
 | 
			
		||||
#define ATA_REG_LBA4       0x0A
 | 
			
		||||
#define ATA_REG_LBA5       0x0B
 | 
			
		||||
#define ATA_REG_CONTROL    0x0C
 | 
			
		||||
#define ATA_REG_ALTSTATUS  0x0C
 | 
			
		||||
#define ATA_REG_DEVADDRESS 0x0D
 | 
			
		||||
 | 
			
		||||
// Channels:
 | 
			
		||||
#define      ATA_PRIMARY      0x00
 | 
			
		||||
#define      ATA_SECONDARY    0x01
 | 
			
		||||
 
 | 
			
		||||
// Directions:
 | 
			
		||||
#define      ATA_READ      0x00
 | 
			
		||||
#define      ATA_WRITE     0x01
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Status
 | 
			
		||||
#define ATA_SR_BSY     0x80    // Busy
 | 
			
		||||
#define ATA_SR_DRDY    0x40    // Drive ready
 | 
			
		||||
#define ATA_SR_DF      0x20    // Drive write fault
 | 
			
		||||
#define ATA_SR_DSC     0x10    // Drive seek complete
 | 
			
		||||
#define ATA_SR_DRQ     0x08    // Data request ready
 | 
			
		||||
#define ATA_SR_CORR    0x04    // Corrected data
 | 
			
		||||
#define ATA_SR_IDX     0x02    // Index
 | 
			
		||||
#define ATA_SR_ERR     0x01    // Error
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Errors
 | 
			
		||||
#define ATA_ER_BBK      0x80    // Bad block
 | 
			
		||||
#define ATA_ER_UNC      0x40    // Uncorrectable data
 | 
			
		||||
#define ATA_ER_MC       0x20    // Media changed
 | 
			
		||||
#define ATA_ER_IDNF     0x10    // ID mark not found
 | 
			
		||||
#define ATA_ER_MCR      0x08    // Media change request
 | 
			
		||||
#define ATA_ER_ABRT     0x04    // Command aborted
 | 
			
		||||
#define ATA_ER_TK0NF    0x02    // Track 0 not found
 | 
			
		||||
#define ATA_ER_AMNF     0x01    // No address mark
 | 
			
		||||
							
								
								
									
										25
									
								
								src/kernel/ide/sampleIDE.definitions.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/kernel/ide/sampleIDE.definitions.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
			
		||||
#pragma once 
 | 
			
		||||
 | 
			
		||||
struct IDEChannelRegisters{
 | 
			
		||||
    unsigned short base; // I/O Base.
 | 
			
		||||
    unsigned short ctrl; // Control Base
 | 
			
		||||
    unsigned short bmide; // Bus Master IDE
 | 
			
		||||
    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 {
 | 
			
		||||
    unsigned char Reserved; // 0 (Empty) or 1 (This device exists).
 | 
			
		||||
    unsigned char Channel; // 0 (Primary Channel) or 1 (Secondary Channel).
 | 
			
		||||
    unsigned char Drive; // 0 (Master Drive) or 1 (Slave Drive).
 | 
			
		||||
    unsigned short Type; // 0 ATA, 1:ATAPI
 | 
			
		||||
    unsigned short Signature; // Drive Signature
 | 
			
		||||
    unsigned short Capabilities; // Features.
 | 
			
		||||
    unsigned int CommandSets; // Command Sets Supported.
 | 
			
		||||
    unsigned int Size; // Size in Sectors
 | 
			
		||||
    unsigned char Model[41]; // Model in string.
 | 
			
		||||
} ide_devices[4];
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										241
									
								
								src/kernel/ide/sampleIDE.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										241
									
								
								src/kernel/ide/sampleIDE.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,241 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <stdint.h> 
 | 
			
		||||
#include "../tty/kterm.h"
 | 
			
		||||
#include "sampleIDE.definitions.h"
 | 
			
		||||
#include "ideCommands.h"
 | 
			
		||||
 | 
			
		||||
void Detect_IO_Ports(uint32_t BAR0, uint32_t BAR1,uint32_t BAR2, uint32_t BAR3, uint32_t BAR4);
 | 
			
		||||
void DetectDevices();
 | 
			
		||||
 | 
			
		||||
unsigned char ide_buf[2048] = {0};
 | 
			
		||||
unsigned  char ide_irq_invoked = 0;
 | 
			
		||||
unsigned  char atapi_packet[12] = {0xA8,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 | 
			
		||||
 | 
			
		||||
void wait(int t){
 | 
			
		||||
    volatile int i,j;
 | 
			
		||||
    for(i=0;i<t;i++)
 | 
			
		||||
        for(j=0;j<25000;j++)
 | 
			
		||||
            asm("NOP");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ide_write(unsigned char channel, unsigned char reg, unsigned char data){
 | 
			
		||||
    if (reg > 0x07 && reg < 0x0C)
 | 
			
		||||
      ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
 | 
			
		||||
    if (reg < 0x08)
 | 
			
		||||
      outb(channels[channel].base  + reg - 0x00, data);
 | 
			
		||||
    else if (reg < 0x0C)
 | 
			
		||||
      outb(channels[channel].base  + reg - 0x06, data);
 | 
			
		||||
    else if (reg < 0x0E)
 | 
			
		||||
      outb(channels[channel].ctrl  + reg - 0x0A, data);
 | 
			
		||||
    else if (reg < 0x16)
 | 
			
		||||
      outb(channels[channel].bmide + reg - 0x0E, data);
 | 
			
		||||
    if (reg > 0x07 && reg < 0x0C)
 | 
			
		||||
      ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned char ide_read(unsigned char channel, unsigned char reg){
 | 
			
		||||
    unsigned char result;
 | 
			
		||||
    if( reg > 0x07 && reg < 0x0C)
 | 
			
		||||
        ide_write(channel,ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
 | 
			
		||||
    if( reg < 0x08) 
 | 
			
		||||
        result = inb(channels[channel].base + reg - 0x00);
 | 
			
		||||
    else if (reg < 0x0C)
 | 
			
		||||
        result = inb(channels[channel].base  + reg - 0x06);
 | 
			
		||||
     else if (reg < 0x0E)
 | 
			
		||||
        result = inb(channels[channel].ctrl  + reg - 0x0A);
 | 
			
		||||
    else if (reg < 0x16)
 | 
			
		||||
        result = inb(channels[channel].bmide + reg - 0x0E);
 | 
			
		||||
    if (reg > 0x07 && reg < 0x0C)
 | 
			
		||||
        ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ide_read_buffer(unsigned char channel, unsigned char reg, unsigned int buffer, unsigned int quads){
 | 
			
		||||
   if (reg > 0x07 && reg < 0x0C)
 | 
			
		||||
      ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN);
 | 
			
		||||
   if (reg < 0x08)
 | 
			
		||||
      insl(channels[channel].base  + reg - 0x00, (void *)buffer, quads);
 | 
			
		||||
   else if (reg < 0x0C)
 | 
			
		||||
      insl(channels[channel].base  + reg - 0x06, (void *)buffer, quads);
 | 
			
		||||
   else if (reg < 0x0E)
 | 
			
		||||
      insl(channels[channel].ctrl  + reg - 0x0A, (void *)buffer, quads);
 | 
			
		||||
   else if (reg < 0x16)
 | 
			
		||||
      insl(channels[channel].bmide + reg - 0x0E, (void *)buffer, quads);
 | 
			
		||||
   if (reg > 0x07 && reg < 0x0C)
 | 
			
		||||
      ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned char ide_polling(unsigned char channel, unsigned int advanced_check) {
 | 
			
		||||
 
 | 
			
		||||
   // (I) Delay 400 nanosecond for BSY to be set:
 | 
			
		||||
   // -------------------------------------------------
 | 
			
		||||
   for(int i = 0; i < 4; i++)
 | 
			
		||||
      ide_read(channel, ATA_REG_ALTSTATUS); // Reading the Alternate Status port wastes 100ns; loop four times.
 | 
			
		||||
 
 | 
			
		||||
   // (II) Wait for BSY to be cleared:
 | 
			
		||||
   // -------------------------------------------------
 | 
			
		||||
   while (ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY)
 | 
			
		||||
      ; // Wait for BSY to be zero.
 | 
			
		||||
 
 | 
			
		||||
   if (advanced_check) {
 | 
			
		||||
      unsigned char state = ide_read(channel, ATA_REG_STATUS); // Read Status Register.
 | 
			
		||||
 
 | 
			
		||||
      // (III) Check For Errors:
 | 
			
		||||
      // -------------------------------------------------
 | 
			
		||||
      if (state & ATA_SR_ERR)
 | 
			
		||||
         return 2; // Error.
 | 
			
		||||
 
 | 
			
		||||
      // (IV) Check If Device fault:
 | 
			
		||||
      // -------------------------------------------------
 | 
			
		||||
      if (state & ATA_SR_DF)
 | 
			
		||||
         return 1; // Device Fault.
 | 
			
		||||
 
 | 
			
		||||
      // (V) Check DRQ:
 | 
			
		||||
      // -------------------------------------------------
 | 
			
		||||
      // BSY = 0; DF = 0; ERR = 0 so we should check for DRQ now.
 | 
			
		||||
      if ((state & ATA_SR_DRQ) == 0)
 | 
			
		||||
         return 3; // DRQ should be set
 | 
			
		||||
 
 | 
			
		||||
   }
 | 
			
		||||
 
 | 
			
		||||
   return 0; // No Error.
 | 
			
		||||
 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned char ide_print_error(unsigned int drive, unsigned char err) {
 | 
			
		||||
   if (err == 0)
 | 
			
		||||
      return err;
 | 
			
		||||
 
 | 
			
		||||
   printf("IDE:");
 | 
			
		||||
   if (err == 1) {printf("- Device Fault\n     "); err = 19;}
 | 
			
		||||
   else if (err == 2) {
 | 
			
		||||
      unsigned char st = ide_read(ide_devices[drive].Channel, ATA_REG_ERROR);
 | 
			
		||||
      if (st & ATA_ER_AMNF)   {printf("- No Address Mark Found\n     ");   err = 7;}
 | 
			
		||||
      if (st & ATA_ER_TK0NF)   {printf("- No Media or Media Error\n     ");   err = 3;}
 | 
			
		||||
      if (st & ATA_ER_ABRT)   {printf("- Command Aborted\n     ");      err = 20;}
 | 
			
		||||
      if (st & ATA_ER_MCR)   {printf("- No Media or Media Error\n     ");   err = 3;}
 | 
			
		||||
      if (st & ATA_ER_IDNF)   {printf("- ID mark not Found\n     ");      err = 21;}
 | 
			
		||||
      if (st & ATA_ER_MC)   {printf("- No Media or Media Error\n     ");   err = 3;}
 | 
			
		||||
      if (st & ATA_ER_UNC)   {printf("- Uncorrectable Data Error\n     ");   err = 22;}
 | 
			
		||||
      if (st & ATA_ER_BBK)   {printf("- Bad Sectors\n     ");       err = 13;}
 | 
			
		||||
   } else  if (err == 3)           {printf("- Reads Nothing\n     "); err = 23;}
 | 
			
		||||
     else  if (err == 4)  {printf("- Write Protected\n     "); err = 8;}
 | 
			
		||||
   printf("- [%s %s] %s\n",
 | 
			
		||||
      (const char *[]){"Primary", "Secondary"}[ide_devices[drive].Channel], // Use the channel as an index into the array
 | 
			
		||||
      (const char *[]){"Master", "Slave"}[ide_devices[drive].Drive], // Same as above, using the drive
 | 
			
		||||
      ide_devices[drive].Model);
 | 
			
		||||
 
 | 
			
		||||
   return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline void init_IDE( uint32_t BAR0, uint32_t BAR1,uint32_t BAR2, uint32_t BAR3, uint32_t BAR4)
 | 
			
		||||
{
 | 
			
		||||
   Detect_IO_Ports( BAR0,  BAR1, BAR2,  BAR3,  BAR4);
 | 
			
		||||
 | 
			
		||||
   printf("ATA Primary port,  base: 0x%x, ctrl: 0x%x\n", channels[ATA_PRIMARY].base , channels[ATA_PRIMARY].ctrl);
 | 
			
		||||
   printf("ATA Secondary port,  base: 0x%x, ctrl: 0x%x\n", channels[ATA_SECONDARY].base , channels[ATA_SECONDARY].ctrl);
 | 
			
		||||
 | 
			
		||||
   // 2- Disable IRQs:
 | 
			
		||||
    ide_write(ATA_PRIMARY  , ATA_REG_CONTROL, 2);
 | 
			
		||||
    ide_write(ATA_SECONDARY, ATA_REG_CONTROL, 2);
 | 
			
		||||
   
 | 
			
		||||
   DetectDevices();
 | 
			
		||||
 
 | 
			
		||||
   // 4- Print Summary:
 | 
			
		||||
   for (int i = 0; i < 4; i++)
 | 
			
		||||
      if (ide_devices[i].Reserved == 1) {
 | 
			
		||||
         printf(" Found %s Drive %d bytes - %x\n",
 | 
			
		||||
            (const char *[]){"ATA", "ATAPI"}[ide_devices[i].Type],         /* Type */
 | 
			
		||||
            ide_devices[i].Size  / 2,               /* Size */
 | 
			
		||||
            ide_devices[i].Model);
 | 
			
		||||
      }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// 3- Detect ATA-ATAPI Devices:
 | 
			
		||||
void DetectDevices(){
 | 
			
		||||
   int i, j, k, count = 0;
 | 
			
		||||
 | 
			
		||||
   for (i = 0; i < 2; i++)
 | 
			
		||||
      for (j = 0; j < 2; j++) {
 | 
			
		||||
 
 | 
			
		||||
         unsigned char err = 0, type = IDE_ATA, status;
 | 
			
		||||
         ide_devices[count].Reserved = 0; // Assuming that no drive here.
 | 
			
		||||
 
 | 
			
		||||
         // (I) Select Drive:
 | 
			
		||||
         ide_write(i, ATA_REG_HDDEVSEL, 0xA0 | (j << 4)); // Select Drive.
 | 
			
		||||
         wait(1000); // Wait 1ms for drive select to work.
 | 
			
		||||
 
 | 
			
		||||
         // (II) Send ATA Identify Command:
 | 
			
		||||
         ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
 | 
			
		||||
         wait(1000); 
 | 
			
		||||
 
 | 
			
		||||
         // (III) Polling:
 | 
			
		||||
         if (ide_read(i, ATA_REG_STATUS) == 0) continue; // If Status = 0, No Device.
 | 
			
		||||
 
 | 
			
		||||
         while(1) {
 | 
			
		||||
            status = ide_read(i, ATA_REG_STATUS);
 | 
			
		||||
            if ((status & ATA_SR_ERR)) {err = 1; break;} // If Err, Device is not ATA.
 | 
			
		||||
            if (!(status & ATA_SR_BSY) && (status & ATA_SR_DRQ)) break; // Everything is right.
 | 
			
		||||
         }
 | 
			
		||||
 
 | 
			
		||||
         // (IV) Probe for ATAPI Devices:
 | 
			
		||||
         if (err != 0) {
 | 
			
		||||
            unsigned char cl = ide_read(i, ATA_REG_LBA1);
 | 
			
		||||
            unsigned char ch = ide_read(i, ATA_REG_LBA2);
 | 
			
		||||
 
 | 
			
		||||
            if (cl == 0x14 && ch ==0xEB)
 | 
			
		||||
               type = IDE_ATAPI;
 | 
			
		||||
            else if (cl == 0x69 && ch == 0x96)
 | 
			
		||||
               type = IDE_ATAPI;
 | 
			
		||||
            else
 | 
			
		||||
               continue; // Unknown Type (may not be a device).
 | 
			
		||||
 
 | 
			
		||||
            ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET);
 | 
			
		||||
            wait(1000);
 | 
			
		||||
         }
 | 
			
		||||
 
 | 
			
		||||
         // (V) Read Identification Space of the Device:
 | 
			
		||||
         ide_read_buffer(i, ATA_REG_DATA, (unsigned int) ide_buf, 128);
 | 
			
		||||
 
 | 
			
		||||
         // (VI) Read Device Parameters:
 | 
			
		||||
         ide_devices[count].Reserved     = 1;
 | 
			
		||||
         ide_devices[count].Type         = type;
 | 
			
		||||
         ide_devices[count].Channel      = i;
 | 
			
		||||
         ide_devices[count].Drive        = j;
 | 
			
		||||
         ide_devices[count].Signature    = *((unsigned short *)(ide_buf + ATA_IDENT_DEVICETYPE));
 | 
			
		||||
         ide_devices[count].Capabilities = *((unsigned short *)(ide_buf + ATA_IDENT_CAPABILITIES));
 | 
			
		||||
         ide_devices[count].CommandSets  = *((unsigned int *)(ide_buf + ATA_IDENT_COMMANDSETS));
 | 
			
		||||
 
 | 
			
		||||
         // (VII) Get Size:
 | 
			
		||||
         if (ide_devices[count].CommandSets & (1 << 26))
 | 
			
		||||
            // Device uses 48-Bit Addressing:
 | 
			
		||||
            ide_devices[count].Size   = *((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA_EXT));
 | 
			
		||||
         else
 | 
			
		||||
            // Device uses CHS or 28-bit Addressing:
 | 
			
		||||
            ide_devices[count].Size   = *((unsigned int *)(ide_buf + ATA_IDENT_MAX_LBA));
 | 
			
		||||
 
 | 
			
		||||
         // (VIII) String indicates model of device (like Western Digital HDD and SONY DVD-RW...):
 | 
			
		||||
         for(k = 0; k < 40; k += 2) {
 | 
			
		||||
            ide_devices[count].Model[k] = ide_buf[ATA_IDENT_MODEL + k + 1];
 | 
			
		||||
            ide_devices[count].Model[k + 1] = ide_buf[ATA_IDENT_MODEL + k];}
 | 
			
		||||
         ide_devices[count].Model[40] = 0; // Terminate String.
 | 
			
		||||
 
 | 
			
		||||
         count++;
 | 
			
		||||
      }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void Detect_IO_Ports(uint32_t BAR0, uint32_t BAR1,uint32_t BAR2, uint32_t BAR3, uint32_t BAR4){
 | 
			
		||||
    // 1 Detect I/O Ports which interface an IDE Controller
 | 
			
		||||
 | 
			
		||||
   // Based on the implementation within serenity
 | 
			
		||||
    channels[ATA_PRIMARY].base = (BAR0 == 0x1 || BAR0 == 0x0) ? 0x1F0 : BAR0 & (~1);
 | 
			
		||||
    channels[ATA_PRIMARY  ].ctrl  = (BAR1 == 0x1 || BAR1 == 0x0) ?  0x3F6 : BAR1 & (~1);
 | 
			
		||||
    channels[ATA_SECONDARY].base  = (BAR2 == 0x1 || BAR2 == 0x0) ? 0x170 : BAR2 & (~1);
 | 
			
		||||
    channels[ATA_SECONDARY].ctrl  = (BAR3 == 0x1 || BAR3 == 0x0) ? 0x376 : BAR3 & (~1);
 | 
			
		||||
    channels[ATA_PRIMARY  ].bmide = (BAR4 & (~1)) + 0; // Bus Master IDE
 | 
			
		||||
    channels[ATA_SECONDARY].bmide = (BAR4 & (~1)) + 8; // Bus Master IDE
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -65,7 +65,11 @@ extern "C" void kernel_main (void);
 | 
			
		||||
     
 | 
			
		||||
 | 
			
		||||
        // Enumerate the PCI bus
 | 
			
		||||
        PCI_Enumerate();        
 | 
			
		||||
        PCI_Enumerate();  
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
       TestIDEController();      
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        while (true){
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,8 @@
 | 
			
		||||
extern "C"{
 | 
			
		||||
   #include "../libc/include/string.h" 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "vga/VBE.h"
 | 
			
		||||
#include "tty/kterm.h"
 | 
			
		||||
 | 
			
		||||
@ -17,7 +19,7 @@ extern "C"{
 | 
			
		||||
#include "cpu.h"
 | 
			
		||||
#include "serial.h"
 | 
			
		||||
#include "pci.h"
 | 
			
		||||
 | 
			
		||||
#include "ide/ide.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define CHECK_FLAG(flags, bit) ((flags) & (1 <<(bit)))
 | 
			
		||||
 | 
			
		||||
@ -121,8 +121,6 @@ const char* getVendor( uint32_t VendorID){
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint32_t ConfigReadWord ( PCIBusAddress& PCIDeviceAddress , uint8_t offset){
 | 
			
		||||
    outl(CONFIG_ADDRESS , PCIDeviceAddress.getAddress() | offset );
 | 
			
		||||
    return inl(CONFIG_DATA);
 | 
			
		||||
@ -144,8 +142,6 @@ uint32_t ConfigReadWord (uint8_t bus, uint8_t device, uint8_t func, uint8_t offs
 | 
			
		||||
    return inl(CONFIG_DATA);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint8_t GetHeaderType( PCIBusAddress& PCIDeviceAddress ){
 | 
			
		||||
    uint32_t header_information = ConfigReadWord(PCIDeviceAddress , 0xC);
 | 
			
		||||
    return (uint8_t) (
 | 
			
		||||
@ -167,9 +163,6 @@ bool IsMultiFunctionDevice(PCIBusAddress& PCIDeviceAddress){
 | 
			
		||||
            >> 7  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void PrintPCIDeviceInfo (PCIBusAddress& PCIDeviceAddress)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t DeviceID =  (GetDevice(PCIDeviceAddress.bus, PCIDeviceAddress.device, PCIDeviceAddress.function) >> 16);
 | 
			
		||||
@ -191,8 +184,6 @@ void PrintPCIDeviceInfo (PCIBusAddress& PCIDeviceAddress)
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void PCI_Enumerate(){
 | 
			
		||||
            int devicesFound = 0;
 | 
			
		||||
        // loop through all possible busses, devices and their functions;
 | 
			
		||||
@ -244,3 +235,13 @@ void PCI_Enumerate(){
 | 
			
		||||
 | 
			
		||||
        printf("Found %d PCI devices!\n", devicesFound);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t GetProgIF (PCIBusAddress& PCIDeviceAddress){
 | 
			
		||||
    uint32_t data = ConfigReadWord(PCIDeviceAddress, 0x8);
 | 
			
		||||
    return ((data >> 8) & 0xFF);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t ReadBAR ( PCIBusAddress& PCIDeviceAddress, int bar_number){
 | 
			
		||||
    int offsetToBar = 0x10 + (bar_number* 0x4);
 | 
			
		||||
    return ConfigReadWord(PCIDeviceAddress, offsetToBar); 
 | 
			
		||||
}
 | 
			
		||||
@ -32,4 +32,7 @@ uint16_t GetClassCodes( PCIBusAddress& PICDeviceAddress );
 | 
			
		||||
const char* getVendor( uint64_t VendorID);
 | 
			
		||||
const char* GetClassCodeName (uint64_t ClassCode );
 | 
			
		||||
 | 
			
		||||
void PCI_Enumerate();
 | 
			
		||||
uint8_t GetProgIF (PCIBusAddress& PCIDeviceAddress);
 | 
			
		||||
void PCI_Enumerate();
 | 
			
		||||
 | 
			
		||||
uint32_t ReadBAR ( PCIBusAddress& PCIDeviceAddress, int bar_number);
 | 
			
		||||
		Reference in New Issue
	
	Block a user