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