xref: /netbsd-src/sys/arch/atari/isa/isa_hades.c (revision 2a84159ada57dac1a3a322c289d36b976db1a473)
1*2a84159aStsutsui /*	$NetBSD: isa_hades.c,v 1.10 2023/01/06 10:28:28 tsutsui Exp $	*/
2164b0454Sleo 
3164b0454Sleo /*-
4164b0454Sleo  * Copyright (c) 2001 The NetBSD Foundation, Inc.
5164b0454Sleo  * All rights reserved.
6164b0454Sleo  *
7164b0454Sleo  * This code is derived from software contributed to The NetBSD Foundation
8164b0454Sleo  * by Leo Weppelman.
9164b0454Sleo  *
10164b0454Sleo  * Redistribution and use in source and binary forms, with or without
11164b0454Sleo  * modification, are permitted provided that the following conditions
12164b0454Sleo  * are met:
13164b0454Sleo  * 1. Redistributions of source code must retain the above copyright
14164b0454Sleo  *    notice, this list of conditions and the following disclaimer.
15164b0454Sleo  * 2. Redistributions in binary form must reproduce the above copyright
16164b0454Sleo  *    notice, this list of conditions and the following disclaimer in the
17164b0454Sleo  *    documentation and/or other materials provided with the distribution.
18164b0454Sleo  *
19164b0454Sleo  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20164b0454Sleo  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21164b0454Sleo  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22164b0454Sleo  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23164b0454Sleo  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24164b0454Sleo  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25164b0454Sleo  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26164b0454Sleo  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27164b0454Sleo  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28164b0454Sleo  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29164b0454Sleo  * POSSIBILITY OF SUCH DAMAGE.
30164b0454Sleo  */
31164b0454Sleo 
32e803bea7Slukem #include <sys/cdefs.h>
33*2a84159aStsutsui __KERNEL_RCSID(0, "$NetBSD: isa_hades.c,v 1.10 2023/01/06 10:28:28 tsutsui Exp $");
34e803bea7Slukem 
35164b0454Sleo #include <sys/types.h>
36164b0454Sleo #include <sys/param.h>
37164b0454Sleo #include <sys/systm.h>
38164b0454Sleo #include <sys/device.h>
39164b0454Sleo 
40164b0454Sleo #include <dev/isa/isavar.h>
41164b0454Sleo #include <dev/isa/isareg.h>
42164b0454Sleo 
43164b0454Sleo #include <m68k/asm_single.h>
44164b0454Sleo 
45164b0454Sleo #include <machine/iomap.h>
46164b0454Sleo #include <machine/mfp.h>
47164b0454Sleo 
48164b0454Sleo void	isa_bus_init(void);
49164b0454Sleo 
50164b0454Sleo void
isa_bus_init(void)51df7f595eScegger isa_bus_init(void)
52164b0454Sleo {
53164b0454Sleo }
54164b0454Sleo 
55164b0454Sleo /*
56164b0454Sleo  * The interrupt stuff is rather ugly. On the Hades, all interrupt lines
57164b0454Sleo  * for a slot are wired together and connected to either IO3 (slot1) or
58164b0454Sleo  * IO7 (slot2). Since no info can be obtained about the slot position
59164b0454Sleo  * at isa_intr_establish() time, the following assumption is made:
60164b0454Sleo  *   - irq <= 6 -> slot 1
61164b0454Sleo  *   - irq >  6 -> slot 2
62164b0454Sleo  */
63164b0454Sleo 
64164b0454Sleo #define	SLOTNR(irq)	((irq <= 6) ? 0 : 1)
65164b0454Sleo 
66164b0454Sleo static isa_intr_info_t iinfo[2] = { { -1 }, { -1 } };
67164b0454Sleo 
6802cdf4d2Sdsl static int	iifun(int, int);
69164b0454Sleo 
70164b0454Sleo static int
iifun(int slot,int sr)71454af1c0Sdsl iifun(int slot, int sr)
72164b0454Sleo {
73164b0454Sleo 	isa_intr_info_t *iinfo_p;
74164b0454Sleo 	int		s;
75164b0454Sleo 
76164b0454Sleo 	iinfo_p = &iinfo[slot];
77164b0454Sleo 
78164b0454Sleo 	/*
79164b0454Sleo 	 * Disable the interrupts
80164b0454Sleo 	 */
81164b0454Sleo 	if (slot == 0) {
82164b0454Sleo 		single_inst_bclr_b(MFP->mf_imrb, IB_ISA1);
83164b0454Sleo 	}
84164b0454Sleo 	else {
85164b0454Sleo 		single_inst_bclr_b(MFP->mf_imra, IA_ISA2);
86164b0454Sleo 	}
87164b0454Sleo 
88164b0454Sleo 	if ((sr & PSL_IPL) >= (iinfo_p->ipl & PSL_IPL)) {
89164b0454Sleo 		/*
90164b0454Sleo 		 * We're running at a too high priority now.
91164b0454Sleo 		 */
92164b0454Sleo 		add_sicallback((si_farg)iifun, (void*)slot, 0);
93164b0454Sleo 	}
94164b0454Sleo 	else {
95164b0454Sleo 		s = splx(iinfo_p->ipl);
96164b0454Sleo 		if (slot == 0) {
97164b0454Sleo 			do {
98164b0454Sleo 				MFP->mf_iprb = (u_int8_t)~IB_ISA1;
99164b0454Sleo 				(void) (iinfo_p->ifunc)(iinfo_p->iarg);
100164b0454Sleo 			} while (MFP->mf_iprb & IB_ISA1);
101164b0454Sleo 			single_inst_bset_b(MFP->mf_imrb, IB_ISA1);
102164b0454Sleo 		}
103164b0454Sleo 		else {
104164b0454Sleo 			do {
105164b0454Sleo 				MFP->mf_ipra = (u_int8_t)~IA_ISA2;
106164b0454Sleo 				(void) (iinfo_p->ifunc)(iinfo_p->iarg);
107164b0454Sleo 			} while (MFP->mf_ipra & IA_ISA2);
108164b0454Sleo 			single_inst_bset_b(MFP->mf_imra, IA_ISA2);
109164b0454Sleo 		}
110164b0454Sleo 		splx(s);
111164b0454Sleo 	}
112164b0454Sleo 	return 1;
113164b0454Sleo }
114164b0454Sleo 
115164b0454Sleo 
116164b0454Sleo /*
117164b0454Sleo  * XXXX
118164b0454Sleo  * XXXX Note that this function is not really working yet! The big problem is
119164b0454Sleo  * XXXX to only generate interrupts for the slot the card is in...
120164b0454Sleo  */
121164b0454Sleo int
isa_intr_alloc(isa_chipset_tag_t ic,int mask,int type,int * irq)122454af1c0Sdsl isa_intr_alloc(isa_chipset_tag_t ic, int mask, int type, int *irq)
123164b0454Sleo {
124164b0454Sleo 	isa_intr_info_t *iinfo_p;
125164b0454Sleo 	int		slot, i;
126164b0454Sleo 
127164b0454Sleo 
128164b0454Sleo 	/*
129164b0454Sleo 	 * The Hades only supports edge triggered interrupts!
130164b0454Sleo 	 */
131164b0454Sleo 	if (type != IST_EDGE)
132164b0454Sleo 		return 1;
133164b0454Sleo 
134164b0454Sleo #define	MAXIRQ		10	/* XXX: Pure fiction	*/
135164b0454Sleo 	for (i = 0; i < MAXIRQ; i++) {
136164b0454Sleo 		if (mask & (1<<i)) {
137164b0454Sleo 		    slot    = SLOTNR(i);
138164b0454Sleo 		    iinfo_p = &iinfo[slot];
139164b0454Sleo 
140164b0454Sleo 		    if (iinfo_p->slot < 0) {
141164b0454Sleo 			*irq = i;
142164b0454Sleo 			printf("WARNING: isa_intr_alloc is not yet ready!\n"
143164b0454Sleo 			       "         make sure the card is in slot %d!\n",
144164b0454Sleo 				slot);
145164b0454Sleo 			return 0;
146164b0454Sleo 		    }
147164b0454Sleo 		}
148164b0454Sleo 	}
149164b0454Sleo 	return (1);
150164b0454Sleo }
151164b0454Sleo void *
isa_intr_establish(isa_chipset_tag_t ic,int irq,int type,int level,int (* ih_fun)(void *),void * ih_arg)1527cc9af7dSdsl isa_intr_establish(isa_chipset_tag_t ic, int irq, int type, int level, int (*ih_fun)(void *), void *ih_arg)
153164b0454Sleo {
154164b0454Sleo 	isa_intr_info_t *iinfo_p;
155164b0454Sleo 	struct intrhand	*ihand;
156164b0454Sleo 	int		slot;
157164b0454Sleo 
158164b0454Sleo 	/*
159164b0454Sleo 	 * The Hades only supports edge triggered interrupts!
160164b0454Sleo 	 */
161164b0454Sleo 	if (type != IST_EDGE)
162164b0454Sleo 		return NULL;
163164b0454Sleo 
164164b0454Sleo 	slot    = SLOTNR(irq);
165164b0454Sleo 	iinfo_p = &iinfo[slot];
166164b0454Sleo 
167164b0454Sleo 	if (iinfo_p->slot >= 0)
1680f09ed48Sprovos 		panic("isa_intr_establish: interrupt was already established");
169164b0454Sleo 
170164b0454Sleo 	ihand = intr_establish((slot == 0) ? 3 : 15, USER_VEC, 0,
171164b0454Sleo 				(hw_ifun_t)iifun, (void *)slot);
172164b0454Sleo 	if (ihand != NULL) {
173164b0454Sleo 		iinfo_p->slot  = slot;
174164b0454Sleo 		iinfo_p->ipl   = level;
175164b0454Sleo 		iinfo_p->ifunc = ih_fun;
176164b0454Sleo 		iinfo_p->iarg  = ih_arg;
177164b0454Sleo 		iinfo_p->ihand = ihand;
178164b0454Sleo 
179164b0454Sleo 		/*
180164b0454Sleo 		 * Enable (unmask) the interrupt
181164b0454Sleo 		 */
182164b0454Sleo 		if (slot == 0) {
183164b0454Sleo 			single_inst_bset_b(MFP->mf_imrb, IB_ISA1);
184164b0454Sleo 			single_inst_bset_b(MFP->mf_ierb, IB_ISA1);
185164b0454Sleo 		}
186164b0454Sleo 		else {
187164b0454Sleo 			single_inst_bset_b(MFP->mf_imra, IA_ISA2);
188164b0454Sleo 			single_inst_bset_b(MFP->mf_iera, IA_ISA2);
189164b0454Sleo 		}
190164b0454Sleo 		return(iinfo_p);
191164b0454Sleo 	}
192164b0454Sleo 	return NULL;
193164b0454Sleo }
194164b0454Sleo 
195164b0454Sleo void
isa_intr_disestablish(isa_chipset_tag_t ic,void * handler)196454af1c0Sdsl isa_intr_disestablish(isa_chipset_tag_t ic, void *handler)
197164b0454Sleo {
198164b0454Sleo 	isa_intr_info_t *iinfo_p = (isa_intr_info_t *)handler;
199164b0454Sleo 
200164b0454Sleo 	if (iinfo_p->slot < 0)
2010f09ed48Sprovos 		panic("isa_intr_disestablish: interrupt was not established");
202164b0454Sleo 
203164b0454Sleo 	(void) intr_disestablish(iinfo_p->ihand);
204164b0454Sleo 	iinfo_p->slot = -1;
205164b0454Sleo }
206