hcd-uhci.c (5ad23e873c858292dc58b9296261365312b8f683) hcd-uhci.c (66a08cbe6ad1aebec8eecf58b3ba042e19dd1649)
1/*
2 * USB UHCI controller emulation
3 *
4 * Copyright (c) 2005 Fabrice Bellard
5 *
6 * Copyright (c) 2008 Max Krasnyansky
7 * Magor rewrite of the UHCI data structures parser and frame processor
8 * Support for fully async operation and multiple outstanding transactions

--- 91 unchanged lines hidden (view full) ---

100 QEMUSGList sgl;
101 UHCIQueue *queue;
102 QTAILQ_ENTRY(UHCIAsync) next;
103 uint32_t td_addr;
104 uint8_t done;
105};
106
107struct UHCIQueue {
1/*
2 * USB UHCI controller emulation
3 *
4 * Copyright (c) 2005 Fabrice Bellard
5 *
6 * Copyright (c) 2008 Max Krasnyansky
7 * Magor rewrite of the UHCI data structures parser and frame processor
8 * Support for fully async operation and multiple outstanding transactions

--- 91 unchanged lines hidden (view full) ---

100 QEMUSGList sgl;
101 UHCIQueue *queue;
102 QTAILQ_ENTRY(UHCIAsync) next;
103 uint32_t td_addr;
104 uint8_t done;
105};
106
107struct UHCIQueue {
108 uint32_t qh_addr;
108 uint32_t token;
109 UHCIState *uhci;
110 USBEndpoint *ep;
111 QTAILQ_ENTRY(UHCIQueue) next;
112 QTAILQ_HEAD(, UHCIAsync) asyncs;
113 int8_t valid;
114};
115

--- 49 unchanged lines hidden (view full) ---

165static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td);
166
167static inline int32_t uhci_queue_token(UHCI_TD *td)
168{
169 /* covers ep, dev, pid -> identifies the endpoint */
170 return td->token & 0x7ffff;
171}
172
109 uint32_t token;
110 UHCIState *uhci;
111 USBEndpoint *ep;
112 QTAILQ_ENTRY(UHCIQueue) next;
113 QTAILQ_HEAD(, UHCIAsync) asyncs;
114 int8_t valid;
115};
116

--- 49 unchanged lines hidden (view full) ---

