1 /** @file 2 3 Copyright (c) 2013-2015, ARM Ltd. All rights reserved.<BR> 4 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include <Library/DebugLib.h> 16 #include <Library/UefiBootServicesTableLib.h> 17 #include <Library/UefiDriverEntryPoint.h> 18 #include <Library/IoLib.h> 19 #include <Library/MemoryAllocationLib.h> 20 21 #include <IndustryStandard/Usb.h> 22 23 #include <Protocol/UsbDevice.h> 24 25 #include "Isp1761UsbDxe.h" 26 27 /* 28 Driver for using the NXP ISP1761 as a USB Peripheral controller. 29 Doesn't use USB OTG - just sets it in Pure Peripheral mode. 30 31 The ISP1582 datasheet has a little more info on the Peripheral controller 32 registers than the ISP1761 datasheet 33 34 We don't do string descriptors. They're optional. 35 We currently assume the device has one configuration, one interface, one IN 36 endpoint, and one OUT endpoint (plus the default control endpoint). 37 38 In fact, this driver is the minimum required to implement fastboot. 39 */ 40 41 // TODO Make sure the controller isn't sending empty packets when it shouldn't 42 // (check behaviour in cases when Buffer Length isn't explcitly set) 43 44 // ISP1582 Datasheet: 45 // "Data transfers preceding the status stage must first be fully 46 // completed before the STATUS bit can be set." 47 // This variable stores whether some control data has been pended in the EP0TX 48 // Tx buffer, so that when an EP0TX interrupt is received we can set the STATUS 49 // bit to go to the Status stage of the control transfer. 50 STATIC BOOLEAN mControlTxPending = FALSE; 51 52 STATIC USB_DEVICE_DESCRIPTOR *mDeviceDescriptor; 53 54 // The config descriptor, interface descriptor, and endpoint descriptors in a 55 // buffer (in that order) 56 STATIC VOID *mDescriptors; 57 // Convenience pointers to those descriptors inside the buffer: 58 STATIC USB_INTERFACE_DESCRIPTOR *mInterfaceDescriptor; 59 STATIC USB_CONFIG_DESCRIPTOR *mConfigDescriptor; 60 STATIC USB_ENDPOINT_DESCRIPTOR *mEndpointDescriptors; 61 62 STATIC USB_DEVICE_RX_CALLBACK mDataReceivedCallback; 63 STATIC USB_DEVICE_TX_CALLBACK mDataSentCallback; 64 65 // The time between interrupt polls, in units of 100 nanoseconds 66 // 10 Microseconds 67 #define ISP1761_INTERRUPT_POLL_PERIOD 10000 68 69 STATIC 70 VOID 71 SelectEndpoint ( 72 IN UINT8 Endpoint 73 ) 74 { 75 // The DMA Endpoint Index must not point to the same as the 76 // Endpoint Index Register. 77 WRITE_REG32 (ISP1761_DMA_ENDPOINT_INDEX, ((Endpoint + 2) % ISP1761_NUM_ENDPOINTS)); 78 WRITE_REG32 (ISP1761_ENDPOINT_INDEX, Endpoint); 79 } 80 81 // Enable going to the Data stage of a control transfer 82 STATIC 83 VOID 84 DataStageEnable ( 85 IN UINT8 Endpoint 86 ) 87 { 88 SelectEndpoint (Endpoint); 89 WRITE_REG32 (ISP1761_CTRL_FUNCTION, ISP1761_CTRL_FUNCTION_DSEN); 90 } 91 92 // Go to the Status stage of a successful control transfer 93 STATIC 94 VOID 95 StatusAcknowledge ( 96 IN UINT8 Endpoint 97 ) 98 { 99 SelectEndpoint (Endpoint); 100 WRITE_REG32 (ISP1761_CTRL_FUNCTION, ISP1761_CTRL_FUNCTION_STATUS); 101 } 102 103 // Read the FIFO for the endpoint indexed by Endpoint, into the buffer pointed 104 // at by Buffer, whose size is *Size bytes. 105 // 106 // If *Size is less than the number of bytes in the FIFO, return EFI_BUFFER_TOO_SMALL 107 // 108 // Update *Size with the number of bytes of data in the FIFO. 109 STATIC 110 EFI_STATUS 111 ReadEndpointBuffer ( 112 IN UINT8 Endpoint, 113 IN OUT UINTN *Size, 114 IN OUT VOID *Buffer 115 ) 116 { 117 UINT16 NumBytesAvailable; 118 UINT32 Val32; 119 UINTN Index; 120 UINTN NumBytesRead; 121 122 SelectEndpoint (Endpoint); 123 124 NumBytesAvailable = READ_REG16 (ISP1761_BUFFER_LENGTH); 125 126 if (NumBytesAvailable > *Size) { 127 *Size = NumBytesAvailable; 128 return EFI_BUFFER_TOO_SMALL; 129 } 130 *Size = NumBytesAvailable; 131 132 /* -- NB! -- 133 The datasheet says the Data Port is 16 bits but it actually appears to 134 be 32 bits. 135 */ 136 137 // Read 32-bit chunks 138 for (Index = 0; Index < NumBytesAvailable / 4; Index++) { 139 ((UINT32 *) Buffer)[Index] = READ_REG32 (ISP1761_DATA_PORT); 140 } 141 142 // Read remaining bytes 143 144 // Round NumBytesAvailable down to nearest power of 4 145 NumBytesRead = NumBytesAvailable & (~0x3); 146 if (NumBytesRead != NumBytesAvailable) { 147 Val32 = READ_REG32 (ISP1761_DATA_PORT); 148 // Copy each required byte of 32-bit word into buffer 149 for (Index = 0; Index < NumBytesAvailable % 4; Index++) { 150 ((UINT8 *) Buffer)[NumBytesRead + Index] = Val32 >> (Index * 8); 151 } 152 } 153 return EFI_SUCCESS; 154 } 155 156 /* 157 Write an endpoint buffer. Parameters: 158 Endpoint Endpoint index (see Endpoint Index Register in datasheet) 159 MaxPacketSize The MaxPacketSize this endpoint is configured for 160 Size The size of the Buffer 161 Buffer The data 162 163 Assumes MaxPacketSize is a multiple of 4. 164 (It seems that all valid values for MaxPacketSize _are_ multiples of 4) 165 */ 166 STATIC 167 EFI_STATUS 168 WriteEndpointBuffer ( 169 IN UINT8 Endpoint, 170 IN UINTN MaxPacketSize, 171 IN UINTN Size, 172 IN CONST VOID *Buffer 173 ) 174 { 175 UINTN Index; 176 UINT32 *DwordBuffer; 177 178 DwordBuffer = (UINT32 *) Buffer; 179 SelectEndpoint (Endpoint); 180 181 /* -- NB! -- 182 The datasheet says the Data Port is 16 bits but it actually appears to 183 be 32 bits. 184 */ 185 186 // Write packets of size MaxPacketSize 187 while (Size > MaxPacketSize) { 188 for (Index = 0; Index < MaxPacketSize / 4; Index++) { 189 WRITE_REG32 (ISP1761_DATA_PORT, DwordBuffer[Index]); 190 } 191 Size -= MaxPacketSize; 192 DwordBuffer += (MaxPacketSize / sizeof (UINT32)); 193 } 194 195 // Write remaining data 196 197 if (Size > 0) { 198 WRITE_REG32 (ISP1761_BUFFER_LENGTH, Size); 199 200 while (Size > 4) { 201 WRITE_REG32 (ISP1761_DATA_PORT, DwordBuffer[0]); 202 Size -= 4; 203 DwordBuffer++; 204 } 205 206 if (Size > 0) { 207 WRITE_REG32 (ISP1761_DATA_PORT, DwordBuffer[0]); 208 } 209 } 210 211 return EFI_SUCCESS; 212 } 213 214 STATIC 215 EFI_STATUS 216 HandleGetDescriptor ( 217 IN USB_DEVICE_REQUEST *Request 218 ) 219 { 220 EFI_STATUS Status; 221 UINT8 DescriptorType; 222 UINTN ResponseSize; 223 VOID *ResponseData; 224 225 ResponseSize = 0; 226 ResponseData = NULL; 227 Status = EFI_SUCCESS; 228 229 // Pretty confused if bmRequestType is anything but this: 230 ASSERT (Request->RequestType == USB_DEV_GET_DESCRIPTOR_REQ_TYPE); 231 232 // Choose the response 233 DescriptorType = Request->Value >> 8; 234 switch (DescriptorType) { 235 case USB_DESC_TYPE_DEVICE: 236 DEBUG ((EFI_D_INFO, "USB: Got a request for device descriptor\n")); 237 ResponseSize = sizeof (USB_DEVICE_DESCRIPTOR); 238 ResponseData = mDeviceDescriptor; 239 break; 240 case USB_DESC_TYPE_CONFIG: 241 DEBUG ((EFI_D_INFO, "USB: Got a request for config descriptor\n")); 242 ResponseSize = mConfigDescriptor->TotalLength; 243 ResponseData = mDescriptors; 244 break; 245 case USB_DESC_TYPE_STRING: 246 DEBUG ((EFI_D_INFO, "USB: Got a request for String descriptor %d\n", Request->Value & 0xFF)); 247 break; 248 default: 249 DEBUG ((EFI_D_INFO, "USB: Didn't understand request for descriptor 0x%04x\n", Request->Value)); 250 Status = EFI_NOT_FOUND; 251 break; 252 } 253 254 // Send the response 255 if (ResponseData) { 256 ASSERT (ResponseSize != 0); 257 258 if (Request->Length < ResponseSize) { 259 // Truncate response 260 ResponseSize = Request->Length; 261 } else if (Request->Length > ResponseSize) { 262 DEBUG ((EFI_D_INFO, "USB: Info: ResponseSize < wLength\n")); 263 } 264 265 DataStageEnable (ISP1761_EP0TX); 266 Status = WriteEndpointBuffer ( 267 ISP1761_EP0TX, 268 MAX_PACKET_SIZE_CONTROL, 269 ResponseSize, 270 ResponseData 271 ); 272 if (!EFI_ERROR (Status)) { 273 // Setting this value should cause us to go to the Status stage on the 274 // next EP0TX interrupt 275 mControlTxPending = TRUE; 276 } 277 } 278 279 return EFI_SUCCESS; 280 } 281 282 STATIC 283 EFI_STATUS 284 HandleSetAddress ( 285 IN USB_DEVICE_REQUEST *Request 286 ) 287 { 288 // Pretty confused if bmRequestType is anything but this: 289 ASSERT (Request->RequestType == USB_DEV_SET_ADDRESS_REQ_TYPE); 290 // USB Spec: "The USB device does not change its device address until after 291 // the Status stage of this request is completed successfully." 292 // ISP1582 datasheet: "The new device address is activated when the 293 // device receives an acknowledgment from the host for the empty packet 294 // token". (StatusAcknowledge causes an empty packet to be sent). 295 // So, we write the Address register _before_ acking the SET_ADDRESS. 296 DEBUG ((EFI_D_INFO, "USB: Setting address to %d\n", Request->Value)); 297 WRITE_REG32 (ISP1761_ADDRESS, Request->Value | ISP1761_ADDRESS_DEVEN); 298 StatusAcknowledge (ISP1761_EP0TX); 299 300 return EFI_SUCCESS; 301 } 302 303 // Move the device to the Configured state. 304 // (This code only supports one configuration for a device, so the configuration 305 // index is ignored) 306 STATIC 307 EFI_STATUS 308 HandleSetConfiguration ( 309 IN USB_DEVICE_REQUEST *Request 310 ) 311 { 312 USB_ENDPOINT_DESCRIPTOR *EPDesc; 313 UINTN Index; 314 UINT8 EndpointIndex; 315 316 ASSERT (Request->RequestType == USB_DEV_SET_CONFIGURATION_REQ_TYPE); 317 DEBUG ((EFI_D_INFO, "USB: Setting configuration.\n")); 318 319 // Configure endpoints 320 for (Index = 0; Index < mInterfaceDescriptor->NumEndpoints; Index++) { 321 EPDesc = &mEndpointDescriptors[Index]; 322 323 // To simplify for now, assume endpoints aren't "sparse", and are in order. 324 ASSERT ((EPDesc->EndpointAddress & 0xF) == ((Index / 2) + 1)); 325 326 // Convert from USB endpoint index to ISP1761 endpoint Index 327 // USB: Endpoint number is bits [3:0], IN/OUT is bit [7] 328 // ISP1761: Endpoint number is bits [4:1], IN/OUT is bit [0] 329 EndpointIndex = ((EPDesc->EndpointAddress & 0xF) << 1) | 330 ((EPDesc->EndpointAddress & BIT7) >> 7); 331 SelectEndpoint (EndpointIndex); 332 // Set endpoint type (Bulk/Isochronous/Interrupt) 333 WRITE_REG32 (ISP1761_ENDPOINT_MAX_PACKET_SIZE, EPDesc->MaxPacketSize); 334 // Hardware foible (bug?): Although the datasheet seems to suggest it should 335 // automatically be set to MaxPacketSize, the Buffer Length register appears 336 // to be reset to 0, which causes an empty packet to be sent in response to 337 // the first IN token of the session. The NOEMPKT field of the Endpoint Type 338 // register sounds like it might fix this problem, but it doesn't 339 // (it's "applicable only in the DMA mode"). 340 WRITE_REG32 (ISP1761_BUFFER_LENGTH, EPDesc->MaxPacketSize); 341 WRITE_REG32 (ISP1761_ENDPOINT_TYPE, (EPDesc->Attributes & 0x3) | 342 ISP1761_ENDPOINT_TYPE_ENABLE); 343 } 344 345 StatusAcknowledge (ISP1761_EP0TX); 346 return EFI_SUCCESS; 347 } 348 349 STATIC 350 EFI_STATUS 351 HandleDeviceRequest ( 352 IN USB_DEVICE_REQUEST *Request 353 ) 354 { 355 EFI_STATUS Status; 356 357 Status = EFI_SUCCESS; 358 359 switch (Request->Request) { 360 case USB_DEV_GET_DESCRIPTOR: 361 Status = HandleGetDescriptor (Request); 362 break; 363 case USB_DEV_SET_ADDRESS: 364 Status = HandleSetAddress (Request); 365 break; 366 case USB_DEV_SET_CONFIGURATION: 367 Status = HandleSetConfiguration (Request); 368 break; 369 default: 370 DEBUG ((EFI_D_ERROR, 371 "Didn't understand RequestType 0x%x Request 0x%x\n", 372 Request->RequestType, Request->Request)); 373 Status = EFI_INVALID_PARAMETER; 374 break; 375 } 376 377 return Status; 378 } 379 380 // Instead of actually registering interrupt handlers, we poll the controller's 381 // interrupt source register in this function. 382 STATIC 383 VOID 384 CheckInterrupts ( 385 IN EFI_EVENT Event, 386 IN VOID *Context 387 ) 388 { 389 UINT32 DcInterrupts; 390 UINTN NumBytes; 391 UINTN MoreBytes; 392 UINT8 Packet[512]; 393 VOID *DataPacket; 394 UINT32 HandledInterrupts; 395 UINT32 UnhandledInterrupts; 396 EFI_STATUS Status; 397 398 // Set bits in HandledInterrupts to mark the interrupt source handled. 399 HandledInterrupts = 0; 400 401 WRITE_REG32 (ISP1761_DEVICE_UNLOCK, ISP1761_DEVICE_UNLOCK_MAGIC); 402 403 DcInterrupts = READ_REG32 (ISP1761_DC_INTERRUPT); 404 if (DcInterrupts & ISP1761_DC_INTERRUPT_SUSP) { 405 DEBUG ((EFI_D_INFO, "USB: Suspend\n")); 406 HandledInterrupts |= ISP1761_DC_INTERRUPT_SUSP; 407 } 408 if (DcInterrupts & ISP1761_DC_INTERRUPT_RESUME) { 409 DEBUG ((EFI_D_INFO, "USB: Resume\n")); 410 HandledInterrupts |= ISP1761_DC_INTERRUPT_RESUME; 411 } 412 if (DcInterrupts & ISP1761_DC_INTERRUPT_EP0SETUP) { 413 NumBytes = 512; 414 ReadEndpointBuffer (0x20, &NumBytes, &Packet); 415 ASSERT (NumBytes == 8); 416 HandleDeviceRequest ((USB_DEVICE_REQUEST *) Packet); 417 HandledInterrupts |= ISP1761_DC_INTERRUPT_EP0SETUP; 418 } 419 if (DcInterrupts & ISP1761_DC_INTERRUPT_EP0RX) { 420 HandledInterrupts |= ISP1761_DC_INTERRUPT_EP0RX; 421 } 422 if (DcInterrupts & ISP1761_DC_INTERRUPT_EP0TX) { 423 if (mControlTxPending) { 424 // We previously put some data in the Control Endpoint's IN (Tx) FIFO. 425 // We assume that that data has now been sent in response to the IN token 426 // that triggered this interrupt. We can therefore go to the Status stage 427 // of the control transfer. 428 StatusAcknowledge (ISP1761_EP0TX); 429 mControlTxPending = FALSE; 430 } 431 HandledInterrupts |= ISP1761_DC_INTERRUPT_EP0TX; 432 } 433 if (DcInterrupts & ISP1761_DC_INTERRUPT_EP1RX) { 434 NumBytes = 512; 435 DataPacket = AllocatePool (NumBytes); 436 Status = ReadEndpointBuffer (ISP1761_EP1RX, &NumBytes, DataPacket); 437 if (EFI_ERROR (Status) || NumBytes == 0) { 438 if (EFI_ERROR (Status)) { 439 DEBUG ((EFI_D_ERROR, "Couldn't read EP1RX data: %r\n", Status)); 440 } 441 FreePool (DataPacket); 442 } else { 443 // Signal this event again so we poll again ASAP 444 gBS->SignalEvent (Event); 445 mDataReceivedCallback (NumBytes, DataPacket); 446 } 447 HandledInterrupts |= ISP1761_DC_INTERRUPT_EP1RX; 448 } 449 if (DcInterrupts & ISP1761_DC_INTERRUPT_EP1TX) { 450 mDataSentCallback (1); 451 HandledInterrupts |= ISP1761_DC_INTERRUPT_EP1TX; 452 } 453 if (DcInterrupts & (ISP1761_DC_INTERRUPT_SOF | ISP1761_DC_INTERRUPT_PSOF)) { 454 // Don't care about SOFs or pseudo-SOFs 455 HandledInterrupts |= (ISP1761_DC_INTERRUPT_SOF | ISP1761_DC_INTERRUPT_PSOF); 456 } 457 if (ISP1761_DC_INTERRUPT_BRESET) { 458 HandledInterrupts |= ISP1761_DC_INTERRUPT_BRESET; 459 } 460 if (ISP1761_DC_INTERRUPT_HS_STAT) { 461 HandledInterrupts |= ISP1761_DC_INTERRUPT_HS_STAT; 462 } 463 if (ISP1761_DC_INTERRUPT_VBUS) { 464 HandledInterrupts |= ISP1761_DC_INTERRUPT_VBUS; 465 } 466 467 UnhandledInterrupts = DcInterrupts & (~HandledInterrupts) & ISP1761_DC_INTERRUPT_MASK; 468 if (UnhandledInterrupts) { 469 DEBUG ((EFI_D_ERROR, "USB: Unhandled DC Interrupts: 0x%08x\n", 470 UnhandledInterrupts)); 471 } 472 473 // Check if we received any more data while we were handling the interrupt. 474 SelectEndpoint (ISP1761_EP1RX); 475 MoreBytes = READ_REG16 (ISP1761_BUFFER_LENGTH); 476 if (MoreBytes) { 477 HandledInterrupts &= ~ISP1761_DC_INTERRUPT_EP1RX; 478 } 479 480 WRITE_REG32 (ISP1761_DC_INTERRUPT, HandledInterrupts); 481 } 482 483 EFI_STATUS 484 Isp1761PeriphSend ( 485 IN UINT8 EndpointIndex, 486 IN UINTN Size, 487 IN CONST VOID *Buffer 488 ) 489 { 490 return WriteEndpointBuffer ( 491 (EndpointIndex << 1) | 0x1, //Convert to ISP1761 endpoint index, Tx 492 MAX_PACKET_SIZE_BULK, 493 Size, 494 Buffer 495 ); 496 } 497 498 EFI_STATUS 499 EFIAPI 500 Isp1761PeriphStart ( 501 IN USB_DEVICE_DESCRIPTOR *DeviceDescriptor, 502 IN VOID **Descriptors, 503 IN USB_DEVICE_RX_CALLBACK RxCallback, 504 IN USB_DEVICE_TX_CALLBACK TxCallback 505 ) 506 { 507 UINT16 OtgStatus; 508 UINT8 *Ptr; 509 EFI_STATUS Status; 510 EFI_EVENT TimerEvent; 511 512 ASSERT (DeviceDescriptor != NULL); 513 ASSERT (Descriptors[0] != NULL); 514 ASSERT (RxCallback != NULL); 515 ASSERT (TxCallback != NULL); 516 517 WRITE_REG32 (ISP1761_DEVICE_UNLOCK, ISP1761_DEVICE_UNLOCK_MAGIC); 518 519 WRITE_REG32 (ISP1761_SW_RESET_REG, ISP1761_SW_RESET_ALL); 520 while (READ_REG32 (ISP1761_SW_RESET_REG) & ISP1761_SW_RESET_ALL) { 521 //busy wait 522 } 523 WRITE_REG32 (ISP1761_MODE, ISP1761_MODE_SFRESET); 524 while (READ_REG32 (ISP1761_MODE) & ISP1761_MODE_SFRESET) { 525 //busy wait 526 } 527 DEBUG ((EFI_D_INFO, "USB: Software reset done\n")); 528 529 WRITE_REG32 (ISP1761_DC_INTERRUPT_ENABLE, 0x03FFFFFF); 530 WRITE_REG32 (ISP1761_OTG_INTERRUPT_ENABLE_RISE, 0x07FF); 531 532 WRITE_REG8 (ISP1761_ADDRESS, ISP1761_ADDRESS_DEVEN); 533 WRITE_REG8 (ISP1761_MODE, ISP1761_MODE_WKUPCS | ISP1761_MODE_CLKAON); 534 535 // Use port 1 as peripheral controller (magic - disagrees with datasheet) 536 WRITE_REG32 (ISP1761_OTG_CTRL_SET, 0xffff0000); 537 WRITE_REG32 (ISP1761_OTG_CTRL_SET, 0x000014d1); 538 539 OtgStatus = READ_REG16 (ISP1761_OTG_STATUS); 540 if ((OtgStatus & ISP1761_OTG_STATUS_B_SESS_END) != 0) { 541 DEBUG ((EFI_D_ERROR, "USB: Vbus not powered.\n")); 542 } 543 if ((OtgStatus & ISP1761_OTG_STATUS_A_B_SESS_VLD) == 0) { 544 DEBUG ((EFI_D_ERROR, "USB: Session not valid.\n")); 545 } 546 547 // Configure Control endpoints 548 SelectEndpoint (0x20); 549 WRITE_REG32 (ISP1761_ENDPOINT_MAX_PACKET_SIZE, MAX_PACKET_SIZE_CONTROL); 550 WRITE_REG32 (ISP1761_ENDPOINT_TYPE, ISP1761_ENDPOINT_TYPE_ENABLE); 551 SelectEndpoint (0x0); 552 WRITE_REG32 (ISP1761_ENDPOINT_MAX_PACKET_SIZE, MAX_PACKET_SIZE_CONTROL); 553 WRITE_REG32 (ISP1761_ENDPOINT_TYPE, ISP1761_ENDPOINT_TYPE_ENABLE); 554 SelectEndpoint (0x1); 555 WRITE_REG32 (ISP1761_ENDPOINT_MAX_PACKET_SIZE, MAX_PACKET_SIZE_CONTROL); 556 WRITE_REG32 (ISP1761_ENDPOINT_TYPE, ISP1761_ENDPOINT_TYPE_ENABLE); 557 558 // Interrupt on all ACK and NAK 559 WRITE_REG32 (ISP1761_INTERRUPT_CONFIG, ISP1761_INTERRUPT_CONFIG_ACK_ONLY); 560 561 mDeviceDescriptor = DeviceDescriptor; 562 mDescriptors = Descriptors[0]; 563 564 // Right now we just support one configuration 565 ASSERT (mDeviceDescriptor->NumConfigurations == 1); 566 // ... and one interface 567 mConfigDescriptor = (USB_CONFIG_DESCRIPTOR *)mDescriptors; 568 ASSERT (mConfigDescriptor->NumInterfaces == 1); 569 570 Ptr = ((UINT8 *) mDescriptors) + sizeof (USB_CONFIG_DESCRIPTOR); 571 mInterfaceDescriptor = (USB_INTERFACE_DESCRIPTOR *) Ptr; 572 Ptr += sizeof (USB_INTERFACE_DESCRIPTOR); 573 574 mEndpointDescriptors = (USB_ENDPOINT_DESCRIPTOR *) Ptr; 575 576 mDataReceivedCallback = RxCallback; 577 mDataSentCallback = TxCallback; 578 579 // Register a timer event so CheckInterupts gets called periodically 580 Status = gBS->CreateEvent ( 581 EVT_TIMER | EVT_NOTIFY_SIGNAL, 582 TPL_CALLBACK, 583 CheckInterrupts, 584 NULL, 585 &TimerEvent 586 ); 587 ASSERT_EFI_ERROR (Status); 588 if (EFI_ERROR (Status)) { 589 return Status; 590 } 591 592 Status = gBS->SetTimer ( 593 TimerEvent, 594 TimerPeriodic, 595 ISP1761_INTERRUPT_POLL_PERIOD 596 ); 597 ASSERT_EFI_ERROR (Status); 598 599 return Status; 600 } 601 602 USB_DEVICE_PROTOCOL mUsbDevice = { 603 Isp1761PeriphStart, 604 Isp1761PeriphSend 605 }; 606 607 608 EFI_STATUS 609 EFIAPI 610 Isp1761PeriphEntryPoint ( 611 IN EFI_HANDLE ImageHandle, 612 IN EFI_SYSTEM_TABLE *SystemTable 613 ) 614 { 615 UINT32 DeviceId; 616 EFI_HANDLE Handle; 617 618 DeviceId = READ_REG32 (ISP1761_DEVICE_ID); 619 620 if (DeviceId != ISP1761_DEVICE_ID_VAL) { 621 DEBUG ((EFI_D_ERROR, 622 "ERROR: Read incorrect device ID for ISP1761: 0x%08x, expected 0x%08x\n", 623 DeviceId , ISP1761_DEVICE_ID_VAL 624 )); 625 return EFI_DEVICE_ERROR; 626 } 627 628 Handle = NULL; 629 return gBS->InstallProtocolInterface ( 630 &Handle, 631 &gUsbDeviceProtocolGuid, 632 EFI_NATIVE_INTERFACE, 633 &mUsbDevice 634 ); 635 } 636