mmeyepcmcia.c revision 1.11 1 /* $NetBSD: mmeyepcmcia.c,v 1.11 2005/12/24 20:07:19 perry 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.11 2005/12/24 20:07:19 perry 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 struct proc *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 void mmeyepcmcia_attach_sockets(struct mmeyepcmcia_softc *);
171 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 int mmeyepcmcia_chip_mem_alloc(pcmcia_chipset_handle_t, bus_size_t,
177 struct pcmcia_mem_handle *);
178 void mmeyepcmcia_chip_mem_free(pcmcia_chipset_handle_t,
179 struct pcmcia_mem_handle *);
180 int mmeyepcmcia_chip_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t,
181 bus_size_t, struct pcmcia_mem_handle *, bus_size_t *, int *);
182 void mmeyepcmcia_chip_mem_unmap(pcmcia_chipset_handle_t, int);
183
184 int mmeyepcmcia_chip_io_alloc(pcmcia_chipset_handle_t, bus_addr_t,
185 bus_size_t, bus_size_t, struct pcmcia_io_handle *);
186 void mmeyepcmcia_chip_io_free(pcmcia_chipset_handle_t,
187 struct pcmcia_io_handle *);
188 int mmeyepcmcia_chip_io_map(pcmcia_chipset_handle_t, int, bus_addr_t,
189 bus_size_t, struct pcmcia_io_handle *, int *);
190 void mmeyepcmcia_chip_io_unmap(pcmcia_chipset_handle_t, int);
191
192 void mmeyepcmcia_chip_socket_enable(pcmcia_chipset_handle_t);
193 void mmeyepcmcia_chip_socket_disable(pcmcia_chipset_handle_t);
194
195 static inline int mmeyepcmcia_read(struct mmeyepcmcia_handle *, int);
196 static inline int
197 mmeyepcmcia_read(struct mmeyepcmcia_handle *h, int idx)
198 {
199 static int prev_idx = 0;
200
201 if (idx == -1){
202 idx = prev_idx;
203 }
204 prev_idx = idx;
205 return (bus_space_read_stream_2(h->sc->iot, h->sc->ioh, idx));
206 }
207
208 static inline void mmeyepcmcia_write(struct mmeyepcmcia_handle *, int, int);
209 static inline void
210 mmeyepcmcia_write(struct mmeyepcmcia_handle *h, int idx, int data)
211 {
212 static int prev_idx;
213 if (idx == -1){
214 idx = prev_idx;
215 }
216 prev_idx = idx;
217 bus_space_write_stream_2(h->sc->iot, h->sc->ioh, idx, (data));
218 }
219
220 void *mmeyepcmcia_chip_intr_establish(pcmcia_chipset_handle_t,
221 struct pcmcia_function *, int, int (*) (void *), void *);
222 void mmeyepcmcia_chip_intr_disestablish(pcmcia_chipset_handle_t, void *);
223 void *mmeyepcmcia_chip_intr_establish(pcmcia_chipset_handle_t,
224 struct pcmcia_function *, int, int (*) (void *), void *);
225 void mmeyepcmcia_chip_intr_disestablish(pcmcia_chipset_handle_t,
226 void *);
227
228 void mmeyepcmcia_attach_socket(struct mmeyepcmcia_handle *);
229 void mmeyepcmcia_init_socket(struct mmeyepcmcia_handle *);
230 int mmeyepcmcia_print (void *, const char *);
231 int mmeyepcmcia_intr_socket(struct mmeyepcmcia_handle *);
232 void mmeyepcmcia_attach_card(struct mmeyepcmcia_handle *);
233 void mmeyepcmcia_detach_card(struct mmeyepcmcia_handle *, int);
234 void mmeyepcmcia_deactivate_card(struct mmeyepcmcia_handle *);
235 void mmeyepcmcia_create_event_thread(void *);
236 void mmeyepcmcia_event_thread(void *);
237 void mmeyepcmcia_queue_event(struct mmeyepcmcia_handle *, int);
238
239 int mmeyepcmcia_match(struct device *, struct cfdata *, void *);
240 void mmeyepcmcia_attach(struct device *, struct device *, void *);
241
242 CFATTACH_DECL(mmeyepcmcia, sizeof(struct mmeyepcmcia_softc),
243 mmeyepcmcia_match, mmeyepcmcia_attach, NULL, NULL);
244
245 static struct pcmcia_chip_functions mmeyepcmcia_functions = {
246 mmeyepcmcia_chip_mem_alloc,
247 mmeyepcmcia_chip_mem_free,
248 mmeyepcmcia_chip_mem_map,
249 mmeyepcmcia_chip_mem_unmap,
250
251 mmeyepcmcia_chip_io_alloc,
252 mmeyepcmcia_chip_io_free,
253 mmeyepcmcia_chip_io_map,
254 mmeyepcmcia_chip_io_unmap,
255
256 mmeyepcmcia_chip_intr_establish,
257 mmeyepcmcia_chip_intr_disestablish,
258
259 mmeyepcmcia_chip_socket_enable,
260 mmeyepcmcia_chip_socket_disable,
261 };
262
263 int
264 mmeyepcmcia_match(struct device *parent, struct cfdata *match, void *aux)
265 {
266 extern struct cfdriver mmeyepcmcia_cd;
267 struct mainbus_attach_args *ma = aux;
268
269 if (strcmp(ma->ma_name, mmeyepcmcia_cd.cd_name) == 0)
270 return (1);
271
272 return (0);
273 }
274
275 void
276 mmeyepcmcia_attach(struct device *parent, struct device *self, void *aux)
277 {
278 struct mainbus_attach_args *ma = aux;
279 struct mmeyepcmcia_softc *sc = (void *)self;
280
281 sc->subregionmask = 1; /* 1999.05.17 T.Horiuchi for R1.4 */
282
283 sc->pct = (pcmcia_chipset_tag_t)&mmeyepcmcia_functions;
284 sc->iot = 0;
285 sc->ioh = ma->ma_addr1;
286 sc->memt = 0;
287 sc->memh = ma->ma_addr2;
288 sc->controller_irq = ma->ma_irq1;
289 sc->card_irq = ma->ma_irq2;
290
291 printf(": using MMTA irq %d\n", sc->controller_irq);
292
293 sc->handle[0].sc = sc;
294 sc->handle[0].flags = MMEYEPCMCIA_FLAG_SOCKETP;
295 sc->handle[0].laststate = MMEYEPCMCIA_LASTSTATE_EMPTY;
296
297 SIMPLEQ_INIT(&sc->handle[0].events);
298
299 mmeye_intr_establish(sc->controller_irq,
300 IST_LEVEL, IPL_TTY, mmeyepcmcia_intr, sc);
301
302 mmeyepcmcia_attach_sockets(sc);
303 }
304
305 void *
306 mmeyepcmcia_chip_intr_establish(pch, pf, ipl, fct, arg)
307 pcmcia_chipset_handle_t pch;
308 struct pcmcia_function *pf;
309 int ipl;
310 int (*fct)(void *);
311 void *arg;
312 {
313 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch;
314 int irq = h->sc->card_irq;
315 void *ih;
316
317 ih = mmeye_intr_establish(irq, IST_LEVEL, ipl, fct, arg);
318 h->ih_irq = irq;
319
320 printf("%s: card irq %d\n", h->pcmcia->dv_xname, irq);
321
322 return (ih);
323 }
324
325 void
326 mmeyepcmcia_chip_intr_disestablish(pcmcia_chipset_handle_t pch, void *ih)
327 {
328 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch;
329
330 h->ih_irq = 0;
331 mmeye_intr_disestablish(ih);
332 }
333
334
335 void
336 mmeyepcmcia_attach_sockets(struct mmeyepcmcia_softc *sc)
337 {
338
339 mmeyepcmcia_attach_socket(&sc->handle[0]);
340 }
341
342 void
343 mmeyepcmcia_attach_socket(struct mmeyepcmcia_handle *h)
344 {
345 struct pcmciabus_attach_args paa;
346
347 /* initialize the rest of the handle */
348
349 h->shutdown = 0;
350 h->memalloc = 0;
351 h->ioalloc = 0;
352 h->ih_irq = 0;
353
354 /* now, config one pcmcia device per socket */
355
356 paa.paa_busname = "pcmcia";
357 paa.pct = (pcmcia_chipset_tag_t) h->sc->pct;
358 paa.pch = (pcmcia_chipset_handle_t) h;
359 paa.iobase = h->sc->iobase;
360 paa.iosize = h->sc->iosize;
361
362 h->pcmcia = config_found_ia(&h->sc->dev, "pcmciabus", &paa,
363 mmeyepcmcia_print);
364
365 /* if there's actually a pcmcia device attached, initialize the slot */
366
367 if (h->pcmcia)
368 mmeyepcmcia_init_socket(h);
369 }
370
371 void
372 mmeyepcmcia_create_event_thread(void *arg)
373 {
374 struct mmeyepcmcia_handle *h = arg;
375
376 if (kthread_create1(mmeyepcmcia_event_thread, h, &h->event_thread,
377 "%s", h->sc->dev.dv_xname)) {
378 printf("%s: unable to create event thread\n",
379 h->sc->dev.dv_xname);
380 panic("mmeyepcmcia_create_event_thread");
381 }
382 }
383
384 void
385 mmeyepcmcia_event_thread(void *arg)
386 {
387 struct mmeyepcmcia_handle *h = arg;
388 struct mmeyepcmcia_event *pe;
389 int s;
390
391 while (h->shutdown == 0) {
392 s = splhigh();
393 if ((pe = SIMPLEQ_FIRST(&h->events)) == NULL) {
394 splx(s);
395 (void) tsleep(&h->events, PWAIT, "mmeyepcmciaev", 0);
396 continue;
397 } else {
398 splx(s);
399 /* sleep .25s to be enqueued chatterling interrupts */
400 (void) tsleep((caddr_t)mmeyepcmcia_event_thread, PWAIT,
401 "mmeyepcmciass", hz/4);
402 }
403 s = splhigh();
404 SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
405 splx(s);
406
407 switch (pe->pe_type) {
408 case MMEYEPCMCIA_EVENT_INSERTION:
409 s = splhigh();
410 while (1) {
411 struct mmeyepcmcia_event *pe1, *pe2;
412
413 if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL)
414 break;
415 if (pe1->pe_type != MMEYEPCMCIA_EVENT_REMOVAL)
416 break;
417 if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL)
418 break;
419 if (pe2->pe_type == MMEYEPCMCIA_EVENT_INSERTION) {
420 SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
421 free(pe1, M_TEMP);
422 SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
423 free(pe2, M_TEMP);
424 }
425 }
426 splx(s);
427
428 DPRINTF(("%s: insertion event\n", h->sc->dev.dv_xname));
429 mmeyepcmcia_attach_card(h);
430 break;
431
432 case MMEYEPCMCIA_EVENT_REMOVAL:
433 s = splhigh();
434 while (1) {
435 struct mmeyepcmcia_event *pe1, *pe2;
436
437 if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL)
438 break;
439 if (pe1->pe_type != MMEYEPCMCIA_EVENT_INSERTION)
440 break;
441 if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL)
442 break;
443 if (pe2->pe_type == MMEYEPCMCIA_EVENT_REMOVAL) {
444 SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
445 free(pe1, M_TEMP);
446 SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
447 free(pe2, M_TEMP);
448 }
449 }
450 splx(s);
451
452 DPRINTF(("%s: removal event\n", h->sc->dev.dv_xname));
453 mmeyepcmcia_detach_card(h, DETACH_FORCE);
454 break;
455
456 default:
457 panic("mmeyepcmcia_event_thread: unknown event %d",
458 pe->pe_type);
459 }
460 free(pe, M_TEMP);
461 }
462
463 h->event_thread = NULL;
464
465 /* In case parent is waiting for us to exit. */
466 wakeup(h->sc);
467
468 kthread_exit(0);
469 }
470
471 void
472 mmeyepcmcia_init_socket(struct mmeyepcmcia_handle *h)
473 {
474 int reg;
475
476 /*
477 * queue creation of a kernel thread to handle insert/removal events.
478 */
479 #ifdef DIAGNOSTIC
480 if (h->event_thread != NULL)
481 panic("mmeyepcmcia_attach_socket: event thread");
482 #endif
483 kthread_create(mmeyepcmcia_create_event_thread, h);
484
485 /* if there's a card there, then attach it. */
486
487 reg = mmeyepcmcia_read(h, MMEYEPCMCIA_IF_STATUS);
488 reg &= ~MMEYEPCMCIA_IF_STATUS_BUSWIDTH; /* Set bus width to 16bit */
489
490 if ((reg & MMEYEPCMCIA_IF_STATUS_CARDDETECT_MASK) ==
491 MMEYEPCMCIA_IF_STATUS_CARDDETECT_PRESENT) {
492 int i;
493
494 /* reset the card */
495 mmeyepcmcia_write(h, MMEYEPCMCIA_IF_STATUS, reg|MMEYEPCMCIA_IF_STATUS_RESET);
496 delay(1000); /* wait 1000 uSec */
497 mmeyepcmcia_write(h, MMEYEPCMCIA_IF_STATUS,
498 reg & ~MMEYEPCMCIA_IF_STATUS_RESET);
499 for (i = 0; i < 10000; i++)
500 delay(1000); /* wait 1 mSec */
501
502 mmeyepcmcia_attach_card(h);
503 h->laststate = MMEYEPCMCIA_LASTSTATE_PRESENT;
504 } else {
505 h->laststate = MMEYEPCMCIA_LASTSTATE_EMPTY;
506 }
507 }
508
509 int
510 mmeyepcmcia_print(void *arg, const char *pnp)
511 {
512
513 if (pnp)
514 aprint_normal("pcmcia at %s", pnp);
515
516 return (UNCONF);
517 }
518
519 int
520 mmeyepcmcia_intr(void *arg)
521 {
522 struct mmeyepcmcia_softc *sc = arg;
523
524 DPRINTF(("%s: intr\n", sc->dev.dv_xname));
525
526 mmeyepcmcia_intr_socket(&sc->handle[0]);
527
528 return (0);
529 }
530
531 int
532 mmeyepcmcia_intr_socket(struct mmeyepcmcia_handle *h)
533 {
534 int cscreg;
535
536 cscreg = mmeyepcmcia_read(h, MMEYEPCMCIA_CSC);
537
538 cscreg &= (MMEYEPCMCIA_CSC_GPI |
539 MMEYEPCMCIA_CSC_CD |
540 MMEYEPCMCIA_CSC_READY |
541 MMEYEPCMCIA_CSC_BATTWARN |
542 MMEYEPCMCIA_CSC_BATTDEAD);
543
544 if (cscreg & MMEYEPCMCIA_CSC_GPI) {
545 DPRINTF(("%s: %02x GPI\n", h->sc->dev.dv_xname, h->sock));
546 }
547 if (cscreg & MMEYEPCMCIA_CSC_CD) {
548 int statreg;
549
550 statreg = mmeyepcmcia_read(h, MMEYEPCMCIA_IF_STATUS);
551
552 DPRINTF(("%s: %02x CD %x\n", h->sc->dev.dv_xname, h->sock,
553 statreg));
554
555 if ((statreg & MMEYEPCMCIA_IF_STATUS_CARDDETECT_MASK) ==
556 MMEYEPCMCIA_IF_STATUS_CARDDETECT_PRESENT) {
557 if (h->laststate != MMEYEPCMCIA_LASTSTATE_PRESENT) {
558 DPRINTF(("%s: enqueing INSERTION event\n",
559 h->sc->dev.dv_xname));
560 mmeyepcmcia_queue_event(h, MMEYEPCMCIA_EVENT_INSERTION);
561 }
562 h->laststate = MMEYEPCMCIA_LASTSTATE_PRESENT;
563 } else {
564 if (h->laststate == MMEYEPCMCIA_LASTSTATE_PRESENT) {
565 /* Deactivate the card now. */
566 DPRINTF(("%s: deactivating card\n",
567 h->sc->dev.dv_xname));
568 mmeyepcmcia_deactivate_card(h);
569
570 DPRINTF(("%s: enqueing REMOVAL event\n",
571 h->sc->dev.dv_xname));
572 mmeyepcmcia_queue_event(h, MMEYEPCMCIA_EVENT_REMOVAL);
573 }
574 h->laststate = ((statreg & MMEYEPCMCIA_IF_STATUS_CARDDETECT_MASK) == 0)
575 ? MMEYEPCMCIA_LASTSTATE_EMPTY : MMEYEPCMCIA_LASTSTATE_HALF;
576 }
577 }
578 if (cscreg & MMEYEPCMCIA_CSC_READY) {
579 DPRINTF(("%s: %02x READY\n", h->sc->dev.dv_xname, h->sock));
580 /* shouldn't happen */
581 }
582 if (cscreg & MMEYEPCMCIA_CSC_BATTWARN) {
583 DPRINTF(("%s: %02x BATTWARN\n", h->sc->dev.dv_xname, h->sock));
584 }
585 if (cscreg & MMEYEPCMCIA_CSC_BATTDEAD) {
586 DPRINTF(("%s: %02x BATTDEAD\n", h->sc->dev.dv_xname, h->sock));
587 }
588 return (cscreg ? 1 : 0);
589 }
590
591 void
592 mmeyepcmcia_queue_event(struct mmeyepcmcia_handle *h, int event)
593 {
594 struct mmeyepcmcia_event *pe;
595 int s;
596
597 pe = malloc(sizeof(*pe), M_TEMP, M_NOWAIT);
598 if (pe == NULL)
599 panic("mmeyepcmcia_queue_event: can't allocate event");
600
601 pe->pe_type = event;
602 s = splhigh();
603 SIMPLEQ_INSERT_TAIL(&h->events, pe, pe_q);
604 splx(s);
605 wakeup(&h->events);
606 }
607
608 void
609 mmeyepcmcia_attach_card(struct mmeyepcmcia_handle *h)
610 {
611
612 if (!(h->flags & MMEYEPCMCIA_FLAG_CARDP)) {
613 /* call the MI attach function */
614 pcmcia_card_attach(h->pcmcia);
615
616 h->flags |= MMEYEPCMCIA_FLAG_CARDP;
617 } else {
618 DPRINTF(("mmeyepcmcia_attach_card: already attached"));
619 }
620 }
621
622 void
623 mmeyepcmcia_detach_card(struct mmeyepcmcia_handle *h, int flags)
624 {
625
626 if (h->flags & MMEYEPCMCIA_FLAG_CARDP) {
627 h->flags &= ~MMEYEPCMCIA_FLAG_CARDP;
628
629 /* call the MI detach function */
630 pcmcia_card_detach(h->pcmcia, flags);
631 } else {
632 DPRINTF(("mmeyepcmcia_detach_card: already detached"));
633 }
634 }
635
636 void
637 mmeyepcmcia_deactivate_card(struct mmeyepcmcia_handle *h)
638 {
639
640 /* call the MI deactivate function */
641 pcmcia_card_deactivate(h->pcmcia);
642
643 /* Power down and reset XXX notyet */
644 }
645
646 int
647 mmeyepcmcia_chip_mem_alloc(pcmcia_chipset_handle_t pch, bus_size_t size,
648 struct pcmcia_mem_handle *pcmhp)
649 {
650 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch;
651 bus_space_handle_t memh = 0;
652 bus_addr_t addr;
653 bus_size_t sizepg;
654 int i, mask, mhandle;
655
656 /* out of sc->memh, allocate as many pages as necessary */
657 #define MMEYEPCMCIA_MEM_ALIGN MMEYEPCMCIA_MEM_PAGESIZE
658 /* convert size to PCIC pages */
659 sizepg = (size + (MMEYEPCMCIA_MEM_ALIGN - 1)) / MMEYEPCMCIA_MEM_ALIGN;
660 if (sizepg > MMEYEPCMCIA_MAX_MEM_PAGES)
661 return (1);
662
663 mask = (1 << sizepg) - 1;
664
665 addr = 0; /* XXX gcc -Wuninitialized */
666 mhandle = 0; /* XXX gcc -Wuninitialized */
667
668 for (i = 0; i <= MMEYEPCMCIA_MAX_MEM_PAGES - sizepg; i++) {
669 if ((h->sc->subregionmask & (mask << i)) == (mask << i)) {
670 #if 0
671 if (bus_space_subregion(h->sc->memt, h->sc->memh,
672 i * MMEYEPCMCIA_MEM_PAGESIZE,
673 sizepg * MMEYEPCMCIA_MEM_PAGESIZE, &memh))
674 return (1);
675 #endif
676 memh = h->sc->memh;
677 mhandle = mask << i;
678 addr = h->sc->membase + (i * MMEYEPCMCIA_MEM_PAGESIZE);
679 h->sc->subregionmask &= ~(mhandle);
680 pcmhp->memt = h->sc->memt;
681 pcmhp->memh = memh;
682 pcmhp->addr = addr;
683 pcmhp->size = size;
684 pcmhp->mhandle = mhandle;
685 pcmhp->realsize = sizepg * MMEYEPCMCIA_MEM_PAGESIZE;
686 return (0);
687 }
688 }
689
690 return (1);
691 }
692
693 void
694 mmeyepcmcia_chip_mem_free(pcmcia_chipset_handle_t pch,
695 struct pcmcia_mem_handle *pcmhp)
696 {
697 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch;
698
699 h->sc->subregionmask |= pcmhp->mhandle;
700 }
701
702 int
703 mmeyepcmcia_chip_mem_map(pcmcia_chipset_handle_t pch, int kind,
704 bus_addr_t card_addr, bus_size_t size, struct pcmcia_mem_handle *pcmhp,
705 bus_size_t *offsetp, int *windowp)
706 {
707 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch;
708 bus_addr_t busaddr;
709 long card_offset;
710 int i, win;
711
712 win = -1;
713 for (i = 0; i < MMEYEPCMCIA_WINS;
714 i++) {
715 if ((h->memalloc & (1 << i)) == 0) {
716 win = i;
717 h->memalloc |= (1 << i);
718 break;
719 }
720 }
721
722 if (win == -1)
723 return (1);
724
725 *windowp = win;
726
727 /* XXX this is pretty gross */
728
729 if (h->sc->memt != pcmhp->memt)
730 panic("mmeyepcmcia_chip_mem_map memt is bogus");
731
732 busaddr = pcmhp->addr;
733
734 /*
735 * compute the address offset to the pcmcia address space for the
736 * pcic. this is intentionally signed. The masks and shifts below
737 * will cause TRT to happen in the pcic registers. Deal with making
738 * sure the address is aligned, and return the alignment offset.
739 */
740
741 *offsetp = 0;
742 card_addr -= *offsetp;
743
744 DPRINTF(("mmeyepcmcia_chip_mem_map window %d bus %lx+%lx+%lx at card addr "
745 "%lx\n", win, (u_long) busaddr, (u_long) * offsetp, (u_long) size,
746 (u_long) card_addr));
747
748 /*
749 * include the offset in the size, and decrement size by one, since
750 * the hw wants start/stop
751 */
752 size += *offsetp - 1;
753
754 card_offset = (((long) card_addr) - ((long) busaddr));
755
756 h->mem[win].addr = busaddr;
757 h->mem[win].size = size;
758 h->mem[win].offset = card_offset;
759 h->mem[win].kind = kind;
760
761 if (kind == PCMCIA_MEM_ATTR) {
762 pcmhp->memh = h->sc->memh + card_addr;
763 } else {
764 pcmhp->memh = h->sc->memh + card_addr + MMEYEPCMCIA_ATTRMEM_SIZE;
765 }
766
767 return (0);
768 }
769
770 void
771 mmeyepcmcia_chip_mem_unmap(pcmcia_chipset_handle_t pch, int window)
772 {
773 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch;
774
775 if (window >= MMEYEPCMCIA_WINS)
776 panic("mmeyepcmcia_chip_mem_unmap: window out of range");
777
778 h->memalloc &= ~(1 << window);
779 }
780
781 int
782 mmeyepcmcia_chip_io_alloc(pcmcia_chipset_handle_t pch, bus_addr_t start,
783 bus_size_t size, bus_size_t align, struct pcmcia_io_handle *pcihp)
784 {
785 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch;
786 bus_space_tag_t iot;
787 bus_space_handle_t ioh;
788 bus_addr_t ioaddr;
789 int flags = 0;
790
791 /*
792 * Allocate some arbitrary I/O space.
793 */
794
795 iot = h->sc->iot;
796
797 if (start) {
798 ioaddr = start;
799 ioh = start;
800 DPRINTF(("mmeyepcmcia_chip_io_alloc map port %lx+%lx\n",
801 (u_long) ioaddr, (u_long) size));
802 } else {
803 flags |= PCMCIA_IO_ALLOCATED;
804 ioaddr = ioh = h->sc->iobase;
805 DPRINTF(("mmeyepcmcia_chip_io_alloc alloc port %lx+%lx\n",
806 (u_long) ioaddr, (u_long) size));
807 }
808
809 pcihp->iot = iot;
810 pcihp->ioh = ioh + h->sc->memh + MMEYEPCMCIA_ATTRMEM_SIZE;
811 pcihp->addr = ioaddr;
812 pcihp->size = size;
813 pcihp->flags = flags;
814
815 return (0);
816 }
817
818 void
819 mmeyepcmcia_chip_io_free(pcmcia_chipset_handle_t pch,
820 struct pcmcia_io_handle *pcihp)
821 {
822 }
823
824 int
825 mmeyepcmcia_chip_io_map(pcmcia_chipset_handle_t pch, int width, bus_addr_t offset,
826 bus_size_t size, struct pcmcia_io_handle *pcihp, int *windowp)
827 {
828 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch;
829 bus_addr_t ioaddr = pcihp->addr + offset;
830 int i, win;
831 #ifdef MMEYEPCMCIADEBUG
832 static char *width_names[] = { "auto", "io8", "io16" };
833 #endif
834 int reg;
835
836 /* I/O width is hardwired to 16bit mode on mmeye. */
837 width = PCMCIA_WIDTH_IO16;
838
839 win = -1;
840 for (i = 0; i < MMEYEPCMCIA_IOWINS; i++) {
841 if ((h->ioalloc & (1 << i)) == 0) {
842 win = i;
843 h->ioalloc |= (1 << i);
844 break;
845 }
846 }
847
848 if (win == -1)
849 return (1);
850
851 *windowp = win;
852
853 /* XXX this is pretty gross */
854
855 if (h->sc->iot != pcihp->iot)
856 panic("mmeyepcmcia_chip_io_map iot is bogus");
857
858 DPRINTF(("mmeyepcmcia_chip_io_map window %d %s port %lx+%lx\n",
859 win, width_names[width], (u_long) ioaddr, (u_long) size));
860
861 /* XXX wtf is this doing here? */
862
863 printf("%s: port 0x%lx", h->sc->dev.dv_xname, (u_long) ioaddr);
864 if (size > 1)
865 printf("-0x%lx", (u_long) ioaddr + (u_long) size - 1);
866 printf("\n");
867
868 h->io[win].addr = ioaddr;
869 h->io[win].size = size;
870 h->io[win].width = width;
871
872 pcihp->ioh = h->sc->memh + MMEYEPCMCIA_ATTRMEM_SIZE;
873
874 if (width == PCMCIA_WIDTH_IO8) { /* IO8 */
875 reg = mmeyepcmcia_read(h, MMEYEPCMCIA_IF_STATUS);
876 reg |= MMEYEPCMCIA_IF_STATUS_BUSWIDTH; /* Set bus width to 8bit */
877 mmeyepcmcia_write(h, MMEYEPCMCIA_IF_STATUS, reg);
878 }
879
880 return (0);
881 }
882
883 void
884 mmeyepcmcia_chip_io_unmap(pcmcia_chipset_handle_t pch, int window)
885 {
886 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch;
887
888 if (window >= MMEYEPCMCIA_IOWINS)
889 panic("mmeyepcmcia_chip_io_unmap: window out of range");
890
891 h->ioalloc &= ~(1 << window);
892 }
893
894 void
895 mmeyepcmcia_chip_socket_enable(pcmcia_chipset_handle_t pch)
896 {
897 }
898
899 void
900 mmeyepcmcia_chip_socket_disable(pcmcia_chipset_handle_t pch)
901 {
902 }
903