166static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td);
167
168static inline int32_t uhci_queue_token(UHCI_TD *td)
169{
170 /* covers ep, dev, pid -> identifies the endpoint */
171 return td->token & 0x7ffff;
172}
173
173static UHCIQueue *uhci_queue_get(UHCIState *s, UHCI_TD *td, USBEndpoint *ep)
174static UHCIQueue *uhci_queue_new(UHCIState *s, uint32_t qh_addr, UHCI_TD *td,
175 USBEndpoint *ep)
174{
176{
175 uint32_t token = uhci_queue_token(td);
176 UHCIQueue *queue;
177
177 UHCIQueue *queue;
178
178 QTAILQ_FOREACH(queue, &s->queues, next) {
179 if (queue->token == token) {
180 return queue;
181 }
182 }
183
184 queue = g_new0(UHCIQueue, 1);
185 queue->uhci = s;
179 queue = g_new0(UHCIQueue, 1);
180 queue->uhci = s;
186 queue->token = token;
181 queue->qh_addr = qh_addr;
182 queue->token = uhci_queue_token(td);
187 queue->ep = ep;
188 QTAILQ_INIT(&queue->asyncs);
189 QTAILQ_INSERT_HEAD(&s->queues, queue, next);
190 trace_usb_uhci_queue_add(queue->token);
191 return queue;
192}
193
183 queue->ep = ep;
184 QTAILQ_INIT(&queue->asyncs);
185 QTAILQ_INSERT_HEAD(&s->queues, queue, next);
186 trace_usb_uhci_queue_add(queue->token);
187 return queue;
188}
189
194static void uhci_queue_free(UHCIQueue *queue)
190static void uhci_queue_free(UHCIQueue *queue, const char *reason)
195{
196 UHCIState *s = queue->uhci;
197 UHCIAsync *async;
198
199 while (!QTAILQ_EMPTY(&queue->asyncs)) {
200 async = QTAILQ_FIRST(&queue->asyncs);
201 uhci_async_cancel(async);
202 }
203
191{
192 UHCIState *s = queue->uhci;
193 UHCIAsync *async;
194
195 while (!QTAILQ_EMPTY(&queue->asyncs)) {
196 async = QTAILQ_FIRST(&queue->asyncs);
197 uhci_async_cancel(async);
198 }
199
204 trace_usb_uhci_queue_del(queue->token);
200 trace_usb_uhci_queue_del(queue->token, reason);
205 QTAILQ_REMOVE(&s->queues, queue, next);
206 g_free(queue);
207}
208
201 QTAILQ_REMOVE(&s->queues, queue, next);
202 g_free(queue);
203}
204
205static UHCIQueue *uhci_queue_find(UHCIState *s, UHCI_TD *td)
206{
207 uint32_t token = uhci_queue_token(td);
208 UHCIQueue *queue;
209
210 QTAILQ_FOREACH(queue, &s->queues, next) {
211 if (queue->token == token) {
212 return queue;
213 }
214 }
215 return NULL;
216}
217
218static bool uhci_queue_verify(UHCIQueue *queue, uint32_t qh_addr, UHCI_TD *td,
219 uint32_t td_addr, bool queuing)
220{
221 UHCIAsync *first = QTAILQ_FIRST(&queue->asyncs);
222
223 return queue->qh_addr == qh_addr &&
224 queue->token == uhci_queue_token(td) &&
225 (queuing || !(td->ctrl & TD_CTRL_ACTIVE) || first == NULL ||
226 first->td_addr == td_addr);
227}
228
209static UHCIAsync *uhci_async_alloc(UHCIQueue *queue, uint32_t td_addr)
210{
211 UHCIAsync *async = g_new0(UHCIAsync, 1);
212
213 async->queue = queue;
214 async->td_addr = td_addr;
215 usb_packet_init(&async->packet);
216 pci_dma_sglist_init(&async->sgl, &queue->uhci->dev, 1);

--- 52 unchanged lines hidden (view full) ---

269 * Cancel async packets that are no longer valid
270 */
271static void uhci_async_validate_end(UHCIState *s)
272{
273 UHCIQueue *queue, *n;
274
275 QTAILQ_FOREACH_SAFE(queue, &s->queues, next, n) {
276 if (!queue->valid) {
229static UHCIAsync *uhci_async_alloc(UHCIQueue *queue, uint32_t td_addr)
230{
231 UHCIAsync *async = g_new0(UHCIAsync, 1);
232
233 async->queue = queue;
234 async->td_addr = td_addr;
235 usb_packet_init(&async->packet);
236 pci_dma_sglist_init(&async->sgl, &queue->uhci->dev, 1);

--- 52 unchanged lines hidden (view full) ---

289 * Cancel async packets that are no longer valid
290 */
291static void uhci_async_validate_end(UHCIState *s)
292{
293 UHCIQueue *queue, *n;
294
295 QTAILQ_FOREACH_SAFE(queue, &s->queues, next, n) {
296 if (!queue->valid) {
277 uhci_queue_free(queue);
297 uhci_queue_free(queue, "validate-end");
278 }
279 }
280}
281
282static void uhci_async_cancel_device(UHCIState *s, USBDevice *dev)
283{
284 UHCIQueue *queue, *n;
285

--- 4 unchanged lines hidden (view full) ---

290 }
291}
292
293static void uhci_async_cancel_all(UHCIState *s)
294{
295 UHCIQueue *queue, *nq;
296
297 QTAILQ_FOREACH_SAFE(queue, &s->queues, next, nq) {
298 }
299 }
300}
301
302static void uhci_async_cancel_device(UHCIState *s, USBDevice *dev)
303{
304 UHCIQueue *queue, *n;
305

--- 4 unchanged lines hidden (view full) ---

310 }
311}
312
313static void uhci_async_cancel_all(UHCIState *s)
314{
315 UHCIQueue *queue, *nq;
316
317 QTAILQ_FOREACH_SAFE(queue, &s->queues, next, nq) {
298 uhci_queue_free(queue);
318 uhci_queue_free(queue, "cancel-all");
299 }
300}
301
302static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t td_addr,
303 UHCI_TD *td)
304{
305 uint32_t token = uhci_queue_token(td);
306 UHCIQueue *queue;

--- 470 unchanged lines hidden (view full) ---

777 s->status |= UHCI_STS_USBERR;
778 if (td->ctrl & TD_CTRL_IOC) {
779 *int_mask |= 0x01;
780 }
781 uhci_update_irq(s);
782 return err;
783}
784
319 }
320}
321
322static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t td_addr,
323 UHCI_TD *td)
324{
325 uint32_t token = uhci_queue_token(td);
326 UHCIQueue *queue;

--- 470 unchanged lines hidden (view full) ---

797 s->status |= UHCI_STS_USBERR;
798 if (td->ctrl & TD_CTRL_IOC) {
799 *int_mask |= 0x01;
800 }
801 uhci_update_irq(s);
802 return err;
803}
804
785static int uhci_handle_td(UHCIState *s, UHCIQueue *q,
805static int uhci_handle_td(UHCIState *s, UHCIQueue *q, uint32_t qh_addr,
786 UHCI_TD *td, uint32_t td_addr, uint32_t *int_mask)
787{
788 UHCIAsync *async;
789 int len = 0, max_len;
790 bool spd;
791 bool queuing = (q != NULL);
792 uint8_t pid = td->token & 0xff;
793
806 UHCI_TD *td, uint32_t td_addr, uint32_t *int_mask)
807{
808 UHCIAsync *async;
809 int len = 0, max_len;
810 bool spd;
811 bool queuing = (q != NULL);
812 uint8_t pid = td->token & 0xff;
813
814 if (q == NULL) {
815 q = uhci_queue_find(s, td);
816 if (q && !uhci_queue_verify(q, qh_addr, td, td_addr, queuing)) {
817 uhci_queue_free(q, "guest re-used qh");
818 q = NULL;
819 }
820 }
821
794 /* Is active ? */
795 if (!(td->ctrl & TD_CTRL_ACTIVE)) {
796 /*
797 * ehci11d spec page 22: "Even if the Active bit in the TD is already
798 * cleared when the TD is fetched ... an IOC interrupt is generated"
799 */
800 if (td->ctrl & TD_CTRL_IOC) {
801 *int_mask |= 0x01;

--- 18 unchanged lines hidden (view full) ---

820 uhci_async_unlink(async);
821 goto done;
822 }
823
824 /* Allocate new packet */
825 if (q == NULL) {
826 USBDevice *dev = uhci_find_device(s, (td->token >> 8) & 0x7f);
827 USBEndpoint *ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf);
822 /* Is active ? */
823 if (!(td->ctrl & TD_CTRL_ACTIVE)) {
824 /*
825 * ehci11d spec page 22: "Even if the Active bit in the TD is already
826 * cleared when the TD is fetched ... an IOC interrupt is generated"
827 */
828 if (td->ctrl & TD_CTRL_IOC) {
829 *int_mask |= 0x01;

--- 18 unchanged lines hidden (view full) ---

848 uhci_async_unlink(async);
849 goto done;
850 }
851
852 /* Allocate new packet */
853 if (q == NULL) {
854 USBDevice *dev = uhci_find_device(s, (td->token >> 8) & 0x7f);
855 USBEndpoint *ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf);
828 q = uhci_queue_get(s, td, ep);
856 q = uhci_queue_new(s, qh_addr, td, ep);
829 }
830 async = uhci_async_alloc(q, td_addr);
831
832 /* valid needs to be large enough to handle 10 frame delay
833 * for initial isochronous requests
834 */
835 async->queue->valid = 32;
836

--- 112 unchanged lines hidden (view full) ---

949 uhci_read_td(q->uhci, &ptd, plink);
950 if (!(ptd.ctrl & TD_CTRL_ACTIVE)) {
951 break;
952 }
953 if (uhci_queue_token(&ptd) != q->token) {
954 break;
955 }
956 trace_usb_uhci_td_queue(plink & ~0xf, ptd.ctrl, ptd.token);
857 }
858 async = uhci_async_alloc(q, td_addr);
859
860 /* valid needs to be large enough to handle 10 frame delay
861 * for initial isochronous requests
862 */
863 async->queue->valid = 32;
864

--- 112 unchanged lines hidden (view full) ---

977 uhci_read_td(q->uhci, &ptd, plink);
978 if (!(ptd.ctrl & TD_CTRL_ACTIVE)) {
979 break;
980 }
981 if (uhci_queue_token(&ptd) != q->token) {
982 break;
983 }
984 trace_usb_uhci_td_queue(plink & ~0xf, ptd.ctrl, ptd.token);
957 ret = uhci_handle_td(q->uhci, q, &ptd, plink, &int_mask);
985 ret = uhci_handle_td(q->uhci, q, q->qh_addr, &ptd, plink, &int_mask);
958 if (ret == TD_RESULT_ASYNC_CONT) {
959 break;
960 }
961 assert(ret == TD_RESULT_ASYNC_START);
962 assert(int_mask == 0);
963 plink = ptd.link;
964 }
965 usb_device_flush_ep_queue(q->ep->dev, q->ep);

--- 64 unchanged lines hidden (view full) ---

1030 continue;
1031 }
1032
1033 /* TD */
1034 uhci_read_td(s, &td, link);
1035 trace_usb_uhci_td_load(curr_qh & ~0xf, link & ~0xf, td.ctrl, td.token);
1036
1037 old_td_ctrl = td.ctrl;
986 if (ret == TD_RESULT_ASYNC_CONT) {
987 break;
988 }
989 assert(ret == TD_RESULT_ASYNC_START);
990 assert(int_mask == 0);
991 plink = ptd.link;
992 }
993 usb_device_flush_ep_queue(q->ep->dev, q->ep);

