mmeyepcmcia.c revision 1.16 1 /* $NetBSD: mmeyepcmcia.c,v 1.16 2011/02/02 05:00:56 kiyohara Exp $ */
2
3 /*
4 * Copyright (c) 1997 Marc Horowitz. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Marc Horowitz.
17 * 4. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * PCMCIA I/F for MMEYE
34 *
35 * T.Horiuichi
36 * Brains Corp. 1998.8.25
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: mmeyepcmcia.c,v 1.16 2011/02/02 05:00:56 kiyohara Exp $");
41
42 #include <sys/types.h>
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/proc.h>
47 #include <sys/device.h>
48 #include <sys/extent.h>
49 #include <sys/malloc.h>
50 #include <sys/kthread.h>
51
52 #include <uvm/uvm_extern.h>
53
54 #include <machine/autoconf.h>
55 #include <machine/bus.h>
56 #include <machine/intr.h>
57 #include <machine/mmeye.h>
58
59 #include <dev/pcmcia/pcmciareg.h>
60 #include <dev/pcmcia/pcmciavar.h>
61 #include <dev/pcmcia/pcmciachip.h>
62
63 #include <mmeye/dev/mmeyepcmciareg.h>
64
65 #ifdef MMEYEPCMCIADEBUG
66 int mmeyepcmcia_debug = 1;
67 #define DPRINTF(arg) if (mmeyepcmcia_debug) printf arg;
68 #else
69 #define DPRINTF(arg)
70 #endif
71
72 struct mmeyepcmcia_event {
73 SIMPLEQ_ENTRY(mmeyepcmcia_event) pe_q;
74 int pe_type;
75 };
76
77 /* pe_type */
78 #define MMEYEPCMCIA_EVENT_INSERTION 0
79 #define MMEYEPCMCIA_EVENT_REMOVAL 1
80
81 struct mmeyepcmcia_handle {
82 struct mmeyepcmcia_softc *sc;
83 int flags;
84 int laststate;
85 int memalloc;
86 struct {
87 bus_addr_t addr;
88 bus_size_t size;
89 long offset;
90 int kind;
91 } mem[MMEYEPCMCIA_MEM_WINS];
92 int ioalloc;
93 struct {
94 bus_addr_t addr;
95 bus_size_t size;
96 int width;
97 } io[MMEYEPCMCIA_IO_WINS];
98 int ih_irq;
99 struct device *pcmcia;
100
101 int shutdown;
102 lwp_t *event_thread;
103 SIMPLEQ_HEAD(, mmeyepcmcia_event) events;
104 };
105
106 /* These four lines are MMTA specific */
107 #define MMEYEPCMCIA_IRQ1 10
108 #define MMEYEPCMCIA_IRQ2 9
109 #define MMEYEPCMCIA_SLOT1_ADDR 0xb8000000
110 #define MMEYEPCMCIA_SLOT2_ADDR 0xb9000000
111
112 #define MMEYEPCMCIA_FLAG_SOCKETP 0x0001
113 #define MMEYEPCMCIA_FLAG_CARDP 0x0002
114
115 #define MMEYEPCMCIA_LASTSTATE_PRESENT 0x0002
116 #define MMEYEPCMCIA_LASTSTATE_HALF 0x0001
117 #define MMEYEPCMCIA_LASTSTATE_EMPTY 0x0000
118
119 /*
120 * This is sort of arbitrary. It merely needs to be "enough". It can be
121 * overridden in the conf file, anyway.
122 */
123
124 #define MMEYEPCMCIA_MEM_PAGES 4
125 #define MMEYEPCMCIA_MEMSIZE MMEYEPCMCIA_MEM_PAGES*MMEYEPCMCIA_MEM_PAGESIZE
126
127 #define MMEYEPCMCIA_NSLOTS 1
128
129 #define MMEYEPCMCIA_WINS 5
130 #define MMEYEPCMCIA_IOWINS 2
131
132 struct mmeyepcmcia_softc {
133 struct device dev;
134
135 bus_space_tag_t memt;
136 bus_space_handle_t memh;
137 bus_space_tag_t iot;
138 bus_space_handle_t ioh;
139
140 /* XXX isa_chipset_tag_t, pci_chipset_tag_t, etc. */
141 void *intr_est;
142
143 pcmcia_chipset_tag_t pct;
144
145 /* this needs to be large enough to hold PCIC_MEM_PAGES bits */
146 int subregionmask;
147 #define MMEYEPCMCIA_MAX_MEM_PAGES (8 * sizeof(int))
148
149 /* used by memory window mapping functions */
150 bus_addr_t membase;
151
152 /*
153 * used by io window mapping functions. These can actually overlap
154 * with another pcic, since the underlying extent mapper will deal
155 * with individual allocations. This is here to deal with the fact
156 * that different busses have different real widths (different pc
157 * hardware seems to use 10 or 12 bits for the I/O bus).
158 */
159 bus_addr_t iobase;
160 bus_addr_t iosize;
161
162 int controller_irq;
163 int card_irq;
164
165 void *ih;
166
167 struct mmeyepcmcia_handle handle[MMEYEPCMCIA_NSLOTS];
168 };
169
170 static void mmeyepcmcia_attach_sockets(struct mmeyepcmcia_softc *);
171 static int mmeyepcmcia_intr(void *arg);
172
173 static inline int mmeyepcmcia_read(struct mmeyepcmcia_handle *, int);
174 static inline void mmeyepcmcia_write(struct mmeyepcmcia_handle *, int, int);
175
176 static int mmeyepcmcia_chip_mem_alloc(pcmcia_chipset_handle_t, bus_size_t,
177 struct pcmcia_mem_handle *);
178 static void mmeyepcmcia_chip_mem_free(pcmcia_chipset_handle_t,
179 struct pcmcia_mem_handle *);
180 static int mmeyepcmcia_chip_mem_map(pcmcia_chipset_handle_t, int,
181 bus_addr_t, bus_size_t, struct pcmcia_mem_handle *,
182 bus_size_t *, int *);
183 static void mmeyepcmcia_chip_mem_unmap(pcmcia_chipset_handle_t, int);
184
185 static int mmeyepcmcia_chip_io_alloc(pcmcia_chipset_handle_t, bus_addr_t,
186 bus_size_t, bus_size_t, struct pcmcia_io_handle *);
187 static void mmeyepcmcia_chip_io_free(pcmcia_chipset_handle_t,
188 struct pcmcia_io_handle *);
189 static int mmeyepcmcia_chip_io_map(pcmcia_chipset_handle_t, int,
190 bus_addr_t, bus_size_t, struct pcmcia_io_handle *, int *);
191 static void mmeyepcmcia_chip_io_unmap(pcmcia_chipset_handle_t, int);
192
193 static void mmeyepcmcia_chip_socket_enable(pcmcia_chipset_handle_t);
194 static void mmeyepcmcia_chip_socket_disable(pcmcia_chipset_handle_t);
195
196 static inline int mmeyepcmcia_read(struct mmeyepcmcia_handle *, int);
197 static inline int
198 mmeyepcmcia_read(struct mmeyepcmcia_handle *h, int idx)
199 {
200 static int prev_idx = 0;
201
202 if (idx == -1){
203 idx = prev_idx;
204 }
205 prev_idx = idx;
206 return (bus_space_read_stream_2(h->sc->iot, h->sc->ioh, idx));
207 }
208
209 static inline void mmeyepcmcia_write(struct mmeyepcmcia_handle *, int, int);
210 static inline void
211 mmeyepcmcia_write(struct mmeyepcmcia_handle *h, int idx, int data)
212 {
213 static int prev_idx;
214 if (idx == -1){
215 idx = prev_idx;
216 }
217 prev_idx = idx;
218 bus_space_write_stream_2(h->sc->iot, h->sc->ioh, idx, (data));
219 }
220
221 static void *mmeyepcmcia_chip_intr_establish(pcmcia_chipset_handle_t,
222 struct pcmcia_function *, int, int (*) (void *), void *);
223 static void mmeyepcmcia_chip_intr_disestablish(pcmcia_chipset_handle_t,
224 void *);
225 static void *mmeyepcmcia_chip_intr_establish(pcmcia_chipset_handle_t,
226 struct pcmcia_function *, int, int (*) (void *), void *);
227 static void mmeyepcmcia_chip_intr_disestablish(pcmcia_chipset_handle_t,
228 void *);
229
230 static void mmeyepcmcia_attach_socket(struct mmeyepcmcia_handle *);
231 static void mmeyepcmcia_init_socket(struct mmeyepcmcia_handle *);
232 static int mmeyepcmcia_print (void *, const char *);
233 static int mmeyepcmcia_intr_socket(struct mmeyepcmcia_handle *);
234 static void mmeyepcmcia_attach_card(struct mmeyepcmcia_handle *);
235 static void mmeyepcmcia_detach_card(struct mmeyepcmcia_handle *, int);
236 static void mmeyepcmcia_deactivate_card(struct mmeyepcmcia_handle *);
237 static void mmeyepcmcia_event_thread(void *);
238 static void mmeyepcmcia_queue_event(struct mmeyepcmcia_handle *, int);
239
240 static int mmeyepcmcia_match(struct device *, struct cfdata *, void *);
241 static void mmeyepcmcia_attach(struct device *, struct device *, void *);
242
243 CFATTACH_DECL(mmeyepcmcia, sizeof(struct mmeyepcmcia_softc),
244 mmeyepcmcia_match, mmeyepcmcia_attach, NULL, NULL);
245
246 static struct pcmcia_chip_functions mmeyepcmcia_functions = {
247 mmeyepcmcia_chip_mem_alloc,
248 mmeyepcmcia_chip_mem_free,
249 mmeyepcmcia_chip_mem_map,
250 mmeyepcmcia_chip_mem_unmap,
251
252 mmeyepcmcia_chip_io_alloc,
253 mmeyepcmcia_chip_io_free,
254 mmeyepcmcia_chip_io_map,
255 mmeyepcmcia_chip_io_unmap,
256
257 mmeyepcmcia_chip_intr_establish,
258 mmeyepcmcia_chip_intr_disestablish,
259
260 mmeyepcmcia_chip_socket_enable,
261 mmeyepcmcia_chip_socket_disable,
262 };
263
264 static int
265 mmeyepcmcia_match(struct device *parent, struct cfdata *match, void *aux)
266 {
267 extern struct cfdriver mmeyepcmcia_cd;
268 struct mainbus_attach_args *ma = aux;
269
270 if (strcmp(ma->ma_name, mmeyepcmcia_cd.cd_name) == 0)
271 return (1);
272
273 return (0);
274 }
275
276 static void
277 mmeyepcmcia_attach(struct device *parent, struct device *self, void *aux)
278 {
279 struct mainbus_attach_args *ma = aux;
280 struct mmeyepcmcia_softc *sc = (void *)self;
281
282 sc->subregionmask = 1; /* 1999.05.17 T.Horiuchi for R1.4 */
283
284 sc->pct = (pcmcia_chipset_tag_t)&mmeyepcmcia_functions;
285 sc->iot = 0;
286 sc->ioh = ma->ma_addr1;
287 sc->memt = 0;
288 sc->memh = ma->ma_addr2;
289 sc->controller_irq = ma->ma_irq1;
290 sc->card_irq = ma->ma_irq2;
291
292 printf(": using MMTA irq %d\n", sc->controller_irq);
293
294 sc->handle[0].sc = sc;
295 sc->handle[0].flags = MMEYEPCMCIA_FLAG_SOCKETP;
296 sc->handle[0].laststate = MMEYEPCMCIA_LASTSTATE_EMPTY;
297
298 SIMPLEQ_INIT(&sc->handle[0].events);
299
300 mmeye_intr_establish(sc->controller_irq,
301 IST_LEVEL, IPL_TTY, mmeyepcmcia_intr, sc);
302
303 mmeyepcmcia_attach_sockets(sc);
304 }
305
306 static void *
307 mmeyepcmcia_chip_intr_establish(pcmcia_chipset_handle_t pch,
308 struct pcmcia_function *pf, int ipl, int (*fct)(void *), void *arg)
309 {
310 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch;
311 int irq = h->sc->card_irq;
312 void *ih;
313
314 ih = mmeye_intr_establish(irq, IST_LEVEL, ipl, fct, arg);
315 h->ih_irq = irq;
316
317 printf("%s: card irq %d\n", h->pcmcia->dv_xname, irq);
318
319 return (ih);
320 }
321
322 static void
323 mmeyepcmcia_chip_intr_disestablish(pcmcia_chipset_handle_t pch, void *ih)
324 {
325 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch;
326
327 h->ih_irq = 0;
328 mmeye_intr_disestablish(ih);
329 }
330
331
332 static void
333 mmeyepcmcia_attach_sockets(struct mmeyepcmcia_softc *sc)
334 {
335
336 mmeyepcmcia_attach_socket(&sc->handle[0]);
337 }
338
339 static void
340 mmeyepcmcia_attach_socket(struct mmeyepcmcia_handle *h)
341 {
342 struct pcmciabus_attach_args paa;
343
344 /* initialize the rest of the handle */
345
346 h->shutdown = 0;
347 h->memalloc = 0;
348 h->ioalloc = 0;
349 h->ih_irq = 0;
350
351 /* now, config one pcmcia device per socket */
352
353 paa.paa_busname = "pcmcia";
354 paa.pct = (pcmcia_chipset_tag_t) h->sc->pct;
355 paa.pch = (pcmcia_chipset_handle_t) h;
356 paa.iobase = h->sc->iobase;
357 paa.iosize = h->sc->iosize;
358
359 h->pcmcia = config_found_ia(&h->sc->dev, "pcmciabus", &paa,
360 mmeyepcmcia_print);
361
362 /* if there's actually a pcmcia device attached, initialize the slot */
363
364 if (h->pcmcia)
365 mmeyepcmcia_init_socket(h);
366 }
367
368 static void
369 mmeyepcmcia_event_thread(void *arg)
370 {
371 struct mmeyepcmcia_handle *h = arg;
372 struct mmeyepcmcia_event *pe;
373 int s;
374
375 while (h->shutdown == 0) {
376 s = splhigh();
377 if ((pe = SIMPLEQ_FIRST(&h->events)) == NULL) {
378 splx(s);
379 (void) tsleep(&h->events, PWAIT, "mmeyepcmciaev", 0);
380 continue;
381 } else {
382 splx(s);
383 /* sleep .25s to be enqueued chatterling interrupts */
384 (void) tsleep((void *)mmeyepcmcia_event_thread, PWAIT,
385 "mmeyepcmciass", hz/4);
386 }
387 s = splhigh();
388 SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
389 splx(s);
390
391 switch (pe->pe_type) {
392 case MMEYEPCMCIA_EVENT_INSERTION:
393 s = splhigh();
394 while (1) {
395 struct mmeyepcmcia_event *pe1, *pe2;
396
397 if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL)
398 break;
399 if (pe1->pe_type != MMEYEPCMCIA_EVENT_REMOVAL)
400 break;
401 if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL)
402 break;
403 if (pe2->pe_type == MMEYEPCMCIA_EVENT_INSERTION) {
404 SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
405 free(pe1, M_TEMP);
406 SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
407 free(pe2, M_TEMP);
408 }
409 }
410 splx(s);
411
412 DPRINTF(("%s: insertion event\n", h->sc->dev.dv_xname));
413 mmeyepcmcia_attach_card(h);
414 break;
415
416 case MMEYEPCMCIA_EVENT_REMOVAL:
417 s = splhigh();
418 while (1) {
419 struct mmeyepcmcia_event *pe1, *pe2;
420
421 if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL)
422 break;
423 if (pe1->pe_type != MMEYEPCMCIA_EVENT_INSERTION)
424 break;
425 if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL)
426 break;
427 if (pe2->pe_type == MMEYEPCMCIA_EVENT_REMOVAL) {
428 SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
429 free(pe1, M_TEMP);
430 SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
431 free(pe2, M_TEMP);
432 }
433 }
434 splx(s);
435
436 DPRINTF(("%s: removal event\n", h->sc->dev.dv_xname));
437 mmeyepcmcia_detach_card(h, DETACH_FORCE);
438 break;
439
440 default:
441 panic("mmeyepcmcia_event_thread: unknown event %d",
442 pe->pe_type);
443 }
444 free(pe, M_TEMP);
445 }
446
447 h->event_thread = NULL;
448
449 /* In case parent is waiting for us to exit. */
450 wakeup(h->sc);
451
452 kthread_exit(0);
453 }
454
455 static void
456 mmeyepcmcia_init_socket(struct mmeyepcmcia_handle *h)
457 {
458 int reg;
459
460 /*
461 * queue creation of a kernel thread to handle insert/removal events.
462 */
463 #ifdef DIAGNOSTIC
464 if (h->event_thread != NULL)
465 panic("mmeyepcmcia_attach_socket: event thread");
466 #endif
467
468 /* if there's a card there, then attach it. */
469
470 reg = mmeyepcmcia_read(h, MMEYEPCMCIA_IF_STATUS);
471 reg &= ~MMEYEPCMCIA_IF_STATUS_BUSWIDTH; /* Set bus width to 16bit */
472
473 if ((reg & MMEYEPCMCIA_IF_STATUS_CARDDETECT_MASK) ==
474 MMEYEPCMCIA_IF_STATUS_CARDDETECT_PRESENT) {
475 int i;
476
477 /* reset the card */
478 mmeyepcmcia_write(h, MMEYEPCMCIA_IF_STATUS, reg|MMEYEPCMCIA_IF_STATUS_RESET);
479 delay(1000); /* wait 1000 uSec */
480 mmeyepcmcia_write(h, MMEYEPCMCIA_IF_STATUS,
481 reg & ~MMEYEPCMCIA_IF_STATUS_RESET);
482 for (i = 0; i < 10000; i++)
483 delay(1000); /* wait 1 mSec */
484
485 mmeyepcmcia_attach_card(h);
486 h->laststate = MMEYEPCMCIA_LASTSTATE_PRESENT;
487 } else {
488 h->laststate = MMEYEPCMCIA_LASTSTATE_EMPTY;
489 }
490
491 if (kthread_create(PRI_NONE, 0, NULL, mmeyepcmcia_event_thread, h,
492 &h->event_thread, "%s", h->sc->dev.dv_xname)) {
493 printf("%s: unable to create event thread\n",
494 h->sc->dev.dv_xname);
495 panic("mmeyepcmcia_create_event_thread");
496 }
497 }
498
499 static int
500 mmeyepcmcia_print(void *arg, const char *pnp)
501 {
502
503 if (pnp)
504 aprint_normal("pcmcia at %s", pnp);
505
506 return (UNCONF);
507 }
508
509 static int
510 mmeyepcmcia_intr(void *arg)
511 {
512 struct mmeyepcmcia_softc *sc = arg;
513
514 DPRINTF(("%s: intr\n", sc->dev.dv_xname));
515
516 mmeyepcmcia_intr_socket(&sc->handle[0]);
517
518 return (0);
519 }
520
521 static int
522 mmeyepcmcia_intr_socket(struct mmeyepcmcia_handle *h)
523 {
524 int cscreg;
525
526 cscreg = mmeyepcmcia_read(h, MMEYEPCMCIA_CSC);
527
528 cscreg &= (MMEYEPCMCIA_CSC_GPI |
529 MMEYEPCMCIA_CSC_CD |
530 MMEYEPCMCIA_CSC_READY |
531 MMEYEPCMCIA_CSC_BATTWARN |
532 MMEYEPCMCIA_CSC_BATTDEAD);
533
534 if (cscreg & MMEYEPCMCIA_CSC_GPI) {
535 DPRINTF(("%s: %02x GPI\n", h->sc->dev.dv_xname, h->sock));
536 }
537 if (cscreg & MMEYEPCMCIA_CSC_CD) {
538 int statreg;
539
540 statreg = mmeyepcmcia_read(h, MMEYEPCMCIA_IF_STATUS);
541
542 DPRINTF(("%s: %02x CD %x\n", h->sc->dev.dv_xname, h->sock,
543 statreg));
544
545 if ((statreg & MMEYEPCMCIA_IF_STATUS_CARDDETECT_MASK) ==
546 MMEYEPCMCIA_IF_STATUS_CARDDETECT_PRESENT) {
547 if (h->laststate != MMEYEPCMCIA_LASTSTATE_PRESENT) {
548 DPRINTF(("%s: enqueing INSERTION event\n",
549 h->sc->dev.dv_xname));
550 mmeyepcmcia_queue_event(h, MMEYEPCMCIA_EVENT_INSERTION);
551 }
552 h->laststate = MMEYEPCMCIA_LASTSTATE_PRESENT;
553 } else {
554 if (h->laststate == MMEYEPCMCIA_LASTSTATE_PRESENT) {
555 /* Deactivate the card now. */
556 DPRINTF(("%s: deactivating card\n",
557 h->sc->dev.dv_xname));
558 mmeyepcmcia_deactivate_card(h);
559
560 DPRINTF(("%s: enqueing REMOVAL event\n",
561 h->sc->dev.dv_xname));
562 mmeyepcmcia_queue_event(h, MMEYEPCMCIA_EVENT_REMOVAL);
563 }
564 h->laststate = ((statreg & MMEYEPCMCIA_IF_STATUS_CARDDETECT_MASK) == 0)
565 ? MMEYEPCMCIA_LASTSTATE_EMPTY : MMEYEPCMCIA_LASTSTATE_HALF;
566 }
567 }
568 if (cscreg & MMEYEPCMCIA_CSC_READY) {
569 DPRINTF(("%s: %02x READY\n", h->sc->dev.dv_xname, h->sock));
570 /* shouldn't happen */
571 }
572 if (cscreg & MMEYEPCMCIA_CSC_BATTWARN) {
573 DPRINTF(("%s: %02x BATTWARN\n", h->sc->dev.dv_xname, h->sock));
574 }
575 if (cscreg & MMEYEPCMCIA_CSC_BATTDEAD) {
576 DPRINTF(("%s: %02x BATTDEAD\n", h->sc->dev.dv_xname, h->sock));
577 }
578 return (cscreg ? 1 : 0);
579 }
580
581 static void
582 mmeyepcmcia_queue_event(struct mmeyepcmcia_handle *h, int event)
583 {
584 struct mmeyepcmcia_event *pe;
585 int s;
586
587 pe = malloc(sizeof(*pe), M_TEMP, M_NOWAIT);
588 if (pe == NULL)
589 panic("mmeyepcmcia_queue_event: can't allocate event");
590
591 pe->pe_type = event;
592 s = splhigh();
593 SIMPLEQ_INSERT_TAIL(&h->events, pe, pe_q);
594 splx(s);
595 wakeup(&h->events);
596 }
597
598 static void
599 mmeyepcmcia_attach_card(struct mmeyepcmcia_handle *h)
600 {
601
602 if (!(h->flags & MMEYEPCMCIA_FLAG_CARDP)) {
603 /* call the MI attach function */
604 pcmcia_card_attach(h->pcmcia);
605
606 h->flags |= MMEYEPCMCIA_FLAG_CARDP;
607 } else {
608 DPRINTF(("mmeyepcmcia_attach_card: already attached"));
609 }
610 }
611
612 static void
613 mmeyepcmcia_detach_card(struct mmeyepcmcia_handle *h, int flags)
614 {
615
616 if (h->flags & MMEYEPCMCIA_FLAG_CARDP) {
617 h->flags &= ~MMEYEPCMCIA_FLAG_CARDP;
618
619 /* call the MI detach function */
620 pcmcia_card_detach(h->pcmcia, flags);
621 } else {
622 DPRINTF(("mmeyepcmcia_detach_card: already detached"));
623 }
624 }
625
626 static void
627 mmeyepcmcia_deactivate_card(struct mmeyepcmcia_handle *h)
628 {
629
630 /* call the MI deactivate function */
631 pcmcia_card_deactivate(h->pcmcia);
632
633 /* Power down and reset XXX notyet */
634 }
635
636 static int
637 mmeyepcmcia_chip_mem_alloc(pcmcia_chipset_handle_t pch, bus_size_t size,
638 struct pcmcia_mem_handle *pcmhp)
639 {
640 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch;
641 bus_space_handle_t memh = 0;
642 bus_addr_t addr;
643 bus_size_t sizepg;
644 int i, mask, mhandle;
645
646 /* out of sc->memh, allocate as many pages as necessary */
647 #define MMEYEPCMCIA_MEM_ALIGN MMEYEPCMCIA_MEM_PAGESIZE
648 /* convert size to PCIC pages */
649 sizepg = (size + (MMEYEPCMCIA_MEM_ALIGN - 1)) / MMEYEPCMCIA_MEM_ALIGN;
650 if (sizepg > MMEYEPCMCIA_MAX_MEM_PAGES)
651 return (1);
652
653 mask = (1 << sizepg) - 1;
654
655 addr = 0; /* XXX gcc -Wuninitialized */
656 mhandle = 0; /* XXX gcc -Wuninitialized */
657
658 for (i = 0; i <= MMEYEPCMCIA_MAX_MEM_PAGES - sizepg; i++) {
659 if ((h->sc->subregionmask & (mask << i)) == (mask << i)) {
660 #if 0
661 if (bus_space_subregion(h->sc->memt, h->sc->memh,
662 i * MMEYEPCMCIA_MEM_PAGESIZE,
663 sizepg * MMEYEPCMCIA_MEM_PAGESIZE, &memh))
664 return (1);
665 #endif
666 memh = h->sc->memh;
667 mhandle = mask << i;
668 addr = h->sc->membase + (i * MMEYEPCMCIA_MEM_PAGESIZE);
669 h->sc->subregionmask &= ~(mhandle);
670 pcmhp->memt = h->sc->memt;
671 pcmhp->memh = memh;
672 pcmhp->addr = addr;
673 pcmhp->size = size;
674 pcmhp->mhandle = mhandle;
675 pcmhp->realsize = sizepg * MMEYEPCMCIA_MEM_PAGESIZE;
676 return (0);
677 }
678 }
679
680 return (1);
681 }
682
683 static void
684 mmeyepcmcia_chip_mem_free(pcmcia_chipset_handle_t pch,
685 struct pcmcia_mem_handle *pcmhp)
686 {
687 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch;
688
689 h->sc->subregionmask |= pcmhp->mhandle;
690 }
691
692 static int
693 mmeyepcmcia_chip_mem_map(pcmcia_chipset_handle_t pch, int kind,
694 bus_addr_t card_addr, bus_size_t size, struct pcmcia_mem_handle *pcmhp,
695 bus_size_t *offsetp, int *windowp)
696 {
697 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch;
698 bus_addr_t busaddr;
699 long card_offset;
700 int i, win;
701
702 win = -1;
703 for (i = 0; i < MMEYEPCMCIA_WINS;
704 i++) {
705 if ((h->memalloc & (1 << i)) == 0) {
706 win = i;
707 h->memalloc |= (1 << i);
708 break;
709 }
710 }
711
712 if (win == -1)
713 return (1);
714
715 *windowp = win;
716
717 /* XXX this is pretty gross */
718
719 if (h->sc->memt != pcmhp->memt)
720 panic("mmeyepcmcia_chip_mem_map memt is bogus");
721
722 busaddr = pcmhp->addr;
723
724 /*
725 * compute the address offset to the pcmcia address space for the
726 * pcic. this is intentionally signed. The masks and shifts below
727 * will cause TRT to happen in the pcic registers. Deal with making
728 * sure the address is aligned, and return the alignment offset.
729 */
730
731 *offsetp = 0;
732 card_addr -= *offsetp;
733
734 DPRINTF(("mmeyepcmcia_chip_mem_map window %d bus %lx+%lx+%lx at card addr "
735 "%lx\n", win, (u_long) busaddr, (u_long) * offsetp, (u_long) size,
736 (u_long) card_addr));
737
738 /*
739 * include the offset in the size, and decrement size by one, since
740 * the hw wants start/stop
741 */
742 size += *offsetp - 1;
743
744 card_offset = (((long) card_addr) - ((long) busaddr));
745
746 h->mem[win].addr = busaddr;
747 h->mem[win].size = size;
748 h->mem[win].offset = card_offset;
749 h->mem[win].kind = kind;
750
751 if (kind == PCMCIA_MEM_ATTR) {
752 pcmhp->memh = h->sc->memh + card_addr;
753 } else {
754 pcmhp->memh = h->sc->memh + card_addr + MMEYEPCMCIA_ATTRMEM_SIZE;
755 }
756
757 return (0);
758 }
759
760 static void
761 mmeyepcmcia_chip_mem_unmap(pcmcia_chipset_handle_t pch, int window)
762 {
763 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch;
764
765 if (window >= MMEYEPCMCIA_WINS)
766 panic("mmeyepcmcia_chip_mem_unmap: window out of range");
767
768 h->memalloc &= ~(1 << window);
769 }
770
771 static int
772 mmeyepcmcia_chip_io_alloc(pcmcia_chipset_handle_t pch, bus_addr_t start,
773 bus_size_t size, bus_size_t align, struct pcmcia_io_handle *pcihp)
774 {
775 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch;
776 bus_space_tag_t iot;
777 bus_space_handle_t ioh;
778 bus_addr_t ioaddr;
779 int flags = 0;
780
781 /*
782 * Allocate some arbitrary I/O space.
783 */
784
785 iot = h->sc->iot;
786
787 if (start) {
788 ioaddr = start;
789 ioh = start;
790 DPRINTF(("mmeyepcmcia_chip_io_alloc map port %lx+%lx\n",
791 (u_long) ioaddr, (u_long) size));
792 } else {
793 flags |= PCMCIA_IO_ALLOCATED;
794 ioaddr = ioh = h->sc->iobase;
795 DPRINTF(("mmeyepcmcia_chip_io_alloc alloc port %lx+%lx\n",
796 (u_long) ioaddr, (u_long) size));
797 }
798
799 pcihp->iot = iot;
800 pcihp->ioh = ioh + h->sc->memh + MMEYEPCMCIA_ATTRMEM_SIZE;
801 pcihp->addr = ioaddr;
802 pcihp->size = size;
803 pcihp->flags = flags;
804
805 return (0);
806 }
807
808 static void
809 mmeyepcmcia_chip_io_free(pcmcia_chipset_handle_t pch,
810 struct pcmcia_io_handle *pcihp)
811 {
812 }
813
814 static int
815 mmeyepcmcia_chip_io_map(pcmcia_chipset_handle_t pch, int width,
816 bus_addr_t offset, bus_size_t size, struct pcmcia_io_handle *pcihp,
817 int *windowp)
818 {
819 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch;
820 bus_addr_t ioaddr = pcihp->addr + offset;
821 int i, win;
822 #ifdef MMEYEPCMCIADEBUG
823 static char *width_names[] = { "auto", "io8", "io16" };
824 #endif
825 int reg;
826
827 /* I/O width is hardwired to 16bit mode on mmeye. */
828 width = PCMCIA_WIDTH_IO16;
829
830 win = -1;
831 for (i = 0; i < MMEYEPCMCIA_IOWINS; i++) {
832 if ((h->ioalloc & (1 << i)) == 0) {
833 win = i;
834 h->ioalloc |= (1 << i);
835 break;
836 }
837 }
838
839 if (win == -1)
840 return (1);
841
842 *windowp = win;
843
844 /* XXX this is pretty gross */
845
846 if (h->sc->iot != pcihp->iot)
847 panic("mmeyepcmcia_chip_io_map iot is bogus");
848
849 DPRINTF(("mmeyepcmcia_chip_io_map window %d %s port %lx+%lx\n",
850 win, width_names[width], (u_long) ioaddr, (u_long) size));
851
852 /* XXX wtf is this doing here? */
853
854 printf("%s: port 0x%lx", h->sc->dev.dv_xname, (u_long) ioaddr);
855 if (size > 1)
856 printf("-0x%lx", (u_long) ioaddr + (u_long) size - 1);
857 printf("\n");
858
859 h->io[win].addr = ioaddr;
860 h->io[win].size = size;
861 h->io[win].width = width;
862
863 pcihp->ioh = h->sc->memh + MMEYEPCMCIA_ATTRMEM_SIZE;
864
865 if (width == PCMCIA_WIDTH_IO8) { /* IO8 */
866 reg = mmeyepcmcia_read(h, MMEYEPCMCIA_IF_STATUS);
867 reg |= MMEYEPCMCIA_IF_STATUS_BUSWIDTH; /* Set bus width to 8bit */
868 mmeyepcmcia_write(h, MMEYEPCMCIA_IF_STATUS, reg);
869 }
870
871 return (0);
872 }
873
874 static void
875 mmeyepcmcia_chip_io_unmap(pcmcia_chipset_handle_t pch, int window)
876 {
877 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch;
878
879 if (window >= MMEYEPCMCIA_IOWINS)
880 panic("mmeyepcmcia_chip_io_unmap: window out of range");
881
882 h->ioalloc &= ~(1 << window);
883 }
884
885 static void
886 mmeyepcmcia_chip_socket_enable(pcmcia_chipset_handle_t pch)
887 {
888 }
889
890 static void
891 mmeyepcmcia_chip_socket_disable(pcmcia_chipset_handle_t pch)
892 {
893 }
894