i82365.c revision 1.1.2.7 1 1.1.2.1 marc #define PCICDEBUG
2 1.1.2.1 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.4 thorpej #include <dev/pcmcia/pcmciavar.h>
20 1.1.2.1 marc
21 1.1.2.1 marc #include <dev/ic/i82365reg.h>
22 1.1.2.1 marc
23 1.1.2.1 marc #ifdef PCICDEBUG
24 1.1.2.2 thorpej int pcic_debug = 0;
25 1.1.2.2 thorpej #define DPRINTF(arg) if (pcic_debug) printf arg;
26 1.1.2.1 marc #else
27 1.1.2.1 marc #define DPRINTF(arg)
28 1.1.2.1 marc #endif
29 1.1.2.1 marc
30 1.1.2.1 marc /* This is sort of arbitrary. It merely needs to be "enough".
31 1.1.2.1 marc It can be overridden in the conf file, anyway. */
32 1.1.2.1 marc
33 1.1.2.1 marc #define PCIC_MEM_PAGES 4
34 1.1.2.1 marc #define PCIC_MEMSIZE PCIC_MEM_PAGES*PCIC_MEM_PAGESIZE
35 1.1.2.1 marc
36 1.1.2.1 marc #define PCIC_NSLOTS 4
37 1.1.2.1 marc
38 1.1.2.1 marc #define PCIC_FLAG_SOCKETP 0x0001
39 1.1.2.1 marc #define PCIC_FLAG_CARDP 0x0002
40 1.1.2.1 marc
41 1.1.2.1 marc #define PCIC_VENDOR_UNKNOWN 0
42 1.1.2.1 marc #define PCIC_VENDOR_I82365SLR0 1
43 1.1.2.1 marc #define PCIC_VENDOR_I82365SLR1 2
44 1.1.2.1 marc #define PCIC_VENDOR_CIRRUS_PD6710 3
45 1.1.2.1 marc #define PCIC_VENDOR_CIRRUS_PD672X 4
46 1.1.2.1 marc
47 1.1.2.1 marc struct pcic_handle {
48 1.1.2.1 marc struct pcic_softc *sc;
49 1.1.2.1 marc int vendor;
50 1.1.2.1 marc int sock;
51 1.1.2.1 marc int flags;
52 1.1.2.1 marc int memalloc;
53 1.1.2.1 marc int ioalloc;
54 1.1.2.1 marc struct device *pcmcia;
55 1.1.2.1 marc };
56 1.1.2.1 marc
57 1.1.2.1 marc struct pcic_softc {
58 1.1.2.1 marc struct device dev;
59 1.1.2.1 marc
60 1.1.2.1 marc isa_chipset_tag_t ic;
61 1.1.2.1 marc
62 1.1.2.1 marc bus_space_tag_t memt;
63 1.1.2.1 marc bus_space_tag_t memh;
64 1.1.2.1 marc bus_space_tag_t iot;
65 1.1.2.1 marc bus_space_tag_t ioh;
66 1.1.2.1 marc
67 1.1.2.1 marc /* this needs to be large enough to hold PCIC_MEM_PAGES bits */
68 1.1.2.1 marc int subregionmask;
69 1.1.2.1 marc
70 1.1.2.4 thorpej /* used by memory window mapping functions */
71 1.1.2.4 thorpej bus_addr_t membase;
72 1.1.2.4 thorpej
73 1.1.2.1 marc int irq;
74 1.1.2.1 marc void *ih;
75 1.1.2.1 marc
76 1.1.2.1 marc struct pcic_handle handle[PCIC_NSLOTS];
77 1.1.2.1 marc };
78 1.1.2.1 marc
79 1.1.2.1 marc #define C0SA PCIC_CHIP0_BASE+PCIC_SOCKETA_INDEX
80 1.1.2.1 marc #define C0SB PCIC_CHIP0_BASE+PCIC_SOCKETB_INDEX
81 1.1.2.1 marc #define C1SA PCIC_CHIP1_BASE+PCIC_SOCKETA_INDEX
82 1.1.2.1 marc #define C1SB PCIC_CHIP1_BASE+PCIC_SOCKETB_INDEX
83 1.1.2.1 marc
84 1.1.2.1 marc /* Individual drivers will allocate their own memory and io regions.
85 1.1.2.1 marc Memory regions must be a multiple of 4k, aligned on a 4k boundary. */
86 1.1.2.1 marc
87 1.1.2.1 marc #define PCIC_MEM_ALIGN PCIC_MEM_PAGESIZE
88 1.1.2.1 marc
89 1.1.2.1 marc int pcic_probe __P((struct device *, void *, void *));
90 1.1.2.1 marc void pcic_attach __P((struct device *, struct device *, void *));
91 1.1.2.1 marc
92 1.1.2.1 marc int pcic_ident_ok __P((int));
93 1.1.2.1 marc int pcic_vendor __P((struct pcic_handle *));
94 1.1.2.1 marc char *pcic_vendor_to_string __P((int));
95 1.1.2.1 marc static inline int pcic_read __P((struct pcic_handle *, int));
96 1.1.2.1 marc static inline void pcic_write __P((struct pcic_handle *, int, int));
97 1.1.2.1 marc static inline void pcic_wait_ready __P((struct pcic_handle *));
98 1.1.2.1 marc void pcic_attach_socket __P((struct pcic_handle *));
99 1.1.2.1 marc void pcic_init_socket __P((struct pcic_handle *));
100 1.1.2.1 marc
101 1.1.2.1 marc #ifdef __BROKEN_INDIRECT_CONFIG
102 1.1.2.1 marc int pcic_submatch __P((struct device *, void *, void *));
103 1.1.2.1 marc #else
104 1.1.2.1 marc int pcic_submatch __P((struct device *, struct cfdata *, void *));
105 1.1.2.1 marc #endif
106 1.1.2.1 marc int pcic_print __P((void *arg, const char *pnp));
107 1.1.2.1 marc int pcic_intr __P((void *arg));
108 1.1.2.1 marc int pcic_intr_socket __P((struct pcic_handle *));
109 1.1.2.1 marc
110 1.1.2.1 marc int pcic_chip_mem_alloc __P((pcmcia_chipset_handle_t, bus_size_t,
111 1.1.2.4 thorpej struct pcmcia_mem_handle *));
112 1.1.2.4 thorpej void pcic_chip_mem_free __P((pcmcia_chipset_handle_t,
113 1.1.2.4 thorpej struct pcmcia_mem_handle *));
114 1.1.2.4 thorpej int pcic_chip_mem_map __P((pcmcia_chipset_handle_t, int, bus_addr_t,
115 1.1.2.4 thorpej bus_size_t, struct pcmcia_mem_handle *,
116 1.1.2.4 thorpej bus_addr_t *, int *));
117 1.1.2.1 marc void pcic_chip_mem_unmap __P((pcmcia_chipset_handle_t, int));
118 1.1.2.1 marc
119 1.1.2.1 marc int pcic_chip_io_alloc __P((pcmcia_chipset_handle_t, bus_addr_t, bus_size_t,
120 1.1.2.4 thorpej struct pcmcia_io_handle *));
121 1.1.2.4 thorpej void pcic_chip_io_free __P((pcmcia_chipset_handle_t,
122 1.1.2.4 thorpej struct pcmcia_io_handle *));
123 1.1.2.4 thorpej int pcic_chip_io_map __P((pcmcia_chipset_handle_t, int, bus_addr_t, bus_size_t,
124 1.1.2.4 thorpej struct pcmcia_io_handle *, int *));
125 1.1.2.1 marc void pcic_chip_io_unmap __P((pcmcia_chipset_handle_t, int));
126 1.1.2.1 marc
127 1.1.2.5 thorpej void *pcic_chip_intr_establish __P((pcmcia_chipset_handle_t,
128 1.1.2.5 thorpej struct pcmcia_function *, int,
129 1.1.2.1 marc int (*)(void *), void *));
130 1.1.2.1 marc void pcic_chip_intr_disestablish __P((pcmcia_chipset_handle_t, void *));
131 1.1.2.1 marc
132 1.1.2.7 thorpej void pcic_chip_socket_enable __P((pcmcia_chipset_handle_t));
133 1.1.2.7 thorpej void pcic_chip_socket_disable __P((pcmcia_chipset_handle_t));
134 1.1.2.1 marc
135 1.1.2.1 marc void pcic_attach_card(struct pcic_handle *);
136 1.1.2.1 marc void pcic_detach_card(struct pcic_handle *);
137 1.1.2.1 marc
138 1.1.2.1 marc static struct pcmcia_chip_functions pcic_functions = {
139 1.1.2.1 marc pcic_chip_mem_alloc,
140 1.1.2.1 marc pcic_chip_mem_free,
141 1.1.2.1 marc pcic_chip_mem_map,
142 1.1.2.1 marc pcic_chip_mem_unmap,
143 1.1.2.1 marc
144 1.1.2.1 marc pcic_chip_io_alloc,
145 1.1.2.1 marc pcic_chip_io_free,
146 1.1.2.1 marc pcic_chip_io_map,
147 1.1.2.1 marc pcic_chip_io_unmap,
148 1.1.2.1 marc
149 1.1.2.1 marc pcic_chip_intr_establish,
150 1.1.2.1 marc pcic_chip_intr_disestablish,
151 1.1.2.7 thorpej
152 1.1.2.7 thorpej pcic_chip_socket_enable,
153 1.1.2.7 thorpej pcic_chip_socket_disable,
154 1.1.2.1 marc };
155 1.1.2.1 marc
156 1.1.2.1 marc struct cfdriver pcic_cd = {
157 1.1.2.1 marc NULL, "pcic", DV_DULL
158 1.1.2.1 marc };
159 1.1.2.1 marc
160 1.1.2.1 marc struct cfattach pcic_ca = {
161 1.1.2.1 marc sizeof(struct pcic_softc), pcic_probe, pcic_attach
162 1.1.2.1 marc };
163 1.1.2.1 marc
164 1.1.2.1 marc static inline int
165 1.1.2.1 marc pcic_read(h, idx)
166 1.1.2.1 marc struct pcic_handle *h;
167 1.1.2.1 marc int idx;
168 1.1.2.1 marc {
169 1.1.2.1 marc if (idx != -1)
170 1.1.2.1 marc bus_space_write_1(h->sc->iot, h->sc->ioh, PCIC_REG_INDEX, h->sock+idx);
171 1.1.2.1 marc return(bus_space_read_1(h->sc->iot, h->sc->ioh, PCIC_REG_DATA));
172 1.1.2.1 marc }
173 1.1.2.1 marc
174 1.1.2.1 marc static inline void
175 1.1.2.1 marc pcic_write(h, idx, data)
176 1.1.2.1 marc struct pcic_handle *h;
177 1.1.2.1 marc int idx;
178 1.1.2.1 marc int data;
179 1.1.2.1 marc {
180 1.1.2.1 marc if (idx != -1)
181 1.1.2.1 marc bus_space_write_1(h->sc->iot, h->sc->ioh, PCIC_REG_INDEX, h->sock+idx);
182 1.1.2.1 marc bus_space_write_1(h->sc->iot, h->sc->ioh, PCIC_REG_DATA, (data));
183 1.1.2.1 marc }
184 1.1.2.1 marc
185 1.1.2.1 marc static inline void
186 1.1.2.1 marc pcic_wait_ready(h)
187 1.1.2.1 marc struct pcic_handle *h;
188 1.1.2.1 marc {
189 1.1.2.1 marc int i;
190 1.1.2.1 marc
191 1.1.2.1 marc for (i=0; i<10000; i++) {
192 1.1.2.1 marc if (pcic_read(h, PCIC_IF_STATUS) & PCIC_IF_STATUS_READY)
193 1.1.2.1 marc return;
194 1.1.2.1 marc delay(500);
195 1.1.2.1 marc }
196 1.1.2.1 marc
197 1.1.2.1 marc DPRINTF(("pcic_wait_ready ready never happened\n"));
198 1.1.2.1 marc }
199 1.1.2.1 marc
200 1.1.2.1 marc int
201 1.1.2.1 marc pcic_ident_ok(ident)
202 1.1.2.1 marc int ident;
203 1.1.2.1 marc {
204 1.1.2.1 marc /* this is very empirical and heuristic */
205 1.1.2.1 marc
206 1.1.2.1 marc if ((ident == 0) || (ident == 0xff) || (ident & PCIC_IDENT_ZERO))
207 1.1.2.1 marc return(0);
208 1.1.2.1 marc
209 1.1.2.1 marc if ((ident & PCIC_IDENT_IFTYPE_MASK) != PCIC_IDENT_IFTYPE_MEM_AND_IO) {
210 1.1.2.1 marc #ifdef DIAGNOSTIC
211 1.1.2.1 marc printf("pcic: does not support memory and I/O cards, ignored (ident=%0x)\n",
212 1.1.2.1 marc ident);
213 1.1.2.1 marc #endif
214 1.1.2.1 marc return(0);
215 1.1.2.1 marc }
216 1.1.2.1 marc
217 1.1.2.1 marc return(1);
218 1.1.2.1 marc }
219 1.1.2.1 marc
220 1.1.2.1 marc int
221 1.1.2.1 marc pcic_vendor(h)
222 1.1.2.1 marc struct pcic_handle *h;
223 1.1.2.1 marc {
224 1.1.2.1 marc int reg;
225 1.1.2.1 marc
226 1.1.2.1 marc /* I can't claim to understand this; I'm just doing what the
227 1.1.2.1 marc linux driver does */
228 1.1.2.1 marc
229 1.1.2.1 marc pcic_write(h, PCIC_CIRRUS_CHIP_INFO, 0);
230 1.1.2.1 marc reg = pcic_read(h, -1);
231 1.1.2.1 marc
232 1.1.2.1 marc if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) ==
233 1.1.2.1 marc PCIC_CIRRUS_CHIP_INFO_CHIP_ID) {
234 1.1.2.1 marc reg = pcic_read(h, -1);
235 1.1.2.1 marc if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) == 0) {
236 1.1.2.1 marc if (reg & PCIC_CIRRUS_CHIP_INFO_SLOTS)
237 1.1.2.1 marc return(PCIC_VENDOR_CIRRUS_PD672X);
238 1.1.2.1 marc else
239 1.1.2.1 marc return(PCIC_VENDOR_CIRRUS_PD6710);
240 1.1.2.1 marc }
241 1.1.2.1 marc }
242 1.1.2.1 marc
243 1.1.2.1 marc reg = pcic_read(h, PCIC_IDENT);
244 1.1.2.1 marc
245 1.1.2.1 marc if ((reg & PCIC_IDENT_REV_MASK) == PCIC_IDENT_REV_I82365SLR0)
246 1.1.2.1 marc return(PCIC_VENDOR_I82365SLR0);
247 1.1.2.1 marc else
248 1.1.2.1 marc return(PCIC_VENDOR_I82365SLR1);
249 1.1.2.1 marc
250 1.1.2.1 marc return(PCIC_VENDOR_UNKNOWN);
251 1.1.2.1 marc }
252 1.1.2.1 marc
253 1.1.2.1 marc char *
254 1.1.2.1 marc pcic_vendor_to_string(vendor)
255 1.1.2.1 marc int vendor;
256 1.1.2.1 marc {
257 1.1.2.1 marc switch (vendor) {
258 1.1.2.1 marc case PCIC_VENDOR_I82365SLR0:
259 1.1.2.1 marc return("Intel 82365SL Revision 0");
260 1.1.2.1 marc case PCIC_VENDOR_I82365SLR1:
261 1.1.2.1 marc return("Intel 82365SL Revision 1");
262 1.1.2.1 marc case PCIC_VENDOR_CIRRUS_PD6710:
263 1.1.2.1 marc return("Cirrus PD6710");
264 1.1.2.1 marc case PCIC_VENDOR_CIRRUS_PD672X:
265 1.1.2.1 marc return("Cirrus PD672X");
266 1.1.2.1 marc }
267 1.1.2.1 marc
268 1.1.2.1 marc return("Unknown controller");
269 1.1.2.1 marc }
270 1.1.2.1 marc
271 1.1.2.1 marc int
272 1.1.2.1 marc pcic_probe(parent, match, aux)
273 1.1.2.1 marc struct device *parent;
274 1.1.2.1 marc void *match, *aux;
275 1.1.2.1 marc {
276 1.1.2.1 marc struct isa_attach_args *ia = aux;
277 1.1.2.1 marc bus_space_tag_t iot = ia->ia_iot;
278 1.1.2.1 marc bus_space_handle_t ioh, memh;
279 1.1.2.1 marc int val, found;
280 1.1.2.1 marc
281 1.1.2.1 marc DPRINTF(("pcic_probe %x\n", ia->ia_iobase));
282 1.1.2.1 marc
283 1.1.2.1 marc if (bus_space_map(iot, ia->ia_iobase, PCIC_IOSIZE, 0, &ioh))
284 1.1.2.1 marc return (0);
285 1.1.2.1 marc
286 1.1.2.1 marc if (ia->ia_msize == -1)
287 1.1.2.1 marc ia->ia_msize = PCIC_MEMSIZE;
288 1.1.2.1 marc
289 1.1.2.1 marc if (bus_space_map(ia->ia_memt, ia->ia_maddr, ia->ia_msize, 0, &memh))
290 1.1.2.1 marc return (0);
291 1.1.2.1 marc
292 1.1.2.1 marc found = 0;
293 1.1.2.1 marc
294 1.1.2.1 marc /* this could be done with a loop, but it would violate the
295 1.1.2.1 marc abstraction */
296 1.1.2.1 marc
297 1.1.2.1 marc bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C0SA+PCIC_IDENT);
298 1.1.2.1 marc
299 1.1.2.1 marc val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
300 1.1.2.1 marc
301 1.1.2.1 marc DPRINTF(("c0sa ident = %02x, ", val));
302 1.1.2.1 marc
303 1.1.2.1 marc if (pcic_ident_ok(val))
304 1.1.2.1 marc found++;
305 1.1.2.1 marc
306 1.1.2.1 marc
307 1.1.2.1 marc bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C0SB+PCIC_IDENT);
308 1.1.2.1 marc
309 1.1.2.1 marc val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
310 1.1.2.1 marc
311 1.1.2.1 marc DPRINTF(("c0sb ident = %02x, ", val));
312 1.1.2.1 marc
313 1.1.2.1 marc if (pcic_ident_ok(val))
314 1.1.2.1 marc found++;
315 1.1.2.1 marc
316 1.1.2.1 marc
317 1.1.2.1 marc bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C1SA+PCIC_IDENT);
318 1.1.2.1 marc
319 1.1.2.1 marc val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
320 1.1.2.1 marc
321 1.1.2.1 marc DPRINTF(("c1sa ident = %02x, ", val));
322 1.1.2.1 marc
323 1.1.2.1 marc if (pcic_ident_ok(val))
324 1.1.2.1 marc found++;
325 1.1.2.1 marc
326 1.1.2.1 marc
327 1.1.2.1 marc bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C1SB+PCIC_IDENT);
328 1.1.2.1 marc
329 1.1.2.1 marc val = bus_space_read_1(iot, ioh, PCIC_REG_DATA);
330 1.1.2.1 marc
331 1.1.2.1 marc DPRINTF(("c1sb ident = %02x\n", val));
332 1.1.2.1 marc
333 1.1.2.1 marc if (pcic_ident_ok(val))
334 1.1.2.1 marc found++;
335 1.1.2.1 marc
336 1.1.2.1 marc
337 1.1.2.1 marc bus_space_unmap(iot, ioh, PCIC_IOSIZE);
338 1.1.2.1 marc bus_space_unmap(ia->ia_memt, memh, ia->ia_msize);
339 1.1.2.1 marc
340 1.1.2.1 marc if (!found)
341 1.1.2.1 marc return(0);
342 1.1.2.1 marc
343 1.1.2.1 marc ia->ia_iosize = PCIC_IOSIZE;
344 1.1.2.1 marc
345 1.1.2.1 marc return(1);
346 1.1.2.1 marc }
347 1.1.2.1 marc
348 1.1.2.1 marc void
349 1.1.2.1 marc pcic_attach(parent, self, aux)
350 1.1.2.1 marc struct device *parent, *self;
351 1.1.2.1 marc void *aux;
352 1.1.2.1 marc {
353 1.1.2.1 marc struct pcic_softc *sc = (void *)self;
354 1.1.2.1 marc struct isa_attach_args *ia = aux;
355 1.1.2.1 marc isa_chipset_tag_t ic = ia->ia_ic;
356 1.1.2.1 marc bus_space_tag_t iot = ia->ia_iot;
357 1.1.2.1 marc bus_space_tag_t memt = ia->ia_memt;
358 1.1.2.1 marc bus_space_handle_t ioh;
359 1.1.2.1 marc bus_space_handle_t memh;
360 1.1.2.6 jtk int vendor, count, i;
361 1.1.2.1 marc
362 1.1.2.1 marc /* Map i/o space. */
363 1.1.2.1 marc if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh))
364 1.1.2.1 marc panic("pcic_attach: can't map i/o space");
365 1.1.2.1 marc
366 1.1.2.1 marc /* Map mem space. */
367 1.1.2.1 marc if (bus_space_map(memt, ia->ia_maddr, ia->ia_msize, 0, &memh))
368 1.1.2.1 marc panic("pcic_attach: can't map i/o space");
369 1.1.2.1 marc
370 1.1.2.1 marc sc->subregionmask = (1<<(ia->ia_msize/PCIC_MEM_PAGESIZE))-1;
371 1.1.2.1 marc
372 1.1.2.1 marc sc->ic = ic;
373 1.1.2.1 marc
374 1.1.2.1 marc sc->iot = iot;
375 1.1.2.1 marc sc->ioh = ioh;
376 1.1.2.1 marc sc->memt = memt;
377 1.1.2.1 marc sc->memh = memh;
378 1.1.2.1 marc
379 1.1.2.4 thorpej sc->membase = ia->ia_maddr;
380 1.1.2.4 thorpej
381 1.1.2.1 marc /* now check for each controller/socket */
382 1.1.2.1 marc
383 1.1.2.1 marc /* this could be done with a loop, but it would violate the
384 1.1.2.1 marc abstraction */
385 1.1.2.1 marc
386 1.1.2.1 marc count = 0;
387 1.1.2.1 marc
388 1.1.2.1 marc sc->handle[0].sc = sc;
389 1.1.2.1 marc sc->handle[0].sock = C0SA;
390 1.1.2.1 marc if (pcic_ident_ok(pcic_read(&sc->handle[0], PCIC_IDENT))) {
391 1.1.2.1 marc sc->handle[0].flags = PCIC_FLAG_SOCKETP;
392 1.1.2.1 marc count++;
393 1.1.2.1 marc } else {
394 1.1.2.1 marc sc->handle[0].flags = 0;
395 1.1.2.1 marc }
396 1.1.2.1 marc
397 1.1.2.1 marc sc->handle[1].sc = sc;
398 1.1.2.1 marc sc->handle[1].sock = C0SB;
399 1.1.2.1 marc if (pcic_ident_ok(pcic_read(&sc->handle[1], PCIC_IDENT))) {
400 1.1.2.1 marc sc->handle[1].flags = PCIC_FLAG_SOCKETP;
401 1.1.2.1 marc count++;
402 1.1.2.1 marc } else {
403 1.1.2.1 marc sc->handle[1].flags = 0;
404 1.1.2.1 marc }
405 1.1.2.1 marc
406 1.1.2.1 marc sc->handle[2].sc = sc;
407 1.1.2.1 marc sc->handle[2].sock = C1SA;
408 1.1.2.1 marc if (pcic_ident_ok(pcic_read(&sc->handle[2], PCIC_IDENT))) {
409 1.1.2.1 marc sc->handle[2].flags = PCIC_FLAG_SOCKETP;
410 1.1.2.1 marc count++;
411 1.1.2.1 marc } else {
412 1.1.2.1 marc sc->handle[2].flags = 0;
413 1.1.2.1 marc }
414 1.1.2.1 marc
415 1.1.2.1 marc sc->handle[3].sc = sc;
416 1.1.2.1 marc sc->handle[3].sock = C1SB;
417 1.1.2.1 marc if (pcic_ident_ok(pcic_read(&sc->handle[3], PCIC_IDENT))) {
418 1.1.2.1 marc sc->handle[3].flags = PCIC_FLAG_SOCKETP;
419 1.1.2.1 marc count++;
420 1.1.2.1 marc } else {
421 1.1.2.1 marc sc->handle[3].flags = 0;
422 1.1.2.1 marc }
423 1.1.2.1 marc
424 1.1.2.1 marc if (count == 0)
425 1.1.2.1 marc panic("pcic_attach: attach found no sockets");
426 1.1.2.1 marc
427 1.1.2.1 marc /* allocate an irq. it will be used by both controllers. I could
428 1.1.2.1 marc use two different interrupts, but interrupts are relatively
429 1.1.2.1 marc scarce, shareable, and for PCIC controllers, very infrequent. */
430 1.1.2.1 marc
431 1.1.2.6 jtk if ((sc->irq = ia->ia_irq) == IRQUNK) {
432 1.1.2.5 thorpej /* XXX CHECK RETURN VALUE */
433 1.1.2.6 jtk (void) isa_intr_alloc(ic,
434 1.1.2.6 jtk PCIC_CSC_INTR_IRQ_VALIDMASK,
435 1.1.2.6 jtk IST_EDGE, &sc->irq);
436 1.1.2.6 jtk printf(": using irq %d", sc->irq);
437 1.1.2.1 marc }
438 1.1.2.1 marc
439 1.1.2.1 marc printf("\n");
440 1.1.2.1 marc
441 1.1.2.1 marc /* establish the interrupt */
442 1.1.2.1 marc
443 1.1.2.1 marc /* XXX block interrupts? */
444 1.1.2.1 marc
445 1.1.2.1 marc for (i=0; i<PCIC_NSLOTS; i++) {
446 1.1.2.1 marc pcic_write(&sc->handle[i], PCIC_CSC_INTR, 0);
447 1.1.2.1 marc pcic_read(&sc->handle[i], PCIC_CSC);
448 1.1.2.1 marc }
449 1.1.2.1 marc
450 1.1.2.6 jtk sc->ih = isa_intr_establish(ic, sc->irq, IST_EDGE, IPL_TTY, pcic_intr, sc);
451 1.1.2.1 marc
452 1.1.2.1 marc if ((sc->handle[0].flags & PCIC_FLAG_SOCKETP) ||
453 1.1.2.1 marc (sc->handle[1].flags & PCIC_FLAG_SOCKETP)) {
454 1.1.2.1 marc vendor = pcic_vendor(&sc->handle[0]);
455 1.1.2.1 marc
456 1.1.2.1 marc printf("%s: controller 0 (%s) has ", sc->dev.dv_xname,
457 1.1.2.1 marc pcic_vendor_to_string(vendor));
458 1.1.2.1 marc
459 1.1.2.1 marc if ((sc->handle[0].flags & PCIC_FLAG_SOCKETP) &&
460 1.1.2.1 marc (sc->handle[1].flags & PCIC_FLAG_SOCKETP))
461 1.1.2.1 marc printf("sockets A and B\n");
462 1.1.2.1 marc else if (sc->handle[0].flags & PCIC_FLAG_SOCKETP)
463 1.1.2.1 marc printf("socket A only\n");
464 1.1.2.1 marc else
465 1.1.2.1 marc printf("socket B only\n");
466 1.1.2.1 marc
467 1.1.2.1 marc #if 0
468 1.1.2.1 marc pcic_write(&sc->handle[0], PCIC_GLOBAL_CTL,
469 1.1.2.1 marc PCIC_GLOBAL_CTL_EXPLICIT_CSC_ACK);
470 1.1.2.1 marc #endif
471 1.1.2.1 marc
472 1.1.2.1 marc if (sc->handle[0].flags & PCIC_FLAG_SOCKETP) {
473 1.1.2.1 marc sc->handle[0].vendor = vendor;
474 1.1.2.1 marc pcic_attach_socket(&sc->handle[0]);
475 1.1.2.1 marc }
476 1.1.2.1 marc if (sc->handle[1].flags & PCIC_FLAG_SOCKETP) {
477 1.1.2.1 marc sc->handle[1].vendor = vendor;
478 1.1.2.1 marc pcic_attach_socket(&sc->handle[1]);
479 1.1.2.1 marc }
480 1.1.2.1 marc }
481 1.1.2.1 marc
482 1.1.2.1 marc if ((sc->handle[2].flags & PCIC_FLAG_SOCKETP) ||
483 1.1.2.1 marc (sc->handle[3].flags & PCIC_FLAG_SOCKETP)) {
484 1.1.2.1 marc vendor = pcic_vendor(&sc->handle[2]);
485 1.1.2.1 marc
486 1.1.2.1 marc printf("%s: controller 1 (%s) has ", sc->dev.dv_xname,
487 1.1.2.1 marc pcic_vendor_to_string(vendor));
488 1.1.2.1 marc
489 1.1.2.1 marc if ((sc->handle[2].flags & PCIC_FLAG_SOCKETP) &&
490 1.1.2.1 marc (sc->handle[3].flags & PCIC_FLAG_SOCKETP))
491 1.1.2.1 marc printf("sockets A and B\n");
492 1.1.2.1 marc else if (sc->handle[2].flags & PCIC_FLAG_SOCKETP)
493 1.1.2.1 marc printf("socket A only\n");
494 1.1.2.1 marc else
495 1.1.2.1 marc printf("socket B only\n");
496 1.1.2.1 marc
497 1.1.2.1 marc #if 0
498 1.1.2.1 marc pcic_write(&sc->handle[2], PCIC_GLOBAL_CTL,
499 1.1.2.1 marc PCIC_GLOBAL_CTL_EXPLICIT_CSC_ACK);
500 1.1.2.1 marc #endif
501 1.1.2.1 marc
502 1.1.2.1 marc if (sc->handle[2].flags & PCIC_FLAG_SOCKETP) {
503 1.1.2.1 marc pcic_attach_socket(&sc->handle[2]);
504 1.1.2.1 marc sc->handle[2].vendor = vendor;
505 1.1.2.1 marc }
506 1.1.2.1 marc if (sc->handle[3].flags & PCIC_FLAG_SOCKETP) {
507 1.1.2.1 marc pcic_attach_socket(&sc->handle[3]);
508 1.1.2.1 marc sc->handle[3].vendor = vendor;
509 1.1.2.1 marc }
510 1.1.2.1 marc }
511 1.1.2.1 marc }
512 1.1.2.1 marc
513 1.1.2.1 marc void
514 1.1.2.1 marc pcic_attach_socket(h)
515 1.1.2.1 marc struct pcic_handle *h;
516 1.1.2.1 marc {
517 1.1.2.1 marc struct pcmciabus_attach_args paa;
518 1.1.2.1 marc
519 1.1.2.1 marc /* initialize the rest of the handle */
520 1.1.2.1 marc
521 1.1.2.1 marc h->memalloc = 0;
522 1.1.2.1 marc h->ioalloc = 0;
523 1.1.2.1 marc
524 1.1.2.1 marc /* now, config one pcmcia device per socket */
525 1.1.2.1 marc
526 1.1.2.1 marc paa.pct = (pcmcia_chipset_tag_t) &pcic_functions;
527 1.1.2.1 marc paa.pch = (pcmcia_chipset_handle_t) h;
528 1.1.2.1 marc
529 1.1.2.1 marc h->pcmcia = config_found_sm(&h->sc->dev, &paa, pcic_print, pcic_submatch);
530 1.1.2.1 marc
531 1.1.2.1 marc /* if there's actually a pcmcia device attached, initialize the slot */
532 1.1.2.1 marc
533 1.1.2.1 marc if (h->pcmcia)
534 1.1.2.1 marc pcic_init_socket(h);
535 1.1.2.1 marc }
536 1.1.2.1 marc
537 1.1.2.1 marc void
538 1.1.2.1 marc pcic_init_socket(h)
539 1.1.2.1 marc struct pcic_handle *h;
540 1.1.2.1 marc {
541 1.1.2.1 marc int reg;
542 1.1.2.1 marc
543 1.1.2.1 marc /* set up the card to interrupt on card detect */
544 1.1.2.1 marc
545 1.1.2.1 marc pcic_write(h, PCIC_CSC_INTR,
546 1.1.2.1 marc (h->sc->irq<<PCIC_CSC_INTR_IRQ_SHIFT)|
547 1.1.2.1 marc PCIC_CSC_INTR_CD_ENABLE);
548 1.1.2.1 marc pcic_write(h, PCIC_INTR, 0);
549 1.1.2.1 marc pcic_read(h, PCIC_CSC);
550 1.1.2.1 marc
551 1.1.2.1 marc /* unsleep the cirrus controller */
552 1.1.2.1 marc
553 1.1.2.1 marc if ((h->vendor == PCIC_VENDOR_CIRRUS_PD6710) ||
554 1.1.2.1 marc (h->vendor == PCIC_VENDOR_CIRRUS_PD672X)) {
555 1.1.2.1 marc reg = pcic_read(h, PCIC_CIRRUS_MISC_CTL_2);
556 1.1.2.1 marc if (reg & PCIC_CIRRUS_MISC_CTL_2_SUSPEND) {
557 1.1.2.1 marc DPRINTF(("%s: socket %02x was suspended\n", h->sc->dev.dv_xname,
558 1.1.2.1 marc h->sock));
559 1.1.2.1 marc reg &= ~PCIC_CIRRUS_MISC_CTL_2_SUSPEND;
560 1.1.2.1 marc pcic_write(h, PCIC_CIRRUS_MISC_CTL_2, reg);
561 1.1.2.1 marc }
562 1.1.2.1 marc }
563 1.1.2.1 marc
564 1.1.2.1 marc /* if there's a card there, then attach it. */
565 1.1.2.1 marc
566 1.1.2.1 marc reg = pcic_read(h, PCIC_IF_STATUS);
567 1.1.2.1 marc
568 1.1.2.1 marc if ((reg & PCIC_IF_STATUS_CARDDETECT_MASK) ==
569 1.1.2.1 marc PCIC_IF_STATUS_CARDDETECT_PRESENT)
570 1.1.2.1 marc pcic_attach_card(h);
571 1.1.2.1 marc }
572 1.1.2.1 marc
573 1.1.2.1 marc int
574 1.1.2.1 marc #ifdef __BROKEN_INDIRECT_CONFIG
575 1.1.2.1 marc pcic_submatch(parent, match, aux)
576 1.1.2.1 marc #else
577 1.1.2.1 marc pcic_submatch(parent, cf, aux)
578 1.1.2.1 marc #endif
579 1.1.2.1 marc struct device *parent;
580 1.1.2.1 marc #ifdef __BROKEN_INDIRECT_CONFIG
581 1.1.2.1 marc void *match;
582 1.1.2.1 marc #else
583 1.1.2.1 marc struct cfdata *cf;
584 1.1.2.1 marc #endif
585 1.1.2.1 marc void *aux;
586 1.1.2.1 marc {
587 1.1.2.1 marc #ifdef __BROKEN_INDIRECT_CONFIG
588 1.1.2.1 marc struct cfdata *cf = match;
589 1.1.2.1 marc #endif
590 1.1.2.1 marc
591 1.1.2.1 marc struct pcmciabus_attach_args *paa = (struct pcmciabus_attach_args *) aux;
592 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) paa->pch;
593 1.1.2.1 marc
594 1.1.2.1 marc switch (h->sock) {
595 1.1.2.1 marc case C0SA:
596 1.1.2.1 marc if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != 0)
597 1.1.2.1 marc return 0;
598 1.1.2.1 marc if (cf->cf_loc[1] != -1 && cf->cf_loc[1] != 0)
599 1.1.2.1 marc return 0;
600 1.1.2.1 marc
601 1.1.2.1 marc break;
602 1.1.2.1 marc case C0SB:
603 1.1.2.1 marc if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != 0)
604 1.1.2.1 marc return 0;
605 1.1.2.1 marc if (cf->cf_loc[1] != -1 && cf->cf_loc[1] != 1)
606 1.1.2.1 marc return 0;
607 1.1.2.1 marc
608 1.1.2.1 marc break;
609 1.1.2.1 marc case C1SA:
610 1.1.2.1 marc if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != 1)
611 1.1.2.1 marc return 0;
612 1.1.2.1 marc if (cf->cf_loc[1] != -1 && cf->cf_loc[1] != 0)
613 1.1.2.1 marc return 0;
614 1.1.2.1 marc
615 1.1.2.1 marc break;
616 1.1.2.1 marc case C1SB:
617 1.1.2.1 marc if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != 1)
618 1.1.2.1 marc return 0;
619 1.1.2.1 marc if (cf->cf_loc[1] != -1 && cf->cf_loc[1] != 1)
620 1.1.2.1 marc return 0;
621 1.1.2.1 marc
622 1.1.2.1 marc break;
623 1.1.2.1 marc default:
624 1.1.2.1 marc panic("unknown pcic socket");
625 1.1.2.1 marc }
626 1.1.2.1 marc
627 1.1.2.1 marc return ((*cf->cf_attach->ca_match)(parent, cf, aux));
628 1.1.2.1 marc }
629 1.1.2.1 marc
630 1.1.2.1 marc int
631 1.1.2.1 marc pcic_print(arg, pnp)
632 1.1.2.1 marc void *arg;
633 1.1.2.1 marc const char *pnp;
634 1.1.2.1 marc {
635 1.1.2.1 marc struct pcmciabus_attach_args *paa = (struct pcmciabus_attach_args *) arg;
636 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) paa->pch;
637 1.1.2.1 marc
638 1.1.2.1 marc if (pnp)
639 1.1.2.1 marc printf("pcmcia at %s", pnp);
640 1.1.2.1 marc
641 1.1.2.1 marc switch (h->sock) {
642 1.1.2.1 marc case C0SA:
643 1.1.2.1 marc printf(" controller 0 socket 0");
644 1.1.2.1 marc break;
645 1.1.2.1 marc case C0SB:
646 1.1.2.1 marc printf(" controller 0 socket 1");
647 1.1.2.1 marc break;
648 1.1.2.1 marc case C1SA:
649 1.1.2.1 marc printf(" controller 1 socket 0");
650 1.1.2.1 marc break;
651 1.1.2.1 marc case C1SB:
652 1.1.2.1 marc printf(" controller 1 socket 1");
653 1.1.2.1 marc break;
654 1.1.2.1 marc default:
655 1.1.2.1 marc panic("unknown pcic socket");
656 1.1.2.1 marc }
657 1.1.2.1 marc
658 1.1.2.1 marc return(UNCONF);
659 1.1.2.1 marc }
660 1.1.2.1 marc
661 1.1.2.1 marc int
662 1.1.2.1 marc pcic_intr(arg)
663 1.1.2.1 marc void *arg;
664 1.1.2.1 marc {
665 1.1.2.1 marc struct pcic_softc *sc = (struct pcic_softc *) arg;
666 1.1.2.1 marc int i, ret = 0;
667 1.1.2.1 marc
668 1.1.2.1 marc DPRINTF(("%s: intr\n", sc->dev.dv_xname));
669 1.1.2.1 marc
670 1.1.2.1 marc for (i=0; i<PCIC_NSLOTS; i++)
671 1.1.2.1 marc if (sc->handle[i].flags & PCIC_FLAG_SOCKETP)
672 1.1.2.1 marc ret += pcic_intr_socket(&sc->handle[i]);
673 1.1.2.1 marc
674 1.1.2.1 marc return(ret?1:0);
675 1.1.2.1 marc }
676 1.1.2.1 marc
677 1.1.2.1 marc int
678 1.1.2.1 marc pcic_intr_socket(h)
679 1.1.2.1 marc struct pcic_handle *h;
680 1.1.2.1 marc {
681 1.1.2.1 marc int cscreg;
682 1.1.2.1 marc
683 1.1.2.1 marc cscreg = pcic_read(h, PCIC_CSC);
684 1.1.2.1 marc
685 1.1.2.1 marc cscreg &= (PCIC_CSC_GPI |
686 1.1.2.1 marc PCIC_CSC_CD |
687 1.1.2.1 marc PCIC_CSC_READY |
688 1.1.2.1 marc PCIC_CSC_BATTWARN |
689 1.1.2.1 marc PCIC_CSC_BATTDEAD);
690 1.1.2.1 marc
691 1.1.2.1 marc if (cscreg & PCIC_CSC_GPI) {
692 1.1.2.1 marc DPRINTF(("%s: %02x GPI\n", h->sc->dev.dv_xname, h->sock));
693 1.1.2.1 marc }
694 1.1.2.1 marc if (cscreg & PCIC_CSC_CD) {
695 1.1.2.1 marc int statreg;
696 1.1.2.1 marc
697 1.1.2.1 marc statreg = pcic_read(h, PCIC_IF_STATUS);
698 1.1.2.1 marc
699 1.1.2.1 marc DPRINTF(("%s: %02x CD %x\n", h->sc->dev.dv_xname, h->sock,
700 1.1.2.1 marc statreg));
701 1.1.2.1 marc
702 1.1.2.1 marc if ((statreg & PCIC_IF_STATUS_CARDDETECT_MASK) ==
703 1.1.2.1 marc PCIC_IF_STATUS_CARDDETECT_PRESENT) {
704 1.1.2.1 marc if (!(h->flags & PCIC_FLAG_CARDP))
705 1.1.2.1 marc pcic_attach_card(h);
706 1.1.2.1 marc } else {
707 1.1.2.1 marc if (h->flags & PCIC_FLAG_CARDP)
708 1.1.2.1 marc pcic_detach_card(h);
709 1.1.2.1 marc }
710 1.1.2.1 marc }
711 1.1.2.1 marc if (cscreg & PCIC_CSC_READY) {
712 1.1.2.1 marc DPRINTF(("%s: %02x READY\n", h->sc->dev.dv_xname, h->sock));
713 1.1.2.1 marc /* shouldn't happen */
714 1.1.2.1 marc }
715 1.1.2.1 marc if (cscreg & PCIC_CSC_BATTWARN) {
716 1.1.2.1 marc DPRINTF(("%s: %02x BATTWARN\n", h->sc->dev.dv_xname, h->sock));
717 1.1.2.1 marc }
718 1.1.2.1 marc if (cscreg & PCIC_CSC_BATTDEAD) {
719 1.1.2.1 marc DPRINTF(("%s: %02x BATTDEAD\n", h->sc->dev.dv_xname, h->sock));
720 1.1.2.1 marc }
721 1.1.2.1 marc
722 1.1.2.1 marc #if 0
723 1.1.2.1 marc /* ack the interrupt */
724 1.1.2.1 marc
725 1.1.2.1 marc pcic_write(h, PCIC_CSC, cscreg);
726 1.1.2.1 marc #endif
727 1.1.2.1 marc
728 1.1.2.1 marc return(cscreg?1:0);
729 1.1.2.1 marc }
730 1.1.2.1 marc
731 1.1.2.1 marc void
732 1.1.2.1 marc pcic_attach_card(h)
733 1.1.2.1 marc struct pcic_handle *h;
734 1.1.2.1 marc {
735 1.1.2.1 marc int iftype;
736 1.1.2.1 marc int reg;
737 1.1.2.1 marc
738 1.1.2.1 marc if (h->flags & PCIC_FLAG_CARDP)
739 1.1.2.1 marc panic("pcic_attach_card: already attached");
740 1.1.2.1 marc
741 1.1.2.1 marc /* power down the socket to reset it, clear the card reset pin */
742 1.1.2.1 marc
743 1.1.2.1 marc pcic_write(h, PCIC_PWRCTL, 0);
744 1.1.2.1 marc
745 1.1.2.1 marc /* power up the socket */
746 1.1.2.1 marc
747 1.1.2.1 marc pcic_write(h, PCIC_PWRCTL, PCIC_PWRCTL_PWR_ENABLE);
748 1.1.2.1 marc delay(10000);
749 1.1.2.1 marc pcic_write(h, PCIC_PWRCTL, PCIC_PWRCTL_PWR_ENABLE | PCIC_PWRCTL_OE);
750 1.1.2.1 marc
751 1.1.2.1 marc /* clear the reset flag */
752 1.1.2.1 marc
753 1.1.2.1 marc pcic_write(h, PCIC_INTR, PCIC_INTR_RESET);
754 1.1.2.1 marc
755 1.1.2.1 marc /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
756 1.1.2.1 marc
757 1.1.2.1 marc delay(20000);
758 1.1.2.1 marc
759 1.1.2.1 marc /* wait for the chip to finish initializing */
760 1.1.2.1 marc
761 1.1.2.1 marc pcic_wait_ready(h);
762 1.1.2.1 marc
763 1.1.2.1 marc /* zero out the address windows */
764 1.1.2.1 marc
765 1.1.2.1 marc pcic_write(h, PCIC_ADDRWIN_ENABLE, 0);
766 1.1.2.1 marc
767 1.1.2.1 marc #if 1
768 1.1.2.1 marc pcic_write(h, PCIC_INTR, PCIC_INTR_RESET | PCIC_INTR_CARDTYPE_IO);
769 1.1.2.1 marc #endif
770 1.1.2.1 marc
771 1.1.2.1 marc reg = pcic_read(h, PCIC_INTR);
772 1.1.2.1 marc
773 1.1.2.1 marc DPRINTF(("%s: %02x PCIC_INTR = %02x\n", h->sc->dev.dv_xname,
774 1.1.2.1 marc h->sock, reg));
775 1.1.2.1 marc
776 1.1.2.1 marc /* call the MI attach function */
777 1.1.2.1 marc
778 1.1.2.1 marc pcmcia_attach_card(h->pcmcia, &iftype);
779 1.1.2.1 marc
780 1.1.2.1 marc /* set the card type */
781 1.1.2.1 marc
782 1.1.2.1 marc DPRINTF(("%s: %02x cardtype %s\n", h->sc->dev.dv_xname, h->sock,
783 1.1.2.1 marc ((iftype == PCMCIA_IFTYPE_IO)?"io":"mem")));
784 1.1.2.1 marc
785 1.1.2.1 marc #if 0
786 1.1.2.1 marc reg = pcic_read(h, PCIC_INTR);
787 1.1.2.1 marc reg &= PCIC_INTR_CARDTYPE_MASK;
788 1.1.2.1 marc reg |= ((iftype == PCMCIA_IFTYPE_IO)?
789 1.1.2.1 marc PCIC_INTR_CARDTYPE_IO:
790 1.1.2.1 marc PCIC_INTR_CARDTYPE_MEM);
791 1.1.2.1 marc pcic_write(h, PCIC_INTR, reg);
792 1.1.2.1 marc #endif
793 1.1.2.1 marc
794 1.1.2.1 marc h->flags |= PCIC_FLAG_CARDP;
795 1.1.2.1 marc }
796 1.1.2.1 marc
797 1.1.2.1 marc void
798 1.1.2.1 marc pcic_detach_card(h)
799 1.1.2.1 marc struct pcic_handle *h;
800 1.1.2.1 marc {
801 1.1.2.1 marc if (!(h->flags & PCIC_FLAG_CARDP))
802 1.1.2.1 marc panic("pcic_attach_card: already attached");
803 1.1.2.1 marc
804 1.1.2.1 marc h->flags &= ~PCIC_FLAG_CARDP;
805 1.1.2.1 marc
806 1.1.2.1 marc /* call the MI attach function */
807 1.1.2.1 marc
808 1.1.2.1 marc pcmcia_detach_card(h->pcmcia);
809 1.1.2.1 marc
810 1.1.2.1 marc /* disable card detect resume and configuration reset */
811 1.1.2.1 marc
812 1.1.2.1 marc #if 0
813 1.1.2.1 marc pcic_write(h, PCIC_CARD_DETECT, 0);
814 1.1.2.1 marc #endif
815 1.1.2.1 marc
816 1.1.2.1 marc /* power down the socket */
817 1.1.2.1 marc
818 1.1.2.1 marc pcic_write(h, PCIC_PWRCTL, 0);
819 1.1.2.1 marc
820 1.1.2.1 marc /* reset the card */
821 1.1.2.1 marc
822 1.1.2.1 marc pcic_write(h, PCIC_INTR, 0);
823 1.1.2.1 marc }
824 1.1.2.1 marc
825 1.1.2.4 thorpej int pcic_chip_mem_alloc(pch, size, pcmhp)
826 1.1.2.1 marc pcmcia_chipset_handle_t pch;
827 1.1.2.1 marc bus_size_t size;
828 1.1.2.4 thorpej struct pcmcia_mem_handle *pcmhp;
829 1.1.2.1 marc {
830 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) pch;
831 1.1.2.4 thorpej bus_space_handle_t memh;
832 1.1.2.4 thorpej bus_addr_t addr;
833 1.1.2.4 thorpej bus_size_t sizepg;
834 1.1.2.4 thorpej int i, mask, mhandle;
835 1.1.2.1 marc
836 1.1.2.1 marc /* out of sc->memh, allocate as many pages as necessary */
837 1.1.2.1 marc
838 1.1.2.4 thorpej /* convert size to PCIC pages */
839 1.1.2.4 thorpej sizepg = (size + (PCIC_MEM_ALIGN - 1)) / PCIC_MEM_ALIGN;
840 1.1.2.1 marc
841 1.1.2.4 thorpej mask = (1 << sizepg) - 1;
842 1.1.2.1 marc
843 1.1.2.4 thorpej addr = 0; /* XXX gcc -Wuninitialized */
844 1.1.2.4 thorpej mhandle = 0; /* XXX gcc -Wuninitialized */
845 1.1.2.4 thorpej for (i=0; i<(PCIC_MEM_PAGES+1-sizepg); i++) {
846 1.1.2.1 marc if ((h->sc->subregionmask & (mask<<i)) == (mask<<i)) {
847 1.1.2.1 marc if (bus_space_subregion(h->sc->memt, h->sc->memh,
848 1.1.2.1 marc i*PCIC_MEM_PAGESIZE,
849 1.1.2.4 thorpej sizepg*PCIC_MEM_PAGESIZE, &memh))
850 1.1.2.1 marc return(1);
851 1.1.2.4 thorpej mhandle = mask << i;
852 1.1.2.4 thorpej addr = h->sc->membase + (i * PCIC_MEM_PAGESIZE);
853 1.1.2.4 thorpej h->sc->subregionmask &= ~(mhandle);
854 1.1.2.1 marc break;
855 1.1.2.1 marc }
856 1.1.2.1 marc }
857 1.1.2.1 marc
858 1.1.2.1 marc if (i == (PCIC_MEM_PAGES+1-size))
859 1.1.2.1 marc return(1);
860 1.1.2.1 marc
861 1.1.2.4 thorpej DPRINTF(("pcic_chip_mem_alloc bus addr 0x%lx+0x%lx\n", (u_long)addr,
862 1.1.2.4 thorpej (u_long)size));
863 1.1.2.4 thorpej
864 1.1.2.4 thorpej pcmhp->memt = h->sc->memt;
865 1.1.2.4 thorpej pcmhp->memh = memh;
866 1.1.2.4 thorpej pcmhp->addr = addr;
867 1.1.2.4 thorpej pcmhp->size = size;
868 1.1.2.4 thorpej pcmhp->mhandle = mhandle;
869 1.1.2.4 thorpej pcmhp->realsize = sizepg * PCIC_MEM_PAGESIZE;
870 1.1.2.1 marc
871 1.1.2.1 marc return(0);
872 1.1.2.1 marc }
873 1.1.2.1 marc
874 1.1.2.4 thorpej void pcic_chip_mem_free(pch, pcmhp)
875 1.1.2.1 marc pcmcia_chipset_handle_t pch;
876 1.1.2.4 thorpej struct pcmcia_mem_handle *pcmhp;
877 1.1.2.1 marc {
878 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) pch;
879 1.1.2.1 marc
880 1.1.2.4 thorpej h->sc->subregionmask |= pcmhp->mhandle;
881 1.1.2.1 marc }
882 1.1.2.1 marc
883 1.1.2.1 marc static struct mem_map_index_st {
884 1.1.2.1 marc int sysmem_start_lsb;
885 1.1.2.1 marc int sysmem_start_msb;
886 1.1.2.1 marc int sysmem_stop_lsb;
887 1.1.2.1 marc int sysmem_stop_msb;
888 1.1.2.1 marc int cardmem_lsb;
889 1.1.2.1 marc int cardmem_msb;
890 1.1.2.1 marc int memenable;
891 1.1.2.1 marc } mem_map_index[] = {
892 1.1.2.1 marc {
893 1.1.2.1 marc PCIC_SYSMEM_ADDR0_START_LSB,
894 1.1.2.1 marc PCIC_SYSMEM_ADDR0_START_MSB,
895 1.1.2.1 marc PCIC_SYSMEM_ADDR0_STOP_LSB,
896 1.1.2.1 marc PCIC_SYSMEM_ADDR0_STOP_MSB,
897 1.1.2.1 marc PCIC_CARDMEM_ADDR0_LSB,
898 1.1.2.1 marc PCIC_CARDMEM_ADDR0_MSB,
899 1.1.2.1 marc PCIC_ADDRWIN_ENABLE_MEM0,
900 1.1.2.1 marc },
901 1.1.2.1 marc {
902 1.1.2.1 marc PCIC_SYSMEM_ADDR1_START_LSB,
903 1.1.2.1 marc PCIC_SYSMEM_ADDR1_START_MSB,
904 1.1.2.1 marc PCIC_SYSMEM_ADDR1_STOP_LSB,
905 1.1.2.1 marc PCIC_SYSMEM_ADDR1_STOP_MSB,
906 1.1.2.1 marc PCIC_CARDMEM_ADDR1_LSB,
907 1.1.2.1 marc PCIC_CARDMEM_ADDR1_MSB,
908 1.1.2.1 marc PCIC_ADDRWIN_ENABLE_MEM1,
909 1.1.2.1 marc },
910 1.1.2.1 marc {
911 1.1.2.1 marc PCIC_SYSMEM_ADDR2_START_LSB,
912 1.1.2.1 marc PCIC_SYSMEM_ADDR2_START_MSB,
913 1.1.2.1 marc PCIC_SYSMEM_ADDR2_STOP_LSB,
914 1.1.2.1 marc PCIC_SYSMEM_ADDR2_STOP_MSB,
915 1.1.2.1 marc PCIC_CARDMEM_ADDR2_LSB,
916 1.1.2.1 marc PCIC_CARDMEM_ADDR2_MSB,
917 1.1.2.1 marc PCIC_ADDRWIN_ENABLE_MEM2,
918 1.1.2.1 marc },
919 1.1.2.1 marc {
920 1.1.2.1 marc PCIC_SYSMEM_ADDR3_START_LSB,
921 1.1.2.1 marc PCIC_SYSMEM_ADDR3_START_MSB,
922 1.1.2.1 marc PCIC_SYSMEM_ADDR3_STOP_LSB,
923 1.1.2.1 marc PCIC_SYSMEM_ADDR3_STOP_MSB,
924 1.1.2.1 marc PCIC_CARDMEM_ADDR3_LSB,
925 1.1.2.1 marc PCIC_CARDMEM_ADDR3_MSB,
926 1.1.2.1 marc PCIC_ADDRWIN_ENABLE_MEM3,
927 1.1.2.1 marc },
928 1.1.2.1 marc {
929 1.1.2.1 marc PCIC_SYSMEM_ADDR4_START_LSB,
930 1.1.2.1 marc PCIC_SYSMEM_ADDR4_START_MSB,
931 1.1.2.1 marc PCIC_SYSMEM_ADDR4_STOP_LSB,
932 1.1.2.1 marc PCIC_SYSMEM_ADDR4_STOP_MSB,
933 1.1.2.1 marc PCIC_CARDMEM_ADDR4_LSB,
934 1.1.2.1 marc PCIC_CARDMEM_ADDR4_MSB,
935 1.1.2.1 marc PCIC_ADDRWIN_ENABLE_MEM4,
936 1.1.2.1 marc },
937 1.1.2.1 marc };
938 1.1.2.1 marc
939 1.1.2.4 thorpej int pcic_chip_mem_map(pch, kind, card_addr, size, pcmhp, offsetp, windowp)
940 1.1.2.1 marc pcmcia_chipset_handle_t pch;
941 1.1.2.1 marc int kind;
942 1.1.2.4 thorpej bus_addr_t card_addr;
943 1.1.2.1 marc bus_size_t size;
944 1.1.2.4 thorpej struct pcmcia_mem_handle *pcmhp;
945 1.1.2.4 thorpej bus_addr_t *offsetp;
946 1.1.2.4 thorpej int *windowp;
947 1.1.2.1 marc {
948 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) pch;
949 1.1.2.1 marc int reg;
950 1.1.2.4 thorpej bus_addr_t busaddr;
951 1.1.2.1 marc long card_offset;
952 1.1.2.1 marc int i, win;
953 1.1.2.1 marc
954 1.1.2.1 marc win = -1;
955 1.1.2.1 marc for (i=0; i<(sizeof(mem_map_index)/sizeof(mem_map_index[0])); i++) {
956 1.1.2.1 marc if ((h->memalloc & (1<<i)) == 0) {
957 1.1.2.1 marc win = i;
958 1.1.2.1 marc h->memalloc |= (1<<i);
959 1.1.2.1 marc break;
960 1.1.2.1 marc }
961 1.1.2.1 marc }
962 1.1.2.1 marc
963 1.1.2.1 marc if (win == -1)
964 1.1.2.1 marc return(1);
965 1.1.2.1 marc
966 1.1.2.4 thorpej *windowp = win;
967 1.1.2.1 marc
968 1.1.2.1 marc /* XXX this is pretty gross */
969 1.1.2.1 marc
970 1.1.2.4 thorpej if (h->sc->memt != pcmhp->memt)
971 1.1.2.1 marc panic("pcic_chip_mem_map memt is bogus");
972 1.1.2.1 marc
973 1.1.2.4 thorpej busaddr = pcmhp->addr;
974 1.1.2.1 marc
975 1.1.2.1 marc /* compute the address offset to the pcmcia address space for the
976 1.1.2.1 marc pcic. this is intentionally signed. The masks and shifts
977 1.1.2.1 marc below will cause TRT to happen in the pcic registers. Deal with
978 1.1.2.1 marc making sure the address is aligned, and return the alignment
979 1.1.2.1 marc offset. */
980 1.1.2.1 marc
981 1.1.2.4 thorpej *offsetp = card_addr % PCIC_MEM_ALIGN;
982 1.1.2.4 thorpej card_addr -= *offsetp;
983 1.1.2.1 marc
984 1.1.2.4 thorpej DPRINTF(("pcic_chip_mem_map window %d bus %lx+%lx+%lx at card addr %lx\n",
985 1.1.2.4 thorpej win, (u_long)busaddr, (u_long)*offsetp, (u_long)size,
986 1.1.2.4 thorpej (u_long)card_addr));
987 1.1.2.1 marc
988 1.1.2.1 marc /* include the offset in the size, and decrement size by one,
989 1.1.2.1 marc since the hw wants start/stop */
990 1.1.2.4 thorpej size += *offsetp - 1;
991 1.1.2.1 marc
992 1.1.2.4 thorpej card_offset = (((long) card_addr) - ((long) busaddr));
993 1.1.2.1 marc
994 1.1.2.1 marc pcic_write(h, mem_map_index[win].sysmem_start_lsb,
995 1.1.2.4 thorpej (busaddr >> PCIC_SYSMEM_ADDRX_SHIFT) & 0xff);
996 1.1.2.1 marc pcic_write(h, mem_map_index[win].sysmem_start_msb,
997 1.1.2.4 thorpej ((busaddr >> (PCIC_SYSMEM_ADDRX_SHIFT + 8)) &
998 1.1.2.1 marc PCIC_SYSMEM_ADDRX_START_MSB_ADDR_MASK));
999 1.1.2.1 marc
1000 1.1.2.1 marc #if 0
1001 1.1.2.1 marc /* XXX do I want 16 bit all the time? */
1002 1.1.2.1 marc PCIC_SYSMEM_ADDRX_START_MSB_DATASIZE_16BIT;
1003 1.1.2.1 marc #endif
1004 1.1.2.1 marc
1005 1.1.2.1 marc pcic_write(h, mem_map_index[win].sysmem_stop_lsb,
1006 1.1.2.4 thorpej ((busaddr + size) >> PCIC_SYSMEM_ADDRX_SHIFT) & 0xff);
1007 1.1.2.1 marc pcic_write(h, mem_map_index[win].sysmem_stop_msb,
1008 1.1.2.4 thorpej (((busaddr + size) >> (PCIC_SYSMEM_ADDRX_SHIFT + 8)) &
1009 1.1.2.1 marc PCIC_SYSMEM_ADDRX_STOP_MSB_ADDR_MASK) |
1010 1.1.2.1 marc PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT2);
1011 1.1.2.1 marc
1012 1.1.2.1 marc
1013 1.1.2.1 marc pcic_write(h, mem_map_index[win].cardmem_lsb,
1014 1.1.2.1 marc (card_offset >> PCIC_CARDMEM_ADDRX_SHIFT) & 0xff);
1015 1.1.2.1 marc pcic_write(h, mem_map_index[win].cardmem_msb,
1016 1.1.2.1 marc ((card_offset >> (PCIC_CARDMEM_ADDRX_SHIFT + 8)) &
1017 1.1.2.1 marc PCIC_CARDMEM_ADDRX_MSB_ADDR_MASK) |
1018 1.1.2.1 marc ((kind == PCMCIA_MEM_ATTR)?
1019 1.1.2.1 marc PCIC_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR:0));
1020 1.1.2.1 marc
1021 1.1.2.1 marc reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
1022 1.1.2.1 marc reg |= (mem_map_index[win].memenable | PCIC_ADDRWIN_ENABLE_MEMCS16 );
1023 1.1.2.1 marc pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
1024 1.1.2.1 marc
1025 1.1.2.1 marc #ifdef PCICDEBUG
1026 1.1.2.1 marc {
1027 1.1.2.1 marc int r1,r2,r3,r4,r5,r6;
1028 1.1.2.1 marc
1029 1.1.2.1 marc r1 = pcic_read(h, mem_map_index[win].sysmem_start_msb);
1030 1.1.2.1 marc r2 = pcic_read(h, mem_map_index[win].sysmem_start_lsb);
1031 1.1.2.1 marc r3 = pcic_read(h, mem_map_index[win].sysmem_stop_msb);
1032 1.1.2.1 marc r4 = pcic_read(h, mem_map_index[win].sysmem_stop_lsb);
1033 1.1.2.1 marc r5 = pcic_read(h, mem_map_index[win].cardmem_msb);
1034 1.1.2.1 marc r6 = pcic_read(h, mem_map_index[win].cardmem_lsb);
1035 1.1.2.1 marc
1036 1.1.2.1 marc DPRINTF(("pcic_chip_mem_map window %d: %02x%02x %02x%02x %02x%02x\n",
1037 1.1.2.1 marc win, r1, r2, r3, r4, r5, r6));
1038 1.1.2.1 marc }
1039 1.1.2.1 marc #endif
1040 1.1.2.1 marc
1041 1.1.2.1 marc return(0);
1042 1.1.2.1 marc }
1043 1.1.2.1 marc
1044 1.1.2.1 marc void pcic_chip_mem_unmap(pch, window)
1045 1.1.2.1 marc pcmcia_chipset_handle_t pch;
1046 1.1.2.1 marc int window;
1047 1.1.2.1 marc {
1048 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) pch;
1049 1.1.2.1 marc int reg;
1050 1.1.2.1 marc
1051 1.1.2.1 marc if (window >= (sizeof(mem_map_index)/sizeof(mem_map_index[0])))
1052 1.1.2.1 marc panic("pcic_chip_mem_unmap: window out of range");
1053 1.1.2.1 marc
1054 1.1.2.1 marc reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
1055 1.1.2.1 marc reg &= ~mem_map_index[window].memenable;
1056 1.1.2.1 marc pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
1057 1.1.2.1 marc
1058 1.1.2.4 thorpej h->memalloc &= ~(1 << window);
1059 1.1.2.1 marc }
1060 1.1.2.1 marc
1061 1.1.2.1 marc
1062 1.1.2.6 jtk /* XXX mycroft recommends this I/O space range. I should put this
1063 1.1.2.6 jtk in a header somewhere */
1064 1.1.2.6 jtk
1065 1.1.2.6 jtk /* XXX some hardware doesn't seem to grok addresses in 0x400 range--
1066 1.1.2.6 jtk apparently missing a bit or more of address lines.
1067 1.1.2.6 jtk (e.g. CIRRUS_PD672X with Linksys EthernetCard ne2000 clone in TI
1068 1.1.2.6 jtk TravelMate 5000--not clear which is at fault)
1069 1.1.2.6 jtk
1070 1.1.2.6 jtk Allow them to be overridden by patching a kernel and/or by a config
1071 1.1.2.6 jtk file option */
1072 1.1.2.6 jtk
1073 1.1.2.6 jtk #ifndef PCIC_ALLOC_IOBASE
1074 1.1.2.6 jtk #define PCIC_ALLOC_IOBASE 0x400
1075 1.1.2.6 jtk #endif
1076 1.1.2.6 jtk
1077 1.1.2.6 jtk int pcic_alloc_iobase = PCIC_ALLOC_IOBASE;
1078 1.1.2.6 jtk
1079 1.1.2.4 thorpej int pcic_chip_io_alloc(pch, start, size, pcihp)
1080 1.1.2.1 marc pcmcia_chipset_handle_t pch;
1081 1.1.2.1 marc bus_addr_t start;
1082 1.1.2.1 marc bus_size_t size;
1083 1.1.2.4 thorpej struct pcmcia_io_handle *pcihp;
1084 1.1.2.1 marc {
1085 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) pch;
1086 1.1.2.4 thorpej bus_space_tag_t iot;
1087 1.1.2.4 thorpej bus_space_handle_t ioh;
1088 1.1.2.1 marc bus_addr_t ioaddr;
1089 1.1.2.4 thorpej int flags = 0;
1090 1.1.2.1 marc
1091 1.1.2.1 marc /*
1092 1.1.2.1 marc * Allocate some arbitrary I/O space. XXX There really should be a
1093 1.1.2.1 marc * generic isa interface to this, but there isn't currently one
1094 1.1.2.1 marc */
1095 1.1.2.1 marc
1096 1.1.2.4 thorpej iot = h->sc->iot;
1097 1.1.2.1 marc
1098 1.1.2.1 marc if (start) {
1099 1.1.2.4 thorpej ioaddr = start;
1100 1.1.2.4 thorpej if (bus_space_map(iot, start, size, 0, &ioh))
1101 1.1.2.1 marc return(1);
1102 1.1.2.1 marc DPRINTF(("pcic_chip_io_alloc map port %lx+%lx\n",
1103 1.1.2.4 thorpej (u_long) ioaddr, (u_long) size));
1104 1.1.2.1 marc } else {
1105 1.1.2.4 thorpej flags |= PCMCIA_IO_ALLOCATED;
1106 1.1.2.6 jtk if (bus_space_alloc(iot, pcic_alloc_iobase, 0xfff, size, size,
1107 1.1.2.4 thorpej 0, 0, &ioaddr, &ioh))
1108 1.1.2.1 marc return(1);
1109 1.1.2.1 marc DPRINTF(("pcic_chip_io_alloc alloc port %lx+%lx\n",
1110 1.1.2.1 marc (u_long) ioaddr, (u_long) size));
1111 1.1.2.1 marc }
1112 1.1.2.1 marc
1113 1.1.2.4 thorpej pcihp->iot = iot;
1114 1.1.2.4 thorpej pcihp->ioh = ioh;
1115 1.1.2.4 thorpej pcihp->addr = ioaddr;
1116 1.1.2.4 thorpej pcihp->size = size;
1117 1.1.2.4 thorpej pcihp->flags = flags;
1118 1.1.2.4 thorpej
1119 1.1.2.1 marc return(0);
1120 1.1.2.1 marc }
1121 1.1.2.1 marc
1122 1.1.2.4 thorpej void pcic_chip_io_free(pch, pcihp)
1123 1.1.2.1 marc pcmcia_chipset_handle_t pch;
1124 1.1.2.4 thorpej struct pcmcia_io_handle *pcihp;
1125 1.1.2.1 marc {
1126 1.1.2.4 thorpej bus_space_tag_t iot = pcihp->iot;
1127 1.1.2.4 thorpej bus_space_handle_t ioh = pcihp->ioh;
1128 1.1.2.4 thorpej bus_size_t size = pcihp->size;
1129 1.1.2.4 thorpej
1130 1.1.2.4 thorpej if (pcihp->flags & PCMCIA_IO_ALLOCATED)
1131 1.1.2.4 thorpej bus_space_free(iot, ioh, size);
1132 1.1.2.4 thorpej else
1133 1.1.2.4 thorpej bus_space_unmap(iot, ioh, size);
1134 1.1.2.1 marc }
1135 1.1.2.1 marc
1136 1.1.2.1 marc
1137 1.1.2.1 marc static struct io_map_index_st {
1138 1.1.2.1 marc int start_lsb;
1139 1.1.2.1 marc int start_msb;
1140 1.1.2.1 marc int stop_lsb;
1141 1.1.2.1 marc int stop_msb;
1142 1.1.2.1 marc int ioenable;
1143 1.1.2.1 marc int ioctlmask;
1144 1.1.2.1 marc int ioctl8;
1145 1.1.2.1 marc int ioctl16;
1146 1.1.2.1 marc } io_map_index[] = {
1147 1.1.2.1 marc {
1148 1.1.2.1 marc PCIC_IOADDR0_START_LSB,
1149 1.1.2.1 marc PCIC_IOADDR0_START_MSB,
1150 1.1.2.1 marc PCIC_IOADDR0_STOP_LSB,
1151 1.1.2.1 marc PCIC_IOADDR0_STOP_MSB,
1152 1.1.2.1 marc PCIC_ADDRWIN_ENABLE_IO0,
1153 1.1.2.1 marc PCIC_IOCTL_IO0_WAITSTATE | PCIC_IOCTL_IO0_ZEROWAIT |
1154 1.1.2.1 marc PCIC_IOCTL_IO0_IOCS16SRC_MASK | PCIC_IOCTL_IO0_DATASIZE_MASK,
1155 1.1.2.1 marc PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE | PCIC_IOCTL_IO0_DATASIZE_8BIT,
1156 1.1.2.1 marc PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE | PCIC_IOCTL_IO0_DATASIZE_16BIT,
1157 1.1.2.1 marc },
1158 1.1.2.1 marc {
1159 1.1.2.1 marc PCIC_IOADDR1_START_LSB,
1160 1.1.2.1 marc PCIC_IOADDR1_START_MSB,
1161 1.1.2.1 marc PCIC_IOADDR1_STOP_LSB,
1162 1.1.2.1 marc PCIC_IOADDR1_STOP_MSB,
1163 1.1.2.1 marc PCIC_ADDRWIN_ENABLE_IO1,
1164 1.1.2.1 marc PCIC_IOCTL_IO1_WAITSTATE | PCIC_IOCTL_IO1_ZEROWAIT |
1165 1.1.2.1 marc PCIC_IOCTL_IO1_IOCS16SRC_MASK | PCIC_IOCTL_IO1_DATASIZE_MASK,
1166 1.1.2.1 marc PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE | PCIC_IOCTL_IO1_DATASIZE_8BIT,
1167 1.1.2.1 marc PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE | PCIC_IOCTL_IO1_DATASIZE_16BIT,
1168 1.1.2.1 marc },
1169 1.1.2.1 marc };
1170 1.1.2.1 marc
1171 1.1.2.4 thorpej int pcic_chip_io_map(pch, width, offset, size, pcihp, windowp)
1172 1.1.2.1 marc pcmcia_chipset_handle_t pch;
1173 1.1.2.1 marc int width;
1174 1.1.2.4 thorpej bus_addr_t offset;
1175 1.1.2.1 marc bus_size_t size;
1176 1.1.2.4 thorpej struct pcmcia_io_handle *pcihp;
1177 1.1.2.4 thorpej int *windowp;
1178 1.1.2.1 marc {
1179 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) pch;
1180 1.1.2.4 thorpej bus_addr_t ioaddr = pcihp->addr + offset;
1181 1.1.2.1 marc int reg;
1182 1.1.2.1 marc int i, win;
1183 1.1.2.1 marc
1184 1.1.2.4 thorpej /* XXX Sanity check offset/size. */
1185 1.1.2.4 thorpej
1186 1.1.2.1 marc win = -1;
1187 1.1.2.1 marc for (i=0; i<(sizeof(io_map_index)/sizeof(io_map_index[0])); i++) {
1188 1.1.2.1 marc if ((h->ioalloc & (1<<i)) == 0) {
1189 1.1.2.1 marc win = i;
1190 1.1.2.1 marc h->ioalloc |= (1<<i);
1191 1.1.2.1 marc break;
1192 1.1.2.1 marc }
1193 1.1.2.1 marc }
1194 1.1.2.1 marc
1195 1.1.2.1 marc if (win == -1)
1196 1.1.2.1 marc return(1);
1197 1.1.2.1 marc
1198 1.1.2.4 thorpej *windowp = win;
1199 1.1.2.1 marc
1200 1.1.2.1 marc /* XXX this is pretty gross */
1201 1.1.2.1 marc
1202 1.1.2.4 thorpej if (h->sc->iot != pcihp->iot)
1203 1.1.2.1 marc panic("pcic_chip_io_map iot is bogus");
1204 1.1.2.1 marc
1205 1.1.2.1 marc DPRINTF(("pcic_chip_io_map window %d %s port %lx+%lx\n",
1206 1.1.2.1 marc win, (width == PCMCIA_WIDTH_IO8)?"io8":"io16",
1207 1.1.2.4 thorpej (u_long) ioaddr, (u_long) size));
1208 1.1.2.1 marc
1209 1.1.2.6 jtk printf(" port 0x%lx", (u_long)ioaddr);
1210 1.1.2.6 jtk if (size > 1)
1211 1.1.2.6 jtk printf("-0x%lx", (u_long)ioaddr + (u_long)size - 1);
1212 1.1.2.6 jtk
1213 1.1.2.4 thorpej pcic_write(h, io_map_index[win].start_lsb, ioaddr & 0xff);
1214 1.1.2.4 thorpej pcic_write(h, io_map_index[win].start_msb, (ioaddr >> 8) & 0xff);
1215 1.1.2.1 marc
1216 1.1.2.4 thorpej pcic_write(h, io_map_index[win].stop_lsb, (ioaddr + size - 1) & 0xff);
1217 1.1.2.4 thorpej pcic_write(h, io_map_index[win].stop_msb,
1218 1.1.2.4 thorpej ((ioaddr + size - 1) >> 8) & 0xff);
1219 1.1.2.1 marc
1220 1.1.2.1 marc reg = pcic_read(h, PCIC_IOCTL);
1221 1.1.2.1 marc reg &= ~io_map_index[win].ioctlmask;
1222 1.1.2.1 marc if (width == PCMCIA_WIDTH_IO8)
1223 1.1.2.1 marc reg |= io_map_index[win].ioctl8;
1224 1.1.2.1 marc else
1225 1.1.2.1 marc reg |= io_map_index[win].ioctl16;
1226 1.1.2.1 marc pcic_write(h, PCIC_IOCTL, reg);
1227 1.1.2.1 marc
1228 1.1.2.1 marc reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
1229 1.1.2.1 marc reg |= io_map_index[win].ioenable;
1230 1.1.2.1 marc pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
1231 1.1.2.1 marc
1232 1.1.2.1 marc return(0);
1233 1.1.2.1 marc }
1234 1.1.2.1 marc
1235 1.1.2.1 marc void pcic_chip_io_unmap(pch, window)
1236 1.1.2.1 marc pcmcia_chipset_handle_t pch;
1237 1.1.2.1 marc int window;
1238 1.1.2.1 marc {
1239 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) pch;
1240 1.1.2.1 marc int reg;
1241 1.1.2.1 marc
1242 1.1.2.1 marc if (window >= (sizeof(io_map_index)/sizeof(io_map_index[0])))
1243 1.1.2.1 marc panic("pcic_chip_io_unmap: window out of range");
1244 1.1.2.1 marc
1245 1.1.2.1 marc reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
1246 1.1.2.1 marc reg &= ~io_map_index[window].ioenable;
1247 1.1.2.1 marc pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
1248 1.1.2.1 marc
1249 1.1.2.4 thorpej h->ioalloc &= ~(1 << window);
1250 1.1.2.1 marc }
1251 1.1.2.6 jtk
1252 1.1.2.6 jtk /* allow patching or kernel option file override of available IRQs.
1253 1.1.2.6 jtk Useful if order of probing would screw up other devices, or if PCIC
1254 1.1.2.6 jtk hardware/cards have trouble with certain interrupt lines. */
1255 1.1.2.1 marc
1256 1.1.2.5 thorpej #ifndef PCIC_INTR_ALLOC_MASK
1257 1.1.2.5 thorpej #define PCIC_INTR_ALLOC_MASK 0xffff
1258 1.1.2.5 thorpej #endif
1259 1.1.2.5 thorpej
1260 1.1.2.5 thorpej int pcic_intr_alloc_mask = PCIC_INTR_ALLOC_MASK;
1261 1.1.2.5 thorpej
1262 1.1.2.1 marc void *
1263 1.1.2.5 thorpej pcic_chip_intr_establish(pch, pf, ipl, fct, arg)
1264 1.1.2.1 marc pcmcia_chipset_handle_t pch;
1265 1.1.2.5 thorpej struct pcmcia_function *pf;
1266 1.1.2.1 marc int ipl;
1267 1.1.2.1 marc int (*fct)(void *);
1268 1.1.2.1 marc void *arg;
1269 1.1.2.1 marc {
1270 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) pch;
1271 1.1.2.5 thorpej int irq, ist;
1272 1.1.2.1 marc void *ih;
1273 1.1.2.1 marc int reg;
1274 1.1.2.1 marc
1275 1.1.2.5 thorpej if (pf->cfe->flags & PCMCIA_CFE_IRQLEVEL)
1276 1.1.2.5 thorpej ist = IST_LEVEL;
1277 1.1.2.5 thorpej else if (pf->cfe->flags & PCMCIA_CFE_IRQPULSE)
1278 1.1.2.5 thorpej ist = IST_PULSE;
1279 1.1.2.5 thorpej else
1280 1.1.2.5 thorpej ist = IST_LEVEL;
1281 1.1.2.3 thorpej
1282 1.1.2.5 thorpej if (isa_intr_alloc(h->sc->ic,
1283 1.1.2.5 thorpej PCIC_INTR_IRQ_VALIDMASK & pcic_intr_alloc_mask,
1284 1.1.2.5 thorpej ist, &irq))
1285 1.1.2.5 thorpej return(NULL);
1286 1.1.2.5 thorpej if (!(ih = isa_intr_establish(h->sc->ic, irq, ist, ipl, fct, arg)))
1287 1.1.2.1 marc return(NULL);
1288 1.1.2.1 marc
1289 1.1.2.1 marc reg = pcic_read(h, PCIC_INTR);
1290 1.1.2.3 thorpej reg &= ~PCIC_INTR_IRQ_MASK;
1291 1.1.2.1 marc reg |= PCIC_INTR_ENABLE;
1292 1.1.2.1 marc reg |= irq;
1293 1.1.2.1 marc pcic_write(h, PCIC_INTR, reg);
1294 1.1.2.1 marc
1295 1.1.2.1 marc printf("%s: card irq %d\n", h->pcmcia->dv_xname, irq);
1296 1.1.2.1 marc
1297 1.1.2.1 marc return(ih);
1298 1.1.2.1 marc }
1299 1.1.2.1 marc
1300 1.1.2.1 marc void pcic_chip_intr_disestablish(pch, ih)
1301 1.1.2.1 marc pcmcia_chipset_handle_t pch;
1302 1.1.2.1 marc void *ih;
1303 1.1.2.1 marc {
1304 1.1.2.1 marc struct pcic_handle *h = (struct pcic_handle *) pch;
1305 1.1.2.3 thorpej int reg;
1306 1.1.2.3 thorpej
1307 1.1.2.3 thorpej reg = pcic_read(h, PCIC_INTR);
1308 1.1.2.3 thorpej reg &= ~(PCIC_INTR_IRQ_MASK|PCIC_INTR_ENABLE);
1309 1.1.2.3 thorpej pcic_write(h, PCIC_INTR, reg);
1310 1.1.2.1 marc
1311 1.1.2.1 marc isa_intr_disestablish(h->sc->ic, ih);
1312 1.1.2.7 thorpej }
1313 1.1.2.7 thorpej
1314 1.1.2.7 thorpej void
1315 1.1.2.7 thorpej pcic_chip_socket_enable(pch)
1316 1.1.2.7 thorpej pcmcia_chipset_handle_t pch;
1317 1.1.2.7 thorpej {
1318 1.1.2.7 thorpej }
1319 1.1.2.7 thorpej
1320 1.1.2.7 thorpej void
1321 1.1.2.7 thorpej pcic_chip_socket_disable(pch)
1322 1.1.2.7 thorpej pcmcia_chipset_handle_t pch;
1323 1.1.2.7 thorpej {
1324 1.1.2.1 marc }
1325