--- 64 unchanged lines hidden (view full) ---

1058 continue;
1059 }
1060
1061 /* TD */
1062 uhci_read_td(s, &td, link);
1063 trace_usb_uhci_td_load(curr_qh & ~0xf, link & ~0xf, td.ctrl, td.token);
1064
1065 old_td_ctrl = td.ctrl;
1038 ret = uhci_handle_td(s, NULL, &td, link, &int_mask);
1066 ret = uhci_handle_td(s, NULL, curr_qh, &td, link, &int_mask);
1039 if (old_td_ctrl != td.ctrl) {
1040 /* update the status bits of the TD */
1041 val = cpu_to_le32(td.ctrl);
1042 pci_dma_write(&s->dev, (link & ~0xf) + 4, &val, sizeof(val));
1043 }
1044
1045 switch (ret) {
1046 case TD_RESULT_STOP_FRAME: /* interrupted frame */

--- 344 unchanged lines hidden ---
1067 if (old_td_ctrl != td.ctrl) {
1068 /* update the status bits of the TD */
1069 val = cpu_to_le32(td.ctrl);
1070 pci_dma_write(&s->dev, (link & ~0xf) + 4, &val, sizeof(val));
1071 }
1072
1073 switch (ret) {
1074 case TD_RESULT_STOP_FRAME: /* interrupted frame */

--- 344 unchanged lines hidden ---