svn commit: r184461 - in stable/7/sys: . dev/bm powerpc/include
powerpc/powermac
Nathan Whitehorn
nwhitehorn at FreeBSD.org
Wed Oct 29 21:01:12 PDT 2008
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 */
/*
More information about the svn-src-all
mailing list