-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathotg.h
4128 lines (3662 loc) · 173 KB
/
otg.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdnoreturn.h>
#ifdef OTG_HOST
# include <stdlib.h>
# include <unistd.h>
#endif
#define OTG_DEBUG
#define TARGET_MODEL 5719
#define ENABLE_NCSI 0
#define PROPRIETARY 1
/* 0: Support either GPHY (copper) or SERDES (SFP) NICs at runtime.
* 1: Support GPHY only (hardcoded).
* 2: Support SERDES only (hardcoded).
*/
#define TARGET_MEDIA 0
/* ---------------------------------------------------------------- */
#if TARGET_MODEL == 5719
# define TARGET_PORTS 4
#else
# error Unsupported device
#endif
#ifndef TARGET_PORTS_ENABLED
# define TARGET_PORTS_ENABLED TARGET_PORTS
#endif
#if TARGET_PORTS_ENABLED < 0 || TARGET_PORTS_ENABLED > TARGET_PORTS
# error Invalid number of enabled target ports
#endif
#if TARGET_MEDIA != 0 && TARGET_MEDIA != 1 && TARGET_MEDIA != 2
# error Invalid TARGET_MEDIA setting.
#endif
#if TARGET_MEDIA == 2 && TARGET_MODEL == 5717
# error 5717 does not support SERDES
#endif
#define PORT_MASK (TARGET_PORTS-1)
/* ---------------------------------------------------------------- */
#define static_assert _Static_assert
#ifndef ARRAYLEN
# define ARRAYLEN(X) (sizeof(X)/sizeof((X)[0]))
#endif
#define CTZL(N) __builtin_ctzl(N)
#define MASK_TO_SHIFT(Mask) ((Mask) ? CTZL(Mask) : 0)
#define BIT(N) (1UL<<(N))
#define BITS(Lo, Hi) ((UINTPTR_MAX<<(Lo)) & (UINTPTR_MAX>>((sizeof(uintptr_t)*8-1)-(Hi))))
#define GETBIT(Value, N) (((Value) & BIT(N) ) >> (N))
#define GETBITS(Value, X, Y) (((Value) & BITS((X),(Y))) >> (X))
#define GETBITSM(Value, Mask) (((Value) & (Mask)) >> MASK_TO_SHIFT(Mask))
#define PUTBITS(Value, X, Y) (((Value) << (X)) & BITS((X),(Y)))
#define PUTBITSM(Value, Mask) (((Value) << MASK_TO_SHIFT(Mask)) & (Mask))
#define CHGBITS(OldValue, X, Y, NewValue) (((OldValue) & ~BITS((X),(Y)))|PUTBITS((NewValue), (X), (Y)))
#define CHGBITSM(OldValue, Mask, NewValue) (((OldValue) & ~(Mask))|PUTBITSM((NewValue), (Mask)))
#define REGMEM_BASE 0xC0000000
#define GENCOM_BASE 0xB50
#define V1_45
// v1.39: 0x0127, v1.45: 0x012D, etc.
#define RX_FW_VERSION 0x012D
/* ---------------------------------------------------------------- */
#define REG_POWER_MANAGEMENT_CONTROL_STATUS 0x004C
#define REG_POWER_MANAGEMENT_CONTROL_STATUS__PME_ENABLE 0x00000100
#define REG_MISCELLANEOUS_HOST_CONTROL 0x0068
#define REG_MISCELLANEOUS_HOST_CONTROL__ENABLE_ENDIAN_WORD_SWAP 0x0008
#define REG_MISCELLANEOUS_HOST_CONTROL__ENABLE_ENDIAN_BYTE_SWAP 0x0004
#define REG_PCI_STATE 0x0070
#define REG_PCI_STATE__APE_CONTROL_REGISTER_WRITE_ENABLE 0x00010000
#define REG_PCI_STATE__APE_SHARED_MEMORY_WRITE_ENABLE 0x00020000
#define REG_PCI_STATE__APE_PROGRAM_SPACE_WRITE_ENABLE 0x00040000
#define REG_PCI_STATE__PCI_EXPANSION_ROM_DESIRED 0x00000010
#define REG_MEMORY_BASE 0x007C
#define REG_UNDI_RECEIVE_RETURN_RING_CONSUMER_INDEX 0x0088
#define REG_UNDI_RECEIVE_RETURN_RING_CONSUMER_INDEX_LOW 0x008C
#define REG_LINK_STATUS_CONTROL 0x00BC
#define REG_LINK_STATUS_CONTROL__NEG_LINK_WIDTH__MASK 0x03F00000
#define REG_LINK_STATUS_CONTROL__NEG_LINK_SPEED__MASK 0x000F0000
#define REG_LINK_STATUS_CONTROL__NEG_LINK_SPEED__1 0x00010000
#define REG_LINK_STATUS_CONTROL__NEG_LINK_SPEED__2 0x00020000
// "APE Scratchpad"
//
// This might be an undocumented way to gain access to APE code memory in a
// similar vein to the other "indirect access" register sets in in early device
// register space.
//
// Write the address to 0x00F8, then write the word you want to write to 0x00FC.
// Uses configuration space, will the copy of it in the first BAR also work?
//
// Known use: An APE image (including image headers) is written to "0xD800" (in
// terms of the address written to 0x00F8), then the address 0x10_D800 (|2 for
// some reason) is written to REG_APE__GPIO_MSG. Seems to be the address of
// what was written so this is probably relative to APEMEM 0x10_0000, which is
// roughly where the code lives.
#define REG_UNK_F8 0x00F8
#define REG_UNK_FC 0x00FC
#define REG_EMAC_MODE 0x0400
#define REG_EMAC_MODE__PORT_MODE_MASK 0x000C
#define REG_EMAC_MODE__PORT_MODE_1000 0x0008 /* Gigabit mode */
#define REG_EMAC_MODE__PORT_MODE_100 0x0004 /* 10/100 mode */
#define REG_EMAC_MODE__PORT_MODE_NONE 0x0000
#define REG_EMAC_MODE__ACPI_POWER_ON_ENABLE 0x00080000
#define REG_EMAC_MODE__MAGIC_PACKET_DETECTION_ENABLE 0x00040000
#define REG_EMAC_MODE__MAC_LOOPBACK_MODE_CONTROL 0x20000000
#define REG_EMAC_MODE__ENABLE_APE_TX_PATH 0x10000000
#define REG_EMAC_MODE__ENABLE_APE_RX_PATH 0x08000000
#define REG_EMAC_STATUS 0x0404
#define REG_EMAC_STATUS__LINK_STATE_CHANGED 0x1000
#define REG_LED_CONTROL 0x040C
#define REG_LED_CONTROL__OVERRIDE_LINK 0x00000001
#define REG_LED_CONTROL__LED_1000 0x00000002
#define REG_LED_CONTROL__LED_100 0x00000004
#define REG_LED_CONTROL__LED_10 0x00000008
#define REG_LED_CONTROL__OVERRIDE_TRAFFIC 0x00000010
#define REG_LED_CONTROL__LED_TRAFFIC_BLINK 0x00000020
#define REG_LED_CONTROL__LED_TRAFFIC 0x00000040
#define REG_LED_CONTROL__LED_MODE__MAC 0x00000000
#define REG_LED_CONTROL__LED_MODE__PHY_MODE_1 0x00000800
#define REG_LED_CONTROL__LED_MODE__PHY_MODE_2 0x00001000
#define REG_LED_CONTROL__LED_MODE__PHY_MODE_1_ 0x00001800
#define REG_LED_CONTROL__LED_MODE__MASK 0x00001800
#define REG_LED_CONTROL__LED_MODE__SHIFT 11
#define REG_LED_CONTROL__SHARED_TRAFFIC_LINK_LED_MODE 0x00004000
#define REG_LED_CONTROL__MAC_MODE 0x00002000
#define REG_EMAC_MAC_ADDRESSES_0_HIGH 0x0410
#define REG_EMAC_MAC_ADDRESSES_0_LOW 0x0414
#define REG_EMAC_MAC_ADDRESSES_1_HIGH 0x0418
#define REG_EMAC_MAC_ADDRESSES_1_LOW 0x041C
#define REG_EMAC_MAC_ADDRESSES_2_HIGH 0x0420
#define REG_EMAC_MAC_ADDRESSES_2_LOW 0x0424
#define REG_EMAC_MAC_ADDRESSES_3_HIGH 0x0428
#define REG_EMAC_MAC_ADDRESSES_3_LOW 0x042C
#define REG_MII_COMMUNICATION 0x044C
#define REG_MII_COMMUNICATION__START_BUSY 0x20000000
#define REG_MII_COMMUNICATION__CMD_READ 0x08000000
#define REG_MII_COMMUNICATION__CMD_WRITE 0x04000000
#define REG_MII_MODE 0x0454
#define REG_MII_MODE__CONSTANT_MDIO_MDC_CLOCK_SPEED 0x00008000
#define REG_RECEIVE_MAC_MODE 0x0468
#define REG_RECEIVE_MAC_MODE__ENABLE BIT( 1)
#define REG_RECEIVE_MAC_MODE__PROMISCUOUS_MODE BIT( 8)
#define REG_RECEIVE_MAC_MODE__APE_PROMISCUOUS_MODE BIT(25)
// According to the register manual, these set the MAC addresses assigned to
// the APE for RX matching purposes. The diag tools consider PERFECT_MATCH1 to
// be the "APE MAC".
//
// The "high" registers take the upper two bytes of the MAC in their low 16
// bits (high 16 set to zero), and the low the remaining four bytes.
#define REG_APE_PERFECT_MATCH1_HIGH 0x0540
#define REG_APE_PERFECT_MATCHN_HIGH(N) (0x0540+8*(N))
#define REG_APE_PERFECT_MATCH1_LOW 0x0544
#define REG_APE_PERFECT_MATCHN_LOW(N) (0x0544+8*(N))
#define REG_APE_PERFECT_MATCH2_HIGH 0x0548
#define REG_APE_PERFECT_MATCH2_LOW 0x054C
#define REG_APE_PERFECT_MATCH3_HIGH 0x0550
#define REG_APE_PERFECT_MATCH3_LOW 0x0554
#define REG_APE_PERFECT_MATCH4_HIGH 0x0558
#define REG_APE_PERFECT_MATCH4_LOW 0x055C
#define REG_SGMII_STATUS 0x05B4
#define REG_SGMII_STATUS__MEDIA_SELECTION_MODE 0x0100
#define REG_SGMII_STATUS__LINK_STATUS 0x0002
#define REG_SGMII_STATUS__SPEED_100 0x0010
#define REG_HTX2B_PROTOCOL_FILTER 0x06D0
#define REG_HTX2B_PROTOCOL_FILTER__ADDR0_ENABLE 0x00000001
#define REG_HTX2B_PROTOCOL_FILTER__ADDR1_ENABLE 0x00000002
#define REG_HTX2B_PROTOCOL_FILTER__ADDR2_ENABLE 0x00000004
#define REG_HTX2B_PROTOCOL_FILTER__ADDR3_ENABLE 0x00000008
#define REG_HTX2B_PROTOCOL_FILTER__ADDR_ENABLE__MASK 0x0000000F
#define REG_HTX2B_PROTOCOL_FILTER__ARP_ENABLE 0x00000010
#define REG_HTX2B_GLOBAL_FILTER 0x06D4
#define REG_HTX2B_GLOBAL_FILTER__MULTICAST_FILTER_ENABLE 0x01
#define REG_HTX2B_GLOBAL_FILTER__BROADCAST_FILTER_ENABLE 0x02
#define REG_APE_NETWORK_STATS_IFHCINOCTETS_GOOD 0x0980
#define REG_APE_NETWORK_STATS_IFHCINOCTETS_BAD 0x0984
#define REG_CPMU_CONTROL 0x3600
#define REG_CPMU_CONTROL__LINK_IDLE_POWER_MODE_ENABLE 0x00000200
#define REG_CPMU_CONTROL__LINK_AWARE_POWER_MODE_ENABLE 0x00000400
#define REG_CPMU_CONTROL__LINK_SPEED_POWER_MODE_ENABLE 0x00004000
#define REG_LINK_AWARE_POWER_MODE_CLOCK_POLICY 0x3610
#define REG_LINK_AWARE_POWER_MODE_CLOCK_POLICY__MAC_CLOCK_SWITCH__MASK 0x001F0000
#define REG_LINK_AWARE_POWER_MODE_CLOCK_POLICY__MAC_CLOCK_SWITCH__6_25MHZ 0x00130000
#define REG_D0U_CLOCK_POLICY 0x3614
#define REG_D0U_CLOCK_POLICY__MAC_CLOCK_SWITCH__6_25MHZ 0x00130000
#define REG_APE_SLEEP_STATE_CLOCK_POLICY 0x3620
#define REG_APE_SLEEP_STATE_CLOCK_POLICY__APE_SLEEP_HCLK_DISABLE 0x80000000
#define REG_CLOCK_SPEED_OVERRIDE_POLICY 0x3624
#define REG_CLOCK_SPEED_OVERRIDE_POLICY__MAC_CLOCK_SPEED_OVERRIDE_ENABLE 0x80000000
#define REG_STATUS 0x362C
#define REG_STATUS__FUNC_NUMBER__SHIFT 30
#define REG_STATUS__VMAIN_POWER_STATUS 0x2000
#define REG_STATUS__ETHERNET_LINK_STATUS__MASK 0x00180000
#define REG_STATUS__ETHERNET_LINK_STATUS__1000 0x00000000
#define REG_STATUS__ETHERNET_LINK_STATUS__100 0x00080000
#define REG_STATUS__ETHERNET_LINK_STATUS__10 0x00100000
#define REG_STATUS__ETHERNET_LINK_STATUS__NONE 0x00180000
#define REG_STATUS__WOL_ACPI_DETECTION_ENABLE_PORT_0 0x00008000
#define REG_STATUS__WOL_ACPI_DETECTION_ENABLE_PORT_1 0x00400000
#define REG_STATUS__WOL_MAGIC_PACKET_DETECTION_ENABLE_PORT_0 0x00004000
#define REG_STATUS__WOL_MAGIC_PACKET_DETECTION_ENABLE_PORT_1 0x00200000
#define REG_STATUS__FUNC_ENABLE_0 0x02000000 /* are these active-low? */
#define REG_STATUS__FUNC_ENABLE_ALL 0x20000000 /* guessed */
#define REG_CLOCK_STATUS 0x3630
#define REG_GPHY_CONTROL_STATUS 0x3638
#define REG_GPHY_CONTROL_STATUS__BIAS_IDDQ 0x00000002
#define REG_GPHY_CONTROL_STATUS__GPHY_IDDQ 0x00000001
#define REG_GPHY_CONTROL_STATUS__SGMII_PCS_POWER_DOWN 0x00008000
#define REG_GPHY_CONTROL_STATUS__TLP_CLOCK_SOURCE 0x04000000
#define REG_GPHY_CONTROL_STATUS__SWITCHING_REGULATOR_POWER_DOWN 0x08000000
#define REG_GPHY_CONTROL_STATUS__POWER_DOWN 0x00000010
#define REG_CHIP_ID 0x3658
#define REG_MUTEX_REQUEST 0x365C
#define REG_MUTEX_GRANT 0x3660
#define REG_GPHY_STRAP 0x3664
#define REG_GPHY_STRAP__TXMBUF_ECC_ENABLE 0x00000004
#define REG_GPHY_STRAP__RXMBUF_ECC_ENABLE 0x00000008
#define REG_GPHY_STRAP__RXCPU_SPAD_ECC_ENABLE 0x00000010
#define REG_TOP_LEVEL_MISCELLANEOUS_CONTROL_1 0x367C
#define REG_TOP_LEVEL_MISCELLANEOUS_CONTROL_1__NCSI_CLOCK_OUTPUT_DISABLE 0x00000010
#define REG_EEE_MODE 0x36B0
#define REG_EEE_MODE__USER_LPI_ENABLE 0x00000080
#define REG_EEE_MODE__TX_LPI_ENABLE 0x00000100
#define REG_EEE_MODE__RX_LPI_ENABLE 0x00000200
#define REG_EEE_MODE__LINK_IDLE_DETECTION_ENABLE 0x00000008
#define REG_EEE_LINK_IDLE_CONTROL 0x36BC
#define REG_EEE_LINK_IDLE_CONTROL__DEBUG_UART_IDLE 0x00000004
#define REG_EEE_CONTROL 0x36D0
#define REG_GLOBAL_MUTEX_REQUEST 0x36F0
#define REG_GLOBAL_MUTEX_GRANT 0x36F4
#define REG_MEMORY_ARBITER_MODE 0x4000
#define REG_MEMORY_ARBITER_MODE__ENABLE 0x0002
#define REG_BUFFER_MANAGER_MODE 0x4400
#define REG_BUFFER_MANAGER_MODE__ENABLE 0x00000002
#define REG_BUFFER_MANAGER_MODE__ATTENTION_ENABLE 0x00000004
#define REG_BUFFER_MANAGER_MODE__RESET_RXMBUF_PTR 0x00000020
#define REG_LSO_READ_DMA_MODE 0x4800
#define REG_LSO_READ_DMA_MODE__INBAND_VLAN_TAG_ENABLE 0x20000000
#define REG_LSO_READ_DMA_MODE__HW_IPV6_POST_DMA_PROCESSING_ENABLE 0x10000000
#define REG_HTX2B_PERFECT_MATCHN_HIGH(N) (0x4880+8*(N))
#define REG_HTX2B_PERFECT_MATCHN_LOW(N) (0x4884+8*(N))
#define REG_LSO_NONLSO_BD_READ_DMA_CORRUPTION_ENABLE_CONTROL 0x4910
#define REG_LSO_NONLSO_BD_READ_DMA_CORRUPTION_ENABLE_CONTROL__PCI_REQUEST_BURST_LENGTH_FOR_NONLSO_RDMA_ENGINE__4K 0x000C0000
#define REG_LSO_NONLSO_BD_READ_DMA_CORRUPTION_ENABLE_CONTROL__PCI_REQUEST_BURST_LENGTH_FOR_NONLSO_RDMA_ENGINE__MASK 0x000C0000
#define REG_LSO_NONLSO_BD_READ_DMA_CORRUPTION_ENABLE_CONTROL__PCI_REQUEST_BURST_LENGTH_FOR_BD_RDMA_ENGINE__4K 0x00030000
#define REG_LSO_NONLSO_BD_READ_DMA_CORRUPTION_ENABLE_CONTROL__PCI_REQUEST_BURST_LENGTH_FOR_BD_RDMA_ENGINE__MASK 0x00030000
#define REG_RX_RISC_MODE 0x5000
#define REG_RX_RISC_MODE__ENABLE_DATA_CACHE 0x00000020
#define REG_RX_RISC_MODE__ENABLE_WATCHDOG 0x00000080
#define REG_RX_RISC_MODE__HALT 0x00000400
#define REG_RX_RISC_MODE__SINGLE_STEP 0x00000002
#define REG_RX_RISC_STATUS 0x5004
#define REG_RX_RISC_STATUS__HARDWARE_BREAKPOINT 0x00000001
#define REG_RX_RISC_STATUS__HALT_INSTRUCTION_EXECUTED 0x00000002
#define REG_RX_RISC_STATUS__INVALID_INSTRUCTION 0x00000004
#define REG_RX_RISC_STATUS__PAGE_0_DATA_REFERENCE 0x00000008
#define REG_RX_RISC_STATUS__PAGE_0_INSTRUCTION_REFERENCE 0x00000010
#define REG_RX_RISC_STATUS__INVALID_DATA_ACCESS 0x00000020
#define REG_RX_RISC_STATUS__INVALID_INSTRUCTION_FETCH 0x00000040
#define REG_RX_RISC_STATUS__BAD_MEMORY_ALIGNMENT 0x00000080
#define REG_RX_RISC_STATUS__MEMORY_ADDRESS_TRAP 0x00000100
#define REG_RX_RISC_STATUS__REGISTER_ADDRESS_TRAP 0x00000200
#define REG_RX_RISC_STATUS__HALTED 0x00000400
#define REG_RX_RISC_STATUS__BIT_11 0x00000800 /* Undocumented but appears to be a W2C halt condition */
#define REG_RX_RISC_STATUS__BIT_12 0x00001000 /* Not yet observed */
#define REG_RX_RISC_STATUS__BIT_13 0x00002000 /* Not yet observed */
#define REG_RX_RISC_STATUS__DATA_ACCESS_STALL 0x00004000
#define REG_RX_RISC_STATUS__INSTRUCTION_FETCH_STALL 0x00008000
#define REG_RX_RISC_STATUS__BLOCKING_READ 0x80000000
#define REG_RX_RISC_STATUS__CLEARABLE_MASK (REG_RX_RISC_STATUS__HARDWARE_BREAKPOINT \
|REG_RX_RISC_STATUS__HALT_INSTRUCTION_EXECUTED \
|REG_RX_RISC_STATUS__INVALID_INSTRUCTION \
|REG_RX_RISC_STATUS__PAGE_0_DATA_REFERENCE \
|REG_RX_RISC_STATUS__PAGE_0_INSTRUCTION_REFERENCE \
|REG_RX_RISC_STATUS__INVALID_DATA_ACCESS \
|REG_RX_RISC_STATUS__INVALID_INSTRUCTION_FETCH \
|REG_RX_RISC_STATUS__BAD_MEMORY_ALIGNMENT \
|REG_RX_RISC_STATUS__MEMORY_ADDRESS_TRAP \
|REG_RX_RISC_STATUS__REGISTER_ADDRESS_TRAP \
|REG_RX_RISC_STATUS__BIT_11 \
)
#define REG_RX_RISC_PROGRAM_COUNTER 0x501C
// This undocumented register contains the current word located at the program
// counter address loaded in REG_RX_RISC_PROGRAM_COUNTER.
#define REG_RX_RISC_CUR_INSTRUCTION 0x5020
// These undocumented registers contain the current values in the CPU register
// file. They can be read and written (at least when the CPU is halted, not
// tested otherwise.)
#define REG_RX_RISC_REG_0 0x5200 /* $zero (R0) */
#define REG_RX_RISC_REG_ZERO 0x5200
#define REG_RX_RISC_REG_1 0x5204 /* $at (R1) */
#define REG_RX_RISC_REG_AT 0x5204
#define REG_RX_RISC_REG_2 0x5208 /* $v0 (R2) -- Confirmed */
#define REG_RX_RISC_REG_V0 0x5208
#define REG_RX_RISC_REG_3 0x520C /* $v1 (R3) -- Confirmed */
#define REG_RX_RISC_REG_V1 0x520C
#define REG_RX_RISC_REG_4 0x5210 /* $a0 (R4) -- Confirmed */
#define REG_RX_RISC_REG_A0 0x5210
#define REG_RX_RISC_REG_5 0x5214 /* $a1 (R5) -- Confirmed */
#define REG_RX_RISC_REG_A1 0x5214
#define REG_RX_RISC_REG_6 0x5218 /* $a2 (R6) */
#define REG_RX_RISC_REG_A2 0x5218
#define REG_RX_RISC_REG_7 0x521C /* $a3 (R7) */
#define REG_RX_RISC_REG_A3 0x521C
#define REG_RX_RISC_REG_8 0x5220 /* $t0 (R8) */
#define REG_RX_RISC_REG_T0 0x5220
#define REG_RX_RISC_REG_9 0x5224 /* $t1 (R9) */
#define REG_RX_RISC_REG_T1 0x5224
#define REG_RX_RISC_REG_10 0x5228 /* $t2 (R10) */
#define REG_RX_RISC_REG_T2 0x5228
#define REG_RX_RISC_REG_11 0x522C /* $t3 (R11) */
#define REG_RX_RISC_REG_T3 0x522C
#define REG_RX_RISC_REG_12 0x5230 /* $t4 (R12) */
#define REG_RX_RISC_REG_T4 0x5230
#define REG_RX_RISC_REG_13 0x5234 /* $t5 (R13) */
#define REG_RX_RISC_REG_T5 0x5234
#define REG_RX_RISC_REG_14 0x5238 /* $t6 (R14) */
#define REG_RX_RISC_REG_T6 0x5238
#define REG_RX_RISC_REG_15 0x523C /* $t7 (R15) */
#define REG_RX_RISC_REG_T7 0x523C
#define REG_RX_RISC_REG_16 0x5240 /* $s0 (R16) */
#define REG_RX_RISC_REG_S0 0x5240
#define REG_RX_RISC_REG_17 0x5244 /* $s1 (R17) */
#define REG_RX_RISC_REG_S1 0x5244
#define REG_RX_RISC_REG_18 0x5248 /* $s2 (R18) */
#define REG_RX_RISC_REG_S2 0x5248
#define REG_RX_RISC_REG_19 0x524C /* $s3 (R19) */
#define REG_RX_RISC_REG_S3 0x524C
#define REG_RX_RISC_REG_20 0x5250 /* $s4 (R20) */
#define REG_RX_RISC_REG_S4 0x5250
#define REG_RX_RISC_REG_21 0x5254 /* $s5 (R21) */
#define REG_RX_RISC_REG_S5 0x5254
#define REG_RX_RISC_REG_22 0x5258 /* $s6 (R22) */
#define REG_RX_RISC_REG_S6 0x5258
#define REG_RX_RISC_REG_23 0x525C /* $s7 (R23) */
#define REG_RX_RISC_REG_S7 0x525C
#define REG_RX_RISC_REG_24 0x5260 /* $t8 (R24) */
#define REG_RX_RISC_REG_T8 0x5260
#define REG_RX_RISC_REG_25 0x5264 /* $t9 (R25) */
#define REG_RX_RISC_REG_T9 0x5264
#define REG_RX_RISC_REG_26 0x5268 /* $k0 (R26) */
#define REG_RX_RISC_REG_K0 0x5268
#define REG_RX_RISC_REG_27 0x526C /* $k1 (R27) */
#define REG_RX_RISC_REG_K1 0x526C
#define REG_RX_RISC_REG_28 0x5270 /* $gp (R28) */
#define REG_RX_RISC_REG_GP 0x5270
#define REG_RX_RISC_REG_29 0x5274 /* $sp (R29) */
#define REG_RX_RISC_REG_SP 0x5274
#define REG_RX_RISC_REG_30 0x5278 /* $fp (R30) */
#define REG_RX_RISC_REG_FP 0x5278
#define REG_RX_RISC_REG_31 0x527C /* $ra (R31) -- Confirmed */
#define REG_RX_RISC_REG_RA 0x527C
#define REG_PCI_SERIAL_NUMBER_LOW 0x6504 /* Guessed */
#define REG_PCI_SERIAL_NUMBER_HIGH 0x6508 /* Guessed */
#define REG_PCI_POWER_CONSUMPTION_INFO 0x6410 /* Guessed */
#define REG_PCI_POWER_DISSIPATED_INFO 0x6414 /* Guessed */
#define REG_PCI_VPD_REQ 0x642C /* Guessed */
#define REG_PCI_VPD_RES 0x6430 /* Guessed */
#define REG_PCI_VENDOR_DEVICE_ID 0x6434
// PCI Vendor/Device ID.
// Upper 16 bits: Vendor ID. Lower 16 bits: Device ID.
// Set by S1MegaUltraInit from IDs specified in NVM.
#define DEFAULT_VENDOR_DEVICE_ID 0x14E41657 /* 5719 specific */
#define REG_PCI_SUBSYSTEM_ID 0x6438
// PCI Subsystem/Subsystem Vendor ID.
// Upper 16 bits: Subsystem ID. Lower 16 bits: Subsystem Vendor ID.
// Set by S1MegaUltraInit from IDs specified in NVM.
#define REG_PCI_CLASS_CODE_REVISION 0x643C /* Guessed */
#define REG_PCI_POWER_BUDGET_0 0x6510 /* Guessed */
#define REG_PCI_POWER_BUDGET__COUNT 8
#define REG_GRC_MODE_CONTROL 0x6800
#define REG_GRC_MODE_CONTROL__PCIE_TL_DL_PL_MAPPING_1 0x00400000
#define REG_GRC_MODE_CONTROL__PCIE_TL_DL_PL_MAPPING_2 0x20000000
#define REG_GRC_MODE_CONTROL__PCIE_TL_DL_PL_MAPPING_3 0x80000000
#define REG_GRC_MODE_CONTROL__PCIE_TL_DL_PL__MASK 0xA0400000
#define REG_GRC_MODE_CONTROL__HOST_STACK_UP 0x00010000
#define REG_GRC_MODE_CONTROL__TIME_SYNC_MODE_ENABLE 0x00080000
#define REG_GRC_MODE_CONTROL__NVRAM_WRITE_ENABLE 0x00200000
#define REG_GRC_MODE_CONTROL__HTX2B_FEATURE_ENABLE 0x00040000
#define REG_GRC_MODE_CONTROL__B2HRX_FEATURE_ENABLE 0x00008000
#define REG_GRC_MODE_CONTROL__B2HRX_BYTE_SWAP 0x00000080
#define REG_GRC_MODE_CONTROL__B2HRX_WORD_SWAP 0x00000040
#define REG_MISCELLANEOUS_CONFIG 0x6804
#define REG_MISCELLANEOUS_CONFIG__PME_ENABLE 0x80000
#define REG_MISCELLANEOUS_LOCAL_CONTROL 0x6808
#define REG_MISCELLANEOUS_LOCAL_CONTROL__AUTO_SEEPROM_ACCESS 0x01000000
#define REG_MISCELLANEOUS_LOCAL_CONTROL__GPIO_0_OUTPUT_ENABLE 0x00000800
#define REG_MISCELLANEOUS_LOCAL_CONTROL__GPIO_1_OUTPUT_ENABLE 0x00001000
#define REG_MISCELLANEOUS_LOCAL_CONTROL__GPIO_2_OUTPUT_ENABLE 0x00002000
#define REG_MISCELLANEOUS_LOCAL_CONTROL__GPIO_0_OUTPUT 0x00004000
#define REG_MISCELLANEOUS_LOCAL_CONTROL__GPIO_1_OUTPUT 0x00008000
#define REG_MISCELLANEOUS_LOCAL_CONTROL__GPIO_2_OUTPUT 0x00010000
#define REG_TIMER 0x680C
#define REG_RX_CPU_EVENT 0x6810
#define REG_RX_CPU_EVENT__VPD_ATTENTION 0x40000000 /* SW Event 12/VPD Attention */
/* The register manual only mentions this in the changelog; it was
* removed from the manual in a previous revision. :|
*/
#define REG_MDI_CONTROL 0x6844
#define REG_FAST_BOOT_PROGRAM_COUNTER 0x6894
#define REG_EXPANSION_ROM_ADDRESS 0x68EC
#define REG_EAV_REF_CLOCK_CONTROL 0x6908
#define REG_EAV_REF_CLOCK_CONTROL__TIMESYNC_GPIO_MAPPING__MASK 0x00030000
#define REG_EAV_REF_CLOCK_CONTROL__TIMESYNC_GPIO_MAPPING__SHIFT 16
#define REG_EAV_REF_CLOCK_CONTROL__APE_GPIO_0_MAPPING__MASK 0x001C0000
#define REG_EAV_REF_CLOCK_CONTROL__APE_GPIO_0_MAPPING__SHIFT 18
#define REG_EAV_REF_CLOCK_CONTROL__APE_GPIO_1_MAPPING__MASK 0x00E00000
#define REG_EAV_REF_CLOCK_CONTROL__APE_GPIO_1_MAPPING__SHIFT 21
#define REG_EAV_REF_CLOCK_CONTROL__APE_GPIO_2_MAPPING__MASK 0x07000000
#define REG_EAV_REF_CLOCK_CONTROL__APE_GPIO_2_MAPPING__SHIFT 24
#define REG_EAV_REF_CLOCK_CONTROL__APE_GPIO_3_MAPPING__MASK 0x38000000
#define REG_EAV_REF_CLOCK_CONTROL__APE_GPIO_3_MAPPING__SHIFT 27
#define REG_NVM_COMMAND 0x7000
#define REG_NVM_COMMAND__DONE 0x0008
#define REG_NVM_COMMAND__DOIT 0x0010
#define REG_NVM_COMMAND__WR 0x0020
#define REG_NVM_COMMAND__FIRST 0x0080
#define REG_NVM_COMMAND__LAST 0x0100
#define REG_NVM_WRITE 0x7008
#define REG_NVM_ADDRESS 0x700C
#define REG_NVM_READ 0x7010
#define REG_NVM_CONFIG_1 0x7014
#define REG_NVM_CONFIG_1__PROTECT_MODE 0x01000000
#define REG_NVM_CONFIG_1__FLASH_SIZE 0x02000000
#define REG_NVM_CONFIG_1__FLASH_MODE 0x00000001
#define REG_NVM_CONFIG_1__BUFFER_MODE 0x00000002
#define REG_NVM_CONFIG_1__PAGE_SIZE__SHIFT 28
#define REG_NVM_CONFIG_1__PAGE_SIZE__MASK 0x70000000
#define REG_NVM_CONFIG_1__PAGE_SIZE_264 0x50000000
#define REG_NVM_CONFIG_1__SPI_CLK_DIV__MASK 0x00000780
#define REG_NVM_CONFIG_1__SPI_CLK_DIV__SHIFT 7
#define REG_SOFTWARE_ARBITRATION 0x7020
#define REG_SOFTWARE_ARBITRATION__ARB_WON0 0x0100
#define REG_SOFTWARE_ARBITRATION__REQ_SET0 0x0001
#define REG_SOFTWARE_ARBITRATION__REQ_CLR0 0x0010
#define REG_SOFTWARE_ARBITRATION__ARB_WON1 0x0200
#define REG_SOFTWARE_ARBITRATION__REQ_SET1 0x0002
#define REG_SOFTWARE_ARBITRATION__REQ_CLR1 0x0020
#define REG_SOFTWARE_ARBITRATION__ARB_WON2 0x0400
#define REG_SOFTWARE_ARBITRATION__REQ_SET2 0x0004
#define REG_SOFTWARE_ARBITRATION__REQ_CLR2 0x0040
#define REG_SOFTWARE_ARBITRATION__ARB_WON3 0x0800
#define REG_SOFTWARE_ARBITRATION__REQ_SET3 0x0008
#define REG_SOFTWARE_ARBITRATION__REQ_CLR3 0x0080
#define REG_NVM_ACCESS 0x7024
#define REG_NVM_ACCESS__NVM_ACCESS_ENABLE 0x0001
#define REG_NVM_ACCESS__NVM_ACCESS_WRITE_ENABLE 0x0002
#ifdef OTG_HOST
# define REG_SOFTWARE_ARBITRATION__ARB_WONX REG_SOFTWARE_ARBITRATION__ARB_WON1
# define REG_SOFTWARE_ARBITRATION__REQ_SETX REG_SOFTWARE_ARBITRATION__REQ_SET1
# define REG_SOFTWARE_ARBITRATION__REQ_CLRX REG_SOFTWARE_ARBITRATION__REQ_CLR1
#else
# define REG_SOFTWARE_ARBITRATION__ARB_WONX REG_SOFTWARE_ARBITRATION__ARB_WON0
# define REG_SOFTWARE_ARBITRATION__REQ_SETX REG_SOFTWARE_ARBITRATION__REQ_SET0
# define REG_SOFTWARE_ARBITRATION__REQ_CLRX REG_SOFTWARE_ARBITRATION__REQ_CLR0
#endif
/* UNKNOWN REGISTERS
* -----------------
*/
/*
0x6400 ] -- DMA Mode
UNKNOWN: 0x6408 ] (0x6400-0x67FF) "PCIe Core Private Registers Access to Configuration Space"
*UNKNOWN: 0x6410 ] -- NVM 0x0C0. PCIe Power Consumption data.
*UNKNOWN: 0x6414 ] -- NVM 0x0BC. PCIe Power Dissipated data.
VPD? 0x642C ] -- random guess: PCI VPD Request. could control PCIe VPD capability register, only used in S2 VPD code
UNKNOWN: 0x6430 ] -- PCI VPD Response
* 0x6434 ] -- guessed: PCI Vendor Device ID
* 0x6438 ] -- guessed: PCI Subsystem/Subsystem Vendor ID
*CL/REV? 0x643C ] -- this is a completely random guess, but could be Class Code+Revision ID?
UNKNOWN: 0x64C0 ] Chip Revision information is set into 8 bits of it, and other 24 are left
UNKNOWN: 0x64C8 ] unchanged.
UNKNOWN: 0x64DC ]
UNKNOWN: 0x6504 ] -- Device Serial Number Low32
UNKNOWN: 0x6508 ] -- Device Serial Number High32
*UNKNOWN:/0x6510]-]-] PCIe Power Budget Values. //// These are set as an array from NVM 0x0E0-0x0F8.
*UNKNOWN:|0x6514] ] ] Only nonzero entries are loaded, and each entry
*UNKNOWN:|0x6518] ] ] can therefore occupy an arbitrary position...
*UNKNOWN:|0x651C] ] ] kinda weird.
*UNKNOWN:|0x6520] ] ]
*UNKNOWN:|0x6524] ] ] Documentation for REG_GRC_MODE_CONTROL states:
*UNKNOWN:|0x6528] ] ] "[...] remap PCIe core TL/DL/PL register to GRC space from
*UNKNOWN:\0x652C]-]-] 0x6400 to 0x67FF."
UNKNOWN: 0x6530 ]
UNKNOWN: 0x6550 ] -- part22, GEN_CFG_1E4 bit 0x0040_0000 (LOM Design) sets LSB of this
UNKNOWN: 0x65F4 ]
UNKNOWN; 0x6838 Used by PXE agent. tg3: seems to relate to legacy SEEPROM access
UNKNOWN: 0x68F0 ] "GRC - Misc Host Control"
UNKNOWN: 0x7C04 ] (0x7C00-0x7FFF) "TL-DL-PL Port - PCIe Core Private Register Access to TL, DL & PL"
tg3: PCIE_TRANSACTION_CFG
PCIE_TRANS_CFG_1SHOT_MSI 0x2000_0000
PCIE_TRANS_CFG_LOM 0x0000_0020
Not touched but mentioned in tg3 and interesting:
0x7C00 TG3_PCIE_TLDLPL_PORT
0x7D28 PCIE_PWR_MGMT_THRESH
0x7D54 TG3_PCIE_LNKCTL
0x7E2C TG3_PCIE_PHY_TSTCTL
0x7E70 TG3_PCIE_EIDLE_DELAY
*/
/* ---------------------------------------------------------------- */
#define MII_REG_CONTROL 0x00
#define MII_REG_CONTROL__AUTO_NEGOTIATION_RESTART 0x0200
#define MII_REG_CONTROL__ISOLATE 0x0400
#define MII_REG_CONTROL__POWER_DOWN 0x0800
#define MII_REG_CONTROL__AUTO_NEGOTIATION_ENABLE 0x1000
#define MII_REG_CONTROL__RESET 0x8000
#define MII_REG_STATUS 0x01
#define MII_REG_STATUS__AUTONEGOTIATION_COMPLETE 0x20
#define MII_REG_PHY_ID_HIGH 0x02
#define MII_REG_PHY_ID_LOW 0x03
#define MII_REG_AUTO_NEGOTIATION_ADVERTISEMENT 0x04
#define MII_REG_AUTO_NEGOTIATION_ADVERTISEMENT__PROTOCOL_SELECT__IEEE_802_3 0x0001
#define MII_REG_AUTO_NEGOTIATION_ADVERTISEMENT__10BASE_T_HALF_DUPLEX 0x0020
#define MII_REG_AUTO_NEGOTIATION_ADVERTISEMENT__10BASE_T_FULL_DUPLEX 0x0040
#define MII_REG_AUTO_NEGOTIATION_ADVERTISEMENT__100BASE_TX_HALF_DUPLEX 0x0080
#define MII_REG_AUTO_NEGOTIATION_ADVERTISEMENT__100BASE_TX_FULL_DUPLEX 0x0100
#define MII_REG_AUTO_NEGOTIATION_ADVERTISEMENT__100BASE_T4 0x0200
#define MII_REG_1000BASE_T_CONTROL 0x09 /* GPHY */
#define MII_REG_1000BASE_T_CONTROL__ADVERTISE_HALF_DUPLEX 0x0100
#define MII_REG_1000BASE_T_CONTROL__ADVERTISE_FULL_DUPLEX 0x0200
#define MII_REG_BCM_SERDES_BLOCKADDRESS 0x1F /* SERDES */
#define MII_REG_SERDES_BLOCK3_ANALOG_TX_1 0x10
#define MII_REG_SERDES_BLOCK3_ANALOG_RX_1 0x13
#define MII_REG_SERDES_BLOCK3_ANALOG_TX_1__IDDQ 0x0001
#define MII_REG_SERDES_BLOCK3_ANALOG_RX_1__IDDQ 0x0001
/* --------------------------------------------------------------------- */
#define DRIVER_READY_MAGIC 0x4B657654 /* 'KevT' */
#define BOOTCODE_READY_MAGIC 0xB49A89AB /* ~'KevT' */
#define BIOS_DISABLED_MAGIC 0xDEADDEAD
#define HEADER_MAGIC 0x669955AA
#define PCI_VENDOR_ID 0x14E4
#define PCI_DEVICE_ID 0x1657
#define PCI_SUBSYSTEM_ID 0x1904
// Talos: 0x1981
#define APE_OFFSET 0x10000
#define APE_REG(X) (APE_OFFSET+(X))
// End of range here is a randomly chosen value, there's nothing nearby so it
// doesn't matter.
#define ROM_START 0x40000000
#define ROM_END 0x40080000
#ifdef __ppc64__
# define MMIO_BARRIER_PRE() do { asm volatile ("sync 0\neieio\n" ::: "memory"); } while(0)
# define MMIO_BARRIER_POST() MMIO_BARRIER_PRE()
#else
# define MMIO_BARRIER_PRE() do {} while (0)
# define MMIO_BARRIER_POST() MMIO_BARRIER_PRE()
#endif
static inline uint32_t Load32(const void *p) {
MMIO_BARRIER_PRE();
uint32_t v = *(volatile uint32_t*)p;
MMIO_BARRIER_POST();
return v;
}
static inline uint32_t Load32Immutable(const void *p) {
MMIO_BARRIER_PRE();
uint32_t v = *(uint32_t*)p;
MMIO_BARRIER_POST();
return v;
}
static inline void Store32(void *p, uint32_t value) {
MMIO_BARRIER_PRE();
*(volatile uint32_t*)p = value;
MMIO_BARRIER_POST();
}
static inline void Store16(void *p, uint16_t value) {
MMIO_BARRIER_PRE();
*(volatile uint16_t*)p = value;
MMIO_BARRIER_POST();
}
#ifndef OTG_APE
static inline uint32_t RegNoToRXAddress(uint32_t regno) {
return REGMEM_BASE+regno;
}
static inline uint32_t GencomToRXAddress(uint32_t gencom) {
return GENCOM_BASE+gencom;
}
static inline uint32_t GetReg(uint32_t regno);
static inline void SetReg(uint32_t regno, uint32_t value);
#ifdef OTG_HOST
static inline void *GetBAR12Base(void);
static inline void *GetBAR34Base(void);
// Getting access to *arbitrary* RX CPU memory addresses from the host is
// fiddlier than it should be. The following functions implement a variety of
// strategies which are selected according to which are believed to work for
// each memory range. No technique works for all ranges, because some regions
// are execute-only (meaning that even RX CPU loads from those addresses don't
// work). Other regions are RW-only (meaning that the RX CPU can load/store to
// those regions, but instruction fetch from them won't work).
// Get word that's within the first 32k of the device registers, and thus is
// directly accessible via BAR1/2 without messing around with the window. regno
// is relative to BAR1/2 (i.e. 0x00=Device/Vendor ID).
static inline uint32_t GetRXWordLow(uint32_t regno) {
return Load32((uint8_t*)GetBAR12Base() + regno);
}
static inline uint32_t GetRXWordLowImmutable(uint32_t regno) {
return Load32Immutable((uint8_t*)GetBAR12Base() + regno);
}
static inline void SetRXWordLow(uint32_t regno, uint32_t value) {
Store32((uint8_t*)GetBAR12Base() + regno, value);
}
static inline void SetRXWord16Low(uint32_t regno, uint16_t value) {
Store16((uint8_t*)GetBAR12Base() + regno, value);
}
// Get word that's within the second 32k of BAR1/2 when the window base is set
// to zero, which we assume to generally be the case. Note that we have to XOR
// bit 2 here, because the device swaps the lower and upper 32-bit words of
// each 64 bits by default for accesses to memory (but NOT device registers in
// the first 32k of BAR1/2). This is when REG_MISCELLANEOUS_HOST_CONTROL's
// ENABLE_ENDIAN_WORD_SWAP=0 and ENABLE_ENDIAN_BYTE_SWAP=0, which is the
// default and what the tg3 driver uses, so we assume that these fields are set
// to those values.
static inline uint32_t GetRXWordWindow(uint32_t regno) {
return Load32((uint8_t*)GetBAR12Base() + (32*1024) + (regno ^ 4));
}
static inline uint32_t GetRXWordWindowImmutable(uint32_t regno) {
return Load32Immutable((uint8_t*)GetBAR12Base() + (32*1024) + (regno ^ 4));
}
static inline void SetRXWordWindow(uint32_t regno, uint32_t value) {
Store32((uint8_t*)GetBAR12Base() + (32*1024) + (regno ^ 4), value);
}
static inline void SetRXWord16Window(uint32_t regno, uint16_t value) {
Store16((uint8_t*)GetBAR12Base() + (32*1024) + (regno ^ 4), value);
}
// Get APE (or higher) word. regno is relative to 0xC001_0000. If we are on the
// host we have to use BAR3/4 to access this space.
static inline uint32_t GetRXWordHigh(uint32_t regno) {
return Load32((uint8_t*)GetBAR34Base() + regno);
}
static inline uint32_t GetRXWordHighImmutable(uint32_t regno) {
return Load32Immutable((uint8_t*)GetBAR34Base() + regno);
}
static inline void SetRXWordHigh(uint32_t regno, uint32_t value) {
Store32((uint8_t*)GetBAR34Base() + regno, value);
}
static inline void SetRXWord16High(uint32_t regno, uint16_t value) {
Store16((uint8_t*)GetBAR34Base() + regno, value);
}
// Used to access an area of the RX CPU's memory that we don't have a better
// way to access - we can use the above methods for certain ranges/registers
// but in the worst case we have to fall back to this for some areas.
//
// Originally tried to use the memory window register to access the address via
// the window which sits in the upper 32k of BAR1/2, but it doesn't seem to
// work right, at least not for all addresses. So just use the ultimate
// solution: halt the CPU, set the instruction pointer to the address, and read
// out the value which gets loaded into the undocumented "current instruction
// word" register. Then restore the previous IP and unhalt the CPU.
static inline uint32_t GetRXWordViaIP(uint32_t rxAddr) {
uint32_t oldMode = GetReg(REG_RX_RISC_MODE);
SetReg(REG_RX_RISC_MODE, oldMode|REG_RX_RISC_MODE__HALT);
uint32_t oldIP = GetReg(REG_RX_RISC_PROGRAM_COUNTER);
SetReg(REG_RX_RISC_PROGRAM_COUNTER, rxAddr);
uint32_t v = GetReg(REG_RX_RISC_CUR_INSTRUCTION);
SetReg(REG_RX_RISC_PROGRAM_COUNTER, oldIP);
SetReg(REG_RX_RISC_MODE, oldMode);
return v;
}
static inline uint32_t GetRXWordViaIPImmutable(uint32_t rxAddr) {
return GetRXWordViaIP(rxAddr);
}
static inline uint32_t GetRXWordViaWindow(uint32_t rxAddr) {
uint32_t oldBase = GetReg(REG_MEMORY_BASE);
//fprintf(stderr, "0x%08X, oldBase=0x%08X, new=0x%08X\n", rxAddr, oldBase, rxAddr & 0xFFFF8000);
SetReg(REG_MEMORY_BASE, rxAddr & 0xFFFF8000); // Select 32k block
//fprintf(stderr, "windowSel=0x%08X\n", GetReg(REG_MEMORY_BASE));
uint32_t v = Load32((uint8_t*)GetBAR12Base() + (32*1024) + (rxAddr & 0x7FFF));
SetReg(REG_MEMORY_BASE, oldBase);
return v;
}
static inline void SetRXWordViaWindow(uint32_t rxAddr, uint32_t value) {
uint32_t oldBase = GetReg(REG_MEMORY_BASE);
//fprintf(stderr, "0x%08X, oldBase=0x%08X, new=0x%08X\n", rxAddr, oldBase, rxAddr & 0xFFFF8000);
SetReg(REG_MEMORY_BASE, rxAddr & 0xFFFF8000); // Select 32k block
//fprintf(stderr, "windowSel=0x%08X\n", GetReg(REG_MEMORY_BASE));
Store32((uint8_t*)GetBAR12Base() + (32*1024) + (rxAddr & 0x7FFF), value);
SetReg(REG_MEMORY_BASE, oldBase);
}
static inline uint32_t GetRXWordViaForcedLoad(uint32_t rxAddr) {
// Halt.
uint32_t oldMode = GetReg(REG_RX_RISC_MODE);
SetReg(REG_RX_RISC_MODE, oldMode|REG_RX_RISC_MODE__HALT);
// Save old state that we will clobber so we can restore it afterwards.
uint32_t oldIP = GetReg(REG_RX_RISC_PROGRAM_COUNTER);
uint32_t oldS6 = GetReg(REG_RX_RISC_REG_S6);
uint32_t oldT7 = GetReg(REG_RX_RISC_REG_T7);
// Check that the instructions we are expecting to use are correct. This will
// break if the ROM is different.
SetReg(REG_RX_RISC_PROGRAM_COUNTER, 0x40000088);
uint32_t iw = GetReg(REG_RX_RISC_CUR_INSTRUCTION);
if (iw != 0x8ECF0020) { // lw $t7, 0x20($s6)
fprintf(stderr, "cannot get RX word via forced load because the device has an unknown ROM (got 0x%08X)\n", iw);
return 0;
}
SetReg(REG_RX_RISC_REG_S6, (rxAddr-0x20));
SetReg(REG_RX_RISC_MODE, oldMode|REG_RX_RISC_MODE__HALT|REG_RX_RISC_MODE__SINGLE_STEP);
// Don't remove this, it creates a small delay which seems to sometimes be
// necessary.
if (GetReg(REG_RX_RISC_PROGRAM_COUNTER) != 0x4000008C)
fprintf(stderr, "bad1\n");
// Get the result.
uint32_t v = GetReg(REG_RX_RISC_REG_T7);
// Restore.
SetReg(REG_RX_RISC_REG_T7, oldT7);
SetReg(REG_RX_RISC_REG_S6, oldS6);
SetReg(REG_RX_RISC_PROGRAM_COUNTER, oldIP);
SetReg(REG_RX_RISC_MODE, oldMode);
return v;
}
static inline uint32_t GetRXWordViaForcedLoadImmutable(uint32_t rxAddr) {
return GetRXWordViaForcedLoad(rxAddr);
}
static inline void SetRXWordViaForcedStore(uint32_t rxAddr, uint32_t value) {
// Halt.
uint32_t oldMode = GetReg(REG_RX_RISC_MODE);
SetReg(REG_RX_RISC_MODE, oldMode|REG_RX_RISC_MODE__HALT);
// Save old state that we will clobber so we can restore it afterwards.
uint32_t oldIP = GetReg(REG_RX_RISC_PROGRAM_COUNTER);
uint32_t oldT6 = GetReg(REG_RX_RISC_REG_T6);
uint32_t oldT7 = GetReg(REG_RX_RISC_REG_T7);
// Check that the instructions we are expecting to use are correct. This will
// break if the ROM is different.
SetReg(REG_RX_RISC_PROGRAM_COUNTER, 0x40000038);
uint32_t iw = GetReg(REG_RX_RISC_CUR_INSTRUCTION);
if (iw != 0xADCF0000) { // sw $t7, 0($t6)
fprintf(stderr, "cannot set RX word via forced store because the device has an unknown ROM (got 0x%08X)\n", iw);
return;
}
SetReg(REG_RX_RISC_REG_T6, rxAddr);
SetReg(REG_RX_RISC_REG_T7, value);
SetReg(REG_RX_RISC_MODE, oldMode|REG_RX_RISC_MODE__HALT|REG_RX_RISC_MODE__SINGLE_STEP);
// Don't remove this, it creates a small delay which seems to sometimes be
// necessary.
uint32_t pc = GetReg(REG_RX_RISC_PROGRAM_COUNTER);
if (pc != 0x4000003C)
fprintf(stderr, " bad2 0x%08x\n", pc);
// Restore.
SetReg(REG_RX_RISC_REG_T7, oldT7);
SetReg(REG_RX_RISC_REG_T6, oldT6);
SetReg(REG_RX_RISC_PROGRAM_COUNTER, oldIP);
SetReg(REG_RX_RISC_MODE, oldMode);
}
static inline void SetRXWord16ViaForcedStore(uint32_t rxAddr, uint16_t value) {
// eh
uint32_t v = GetRXWordViaForcedLoad(rxAddr);
SetRXWordViaForcedStore(rxAddr, (v & 0x0000FFFF) | (((uint32_t)value) << 16));
}
static inline void SetRXWordMid(uint32_t rxAddr, uint32_t value) {
fprintf(stderr, "setting midrange RX CPU words is currently not supported\n");
#if 0
uint32_t oldBase = GetReg(REG_MEMORY_BASE);
SetReg(REG_MEMORY_BASE, rxAddr & 0xFFFF8000); // Select 32k block
Store32((uint8_t*)GetBAR12Base() + (32*1024) + (rxAddr & 0x7FFF), value);
SetReg(REG_MEMORY_BASE, oldBase);
#endif
}
static inline void SetRXWord16Mid(uint32_t rxAddr, uint16_t value) {
fprintf(stderr, "setting midrange RX CPU words is currently not supported\n");
#if 0
uint32_t oldBase = GetReg(REG_MEMORY_BASE);
SetReg(REG_MEMORY_BASE, rxAddr & 0xFFFF8000); // Select 32k block
Store16((uint8_t*)GetBAR12Base() + (32*1024) + (rxAddr & 0x7FFF), value);
SetReg(REG_MEMORY_BASE, oldBase);
#endif
}
#endif
static inline uint32_t GetRXWord(uint32_t rxAddr) {
#ifdef OTG_HOST
if (rxAddr >= REGMEM_BASE && rxAddr < 0xC0008000)
// Access a device register.
return GetRXWordLow(rxAddr - REGMEM_BASE);
else if (rxAddr < 0x8000)
// First 32k of memory - we can use the window, which we currently assume is set to 0.
return GetRXWordWindow(rxAddr);
else if (rxAddr >= (REGMEM_BASE + APE_OFFSET) && rxAddr < 0xC0020000)
// APE, etc.
return GetRXWordHigh(rxAddr - (REGMEM_BASE + APE_OFFSET));
else if (rxAddr >= ROM_START && rxAddr < ROM_END)
// This is an execute-only range so we can only load it via the instruction
// fetch hardware.
return GetRXWordViaIP(rxAddr);
else
// RX CPU SRAM.
return GetRXWordViaForcedLoad(rxAddr);
#else
return Load32((void*)rxAddr);
#endif
}
static inline uint32_t GetRXWordImmutable(uint32_t rxAddr) {
#ifdef OTG_HOST
if (rxAddr >= 0xC0000000 && rxAddr < 0xC0008000)
// Access a device register.
return GetRXWordLowImmutable(rxAddr - 0xC0000000);
else if (rxAddr < 0x8000)
// First 32k of memory - we can use the window, which we currently assume is set to 0.
return GetRXWordWindowImmutable(rxAddr);
else if (rxAddr > (REGMEM_BASE + APE_OFFSET) && rxAddr < 0xC0002000)
// APE, etc.
return GetRXWordHighImmutable(rxAddr - (REGMEM_BASE + APE_OFFSET));
else if (rxAddr >= ROM_START && rxAddr < ROM_END)
// This is an execute-only range so we can only load it via the instruction
// fetch hardware.
return GetRXWordViaIPImmutable(rxAddr);
else
// RX CPU SRAM.
return GetRXWordViaForcedLoadImmutable(rxAddr);
#else
return Load32Immutable((void*)rxAddr);
#endif
}
static inline void SetRXWord(uint32_t rxAddr, uint32_t value) {
#ifdef OTG_HOST
if (rxAddr >= REGMEM_BASE && rxAddr < 0xC0008000)
// Access a device register.
return SetRXWordLow(rxAddr - REGMEM_BASE, value);
else if (rxAddr < 0x8000)
// First 32k of memory - we can use the window, which we currently assume is set to 0.
return SetRXWordWindow(rxAddr, value);
else if (rxAddr >= (REGMEM_BASE + APE_OFFSET) && rxAddr < 0xC0002000)
// APE, etc.
return SetRXWordHigh(rxAddr - (REGMEM_BASE + APE_OFFSET), value);
else
// RX CPU SRAM.
return SetRXWordViaForcedStore(rxAddr, value);
#else
Store32((void*)rxAddr, value);
#endif
}
static inline void SetRXWord16(uint32_t rxAddr, uint16_t value) {
#ifdef OTG_HOST
if (rxAddr >= REGMEM_BASE && rxAddr < 0xC0008000)
// Access a device register.
return SetRXWord16Low(rxAddr - REGMEM_BASE, value);
else if (rxAddr < 0x8000)
// First 32k of memory - we can use the window, which we currently assume is set to 0.
return SetRXWord16Window(rxAddr, value);
else if (rxAddr >= (REGMEM_BASE + APE_OFFSET) && rxAddr < 0xC0002000)
// APE, etc.
return SetRXWord16High(rxAddr - (REGMEM_BASE + APE_OFFSET), value);
else
// RX CPU SRAM.
return SetRXWord16ViaForcedStore(rxAddr, value);
#else
Store16((void*)rxAddr, value);
#endif
}
#ifdef OTG_HOST
static inline uint32_t GetAPEWordViaF8(uint32_t apeAddr) {
if (apeAddr < 0x00100000)
abort();
SetReg(0x00F8, apeAddr - 0x00100000);
return GetReg(0x00FC);
}
static inline void SetAPEWordViaF8(uint32_t apeAddr, uint32_t v) {
if (apeAddr < 0x00100000)
abort();
SetReg(0x00F8, apeAddr - 0x00100000);
SetReg(0x00FC, v);
}
static inline uint32_t GetAPEWord(uint32_t apeAddr) {
if (apeAddr >= 0x00100000)
return GetAPEWordViaF8(apeAddr);