o Fix MFC cards.  We were bogusly setting CCR_IOBASE[01] and CCR_IOLIMIT.
  now when we activate the resource, we adjust these for MFC cards, per the
  spec.
o Change type of pf_mfc_* to be bus_addr_t, which is more correct than
  long.

This makes my 3C362D/3C363D and 3CXEM556 cards work!  Woo Hoo!
This commit is contained in:
Warner Losh 2003-11-02 20:18:19 +00:00
parent 1c4c419607
commit 4f9303c05a
2 changed files with 99 additions and 49 deletions

View File

@ -263,9 +263,10 @@ pccard_attach_card(device_t dev)
pccard_set_default_descr(child) == 0 &&
device_probe_and_attach(child) == 0) {
DEVPRINTF((sc->dev, "function %d CCR at %d "
"offset %x: %x %x %x %x, %x %x %x %x, %x\n",
"offset %x mask %x: "
"%x %x %x %x, %x %x %x %x, %x\n",
pf->number, pf->pf_ccr_window, pf->pf_ccr_offset,
pccard_ccr_read(pf, 0x00),
pf->ccr_mask, pccard_ccr_read(pf, 0x00),
pccard_ccr_read(pf, 0x02), pccard_ccr_read(pf, 0x04),
pccard_ccr_read(pf, 0x06), pccard_ccr_read(pf, 0x0A),
pccard_ccr_read(pf, 0x0C), pccard_ccr_read(pf, 0x0E),
@ -528,6 +529,43 @@ pccard_function_free(struct pccard_function *pf)
resource_list_free(&devi->resources);
}
static void
pccard_mfc_adjust_iobase(struct pccard_function *pf, bus_addr_t addr,
bus_addr_t offset, bus_size_t size)
{
bus_addr_t iosize;
bus_size_t tmp;
if (addr != 0) {
if (pf->pf_mfc_iomax == 0) {
pf->pf_mfc_iobase = addr + offset;
pf->pf_mfc_iomax = pf->pf_mfc_iobase + size;
} else {
/* this makes the assumption that nothing overlaps */
if (pf->pf_mfc_iobase > addr + offset)
pf->pf_mfc_iobase = addr + offset;
if (pf->pf_mfc_iomax < addr + offset + size)
pf->pf_mfc_iomax = addr + offset + size;
}
}
tmp = pf->pf_mfc_iomax - pf->pf_mfc_iobase;
/* round up to nearest (2^n)-1 */
for (iosize = 1; iosize < tmp; iosize <<= 1)
;
iosize--;
DEVPRINTF((pf->dev, "MFC: I/O base 0x%x IOSIZE %lld\n",
pf->pf_mfc_iobase, (uint64_t) iosize));
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);
pccard_ccr_write(pf, PCCARD_CCR_IOBASE2, 0);
pccard_ccr_write(pf, PCCARD_CCR_IOBASE3, 0);
pccard_ccr_write(pf, PCCARD_CCR_IOSIZE, iosize);
}
/* Enable a PCCARD function */
static int
pccard_function_enable(struct pccard_function *pf)
@ -615,24 +653,8 @@ pccard_function_enable(struct pccard_function *pf)
pccard_ccr_write(pf, PCCARD_CCR_SOCKETCOPY, 0);
if (pccard_mfc(pf->sc)) {
long tmp, iosize;
tmp = pf->pf_mfc_iomax - pf->pf_mfc_iobase;
/* round up to nearest (2^n)-1 */
for (iosize = 1; iosize < tmp; iosize <<= 1)
;
iosize--;
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);
pccard_ccr_write(pf, PCCARD_CCR_IOBASE2, 0);
pccard_ccr_write(pf, PCCARD_CCR_IOBASE3, 0);
pccard_ccr_write(pf, PCCARD_CCR_IOSIZE, iosize);
}
if (pccard_mfc(pf->sc))
pccard_mfc_adjust_iobase(pf, 0, 0, 0);
#ifdef PCCARDDEBUG
if (pccard_debug) {
@ -1052,8 +1074,10 @@ pccard_alloc_resource(device_t dev, device_t child, int type, int *rid,
struct pccard_ivar *dinfo;
struct resource_list_entry *rle = 0;
int passthrough = (device_get_parent(child) != dev);
int isdefault = (start == 0 && end == ~0UL && count == 1);
struct resource *r = NULL;
/* XXX I'm no longer sure this is right */
if (passthrough) {
return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
type, rid, start, end, count, flags));
@ -1062,30 +1086,27 @@ pccard_alloc_resource(device_t dev, device_t child, int type, int *rid,
dinfo = device_get_ivars(child);
rle = resource_list_find(&dinfo->resources, type, *rid);
if (rle == NULL)
return (NULL); /* no resource of that type/rid */
if (rle->res == NULL) {
switch(type) {
case SYS_RES_IOPORT:
r = bus_alloc_resource(dev, type, rid, start, end,
count, rman_make_alignment_flags(count));
if (r == NULL)
goto bad;
resource_list_add(&dinfo->resources, type, *rid,
rman_get_start(r), rman_get_end(r), count);
rle = resource_list_find(&dinfo->resources, type, *rid);
if (!rle)
goto bad;
rle->res = r;
break;
case SYS_RES_MEMORY:
break;
case SYS_RES_IRQ:
break;
}
return (rle->res);
if (rle == NULL && isdefault)
return (NULL); /* no resource of that type/rid */
if (rle == NULL || rle->res == NULL) {
/* Do we want this device to own it? */
/* XXX I think so, but that might be lame XXX */
r = bus_alloc_resource(dev, type, rid, start, end,
count, flags /* XXX aligment? */);
if (r == NULL)
goto bad;
resource_list_add(&dinfo->resources, type, *rid,
rman_get_start(r), rman_get_end(r), count);
rle = resource_list_find(&dinfo->resources, type, *rid);
if (!rle)
goto bad;
rle->res = r;
}
/*
* XXX the following looks wrong, in theory, but likely it is
* XXX needed because of how the CIS code allocates resources
* XXX for this device.
*/
if (rman_get_device(rle->res) != dev)
return (NULL);
bus_release_resource(dev, type, *rid, rle->res);
@ -1252,6 +1273,37 @@ pccard_teardown_intr(device_t dev, device_t child, struct resource *r,
return (ret);
}
static int
pccard_activate_resource(device_t brdev, device_t child, int type, int rid,
struct resource *r)
{
struct pccard_ivar *ivar = PCCARD_IVAR(child);
struct pccard_function *pf = ivar->fcn;
switch(type) {
case SYS_RES_IOPORT:
/*
* We need to adjust IOBASE[01] and IOSIZE if we're an MFC
* card.
*/
if (pccard_mfc(pf->sc))
pccard_mfc_adjust_iobase(pf, rman_get_start(r), 0,
rman_get_size(r));
break;
default:
break;
}
return (bus_generic_activate_resource(brdev, child, type, rid, r));
}
static int
pccard_deactivate_resource(device_t brdev, device_t child, int type,
int rid, struct resource *r)
{
/* XXX undo pccard_activate_resource? XXX */
return (bus_generic_deactivate_resource(brdev, child, type, rid, r));
}
static device_method_t pccard_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, pccard_probe),
@ -1267,8 +1319,8 @@ static device_method_t pccard_methods[] = {
DEVMETHOD(bus_child_detached, pccard_child_detached),
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_activate_resource, pccard_activate_resource),
DEVMETHOD(bus_deactivate_resource, pccard_deactivate_resource),
DEVMETHOD(bus_setup_intr, pccard_setup_intr),
DEVMETHOD(bus_teardown_intr, pccard_teardown_intr),
DEVMETHOD(bus_set_resource, pccard_set_resource),

View File

@ -147,8 +147,8 @@ struct pccard_function {
#define pf_ccr_realsize pf_pcmh.realsize
uint32_t pf_ccr_offset; /* Offset from ccr_base of CIS */
int pf_ccr_window;
long pf_mfc_iobase; /* Right type? */
long pf_mfc_iomax;
bus_addr_t pf_mfc_iobase;
bus_addr_t pf_mfc_iomax;
int pf_flags;
driver_intr_t *intr_handler;
void *intr_handler_arg;
@ -373,10 +373,8 @@ enum {
#define PCMCIA_CARD2_D(v1, p1, p2, f) \
{ PCMCIA_STR_ ## p2, PCMCIA_VENDOR_ ## v1, PCCARD_P(v1, p1), \
f, PCMCIA_CIS_ ## p2}
#if 1
#define PCMCIA_CARD(v, p, f) { NULL, PCMCIA_VENDOR_ ## v, \
PCCARD_P(v, p), f, PCCARD_C(v, p) }
#define PCMCIA_CARD2(v1, p1, p2, f) \
{ NULL, PCMCIA_VENDOR_ ## v1, PCCARD_P(v1, p1), \
f, PCMCIA_CIS_ ## p2}
#endif