Now that reads and writes accesses are going through, what does it take for the PCI plug-and-play to work?
Our PCI card is not yet in the list...
Remember that PCI cards have three "spaces" where transactions (reads and writes) take place?
- Memory space
- IO space
- Configuration space
The configuration space is the heart of PCI plug-and-play.
The OS (Windows, Linux...) reads there first to find if PCI cards are plugged-in, and their characteristics.
For simple boards, the configuration space consists of just 64 bytes.
They important fields are:
|0||Vendor ID||Manufacturer number||... allocated by the PCI-SIG||2 bytes
|2||Device ID||Device number||... allocated by the manufacturers themselves||2 bytes
|4||Command||Turn on and off accesses to the PCI board||... but configuration space accesses are always on||2 bytes
|16||BAR0 (Base address register 0)||Address at which the PCI board should respond||... followed by BAR1 through BAR5||4 bytes each
By implementing the right values and registers at these locations, the OS can "find" the PCI card.
Configuration space transactions
Each PCI slots as a signal called IDSEL.
The IDSEL signal is not shared along the bus; each PCI slot has its own.
When a PCI card sees a configuration space transaction on the bus, and its own IDSEL is asserted, it knows it should respond.
parameter PCI_CBECD_CSRead = 4'b1010; // configuration space read|
parameter PCI_CBECD_CSWrite = 4'b1011; // configuration space write
wire PCI_Targeted = PCI_TransactionStart & PCI_IDSEL & ((PCI_CBE==PCI_CBECD_CSRead) | (PCI_CBE==PCI_CBECD_CSWrite)) & (PCI_AD[1:0]==0);
After that, it can be a read or a write but it works the same way than memory or IO spaces do.
A few details:
- For the Vendor ID, let's just pick a number; we are just experimenting, right? ok, 0x0100 works fine.
- Device ID can be left at 0
- Command bit 0 is the "on/off" bit for the IO space, while bit 1 is the "on/off" bit for the Memory space.
- BAR0 is a register that is written by the OS, once it decides at which address the PCI card should be located.
There are a few other details left out, like some bits of BAR0 are read-only...
Please refer to a PCI specification/book for the down-to-earth details.
Once these registers are implemented, the OS can discover the new hardware.
But the OS requires a driver before...
... it agrees to allocate the memory resource.