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