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