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