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