Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 30 Oct 2008 04:01:12 +0000 (UTC)
From:      Nathan Whitehorn <nwhitehorn@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org
Subject:   svn commit: r184461 - in stable/7/sys: . dev/bm powerpc/include powerpc/powermac
Message-ID:  <200810300401.m9U41CMT040921@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: nwhitehorn
Date: Thu Oct 30 04:01:11 2008
New Revision: 184461
URL: http://svn.freebsd.org/changeset/base/184461

Log:
  MFC r183288,183411,183827,184382:
  
  Expand DBDMA API to allow setting device-dependent control bits and allow
  DBDMA registers to lie in a subregion of a resource.
  
  Also import changes to the BMAC driver to handle these changes and
  change the way we enable the BMAC cell in macio. Instead of calling the
  macio's enable-enet word, which apparently does nothing on some machines,
  open an OF instance of the ethernet controller. This fixes cold booting
  from disk on my Blue & White G3.
  
  Approved by:	re (gnn)

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/dev/bm/if_bm.c
  stable/7/sys/powerpc/include/dbdma.h
  stable/7/sys/powerpc/powermac/dbdma.c
  stable/7/sys/powerpc/powermac/dbdmavar.h

Modified: stable/7/sys/dev/bm/if_bm.c
==============================================================================
--- stable/7/sys/dev/bm/if_bm.c	Thu Oct 30 03:31:33 2008	(r184460)
+++ stable/7/sys/dev/bm/if_bm.c	Thu Oct 30 04:01:11 2008	(r184461)
@@ -488,9 +488,9 @@ bm_attach(device_t dev)
 		return (ENXIO);
 	}
 
