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