|
0
|
1 //================================================================= |
|
|
2 // |
|
|
3 // gdb_1.cxx |
|
|
4 // |
|
|
5 // Pseudo Driver for GDB |
|
|
6 // |
|
|
7 //================================================================= |
|
|
8 //####COPYRIGHTBEGIN#### |
|
|
9 // |
|
|
10 // ------------------------------------------- |
|
|
11 // The contents of this file are subject to the Cygnus eCos Public License |
|
|
12 // Version 1.0 (the "License"); you may not use this file except in |
|
|
13 // compliance with the License. You may obtain a copy of the License at |
|
|
14 // http://sourceware.cygnus.com/ecos |
|
|
15 // |
|
|
16 // Software distributed under the License is distributed on an "AS IS" |
|
|
17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the |
|
|
18 // License for the specific language governing rights and limitations under |
|
|
19 // the License. |
|
|
20 // |
|
|
21 // The Original Code is eCos - Embedded Cygnus Operating System, released |
|
|
22 // September 30, 1998. |
|
|
23 // |
|
|
24 // The Initial Developer of the Original Code is Cygnus. Portions created |
|
|
25 // by Cygnus are Copyright (C) 1998 Cygnus Solutions. All Rights Reserved. |
|
|
26 // ------------------------------------------- |
|
|
27 // |
|
|
28 //####COPYRIGHTEND#### |
|
|
29 //================================================================= |
|
|
30 //#####DESCRIPTIONBEGIN#### |
|
|
31 // |
|
|
32 // Author(s): proven |
|
|
33 // Contributors: proven |
|
|
34 // Date: 1998-05-30 |
|
|
35 // Description: Class methods for class Cyg_Device_GDB_1 |
|
|
36 //####DESCRIPTIONEND#### |
|
|
37 |
|
|
38 #include <pkgconf/devs.h> // To see if we need to bother |
|
|
39 #ifdef CYG_DEVICE_GDB_1 // Do we need to build this file |
|
|
40 |
|
|
41 #define CYG_DEVICE_INTERNAL |
|
|
42 #include <cyg/devs/gdb/gdb_1.hxx> |
|
|
43 #include <cyg/kernel/sema.hxx> // Cyg_Binary_Semaphore |
|
|
44 #include <stddef.h> // NULL |
|
|
45 |
|
|
46 #ifdef CYG_DEVICE_GDB_1_NAME // Only construct object if there is a name |
|
|
47 CYG_CLASS_DEVICE_GDB_1 CYG_DEVICE_GDB_1_NAME; |
|
|
48 #endif |
|
|
49 |
|
|
50 // ------------------------------------------------------------------------ |
|
|
51 // Constructor for GDB device |
|
|
52 // |
|
|
53 CYG_CLASS_DEVICE_GDB_1::CYG_CLASS_DEVICE_GDB_1() |
|
|
54 : CYG_DEVICE_GDB_1_CLASS() |
|
|
55 { |
|
|
56 CYG_REPORT_FUNCTION(); |
|
|
57 |
|
|
58 // Initialize any data |
|
|
59 |
|
|
60 // write_buffers = NULL; |
|
|
61 |
|
|
62 } |
|
|
63 |
|
|
64 // ------------------------------------------------------------------------ |
|
|
65 // Routines to deal with the new iorb |
|
|
66 // |
|
|
67 |
|
|
68 static const char hexchars[] = "0123456789abcdef"; |
|
|
69 |
|
|
70 static cyg_uint32 |
|
|
71 iorb_compute(char * in_data, cyg_uint32 length, Cyg_IORB * out) |
|
|
72 { |
|
|
73 cyg_uint8 csum = 0; |
|
|
74 cyg_ucount8 i; |
|
|
75 char * data; |
|
|
76 |
|
|
77 data = (char *)out->buffer; |
|
|
78 |
|
|
79 if (length > CYGNUM_DEVICE_GDB_BUFFER_SIZE) { |
|
|
80 length = CYGNUM_DEVICE_GDB_BUFFER_SIZE; |
|
|
81 } |
|
|
82 |
|
|
83 data[0] = '$'; |
|
|
84 data[1] = 'O'; |
|
|
85 csum += data[1]; |
|
|
86 for (i = 0; i < length; i++) { |
|
|
87 data[(i*2)+2] = hexchars[(in_data[i] >> 4) & 0x0f]; |
|
|
88 data[(i*2)+3] = hexchars[in_data[i] & 0x0f]; |
|
|
89 csum += data[(i*2)+2]; |
|
|
90 csum += data[(i*2)+3]; |
|
|
91 } |
|
|
92 data[(i*2)+2] = '#'; |
|
|
93 data[(i*2)+3] = hexchars[csum >> 4]; |
|
|
94 data[(i*2)+4] = hexchars[csum & 0x0f]; |
|
|
95 |
|
|
96 out->buffer_length = (i * 2) + 5; |
|
|
97 return (length); |
|
|
98 } |
|
|
99 |
|
|
100 void |
|
|
101 CYG_CLASS_DEVICE_GDB_1::iorb_setup(CYG_CLASS_DEVICE_GDB_1 * data) |
|
|
102 { |
|
|
103 Cyg_IORB * iorb; |
|
|
104 |
|
|
105 iorb = data->gdb_write_buffer_first; |
|
|
106 |
|
|
107 /* set up gdb_write_iorb */ |
|
|
108 data->gdb_write_iorb.buffer = data->gdb_write_buf; |
|
|
109 data->gdb_write_iorb.callback = iorb_callback; |
|
|
110 data->gdb_write_iorb.callback_data = (CYG_ADDRWORD)data; |
|
|
111 iorb->xferred_length = iorb_compute((char *)iorb->buffer, iorb->buffer_length, &data->gdb_write_iorb); |
|
|
112 |
|
|
113 /* Save the length of the original data that still needs to be sent */ |
|
|
114 data->gdb_write_length = iorb->buffer_length - iorb->xferred_length; |
|
|
115 |
|
|
116 /* Start the write process */ |
|
|
117 data->io_write(&data->gdb_write_iorb); |
|
|
118 } |
|
|
119 |
|
|
120 void |
|
|
121 CYG_CLASS_DEVICE_GDB_1::iorb_callback(Cyg_IORB *iorb) |
|
|
122 { |
|
|
123 CYG_CLASS_DEVICE_GDB_1 * foo = (CYG_CLASS_DEVICE_GDB_1 *)iorb->callback_data; |
|
|
124 cyg_uint32 length; |
|
|
125 |
|
|
126 if (foo->gdb_write_length) { |
|
|
127 /* Compute the offset into the original data */ |
|
|
128 length = iorb_compute ((char *)foo->gdb_write_buffer_first->buffer + |
|
|
129 foo->gdb_write_buffer_first->xferred_length, foo->gdb_write_length, |
|
|
130 &foo->gdb_write_iorb); |
|
|
131 |
|
|
132 foo->gdb_write_buffer_first->xferred_length += length; |
|
|
133 foo->gdb_write_length -= length; |
|
|
134 |
|
|
135 foo->io_write(&foo->gdb_write_iorb); |
|
|
136 |
|
|
137 } else { |
|
|
138 Cyg_IORB * done; |
|
|
139 |
|
|
140 /* Get the next iorb */ |
|
|
141 done = foo->gdb_write_buffer_first; |
|
|
142 foo->gdb_write_buffer_first = foo->gdb_write_buffer_first->next; |
|
|
143 if (foo->gdb_write_buffer_first == NULL) { |
|
|
144 foo->gdb_write_buffer_last = NULL; |
|
|
145 } else { |
|
|
146 foo->iorb_setup(foo); |
|
|
147 } |
|
|
148 if (done->callback) { |
|
|
149 done->callback(done); |
|
|
150 } |
|
|
151 } |
|
|
152 } |
|
|
153 |
|
|
154 // ------------------------------------------------------------------------ |
|
|
155 // Asynchronous write |
|
|
156 // |
|
|
157 |
|
|
158 cyg_int32 |
|
|
159 CYG_CLASS_DEVICE_GDB_1::io_write_asynchronous(Cyg_IORB * iorb) |
|
|
160 { |
|
|
161 iorb->next = NULL; |
|
|
162 Cyg_Scheduler::lock(); |
|
|
163 if (gdb_write_buffer_first == NULL) { |
|
|
164 gdb_write_buffer_first = iorb; |
|
|
165 gdb_write_buffer_last = iorb; |
|
|
166 Cyg_Scheduler::unlock(); |
|
|
167 iorb_setup(this); |
|
|
168 } else { |
|
|
169 gdb_write_buffer_last->next = iorb; |
|
|
170 gdb_write_buffer_last = iorb; |
|
|
171 Cyg_Scheduler::unlock(); |
|
|
172 } |
|
|
173 return 0; |
|
|
174 } |
|
|
175 |
|
|
176 // ------------------------------------------------------------------------ |
|
|
177 // Synchronous write |
|
|
178 // |
|
|
179 |
|
|
180 static void |
|
|
181 callback(Cyg_IORB *iorb) |
|
|
182 { |
|
|
183 Cyg_Binary_Semaphore * data = (Cyg_Binary_Semaphore *)iorb->callback_data; |
|
|
184 data->post(); |
|
|
185 } |
|
|
186 |
|
|
187 cyg_int32 |
|
|
188 CYG_CLASS_DEVICE_GDB_1::io_write_blocking(Cyg_IORB * iorb) |
|
|
189 { |
|
|
190 Cyg_Binary_Semaphore write(0); |
|
|
191 |
|
|
192 // We need a callback routine to wake us up |
|
|
193 iorb->callback_data = (CYG_ADDRESS)&write; |
|
|
194 iorb->callback = callback; |
|
|
195 iorb->next = NULL; |
|
|
196 |
|
|
197 Cyg_Scheduler::lock(); |
|
|
198 if (gdb_write_buffer_first == NULL) { |
|
|
199 gdb_write_buffer_last = iorb; |
|
|
200 gdb_write_buffer_first = iorb; |
|
|
201 } else { |
|
|
202 gdb_write_buffer_last->next = iorb; |
|
|
203 gdb_write_buffer_last = iorb; |
|
|
204 Cyg_Scheduler::unlock(); |
|
|
205 write.wait(); |
|
|
206 return 0; |
|
|
207 } |
|
|
208 |
|
|
209 Cyg_Scheduler::unlock(); |
|
|
210 iorb_setup(this); |
|
|
211 write.wait(); |
|
|
212 return 0; |
|
|
213 } |
|
|
214 |
|
|
215 // ------------------------------------------------------------------------ |
|
|
216 // Assert versions. These versions bypass most of the driver code. |
|
|
217 // These are to be used by the BSP or asserts. Only use them once |
|
|
218 // start_sync() is called and when done normal operations is |
|
|
219 // restarted with the end_sync() mode. |
|
|
220 // |
|
|
221 // Note DO NOT DO LOCKING IN THIS ROUTINE!!! |
|
|
222 // |
|
|
223 |
|
|
224 cyg_int32 |
|
|
225 CYG_CLASS_DEVICE_GDB_1::io_write_assert(Cyg_IORB * iorb) |
|
|
226 { |
|
|
227 Cyg_IORB assert_iorb; |
|
|
228 char assert_buffer[256]; |
|
|
229 cyg_uint32 length, length_left; |
|
|
230 |
|
|
231 assert_iorb.callback = NULL; |
|
|
232 assert_iorb.callback_data = 0; |
|
|
233 assert_iorb.buffer = assert_buffer; |
|
|
234 for (length_left = iorb->buffer_length; length_left; length_left -= length) { |
|
|
235 length = iorb_compute((char *)iorb->buffer + iorb->xferred_length, |
|
|
236 length_left, &assert_iorb); |
|
|
237 iorb->xferred_length += length; |
|
|
238 (CYG_DEVICE_GDB_1_CLASS *)this->io_write_assert(&assert_iorb); |
|
|
239 } |
|
|
240 |
|
|
241 return 0; |
|
|
242 } |
|
|
243 |
|
|
244 #endif // #ifdef CYG_DEVICE_GDB_1 |
|
|
245 // EOF gdb_1.cxx |