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