summaryrefslogtreecommitdiff
path: root/utils/hwstub/stub
diff options
context:
space:
mode:
Diffstat (limited to 'utils/hwstub/stub')
-rw-r--r--utils/hwstub/stub/SOURCES2
-rw-r--r--utils/hwstub/stub/asm/arm/atomic_rw.S58
-rw-r--r--utils/hwstub/stub/asm/mips/atomic_rw.S61
-rw-r--r--utils/hwstub/stub/main.c72
-rw-r--r--utils/hwstub/stub/protocol.h2
-rw-r--r--utils/hwstub/stub/target.h8
6 files changed, 200 insertions, 3 deletions
diff --git a/utils/hwstub/stub/SOURCES b/utils/hwstub/stub/SOURCES
index 1b0b56072d..c91580c966 100644
--- a/utils/hwstub/stub/SOURCES
+++ b/utils/hwstub/stub/SOURCES
@@ -2,9 +2,11 @@
2asm/arm/memcpy.S 2asm/arm/memcpy.S
3asm/arm/memmove.S 3asm/arm/memmove.S
4asm/arm/memset.S 4asm/arm/memset.S
5asm/arm/atomic_rw.S
5#elif defined(CPU_MIPS) 6#elif defined(CPU_MIPS)
6asm/mips/memcpy.S 7asm/mips/memcpy.S
7asm/mips/memset.S 8asm/mips/memset.S
9asm/mips/atomic_rw.S
8#else 10#else
9#error "Unimplemented ISA" 11#error "Unimplemented ISA"
10#endif 12#endif
diff --git a/utils/hwstub/stub/asm/arm/atomic_rw.S b/utils/hwstub/stub/asm/arm/atomic_rw.S
new file mode 100644
index 0000000000..cb6272b4dc
--- /dev/null
+++ b/utils/hwstub/stub/asm/arm/atomic_rw.S
@@ -0,0 +1,58 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2014 by Marcin Bukat
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20
21 .section .text, "ax", %progbits
22 .global target_read8
23 .type target_read8, %function
24 .global target_read16
25 .type target_read16, %function
26 .global target_read32
27 .type target_read32, %function
28 .global target_write8
29 .type target_write8, %function
30 .global target_write16
31 .type target_write16, %function
32 .global target_write32
33 .type target_write32, %function
34
35target_read8:
36 ldrb r0, [r0]
37 bx lr
38
39target_read16:
40 ldrh r0, [r0]
41 bx lr
42
43target_read32:
44 ldr r0, [r0]
45 bx lr
46
47target_write8:
48 strb r1, [r0]
49 bx lr
50
51target_write16:
52 strh r1, [r0]
53 bx lr
54
55target_write32:
56 str r1, [r0]
57 bx lr
58
diff --git a/utils/hwstub/stub/asm/mips/atomic_rw.S b/utils/hwstub/stub/asm/mips/atomic_rw.S
new file mode 100644
index 0000000000..47c4213a5d
--- /dev/null
+++ b/utils/hwstub/stub/asm/mips/atomic_rw.S
@@ -0,0 +1,61 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2014 by Marcin Bukat
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20#include "mips.h"
21
22 .set noreorder
23 .section .text, "ax", %progbits
24 .global target_read8
25 .type target_read8, %function
26 .global target_read16
27 .type target_read16, %function
28 .global target_read32
29 .type target_read32, %function
30 .global target_write8
31 .type target_write8, %function
32 .global target_write16
33 .type target_write16, %function
34 .global target_write32
35 .type target_write32, %function
36
37target_read8:
38 jr ra
39 lbu v0, 0(a0)
40
41target_read16:
42 jr ra
43 lhu v0, 0(a0)
44
45target_read32:
46 jr ra
47 lw v0, 0(a0)
48
49target_write8:
50 jr ra
51 sb a1, 0(a0)
52
53target_write16:
54 jr ra
55 sh a1, 0(a0)
56
57target_write32:
58 jr ra
59 sw a1, 0(a0)
60
61 .set reorder
diff --git a/utils/hwstub/stub/main.c b/utils/hwstub/stub/main.c
index 4e54b8fd89..3604cfdae0 100644
--- a/utils/hwstub/stub/main.c
+++ b/utils/hwstub/stub/main.c
@@ -356,6 +356,49 @@ static void handle_get_log(struct usb_ctrlrequest *req)
356 enable_logf(true); 356 enable_logf(true);
357} 357}
358 358
359/* default implementation, relying on the compiler to produce correct code,
360 * targets should reimplement this... */
361uint8_t __attribute__((weak)) target_read8(const void *addr)
362{
363 return *(volatile uint8_t *)addr;
364}
365
366uint16_t __attribute__((weak)) target_read16(const void *addr)
367{
368 return *(volatile uint16_t *)addr;
369}
370
371uint32_t __attribute__((weak)) target_read32(const void *addr)
372{
373 return *(volatile uint32_t *)addr;
374}
375
376void __attribute__((weak)) target_write8(void *addr, uint8_t val)
377{
378 *(volatile uint8_t *)addr = val;
379}
380
381void __attribute__((weak)) target_write16(void *addr, uint16_t val)
382{
383 *(volatile uint16_t *)addr = val;
384}
385
386void __attribute__((weak)) target_write32(void *addr, uint32_t val)
387{
388 *(volatile uint32_t *)addr = val;
389}
390
391static bool read_atomic(void *dst, void *src, size_t sz)
392{
393 switch(sz)
394 {
395 case 1: *(uint8_t *)dst = target_read8(src); return true;
396 case 2: *(uint16_t *)dst = target_read16(src); return true;
397 case 4: *(uint32_t *)dst = target_read32(src); return true;
398 default: return false;
399 }
400}
401
359static void handle_read(struct usb_ctrlrequest *req) 402static void handle_read(struct usb_ctrlrequest *req)
360{ 403{
361 static uint32_t last_addr = 0; 404 static uint32_t last_addr = 0;
@@ -377,13 +420,30 @@ static void handle_read(struct usb_ctrlrequest *req)
377 { 420 {
378 if(id != last_id) 421 if(id != last_id)
379 return usb_drv_stall(EP_CONTROL, true, true); 422 return usb_drv_stall(EP_CONTROL, true, true);
380 memcpy(usb_buffer, (void *)last_addr, req->wLength); 423 if(req->bRequest == HWSTUB_READ2_ATOMIC)
424 {
425 if(!read_atomic(usb_buffer, (void *)last_addr, req->wLength))
426 return usb_drv_stall(EP_CONTROL, true, true);
427 }
428 else
429 memcpy(usb_buffer, (void *)last_addr, req->wLength);
381 asm volatile("nop" : : : "memory"); 430 asm volatile("nop" : : : "memory");
382 usb_drv_send(EP_CONTROL, usb_buffer, req->wLength); 431 usb_drv_send(EP_CONTROL, usb_buffer, req->wLength);
383 usb_drv_recv(EP_CONTROL, NULL, 0); 432 usb_drv_recv(EP_CONTROL, NULL, 0);
384 } 433 }
385}; 434};
386 435
436static bool write_atomic(void *dst, void *src, size_t sz)
437{
438 switch(sz)
439 {
440 case 1: target_write8(dst, *(uint8_t *)src); return true;
441 case 2: target_write16(dst, *(uint16_t *)src); return true;
442 case 4: target_write32(dst, *(uint32_t *)src); return true;
443 default: return false;
444 }
445}
446
387static void handle_write(struct usb_ctrlrequest *req) 447static void handle_write(struct usb_ctrlrequest *req)
388{ 448{
389 int size = usb_drv_recv(EP_CONTROL, usb_buffer, req->wLength); 449 int size = usb_drv_recv(EP_CONTROL, usb_buffer, req->wLength);
@@ -392,7 +452,13 @@ static void handle_write(struct usb_ctrlrequest *req)
392 int sz_hdr = sizeof(struct hwstub_write_req_t); 452 int sz_hdr = sizeof(struct hwstub_write_req_t);
393 if(size < sz_hdr) 453 if(size < sz_hdr)
394 return usb_drv_stall(EP_CONTROL, true, true); 454 return usb_drv_stall(EP_CONTROL, true, true);
395 memcpy((void *)write->dAddress, usb_buffer + sz_hdr, size - sz_hdr); 455 if(req->bRequest == HWSTUB_WRITE_ATOMIC)
456 {
457 if(!write_atomic((void *)write->dAddress, usb_buffer + sz_hdr, size - sz_hdr))
458 return usb_drv_stall(EP_CONTROL, true, true);
459 }
460 else
461 memcpy((void *)write->dAddress, usb_buffer + sz_hdr, size - sz_hdr);
396 usb_drv_send(EP_CONTROL, NULL, 0); 462 usb_drv_send(EP_CONTROL, NULL, 0);
397} 463}
398 464
@@ -451,8 +517,10 @@ static void handle_class_intf_req(struct usb_ctrlrequest *req)
451 return handle_get_log(req); 517 return handle_get_log(req);
452 case HWSTUB_READ: 518 case HWSTUB_READ:
453 case HWSTUB_READ2: 519 case HWSTUB_READ2:
520 case HWSTUB_READ2_ATOMIC:
454 return handle_read(req); 521 return handle_read(req);
455 case HWSTUB_WRITE: 522 case HWSTUB_WRITE:
523 case HWSTUB_WRITE_ATOMIC:
456 return handle_write(req); 524 return handle_write(req);
457 case HWSTUB_EXEC: 525 case HWSTUB_EXEC:
458 return handle_exec(req); 526 return handle_exec(req);
diff --git a/utils/hwstub/stub/protocol.h b/utils/hwstub/stub/protocol.h
index e358bb0a36..d551342d4b 100644
--- a/utils/hwstub/stub/protocol.h
+++ b/utils/hwstub/stub/protocol.h
@@ -1,3 +1,3 @@
1#include "../hwstub_protocol.h" 1#include "../hwstub_protocol.h"
2 2
3#define HWSTUB_VERSION_REV 1 \ No newline at end of file 3#define HWSTUB_VERSION_REV 0 \ No newline at end of file
diff --git a/utils/hwstub/stub/target.h b/utils/hwstub/stub/target.h
index cb17401a9c..5cd049d04f 100644
--- a/utils/hwstub/stub/target.h
+++ b/utils/hwstub/stub/target.h
@@ -33,6 +33,14 @@ void target_get_config_desc(void *buffer, int *size);
33void target_udelay(int us); 33void target_udelay(int us);
34/* Wait for a short time (ms <= 1000) */ 34/* Wait for a short time (ms <= 1000) */
35void target_mdelay(int ms); 35void target_mdelay(int ms);
36/* Read a n-bit word atomically */
37uint8_t target_read8(const void *addr);
38uint16_t target_read16(const void *addr);
39uint32_t target_read32(const void *addr);
40/* Write a n-bit word atomically */
41void target_write8(void *addr, uint8_t val);
42void target_write16(void *addr, uint16_t val);
43void target_write32(void *addr, uint32_t val);
36 44
37/* mandatory for all targets */ 45/* mandatory for all targets */
38extern struct hwstub_target_desc_t target_descriptor; 46extern struct hwstub_target_desc_t target_descriptor;