#pragma option -3 #include #include #include #include #include #include #include #include #include "bioslib.h" #define VENDORID 0x494F #define DEVICEID 0x0200 #define SETHOLEMASK 0x80000000 #define HOLEIO 0x0C #define VBSILENT 0 #define VBQUIET 1 #define VBLOUD 2 #define VBDEBUG 3 unsigned long NewBase[] = {0x1801, 0x1F01, 0x1E01, 0x1D01}; unsigned char bn, df, mbn; unsigned Verbosity = VBLOUD, DumpOldAddrs = 0, DumpNewAddrs = 0, StateLocation = 0, Warnings = 0; unsigned AddrFromHole[] = { 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, 0x100, 0x120, 0x140, 0x160, 0x180, 0x1A0, 0x1C0, 0x1E0 }, HoleFromAddr[22], Cursor = 0, DoManualConfig = 0; word Base0; unsigned long HoleMask = 0; char HolePath[256] = "PCISACfg.hol"; unsigned SetHolePath = 0; void outpl(unsigned portid, unsigned long value); void Beep(void) { sound(300); delay(100); nosound(); } void Fail(char *FailText) { if (Verbosity) printf("%s\n",FailText); exit(-1); } int BinToMask(char *S, unsigned long *L) { char *C; unsigned long IL; int I; if (!S || !L) return(0); C = S; do //This will return false if passed an empty string { if ((*C != '0') && (*C != '1')) return(0); } while(*(++C)); C = S; IL = *C - '0'; while (*(++C)) IL = IL * 2 + *C - '0'; *L = 0; for (I = 0; I < 22; ++I) if (IL & (1UL << I)) *L |= 1UL << HoleFromAddr[I]; //This maps the result into the //goofy hole space return (C - S); } void dump_pci_config_regs(void) { unsigned char *Data; unsigned int I; char *BaseText = "Addresses"; TPCICommonConfig config; Data = (unsigned char*)&config; for (I = 0; I < 64; ++I, ++Data) { if (read_config_byte(bn, df, I, Data) != SUCCESSFUL) Fail("Error: Failed to read PCICommonConfig."); } Base0 = config.BaseAddresses[0] & 0xFFFE; BaseText[0] = 'A'; for (I = 0; I < 6; ++I) { if (config.BaseAddresses[I]) printf("%9s[%1x]: %08lX %3s\n", BaseText, I, config.BaseAddresses[I]&0xfffe,(Verbosity>=VBDEBUG?(config.BaseAddresses[I]&0x1?"[I/O]":"[MEM]"):"")); BaseText[0] = 0; } printf(" IRQ: %02x\n",config.InterruptLine); } void NameAndVer(void) { puts("PCISACfg - PCI-ISA Expansion Kit Configuration Program 1.01"); } void DoHelp(void) { int I, J; NameAndVer(); puts(" Options:"); puts(" /? Show this help screen; do not configure the PCI-ISA expansion card."); puts(" /QUIET Don't show header or success, but show errors and options."); puts(" /SILENT Only show information requested by options."); puts(" /OLD Show old addresses."); puts(" /NEW Show new addresses."); puts(" /LOC Show PCI-ISA expansion card PCI bus location."); puts(" /MANUAL Manually configure what addresses are used by host devices and what"); puts("addresses are available on the expansion chassis. Without /MANUAL, they will be"); puts("taken from the config file if present, or all addresses will be available."); puts(" /CFGFILE [path & filename]"); puts(" Specify the location (and name) of the config file. Without /CFGFILE"); puts("or /MANUAL, PCISACfg will use PCISACfg.hol in the current directory."); puts(""); puts(" All options are case-insensitive, and only the first letter matters."); exit(0); } void CheckReadback(void) { unsigned long CurrentBase; unsigned int I; for (I = 0; I < 4; ++I) if (read_config_dword(bn, df, 16 + 4 * I, &CurrentBase) != SUCCESSFUL) Fail("Error: Failed to read back PCICommonConfig structure."); else if (CurrentBase != NewBase[I]) Fail("Error: Readback discrepancy."); } void CheckBusy(void) { unsigned I,tbn,tdf; unsigned long data; data=0; for (tbn=0; tbn<=mbn;tbn++) for (tdf=0; tdf<256; tdf++) if (!((tbn==bn) && (tdf==df))) for (I = 0; I < 6; ++I) { read_config_dword(tbn, tdf, 16 + 4 * I, &data); if (Verbosity>=VBDEBUG) { printf("bn:%02x df:%02x base[%1x]:%04x",tbn,tdf,I,data); delay(3); gotoxy(1,wherey()); } if ((data&1L) && //must be i/o space not mem (((data>=0x1D00)&&(data<0x2000)) || //can't be between 1D00 and 1FFF ((data>=0x1800)&&(data<0x1900)))) //can't be between 1800 and 18FF Fail("Error: The addresses needed are already occupied by a PCI device.\n" "Please contact the factory for a solution."); }//end for each base address if (Verbosity >= VBDEBUG) clreol(); } int CheckEnabled(void) { unsigned char cmd; if(read_config_byte(bn, df, PCI_CS_COMMAND, &cmd) == SUCCESSFUL) { if ((cmd & 1) == 0) { if (Verbosity) puts("Warning: PCI-ISA expansion card has been disabled by the system."); } else return(1); } ++Warnings; return(0); } void write_arg_config(void) { int I; for (I = 0; I < 4; ++I) if (write_config_dword(bn, df, 16 + 4 * I, NewBase[I]) != SUCCESSFUL) Fail("Error: Failed to configure PCI-ISA expansion card."); } int CheckBus(void) { if ( bn == 0 ) return(1); if (Verbosity) printf("Warning: PCI-ISA expansion card was found on bus %d. It probably needs to be on\n" "bus 0. If it fails to function, try a different PCI slot(bus 0 is usually\n" "closest to the CPU).\n", bn ); ++Warnings; return(0); } void DrawLine(unsigned I) { unsigned Here = (HoleMask & (1UL << HoleFromAddr[I])) != 0; textbackground(0); gotoxy(1, 3 + I); if (Cursor == I) { textcolor(15); cputs(">"); if (!Here) textbackground(1); textcolor(10); cprintf("%03Xh to %03Xh", AddrFromHole[HoleFromAddr[I]], AddrFromHole[HoleFromAddr[I]] + 0x1F); if (!Here) textbackground(0); textcolor(15); cputs("<"); } else { textcolor(15); cputs(" "); if (!Here) textbackground(1); textcolor(10); cprintf("%03Xh to %03Xh", AddrFromHole[HoleFromAddr[I]], AddrFromHole[HoleFromAddr[I]] + 0x1F); if (!Here) textbackground(0); textcolor(15); cputs(" "); } textcolor(11); if (Here) cprintf(" Used "); else { cprintf(" Available"); } gotoxy(1, 3 + I); } void ManualConfig(void) { int I; char Done = 0; textmode(C80); textcolor(15); textbackground(0); clrscr(); NameAndVer(); gotoxy(1, 25); textcolor(14); cputs(" and  to select, Space to change, Enter to accept, Escape to cancel"); textbackground(0); textcolor(15); gotoxy(38, 5); cputs("ÚÄÄÄÄÄÄÄÄÄÄÄÄ Legend ÄÄÄÄÄÄÄÄÄÄÄÄ¿"); gotoxy(38, 6); cputs("³ ³"); gotoxy(38, 7); cputs("³ ³"); gotoxy(38, 8); cputs("³ ³"); gotoxy(38, 9); cputs("³ ³"); gotoxy(38, 10); cputs("ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ"); gotoxy(40, 7); textcolor(10); cputs(" Used by Host Devices "); gotoxy(40, 8); textbackground(1); textcolor(10); cputs("Available on Expansion Chassis"); for (I = 21; I >= 0; --I) DrawLine(I); do { char Ink; unsigned OCursor; switch (getch()) { case 27: textcolor(7); textbackground(0); clrscr(); exit(Warnings); //break; case 13: Done = -1; break; case 32: HoleMask ^= (1UL << HoleFromAddr[Cursor]); DrawLine(Cursor); break; case 0: Ink = getch(); if (Ink == 'H' || Ink == 'P') { OCursor = Cursor; if (Ink == 'H') { if (Cursor == 0) Cursor = 21; else --Cursor; } else if (Ink == 'P') { if (Cursor == 21) Cursor = 0; else ++Cursor; } DrawLine(OCursor); DrawLine(Cursor); } else Beep(); break; default: Beep(); } } while (!Done); textcolor(7); textbackground(0); clrscr(); { FILE *Fil; #pragma warn -pia if (Fil = fopen(HolePath, "w+b")) #pragma warn +pia { char *Data = (char*)&HoleMask; //fprintf(Fil, "%-80s", "PCISACfg Hole Configuration File "); fputc(*(Data++), Fil); fputc(*(Data++), Fil); fputc(*(Data++), Fil); fputc(*(Data++), Fil); fclose(Fil); } else { if (Verbosity) puts("Warning: Failed to create/update PCISACfg.hol."); ++Warnings; } } } int main(int Params, char *Param[]) { unsigned long temp; int I; for (I = 21; I >= 0; --I) HoleFromAddr[(AddrFromHole[I] - 0x100) / 0x20] = I; //_fmode = O_BINARY; for (I = 1; I < Params; ++I) { strupr(Param[I]); if (strncmp(Param[I], "/O", 2) == 0) DumpOldAddrs = -1; else if (strncmp(Param[I], "/N", 2) == 0) DumpNewAddrs = -1; else if (strncmp(Param[I], "/L", 2) == 0) StateLocation = -1; else if (strncmp(Param[I], "/D", 2) == 0) Verbosity = VBDEBUG; else if (strncmp(Param[I], "/Q", 2) == 0) Verbosity = VBQUIET; else if (strncmp(Param[I], "/S", 2) == 0) Verbosity = VBSILENT; else if (strncmp(Param[I], "/M", 2) == 0) DoManualConfig = -1; else if ((strncmp(Param[I], "/C", 2) == 0) && (I + 1 < Params)) strcpy(HolePath, Param[++I]), SetHolePath = -1; else DoHelp(); } { FILE *Fil; #pragma warn -pia if (Fil = fopen(HolePath, "rb")) #pragma warn +pia { char *Data; //for (I = 19; I >= 0; I--) //read 4 bytes 20 times // fscanf(Fil, "%4s", &Data); Data = (char*)&HoleMask; *(Data++) = fgetc(Fil); *(Data++) = fgetc(Fil); *(Data++) = fgetc(Fil); *(Data++) = fgetc(Fil); fclose(Fil); } else if (SetHolePath) { #pragma warn -pia if (Fil = fopen(HolePath, "w+b")) #pragma warn +pia { char *Data = (char*)&HoleMask; //fprintf(Fil, "%-80s", "PCISACfg Hole Configuration File "); fputc(*(Data++), Fil); fputc(*(Data++), Fil); fputc(*(Data++), Fil); fputc(*(Data++), Fil); fclose(Fil); } else { char ErrStr[512]; sprintf(ErrStr, "Error: Failed to create config file \"%s\".", HolePath); Fail(ErrStr); } } } HoleMask &= 0x3FFFFF; if (Verbosity >= VBLOUD) NameAndVer(); if (pci_bios_present((byte*)&temp,(word*)&temp,&mbn) != SUCCESSFUL) Fail("Error: PCI BIOS not found.\n" "You may be running in a Windows NT/2000 based system."); if (find_pci_device(DEVICEID, VENDORID, 0, &bn, &df) != SUCCESSFUL) Fail("Error: PCI-ISA expansion card not found."); if (DoManualConfig) { if (Verbosity < VBLOUD) NameAndVer(); ManualConfig(); //Get the hole mask from the user } if (Verbosity >= VBDEBUG) printf("PCI Bus info: pci_bios_present mbn=0x%02x\n", mbn); if (StateLocation) printf("PCI-ISA expansion card found on bus %d as device %d, function %d.\n", (unsigned int)bn, (unsigned int)(df >> 3), (unsigned int)(df & 7) ); if (DumpOldAddrs) dump_pci_config_regs(); //State addresses and get Base0 else read_config_word(bn, df, 0x10, &Base0); //Get Base0 outpl((Base0 & 0xFFFE) + HOLEIO, 0x3FFFFF | SETHOLEMASK); CheckEnabled(); //See if we're disabled(warning-level) CheckBus(); //See if we're not on the root bus(warning-level) CheckBusy(); //See if anyone else is where we want to be write_arg_config(); //Move the card CheckReadback(); //See if it got moved outpl(0x1800 + HOLEIO, HoleMask | SETHOLEMASK); if (DumpNewAddrs) dump_pci_config_regs(); //State addresses if (Verbosity >= VBLOUD) puts("PCI-ISA expansion card configured."); return(Warnings); } #pragma inline void outpl(unsigned portid, unsigned long value) { asm { mov dx,[portid] mov eax,[value] out dx,eax } } //Warning: #PRAGMA INLINE in effect!