Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 22 Aug 2010 19:09:18 +0000 (UTC)
From:      Nathan Whitehorn <nwhitehorn@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r211636 - in user/nwhitehorn/ps3/powerpc: include ps3
Message-ID:  <201008221909.o7MJ9IUZ012226@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: nwhitehorn
Date: Sun Aug 22 19:09:18 2010
New Revision: 211636
URL: http://svn.freebsd.org/changeset/base/211636

Log:
  Get interrupts functioning, along with a few other minor things. The
  kernel now can transmit and receive network traffic, mounts root, and
  gets several thousand packets in before hanging.

Modified:
  user/nwhitehorn/ps3/powerpc/include/cpufunc.h
  user/nwhitehorn/ps3/powerpc/include/spr.h
  user/nwhitehorn/ps3/powerpc/ps3/if_glc.c
  user/nwhitehorn/ps3/powerpc/ps3/platform_ps3.c
  user/nwhitehorn/ps3/powerpc/ps3/ps3bus.c
  user/nwhitehorn/ps3/powerpc/ps3/ps3pic.c

Modified: user/nwhitehorn/ps3/powerpc/include/cpufunc.h
==============================================================================
--- user/nwhitehorn/ps3/powerpc/include/cpufunc.h	Sun Aug 22 19:06:20 2010	(r211635)
+++ user/nwhitehorn/ps3/powerpc/include/cpufunc.h	Sun Aug 22 19:09:18 2010	(r211636)
@@ -106,6 +106,17 @@ mfsrin(vm_offset_t va)
 }
 #endif
 
