]>
Commit | Line | Data |
---|---|---|
1dda0b1f WD |
1 | /* |
2 | * Bedbug Functions specific to the MPC603e core | |
3 | */ | |
4 | ||
5 | #include <common.h> | |
6 | #include <command.h> | |
7 | #include <linux/ctype.h> | |
8bde7f77 | 8 | #include <bedbug/type.h> |
1dda0b1f WD |
9 | #include <bedbug/bedbug.h> |
10 | #include <bedbug/regs.h> | |
11 | #include <bedbug/ppc.h> | |
12 | ||
13 | #if (CONFIG_COMMANDS & CFG_CMD_BEDBUG) && (defined(CONFIG_MPC824X) || defined(CONFIG_MPC8260)) | |
14 | ||
15 | #define MAX_BREAK_POINTS 1 | |
16 | ||
17 | extern CPU_DEBUG_CTX bug_ctx; | |
18 | ||
19 | void bedbug603e_init __P((void)); | |
20 | void bedbug603e_do_break __P((cmd_tbl_t*,int,int,char*[])); | |
21 | void bedbug603e_break_isr __P((struct pt_regs*)); | |
22 | int bedbug603e_find_empty __P((void)); | |
23 | int bedbug603e_set __P((int,unsigned long)); | |
24 | int bedbug603e_clear __P((int)); | |
25 | ||
26 | \f | |
27 | /* ====================================================================== | |
28 | * Initialize the global bug_ctx structure for the processor. Clear all | |
29 | * of the breakpoints. | |
30 | * ====================================================================== */ | |
31 | ||
32 | void bedbug603e_init( void ) | |
33 | { | |
34 | int i; | |
35 | /* -------------------------------------------------- */ | |
36 | ||
37 | bug_ctx.hw_debug_enabled = 0; | |
38 | bug_ctx.stopped = 0; | |
39 | bug_ctx.current_bp = 0; | |
40 | bug_ctx.regs = NULL; | |
41 | ||
42 | bug_ctx.do_break = bedbug603e_do_break; | |
43 | bug_ctx.break_isr = bedbug603e_break_isr; | |
44 | bug_ctx.find_empty = bedbug603e_find_empty; | |
45 | bug_ctx.set = bedbug603e_set; | |
46 | bug_ctx.clear = bedbug603e_clear; | |
47 | ||
48 | for( i = 1; i <= MAX_BREAK_POINTS; ++i ) | |
49 | (*bug_ctx.clear)( i ); | |
50 | ||
51 | puts ("BEDBUG:ready\n"); | |
52 | return; | |
53 | } /* bedbug_init_breakpoints */ | |
54 | ||
55 | ||
56 | \f | |
57 | /* ====================================================================== | |
58 | * Set/clear/show the hardware breakpoint for the 603e. The "off" | |
59 | * string will disable a specific breakpoint. The "show" string will | |
60 | * display the current breakpoints. Otherwise an address will set a | |
61 | * breakpoint at that address. Setting a breakpoint uses the CPU-specific | |
62 | * set routine which will assign a breakpoint number. | |
63 | * ====================================================================== */ | |
64 | ||
65 | void bedbug603e_do_break (cmd_tbl_t *cmdtp, int flag, int argc, | |
8bde7f77 | 66 | char *argv[]) |
1dda0b1f WD |
67 | { |
68 | long addr; /* Address to break at */ | |
69 | int which_bp; /* Breakpoint number */ | |
70 | /* -------------------------------------------------- */ | |
71 | ||
72 | if (argc < 2) | |
73 | { | |
74 | printf ("Usage:\n%s\n", cmdtp->usage); | |
75 | return; | |
76 | } | |
77 | ||
78 | /* Turn off a breakpoint */ | |
79 | ||
80 | if( strcmp( argv[ 1 ], "off" ) == 0 ) | |
81 | { | |
82 | if( bug_ctx.hw_debug_enabled == 0 ) | |
83 | { | |
84 | printf( "No breakpoints enabled\n" ); | |
85 | return; | |
86 | } | |
87 | ||
88 | which_bp = simple_strtoul( argv[ 2 ], NULL, 10 ); | |
89 | ||
90 | if( bug_ctx.clear ) | |
91 | (*bug_ctx.clear)( which_bp ); | |
92 | ||
93 | printf( "Breakpoint %d removed\n", which_bp ); | |
94 | return; | |
95 | } | |
96 | ||
97 | /* Show a list of breakpoints */ | |
98 | ||
99 | if( strcmp( argv[ 1 ], "show" ) == 0 ) | |
100 | { | |
101 | for( which_bp = 1; which_bp <= MAX_BREAK_POINTS; ++which_bp ) | |
102 | { | |
103 | ||
104 | addr = GET_IABR(); | |
105 | ||
106 | printf( "Breakpoint [%d]: ", which_bp ); | |
107 | if( (addr & 0x00000002) == 0 ) | |
108 | printf( "NOT SET\n" ); | |
109 | else | |
110 | disppc( (unsigned char *)(addr & 0xFFFFFFFC), 0, 1, bedbug_puts, F_RADHEX ); | |
111 | } | |
112 | return; | |
113 | } | |
114 | ||
115 | /* Set a breakpoint at the address */ | |
116 | ||
117 | if(!(( isdigit( argv[ 1 ][ 0 ] )) || | |
8bde7f77 WD |
118 | (( argv[ 1 ][ 0 ] >= 'a' ) && ( argv[ 1 ][ 0 ] <= 'f' )) || |
119 | (( argv[ 1 ][ 0 ] >= 'A' ) && ( argv[ 1 ][ 0 ] <= 'F' )))) | |
1dda0b1f WD |
120 | { |
121 | printf ("Usage:\n%s\n", cmdtp->usage); | |
122 | return; | |
123 | } | |
124 | ||
125 | addr = simple_strtoul( argv[ 1 ], NULL, 16 ); | |
126 | ||
127 | if(( bug_ctx.set ) && ( which_bp = (*bug_ctx.set)( 0, addr )) > 0 ) | |
128 | { | |
129 | printf( "Breakpoint [%d]: ", which_bp ); | |
130 | disppc( (unsigned char *)addr, 0, 1, bedbug_puts, F_RADHEX ); | |
131 | } | |
132 | ||
133 | return; | |
134 | } /* bedbug603e_do_break */ | |
135 | ||
136 | ||
137 | \f | |
138 | /* ====================================================================== | |
139 | * Handle a breakpoint. Enter a mini main loop. Stay in the loop until | |
140 | * the stopped flag in the debug context is cleared. | |
141 | * ====================================================================== */ | |
142 | ||
143 | void bedbug603e_break_isr( struct pt_regs *regs ) | |
144 | { | |
145 | unsigned long addr; /* Address stopped at */ | |
146 | /* -------------------------------------------------- */ | |
147 | ||
148 | bug_ctx.current_bp = 1; | |
149 | addr = GET_IABR() & 0xFFFFFFFC; | |
150 | ||
151 | bedbug_main_loop( addr, regs ); | |
152 | return; | |
153 | } /* bedbug603e_break_isr */ | |
154 | ||
155 | ||
156 | \f | |
157 | /* ====================================================================== | |
158 | * See if the hardware breakpoint is available. | |
159 | * ====================================================================== */ | |
160 | ||
161 | int bedbug603e_find_empty( void ) | |
162 | { | |
163 | /* -------------------------------------------------- */ | |
164 | ||
165 | if( (GET_IABR() && 0x00000002) == 0 ) | |
166 | return 1; | |
167 | ||
168 | return 0; | |
169 | } /* bedbug603e_find_empty */ | |
170 | ||
171 | ||
172 | \f | |
173 | /* ====================================================================== | |
174 | * Set a breakpoint. If 'which_bp' is zero then find an unused breakpoint | |
175 | * number, otherwise reassign the given breakpoint. If hardware debugging | |
176 | * is not enabled, then turn it on via the MSR and DBCR0. Set the break | |
177 | * address in the IABR register. | |
178 | * ====================================================================== */ | |
179 | ||
180 | int bedbug603e_set( int which_bp, unsigned long addr ) | |
181 | { | |
182 | /* -------------------------------------------------- */ | |
183 | ||
184 | if(( addr & 0x00000003 ) != 0 ) | |
185 | { | |
186 | printf( "Breakpoints must be on a 32 bit boundary\n" ); | |
187 | return 0; | |
188 | } | |
189 | ||
190 | /* Only look if which_bp == 0, else use which_bp */ | |
191 | if(( bug_ctx.find_empty ) && ( !which_bp ) && | |
192 | ( which_bp = (*bug_ctx.find_empty)()) == 0 ) | |
193 | { | |
194 | printf( "All breakpoints in use\n" ); | |
195 | return 0; | |
196 | } | |
197 | ||
198 | if( which_bp < 1 || which_bp > MAX_BREAK_POINTS ) | |
199 | { | |
200 | printf( "Invalid break point # %d\n", which_bp ); | |
201 | return 0; | |
202 | } | |
203 | ||
204 | if( ! bug_ctx.hw_debug_enabled ) | |
205 | { | |
206 | bug_ctx.hw_debug_enabled = 1; | |
207 | } | |
208 | ||
209 | SET_IABR( addr | 0x00000002 ); | |
210 | ||
211 | return which_bp; | |
212 | } /* bedbug603e_set */ | |
213 | ||
214 | ||
215 | \f | |
216 | /* ====================================================================== | |
217 | * Disable a specific breakoint by setting the IABR register to zero. | |
218 | * ====================================================================== */ | |
219 | ||
220 | int bedbug603e_clear( int which_bp ) | |
221 | { | |
222 | /* -------------------------------------------------- */ | |
223 | ||
224 | if( which_bp < 1 || which_bp > MAX_BREAK_POINTS ) | |
225 | { | |
226 | printf( "Invalid break point # (%d)\n", which_bp ); | |
227 | return -1; | |
228 | } | |
229 | ||
230 | SET_IABR( 0 ); | |
231 | ||
232 | return 0; | |
233 | } /* bedbug603e_clear */ | |
234 | ||
235 | ||
236 | /* ====================================================================== */ | |
237 | #endif |