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