Jump to content
  • Sky
  • Blueberry
  • Slate
  • Blackcurrant
  • Watermelon
  • Strawberry
  • Orange
  • Banana
  • Apple
  • Emerald
  • Chocolate
  • Charcoal
Sign in to follow this  

Proposal for main component bus interface [OC2]

Recommended Posts

Draft 1


D1:   2016-08-05T02:45:39+00:00

$ date -u -Iseconds

There are two address spaces for all components: the config space, and the main I/O space.

Every component has a VID (virtual ID) and that is how components are addressed. Every VID should be physically settable to any 8-bit value on each component. Any component with a VID set to 0xFF is rendered inaccessible by any methods that address by VID.

Every component also has a PID (physical ID) which indicates the physical location of this component on a given bus master.

The config space is read-only. Everything in the config space is readable by any bit width.


This bus is little-endian.

These fields are compulsory, and every component needs to read at least the bottom 3 address bits:

  • 0x00[4]: 4-byte type ID. Forms a 4-char ASCII string.
  • 0x04[1]: Bus PID.
  • 0x05[1]: Bus master VID. 0xFF if using the root bus master.
  • 0x06[1]: Bus PID with all bits inverted.
  • 0x07[1]: Bus master VID with all bits inverted.
These two fields are optional, and there is no requirement for bit 3 to be read:
  • 0x08[4]: 4-byte extension ID #1.
  • 0x0C[4]: 4-byte extension ID #2.
Components are allowed to go further than this.

Open bus is 0xFFFFFFFF, because that's what us low-level weirdos tend to expect. This applies to all busses. Because of this, if you have a type ID of 0xFFFFFFFF, that VID has no component using it.

The root bus master (it'll be on your motherboard) is of course an exception to a lot of these rules:

  • VID is always 0xFF and it is completely unconfigurable.
  • PID is 0xFF too. So is the bus master VID.
  • If the ID is 0xFFFFFFFF, then this bus master cannot be reconfigured, but there's DEFINITELY a bus master here.
  • Basically, if you have a "dumb" bus master, the config space will be open bus, which also means that a bus conflict check will fail.
Components should avoid using any I/O ports outside of 0x00-0x7F in its main I/O bus for ease of addressability with a lot of CPUs.

Some components will have standard VID slots. Conflicts should be avoided where possible. Proposed standard slots:

  • 0x00: Various BIOS EEPROMs would probably end up using this.
  • 0xDB: Serial debug interface. ID is "Dbg0". Write to 0x00 to output byte, read from 0x00 to input byte, -1 will be returned if no byte is available, bus is actually 32 bits wide, but can be accessed by byte, reads from 0x01-0x03 are buffered.
For an example, here's how things would be addressed on MIPS:
  • 0x0+++++++: User virtual memory space
  • 0x800xxxxx: Cached RAM (bit mask is for 1MB)
  • 0xA00xxxxx: Uncached RAM (bit mask is for 1MB)
  • 0xBEvv00rr: Uncached Config space for VID=v, address=r
  • 0xBFvvrrrr: Uncached Main I/O space for VID=v, address=r
  • 0xC+++++++: Kernel virtual memory space

These are in MIPS assembly. There is no op reordering, but I have decided to insert NOPs in delay slots just for the sake of readability. I have also decided to use the LA ("Load Address") pseudo-op as a load-immediate so things are a bit more obvious.

To clarify: LA loads the 32-bit value you see there DIRECTLY - it does not do a memory load. (It's also reasonably likely to use 2 real ops, although I think there's really only one place here where it actually does.)

I have tried to avoid MIPSisms here.

Component presence detection: (ID in $a0, $v0 returns nonzero if there is a component)

LA      $t0,      0xBE000000
ANDI    $t1, $a0, 0x00FF
SLL     $t1, $t1, 16
ORI     $t0, $t0, $t1
LW      $t1,      0x00($t0)
ADDIU   $v0, $v0, 1 // convert 0xFFFFFFFF -> 0
JR      $ra
Bus conflict detection: (ID in $a0, $v0 returns nonzero if there is a conflict, note this will trigger if there is no component)

LA      $t0,      0xBE000000
ANDI    $t1, $a0, 0x00FF
SLL     $t1, $t1, 16
ORI     $t0, $t0, $t1
LH      $t1,      0x04($t0) // LH is a signed load, thus you get a sign extension
LH      $t2,      0x06($t0)
XOR     $v0, $t1, $t2
ADDIU   $v0, $v0, 1 // convert 0xFFFFFFFF -> 0, or 0 -> 1
JR      $ra
Fun thing, if there is no component here, you will get 1 in $v0, so you can do this:

MOVE    $a0,      $s0
J       detect_bus_conflict
LA      $t0,      1
BEQ     $v0, $t0, _vid_does_not_exist
BNEZ    $v0,      _vid_has_bus_conflict
Finally, how to spew "Hello World!" down every Dbg0 device (as opposed to just assuming that it's at 0xDB):

LA      $t0,      0xBE000000
LA      $t1,      0x00010000
LA      $t2,      255
LA      $t3,      'Dbg0'


// Detect Dbg0 component
LW      $t4,      0x00($t0)
BNE     $t4, $t3, _loop_find_continue

// Print hello message
LA      $t6,      str_hello
LA      $t5,      0x01000000
LB      $t7,      0($t6) // Preload first byte
ADDU    $t5, $t5, $t0 // 0xBFxxxxxx address

// Actual print loop
SB      $t7,      0($t5)
ADDIU   $t6, $t6, 1
LB      $t7,      0($t6)
BNEZ    $t7,      _loop_hello

// Advance loop
ADDIU   $t2, $t2, -1
ADDU    $t0, $t0, $t1
BNEZ    $t2,      _loop_find

// Return
JR $ra

// Read-only data
str_hello: .asciiz "Hello World!\n"

Share this post

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

  • Create New...

Important Information

By using this site, you agree to our Terms of Use and Privacy Policy.