svn commit: r193945 - stable/7/sys/dev/cardbus

Warner Losh imp at FreeBSD.org
Wed Jun 10 19:21:24 UTC 2009


Author: imp
Date: Wed Jun 10 19:21:23 2009
New Revision: 193945
URL: http://svn.freebsd.org/changeset/base/193945

Log:
  MFC:
  
  r188216 | wkoszek | 2009-02-05 17:55:19 -0700 (Thu, 05 Feb 2009) | 5 lines
  r185545 | imp | 2008-12-01 21:54:31 -0700 (Mon, 01 Dec 2008) | 2 lines
  r185140 | imp | 2008-11-20 20:03:57 -0700 (Thu, 20 Nov 2008) | 4 lines
  r185015 | imp | 2008-11-16 18:32:29 -0700 (Sun, 16 Nov 2008) | 8 lines
  r184981 | imp | 2008-11-14 22:22:06 -0700 (Fri, 14 Nov 2008) | 5 lines
  
  These commits move all the parsing of the CIS to where the card is
  detected, rather than when the open call for the device happens.  This
  means that we can now reliably get this info from cards.  Atheros
  network cards in conjunction with the HAL were a primary motivator for
  this fix, although other applications benefit.

Modified:
  stable/7/sys/dev/cardbus/cardbus.c
  stable/7/sys/dev/cardbus/cardbus_cis.c
  stable/7/sys/dev/cardbus/cardbus_device.c
  stable/7/sys/dev/cardbus/cardbusvar.h

Modified: stable/7/sys/dev/cardbus/cardbus.c
==============================================================================
--- stable/7/sys/dev/cardbus/cardbus.c	Wed Jun 10 19:03:23 2009	(r193944)
+++ stable/7/sys/dev/cardbus/cardbus.c	Wed Jun 10 19:21:23 2009	(r193945)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2003 M. Warner Losh.  All Rights Reserved.
+ * Copyright (c) 2003-2008 M. Warner Losh.  All Rights Reserved.
  * Copyright (c) 2000,2001 Jonathan Chen.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -99,20 +99,18 @@ cardbus_probe(device_t cbdev)
 static int
 cardbus_attach(device_t cbdev)
 {
-	struct cardbus_softc *sc = device_get_softc(cbdev);
+	struct cardbus_softc *sc;
 
+	sc = device_get_softc(cbdev);
 	sc->sc_dev = cbdev;
-	cardbus_device_create(sc);
 	return (0);
 }
 
 static int
 cardbus_detach(device_t cbdev)
 {
-	struct cardbus_softc *sc = device_get_softc(cbdev);
 
 	cardbus_detach_card(cbdev);
-	cardbus_device_destroy(sc);
 	return (0);
 }
 
@@ -165,7 +163,9 @@ cardbus_attach_card(device_t cbdev)
 	int bus, domain, slot, func;
 	int cardattached = 0;
 	int cardbusfunchigh = 0;
+	struct cardbus_softc *sc;
 
+	sc = device_get_softc(cbdev);
 	cardbus_detach_card(cbdev); /* detach existing cards */
 	POWER_ENABLE_SOCKET(brdev, cbdev);
 	domain = pcib_get_domain(cbdev);
@@ -192,6 +192,7 @@ cardbus_attach_card(device_t cbdev)
 		dinfo->pci.cfg.dev = child;
 		resource_list_init(&dinfo->pci.resources);
 		device_set_ivars(child, dinfo);
+		cardbus_device_create(sc, dinfo, cbdev, child);
 		if (cardbus_do_cis(cbdev, child) != 0)
 			DEVPRINTF((cbdev, "Warning: Bogus CIS ignored\n"));
 		pci_cfg_save(dinfo->pci.cfg.dev, &dinfo->pci, 0);
@@ -235,6 +236,7 @@ cardbus_detach_card(device_t cbdev)
 		if (status == DS_ATTACHED || status == DS_BUSY)
 			device_detach(devlist[tmp]);
 		cardbus_release_all_resources(cbdev, dinfo);