-	error = dbdma_allocate_channel(sc->sc_txdmar, bus_get_dma_tag(dev),
+	error = dbdma_allocate_channel(sc->sc_txdmar, 0, bus_get_dma_tag(dev),
 	    BM_MAX_DMA_COMMANDS, &sc->sc_txdma);
-	error += dbdma_allocate_channel(sc->sc_rxdmar, bus_get_dma_tag(dev),
+	error += dbdma_allocate_channel(sc->sc_rxdmar, 0, bus_get_dma_tag(dev),
 	    BM_MAX_DMA_COMMANDS, &sc->sc_rxdma);
 
 	if (error) {
@@ -1119,21 +1119,25 @@ bm_chip_setup(struct bm_softc *sc)
 {
 	uint16_t reg;
 	uint16_t *eaddr_sect;
-	char hrow_path[128];
-	ihandle_t hrow_ih;
+	char path[128];
+	ihandle_t bmac_ih;
 
 	eaddr_sect = (uint16_t *)(sc->sc_enaddr);
 
-	/* Enable BMAC cell */
-	OF_package_to_path(OF_parent(ofw_bus_get_node(sc->sc_dev)),
-	    hrow_path, sizeof(hrow_path));
-	hrow_ih = OF_open(hrow_path);
-	if (hrow_ih == -1) {
+	/* 
+	 * Enable BMAC cell by opening and closing its OF node. This enables 
+	 * the cell in macio as a side effect. We should probably directly 
+	 * twiddle the FCR bits, but we lack a good interface for this at the
+	 * present time. 
+	 */
+
+	OF_package_to_path(ofw_bus_get_node(sc->sc_dev), path, sizeof(path));
+	bmac_ih = OF_open(path);
+	if (bmac_ih == -1) {
 		device_printf(sc->sc_dev,
 		    "Enabling BMAC cell failed! Hoping it's already active.\n");
 	} else {
-		OF_call_method("enable-enet", hrow_ih, 0, 0);
-		OF_close(hrow_ih);
+		OF_close(bmac_ih);
 	}
 
 	/* Reset chip */

Modified: stable/7/sys/powerpc/include/dbdma.h
==============================================================================
--- stable/7/sys/powerpc/include/dbdma.h	Thu Oct 30 03:31:33 2008	(r184460)
+++ stable/7/sys/powerpc/include/dbdma.h	Thu Oct 30 04:01:11 2008	(r184461)
@@ -78,15 +78,12 @@ typedef struct dbdma_command dbdma_comma
 struct dbdma_channel;
 typedef struct dbdma_channel dbdma_channel_t;
 
-int dbdma_allocate_channel(struct resource *dbdma_regs,
+int dbdma_allocate_channel(struct resource *dbdma_regs, u_int offset,
     bus_dma_tag_t parent_dma, int slots, dbdma_channel_t **chan);
 
 int dbdma_resize_channel(dbdma_channel_t *chan, int newslots);
 int dbdma_free_channel(dbdma_channel_t *chan);
 
-uint16_t dbdma_get_cmd_status(dbdma_channel_t *chan, int slot);
-uint16_t dbdma_get_residuals(dbdma_channel_t *chan, int slot);
-
 void dbdma_run(dbdma_channel_t *chan);
 void dbdma_stop(dbdma_channel_t *chan);
 void dbdma_reset(dbdma_channel_t *chan);
@@ -95,8 +92,43 @@ void dbdma_set_current_cmd(dbdma_channel
 void dbdma_pause(dbdma_channel_t *chan);
 void dbdma_wake(dbdma_channel_t *chan);
 
+/*
+ * DBDMA uses a 16 bit channel control register to describe the current
+ * state of DMA on the channel. The high-order bits (8-15) contain information
+ * on the run state and are listed in the DBDMA_STATUS_* constants above. These
+ * are manipulated with the dbdma_run/stop/reset() routines above.
+ *
+ * The low order bits (0-7) are device dependent status bits. These can be set
+ * and read by both hardware and software. The mask is the set of bits to 
+ * modify; if mask is 0x03 and value is 0, the lowest order 2 bits will be
+ * zeroed.
+ */
+
 uint16_t dbdma_get_chan_status(dbdma_channel_t *chan);
-uint8_t dbdma_get_chan_device_status(dbdma_channel_t *chan);
+
+uint8_t dbdma_get_device_status(dbdma_channel_t *chan);
+void dbdma_set_device_status(dbdma_channel_t *chan, uint8_t mask,
+    uint8_t value);
+
+/*
+ * Each DBDMA command word has the current channel status register and the
+ * number of residual bytes (requested - actually transferred) written to it
+ * at time of command completion.
+ */
+
+uint16_t dbdma_get_cmd_status(dbdma_channel_t *chan, int slot);
+uint16_t dbdma_get_residuals(dbdma_channel_t *chan, int slot);
+
+void dbdma_clear_cmd_status(dbdma_channel_t *chan, int slot);
+
+/*
+ * The interrupt/branch/wait selector let you specify a set of values
+ * of the device dependent status bits that will cause intterupt/branch/wait
+ * conditions to be taken if the flags for these are set to one of the 
+ * DBDMA_COND_* values.
+ * 
+ * The condition is considered true if (status & mask) == value.
+ */
 
 void dbdma_set_interrupt_selector(dbdma_channel_t *chan, uint8_t mask,
     uint8_t value);

Modified: stable/7/sys/powerpc/powermac/dbdma.c
==============================================================================
--- stable/7/sys/powerpc/powermac/dbdma.c	Thu Oct 30 03:31:33 2008	(r184460)
+++ stable/7/sys/powerpc/powermac/dbdma.c	Thu Oct 30 04:01:11 2008	(r184461)
@@ -56,8 +56,8 @@ dbdma_phys_callback(void *chan, bus_dma_
 }
 
 int
-dbdma_allocate_channel(struct resource *dbdma_regs, bus_dma_tag_t parent_dma,
-    int slots, dbdma_channel_t **chan)
+dbdma_allocate_channel(struct resource *dbdma_regs, u_int offset,
+    bus_dma_tag_t parent_dma, int slots, dbdma_channel_t **chan)
 {
 	int error = 0;
 	dbdma_channel_t *channel;
@@ -65,8 +65,8 @@ dbdma_allocate_channel(struct resource *
 	channel = *chan = malloc(sizeof(struct dbdma_channel), M_DBDMA, 
 	    M_WAITOK | M_ZERO);
 
-	channel->sc_bt = rman_get_bustag(dbdma_regs);
-	channel->sc_bh = rman_get_bushandle(dbdma_regs);
+	channel->sc_regs = dbdma_regs;
+	channel->sc_off = offset;
 	dbdma_stop(channel);
 
 	channel->sc_slots_pa = 0;
@@ -82,6 +82,8 @@ dbdma_allocate_channel(struct resource *
 	error = bus_dmamap_load(channel->sc_dmatag, channel->sc_dmamap,
 	    channel->sc_slots, PAGE_SIZE, dbdma_phys_callback, channel, 0);
 
+	dbdma_write_reg(channel, CHAN_CMDPTR_HI, 0);
+
 	channel->sc_nslots = slots;
 
 	return (error);
@@ -91,7 +93,7 @@ int
 dbdma_resize_channel(dbdma_channel_t *chan, int newslots)
 {
 
-	if (newslots > (PAGE_SIZE / 16))
+	if (newslots > (PAGE_SIZE / sizeof(struct dbdma_command)))
 		return (-1);
 	
 	chan->sc_nslots = newslots;
@@ -125,6 +127,13 @@ dbdma_get_cmd_status(dbdma_channel_t *ch
 	return (le16toh(chan->sc_slots[slot].resCount));
 }
 
+void
+dbdma_clear_cmd_status(dbdma_channel_t *chan, int slot)
+{
+	/* See endian note above */
+	chan->sc_slots[slot].resCount = 0;
+}
+
 uint16_t
 dbdma_get_residuals(dbdma_channel_t *chan, int slot)
 {
@@ -150,7 +159,8 @@ dbdma_run(dbdma_channel_t *chan)
 
 	control_reg = DBDMA_STATUS_RUN | DBDMA_STATUS_PAUSE |
 	    DBDMA_STATUS_WAKE | DBDMA_STATUS_DEAD;
-	control_reg <<= 16;
+	control_reg <<= DBDMA_REG_MASK_SHIFT;
+
 	control_reg |= DBDMA_STATUS_RUN;
 	dbdma_write_reg(chan, CHAN_CONTROL_REG, control_reg);
 }
@@ -161,7 +171,8 @@ dbdma_pause(dbdma_channel_t *chan)
 	uint32_t control_reg;
 
 	control_reg = DBDMA_STATUS_PAUSE;
-	control_reg <<= 16;
+	control_reg <<= DBDMA_REG_MASK_SHIFT;
+
 	control_reg |= DBDMA_STATUS_PAUSE;
 	dbdma_write_reg(chan, CHAN_CONTROL_REG, control_reg);
 }
@@ -173,7 +184,8 @@ dbdma_wake(dbdma_channel_t *chan)
 
 	control_reg = DBDMA_STATUS_WAKE | DBDMA_STATUS_PAUSE |
 	    DBDMA_STATUS_RUN | DBDMA_STATUS_DEAD;
-	control_reg <<= 16;
+	control_reg <<= DBDMA_REG_MASK_SHIFT;
+
 	control_reg |= DBDMA_STATUS_WAKE | DBDMA_STATUS_RUN;
 	dbdma_write_reg(chan, CHAN_CONTROL_REG, control_reg);
 }
@@ -184,7 +196,8 @@ dbdma_stop(dbdma_channel_t *chan)
 	uint32_t control_reg;
 
 	control_reg = DBDMA_STATUS_RUN;
-	control_reg <<= 16;
+	control_reg <<= DBDMA_REG_MASK_SHIFT;
+
 	dbdma_write_reg(chan, CHAN_CONTROL_REG, control_reg);
 
 	while (dbdma_read_reg(chan, CHAN_STATUS_REG) & DBDMA_STATUS_ACTIVE)
@@ -196,7 +209,7 @@ dbdma_set_current_cmd(dbdma_channel_t *c
 {
 	uint32_t cmd;
 
-	cmd = chan->sc_slots_pa + slot * 16;
+	cmd = chan->sc_slots_pa + slot * sizeof(struct dbdma_command);
 	dbdma_write_reg(chan, CHAN_CMDPTR, cmd);
 }
 
@@ -210,19 +223,31 @@ dbdma_get_chan_status(dbdma_channel_t *c
 }
 
 uint8_t
-dbdma_get_chan_device_status(dbdma_channel_t *chan)
+dbdma_get_device_status(dbdma_channel_t *chan)
 {
-
 	return (dbdma_get_chan_status(chan) & 0x00ff);
 }
 
 void
+dbdma_set_device_status(dbdma_channel_t *chan, uint8_t mask, uint8_t value)
+{
+	uint32_t control_reg;
+	
+	control_reg = mask;
+	control_reg <<= DBDMA_REG_MASK_SHIFT;
+	control_reg |= value;
+
+	dbdma_write_reg(chan, CHAN_CONTROL_REG, control_reg);
+}
+
+void
 dbdma_set_interrupt_selector(dbdma_channel_t *chan, uint8_t mask, uint8_t val)
 {
 	uint32_t intr_select;
 
 	intr_select = mask;
-	intr_select <<= 16;
+	intr_select <<= DBDMA_REG_MASK_SHIFT;
+
 	intr_select |= val;
 	dbdma_write_reg(chan, CHAN_INTR_SELECT, intr_select);
 }
@@ -233,7 +258,8 @@ dbdma_set_branch_selector(dbdma_channel_
 	uint32_t br_select;
 
 	br_select = mask;
-	br_select <<= 16;
+	br_select <<= DBDMA_REG_MASK_SHIFT;
+
 	br_select |= val;
 	dbdma_write_reg(chan, CHAN_BRANCH_SELECT, br_select);
 }
@@ -244,7 +270,7 @@ dbdma_set_wait_selector(dbdma_channel_t 
 	uint32_t wait_select;
 
 	wait_select = mask;
-	wait_select <<= 16;
+	wait_select <<= DBDMA_REG_MASK_SHIFT;
 	wait_select |= val;
 	dbdma_write_reg(chan, CHAN_WAIT_SELECT, wait_select);
 }
@@ -266,7 +292,8 @@ dbdma_insert_command(dbdma_channel_t *ch
 	cmd.reqCount = count;
 	cmd.address = (uint32_t)(data);
 	if (command != DBDMA_STORE_QUAD && command != DBDMA_LOAD_QUAD)
-		cmd.cmdDep = chan->sc_slots_pa + branch_slot * 16;
+		cmd.cmdDep = chan->sc_slots_pa + 
+		    branch_slot * sizeof(struct dbdma_command);
 	else
 		cmd.cmdDep = branch_slot;
 
@@ -320,12 +347,12 @@ static uint32_t
 dbdma_read_reg(dbdma_channel_t *chan, u_int offset)
 {
 
-	return (bus_space_read_4(chan->sc_bt, chan->sc_bh, offset));
+	return (bus_read_4(chan->sc_regs, chan->sc_off + offset));
 }
 
 static void
 dbdma_write_reg(dbdma_channel_t *chan, u_int offset, uint32_t val)
 {
 
-	bus_space_write_4(chan->sc_bt, chan->sc_bh, offset, val);
+	bus_write_4(chan->sc_regs, chan->sc_off + offset, val);
 }

Modified: stable/7/sys/powerpc/powermac/dbdmavar.h
==============================================================================
--- stable/7/sys/powerpc/powermac/dbdmavar.h	Thu Oct 30 03:31:33 2008	(r184460)
+++ stable/7/sys/powerpc/powermac/dbdmavar.h	Thu Oct 30 04:01:11 2008	(r184461)
@@ -51,8 +51,8 @@ struct dbdma_command {
 };
 
 struct dbdma_channel {
-	bus_space_tag_t		sc_bt;
-	bus_space_handle_t	sc_bh;
+	struct resource 	*sc_regs;
+	u_int			sc_off;
 
 	struct dbdma_command	*sc_slots;
 	int			sc_nslots;
@@ -78,6 +78,7 @@ struct dbdma_channel {
 
 #define CHAN_CONTROL_REG	0x00
 #define	CHAN_STATUS_REG		0x04
+#define CHAN_CMDPTR_HI		0x08
 #define CHAN_CMDPTR		0x0C
 #define	CHAN_INTR_SELECT	0x10
 #define CHAN_BRANCH_SELECT	0x14
@@ -86,6 +87,8 @@ struct dbdma_channel {
 /* Channel control is the write channel to channel status, the upper 16 bits
    are a mask of which bytes to change */
 
+#define	DBDMA_REG_MASK_SHIFT	16
+
 /* Status bits 0-7 are device dependent status bits */
 
 /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200810300401.m9U41CMT040921>