shpcic.c revision 1.2 1 /* $NetBSD: shpcic.c,v 1.2 1999/09/14 10:22:35 tsubai Exp $ */
2
3 #define SHPCICDEBUG
4
5 /*
6 * Copyright (c) 1997 Marc Horowitz. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Marc Horowitz.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/device.h>
38 #include <sys/extent.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/kthread.h>
42
43 #include <vm/vm.h>
44
45 #include <machine/bus.h>
46 #include <machine/intr.h>
47
48 #include <dev/pcmcia/pcmciareg.h>
49 #include <dev/pcmcia/pcmciavar.h>
50
51 #include <sh3/dev/shpcicreg.h>
52 #include <sh3/dev/shpcicvar.h>
53
54 #include "locators.h"
55
56 #ifdef SHPCICDEBUG
57 int shpcic_debug = 0;
58 #define DPRINTF(arg) if (shpcic_debug) printf arg;
59 #else
60 #define DPRINTF(arg)
61 #endif
62
63 #define PCIC_VENDOR_UNKNOWN 0
64 #define PCIC_VENDOR_HITACHI 1
65
66 /*
67 * Individual drivers will allocate their own memory and io regions. Memory
68 * regions must be a multiple of 4k, aligned on a 4k boundary.
69 */
70
71 #define SHPCIC_MEM_ALIGN SHPCIC_MEM_PAGESIZE
72
73 void shpcic_attach_socket __P((struct shpcic_handle *));
74 void shpcic_init_socket __P((struct shpcic_handle *));
75
76 int shpcic_submatch __P((struct device *, struct cfdata *, void *));
77 int shpcic_print __P((void *arg, const char *pnp));
78 int shpcic_intr_socket __P((struct shpcic_handle *));
79
80 void shpcic_attach_card __P((struct shpcic_handle *));
81 void shpcic_detach_card __P((struct shpcic_handle *, int));
82 void shpcic_deactivate_card __P((struct shpcic_handle *));
83
84 void shpcic_chip_do_mem_map __P((struct shpcic_handle *, int));
85 void shpcic_chip_do_io_map __P((struct shpcic_handle *, int));
86
87 void shpcic_create_event_thread __P((void *));
88 void shpcic_event_thread __P((void *));
89
90 void shpcic_queue_event __P((struct shpcic_handle *, int));
91
92 /* static void shpcic_wait_ready __P((struct shpcic_handle *)); */
93
94 int
95 shpcic_ident_ok(ident)
96 int ident;
97 {
98 /* this is very empirical and heuristic */
99
100 if ((ident == 0) || (ident == 0xff) || (ident & SHPCIC_IDENT_ZERO))
101 return (0);
102
103 if ((ident & SHPCIC_IDENT_IFTYPE_MASK) != SHPCIC_IDENT_IFTYPE_MEM_AND_IO) {
104 #ifdef DIAGNOSTIC
105 printf("shpcic: does not support memory and I/O cards, "
106 "ignored (ident=%0x)\n", ident);
107 #endif
108 return (0);
109 }
110 return (1);
111 }
112
113 int
114 shpcic_vendor(h)
115 struct shpcic_handle *h;
116 {
117 return (PCIC_VENDOR_HITACHI);
118 }
119
120 char *
121 shpcic_vendor_to_string(vendor)
122 int vendor;
123 {
124 switch (vendor) {
125 case PCIC_VENDOR_HITACHI:
126 return ("Hitachi SH");
127 }
128
129 return ("Unknown controller");
130 }
131
132 void
133 shpcic_attach(sc)
134 struct shpcic_softc *sc;
135 {
136 int vendor, count, i;
137
138 /* now check for each controller/socket */
139
140 /*
141 * this could be done with a loop, but it would violate the
142 * abstraction
143 */
144
145 count = 0;
146
147 #if 0
148 DPRINTF(("shpcic ident regs:"));
149 #endif
150
151 sc->handle[0].sc = sc;
152 sc->handle[0].sock = C0SA;
153 sc->handle[0].flags = SHPCIC_FLAG_SOCKETP;
154 sc->handle[0].laststate = SHPCIC_LASTSTATE_EMPTY;
155 count++;
156
157 sc->handle[1].sc = sc;
158 sc->handle[1].sock = C0SB;
159 sc->handle[1].flags = 0;
160 sc->handle[1].laststate = SHPCIC_LASTSTATE_EMPTY;
161 count++;
162
163 sc->handle[2].sc = sc;
164 sc->handle[2].sock = C1SA;
165 sc->handle[2].flags = 0;
166 sc->handle[2].laststate = SHPCIC_LASTSTATE_EMPTY;
167
168 sc->handle[3].sc = sc;
169 sc->handle[3].sock = C1SB;
170 sc->handle[3].flags = 0;
171 sc->handle[3].laststate = SHPCIC_LASTSTATE_EMPTY;
172
173 if (count == 0)
174 panic("shpcic_attach: attach found no sockets");
175
176 /* establish the interrupt */
177
178 /* XXX block interrupts? */
179
180 for (i = 0; i < SHPCIC_NSLOTS; i++) {
181 /*
182 * this should work, but w/o it, setting tty flags hangs at
183 * boot time.
184 */
185 if (sc->handle[i].flags & SHPCIC_FLAG_SOCKETP)
186 {
187 SIMPLEQ_INIT(&sc->handle[i].events);
188 #if 0
189 shpcic_write(&sc->handle[i], SHPCIC_CSC_INTR, 0);
190 shpcic_read(&sc->handle[i], SHPCIC_CSC);
191 #endif
192 }
193 }
194
195 if ((sc->handle[0].flags & SHPCIC_FLAG_SOCKETP) ||
196 (sc->handle[1].flags & SHPCIC_FLAG_SOCKETP)) {
197 vendor = shpcic_vendor(&sc->handle[0]);
198
199 printf("%s: controller 0 (%s) has ", sc->dev.dv_xname,
200 shpcic_vendor_to_string(vendor));
201
202 if ((sc->handle[0].flags & SHPCIC_FLAG_SOCKETP) &&
203 (sc->handle[1].flags & SHPCIC_FLAG_SOCKETP))
204 printf("sockets A and B\n");
205 else if (sc->handle[0].flags & SHPCIC_FLAG_SOCKETP)
206 printf("socket A only\n");
207 else
208 printf("socket B only\n");
209
210 if (sc->handle[0].flags & SHPCIC_FLAG_SOCKETP)
211 sc->handle[0].vendor = vendor;
212 if (sc->handle[1].flags & SHPCIC_FLAG_SOCKETP)
213 sc->handle[1].vendor = vendor;
214 }
215 }
216
217 void
218 shpcic_attach_sockets(sc)
219 struct shpcic_softc *sc;
220 {
221 int i;
222
223 for (i = 0; i < SHPCIC_NSLOTS; i++)
224 if (sc->handle[i].flags & SHPCIC_FLAG_SOCKETP)
225 shpcic_attach_socket(&sc->handle[i]);
226 }
227
228 void
229 shpcic_attach_socket(h)
230 struct shpcic_handle *h;
231 {
232 struct pcmciabus_attach_args paa;
233
234 /* initialize the rest of the handle */
235
236 h->shutdown = 0;
237 h->memalloc = 0;
238 h->ioalloc = 0;
239 h->ih_irq = 0;
240
241 /* now, config one pcmcia device per socket */
242
243 paa.pct = (pcmcia_chipset_tag_t) h->sc->pct;
244 paa.pch = (pcmcia_chipset_handle_t) h;
245 paa.iobase = h->sc->iobase;
246 paa.iosize = h->sc->iosize;
247
248 h->pcmcia = config_found_sm(&h->sc->dev, &paa, shpcic_print,
249 shpcic_submatch);
250
251 /* if there's actually a pcmcia device attached, initialize the slot */
252
253 if (h->pcmcia)
254 shpcic_init_socket(h);
255 }
256
257 void
258 shpcic_create_event_thread(arg)
259 void *arg;
260 {
261 struct shpcic_handle *h = arg;
262 const char *cs;
263
264 switch (h->sock) {
265 case C0SA:
266 cs = "0,0";
267 break;
268 case C0SB:
269 cs = "0,1";
270 break;
271 case C1SA:
272 cs = "1,0";
273 break;
274 case C1SB:
275 cs = "1,1";
276 break;
277 default:
278 panic("shpcic_create_event_thread: unknown pcic socket");
279 }
280
281 if (kthread_create1(shpcic_event_thread, h, &h->event_thread,
282 "%s,%s", h->sc->dev.dv_xname, cs)) {
283 printf("%s: unable to create event thread for sock 0x%02x\n",
284 h->sc->dev.dv_xname, h->sock);
285 panic("shpcic_create_event_thread");
286 }
287 }
288
289 void
290 shpcic_event_thread(arg)
291 void *arg;
292 {
293 struct shpcic_handle *h = arg;
294 struct shpcic_event *pe;
295 int s;
296
297 while (h->shutdown == 0) {
298 s = splhigh();
299 if ((pe = SIMPLEQ_FIRST(&h->events)) == NULL) {
300 splx(s);
301 (void) tsleep(&h->events, PWAIT, "shpcicev", 0);
302 continue;
303 } else {
304 splx(s);
305 /* sleep .25s to be enqueued chatterling interrupts */
306 (void) tsleep((caddr_t)shpcic_event_thread, PWAIT, "shpcicss", hz/4);
307 }
308 s = splhigh();
309 SIMPLEQ_REMOVE_HEAD(&h->events, pe, pe_q);
310 splx(s);
311
312 switch (pe->pe_type) {
313 case SHPCIC_EVENT_INSERTION:
314 s = splhigh();
315 while (1) {
316 struct shpcic_event *pe1, *pe2;
317
318 if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL)
319 break;
320 if (pe1->pe_type != SHPCIC_EVENT_REMOVAL)
321 break;
322 if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL)
323 break;
324 if (pe2->pe_type == SHPCIC_EVENT_INSERTION) {
325 SIMPLEQ_REMOVE_HEAD(&h->events, pe1, pe_q);
326 free(pe1, M_TEMP);
327 SIMPLEQ_REMOVE_HEAD(&h->events, pe2, pe_q);
328 free(pe2, M_TEMP);
329 }
330 }
331 splx(s);
332
333 DPRINTF(("%s: insertion event\n", h->sc->dev.dv_xname));
334 shpcic_attach_card(h);
335 break;
336
337 case SHPCIC_EVENT_REMOVAL:
338 s = splhigh();
339 while (1) {
340 struct shpcic_event *pe1, *pe2;
341
342 if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL)
343 break;
344 if (pe1->pe_type != SHPCIC_EVENT_INSERTION)
345 break;
346 if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL)
347 break;
348 if (pe2->pe_type == SHPCIC_EVENT_REMOVAL) {
349 SIMPLEQ_REMOVE_HEAD(&h->events, pe1, pe_q);
350 free(pe1, M_TEMP);
351 SIMPLEQ_REMOVE_HEAD(&h->events, pe2, pe_q);
352 free(pe2, M_TEMP);
353 }
354 }
355 splx(s);
356
357 DPRINTF(("%s: removal event\n", h->sc->dev.dv_xname));
358 shpcic_detach_card(h, DETACH_FORCE);
359 break;
360
361 default:
362 panic("shpcic_event_thread: unknown event %d",
363 pe->pe_type);
364 }
365 free(pe, M_TEMP);
366 }
367
368 h->event_thread = NULL;
369
370 /* In case parent is waiting for us to exit. */
371 wakeup(h->sc);
372
373 kthread_exit(0);
374 }
375
376 void
377 shpcic_init_socket(h)
378 struct shpcic_handle *h;
379 {
380 int reg;
381
382 /*
383 * queue creation of a kernel thread to handle insert/removal events.
384 */
385 #ifdef DIAGNOSTIC
386 if (h->event_thread != NULL)
387 panic("shpcic_attach_socket: event thread");
388 #endif
389 kthread_create(shpcic_create_event_thread, h);
390
391 /* if there's a card there, then attach it. */
392
393 reg = shpcic_read(h, SHPCIC_IF_STATUS);
394 reg &= ~SHPCIC_IF_STATUS_BUSWIDTH; /* Set bus width to 16bit */
395
396 if ((reg & SHPCIC_IF_STATUS_CARDDETECT_MASK) ==
397 SHPCIC_IF_STATUS_CARDDETECT_PRESENT) {
398 int i;
399
400 /* reset the card */
401 shpcic_write(h, SHPCIC_IF_STATUS, reg|SHPCIC_IF_STATUS_RESET);
402 delay(1000); /* wait 1000 uSec */
403 shpcic_write(h, SHPCIC_IF_STATUS,
404 reg & ~SHPCIC_IF_STATUS_RESET);
405 for (i = 0; i < 10000; i++)
406 delay(1000); /* wait 1 mSec */
407
408 shpcic_attach_card(h);
409 h->laststate = SHPCIC_LASTSTATE_PRESENT;
410 } else {
411 h->laststate = SHPCIC_LASTSTATE_EMPTY;
412 }
413 }
414
415 int
416 shpcic_submatch(parent, cf, aux)
417 struct device *parent;
418 struct cfdata *cf;
419 void *aux;
420 {
421
422 struct pcmciabus_attach_args *paa = aux;
423 struct shpcic_handle *h = (struct shpcic_handle *) paa->pch;
424
425 switch (h->sock) {
426 case C0SA:
427 #ifdef TODO
428 if (cf->cf_loc[PCMCIABUSCF_CONTROLLER] !=
429 PCMCIABUSCF_CONTROLLER_DEFAULT &&
430 cf->cf_loc[PCMCIABUSCF_CONTROLLER] != 0)
431 return 0;
432 if (cf->cf_loc[PCMCIABUSCF_SOCKET] !=
433 PCMCIABUSCF_SOCKET_DEFAULT &&
434 cf->cf_loc[PCMCIABUSCF_SOCKET] != 0)
435 return 0;
436 #endif
437
438 break;
439 case C0SB:
440 #ifdef TODO
441 if (cf->cf_loc[PCMCIABUSCF_CONTROLLER] !=
442 PCMCIABUSCF_CONTROLLER_DEFAULT &&
443 cf->cf_loc[PCMCIABUSCF_CONTROLLER] != 0)
444 return 0;
445 if (cf->cf_loc[PCMCIABUSCF_SOCKET] !=
446 PCMCIABUSCF_SOCKET_DEFAULT &&
447 cf->cf_loc[PCMCIABUSCF_SOCKET] != 1)
448 return 0;
449 #endif
450
451 break;
452 case C1SA:
453 if (cf->cf_loc[PCMCIABUSCF_CONTROLLER] !=
454 PCMCIABUSCF_CONTROLLER_DEFAULT &&
455 cf->cf_loc[PCMCIABUSCF_CONTROLLER] != 1)
456 return 0;
457 if (cf->cf_loc[PCMCIABUSCF_SOCKET] !=
458 PCMCIABUSCF_SOCKET_DEFAULT &&
459 cf->cf_loc[PCMCIABUSCF_SOCKET] != 0)
460 return 0;
461
462 break;
463 case C1SB:
464 if (cf->cf_loc[PCMCIABUSCF_CONTROLLER] !=
465 PCMCIABUSCF_CONTROLLER_DEFAULT &&
466 cf->cf_loc[PCMCIABUSCF_CONTROLLER] != 1)
467 return 0;
468 if (cf->cf_loc[PCMCIABUSCF_SOCKET] !=
469 PCMCIABUSCF_SOCKET_DEFAULT &&
470 cf->cf_loc[PCMCIABUSCF_SOCKET] != 1)
471 return 0;
472
473 break;
474 default:
475 panic("unknown pcic socket");
476 }
477
478 return ((*cf->cf_attach->ca_match)(parent, cf, aux));
479 }
480
481 int
482 shpcic_print(arg, pnp)
483 void *arg;
484 const char *pnp;
485 {
486 struct pcmciabus_attach_args *paa = arg;
487 struct shpcic_handle *h = (struct shpcic_handle *) paa->pch;
488
489 /* Only "pcmcia"s can attach to "pcic"s... easy. */
490 if (pnp)
491 printf("pcmcia at %s", pnp);
492
493 switch (h->sock) {
494 case C0SA:
495 printf(" controller 0 socket 0");
496 break;
497 case C0SB:
498 printf(" controller 0 socket 1");
499 break;
500 case C1SA:
501 printf(" controller 1 socket 0");
502 break;
503 case C1SB:
504 printf(" controller 1 socket 1");
505 break;
506 default:
507 panic("unknown pcic socket");
508 }
509
510 return (UNCONF);
511 }
512
513 int
514 shpcic_intr(arg)
515 void *arg;
516 {
517 struct shpcic_softc *sc = arg;
518 int i, ret = 0;
519
520 DPRINTF(("%s: intr\n", sc->dev.dv_xname));
521
522 for (i = 0; i < SHPCIC_NSLOTS; i++)
523 if (sc->handle[i].flags & SHPCIC_FLAG_SOCKETP)
524 ret += shpcic_intr_socket(&sc->handle[i]);
525
526 return (ret ? 1 : 0);
527 }
528
529 int
530 shpcic_intr_socket(h)
531 struct shpcic_handle *h;
532 {
533 int cscreg;
534
535 cscreg = shpcic_read(h, SHPCIC_CSC);
536
537 cscreg &= (SHPCIC_CSC_GPI |
538 SHPCIC_CSC_CD |
539 SHPCIC_CSC_READY |
540 SHPCIC_CSC_BATTWARN |
541 SHPCIC_CSC_BATTDEAD);
542
543 if (cscreg & SHPCIC_CSC_GPI) {
544 DPRINTF(("%s: %02x GPI\n", h->sc->dev.dv_xname, h->sock));
545 }
546 if (cscreg & SHPCIC_CSC_CD) {
547 int statreg;
548
549 statreg = shpcic_read(h, SHPCIC_IF_STATUS);
550
551 DPRINTF(("%s: %02x CD %x\n", h->sc->dev.dv_xname, h->sock,
552 statreg));
553
554 if ((statreg & SHPCIC_IF_STATUS_CARDDETECT_MASK) ==
555 SHPCIC_IF_STATUS_CARDDETECT_PRESENT) {
556 if (h->laststate != SHPCIC_LASTSTATE_PRESENT) {
557 DPRINTF(("%s: enqueing INSERTION event\n",
558 h->sc->dev.dv_xname));
559 shpcic_queue_event(h, SHPCIC_EVENT_INSERTION);
560 }
561 h->laststate = SHPCIC_LASTSTATE_PRESENT;
562 } else {
563 if (h->laststate == SHPCIC_LASTSTATE_PRESENT) {
564 /* Deactivate the card now. */
565 DPRINTF(("%s: deactivating card\n",
566 h->sc->dev.dv_xname));
567 shpcic_deactivate_card(h);
568
569 DPRINTF(("%s: enqueing REMOVAL event\n",
570 h->sc->dev.dv_xname));
571 shpcic_queue_event(h, SHPCIC_EVENT_REMOVAL);
572 }
573 h->laststate = ((statreg & SHPCIC_IF_STATUS_CARDDETECT_MASK) == 0)
574 ? SHPCIC_LASTSTATE_EMPTY : SHPCIC_LASTSTATE_HALF;
575 }
576 }
577 if (cscreg & SHPCIC_CSC_READY) {
578 DPRINTF(("%s: %02x READY\n", h->sc->dev.dv_xname, h->sock));
579 /* shouldn't happen */
580 }
581 if (cscreg & SHPCIC_CSC_BATTWARN) {
582 DPRINTF(("%s: %02x BATTWARN\n", h->sc->dev.dv_xname, h->sock));
583 }
584 if (cscreg & SHPCIC_CSC_BATTDEAD) {
585 DPRINTF(("%s: %02x BATTDEAD\n", h->sc->dev.dv_xname, h->sock));
586 }
587 return (cscreg ? 1 : 0);
588 }
589
590 void
591 shpcic_queue_event(h, event)
592 struct shpcic_handle *h;
593 int event;
594 {
595 struct shpcic_event *pe;
596 int s;
597
598 pe = malloc(sizeof(*pe), M_TEMP, M_NOWAIT);
599 if (pe == NULL)
600 panic("shpcic_queue_event: can't allocate event");
601
602 pe->pe_type = event;
603 s = splhigh();
604 SIMPLEQ_INSERT_TAIL(&h->events, pe, pe_q);
605 splx(s);
606 wakeup(&h->events);
607 }
608
609 void
610 shpcic_attach_card(h)
611 struct shpcic_handle *h;
612 {
613
614 if (!(h->flags & SHPCIC_FLAG_CARDP)) {
615 /* call the MI attach function */
616 pcmcia_card_attach(h->pcmcia);
617
618 h->flags |= SHPCIC_FLAG_CARDP;
619 } else {
620 DPRINTF(("shpcic_attach_card: already attached"));
621 }
622 }
623
624 void
625 shpcic_detach_card(h, flags)
626 struct shpcic_handle *h;
627 int flags; /* DETACH_* */
628 {
629
630 if (h->flags & SHPCIC_FLAG_CARDP) {
631 h->flags &= ~SHPCIC_FLAG_CARDP;
632
633 /* call the MI detach function */
634 pcmcia_card_detach(h->pcmcia, flags);
635 } else {
636 DPRINTF(("shpcic_detach_card: already detached"));
637 }
638 }
639
640 void
641 shpcic_deactivate_card(h)
642 struct shpcic_handle *h;
643 {
644
645 /* call the MI deactivate function */
646 pcmcia_card_deactivate(h->pcmcia);
647
648 #if 0
649 /* power down the socket */
650 shpcic_write(h, SHPCIC_PWRCTL, 0);
651
652 /* reset the socket */
653 shpcic_write(h, SHPCIC_INTR, 0);
654 #endif
655 }
656
657 int
658 shpcic_chip_mem_alloc(pch, size, pcmhp)
659 pcmcia_chipset_handle_t pch;
660 bus_size_t size;
661 struct pcmcia_mem_handle *pcmhp;
662 {
663 struct shpcic_handle *h = (struct shpcic_handle *) pch;
664 bus_space_handle_t memh = 0;
665 bus_addr_t addr;
666 bus_size_t sizepg;
667 int i, mask, mhandle;
668
669 /* out of sc->memh, allocate as many pages as necessary */
670
671 /* convert size to PCIC pages */
672 sizepg = (size + (SHPCIC_MEM_ALIGN - 1)) / SHPCIC_MEM_ALIGN;
673 if (sizepg > SHPCIC_MAX_MEM_PAGES)
674 return (1);
675
676 mask = (1 << sizepg) - 1;
677
678 addr = 0; /* XXX gcc -Wuninitialized */
679 mhandle = 0; /* XXX gcc -Wuninitialized */
680
681 for (i = 0; i <= SHPCIC_MAX_MEM_PAGES - sizepg; i++) {
682 if ((h->sc->subregionmask & (mask << i)) == (mask << i)) {
683 #if 0
684 if (bus_space_subregion(h->sc->memt, h->sc->memh,
685 i * SHPCIC_MEM_PAGESIZE,
686 sizepg * SHPCIC_MEM_PAGESIZE, &memh))
687 return (1);
688 #endif
689 memh = h->sc->memh;
690 mhandle = mask << i;
691 addr = h->sc->membase + (i * SHPCIC_MEM_PAGESIZE);
692 h->sc->subregionmask &= ~(mhandle);
693 pcmhp->memt = h->sc->memt;
694 pcmhp->memh = memh;
695 pcmhp->addr = addr;
696 pcmhp->size = size;
697 pcmhp->mhandle = mhandle;
698 pcmhp->realsize = sizepg * SHPCIC_MEM_PAGESIZE;
699 return (0);
700 }
701 }
702
703 return (1);
704 }
705
706 void
707 shpcic_chip_mem_free(pch, pcmhp)
708 pcmcia_chipset_handle_t pch;
709 struct pcmcia_mem_handle *pcmhp;
710 {
711 struct shpcic_handle *h = (struct shpcic_handle *) pch;
712
713 h->sc->subregionmask |= pcmhp->mhandle;
714 }
715
716 int
717 shpcic_chip_mem_map(pch, kind, card_addr, size, pcmhp, offsetp, windowp)
718 pcmcia_chipset_handle_t pch;
719 int kind;
720 bus_addr_t card_addr;
721 bus_size_t size;
722 struct pcmcia_mem_handle *pcmhp;
723 bus_addr_t *offsetp;
724 int *windowp;
725 {
726 struct shpcic_handle *h = (struct shpcic_handle *) pch;
727 bus_addr_t busaddr;
728 long card_offset;
729 int i, win;
730
731 win = -1;
732 for (i = 0; i < SHPCIC_WINS;
733 i++) {
734 if ((h->memalloc & (1 << i)) == 0) {
735 win = i;
736 h->memalloc |= (1 << i);
737 break;
738 }
739 }
740
741 if (win == -1)
742 return (1);
743
744 *windowp = win;
745
746 /* XXX this is pretty gross */
747
748 if (h->sc->memt != pcmhp->memt)
749 panic("shpcic_chip_mem_map memt is bogus");
750
751 busaddr = pcmhp->addr;
752
753 /*
754 * compute the address offset to the pcmcia address space for the
755 * pcic. this is intentionally signed. The masks and shifts below
756 * will cause TRT to happen in the pcic registers. Deal with making
757 * sure the address is aligned, and return the alignment offset.
758 */
759
760 *offsetp = 0;
761 card_addr -= *offsetp;
762
763 DPRINTF(("shpcic_chip_mem_map window %d bus %lx+%lx+%lx at card addr "
764 "%lx\n", win, (u_long) busaddr, (u_long) * offsetp, (u_long) size,
765 (u_long) card_addr));
766
767 /*
768 * include the offset in the size, and decrement size by one, since
769 * the hw wants start/stop
770 */
771 size += *offsetp - 1;
772
773 card_offset = (((long) card_addr) - ((long) busaddr));
774
775 h->mem[win].addr = busaddr;
776 h->mem[win].size = size;
777 h->mem[win].offset = card_offset;
778 h->mem[win].kind = kind;
779
780 if (kind == PCMCIA_MEM_ATTR) {
781 pcmhp->memh = h->sc->memh + card_addr;
782 } else {
783 pcmhp->memh = h->sc->memh + card_addr + SHPCIC_ATTRMEM_SIZE;
784 }
785 #if 0
786 shpcic_chip_do_mem_map(h, win);
787 #endif
788
789 return (0);
790 }
791
792 void
793 shpcic_chip_mem_unmap(pch, window)
794 pcmcia_chipset_handle_t pch;
795 int window;
796 {
797 struct shpcic_handle *h = (struct shpcic_handle *) pch;
798
799 if (window >= SHPCIC_WINS)
800 panic("shpcic_chip_mem_unmap: window out of range");
801
802 h->memalloc &= ~(1 << window);
803 }
804
805 int
806 shpcic_chip_io_alloc(pch, start, size, align, pcihp)
807 pcmcia_chipset_handle_t pch;
808 bus_addr_t start;
809 bus_size_t size;
810 bus_size_t align;
811 struct pcmcia_io_handle *pcihp;
812 {
813 struct shpcic_handle *h = (struct shpcic_handle *) pch;
814 bus_space_tag_t iot;
815 bus_space_handle_t ioh;
816 bus_addr_t ioaddr;
817 int flags = 0;
818
819 /*
820 * Allocate some arbitrary I/O space.
821 */
822
823 iot = h->sc->iot;
824
825 if (start) {
826 ioaddr = start;
827 if (bus_space_map(iot, start, size, 0, &ioh))
828 return (1);
829 DPRINTF(("shpcic_chip_io_alloc map port %lx+%lx\n",
830 (u_long) ioaddr, (u_long) size));
831 } else {
832 flags |= PCMCIA_IO_ALLOCATED;
833 if (bus_space_alloc(iot, h->sc->iobase,
834 h->sc->iobase + h->sc->iosize, size, align, 0, 0,
835 &ioaddr, &ioh))
836 return (1);
837 DPRINTF(("shpcic_chip_io_alloc alloc port %lx+%lx\n",
838 (u_long) ioaddr, (u_long) size));
839 }
840
841 pcihp->iot = iot;
842 pcihp->ioh = ioh + h->sc->memh + SHPCIC_ATTRMEM_SIZE;;
843 pcihp->addr = ioaddr;
844 pcihp->size = size;
845 pcihp->flags = flags;
846
847 return (0);
848 }
849
850 void
851 shpcic_chip_io_free(pch, pcihp)
852 pcmcia_chipset_handle_t pch;
853 struct pcmcia_io_handle *pcihp;
854 {
855 bus_space_tag_t iot = pcihp->iot;
856 bus_space_handle_t ioh = pcihp->ioh;
857 bus_size_t size = pcihp->size;
858
859 if (pcihp->flags & PCMCIA_IO_ALLOCATED)
860 bus_space_free(iot, ioh, size);
861 else
862 bus_space_unmap(iot, ioh, size);
863 }
864
865 int
866 shpcic_chip_io_map(pch, width, offset, size, pcihp, windowp)
867 pcmcia_chipset_handle_t pch;
868 int width;
869 bus_addr_t offset;
870 bus_size_t size;
871 struct pcmcia_io_handle *pcihp;
872 int *windowp;
873 {
874 struct shpcic_handle *h = (struct shpcic_handle *) pch;
875 bus_addr_t ioaddr = pcihp->addr + offset;
876 int i, win;
877 #ifdef SHPCICDEBUG
878 static char *width_names[] = { "auto", "io8", "io16" };
879 #endif
880 int reg;
881
882 /* XXX Sanity check offset/size. */
883
884 #ifdef MMEYE
885 /* I/O width is hardwired to 16bit mode on mmeye. */
886 width = PCMCIA_WIDTH_IO16;
887 #endif
888
889 win = -1;
890 for (i = 0; i < SHPCIC_IOWINS; i++) {
891 if ((h->ioalloc & (1 << i)) == 0) {
892 win = i;
893 h->ioalloc |= (1 << i);
894 break;
895 }
896 }
897
898 if (win == -1)
899 return (1);
900
901 *windowp = win;
902
903 /* XXX this is pretty gross */
904
905 if (h->sc->iot != pcihp->iot)
906 panic("shpcic_chip_io_map iot is bogus");
907
908 DPRINTF(("shpcic_chip_io_map window %d %s port %lx+%lx\n",
909 win, width_names[width], (u_long) ioaddr, (u_long) size));
910
911 /* XXX wtf is this doing here? */
912
913 printf(" port 0x%lx", (u_long) ioaddr);
914 if (size > 1)
915 printf("-0x%lx", (u_long) ioaddr + (u_long) size - 1);
916
917 h->io[win].addr = ioaddr;
918 h->io[win].size = size;
919 h->io[win].width = width;
920
921 pcihp->ioh = h->sc->memh + SHPCIC_ATTRMEM_SIZE;
922
923 if (width == PCMCIA_WIDTH_IO8) { /* IO8 */
924 reg = shpcic_read(h, SHPCIC_IF_STATUS);
925 reg |= SHPCIC_IF_STATUS_BUSWIDTH; /* Set bus width to 8bit */
926 shpcic_write(h, SHPCIC_IF_STATUS, reg);
927 }
928
929 #if 0
930 shpcic_chip_do_io_map(h, win);
931 #endif
932
933 return (0);
934 }
935
936 void
937 shpcic_chip_io_unmap(pch, window)
938 pcmcia_chipset_handle_t pch;
939 int window;
940 {
941 struct shpcic_handle *h = (struct shpcic_handle *) pch;
942
943 if (window >= SHPCIC_IOWINS)
944 panic("shpcic_chip_io_unmap: window out of range");
945
946 h->ioalloc &= ~(1 << window);
947 }
948
949 #if 0
950 static void
951 shpcic_wait_ready(h)
952 struct shpcic_handle *h;
953 {
954 int i;
955
956 for (i = 0; i < 10000; i++) {
957 if (shpcic_read(h, SHPCIC_IF_STATUS) & SHPCIC_IF_STATUS_READY)
958 return;
959 delay(500);
960 #ifdef SHPCICDEBUG
961 if (shpcic_debug) {
962 if ((i>5000) && (i%100 == 99))
963 printf(".");
964 }
965 #endif
966 }
967
968 #ifdef DIAGNOSTIC
969 printf("shpcic_wait_ready: ready never happened, status = %02x\n",
970 shpcic_read(h, SHPCIC_IF_STATUS));
971 #endif
972 }
973 #endif
974
975 void
976 shpcic_chip_socket_enable(pch)
977 pcmcia_chipset_handle_t pch;
978 {
979 #if 0
980 struct shpcic_handle *h = (struct shpcic_handle *) pch;
981 int cardtype, reg, win;
982
983 /* this bit is mostly stolen from shpcic_attach_card */
984
985 /* power down the socket to reset it, clear the card reset pin */
986
987 shpcic_write(h, SHPCIC_PWRCTL, 0);
988
989 /*
990 * wait 300ms until power fails (Tpf). Then, wait 100ms since
991 * we are changing Vcc (Toff).
992 */
993 delay((300 + 100) * 1000);
994
995 #ifdef VADEM_POWER_HACK
996 bus_space_write_1(h->sc->iot, h->sc->ioh, SHPCIC_REG_INDEX, 0x0e);
997 bus_space_write_1(h->sc->iot, h->sc->ioh, SHPCIC_REG_INDEX, 0x37);
998 printf("prcr = %02x\n", shpcic_read(h, 0x02));
999 printf("cvsr = %02x\n", shpcic_read(h, 0x2f));
1000 printf("DANGER WILL ROBINSON! Changing voltage select!\n");
1001 shpcic_write(h, 0x2f, shpcic_read(h, 0x2f) & ~0x03);
1002 printf("cvsr = %02x\n", shpcic_read(h, 0x2f));
1003 #endif
1004
1005 /* power up the socket */
1006
1007 shpcic_write(h, SHPCIC_PWRCTL, SHPCIC_PWRCTL_DISABLE_RESETDRV
1008 | SHPCIC_PWRCTL_PWR_ENABLE);
1009
1010 /*
1011 * wait 100ms until power raise (Tpr) and 20ms to become
1012 * stable (Tsu(Vcc)).
1013 *
1014 * some machines require some more time to be settled
1015 * (300ms is added here).
1016 */
1017 delay((100 + 20 + 300) * 1000);
1018
1019 shpcic_write(h, SHPCIC_PWRCTL, SHPCIC_PWRCTL_DISABLE_RESETDRV | SHPCIC_PWRCTL_OE
1020 | SHPCIC_PWRCTL_PWR_ENABLE);
1021 shpcic_write(h, SHPCIC_INTR, 0);
1022
1023 /*
1024 * hold RESET at least 10us.
1025 */
1026 delay(10);
1027
1028 /* clear the reset flag */
1029
1030 shpcic_write(h, SHPCIC_INTR, SHPCIC_INTR_RESET);
1031
1032 /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
1033
1034 delay(20000);
1035
1036 /* wait for the chip to finish initializing */
1037
1038 #ifdef DIAGNOSTIC
1039 reg = shpcic_read(h, SHPCIC_IF_STATUS);
1040 if (!(reg & SHPCIC_IF_STATUS_POWERACTIVE)) {
1041 printf("shpcic_chip_socket_enable: status %x", reg);
1042 }
1043 #endif
1044
1045 shpcic_wait_ready(h);
1046
1047 /* zero out the address windows */
1048
1049 shpcic_write(h, SHPCIC_ADDRWIN_ENABLE, 0);
1050
1051 /* set the card type */
1052
1053 cardtype = pcmcia_card_gettype(h->pcmcia);
1054
1055 reg = shpcic_read(h, SHPCIC_INTR);
1056 reg &= ~(SHPCIC_INTR_CARDTYPE_MASK | SHPCIC_INTR_IRQ_MASK | SHPCIC_INTR_ENABLE);
1057 reg |= ((cardtype == PCMCIA_IFTYPE_IO) ?
1058 SHPCIC_INTR_CARDTYPE_IO :
1059 SHPCIC_INTR_CARDTYPE_MEM);
1060 reg |= h->ih_irq;
1061 shpcic_write(h, SHPCIC_INTR, reg);
1062
1063 DPRINTF(("%s: shpcic_chip_socket_enable %02x cardtype %s %02x\n",
1064 h->sc->dev.dv_xname, h->sock,
1065 ((cardtype == PCMCIA_IFTYPE_IO) ? "io" : "mem"), reg));
1066
1067 /* reinstall all the memory and io mappings */
1068
1069 for (win = 0; win < SHPCIC_MEM_WINS; win++)
1070 if (h->memalloc & (1 << win))
1071 shpcic_chip_do_mem_map(h, win);
1072
1073 for (win = 0; win < SHPCIC_IO_WINS; win++)
1074 if (h->ioalloc & (1 << win))
1075 shpcic_chip_do_io_map(h, win);
1076 #endif
1077 }
1078
1079 void
1080 shpcic_chip_socket_disable(pch)
1081 pcmcia_chipset_handle_t pch;
1082 {
1083 #if 0
1084 struct shpcic_handle *h = (struct shpcic_handle *) pch;
1085
1086 DPRINTF(("shpcic_chip_socket_disable\n"));
1087
1088 /* power down the socket */
1089
1090 shpcic_write(h, SHPCIC_PWRCTL, 0);
1091
1092 /*
1093 * wait 300ms until power fails (Tpf).
1094 */
1095 delay(300 * 1000);
1096 #endif
1097 }
1098