+		cardbus_device_destroy(dinfo);
 		device_delete_child(cbdev, devlist[tmp]);
 		pci_freecfg((struct pci_devinfo *)dinfo);
 	}

Modified: stable/7/sys/dev/cardbus/cardbus_cis.c
==============================================================================
--- stable/7/sys/dev/cardbus/cardbus_cis.c	Wed Jun 10 19:03:23 2009	(r193944)
+++ stable/7/sys/dev/cardbus/cardbus_cis.c	Wed Jun 10 19:21:23 2009	(r193945)
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2005-2008, M. Warner Losh
  * Copyright (c) 2000,2001 Jonathan Chen.
  * All rights reserved.
  *
@@ -318,29 +319,27 @@ decode_tuple_bar(device_t cbdev, device_
 	if (type == SYS_RES_MEMORY) {
 		if (reg & TPL_BAR_REG_PREFETCHABLE)
 			dinfo->mprefetchable |= (1 << PCI_RID2BAR(bar));
-#if 0
 		/*
-		 * XXX: It appears from a careful reading of the spec
-		 * that we're not supposed to honor this when the bridge
-		 * is not on the main system bus.  PCI spec doesn't appear
-		 * to allow for memory ranges not listed in the bridge's
-		 * decode range to be decoded.  The PC Card spec seems to
-		 * indicate that this should only be done on x86 based
-		 * machines, which seems to imply that on non-x86 machines
-		 * the adddresses can be anywhere.  This further implies that
-		 * since the hardware can do it on non-x86 machines, it should
-		 * be able to do it on x86 machines.  Therefore, we can and
-		 * should ignore this hint.  Furthermore, the PC Card spec
-		 * recommends always allocating memory above 1MB, contradicting
-		 * the other part of the PC Card spec.
+		 * The PC Card spec says we're only supposed to honor this
+		 * hint when the cardbus bridge is a child of pci0 (the main
+		 * bus).  The PC Card spec seems to indicate that this should
+		 * only be done on x86 based machines, which suggests that on
+		 * non-x86 machines the adddresses can be anywhere.  Since the
+		 * hardware can do it on non-x86 machines, it should be able
+		 * to do it on x86 machines too.  Therefore, we can and should
+		 * ignore this hint.  Furthermore, the PC Card spec recommends
+		 * always allocating memory above 1MB, contradicting the other
+		 * part of the PC Card spec, it seems.  We make note of it,
+		 * but otherwise don't use this information.
 		 *
-		 * NetBSD ignores this bit, but it also ignores the
-		 * prefetchable bit too, so that's not an indication of
-		 * correctness.
+		 * Some Realtek cards have this set in their CIS, but fail
+		 * to actually work when mapped this way, and experience
+		 * has shown ignoring this big to be a wise choice.
+		 *
+		 * XXX We should cite chapter and verse for standard refs.
 		 */
 		if (reg & TPL_BAR_REG_BELOW1MB)
 			dinfo->mbelow1mb |= (1 << PCI_RID2BAR(bar));
-#endif
 	}
 
 	return (0);

Modified: stable/7/sys/dev/cardbus/cardbus_device.c
==============================================================================
--- stable/7/sys/dev/cardbus/cardbus_device.c	Wed Jun 10 19:03:23 2009	(r193944)
+++ stable/7/sys/dev/cardbus/cardbus_device.c	Wed Jun 10 19:21:23 2009	(r193945)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2005, M. Warner Losh
+ * Copyright (c) 2005-2008, M. Warner Losh
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -63,26 +63,6 @@ static struct cdevsw cardbus_cdevsw = {
 	.d_name =	"cardbus"
 };
 
-int
-cardbus_device_create(struct cardbus_softc *sc)
-{
-	uint32_t minor;
-
-	minor = device_get_unit(sc->sc_dev) << 16;
-	sc->sc_cisdev = make_dev(&cardbus_cdevsw, minor, 0, 0, 0666,
-	    "cardbus%u.cis", device_get_unit(sc->sc_dev));
-	sc->sc_cisdev->si_drv1 = sc;
-	return (0);
-}
-
-int
-cardbus_device_destroy(struct cardbus_softc *sc)
-{
-	if (sc->sc_cisdev)
-		destroy_dev(sc->sc_cisdev);
-	return (0);
-}
-
 static int
 cardbus_build_cis(device_t cbdev, device_t child, int id,
     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
@@ -96,13 +76,17 @@ cardbus_build_cis(device_t cbdev, device
 	 * CISTPL_END is a special case, it has no length field.
 	 */
 	if (id == CISTPL_END) {
-		if (cis->len + 1 > sizeof(cis->buffer))
+		if (cis->len + 1 > sizeof(cis->buffer)) {
+			cis->len = 0;
 			return (ENOSPC);
+		}
 		cis->buffer[cis->len++] = id;
 		return (0);
 	}
-	if (cis->len + 2 + len > sizeof(cis->buffer))
+	if (cis->len + 2 + len > sizeof(cis->buffer)) {
+		cis->len = 0;
 		return (ENOSPC);
+	}
 	cis->buffer[cis->len++] = id;
 	cis->buffer[cis->len++] = len;
 	for (i = 0; i < len; i++)
@@ -110,52 +94,54 @@ cardbus_build_cis(device_t cbdev, device
 	return (0);
 }
 
-static	int
-cardbus_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+static int
+cardbus_device_buffer_cis(device_t parent, device_t child,
+    struct cis_buffer *cbp)
 {
-	device_t parent, child;
-	device_t *kids;
-	int cnt, err;
-	struct cardbus_softc *sc;
 	struct tuple_callbacks cb[] = {
 		{CISTPL_GENERIC, "GENERIC", cardbus_build_cis}
 	};
 
-	sc = dev->si_drv1;
-	if (sc->sc_cis_open)
-		return (EBUSY);
-	parent = sc->sc_dev;
-	err = device_get_children(parent, &kids, &cnt);
-	if (err)
-		return err;
-	if (cnt == 0) {
-		free(kids, M_TEMP);
-		sc->sc_cis_open++;
-		sc->sc_cis = NULL;
-		return (0);
-	}
-	child = kids[0];
-	free(kids, M_TEMP);
-	sc->sc_cis = malloc(sizeof(*sc->sc_cis), M_TEMP, M_ZERO | M_WAITOK);
-	err = cardbus_parse_cis(parent, child, cb, sc->sc_cis);
-	if (err) {
-		free(sc->sc_cis, M_TEMP);
-		sc->sc_cis = NULL;
-		return (err);
-	}
-	sc->sc_cis_open++;
+	return (cardbus_parse_cis(parent, child, cb, cbp));
+}
+
+int
+cardbus_device_create(struct cardbus_softc *sc, struct cardbus_devinfo *devi,
+    device_t parent, device_t child)
+{
+	uint32_t minor;
+	int unit;
+
+	cardbus_device_buffer_cis(parent, child, &devi->sc_cis);
+	minor = (device_get_unit(sc->sc_dev) << 8) + devi->pci.cfg.func;
+	unit = device_get_unit(sc->sc_dev);
+	devi->sc_cisdev = make_dev(&cardbus_cdevsw, minor, 0, 0, 0666,
+	    "cardbus%d.%d.cis", unit, devi->pci.cfg.func);
+	if (devi->pci.cfg.func == 0)
+		make_dev_alias(devi->sc_cisdev, "cardbus%d.cis", unit);
+	devi->sc_cisdev->si_drv1 = devi;
+	return (0);
+}
+
+int
+cardbus_device_destroy(struct cardbus_devinfo *devi)
+{
+	if (devi->sc_cisdev)
+		destroy_dev(devi->sc_cisdev);
+	return (0);
+}
+
+static	int
+cardbus_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+{
+
 	return (0);
 }
 
 static	int
 cardbus_close(struct cdev *dev, int fflags, int devtype, struct thread *td)
 {
-	struct cardbus_softc *sc;
 
-	sc = dev->si_drv1;
-	free(sc->sc_cis, M_TEMP);
-	sc->sc_cis = NULL;
-	sc->sc_cis_open = 0;
 	return (0);
 }
 
@@ -169,12 +155,12 @@ cardbus_ioctl(struct cdev *dev, u_long c
 static	int
 cardbus_read(struct cdev *dev, struct uio *uio, int ioflag)
 {
-	struct cardbus_softc *sc;
+	struct cardbus_devinfo *devi;
 
-	sc = dev->si_drv1;
+	devi = dev->si_drv1;
 	/* EOF */
-	if (sc->sc_cis == NULL || uio->uio_offset > sc->sc_cis->len)
+	if (uio->uio_offset >= devi->sc_cis.len)
 		return (0);
-	return (uiomove(sc->sc_cis->buffer + uio->uio_offset,
-	  MIN(uio->uio_resid, sc->sc_cis->len - uio->uio_offset), uio));
+	return (uiomove(devi->sc_cis.buffer + uio->uio_offset,
+	  MIN(uio->uio_resid, devi->sc_cis.len - uio->uio_offset), uio));
 }

Modified: stable/7/sys/dev/cardbus/cardbusvar.h
==============================================================================
--- stable/7/sys/dev/cardbus/cardbusvar.h	Wed Jun 10 19:03:23 2009	(r193944)
+++ stable/7/sys/dev/cardbus/cardbusvar.h	Wed Jun 10 19:21:23 2009	(r193945)
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2008, M. Warner Losh
  * Copyright (c) 2000,2001 Jonathan Chen.
  * All rights reserved.
  *
@@ -29,12 +30,26 @@
 /*
  * Structure definitions for the Cardbus Bus driver
  */
+
+/*
+ * Static copy of the CIS buffer.  Technically, you aren't supposed
+ * to do this.  In practice, however, it works well.
+ */
+struct cis_buffer
+{
+	size_t	len;			/* Actual length of the CIS */
+	uint8_t buffer[2040];		/* small enough to be 2k */
+};
+
+/*
+ * Per child information for the PCI device.  Cardbus layers on some
+ * additional data.
+ */
 struct cardbus_devinfo
 {
 	struct pci_devinfo pci;
 	uint8_t        mprefetchable; /* bit mask of prefetchable BARs */
 	uint8_t        mbelow1mb; /* bit mask of BARs which require below 1Mb */
-	uint8_t        ibelow1mb; /* bit mask of BARs which require below 1Mb */
 	uint16_t	mfrid;		/* manufacturer id */
 	uint16_t	prodid;		/* product id */
 	u_int		funcid;		/* function id */
@@ -44,36 +59,33 @@ struct cardbus_devinfo
 		} lan;
 	} funce;
 	uint32_t	fepresent;	/* bit mask of funce values present */
+	struct cdev 	*sc_cisdev;
+	struct cis_buffer sc_cis;
 };
 
-struct cis_buffer
-{
-	size_t	len;			/* Actual length of the CIS */
-	uint8_t buffer[2040];		/* small enough to be 2k */
-};
-
+/*
+ * Per cardbus soft info.  Not sure why we even keep this around...
+ */
 struct cardbus_softc 
 {
-	/* XXX need mutex XXX */
 	device_t	sc_dev;
-	struct cdev 	*sc_cisdev;
-	struct cis_buffer *sc_cis;
-	int		sc_cis_open;
 };
 
+/*
+ * Per node callback structures.
+ */
 struct tuple_callbacks;
-
 typedef int (tuple_cb) (device_t cbdev, device_t child, int id, int len,
 		 uint8_t *tupledata, uint32_t start, uint32_t *off,
 		 struct tuple_callbacks *info, void *);
-
 struct tuple_callbacks {
 	int	id;
 	char	*name;
 	tuple_cb *func;
 };
 
-int	cardbus_device_create(struct cardbus_softc *);
-int	cardbus_device_destroy(struct cardbus_softc *);
+int	cardbus_device_create(struct cardbus_softc *sc,
+	    struct cardbus_devinfo *devi, device_t parent, device_t child);
+int	cardbus_device_destroy(struct cardbus_devinfo *devi);
 int	cardbus_parse_cis(device_t cbdev, device_t child,
 	    struct tuple_callbacks *callbacks, void *);


More information about the svn-src-all mailing list