summaryrefslogtreecommitdiffstats
path: root/cfe/cfe/usb/usbhack.c
diff options
context:
space:
mode:
Diffstat (limited to 'cfe/cfe/usb/usbhack.c')
-rw-r--r--cfe/cfe/usb/usbhack.c528
1 files changed, 528 insertions, 0 deletions
diff --git a/cfe/cfe/usb/usbhack.c b/cfe/cfe/usb/usbhack.c
new file mode 100644
index 0000000..647f213
--- /dev/null
+++ b/cfe/cfe/usb/usbhack.c
@@ -0,0 +1,528 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * Main Module File: usbhack.c
+ *
+ * A crude test program to let us tinker with a USB controller
+ * installed in an X86 Linux PC. Eventually we'll clean up
+ * this stuff and incorporate it into CFE.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR 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), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <sys/mman.h>
+#include <sys/fcntl.h>
+#include <signal.h>
+#include <memory.h>
+#include <time.h>
+
+#include "lib_malloc.h"
+#include "lib_queue.h"
+#include "usbchap9.h"
+#include "usbd.h"
+#include "ohci.h"
+
+/* *********************************************************************
+ * Macros
+ ********************************************************************* */
+
+#define OHCI_WRITECSR(softc,x,y) \
+ *((volatile uint32_t *) ((softc)->ohci_regs + ((x)/sizeof(uint32_t)))) = (y)
+#define OHCI_READCSR(softc,x) \
+ *((volatile uint32_t *) ((softc)->ohci_regs + ((x)/sizeof(uint32_t))))
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+extern int usb_noisy;
+extern int ohcidebug;
+
+extern usbdev_t *usbmass_dev;
+extern int usbmass_read_sector(usbdev_t *dev,uint32_t sectornum,uint32_t seccnt,
+ uint8_t *buffer);
+
+
+/* *********************************************************************
+ * Play Area definitions
+ *
+ * We use /dev/mem to map two areas - the "play" area and the
+ * "device" area.
+ *
+ * The "play" area maps to the upper 1MB of physical memory.
+ * You need to calculate this address yourself based on your system
+ * setup. If you have 256MB of memory, in your lilo.conf file put
+ * the following line:
+ *
+ * append="mem=255M"
+ *
+ * where '255' is one less than your system memory size. this
+ * leaves 1MB out of Linux's physical memory map and therefore
+ * leaves it to you to play with. /dev/mem will map this
+ * uncached using the Pentium MTRR registers, but for playing
+ * around this will be fine.
+ *
+ * the second area is the "device area" - this is the address
+ * the PCI USB controller's BARs were mapped to. You can find
+ * this by looking through /proc/pci until you find:
+ *
+ * Bus 0, device 8, function 0:
+ * USB Controller: OPTi Unknown device (rev 16).
+ * Vendor id=1045. Device id=c861.
+ * Medium devsel. Fast back-to-back capable. IRQ 3.
+ * Master Capable. Latency=32.
+ * Non-prefetchable 32 bit memory at 0xd9100000 [0xd9100000].
+ *
+ * The 0xd9100000 will probably be different on your system.
+ *
+ * Of course, to make this work you'll need to rebuild the kernel
+ * without USB support, if you're running a recent kernel.
+ * Fortunately(?), I've been using RH 6.2, no USB support there
+ * in the old 2.2 kernels.
+ *
+ * Finally, you'll need to run this program as root. Even if
+ * you mess with the permissions on /dev/mem, there are additional
+ * checks in the kernel, so you will lose.
+ *
+ * But, the good news is that it works well - I've never crashed
+ * my Linux box, and I can use gdb to debug programs.
+ * You will NOT be able to use GDB to display things in the
+ * play area - I believe GDB doesn't know how to deal with
+ * the uncached nature of the memory there. You can see stuff
+ * in the area by tracing through instructions that read the play
+ * area, and viewing the register contents.
+ ********************************************************************* */
+
+#define PLAY_AREA_ADDR (255*1024*1024) /* EDIT ME */
+#define PLAY_AREA_SIZE (1024*1024)
+int play_fd = -1;
+uint8_t *play_area = MAP_FAILED;
+
+#define DEVICE_AREA_ADDR 0xd9100000 /* EDIT ME */
+#define DEVICE_AREA_SIZE 4096
+int dev_fd = -1;
+uint8_t *device_area = MAP_FAILED;
+
+/* *********************************************************************
+ * Globals
+ ********************************************************************* */
+
+
+usbbus_t *bus = NULL;
+ohci_softc_t *ohci = NULL;
+int running = 1;
+
+/* *********************************************************************
+ * vtop(v)
+ *
+ * Given a virtual address in the play area, return its physical
+ * address.
+ *
+ * Input parameters:
+ * v - virtual address
+ *
+ * Return value:
+ * physical address
+ ********************************************************************* */
+
+
+uint32_t vtop(void *v)
+{
+ uint32_t p = (uint32_t) v;
+
+ if (v == 0) return 0;
+
+ p -= (uint32_t) play_area;
+ p += PLAY_AREA_ADDR;
+
+ return p;
+}
+
+/* *********************************************************************
+ * ptov(v)
+ *
+ * Given a phyiscal address in the play area, return the virtual
+ * address.
+ *
+ * Input parameters:
+ * p - physical address
+ *
+ *
+ * Return value:
+ * virtual address (void pointer)
+ ********************************************************************* */
+
+void *ptov(uint32_t p)
+{
+ if (p == 0) return 0;
+
+ p -= PLAY_AREA_ADDR;
+ p += (uint32_t) play_area;
+
+ return (void *) p;
+}
+
+/* *********************************************************************
+ * mydelay(x)
+ *
+ * delay for 'x' milliseconds.
+ *
+ * Input parameters:
+ * x - milliseconds
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void mydelay(int x)
+{
+ struct timespec ts;
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = x * 1000000; /* milliseconds */
+ nanosleep(&ts,NULL);
+}
+
+/* *********************************************************************
+ * console_log(tmplt,...)
+ *
+ * Display a console log message - this is a CFE function
+ * transplanted here.
+ *
+ * Input parameters:
+ * tmplt - printf string args...
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void console_log(const char *tmplt,...)
+{
+ char buffer[256];
+ va_list marker;
+
+ va_start(marker,tmplt);
+ vsprintf(buffer,tmplt,marker);
+ va_end(marker);
+ printf("%s\n",buffer);
+}
+
+/* *********************************************************************
+ * init_devaccess()
+ *
+ * Open /dev/mem and create the play area
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * 0 if ok, else error
+ ********************************************************************* */
+
+int init_devaccess(void)
+{
+ int idx;
+
+ play_fd = open("/dev/mem",O_RDWR);
+
+ if (play_fd < 0) {
+ perror("open");
+ return -1;
+ }
+
+ dev_fd = open("/dev/mem",O_RDWR | O_SYNC);
+
+ if (dev_fd < 0) {
+ perror("open");
+ close(play_fd);
+ play_fd = -1;
+ return -1;
+ }
+
+ play_area = mmap(NULL,
+ PLAY_AREA_SIZE,
+ PROT_READ|PROT_WRITE,MAP_SHARED,
+ play_fd,
+ PLAY_AREA_ADDR);
+
+ if (play_area != MAP_FAILED) {
+ printf("Play area mapped ok at address %p to %p\n",play_area,play_area+PLAY_AREA_SIZE-1);
+ for (idx = 0; idx < PLAY_AREA_SIZE; idx++) {
+ play_area[idx] = 0x55;
+ if (play_area[idx] != 0x55) printf("Offset %x doesn't work\n",idx);
+ play_area[idx] = 0xaa;
+ if (play_area[idx] != 0xaa) printf("Offset %x doesn't work\n",idx);
+ play_area[idx] = 0x0;
+ if (play_area[idx] != 0x0) printf("Offset %x doesn't work\n",idx);
+ }
+ }
+ else {
+ perror("mmap");
+ close(play_fd);
+ close(dev_fd);
+ play_fd = -1;
+ dev_fd = -1;
+ return -1;
+ }
+
+ device_area = mmap(NULL,
+ DEVICE_AREA_SIZE,
+ PROT_READ|PROT_WRITE,MAP_SHARED,
+ dev_fd,
+ DEVICE_AREA_ADDR);
+
+ if (device_area != MAP_FAILED) {
+ printf("Device area mapped ok at address %p\n",device_area);
+ }
+ else {
+ perror("mmap");
+ munmap(play_area,PLAY_AREA_SIZE);
+ play_area = MAP_FAILED;
+ close(play_fd);
+ close(dev_fd);
+ play_fd = -1;
+ dev_fd = -1;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/* *********************************************************************
+ * uninit_devaccess()
+ *
+ * Turn off access to the /dev/mem area. this will also
+ * set the OHCI controller's state to reset if we were playing
+ * with it.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void uninit_devaccess(void)
+{
+ if (ohci->ohci_regs) {
+ OHCI_WRITECSR(ohci,R_OHCI_CONTROL,V_OHCI_CONTROL_HCFS(K_OHCI_HCFS_RESET));
+ }
+
+ if (play_area != MAP_FAILED) munmap(play_area,PLAY_AREA_SIZE);
+ if (device_area != MAP_FAILED) munmap(device_area,DEVICE_AREA_SIZE);
+
+ if (play_fd > 0) close(play_fd);
+ if (dev_fd > 0) close(dev_fd);
+
+ device_area = MAP_FAILED;
+ play_area = MAP_FAILED;
+
+ dev_fd = -1;
+ play_fd = -1;
+}
+
+/* *********************************************************************
+ * sighandler()
+ *
+ * ^C handler - switch off OHCI controller
+ *
+ * Input parameters:
+ * sig - signal
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+void sighandler(int sig)
+{
+ signal(SIGINT,SIG_DFL);
+ printf("Interrupted, controller reset\n");
+ if (ohci->ohci_regs) {
+ OHCI_WRITECSR(ohci,R_OHCI_CONTROL,V_OHCI_CONTROL_HCFS(K_OHCI_HCFS_RESET));
+ }
+ running = 0;
+}
+
+
+extern usb_hcdrv_t ohci_driver;
+
+/* *********************************************************************
+ * xprintf(str)
+ *
+ * Called by lib_malloc, we need to supply it.
+ *
+ * Input parameters:
+ * str - string
+ *
+ * Return value:
+ * 0
+ ********************************************************************* */
+
+int xprintf(char *str)
+{
+ printf("%s",str);
+ return 0;
+}
+
+/* *********************************************************************
+ * main(argc,argv)
+ *
+ * Main test program
+ *
+ * Input parameters:
+ * argc,argv - guess.
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+
+int main(int argc,char *argv[])
+{
+ int res;
+ memstats_t stats;
+ uint8_t *buffer;
+
+ /*
+ * Parse command line args
+ */
+
+ for (res = 1; res < argc; res++) {
+ if (strcmp(argv[res],"-o") == 0) ohcidebug++;
+ if (strcmp(argv[res],"-u") == 0) usb_noisy++;
+ }
+
+ /*
+ * Open the play area.
+ */
+
+ if (init_devaccess() < 0) {
+ printf("Could not map USB controller\n");
+ }
+
+ /*
+ * Establish signal and exit handlers
+ */
+
+ signal(SIGINT,sighandler);
+ atexit(uninit_devaccess);
+
+ /*
+ * Initialize a buffer pool to point at the play area.
+ * the 'malloc' calls inside our driver will therefore
+ * allocate memory suitable for DMA, just like on real
+ * hardware.
+ */
+
+ KMEMINIT(play_area,PLAY_AREA_SIZE);
+
+ buffer = KMALLOC(512,32);
+
+ printf("-------------------------------------------\n\n");
+
+ /*
+ * Create the OHCI driver instance.
+ */
+
+
+ bus = UBCREATE(&ohci_driver,(void *) device_area);
+
+ /*
+ * Hack: retrieve copy of softc for our exception handler
+ */
+
+ ohci = (ohci_softc_t *) bus->ub_hwsoftc;
+
+ /*
+ * Start the controller.
+ */
+
+ res = UBSTART(bus);
+
+ if (res != 0) {
+ printf("Could not init hardware\n");
+ UBSTOP(bus);
+ exit(1);
+ }
+
+ /*
+ * Init the root hub
+ */
+
+ usb_initroot(bus);
+
+ /*
+ * Main loop - just call interrupt routine to poll
+ */
+
+ while (usbmass_dev== NULL) {
+ usb_poll(bus);
+ usb_daemon(bus);
+ }
+
+ for (res = 0; res < 1000; res++) {
+ usbmass_read_sector(usbmass_dev,0,1,buffer);
+ }
+
+ printf("----- finished reading all sectors ----\n");
+
+ while (running) {
+ usb_poll(bus);
+ usb_daemon(bus);
+ }
+
+ /*
+ * Clean up - get heap statistics to see if we
+ * screwed up.
+ */
+
+ res = KMEMSTATS(&stats);
+ if (res < 0) printf("Warning: heap is not consistent\n");
+ else printf("Heap is ok\n");
+
+ exit(0);
+
+}