| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: if_scx.c,v 1.40 2023/05/21 00:35:38 nisimura Exp $ */ | | 1 | /* $NetBSD: if_scx.c,v 1.41 2023/06/13 00:15:52 nisimura Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2020 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2020 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Tohru Nishimura. | | 8 | * by Tohru Nishimura. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -39,53 +39,53 @@ | | | @@ -39,53 +39,53 @@ |
39 | * to handle incoming frames, outgoing frames and packet data crypto | | 39 | * to handle incoming frames, outgoing frames and packet data crypto |
40 | * processing. uP programs are stored in an external flash memory and | | 40 | * processing. uP programs are stored in an external flash memory and |
41 | * have to be loaded by device driver. | | 41 | * have to be loaded by device driver. |
42 | * NetSec uses Synopsys DesignWare Core EMAC. DWC implementation | | 42 | * NetSec uses Synopsys DesignWare Core EMAC. DWC implementation |
43 | * register (0x20) is known to have 0x10.36 and feature register (0x1058) | | 43 | * register (0x20) is known to have 0x10.36 and feature register (0x1058) |
44 | * reports 0x11056f37. | | 44 | * reports 0x11056f37. |
45 | * <24> alternative/enhanced desc format | | 45 | * <24> alternative/enhanced desc format |
46 | * <18> receive IP type 2 checksum offload | | 46 | * <18> receive IP type 2 checksum offload |
47 | * <16> transmit checksum offload | | 47 | * <16> transmit checksum offload |
48 | * <11> event counter (mac management counter, MMC) | | 48 | * <11> event counter (mac management counter, MMC) |
49 | */ | | 49 | */ |
50 | | | 50 | |
51 | #include <sys/cdefs.h> | | 51 | #include <sys/cdefs.h> |
52 | __KERNEL_RCSID(0, "$NetBSD: if_scx.c,v 1.40 2023/05/21 00:35:38 nisimura Exp $"); | | 52 | __KERNEL_RCSID(0, "$NetBSD: if_scx.c,v 1.41 2023/06/13 00:15:52 nisimura Exp $"); |
53 | | | 53 | |
54 | #include <sys/param.h> | | 54 | #include <sys/param.h> |
55 | #include <sys/bus.h> | | 55 | #include <sys/bus.h> |
56 | #include <sys/intr.h> | | 56 | #include <sys/intr.h> |
57 | #include <sys/device.h> | | 57 | #include <sys/device.h> |
58 | #include <sys/callout.h> | | 58 | #include <sys/callout.h> |
59 | #include <sys/mbuf.h> | | 59 | #include <sys/mbuf.h> |
60 | #include <sys/errno.h> | | 60 | #include <sys/errno.h> |
61 | #include <sys/rndsource.h> | | 61 | #include <sys/rndsource.h> |
62 | #include <sys/kernel.h> | | 62 | #include <sys/kernel.h> |
63 | #include <sys/systm.h> | | 63 | #include <sys/systm.h> |
64 | | | 64 | |
65 | #include <net/if.h> | | 65 | #include <net/if.h> |
66 | #include <net/if_media.h> | | 66 | #include <net/if_media.h> |
67 | #include <net/if_dl.h> | | 67 | #include <net/if_dl.h> |
68 | #include <net/if_ether.h> | | 68 | #include <net/if_ether.h> |
69 | #include <dev/mii/mii.h> | | 69 | #include <dev/mii/mii.h> |
70 | #include <dev/mii/miivar.h> | | 70 | #include <dev/mii/miivar.h> |
71 | #include <net/bpf.h> | | 71 | #include <net/bpf.h> |
72 | | | 72 | |
73 | #include <dev/fdt/fdtvar.h> | | 73 | #include <dev/fdt/fdtvar.h> |
74 | #include <dev/acpi/acpireg.h> | | 74 | #include <dev/acpi/acpireg.h> |
75 | #include <dev/acpi/acpivar.h> | | 75 | #include <dev/acpi/acpivar.h> |
76 | #include <dev/acpi/acpi_intr.h> | | 76 | #include <dev/acpi/acpi_intr.h> |
77 | | | 77 | |
78 | /* SC2A11 GbE 64-bit paddr descriptor */ | | 78 | /* SC2A11 GbE has 64-bit paddr descriptor */ |
79 | struct tdes { | | 79 | struct tdes { |
80 | uint32_t t0, t1, t2, t3; | | 80 | uint32_t t0, t1, t2, t3; |
81 | }; | | 81 | }; |
82 | struct rdes { | | 82 | struct rdes { |
83 | uint32_t r0, r1, r2, r3; | | 83 | uint32_t r0, r1, r2, r3; |
84 | }; | | 84 | }; |
85 | #define T0_OWN (1U<<31) /* desc is ready to Tx */ | | 85 | #define T0_OWN (1U<<31) /* desc is ready to Tx */ |
86 | #define T0_LD (1U<<30) /* last descriptor in array */ | | 86 | #define T0_LD (1U<<30) /* last descriptor in array */ |
87 | #define T0_DRID (24) /* 29:24 desc ring id */ | | 87 | #define T0_DRID (24) /* 29:24 desc ring id */ |
88 | #define T0_PT (1U<<21) /* 23:21 "pass-through" */ | | 88 | #define T0_PT (1U<<21) /* 23:21 "pass-through" */ |
89 | #define T0_TDRID (16) /* 20:16 target desc ring id: GMAC=15 */ | | 89 | #define T0_TDRID (16) /* 20:16 target desc ring id: GMAC=15 */ |
90 | #define T0_CC (1U<<15) /* ??? */ | | 90 | #define T0_CC (1U<<15) /* ??? */ |
91 | #define T0_FS (1U<<9) /* first segment of frame */ | | 91 | #define T0_FS (1U<<9) /* first segment of frame */ |
| @@ -95,155 +95,159 @@ struct rdes { | | | @@ -95,155 +95,159 @@ struct rdes { |
95 | #define T0_TRS (1U<<4) /* 5:4 "TRS" ??? */ | | 95 | #define T0_TRS (1U<<4) /* 5:4 "TRS" ??? */ |
96 | /* T1 frame segment address 63:32 */ | | 96 | /* T1 frame segment address 63:32 */ |
97 | /* T2 frame segment address 31:0 */ | | 97 | /* T2 frame segment address 31:0 */ |
98 | /* T3 31:16 TCP segment length, 15:0 frame segment length to transmit */ | | 98 | /* T3 31:16 TCP segment length, 15:0 frame segment length to transmit */ |
99 | #define R0_OWN (1U<<31) /* desc is empty */ | | 99 | #define R0_OWN (1U<<31) /* desc is empty */ |
100 | #define R0_LD (1U<<30) /* last descriptor in array */ | | 100 | #define R0_LD (1U<<30) /* last descriptor in array */ |
101 | #define R0_SDRID (24) /* 29:24 source desc ring id */ | | 101 | #define R0_SDRID (24) /* 29:24 source desc ring id */ |
102 | #define R0_FR (1U<<23) /* found fragmented */ | | 102 | #define R0_FR (1U<<23) /* found fragmented */ |
103 | #define R0_ER (1U<<21) /* Rx error indication */ | | 103 | #define R0_ER (1U<<21) /* Rx error indication */ |
104 | #define R0_ERR (3U<<16) /* 18:16 receive error code */ | | 104 | #define R0_ERR (3U<<16) /* 18:16 receive error code */ |
105 | #define R0_TDRID (12) /* 15:12 target desc ring id */ | | 105 | #define R0_TDRID (12) /* 15:12 target desc ring id */ |
106 | #define R0_FS (1U<<9) /* first segment of frame */ | | 106 | #define R0_FS (1U<<9) /* first segment of frame */ |
107 | #define R0_LS (1U<<8) /* last segment of frame */ | | 107 | #define R0_LS (1U<<8) /* last segment of frame */ |
108 | #define R0_CSUM (3U<<6) /* 7:6 checksum status */ | | 108 | #define R0_CSUM (3U<<6) /* 7:6 checksum status, 0: undone */ |
109 | #define R0_CERR (2U<<6) /* 0: undone, 1: found ok, 2: bad */ | | 109 | #define R0_CERR (2U<<6) /* 2: found bad */ |
| | | 110 | #define R0_COK (1U<<6) /* 1: found ok */ |
110 | /* R1 frame address 63:32 */ | | 111 | /* R1 frame address 63:32 */ |
111 | /* R2 frame address 31:0 */ | | 112 | /* R2 frame address 31:0 */ |
112 | /* R3 31:16 received frame length, 15:0 buffer length to receive */ | | 113 | /* R3 31:16 received frame length, 15:0 buffer length to receive */ |
113 | | | 114 | |
114 | /* | | 115 | /* |
115 | * SC2A11 registers. 0x100 - 1204 | | 116 | * SC2A11 registers. 0x100 - 1204 |
116 | */ | | 117 | */ |
117 | #define SWRESET 0x104 | | 118 | #define SWRESET 0x104 |
118 | #define SRST_RUN (1U<<31) /* instruct start, 0 to stop */ | | 119 | #define SRST_RUN (1U<<31) /* instruct start, 0 to stop */ |
119 | #define COMINIT 0x120 | | 120 | #define COMINIT 0x120 |
120 | #define INIT_DB (1U<<2) /* ???; self clear when done */ | | 121 | #define INIT_DB (1U<<2) /* ???; self clear when done */ |
121 | #define INIT_CLS (1U<<1) /* ???; self clear when done */ | | 122 | #define INIT_CLS (1U<<1) /* ???; self clear when done */ |
122 | #define PKTCTRL 0x140 /* pkt engine control */ | | 123 | #define PKTCTRL 0x140 /* pkt engine control */ |
123 | #define MODENRM (1U<<28) /* change mode to normal */ | | 124 | #define MODENRM (1U<<28) /* set operational mode to 'normal' */ |
124 | #define ENJUMBO (1U<<27) /* allow jumbo frame */ | | 125 | #define ENJUMBO (1U<<27) /* allow jumbo frame */ |
125 | #define RPTCSUMERR (1U<<3) /* log Rx checksum error */ | | 126 | #define RPTCSUMERR (1U<<3) /* log Rx checksum error */ |
126 | #define RPTHDCOMP (1U<<2) /* log HD incomplete condition */ | | 127 | #define RPTHDCOMP (1U<<2) /* log header incomplete condition */ |
127 | #define RPTHDERR (1U<<1) /* log HD error */ | | 128 | #define RPTHDERR (1U<<1) /* log header error */ |
128 | #define DROPNOMATCH (1U<<0) /* drop no match frames */ | | 129 | #define DROPNOMATCH (1U<<0) /* drop no match frames */ |
129 | #define xINTSR 0x200 /* aggregated interrupt status */ | | 130 | #define xINTSR 0x200 /* aggregated interrupt status */ |
130 | #define IRQ_UCODE (1U<<20) /* ucode load completed; W1C */ | | 131 | #define IRQ_UCODE (1U<<20) /* ucode load completed; W1C */ |
131 | #define IRQ_MAC (1U<<19) /* ??? */ | | 132 | #define IRQ_MAC (1U<<19) /* ??? */ |
132 | #define IRQ_PKT (1U<<18) /* ??? */ | | 133 | #define IRQ_PKT (1U<<18) /* ??? */ |
133 | #define IRQ_BOOTCODE (1U<<5) /* ??? */ | | 134 | #define IRQ_BOOTCODE (1U<<5) /* ??? */ |
134 | #define IRQ_XDONE (1U<<4) /* ??? mode change completed */ | | 135 | #define IRQ_XDONE (1U<<4) /* ??? mode change completed */ |
135 | #define IRQ_RX (1U<<1) /* top level Rx interrupt */ | | 136 | #define IRQ_RX (1U<<1) /* top level Rx interrupt */ |
136 | #define IRQ_TX (1U<<0) /* top level Tx interrupt */ | | 137 | #define IRQ_TX (1U<<0) /* top level Tx interrupt */ |
137 | #define xINTAEN 0x204 /* INT_A enable */ | | 138 | #define xINTAEN 0x204 /* INT_A enable */ |
138 | #define xINTAE_SET 0x234 /* bit to set */ | | 139 | #define xINTAE_SET 0x234 /* bit to set */ |
139 | #define xINTAE_CLR 0x238 /* bit to clr */ | | 140 | #define xINTAE_CLR 0x238 /* bit to clr */ |
140 | #define xINTBEN 0x23c /* INT_B enable */ | | 141 | #define xINTBEN 0x23c /* INT_B enable */ |
141 | #define xINTBE_SET 0x240 /* bit to set */ | | 142 | #define xINTBE_SET 0x240 /* bit to set */ |
142 | #define xINTBE_CLR 0x244 /* bit to clr */ | | 143 | #define xINTBE_CLR 0x244 /* bit to clr */ |
143 | #define TXISR 0x400 /* transmit status; W1C */ | | 144 | #define TXISR 0x400 /* transmit status; W1C */ |
144 | #define TXIEN 0x404 /* tx interrupt enable */ | | 145 | #define TXIEN 0x404 /* tx interrupt enable */ |
145 | #define TXIE_SET 0x428 /* bit to set */ | | 146 | #define TXIE_SET 0x428 /* bit to set */ |
146 | #define TXIE_CLR 0x42c /* bit to clr */ | | 147 | #define TXIE_CLR 0x42c /* bit to clr */ |
147 | #define TXI_NTOWNR (1U<<17) /* ??? desc array got empty */ | | 148 | #define TXI_NTOWNR (1U<<17) /* ??? desc array got empty */ |
148 | #define TXI_TR_ERR (1U<<16) /* tx error */ | | 149 | #define TXI_TR_ERR (1U<<16) /* xmit error */ |
149 | #define TXI_TXDONE (1U<<15) /* tx completed */ | | 150 | #define TXI_TXDONE (1U<<15) /* xmit completed */ |
150 | #define TXI_TMREXP (1U<<14) /* coalesce timer expired */ | | 151 | #define TXI_TMREXP (1U<<14) /* coalesce guard timer expired */ |
151 | #define RXISR 0x440 /* receive status; W1C */ | | 152 | #define RXISR 0x440 /* receive status; W1C */ |
152 | #define RXIEN 0x444 /* rx interrupt enable */ | | 153 | #define RXIEN 0x444 /* rx interrupt enable */ |
153 | #define RXIE_SET 0x468 /* bit to set */ | | 154 | #define RXIE_SET 0x468 /* bit to set */ |
154 | #define RXIE_CLR 0x46c /* bit to clr */ | | 155 | #define RXIE_CLR 0x46c /* bit to clr */ |
155 | #define RXI_RC_ERR (1U<<16) /* rx error */ | | 156 | #define RXI_RC_ERR (1U<<16) /* recv error */ |
156 | #define RXI_PKTCNT (1U<<15) /* rx counter has new value */ | | 157 | #define RXI_PKTCNT (1U<<15) /* recv counter has new value */ |
157 | #define RXI_TMREXP (1U<<14) /* coalesce timer expired */ | | 158 | #define RXI_TMREXP (1U<<14) /* coalesce guard timer expired */ |
158 | /* 13 sets of special purpose desc interrupt handling register exist */ | | 159 | /* 13 sets of special purpose desc interrupt handling register exist */ |
159 | #define TDBA_LO 0x408 /* tdes array base addr 31:0 */ | | 160 | #define TDBA_LO 0x408 /* tdes array base addr 31:0 */ |
160 | #define TDBA_HI 0x434 /* tdes array base addr 63:32 */ | | 161 | #define TDBA_HI 0x434 /* tdes array base addr 63:32 */ |
161 | #define RDBA_LO 0x448 /* rdes array base addr 31:0 */ | | 162 | #define RDBA_LO 0x448 /* rdes array base addr 31:0 */ |
162 | #define RDBA_HI 0x474 /* rdes array base addr 63:32 */ | | 163 | #define RDBA_HI 0x474 /* rdes array base addr 63:32 */ |
163 | /* 13 pairs of special purpose desc array base address register exist */ | | 164 | /* 13 pairs of special purpose desc array base address register exist */ |
164 | #define TXCONF 0x430 | | 165 | #define TXCONF 0x430 |
165 | #define RXCONF 0x470 | | 166 | #define RXCONF 0x470 |
166 | #define DESCNF_UP (1U<<31) /* up-and-running */ | | 167 | #define DESCNF_UP (1U<<31) /* 'up-and-running' */ |
167 | #define DESCNF_CHRST (1U<<30) /* channel reset */ | | 168 | #define DESCNF_CHRST (1U<<30) /* channel reset */ |
168 | #define DESCNF_TMR (1U<<4) /* coalesce timer mode select */ | | 169 | #define DESCNF_TMR (1U<<4) /* coalesce timer mode select */ |
169 | #define DESCNF_LE (1) /* little endian desc format */ | | 170 | #define DESCNF_LE (1) /* little endian desc format */ |
170 | #define TXSUBMIT 0x410 /* submit frame(s) to transmit */ | | 171 | #define TXSUBMIT 0x410 /* submit frame(s) to transmit */ |
171 | #define TXCLSCMAX 0x418 /* tx intr coalesce upper bound */ | | 172 | #define TXCOALESC 0x418 /* tx intr coalesce upper bound */ |
172 | #define RXCLSCMAX 0x458 /* rx intr coalesce upper bound */ | | 173 | #define RXCOALESC 0x458 /* rx intr coalesce upper bound */ |
173 | #define TXITIMER 0x420 /* coalesce timer usec, MSB to use */ | | 174 | #define TCLSCTIME 0x420 /* tintr guard time usec, MSB to on */ |
174 | #define RXITIMER 0x460 /* coalesce timer usec, MSB to use */ | | 175 | #define RCLSCTIME 0x460 /* rintr guard time usec, MSB to on */ |
175 | #define TXDONECNT 0x414 /* tx completed count, auto-zero */ | | 176 | #define TXDONECNT 0x414 /* tx completed count, auto-zero */ |
176 | #define RXDONECNT 0x454 /* rx available count, auto-zero */ | | 177 | #define RXAVAILCNT 0x454 /* rx available count, auto-zero */ |
177 | #define DMACTL_TMR 0x20c /* engine DMA timer value */ | | 178 | #define DMACTL_TMR 0x20c /* engine DMA timer value */ |
178 | #define UCODE_H2M 0x210 /* host2media engine ucode port */ | | 179 | #define UCODE_H2M 0x210 /* host2media engine ucode port */ |
179 | #define UCODE_M2H 0x21c /* media2host engine ucode port */ | | 180 | #define UCODE_M2H 0x21c /* media2host engine ucode port */ |
180 | #define CORESTAT 0x218 /* engine run state */ | | 181 | #define CORESTAT 0x218 /* engine run state */ |
181 | #define PKTSTOP (1U<<2) | | 182 | #define PKTSTOP (1U<<2) /* pkt engine stopped */ |
182 | #define M2HSTOP (1U<<1) | | 183 | #define M2HSTOP (1U<<1) /* M2H engine stopped */ |
183 | #define H2MSTOP (1U<<0) | | 184 | #define H2MSTOP (1U<<0) /* H2M engine stopped */ |
184 | #define DMACTL_H2M 0x214 /* host2media engine control */ | | 185 | #define DMACTL_H2M 0x214 /* host2media engine control */ |
185 | #define DMACTL_M2H 0x220 /* media2host engine control */ | | 186 | #define DMACTL_M2H 0x220 /* media2host engine control */ |
186 | #define DMACTL_STOP (1U<<0) /* instruct stop; self-clear */ | | 187 | #define DMACTL_STOP (1U<<0) /* instruct stop; self-clear */ |
| | | 188 | #define M2H_MODE_TRANS (1U<<20) /* initiate M2H mode change */ |
187 | #define UCODE_PKT 0x0d0 /* packet engine ucode port */ | | 189 | #define UCODE_PKT 0x0d0 /* packet engine ucode port */ |
188 | #define CLKEN 0x100 /* clock distribution enable */ | | 190 | #define CLKEN 0x100 /* clock distribution enable */ |
189 | #define CLK_G (1U<<5) /* feed clk domain E */ | | 191 | #define CLK_G (1U<<5) /* feed clk domain G */ |
190 | #define CLK_C (1U<<1) /* feed clk domain C */ | | 192 | #define CLK_C (1U<<1) /* feed clk domain C */ |
191 | #define CLK_D (1U<<0) /* feed clk domain D */ | | 193 | #define CLK_D (1U<<0) /* feed clk domain D */ |
192 | #define CLK_ALL 0x23 /* all above; 0x24 ??? 0x3f ??? */ | | | |
193 | | | 194 | |
194 | /* GMAC register indirect access. thru MACCMD/MACDATA operation */ | | 195 | /* GMAC register indirect access. thru MACCMD/MACDATA operation */ |
195 | #define MACDATA 0x11c0 /* gmac register rd/wr data */ | | 196 | #define MACDATA 0x11c0 /* gmac register rd/wr data */ |
196 | #define MACCMD 0x11c4 /* gmac register operation */ | | 197 | #define MACCMD 0x11c4 /* gmac register operation */ |
197 | #define CMD_IOWR (1U<<28) /* write op */ | | 198 | #define CMD_IOWR (1U<<28) /* write op */ |
198 | #define CMD_BUSY (1U<<31) /* busy bit */ | | 199 | #define CMD_BUSY (1U<<31) /* busy bit */ |
199 | #define MACSTAT 0x1024 /* gmac status; ??? */ | | 200 | #define MACSTAT 0x1024 /* gmac status; ??? */ |
200 | #define MACINTE 0x1028 /* interrupt enable; ??? */ | | 201 | #define MACINTE 0x1028 /* interrupt enable; ??? */ |
201 | | | 202 | |
202 | #define FLOWTHR 0x11cc /* flow control threshold */ | | 203 | #define FLOWTHR 0x11cc /* flow control threshold */ |
203 | /* 31:16 pause threshold, 15:0 resume threshold */ | | 204 | /* 31:16 pause threshold, 15:0 resume threshold */ |
204 | #define INTF_SEL 0x11d4 /* ??? */ | | 205 | #define INTF_SEL 0x11d4 /* phy interface type */ |
| | | 206 | #define INTF_GMII 0 |
| | | 207 | #define INTF_RGMII 1 |
| | | 208 | #define INTF_RMII 4 |
205 | | | 209 | |
206 | #define DESC_INIT 0x11fc /* write 1 for desc init, SC */ | | 210 | #define DESC_INIT 0x11fc /* write 1 for desc init, SC */ |
207 | #define DESC_SRST 0x1204 /* write 1 for desc sw reset, SC */ | | 211 | #define DESC_SRST 0x1204 /* write 1 for desc sw reset, SC */ |
208 | #define MODE_TRANS 0x500 /* mode change completion status */ | | 212 | #define MODE_TRANS 0x500 /* mode change completion status */ |
209 | #define N2T_DONE (1U<<20) /* normal->taiki change completed */ | | 213 | #define N2T_DONE (1U<<20) /* normal->taiki change completed */ |
210 | #define T2N_DONE (1U<<19) /* taiki->normal change completed */ | | 214 | #define T2N_DONE (1U<<19) /* taiki->normal change completed */ |
211 | #define MACADRH 0x10c /* ??? */ | | 215 | #define MACADRH 0x10c /* ??? */ |
212 | #define MACADRL 0x110 /* ??? */ | | 216 | #define MACADRL 0x110 /* ??? */ |
213 | #define MCVER 0x22c /* micro controller version */ | | 217 | #define MCVER 0x22c /* micro controller version */ |
214 | #define HWVER 0x230 /* hardware version */ | | 218 | #define HWVER 0x230 /* hardware version */ |
215 | | | 219 | |
216 | /* | | 220 | /* |
217 | * GMAC registers are mostly identical to Synopsys DesignWare Core | | 221 | * GMAC registers are mostly identical to Synopsys DesignWare Core |
218 | * Ethernet. These must be handled by indirect access. | | 222 | * Ethernet. These must be handled by indirect access. |
219 | */ | | 223 | */ |
220 | #define GMACMCR 0x0000 /* MAC configuration */ | | 224 | #define GMACMCR 0x0000 /* MAC configuration */ |
221 | #define MCR_IBN (1U<<30) /* ??? */ | | 225 | #define MCR_IBN (1U<<30) /* watch in-band-signal */ |
222 | #define MCR_CST (1U<<25) /* strip CRC */ | | 226 | #define MCR_CST (1U<<25) /* strip CRC */ |
223 | #define MCR_TC (1U<<24) /* keep RGMII PHY notified */ | | 227 | #define MCR_TC (1U<<24) /* keep RGMII PHY notified */ |
224 | #define MCR_WD (1U<<23) /* allow long >2048 tx frame */ | | 228 | #define MCR_WD (1U<<23) /* allow long >2048 tx frame */ |
225 | #define MCR_JE (1U<<20) /* allow ~9018 tx jumbo frame */ | | 229 | #define MCR_JE (1U<<20) /* allow ~9018 tx jumbo frame */ |
226 | #define MCR_IFG (7U<<17) /* 19:17 IFG value 0~7 */ | | 230 | #define MCR_IFG (7U<<17) /* 19:17 IFG value 0~7 */ |
227 | #define MCR_DCRS (1U<<16) /* ignore (G)MII HDX Tx error */ | | 231 | #define MCR_DCRS (1U<<16) /* ignore (G)MII HDX Tx error */ |
228 | #define MCR_PS (1U<<15) /* 1: MII 10/100, 0: GMII 1000 */ | | 232 | #define MCR_PS (1U<<15) /* 1: MII 10/100, 0: GMII 1000 */ |
229 | #define MCR_FES (1U<<14) /* force speed 100 */ | | 233 | #define MCR_FES (1U<<14) /* force speed 100 */ |
230 | #define MCR_DO (1U<<13) /* don't receive my own HDX Tx frames */ | | 234 | #define MCR_DO (1U<<13) /* don't receive my own HDX Tx frames */ |
231 | #define MCR_LOOP (1U<<12) /* run loop back */ | | 235 | #define MCR_LOOP (1U<<12) /* run loop back */ |
232 | #define MCR_USEFDX (1U<<11) /* force full duplex */ | | 236 | #define MCR_USEFDX (1U<<11) /* force full duplex */ |
233 | #define MCR_IPCEN (1U<<10) /* handle checksum */ | | 237 | #define MCR_IPCEN (1U<<10) /* handle checksum */ |
234 | #define MCR_DR (1U<<9) /* attempt no tx retry, send once */ | | 238 | #define MCR_DR (1U<<9) /* attempt no tx retry, send once */ |
235 | #define MCR_LUD (1U<<8) /* link condition report when RGMII */ | | 239 | #define MCR_LUD (1U<<8) /* link condition report when RGMII */ |
236 | #define MCR_ACS (1U<<7) /* auto pad strip CRC */ | | 240 | #define MCR_ACS (1U<<7) /* auto pad auto strip CRC */ |
237 | #define MCR_DC (1U<<4) /* report excessive tx deferral */ | | 241 | #define MCR_DC (1U<<4) /* report excessive tx deferral */ |
238 | #define MCR_TE (1U<<3) /* run Tx MAC engine, 0 to stop */ | | 242 | #define MCR_TE (1U<<3) /* run Tx MAC engine, 0 to stop */ |
239 | #define MCR_RE (1U<<2) /* run Rx MAC engine, 0 to stop */ | | 243 | #define MCR_RE (1U<<2) /* run Rx MAC engine, 0 to stop */ |
240 | #define MCR_PREA (3U) /* 1:0 preamble len. 0~2 */ | | 244 | #define MCR_PREA (3U) /* 1:0 preamble len. 0~2 */ |
241 | #define GMACAFR 0x0004 /* frame DA/SA address filter */ | | 245 | #define GMACAFR 0x0004 /* frame DA/SA address filter */ |
242 | #define AFR_RA (1U<<31) /* accept all irrespective of filt. */ | | 246 | #define AFR_RA (1U<<31) /* accept all irrespective of filt. */ |
243 | #define AFR_HPF (1U<<10) /* hash+perfect filter, or hash only */ | | 247 | #define AFR_HPF (1U<<10) /* hash+perfect filter, or hash only */ |
244 | #define AFR_SAF (1U<<9) /* source address filter */ | | 248 | #define AFR_SAF (1U<<9) /* source address filter */ |
245 | #define AFR_SAIF (1U<<8) /* SA inverse filtering */ | | 249 | #define AFR_SAIF (1U<<8) /* SA inverse filtering */ |
246 | #define AFR_PCF (2U<<6) /* ??? */ | | 250 | #define AFR_PCF (2U<<6) /* ??? */ |
247 | #define AFR_DBF (1U<<5) /* reject broadcast frame */ | | 251 | #define AFR_DBF (1U<<5) /* reject broadcast frame */ |
248 | #define AFR_PM (1U<<4) /* accept all multicast frame */ | | 252 | #define AFR_PM (1U<<4) /* accept all multicast frame */ |
249 | #define AFR_DAIF (1U<<3) /* DA inverse filtering */ | | 253 | #define AFR_DAIF (1U<<3) /* DA inverse filtering */ |
| @@ -394,35 +398,33 @@ struct rdes { | | | @@ -394,35 +398,33 @@ struct rdes { |
394 | * 0x08 - 0b H->MAC xfer engine program start addr 63:32. | | 398 | * 0x08 - 0b H->MAC xfer engine program start addr 63:32. |
395 | * 0x0c - 0f H2M program addr 31:0 (these are absolute addr, not offset) | | 399 | * 0x0c - 0f H2M program addr 31:0 (these are absolute addr, not offset) |
396 | * 0x10 - 13 H2M program length in 4 byte count. | | 400 | * 0x10 - 13 H2M program length in 4 byte count. |
397 | * 0x14 - 0b M->HOST xfer engine program start addr 63:32. | | 401 | * 0x14 - 0b M->HOST xfer engine program start addr 63:32. |
398 | * 0x18 - 0f M2H program addr 31:0 (absolute addr, not relative) | | 402 | * 0x18 - 0f M2H program addr 31:0 (absolute addr, not relative) |
399 | * 0x1c - 13 M2H program length in 4 byte count. | | 403 | * 0x1c - 13 M2H program length in 4 byte count. |
400 | * 0x20 - 23 packet engine program addr 31:0, (absolute addr, not offset) | | 404 | * 0x20 - 23 packet engine program addr 31:0, (absolute addr, not offset) |
401 | * 0x24 - 27 packet program length in 4 byte count. | | 405 | * 0x24 - 27 packet program length in 4 byte count. |
402 | * | | 406 | * |
403 | * above ucode are loaded via mapped reg 0x210, 0x21c and 0x0c0. | | 407 | * above ucode are loaded via mapped reg 0x210, 0x21c and 0x0c0. |
404 | */ | | 408 | */ |
405 | | | 409 | |
406 | #define _BMR 0x00412080 /* XXX TBD */ | | 410 | #define _BMR 0x00412080 /* XXX TBD */ |
407 | #define _BMR0 0x00020181 /* XXX TBD */ | | 411 | /* NetSec uses local RAM to handle GMAC desc arrays */ |
408 | /* NetSec uses local RAM to handle GMAC desc arrays and frame buffers */ | | | |
409 | #define _RDLA 0x18000 | | 412 | #define _RDLA 0x18000 |
410 | #define _TDLA 0x1c000 | | 413 | #define _TDLA 0x1c000 |
411 | #define _MCR_FDX 0x0000280c /* XXX TBD */ | | 414 | /* lower address region is used for intermediate frame data buffers */ |
412 | #define _MCR_HDX 0x0001a00c /* XXX TBD */ | | | |
413 | | | 415 | |
414 | /* | | 416 | /* |
415 | * all below are software constraction. | | 417 | * all below are software construction. |
416 | */ | | 418 | */ |
417 | #define MD_NTXDESC 128 | | 419 | #define MD_NTXDESC 128 |
418 | #define MD_NRXDESC 64 | | 420 | #define MD_NRXDESC 64 |
419 | | | 421 | |
420 | #define MD_NTXSEGS 16 | | 422 | #define MD_NTXSEGS 16 |
421 | #define MD_TXQUEUELEN 8 | | 423 | #define MD_TXQUEUELEN 8 |
422 | #define MD_TXQUEUELEN_MASK (MD_TXQUEUELEN - 1) | | 424 | #define MD_TXQUEUELEN_MASK (MD_TXQUEUELEN - 1) |
423 | #define MD_TXQUEUE_GC (MD_TXQUEUELEN / 4) | | 425 | #define MD_TXQUEUE_GC (MD_TXQUEUELEN / 4) |
424 | #define MD_NTXDESC_MASK (MD_NTXDESC - 1) | | 426 | #define MD_NTXDESC_MASK (MD_NTXDESC - 1) |
425 | #define MD_NEXTTX(x) (((x) + 1) & MD_NTXDESC_MASK) | | 427 | #define MD_NEXTTX(x) (((x) + 1) & MD_NTXDESC_MASK) |
426 | #define MD_NEXTTXS(x) (((x) + 1) & MD_TXQUEUELEN_MASK) | | 428 | #define MD_NEXTTXS(x) (((x) + 1) & MD_TXQUEUELEN_MASK) |
427 | | | 429 | |
428 | #define MD_NRXDESC_MASK (MD_NRXDESC - 1) | | 430 | #define MD_NRXDESC_MASK (MD_NRXDESC - 1) |
| @@ -522,27 +524,27 @@ do { \ | | | @@ -522,27 +524,27 @@ do { \ |
522 | do { \ | | 524 | do { \ |
523 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ | | 525 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ |
524 | SCX_CDRXOFF((x)), sizeof(struct rdes), (ops)); \ | | 526 | SCX_CDRXOFF((x)), sizeof(struct rdes), (ops)); \ |
525 | } while (/*CONSTCOND*/0) | | 527 | } while (/*CONSTCOND*/0) |
526 | | | 528 | |
527 | #define SCX_INIT_RXDESC(sc, x) \ | | 529 | #define SCX_INIT_RXDESC(sc, x) \ |
528 | do { \ | | 530 | do { \ |
529 | struct scx_rxsoft *__rxs = &(sc)->sc_rxsoft[(x)]; \ | | 531 | struct scx_rxsoft *__rxs = &(sc)->sc_rxsoft[(x)]; \ |
530 | struct rdes *__rxd = &(sc)->sc_rxdescs[(x)]; \ | | 532 | struct rdes *__rxd = &(sc)->sc_rxdescs[(x)]; \ |
531 | struct mbuf *__m = __rxs->rxs_mbuf; \ | | 533 | struct mbuf *__m = __rxs->rxs_mbuf; \ |
532 | bus_addr_t __p = __rxs->rxs_dmamap->dm_segs[0].ds_addr; \ | | 534 | bus_addr_t __p = __rxs->rxs_dmamap->dm_segs[0].ds_addr; \ |
533 | bus_size_t __z = __rxs->rxs_dmamap->dm_segs[0].ds_len; \ | | 535 | bus_size_t __z = __rxs->rxs_dmamap->dm_segs[0].ds_len; \ |
534 | __m->m_data = __m->m_ext.ext_buf; \ | | 536 | __m->m_data = __m->m_ext.ext_buf; \ |
535 | __rxd->r3 = htole32(__z); \ | | 537 | __rxd->r3 = htole32(__z - 4); \ |
536 | __rxd->r2 = htole32(BUS_ADDR_LO32(__p)); \ | | 538 | __rxd->r2 = htole32(BUS_ADDR_LO32(__p)); \ |
537 | __rxd->r1 = htole32(BUS_ADDR_HI32(__p)); \ | | 539 | __rxd->r1 = htole32(BUS_ADDR_HI32(__p)); \ |
538 | __rxd->r0 &= htole32(R0_LD); \ | | 540 | __rxd->r0 &= htole32(R0_LD); \ |
539 | __rxd->r0 |= htole32(R0_OWN); \ | | 541 | __rxd->r0 |= htole32(R0_OWN); \ |
540 | } while (/*CONSTCOND*/0) | | 542 | } while (/*CONSTCOND*/0) |
541 | | | 543 | |
542 | /* memory mapped CSR register access */ | | 544 | /* memory mapped CSR register access */ |
543 | #define CSR_READ(sc,off) \ | | 545 | #define CSR_READ(sc,off) \ |
544 | bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (off)) | | 546 | bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (off)) |
545 | #define CSR_WRITE(sc,off,val) \ | | 547 | #define CSR_WRITE(sc,off,val) \ |
546 | bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (off), (val)) | | 548 | bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (off), (val)) |
547 | | | 549 | |
548 | /* flash memory access */ | | 550 | /* flash memory access */ |
| @@ -552,91 +554,90 @@ do { \ | | | @@ -552,91 +554,90 @@ do { \ |
552 | static int scx_fdt_match(device_t, cfdata_t, void *); | | 554 | static int scx_fdt_match(device_t, cfdata_t, void *); |
553 | static void scx_fdt_attach(device_t, device_t, void *); | | 555 | static void scx_fdt_attach(device_t, device_t, void *); |
554 | static int scx_acpi_match(device_t, cfdata_t, void *); | | 556 | static int scx_acpi_match(device_t, cfdata_t, void *); |
555 | static void scx_acpi_attach(device_t, device_t, void *); | | 557 | static void scx_acpi_attach(device_t, device_t, void *); |
556 | | | 558 | |
557 | CFATTACH_DECL_NEW(scx_fdt, sizeof(struct scx_softc), | | 559 | CFATTACH_DECL_NEW(scx_fdt, sizeof(struct scx_softc), |
558 | scx_fdt_match, scx_fdt_attach, NULL, NULL); | | 560 | scx_fdt_match, scx_fdt_attach, NULL, NULL); |
559 | | | 561 | |
560 | CFATTACH_DECL_NEW(scx_acpi, sizeof(struct scx_softc), | | 562 | CFATTACH_DECL_NEW(scx_acpi, sizeof(struct scx_softc), |
561 | scx_acpi_match, scx_acpi_attach, NULL, NULL); | | 563 | scx_acpi_match, scx_acpi_attach, NULL, NULL); |
562 | | | 564 | |
563 | static void scx_attach_i(struct scx_softc *); | | 565 | static void scx_attach_i(struct scx_softc *); |
564 | static void scx_reset(struct scx_softc *); | | 566 | static void scx_reset(struct scx_softc *); |
565 | static int scx_init(struct ifnet *); | | | |
566 | static void scx_stop(struct ifnet *, int); | | 567 | static void scx_stop(struct ifnet *, int); |
| | | 568 | static int scx_init(struct ifnet *); |
567 | static int scx_ioctl(struct ifnet *, u_long, void *); | | 569 | static int scx_ioctl(struct ifnet *, u_long, void *); |
568 | static void scx_set_rcvfilt(struct scx_softc *); | | 570 | static void scx_set_rcvfilt(struct scx_softc *); |
569 | static void scx_start(struct ifnet *); | | 571 | static void scx_start(struct ifnet *); |
570 | static void scx_watchdog(struct ifnet *); | | 572 | static void scx_watchdog(struct ifnet *); |
571 | static int scx_intr(void *); | | 573 | static int scx_intr(void *); |
572 | static void txreap(struct scx_softc *); | | 574 | static void txreap(struct scx_softc *); |
573 | static void rxintr(struct scx_softc *); | | 575 | static void rxfill(struct scx_softc *); |
574 | static int add_rxbuf(struct scx_softc *, int); | | 576 | static int add_rxbuf(struct scx_softc *, int); |
575 | static void rxdrain(struct scx_softc *sc); | | 577 | static void rxdrain(struct scx_softc *sc); |
576 | static void mii_statchg(struct ifnet *); | | 578 | static void mii_statchg(struct ifnet *); |
577 | static void scx_ifmedia_sts(struct ifnet *, struct ifmediareq *); | | 579 | static void scx_ifmedia_sts(struct ifnet *, struct ifmediareq *); |
578 | static int mii_readreg(device_t, int, int, uint16_t *); | | 580 | static int mii_readreg(device_t, int, int, uint16_t *); |
579 | static int mii_writereg(device_t, int, int, uint16_t); | | 581 | static int mii_writereg(device_t, int, int, uint16_t); |
580 | static void phy_tick(void *); | | 582 | static void phy_tick(void *); |
581 | static void dump_hwfeature(struct scx_softc *); | | 583 | static void dump_hwfeature(struct scx_softc *); |
582 | | | 584 | |
583 | static void stopuengine(struct scx_softc *); | | 585 | static void resetuengine(struct scx_softc *); |
584 | static void startuengine(struct scx_softc *); | | | |
585 | static void loaducode(struct scx_softc *); | | 586 | static void loaducode(struct scx_softc *); |
586 | static void injectucode(struct scx_softc *, int, bus_addr_t, bus_size_t); | | 587 | static void injectucode(struct scx_softc *, int, bus_addr_t, bus_size_t); |
587 | | | 588 | |
588 | static int get_mdioclk(uint32_t); | | 589 | static int get_mdioclk(uint32_t); |
589 | | | 590 | |
590 | #define WAIT_FOR_SET(sc, reg, set, fail) \ | | 591 | #define WAIT_FOR_SET(sc, reg, set) \ |
591 | wait_for_bits(sc, reg, set, ~0, fail) | | 592 | wait_for_bits(sc, reg, set, ~0, 0) |
592 | #define WAIT_FOR_CLR(sc, reg, clr, fail) \ | | 593 | #define WAIT_FOR_CLR(sc, reg, clr) \ |
593 | wait_for_bits(sc, reg, 0, clr, fail) | | 594 | wait_for_bits(sc, reg, 0, clr, 0) |
594 | | | 595 | |
595 | static int | | 596 | static int |
596 | wait_for_bits(struct scx_softc *sc, int reg, | | 597 | wait_for_bits(struct scx_softc *sc, int reg, |
597 | uint32_t set, uint32_t clr, uint32_t fail) | | 598 | uint32_t set, uint32_t clr, uint32_t fail) |
598 | { | | 599 | { |
599 | uint32_t val; | | 600 | uint32_t val; |
600 | int ntries; | | 601 | int ntries; |
601 | | | 602 | |
602 | for (ntries = 0; ntries < 1000; ntries++) { | | 603 | for (ntries = 0; ntries < 1000; ntries++) { |
603 | val = CSR_READ(sc, reg); | | 604 | val = CSR_READ(sc, reg); |
604 | if ((val & set) || !(val & clr)) | | 605 | if ((val & set) || !(val & clr)) |
605 | return 0; | | 606 | return 0; |
606 | if (val & fail) | | 607 | if (val & fail) |
607 | return 1; | | 608 | return 1; |
608 | DELAY(1); | | 609 | DELAY(1); |
609 | } | | 610 | } |
610 | return 1; | | 611 | return 1; |
611 | } | | 612 | } |
612 | | | 613 | |
613 | /* GMAC register indirect access */ | | 614 | /* GMAC register indirect access */ |
614 | static int | | 615 | static int |
615 | mac_read(struct scx_softc *sc, int reg) | | 616 | mac_read(struct scx_softc *sc, int reg) |
616 | { | | 617 | { |
617 | | | 618 | |
618 | CSR_WRITE(sc, MACCMD, reg | CMD_BUSY); | | 619 | CSR_WRITE(sc, MACCMD, reg | CMD_BUSY); |
619 | (void)WAIT_FOR_CLR(sc, MACCMD, CMD_BUSY, 0); | | 620 | (void)WAIT_FOR_CLR(sc, MACCMD, CMD_BUSY); |
620 | return CSR_READ(sc, MACDATA); | | 621 | return CSR_READ(sc, MACDATA); |
621 | } | | 622 | } |
622 | | | 623 | |
623 | static void | | 624 | static void |
624 | mac_write(struct scx_softc *sc, int reg, int val) | | 625 | mac_write(struct scx_softc *sc, int reg, int val) |
625 | { | | 626 | { |
626 | | | 627 | |
627 | CSR_WRITE(sc, MACDATA, val); | | 628 | CSR_WRITE(sc, MACDATA, val); |
628 | CSR_WRITE(sc, MACCMD, reg | CMD_IOWR | CMD_BUSY); | | 629 | CSR_WRITE(sc, MACCMD, reg | CMD_IOWR | CMD_BUSY); |
629 | (void)WAIT_FOR_CLR(sc, MACCMD, CMD_BUSY, 0); | | 630 | (void)WAIT_FOR_CLR(sc, MACCMD, CMD_BUSY); |
630 | } | | 631 | } |
631 | | | 632 | |
632 | /* dig and decode "clock-frequency" value for a given clkname */ | | 633 | /* dig and decode "clock-frequency" value for a given clkname */ |
633 | static int | | 634 | static int |
634 | get_clk_freq(int phandle, const char *clkname) | | 635 | get_clk_freq(int phandle, const char *clkname) |
635 | { | | 636 | { |
636 | u_int index, n, cells; | | 637 | u_int index, n, cells; |
637 | const u_int *p; | | 638 | const u_int *p; |
638 | int err, len, resid; | | 639 | int err, len, resid; |
639 | unsigned int freq = 0; | | 640 | unsigned int freq = 0; |
640 | | | 641 | |
641 | err = fdtbus_get_index(phandle, "clock-names", clkname, &index); | | 642 | err = fdtbus_get_index(phandle, "clock-names", clkname, &index); |
642 | if (err == -1) | | 643 | if (err == -1) |
| @@ -863,27 +864,27 @@ aprint_normal("%s", device_xname(self)); | | | @@ -863,27 +864,27 @@ aprint_normal("%s", device_xname(self)); |
863 | acpi_resource_cleanup(&res); | | 864 | acpi_resource_cleanup(&res); |
864 | return; | | 865 | return; |
865 | } | | 866 | } |
866 | | | 867 | |
867 | static void | | 868 | static void |
868 | scx_attach_i(struct scx_softc *sc) | | 869 | scx_attach_i(struct scx_softc *sc) |
869 | { | | 870 | { |
870 | struct ifnet * const ifp = &sc->sc_ethercom.ec_if; | | 871 | struct ifnet * const ifp = &sc->sc_ethercom.ec_if; |
871 | struct mii_data * const mii = &sc->sc_mii; | | 872 | struct mii_data * const mii = &sc->sc_mii; |
872 | struct ifmedia * const ifm = &mii->mii_media; | | 873 | struct ifmedia * const ifm = &mii->mii_media; |
873 | uint32_t which, dwimp, dwfea; | | 874 | uint32_t which, dwimp, dwfea; |
874 | uint8_t enaddr[ETHER_ADDR_LEN]; | | 875 | uint8_t enaddr[ETHER_ADDR_LEN]; |
875 | bus_dma_segment_t seg; | | 876 | bus_dma_segment_t seg; |
876 | paddr_t paddr; | | 877 | paddr_t p, q; |
877 | uint32_t csr; | | 878 | uint32_t csr; |
878 | int i, nseg, error = 0; | | 879 | int i, nseg, error = 0; |
879 | | | 880 | |
880 | which = CSR_READ(sc, HWVER); /* Socionext version 5.xx */ | | 881 | which = CSR_READ(sc, HWVER); /* Socionext version 5.xx */ |
881 | dwimp = mac_read(sc, GMACIMPL); /* DWC implementation XX.YY */ | | 882 | dwimp = mac_read(sc, GMACIMPL); /* DWC implementation XX.YY */ |
882 | dwfea = mac_read(sc, HWFEA); /* DWC feature bits */ | | 883 | dwfea = mac_read(sc, HWFEA); /* DWC feature bits */ |
883 | | | 884 | |
884 | aprint_naive("\n"); | | 885 | aprint_naive("\n"); |
885 | aprint_normal(": Socionext NetSec Gigabit Ethernet controller " | | 886 | aprint_normal(": Socionext NetSec Gigabit Ethernet controller " |
886 | "%x.%x\n", which >> 16, which & 0xffff); | | 887 | "%x.%x\n", which >> 16, which & 0xffff); |
887 | | | 888 | |
888 | aprint_normal_dev(sc->sc_dev, | | 889 | aprint_normal_dev(sc->sc_dev, |
889 | "DesignWare EMAC ver 0x%x (0x%x) hw feature %08x\n", | | 890 | "DesignWare EMAC ver 0x%x (0x%x) hw feature %08x\n", |
| @@ -1000,41 +1001,49 @@ aprint_normal_dev(sc->sc_dev, "descripto | | | @@ -1000,41 +1001,49 @@ aprint_normal_dev(sc->sc_dev, "descripto |
1000 | | | 1001 | |
1001 | sc->sc_flowflags = 0; /* track PAUSE flow caps */ | | 1002 | sc->sc_flowflags = 0; /* track PAUSE flow caps */ |
1002 | | | 1003 | |
1003 | if_attach(ifp); | | 1004 | if_attach(ifp); |
1004 | if_deferred_start_init(ifp, NULL); | | 1005 | if_deferred_start_init(ifp, NULL); |
1005 | ether_ifattach(ifp, enaddr); | | 1006 | ether_ifattach(ifp, enaddr); |
1006 | | | 1007 | |
1007 | callout_init(&sc->sc_callout, 0); | | 1008 | callout_init(&sc->sc_callout, 0); |
1008 | callout_setfunc(&sc->sc_callout, phy_tick, sc); | | 1009 | callout_setfunc(&sc->sc_callout, phy_tick, sc); |
1009 | | | 1010 | |
1010 | rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), | | 1011 | rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), |
1011 | RND_TYPE_NET, RND_FLAG_DEFAULT); | | 1012 | RND_TYPE_NET, RND_FLAG_DEFAULT); |
1012 | | | 1013 | |
1013 | stopuengine(sc); | | 1014 | resetuengine(sc); |
1014 | loaducode(sc); | | 1015 | loaducode(sc); |
1015 | | | 1016 | |
1016 | /* feed NetSec descriptor array base addresses and timer value */ | | 1017 | /* feed NetSec descriptor array base addresses and timer value */ |
1017 | paddr = SCX_CDTXADDR(sc, 0); /* tdes array (ring#0) */ | | 1018 | p = SCX_CDTXADDR(sc, 0); /* tdes array (ring#0) */ |
1018 | CSR_WRITE(sc, TDBA_HI, BUS_ADDR_HI32(paddr)); | | 1019 | q = SCX_CDRXADDR(sc, 0); /* rdes array (ring#1) */ |
1019 | CSR_WRITE(sc, TDBA_LO, BUS_ADDR_LO32(paddr)); | | 1020 | CSR_WRITE(sc, TDBA_LO, BUS_ADDR_LO32(p)); |
1020 | paddr = SCX_CDRXADDR(sc, 0); /* rdes array (ring#1) */ | | 1021 | CSR_WRITE(sc, TDBA_HI, BUS_ADDR_HI32(p)); |
1021 | CSR_WRITE(sc, RDBA_HI, BUS_ADDR_HI32(paddr)); | | 1022 | CSR_WRITE(sc, RDBA_LO, BUS_ADDR_LO32(q)); |
1022 | CSR_WRITE(sc, RDBA_LO, BUS_ADDR_LO32(paddr)); | | 1023 | CSR_WRITE(sc, RDBA_HI, BUS_ADDR_HI32(q)); |
1023 | CSR_WRITE(sc, TXCONF, DESCNF_LE); /* little endian */ | | 1024 | CSR_WRITE(sc, TXCONF, DESCNF_LE); /* little endian */ |
1024 | CSR_WRITE(sc, RXCONF, DESCNF_LE); /* little endian */ | | 1025 | CSR_WRITE(sc, RXCONF, DESCNF_LE); /* little endian */ |
1025 | CSR_WRITE(sc, DMACTL_TMR, sc->sc_freq / 1000000 - 1); | | 1026 | CSR_WRITE(sc, DMACTL_TMR, sc->sc_freq / 1000000 - 1); |
1026 | | | 1027 | |
1027 | startuengine(sc); | | 1028 | CSR_WRITE(sc, DMACTL_M2H, M2H_MODE_TRANS); |
| | | 1029 | CSR_WRITE(sc, PKTCTRL, MODENRM); /* change to use normal mode */ |
| | | 1030 | WAIT_FOR_SET(sc, MODE_TRANS, T2N_DONE); |
| | | 1031 | /* do { |
| | | 1032 | csr = CSR_READ(sc, MODE_TRANS); |
| | | 1033 | } while ((csr & T2N_DONE) == 0); */ |
| | | 1034 | |
| | | 1035 | CSR_WRITE(sc, TXISR, ~0); /* clear pending emtpry/error irq */ |
| | | 1036 | CSR_WRITE(sc, xINTAE_CLR, ~0); /* disable tx / rx interrupts */ |
1028 | | | 1037 | |
1029 | return; | | 1038 | return; |
1030 | | | 1039 | |
1031 | fail_5: | | 1040 | fail_5: |
1032 | for (i = 0; i < MD_NRXDESC; i++) { | | 1041 | for (i = 0; i < MD_NRXDESC; i++) { |
1033 | if (sc->sc_rxsoft[i].rxs_dmamap != NULL) | | 1042 | if (sc->sc_rxsoft[i].rxs_dmamap != NULL) |
1034 | bus_dmamap_destroy(sc->sc_dmat, | | 1043 | bus_dmamap_destroy(sc->sc_dmat, |
1035 | sc->sc_rxsoft[i].rxs_dmamap); | | 1044 | sc->sc_rxsoft[i].rxs_dmamap); |
1036 | } | | 1045 | } |
1037 | fail_4: | | 1046 | fail_4: |
1038 | for (i = 0; i < MD_TXQUEUELEN; i++) { | | 1047 | for (i = 0; i < MD_TXQUEUELEN; i++) { |
1039 | if (sc->sc_txsoft[i].txs_dmamap != NULL) | | 1048 | if (sc->sc_txsoft[i].txs_dmamap != NULL) |
1040 | bus_dmamap_destroy(sc->sc_dmat, | | 1049 | bus_dmamap_destroy(sc->sc_dmat, |
| @@ -1060,37 +1069,52 @@ aprint_normal_dev(sc->sc_dev, "descripto | | | @@ -1060,37 +1069,52 @@ aprint_normal_dev(sc->sc_dev, "descripto |
1060 | static void | | 1069 | static void |
1061 | scx_reset(struct scx_softc *sc) | | 1070 | scx_reset(struct scx_softc *sc) |
1062 | { | | 1071 | { |
1063 | int loop = 0, busy; | | 1072 | int loop = 0, busy; |
1064 | | | 1073 | |
1065 | mac_write(sc, GMACOMR, 0); | | 1074 | mac_write(sc, GMACOMR, 0); |
1066 | mac_write(sc, GMACBMR, BMR_RST); | | 1075 | mac_write(sc, GMACBMR, BMR_RST); |
1067 | do { | | 1076 | do { |
1068 | DELAY(1); | | 1077 | DELAY(1); |
1069 | busy = mac_read(sc, GMACBMR) & BMR_RST; | | 1078 | busy = mac_read(sc, GMACBMR) & BMR_RST; |
1070 | } while (++loop < 3000 && busy); | | 1079 | } while (++loop < 3000 && busy); |
1071 | mac_write(sc, GMACBMR, _BMR); | | 1080 | mac_write(sc, GMACBMR, _BMR); |
1072 | mac_write(sc, GMACAFR, 0); | | 1081 | mac_write(sc, GMACAFR, 0); |
| | | 1082 | } |
1073 | | | 1083 | |
1074 | #if 0 | | 1084 | static void |
1075 | CSR_WRITE(sc, CLKEN, CLK_ALL); /* distribute clock sources */ | | 1085 | scx_stop(struct ifnet *ifp, int disable) |
1076 | CSR_WRITE(sc, SWRESET, 0); /* reset operation */ | | 1086 | { |
1077 | CSR_WRITE(sc, SWRESET, SRST_RUN); /* manifest run */ | | 1087 | struct scx_softc *sc = ifp->if_softc; |
1078 | CSR_WRITE(sc, COMINIT, INIT_DB | INIT_CLS); | | 1088 | uint32_t csr; |
1079 | WAIT_FOR_CLR(sc, COMINIT, (INIT_DB | INIT_CLS), 0); | | | |
1080 | | | 1089 | |
1081 | CSR_WRITE(sc, TXISR, ~0); | | 1090 | /* Stop the one second clock. */ |
| | | 1091 | callout_stop(&sc->sc_callout); |
| | | 1092 | |
| | | 1093 | /* Down the MII. */ |
| | | 1094 | mii_down(&sc->sc_mii); |
| | | 1095 | |
| | | 1096 | /* Mark the interface down and cancel the watchdog timer. */ |
| | | 1097 | ifp->if_flags &= ~IFF_RUNNING; |
| | | 1098 | ifp->if_timer = 0; |
| | | 1099 | |
| | | 1100 | CSR_WRITE(sc, RXIE_CLR, ~0); |
| | | 1101 | CSR_WRITE(sc, TXIE_CLR, ~0); |
1082 | CSR_WRITE(sc, xINTAE_CLR, ~0); | | 1102 | CSR_WRITE(sc, xINTAE_CLR, ~0); |
1083 | #endif | | 1103 | CSR_WRITE(sc, TXISR, ~0); |
| | | 1104 | CSR_WRITE(sc, RXISR, ~0); |
| | | 1105 | |
| | | 1106 | csr = mac_read(sc, GMACOMR); |
| | | 1107 | mac_write(sc, GMACOMR, csr &~ (OMR_SR | OMR_ST)); |
1084 | } | | 1108 | } |
1085 | | | 1109 | |
1086 | static int | | 1110 | static int |
1087 | scx_init(struct ifnet *ifp) | | 1111 | scx_init(struct ifnet *ifp) |
1088 | { | | 1112 | { |
1089 | struct scx_softc *sc = ifp->if_softc; | | 1113 | struct scx_softc *sc = ifp->if_softc; |
1090 | const uint8_t *ea = CLLADDR(ifp->if_sadl); | | 1114 | const uint8_t *ea = CLLADDR(ifp->if_sadl); |
1091 | uint32_t csr; | | 1115 | uint32_t csr; |
1092 | int i, error; | | 1116 | int i, error; |
1093 | | | 1117 | |
1094 | /* Cancel pending I/O. */ | | 1118 | /* Cancel pending I/O. */ |
1095 | scx_stop(ifp, 0); | | 1119 | scx_stop(ifp, 0); |
1096 | | | 1120 | |
| @@ -1132,86 +1156,64 @@ scx_init(struct ifnet *ifp) | | | @@ -1132,86 +1156,64 @@ scx_init(struct ifnet *ifp) |
1132 | csr = (ea[3] << 24) | (ea[2] << 16) | (ea[1] << 8) | ea[0]; | | 1156 | csr = (ea[3] << 24) | (ea[2] << 16) | (ea[1] << 8) | ea[0]; |
1133 | mac_write(sc, GMACMAL0, csr); | | 1157 | mac_write(sc, GMACMAL0, csr); |
1134 | csr = (ea[5] << 8) | ea[4]; | | 1158 | csr = (ea[5] << 8) | ea[4]; |
1135 | mac_write(sc, GMACMAH0, csr); | | 1159 | mac_write(sc, GMACMAH0, csr); |
1136 | | | 1160 | |
1137 | /* accept multicast frame or run promisc mode */ | | 1161 | /* accept multicast frame or run promisc mode */ |
1138 | scx_set_rcvfilt(sc); | | 1162 | scx_set_rcvfilt(sc); |
1139 | | | 1163 | |
1140 | /* set current media */ | | 1164 | /* set current media */ |
1141 | if ((error = ether_mediachange(ifp)) != 0) | | 1165 | if ((error = ether_mediachange(ifp)) != 0) |
1142 | goto out; | | 1166 | goto out; |
1143 | | | 1167 | |
1144 | CSR_WRITE(sc, DESC_SRST, 01); | | 1168 | CSR_WRITE(sc, DESC_SRST, 01); |
1145 | WAIT_FOR_CLR(sc, DESC_SRST, 01, 0); | | 1169 | WAIT_FOR_CLR(sc, DESC_SRST, 01); |
1146 | | | 1170 | |
1147 | CSR_WRITE(sc, DESC_INIT, 01); | | 1171 | CSR_WRITE(sc, DESC_INIT, 01); |
1148 | WAIT_FOR_CLR(sc, DESC_INIT, 01, 0); | | 1172 | WAIT_FOR_CLR(sc, DESC_INIT, 01); |
1149 | | | 1173 | |
1150 | /* feed local memory descriptor array base addresses */ | | 1174 | /* feed local memory descriptor array base addresses */ |
1151 | mac_write(sc, GMACRDLA, _RDLA); /* GMAC rdes store */ | | 1175 | mac_write(sc, GMACRDLA, _RDLA); /* GMAC rdes store */ |
1152 | mac_write(sc, GMACTDLA, _TDLA); /* GMAC tdes store */ | | 1176 | mac_write(sc, GMACTDLA, _TDLA); /* GMAC tdes store */ |
1153 | | | 1177 | |
1154 | CSR_WRITE(sc, FLOWTHR, (48<<16) | 36); /* pause|resume threshold */ | | 1178 | CSR_WRITE(sc, FLOWTHR, (48<<16) | 36); /* pause|resume threshold */ |
1155 | mac_write(sc, GMACFCR, 256 << 16); /* 31:16 pause value */ | | 1179 | mac_write(sc, GMACFCR, 256 << 16); /* 31:16 pause value */ |
1156 | | | 1180 | |
1157 | CSR_WRITE(sc, RXIE_CLR, ~0); /* clear Rx interrupt enable */ | | 1181 | CSR_WRITE(sc, INTF_SEL, sc->sc_miigmii ? INTF_GMII : INTF_RGMII); |
1158 | CSR_WRITE(sc, TXIE_CLR, ~0); /* clear Tx interrupt enable */ | | | |
1159 | | | 1182 | |
1160 | CSR_WRITE(sc, RXCLSCMAX, 8); /* Rx coalesce upper bound */ | | 1183 | CSR_WRITE(sc, RXCOALESC, 8); /* Rx coalesce bound */ |
1161 | CSR_WRITE(sc, TXCLSCMAX, 8); /* Tx coalesce upper bound */ | | 1184 | CSR_WRITE(sc, TXCOALESC, 8); /* Tx coalesce bound */ |
1162 | CSR_WRITE(sc, RXITIMER, 500); /* Rx co. timer usec */ | | 1185 | CSR_WRITE(sc, RCLSCTIME, 500|(1U<<31)); /* Rx co. guard time usec */ |
1163 | CSR_WRITE(sc, TXITIMER, 500); /* Tx co. timer usec */ | | 1186 | CSR_WRITE(sc, TCLSCTIME, 500|(1U<<31)); /* Tx co. guard time usec */ |
1164 | | | 1187 | |
1165 | CSR_WRITE(sc, RXIE_SET, RXI_RC_ERR | RXI_PKTCNT | RXI_TMREXP); | | 1188 | CSR_WRITE(sc, RXIE_SET, RXI_RC_ERR | RXI_PKTCNT | RXI_TMREXP); |
1166 | CSR_WRITE(sc, TXIE_SET, TXI_TR_ERR | TXI_TXDONE | TXI_TMREXP); | | 1189 | CSR_WRITE(sc, TXIE_SET, TXI_TR_ERR | TXI_TXDONE | TXI_TMREXP); |
1167 | | | | |
1168 | CSR_WRITE(sc, xINTAE_SET, IRQ_RX | IRQ_TX); | | 1190 | CSR_WRITE(sc, xINTAE_SET, IRQ_RX | IRQ_TX); |
1169 | #if 1 | | 1191 | #if 1 |
1170 | /* clear event counters, auto-zero after every read */ | | 1192 | /* clear event counters, auto-zero after every read */ |
1171 | mac_write(sc, GMACEVCTL, EVC_CR /* | EVC_ROR */); | | 1193 | mac_write(sc, GMACEVCTL, EVC_CR | EVC_ROR); |
1172 | #endif | | 1194 | #endif |
1173 | /* kick to start GMAC engine */ | | 1195 | /* kick to start GMAC engine */ |
1174 | csr = mac_read(sc, GMACOMR); | | 1196 | csr = mac_read(sc, GMACOMR); |
1175 | mac_write(sc, GMACOMR, csr | OMR_SR | OMR_ST); | | 1197 | mac_write(sc, GMACOMR, csr | OMR_SR | OMR_ST); |
1176 | | | 1198 | |
1177 | ifp->if_flags |= IFF_RUNNING; | | 1199 | ifp->if_flags |= IFF_RUNNING; |
1178 | | | 1200 | |
1179 | /* start one second timer */ | | 1201 | /* start one second timer */ |
1180 | callout_schedule(&sc->sc_callout, hz); | | 1202 | callout_schedule(&sc->sc_callout, hz); |
1181 | out: | | 1203 | out: |
1182 | return error; | | 1204 | return error; |
1183 | } | | 1205 | } |
1184 | | | 1206 | |
1185 | static void | | | |
1186 | scx_stop(struct ifnet *ifp, int disable) | | | |
1187 | { | | | |
1188 | struct scx_softc *sc = ifp->if_softc; | | | |
1189 | | | | |
1190 | /* Stop the one second clock. */ | | | |
1191 | callout_stop(&sc->sc_callout); | | | |
1192 | | | | |
1193 | /* Down the MII. */ | | | |
1194 | mii_down(&sc->sc_mii); | | | |
1195 | | | | |
1196 | /* Mark the interface down and cancel the watchdog timer. */ | | | |
1197 | ifp->if_flags &= ~IFF_RUNNING; | | | |
1198 | ifp->if_timer = 0; | | | |
1199 | | | | |
1200 | CSR_WRITE(sc, xINTAE_CLR, ~0); | | | |
1201 | CSR_WRITE(sc, TXISR, ~0); | | | |
1202 | CSR_WRITE(sc, RXISR, ~0); | | | |
1203 | } | | | |
1204 | | | | |
1205 | static int | | 1207 | static int |
1206 | scx_ioctl(struct ifnet *ifp, u_long cmd, void *data) | | 1208 | scx_ioctl(struct ifnet *ifp, u_long cmd, void *data) |
1207 | { | | 1209 | { |
1208 | struct scx_softc *sc = ifp->if_softc; | | 1210 | struct scx_softc *sc = ifp->if_softc; |
1209 | struct ifreq *ifr = (struct ifreq *)data; | | 1211 | struct ifreq *ifr = (struct ifreq *)data; |
1210 | struct ifmedia *ifm = &sc->sc_mii.mii_media; | | 1212 | struct ifmedia *ifm = &sc->sc_mii.mii_media; |
1211 | int s, error; | | 1213 | int s, error; |
1212 | | | 1214 | |
1213 | s = splnet(); | | 1215 | s = splnet(); |
1214 | | | 1216 | |
1215 | switch (cmd) { | | 1217 | switch (cmd) { |
1216 | case SIOCSIFMEDIA: | | 1218 | case SIOCSIFMEDIA: |
1217 | /* Flow control requires full-duplex mode. */ | | 1219 | /* Flow control requires full-duplex mode. */ |
| @@ -1325,192 +1327,187 @@ aprint_normal_dev(sc->sc_dev, "[%d] %s\n | | | @@ -1325,192 +1327,187 @@ aprint_normal_dev(sc->sc_dev, "[%d] %s\n |
1325 | mac_write(sc, GMACMAH(i), addr | 1U<<31); | | 1327 | mac_write(sc, GMACMAH(i), addr | 1U<<31); |
1326 | } else { | | 1328 | } else { |
1327 | /* use hash table when too many */ | | 1329 | /* use hash table when too many */ |
1328 | crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN); | | 1330 | crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN); |
1329 | crc = bit_reverse_32(~crc); | | 1331 | crc = bit_reverse_32(~crc); |
1330 | /* 1(31) 5(30:26) bit sampling */ | | 1332 | /* 1(31) 5(30:26) bit sampling */ |
1331 | mchash[crc >> 31] |= 1 << ((crc >> 26) & 0x1f); | | 1333 | mchash[crc >> 31] |= 1 << ((crc >> 26) & 0x1f); |
1332 | } | | 1334 | } |
1333 | ETHER_NEXT_MULTI(step, enm); | | 1335 | ETHER_NEXT_MULTI(step, enm); |
1334 | i++; | | 1336 | i++; |
1335 | } | | 1337 | } |
1336 | ETHER_UNLOCK(ec); | | 1338 | ETHER_UNLOCK(ec); |
1337 | if (crc) | | 1339 | if (crc) |
1338 | csr |= AFR_MHTE; | | 1340 | csr |= AFR_MHTE; /* use mchash[] */ |
1339 | csr |= AFR_HPF; /* use hash+perfect */ | | 1341 | csr |= AFR_HPF; /* use perfect match as well */ |
| | | 1342 | update: |
1340 | mac_write(sc, GMACMHTH, mchash[1]); | | 1343 | mac_write(sc, GMACMHTH, mchash[1]); |
1341 | mac_write(sc, GMACMHTL, mchash[0]); | | 1344 | mac_write(sc, GMACMHTL, mchash[0]); |
1342 | update: | | | |
1343 | /* With PR or PM, MHTE/MHTL/MHTH are never consulted. really? */ | | | |
1344 | mac_write(sc, GMACAFR, csr); | | 1345 | mac_write(sc, GMACAFR, csr); |
1345 | return; | | 1346 | return; |
1346 | } | | 1347 | } |
1347 | | | 1348 | |
1348 | static void | | 1349 | static void |
1349 | scx_start(struct ifnet *ifp) | | 1350 | scx_start(struct ifnet *ifp) |
1350 | { | | 1351 | { |
1351 | struct scx_softc *sc = ifp->if_softc; | | 1352 | struct scx_softc *sc = ifp->if_softc; |
1352 | struct mbuf *m0; | | 1353 | struct mbuf *m0; |
1353 | struct scx_txsoft *txs; | | 1354 | struct scx_txsoft *txs; |
1354 | bus_dmamap_t dmamap; | | 1355 | bus_dmamap_t dmamap; |
1355 | int error, nexttx, lasttx, ofree, seg; | | 1356 | int error, nexttx, lasttx, ofree, seg; |
1356 | uint32_t tdes0; | | 1357 | uint32_t tdes0; |
1357 | | | 1358 | |
1358 | if ((ifp->if_flags & IFF_RUNNING) == 0) | | 1359 | if ((ifp->if_flags & IFF_RUNNING) == 0) |
1359 | return; | | 1360 | return; |
1360 | | | 1361 | |
1361 | /* Remember the previous number of free descriptors. */ | | 1362 | /* Remember the previous number of free descriptors. */ |
1362 | ofree = sc->sc_txfree; | | 1363 | ofree = sc->sc_txfree; |
1363 | | | | |
1364 | /* | | 1364 | /* |
1365 | * Loop through the send queue, setting up transmit descriptors | | 1365 | * Loop through the send queue, setting up transmit descriptors |
1366 | * until we drain the queue, or use up all available transmit | | 1366 | * until we drain the queue, or use up all available transmit |
1367 | * descriptors. | | 1367 | * descriptors. |
1368 | */ | | 1368 | */ |
1369 | for (;;) { | | 1369 | for (;;) { |
1370 | IFQ_POLL(&ifp->if_snd, m0); | | 1370 | IFQ_POLL(&ifp->if_snd, m0); |
1371 | if (m0 == NULL) | | 1371 | if (m0 == NULL) |
1372 | break; | | 1372 | break; |
1373 | | | | |
1374 | if (sc->sc_txsfree < MD_TXQUEUE_GC) { | | 1373 | if (sc->sc_txsfree < MD_TXQUEUE_GC) { |
1375 | txreap(sc); | | 1374 | txreap(sc); |
1376 | if (sc->sc_txsfree == 0) | | 1375 | if (sc->sc_txsfree == 0) |
1377 | break; | | 1376 | break; |
1378 | } | | 1377 | } |
1379 | txs = &sc->sc_txsoft[sc->sc_txsnext]; | | 1378 | txs = &sc->sc_txsoft[sc->sc_txsnext]; |
1380 | dmamap = txs->txs_dmamap; | | 1379 | dmamap = txs->txs_dmamap; |
1381 | | | | |
1382 | error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0, | | 1380 | error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0, |
1383 | BUS_DMA_WRITE | BUS_DMA_NOWAIT); | | 1381 | BUS_DMA_WRITE | BUS_DMA_NOWAIT); |
1384 | if (error) { | | 1382 | if (error) { |
1385 | if (error == EFBIG) { | | 1383 | if (error == EFBIG) { |
1386 | aprint_error_dev(sc->sc_dev, | | 1384 | aprint_error_dev(sc->sc_dev, |
1387 | "Tx packet consumes too many " | | 1385 | "Tx packet consumes too many " |
1388 | "DMA segments, dropping...\n"); | | 1386 | "DMA segments, dropping...\n"); |
1389 | IFQ_DEQUEUE(&ifp->if_snd, m0); | | 1387 | IFQ_DEQUEUE(&ifp->if_snd, m0); |
1390 | m_freem(m0); | | 1388 | m_freem(m0); |
1391 | if_statinc_ref(ifp, if_oerrors); | | 1389 | if_statinc_ref(ifp, if_oerrors); |
1392 | continue; | | 1390 | continue; |
1393 | } | | 1391 | } |
1394 | /* Short on resources, just stop for now. */ | | 1392 | /* Short on resources, just stop for now. */ |
1395 | break; | | 1393 | break; |
1396 | } | | 1394 | } |
1397 | | | | |
1398 | if (dmamap->dm_nsegs > sc->sc_txfree) { | | 1395 | if (dmamap->dm_nsegs > sc->sc_txfree) { |
1399 | /* | | 1396 | /* |
1400 | * Not enough free descriptors to transmit this | | 1397 | * Not enough free descriptors to transmit this |
1401 | * packet. We haven't committed anything yet, | | 1398 | * packet. We haven't committed anything yet, |
1402 | * so just unload the DMA map, put the packet | | 1399 | * so just unload the DMA map, put the packet |
1403 | * back on the queue, and punt. | | 1400 | * back on the queue, and punt. |
1404 | */ | | 1401 | */ |
1405 | bus_dmamap_unload(sc->sc_dmat, dmamap); | | 1402 | bus_dmamap_unload(sc->sc_dmat, dmamap); |
1406 | break; | | 1403 | break; |
1407 | } | | 1404 | } |
1408 | | | 1405 | |
1409 | IFQ_DEQUEUE(&ifp->if_snd, m0); | | 1406 | IFQ_DEQUEUE(&ifp->if_snd, m0); |
1410 | | | | |
1411 | /* | | 1407 | /* |
1412 | * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET. | | 1408 | * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET. |
1413 | */ | | 1409 | */ |
1414 | | | | |
1415 | bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize, | | 1410 | bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize, |
1416 | BUS_DMASYNC_PREWRITE); | | 1411 | BUS_DMASYNC_PREWRITE); |
1417 | | | 1412 | |
1418 | tdes0 = 0; /* to postpone 1st segment T0_OWN write */ | | 1413 | tdes0 = 0; /* to postpone 1st segment T0_OWN write */ |
1419 | lasttx = -1; | | 1414 | lasttx = -1; |
1420 | for (nexttx = sc->sc_txnext, seg = 0; | | 1415 | for (nexttx = sc->sc_txnext, seg = 0; |
1421 | seg < dmamap->dm_nsegs; | | 1416 | seg < dmamap->dm_nsegs; |
1422 | seg++, nexttx = MD_NEXTTX(nexttx)) { | | 1417 | seg++, nexttx = MD_NEXTTX(nexttx)) { |
1423 | struct tdes *tdes = &sc->sc_txdescs[nexttx]; | | 1418 | struct tdes *tdes = &sc->sc_txdescs[nexttx]; |
1424 | bus_addr_t paddr = dmamap->dm_segs[seg].ds_addr; | | 1419 | bus_addr_t p = dmamap->dm_segs[seg].ds_addr; |
| | | 1420 | bus_size_t z = dmamap->dm_segs[seg].ds_len; |
1425 | /* | | 1421 | /* |
1426 | * If this is the first descriptor we're | | 1422 | * If this is the first descriptor we're |
1427 | * enqueueing, don't set the OWN bit just | | 1423 | * enqueueing, don't set the OWN bit just |
1428 | * yet. That could cause a race condition. | | 1424 | * yet. That could cause a race condition. |
1429 | * We'll do it below. | | 1425 | * We'll do it below. |
1430 | */ | | 1426 | */ |
1431 | tdes->t3 = htole32(dmamap->dm_segs[seg].ds_len); | | 1427 | tdes->t3 = htole32(z); |
1432 | tdes->t2 = htole32(BUS_ADDR_LO32(paddr)); | | 1428 | tdes->t2 = htole32(BUS_ADDR_LO32(p)); |
1433 | tdes->t1 = htole32(BUS_ADDR_HI32(paddr)); | | 1429 | tdes->t1 = htole32(BUS_ADDR_HI32(p)); |
1434 | tdes->t0 = htole32(tdes0 | (tdes->t0 & T0_LD) | | | 1430 | tdes->t0 &= htole32(T0_LD); |
| | | 1431 | tdes->t0 |= htole32(tdes0 | |
1435 | (15 << T0_TDRID) | T0_PT | | | 1432 | (15 << T0_TDRID) | T0_PT | |
1436 | sc->sc_t0cotso | T0_TRS); | | 1433 | sc->sc_t0cotso | T0_TRS); |
1437 | tdes0 = T0_OWN; /* 2nd and other segments */ | | 1434 | tdes0 = T0_OWN; /* 2nd and other segments */ |
1438 | /* NB; t0 DRID field contains zero */ | | 1435 | /* NB; t0 DRID field contains zero */ |
1439 | lasttx = nexttx; | | 1436 | lasttx = nexttx; |
1440 | } | | 1437 | } |
1441 | | | 1438 | |
| | | 1439 | /* HW lacks of per-frame xmit done interrupt control */ |
| | | 1440 | |
1442 | /* Write deferred 1st segment T0_OWN at the final stage */ | | 1441 | /* Write deferred 1st segment T0_OWN at the final stage */ |
1443 | sc->sc_txdescs[lasttx].t0 |= htole32(T0_LS); | | 1442 | sc->sc_txdescs[lasttx].t0 |= htole32(T0_LS); |
1444 | sc->sc_txdescs[sc->sc_txnext].t0 |= htole32(T0_FS | T0_OWN); | | 1443 | sc->sc_txdescs[sc->sc_txnext].t0 |= htole32(T0_FS | T0_OWN); |
1445 | SCX_CDTXSYNC(sc, sc->sc_txnext, dmamap->dm_nsegs, | | 1444 | SCX_CDTXSYNC(sc, sc->sc_txnext, dmamap->dm_nsegs, |
1446 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | | 1445 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); |
1447 | | | 1446 | |
1448 | /* submit one frame to xmit */ | | 1447 | /* submit one frame to xmit */ |
1449 | CSR_WRITE(sc, TXSUBMIT, 1); | | 1448 | CSR_WRITE(sc, TXSUBMIT, 1); |
1450 | | | 1449 | |
1451 | txs->txs_mbuf = m0; | | 1450 | txs->txs_mbuf = m0; |
1452 | txs->txs_firstdesc = sc->sc_txnext; | | 1451 | txs->txs_firstdesc = sc->sc_txnext; |
1453 | txs->txs_lastdesc = lasttx; | | 1452 | txs->txs_lastdesc = lasttx; |
1454 | txs->txs_ndesc = dmamap->dm_nsegs; | | 1453 | txs->txs_ndesc = dmamap->dm_nsegs; |
1455 | | | | |
1456 | sc->sc_txfree -= txs->txs_ndesc; | | 1454 | sc->sc_txfree -= txs->txs_ndesc; |
1457 | sc->sc_txnext = nexttx; | | 1455 | sc->sc_txnext = nexttx; |
1458 | sc->sc_txsfree--; | | 1456 | sc->sc_txsfree--; |
1459 | sc->sc_txsnext = MD_NEXTTXS(sc->sc_txsnext); | | 1457 | sc->sc_txsnext = MD_NEXTTXS(sc->sc_txsnext); |
1460 | /* | | 1458 | /* |
1461 | * Pass the packet to any BPF listeners. | | 1459 | * Pass the packet to any BPF listeners. |
1462 | */ | | 1460 | */ |
1463 | bpf_mtap(ifp, m0, BPF_D_OUT); | | 1461 | bpf_mtap(ifp, m0, BPF_D_OUT); |
1464 | } | | 1462 | } |
1465 | | | | |
1466 | if (sc->sc_txfree != ofree) { | | 1463 | if (sc->sc_txfree != ofree) { |
1467 | /* Set a watchdog timer in case the chip flakes out. */ | | 1464 | /* Set a watchdog timer in case the chip flakes out. */ |
1468 | ifp->if_timer = 5; | | 1465 | ifp->if_timer = 5; |
1469 | } | | 1466 | } |
1470 | } | | 1467 | } |
1471 | | | 1468 | |
1472 | #define EVENT_DEBUG 1 | | 1469 | #define EVENT_DEBUG 1 |
1473 | | | 1470 | |
1474 | static void | | 1471 | static void |
1475 | scx_watchdog(struct ifnet *ifp) | | 1472 | scx_watchdog(struct ifnet *ifp) |
1476 | { | | 1473 | { |
1477 | struct scx_softc *sc = ifp->if_softc; | | 1474 | struct scx_softc *sc = ifp->if_softc; |
1478 | | | 1475 | |
1479 | /* | | 1476 | /* |
1480 | * Since we're not interrupting every packet, sweep | | 1477 | * Since we're not interrupting every packet, sweep |
1481 | * up before we report an error. | | 1478 | * up before we report an error. |
1482 | */ | | 1479 | */ |
1483 | txreap(sc); | | 1480 | txreap(sc); |
1484 | | | 1481 | |
1485 | if (sc->sc_txfree != MD_NTXDESC) { | | 1482 | if (sc->sc_txfree != MD_NTXDESC) { |
1486 | aprint_error_dev(sc->sc_dev, | | 1483 | aprint_error_dev(sc->sc_dev, |
1487 | "device timeout (txfree %d txsfree %d txnext %d)\n", | | 1484 | "device timeout (txfree %d txsfree %d txnext %d)\n", |
1488 | sc->sc_txfree, sc->sc_txsfree, sc->sc_txnext); | | 1485 | sc->sc_txfree, sc->sc_txsfree, sc->sc_txnext); |
1489 | if_statinc(ifp, if_oerrors); | | 1486 | if_statinc(ifp, if_oerrors); |
1490 | #if EVENT_DEBUG == 1 | | 1487 | #if EVENT_DEBUG == 1 |
1491 | aprint_error_dev(sc->sc_dev, | | 1488 | aprint_error_dev(sc->sc_dev, |
1492 | "rx frames %d, octects %d, bcast %d, mcast %d\n", | | | |
1493 | mac_read(sc, GMACEVCNT(27)), | | | |
1494 | mac_read(sc, GMACEVCNT(28)), | | | |
1495 | mac_read(sc, GMACEVCNT(30)), | | | |
1496 | mac_read(sc, GMACEVCNT(31))); | | | |
1497 | aprint_error_dev(sc->sc_dev, | | | |
1498 | "tx frames %d, octects %d, bcast %d, mcast %d\n", | | 1489 | "tx frames %d, octects %d, bcast %d, mcast %d\n", |
1499 | mac_read(sc, GMACEVCNT(1)), | | 1490 | mac_read(sc, GMACEVCNT(1)), |
1500 | mac_read(sc, GMACEVCNT(0)), | | 1491 | mac_read(sc, GMACEVCNT(0)), |
1501 | mac_read(sc, GMACEVCNT(2)), | | 1492 | mac_read(sc, GMACEVCNT(2)), |
1502 | mac_read(sc, GMACEVCNT(3))); | | 1493 | mac_read(sc, GMACEVCNT(3))); |
1503 | aprint_error_dev(sc->sc_dev, | | 1494 | aprint_error_dev(sc->sc_dev, |
| | | 1495 | "rx frames %d, octects %d, bcast %d, mcast %d\n", |
| | | 1496 | mac_read(sc, GMACEVCNT(27)), |
| | | 1497 | mac_read(sc, GMACEVCNT(28)), |
| | | 1498 | mac_read(sc, GMACEVCNT(30)), |
| | | 1499 | mac_read(sc, GMACEVCNT(31))); |
| | | 1500 | aprint_error_dev(sc->sc_dev, |
1504 | "current tdes addr %x, buf addr %x\n", | | 1501 | "current tdes addr %x, buf addr %x\n", |
1505 | mac_read(sc, 0x1048), mac_read(sc, 0x1050)); | | 1502 | mac_read(sc, 0x1048), mac_read(sc, 0x1050)); |
1506 | aprint_error_dev(sc->sc_dev, | | 1503 | aprint_error_dev(sc->sc_dev, |
1507 | "current rdes addr %x, buf addr %x\n", | | 1504 | "current rdes addr %x, buf addr %x\n", |
1508 | mac_read(sc, 0x104c), mac_read(sc, 0x1054)); | | 1505 | mac_read(sc, 0x104c), mac_read(sc, 0x1054)); |
1509 | #endif | | 1506 | #endif |
1510 | /* Reset the interface. */ | | 1507 | /* Reset the interface. */ |
1511 | scx_init(ifp); | | 1508 | scx_init(ifp); |
1512 | } | | 1509 | } |
1513 | | | 1510 | |
1514 | scx_start(ifp); | | 1511 | scx_start(ifp); |
1515 | } | | 1512 | } |
1516 | | | 1513 | |
| @@ -1522,28 +1519,28 @@ scx_intr(void *arg) | | | @@ -1522,28 +1519,28 @@ scx_intr(void *arg) |
1522 | | | 1519 | |
1523 | status = CSR_READ(sc, xINTSR); /* not W1C */ | | 1520 | status = CSR_READ(sc, xINTSR); /* not W1C */ |
1524 | enable = CSR_READ(sc, xINTAEN); | | 1521 | enable = CSR_READ(sc, xINTAEN); |
1525 | if ((status & enable) == 0) | | 1522 | if ((status & enable) == 0) |
1526 | return 0; | | 1523 | return 0; |
1527 | if (status & (IRQ_TX | IRQ_RX)) { | | 1524 | if (status & (IRQ_TX | IRQ_RX)) { |
1528 | CSR_WRITE(sc, xINTAE_CLR, (IRQ_TX | IRQ_RX)); | | 1525 | CSR_WRITE(sc, xINTAE_CLR, (IRQ_TX | IRQ_RX)); |
1529 | | | 1526 | |
1530 | status = CSR_READ(sc, RXISR); | | 1527 | status = CSR_READ(sc, RXISR); |
1531 | CSR_WRITE(sc, RXISR, status); | | 1528 | CSR_WRITE(sc, RXISR, status); |
1532 | if (status & RXI_RC_ERR) | | 1529 | if (status & RXI_RC_ERR) |
1533 | aprint_error_dev(sc->sc_dev, "Rx error\n"); | | 1530 | aprint_error_dev(sc->sc_dev, "Rx error\n"); |
1534 | if (status & (RXI_PKTCNT | RXI_TMREXP)) { | | 1531 | if (status & (RXI_PKTCNT | RXI_TMREXP)) { |
1535 | rxintr(sc); | | 1532 | rxfill(sc); |
1536 | (void)CSR_READ(sc, RXDONECNT); /* clear RXI_RXDONE */ | | 1533 | (void)CSR_READ(sc, RXAVAILCNT); /* clear RXI_PKTCNT */ |
1537 | } | | 1534 | } |
1538 | | | 1535 | |
1539 | status = CSR_READ(sc, TXISR); | | 1536 | status = CSR_READ(sc, TXISR); |
1540 | CSR_WRITE(sc, TXISR, status); | | 1537 | CSR_WRITE(sc, TXISR, status); |
1541 | if (status & TXI_TR_ERR) | | 1538 | if (status & TXI_TR_ERR) |
1542 | aprint_error_dev(sc->sc_dev, "Tx error\n"); | | 1539 | aprint_error_dev(sc->sc_dev, "Tx error\n"); |
1543 | if (status & (TXI_TXDONE | TXI_TMREXP)) { | | 1540 | if (status & (TXI_TXDONE | TXI_TMREXP)) { |
1544 | txreap(sc); | | 1541 | txreap(sc); |
1545 | (void)CSR_READ(sc, TXDONECNT); /* clear TXI_TXDONE */ | | 1542 | (void)CSR_READ(sc, TXDONECNT); /* clear TXI_TXDONE */ |
1546 | } | | 1543 | } |
1547 | | | 1544 | |
1548 | CSR_WRITE(sc, xINTAE_SET, (IRQ_TX | IRQ_RX)); | | 1545 | CSR_WRITE(sc, xINTAE_SET, (IRQ_TX | IRQ_RX)); |
1549 | } | | 1546 | } |
| @@ -1576,133 +1573,128 @@ txreap(struct scx_softc *sc) | | | @@ -1576,133 +1573,128 @@ txreap(struct scx_softc *sc) |
1576 | sc->sc_txfree += txs->txs_ndesc; | | 1573 | sc->sc_txfree += txs->txs_ndesc; |
1577 | bus_dmamap_sync(sc->sc_dmat, txs->txs_dmamap, | | 1574 | bus_dmamap_sync(sc->sc_dmat, txs->txs_dmamap, |
1578 | 0, txs->txs_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE); | | 1575 | 0, txs->txs_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE); |
1579 | bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap); | | 1576 | bus_dmamap_unload(sc->sc_dmat, txs->txs_dmamap); |
1580 | m_freem(txs->txs_mbuf); | | 1577 | m_freem(txs->txs_mbuf); |
1581 | txs->txs_mbuf = NULL; | | 1578 | txs->txs_mbuf = NULL; |
1582 | } | | 1579 | } |
1583 | sc->sc_txsdirty = i; | | 1580 | sc->sc_txsdirty = i; |
1584 | if (sc->sc_txsfree == MD_TXQUEUELEN) | | 1581 | if (sc->sc_txsfree == MD_TXQUEUELEN) |
1585 | ifp->if_timer = 0; | | 1582 | ifp->if_timer = 0; |
1586 | } | | 1583 | } |
1587 | | | 1584 | |
1588 | static void | | 1585 | static void |
1589 | rxintr(struct scx_softc *sc) | | 1586 | rxfill(struct scx_softc *sc) |
1590 | { | | 1587 | { |
1591 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | | 1588 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; |
1592 | struct scx_rxsoft *rxs; | | 1589 | struct scx_rxsoft *rxs; |
1593 | struct mbuf *m; | | 1590 | struct mbuf *m; |
1594 | uint32_t rxstat; | | 1591 | uint32_t rxstat, rlen; |
1595 | int i, len; | | 1592 | int i; |
1596 | | | 1593 | |
1597 | for (i = sc->sc_rxptr; /*CONSTCOND*/ 1; i = MD_NEXTRX(i)) { | | 1594 | for (i = sc->sc_rxptr; /*CONSTCOND*/ 1; i = MD_NEXTRX(i)) { |
1598 | rxs = &sc->sc_rxsoft[i]; | | | |
1599 | | | | |
1600 | SCX_CDRXSYNC(sc, i, | | 1595 | SCX_CDRXSYNC(sc, i, |
1601 | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); | | 1596 | BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); |
1602 | | | 1597 | |
1603 | rxstat = le32toh(sc->sc_rxdescs[i].r0); | | 1598 | rxstat = le32toh(sc->sc_rxdescs[i].r0); |
1604 | if (rxstat & R0_OWN) /* desc is left empty */ | | 1599 | if (rxstat & R0_OWN) /* desc is left empty */ |
1605 | break; | | 1600 | break; |
1606 | | | 1601 | |
1607 | /* R0_FS | R0_LS must have been marked for this desc */ | | 1602 | /* received frame length in R3 31:16 */ |
| | | 1603 | rlen = le32toh(sc->sc_rxdescs[i].r3) >> 16; |
1608 | | | 1604 | |
| | | 1605 | /* R0_FS | R0_LS must have been marked for this desc */ |
| | | 1606 | rxs = &sc->sc_rxsoft[i]; |
1609 | bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, | | 1607 | bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, |
1610 | rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD); | | 1608 | rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD); |
1611 | | | 1609 | |
1612 | len = sc->sc_rxdescs[i].r3 >> 16; /* 31:16 received */ | | 1610 | /* dispense new storage to receive frame */ |
1613 | len -= ETHER_CRC_LEN; /* Trim CRC off */ | | | |
1614 | m = rxs->rxs_mbuf; | | 1611 | m = rxs->rxs_mbuf; |
1615 | | | | |
1616 | if (add_rxbuf(sc, i) != 0) { | | 1612 | if (add_rxbuf(sc, i) != 0) { |
1617 | if_statinc(ifp, if_ierrors); | | 1613 | if_statinc(ifp, if_ierrors); /* resource shortage */ |
1618 | SCX_INIT_RXDESC(sc, i); | | 1614 | SCX_INIT_RXDESC(sc, i); /* then reuse */ |
1619 | bus_dmamap_sync(sc->sc_dmat, | | 1615 | bus_dmamap_sync(sc->sc_dmat, |
1620 | rxs->rxs_dmamap, 0, | | 1616 | rxs->rxs_dmamap, 0, |
1621 | rxs->rxs_dmamap->dm_mapsize, | | 1617 | rxs->rxs_dmamap->dm_mapsize, |
1622 | BUS_DMASYNC_PREREAD); | | 1618 | BUS_DMASYNC_PREREAD); |
1623 | continue; | | 1619 | continue; |
1624 | } | | 1620 | } |
1625 | | | 1621 | /* complete mbuf */ |
1626 | m_set_rcvif(m, ifp); | | 1622 | m_set_rcvif(m, ifp); |
1627 | m->m_pkthdr.len = m->m_len = len; | | 1623 | m->m_pkthdr.len = m->m_len = rlen; |
1628 | | | 1624 | m->m_flags |= M_HASFCS; |
1629 | if (rxstat & R0_CSUM) { | | 1625 | if (rxstat & R0_CSUM) { |
1630 | uint32_t csum = M_CSUM_IPv4; | | 1626 | uint32_t csum = M_CSUM_IPv4; |
1631 | if (rxstat & R0_CERR) | | 1627 | if (rxstat & R0_CERR) |
1632 | csum |= M_CSUM_IPv4_BAD; | | 1628 | csum |= M_CSUM_IPv4_BAD; |
1633 | m->m_pkthdr.csum_flags |= csum; | | 1629 | m->m_pkthdr.csum_flags |= csum; |
1634 | } | | 1630 | } |
| | | 1631 | /* and pass to upper layer */ |
1635 | if_percpuq_enqueue(ifp->if_percpuq, m); | | 1632 | if_percpuq_enqueue(ifp->if_percpuq, m); |
1636 | } | | 1633 | } |
1637 | sc->sc_rxptr = i; | | 1634 | sc->sc_rxptr = i; |
1638 | } | | 1635 | } |
1639 | | | 1636 | |
1640 | static int | | 1637 | static int |
1641 | add_rxbuf(struct scx_softc *sc, int i) | | 1638 | add_rxbuf(struct scx_softc *sc, int i) |
1642 | { | | 1639 | { |
1643 | struct scx_rxsoft *rxs = &sc->sc_rxsoft[i]; | | 1640 | struct scx_rxsoft *rxs = &sc->sc_rxsoft[i]; |
1644 | struct mbuf *m; | | 1641 | struct mbuf *m; |
1645 | int error; | | 1642 | int error; |
1646 | | | 1643 | |
1647 | MGETHDR(m, M_DONTWAIT, MT_DATA); | | 1644 | MGETHDR(m, M_DONTWAIT, MT_DATA); |
1648 | if (m == NULL) | | 1645 | if (m == NULL) |
1649 | return ENOBUFS; | | 1646 | return ENOBUFS; |
1650 | | | | |
1651 | MCLGET(m, M_DONTWAIT); | | 1647 | MCLGET(m, M_DONTWAIT); |
1652 | if ((m->m_flags & M_EXT) == 0) { | | 1648 | if ((m->m_flags & M_EXT) == 0) { |
1653 | m_freem(m); | | 1649 | m_freem(m); |
1654 | return ENOBUFS; | | 1650 | return ENOBUFS; |
1655 | } | | 1651 | } |
1656 | | | | |
1657 | if (rxs->rxs_mbuf != NULL) | | 1652 | if (rxs->rxs_mbuf != NULL) |
1658 | bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap); | | 1653 | bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap); |
1659 | | | | |
1660 | rxs->rxs_mbuf = m; | | 1654 | rxs->rxs_mbuf = m; |
1661 | | | | |
1662 | error = bus_dmamap_load(sc->sc_dmat, rxs->rxs_dmamap, | | 1655 | error = bus_dmamap_load(sc->sc_dmat, rxs->rxs_dmamap, |
1663 | m->m_ext.ext_buf, m->m_ext.ext_size, NULL, BUS_DMA_NOWAIT); | | 1656 | m->m_ext.ext_buf, m->m_ext.ext_size, NULL, BUS_DMA_NOWAIT); |
1664 | if (error) { | | 1657 | if (error) { |
1665 | aprint_error_dev(sc->sc_dev, | | 1658 | aprint_error_dev(sc->sc_dev, |
1666 | "can't load rx DMA map %d, error = %d\n", i, error); | | 1659 | "can't load rx DMA map %d, error = %d\n", i, error); |
1667 | panic("add_rxbuf"); | | 1660 | panic("add_rxbuf"); |
1668 | } | | 1661 | } |
1669 | | | | |
1670 | bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, | | 1662 | bus_dmamap_sync(sc->sc_dmat, rxs->rxs_dmamap, 0, |
1671 | rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); | | 1663 | rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); |
1672 | SCX_INIT_RXDESC(sc, i); | | 1664 | SCX_INIT_RXDESC(sc, i); |
1673 | | | 1665 | |
1674 | return 0; | | 1666 | return 0; |
1675 | } | | 1667 | } |
1676 | | | 1668 | |
1677 | static void | | 1669 | static void |
1678 | rxdrain(struct scx_softc *sc) | | 1670 | rxdrain(struct scx_softc *sc) |
1679 | { | | 1671 | { |
1680 | struct scx_rxsoft *rxs; | | 1672 | struct scx_rxsoft *rxs; |
1681 | int i; | | 1673 | int i; |
1682 | | | 1674 | |
1683 | for (i = 0; i < MD_NRXDESC; i++) { | | 1675 | for (i = 0; i < MD_NRXDESC; i++) { |
1684 | rxs = &sc->sc_rxsoft[i]; | | 1676 | rxs = &sc->sc_rxsoft[i]; |
1685 | if (rxs->rxs_mbuf != NULL) { | | 1677 | if (rxs->rxs_mbuf != NULL) { |
1686 | bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap); | | 1678 | bus_dmamap_unload(sc->sc_dmat, rxs->rxs_dmamap); |
1687 | m_freem(rxs->rxs_mbuf); | | 1679 | m_freem(rxs->rxs_mbuf); |
1688 | rxs->rxs_mbuf = NULL; | | 1680 | rxs->rxs_mbuf = NULL; |
1689 | } | | 1681 | } |
1690 | } | | 1682 | } |
1691 | } | | 1683 | } |
1692 | | | 1684 | |
1693 | #define LINK_DEBUG 0 | | 1685 | #define LINK_DEBUG 0 |
1694 | | | 1686 | |
1695 | void | | 1687 | static void |
1696 | mii_statchg(struct ifnet *ifp) | | 1688 | mii_statchg(struct ifnet *ifp) |
1697 | { | | 1689 | { |
1698 | struct scx_softc *sc = ifp->if_softc; | | 1690 | struct scx_softc *sc = ifp->if_softc; |
1699 | struct mii_data *mii = &sc->sc_mii; | | 1691 | struct mii_data *mii = &sc->sc_mii; |
1700 | const int Mbps[4] = { 10, 100, 1000, 0 }; | | 1692 | const int Mbps[4] = { 10, 100, 1000, 0 }; |
1701 | uint32_t miisr, mcr, fcr; | | 1693 | uint32_t miisr, mcr, fcr; |
1702 | int spd; | | 1694 | int spd; |
1703 | | | 1695 | |
1704 | /* decode MIISR register value */ | | 1696 | /* decode MIISR register value */ |
1705 | miisr = mac_read(sc, GMACMIISR); | | 1697 | miisr = mac_read(sc, GMACMIISR); |
1706 | spd = Mbps[(miisr & MIISR_SPD) >> 1]; | | 1698 | spd = Mbps[(miisr & MIISR_SPD) >> 1]; |
1707 | #if LINK_DEBUG == 1 | | 1699 | #if LINK_DEBUG == 1 |
1708 | static uint32_t oldmiisr = 0; | | 1700 | static uint32_t oldmiisr = 0; |
| @@ -1818,87 +1810,91 @@ phy_tick(void *arg) | | | @@ -1818,87 +1810,91 @@ phy_tick(void *arg) |
1818 | struct mii_data *mii = &sc->sc_mii; | | 1810 | struct mii_data *mii = &sc->sc_mii; |
1819 | int s; | | 1811 | int s; |
1820 | | | 1812 | |
1821 | s = splnet(); | | 1813 | s = splnet(); |
1822 | mii_tick(mii); | | 1814 | mii_tick(mii); |
1823 | splx(s); | | 1815 | splx(s); |
1824 | #ifdef GMAC_EVENT_COUNTERS | | 1816 | #ifdef GMAC_EVENT_COUNTERS |
1825 | /* 80 event counters exist */ | | 1817 | /* 80 event counters exist */ |
1826 | #endif | | 1818 | #endif |
1827 | callout_schedule(&sc->sc_callout, hz); | | 1819 | callout_schedule(&sc->sc_callout, hz); |
1828 | } | | 1820 | } |
1829 | | | 1821 | |
1830 | static void | | 1822 | static void |
1831 | stopuengine(struct scx_softc *sc) | | 1823 | resetuengine(struct scx_softc *sc) |
1832 | { | | 1824 | { |
1833 | | | 1825 | |
1834 | if (CSR_READ(sc, CORESTAT) != 0) { | | 1826 | if (CSR_READ(sc, CORESTAT) == 0) { |
| | | 1827 | /* make sure to stop */ |
1835 | CSR_WRITE(sc, DMACTL_H2M, DMACTL_STOP); | | 1828 | CSR_WRITE(sc, DMACTL_H2M, DMACTL_STOP); |
1836 | CSR_WRITE(sc, DMACTL_M2H, DMACTL_STOP); | | 1829 | CSR_WRITE(sc, DMACTL_M2H, DMACTL_STOP); |
1837 | WAIT_FOR_CLR(sc, DMACTL_H2M, DMACTL_STOP, 0); | | 1830 | WAIT_FOR_CLR(sc, DMACTL_H2M, DMACTL_STOP); |
1838 | WAIT_FOR_CLR(sc, DMACTL_M2H, DMACTL_STOP, 0); | | 1831 | WAIT_FOR_CLR(sc, DMACTL_M2H, DMACTL_STOP); |
1839 | } | | 1832 | } |
1840 | CSR_WRITE(sc, SWRESET, 0); /* reset operation */ | | 1833 | CSR_WRITE(sc, SWRESET, 0); /* reset operation */ |
1841 | CSR_WRITE(sc, SWRESET, SRST_RUN); /* manifest run */ | | 1834 | CSR_WRITE(sc, SWRESET, SRST_RUN); /* manifest run */ |
1842 | CSR_WRITE(sc, COMINIT, INIT_DB | INIT_CLS); | | 1835 | CSR_WRITE(sc, COMINIT, INIT_DB | INIT_CLS); |
1843 | WAIT_FOR_CLR(sc, COMINIT, (INIT_DB | INIT_CLS), 0); | | 1836 | WAIT_FOR_CLR(sc, COMINIT, (INIT_DB | INIT_CLS)); |
1844 | } | | 1837 | } |
1845 | | | 1838 | |
1846 | static void | | 1839 | #define UCODE_DEBUG 0 |
1847 | startuengine(struct scx_softc *sc) | | | |
1848 | { | | | |
1849 | int err; | | | |
1850 | | | | |
1851 | CSR_WRITE(sc, CORESTAT, 0); | | | |
1852 | err = WAIT_FOR_SET(sc, xINTSR, IRQ_UCODE, 0); | | | |
1853 | if (err) { | | | |
1854 | aprint_error_dev(sc->sc_dev, "uengine start failed\n"); | | | |
1855 | } | | | |
1856 | CSR_WRITE(sc, xINTSR, IRQ_UCODE); | | | |
1857 | } | | | |
1858 | | | 1840 | |
1859 | /* | | 1841 | /* |
1860 | * 3 independent uengines exist to process host2media, media2host and | | 1842 | * 3 independent uengines exist to process host2media, media2host and |
1861 | * packet data flows. | | 1843 | * packet data flows. |
1862 | */ | | 1844 | */ |
1863 | static void | | 1845 | static void |
1864 | loaducode(struct scx_softc *sc) | | 1846 | loaducode(struct scx_softc *sc) |
1865 | { | | 1847 | { |
1866 | uint32_t up, lo, sz; | | 1848 | uint32_t up, lo, sz; |
1867 | uint64_t addr; | | 1849 | uint64_t addr; |
| | | 1850 | int err; |
1868 | | | 1851 | |
1869 | CSR_WRITE(sc, xINTSR, IRQ_UCODE); | | 1852 | CSR_WRITE(sc, xINTSR, IRQ_UCODE); |
1870 | | | 1853 | |
1871 | up = EE_READ(sc, 0x08); /* H->M ucode addr high */ | | 1854 | up = EE_READ(sc, 0x08); /* H->M ucode addr high */ |
1872 | lo = EE_READ(sc, 0x0c); /* H->M ucode addr low */ | | 1855 | lo = EE_READ(sc, 0x0c); /* H->M ucode addr low */ |
1873 | sz = EE_READ(sc, 0x10); /* H->M ucode size */ | | 1856 | sz = EE_READ(sc, 0x10); /* H->M ucode size */ |
1874 | sz *= 4; | | 1857 | sz *= 4; |
1875 | addr = ((uint64_t)up << 32) | lo; | | 1858 | addr = ((uint64_t)up << 32) | lo; |
1876 | aprint_normal_dev(sc->sc_dev, "0x%x H2M ucode %u\n", lo, sz); | | | |
1877 | injectucode(sc, UCODE_H2M, (bus_addr_t)addr, (bus_size_t)sz); | | 1859 | injectucode(sc, UCODE_H2M, (bus_addr_t)addr, (bus_size_t)sz); |
| | | 1860 | #if UCODE_DEBUG == 1 |
| | | 1861 | aprint_normal_dev(sc->sc_dev, "0x%x H2M ucode %u\n", lo, sz); |
| | | 1862 | #endif |
1878 | | | 1863 | |
1879 | up = EE_READ(sc, 0x14); /* M->H ucode addr high */ | | 1864 | up = EE_READ(sc, 0x14); /* M->H ucode addr high */ |
1880 | lo = EE_READ(sc, 0x18); /* M->H ucode addr low */ | | 1865 | lo = EE_READ(sc, 0x18); /* M->H ucode addr low */ |
1881 | sz = EE_READ(sc, 0x1c); /* M->H ucode size */ | | 1866 | sz = EE_READ(sc, 0x1c); /* M->H ucode size */ |
1882 | sz *= 4; | | 1867 | sz *= 4; |
1883 | addr = ((uint64_t)up << 32) | lo; | | 1868 | addr = ((uint64_t)up << 32) | lo; |
1884 | injectucode(sc, UCODE_M2H, (bus_addr_t)addr, (bus_size_t)sz); | | 1869 | injectucode(sc, UCODE_M2H, (bus_addr_t)addr, (bus_size_t)sz); |
| | | 1870 | #if UCODE_DEBUG == 1 |
1885 | aprint_normal_dev(sc->sc_dev, "0x%x M2H ucode %u\n", lo, sz); | | 1871 | aprint_normal_dev(sc->sc_dev, "0x%x M2H ucode %u\n", lo, sz); |
| | | 1872 | #endif |
1886 | | | 1873 | |
1887 | lo = EE_READ(sc, 0x20); /* PKT ucode addr */ | | 1874 | lo = EE_READ(sc, 0x20); /* PKT ucode addr */ |
1888 | sz = EE_READ(sc, 0x24); /* PKT ucode size */ | | 1875 | sz = EE_READ(sc, 0x24); /* PKT ucode size */ |
1889 | sz *= 4; | | 1876 | sz *= 4; |
1890 | injectucode(sc, UCODE_PKT, (bus_addr_t)lo, (bus_size_t)sz); | | 1877 | injectucode(sc, UCODE_PKT, (bus_addr_t)lo, (bus_size_t)sz); |
| | | 1878 | #if UCODE_DEBUG == 1 |
1891 | aprint_normal_dev(sc->sc_dev, "0x%x PKT ucode %u\n", lo, sz); | | 1879 | aprint_normal_dev(sc->sc_dev, "0x%x PKT ucode %u\n", lo, sz); |
| | | 1880 | #endif |
| | | 1881 | |
| | | 1882 | CSR_WRITE(sc, CORESTAT, 0); |
| | | 1883 | err = WAIT_FOR_SET(sc, xINTSR, IRQ_UCODE); |
| | | 1884 | if (err) { |
| | | 1885 | aprint_error_dev(sc->sc_dev, "uengine start failed\n"); |
| | | 1886 | } |
| | | 1887 | CSR_WRITE(sc, xINTSR, IRQ_UCODE); |
1892 | } | | 1888 | } |
1893 | | | 1889 | |
1894 | static void | | 1890 | static void |
1895 | injectucode(struct scx_softc *sc, int port, | | 1891 | injectucode(struct scx_softc *sc, int port, |
1896 | bus_addr_t addr, bus_size_t size) | | 1892 | bus_addr_t addr, bus_size_t size) |
1897 | { | | 1893 | { |
1898 | bus_space_handle_t bsh; | | 1894 | bus_space_handle_t bsh; |
1899 | bus_size_t off; | | 1895 | bus_size_t off; |
1900 | uint32_t ucode; | | 1896 | uint32_t ucode; |
1901 | | | 1897 | |
1902 | if (bus_space_map(sc->sc_st, addr, size, 0, &bsh) != 0) { | | 1898 | if (bus_space_map(sc->sc_st, addr, size, 0, &bsh) != 0) { |
1903 | aprint_error_dev(sc->sc_dev, | | 1899 | aprint_error_dev(sc->sc_dev, |
1904 | "eeprom map failure for ucode port 0x%x\n", port); | | 1900 | "eeprom map failure for ucode port 0x%x\n", port); |
| @@ -1922,27 +1918,27 @@ get_mdioclk(uint32_t freq) | | | @@ -1922,27 +1918,27 @@ get_mdioclk(uint32_t freq) |
1922 | if (freq < 60) | | 1918 | if (freq < 60) |
1923 | return GAR_MDIO_35_60MHZ; | | 1919 | return GAR_MDIO_35_60MHZ; |
1924 | if (freq < 100) | | 1920 | if (freq < 100) |
1925 | return GAR_MDIO_60_100MHZ; | | 1921 | return GAR_MDIO_60_100MHZ; |
1926 | if (freq < 150) | | 1922 | if (freq < 150) |
1927 | return GAR_MDIO_100_150MHZ; | | 1923 | return GAR_MDIO_100_150MHZ; |
1928 | if (freq < 250) | | 1924 | if (freq < 250) |
1929 | return GAR_MDIO_150_250MHZ; | | 1925 | return GAR_MDIO_150_250MHZ; |
1930 | return GAR_MDIO_250_300MHZ; | | 1926 | return GAR_MDIO_250_300MHZ; |
1931 | } | | 1927 | } |
1932 | | | 1928 | |
1933 | #define HWFEA_DEBUG 1 | | 1929 | #define HWFEA_DEBUG 1 |
1934 | | | 1930 | |
1935 | void | | 1931 | static void |
1936 | dump_hwfeature(struct scx_softc *sc) | | 1932 | dump_hwfeature(struct scx_softc *sc) |
1937 | { | | 1933 | { |
1938 | #if HWFEA_DEBUG == 1 | | 1934 | #if HWFEA_DEBUG == 1 |
1939 | struct { | | 1935 | struct { |
1940 | uint32_t bit; | | 1936 | uint32_t bit; |
1941 | const char *des; | | 1937 | const char *des; |
1942 | } field[] = { | | 1938 | } field[] = { |
1943 | { 27, "SA/VLAN insertion replacement enabled" }, | | 1939 | { 27, "SA/VLAN insertion replacement enabled" }, |
1944 | { 26, "flexible PPS enabled" }, | | 1940 | { 26, "flexible PPS enabled" }, |
1945 | { 25, "time stamping with internal system enabled" }, | | 1941 | { 25, "time stamping with internal system enabled" }, |
1946 | { 24, "alternate/enhanced descriptor enabled" }, | | 1942 | { 24, "alternate/enhanced descriptor enabled" }, |
1947 | { 19, "rx FIFO >2048 enabled" }, | | 1943 | { 19, "rx FIFO >2048 enabled" }, |
1948 | { 18, "type 2 IP checksum offload enabled" }, | | 1944 | { 18, "type 2 IP checksum offload enabled" }, |