1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-20 15:43:16 +00:00

* Better kld support in pccbb/cardbus

- pccbb no longer needs to remember whether a card is inserted.
  - pccbb reissues insertion on load of cardbus/pccard modules.
  - got rid of unnecessary delays in power functions.
  - Cardbus children are no longer deleted if probe/attach fails.
  - non-attached child devices are reprobed at driver_added.

* CARD interface to read CIS
  - added card_cis_read/card_cis_free interface to read arbitrary CIS
    data.  This currently is only implemented in cardbus.

* pccard begins to work
  - pccard can now use higher memory space (and uses it by default).
  - set_memory_offset interface changed.
  - fixed ccr access, which was broken at multiple locations.
  - implement an interrupt handler - pccard can now share interrupts.
  - resource alloc/release/activate/deactivate functions gutted: some
    resources are allocated by the bridge before the child device is
    probed or attached.  Thus the resource "belongs" to the bridge, and
    the pccard_*_resource functions need to fudge the owner/rid.
  - changed some error conditions to panics to speed debugging.

* Mutex fix - Giant is entered at the beginning of thread
This commit is contained in:
Jonathan Chen 2001-01-06 18:04:55 +00:00
parent 41ed17bfec
commit 0c95c70577
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=70715
8 changed files with 597 additions and 207 deletions

View File

