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