Page 1 of 2
Detecting hardware
Posted: Mon Jul 14, 2008 10:54 am
by Revelation
Hi,
Now that my p-mode kernel is working properly, I want to communicate with my hardware. For example my hard drive. But I don't really know how to detect my hdd and other hardware. How can I do that?
Re: Detecting hardware
Posted: Mon Jul 14, 2008 11:02 am
by suthers
Use PIO, this a fairly good tutorial:
http://www.osdever.net/tutorials/lba.php
or DMA works too...
Jules
Re: Detecting hardware
Posted: Mon Jul 14, 2008 1:31 pm
by Masterkiller
Scan the PCI Configuration Space. It should provide you with controllers to most buses. Then you should scan every bus separately. Everyone uses different method to say if there and how many devices are attached.
The other way is far more harder but probably more efficient. You could use the ACPI tables. But don't mess with that, it use machine code different from x86 assembly.
Re: Detecting hardware
Posted: Mon Jul 14, 2008 1:52 pm
by Combuster
The PCI space won't tell you all devices. ISA needs to be detected manually, standard peripherals must be detected manually. the floppy and ide controllers may not be listed in the PCI tables, nor in the ACPI tables, especially when dealing with computers predating those standards.
Re: Detecting hardware
Posted: Mon Jul 14, 2008 3:27 pm
by Masterkiller
Combuster wrote:The PCI space won't tell you all devices. ISA needs to be detected manually, standard peripherals must be detected manually. the floppy and ide controllers may not be listed in the PCI tables, nor in the ACPI tables, especially when dealing with computers predating those standards.
PCI will tell you if PCI-to-ISA bridge exist. If any then you should load ISA driver and test devices. PCI-to-ISA bridge may exist even if there isn't any ISA slots on your motherboard.
PCI will tell you most of the integrated devices and all the devices connected to PCI slot and it won't report about any other devices like peripherals, HDD, etc. Integrated devices into I/O chip also include bridges to buses (AGP, ISA, USB). You should "ask" every bus what devices are connected to it (if any).
Re: Detecting hardware
Posted: Mon Jul 14, 2008 3:42 pm
by Revelation
Use PIO, this a fairly good tutorial
I currently have a hdd driver based on that tutorial, though I am not sure if it will work on my S-ATA drive. I also saw that this way of communicating to a drive only lets me access 4 drives, 2 on primary and 2 on secondary IDE.
This is the code I use to find if the drive on that IDE cable exists and if it is a hard drive:
Code: Select all
int DetectDrive(unsigned char ide, unsigned long drive)
{
unsigned short tmpword;
unsigned char check;
unsigned short base;
unsigned short buf[256];
unsigned short idx;
if (ide == 0)
base = 0x1F0;
else
if (ide == 1)
base = 0x170;
else
return 0; // only 2 IDE controllers
outb(base + 3, 0x88); // write
check = inb(base + 3); // read
if (check != 0x88) // check if the magic value is the same
{
puts("Error: the IDE controller does not exist.\n");
return 0;
}
outb(base + 6, 0xA0 | (drive << 4));
sleep(1); // wait a while, min wait time: 400ns
outb(base + 7, 0xEC); //send identify
if (!waituntilbusy(base))
return 0;
buf[0] = inw(base);
if (buf[0]) // if exists
{
puts("Drive exists\n");
for (idx = 1; idx < 256; idx++)
buf[idx] = inw(base); // read a word
if (buf[0] | 0x0040 == buf[0])
puts("Hard drive\n");
else
{
puts("No hard drive\n");
return 0;
}
return 1;
}
else
{
puts("Drive does not exist\n");
return 0;
}
}
As far as I could tell, this check should work.
Scan the PCI Configuration Space
Thanks, I'll try and look up some documents.
Re: Detecting hardware
Posted: Tue Jul 15, 2008 5:49 am
by jal
Masterkiller wrote:PCI-to-ISA bridge may exist even if there isn't any ISA slots on your motherboard.
It's my understanding that all motherboards have a PCI-to-ISA bridge, as most legacy devices (e.g. floppy) are connected to the (internal) ISA bus. But I may be wrong.
JAL
Re: Detecting hardware
Posted: Tue Jul 15, 2008 6:02 am
by Revelation
When I use my detect code outside Bochs, it doesn't detect my SATA drive. Should I do something special for that?
Re: Detecting hardware
Posted: Tue Jul 15, 2008 8:17 am
by jal
Revelation wrote:When I use my detect code outside Bochs, it doesn't detect my SATA drive. Should I do something special for that?
Well, start with explaining how you detect it in Bochs.
JAL
Re: Detecting hardware
Posted: Tue Jul 15, 2008 9:06 am
by Revelation
I don't really. In Bochs I set my ata0-master to a hdd image, so not my real hdd. Also, that's ata0 and not sata.
Re: Detecting hardware
Posted: Wed Jul 16, 2008 3:20 pm
by Revelation
I'm probably doing something very stupid, but why doesn't this work?
Code: Select all
static unsigned long pci_read(unsigned int bus,unsigned int dev,unsigned int func,unsigned int reg)
{
outl(0xCF8, ((unsigned long) 0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | reg));
return inl(0xCFC);
}
void scanpci()
{
unsigned char bus, dev, func;
unsigned long a, value;
unsigned char classcode;
for (bus = 0; bus < 255; bus++)
for (dev = 0; dev < 32; dev++)
for (func = 0; func < 8; func++)
{
a = pci_read(bus, dev, func, 0x08); // class info
classcode = a >> 8;
if (classcode == 0x0C)
puts("USB detected\n");
}
}
Re: Detecting hardware
Posted: Wed Jul 16, 2008 5:21 pm
by Masterkiller
Revelation wrote:I'm probably doing something very stupid, but why doesn't this work?
Code: Select all
static unsigned long pci_read(unsigned int bus,unsigned int dev,unsigned int func,unsigned int reg)
{
outl(0xCF8, ((unsigned long) 0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | reg));
return inl(0xCFC);
}
void scanpci()
{
unsigned char bus, dev, func;
unsigned long a, value;
unsigned char classcode;
for (bus = 0; bus < 255; bus++)
for (dev = 0; dev < 32; dev++)
for (func = 0; func < 8; func++)
{
a = pci_read(bus, dev, func, 0x08); // class info
classcode = a >> 8;
if (classcode == 0x0C)
puts("USB detected\n");
}
}
Suggestion: It depends on the compiler, but mostly "int" type uses current section BITS size. For 16-bit DOS application it should be 16-bit, in 32-bit protected mode 32-bit and in long-mode 64-bit. The "long" type is strict 32-bit in size. You should use it instead of int.
Contents of the 0x08 PCI regitser are 0xCCSSRRRR where, C is class code, S - Subclass, R - Revising. Shifting Right by 8 and in you get 0x00CCSSRR > 0x00010000 so it is impossible to be equal to 0x0C. Shift Right by 24 and you will get what you want.
http://www.acm.uiuc.edu/sigops/roll_your_own/7.c.1.html
According to this document might be better to do it: if(a>>16==0x0C03) to be sure you don't recognize Firewire as a USB
Re: Detecting hardware
Posted: Wed Jul 16, 2008 7:52 pm
by bewing
You recognize SATA by the error "message" that you get back when you try to do an IDENTIFY command on that drive.
The details are in
ATA_PIO_Mode.
Re: Detecting hardware
Posted: Thu Jul 17, 2008 2:56 am
by jal
Masterkiller wrote:The "long" type is strict 32-bit in size. You should use it instead of int.
'int' is guaranteed to be 32 bits on modern 32 and 64 bit platforms. However, instead of directly using long, it's better to define an int32_t type and use that for maximum portability.
JAL
Re: Detecting hardware
Posted: Thu Jul 17, 2008 3:07 am
by AJ
It depends on the compiler, but mostly "int" type uses current section BITS size. For 16-bit DOS application it should be 16-bit, in 32-bit protected mode 32-bit and in long-mode 64-bit. The "long" type is strict 32-bit in size. You should use it instead of int.
Long>=Int
On my i586-32 GCC Cross Compiler, char=8, short = 16, int = 32, long = 32, long long = 64.
On my x86-64 GCC Cross Compiler, char=8, short = 16, int = 32, long = 64, long long = 64.
However, even these sizes are not guaranteed and you should always check before you use them.
Cheers,
Adam