?? 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 <stdio.h>
#include <stdlib.h>
#include <dos.h>
#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;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -