diff options
author | Warner Losh <imp@FreeBSD.org> | 2005-09-25 21:29:32 +0000 |
---|---|---|
committer | Warner Losh <imp@FreeBSD.org> | 2005-09-25 21:29:32 +0000 |
commit | 9f8aaf685b48712cfeead72c80a64715c559ad82 (patch) | |
tree | 58cc7567434699af9d901ac0a0ab8c262f3b1f22 /sys/pccard/pccard.c | |
parent | f31f999d7d9c64d1269ae74e9be7fe20ffab9274 (diff) |
Remove the kernel portion of OLDCARD. I'm working on a replacement
for pccardc dumpcis, but until I'm done with that, I'm leaving pccardc
in place. As such, I'm leaving the .h files in place for the moment.
Notes
Notes:
svn path=/head/; revision=150556
Diffstat (limited to 'sys/pccard/pccard.c')
-rw-r--r-- | sys/pccard/pccard.c | 731 |
1 files changed, 0 insertions, 731 deletions
diff --git a/sys/pccard/pccard.c b/sys/pccard/pccard.c deleted file mode 100644 index b8ebea9033c5..000000000000 --- a/sys/pccard/pccard.c +++ /dev/null @@ -1,731 +0,0 @@ -/* - * pccard.c - Interface code for PC-CARD controllers. - * - * June 1995, Andrew McRae (andrew@mega.com.au) - *------------------------------------------------------------------------- - */ -/*- - * Copyright (c) 2001 M. Warner Losh. All rights reserved. - * Copyright (c) 1995 Andrew McRae. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#define OBSOLETE_IN_6 - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/sysctl.h> -#include <sys/conf.h> -#include <sys/uio.h> -#include <sys/poll.h> -#include <sys/bus.h> -#include <sys/proc.h> -#include <machine/bus.h> - -#include <pccard/cardinfo.h> -#include <pccard/driver.h> -#include <pccard/slot.h> -#include <pccard/pccard_nbk.h> - -#include <machine/md_var.h> - -static int allocate_driver(struct slot *, struct dev_desc *); -static void inserted(void *); -static void disable_slot(struct slot *); -static void disable_slot_to(struct slot *); -static void power_off_slot(void *); - -/* - * The driver interface for read/write uses a block - * of memory in the ISA I/O memory space allocated via - * an ioctl setting. - * - * Now that we have different bus attachments, we should really - * use a better algorythm to allocate memory. - */ -static unsigned long pccard_mem; /* Physical memory */ -static unsigned char *pccard_kmem; /* Kernel virtual address */ -static struct resource *pccard_mem_res; -static int pccard_mem_rid; - -static d_open_t crdopen; -static d_close_t crdclose; -static d_read_t crdread; -static d_write_t crdwrite; -static d_ioctl_t crdioctl; -static d_poll_t crdpoll; - -static struct cdevsw crd_cdevsw = { - .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, - .d_open = crdopen, - .d_close = crdclose, - .d_read = crdread, - .d_write = crdwrite, - .d_ioctl = crdioctl, - .d_poll = crdpoll, - .d_name = "crd", -}; - -/* - * Power off the slot. - * (doing it immediately makes the removal of some cards unstable) - */ -static void -power_off_slot(void *arg) -{ - struct slot *slt = (struct slot *)arg; - int s; - - /* - * The following will generate an interrupt. So, to hold off - * the interrupt unitl after disable runs so that we can get rid - * rid of the interrupt before it becomes unsafe to touch the - * device. - * - * XXX In current, the spl stuff is a nop. - */ - s = splhigh(); - /* Power off the slot. */ - slt->pwr_off_pending = 0; - slt->ctrl->disable(slt); - splx(s); -} - -/* - * disable_slot - Disables the slot by removing - * the power and unmapping the I/O - */ -static void -disable_slot(struct slot *slt) -{ - device_t pccarddev; - device_t *kids; - int nkids; - int i; - int ret; - - /* - * Note that a race condition is possible here; if a - * driver is accessing the device and it is removed, then - * all bets are off... - */ - pccarddev = slt->dev; - device_get_children(pccarddev, &kids, &nkids); - for (i = 0; i < nkids; i++) { - if ((ret = device_delete_child(pccarddev, kids[i])) != 0) - printf("pccard: delete of %s failed: %d\n", - device_get_nameunit(kids[i]), ret); - } - free(kids, M_TEMP); - - /* Power off the slot 1/2 second after removal of the card */ - slt->poff_ch = timeout(power_off_slot, (caddr_t)slt, hz / 2); - slt->pwr_off_pending = 1; -} - -static void -disable_slot_to(struct slot *slt) -{ - disable_slot(slt); - if (slt->state == empty) - printf("pccard: card removed, slot %d\n", slt->slotnum); - else - printf("pccard: card deactivated, slot %d\n", slt->slotnum); - pccard_remove_beep(); - selwakeuppri(&slt->selp, PZERO); -} - -/* - * pccard_init_slot - Initialize the slot controller and attach various - * things to it. We also make the device for it. We create the device that - * will be exported to devfs. - */ -struct slot * -pccard_init_slot(device_t dev, struct slot_ctrl *ctrl) -{ - int slotno; - struct slot *slt; - - slt = PCCARD_DEVICE2SOFTC(dev); - slotno = device_get_unit(dev); - slt->dev = dev; - slt->d = make_dev(&crd_cdevsw, slotno, 0, 0, 0600, "card%d", slotno); - slt->d->si_drv1 = slt; - slt->ctrl = ctrl; - slt->slotnum = slotno; - callout_handle_init(&slt->insert_ch); - callout_handle_init(&slt->poff_ch); - - return (slt); -} - -/* - * allocate_driver - Create a new device entry for this - * slot, and attach a driver to it. - */ -static int -allocate_driver(struct slot *slt, struct dev_desc *desc) -{ - struct pccard_devinfo *devi; - device_t pccarddev; - int err, irq = 0; - device_t child; - device_t *devs; - int count; - - pccarddev = slt->dev; - err = device_get_children(pccarddev, &devs, &count); - if (err != 0) - return (err); - free(devs, M_TEMP); - if (count) { - device_printf(pccarddev, - "Can not attach more than one child.\n"); - return (EIO); - } - irq = ffs(desc->irqmask) - 1; - MALLOC(devi, struct pccard_devinfo *, sizeof(*devi), M_DEVBUF, - M_WAITOK | M_ZERO); - strcpy(devi->name, desc->name); - /* - * Create an entry for the device under this slot. - */ - devi->running = 1; - devi->slt = slt; - bcopy(desc->misc, devi->misc, sizeof(desc->misc)); - strcpy(devi->manufstr, desc->manufstr); - strcpy(devi->versstr, desc->versstr); - strcpy(devi->cis3str, desc->cis3str); - strcpy(devi->cis4str, desc->cis4str); - devi->manufacturer = desc->manufacturer; - devi->product = desc->product; - devi->prodext = desc->prodext; - resource_list_init(&devi->resources); - child = device_add_child(pccarddev, devi->name, desc->unit); - if (child == NULL) { - if (desc->unit != -1) - device_printf(pccarddev, - "Unit %d failed for %s, try a different unit\n", - desc->unit, devi->name); - else - device_printf(pccarddev, - "No units available for %s. Impossible?\n", - devi->name); - return (EIO); - } - device_set_flags(child, desc->flags); - device_set_ivars(child, devi); - if (bootverbose) { - device_printf(pccarddev, "Assigning %s:", - device_get_nameunit(child)); - if (desc->iobase) - printf(" io 0x%x-0x%x", - desc->iobase, desc->iobase + desc->iosize - 1); - if (irq) - printf(" irq %d", irq); - if (desc->mem) - printf(" mem 0x%lx-0x%lx", desc->mem, - desc->mem + desc->memsize - 1); - printf(" flags 0x%x\n", desc->flags); - } - err = bus_set_resource(child, SYS_RES_IOPORT, 0, desc->iobase, - desc->iosize); - if (err) - goto err; - if (irq) - err = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1); - if (err) - goto err; - if (desc->memsize) { - err = bus_set_resource(child, SYS_RES_MEMORY, 0, desc->mem, - desc->memsize); - if (err) - goto err; - } - err = device_probe_and_attach(child); - /* - * XXX We unwisely assume that the detach code won't run while the - * XXX the attach code is attaching. Someone should put some - * XXX interlock code. This can happen if probe/attach takes a while - * XXX and the user ejects the card, which causes the detach - * XXX function to be called. - */ - strncpy(desc->name, device_get_nameunit(child), sizeof(desc->name)); - desc->name[sizeof(desc->name) - 1] = '\0'; -err: - if (err) - device_delete_child(pccarddev, child); - return (err); -} - -/* - * card insert routine - Called from a timeout to debounce - * insertion events. - */ -static void -inserted(void *arg) -{ - struct slot *slt = arg; - - slt->state = filled; - /* - * Disable any pending timeouts for this slot, and explicitly - * power it off right now. Then, re-enable the power using - * the (possibly new) power settings. - */ - untimeout(power_off_slot, (caddr_t)slt, slt->poff_ch); - power_off_slot(slt); - - /* - * Enable 5V to the card so that the CIS can be read. Well, - * enable the most natural voltage so that the CIS can be read. - */ - slt->pwr.vcc = -1; - slt->pwr.vpp = -1; - slt->ctrl->power(slt); - - printf("pccard: card inserted, slot %d\n", slt->slotnum); - pccard_insert_beep(); - slt->ctrl->reset(slt); -} - -/* - * Card event callback. Called at splhigh to prevent - * device interrupts from interceding. - */ -void -pccard_event(struct slot *slt, enum card_event event) -{ - if (slt->insert_seq) { - slt->insert_seq = 0; - untimeout(inserted, (void *)slt, slt->insert_ch); - } - - switch(event) { - case card_removed: - case card_deactivated: - if (slt->state == filled || slt->state == inactive) { - if (event == card_removed) - slt->state = empty; - else - slt->state = inactive; - disable_slot_to(slt); - } - break; - case card_inserted: - slt->insert_seq = 1; - slt->insert_ch = timeout(inserted, (void *)slt, hz/4); - break; - } -} - -/* - * Device driver interface. - */ -static int -crdopen(struct cdev *dev, int oflags, int devtype, d_thread_t *td) -{ - struct slot *slt = PCCARD_DEV2SOFTC(dev); - - if (slt == NULL) - return (ENXIO); - if (slt->rwmem == 0) - slt->rwmem = MDF_ATTR; - return (0); -} - -/* - * Close doesn't de-allocate any resources, since - * slots may be assigned to drivers already. - */ -static int -crdclose(struct cdev *dev, int fflag, int devtype, d_thread_t *td) -{ - return (0); -} - -/* - * read interface. Map memory at lseek offset, - * then transfer to user space. - */ -static int -crdread(struct cdev *dev, struct uio *uio, int ioflag) -{ - struct slot *slt = PCCARD_DEV2SOFTC(dev); - struct mem_desc *mp, oldmap; - unsigned char *p; - unsigned int offs; - int error = 0, win, count; - - if (slt == 0 || slt->state != filled) - return (ENXIO); - if (pccard_mem == 0) - return (ENOMEM); - for (win = slt->ctrl->maxmem - 1; win >= 0; win--) - if ((slt->mem[win].flags & MDF_ACTIVE) == 0) - break; - if (win < 0) - return (EBUSY); - mp = &slt->mem[win]; - oldmap = *mp; - mp->flags = slt->rwmem | MDF_ACTIVE; - while (uio->uio_resid && error == 0) { - mp->card = uio->uio_offset; - mp->size = PCCARD_MEMSIZE; - mp->start = (caddr_t)(void *)(uintptr_t)pccard_mem; - if ((error = slt->ctrl->mapmem(slt, win)) != 0) - break; - offs = (unsigned int)uio->uio_offset & (PCCARD_MEMSIZE - 1); - p = pccard_kmem + offs; - count = MIN(PCCARD_MEMSIZE - offs, uio->uio_resid); - error = uiomove(p, count, uio); - } - /* - * Restore original map. - */ - *mp = oldmap; - slt->ctrl->mapmem(slt, win); - - return (error); -} - -/* - * crdwrite - Write data to card memory. - * Handles wrap around so that only one memory - * window is used. - */ -static int -crdwrite(struct cdev *dev, struct uio *uio, int ioflag) -{ - struct slot *slt = PCCARD_DEV2SOFTC(dev); - struct mem_desc *mp, oldmap; - unsigned char *p; - unsigned int offs; - int error = 0, win, count; - - if (slt == 0 || slt->state != filled) - return (ENXIO); - if (pccard_mem == 0) - return (ENOMEM); - for (win = slt->ctrl->maxmem - 1; win >= 0; win--) - if ((slt->mem[win].flags & MDF_ACTIVE) == 0) - break; - if (win < 0) - return (EBUSY); - mp = &slt->mem[win]; - oldmap = *mp; - mp->flags = slt->rwmem | MDF_ACTIVE; - while (uio->uio_resid && error == 0) { - mp->card = uio->uio_offset; - mp->size = PCCARD_MEMSIZE; - mp->start = (caddr_t)(void *)(uintptr_t)pccard_mem; - if ((error = slt->ctrl->mapmem(slt, win)) != 0) - break; - offs = (unsigned int)uio->uio_offset & (PCCARD_MEMSIZE - 1); - p = pccard_kmem + offs; - count = MIN(PCCARD_MEMSIZE - offs, uio->uio_resid); - error = uiomove(p, count, uio); - } - /* - * Restore original map. - */ - *mp = oldmap; - slt->ctrl->mapmem(slt, win); - - return (error); -} - -/* - * ioctl calls - allows setting/getting of memory and I/O - * descriptors, and assignment of drivers. - */ -static int -crdioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, d_thread_t *td) -{ - u_int32_t addr; - int err; - struct io_desc *ip; - struct mem_desc *mp; - device_t pccarddev; - int pwval; - int s; - struct slot *slt = PCCARD_DEV2SOFTC(dev); -/*XXX*/#if __FreeBSD_version < 5000000 /* 4.x compatibility only. */ - struct dev_desc d; - struct dev_desc_old *odp; -/*XXX*/#endif - - if (slt == 0 && cmd != PIOCRWMEM) - return (ENXIO); - switch(cmd) { - default: - if (slt->ctrl->ioctl) - return (slt->ctrl->ioctl(slt, cmd, data)); - return (ENOTTY); - /* - * Get slot state. - */ - case PIOCGSTATE: - s = splhigh(); - ((struct slotstate *)data)->state = slt->state; - ((struct slotstate *)data)->laststate = slt->laststate; - slt->laststate = slt->state; - splx(s); - ((struct slotstate *)data)->maxmem = slt->ctrl->maxmem; - ((struct slotstate *)data)->maxio = slt->ctrl->maxio; - ((struct slotstate *)data)->irqs = 0; - break; - /* - * Get memory context. - */ - case PIOCGMEM: - s = ((struct mem_desc *)data)->window; - if (s < 0 || s >= slt->ctrl->maxmem) - return (EINVAL); - mp = &slt->mem[s]; - ((struct mem_desc *)data)->flags = mp->flags; - ((struct mem_desc *)data)->start = mp->start; - ((struct mem_desc *)data)->size = mp->size; - ((struct mem_desc *)data)->card = mp->card; - break; - /* - * Set memory context. If context already active, then unmap it. - * It is hard to see how the parameters can be checked. - * At the very least, we only allow root to set the context. - */ - case PIOCSMEM: - if (suser(td)) - return (EPERM); - if (slt->state != filled) - return (ENXIO); - s = ((struct mem_desc *)data)->window; - if (s < 0 || s >= slt->ctrl->maxmem) - return (EINVAL); - slt->mem[s] = *((struct mem_desc *)data); - return (slt->ctrl->mapmem(slt, s)); - /* - * Get I/O port context. - */ - case PIOCGIO: - s = ((struct io_desc *)data)->window; - if (s < 0 || s >= slt->ctrl->maxio) - return (EINVAL); - ip = &slt->io[s]; - ((struct io_desc *)data)->flags = ip->flags; - ((struct io_desc *)data)->start = ip->start; - ((struct io_desc *)data)->size = ip->size; - break; - /* - * Set I/O port context. - */ - case PIOCSIO: - if (suser(td)) - return (EPERM); - if (slt->state != filled) - return (ENXIO); - s = ((struct io_desc *)data)->window; - if (s < 0 || s >= slt->ctrl->maxio) - return (EINVAL); - slt->io[s] = *((struct io_desc *)data); - /* XXX Don't actually map */ - return (0); - break; - /* - * Set memory window flags for read/write interface. - */ - case PIOCRWFLAG: - slt->rwmem = *(int *)data; - break; - /* - * Set the memory window to be used for the read/write interface. - */ - case PIOCRWMEM: - if (*(unsigned long *)data == 0) { - *(unsigned long *)data = pccard_mem; - break; - } - if (suser(td)) - return (EPERM); - /* - * Validate the memory by checking it against the I/O - * memory range. It must also start on an aligned block size. - */ - if (*(unsigned long *)data & (PCCARD_MEMSIZE-1)) - return (EINVAL); - pccarddev = PCCARD_DEV2SOFTC(dev)->dev; - pccard_mem_rid = 0; - addr = *(unsigned long *)data; - if (pccard_mem_res) - bus_release_resource(pccarddev, SYS_RES_MEMORY, - pccard_mem_rid, pccard_mem_res); - pccard_mem_res = bus_alloc_resource(pccarddev, SYS_RES_MEMORY, - &pccard_mem_rid, addr, addr, PCCARD_MEMSIZE, - RF_ACTIVE | rman_make_alignment_flags(PCCARD_MEMSIZE)); - if (pccard_mem_res == NULL) - return (EINVAL); - pccard_mem = rman_get_start(pccard_mem_res); - pccard_kmem = rman_get_virtual(pccard_mem_res); - break; - /* - * Set power values. - */ - case PIOCSPOW: - slt->pwr = *(struct power *)data; - return (slt->ctrl->power(slt)); - /* - * Allocate a driver to this slot. - */ - case PIOCSDRV: - if (suser(td)) - return (EPERM); - err = allocate_driver(slt, (struct dev_desc *)data); - if (!err) - pccard_success_beep(); - else - pccard_failure_beep(); - return (err); -/***/#if __FreeBSD_version < 5000000 /* 4.x compatibility only. */ - case PIOCSDRVOLD: - if (suser(td)) - return (EPERM); - odp = (struct dev_desc_old *) data; - strlcpy(d.name, odp->name, sizeof(d.name)); - d.unit = odp->unit; - d.mem = odp->mem; - d.memsize = odp->memsize; - d.iobase = odp->iobase; - d.iosize = odp->iosize; - d.irqmask = odp->irqmask; - d.flags = odp->flags; - memcpy(d.misc, odp->misc, sizeof(odp->misc)); - strlcpy(d.manufstr, odp->manufstr, sizeof(d.manufstr)); - strlcpy(d.versstr, odp->versstr, sizeof(d.versstr)); - *d.cis3str = '\0'; - *d.cis4str = '\0'; - d.manufacturer = odp->manufacturer; - d.product = odp->product; - d.prodext = odp->prodext; - err = allocate_driver(slt, &d); - if (!err) - pccard_success_beep(); - else - pccard_failure_beep(); - return (err); -/***/#endif - /* - * Virtual removal/insertion - */ - case PIOCSVIR: - pwval = *(int *)data; - if (!pwval) { - if (slt->state != filled) - return (EINVAL); - pccard_event(slt, card_deactivated); - } else { - if (slt->state != empty && slt->state != inactive) - return (EINVAL); - pccard_event(slt, card_inserted); - } - break; - case PIOCSBEEP: - if (pccard_beep_select(*(int *)data)) { - return (EINVAL); - } - break; - } - return (0); -} - -/* - * poll - Poll on exceptions will return true - * when a change in card status occurs. - */ -static int -crdpoll(struct cdev *dev, int events, d_thread_t *td) -{ - int revents = 0; - int s; - struct slot *slt = PCCARD_DEV2SOFTC(dev); - - if (events & (POLLIN | POLLRDNORM)) - revents |= events & (POLLIN | POLLRDNORM); - - if (events & (POLLOUT | POLLWRNORM)) - revents |= events & (POLLIN | POLLRDNORM); - - s = splhigh(); - /* - * select for exception - card event. - */ - if (events & POLLRDBAND) - if (slt == 0 || slt->laststate != slt->state) - revents |= POLLRDBAND; - - if (revents == 0) - selrecord(td, &slt->selp); - - splx(s); - return (revents); -} - -/* - * APM hooks for suspending and resuming. - */ -int -pccard_suspend(device_t dev) -{ - struct slot *slt = PCCARD_DEVICE2SOFTC(dev); - - /* This code stolen from pccard_event:card_removed */ - if (slt->state == filled) { - int s = splhigh(); /* nop on current */ - disable_slot(slt); - slt->laststate = suspend; /* for pccardd */ - slt->state = empty; - splx(s); - printf("pccard: card disabled, slot %d\n", slt->slotnum); - } - /* - * Disable any pending timeouts for this slot since we're - * powering it down/disabling now. - */ - untimeout(power_off_slot, (caddr_t)slt, slt->poff_ch); - slt->ctrl->disable(slt); - return (0); -} - -int -pccard_resume(device_t dev) -{ - struct slot *slt = PCCARD_DEVICE2SOFTC(dev); - - slt->ctrl->resume(slt); - return (0); -} |