accessing the network card
accessing the network card
HI
How can we find the network card on the PCI bus and access its memory addresses and registers. Main idea is to initialize the NIC, access its address space.
Can someone provide any links for this information
BR
Alok
How can we find the network card on the PCI bus and access its memory addresses and registers. Main idea is to initialize the NIC, access its address space.
Can someone provide any links for this information
BR
Alok
- Combuster
- 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: accessing the network card
You may want to look up your keywords in the wiki before posting them here: PCI
Re: accessing the network card
Hi,
Yes had gone through that before posting!!. My code for now has a bootloader that jumps to c code which has set gdt and idt. Now i want to access pci deivces i.e NIC.
So needed some guidance on that!!
BR
Alok
Yes had gone through that before posting!!. My code for now has a bootloader that jumps to c code which has set gdt and idt. Now i want to access pci deivces i.e NIC.
So needed some guidance on that!!
BR
Alok
Re: accessing the network card
The article Combuster linked to describes how to access PCI devices; it is now up to you to find the device you need in PCI configuration space and to program it (which is usually somewhat dependant on the device itself). If it's a specific network card you're looking for, you might have some luck browsing through the category.
When the chance of succeeding is 99%, there is still a 50% chance of that success happening.
Re: accessing the network card
You should implement functions to scan the pci bus and to read/write to pci registers. Then you will have something like:
The wiki is very helpful regarding PCI bus.
The install routine for the speciifc network card could be like this:
Good luck!
Code: Select all
void pciScan()
{
for (uint32_t i=0;i<PCIARRAYSIZE;++i)
{
pciDev_Array[i].number = i;
}
int number=0;
for (uint8_t bus = 0; bus < 4; ++bus) // we scan only four busses of 256 possibles
{
for (uint8_t device = 0; device < 32; ++device)
{
for (uint8_t func = 0; func < 8; ++func)
{
uint16_t vendorID = pci_config_read(bus, device, func, PCI_VENDOR_ID);
if (vendorID && (vendorID != 0xFFFF))
{
//...
/// RTL 8139 network card
if ((pciDev_Array[number].deviceID == 0x8139))
{
install_RTL8139(number);
}
++number;
The install routine for the speciifc network card could be like this:
Code: Select all
void install_RTL8139(uint32_t number)
{
for (uint8_t j=0;j<6;++j) // check network card BARs
{
pciDev_Array[number].bar[j].memoryType = pciDev_Array[number].bar[j].baseAddress & 0x01;
if (pciDev_Array[number].bar[j].baseAddress) // check valid BAR
{
if (pciDev_Array[number].bar[j].memoryType == 0)
{
BaseAddressRTL8139_MMIO = pciDev_Array[number].bar[j].baseAddress &= 0xFFFFFFF0;
}
if (pciDev_Array[number].bar[j].memoryType == 1)
{
BaseAddressRTL8139_IO = pciDev_Array[number].bar[j].baseAddress &= 0xFFFC;
}
}
}
http://www.henkessoft.de/OS_Dev/OS_Dev3.htm (OSDEV)
http://www.c-plusplus.de/forum/viewforu ... is-62.html
irc.euirc.net #PrettyOS
http://www.c-plusplus.de/forum/viewforu ... is-62.html
irc.euirc.net #PrettyOS
Re: accessing the network card
Hi
Thanks for the reply
To do this i'll need to implement pci_config_read function also.
One more thing i was following the wiki page http://wiki.osdev.org/RTL8169. Here it tells how to get the MAC address of the card. Is this tutorial correct?
Now to get the I/O base address from PCI configuration space i used lspci command and ifconfig and i got the following
lspci
Thanks
Alok
Thanks for the reply
To do this i'll need to implement pci_config_read function also.
One more thing i was following the wiki page http://wiki.osdev.org/RTL8169. Here it tells how to get the MAC address of the card. Is this tutorial correct?
Now to get the I/O base address from PCI configuration space i used lspci command and ifconfig and i got the following
lspci
and ifconfig i get05:00.0 Ethernet controller: Broadcom Corporation NetXtreme II BCM5708 Gigabit Ethernet (rev 12)
Subsystem: Hewlett-Packard Company NC373i Integrated Multifunction Gigabit Server Adapter
Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV+ VGASnoop- ParErr+ Stepping- SERR+ FastB2B-
Status: Cap+ 66MHz+ UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR-
Latency: 64 (16000ns min), Cache Line Size: 64 bytes
Interrupt: pin A routed to IRQ 130
Region 0: Memory at fa000000 (64-bit, non-prefetchable) [size=32M]
[virtual] Expansion ROM at d1200000 [disabled] [size=2K]
Capabilities: [40] PCI-X non-bridge device
Command: DPERE- ERO- RBC=512 OST=8
Status: Dev=05:00.0 64bit+ 133MHz+ SCD- USC- DC=simple DMMRBC=512 DMOST=8 DMCRS=32 RSCEM- 266MHz- 533MHz-
Capabilities: [48] Power Management version 2
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot+,D3cold+)
Status: D0 PME-Enable- DSel=0 DScale=1 PME-
Capabilities: [50] Vital Product Data
Capabilities: [58] Message Signalled Interrupts: 64bit+ Queue=0/0 Enable+
Address: 00000000fee01000 Data: 4082
So is the I/O base address fa000000???eth1 Link encap:Ethernet HWaddr 00:1F:29:CC:BC:12
inet addr:10.58.112.248 Bcast:10.58.112.255 Mask:255.255.255.0
inet6 addr: fe80::21ffecc:bc12/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:103895656 errors:1 dropped:0 overruns:0 frame:1
TX packets:73155493 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:702144647 (669.6 MiB) TX bytes:561130821 (535.1 MiB)
Interrupt:82 Memory:fa000000-fa012100
Thanks
Alok
Re: accessing the network card
Kind of. The lspci output (in particular) states that it owns a chunk of *memory* at that location. Not IO address space, which in many cases is only used for legacy compatibility; most stuff uses memory mapping like that.aloktiagi wrote:So is the I/O base address fa000000???
That chunk of memory will, however, have the various controls registers, buffers and whatever else laid out within it (though you'll likely need to find documentation for that specific card or series of cards)
Re: accessing the network card
Hi,
So how do i find out the I/O base address of a device when i jump from my bootloader to the c code without the OS being there i.e no lspci command!!!
Regards
Alok
So how do i find out the I/O base address of a device when i jump from my bootloader to the c code without the OS being there i.e no lspci command!!!
Regards
Alok
- Combuster
- 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: accessing the network card
Please, if you ask an answered question again in the same thread it only makes you look like you are lazy and want to be spoon-fed code. Please read the links posted earlier in this thread before trying again. If you do actually get stuck, at least make some effort showing us what you did so far. (see here why)So how do i find out the I/O base address of a device when i jump from my bootloader to the c code without the OS being there i.e no lspci command!!!
I wrote:You may want to look up your keywords in the wiki before posting them here: PCI
Re: accessing the network card
Hi,
In code at the PCI Wiki link
What is meant by the offset??
Alok
In code at the PCI Wiki link
Code: Select all
unsigned short pciConfigReadWord (unsigned short bus, unsigned short slot,
unsigned short func, unsigned short offset)
{
unsigned long address;
unsigned long lbus = (unsigned long)bus;
unsigned long lslot = (unsigned long)slot;
unsigned long lfunc = (unsigned long)func;
unsigned short tmp = 0;
/* create configuration address as per Figure 1 */
address = (unsigned long)((lbus << 16) | (lslot << 11) |
(lfunc << 8) | (offset & 0xfc) | ((UINT32)0x80000000));
/* write out the address */
sysOutLong (0xCF8, address);
/* read in the data */
tmp = (unsigned short)((sysInLong (0xCFC) >> ((offset & 2) * 8)) & 0xffff);
return (tmp);
}
Alok
- Combuster
- 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: accessing the network card
What do (should) you do when you don't know what a word means: you derive it from the context. The same holds for code:
Draw the lines and entertain meEnable Bit - Reserved - Bus Number - Device Number - Function Number - Register Number - 00
(...)
/* create configuration address as per Figure 1 */
address = (unsigned long)((lbus << 16) | (lslot << 11) | (lfunc << 8 ) | (offset & 0xfc) | ((UINT32)0x80000000));
Re: accessing the network card
Hi,
Currently my code goes like this (my broadcom BCM5708 card's parameters are bus 3 and device 0)
The output i get is
Now the http://wiki.osdev.org/PCI link tells that to retrieve the actual base address of a BAR
we need to mask the lower bits, i.e BAR[x] & 0xFFFFFFF0 for 32 bit. So after this i get the BAR address as 0xF800000.
So from 0xF800000 can i now access the NIC's registers, for e.g get the MAC address values?
Regards
Alok
Currently my code goes like this (my broadcom BCM5708 card's parameters are bus 3 and device 0)
Code: Select all
for(i=0;i<10;i++)
{
idx = 0x80000000 + ((0x03&0xFF)<<16) + ((0x00&0x1F)<<11) + ((0x00&0x7)<<8) + (header&0xFC);
outl(idx,0xCF8);
tmp = inl(0xCFC);
if ( tmp == ~0 ) printf("alok");
printf( " ADDR=%X REG VAL=%X \n",header, tmp);
header=header+0x04;
}
So 0xF800004 is my BAR0 value.ADDR=0 REG VAL=164C14E4 Device and vendor ID
ADDR=4 REG VAL=2B00156
ADDR=8 REG VAL=2000011
ADDR=C REG VAL=4010
ADDR=10 REG VAL=F8000004
ADDR=14 REG VAL=0
ADDR=18 REG VAL=0
ADDR=1C REG VAL=0
ADDR=20 REG VAL=0
ADDR=24 REG VAL=0
Now the http://wiki.osdev.org/PCI link tells that to retrieve the actual base address of a BAR
we need to mask the lower bits, i.e BAR[x] & 0xFFFFFFF0 for 32 bit. So after this i get the BAR address as 0xF800000.
So from 0xF800000 can i now access the NIC's registers, for e.g get the MAC address values?
Regards
Alok
Re: accessing the network card
Also in addition to the above query one more problem!
From the wiki page http://wiki.osdev.org/Inline_Assembly/Examples i found out the implementation of both inb and outb but i'm having a problem implementing inl
For inb its like
But how do i do it for inl i've tried replacing %0 with %%eax but that doesn't work !!!
From the wiki page http://wiki.osdev.org/Inline_Assembly/Examples i found out the implementation of both inb and outb but i'm having a problem implementing inl
For inb its like
Code: Select all
static __inline__ unsigned char inb(unsigned short port)
{
unsigned char ret;
asm volatile ("inb %1,%0":"=a"(ret):"Nd"(port));
return ret;
}
Re: accessing the network card
You have to replace the inb instruction with inl and change the type of ret since an unsigned char is too small for inl (which means in long, btw)
Also, from reading your postings I strongly suggest you to read some C and assembly tutorials
Furthermore, if you get to that point, you need to modify the pci device's control register to be able to access its io address space. If I remember correctly you have to set bit 0 for the io and bit 1 for the memory address space.
If you don't do that, you will just get all zeroes when accessing the device's address space. When I implemented my first PCI device driver I failed to realise this for hours and I only found out after reading the pci specifications
Also, from reading your postings I strongly suggest you to read some C and assembly tutorials
Furthermore, if you get to that point, you need to modify the pci device's control register to be able to access its io address space. If I remember correctly you have to set bit 0 for the io and bit 1 for the memory address space.
If you don't do that, you will just get all zeroes when accessing the device's address space. When I implemented my first PCI device driver I failed to realise this for hours and I only found out after reading the pci specifications
Re: accessing the network card
Yes i got that after some time char was small for inl!!
The PCI page says that to calculate I/O base address we shud do
(BAR[x] & 0xFFFFFFFC).
Is it same as what u have said
The PCI page says that to calculate I/O base address we shud do
(BAR[x] & 0xFFFFFFFC).
Is it same as what u have said
If I remember correctly you have to set bit 0 for the io and bit 1 for the memory address space.