Reorganize the attachement point for pcic (it was unattached and
floating before). Attach pccard devices to pcic, one per slot (although this may change to one per pcic). pcic is now attached to isa (to act as a bridge) and pccard is attached to pcic, cbb and pc98ic (the last two are card bus bridge and the pc98ic version of pcic, neither of which are in the tree yet). Move pccard compat code into pccard/pccard_compat.c. THIS REQUIRES A CONFIG FILE CHANGE. You must change your pcic/card entries to be: # PCCARD (PCMCIA) support controller pcic0 at isa? controller pcic1 at isa? controller card0 The old system was upside down and this corrects that problem. It will make it easier to add support for YENTA pccard/card bus bridges. Much more cleanup needs to happen before newbus devices can have pccard attachments. My previous commit's comments were premature.
This commit is contained in:
parent
ae409c2b97
commit
b5137699ae
@ -1810,11 +1810,11 @@ device bktr0
|
||||
#
|
||||
# PCCARD/PCMCIA
|
||||
#
|
||||
# card: slot controller
|
||||
# pcic: slots
|
||||
# card: pccard slots
|
||||
# pcic: isa/pccard bridge
|
||||
controller pcic0 at isa?
|
||||
controller pcic1 at isa?
|
||||
controller card0
|
||||
device pcic0 at card?
|
||||
device pcic1 at card?
|
||||
|
||||
# You may need to reset all pccards after resuming
|
||||
options PCIC_RESUME_RESET # reset after resume
|
||||
|
@ -1810,11 +1810,11 @@ device bktr0
|
||||
#
|
||||
# PCCARD/PCMCIA
|
||||
#
|
||||
# card: slot controller
|
||||
# pcic: slots
|
||||
# card: pccard slots
|
||||
# pcic: isa/pccard bridge
|
||||
controller pcic0 at isa?
|
||||
controller pcic1 at isa?
|
||||
controller card0
|
||||
device pcic0 at card?
|
||||
device pcic1 at card?
|
||||
|
||||
# You may need to reset all pccards after resuming
|
||||
options PCIC_RESUME_RESET # reset after resume
|
||||
|
@ -1810,11 +1810,11 @@ device bktr0
|
||||
#
|
||||
# PCCARD/PCMCIA
|
||||
#
|
||||
# card: slot controller
|
||||
# pcic: slots
|
||||
# card: pccard slots
|
||||
# pcic: isa/pccard bridge
|
||||
controller pcic0 at isa?
|
||||
controller pcic1 at isa?
|
||||
controller card0
|
||||
device pcic0 at card?
|
||||
device pcic1 at card?
|
||||
|
||||
# You may need to reset all pccards after resuming
|
||||
options PCIC_RESUME_RESET # reset after resume
|
||||
|
@ -139,8 +139,8 @@ device apm0 at nexus? disable flags 0x31 # Advanced Power Management
|
||||
|
||||
# PCCARD (PCMCIA) support
|
||||
controller card0
|
||||
device pcic0 at card?
|
||||
device pcic1 at card?
|
||||
controller pcic0 at isa?
|
||||
controller pcic1 at isa?
|
||||
|
||||
# Serial (COM) ports
|
||||
device sio0 at isa? port IO_COM1 flags 0x10 irq 4
|
||||
|
@ -17,7 +17,6 @@ int pccard_alloc_intr __P((u_int imask, ointhand2_t *hand, int unit,
|
||||
u_int *maskp, u_int *pcic_imask));
|
||||
#endif
|
||||
void pccard_remove_driver __P((struct pccard_device *));
|
||||
int pcic_probe __P((void)); /* XXX should be linker set */
|
||||
|
||||
enum beepstate { BEEP_ON, BEEP_OFF };
|
||||
|
||||
|
@ -504,8 +504,6 @@ pccard_alloc_slot(struct slot_ctrl *ctrl)
|
||||
ctrl->maxmem = NUM_MEM_WINDOWS;
|
||||
if (ctrl->maxio > NUM_IO_WINDOWS)
|
||||
ctrl->maxio = NUM_IO_WINDOWS;
|
||||
printf("pcic: pccard bridge %s (%d mem & %d I/O windows)\n",
|
||||
ctrl->name, ctrl->maxmem, ctrl->maxio);
|
||||
}
|
||||
callout_handle_init(&slt->insert_ch);
|
||||
callout_handle_init(&slt->poff_ch);
|
||||
@ -573,7 +571,7 @@ allocate_driver(struct slot *slt, struct dev_desc *desc)
|
||||
struct pccard_device *drv;
|
||||
device_t pccarddev;
|
||||
char devnam[128];
|
||||
int err, irq = 0, s;
|
||||
int err, irq = 0;
|
||||
|
||||
pccarddev = devclass_get_device(pccard_devclass, 0);
|
||||
snprintf(devnam, sizeof(devnam), "pccard-%s", desc->name);
|
||||
|
@ -86,7 +86,7 @@ pccard_add_children(device_t dev, int busno)
|
||||
static int
|
||||
pccard_probe(device_t dev)
|
||||
{
|
||||
device_set_desc(dev, "PC Card bus -- KLUDGE version");
|
||||
device_set_desc(dev, "PC Card bus -- kludge version");
|
||||
return pccard_add_children(dev, device_get_unit(dev));
|
||||
}
|
||||
|
||||
@ -162,171 +162,6 @@ static driver_t pccard_driver = {
|
||||
1, /* no softc */
|
||||
};
|
||||
|
||||
|
||||
DRIVER_MODULE(pccard, nexus, pccard_driver, pccard_devclass, 0, 0);
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
static int
|
||||
pccnbk_probe(device_t dev)
|
||||
{
|
||||
char devnam[128];
|
||||
const char *name;
|
||||
struct pccard_devinfo *devi = device_get_ivars(dev);
|
||||
|
||||
if (devi) {
|
||||
name = device_get_name(dev);
|
||||
snprintf(devnam, sizeof(devnam), "pccard-%s",
|
||||
devi->drv->name);
|
||||
if (!name || strcmp(name, devnam) != 0)
|
||||
return ENXIO;
|
||||
device_set_desc(dev, devi->drv->name);
|
||||
return 0;
|
||||
}
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
static int
|
||||
pccnbk_attach(device_t dev)
|
||||
{
|
||||
struct pccard_devinfo *devi = device_get_ivars(dev);
|
||||
struct pccard_device *drv;
|
||||
struct slot *slt;
|
||||
int err;
|
||||
int s;
|
||||
|
||||
slt = devi->slt;
|
||||
drv = devi->drv;
|
||||
devi->next = slt->devices;
|
||||
slt->devices = devi;
|
||||
s = splhigh();
|
||||
err = drv->enable(devi);
|
||||
splx(s);
|
||||
/*
|
||||
* If the enable functions returns no error, then the
|
||||
* device has been successfully installed. If so, then
|
||||
* attach it to the slot, otherwise free it and return
|
||||
* the error. We assume that when we free the device,
|
||||
* it will also set 'running' to off.
|
||||
*/
|
||||
if (err) {
|
||||
printf("pccard: %s%d Enable failed %d\n", devi->drv->name,
|
||||
devi->isahd.id_unit, err);
|
||||
pccard_remove_device(devi);
|
||||
}
|
||||
return(err);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate resources for this device in the rman system.
|
||||
*/
|
||||
int
|
||||
pccnbk_alloc_resources(device_t dev)
|
||||
{
|
||||
struct pccard_devinfo *devi = device_get_ivars(dev);
|
||||
int rid;
|
||||
u_long start;
|
||||
u_long end;
|
||||
u_long count;
|
||||
|
||||
start = devi->isahd.id_iobase;
|
||||
count = devi->isahd.id_iosize;
|
||||
end = start + count - 1;
|
||||
|
||||
rid = 0;
|
||||
devi->iorv = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
|
||||
SYS_RES_IOPORT, &rid, start, end, count, RF_ACTIVE);
|
||||
if (!devi->iorv) {
|
||||
printf("Cannot allocate ports 0x%lx-0x%lx\n", start, end);
|
||||
return (ENOMEM);
|
||||
}
|
||||
rid = 0;
|
||||
start = end = ffs(devi->isahd.id_irq) - 1;
|
||||
count = 1;
|
||||
devi->irqrv = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
|
||||
SYS_RES_IRQ, &rid, start, end, count, RF_ACTIVE);
|
||||
if (!devi->irqrv) {
|
||||
return (ENOMEM);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
void
|
||||
pccnbk_release_resources(device_t dev)
|
||||
{
|
||||
struct pccard_devinfo *devi = device_get_ivars(dev);
|
||||
u_long start;
|
||||
u_long end;
|
||||
u_long count;
|
||||
|
||||
start = devi->isahd.id_iobase;
|
||||
count = devi->isahd.id_iosize;
|
||||
end = start + count - 1;
|
||||
|
||||
if (devi->iorv) {
|
||||
BUS_RELEASE_RESOURCE(device_get_parent(dev), dev,
|
||||
SYS_RES_IOPORT, 0, devi->iorv);
|
||||
devi->iorv = NULL;
|
||||
}
|
||||
if (devi->irqrv) {
|
||||
BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, SYS_RES_IRQ,
|
||||
0, devi->irqrv);
|
||||
devi->irqrv = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static device_method_t pccnbk_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, pccnbk_probe),
|
||||
DEVMETHOD(device_attach, pccnbk_attach),
|
||||
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_driver_added, bus_generic_driver_added),
|
||||
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
|
||||
DEVMETHOD(bus_release_resource, bus_generic_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),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
void
|
||||
pccnbk_wrap_old_driver(struct pccard_device *drv)
|
||||
{
|
||||
char devnam[128];
|
||||
char *nm;
|
||||
driver_t *driver;
|
||||
|
||||
snprintf(devnam, sizeof(devnam), "pccard-%s", drv->name);
|
||||
driver = malloc(sizeof(driver_t), M_DEVBUF, M_NOWAIT);
|
||||
if (!driver)
|
||||
return;
|
||||
bzero(driver, sizeof(driver_t));
|
||||
/* XXX May create a memory leak for load/unload :-( XXX */
|
||||
nm = malloc(strlen(devnam) + 1, M_DEVBUF, M_NOWAIT);
|
||||
strcpy(nm, devnam);
|
||||
driver->name = nm;
|
||||
driver->methods = pccnbk_methods;
|
||||
driver->softc = sizeof(struct pccard_device);
|
||||
driver->priv = drv;
|
||||
devclass_add_driver(pccard_devclass, driver);
|
||||
drv->driver = driver;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static devclass_t pccnbk_devclass;
|
||||
|
||||
static driver_t pccnbk_driver = {
|
||||
"pccnbk",
|
||||
pccnbk_methods,
|
||||
1, /* no softc */
|
||||
};
|
||||
|
||||
DRIVER_MODULE(pccnbk, pccard, pccnbk_driver, pccnbk_devclass, 0, 0);
|
||||
#endif
|
||||
DRIVER_MODULE(pccard, pcic, pccard_driver, pccard_devclass, 0, 0);
|
||||
DRIVER_MODULE(pccard, pc98pcic, pccard_driver, pccard_devclass, 0, 0);
|
||||
DRIVER_MODULE(pccard, cbb, pccard_driver, pccard_devclass, 0, 0);
|
||||
|
@ -75,11 +75,8 @@ static void pcic_mapirq __P((struct slot *, int));
|
||||
static timeout_t pcictimeout;
|
||||
static struct callout_handle pcictimeout_ch
|
||||
= CALLOUT_HANDLE_INITIALIZER(&pcictimeout_ch);
|
||||
static int pcic_modevent __P((module_t, int, void *));
|
||||
static int pcic_unload __P((void));
|
||||
static int pcic_memory(struct slot *, int);
|
||||
static int pcic_io(struct slot *, int);
|
||||
static u_int build_freelist(u_int);
|
||||
|
||||
/*
|
||||
* Per-slot data table.
|
||||
@ -206,84 +203,6 @@ int unregister_pcic_intr(int intr, ointhand2_t handler)
|
||||
|
||||
#endif /* APIC_IO */
|
||||
|
||||
|
||||
/*
|
||||
* Loadable kernel module interface.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Module handler that processes loads and unloads.
|
||||
* Once the module is loaded, the probe routine
|
||||
* is called to install the slots (if any).
|
||||
*/
|
||||
static int
|
||||
pcic_modevent(module_t mod, int what, void *arg)
|
||||
{
|
||||
int err = 0; /* default = success*/
|
||||
static int pcic_started = 0;
|
||||
|
||||
switch (what) {
|
||||
case MOD_LOAD:
|
||||
|
||||
/*
|
||||
* Call the probe routine to find the slots. If
|
||||
* no slots exist, then don't bother loading the module.
|
||||
* XXX but this is not appropriate as a static module.
|
||||
*/
|
||||
if (pcic_probe())
|
||||
pcic_started = 1;
|
||||
break;
|
||||
|
||||
case MOD_UNLOAD:
|
||||
/*
|
||||
* Attempt to unload the slot driver.
|
||||
*/
|
||||
if (pcic_started) {
|
||||
printf("Unloading PCIC driver\n");
|
||||
err = pcic_unload();
|
||||
pcic_started = 0;
|
||||
}
|
||||
break; /* Success*/
|
||||
|
||||
default: /* we only care about load/unload; ignore shutdown */
|
||||
break;
|
||||
}
|
||||
|
||||
return(err);
|
||||
}
|
||||
|
||||
static moduledata_t pcic_mod = {
|
||||
"pcic",
|
||||
pcic_modevent,
|
||||
0
|
||||
};
|
||||
|
||||
/* After configure() has run.. bring on the new bus system! */
|
||||
DECLARE_MODULE(pcic, pcic_mod, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE);
|
||||
|
||||
/*
|
||||
* pcic_unload - Called when unloading a kernel module.
|
||||
* Disables interrupts and resets PCIC.
|
||||
*/
|
||||
static int
|
||||
pcic_unload()
|
||||
{
|
||||
int slot;
|
||||
struct pcic_slot *sp = pcic_slots;
|
||||
|
||||
untimeout(pcictimeout, 0, pcictimeout_ch);
|
||||
if (pcic_irq) {
|
||||
for (slot = 0; slot < PCIC_MAX_SLOTS; slot++, sp++) {
|
||||
if (sp->slt)
|
||||
sp->putb(sp, PCIC_STAT_INT, 0);
|
||||
}
|
||||
unregister_pcic_intr(pcic_irq, pcicintr);
|
||||
}
|
||||
pccard_remove_controller(&cinfo);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static void
|
||||
pcic_dump_attributes(unsigned char *scratch, int maxlen)
|
||||
@ -308,43 +227,6 @@ pcic_dump_attributes(unsigned char *scratch, int maxlen)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
nullfunc(int arg)
|
||||
{
|
||||
/* empty */
|
||||
}
|
||||
|
||||
static u_int
|
||||
build_freelist(u_int pcic_mask)
|
||||
{
|
||||
int irq;
|
||||
u_int mask, freemask;
|
||||
|
||||
/* No free IRQs (yet). */
|
||||
freemask = 0;
|
||||
|
||||
/* Walk through all of the IRQ's and find any that aren't allocated. */
|
||||
for (irq = 1; irq < ICU_LEN; irq++) {
|
||||
/*
|
||||
* If the PCIC controller can't generate it, don't
|
||||
* bother checking to see if it it's free.
|
||||
*/
|
||||
mask = 1 << irq;
|
||||
if (!(mask & pcic_mask)) continue;
|
||||
|
||||
/* See if the IRQ is free. */
|
||||
if (register_pcic_intr(irq, 0, 0, nullfunc, NULL, irq) == 0) {
|
||||
/* Give it back, but add it to the mask */
|
||||
INTRMASK(freemask, mask);
|
||||
unregister_pcic_intr(irq, nullfunc);
|
||||
}
|
||||
}
|
||||
#ifdef PCIC_DEBUG
|
||||
printf("Freelist of IRQ's <0x%x>\n", freemask);
|
||||
#endif
|
||||
return freemask;
|
||||
}
|
||||
|
||||
/*
|
||||
* entry point from main code to map/unmap memory context.
|
||||
*/
|
||||
@ -571,18 +453,22 @@ printf("Map I/O 0x%x (size 0x%x) on Window %d\n", ip->start, ip->size, win);
|
||||
* of slot 1. Assume it's the only PCIC whose vendor ID is 0x84,
|
||||
* contact Nate Williams <nate@FreeBSD.org> if incorrect.
|
||||
*/
|
||||
int
|
||||
pcic_probe(void)
|
||||
static int
|
||||
pcic_probe(device_t dev)
|
||||
{
|
||||
int slotnum, validslots = 0;
|
||||
u_int free_irqs, desired_irq;
|
||||
struct slot *slt;
|
||||
struct pcic_slot *sp;
|
||||
unsigned char c;
|
||||
int i;
|
||||
static int maybe_vlsi = 0;
|
||||
|
||||
if (device_get_unit(dev) != 0)
|
||||
return ENXIO;
|
||||
|
||||
/* Determine the list of free interrupts */
|
||||
free_irqs = build_freelist(PCIC_INT_MASK_ALLOWED);
|
||||
free_irqs = PCIC_INT_MASK_ALLOWED;
|
||||
|
||||
/*
|
||||
* Initialise controller information structure.
|
||||
@ -749,6 +635,7 @@ pcic_probe(void)
|
||||
cinfo.name = "Unknown!";
|
||||
break;
|
||||
}
|
||||
device_set_desc(dev, cinfo.name);
|
||||
/*
|
||||
* OK it seems we have a PCIC or lookalike.
|
||||
* Allocate a slot and initialise the data structures.
|
||||
@ -765,7 +652,6 @@ pcic_probe(void)
|
||||
* then attempt to get one.
|
||||
*/
|
||||
if (pcic_irq == 0) {
|
||||
|
||||
pcic_imask = soft_imask;
|
||||
|
||||
/* See if the user has requested a specific IRQ */
|
||||
@ -851,7 +737,12 @@ pcic_probe(void)
|
||||
#endif /* PC98 */
|
||||
if (validslots && pcic_irq <= 0)
|
||||
pcictimeout_ch = timeout(pcictimeout, 0, hz/2);
|
||||
return(validslots);
|
||||
if (validslots) {
|
||||
for (i = 0; i < validslots; i++) {
|
||||
device_add_child(dev, NULL, -1, NULL);
|
||||
}
|
||||
}
|
||||
return(validslots ? 0 : ENXIO);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1181,3 +1072,34 @@ pcic_resume(struct slot *slt)
|
||||
setb(sp, PCIC_MISC2, PCIC_LPDM_EN);
|
||||
}
|
||||
}
|
||||
|
||||
static device_method_t pcic_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, pcic_probe),
|
||||
DEVMETHOD(device_attach, bus_generic_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, 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),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
devclass_t pcic_devclass;
|
||||
|
||||
static driver_t pcic_driver = {
|
||||
"pcic",
|
||||
pcic_methods,
|
||||
1, /* no softc */
|
||||
};
|
||||
|
||||
DRIVER_MODULE(pcic, isa, pcic_driver, pcic_devclass, 0, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user