Changes in / [ec4538d:f16a76b] in mainline
- Files:
-
- 19 edited
Legend:
- Unmodified
- Added
- Removed
-
.bzrignore
rec4538d rf16a76b 77 77 ./uspace/dist/srv/* 78 78 ./uspace/drv/root/root 79 ./uspace/drv/ehci-hcd/ehci-hcd 79 80 ./uspace/drv/isa/isa 80 81 ./uspace/drv/ns8250/ns8250 … … 84 85 ./uspace/drv/test1/test1 85 86 ./uspace/drv/test2/test2 86 ./uspace/drv/ehci-hcd/ehci-hcd87 87 ./uspace/drv/uhci-hcd/uhci-hcd 88 88 ./uspace/drv/uhci-rhd/uhci-rhd -
uspace/drv/ehci-hcd/main.c
rec4538d rf16a76b 57 57 }; 58 58 /*----------------------------------------------------------------------------*/ 59 /** Initializes a new ddf driver instance of EHCI hcd.60 *61 * @param[in] device DDF instance of the device to initialize.62 * @return Error code.63 */64 59 static int ehci_add_device(ddf_dev_t *device) 65 60 { … … 92 87 } 93 88 /*----------------------------------------------------------------------------*/ 94 /** Initializes global driver structures (NONE).95 *96 * @param[in] argc Nmber of arguments in argv vector (ignored).97 * @param[in] argv Cmdline argument vector (ignored).98 * @return Error code.99 *100 * Driver debug level is set here.101 */102 89 int main(int argc, char *argv[]) 103 90 { -
uspace/drv/ehci-hcd/pci.c
rec4538d rf16a76b 48 48 49 49 #define PAGE_SIZE_MASK 0xfffff000 50 51 50 #define HCC_PARAMS_OFFSET 0x8 52 51 #define HCC_PARAMS_EECP_MASK 0xff 53 52 #define HCC_PARAMS_EECP_OFFSET 8 54 55 #define CMD_OFFSET 0x056 #define CONFIGFLAG_OFFSET 0x4057 53 58 54 #define USBCMD_RUN 1 … … 66 62 #define WAIT_STEP 10 67 63 64 68 65 /** Get address of registers and IRQ for given device. 69 66 * 70 67 * @param[in] dev Device asking for the addresses. 71 * @param[out] mem_reg_address Base address of the memoryrange.72 * @param[out] mem_reg_size Size of the memoryrange.68 * @param[out] io_reg_address Base address of the I/O range. 69 * @param[out] io_reg_size Size of the I/O range. 73 70 * @param[out] irq_no IRQ assigned to the device. 74 71 * @return Error code. … … 90 87 rc = hw_res_get_resource_list(parent_phone, &hw_resources); 91 88 if (rc != EOK) { 92 async_hangup(parent_phone); 93 return rc; 89 goto leave; 94 90 } 95 91 … … 104 100 for (i = 0; i < hw_resources.count; i++) { 105 101 hw_resource_t *res = &hw_resources.resources[i]; 106 switch (res->type) 107 { 108 case INTERRUPT: 109 irq = res->res.interrupt.irq; 110 irq_found = true; 111 usb_log_debug2("Found interrupt: %d.\n", irq); 112 break; 113 114 case MEM_RANGE: 115 if (res->res.mem_range.address != 0 116 && res->res.mem_range.size != 0 ) { 117 mem_address = res->res.mem_range.address; 118 mem_size = res->res.mem_range.size; 119 usb_log_debug2("Found mem: %llx %zu.\n", 120 mem_address, mem_size); 121 mem_found = true; 102 switch (res->type) { 103 case INTERRUPT: 104 irq = res->res.interrupt.irq; 105 irq_found = true; 106 usb_log_debug2("Found interrupt: %d.\n", irq); 107 break; 108 case MEM_RANGE: 109 if (res->res.mem_range.address != 0 110 && res->res.mem_range.size != 0 ) { 111 mem_address = res->res.mem_range.address; 112 mem_size = res->res.mem_range.size; 113 usb_log_debug2("Found mem: %llx %zu.\n", 114 res->res.mem_range.address, res->res.mem_range.size); 115 mem_found = true; 122 116 } 123 default: 124 break; 117 break; 118 default: 119 break; 125 120 } 126 121 } 127 122 128 if (mem_found && irq_found) { 129 *mem_reg_address = mem_address; 130 *mem_reg_size = mem_size; 131 *irq_no = irq; 132 rc = EOK; 133 } else { 123 if (!mem_found) { 134 124 rc = ENOENT; 135 } 136 125 goto leave; 126 } 127 128 if (!irq_found) { 129 rc = ENOENT; 130 goto leave; 131 } 132 133 *mem_reg_address = mem_address; 134 *mem_reg_size = mem_size; 135 *irq_no = irq; 136 137 rc = EOK; 138 leave: 137 139 async_hangup(parent_phone); 140 138 141 return rc; 139 142 } 140 143 /*----------------------------------------------------------------------------*/ 141 /** Calls the PCI driver with a request to enable interrupts142 *143 * @param[in] device Device asking for interrupts144 * @return Error code.145 */146 144 int pci_enable_interrupts(ddf_dev_t *device) 147 145 { 148 int parent_phone = 149 devman_parent_device_connect(device->handle, IPC_FLAG_BLOCKING); 150 if (parent_phone < 0) { 151 return parent_phone; 152 } 146 int parent_phone = devman_parent_device_connect(device->handle, 147 IPC_FLAG_BLOCKING); 153 148 bool enabled = hw_res_enable_interrupt(parent_phone); 154 149 async_hangup(parent_phone); … … 156 151 } 157 152 /*----------------------------------------------------------------------------*/ 158 /** Implements BIOS handoff routine as decribed in EHCI spec159 *160 * @param[in] device Device asking for interrupts161 * @return Error code.162 */163 153 int pci_disable_legacy(ddf_dev_t *device) 164 154 { … … 170 160 } 171 161 172 #define CHECK_RET_HANGUP_RETURN(ret, message...) \ 173 if (ret != EOK) { \ 174 usb_log_error(message); \ 175 async_hangup(parent_phone); \ 176 return ret; \ 177 } else (void)0 178 179 180 /* read register space BASE BAR */ 162 /* read register space BAR */ 181 163 sysarg_t address = 0x10; 182 164 sysarg_t value; 183 165 184 166 int ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE), 185 167 IPC_M_CONFIG_SPACE_READ_32, address, &value); 186 CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read PCI config space.\n",187 ret);188 168 usb_log_info("Register space BAR at %p:%x.\n", address, value); 189 169 190 /* clear lower byte, it's not part of the BASEaddress */170 /* clear lower byte, it's not part of the address */ 191 171 uintptr_t registers = (value & 0xffffff00); 192 usb_log_info("Mem ory registers BASEaddress:%p.\n", registers);193 194 /* if nothing setup the hc, we don't needto turn it off */172 usb_log_info("Mem register address:%p.\n", registers); 173 174 /* if nothing setup the hc, the we don't need to to turn it off */ 195 175 if (registers == 0) 196 176 return ENOTSUP; 197 177 198 /* map EHCI registers*/178 /* EHCI registers need 20 bytes*/ 199 179 void *regs = as_get_mappable_page(4096); 200 180 ret = physmem_map((void*)(registers & PAGE_SIZE_MASK), regs, 1, 201 181 AS_AREA_READ | AS_AREA_WRITE); 202 CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to map registers %p:%p.\n", 203 ret, regs, registers); 204 182 if (ret != EOK) { 183 usb_log_error("Failed(%d) to map registers %p:%p.\n", 184 ret, regs, registers); 185 } 205 186 /* calculate value of BASE */ 206 187 registers = (registers & 0xf00) | (uintptr_t)regs; 207 188 208 const uint32_t hcc_params =209 *(uint32_t*)(registers + HCC_PARAMS_OFFSET); 189 uint32_t hcc_params = *(uint32_t*)(registers + HCC_PARAMS_OFFSET); 190 210 191 usb_log_debug("Value of hcc params register: %x.\n", hcc_params); 211 212 /* Read value of EHCI Extended Capabilities Pointer 213 * (points to PCI config space) */ 214 uint32_t eecp = 215 (hcc_params >> HCC_PARAMS_EECP_OFFSET) & HCC_PARAMS_EECP_MASK; 192 uint32_t eecp = (hcc_params >> HCC_PARAMS_EECP_OFFSET) & HCC_PARAMS_EECP_MASK; 216 193 usb_log_debug("Value of EECP: %x.\n", eecp); 217 194 218 /* Read the second EEC. i.e. Legacy Support and Control register */219 /* TODO: Check capability type here */220 195 ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE), 221 196 IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGCTLSTS_OFFSET, &value); 222 CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGCTLSTS.\n", ret); 223 usb_log_debug("USBLEGCTLSTS: %x.\n", value); 224 225 /* Read the first EEC. i.e. Legacy Support register */ 226 /* TODO: Check capability type here */ 197 if (ret != EOK) { 198 usb_log_error("Failed(%d) to read USBLEGCTLSTS.\n", ret); 199 return ret; 200 } 201 usb_log_debug2("USBLEGCTLSTS: %x.\n", value); 202 227 203 ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE), 228 204 IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGSUP_OFFSET, &value); 229 CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGSUP.\n", ret); 205 if (ret != EOK) { 206 usb_log_error("Failed(%d) to read USBLEGSUP.\n", ret); 207 return ret; 208 } 230 209 usb_log_debug2("USBLEGSUP: %x.\n", value); 231 210 232 /* Request control from firmware/BIOS, by writing 1 to highest byte. 233 * (OS Control semaphore)*/ 211 /* request control from firmware/BIOS, by writing 1 to highest byte */ 234 212 ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE), 235 213 IPC_M_CONFIG_SPACE_WRITE_8, eecp + USBLEGSUP_OFFSET + 3, 1); 236 CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to request OS EHCI control.\n", 237 ret); 238 239 size_t wait = 0; 240 /* Wait for BIOS to release control. */ 214 if (ret != EOK) { 215 usb_log_error("Failed(%d) request OS EHCI control.\n", ret); 216 return ret; 217 } 218 219 size_t wait = 0; /* might be anything */ 220 /* wait for BIOS to release control */ 241 221 while ((wait < DEFAULT_WAIT) && (value & USBLEGSUP_BIOS_CONTROL)) { 242 222 async_usleep(WAIT_STEP); 243 223 ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE), 244 224 IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGSUP_OFFSET, &value); 245 225 wait += WAIT_STEP; 246 226 } 247 227 248 249 228 if ((value & USBLEGSUP_BIOS_CONTROL) != 0) { 250 usb_log_info("BIOS released control after %d usec.\n", wait); 229 usb_log_warning( 230 "BIOS failed to release control after %d usecs, force it.\n", 231 wait); 232 ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE), 233 IPC_M_CONFIG_SPACE_WRITE_32, eecp + USBLEGSUP_OFFSET, 234 USBLEGSUP_OS_CONTROL); 235 if (ret != EOK) { 236 usb_log_error("Failed(%d) to force OS EHCI control.\n", ret); 237 return ret; 238 } 251 239 } else { 252 /* BIOS failed to hand over control, this should not happen. */ 253 usb_log_warning( "BIOS failed to release control after" 254 "%d usecs, force it.\n", wait); 255 ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE), 256 IPC_M_CONFIG_SPACE_WRITE_32, eecp + USBLEGSUP_OFFSET, 257 USBLEGSUP_OS_CONTROL); 258 CHECK_RET_HANGUP_RETURN(ret, 259 "Failed(%d) to force OS EHCI control.\n", ret); 260 /* TODO: This does not seem to work on my machine */ 261 } 262 263 /* Zero SMI enables in legacy control register. 264 * It would prevent pre-OS code from interfering. */ 240 usb_log_info("BIOS released control after %d usec.\n", 241 wait); 242 } 243 244 245 /* zero SMI enables in legacy control register */ 265 246 ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE), 266 247 IPC_M_CONFIG_SPACE_WRITE_32, eecp + USBLEGCTLSTS_OFFSET, 0); 267 CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) zero USBLEGCTLSTS.\n", ret); 248 if (ret != EOK) { 249 usb_log_error("Failed(%d) zero USBLEGCTLSTS.\n", ret); 250 return ret; 251 } 268 252 usb_log_debug("Zeroed USBLEGCTLSTS register.\n"); 269 253 270 /* Read again Legacy Support and Control register */271 254 ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE), 272 255 IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGCTLSTS_OFFSET, &value); 273 CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGCTLSTS.\n", ret); 256 if (ret != EOK) { 257 usb_log_error("Failed(%d) to read USBLEGCTLSTS.\n", ret); 258 return ret; 259 } 274 260 usb_log_debug2("USBLEGCTLSTS: %x.\n", value); 275 261 276 /* Read again Legacy Support register */277 262 ret = async_req_2_1(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE), 278 263 IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGSUP_OFFSET, &value); 279 CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGSUP.\n", ret); 264 if (ret != EOK) { 265 usb_log_error("Failed(%d) to read USBLEGSUP.\n", ret); 266 return ret; 267 } 280 268 usb_log_debug2("USBLEGSUP: %x.\n", value); 281 269 … … 284 272 */ 285 273 286 /* Get size of capability registers in memory space.*/274 /* size of capability registers in memory space */ 287 275 uint8_t operation_offset = *(uint8_t*)registers; 288 276 usb_log_debug("USBCMD offset: %d.\n", operation_offset); 289 290 /* Zero USBCMD register. */ 277 /* zero USBCMD register */ 291 278 volatile uint32_t *usbcmd = 292 (uint32_t*)((uint8_t*)registers + operation_offset + CMD_OFFSET); 293 volatile uint32_t *usbconfigured = 294 (uint32_t*)((uint8_t*)registers + operation_offset 295 + CONFIGFLAG_OFFSET); 279 (uint32_t*)((uint8_t*)registers + operation_offset); 296 280 usb_log_debug("USBCMD value: %x.\n", *usbcmd); 297 281 if (*usbcmd & USBCMD_RUN) { 298 282 *usbcmd = 0; 299 *usbconfigured = 0;300 283 usb_log_info("EHCI turned off.\n"); 301 284 } else { … … 303 286 } 304 287 288 305 289 async_hangup(parent_phone); 306 return ret; 307 #undef CHECK_RET_HANGUP_RETURN 290 291 return ret; 308 292 } 309 293 /*----------------------------------------------------------------------------*/ -
uspace/drv/uhci-hcd/batch.c
rec4538d rf16a76b 57 57 58 58 59 /** Allocates memory and initializes internal data structures.60 *61 * @param[in] fun DDF function to pass to callback.62 * @param[in] target Device and endpoint target of the transaction.63 * @param[in] transfer_type Interrupt, Control or Bulk.64 * @param[in] max_packet_size maximum allowed size of data packets.65 * @param[in] speed Speed of the transaction.66 * @param[in] buffer Data source/destination.67 * @param[in] size Size of the buffer.68 * @param[in] setup_buffer Setup data source (if not NULL)69 * @param[in] setup_size Size of setup_buffer (should be always 8)70 * @param[in] func_in function to call on inbound transaction completion71 * @param[in] func_out function to call on outbound transaction completion72 * @param[in] arg additional parameter to func_in or func_out73 * @param[in] manager Pointer to toggle management structure.74 * @return False, if there is an active TD, true otherwise.75 */76 59 batch_t * batch_get(ddf_fun_t *fun, usb_target_t target, 77 60 usb_transfer_type_t transfer_type, size_t max_packet_size, … … 86 69 assert(func_in != NULL || func_out != NULL); 87 70 88 #define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \89 if (ptr == NULL) { \90 usb_log_error(message); \91 if (instance) { \92 batch_dispose(instance); \93 } \94 return NULL; \95 } else (void)096 97 71 batch_t *instance = malloc(sizeof(batch_t)); 98 CHECK_NULL_DISPOSE_RETURN(instance, 99 "Failed to allocate batch instance.\n"); 100 bzero(instance, sizeof(batch_t)); 101 102 instance->qh = malloc32(sizeof(queue_head_t)); 103 CHECK_NULL_DISPOSE_RETURN(instance->qh, 104 "Failed to allocate batch queue head.\n"); 105 queue_head_init(instance->qh); 72 if (instance == NULL) { 73 usb_log_error("Failed to allocate batch instance.\n"); 74 return NULL; 75 } 76 77 instance->qh = queue_head_get(); 78 if (instance->qh == NULL) { 79 usb_log_error("Failed to allocate queue head.\n"); 80 free(instance); 81 return NULL; 82 } 106 83 107 84 instance->packets = (size + max_packet_size - 1) / max_packet_size; … … 111 88 112 89 instance->tds = malloc32(sizeof(td_t) * instance->packets); 113 CHECK_NULL_DISPOSE_RETURN( 114 instance->tds, "Failed to allocate transfer descriptors.\n"); 90 if (instance->tds == NULL) { 91 usb_log_error("Failed to allocate transfer descriptors.\n"); 92 queue_head_dispose(instance->qh); 93 free(instance); 94 return NULL; 95 } 115 96 bzero(instance->tds, sizeof(td_t) * instance->packets); 116 97 117 // const size_t transport_size = max_packet_size * instance->packets; 118 119 if (size > 0) { 120 instance->transport_buffer = malloc32(size); 121 CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer, 122 "Failed to allocate device accessible buffer.\n"); 123 } 124 125 if (setup_size > 0) { 126 instance->setup_buffer = malloc32(setup_size); 127 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer, 128 "Failed to allocate device accessible setup buffer.\n"); 98 const size_t transport_size = max_packet_size * instance->packets; 99 100 instance->transport_buffer = 101 (size > 0) ? malloc32(transport_size) : NULL; 102 103 if ((size > 0) && (instance->transport_buffer == NULL)) { 104 usb_log_error("Failed to allocate device accessible buffer.\n"); 105 queue_head_dispose(instance->qh); 106 free32(instance->tds); 107 free(instance); 108 return NULL; 109 } 110 111 instance->setup_buffer = setup_buffer ? malloc32(setup_size) : NULL; 112 if ((setup_size > 0) && (instance->setup_buffer == NULL)) { 113 usb_log_error("Failed to allocate device accessible setup buffer.\n"); 114 queue_head_dispose(instance->qh); 115 free32(instance->tds); 116 free32(instance->transport_buffer); 117 free(instance); 118 return NULL; 119 } 120 if (instance->setup_buffer) { 129 121 memcpy(instance->setup_buffer, setup_buffer, setup_size); 130 122 } 131 123 124 instance->max_packet_size = max_packet_size; 132 125 133 126 link_initialize(&instance->link); 134 127 135 instance->max_packet_size = max_packet_size;136 128 instance->target = target; 137 129 instance->transfer_type = transfer_type; 130 131 if (func_out) 132 instance->callback_out = func_out; 133 if (func_in) 134 instance->callback_in = func_in; 135 138 136 instance->buffer = buffer; 139 137 instance->buffer_size = size; … … 144 142 instance->manager = manager; 145 143 146 if (func_out) 147 instance->callback_out = func_out; 148 if (func_in) 149 instance->callback_in = func_in; 150 151 queue_head_set_element_td(instance->qh, addr_to_phys(instance->tds)); 152 144 queue_head_element_td(instance->qh, addr_to_phys(instance->tds)); 153 145 usb_log_debug("Batch(%p) %d:%d memory structures ready.\n", 154 146 instance, target.address, target.endpoint); … … 156 148 } 157 149 /*----------------------------------------------------------------------------*/ 158 /** Checks batch TDs for activity.159 *160 * @param[in] instance Batch structure to use.161 * @return False, if there is an active TD, true otherwise.162 */163 150 bool batch_is_complete(batch_t *instance) 164 151 { … … 178 165 instance, i, instance->tds[i].status); 179 166 180 device_keeper_set_toggle(instance->manager, 181 instance->target,td_toggle(&instance->tds[i]));167 device_keeper_set_toggle(instance->manager, instance->target, 168 td_toggle(&instance->tds[i])); 182 169 if (i > 0) 183 170 goto substract_ret; … … 194 181 } 195 182 /*----------------------------------------------------------------------------*/ 196 /** Prepares control write transaction.197 *198 * @param[in] instance Batch structure to use.199 */200 183 void batch_control_write(batch_t *instance) 201 184 { 202 185 assert(instance); 203 186 /* we are data out, we are supposed to provide data */ 204 memcpy(instance->transport_buffer, instance->buffer, 205 instance->buffer_size); 187 memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size); 206 188 batch_control(instance, USB_PID_OUT, USB_PID_IN); 207 189 instance->next_step = batch_call_out_and_dispose; … … 210 192 } 211 193 /*----------------------------------------------------------------------------*/ 212 /** Prepares control read transaction.213 *214 * @param[in] instance Batch structure to use.215 */216 194 void batch_control_read(batch_t *instance) 217 195 { … … 223 201 } 224 202 /*----------------------------------------------------------------------------*/ 225 /** Prepares interrupt in transaction.226 *227 * @param[in] instance Batch structure to use.228 */229 203 void batch_interrupt_in(batch_t *instance) 230 204 { … … 236 210 } 237 211 /*----------------------------------------------------------------------------*/ 238 /** Prepares interrupt out transaction.239 *240 * @param[in] instance Batch structure to use.241 */242 212 void batch_interrupt_out(batch_t *instance) 243 213 { 244 214 assert(instance); 245 /* we are data out, we are supposed to provide data */246 215 memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size); 247 216 batch_data(instance, USB_PID_OUT); … … 251 220 } 252 221 /*----------------------------------------------------------------------------*/ 253 /** Prepares bulk in transaction.254 *255 * @param[in] instance Batch structure to use.256 */257 222 void batch_bulk_in(batch_t *instance) 258 223 { … … 264 229 } 265 230 /*----------------------------------------------------------------------------*/ 266 /** Prepares bulk out transaction.267 *268 * @param[in] instance Batch structure to use.269 */270 231 void batch_bulk_out(batch_t *instance) 271 232 { … … 278 239 } 279 240 /*----------------------------------------------------------------------------*/ 280 /** Prepares generic data transaction281 *282 * @param[in] instance Batch structure to use.283 * @param[in] pid to use for data packets.284 */285 241 void batch_data(batch_t *instance, usb_packet_id pid) 286 242 { 287 243 assert(instance); 288 244 const bool low_speed = instance->speed == USB_SPEED_LOW; 289 int toggle = 290 device_keeper_get_toggle(instance->manager, instance->target); 245 int toggle = device_keeper_get_toggle(instance->manager, instance->target); 291 246 assert(toggle == 0 || toggle == 1); 292 247 … … 298 253 - remain_size; 299 254 255 300 256 const size_t packet_size = 301 257 (instance->max_packet_size > remain_size) ? 302 258 remain_size : instance->max_packet_size; 303 259 304 td_t *next_packet = (packet + 1 < instance->packets) 305 ? &instance->tds[packet + 1] : NULL; 306 307 assert(packet < instance->packets); 260 td_init(&instance->tds[packet], 261 DEFAULT_ERROR_COUNT, packet_size, toggle, false, low_speed, 262 instance->target, pid, data, 263 &instance->tds[packet + 1]); 264 265 toggle = 1 - toggle; 266 ++packet; 267 assert(packet <= instance->packets); 308 268 assert(packet_size <= remain_size); 309 310 td_init(311 &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,312 toggle, false, low_speed, instance->target, pid, data,313 next_packet);314 315 316 toggle = 1 - toggle;317 269 remain_size -= packet_size; 318 ++packet;319 270 } 320 271 device_keeper_set_toggle(instance->manager, instance->target, toggle); 321 } 322 /*----------------------------------------------------------------------------*/ 323 /** Prepares generic control transaction 324 * 325 * @param[in] instance Batch structure to use. 326 * @param[in] data_stage to use for data packets. 327 * @param[in] status_stage to use for data packets. 328 */ 272 273 instance->tds[packet - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG; 274 instance->tds[packet - 1].next = 0 | LINK_POINTER_TERMINATE_FLAG; 275 } 276 /*----------------------------------------------------------------------------*/ 329 277 void batch_control(batch_t *instance, 330 278 usb_packet_id data_stage, usb_packet_id status_stage) … … 353 301 remain_size : instance->max_packet_size; 354 302 355 td_init( 356 &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size,357 toggle, false, low_speed, instance->target, data_stage,358 data,&instance->tds[packet + 1]);303 td_init(&instance->tds[packet], 304 DEFAULT_ERROR_COUNT, packet_size, toggle, false, low_speed, 305 instance->target, data_stage, data, 306 &instance->tds[packet + 1]); 359 307 360 308 ++packet; … … 375 323 } 376 324 /*----------------------------------------------------------------------------*/ 377 /** Prepares data, gets error status and calls callback in.378 *379 * @param[in] instance Batch structure to use.380 */381 325 void batch_call_in(batch_t *instance) 382 326 { … … 384 328 assert(instance->callback_in); 385 329 386 /* we are data in, we need data */ 387 memcpy(instance->buffer, instance->transport_buffer, 388 instance->buffer_size); 330 memcpy(instance->buffer, instance->transport_buffer, instance->buffer_size); 389 331 390 332 int err = instance->error; … … 393 335 instance->transfered_size); 394 336 395 instance->callback_in( 396 instance->fun, err, instance->transfered_size, instance->arg); 397 } 398 /*----------------------------------------------------------------------------*/ 399 /** Gets error status and calls callback out. 400 * 401 * @param[in] instance Batch structure to use. 402 */ 337 instance->callback_in(instance->fun, 338 err, instance->transfered_size, 339 instance->arg); 340 } 341 /*----------------------------------------------------------------------------*/ 403 342 void batch_call_out(batch_t *instance) 404 343 { … … 413 352 } 414 353 /*----------------------------------------------------------------------------*/ 415 /** Prepares data, gets error status, calls callback in and dispose.416 *417 * @param[in] instance Batch structure to use.418 */419 354 void batch_call_in_and_dispose(batch_t *instance) 420 355 { … … 424 359 } 425 360 /*----------------------------------------------------------------------------*/ 426 /** Gets error status, calls callback out and dispose.427 *428 * @param[in] instance Batch structure to use.429 */430 361 void batch_call_out_and_dispose(batch_t *instance) 431 362 { … … 435 366 } 436 367 /*----------------------------------------------------------------------------*/ 437 /** Correctly disposes all used data structures.438 *439 * @param[in] instance Batch structure to use.440 */441 368 void batch_dispose(batch_t *instance) 442 369 { 443 370 assert(instance); 444 371 usb_log_debug("Batch(%p) disposing.\n", instance); 445 /* free32 is NULL safe */446 372 free32(instance->tds); 447 373 free32(instance->qh); -
uspace/drv/uhci-hcd/iface.c
rec4538d rf16a76b 43 43 #include "utils/device_keeper.h" 44 44 45 /** Reserve default address interface function46 *47 * @param[in] fun DDF function that was called.48 * @param[in] speed Speed to associate with the new default address.49 * @return Error code.50 */51 45 /*----------------------------------------------------------------------------*/ 52 46 static int reserve_default_address(ddf_fun_t *fun, usb_speed_t speed) … … 60 54 } 61 55 /*----------------------------------------------------------------------------*/ 62 /** Release default address interface function63 *64 * @param[in] fun DDF function that was called.65 * @return Error code.66 */67 56 static int release_default_address(ddf_fun_t *fun) 68 57 { … … 75 64 } 76 65 /*----------------------------------------------------------------------------*/ 77 /** Request address interface function78 *79 * @param[in] fun DDF function that was called.80 * @param[in] speed Speed to associate with the new default address.81 * @param[out] address Place to write a new address.82 * @return Error code.83 */84 66 static int request_address(ddf_fun_t *fun, usb_speed_t speed, 85 67 usb_address_t *address) … … 98 80 } 99 81 /*----------------------------------------------------------------------------*/ 100 /** Bind address interface function101 *102 * @param[in] fun DDF function that was called.103 * @param[in] address Address of the device104 * @param[in] handle Devman handle of the device driver.105 * @return Error code.106 */107 82 static int bind_address( 108 83 ddf_fun_t *fun, usb_address_t address, devman_handle_t handle) … … 116 91 } 117 92 /*----------------------------------------------------------------------------*/ 118 /** Release address interface function119 *120 * @param[in] fun DDF function that was called.121 * @param[in] address USB address to be released.122 * @return Error code.123 */124 93 static int release_address(ddf_fun_t *fun, usb_address_t address) 125 94 { … … 132 101 } 133 102 /*----------------------------------------------------------------------------*/ 134 /** Interrupt out transaction interface function135 *136 * @param[in] fun DDF function that was called.137 * @param[in] target USB device to write to.138 * @param[in] max_packet_size maximum size of data packet the device accepts139 * @param[in] data Source of data.140 * @param[in] size Size of data source.141 * @param[in] callback Function to call on transaction completion142 * @param[in] arg Additional for callback function.143 * @return Error code.144 */145 103 static int interrupt_out(ddf_fun_t *fun, usb_target_t target, 146 104 size_t max_packet_size, void *data, size_t size, … … 164 122 } 165 123 /*----------------------------------------------------------------------------*/ 166 /** Interrupt in transaction interface function167 *168 * @param[in] fun DDF function that was called.169 * @param[in] target USB device to write to.170 * @param[in] max_packet_size maximum size of data packet the device accepts171 * @param[out] data Data destination.172 * @param[in] size Size of data source.173 * @param[in] callback Function to call on transaction completion174 * @param[in] arg Additional for callback function.175 * @return Error code.176 */177 124 static int interrupt_in(ddf_fun_t *fun, usb_target_t target, 178 125 size_t max_packet_size, void *data, size_t size, … … 195 142 } 196 143 /*----------------------------------------------------------------------------*/ 197 /** Bulk out transaction interface function198 *199 * @param[in] fun DDF function that was called.200 * @param[in] target USB device to write to.201 * @param[in] max_packet_size maximum size of data packet the device accepts202 * @param[in] data Source of data.203 * @param[in] size Size of data source.204 * @param[in] callback Function to call on transaction completion205 * @param[in] arg Additional for callback function.206 * @return Error code.207 */208 144 static int bulk_out(ddf_fun_t *fun, usb_target_t target, 209 145 size_t max_packet_size, void *data, size_t size, … … 227 163 } 228 164 /*----------------------------------------------------------------------------*/ 229 /** Bulk in transaction interface function230 *231 * @param[in] fun DDF function that was called.232 * @param[in] target USB device to write to.233 * @param[in] max_packet_size maximum size of data packet the device accepts234 * @param[out] data Data destination.235 * @param[in] size Size of data source.236 * @param[in] callback Function to call on transaction completion237 * @param[in] arg Additional for callback function.238 * @return Error code.239 */240 165 static int bulk_in(ddf_fun_t *fun, usb_target_t target, 241 166 size_t max_packet_size, void *data, size_t size, … … 258 183 } 259 184 /*----------------------------------------------------------------------------*/ 260 /** Control write transaction interface function261 *262 * @param[in] fun DDF function that was called.263 * @param[in] target USB device to write to.264 * @param[in] max_packet_size maximum size of data packet the device accepts.265 * @param[in] setup_data Data to send with SETUP packet.266 * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).267 * @param[in] data Source of data.268 * @param[in] size Size of data source.269 * @param[in] callback Function to call on transaction completion.270 * @param[in] arg Additional for callback function.271 * @return Error code.272 */273 185 static int control_write(ddf_fun_t *fun, usb_target_t target, 274 186 size_t max_packet_size, … … 296 208 } 297 209 /*----------------------------------------------------------------------------*/ 298 /** Control read transaction interface function299 *300 * @param[in] fun DDF function that was called.301 * @param[in] target USB device to write to.302 * @param[in] max_packet_size maximum size of data packet the device accepts.303 * @param[in] setup_data Data to send with SETUP packet.304 * @param[in] setup_size Size of data to send with SETUP packet (should be 8B).305 * @param[out] data Source of data.306 * @param[in] size Size of data source.307 * @param[in] callback Function to call on transaction completion.308 * @param[in] arg Additional for callback function.309 * @return Error code.310 */311 210 static int control_read(ddf_fun_t *fun, usb_target_t target, 312 211 size_t max_packet_size, -
uspace/drv/uhci-hcd/main.c
rec4538d rf16a76b 60 60 }; 61 61 /*----------------------------------------------------------------------------*/ 62 /** IRQ handling callback, identifies devic63 *64 * @param[in] dev DDF instance of the device to use.65 * @param[in] iid (Unused).66 * @param[in] call Pointer to the call that represents interrupt.67 */68 62 static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call) 69 63 { … … 75 69 } 76 70 /*----------------------------------------------------------------------------*/ 77 /** Initializes a new ddf driver instance of UHCI hcd. 78 * 79 * @param[in] device DDF instance of the device to initialize. 80 * @return Error code. 81 * 82 * Gets and initialies hardware resources, disables any legacy support, 83 * and reports root hub device. 84 */ 85 int uhci_add_device(ddf_dev_t *device) 71 static int uhci_add_device(ddf_dev_t *device) 86 72 { 87 73 assert(device); … … 110 96 ret = pci_disable_legacy(device); 111 97 CHECK_RET_FREE_HC_RETURN(ret, 112 "Failed(%d) todisable legacy USB: %s.\n", ret, str_error(ret));98 "Failed(%d) disable legacy USB: %s.\n", ret, str_error(ret)); 113 99 114 100 #if 0 … … 127 113 128 114 ret = uhci_init(hcd, device, (void*)io_reg_base, io_reg_size); 129 CHECK_RET_FREE_HC_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", ret); 115 CHECK_RET_FREE_HC_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", 116 ret); 130 117 #undef CHECK_RET_FREE_HC_RETURN 131 118 … … 168 155 } 169 156 /*----------------------------------------------------------------------------*/ 170 /** Initializes global driver structures (NONE).171 *172 * @param[in] argc Nmber of arguments in argv vector (ignored).173 * @param[in] argv Cmdline argument vector (ignored).174 * @return Error code.175 *176 * Driver debug level is set here.177 */178 157 int main(int argc, char *argv[]) 179 158 { -
uspace/drv/uhci-hcd/pci.c
rec4538d rf16a76b 65 65 66 66 int rc; 67 67 68 hw_resource_list_t hw_resources; 68 69 rc = hw_res_get_resource_list(parent_phone, &hw_resources); … … 81 82 for (i = 0; i < hw_resources.count; i++) { 82 83 hw_resource_t *res = &hw_resources.resources[i]; 83 switch (res->type) 84 { 85 case INTERRUPT: 86 irq = res->res.interrupt.irq; 87 irq_found = true; 88 usb_log_debug2("Found interrupt: %d.\n", irq); 89 break; 90 91 case IO_RANGE: 92 io_address = res->res.io_range.address; 93 io_size = res->res.io_range.size; 94 usb_log_debug2("Found io: %llx %zu.\n", 95 res->res.io_range.address, res->res.io_range.size); 96 io_found = true; 97 98 default: 99 break; 84 switch (res->type) { 85 case INTERRUPT: 86 irq = res->res.interrupt.irq; 87 irq_found = true; 88 usb_log_debug2("Found interrupt: %d.\n", irq); 89 break; 90 case IO_RANGE: 91 io_address = res->res.io_range.address; 92 io_size = res->res.io_range.size; 93 usb_log_debug2("Found io: %llx %zu.\n", 94 res->res.io_range.address, res->res.io_range.size); 95 io_found = true; 96 break; 97 default: 98 break; 100 99 } 101 100 } 102 101 103 if (!io_found || !irq_found) { 102 if (!io_found) { 103 rc = ENOENT; 104 goto leave; 105 } 106 107 if (!irq_found) { 104 108 rc = ENOENT; 105 109 goto leave; … … 117 121 } 118 122 /*----------------------------------------------------------------------------*/ 119 /** Calls the PCI driver with a request to enable interrupts120 *121 * @param[in] device Device asking for interrupts122 * @return Error code.123 */124 123 int pci_enable_interrupts(ddf_dev_t *device) 125 124 { … … 131 130 } 132 131 /*----------------------------------------------------------------------------*/ 133 /** Calls the PCI driver with a request to clear legacy support register134 *135 * @param[in] device Device asking to disable interrupts136 * @return Error code.137 */138 132 int pci_disable_legacy(ddf_dev_t *device) 139 133 { 140 134 assert(device); 141 int parent_phone = 142 devman_parent_device_connect(device->handle,IPC_FLAG_BLOCKING);135 int parent_phone = devman_parent_device_connect(device->handle, 136 IPC_FLAG_BLOCKING); 143 137 if (parent_phone < 0) { 144 138 return parent_phone; … … 150 144 sysarg_t value = 0x8f00; 151 145 152 146 int rc = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE), 153 147 IPC_M_CONFIG_SPACE_WRITE_16, address, value); 154 148 async_hangup(parent_phone); 155 149 156 150 return rc; 157 151 } 158 152 /*----------------------------------------------------------------------------*/ -
uspace/drv/uhci-hcd/root_hub.c
rec4538d rf16a76b 45 45 46 46 /*----------------------------------------------------------------------------*/ 47 /** Gets handle of the respective hc (parent device). 48 * 49 * @param[in] root_hub_fun Root hub function seeking hc handle. 50 * @param[out] handle Place to write the handle. 51 * @return Error code. 52 */ 53 static int usb_iface_get_hc_handle_rh_impl( 54 ddf_fun_t *root_hub_fun, devman_handle_t *handle) 47 static int usb_iface_get_hc_handle_rh_impl(ddf_fun_t *root_hub_fun, 48 devman_handle_t *handle) 55 49 { 56 /* TODO: Can't this use parent pointer? */57 50 ddf_fun_t *hc_fun = root_hub_fun->driver_data; 58 51 assert(hc_fun != NULL); … … 63 56 } 64 57 /*----------------------------------------------------------------------------*/ 65 /** Gets USB address of the calling device. 66 * 67 * @param[in] fun Root hub function. 68 * @param[in] handle Handle of the device seeking address. 69 * @param[out] address Place to store found address. 70 * @return Error code. 71 */ 72 static int usb_iface_get_address_rh_impl( 73 ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address) 58 static int usb_iface_get_address_rh_impl(ddf_fun_t *fun, devman_handle_t handle, 59 usb_address_t *address) 74 60 { 75 /* TODO: What does this do? Is it neccessary? Can't it use implemented76 * hc function?*/77 61 assert(fun); 78 62 ddf_fun_t *hc_fun = fun->driver_data; … … 81 65 assert(hc); 82 66 83 usb_address_t addr = device_keeper_find(&hc->device_manager, handle); 67 usb_address_t addr = device_keeper_find(&hc->device_manager, 68 handle); 84 69 if (addr < 0) { 85 70 return addr; … … 98 83 }; 99 84 /*----------------------------------------------------------------------------*/ 100 /** Gets root hub hw resources.101 *102 * @param[in] fun Root hub function.103 * @return Pointer to the resource list used by the root hub.104 */105 85 static hw_resource_list_t *get_resource_list(ddf_fun_t *dev) 106 86 { … … 111 91 assert(hc); 112 92 113 / * TODO: fix memory leak */93 //TODO: fix memory leak 114 94 hw_resource_list_t *resource_list = malloc(sizeof(hw_resource_list_t)); 115 95 assert(resource_list); -
uspace/drv/uhci-hcd/transfer_list.c
rec4538d rf16a76b 38 38 #include "transfer_list.h" 39 39 40 static void transfer_list_remove_batch(41 transfer_list_t *instance, batch_t *batch);42 /*----------------------------------------------------------------------------*/43 /** Initializes transfer list structures.44 *45 * @param[in] instance Memory place to use.46 * @param[in] name Name of te new list.47 * @return Error code48 *49 * Allocates memory for internat queue_head_t structure.50 */51 40 int transfer_list_init(transfer_list_t *instance, const char *name) 52 41 { … … 54 43 instance->next = NULL; 55 44 instance->name = name; 56 instance->queue_head = malloc32(sizeof(queue_head_t));45 instance->queue_head = queue_head_get(); 57 46 if (!instance->queue_head) { 58 47 usb_log_error("Failed to allocate queue head.\n"); 59 48 return ENOMEM; 60 49 } 61 instance->queue_head_pa = addr_to_phys(instance->queue_head);50 instance->queue_head_pa = (uintptr_t)addr_to_phys(instance->queue_head); 62 51 63 52 queue_head_init(instance->queue_head); … … 67 56 } 68 57 /*----------------------------------------------------------------------------*/ 69 /** Set the next list in chain.70 *71 * @param[in] instance List to lead.72 * @param[in] next List to append.73 * @return Error code74 */75 58 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next) 76 59 { … … 83 66 } 84 67 /*----------------------------------------------------------------------------*/ 85 /** Submits a new transfer batch to list and queue.86 *87 * @param[in] instance List to use.88 * @param[in] batch Transfer batch to submit.89 * @return Error code90 */91 68 void transfer_list_add_batch(transfer_list_t *instance, batch_t *batch) 92 69 { 93 70 assert(instance); 94 71 assert(batch); 95 usb_log_debug2( 96 "Adding batch(%p) to queue %s.\n", batch, instance->name); 72 usb_log_debug2("Adding batch(%p) to queue %s.\n", batch, instance->name); 97 73 98 74 uint32_t pa = (uintptr_t)addr_to_phys(batch->qh); … … 121 97 queue_head_append_qh(last->qh, pa); 122 98 list_append(&batch->link, &instance->batch_list); 123 124 99 usb_log_debug("Batch(%p) added to queue %s last, first is %p.\n", 125 batch, instance->name, first );100 batch, instance->name, first ); 126 101 fibril_mutex_unlock(&instance->guard); 127 102 } 128 103 /*----------------------------------------------------------------------------*/ 129 /** Removes a transfer batch from list and queue. 130 * 131 * @param[in] instance List to use. 132 * @param[in] batch Transfer batch to remove. 133 * @return Error code 134 */ 135 void transfer_list_remove_batch(transfer_list_t *instance, batch_t *batch) 104 static void transfer_list_remove_batch( 105 transfer_list_t *instance, batch_t *batch) 136 106 { 137 107 assert(instance); … … 139 109 assert(instance->queue_head); 140 110 assert(batch->qh); 141 usb_log_debug2( 142 "Removing batch(%p) from queue %s.\n", batch, instance->name); 111 usb_log_debug2("Removing batch(%p) from queue %s.\n", batch, instance->name); 143 112 113 /* I'm the first one here */ 144 114 if (batch->link.prev == &instance->batch_list) { 145 /* I'm the first one here */ 146 usb_log_debug( 147 "Batch(%p) removed (FIRST) from %s, next element %x.\n", 148 batch, instance->name, batch->qh->next_queue); 115 usb_log_debug("Batch(%p) removed (FIRST) from queue %s, next element %x.\n", 116 batch, instance->name, batch->qh->next_queue); 149 117 instance->queue_head->element = batch->qh->next_queue; 150 118 } else { 151 usb_log_debug( 152 "Batch(%p) removed (FIRST:NO) from %s, next element %x.\n", 153 batch, instance->name, batch->qh->next_queue); 154 batch_t *prev = 155 list_get_instance(batch->link.prev, batch_t, link); 119 usb_log_debug("Batch(%p) removed (NOT FIRST) from queue, next element %x.\n", 120 batch, instance->name, batch->qh->next_queue); 121 batch_t *prev = list_get_instance(batch->link.prev, batch_t, link); 156 122 prev->qh->next_queue = batch->qh->next_queue; 157 123 } … … 159 125 } 160 126 /*----------------------------------------------------------------------------*/ 161 /** Checks list for finished transfers.162 *163 * @param[in] instance List to use.164 * @return Error code165 */166 127 void transfer_list_remove_finished(transfer_list_t *instance) 167 128 { -
uspace/drv/uhci-hcd/transfer_list.h
rec4538d rf16a76b 58 58 { 59 59 assert(instance); 60 free32(instance->queue_head);60 queue_head_dispose(instance->queue_head); 61 61 } 62 62 void transfer_list_remove_finished(transfer_list_t *instance); -
uspace/drv/uhci-hcd/uhci.c
rec4538d rf16a76b 61 61 }; 62 62 63 /** Gets USB address of the calling device. 64 * 65 * @param[in] fun UHCI hc function. 66 * @param[in] handle Handle of the device seeking address. 67 * @param[out] address Place to store found address. 68 * @return Error code. 69 */ 70 static int usb_iface_get_address( 71 ddf_fun_t *fun, devman_handle_t handle, usb_address_t *address) 63 static int usb_iface_get_address(ddf_fun_t *fun, devman_handle_t handle, 64 usb_address_t *address) 72 65 { 73 66 assert(fun); … … 106 99 107 100 static bool allowed_usb_packet( 108 bool low_speed, usb_transfer_type_t transfer, size_t size); 109 /*----------------------------------------------------------------------------*/ 110 /** Initializes UHCI hcd driver structure 111 * 112 * @param[in] instance Memory place to initialize. 113 * @param[in] dev DDF device. 114 * @param[in] regs Address of I/O control registers. 115 * @param[in] size Size of I/O control registers. 116 * @return Error code. 117 * @note Should be called only once on any structure. 118 */ 101 bool low_speed, usb_transfer_type_t, size_t size); 102 103 119 104 int uhci_init(uhci_t *instance, ddf_dev_t *dev, void *regs, size_t reg_size) 120 105 { … … 171 156 } 172 157 /*----------------------------------------------------------------------------*/ 173 /** Initializes UHCI hcd hw resources.174 *175 * @param[in] instance UHCI structure to use.176 */177 158 void uhci_init_hw(uhci_t *instance) 178 159 { 179 160 assert(instance); 180 regs_t *registers = instance->registers; 181 182 /* Reset everything, who knows what touched it before us */ 183 pio_write_16(®isters->usbcmd, UHCI_CMD_GLOBAL_RESET); 161 162 /* reset everything, who knows what touched it before us */ 163 pio_write_16(&instance->registers->usbcmd, UHCI_CMD_GLOBAL_RESET); 184 164 async_usleep(10000); /* 10ms according to USB spec */ 185 pio_write_16(& registers->usbcmd, 0);186 187 /* Reset hc, all states and counters */188 pio_write_16(& registers->usbcmd, UHCI_CMD_HCRESET);165 pio_write_16(&instance->registers->usbcmd, 0); 166 167 /* reset hc, all states and counters */ 168 pio_write_16(&instance->registers->usbcmd, UHCI_CMD_HCRESET); 189 169 do { async_usleep(10); } 190 while ((pio_read_16(& registers->usbcmd) & UHCI_CMD_HCRESET) != 0);191 192 /* Set framelist pointer */170 while ((pio_read_16(&instance->registers->usbcmd) & UHCI_CMD_HCRESET) != 0); 171 172 /* set framelist pointer */ 193 173 const uint32_t pa = addr_to_phys(instance->frame_list); 194 pio_write_32(& registers->flbaseadd, pa);195 196 /* Enable all interrupts, but resume interrupt */174 pio_write_32(&instance->registers->flbaseadd, pa); 175 176 /* enable all interrupts, but resume interrupt */ 197 177 // pio_write_16(&instance->registers->usbintr, 198 178 // UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET); 199 179 200 uint16_t status = pio_read_16(®isters->usbcmd); 201 if (status != 0) 202 usb_log_warning("Previous command value: %x.\n", status); 203 180 uint16_t status = pio_read_16(&instance->registers->usbcmd); 181 usb_log_warning("Previous command value: %x.\n", status); 204 182 /* Start the hc with large(64B) packet FSBR */ 205 pio_write_16(& registers->usbcmd,183 pio_write_16(&instance->registers->usbcmd, 206 184 UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE); 207 185 } 208 186 /*----------------------------------------------------------------------------*/ 209 /** Initializes UHCI hcd memory structures.210 *211 * @param[in] instance UHCI structure to use.212 * @return Error code213 * @note Should be called only once on any structure.214 */215 187 int uhci_init_mem_structures(uhci_t *instance) 216 188 { … … 224 196 } else (void) 0 225 197 226 /* Init interrupt code */198 /* init interrupt code */ 227 199 instance->interrupt_code.cmds = malloc(sizeof(uhci_cmds)); 228 200 int ret = (instance->interrupt_code.cmds == NULL) ? ENOMEM : EOK; 229 CHECK_RET_DEST_CMDS_RETURN(ret, 230 "Failed to allocate interrupt cmds space.\n"); 201 CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to allocate interrupt cmds space.\n"); 231 202 232 203 { 233 204 irq_cmd_t *interrupt_commands = instance->interrupt_code.cmds; 234 205 memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds)); 235 interrupt_commands[0].addr = 236 (void*)&instance->registers->usbsts; 237 interrupt_commands[1].addr = 238 (void*)&instance->registers->usbsts; 206 interrupt_commands[0].addr = (void*)&instance->registers->usbsts; 207 interrupt_commands[1].addr = (void*)&instance->registers->usbsts; 239 208 instance->interrupt_code.cmdcount = 240 209 sizeof(uhci_cmds) / sizeof(irq_cmd_t); 241 210 } 242 211 243 /* Init transfer lists */212 /* init transfer lists */ 244 213 ret = uhci_init_transfer_lists(instance); 245 CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to init transfer lists.\n");214 CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to initialize transfer lists.\n"); 246 215 usb_log_debug("Initialized transfer lists.\n"); 247 216 248 /* Init USB frame list page*/217 /* frame list initialization */ 249 218 instance->frame_list = get_page(); 250 219 ret = instance ? EOK : ENOMEM; … … 252 221 usb_log_debug("Initialized frame list.\n"); 253 222 254 /* Setall frames to point to the first queue head */223 /* initialize all frames to point to the first queue head */ 255 224 const uint32_t queue = 256 225 instance->transfers_interrupt.queue_head_pa … … 262 231 } 263 232 264 /* Init device keeper*/233 /* init address keeper(libusb) */ 265 234 device_keeper_init(&instance->device_manager); 266 235 usb_log_debug("Initialized device manager.\n"); … … 270 239 } 271 240 /*----------------------------------------------------------------------------*/ 272 /** Initializes UHCI hcd transfer lists.273 *274 * @param[in] instance UHCI structure to use.275 * @return Error code276 * @note Should be called only once on any structure.277 */278 241 int uhci_init_transfer_lists(uhci_t *instance) 279 242 { … … 294 257 CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list."); 295 258 296 ret = transfer_list_init( 297 &instance->transfers_control_full, "CONTROL_FULL"); 259 ret = transfer_list_init(&instance->transfers_control_full, "CONTROL_FULL"); 298 260 CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list."); 299 261 300 ret = transfer_list_init( 301 &instance->transfers_control_slow, "CONTROL_SLOW"); 262 ret = transfer_list_init(&instance->transfers_control_slow, "CONTROL_SLOW"); 302 263 CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list."); 303 264 … … 318 279 #endif 319 280 320 /* Assign pointers to be used during scheduling */ 321 instance->transfers[USB_SPEED_FULL][USB_TRANSFER_INTERRUPT] = 281 instance->transfers[0][USB_TRANSFER_INTERRUPT] = 322 282 &instance->transfers_interrupt; 323 instance->transfers[ USB_SPEED_LOW][USB_TRANSFER_INTERRUPT] =283 instance->transfers[1][USB_TRANSFER_INTERRUPT] = 324 284 &instance->transfers_interrupt; 325 instance->transfers[ USB_SPEED_FULL][USB_TRANSFER_CONTROL] =285 instance->transfers[0][USB_TRANSFER_CONTROL] = 326 286 &instance->transfers_control_full; 327 instance->transfers[ USB_SPEED_LOW][USB_TRANSFER_CONTROL] =287 instance->transfers[1][USB_TRANSFER_CONTROL] = 328 288 &instance->transfers_control_slow; 329 instance->transfers[ USB_SPEED_FULL][USB_TRANSFER_BULK] =289 instance->transfers[0][USB_TRANSFER_BULK] = 330 290 &instance->transfers_bulk_full; 331 291 … … 334 294 } 335 295 /*----------------------------------------------------------------------------*/ 336 /** Schedules batch for execution.337 *338 * @param[in] instance UHCI structure to use.339 * @param[in] batch Transfer batch to schedule.340 * @return Error code341 */342 296 int uhci_schedule(uhci_t *instance, batch_t *batch) 343 297 { … … 347 301 if (!allowed_usb_packet( 348 302 low_speed, batch->transfer_type, batch->max_packet_size)) { 349 usb_log_warning( 350 "Invalid USB packet specified %s SPEED %d %zu.\n", 303 usb_log_warning("Invalid USB packet specified %s SPEED %d %zu.\n", 351 304 low_speed ? "LOW" : "FULL" , batch->transfer_type, 352 305 batch->max_packet_size); … … 363 316 } 364 317 /*----------------------------------------------------------------------------*/ 365 /** Takes action based on the interrupt cause.366 *367 * @param[in] instance UHCI structure to use.368 * @param[in] status Value of the stsatus regiser at the time of interrupt.369 */370 318 void uhci_interrupt(uhci_t *instance, uint16_t status) 371 319 { 372 320 assert(instance); 373 /* TODO: Check interrupt cause here */374 321 transfer_list_remove_finished(&instance->transfers_interrupt); 375 322 transfer_list_remove_finished(&instance->transfers_control_slow); … … 378 325 } 379 326 /*----------------------------------------------------------------------------*/ 380 /** Polling function, emulates interrupts.381 *382 * @param[in] arg UHCI structure to use.383 * @return EOK384 */385 327 int uhci_interrupt_emulator(void* arg) 386 328 { … … 401 343 } 402 344 /*---------------------------------------------------------------------------*/ 403 /** Debug function, checks consistency of memory structures.404 *405 * @param[in] arg UHCI structure to use.406 * @return EOK407 */408 345 int uhci_debug_checker(void *arg) 409 346 { … … 464 401 async_usleep(UHCI_DEBUGER_TIMEOUT); 465 402 } 466 return EOK;403 return 0; 467 404 #undef QH 468 405 } 469 406 /*----------------------------------------------------------------------------*/ 470 /** Checks transfer packets, for USB validity471 *472 * @param[in] low_speed Transfer speed.473 * @param[in] transfer Transer type474 * @param[in] size Maximum size of used packets475 * @return EOK476 */477 407 bool allowed_usb_packet( 478 408 bool low_speed, usb_transfer_type_t transfer, size_t size) -
uspace/drv/uhci-hcd/uhci.h
rec4538d rf16a76b 84 84 device_keeper_t device_manager; 85 85 86 regs_t *registers;86 volatile regs_t *registers; 87 87 88 88 link_pointer_t *frame_list; -
uspace/drv/uhci-hcd/uhci_struct/queue_head.h
rec4538d rf16a76b 71 71 } 72 72 73 static inline void queue_head_ set_element_td(queue_head_t *instance, uint32_t pa)73 static inline void queue_head_element_td(queue_head_t *instance, uint32_t pa) 74 74 { 75 75 if (pa) { … … 78 78 } 79 79 80 static inline queue_head_t * queue_head_get() { 81 queue_head_t *ret = malloc32(sizeof(queue_head_t)); 82 if (ret) 83 queue_head_init(ret); 84 return ret; 85 } 86 87 static inline void queue_head_dispose(queue_head_t *head) 88 { free32(head); } 89 90 80 91 #endif 81 92 /** -
uspace/drv/uhci-hcd/uhci_struct/transfer_descriptor.c
rec4538d rf16a76b 38 38 #include "utils/malloc32.h" 39 39 40 /** Initializes Transfer Descriptor41 *42 * @param[in] instance Memory place to initialize.43 * @param[in] err_count Number of retries hc should attempt.44 * @param[in] size Size of data source.45 * @param[in] toggle Value of toggle bit.46 * @param[in] iso True if TD is for Isochronous transfer.47 * @param[in] low_speed Target device's speed.48 * @param[in] target Address and endpoint receiving the transfer.49 * @param[in] pid Packet identification (SETUP, IN or OUT).50 * @param[in] buffer Source of data.51 * @param[in] next Net TD in transaction.52 * @return Error code.53 */54 40 void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso, 55 bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer, 56 td_t *next) 41 bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer, td_t *next) 57 42 { 58 43 assert(instance); 59 44 assert(size < 1024); 60 assert((pid == USB_PID_SETUP) || (pid == USB_PID_IN) 61 || (pid == USB_PID_OUT)); 45 assert((pid == USB_PID_SETUP) || (pid == USB_PID_IN) || (pid == USB_PID_OUT)); 62 46 63 47 instance->next = 0 … … 97 81 } 98 82 /*----------------------------------------------------------------------------*/ 99 /** Converts TD status into standard error code100 *101 * @param[in] instance TD structure to use.102 * @return Error code.103 */104 83 int td_status(td_t *instance) 105 84 { -
uspace/drv/uhci-hcd/utils/device_keeper.c
rec4538d rf16a76b 39 39 40 40 /*----------------------------------------------------------------------------*/ 41 /** Initializes device keeper structure.42 *43 * @param[in] instance Memory place to initialize.44 */45 41 void device_keeper_init(device_keeper_t *instance) 46 42 { … … 57 53 } 58 54 /*----------------------------------------------------------------------------*/ 59 /** Attempts to obtain address 0, blocks. 60 * 61 * @param[in] instance Device keeper structure to use. 62 * @param[in] speed Speed of the device requesting default address. 63 */ 64 void device_keeper_reserve_default(device_keeper_t *instance, usb_speed_t speed) 55 void device_keeper_reserve_default( 56 device_keeper_t *instance, usb_speed_t speed) 65 57 { 66 58 assert(instance); … … 75 67 } 76 68 /*----------------------------------------------------------------------------*/ 77 /** Attempts to obtain address 0, blocks.78 *79 * @param[in] instance Device keeper structure to use.80 * @param[in] speed Speed of the device requesting default address.81 */82 69 void device_keeper_release_default(device_keeper_t *instance) 83 70 { … … 89 76 } 90 77 /*----------------------------------------------------------------------------*/ 91 /** Checks setup data for signs of toggle reset.92 *93 * @param[in] instance Device keeper structure to use.94 * @param[in] target Device to receive setup packet.95 * @param[in] data Setup packet data.96 */97 78 void device_keeper_reset_if_need( 98 79 device_keeper_t *instance, usb_target_t target, const unsigned char *data) … … 103 84 || target.address >= USB_ADDRESS_COUNT || target.address < 0 104 85 || !instance->devices[target.address].occupied) { 105 fibril_mutex_unlock(&instance->guard); 106 return; 86 goto the_end; 107 87 } 108 88 … … 110 90 { 111 91 case 0x01: /*clear feature*/ 112 /* recipient is en dpoint, value is zero (ENDPOINT_STALL) */92 /* recipient is enpoint, value is zero (ENDPOINT_STALL) */ 113 93 if (((data[0] & 0xf) == 1) && ((data[2] | data[3]) == 0)) { 114 /* endpoint number is < 16, thus first byte is enough */ 115 instance->devices[target.address].toggle_status &= 116 ~(1 << data[4]); 94 /* enpoint number is < 16, thus first byte is enough */ 95 instance->devices[target.address].toggle_status &= ~(1 << data[4]); 117 96 } 118 97 break; … … 123 102 break; 124 103 } 125 fibril_mutex_unlock(&instance->guard); 126 } 127 /*----------------------------------------------------------------------------*/ 128 /** Gets current value of endpoint toggle. 129 * 130 * @param[in] instance Device keeper structure to use. 131 * @param[in] target Device and endpoint used. 132 * @return Error code 133 */ 104 the_end: 105 fibril_mutex_unlock(&instance->guard); 106 } 107 /*----------------------------------------------------------------------------*/ 134 108 int device_keeper_get_toggle(device_keeper_t *instance, usb_target_t target) 135 109 { … … 142 116 ret = EINVAL; 143 117 } else { 144 ret = 145 (instance->devices[target.address].toggle_status 146 >> target.endpoint) & 1; 118 ret = (instance->devices[target.address].toggle_status >> target.endpoint) & 1; 147 119 } 148 120 fibril_mutex_unlock(&instance->guard); … … 150 122 } 151 123 /*----------------------------------------------------------------------------*/ 152 /** Sets current value of endpoint toggle.153 *154 * @param[in] instance Device keeper structure to use.155 * @param[in] target Device and endpoint used.156 * @param[in] toggle Current toggle value.157 * @return Error code.158 */159 124 int device_keeper_set_toggle( 160 125 device_keeper_t *instance, usb_target_t target, bool toggle) … … 179 144 } 180 145 /*----------------------------------------------------------------------------*/ 181 /** Gets a free USB address182 *183 * @param[in] instance Device keeper structure to use.184 * @param[in] speed Speed of the device requiring address.185 * @return Free address, or error code.186 */187 146 usb_address_t device_keeper_request( 188 147 device_keeper_t *instance, usb_speed_t speed) … … 212 171 } 213 172 /*----------------------------------------------------------------------------*/ 214 /** Binds USB address to devman handle.215 *216 * @param[in] instance Device keeper structure to use.217 * @param[in] address Device address218 * @param[in] handle Devman handle of the device.219 */220 173 void device_keeper_bind( 221 174 device_keeper_t *instance, usb_address_t address, devman_handle_t handle) … … 230 183 } 231 184 /*----------------------------------------------------------------------------*/ 232 /** Releases used USB address.233 *234 * @param[in] instance Device keeper structure to use.235 * @param[in] address Device address236 */237 185 void device_keeper_release(device_keeper_t *instance, usb_address_t address) 238 186 { … … 247 195 } 248 196 /*----------------------------------------------------------------------------*/ 249 /** Finds USB address associated with the device250 *251 * @param[in] instance Device keeper structure to use.252 * @param[in] handle Devman handle of the device seeking its address.253 * @return USB Address, or error code.254 */255 197 usb_address_t device_keeper_find( 256 198 device_keeper_t *instance, devman_handle_t handle) … … 270 212 } 271 213 /*----------------------------------------------------------------------------*/ 272 /** Gets speed associated with the address273 *274 * @param[in] instance Device keeper structure to use.275 * @param[in] address Address of the device.276 * @return USB speed.277 */278 214 usb_speed_t device_keeper_speed( 279 215 device_keeper_t *instance, usb_address_t address) -
uspace/drv/uhci-rhd/main.c
rec4538d rf16a76b 35 35 #include <devman.h> 36 36 #include <device/hw_res.h> 37 #include <errno.h>38 37 #include <usb_iface.h> 39 38 #include <usb/ddfiface.h> 39 40 #include <errno.h> 41 40 42 #include <usb/debug.h> 41 42 43 43 44 44 #include "root_hub.h" … … 47 47 static int hc_get_my_registers(ddf_dev_t *dev, 48 48 uintptr_t *io_reg_address, size_t *io_reg_size); 49 /*----------------------------------------------------------------------------*/ 49 50 50 static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle) 51 51 { … … 58 58 return EOK; 59 59 } 60 /*----------------------------------------------------------------------------*/ 60 61 61 static usb_iface_t uhci_rh_usb_iface = { 62 62 .get_hc_handle = usb_iface_get_hc_handle, 63 63 .get_address = usb_iface_get_address_hub_impl 64 64 }; 65 /*----------------------------------------------------------------------------*/ 65 66 66 static ddf_dev_ops_t uhci_rh_ops = { 67 67 .interfaces[USB_DEV_IFACE] = &uhci_rh_usb_iface, 68 68 }; 69 /*----------------------------------------------------------------------------*/ 70 /** Initializes a new ddf driver instance of UHCI root hub. 71 * 72 * @param[in] device DDF instance of the device to initialize. 73 * @return Error code. 74 */ 69 75 70 static int uhci_rh_add_device(ddf_dev_t *device) 76 71 { … … 109 104 return EOK; 110 105 } 111 /*----------------------------------------------------------------------------*/ 106 112 107 static driver_ops_t uhci_rh_driver_ops = { 113 108 .add_device = uhci_rh_add_device, 114 109 }; 115 /*----------------------------------------------------------------------------*/ 110 116 111 static driver_t uhci_rh_driver = { 117 112 .name = NAME, … … 119 114 }; 120 115 /*----------------------------------------------------------------------------*/ 121 /** Initializes global driver structures (NONE).122 *123 * @param[in] argc Nmber of arguments in argv vector (ignored).124 * @param[in] argv Cmdline argument vector (ignored).125 * @return Error code.126 *127 * Driver debug level is set here.128 */129 116 int main(int argc, char *argv[]) 130 117 { … … 133 120 } 134 121 /*----------------------------------------------------------------------------*/ 135 /** Get address of I/O registers. 136 * 137 * @param[in] dev Device asking for the addresses. 138 * @param[out] io_reg_address Base address of the memory range. 139 * @param[out] io_reg_size Size of the memory range. 140 * @return Error code. 141 */ 142 int hc_get_my_registers( 143 ddf_dev_t *dev, uintptr_t *io_reg_address, size_t *io_reg_size) 122 int hc_get_my_registers(ddf_dev_t *dev, 123 uintptr_t *io_reg_address, size_t *io_reg_size) 144 124 { 145 125 assert(dev != NULL); … … 166 146 for (i = 0; i < hw_resources.count; i++) { 167 147 hw_resource_t *res = &hw_resources.resources[i]; 168 switch (res->type) 169 {170 case IO_RANGE:171 io_address = (uintptr_t)res->res.io_range.address;172 io_size = res->res.io_range.size;173 io_found = true;174 175 default:176 break;148 switch (res->type) { 149 case IO_RANGE: 150 io_address = (uintptr_t) 151 res->res.io_range.address; 152 io_size = res->res.io_range.size; 153 io_found = true; 154 break; 155 default: 156 break; 177 157 } 178 158 } … … 190 170 } 191 171 rc = EOK; 192 193 172 leave: 194 173 async_hangup(parent_phone); 174 195 175 return rc; 196 176 } -
uspace/drv/uhci-rhd/port.c
rec4538d rf16a76b 46 46 #include "port_status.h" 47 47 48 static int uhci_port_new_device(uhci_port_t *port, u sb_speed_t speed);48 static int uhci_port_new_device(uhci_port_t *port, uint16_t status); 49 49 static int uhci_port_remove_device(uhci_port_t *port); 50 50 static int uhci_port_set_enabled(uhci_port_t *port, bool enabled); 51 51 static int uhci_port_check(void *port); 52 static int uhci_port_reset_enable(int portno, void *arg); 53 /*----------------------------------------------------------------------------*/ 54 /** Initializes UHCI root hub port instance. 55 * 56 * @param[in] port Memory structure to use. 57 * @param[in] addr Address of I/O register. 58 * @param[in] number Port number. 59 * @param[in] usec Polling interval. 60 * @param[in] rh Pointer to ddf instance fo the root hub driver. 61 * @return Error code. 62 * 63 * Starts the polling fibril. 64 */ 65 int uhci_port_init(uhci_port_t *port, 66 port_status_t *address, unsigned number, unsigned usec, ddf_dev_t *rh) 52 static int new_device_enable_port(int portno, void *arg); 53 54 int uhci_port_init( 55 uhci_port_t *port, port_status_t *address, unsigned number, 56 unsigned usec, ddf_dev_t *rh) 67 57 { 68 58 assert(port); 69 70 59 port->address = address; 71 60 port->number = number; … … 73 62 port->attached_device = 0; 74 63 port->rh = rh; 75 76 64 int rc = usb_hc_connection_initialize_from_device( 77 65 &port->hc_connection, rh); … … 87 75 return ENOMEM; 88 76 } 89 90 77 fibril_add_ready(port->checker); 91 78 usb_log_debug("Port(%p - %d): Added fibril. %x\n", … … 94 81 } 95 82 /*----------------------------------------------------------------------------*/ 96 /** Finishes UHCI root hub port instance.97 *98 * @param[in] port Memory structure to use.99 *100 * Stops the polling fibril.101 */102 83 void uhci_port_fini(uhci_port_t *port) 103 84 { 104 /* TODO: Kill fibril here */ 85 // TODO: destroy fibril 86 // TODO: hangup phone 87 // fibril_teardown(port->checker); 105 88 return; 106 89 } 107 90 /*----------------------------------------------------------------------------*/ 108 /** Periodically checks port status and reports new devices.109 *110 * @param[in] port Memory structure to use.111 * @return Error code.112 */113 91 int uhci_port_check(void *port) 114 92 { 115 uhci_port_t * instance = port;116 assert( instance);117 118 /* Iteration count, for debug purposes only */ 93 uhci_port_t *port_instance = port; 94 assert(port_instance); 95 // port_status_write(port_instance->address, 0); 96 119 97 unsigned count = 0; 120 98 121 99 while (1) { 122 async_usleep( instance->wait_period_usec);100 async_usleep(port_instance->wait_period_usec); 123 101 124 102 /* read register value */ 125 port_status_t port_status = port_status_read(instance->address);126 127 /* debug print mutex */ 128 static fibril_mutex_t dbg_mtx =129 103 port_status_t port_status = 104 port_status_read(port_instance->address); 105 106 /* debug print */ 107 static fibril_mutex_t dbg_mtx = FIBRIL_MUTEX_INITIALIZER(dbg_mtx); 130 108 fibril_mutex_lock(&dbg_mtx); 131 109 usb_log_debug2("Port(%p - %d): Status: %#04x. === %u\n", 132 instance->address,instance->number, port_status, count++);110 port_instance->address, port_instance->number, port_status, count++); 133 111 // print_port_status(port_status); 134 112 fibril_mutex_unlock(&dbg_mtx); 135 113 136 if ((port_status & STATUS_CONNECTED_CHANGED) == 0) 137 continue; 138 139 usb_log_debug("Port(%p - %d): Connected change detected: %x.\n", 140 instance->address, instance->number, port_status); 141 142 int rc = 143 usb_hc_connection_open(&instance->hc_connection); 144 if (rc != EOK) { 145 usb_log_error("Port(%p - %d): Failed to connect to HC.", 146 instance->address, instance->number); 147 continue; 114 if ((port_status & STATUS_CONNECTED_CHANGED) != 0) { 115 usb_log_debug("Port(%p - %d): Connected change detected: %x.\n", 116 port_instance->address, port_instance->number, port_status); 117 118 119 int rc = usb_hc_connection_open( 120 &port_instance->hc_connection); 121 if (rc != EOK) { 122 usb_log_error("Port(%p - %d): Failed to connect to HC.", 123 port_instance->address, port_instance->number); 124 continue; 125 } 126 127 /* remove any old device */ 128 if (port_instance->attached_device) { 129 usb_log_debug("Port(%p - %d): Removing device.\n", 130 port_instance->address, port_instance->number); 131 uhci_port_remove_device(port_instance); 132 } 133 134 if ((port_status & STATUS_CONNECTED) != 0) { 135 /* new device */ 136 uhci_port_new_device(port_instance, port_status); 137 } else { 138 /* ack changes by writing one to WC bits */ 139 port_status_write(port_instance->address, port_status); 140 usb_log_debug("Port(%p - %d): Change status ACK.\n", 141 port_instance->address, port_instance->number); 142 } 143 144 rc = usb_hc_connection_close( 145 &port_instance->hc_connection); 146 if (rc != EOK) { 147 usb_log_error("Port(%p - %d): Failed to disconnect from HC.", 148 port_instance->address, port_instance->number); 149 } 148 150 } 149 150 /* Remove any old device */ 151 if (instance->attached_device) { 152 usb_log_debug2("Port(%p - %d): Removing device.\n", 153 instance->address, instance->number); 154 uhci_port_remove_device(instance); 155 } 156 157 if ((port_status & STATUS_CONNECTED) != 0) { 158 /* New device */ 159 const usb_speed_t speed = 160 ((port_status & STATUS_LOW_SPEED) != 0) ? 161 USB_SPEED_LOW : USB_SPEED_FULL; 162 uhci_port_new_device(instance, speed); 163 } else { 164 /* Write one to WC bits, to ack changes */ 165 port_status_write(instance->address, port_status); 166 usb_log_debug("Port(%p - %d): Change status ACK.\n", 167 instance->address, instance->number); 168 } 169 170 rc = usb_hc_connection_close(&instance->hc_connection); 171 if (rc != EOK) { 172 usb_log_error("Port(%p - %d): Failed to disconnect.", 173 instance->address, instance->number); 174 } 175 } 176 return EOK; 177 } 178 /*----------------------------------------------------------------------------*/ 151 } 152 return EOK; 153 } 154 179 155 /** Callback for enabling port during adding a new device. 180 156 * … … 183 159 * @return Error code. 184 160 */ 185 int uhci_port_reset_enable(int portno, void *arg)161 static int new_device_enable_port(int portno, void *arg) 186 162 { 187 163 uhci_port_t *port = (uhci_port_t *) arg; … … 208 184 port_status_write(port->address, port_status); 209 185 async_usleep(10000); 210 port_status = port_status_read(port->address); 186 port_status = 187 port_status_read(port->address); 211 188 port_status &= ~STATUS_IN_RESET; 212 189 port_status_write(port->address, port_status); … … 217 194 /* Enable the port. */ 218 195 uhci_port_set_enabled(port, true); 219 return EOK; 220 } 221 /*----------------------------------------------------------------------------*/ 222 /** Initializes and reports connected device. 223 * 224 * @param[in] port Memory structure to use. 225 * @param[in] speed Detected speed. 226 * @return Error code. 227 * 228 * Uses libUSB function to do the actual work. 229 */ 230 int uhci_port_new_device(uhci_port_t *port, usb_speed_t speed) 196 197 return EOK; 198 } 199 200 /*----------------------------------------------------------------------------*/ 201 static int uhci_port_new_device(uhci_port_t *port, uint16_t status) 231 202 { 232 203 assert(port); … … 238 209 usb_address_t dev_addr; 239 210 int rc = usb_hc_new_device_wrapper(port->rh, &port->hc_connection, 240 speed, uhci_port_reset_enable, port->number, port, 211 ((status & STATUS_LOW_SPEED) != 0) ? USB_SPEED_LOW : USB_SPEED_FULL, 212 new_device_enable_port, port->number, port, 241 213 &dev_addr, &port->attached_device, NULL, NULL, NULL); 242 214 243 215 if (rc != EOK) { 244 usb_log_error("Port(%p-%d): Failed(%d) to adddevice: %s.\n",216 usb_log_error("Port(%p-%d): Failed(%d) adding new device: %s.\n", 245 217 port->address, port->number, rc, str_error(rc)); 246 218 uhci_port_set_enabled(port, false); … … 253 225 return EOK; 254 226 } 255 /*----------------------------------------------------------------------------*/ 256 /** Removes device. 257 * 258 * @param[in] port Memory structure to use. 259 * @return Error code. 260 * 261 * Does not work DDF does not support device removal. 262 */ 263 int uhci_port_remove_device(uhci_port_t *port) 227 228 /*----------------------------------------------------------------------------*/ 229 static int uhci_port_remove_device(uhci_port_t *port) 264 230 { 265 231 usb_log_error("Port(%p-%d): Don't know how to remove device %#x.\n", 266 port->address, port->number, (unsigned int)port->attached_device); 267 return EOK; 268 } 269 /*----------------------------------------------------------------------------*/ 270 /** Enables and disables port. 271 * 272 * @param[in] port Memory structure to use. 273 * @return Error code. (Always EOK) 274 */ 275 int uhci_port_set_enabled(uhci_port_t *port, bool enabled) 232 port->address, port->number, (unsigned int)port->attached_device); 233 // uhci_port_set_enabled(port, false); 234 return EOK; 235 } 236 /*----------------------------------------------------------------------------*/ 237 static int uhci_port_set_enabled(uhci_port_t *port, bool enabled) 276 238 { 277 239 assert(port); 278 240 279 /* Read register value */ 280 port_status_t port_status = port_status_read(port->address); 281 282 /* Set enabled bit */ 241 /* read register value */ 242 port_status_t port_status 243 = port_status_read(port->address); 244 245 /* enable port: register write */ 283 246 if (enabled) { 284 247 port_status |= STATUS_ENABLED; … … 286 249 port_status &= ~STATUS_ENABLED; 287 250 } 288 289 /* Write new value. */290 251 port_status_write(port->address, port_status); 291 252 -
uspace/drv/uhci-rhd/port_status.c
rec4538d rf16a76b 60 60 }; 61 61 62 /** Prints portr status in a human readable way.63 *64 * @param[in] value Port value to print.65 * @return Error code.66 */67 62 void print_port_status(port_status_t value) 68 63 { -
uspace/drv/uhci-rhd/root_hub.c
rec4538d rf16a76b 40 40 #include "root_hub.h" 41 41 42 /** Initializes UHCI root hub instance.43 *44 * @param[in] instance Driver memory structure to use.45 * @param[in] addr Address of I/O registers.46 * @param[in] size Size of available I/O space.47 * @param[in] rh Pointer to ddf instance fo the root hub driver.48 * @return Error code.49 */50 42 int uhci_root_hub_init( 51 43 uhci_root_hub_t *instance, void *addr, size_t size, ddf_dev_t *rh) … … 55 47 int ret; 56 48 57 /* Allow access to root hub portregisters */58 assert(sizeof(port_status_t) * UHCI_ROOT_HUB_PORT_COUNT <= size);49 /* allow access to root hub registers */ 50 assert(sizeof(port_status_t) * UHCI_ROOT_HUB_PORT_COUNT == size); 59 51 port_status_t *regs; 60 52 ret = pio_enable(addr, size, (void**)®s); 53 61 54 if (ret < 0) { 62 usb_log_error( 63 "Failed to gain access to port registers at %p\n", regs); 55 usb_log_error("Failed to gain access to port registers at %p\n", regs); 64 56 return ret; 65 57 } … … 68 60 unsigned i = 0; 69 61 for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) { 70 /* NOTE: mind pointer arithmetics here*/62 /* mind pointer arithmetics */ 71 63 ret = uhci_port_init( 72 64 &instance->ports[i], regs + i, i, ROOT_HUB_WAIT_USEC, rh); 73 65 if (ret != EOK) { 74 66 unsigned j = 0; … … 82 74 } 83 75 /*----------------------------------------------------------------------------*/ 84 /** Finishes UHCI root hub instance. 85 * 86 * @param[in] instance Driver memory structure to use. 87 * @return Error code. 88 */ 89 int uhci_root_hub_fini(uhci_root_hub_t* instance) 76 int uhci_root_hub_fini( uhci_root_hub_t* instance ) 90 77 { 91 assert(instance); 92 unsigned i = 0; 93 for (; i < UHCI_ROOT_HUB_PORT_COUNT; ++i) { 94 uhci_port_fini(&instance->ports[i]); 95 } 78 assert( instance ); 79 // TODO: 80 //destroy fibril here 81 //disable access to registers 96 82 return EOK; 97 83 }
Note:
See TracChangeset
for help on using the changeset viewer.