Module Name:    src
Committed By:   jmcneill
Date:           Fri Jul 15 00:21:26 UTC 2011

Modified Files:
        src/sys/dev/pci: cxdtv.c cxdtvvar.h

Log Message:
add detach support


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/dev/pci/cxdtv.c
cvs rdiff -u -r1.1 -r1.2 src/sys/dev/pci/cxdtvvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/cxdtv.c
diff -u src/sys/dev/pci/cxdtv.c:1.2 src/sys/dev/pci/cxdtv.c:1.3
--- src/sys/dev/pci/cxdtv.c:1.2	Thu Jul 14 23:47:45 2011
+++ src/sys/dev/pci/cxdtv.c	Fri Jul 15 00:21:26 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: cxdtv.c,v 1.2 2011/07/14 23:47:45 jmcneill Exp $ */
+/* $NetBSD: cxdtv.c,v 1.3 2011/07/15 00:21:26 jmcneill Exp $ */
 
 /*
  * Copyright (c) 2008, 2011 Jonathan A. Kollasch
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cxdtv.c,v 1.2 2011/07/14 23:47:45 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cxdtv.c,v 1.3 2011/07/15 00:21:26 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -65,6 +65,7 @@
 static int cxdtv_match(struct device *, struct cfdata *, void *);
 static void cxdtv_attach(struct device *, struct device *, void *);
 static int cxdtv_detach(struct device *, int);
+static void cxdtv_childdet(struct device *, struct device *);
 static int cxdtv_intr(void *);
 
 static bool cxdtv_resume(device_t, const pmf_qual_t *);
@@ -90,6 +91,7 @@
 static int	cxdtv_risc_field(struct cxdtv_softc *, uint32_t *, uint32_t);
 
 static int     cxdtv_mpeg_attach(struct cxdtv_softc *);
+static int     cxdtv_mpeg_detach(struct cxdtv_softc *, int flags);
 static int     cxdtv_mpeg_intr(struct cxdtv_softc *);
 static int     cxdtv_mpeg_reset(struct cxdtv_softc *);
 
@@ -127,8 +129,8 @@
 	},
 };
 
-CFATTACH_DECL_NEW(cxdtv, sizeof(struct cxdtv_softc),
-    cxdtv_match, cxdtv_attach, cxdtv_detach, NULL);
+CFATTACH_DECL2_NEW(cxdtv, sizeof(struct cxdtv_softc),
+    cxdtv_match, cxdtv_attach, cxdtv_detach, NULL, NULL, cxdtv_childdet);
 
 static int
 cxdtv_match(device_t parent, cfdata_t match, void *aux)
@@ -164,6 +166,7 @@
 	sc = device_private(self);
 
 	sc->sc_dev = self;
+	sc->sc_pc = pa->pa_pc;
 
 	aprint_naive("\n");
 
@@ -249,7 +252,33 @@
 static int
 cxdtv_detach(device_t self, int flags)
 {
-	return EBUSY;
+	struct cxdtv_softc *sc = device_private(self);
+	int error;
+
+	error = cxdtv_mpeg_detach(sc, flags);
+	if (error)
+		return error;
+
+	if (sc->sc_ih)
+		pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
+
+	if (sc->sc_mems)
+		bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_mems);
+
+	mutex_destroy(&sc->sc_i2c_buslock);
+	mutex_destroy(&sc->sc_delaylock);
+	cv_destroy(&sc->sc_delaycv);
+
+	return 0;
+}
+
+static void
+cxdtv_childdet(device_t self, device_t child)
+{
+	struct cxdtv_softc *sc = device_private(self);
+
+	if (child == sc->sc_dtvdev)
+		sc->sc_dtvdev = NULL;
 }
 
 static bool
@@ -463,6 +492,50 @@
 	return (sc->sc_dtvdev != NULL);
 }
 
+int
+cxdtv_mpeg_detach(struct cxdtv_softc *sc, int flags)
+{
+	int error = 0;
+
+	if (sc->sc_dtvdev) {
+		error = config_detach(sc->sc_dtvdev, flags);
+		if (error)
+			return error;
+	}
+
+	if (sc->sc_demod) {
+		switch (sc->sc_board->cb_demod) {
+		case CXDTV_DEMOD_NXT2004:
+			nxt2k_close(sc->sc_demod);
+			break;
+		case CXDTV_DEMOD_LG3303:
+			lg3303_close(sc->sc_demod);
+			break;
+		default:
+			break;
+		}
+		sc->sc_demod = NULL;
+	}
+	if (sc->sc_tuner) {
+		switch (sc->sc_board->cb_tuner) {
+		case CXDTV_TUNER_PLL:
+			tvpll_close(sc->sc_tuner);
+			break;
+		default:
+			break;
+		}
+		sc->sc_tuner = NULL;
+	}
+
+	if (sc->sc_riscbuf) {
+		kmem_free(sc->sc_riscbuf, sc->sc_riscbufsz);
+		sc->sc_riscbuf = NULL;
+		sc->sc_riscbufsz = 0;
+	}
+
+	return error;
+}
+
 static void
 cxdtv_dtv_get_devinfo(void *priv, struct dvb_frontend_info *info)
 {
@@ -1076,15 +1149,11 @@
 
 	val &= ~1;
 	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_GP0_IO, val);
-	mutex_enter(&sc->sc_delaylock);
-	cv_timedwait(&sc->sc_delaycv, &sc->sc_delaylock, mstohz(10));
-	mutex_exit(&sc->sc_delaylock);
+	delay(100000);
 
 	val |= 1;
 	bus_space_write_4(sc->sc_memt, sc->sc_memh, CXDTV_GP0_IO, val);
-	mutex_enter(&sc->sc_delaylock);
-	cv_timedwait(&sc->sc_delaycv, &sc->sc_delaylock, mstohz(15));
-	mutex_exit(&sc->sc_delaylock);
+	delay(200000);
 }
 
 MODULE(MODULE_CLASS_DRIVER, cxdtv, "dtv,tvpll,nxt2k,lg3303");

Index: src/sys/dev/pci/cxdtvvar.h
diff -u src/sys/dev/pci/cxdtvvar.h:1.1 src/sys/dev/pci/cxdtvvar.h:1.2
--- src/sys/dev/pci/cxdtvvar.h:1.1	Mon Jul 11 00:46:04 2011
+++ src/sys/dev/pci/cxdtvvar.h	Fri Jul 15 00:21:26 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: cxdtvvar.h,v 1.1 2011/07/11 00:46:04 jakllsch Exp $ */
+/* $NetBSD: cxdtvvar.h,v 1.2 2011/07/15 00:21:26 jmcneill Exp $ */
 
 /*
  * Copyright (c) 2008, 2011 Jonathan A. Kollasch
@@ -76,6 +76,8 @@
 	device_t		sc_dev;
 	device_t		sc_dtvdev;
 
+	pci_chipset_tag_t	sc_pc;
+
 	bus_space_tag_t		sc_memt;
 	bus_space_handle_t	sc_memh;
 	bus_size_t		sc_mems;

Reply via email to