svn commit: r211636 - in user/nwhitehorn/ps3/powerpc: include ps3
Nathan Whitehorn
nwhitehorn at FreeBSD.org
Sun Aug 22 19:09:18 UTC 2010
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
More information about the svn-src-user
mailing list