www.pudn.com > ScriptsSample.zip > SPCI.C
/*--------------------------------------------------*/ /* */ /* Module SPCI.C */ /* */ /* PCI access functions for sample code. */ /* */ /* Adapted from Symbios Logic */ /* Software Development Kit */ /* */ /* Project: A Programmer's Guide to SCSI */ /* Copyright (C) 1997, Brian Sawert. */ /* All rights reserved. */ /* */ /*--------------------------------------------------*/ #include#include #include #include "gen_tool.h" // generic tools #include "spci.h" // PCI definitions #include "s8xx.h" // Symbios 8XX definitions #pragma inline // enable inline assembly /*---------- defines and macros ----------*/ /*---------- global variables ----------*/ /*---------- external variables ----------*/ /*---------- local functions ----------*/ /*---------- external functions ----------*/ /*---------- function definitions ----------*/ /*--------------------------------------------------*/ /* */ /* Routine to get PCI BIOS information. */ /* */ /* Usage: WORD PCI_GetPCIBIOSVersion( */ /* pci_bios *ppcibios); */ /* */ /* Parameters: */ /* ppcibios: pointer to pci_bios struct */ /* */ /* Return value: */ /* Returns PCI BIOS version number on success, */ /* 0 if PCI BIOS not found. Fills pci_bios */ /* struct on success. */ /* */ /*--------------------------------------------------*/ WORD PCI_GetPCIBIOSVersion(pci_bios *ppcibios) { WORD r_ax, r_bx, r_cx, r_dx; // register variables DWORD r_edx; DWORD pci_sig; // PCI signature WORD retval = PCI_NO_BIOS; pci_sig = 0x20494350L; // " ICP" signature // call PCI function to check for BIOS r_ax = ((PCI_FUNCTION_ID << 8) | PCI_BIOS_PRESENT); asm { .386 mov ax, [r_ax] int PCI_BIOS_INT mov DWORD PTR [r_edx], edx mov [r_dx], dx mov [r_cx], cx mov [r_bx], bx mov [r_ax], ax } if (r_dx == LOWORD(pci_sig)) { // PCI BIOS is present if (r_cx == HIWORD(pci_sig) && (r_bx & 0xff00) == 0x0100) { // PCI BIOS version 1.x retval = PCI_BIOS_REV_1X; } else if (r_edx == pci_sig) { // PCI BIOS version 2.x retval = PCI_BIOS_REV_2X; } else { // unknown version retval = PCI_UNKNOWN_BIOS; } if (ppcibios != NULL) { // fill BIOS info struct ppcibios->access = (r_ax & 0xff); ppcibios->version = r_bx; ppcibios->lastbus = (r_cx & 0xff); } } return retval; } /*--------------------------------------------------*/ /* */ /* Routine to locate PCI device. */ /* */ /* Usage: int PCI_FindDevice( */ /* pci_device *ppcidevice); */ /* */ /* Parameters: */ /* ppcidevice: pointer to pci_device struct */ /* */ /* Return value: */ /* Returns 1 if device found, 0 otherwise. */ /* Fills pci_device struct on success. */ /* */ /*--------------------------------------------------*/ int PCI_FindDevice(pci_device *ppcidevice) { // struct REGPACK regs; WORD r_ax, r_bx, r_cx, r_dx, r_si; DWORD config; int retval = 0; // make sure we have a PCI BIOS if (PCI_GetPCIBIOSVersion(NULL) != PCI_NO_BIOS) { // PCI BIOS is present // call PCI function to find device r_ax = ((PCI_FUNCTION_ID << 8) | (PCI_FIND_DEVICE)); r_cx = ppcidevice->dev_id; r_dx = ppcidevice->vend_id; r_si = ppcidevice->dev_index; asm { .386 mov ax, [r_ax] mov cx, [r_cx] mov dx, [r_dx] mov si, [r_si] int PCI_BIOS_INT mov ax, 0 adc ax, 0 mov [r_bx], bx mov [r_ax], ax } if (r_ax == 0) { // carry bit is clear - call succeeded // save device bus number ppcidevice->bus_num = ((r_bx & 0xFF00) >> 8); // save device number ppcidevice->dev_num = (r_bx & 0x00FF); // save device function ppcidevice->function = (r_bx & 0x0007); // get command register ppcidevice->command = (WORD) PCI_GetConfigRegister( ppcidevice, PCI_CONFIG_REG_CMD); // get revision ID ppcidevice->rev_id = (BYTE) PCI_GetConfigRegister( ppcidevice, PCI_CONFIG_REG_REVID); // get subsystem and vendor ID config = PCI_GetConfigRegister( ppcidevice, PCI_CONFIG_REG_SUBV); ppcidevice->sub_vend_id = (WORD) config; ppcidevice->sub_id = (WORD) (config >> 16); // get I/O base address config = PCI_GetConfigRegister( ppcidevice, C8XX_CONFIG_REG_IOB); ppcidevice->io_base = (config & 0xFFFFFFFEL); // get SCRIPTS RAM base address ppcidevice->ram_base = PCI_GetConfigRegister( ppcidevice, C8XX_CONFIG_REG_RAMB); // get ROM base address ppcidevice->rom_base = PCI_GetConfigRegister( ppcidevice, PCI_CONFIG_REG_ROM); // get interrupt number config = PCI_GetConfigRegister( ppcidevice, PCI_CONFIG_REG_INTL); ppcidevice->intl = (BYTE) config; retval = 1; } } return retval; } /*--------------------------------------------------*/ /* */ /* Routine to read PCI configuration register. */ /* */ /* Usage: DWORD PCI_GetConfigRegister( */ /* pci_device *ppcidevice, WORD offset) */ /* */ /* Parameters: */ /* ppcidevice: pointer to pci_device struct */ /* offset: config register offset */ /* */ /* Return value: */ /* Returns register value on success, */ /* 0 otherwise. */ /* */ /*--------------------------------------------------*/ DWORD PCI_GetConfigRegister(pci_device *ppcidevice, WORD offset) { WORD r_ax, r_bx, r_di, r_dx, r_cx; DWORD r_ecx; WORD pci_version; DWORD retval = 0L; // get PCI version pci_version = PCI_GetPCIBIOSVersion(NULL); if (!(pci_version == PCI_NO_BIOS || pci_version == PCI_UNKNOWN_BIOS)) { // PCI BIOS present // call PCI function to read register r_ax = ((PCI_FUNCTION_ID << 8) | (PCI_READ_CONFIG_DWORD)); // set bus number and device number r_bx = ((ppcidevice->bus_num & 0xff) << 8) | (ppcidevice->dev_num & 0xff); // set configuration register offset r_di = offset; asm { .386 mov ax, [r_ax] mov bx, [r_bx] mov di, [r_di] int PCI_BIOS_INT mov DWORD PTR [r_ecx], ecx mov [r_dx], dx mov [r_cx], cx } if (pci_version == PCI_BIOS_REV_1X) { // PCI version 1.x retval = r_dx; retval = (retval << 16) | r_cx; } else if (pci_version == PCI_BIOS_REV_2X) { // PCI version 2.x retval = r_ecx; } } return retval; } /*--------------------------------------------------*/ /* */ /* Routine to write to PCI configuration register. */ /* */ /* Usage: void PCI_SetConfigRegister( */ /* pci_device *ppcidevice, WORD offset, */ /* DWORD value) */ /* */ /* Parameters: */ /* ppcidevice: pointer to pci_device struct */ /* offset: config register offset */ /* value: value to write to register */ /* */ /* Return value: */ /* Returns 0 if no PCI BIOS, 1 otherwise. */ /* */ /*--------------------------------------------------*/ WORD PCI_SetConfigRegister(pci_device *ppcidevice, WORD offset, DWORD value) { WORD r_ax, r_bx, r_di, r_dx, r_cx; DWORD r_ecx; WORD pci_version; WORD retval = 0; // get PCI version pci_version = PCI_GetPCIBIOSVersion(NULL); if (!(pci_version == PCI_NO_BIOS || pci_version == PCI_UNKNOWN_BIOS)) { // PCI BIOS present retval = 1; // call PCI function to write to register r_ax = ((PCI_FUNCTION_ID << 8) | (PCI_WRITE_CONFIG_DWORD)); // set bus number and device number r_bx = ((ppcidevice->bus_num & 0xff) << 8) | (ppcidevice->dev_num & 0xff); // set configuration register offset r_di = offset; if (pci_version == PCI_BIOS_REV_1X) { // PCI version 1.x r_cx = (WORD) value; r_dx = (WORD) (value >> 16); } else if (pci_version == PCI_BIOS_REV_2X) { // PCI version 2.x r_ecx = value; } asm { .386 mov ax, [r_ax] mov bx, [r_bx] mov cx, [r_cx] mov dx, [r_dx] mov di, [r_di] mov ecx, DWORD PTR [r_ecx] int PCI_BIOS_INT } } return retval; }