summaryrefslogtreecommitdiff
path: root/utils/hwstub/lib
diff options
context:
space:
mode:
authorMarcin Bukat <marcin.bukat@gmail.com>2014-11-18 23:27:26 +0100
committerMarcin Bukat <marcin.bukat@gmail.com>2014-11-18 23:30:44 +0100
commitcd04a5f1aadc8e2ec4e787f5ba4cc8c38a579314 (patch)
tree63e9f095451aeba0139152c8742d0af67413690a /utils/hwstub/lib
parent794169a18f644eea32de20b26646381137545e2d (diff)
downloadrockbox-cd04a5f1aadc8e2ec4e787f5ba4cc8c38a579314.tar.gz
rockbox-cd04a5f1aadc8e2ec4e787f5ba4cc8c38a579314.zip
hwstub/qeditor: add support for atomic read/writes
The current code assumed that READ/WRITE would produce atomic read/writes for 8/16/32-bit words, which in turned put assumption on the memcpy function. Since some memcpy implementation do not always guarantee such strong assumption, introduce two new operation READ/WRITE_ATOMIC which provide the necessary tools to do correct read and write to register in a single memory access. Change-Id: I37451bd5057bb0dcaf5a800d8aef8791c792a090
Diffstat (limited to 'utils/hwstub/lib')
-rw-r--r--utils/hwstub/lib/hwstub.c40
-rw-r--r--utils/hwstub/lib/hwstub.h5
2 files changed, 36 insertions, 9 deletions
diff --git a/utils/hwstub/lib/hwstub.c b/utils/hwstub/lib/hwstub.c
index 6ae0400a66..d3908585da 100644
--- a/utils/hwstub/lib/hwstub.c
+++ b/utils/hwstub/lib/hwstub.c
@@ -140,7 +140,8 @@ int hwstub_get_log(struct hwstub_device_t *dev, void *buf, size_t sz)
140 HWSTUB_GET_LOG, 0, dev->intf, buf, sz, 1000); 140 HWSTUB_GET_LOG, 0, dev->intf, buf, sz, 1000);
141} 141}
142 142
143static int _hwstub_read(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz) 143static int _hwstub_read(struct hwstub_device_t *dev, uint8_t breq, uint32_t addr,
144 void *buf, size_t sz)
144{ 145{
145 struct hwstub_read_req_t read; 146 struct hwstub_read_req_t read;
146 read.dAddress = addr; 147 read.dAddress = addr;
@@ -151,10 +152,11 @@ static int _hwstub_read(struct hwstub_device_t *dev, uint32_t addr, void *buf, s
151 return -1; 152 return -1;
152 return libusb_control_transfer(dev->handle, 153 return libusb_control_transfer(dev->handle,
153 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN, 154 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN,
154 HWSTUB_READ2, dev->id++, dev->intf, buf, sz, 1000); 155 breq, dev->id++, dev->intf, buf, sz, 1000);
155} 156}
156 157
157static int _hwstub_write(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz) 158static int _hwstub_write(struct hwstub_device_t *dev, uint8_t breq, uint32_t addr,
159 const void *buf, size_t sz)
158{ 160{
159 size_t hdr_sz = sizeof(struct hwstub_write_req_t); 161 size_t hdr_sz = sizeof(struct hwstub_write_req_t);
160 struct hwstub_write_req_t *req = malloc(sz + hdr_sz); 162 struct hwstub_write_req_t *req = malloc(sz + hdr_sz);
@@ -162,18 +164,34 @@ static int _hwstub_write(struct hwstub_device_t *dev, uint32_t addr, void *buf,
162 memcpy(req + 1, buf, sz); 164 memcpy(req + 1, buf, sz);
163 int size = libusb_control_transfer(dev->handle, 165 int size = libusb_control_transfer(dev->handle,
164 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT, 166 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT,
165 HWSTUB_WRITE, dev->id++, dev->intf, (void *)req, sz + hdr_sz, 1000); 167 breq, dev->id++, dev->intf, (void *)req, sz + hdr_sz, 1000);
166 free(req); 168 free(req);
167 return size - hdr_sz; 169 return size - hdr_sz;
168} 170}
169 171
172int hwstub_read_atomic(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz)
173{
174 /* reject any read greater than the buffer, it makes no sense anyway */
175 if(sz > dev->buf_sz)
176 return -1;
177 return _hwstub_read(dev, HWSTUB_READ2_ATOMIC, addr, buf, sz);
178}
179
180int hwstub_write_atomic(struct hwstub_device_t *dev, uint32_t addr, const void *buf, size_t sz)
181{
182 /* reject any write greater than the buffer, it makes no sense anyway */
183 if(sz + sizeof(struct hwstub_write_req_t) > dev->buf_sz)
184 return -1;
185 return _hwstub_write(dev, HWSTUB_WRITE_ATOMIC, addr, buf, sz);
186}
187
170/* Intermediate function which make sure we don't overflow the device buffer */ 188/* Intermediate function which make sure we don't overflow the device buffer */
171int hwstub_read(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz) 189int hwstub_read(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz)
172{ 190{
173 int cnt = 0; 191 int cnt = 0;
174 while(sz > 0) 192 while(sz > 0)
175 { 193 {
176 int xfer = _hwstub_read(dev, addr, buf, MIN(sz, dev->buf_sz)); 194 int xfer = _hwstub_read(dev, HWSTUB_READ2, addr, buf, MIN(sz, dev->buf_sz));
177 if(xfer < 0) 195 if(xfer < 0)
178 return xfer; 196 return xfer;
179 sz -= xfer; 197 sz -= xfer;
@@ -185,13 +203,13 @@ int hwstub_read(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz
185} 203}
186 204
187/* Intermediate function which make sure we don't overflow the device buffer */ 205/* Intermediate function which make sure we don't overflow the device buffer */
188int hwstub_write(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz) 206int hwstub_write(struct hwstub_device_t *dev, uint32_t addr, const void *buf, size_t sz)
189{ 207{
190 int cnt = 0; 208 int cnt = 0;
191 while(sz > 0) 209 while(sz > 0)
192 { 210 {
193 int xfer = _hwstub_write(dev, addr, buf, MIN(sz, dev->buf_sz - 211 int xfer = _hwstub_write(dev, HWSTUB_WRITE, addr, buf,
194 sizeof(struct hwstub_write_req_t))); 212 MIN(sz, dev->buf_sz - sizeof(struct hwstub_write_req_t)));
195 if(xfer < 0) 213 if(xfer < 0)
196 return xfer; 214 return xfer;
197 sz -= xfer; 215 sz -= xfer;
@@ -207,6 +225,12 @@ int hwstub_rw_mem(struct hwstub_device_t *dev, int read, uint32_t addr, void *bu
207 return read ? hwstub_read(dev, addr, buf, sz) : hwstub_write(dev, addr, buf, sz); 225 return read ? hwstub_read(dev, addr, buf, sz) : hwstub_write(dev, addr, buf, sz);
208} 226}
209 227
228int hwstub_rw_mem_atomic(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz)
229{
230 return read ? hwstub_read_atomic(dev, addr, buf, sz) :
231 hwstub_write_atomic(dev, addr, buf, sz);
232}
233
210int hwstub_exec(struct hwstub_device_t *dev, uint32_t addr, uint16_t flags) 234int hwstub_exec(struct hwstub_device_t *dev, uint32_t addr, uint16_t flags)
211{ 235{
212 struct hwstub_exec_req_t exec; 236 struct hwstub_exec_req_t exec;
diff --git a/utils/hwstub/lib/hwstub.h b/utils/hwstub/lib/hwstub.h
index d7d6ceb8ef..4d12de8eda 100644
--- a/utils/hwstub/lib/hwstub.h
+++ b/utils/hwstub/lib/hwstub.h
@@ -53,8 +53,11 @@ int hwstub_get_desc(struct hwstub_device_t *dev, uint16_t desc, void *info, size
53int hwstub_get_log(struct hwstub_device_t *dev, void *buf, size_t sz); 53int hwstub_get_log(struct hwstub_device_t *dev, void *buf, size_t sz);
54/* Returns number of bytes written/read or <0 on error */ 54/* Returns number of bytes written/read or <0 on error */
55int hwstub_read(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz); 55int hwstub_read(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz);
56int hwstub_write(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz); 56int hwstub_read_atomic(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz);
57int hwstub_write(struct hwstub_device_t *dev, uint32_t addr, const void *buf, size_t sz);
58int hwstub_write_atomic(struct hwstub_device_t *dev, uint32_t addr, const void *buf, size_t sz);
57int hwstub_rw_mem(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz); 59int hwstub_rw_mem(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz);
60int hwstub_rw_mem_atomic(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz);
58/* Returns <0 on error */ 61/* Returns <0 on error */
59int hwstub_exec(struct hwstub_device_t *dev, uint32_t addr, uint16_t flags); 62int hwstub_exec(struct hwstub_device_t *dev, uint32_t addr, uint16_t flags);
60int hwstub_call(struct hwstub_device_t *dev, uint32_t addr); 63int hwstub_call(struct hwstub_device_t *dev, uint32_t addr);