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