📄 tcic.c
字号:
/* tcic.c - Databook TCIC/2 PCMCIA host bus adaptor chip driver *//* Copyright 1984-1996 Wind River Systems, Inc. *//* Copyright (c) 1994 David A. Hinds -- All Rights Reserved */#include "copyright_wrs.h"/*modification history--------------------01f,21jun00,rsh upgrade to dosFs 2.001e,29mar96,jdi doc: fixed error.01d,28mar96,jdi doc: cleaned up language and format.01c,08mar96,hdn added more descriptions.01b,22feb96,hdn cleaned up01a,03oct95,hdn written based on David Hinds's version 2.2.3.*//*DESCRIPTIONThis library contains routines to manipulate the PCMCIA functions on theDatabook DB86082 PCMCIA chip. The initialization routine tcicInit() is the only global function and isincluded in the PCMCIA chip table `pcmciaAdapter'. If tcicInit() findsthe TCIC chip, it registers all function pointers of the PCMCIA_CHIPstructure.*/#include "vxWorks.h"#include "taskLib.h"#include "intLib.h"#include "sysLib.h"#include "drv/pcmcia/pcmciaLib.h"#include "drv/pcmcia/tcic.h"/* defines */#define TCIC_GETB(reg) sysInByte (tcicBase+reg)#define TCIC_GETW(reg) sysInWord (tcicBase+reg)#define TCIC_SETB(reg, value) sysOutByte (tcicBase+reg, value)#define TCIC_SETW(reg, value) sysOutWord (tcicBase+reg, value)/* imports */IMPORT PCMCIA_CTRL pcmciaCtrl;/* globals */int tcicBase;/* locals */LOCAL char tcicCardStatus[TCIC_MAX_SOCKS];LOCAL SEMAPHORE tcicMuteSem;/* forward declarations */LOCAL STATUS tcicReset (int sock);LOCAL int tcicStatus (int sock);LOCAL int tcicFlagGet (int sock);LOCAL STATUS tcicFlagSet (int sock, int flag);LOCAL STATUS tcicCscOn (int sock, int irq);LOCAL STATUS tcicCscOff (int sock, int irq);LOCAL int tcicCscPoll (int sock);LOCAL int tcicIrqGet (int sock);LOCAL STATUS tcicIrqSet (int sock, int irq);LOCAL STATUS tcicIowinGet (int sock, PCMCIA_IOWIN *io);LOCAL STATUS tcicIowinSet (int sock, PCMCIA_IOWIN *io);LOCAL STATUS tcicMemwinGet (int sock, PCMCIA_MEMWIN *mem);LOCAL STATUS tcicMemwinSet (int sock, PCMCIA_MEMWIN *mem);LOCAL char tcicAuxGetb (int reg);LOCAL void tcicAuxSetb (int reg, char value);#ifdef __unused__LOCAL short tcicAuxGetw (int reg);#endifLOCAL void tcicAuxSetw (int reg, short value);LOCAL long tcicGetl (int reg);LOCAL void tcicSetl (int reg, long value);/********************************************************************************* tcicInit - initialize the TCIC chip** This routine initializes the TCIC chip.** RETURNS: OK, or ERROR if the TCIC chip cannot be found.*/STATUS tcicInit ( int ioBase, /* IO base address */ int intVec, /* interrupt vector */ int intLevel, /* interrupt level */ FUNCPTR showRtn /* show routine */ ) { PCMCIA_CTRL *pCtrl = &pcmciaCtrl; PCMCIA_CHIP *pChip = &pCtrl->chip; int sock = 0; int ix; tcicBase = ioBase; TCIC_SETW (TCIC_ADDR, 0); if (TCIC_GETW (TCIC_ADDR) == 0) { TCIC_SETW (TCIC_ADDR, 0xc3a5); if (TCIC_GETW (TCIC_ADDR) == 0xc3a5) sock = 2; } if (sock == 0) return (ERROR); semMInit (&tcicMuteSem, SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE); semTake (&tcicMuteSem, WAIT_FOREVER); /* mutual execlusion start */ tcicAuxSetb (TCIC_AUX_WCTL, TCIC_WAIT_SENSE | TCIC_WAIT_ASYNC | 7); tcicAuxSetw (TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY | 0x0a00); for (ix = 0; ix < sock; ix++) { tcicSetl (TCIC_ADDR, (sock << TCIC_ADDR_SS_SHFT) | TCIC_ADDR_INDREG | TCIC_SCF1(sock)); tcicAuxSetb (TCIC_AUX_ILOCK, TCIC_ILOCK_HOLD_CCLK | TCIC_ILOCK_CWAIT | TCIC_ILOCK_CRESENA); tcicCardStatus[sock] = TCIC_GETB (TCIC_SSTAT); } pChip->name = "Databook TCIC2"; pChip->reset = (FUNCPTR) tcicReset; pChip->status = (FUNCPTR) tcicStatus; pChip->flagGet = (FUNCPTR) tcicFlagGet; pChip->flagSet = (FUNCPTR) tcicFlagSet; pChip->cscOn = (FUNCPTR) tcicCscOn; pChip->cscOff = (FUNCPTR) tcicCscOff; pChip->cscPoll = (FUNCPTR) tcicCscPoll; pChip->irqGet = (FUNCPTR) tcicIrqGet; pChip->irqSet = (FUNCPTR) tcicIrqSet; pChip->iowinGet = (FUNCPTR) tcicIowinGet; pChip->iowinSet = (FUNCPTR) tcicIowinSet; pChip->memwinGet = (FUNCPTR) tcicMemwinGet; pChip->memwinSet = (FUNCPTR) tcicMemwinSet; pChip->type = PCMCIA_TCIC; pChip->socks = sock; pChip->installed = TRUE; pChip->intLevel = intLevel; pChip->memWindows = TCIC_MEM_WINDOWS; pChip->ioWindows = TCIC_IO_WINDOWS; pChip->showRtn = showRtn; semGive (&tcicMuteSem); /* mutual execlusion stop */ return (OK); }/********************************************************************************* tcicStatus - Get status of the socket.** This routine gets status of the socket.* This routine can be called in interrupt level.** RETURNS: The status of the socket.*/LOCAL int tcicStatus ( int sock /* socket no. */ ) { BOOL intMode = intContext (); int valueAddr = 0; char value; int status; if (intMode) valueAddr = tcicGetl (TCIC_ADDR); else semTake (&tcicMuteSem, WAIT_FOREVER); /* mutual execlusion start */ tcicSetl (TCIC_ADDR, (sock << TCIC_ADDR_SS_SHFT) | TCIC_ADDR_INDREG | TCIC_SCF1(sock)); value = TCIC_GETB (TCIC_SSTAT); status = (value & TCIC_SSTAT_CD) ? PC_IS_CARD : PC_NO_CARD; status |= (value & TCIC_SSTAT_WP) ? PC_WRPROT : 0; if (TCIC_GETW (TCIC_DATA) & TCIC_SCF1_IOSTS) status |= (value & TCIC_SSTAT_LBAT1) ? PC_STSCHG : 0; else { status |= (value & TCIC_SSTAT_RDY) ? PC_READY : 0; status |= (value & TCIC_SSTAT_LBAT1) ? PC_BATDEAD : 0; status |= (value & TCIC_SSTAT_LBAT2) ? PC_BATWARN : 0; } value = TCIC_GETB (TCIC_PWR); if (value & (TCIC_PWR_VCC (sock) | TCIC_PWR_VPP (sock))) status |= PC_POWERON; if (intMode) tcicSetl (TCIC_ADDR, valueAddr); else semGive (&tcicMuteSem); /* mutual execlusion stop */ return (status); } /********************************************************************************* tcicFlagGet - Get configuration flag from the socket.** This routine gets configuration flag from the socket.** RETURNS: The configuration flag of the socket.*/LOCAL int tcicFlagGet ( int sock /* socket no. */ ) { short value; int flag; semTake (&tcicMuteSem, WAIT_FOREVER); /* mutual execlusion start */ tcicSetl (TCIC_ADDR, (sock << TCIC_ADDR_SS_SHFT) | TCIC_ADDR_INDREG | TCIC_SCF1(sock)); flag = (TCIC_GETW (TCIC_DATA) & TCIC_SCF1_IOSTS) ? PC_IOCARD : 0; value = TCIC_GETB (TCIC_PWR); if (value & TCIC_PWR_VCC (sock)) { if (value & TCIC_PWR_VPP (sock)) flag |= PC_VCC_5V; else flag |= PC_VCC_5V | PC_VPP_5V; } else if (value & TCIC_PWR_VPP (sock)) flag |= PC_VCC_5V | PC_VPP_12V; value = tcicAuxGetb (TCIC_AUX_ILOCK); flag |= (value & TCIC_ILOCK_CRESET) ? PC_RESET : 0; semGive (&tcicMuteSem); /* mutual execlusion stop */ return (flag); }/********************************************************************************* tcicFlagSet - Set configuration flag into the socket.** This routine sets configuration flag into the socket.** RETURNS: OK (always).*/LOCAL STATUS tcicFlagSet ( int sock, /* socket no. */ int flag /* configuration flag */ ) { char value; short scf1; short scf2; semTake (&tcicMuteSem, WAIT_FOREVER); /* mutual execlusion start */ TCIC_SETW (TCIC_ADDR+2, (sock << TCIC_SS_SHFT) | TCIC_ADR2_INDREG); value = TCIC_GETB (TCIC_PWR); value &= ~(TCIC_PWR_VCC (sock) | TCIC_PWR_VPP (sock)); if (flag & PC_VCC_5V) { if (flag & PC_VPP_12V) value |= TCIC_PWR_VPP (sock); else if (flag & PC_VPP_5V) value |= TCIC_PWR_VCC (sock); else value |= TCIC_PWR_VCC (sock) | TCIC_PWR_VPP (sock); } TCIC_SETB (TCIC_PWR, value); taskDelay (sysClkRateGet () >> 4); TCIC_SETW (TCIC_ADDR, TCIC_SCF1 (sock)); scf1 = TCIC_GETW (TCIC_DATA); TCIC_SETW (TCIC_ADDR, TCIC_SCF2 (sock)); scf2 = TCIC_GETW (TCIC_DATA); if (flag & PC_IOCARD) { scf1 |= TCIC_SCF1_IOSTS | TCIC_SCF1_SPKR; scf2 |= TCIC_SCF2_MRDY; } else { scf1 &= ~(TCIC_SCF1_IOSTS | TCIC_SCF1_SPKR); scf2 &= ~TCIC_SCF2_MRDY; } TCIC_SETW (TCIC_ADDR, TCIC_SCF1 (sock)); TCIC_SETW (TCIC_DATA, scf1); TCIC_SETW (TCIC_ADDR, TCIC_SCF2 (sock)); TCIC_SETW (TCIC_DATA, scf2); if (flag & PC_VCC_MASK) TCIC_SETB (TCIC_SCTRL, TCIC_SCTRL_ENA); value = tcicAuxGetb (TCIC_AUX_ILOCK) & ~TCIC_ILOCK_CRESET; if (flag & PC_RESET) value |= TCIC_ILOCK_CRESET; tcicAuxSetb (TCIC_AUX_ILOCK, value); semGive (&tcicMuteSem); /* mutual execlusion stop */ return (OK); } /********************************************************************************* tcicCscOn - Enables card status change interrupt.** This routine enables card status change interrupt.** RETURNS: OK (always).*/LOCAL STATUS tcicCscOn ( int sock, /* socket no. */ int irq /* IRQ for CSC */ ) { char value; short scf2; semTake (&tcicMuteSem, WAIT_FOREVER); /* mutual execlusion start */ /* Turn on all card status change interrupts */ tcicSetl (TCIC_ADDR, (sock << TCIC_ADDR_SS_SHFT) | TCIC_ADDR_INDREG | TCIC_SCF2(sock)); value = tcicAuxGetb (TCIC_AUX_SYSCFG); tcicAuxSetb (TCIC_AUX_SYSCFG, value | irq); TCIC_SETB (TCIC_IENA, TCIC_IENA_CDCHG | TCIC_IENA_CFG_HIGH); scf2 = TCIC_GETW (TCIC_DATA); scf2 &= TCIC_SCF2_MDBR | TCIC_SCF2_IDBR | TCIC_SCF2_RI; TCIC_SETW (TCIC_DATA, scf2); /* flush current card status changes */ TCIC_SETB (TCIC_ICSR, TCIC_ICSR_CLEAR); semGive (&tcicMuteSem); /* mutual execlusion stop */ return (OK); }/********************************************************************************* tcicCscOff - Disable card status change interrupt.** This routine disables card status change interrupt.** RETURNS: OK (always).*/LOCAL STATUS tcicCscOff ( int sock, /* socket no. */ int irq /* IRQ for CSC */ ) { semTake (&tcicMuteSem, WAIT_FOREVER); /* mutual execlusion start */ TCIC_SETW (TCIC_ADDR+2, (sock << TCIC_SS_SHFT)); TCIC_SETB (TCIC_IENA, TCIC_IENA_CFG_OFF); semGive (&tcicMuteSem); /* mutual execlusion stop */ return (OK); }/********************************************************************************* tcicCscPoll - Get the card status by polling the register.** This routine gets the card status by polling the register.* This routine can be called in interrupt level.** RETURNS: The card status of the socket.*/LOCAL int tcicCscPoll ( int sock /* socket no. */ ) { char latch = 0; BOOL intMode = intContext (); char value; int status; int ix; int valueAddr = 0; if (intMode) valueAddr = tcicGetl (TCIC_ADDR); else semTake (&tcicMuteSem, WAIT_FOREVER); /* mutual execlusion start */ tcicSetl (TCIC_ADDR, (sock << TCIC_ADDR_SS_SHFT) | TCIC_ADDR_INDREG | TCIC_SCF1(sock)); for (ix = 0; ix < 10; ix++) { /* What bits have changed state? */ value = TCIC_GETB (TCIC_SSTAT); latch |= value ^ tcicCardStatus[sock]; tcicCardStatus[sock] = value; /* Try to reset interrupt status register */ if (TCIC_GETB (TCIC_ICSR) != 0) TCIC_SETB (TCIC_ICSR, TCIC_ICSR_CLEAR); else break; } status = (latch & TCIC_SSTAT_CD) ? PC_DETECT : 0; status |= (latch & TCIC_SSTAT_WP) ? PC_WRPROT : 0; if (TCIC_GETW (TCIC_DATA) & TCIC_SCF1_IOSTS) status |= (latch & TCIC_SSTAT_LBAT1) ? PC_STSCHG : 0; else { status |= (latch & TCIC_SSTAT_RDY) ? PC_READY : 0; status |= (latch & TCIC_SSTAT_LBAT1) ? PC_BATDEAD : 0; status |= (latch & TCIC_SSTAT_LBAT2) ? PC_BATWARN : 0; } if (intMode) tcicSetl (TCIC_ADDR, valueAddr); else semGive (&tcicMuteSem); /* mutual execlusion stop */ return (status); }/********************************************************************************* tcicIrqGet - Get IRQ level of the socket.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -