MFC: Remove OLDCARD. It only panics on my pc98 laptop. I'll fix cbb to attach to isa.

Approved by: re (scottl)
This commit is contained in:
imp 2005-10-06 16:34:27 +00:00
parent 91cfbaebd1
commit 9fc8aec782
9 changed files with 1 additions and 5441 deletions

View File

@ -2139,24 +2139,10 @@ device nmdm
#
device bktr
#
# PC Card/PCMCIA
# (OLDCARD)
#
# card: pccard slots
# pcic: isa/pccard bridge
#device pcic
#hint.pcic.0.at="isa"
#hint.pcic.1.at="isa"
#device card 1
#
# PC Card/PCMCIA and Cardbus
# (NEWCARD)
#
# Note that NEWCARD and OLDCARD are incompatible. Do not use both at the same
# time.
#
# pccbb: pci/cardbus bridge implementing YENTA interface
# pccard: pccard slots
# cardbus: cardbus slots

View File

@ -92,29 +92,19 @@ crypto/des/arch/i386/des_enc.S optional crypto
crypto/des/des_ecb.c optional crypto
crypto/des/des_setkey.c optional crypto
dev/aic/aic_cbus.c optional aic isa
dev/aic/aic_pccard.c optional aic card
dev/an/if_an_pccard.c optional an card
dev/ar/if_ar.c optional ar
dev/ar/if_ar_pci.c optional ar pci
dev/ata/ata-card.c optional ata card
dev/awi/if_awi_pccard.c optional awi card
dev/cnw/if_cnw.c optional cnw card
dev/cp/cpddk.c optional cp
dev/cp/if_cp.c optional cp
dev/cs/if_cs_pccard.c optional cs card
dev/ct/bshw_machdep.c optional ct
dev/ct/ct.c optional ct
dev/ct/ct_isa.c optional ct isa
dev/ed/if_ed_cbus.c optional ed isa
dev/ed/if_ed_pccard.c optional ed card
dev/ed/if_ed_wd80x3.c optional ed isa
dev/ep/if_ep_pccard.c optional ep card
dev/ex/if_ex_pccard.c optional ex card
dev/fb/fb.c optional fb
dev/fb/fb.c optional gdc
dev/fb/splash.c optional splash
dev/fe/if_fe_cbus.c optional fe isa
dev/fe/if_fe_pccard.c optional fe card
dev/hwpmc/hwpmc_amd.c optional hwpmc
dev/hwpmc/hwpmc_pentium.c optional hwpmc
dev/hwpmc/hwpmc_piv.c optional hwpmc
@ -128,20 +118,14 @@ dev/lnc/if_lnc_cbus.c optional lnc isa
dev/mem/memutil.c optional mem
dev/mse/mse.c optional mse
dev/mse/mse_cbus.c optional mse isa
dev/ncv/ncr53c500_pccard.c optional ncv card
dev/nsp/nsp_pccard.c optional nsp card
dev/ppc/ppc_puc.c optional ppc puc pci
dev/ray/if_ray.c optional ray card
dev/sbni/if_sbni.c optional sbni
dev/sbni/if_sbni_pci.c optional sbni pci
dev/sio/sio_pccard.c optional sio card
dev/sn/if_sn_pccard.c optional sn card
dev/snc/dp83932.c optional snc
dev/snc/dp83932subr.c optional snc
dev/snc/if_snc.c optional snc
dev/snc/if_snc_cbus.c optional snc isa
dev/snc/if_snc_pccard.c optional snc card
dev/stg/tmc18c30_pccard.c optional stg card
dev/snc/if_snc_pccard.c optional snc pccard
dev/syscons/apm/apm_saver.c optional apm_saver apm
dev/syscons/schistory.c optional sc
dev/syscons/scmouse.c optional sc
@ -151,8 +135,6 @@ dev/syscons/scvidctl.c optional sc
dev/syscons/syscons.c optional sc
dev/syscons/sysmouse.c optional sc
dev/uart/uart_cpu_pc98.c optional uart
dev/wi/if_wi_pccard.c optional wi card
dev/xe/if_xe_pccard.c optional xe card
geom/geom_bsd.c standard
geom/geom_bsd_enc.c standard
geom/geom_pc98.c standard
@ -369,13 +351,6 @@ pc98/pc98/canbus.c optional canbus
pc98/pc98/canbus_if.m optional canbus
pc98/pc98/machdep.c standard
pc98/pc98/pc98_machdep.c standard
pccard/pccard.c optional card
pccard/pccard_beep.c optional card
pccard/pccard_nbk.c optional card
pccard/pcic.c optional pcic card
pccard/pcic_isa.c optional pcic card isa
pccard/pcic_pci.c optional pcic card pci
pccard/mecia.c optional mecia card
pci/agp_ali.c optional agp
pci/agp_amd.c optional agp
pci/agp_i810.c optional agp

View File

@ -1,767 +0,0 @@
/*
* NEC MECIA controller.
*-------------------------------------------------------------------------
*/
/*-
* Copyright (c) 2001 M. Warner Losh. 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.
*
* 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$
*
* Based heavily on the FreeBSD pcic driver's pcic98 support, derived
* from PAO3 tree. This copyright notice likely needs modification for
* such a linage. The only authorship I could find was:
*
* PC9801 original PCMCIA controller code for NS/A,Ne,NX/C,NR/L.
* by Noriyuki Hosobuchi <hoso@ce.mbn.or.jp>
*/
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <pccard/meciareg.h>
#include <pccard/cardinfo.h>
#include <pccard/slot.h>
#ifndef MECIA_IOBASE
#define MECIA_IOBASE 0x80d0
#endif
/* Get pnp IDs */
#include <isa/isavar.h>
#include <dev/pccard/pccardvar.h>
#include "card_if.h"
#define MECIA_DEVICE2SOFTC(dev) ((struct mecia_slot *) device_get_softc(dev))
/*
* Prototypes for interrupt handler.
*/
static driver_intr_t meciaintr;
static int mecia_ioctl(struct slot *, int, caddr_t);
static int mecia_power(struct slot *);
static void mecia_mapirq(struct slot *, int);
static timeout_t mecia_reset;
static void mecia_resume(struct slot *);
static void mecia_disable(struct slot *);
static timeout_t meciatimeout;
static struct callout_handle meciatimeout_ch
= CALLOUT_HANDLE_INITIALIZER(&meciatimeout_ch);
static int mecia_memory(struct slot *, int);
static int mecia_io(struct slot *, int);
/*
* Per-slot data table.
*/
struct mecia_slot {
int unit; /* Unit number */
int slotnum; /* My slot number */
struct slot *slt; /* Back ptr to slot */
device_t dev; /* My device */
u_char last_reg1; /* Last value of change reg */
};
static struct slot_ctrl mecia_cinfo = {
mecia_mapirq,
mecia_memory,
mecia_io,
mecia_reset,
mecia_disable,
mecia_power,
mecia_ioctl,
mecia_resume,
1,
#if 0
1
#else
2 /* Fake for UE2212 LAN card */
#endif
};
static int validunits = 0;
/*
* Look for an NEC MECIA.
* For each available slot, allocate a PC-CARD slot.
*/
static int
mecia_probe(device_t dev)
{
int validslots = 0;
/* Check isapnp ids */
if (isa_get_logicalid(dev)) /* skip PnP probes */
return (ENXIO);
if (inb(MECIA_REG0) != 0xff) {
validslots++;
/* XXX need to allocated the port resources */
device_set_desc(dev, "MECIA PC98 Original PCMCIA Controller");
}
return (validslots ? 0 : ENXIO);
}
static int
mecia_attach(device_t dev)
{
int error;
int irq;
void *ih;
device_t kid;
struct resource *r;
int rid;
struct slot *slt;
struct mecia_slot *sp;
sp = MECIA_DEVICE2SOFTC(dev);
sp->unit = validunits++;
kid = device_add_child(dev, NULL, -1);
if (kid == NULL) {
device_printf(dev, "Can't add pccard bus slot 0\n");
return (ENXIO);
}
device_probe_and_attach(kid);
slt = pccard_init_slot(kid, &mecia_cinfo);
if (slt == 0) {
device_printf(dev, "Can't get pccard info slot 0\n");
return (ENXIO);
}
slt->cdata = sp;
sp->slt = slt;
validunits++;
rid = 0;
r = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
if (!r)
return (ENXIO);
irq = bus_get_resource_start(dev, SYS_RES_IRQ, 0);
if (irq == 0) {
/* See if the user has requested a specific IRQ */
if (!getenv_int("machdep.pccard.mecia_irq", &irq))
irq = 0;
}
rid = 0;
r = 0;
if (irq > 0) {
r = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, irq,
irq, 1, RF_ACTIVE);
}
if (r && ((1 << (rman_get_start(r))) & MECIA_INT_MASK_ALLOWED) == 0) {
device_printf(dev,
"Hardware does not support irq %d, trying polling.\n",
irq);
bus_release_resource(dev, SYS_RES_IRQ, rid, r);
r = 0;
irq = 0;
}
if (r) {
error = bus_setup_intr(dev, r, INTR_TYPE_MISC,
meciaintr, (void *) sp, &ih);
if (error) {
bus_release_resource(dev, SYS_RES_IRQ, rid, r);
return (error);
}
irq = rman_get_start(r);
device_printf(dev, "management irq %d\n", irq);
} else {
irq = 0;
}
if (irq == 0) {
meciatimeout_ch = timeout(meciatimeout, (void *) sp, hz/2);
device_printf(dev, "Polling mode\n");
}
sp->last_reg1 = inb(MECIA_REG1);
if (sp->last_reg1 & MECIA_CARDEXIST) {
/* PCMCIA card exist */
sp->slt->laststate = sp->slt->state = filled;
pccard_event(sp->slt, card_inserted);
} else {
sp->slt->laststate = sp->slt->state = empty;
}
sp->slt->irq = irq;
return (bus_generic_attach(dev));
}
static int
mecia_sresource(struct slot *slt, caddr_t data)
{
struct pccard_resource *pr;
struct resource *r;
int flags;
int rid = 0;
device_t pccarddev = slt->dev;
pr = (struct pccard_resource *)data;
pr->resource_addr = ~0ul;
switch(pr->type) {
default:
return (EINVAL);
case SYS_RES_MEMORY:
case SYS_RES_IRQ:
case SYS_RES_IOPORT:
break;
}
flags = rman_make_alignment_flags(pr->size);
r = bus_alloc_resource(pccarddev, pr->type, &rid, pr->min, pr->max,
pr->size, flags);
if (r != NULL) {
pr->resource_addr = (u_long)rman_get_start(r);
bus_release_resource(bridgedev, pr->type, rid, r);
}
return (0);
}
/*
* ioctl calls - Controller specific ioctls
*/
static int
mecia_ioctl(struct slot *slt, int cmd, caddr_t data)
{
switch(cmd) {
default:
return (ENOTTY);
case PIOCSRESOURCE: /* Can I use this resource? */
mecia_sresource(slt, data);
break;
}
return (0);
}
/*
* MECIA timer. If the controller doesn't have a free IRQ to use
* or if interrupt steering doesn't work, poll the controller for
* insertion/removal events.
*/
static void
meciatimeout(void *chan)
{
meciaintr(chan);
meciatimeout_ch = timeout(meciatimeout, chan, hz/2);
}
/*
* MECIA Interrupt handler.
* Check the slot and report any changes.
*/
static void
meciaintr(void *arg)
{
u_char reg1;
int s;
struct mecia_slot *sp = (struct mecia_slot *) arg;
s = splhigh();
/* Check for a card in this slot */
reg1 = inb(MECIA_REG1);
if ((sp->last_reg1 ^ reg1) & MECIA_CARDEXIST) {
sp->last_reg1 = reg1;
if (reg1 & MECIA_CARDEXIST)
pccard_event(sp->slt, card_inserted);
else
pccard_event(sp->slt, card_removed);
}
splx(s);
}
/*
* local functions for PC-98 Original PC-Card controller
*/
#define MECIA_ALWAYS_128MAPPING 1 /* trick for using UE2212 */
int mecia_mode = 0; /* almost the same as the value in MECIA_REG2 */
static unsigned char reg_winsel = MECIA_UNMAPWIN;
static unsigned short reg_pagofs = 0;
static int
mecia_memory(struct slot *slt, int win)
{
struct mem_desc *mp = &slt->mem[win];
unsigned char x;
if (mp->flags & MDF_ACTIVE) {
/* slot = 0, window = 0, sys_addr = 0xda000, length = 8KB */
if ((unsigned long)mp->start != 0xda000) {
printf(
"sys_addr must be 0xda000. requested address = %p\n",
mp->start);
return (EINVAL);
}
/* omajinai ??? */
outb(MECIA_REG0, 0);
x = inb(MECIA_REG1);
x &= 0xfc;
x |= 0x02;
outb(MECIA_REG1, x);
reg_winsel = inb(MECIA_REG_WINSEL);
reg_pagofs = inw(MECIA_REG_PAGOFS);
outb(MECIA_REG_WINSEL, MECIA_MAPWIN);
outw(MECIA_REG_PAGOFS, (mp->card >> 13)); /* 8KB */
if (mp->flags & MDF_ATTR)
outb(MECIA_REG7, inb(MECIA_REG7) | MECIA_ATTRMEM);
else
outb(MECIA_REG7, inb(MECIA_REG7) & (~MECIA_ATTRMEM));
outb(MECIA_REG_WINSEL, MECIA_MAPWIN);
#if 0
if ((mp->flags & MDF_16BITS) == 1) /* 16bit */
outb(MECIA_REG2, inb(MECIA_REG2) & (~MECIA_8BIT));
else /* 8bit */
outb(MECIA_REG2, inb(MECIA_REG2) | MECIA_8BIT);
#endif
} else { /* !(mp->flags & MDF_ACTIVE) */
outb(MECIA_REG0, 0);
x = inb(MECIA_REG1);
x &= 0xfc;
x |= 0x02;
outb(MECIA_REG1, x);
#if 0
outb(MECIA_REG_WINSEL, MECIA_UNMAPWIN);
outw(MECIA_REG_PAGOFS, 0);
#else
outb(MECIA_REG_WINSEL, reg_winsel);
outw(MECIA_REG_PAGOFS, reg_pagofs);
#endif
}
return (0);
}
static int
mecia_io(struct slot *slt, int win)
{
struct io_desc *ip = &slt->io[win];
unsigned char x;
unsigned short cardbase;
u_short ofst;
if (win != 0) {
/* ignore for UE2212 */
printf(
"mecia:Illegal MECIA I/O window(%d) request! Ignored.\n", win);
/* return (EINVAL);*/
return (0);
}
if (ip->flags & IODF_ACTIVE) {
x = inb(MECIA_REG2) & 0x0f;
#if 0
if (! (ip->flags & IODF_CS16))
x |= MECIA_8BIT;
#else
if (! (ip->flags & IODF_16BIT)) {
x |= MECIA_8BIT;
mecia_mode |= MECIA_8BIT;
}
#endif
ofst = ip->start & 0xf;
cardbase = ip->start & ~0xf;
#ifndef MECIA_ALWAYS_128MAPPING
if (ip->size + ofst > 16)
#endif
{ /* 128bytes mapping */
x |= MECIA_MAP128;
mecia_mode |= MECIA_MAP128;
ofst |= ((cardbase & 0x70) << 4);
cardbase &= ~0x70;
}
x |= MECIA_MAPIO;
outb(MECIA_REG2, x);
outw(MECIA_REG4, MECIA_IOBASE); /* 98side I/O base */
outw(MECIA_REG5, cardbase); /* card side I/O base */
if (bootverbose) {
printf("mecia: I/O mapped 0x%04x(98) -> "
"0x%04x(Card) and width %d bytes\n",
MECIA_IOBASE+ofst, ip->start, ip->size);
printf("mecia: reg2=0x%02x reg3=0x%02x reg7=0x%02x\n",
inb(MECIA_REG2), inb(MECIA_REG3),
inb(MECIA_REG7));
printf("mecia: mode=%d\n", mecia_mode);
}
ip->start = MECIA_IOBASE + ofst;
} else {
outb(MECIA_REG2, inb(MECIA_REG2) & (~MECIA_MAPIO));
mecia_mode = 0;
}
return (0);
}
static int
mecia_power(struct slot *slt)
{
unsigned char reg;
reg = inb(MECIA_REG7) & (~MECIA_VPP12V);
switch(slt->pwr.vpp) {
default:
return (EINVAL);
case 50:
break;
case 120:
reg |= MECIA_VPP12V;
break;
}
outb(MECIA_REG7, reg);
DELAY(100*1000);
reg = inb(MECIA_REG2) & (~MECIA_VCC3P3V);
switch(slt->pwr.vcc) {
default:
return (EINVAL);
case 33:
reg |= MECIA_VCC3P3V;
break;
case 50:
break;
}
outb(MECIA_REG2, reg);
DELAY(100*1000);
return (0);
}
static void
mecia_mapirq(struct slot *slt, int irq)
{
u_char x;
switch (irq) {
case 3:
x = MECIA_INT0;
break;
case 5:
x = MECIA_INT1;
break;
case 6:
x = MECIA_INT2;
break;
case 10:
x = MECIA_INT4;
break;
case 12:
x = MECIA_INT5;
break;
case 0: /* disable */
x = MECIA_INTDISABLE;
break;
default:
printf("mecia: illegal irq %d\n", irq);
return;
}
#ifdef MECIA_DEBUG
printf("mecia: irq=%d mapped.\n", irq);
#endif
outb(MECIA_REG3, x);
}
static void
mecia_reset(void *chan)
{
struct slot *slt = chan;
outb(MECIA_REG0, 0);
outb(MECIA_REG2, inb(MECIA_REG2) & (~MECIA_MAPIO));
outb(MECIA_REG3, MECIA_INTDISABLE);
#if 0
/* mecia_reset() is called after mecia_power() */
outb(MECIA_REG2, inb(MECIA_REG2) & (~MECIA_VCC3P3V));
outb(MECIA_REG7, inb(MECIA_REG7) & (~MECIA_VPP12V));
#endif
outb(MECIA_REG1, 0);
selwakeuppri(&slt->selp, PZERO);
}
static void
mecia_disable(struct slot *slt)
{
/* null function */
}
static void
mecia_resume(struct slot *slt)
{
/* XXX MECIA How ? */
}
static int
mecia_activate_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
{
struct pccard_devinfo *devi = device_get_ivars(child);
int err;
if (dev != device_get_parent(device_get_parent(child)) || devi == NULL)
return (bus_generic_activate_resource(dev, child, type,
rid, r));
switch (type) {
case SYS_RES_IOPORT: {
struct io_desc *ip;
ip = &devi->slt->io[rid];
if (ip->flags == 0) {
if (rid == 0)
ip->flags = IODF_WS | IODF_16BIT | IODF_CS16;
else
ip->flags = devi->slt->io[0].flags;
}
ip->flags |= IODF_ACTIVE;
ip->start = rman_get_start(r);
ip->size = rman_get_end(r) - rman_get_start(r) + 1;
err = mecia_cinfo.mapio(devi->slt, rid);
if (err)
return (err);
break;
}
case SYS_RES_IRQ:
/*
* We actually defer the activation of the IRQ resource
* until the interrupt is registered to avoid stray
* interrupt messages.
*/
break;
case SYS_RES_MEMORY: {
struct mem_desc *mp;
if (rid >= NUM_MEM_WINDOWS)
return (EINVAL);
mp = &devi->slt->mem[rid];
mp->flags |= MDF_ACTIVE;
mp->start = (caddr_t) rman_get_start(r);
mp->size = rman_get_end(r) - rman_get_start(r) + 1;
err = mecia_cinfo.mapmem(devi->slt, rid);
if (err)
return (err);
break;
}
default:
break;
}
err = bus_generic_activate_resource(dev, child, type, rid, r);
return (err);
}
static int
mecia_deactivate_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
{
struct pccard_devinfo *devi = device_get_ivars(child);
int err;
if (dev != device_get_parent(device_get_parent(child)) || devi == NULL)
return (bus_generic_deactivate_resource(dev, child, type,
rid, r));
switch (type) {
case SYS_RES_IOPORT: {
struct io_desc *ip = &devi->slt->io[rid];
ip->flags &= ~IODF_ACTIVE;
err = mecia_cinfo.mapio(devi->slt, rid);
if (err)
return (err);
break;
}
case SYS_RES_IRQ:
break;
case SYS_RES_MEMORY: {
struct mem_desc *mp = &devi->slt->mem[rid];
mp->flags &= ~(MDF_ACTIVE | MDF_ATTR);
err = mecia_cinfo.mapmem(devi->slt, rid);
if (err)
return (err);
break;
}
default:
break;
}
err = bus_generic_deactivate_resource(dev, child, type, rid, r);
return (err);
}
static int
mecia_setup_intr(device_t dev, device_t child, struct resource *irq,
int flags, driver_intr_t *intr, void *arg, void **cookiep)
{
struct pccard_devinfo *devi = device_get_ivars(child);
int err;
if (((1 << rman_get_start(irq)) & MECIA_INT_MASK_ALLOWED) == 0) {
device_printf(dev, "Hardware does not support irq %ld.\n",
rman_get_start(irq));
return (EINVAL);
}
err = bus_generic_setup_intr(dev, child, irq, flags, intr, arg,
cookiep);
if (err == 0)
mecia_cinfo.mapirq(devi->slt, rman_get_start(irq));
else
device_printf(dev, "Error %d irq %ld\n", err,
rman_get_start(irq));
return (err);
}
static int
mecia_teardown_intr(device_t dev, device_t child, struct resource *irq,
void *cookie)
{
struct pccard_devinfo *devi = device_get_ivars(child);
mecia_cinfo.mapirq(devi->slt, 0);
return (bus_generic_teardown_intr(dev, child, irq, cookie));
}
static int
mecia_set_res_flags(device_t bus, device_t child, int restype, int rid,
u_long value)
{
struct pccard_devinfo *devi = device_get_ivars(child);
int err = 0;
switch (restype) {
case SYS_RES_MEMORY: {
struct mem_desc *mp = &devi->slt->mem[rid];
switch (value) {
case PCCARD_A_MEM_COM:
mp->flags &= ~MDF_ATTR;
break;
case PCCARD_A_MEM_ATTR:
mp->flags |= MDF_ATTR;
break;
case PCCARD_A_MEM_8BIT:
mp->flags &= ~MDF_16BITS;
break;
case PCCARD_A_MEM_16BIT:
mp->flags |= MDF_16BITS;
break;
}
err = mecia_cinfo.mapmem(devi->slt, rid);
break;
}
default:
err = EOPNOTSUPP;
}
return (err);
}
static int
mecia_get_res_flags(device_t bus, device_t child, int restype, int rid,
u_long *value)
{
struct pccard_devinfo *devi = device_get_ivars(child);
int err = 0;
if (value == 0)
return (ENOMEM);
switch (restype) {
case SYS_RES_IOPORT: {
struct io_desc *ip = &devi->slt->io[rid];
*value = ip->flags;
break;
}
case SYS_RES_MEMORY: {
struct mem_desc *mp = &devi->slt->mem[rid];
*value = mp->flags;
break;
}
default:
err = EOPNOTSUPP;
}
return (err);
}
static int
mecia_set_memory_offset(device_t bus, device_t child, int rid,
u_int32_t offset, u_int32_t *deltap)
{
struct pccard_devinfo *devi = device_get_ivars(child);
struct mem_desc *mp = &devi->slt->mem[rid];
mp->card = offset;
if (deltap)
*deltap = 0; /* XXX BAD XXX */
return (mecia_cinfo.mapmem(devi->slt, rid));
}
static int
mecia_get_memory_offset(device_t bus, device_t child, int rid,
u_int32_t *offset)
{
struct pccard_devinfo *devi = device_get_ivars(child);
struct mem_desc *mp = &devi->slt->mem[rid];
if (offset == 0)
return (ENOMEM);
*offset = mp->card;
return (0);
}
static device_method_t mecia_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, mecia_probe),
DEVMETHOD(device_attach, mecia_attach),
DEVMETHOD(device_detach, bus_generic_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_suspend, bus_generic_suspend),
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, mecia_activate_resource),
DEVMETHOD(bus_deactivate_resource, mecia_deactivate_resource),
DEVMETHOD(bus_setup_intr, mecia_setup_intr),
DEVMETHOD(bus_teardown_intr, mecia_teardown_intr),
/* Card interface */
DEVMETHOD(card_set_res_flags, mecia_set_res_flags),
DEVMETHOD(card_get_res_flags, mecia_get_res_flags),
DEVMETHOD(card_set_memory_offset, mecia_set_memory_offset),
DEVMETHOD(card_get_memory_offset, mecia_get_memory_offset),
{ 0, 0 }
};
devclass_t mecia_devclass;
static driver_t mecia_driver = {
"mecia",
mecia_methods,
sizeof(struct mecia_slot)
};
DRIVER_MODULE(mecia, isa, mecia_driver, mecia_devclass, 0, 0);

View File

@ -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);
}

View File

@ -1,138 +0,0 @@
/*-
* pccard noise interface.
* Nate Williams, October 1997.
* This file is in the public domain.
*/
/* $FreeBSD$ */
#define OBSOLETE_IN_6
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <machine/clock.h>
#include <pccard/driver.h>
static enum beepstate allow_beep = BEEP_OFF;
static int melody_type = 0;
#define MAX_TONE_MODE 3
#define MAX_STATE 4
struct tone {
int pitch;
int duration;
};
static struct tone silent_beep[] = {
{0, 0}
};
static struct tone success_beep[] = {
{1200, 40}, {0, 0}
};
static struct tone failure_beep[] = {
{3200, 40}, {0, 0}
};
static struct tone insert_remove_beep[] = {
{1600, 20}, {0, 0}
};
static struct tone success_melody_beep[] = {
{1200, 7}, {1000, 7}, { 800, 15}, {0, 0}
};
static struct tone failure_melody_beep[] = {
{2000, 7}, {2400, 7}, {2800, 15}, {0, 0}
};
static struct tone insert_melody_beep[] = {
{1600, 10}, {1200, 5}, {0, 0}
};
static struct tone remove_melody_beep[] = {
{1200, 10}, {1600, 5}, {0, 0}
};
static struct tone *melody_table[MAX_TONE_MODE][MAX_STATE] = {
{ /* silent mode */
silent_beep, silent_beep, silent_beep, silent_beep,
},
{ /* simple beep mode */
success_beep, failure_beep,
insert_remove_beep, insert_remove_beep,
},
{ /* melody beep mode */
success_melody_beep, failure_melody_beep,
insert_melody_beep, remove_melody_beep,
},
};
static void
pccard_beep_sub(void *arg)
{
struct tone *melody;
melody = (struct tone *)arg;
if (melody->pitch != 0) {
sysbeep(melody->pitch, (melody->duration * hz + 99) / 100);
timeout(pccard_beep_sub, melody + 1,
(melody->duration * hz + 99) / 100);
} else
allow_beep = BEEP_ON;
}
static void
pccard_beep_start(void *arg)
{
struct tone *melody;
melody = (struct tone *)arg;
if (allow_beep == BEEP_ON && melody->pitch != 0) {
allow_beep = BEEP_OFF;
sysbeep(melody->pitch, (melody->duration * hz + 99) / 100);
timeout(pccard_beep_sub, melody + 1,
(melody->duration * hz + 99) / 100);
}
}
void
pccard_success_beep(void)
{
pccard_beep_start(melody_table[melody_type][0]);
}
void
pccard_failure_beep(void)
{
pccard_beep_start(melody_table[melody_type][1]);
}
void
pccard_insert_beep(void)
{
pccard_beep_start(melody_table[melody_type][2]);
}
void
pccard_remove_beep(void)
{
pccard_beep_start(melody_table[melody_type][3]);
}
int
pccard_beep_select(int type)
{
int errcode = 0;
if (type == 0) {
allow_beep = BEEP_OFF;
melody_type = 0;
} else if (type < 0 || MAX_TONE_MODE - 1 < type) {
errcode = 1;
} else {
allow_beep = BEEP_ON;
melody_type = type;
}
return (errcode);
}

View File

@ -1,436 +0,0 @@
/*-
* Copyright (c) 1999, 2001 M. Warner Losh. 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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$
*/
/*
* This file contains various kludges to allow the legacy pccard system to
* work in the newbus system until the pccard system can be converted
* wholesale to newbus. As that is a while off, I'm providing this glue to
* allow newbus drivers to have pccard attachments.
*
* We do *NOT* implement ISA ivars at all. We are not an isa bus, and drivers
* that abuse isa_{set,get}_* must be fixed in order to work with pccard.
* We use ivars for something else anyway, so it becomes fairly awkward
* to do so.
*
* Here's a summary of the glue that we do to make things work.
*
* First, we have pccard node in the device and driver trees. The pccard
* device lives in the instance tree attached to the nexus. The pccard
* attachments will be attached to that node. This allows one to pass things
* up the tree that terminates at the nexus, like other buses. The pccard
* code will create a device instance for each of the drivers that are to
* be attached.
*
* These compatibility nodes are called pccnbk. PCCard New Bus Kludge.
*/
#define OBSOLETE_IN_6
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
#include <sys/queue.h>
#include <sys/types.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <machine/resource.h>
/* XXX Shouldn't reach into the MD code here */
#ifdef PC98
#include <pc98/cbus/cbus.h>
#else
#include <i386/isa/isa.h>
#endif
#include <pccard/cardinfo.h>
#include <pccard/slot.h>
#include <dev/pccard/pccardvar.h>
#include <net/ethernet.h>
#include "card_if.h"
devclass_t pccard_devclass;
#define PCCARD_NPORT 2
#define PCCARD_NMEM 5
#define PCCARD_NIRQ 1
#define PCCARD_NDRQ 0
#define PCCARD_DEVINFO(d) (struct pccard_devinfo *) device_get_ivars(d)
SYSCTL_NODE(_machdep, OID_AUTO, pccard, CTLFLAG_RW, 0, "pccard");
#ifdef UNSAFE
static u_long mem_start = IOM_BEGIN;
static u_long mem_end = IOM_END;
#else
static u_long mem_start = 0xd0000;
static u_long mem_end = 0xeffff;
#endif
SYSCTL_ULONG(_machdep_pccard, OID_AUTO, mem_start, CTLFLAG_RW,
&mem_start, 0, "");
SYSCTL_ULONG(_machdep_pccard, OID_AUTO, mem_end, CTLFLAG_RW,
&mem_end, 0, "");
#if __FreeBSD_version >= 500000
/*
* glue for NEWCARD/OLDCARD compat layer
*/
static int
pccard_compat_do_probe(device_t bus, device_t dev)
{
return (CARD_COMPAT_PROBE(dev));
}
static int
pccard_compat_do_attach(device_t bus, device_t dev)
{
return (CARD_COMPAT_ATTACH(dev));
}
#endif
static int
pccard_probe(device_t dev)
{
device_set_desc(dev, "PC Card 16-bit bus (classic)");
return (0);
}
static int
pccard_attach(device_t dev)
{
return (0);
}
static void
pccard_print_resources(struct resource_list *rl, const char *name, int type,
int count, const char *format)
{
struct resource_list_entry *rle;
int printed;
int i;
printed = 0;
for (i = 0; i < count; i++) {
rle = resource_list_find(rl, type, i);
if (rle) {
if (printed == 0)
printf(" %s ", name);
else if (printed > 0)
printf(",");
printed++;
printf(format, rle->start);
if (rle->count > 1) {
printf("-");
printf(format, rle->start + rle->count - 1);
}
} else if (i > 3) {
/* check the first few regardless */
break;
}
}
}
static int
pccard_print_child(device_t dev, device_t child)
{
struct pccard_devinfo *devi = PCCARD_DEVINFO(child);
struct resource_list *rl = &devi->resources;
int retval = 0;
int flags = device_get_flags(child);
retval += bus_print_child_header(dev, child);
retval += printf(" at");
if (devi) {
pccard_print_resources(rl, "port", SYS_RES_IOPORT,
PCCARD_NPORT, "%#lx");
pccard_print_resources(rl, "iomem", SYS_RES_MEMORY,
PCCARD_NMEM, "%#lx");
pccard_print_resources(rl, "irq", SYS_RES_IRQ, PCCARD_NIRQ,
"%ld");
pccard_print_resources(rl, "drq", SYS_RES_DRQ, PCCARD_NDRQ,
"%ld");
if (flags != 0)
retval += printf(" flags 0x%x", flags);
retval += printf(" slot %d", devi->slt->slotnum);
}
retval += bus_print_child_footer(dev, child);
return (retval);
}
static int
pccard_set_resource(device_t dev, device_t child, int type, int rid,
u_long start, u_long count)
{
struct pccard_devinfo *devi = PCCARD_DEVINFO(child);
struct resource_list *rl = &devi->resources;
if (type != SYS_RES_IOPORT && type != SYS_RES_MEMORY
&& type != SYS_RES_IRQ && type != SYS_RES_DRQ)
return (EINVAL);
if (rid < 0)
return (EINVAL);
if (type == SYS_RES_IOPORT && rid >= PCCARD_NPORT)
return (EINVAL);
if (type == SYS_RES_MEMORY && rid >= PCCARD_NMEM)
return (EINVAL);
if (type == SYS_RES_IRQ && rid >= PCCARD_NIRQ)
return (EINVAL);
if (type == SYS_RES_DRQ && rid >= PCCARD_NDRQ)
return (EINVAL);
resource_list_add(rl, type, rid, start, start + count - 1, count);
return (0);
}
static int
pccard_get_resource(device_t dev, device_t child, int type, int rid,
u_long *startp, u_long *countp)
{
struct pccard_devinfo *devi = PCCARD_DEVINFO(child);
struct resource_list *rl = &devi->resources;
struct resource_list_entry *rle;
rle = resource_list_find(rl, type, rid);
if (!rle)
return (ENOENT);
if (startp)
*startp = rle->start;
if (countp)
*countp = rle->count;
return (0);
}
static void
pccard_delete_resource(device_t dev, device_t child, int type, int rid)
{
struct pccard_devinfo *devi = PCCARD_DEVINFO(child);
struct resource_list *rl = &devi->resources;
resource_list_delete(rl, type, rid);
}
static struct resource *
pccard_alloc_resource(device_t bus, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
/*
* Consider adding a resource definition. We allow rid 0 for
* irq, 0-4 for memory and 0-1 for ports
*/
int passthrough = (device_get_parent(child) != bus);
int isdefault;
struct pccard_devinfo *devi = device_get_ivars(child);
struct resource_list *rl = &devi->resources;
struct resource_list_entry *rle;
struct resource *res;
if (start == 0 && end == ~0 && type == SYS_RES_MEMORY && count != 1) {
start = mem_start;
end = mem_end;
}
isdefault = (start == 0UL && end == ~0UL);
if (!passthrough && !isdefault) {
rle = resource_list_find(rl, type, *rid);
if (!rle) {
if (*rid < 0)
return (NULL);
switch (type) {
case SYS_RES_IRQ:
if (*rid >= PCCARD_NIRQ)
return (NULL);
break;
case SYS_RES_DRQ:
if (*rid >= PCCARD_NDRQ)
return (NULL);
break;
case SYS_RES_MEMORY:
if (*rid >= PCCARD_NMEM)
return (NULL);
break;
case SYS_RES_IOPORT:
if (*rid >= PCCARD_NPORT)
return (NULL);
break;
default:
return (NULL);
}
resource_list_add(rl, type, *rid, start, end, count);
}
}
res = resource_list_alloc(rl, bus, child, type, rid, start, end,
count, flags);
return (res);
}
static int
pccard_release_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
struct pccard_devinfo *devi = PCCARD_DEVINFO(child);
struct resource_list *rl = &devi->resources;
return (resource_list_release(rl, bus, child, type, rid, r));
}
static int
pccard_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
{
struct pccard_devinfo *devi = PCCARD_DEVINFO(child);
switch (which) {
case PCCARD_IVAR_ETHADDR:
bcopy(devi->misc, result, ETHER_ADDR_LEN);
return (0);
case PCCARD_IVAR_VENDOR:
*(u_int32_t *) result = devi->manufacturer;
return (0);
case PCCARD_IVAR_PRODUCT:
*(u_int32_t *) result = devi->product;
return (0);
case PCCARD_IVAR_PRODEXT:
*(u_int16_t *) result = devi->prodext;
return (0);
case PCCARD_IVAR_VENDOR_STR:
*(char **) result = devi->manufstr;
break;
case PCCARD_IVAR_PRODUCT_STR:
*(char **) result = devi->versstr;
break;
case PCCARD_IVAR_CIS3_STR:
*(char **) result = devi->cis3str;
break;
case PCCARD_IVAR_CIS4_STR:
*(char **) result = devi->cis4str;
break;
}
return (ENOENT);
}
static int
pccard_set_res_flags(device_t bus, device_t child, int restype, int rid,
u_long value)
{
return (CARD_SET_RES_FLAGS(device_get_parent(bus), child, restype,
rid, value));
}
static int
pccard_get_res_flags(device_t bus, device_t child, int restype, int rid,
u_long *value)
{
return (CARD_GET_RES_FLAGS(device_get_parent(bus), child, restype,
rid, value));
}
static int
pccard_set_memory_offset(device_t bus, device_t child, int rid,
u_int32_t offset
#if __FreeBSD_version >= 500000
, u_int32_t *deltap
#endif
)
{
return (CARD_SET_MEMORY_OFFSET(device_get_parent(bus), child, rid,
offset
#if __FreeBSD_version >= 500000
, deltap
#endif
));
}
static int
pccard_get_memory_offset(device_t bus, device_t child, int rid,
u_int32_t *offset)
{
return (CARD_GET_MEMORY_OFFSET(device_get_parent(bus), child, rid,
offset));
}
#if __FreeBSD_version >= 500000
static const struct pccard_product *
pccard_do_product_lookup(device_t bus, device_t dev,
const struct pccard_product *tab,
size_t ent_size, pccard_product_match_fn matchfn)
{
return (NULL);
}
#endif
static device_method_t pccard_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, pccard_probe),
DEVMETHOD(device_attach, pccard_attach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_suspend, pccard_suspend),
DEVMETHOD(device_resume, pccard_resume),
/* Bus interface */
DEVMETHOD(bus_print_child, pccard_print_child),
DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD(bus_alloc_resource, pccard_alloc_resource),
DEVMETHOD(bus_release_resource, pccard_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
DEVMETHOD(bus_set_resource, pccard_set_resource),
DEVMETHOD(bus_get_resource, pccard_get_resource),
DEVMETHOD(bus_delete_resource, pccard_delete_resource),
DEVMETHOD(bus_read_ivar, pccard_read_ivar),
/* Card interface */
DEVMETHOD(card_set_res_flags, pccard_set_res_flags),
DEVMETHOD(card_get_res_flags, pccard_get_res_flags),
DEVMETHOD(card_set_memory_offset, pccard_set_memory_offset),
DEVMETHOD(card_get_memory_offset, pccard_get_memory_offset),
#if __FreeBSD_version >= 500000
DEVMETHOD(card_compat_do_probe, pccard_compat_do_probe),
DEVMETHOD(card_compat_do_attach, pccard_compat_do_attach),
DEVMETHOD(card_do_product_lookup, pccard_do_product_lookup),
#endif
{ 0, 0 }
};
static driver_t pccard_driver = {
"pccard",
pccard_methods,
sizeof(struct slot)
};
DRIVER_MODULE(pccard, pcic, pccard_driver, pccard_devclass, 0, 0);
DRIVER_MODULE(pccard, mecia, pccard_driver, pccard_devclass, 0, 0);
MODULE_VERSION(pccard, 1);

File diff suppressed because it is too large Load Diff

View File

@ -1,399 +0,0 @@
/*-
* Copyright (c) 2001 M. Warner Losh. 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.
*
* 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/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <pccard/i82365.h>
#include <pccard/cardinfo.h>
#include <pccard/slot.h>
#include <pccard/pcicvar.h>
/* Get pnp IDs */
#include <isa/isavar.h>
#include <dev/pccard/pccardvar.h>
#include "card_if.h"
static struct isa_pnp_id pcic_ids[] = {
{PCIC_PNP_ACTIONTEC, NULL}, /* AEI0218 */
{PCIC_PNP_IBM3765, NULL}, /* IBM3765 */
{PCIC_PNP_82365, NULL}, /* PNP0E00 */
{PCIC_PNP_CL_PD6720, NULL}, /* PNP0E01 */
{PCIC_PNP_VLSI_82C146, NULL}, /* PNP0E02 */
{PCIC_PNP_82365_CARDBUS, NULL}, /* PNP0E03 */
{PCIC_PNP_SCM_SWAPBOX, NULL}, /* SCM0469 */
{PCIC_NEC_PC9801_102, NULL}, /* NEC8091 */
{PCIC_NEC_PC9821RA_E01, NULL}, /* NEC8121 */
{0}
};
static struct {
const char *name;
u_int32_t flags;
} bridges[] = {
{ "Intel i82365SL-A/B", PCIC_AB_POWER},
{ "IBM PCIC", PCIC_AB_POWER},
{ "VLSI 82C146", PCIC_AB_POWER},
{ "Cirrus logic 6722", PCIC_PD_POWER},
{ "Cirrus logic 6710", PCIC_PD_POWER},
{ "Vadem 365", PCIC_VG_POWER},
{ "Vadem 465", PCIC_VG_POWER},
{ "Vadem 468", PCIC_VG_POWER},
{ "Vadem 469", PCIC_VG_POWER},
{ "Ricoh RF5C296", PCIC_RICOH_POWER},
{ "Ricoh RF5C396", PCIC_RICOH_POWER},
{ "IBM KING", PCIC_KING_POWER},
{ "Intel i82365SL-DF", PCIC_DF_POWER}
};
static pcic_intr_way_t pcic_isa_intr_way;
static pcic_init_t pcic_isa_init;
struct pcic_chip pcic_isa_chip = {
pcic_isa_intr_way,
pcic_isa_intr_way,
pcic_isa_mapirq,
pcic_isa_init
};
/*
* Look for an Intel PCIC (or compatible).
* For each available slot, allocate a PC-CARD slot.
*/
static int
pcic_isa_probe(device_t dev)
{
int slotnum, validslots = 0;
struct pcic_slot *sp;
struct pcic_slot *sp0;
struct pcic_slot *sp1;
struct pcic_slot spsave;
unsigned char c;
struct resource *r;
int rid;
struct pcic_softc *sc;
int error;
/* Check isapnp ids */
error = ISA_PNP_PROBE(device_get_parent(dev), dev, pcic_ids);
if (error == ENXIO)
return (ENXIO);
if (bus_get_resource_start(dev, SYS_RES_IOPORT, 0) == 0)
bus_set_resource(dev, SYS_RES_IOPORT, 0, PCIC_PORT_0,
PCIC_NPORT);
rid = 0;
r = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE);
if (!r) {
if (bootverbose)
device_printf(dev, "Cannot get I/O range\n");
return (ENOMEM);
}
sc = (struct pcic_softc *) device_get_softc(dev);
sc->dev = dev;
sp = &sc->slots[0];
for (slotnum = 0; slotnum < PCIC_CARD_SLOTS; slotnum++, sp++) {
/*
* Initialise the PCIC slot table.
*/
sp->getb = pcic_getb_io;
sp->putb = pcic_putb_io;
sp->bst = rman_get_bustag(r);
sp->bsh = rman_get_bushandle(r);
sp->offset = slotnum * PCIC_SLOT_SIZE;
sp->controller = -1;
}
/*
* Prescan for the broken VLSI chips.
*
* According to the Linux PCMCIA code from David Hinds,
* working chipsets return 0x84 from their (correct) ID ports,
* while the broken ones would need to be probed at the new
* offset we set after we assume it's broken.
*
* Note: because of this, we may incorrectly detect a single
* slot vlsi chip as an i82365sl step D. I cannot find a
* datasheet for the affected chip, so that's the best we can
* do for now.
*/
sp0 = &sc->slots[0];
sp1 = &sc->slots[1];
if (sp0->getb(sp0, PCIC_ID_REV) == PCIC_VLSI82C146 &&
sp1->getb(sp1, PCIC_ID_REV) != PCIC_VLSI82C146) {
spsave = *sp1;
sp1->bsh += 4;
sp1->offset = PCIC_SLOT_SIZE << 1;
if (sp1->getb(sp1, PCIC_ID_REV) != PCIC_VLSI82C146) {
*sp1 = spsave;
} else {
sp0->controller = PCIC_VLSI;
sp1->controller = PCIC_VLSI;
}
}
/*
* Look for normal chipsets here.
*/
sp = &sc->slots[0];
for (slotnum = 0; slotnum < PCIC_CARD_SLOTS; slotnum++, sp++) {
/*
* see if there's a PCMCIA controller here
* Intel PCMCIA controllers use 0x82 and 0x83
* IBM clone chips use 0x88 and 0x89, apparently
*/
c = sp->getb(sp, PCIC_ID_REV);
sp->revision = -1;
switch(c) {
/*
* 82365 or clones.
*/
case PCIC_INTEL0:
case PCIC_INTEL1:
sp->controller = PCIC_I82365;
sp->revision = c & 1;
/*
* Check for Vadem chips by unlocking their extra
* registers and looking for valid ID. Bit 3 in
* the ID register is normally 0, except when
* PCIC_VADEMREV is set. Other bridges appear
* to ignore this frobbing.
*/
bus_space_write_1(sp->bst, sp->bsh, PCIC_INDEX, 0x0E);
bus_space_write_1(sp->bst, sp->bsh, PCIC_INDEX, 0x37);
pcic_setb(sp, PCIC_VMISC, PCIC_VADEMREV);
c = sp->getb(sp, PCIC_ID_REV);
if (c & 0x08) {
switch (sp->revision = c & 7) {
case 1:
sp->controller = PCIC_VG365;
break;
case 2:
sp->controller = PCIC_VG465;
break;
case 3:
sp->controller = PCIC_VG468;
break;
default:
sp->controller = PCIC_VG469;
break;
}
pcic_clrb(sp, PCIC_VMISC, PCIC_VADEMREV);
}
/*
* Check for RICOH RF5C[23]96 PCMCIA Controller
*/
c = sp->getb(sp, PCIC_RICOH_ID);
if (c == PCIC_RID_396)
sp->controller = PCIC_RF5C396;
else if (c == PCIC_RID_296)
sp->controller = PCIC_RF5C296;
break;
/*
* Intel i82365sl-DF step or maybe a vlsi 82c146
* we detected the vlsi case earlier, so if the controller
* isn't set, we know it is an i82365sl step D.
*/
case PCIC_INTEL2:
if (sp->controller == -1)
sp->controller = PCIC_I82365SL_DF;
break;
case PCIC_IBM1:
case PCIC_IBM2:
sp->controller = PCIC_IBM;
sp->revision = c & 1;
break;
case PCIC_IBM3:
sp->controller = PCIC_IBM_KING;
sp->revision = c & 1;
break;
default:
continue;
}
/*
* Check for Cirrus logic chips.
*/
sp->putb(sp, PCIC_CLCHIP, 0);
c = sp->getb(sp, PCIC_CLCHIP);
if ((c & PCIC_CLC_TOGGLE) == PCIC_CLC_TOGGLE) {
c = sp->getb(sp, PCIC_CLCHIP);
if ((c & PCIC_CLC_TOGGLE) == 0) {
if (c & PCIC_CLC_DUAL)
sp->controller = PCIC_PD6722;
else
sp->controller = PCIC_PD6710;
sp->revision = 8 - ((c & 0x1F) >> 2);
}
}
device_set_desc(dev, bridges[(int) sp->controller].name);
sc->flags = bridges[(int) sp->controller].flags;
/*
* OK it seems we have a PCIC or lookalike.
* Allocate a slot and initialise the data structures.
*/
validslots++;
sp->slt = (struct slot *) 1;
/*
* Modem cards send the speaker audio (dialing noises)
* to the host's speaker. Cirrus Logic PCIC chips must
* enable this. There is also a Low Power Dynamic Mode bit
* that claims to reduce power consumption by 30%, so
* enable it and hope for the best.
*/
if (sp->controller == PCIC_PD6722) {
pcic_setb(sp, PCIC_MISC1, PCIC_MISC1_SPEAKER);
pcic_setb(sp, PCIC_MISC2, PCIC_LPDM_EN);
}
}
bus_release_resource(dev, SYS_RES_IOPORT, rid, r);
return (validslots ? 0 : ENXIO);
}
static int
pcic_isa_attach(device_t dev)
{
struct pcic_softc *sc;
int rid;
struct resource *r;
int irq = 0;
int error;
sc = device_get_softc(dev);
rid = 0;
r = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE);
if (!r) {
pcic_dealloc(dev);
return (ENXIO);
}
sc->iorid = rid;
sc->iores = r;
sc->csc_route = pcic_iw_isa;
sc->func_route = pcic_iw_isa;
sc->chip = &pcic_isa_chip;
rid = 0;
r = NULL;
r = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_ACTIVE);
if (r == NULL && pcic_override_irq != 0) {
irq = pcic_override_irq;
r = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, irq, irq, 1,
RF_ACTIVE);
}
if (r && ((1 << (rman_get_start(r))) & PCIC_INT_MASK_ALLOWED) == 0) {
device_printf(dev,
"Hardware does not support irq %d, trying polling.\n",
irq);
bus_release_resource(dev, SYS_RES_IRQ, rid, r);
irq = 0;
r = NULL;
}
sc->irqrid = rid;
sc->irqres = r;
irq = 0;
if (r != NULL) {
error = bus_setup_intr(dev, r, INTR_TYPE_MISC,
pcic_isa_intr, (void *) sc, &sc->ih);
if (error) {
pcic_dealloc(dev);
return (error);
}
irq = rman_get_start(r);
device_printf(dev, "management irq %d\n", irq);
}
sc->irq = irq;
if (irq == 0) {
sc->slot_poll = pcic_timeout;
sc->timeout_ch = timeout(sc->slot_poll, (void *) sc, hz/2);
device_printf(dev, "Polling mode\n");
}
return (pcic_attach(dev));
}
/*
* ISA cards can only do ISA interrupts. There's no need to do
* anything but check args for sanity.
*/
static int
pcic_isa_intr_way(struct pcic_slot *sp, enum pcic_intr_way iw)
{
if (iw != pcic_iw_isa)
return (EINVAL);
return (0);
}
/*
* No speicial initialization is necesary for ISA cards.
*/
static void
pcic_isa_init(device_t dev)
{
}
static device_method_t pcic_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, pcic_isa_probe),
DEVMETHOD(device_attach, pcic_isa_attach),
DEVMETHOD(device_detach, bus_generic_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_suspend, bus_generic_suspend),
DEVMETHOD(device_resume, bus_generic_resume),
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_alloc_resource, pcic_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, pcic_activate_resource),
DEVMETHOD(bus_deactivate_resource, pcic_deactivate_resource),
DEVMETHOD(bus_setup_intr, pcic_setup_intr),
DEVMETHOD(bus_teardown_intr, pcic_teardown_intr),
/* Card interface */
DEVMETHOD(card_set_res_flags, pcic_set_res_flags),
DEVMETHOD(card_get_res_flags, pcic_get_res_flags),
DEVMETHOD(card_set_memory_offset, pcic_set_memory_offset),
DEVMETHOD(card_get_memory_offset, pcic_get_memory_offset),
{ 0, 0 }
};
static driver_t pcic_driver = {
"pcic",
pcic_methods,
sizeof(struct pcic_softc)
};
DRIVER_MODULE(pcic, isa, pcic_driver, pcic_devclass, 0, 0);

File diff suppressed because it is too large Load Diff