📄 amccpci.c
字号:
/*
**
** File: AMCCPCI.C
**
** Function: Contains routines necessary for the
** main AMCCPCI program. Also contains
** "library" functions used throughout
** AMCCPCI program.
**
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
#include <conio.h>
#include <io.h>
#include <dos.h>
#include "cxldef.h"
#include "cxlkey.h"
#include "cxlmou.h"
#include "cxlstr.h"
#include "cxlvid.h"
#include "cxlwin.h"
#include "amcc.h"
#include "amccpci.h"
static void initialize(void);
static void open_back_wind(void);
static void open_stat_wind(void);
static void open_titl_wind(void);
static void parse_cmd_line(int, char **);
static void pre_main_menu(void);
static void main_menu(void);
static void pre_help(void);
int n_pci_devs;
struct pci_devices pci_devices[MAX_PCI_DEVICES];
enum device_type current_device_type = UNKNOWN_DEVICE_TYPE;
int cur_pci_dev = -1;
int background_color[] = {
_BLACK, _BLUE, _GREEN, _CYAN, _RED, _MAGENTA, _BROWN, _LGREY
};
int menu_border_color = LCYAN | _BLUE;
int menu_window_color = LCYAN | _BLUE;
int menu_selection_color = WHITE | _BLACK; // BLUE | _CYAN;
int menu_disabled_sel_color = GREEN | _BLUE; // LBLUE | _BLUE;
int menu_qsel_color = YELLOW| _BLUE;
int submenu_border_color = BLUE | _LGREY;
int submenu_window_color = BLUE | _LGREY;
int submenu_selection_color = LGREY | _BLUE;
int submenu_qsel_color = WHITE | _LGREY;
int shadow_color = LGREY | _BLACK;
WINDOW title_window, main_menu_window, edit_menu_window;
WINDOW edit_base_menu_window, edit_other_menu_window;
static word supported_device_types[] = {
0x5920,
0x5933
};
static char *device_type_strs[] = {
"PCI S5920",
"PCI S5935"
};
/*
** Error Message Table
*/
static char *error_text[]= {
NULL, /* errnum = 0, no error */
NULL, /* errnum == 1, windowing error */
"Syntax: NVBUILD -switches]\n\n"
"\t -c = CGA snow elimination\n"
"\t -b = BIOS screen writing\n"
"\t -m = force monochrome text attributes",
"Memory allocation error",
"Too many PCI devices\n"
};
void
display_pci_bus(struct pci_devices *pci, int n_pci)
{
struct pci_devices *opci;
int len, ndx, row, max;
static char buf[256];
/*
** Determine the longest string so we can decide on the
** size of the window.
*/
opci = pci;
for (max = ndx = 0; ndx < n_pci; pci++, ndx++) {
len = sprint_dev_config(pci, buf, 255);
max = len > max ? len : max;
}
if (!wopen(8, ((80 - max) / 2) + 3, n_pci + 13, max + 3 + 4, 0,
(LCYAN | _BLUE), (LCYAN | _BLUE)))
error_exit(1);
add_shadow();
wtitle("[ PCI Bus Devices ]", TCENTER, (LCYAN | _BLUE));
pci = opci;
for (row = 1, ndx = 0; ndx < n_pci; pci++, ndx++, row++) {
sprint_dev_config(pci, buf, 255);
wgotoxy(row, 1);
cxl_wprintf("%s", buf);
}
press_a_key(row + 1);
wclose();
}
void
main(int argc,char *argv[])
{
parse_cmd_line(argc, argv);
initialize();
n_pci_devs = find_all_pci_devices(pci_devices, MAX_PCI_DEVICES);
open_back_wind();
open_stat_wind();
open_titl_wind();
display_pci_bus(pci_devices, n_pci_devs);
main_menu();
normal_exit();
}
/*
** Parse the command line for valid invocation switches. If any valid
** switches are found, the appropriate video variable will be set. If
** any invalid parameters are found, a syntax message is displayed.
*/
static void
parse_cmd_line(int argc, char **argv)
{
int i, j;
char *p;
for (i = 1; i < argc; i++) {
p = argv[i];
if (*p == '-' || *p == '/')
{
for (j = 1; *(p + j); j++) {
switch(tolower(*(p + j))) {
case 'c':
setvparam(VP_CGA);
break;
case 'b':
setvparam(VP_BIOS);
break;
case 'm':
setvparam(VP_MONO);
break;
default:
error_exit(2);
}
}
} else
error_exit(2);
}
}
static short int *savescrn;
static int crow, ccol;
/*
** Initialize CXL's video, mouse, keyboard, and help systems.
** It also calls all sub-system initialization routines.
*/
static void
initialize(void)
{
/* initialize the CXL video system and save current screen info */
videoinit();
readcur(&crow,&ccol);
hidecur();
if ((savescrn = ssave()) == NULL)
error_exit(3);
/* attach [Alt-X] to the confirm_quit() function */
setonkey(0x2d00,confirm_quit,0);
/* initialize help system, help key = [F1] */
whelpdef("AMCCPCI.HLP", 0x3b00,
YELLOW|_RED, YELLOW|_RED, WHITE|_RED, RED|_LGREY, pre_help);
/* Initialize all sub-systems */
initialize_nvbuild();
}
/*
** Open the background window.
*/
static void
open_back_wind(void)
{
wfillch(176);
if (!wopen(0, 0, 23, 79, 5, 0, LRED | _CYAN))
error_exit(1);
wfillch(' ');
}
/*
** Open the status window (last row on screen)
*/
static void
open_stat_wind(void)
{
wfillch('\260');
wopen(24, 0, 24, 79, 5, 0, LGREY | _RED);
wprints( 0, 1, LGREY|_RED, "[F1]=Help");
wcenters(0, LGREY|_RED, "AMCCPCI v" VERSION_NUMBER_STR);
wrjusts( 0, 78, LGREY|_RED, "[Alt-X]=Quit");
wfillch(' ');
}
/*
** Open the title window.
*/
static void
open_titl_wind(void)
{
if (!(title_window = wopen(1, 12, 6, 67, 0, LRED|_MAGENTA, LRED|_MAGENTA)))
error_exit(1);
add_shadow();
wcenters(0, WHITE|_MAGENTA, "AMCCPCI v" VERSION_NUMBER_STR
" (" __DATE__ ")");
wcenters(1, WHITE|_MAGENTA, "S5920 and S5935 PCI Utility");
wcenters(3, LCYAN|_MAGENTA, "Copyright (c) 1994-1998 AMCC");
}
static void
s5920_nvbuild_menu(void)
{
current_device_type = S5920;
nvbuild_menu();
}
static void
s5933_nvbuild_menu(void)
{
current_device_type = S5933;
nvbuild_menu();
}
/*
** Display the main selection menu to determine the sub-system to be used.
*/
static void
main_menu(void)
{
int row;
/* push global help category onto help stack, so when */
/* [F1] is pressed while selection bar is on an item */
/* without help, the global help category will be used. */
whelpushc(H_GLOBAL);
/* define and process the main menu */
wmenubeg(8,20,22,60,0,menu_border_color,menu_window_color,pre_main_menu);
row = 3;
wmenuitem(row, 2, "1) S5920 Non-volatile Memory Builder", '1', 1,
0, s5920_nvbuild_menu ,0, H_NVBUILD);
row += 2;
wmenuitem(row, 2, "2) S5935 Non-volatile Memory Builder", '2', 2,
0, s5933_nvbuild_menu ,0, H_NVBUILD);
row += 2;
wmenuitem(row, 2, "3) Exit Program", '3', 3, 0, NULL , 0, 0);
wmenuend(1, M_VERT, 0, 6, menu_border_color, menu_qsel_color,
menu_disabled_sel_color, menu_selection_color);
if (wmenuget() == -1 && _winfo.errno > W_ESCPRESS)
error_exit(1);
/* pop the global help category off of the stack, and into the void */
whelpopc();
}
/*
** This is called during the setup of the main menu. It is called by
** wmenuget() right after the main menu's window is opened.
*/
static void
pre_main_menu(void)
{
hidecur();
add_shadow();
wtitle("[ Select Main Operation ]", TCENTER, menu_border_color);
main_menu_window = whandle();
}
/*
** Handles abnormal termination. If it is passed an error code of 1,
** then it is a windowing system error. Otherwise the error message is
** looked up in the error message table.
*/
void
error_exit(int errnum)
{
if (errnum) {
printf("\n%s\n", errnum == 1 ? werrmsg() : error_text[errnum]);
exit(errnum);
}
}
/*
** Handles normal termination. The original screen and cursor
** coordinates are restored before exiting to DOS with ERRORLEVEL 0.
*/
static void
normal_exit(void)
{
hidecur();
srestore(savescrn);
gotoxy_(crow,ccol);
showcur();
exit(0);
}
/*
** Pop open a window and confirms that the user really wants to quit.
** If so, it terminates the program.
*/
static void
confirm_quit(void)
{
struct _onkey_t *kblist;
kblist = chgonkey(NULL); /* hide any existing hot keys */
if (!wopen(9, 26, 13, 55, 0, WHITE | _BROWN, WHITE | _BROWN))
error_exit(1);
add_shadow();
wputs("\n Quit, are you sure? \033A\156Y\b");
clearkeys();
showcur();
if (wgetchf("YN", 'Y') == 'Y')
normal_exit();
wclose();
hidecur();
chgonkey(kblist); /* restore any hidden hot keys */
}
/*
** Called just prior to displaying the help menu.
*/
static void
pre_help(void)
{
add_shadow();
setonkey(0x2d00, confirm_quit, 0);
}
/*
** This will add a shadow to the active window
*/
void
add_shadow(void)
{
wshadow(shadow_color);
}
/*
** Checks the input to make sure the user entered a "y" or a "n".
*/
int
check_y_n(char *yes_no_ch)
{
int ch;
ch = toupper(*yes_no_ch);
if (ch == 'Y' || ch == 'N')
return(0);
wperror("Press Y for Yes, or N for No", YES);
return(1);
}
/*
** Display a pause message then pauses for a keypress
*/
void
press_a_key(int wrow)
{
int attr;
attr = (BLINK | YELLOW) | ((_winfo.active->wattr >> 4) << 4);
wcenters(wrow,attr,"Press a key");
hidecur();
waitkey();
wcenters(wrow, attr, " ");
}
/*
** Displays a generic message to the screen.
*/
void
wdisp_message(char *message)
{
int msg_length, col, ecol;
if ((msg_length = strlen(message)) > 76) {
wperror("wdisp_message length too long", YES);
error_exit(3);
}
col = 37 - msg_length / 2;
ecol = col + msg_length + 4;
if (!wopen(11, col, 17, ecol, 0, WHITE | _MAGENTA, WHITE | _MAGENTA))
error_exit(1);
wcenters(1, WHITE|_MAGENTA, message);
press_a_key(3);
wclose();
}
/*
** Prompt user to select PCI device
*/
int
select_pci_device(void)
{
int pci_device_index, index, row, col, erow, ecol;
char *str[MAX_PCI_DEVICES+1];
struct _wrec_t *wrec;
erow = 8 + 4 + n_pci_devs;
if (erow > 23)
erow = 23;
if (!wopen(8, 17, erow, 63, 0, menu_border_color, menu_window_color))
error_exit(1);
add_shadow();
wtitle("[ Select PCI Device ]", TCENTER, menu_border_color);
wcenters(0, menu_window_color, " Bus Device Vendor Base Sub");
wcenters(1, menu_window_color, "Number ID ID Class Class");
wcenters(2, menu_window_color, "------ ------ ------ ----- -----");
for (index = 0; index < n_pci_devs; index++) {
if ((str[index] = malloc(60)) == NULL)
error_exit(3);
sprintf(str[index], "%2.2xh %4.4xh %4.4xh %2.2xh "
"%2.2xh", pci_devices[index].bus, pci_devices[index].device_id,
pci_devices[index].vendor_id, pci_devices[index].base_class,
pci_devices[index].sub_class);
}
str[n_pci_devs] = NULL;
wrec = wfindrec(whandle());
row = wrec->srow + 4;
erow = wrec->erow - 1;
if (erow == 22) {
erow--;
wgotoxy(13, 18);
cxl_wprintf("More %c", 0x19);
}
col = wrec->scol + 1;
ecol = wrec->ecol - 1;
pci_device_index = wpickstr(row, col, erow, ecol, 5, menu_border_color,
menu_window_color, menu_selection_color, str,
cur_pci_dev, NULL);
if (pci_device_index == -1)
{
if (_winfo.errno > W_ESCPRESS)
error_exit(1);
goto ErrorOccurred;
}
cur_pci_dev = pci_device_index;
for (index = 0; index < n_pci_devs; index++) {
free(str[index]);
str[index] = NULL;
}
wclose();
return(OK);
ErrorOccurred:
wclose();
return(ERROR_OCCURRED);
}
/*
** MAP_MEMORY_ADDRESS
**
** Take a memory address and form a segment and offset. If the memory
** address is a real-mode address, use segment 0x34, which is already
** allocated by Pharlap. If a protected mode address, must allocate a new
** segment in the LDT and map the physical page into that segment.
*/
int
map_memory_address(dword mem_addr, word *segment, dword *offset)
{
struct _SREGS sregs; /* processor segment registers for intdosx call */
union _REGS regs; /* processor registers for intdos(x) calls */
dword base; /* PM base address (must be 4K boundary) */
/* Determine if mem_addr is a Protected Mode Address */
if (mem_addr > (0xfffffL - CONF_SPACE_SIZE + 1)) {
/* Allocate Segment in LDT */
regs.d.eax = 0x4800;
regs.d.ebx = 0;
_intdos(®s, ®s);
if (regs.x.cflag & CARRY_FLAG) {
wperror("Unable to allocate segment in LDT", YES);
return(ERROR_OCCURRED);
}
*segment = regs.w.ax; /* Segment selector returned from call */
/*
** Compute base & offset
*/
*offset = (mem_addr - (mem_addr / (4*1024) * (4*1024)));
base = mem_addr - *offset;
/* Map physical page into segment */
sregs.es = *segment;
_asm mov sregs.cs,cs
_asm mov sregs.ds,ds
_asm mov sregs.ss,ss
regs.d.ebx = base; /* Phys addr to map */
regs.d.ecx = 1; /* Map 1 segment */
regs.d.eax = 0x250a; /* Map Physical Memory at End of Segment */
_intdosx(®s, ®s, &sregs);
if (regs.x.cflag & CARRY_FLAG) {
wperror("DPMI Server does not allow needed function (Map Phys)",
YES);
deallocate_segment(*segment);
return(ERROR_OCCURRED);
}
return(OK);
}
/*
** Real Mode Address
*/
*offset = mem_addr;
*segment = SS_DOSMEM; /* Pharlap Real Memory segment selector */
return(OK);
}
/****************************************************************************/
/* */
/* DEALLOCATE_SEGMENT */
/* */
/* Delete an LDT segment selector that was allocated by map_memory_address, */
/* unless the address was a real-mode address ( < 1MB). */
/* */
/****************************************************************************/
void
deallocate_segment(word segment)
{
union _REGS regs;
struct _SREGS sregs;
if (segment != SS_DOSMEM) {
/* Deallocate segment previously allocated */
regs.h.ah = 0x49;
sregs.es = segment;
_asm mov sregs.cs,cs
_asm mov sregs.ds,ds
_asm mov sregs.ss,ss
_intdosx(®s, ®s, &sregs);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -