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