svn commit: r206525 - in user/imp/tbemd/sys/mips: atheros cavium cavium/dev/rgmii conf include mips sibyte

Warner Losh imp at FreeBSD.org
Mon Apr 12 23:16:17 UTC 2010


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 ***


More information about the svn-src-user mailing list