From owner-svn-src-user@FreeBSD.ORG Mon Apr 12 23:16:17 2010 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 07B45106566B; Mon, 12 Apr 2010 23:16:17 +0000 (UTC) (envelope-from imp@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id EA8F28FC13; Mon, 12 Apr 2010 23:16:16 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o3CNGGiX070584; Mon, 12 Apr 2010 23:16:16 GMT (envelope-from imp@svn.freebsd.org) Received: (from imp@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o3CNGG2t070577; Mon, 12 Apr 2010 23:16:16 GMT (envelope-from imp@svn.freebsd.org) Message-Id: <201004122316.o3CNGG2t070577@svn.freebsd.org> From: Warner Losh Date: Mon, 12 Apr 2010 23:16:16 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r206525 - in user/imp/tbemd/sys/mips: atheros cavium cavium/dev/rgmii conf include mips sibyte X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 12 Apr 2010 23:16:17 -0000 Author: imp Date: Mon Apr 12 23:16:16 2010 New Revision: 206525 URL: http://svn.freebsd.org/changeset/base/206525 Log: merge from head, part 10 of many Modified: user/imp/tbemd/sys/mips/atheros/if_arge.c user/imp/tbemd/sys/mips/cavium/dev/rgmii/octeon_rgmx.c user/imp/tbemd/sys/mips/cavium/octeon_ebt3000_cf.c user/imp/tbemd/sys/mips/cavium/octeon_machdep.c user/imp/tbemd/sys/mips/cavium/octeon_pcmap_regs.h user/imp/tbemd/sys/mips/conf/AR71XX user/imp/tbemd/sys/mips/conf/OCTEON1 user/imp/tbemd/sys/mips/conf/OCTEON1-32 user/imp/tbemd/sys/mips/include/bus.h user/imp/tbemd/sys/mips/include/clock.h user/imp/tbemd/sys/mips/include/cpu.h user/imp/tbemd/sys/mips/include/cpufunc.h user/imp/tbemd/sys/mips/include/cpuregs.h user/imp/tbemd/sys/mips/include/db_machdep.h user/imp/tbemd/sys/mips/include/kdb.h user/imp/tbemd/sys/mips/include/param.h user/imp/tbemd/sys/mips/include/pmap.h user/imp/tbemd/sys/mips/include/smp.h user/imp/tbemd/sys/mips/include/trap.h user/imp/tbemd/sys/mips/mips/busdma_machdep.c user/imp/tbemd/sys/mips/mips/db_trace.c user/imp/tbemd/sys/mips/mips/exception.S user/imp/tbemd/sys/mips/mips/mp_machdep.c user/imp/tbemd/sys/mips/mips/nexus.c user/imp/tbemd/sys/mips/mips/pm_machdep.c user/imp/tbemd/sys/mips/mips/pmap.c user/imp/tbemd/sys/mips/mips/support.S user/imp/tbemd/sys/mips/mips/swtch.S user/imp/tbemd/sys/mips/mips/tick.c user/imp/tbemd/sys/mips/mips/trap.c user/imp/tbemd/sys/mips/mips/vm_machdep.c user/imp/tbemd/sys/mips/sibyte/sb_asm.S user/imp/tbemd/sys/mips/sibyte/sb_machdep.c user/imp/tbemd/sys/mips/sibyte/sb_scd.c user/imp/tbemd/sys/mips/sibyte/sb_scd.h Modified: user/imp/tbemd/sys/mips/atheros/if_arge.c ============================================================================== --- user/imp/tbemd/sys/mips/atheros/if_arge.c Mon Apr 12 23:16:01 2010 (r206524) +++ user/imp/tbemd/sys/mips/atheros/if_arge.c Mon Apr 12 23:16:16 2010 (r206525) @@ -171,7 +171,7 @@ extern uint32_t ar711_base_mac[ETHER_ADD static struct mtx miibus_mtx; -MTX_SYSINIT(miibus_mtx, &miibus_mtx, "arge mii lock", MTX_SPIN); +MTX_SYSINIT(miibus_mtx, &miibus_mtx, "arge mii lock", MTX_DEF); /* Modified: user/imp/tbemd/sys/mips/cavium/dev/rgmii/octeon_rgmx.c ============================================================================== --- user/imp/tbemd/sys/mips/cavium/dev/rgmii/octeon_rgmx.c Mon Apr 12 23:16:01 2010 (r206524) +++ user/imp/tbemd/sys/mips/cavium/dev/rgmii/octeon_rgmx.c Mon Apr 12 23:16:16 2010 (r206525) @@ -136,7 +136,6 @@ struct rgmx_softc_dev { u_int idx; u_char ieee[6]; - char const * typestr; /* printable name of the interface. */ u_short txb_size; /* size of TX buffer, in bytes */ /* Transmission buffer management. */ @@ -182,7 +181,6 @@ static u_int get_rgmx_port_ordinal(u_int static void octeon_rgmx_set_mac(u_int port); static void octeon_rgmx_init_sc(struct rgmx_softc_dev *sc, device_t dev, u_int port, u_int num_devices); static int octeon_rgmx_init_ifnet(struct rgmx_softc_dev *sc); -static void octeon_rgmx_mark_ready(struct rgmx_softc_dev *sc); static void octeon_rgmx_stop(struct rgmx_softc_dev *sc); static void octeon_rgmx_config_speed(u_int port, u_int); #ifdef DEBUG_RGMX_DUMP @@ -211,6 +209,7 @@ static int octeon_rgmx_intr(void *arg); /* Standard driver entry points. These can be static. */ static void octeon_rgmx_init (void *); //static driver_intr_t rgmx_intr; +static void octeon_rgmx_config_cam (struct ifnet *); static int octeon_rgmx_ioctl (struct ifnet *, u_long, caddr_t); static void octeon_rgmx_output_start (struct ifnet *); static void octeon_rgmx_output_start_locked (struct ifnet *); @@ -349,8 +348,6 @@ static int octeon_rgmx_init_ifnet (struc ifmedia_set(&sc->media, bit2media[0]); ether_ifattach(sc->ifp, sc->ieee); - /* Print additional info when attached. */ - device_printf(sc->sc_dev, "type %s, full duplex\n", sc->typestr); return (0); } @@ -447,12 +444,6 @@ static int rgmii_attach (device_t dev) device_printf(dev, " ifinit failed for rgmx port %u\n", port); return (ENOSPC); } -/* - * Don't call octeon_rgmx_mark_ready() - * ifnet will call it indirectly via octeon_rgmx_init() - * - * octeon_rgmx_mark_ready(sc); - */ num_devices++; } } @@ -1024,10 +1015,9 @@ static u_int octeon_rgmx_pko_xmit_packet * 3 words or less are left. We write our 2nd word now and then put in a chain link * to new PKO cmd buf. */ - void *pko_cmd_buf = octeon_fpa_alloc(OCTEON_FPA_TX_CMDBUF_POOL); - uint64_t phys_cmd_buf; + uint64_t phys_cmd_buf = octeon_fpa_alloc_phys(OCTEON_FPA_TX_CMDBUF_POOL); - if (!pko_cmd_buf) { + if (!phys_cmd_buf) { /* * FPA pool for xmit-buffer-commands is empty. */ @@ -1035,7 +1025,6 @@ static u_int octeon_rgmx_pko_xmit_packet octeon_spinlock_unlock(&(sc->outq_ptr[queue].lock)); return (0); } - phys_cmd_buf = OCTEON_PTR2PHYS(pko_cmd_buf); xmit_cmd_ptr[1] = pko_pkt_word.word64; xmit_cmd_ptr[2] = phys_cmd_buf; @@ -1235,6 +1224,8 @@ static void octeon_rgmx_output_start_loc for (ii = 0; ii < len; ii++) printf(" %X", dc[ii]); printf("\n"); #endif + ETHER_BPF_MTAP(ifp, m); + IF_ENQUEUE(&sc->tx_pending_queue, m); /* @@ -1648,9 +1639,106 @@ static int octeon_rgmx_medchange (struct static void octeon_rgmx_medstat (struct ifnet *ifp, struct ifmediareq *ifm) { - /* - * No support for Media Status callback - */ + struct rgmx_softc_dev *sc = ifp->if_softc; + octeon_rgmx_rxx_rx_inbnd_t link_status; + + octeon_rgmx_config_speed(sc->port, 1); + + RGMX_LOCK(sc); + + ifm->ifm_status = IFM_AVALID; + ifm->ifm_active = IFM_ETHER; + + /* + * Parse link status. + */ + link_status.word64 = sc->link_status; + + if (!link_status.bits.status) { + RGMX_UNLOCK(sc); + return; + } + + ifm->ifm_status |= IFM_ACTIVE; + + switch (link_status.bits.speed) { + case 0: + ifm->ifm_active |= IFM_10_T; + break; + case 1: + ifm->ifm_active |= IFM_100_TX; + break; + case 2: + ifm->ifm_active |= IFM_1000_T;; + break; + default: + /* Unknown! */ + break; + } + + /* + * Check duplex. + */ + if (link_status.bits.duplex == 1) + ifm->ifm_active |= IFM_FDX; + else + ifm->ifm_active |= IFM_HDX; + + RGMX_UNLOCK(sc); +} + +static void octeon_rgmx_config_cam(struct ifnet *ifp) +{ + struct rgmx_softc_dev *sc = ifp->if_softc; + u_int port = sc->port; + int index = INDEX(port); + int iface = INTERFACE(port); + u_int last_enabled; + uint64_t adr_ctl; + + last_enabled = octeon_rgmx_stop_port(port); + + adr_ctl = oct_read64(OCTEON_RGMX_RXX_ADR_CTL(index, iface)); + + /* + * Always accept broadcast traffic. + */ + if ((adr_ctl & OCTEON_RGMX_ADRCTL_ACCEPT_BROADCAST) == 0) + adr_ctl |= OCTEON_RGMX_ADRCTL_ACCEPT_BROADCAST; + + /* + * Accept all multicast in all multicast mode and in + * promiscuous mode. + * + * XXX Since we don't handle programming the CAM for + * multicast filtering, always accept all multicast. + */ + adr_ctl &= ~OCTEON_RGMX_ADRCTL_REJECT_ALL_MULTICAST; + adr_ctl |= OCTEON_RGMX_ADRCTL_ACCEPT_ALL_MULTICAST; + + /* + * In promiscuous mode, the CAM is shut off, so reject everything. + * Otherwise, filter using the CAM. + */ + if ((ifp->if_flags & IFF_PROMISC) != 0) { + adr_ctl &= ~OCTEON_RGMX_ADRCTL_CAM_MODE_ACCEPT_DMAC; + adr_ctl |= OCTEON_RGMX_ADRCTL_CAM_MODE_REJECT_DMAC; + } else { + adr_ctl &= ~OCTEON_RGMX_ADRCTL_CAM_MODE_REJECT_DMAC; + adr_ctl |= OCTEON_RGMX_ADRCTL_CAM_MODE_ACCEPT_DMAC; + } + + oct_write64(OCTEON_RGMX_RXX_ADR_CTL(index, iface), adr_ctl); + + /* + * If in promiscuous mode, disable the CAM. + */ + if ((ifp->if_flags & IFF_PROMISC) != 0) + oct_write64(OCTEON_RGMX_RXX_ADR_CAM_EN(index, iface), 0); + else + oct_write64(OCTEON_RGMX_RXX_ADR_CAM_EN(index, iface), 1); + + if (last_enabled) octeon_rgmx_start_port(port); } static int octeon_rgmx_ioctl (struct ifnet * ifp, u_long command, caddr_t data) @@ -1671,28 +1759,21 @@ static int octeon_rgmx_ioctl (struct ifn * "stopped", reflecting the UP flag. */ if (ifp->if_flags & IFF_UP) { - - /* * New state is IFF_UP * Restart or Start now, if driver is not running currently. */ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { - printf(" SIOCSTIFFLAGS UP/Not-running\n"); break; octeon_rgmx_init(sc); - } else { - printf(" SIOCSTIFFLAGS UP/Running\n"); break; } + octeon_rgmx_config_cam(ifp); } else { /* * New state is IFF_DOWN. * Stop & shut it down now, if driver is running currently. */ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { - printf(" SIOCSTIFFLAGS Down/Running\n"); break; octeon_rgmx_stop(sc); - } else { - printf(" SIOCSTIFFLAGS Down/Not-Running\n"); break; } } break; @@ -1734,17 +1815,9 @@ static int octeon_rgmx_ioctl (struct ifn return (error); } - - - -/* - * octeon_rgmx_mark_ready - * - * Initialize the rgmx driver for this instance - * Initialize device. - */ -static void octeon_rgmx_mark_ready (struct rgmx_softc_dev *sc) +static void octeon_rgmx_init (void *xsc) { + struct rgmx_softc_dev *sc = xsc; /* Enable interrupts. */ /* For RGMX they are already enabled earlier */ @@ -1763,21 +1836,9 @@ static void octeon_rgmx_mark_ready (stru /* Kick start the output */ /* Hopefully PKO is running and will pick up packets via the timer or receive loop */ -} - -static void octeon_rgmx_init (void *xsc) -{ - - /* - * Called mostly from ifnet interface ifp->if_init(); - * I think we can anchor most of our iniialization here and - * not do it in different places from driver_attach(). - */ - /* - * For now, we only mark the interface ready - */ - octeon_rgmx_mark_ready((struct rgmx_softc_dev *) xsc); + /* Set link status. */ + octeon_rgmx_config_speed(sc->port, 1); } @@ -1792,7 +1853,6 @@ static void octeon_rgmx_config_speed (u_ uint64_t val64_tx_clk, val64_tx_slot, val64_tx_burst; u_int last_enabled; - sc = get_rgmx_softc(port); if (!sc) { printf(" config_speed didn't find sc int:%u port:%u", iface, port); @@ -1804,79 +1864,96 @@ static void octeon_rgmx_config_speed (u_ */ link_status.word64 = oct_read64(OCTEON_RGMX_RXX_RX_INBND(index, iface)); + RGMX_LOCK(sc); + /* * Compre to prev known state. If same then nothing to do. */ if (link_status.word64 == sc->link_status) { + RGMX_UNLOCK(sc); return; } - - RGMX_LOCK(sc); - old_link_status.word64 = sc->link_status; - sc->link_status = link_status.word64; - - last_enabled = octeon_rgmx_stop_port(port); - - gmx_cfg.word64 = oct_read64(OCTEON_RGMX_PRTX_CFG(index, iface)); - - /* - * Duplex - */ - gmx_cfg.bits.duplex = 1; - - switch (link_status.bits.speed) { - case 0: /* 10Mbps */ - gmx_cfg.bits.speed = 0; - gmx_cfg.bits.slottime = 0; - val64_tx_clk = 50; val64_tx_slot = 0x40; val64_tx_burst = 0; - break; - case 1: /* 100Mbps */ - gmx_cfg.bits.speed = 0; - gmx_cfg.bits.slottime = 0; - val64_tx_clk = 5; val64_tx_slot = 0x40; val64_tx_burst = 0; - break; - - case 2: /* 1Gbps */ - gmx_cfg.bits.speed = 1; - gmx_cfg.bits.slottime = 1; - val64_tx_clk = 1; val64_tx_slot = 0x200; val64_tx_burst = 0x2000; - break; - - case 3: /* ?? */ - default: - gmx_cfg.bits.speed = 1; - gmx_cfg.bits.slottime = 1; - val64_tx_clk = 1; val64_tx_slot = 0x200; val64_tx_burst = 0x2000; - break; - } + /* + * Compare to previous state modulo link status. If only link + * status is different, we don't need to change media. + */ + if (old_link_status.bits.duplex != link_status.bits.duplex || + old_link_status.bits.speed != link_status.bits.speed) { + last_enabled = octeon_rgmx_stop_port(port); + + gmx_cfg.word64 = oct_read64(OCTEON_RGMX_PRTX_CFG(index, iface)); - oct_write64(OCTEON_RGMX_TXX_CLK(index, iface), val64_tx_clk); - oct_write64(OCTEON_RGMX_TXX_SLOT(index, iface), val64_tx_slot); - oct_write64(OCTEON_RGMX_TXX_BURST(index, iface), val64_tx_burst); + /* + * Duplex + * XXX Set based on link_status.bits.duplex? + */ + gmx_cfg.bits.duplex = 1; + + switch (link_status.bits.speed) { + case 0: /* 10Mbps */ + gmx_cfg.bits.speed = 0; + gmx_cfg.bits.slottime = 0; + val64_tx_clk = 50; val64_tx_slot = 0x40; val64_tx_burst = 0; + break; + + case 1: /* 100Mbps */ + gmx_cfg.bits.speed = 0; + gmx_cfg.bits.slottime = 0; + val64_tx_clk = 5; val64_tx_slot = 0x40; val64_tx_burst = 0; + break; + + case 2: /* 1Gbps */ + gmx_cfg.bits.speed = 1; + gmx_cfg.bits.slottime = 1; + val64_tx_clk = 1; val64_tx_slot = 0x200; val64_tx_burst = 0x2000; + break; + + case 3: /* ?? */ + default: + gmx_cfg.bits.speed = 1; + gmx_cfg.bits.slottime = 1; + val64_tx_clk = 1; val64_tx_slot = 0x200; val64_tx_burst = 0x2000; + break; + } - oct_write64(OCTEON_RGMX_PRTX_CFG(index, iface), gmx_cfg.word64); + oct_write64(OCTEON_RGMX_TXX_CLK(index, iface), val64_tx_clk); + oct_write64(OCTEON_RGMX_TXX_SLOT(index, iface), val64_tx_slot); + oct_write64(OCTEON_RGMX_TXX_BURST(index, iface), val64_tx_burst); + + oct_write64(OCTEON_RGMX_PRTX_CFG(index, iface), gmx_cfg.word64); + + if (last_enabled) octeon_rgmx_start_port(port); + } - if (last_enabled) octeon_rgmx_start_port(port); + /* + * Now check and possibly change link status. + */ + if (link_status.bits.status != old_link_status.bits.status) { + if (report_link) { + if (link_status.bits.status) { + if_link_state_change(sc->ifp, LINK_STATE_UP); + } else { + if_link_state_change(sc->ifp, LINK_STATE_DOWN); + } + } + } - if (link_status.bits.status != old_link_status.bits.status) { + if (report_link) { + sc->link_status = link_status.word64; + } else { + /* + * We can't update link status proper since we can't + * change it in the interface, so keep the old link + * status intact but note the current speed and duplex + * settings. + */ + link_status.bits.status = old_link_status.bits.status; + sc->link_status = link_status.word64; + } -//#define DEBUG_LINESTATUS - if (link_status.bits.status) { -#ifdef DEBUG_LINESTATUS - printf(" %u/%u: Interface is now alive\n", iface, port); -#endif - if (report_link) if_link_state_change(sc->ifp, LINK_STATE_UP); - } else { -#ifdef DEBUG_LINESTATUS - printf(" %u/%u: Interface went down\n", iface, port); -#endif - if (report_link) if_link_state_change(sc->ifp, LINK_STATE_DOWN); - } - } RGMX_UNLOCK(sc); - } @@ -2096,7 +2173,6 @@ static void octeon_config_rgmii_port (u_ gmx_cfg.bits.en = 1; oct_write64(OCTEON_RGMX_PRTX_CFG(index, iface), gmx_cfg.word64); - octeon_rgmx_config_speed(port, 0); oct_write64(OCTEON_RGMX_TXX_THRESH(index, iface), 32); @@ -2181,7 +2257,7 @@ static int octeon_has_4ports (void) u_int chipid; int retcode = 1; - chipid = octeon_get_chipid() & 0xffffff00; + chipid = octeon_get_chipid(); switch (chipid) { case OCTEON_CN31XX_CHIP: Modified: user/imp/tbemd/sys/mips/cavium/octeon_ebt3000_cf.c ============================================================================== --- user/imp/tbemd/sys/mips/cavium/octeon_ebt3000_cf.c Mon Apr 12 23:16:01 2010 (r206524) +++ user/imp/tbemd/sys/mips/cavium/octeon_ebt3000_cf.c Mon Apr 12 23:16:16 2010 (r206525) @@ -89,6 +89,7 @@ __FBSDID("$FreeBSD$"); /* Status Register */ #define STATUS_BSY 0x80 /* Drive is busy */ #define STATUS_RDY 0x40 /* Drive is ready */ +#define STATUS_DF 0x20 /* Device fault */ #define STATUS_DRQ 0x08 /* Data can be transferred */ /* Miscelaneous */ @@ -153,11 +154,11 @@ static int cf_attach(device_t); static int cf_attach_geom(void *, int); /* ATA methods */ -static void cf_cmd_identify(void); -static void cf_cmd_write(uint32_t, uint32_t, void *); -static void cf_cmd_read(uint32_t, uint32_t, void *); -static void cf_wait_busy(void); -static void cf_send_cmd(uint32_t, uint8_t); +static int cf_cmd_identify(void); +static int cf_cmd_write(uint32_t, uint32_t, void *); +static int cf_cmd_read(uint32_t, uint32_t, void *); +static int cf_wait_busy(void); +static int cf_send_cmd(uint32_t, uint8_t); static void cf_attach_geom_proxy(void *arg, int flag); /* Miscelenous */ @@ -183,6 +184,8 @@ static int cf_access (struct g_provider * ------------------------------------------------------------------- */ static void cf_start (struct bio *bp) { + int error; + /* * Handle actual I/O requests. The request is passed down through * the bio struct. @@ -200,12 +203,19 @@ static void cf_start (struct bio *bp) if ((bp->bio_cmd & (BIO_READ | BIO_WRITE))) { if (bp->bio_cmd & BIO_READ) { - cf_cmd_read(bp->bio_length / drive_param.sector_size, - bp->bio_offset / drive_param.sector_size, bp->bio_data); - + error = cf_cmd_read(bp->bio_length / drive_param.sector_size, + bp->bio_offset / drive_param.sector_size, bp->bio_data); } else if (bp->bio_cmd & BIO_WRITE) { - cf_cmd_write(bp->bio_length / drive_param.sector_size, - bp->bio_offset/drive_param.sector_size, bp->bio_data); + error = cf_cmd_write(bp->bio_length / drive_param.sector_size, + bp->bio_offset/drive_param.sector_size, bp->bio_data); + } else { + printf("%s: unrecognized bio_cmd %x.\n", __func__, bp->bio_cmd); + error = ENOTSUP; + } + + if (error != 0) { + g_io_deliver(bp, error); + return; } bp->bio_resid = 0; @@ -227,12 +237,13 @@ static int cf_ioctl (struct g_provider * * * Read nr_sectors from the device starting from start_sector. */ -static void cf_cmd_read (uint32_t nr_sectors, uint32_t start_sector, void *buf) +static int cf_cmd_read (uint32_t nr_sectors, uint32_t start_sector, void *buf) { unsigned long lba; uint32_t count; uint16_t *ptr_16; uint8_t *ptr_8; + int error; //#define OCTEON_VISUAL_CF_0 1 #ifdef OCTEON_VISUAL_CF_0 @@ -244,8 +255,11 @@ static void cf_cmd_read (uint32_t nr_sec while (nr_sectors--) { - - cf_send_cmd(lba, CMD_READ_SECTOR); + error = cf_send_cmd(lba, CMD_READ_SECTOR); + if (error != 0) { + printf("%s: cf_send_cmd(CMD_READ_SECTOR) failed: %d\n", __func__, error); + return (error); + } if (bus_width == 8) { volatile uint8_t *task_file = (volatile uint8_t*)base_addr; @@ -270,6 +284,7 @@ static void cf_cmd_read (uint32_t nr_sec #ifdef OCTEON_VISUAL_CF_0 octeon_led_write_char(0, ' '); #endif + return (0); } @@ -279,12 +294,13 @@ static void cf_cmd_read (uint32_t nr_sec * * Write nr_sectors to the device starting from start_sector. */ -static void cf_cmd_write (uint32_t nr_sectors, uint32_t start_sector, void *buf) +static int cf_cmd_write (uint32_t nr_sectors, uint32_t start_sector, void *buf) { uint32_t lba; uint32_t count; uint16_t *ptr_16; uint8_t *ptr_8; + int error; //#define OCTEON_VISUAL_CF_1 1 #ifdef OCTEON_VISUAL_CF_1 @@ -295,8 +311,11 @@ static void cf_cmd_write (uint32_t nr_se ptr_16 = (uint16_t*)buf; while (nr_sectors--) { - - cf_send_cmd(lba, CMD_WRITE_SECTOR); + error = cf_send_cmd(lba, CMD_WRITE_SECTOR); + if (error != 0) { + printf("%s: cf_send_cmd(CMD_WRITE_SECTOR) failed: %d\n", __func__, error); + return (error); + } if (bus_width == 8) { volatile uint8_t *task_file; @@ -324,6 +343,7 @@ static void cf_cmd_write (uint32_t nr_se #ifdef OCTEON_VISUAL_CF_1 octeon_led_write_char(1, ' '); #endif + return (0); } @@ -335,10 +355,11 @@ static void cf_cmd_write (uint32_t nr_se * it in the drive_param structure * */ -static void cf_cmd_identify (void) +static int cf_cmd_identify (void) { int count; uint8_t status; + int error; if (bus_width == 8) { volatile uint8_t *task_file; @@ -356,11 +377,11 @@ static void cf_cmd_identify (void) task_file[TF_DRV_HEAD] = 0; task_file[TF_COMMAND] = CMD_IDENTIFY; - cf_wait_busy(); - - for (count = 0; count < SECTOR_SIZE; count++) - drive_param.u.buf[count] = task_file[TF_DATA]; - + error = cf_wait_busy(); + if (error == 0) { + for (count = 0; count < SECTOR_SIZE; count++) + drive_param.u.buf[count] = task_file[TF_DATA]; + } } else { volatile uint16_t *task_file; @@ -374,17 +395,22 @@ static void cf_cmd_identify (void) task_file[TF_CYL_LSB/2] = 0; /* this includes TF_CYL_MSB */ task_file[TF_DRV_HEAD/2] = 0 | (CMD_IDENTIFY<<8); /* this includes TF_COMMAND */ - cf_wait_busy(); - - for (count = 0; count < SECTOR_SIZE; count+=2) { - uint16_t temp; - temp = task_file[TF_DATA]; - - /* endianess will be swapped below */ - drive_param.u.buf[count] = (temp & 0xff); - drive_param.u.buf[count+1] = (temp & 0xff00)>>8; + error = cf_wait_busy(); + if (error == 0) { + for (count = 0; count < SECTOR_SIZE; count+=2) { + uint16_t temp; + temp = task_file[TF_DATA]; + + /* endianess will be swapped below */ + drive_param.u.buf[count] = (temp & 0xff); + drive_param.u.buf[count+1] = (temp & 0xff00)>>8; + } } } + if (error != 0) { + printf("%s: identify failed: %d\n", __func__, error); + return (error); + } cf_swap_ascii(drive_param.u.driveid.model, drive_param.model); @@ -394,6 +420,7 @@ static void cf_cmd_identify (void) drive_param.sec_track = SWAP_SHORT (drive_param.u.driveid.cur_sectors); drive_param.nr_sectors = SWAP_LONG (drive_param.u.driveid.lba_capacity); + return (0); } @@ -404,7 +431,7 @@ static void cf_cmd_identify (void) * Send command to read/write one sector specified by lba. * */ -static void cf_send_cmd (uint32_t lba, uint8_t cmd) +static int cf_send_cmd (uint32_t lba, uint8_t cmd) { uint8_t status; @@ -439,7 +466,7 @@ static void cf_send_cmd (uint32_t lba, u } - cf_wait_busy(); + return (cf_wait_busy()); } /* ------------------------------------------------------------------- * @@ -448,12 +475,16 @@ static void cf_send_cmd (uint32_t lba, u * * Wait until the drive finishes a given command and data is * ready to be transferred. This is done by repeatedly checking - * the BSY and DRQ bits of the status register. When the controller - * is ready for data transfer, it clears the BSY bit and sets the - * DRQ bit. + * the BSY bit of the status register. When the controller is ready for + * data transfer, it clears the BSY bit and sets the DRQ bit. + * + * If the DF bit is ever set, we return error. * + * This code originally spun on DRQ. If that behavior turns out to be + * necessary, a flag can be added or this function can be called + * repeatedly as long as it is returning ENXIO. */ -static void cf_wait_busy (void) +static int cf_wait_busy (void) { uint8_t status; @@ -469,7 +500,11 @@ static void cf_wait_busy (void) task_file = (volatile uint8_t *)base_addr; status = task_file[TF_STATUS]; - while ((status & STATUS_BSY) == STATUS_BSY || (status & STATUS_DRQ) != STATUS_DRQ ) { + while ((status & STATUS_BSY) == STATUS_BSY) { + if ((status & STATUS_DF) != 0) { + printf("%s: device fault (status=%x)\n", __func__, status); + return (EIO); + } DELAY(WAIT_DELAY); status = task_file[TF_STATUS]; } @@ -478,15 +513,24 @@ static void cf_wait_busy (void) task_file = (volatile uint16_t *)base_addr; status = task_file[TF_STATUS/2]>>8; - while ((status & STATUS_BSY) == STATUS_BSY || (status & STATUS_DRQ) != STATUS_DRQ ) { + while ((status & STATUS_BSY) == STATUS_BSY) { + if ((status & STATUS_DF) != 0) { + printf("%s: device fault (status=%x)\n", __func__, status); + return (EIO); + } DELAY(WAIT_DELAY); status = (uint8_t)(task_file[TF_STATUS/2]>>8); } } + if ((status & STATUS_DRQ) == 0) { + printf("%s: device not ready (status=%x)\n", __func__, status); + return (ENXIO); + } #ifdef OCTEON_VISUAL_CF_2 octeon_led_write_char(2, ' '); #endif + return (0); } /* ------------------------------------------------------------------- * @@ -522,9 +566,7 @@ static int cf_probe (device_t dev) device_set_desc(dev, "Octeon Compact Flash Driver"); - cf_cmd_identify(); - - return (0); + return (cf_cmd_identify()); } /* ------------------------------------------------------------------- * @@ -543,7 +585,6 @@ static void cf_identify (driver_t *drv, int count = 0; octeon_mio_boot_reg_cfgx_t cfg; - if (!octeon_board_real()) return; Modified: user/imp/tbemd/sys/mips/cavium/octeon_machdep.c ============================================================================== --- user/imp/tbemd/sys/mips/cavium/octeon_machdep.c Mon Apr 12 23:16:01 2010 (r206524) +++ user/imp/tbemd/sys/mips/cavium/octeon_machdep.c Mon Apr 12 23:16:16 2010 (r206525) @@ -730,8 +730,6 @@ platform_start(__register_t a0, __regist { uint64_t platform_counter_freq; - boothowto |= RB_SINGLE; - /* Initialize pcpu stuff */ mips_pcpu0_init(); mips_timer_early_init(OCTEON_CLOCK_DEFAULT); @@ -873,8 +871,9 @@ int octeon_chip_rev_major = 0, octeon_ch static octeon_boot_descriptor_t *app_desc_ptr; static cvmx_bootinfo_t *cvmx_desc_ptr; -#define OCTEON_BOARD_TYPE_NONE 0 -#define OCTEON_BOARD_TYPE_SIM 1 +#define OCTEON_BOARD_TYPE_NONE 0 +#define OCTEON_BOARD_TYPE_SIM 1 +#define OCTEON_BOARD_TYPE_CN3010_EVB_HS5 11 #define OCTEON_CLOCK_MIN (100 * 1000 * 1000) #define OCTEON_CLOCK_MAX (800 * 1000 * 1000) @@ -886,11 +885,23 @@ static cvmx_bootinfo_t *cvmx_desc_ptr; int octeon_board_real(void) { - if ((octeon_board_type == OCTEON_BOARD_TYPE_NONE) || - (octeon_board_type == OCTEON_BOARD_TYPE_SIM) || - !octeon_board_rev_major) + switch (octeon_board_type) { + case OCTEON_BOARD_TYPE_NONE: + case OCTEON_BOARD_TYPE_SIM: return 0; - return 1; + case OCTEON_BOARD_TYPE_CN3010_EVB_HS5: + /* + * XXX + * The CAM-0100 identifies itself as type 11, revision 0.0, + * despite its being rather real. Disable the revision check + * for type 11. + */ + return 1; + default: + if (octeon_board_rev_major == 0) + return 0; + return 1; + } } static void Modified: user/imp/tbemd/sys/mips/cavium/octeon_pcmap_regs.h ============================================================================== --- user/imp/tbemd/sys/mips/cavium/octeon_pcmap_regs.h Mon Apr 12 23:16:01 2010 (r206524) +++ user/imp/tbemd/sys/mips/cavium/octeon_pcmap_regs.h Mon Apr 12 23:16:16 2010 (r206525) @@ -90,350 +90,228 @@ extern struct pcpu *cpuid_to_pcpu[]; #define OCTEON_SYNCW __asm __volatile (".word 0x10f" : : ) #define OCTEON_SYNCWS __asm __volatile (".word 0x14f" : : ) -#if defined(__mips_n32) || defined(__mips_n64) +#if defined(__mips_n64) +#define oct_write64(a, v) (*(volatile uint64_t *)(a) = (uint64_t)(v)) +#define oct_write8_x8(a, v) (*(volatile uint8_t *)(a) = (uint8_t)(v)) + +#define OCT_READ(n, t) \ +static inline t oct_read ## n(uintptr_t a) \ +{ \ + volatile t *p = (volatile t *)a; \ + return (*p); \ +} + +OCT_READ(8, uint8_t); +OCT_READ(16, uint16_t); +OCT_READ(32, uint32_t); +OCT_READ(64, uint64_t); +#elif defined(__mips_n32) || defined(__mips_o32) +#if defined(__mips_n32) static inline void oct_write64 (uint64_t csr_addr, uint64_t val64) { - uint64_t *ptr = (uint64_t *) csr_addr; - *ptr = val64; -} - -static inline void oct_write64_int64 (uint64_t csr_addr, int64_t val64i) -{ - int64_t *ptr = (int64_t *) csr_addr; - *ptr = val64i; + __asm __volatile ( + ".set push\n" + ".set mips64\n" + "sd %0, 0(%1)\n" + ".set pop\n" + : + : "r"(val64), "r"(csr_addr)); } static inline void oct_write8_x8 (uint64_t csr_addr, uint8_t val8) { - uint64_t *ptr = (uint64_t *) csr_addr; - *ptr = (uint64_t) val8; -} + __asm __volatile ( + ".set push\n" + ".set mips64\n" + "sb %0, 0(%1)\n" + ".set pop\n" + : + : "r"(val8), "r"(csr_addr)); +} + +#define OCT_READ(n, t, insn) \ +static inline t oct_read ## n(uint64_t a) \ +{ \ + uint64_t tmp; \ + \ + __asm __volatile ( \ + ".set push\n" \ + ".set mips64\n" \ + insn "\t%0, 0(%1)\n" \ + ".set pop\n" \ + : "=r"(tmp) \ + : "r"(a)); \ + return ((t)tmp); \ +} + +OCT_READ(8, uint8_t, "lb"); +OCT_READ(16, uint16_t, "lh"); +OCT_READ(32, uint32_t, "lw"); +OCT_READ(64, uint64_t, "ld"); +#else -static inline void oct_write8 (uint64_t csr_addr, uint8_t val8) +/* + * XXX + * Add o32 variants that load the address into a register and the result out + * of a register properly, and simply disable interrupts before and after and + * hope that we don't need to refill or modify the TLB to access the address. + * I'd be a lot happier if csr_addr were a physical address and we mapped it + * into XKPHYS here so that we could guarantee that interrupts were the only + * kind of exception we needed to worry about. + * + * Also, some of this inline assembly is needlessly verbose. Oh, well. + */ +static inline void oct_write64 (uint64_t csr_addr, uint64_t val64) { - oct_write64(csr_addr, (uint64_t) val8); -} + uint32_t csr_addrh = csr_addr >> 32; + uint32_t csr_addrl = csr_addr; + uint32_t valh = val64 >> 32; + uint32_t vall = val64; + uint32_t tmp1; + uint32_t tmp2; + uint32_t tmp3; + register_t sr; -static inline void oct_write16 (uint64_t csr_addr, uint16_t val16) -{ - oct_write64(csr_addr, (uint64_t) val16); -} + sr = intr_disable(); -static inline void oct_write32 (uint64_t csr_addr, uint32_t val32) -{ - oct_write64(csr_addr, (uint64_t) val32); -} + __asm __volatile ( + ".set push\n" + ".set mips64\n" + ".set noreorder\n" + ".set noat\n" + "dsll %0, %3, 32\n" + "dsll %1, %5, 32\n" + "dsll %2, %4, 32\n" + "dsrl %2, %2, 32\n" + "or %0, %0, %2\n" + "dsll %2, %6, 32\n" + "dsrl %2, %2, 32\n" + "or %1, %1, %2\n" + "sd %0, 0(%1)\n" + ".set pop\n" + : "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3) + : "r" (valh), "r" (vall), "r" (csr_addrh), "r" (csr_addrl)); -static inline uint8_t oct_read8 (uint64_t csr_addr) -{ - uint8_t *ptr = (uint8_t *) csr_addr; - return (*ptr); + intr_restore(sr); } -static inline uint8_t oct_read16 (uint64_t csr_addr) +static inline void oct_write8_x8 (uint64_t csr_addr, uint8_t val8) { - uint16_t *ptr = (uint16_t *) csr_addr; - return (*ptr); -} + uint32_t csr_addrh = csr_addr >> 32; + uint32_t csr_addrl = csr_addr; + uint32_t tmp1; + uint32_t tmp2; + register_t sr; + sr = intr_disable(); -static inline uint32_t oct_read32 (uint64_t csr_addr) -{ - uint32_t *ptr = (uint32_t *) csr_addr; - return (*ptr); -} + __asm __volatile ( + ".set push\n" + ".set mips64\n" + ".set noreorder\n" + ".set noat\n" + "dsll %0, %3, 32\n" + "dsll %1, %4, 32\n" + "dsrl %1, %1, 32\n" + "or %0, %0, %1\n" + "sb %2, 0(%0)\n" + ".set pop\n" + : "=&r" (tmp1), "=&r" (tmp2) + : "r" (val8), "r" (csr_addrh), "r" (csr_addrl)); + + intr_restore(sr); +} + +#define OCT_READ(n, t, insn) \ +static inline t oct_read ## n(uint64_t csr_addr) \ +{ \ + uint32_t csr_addrh = csr_addr >> 32; \ + uint32_t csr_addrl = csr_addr; \ + uint32_t tmp1, tmp2; \ + register_t sr; \ + \ + sr = intr_disable(); \ + \ + __asm __volatile ( \ + ".set push\n" \ + ".set mips64\n" \ + ".set noreorder\n" \ + ".set noat\n" \ + "dsll %1, %2, 32\n" \ + "dsll %0, %3, 32\n" \ + "dsrl %0, %0, 32\n" \ *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***