📄 cislib.c
字号:
/* cisLib.c - PCMCIA CIS library *//* Copyright 1984-1996 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01f,21jun00,rsh upgrade to dosFs 2.001g,17sep98,lrn reworked DosFs 2.0 support and memory leak issues01f,14jul98,lrn DosFs2.0: can not delete DOS devices01e,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 up01a,10feb95,hdn written.*//*DESCRIPTIONThis library contains routines to manipulate the CIS (ConfigurationInformation 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 interpretedand stored in another link list, `cisConifigList'. After the CIS is read,the PC card's enabler routine allocates resources and initializes a devicedriver for the PC card.If a PC card is inserted, the CSC (Card Status Change) interrupt handlergets a CSC event from the PCMCIA chip and adds a cisGet() job to thePCMCIA daemon. The PCMCIA daemon initiates the cisGet() work. The CISlibrary reads the CIS from the PC card and makes a linked list of CIStuples. It then enables the card.If the PC card is removed, the CSC interrupt handler gets a CSC event fromthe PCMCIA chip and adds a cisFree() job to the PCMCIA daemon. The PCMCIAdaemon 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 + -