rp_isa.c revision 69781
161541Stanimura/*
261541Stanimura * Copyright (c) Comtrol Corporation <support@comtrol.com>
361541Stanimura * All rights reserved.
461541Stanimura *
561541Stanimura * ISA-specific part separated from:
661541Stanimura * sys/i386/isa/rp.c,v 1.33 1999/09/28 11:45:27 phk Exp
761541Stanimura *
861541Stanimura * Redistribution and use in source and binary forms, with or without
961541Stanimura * modification, are permitted prodived that the follwoing conditions
1061541Stanimura * are met.
1161541Stanimura * 1. Redistributions of source code must retain the above copyright
1261541Stanimura *    notive, this list of conditions and the following disclainer.
1361541Stanimura * 2. Redistributions in binary form must reproduce the above copyright
1461541Stanimura *    notice, this list of conditions and the following disclaimer in the
1561541Stanimura *    documentation and/or other materials prodided with the distribution.
1661541Stanimura * 3. All advertising materials mentioning features or use of this software
1761541Stanimura *    must display the following acknowledgement:
1861541Stanimura *       This product includes software developed by Comtrol Corporation.
1961541Stanimura * 4. The name of Comtrol Corporation may not be used to endorse or
2061541Stanimura *    promote products derived from this software without specific
2161541Stanimura *    prior written permission.
2261541Stanimura *
2361541Stanimura * THIS SOFTWARE IS PROVIDED BY COMTROL CORPORATION ``AS IS'' AND ANY
2461541Stanimura * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2561541Stanimura * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2661541Stanimura * ARE DISCLAIMED.  IN NO EVENT SHALL COMTROL CORPORATION BE LIABLE FOR
2761541Stanimura * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2861541Stanimura * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2961541Stanimura * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
3061541Stanimura * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3161541Stanimura * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3261541Stanimura * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3361541Stanimura * SUCH DAMAGE.
3461541Stanimura *
3561541Stanimura * $FreeBSD: head/sys/dev/rp/rp_isa.c 69781 2000-12-08 21:51:06Z dwmalone $
3661541Stanimura */
3761541Stanimura
3861541Stanimura#include <sys/param.h>
3961541Stanimura#include <sys/systm.h>
4061541Stanimura#include <sys/fcntl.h>
4161541Stanimura#include <sys/malloc.h>
4261541Stanimura#include <sys/tty.h>
4361541Stanimura#include <sys/conf.h>
4461541Stanimura#include <sys/kernel.h>
4561541Stanimura#include <machine/resource.h>
4661541Stanimura#include <machine/bus.h>
4761541Stanimura#include <sys/bus.h>
4861541Stanimura#include <sys/rman.h>
4961541Stanimura
5061541Stanimura#define ROCKET_C
5161541Stanimura#include <dev/rp/rpreg.h>
5261541Stanimura#include <dev/rp/rpvar.h>
5361541Stanimura
5461541Stanimura#include <isa/isavar.h>
5561541Stanimura
5661541Stanimura/* ISA-specific part of CONTROLLER_t */
5761541Stanimurastruct ISACONTROLLER_T {
5861541Stanimura	int		MBaseIO;	/* rid of the Mudbac controller for this controller */
5961541Stanimura	int		MReg0IO;	/* offset0 of the Mudbac controller for this controller */
6061541Stanimura	int		MReg1IO;	/* offset1 of the Mudbac controller for this controller */
6161541Stanimura	int		MReg2IO;	/* offset2 of the Mudbac controller for this controller */
6261541Stanimura	int		MReg3IO;	/* offset3 of the Mudbac controller for this controller */
6361541Stanimura	Byte_t		MReg2;
6461541Stanimura	Byte_t		MReg3;
6561541Stanimura};
6661541Stanimuratypedef struct ISACONTROLLER_T ISACONTROLLER_t;
6761541Stanimura
6861541Stanimura#define ISACTL(ctlp) ((ISACONTROLLER_t *)((ctlp)->bus_ctlp))
6961541Stanimura
7061541Stanimura/***************************************************************************
7161541StanimuraFunction: sControllerEOI
7261541StanimuraPurpose:  Strobe the MUDBAC's End Of Interrupt bit.
7361541StanimuraCall:	  sControllerEOI(MudbacCtlP,CtlP)
7461541Stanimura	  CONTROLLER_T *MudbacCtlP; Ptr to Mudbac controller structure
7561541Stanimura	  CONTROLLER_T *CtlP; Ptr to controller structure
7661541Stanimura*/
7761541Stanimura#define sControllerEOI(MudbacCtlP,CtlP) \
7861541Stanimura	rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg2IO,ISACTL(CtlP)->MReg2 | INT_STROB)
7961541Stanimura
8061541Stanimura/***************************************************************************
8161541StanimuraFunction: sDisAiop
8261541StanimuraPurpose:  Disable I/O access to an AIOP
8361541StanimuraCall:	  sDisAiop(MudbacCtlP,CtlP)
8461541Stanimura	  CONTROLLER_T *MudbacCtlP; Ptr to Mudbac controller structure
8561541Stanimura	  CONTROLLER_T *CtlP; Ptr to controller structure
8661541Stanimura	  int AiopNum; Number of AIOP on controller
8761541Stanimura*/
8861541Stanimura#define sDisAiop(MudbacCtlP,CtlP,AIOPNUM) \
8961541Stanimura{ \
9061541Stanimura   ISACTL(CtlP)->MReg3 &= rp_sBitMapClrTbl[AIOPNUM]; \
9161541Stanimura   rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg3IO,ISACTL(CtlP)->MReg3); \
9261541Stanimura}
9361541Stanimura
9461541Stanimura/***************************************************************************
9561541StanimuraFunction: sEnAiop
9661541StanimuraPurpose:  Enable I/O access to an AIOP
9761541StanimuraCall:	  sEnAiop(MudbacCtlP,CtlP)
9861541Stanimura	  CONTROLLER_T *MudbacCtlP; Ptr to Mudbac controller structure
9961541Stanimura	  CONTROLLER_T *CtlP; Ptr to controller structure
10061541Stanimura	  int AiopNum; Number of AIOP on controller
10161541Stanimura*/
10261541Stanimura#define sEnAiop(MudbacCtlP,CtlP,AIOPNUM) \
10361541Stanimura{ \
10461541Stanimura   ISACTL(CtlP)->MReg3 |= rp_sBitMapSetTbl[AIOPNUM]; \
10561541Stanimura   rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg3IO,ISACTL(CtlP)->MReg3); \
10661541Stanimura}
10761541Stanimura
10861541Stanimura/***************************************************************************
10961541StanimuraFunction: sGetControllerIntStatus
11061541StanimuraPurpose:  Get the controller interrupt status
11161541StanimuraCall:	  sGetControllerIntStatus(MudbacCtlP,CtlP)
11261541Stanimura	  CONTROLLER_T *MudbacCtlP; Ptr to Mudbac controller structure
11361541Stanimura	  CONTROLLER_T *CtlP; Ptr to controller structure
11461541StanimuraReturn:   Byte_t: The controller interrupt status in the lower 4
11561541Stanimura			 bits.	Bits 0 through 3 represent AIOP's 0
11661541Stanimura			 through 3 respectively.  If a bit is set that
11761541Stanimura			 AIOP is interrupting.	Bits 4 through 7 will
11861541Stanimura			 always be cleared.
11961541Stanimura*/
12061541Stanimura#define sGetControllerIntStatus(MudbacCtlP,CtlP) \
12161541Stanimura	(rp_readio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg1IO) & 0x0f)
12261541Stanimura
12361541Stanimurastatic devclass_t rp_devclass;
12461541Stanimurastatic CONTROLLER_t *rp_controller;
12561541Stanimurastatic int rp_nisadevs;
12661541Stanimura
12761541Stanimurastatic int rp_probe(device_t dev);
12861541Stanimurastatic int rp_attach(device_t dev);
12961541Stanimurastatic void rp_isareleaseresource(CONTROLLER_t *ctlp);
13061541Stanimurastatic int sInitController(CONTROLLER_T *CtlP,
13161541Stanimura			   CONTROLLER_T *MudbacCtlP,
13261541Stanimura			   int AiopNum,
13361541Stanimura			   int IRQNum,
13461541Stanimura			   Byte_t Frequency,
13561541Stanimura			   int PeriodicOnly);
13661541Stanimurastatic rp_aiop2rid_t rp_isa_aiop2rid;
13761541Stanimurastatic rp_aiop2off_t rp_isa_aiop2off;
13861541Stanimurastatic rp_ctlmask_t rp_isa_ctlmask;
13961541Stanimura
14061541Stanimurastatic int
14161541Stanimurarp_probe(device_t dev)
14261541Stanimura{
14361541Stanimura	int unit;
14461541Stanimura	CONTROLLER_t *controller;
14561541Stanimura	int num_aiops;
14661541Stanimura	CONTROLLER_t *ctlp;
14761541Stanimura	int retval;
14861541Stanimura
14961541Stanimura	/*
15061541Stanimura	 * We have no PnP RocketPort cards.
15161541Stanimura	 * (At least according to LINT)
15261541Stanimura	 */
15361541Stanimura	if (isa_get_logicalid(dev) != 0)
15461541Stanimura		return (ENXIO);
15561541Stanimura
15661541Stanimura	/* We need IO port resource to configure an ISA device. */
15761541Stanimura	if (bus_get_resource_count(dev, SYS_RES_IOPORT, 0) == 0)
15861541Stanimura		return (ENXIO);
15961541Stanimura
16061541Stanimura	unit = device_get_unit(dev);
16161541Stanimura	if (unit >= 4) {
16261541Stanimura		device_printf(dev, "rpprobe: unit number %d invalid.\n", unit);
16361541Stanimura		return (ENXIO);
16461541Stanimura	}
16561541Stanimura	device_printf(dev, "probing for RocketPort(ISA) unit %d.\n", unit);
16661541Stanimura
16761541Stanimura	ctlp = device_get_softc(dev);
16861541Stanimura	bzero(ctlp, sizeof(*ctlp));
16961541Stanimura	ctlp->dev = dev;
17061541Stanimura	ctlp->aiop2rid = rp_isa_aiop2rid;
17161541Stanimura	ctlp->aiop2off = rp_isa_aiop2off;
17261541Stanimura	ctlp->ctlmask = rp_isa_ctlmask;
17361541Stanimura
17461541Stanimura	/* The IO ports of AIOPs for an ISA controller are discrete. */
17561541Stanimura	ctlp->io_num = 1;
17669781Sdwmalone	ctlp->io_rid = malloc(sizeof(*(ctlp->io_rid)) * MAX_AIOPS_PER_BOARD, M_DEVBUF, M_NOWAIT | M_ZERO);
17769781Sdwmalone	ctlp->io = malloc(sizeof(*(ctlp->io)) * MAX_AIOPS_PER_BOARD, M_DEVBUF, M_NOWAIT | M_ZERO);
17861541Stanimura	if (ctlp->io_rid == NULL || ctlp->io == NULL) {
17961541Stanimura		device_printf(dev, "rp_attach: Out of memory.\n");
18061541Stanimura		retval = ENOMEM;
18161541Stanimura		goto nogo;
18261541Stanimura	}
18361541Stanimura
18469781Sdwmalone	ctlp->bus_ctlp = malloc(sizeof(ISACONTROLLER_t) * 1, M_DEVBUF, M_NOWAIT | M_ZERO);
18561541Stanimura	if (ctlp->bus_ctlp == NULL) {
18661541Stanimura		device_printf(dev, "rp_attach: Out of memory.\n");
18761541Stanimura		retval = ENOMEM;
18861541Stanimura		goto nogo;
18961541Stanimura	}
19061541Stanimura
19161541Stanimura	ctlp->io_rid[0] = 0;
19261541Stanimura	if (rp_controller != NULL) {
19361541Stanimura		controller = rp_controller;
19461541Stanimura		ctlp->io[0] = bus_alloc_resource(dev, SYS_RES_IOPORT, &ctlp->io_rid[0], 0, ~0, 0x40, RF_ACTIVE);
19561541Stanimura	} else {
19661541Stanimura		controller = rp_controller = ctlp;
19761541Stanimura		ctlp->io[0] = bus_alloc_resource(dev, SYS_RES_IOPORT, &ctlp->io_rid[0], 0, ~0, 0x44, RF_ACTIVE);
19861541Stanimura	}
19961541Stanimura	if (ctlp->io[0] == NULL) {
20061541Stanimura		device_printf(dev, "rp_attach: Resource not available.\n");
20161541Stanimura		retval = ENXIO;
20261541Stanimura		goto nogo;
20361541Stanimura	}
20461541Stanimura
20561541Stanimura	num_aiops = sInitController(ctlp,
20661541Stanimura				controller,
20761541Stanimura				MAX_AIOPS_PER_BOARD, 0,
20861541Stanimura				FREQ_DIS, 0);
20961541Stanimura	if (num_aiops <= 0) {
21061541Stanimura		device_printf(dev, "board%d init failed.\n", unit);
21161541Stanimura		retval = ENXIO;
21261541Stanimura		goto nogo;
21361541Stanimura	}
21461541Stanimura
21561541Stanimura	if (rp_controller == NULL)
21661541Stanimura		rp_controller = controller;
21761541Stanimura	rp_nisadevs++;
21861541Stanimura
21961541Stanimura	device_set_desc(dev, "RocketPort ISA");
22061541Stanimura
22161541Stanimura	return (0);
22261541Stanimura
22361541Stanimuranogo:
22461541Stanimura	rp_isareleaseresource(ctlp);
22561541Stanimura
22661541Stanimura	return (retval);
22761541Stanimura}
22861541Stanimura
22961541Stanimurastatic int
23061541Stanimurarp_attach(device_t dev)
23161541Stanimura{
23261541Stanimura	int	unit;
23361541Stanimura	int	num_ports, num_aiops;
23461541Stanimura	int	aiop;
23561541Stanimura	CONTROLLER_t	*ctlp;
23661541Stanimura	int	retval;
23761541Stanimura
23861541Stanimura	unit = device_get_unit(dev);
23961541Stanimura
24061541Stanimura	ctlp = device_get_softc(dev);
24161541Stanimura
24261541Stanimura#if notdef
24361541Stanimura	num_aiops = sInitController(ctlp,
24461541Stanimura				rp_controller,
24561541Stanimura				MAX_AIOPS_PER_BOARD, 0,
24661541Stanimura				FREQ_DIS, 0);
24761541Stanimura#else
24861541Stanimura	num_aiops = ctlp->NumAiop;
24961541Stanimura#endif /* notdef */
25061541Stanimura
25161541Stanimura	num_ports = 0;
25261541Stanimura	for(aiop=0; aiop < num_aiops; aiop++) {
25361541Stanimura		sResetAiopByNum(ctlp, aiop);
25461541Stanimura		sEnAiop(rp_controller, ctlp, aiop);
25561541Stanimura		num_ports += sGetAiopNumChan(ctlp, aiop);
25661541Stanimura	}
25761541Stanimura
25861541Stanimura	retval = rp_attachcommon(ctlp, num_aiops, num_ports);
25961541Stanimura	if (retval != 0)
26061541Stanimura		goto nogo;
26161541Stanimura
26261541Stanimura	return (0);
26361541Stanimura
26461541Stanimuranogo:
26561541Stanimura	rp_isareleaseresource(ctlp);
26661541Stanimura
26761541Stanimura	return (retval);
26861541Stanimura}
26961541Stanimura
27061541Stanimurastatic void
27161541Stanimurarp_isareleaseresource(CONTROLLER_t *ctlp)
27261541Stanimura{
27361541Stanimura	int i;
27461541Stanimura
27561541Stanimura	rp_releaseresource(ctlp);
27661541Stanimura
27761541Stanimura	if (ctlp == rp_controller)
27861541Stanimura		rp_controller = NULL;
27961541Stanimura	if (ctlp->io != NULL) {
28061541Stanimura		for (i = 0 ; i < MAX_AIOPS_PER_BOARD ; i++)
28161541Stanimura			if (ctlp->io[i] != NULL)
28261541Stanimura				bus_release_resource(ctlp->dev, SYS_RES_IOPORT, ctlp->io_rid[i], ctlp->io[i]);
28361541Stanimura		free(ctlp->io, M_DEVBUF);
28461541Stanimura	}
28561541Stanimura	if (ctlp->io_rid != NULL)
28661541Stanimura		free(ctlp->io_rid, M_DEVBUF);
28761541Stanimura	if (rp_controller != NULL && rp_controller->io[ISACTL(ctlp)->MBaseIO] != NULL) {
28861541Stanimura		bus_release_resource(rp_controller->dev, SYS_RES_IOPORT, rp_controller->io_rid[ISACTL(ctlp)->MBaseIO], rp_controller->io[ISACTL(ctlp)->MBaseIO]);
28961541Stanimura		rp_controller->io[ISACTL(ctlp)->MBaseIO] = NULL;
29061541Stanimura		rp_controller->io_rid[ISACTL(ctlp)->MBaseIO] = 0;
29161541Stanimura	}
29261541Stanimura	if (ctlp->bus_ctlp != NULL)
29361541Stanimura		free(ctlp->bus_ctlp, M_DEVBUF);
29461541Stanimura}
29561541Stanimura
29661541Stanimura/***************************************************************************
29761541StanimuraFunction: sInitController
29861541StanimuraPurpose:  Initialization of controller global registers and controller
29961541Stanimura	  structure.
30061541StanimuraCall:	  sInitController(CtlP,MudbacCtlP,AiopNum,
30161541Stanimura			  IRQNum,Frequency,PeriodicOnly)
30261541Stanimura	  CONTROLLER_T *CtlP; Ptr to controller structure
30361541Stanimura	  CONTROLLER_T *MudbacCtlP; Ptr to Mudbac controller structure
30461541Stanimura	  int AiopNum; Number of Aiops
30561541Stanimura	  int IRQNum; Interrupt Request number.  Can be any of the following:
30661541Stanimura			 0: Disable global interrupts
30761541Stanimura			 3: IRQ 3
30861541Stanimura			 4: IRQ 4
30961541Stanimura			 5: IRQ 5
31061541Stanimura			 9: IRQ 9
31161541Stanimura			 10: IRQ 10
31261541Stanimura			 11: IRQ 11
31361541Stanimura			 12: IRQ 12
31461541Stanimura			 15: IRQ 15
31561541Stanimura	  Byte_t Frequency: A flag identifying the frequency
31661541Stanimura		   of the periodic interrupt, can be any one of the following:
31761541Stanimura		      FREQ_DIS - periodic interrupt disabled
31861541Stanimura		      FREQ_137HZ - 137 Hertz
31961541Stanimura		      FREQ_69HZ - 69 Hertz
32061541Stanimura		      FREQ_34HZ - 34 Hertz
32161541Stanimura		      FREQ_17HZ - 17 Hertz
32261541Stanimura		      FREQ_9HZ - 9 Hertz
32361541Stanimura		      FREQ_4HZ - 4 Hertz
32461541Stanimura		   If IRQNum is set to 0 the Frequency parameter is
32561541Stanimura		   overidden, it is forced to a value of FREQ_DIS.
32661541Stanimura	  int PeriodicOnly: TRUE if all interrupts except the periodic
32761541Stanimura			       interrupt are to be blocked.
32861541Stanimura			    FALSE is both the periodic interrupt and
32961541Stanimura			       other channel interrupts are allowed.
33061541Stanimura			    If IRQNum is set to 0 the PeriodicOnly parameter is
33161541Stanimura			       overidden, it is forced to a value of FALSE.
33261541StanimuraReturn:   int: Number of AIOPs on the controller, or CTLID_NULL if controller
33361541Stanimura	       initialization failed.
33461541Stanimura
33561541StanimuraComments:
33661541Stanimura	  If periodic interrupts are to be disabled but AIOP interrupts
33761541Stanimura	  are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE.
33861541Stanimura
33961541Stanimura	  If interrupts are to be completely disabled set IRQNum to 0.
34061541Stanimura
34161541Stanimura	  Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
34261541Stanimura	  invalid combination.
34361541Stanimura
34461541Stanimura	  This function performs initialization of global interrupt modes,
34561541Stanimura	  but it does not actually enable global interrupts.  To enable
34661541Stanimura	  and disable global interrupts use functions sEnGlobalInt() and
34761541Stanimura	  sDisGlobalInt().  Enabling of global interrupts is normally not
34861541Stanimura	  done until all other initializations are complete.
34961541Stanimura
35061541Stanimura	  Even if interrupts are globally enabled, they must also be
35161541Stanimura	  individually enabled for each channel that is to generate
35261541Stanimura	  interrupts.
35361541Stanimura
35461541StanimuraWarnings: No range checking on any of the parameters is done.
35561541Stanimura
35661541Stanimura	  No context switches are allowed while executing this function.
35761541Stanimura
35861541Stanimura	  After this function all AIOPs on the controller are disabled,
35961541Stanimura	  they can be enabled with sEnAiop().
36061541Stanimura*/
36161541Stanimurastatic int
36261541StanimurasInitController(	CONTROLLER_T *CtlP,
36361541Stanimura			CONTROLLER_T *MudbacCtlP,
36461541Stanimura			int AiopNum,
36561541Stanimura			int IRQNum,
36661541Stanimura			Byte_t Frequency,
36761541Stanimura			int PeriodicOnly)
36861541Stanimura{
36961541Stanimura	int		i;
37061541Stanimura	int		ctl_base, aiop_base, aiop_size;
37161541Stanimura
37261541Stanimura	CtlP->CtlID = CTLID_0001;		/* controller release 1 */
37361541Stanimura
37461541Stanimura	ISACTL(CtlP)->MBaseIO = rp_nisadevs;
37561541Stanimura	if (MudbacCtlP->io[ISACTL(CtlP)->MBaseIO] != NULL) {
37661541Stanimura		ISACTL(CtlP)->MReg0IO = 0x40 + 0;
37761541Stanimura		ISACTL(CtlP)->MReg1IO = 0x40 + 1;
37861541Stanimura		ISACTL(CtlP)->MReg2IO = 0x40 + 2;
37961541Stanimura		ISACTL(CtlP)->MReg3IO = 0x40 + 3;
38061541Stanimura	} else {
38161541Stanimura		MudbacCtlP->io_rid[ISACTL(CtlP)->MBaseIO] = ISACTL(CtlP)->MBaseIO;
38261541Stanimura		ctl_base = rman_get_start(MudbacCtlP->io[0]) + 0x40 + 0x400 * rp_nisadevs;
38361541Stanimura		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);
38461541Stanimura		ISACTL(CtlP)->MReg0IO = 0;
38561541Stanimura		ISACTL(CtlP)->MReg1IO = 1;
38661541Stanimura		ISACTL(CtlP)->MReg2IO = 2;
38761541Stanimura		ISACTL(CtlP)->MReg3IO = 3;
38861541Stanimura	}
38961541Stanimura#if 1
39061541Stanimura	ISACTL(CtlP)->MReg2 = 0;			/* interrupt disable */
39161541Stanimura	ISACTL(CtlP)->MReg3 = 0;			/* no periodic interrupts */
39261541Stanimura#else
39361541Stanimura	if(sIRQMap[IRQNum] == 0)		/* interrupts globally disabled */
39461541Stanimura	{
39561541Stanimura		ISACTL(CtlP)->MReg2 = 0;		/* interrupt disable */
39661541Stanimura		ISACTL(CtlP)->MReg3 = 0;		/* no periodic interrupts */
39761541Stanimura	}
39861541Stanimura	else
39961541Stanimura	{
40061541Stanimura		ISACTL(CtlP)->MReg2 = sIRQMap[IRQNum];	/* set IRQ number */
40161541Stanimura		ISACTL(CtlP)->MReg3 = Frequency;	/* set frequency */
40261541Stanimura		if(PeriodicOnly)		/* periodic interrupt only */
40361541Stanimura		{
40461541Stanimura			ISACTL(CtlP)->MReg3 |= PERIODIC_ONLY;
40561541Stanimura		}
40661541Stanimura	}
40761541Stanimura#endif
40861541Stanimura	rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg2IO,ISACTL(CtlP)->MReg2);
40961541Stanimura	rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg3IO,ISACTL(CtlP)->MReg3);
41061541Stanimura	sControllerEOI(MudbacCtlP,CtlP);			/* clear EOI if warm init */
41161541Stanimura
41261541Stanimura	/* Init AIOPs */
41361541Stanimura	CtlP->NumAiop = 0;
41461541Stanimura	for(i=0; i < AiopNum; i++)
41561541Stanimura	{
41661541Stanimura		if (CtlP->io[i] == NULL) {
41761541Stanimura			CtlP->io_rid[i] = i;
41861541Stanimura			aiop_base = rman_get_start(CtlP->io[0]) + 0x400 * i;
41961541Stanimura			if (rp_nisadevs == 0)
42061541Stanimura				aiop_size = 0x44;
42161541Stanimura			else
42261541Stanimura				aiop_size = 0x40;
42361541Stanimura			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);
42461541Stanimura		} else
42561541Stanimura			aiop_base = rman_get_start(CtlP->io[i]);
42661541Stanimura		rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,
42761541Stanimura			    ISACTL(CtlP)->MReg2IO,
42861541Stanimura			    ISACTL(CtlP)->MReg2 | (i & 0x03));	/* AIOP index */
42961541Stanimura		rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,
43061541Stanimura			    ISACTL(CtlP)->MReg0IO,
43161541Stanimura			    (Byte_t)(aiop_base >> 6));		/* set up AIOP I/O in MUDBAC */
43261541Stanimura		sEnAiop(MudbacCtlP,CtlP,i);			/* enable the AIOP */
43361541Stanimura
43461541Stanimura		CtlP->AiopID[i] = sReadAiopID(CtlP, i);		/* read AIOP ID */
43561541Stanimura		if(CtlP->AiopID[i] == AIOPID_NULL)		/* if AIOP does not exist */
43661541Stanimura		{
43761541Stanimura			sDisAiop(MudbacCtlP,CtlP,i);		/* disable AIOP */
43861541Stanimura			bus_release_resource(CtlP->dev, SYS_RES_IOPORT, CtlP->io_rid[i], CtlP->io[i]);
43961541Stanimura			CtlP->io[i] = NULL;
44061541Stanimura			break;					/* done looking for AIOPs */
44161541Stanimura		}
44261541Stanimura
44361541Stanimura		CtlP->AiopNumChan[i] = sReadAiopNumChan(CtlP, i);	/* num channels in AIOP */
44461541Stanimura		rp_writeaiop2(CtlP,i,_INDX_ADDR,_CLK_PRE);	/* clock prescaler */
44561541Stanimura		rp_writeaiop1(CtlP,i,_INDX_DATA,CLOCK_PRESC);
44661541Stanimura		CtlP->NumAiop++;				/* bump count of AIOPs */
44761541Stanimura		sDisAiop(MudbacCtlP,CtlP,i);			/* disable AIOP */
44861541Stanimura	}
44961541Stanimura
45061541Stanimura	if(CtlP->NumAiop == 0)
45161541Stanimura		return(-1);
45261541Stanimura	else
45361541Stanimura		return(CtlP->NumAiop);
45461541Stanimura}
45561541Stanimura
45661541Stanimura/*
45761541Stanimura * ARGSUSED
45861541Stanimura * Maps (aiop, offset) to rid.
45961541Stanimura */
46061541Stanimurastatic int
46161541Stanimurarp_isa_aiop2rid(int aiop, int offset)
46261541Stanimura{
46361541Stanimura	/* rid equals to aiop for an ISA controller. */
46461541Stanimura	return aiop;
46561541Stanimura}
46661541Stanimura
46761541Stanimura/*
46861541Stanimura * ARGSUSED
46961541Stanimura * Maps (aiop, offset) to the offset of resource.
47061541Stanimura */
47161541Stanimurastatic int
47261541Stanimurarp_isa_aiop2off(int aiop, int offset)
47361541Stanimura{
47461541Stanimura	/* Each aiop has its own resource. */
47561541Stanimura	return offset;
47661541Stanimura}
47761541Stanimura
47861541Stanimura/* Read the int status for an ISA controller. */
47961541Stanimuraunsigned char
48061541Stanimurarp_isa_ctlmask(CONTROLLER_t *ctlp)
48161541Stanimura{
48261541Stanimura	return sGetControllerIntStatus(rp_controller,ctlp);
48361541Stanimura}
48461541Stanimura
48561541Stanimurastatic device_method_t rp_methods[] = {
48661541Stanimura	/* Device interface */
48761541Stanimura	DEVMETHOD(device_probe,		rp_probe),
48861541Stanimura	DEVMETHOD(device_attach,	rp_attach),
48961541Stanimura
49061541Stanimura	{ 0, 0 }
49161541Stanimura};
49261541Stanimura
49361541Stanimurastatic driver_t rp_driver = {
49461541Stanimura	"rp",
49561541Stanimura	rp_methods,
49661541Stanimura	sizeof(CONTROLLER_t),
49761541Stanimura};
49861541Stanimura
49961541Stanimura/*
50061541Stanimura * rp can be attached to an isa bus.
50161541Stanimura */
50261541StanimuraDRIVER_MODULE(rp, isa, rp_driver, rp_devclass, 0, 0);
503