/*************************************************************************** Function: sReadAiopNumChan Purpose: Read the number of channels available in an AIOP directly from an AIOP. Call: sReadAiopNumChan(CtlP, aiop) CONTROLLER_T *CtlP; Ptr to controller structure int aiop: AIOP index Return: int: The number of channels available Comments: The number of channels is determined by write/reads from identical offsets within the SRAM address spaces for channels 0 and 4. If the channel 4 space is mirrored to channel 0 it is a 4 channel AIOP, otherwise it is an 8 channel. Warnings: No context switches are allowed while executing this function. */ int sReadAiopNumChan(CONTROLLER_T *CtlP, int aiop) { Word_t x, y; rp_writeaiop4(CtlP, aiop, _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */ rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0); /* read from SRAM, chan 0 */ x = rp_readaiop2(CtlP, aiop, _INDX_DATA); rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0x4000); /* read from SRAM, chan 4 */ y = rp_readaiop2(CtlP, aiop, _INDX_DATA); if(x != y) /* if different must be 8 chan */ return(8); else return(4); }
static int sPCIInitController( CONTROLLER_t *CtlP, int AiopNum, int IRQNum, Byte_t Frequency, int PeriodicOnly, int VendorDevice) { int i; CtlP->CtlID = CTLID_0001; /* controller release 1 */ sPCIControllerEOI(CtlP); /* Init AIOPs */ CtlP->NumAiop = 0; for(i=0; i < AiopNum; i++) { /*device_printf(CtlP->dev, "aiop %d.\n", i);*/ CtlP->AiopID[i] = sReadAiopID(CtlP, i); /* read AIOP ID */ /*device_printf(CtlP->dev, "ID = %d.\n", CtlP->AiopID[i]);*/ if(CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */ { break; /* done looking for AIOPs */ } switch( VendorDevice ) { case PCI_PRODUCT_COMTROL_ROCKETPORT4QUAD: case PCI_PRODUCT_COMTROL_ROCKETPORT4RJ: case PCI_PRODUCT_COMTROL_ROCKETMODEM4: CtlP->AiopNumChan[i] = 4; break; case PCI_PRODUCT_COMTROL_ROCKETMODEM6: CtlP->AiopNumChan[i] = 6; break; case PCI_PRODUCT_COMTROL_ROCKETPORT8OCTA: case PCI_PRODUCT_COMTROL_ROCKETPORT8RJ: case PCI_PRODUCT_COMTROL_ROCKETPORT8EXT: case PCI_PRODUCT_COMTROL_ROCKETPORT16EXT: case PCI_PRODUCT_COMTROL_ROCKETPORT32EXT: CtlP->AiopNumChan[i] = 8; break; default: CtlP->AiopNumChan[i] = sReadAiopNumChan(CtlP, i); break; } /*device_printf(CtlP->dev, "%d channels.\n", CtlP->AiopNumChan[i]);*/ rp_writeaiop2(CtlP, i, _INDX_ADDR,_CLK_PRE); /* clock prescaler */ /*device_printf(CtlP->dev, "configuring clock prescaler.\n");*/ rp_writeaiop1(CtlP, i, _INDX_DATA,CLOCK_PRESC); /*device_printf(CtlP->dev, "configured clock prescaler.\n");*/ CtlP->NumAiop++; /* bump count of AIOPs */ } if(CtlP->NumAiop == 0) return(-1); else return(CtlP->NumAiop); }
static int sPCIInitController( CONTROLLER_t *CtlP, int AiopNum, int IRQNum, Byte_t Frequency, int PeriodicOnly, int VendorDevice) { int i; CtlP->CtlID = CTLID_0001; /* controller release 1 */ sPCIControllerEOI(CtlP); /* Init AIOPs */ CtlP->NumAiop = 0; for(i=0; i < AiopNum; i++) { /*device_printf(CtlP->dev, "aiop %d.\n", i);*/ CtlP->AiopID[i] = sReadAiopID(CtlP, i); /* read AIOP ID */ /*device_printf(CtlP->dev, "ID = %d.\n", CtlP->AiopID[i]);*/ if(CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */ { break; /* done looking for AIOPs */ } switch( VendorDevice ) { case RP_DEVICE_ID_4Q: case RP_DEVICE_ID_4J: case RP_DEVICE_ID_4M: CtlP->AiopNumChan[i] = 4; break; case RP_DEVICE_ID_6M: CtlP->AiopNumChan[i] = 6; break; case RP_DEVICE_ID_8O: case RP_DEVICE_ID_8J: case RP_DEVICE_ID_8I: case RP_DEVICE_ID_16I: case RP_DEVICE_ID_32I: CtlP->AiopNumChan[i] = 8; break; default: #ifdef notdef CtlP->AiopNumChan[i] = 8; #else CtlP->AiopNumChan[i] = sReadAiopNumChan(CtlP, i); #endif /* notdef */ break; } /*device_printf(CtlP->dev, "%d channels.\n", CtlP->AiopNumChan[i]);*/ rp_writeaiop2(CtlP, i, _INDX_ADDR,_CLK_PRE); /* clock prescaler */ /*device_printf(CtlP->dev, "configuring clock prescaler.\n");*/ rp_writeaiop1(CtlP, i, _INDX_DATA,CLOCK_PRESC); /*device_printf(CtlP->dev, "configured clock prescaler.\n");*/ CtlP->NumAiop++; /* bump count of AIOPs */ } if(CtlP->NumAiop == 0) return(-1); else return(CtlP->NumAiop); }
/*************************************************************************** Function: sInitController Purpose: Initialization of controller global registers and controller structure. Call: sInitController(CtlP,MudbacCtlP,AiopNum, IRQNum,Frequency,PeriodicOnly) CONTROLLER_T *CtlP; Ptr to controller structure CONTROLLER_T *MudbacCtlP; Ptr to Mudbac controller structure int AiopNum; Number of Aiops int IRQNum; Interrupt Request number. Can be any of the following: 0: Disable global interrupts 3: IRQ 3 4: IRQ 4 5: IRQ 5 9: IRQ 9 10: IRQ 10 11: IRQ 11 12: IRQ 12 15: IRQ 15 Byte_t Frequency: A flag identifying the frequency of the periodic interrupt, can be any one of the following: FREQ_DIS - periodic interrupt disabled FREQ_137HZ - 137 Hertz FREQ_69HZ - 69 Hertz FREQ_34HZ - 34 Hertz FREQ_17HZ - 17 Hertz FREQ_9HZ - 9 Hertz FREQ_4HZ - 4 Hertz If IRQNum is set to 0 the Frequency parameter is overidden, it is forced to a value of FREQ_DIS. int PeriodicOnly: TRUE if all interrupts except the periodic interrupt are to be blocked. FALSE is both the periodic interrupt and other channel interrupts are allowed. If IRQNum is set to 0 the PeriodicOnly parameter is overidden, it is forced to a value of FALSE. Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller initialization failed. Comments: If periodic interrupts are to be disabled but AIOP interrupts are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE. If interrupts are to be completely disabled set IRQNum to 0. Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an invalid combination. This function performs initialization of global interrupt modes, but it does not actually enable global interrupts. To enable and disable global interrupts use functions sEnGlobalInt() and sDisGlobalInt(). Enabling of global interrupts is normally not done until all other initializations are complete. Even if interrupts are globally enabled, they must also be individually enabled for each channel that is to generate interrupts. Warnings: No range checking on any of the parameters is done. No context switches are allowed while executing this function. After this function all AIOPs on the controller are disabled, they can be enabled with sEnAiop(). */ static int sInitController( CONTROLLER_T *CtlP, CONTROLLER_T *MudbacCtlP, int AiopNum, int IRQNum, Byte_t Frequency, int PeriodicOnly) { int i; int ctl_base, aiop_base, aiop_size; CtlP->CtlID = CTLID_0001; /* controller release 1 */ ISACTL(CtlP)->MBaseIO = rp_nisadevs; if (MudbacCtlP->io[ISACTL(CtlP)->MBaseIO] != NULL) { ISACTL(CtlP)->MReg0IO = 0x40 + 0; ISACTL(CtlP)->MReg1IO = 0x40 + 1; ISACTL(CtlP)->MReg2IO = 0x40 + 2; ISACTL(CtlP)->MReg3IO = 0x40 + 3; } else { MudbacCtlP->io_rid[ISACTL(CtlP)->MBaseIO] = ISACTL(CtlP)->MBaseIO; ctl_base = rman_get_start(MudbacCtlP->io[0]) + 0x40 + 0x400 * rp_nisadevs; MudbacCtlP->io[ISACTL(CtlP)->MBaseIO] = bus_alloc_resource(MudbacCtlP->dev, SYS_RES_IOPORT, &CtlP->io_rid[ISACTL(CtlP)->MBaseIO], ctl_base, ctl_base + 3, 4, RF_ACTIVE); ISACTL(CtlP)->MReg0IO = 0; ISACTL(CtlP)->MReg1IO = 1; ISACTL(CtlP)->MReg2IO = 2; ISACTL(CtlP)->MReg3IO = 3; } #if 1 ISACTL(CtlP)->MReg2 = 0; /* interrupt disable */ ISACTL(CtlP)->MReg3 = 0; /* no periodic interrupts */ #else if(sIRQMap[IRQNum] == 0) /* interrupts globally disabled */ { ISACTL(CtlP)->MReg2 = 0; /* interrupt disable */ ISACTL(CtlP)->MReg3 = 0; /* no periodic interrupts */ } else { ISACTL(CtlP)->MReg2 = sIRQMap[IRQNum]; /* set IRQ number */ ISACTL(CtlP)->MReg3 = Frequency; /* set frequency */ if(PeriodicOnly) /* periodic interrupt only */ { ISACTL(CtlP)->MReg3 |= PERIODIC_ONLY; } } #endif rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg2IO,ISACTL(CtlP)->MReg2); rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg3IO,ISACTL(CtlP)->MReg3); sControllerEOI(MudbacCtlP,CtlP); /* clear EOI if warm init */ /* Init AIOPs */ CtlP->NumAiop = 0; for(i=0; i < AiopNum; i++) { if (CtlP->io[i] == NULL) { CtlP->io_rid[i] = i; aiop_base = rman_get_start(CtlP->io[0]) + 0x400 * i; if (rp_nisadevs == 0) aiop_size = 0x44; else aiop_size = 0x40; CtlP->io[i] = bus_alloc_resource(CtlP->dev, SYS_RES_IOPORT, &CtlP->io_rid[i], aiop_base, aiop_base + aiop_size - 1, aiop_size, RF_ACTIVE); } else aiop_base = rman_get_start(CtlP->io[i]); rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO, ISACTL(CtlP)->MReg2IO, ISACTL(CtlP)->MReg2 | (i & 0x03)); /* AIOP index */ rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO, ISACTL(CtlP)->MReg0IO, (Byte_t)(aiop_base >> 6)); /* set up AIOP I/O in MUDBAC */ sEnAiop(MudbacCtlP,CtlP,i); /* enable the AIOP */ CtlP->AiopID[i] = sReadAiopID(CtlP, i); /* read AIOP ID */ if(CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */ { sDisAiop(MudbacCtlP,CtlP,i); /* disable AIOP */ bus_release_resource(CtlP->dev, SYS_RES_IOPORT, CtlP->io_rid[i], CtlP->io[i]); CtlP->io[i] = NULL; break; /* done looking for AIOPs */ } CtlP->AiopNumChan[i] = sReadAiopNumChan(CtlP, i); /* num channels in AIOP */ rp_writeaiop2(CtlP,i,_INDX_ADDR,_CLK_PRE); /* clock prescaler */ rp_writeaiop1(CtlP,i,_INDX_DATA,CLOCK_PRESC); CtlP->NumAiop++; /* bump count of AIOPs */ sDisAiop(MudbacCtlP,CtlP,i); /* disable AIOP */ } if(CtlP->NumAiop == 0) return(-1); else return(CtlP->NumAiop); }