MFp4:
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:
parent
1c4c419607
commit
4f9303c05a
@ -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),
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user