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