+static __inline register_t
+mfctrl(void)
+{
+	register_t value;
+
+	__asm __volatile ("mfspr %0,136" : "=r"(value));
+
+	return (value);
+}
+
+
 static __inline void
 mtdec(register_t value)
 {

Modified: user/nwhitehorn/ps3/powerpc/include/spr.h
==============================================================================
--- user/nwhitehorn/ps3/powerpc/include/spr.h	Sun Aug 22 19:06:20 2010	(r211635)
+++ user/nwhitehorn/ps3/powerpc/include/spr.h	Sun Aug 22 19:09:18 2010	(r211636)
@@ -423,7 +423,7 @@
 #define	SPR_HID6		0x3f9	/* ..8 Hardware Implementation Register 6 */
 
 #define	SPR_CELL_TSRL		0x380	/* ... Cell BE Thread Status Register */
-#define	SPR_CELL_TSCR		0x399	/* ... Cell BE Thread Status Register */
+#define	SPR_CELL_TSCR		0x399	/* ... Cell BE Thread Switch Register */
 
 #if defined(AIM)
 #define	SPR_DBSR		0x3f0	/* 4.. Debug Status Register */

Modified: user/nwhitehorn/ps3/powerpc/ps3/if_glc.c
==============================================================================
--- user/nwhitehorn/ps3/powerpc/ps3/if_glc.c	Sun Aug 22 19:06:20 2010	(r211635)
+++ user/nwhitehorn/ps3/powerpc/ps3/if_glc.c	Sun Aug 22 19:09:18 2010	(r211636)
@@ -128,32 +128,15 @@ glc_attach(device_t dev) 
 	sc->next_txdma_slot = sc->first_used_txdma_slot = 0;
 
 	/*
-	 * Open device, and shut down existing tasks.
+	 * Shut down existing tasks.
 	 */
 
-	err = lv1_open_device(sc->sc_bus, sc->sc_dev, 0);
-	if (err) {
-		device_printf(dev, "Error opening device: %d\n", err);
-		mtx_destroy(&sc->sc_mtx);
-		return (ENXIO);
-	}
-
 	lv1_net_stop_tx_dma(sc->sc_bus, sc->sc_dev, 0);
 	lv1_net_stop_rx_dma(sc->sc_bus, sc->sc_dev, 0);
 
 	sc->sc_ifp = if_alloc(IFT_ETHER);
 	sc->sc_ifp->if_softc = sc;
 
-/* Wait for link */
-for (i = 0; i < 1000; i++) {
-	lv1_net_control(sc->sc_bus, sc->sc_dev, GELIC_GET_LINK_STATUS, 2, 0,
-	    0, &val, &junk);
-	if (val & GELIC_LINK_UP)
-		break;
-	DELAY(500);
-}
-
-
 	/*
 	 * Get MAC address and VLAN id
 	 */
@@ -357,7 +340,6 @@ glc_start_locked(struct ifnet *ifp)
 	mtx_assert(&sc->sc_mtx, MA_OWNED);
 	first = 0;
 
-printf("Transmitting packet!\n");
 	while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
 		IFQ_DRV_DEQUEUE(&ifp->if_snd, mb_head);
 
@@ -614,7 +596,6 @@ glc_rxintr(struct glc_softc *sc)
 {
 	int i, restart_rxdma;
 	struct mbuf *m;
-	uint16_t tag;
 	struct ifnet *ifp = sc->sc_ifp;
 
 	bus_dmamap_sync(sc->sc_dmadesc_tag, sc->sc_rxdmadesc_map,
@@ -640,27 +621,11 @@ glc_rxintr(struct glc_softc *sc)
 		m->m_len = sc->sc_rxdmadesc[i].valid_size;
 		m->m_pkthdr.len = m->m_len;
 		sc->sc_next_rxdma_slot++;
+		if (sc->sc_next_rxdma_slot >= GLC_MAX_RX_PACKETS)
+			sc->sc_next_rxdma_slot = 0;
 
-		if (sc->sc_rx_vlan >= 0) {
-			struct ether_vlan_header *evl;
-			if (m->m_len < sizeof(*evl) &&
-			    (m = m_pullup(m, sizeof(*evl))) == NULL) {
-				if_printf(ifp, "cannot pullup VLAN header\n");
-				return;
-			}
-			evl = mtod(m, struct ether_vlan_header *);
-			tag = EVL_VLANOFTAG(ntohs(evl->evl_tag));
-
-			/*
-			 * Remove the 802.1q header by copying the Ethernet
-			 * addresses over it and adjusting the beginning of
-			 * the data in the mbuf.  The encapsulated Ethernet
-			 * type field is already in place.
-			 */
-			bcopy((char *)evl, (char *)evl + ETHER_VLAN_ENCAP_LEN,
-			      ETHER_HDR_LEN - ETHER_TYPE_LEN);
-			m_adj(m, ETHER_VLAN_ENCAP_LEN);
-		}
+		if (sc->sc_rx_vlan >= 0)
+			m_adj(m, 2);
 
 		mtx_unlock(&sc->sc_mtx);
 		(*ifp->if_input)(ifp, m);
@@ -725,12 +690,11 @@ glc_intr(void *xsc)
 
 	mtx_lock(&sc->sc_mtx);
 
-	if (sc->sc_interrupt_status == 0) {
+	if (*sc->sc_interrupt_status == 0) {
 		device_printf(sc->sc_self, "stray interrupt!\n");
 		mtx_unlock(&sc->sc_mtx);
 		return;
 	}
-printf("GLC Interrupt!\n");
 
 	if (*sc->sc_interrupt_status & (GELIC_INT_RXDONE | GELIC_INT_RXFRAME))
 		glc_rxintr(sc);

Modified: user/nwhitehorn/ps3/powerpc/ps3/platform_ps3.c
==============================================================================
--- user/nwhitehorn/ps3/powerpc/ps3/platform_ps3.c	Sun Aug 22 19:06:20 2010	(r211635)
+++ user/nwhitehorn/ps3/powerpc/ps3/platform_ps3.c	Sun Aug 22 19:09:18 2010	(r211636)
@@ -192,7 +192,7 @@ static int
 ps3_smp_start_cpu(platform_t plat, struct pcpu *pc)
 {
 #ifdef SMP
-	/* loader(8) is spinning on 0x40 == 1 right now */
+	/* loader(8) is spinning on 0x40 == 0 right now */
 	uint32_t *secondary_spin_sem = (uint32_t *)(0x40);
 	int timeout;
 

Modified: user/nwhitehorn/ps3/powerpc/ps3/ps3bus.c
==============================================================================
--- user/nwhitehorn/ps3/powerpc/ps3/ps3bus.c	Sun Aug 22 19:06:20 2010	(r211635)
+++ user/nwhitehorn/ps3/powerpc/ps3/ps3bus.c	Sun Aug 22 19:09:18 2010	(r211636)
@@ -62,6 +62,12 @@ struct ps3bus_devinfo {
 
 static MALLOC_DEFINE(M_PS3BUS, "ps3bus", "PS3 system bus device information");
 
+enum ps3bus_irq_type {
+	SB_IRQ = 2,
+	OHCI_IRQ = 3,
+	EHCI_IRQ = 4,
+};
+
 static device_method_t ps3bus_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_identify,	ps3bus_identify),
@@ -75,6 +81,8 @@ static device_method_t ps3bus_methods[] 
 	DEVMETHOD(bus_read_ivar,	ps3bus_read_ivar),
 	DEVMETHOD(bus_alloc_resource,	ps3bus_alloc_resource),
 	DEVMETHOD(bus_activate_resource, ps3bus_activate_resource),
+	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
+	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
 
 	{ 0, 0 }
 };
@@ -112,13 +120,18 @@ ps3bus_probe(device_t dev) 
 static void
 ps3bus_resources_init(int bus_index, int dev_index, struct resource_list *rl)
 {
-	uint64_t irq_type, irq;
+	uint64_t irq_type, irq, outlet;
 	uint64_t reg_type, paddr, len;
+	uint64_t bus, dev, ppe;
 	uint64_t junk;
 	int i, result;
+	int thread;
 
 	resource_list_init(rl);
 
+	lv1_get_logical_ppe_id(&ppe);
+	thread = 32 - fls(mfctrl());
+
 	/* Scan for interrupts */
 	for (i = 0; i < 10; i++) {
 		result = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
@@ -129,7 +142,35 @@ ps3bus_resources_init(int bus_index, int
 		if (result != 0)
 			break;
 
-		resource_list_add(rl, SYS_RES_IRQ, i, irq, irq, 1);
+		lv1_get_repository_node_value(PS3_LPAR_ID_PME,
+		    (lv1_repository_string("bus") >> 32) | bus_index,
+		    lv1_repository_string("id"), 0, 0, &bus, &junk);
+		lv1_get_repository_node_value(PS3_LPAR_ID_PME,
+		    (lv1_repository_string("bus") >> 32) | bus_index,
+		    lv1_repository_string("dev") | dev_index,
+		    lv1_repository_string("id"), 0, &dev, &junk);
+
+		switch (irq_type) {
+		case SB_IRQ:
+			lv1_construct_event_receive_port(&outlet);
+			lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet,
+			    0);
+			lv1_connect_interrupt_event_receive_port(bus, dev,
+			    outlet, irq);
+			break;
+		case OHCI_IRQ:
+		case EHCI_IRQ:
+			lv1_construct_io_irq_outlet(irq, &outlet);
+			lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet,
+			    0);
+			break;
+		default:
+			printf("Unknown IRQ type %ld for device %ld.%ld\n",
+			    irq_type, bus, dev);
+			break;
+		}
+
+		resource_list_add(rl, SYS_RES_IRQ, i, outlet, outlet, 1);
 	}
 
 	/* Scan for registers */
@@ -212,6 +253,9 @@ ps3bus_attach(device_t self) 
 			dinfo->bustype = bustype;
 			dinfo->devtype = devtype;
 
+			if (dinfo->bustype == PS3_BUSTYPE_SYSBUS)
+				lv1_open_device(bus, dev, 0);
+
 			ps3bus_resources_init(bus_index, dev_index,
 			    &dinfo->resources);
 

Modified: user/nwhitehorn/ps3/powerpc/ps3/ps3pic.c
==============================================================================
--- user/nwhitehorn/ps3/powerpc/ps3/ps3pic.c	Sun Aug 22 19:06:20 2010	(r211635)
+++ user/nwhitehorn/ps3/powerpc/ps3/ps3pic.c	Sun Aug 22 19:09:18 2010	(r211636)
@@ -31,7 +31,10 @@
 #include <sys/bus.h>
 #include <sys/conf.h>
 #include <sys/kernel.h>
-#include <sys/rman.h>
+#include <sys/malloc.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
 
 #include <machine/bus.h>
 #include <machine/intr_machdep.h>
@@ -53,6 +56,15 @@ static void	ps3pic_mask(device_t, u_int)
 static void	ps3pic_unmask(device_t, u_int);
 static uint32_t ps3pic_id(device_t dev);
 
+struct ps3pic_softc {
+	uint64_t	*bitmap_thread0;
+	uint64_t	*mask_thread0;
+	uint64_t	*bitmap_thread1;
+	uint64_t	*mask_thread1;
+
+	int		sc_vector[64];
+};
+
 static device_method_t  ps3pic_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_identify,	ps3pic_identify),
@@ -74,13 +86,15 @@ static device_method_t  ps3pic_methods[]
 static driver_t ps3pic_driver = {
 	"ps3pic",
 	ps3pic_methods,
-	0
+	sizeof(struct ps3pic_softc)
 };
 
 static devclass_t ps3pic_devclass;
 
 DRIVER_MODULE(ps3pic, nexus, ps3pic_driver, ps3pic_devclass, 0, 0);
 
+static MALLOC_DEFINE(M_PS3PIC, "ps3pic", "PS3 PIC");
+
 static void
 ps3pic_identify(driver_t *driver, device_t parent)
 {
@@ -101,9 +115,31 @@ ps3pic_probe(device_t dev)
 static int
 ps3pic_attach(device_t dev)
 {
+	struct ps3pic_softc *sc;
+	uint64_t ppe;
+	int thread;
+
 	powerpc_register_pic(dev, 64);
 	root_pic = dev; /* PS3s have only one PIC */
 
+	sc = device_get_softc(dev);
+
+	sc->bitmap_thread0 = contigmalloc(128 /* 512 bits * 2 */, M_PS3PIC,
+	    M_NOWAIT | M_ZERO, 0, BUS_SPACE_MAXADDR, 64 /* alignment */,
+	    PAGE_SIZE /* boundary */);
+	sc->mask_thread0 = sc->bitmap_thread0 + 4;
+	sc->bitmap_thread1 = sc->bitmap_thread0 + 8;
+	sc->mask_thread1 = sc->bitmap_thread0 + 12;
+
+	lv1_get_logical_ppe_id(&ppe);
+	thread = 32 - fls(mfctrl());
+	lv1_configure_irq_state_bitmap(ppe, thread,
+	    vtophys(sc->bitmap_thread0));
+#ifdef SMP
+	lv1_configure_irq_state_bitmap(ppe, !thread,
+	    vtophys(sc->bitmap_thread1));
+#endif
+
 	return (0);
 }
 
@@ -114,16 +150,50 @@ ps3pic_attach(device_t dev)
 static void
 ps3pic_dispatch(device_t dev, struct trapframe *tf)
 {
+	uint64_t bitmap, mask;
+	int irq;
+	struct ps3pic_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	if (PCPU_GET(cpuid) == 0) {
+		bitmap = sc->bitmap_thread0[0];
+		mask = sc->mask_thread0[0];
+	} else {
+		bitmap = sc->bitmap_thread1[0];
+		mask = sc->mask_thread1[0];
+	}
+
+	while ((irq = ffsl(bitmap & mask) - 1) != -1) {
+		bitmap &= ~(1UL << irq);
+		powerpc_dispatch_intr(sc->sc_vector[63 - irq], tf);
+	}
 }
 
 static void
 ps3pic_enable(device_t dev, u_int irq, u_int vector)
 {
+	struct ps3pic_softc *sc;
+
+	if (irq > 63) /* IPI */
+		return;
+
+	sc = device_get_softc(dev);
+	sc->sc_vector[irq] = vector;
+
+	ps3pic_unmask(dev, irq);
 }
 
 static void
-ps3pic_eoi(device_t dev __unused, u_int irq __unused)
+ps3pic_eoi(device_t dev, u_int irq)
 {
+	uint64_t ppe;
+	int thread;
+
+	lv1_get_logical_ppe_id(&ppe);
+	thread = 32 - fls(mfctrl());
+
+	lv1_end_of_interrupt_ext(ppe, thread, irq);
 }
 
 static void
@@ -134,11 +204,31 @@ ps3pic_ipi(device_t dev, u_int irq)
 static void
 ps3pic_mask(device_t dev, u_int irq)
 {
+	struct ps3pic_softc *sc;
+	uint64_t ppe;
+
+	sc = device_get_softc(dev);
+	sc->mask_thread0[0] &= ~(1UL << (63 - irq));
+	sc->mask_thread1[0] &= ~(1UL << (63 - irq));
+
+	lv1_get_logical_ppe_id(&ppe);
+	lv1_did_update_interrupt_mask(ppe, 0);
+	lv1_did_update_interrupt_mask(ppe, 1);
 }
 
 static void
 ps3pic_unmask(device_t dev, u_int irq)
 {
+	struct ps3pic_softc *sc;
+	uint64_t ppe;
+
+	sc = device_get_softc(dev);
+	sc->mask_thread0[0] |= (1UL << (63 - irq));
+	sc->mask_thread1[0] |= (1UL << (63 - irq));
+
+	lv1_get_logical_ppe_id(&ppe);
+	lv1_did_update_interrupt_mask(ppe, 0);
+	lv1_did_update_interrupt_mask(ppe, 1);
 }
 
 static uint32_t



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