i82365_isa.c revision 1.1.2.2 1 1.1.2.2 marc #define PCICISADEBUG
2 1.1.2.2 marc
3 1.1.2.1 marc #include <sys/types.h>
4 1.1.2.1 marc #include <sys/param.h>
5 1.1.2.1 marc #include <sys/systm.h>
6 1.1.2.1 marc #include <sys/device.h>
7 1.1.2.1 marc #include <sys/extent.h>
8 1.1.2.1 marc #include <sys/malloc.h>
9 1.1.2.1 marc
10 1.1.2.1 marc #include <vm/vm.h>
11 1.1.2.1 marc
12 1.1.2.1 marc #include <machine/bus.h>
13 1.1.2.1 marc #include <machine/intr.h>
14 1.1.2.1 marc
15 1.1.2.1 marc #include <dev/isa/isareg.h>
16 1.1.2.1 marc #include <dev/isa/isavar.h>
17 1.1.2.1 marc
18 1.1.2.1 marc #include <dev/pcmcia/pcmciareg.h>
19 1.1.2.1 marc #include <dev/pcmcia/pcmciavar.h>
20 1.1.2.1 marc #include <dev/pcmcia/pcmciachip.h>
21 1.1.2.1 marc
22 1.1.2.1 marc #include <dev/ic/i82365reg.h>
23 1.1.2.1 marc #include <dev/ic/i82365var.h>
24 1.1.2.1 marc
25 1.1.2.2 marc #ifdef PCICISADEBUG
26 1.1.2.2 marc int pcicisa_debug = 0 /* XXX */;
27 1.1.2.2 marc #define DPRINTF(arg) if (pcicisa_debug) printf arg;
28 1.1.2.2 marc #else
29 1.1.2.2 marc #define DPRINTF(arg)
30 1.1.2.2 marc #endif
31 1.1.2.2 marc
32 1.1.2.1 marc int pcic_isa_probe __P((struct device *, void *, void *));
33 1.1.2.1 marc void pcic_isa_attach __P((struct device *, struct device *, void *));
34 1.1.2.1 marc
35 1.1.2.1 marc void *pcic_isa_chip_intr_establish __P((pcmcia_chipset_handle_t,
36 1.1.2.1 marc struct pcmcia_function *, int,
37 1.1.2.1 marc int (*)(void *), void *));
38 1.1.2.1 marc void pcic_isa_chip_intr_disestablish __P((pcmcia_chipset_handle_t, void *));
39 1.1.2.1 marc
40 1.1.2.1 marc struct cfattach pcic_isa_ca = {
41 1.1.2.1 marc sizeof(struct pcic_softc), pcic_isa_probe, pcic_isa_attach
42 1.1.2.1 marc };
43 1.1.2.1 marc
44 1.1.2.1 marc static struct pcmcia_chip_functions pcic_isa_functions = {
45 1.1.2.1 marc pcic_chip_mem_alloc,
46 1.1.2.1 marc pcic_chip_mem_free,
47 1.1.2.1 marc pcic_chip_mem_map,
48 1.1.2.1 marc pcic_chip_mem_unmap,
49 1.1.2.1 marc
50 1.1.2.1 marc pcic_chip_io_alloc,
51 1.1.2.1 marc pcic_chip_io_free,
52 1.1.2.1 marc pcic_chip_io_map,
53 1.1.2.1 marc pcic_chip_io_unmap,
54 1.1.2.1 marc
55 1.1.2.1 marc pcic_isa_chip_intr_establish,
56 1.1.2.1 marc pcic_isa_chip_intr_disestablish,
57 1.1.2.1 marc
58 1.1.2.1 marc pcic_chip_socket_enable,
59 1.1.2.1 marc pcic_chip_socket_disable,
60 1.1.2.1 marc };
61 1.1.2.1 marc
62 1.1.2.1 marc int
63 1.1.2.1 marc pcic_isa_probe(parent, match, aux)
64 1.1.2.1 marc struct device *parent;
65 1.1.2.1 marc void *match, *aux;
66 1.1.2.1 marc {
67 1.1.2.1 marc struct isa_attach_args *ia = aux;
68 1.1.2.1 marc bus_space_tag_t iot = ia->ia_iot;
69 1.1.2.1 marc bus_space_handle_t ioh, memh;
70 1.1.2.1 marc int val, found;
71 1.1.2.1 marc
72 1.1.2.1 marc if (bus_space_map(iot, ia->ia_iobase, PCIC_IOSIZE, 0, &ioh))
73 1.1.2.1 marc return (0);
74 1.1.2.1 marc
75 1.1.2.1 marc if (ia->ia_msize == -1)
76 1.1.2.1 marc ia->ia_msize = PCIC_MEMSIZE;
77 1.1.2.1 marc
78 1.1.2.1 marc if (bus_space_map(ia->ia_memt, ia->ia_maddr, ia->ia_msize, 0, &memh))
79 1.1.2.1 marc return (0);
80 1.1.2.1 marc
81 1.1.2.1 marc found = 0;
82 1.1.2.1 marc
83 1.1.2.1 marc /* this could be done with a loop, but it would violate the
84 1.1.2.1 marc abstraction */
85 1.1.2.1 marc
86 1.1.2.1 marc bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C0SA+PCIC_IDENT);
87 1.1.2.1 marc
88 1.1.2.1 marc val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
89 1.1.2.1 marc
90 1.1.2.1 marc if (pcic_ident_ok(val))
91 1.1.2.1 marc found++;
92 1.1.2.1 marc
93 1.1.2.1 marc
94 1.1.2.1 marc bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C0SB+PCIC_IDENT);
95 1.1.2.1 marc
96 1.1.2.1 marc val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
97 1.1.2.1 marc
98 1.1.2.1 marc if (pcic_ident_ok(val))
99 1.1.2.1 marc found++;
100 1.1.2.1 marc
101 1.1.2.1 marc
102 1.1.2.1 marc bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C1SA+PCIC_IDENT);
103 1.1.2.1 marc
104 1.1.2.1 marc val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
105 1.1.2.1 marc
106 1.1.2.1 marc if (pcic_ident_ok(val))
107 1.1.2.1 marc found++;
108 1.1.2.1 marc
109 1.1.2.1 marc
110 1.1.2.1 marc bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C1SB+PCIC_IDENT);
111 1.1.2.1 marc
112 1.1.2.1 marc val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
113 1.1.2.1 marc
114 1.1.2.1 marc if (pcic_ident_ok(val))
115 1.1.2.1 marc found++;
116 1.1.2.1 marc
117 1.1.2.1 marc
118 1.1.2.1 marc bus_space_unmap(iot, ioh, PCIC_IOSIZE);
119 1.1.2.1 marc bus_space_unmap(ia->ia_memt, memh, ia->ia_msize);
120 1.1.2.1 marc
121 1.1.2.1 marc if (!found)
122 1.1.2.1 marc return(0);
123 1.1.2.1 marc
124 1.1.2.1 marc ia->ia_iosize = PCIC_IOSIZE;
125 1.1.2.1 marc
126 1.1.2.1 marc return(1);
127 1.1.2.1 marc }
128 1.1.2.1 marc
129 1.1.2.2 marc #ifndef PCIC_ISA_ALLOC_IOBASE
130 1.1.2.2 marc #define PCIC_ISA_ALLOC_IOBASE 0
131 1.1.2.2 marc #endif
132 1.1.2.2 marc
133 1.1.2.2 marc #ifndef PCIC_ISA_ALLOC_IOSIZE
134 1.1.2.2 marc #define PCIC_ISA_ALLOC_IOSIZE 0
135 1.1.2.2 marc #endif
136 1.1.2.2 marc
137 1.1.2.2 marc int pcic_isa_alloc_iobase = PCIC_ISA_ALLOC_IOBASE;
138 1.1.2.2 marc int pcic_isa_alloc_iosize = PCIC_ISA_ALLOC_IOSIZE;
139 1.1.2.2 marc
140 1.1.2.1 marc void
141 1.1.2.1 marc pcic_isa_attach(parent, self, aux)
142 1.1.2.1 marc struct device *parent, *self;
143 1.1.2.1 marc void *aux;
144 1.1.2.1 marc {
145 1.1.2.1 marc struct pcic_softc *sc = (void *)self;
146 1.1.2.1 marc struct isa_attach_args *ia = aux;
147 1.1.2.1 marc isa_chipset_tag_t ic = ia->ia_ic;
148 1.1.2.1 marc bus_space_tag_t iot = ia->ia_iot;
149 1.1.2.1 marc bus_space_tag_t memt = ia->ia_memt;
150 1.1.2.1 marc bus_space_handle_t ioh;
151 1.1.2.1 marc bus_space_handle_t memh;
152 1.1.2.2 marc bus_space_handle_t ioh_high;
153 1.1.2.2 marc int i, iobuswidth, tmp1, tmp2;
154 1.1.2.1 marc
155 1.1.2.1 marc /* Map i/o space. */
156 1.1.2.1 marc if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh))
157 1.1.2.1 marc panic("pcic_isa_attach: can't map i/o space");
158 1.1.2.1 marc
159 1.1.2.1 marc /* Map mem space. */
160 1.1.2.1 marc if (bus_space_map(memt, ia->ia_maddr, ia->ia_msize, 0, &memh))
161 1.1.2.1 marc panic("pcic_isa_attach: can't map i/o space");
162 1.1.2.1 marc
163 1.1.2.1 marc sc->membase = ia->ia_maddr;
164 1.1.2.1 marc sc->subregionmask = (1<<(ia->ia_msize/PCIC_MEM_PAGESIZE))-1;
165 1.1.2.1 marc
166 1.1.2.1 marc sc->intr_est = ic;
167 1.1.2.1 marc sc->pct = (pcmcia_chipset_tag_t) &pcic_isa_functions;
168 1.1.2.1 marc
169 1.1.2.1 marc sc->iot = iot;
170 1.1.2.1 marc sc->ioh = ioh;
171 1.1.2.1 marc sc->memt = memt;
172 1.1.2.1 marc sc->memh = memh;
173 1.1.2.1 marc
174 1.1.2.1 marc /* allocate an irq. it will be used by both controllers. I could
175 1.1.2.1 marc use two different interrupts, but interrupts are relatively
176 1.1.2.1 marc scarce, shareable, and for PCIC controllers, very infrequent. */
177 1.1.2.1 marc
178 1.1.2.1 marc if ((sc->irq = ia->ia_irq) == IRQUNK) {
179 1.1.2.1 marc /* XXX CHECK RETURN VALUE */
180 1.1.2.1 marc (void) isa_intr_alloc(ic,
181 1.1.2.1 marc PCIC_CSC_INTR_IRQ_VALIDMASK,
182 1.1.2.1 marc IST_EDGE, &sc->irq);
183 1.1.2.1 marc printf(": using irq %d", sc->irq);
184 1.1.2.1 marc }
185 1.1.2.1 marc
186 1.1.2.1 marc printf("\n");
187 1.1.2.1 marc
188 1.1.2.1 marc pcic_attach(sc);
189 1.1.2.1 marc
190 1.1.2.2 marc /* figure out how wide the isa bus is. Do this by checking if
191 1.1.2.2 marc the pcic controller is mirrored 0x400 above where we expect it
192 1.1.2.2 marc to be. */
193 1.1.2.2 marc
194 1.1.2.2 marc iobuswidth = 12;
195 1.1.2.2 marc
196 1.1.2.2 marc /* Map i/o space. */
197 1.1.2.2 marc if (bus_space_map(iot, ia->ia_iobase+0x400, ia->ia_iosize, 0, &ioh_high))
198 1.1.2.2 marc panic("pcic_isa_attach: can't map high i/o space");
199 1.1.2.2 marc
200 1.1.2.2 marc for (i=0; i<PCIC_NSLOTS; i++) {
201 1.1.2.2 marc if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) {
202 1.1.2.2 marc /* read the ident flags from the normal space
203 1.1.2.2 marc and from the mirror, and compare them */
204 1.1.2.2 marc
205 1.1.2.2 marc bus_space_write_1(iot, ioh, PCIC_REG_INDEX,
206 1.1.2.2 marc sc->handle[i].sock+PCIC_IDENT);
207 1.1.2.2 marc tmp1 = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
208 1.1.2.2 marc
209 1.1.2.2 marc bus_space_write_1(iot, ioh_high, PCIC_REG_INDEX,
210 1.1.2.2 marc sc->handle[i].sock+PCIC_IDENT);
211 1.1.2.2 marc tmp2 = bus_space_read_1(iot, ioh_high, PCIC_REG_DATA);
212 1.1.2.2 marc
213 1.1.2.2 marc if (tmp1 == tmp2)
214 1.1.2.2 marc iobuswidth = 10;
215 1.1.2.2 marc }
216 1.1.2.2 marc }
217 1.1.2.2 marc
218 1.1.2.2 marc bus_space_free(iot, ioh_high, ia->ia_iosize);
219 1.1.2.2 marc
220 1.1.2.2 marc /* XXX mycroft recommends I/O space range 0x400-0xfff . I should put
221 1.1.2.2 marc this in a header somewhere */
222 1.1.2.2 marc
223 1.1.2.2 marc /* XXX some hardware doesn't seem to grok addresses in 0x400 range--
224 1.1.2.2 marc apparently missing a bit or more of address lines.
225 1.1.2.2 marc (e.g. CIRRUS_PD672X with Linksys EthernetCard ne2000 clone in TI
226 1.1.2.2 marc TravelMate 5000--not clear which is at fault)
227 1.1.2.2 marc
228 1.1.2.2 marc Add a kludge to detect 10 bit wide buses and deal with them, and
229 1.1.2.2 marc also a config file option to override the probe. */
230 1.1.2.2 marc
231 1.1.2.2 marc if (iobuswidth == 10) {
232 1.1.2.2 marc sc->iobase = 0x300;
233 1.1.2.2 marc sc->iosize = 0x0ff;
234 1.1.2.2 marc } else {
235 1.1.2.2 marc sc->iobase = 0x400;
236 1.1.2.2 marc sc->iosize = 0xbff;
237 1.1.2.2 marc }
238 1.1.2.2 marc
239 1.1.2.2 marc DPRINTF(("%s: bus_space_alloc range 0x%04lx-0x%04lx (probed)\n",
240 1.1.2.2 marc sc->dev.dv_xname, (long) sc->iobase,
241 1.1.2.2 marc (long) sc->iobase+sc->iosize));
242 1.1.2.2 marc
243 1.1.2.2 marc if (pcic_isa_alloc_iobase && pcic_isa_alloc_iosize) {
244 1.1.2.2 marc sc->iobase = pcic_isa_alloc_iobase;
245 1.1.2.2 marc sc->iosize = pcic_isa_alloc_iosize;
246 1.1.2.2 marc
247 1.1.2.2 marc DPRINTF(("%s: bus_space_alloc range 0x%04lx-0x%04lx (config override)\n",
248 1.1.2.2 marc sc->dev.dv_xname, (long) sc->iobase,
249 1.1.2.2 marc (long) sc->iobase+sc->iosize));
250 1.1.2.2 marc }
251 1.1.2.2 marc
252 1.1.2.1 marc sc->ih = isa_intr_establish(ic, sc->irq, IST_EDGE, IPL_TTY, pcic_intr, sc);
253 1.1.2.1 marc
254 1.1.2.1 marc pcic_attach_sockets(sc);
255 1.1.2.1 marc }
256 1.1.2.1 marc
257 1.1.2.1 marc /* allow patching or kernel option file override of available IRQs.
258 1.1.2.1 marc Useful if order of probing would screw up other devices, or if PCIC
259 1.1.2.1 marc hardware/cards have trouble with certain interrupt lines. */
260 1.1.2.1 marc
261 1.1.2.1 marc #ifndef PCIC_INTR_ALLOC_MASK
262 1.1.2.1 marc #define PCIC_INTR_ALLOC_MASK 0xffff
263 1.1.2.1 marc #endif
264 1.1.2.1 marc
265 1.1.2.1 marc int pcic_intr_alloc_mask = PCIC_INTR_ALLOC_MASK;
266 1.1.2.1 marc
267 1.1.2.1 marc void *
268 1.1.2.1 marc pcic_isa_chip_intr_establish(pch, pf, ipl, fct, arg)
269 1.1.2.1 marc pcmcia_chipset_handle_t pch;
270 1.1.2.1 marc struct pcmcia_function *pf;
271 1.1.2.1 marc int ipl;
272 1.1.2.1 marc int (*fct)(void *);
273 1.1.2.1 marc void *arg;
274 1.1.2.1 marc {
275 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) pch;
276 1.1.2.1 marc int irq, ist;
277 1.1.2.1 marc void *ih;
278 1.1.2.1 marc int reg;
279 1.1.2.1 marc
280 1.1.2.1 marc if (pf->cfe->flags & PCMCIA_CFE_IRQLEVEL)
281 1.1.2.1 marc ist = IST_LEVEL;
282 1.1.2.1 marc else if (pf->cfe->flags & PCMCIA_CFE_IRQPULSE)
283 1.1.2.1 marc ist = IST_PULSE;
284 1.1.2.1 marc else
285 1.1.2.1 marc ist = IST_LEVEL;
286 1.1.2.1 marc
287 1.1.2.1 marc if (isa_intr_alloc(h->sc->intr_est,
288 1.1.2.1 marc PCIC_INTR_IRQ_VALIDMASK & pcic_intr_alloc_mask,
289 1.1.2.1 marc ist, &irq))
290 1.1.2.1 marc return(NULL);
291 1.1.2.1 marc if (!(ih = isa_intr_establish(h->sc->intr_est, irq, ist, ipl, fct, arg)))
292 1.1.2.1 marc return(NULL);
293 1.1.2.1 marc
294 1.1.2.1 marc reg = pcic_read(h, PCIC_INTR);
295 1.1.2.1 marc reg &= ~PCIC_INTR_IRQ_MASK;
296 1.1.2.1 marc reg |= irq;
297 1.1.2.1 marc pcic_write(h, PCIC_INTR, reg);
298 1.1.2.1 marc
299 1.1.2.2 marc h->ih_irq = irq;
300 1.1.2.2 marc
301 1.1.2.1 marc printf("%s: card irq %d\n", h->pcmcia->dv_xname, irq);
302 1.1.2.1 marc
303 1.1.2.1 marc return(ih);
304 1.1.2.1 marc }
305 1.1.2.1 marc
306 1.1.2.1 marc void pcic_isa_chip_intr_disestablish(pch, ih)
307 1.1.2.1 marc pcmcia_chipset_handle_t pch;
308 1.1.2.1 marc void *ih;
309 1.1.2.1 marc {
310 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) pch;
311 1.1.2.1 marc int reg;
312 1.1.2.2 marc
313 1.1.2.2 marc h->ih_irq = 0;
314 1.1.2.1 marc
315 1.1.2.1 marc reg = pcic_read(h, PCIC_INTR);
316 1.1.2.1 marc reg &= ~(PCIC_INTR_IRQ_MASK|PCIC_INTR_ENABLE);
317 1.1.2.1 marc pcic_write(h, PCIC_INTR, reg);
318 1.1.2.1 marc
319 1.1.2.1 marc isa_intr_disestablish(h->sc->intr_est, ih);
320 1.1.2.1 marc }
321