]> git.proxmox.com Git - mirror_edk2.git/blob - EmbeddedPkg/Drivers/Isp1761UsbDxe/Isp1761UsbDxe.c
dfc3786297e22df66a470e523bddd40ebca03f4d
[mirror_edk2.git] / EmbeddedPkg / Drivers / Isp1761UsbDxe / Isp1761UsbDxe.c
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 }