?? cislib.c
字號:
/* cisLib.c - PCMCIA CIS library */
/* Copyright 1984-1996 Wind River Systems, Inc. */
#include "copyright_wrs.h"
/*
modification history
--------------------
01g,17sep98,lrn reworked DosFs 2.0 support and memory leak issues
01f,14jul98,lrn DosFs2.0: can not delete DOS devices
01e,16jan97,hdn added pCtrl->memBase, CIS_MAX_TUPLES.
01d,28mar96,jdi doc: cleaned up language and format.
01c,08mar96,hdn added more descriptions.
01b,22feb96,hdn cleaned up
01a,10feb95,hdn written.
*/
/*
DESCRIPTION
This library contains routines to manipulate the CIS (Configuration
Information Structure) tuples and the card configuration registers.
The library uses a memory window which is defined in `pcmciaMemwin'
to access the CIS of a PC card.
All CIS tuples in a PC card are read and stored in a linked list,
`cisTupleList'. If there are configuration tuples, they are interpreted
and stored in another link list, `cisConifigList'. After the CIS is read,
the PC card's enabler routine allocates resources and initializes a device
driver for the PC card.
If a PC card is inserted, the CSC (Card Status Change) interrupt handler
gets a CSC event from the PCMCIA chip and adds a cisGet() job to the
PCMCIA daemon. The PCMCIA daemon initiates the cisGet() work. The CIS
library reads the CIS from the PC card and makes a linked list of CIS
tuples. It then enables the card.
If the PC card is removed, the CSC interrupt handler gets a CSC event from
the PCMCIA chip and adds a cisFree() job to the PCMCIA daemon. The PCMCIA
daemon initiates the cisFree() work. The CIS library frees allocated
memory for the linked list of CIS tuples.
*/
#include "vxWorks.h"
#include "taskLib.h"
#include "sysLib.h"
#include "stdlib.h"
#include "string.h"
#include "drv/pcmcia/pcmciaLib.h"
#include "drv/pcmcia/cisLib.h"
/* defines */
/* imports */
IMPORT PCMCIA_CTRL pcmciaCtrl;
IMPORT PCMCIA_MEMWIN pcmciaMemwin[];
IMPORT PCCARD_ENABLER pccardEnabler[];
IMPORT int pccardEnablerNumEnt;
/* globals */
SEMAPHORE cisMuteSem;
/* locals */
LOCAL u_char powerMantissa [] = {10, 12, 13, 15, 20, 25, 30, 35,
40, 45, 50, 55, 60, 70, 80, 90};
LOCAL u_char powerExponent [] = {0, 0, 0, 0, 0, 1, 10, 100};
/* forward declarations */
LOCAL STATUS cisTupleGet (int sock);
LOCAL STATUS cisConfigGet (int sock);
LOCAL STATUS cisResourceGet (int sock);
/*******************************************************************************
*
* cisGet - get information from a PC card's CIS
*
* This routine gets information from a PC card's CIS, configures the PC card,
* and allocates resources for the PC card.
*
* RETURNS: OK, or ERROR if it cannot get the CIS information,
* configure the PC card, or allocate resources.
*/
STATUS cisGet
(
int sock /* socket no. */
)
{
PCMCIA_CTRL *pCtrl = &pcmciaCtrl;
PCMCIA_CHIP *pChip = &pCtrl->chip;
PCMCIA_CARD *pCard = &pCtrl->card[sock];
STATUS status = ERROR;
DL_NODE *pNode;
DL_NODE *pTemp;
semTake (&cisMuteSem, WAIT_FOREVER); /* mutual exclusion begin */
(void) (* pChip->cscOff) (sock, pChip->intLevel);
for (pNode = DLL_FIRST(&pCard->cisTupleList); pNode != NULL; pNode = pTemp)
{
pTemp = DLL_NEXT(pNode);
free (pNode);
}
for (pNode = DLL_FIRST(&pCard->cisConfigList); pNode != NULL; pNode = pTemp)
{
pTemp = DLL_NEXT(pNode);
free (pNode);
}
dllInit (&pCard->cisTupleList);
dllInit (&pCard->cisConfigList);
if ((cisTupleGet (sock) == OK) &&
(cisConfigGet (sock) == OK) &&
(cisResourceGet (sock) == OK))
status = OK;
(void) (* pChip->cscPoll) (sock);
(void) (* pChip->cscOn) (sock, pChip->intLevel);
semGive (&cisMuteSem); /* mutual exclusion end */
return (status);
}
/*******************************************************************************
*
* cisTupleGet - get tuples from PC card and attach it to the link list
*
* This routine get tuples from PC card and attach it to the link list.
*
* RETURNS: OK, or ERROR if it couldn't set a value to the PCMCIA chip.
*/
LOCAL STATUS cisTupleGet
(
int sock /* socket no. */
)
{
BOOL endList = FALSE;
BOOL noLink = FALSE;
u_long longlinkA = 0;
u_long longlinkC = 0;
PCMCIA_CTRL *pCtrl = &pcmciaCtrl;
PCMCIA_CHIP *pChip = &pCtrl->chip;
PCMCIA_CARD *pCard = &pCtrl->card[sock];
int ix = 0;
PCMCIA_MEMWIN cisMemwin;
CIS_TUPLE_A *pTupleA;
CIS_TUPLE_C *pTupleC;
DL_NODE *pNode;
u_char *pChar;
u_char *pd;
u_char *ps;
int flag;
int tuples;
/* XXX
* Assumption
* 1. CIS tuple chain is in between start and stop in pcmciaMemwin[0].
* 2. Longlink from Common memory to Attribute memory doesn't occur
*
* Card reset/power signal sequence (See p.60 PCMCIA Developer's guide)
* ______________________________________________
* Card detect __|
* >50ms-
* _______________________________________
* Vcc _________|
* >300ms--------
* Card signal ________________________
* enabled ________________________|
* __________
* Reset ________________________| |______________
* >10ms---
* >20ms----
* Card access _____
* allowed ___________________________________________|
*/
if (pChip->installed != TRUE)
return (ERROR);
taskDelay (sysClkRateGet() >> 3); /* 7 * 16ms = 112ms */
if ((* pChip->reset)(sock) != OK)
return (ERROR);
flag = PC_PWR_AUTO | PC_VCC_5V | PC_VPP_5V;
if ((* pChip->flagSet)(sock, flag) != OK)
return (ERROR);
taskDelay (sysClkRateGet() >> 1); /* 30 * 16ms = 500ms */
flag = PC_PWR_AUTO | PC_VCC_5V | PC_VPP_5V | PC_RESET;
if ((* pChip->flagSet)(sock, flag) != OK)
return (ERROR);
taskDelay (sysClkRateGet() >> 4); /* 3 * 16ms = 48ms */
flag = PC_PWR_AUTO | PC_VCC_5V | PC_VPP_5V;
if ((* pChip->flagSet)(sock, flag) != OK)
return (ERROR);
taskDelay (sysClkRateGet() >> 2); /* 15 * 16ms = 240ms */
flag = PC_READY | PC_POWERON;
while ((((* pChip->status)(sock) & flag) != flag) && (ix++ < 8))
taskDelay (sysClkRateGet() >> 2);
do {
/* map attribute memory */
pChar = (u_char *)pcmciaMemwin[CIS_MEM_TUPLE].start +
pCtrl->memBase;
cisMemwin.window = PCMCIA_CIS_WINDOW;
cisMemwin.flags = MAP_ACTIVE | MAP_16BIT | MAP_ATTRIB;
cisMemwin.extraws = 2;
cisMemwin.start = pcmciaMemwin[CIS_MEM_TUPLE].start;
cisMemwin.stop = pcmciaMemwin[CIS_MEM_TUPLE].stop;
cisMemwin.cardstart = longlinkA;
if ((* pChip->memwinSet)(sock, &cisMemwin) != OK)
return (ERROR);
/* check the link target tuple if we had longlink tuple */
if (longlinkA != 0)
{
longlinkA = 0;
pTupleA = (CIS_TUPLE_A *)pChar;
if (pTupleA->code == CISTPL_LINKTARGET)
pChar += (pTupleA->link + 2) * 2;
else
break;
}
/* parse the tuple chain */
endList = FALSE;
for (tuples = 0; !endList; tuples++)
{
pTupleA = (CIS_TUPLE_A *)pChar;
switch (pTupleA->code)
{
case CISTPL_NULL:
pChar += 2;
break;
case CISTPL_LONGLINK_A:
ps = pChar + 4;
pd = (u_char *)&longlinkA;
for (ix = 0; ix < 4; ix++)
*pd++ = *ps++;
pChar += (pTupleA->link + 2) * 2;
break;
case CISTPL_LONGLINK_C:
ps = pChar + 4;
pd = (u_char *)&longlinkC;
for (ix = 0; ix < 4; ix++)
*pd++ = *ps++;
pChar += (pTupleA->link + 2) * 2;
break;
case CISTPL_NO_LINK:
noLink = TRUE;
pChar += (pTupleA->link + 2) * 2;
break;
case CISTPL_END:
if (tuples != 0)
endList = TRUE;
pChar += (pTupleA->link + 2) * 2;
break;
case CISTPL_CHECKSUM:
/* XXX ignore now */
pChar += (pTupleA->link + 2) * 2;
break;
default:
pNode = (DL_NODE *)malloc (pTupleA->link + 2 +
sizeof(DL_NODE));
pd = (u_char *)pNode + sizeof(DL_NODE);
ps = pChar;
for (ix = 0; ix < (pTupleA->link + 2); ix++)
{
*pd++ = *ps++;
ps++;
}
dllAdd (&pCard->cisTupleList, pNode);
pChar += (pTupleA->link + 2) * 2;
break;
}
if ((pTupleA->link == 0xff) || (tuples >= CIS_MAX_TUPLES))
endList = TRUE;
}
} while (longlinkA != 0);
if (noLink)
{
/* unmap memory window */
cisMemwin.window = 0;
cisMemwin.flags = 0;
cisMemwin.extraws = 0;
cisMemwin.start = 0;
cisMemwin.stop = 0;
cisMemwin.cardstart = 0;
if ((* pChip->memwinSet)(sock, &cisMemwin) != OK)
return (ERROR);
return (OK);
}
do {
/* map common memory */
pChar = (u_char *)pcmciaMemwin[CIS_MEM_TUPLE].start +
pCtrl->memBase;
cisMemwin.window = PCMCIA_CIS_WINDOW;
cisMemwin.flags = MAP_ACTIVE | MAP_16BIT;
cisMemwin.extraws = 2;
cisMemwin.start = pcmciaMemwin[CIS_MEM_TUPLE].start;
cisMemwin.stop = pcmciaMemwin[CIS_MEM_TUPLE].stop;
cisMemwin.cardstart = longlinkC;
if ((* pChip->memwinSet)(sock, &cisMemwin) != OK)
return (ERROR);
/* check the link target tuple */
pTupleC = (CIS_TUPLE_C *)pChar;
if (pTupleC->code == CISTPL_LINKTARGET)
pChar += pTupleC->link + 2;
else
break;
/* parse the tuple chain */
endList = FALSE;
for (tuples = 0; !endList; tuples++)
{
pTupleC = (CIS_TUPLE_C *)pChar;
switch (pTupleC->code)
{
case CISTPL_NULL:
pChar++;
break;
case CISTPL_LONGLINK_A:
ps = pChar + 2;
pd = (u_char *)&longlinkA;
for (ix = 0; ix < 4; ix++)
*pd++ = *ps++;
pChar += pTupleC->link + 2;
break;
case CISTPL_LONGLINK_C:
ps = pChar + 2;
pd = (u_char *)&longlinkC;
for (ix = 0; ix < 4; ix++)
*pd++ = *ps++;
pChar += pTupleC->link + 2;
break;
case CISTPL_NO_LINK:
noLink = TRUE;
pChar += pTupleC->link + 2;
break;
case CISTPL_END:
if (tuples != 0)
endList = TRUE;
pChar += pTupleC->link + 2;
break;
case CISTPL_CHECKSUM:
/* XXX ignore now */
pChar += pTupleC->link + 2;
break;
default:
pNode = (DL_NODE *)malloc (pTupleC->link + 2 +
sizeof(DL_NODE));
pd = (u_char *)pNode + sizeof(DL_NODE);
ps = pChar;
for (ix = 0; ix < (pTupleC->link + 2); ix++)
*pd++ = *ps++;
dllAdd (&pCard->cisTupleList, pNode);
pChar += pTupleC->link + 2;
break;
}
if ((pTupleC->link == 0xff) || (tuples >= CIS_MAX_TUPLES))
endList = TRUE;
}
} while (longlinkC != 0);
/* unmap memory window */
cisMemwin.window = 0;
cisMemwin.flags = 0;
cisMemwin.extraws = 0;
cisMemwin.start = 0;
cisMemwin.stop = 0;
cisMemwin.cardstart = 0;
if ((* pChip->memwinSet)(sock, &cisMemwin) != OK)
return (ERROR);
return (OK);
}
/*******************************************************************************
*
* cisConfigGet - get configuration information from the CIS tuple link list
*
* Get configuration information from the CIS tuple link list.
*
* RETURNS: OK (always).
*/
LOCAL STATUS cisConfigGet
(
int sock /* socket no. */
)
{
PCMCIA_CTRL *pCtrl = &pcmciaCtrl;
PCMCIA_CARD *pCard = &pCtrl->card[sock];
CIS_CONFIG *pDefault = 0;
CIS_CONFIG *pConfig;
DL_NODE *pNode;
CIS_TUPLE *pTuple;
CIS_BYTE4 base;
CIS_BYTE4 mask;
CIS_BYTE4 addr;
CIS_BYTE4 length;
CIS_BYTE4 cAddr;
CIS_BYTE4 hAddr;
int lengthSize;
int addrSize;
int maskSize;
int windows;
int ix;
u_char *pChar;
u_char *pEnd;
u_char *pv;
u_char featureSelection;
u_char parameterSelection;
u_char hostaddr;
u_char waitScale;
u_char busyScale;
u_char reservedScale;
for (pNode = DLL_FIRST (&pCard->cisTupleList);
pNode != NULL;
pNode = DLL_NEXT(pNode))
{
pTuple = (CIS_TUPLE *)((char *)pNode + sizeof (DL_NODE));
pChar = (u_char *)pTuple + sizeof (CIS_TUPLE);
pEnd = pChar + pTuple->link;
switch (pTuple->code)
{
case CISTPL_CONFIG:
pCard->regBase = 0;
pCard->regMask = 0;
addrSize = (*pChar & 0x03) + 1;
maskSize = ((*pChar & 0x3c) >> 2) + 1;
pChar += 2;
if (pChar > pEnd)
break;
base.l = 0;
for (ix = 0; ix < addrSize; ix++)
base.c[ix] = *pChar++;
mask.l = 0;
for (ix = 0; ix < maskSize; ix++)
mask.c[ix] = *pChar++;
pCard->regBase = base.l;
pCard->regMask = mask.l;
break;
case CISTPL_CFTABLE_ENTRY:
pConfig = (CIS_CONFIG *)calloc(1, sizeof(CIS_CONFIG));
if (*pChar & 0x40)
pDefault = pConfig;
else if (pDefault != 0)
{
bcopy ((char *)pDefault, (char *)pConfig,
sizeof(CIS_CONFIG));
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -