Detecting hardware

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
User avatar
Revelation
Member
Member
Posts: 47
Joined: Sat Jun 21, 2008 8:15 am

Detecting hardware

Post 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?
Now is the winter of my disk content.
User avatar
suthers
Member
Member
Posts: 672
Joined: Tue Feb 20, 2007 3:00 pm
Location: London UK
Contact:

Re: Detecting hardware

Post by suthers »

Use PIO, this a fairly good tutorial:
http://www.osdever.net/tutorials/lba.php
or DMA works too...
Jules
User avatar
Masterkiller
Member
Member
Posts: 153
Joined: Sat May 05, 2007 6:20 pm

Re: Detecting hardware

Post 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.
ALCA OS: Project temporarity suspended!
Current state: real-mode kernel-FS reader...
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Detecting hardware

Post 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.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
Masterkiller
Member
Member
Posts: 153
Joined: Sat May 05, 2007 6:20 pm

Re: Detecting hardware

Post 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).
ALCA OS: Project temporarity suspended!
Current state: real-mode kernel-FS reader...
User avatar
Revelation
Member
Member
Posts: 47
Joined: Sat Jun 21, 2008 8:15 am

Re: Detecting hardware

Post 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.
Now is the winter of my disk content.
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Re: Detecting hardware

Post 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
User avatar
Revelation
Member
Member
Posts: 47
Joined: Sat Jun 21, 2008 8:15 am

Re: Detecting hardware

Post by Revelation »

When I use my detect code outside Bochs, it doesn't detect my SATA drive. Should I do something special for that?
Now is the winter of my disk content.
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Re: Detecting hardware

Post 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
User avatar
Revelation
Member
Member
Posts: 47
Joined: Sat Jun 21, 2008 8:15 am

Re: Detecting hardware

Post 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.
Now is the winter of my disk content.
User avatar
Revelation
Member
Member
Posts: 47
Joined: Sat Jun 21, 2008 8:15 am

Re: Detecting hardware

Post 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");
}

}
Now is the winter of my disk content.
User avatar
Masterkiller
Member
Member
Posts: 153
Joined: Sat May 05, 2007 6:20 pm

Re: Detecting hardware

Post 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 ;)
ALCA OS: Project temporarity suspended!
Current state: real-mode kernel-FS reader...
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: Detecting hardware

Post 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.
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Re: Detecting hardware

Post 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
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Re: Detecting hardware

Post 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
Post Reply