1 /* 2 * pccard.c - Interface code for PC-CARD controllers. 3 * 4 * June 1995, Andrew McRae (andrew@mega.com.au) 5 *------------------------------------------------------------------------- 6 * 7 * Copyright (c) 2001 M. Warner Losh. All rights reserved. 8 * Copyright (c) 1995 Andrew McRae. All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * 32 * $FreeBSD: src/sys/pccard/pccard.c,v 1.106.2.15 2003/02/26 18:42:00 imp Exp $ 33 */ 34 35 #include <sys/param.h> 36 #include <sys/types.h> 37 #include <sys/systm.h> 38 #include <sys/kernel.h> 39 #include <sys/malloc.h> 40 #include <sys/sysctl.h> 41 #include <sys/conf.h> 42 #include <sys/uio.h> 43 #include <sys/poll.h> 44 #include <sys/bus.h> 45 #include <sys/proc.h> 46 #include <machine/bus.h> 47 48 #include <pccard/cardinfo.h> 49 #include <pccard/driver.h> 50 #include <pccard/slot.h> 51 #include <pccard/pccard_nbk.h> 52 53 #include <machine/md_var.h> 54 55 #define MIN(a,b) ((a)<(b)?(a):(b)) 56 57 static int allocate_driver(struct slot *, struct dev_desc *); 58 static void inserted(void *); 59 static void disable_slot(struct slot *); 60 static void disable_slot_to(struct slot *); 61 static void power_off_slot(void *); 62 63 /* 64 * The driver interface for read/write uses a block 65 * of memory in the ISA I/O memory space allocated via 66 * an ioctl setting. 67 * 68 * Now that we have different bus attachments, we should really 69 * use a better algorythm to allocate memory. 70 */ 71 static unsigned long pccard_mem; /* Physical memory */ 72 static unsigned char *pccard_kmem; /* Kernel virtual address */ 73 static struct resource *pccard_mem_res; 74 static int pccard_mem_rid; 75 76 static d_open_t crdopen; 77 static d_close_t crdclose; 78 static d_read_t crdread; 79 static d_write_t crdwrite; 80 static d_ioctl_t crdioctl; 81 static d_poll_t crdpoll; 82 83 #define CDEV_MAJOR 50 84 static struct cdevsw crd_cdevsw = { 85 /* open */ crdopen, 86 /* close */ crdclose, 87 /* read */ crdread, 88 /* write */ crdwrite, 89 /* ioctl */ crdioctl, 90 /* poll */ crdpoll, 91 /* mmap */ nommap, 92 /* strategy */ nostrategy, 93 /* name */ "crd", 94 /* maj */ CDEV_MAJOR, 95 /* dump */ nodump, 96 /* psize */ nopsize, 97 /* flags */ 0, 98 }; 99 100 /* 101 * Power off the slot. 102 * (doing it immediately makes the removal of some cards unstable) 103 */ 104 static void 105 power_off_slot(void *arg) 106 { 107 struct slot *slt = (struct slot *)arg; 108 int s; 109 110 /* 111 * The following will generate an interrupt. So, to hold off 112 * the interrupt unitl after disable runs so that we can get rid 113 * rid of the interrupt before it becomes unsafe to touch the 114 * device. 115 * 116 * XXX In current, the spl stuff is a nop. 117 */ 118 s = splhigh(); 119 /* Power off the slot. */ 120 slt->pwr_off_pending = 0; 121 slt->ctrl->disable(slt); 122 splx(s); 123 } 124 125 /* 126 * disable_slot - Disables the slot by removing 127 * the power and unmapping the I/O 128 */ 129 static void 130 disable_slot(struct slot *slt) 131 { 132 device_t pccarddev; 133 device_t *kids; 134 int nkids; 135 int i; 136 int ret; 137 138 /* 139 * Note that a race condition is possible here; if a 140 * driver is accessing the device and it is removed, then 141 * all bets are off... 142 */ 143 pccarddev = slt->dev; 144 device_get_children(pccarddev, &kids, &nkids); 145 for (i = 0; i < nkids; i++) { 146 if ((ret = device_delete_child(pccarddev, kids[i])) != 0) 147 printf("pccard: delete of %s failed: %d\n", 148 device_get_nameunit(kids[i]), ret); 149 } 150 free(kids, M_TEMP); 151 152 /* Power off the slot 1/2 second after removal of the card */ 153 slt->poff_ch = timeout(power_off_slot, (caddr_t)slt, hz / 2); 154 slt->pwr_off_pending = 1; 155 } 156 157 static void 158 disable_slot_to(struct slot *slt) 159 { 160 disable_slot(slt); 161 if (slt->state == empty) 162 printf("pccard: card removed, slot %d\n", slt->slotnum); 163 else 164 printf("pccard: card deactivated, slot %d\n", slt->slotnum); 165 pccard_remove_beep(); 166 selwakeup(&slt->selp); 167 } 168 169 /* 170 * pccard_init_slot - Initialize the slot controller and attach various 171 * things to it. We also make the device for it. We create the device that 172 * will be exported to devfs. 173 */ 174 struct slot * 175 pccard_init_slot(device_t dev, struct slot_ctrl *ctrl) 176 { 177 int slotno; 178 struct slot *slt; 179 180 slt = PCCARD_DEVICE2SOFTC(dev); 181 slotno = device_get_unit(dev); 182 slt->dev = dev; 183 slt->d = make_dev(&crd_cdevsw, slotno, 0, 0, 0600, "card%d", slotno); 184 slt->d->si_drv1 = slt; 185 slt->ctrl = ctrl; 186 slt->slotnum = slotno; 187 callout_handle_init(&slt->insert_ch); 188 callout_handle_init(&slt->poff_ch); 189 190 return (slt); 191 } 192 193 /* 194 * allocate_driver - Create a new device entry for this 195 * slot, and attach a driver to it. 196 */ 197 static int 198 allocate_driver(struct slot *slt, struct dev_desc *desc) 199 { 200 struct pccard_devinfo *devi; 201 device_t pccarddev; 202 int err, irq = 0; 203 device_t child; 204 device_t *devs; 205 int count; 206 207 pccarddev = slt->dev; 208 err = device_get_children(pccarddev, &devs, &count); 209 if (err != 0) 210 return (err); 211 free(devs, M_TEMP); 212 if (count) { 213 device_printf(pccarddev, 214 "Can not attach more than one child.\n"); 215 return (EIO); 216 } 217 irq = ffs(desc->irqmask) - 1; 218 MALLOC(devi, struct pccard_devinfo *, sizeof(*devi), M_DEVBUF, 219 M_WAITOK | M_ZERO); 220 strcpy(devi->name, desc->name); 221 /* 222 * Create an entry for the device under this slot. 223 */ 224 devi->running = 1; 225 devi->slt = slt; 226 bcopy(desc->misc, devi->misc, sizeof(desc->misc)); 227 strcpy(devi->manufstr, desc->manufstr); 228 strcpy(devi->versstr, desc->versstr); 229 devi->manufacturer = desc->manufacturer; 230 devi->product = desc->product; 231 devi->prodext = desc->prodext; 232 resource_list_init(&devi->resources); 233 child = device_add_child(pccarddev, devi->name, desc->unit); 234 if (child == NULL) { 235 if (desc->unit != -1) 236 device_printf(pccarddev, 237 "Unit %d failed for %s, try a different unit\n", 238 desc->unit, devi->name); 239 else 240 device_printf(pccarddev, 241 "No units available for %s. Impossible?\n", 242 devi->name); 243 return (EIO); 244 } 245 device_set_flags(child, desc->flags); 246 device_set_ivars(child, devi); 247 if (bootverbose) { 248 device_printf(pccarddev, "Assigning %s:", 249 device_get_nameunit(child)); 250 if (desc->iobase) 251 printf(" io 0x%x-0x%x", 252 desc->iobase, desc->iobase + desc->iosize - 1); 253 if (irq) 254 printf(" irq %d", irq); 255 if (desc->mem) 256 printf(" mem 0x%lx-0x%lx", desc->mem, 257 desc->mem + desc->memsize - 1); 258 printf(" flags 0x%x\n", desc->flags); 259 } 260 err = bus_set_resource(child, SYS_RES_IOPORT, 0, desc->iobase, 261 desc->iosize); 262 if (err) 263 goto err; 264 if (irq) 265 err = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1); 266 if (err) 267 goto err; 268 if (desc->memsize) { 269 err = bus_set_resource(child, SYS_RES_MEMORY, 0, desc->mem, 270 desc->memsize); 271 if (err) 272 goto err; 273 } 274 err = device_probe_and_attach(child); 275 /* 276 * XXX We unwisely assume that the detach code won't run while the 277 * XXX the attach code is attaching. Someone should put some 278 * XXX interlock code. This can happen if probe/attach takes a while 279 * XXX and the user ejects the card, which causes the detach 280 * XXX function to be called. 281 */ 282 strncpy(desc->name, device_get_nameunit(child), sizeof(desc->name)); 283 desc->name[sizeof(desc->name) - 1] = '\0'; 284 err: 285 if (err) 286 device_delete_child(pccarddev, child); 287 return (err); 288 } 289 290 /* 291 * card insert routine - Called from a timeout to debounce 292 * insertion events. 293 */ 294 static void 295 inserted(void *arg) 296 { 297 struct slot *slt = arg; 298 299 slt->state = filled; 300 /* 301 * Disable any pending timeouts for this slot, and explicitly 302 * power it off right now. Then, re-enable the power using 303 * the (possibly new) power settings. 304 */ 305 untimeout(power_off_slot, (caddr_t)slt, slt->poff_ch); 306 power_off_slot(slt); 307 308 /* 309 * Enable 5V to the card so that the CIS can be read. Well, 310 * enable the most natural voltage so that the CIS can be read. 311 */ 312 slt->pwr.vcc = -1; 313 slt->pwr.vpp = -1; 314 slt->ctrl->power(slt); 315 316 printf("pccard: card inserted, slot %d\n", slt->slotnum); 317 pccard_insert_beep(); 318 slt->ctrl->reset(slt); 319 } 320 321 /* 322 * Card event callback. Called at splhigh to prevent 323 * device interrupts from interceding. 324 */ 325 void 326 pccard_event(struct slot *slt, enum card_event event) 327 { 328 if (slt->insert_seq) { 329 slt->insert_seq = 0; 330 untimeout(inserted, (void *)slt, slt->insert_ch); 331 } 332 333 switch(event) { 334 case card_removed: 335 case card_deactivated: 336 if (slt->state == filled || slt->state == inactive) { 337 if (event == card_removed) 338 slt->state = empty; 339 else 340 slt->state = inactive; 341 disable_slot_to(slt); 342 } 343 break; 344 case card_inserted: 345 slt->insert_seq = 1; 346 slt->insert_ch = timeout(inserted, (void *)slt, hz/4); 347 break; 348 } 349 } 350 351 /* 352 * Device driver interface. 353 */ 354 static int 355 crdopen(dev_t dev, int oflags, int devtype, d_thread_t *td) 356 { 357 struct slot *slt = PCCARD_DEV2SOFTC(dev); 358 359 if (slt == NULL) 360 return (ENXIO); 361 if (slt->rwmem == 0) 362 slt->rwmem = MDF_ATTR; 363 return (0); 364 } 365 366 /* 367 * Close doesn't de-allocate any resources, since 368 * slots may be assigned to drivers already. 369 */ 370 static int 371 crdclose(dev_t dev, int fflag, int devtype, d_thread_t *td) 372 { 373 return (0); 374 } 375 376 /* 377 * read interface. Map memory at lseek offset, 378 * then transfer to user space. 379 */ 380 static int 381 crdread(dev_t dev, struct uio *uio, int ioflag) 382 { 383 struct slot *slt = PCCARD_DEV2SOFTC(dev); 384 struct mem_desc *mp, oldmap; 385 unsigned char *p; 386 unsigned int offs; 387 int error = 0, win, count; 388 389 if (slt == 0 || slt->state != filled) 390 return (ENXIO); 391 if (pccard_mem == 0) 392 return (ENOMEM); 393 for (win = slt->ctrl->maxmem - 1; win >= 0; win--) 394 if ((slt->mem[win].flags & MDF_ACTIVE) == 0) 395 break; 396 if (win < 0) 397 return (EBUSY); 398 mp = &slt->mem[win]; 399 oldmap = *mp; 400 mp->flags = slt->rwmem | MDF_ACTIVE; 401 while (uio->uio_resid && error == 0) { 402 mp->card = uio->uio_offset; 403 mp->size = PCCARD_MEMSIZE; 404 mp->start = (caddr_t)(void *)(uintptr_t)pccard_mem; 405 if ((error = slt->ctrl->mapmem(slt, win)) != 0) 406 break; 407 offs = (unsigned int)uio->uio_offset & (PCCARD_MEMSIZE - 1); 408 p = pccard_kmem + offs; 409 count = MIN(PCCARD_MEMSIZE - offs, uio->uio_resid); 410 error = uiomove(p, count, uio); 411 } 412 /* 413 * Restore original map. 414 */ 415 *mp = oldmap; 416 slt->ctrl->mapmem(slt, win); 417 418 return (error); 419 } 420 421 /* 422 * crdwrite - Write data to card memory. 423 * Handles wrap around so that only one memory 424 * window is used. 425 */ 426 static int 427 crdwrite(dev_t dev, struct uio *uio, int ioflag) 428 { 429 struct slot *slt = PCCARD_DEV2SOFTC(dev); 430 struct mem_desc *mp, oldmap; 431 unsigned char *p; 432 unsigned int offs; 433 int error = 0, win, count; 434 435 if (slt == 0 || slt->state != filled) 436 return (ENXIO); 437 if (pccard_mem == 0) 438 return (ENOMEM); 439 for (win = slt->ctrl->maxmem - 1; win >= 0; win--) 440 if ((slt->mem[win].flags & MDF_ACTIVE) == 0) 441 break; 442 if (win < 0) 443 return (EBUSY); 444 mp = &slt->mem[win]; 445 oldmap = *mp; 446 mp->flags = slt->rwmem | MDF_ACTIVE; 447 while (uio->uio_resid && error == 0) { 448 mp->card = uio->uio_offset; 449 mp->size = PCCARD_MEMSIZE; 450 mp->start = (caddr_t)(void *)(uintptr_t)pccard_mem; 451 if ((error = slt->ctrl->mapmem(slt, win)) != 0) 452 break; 453 offs = (unsigned int)uio->uio_offset & (PCCARD_MEMSIZE - 1); 454 p = pccard_kmem + offs; 455 count = MIN(PCCARD_MEMSIZE - offs, uio->uio_resid); 456 error = uiomove(p, count, uio); 457 } 458 /* 459 * Restore original map. 460 */ 461 *mp = oldmap; 462 slt->ctrl->mapmem(slt, win); 463 464 return (error); 465 } 466 467 /* 468 * ioctl calls - allows setting/getting of memory and I/O 469 * descriptors, and assignment of drivers. 470 */ 471 static int 472 crdioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, d_thread_t *td) 473 { 474 u_int32_t addr; 475 int err; 476 struct io_desc *ip; 477 struct mem_desc *mp; 478 device_t pccarddev; 479 int pwval; 480 int s; 481 struct slot *slt = PCCARD_DEV2SOFTC(dev); 482 483 if (slt == 0 && cmd != PIOCRWMEM) 484 return (ENXIO); 485 switch(cmd) { 486 default: 487 if (slt->ctrl->ioctl) 488 return (slt->ctrl->ioctl(slt, cmd, data)); 489 return (ENOTTY); 490 /* 491 * Get slot state. 492 */ 493 case PIOCGSTATE: 494 s = splhigh(); 495 ((struct slotstate *)data)->state = slt->state; 496 ((struct slotstate *)data)->laststate = slt->laststate; 497 slt->laststate = slt->state; 498 splx(s); 499 ((struct slotstate *)data)->maxmem = slt->ctrl->maxmem; 500 ((struct slotstate *)data)->maxio = slt->ctrl->maxio; 501 ((struct slotstate *)data)->irqs = 0; 502 break; 503 /* 504 * Get memory context. 505 */ 506 case PIOCGMEM: 507 s = ((struct mem_desc *)data)->window; 508 if (s < 0 || s >= slt->ctrl->maxmem) 509 return (EINVAL); 510 mp = &slt->mem[s]; 511 ((struct mem_desc *)data)->flags = mp->flags; 512 ((struct mem_desc *)data)->start = mp->start; 513 ((struct mem_desc *)data)->size = mp->size; 514 ((struct mem_desc *)data)->card = mp->card; 515 break; 516 /* 517 * Set memory context. If context already active, then unmap it. 518 * It is hard to see how the parameters can be checked. 519 * At the very least, we only allow root to set the context. 520 */ 521 case PIOCSMEM: 522 if (suser(td)) 523 return (EPERM); 524 if (slt->state != filled) 525 return (ENXIO); 526 s = ((struct mem_desc *)data)->window; 527 if (s < 0 || s >= slt->ctrl->maxmem) 528 return (EINVAL); 529 slt->mem[s] = *((struct mem_desc *)data); 530 return (slt->ctrl->mapmem(slt, s)); 531 /* 532 * Get I/O port context. 533 */ 534 case PIOCGIO: 535 s = ((struct io_desc *)data)->window; 536 if (s < 0 || s >= slt->ctrl->maxio) 537 return (EINVAL); 538 ip = &slt->io[s]; 539 ((struct io_desc *)data)->flags = ip->flags; 540 ((struct io_desc *)data)->start = ip->start; 541 ((struct io_desc *)data)->size = ip->size; 542 break; 543 /* 544 * Set I/O port context. 545 */ 546 case PIOCSIO: 547 if (suser(td)) 548 return (EPERM); 549 if (slt->state != filled) 550 return (ENXIO); 551 s = ((struct io_desc *)data)->window; 552 if (s < 0 || s >= slt->ctrl->maxio) 553 return (EINVAL); 554 slt->io[s] = *((struct io_desc *)data); 555 /* XXX Don't actually map */ 556 return (0); 557 break; 558 /* 559 * Set memory window flags for read/write interface. 560 */ 561 case PIOCRWFLAG: 562 slt->rwmem = *(int *)data; 563 break; 564 /* 565 * Set the memory window to be used for the read/write interface. 566 */ 567 case PIOCRWMEM: 568 if (*(unsigned long *)data == 0) { 569 *(unsigned long *)data = pccard_mem; 570 break; 571 } 572 if (suser(td)) 573 return (EPERM); 574 /* 575 * Validate the memory by checking it against the I/O 576 * memory range. It must also start on an aligned block size. 577 */ 578 if (*(unsigned long *)data & (PCCARD_MEMSIZE-1)) 579 return (EINVAL); 580 pccarddev = PCCARD_DEV2SOFTC(dev)->dev; 581 pccard_mem_rid = 0; 582 addr = *(unsigned long *)data; 583 if (pccard_mem_res) 584 bus_release_resource(pccarddev, SYS_RES_MEMORY, 585 pccard_mem_rid, pccard_mem_res); 586 pccard_mem_res = bus_alloc_resource(pccarddev, SYS_RES_MEMORY, 587 &pccard_mem_rid, addr, addr, PCCARD_MEMSIZE, 588 RF_ACTIVE | rman_make_alignment_flags(PCCARD_MEMSIZE)); 589 if (pccard_mem_res == NULL) 590 return (EINVAL); 591 pccard_mem = rman_get_start(pccard_mem_res); 592 pccard_kmem = rman_get_virtual(pccard_mem_res); 593 break; 594 /* 595 * Set power values. 596 */ 597 case PIOCSPOW: 598 slt->pwr = *(struct power *)data; 599 return (slt->ctrl->power(slt)); 600 /* 601 * Allocate a driver to this slot. 602 */ 603 case PIOCSDRV: 604 if (suser(td)) 605 return (EPERM); 606 err = allocate_driver(slt, (struct dev_desc *)data); 607 if (!err) 608 pccard_success_beep(); 609 else 610 pccard_failure_beep(); 611 return (err); 612 /* 613 * Virtual removal/insertion 614 */ 615 case PIOCSVIR: 616 pwval = *(int *)data; 617 if (!pwval) { 618 if (slt->state != filled) 619 return (EINVAL); 620 pccard_event(slt, card_deactivated); 621 } else { 622 if (slt->state != empty && slt->state != inactive) 623 return (EINVAL); 624 pccard_event(slt, card_inserted); 625 } 626 break; 627 case PIOCSBEEP: 628 if (pccard_beep_select(*(int *)data)) { 629 return (EINVAL); 630 } 631 break; 632 } 633 return (0); 634 } 635 636 /* 637 * poll - Poll on exceptions will return true 638 * when a change in card status occurs. 639 */ 640 static int 641 crdpoll(dev_t dev, int events, d_thread_t *td) 642 { 643 int revents = 0; 644 int s; 645 struct slot *slt = PCCARD_DEV2SOFTC(dev); 646 647 if (events & (POLLIN | POLLRDNORM)) 648 revents |= events & (POLLIN | POLLRDNORM); 649 650 if (events & (POLLOUT | POLLWRNORM)) 651 revents |= events & (POLLIN | POLLRDNORM); 652 653 s = splhigh(); 654 /* 655 * select for exception - card event. 656 */ 657 if (events & POLLRDBAND) 658 if (slt == 0 || slt->laststate != slt->state) 659 revents |= POLLRDBAND; 660 661 if (revents == 0) 662 selrecord(td, &slt->selp); 663 664 splx(s); 665 return (revents); 666 } 667 668 /* 669 * APM hooks for suspending and resuming. 670 */ 671 int 672 pccard_suspend(device_t dev) 673 { 674 struct slot *slt = PCCARD_DEVICE2SOFTC(dev); 675 676 /* This code stolen from pccard_event:card_removed */ 677 if (slt->state == filled) { 678 int s = splhigh(); /* nop on current */ 679 disable_slot(slt); 680 slt->laststate = suspend; /* for pccardd */ 681 slt->state = empty; 682 splx(s); 683 printf("pccard: card disabled, slot %d\n", slt->slotnum); 684 } 685 /* 686 * Disable any pending timeouts for this slot since we're 687 * powering it down/disabling now. 688 */ 689 untimeout(power_off_slot, (caddr_t)slt, slt->poff_ch); 690 slt->ctrl->disable(slt); 691 return (0); 692 } 693 694 int 695 pccard_resume(device_t dev) 696 { 697 struct slot *slt = PCCARD_DEVICE2SOFTC(dev); 698 699 slt->ctrl->resume(slt); 700 return (0); 701 } 702