@ -190,8 +190,9 @@ cardbus_attach_card(device_t dev)
static int curr_bus_number = 2; /* XXX EVILE BAD (see below) */
int bus, slot, func;
POWER_ENABLE_SOCKET(bdev, dev);
cardbus_detach_card(dev, DETACH_NOWARN); /* detach existing cards */
POWER_ENABLE_SOCKET(bdev, dev);
bus = pcib_get_bus(dev);
if (bus == 0) {
/*
@ -205,7 +206,6 @@ cardbus_attach_card(device_t dev)
pci_write_config (bdev, PCIR_SUBBUS_2, curr_bus_number+2, 1);
curr_bus_number += 3;
}
for (slot = 0; slot <= CARDBUS_SLOTMAX; slot++) {
int cardbusfunchigh = 0;
for (func = 0; func <= cardbusfunchigh; func++) {
@ -230,8 +230,6 @@ cardbus_attach_card(device_t dev)
if (device_probe_and_attach(dinfo->cfg.dev) != 0) {
cardbus_release_all_resources(dinfo->cfg.dev,
&dinfo->resources);
device_delete_child(dev, dinfo->cfg.dev);
cardbus_freecfg(dinfo);
} else
cardattached++;
}
@ -253,20 +251,30 @@ cardbus_detach_card(device_t dev, int flags)
device_get_children(dev, &devlist, &numdevs);
if (numdevs == 0) {
DEVPRINTF((dev, "Detaching card: no cards to detach!\n"));
POWER_DISABLE_SOCKET(device_get_parent(dev), dev);
if (!(flags & DETACH_NOWARN)) {
DEVPRINTF((dev, "Detaching card: no cards to detach!\n"));
POWER_DISABLE_SOCKET(device_get_parent(dev), dev);
}
return ENOENT;
}
for (tmp = 0; tmp < numdevs; tmp++) {
struct cardbus_devinfo *dinfo = device_get_ivars(devlist[tmp]);
if (device_detach(dinfo->cfg.dev) == 0 || flags & DETACH_FORCE){
cardbus_release_all_resources(dinfo->cfg.dev,
&dinfo->resources);
int status = device_get_state(devlist[tmp]);
if (status == DS_ATTACHED || status == DS_BUSY) {
if (device_detach(dinfo->cfg.dev) == 0 ||
flags & DETACH_FORCE){
cardbus_release_all_resources(dinfo->cfg.dev,
&dinfo->resources);
device_delete_child(dev, devlist[tmp]);
} else {
err++;
}
cardbus_freecfg(dinfo);
} else {
device_delete_child(dev, devlist[tmp]);
} else
err++;
cardbus_freecfg(dinfo);
}
}
if (err == 0)
POWER_DISABLE_SOCKET(device_get_parent(dev), dev);
@ -276,19 +284,39 @@ cardbus_detach_card(device_t dev, int flags)
static void
cardbus_driver_added(device_t dev, driver_t *driver)
{
/*
* For this to work, we should:
* 1) power up the slot if it isn't powered.
* (Is this necessary? Can we assume _probe() doesn't need power?)
* 2) probe (we should probe even though we already have child?)
* 3) power up if we haven't done so and probe succeeds
* 4) attach if probe succeeds.
* 5) power down if probe or attach failed, and the slot was powered
* down to begin with.
*/
printf("I see you added a driver that could be a child of cardbus...\n");
printf("If this is for a cardbus card, please remove and reinsert the card.\n");
printf("(there is no current support for adding a driver like this)\n");
int numdevs;
device_t *devlist;
device_t bdev = device_get_parent(dev);
int tmp, cardattached;
device_get_children(dev, &devlist, &numdevs);
cardattached = 0;
for (tmp = 0; tmp < numdevs; tmp++) {
if (device_get_state(devlist[tmp]) != DS_NOTPRESENT)
cardattached++;
}
if (cardattached == 0)
POWER_ENABLE_SOCKET(bdev, dev);
DEVICE_IDENTIFY(driver, dev);
for (tmp = 0; tmp < numdevs; tmp++) {
if (device_get_state(devlist[tmp]) == DS_NOTPRESENT){
struct cardbus_devinfo *dinfo;
dinfo = device_get_ivars(devlist[tmp]);
resource_list_init(&dinfo->resources);
cardbus_add_resources(dinfo->cfg.dev, &dinfo->cfg);
cardbus_do_cis(dev, dinfo->cfg.dev);
if (device_probe_and_attach(dinfo->cfg.dev) != 0) {
cardbus_release_all_resources(dinfo->cfg.dev,
&dinfo->resources);
} else
cardattached++;
}
}
if (cardattached == 0)
POWER_DISABLE_SOCKET(bdev, dev);
}
/************************************************************************/
@ -344,7 +372,7 @@ cardbus_read_device(device_t pcib, int b, int s, int f)
cfg->intline = airq;
}
} else {
/*
/*
* PCI interrupts might be redirected to the
* ISA bus according to some MP tables. Use the
* same methods as used by the ISA devices
@ -655,7 +683,7 @@ cardbus_alloc_resource(device_t self, device_t child, int type,
rle = resource_list_find(rl, type, *rid);
if (rle) {
if (flags & RF_ACTIVE) {
if (bus_activate_resource(child, type, *rid,
if (bus_activate_resource(child, rle->type, *rid,
rle->res)) {
return NULL;
}
@ -930,6 +958,8 @@ static device_method_t cardbus_methods[] = {
/* Card Interface */
DEVMETHOD(card_attach_card, cardbus_attach_card),
DEVMETHOD(card_detach_card, cardbus_detach_card),
DEVMETHOD(card_cis_read, cardbus_cis_read),
DEVMETHOD(card_cis_free, cardbus_cis_free),
/* Cardbus/PCI interface */
DEVMETHOD(pci_read_config, cardbus_read_config_method),
@ -947,4 +977,6 @@ static driver_t cardbus_driver = {
static devclass_t cardbus_devclass;
DRIVER_MODULE(cardbus, pccbb, cardbus_driver, cardbus_devclass, 0, 0);
/*
MODULE_DEPEND(cardbus, pccbb, 1, 1, 1);
*/

View File

@ -37,6 +37,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/bus.h>
#include <machine/bus.h>
@ -48,6 +49,8 @@
#include <dev/cardbus/cardbusreg.h>
#include <dev/cardbus/cardbus_cis.h>
#include "card_if.h"
#if defined CARDBUS_DEBUG
#define STATIC
#define DPRINTF(a) printf a
@ -63,7 +66,7 @@ static const char rcsid[] =
"$FreeBSD$";
#endif
struct tupleinfo;
struct tuple_callbacks;
static int cardbus_read_tuple_conf(device_t dev, device_t child,
u_int32_t *start, u_int32_t *off,
@ -78,13 +81,19 @@ static int cardbus_read_tuple(device_t dev, device_t child, u_int32_t *start,
u_int32_t *off, int *tupleid, int *len,
u_int8_t *tupledata);
static int decode_tuple(device_t dev, device_t child, int tupleid, int len,
u_int8_t *tupledata, u_int32_t *start, u_int32_t *off);
u_int8_t *tupledata, u_int32_t *start, u_int32_t *off,
struct tuple_callbacks *callbacks);
static int cardbus_parse_cis(device_t dev, device_t child,
struct tuple_callbacks *callbacks);
#define DECODE_PROTOTYPE(NAME) static int decode_tuple_ ## NAME \
#define DECODE_PARAMS \
(device_t dev, device_t child, int id, int len, \
u_int8_t *tupledata, u_int32_t *start, u_int32_t *off, \
struct tupleinfo *info)
struct tuple_callbacks *info)
#define DECODE_PROTOTYPE(NAME) static int decode_tuple_ ## NAME DECODE_PARAMS
DECODE_PROTOTYPE(generic);
DECODE_PROTOTYPE(nothing);
DECODE_PROTOTYPE(copy);
DECODE_PROTOTYPE(bar);
DECODE_PROTOTYPE(linktarget);
DECODE_PROTOTYPE(vers_1);
@ -94,54 +103,12 @@ DECODE_PROTOTYPE(funce);
DECODE_PROTOTYPE(end);
DECODE_PROTOTYPE(unhandled);
static struct tupleinfo {
u_int8_t id;
struct tuple_callbacks {
int id;
char* name;
int (*func)(device_t dev, device_t child, int id, int len,
u_int8_t *tupledata, u_int32_t *start, u_int32_t *off,
struct tupleinfo *info);
} tupleinfo[] = {
#define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC }
MAKETUPLE(NULL, generic),
MAKETUPLE(DEVICE, generic),
MAKETUPLE(LONG_LINK_CB, unhandled),
MAKETUPLE(INDIRECT, unhandled),
MAKETUPLE(CONFIG_CB, generic),
MAKETUPLE(CFTABLE_ENTRY_CB, generic),
MAKETUPLE(LONGLINK_MFC, unhandled),
MAKETUPLE(BAR, bar),
MAKETUPLE(PWR_MGMNT, generic),
MAKETUPLE(EXTDEVICE, generic),
MAKETUPLE(CHECKSUM, generic),
MAKETUPLE(LONGLINK_A, unhandled),
MAKETUPLE(LONGLINK_C, unhandled),
MAKETUPLE(LINKTARGET, linktarget),
MAKETUPLE(NO_LINK, generic),
MAKETUPLE(VERS_1, vers_1),
MAKETUPLE(ALTSTR, generic),
MAKETUPLE(DEVICE_A, generic),
MAKETUPLE(JEDEC_C, generic),
MAKETUPLE(JEDEC_A, generic),
MAKETUPLE(CONFIG, generic),
MAKETUPLE(CFTABLE_ENTRY, generic),
MAKETUPLE(DEVICE_OC, generic),
MAKETUPLE(DEVICE_OA, generic),
MAKETUPLE(DEVICE_GEO, generic),
MAKETUPLE(DEVICE_GEO_A, generic),
MAKETUPLE(MANFID, manfid),
MAKETUPLE(FUNCID, funcid),
MAKETUPLE(FUNCE, funce),
MAKETUPLE(SWIL, generic),
MAKETUPLE(VERS_2, generic),
MAKETUPLE(FORMAT, generic),
MAKETUPLE(GEOMETRY, generic),
MAKETUPLE(BYTEORDER, generic),
MAKETUPLE(DATE, generic),
MAKETUPLE(BATTERY, generic),
MAKETUPLE(ORG, generic),
MAKETUPLE(END, end),
#undef MAKETUPLE
int (*func) DECODE_PARAMS;
};
#define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC }
static char* funcnames[] = {
"Multi-Functioned",
@ -156,6 +123,9 @@ static char* funcnames[] = {
"Security"
};
static struct cis_tupleinfo* cisread_buf;
static int ncisread_buf;
DECODE_PROTOTYPE(generic)
{
#ifdef CARDBUS_DEBUG
@ -176,6 +146,32 @@ DECODE_PROTOTYPE(generic)
return 0;
}
DECODE_PROTOTYPE(nothing)
{
return 0;
}
DECODE_PROTOTYPE(copy)
{
struct cis_tupleinfo* tmpbuf;
tmpbuf = malloc(sizeof(struct cis_tupleinfo)*(ncisread_buf+1),
M_DEVBUF, M_WAITOK);
if (ncisread_buf > 0) {
memcpy(tmpbuf, cisread_buf,
sizeof(struct cis_tupleinfo)*ncisread_buf);
free(cisread_buf, M_DEVBUF);
}
cisread_buf = tmpbuf;
cisread_buf[ncisread_buf].id = id;
cisread_buf[ncisread_buf].len = len;
cisread_buf[ncisread_buf].data = malloc(len, M_DEVBUF, M_WAITOK);
memcpy (cisread_buf[ncisread_buf].data, tupledata, len);
ncisread_buf++;
return 0;
}
DECODE_PROTOTYPE(linktarget)
{
#ifdef CARDBUS_DEBUG
@ -277,7 +273,7 @@ DECODE_PROTOTYPE(bar)
if (bar < 0 || bar > 5 || (type == SYS_RES_IOPORT && bar == 5)) {
device_printf(dev, "Invalid BAR number: %02x(%02x)\n",
reg, bar);
return EINVAL;
return 0;
}
bar = CARDBUS_BASE0_REG + bar * 4;
DEVPRINTF((dev, "Opening BAR: type=%s, bar=%02x, len=%04x\n",
@ -299,6 +295,7 @@ DECODE_PROTOTYPE(unhandled)
DECODE_PROTOTYPE(end)
{
printf("CIS reading done\n");
return 0;
}
@ -451,27 +448,29 @@ cardbus_read_tuple(device_t dev, device_t child, u_int32_t *start,
static int
decode_tuple(device_t dev, device_t child, int tupleid, int len,
u_int8_t *tupledata, u_int32_t *start, u_int32_t *off)
u_int8_t *tupledata, u_int32_t *start, u_int32_t *off,
struct tuple_callbacks *callbacks)
{
int i;
int numtupleids = sizeof(tupleinfo)/sizeof(tupleinfo[0]);
for (i = 0; i < numtupleids; i++) {
if (tupleid == tupleinfo[i].id)
return tupleinfo[i].func(dev, child, tupleid, len,
for (i = 0; callbacks[i].id != CISTPL_GENERIC; i++) {
if (tupleid == callbacks[i].id)
return callbacks[i].func(dev, child, tupleid, len,
tupledata, start, off,
&tupleinfo[i]);
&callbacks[i]);
}
if (tupleid < CISTPL_CUSTOMSTART) {
device_printf(dev, "Undefined tuple encountered, CIS parsing terminated\n");
return EINVAL;
}
return decode_tuple_generic(dev, child, tupleid, len, tupledata,
start, off, NULL);
return callbacks[i].func(dev, child, tupleid, len,
tupledata, start, off,
NULL);
}
int
cardbus_do_cis(device_t dev, device_t child)
static int
cardbus_parse_cis(device_t dev, device_t child,
struct tuple_callbacks *callbacks)
{
u_int8_t tupledata[MAXTUPLESIZE];
int tupleid;
@ -493,10 +492,128 @@ cardbus_do_cis(device_t dev, device_t child)
return EINVAL;
}
expect_linktarget = decode_tuple(dev, child, tupleid, len,
tupledata, &start, &off);
tupledata, &start, &off,
callbacks);
if (expect_linktarget != 0)
return expect_linktarget;
} while (tupleid != CISTPL_END);
return 0;
}
int
cardbus_cis_read(device_t dev, device_t child, u_int8_t id,
struct cis_tupleinfo** buff, int* nret)
{
struct tuple_callbacks cisread_callbacks[] = {
MAKETUPLE(NULL, nothing),
/* first entry will be overwritten */
MAKETUPLE(NULL, nothing),
MAKETUPLE(DEVICE, nothing),
MAKETUPLE(LONG_LINK_CB, unhandled),
MAKETUPLE(INDIRECT, unhandled),
MAKETUPLE(CONFIG_CB, nothing),
MAKETUPLE(CFTABLE_ENTRY_CB, nothing),
MAKETUPLE(LONGLINK_MFC, unhandled),
MAKETUPLE(BAR, nothing),
MAKETUPLE(PWR_MGMNT, nothing),
MAKETUPLE(EXTDEVICE, nothing),
MAKETUPLE(CHECKSUM, nothing),
MAKETUPLE(LONGLINK_A, unhandled),
MAKETUPLE(LONGLINK_C, unhandled),
MAKETUPLE(LINKTARGET, nothing),
MAKETUPLE(NO_LINK, nothing),
MAKETUPLE(VERS_1, nothing),
MAKETUPLE(ALTSTR, nothing),
MAKETUPLE(DEVICE_A, nothing),
MAKETUPLE(JEDEC_C, nothing),
MAKETUPLE(JEDEC_A, nothing),
MAKETUPLE(CONFIG, nothing),
MAKETUPLE(CFTABLE_ENTRY, nothing),
MAKETUPLE(DEVICE_OC, nothing),
MAKETUPLE(DEVICE_OA, nothing),
MAKETUPLE(DEVICE_GEO, nothing),
MAKETUPLE(DEVICE_GEO_A, nothing),
MAKETUPLE(MANFID, nothing),
MAKETUPLE(FUNCID, nothing),
MAKETUPLE(FUNCE, nothing),
MAKETUPLE(SWIL, nothing),
MAKETUPLE(VERS_2, nothing),
MAKETUPLE(FORMAT, nothing),
MAKETUPLE(GEOMETRY, nothing),
MAKETUPLE(BYTEORDER, nothing),
MAKETUPLE(DATE, nothing),
MAKETUPLE(BATTERY, nothing),
MAKETUPLE(ORG, nothing),
MAKETUPLE(END, end),
MAKETUPLE(GENERIC, nothing),
};
int ret;
cisread_callbacks[0].id = id;
cisread_callbacks[0].name = "COPY";
cisread_callbacks[0].func = decode_tuple_copy;
ncisread_buf = 0;
cisread_buf = NULL;
ret = cardbus_parse_cis(dev, child, cisread_callbacks);
*buff = cisread_buf;
*nret = ncisread_buf;
return ret;
}
void
cardbus_cis_free(device_t dev, struct cis_tupleinfo *buff, int* nret)
{
int i;
for (i = 0; i < nret; i++)
free(buff[i].data, M_DEVBUF);
if (nret > 0)
free(buff, M_DEVBUF);
}
int
cardbus_do_cis(device_t dev, device_t child)
{
struct tuple_callbacks init_callbacks[] = {
MAKETUPLE(NULL, generic),
MAKETUPLE(DEVICE, generic),
MAKETUPLE(LONG_LINK_CB, unhandled),
MAKETUPLE(INDIRECT, unhandled),
MAKETUPLE(CONFIG_CB, generic),
MAKETUPLE(CFTABLE_ENTRY_CB, generic),
MAKETUPLE(LONGLINK_MFC, unhandled),
MAKETUPLE(BAR, bar),
MAKETUPLE(PWR_MGMNT, generic),
MAKETUPLE(EXTDEVICE, generic),
MAKETUPLE(CHECKSUM, generic),
MAKETUPLE(LONGLINK_A, unhandled),
MAKETUPLE(LONGLINK_C, unhandled),
MAKETUPLE(LINKTARGET, linktarget),
MAKETUPLE(NO_LINK, generic),
MAKETUPLE(VERS_1, vers_1),
MAKETUPLE(ALTSTR, generic),
MAKETUPLE(DEVICE_A, generic),
MAKETUPLE(JEDEC_C, generic),
MAKETUPLE(JEDEC_A, generic),
MAKETUPLE(CONFIG, generic),
MAKETUPLE(CFTABLE_ENTRY, generic),
MAKETUPLE(DEVICE_OC, generic),
MAKETUPLE(DEVICE_OA, generic),
MAKETUPLE(DEVICE_GEO, generic),
MAKETUPLE(DEVICE_GEO_A, generic),
MAKETUPLE(MANFID, manfid),
MAKETUPLE(FUNCID, funcid),
MAKETUPLE(FUNCE, funce),
MAKETUPLE(SWIL, generic),
MAKETUPLE(VERS_2, generic),
MAKETUPLE(FORMAT, generic),
MAKETUPLE(GEOMETRY, generic),
MAKETUPLE(BYTEORDER, generic),
MAKETUPLE(DATE, generic),
MAKETUPLE(BATTERY, generic),
MAKETUPLE(ORG, generic),
MAKETUPLE(END, end),
MAKETUPLE(GENERIC, generic),
};
return cardbus_parse_cis(dev, child, init_callbacks);
}

View File

@ -32,7 +32,12 @@
* Cardbus CIS definitions
*/
struct cis_tupleinfo;
int cardbus_do_cis(device_t dev, device_t child);
int cardbus_cis_read(device_t dev, device_t child, u_int8_t id,
struct cis_tupleinfo** buff, int* nret);
void cardbus_cis_free(device_t dev, struct cis_tupleinfo *buff, int* nret);
#define MAXTUPLESIZE 0x400
@ -78,6 +83,8 @@ int cardbus_do_cis(device_t dev, device_t child);
#define CISTPL_CUSTOMSTART 0x80
#define CISTPL_END 0xFF
#define CISTPL_GENERIC -1 /* catchall */
/* BAR */
#define TPL_BAR_REG_ASI_MASK 0x07
#define TPL_BAR_REG_AS 0x10

View File

@ -63,7 +63,8 @@ METHOD int set_memory_offset {
device_t dev;
device_t child;
int rid;
u_int32_t offset;
u_int32_t cardaddr;
u_int32_t *offsetp;
}
METHOD int get_memory_offset {
@ -90,6 +91,7 @@ METHOD int detach_card {
HEADER {
#define DETACH_FORCE 0x01
#define DETACH_NOWARN 0x02
}
#
@ -163,3 +165,53 @@ METHOD int compat_attach {
METHOD int compat_match {
device_t dev;
}
#
# Method for devices to ask its CIS-enabled parent bus for CIS info.
# Device driver requests all tuples if type 'id', the routine places
# 'nret' number of tuples in 'buff'. Returns 0 if all tuples processed,
# or an error code if processing was aborted.
# Users of this method will be responsible for freeing the memory allocated
# by calling the cis_free method.
#
HEADER {
struct cis_tupleinfo {
u_int8_t id;
int len;
char* data;
};
};
CODE {
static int
null_cis_read(device_t dev, device_t child, u_int8_t id,
struct cis_tupleinfo **buff, int* nret)
{
*nret = 0;
*buff = NULL;
return ENXIO;
}
static void
null_cis_free(device_t dev, struct cis_tupleinfo *buff, int* nret)
{
return;
}
};
METHOD int cis_read {
device_t dev;
device_t child;
u_int8_t id;
struct cis_tupleinfo **buff;
int* nret;
} DEFAULT null_cis_read;
METHOD int cis_free {
device_t dev;
struct cis_tupleinfo *buff;
int nret;
} DEFAULT null_cis_free;

View File

@ -103,6 +103,7 @@ pccard_attach_card(device_t dev)
device_t child;
int attached;
sc->intr_handler_count = 0;
/*
* this is here so that when socket_enable calls gettype, trt happens
*/
@ -122,10 +123,14 @@ pccard_attach_card(device_t dev)
* the cis.
*/
if (sc->card.error)
if (sc->card.error) {
device_printf (dev, "CARD ERROR!\n");
return (1);
if (STAILQ_EMPTY(&sc->card.pf_head))
}
if (STAILQ_EMPTY(&sc->card.pf_head)) {
device_printf (dev, "Card has no functions!\n");
return (1);
}
if (1)
pccard_print_cis(dev);
@ -228,7 +233,7 @@ pccard_product_lookup(device_t dev, const struct pccard_product *tab,
#ifdef DIAGNOSTIC
if (sizeof *ent > ent_size)
panic("pccard_product_lookup: bogus ent_size %ld",
panic("pccard_product_lookup: bogus ent_size %ld",
(long) ent_size);
#endif
if (pccard_get_vendor(dev, &vendor))
@ -241,7 +246,7 @@ pccard_product_lookup(device_t dev, const struct pccard_product *tab,
return (NULL);
if (pccard_get_product_str(dev, &prodstr))
return (NULL);
for (ent = tab; ent->pp_name != NULL;
for (ent = tab; ent->pp_name != NULL;
ent = (const struct pccard_product *)
((const char *) ent + ent_size)) {
matches = 1;
@ -253,10 +258,10 @@ pccard_product_lookup(device_t dev, const struct pccard_product *tab,
matches = 0;
if (matches && fcn != ent->pp_expfunc)
matches = 0;
if (matches && ent->pp_vendor_str &&
if (matches && ent->pp_vendor_str &&
strcmp(ent->pp_vendor_str, vendorstr) != 0)
matches = 0;
if (matches && ent->pp_product_str &&
if (matches && ent->pp_product_str &&
strcmp(ent->pp_product_str, prodstr) != 0)
matches = 0;
if (matchfn != NULL)
@ -267,7 +272,7 @@ pccard_product_lookup(device_t dev, const struct pccard_product *tab,
return (NULL);
}
static int
static int
pccard_card_gettype(device_t dev, int *type)
{
struct pccard_softc *sc = PCCARD_SOFTC(dev);
@ -293,7 +298,7 @@ pccard_card_gettype(device_t dev, int *type)
* disabled.
*/
void
pccard_function_init(struct pccard_function *pf)
pccard_function_init(struct pccard_function *pf)
{
struct pccard_config_entry *cfe;
int i;
@ -304,9 +309,10 @@ pccard_function_init(struct pccard_function *pf)
int start;
int end;
if (pf->pf_flags & PFF_ENABLED)
panic("pccard_function_init: function is enabled");
if (pf->pf_flags & PFF_ENABLED) {
printf("pccard_function_init: function is enabled");
return;
}
bus = device_get_parent(pf->dev);
/* Remember which configuration entry we are using. */
for (cfe = STAILQ_FIRST(&pf->cfe_head); cfe != NULL;
@ -323,13 +329,17 @@ pccard_function_init(struct pccard_function *pf)
cfe->iorid[i] = i;
r = cfe->iores[i] = bus_alloc_resource(bus,
SYS_RES_IOPORT, &cfe->iorid[i], start, end,
cfe->iospace[i].length,
cfe->iospace[i].length,
rman_make_alignment_flags(cfe->iospace[i].length));
if (cfe->iores[i] == 0)
goto not_this_one;
resource_list_add(rl, SYS_RES_IOPORT, cfe->iorid[i],
rman_get_start(r), rman_get_end(r),
cfe->iospace[i].length);
{
struct resource_list_entry *rle = resource_list_find(rl, SYS_RES_IOPORT, cfe->iorid[i]);
rle->res = r;
}
}
if (cfe->num_memspace > 0) {
goto not_this_one;
@ -342,6 +352,10 @@ pccard_function_init(struct pccard_function *pf)
goto not_this_one;
resource_list_add(rl, SYS_RES_IRQ, cfe->irqrid,
rman_get_start(r), rman_get_end(r), 1);
{
struct resource_list_entry *rle = resource_list_find(rl, SYS_RES_IRQ, cfe->irqrid);
rle->res = r;
}
}
/* XXX Don't know how to deal with maxtwins */
/* If we get to here, we've allocated all we need */
@ -357,7 +371,7 @@ pccard_function_init(struct pccard_function *pf)
for (i = 0; i < cfe->num_iospace; i++) {
resource_list_delete(rl, SYS_RES_IOPORT, i);
if (cfe->iores[i])
bus_release_resource(bus, SYS_RES_IOPORT,
bus_release_resource(bus, SYS_RES_IOPORT,
cfe->iorid[i], cfe->iores[i]);
cfe->iores[i] = NULL;
}
@ -377,7 +391,6 @@ pccard_function_enable(struct pccard_function *pf)
struct pccard_function *tmp;
int reg;
device_t dev = pf->sc->dev;
if (pf->cfe == NULL) {
DEVPRVERBOSE((dev, "No config entry could be allocated.\n"));
return ENOMEM;
@ -416,29 +429,27 @@ pccard_function_enable(struct pccard_function *pf)
* pf->pf_ccr_offset = (tmp->pf_ccr_offset -
* tmp->ccr_base) + pf->ccr_base;
*/
pf->pf_ccr_offset =
/* pf->pf_ccr_offset =
(tmp->pf_ccr_offset + pf->ccr_base) -
tmp->ccr_base;
tmp->ccr_base; */
pf->pf_ccr_window = tmp->pf_ccr_window;
break;
}
}
if (tmp == NULL) {
pf->ccr_rid = 0;
pf->ccr_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
&pf->ccr_rid, 0xa0000, 0xdffff, 1 << 10, RF_ACTIVE);
if (!pf->ccr_res) {
DEVPRINTF((dev, "ccr_res == 0\n"));
&pf->ccr_rid, 0, ~0, 1 << 10, RF_ACTIVE);
if (!pf->ccr_res)
goto bad;
}
DEVPRINTF((dev, "ccr_res == %lx-%lx, base=%lx\n", rman_get_start(pf->ccr_res), rman_get_end(pf->ccr_res), pf->ccr_base));
CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY,
pf->ccr_rid, PCCARD_A_MEM_ATTR);
CARD_SET_MEMORY_OFFSET(device_get_parent(dev), dev,
pf->ccr_rid, (pf->ccr_rid >> 10) << 10);
CARD_SET_MEMORY_OFFSET(device_get_parent(dev), dev,
pf->ccr_rid, pf->ccr_base,
&pf->pf_ccr_offset);
pf->pf_ccrt = rman_get_bustag(pf->ccr_res);
pf->pf_ccrh = rman_get_bushandle(pf->ccr_res);
pf->pf_ccr_offset = rman_get_start(pf->ccr_res);
pf->pf_ccr_realsize = 1;
}
@ -447,12 +458,12 @@ pccard_function_enable(struct pccard_function *pf)
if (pccard_mfc(pf->sc)) {
reg |= (PCCARD_CCR_OPTION_FUNC_ENABLE |
PCCARD_CCR_OPTION_ADDR_DECODE);
/*
/*
* XXX Need to enable PCCARD_CCR_OPTION_IRQ_ENABLE if
* XXX we have an interrupt handler, but we don't know that
* XXX at this point.
*/
reg |= PCCARD_CCR_OPTION_IREQ_ENABLE;
/* reg |= PCCARD_CCR_OPTION_IREQ_ENABLE;*/
}
pccard_ccr_write(pf, PCCARD_CCR_OPTION, reg);
@ -487,17 +498,17 @@ pccard_function_enable(struct pccard_function *pf)
#ifdef PCCARDDEBUG
if (pccard_debug) {
STAILQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
device_printf(tmp->sc->dev,
device_printf(tmp->sc->dev,
"function %d CCR at %d offset %x: "
"%x %x %x %x, %x %x %x %x, %x\n",
tmp->number, tmp->pf_ccr_window,
tmp->number, tmp->pf_ccr_window,
tmp->pf_ccr_offset,
pccard_ccr_read(tmp, 0x00),
pccard_ccr_read(tmp, 0x02),
pccard_ccr_read(tmp, 0x04),
pccard_ccr_read(tmp, 0x06),
pccard_ccr_read(tmp, 0x0A),
pccard_ccr_read(tmp, 0x0C),
pccard_ccr_read(tmp, 0x0C),
pccard_ccr_read(tmp, 0x0E),
pccard_ccr_read(tmp, 0x10),
pccard_ccr_read(tmp, 0x12));
@ -536,6 +547,27 @@ pccard_function_disable(struct pccard_function *pf)
return;
}
if (pf->intr_handler != NULL) {
pf->intr_handler = NULL;
pf->intr_handler_arg = NULL;
pf->intr_handler_cookie = NULL;
pccard_ccr_write(pf, PCCARD_CCR_OPTION,
pccard_ccr_read(pf, PCCARD_CCR_OPTION) &
~PCCARD_CCR_OPTION_IREQ_ENABLE);
if (pf->sc->intr_handler_count == 1) {
struct pccard_ivar *ivar = PCCARD_IVAR(pf->dev);
struct resource_list_entry *rle = NULL;
pf->sc->intr_handler_count--;
rle = resource_list_find(&ivar->resources, SYS_RES_IRQ, 0);
if (rle == NULL)
panic("No IRQ for pccard?");
bus_teardown_intr(dev, rle->res, &pf->sc->intr_handler_count);
}
}
/*
* it's possible for different functions' CCRs to be in the same
* underlying page. Check for that. Note we mark us as disabled
@ -553,7 +585,7 @@ pccard_function_disable(struct pccard_function *pf)
/* Not used by anyone else; unmap the CCR. */
if (tmp == NULL) {
bus_release_resource(dev, SYS_RES_MEMORY, pf->ccr_rid,
bus_release_resource(dev, SYS_RES_MEMORY, pf->ccr_rid,
pf->ccr_res);
pf->ccr_res = NULL;
}
@ -605,7 +637,7 @@ pccard_io_map(struct pccard_function *pf, int width, bus_addr_t offset,
;
iosize--;
pccard_ccr_write(pf, PCCARD_CCR_IOBASE0,
pccard_ccr_write(pf, PCCARD_CCR_IOBASE0,
pf->pf_mfc_iobase & 0xff);
pccard_ccr_write(pf, PCCARD_CCR_IOBASE1,
(pf->pf_mfc_iobase >> 8) & 0xff);
@ -728,7 +760,7 @@ pccard_print_child(device_t dev, device_t child)
PCCARD_NMEM, "%#lx");
pccard_print_resources(rl, "irq", SYS_RES_IRQ, PCCARD_NIRQ,
"%ld");
pccard_print_resources(rl, "drq", SYS_RES_DRQ, PCCARD_NDRQ,
pccard_print_resources(rl, "drq", SYS_RES_DRQ, PCCARD_NDRQ,
"%ld");
retval += printf(" function %d config %d", devi->fcn->number,
devi->fcn->cfe->number);
@ -776,7 +808,7 @@ pccard_get_resource(device_t dev, device_t child, int type, int rid,
rle = resource_list_find(rl, type, rid);
if (!rle)
return ENOENT;
if (startp)
*startp = rle->start;
if (countp)
@ -803,10 +835,11 @@ pccard_set_res_flags(device_t dev, device_t child, int type, int rid,
static int
pccard_set_memory_offset(device_t dev, device_t child, int rid,
u_int32_t offset)
u_int32_t offset, u_int32_t *offsetp)
{
return CARD_SET_MEMORY_OFFSET(device_get_parent(dev), child, rid,
offset);
offset, offsetp);
}
static int
@ -866,33 +899,21 @@ static struct resource *
pccard_alloc_resource(device_t dev, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
struct pccard_ivar *ivar;
struct pccard_function *pf;
struct resource *r = 0;
struct resource_list_entry *rle = NULL;
/* XXX: This is an ugly way to fudge the resources. */
if (device_get_parent(child) == dev) {
ivar = PCCARD_IVAR(child);
pf = ivar->fcn;
switch (type) {
case SYS_RES_IRQ:
if (*rid > 0)
return NULL;
r = pf->cfe->irqres;
break;
case SYS_RES_IOPORT:
if (*rid > 3) /* XXX */
return NULL;
r = pf->cfe->iores[*rid];
break;
default:
break;
}
struct pccard_ivar *devi = PCCARD_IVAR(child);
struct resource_list *rl = &devi->resources;
rle = resource_list_find(rl, type, *rid);
}
if (r != NULL) {
if (flags & RF_ACTIVE)
bus_generic_activate_resource(dev, child, type,
*rid, r);
return (r);
if (rle != NULL) {
if (flags & RF_ACTIVE)
bus_activate_resource(dev, type, rle->rid, rle->res);
return (rle->res);
}
return (bus_generic_alloc_resource(dev, child, type, rid, start,
end, count, flags));
@ -902,6 +923,19 @@ static int
pccard_release_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
{
struct resource_list_entry *rle = NULL;
if (device_get_parent(child) == dev) {
struct pccard_ivar *devi = PCCARD_IVAR(child);
struct resource_list *rl = &devi->resources;
rle = resource_list_find(rl, type, rid);
}
if (rle != NULL) {
return bus_release_resource(dev, type, rle->rid, rle->res);
}
return bus_generic_release_resource(dev, child, type, rid, r);
}
@ -910,6 +944,19 @@ pccard_activate_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
{
/* XXX need to write to the COR to activate this for mf cards */
struct resource_list_entry *rle = NULL;
if (device_get_parent(child) == dev) {
struct pccard_ivar *devi = PCCARD_IVAR(child);
struct resource_list *rl = &devi->resources;
rle = resource_list_find(rl, type, rid);
}
if (rle != NULL) {
return (bus_activate_resource(dev, type, rle->rid, rle->res));
}
return (bus_generic_activate_resource(dev, child, type, rid, r));
}
@ -918,6 +965,19 @@ pccard_deactivate_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
{
/* XXX need to write to the COR to deactivate this for mf cards */
struct resource_list_entry *rle = NULL;
if (device_get_parent(child) == dev) {
struct pccard_ivar *devi = PCCARD_IVAR(child);
struct resource_list *rl = &devi->resources;
rle = resource_list_find(rl, type, rid);
}
if (rle != NULL) {
return (bus_deactivate_resource(dev, type, rle->rid, rle->res));
}
return (bus_generic_deactivate_resource(dev, child, type, rid, r));
}
@ -930,6 +990,85 @@ pccard_child_detached(device_t parent, device_t dev)
free(ivar, M_DEVBUF);
}
static void
pccard_intr(void *arg) {
struct pccard_function *pf;
STAILQ_FOREACH(pf, &((struct pccard_softc*)arg)->card.pf_head, pf_list) {
if (pf->intr_handler != NULL) {
int reg = pccard_ccr_read(pf, PCCARD_CCR_STATUS);
if (reg & PCCARD_CCR_STATUS_INTR) {
pccard_ccr_write(pf, PCCARD_CCR_STATUS,
reg & ~PCCARD_CCR_STATUS_INTR);
pf->intr_handler(pf->intr_handler_arg);
}
}
}
}
static int
pccard_setup_intr(device_t dev, device_t child,
struct resource *irq, int flags,
driver_intr_t *intr, void *arg, void **cookiep)
{
struct pccard_ivar *ivar = PCCARD_IVAR(child);
struct pccard_function *func = ivar->fcn;
struct resource_list_entry *rle = NULL;
struct pccard_softc *sc = device_get_softc(dev);
if (func->intr_handler != NULL)
panic("Only one interrupt handler per function allowed for pccard\n");
rle = resource_list_find(&ivar->resources, SYS_RES_IRQ, 0);
if (rle == NULL || rle->res != irq)
panic("irq in setup_intr does not match allocated irq\n");
func->intr_handler = intr;
func->intr_handler_arg = arg;
func->intr_handler_cookie = cookiep;
pccard_ccr_write(func, PCCARD_CCR_OPTION,
pccard_ccr_read(func, PCCARD_CCR_OPTION) |
PCCARD_CCR_OPTION_IREQ_ENABLE);
if (sc->intr_handler_count++ == 0) {
rle = resource_list_find(&ivar->resources, SYS_RES_IRQ, 0);
if (rle == NULL)
panic("No IRQ for pccard?");
bus_setup_intr(dev, rle->res, INTR_TYPE_TTY/* | INTR_FAST*/,
pccard_intr, sc, (void*)&sc->intr_handler_count);
}
return 0;
}
static int
pccard_teardown_intr(device_t dev, device_t child, struct resource *r, void *cookie)
{
struct pccard_ivar *ivar = PCCARD_IVAR(child);
struct pccard_function *func = ivar->fcn;
struct pccard_softc *sc = device_get_softc(dev);
if (func->intr_handler_cookie != cookie)
panic("pccard teardown of unknown interrupt handler\n");
func->intr_handler = NULL;
func->intr_handler_arg = NULL;
func->intr_handler_cookie = NULL;
pccard_ccr_write(func, PCCARD_CCR_OPTION,
pccard_ccr_read(func, PCCARD_CCR_OPTION) &
~PCCARD_CCR_OPTION_IREQ_ENABLE);
if (--sc->intr_handler_count == 0) {
struct resource_list_entry *rle = NULL;
rle = resource_list_find(&ivar->resources, SYS_RES_IRQ, 0);
if (rle == NULL)
panic("No IRQ for pccard?");
bus_teardown_intr(dev, rle->res, &sc->intr_handler_count);
}
return 0;
}
static device_method_t pccard_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, pccard_probe),
@ -947,8 +1086,8 @@ static device_method_t pccard_methods[] = {
DEVMETHOD(bus_release_resource, pccard_release_resource),
DEVMETHOD(bus_activate_resource, pccard_activate_resource),
DEVMETHOD(bus_deactivate_resource, pccard_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
DEVMETHOD(bus_setup_intr, pccard_setup_intr),
DEVMETHOD(bus_teardown_intr, pccard_teardown_intr),
DEVMETHOD(bus_set_resource, pccard_set_resource),
DEVMETHOD(bus_get_resource, pccard_get_resource),
DEVMETHOD(bus_delete_resource, pccard_delete_resource),
@ -977,4 +1116,4 @@ DRIVER_MODULE(pccard, pc98pcic, pccard_driver, pccard_devclass, 0, 0);
DRIVER_MODULE(pccard, pccbb, pccard_driver, pccard_devclass, 0, 0);
DRIVER_MODULE(pccard, tcic, pccard_driver, pccard_devclass, 0, 0);
MODULE_VERSION(pccard, 1);
MODULE_DEPEND(pccard, pcic, 1, 1, 1);
/*MODULE_DEPEND(pccard, pcic, 1, 1, 1);*/

View File

@ -136,6 +136,9 @@ struct pccard_function {
long pf_mfc_iobase;
long pf_mfc_iomax;
int pf_flags;
driver_intr_t *intr_handler;
void *intr_handler_arg;
void *intr_handler_cookie;
};
/* pf_flags */
@ -181,6 +184,7 @@ struct pccard_softc {
/* this stuff is for the card */
struct pccard_card card;
int sc_enabled_count; /* num functions enabled */
int intr_handler_count;
};
void

View File

@ -242,7 +242,7 @@ static int pccbb_pcic_release_resource(device_t self, device_t child, int type,
static int pccbb_pcic_set_res_flags(device_t self, device_t child, int type,
int rid, u_int32_t flags);
static int pccbb_pcic_set_memory_offset(device_t self, device_t child, int rid,
u_int32_t offset);
u_int32_t offset, u_int32_t *offsetp);
static int pccbb_power_enable_socket(device_t self, device_t child);
static void pccbb_power_disable_socket(device_t self, device_t child);
static int pccbb_activate_resource(device_t self, device_t child, int type,
@ -378,7 +378,6 @@ static int
pccbb_attach(device_t dev)
{
struct pccbb_softc *sc = (struct pccbb_softc *)device_get_softc(dev);
int flags;
int rid;
u_int32_t tmp;
@ -387,9 +386,8 @@ pccbb_attach(device_t dev)
STAILQ_INIT(&softcs);
}
mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_DEF);
sc->sc_chipset = cb_chipset(pci_get_devid(dev), NULL, &flags);
sc->sc_chipset = cb_chipset(pci_get_devid(dev), NULL, &sc->sc_flags);
sc->sc_dev = dev;
sc->sc_flags = 0;
sc->sc_cbdev = NULL;
sc->sc_pccarddev = NULL;
sc->sc_secbus = pci_read_config(dev, PCIR_SECBUS_2, 1);
@ -562,7 +560,7 @@ pccbb_driver_added(device_t dev, driver_t *driver)
device_t *devlist;
int tmp;
int numdevs;
DEVICE_IDENTIFY(driver, dev);
device_get_children(dev, &devlist, &numdevs);
for (tmp = 0; tmp < numdevs; tmp++) {
@ -570,12 +568,24 @@ pccbb_driver_added(device_t dev, driver_t *driver)
device_probe_and_attach(devlist[tmp]) == 0) {
if (devlist[tmp] == NULL)
/* NOTHING */;
else if (strcmp(driver->name, "cardbus") == 0)
else if (strcmp(driver->name, "cardbus") == 0) {
sc->sc_cbdev = devlist[tmp];
else if (strcmp(driver->name, "pccard") == 0)
if ((sc->sc_socketreg->socket_state
& PCCBB_SOCKET_STAT_CD) == 0) {
mtx_enter(&sc->sc_mtx, MTX_DEF);
wakeup(sc);
mtx_exit(&sc->sc_mtx, MTX_DEF);
}
} else if (strcmp(driver->name, "pccard") == 0) {
sc->sc_pccarddev = devlist[tmp];
else
device_printf(dev,
if ((sc->sc_socketreg->socket_state
& PCCBB_SOCKET_STAT_CD) == 0) {
mtx_enter(&sc->sc_mtx, MTX_DEF);
wakeup(sc);
mtx_exit(&sc->sc_mtx, MTX_DEF);
}
} else
device_printf(dev,
"Unsupported child bus: %s\n",
driver->name);
}
@ -605,6 +615,7 @@ pccbb_event_thread (void *arg)
struct pccbb_softc *sc = arg;
u_int32_t status;
mtx_enter(&Giant, MTX_DEF);
for(;;) {
if (!(sc->sc_flags & PCCBB_KTHREAD_RUNNING))
sc->sc_flags |= PCCBB_KTHREAD_RUNNING;
@ -623,24 +634,15 @@ pccbb_event_thread (void *arg)
status = sc->sc_socketreg->socket_state;
if ((status & PCCBB_SOCKET_STAT_CD) == 0) {
if (!(sc->sc_flags & PCCBB_CARDATTACHED))
pccbb_insert(sc);
else
device_printf(sc->sc_dev,
"duplicate card insert\n");
pccbb_insert(sc);
} else {
if (!(sc->sc_flags & PCCBB_CARDATTACHED))
DEVPRINTF((sc->sc_dev,
"removal of nonexistant card!\n"));
else
pccbb_removal(sc);
pccbb_removal(sc);
}
mtx_exit(&sc->sc_mtx, MTX_DEF);
}
mtx_exit(&sc->sc_mtx, MTX_DEF);
sc->sc_flags &= ~PCCBB_KTHREAD_RUNNING;
wakeup(sc);
mtx_enter(&Giant, MTX_DEF);
kthread_exit(0);
}
@ -689,18 +691,13 @@ pccbb_insert (struct pccbb_softc *sc)
sockevent, sockstate));
if (sockstate & PCCBB_SOCKET_STAT_16BIT && sc->sc_pccarddev != NULL) {
sc->sc_flags |= PCCBB_CARDATTACHED | PCCBB_16BIT_CARD;
if (CARD_ATTACH_CARD(sc->sc_pccarddev) != 0) {
sc->sc_flags |= PCCBB_16BIT_CARD;
if (CARD_ATTACH_CARD(sc->sc_pccarddev) != 0)
device_printf(sc->sc_dev, "card activation failed\n");
sc->sc_flags &= ~PCCBB_CARDATTACHED;
}
} else if (sockstate & PCCBB_SOCKET_STAT_CB && sc->sc_cbdev != NULL) {
sc->sc_flags |= PCCBB_CARDATTACHED;
sc->sc_flags &= ~PCCBB_16BIT_CARD;
if (CARD_ATTACH_CARD(sc->sc_cbdev) != 0) {
if (CARD_ATTACH_CARD(sc->sc_cbdev) != 0)
device_printf(sc->sc_dev, "card activation failed\n");
sc->sc_flags &= ~PCCBB_CARDATTACHED;
}
} else {
device_printf (sc->sc_dev, "Unsupported card type detected\n");
}
@ -714,10 +711,9 @@ pccbb_removal (struct pccbb_softc *sc)
sockstate = sc->sc_socketreg->socket_state;
sc->sc_flags &= ~PCCBB_CARDATTACHED;
if (sockstate & PCCBB_16BIT_CARD)
if (sockstate & PCCBB_16BIT_CARD && sc->sc_pccarddev != NULL)
CARD_DETACH_CARD(sc->sc_pccarddev, DETACH_FORCE);
else
else if ((!(sockstate & PCCBB_16BIT_CARD)) && sc->sc_cbdev != NULL)
CARD_DETACH_CARD(sc->sc_cbdev, DETACH_FORCE);
while (NULL != (rle = SLIST_FIRST(&sc->rl))) {
@ -862,6 +858,9 @@ pccbb_power(device_t dev, int volts)
break;
}
if (sc->sc_socketreg->socket_control == sock_ctrl)
return 1; /* no change necessary */
sc->sc_socketreg->socket_control = sock_ctrl;
status = sc->sc_socketreg->socket_state;
@ -926,7 +925,7 @@ pccbb_cardbus_reset(device_t dev)
DELAY(delay_us);
/* If a card exists, unreset it! */
if (sc->sc_flags & PCCBB_CARDATTACHED) {
if ((sc->sc_socketreg->socket_state & PCCBB_SOCKET_STAT_CD) == 0) {
PCI_MASK_CONFIG(dev, PCCBBR_BRIDGECTRL,
&~PCCBBM_BRIDGECTRL_RESET, 2);
DELAY(delay_us);
@ -936,8 +935,13 @@ pccbb_cardbus_reset(device_t dev)
static int
pccbb_cardbus_power_enable_socket(device_t self, device_t child)
{
struct pccbb_softc *sc = device_get_softc(self);
int voltage;
if ((sc->sc_socketreg->socket_state & PCCBB_SOCKET_STAT_CD)
== PCCBB_SOCKET_STAT_CD)
return ENODEV;
voltage = pccbb_detect_voltage(self);
pccbb_power(self, CARD_VCC_0V | CARD_VPP_0V);
@ -1285,6 +1289,7 @@ pccbb_pcic_wait_ready(struct pccbb_softc *sc)
PCIC_SYSMEM_ADDR ## NUM ## _START_MSB, \
PCIC_SYSMEM_ADDR ## NUM ## _STOP_LSB, \
PCIC_SYSMEM_ADDR ## NUM ## _STOP_MSB, \
PCIC_SYSMEM_ADDR ## NUM ## _WIN, \
PCIC_CARDMEM_ADDR ## NUM ## _LSB, \
PCIC_CARDMEM_ADDR ## NUM ## _MSB, \
PCIC_ADDRWIN_ENABLE_MEM ## NUM ## , \
@ -1295,6 +1300,7 @@ static struct mem_map_index_st {
int sysmem_start_msb;
int sysmem_stop_lsb;
int sysmem_stop_msb;
int sysmem_win;
int cardmem_lsb;
int cardmem_msb;
int memenable;
@ -1314,7 +1320,7 @@ pccbb_pcic_do_mem_map(struct pccbb_softc *sc, int win)
(sc->mem[win].addr >> PCIC_SYSMEM_ADDRX_SHIFT) & 0xff);
PCIC_WRITE(sc, mem_map_index[win].sysmem_start_msb,
((sc->mem[win].addr >> (PCIC_SYSMEM_ADDRX_SHIFT + 8)) &
PCIC_SYSMEM_ADDRX_START_MSB_ADDR_MASK));
PCIC_SYSMEM_ADDRX_START_MSB_ADDR_MASK) | 0x80);
PCIC_WRITE(sc, mem_map_index[win].sysmem_stop_lsb,
((sc->mem[win].addr + sc->mem[win].realsize - 1) >>
@ -1325,6 +1331,9 @@ pccbb_pcic_do_mem_map(struct pccbb_softc *sc, int win)
PCIC_SYSMEM_ADDRX_STOP_MSB_ADDR_MASK) |
PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT2);
PCIC_WRITE(sc, mem_map_index[win].sysmem_win,
(sc->mem[win].addr >> PCIC_MEMREG_WIN_SHIFT) & 0xff);
PCIC_WRITE(sc, mem_map_index[win].cardmem_lsb,
(sc->mem[win].offset >> PCIC_CARDMEM_ADDRX_SHIFT) & 0xff);
PCIC_WRITE(sc, mem_map_index[win].cardmem_msb,
@ -1340,15 +1349,17 @@ pccbb_pcic_do_mem_map(struct pccbb_softc *sc, int win)
#ifdef CBB_DEBUG
{
int r1, r2, r3, r4, r5, r6;
int r1, r2, r3, r4, r5, r6, r7;
r1 = PCIC_READ(sc, mem_map_index[win].sysmem_start_msb);
r2 = PCIC_READ(sc, mem_map_index[win].sysmem_start_lsb);
r3 = PCIC_READ(sc, mem_map_index[win].sysmem_stop_msb);
r4 = PCIC_READ(sc, mem_map_index[win].sysmem_stop_lsb);
r5 = PCIC_READ(sc, mem_map_index[win].cardmem_msb);
r6 = PCIC_READ(sc, mem_map_index[win].cardmem_lsb);
r7 = PCIC_READ(sc, mem_map_index[win].sysmem_win);
DPRINTF(("pccbb_pcic_do_mem_map window %d: %02x%02x %02x%02x "
"%02x%02x\n", win, r1, r2, r3, r4, r5, r6));
"%02x%02x %02x (%08x+%08x.%08x*%08lx)\n", win, r1, r2, r3, r4, r5, r6, r7,
sc->mem[win].addr, sc->mem[win].size, sc->mem[win].realsize, sc->mem[win].offset));
}
#endif
}
@ -1371,7 +1382,6 @@ pccbb_pcic_mem_map(struct pccbb_softc *sc, int kind,
return (1);
card_addr = card_addr - card_addr % PCIC_MEM_PAGESIZE;
sc->mem[*win].memt = rman_get_bustag(r);
sc->mem[*win].memh = rman_get_bushandle(r);
sc->mem[*win].addr = rman_get_start(r);
@ -1399,7 +1409,6 @@ pccbb_pcic_mem_unmap(struct pccbb_softc *sc, int window)
panic("pccbb_pcic_mem_unmap: window out of range");
PCIC_MASK(sc, PCIC_ADDRWIN_ENABLE, & ~mem_map_index[window].memenable);
sc->memalloc &= ~(1 << window);
}
@ -1452,6 +1461,18 @@ static void pccbb_pcic_do_io_map(struct pccbb_softc *sc, int win)
| io_map_index[win].ioctlbits[sc->io[win].width]);
PCIC_MASK(sc, PCIC_ADDRWIN_ENABLE, | io_map_index[win].ioenable);
#ifdef CBB_DEBUG
{
int r1, r2, r3, r4;
r1 = PCIC_READ(sc, io_map_index[win].start_msb);
r2 = PCIC_READ(sc, io_map_index[win].start_lsb);
r3 = PCIC_READ(sc, io_map_index[win].stop_msb);
r4 = PCIC_READ(sc, io_map_index[win].stop_lsb);
DPRINTF(("pccbb_pcic_do_io_map window %d: %02x%02x %02x%02x "
"(%08x+%08x)\n", win, r1, r2, r3, r4,
sc->io[win].addr, sc->io[win].size));
}
#endif
}
static int
@ -1517,6 +1538,9 @@ pccbb_pcic_activate_resource(device_t self, device_t child, int type, int rid,
struct pccbb_reslist *rle;
struct pccbb_softc *sc = device_get_softc(self);
if (rman_get_flags(r) & RF_ACTIVE)
return 0;
switch (type) {
case SYS_RES_IOPORT:
err = pccbb_pcic_io_map(sc, 0, r, 0, &win);
@ -1549,7 +1573,6 @@ pccbb_pcic_deactivate_resource(device_t self, device_t child, int type,
struct pccbb_softc *sc = device_get_softc(self);
int win;
struct pccbb_reslist *rle;
win = -1;
SLIST_FOREACH(rle, &sc->rl, entries) {
if (type == rle->type && rid == rle->rid &&
@ -1558,8 +1581,10 @@ pccbb_pcic_deactivate_resource(device_t self, device_t child, int type,
break;
}
}
if (win == -1)
if (win == -1) {
panic("pccbb_pcic: deactivating bogus resoure");
return 1;
}
switch (type) {
case SYS_RES_IOPORT:
@ -1582,18 +1607,16 @@ pccbb_pcic_alloc_resource(device_t self, device_t child, int type, int* rid,
struct pccbb_softc *sc = device_get_softc(self);
struct pccbb_reslist *rle;
/* Nearly default */
if (type == SYS_RES_MEMORY && start == 0 && end == ~0 && count != 1) {
start = 0xd0000; /* XXX */
end = 0xdffff;
if ((sc->sc_flags & PCCBB_PCIC_MEM_32) == 0) {
panic("PCCBB bridge cannot handle non MEM_32 bridges\n");
}
switch (type) {
case SYS_RES_MEMORY:
/* Nearly default */
if (start == 0 && end == ~0 && count != 1) {
start = 0xd0000; /* XXX -- should be tweakable*/
end = 0xdffff;
start = CARDBUS_SYS_RES_MEMORY_START; /* XXX -- should be tweakable*/
end = CARDBUS_SYS_RES_MEMORY_END;
}
flags = (flags & ~RF_ALIGNMENT_MASK)
| rman_make_alignment_flags(PCCBB_MEMALIGN);
@ -1639,15 +1662,27 @@ pccbb_pcic_release_resource(device_t self, device_t child, int type,
{
struct pccbb_softc *sc = device_get_softc(self);
struct pccbb_reslist *rle;
int count = 0;
if (rman_get_flags(res) & RF_ACTIVE) {
int error;
error = bus_deactivate_resource(child, type, rid, res);
if (error != 0)
return error;
}
SLIST_FOREACH(rle, &sc->rl, entries) {
if (type == rle->type && rid == rle->rid &&
child == rle->odev) {
SLIST_REMOVE(&sc->rl, rle, pccbb_reslist, entries);
free(rle, M_DEVBUF);
count++;
break;
}
}
if (count == 0) {
panic("pccbb_pcic: releasing bogus resource");
}
return bus_generic_release_resource(self, child, type, rid, res);
}
@ -1671,13 +1706,14 @@ pccbb_pcic_set_res_flags(device_t self, device_t child, int type, int rid,
static int
pccbb_pcic_set_memory_offset(device_t self, device_t child, int rid,
u_int32_t offset)
u_int32_t cardaddr, u_int32_t *offsetp)
{
struct pccbb_softc *sc = device_get_softc(self);
int win;
struct pccbb_reslist *rle;
win = -1;
SLIST_FOREACH(rle, &sc->rl, entries) {
if (SYS_RES_MEMORY == rle->type && rid == rle->rid &&
child == rle->odev) {
@ -1685,13 +1721,17 @@ pccbb_pcic_set_memory_offset(device_t self, device_t child, int rid,
break;
}
}
if (win == -1)
if (win == -1) {
panic("pccbb_pcic: setting memory offset of bogus resource");
return 1;
}
offset = offset - offset % PCIC_MEM_PAGESIZE;
sc->mem[win].offset = ((long)offset) -
((long)(sc->mem[win].addr));
*offsetp = cardaddr % PCIC_MEM_PAGESIZE;
cardaddr -= *offsetp;
sc->mem[win].realsize = sc->mem[win].size + *offsetp + PCIC_MEM_PAGESIZE - 1;
sc->mem[win].realsize = sc->mem[win].realsize -
(sc->mem[win].realsize % PCIC_MEM_PAGESIZE);
sc->mem[win].offset = cardaddr - sc->mem[win].addr;
pccbb_pcic_do_mem_map(sc, win);
return 0;
@ -1785,7 +1825,7 @@ static int
pccbb_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
{
struct pccbb_softc *sc = device_get_softc(dev);
switch (which) {
case PCIB_IVAR_BUS:
*result = sc->sc_secbus;

View File

@ -71,7 +71,6 @@ struct pccbb_softc {
u_int32_t sc_flags;
#define PCCBB_PCIC_IO_RELOC 0x01
#define PCCBB_PCIC_MEM_32 0x02
#define PCCBB_CARDATTACHED 0x01000000
#define PCCBB_16BIT_CARD 0x02000000
#define PCCBB_KTHREAD_RUNNING 0x04000000
#define PCCBB_KTHREAD_DONE 0x08000000
@ -122,7 +121,7 @@ struct pccbb_softc {
#define CARD_VPPMASK 0x00f0
/* XXX: rman is dumb */
#define CARDBUS_SYS_RES_MEMORY_START 0x18020000
#define CARDBUS_SYS_RES_MEMORY_START 0x44000000
#define CARDBUS_SYS_RES_MEMORY_END 0xEFFFFFFF
#define CARDBUS_SYS_RES_IOPORT_START 0x3000
#define CARDBUS_SYS_RES_IOPORT_END 0xEFFF