1139749Simp/*-
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 */
3661541Stanimura
37119418Sobrien#include <sys/cdefs.h>
38119418Sobrien__FBSDID("$FreeBSD$");
39119418Sobrien
4061541Stanimura#include <sys/param.h>
4161541Stanimura#include <sys/systm.h>
4261541Stanimura#include <sys/fcntl.h>
4361541Stanimura#include <sys/malloc.h>
4461541Stanimura#include <sys/tty.h>
4561541Stanimura#include <sys/conf.h>
4661541Stanimura#include <sys/kernel.h>
47129879Sphk#include <sys/module.h>
4861541Stanimura#include <machine/resource.h>
4961541Stanimura#include <machine/bus.h>
5061541Stanimura#include <sys/bus.h>
5161541Stanimura#include <sys/rman.h>
5261541Stanimura
5361541Stanimura#define ROCKET_C
5461541Stanimura#include <dev/rp/rpreg.h>
5561541Stanimura#include <dev/rp/rpvar.h>
5661541Stanimura
5761541Stanimura#include <isa/isavar.h>
5861541Stanimura
5961541Stanimura/* ISA-specific part of CONTROLLER_t */
6061541Stanimurastruct ISACONTROLLER_T {
6161541Stanimura	int		MBaseIO;	/* rid of the Mudbac controller for this controller */
6261541Stanimura	int		MReg0IO;	/* offset0 of the Mudbac controller for this controller */
6361541Stanimura	int		MReg1IO;	/* offset1 of the Mudbac controller for this controller */
6461541Stanimura	int		MReg2IO;	/* offset2 of the Mudbac controller for this controller */
6561541Stanimura	int		MReg3IO;	/* offset3 of the Mudbac controller for this controller */
6661541Stanimura	Byte_t		MReg2;
6761541Stanimura	Byte_t		MReg3;
6861541Stanimura};
6961541Stanimuratypedef struct ISACONTROLLER_T ISACONTROLLER_t;
7061541Stanimura
7161541Stanimura#define ISACTL(ctlp) ((ISACONTROLLER_t *)((ctlp)->bus_ctlp))
7261541Stanimura
7361541Stanimura/***************************************************************************
7461541StanimuraFunction: sControllerEOI
7561541StanimuraPurpose:  Strobe the MUDBAC's End Of Interrupt bit.
7661541StanimuraCall:	  sControllerEOI(MudbacCtlP,CtlP)
7761541Stanimura	  CONTROLLER_T *MudbacCtlP; Ptr to Mudbac controller structure
7861541Stanimura	  CONTROLLER_T *CtlP; Ptr to controller structure
7961541Stanimura*/
8061541Stanimura#define sControllerEOI(MudbacCtlP,CtlP) \
8161541Stanimura	rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg2IO,ISACTL(CtlP)->MReg2 | INT_STROB)
8261541Stanimura
8361541Stanimura/***************************************************************************
8461541StanimuraFunction: sDisAiop
8561541StanimuraPurpose:  Disable I/O access to an AIOP
8661541StanimuraCall:	  sDisAiop(MudbacCtlP,CtlP)
8761541Stanimura	  CONTROLLER_T *MudbacCtlP; Ptr to Mudbac controller structure
8861541Stanimura	  CONTROLLER_T *CtlP; Ptr to controller structure
8961541Stanimura	  int AiopNum; Number of AIOP on controller
9061541Stanimura*/
9161541Stanimura#define sDisAiop(MudbacCtlP,CtlP,AIOPNUM) \
9261541Stanimura{ \
9361541Stanimura   ISACTL(CtlP)->MReg3 &= rp_sBitMapClrTbl[AIOPNUM]; \
9461541Stanimura   rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg3IO,ISACTL(CtlP)->MReg3); \
9561541Stanimura}
9661541Stanimura
9761541Stanimura/***************************************************************************
9861541StanimuraFunction: sEnAiop
9961541StanimuraPurpose:  Enable I/O access to an AIOP
10061541StanimuraCall:	  sEnAiop(MudbacCtlP,CtlP)
10161541Stanimura	  CONTROLLER_T *MudbacCtlP; Ptr to Mudbac controller structure
10261541Stanimura	  CONTROLLER_T *CtlP; Ptr to controller structure
10361541Stanimura	  int AiopNum; Number of AIOP on controller
10461541Stanimura*/
10561541Stanimura#define sEnAiop(MudbacCtlP,CtlP,AIOPNUM) \
10661541Stanimura{ \
10761541Stanimura   ISACTL(CtlP)->MReg3 |= rp_sBitMapSetTbl[AIOPNUM]; \
10861541Stanimura   rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg3IO,ISACTL(CtlP)->MReg3); \
10961541Stanimura}
11061541Stanimura
11161541Stanimura/***************************************************************************
11261541StanimuraFunction: sGetControllerIntStatus
11361541StanimuraPurpose:  Get the controller interrupt status
11461541StanimuraCall:	  sGetControllerIntStatus(MudbacCtlP,CtlP)
11561541Stanimura	  CONTROLLER_T *MudbacCtlP; Ptr to Mudbac controller structure
11661541Stanimura	  CONTROLLER_T *CtlP; Ptr to controller structure
11761541StanimuraReturn:   Byte_t: The controller interrupt status in the lower 4
11861541Stanimura			 bits.	Bits 0 through 3 represent AIOP's 0
11961541Stanimura			 through 3 respectively.  If a bit is set that
12061541Stanimura			 AIOP is interrupting.	Bits 4 through 7 will
12161541Stanimura			 always be cleared.
12261541Stanimura*/
12361541Stanimura#define sGetControllerIntStatus(MudbacCtlP,CtlP) \
12461541Stanimura	(rp_readio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg1IO) & 0x0f)
12561541Stanimura
12661541Stanimurastatic devclass_t rp_devclass;
12761541Stanimurastatic CONTROLLER_t *rp_controller;
12861541Stanimurastatic int rp_nisadevs;
12961541Stanimura
13061541Stanimurastatic int rp_probe(device_t dev);
13161541Stanimurastatic int rp_attach(device_t dev);
13261541Stanimurastatic void rp_isareleaseresource(CONTROLLER_t *ctlp);
13361541Stanimurastatic int sInitController(CONTROLLER_T *CtlP,
13461541Stanimura			   CONTROLLER_T *MudbacCtlP,
13561541Stanimura			   int AiopNum,
13661541Stanimura			   int IRQNum,
13761541Stanimura			   Byte_t Frequency,
13861541Stanimura			   int PeriodicOnly);
13961541Stanimurastatic rp_aiop2rid_t rp_isa_aiop2rid;
14061541Stanimurastatic rp_aiop2off_t rp_isa_aiop2off;
14161541Stanimurastatic rp_ctlmask_t rp_isa_ctlmask;
14261541Stanimura
14361541Stanimurastatic int
14461541Stanimurarp_probe(device_t dev)
14561541Stanimura{
14661541Stanimura	int unit;
14761541Stanimura	CONTROLLER_t *controller;
14861541Stanimura	int num_aiops;
14961541Stanimura	CONTROLLER_t *ctlp;
15061541Stanimura	int retval;
15161541Stanimura
15261541Stanimura	/*
15361541Stanimura	 * We have no PnP RocketPort cards.
15461541Stanimura	 * (At least according to LINT)
15561541Stanimura	 */
15661541Stanimura	if (isa_get_logicalid(dev) != 0)
15761541Stanimura		return (ENXIO);
15861541Stanimura
15961541Stanimura	/* We need IO port resource to configure an ISA device. */
16061541Stanimura	if (bus_get_resource_count(dev, SYS_RES_IOPORT, 0) == 0)
16161541Stanimura		return (ENXIO);
16261541Stanimura
16361541Stanimura	unit = device_get_unit(dev);
16461541Stanimura	if (unit >= 4) {
16561541Stanimura		device_printf(dev, "rpprobe: unit number %d invalid.\n", unit);
16661541Stanimura		return (ENXIO);
16761541Stanimura	}
16861541Stanimura	device_printf(dev, "probing for RocketPort(ISA) unit %d.\n", unit);
16961541Stanimura
17061541Stanimura	ctlp = device_get_softc(dev);
17161541Stanimura	bzero(ctlp, sizeof(*ctlp));
17261541Stanimura	ctlp->dev = dev;
17361541Stanimura	ctlp->aiop2rid = rp_isa_aiop2rid;
17461541Stanimura	ctlp->aiop2off = rp_isa_aiop2off;
17561541Stanimura	ctlp->ctlmask = rp_isa_ctlmask;
17661541Stanimura
17761541Stanimura	/* The IO ports of AIOPs for an ISA controller are discrete. */
17861541Stanimura	ctlp->io_num = 1;
17969781Sdwmalone	ctlp->io_rid = malloc(sizeof(*(ctlp->io_rid)) * MAX_AIOPS_PER_BOARD, M_DEVBUF, M_NOWAIT | M_ZERO);
18069781Sdwmalone	ctlp->io = malloc(sizeof(*(ctlp->io)) * MAX_AIOPS_PER_BOARD, M_DEVBUF, M_NOWAIT | M_ZERO);
18161541Stanimura	if (ctlp->io_rid == NULL || ctlp->io == NULL) {
18261541Stanimura		device_printf(dev, "rp_attach: Out of memory.\n");
18361541Stanimura		retval = ENOMEM;
18461541Stanimura		goto nogo;
18561541Stanimura	}
18661541Stanimura
18769781Sdwmalone	ctlp->bus_ctlp = malloc(sizeof(ISACONTROLLER_t) * 1, M_DEVBUF, M_NOWAIT | M_ZERO);
18861541Stanimura	if (ctlp->bus_ctlp == NULL) {
18961541Stanimura		device_printf(dev, "rp_attach: Out of memory.\n");
19061541Stanimura		retval = ENOMEM;
19161541Stanimura		goto nogo;
19261541Stanimura	}
19361541Stanimura
19461541Stanimura	ctlp->io_rid[0] = 0;
19561541Stanimura	if (rp_controller != NULL) {
19661541Stanimura		controller = rp_controller;
19761541Stanimura		ctlp->io[0] = bus_alloc_resource(dev, SYS_RES_IOPORT, &ctlp->io_rid[0], 0, ~0, 0x40, RF_ACTIVE);
19861541Stanimura	} else {
19961541Stanimura		controller = rp_controller = ctlp;
20061541Stanimura		ctlp->io[0] = bus_alloc_resource(dev, SYS_RES_IOPORT, &ctlp->io_rid[0], 0, ~0, 0x44, RF_ACTIVE);
20161541Stanimura	}
20261541Stanimura	if (ctlp->io[0] == NULL) {
20361541Stanimura		device_printf(dev, "rp_attach: Resource not available.\n");
20461541Stanimura		retval = ENXIO;
20561541Stanimura		goto nogo;
20661541Stanimura	}
20761541Stanimura
20861541Stanimura	num_aiops = sInitController(ctlp,
20961541Stanimura				controller,
21061541Stanimura				MAX_AIOPS_PER_BOARD, 0,
21161541Stanimura				FREQ_DIS, 0);
21261541Stanimura	if (num_aiops <= 0) {
21361541Stanimura		device_printf(dev, "board%d init failed.\n", unit);
21461541Stanimura		retval = ENXIO;
21561541Stanimura		goto nogo;
21661541Stanimura	}
21761541Stanimura
21861541Stanimura	if (rp_controller == NULL)
21961541Stanimura		rp_controller = controller;
22061541Stanimura	rp_nisadevs++;
22161541Stanimura
22261541Stanimura	device_set_desc(dev, "RocketPort ISA");
22361541Stanimura
22461541Stanimura	return (0);
22561541Stanimura
22661541Stanimuranogo:
22761541Stanimura	rp_isareleaseresource(ctlp);
22861541Stanimura
22961541Stanimura	return (retval);
23061541Stanimura}
23161541Stanimura
23261541Stanimurastatic int
23361541Stanimurarp_attach(device_t dev)
23461541Stanimura{
23561541Stanimura	int	unit;
23661541Stanimura	int	num_ports, num_aiops;
23761541Stanimura	int	aiop;
23861541Stanimura	CONTROLLER_t	*ctlp;
23961541Stanimura	int	retval;
24061541Stanimura
24161541Stanimura	unit = device_get_unit(dev);
24261541Stanimura
24361541Stanimura	ctlp = device_get_softc(dev);
24461541Stanimura
245153084Sru#ifdef notdef
24661541Stanimura	num_aiops = sInitController(ctlp,
24761541Stanimura				rp_controller,
24861541Stanimura				MAX_AIOPS_PER_BOARD, 0,
24961541Stanimura				FREQ_DIS, 0);
25061541Stanimura#else
25161541Stanimura	num_aiops = ctlp->NumAiop;
25261541Stanimura#endif /* notdef */
25361541Stanimura
25461541Stanimura	num_ports = 0;
25561541Stanimura	for(aiop=0; aiop < num_aiops; aiop++) {
25661541Stanimura		sResetAiopByNum(ctlp, aiop);
25761541Stanimura		sEnAiop(rp_controller, ctlp, aiop);
25861541Stanimura		num_ports += sGetAiopNumChan(ctlp, aiop);
25961541Stanimura	}
26061541Stanimura
26161541Stanimura	retval = rp_attachcommon(ctlp, num_aiops, num_ports);
26261541Stanimura	if (retval != 0)
26361541Stanimura		goto nogo;
26461541Stanimura
26561541Stanimura	return (0);
26661541Stanimura
26761541Stanimuranogo:
26861541Stanimura	rp_isareleaseresource(ctlp);
26961541Stanimura
27061541Stanimura	return (retval);
27161541Stanimura}
27261541Stanimura
27361541Stanimurastatic void
27461541Stanimurarp_isareleaseresource(CONTROLLER_t *ctlp)
27561541Stanimura{
27661541Stanimura	int i;
27761541Stanimura
27861541Stanimura	rp_releaseresource(ctlp);
27961541Stanimura
28061541Stanimura	if (ctlp == rp_controller)
28161541Stanimura		rp_controller = NULL;
28261541Stanimura	if (ctlp->io != NULL) {
28361541Stanimura		for (i = 0 ; i < MAX_AIOPS_PER_BOARD ; i++)
28461541Stanimura			if (ctlp->io[i] != NULL)
28561541Stanimura				bus_release_resource(ctlp->dev, SYS_RES_IOPORT, ctlp->io_rid[i], ctlp->io[i]);
28661541Stanimura		free(ctlp->io, M_DEVBUF);
28761541Stanimura	}
28861541Stanimura	if (ctlp->io_rid != NULL)
28961541Stanimura		free(ctlp->io_rid, M_DEVBUF);
29061541Stanimura	if (rp_controller != NULL && rp_controller->io[ISACTL(ctlp)->MBaseIO] != NULL) {
29161541Stanimura		bus_release_resource(rp_controller->dev, SYS_RES_IOPORT, rp_controller->io_rid[ISACTL(ctlp)->MBaseIO], rp_controller->io[ISACTL(ctlp)->MBaseIO]);
29261541Stanimura		rp_controller->io[ISACTL(ctlp)->MBaseIO] = NULL;
29361541Stanimura		rp_controller->io_rid[ISACTL(ctlp)->MBaseIO] = 0;
29461541Stanimura	}
29561541Stanimura	if (ctlp->bus_ctlp != NULL)
29661541Stanimura		free(ctlp->bus_ctlp, M_DEVBUF);
29761541Stanimura}
29861541Stanimura
29961541Stanimura/***************************************************************************
30061541StanimuraFunction: sInitController
30161541StanimuraPurpose:  Initialization of controller global registers and controller
30261541Stanimura	  structure.
30361541StanimuraCall:	  sInitController(CtlP,MudbacCtlP,AiopNum,
30461541Stanimura			  IRQNum,Frequency,PeriodicOnly)
30561541Stanimura	  CONTROLLER_T *CtlP; Ptr to controller structure
30661541Stanimura	  CONTROLLER_T *MudbacCtlP; Ptr to Mudbac controller structure
30761541Stanimura	  int AiopNum; Number of Aiops
30861541Stanimura	  int IRQNum; Interrupt Request number.  Can be any of the following:
30961541Stanimura			 0: Disable global interrupts
31061541Stanimura			 3: IRQ 3
31161541Stanimura			 4: IRQ 4
31261541Stanimura			 5: IRQ 5
31361541Stanimura			 9: IRQ 9
31461541Stanimura			 10: IRQ 10
31561541Stanimura			 11: IRQ 11
31661541Stanimura			 12: IRQ 12
31761541Stanimura			 15: IRQ 15
31861541Stanimura	  Byte_t Frequency: A flag identifying the frequency
31961541Stanimura		   of the periodic interrupt, can be any one of the following:
32061541Stanimura		      FREQ_DIS - periodic interrupt disabled
32161541Stanimura		      FREQ_137HZ - 137 Hertz
32261541Stanimura		      FREQ_69HZ - 69 Hertz
32361541Stanimura		      FREQ_34HZ - 34 Hertz
32461541Stanimura		      FREQ_17HZ - 17 Hertz
32561541Stanimura		      FREQ_9HZ - 9 Hertz
32661541Stanimura		      FREQ_4HZ - 4 Hertz
32761541Stanimura		   If IRQNum is set to 0 the Frequency parameter is
32861541Stanimura		   overidden, it is forced to a value of FREQ_DIS.
32961541Stanimura	  int PeriodicOnly: TRUE if all interrupts except the periodic
33061541Stanimura			       interrupt are to be blocked.
33161541Stanimura			    FALSE is both the periodic interrupt and
33261541Stanimura			       other channel interrupts are allowed.
33361541Stanimura			    If IRQNum is set to 0 the PeriodicOnly parameter is
33461541Stanimura			       overidden, it is forced to a value of FALSE.
33561541StanimuraReturn:   int: Number of AIOPs on the controller, or CTLID_NULL if controller
33661541Stanimura	       initialization failed.
33761541Stanimura
33861541StanimuraComments:
33961541Stanimura	  If periodic interrupts are to be disabled but AIOP interrupts
34061541Stanimura	  are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE.
34161541Stanimura
34261541Stanimura	  If interrupts are to be completely disabled set IRQNum to 0.
34361541Stanimura
34461541Stanimura	  Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
34561541Stanimura	  invalid combination.
34661541Stanimura
34761541Stanimura	  This function performs initialization of global interrupt modes,
34861541Stanimura	  but it does not actually enable global interrupts.  To enable
34961541Stanimura	  and disable global interrupts use functions sEnGlobalInt() and
35061541Stanimura	  sDisGlobalInt().  Enabling of global interrupts is normally not
35161541Stanimura	  done until all other initializations are complete.
35261541Stanimura
35361541Stanimura	  Even if interrupts are globally enabled, they must also be
35461541Stanimura	  individually enabled for each channel that is to generate
35561541Stanimura	  interrupts.
35661541Stanimura
35761541StanimuraWarnings: No range checking on any of the parameters is done.
35861541Stanimura
35961541Stanimura	  No context switches are allowed while executing this function.
36061541Stanimura
36161541Stanimura	  After this function all AIOPs on the controller are disabled,
36261541Stanimura	  they can be enabled with sEnAiop().
36361541Stanimura*/
36461541Stanimurastatic int
36561541StanimurasInitController(	CONTROLLER_T *CtlP,
36661541Stanimura			CONTROLLER_T *MudbacCtlP,
36761541Stanimura			int AiopNum,
36861541Stanimura			int IRQNum,
36961541Stanimura			Byte_t Frequency,
37061541Stanimura			int PeriodicOnly)
37161541Stanimura{
37261541Stanimura	int		i;
37361541Stanimura	int		ctl_base, aiop_base, aiop_size;
37461541Stanimura
37561541Stanimura	CtlP->CtlID = CTLID_0001;		/* controller release 1 */
37661541Stanimura
37761541Stanimura	ISACTL(CtlP)->MBaseIO = rp_nisadevs;
37861541Stanimura	if (MudbacCtlP->io[ISACTL(CtlP)->MBaseIO] != NULL) {
37961541Stanimura		ISACTL(CtlP)->MReg0IO = 0x40 + 0;
38061541Stanimura		ISACTL(CtlP)->MReg1IO = 0x40 + 1;
38161541Stanimura		ISACTL(CtlP)->MReg2IO = 0x40 + 2;
38261541Stanimura		ISACTL(CtlP)->MReg3IO = 0x40 + 3;
38361541Stanimura	} else {
38461541Stanimura		MudbacCtlP->io_rid[ISACTL(CtlP)->MBaseIO] = ISACTL(CtlP)->MBaseIO;
38561541Stanimura		ctl_base = rman_get_start(MudbacCtlP->io[0]) + 0x40 + 0x400 * rp_nisadevs;
38661541Stanimura		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);
38761541Stanimura		ISACTL(CtlP)->MReg0IO = 0;
38861541Stanimura		ISACTL(CtlP)->MReg1IO = 1;
38961541Stanimura		ISACTL(CtlP)->MReg2IO = 2;
39061541Stanimura		ISACTL(CtlP)->MReg3IO = 3;
39161541Stanimura	}
39261541Stanimura#if 1
39361541Stanimura	ISACTL(CtlP)->MReg2 = 0;			/* interrupt disable */
39461541Stanimura	ISACTL(CtlP)->MReg3 = 0;			/* no periodic interrupts */
39561541Stanimura#else
39661541Stanimura	if(sIRQMap[IRQNum] == 0)		/* interrupts globally disabled */
39761541Stanimura	{
39861541Stanimura		ISACTL(CtlP)->MReg2 = 0;		/* interrupt disable */
39961541Stanimura		ISACTL(CtlP)->MReg3 = 0;		/* no periodic interrupts */
40061541Stanimura	}
40161541Stanimura	else
40261541Stanimura	{
40361541Stanimura		ISACTL(CtlP)->MReg2 = sIRQMap[IRQNum];	/* set IRQ number */
40461541Stanimura		ISACTL(CtlP)->MReg3 = Frequency;	/* set frequency */
40561541Stanimura		if(PeriodicOnly)		/* periodic interrupt only */
40661541Stanimura		{
40761541Stanimura			ISACTL(CtlP)->MReg3 |= PERIODIC_ONLY;
40861541Stanimura		}
40961541Stanimura	}
41061541Stanimura#endif
41161541Stanimura	rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg2IO,ISACTL(CtlP)->MReg2);
41261541Stanimura	rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg3IO,ISACTL(CtlP)->MReg3);
41361541Stanimura	sControllerEOI(MudbacCtlP,CtlP);			/* clear EOI if warm init */
41461541Stanimura
41561541Stanimura	/* Init AIOPs */
41661541Stanimura	CtlP->NumAiop = 0;
41761541Stanimura	for(i=0; i < AiopNum; i++)
41861541Stanimura	{
41961541Stanimura		if (CtlP->io[i] == NULL) {
42061541Stanimura			CtlP->io_rid[i] = i;
42161541Stanimura			aiop_base = rman_get_start(CtlP->io[0]) + 0x400 * i;
42261541Stanimura			if (rp_nisadevs == 0)
42361541Stanimura				aiop_size = 0x44;
42461541Stanimura			else
42561541Stanimura				aiop_size = 0x40;
42661541Stanimura			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);
42761541Stanimura		} else
42861541Stanimura			aiop_base = rman_get_start(CtlP->io[i]);
42961541Stanimura		rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,
43061541Stanimura			    ISACTL(CtlP)->MReg2IO,
43161541Stanimura			    ISACTL(CtlP)->MReg2 | (i & 0x03));	/* AIOP index */
43261541Stanimura		rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,
43361541Stanimura			    ISACTL(CtlP)->MReg0IO,
43461541Stanimura			    (Byte_t)(aiop_base >> 6));		/* set up AIOP I/O in MUDBAC */
43561541Stanimura		sEnAiop(MudbacCtlP,CtlP,i);			/* enable the AIOP */
43661541Stanimura
43761541Stanimura		CtlP->AiopID[i] = sReadAiopID(CtlP, i);		/* read AIOP ID */
43861541Stanimura		if(CtlP->AiopID[i] == AIOPID_NULL)		/* if AIOP does not exist */
43961541Stanimura		{
44061541Stanimura			sDisAiop(MudbacCtlP,CtlP,i);		/* disable AIOP */
44161541Stanimura			bus_release_resource(CtlP->dev, SYS_RES_IOPORT, CtlP->io_rid[i], CtlP->io[i]);
44261541Stanimura			CtlP->io[i] = NULL;
44361541Stanimura			break;					/* done looking for AIOPs */
44461541Stanimura		}
44561541Stanimura
44661541Stanimura		CtlP->AiopNumChan[i] = sReadAiopNumChan(CtlP, i);	/* num channels in AIOP */
44761541Stanimura		rp_writeaiop2(CtlP,i,_INDX_ADDR,_CLK_PRE);	/* clock prescaler */
44861541Stanimura		rp_writeaiop1(CtlP,i,_INDX_DATA,CLOCK_PRESC);
44961541Stanimura		CtlP->NumAiop++;				/* bump count of AIOPs */
45061541Stanimura		sDisAiop(MudbacCtlP,CtlP,i);			/* disable AIOP */
45161541Stanimura	}
45261541Stanimura
45361541Stanimura	if(CtlP->NumAiop == 0)
45461541Stanimura		return(-1);
45561541Stanimura	else
45661541Stanimura		return(CtlP->NumAiop);
45761541Stanimura}
45861541Stanimura
45961541Stanimura/*
46061541Stanimura * ARGSUSED
46161541Stanimura * Maps (aiop, offset) to rid.
46261541Stanimura */
46361541Stanimurastatic int
46461541Stanimurarp_isa_aiop2rid(int aiop, int offset)
46561541Stanimura{
46661541Stanimura	/* rid equals to aiop for an ISA controller. */
46761541Stanimura	return aiop;
46861541Stanimura}
46961541Stanimura
47061541Stanimura/*
47161541Stanimura * ARGSUSED
47261541Stanimura * Maps (aiop, offset) to the offset of resource.
47361541Stanimura */
47461541Stanimurastatic int
47561541Stanimurarp_isa_aiop2off(int aiop, int offset)
47661541Stanimura{
47761541Stanimura	/* Each aiop has its own resource. */
47861541Stanimura	return offset;
47961541Stanimura}
48061541Stanimura
48161541Stanimura/* Read the int status for an ISA controller. */
482105215Sphkstatic unsigned char
48361541Stanimurarp_isa_ctlmask(CONTROLLER_t *ctlp)
48461541Stanimura{
48561541Stanimura	return sGetControllerIntStatus(rp_controller,ctlp);
48661541Stanimura}
48761541Stanimura
48861541Stanimurastatic device_method_t rp_methods[] = {
48961541Stanimura	/* Device interface */
49061541Stanimura	DEVMETHOD(device_probe,		rp_probe),
49161541Stanimura	DEVMETHOD(device_attach,	rp_attach),
49261541Stanimura
49361541Stanimura	{ 0, 0 }
49461541Stanimura};
49561541Stanimura
49661541Stanimurastatic driver_t rp_driver = {
49761541Stanimura	"rp",
49861541Stanimura	rp_methods,
49961541Stanimura	sizeof(CONTROLLER_t),
50061541Stanimura};
50161541Stanimura
50261541Stanimura/*
50361541Stanimura * rp can be attached to an isa bus.
50461541Stanimura */
50561541StanimuraDRIVER_MODULE(rp, isa, rp_driver, rp_devclass, 0, 0);
506