1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * Main Module File: usbhack.c
6 * A crude test program to let us tinker with a USB controller
7 * installed in an X86 Linux PC. Eventually we'll clean up
8 * this stuff and incorporate it into CFE.
10 * Author: Mitch Lichtenberg (mpl@broadcom.com)
12 *********************************************************************
14 * Copyright 2000,2001,2002,2003
15 * Broadcom Corporation. All rights reserved.
17 * This software is furnished under license and may be used and
18 * copied only in accordance with the following terms and
19 * conditions. Subject to these conditions, you may download,
20 * copy, install, use, modify and distribute modified or unmodified
21 * copies of this software in source and/or binary form. No title
22 * or ownership is transferred hereby.
24 * 1) Any source code used, modified or distributed must reproduce
25 * and retain this copyright notice and list of conditions
26 * as they appear in the source file.
28 * 2) No right is granted to use any trade name, trademark, or
29 * logo of Broadcom Corporation. The "Broadcom Corporation"
30 * name may not be used to endorse or promote products derived
31 * from this software without the prior written permission of
32 * Broadcom Corporation.
34 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
35 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
36 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
37 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
38 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
39 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
40 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
41 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
42 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
44 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
45 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
46 * THE POSSIBILITY OF SUCH DAMAGE.
47 ********************************************************************* */
56 #include <sys/fcntl.h>
61 #include "lib_malloc.h"
62 #include "lib_queue.h"
67 /* *********************************************************************
69 ********************************************************************* */
71 #define OHCI_WRITECSR(softc,x,y) \
72 *((volatile uint32_t *) ((softc)->ohci_regs + ((x)/sizeof(uint32_t)))) = (y)
73 #define OHCI_READCSR(softc,x) \
74 *((volatile uint32_t *) ((softc)->ohci_regs + ((x)/sizeof(uint32_t))))
76 /* *********************************************************************
78 ********************************************************************* */
83 extern usbdev_t
*usbmass_dev
;
84 extern int usbmass_read_sector(usbdev_t
*dev
,uint32_t sectornum
,uint32_t seccnt
,
88 /* *********************************************************************
89 * Play Area definitions
91 * We use /dev/mem to map two areas - the "play" area and the
94 * The "play" area maps to the upper 1MB of physical memory.
95 * You need to calculate this address yourself based on your system
96 * setup. If you have 256MB of memory, in your lilo.conf file put
101 * where '255' is one less than your system memory size. this
102 * leaves 1MB out of Linux's physical memory map and therefore
103 * leaves it to you to play with. /dev/mem will map this
104 * uncached using the Pentium MTRR registers, but for playing
105 * around this will be fine.
107 * the second area is the "device area" - this is the address
108 * the PCI USB controller's BARs were mapped to. You can find
109 * this by looking through /proc/pci until you find:
111 * Bus 0, device 8, function 0:
112 * USB Controller: OPTi Unknown device (rev 16).
113 * Vendor id=1045. Device id=c861.
114 * Medium devsel. Fast back-to-back capable. IRQ 3.
115 * Master Capable. Latency=32.
116 * Non-prefetchable 32 bit memory at 0xd9100000 [0xd9100000].
118 * The 0xd9100000 will probably be different on your system.
120 * Of course, to make this work you'll need to rebuild the kernel
121 * without USB support, if you're running a recent kernel.
122 * Fortunately(?), I've been using RH 6.2, no USB support there
123 * in the old 2.2 kernels.
125 * Finally, you'll need to run this program as root. Even if
126 * you mess with the permissions on /dev/mem, there are additional
127 * checks in the kernel, so you will lose.
129 * But, the good news is that it works well - I've never crashed
130 * my Linux box, and I can use gdb to debug programs.
131 * You will NOT be able to use GDB to display things in the
132 * play area - I believe GDB doesn't know how to deal with
133 * the uncached nature of the memory there. You can see stuff
134 * in the area by tracing through instructions that read the play
135 * area, and viewing the register contents.
136 ********************************************************************* */
138 #define PLAY_AREA_ADDR (255*1024*1024) /* EDIT ME */
139 #define PLAY_AREA_SIZE (1024*1024)
141 uint8_t *play_area
= MAP_FAILED
;
143 #define DEVICE_AREA_ADDR 0xd9100000 /* EDIT ME */
144 #define DEVICE_AREA_SIZE 4096
146 uint8_t *device_area
= MAP_FAILED
;
148 /* *********************************************************************
150 ********************************************************************* */
153 usbbus_t
*bus
= NULL
;
154 ohci_softc_t
*ohci
= NULL
;
157 /* *********************************************************************
160 * Given a virtual address in the play area, return its physical
164 * v - virtual address
168 ********************************************************************* */
171 uint32_t vtop(void *v
)
173 uint32_t p
= (uint32_t) v
;
175 if (v
== 0) return 0;
177 p
-= (uint32_t) play_area
;
183 /* *********************************************************************
186 * Given a phyiscal address in the play area, return the virtual
190 * p - physical address
194 * virtual address (void pointer)
195 ********************************************************************* */
197 void *ptov(uint32_t p
)
199 if (p
== 0) return 0;
202 p
+= (uint32_t) play_area
;
207 /* *********************************************************************
210 * delay for 'x' milliseconds.
217 ********************************************************************* */
224 ts
.tv_nsec
= x
* 1000000; /* milliseconds */
228 /* *********************************************************************
229 * console_log(tmplt,...)
231 * Display a console log message - this is a CFE function
235 * tmplt - printf string args...
239 ********************************************************************* */
241 void console_log(const char *tmplt
,...)
246 va_start(marker
,tmplt
);
247 vsprintf(buffer
,tmplt
,marker
);
249 printf("%s\n",buffer
);
252 /* *********************************************************************
255 * Open /dev/mem and create the play area
261 * 0 if ok, else error
262 ********************************************************************* */
264 int init_devaccess(void)
268 play_fd
= open("/dev/mem",O_RDWR
);
275 dev_fd
= open("/dev/mem",O_RDWR
| O_SYNC
);
284 play_area
= mmap(NULL
,
286 PROT_READ
|PROT_WRITE
,MAP_SHARED
,
290 if (play_area
!= MAP_FAILED
) {
291 printf("Play area mapped ok at address %p to %p\n",play_area
,play_area
+PLAY_AREA_SIZE
-1);
292 for (idx
= 0; idx
< PLAY_AREA_SIZE
; idx
++) {
293 play_area
[idx
] = 0x55;
294 if (play_area
[idx
] != 0x55) printf("Offset %x doesn't work\n",idx
);
295 play_area
[idx
] = 0xaa;
296 if (play_area
[idx
] != 0xaa) printf("Offset %x doesn't work\n",idx
);
297 play_area
[idx
] = 0x0;
298 if (play_area
[idx
] != 0x0) printf("Offset %x doesn't work\n",idx
);
310 device_area
= mmap(NULL
,
312 PROT_READ
|PROT_WRITE
,MAP_SHARED
,
316 if (device_area
!= MAP_FAILED
) {
317 printf("Device area mapped ok at address %p\n",device_area
);
321 munmap(play_area
,PLAY_AREA_SIZE
);
322 play_area
= MAP_FAILED
;
334 /* *********************************************************************
337 * Turn off access to the /dev/mem area. this will also
338 * set the OHCI controller's state to reset if we were playing
346 ********************************************************************* */
348 void uninit_devaccess(void)
350 if (ohci
->ohci_regs
) {
351 OHCI_WRITECSR(ohci
,R_OHCI_CONTROL
,V_OHCI_CONTROL_HCFS(K_OHCI_HCFS_RESET
));
354 if (play_area
!= MAP_FAILED
) munmap(play_area
,PLAY_AREA_SIZE
);
355 if (device_area
!= MAP_FAILED
) munmap(device_area
,DEVICE_AREA_SIZE
);
357 if (play_fd
> 0) close(play_fd
);
358 if (dev_fd
> 0) close(dev_fd
);
360 device_area
= MAP_FAILED
;
361 play_area
= MAP_FAILED
;
367 /* *********************************************************************
370 * ^C handler - switch off OHCI controller
377 ********************************************************************* */
379 void sighandler(int sig
)
381 signal(SIGINT
,SIG_DFL
);
382 printf("Interrupted, controller reset\n");
383 if (ohci
->ohci_regs
) {
384 OHCI_WRITECSR(ohci
,R_OHCI_CONTROL
,V_OHCI_CONTROL_HCFS(K_OHCI_HCFS_RESET
));
390 extern usb_hcdrv_t ohci_driver
;
392 /* *********************************************************************
395 * Called by lib_malloc, we need to supply it.
402 ********************************************************************* */
404 int xprintf(char *str
)
410 /* *********************************************************************
420 ********************************************************************* */
423 int main(int argc
,char *argv
[])
430 * Parse command line args
433 for (res
= 1; res
< argc
; res
++) {
434 if (strcmp(argv
[res
],"-o") == 0) ohcidebug
++;
435 if (strcmp(argv
[res
],"-u") == 0) usb_noisy
++;
439 * Open the play area.
442 if (init_devaccess() < 0) {
443 printf("Could not map USB controller\n");
447 * Establish signal and exit handlers
450 signal(SIGINT
,sighandler
);
451 atexit(uninit_devaccess
);
454 * Initialize a buffer pool to point at the play area.
455 * the 'malloc' calls inside our driver will therefore
456 * allocate memory suitable for DMA, just like on real
460 KMEMINIT(play_area
,PLAY_AREA_SIZE
);
462 buffer
= KMALLOC(512,32);
464 printf("-------------------------------------------\n\n");
467 * Create the OHCI driver instance.
471 bus
= UBCREATE(&ohci_driver
,(void *) device_area
);
474 * Hack: retrieve copy of softc for our exception handler
477 ohci
= (ohci_softc_t
*) bus
->ub_hwsoftc
;
480 * Start the controller.
486 printf("Could not init hardware\n");
498 * Main loop - just call interrupt routine to poll
501 while (usbmass_dev
== NULL
) {
506 for (res
= 0; res
< 1000; res
++) {
507 usbmass_read_sector(usbmass_dev
,0,1,buffer
);
510 printf("----- finished reading all sectors ----\n");
518 * Clean up - get heap statistics to see if we
522 res
= KMEMSTATS(&stats
);
523 if (res
< 0) printf("Warning: heap is not consistent\n");
524 else printf("Heap is ok\n");