From owner-svn-src-stable-7@FreeBSD.ORG Thu Oct 30 04:01:12 2008 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7C0F41065673; Thu, 30 Oct 2008 04:01:12 +0000 (UTC) (envelope-from nwhitehorn@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 606C38FC0A; Thu, 30 Oct 2008 04:01:12 +0000 (UTC) (envelope-from nwhitehorn@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9U41CmY040926; Thu, 30 Oct 2008 04:01:12 GMT (envelope-from nwhitehorn@svn.freebsd.org) Received: (from nwhitehorn@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9U41CMT040921; Thu, 30 Oct 2008 04:01:12 GMT (envelope-from nwhitehorn@svn.freebsd.org) Message-Id: <200810300401.m9U41CMT040921@svn.freebsd.org> From: Nathan Whitehorn Date: Thu, 30 Oct 2008 04:01:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184461 - in stable/7/sys: . dev/bm powerpc/include powerpc/powermac X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 30 Oct 2008 04:01:12 -0000 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 */ /*