1 /* $NetBSD: mmeyepcmcia.c,v 1.1 2002/03/24 18:08:46 uch 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 struct cfattach mmeyepcmcia_ca = { 241 sizeof(struct mmeyepcmcia_softc), mmeyepcmcia_match, 242 mmeyepcmcia_attach 243 }; 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_sm(&h->sc->dev, &paa, mmeyepcmcia_print, 363 mmeyepcmcia_submatch); 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, 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, pe1, pe_q); 421 free(pe1, M_TEMP); 422 SIMPLEQ_REMOVE_HEAD(&h->events, pe2, 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, pe1, pe_q); 445 free(pe1, M_TEMP); 446 SIMPLEQ_REMOVE_HEAD(&h->events, pe2, 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_submatch(struct device *parent, struct cfdata *cf, void *aux) 511 { 512 513 return ((*cf->cf_attach->ca_match)(parent, cf, aux)); 514 } 515 516 int 517 mmeyepcmcia_print(void *arg, const char *pnp) 518 { 519 520 if (pnp) 521 printf("pcmcia at %s", pnp); 522 523 return (UNCONF); 524 } 525 526 int 527 mmeyepcmcia_intr(void *arg) 528 { 529 struct mmeyepcmcia_softc *sc = arg; 530 531 DPRINTF(("%s: intr\n", sc->dev.dv_xname)); 532 533 mmeyepcmcia_intr_socket(&sc->handle[0]); 534 535 return (0); 536 } 537 538 int 539 mmeyepcmcia_intr_socket(struct mmeyepcmcia_handle *h) 540 { 541 int cscreg; 542 543 cscreg = mmeyepcmcia_read(h, MMEYEPCMCIA_CSC); 544 545 cscreg &= (MMEYEPCMCIA_CSC_GPI | 546 MMEYEPCMCIA_CSC_CD | 547 MMEYEPCMCIA_CSC_READY | 548 MMEYEPCMCIA_CSC_BATTWARN | 549 MMEYEPCMCIA_CSC_BATTDEAD); 550 551 if (cscreg & MMEYEPCMCIA_CSC_GPI) { 552 DPRINTF(("%s: %02x GPI\n", h->sc->dev.dv_xname, h->sock)); 553 } 554 if (cscreg & MMEYEPCMCIA_CSC_CD) { 555 int statreg; 556 557 statreg = mmeyepcmcia_read(h, MMEYEPCMCIA_IF_STATUS); 558 559 DPRINTF(("%s: %02x CD %x\n", h->sc->dev.dv_xname, h->sock, 560 statreg)); 561 562 if ((statreg & MMEYEPCMCIA_IF_STATUS_CARDDETECT_MASK) == 563 MMEYEPCMCIA_IF_STATUS_CARDDETECT_PRESENT) { 564 if (h->laststate != MMEYEPCMCIA_LASTSTATE_PRESENT) { 565 DPRINTF(("%s: enqueing INSERTION event\n", 566 h->sc->dev.dv_xname)); 567 mmeyepcmcia_queue_event(h, MMEYEPCMCIA_EVENT_INSERTION); 568 } 569 h->laststate = MMEYEPCMCIA_LASTSTATE_PRESENT; 570 } else { 571 if (h->laststate == MMEYEPCMCIA_LASTSTATE_PRESENT) { 572 /* Deactivate the card now. */ 573 DPRINTF(("%s: deactivating card\n", 574 h->sc->dev.dv_xname)); 575 mmeyepcmcia_deactivate_card(h); 576 577 DPRINTF(("%s: enqueing REMOVAL event\n", 578 h->sc->dev.dv_xname)); 579 mmeyepcmcia_queue_event(h, MMEYEPCMCIA_EVENT_REMOVAL); 580 } 581 h->laststate = ((statreg & MMEYEPCMCIA_IF_STATUS_CARDDETECT_MASK) == 0) 582 ? MMEYEPCMCIA_LASTSTATE_EMPTY : MMEYEPCMCIA_LASTSTATE_HALF; 583 } 584 } 585 if (cscreg & MMEYEPCMCIA_CSC_READY) { 586 DPRINTF(("%s: %02x READY\n", h->sc->dev.dv_xname, h->sock)); 587 /* shouldn't happen */ 588 } 589 if (cscreg & MMEYEPCMCIA_CSC_BATTWARN) { 590 DPRINTF(("%s: %02x BATTWARN\n", h->sc->dev.dv_xname, h->sock)); 591 } 592 if (cscreg & MMEYEPCMCIA_CSC_BATTDEAD) { 593 DPRINTF(("%s: %02x BATTDEAD\n", h->sc->dev.dv_xname, h->sock)); 594 } 595 return (cscreg ? 1 : 0); 596 } 597 598 void 599 mmeyepcmcia_queue_event(struct mmeyepcmcia_handle *h, int event) 600 { 601 struct mmeyepcmcia_event *pe; 602 int s; 603 604 pe = malloc(sizeof(*pe), M_TEMP, M_NOWAIT); 605 if (pe == NULL) 606 panic("mmeyepcmcia_queue_event: can't allocate event"); 607 608 pe->pe_type = event; 609 s = splhigh(); 610 SIMPLEQ_INSERT_TAIL(&h->events, pe, pe_q); 611 splx(s); 612 wakeup(&h->events); 613 } 614 615 void 616 mmeyepcmcia_attach_card(struct mmeyepcmcia_handle *h) 617 { 618 619 if (!(h->flags & MMEYEPCMCIA_FLAG_CARDP)) { 620 /* call the MI attach function */ 621 pcmcia_card_attach(h->pcmcia); 622 623 h->flags |= MMEYEPCMCIA_FLAG_CARDP; 624 } else { 625 DPRINTF(("mmeyepcmcia_attach_card: already attached")); 626 } 627 } 628 629 void 630 mmeyepcmcia_detach_card(struct mmeyepcmcia_handle *h, int flags) 631 { 632 633 if (h->flags & MMEYEPCMCIA_FLAG_CARDP) { 634 h->flags &= ~MMEYEPCMCIA_FLAG_CARDP; 635 636 /* call the MI detach function */ 637 pcmcia_card_detach(h->pcmcia, flags); 638 } else { 639 DPRINTF(("mmeyepcmcia_detach_card: already detached")); 640 } 641 } 642 643 void 644 mmeyepcmcia_deactivate_card(struct mmeyepcmcia_handle *h) 645 { 646 647 /* call the MI deactivate function */ 648 pcmcia_card_deactivate(h->pcmcia); 649 650 /* Power down and reset XXX notyet */ 651 } 652 653 int 654 mmeyepcmcia_chip_mem_alloc(pcmcia_chipset_handle_t pch, bus_size_t size, 655 struct pcmcia_mem_handle *pcmhp) 656 { 657 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch; 658 bus_space_handle_t memh = 0; 659 bus_addr_t addr; 660 bus_size_t sizepg; 661 int i, mask, mhandle; 662 663 /* out of sc->memh, allocate as many pages as necessary */ 664 #define MMEYEPCMCIA_MEM_ALIGN MMEYEPCMCIA_MEM_PAGESIZE 665 /* convert size to PCIC pages */ 666 sizepg = (size + (MMEYEPCMCIA_MEM_ALIGN - 1)) / MMEYEPCMCIA_MEM_ALIGN; 667 if (sizepg > MMEYEPCMCIA_MAX_MEM_PAGES) 668 return (1); 669 670 mask = (1 << sizepg) - 1; 671 672 addr = 0; /* XXX gcc -Wuninitialized */ 673 mhandle = 0; /* XXX gcc -Wuninitialized */ 674 675 for (i = 0; i <= MMEYEPCMCIA_MAX_MEM_PAGES - sizepg; i++) { 676 if ((h->sc->subregionmask & (mask << i)) == (mask << i)) { 677 #if 0 678 if (bus_space_subregion(h->sc->memt, h->sc->memh, 679 i * MMEYEPCMCIA_MEM_PAGESIZE, 680 sizepg * MMEYEPCMCIA_MEM_PAGESIZE, &memh)) 681 return (1); 682 #endif 683 memh = h->sc->memh; 684 mhandle = mask << i; 685 addr = h->sc->membase + (i * MMEYEPCMCIA_MEM_PAGESIZE); 686 h->sc->subregionmask &= ~(mhandle); 687 pcmhp->memt = h->sc->memt; 688 pcmhp->memh = memh; 689 pcmhp->addr = addr; 690 pcmhp->size = size; 691 pcmhp->mhandle = mhandle; 692 pcmhp->realsize = sizepg * MMEYEPCMCIA_MEM_PAGESIZE; 693 return (0); 694 } 695 } 696 697 return (1); 698 } 699 700 void 701 mmeyepcmcia_chip_mem_free(pcmcia_chipset_handle_t pch, 702 struct pcmcia_mem_handle *pcmhp) 703 { 704 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch; 705 706 h->sc->subregionmask |= pcmhp->mhandle; 707 } 708 709 int 710 mmeyepcmcia_chip_mem_map(pcmcia_chipset_handle_t pch, int kind, 711 bus_addr_t card_addr, bus_size_t size, struct pcmcia_mem_handle *pcmhp, 712 bus_size_t *offsetp, int *windowp) 713 { 714 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch; 715 bus_addr_t busaddr; 716 long card_offset; 717 int i, win; 718 719 win = -1; 720 for (i = 0; i < MMEYEPCMCIA_WINS; 721 i++) { 722 if ((h->memalloc & (1 << i)) == 0) { 723 win = i; 724 h->memalloc |= (1 << i); 725 break; 726 } 727 } 728 729 if (win == -1) 730 return (1); 731 732 *windowp = win; 733 734 /* XXX this is pretty gross */ 735 736 if (h->sc->memt != pcmhp->memt) 737 panic("mmeyepcmcia_chip_mem_map memt is bogus"); 738 739 busaddr = pcmhp->addr; 740 741 /* 742 * compute the address offset to the pcmcia address space for the 743 * pcic. this is intentionally signed. The masks and shifts below 744 * will cause TRT to happen in the pcic registers. Deal with making 745 * sure the address is aligned, and return the alignment offset. 746 */ 747 748 *offsetp = 0; 749 card_addr -= *offsetp; 750 751 DPRINTF(("mmeyepcmcia_chip_mem_map window %d bus %lx+%lx+%lx at card addr " 752 "%lx\n", win, (u_long) busaddr, (u_long) * offsetp, (u_long) size, 753 (u_long) card_addr)); 754 755 /* 756 * include the offset in the size, and decrement size by one, since 757 * the hw wants start/stop 758 */ 759 size += *offsetp - 1; 760 761 card_offset = (((long) card_addr) - ((long) busaddr)); 762 763 h->mem[win].addr = busaddr; 764 h->mem[win].size = size; 765 h->mem[win].offset = card_offset; 766 h->mem[win].kind = kind; 767 768 if (kind == PCMCIA_MEM_ATTR) { 769 pcmhp->memh = h->sc->memh + card_addr; 770 } else { 771 pcmhp->memh = h->sc->memh + card_addr + MMEYEPCMCIA_ATTRMEM_SIZE; 772 } 773 774 return (0); 775 } 776 777 void 778 mmeyepcmcia_chip_mem_unmap(pcmcia_chipset_handle_t pch, int window) 779 { 780 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch; 781 782 if (window >= MMEYEPCMCIA_WINS) 783 panic("mmeyepcmcia_chip_mem_unmap: window out of range"); 784 785 h->memalloc &= ~(1 << window); 786 } 787 788 int 789 mmeyepcmcia_chip_io_alloc(pcmcia_chipset_handle_t pch, bus_addr_t start, 790 bus_size_t size, bus_size_t align, struct pcmcia_io_handle *pcihp) 791 { 792 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch; 793 bus_space_tag_t iot; 794 bus_space_handle_t ioh; 795 bus_addr_t ioaddr; 796 int flags = 0; 797 798 /* 799 * Allocate some arbitrary I/O space. 800 */ 801 802 iot = h->sc->iot; 803 804 if (start) { 805 ioaddr = start; 806 ioh = start; 807 DPRINTF(("mmeyepcmcia_chip_io_alloc map port %lx+%lx\n", 808 (u_long) ioaddr, (u_long) size)); 809 } else { 810 flags |= PCMCIA_IO_ALLOCATED; 811 ioaddr = ioh = h->sc->iobase; 812 DPRINTF(("mmeyepcmcia_chip_io_alloc alloc port %lx+%lx\n", 813 (u_long) ioaddr, (u_long) size)); 814 } 815 816 pcihp->iot = iot; 817 pcihp->ioh = ioh + h->sc->memh + MMEYEPCMCIA_ATTRMEM_SIZE; 818 pcihp->addr = ioaddr; 819 pcihp->size = size; 820 pcihp->flags = flags; 821 822 return (0); 823 } 824 825 void 826 mmeyepcmcia_chip_io_free(pcmcia_chipset_handle_t pch, 827 struct pcmcia_io_handle *pcihp) 828 { 829 } 830 831 int 832 mmeyepcmcia_chip_io_map(pcmcia_chipset_handle_t pch, int width, bus_addr_t offset, 833 bus_size_t size, struct pcmcia_io_handle *pcihp, int *windowp) 834 { 835 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch; 836 bus_addr_t ioaddr = pcihp->addr + offset; 837 int i, win; 838 #ifdef MMEYEPCMCIADEBUG 839 static char *width_names[] = { "auto", "io8", "io16" }; 840 #endif 841 int reg; 842 843 /* I/O width is hardwired to 16bit mode on mmeye. */ 844 width = PCMCIA_WIDTH_IO16; 845 846 win = -1; 847 for (i = 0; i < MMEYEPCMCIA_IOWINS; i++) { 848 if ((h->ioalloc & (1 << i)) == 0) { 849 win = i; 850 h->ioalloc |= (1 << i); 851 break; 852 } 853 } 854 855 if (win == -1) 856 return (1); 857 858 *windowp = win; 859 860 /* XXX this is pretty gross */ 861 862 if (h->sc->iot != pcihp->iot) 863 panic("mmeyepcmcia_chip_io_map iot is bogus"); 864 865 DPRINTF(("mmeyepcmcia_chip_io_map window %d %s port %lx+%lx\n", 866 win, width_names[width], (u_long) ioaddr, (u_long) size)); 867 868 /* XXX wtf is this doing here? */ 869 870 printf(" port 0x%lx", (u_long) ioaddr); 871 if (size > 1) 872 printf("-0x%lx", (u_long) ioaddr + (u_long) size - 1); 873 874 h->io[win].addr = ioaddr; 875 h->io[win].size = size; 876 h->io[win].width = width; 877 878 pcihp->ioh = h->sc->memh + MMEYEPCMCIA_ATTRMEM_SIZE; 879 880 if (width == PCMCIA_WIDTH_IO8) { /* IO8 */ 881 reg = mmeyepcmcia_read(h, MMEYEPCMCIA_IF_STATUS); 882 reg |= MMEYEPCMCIA_IF_STATUS_BUSWIDTH; /* Set bus width to 8bit */ 883 mmeyepcmcia_write(h, MMEYEPCMCIA_IF_STATUS, reg); 884 } 885 886 return (0); 887 } 888 889 void 890 mmeyepcmcia_chip_io_unmap(pcmcia_chipset_handle_t pch, int window) 891 { 892 struct mmeyepcmcia_handle *h = (struct mmeyepcmcia_handle *) pch; 893 894 if (window >= MMEYEPCMCIA_IOWINS) 895 panic("mmeyepcmcia_chip_io_unmap: window out of range"); 896 897 h->ioalloc &= ~(1 << window); 898 } 899 900 void 901 mmeyepcmcia_chip_socket_enable(pcmcia_chipset_handle_t pch) 902 { 903 } 904 905 void 906 mmeyepcmcia_chip_socket_disable(pcmcia_chipset_handle_t pch) 907 { 908 } 909