source: mainline/uspace/drv/uhci/uhci.c@ b00163f

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b00163f was b00163f, checked in by Jan Vesely <jano.vesely@…>, 15 years ago

Move transfer initialization an queue to uhci_add_transfer()

Use uhci add transfer for all transfers
Error message fixes

  • Property mode set to 100644
File size: 6.2 KB
Line 
1#include <errno.h>
2#include <usb/debug.h>
3#include <usb/usb.h>
4
5#include "translating_malloc.h"
6
7#include "debug.h"
8#include "name.h"
9#include "uhci.h"
10
11static int uhci_init_tranfer_lists(transfer_list_t list[]);
12
13static inline int uhci_add_transfer(
14 device_t *dev,
15 usb_target_t target,
16 usb_transfer_type_t transfer_type,
17 usb_packet_id pid,
18 void *buffer, size_t size,
19 usbhc_iface_transfer_out_callback_t callback_out,
20 usbhc_iface_transfer_in_callback_t callback_in,
21 void *arg );
22
23int uhci_init(device_t *device, void *regs)
24{
25 assert( device );
26 uhci_print_info( "Initializing device at address %p\n", device);
27
28 /* create instance */
29 uhci_t *instance = malloc( sizeof(uhci_t) );
30 if (!instance)
31 { return ENOMEM; }
32 bzero( instance, sizeof(uhci_t) );
33
34 /* init address keeper(libusb) */
35 usb_address_keeping_init( &instance->address_manager, USB11_ADDRESS_MAX );
36
37 /* allow access to hc control registers */
38 regs_t *io;
39 int ret = pio_enable( regs, sizeof(regs_t), (void**)&io);
40 if (ret < 0) {
41 free( instance );
42 uhci_print_error("Failed to gain access to registers at %p\n", io);
43 return ret;
44 }
45 instance->registers = io;
46
47 /* init root hub */
48 ret = uhci_root_hub_init(&instance->root_hub, device,
49 (char*)regs + UHCI_ROOT_HUB_PORT_REGISTERS_OFFSET);
50 if (ret < 0) {
51 free(instance);
52 uhci_print_error("Failed to initialize root hub driver.\n");
53 return ret;
54 }
55
56 instance->frame_list = trans_malloc(sizeof(frame_list_t));
57 if (instance->frame_list == NULL) {
58 uhci_print_error("Failed to allocate frame list pointer.\n");
59 uhci_root_hub_fini(&instance->root_hub);
60 free(instance);
61 return ENOMEM;
62 }
63
64 const uintptr_t pa = (uintptr_t)addr_to_phys(instance->frame_list);
65
66 pio_write_32(&instance->registers->flbaseadd, (uint32_t)pa);
67
68 ret = uhci_init_tranfer_lists(instance->transfers);
69 if (ret != EOK) {
70 uhci_print_error("Transfer list initialization failed.\n");
71 uhci_root_hub_fini(&instance->root_hub);
72 free(instance);
73 return ret;
74 }
75
76 device->driver_data = instance;
77 return EOK;
78}
79/*----------------------------------------------------------------------------*/
80int uhci_in(
81 device_t *dev,
82 usb_target_t target,
83 usb_transfer_type_t transfer_type,
84 void *buffer, size_t size,
85 usbhc_iface_transfer_in_callback_t callback, void *arg
86 )
87{
88 uhci_print_info( "transfer IN [%d.%d (%s); %zu]\n",
89 target.address, target.endpoint,
90 usb_str_transfer_type(transfer_type),
91 size);
92 return uhci_add_transfer(
93 dev, target, transfer_type, USB_PID_IN, buffer, size, NULL, callback, arg);
94}
95/*----------------------------------------------------------------------------*/
96int uhci_out(
97 device_t *dev,
98 usb_target_t target,
99 usb_transfer_type_t transfer_type,
100 void *buffer, size_t size,
101 usbhc_iface_transfer_out_callback_t callback, void *arg
102 )
103{
104 uhci_print_info( "transfer OUT [%d.%d (%s); %zu]\n",
105 target.address, target.endpoint,
106 usb_str_transfer_type(transfer_type),
107 size);
108 return uhci_add_transfer(
109 dev, target, transfer_type, USB_PID_OUT, buffer, size, callback, NULL, arg);
110}
111/*----------------------------------------------------------------------------*/
112int uhci_setup(
113 device_t *dev,
114 usb_target_t target,
115 usb_transfer_type_t transfer_type,
116 void *buffer, size_t size,
117 usbhc_iface_transfer_out_callback_t callback, void *arg
118 )
119{
120 uhci_print_info( "transfer SETUP [%d.%d (%s); %zu]\n",
121 target.address, target.endpoint,
122 usb_str_transfer_type(transfer_type),
123 size);
124 uhci_print_info("Setup packet content: %x %x.\n", ((uint8_t*)buffer)[0],
125 ((uint8_t*)buffer)[1]);
126 return uhci_add_transfer( dev,
127 target, transfer_type, USB_PID_SETUP, buffer, size, callback, NULL, arg);
128
129}
130/*----------------------------------------------------------------------------*/
131int uhci_init_tranfer_lists(transfer_list_t transfers[])
132{
133 //TODO:refactor
134 transfers[USB_TRANSFER_ISOCHRONOUS].first = NULL;
135 transfers[USB_TRANSFER_ISOCHRONOUS].last = NULL;
136
137 int ret;
138 ret = transfer_list_init(&transfers[USB_TRANSFER_BULK], NULL);
139 if (ret != EOK) {
140 uhci_print_error("Failed to initialize bulk queue.\n");
141 return ret;
142 }
143
144 ret = transfer_list_init(
145 &transfers[USB_TRANSFER_CONTROL], &transfers[USB_TRANSFER_BULK]);
146 if (ret != EOK) {
147 uhci_print_error("Failed to initialize control queue.\n");
148 transfer_list_fini(&transfers[USB_TRANSFER_BULK]);
149 return ret;
150 }
151
152 ret = transfer_list_init(
153 &transfers[USB_TRANSFER_INTERRUPT], &transfers[USB_TRANSFER_CONTROL]);
154 if (ret != EOK) {
155 uhci_print_error("Failed to initialize interrupt queue.\n");
156 transfer_list_fini(&transfers[USB_TRANSFER_CONTROL]);
157 transfer_list_fini(&transfers[USB_TRANSFER_BULK]);
158 return ret;
159 }
160
161 return EOK;
162}
163/*----------------------------------------------------------------------------*/
164static inline int uhci_add_transfer(
165 device_t *dev,
166 usb_target_t target,
167 usb_transfer_type_t transfer_type,
168 usb_packet_id pid,
169 void *buffer, size_t size,
170 usbhc_iface_transfer_out_callback_t callback_out,
171 usbhc_iface_transfer_in_callback_t callback_in,
172 void *arg )
173{
174 // TODO: Add support for isochronous transfers
175 if (transfer_type == USB_TRANSFER_ISOCHRONOUS)
176 return ENOTSUP;
177
178 if (size >= 1024)
179 return ENOTSUP;
180
181 transfer_descriptor_t *td = NULL;
182 callback_t *job = NULL;
183 int ret = EOK;
184
185#define CHECK_RET_TRANS_FREE_JOB_TD(message) \
186 if (ret != EOK) { \
187 uhci_print_error(message); \
188 if (job) { \
189 callback_fini(job); \
190 trans_free(job); \
191 } \
192 if (td) { trans_free(td); } \
193 return ret; \
194 } else (void) 0
195
196
197 job = malloc(sizeof(callback_t));
198 ret= job ? EOK : ENOMEM;
199 CHECK_RET_TRANS_FREE_JOB_TD("Failed to allocate callback structure.\n");
200
201 ret = callback_init(job, dev, buffer, size, callback_in, callback_out, arg);
202 CHECK_RET_TRANS_FREE_JOB_TD("Failed to initialize callback structure.\n");
203
204 td = trans_malloc(sizeof(transfer_descriptor_t));
205 ret = td ? ENOMEM : EOK;
206 CHECK_RET_TRANS_FREE_JOB_TD("Failed to allocate tranfer descriptor.\n");
207
208 ret = transfer_descriptor_init(td, 3, size, false, target, pid);
209 CHECK_RET_TRANS_FREE_JOB_TD("Failed to initialize transfer descriptor.\n");
210
211 td->callback = job;
212
213 assert(dev);
214 uhci_t *instance = (uhci_t*)dev->driver_data;
215 assert(instance);
216
217 ret = transfer_list_append(&instance->transfers[transfer_type], td);
218 CHECK_RET_TRANS_FREE_JOB_TD("Failed to append transfer descriptor.\n");
219
220 return EOK;
221}
Note: See TracBrowser for help on using the repository browser.