summaryrefslogtreecommitdiffstats
path: root/sys/dev/pccard
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2003-11-02 20:18:19 +0000
committerimp <imp@FreeBSD.org>2003-11-02 20:18:19 +0000
commit1715012e34106bd2f21f06896f5fc245a1ad94ec (patch)
treec0a07ddb0b41cbbe04ff79bdae38cb0529394087 /sys/dev/pccard
parent3fef709f3d4e6341ae128b765428a98dd68b0d4d (diff)
downloadFreeBSD-src-1715012e34106bd2f21f06896f5fc245a1ad94ec.zip
FreeBSD-src-1715012e34106bd2f21f06896f5fc245a1ad94ec.tar.gz
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!
Diffstat (limited to 'sys/dev/pccard')
-rw-r--r--sys/dev/pccard/pccard.c142
-rw-r--r--sys/dev/pccard/pccardvar.h6
2 files changed, 99 insertions, 49 deletions
diff --git a/sys/dev/pccard/pccard.c b/sys/dev/pccard/pccard.c
index 4194275..622c198 100644
--- a/sys/dev/pccard/pccard.c
+++ b/sys/dev/pccard/pccard.c
@@ -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),
diff --git a/sys/dev/pccard/pccardvar.h b/sys/dev/pccard/pccardvar.h
index 7a20f48..1868a37 100644
--- a/sys/dev/pccard/pccardvar.h
+++ b/sys/dev/pccard/pccardvar.h
@@ -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
OpenPOWER on IntegriCloud