diff options
author | Michael Sparmann <theseven@rockbox.org> | 2010-08-12 08:35:43 +0000 |
---|---|---|
committer | Michael Sparmann <theseven@rockbox.org> | 2010-08-12 08:35:43 +0000 |
commit | f3834a46262a548051d882db813f4d408939989b (patch) | |
tree | 211337dc3b552c2d584d1bd5ed1ba4091ca03ff7 | |
parent | ad4deec074ad071db216049b796b74a3820bc481 (diff) | |
download | rockbox-f3834a46262a548051d882db813f4d408939989b.tar.gz rockbox-f3834a46262a548051d882db813f4d408939989b.zip |
emBIOS backports part one: Fix an annoying race condition in the Synopsys OTG driver, and a bit of const correctness.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27779 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/export/usb_drv.h | 4 | ||||
-rw-r--r-- | firmware/target/arm/usb-s3c6400x.c | 43 |
2 files changed, 26 insertions, 21 deletions
diff --git a/firmware/export/usb_drv.h b/firmware/export/usb_drv.h index fad9c79c10..c29d2892d6 100644 --- a/firmware/export/usb_drv.h +++ b/firmware/export/usb_drv.h | |||
@@ -33,8 +33,8 @@ void usb_drv_attach(void); | |||
33 | void usb_drv_int(void); /* Call from target INT handler */ | 33 | void usb_drv_int(void); /* Call from target INT handler */ |
34 | void usb_drv_stall(int endpoint, bool stall,bool in); | 34 | void usb_drv_stall(int endpoint, bool stall,bool in); |
35 | bool usb_drv_stalled(int endpoint,bool in); | 35 | bool usb_drv_stalled(int endpoint,bool in); |
36 | int usb_drv_send(int endpoint, void* ptr, int length); | 36 | int usb_drv_send(int endpoint, const void* ptr, int length); |
37 | int usb_drv_send_nonblocking(int endpoint, void* ptr, int length); | 37 | int usb_drv_send_nonblocking(int endpoint, const void* ptr, int length); |
38 | int usb_drv_recv(int endpoint, void* ptr, int length); | 38 | int usb_drv_recv(int endpoint, void* ptr, int length); |
39 | void usb_drv_ack(struct usb_ctrlrequest* req); | 39 | void usb_drv_ack(struct usb_ctrlrequest* req); |
40 | void usb_drv_set_address(int address); | 40 | void usb_drv_set_address(int address); |
diff --git a/firmware/target/arm/usb-s3c6400x.c b/firmware/target/arm/usb-s3c6400x.c index 6fbf453cd1..8755eabdf9 100644 --- a/firmware/target/arm/usb-s3c6400x.c +++ b/firmware/target/arm/usb-s3c6400x.c | |||
@@ -148,6 +148,8 @@ static void usb_reset(void) | |||
148 | while (GRSTCTL & 1); /* Wait for OTG to ack reset */ | 148 | while (GRSTCTL & 1); /* Wait for OTG to ack reset */ |
149 | while (!(GRSTCTL & 0x80000000)); /* Wait for OTG AHB master idle */ | 149 | while (!(GRSTCTL & 0x80000000)); /* Wait for OTG AHB master idle */ |
150 | 150 | ||
151 | GRXFSIZ = 0x00000200; /* RX FIFO: 512 bytes */ | ||
152 | GNPTXFSIZ = 0x02000200; /* Non-periodic TX FIFO: 512 bytes */ | ||
151 | GAHBCFG = 0x27; /* OTG AHB config: Unmask ints, burst length 4, DMA on */ | 153 | GAHBCFG = 0x27; /* OTG AHB config: Unmask ints, burst length 4, DMA on */ |
152 | GUSBCFG = 0x1408; /* OTG: 16bit PHY and some reserved bits */ | 154 | GUSBCFG = 0x1408; /* OTG: 16bit PHY and some reserved bits */ |
153 | 155 | ||
@@ -155,6 +157,7 @@ static void usb_reset(void) | |||
155 | DCTL = 0x800; /* Soft Reconnect */ | 157 | DCTL = 0x800; /* Soft Reconnect */ |
156 | DIEPMSK = 0x0D; /* IN EP interrupt mask */ | 158 | DIEPMSK = 0x0D; /* IN EP interrupt mask */ |
157 | DOEPMSK = 0x0D; /* IN EP interrupt mask */ | 159 | DOEPMSK = 0x0D; /* IN EP interrupt mask */ |
160 | DAINTMSK = 0xFFFFFFFF; /* Enable interrupts on all endpoints */ | ||
158 | GINTMSK = 0xC3000; /* Interrupt mask: IN event, OUT event, bus reset */ | 161 | GINTMSK = 0xC3000; /* Interrupt mask: IN event, OUT event, bus reset */ |
159 | 162 | ||
160 | reset_endpoints(1); | 163 | reset_endpoints(1); |
@@ -164,14 +167,16 @@ static void usb_reset(void) | |||
164 | void INT_USB_FUNC(void) | 167 | void INT_USB_FUNC(void) |
165 | { | 168 | { |
166 | int i; | 169 | int i; |
167 | if (GINTSTS & 0x1000) /* bus reset */ | 170 | uint32_t ints = GINTSTS; |
171 | uint32_t epints; | ||
172 | if (ints & 0x1000) /* bus reset */ | ||
168 | { | 173 | { |
169 | DCFG = 4; /* Address 0 */ | 174 | DCFG = 4; /* Address 0 */ |
170 | reset_endpoints(1); | 175 | reset_endpoints(1); |
171 | usb_core_bus_reset(); | 176 | usb_core_bus_reset(); |
172 | } | 177 | } |
173 | 178 | ||
174 | if (GINTSTS & 0x2000) /* enumeration done, we now know the speed */ | 179 | if (ints & 0x2000) /* enumeration done, we now know the speed */ |
175 | { | 180 | { |
176 | /* Set up the maximum packet sizes accordingly */ | 181 | /* Set up the maximum packet sizes accordingly */ |
177 | uint32_t maxpacket = usb_drv_port_speed() ? 512 : 64; | 182 | uint32_t maxpacket = usb_drv_port_speed() ? 512 : 64; |
@@ -181,11 +186,11 @@ void INT_USB_FUNC(void) | |||
181 | DOEPCTL4 = (DOEPCTL4 & ~0x000003FF) | maxpacket; | 186 | DOEPCTL4 = (DOEPCTL4 & ~0x000003FF) | maxpacket; |
182 | } | 187 | } |
183 | 188 | ||
184 | if (GINTSTS & 0x40000) /* IN EP event */ | 189 | if (ints & 0x40000) /* IN EP event */ |
185 | for (i = 0; i < 5; i ++) | 190 | for (i = 0; i < 4; i += i + 1) // 0, 1, 3 |
186 | if (i != 2 && i != 4 && DIEPINT(i)) | 191 | if ((epints = DIEPINT(i))) |
187 | { | 192 | { |
188 | if (DIEPINT(i) & 1) /* Transfer completed */ | 193 | if (epints & 1) /* Transfer completed */ |
189 | { | 194 | { |
190 | invalidate_dcache(); | 195 | invalidate_dcache(); |
191 | int bytes = endpoints[i].size - (DIEPTSIZ(i) & 0x3FFFF); | 196 | int bytes = endpoints[i].size - (DIEPTSIZ(i) & 0x3FFFF); |
@@ -198,9 +203,9 @@ void INT_USB_FUNC(void) | |||
198 | wakeup_signal(&endpoints[i].complete); | 203 | wakeup_signal(&endpoints[i].complete); |
199 | } | 204 | } |
200 | } | 205 | } |
201 | if (DIEPINT(i) & 4) /* AHB error */ | 206 | if (epints & 4) /* AHB error */ |
202 | panicf("USB: AHB error on IN EP%d", i); | 207 | panicf("USB: AHB error on IN EP%d", i); |
203 | if (DIEPINT(i) & 8) /* Timeout */ | 208 | if (epints & 8) /* Timeout */ |
204 | { | 209 | { |
205 | if (endpoints[i].busy) | 210 | if (endpoints[i].busy) |
206 | { | 211 | { |
@@ -210,14 +215,14 @@ void INT_USB_FUNC(void) | |||
210 | wakeup_signal(&endpoints[i].complete); | 215 | wakeup_signal(&endpoints[i].complete); |
211 | } | 216 | } |
212 | } | 217 | } |
213 | DIEPINT(i) = DIEPINT(i); | 218 | DIEPINT(i) = epints; |
214 | } | 219 | } |
215 | 220 | ||
216 | if (GINTSTS & 0x80000) /* OUT EP event */ | 221 | if (ints & 0x80000) /* OUT EP event */ |
217 | for (i = 0; i < 5; i += 2) | 222 | for (i = 0; i < 5; i += 2) |
218 | if (DOEPINT(i)) | 223 | if ((epints = DOEPINT(i))) |
219 | { | 224 | { |
220 | if (DOEPINT(i) & 1) /* Transfer completed */ | 225 | if (epints & 1) /* Transfer completed */ |
221 | { | 226 | { |
222 | invalidate_dcache(); | 227 | invalidate_dcache(); |
223 | int bytes = endpoints[i].size - (DOEPTSIZ(i) & 0x3FFFF); | 228 | int bytes = endpoints[i].size - (DOEPTSIZ(i) & 0x3FFFF); |
@@ -230,9 +235,9 @@ void INT_USB_FUNC(void) | |||
230 | wakeup_signal(&endpoints[i].complete); | 235 | wakeup_signal(&endpoints[i].complete); |
231 | } | 236 | } |
232 | } | 237 | } |
233 | if (DOEPINT(i) & 4) /* AHB error */ | 238 | if (epints & 4) /* AHB error */ |
234 | panicf("USB: AHB error on OUT EP%d", i); | 239 | panicf("USB: AHB error on OUT EP%d", i); |
235 | if (DOEPINT(i) & 8) /* SETUP phase done */ | 240 | if (epints & 8) /* SETUP phase done */ |
236 | { | 241 | { |
237 | invalidate_dcache(); | 242 | invalidate_dcache(); |
238 | if (i == 0) | 243 | if (i == 0) |
@@ -255,10 +260,10 @@ void INT_USB_FUNC(void) | |||
255 | DOEPDMA0 = (uint32_t)&ctrlreq; | 260 | DOEPDMA0 = (uint32_t)&ctrlreq; |
256 | DOEPCTL0 |= 0x84000000; | 261 | DOEPCTL0 |= 0x84000000; |
257 | } | 262 | } |
258 | DOEPINT(i) = DOEPINT(i); | 263 | DOEPINT(i) = epints; |
259 | } | 264 | } |
260 | 265 | ||
261 | GINTSTS = GINTSTS; | 266 | GINTSTS = ints; |
262 | } | 267 | } |
263 | 268 | ||
264 | void usb_drv_set_address(int address) | 269 | void usb_drv_set_address(int address) |
@@ -270,7 +275,7 @@ void usb_drv_set_address(int address) | |||
270 | into the USB core, which will then call this dummy function. */ | 275 | into the USB core, which will then call this dummy function. */ |
271 | } | 276 | } |
272 | 277 | ||
273 | static void ep_send(int ep, void *ptr, int length) | 278 | static void ep_send(int ep, const void *ptr, int length) |
274 | { | 279 | { |
275 | endpoints[ep].busy = true; | 280 | endpoints[ep].busy = true; |
276 | endpoints[ep].size = length; | 281 | endpoints[ep].size = length; |
@@ -313,7 +318,7 @@ static void ep_recv(int ep, void *ptr, int length) | |||
313 | DOEPCTL(ep) |= 0x84000000; /* EPx OUT ENABLE CLEARNAK */ | 318 | DOEPCTL(ep) |= 0x84000000; /* EPx OUT ENABLE CLEARNAK */ |
314 | } | 319 | } |
315 | 320 | ||
316 | int usb_drv_send(int endpoint, void *ptr, int length) | 321 | int usb_drv_send(int endpoint, const void *ptr, int length) |
317 | { | 322 | { |
318 | endpoint &= 0x7f; | 323 | endpoint &= 0x7f; |
319 | endpoints[endpoint].done = false; | 324 | endpoints[endpoint].done = false; |
@@ -323,7 +328,7 @@ int usb_drv_send(int endpoint, void *ptr, int length) | |||
323 | return endpoints[endpoint].rc; | 328 | return endpoints[endpoint].rc; |
324 | } | 329 | } |
325 | 330 | ||
326 | int usb_drv_send_nonblocking(int endpoint, void *ptr, int length) | 331 | int usb_drv_send_nonblocking(int endpoint, const void *ptr, int length) |
327 | { | 332 | { |
328 | ep_send(endpoint & 0x7f, ptr, length); | 333 | ep_send(endpoint & 0x7f, ptr, length); |
329 | return 0; | 334 | return 0; |