1 //
2 // Copyright (c) 2010-2024 Antmicro
3 //
4 // This file is licensed under the MIT License.
5 // Full license text is available in 'licenses/MIT.txt'.
6 //
7 
8 using System;
9 using System.Linq;
10 using System.Collections.Generic;
11 
12 using Antmicro.Migrant;
13 using Antmicro.Renode.Core;
14 using Antmicro.Renode.Core.USB;
15 using Antmicro.Renode.Core.Structure.Registers;
16 using Antmicro.Renode.Logging;
17 using Antmicro.Renode.Peripherals.Bus;
18 using Antmicro.Renode.Peripherals.USB;
19 using Antmicro.Renode.Peripherals.Miscellaneous;
20 using Antmicro.Renode.Utilities;
21 
22 namespace Antmicro.Renode.Peripherals.USB
23 {
24     public class NRF_USBD : IUSBDevice, IDoubleWordPeripheral, IProvidesRegisterCollection<DoubleWordRegisterCollection>, IKnownSize, INRFEventProvider
25     {
NRF_USBD(IMachine machine, short maximumPacketSize = 64)26         public NRF_USBD(IMachine machine, short maximumPacketSize = 64)
27         {
28             this.machine = machine;
29             USBCore = new USBDeviceCore(this, customSetupPacketHandler: HandleSetupPacket);
30             registers = new DoubleWordRegisterCollection(this);
31             IRQ = new GPIO();
32             interruptManager = new InterruptManager<Events>(this, IRQ, "UsbIrq");
33             events = new IFlagRegisterField[(int)Events.EpData + 1];
34             epInDataStatus = new bool[EndpointCount];
35             epInStatus = new bool[EndpointCount];
36             this.maximumPacketSize = maximumPacketSize;
37             InitiateUSBCore();
38             DefineRegisters();
39         }
40 
Reset()41         public void Reset()
42         {
43             interruptManager.Reset();
44             registers.Reset();
45         }
46 
47         public USBDeviceCore USBCore { get; }
48 
ReadDoubleWord(long offset)49         public uint ReadDoubleWord(long offset)
50         {
51             return registers.Read(offset);
52         }
53 
WriteDoubleWord(long offset, uint value)54         public void WriteDoubleWord(long offset, uint value)
55         {
56             registers.Write(offset, value);
57         }
58 
59         [IrqProvider]
60         public GPIO IRQ { get; }
61         public long Size => 0x1000;
62 
63         public event Action<uint> EventTriggered;
64 
HandleSetupPacket(SetupPacket packet, byte[] arg2, Action<byte[]> action)65         private void HandleSetupPacket(SetupPacket packet, byte[] arg2, Action<byte[]> action)
66         {
67             // Note: this method handled some setup packets in the model instead of relying them to the simulated software
68             // This is a simplification that needs to be resolved in the future
69             this.Log(LogLevel.Noisy, "Received SetupPacket. Request: {0}", packet.Request);
70             setupPacket = packet;
71             SetEvent(Events.Ep0Setup);
72             setupPacketResultCallback = action;
73 
74             switch(packet.Request)
75             {
76                 case (byte)StandardRequest.SetAddress:
77                     USBCore.Address = (byte)setupPacket.Value;
78                     setupPacketResultCallback(Array.Empty<byte>());
79                     break;
80                 case (byte)StandardRequest.SetConfiguration:
81                     setupPacketResultCallback(Array.Empty<byte>());
82                     break;
83             }
84         }
85 
GetData(ushort epNumber)86         private void GetData(ushort epNumber)
87         {
88             this.Log(LogLevel.Noisy, "Reading data from EP number: {0}", epNumber);
89             // Every pointer to endpoint data and endpoint count is n * 0x14 away from endpoint's 0, where n is number of endpoint.
90             // E.g: pointer to second endpoint data would be: (2 * 0x14 + address of endpoint 0)
91             uint endpointIn = registers.Read((0x14 * epNumber) + (long)Registers.Endpoint0In);
92             uint endpointInCount = registers.Read((0x14 * epNumber) + (long)Registers.Endpoint0InCount);
93             var usbPacket = machine.GetSystemBus(this).ReadBytes(endpointIn, (int)endpointInCount);
94 
95             if(epNumber == 0)
96             {
97                 setupPacketResultCallback(usbPacket);
98                 endpoint0InCount.Value = endpointInCount;
99             }
100             else if(usbPacket.Length != 0)
101             {
102                 deviceToHostEndpoint.HandlePacket(usbPacket);
103             }
104             DataAcknowledged(epNumber);
105         }
106 
DataAcknowledged(ushort epNumber)107         private void DataAcknowledged(ushort epNumber)
108         {
109             epInDataStatus[epNumber] = true;
110 
111             SetEvent(Events.Started);
112             SetEvent(Events.EndEpIn0 + epNumber);
113             SetEvent(Events.EpData);
114 
115             // Special event for control endpoint
116             if(epNumber == 0)
117             {
118                 SetEvent(Events.Ep0DataDone);
119             }
120         }
121 
122         private void SetEvent(Events @event)
123         {
124             interruptManager.SetInterrupt(@event);
125             events[(int)@event].Value = true;
126             // Events registers start at 0x100, they are apart of each other by 4 bytes.
127             EventTriggered?.Invoke((uint)@event * 4 + 0x100);
128         }
129 
DefineTask(Registers register, Action<ushort> callback, ushort epNumber, string name)130         private void DefineTask(Registers register, Action<ushort> callback, ushort epNumber, string name)
131         {
132             register.Define(this, name: name)
133                 .WithFlag(0, FieldMode.Write, writeCallback: (_, value) => { if(value) callback(epNumber); })
134                 .WithReservedBits(1, 31);
135         }
136 
DefineEvent(Registers register, Events @event, string name)137         private void DefineEvent(Registers register, Events @event, string name)
138         {
139             register.Define(this, name: name)
140                 .WithFlag(0, out events[(int)@event], writeCallback: (_, value) =>
141                 {
142                     if(!value)
143                     {
144                         interruptManager.SetInterrupt(@event, false);
145                     }
146                 })
147                 .WithReservedBits(1, 31);
148         }
149 
DefineRegisters()150         private void DefineRegisters()
151         {
152             DefineTask(Registers.TasksStartEpIn0, GetData, 0, "TASKS_STARTEPIN0");
153             DefineTask(Registers.TasksStartEpIn1, GetData, 1, "TASKS_STARTEPIN1");
154             DefineTask(Registers.TasksStartEpIn2, GetData, 2, "TASKS_STARTEPIN2");
155             DefineTask(Registers.TasksStartEpIn3, GetData, 3, "TASKS_STARTEPIN3");
156             DefineTask(Registers.TasksStartEpIn4, GetData, 4, "TASKS_STARTEPIN4");
157             DefineTask(Registers.TasksStartEpIn5, GetData, 5, "TASKS_STARTEPIN5");
158             DefineTask(Registers.TasksStartEpIn6, GetData, 6, "TASKS_STARTEPIN6");
159             DefineTask(Registers.TasksStartEpIn7, GetData, 7, "TASKS_STARTEPIN7");
160             DefineTask(Registers.TasksEp0Status, (_) => {}, 0, "TASKS_EP0STATUS");
161             DefineEvent(Registers.EventsUsbReset, Events.UsbReset, "EVENTS_USBRESET");
162             DefineEvent(Registers.EventsEp0Setup, Events.Ep0Setup, "EVENTS_EP0SETUP");
163             DefineEvent(Registers.EventsStarted, Events.Started, "EVENTS_STARTED");
164             DefineEvent(Registers.EventsEndEpIn0, Events.EndEpIn0, "EVENTS_ENDEPIN0");
165             DefineEvent(Registers.EventsEndEpIn1, Events.EndEpIn1, "EVENTS_ENDEPIN1");
166             DefineEvent(Registers.EventsEndEpIn2, Events.EndEpIn2, "EVENTS_ENDEPIN2");
167             DefineEvent(Registers.EventsEndEpIn3, Events.EndEpIn3, "EVENTS_ENDEPIN3");
168             DefineEvent(Registers.EventsEndEpIn4, Events.EndEpIn4, "EVENTS_ENDEPIN4");
169             DefineEvent(Registers.EventsEndEpIn5, Events.EndEpIn5, "EVENTS_ENDEPIN5");
170             DefineEvent(Registers.EventsEndEpIn6, Events.EndEpIn6, "EVENTS_ENDEPIN6");
171             DefineEvent(Registers.EventsEndEpIn7, Events.EndEpIn7, "EVENTS_ENDEPIN7");
172             DefineEvent(Registers.EventsEp0DataDone, Events.Ep0DataDone, "EVENTS_EP0DATADONE");
173             DefineEvent(Registers.EventsEpData, Events.EpData, "EVENTS_EPDATA");
174 
175             registers.AddRegister((long)Registers.InterruptEnable,
176                 interruptManager.GetInterruptEnableSetRegister<DoubleWordRegister>());
177 
178             Registers.EventCause.Define(this)
179                 .WithTaggedFlag("EVENT_ISOOUTCRC", 0)
180                 .WithTaggedFlag("EVENT_SUSPEND", 8)
181                 .WithTaggedFlag("EVENT_RESUME", 9)
182                 .WithTaggedFlag("EVENT_USBWUALLOWED", 10)
183                 .WithFlag(11, name: "EVENT_READY")
184                 .WithReservedBits(12, 20);
185 
186             Registers.EndpointStatus.Define(this)
187                 .WithFlag(0, writeCallback: (_, val) => {epInStatus[0] = val;}, valueProviderCallback: _ => epInStatus[0], name: "EPIN1")
188                 .WithFlag(1, writeCallback: (_, val) => {epInStatus[1] = val;}, valueProviderCallback: _ => epInStatus[1], name: "EPIN1")
189                 .WithFlag(2, writeCallback: (_, val) => {epInStatus[2] = val;}, valueProviderCallback: _ => epInStatus[2], name: "EPIN2")
190                 .WithFlag(3, writeCallback: (_, val) => {epInStatus[3] = val;}, valueProviderCallback: _ => epInStatus[3], name: "EPIN3")
191                 .WithFlag(4, writeCallback: (_, val) => {epInStatus[4] = val;}, valueProviderCallback: _ => epInStatus[4], name: "EPIN4")
192                 .WithFlag(5, writeCallback: (_, val) => {epInStatus[5] = val;}, valueProviderCallback: _ => epInStatus[5], name: "EPIN5")
193                 .WithFlag(6, writeCallback: (_, val) => {epInStatus[6] = val;}, valueProviderCallback: _ => epInStatus[6], name: "EPIN6")
194                 .WithFlag(7, writeCallback: (_, val) => {epInStatus[7] = val;}, valueProviderCallback: _ => epInStatus[7], name: "EPIN7")
195                 .WithReservedBits(8, 8)
196                 .WithTaggedFlag("EPOUT0", 16)
197                 .WithTaggedFlag("EPOUT1", 17)
198                 .WithTaggedFlag("EPOUT2", 18)
199                 .WithTaggedFlag("EPOUT3", 19)
200                 .WithTaggedFlag("EPOUT4", 20)
201                 .WithTaggedFlag("EPOUT5", 21)
202                 .WithTaggedFlag("EPOUT6", 22)
203                 .WithTaggedFlag("EPOUT7", 23)
204                 .WithTaggedFlag("EPOUT8", 24)
205                 .WithReservedBits(25, 7);
206 
207             Registers.EndpointDataStatus.Define(this)
208                 .WithReservedBits(0, 1) // Ep0 has no data status
209                 .WithFlag(1, writeCallback: (_, val) => {epInDataStatus[1] = val;}, valueProviderCallback: _ => epInDataStatus[1], name: "EPIN1")
210                 .WithFlag(2, writeCallback: (_, val) => {epInDataStatus[2] = val;}, valueProviderCallback: _ => epInDataStatus[2], name: "EPIN2")
211                 .WithFlag(3, writeCallback: (_, val) => {epInDataStatus[3] = val;}, valueProviderCallback: _ => epInDataStatus[3], name: "EPIN3")
212                 .WithFlag(4, writeCallback: (_, val) => {epInDataStatus[4] = val;}, valueProviderCallback: _ => epInDataStatus[4], name: "EPIN4")
213                 .WithFlag(5, writeCallback: (_, val) => {epInDataStatus[5] = val;}, valueProviderCallback: _ => epInDataStatus[5], name: "EPIN5")
214                 .WithFlag(6, writeCallback: (_, val) => {epInDataStatus[6] = val;}, valueProviderCallback: _ => epInDataStatus[6], name: "EPIN6")
215                 .WithFlag(7, writeCallback: (_, val) => {epInDataStatus[7] = val;}, valueProviderCallback: _ => epInDataStatus[7], name: "EPIN7")
216                 .WithReservedBits(8, 9)
217                 .WithTaggedFlag("EPOUT1", 17)
218                 .WithTaggedFlag("EPOUT2", 18)
219                 .WithTaggedFlag("EPOUT3", 19)
220                 .WithTaggedFlag("EPOUT4", 20)
221                 .WithTaggedFlag("EPOUT5", 21)
222                 .WithTaggedFlag("EPOUT6", 22)
223                 .WithTaggedFlag("EPOUT7", 23)
224                 .WithReservedBits(24, 8);
225 
226             Registers.UsbAddress.Define(this)
227                 .WithValueField(0, 7, out usbAddress, FieldMode.Read)
228                 .WithReservedBits(7, 24);
229 
230             Registers.bmRequestType.Define(this)
231                 .WithTag("RECIPIENT", 0, 5)
232                 .WithValueField(5, 2, FieldMode.Read, valueProviderCallback: _ => 0, name: "TYPE")
233                 .WithValueField(7, 1, FieldMode.Read, name: "DIRECTION",
234                     valueProviderCallback: _ => (ulong)setupPacket.Direction)
235                 .WithReservedBits(8, 24);
236 
237             Registers.bRequest.Define(this)
238                 .WithValueField(0, 8, FieldMode.Read, valueProviderCallback: _ => setupPacket.Request)
239                 .WithReservedBits(8, 24);
240 
241             Registers.wValueLow.Define(this)
242                 .WithValueField(0, 8, FieldMode.Read, valueProviderCallback: _ => (byte)(setupPacket.Value & 0xFF))
243                 .WithReservedBits(8, 24);
244 
245             Registers.wValueHigh.Define(this)
246                 .WithValueField(0, 8, FieldMode.Read, valueProviderCallback: _ => (byte)(setupPacket.Value >> 8 & 0xFF))
247                 .WithReservedBits(8, 24);
248 
249             Registers.wIndexLow.Define(this)
250                 .WithValueField(0, 8, FieldMode.Read, valueProviderCallback: _ => setupPacket.Index)
251                 .WithReservedBits(8, 24);
252 
253             Registers.wLengthLow.Define(this)
254                 .WithValueField(0, 8, FieldMode.Read, valueProviderCallback: _ => setupPacket.Count)
255                 .WithReservedBits(8, 24);
256 
257             Registers.Enable.Define(this)
258                 .WithFlag(0, out usbEnable, name: "ENABLE")
259                 .WithReservedBits(1, 31);
260 
261             Registers.UsbPullup.Define(this)
262                 .WithFlag(0, out usbPullup, name: "CONNECT")
263                 .WithReservedBits(1, 31);
264 
265             Registers.DataToggle.Define(this)
266                 .WithValueField(0, 3, valueField: out dataToggleEndpoint, name: "EP")
267                 .WithFlag(7, out dataToggleInputOutput, name: "IO")
268                 .WithValueField(8, 2, valueField: out dataToggleValue, name: "VALUE")
269                 .WithReservedBits(10, 22)
270                 .WithWriteCallback((_, __) => HandleToggle());
271 
272             Registers.EndpointInEnable.Define(this)
273                 .WithFlag(0, out ep0InEnabled, name: "IN0")
274                 .WithTaggedFlag("IN1", 1)
275                 .WithTaggedFlag("IN2", 2)
276                 .WithTaggedFlag("IN3", 3)
277                 .WithTaggedFlag("IN4", 4)
278                 .WithTaggedFlag("IN5", 5)
279                 .WithTaggedFlag("IN6", 6)
280                 .WithTaggedFlag("IN7", 7)
281                 .WithTaggedFlag("ISOIN", 8)
282                 .WithReservedBits(9, 23);
283 
284             Registers.EndpointOutEnable.Define(this)
285                 .WithFlag(0, out ep0OutEnabled, name: "OUT0")
286                 .WithTaggedFlag("OUT1", 1)
287                 .WithTaggedFlag("OUT2", 2)
288                 .WithTaggedFlag("OUT3", 3)
289                 .WithTaggedFlag("OUT4", 4)
290                 .WithTaggedFlag("OUT5", 5)
291                 .WithTaggedFlag("OUT6", 6)
292                 .WithTaggedFlag("OUT7", 7)
293                 .WithTaggedFlag("ISOOUT", 8)
294                 .WithReservedBits(9, 23);
295 
296             Registers.EndpointStall.Define(this)
297                 .WithValueField(0, 3, out epstallEndpoint, name: "EP")
298                 .WithReservedBits(3, 4)
299                 .WithFlag(7, out epstallIO, name: "IO")
300                 .WithFlag(8, out epstallStall, name: "STALL")
301                 .WithReservedBits(9, 23)
302                 .WithWriteCallback((_, __) => HandleStalling());
303 
304             Registers.IsoInConfig.Define(this) // This is last thing happening in nRF5340, after this the enumeration should start
305                 .WithTaggedFlag("RESPONSE", 0)
306                 .WithReservedBits(1, 31);
307 
308 
309             Registers.Endpoint0In.Define(this)
310                 .WithValueField(0, 32, name: "EPIN0", valueField: out endpoint0In);
311             Registers.Endpoint0InCount.Define(this)
312                 .WithValueField(0, 8, name: "EPIN0_MAXCNT", valueField: out endpoint0InCount)
313                 .WithReservedBits(8, 24);
314 
315             Registers.Endpoint1In.Define(this)
316                 .WithValueField(0, 32, name: "EPIN1");
317             Registers.Endpoint1InCount.Define(this)
318                 .WithValueField(0, 8, name: "EPIN1_MAXCNT")
319                 .WithReservedBits(8, 24);
320 
321             Registers.Endpoint2In.Define(this)
322                 .WithValueField(0, 32, name: "EPIN2");
323             Registers.Endpoint2InCount.Define(this)
324                 .WithValueField(0, 8, name: "EPIN2_MAXCNT")
325                 .WithReservedBits(8, 24);
326 
327             Registers.Endpoint3In.Define(this)
328                 .WithValueField(0, 32, name: "EPIN3");
329             Registers.Endpoint3InCount.Define(this)
330                 .WithValueField(0, 8, name: "EPIN3_MAXCNT")
331                 .WithReservedBits(8, 24);
332 
333             Registers.Endpoint4In.Define(this)
334                 .WithValueField(0, 32, name: "EPIN4");
335             Registers.Endpoint4InCount.Define(this)
336                 .WithValueField(0, 8, name: "EPIN4_MAXCNT")
337                 .WithReservedBits(8, 24);
338 
339             Registers.Endpoint5In.Define(this)
340                 .WithValueField(0, 32, name: "EPIN5");
341             Registers.Endpoint5InCount.Define(this)
342                 .WithValueField(0, 8, name: "EPIN5_MAXCNT")
343                 .WithReservedBits(8, 24);
344 
345             Registers.Endpoint6In.Define(this)
346                 .WithValueField(0, 32, name: "EPIN6");
347             Registers.Endpoint6InCount.Define(this)
348                 .WithValueField(0, 8, name: "EPIN6_MAXCNT")
349                 .WithReservedBits(8, 24);
350 
351             Registers.Endpoint7In.Define(this)
352                 .WithValueField(0, 32, name: "EPIN7");
353             Registers.Endpoint7InCount.Define(this)
354                 .WithValueField(0, 8, name: "EPIN7_MAXCNT")
355                 .WithReservedBits(8, 24);
356         }
357 
HandleToggle()358         private void HandleToggle()
359         {
360             if(dataToggleValue.Value == 0)
361             {
362                 this.Log(LogLevel.Noisy, "Selecting EP #{0}, {1}", dataToggleEndpoint.Value, dataToggleInputOutput.Value ? "in" : "out");
363                 return;
364             }
365             this.Log(LogLevel.Noisy, "Accessing EP #{0}, {1}; DATA{2}", dataToggleEndpoint.Value, dataToggleInputOutput.Value==false ? "out" : "in", dataToggleValue.Value == 1 ? "0" : "1");
366         }
367 
HandleStalling()368         private void HandleStalling()
369         {
370             // This is useful for debugging, as software may stall endpoint
371             // on wrong/unsupported tokens
372             this.Log(LogLevel.Noisy, "{0} EP #{1}, {2}", epstallStall.Value == true ? "Stalling" : "Unstalling", epstallEndpoint.Value, epstallIO.Value==false ? "out" : "in");
373         }
374 
InitiateUSBCore()375         private void InitiateUSBCore()
376         {
377             // Define all possible endpoints as available right away
378             // This is to be improved in the future and should reflect what software returns as a result of enumaration, but will require support from `USB` subsystem in Renode
379             USBConfiguration config = new USBConfiguration(this, 0, "").WithInterface(
380                     configure: x =>
381                         x.WithEndpoint(
382                             Direction.DeviceToHost,
383                             EndpointTransferType.Control,
384                             maximumPacketSize,
385                             0x10,
386                             out _)
387                         .WithEndpoint(
388                             Direction.DeviceToHost,
389                             EndpointTransferType.Bulk,
390                             maximumPacketSize,
391                             0x10,
392                             out deviceToHostEndpoint)
393                         .WithEndpoint(
394                             Direction.DeviceToHost,
395                             EndpointTransferType.Bulk,
396                             maximumPacketSize,
397                             0x10,
398                             out _)
399                         .WithEndpoint(
400                             Direction.DeviceToHost,
401                             EndpointTransferType.Bulk,
402                             maximumPacketSize,
403                             0x10,
404                             out _)
405                         .WithEndpoint(
406                             Direction.DeviceToHost,
407                             EndpointTransferType.Bulk,
408                             maximumPacketSize,
409                             0x10,
410                             out _)
411                         .WithEndpoint(
412                             Direction.DeviceToHost,
413                             EndpointTransferType.Bulk,
414                             maximumPacketSize,
415                             0x10,
416                             out _)
417                         .WithEndpoint(
418                             Direction.DeviceToHost,
419                             EndpointTransferType.Bulk,
420                             maximumPacketSize,
421                             0x10,
422                             out _)
423                         .WithEndpoint(
424                             Direction.DeviceToHost,
425                             EndpointTransferType.Bulk,
426                             maximumPacketSize,
427                             0x10,
428                             out _)
429                         .WithEndpoint(
430                             Direction.HostToDevice,
431                             EndpointTransferType.Control,
432                             maximumPacketSize,
433                             0x10,
434                             out _)
435                         .WithEndpoint(
436                             Direction.HostToDevice,
437                             EndpointTransferType.Bulk,
438                             maximumPacketSize,
439                             0x10,
440                             out _)
441                         .WithEndpoint(
442                             Direction.HostToDevice,
443                             EndpointTransferType.Bulk,
444                             maximumPacketSize,
445                             0x10,
446                             out _)
447                         .WithEndpoint(
448                             Direction.HostToDevice,
449                             EndpointTransferType.Bulk,
450                             maximumPacketSize,
451                             0x10,
452                             out _)
453                         .WithEndpoint(
454                             Direction.HostToDevice,
455                             EndpointTransferType.Bulk,
456                             maximumPacketSize,
457                             0x10,
458                             out _)
459                         .WithEndpoint(
460                             Direction.HostToDevice,
461                             EndpointTransferType.Bulk,
462                             maximumPacketSize,
463                             0x10,
464                             out _)
465                         .WithEndpoint(
466                             Direction.HostToDevice,
467                             EndpointTransferType.Bulk,
468                             maximumPacketSize,
469                             0x10,
470                             out _)
471                         .WithEndpoint(
472                             Direction.HostToDevice,
473                             EndpointTransferType.Bulk,
474                             maximumPacketSize,
475                             0x10,
476                             out _));
477             USBCore.SelectedConfiguration = config;
478         }
479 
480         DoubleWordRegisterCollection IProvidesRegisterCollection<DoubleWordRegisterCollection>.RegistersCollection => registers;
481 
482         private USBEndpoint deviceToHostEndpoint;
483         private Action<byte[]> setupPacketResultCallback;
484         private readonly IMachine machine;
485         private readonly bool[] epInDataStatus;
486         private readonly bool[] epInStatus;
487 
488         private readonly InterruptManager<Events> interruptManager;
489         private readonly IFlagRegisterField[] events;
490 
491         private SetupPacket setupPacket;
492 
493         private IValueRegisterField endpoint0In;
494         private IValueRegisterField endpoint0InCount;
495         private IValueRegisterField dataToggleEndpoint;
496         private IFlagRegisterField dataToggleInputOutput;
497         private IValueRegisterField dataToggleValue;
498 
499         private IValueRegisterField usbAddress;
500         private IValueRegisterField epstallEndpoint;
501         private IFlagRegisterField epstallIO;
502         private IFlagRegisterField epstallStall;
503 
504         private IFlagRegisterField usbPullup;
505         private IFlagRegisterField usbEnable;
506         private IFlagRegisterField ep0InEnabled;
507         private IFlagRegisterField ep0OutEnabled;
508 
509         private readonly short maximumPacketSize;
510         private readonly DoubleWordRegisterCollection registers;
511 
512         private const ushort EndpointCount = 8;
513 
514         private enum Events
515         {
516            UsbReset = 0,
517            Started = 1,
518            EndEpIn0 = 2,
519            EndEpIn1 = 3,
520            EndEpIn2 = 4,
521            EndEpIn3 = 5,
522            EndEpIn4 = 6,
523            EndEpIn5 = 7,
524            EndEpIn6 = 8,
525            EndEpIn7 = 9,
526            Ep0DataDone = 10,
527            EndIsoIn = 11,
528            EndEpOut0 = 12,
529            EndEpOut1 = 13,
530            EndEpOut2 = 14,
531            EndEpOut3 = 15,
532            EndEpOut4 = 16,
533            EndEpOut5 = 17,
534            EndEpOut6 = 18,
535            EndEpOut7 = 19,
536            EndIsoOut = 20,
537            StartOfFrame = 21,
538            UsbEvent = 22,
539            Ep0Setup = 23,
540            EpData = 24
541         }
542 
543         private enum Registers : long
544         {
545             TasksStartEpIn0 = 0x004,
546             TasksStartEpIn1 = 0x008,
547             TasksStartEpIn2 = 0x00C,
548             TasksStartEpIn3 = 0x010,
549             TasksStartEpIn4 = 0x014,
550             TasksStartEpIn5 = 0x018,
551             TasksStartEpIn6 = 0x01C,
552             TasksStartEpIn7 = 0x020,
553             TasksStartIsoIn = 0x024,
554             TasksStartEpOut0 = 0x028,
555             TasksStartEpOut1 = 0x02C,
556             TasksStartEpOut2 = 0x030,
557             TasksStartEpOut3 = 0x034,
558             TasksStartEpOut4 = 0x038,
559             TasksStartEpOut5 = 0x03C,
560             TasksStartEpOut6 = 0x040,
561             TasksStartEpOut7 = 0x044,
562             TasksStartIsoOut = 0x048,
563             TasksEp0RcvOut = 0x04C,
564             TasksEp0Status = 0x050,
565             TasksEp0Stall = 0x054,
566             TasksDPDMDrive = 0x058,
567             TasksDPDMNODrive = 0x05C,
568             EventsUsbReset = 0x100,
569             EventsStarted = 0x104,
570             EventsEndEpIn0 = 0x108,
571             EventsEndEpIn1 = 0x10C,
572             EventsEndEpIn2 = 0x110,
573             EventsEndEpIn3 = 0x114,
574             EventsEndEpIn4 = 0x118,
575             EventsEndEpIn5 = 0x11C,
576             EventsEndEpIn6 = 0x120,
577             EventsEndEpIn7 = 0x124,
578             EventsEp0DataDone = 0x128,
579             EventsEndIsoIn = 0x12C,
580             EventsEndEpOut0 = 0x130,
581             EventsEndEpOut1 = 0x134,
582             EventsEndEpOut2 = 0x138,
583             EventsEndEpOut3 = 0x13C,
584             EventsEndEpOut4 = 0x140,
585             EventsEndEpOut5 = 0x144,
586             EventsEndEpOut6 = 0x148,
587             EventsEndEpOut7 = 0x14C,
588             EventsEndIsoOut = 0x150,
589             EventsStartOfFrame = 0x154,
590             EventsUsbEvent = 0x158,
591             EventsEp0Setup = 0x15C,
592             EventsEpData = 0x160,
593             InterruptEnable = 0x300,
594             UsbPullup = 0x504,
595             DataToggle = 0x50C,
596             IsoSplit = 0x51C,
597             IsoInConfig = 0x530,
598             HaltedEndpointOut0 = 0x444,
599             EndpointStall = 0x518,
600             EventCause = 0x400,
601             EndpointStatus = 0x468,
602             EndpointDataStatus = 0x46c,
603             UsbAddress = 0x470,
604             bmRequestType = 0x480,
605             bRequest = 0x484,
606             wValueLow = 0x488,
607             wValueHigh = 0x48C,
608             wIndexLow = 0x490,
609             wIndexHigh = 0x494,
610             wLengthLow = 0x498,
611             wLengthHigh = 0x49C,
612             Enable = 0x500,
613             EndpointInEnable = 0x510,
614             EndpointOutEnable = 0x514,
615             Endpoint0In = 0x600,
616             Endpoint0InCount = 0x604,
617             Endpoint0InAmount = 0x608,
618             Endpoint1In = 0x614,
619             Endpoint1InCount = 0x618,
620             Endpoint2In = 0x628,
621             Endpoint2InCount = 0x62C,
622             Endpoint2Amount = 0x630,
623             Endpoint3In = 0x63C,
624             Endpoint3InCount = 0x640,
625             Endpoint4In = 0x650,
626             Endpoint4InCount = 0x654,
627             Endpoint5In = 0x664,
628             Endpoint5InCount = 0x668,
629             Endpoint6In = 0x678,
630             Endpoint6InCount = 0x67C,
631             Endpoint7In = 0x68C,
632             Endpoint7InCount = 0x690,
633 
634             Endpoint0Out = 0x700,
635             Endpoint0OutCount = 0x704,
636             Endpoint0OutAmount = 0x708,
637             Endpoint1Out = 0x714,
638             Endpoint1OutCount = 0x718,
639             Endpoint2Out = 0x728,
640             Endpoint2OutCount = 0x72C,
641         }
642     }
643 }
644