#pragma option -3 #include #include #include "bioslib.h" static int read_config_area(byte function, byte bus_number, byte device_and_function, byte register_number, dword *data); static int write_config_area(byte function, byte bus_number, byte device_and_function, byte register_number, dword data_to_write); /****************************************************************************/ /* */ /* PCI_BIOS_PRESENT */ /* */ /* Purpose: Determine the presence of the PCI BIOS */ /* */ /* Inputs: None */ /* */ /* Outputs: */ /* */ /* byte *hardware_mechanism */ /* Identifies the hardware characteristics used by the platform. */ /* Value not assigned if NULL pointer. */ /* Bit 0 - Mechanism #1 supported */ /* Bit 1 - Mechanism #2 supported */ /* */ /* word *interface_level_version */ /* PCI BIOS Version - Value not assigned if NULL pointer. */ /* High Byte - Major version number */ /* Low Byte - Minor version number */ /* */ /* byte *last_pci_bus_number */ /* Number of last PCI bus in the system. Value not assigned if NULL*/ /* pointer */ /* */ /* Return Value - Indicates presence of PCI BIOS */ /* SUCCESSFUL - PCI BIOS Present */ /* NOT_SUCCESSFUL - PCI BIOS Not Present */ /* */ /****************************************************************************/ int pci_bios_present(byte *hardware_mechanism, word *interface_level_version, byte *last_pci_bus_number) { int ret_status; /* Function Return Status. */ byte bios_present_status;/* Indicates if PCI bios present */ dword pci_signature; /* PCI Signature ('P', 'C', 'I', ' ') */ word ax, bx, cx, flags; /* Temporary variables to hold register values */ /* Load entry registers for PCI BIOS */ _AH = PCI_FUNCTION_ID; _AL = PCI_BIOS_PRESENT; /* Call PCI BIOS Int 1Ah interface */ geninterrupt(0x1a); /* Save registers before overwritten by compiler usage of registers */ ax = _AX; bx = _BX; cx = _CX; pci_signature = _EDX; flags = _FLAGS; bios_present_status = HIGH_BYTE(ax); /* First check if CARRY FLAG Set, if so, BIOS not present */ if ((flags & CARRY_FLAG) == 0) { /* Next, must check that AH (BIOS Present Status) == 0 */ if (bios_present_status == 0) { /* Check bytes in pci_signature for PCI Signature */ if ((pci_signature & 0xff) == 'P' && ((pci_signature >> 8) & 0xff) == 'C' && ((pci_signature >> 16) & 0xff) == 'I' && ((pci_signature >> 24) & 0xff) == ' ') { /* Indicate to caller that PCI bios present */ ret_status = SUCCESSFUL; /* Extract calling parameters from saved registers */ if (hardware_mechanism != NULL) *hardware_mechanism = LOW_BYTE(ax); if (interface_level_version != NULL) *interface_level_version = bx; if (last_pci_bus_number != NULL) *last_pci_bus_number = LOW_BYTE(cx); } } else ret_status = NOT_SUCCESSFUL; } else ret_status = NOT_SUCCESSFUL; return (ret_status); } /****************************************************************************/ /* */ /* FIND_PCI_DEVICE */ /* */ /* Purpose: Determine the location of PCI devices given a specific Vendor */ /* Device ID and Index number. To find the first device, specify */ /* 0 for index, 1 in index finds the second device, etc. */ /* */ /* Inputs: */ /* */ /* word device_id */ /* Device ID of PCI device desired */ /* */ /* word vendor_id */ /* Vendor ID of PCI device desired */ /* */ /* word index */ /* Device number to find (0 - (N-1)) */ /* */ /* Outputs: */ /* */ /* byte *bus_number */ /* PCI Bus in which this device is found */ /* */ /* byte *device_and_function */ /* Device Number in upper 5 bits, Function Number in lower 3 bits */ /* */ /* Return Value - Indicates presence of device */ /* SUCCESSFUL - Device found */ /* NOT_SUCCESSFUL - BIOS error */ /* DEVICE_NOT_FOUND - Device not found */ /* BAD_VENDOR_ID - Illegal Vendor ID (0xffff) */ /* */ /****************************************************************************/ int find_pci_device(word device_id, word vendor_id, word index, byte *bus_number, byte *device_and_function) { int ret_status; /* Function Return Status */ word ax, bx, flags; /* Temporary variables to hold register values */ /* Load entry registers for PCI BIOS */ _CX = device_id; _DX = vendor_id; _SI = index; _AH = PCI_FUNCTION_ID; _AL = FIND_PCI_DEVICE; /* Call PCI BIOS Int 1Ah interface */ geninterrupt(0x1a); /* Save registers before overwritten by compiler usage of registers */ ax = _AX; bx = _BX; flags = _FLAGS; /* First check if CARRY FLAG Set, if so, error has occurred */ if ((flags & CARRY_FLAG) == 0) { /* Get Return code from BIOS */ ret_status = HIGH_BYTE(ax); if (ret_status == SUCCESSFUL) { /* Assign Bus Number, Device & Function if successful */ if (bus_number != NULL) *bus_number = HIGH_BYTE(bx); if (device_and_function != NULL) *device_and_function = LOW_BYTE(bx); } } else ret_status = NOT_SUCCESSFUL; return (ret_status); } /****************************************************************************/ /* */ /* FIND_PCI_CLASS_CODE */ /* */ /* Purpose: Determine the location of PCI devices given a specific Class */ /* Code and Index number. To find the first device, specify */ /* 0 for index, 1 in index finds the second device, etc. */ /* */ /* Inputs: */ /* */ /* word class_code */ /* Class Code of PCI device desired (in lower 3 bytes) */ /* */ /* word index */ /* Device number to find (0 - (N-1)) */ /* */ /* Outputs: */ /* */ /* byte *bus_number */ /* PCI Bus in which this device is found */ /* */ /* byte *device_and_function */ /* Device Number in upper 5 bits, Function Number in lower 3 bits */ /* */ /* Return Value - Indicates presence of device */ /* SUCCESSFUL - Device found */ /* NOT_SUCCESSFUL - BIOS error */ /* DEVICE_NOT_FOUND - Device not found */ /* */ /****************************************************************************/ int find_pci_class_code(dword class_code, word index, byte *bus_number, byte *device_and_function) { int ret_status; /* Function Return Status */ word ax, bx, flags; /* Temporary variables to hold register values */ /* Load entry registers for PCI BIOS */ _ECX = class_code & 0xFFFFFF; _SI = index; _AH = PCI_FUNCTION_ID; _AL = FIND_PCI_CLASS_CODE; /* Call PCI BIOS Int 1Ah interface */ geninterrupt(0x1a); /* Save registers before overwritten by compiler usage of registers */ ax = _AX; bx = _BX; flags = _FLAGS; /* First check if CARRY FLAG Set, if so, error has occurred */ if ((flags & CARRY_FLAG) == 0) { /* Get Return code from BIOS */ ret_status = HIGH_BYTE(ax); if (ret_status == SUCCESSFUL) { /* Assign Bus Number, Device & Function if successful */ if (bus_number != NULL) *bus_number = HIGH_BYTE(bx); if (device_and_function != NULL) *device_and_function = LOW_BYTE(bx); } } else ret_status = NOT_SUCCESSFUL; return (ret_status); } /****************************************************************************/ /* */ /* GENERATE_SPECIAL_CYCLE */ /* */ /* Purpose: Allows for generation of PCI special cycles. The generated */ /* special cycle will be broadcast on a specific PCI bus in the */ /* system. */ /* */ /* Inputs: */ /* */ /* byte bus_number */ /* PCI bus number */ /* */ /* dword special_cycle_data */ /* Special cycle data */ /* */ /* */ /* Outputs: */ /* */ /* Return Value - Indicates presence of device */ /* SUCCESSFUL - Device found */ /* NOT_SUCCESSFUL - BIOS error */ /* FUNC_NOT_SUPPORTED - Function not supported */ /* */ /****************************************************************************/ int generate_special_cycle(byte bus_number, dword special_cycle_data) { int ret_status; /* Function Return Status */ word ax, flags; /* Temporary variables to hold register values */ /* Load entry registers for PCI BIOS */ _EDX = special_cycle_data; _BH = bus_number; _AH = PCI_FUNCTION_ID; _AL = GENERATE_SPECIAL_CYCLE; /* Call PCI BIOS Int 1Ah interface */ geninterrupt(0x1a); /* Save registers before overwritten by compiler usage of registers */ ax = _AX; flags = _FLAGS; /* First check if CARRY FLAG Set, if so, error has occurred */ if ((flags & CARRY_FLAG) == 0) { /* Get Return code from BIOS */ ret_status = HIGH_BYTE(ax); } else ret_status = NOT_SUCCESSFUL; return (ret_status); } /****************************************************************************/ /* */ /* READ_PCI_CONFIG */ /* */ /* Purpose: Reads an entire configuration space of a specific device */ /* */ /* Inputs: */ /* */ /* word device_id */ /* Device ID of device to read */ /* */ /* word vendor_id */ /* Vendor ID of device to read */ /* */ /* word card_index */ /* Card index if more than one card installed (0-(N-1)) */ /* */ /* Outputs: */ /* */ /* TPCICommonConfig *config */ /* PCI Common Config read */ /* */ /* Return Value - Indicates presence of device */ /* SUCCESSFUL - Device found */ /* NOT_SUCCESSFUL - BIOS error */ /* */ /****************************************************************************/ int read_pci_config(word device_id, word vendor_id, word card_index, TPCICommonConfig *config) { int ret_status, i; /* Function Return Status */ byte data; byte bus_number, device_and_function; ret_status = find_pci_device(device_id, vendor_id, card_index, &bus_number, &device_and_function); if (ret_status == SUCCESSFUL) { for (i=0;i<64;i++) { /* Call read_config_area function with dword data */ ret_status = read_config_byte(bus_number, device_and_function, i, &data); if (ret_status == SUCCESSFUL) { memmove((byte*)config+i, &data, 1); } } } return (ret_status); } /****************************************************************************/ /* */ /* READ_CONFIG_DWORD */ /* */ /* Purpose: Reads a dword from the configuration space of a specific device */ /* */ /* Inputs: */ /* */ /* byte bus_number */ /* PCI bus to read configuration data from */ /* */ /* byte device_and_function */ /* Device Number in upper 5 bits, Function Number in lower 3 bits */ /* */ /* byte register_number */ /* Register Number of configuration space to read */ /* */ /* Outputs: */ /* */ /* dword *dword_read */ /* Dword read from Configuration Space */ /* */ /* Return Value - Indicates presence of device */ /* SUCCESSFUL - Device found */ /* NOT_SUCCESSFUL - BIOS error */ /* BAD_REGISTER_NUMBER - Invalid Register Number */ /* */ /****************************************************************************/ int read_config_dword(byte bus_number, byte device_and_function, byte register_number, dword *dword_read) { int ret_status; /* Function Return Status */ dword data; /* Call read_config_area function with dword data */ ret_status = read_config_area(READ_CONFIG_DWORD, bus_number, device_and_function, register_number, &data); if (ret_status == SUCCESSFUL) { /* Extract dword */ *dword_read = data; } return (ret_status); } /****************************************************************************/ /* */ /* READ_CONFIG_WORD */ /* */ /* Purpose: Reads a word from the configuration space of a specific device */ /* */ /* Inputs: */ /* */ /* byte bus_number */ /* PCI bus to read configuration data from */ /* */ /* byte device_and_function */ /* Device Number in upper 5 bits, Function Number in lower 3 bits */ /* */ /* byte register_number */ /* Register Number of configuration space to read */ /* */ /* Outputs: */ /* */ /* word *word_read */ /* Word read from Configuration Space */ /* */ /* Return Value - Indicates presence of device */ /* SUCCESSFUL - Device found */ /* NOT_SUCCESSFUL - BIOS error */ /* BAD_REGISTER_NUMBER - Invalid Register Number */ /* */ /****************************************************************************/ int read_config_word(byte bus_number, byte device_and_function, byte register_number, word *word_read) { int ret_status; /* Function Return Status */ dword data; /* Call read_config_area function with word data */ ret_status = read_config_area(READ_CONFIG_WORD, bus_number, device_and_function, register_number, &data); if (ret_status == SUCCESSFUL) { /* Extract word */ *word_read = (word)(data & 0xffff); } return (ret_status); } /****************************************************************************/ /* */ /* READ_CONFIG_BYTE */ /* */ /* Purpose: Reads a byte from the configuration space of a specific device */ /* */ /* Inputs: */ /* */ /* byte bus_number */ /* PCI bus to read configuration data from */ /* */ /* byte device_and_function */ /* Device Number in upper 5 bits, Function Number in lower 3 bits */ /* */ /* byte register_number */ /* Register Number of configuration space to read */ /* */ /* Outputs: */ /* */ /* byte *byte_read */ /* Byte read from Configuration Space */ /* */ /* Return Value - Indicates presence of device */ /* SUCCESSFUL - Device found */ /* NOT_SUCCESSFUL - BIOS error */ /* BAD_REGISTER_NUMBER - Invalid Register Number */ /* */ /****************************************************************************/ int read_config_byte(byte bus_number, byte device_and_function, byte register_number, byte *byte_read) { int ret_status; /* Function Return Status */ dword data; /* Call read_config_area function with byte data */ ret_status = read_config_area(READ_CONFIG_BYTE, bus_number, device_and_function, register_number, &data); if (ret_status == SUCCESSFUL) { /* Extract byte */ *byte_read = (byte)(data & 0xff); } return (ret_status); } /****************************************************************************/ /* */ /* READ_CONFIG_AREA */ /* */ /* Purpose: Reads a byte/word/dword from the configuration space of a */ /* specific device */ /* */ /* Inputs: */ /* */ /* byte bus_number */ /* PCI bus to read configuration data from */ /* */ /* byte device_and_function */ /* Device Number in upper 5 bits, Function Number in lower 3 bits */ /* */ /* byte register_number */ /* Register Number of configuration space to read */ /* */ /* Outputs: */ /* */ /* dword *dword_read */ /* Dword read from Configuration Space */ /* */ /* Return Value - Indicates presence of device */ /* SUCCESSFUL - Device found */ /* NOT_SUCCESSFUL - BIOS error */ /* BAD_REGISTER_NUMBER - Invalid Register Number */ /* */ /****************************************************************************/ static int read_config_area(byte function, byte bus_number, byte device_and_function, byte register_number, dword *data) { int ret_status; /* Function Return Status */ word ax, flags; /* Temporary variables to hold register values */ dword ecx; /* Temporary variable to hold ECX register value */ /* Load entry registers for PCI BIOS */ _BH = bus_number; _BL = device_and_function; _DI = register_number; _AH = PCI_FUNCTION_ID; _AL = function; /* Call PCI BIOS Int 1Ah interface */ geninterrupt(0x1a); /* Save registers before overwritten by compiler usage of registers */ ecx = _ECX; ax = _AX; flags = _FLAGS; /* First check if CARRY FLAG Set, if so, error has occurred */ if ((flags & CARRY_FLAG) == 0) { /* Get Return code from BIOS */ ret_status = HIGH_BYTE(ax); /* If successful, return data */ if (ret_status == SUCCESSFUL) *data = ecx; } else ret_status = NOT_SUCCESSFUL; return (ret_status); } /****************************************************************************/ /* */ /* WRITE_CONFIG_DWORD */ /* */ /* Purpose: Writes a dword to the configuration space of a specific device */ /* */ /* Inputs: */ /* */ /* byte bus_number */ /* PCI bus to write configuration data to */ /* */ /* byte device_and_function */ /* Device Number in upper 5 bits, Function Number in lower 3 bits */ /* */ /* byte register_number */ /* Register Number of configuration space to write */ /* */ /* dword dword_to_write */ /* Dword to write to Configuration Space */ /* */ /* Outputs: */ /* */ /* Return Value - Indicates presence of device */ /* SUCCESSFUL - Device found */ /* NOT_SUCCESSFUL - BIOS error */ /* BAD_REGISTER_NUMBER - Invalid Register Number */ /* */ /****************************************************************************/ int write_config_dword(byte bus_number, byte device_and_function, byte register_number, dword dword_to_write) { int ret_status; /* Function Return Status */ register_number &= 0xFC; /* Force register_number to dword alignment */ /* Call write_config_area function with dword data */ ret_status = write_config_area(WRITE_CONFIG_DWORD, bus_number, device_and_function, register_number, dword_to_write); return (ret_status); } /****************************************************************************/ /* */ /* WRITE_CONFIG_WORD */ /* */ /* Purpose: Writes a word to the configuration space of a specific device */ /* */ /* Inputs: */ /* */ /* byte bus_number */ /* PCI bus to write configuration data to */ /* */ /* byte device_and_function */ /* Device Number in upper 5 bits, Function Number in lower 3 bits */ /* */ /* byte register_number */ /* Register Number of configuration space to write */ /* */ /* word word_to_write */ /* Word to write to Configuration Space */ /* */ /* Outputs: */ /* */ /* Return Value - Indicates presence of device */ /* SUCCESSFUL - Device found */ /* NOT_SUCCESSFUL - BIOS error */ /* BAD_REGISTER_NUMBER - Invalid Register Number */ /* */ /****************************************************************************/ int write_config_word(byte bus_number, byte device_and_function, byte register_number, word word_to_write) { int ret_status; /* Function Return Status */ register_number &= 0xFE; /* Force register_number to word alignment */ /* Call write_config_area function with word data */ ret_status = write_config_area(WRITE_CONFIG_WORD, bus_number, device_and_function, register_number, word_to_write); return (ret_status); } /****************************************************************************/ /* */ /* WRITE_CONFIG_BYTE */ /* */ /* Purpose: Writes a byte to the configuration space of a specific device */ /* */ /* Inputs: */ /* */ /* byte bus_number */ /* PCI bus to write configuration data to */ /* */ /* byte device_and_function */ /* Device Number in upper 5 bits, Function Number in lower 3 bits */ /* */ /* byte register_number */ /* Register Number of configuration space to write */ /* */ /* byte byte_to_write */ /* Byte to write to Configuration Space */ /* */ /* Outputs: */ /* */ /* Return Value - Indicates presence of device */ /* SUCCESSFUL - Device found */ /* NOT_SUCCESSFUL - BIOS error */ /* BAD_REGISTER_NUMBER - Invalid Register Number */ /* */ /****************************************************************************/ int write_config_byte(byte bus_number, byte device_and_function, byte register_number, byte byte_to_write) { int ret_status; /* Function Return Status */ /* Call write_config_area function with byte data */ ret_status = write_config_area(WRITE_CONFIG_BYTE, bus_number, device_and_function, register_number, byte_to_write); return (ret_status); } /****************************************************************************/ /* */ /* WRITE_CONFIG_AREA */ /* */ /* Purpose: Writes a byte/word/dword to the configuration space of a */ /* specific device */ /* */ /* Inputs: */ /* */ /* byte bus_number */ /* PCI bus to write configuration data to */ /* */ /* byte device_and_function */ /* Device Number in upper 5 bits, Function Number in lower 3 bits */ /* */ /* byte register_number */ /* Register Number of configuration space to write */ /* */ /* dword data_to_write */ /* Data to write to Configuration Space */ /* */ /* Outputs: */ /* */ /* Return Value - Indicates presence of device */ /* SUCCESSFUL - Device found */ /* NOT_SUCCESSFUL - BIOS error */ /* BAD_REGISTER_NUMBER - Invalid Register Number */ /* */ /****************************************************************************/ static int write_config_area(byte function, byte bus_number, byte device_and_function, byte register_number, dword data_to_write) { int ret_status; /* Function Return Status */ word ax, flags; /* Temporary variables to hold register values */ /* Load entry registers for PCI BIOS */ _BH = bus_number; _BL = device_and_function; _DI = register_number; _ECX= data_to_write; _AH = PCI_FUNCTION_ID; _AL = function; /* Call PCI BIOS Int 1Ah interface */ geninterrupt(0x1a); /* Save registers before overwritten by compiler usage of registers */ ax = _AX; flags = _FLAGS; /* First check if CARRY FLAG Set, if so, error has occurred */ if ((flags & CARRY_FLAG) == 0) { /* Get Return code from BIOS */ ret_status = HIGH_BYTE(ax); } else ret_status = NOT_SUCCESSFUL; return (ret_status); }