Changeset e1dbcbc in mainline for uspace/drv/ohci/root_hub.c
- Timestamp:
- 2011-04-29T13:43:01Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- a81a1d09
- Parents:
- 380e0364 (diff), f19f1b7 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/ohci/root_hub.c
r380e0364 re1dbcbc 149 149 150 150 151 static void usb_create_serialized_hub_descriptor(rh_t *instance, 152 uint8_t ** out_result, 153 size_t * out_size); 154 155 static void rh_init_descriptors(rh_t *instance); 151 static int create_serialized_hub_descriptor(rh_t *instance); 152 153 static int rh_init_descriptors(rh_t *instance); 156 154 157 155 static int process_get_port_status_request(rh_t *instance, uint16_t port, … … 164 162 usb_transfer_batch_t * request); 165 163 166 static void create_interrupt_mask(rh_t *instance, void ** buffer, 167 size_t * buffer_size); 164 static void create_interrupt_mask_in_instance(rh_t *instance); 168 165 169 166 static int process_get_descriptor_request(rh_t *instance, … … 198 195 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request); 199 196 200 197 static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request); 198 199 static bool is_zeros(void * buffer, size_t size); 201 200 202 201 … … 205 204 * @return Error code. 206 205 */ 207 int rh_init(rh_t *instance, ddf_dev_t *dev,ohci_regs_t *regs) {206 int rh_init(rh_t *instance, ohci_regs_t *regs) { 208 207 assert(instance); 209 //instance->address = -1;210 208 instance->registers = regs; 211 instance->device = dev;212 209 instance->port_count = 213 210 (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK; 214 rh_init_descriptors(instance); 211 int opResult = rh_init_descriptors(instance); 212 if(opResult != EOK){ 213 return opResult; 214 } 215 215 // set port power mode to no-power-switching 216 instance->registers->rh_desc_a = 217 instance->registers->rh_desc_a | (1<<9); 216 instance->registers->rh_desc_a |= RHDA_NPS_FLAG; 217 instance->unfinished_interrupt_transfer = NULL; 218 instance->interrupt_mask_size = (instance->port_count + 8)/8; 219 instance->interrupt_buffer = malloc(instance->interrupt_mask_size); 220 if(!instance->interrupt_buffer) 221 return ENOMEM; 222 218 223 219 224 usb_log_info("OHCI root hub with %d ports.\n", instance->port_count); 220 221 //start generic usb hub driver222 223 /* TODO: implement */224 225 return EOK; 225 226 } … … 237 238 assert(request); 238 239 int opResult; 239 if (request-> transfer_type == USB_TRANSFER_CONTROL) {240 if (request->ep->transfer_type == USB_TRANSFER_CONTROL) { 240 241 usb_log_info("Root hub got CONTROL packet\n"); 241 242 opResult = process_ctrl_request(instance, request); 242 } else if (request->transfer_type == USB_TRANSFER_INTERRUPT) { 243 usb_transfer_batch_finish_error(request, opResult); 244 } else if (request->ep->transfer_type == USB_TRANSFER_INTERRUPT) { 243 245 usb_log_info("Root hub got INTERRUPT packet\n"); 244 void * buffer; 245 create_interrupt_mask(instance, &buffer, 246 &(request->transfered_size)); 247 memcpy(request->transport_buffer, buffer, 248 request->transfered_size); 246 create_interrupt_mask_in_instance(instance); 247 if(is_zeros(instance->interrupt_buffer, 248 instance->interrupt_mask_size)){ 249 usb_log_debug("no changes..\n"); 250 instance->unfinished_interrupt_transfer = request; 251 //will be finished later 252 }else{ 253 usb_log_debug("processing changes..\n"); 254 process_interrupt_mask_in_instance(instance, request); 255 } 249 256 opResult = EOK; 250 257 } else { 251 258 opResult = EINVAL; 252 } 253 usb_transfer_batch_finish_error(request, opResult); 254 return EOK; 255 } 256 257 /*----------------------------------------------------------------------------*/ 258 259 259 usb_transfer_batch_finish_error(request, opResult); 260 } 261 return EOK; 262 } 263 264 /*----------------------------------------------------------------------------*/ 265 266 /** 267 * process interrupt on a hub 268 * 269 * If there is no pending interrupt transfer, nothing happens. 270 * @param instance 271 */ 260 272 void rh_interrupt(rh_t *instance) { 261 usb_log_info("Whoa whoa wait, I`m not supposed to receive any " 262 "interrupts, am I?\n"); 263 /* TODO: implement? */ 273 if(!instance->unfinished_interrupt_transfer){ 274 return; 275 } 276 usb_log_debug("finalizing interrupt transfer\n"); 277 create_interrupt_mask_in_instance(instance); 278 process_interrupt_mask_in_instance(instance, 279 instance->unfinished_interrupt_transfer); 264 280 } 265 281 /*----------------------------------------------------------------------------*/ … … 272 288 * 273 289 * @param instance root hub instance 274 * @param@out out_result pointer to resultant serialized descriptor 275 * @param@out out_size size of serialized descriptor 276 */ 277 static void usb_create_serialized_hub_descriptor(rh_t *instance, 278 uint8_t ** out_result, 279 size_t * out_size) { 280 //base size 281 size_t size = 7; 282 //variable size according to port count 283 size_t var_size = instance->port_count / 8 + 284 ((instance->port_count % 8 > 0) ? 1 : 0); 285 size += 2 * var_size; 290 * @return error code 291 */ 292 static int create_serialized_hub_descriptor(rh_t *instance) { 293 size_t size = 7 + 294 ((instance->port_count +7 )/ 8) * 2; 295 size_t var_size = (instance->port_count +7 )/ 8; 286 296 uint8_t * result = (uint8_t*) malloc(size); 297 if(!result) return ENOMEM; 298 287 299 bzero(result, size); 288 300 //size … … 313 325 result[7 + var_size + i] = 255; 314 326 } 315 (*out_result) = result; 316 (*out_size) = size; 327 instance->hub_descriptor = result; 328 instance->descriptor_size = size; 329 return EOK; 317 330 } 318 331 /*----------------------------------------------------------------------------*/ … … 323 336 * be initialized only once per hub. 324 337 * @instance root hub instance 325 */ 326 static void rh_init_descriptors(rh_t *instance) { 338 * @return error code 339 */ 340 static int rh_init_descriptors(rh_t *instance) { 327 341 memcpy(&instance->descriptors.device, &ohci_rh_device_descriptor, 328 342 sizeof (ohci_rh_device_descriptor) … … 331 345 memcpy(&descriptor, &ohci_rh_conf_descriptor, 332 346 sizeof (ohci_rh_conf_descriptor)); 333 uint8_t * hub_descriptor; 334 size_t hub_desc_size;335 usb_create_serialized_hub_descriptor(instance, &hub_descriptor,336 &hub_desc_size);337 347 348 int opResult = create_serialized_hub_descriptor(instance); 349 if(opResult != EOK){ 350 return opResult; 351 } 338 352 descriptor.total_length = 339 353 sizeof (usb_standard_configuration_descriptor_t) + 340 354 sizeof (usb_standard_endpoint_descriptor_t) + 341 355 sizeof (usb_standard_interface_descriptor_t) + 342 hub_desc_size;356 instance->descriptor_size; 343 357 344 358 uint8_t * full_config_descriptor = 345 359 (uint8_t*) malloc(descriptor.total_length); 360 if(!full_config_descriptor){ 361 return ENOMEM; 362 } 346 363 memcpy(full_config_descriptor, &descriptor, sizeof (descriptor)); 347 364 memcpy(full_config_descriptor + sizeof (descriptor), … … 353 370 sizeof (ohci_rh_iface_descriptor) + 354 371 sizeof (ohci_rh_ep_descriptor), 355 hub_descriptor, hub_desc_size);356 372 instance->hub_descriptor, instance->descriptor_size); 373 357 374 instance->descriptors.configuration = full_config_descriptor; 358 375 instance->descriptors.configuration_size = descriptor.total_length; 376 return EOK; 359 377 } 360 378 /*----------------------------------------------------------------------------*/ … … 374 392 if (port < 1 || port > instance->port_count) 375 393 return EINVAL; 376 uint32_t * uint32_buffer = (uint32_t*) request-> transport_buffer;394 uint32_t * uint32_buffer = (uint32_t*) request->data_buffer; 377 395 request->transfered_size = 4; 378 396 uint32_buffer[0] = instance->registers->rh_port_status[port - 1]; … … 400 418 static int process_get_hub_status_request(rh_t *instance, 401 419 usb_transfer_batch_t * request) { 402 uint32_t * uint32_buffer = (uint32_t*) request-> transport_buffer;420 uint32_t * uint32_buffer = (uint32_t*) request->data_buffer; 403 421 request->transfered_size = 4; 404 422 //bits, 0,1,16,17 … … 447 465 * bit i indicates change on i`th port (i>0). For more info see 448 466 * Hub and Port status bitmap specification in USB specification 449 * (chapter 11.13.4) 450 * @param instance root hub instance 451 * @param@out buffer pointer to created interrupt mas 452 * @param@out buffer_size size of created interrupt mask 453 */ 454 static void create_interrupt_mask(rh_t *instance, void ** buffer, 455 size_t * buffer_size) { 456 int bit_count = instance->port_count + 1; 457 (*buffer_size) = (bit_count / 8) + ((bit_count % 8 == 0) ? 0 : 1); 458 459 (*buffer) = malloc(*buffer_size); 460 uint8_t * bitmap = (uint8_t*) (*buffer); 467 * (chapter 11.13.4). 468 * Uses instance`s interrupt buffer to store the interrupt information. 469 * @param instance root hub instance 470 */ 471 static void create_interrupt_mask_in_instance(rh_t * instance) { 472 uint8_t * bitmap = (uint8_t*) (instance->interrupt_buffer); 461 473 uint32_t mask = (1 << (USB_HUB_FEATURE_C_HUB_LOCAL_POWER + 16)) 462 474 | (1 << (USB_HUB_FEATURE_C_HUB_OVER_CURRENT + 16)); 463 bzero(bitmap, (*buffer_size));475 bzero(bitmap, instance->interrupt_mask_size); 464 476 if (instance->registers->rh_status & mask) { 465 477 bitmap[0] = 1; … … 492 504 const uint16_t setup_request_value = setup_request->value_high; 493 505 //(setup_request->value_low << 8); 494 bool del = false;495 506 switch (setup_request_value) { 496 507 case USB_DESCTYPE_HUB: 497 508 { 498 uint8_t * descriptor; 499 usb_create_serialized_hub_descriptor( 500 instance, &descriptor, &size); 501 result_descriptor = descriptor; 502 if (result_descriptor) del = true; 509 usb_log_debug("USB_DESCTYPE_HUB\n"); 510 result_descriptor = instance->hub_descriptor; 511 size = instance->descriptor_size; 503 512 break; 504 513 } … … 550 559 } 551 560 request->transfered_size = size; 552 memcpy(request->transport_buffer, result_descriptor, size); 553 if (del) 554 free(result_descriptor); 561 memcpy(request->data_buffer, result_descriptor, size); 555 562 return EOK; 556 563 } … … 571 578 if (request->buffer_size != 1) 572 579 return EINVAL; 573 request-> transport_buffer[0] = 1;580 request->data_buffer[0] = 1; 574 581 request->transfered_size = 1; 575 582 return EOK; … … 866 873 return opResult; 867 874 } 875 /*----------------------------------------------------------------------------*/ 876 877 /** 878 * process hanging interrupt request 879 * 880 * If an interrupt transfer has been received and there was no change, 881 * the driver stores the transfer information and waits for change to occcur. 882 * This routine is called when that happens and it finalizes the interrupt 883 * transfer. 884 * 885 * @param instance hub instance 886 * @param request batch request to be processed 887 * 888 * @return 889 */ 890 static int process_interrupt_mask_in_instance(rh_t *instance, usb_transfer_batch_t * request){ 891 memcpy(request->data_buffer, instance->interrupt_buffer, 892 instance->interrupt_mask_size); 893 request->transfered_size = instance->interrupt_mask_size; 894 instance->unfinished_interrupt_transfer = NULL; 895 usb_transfer_batch_finish_error(request, EOK); 896 return EOK; 897 } 898 899 /*----------------------------------------------------------------------------*/ 900 901 /** 902 * return whether the buffer is full of zeros 903 * 904 * Convenience function. 905 * @param buffer 906 * @param size 907 * @return 908 */ 909 static bool is_zeros(void * buffer, size_t size){ 910 if(!buffer) return true; 911 if(!size) return true; 912 size_t i; 913 for(i=0;i<size;++i){ 914 if(((char*)buffer)[i]) 915 return false; 916 } 917 return true; 918 } 868 919 869 920 /**
Note:
See TracChangeset
for help on using the changeset viewer.