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