From owner-svn-src-user@FreeBSD.ORG Sun Oct 24 04:38:56 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 92E4F106566B; Sun, 24 Oct 2010 04:38:56 +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 7F87E8FC12; Sun, 24 Oct 2010 04:38:56 +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 o9O4cuVF017547; Sun, 24 Oct 2010 04:38:56 GMT (envelope-from nwhitehorn@svn.freebsd.org) Received: (from nwhitehorn@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o9O4cufb017542; Sun, 24 Oct 2010 04:38:56 GMT (envelope-from nwhitehorn@svn.freebsd.org) Message-Id: <201010240438.o9O4cufb017542@svn.freebsd.org> From: Nathan Whitehorn Date: Sun, 24 Oct 2010 04:38:56 +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: r214259 - in user/nwhitehorn/ps3: conf dev/usb/controller powerpc/ps3 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: Sun, 24 Oct 2010 04:38:56 -0000 Author: nwhitehorn Date: Sun Oct 24 04:38:56 2010 New Revision: 214259 URL: http://svn.freebsd.org/changeset/base/214259 Log: Checkpoint USB support on the PS3. It can see the EHCI registers and reset the controller, etc., but will not actually work until busdma has IOMMU support in it. Added: user/nwhitehorn/ps3/powerpc/ps3/ehci_ps3.c (contents, props changed) Modified: user/nwhitehorn/ps3/conf/files.powerpc user/nwhitehorn/ps3/dev/usb/controller/ehci.c user/nwhitehorn/ps3/powerpc/ps3/ps3bus.c Modified: user/nwhitehorn/ps3/conf/files.powerpc ============================================================================== --- user/nwhitehorn/ps3/conf/files.powerpc Sun Oct 24 03:20:54 2010 (r214258) +++ user/nwhitehorn/ps3/conf/files.powerpc Sun Oct 24 04:38:56 2010 (r214259) @@ -191,6 +191,7 @@ powerpc/powerpc/suswintr.c standard powerpc/powerpc/syncicache.c standard powerpc/powerpc/sys_machdep.c standard powerpc/powerpc/uio_machdep.c standard +powerpc/ps3/ehci_ps3.c optional ps3 ehci powerpc/ps3/if_glc.c optional ps3 glc powerpc/ps3/mmu_ps3.c optional ps3 powerpc/ps3/platform_ps3.c optional ps3 Modified: user/nwhitehorn/ps3/dev/usb/controller/ehci.c ============================================================================== --- user/nwhitehorn/ps3/dev/usb/controller/ehci.c Sun Oct 24 03:20:54 2010 (r214258) +++ user/nwhitehorn/ps3/dev/usb/controller/ehci.c Sun Oct 24 04:38:56 2010 (r214259) @@ -268,9 +268,9 @@ ehci_init(ehci_softc_t *sc) } #endif - sc->sc_offs = EREAD1(sc, EHCI_CAPLENGTH); + sc->sc_offs = EREAD4(sc, EHCI_CAPLENGTH) & 0xff; - version = EREAD2(sc, EHCI_HCIVERSION); + version = EREAD4(sc, EHCI_HCIVERSION & ~3) >> 16; device_printf(sc->sc_bus.bdev, "EHCI version %x.%x\n", version >> 8, version & 0xff); Added: user/nwhitehorn/ps3/powerpc/ps3/ehci_ps3.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/nwhitehorn/ps3/powerpc/ps3/ehci_ps3.c Sun Oct 24 04:38:56 2010 (r214259) @@ -0,0 +1,173 @@ +/*- + * Copyright (C) 2010 Nathan Whitehorn + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ps3bus.h" + +struct ps3_ehci_softc { + ehci_softc_t base; + struct bus_space tag; +}; + +static int +ehci_ps3_probe(device_t dev) +{ + if (ps3bus_get_bustype(dev) != PS3_BUSTYPE_SYSBUS || + ps3bus_get_devtype(dev) != PS3_DEVTYPE_USB) + return (ENXIO); + + device_set_desc(dev, "Playstation 3 USB 2.0 controller"); + return (BUS_PROBE_SPECIFIC); +} + +static int +ehci_ps3_attach(device_t dev) +{ + ehci_softc_t *sc = device_get_softc(dev); + int rid, err; + + sc->sc_bus.parent = dev; + sc->sc_bus.devices = sc->sc_devices; + sc->sc_bus.devices_max = EHCI_MAX_DEVICES; + + if (usb_bus_mem_alloc_all(&sc->sc_bus, + USB_GET_DMA_TAG(dev), &ehci_iterate_hw_softc)) + return (ENOMEM); + + rid = 1; + sc->sc_io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &rid, RF_ACTIVE); + + if (!sc->sc_io_res) { + device_printf(dev, "Could not map memory\n"); + goto error; + } + + sc->sc_io_tag = rman_get_bustag(sc->sc_io_res); + sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res); + sc->sc_io_size = rman_get_size(sc->sc_io_res); + + rid = 1; + sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, + RF_SHAREABLE | RF_ACTIVE); + + if (sc->sc_irq_res == NULL) { + device_printf(dev, "Could not allocate irq\n"); + return (ENXIO); + } + + sc->sc_bus.bdev = device_add_child(dev, "usbus", -1); + if (!sc->sc_bus.bdev) { + device_printf(dev, "Could not add USB device\n"); + return (ENXIO); + } + + device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus); + + sprintf(sc->sc_vendor, "Sony"); + + err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, + NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl); + if (err) { + device_printf(dev, "Could not setup error irq, %d\n", err); + goto error; + } + + sc->sc_flags |= EHCI_SCFLG_BIGEMMIO; + err = ehci_init(sc); + if (err) { + device_printf(dev, "USB init failed err=%d\n", err); + goto error; + } + + err = device_probe_and_attach(sc->sc_bus.bdev); + if (err == 0) + return (0); + +error: + return (ENXIO); +} + +static device_method_t ehci_ps3_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ehci_ps3_probe), + DEVMETHOD(device_attach, ehci_ps3_attach), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + + {0, 0} +}; + +static driver_t ehci_ps3_driver = { + "ehci", + ehci_ps3_methods, + sizeof(ehci_softc_t), +}; + +static devclass_t ehci_ps3_devclass; + +DRIVER_MODULE(ehci_ps3, ps3bus, ehci_ps3_driver, ehci_ps3_devclass, 0, 0); +MODULE_DEPEND(ehci_ps3, usb, 1, 1, 1); + Modified: user/nwhitehorn/ps3/powerpc/ps3/ps3bus.c ============================================================================== --- user/nwhitehorn/ps3/powerpc/ps3/ps3bus.c Sun Oct 24 03:20:54 2010 (r214258) +++ user/nwhitehorn/ps3/powerpc/ps3/ps3bus.c Sun Oct 24 04:38:56 2010 (r214259) @@ -32,9 +32,16 @@ #include #include #include -#include +#include +#include + +#include +#include -#include +#include +#include +#include +#include #include "ps3bus.h" #include "ps3-hvcall.h" @@ -87,10 +94,14 @@ static device_method_t ps3bus_methods[] { 0, 0 } }; +struct ps3bus_softc { + struct rman sc_mem_rman; +}; + static driver_t ps3bus_driver = { "ps3bus", ps3bus_methods, - 0 + sizeof(struct ps3bus_softc) }; static devclass_t ps3bus_devclass; @@ -118,16 +129,16 @@ ps3bus_probe(device_t dev) } static void -ps3bus_resources_init(int bus_index, int dev_index, struct resource_list *rl) +ps3bus_resources_init(struct rman *rm, int bus_index, int dev_index, + struct ps3bus_devinfo *dinfo) { uint64_t irq_type, irq, outlet; uint64_t reg_type, paddr, len; - uint64_t bus, dev, ppe; - uint64_t junk; + uint64_t ppe, junk; int i, result; int thread; - resource_list_init(rl); + resource_list_init(&dinfo->resources); lv1_get_logical_ppe_id(&ppe); thread = 32 - fls(mfctrl()); @@ -142,21 +153,13 @@ ps3bus_resources_init(int bus_index, int if (result != 0) break; - 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); + lv1_connect_interrupt_event_receive_port(dinfo->bus, + dinfo->dev, outlet, irq); break; case OHCI_IRQ: case EHCI_IRQ: @@ -165,12 +168,13 @@ ps3bus_resources_init(int bus_index, int 0); break; default: - printf("Unknown IRQ type %ld for device %ld.%ld\n", - irq_type, bus, dev); + printf("Unknown IRQ type %ld for device %d.%d\n", + irq_type, dinfo->bus, dinfo->dev); break; } - resource_list_add(rl, SYS_RES_IRQ, i, outlet, outlet, 1); + resource_list_add(&dinfo->resources, SYS_RES_IRQ, i, + outlet, outlet, 1); } /* Scan for registers */ @@ -190,14 +194,26 @@ ps3bus_resources_init(int bus_index, int lv1_repository_string("reg") | i, lv1_repository_string("data"), &paddr, &len); - resource_list_add(rl, SYS_RES_MEMORY, i, paddr, paddr + len, - len); + result = lv1_map_device_mmio_region(dinfo->bus, dinfo->dev, + paddr, len, 12 /* log_2(4 KB) */, &paddr); + + if (result != 0) { + printf("Mapping registers failed for device " + "%d.%d (%ld.%ld): %d\n", dinfo->bus, dinfo->dev, + dinfo->bustype, dinfo->devtype, result); + continue; + } + + rman_manage_region(rm, paddr, paddr + len - 1); + resource_list_add(&dinfo->resources, SYS_RES_MEMORY, i, + paddr, paddr + len, len); } } static int ps3bus_attach(device_t self) { + struct ps3bus_softc *sc; struct ps3bus_devinfo *dinfo; int bus_index, dev_index, result; uint64_t bustype, bus, devs; @@ -205,6 +221,11 @@ ps3bus_attach(device_t self) uint64_t junk; device_t cdev; + sc = device_get_softc(self); + sc->sc_mem_rman.rm_type = RMAN_ARRAY; + sc->sc_mem_rman.rm_descr = "PS3Bus Memory Mapped I/O"; + rman_init(&sc->sc_mem_rman); + /* * Probe all the PS3's buses. */ @@ -256,8 +277,8 @@ ps3bus_attach(device_t self) if (dinfo->bustype == PS3_BUSTYPE_SYSBUS) lv1_open_device(bus, dev, 0); - ps3bus_resources_init(bus_index, dev_index, - &dinfo->resources); + ps3bus_resources_init(&sc->sc_mem_rman, bus_index, + dev_index, dinfo); cdev = device_add_child(self, NULL, -1); if (cdev == NULL) { @@ -319,9 +340,47 @@ static struct resource * ps3bus_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { - struct ps3bus_devinfo *dinfo = device_get_ivars(child); + struct ps3bus_devinfo *dinfo; + struct ps3bus_softc *sc; + int needactivate; + struct resource *rv; + struct rman *rm; + u_long adjstart, adjend, adjcount; + struct resource_list_entry *rle; + + sc = device_get_softc(bus); + dinfo = device_get_ivars(child); + needactivate = flags & RF_ACTIVE; + flags &= ~RF_ACTIVE; switch (type) { + case SYS_RES_MEMORY: + rle = resource_list_find(&dinfo->resources, SYS_RES_MEMORY, + *rid); + if (rle == NULL) { + device_printf(bus, "no rle for %s memory %d\n", + device_get_nameunit(child), *rid); + return (NULL); + } + + if (start < rle->start) + adjstart = rle->start; + else if (start > rle->end) + adjstart = rle->end; + else + adjstart = start; + + if (end < rle->start) + adjend = rle->start; + else if (end > rle->end) + adjend = rle->end; + else + adjend = end; + + adjcount = adjend - adjstart; + + rm = &sc->sc_mem_rman; + break; case SYS_RES_IRQ: return (resource_list_alloc(&dinfo->resources, bus, child, type, rid, start, end, count, flags)); @@ -331,16 +390,57 @@ ps3bus_alloc_resource(device_t bus, devi return (NULL); } - return (NULL); + rv = rman_reserve_resource(rm, adjstart, adjend, adjcount, flags, + child); + if (rv == NULL) { + device_printf(bus, + "failed to reserve resource %#lx - %#lx (%#lx)" + " for %s\n", adjstart, adjend, adjcount, + device_get_nameunit(child)); + return (NULL); + } + + rman_set_rid(rv, *rid); + + if (needactivate) { + if (bus_activate_resource(child, type, *rid, rv) != 0) { + device_printf(bus, + "failed to activate resource for %s\n", + device_get_nameunit(child)); + rman_release_resource(rv); + return (NULL); + } + } + + return (rv); } static int ps3bus_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *res) { + void *p; + if (type == SYS_RES_IRQ) return (bus_activate_resource(bus, type, rid, res)); + if (type == SYS_RES_MEMORY) { + vm_offset_t start; + + start = (vm_offset_t) rman_get_start(res); + + if (bootverbose) + printf("ps3 mapdev: start %zx, len %ld\n", start, + rman_get_size(res)); + + p = pmap_mapdev(start, (vm_size_t) rman_get_size(res)); + if (p == NULL) + return (ENOMEM); + rman_set_virtual(res, p); + rman_set_bustag(res, &bs_be_tag); + rman_set_bushandle(res, (u_long)p); + } + return (rman_activate_resource(res)); }