home *** CD-ROM | disk | FTP | other *** search
- /*
- SetCPU V1.60
- by Dave Haynie, April 13, 1990
- Released to the Public Domain
-
- EXPANSION DEVICE MODULE
-
- This module maintains the code used to detect and translate
- a given expansion device.
- */
-
- #include "setcpu.h"
-
- /* ====================================================================== */
-
- /* Stuff I need for this module. */
-
- char *malloc();
- int sscanf();
-
- /* ====================================================================== */
-
- /* This section manages devices with on-board ROM. The actual
- implementation of this stuff is pretty well hidden in this
- module. */
-
- /* This structure manages the expansion devices that we know about. */
-
- struct ExpDev {
- struct Node node;
- ULONG manuf;
- ULONG board;
- ULONG size;
- ULONG romoffset;
- ULONG romsize;
- };
-
- /* Here's the list of all the devices we know about. */
-
- static struct List Devices =
- {(struct Node *)&Devices.lh_Tail,NULL,(struct Node *)&Devices.lh_Head,0,0};
-
- static struct ExpDev *CurrentDevice = NULL;
-
- /* This function reads the list of expansion devices from the given file.
- The file should contain data for one device per line, with the
- following format:
-
- MANUF PROD SIZE START LENGTH id-string
-
- Except for the last field, all numbers are integers, which may be
- expressed as decimal or hexidecimal. The last field is a text
- string which may contain any information. It's very likely that
- the line for each device will have to be supplied by the maker
- of any device, since there's no way to figure out if a device's
- ROM is on the same MMU page as an important I/O register which
- shouldn't ever be translated. The description I use for the Amiga
- 2090A controller is:
-
- 0x202 0x01 0x10000 0x8000 0x4000 CBM 2090A Disk Controller
-
- The actual fields are:
-
- MANUF The Manufacturer's code for the PIC
- PROD The Product code for the PIC
- SIZE The configured size of the PIC
- START The offset from the PIC base for the start of ROM
- LENGTH The length of the ROM
- id-string Whatever the hell you want
- */
-
- LONG ReadExpDevs(name)
- char *name;
- {
- FILE *file;
- char buf[256],msg[256];
- struct ExpDev *ed;
- int len,i;
-
- if (!(file = fopen(name,"r"))) return FALSE;
-
- while (fgets(buf,256,file)) {
- ed = (struct ExpDev *)malloc(sizeof(struct ExpDev));
- if (sscanf(buf,"%lx%lx%lx%lx%lx%s",&ed->manuf,&ed->board,&ed->size,
- &ed->romoffset,&ed->romsize,msg) >= 5) {
- if (len = strlen(msg)) {
- ed->node.ln_Name = (char *)malloc(len+1);
- for (i = 0; i <= len; ++i)
- ed->node.ln_Name[i] = (msg[i] == '_')?' ':msg[i];
- }
- if (ed->romsize = ((ed->romsize/DEVROUND)*DEVROUND))
- AddHead(&Devices,(struct Node *)ed);
- else
- free(ed);
- } else
- free(ed);
- }
- fclose(file);
- CurrentDevice = (struct ExpDev *)Devices.lh_Head;
- return TRUE;
- }
-
- /* ====================================================================== */
-
- /* This function returns the ROM information I'll need for a given
- expansion device. Because of some Commodore screwups, the A2090A
- appears the same device as other boards like the Commodore RAM
- board. So I have the size passed as well, as a consistency
- check. The returned ExpROMData structure is allocated here, and
- can be freed when no longer needed. */
-
- struct ExpROMData *GetExpROM()
- {
- struct ConfigDev *cd;
- struct DiagArea *da;
- struct ExpROMData *ed;
-
- if (!CurrentDevice || !ExpansionBase) return NULL;
- cd = FindConfigDev(NULL,CurrentDevice->manuf,CurrentDevice->board);
-
- while (cd) {
- if (((ULONG)cd->cd_BoardSize == CurrentDevice->size) &&
- (cd->cd_Rom.er_Type & ERTF_DIAGVALID)) {
- da = (struct DiagArea *)(((ULONG)cd->cd_BoardAddr)+((ULONG)cd->cd_Rom.er_InitDiagVec));
-
- /* This is just a sanity check to make sure we really use the
- ROM out on this card -- a nybble or byte wide ROM will be in
- RAM already. */
- if ((da->da_Config & DAC_BUSWIDTH) == DAC_WORDWIDE) {
- ed = (struct ExpROMData *)AllocMem(SizeOf(struct ExpROMData),MEMF_CLEAR);
- ed->ROMbase = ((ULONG)cd->cd_BoardAddr) + CurrentDevice->romoffset;
- ed->ROMsize = CurrentDevice->romsize;
- ed->imagebase = NULL;
- ed->tablebase = NULL;
- ed->name = (char *)AllocMem((ULONG)
- strlen(CurrentDevice->node.ln_Name)+1,0L);
- strcpy(ed->name,CurrentDevice->node.ln_Name);
- ++CurrentDevice;
- return ed;
- }
- }
- cd = FindConfigDev(cd,CurrentDevice->manuf,CurrentDevice->board);
- }
- CurrentDevice = (struct ExpDev *)CurrentDevice->node.ln_Succ;
- return NULL;
- }
-
- /* This function removes a CardROMFile generated I/O ROM table list. */
-
- void FreeExpROM(emem)
- struct ExpROMData *emem;
- {
- struct ExpROMData *edel;
-
- while (emem) {
- edel = emem;
- emem = emem->next;
- FreeMem(edel->imagebase,edel->ROMsize);
- FreeMem(edel->name,(ULONG)strlen(edel->name)+1);
- FreeMem(edel,SizeOf(struct ExpROMData));
- }
- }
-
- /* ====================================================================== */
-
- /* This routine is called to configure the system devices without calling any
- ROM routines that could possibly goober up on older OS releases. Other
- than skipping ROMs, this should do the same thing as the ConfigChain()
- function in expansion.library. */
-
- void SafeConfigDevs()
- {
- struct ConfigDev *cd;
- char *base = (char *)0xe80000;
-
- if (!ExpansionBase) return;
-
- /* Should also loop only as long as
- !(ExpansionBase->eb_Flags & EBB_CLOGGED),
- but I don't know what EBB_CLOGGED is yet.. */
-
- while (cd = AllocConfigDev()) {
- if (ReadExpansionRom(base,cd)) {
- FreeConfigDev(cd);
- break;
- }
-
- /* Got it, let's get rid of any ROM critters. */
- cd->cd_Rom.er_Type &= ~ERTF_DIAGVALID;
-
- /* Now adding the board should be safe! */
- if (ConfigBoard(base,cd)) {
- FreeConfigDev(cd);
- break;
- }
- AddConfigDev(cd);
- }
- }
-
-