Previous Next Contents

2. General

2.1 Resources

All cards get their resources (memory and IO areas, interrupts) assigned and set by the system. Drivers and other programs may not modify these settings.

2.2 Calling Conventions

The PCI BIOS functions use the 680x0 CPU registers to pass arguments and to return status.

The routines may modify only those registers which are used to pass parameters or to return information in as specified for the specific function, plus the status register.

The routines must be called in Supervisor mode, and the available stack must be at least 1024 bytes.

The functions may disable interrupts during execution, but will return with the interrupts in the same state as when they were called.

All functions return an error code in D0 if an error occurred.

2.3 Device Handles

Every device on a PCI (or ISA) card is specified by using a device handle. The device handle is used as an opaque data type by the driver - no assumptions are to be made about the meaning of bits in this value. device handles are positive 32-bit integers - negative values are used for error codes for functions which return device handles.

2.4 Locating the function entry points

The BIOS installs a "_PCI" cookie which points to the following structure of entry points to the individual functions:


dc.l  0                         ; $00 pointer to sub cookie jar (for 
                                ; compatibility) or 0 if not present
dc.l  $00010000                 ; $04 version number of this structure
dc.l  find_pci_device           ; $08
dc.l  find_pci_classcode        ; $0C 
dc.l  read_config_byte          ; $10
dc.l  read_config_word          ; $14
dc.l  read_config_longword      ; $18
dc.l  fast_read_config_byte     ; $1C
dc.l  fast_read_config_word     ; $20
dc.l  fast_read_config_longword ; $24
dc.l  write_config_byte         ; $28
dc.l  write_config_word         ; $2C
dc.l  write_config_longword     ; $30
dc.l  hook_interrupt            ; $34
dc.l  unhook_interrupt          ; $38
dc.l  special_cycle             ; $3C
dc.l  get_routing               ; $40
dc.l  set_interrupt             ; $44
dc.l  get_resource              ; $48
dc.l  get_card_used             ; $4C
dc.l  set_card_used             ; $50
dc.l  read_mem_byte             ; $54
dc.l  read_mem_word             ; $58
dc.l  read_mem_longword         ; $5C
dc.l  fast_read_mem_byte        ; $60
dc.l  fast_read_mem_word        ; $64
dc.l  fast_read_mem_longword    ; $68
dc.l  write_mem_byte            ; $6C
dc.l  write_mem_word            ; $70
dc.l  write_mem_longword        ; $74
dc.l  read_io_byte              ; $78
dc.l  read_io_word              ; $7C
dc.l  read_io_longword          ; $80
dc.l  fast_read_io_byte         ; $84
dc.l  fast_read_io_word         ; $88
dc.l  fast_read_io_longword     ; $8C
dc.l  write_io_byte             ; $90
dc.l  write_io_word             ; $94
dc.l  write_io_longword         ; $98
dc.l  get_machine_id            ; $9C
dc.l  get_pagesize              ; $A0
dc.l  virt_to_bus               ; $A4
dc.l  bus_to_virt               ; $A8
dc.l  virt_to_phys              ; $AC
dc.l  phys_to_virt              ; $B0

The high word of the version number marks major changes which affect compatibility with older programs (this should be avoided). The minor version number marks changes in the structure which only add function entries or fix bugs in existing ones, but which do not cause incompatibilities with earlier revisions.

This structure, and the functions it points to, should be in ROM or some other place which is safe from being overwritten (eg. above phystop), if it is desirable that alternative Operating Systems can use the functions.

The circumstances for calling the functions may need to be specified further for this case.

2.5 Interrupt Handlers

For each hardware interrupt, there is a chain of interrupt handlers, as multiple cards can share the same interrupt.

By specifying a device handle, a driver can hook into the chain that handles this interrupt without knowing which one it actually is.

When an interrupt occurs, the driver is called with a value in A0 which is set by the driver when hooking into the interrupt. The meaning of this parameter depends on the driver - it can be a device handle, a pointer to some driver-internal data structure, etc..


interrupt_handler:
Input:
  A0.L   value as passed to hook_interrupt
  D0.L   BIOS internal data
Output:
  D0.L   bit 0 set if the interrupt was from this card. D0 unmodified
         otherwise.

The interrupt handler must not modify any register except D0 (only as specified) and A0. If the interrupt was caused by the card which this handler is monitoring, it must make sure that the card returns the interrupt line to inactive state, and return with D0.0 set.

If the card did not cause the interrupt, the driver may not modify D0.

The interrupt handler returns by using an RTS instruction.

2.6 Error codes

The following error codes can be returned by the PCI BIOS functions:


 $00000000   PCI_SUCCESSFUL
 $FFFFFFFE   PCI_FUNC_NOT_SUPPORTED
 $FFFFFFFD   PCI_BAD_VENDOR_ID
 $FFFFFFFC   PCI_DEVICE_NOT_FOUND
 $FFFFFFFB   PCI_BAD_REGISTER_NUMBER
 $FFFFFFFA   PCI_SET_FAILED
 $FFFFFFF9   PCI_BUFFER_TOO_SMALL
 $FFFFFFF8   PCI_GENERAL_ERROR
 $FFFFFFF7   PCI_BAD_HANDLE

The following error codes are not returned by PCI BIOS functions directly, but are reserved for use by a library which uses these routines.


 $FFFFF001   PCI_BIOS_NOT_INSTALLED
 $FFFFF000   PCI_BIOS_WRONG_VERSION 


Previous Next Contents