match some more devices.diff -r1.33 -r1.34 src/sys/dev/pci/aac_pci.c
(chs)
--- src/sys/dev/pci/aac_pci.c 2011/09/29 12:51:28 1.33
+++ src/sys/dev/pci/aac_pci.c 2012/09/23 01:10:59 1.34
@@ -1,881 +1,897 @@ | @@ -1,881 +1,897 @@ | |||
1 | /* $NetBSD: aac_pci.c,v 1.33 2011/09/29 12:51:28 is Exp $ */ | 1 | /* $NetBSD: aac_pci.c,v 1.34 2012/09/23 01:10:59 chs Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2002 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2002 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 Andrew Doran. | 8 | * by Andrew Doran. | |
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. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | /*- | 32 | /*- | |
33 | * Copyright (c) 2000 Michael Smith | 33 | * Copyright (c) 2000 Michael Smith | |
34 | * Copyright (c) 2000 BSDi | 34 | * Copyright (c) 2000 BSDi | |
35 | * Copyright (c) 2000 Niklas Hallqvist | 35 | * Copyright (c) 2000 Niklas Hallqvist | |
36 | * All rights reserved. | 36 | * All rights reserved. | |
37 | * | 37 | * | |
38 | * Redistribution and use in source and binary forms, with or without | 38 | * Redistribution and use in source and binary forms, with or without | |
39 | * modification, are permitted provided that the following conditions | 39 | * modification, are permitted provided that the following conditions | |
40 | * are met: | 40 | * are met: | |
41 | * 1. Redistributions of source code must retain the above copyright | 41 | * 1. Redistributions of source code must retain the above copyright | |
42 | * notice, this list of conditions and the following disclaimer. | 42 | * notice, this list of conditions and the following disclaimer. | |
43 | * 2. Redistributions in binary form must reproduce the above copyright | 43 | * 2. Redistributions in binary form must reproduce the above copyright | |
44 | * notice, this list of conditions and the following disclaimer in the | 44 | * notice, this list of conditions and the following disclaimer in the | |
45 | * documentation and/or other materials provided with the distribution. | 45 | * documentation and/or other materials provided with the distribution. | |
46 | * | 46 | * | |
47 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | 47 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
48 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 48 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
49 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 49 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
50 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | 50 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
51 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 51 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
52 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 52 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
53 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 53 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
54 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 54 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
55 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 55 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
56 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 56 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
57 | * SUCH DAMAGE. | 57 | * SUCH DAMAGE. | |
58 | * | 58 | * | |
59 | * from FreeBSD: aac_pci.c,v 1.1 2000/09/13 03:20:34 msmith Exp | 59 | * from FreeBSD: aac_pci.c,v 1.1 2000/09/13 03:20:34 msmith Exp | |
60 | * via OpenBSD: aac_pci.c,v 1.7 2002/03/14 01:26:58 millert Exp | 60 | * via OpenBSD: aac_pci.c,v 1.7 2002/03/14 01:26:58 millert Exp | |
61 | */ | 61 | */ | |
62 | 62 | |||
63 | /* | 63 | /* | |
64 | * PCI front-end for the `aac' driver. | 64 | * PCI front-end for the `aac' driver. | |
65 | */ | 65 | */ | |
66 | 66 | |||
67 | #include <sys/cdefs.h> | 67 | #include <sys/cdefs.h> | |
68 | __KERNEL_RCSID(0, "$NetBSD: aac_pci.c,v 1.33 2011/09/29 12:51:28 is Exp $"); | 68 | __KERNEL_RCSID(0, "$NetBSD: aac_pci.c,v 1.34 2012/09/23 01:10:59 chs Exp $"); | |
69 | 69 | |||
70 | #include <sys/param.h> | 70 | #include <sys/param.h> | |
71 | #include <sys/systm.h> | 71 | #include <sys/systm.h> | |
72 | #include <sys/device.h> | 72 | #include <sys/device.h> | |
73 | #include <sys/kernel.h> | 73 | #include <sys/kernel.h> | |
74 | #include <sys/malloc.h> | 74 | #include <sys/malloc.h> | |
75 | #include <sys/queue.h> | 75 | #include <sys/queue.h> | |
76 | 76 | |||
77 | #include <sys/bus.h> | 77 | #include <sys/bus.h> | |
78 | #include <machine/endian.h> | 78 | #include <machine/endian.h> | |
79 | #include <sys/intr.h> | 79 | #include <sys/intr.h> | |
80 | 80 | |||
81 | #include <dev/pci/pcidevs.h> | 81 | #include <dev/pci/pcidevs.h> | |
82 | #include <dev/pci/pcireg.h> | 82 | #include <dev/pci/pcireg.h> | |
83 | #include <dev/pci/pcivar.h> | 83 | #include <dev/pci/pcivar.h> | |
84 | 84 | |||
85 | #include <dev/ic/aacreg.h> | 85 | #include <dev/ic/aacreg.h> | |
86 | #include <dev/ic/aacvar.h> | 86 | #include <dev/ic/aacvar.h> | |
87 | 87 | |||
88 | struct aac_pci_softc { | 88 | struct aac_pci_softc { | |
89 | struct aac_softc sc_aac; | 89 | struct aac_softc sc_aac; | |
90 | pci_chipset_tag_t sc_pc; | 90 | pci_chipset_tag_t sc_pc; | |
91 | pci_intr_handle_t sc_ih; | 91 | pci_intr_handle_t sc_ih; | |
92 | }; | 92 | }; | |
93 | 93 | |||
94 | /* i960Rx interface */ | 94 | /* i960Rx interface */ | |
95 | static int aac_rx_get_fwstatus(struct aac_softc *); | 95 | static int aac_rx_get_fwstatus(struct aac_softc *); | |
96 | static void aac_rx_qnotify(struct aac_softc *, int); | 96 | static void aac_rx_qnotify(struct aac_softc *, int); | |
97 | static int aac_rx_get_istatus(struct aac_softc *); | 97 | static int aac_rx_get_istatus(struct aac_softc *); | |
98 | static void aac_rx_clear_istatus(struct aac_softc *, int); | 98 | static void aac_rx_clear_istatus(struct aac_softc *, int); | |
99 | static void aac_rx_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t, | 99 | static void aac_rx_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t, | |
100 | u_int32_t, u_int32_t, u_int32_t); | 100 | u_int32_t, u_int32_t, u_int32_t); | |
101 | static uint32_t aac_rx_get_mailbox(struct aac_softc *, int); | 101 | static uint32_t aac_rx_get_mailbox(struct aac_softc *, int); | |
102 | static void aac_rx_set_interrupts(struct aac_softc *, int); | 102 | static void aac_rx_set_interrupts(struct aac_softc *, int); | |
103 | static int aac_rx_send_command(struct aac_softc *, struct aac_ccb *); | 103 | static int aac_rx_send_command(struct aac_softc *, struct aac_ccb *); | |
104 | static int aac_rx_get_outb_queue(struct aac_softc *); | 104 | static int aac_rx_get_outb_queue(struct aac_softc *); | |
105 | static void aac_rx_set_outb_queue(struct aac_softc *, int); | 105 | static void aac_rx_set_outb_queue(struct aac_softc *, int); | |
106 | 106 | |||
107 | /* StrongARM interface */ | 107 | /* StrongARM interface */ | |
108 | static int aac_sa_get_fwstatus(struct aac_softc *); | 108 | static int aac_sa_get_fwstatus(struct aac_softc *); | |
109 | static void aac_sa_qnotify(struct aac_softc *, int); | 109 | static void aac_sa_qnotify(struct aac_softc *, int); | |
110 | static int aac_sa_get_istatus(struct aac_softc *); | 110 | static int aac_sa_get_istatus(struct aac_softc *); | |
111 | static void aac_sa_clear_istatus(struct aac_softc *, int); | 111 | static void aac_sa_clear_istatus(struct aac_softc *, int); | |
112 | static void aac_sa_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t, | 112 | static void aac_sa_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t, | |
113 | u_int32_t, u_int32_t, u_int32_t); | 113 | u_int32_t, u_int32_t, u_int32_t); | |
114 | static uint32_t aac_sa_get_mailbox(struct aac_softc *, int); | 114 | static uint32_t aac_sa_get_mailbox(struct aac_softc *, int); | |
115 | static void aac_sa_set_interrupts(struct aac_softc *, int); | 115 | static void aac_sa_set_interrupts(struct aac_softc *, int); | |
116 | 116 | |||
117 | /* Rocket/MIPS interface */ | 117 | /* Rocket/MIPS interface */ | |
118 | static int aac_rkt_get_fwstatus(struct aac_softc *); | 118 | static int aac_rkt_get_fwstatus(struct aac_softc *); | |
119 | static void aac_rkt_qnotify(struct aac_softc *, int); | 119 | static void aac_rkt_qnotify(struct aac_softc *, int); | |
120 | static int aac_rkt_get_istatus(struct aac_softc *); | 120 | static int aac_rkt_get_istatus(struct aac_softc *); | |
121 | static void aac_rkt_clear_istatus(struct aac_softc *, int); | 121 | static void aac_rkt_clear_istatus(struct aac_softc *, int); | |
122 | static void aac_rkt_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t, | 122 | static void aac_rkt_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t, | |
123 | u_int32_t, u_int32_t, u_int32_t); | 123 | u_int32_t, u_int32_t, u_int32_t); | |
124 | static uint32_t aac_rkt_get_mailbox(struct aac_softc *, int); | 124 | static uint32_t aac_rkt_get_mailbox(struct aac_softc *, int); | |
125 | static void aac_rkt_set_interrupts(struct aac_softc *, int); | 125 | static void aac_rkt_set_interrupts(struct aac_softc *, int); | |
126 | static int aac_rkt_send_command(struct aac_softc *, struct aac_ccb *); | 126 | static int aac_rkt_send_command(struct aac_softc *, struct aac_ccb *); | |
127 | static int aac_rkt_get_outb_queue(struct aac_softc *); | 127 | static int aac_rkt_get_outb_queue(struct aac_softc *); | |
128 | static void aac_rkt_set_outb_queue(struct aac_softc *, int); | 128 | static void aac_rkt_set_outb_queue(struct aac_softc *, int); | |
129 | 129 | |||
130 | static const struct aac_interface aac_rx_interface = { | 130 | static const struct aac_interface aac_rx_interface = { | |
131 | aac_rx_get_fwstatus, | 131 | aac_rx_get_fwstatus, | |
132 | aac_rx_qnotify, | 132 | aac_rx_qnotify, | |
133 | aac_rx_get_istatus, | 133 | aac_rx_get_istatus, | |
134 | aac_rx_clear_istatus, | 134 | aac_rx_clear_istatus, | |
135 | aac_rx_set_mailbox, | 135 | aac_rx_set_mailbox, | |
136 | aac_rx_get_mailbox, | 136 | aac_rx_get_mailbox, | |
137 | aac_rx_set_interrupts, | 137 | aac_rx_set_interrupts, | |
138 | aac_rx_send_command, | 138 | aac_rx_send_command, | |
139 | aac_rx_get_outb_queue, | 139 | aac_rx_get_outb_queue, | |
140 | aac_rx_set_outb_queue | 140 | aac_rx_set_outb_queue | |
141 | }; | 141 | }; | |
142 | 142 | |||
143 | static const struct aac_interface aac_sa_interface = { | 143 | static const struct aac_interface aac_sa_interface = { | |
144 | aac_sa_get_fwstatus, | 144 | aac_sa_get_fwstatus, | |
145 | aac_sa_qnotify, | 145 | aac_sa_qnotify, | |
146 | aac_sa_get_istatus, | 146 | aac_sa_get_istatus, | |
147 | aac_sa_clear_istatus, | 147 | aac_sa_clear_istatus, | |
148 | aac_sa_set_mailbox, | 148 | aac_sa_set_mailbox, | |
149 | aac_sa_get_mailbox, | 149 | aac_sa_get_mailbox, | |
150 | aac_sa_set_interrupts, | 150 | aac_sa_set_interrupts, | |
151 | NULL, NULL, NULL | 151 | NULL, NULL, NULL | |
152 | }; | 152 | }; | |
153 | 153 | |||
154 | static const struct aac_interface aac_rkt_interface = { | 154 | static const struct aac_interface aac_rkt_interface = { | |
155 | aac_rkt_get_fwstatus, | 155 | aac_rkt_get_fwstatus, | |
156 | aac_rkt_qnotify, | 156 | aac_rkt_qnotify, | |
157 | aac_rkt_get_istatus, | 157 | aac_rkt_get_istatus, | |
158 | aac_rkt_clear_istatus, | 158 | aac_rkt_clear_istatus, | |
159 | aac_rkt_set_mailbox, | 159 | aac_rkt_set_mailbox, | |
160 | aac_rkt_get_mailbox, | 160 | aac_rkt_get_mailbox, | |
161 | aac_rkt_set_interrupts, | 161 | aac_rkt_set_interrupts, | |
162 | aac_rkt_send_command, | 162 | aac_rkt_send_command, | |
163 | aac_rkt_get_outb_queue, | 163 | aac_rkt_get_outb_queue, | |
164 | aac_rkt_set_outb_queue | 164 | aac_rkt_set_outb_queue | |
165 | }; | 165 | }; | |
166 | 166 | |||
167 | static struct aac_ident { | 167 | static struct aac_ident { | |
168 | u_short vendor; | 168 | u_short vendor; | |
169 | u_short device; | 169 | u_short device; | |
170 | u_short subvendor; | 170 | u_short subvendor; | |
171 | u_short subdevice; | 171 | u_short subdevice; | |
172 | u_short hwif; | 172 | u_short hwif; | |
173 | u_short quirks; | 173 | u_short quirks; | |
174 | const char *prodstr; | 174 | const char *prodstr; | |
175 | } const aac_ident[] = { | 175 | } const aac_ident[] = { | |
176 | { | 176 | { | |
177 | PCI_VENDOR_DELL, | 177 | PCI_VENDOR_DELL, | |
178 | PCI_PRODUCT_DELL_PERC_2SI, | 178 | PCI_PRODUCT_DELL_PERC_2SI, | |
179 | PCI_VENDOR_DELL, | 179 | PCI_VENDOR_DELL, | |
180 | PCI_PRODUCT_DELL_PERC_2SI, | 180 | PCI_PRODUCT_DELL_PERC_2SI, | |
181 | AAC_HWIF_I960RX, | 181 | AAC_HWIF_I960RX, | |
182 | 0, | 182 | 0, | |
183 | "Dell PERC 2/Si" | 183 | "Dell PERC 2/Si" | |
184 | }, | 184 | }, | |
185 | { | 185 | { | |
186 | PCI_VENDOR_DELL, | 186 | PCI_VENDOR_DELL, | |
187 | PCI_PRODUCT_DELL_PERC_3DI, | 187 | PCI_PRODUCT_DELL_PERC_3DI, | |
188 | PCI_VENDOR_DELL, | 188 | PCI_VENDOR_DELL, | |
189 | PCI_PRODUCT_DELL_PERC_3DI, | 189 | PCI_PRODUCT_DELL_PERC_3DI, | |
190 | AAC_HWIF_I960RX, | 190 | AAC_HWIF_I960RX, | |
191 | 0, | 191 | 0, | |
192 | "Dell PERC 3/Di" | 192 | "Dell PERC 3/Di" | |
193 | }, | 193 | }, | |
194 | { | 194 | { | |
195 | PCI_VENDOR_DELL, | 195 | PCI_VENDOR_DELL, | |
196 | PCI_PRODUCT_DELL_PERC_3DI, | 196 | PCI_PRODUCT_DELL_PERC_3DI, | |
197 | PCI_VENDOR_DELL, | 197 | PCI_VENDOR_DELL, | |
198 | PCI_PRODUCT_DELL_PERC_3DI_SUB2, | 198 | PCI_PRODUCT_DELL_PERC_3DI_SUB2, | |
199 | AAC_HWIF_I960RX, | 199 | AAC_HWIF_I960RX, | |
200 | 0, | 200 | 0, | |
201 | "Dell PERC 3/Di" | 201 | "Dell PERC 3/Di" | |
202 | }, | 202 | }, | |
203 | { | 203 | { | |
204 | PCI_VENDOR_DELL, | 204 | PCI_VENDOR_DELL, | |
205 | PCI_PRODUCT_DELL_PERC_3DI, | 205 | PCI_PRODUCT_DELL_PERC_3DI, | |
206 | PCI_VENDOR_DELL, | 206 | PCI_VENDOR_DELL, | |
207 | PCI_PRODUCT_DELL_PERC_3DI_SUB3, | 207 | PCI_PRODUCT_DELL_PERC_3DI_SUB3, | |
208 | AAC_HWIF_I960RX, | 208 | AAC_HWIF_I960RX, | |
209 | 0, | 209 | 0, | |
210 | "Dell PERC 3/Di" | 210 | "Dell PERC 3/Di" | |
211 | }, | 211 | }, | |
212 | { | 212 | { | |
213 | PCI_VENDOR_DELL, | 213 | PCI_VENDOR_DELL, | |
214 | PCI_PRODUCT_DELL_PERC_3DI_2, | 214 | PCI_PRODUCT_DELL_PERC_3DI_2, | |
215 | PCI_VENDOR_DELL, | 215 | PCI_VENDOR_DELL, | |
216 | PCI_PRODUCT_DELL_PERC_3DI_2_SUB, | 216 | PCI_PRODUCT_DELL_PERC_3DI_2_SUB, | |
217 | AAC_HWIF_I960RX, | 217 | AAC_HWIF_I960RX, | |
218 | 0, | 218 | 0, | |
219 | "Dell PERC 3/Di" | 219 | "Dell PERC 3/Di" | |
220 | }, | 220 | }, | |
221 | { | 221 | { | |
222 | PCI_VENDOR_DELL, | 222 | PCI_VENDOR_DELL, | |
223 | PCI_PRODUCT_DELL_PERC_3DI_3, | 223 | PCI_PRODUCT_DELL_PERC_3DI_3, | |
224 | PCI_VENDOR_DELL, | 224 | PCI_VENDOR_DELL, | |
225 | PCI_PRODUCT_DELL_PERC_3DI_3_SUB, | 225 | PCI_PRODUCT_DELL_PERC_3DI_3_SUB, | |
226 | AAC_HWIF_I960RX, | 226 | AAC_HWIF_I960RX, | |
227 | 0, | 227 | 0, | |
228 | "Dell PERC 3/Di" | 228 | "Dell PERC 3/Di" | |
229 | }, | 229 | }, | |
230 | { | 230 | { | |
231 | PCI_VENDOR_DELL, | 231 | PCI_VENDOR_DELL, | |
232 | PCI_PRODUCT_DELL_PERC_3DI_3, | 232 | PCI_PRODUCT_DELL_PERC_3DI_3, | |
233 | PCI_VENDOR_DELL, | 233 | PCI_VENDOR_DELL, | |
234 | PCI_PRODUCT_DELL_PERC_3DI_3_SUB2, | 234 | PCI_PRODUCT_DELL_PERC_3DI_3_SUB2, | |
235 | AAC_HWIF_I960RX, | 235 | AAC_HWIF_I960RX, | |
236 | 0, | 236 | 0, | |
237 | "Dell PERC 3/Di" | 237 | "Dell PERC 3/Di" | |
238 | }, | 238 | }, | |
239 | { | 239 | { | |
240 | PCI_VENDOR_DELL, | 240 | PCI_VENDOR_DELL, | |
241 | PCI_PRODUCT_DELL_PERC_3DI_3, | 241 | PCI_PRODUCT_DELL_PERC_3DI_3, | |
242 | PCI_VENDOR_DELL, | 242 | PCI_VENDOR_DELL, | |
243 | PCI_PRODUCT_DELL_PERC_3DI_3_SUB3, | 243 | PCI_PRODUCT_DELL_PERC_3DI_3_SUB3, | |
244 | AAC_HWIF_I960RX, | 244 | AAC_HWIF_I960RX, | |
245 | 0, | 245 | 0, | |
246 | "Dell PERC 3/Di" | 246 | "Dell PERC 3/Di" | |
247 | }, | 247 | }, | |
248 | { | 248 | { | |
249 | PCI_VENDOR_DELL, | 249 | PCI_VENDOR_DELL, | |
250 | PCI_PRODUCT_DELL_PERC_3SI, | 250 | PCI_PRODUCT_DELL_PERC_3SI, | |
251 | PCI_VENDOR_DELL, | 251 | PCI_VENDOR_DELL, | |
252 | PCI_PRODUCT_DELL_PERC_3SI, | 252 | PCI_PRODUCT_DELL_PERC_3SI, | |
253 | AAC_HWIF_I960RX, | 253 | AAC_HWIF_I960RX, | |
254 | 0, | 254 | 0, | |
255 | "Dell PERC 3/Si" | 255 | "Dell PERC 3/Si" | |
256 | }, | 256 | }, | |
257 | { | 257 | { | |
258 | PCI_VENDOR_DELL, | 258 | PCI_VENDOR_DELL, | |
259 | PCI_PRODUCT_DELL_PERC_3SI_2, | 259 | PCI_PRODUCT_DELL_PERC_3SI_2, | |
260 | PCI_VENDOR_DELL, | 260 | PCI_VENDOR_DELL, | |
261 | PCI_PRODUCT_DELL_PERC_3SI_2_SUB, | 261 | PCI_PRODUCT_DELL_PERC_3SI_2_SUB, | |
262 | AAC_HWIF_I960RX, | 262 | AAC_HWIF_I960RX, | |
263 | 0, | 263 | 0, | |
264 | "Dell PERC 3/Si" | 264 | "Dell PERC 3/Si" | |
265 | }, | 265 | }, | |
266 | { | 266 | { | |
267 | PCI_VENDOR_ADP2, | 267 | PCI_VENDOR_ADP2, | |
268 | PCI_PRODUCT_ADP2_ASR2200S, | 268 | PCI_PRODUCT_ADP2_ASR2200S, | |
269 | PCI_VENDOR_DELL, | 269 | PCI_VENDOR_DELL, | |
270 | PCI_PRODUCT_DELL_CERC_1_5, | 270 | PCI_PRODUCT_DELL_CERC_1_5, | |
271 | AAC_HWIF_I960RX, | 271 | AAC_HWIF_I960RX, | |
272 | AAC_QUIRK_NO4GB, | 272 | AAC_QUIRK_NO4GB, | |
273 | "Dell CERC SATA RAID 1.5/6ch" | 273 | "Dell CERC SATA RAID 1.5/6ch" | |
274 | }, | 274 | }, | |
275 | { | 275 | { | |
276 | PCI_VENDOR_ADP2, | 276 | PCI_VENDOR_ADP2, | |
277 | PCI_PRODUCT_ADP2_AAC2622, | 277 | PCI_PRODUCT_ADP2_AAC2622, | |
278 | PCI_VENDOR_ADP2, | 278 | PCI_VENDOR_ADP2, | |
279 | PCI_PRODUCT_ADP2_AAC2622, | 279 | PCI_PRODUCT_ADP2_AAC2622, | |
280 | AAC_HWIF_I960RX, | 280 | AAC_HWIF_I960RX, | |
281 | 0, | 281 | 0, | |
282 | "Adaptec ADP-2622" | 282 | "Adaptec ADP-2622" | |
283 | }, | 283 | }, | |
284 | { | 284 | { | |
285 | PCI_VENDOR_ADP2, | 285 | PCI_VENDOR_ADP2, | |
286 | PCI_PRODUCT_ADP2_ASR2200S, | 286 | PCI_PRODUCT_ADP2_ASR2200S, | |
287 | PCI_VENDOR_ADP2, | 287 | PCI_VENDOR_ADP2, | |
288 | PCI_PRODUCT_ADP2_ASR2200S_SUB2M, | 288 | PCI_PRODUCT_ADP2_ASR2200S_SUB2M, | |
289 | AAC_HWIF_I960RX, | 289 | AAC_HWIF_I960RX, | |
290 | AAC_QUIRK_NO4GB | AAC_QUIRK_256FIBS, | 290 | AAC_QUIRK_NO4GB | AAC_QUIRK_256FIBS, | |
291 | "Adaptec ASR-2200S" | 291 | "Adaptec ASR-2200S" | |
292 | }, | 292 | }, | |
293 | { | 293 | { | |
294 | PCI_VENDOR_ADP2, | 294 | PCI_VENDOR_ADP2, | |
295 | PCI_PRODUCT_ADP2_ASR2200S, | 295 | PCI_PRODUCT_ADP2_ASR2200S, | |
296 | PCI_VENDOR_DELL, | 296 | PCI_VENDOR_DELL, | |
297 | PCI_PRODUCT_ADP2_ASR2200S_SUB2M, | 297 | PCI_PRODUCT_ADP2_ASR2200S_SUB2M, | |
298 | AAC_HWIF_I960RX, | 298 | AAC_HWIF_I960RX, | |
299 | AAC_QUIRK_NO4GB | AAC_QUIRK_256FIBS, | 299 | AAC_QUIRK_NO4GB | AAC_QUIRK_256FIBS, | |
300 | "Dell PERC 320/DC" | 300 | "Dell PERC 320/DC" | |
301 | }, | 301 | }, | |
302 | { | 302 | { | |
303 | PCI_VENDOR_ADP2, | 303 | PCI_VENDOR_ADP2, | |
304 | PCI_PRODUCT_ADP2_ASR2200S, | 304 | PCI_PRODUCT_ADP2_ASR2200S, | |
305 | PCI_VENDOR_ADP2, | 305 | PCI_VENDOR_ADP2, | |
306 | PCI_PRODUCT_ADP2_ASR2200S, | 306 | PCI_PRODUCT_ADP2_ASR2200S, | |
307 | AAC_HWIF_I960RX, | 307 | AAC_HWIF_I960RX, | |
308 | AAC_QUIRK_NO4GB | AAC_QUIRK_256FIBS, | 308 | AAC_QUIRK_NO4GB | AAC_QUIRK_256FIBS, | |
309 | "Adaptec ASR-2200S" | 309 | "Adaptec ASR-2200S" | |
310 | }, | 310 | }, | |
311 | { | 311 | { | |
312 | PCI_VENDOR_ADP2, | 312 | PCI_VENDOR_ADP2, | |
313 | PCI_PRODUCT_ADP2_ASR2200S, | 313 | PCI_PRODUCT_ADP2_ASR2200S, | |
314 | PCI_VENDOR_ADP2, | 314 | PCI_VENDOR_ADP2, | |
315 | PCI_PRODUCT_ADP2_AAR2810SA, | 315 | PCI_PRODUCT_ADP2_AAR2810SA, | |
316 | AAC_HWIF_I960RX, | 316 | AAC_HWIF_I960RX, | |
317 | AAC_QUIRK_NO4GB, | 317 | AAC_QUIRK_NO4GB, | |
318 | "Adaptec AAR-2810SA" | 318 | "Adaptec AAR-2810SA" | |
319 | }, | 319 | }, | |
320 | { | 320 | { | |
321 | PCI_VENDOR_ADP2, | 321 | PCI_VENDOR_ADP2, | |
322 | PCI_PRODUCT_ADP2_ASR2200S, | 322 | PCI_PRODUCT_ADP2_ASR2200S, | |
323 | PCI_VENDOR_ADP2, | 323 | PCI_VENDOR_ADP2, | |
324 | PCI_PRODUCT_ADP2_ASR2120S, | 324 | PCI_PRODUCT_ADP2_ASR2120S, | |
325 | AAC_HWIF_I960RX, | 325 | AAC_HWIF_I960RX, | |
326 | AAC_QUIRK_NO4GB | AAC_QUIRK_256FIBS, | 326 | AAC_QUIRK_NO4GB | AAC_QUIRK_256FIBS, | |
327 | "Adaptec ASR-2120S" | 327 | "Adaptec ASR-2120S" | |
328 | }, | 328 | }, | |
329 | { | 329 | { | |
330 | PCI_VENDOR_ADP2, | 330 | PCI_VENDOR_ADP2, | |
331 | PCI_PRODUCT_ADP2_ASR2200S, | 331 | PCI_PRODUCT_ADP2_ASR2200S, | |
332 | PCI_VENDOR_ADP2, | 332 | PCI_VENDOR_ADP2, | |
333 | PCI_PRODUCT_ADP2_ASR2410SA, | 333 | PCI_PRODUCT_ADP2_ASR2410SA, | |
334 | AAC_HWIF_I960RX, | 334 | AAC_HWIF_I960RX, | |
335 | AAC_QUIRK_NO4GB, | 335 | AAC_QUIRK_NO4GB, | |
336 | "Adaptec ASR-2410SA" | 336 | "Adaptec ASR-2410SA" | |
337 | }, | 337 | }, | |
338 | { | 338 | { | |
339 | PCI_VENDOR_ADP2, | 339 | PCI_VENDOR_ADP2, | |
340 | PCI_PRODUCT_ADP2_ASR2200S, | 340 | PCI_PRODUCT_ADP2_ASR2200S, | |
341 | PCI_VENDOR_HP, | 341 | PCI_VENDOR_HP, | |
342 | PCI_PRODUCT_ADP2_HP_M110_G2, | 342 | PCI_PRODUCT_ADP2_HP_M110_G2, | |
343 | AAC_HWIF_I960RX, | 343 | AAC_HWIF_I960RX, | |
344 | AAC_QUIRK_NO4GB, | 344 | AAC_QUIRK_NO4GB, | |
345 | "HP ML110 G2 (Adaptec ASR-2610SA)" | 345 | "HP ML110 G2 (Adaptec ASR-2610SA)" | |
346 | }, | 346 | }, | |
347 | { | 347 | { | |
348 | PCI_VENDOR_ADP2, | 348 | PCI_VENDOR_ADP2, | |
349 | PCI_PRODUCT_ADP2_ASR2120S, | 349 | PCI_PRODUCT_ADP2_ASR2120S, | |
350 | PCI_VENDOR_IBM, | 350 | PCI_VENDOR_IBM, | |
351 | PCI_PRODUCT_IBM_SERVERAID8K, | 351 | PCI_PRODUCT_IBM_SERVERAID8K, | |
352 | AAC_HWIF_RKT, | 352 | AAC_HWIF_RKT, | |
353 | 0, | 353 | 0, | |
354 | "IBM ServeRAID 8k" | 354 | "IBM ServeRAID 8k" | |
355 | }, | 355 | }, | |
356 | { PCI_VENDOR_ADP2, | 356 | { PCI_VENDOR_ADP2, | |
357 | PCI_PRODUCT_ADP2_ASR2200S, | 357 | PCI_PRODUCT_ADP2_ASR2200S, | |
358 | PCI_VENDOR_ADP2, | 358 | PCI_VENDOR_ADP2, | |
359 | PCI_PRODUCT_ADP2_2405, | |||
360 | AAC_HWIF_I960RX, | |||
361 | 0, | |||
362 | "Adaptec RAID 2405" | |||
363 | }, | |||
364 | { PCI_VENDOR_ADP2, | |||
365 | PCI_PRODUCT_ADP2_ASR2200S, | |||
366 | PCI_VENDOR_ADP2, | |||
359 | PCI_PRODUCT_ADP2_3405, | 367 | PCI_PRODUCT_ADP2_3405, | |
360 | AAC_HWIF_I960RX, | 368 | AAC_HWIF_I960RX, | |
361 | 0, | 369 | 0, | |
362 | "Adaptec RAID 3405" | 370 | "Adaptec RAID 3405" | |
363 | }, | 371 | }, | |
372 | { PCI_VENDOR_ADP2, | |||
373 | PCI_PRODUCT_ADP2_ASR2200S, | |||
374 | PCI_VENDOR_ADP2, | |||
375 | PCI_PRODUCT_ADP2_3805, | |||
376 | AAC_HWIF_I960RX, | |||
377 | 0, | |||
378 | "Adaptec RAID 3805" | |||
379 | }, | |||
364 | { | 380 | { | |
365 | PCI_VENDOR_DEC, | 381 | PCI_VENDOR_DEC, | |
366 | PCI_PRODUCT_DEC_21554, | 382 | PCI_PRODUCT_DEC_21554, | |
367 | PCI_VENDOR_ADP2, | 383 | PCI_VENDOR_ADP2, | |
368 | PCI_PRODUCT_ADP2_AAC364, | 384 | PCI_PRODUCT_ADP2_AAC364, | |
369 | AAC_HWIF_STRONGARM, | 385 | AAC_HWIF_STRONGARM, | |
370 | 0, | 386 | 0, | |
371 | "Adaptec AAC-364" | 387 | "Adaptec AAC-364" | |
372 | }, | 388 | }, | |
373 | { | 389 | { | |
374 | PCI_VENDOR_DEC, | 390 | PCI_VENDOR_DEC, | |
375 | PCI_PRODUCT_DEC_21554, | 391 | PCI_PRODUCT_DEC_21554, | |
376 | PCI_VENDOR_ADP2, | 392 | PCI_VENDOR_ADP2, | |
377 | PCI_PRODUCT_ADP2_ASR5400S, | 393 | PCI_PRODUCT_ADP2_ASR5400S, | |
378 | AAC_HWIF_STRONGARM, | 394 | AAC_HWIF_STRONGARM, | |
379 | AAC_QUIRK_BROKEN_MMAP, | 395 | AAC_QUIRK_BROKEN_MMAP, | |
380 | "Adaptec ASR-5400S" | 396 | "Adaptec ASR-5400S" | |
381 | }, | 397 | }, | |
382 | { | 398 | { | |
383 | PCI_VENDOR_DEC, | 399 | PCI_VENDOR_DEC, | |
384 | PCI_PRODUCT_DEC_21554, | 400 | PCI_PRODUCT_DEC_21554, | |
385 | PCI_VENDOR_ADP2, | 401 | PCI_VENDOR_ADP2, | |
386 | PCI_PRODUCT_ADP2_PERC_2QC, | 402 | PCI_PRODUCT_ADP2_PERC_2QC, | |
387 | AAC_HWIF_STRONGARM, | 403 | AAC_HWIF_STRONGARM, | |
388 | AAC_QUIRK_PERC2QC, | 404 | AAC_QUIRK_PERC2QC, | |
389 | "Dell PERC 2/QC" | 405 | "Dell PERC 2/QC" | |
390 | }, | 406 | }, | |
391 | { | 407 | { | |
392 | PCI_VENDOR_DEC, | 408 | PCI_VENDOR_DEC, | |
393 | PCI_PRODUCT_DEC_21554, | 409 | PCI_PRODUCT_DEC_21554, | |
394 | PCI_VENDOR_ADP2, | 410 | PCI_VENDOR_ADP2, | |
395 | PCI_PRODUCT_ADP2_PERC_3QC, | 411 | PCI_PRODUCT_ADP2_PERC_3QC, | |
396 | AAC_HWIF_STRONGARM, | 412 | AAC_HWIF_STRONGARM, | |
397 | 0, | 413 | 0, | |
398 | "Dell PERC 3/QC" | 414 | "Dell PERC 3/QC" | |
399 | }, | 415 | }, | |
400 | { | 416 | { | |
401 | PCI_VENDOR_DEC, | 417 | PCI_VENDOR_DEC, | |
402 | PCI_PRODUCT_DEC_21554, | 418 | PCI_PRODUCT_DEC_21554, | |
403 | PCI_VENDOR_HP, | 419 | PCI_VENDOR_HP, | |
404 | PCI_PRODUCT_HP_NETRAID_4M, | 420 | PCI_PRODUCT_HP_NETRAID_4M, | |
405 | AAC_HWIF_STRONGARM, | 421 | AAC_HWIF_STRONGARM, | |
406 | 0, | 422 | 0, | |
407 | "HP NetRAID-4M" | 423 | "HP NetRAID-4M" | |
408 | }, | 424 | }, | |
409 | { | 425 | { | |
410 | PCI_VENDOR_ADP2, | 426 | PCI_VENDOR_ADP2, | |
411 | PCI_PRODUCT_ADP2_ASR2200S, | 427 | PCI_PRODUCT_ADP2_ASR2200S, | |
412 | PCI_VENDOR_SUN, | 428 | PCI_VENDOR_SUN, | |
413 | PCI_PRODUCT_ADP2_ASR2120S, | 429 | PCI_PRODUCT_ADP2_ASR2120S, | |
414 | AAC_HWIF_I960RX, | 430 | AAC_HWIF_I960RX, | |
415 | 0, | 431 | 0, | |
416 | "SG-XPCIESAS-R-IN" | 432 | "SG-XPCIESAS-R-IN" | |
417 | }, | 433 | }, | |
418 | }; | 434 | }; | |
419 | 435 | |||
420 | static const struct aac_ident * | 436 | static const struct aac_ident * | |
421 | aac_find_ident(struct pci_attach_args *pa) | 437 | aac_find_ident(struct pci_attach_args *pa) | |
422 | { | 438 | { | |
423 | const struct aac_ident *m, *mm; | 439 | const struct aac_ident *m, *mm; | |
424 | u_int32_t subsysid; | 440 | u_int32_t subsysid; | |
425 | 441 | |||
426 | m = aac_ident; | 442 | m = aac_ident; | |
427 | mm = aac_ident + (sizeof(aac_ident) / sizeof(aac_ident[0])); | 443 | mm = aac_ident + (sizeof(aac_ident) / sizeof(aac_ident[0])); | |
428 | 444 | |||
429 | while (m < mm) { | 445 | while (m < mm) { | |
430 | if (m->vendor == PCI_VENDOR(pa->pa_id) && | 446 | if (m->vendor == PCI_VENDOR(pa->pa_id) && | |
431 | m->device == PCI_PRODUCT(pa->pa_id)) { | 447 | m->device == PCI_PRODUCT(pa->pa_id)) { | |
432 | subsysid = pci_conf_read(pa->pa_pc, pa->pa_tag, | 448 | subsysid = pci_conf_read(pa->pa_pc, pa->pa_tag, | |
433 | PCI_SUBSYS_ID_REG); | 449 | PCI_SUBSYS_ID_REG); | |
434 | if (m->subvendor == PCI_VENDOR(subsysid) && | 450 | if (m->subvendor == PCI_VENDOR(subsysid) && | |
435 | m->subdevice == PCI_PRODUCT(subsysid)) | 451 | m->subdevice == PCI_PRODUCT(subsysid)) | |
436 | return (m); | 452 | return (m); | |
437 | } | 453 | } | |
438 | m++; | 454 | m++; | |
439 | } | 455 | } | |
440 | 456 | |||
441 | return (NULL); | 457 | return (NULL); | |
442 | } | 458 | } | |
443 | 459 | |||
444 | static int | 460 | static int | |
445 | aac_pci_intr_set(struct aac_softc *sc, int (*hand)(void*), void *arg) | 461 | aac_pci_intr_set(struct aac_softc *sc, int (*hand)(void*), void *arg) | |
446 | { | 462 | { | |
447 | struct aac_pci_softc *pcisc; | 463 | struct aac_pci_softc *pcisc; | |
448 | 464 | |||
449 | pcisc = (struct aac_pci_softc *) sc; | 465 | pcisc = (struct aac_pci_softc *) sc; | |
450 | 466 | |||
451 | pci_intr_disestablish(pcisc->sc_pc, sc->sc_ih); | 467 | pci_intr_disestablish(pcisc->sc_pc, sc->sc_ih); | |
452 | sc->sc_ih = pci_intr_establish(pcisc->sc_pc, pcisc->sc_ih, | 468 | sc->sc_ih = pci_intr_establish(pcisc->sc_pc, pcisc->sc_ih, | |
453 | IPL_BIO, hand, arg); | 469 | IPL_BIO, hand, arg); | |
454 | if (sc->sc_ih == NULL) { | 470 | if (sc->sc_ih == NULL) { | |
455 | return ENXIO; | 471 | return ENXIO; | |
456 | } | 472 | } | |
457 | return 0; | 473 | return 0; | |
458 | } | 474 | } | |
459 | 475 | |||
460 | static int | 476 | static int | |
461 | aac_pci_match(device_t parent, cfdata_t match, void *aux) | 477 | aac_pci_match(device_t parent, cfdata_t match, void *aux) | |
462 | { | 478 | { | |
463 | struct pci_attach_args *pa; | 479 | struct pci_attach_args *pa; | |
464 | 480 | |||
465 | pa = aux; | 481 | pa = aux; | |
466 | 482 | |||
467 | if (PCI_CLASS(pa->pa_class) == PCI_CLASS_I2O) | 483 | if (PCI_CLASS(pa->pa_class) == PCI_CLASS_I2O) | |
468 | return (0); | 484 | return (0); | |
469 | 485 | |||
470 | return (aac_find_ident(pa) != NULL); | 486 | return (aac_find_ident(pa) != NULL); | |
471 | } | 487 | } | |
472 | 488 | |||
473 | static void | 489 | static void | |
474 | aac_pci_attach(device_t parent, device_t self, void *aux) | 490 | aac_pci_attach(device_t parent, device_t self, void *aux) | |
475 | { | 491 | { | |
476 | struct pci_attach_args *pa; | 492 | struct pci_attach_args *pa; | |
477 | pci_chipset_tag_t pc; | 493 | pci_chipset_tag_t pc; | |
478 | struct aac_pci_softc *pcisc; | 494 | struct aac_pci_softc *pcisc; | |
479 | struct aac_softc *sc; | 495 | struct aac_softc *sc; | |
480 | u_int16_t command; | 496 | u_int16_t command; | |
481 | bus_addr_t membase; | 497 | bus_addr_t membase; | |
482 | bus_size_t memsize; | 498 | bus_size_t memsize; | |
483 | const char *intrstr; | 499 | const char *intrstr; | |
484 | int state; | 500 | int state; | |
485 | const struct aac_ident *m; | 501 | const struct aac_ident *m; | |
486 | 502 | |||
487 | pa = aux; | 503 | pa = aux; | |
488 | pc = pa->pa_pc; | 504 | pc = pa->pa_pc; | |
489 | pcisc = device_private(self); | 505 | pcisc = device_private(self); | |
490 | pcisc->sc_pc = pc; | 506 | pcisc->sc_pc = pc; | |
491 | sc = &pcisc->sc_aac; | 507 | sc = &pcisc->sc_aac; | |
492 | state = 0; | 508 | state = 0; | |
493 | 509 | |||
494 | aprint_naive(": RAID controller\n"); | 510 | aprint_naive(": RAID controller\n"); | |
495 | aprint_normal(": "); | 511 | aprint_normal(": "); | |
496 | 512 | |||
497 | /* | 513 | /* | |
498 | * Verify that the adapter is correctly set up in PCI space. | 514 | * Verify that the adapter is correctly set up in PCI space. | |
499 | */ | 515 | */ | |
500 | command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); | 516 | command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); | |
501 | command |= PCI_COMMAND_MASTER_ENABLE; | 517 | command |= PCI_COMMAND_MASTER_ENABLE; | |
502 | pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command); | 518 | pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command); | |
503 | command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); | 519 | command = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); | |
504 | AAC_DPRINTF(AAC_D_MISC, ("pci command status reg 0x08x ")); | 520 | AAC_DPRINTF(AAC_D_MISC, ("pci command status reg 0x08x ")); | |
505 | 521 | |||
506 | if ((command & PCI_COMMAND_MASTER_ENABLE) == 0) { | 522 | if ((command & PCI_COMMAND_MASTER_ENABLE) == 0) { | |
507 | aprint_error("can't enable bus-master feature\n"); | 523 | aprint_error("can't enable bus-master feature\n"); | |
508 | goto bail_out; | 524 | goto bail_out; | |
509 | } | 525 | } | |
510 | 526 | |||
511 | if ((command & PCI_COMMAND_MEM_ENABLE) == 0) { | 527 | if ((command & PCI_COMMAND_MEM_ENABLE) == 0) { | |
512 | aprint_error("memory window not available\n"); | 528 | aprint_error("memory window not available\n"); | |
513 | goto bail_out; | 529 | goto bail_out; | |
514 | } | 530 | } | |
515 | 531 | |||
516 | /* | 532 | /* | |
517 | * Map control/status registers. | 533 | * Map control/status registers. | |
518 | */ | 534 | */ | |
519 | if (pci_mapreg_map(pa, PCI_MAPREG_START, | 535 | if (pci_mapreg_map(pa, PCI_MAPREG_START, | |
520 | PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->sc_memt, | 536 | PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->sc_memt, | |
521 | &sc->sc_memh, &membase, &memsize)) { | 537 | &sc->sc_memh, &membase, &memsize)) { | |
522 | aprint_error("can't find mem space\n"); | 538 | aprint_error("can't find mem space\n"); | |
523 | goto bail_out; | 539 | goto bail_out; | |
524 | } | 540 | } | |
525 | state++; | 541 | state++; | |
526 | 542 | |||
527 | if (pci_intr_map(pa, &pcisc->sc_ih)) { | 543 | if (pci_intr_map(pa, &pcisc->sc_ih)) { | |
528 | aprint_error("couldn't map interrupt\n"); | 544 | aprint_error("couldn't map interrupt\n"); | |
529 | goto bail_out; | 545 | goto bail_out; | |
530 | } | 546 | } | |
531 | intrstr = pci_intr_string(pc, pcisc->sc_ih); | 547 | intrstr = pci_intr_string(pc, pcisc->sc_ih); | |
532 | sc->sc_ih = pci_intr_establish(pc, pcisc->sc_ih, IPL_BIO, aac_intr, sc); | 548 | sc->sc_ih = pci_intr_establish(pc, pcisc->sc_ih, IPL_BIO, aac_intr, sc); | |
533 | if (sc->sc_ih == NULL) { | 549 | if (sc->sc_ih == NULL) { | |
534 | aprint_error("couldn't establish interrupt"); | 550 | aprint_error("couldn't establish interrupt"); | |
535 | if (intrstr != NULL) | 551 | if (intrstr != NULL) | |
536 | aprint_error(" at %s", intrstr); | 552 | aprint_error(" at %s", intrstr); | |
537 | aprint_error("\n"); | 553 | aprint_error("\n"); | |
538 | goto bail_out; | 554 | goto bail_out; | |
539 | } | 555 | } | |
540 | state++; | 556 | state++; | |
541 | 557 | |||
542 | sc->sc_dmat = pa->pa_dmat; | 558 | sc->sc_dmat = pa->pa_dmat; | |
543 | 559 | |||
544 | m = aac_find_ident(pa); | 560 | m = aac_find_ident(pa); | |
545 | aprint_normal("%s\n", m->prodstr); | 561 | aprint_normal("%s\n", m->prodstr); | |
546 | if (intrstr != NULL) | 562 | if (intrstr != NULL) | |
547 | aprint_normal_dev(&sc->sc_dv, "interrupting at %s\n", | 563 | aprint_normal_dev(&sc->sc_dv, "interrupting at %s\n", | |
548 | intrstr); | 564 | intrstr); | |
549 | 565 | |||
550 | sc->sc_hwif = m->hwif; | 566 | sc->sc_hwif = m->hwif; | |
551 | sc->sc_quirks = m->quirks; | 567 | sc->sc_quirks = m->quirks; | |
552 | switch (sc->sc_hwif) { | 568 | switch (sc->sc_hwif) { | |
553 | case AAC_HWIF_I960RX: | 569 | case AAC_HWIF_I960RX: | |
554 | AAC_DPRINTF(AAC_D_MISC, | 570 | AAC_DPRINTF(AAC_D_MISC, | |
555 | ("set hardware up for i960Rx")); | 571 | ("set hardware up for i960Rx")); | |
556 | sc->sc_if = aac_rx_interface; | 572 | sc->sc_if = aac_rx_interface; | |
557 | break; | 573 | break; | |
558 | 574 | |||
559 | case AAC_HWIF_STRONGARM: | 575 | case AAC_HWIF_STRONGARM: | |
560 | AAC_DPRINTF(AAC_D_MISC, | 576 | AAC_DPRINTF(AAC_D_MISC, | |
561 | ("set hardware up for StrongARM")); | 577 | ("set hardware up for StrongARM")); | |
562 | sc->sc_if = aac_sa_interface; | 578 | sc->sc_if = aac_sa_interface; | |
563 | break; | 579 | break; | |
564 | 580 | |||
565 | case AAC_HWIF_RKT: | 581 | case AAC_HWIF_RKT: | |
566 | AAC_DPRINTF(AAC_D_MISC, | 582 | AAC_DPRINTF(AAC_D_MISC, | |
567 | ("set hardware up for MIPS/Rocket")); | 583 | ("set hardware up for MIPS/Rocket")); | |
568 | sc->sc_if = aac_rkt_interface; | 584 | sc->sc_if = aac_rkt_interface; | |
569 | break; | 585 | break; | |
570 | } | 586 | } | |
571 | sc->sc_regsize = memsize; | 587 | sc->sc_regsize = memsize; | |
572 | sc->sc_intr_set = aac_pci_intr_set; | 588 | sc->sc_intr_set = aac_pci_intr_set; | |
573 | 589 | |||
574 | if (!aac_attach(sc)) | 590 | if (!aac_attach(sc)) | |
575 | return; | 591 | return; | |
576 | 592 | |||
577 | bail_out: | 593 | bail_out: | |
578 | if (state > 1) | 594 | if (state > 1) | |
579 | pci_intr_disestablish(pc, sc->sc_ih); | 595 | pci_intr_disestablish(pc, sc->sc_ih); | |
580 | if (state > 0) | 596 | if (state > 0) | |
581 | bus_space_unmap(sc->sc_memt, sc->sc_memh, memsize); | 597 | bus_space_unmap(sc->sc_memt, sc->sc_memh, memsize); | |
582 | } | 598 | } | |
583 | 599 | |||
584 | CFATTACH_DECL(aac_pci, sizeof(struct aac_pci_softc), | 600 | CFATTACH_DECL(aac_pci, sizeof(struct aac_pci_softc), | |
585 | aac_pci_match, aac_pci_attach, NULL, NULL); | 601 | aac_pci_match, aac_pci_attach, NULL, NULL); | |
586 | 602 | |||
587 | /* | 603 | /* | |
588 | * Read the current firmware status word. | 604 | * Read the current firmware status word. | |
589 | */ | 605 | */ | |
590 | static int | 606 | static int | |
591 | aac_sa_get_fwstatus(struct aac_softc *sc) | 607 | aac_sa_get_fwstatus(struct aac_softc *sc) | |
592 | { | 608 | { | |
593 | 609 | |||
594 | return (AAC_GETREG4(sc, AAC_SA_FWSTATUS)); | 610 | return (AAC_GETREG4(sc, AAC_SA_FWSTATUS)); | |
595 | } | 611 | } | |
596 | 612 | |||
597 | static int | 613 | static int | |
598 | aac_rx_get_fwstatus(struct aac_softc *sc) | 614 | aac_rx_get_fwstatus(struct aac_softc *sc) | |
599 | { | 615 | { | |
600 | 616 | |||
601 | return (AAC_GETREG4(sc, AAC_RX_FWSTATUS)); | 617 | return (AAC_GETREG4(sc, AAC_RX_FWSTATUS)); | |
602 | } | 618 | } | |
603 | 619 | |||
604 | static int | 620 | static int | |
605 | aac_rkt_get_fwstatus(struct aac_softc *sc) | 621 | aac_rkt_get_fwstatus(struct aac_softc *sc) | |
606 | { | 622 | { | |
607 | 623 | |||
608 | return (AAC_GETREG4(sc, AAC_RKT_FWSTATUS)); | 624 | return (AAC_GETREG4(sc, AAC_RKT_FWSTATUS)); | |
609 | } | 625 | } | |
610 | 626 | |||
611 | /* | 627 | /* | |
612 | * Notify the controller of a change in a given queue | 628 | * Notify the controller of a change in a given queue | |
613 | */ | 629 | */ | |
614 | 630 | |||
615 | static void | 631 | static void | |
616 | aac_sa_qnotify(struct aac_softc *sc, int qbit) | 632 | aac_sa_qnotify(struct aac_softc *sc, int qbit) | |
617 | { | 633 | { | |
618 | 634 | |||
619 | AAC_SETREG2(sc, AAC_SA_DOORBELL1_SET, qbit); | 635 | AAC_SETREG2(sc, AAC_SA_DOORBELL1_SET, qbit); | |
620 | } | 636 | } | |
621 | 637 | |||
622 | static void | 638 | static void | |
623 | aac_rx_qnotify(struct aac_softc *sc, int qbit) | 639 | aac_rx_qnotify(struct aac_softc *sc, int qbit) | |
624 | { | 640 | { | |
625 | 641 | |||
626 | AAC_SETREG4(sc, AAC_RX_IDBR, qbit); | 642 | AAC_SETREG4(sc, AAC_RX_IDBR, qbit); | |
627 | } | 643 | } | |
628 | 644 | |||
629 | static void | 645 | static void | |
630 | aac_rkt_qnotify(struct aac_softc *sc, int qbit) | 646 | aac_rkt_qnotify(struct aac_softc *sc, int qbit) | |
631 | { | 647 | { | |
632 | 648 | |||
633 | AAC_SETREG4(sc, AAC_RKT_IDBR, qbit); | 649 | AAC_SETREG4(sc, AAC_RKT_IDBR, qbit); | |
634 | } | 650 | } | |
635 | 651 | |||
636 | /* | 652 | /* | |
637 | * Get the interrupt reason bits | 653 | * Get the interrupt reason bits | |
638 | */ | 654 | */ | |
639 | static int | 655 | static int | |
640 | aac_sa_get_istatus(struct aac_softc *sc) | 656 | aac_sa_get_istatus(struct aac_softc *sc) | |
641 | { | 657 | { | |
642 | 658 | |||
643 | return (AAC_GETREG2(sc, AAC_SA_DOORBELL0)); | 659 | return (AAC_GETREG2(sc, AAC_SA_DOORBELL0)); | |
644 | } | 660 | } | |
645 | 661 | |||
646 | static int | 662 | static int | |
647 | aac_rx_get_istatus(struct aac_softc *sc) | 663 | aac_rx_get_istatus(struct aac_softc *sc) | |
648 | { | 664 | { | |
649 | 665 | |||
650 | return (AAC_GETREG4(sc, AAC_RX_ODBR)); | 666 | return (AAC_GETREG4(sc, AAC_RX_ODBR)); | |
651 | } | 667 | } | |
652 | 668 | |||
653 | static int | 669 | static int | |
654 | aac_rkt_get_istatus(struct aac_softc *sc) | 670 | aac_rkt_get_istatus(struct aac_softc *sc) | |
655 | { | 671 | { | |
656 | 672 | |||
657 | return (AAC_GETREG4(sc, AAC_RKT_ODBR)); | 673 | return (AAC_GETREG4(sc, AAC_RKT_ODBR)); | |
658 | } | 674 | } | |
659 | 675 | |||
660 | /* | 676 | /* | |
661 | * Clear some interrupt reason bits | 677 | * Clear some interrupt reason bits | |
662 | */ | 678 | */ | |
663 | static void | 679 | static void | |
664 | aac_sa_clear_istatus(struct aac_softc *sc, int mask) | 680 | aac_sa_clear_istatus(struct aac_softc *sc, int mask) | |
665 | { | 681 | { | |
666 | 682 | |||
667 | AAC_SETREG2(sc, AAC_SA_DOORBELL0_CLEAR, mask); | 683 | AAC_SETREG2(sc, AAC_SA_DOORBELL0_CLEAR, mask); | |
668 | } | 684 | } | |
669 | 685 | |||
670 | static void | 686 | static void | |
671 | aac_rx_clear_istatus(struct aac_softc *sc, int mask) | 687 | aac_rx_clear_istatus(struct aac_softc *sc, int mask) | |
672 | { | 688 | { | |
673 | 689 | |||
674 | AAC_SETREG4(sc, AAC_RX_ODBR, mask); | 690 | AAC_SETREG4(sc, AAC_RX_ODBR, mask); | |
675 | } | 691 | } | |
676 | 692 | |||
677 | static void | 693 | static void | |
678 | aac_rkt_clear_istatus(struct aac_softc *sc, int mask) | 694 | aac_rkt_clear_istatus(struct aac_softc *sc, int mask) | |
679 | { | 695 | { | |
680 | 696 | |||
681 | AAC_SETREG4(sc, AAC_RKT_ODBR, mask); | 697 | AAC_SETREG4(sc, AAC_RKT_ODBR, mask); | |
682 | } | 698 | } | |
683 | 699 | |||
684 | /* | 700 | /* | |
685 | * Populate the mailbox and set the command word | 701 | * Populate the mailbox and set the command word | |
686 | */ | 702 | */ | |
687 | static void | 703 | static void | |
688 | aac_sa_set_mailbox(struct aac_softc *sc, u_int32_t command, | 704 | aac_sa_set_mailbox(struct aac_softc *sc, u_int32_t command, | |
689 | u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, | 705 | u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, | |
690 | u_int32_t arg3) | 706 | u_int32_t arg3) | |
691 | { | 707 | { | |
692 | 708 | |||
693 | AAC_SETREG4(sc, AAC_SA_MAILBOX, command); | 709 | AAC_SETREG4(sc, AAC_SA_MAILBOX, command); | |
694 | AAC_SETREG4(sc, AAC_SA_MAILBOX + 4, arg0); | 710 | AAC_SETREG4(sc, AAC_SA_MAILBOX + 4, arg0); | |
695 | AAC_SETREG4(sc, AAC_SA_MAILBOX + 8, arg1); | 711 | AAC_SETREG4(sc, AAC_SA_MAILBOX + 8, arg1); | |
696 | AAC_SETREG4(sc, AAC_SA_MAILBOX + 12, arg2); | 712 | AAC_SETREG4(sc, AAC_SA_MAILBOX + 12, arg2); | |
697 | AAC_SETREG4(sc, AAC_SA_MAILBOX + 16, arg3); | 713 | AAC_SETREG4(sc, AAC_SA_MAILBOX + 16, arg3); | |
698 | } | 714 | } | |
699 | 715 | |||
700 | static void | 716 | static void | |
701 | aac_rx_set_mailbox(struct aac_softc *sc, u_int32_t command, | 717 | aac_rx_set_mailbox(struct aac_softc *sc, u_int32_t command, | |
702 | u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, | 718 | u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, | |
703 | u_int32_t arg3) | 719 | u_int32_t arg3) | |
704 | { | 720 | { | |
705 | 721 | |||
706 | AAC_SETREG4(sc, AAC_RX_MAILBOX, command); | 722 | AAC_SETREG4(sc, AAC_RX_MAILBOX, command); | |
707 | AAC_SETREG4(sc, AAC_RX_MAILBOX + 4, arg0); | 723 | AAC_SETREG4(sc, AAC_RX_MAILBOX + 4, arg0); | |
708 | AAC_SETREG4(sc, AAC_RX_MAILBOX + 8, arg1); | 724 | AAC_SETREG4(sc, AAC_RX_MAILBOX + 8, arg1); | |
709 | AAC_SETREG4(sc, AAC_RX_MAILBOX + 12, arg2); | 725 | AAC_SETREG4(sc, AAC_RX_MAILBOX + 12, arg2); | |
710 | AAC_SETREG4(sc, AAC_RX_MAILBOX + 16, arg3); | 726 | AAC_SETREG4(sc, AAC_RX_MAILBOX + 16, arg3); | |
711 | } | 727 | } | |
712 | 728 | |||
713 | static void | 729 | static void | |
714 | aac_rkt_set_mailbox(struct aac_softc *sc, u_int32_t command, | 730 | aac_rkt_set_mailbox(struct aac_softc *sc, u_int32_t command, | |
715 | u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, | 731 | u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, | |
716 | u_int32_t arg3) | 732 | u_int32_t arg3) | |
717 | { | 733 | { | |
718 | 734 | |||
719 | AAC_SETREG4(sc, AAC_RKT_MAILBOX, command); | 735 | AAC_SETREG4(sc, AAC_RKT_MAILBOX, command); | |
720 | AAC_SETREG4(sc, AAC_RKT_MAILBOX + 4, arg0); | 736 | AAC_SETREG4(sc, AAC_RKT_MAILBOX + 4, arg0); | |
721 | AAC_SETREG4(sc, AAC_RKT_MAILBOX + 8, arg1); | 737 | AAC_SETREG4(sc, AAC_RKT_MAILBOX + 8, arg1); | |
722 | AAC_SETREG4(sc, AAC_RKT_MAILBOX + 12, arg2); | 738 | AAC_SETREG4(sc, AAC_RKT_MAILBOX + 12, arg2); | |
723 | AAC_SETREG4(sc, AAC_RKT_MAILBOX + 16, arg3); | 739 | AAC_SETREG4(sc, AAC_RKT_MAILBOX + 16, arg3); | |
724 | } | 740 | } | |
725 | 741 | |||
726 | /* | 742 | /* | |
727 | * Fetch the specified mailbox | 743 | * Fetch the specified mailbox | |
728 | */ | 744 | */ | |
729 | static uint32_t | 745 | static uint32_t | |
730 | aac_sa_get_mailbox(struct aac_softc *sc, int mb) | 746 | aac_sa_get_mailbox(struct aac_softc *sc, int mb) | |
731 | { | 747 | { | |
732 | 748 | |||
733 | return (AAC_GETREG4(sc, AAC_SA_MAILBOX + (mb * 4))); | 749 | return (AAC_GETREG4(sc, AAC_SA_MAILBOX + (mb * 4))); | |
734 | } | 750 | } | |
735 | 751 | |||
736 | static uint32_t | 752 | static uint32_t | |
737 | aac_rx_get_mailbox(struct aac_softc *sc, int mb) | 753 | aac_rx_get_mailbox(struct aac_softc *sc, int mb) | |
738 | { | 754 | { | |
739 | 755 | |||
740 | return (AAC_GETREG4(sc, AAC_RX_MAILBOX + (mb * 4))); | 756 | return (AAC_GETREG4(sc, AAC_RX_MAILBOX + (mb * 4))); | |
741 | } | 757 | } | |
742 | 758 | |||
743 | static uint32_t | 759 | static uint32_t | |
744 | aac_rkt_get_mailbox(struct aac_softc *sc, int mb) | 760 | aac_rkt_get_mailbox(struct aac_softc *sc, int mb) | |
745 | { | 761 | { | |
746 | 762 | |||
747 | return (AAC_GETREG4(sc, AAC_RKT_MAILBOX + (mb * 4))); | 763 | return (AAC_GETREG4(sc, AAC_RKT_MAILBOX + (mb * 4))); | |
748 | } | 764 | } | |
749 | 765 | |||
750 | /* | 766 | /* | |
751 | * Set/clear interrupt masks | 767 | * Set/clear interrupt masks | |
752 | */ | 768 | */ | |
753 | static void | 769 | static void | |
754 | aac_sa_set_interrupts(struct aac_softc *sc, int enable) | 770 | aac_sa_set_interrupts(struct aac_softc *sc, int enable) | |
755 | { | 771 | { | |
756 | 772 | |||
757 | if (enable) | 773 | if (enable) | |
758 | AAC_SETREG2((sc), AAC_SA_MASK0_CLEAR, AAC_DB_INTERRUPTS); | 774 | AAC_SETREG2((sc), AAC_SA_MASK0_CLEAR, AAC_DB_INTERRUPTS); | |
759 | else | 775 | else | |
760 | AAC_SETREG2((sc), AAC_SA_MASK0_SET, ~0); | 776 | AAC_SETREG2((sc), AAC_SA_MASK0_SET, ~0); | |
761 | } | 777 | } | |
762 | 778 | |||
763 | static void | 779 | static void | |
764 | aac_rx_set_interrupts(struct aac_softc *sc, int enable) | 780 | aac_rx_set_interrupts(struct aac_softc *sc, int enable) | |
765 | { | 781 | { | |
766 | 782 | |||
767 | if (enable) { | 783 | if (enable) { | |
768 | if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) | 784 | if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) | |
769 | AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INT_NEW_COMM); | 785 | AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INT_NEW_COMM); | |
770 | else | 786 | else | |
771 | AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INTERRUPTS); | 787 | AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INTERRUPTS); | |
772 | } else { | 788 | } else { | |
773 | AAC_SETREG4(sc, AAC_RX_OIMR, ~0); | 789 | AAC_SETREG4(sc, AAC_RX_OIMR, ~0); | |
774 | } | 790 | } | |
775 | } | 791 | } | |
776 | 792 | |||
777 | static void | 793 | static void | |
778 | aac_rkt_set_interrupts(struct aac_softc *sc, int enable) | 794 | aac_rkt_set_interrupts(struct aac_softc *sc, int enable) | |
779 | { | 795 | { | |
780 | 796 | |||
781 | if (enable) { | 797 | if (enable) { | |
782 | if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) | 798 | if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) | |
783 | AAC_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INT_NEW_COMM); | 799 | AAC_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INT_NEW_COMM); | |
784 | else | 800 | else | |
785 | AAC_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INTERRUPTS); | 801 | AAC_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INTERRUPTS); | |
786 | } else { | 802 | } else { | |
787 | AAC_SETREG4(sc, AAC_RKT_OIMR, ~0); | 803 | AAC_SETREG4(sc, AAC_RKT_OIMR, ~0); | |
788 | } | 804 | } | |
789 | } | 805 | } | |
790 | 806 | |||
791 | /* | 807 | /* | |
792 | * New comm. interface: Send command functions | 808 | * New comm. interface: Send command functions | |
793 | */ | 809 | */ | |
794 | static int | 810 | static int | |
795 | aac_rx_send_command(struct aac_softc *sc, struct aac_ccb *ac) | 811 | aac_rx_send_command(struct aac_softc *sc, struct aac_ccb *ac) | |
796 | { | 812 | { | |
797 | u_int32_t index, device; | 813 | u_int32_t index, device; | |
798 | 814 | |||
799 | index = AAC_GETREG4(sc, AAC_RX_IQUE); | 815 | index = AAC_GETREG4(sc, AAC_RX_IQUE); | |
800 | if (index == 0xffffffffL) | 816 | if (index == 0xffffffffL) | |
801 | index = AAC_GETREG4(sc, AAC_RX_IQUE); | 817 | index = AAC_GETREG4(sc, AAC_RX_IQUE); | |
802 | if (index == 0xffffffffL) | 818 | if (index == 0xffffffffL) | |
803 | return index; | 819 | return index; | |
804 | #ifdef notyet | 820 | #ifdef notyet | |
805 | aac_enqueue_busy(ac); | 821 | aac_enqueue_busy(ac); | |
806 | #endif | 822 | #endif | |
807 | device = index; | 823 | device = index; | |
808 | AAC_SETREG4(sc, device, | 824 | AAC_SETREG4(sc, device, | |
809 | htole32((u_int32_t)(ac->ac_fibphys & 0xffffffffUL))); | 825 | htole32((u_int32_t)(ac->ac_fibphys & 0xffffffffUL))); | |
810 | device += 4; | 826 | device += 4; | |
811 | if (sizeof(bus_addr_t) > 4) { | 827 | if (sizeof(bus_addr_t) > 4) { | |
812 | AAC_SETREG4(sc, device, | 828 | AAC_SETREG4(sc, device, | |
813 | htole32((u_int32_t)((u_int64_t)ac->ac_fibphys >> 32))); | 829 | htole32((u_int32_t)((u_int64_t)ac->ac_fibphys >> 32))); | |
814 | } else { | 830 | } else { | |
815 | AAC_SETREG4(sc, device, 0); | 831 | AAC_SETREG4(sc, device, 0); | |
816 | } | 832 | } | |
817 | device += 4; | 833 | device += 4; | |
818 | AAC_SETREG4(sc, device, ac->ac_fib->Header.Size); | 834 | AAC_SETREG4(sc, device, ac->ac_fib->Header.Size); | |
819 | AAC_SETREG4(sc, AAC_RX_IQUE, index); | 835 | AAC_SETREG4(sc, AAC_RX_IQUE, index); | |
820 | return 0; | 836 | return 0; | |
821 | } | 837 | } | |
822 | 838 | |||
823 | static int | 839 | static int | |
824 | aac_rkt_send_command(struct aac_softc *sc, struct aac_ccb *ac) | 840 | aac_rkt_send_command(struct aac_softc *sc, struct aac_ccb *ac) | |
825 | { | 841 | { | |
826 | u_int32_t index, device; | 842 | u_int32_t index, device; | |
827 | 843 | |||
828 | index = AAC_GETREG4(sc, AAC_RKT_IQUE); | 844 | index = AAC_GETREG4(sc, AAC_RKT_IQUE); | |
829 | if (index == 0xffffffffL) | 845 | if (index == 0xffffffffL) | |
830 | index = AAC_GETREG4(sc, AAC_RKT_IQUE); | 846 | index = AAC_GETREG4(sc, AAC_RKT_IQUE); | |
831 | if (index == 0xffffffffL) | 847 | if (index == 0xffffffffL) | |
832 | return index; | 848 | return index; | |
833 | #ifdef notyet | 849 | #ifdef notyet | |
834 | aac_enqueue_busy(ac); | 850 | aac_enqueue_busy(ac); | |
835 | #endif | 851 | #endif | |
836 | device = index; | 852 | device = index; | |
837 | AAC_SETREG4(sc, device, | 853 | AAC_SETREG4(sc, device, | |
838 | htole32((u_int32_t)(ac->ac_fibphys & 0xffffffffUL))); | 854 | htole32((u_int32_t)(ac->ac_fibphys & 0xffffffffUL))); | |
839 | device += 4; | 855 | device += 4; | |
840 | if (sizeof(bus_addr_t) > 4) { | 856 | if (sizeof(bus_addr_t) > 4) { | |
841 | AAC_SETREG4(sc, device, | 857 | AAC_SETREG4(sc, device, | |
842 | htole32((u_int32_t)((u_int64_t)ac->ac_fibphys >> 32))); | 858 | htole32((u_int32_t)((u_int64_t)ac->ac_fibphys >> 32))); | |
843 | } else { | 859 | } else { | |
844 | AAC_SETREG4(sc, device, 0); | 860 | AAC_SETREG4(sc, device, 0); | |
845 | } | 861 | } | |
846 | device += 4; | 862 | device += 4; | |
847 | AAC_SETREG4(sc, device, ac->ac_fib->Header.Size); | 863 | AAC_SETREG4(sc, device, ac->ac_fib->Header.Size); | |
848 | AAC_SETREG4(sc, AAC_RKT_IQUE, index); | 864 | AAC_SETREG4(sc, AAC_RKT_IQUE, index); | |
849 | return 0; | 865 | return 0; | |
850 | } | 866 | } | |
851 | 867 | |||
852 | /* | 868 | /* | |
853 | * New comm. interface: get, set outbound queue index | 869 | * New comm. interface: get, set outbound queue index | |
854 | */ | 870 | */ | |
855 | static int | 871 | static int | |
856 | aac_rx_get_outb_queue(struct aac_softc *sc) | 872 | aac_rx_get_outb_queue(struct aac_softc *sc) | |
857 | { | 873 | { | |
858 | 874 | |||
859 | return AAC_GETREG4(sc, AAC_RX_OQUE); | 875 | return AAC_GETREG4(sc, AAC_RX_OQUE); | |
860 | } | 876 | } | |
861 | 877 | |||
862 | static int | 878 | static int | |
863 | aac_rkt_get_outb_queue(struct aac_softc *sc) | 879 | aac_rkt_get_outb_queue(struct aac_softc *sc) | |
864 | { | 880 | { | |
865 | 881 | |||
866 | return AAC_GETREG4(sc, AAC_RKT_OQUE); | 882 | return AAC_GETREG4(sc, AAC_RKT_OQUE); | |
867 | } | 883 | } | |
868 | 884 | |||
869 | static void | 885 | static void | |
870 | aac_rx_set_outb_queue(struct aac_softc *sc, int index) | 886 | aac_rx_set_outb_queue(struct aac_softc *sc, int index) | |
871 | { | 887 | { | |
872 | 888 | |||
873 | AAC_SETREG4(sc, AAC_RX_OQUE, index); | 889 | AAC_SETREG4(sc, AAC_RX_OQUE, index); | |
874 | } | 890 | } | |
875 | 891 | |||
876 | static void | 892 | static void | |
877 | aac_rkt_set_outb_queue(struct aac_softc *sc, int index) | 893 | aac_rkt_set_outb_queue(struct aac_softc *sc, int index) | |
878 | { | 894 | { | |
879 | 895 | |||
880 | AAC_SETREG4(sc, AAC_RKT_OQUE, index); | 896 | AAC_SETREG4(sc, AAC_RKT_OQUE, index); | |
881 | } | 897 | } |
--- src/sys/dev/pci/if_an_pci.c 2012/01/30 19:41:19 1.33
+++ src/sys/dev/pci/if_an_pci.c 2012/09/23 01:10:59 1.34
@@ -1,171 +1,172 @@ | @@ -1,171 +1,172 @@ | |||
1 | /* $NetBSD: if_an_pci.c,v 1.33 2012/01/30 19:41:19 drochner Exp $ */ | 1 | /* $NetBSD: if_an_pci.c,v 1.34 2012/09/23 01:10:59 chs Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2000 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2000 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 Atsushi Onoe. | 8 | * by Atsushi Onoe. | |
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. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | /* | 32 | /* | |
33 | * PCI bus front-end for the Aironet PC4500/PC4800 Wireless LAN Adapter. | 33 | * PCI bus front-end for the Aironet PC4500/PC4800 Wireless LAN Adapter. | |
34 | * Unlike WaveLAN, this adapter attached as PCI device using a PLX 9050 | 34 | * Unlike WaveLAN, this adapter attached as PCI device using a PLX 9050 | |
35 | * PCI to "dumb bus" bridge chip. | 35 | * PCI to "dumb bus" bridge chip. | |
36 | */ | 36 | */ | |
37 | 37 | |||
38 | #include <sys/cdefs.h> | 38 | #include <sys/cdefs.h> | |
39 | __KERNEL_RCSID(0, "$NetBSD: if_an_pci.c,v 1.33 2012/01/30 19:41:19 drochner Exp $"); | 39 | __KERNEL_RCSID(0, "$NetBSD: if_an_pci.c,v 1.34 2012/09/23 01:10:59 chs Exp $"); | |
40 | 40 | |||
41 | #include <sys/param.h> | 41 | #include <sys/param.h> | |
42 | #include <sys/systm.h> | 42 | #include <sys/systm.h> | |
43 | #include <sys/mbuf.h> | 43 | #include <sys/mbuf.h> | |
44 | #include <sys/malloc.h> | 44 | #include <sys/malloc.h> | |
45 | #include <sys/kernel.h> | 45 | #include <sys/kernel.h> | |
46 | #include <sys/socket.h> | 46 | #include <sys/socket.h> | |
47 | #include <sys/ioctl.h> | 47 | #include <sys/ioctl.h> | |
48 | #include <sys/errno.h> | 48 | #include <sys/errno.h> | |
49 | #include <sys/device.h> | 49 | #include <sys/device.h> | |
50 | #include <sys/callout.h> | 50 | #include <sys/callout.h> | |
51 | 51 | |||
52 | #include <machine/endian.h> | 52 | #include <machine/endian.h> | |
53 | 53 | |||
54 | #include <net/if.h> | 54 | #include <net/if.h> | |
55 | #include <net/if_dl.h> | 55 | #include <net/if_dl.h> | |
56 | #include <net/if_media.h> | 56 | #include <net/if_media.h> | |
57 | #include <net/if_ether.h> | 57 | #include <net/if_ether.h> | |
58 | 58 | |||
59 | #include <net80211/ieee80211_netbsd.h> | 59 | #include <net80211/ieee80211_netbsd.h> | |
60 | #include <net80211/ieee80211_var.h> | 60 | #include <net80211/ieee80211_var.h> | |
61 | 61 | |||
62 | #include <sys/bus.h> | 62 | #include <sys/bus.h> | |
63 | #include <sys/intr.h> | 63 | #include <sys/intr.h> | |
64 | 64 | |||
65 | #include <dev/ic/anreg.h> | 65 | #include <dev/ic/anreg.h> | |
66 | #include <dev/ic/anvar.h> | 66 | #include <dev/ic/anvar.h> | |
67 | 67 | |||
68 | #include <dev/pci/pcivar.h> | 68 | #include <dev/pci/pcivar.h> | |
69 | #include <dev/pci/pcireg.h> | 69 | #include <dev/pci/pcireg.h> | |
70 | #include <dev/pci/pcidevs.h> | 70 | #include <dev/pci/pcidevs.h> | |
71 | 71 | |||
72 | #define AN_PCI_PLX_IOBA 0x14 /* i/o base for PLX chip */ | 72 | #define AN_PCI_PLX_IOBA 0x14 /* i/o base for PLX chip */ | |
73 | #define AN_PCI_IOBA PCI_BAR(2) /* i/o base */ | 73 | #define AN_PCI_IOBA PCI_BAR(2) /* i/o base */ | |
74 | 74 | |||
75 | struct an_pci_softc { | 75 | struct an_pci_softc { | |
76 | struct an_softc sc_an; /* real "an" softc */ | 76 | struct an_softc sc_an; /* real "an" softc */ | |
77 | pci_chipset_tag_t sc_pct; | 77 | pci_chipset_tag_t sc_pct; | |
78 | pcitag_t sc_pcitag; | 78 | pcitag_t sc_pcitag; | |
79 | 79 | |||
80 | /* PCI-specific goo. */ | 80 | /* PCI-specific goo. */ | |
81 | void *sc_ih; /* interrupt handle */ | 81 | void *sc_ih; /* interrupt handle */ | |
82 | }; | 82 | }; | |
83 | 83 | |||
84 | static int an_pci_match(device_t, cfdata_t, void *); | 84 | static int an_pci_match(device_t, cfdata_t, void *); | |
85 | static void an_pci_attach(device_t, device_t, void *); | 85 | static void an_pci_attach(device_t, device_t, void *); | |
86 | 86 | |||
87 | CFATTACH_DECL_NEW(an_pci, sizeof(struct an_pci_softc), | 87 | CFATTACH_DECL_NEW(an_pci, sizeof(struct an_pci_softc), | |
88 | an_pci_match, an_pci_attach, NULL, NULL); | 88 | an_pci_match, an_pci_attach, NULL, NULL); | |
89 | 89 | |||
90 | static const struct an_pci_product { | 90 | static const struct an_pci_product { | |
91 | u_int32_t app_vendor; /* PCI vendor ID */ | 91 | u_int32_t app_vendor; /* PCI vendor ID */ | |
92 | u_int32_t app_product; /* PCI product ID */ | 92 | u_int32_t app_product; /* PCI product ID */ | |
93 | } an_pci_products[] = { | 93 | } an_pci_products[] = { | |
94 | { PCI_VENDOR_AIRONET, PCI_PRODUCT_AIRONET_PC4xxx }, | 94 | { PCI_VENDOR_AIRONET, PCI_PRODUCT_AIRONET_PC4xxx }, | |
95 | { PCI_VENDOR_AIRONET, PCI_PRODUCT_AIRONET_PC4500 }, | 95 | { PCI_VENDOR_AIRONET, PCI_PRODUCT_AIRONET_PC4500 }, | |
96 | { PCI_VENDOR_AIRONET, PCI_PRODUCT_AIRONET_PC4800 }, | 96 | { PCI_VENDOR_AIRONET, PCI_PRODUCT_AIRONET_PC4800 }, | |
97 | { PCI_VENDOR_AIRONET, PCI_PRODUCT_AIRONET_PCI350 }, | 97 | { PCI_VENDOR_AIRONET, PCI_PRODUCT_AIRONET_PCI350 }, | |
98 | { PCI_VENDOR_AIRONET, PCI_PRODUCT_AIRONET_MPI350 }, | |||
98 | { 0, 0 } | 99 | { 0, 0 } | |
99 | }; | 100 | }; | |
100 | 101 | |||
101 | static int | 102 | static int | |
102 | an_pci_match(device_t parent, cfdata_t match, void *aux) | 103 | an_pci_match(device_t parent, cfdata_t match, void *aux) | |
103 | { | 104 | { | |
104 | struct pci_attach_args *pa = aux; | 105 | struct pci_attach_args *pa = aux; | |
105 | const struct an_pci_product *app; | 106 | const struct an_pci_product *app; | |
106 | 107 | |||
107 | for (app = an_pci_products; app->app_vendor != 0; app++) { | 108 | for (app = an_pci_products; app->app_vendor != 0; app++) { | |
108 | if (PCI_VENDOR(pa->pa_id) == app->app_vendor && | 109 | if (PCI_VENDOR(pa->pa_id) == app->app_vendor && | |
109 | PCI_PRODUCT(pa->pa_id) == app->app_product) | 110 | PCI_PRODUCT(pa->pa_id) == app->app_product) | |
110 | return 1; | 111 | return 1; | |
111 | } | 112 | } | |
112 | return 0; | 113 | return 0; | |
113 | } | 114 | } | |
114 | 115 | |||
115 | static void | 116 | static void | |
116 | an_pci_attach(device_t parent, device_t self, void *aux) | 117 | an_pci_attach(device_t parent, device_t self, void *aux) | |
117 | { | 118 | { | |
118 | struct pci_attach_args *pa = (struct pci_attach_args *)aux; | 119 | struct pci_attach_args *pa = (struct pci_attach_args *)aux; | |
119 | struct an_pci_softc *psc = device_private(self); | 120 | struct an_pci_softc *psc = device_private(self); | |
120 | struct an_softc *sc = &psc->sc_an; | 121 | struct an_softc *sc = &psc->sc_an; | |
121 | char const *intrstr; | 122 | char const *intrstr; | |
122 | pci_intr_handle_t ih; | 123 | pci_intr_handle_t ih; | |
123 | bus_size_t iosize; | 124 | bus_size_t iosize; | |
124 | u_int32_t csr; | 125 | u_int32_t csr; | |
125 | 126 | |||
126 | sc->sc_dev = self; | 127 | sc->sc_dev = self; | |
127 | psc->sc_pct = pa->pa_pc; | 128 | psc->sc_pct = pa->pa_pc; | |
128 | psc->sc_pcitag = pa->pa_tag; | 129 | psc->sc_pcitag = pa->pa_tag; | |
129 | 130 | |||
130 | pci_aprint_devinfo(pa, "802.11 controller"); | 131 | pci_aprint_devinfo(pa, "802.11 controller"); | |
131 | 132 | |||
132 | /* Map I/O registers */ | 133 | /* Map I/O registers */ | |
133 | if (pci_mapreg_map(pa, AN_PCI_IOBA, PCI_MAPREG_TYPE_IO, 0, | 134 | if (pci_mapreg_map(pa, AN_PCI_IOBA, PCI_MAPREG_TYPE_IO, 0, | |
134 | &sc->sc_iot, &sc->sc_ioh, NULL, &iosize) != 0) { | 135 | &sc->sc_iot, &sc->sc_ioh, NULL, &iosize) != 0) { | |
135 | aprint_error_dev(self, "unable to map registers\n"); | 136 | aprint_error_dev(self, "unable to map registers\n"); | |
136 | return; | 137 | return; | |
137 | } | 138 | } | |
138 | 139 | |||
139 | /* Enable the device. */ | 140 | /* Enable the device. */ | |
140 | csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); | 141 | csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); | |
141 | pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, | 142 | pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, | |
142 | csr | PCI_COMMAND_MASTER_ENABLE); | 143 | csr | PCI_COMMAND_MASTER_ENABLE); | |
143 | 144 | |||
144 | /* Map and establish the interrupt. */ | 145 | /* Map and establish the interrupt. */ | |
145 | if (pci_intr_map(pa, &ih)) { | 146 | if (pci_intr_map(pa, &ih)) { | |
146 | aprint_error_dev(self, "unable to map interrupt\n"); | 147 | aprint_error_dev(self, "unable to map interrupt\n"); | |
147 | return; | 148 | return; | |
148 | } | 149 | } | |
149 | intrstr = pci_intr_string(pa->pa_pc, ih); | 150 | intrstr = pci_intr_string(pa->pa_pc, ih); | |
150 | psc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET, an_intr, sc); | 151 | psc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET, an_intr, sc); | |
151 | if (psc->sc_ih == NULL) { | 152 | if (psc->sc_ih == NULL) { | |
152 | aprint_error_dev(self, "unable to establish interrupt"); | 153 | aprint_error_dev(self, "unable to establish interrupt"); | |
153 | if (intrstr != NULL) | 154 | if (intrstr != NULL) | |
154 | aprint_error(" at %s", intrstr); | 155 | aprint_error(" at %s", intrstr); | |
155 | aprint_error("\n"); | 156 | aprint_error("\n"); | |
156 | return; | 157 | return; | |
157 | } | 158 | } | |
158 | aprint_normal_dev(self, "interrupting at %s\n", intrstr); | 159 | aprint_normal_dev(self, "interrupting at %s\n", intrstr); | |
159 | sc->sc_enabled = 1; | 160 | sc->sc_enabled = 1; | |
160 | 161 | |||
161 | if (an_attach(sc) != 0) { | 162 | if (an_attach(sc) != 0) { | |
162 | aprint_error_dev(self, "failed to attach controller\n"); | 163 | aprint_error_dev(self, "failed to attach controller\n"); | |
163 | pci_intr_disestablish(pa->pa_pc, psc->sc_ih); | 164 | pci_intr_disestablish(pa->pa_pc, psc->sc_ih); | |
164 | bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize); | 165 | bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize); | |
165 | } | 166 | } | |
166 | 167 | |||
167 | if (pmf_device_register(self, NULL, NULL)) | 168 | if (pmf_device_register(self, NULL, NULL)) | |
168 | pmf_class_network_register(self, &sc->sc_if); | 169 | pmf_class_network_register(self, &sc->sc_if); | |
169 | else | 170 | else | |
170 | aprint_error_dev(self, "couldn't establish power handler\n"); | 171 | aprint_error_dev(self, "couldn't establish power handler\n"); | |
171 | } | 172 | } |
--- src/sys/dev/pci/if_sip.c 2012/07/22 14:33:03 1.154
+++ src/sys/dev/pci/if_sip.c 2012/09/23 01:10:59 1.155
@@ -1,1742 +1,1745 @@ | @@ -1,1742 +1,1745 @@ | |||
1 | /* $NetBSD: if_sip.c,v 1.154 2012/07/22 14:33:03 matt Exp $ */ | 1 | /* $NetBSD: if_sip.c,v 1.155 2012/09/23 01:10:59 chs Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2001, 2002 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 Jason R. Thorpe. | 8 | * by Jason R. Thorpe. | |
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. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | /*- | 32 | /*- | |
33 | * Copyright (c) 1999 Network Computer, Inc. | 33 | * Copyright (c) 1999 Network Computer, Inc. | |
34 | * All rights reserved. | 34 | * All rights reserved. | |
35 | * | 35 | * | |
36 | * Redistribution and use in source and binary forms, with or without | 36 | * Redistribution and use in source and binary forms, with or without | |
37 | * modification, are permitted provided that the following conditions | 37 | * modification, are permitted provided that the following conditions | |
38 | * are met: | 38 | * are met: | |
39 | * 1. Redistributions of source code must retain the above copyright | 39 | * 1. Redistributions of source code must retain the above copyright | |
40 | * notice, this list of conditions and the following disclaimer. | 40 | * notice, this list of conditions and the following disclaimer. | |
41 | * 2. Redistributions in binary form must reproduce the above copyright | 41 | * 2. Redistributions in binary form must reproduce the above copyright | |
42 | * notice, this list of conditions and the following disclaimer in the | 42 | * notice, this list of conditions and the following disclaimer in the | |
43 | * documentation and/or other materials provided with the distribution. | 43 | * documentation and/or other materials provided with the distribution. | |
44 | * 3. Neither the name of Network Computer, Inc. nor the names of its | 44 | * 3. Neither the name of Network Computer, Inc. nor the names of its | |
45 | * contributors may be used to endorse or promote products derived | 45 | * contributors may be used to endorse or promote products derived | |
46 | * from this software without specific prior written permission. | 46 | * from this software without specific prior written permission. | |
47 | * | 47 | * | |
48 | * THIS SOFTWARE IS PROVIDED BY NETWORK COMPUTER, INC. AND CONTRIBUTORS | 48 | * THIS SOFTWARE IS PROVIDED BY NETWORK COMPUTER, INC. AND CONTRIBUTORS | |
49 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 49 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
50 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 50 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
51 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 51 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
52 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 52 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
53 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 53 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
54 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 54 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
55 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 55 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
56 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 56 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
57 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 57 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
58 | * POSSIBILITY OF SUCH DAMAGE. | 58 | * POSSIBILITY OF SUCH DAMAGE. | |
59 | */ | 59 | */ | |
60 | 60 | |||
61 | /* | 61 | /* | |
62 | * Device driver for the Silicon Integrated Systems SiS 900, | 62 | * Device driver for the Silicon Integrated Systems SiS 900, | |
63 | * SiS 7016 10/100, National Semiconductor DP83815 10/100, and | 63 | * SiS 7016 10/100, National Semiconductor DP83815 10/100, and | |
64 | * National Semiconductor DP83820 10/100/1000 PCI Ethernet | 64 | * National Semiconductor DP83820 10/100/1000 PCI Ethernet | |
65 | * controllers. | 65 | * controllers. | |
66 | * | 66 | * | |
67 | * Originally written to support the SiS 900 by Jason R. Thorpe for | 67 | * Originally written to support the SiS 900 by Jason R. Thorpe for | |
68 | * Network Computer, Inc. | 68 | * Network Computer, Inc. | |
69 | * | 69 | * | |
70 | * TODO: | 70 | * TODO: | |
71 | * | 71 | * | |
72 | * - Reduce the Rx interrupt load. | 72 | * - Reduce the Rx interrupt load. | |
73 | */ | 73 | */ | |
74 | 74 | |||
75 | #include <sys/cdefs.h> | 75 | #include <sys/cdefs.h> | |
76 | __KERNEL_RCSID(0, "$NetBSD: if_sip.c,v 1.154 2012/07/22 14:33:03 matt Exp $"); | 76 | __KERNEL_RCSID(0, "$NetBSD: if_sip.c,v 1.155 2012/09/23 01:10:59 chs Exp $"); | |
77 | 77 | |||
78 | 78 | |||
79 | 79 | |||
80 | #include <sys/param.h> | 80 | #include <sys/param.h> | |
81 | #include <sys/systm.h> | 81 | #include <sys/systm.h> | |
82 | #include <sys/callout.h> | 82 | #include <sys/callout.h> | |
83 | #include <sys/mbuf.h> | 83 | #include <sys/mbuf.h> | |
84 | #include <sys/malloc.h> | 84 | #include <sys/malloc.h> | |
85 | #include <sys/kernel.h> | 85 | #include <sys/kernel.h> | |
86 | #include <sys/socket.h> | 86 | #include <sys/socket.h> | |
87 | #include <sys/ioctl.h> | 87 | #include <sys/ioctl.h> | |
88 | #include <sys/errno.h> | 88 | #include <sys/errno.h> | |
89 | #include <sys/device.h> | 89 | #include <sys/device.h> | |
90 | #include <sys/queue.h> | 90 | #include <sys/queue.h> | |
91 | 91 | |||
92 | #include <sys/rnd.h> | 92 | #include <sys/rnd.h> | |
93 | 93 | |||
94 | #include <net/if.h> | 94 | #include <net/if.h> | |
95 | #include <net/if_dl.h> | 95 | #include <net/if_dl.h> | |
96 | #include <net/if_media.h> | 96 | #include <net/if_media.h> | |
97 | #include <net/if_ether.h> | 97 | #include <net/if_ether.h> | |
98 | 98 | |||
99 | #include <net/bpf.h> | 99 | #include <net/bpf.h> | |
100 | 100 | |||
101 | #include <sys/bus.h> | 101 | #include <sys/bus.h> | |
102 | #include <sys/intr.h> | 102 | #include <sys/intr.h> | |
103 | #include <machine/endian.h> | 103 | #include <machine/endian.h> | |
104 | 104 | |||
105 | #include <dev/mii/mii.h> | 105 | #include <dev/mii/mii.h> | |
106 | #include <dev/mii/miivar.h> | 106 | #include <dev/mii/miivar.h> | |
107 | #include <dev/mii/mii_bitbang.h> | 107 | #include <dev/mii/mii_bitbang.h> | |
108 | 108 | |||
109 | #include <dev/pci/pcireg.h> | 109 | #include <dev/pci/pcireg.h> | |
110 | #include <dev/pci/pcivar.h> | 110 | #include <dev/pci/pcivar.h> | |
111 | #include <dev/pci/pcidevs.h> | 111 | #include <dev/pci/pcidevs.h> | |
112 | 112 | |||
113 | #include <dev/pci/if_sipreg.h> | 113 | #include <dev/pci/if_sipreg.h> | |
114 | 114 | |||
115 | /* | 115 | /* | |
116 | * Transmit descriptor list size. This is arbitrary, but allocate | 116 | * Transmit descriptor list size. This is arbitrary, but allocate | |
117 | * enough descriptors for 128 pending transmissions, and 8 segments | 117 | * enough descriptors for 128 pending transmissions, and 8 segments | |
118 | * per packet (64 for DP83820 for jumbo frames). | 118 | * per packet (64 for DP83820 for jumbo frames). | |
119 | * | 119 | * | |
120 | * This MUST work out to a power of 2. | 120 | * This MUST work out to a power of 2. | |
121 | */ | 121 | */ | |
122 | #define GSIP_NTXSEGS_ALLOC 16 | 122 | #define GSIP_NTXSEGS_ALLOC 16 | |
123 | #define SIP_NTXSEGS_ALLOC 8 | 123 | #define SIP_NTXSEGS_ALLOC 8 | |
124 | 124 | |||
125 | #define SIP_TXQUEUELEN 256 | 125 | #define SIP_TXQUEUELEN 256 | |
126 | #define MAX_SIP_NTXDESC \ | 126 | #define MAX_SIP_NTXDESC \ | |
127 | (SIP_TXQUEUELEN * MAX(SIP_NTXSEGS_ALLOC, GSIP_NTXSEGS_ALLOC)) | 127 | (SIP_TXQUEUELEN * MAX(SIP_NTXSEGS_ALLOC, GSIP_NTXSEGS_ALLOC)) | |
128 | 128 | |||
129 | /* | 129 | /* | |
130 | * Receive descriptor list size. We have one Rx buffer per incoming | 130 | * Receive descriptor list size. We have one Rx buffer per incoming | |
131 | * packet, so this logic is a little simpler. | 131 | * packet, so this logic is a little simpler. | |
132 | * | 132 | * | |
133 | * Actually, on the DP83820, we allow the packet to consume more than | 133 | * Actually, on the DP83820, we allow the packet to consume more than | |
134 | * one buffer, in order to support jumbo Ethernet frames. In that | 134 | * one buffer, in order to support jumbo Ethernet frames. In that | |
135 | * case, a packet may consume up to 5 buffers (assuming a 2048 byte | 135 | * case, a packet may consume up to 5 buffers (assuming a 2048 byte | |
136 | * mbuf cluster). 256 receive buffers is only 51 maximum size packets, | 136 | * mbuf cluster). 256 receive buffers is only 51 maximum size packets, | |
137 | * so we'd better be quick about handling receive interrupts. | 137 | * so we'd better be quick about handling receive interrupts. | |
138 | */ | 138 | */ | |
139 | #define GSIP_NRXDESC 256 | 139 | #define GSIP_NRXDESC 256 | |
140 | #define SIP_NRXDESC 128 | 140 | #define SIP_NRXDESC 128 | |
141 | 141 | |||
142 | #define MAX_SIP_NRXDESC MAX(GSIP_NRXDESC, SIP_NRXDESC) | 142 | #define MAX_SIP_NRXDESC MAX(GSIP_NRXDESC, SIP_NRXDESC) | |
143 | 143 | |||
144 | /* | 144 | /* | |
145 | * Control structures are DMA'd to the SiS900 chip. We allocate them in | 145 | * Control structures are DMA'd to the SiS900 chip. We allocate them in | |
146 | * a single clump that maps to a single DMA segment to make several things | 146 | * a single clump that maps to a single DMA segment to make several things | |
147 | * easier. | 147 | * easier. | |
148 | */ | 148 | */ | |
149 | struct sip_control_data { | 149 | struct sip_control_data { | |
150 | /* | 150 | /* | |
151 | * The transmit descriptors. | 151 | * The transmit descriptors. | |
152 | */ | 152 | */ | |
153 | struct sip_desc scd_txdescs[MAX_SIP_NTXDESC]; | 153 | struct sip_desc scd_txdescs[MAX_SIP_NTXDESC]; | |
154 | 154 | |||
155 | /* | 155 | /* | |
156 | * The receive descriptors. | 156 | * The receive descriptors. | |
157 | */ | 157 | */ | |
158 | struct sip_desc scd_rxdescs[MAX_SIP_NRXDESC]; | 158 | struct sip_desc scd_rxdescs[MAX_SIP_NRXDESC]; | |
159 | }; | 159 | }; | |
160 | 160 | |||
161 | #define SIP_CDOFF(x) offsetof(struct sip_control_data, x) | 161 | #define SIP_CDOFF(x) offsetof(struct sip_control_data, x) | |
162 | #define SIP_CDTXOFF(x) SIP_CDOFF(scd_txdescs[(x)]) | 162 | #define SIP_CDTXOFF(x) SIP_CDOFF(scd_txdescs[(x)]) | |
163 | #define SIP_CDRXOFF(x) SIP_CDOFF(scd_rxdescs[(x)]) | 163 | #define SIP_CDRXOFF(x) SIP_CDOFF(scd_rxdescs[(x)]) | |
164 | 164 | |||
165 | /* | 165 | /* | |
166 | * Software state for transmit jobs. | 166 | * Software state for transmit jobs. | |
167 | */ | 167 | */ | |
168 | struct sip_txsoft { | 168 | struct sip_txsoft { | |
169 | struct mbuf *txs_mbuf; /* head of our mbuf chain */ | 169 | struct mbuf *txs_mbuf; /* head of our mbuf chain */ | |
170 | bus_dmamap_t txs_dmamap; /* our DMA map */ | 170 | bus_dmamap_t txs_dmamap; /* our DMA map */ | |
171 | int txs_firstdesc; /* first descriptor in packet */ | 171 | int txs_firstdesc; /* first descriptor in packet */ | |
172 | int txs_lastdesc; /* last descriptor in packet */ | 172 | int txs_lastdesc; /* last descriptor in packet */ | |
173 | SIMPLEQ_ENTRY(sip_txsoft) txs_q; | 173 | SIMPLEQ_ENTRY(sip_txsoft) txs_q; | |
174 | }; | 174 | }; | |
175 | 175 | |||
176 | SIMPLEQ_HEAD(sip_txsq, sip_txsoft); | 176 | SIMPLEQ_HEAD(sip_txsq, sip_txsoft); | |
177 | 177 | |||
178 | /* | 178 | /* | |
179 | * Software state for receive jobs. | 179 | * Software state for receive jobs. | |
180 | */ | 180 | */ | |
181 | struct sip_rxsoft { | 181 | struct sip_rxsoft { | |
182 | struct mbuf *rxs_mbuf; /* head of our mbuf chain */ | 182 | struct mbuf *rxs_mbuf; /* head of our mbuf chain */ | |
183 | bus_dmamap_t rxs_dmamap; /* our DMA map */ | 183 | bus_dmamap_t rxs_dmamap; /* our DMA map */ | |
184 | }; | 184 | }; | |
185 | 185 | |||
186 | enum sip_attach_stage { | 186 | enum sip_attach_stage { | |
187 | SIP_ATTACH_FIN = 0 | 187 | SIP_ATTACH_FIN = 0 | |
188 | , SIP_ATTACH_CREATE_RXMAP | 188 | , SIP_ATTACH_CREATE_RXMAP | |
189 | , SIP_ATTACH_CREATE_TXMAP | 189 | , SIP_ATTACH_CREATE_TXMAP | |
190 | , SIP_ATTACH_LOAD_MAP | 190 | , SIP_ATTACH_LOAD_MAP | |
191 | , SIP_ATTACH_CREATE_MAP | 191 | , SIP_ATTACH_CREATE_MAP | |
192 | , SIP_ATTACH_MAP_MEM | 192 | , SIP_ATTACH_MAP_MEM | |
193 | , SIP_ATTACH_ALLOC_MEM | 193 | , SIP_ATTACH_ALLOC_MEM | |
194 | , SIP_ATTACH_INTR | 194 | , SIP_ATTACH_INTR | |
195 | , SIP_ATTACH_MAP | 195 | , SIP_ATTACH_MAP | |
196 | }; | 196 | }; | |
197 | 197 | |||
198 | /* | 198 | /* | |
199 | * Software state per device. | 199 | * Software state per device. | |
200 | */ | 200 | */ | |
201 | struct sip_softc { | 201 | struct sip_softc { | |
202 | device_t sc_dev; /* generic device information */ | 202 | device_t sc_dev; /* generic device information */ | |
203 | device_suspensor_t sc_suspensor; | 203 | device_suspensor_t sc_suspensor; | |
204 | pmf_qual_t sc_qual; | 204 | pmf_qual_t sc_qual; | |
205 | 205 | |||
206 | bus_space_tag_t sc_st; /* bus space tag */ | 206 | bus_space_tag_t sc_st; /* bus space tag */ | |
207 | bus_space_handle_t sc_sh; /* bus space handle */ | 207 | bus_space_handle_t sc_sh; /* bus space handle */ | |
208 | bus_size_t sc_sz; /* bus space size */ | 208 | bus_size_t sc_sz; /* bus space size */ | |
209 | bus_dma_tag_t sc_dmat; /* bus DMA tag */ | 209 | bus_dma_tag_t sc_dmat; /* bus DMA tag */ | |
210 | pci_chipset_tag_t sc_pc; | 210 | pci_chipset_tag_t sc_pc; | |
211 | bus_dma_segment_t sc_seg; | 211 | bus_dma_segment_t sc_seg; | |
212 | struct ethercom sc_ethercom; /* ethernet common data */ | 212 | struct ethercom sc_ethercom; /* ethernet common data */ | |
213 | 213 | |||
214 | const struct sip_product *sc_model; /* which model are we? */ | 214 | const struct sip_product *sc_model; /* which model are we? */ | |
215 | int sc_gigabit; /* 1: 83820, 0: other */ | 215 | int sc_gigabit; /* 1: 83820, 0: other */ | |
216 | int sc_rev; /* chip revision */ | 216 | int sc_rev; /* chip revision */ | |
217 | 217 | |||
218 | void *sc_ih; /* interrupt cookie */ | 218 | void *sc_ih; /* interrupt cookie */ | |
219 | 219 | |||
220 | struct mii_data sc_mii; /* MII/media information */ | 220 | struct mii_data sc_mii; /* MII/media information */ | |
221 | 221 | |||
222 | callout_t sc_tick_ch; /* tick callout */ | 222 | callout_t sc_tick_ch; /* tick callout */ | |
223 | 223 | |||
224 | bus_dmamap_t sc_cddmamap; /* control data DMA map */ | 224 | bus_dmamap_t sc_cddmamap; /* control data DMA map */ | |
225 | #define sc_cddma sc_cddmamap->dm_segs[0].ds_addr | 225 | #define sc_cddma sc_cddmamap->dm_segs[0].ds_addr | |
226 | 226 | |||
227 | /* | 227 | /* | |
228 | * Software state for transmit and receive descriptors. | 228 | * Software state for transmit and receive descriptors. | |
229 | */ | 229 | */ | |
230 | struct sip_txsoft sc_txsoft[SIP_TXQUEUELEN]; | 230 | struct sip_txsoft sc_txsoft[SIP_TXQUEUELEN]; | |
231 | struct sip_rxsoft sc_rxsoft[MAX_SIP_NRXDESC]; | 231 | struct sip_rxsoft sc_rxsoft[MAX_SIP_NRXDESC]; | |
232 | 232 | |||
233 | /* | 233 | /* | |
234 | * Control data structures. | 234 | * Control data structures. | |
235 | */ | 235 | */ | |
236 | struct sip_control_data *sc_control_data; | 236 | struct sip_control_data *sc_control_data; | |
237 | #define sc_txdescs sc_control_data->scd_txdescs | 237 | #define sc_txdescs sc_control_data->scd_txdescs | |
238 | #define sc_rxdescs sc_control_data->scd_rxdescs | 238 | #define sc_rxdescs sc_control_data->scd_rxdescs | |
239 | 239 | |||
240 | #ifdef SIP_EVENT_COUNTERS | 240 | #ifdef SIP_EVENT_COUNTERS | |
241 | /* | 241 | /* | |
242 | * Event counters. | 242 | * Event counters. | |
243 | */ | 243 | */ | |
244 | struct evcnt sc_ev_txsstall; /* Tx stalled due to no txs */ | 244 | struct evcnt sc_ev_txsstall; /* Tx stalled due to no txs */ | |
245 | struct evcnt sc_ev_txdstall; /* Tx stalled due to no txd */ | 245 | struct evcnt sc_ev_txdstall; /* Tx stalled due to no txd */ | |
246 | struct evcnt sc_ev_txforceintr; /* Tx interrupts forced */ | 246 | struct evcnt sc_ev_txforceintr; /* Tx interrupts forced */ | |
247 | struct evcnt sc_ev_txdintr; /* Tx descriptor interrupts */ | 247 | struct evcnt sc_ev_txdintr; /* Tx descriptor interrupts */ | |
248 | struct evcnt sc_ev_txiintr; /* Tx idle interrupts */ | 248 | struct evcnt sc_ev_txiintr; /* Tx idle interrupts */ | |
249 | struct evcnt sc_ev_rxintr; /* Rx interrupts */ | 249 | struct evcnt sc_ev_rxintr; /* Rx interrupts */ | |
250 | struct evcnt sc_ev_hiberr; /* HIBERR interrupts */ | 250 | struct evcnt sc_ev_hiberr; /* HIBERR interrupts */ | |
251 | struct evcnt sc_ev_rxpause; /* PAUSE received */ | 251 | struct evcnt sc_ev_rxpause; /* PAUSE received */ | |
252 | /* DP83820 only */ | 252 | /* DP83820 only */ | |
253 | struct evcnt sc_ev_txpause; /* PAUSE transmitted */ | 253 | struct evcnt sc_ev_txpause; /* PAUSE transmitted */ | |
254 | struct evcnt sc_ev_rxipsum; /* IP checksums checked in-bound */ | 254 | struct evcnt sc_ev_rxipsum; /* IP checksums checked in-bound */ | |
255 | struct evcnt sc_ev_rxtcpsum; /* TCP checksums checked in-bound */ | 255 | struct evcnt sc_ev_rxtcpsum; /* TCP checksums checked in-bound */ | |
256 | struct evcnt sc_ev_rxudpsum; /* UDP checksums checked in-boudn */ | 256 | struct evcnt sc_ev_rxudpsum; /* UDP checksums checked in-boudn */ | |
257 | struct evcnt sc_ev_txipsum; /* IP checksums comp. out-bound */ | 257 | struct evcnt sc_ev_txipsum; /* IP checksums comp. out-bound */ | |
258 | struct evcnt sc_ev_txtcpsum; /* TCP checksums comp. out-bound */ | 258 | struct evcnt sc_ev_txtcpsum; /* TCP checksums comp. out-bound */ | |
259 | struct evcnt sc_ev_txudpsum; /* UDP checksums comp. out-bound */ | 259 | struct evcnt sc_ev_txudpsum; /* UDP checksums comp. out-bound */ | |
260 | #endif /* SIP_EVENT_COUNTERS */ | 260 | #endif /* SIP_EVENT_COUNTERS */ | |
261 | 261 | |||
262 | u_int32_t sc_txcfg; /* prototype TXCFG register */ | 262 | u_int32_t sc_txcfg; /* prototype TXCFG register */ | |
263 | u_int32_t sc_rxcfg; /* prototype RXCFG register */ | 263 | u_int32_t sc_rxcfg; /* prototype RXCFG register */ | |
264 | u_int32_t sc_imr; /* prototype IMR register */ | 264 | u_int32_t sc_imr; /* prototype IMR register */ | |
265 | u_int32_t sc_rfcr; /* prototype RFCR register */ | 265 | u_int32_t sc_rfcr; /* prototype RFCR register */ | |
266 | 266 | |||
267 | u_int32_t sc_cfg; /* prototype CFG register */ | 267 | u_int32_t sc_cfg; /* prototype CFG register */ | |
268 | 268 | |||
269 | u_int32_t sc_gpior; /* prototype GPIOR register */ | 269 | u_int32_t sc_gpior; /* prototype GPIOR register */ | |
270 | 270 | |||
271 | u_int32_t sc_tx_fill_thresh; /* transmit fill threshold */ | 271 | u_int32_t sc_tx_fill_thresh; /* transmit fill threshold */ | |
272 | u_int32_t sc_tx_drain_thresh; /* transmit drain threshold */ | 272 | u_int32_t sc_tx_drain_thresh; /* transmit drain threshold */ | |
273 | 273 | |||
274 | u_int32_t sc_rx_drain_thresh; /* receive drain threshold */ | 274 | u_int32_t sc_rx_drain_thresh; /* receive drain threshold */ | |
275 | 275 | |||
276 | int sc_flowflags; /* 802.3x flow control flags */ | 276 | int sc_flowflags; /* 802.3x flow control flags */ | |
277 | int sc_rx_flow_thresh; /* Rx FIFO threshold for flow control */ | 277 | int sc_rx_flow_thresh; /* Rx FIFO threshold for flow control */ | |
278 | int sc_paused; /* paused indication */ | 278 | int sc_paused; /* paused indication */ | |
279 | 279 | |||
280 | int sc_txfree; /* number of free Tx descriptors */ | 280 | int sc_txfree; /* number of free Tx descriptors */ | |
281 | int sc_txnext; /* next ready Tx descriptor */ | 281 | int sc_txnext; /* next ready Tx descriptor */ | |
282 | int sc_txwin; /* Tx descriptors since last intr */ | 282 | int sc_txwin; /* Tx descriptors since last intr */ | |
283 | 283 | |||
284 | struct sip_txsq sc_txfreeq; /* free Tx descsofts */ | 284 | struct sip_txsq sc_txfreeq; /* free Tx descsofts */ | |
285 | struct sip_txsq sc_txdirtyq; /* dirty Tx descsofts */ | 285 | struct sip_txsq sc_txdirtyq; /* dirty Tx descsofts */ | |
286 | 286 | |||
287 | /* values of interface state at last init */ | 287 | /* values of interface state at last init */ | |
288 | struct { | 288 | struct { | |
289 | /* if_capenable */ | 289 | /* if_capenable */ | |
290 | uint64_t if_capenable; | 290 | uint64_t if_capenable; | |
291 | /* ec_capenable */ | 291 | /* ec_capenable */ | |
292 | int ec_capenable; | 292 | int ec_capenable; | |
293 | /* VLAN_ATTACHED */ | 293 | /* VLAN_ATTACHED */ | |
294 | int is_vlan; | 294 | int is_vlan; | |
295 | } sc_prev; | 295 | } sc_prev; | |
296 | 296 | |||
297 | short sc_if_flags; | 297 | short sc_if_flags; | |
298 | 298 | |||
299 | int sc_rxptr; /* next ready Rx descriptor/descsoft */ | 299 | int sc_rxptr; /* next ready Rx descriptor/descsoft */ | |
300 | int sc_rxdiscard; | 300 | int sc_rxdiscard; | |
301 | int sc_rxlen; | 301 | int sc_rxlen; | |
302 | struct mbuf *sc_rxhead; | 302 | struct mbuf *sc_rxhead; | |
303 | struct mbuf *sc_rxtail; | 303 | struct mbuf *sc_rxtail; | |
304 | struct mbuf **sc_rxtailp; | 304 | struct mbuf **sc_rxtailp; | |
305 | 305 | |||
306 | int sc_ntxdesc; | 306 | int sc_ntxdesc; | |
307 | int sc_ntxdesc_mask; | 307 | int sc_ntxdesc_mask; | |
308 | 308 | |||
309 | int sc_nrxdesc_mask; | 309 | int sc_nrxdesc_mask; | |
310 | 310 | |||
311 | const struct sip_parm { | 311 | const struct sip_parm { | |
312 | const struct sip_regs { | 312 | const struct sip_regs { | |
313 | int r_rxcfg; | 313 | int r_rxcfg; | |
314 | int r_txcfg; | 314 | int r_txcfg; | |
315 | } p_regs; | 315 | } p_regs; | |
316 | 316 | |||
317 | const struct sip_bits { | 317 | const struct sip_bits { | |
318 | uint32_t b_txcfg_mxdma_8; | 318 | uint32_t b_txcfg_mxdma_8; | |
319 | uint32_t b_txcfg_mxdma_16; | 319 | uint32_t b_txcfg_mxdma_16; | |
320 | uint32_t b_txcfg_mxdma_32; | 320 | uint32_t b_txcfg_mxdma_32; | |
321 | uint32_t b_txcfg_mxdma_64; | 321 | uint32_t b_txcfg_mxdma_64; | |
322 | uint32_t b_txcfg_mxdma_128; | 322 | uint32_t b_txcfg_mxdma_128; | |
323 | uint32_t b_txcfg_mxdma_256; | 323 | uint32_t b_txcfg_mxdma_256; | |
324 | uint32_t b_txcfg_mxdma_512; | 324 | uint32_t b_txcfg_mxdma_512; | |
325 | uint32_t b_txcfg_flth_mask; | 325 | uint32_t b_txcfg_flth_mask; | |
326 | uint32_t b_txcfg_drth_mask; | 326 | uint32_t b_txcfg_drth_mask; | |
327 | 327 | |||
328 | uint32_t b_rxcfg_mxdma_8; | 328 | uint32_t b_rxcfg_mxdma_8; | |
329 | uint32_t b_rxcfg_mxdma_16; | 329 | uint32_t b_rxcfg_mxdma_16; | |
330 | uint32_t b_rxcfg_mxdma_32; | 330 | uint32_t b_rxcfg_mxdma_32; | |
331 | uint32_t b_rxcfg_mxdma_64; | 331 | uint32_t b_rxcfg_mxdma_64; | |
332 | uint32_t b_rxcfg_mxdma_128; | 332 | uint32_t b_rxcfg_mxdma_128; | |
333 | uint32_t b_rxcfg_mxdma_256; | 333 | uint32_t b_rxcfg_mxdma_256; | |
334 | uint32_t b_rxcfg_mxdma_512; | 334 | uint32_t b_rxcfg_mxdma_512; | |
335 | 335 | |||
336 | uint32_t b_isr_txrcmp; | 336 | uint32_t b_isr_txrcmp; | |
337 | uint32_t b_isr_rxrcmp; | 337 | uint32_t b_isr_rxrcmp; | |
338 | uint32_t b_isr_dperr; | 338 | uint32_t b_isr_dperr; | |
339 | uint32_t b_isr_sserr; | 339 | uint32_t b_isr_sserr; | |
340 | uint32_t b_isr_rmabt; | 340 | uint32_t b_isr_rmabt; | |
341 | uint32_t b_isr_rtabt; | 341 | uint32_t b_isr_rtabt; | |
342 | 342 | |||
343 | uint32_t b_cmdsts_size_mask; | 343 | uint32_t b_cmdsts_size_mask; | |
344 | } p_bits; | 344 | } p_bits; | |
345 | int p_filtmem; | 345 | int p_filtmem; | |
346 | int p_rxbuf_len; | 346 | int p_rxbuf_len; | |
347 | bus_size_t p_tx_dmamap_size; | 347 | bus_size_t p_tx_dmamap_size; | |
348 | int p_ntxsegs; | 348 | int p_ntxsegs; | |
349 | int p_ntxsegs_alloc; | 349 | int p_ntxsegs_alloc; | |
350 | int p_nrxdesc; | 350 | int p_nrxdesc; | |
351 | } *sc_parm; | 351 | } *sc_parm; | |
352 | 352 | |||
353 | void (*sc_rxintr)(struct sip_softc *); | 353 | void (*sc_rxintr)(struct sip_softc *); | |
354 | 354 | |||
355 | krndsource_t rnd_source; /* random source */ | 355 | krndsource_t rnd_source; /* random source */ | |
356 | }; | 356 | }; | |
357 | 357 | |||
358 | #define sc_bits sc_parm->p_bits | 358 | #define sc_bits sc_parm->p_bits | |
359 | #define sc_regs sc_parm->p_regs | 359 | #define sc_regs sc_parm->p_regs | |
360 | 360 | |||
361 | static const struct sip_parm sip_parm = { | 361 | static const struct sip_parm sip_parm = { | |
362 | .p_filtmem = OTHER_RFCR_NS_RFADDR_FILTMEM | 362 | .p_filtmem = OTHER_RFCR_NS_RFADDR_FILTMEM | |
363 | , .p_rxbuf_len = MCLBYTES - 1 /* field width */ | 363 | , .p_rxbuf_len = MCLBYTES - 1 /* field width */ | |
364 | , .p_tx_dmamap_size = MCLBYTES | 364 | , .p_tx_dmamap_size = MCLBYTES | |
365 | , .p_ntxsegs = 16 | 365 | , .p_ntxsegs = 16 | |
366 | , .p_ntxsegs_alloc = SIP_NTXSEGS_ALLOC | 366 | , .p_ntxsegs_alloc = SIP_NTXSEGS_ALLOC | |
367 | , .p_nrxdesc = SIP_NRXDESC | 367 | , .p_nrxdesc = SIP_NRXDESC | |
368 | , .p_bits = { | 368 | , .p_bits = { | |
369 | .b_txcfg_mxdma_8 = 0x00200000 /* 8 bytes */ | 369 | .b_txcfg_mxdma_8 = 0x00200000 /* 8 bytes */ | |
370 | , .b_txcfg_mxdma_16 = 0x00300000 /* 16 bytes */ | 370 | , .b_txcfg_mxdma_16 = 0x00300000 /* 16 bytes */ | |
371 | , .b_txcfg_mxdma_32 = 0x00400000 /* 32 bytes */ | 371 | , .b_txcfg_mxdma_32 = 0x00400000 /* 32 bytes */ | |
372 | , .b_txcfg_mxdma_64 = 0x00500000 /* 64 bytes */ | 372 | , .b_txcfg_mxdma_64 = 0x00500000 /* 64 bytes */ | |
373 | , .b_txcfg_mxdma_128 = 0x00600000 /* 128 bytes */ | 373 | , .b_txcfg_mxdma_128 = 0x00600000 /* 128 bytes */ | |
374 | , .b_txcfg_mxdma_256 = 0x00700000 /* 256 bytes */ | 374 | , .b_txcfg_mxdma_256 = 0x00700000 /* 256 bytes */ | |
375 | , .b_txcfg_mxdma_512 = 0x00000000 /* 512 bytes */ | 375 | , .b_txcfg_mxdma_512 = 0x00000000 /* 512 bytes */ | |
376 | , .b_txcfg_flth_mask = 0x00003f00 /* Tx fill threshold */ | 376 | , .b_txcfg_flth_mask = 0x00003f00 /* Tx fill threshold */ | |
377 | , .b_txcfg_drth_mask = 0x0000003f /* Tx drain threshold */ | 377 | , .b_txcfg_drth_mask = 0x0000003f /* Tx drain threshold */ | |
378 | 378 | |||
379 | , .b_rxcfg_mxdma_8 = 0x00200000 /* 8 bytes */ | 379 | , .b_rxcfg_mxdma_8 = 0x00200000 /* 8 bytes */ | |
380 | , .b_rxcfg_mxdma_16 = 0x00300000 /* 16 bytes */ | 380 | , .b_rxcfg_mxdma_16 = 0x00300000 /* 16 bytes */ | |
381 | , .b_rxcfg_mxdma_32 = 0x00400000 /* 32 bytes */ | 381 | , .b_rxcfg_mxdma_32 = 0x00400000 /* 32 bytes */ | |
382 | , .b_rxcfg_mxdma_64 = 0x00500000 /* 64 bytes */ | 382 | , .b_rxcfg_mxdma_64 = 0x00500000 /* 64 bytes */ | |
383 | , .b_rxcfg_mxdma_128 = 0x00600000 /* 128 bytes */ | 383 | , .b_rxcfg_mxdma_128 = 0x00600000 /* 128 bytes */ | |
384 | , .b_rxcfg_mxdma_256 = 0x00700000 /* 256 bytes */ | 384 | , .b_rxcfg_mxdma_256 = 0x00700000 /* 256 bytes */ | |
385 | , .b_rxcfg_mxdma_512 = 0x00000000 /* 512 bytes */ | 385 | , .b_rxcfg_mxdma_512 = 0x00000000 /* 512 bytes */ | |
386 | 386 | |||
387 | , .b_isr_txrcmp = 0x02000000 /* transmit reset complete */ | 387 | , .b_isr_txrcmp = 0x02000000 /* transmit reset complete */ | |
388 | , .b_isr_rxrcmp = 0x01000000 /* receive reset complete */ | 388 | , .b_isr_rxrcmp = 0x01000000 /* receive reset complete */ | |
389 | , .b_isr_dperr = 0x00800000 /* detected parity error */ | 389 | , .b_isr_dperr = 0x00800000 /* detected parity error */ | |
390 | , .b_isr_sserr = 0x00400000 /* signalled system error */ | 390 | , .b_isr_sserr = 0x00400000 /* signalled system error */ | |
391 | , .b_isr_rmabt = 0x00200000 /* received master abort */ | 391 | , .b_isr_rmabt = 0x00200000 /* received master abort */ | |
392 | , .b_isr_rtabt = 0x00100000 /* received target abort */ | 392 | , .b_isr_rtabt = 0x00100000 /* received target abort */ | |
393 | , .b_cmdsts_size_mask = OTHER_CMDSTS_SIZE_MASK | 393 | , .b_cmdsts_size_mask = OTHER_CMDSTS_SIZE_MASK | |
394 | } | 394 | } | |
395 | , .p_regs = { | 395 | , .p_regs = { | |
396 | .r_rxcfg = OTHER_SIP_RXCFG, | 396 | .r_rxcfg = OTHER_SIP_RXCFG, | |
397 | .r_txcfg = OTHER_SIP_TXCFG | 397 | .r_txcfg = OTHER_SIP_TXCFG | |
398 | } | 398 | } | |
399 | }, gsip_parm = { | 399 | }, gsip_parm = { | |
400 | .p_filtmem = DP83820_RFCR_NS_RFADDR_FILTMEM | 400 | .p_filtmem = DP83820_RFCR_NS_RFADDR_FILTMEM | |
401 | , .p_rxbuf_len = MCLBYTES - 8 | 401 | , .p_rxbuf_len = MCLBYTES - 8 | |
402 | , .p_tx_dmamap_size = ETHER_MAX_LEN_JUMBO | 402 | , .p_tx_dmamap_size = ETHER_MAX_LEN_JUMBO | |
403 | , .p_ntxsegs = 64 | 403 | , .p_ntxsegs = 64 | |
404 | , .p_ntxsegs_alloc = GSIP_NTXSEGS_ALLOC | 404 | , .p_ntxsegs_alloc = GSIP_NTXSEGS_ALLOC | |
405 | , .p_nrxdesc = GSIP_NRXDESC | 405 | , .p_nrxdesc = GSIP_NRXDESC | |
406 | , .p_bits = { | 406 | , .p_bits = { | |
407 | .b_txcfg_mxdma_8 = 0x00100000 /* 8 bytes */ | 407 | .b_txcfg_mxdma_8 = 0x00100000 /* 8 bytes */ | |
408 | , .b_txcfg_mxdma_16 = 0x00200000 /* 16 bytes */ | 408 | , .b_txcfg_mxdma_16 = 0x00200000 /* 16 bytes */ | |
409 | , .b_txcfg_mxdma_32 = 0x00300000 /* 32 bytes */ | 409 | , .b_txcfg_mxdma_32 = 0x00300000 /* 32 bytes */ | |
410 | , .b_txcfg_mxdma_64 = 0x00400000 /* 64 bytes */ | 410 | , .b_txcfg_mxdma_64 = 0x00400000 /* 64 bytes */ | |
411 | , .b_txcfg_mxdma_128 = 0x00500000 /* 128 bytes */ | 411 | , .b_txcfg_mxdma_128 = 0x00500000 /* 128 bytes */ | |
412 | , .b_txcfg_mxdma_256 = 0x00600000 /* 256 bytes */ | 412 | , .b_txcfg_mxdma_256 = 0x00600000 /* 256 bytes */ | |
413 | , .b_txcfg_mxdma_512 = 0x00700000 /* 512 bytes */ | 413 | , .b_txcfg_mxdma_512 = 0x00700000 /* 512 bytes */ | |
414 | , .b_txcfg_flth_mask = 0x0000ff00 /* Fx fill threshold */ | 414 | , .b_txcfg_flth_mask = 0x0000ff00 /* Fx fill threshold */ | |
415 | , .b_txcfg_drth_mask = 0x000000ff /* Tx drain threshold */ | 415 | , .b_txcfg_drth_mask = 0x000000ff /* Tx drain threshold */ | |
416 | 416 | |||
417 | , .b_rxcfg_mxdma_8 = 0x00100000 /* 8 bytes */ | 417 | , .b_rxcfg_mxdma_8 = 0x00100000 /* 8 bytes */ | |
418 | , .b_rxcfg_mxdma_16 = 0x00200000 /* 16 bytes */ | 418 | , .b_rxcfg_mxdma_16 = 0x00200000 /* 16 bytes */ | |
419 | , .b_rxcfg_mxdma_32 = 0x00300000 /* 32 bytes */ | 419 | , .b_rxcfg_mxdma_32 = 0x00300000 /* 32 bytes */ | |
420 | , .b_rxcfg_mxdma_64 = 0x00400000 /* 64 bytes */ | 420 | , .b_rxcfg_mxdma_64 = 0x00400000 /* 64 bytes */ | |
421 | , .b_rxcfg_mxdma_128 = 0x00500000 /* 128 bytes */ | 421 | , .b_rxcfg_mxdma_128 = 0x00500000 /* 128 bytes */ | |
422 | , .b_rxcfg_mxdma_256 = 0x00600000 /* 256 bytes */ | 422 | , .b_rxcfg_mxdma_256 = 0x00600000 /* 256 bytes */ | |
423 | , .b_rxcfg_mxdma_512 = 0x00700000 /* 512 bytes */ | 423 | , .b_rxcfg_mxdma_512 = 0x00700000 /* 512 bytes */ | |
424 | 424 | |||
425 | , .b_isr_txrcmp = 0x00400000 /* transmit reset complete */ | 425 | , .b_isr_txrcmp = 0x00400000 /* transmit reset complete */ | |
426 | , .b_isr_rxrcmp = 0x00200000 /* receive reset complete */ | 426 | , .b_isr_rxrcmp = 0x00200000 /* receive reset complete */ | |
427 | , .b_isr_dperr = 0x00100000 /* detected parity error */ | 427 | , .b_isr_dperr = 0x00100000 /* detected parity error */ | |
428 | , .b_isr_sserr = 0x00080000 /* signalled system error */ | 428 | , .b_isr_sserr = 0x00080000 /* signalled system error */ | |
429 | , .b_isr_rmabt = 0x00040000 /* received master abort */ | 429 | , .b_isr_rmabt = 0x00040000 /* received master abort */ | |
430 | , .b_isr_rtabt = 0x00020000 /* received target abort */ | 430 | , .b_isr_rtabt = 0x00020000 /* received target abort */ | |
431 | , .b_cmdsts_size_mask = DP83820_CMDSTS_SIZE_MASK | 431 | , .b_cmdsts_size_mask = DP83820_CMDSTS_SIZE_MASK | |
432 | } | 432 | } | |
433 | , .p_regs = { | 433 | , .p_regs = { | |
434 | .r_rxcfg = DP83820_SIP_RXCFG, | 434 | .r_rxcfg = DP83820_SIP_RXCFG, | |
435 | .r_txcfg = DP83820_SIP_TXCFG | 435 | .r_txcfg = DP83820_SIP_TXCFG | |
436 | } | 436 | } | |
437 | }; | 437 | }; | |
438 | 438 | |||
439 | static inline int | 439 | static inline int | |
440 | sip_nexttx(const struct sip_softc *sc, int x) | 440 | sip_nexttx(const struct sip_softc *sc, int x) | |
441 | { | 441 | { | |
442 | return (x + 1) & sc->sc_ntxdesc_mask; | 442 | return (x + 1) & sc->sc_ntxdesc_mask; | |
443 | } | 443 | } | |
444 | 444 | |||
445 | static inline int | 445 | static inline int | |
446 | sip_nextrx(const struct sip_softc *sc, int x) | 446 | sip_nextrx(const struct sip_softc *sc, int x) | |
447 | { | 447 | { | |
448 | return (x + 1) & sc->sc_nrxdesc_mask; | 448 | return (x + 1) & sc->sc_nrxdesc_mask; | |
449 | } | 449 | } | |
450 | 450 | |||
451 | /* 83820 only */ | 451 | /* 83820 only */ | |
452 | static inline void | 452 | static inline void | |
453 | sip_rxchain_reset(struct sip_softc *sc) | 453 | sip_rxchain_reset(struct sip_softc *sc) | |
454 | { | 454 | { | |
455 | sc->sc_rxtailp = &sc->sc_rxhead; | 455 | sc->sc_rxtailp = &sc->sc_rxhead; | |
456 | *sc->sc_rxtailp = NULL; | 456 | *sc->sc_rxtailp = NULL; | |
457 | sc->sc_rxlen = 0; | 457 | sc->sc_rxlen = 0; | |
458 | } | 458 | } | |
459 | 459 | |||
460 | /* 83820 only */ | 460 | /* 83820 only */ | |
461 | static inline void | 461 | static inline void | |
462 | sip_rxchain_link(struct sip_softc *sc, struct mbuf *m) | 462 | sip_rxchain_link(struct sip_softc *sc, struct mbuf *m) | |
463 | { | 463 | { | |
464 | *sc->sc_rxtailp = sc->sc_rxtail = m; | 464 | *sc->sc_rxtailp = sc->sc_rxtail = m; | |
465 | sc->sc_rxtailp = &m->m_next; | 465 | sc->sc_rxtailp = &m->m_next; | |
466 | } | 466 | } | |
467 | 467 | |||
468 | #ifdef SIP_EVENT_COUNTERS | 468 | #ifdef SIP_EVENT_COUNTERS | |
469 | #define SIP_EVCNT_INCR(ev) (ev)->ev_count++ | 469 | #define SIP_EVCNT_INCR(ev) (ev)->ev_count++ | |
470 | #else | 470 | #else | |
471 | #define SIP_EVCNT_INCR(ev) /* nothing */ | 471 | #define SIP_EVCNT_INCR(ev) /* nothing */ | |
472 | #endif | 472 | #endif | |
473 | 473 | |||
474 | #define SIP_CDTXADDR(sc, x) ((sc)->sc_cddma + SIP_CDTXOFF((x))) | 474 | #define SIP_CDTXADDR(sc, x) ((sc)->sc_cddma + SIP_CDTXOFF((x))) | |
475 | #define SIP_CDRXADDR(sc, x) ((sc)->sc_cddma + SIP_CDRXOFF((x))) | 475 | #define SIP_CDRXADDR(sc, x) ((sc)->sc_cddma + SIP_CDRXOFF((x))) | |
476 | 476 | |||
477 | static inline void | 477 | static inline void | |
478 | sip_cdtxsync(struct sip_softc *sc, const int x0, const int n0, const int ops) | 478 | sip_cdtxsync(struct sip_softc *sc, const int x0, const int n0, const int ops) | |
479 | { | 479 | { | |
480 | int x, n; | 480 | int x, n; | |
481 | 481 | |||
482 | x = x0; | 482 | x = x0; | |
483 | n = n0; | 483 | n = n0; | |
484 | 484 | |||
485 | /* If it will wrap around, sync to the end of the ring. */ | 485 | /* If it will wrap around, sync to the end of the ring. */ | |
486 | if (x + n > sc->sc_ntxdesc) { | 486 | if (x + n > sc->sc_ntxdesc) { | |
487 | bus_dmamap_sync(sc->sc_dmat, sc->sc_cddmamap, | 487 | bus_dmamap_sync(sc->sc_dmat, sc->sc_cddmamap, | |
488 | SIP_CDTXOFF(x), sizeof(struct sip_desc) * | 488 | SIP_CDTXOFF(x), sizeof(struct sip_desc) * | |
489 | (sc->sc_ntxdesc - x), ops); | 489 | (sc->sc_ntxdesc - x), ops); | |
490 | n -= (sc->sc_ntxdesc - x); | 490 | n -= (sc->sc_ntxdesc - x); | |
491 | x = 0; | 491 | x = 0; | |
492 | } | 492 | } | |
493 | 493 | |||
494 | /* Now sync whatever is left. */ | 494 | /* Now sync whatever is left. */ | |
495 | bus_dmamap_sync(sc->sc_dmat, sc->sc_cddmamap, | 495 | bus_dmamap_sync(sc->sc_dmat, sc->sc_cddmamap, | |
496 | SIP_CDTXOFF(x), sizeof(struct sip_desc) * n, ops); | 496 | SIP_CDTXOFF(x), sizeof(struct sip_desc) * n, ops); | |
497 | } | 497 | } | |
498 | 498 | |||
499 | static inline void | 499 | static inline void | |
500 | sip_cdrxsync(struct sip_softc *sc, int x, int ops) | 500 | sip_cdrxsync(struct sip_softc *sc, int x, int ops) | |
501 | { | 501 | { | |
502 | bus_dmamap_sync(sc->sc_dmat, sc->sc_cddmamap, | 502 | bus_dmamap_sync(sc->sc_dmat, sc->sc_cddmamap, | |
503 | SIP_CDRXOFF(x), sizeof(struct sip_desc), ops); | 503 | SIP_CDRXOFF(x), sizeof(struct sip_desc), ops); | |
504 | } | 504 | } | |
505 | 505 | |||
506 | #if 0 | 506 | #if 0 | |
507 | #ifdef DP83820 | 507 | #ifdef DP83820 | |
508 | u_int32_t sipd_bufptr; /* pointer to DMA segment */ | 508 | u_int32_t sipd_bufptr; /* pointer to DMA segment */ | |
509 | u_int32_t sipd_cmdsts; /* command/status word */ | 509 | u_int32_t sipd_cmdsts; /* command/status word */ | |
510 | #else | 510 | #else | |
511 | u_int32_t sipd_cmdsts; /* command/status word */ | 511 | u_int32_t sipd_cmdsts; /* command/status word */ | |
512 | u_int32_t sipd_bufptr; /* pointer to DMA segment */ | 512 | u_int32_t sipd_bufptr; /* pointer to DMA segment */ | |
513 | #endif /* DP83820 */ | 513 | #endif /* DP83820 */ | |
514 | #endif /* 0 */ | 514 | #endif /* 0 */ | |
515 | 515 | |||
516 | static inline volatile uint32_t * | 516 | static inline volatile uint32_t * | |
517 | sipd_cmdsts(struct sip_softc *sc, struct sip_desc *sipd) | 517 | sipd_cmdsts(struct sip_softc *sc, struct sip_desc *sipd) | |
518 | { | 518 | { | |
519 | return &sipd->sipd_cbs[(sc->sc_gigabit) ? 1 : 0]; | 519 | return &sipd->sipd_cbs[(sc->sc_gigabit) ? 1 : 0]; | |
520 | } | 520 | } | |
521 | 521 | |||
522 | static inline volatile uint32_t * | 522 | static inline volatile uint32_t * | |
523 | sipd_bufptr(struct sip_softc *sc, struct sip_desc *sipd) | 523 | sipd_bufptr(struct sip_softc *sc, struct sip_desc *sipd) | |
524 | { | 524 | { | |
525 | return &sipd->sipd_cbs[(sc->sc_gigabit) ? 0 : 1]; | 525 | return &sipd->sipd_cbs[(sc->sc_gigabit) ? 0 : 1]; | |
526 | } | 526 | } | |
527 | 527 | |||
528 | static inline void | 528 | static inline void | |
529 | sip_init_rxdesc(struct sip_softc *sc, int x) | 529 | sip_init_rxdesc(struct sip_softc *sc, int x) | |
530 | { | 530 | { | |
531 | struct sip_rxsoft *rxs = &sc->sc_rxsoft[x]; | 531 | struct sip_rxsoft *rxs = &sc->sc_rxsoft[x]; | |
532 | struct sip_desc *sipd = &sc->sc_rxdescs[x]; | 532 | struct sip_desc *sipd = &sc->sc_rxdescs[x]; | |
533 | 533 | |||
534 | sipd->sipd_link = htole32(SIP_CDRXADDR(sc, sip_nextrx(sc, x))); | 534 | sipd->sipd_link = htole32(SIP_CDRXADDR(sc, sip_nextrx(sc, x))); | |
535 | *sipd_bufptr(sc, sipd) = htole32(rxs->rxs_dmamap->dm_segs[0].ds_addr); | 535 | *sipd_bufptr(sc, sipd) = htole32(rxs->rxs_dmamap->dm_segs[0].ds_addr); | |
536 | *sipd_cmdsts(sc, sipd) = htole32(CMDSTS_INTR | | 536 | *sipd_cmdsts(sc, sipd) = htole32(CMDSTS_INTR | | |
537 | (sc->sc_parm->p_rxbuf_len & sc->sc_bits.b_cmdsts_size_mask)); | 537 | (sc->sc_parm->p_rxbuf_len & sc->sc_bits.b_cmdsts_size_mask)); | |
538 | sipd->sipd_extsts = 0; | 538 | sipd->sipd_extsts = 0; | |
539 | sip_cdrxsync(sc, x, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); | 539 | sip_cdrxsync(sc, x, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); | |
540 | } | 540 | } | |
541 | 541 | |||
542 | #define SIP_CHIP_VERS(sc, v, p, r) \ | 542 | #define SIP_CHIP_VERS(sc, v, p, r) \ | |
543 | ((sc)->sc_model->sip_vendor == (v) && \ | 543 | ((sc)->sc_model->sip_vendor == (v) && \ | |
544 | (sc)->sc_model->sip_product == (p) && \ | 544 | (sc)->sc_model->sip_product == (p) && \ | |
545 | (sc)->sc_rev == (r)) | 545 | (sc)->sc_rev == (r)) | |
546 | 546 | |||
547 | #define SIP_CHIP_MODEL(sc, v, p) \ | 547 | #define SIP_CHIP_MODEL(sc, v, p) \ | |
548 | ((sc)->sc_model->sip_vendor == (v) && \ | 548 | ((sc)->sc_model->sip_vendor == (v) && \ | |
549 | (sc)->sc_model->sip_product == (p)) | 549 | (sc)->sc_model->sip_product == (p)) | |
550 | 550 | |||
551 | #define SIP_SIS900_REV(sc, rev) \ | 551 | #define SIP_SIS900_REV(sc, rev) \ | |
552 | SIP_CHIP_VERS((sc), PCI_VENDOR_SIS, PCI_PRODUCT_SIS_900, (rev)) | 552 | SIP_CHIP_VERS((sc), PCI_VENDOR_SIS, PCI_PRODUCT_SIS_900, (rev)) | |
553 | 553 | |||
554 | #define SIP_TIMEOUT 1000 | 554 | #define SIP_TIMEOUT 1000 | |
555 | 555 | |||
556 | static int sip_ifflags_cb(struct ethercom *); | 556 | static int sip_ifflags_cb(struct ethercom *); | |
557 | static void sipcom_start(struct ifnet *); | 557 | static void sipcom_start(struct ifnet *); | |
558 | static void sipcom_watchdog(struct ifnet *); | 558 | static void sipcom_watchdog(struct ifnet *); | |
559 | static int sipcom_ioctl(struct ifnet *, u_long, void *); | 559 | static int sipcom_ioctl(struct ifnet *, u_long, void *); | |
560 | static int sipcom_init(struct ifnet *); | 560 | static int sipcom_init(struct ifnet *); | |
561 | static void sipcom_stop(struct ifnet *, int); | 561 | static void sipcom_stop(struct ifnet *, int); | |
562 | 562 | |||
563 | static bool sipcom_reset(struct sip_softc *); | 563 | static bool sipcom_reset(struct sip_softc *); | |
564 | static void sipcom_rxdrain(struct sip_softc *); | 564 | static void sipcom_rxdrain(struct sip_softc *); | |
565 | static int sipcom_add_rxbuf(struct sip_softc *, int); | 565 | static int sipcom_add_rxbuf(struct sip_softc *, int); | |
566 | static void sipcom_read_eeprom(struct sip_softc *, int, int, | 566 | static void sipcom_read_eeprom(struct sip_softc *, int, int, | |
567 | u_int16_t *); | 567 | u_int16_t *); | |
568 | static void sipcom_tick(void *); | 568 | static void sipcom_tick(void *); | |
569 | 569 | |||
570 | static void sipcom_sis900_set_filter(struct sip_softc *); | 570 | static void sipcom_sis900_set_filter(struct sip_softc *); | |
571 | static void sipcom_dp83815_set_filter(struct sip_softc *); | 571 | static void sipcom_dp83815_set_filter(struct sip_softc *); | |
572 | 572 | |||
573 | static void sipcom_dp83820_read_macaddr(struct sip_softc *, | 573 | static void sipcom_dp83820_read_macaddr(struct sip_softc *, | |
574 | const struct pci_attach_args *, u_int8_t *); | 574 | const struct pci_attach_args *, u_int8_t *); | |
575 | static void sipcom_sis900_eeprom_delay(struct sip_softc *sc); | 575 | static void sipcom_sis900_eeprom_delay(struct sip_softc *sc); | |
576 | static void sipcom_sis900_read_macaddr(struct sip_softc *, | 576 | static void sipcom_sis900_read_macaddr(struct sip_softc *, | |
577 | const struct pci_attach_args *, u_int8_t *); | 577 | const struct pci_attach_args *, u_int8_t *); | |
578 | static void sipcom_dp83815_read_macaddr(struct sip_softc *, | 578 | static void sipcom_dp83815_read_macaddr(struct sip_softc *, | |
579 | const struct pci_attach_args *, u_int8_t *); | 579 | const struct pci_attach_args *, u_int8_t *); | |
580 | 580 | |||
581 | static int sipcom_intr(void *); | 581 | static int sipcom_intr(void *); | |
582 | static void sipcom_txintr(struct sip_softc *); | 582 | static void sipcom_txintr(struct sip_softc *); | |
583 | static void sip_rxintr(struct sip_softc *); | 583 | static void sip_rxintr(struct sip_softc *); | |
584 | static void gsip_rxintr(struct sip_softc *); | 584 | static void gsip_rxintr(struct sip_softc *); | |
585 | 585 | |||
586 | static int sipcom_dp83820_mii_readreg(device_t, int, int); | 586 | static int sipcom_dp83820_mii_readreg(device_t, int, int); | |
587 | static void sipcom_dp83820_mii_writereg(device_t, int, int, int); | 587 | static void sipcom_dp83820_mii_writereg(device_t, int, int, int); | |
588 | static void sipcom_dp83820_mii_statchg(struct ifnet *); | 588 | static void sipcom_dp83820_mii_statchg(struct ifnet *); | |
589 | 589 | |||
590 | static int sipcom_sis900_mii_readreg(device_t, int, int); | 590 | static int sipcom_sis900_mii_readreg(device_t, int, int); | |
591 | static void sipcom_sis900_mii_writereg(device_t, int, int, int); | 591 | static void sipcom_sis900_mii_writereg(device_t, int, int, int); | |
592 | static void sipcom_sis900_mii_statchg(struct ifnet *); | 592 | static void sipcom_sis900_mii_statchg(struct ifnet *); | |
593 | 593 | |||
594 | static int sipcom_dp83815_mii_readreg(device_t, int, int); | 594 | static int sipcom_dp83815_mii_readreg(device_t, int, int); | |
595 | static void sipcom_dp83815_mii_writereg(device_t, int, int, int); | 595 | static void sipcom_dp83815_mii_writereg(device_t, int, int, int); | |
596 | static void sipcom_dp83815_mii_statchg(struct ifnet *); | 596 | static void sipcom_dp83815_mii_statchg(struct ifnet *); | |
597 | 597 | |||
598 | static void sipcom_mediastatus(struct ifnet *, struct ifmediareq *); | 598 | static void sipcom_mediastatus(struct ifnet *, struct ifmediareq *); | |
599 | 599 | |||
600 | static int sipcom_match(device_t, cfdata_t, void *); | 600 | static int sipcom_match(device_t, cfdata_t, void *); | |
601 | static void sipcom_attach(device_t, device_t, void *); | 601 | static void sipcom_attach(device_t, device_t, void *); | |
602 | static void sipcom_do_detach(device_t, enum sip_attach_stage); | 602 | static void sipcom_do_detach(device_t, enum sip_attach_stage); | |
603 | static int sipcom_detach(device_t, int); | 603 | static int sipcom_detach(device_t, int); | |
604 | static bool sipcom_resume(device_t, const pmf_qual_t *); | 604 | static bool sipcom_resume(device_t, const pmf_qual_t *); | |
605 | static bool sipcom_suspend(device_t, const pmf_qual_t *); | 605 | static bool sipcom_suspend(device_t, const pmf_qual_t *); | |
606 | 606 | |||
607 | int gsip_copy_small = 0; | 607 | int gsip_copy_small = 0; | |
608 | int sip_copy_small = 0; | 608 | int sip_copy_small = 0; | |
609 | 609 | |||
610 | CFATTACH_DECL3_NEW(gsip, sizeof(struct sip_softc), | 610 | CFATTACH_DECL3_NEW(gsip, sizeof(struct sip_softc), | |
611 | sipcom_match, sipcom_attach, sipcom_detach, NULL, NULL, NULL, | 611 | sipcom_match, sipcom_attach, sipcom_detach, NULL, NULL, NULL, | |
612 | DVF_DETACH_SHUTDOWN); | 612 | DVF_DETACH_SHUTDOWN); | |
613 | CFATTACH_DECL3_NEW(sip, sizeof(struct sip_softc), | 613 | CFATTACH_DECL3_NEW(sip, sizeof(struct sip_softc), | |
614 | sipcom_match, sipcom_attach, sipcom_detach, NULL, NULL, NULL, | 614 | sipcom_match, sipcom_attach, sipcom_detach, NULL, NULL, NULL, | |
615 | DVF_DETACH_SHUTDOWN); | 615 | DVF_DETACH_SHUTDOWN); | |
616 | 616 | |||
617 | /* | 617 | /* | |
618 | * Descriptions of the variants of the SiS900. | 618 | * Descriptions of the variants of the SiS900. | |
619 | */ | 619 | */ | |
620 | struct sip_variant { | 620 | struct sip_variant { | |
621 | int (*sipv_mii_readreg)(device_t, int, int); | 621 | int (*sipv_mii_readreg)(device_t, int, int); | |
622 | void (*sipv_mii_writereg)(device_t, int, int, int); | 622 | void (*sipv_mii_writereg)(device_t, int, int, int); | |
623 | void (*sipv_mii_statchg)(struct ifnet *); | 623 | void (*sipv_mii_statchg)(struct ifnet *); | |
624 | void (*sipv_set_filter)(struct sip_softc *); | 624 | void (*sipv_set_filter)(struct sip_softc *); | |
625 | void (*sipv_read_macaddr)(struct sip_softc *, | 625 | void (*sipv_read_macaddr)(struct sip_softc *, | |
626 | const struct pci_attach_args *, u_int8_t *); | 626 | const struct pci_attach_args *, u_int8_t *); | |
627 | }; | 627 | }; | |
628 | 628 | |||
629 | static u_int32_t sipcom_mii_bitbang_read(device_t); | 629 | static u_int32_t sipcom_mii_bitbang_read(device_t); | |
630 | static void sipcom_mii_bitbang_write(device_t, u_int32_t); | 630 | static void sipcom_mii_bitbang_write(device_t, u_int32_t); | |
631 | 631 | |||
632 | static const struct mii_bitbang_ops sipcom_mii_bitbang_ops = { | 632 | static const struct mii_bitbang_ops sipcom_mii_bitbang_ops = { | |
633 | sipcom_mii_bitbang_read, | 633 | sipcom_mii_bitbang_read, | |
634 | sipcom_mii_bitbang_write, | 634 | sipcom_mii_bitbang_write, | |
635 | { | 635 | { | |
636 | EROMAR_MDIO, /* MII_BIT_MDO */ | 636 | EROMAR_MDIO, /* MII_BIT_MDO */ | |
637 | EROMAR_MDIO, /* MII_BIT_MDI */ | 637 | EROMAR_MDIO, /* MII_BIT_MDI */ | |
638 | EROMAR_MDC, /* MII_BIT_MDC */ | 638 | EROMAR_MDC, /* MII_BIT_MDC */ | |
639 | EROMAR_MDDIR, /* MII_BIT_DIR_HOST_PHY */ | 639 | EROMAR_MDDIR, /* MII_BIT_DIR_HOST_PHY */ | |
640 | 0, /* MII_BIT_DIR_PHY_HOST */ | 640 | 0, /* MII_BIT_DIR_PHY_HOST */ | |
641 | } | 641 | } | |
642 | }; | 642 | }; | |
643 | 643 | |||
644 | static const struct sip_variant sipcom_variant_dp83820 = { | 644 | static const struct sip_variant sipcom_variant_dp83820 = { | |
645 | sipcom_dp83820_mii_readreg, | 645 | sipcom_dp83820_mii_readreg, | |
646 | sipcom_dp83820_mii_writereg, | 646 | sipcom_dp83820_mii_writereg, | |
647 | sipcom_dp83820_mii_statchg, | 647 | sipcom_dp83820_mii_statchg, | |
648 | sipcom_dp83815_set_filter, | 648 | sipcom_dp83815_set_filter, | |
649 | sipcom_dp83820_read_macaddr, | 649 | sipcom_dp83820_read_macaddr, | |
650 | }; | 650 | }; | |
651 | 651 | |||
652 | static const struct sip_variant sipcom_variant_sis900 = { | 652 | static const struct sip_variant sipcom_variant_sis900 = { | |
653 | sipcom_sis900_mii_readreg, | 653 | sipcom_sis900_mii_readreg, | |
654 | sipcom_sis900_mii_writereg, | 654 | sipcom_sis900_mii_writereg, | |
655 | sipcom_sis900_mii_statchg, | 655 | sipcom_sis900_mii_statchg, | |
656 | sipcom_sis900_set_filter, | 656 | sipcom_sis900_set_filter, | |
657 | sipcom_sis900_read_macaddr, | 657 | sipcom_sis900_read_macaddr, | |
658 | }; | 658 | }; | |
659 | 659 | |||
660 | static const struct sip_variant sipcom_variant_dp83815 = { | 660 | static const struct sip_variant sipcom_variant_dp83815 = { | |
661 | sipcom_dp83815_mii_readreg, | 661 | sipcom_dp83815_mii_readreg, | |
662 | sipcom_dp83815_mii_writereg, | 662 | sipcom_dp83815_mii_writereg, | |
663 | sipcom_dp83815_mii_statchg, | 663 | sipcom_dp83815_mii_statchg, | |
664 | sipcom_dp83815_set_filter, | 664 | sipcom_dp83815_set_filter, | |
665 | sipcom_dp83815_read_macaddr, | 665 | sipcom_dp83815_read_macaddr, | |
666 | }; | 666 | }; | |
667 | 667 | |||
668 | 668 | |||
669 | /* | 669 | /* | |
670 | * Devices supported by this driver. | 670 | * Devices supported by this driver. | |
671 | */ | 671 | */ | |
672 | static const struct sip_product { | 672 | static const struct sip_product { | |
673 | pci_vendor_id_t sip_vendor; | 673 | pci_vendor_id_t sip_vendor; | |
674 | pci_product_id_t sip_product; | 674 | pci_product_id_t sip_product; | |
675 | const char *sip_name; | 675 | const char *sip_name; | |
676 | const struct sip_variant *sip_variant; | 676 | const struct sip_variant *sip_variant; | |
677 | int sip_gigabit; | 677 | int sip_gigabit; | |
678 | } sipcom_products[] = { | 678 | } sipcom_products[] = { | |
679 | { PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83820, | 679 | { PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83820, | |
680 | "NatSemi DP83820 Gigabit Ethernet", | 680 | "NatSemi DP83820 Gigabit Ethernet", | |
681 | &sipcom_variant_dp83820, 1 }, | 681 | &sipcom_variant_dp83820, 1 }, | |
682 | { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_900, | 682 | { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_900, | |
683 | "SiS 900 10/100 Ethernet", | 683 | "SiS 900 10/100 Ethernet", | |
684 | &sipcom_variant_sis900, 0 }, | 684 | &sipcom_variant_sis900, 0 }, | |
685 | { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_7016, | 685 | { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_7016, | |
686 | "SiS 7016 10/100 Ethernet", | 686 | "SiS 7016 10/100 Ethernet", | |
687 | &sipcom_variant_sis900, 0 }, | 687 | &sipcom_variant_sis900, 0 }, | |
688 | 688 | |||
689 | { PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83815, | 689 | { PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83815, | |
690 | "NatSemi DP83815 10/100 Ethernet", | 690 | "NatSemi DP83815 10/100 Ethernet", | |
691 | &sipcom_variant_dp83815, 0 }, | 691 | &sipcom_variant_dp83815, 0 }, | |
692 | 692 | |||
693 | { 0, 0, | 693 | { 0, 0, | |
694 | NULL, | 694 | NULL, | |
695 | NULL, 0 }, | 695 | NULL, 0 }, | |
696 | }; | 696 | }; | |
697 | 697 | |||
698 | static const struct sip_product * | 698 | static const struct sip_product * | |
699 | sipcom_lookup(const struct pci_attach_args *pa, bool gigabit) | 699 | sipcom_lookup(const struct pci_attach_args *pa, bool gigabit) | |
700 | { | 700 | { | |
701 | const struct sip_product *sip; | 701 | const struct sip_product *sip; | |
702 | 702 | |||
703 | for (sip = sipcom_products; sip->sip_name != NULL; sip++) { | 703 | for (sip = sipcom_products; sip->sip_name != NULL; sip++) { | |
704 | if (PCI_VENDOR(pa->pa_id) == sip->sip_vendor && | 704 | if (PCI_VENDOR(pa->pa_id) == sip->sip_vendor && | |
705 | PCI_PRODUCT(pa->pa_id) == sip->sip_product && | 705 | PCI_PRODUCT(pa->pa_id) == sip->sip_product && | |
706 | sip->sip_gigabit == gigabit) | 706 | sip->sip_gigabit == gigabit) | |
707 | return sip; | 707 | return sip; | |
708 | } | 708 | } | |
709 | return NULL; | 709 | return NULL; | |
710 | } | 710 | } | |
711 | 711 | |||
712 | /* | 712 | /* | |
713 | * I really hate stupid hardware vendors. There's a bit in the EEPROM | 713 | * I really hate stupid hardware vendors. There's a bit in the EEPROM | |
714 | * which indicates if the card can do 64-bit data transfers. Unfortunately, | 714 | * which indicates if the card can do 64-bit data transfers. Unfortunately, | |
715 | * several vendors of 32-bit cards fail to clear this bit in the EEPROM, | 715 | * several vendors of 32-bit cards fail to clear this bit in the EEPROM, | |
716 | * which means we try to use 64-bit data transfers on those cards if we | 716 | * which means we try to use 64-bit data transfers on those cards if we | |
717 | * happen to be plugged into a 32-bit slot. | 717 | * happen to be plugged into a 32-bit slot. | |
718 | * | 718 | * | |
719 | * What we do is use this table of cards known to be 64-bit cards. If | 719 | * What we do is use this table of cards known to be 64-bit cards. If | |
720 | * you have a 64-bit card who's subsystem ID is not listed in this table, | 720 | * you have a 64-bit card who's subsystem ID is not listed in this table, | |
721 | * send the output of "pcictl dump ..." of the device to me so that your | 721 | * send the output of "pcictl dump ..." of the device to me so that your | |
722 | * card will use the 64-bit data path when plugged into a 64-bit slot. | 722 | * card will use the 64-bit data path when plugged into a 64-bit slot. | |
723 | * | 723 | * | |
724 | * -- Jason R. Thorpe <thorpej@NetBSD.org> | 724 | * -- Jason R. Thorpe <thorpej@NetBSD.org> | |
725 | * June 30, 2002 | 725 | * June 30, 2002 | |
726 | */ | 726 | */ | |
727 | static int | 727 | static int | |
728 | sipcom_check_64bit(const struct pci_attach_args *pa) | 728 | sipcom_check_64bit(const struct pci_attach_args *pa) | |
729 | { | 729 | { | |
730 | static const struct { | 730 | static const struct { | |
731 | pci_vendor_id_t c64_vendor; | 731 | pci_vendor_id_t c64_vendor; | |
732 | pci_product_id_t c64_product; | 732 | pci_product_id_t c64_product; | |
733 | } card64[] = { | 733 | } card64[] = { | |
734 | /* Asante GigaNIX */ | 734 | /* Asante GigaNIX */ | |
735 | { 0x128a, 0x0002 }, | 735 | { 0x128a, 0x0002 }, | |
736 | 736 | |||
737 | /* Accton EN1407-T, Planex GN-1000TE */ | 737 | /* Accton EN1407-T, Planex GN-1000TE */ | |
738 | { 0x1113, 0x1407 }, | 738 | { 0x1113, 0x1407 }, | |
739 | 739 | |||
740 | /* Netgear GA-621 */ | 740 | /* Netgear GA621 */ | |
741 | { 0x1385, 0x621a }, | 741 | { 0x1385, 0x621a }, | |
742 | 742 | |||
743 | /* SMC EZ Card */ | 743 | /* Netgear GA622 */ | |
744 | { 0x1385, 0x622a }, | |||
745 | ||||
746 | /* SMC EZ Card 1000 (9462TX) */ | |||
744 | { 0x10b8, 0x9462 }, | 747 | { 0x10b8, 0x9462 }, | |
745 | 748 | |||
746 | { 0, 0} | 749 | { 0, 0} | |
747 | }; | 750 | }; | |
748 | pcireg_t subsys; | 751 | pcireg_t subsys; | |
749 | int i; | 752 | int i; | |
750 | 753 | |||
751 | subsys = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); | 754 | subsys = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); | |
752 | 755 | |||
753 | for (i = 0; card64[i].c64_vendor != 0; i++) { | 756 | for (i = 0; card64[i].c64_vendor != 0; i++) { | |
754 | if (PCI_VENDOR(subsys) == card64[i].c64_vendor && | 757 | if (PCI_VENDOR(subsys) == card64[i].c64_vendor && | |
755 | PCI_PRODUCT(subsys) == card64[i].c64_product) | 758 | PCI_PRODUCT(subsys) == card64[i].c64_product) | |
756 | return (1); | 759 | return (1); | |
757 | } | 760 | } | |
758 | 761 | |||
759 | return (0); | 762 | return (0); | |
760 | } | 763 | } | |
761 | 764 | |||
762 | static int | 765 | static int | |
763 | sipcom_match(device_t parent, cfdata_t cf, void *aux) | 766 | sipcom_match(device_t parent, cfdata_t cf, void *aux) | |
764 | { | 767 | { | |
765 | struct pci_attach_args *pa = aux; | 768 | struct pci_attach_args *pa = aux; | |
766 | 769 | |||
767 | if (sipcom_lookup(pa, strcmp(cf->cf_name, "gsip") == 0) != NULL) | 770 | if (sipcom_lookup(pa, strcmp(cf->cf_name, "gsip") == 0) != NULL) | |
768 | return 1; | 771 | return 1; | |
769 | 772 | |||
770 | return 0; | 773 | return 0; | |
771 | } | 774 | } | |
772 | 775 | |||
773 | static void | 776 | static void | |
774 | sipcom_dp83820_attach(struct sip_softc *sc, struct pci_attach_args *pa) | 777 | sipcom_dp83820_attach(struct sip_softc *sc, struct pci_attach_args *pa) | |
775 | { | 778 | { | |
776 | u_int32_t reg; | 779 | u_int32_t reg; | |
777 | int i; | 780 | int i; | |
778 | 781 | |||
779 | /* | 782 | /* | |
780 | * Cause the chip to load configuration data from the EEPROM. | 783 | * Cause the chip to load configuration data from the EEPROM. | |
781 | */ | 784 | */ | |
782 | bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_PTSCR, PTSCR_EELOAD_EN); | 785 | bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_PTSCR, PTSCR_EELOAD_EN); | |
783 | for (i = 0; i < 10000; i++) { | 786 | for (i = 0; i < 10000; i++) { | |
784 | delay(10); | 787 | delay(10); | |
785 | if ((bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_PTSCR) & | 788 | if ((bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_PTSCR) & | |
786 | PTSCR_EELOAD_EN) == 0) | 789 | PTSCR_EELOAD_EN) == 0) | |
787 | break; | 790 | break; | |
788 | } | 791 | } | |
789 | if (bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_PTSCR) & | 792 | if (bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_PTSCR) & | |
790 | PTSCR_EELOAD_EN) { | 793 | PTSCR_EELOAD_EN) { | |
791 | printf("%s: timeout loading configuration from EEPROM\n", | 794 | printf("%s: timeout loading configuration from EEPROM\n", | |
792 | device_xname(sc->sc_dev)); | 795 | device_xname(sc->sc_dev)); | |
793 | return; | 796 | return; | |
794 | } | 797 | } | |
795 | 798 | |||
796 | sc->sc_gpior = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_GPIOR); | 799 | sc->sc_gpior = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_GPIOR); | |
797 | 800 | |||
798 | reg = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_CFG); | 801 | reg = bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_CFG); | |
799 | if (reg & CFG_PCI64_DET) { | 802 | if (reg & CFG_PCI64_DET) { | |
800 | printf("%s: 64-bit PCI slot detected", device_xname(sc->sc_dev)); | 803 | printf("%s: 64-bit PCI slot detected", device_xname(sc->sc_dev)); | |
801 | /* | 804 | /* | |
802 | * Check to see if this card is 64-bit. If so, enable 64-bit | 805 | * Check to see if this card is 64-bit. If so, enable 64-bit | |
803 | * data transfers. | 806 | * data transfers. | |
804 | * | 807 | * | |
805 | * We can't use the DATA64_EN bit in the EEPROM, because | 808 | * We can't use the DATA64_EN bit in the EEPROM, because | |
806 | * vendors of 32-bit cards fail to clear that bit in many | 809 | * vendors of 32-bit cards fail to clear that bit in many | |
807 | * cases (yet the card still detects that it's in a 64-bit | 810 | * cases (yet the card still detects that it's in a 64-bit | |
808 | * slot; go figure). | 811 | * slot; go figure). | |
809 | */ | 812 | */ | |
810 | if (sipcom_check_64bit(pa)) { | 813 | if (sipcom_check_64bit(pa)) { | |
811 | sc->sc_cfg |= CFG_DATA64_EN; | 814 | sc->sc_cfg |= CFG_DATA64_EN; | |
812 | printf(", using 64-bit data transfers"); | 815 | printf(", using 64-bit data transfers"); | |
813 | } | 816 | } | |
814 | printf("\n"); | 817 | printf("\n"); | |
815 | } | 818 | } | |
816 | 819 | |||
817 | /* | 820 | /* | |
818 | * XXX Need some PCI flags indicating support for | 821 | * XXX Need some PCI flags indicating support for | |
819 | * XXX 64-bit addressing. | 822 | * XXX 64-bit addressing. | |
820 | */ | 823 | */ | |
821 | #if 0 | 824 | #if 0 | |
822 | if (reg & CFG_M64ADDR) | 825 | if (reg & CFG_M64ADDR) | |
823 | sc->sc_cfg |= CFG_M64ADDR; | 826 | sc->sc_cfg |= CFG_M64ADDR; | |
824 | if (reg & CFG_T64ADDR) | 827 | if (reg & CFG_T64ADDR) | |
825 | sc->sc_cfg |= CFG_T64ADDR; | 828 | sc->sc_cfg |= CFG_T64ADDR; | |
826 | #endif | 829 | #endif | |
827 | 830 | |||
828 | if (reg & (CFG_TBI_EN|CFG_EXT_125)) { | 831 | if (reg & (CFG_TBI_EN|CFG_EXT_125)) { | |
829 | const char *sep = ""; | 832 | const char *sep = ""; | |
830 | printf("%s: using ", device_xname(sc->sc_dev)); | 833 | printf("%s: using ", device_xname(sc->sc_dev)); | |
831 | if (reg & CFG_EXT_125) { | 834 | if (reg & CFG_EXT_125) { | |
832 | sc->sc_cfg |= CFG_EXT_125; | 835 | sc->sc_cfg |= CFG_EXT_125; | |
833 | printf("%s125MHz clock", sep); | 836 | printf("%s125MHz clock", sep); | |
834 | sep = ", "; | 837 | sep = ", "; | |
835 | } | 838 | } | |
836 | if (reg & CFG_TBI_EN) { | 839 | if (reg & CFG_TBI_EN) { | |
837 | sc->sc_cfg |= CFG_TBI_EN; | 840 | sc->sc_cfg |= CFG_TBI_EN; | |
838 | printf("%sten-bit interface", sep); | 841 | printf("%sten-bit interface", sep); | |
839 | sep = ", "; | 842 | sep = ", "; | |
840 | } | 843 | } | |
841 | printf("\n"); | 844 | printf("\n"); | |
842 | } | 845 | } | |
843 | if ((pa->pa_flags & PCI_FLAGS_MRM_OKAY) == 0 || | 846 | if ((pa->pa_flags & PCI_FLAGS_MRM_OKAY) == 0 || | |
844 | (reg & CFG_MRM_DIS) != 0) | 847 | (reg & CFG_MRM_DIS) != 0) | |
845 | sc->sc_cfg |= CFG_MRM_DIS; | 848 | sc->sc_cfg |= CFG_MRM_DIS; | |
846 | if ((pa->pa_flags & PCI_FLAGS_MWI_OKAY) == 0 || | 849 | if ((pa->pa_flags & PCI_FLAGS_MWI_OKAY) == 0 || | |
847 | (reg & CFG_MWI_DIS) != 0) | 850 | (reg & CFG_MWI_DIS) != 0) | |
848 | sc->sc_cfg |= CFG_MWI_DIS; | 851 | sc->sc_cfg |= CFG_MWI_DIS; | |
849 | 852 | |||
850 | /* | 853 | /* | |
851 | * Use the extended descriptor format on the DP83820. This | 854 | * Use the extended descriptor format on the DP83820. This | |
852 | * gives us an interface to VLAN tagging and IPv4/TCP/UDP | 855 | * gives us an interface to VLAN tagging and IPv4/TCP/UDP | |
853 | * checksumming. | 856 | * checksumming. | |
854 | */ | 857 | */ | |
855 | sc->sc_cfg |= CFG_EXTSTS_EN; | 858 | sc->sc_cfg |= CFG_EXTSTS_EN; | |
856 | } | 859 | } | |
857 | 860 | |||
858 | static int | 861 | static int | |
859 | sipcom_detach(device_t self, int flags) | 862 | sipcom_detach(device_t self, int flags) | |
860 | { | 863 | { | |
861 | int s; | 864 | int s; | |
862 | 865 | |||
863 | s = splnet(); | 866 | s = splnet(); | |
864 | sipcom_do_detach(self, SIP_ATTACH_FIN); | 867 | sipcom_do_detach(self, SIP_ATTACH_FIN); | |
865 | splx(s); | 868 | splx(s); | |
866 | 869 | |||
867 | return 0; | 870 | return 0; | |
868 | } | 871 | } | |
869 | 872 | |||
870 | static void | 873 | static void | |
871 | sipcom_do_detach(device_t self, enum sip_attach_stage stage) | 874 | sipcom_do_detach(device_t self, enum sip_attach_stage stage) | |
872 | { | 875 | { | |
873 | int i; | 876 | int i; | |
874 | struct sip_softc *sc = device_private(self); | 877 | struct sip_softc *sc = device_private(self); | |
875 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | 878 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | |
876 | 879 | |||
877 | /* | 880 | /* | |
878 | * Free any resources we've allocated during attach. | 881 | * Free any resources we've allocated during attach. | |
879 | * Do this in reverse order and fall through. | 882 | * Do this in reverse order and fall through. | |
880 | */ | 883 | */ | |
881 | switch (stage) { | 884 | switch (stage) { | |
882 | case SIP_ATTACH_FIN: | 885 | case SIP_ATTACH_FIN: | |
883 | sipcom_stop(ifp, 1); | 886 | sipcom_stop(ifp, 1); | |
884 | pmf_device_deregister(self); | 887 | pmf_device_deregister(self); | |
885 | #ifdef SIP_EVENT_COUNTERS | 888 | #ifdef SIP_EVENT_COUNTERS | |
886 | /* | 889 | /* | |
887 | * Attach event counters. | 890 | * Attach event counters. | |
888 | */ | 891 | */ | |
889 | evcnt_detach(&sc->sc_ev_txforceintr); | 892 | evcnt_detach(&sc->sc_ev_txforceintr); | |
890 | evcnt_detach(&sc->sc_ev_txdstall); | 893 | evcnt_detach(&sc->sc_ev_txdstall); | |
891 | evcnt_detach(&sc->sc_ev_txsstall); | 894 | evcnt_detach(&sc->sc_ev_txsstall); | |
892 | evcnt_detach(&sc->sc_ev_hiberr); | 895 | evcnt_detach(&sc->sc_ev_hiberr); | |
893 | evcnt_detach(&sc->sc_ev_rxintr); | 896 | evcnt_detach(&sc->sc_ev_rxintr); | |
894 | evcnt_detach(&sc->sc_ev_txiintr); | 897 | evcnt_detach(&sc->sc_ev_txiintr); | |
895 | evcnt_detach(&sc->sc_ev_txdintr); | 898 | evcnt_detach(&sc->sc_ev_txdintr); | |
896 | if (!sc->sc_gigabit) { | 899 | if (!sc->sc_gigabit) { | |
897 | evcnt_detach(&sc->sc_ev_rxpause); | 900 | evcnt_detach(&sc->sc_ev_rxpause); | |
898 | } else { | 901 | } else { | |
899 | evcnt_detach(&sc->sc_ev_txudpsum); | 902 | evcnt_detach(&sc->sc_ev_txudpsum); | |
900 | evcnt_detach(&sc->sc_ev_txtcpsum); | 903 | evcnt_detach(&sc->sc_ev_txtcpsum); | |
901 | evcnt_detach(&sc->sc_ev_txipsum); | 904 | evcnt_detach(&sc->sc_ev_txipsum); | |
902 | evcnt_detach(&sc->sc_ev_rxudpsum); | 905 | evcnt_detach(&sc->sc_ev_rxudpsum); | |
903 | evcnt_detach(&sc->sc_ev_rxtcpsum); | 906 | evcnt_detach(&sc->sc_ev_rxtcpsum); | |
904 | evcnt_detach(&sc->sc_ev_rxipsum); | 907 | evcnt_detach(&sc->sc_ev_rxipsum); | |
905 | evcnt_detach(&sc->sc_ev_txpause); | 908 | evcnt_detach(&sc->sc_ev_txpause); | |
906 | evcnt_detach(&sc->sc_ev_rxpause); | 909 | evcnt_detach(&sc->sc_ev_rxpause); | |
907 | } | 910 | } | |
908 | #endif /* SIP_EVENT_COUNTERS */ | 911 | #endif /* SIP_EVENT_COUNTERS */ | |
909 | 912 | |||
910 | rnd_detach_source(&sc->rnd_source); | 913 | rnd_detach_source(&sc->rnd_source); | |
911 | 914 | |||
912 | ether_ifdetach(ifp); | 915 | ether_ifdetach(ifp); | |
913 | if_detach(ifp); | 916 | if_detach(ifp); | |
914 | mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY); | 917 | mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY); | |
915 | 918 | |||
916 | /*FALLTHROUGH*/ | 919 | /*FALLTHROUGH*/ | |
917 | case SIP_ATTACH_CREATE_RXMAP: | 920 | case SIP_ATTACH_CREATE_RXMAP: | |
918 | for (i = 0; i < sc->sc_parm->p_nrxdesc; i++) { | 921 | for (i = 0; i < sc->sc_parm->p_nrxdesc; i++) { | |
919 | if (sc->sc_rxsoft[i].rxs_dmamap != NULL) | 922 | if (sc->sc_rxsoft[i].rxs_dmamap != NULL) | |
920 | bus_dmamap_destroy(sc->sc_dmat, | 923 | bus_dmamap_destroy(sc->sc_dmat, | |
921 | sc->sc_rxsoft[i].rxs_dmamap); | 924 | sc->sc_rxsoft[i].rxs_dmamap); | |
922 | } | 925 | } | |
923 | /*FALLTHROUGH*/ | 926 | /*FALLTHROUGH*/ | |
924 | case SIP_ATTACH_CREATE_TXMAP: | 927 | case SIP_ATTACH_CREATE_TXMAP: | |
925 | for (i = 0; i < SIP_TXQUEUELEN; i++) { | 928 | for (i = 0; i < SIP_TXQUEUELEN; i++) { | |
926 | if (sc->sc_txsoft[i].txs_dmamap != NULL) | 929 | if (sc->sc_txsoft[i].txs_dmamap != NULL) | |
927 | bus_dmamap_destroy(sc->sc_dmat, | 930 | bus_dmamap_destroy(sc->sc_dmat, | |
928 | sc->sc_txsoft[i].txs_dmamap); | 931 | sc->sc_txsoft[i].txs_dmamap); | |
929 | } | 932 | } | |
930 | /*FALLTHROUGH*/ | 933 | /*FALLTHROUGH*/ | |
931 | case SIP_ATTACH_LOAD_MAP: | 934 | case SIP_ATTACH_LOAD_MAP: | |
932 | bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap); | 935 | bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap); | |
933 | /*FALLTHROUGH*/ | 936 | /*FALLTHROUGH*/ | |
934 | case SIP_ATTACH_CREATE_MAP: | 937 | case SIP_ATTACH_CREATE_MAP: | |
935 | bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap); | 938 | bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap); | |
936 | /*FALLTHROUGH*/ | 939 | /*FALLTHROUGH*/ | |
937 | case SIP_ATTACH_MAP_MEM: | 940 | case SIP_ATTACH_MAP_MEM: | |
938 | bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data, | 941 | bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data, | |
939 | sizeof(struct sip_control_data)); | 942 | sizeof(struct sip_control_data)); | |
940 | /*FALLTHROUGH*/ | 943 | /*FALLTHROUGH*/ | |
941 | case SIP_ATTACH_ALLOC_MEM: | 944 | case SIP_ATTACH_ALLOC_MEM: | |
942 | bus_dmamem_free(sc->sc_dmat, &sc->sc_seg, 1); | 945 | bus_dmamem_free(sc->sc_dmat, &sc->sc_seg, 1); | |
943 | /* FALLTHROUGH*/ | 946 | /* FALLTHROUGH*/ | |
944 | case SIP_ATTACH_INTR: | 947 | case SIP_ATTACH_INTR: | |
945 | pci_intr_disestablish(sc->sc_pc, sc->sc_ih); | 948 | pci_intr_disestablish(sc->sc_pc, sc->sc_ih); | |
946 | /* FALLTHROUGH*/ | 949 | /* FALLTHROUGH*/ | |
947 | case SIP_ATTACH_MAP: | 950 | case SIP_ATTACH_MAP: | |
948 | bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz); | 951 | bus_space_unmap(sc->sc_st, sc->sc_sh, sc->sc_sz); | |
949 | break; | 952 | break; | |
950 | default: | 953 | default: | |
951 | break; | 954 | break; | |
952 | } | 955 | } | |
953 | return; | 956 | return; | |
954 | } | 957 | } | |
955 | 958 | |||
956 | static bool | 959 | static bool | |
957 | sipcom_resume(device_t self, const pmf_qual_t *qual) | 960 | sipcom_resume(device_t self, const pmf_qual_t *qual) | |
958 | { | 961 | { | |
959 | struct sip_softc *sc = device_private(self); | 962 | struct sip_softc *sc = device_private(self); | |
960 | 963 | |||
961 | return sipcom_reset(sc); | 964 | return sipcom_reset(sc); | |
962 | } | 965 | } | |
963 | 966 | |||
964 | static bool | 967 | static bool | |
965 | sipcom_suspend(device_t self, const pmf_qual_t *qual) | 968 | sipcom_suspend(device_t self, const pmf_qual_t *qual) | |
966 | { | 969 | { | |
967 | struct sip_softc *sc = device_private(self); | 970 | struct sip_softc *sc = device_private(self); | |
968 | 971 | |||
969 | sipcom_rxdrain(sc); | 972 | sipcom_rxdrain(sc); | |
970 | return true; | 973 | return true; | |
971 | } | 974 | } | |
972 | 975 | |||
973 | static void | 976 | static void | |
974 | sipcom_attach(device_t parent, device_t self, void *aux) | 977 | sipcom_attach(device_t parent, device_t self, void *aux) | |
975 | { | 978 | { | |
976 | struct sip_softc *sc = device_private(self); | 979 | struct sip_softc *sc = device_private(self); | |
977 | struct pci_attach_args *pa = aux; | 980 | struct pci_attach_args *pa = aux; | |
978 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | 981 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | |
979 | pci_chipset_tag_t pc = pa->pa_pc; | 982 | pci_chipset_tag_t pc = pa->pa_pc; | |
980 | pci_intr_handle_t ih; | 983 | pci_intr_handle_t ih; | |
981 | const char *intrstr = NULL; | 984 | const char *intrstr = NULL; | |
982 | bus_space_tag_t iot, memt; | 985 | bus_space_tag_t iot, memt; | |
983 | bus_space_handle_t ioh, memh; | 986 | bus_space_handle_t ioh, memh; | |
984 | bus_size_t iosz, memsz; | 987 | bus_size_t iosz, memsz; | |
985 | int ioh_valid, memh_valid; | 988 | int ioh_valid, memh_valid; | |
986 | int i, rseg, error; | 989 | int i, rseg, error; | |
987 | const struct sip_product *sip; | 990 | const struct sip_product *sip; | |
988 | u_int8_t enaddr[ETHER_ADDR_LEN]; | 991 | u_int8_t enaddr[ETHER_ADDR_LEN]; | |
989 | pcireg_t csr; | 992 | pcireg_t csr; | |
990 | pcireg_t memtype; | 993 | pcireg_t memtype; | |
991 | bus_size_t tx_dmamap_size; | 994 | bus_size_t tx_dmamap_size; | |
992 | int ntxsegs_alloc; | 995 | int ntxsegs_alloc; | |
993 | cfdata_t cf = device_cfdata(self); | 996 | cfdata_t cf = device_cfdata(self); | |
994 | 997 | |||
995 | callout_init(&sc->sc_tick_ch, 0); | 998 | callout_init(&sc->sc_tick_ch, 0); | |
996 | 999 | |||
997 | sip = sipcom_lookup(pa, strcmp(cf->cf_name, "gsip") == 0); | 1000 | sip = sipcom_lookup(pa, strcmp(cf->cf_name, "gsip") == 0); | |
998 | if (sip == NULL) { | 1001 | if (sip == NULL) { | |
999 | printf("\n"); | 1002 | printf("\n"); | |
1000 | panic("%s: impossible", __func__); | 1003 | panic("%s: impossible", __func__); | |
1001 | } | 1004 | } | |
1002 | sc->sc_dev = self; | 1005 | sc->sc_dev = self; | |
1003 | sc->sc_gigabit = sip->sip_gigabit; | 1006 | sc->sc_gigabit = sip->sip_gigabit; | |
1004 | pmf_self_suspensor_init(self, &sc->sc_suspensor, &sc->sc_qual); | 1007 | pmf_self_suspensor_init(self, &sc->sc_suspensor, &sc->sc_qual); | |
1005 | sc->sc_pc = pc; | 1008 | sc->sc_pc = pc; | |
1006 | 1009 | |||
1007 | if (sc->sc_gigabit) { | 1010 | if (sc->sc_gigabit) { | |
1008 | sc->sc_rxintr = gsip_rxintr; | 1011 | sc->sc_rxintr = gsip_rxintr; | |
1009 | sc->sc_parm = &gsip_parm; | 1012 | sc->sc_parm = &gsip_parm; | |
1010 | } else { | 1013 | } else { | |
1011 | sc->sc_rxintr = sip_rxintr; | 1014 | sc->sc_rxintr = sip_rxintr; | |
1012 | sc->sc_parm = &sip_parm; | 1015 | sc->sc_parm = &sip_parm; | |
1013 | } | 1016 | } | |
1014 | tx_dmamap_size = sc->sc_parm->p_tx_dmamap_size; | 1017 | tx_dmamap_size = sc->sc_parm->p_tx_dmamap_size; | |
1015 | ntxsegs_alloc = sc->sc_parm->p_ntxsegs_alloc; | 1018 | ntxsegs_alloc = sc->sc_parm->p_ntxsegs_alloc; | |
1016 | sc->sc_ntxdesc = SIP_TXQUEUELEN * ntxsegs_alloc; | 1019 | sc->sc_ntxdesc = SIP_TXQUEUELEN * ntxsegs_alloc; | |
1017 | sc->sc_ntxdesc_mask = sc->sc_ntxdesc - 1; | 1020 | sc->sc_ntxdesc_mask = sc->sc_ntxdesc - 1; | |
1018 | sc->sc_nrxdesc_mask = sc->sc_parm->p_nrxdesc - 1; | 1021 | sc->sc_nrxdesc_mask = sc->sc_parm->p_nrxdesc - 1; | |
1019 | 1022 | |||
1020 | sc->sc_rev = PCI_REVISION(pa->pa_class); | 1023 | sc->sc_rev = PCI_REVISION(pa->pa_class); | |
1021 | 1024 | |||
1022 | printf(": %s, rev %#02x\n", sip->sip_name, sc->sc_rev); | 1025 | printf(": %s, rev %#02x\n", sip->sip_name, sc->sc_rev); | |
1023 | 1026 | |||
1024 | sc->sc_model = sip; | 1027 | sc->sc_model = sip; | |
1025 | 1028 | |||
1026 | /* | 1029 | /* | |
1027 | * XXX Work-around broken PXE firmware on some boards. | 1030 | * XXX Work-around broken PXE firmware on some boards. | |
1028 | * | 1031 | * | |
1029 | * The DP83815 shares an address decoder with the MEM BAR | 1032 | * The DP83815 shares an address decoder with the MEM BAR | |
1030 | * and the ROM BAR. Make sure the ROM BAR is disabled, | 1033 | * and the ROM BAR. Make sure the ROM BAR is disabled, | |
1031 | * so that memory mapped access works. | 1034 | * so that memory mapped access works. | |
1032 | */ | 1035 | */ | |
1033 | pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM, | 1036 | pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM, | |
1034 | pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM) & | 1037 | pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_MAPREG_ROM) & | |
1035 | ~PCI_MAPREG_ROM_ENABLE); | 1038 | ~PCI_MAPREG_ROM_ENABLE); | |
1036 | 1039 | |||
1037 | /* | 1040 | /* | |
1038 | * Map the device. | 1041 | * Map the device. | |
1039 | */ | 1042 | */ | |
1040 | ioh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGIOA, | 1043 | ioh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGIOA, | |
1041 | PCI_MAPREG_TYPE_IO, 0, | 1044 | PCI_MAPREG_TYPE_IO, 0, | |
1042 | &iot, &ioh, NULL, &iosz) == 0); | 1045 | &iot, &ioh, NULL, &iosz) == 0); | |
1043 | if (sc->sc_gigabit) { | 1046 | if (sc->sc_gigabit) { | |
1044 | memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, SIP_PCI_CFGMA); | 1047 | memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, SIP_PCI_CFGMA); | |
1045 | switch (memtype) { | 1048 | switch (memtype) { | |
1046 | case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT: | 1049 | case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT: | |
1047 | case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT: | 1050 | case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT: | |
1048 | memh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGMA, | 1051 | memh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGMA, | |
1049 | memtype, 0, &memt, &memh, NULL, &memsz) == 0); | 1052 | memtype, 0, &memt, &memh, NULL, &memsz) == 0); | |
1050 | break; | 1053 | break; | |
1051 | default: | 1054 | default: | |
1052 | memh_valid = 0; | 1055 | memh_valid = 0; | |
1053 | } | 1056 | } | |
1054 | } else { | 1057 | } else { | |
1055 | memh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGMA, | 1058 | memh_valid = (pci_mapreg_map(pa, SIP_PCI_CFGMA, | |
1056 | PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, | 1059 | PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, | |
1057 | &memt, &memh, NULL, &memsz) == 0); | 1060 | &memt, &memh, NULL, &memsz) == 0); | |
1058 | } | 1061 | } | |
1059 | 1062 | |||
1060 | if (memh_valid) { | 1063 | if (memh_valid) { | |
1061 | sc->sc_st = memt; | 1064 | sc->sc_st = memt; | |
1062 | sc->sc_sh = memh; | 1065 | sc->sc_sh = memh; | |
1063 | sc->sc_sz = memsz; | 1066 | sc->sc_sz = memsz; | |
1064 | } else if (ioh_valid) { | 1067 | } else if (ioh_valid) { | |
1065 | sc->sc_st = iot; | 1068 | sc->sc_st = iot; | |
1066 | sc->sc_sh = ioh; | 1069 | sc->sc_sh = ioh; | |
1067 | sc->sc_sz = iosz; | 1070 | sc->sc_sz = iosz; | |
1068 | } else { | 1071 | } else { | |
1069 | printf("%s: unable to map device registers\n", | 1072 | printf("%s: unable to map device registers\n", | |
1070 | device_xname(sc->sc_dev)); | 1073 | device_xname(sc->sc_dev)); | |
1071 | return; | 1074 | return; | |
1072 | } | 1075 | } | |
1073 | 1076 | |||
1074 | sc->sc_dmat = pa->pa_dmat; | 1077 | sc->sc_dmat = pa->pa_dmat; | |
1075 | 1078 | |||
1076 | /* | 1079 | /* | |
1077 | * Make sure bus mastering is enabled. Also make sure | 1080 | * Make sure bus mastering is enabled. Also make sure | |
1078 | * Write/Invalidate is enabled if we're allowed to use it. | 1081 | * Write/Invalidate is enabled if we're allowed to use it. | |
1079 | */ | 1082 | */ | |
1080 | csr = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); | 1083 | csr = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); | |
1081 | if (pa->pa_flags & PCI_FLAGS_MWI_OKAY) | 1084 | if (pa->pa_flags & PCI_FLAGS_MWI_OKAY) | |
1082 | csr |= PCI_COMMAND_INVALIDATE_ENABLE; | 1085 | csr |= PCI_COMMAND_INVALIDATE_ENABLE; | |
1083 | pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, | 1086 | pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, | |
1084 | csr | PCI_COMMAND_MASTER_ENABLE); | 1087 | csr | PCI_COMMAND_MASTER_ENABLE); | |
1085 | 1088 | |||
1086 | /* power up chip */ | 1089 | /* power up chip */ | |
1087 | error = pci_activate(pa->pa_pc, pa->pa_tag, self, pci_activate_null); | 1090 | error = pci_activate(pa->pa_pc, pa->pa_tag, self, pci_activate_null); | |
1088 | if (error != 0 && error != EOPNOTSUPP) { | 1091 | if (error != 0 && error != EOPNOTSUPP) { | |
1089 | aprint_error_dev(sc->sc_dev, "cannot activate %d\n", error); | 1092 | aprint_error_dev(sc->sc_dev, "cannot activate %d\n", error); | |
1090 | return; | 1093 | return; | |
1091 | } | 1094 | } | |
1092 | 1095 | |||
1093 | /* | 1096 | /* | |
1094 | * Map and establish our interrupt. | 1097 | * Map and establish our interrupt. | |
1095 | */ | 1098 | */ | |
1096 | if (pci_intr_map(pa, &ih)) { | 1099 | if (pci_intr_map(pa, &ih)) { | |
1097 | aprint_error_dev(sc->sc_dev, "unable to map interrupt\n"); | 1100 | aprint_error_dev(sc->sc_dev, "unable to map interrupt\n"); | |
1098 | return; | 1101 | return; | |
1099 | } | 1102 | } | |
1100 | intrstr = pci_intr_string(pc, ih); | 1103 | intrstr = pci_intr_string(pc, ih); | |
1101 | sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, sipcom_intr, sc); | 1104 | sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, sipcom_intr, sc); | |
1102 | if (sc->sc_ih == NULL) { | 1105 | if (sc->sc_ih == NULL) { | |
1103 | aprint_error_dev(sc->sc_dev, "unable to establish interrupt"); | 1106 | aprint_error_dev(sc->sc_dev, "unable to establish interrupt"); | |
1104 | if (intrstr != NULL) | 1107 | if (intrstr != NULL) | |
1105 | aprint_error(" at %s", intrstr); | 1108 | aprint_error(" at %s", intrstr); | |
1106 | aprint_error("\n"); | 1109 | aprint_error("\n"); | |
1107 | sipcom_do_detach(self, SIP_ATTACH_MAP); | 1110 | sipcom_do_detach(self, SIP_ATTACH_MAP); | |
1108 | return; | 1111 | return; | |
1109 | } | 1112 | } | |
1110 | aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr); | 1113 | aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr); | |
1111 | 1114 | |||
1112 | SIMPLEQ_INIT(&sc->sc_txfreeq); | 1115 | SIMPLEQ_INIT(&sc->sc_txfreeq); | |
1113 | SIMPLEQ_INIT(&sc->sc_txdirtyq); | 1116 | SIMPLEQ_INIT(&sc->sc_txdirtyq); | |
1114 | 1117 | |||
1115 | /* | 1118 | /* | |
1116 | * Allocate the control data structures, and create and load the | 1119 | * Allocate the control data structures, and create and load the | |
1117 | * DMA map for it. | 1120 | * DMA map for it. | |
1118 | */ | 1121 | */ | |
1119 | if ((error = bus_dmamem_alloc(sc->sc_dmat, | 1122 | if ((error = bus_dmamem_alloc(sc->sc_dmat, | |
1120 | sizeof(struct sip_control_data), PAGE_SIZE, 0, &sc->sc_seg, 1, | 1123 | sizeof(struct sip_control_data), PAGE_SIZE, 0, &sc->sc_seg, 1, | |
1121 | &rseg, 0)) != 0) { | 1124 | &rseg, 0)) != 0) { | |
1122 | aprint_error_dev(sc->sc_dev, "unable to allocate control data, error = %d\n", | 1125 | aprint_error_dev(sc->sc_dev, "unable to allocate control data, error = %d\n", | |
1123 | error); | 1126 | error); | |
1124 | sipcom_do_detach(self, SIP_ATTACH_INTR); | 1127 | sipcom_do_detach(self, SIP_ATTACH_INTR); | |
1125 | return; | 1128 | return; | |
1126 | } | 1129 | } | |
1127 | 1130 | |||
1128 | if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_seg, rseg, | 1131 | if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_seg, rseg, | |
1129 | sizeof(struct sip_control_data), (void **)&sc->sc_control_data, | 1132 | sizeof(struct sip_control_data), (void **)&sc->sc_control_data, | |
1130 | BUS_DMA_COHERENT)) != 0) { | 1133 | BUS_DMA_COHERENT)) != 0) { | |
1131 | aprint_error_dev(sc->sc_dev, "unable to map control data, error = %d\n", | 1134 | aprint_error_dev(sc->sc_dev, "unable to map control data, error = %d\n", | |
1132 | error); | 1135 | error); | |
1133 | sipcom_do_detach(self, SIP_ATTACH_ALLOC_MEM); | 1136 | sipcom_do_detach(self, SIP_ATTACH_ALLOC_MEM); | |
1134 | } | 1137 | } | |
1135 | 1138 | |||
1136 | if ((error = bus_dmamap_create(sc->sc_dmat, | 1139 | if ((error = bus_dmamap_create(sc->sc_dmat, | |
1137 | sizeof(struct sip_control_data), 1, | 1140 | sizeof(struct sip_control_data), 1, | |
1138 | sizeof(struct sip_control_data), 0, 0, &sc->sc_cddmamap)) != 0) { | 1141 | sizeof(struct sip_control_data), 0, 0, &sc->sc_cddmamap)) != 0) { | |
1139 | aprint_error_dev(sc->sc_dev, "unable to create control data DMA map, " | 1142 | aprint_error_dev(sc->sc_dev, "unable to create control data DMA map, " | |
1140 | "error = %d\n", error); | 1143 | "error = %d\n", error); | |
1141 | sipcom_do_detach(self, SIP_ATTACH_MAP_MEM); | 1144 | sipcom_do_detach(self, SIP_ATTACH_MAP_MEM); | |
1142 | } | 1145 | } | |
1143 | 1146 | |||
1144 | if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap, | 1147 | if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap, | |
1145 | sc->sc_control_data, sizeof(struct sip_control_data), NULL, | 1148 | sc->sc_control_data, sizeof(struct sip_control_data), NULL, | |
1146 | 0)) != 0) { | 1149 | 0)) != 0) { | |
1147 | aprint_error_dev(sc->sc_dev, "unable to load control data DMA map, error = %d\n", | 1150 | aprint_error_dev(sc->sc_dev, "unable to load control data DMA map, error = %d\n", | |
1148 | error); | 1151 | error); | |
1149 | sipcom_do_detach(self, SIP_ATTACH_CREATE_MAP); | 1152 | sipcom_do_detach(self, SIP_ATTACH_CREATE_MAP); | |
1150 | } | 1153 | } | |
1151 | 1154 | |||
1152 | /* | 1155 | /* | |
1153 | * Create the transmit buffer DMA maps. | 1156 | * Create the transmit buffer DMA maps. | |
1154 | */ | 1157 | */ | |
1155 | for (i = 0; i < SIP_TXQUEUELEN; i++) { | 1158 | for (i = 0; i < SIP_TXQUEUELEN; i++) { | |
1156 | if ((error = bus_dmamap_create(sc->sc_dmat, tx_dmamap_size, | 1159 | if ((error = bus_dmamap_create(sc->sc_dmat, tx_dmamap_size, | |
1157 | sc->sc_parm->p_ntxsegs, MCLBYTES, 0, 0, | 1160 | sc->sc_parm->p_ntxsegs, MCLBYTES, 0, 0, | |
1158 | &sc->sc_txsoft[i].txs_dmamap)) != 0) { | 1161 | &sc->sc_txsoft[i].txs_dmamap)) != 0) { | |
1159 | aprint_error_dev(sc->sc_dev, "unable to create tx DMA map %d, " | 1162 | aprint_error_dev(sc->sc_dev, "unable to create tx DMA map %d, " | |
1160 | "error = %d\n", i, error); | 1163 | "error = %d\n", i, error); | |
1161 | sipcom_do_detach(self, SIP_ATTACH_CREATE_TXMAP); | 1164 | sipcom_do_detach(self, SIP_ATTACH_CREATE_TXMAP); | |
1162 | } | 1165 | } | |
1163 | } | 1166 | } | |
1164 | 1167 | |||
1165 | /* | 1168 | /* | |
1166 | * Create the receive buffer DMA maps. | 1169 | * Create the receive buffer DMA maps. | |
1167 | */ | 1170 | */ | |
1168 | for (i = 0; i < sc->sc_parm->p_nrxdesc; i++) { | 1171 | for (i = 0; i < sc->sc_parm->p_nrxdesc; i++) { | |
1169 | if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, | 1172 | if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, | |
1170 | MCLBYTES, 0, 0, &sc->sc_rxsoft[i].rxs_dmamap)) != 0) { | 1173 | MCLBYTES, 0, 0, &sc->sc_rxsoft[i].rxs_dmamap)) != 0) { | |
1171 | aprint_error_dev(sc->sc_dev, "unable to create rx DMA map %d, " | 1174 | aprint_error_dev(sc->sc_dev, "unable to create rx DMA map %d, " | |
1172 | "error = %d\n", i, error); | 1175 | "error = %d\n", i, error); | |
1173 | sipcom_do_detach(self, SIP_ATTACH_CREATE_RXMAP); | 1176 | sipcom_do_detach(self, SIP_ATTACH_CREATE_RXMAP); | |
1174 | } | 1177 | } | |
1175 | sc->sc_rxsoft[i].rxs_mbuf = NULL; | 1178 | sc->sc_rxsoft[i].rxs_mbuf = NULL; | |
1176 | } | 1179 | } | |
1177 | 1180 | |||
1178 | /* | 1181 | /* | |
1179 | * Reset the chip to a known state. | 1182 | * Reset the chip to a known state. | |
1180 | */ | 1183 | */ | |
1181 | sipcom_reset(sc); | 1184 | sipcom_reset(sc); | |
1182 | 1185 | |||
1183 | /* | 1186 | /* | |
1184 | * Read the Ethernet address from the EEPROM. This might | 1187 | * Read the Ethernet address from the EEPROM. This might | |
1185 | * also fetch other stuff from the EEPROM and stash it | 1188 | * also fetch other stuff from the EEPROM and stash it | |
1186 | * in the softc. | 1189 | * in the softc. | |
1187 | */ | 1190 | */ | |
1188 | sc->sc_cfg = 0; | 1191 | sc->sc_cfg = 0; | |
1189 | if (!sc->sc_gigabit) { | 1192 | if (!sc->sc_gigabit) { | |
1190 | if (SIP_SIS900_REV(sc,SIS_REV_635) || | 1193 | if (SIP_SIS900_REV(sc,SIS_REV_635) || | |
1191 | SIP_SIS900_REV(sc,SIS_REV_900B)) | 1194 | SIP_SIS900_REV(sc,SIS_REV_900B)) | |
1192 | sc->sc_cfg |= (CFG_PESEL | CFG_RNDCNT); | 1195 | sc->sc_cfg |= (CFG_PESEL | CFG_RNDCNT); | |
1193 | 1196 | |||
1194 | if (SIP_SIS900_REV(sc,SIS_REV_635) || | 1197 | if (SIP_SIS900_REV(sc,SIS_REV_635) || | |
1195 | SIP_SIS900_REV(sc,SIS_REV_960) || | 1198 | SIP_SIS900_REV(sc,SIS_REV_960) || | |
1196 | SIP_SIS900_REV(sc,SIS_REV_900B)) | 1199 | SIP_SIS900_REV(sc,SIS_REV_900B)) | |
1197 | sc->sc_cfg |= | 1200 | sc->sc_cfg |= | |
1198 | (bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_CFG) & | 1201 | (bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_CFG) & | |
1199 | CFG_EDBMASTEN); | 1202 | CFG_EDBMASTEN); | |
1200 | } | 1203 | } | |
1201 | 1204 | |||
1202 | (*sip->sip_variant->sipv_read_macaddr)(sc, pa, enaddr); | 1205 | (*sip->sip_variant->sipv_read_macaddr)(sc, pa, enaddr); | |
1203 | 1206 | |||
1204 | printf("%s: Ethernet address %s\n", device_xname(sc->sc_dev), | 1207 | printf("%s: Ethernet address %s\n", device_xname(sc->sc_dev), | |
1205 | ether_sprintf(enaddr)); | 1208 | ether_sprintf(enaddr)); | |
1206 | 1209 | |||
1207 | /* | 1210 | /* | |
1208 | * Initialize the configuration register: aggressive PCI | 1211 | * Initialize the configuration register: aggressive PCI | |
1209 | * bus request algorithm, default backoff, default OW timer, | 1212 | * bus request algorithm, default backoff, default OW timer, | |
1210 | * default parity error detection. | 1213 | * default parity error detection. | |
1211 | * | 1214 | * | |
1212 | * NOTE: "Big endian mode" is useless on the SiS900 and | 1215 | * NOTE: "Big endian mode" is useless on the SiS900 and | |
1213 | * friends -- it affects packet data, not descriptors. | 1216 | * friends -- it affects packet data, not descriptors. | |
1214 | */ | 1217 | */ | |
1215 | if (sc->sc_gigabit) | 1218 | if (sc->sc_gigabit) | |
1216 | sipcom_dp83820_attach(sc, pa); | 1219 | sipcom_dp83820_attach(sc, pa); | |
1217 | 1220 | |||
1218 | /* | 1221 | /* | |
1219 | * Initialize our media structures and probe the MII. | 1222 | * Initialize our media structures and probe the MII. | |
1220 | */ | 1223 | */ | |
1221 | sc->sc_mii.mii_ifp = ifp; | 1224 | sc->sc_mii.mii_ifp = ifp; | |
1222 | sc->sc_mii.mii_readreg = sip->sip_variant->sipv_mii_readreg; | 1225 | sc->sc_mii.mii_readreg = sip->sip_variant->sipv_mii_readreg; | |
1223 | sc->sc_mii.mii_writereg = sip->sip_variant->sipv_mii_writereg; | 1226 | sc->sc_mii.mii_writereg = sip->sip_variant->sipv_mii_writereg; | |
1224 | sc->sc_mii.mii_statchg = sip->sip_variant->sipv_mii_statchg; | 1227 | sc->sc_mii.mii_statchg = sip->sip_variant->sipv_mii_statchg; | |
1225 | sc->sc_ethercom.ec_mii = &sc->sc_mii; | 1228 | sc->sc_ethercom.ec_mii = &sc->sc_mii; | |
1226 | ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK, ether_mediachange, | 1229 | ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK, ether_mediachange, | |
1227 | sipcom_mediastatus); | 1230 | sipcom_mediastatus); | |
1228 | 1231 | |||
1229 | /* | 1232 | /* | |
1230 | * XXX We cannot handle flow control on the DP83815. | 1233 | * XXX We cannot handle flow control on the DP83815. | |
1231 | */ | 1234 | */ | |
1232 | if (SIP_CHIP_MODEL(sc, PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83815)) | 1235 | if (SIP_CHIP_MODEL(sc, PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83815)) | |
1233 | mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, | 1236 | mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, | |
1234 | MII_OFFSET_ANY, 0); | 1237 | MII_OFFSET_ANY, 0); | |
1235 | else | 1238 | else | |
1236 | mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, | 1239 | mii_attach(sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, | |
1237 | MII_OFFSET_ANY, MIIF_DOPAUSE); | 1240 | MII_OFFSET_ANY, MIIF_DOPAUSE); | |
1238 | if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { | 1241 | if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { | |
1239 | ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL); | 1242 | ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL); | |
1240 | ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE); | 1243 | ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE); | |
1241 | } else | 1244 | } else | |
1242 | ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO); | 1245 | ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO); | |
1243 | 1246 | |||
1244 | ifp = &sc->sc_ethercom.ec_if; | 1247 | ifp = &sc->sc_ethercom.ec_if; | |
1245 | strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); | 1248 | strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); | |
1246 | ifp->if_softc = sc; | 1249 | ifp->if_softc = sc; | |
1247 | ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | 1250 | ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | |
1248 | sc->sc_if_flags = ifp->if_flags; | 1251 | sc->sc_if_flags = ifp->if_flags; | |
1249 | ifp->if_ioctl = sipcom_ioctl; | 1252 | ifp->if_ioctl = sipcom_ioctl; | |
1250 | ifp->if_start = sipcom_start; | 1253 | ifp->if_start = sipcom_start; | |
1251 | ifp->if_watchdog = sipcom_watchdog; | 1254 | ifp->if_watchdog = sipcom_watchdog; | |
1252 | ifp->if_init = sipcom_init; | 1255 | ifp->if_init = sipcom_init; | |
1253 | ifp->if_stop = sipcom_stop; | 1256 | ifp->if_stop = sipcom_stop; | |
1254 | IFQ_SET_READY(&ifp->if_snd); | 1257 | IFQ_SET_READY(&ifp->if_snd); | |
1255 | 1258 | |||
1256 | /* | 1259 | /* | |
1257 | * We can support 802.1Q VLAN-sized frames. | 1260 | * We can support 802.1Q VLAN-sized frames. | |
1258 | */ | 1261 | */ | |
1259 | sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; | 1262 | sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; | |
1260 | 1263 | |||
1261 | if (sc->sc_gigabit) { | 1264 | if (sc->sc_gigabit) { | |
1262 | /* | 1265 | /* | |
1263 | * And the DP83820 can do VLAN tagging in hardware, and | 1266 | * And the DP83820 can do VLAN tagging in hardware, and | |
1264 | * support the jumbo Ethernet MTU. | 1267 | * support the jumbo Ethernet MTU. | |
1265 | */ | 1268 | */ | |
1266 | sc->sc_ethercom.ec_capabilities |= | 1269 | sc->sc_ethercom.ec_capabilities |= | |
1267 | ETHERCAP_VLAN_HWTAGGING | ETHERCAP_JUMBO_MTU; | 1270 | ETHERCAP_VLAN_HWTAGGING | ETHERCAP_JUMBO_MTU; | |
1268 | 1271 | |||
1269 | /* | 1272 | /* | |
1270 | * The DP83820 can do IPv4, TCPv4, and UDPv4 checksums | 1273 | * The DP83820 can do IPv4, TCPv4, and UDPv4 checksums | |
1271 | * in hardware. | 1274 | * in hardware. | |
1272 | */ | 1275 | */ | |
1273 | ifp->if_capabilities |= | 1276 | ifp->if_capabilities |= | |
1274 | IFCAP_CSUM_IPv4_Tx | IFCAP_CSUM_IPv4_Rx | | 1277 | IFCAP_CSUM_IPv4_Tx | IFCAP_CSUM_IPv4_Rx | | |
1275 | IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_TCPv4_Rx | | 1278 | IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_TCPv4_Rx | | |
1276 | IFCAP_CSUM_UDPv4_Tx | IFCAP_CSUM_UDPv4_Rx; | 1279 | IFCAP_CSUM_UDPv4_Tx | IFCAP_CSUM_UDPv4_Rx; | |
1277 | } | 1280 | } | |
1278 | 1281 | |||
1279 | /* | 1282 | /* | |
1280 | * Attach the interface. | 1283 | * Attach the interface. | |
1281 | */ | 1284 | */ | |
1282 | if_attach(ifp); | 1285 | if_attach(ifp); | |
1283 | ether_ifattach(ifp, enaddr); | 1286 | ether_ifattach(ifp, enaddr); | |
1284 | ether_set_ifflags_cb(&sc->sc_ethercom, sip_ifflags_cb); | 1287 | ether_set_ifflags_cb(&sc->sc_ethercom, sip_ifflags_cb); | |
1285 | sc->sc_prev.ec_capenable = sc->sc_ethercom.ec_capenable; | 1288 | sc->sc_prev.ec_capenable = sc->sc_ethercom.ec_capenable; | |
1286 | sc->sc_prev.is_vlan = VLAN_ATTACHED(&(sc)->sc_ethercom); | 1289 | sc->sc_prev.is_vlan = VLAN_ATTACHED(&(sc)->sc_ethercom); | |
1287 | sc->sc_prev.if_capenable = ifp->if_capenable; | 1290 | sc->sc_prev.if_capenable = ifp->if_capenable; | |
1288 | rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), | 1291 | rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev), | |
1289 | RND_TYPE_NET, 0); | 1292 | RND_TYPE_NET, 0); | |
1290 | 1293 | |||
1291 | /* | 1294 | /* | |
1292 | * The number of bytes that must be available in | 1295 | * The number of bytes that must be available in | |
1293 | * the Tx FIFO before the bus master can DMA more | 1296 | * the Tx FIFO before the bus master can DMA more | |
1294 | * data into the FIFO. | 1297 | * data into the FIFO. | |
1295 | */ | 1298 | */ | |
1296 | sc->sc_tx_fill_thresh = 64 / 32; | 1299 | sc->sc_tx_fill_thresh = 64 / 32; | |
1297 | 1300 | |||
1298 | /* | 1301 | /* | |
1299 | * Start at a drain threshold of 512 bytes. We will | 1302 | * Start at a drain threshold of 512 bytes. We will | |
1300 | * increase it if a DMA underrun occurs. | 1303 | * increase it if a DMA underrun occurs. | |
1301 | * | 1304 | * | |
1302 | * XXX The minimum value of this variable should be | 1305 | * XXX The minimum value of this variable should be | |
1303 | * tuned. We may be able to improve performance | 1306 | * tuned. We may be able to improve performance | |
1304 | * by starting with a lower value. That, however, | 1307 | * by starting with a lower value. That, however, | |
1305 | * may trash the first few outgoing packets if the | 1308 | * may trash the first few outgoing packets if the | |
1306 | * PCI bus is saturated. | 1309 | * PCI bus is saturated. | |
1307 | */ | 1310 | */ | |
1308 | if (sc->sc_gigabit) | 1311 | if (sc->sc_gigabit) | |
1309 | sc->sc_tx_drain_thresh = 6400 / 32; /* from FreeBSD nge(4) */ | 1312 | sc->sc_tx_drain_thresh = 6400 / 32; /* from FreeBSD nge(4) */ | |
1310 | else | 1313 | else | |
1311 | sc->sc_tx_drain_thresh = 1504 / 32; | 1314 | sc->sc_tx_drain_thresh = 1504 / 32; | |
1312 | 1315 | |||
1313 | /* | 1316 | /* | |
1314 | * Initialize the Rx FIFO drain threshold. | 1317 | * Initialize the Rx FIFO drain threshold. | |
1315 | * | 1318 | * | |
1316 | * This is in units of 8 bytes. | 1319 | * This is in units of 8 bytes. | |
1317 | * | 1320 | * | |
1318 | * We should never set this value lower than 2; 14 bytes are | 1321 | * We should never set this value lower than 2; 14 bytes are | |
1319 | * required to filter the packet. | 1322 | * required to filter the packet. | |
1320 | */ | 1323 | */ | |
1321 | sc->sc_rx_drain_thresh = 128 / 8; | 1324 | sc->sc_rx_drain_thresh = 128 / 8; | |
1322 | 1325 | |||
1323 | #ifdef SIP_EVENT_COUNTERS | 1326 | #ifdef SIP_EVENT_COUNTERS | |
1324 | /* | 1327 | /* | |
1325 | * Attach event counters. | 1328 | * Attach event counters. | |
1326 | */ | 1329 | */ | |
1327 | evcnt_attach_dynamic(&sc->sc_ev_txsstall, EVCNT_TYPE_MISC, | 1330 | evcnt_attach_dynamic(&sc->sc_ev_txsstall, EVCNT_TYPE_MISC, | |
1328 | NULL, device_xname(sc->sc_dev), "txsstall"); | 1331 | NULL, device_xname(sc->sc_dev), "txsstall"); | |
1329 | evcnt_attach_dynamic(&sc->sc_ev_txdstall, EVCNT_TYPE_MISC, | 1332 | evcnt_attach_dynamic(&sc->sc_ev_txdstall, EVCNT_TYPE_MISC, | |
1330 | NULL, device_xname(sc->sc_dev), "txdstall"); | 1333 | NULL, device_xname(sc->sc_dev), "txdstall"); | |
1331 | evcnt_attach_dynamic(&sc->sc_ev_txforceintr, EVCNT_TYPE_INTR, | 1334 | evcnt_attach_dynamic(&sc->sc_ev_txforceintr, EVCNT_TYPE_INTR, | |
1332 | NULL, device_xname(sc->sc_dev), "txforceintr"); | 1335 | NULL, device_xname(sc->sc_dev), "txforceintr"); | |
1333 | evcnt_attach_dynamic(&sc->sc_ev_txdintr, EVCNT_TYPE_INTR, | 1336 | evcnt_attach_dynamic(&sc->sc_ev_txdintr, EVCNT_TYPE_INTR, | |
1334 | NULL, device_xname(sc->sc_dev), "txdintr"); | 1337 | NULL, device_xname(sc->sc_dev), "txdintr"); | |
1335 | evcnt_attach_dynamic(&sc->sc_ev_txiintr, EVCNT_TYPE_INTR, | 1338 | evcnt_attach_dynamic(&sc->sc_ev_txiintr, EVCNT_TYPE_INTR, | |
1336 | NULL, device_xname(sc->sc_dev), "txiintr"); | 1339 | NULL, device_xname(sc->sc_dev), "txiintr"); | |
1337 | evcnt_attach_dynamic(&sc->sc_ev_rxintr, EVCNT_TYPE_INTR, | 1340 | evcnt_attach_dynamic(&sc->sc_ev_rxintr, EVCNT_TYPE_INTR, | |
1338 | NULL, device_xname(sc->sc_dev), "rxintr"); | 1341 | NULL, device_xname(sc->sc_dev), "rxintr"); | |
1339 | evcnt_attach_dynamic(&sc->sc_ev_hiberr, EVCNT_TYPE_INTR, | 1342 | evcnt_attach_dynamic(&sc->sc_ev_hiberr, EVCNT_TYPE_INTR, | |
1340 | NULL, device_xname(sc->sc_dev), "hiberr"); | 1343 | NULL, device_xname(sc->sc_dev), "hiberr"); | |
1341 | if (!sc->sc_gigabit) { | 1344 | if (!sc->sc_gigabit) { | |
1342 | evcnt_attach_dynamic(&sc->sc_ev_rxpause, EVCNT_TYPE_INTR, | 1345 | evcnt_attach_dynamic(&sc->sc_ev_rxpause, EVCNT_TYPE_INTR, | |
1343 | NULL, device_xname(sc->sc_dev), "rxpause"); | 1346 | NULL, device_xname(sc->sc_dev), "rxpause"); | |
1344 | } else { | 1347 | } else { | |
1345 | evcnt_attach_dynamic(&sc->sc_ev_rxpause, EVCNT_TYPE_MISC, | 1348 | evcnt_attach_dynamic(&sc->sc_ev_rxpause, EVCNT_TYPE_MISC, | |
1346 | NULL, device_xname(sc->sc_dev), "rxpause"); | 1349 | NULL, device_xname(sc->sc_dev), "rxpause"); | |
1347 | evcnt_attach_dynamic(&sc->sc_ev_txpause, EVCNT_TYPE_MISC, | 1350 | evcnt_attach_dynamic(&sc->sc_ev_txpause, EVCNT_TYPE_MISC, | |
1348 | NULL, device_xname(sc->sc_dev), "txpause"); | 1351 | NULL, device_xname(sc->sc_dev), "txpause"); | |
1349 | evcnt_attach_dynamic(&sc->sc_ev_rxipsum, EVCNT_TYPE_MISC, | 1352 | evcnt_attach_dynamic(&sc->sc_ev_rxipsum, EVCNT_TYPE_MISC, | |
1350 | NULL, device_xname(sc->sc_dev), "rxipsum"); | 1353 | NULL, device_xname(sc->sc_dev), "rxipsum"); | |
1351 | evcnt_attach_dynamic(&sc->sc_ev_rxtcpsum, EVCNT_TYPE_MISC, | 1354 | evcnt_attach_dynamic(&sc->sc_ev_rxtcpsum, EVCNT_TYPE_MISC, | |
1352 | NULL, device_xname(sc->sc_dev), "rxtcpsum"); | 1355 | NULL, device_xname(sc->sc_dev), "rxtcpsum"); | |
1353 | evcnt_attach_dynamic(&sc->sc_ev_rxudpsum, EVCNT_TYPE_MISC, | 1356 | evcnt_attach_dynamic(&sc->sc_ev_rxudpsum, EVCNT_TYPE_MISC, | |
1354 | NULL, device_xname(sc->sc_dev), "rxudpsum"); | 1357 | NULL, device_xname(sc->sc_dev), "rxudpsum"); | |
1355 | evcnt_attach_dynamic(&sc->sc_ev_txipsum, EVCNT_TYPE_MISC, | 1358 | evcnt_attach_dynamic(&sc->sc_ev_txipsum, EVCNT_TYPE_MISC, | |
1356 | NULL, device_xname(sc->sc_dev), "txipsum"); | 1359 | NULL, device_xname(sc->sc_dev), "txipsum"); | |
1357 | evcnt_attach_dynamic(&sc->sc_ev_txtcpsum, EVCNT_TYPE_MISC, | 1360 | evcnt_attach_dynamic(&sc->sc_ev_txtcpsum, EVCNT_TYPE_MISC, | |
1358 | NULL, device_xname(sc->sc_dev), "txtcpsum"); | 1361 | NULL, device_xname(sc->sc_dev), "txtcpsum"); | |
1359 | evcnt_attach_dynamic(&sc->sc_ev_txudpsum, EVCNT_TYPE_MISC, | 1362 | evcnt_attach_dynamic(&sc->sc_ev_txudpsum, EVCNT_TYPE_MISC, | |
1360 | NULL, device_xname(sc->sc_dev), "txudpsum"); | 1363 | NULL, device_xname(sc->sc_dev), "txudpsum"); | |
1361 | } | 1364 | } | |
1362 | #endif /* SIP_EVENT_COUNTERS */ | 1365 | #endif /* SIP_EVENT_COUNTERS */ | |
1363 | 1366 | |||
1364 | if (pmf_device_register(self, sipcom_suspend, sipcom_resume)) | 1367 | if (pmf_device_register(self, sipcom_suspend, sipcom_resume)) | |
1365 | pmf_class_network_register(self, ifp); | 1368 | pmf_class_network_register(self, ifp); | |
1366 | else | 1369 | else | |
1367 | aprint_error_dev(self, "couldn't establish power handler\n"); | 1370 | aprint_error_dev(self, "couldn't establish power handler\n"); | |
1368 | } | 1371 | } | |
1369 | 1372 | |||
1370 | static inline void | 1373 | static inline void | |
1371 | sipcom_set_extsts(struct sip_softc *sc, int lasttx, struct mbuf *m0, | 1374 | sipcom_set_extsts(struct sip_softc *sc, int lasttx, struct mbuf *m0, | |
1372 | uint64_t capenable) | 1375 | uint64_t capenable) | |
1373 | { | 1376 | { | |
1374 | struct m_tag *mtag; | 1377 | struct m_tag *mtag; | |
1375 | u_int32_t extsts; | 1378 | u_int32_t extsts; | |
1376 | #ifdef DEBUG | 1379 | #ifdef DEBUG | |
1377 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | 1380 | struct ifnet *ifp = &sc->sc_ethercom.ec_if; | |
1378 | #endif | 1381 | #endif | |
1379 | /* | 1382 | /* | |
1380 | * If VLANs are enabled and the packet has a VLAN tag, set | 1383 | * If VLANs are enabled and the packet has a VLAN tag, set | |
1381 | * up the descriptor to encapsulate the packet for us. | 1384 | * up the descriptor to encapsulate the packet for us. | |
1382 | * | 1385 | * | |
1383 | * This apparently has to be on the last descriptor of | 1386 | * This apparently has to be on the last descriptor of | |
1384 | * the packet. | 1387 | * the packet. | |
1385 | */ | 1388 | */ | |
1386 | 1389 | |||
1387 | /* | 1390 | /* | |
1388 | * Byte swapping is tricky. We need to provide the tag | 1391 | * Byte swapping is tricky. We need to provide the tag | |
1389 | * in a network byte order. On a big-endian machine, | 1392 | * in a network byte order. On a big-endian machine, | |
1390 | * the byteorder is correct, but we need to swap it | 1393 | * the byteorder is correct, but we need to swap it | |
1391 | * anyway, because this will be undone by the outside | 1394 | * anyway, because this will be undone by the outside | |
1392 | * htole32(). That's why there must be an | 1395 | * htole32(). That's why there must be an | |
1393 | * unconditional swap instead of htons() inside. | 1396 | * unconditional swap instead of htons() inside. | |
1394 | */ | 1397 | */ | |
1395 | if ((mtag = VLAN_OUTPUT_TAG(&sc->sc_ethercom, m0)) != NULL) { | 1398 | if ((mtag = VLAN_OUTPUT_TAG(&sc->sc_ethercom, m0)) != NULL) { | |
1396 | sc->sc_txdescs[lasttx].sipd_extsts |= | 1399 | sc->sc_txdescs[lasttx].sipd_extsts |= | |
1397 | htole32(EXTSTS_VPKT | | 1400 | htole32(EXTSTS_VPKT | | |
1398 | (bswap16(VLAN_TAG_VALUE(mtag)) & | 1401 | (bswap16(VLAN_TAG_VALUE(mtag)) & | |
1399 | EXTSTS_VTCI)); | 1402 | EXTSTS_VTCI)); | |
1400 | } | 1403 | } | |
1401 | 1404 | |||
1402 | /* | 1405 | /* | |
1403 | * If the upper-layer has requested IPv4/TCPv4/UDPv4 | 1406 | * If the upper-layer has requested IPv4/TCPv4/UDPv4 | |
1404 | * checksumming, set up the descriptor to do this work | 1407 | * checksumming, set up the descriptor to do this work | |
1405 | * for us. | 1408 | * for us. | |
1406 | * | 1409 | * | |
1407 | * This apparently has to be on the first descriptor of | 1410 | * This apparently has to be on the first descriptor of | |
1408 | * the packet. | 1411 | * the packet. | |
1409 | * | 1412 | * | |
1410 | * Byte-swap constants so the compiler can optimize. | 1413 | * Byte-swap constants so the compiler can optimize. | |
1411 | */ | 1414 | */ | |
1412 | extsts = 0; | 1415 | extsts = 0; | |
1413 | if (m0->m_pkthdr.csum_flags & M_CSUM_IPv4) { | 1416 | if (m0->m_pkthdr.csum_flags & M_CSUM_IPv4) { | |
1414 | KDASSERT(ifp->if_capenable & IFCAP_CSUM_IPv4_Tx); | 1417 | KDASSERT(ifp->if_capenable & IFCAP_CSUM_IPv4_Tx); | |
1415 | SIP_EVCNT_INCR(&sc->sc_ev_txipsum); | 1418 | SIP_EVCNT_INCR(&sc->sc_ev_txipsum); | |
1416 | extsts |= htole32(EXTSTS_IPPKT); | 1419 | extsts |= htole32(EXTSTS_IPPKT); | |
1417 | } | 1420 | } | |
1418 | if (m0->m_pkthdr.csum_flags & M_CSUM_TCPv4) { | 1421 | if (m0->m_pkthdr.csum_flags & M_CSUM_TCPv4) { | |
1419 | KDASSERT(ifp->if_capenable & IFCAP_CSUM_TCPv4_Tx); | 1422 | KDASSERT(ifp->if_capenable & IFCAP_CSUM_TCPv4_Tx); | |
1420 | SIP_EVCNT_INCR(&sc->sc_ev_txtcpsum); | 1423 | SIP_EVCNT_INCR(&sc->sc_ev_txtcpsum); | |
1421 | extsts |= htole32(EXTSTS_TCPPKT); | 1424 | extsts |= htole32(EXTSTS_TCPPKT); | |
1422 | } else if (m0->m_pkthdr.csum_flags & M_CSUM_UDPv4) { | 1425 | } else if (m0->m_pkthdr.csum_flags & M_CSUM_UDPv4) { | |
1423 | KDASSERT(ifp->if_capenable & IFCAP_CSUM_UDPv4_Tx); | 1426 | KDASSERT(ifp->if_capenable & IFCAP_CSUM_UDPv4_Tx); | |
1424 | SIP_EVCNT_INCR(&sc->sc_ev_txudpsum); | 1427 | SIP_EVCNT_INCR(&sc->sc_ev_txudpsum); | |
1425 | extsts |= htole32(EXTSTS_UDPPKT); | 1428 | extsts |= htole32(EXTSTS_UDPPKT); | |
1426 | } | 1429 | } | |
1427 | sc->sc_txdescs[sc->sc_txnext].sipd_extsts |= extsts; | 1430 | sc->sc_txdescs[sc->sc_txnext].sipd_extsts |= extsts; | |
1428 | } | 1431 | } | |
1429 | 1432 | |||
1430 | /* | 1433 | /* | |
1431 | * sip_start: [ifnet interface function] | 1434 | * sip_start: [ifnet interface function] | |
1432 | * | 1435 | * | |
1433 | * Start packet transmission on the interface. | 1436 | * Start packet transmission on the interface. | |
1434 | */ | 1437 | */ | |
1435 | static void | 1438 | static void | |
1436 | sipcom_start(struct ifnet *ifp) | 1439 | sipcom_start(struct ifnet *ifp) | |
1437 | { | 1440 | { | |
1438 | struct sip_softc *sc = ifp->if_softc; | 1441 | struct sip_softc *sc = ifp->if_softc; | |
1439 | struct mbuf *m0; | 1442 | struct mbuf *m0; | |
1440 | struct mbuf *m; | 1443 | struct mbuf *m; | |
1441 | struct sip_txsoft *txs; | 1444 | struct sip_txsoft *txs; | |
1442 | bus_dmamap_t dmamap; | 1445 | bus_dmamap_t dmamap; | |
1443 | int error, nexttx, lasttx, seg; | 1446 | int error, nexttx, lasttx, seg; | |
1444 | int ofree = sc->sc_txfree; | 1447 | int ofree = sc->sc_txfree; | |
1445 | #if 0 | 1448 | #if 0 | |
1446 | int firsttx = sc->sc_txnext; | 1449 | int firsttx = sc->sc_txnext; | |
1447 | #endif | 1450 | #endif | |
1448 | 1451 | |||
1449 | /* | 1452 | /* | |
1450 | * If we've been told to pause, don't transmit any more packets. | 1453 | * If we've been told to pause, don't transmit any more packets. | |
1451 | */ | 1454 | */ | |
1452 | if (!sc->sc_gigabit && sc->sc_paused) | 1455 | if (!sc->sc_gigabit && sc->sc_paused) | |
1453 | ifp->if_flags |= IFF_OACTIVE; | 1456 | ifp->if_flags |= IFF_OACTIVE; | |
1454 | 1457 | |||
1455 | if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING) | 1458 | if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING) | |
1456 | return; | 1459 | return; | |
1457 | 1460 | |||
1458 | /* | 1461 | /* | |
1459 | * Loop through the send queue, setting up transmit descriptors | 1462 | * Loop through the send queue, setting up transmit descriptors | |
1460 | * until we drain the queue, or use up all available transmit | 1463 | * until we drain the queue, or use up all available transmit | |
1461 | * descriptors. | 1464 | * descriptors. | |
1462 | */ | 1465 | */ | |
1463 | for (;;) { | 1466 | for (;;) { | |
1464 | /* Get a work queue entry. */ | 1467 | /* Get a work queue entry. */ | |
1465 | if ((txs = SIMPLEQ_FIRST(&sc->sc_txfreeq)) == NULL) { | 1468 | if ((txs = SIMPLEQ_FIRST(&sc->sc_txfreeq)) == NULL) { | |
1466 | SIP_EVCNT_INCR(&sc->sc_ev_txsstall); | 1469 | SIP_EVCNT_INCR(&sc->sc_ev_txsstall); | |
1467 | break; | 1470 | break; | |
1468 | } | 1471 | } | |
1469 | 1472 | |||
1470 | /* | 1473 | /* | |
1471 | * Grab a packet off the queue. | 1474 | * Grab a packet off the queue. | |
1472 | */ | 1475 | */ | |
1473 | IFQ_POLL(&ifp->if_snd, m0); | 1476 | IFQ_POLL(&ifp->if_snd, m0); | |
1474 | if (m0 == NULL) | 1477 | if (m0 == NULL) | |
1475 | break; | 1478 | break; | |
1476 | m = NULL; | 1479 | m = NULL; | |
1477 | 1480 | |||
1478 | dmamap = txs->txs_dmamap; | 1481 | dmamap = txs->txs_dmamap; | |
1479 | 1482 | |||
1480 | /* | 1483 | /* | |
1481 | * Load the DMA map. If this fails, the packet either | 1484 | * Load the DMA map. If this fails, the packet either | |
1482 | * didn't fit in the alloted number of segments, or we | 1485 | * didn't fit in the alloted number of segments, or we | |
1483 | * were short on resources. | 1486 | * were short on resources. | |
1484 | */ | 1487 | */ | |
1485 | error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0, | 1488 | error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0, | |
1486 | BUS_DMA_WRITE|BUS_DMA_NOWAIT); | 1489 | BUS_DMA_WRITE|BUS_DMA_NOWAIT); | |
1487 | /* In the non-gigabit case, we'll copy and try again. */ | 1490 | /* In the non-gigabit case, we'll copy and try again. */ | |
1488 | if (error != 0 && !sc->sc_gigabit) { | 1491 | if (error != 0 && !sc->sc_gigabit) { | |
1489 | MGETHDR(m, M_DONTWAIT, MT_DATA); | 1492 | MGETHDR(m, M_DONTWAIT, MT_DATA); | |
1490 | if (m == NULL) { | 1493 | if (m == NULL) { | |
1491 | printf("%s: unable to allocate Tx mbuf\n", | 1494 | printf("%s: unable to allocate Tx mbuf\n", | |
1492 | device_xname(sc->sc_dev)); | 1495 | device_xname(sc->sc_dev)); | |
1493 | break; | 1496 | break; | |
1494 | } | 1497 | } | |
1495 | MCLAIM(m, &sc->sc_ethercom.ec_tx_mowner); | 1498 | MCLAIM(m, &sc->sc_ethercom.ec_tx_mowner); | |
1496 | if (m0->m_pkthdr.len > MHLEN) { | 1499 | if (m0->m_pkthdr.len > MHLEN) { | |
1497 | MCLGET(m, M_DONTWAIT); | 1500 | MCLGET(m, M_DONTWAIT); | |
1498 | if ((m->m_flags & M_EXT) == 0) { | 1501 | if ((m->m_flags & M_EXT) == 0) { | |
1499 | printf("%s: unable to allocate Tx " | 1502 | printf("%s: unable to allocate Tx " | |
1500 | "cluster\n", device_xname(sc->sc_dev)); | 1503 | "cluster\n", device_xname(sc->sc_dev)); | |
1501 | m_freem(m); | 1504 | m_freem(m); | |
1502 | break; | 1505 | break; | |
1503 | } | 1506 | } | |
1504 | } | 1507 | } | |
1505 | m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, void *)); | 1508 | m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, void *)); | |
1506 | m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len; | 1509 | m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len; | |
1507 | error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, | 1510 | error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, | |
1508 | m, BUS_DMA_WRITE|BUS_DMA_NOWAIT); | 1511 | m, BUS_DMA_WRITE|BUS_DMA_NOWAIT); | |
1509 | if (error) { | 1512 | if (error) { | |
1510 | printf("%s: unable to load Tx buffer, " | 1513 | printf("%s: unable to load Tx buffer, " | |
1511 | "error = %d\n", device_xname(sc->sc_dev), error); | 1514 | "error = %d\n", device_xname(sc->sc_dev), error); | |
1512 | break; | 1515 | break; | |
1513 | } | 1516 | } | |
1514 | } else if (error == EFBIG) { | 1517 | } else if (error == EFBIG) { | |
1515 | /* | 1518 | /* | |
1516 | * For the too-many-segments case, we simply | 1519 | * For the too-many-segments case, we simply | |
1517 | * report an error and drop the packet, | 1520 | * report an error and drop the packet, | |
1518 | * since we can't sanely copy a jumbo packet | 1521 | * since we can't sanely copy a jumbo packet | |
1519 | * to a single buffer. | 1522 | * to a single buffer. | |
1520 | */ | 1523 | */ | |
1521 | printf("%s: Tx packet consumes too many " | 1524 | printf("%s: Tx packet consumes too many " | |
1522 | "DMA segments, dropping...\n", device_xname(sc->sc_dev)); | 1525 | "DMA segments, dropping...\n", device_xname(sc->sc_dev)); | |
1523 | IFQ_DEQUEUE(&ifp->if_snd, m0); | 1526 | IFQ_DEQUEUE(&ifp->if_snd, m0); | |
1524 | m_freem(m0); | 1527 | m_freem(m0); | |
1525 | continue; | 1528 | continue; | |
1526 | } else if (error != 0) { | 1529 | } else if (error != 0) { | |
1527 | /* | 1530 | /* | |
1528 | * Short on resources, just stop for now. | 1531 | * Short on resources, just stop for now. | |
1529 | */ | 1532 | */ | |
1530 | break; | 1533 | break; | |
1531 | } | 1534 | } | |
1532 | 1535 | |||
1533 | /* | 1536 | /* | |
1534 | * Ensure we have enough descriptors free to describe | 1537 | * Ensure we have enough descriptors free to describe | |
1535 | * the packet. Note, we always reserve one descriptor | 1538 | * the packet. Note, we always reserve one descriptor | |
1536 | * at the end of the ring as a termination point, to | 1539 | * at the end of the ring as a termination point, to | |
1537 | * prevent wrap-around. | 1540 | * prevent wrap-around. | |
1538 | */ | 1541 | */ | |
1539 | if (dmamap->dm_nsegs > (sc->sc_txfree - 1)) { | 1542 | if (dmamap->dm_nsegs > (sc->sc_txfree - 1)) { | |
1540 | /* | 1543 | /* | |
1541 | * Not enough free descriptors to transmit this | 1544 | * Not enough free descriptors to transmit this | |
1542 | * packet. We haven't committed anything yet, | 1545 | * packet. We haven't committed anything yet, | |
1543 | * so just unload the DMA map, put the packet | 1546 | * so just unload the DMA map, put the packet | |
1544 | * back on the queue, and punt. Notify the upper | 1547 | * back on the queue, and punt. Notify the upper | |
1545 | * layer that there are not more slots left. | 1548 | * layer that there are not more slots left. | |
1546 | * | 1549 | * | |
1547 | * XXX We could allocate an mbuf and copy, but | 1550 | * XXX We could allocate an mbuf and copy, but | |
1548 | * XXX is it worth it? | 1551 | * XXX is it worth it? | |
1549 | */ | 1552 | */ | |
1550 | ifp->if_flags |= IFF_OACTIVE; | 1553 | ifp->if_flags |= IFF_OACTIVE; | |
1551 | bus_dmamap_unload(sc->sc_dmat, dmamap); | 1554 | bus_dmamap_unload(sc->sc_dmat, dmamap); | |
1552 | if (m != NULL) | 1555 | if (m != NULL) | |
1553 | m_freem(m); | 1556 | m_freem(m); | |
1554 | SIP_EVCNT_INCR(&sc->sc_ev_txdstall); | 1557 | SIP_EVCNT_INCR(&sc->sc_ev_txdstall); | |
1555 | break; | 1558 | break; | |
1556 | } | 1559 | } | |
1557 | 1560 | |||
1558 | IFQ_DEQUEUE(&ifp->if_snd, m0); | 1561 | IFQ_DEQUEUE(&ifp->if_snd, m0); | |
1559 | if (m != NULL) { | 1562 | if (m != NULL) { | |
1560 | m_freem(m0); | 1563 | m_freem(m0); | |
1561 | m0 = m; | 1564 | m0 = m; | |
1562 | } | 1565 | } | |
1563 | 1566 | |||
1564 | /* | 1567 | /* | |
1565 | * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET. | 1568 | * WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET. | |
1566 | */ | 1569 | */ | |
1567 | 1570 | |||
1568 | /* Sync the DMA map. */ | 1571 | /* Sync the DMA map. */ | |
1569 | bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize, | 1572 | bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize, | |
1570 | BUS_DMASYNC_PREWRITE); | 1573 | BUS_DMASYNC_PREWRITE); | |
1571 | 1574 | |||
1572 | /* | 1575 | /* | |
1573 | * Initialize the transmit descriptors. | 1576 | * Initialize the transmit descriptors. | |
1574 | */ | 1577 | */ | |
1575 | for (nexttx = lasttx = sc->sc_txnext, seg = 0; | 1578 | for (nexttx = lasttx = sc->sc_txnext, seg = 0; | |
1576 | seg < dmamap->dm_nsegs; | 1579 | seg < dmamap->dm_nsegs; | |
1577 | seg++, nexttx = sip_nexttx(sc, nexttx)) { | 1580 | seg++, nexttx = sip_nexttx(sc, nexttx)) { | |
1578 | /* | 1581 | /* | |
1579 | * If this is the first descriptor we're | 1582 | * If this is the first descriptor we're | |
1580 | * enqueueing, don't set the OWN bit just | 1583 | * enqueueing, don't set the OWN bit just | |
1581 | * yet. That could cause a race condition. | 1584 | * yet. That could cause a race condition. | |
1582 | * We'll do it below. | 1585 | * We'll do it below. | |
1583 | */ | 1586 | */ | |
1584 | *sipd_bufptr(sc, &sc->sc_txdescs[nexttx]) = | 1587 | *sipd_bufptr(sc, &sc->sc_txdescs[nexttx]) = | |
1585 | htole32(dmamap->dm_segs[seg].ds_addr); | 1588 | htole32(dmamap->dm_segs[seg].ds_addr); | |
1586 | *sipd_cmdsts(sc, &sc->sc_txdescs[nexttx]) = | 1589 | *sipd_cmdsts(sc, &sc->sc_txdescs[nexttx]) = | |
1587 | htole32((nexttx == sc->sc_txnext ? 0 : CMDSTS_OWN) | | 1590 | htole32((nexttx == sc->sc_txnext ? 0 : CMDSTS_OWN) | | |
1588 | CMDSTS_MORE | dmamap->dm_segs[seg].ds_len); | 1591 | CMDSTS_MORE | dmamap->dm_segs[seg].ds_len); | |
1589 | sc->sc_txdescs[nexttx].sipd_extsts = 0; | 1592 | sc->sc_txdescs[nexttx].sipd_extsts = 0; | |
1590 | lasttx = nexttx; | 1593 | lasttx = nexttx; | |
1591 | } | 1594 | } | |
1592 | 1595 | |||
1593 | /* Clear the MORE bit on the last segment. */ | 1596 | /* Clear the MORE bit on the last segment. */ | |
1594 | *sipd_cmdsts(sc, &sc->sc_txdescs[lasttx]) &= | 1597 | *sipd_cmdsts(sc, &sc->sc_txdescs[lasttx]) &= | |
1595 | htole32(~CMDSTS_MORE); | 1598 | htole32(~CMDSTS_MORE); | |
1596 | 1599 | |||
1597 | /* | 1600 | /* | |
1598 | * If we're in the interrupt delay window, delay the | 1601 | * If we're in the interrupt delay window, delay the | |
1599 | * interrupt. | 1602 | * interrupt. | |
1600 | */ | 1603 | */ | |
1601 | if (++sc->sc_txwin >= (SIP_TXQUEUELEN * 2 / 3)) { | 1604 | if (++sc->sc_txwin >= (SIP_TXQUEUELEN * 2 / 3)) { | |
1602 | SIP_EVCNT_INCR(&sc->sc_ev_txforceintr); | 1605 | SIP_EVCNT_INCR(&sc->sc_ev_txforceintr); | |
1603 | *sipd_cmdsts(sc, &sc->sc_txdescs[lasttx]) |= | 1606 | *sipd_cmdsts(sc, &sc->sc_txdescs[lasttx]) |= | |
1604 | htole32(CMDSTS_INTR); | 1607 | htole32(CMDSTS_INTR); | |
1605 | sc->sc_txwin = 0; | 1608 | sc->sc_txwin = 0; | |
1606 | } | 1609 | } | |
1607 | 1610 | |||
1608 | if (sc->sc_gigabit) | 1611 | if (sc->sc_gigabit) | |
1609 | sipcom_set_extsts(sc, lasttx, m0, ifp->if_capenable); | 1612 | sipcom_set_extsts(sc, lasttx, m0, ifp->if_capenable); | |
1610 | 1613 | |||
1611 | /* Sync the descriptors we're using. */ | 1614 | /* Sync the descriptors we're using. */ | |
1612 | sip_cdtxsync(sc, sc->sc_txnext, dmamap->dm_nsegs, | 1615 | sip_cdtxsync(sc, sc->sc_txnext, dmamap->dm_nsegs, | |
1613 | BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); | 1616 | BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); | |
1614 | 1617 | |||
1615 | /* | 1618 | /* | |
1616 | * The entire packet is set up. Give the first descrptor | 1619 | * The entire packet is set up. Give the first descrptor | |
1617 | * to the chip now. | 1620 | * to the chip now. | |
1618 | */ | 1621 | */ | |
1619 | *sipd_cmdsts(sc, &sc->sc_txdescs[sc->sc_txnext]) |= | 1622 | *sipd_cmdsts(sc, &sc->sc_txdescs[sc->sc_txnext]) |= | |
1620 | htole32(CMDSTS_OWN); | 1623 | htole32(CMDSTS_OWN); | |
1621 | sip_cdtxsync(sc, sc->sc_txnext, 1, | 1624 | sip_cdtxsync(sc, sc->sc_txnext, 1, | |
1622 | BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); | 1625 | BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); | |
1623 | 1626 | |||
1624 | /* | 1627 | /* | |
1625 | * Store a pointer to the packet so we can free it later, | 1628 | * Store a pointer to the packet so we can free it later, | |
1626 | * and remember what txdirty will be once the packet is | 1629 | * and remember what txdirty will be once the packet is | |
1627 | * done. | 1630 | * done. | |
1628 | */ | 1631 | */ | |
1629 | txs->txs_mbuf = m0; | 1632 | txs->txs_mbuf = m0; | |
1630 | txs->txs_firstdesc = sc->sc_txnext; | 1633 | txs->txs_firstdesc = sc->sc_txnext; | |
1631 | txs->txs_lastdesc = lasttx; | 1634 | txs->txs_lastdesc = lasttx; | |
1632 | 1635 | |||
1633 | /* Advance the tx pointer. */ | 1636 | /* Advance the tx pointer. */ | |
1634 | sc->sc_txfree -= dmamap->dm_nsegs; | 1637 | sc->sc_txfree -= dmamap->dm_nsegs; | |
1635 | sc->sc_txnext = nexttx; | 1638 | sc->sc_txnext = nexttx; | |
1636 | 1639 | |||
1637 | SIMPLEQ_REMOVE_HEAD(&sc->sc_txfreeq, txs_q); | 1640 | SIMPLEQ_REMOVE_HEAD(&sc->sc_txfreeq, txs_q); | |
1638 | SIMPLEQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q); | 1641 | SIMPLEQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q); | |
1639 | 1642 | |||
1640 | /* | 1643 | /* | |
1641 | * Pass the packet to any BPF listeners. | 1644 | * Pass the packet to any BPF listeners. | |
1642 | */ | 1645 | */ | |
1643 | bpf_mtap(ifp, m0); | 1646 | bpf_mtap(ifp, m0); | |
1644 | } | 1647 | } | |
1645 | 1648 | |||
1646 | if (txs == NULL || sc->sc_txfree == 0) { | 1649 | if (txs == NULL || sc->sc_txfree == 0) { | |
1647 | /* No more slots left; notify upper layer. */ | 1650 | /* No more slots left; notify upper layer. */ | |
1648 | ifp->if_flags |= IFF_OACTIVE; | 1651 | ifp->if_flags |= IFF_OACTIVE; | |
1649 | } | 1652 | } | |
1650 | 1653 | |||
1651 | if (sc->sc_txfree != ofree) { | 1654 | if (sc->sc_txfree != ofree) { | |
1652 | /* | 1655 | /* | |
1653 | * Start the transmit process. Note, the manual says | 1656 | * Start the transmit process. Note, the manual says | |
1654 | * that if there are no pending transmissions in the | 1657 | * that if there are no pending transmissions in the | |
1655 | * chip's internal queue (indicated by TXE being clear), | 1658 | * chip's internal queue (indicated by TXE being clear), | |
1656 | * then the driver software must set the TXDP to the | 1659 | * then the driver software must set the TXDP to the | |
1657 | * first descriptor to be transmitted. However, if we | 1660 | * first descriptor to be transmitted. However, if we | |
1658 | * do this, it causes serious performance degredation on | 1661 | * do this, it causes serious performance degredation on | |
1659 | * the DP83820 under load, not setting TXDP doesn't seem | 1662 | * the DP83820 under load, not setting TXDP doesn't seem | |
1660 | * to adversely affect the SiS 900 or DP83815. | 1663 | * to adversely affect the SiS 900 or DP83815. | |
1661 | * | 1664 | * | |
1662 | * Well, I guess it wouldn't be the first time a manual | 1665 | * Well, I guess it wouldn't be the first time a manual | |
1663 | * has lied -- and they could be speaking of the NULL- | 1666 | * has lied -- and they could be speaking of the NULL- | |
1664 | * terminated descriptor list case, rather than OWN- | 1667 | * terminated descriptor list case, rather than OWN- | |
1665 | * terminated rings. | 1668 | * terminated rings. | |
1666 | */ | 1669 | */ | |
1667 | #if 0 | 1670 | #if 0 | |
1668 | if ((bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_CR) & | 1671 | if ((bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_CR) & | |
1669 | CR_TXE) == 0) { | 1672 | CR_TXE) == 0) { | |
1670 | bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_TXDP, | 1673 | bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_TXDP, | |
1671 | SIP_CDTXADDR(sc, firsttx)); | 1674 | SIP_CDTXADDR(sc, firsttx)); | |
1672 | bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_CR, CR_TXE); | 1675 | bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_CR, CR_TXE); | |
1673 | } | 1676 | } | |
1674 | #else | 1677 | #else | |
1675 | bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_CR, CR_TXE); | 1678 | bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_CR, CR_TXE); | |
1676 | #endif | 1679 | #endif | |
1677 | 1680 | |||
1678 | /* Set a watchdog timer in case the chip flakes out. */ | 1681 | /* Set a watchdog timer in case the chip flakes out. */ | |
1679 | /* Gigabit autonegotiation takes 5 seconds. */ | 1682 | /* Gigabit autonegotiation takes 5 seconds. */ | |
1680 | ifp->if_timer = (sc->sc_gigabit) ? 10 : 5; | 1683 | ifp->if_timer = (sc->sc_gigabit) ? 10 : 5; | |
1681 | } | 1684 | } | |
1682 | } | 1685 | } | |
1683 | 1686 | |||
1684 | /* | 1687 | /* | |
1685 | * sip_watchdog: [ifnet interface function] | 1688 | * sip_watchdog: [ifnet interface function] | |
1686 | * | 1689 | * | |
1687 | * Watchdog timer handler. | 1690 | * Watchdog timer handler. | |
1688 | */ | 1691 | */ | |
1689 | static void | 1692 | static void | |
1690 | sipcom_watchdog(struct ifnet *ifp) | 1693 | sipcom_watchdog(struct ifnet *ifp) | |
1691 | { | 1694 | { | |
1692 | struct sip_softc *sc = ifp->if_softc; | 1695 | struct sip_softc *sc = ifp->if_softc; | |
1693 | 1696 | |||
1694 | /* | 1697 | /* | |
1695 | * The chip seems to ignore the CMDSTS_INTR bit sometimes! | 1698 | * The chip seems to ignore the CMDSTS_INTR bit sometimes! | |
1696 | * If we get a timeout, try and sweep up transmit descriptors. | 1699 | * If we get a timeout, try and sweep up transmit descriptors. | |
1697 | * If we manage to sweep them all up, ignore the lack of | 1700 | * If we manage to sweep them all up, ignore the lack of | |
1698 | * interrupt. | 1701 | * interrupt. | |
1699 | */ | 1702 | */ | |
1700 | sipcom_txintr(sc); | 1703 | sipcom_txintr(sc); | |
1701 | 1704 | |||
1702 | if (sc->sc_txfree != sc->sc_ntxdesc) { | 1705 | if (sc->sc_txfree != sc->sc_ntxdesc) { | |
1703 | printf("%s: device timeout\n", device_xname(sc->sc_dev)); | 1706 | printf("%s: device timeout\n", device_xname(sc->sc_dev)); | |
1704 | ifp->if_oerrors++; | 1707 | ifp->if_oerrors++; | |
1705 | 1708 | |||
1706 | /* Reset the interface. */ | 1709 | /* Reset the interface. */ | |
1707 | (void) sipcom_init(ifp); | 1710 | (void) sipcom_init(ifp); | |
1708 | } else if (ifp->if_flags & IFF_DEBUG) | 1711 | } else if (ifp->if_flags & IFF_DEBUG) | |
1709 | printf("%s: recovered from device timeout\n", | 1712 | printf("%s: recovered from device timeout\n", | |
1710 | device_xname(sc->sc_dev)); | 1713 | device_xname(sc->sc_dev)); | |
1711 | 1714 | |||
1712 | /* Try to get more packets going. */ | 1715 | /* Try to get more packets going. */ | |
1713 | sipcom_start(ifp); | 1716 | sipcom_start(ifp); | |
1714 | } | 1717 | } | |
1715 | 1718 | |||
1716 | /* If the interface is up and running, only modify the receive | 1719 | /* If the interface is up and running, only modify the receive | |
1717 | * filter when setting promiscuous or debug mode. Otherwise fall | 1720 | * filter when setting promiscuous or debug mode. Otherwise fall | |
1718 | * through to ether_ioctl, which will reset the chip. | 1721 | * through to ether_ioctl, which will reset the chip. | |
1719 | */ | 1722 | */ | |
1720 | static int | 1723 | static int | |
1721 | sip_ifflags_cb(struct ethercom *ec) | 1724 | sip_ifflags_cb(struct ethercom *ec) | |
1722 | { | 1725 | { | |
1723 | #define COMPARE_EC(sc) (((sc)->sc_prev.ec_capenable \ | 1726 | #define COMPARE_EC(sc) (((sc)->sc_prev.ec_capenable \ | |
1724 | == (sc)->sc_ethercom.ec_capenable) \ | 1727 | == (sc)->sc_ethercom.ec_capenable) \ | |
1725 | && ((sc)->sc_prev.is_vlan == \ | 1728 | && ((sc)->sc_prev.is_vlan == \ | |
1726 | VLAN_ATTACHED(&(sc)->sc_ethercom) )) | 1729 | VLAN_ATTACHED(&(sc)->sc_ethercom) )) | |
1727 | #define COMPARE_IC(sc, ifp) ((sc)->sc_prev.if_capenable == (ifp)->if_capenable) | 1730 | #define COMPARE_IC(sc, ifp) ((sc)->sc_prev.if_capenable == (ifp)->if_capenable) | |
1728 | struct ifnet *ifp = &ec->ec_if; | 1731 | struct ifnet *ifp = &ec->ec_if; | |
1729 | struct sip_softc *sc = ifp->if_softc; | 1732 | struct sip_softc *sc = ifp->if_softc; | |
1730 | int change = ifp->if_flags ^ sc->sc_if_flags; | 1733 | int change = ifp->if_flags ^ sc->sc_if_flags; | |
1731 | 1734 | |||
1732 | if ((change & ~(IFF_CANTCHANGE|IFF_DEBUG)) != 0 || !COMPARE_EC(sc) || | 1735 | if ((change & ~(IFF_CANTCHANGE|IFF_DEBUG)) != 0 || !COMPARE_EC(sc) || | |
1733 | !COMPARE_IC(sc, ifp)) | 1736 | !COMPARE_IC(sc, ifp)) | |
1734 | return ENETRESET; | 1737 | return ENETRESET; | |
1735 | /* Set up the receive filter. */ | 1738 | /* Set up the receive filter. */ | |
1736 | (*sc->sc_model->sip_variant->sipv_set_filter)(sc); | 1739 | (*sc->sc_model->sip_variant->sipv_set_filter)(sc); | |
1737 | return 0; | 1740 | return 0; | |
1738 | } | 1741 | } | |
1739 | 1742 | |||
1740 | /* | 1743 | /* | |
1741 | * sip_ioctl: [ifnet interface function] | 1744 | * sip_ioctl: [ifnet interface function] | |
1742 | * | 1745 | * |
--- src/sys/dev/pci/if_tlp_pci.c 2011/11/11 23:01:59 1.121
+++ src/sys/dev/pci/if_tlp_pci.c 2012/09/23 01:10:59 1.122
@@ -1,1707 +1,1714 @@ | @@ -1,1707 +1,1714 @@ | |||
1 | /* $NetBSD: if_tlp_pci.c,v 1.121 2011/11/11 23:01:59 jakllsch Exp $ */ | 1 | /* $NetBSD: if_tlp_pci.c,v 1.122 2012/09/23 01:10:59 chs Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1998, 1999, 2000, 2002 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1998, 1999, 2000, 2002 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 Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | 8 | * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, | |
9 | * NASA Ames Research Center; and Charles M. Hannum. | 9 | * NASA Ames Research Center; and Charles M. Hannum. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
15 | * notice, this list of conditions and the following disclaimer. | 15 | * notice, this list of conditions and the following disclaimer. | |
16 | * 2. Redistributions in binary form must reproduce the above copyright | 16 | * 2. Redistributions in binary form must reproduce the above copyright | |
17 | * notice, this list of conditions and the following disclaimer in the | 17 | * notice, this list of conditions and the following disclaimer in the | |
18 | * documentation and/or other materials provided with the distribution. | 18 | * documentation and/or other materials provided with the distribution. | |
19 | * | 19 | * | |
20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 20 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
30 | * POSSIBILITY OF SUCH DAMAGE. | 30 | * POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | /* | 33 | /* | |
34 | * PCI bus front-end for the Digital Semiconductor ``Tulip'' (21x4x) | 34 | * PCI bus front-end for the Digital Semiconductor ``Tulip'' (21x4x) | |
35 | * Ethernet controller family driver. | 35 | * Ethernet controller family driver. | |
36 | */ | 36 | */ | |
37 | 37 | |||
38 | #include <sys/cdefs.h> | 38 | #include <sys/cdefs.h> | |
39 | __KERNEL_RCSID(0, "$NetBSD: if_tlp_pci.c,v 1.121 2011/11/11 23:01:59 jakllsch Exp $"); | 39 | __KERNEL_RCSID(0, "$NetBSD: if_tlp_pci.c,v 1.122 2012/09/23 01:10:59 chs Exp $"); | |
40 | 40 | |||
41 | #include <sys/param.h> | 41 | #include <sys/param.h> | |
42 | #include <sys/systm.h> | 42 | #include <sys/systm.h> | |
43 | #include <sys/mbuf.h> | 43 | #include <sys/mbuf.h> | |
44 | #include <sys/malloc.h> | 44 | #include <sys/malloc.h> | |
45 | #include <sys/kernel.h> | 45 | #include <sys/kernel.h> | |
46 | #include <sys/socket.h> | 46 | #include <sys/socket.h> | |
47 | #include <sys/ioctl.h> | 47 | #include <sys/ioctl.h> | |
48 | #include <sys/errno.h> | 48 | #include <sys/errno.h> | |
49 | #include <sys/device.h> | 49 | #include <sys/device.h> | |
50 | 50 | |||
51 | #include <machine/endian.h> | 51 | #include <machine/endian.h> | |
52 | 52 | |||
53 | #include <net/if.h> | 53 | #include <net/if.h> | |
54 | #include <net/if_dl.h> | 54 | #include <net/if_dl.h> | |
55 | #include <net/if_media.h> | 55 | #include <net/if_media.h> | |
56 | #include <net/if_ether.h> | 56 | #include <net/if_ether.h> | |
57 | 57 | |||
58 | #include <sys/bus.h> | 58 | #include <sys/bus.h> | |
59 | #include <sys/intr.h> | 59 | #include <sys/intr.h> | |
60 | 60 | |||
61 | #include <dev/mii/miivar.h> | 61 | #include <dev/mii/miivar.h> | |
62 | #include <dev/mii/mii_bitbang.h> | 62 | #include <dev/mii/mii_bitbang.h> | |
63 | 63 | |||
64 | #include <dev/ic/tulipreg.h> | 64 | #include <dev/ic/tulipreg.h> | |
65 | #include <dev/ic/tulipvar.h> | 65 | #include <dev/ic/tulipvar.h> | |
66 | 66 | |||
67 | #include <dev/pci/pcivar.h> | 67 | #include <dev/pci/pcivar.h> | |
68 | #include <dev/pci/pcireg.h> | 68 | #include <dev/pci/pcireg.h> | |
69 | #include <dev/pci/pcidevs.h> | 69 | #include <dev/pci/pcidevs.h> | |
70 | 70 | |||
71 | /* | 71 | /* | |
72 | * PCI configuration space registers used by the Tulip. | 72 | * PCI configuration space registers used by the Tulip. | |
73 | */ | 73 | */ | |
74 | #define TULIP_PCI_IOBA PCI_BAR(0) /* i/o mapped base */ | 74 | #define TULIP_PCI_IOBA PCI_BAR(0) /* i/o mapped base */ | |
75 | #define TULIP_PCI_MMBA PCI_BAR(1) /* memory mapped base */ | 75 | #define TULIP_PCI_MMBA PCI_BAR(1) /* memory mapped base */ | |
76 | #define TULIP_PCI_CFDA 0x40 /* configuration driver area */ | 76 | #define TULIP_PCI_CFDA 0x40 /* configuration driver area */ | |
77 | 77 | |||
78 | #define CFDA_SLEEP 0x80000000 /* sleep mode */ | 78 | #define CFDA_SLEEP 0x80000000 /* sleep mode */ | |
79 | #define CFDA_SNOOZE 0x40000000 /* snooze mode */ | 79 | #define CFDA_SNOOZE 0x40000000 /* snooze mode */ | |
80 | 80 | |||
81 | struct tulip_pci_softc { | 81 | struct tulip_pci_softc { | |
82 | struct tulip_softc sc_tulip; /* real Tulip softc */ | 82 | struct tulip_softc sc_tulip; /* real Tulip softc */ | |
83 | 83 | |||
84 | /* PCI-specific goo. */ | 84 | /* PCI-specific goo. */ | |
85 | void *sc_ih; /* interrupt handle */ | 85 | void *sc_ih; /* interrupt handle */ | |
86 | bus_size_t sc_mapsize; | 86 | bus_size_t sc_mapsize; | |
87 | 87 | |||
88 | pci_chipset_tag_t sc_pc; /* our PCI chipset */ | 88 | pci_chipset_tag_t sc_pc; /* our PCI chipset */ | |
89 | pcitag_t sc_pcitag; /* our PCI tag */ | 89 | pcitag_t sc_pcitag; /* our PCI tag */ | |
90 | 90 | |||
91 | int sc_flags; /* flags; see below */ | 91 | int sc_flags; /* flags; see below */ | |
92 | 92 | |||
93 | LIST_HEAD(, tulip_pci_softc) sc_intrslaves; | 93 | LIST_HEAD(, tulip_pci_softc) sc_intrslaves; | |
94 | LIST_ENTRY(tulip_pci_softc) sc_intrq; | 94 | LIST_ENTRY(tulip_pci_softc) sc_intrq; | |
95 | 95 | |||
96 | /* Our {ROM,interrupt} master. */ | 96 | /* Our {ROM,interrupt} master. */ | |
97 | struct tulip_pci_softc *sc_master; | 97 | struct tulip_pci_softc *sc_master; | |
98 | }; | 98 | }; | |
99 | 99 | |||
100 | /* sc_flags */ | 100 | /* sc_flags */ | |
101 | #define TULIP_PCI_SHAREDINTR 0x01 /* interrupt is shared */ | 101 | #define TULIP_PCI_SHAREDINTR 0x01 /* interrupt is shared */ | |
102 | #define TULIP_PCI_SLAVEINTR 0x02 /* interrupt is slave */ | 102 | #define TULIP_PCI_SLAVEINTR 0x02 /* interrupt is slave */ | |
103 | #define TULIP_PCI_SHAREDROM 0x04 /* ROM is shared */ | 103 | #define TULIP_PCI_SHAREDROM 0x04 /* ROM is shared */ | |
104 | #define TULIP_PCI_SLAVEROM 0x08 /* slave of shared ROM */ | 104 | #define TULIP_PCI_SLAVEROM 0x08 /* slave of shared ROM */ | |
105 | 105 | |||
106 | static int tlp_pci_match(device_t, cfdata_t, void *); | 106 | static int tlp_pci_match(device_t, cfdata_t, void *); | |
107 | static void tlp_pci_attach(device_t, device_t, void *); | 107 | static void tlp_pci_attach(device_t, device_t, void *); | |
108 | static int tlp_pci_detach(device_t, int); | 108 | static int tlp_pci_detach(device_t, int); | |
109 | 109 | |||
110 | CFATTACH_DECL3_NEW(tlp_pci, sizeof(struct tulip_pci_softc), | 110 | CFATTACH_DECL3_NEW(tlp_pci, sizeof(struct tulip_pci_softc), | |
111 | tlp_pci_match, tlp_pci_attach, tlp_pci_detach, NULL, NULL, NULL, | 111 | tlp_pci_match, tlp_pci_attach, tlp_pci_detach, NULL, NULL, NULL, | |
112 | DVF_DETACH_SHUTDOWN); | 112 | DVF_DETACH_SHUTDOWN); | |
113 | 113 | |||
114 | static const struct tulip_pci_product { | 114 | static const struct tulip_pci_product { | |
115 | uint32_t tpp_vendor; /* PCI vendor ID */ | 115 | uint32_t tpp_vendor; /* PCI vendor ID */ | |
116 | uint32_t tpp_product; /* PCI product ID */ | 116 | uint32_t tpp_product; /* PCI product ID */ | |
117 | tulip_chip_t tpp_chip; /* base Tulip chip type */ | 117 | tulip_chip_t tpp_chip; /* base Tulip chip type */ | |
118 | } tlp_pci_products[] = { | 118 | } tlp_pci_products[] = { | |
119 | { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21040, | 119 | { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21040, | |
120 | TULIP_CHIP_21040 }, | 120 | TULIP_CHIP_21040 }, | |
121 | { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21041, | 121 | { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21041, | |
122 | TULIP_CHIP_21041 }, | 122 | TULIP_CHIP_21041 }, | |
123 | { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21140, | 123 | { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21140, | |
124 | TULIP_CHIP_21140 }, | 124 | TULIP_CHIP_21140 }, | |
125 | { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21142, | 125 | { PCI_VENDOR_DEC, PCI_PRODUCT_DEC_21142, | |
126 | TULIP_CHIP_21142 }, | 126 | TULIP_CHIP_21142 }, | |
127 | 127 | |||
128 | { PCI_VENDOR_LITEON, PCI_PRODUCT_LITEON_82C168, | 128 | { PCI_VENDOR_LITEON, PCI_PRODUCT_LITEON_82C168, | |
129 | TULIP_CHIP_82C168 }, | 129 | TULIP_CHIP_82C168 }, | |
130 | 130 | |||
131 | /* | 131 | /* | |
132 | * Note: This is like a MX98725 with Wake-On-LAN and a | 132 | * Note: This is like a MX98725 with Wake-On-LAN and a | |
133 | * 128-bit multicast hash table. | 133 | * 128-bit multicast hash table. | |
134 | */ | 134 | */ | |
135 | { PCI_VENDOR_LITEON, PCI_PRODUCT_LITEON_82C115, | 135 | { PCI_VENDOR_LITEON, PCI_PRODUCT_LITEON_82C115, | |
136 | TULIP_CHIP_82C115 }, | 136 | TULIP_CHIP_82C115 }, | |
137 | 137 | |||
138 | { PCI_VENDOR_MACRONIX, PCI_PRODUCT_MACRONIX_MX98713, | 138 | { PCI_VENDOR_MACRONIX, PCI_PRODUCT_MACRONIX_MX98713, | |
139 | TULIP_CHIP_MX98713 }, | 139 | TULIP_CHIP_MX98713 }, | |
140 | { PCI_VENDOR_MACRONIX, PCI_PRODUCT_MACRONIX_MX987x5, | 140 | { PCI_VENDOR_MACRONIX, PCI_PRODUCT_MACRONIX_MX987x5, | |
141 | TULIP_CHIP_MX98715 }, | 141 | TULIP_CHIP_MX98715 }, | |
142 | 142 | |||
143 | { PCI_VENDOR_COMPEX, PCI_PRODUCT_COMPEX_RL100TX, | 143 | { PCI_VENDOR_COMPEX, PCI_PRODUCT_COMPEX_RL100TX, | |
144 | TULIP_CHIP_MX98713 }, | 144 | TULIP_CHIP_MX98713 }, | |
145 | 145 | |||
146 | { PCI_VENDOR_WINBOND, PCI_PRODUCT_WINBOND_W89C840F, | 146 | { PCI_VENDOR_WINBOND, PCI_PRODUCT_WINBOND_W89C840F, | |
147 | TULIP_CHIP_WB89C840F }, | 147 | TULIP_CHIP_WB89C840F }, | |
148 | { PCI_VENDOR_COMPEX, PCI_PRODUCT_COMPEX_RL100ATX, | 148 | { PCI_VENDOR_COMPEX, PCI_PRODUCT_COMPEX_RL100ATX, | |
149 | TULIP_CHIP_WB89C840F }, | 149 | TULIP_CHIP_WB89C840F }, | |
150 | 150 | |||
151 | { PCI_VENDOR_DAVICOM, PCI_PRODUCT_DAVICOM_DM9102, | 151 | { PCI_VENDOR_DAVICOM, PCI_PRODUCT_DAVICOM_DM9102, | |
152 | TULIP_CHIP_DM9102 }, | 152 | TULIP_CHIP_DM9102 }, | |
153 | 153 | |||
154 | { PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_AL981, | 154 | { PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_AL981, | |
155 | TULIP_CHIP_AL981 }, | 155 | TULIP_CHIP_AL981 }, | |
156 | 156 | |||
157 | { PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_AN983, | 157 | { PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_AN983, | |
158 | TULIP_CHIP_AN985 }, | 158 | TULIP_CHIP_AN985 }, | |
159 | { PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_ADM9511, | 159 | { PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_ADM9511, | |
160 | TULIP_CHIP_AN985 }, | 160 | TULIP_CHIP_AN985 }, | |
161 | { PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_ADM9513, | 161 | { PCI_VENDOR_ADMTEK, PCI_PRODUCT_ADMTEK_ADM9513, | |
162 | TULIP_CHIP_AN985 }, | 162 | TULIP_CHIP_AN985 }, | |
163 | { PCI_VENDOR_ACCTON, PCI_PRODUCT_ACCTON_EN2242, | 163 | { PCI_VENDOR_ACCTON, PCI_PRODUCT_ACCTON_EN2242, | |
164 | TULIP_CHIP_AN985 }, | 164 | TULIP_CHIP_AN985 }, | |
165 | 165 | |||
166 | { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C910SOHOB, | 166 | { PCI_VENDOR_3COM, PCI_PRODUCT_3COM_3C910SOHOB, | |
167 | TULIP_CHIP_AN985 }, | 167 | TULIP_CHIP_AN985 }, | |
168 | 168 | |||
169 | { PCI_VENDOR_ASIX, PCI_PRODUCT_ASIX_AX88140A, | 169 | { PCI_VENDOR_ASIX, PCI_PRODUCT_ASIX_AX88140A, | |
170 | TULIP_CHIP_AX88140 }, | 170 | TULIP_CHIP_AX88140 }, | |
171 | 171 | |||
172 | { PCI_VENDOR_CONEXANT, PCI_PRODUCT_CONEXANT_LANFINITY, | 172 | { PCI_VENDOR_CONEXANT, PCI_PRODUCT_CONEXANT_LANFINITY, | |
173 | TULIP_CHIP_RS7112 }, | 173 | TULIP_CHIP_RS7112 }, | |
174 | 174 | |||
175 | { 0, 0, | 175 | { 0, 0, | |
176 | TULIP_CHIP_INVALID }, | 176 | TULIP_CHIP_INVALID }, | |
177 | }; | 177 | }; | |
178 | 178 | |||
179 | struct tlp_pci_quirks { | 179 | struct tlp_pci_quirks { | |
180 | void (*tpq_func)(struct tulip_pci_softc *, | 180 | void (*tpq_func)(struct tulip_pci_softc *, | |
181 | const uint8_t *); | 181 | const uint8_t *); | |
182 | uint8_t tpq_oui[3]; | 182 | uint8_t tpq_oui[3]; | |
183 | }; | 183 | }; | |
184 | 184 | |||
185 | static void tlp_pci_dec_quirks(struct tulip_pci_softc *, | 185 | static void tlp_pci_dec_quirks(struct tulip_pci_softc *, | |
186 | const uint8_t *); | 186 | const uint8_t *); | |
187 | 187 | |||
188 | static void tlp_pci_znyx_21040_quirks(struct tulip_pci_softc *, | 188 | static void tlp_pci_znyx_21040_quirks(struct tulip_pci_softc *, | |
189 | const uint8_t *); | 189 | const uint8_t *); | |
190 | static void tlp_pci_smc_21040_quirks(struct tulip_pci_softc *, | 190 | static void tlp_pci_smc_21040_quirks(struct tulip_pci_softc *, | |
191 | const uint8_t *); | 191 | const uint8_t *); | |
192 | static void tlp_pci_cogent_21040_quirks(struct tulip_pci_softc *, | 192 | static void tlp_pci_cogent_21040_quirks(struct tulip_pci_softc *, | |
193 | const uint8_t *); | 193 | const uint8_t *); | |
194 | static void tlp_pci_accton_21040_quirks(struct tulip_pci_softc *, | 194 | static void tlp_pci_accton_21040_quirks(struct tulip_pci_softc *, | |
195 | const uint8_t *); | 195 | const uint8_t *); | |
196 | 196 | |||
197 | static void tlp_pci_cobalt_21142_quirks(struct tulip_pci_softc *, | 197 | static void tlp_pci_cobalt_21142_quirks(struct tulip_pci_softc *, | |
198 | const uint8_t *); | 198 | const uint8_t *); | |
199 | static void tlp_pci_algor_21142_quirks(struct tulip_pci_softc *, | 199 | static void tlp_pci_algor_21142_quirks(struct tulip_pci_softc *, | |
200 | const uint8_t *); | 200 | const uint8_t *); | |
201 | static void tlp_pci_netwinder_21142_quirks(struct tulip_pci_softc *, | 201 | static void tlp_pci_netwinder_21142_quirks(struct tulip_pci_softc *, | |
202 | const uint8_t *); | 202 | const uint8_t *); | |
203 | static void tlp_pci_phobos_21142_quirks(struct tulip_pci_softc *, | 203 | static void tlp_pci_phobos_21142_quirks(struct tulip_pci_softc *, | |
204 | const uint8_t *); | 204 | const uint8_t *); | |
205 | static void tlp_pci_znyx_21142_quirks(struct tulip_pci_softc *, | 205 | static void tlp_pci_znyx_21142_quirks(struct tulip_pci_softc *, | |
206 | const uint8_t *); | 206 | const uint8_t *); | |
207 | 207 | |||
208 | static void tlp_pci_adaptec_quirks(struct tulip_pci_softc *, | 208 | static void tlp_pci_adaptec_quirks(struct tulip_pci_softc *, | |
209 | const uint8_t *); | 209 | const uint8_t *); | |
210 | 210 | |||
211 | static const struct tlp_pci_quirks tlp_pci_21040_quirks[] = { | 211 | static const struct tlp_pci_quirks tlp_pci_21040_quirks[] = { | |
212 | { tlp_pci_znyx_21040_quirks, { 0x00, 0xc0, 0x95 } }, | 212 | { tlp_pci_znyx_21040_quirks, { 0x00, 0xc0, 0x95 } }, | |
213 | { tlp_pci_smc_21040_quirks, { 0x00, 0x00, 0xc0 } }, | 213 | { tlp_pci_smc_21040_quirks, { 0x00, 0x00, 0xc0 } }, | |
214 | { tlp_pci_cogent_21040_quirks, { 0x00, 0x00, 0x92 } }, | 214 | { tlp_pci_cogent_21040_quirks, { 0x00, 0x00, 0x92 } }, | |
215 | { tlp_pci_accton_21040_quirks, { 0x00, 0x00, 0xe8 } }, | 215 | { tlp_pci_accton_21040_quirks, { 0x00, 0x00, 0xe8 } }, | |
216 | { NULL, { 0, 0, 0 } } | 216 | { NULL, { 0, 0, 0 } } | |
217 | }; | 217 | }; | |
218 | 218 | |||
219 | static const struct tlp_pci_quirks tlp_pci_21041_quirks[] = { | 219 | static const struct tlp_pci_quirks tlp_pci_21041_quirks[] = { | |
220 | { tlp_pci_dec_quirks, { 0x08, 0x00, 0x2b } }, | 220 | { tlp_pci_dec_quirks, { 0x08, 0x00, 0x2b } }, | |
221 | { tlp_pci_dec_quirks, { 0x00, 0x00, 0xf8 } }, | 221 | { tlp_pci_dec_quirks, { 0x00, 0x00, 0xf8 } }, | |
222 | { NULL, { 0, 0, 0 } } | 222 | { NULL, { 0, 0, 0 } } | |
223 | }; | 223 | }; | |
224 | 224 | |||
225 | static void tlp_pci_asante_21140_quirks(struct tulip_pci_softc *, | 225 | static void tlp_pci_asante_21140_quirks(struct tulip_pci_softc *, | |
226 | const uint8_t *); | 226 | const uint8_t *); | |
227 | static void tlp_pci_e100_quirks(struct tulip_pci_softc *, | 227 | static void tlp_pci_e100_quirks(struct tulip_pci_softc *, | |
228 | const uint8_t *); | 228 | const uint8_t *); | |
229 | static void tlp_pci_phobos_21140_quirks(struct tulip_pci_softc *, | 229 | static void tlp_pci_phobos_21140_quirks(struct tulip_pci_softc *, | |
230 | const uint8_t *); | 230 | const uint8_t *); | |
231 | static void tlp_pci_smc_21140_quirks(struct tulip_pci_softc *, | 231 | static void tlp_pci_smc_21140_quirks(struct tulip_pci_softc *, | |
232 | const uint8_t *); | 232 | const uint8_t *); | |
233 | static void tlp_pci_vpc_21140_quirks(struct tulip_pci_softc *, | 233 | static void tlp_pci_vpc_21140_quirks(struct tulip_pci_softc *, | |
234 | const uint8_t *); | 234 | const uint8_t *); | |
235 | 235 | |||
236 | static const struct tlp_pci_quirks tlp_pci_21140_quirks[] = { | 236 | static const struct tlp_pci_quirks tlp_pci_21140_quirks[] = { | |
237 | { tlp_pci_dec_quirks, { 0x08, 0x00, 0x2b } }, | 237 | { tlp_pci_dec_quirks, { 0x08, 0x00, 0x2b } }, | |
238 | { tlp_pci_dec_quirks, { 0x00, 0x00, 0xf8 } }, | 238 | { tlp_pci_dec_quirks, { 0x00, 0x00, 0xf8 } }, | |
239 | { tlp_pci_e100_quirks, { 0x00, 0xa0, 0x59 } }, | 239 | { tlp_pci_e100_quirks, { 0x00, 0xa0, 0x59 } }, | |
240 | { tlp_pci_asante_21140_quirks, { 0x00, 0x00, 0x94 } }, | 240 | { tlp_pci_asante_21140_quirks, { 0x00, 0x00, 0x94 } }, | |
241 | { tlp_pci_adaptec_quirks, { 0x00, 0x00, 0x92 } }, | 241 | { tlp_pci_adaptec_quirks, { 0x00, 0x00, 0x92 } }, | |
242 | { tlp_pci_adaptec_quirks, { 0x00, 0x00, 0xd1 } }, | 242 | { tlp_pci_adaptec_quirks, { 0x00, 0x00, 0xd1 } }, | |
243 | { tlp_pci_phobos_21140_quirks, { 0x00, 0x60, 0xf5 } }, | 243 | { tlp_pci_phobos_21140_quirks, { 0x00, 0x60, 0xf5 } }, | |
244 | { tlp_pci_smc_21140_quirks, { 0x00, 0x00, 0xc0 } }, | 244 | { tlp_pci_smc_21140_quirks, { 0x00, 0x00, 0xc0 } }, | |
245 | { tlp_pci_vpc_21140_quirks, { 0x00, 0x03, 0xff } }, | 245 | { tlp_pci_vpc_21140_quirks, { 0x00, 0x03, 0xff } }, | |
246 | { NULL, { 0, 0, 0 } } | 246 | { NULL, { 0, 0, 0 } } | |
247 | }; | 247 | }; | |
248 | 248 | |||
249 | static const struct tlp_pci_quirks tlp_pci_21142_quirks[] = { | 249 | static const struct tlp_pci_quirks tlp_pci_21142_quirks[] = { | |
250 | { tlp_pci_dec_quirks, { 0x08, 0x00, 0x2b } }, | 250 | { tlp_pci_dec_quirks, { 0x08, 0x00, 0x2b } }, | |
251 | { tlp_pci_dec_quirks, { 0x00, 0x00, 0xf8 } }, | 251 | { tlp_pci_dec_quirks, { 0x00, 0x00, 0xf8 } }, | |
252 | { tlp_pci_cobalt_21142_quirks, { 0x00, 0x10, 0xe0 } }, | 252 | { tlp_pci_cobalt_21142_quirks, { 0x00, 0x10, 0xe0 } }, | |
253 | { tlp_pci_algor_21142_quirks, { 0x00, 0x40, 0xbc } }, | 253 | { tlp_pci_algor_21142_quirks, { 0x00, 0x40, 0xbc } }, | |
254 | { tlp_pci_adaptec_quirks, { 0x00, 0x00, 0xd1 } }, | 254 | { tlp_pci_adaptec_quirks, { 0x00, 0x00, 0xd1 } }, | |
255 | { tlp_pci_netwinder_21142_quirks,{ 0x00, 0x10, 0x57 } }, | 255 | { tlp_pci_netwinder_21142_quirks,{ 0x00, 0x10, 0x57 } }, | |
256 | { tlp_pci_phobos_21142_quirks, { 0x00, 0x60, 0xf5 } }, | 256 | { tlp_pci_phobos_21142_quirks, { 0x00, 0x60, 0xf5 } }, | |
257 | { tlp_pci_znyx_21142_quirks, { 0x00, 0xc0, 0x95 } }, | 257 | { tlp_pci_znyx_21142_quirks, { 0x00, 0xc0, 0x95 } }, | |
258 | { NULL, { 0, 0, 0 } } | 258 | { NULL, { 0, 0, 0 } } | |
259 | }; | 259 | }; | |
260 | 260 | |||
261 | static int tlp_pci_shared_intr(void *); | 261 | static int tlp_pci_shared_intr(void *); | |
262 | 262 | |||
263 | static const struct tulip_pci_product * | 263 | static const struct tulip_pci_product * | |
264 | tlp_pci_lookup(const struct pci_attach_args *pa) | 264 | tlp_pci_lookup(const struct pci_attach_args *pa) | |
265 | { | 265 | { | |
266 | const struct tulip_pci_product *tpp; | 266 | const struct tulip_pci_product *tpp; | |
267 | 267 | |||
268 | /* Don't match lmc cards */ | 268 | /* Don't match lmc cards */ | |
269 | if (PCI_VENDOR(pci_conf_read(pa->pa_pc, pa->pa_tag, | 269 | if (PCI_VENDOR(pci_conf_read(pa->pa_pc, pa->pa_tag, | |
270 | PCI_SUBSYS_ID_REG)) == PCI_VENDOR_LMC) | 270 | PCI_SUBSYS_ID_REG)) == PCI_VENDOR_LMC) | |
271 | return NULL; | 271 | return NULL; | |
272 | 272 | |||
273 | for (tpp = tlp_pci_products; tpp->tpp_chip != TULIP_CHIP_INVALID; | 273 | for (tpp = tlp_pci_products; tpp->tpp_chip != TULIP_CHIP_INVALID; | |
274 | tpp++) { | 274 | tpp++) { | |
275 | if (PCI_VENDOR(pa->pa_id) == tpp->tpp_vendor && | 275 | if (PCI_VENDOR(pa->pa_id) == tpp->tpp_vendor && | |
276 | PCI_PRODUCT(pa->pa_id) == tpp->tpp_product) | 276 | PCI_PRODUCT(pa->pa_id) == tpp->tpp_product) | |
277 | return tpp; | 277 | return tpp; | |
278 | } | 278 | } | |
279 | return NULL; | 279 | return NULL; | |
280 | } | 280 | } | |
281 | 281 | |||
282 | static void | 282 | static void | |
283 | tlp_pci_get_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr, | 283 | tlp_pci_get_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr, | |
284 | const struct tlp_pci_quirks *tpq) | 284 | const struct tlp_pci_quirks *tpq) | |
285 | { | 285 | { | |
286 | 286 | |||
287 | for (; tpq->tpq_func != NULL; tpq++) { | 287 | for (; tpq->tpq_func != NULL; tpq++) { | |
288 | if (tpq->tpq_oui[0] == enaddr[0] && | 288 | if (tpq->tpq_oui[0] == enaddr[0] && | |
289 | tpq->tpq_oui[1] == enaddr[1] && | 289 | tpq->tpq_oui[1] == enaddr[1] && | |
290 | tpq->tpq_oui[2] == enaddr[2]) { | 290 | tpq->tpq_oui[2] == enaddr[2]) { | |
291 | (*tpq->tpq_func)(psc, enaddr); | 291 | (*tpq->tpq_func)(psc, enaddr); | |
292 | return; | 292 | return; | |
293 | } | 293 | } | |
294 | } | 294 | } | |
295 | } | 295 | } | |
296 | 296 | |||
297 | static void | 297 | static void | |
298 | tlp_pci_check_slaved(struct tulip_pci_softc *psc, int shared, int slaved) | 298 | tlp_pci_check_slaved(struct tulip_pci_softc *psc, int shared, int slaved) | |
299 | { | 299 | { | |
300 | extern struct cfdriver tlp_cd; | 300 | extern struct cfdriver tlp_cd; | |
301 | struct tulip_pci_softc *cur, *best = NULL; | 301 | struct tulip_pci_softc *cur, *best = NULL; | |
302 | struct tulip_softc *sc = &psc->sc_tulip; | 302 | struct tulip_softc *sc = &psc->sc_tulip; | |
303 | int i; | 303 | int i; | |
304 | 304 | |||
305 | /* | 305 | /* | |
306 | * First of all, find the lowest pcidev numbered device on our | 306 | * First of all, find the lowest pcidev numbered device on our | |
307 | * bus marked as shared. That should be our master. | 307 | * bus marked as shared. That should be our master. | |
308 | */ | 308 | */ | |
309 | for (i = 0; i < tlp_cd.cd_ndevs; i++) { | 309 | for (i = 0; i < tlp_cd.cd_ndevs; i++) { | |
310 | if ((cur = device_lookup_private(&tlp_cd, i)) == NULL) | 310 | if ((cur = device_lookup_private(&tlp_cd, i)) == NULL) | |
311 | continue; | 311 | continue; | |
312 | if (device_parent(cur->sc_tulip.sc_dev) != | 312 | if (device_parent(cur->sc_tulip.sc_dev) != | |
313 | device_parent(sc->sc_dev)) | 313 | device_parent(sc->sc_dev)) | |
314 | continue; | 314 | continue; | |
315 | if ((cur->sc_flags & shared) == 0) | 315 | if ((cur->sc_flags & shared) == 0) | |
316 | continue; | 316 | continue; | |
317 | if (cur == psc) | 317 | if (cur == psc) | |
318 | continue; | 318 | continue; | |
319 | if (best == NULL || | 319 | if (best == NULL || | |
320 | best->sc_tulip.sc_devno > cur->sc_tulip.sc_devno) | 320 | best->sc_tulip.sc_devno > cur->sc_tulip.sc_devno) | |
321 | best = cur; | 321 | best = cur; | |
322 | } | 322 | } | |
323 | 323 | |||
324 | if (best != NULL) { | 324 | if (best != NULL) { | |
325 | psc->sc_master = best; | 325 | psc->sc_master = best; | |
326 | psc->sc_flags |= (shared | slaved); | 326 | psc->sc_flags |= (shared | slaved); | |
327 | } | 327 | } | |
328 | } | 328 | } | |
329 | 329 | |||
330 | static int | 330 | static int | |
331 | tlp_pci_match(device_t parent, cfdata_t match, void *aux) | 331 | tlp_pci_match(device_t parent, cfdata_t match, void *aux) | |
332 | { | 332 | { | |
333 | struct pci_attach_args *pa = aux; | 333 | struct pci_attach_args *pa = aux; | |
334 | 334 | |||
335 | if (tlp_pci_lookup(pa) != NULL) | 335 | if (tlp_pci_lookup(pa) != NULL) | |
336 | return 10; /* beat if_de.c */ | 336 | return 10; /* beat if_de.c */ | |
337 | 337 | |||
338 | return 0; | 338 | return 0; | |
339 | } | 339 | } | |
340 | 340 | |||
341 | static void | 341 | static void | |
342 | tlp_pci_attach(device_t parent, device_t self, void *aux) | 342 | tlp_pci_attach(device_t parent, device_t self, void *aux) | |
343 | { | 343 | { | |
344 | struct tulip_pci_softc *psc = device_private(self); | 344 | struct tulip_pci_softc *psc = device_private(self); | |
345 | struct tulip_softc *sc = &psc->sc_tulip; | 345 | struct tulip_softc *sc = &psc->sc_tulip; | |
346 | struct pci_attach_args *pa = aux; | 346 | struct pci_attach_args *pa = aux; | |
347 | pci_chipset_tag_t pc = pa->pa_pc; | 347 | pci_chipset_tag_t pc = pa->pa_pc; | |
348 | pci_intr_handle_t ih; | 348 | pci_intr_handle_t ih; | |
349 | const char *intrstr = NULL; | 349 | const char *intrstr = NULL; | |
350 | bus_space_tag_t iot, memt; | 350 | bus_space_tag_t iot, memt; | |
351 | bus_space_handle_t ioh, memh; | 351 | bus_space_handle_t ioh, memh; | |
352 | int ioh_valid, memh_valid, i, j; | 352 | int ioh_valid, memh_valid, i, j; | |
353 | const struct tulip_pci_product *tpp; | 353 | const struct tulip_pci_product *tpp; | |
354 | prop_data_t ea; | 354 | prop_data_t ea; | |
355 | uint8_t enaddr[ETHER_ADDR_LEN]; | 355 | uint8_t enaddr[ETHER_ADDR_LEN]; | |
356 | uint32_t val = 0; | 356 | uint32_t val = 0; | |
357 | pcireg_t reg; | 357 | pcireg_t reg; | |
358 | int error; | 358 | int error; | |
359 | bus_size_t iosize = 0, memsize = 0; | 359 | bus_size_t iosize = 0, memsize = 0; | |
360 | 360 | |||
361 | sc->sc_dev = self; | 361 | sc->sc_dev = self; | |
362 | sc->sc_devno = pa->pa_device; | 362 | sc->sc_devno = pa->pa_device; | |
363 | psc->sc_pc = pa->pa_pc; | 363 | psc->sc_pc = pa->pa_pc; | |
364 | psc->sc_pcitag = pa->pa_tag; | 364 | psc->sc_pcitag = pa->pa_tag; | |
365 | 365 | |||
366 | LIST_INIT(&psc->sc_intrslaves); | 366 | LIST_INIT(&psc->sc_intrslaves); | |
367 | 367 | |||
368 | tpp = tlp_pci_lookup(pa); | 368 | tpp = tlp_pci_lookup(pa); | |
369 | if (tpp == NULL) { | 369 | if (tpp == NULL) { | |
370 | printf("\n"); | 370 | printf("\n"); | |
371 | panic("tlp_pci_attach: impossible"); | 371 | panic("tlp_pci_attach: impossible"); | |
372 | } | 372 | } | |
373 | sc->sc_chip = tpp->tpp_chip; | 373 | sc->sc_chip = tpp->tpp_chip; | |
374 | 374 | |||
375 | /* | 375 | /* | |
376 | * By default, Tulip registers are 8 bytes long (4 bytes | 376 | * By default, Tulip registers are 8 bytes long (4 bytes | |
377 | * followed by a 4 byte pad). | 377 | * followed by a 4 byte pad). | |
378 | */ | 378 | */ | |
379 | sc->sc_regshift = 3; | 379 | sc->sc_regshift = 3; | |
380 | 380 | |||
381 | /* | 381 | /* | |
382 | * No power management hooks. | 382 | * No power management hooks. | |
383 | * XXX Maybe we should add some! | 383 | * XXX Maybe we should add some! | |
384 | */ | 384 | */ | |
385 | sc->sc_flags |= TULIPF_ENABLED; | 385 | sc->sc_flags |= TULIPF_ENABLED; | |
386 | 386 | |||
387 | /* | 387 | /* | |
388 | * Get revision info, and set some chip-specific variables. | 388 | * Get revision info, and set some chip-specific variables. | |
389 | */ | 389 | */ | |
390 | sc->sc_rev = PCI_REVISION(pa->pa_class); | 390 | sc->sc_rev = PCI_REVISION(pa->pa_class); | |
391 | switch (sc->sc_chip) { | 391 | switch (sc->sc_chip) { | |
392 | case TULIP_CHIP_21140: | 392 | case TULIP_CHIP_21140: | |
393 | if (sc->sc_rev >= 0x20) | 393 | if (sc->sc_rev >= 0x20) | |
394 | sc->sc_chip = TULIP_CHIP_21140A; | 394 | sc->sc_chip = TULIP_CHIP_21140A; | |
395 | break; | 395 | break; | |
396 | 396 | |||
397 | case TULIP_CHIP_21142: | 397 | case TULIP_CHIP_21142: | |
398 | if (sc->sc_rev >= 0x20) | 398 | if (sc->sc_rev >= 0x20) | |
399 | sc->sc_chip = TULIP_CHIP_21143; | 399 | sc->sc_chip = TULIP_CHIP_21143; | |
400 | break; | 400 | break; | |
401 | 401 | |||
402 | case TULIP_CHIP_82C168: | 402 | case TULIP_CHIP_82C168: | |
403 | if (sc->sc_rev >= 0x20) | 403 | if (sc->sc_rev >= 0x20) | |
404 | sc->sc_chip = TULIP_CHIP_82C169; | 404 | sc->sc_chip = TULIP_CHIP_82C169; | |
405 | break; | 405 | break; | |
406 | 406 | |||
407 | case TULIP_CHIP_MX98713: | 407 | case TULIP_CHIP_MX98713: | |
408 | if (sc->sc_rev >= 0x10) | 408 | if (sc->sc_rev >= 0x10) | |
409 | sc->sc_chip = TULIP_CHIP_MX98713A; | 409 | sc->sc_chip = TULIP_CHIP_MX98713A; | |
410 | break; | 410 | break; | |
411 | 411 | |||
412 | case TULIP_CHIP_MX98715: | 412 | case TULIP_CHIP_MX98715: | |
413 | if (sc->sc_rev >= 0x20) | 413 | if (sc->sc_rev >= 0x20) | |
414 | sc->sc_chip = TULIP_CHIP_MX98715A; | 414 | sc->sc_chip = TULIP_CHIP_MX98715A; | |
415 | if (sc->sc_rev >= 0x25) | 415 | if (sc->sc_rev >= 0x25) | |
416 | sc->sc_chip = TULIP_CHIP_MX98715AEC_X; | 416 | sc->sc_chip = TULIP_CHIP_MX98715AEC_X; | |
417 | if (sc->sc_rev >= 0x30) | 417 | if (sc->sc_rev >= 0x30) | |
418 | sc->sc_chip = TULIP_CHIP_MX98725; | 418 | sc->sc_chip = TULIP_CHIP_MX98725; | |
419 | break; | 419 | break; | |
420 | 420 | |||
421 | case TULIP_CHIP_WB89C840F: | 421 | case TULIP_CHIP_WB89C840F: | |
422 | sc->sc_regshift = 2; | 422 | sc->sc_regshift = 2; | |
423 | break; | 423 | break; | |
424 | 424 | |||
425 | case TULIP_CHIP_AN985: | 425 | case TULIP_CHIP_AN985: | |
426 | /* | 426 | /* | |
427 | * The AN983 and AN985 are very similar, and are | 427 | * The AN983 and AN985 are very similar, and are | |
428 | * differentiated by a "signature" register that | 428 | * differentiated by a "signature" register that | |
429 | * is like, but not identical, to a PCI ID register. | 429 | * is like, but not identical, to a PCI ID register. | |
430 | */ | 430 | */ | |
431 | reg = pci_conf_read(pc, pa->pa_tag, 0x80); | 431 | reg = pci_conf_read(pc, pa->pa_tag, 0x80); | |
432 | switch (reg) { | 432 | switch (reg) { | |
433 | case 0x09811317: | 433 | case 0x09811317: | |
434 | sc->sc_chip = TULIP_CHIP_AN985; | 434 | sc->sc_chip = TULIP_CHIP_AN985; | |
435 | break; | 435 | break; | |
436 | 436 | |||
437 | case 0x09851317: | 437 | case 0x09851317: | |
438 | sc->sc_chip = TULIP_CHIP_AN983; | 438 | sc->sc_chip = TULIP_CHIP_AN983; | |
439 | break; | 439 | break; | |
440 | 440 | |||
441 | default: | 441 | default: | |
442 | /* Unknown -- use default. */ | 442 | /* Unknown -- use default. */ | |
443 | break; | 443 | break; | |
444 | } | 444 | } | |
445 | break; | 445 | break; | |
446 | 446 | |||
447 | case TULIP_CHIP_AX88140: | 447 | case TULIP_CHIP_AX88140: | |
448 | if (sc->sc_rev >= 0x10) | 448 | if (sc->sc_rev >= 0x10) | |
449 | sc->sc_chip = TULIP_CHIP_AX88141; | 449 | sc->sc_chip = TULIP_CHIP_AX88141; | |
450 | break; | 450 | break; | |
451 | 451 | |||
452 | case TULIP_CHIP_DM9102: | 452 | case TULIP_CHIP_DM9102: | |
453 | if (sc->sc_rev >= 0x30) | 453 | if (sc->sc_rev >= 0x30) | |
454 | sc->sc_chip = TULIP_CHIP_DM9102A; | 454 | sc->sc_chip = TULIP_CHIP_DM9102A; | |
455 | break; | 455 | break; | |
456 | 456 | |||
457 | default: | 457 | default: | |
458 | /* Nothing. */ | 458 | /* Nothing. */ | |
459 | break; | 459 | break; | |
460 | } | 460 | } | |
461 | 461 | |||
462 | aprint_normal(": %s Ethernet, pass %d.%d\n", | 462 | aprint_normal(": %s Ethernet, pass %d.%d\n", | |
463 | tlp_chip_name(sc->sc_chip), | 463 | tlp_chip_name(sc->sc_chip), | |
464 | (sc->sc_rev >> 4) & 0xf, sc->sc_rev & 0xf); | 464 | (sc->sc_rev >> 4) & 0xf, sc->sc_rev & 0xf); | |
465 | 465 | |||
466 | switch (sc->sc_chip) { | 466 | switch (sc->sc_chip) { | |
467 | case TULIP_CHIP_21040: | 467 | case TULIP_CHIP_21040: | |
468 | if (sc->sc_rev < 0x20) { | 468 | if (sc->sc_rev < 0x20) { | |
469 | aprint_normal_dev(self, | 469 | aprint_normal_dev(self, | |
470 | "21040 must be at least pass 2.0\n"); | 470 | "21040 must be at least pass 2.0\n"); | |
471 | return; | 471 | return; | |
472 | } | 472 | } | |
473 | break; | 473 | break; | |
474 | 474 | |||
475 | case TULIP_CHIP_21140: | 475 | case TULIP_CHIP_21140: | |
476 | if (sc->sc_rev < 0x11) { | 476 | if (sc->sc_rev < 0x11) { | |
477 | aprint_normal_dev(self, | 477 | aprint_normal_dev(self, | |
478 | "21140 must be at least pass 1.1\n"); | 478 | "21140 must be at least pass 1.1\n"); | |
479 | return; | 479 | return; | |
480 | } | 480 | } | |
481 | break; | 481 | break; | |
482 | 482 | |||
483 | default: | 483 | default: | |
484 | /* Nothing. */ | 484 | /* Nothing. */ | |
485 | break; | 485 | break; | |
486 | } | 486 | } | |
487 | 487 | |||
488 | /* | 488 | /* | |
489 | * Check to see if the device is in power-save mode, and | 489 | * Check to see if the device is in power-save mode, and | |
490 | * being it out if necessary. | 490 | * being it out if necessary. | |
491 | */ | 491 | */ | |
492 | switch (sc->sc_chip) { | 492 | switch (sc->sc_chip) { | |
493 | case TULIP_CHIP_21140: | 493 | case TULIP_CHIP_21140: | |
494 | case TULIP_CHIP_21140A: | 494 | case TULIP_CHIP_21140A: | |
495 | case TULIP_CHIP_21142: | 495 | case TULIP_CHIP_21142: | |
496 | case TULIP_CHIP_21143: | 496 | case TULIP_CHIP_21143: | |
497 | case TULIP_CHIP_MX98713A: | 497 | case TULIP_CHIP_MX98713A: | |
498 | case TULIP_CHIP_MX98715: | 498 | case TULIP_CHIP_MX98715: | |
499 | case TULIP_CHIP_MX98715A: | 499 | case TULIP_CHIP_MX98715A: | |
500 | case TULIP_CHIP_MX98715AEC_X: | 500 | case TULIP_CHIP_MX98715AEC_X: | |
501 | case TULIP_CHIP_MX98725: | 501 | case TULIP_CHIP_MX98725: | |
502 | case TULIP_CHIP_DM9102: | 502 | case TULIP_CHIP_DM9102: | |
503 | case TULIP_CHIP_DM9102A: | 503 | case TULIP_CHIP_DM9102A: | |
504 | case TULIP_CHIP_AX88140: | 504 | case TULIP_CHIP_AX88140: | |
505 | case TULIP_CHIP_AX88141: | 505 | case TULIP_CHIP_AX88141: | |
506 | case TULIP_CHIP_RS7112: | 506 | case TULIP_CHIP_RS7112: | |
507 | /* | 507 | /* | |
508 | * Clear the "sleep mode" bit in the CFDA register. | 508 | * Clear the "sleep mode" bit in the CFDA register. | |
509 | */ | 509 | */ | |
510 | reg = pci_conf_read(pc, pa->pa_tag, TULIP_PCI_CFDA); | 510 | reg = pci_conf_read(pc, pa->pa_tag, TULIP_PCI_CFDA); | |
511 | if (reg & (CFDA_SLEEP|CFDA_SNOOZE)) | 511 | if (reg & (CFDA_SLEEP|CFDA_SNOOZE)) | |
512 | pci_conf_write(pc, pa->pa_tag, TULIP_PCI_CFDA, | 512 | pci_conf_write(pc, pa->pa_tag, TULIP_PCI_CFDA, | |
513 | reg & ~(CFDA_SLEEP|CFDA_SNOOZE)); | 513 | reg & ~(CFDA_SLEEP|CFDA_SNOOZE)); | |
514 | break; | 514 | break; | |
515 | 515 | |||
516 | default: | 516 | default: | |
517 | /* Nothing. */ | 517 | /* Nothing. */ | |
518 | break; | 518 | break; | |
519 | } | 519 | } | |
520 | 520 | |||
521 | /* power up chip */ | 521 | /* power up chip */ | |
522 | if ((error = pci_activate(pa->pa_pc, pa->pa_tag, self, | 522 | if ((error = pci_activate(pa->pa_pc, pa->pa_tag, self, | |
523 | NULL)) && error != EOPNOTSUPP) { | 523 | NULL)) && error != EOPNOTSUPP) { | |
524 | aprint_error_dev(self, "cannot activate %d\n", | 524 | aprint_error_dev(self, "cannot activate %d\n", | |
525 | error); | 525 | error); | |
526 | return; | 526 | return; | |
527 | } | 527 | } | |
528 | 528 | |||
529 | /* | 529 | /* | |
530 | * Map the device. | 530 | * Map the device. | |
531 | */ | 531 | */ | |
532 | 532 | |||
533 | ioh_valid = (pci_mapreg_map(pa, TULIP_PCI_IOBA, | 533 | ioh_valid = (pci_mapreg_map(pa, TULIP_PCI_IOBA, | |
534 | PCI_MAPREG_TYPE_IO, 0, | 534 | PCI_MAPREG_TYPE_IO, 0, | |
535 | &iot, &ioh, NULL, &iosize) == 0); | 535 | &iot, &ioh, NULL, &iosize) == 0); | |
536 | memh_valid = (pci_mapreg_map(pa, TULIP_PCI_MMBA, | 536 | memh_valid = (pci_mapreg_map(pa, TULIP_PCI_MMBA, | |
537 | PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, | 537 | PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT, 0, | |
538 | &memt, &memh, NULL, &memsize) == 0); | 538 | &memt, &memh, NULL, &memsize) == 0); | |
539 | if (memh_valid) { | 539 | if (memh_valid) { | |
540 | sc->sc_st = memt; | 540 | sc->sc_st = memt; | |
541 | sc->sc_sh = memh; | 541 | sc->sc_sh = memh; | |
542 | psc->sc_mapsize = memsize; | 542 | psc->sc_mapsize = memsize; | |
543 | if (ioh_valid) { | 543 | if (ioh_valid) { | |
544 | bus_space_unmap(iot, ioh, iosize); | 544 | bus_space_unmap(iot, ioh, iosize); | |
545 | ioh_valid = 0; | 545 | ioh_valid = 0; | |
546 | } | 546 | } | |
547 | } else if (ioh_valid) { | 547 | } else if (ioh_valid) { | |
548 | sc->sc_st = iot; | 548 | sc->sc_st = iot; | |
549 | sc->sc_sh = ioh; | 549 | sc->sc_sh = ioh; | |
550 | psc->sc_mapsize = iosize; | 550 | psc->sc_mapsize = iosize; | |
551 | if (memh_valid) { | 551 | if (memh_valid) { | |
552 | bus_space_unmap(memt, memh, memsize); | 552 | bus_space_unmap(memt, memh, memsize); | |
553 | memh_valid = 0; | 553 | memh_valid = 0; | |
554 | } | 554 | } | |
555 | } else { | 555 | } else { | |
556 | aprint_error_dev(self, "unable to map device registers\n"); | 556 | aprint_error_dev(self, "unable to map device registers\n"); | |
557 | goto fail; | 557 | goto fail; | |
558 | } | 558 | } | |
559 | 559 | |||
560 | sc->sc_dmat = pa->pa_dmat; | 560 | sc->sc_dmat = pa->pa_dmat; | |
561 | 561 | |||
562 | /* | 562 | /* | |
563 | * Make sure bus mastering is enabled. | 563 | * Make sure bus mastering is enabled. | |
564 | */ | 564 | */ | |
565 | pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, | 565 | pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, | |
566 | pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) | | 566 | pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) | | |
567 | PCI_COMMAND_MASTER_ENABLE); | 567 | PCI_COMMAND_MASTER_ENABLE); | |
568 | 568 | |||
569 | /* | 569 | /* | |
570 | * Get the cacheline size. | 570 | * Get the cacheline size. | |
571 | */ | 571 | */ | |
572 | sc->sc_cacheline = PCI_CACHELINE(pci_conf_read(pc, pa->pa_tag, | 572 | sc->sc_cacheline = PCI_CACHELINE(pci_conf_read(pc, pa->pa_tag, | |
573 | PCI_BHLC_REG)); | 573 | PCI_BHLC_REG)); | |
574 | 574 | |||
575 | /* | 575 | /* | |
576 | * Get PCI data moving command info. | 576 | * Get PCI data moving command info. | |
577 | */ | 577 | */ | |
578 | if (pa->pa_flags & PCI_FLAGS_MRL_OKAY) | 578 | if (pa->pa_flags & PCI_FLAGS_MRL_OKAY) | |
579 | sc->sc_flags |= TULIPF_MRL; | 579 | sc->sc_flags |= TULIPF_MRL; | |
580 | if (pa->pa_flags & PCI_FLAGS_MRM_OKAY) | 580 | if (pa->pa_flags & PCI_FLAGS_MRM_OKAY) | |
581 | sc->sc_flags |= TULIPF_MRM; | 581 | sc->sc_flags |= TULIPF_MRM; | |
582 | if (pa->pa_flags & PCI_FLAGS_MWI_OKAY) | 582 | if (pa->pa_flags & PCI_FLAGS_MWI_OKAY) | |
583 | sc->sc_flags |= TULIPF_MWI; | 583 | sc->sc_flags |= TULIPF_MWI; | |
584 | 584 | |||
585 | /* | 585 | /* | |
586 | * Read the contents of the Ethernet Address ROM/SROM. | 586 | * Read the contents of the Ethernet Address ROM/SROM. | |
587 | */ | 587 | */ | |
588 | switch (sc->sc_chip) { | 588 | switch (sc->sc_chip) { | |
589 | case TULIP_CHIP_21040: | 589 | case TULIP_CHIP_21040: | |
590 | sc->sc_srom_addrbits = 6; | 590 | sc->sc_srom_addrbits = 6; | |
591 | sc->sc_srom = malloc(TULIP_ROM_SIZE(6), M_DEVBUF, M_NOWAIT); | 591 | sc->sc_srom = malloc(TULIP_ROM_SIZE(6), M_DEVBUF, M_NOWAIT); | |
592 | TULIP_WRITE(sc, CSR_MIIROM, MIIROM_SROMCS); | 592 | TULIP_WRITE(sc, CSR_MIIROM, MIIROM_SROMCS); | |
593 | for (i = 0; i < TULIP_ROM_SIZE(6); i++) { | 593 | for (i = 0; i < TULIP_ROM_SIZE(6); i++) { | |
594 | for (j = 0; j < 10000; j++) { | 594 | for (j = 0; j < 10000; j++) { | |
595 | val = TULIP_READ(sc, CSR_MIIROM); | 595 | val = TULIP_READ(sc, CSR_MIIROM); | |
596 | if ((val & MIIROM_DN) == 0) | 596 | if ((val & MIIROM_DN) == 0) | |
597 | break; | 597 | break; | |
598 | } | 598 | } | |
599 | sc->sc_srom[i] = val & MIIROM_DATA; | 599 | sc->sc_srom[i] = val & MIIROM_DATA; | |
600 | } | 600 | } | |
601 | break; | 601 | break; | |
602 | 602 | |||
603 | case TULIP_CHIP_82C168: | 603 | case TULIP_CHIP_82C168: | |
604 | case TULIP_CHIP_82C169: | 604 | case TULIP_CHIP_82C169: | |
605 | { | 605 | { | |
606 | sc->sc_srom_addrbits = 2; | 606 | sc->sc_srom_addrbits = 2; | |
607 | sc->sc_srom = malloc(TULIP_ROM_SIZE(2), M_DEVBUF, M_NOWAIT); | 607 | sc->sc_srom = malloc(TULIP_ROM_SIZE(2), M_DEVBUF, M_NOWAIT); | |
608 | 608 | |||
609 | /* | 609 | /* | |
610 | * The Lite-On PNIC stores the Ethernet address in | 610 | * The Lite-On PNIC stores the Ethernet address in | |
611 | * the first 3 words of the EEPROM. EEPROM access | 611 | * the first 3 words of the EEPROM. EEPROM access | |
612 | * is not like the other Tulip chips. | 612 | * is not like the other Tulip chips. | |
613 | */ | 613 | */ | |
614 | for (i = 0; i < 6; i += 2) { | 614 | for (i = 0; i < 6; i += 2) { | |
615 | TULIP_WRITE(sc, CSR_PNIC_SROMCTL, | 615 | TULIP_WRITE(sc, CSR_PNIC_SROMCTL, | |
616 | PNIC_SROMCTL_READ | (i >> 1)); | 616 | PNIC_SROMCTL_READ | (i >> 1)); | |
617 | for (j = 0; j < 500; j++) { | 617 | for (j = 0; j < 500; j++) { | |
618 | delay(2); | 618 | delay(2); | |
619 | val = TULIP_READ(sc, CSR_MIIROM); | 619 | val = TULIP_READ(sc, CSR_MIIROM); | |
620 | if ((val & PNIC_MIIROM_BUSY) == 0) | 620 | if ((val & PNIC_MIIROM_BUSY) == 0) | |
621 | break; | 621 | break; | |
622 | } | 622 | } | |
623 | if (val & PNIC_MIIROM_BUSY) { | 623 | if (val & PNIC_MIIROM_BUSY) { | |
624 | aprint_error_dev(self, "EEPROM timed out\n"); | 624 | aprint_error_dev(self, "EEPROM timed out\n"); | |
625 | goto fail; | 625 | goto fail; | |
626 | } | 626 | } | |
627 | val &= PNIC_MIIROM_DATA; | 627 | val &= PNIC_MIIROM_DATA; | |
628 | sc->sc_srom[i] = val >> 8; | 628 | sc->sc_srom[i] = val >> 8; | |
629 | sc->sc_srom[i + 1] = val & 0xff; | 629 | sc->sc_srom[i + 1] = val & 0xff; | |
630 | } | 630 | } | |
631 | break; | 631 | break; | |
632 | } | 632 | } | |
633 | 633 | |||
634 | default: | 634 | default: | |
635 | /* | 635 | /* | |
636 | * XXX This isn't quite the right way to do this; we should | 636 | * XXX This isn't quite the right way to do this; we should | |
637 | * XXX be attempting to fetch the mac-addr property in the | 637 | * XXX be attempting to fetch the mac-addr property in the | |
638 | * XXX bus-agnostic part of the driver independently. But | 638 | * XXX bus-agnostic part of the driver independently. But | |
639 | * XXX that requires a larger change in the SROM handling | 639 | * XXX that requires a larger change in the SROM handling | |
640 | * XXX logic, and for now we can at least remove a machine- | 640 | * XXX logic, and for now we can at least remove a machine- | |
641 | * XXX dependent wart from the PCI front-end. | 641 | * XXX dependent wart from the PCI front-end. | |
642 | */ | 642 | */ | |
643 | ea = prop_dictionary_get(device_properties(self), | 643 | ea = prop_dictionary_get(device_properties(self), | |
644 | "mac-address"); | 644 | "mac-address"); | |
645 | if (ea != NULL) { | 645 | if (ea != NULL) { | |
646 | extern int tlp_srom_debug; | 646 | extern int tlp_srom_debug; | |
647 | KASSERT(prop_object_type(ea) == PROP_TYPE_DATA); | 647 | KASSERT(prop_object_type(ea) == PROP_TYPE_DATA); | |
648 | KASSERT(prop_data_size(ea) == ETHER_ADDR_LEN); | 648 | KASSERT(prop_data_size(ea) == ETHER_ADDR_LEN); | |
649 | 649 | |||
650 | memcpy(enaddr, prop_data_data_nocopy(ea), | 650 | memcpy(enaddr, prop_data_data_nocopy(ea), | |
651 | ETHER_ADDR_LEN); | 651 | ETHER_ADDR_LEN); | |
652 | 652 | |||
653 | sc->sc_srom_addrbits = 6; | 653 | sc->sc_srom_addrbits = 6; | |
654 | sc->sc_srom = malloc(TULIP_ROM_SIZE(6), M_DEVBUF, | 654 | sc->sc_srom = malloc(TULIP_ROM_SIZE(6), M_DEVBUF, | |
655 | M_NOWAIT|M_ZERO); | 655 | M_NOWAIT|M_ZERO); | |
656 | memcpy(sc->sc_srom, enaddr, sizeof(enaddr)); | 656 | memcpy(sc->sc_srom, enaddr, sizeof(enaddr)); | |
657 | if (tlp_srom_debug) { | 657 | if (tlp_srom_debug) { | |
658 | aprint_normal("SROM CONTENTS:"); | 658 | aprint_normal("SROM CONTENTS:"); | |
659 | for (i = 0; i < TULIP_ROM_SIZE(6); i++) { | 659 | for (i = 0; i < TULIP_ROM_SIZE(6); i++) { | |
660 | if ((i % 8) == 0) | 660 | if ((i % 8) == 0) | |
661 | aprint_normal("\n\t"); | 661 | aprint_normal("\n\t"); | |
662 | aprint_normal("0x%02x ", sc->sc_srom[i]); | 662 | aprint_normal("0x%02x ", sc->sc_srom[i]); | |
663 | } | 663 | } | |
664 | aprint_normal("\n"); | 664 | aprint_normal("\n"); | |
665 | } | 665 | } | |
666 | break; | 666 | break; | |
667 | } | 667 | } | |
668 | 668 | |||
669 | /* Check for a slaved ROM on a multi-port board. */ | 669 | /* Check for a slaved ROM on a multi-port board. */ | |
670 | tlp_pci_check_slaved(psc, TULIP_PCI_SHAREDROM, | 670 | tlp_pci_check_slaved(psc, TULIP_PCI_SHAREDROM, | |
671 | TULIP_PCI_SLAVEROM); | 671 | TULIP_PCI_SLAVEROM); | |
672 | if (psc->sc_flags & TULIP_PCI_SLAVEROM) { | 672 | if (psc->sc_flags & TULIP_PCI_SLAVEROM) { | |
673 | sc->sc_srom_addrbits = | 673 | sc->sc_srom_addrbits = | |
674 | psc->sc_master->sc_tulip.sc_srom_addrbits; | 674 | psc->sc_master->sc_tulip.sc_srom_addrbits; | |
675 | sc->sc_srom = psc->sc_master->sc_tulip.sc_srom; | 675 | sc->sc_srom = psc->sc_master->sc_tulip.sc_srom; | |
676 | enaddr[5] += | 676 | enaddr[5] += | |
677 | sc->sc_devno - psc->sc_master->sc_tulip.sc_devno; | 677 | sc->sc_devno - psc->sc_master->sc_tulip.sc_devno; | |
678 | } | 678 | } | |
679 | else if (tlp_read_srom(sc) == 0) | 679 | else if (tlp_read_srom(sc) == 0) | |
680 | goto cant_cope; | 680 | goto cant_cope; | |
681 | break; | 681 | break; | |
682 | } | 682 | } | |
683 | 683 | |||
684 | /* | 684 | /* | |
685 | * Deal with chip/board quirks. This includes setting up | 685 | * Deal with chip/board quirks. This includes setting up | |
686 | * the mediasw, and extracting the Ethernet address from | 686 | * the mediasw, and extracting the Ethernet address from | |
687 | * the rombuf. | 687 | * the rombuf. | |
688 | */ | 688 | */ | |
689 | switch (sc->sc_chip) { | 689 | switch (sc->sc_chip) { | |
690 | case TULIP_CHIP_21040: | 690 | case TULIP_CHIP_21040: | |
691 | /* | 691 | /* | |
692 | * Parse the Ethernet Address ROM. | 692 | * Parse the Ethernet Address ROM. | |
693 | */ | 693 | */ | |
694 | if (tlp_parse_old_srom(sc, enaddr) == 0) | 694 | if (tlp_parse_old_srom(sc, enaddr) == 0) | |
695 | goto cant_cope; | 695 | goto cant_cope; | |
696 | 696 | |||
697 | 697 | |||
698 | /* | 698 | /* | |
699 | * All 21040 boards start out with the same | 699 | * All 21040 boards start out with the same | |
700 | * media switch. | 700 | * media switch. | |
701 | */ | 701 | */ | |
702 | sc->sc_mediasw = &tlp_21040_mediasw; | 702 | sc->sc_mediasw = &tlp_21040_mediasw; | |
703 | 703 | |||
704 | /* | 704 | /* | |
705 | * Deal with any quirks this board might have. | 705 | * Deal with any quirks this board might have. | |
706 | */ | 706 | */ | |
707 | tlp_pci_get_quirks(psc, enaddr, tlp_pci_21040_quirks); | 707 | tlp_pci_get_quirks(psc, enaddr, tlp_pci_21040_quirks); | |
708 | break; | 708 | break; | |
709 | 709 | |||
710 | case TULIP_CHIP_21041: | 710 | case TULIP_CHIP_21041: | |
711 | /* Check for new format SROM. */ | 711 | /* Check for new format SROM. */ | |
712 | if (tlp_isv_srom_enaddr(sc, enaddr) == 0) { | 712 | if (tlp_isv_srom_enaddr(sc, enaddr) == 0) { | |
713 | /* | 713 | /* | |
714 | * Not an ISV SROM; try the old DEC Ethernet Address | 714 | * Not an ISV SROM; try the old DEC Ethernet Address | |
715 | * ROM format. | 715 | * ROM format. | |
716 | */ | 716 | */ | |
717 | if (tlp_parse_old_srom(sc, enaddr) == 0) | 717 | if (tlp_parse_old_srom(sc, enaddr) == 0) | |
718 | goto cant_cope; | 718 | goto cant_cope; | |
719 | } | 719 | } | |
720 | 720 | |||
721 | /* | 721 | /* | |
722 | * All 21041 boards use the same media switch; they all | 722 | * All 21041 boards use the same media switch; they all | |
723 | * work basically the same! Yippee! | 723 | * work basically the same! Yippee! | |
724 | */ | 724 | */ | |
725 | sc->sc_mediasw = &tlp_21041_mediasw; | 725 | sc->sc_mediasw = &tlp_21041_mediasw; | |
726 | 726 | |||
727 | /* | 727 | /* | |
728 | * Deal with any quirks this board might have. | 728 | * Deal with any quirks this board might have. | |
729 | */ | 729 | */ | |
730 | tlp_pci_get_quirks(psc, enaddr, tlp_pci_21041_quirks); | 730 | tlp_pci_get_quirks(psc, enaddr, tlp_pci_21041_quirks); | |
731 | break; | 731 | break; | |
732 | 732 | |||
733 | case TULIP_CHIP_21140: | 733 | case TULIP_CHIP_21140: | |
734 | case TULIP_CHIP_21140A: | 734 | case TULIP_CHIP_21140A: | |
735 | /* Check for new format SROM. */ | 735 | /* Check for new format SROM. */ | |
736 | if (tlp_isv_srom_enaddr(sc, enaddr) == 0) { | 736 | if (tlp_isv_srom_enaddr(sc, enaddr) == 0) { | |
737 | /* | 737 | /* | |
738 | * Not an ISV SROM; try the old DEC Ethernet Address | 738 | * Not an ISV SROM; try the old DEC Ethernet Address | |
739 | * ROM format. | 739 | * ROM format. | |
740 | */ | 740 | */ | |
741 | if (tlp_parse_old_srom(sc, enaddr) == 0) | 741 | if (tlp_parse_old_srom(sc, enaddr) == 0) | |
742 | goto cant_cope; | 742 | goto cant_cope; | |
743 | } else { | 743 | } else { | |
744 | /* | 744 | /* | |
745 | * We start out with the 2114x ISV media switch. | 745 | * We start out with the 2114x ISV media switch. | |
746 | * When we search for quirks, we may change to | 746 | * When we search for quirks, we may change to | |
747 | * a different switch. | 747 | * a different switch. | |
748 | */ | 748 | */ | |
749 | sc->sc_mediasw = &tlp_2114x_isv_mediasw; | 749 | sc->sc_mediasw = &tlp_2114x_isv_mediasw; | |
750 | } | 750 | } | |
751 | 751 | |||
752 | /* | 752 | /* | |
753 | * Deal with any quirks this board might have. | 753 | * Deal with any quirks this board might have. | |
754 | */ | 754 | */ | |
755 | tlp_pci_get_quirks(psc, enaddr, tlp_pci_21140_quirks); | 755 | tlp_pci_get_quirks(psc, enaddr, tlp_pci_21140_quirks); | |
756 | 756 | |||
757 | /* | 757 | /* | |
758 | * Bail out now if we can't deal with this board. | 758 | * Bail out now if we can't deal with this board. | |
759 | */ | 759 | */ | |
760 | if (sc->sc_mediasw == NULL) | 760 | if (sc->sc_mediasw == NULL) | |
761 | goto cant_cope; | 761 | goto cant_cope; | |
762 | break; | 762 | break; | |
763 | 763 | |||
764 | case TULIP_CHIP_21142: | 764 | case TULIP_CHIP_21142: | |
765 | case TULIP_CHIP_21143: | 765 | case TULIP_CHIP_21143: | |
766 | /* Check for new format SROM. */ | 766 | /* Check for new format SROM. */ | |
767 | if (tlp_isv_srom_enaddr(sc, enaddr) == 0) { | 767 | if (tlp_isv_srom_enaddr(sc, enaddr) == 0) { | |
768 | /* | 768 | /* | |
769 | * Not an ISV SROM; try the old DEC Ethernet Address | 769 | * Not an ISV SROM; try the old DEC Ethernet Address | |
770 | * ROM format. | 770 | * ROM format. | |
771 | */ | 771 | */ | |
772 | if (tlp_parse_old_srom(sc, enaddr) == 0) { | 772 | if (tlp_parse_old_srom(sc, enaddr) == 0) { | |
773 | /* | 773 | /* | |
774 | * One last try: just copy the address | 774 | * One last try: just copy the address | |
775 | * from offset 20 and try to look | 775 | * from offset 20 and try to look | |
776 | * up quirks. | 776 | * up quirks. | |
777 | */ | 777 | */ | |
778 | memcpy(enaddr, &sc->sc_srom[20], | 778 | memcpy(enaddr, &sc->sc_srom[20], | |
779 | ETHER_ADDR_LEN); | 779 | ETHER_ADDR_LEN); | |
780 | } | 780 | } | |
781 | } else { | 781 | } else { | |
782 | /* | 782 | /* | |
783 | * We start out with the 2114x ISV media switch. | 783 | * We start out with the 2114x ISV media switch. | |
784 | * When we search for quirks, we may change to | 784 | * When we search for quirks, we may change to | |
785 | * a different switch. | 785 | * a different switch. | |
786 | */ | 786 | */ | |
787 | sc->sc_mediasw = &tlp_2114x_isv_mediasw; | 787 | sc->sc_mediasw = &tlp_2114x_isv_mediasw; | |
788 | } | 788 | } | |
789 | 789 | |||
790 | /* | 790 | /* | |
791 | * Deal with any quirks this board might have. | 791 | * Deal with any quirks this board might have. | |
792 | */ | 792 | */ | |
793 | tlp_pci_get_quirks(psc, enaddr, tlp_pci_21142_quirks); | 793 | tlp_pci_get_quirks(psc, enaddr, tlp_pci_21142_quirks); | |
794 | 794 | |||
795 | /* | 795 | /* | |
796 | * Bail out now if we can't deal with this board. | 796 | * Bail out now if we can't deal with this board. | |
797 | */ | 797 | */ | |
798 | if (sc->sc_mediasw == NULL) | 798 | if (sc->sc_mediasw == NULL) | |
799 | goto cant_cope; | 799 | goto cant_cope; | |
800 | break; | 800 | break; | |
801 | 801 | |||
802 | case TULIP_CHIP_82C168: | 802 | case TULIP_CHIP_82C168: | |
803 | case TULIP_CHIP_82C169: | 803 | case TULIP_CHIP_82C169: | |
804 | /* | 804 | /* | |
805 | * Lite-On PNIC's Ethernet address is the first 6 | 805 | * Lite-On PNIC's Ethernet address is the first 6 | |
806 | * bytes of its EEPROM. | 806 | * bytes of its EEPROM. | |
807 | */ | 807 | */ | |
808 | memcpy(enaddr, sc->sc_srom, ETHER_ADDR_LEN); | 808 | memcpy(enaddr, sc->sc_srom, ETHER_ADDR_LEN); | |
809 | 809 | |||
810 | /* | 810 | /* | |
811 | * Lite-On PNICs always use the same mediasw; we | 811 | * Lite-On PNICs always use the same mediasw; we | |
812 | * select MII vs. internal NWAY automatically. | 812 | * select MII vs. internal NWAY automatically. | |
813 | */ | 813 | */ | |
814 | sc->sc_mediasw = &tlp_pnic_mediasw; | 814 | sc->sc_mediasw = &tlp_pnic_mediasw; | |
815 | break; | 815 | break; | |
816 | 816 | |||
817 | case TULIP_CHIP_MX98713: | 817 | case TULIP_CHIP_MX98713: | |
818 | /* | 818 | /* | |
819 | * The Macronix MX98713 has an MII and GPIO, but no | 819 | * The Macronix MX98713 has an MII and GPIO, but no | |
820 | * internal Nway block. This chip is basically a | 820 | * internal Nway block. This chip is basically a | |
821 | * perfect 21140A clone, with the exception of the | 821 | * perfect 21140A clone, with the exception of the | |
822 | * a magic register frobbing in order to make the | 822 | * a magic register frobbing in order to make the | |
823 | * interface function. | 823 | * interface function. | |
824 | */ | 824 | */ | |
825 | if (tlp_isv_srom_enaddr(sc, enaddr)) { | 825 | if (tlp_isv_srom_enaddr(sc, enaddr)) { | |
826 | sc->sc_mediasw = &tlp_2114x_isv_mediasw; | 826 | sc->sc_mediasw = &tlp_2114x_isv_mediasw; | |
827 | break; | 827 | break; | |
828 | } | 828 | } | |
829 | /* FALLTHROUGH */ | 829 | /* FALLTHROUGH */ | |
830 | 830 | |||
831 | case TULIP_CHIP_82C115: | 831 | case TULIP_CHIP_82C115: | |
832 | /* | 832 | /* | |
833 | * Yippee! The Lite-On 82C115 is a clone of | 833 | * Yippee! The Lite-On 82C115 is a clone of | |
834 | * the MX98725 (the data sheet even says `MXIC' | 834 | * the MX98725 (the data sheet even says `MXIC' | |
835 | * on it)! Imagine that, a clone of a clone. | 835 | * on it)! Imagine that, a clone of a clone. | |
836 | * | 836 | * | |
837 | * The differences are really minimal: | 837 | * The differences are really minimal: | |
838 | * | 838 | * | |
839 | * - Wake-On-LAN support | 839 | * - Wake-On-LAN support | |
840 | * - 128-bit multicast hash table, rather than | 840 | * - 128-bit multicast hash table, rather than | |
841 | * the standard 512-bit hash table | 841 | * the standard 512-bit hash table | |
842 | */ | 842 | */ | |
843 | /* FALLTHROUGH */ | 843 | /* FALLTHROUGH */ | |
844 | 844 | |||
845 | case TULIP_CHIP_MX98713A: | 845 | case TULIP_CHIP_MX98713A: | |
846 | case TULIP_CHIP_MX98715A: | 846 | case TULIP_CHIP_MX98715A: | |
847 | case TULIP_CHIP_MX98715AEC_X: | 847 | case TULIP_CHIP_MX98715AEC_X: | |
848 | case TULIP_CHIP_MX98725: | 848 | case TULIP_CHIP_MX98725: | |
849 | /* | 849 | /* | |
850 | * The MX98713A has an MII as well as an internal Nway block, | 850 | * The MX98713A has an MII as well as an internal Nway block, | |
851 | * but no GPIO. The MX98715 and MX98725 have an internal | 851 | * but no GPIO. The MX98715 and MX98725 have an internal | |
852 | * Nway block only. | 852 | * Nway block only. | |
853 | * | 853 | * | |
854 | * The internal Nway block, unlike the Lite-On PNIC's, does | 854 | * The internal Nway block, unlike the Lite-On PNIC's, does | |
855 | * just that - performs Nway. Once autonegotiation completes, | 855 | * just that - performs Nway. Once autonegotiation completes, | |
856 | * we must program the GPR media information into the chip. | 856 | * we must program the GPR media information into the chip. | |
857 | * | 857 | * | |
858 | * The byte offset of the Ethernet address is stored at | 858 | * The byte offset of the Ethernet address is stored at | |
859 | * offset 0x70. | 859 | * offset 0x70. | |
860 | */ | 860 | */ | |
861 | memcpy(enaddr, &sc->sc_srom[sc->sc_srom[0x70]], ETHER_ADDR_LEN); | 861 | memcpy(enaddr, &sc->sc_srom[sc->sc_srom[0x70]], ETHER_ADDR_LEN); | |
862 | sc->sc_mediasw = &tlp_pmac_mediasw; | 862 | sc->sc_mediasw = &tlp_pmac_mediasw; | |
863 | break; | 863 | break; | |
864 | 864 | |||
865 | case TULIP_CHIP_WB89C840F: | 865 | case TULIP_CHIP_WB89C840F: | |
866 | /* | 866 | /* | |
867 | * Winbond 89C840F's Ethernet address is the first | 867 | * Winbond 89C840F's Ethernet address is the first | |
868 | * 6 bytes of its EEPROM. | 868 | * 6 bytes of its EEPROM. | |
869 | */ | 869 | */ | |
870 | memcpy(enaddr, sc->sc_srom, ETHER_ADDR_LEN); | 870 | memcpy(enaddr, sc->sc_srom, ETHER_ADDR_LEN); | |
871 | 871 | |||
872 | /* | 872 | /* | |
873 | * Winbond 89C840F has an MII attached to the SIO. | 873 | * Winbond 89C840F has an MII attached to the SIO. | |
874 | */ | 874 | */ | |
875 | sc->sc_mediasw = &tlp_sio_mii_mediasw; | 875 | sc->sc_mediasw = &tlp_sio_mii_mediasw; | |
876 | break; | 876 | break; | |
877 | 877 | |||
878 | case TULIP_CHIP_AL981: | 878 | case TULIP_CHIP_AL981: | |
879 | /* | 879 | /* | |
880 | * The ADMtek AL981's Ethernet address is located | 880 | * The ADMtek AL981's Ethernet address is located | |
881 | * at offset 8 of its EEPROM. | 881 | * at offset 8 of its EEPROM. | |
882 | */ | 882 | */ | |
883 | memcpy(enaddr, &sc->sc_srom[8], ETHER_ADDR_LEN); | 883 | memcpy(enaddr, &sc->sc_srom[8], ETHER_ADDR_LEN); | |
884 | 884 | |||
885 | /* | 885 | /* | |
886 | * ADMtek AL981 has a built-in PHY accessed through | 886 | * ADMtek AL981 has a built-in PHY accessed through | |
887 | * special registers. | 887 | * special registers. | |
888 | */ | 888 | */ | |
889 | sc->sc_mediasw = &tlp_al981_mediasw; | 889 | sc->sc_mediasw = &tlp_al981_mediasw; | |
890 | break; | 890 | break; | |
891 | 891 | |||
892 | case TULIP_CHIP_AN983: | 892 | case TULIP_CHIP_AN983: | |
893 | case TULIP_CHIP_AN985: | 893 | case TULIP_CHIP_AN985: | |
894 | /* | 894 | /* | |
895 | * The ADMtek AN985's Ethernet address is located | 895 | * The ADMtek AN985's Ethernet address is located | |
896 | * at offset 8 of its EEPROM. | 896 | * at offset 8 of its EEPROM. | |
897 | */ | 897 | */ | |
898 | memcpy(enaddr, &sc->sc_srom[8], ETHER_ADDR_LEN); | 898 | memcpy(enaddr, &sc->sc_srom[8], ETHER_ADDR_LEN); | |
899 | 899 | |||
900 | /* | 900 | /* | |
901 | * The ADMtek AN985 can be configured in Single-Chip | 901 | * The ADMtek AN985 can be configured in Single-Chip | |
902 | * mode or MAC-only mode. Single-Chip uses the built-in | 902 | * mode or MAC-only mode. Single-Chip uses the built-in | |
903 | * PHY, MAC-only has an external PHY (usually HomePNA). | 903 | * PHY, MAC-only has an external PHY (usually HomePNA). | |
904 | * The selection is based on an EEPROM setting, and both | 904 | * The selection is based on an EEPROM setting, and both | |
905 | * PHYs are accessed via MII attached to SIO. | 905 | * PHYs are accessed via MII attached to SIO. | |
906 | * | 906 | * | |
907 | * The AN985 "ghosts" the internal PHY onto all | 907 | * The AN985 "ghosts" the internal PHY onto all | |
908 | * MII addresses, so we have to use a media init | 908 | * MII addresses, so we have to use a media init | |
909 | * routine that limits the search. | 909 | * routine that limits the search. | |
910 | * XXX How does this work with MAC-only mode? | 910 | * XXX How does this work with MAC-only mode? | |
911 | */ | 911 | */ | |
912 | sc->sc_mediasw = &tlp_an985_mediasw; | 912 | sc->sc_mediasw = &tlp_an985_mediasw; | |
913 | break; | 913 | break; | |
914 | 914 | |||
915 | case TULIP_CHIP_DM9102: | 915 | case TULIP_CHIP_DM9102: | |
916 | case TULIP_CHIP_DM9102A: | 916 | case TULIP_CHIP_DM9102A: | |
917 | /* | 917 | /* | |
918 | * Some boards with the Davicom chip have an ISV | 918 | * Some boards with the Davicom chip have an ISV | |
919 | * SROM (mostly DM9102A boards -- trying to describe | 919 | * SROM (mostly DM9102A boards -- trying to describe | |
920 | * the HomePNA PHY, probably) although the data in | 920 | * the HomePNA PHY, probably) although the data in | |
921 | * them is generally wrong. Check for ISV format | 921 | * them is generally wrong. Check for ISV format | |
922 | * and grab the Ethernet address that way, and if | 922 | * and grab the Ethernet address that way, and if | |
923 | * that fails, fall back on grabbing it from an | 923 | * that fails, fall back on grabbing it from an | |
924 | * observed offset of 20 (which is where it would | 924 | * observed offset of 20 (which is where it would | |
925 | * be in an ISV SROM anyhow, tho ISV can cope with | 925 | * be in an ISV SROM anyhow, tho ISV can cope with | |
926 | * multi-port boards). | 926 | * multi-port boards). | |
927 | */ | 927 | */ | |
928 | if (!tlp_isv_srom_enaddr(sc, enaddr)) { | 928 | if (!tlp_isv_srom_enaddr(sc, enaddr)) { | |
929 | 929 | |||
930 | prop_data_t eaddrprop; | 930 | prop_data_t eaddrprop; | |
931 | 931 | |||
932 | eaddrprop = prop_dictionary_get( | 932 | eaddrprop = prop_dictionary_get( | |
933 | device_properties(self), "mac-address"); | 933 | device_properties(self), "mac-address"); | |
934 | 934 | |||
935 | if (eaddrprop != NULL | 935 | if (eaddrprop != NULL | |
936 | && prop_data_size(eaddrprop) == ETHER_ADDR_LEN) | 936 | && prop_data_size(eaddrprop) == ETHER_ADDR_LEN) | |
937 | memcpy(enaddr, | 937 | memcpy(enaddr, | |
938 | prop_data_data_nocopy(eaddrprop), | 938 | prop_data_data_nocopy(eaddrprop), | |
939 | ETHER_ADDR_LEN); | 939 | ETHER_ADDR_LEN); | |
940 | else | 940 | else | |
941 | memcpy(enaddr, &sc->sc_srom[20], | 941 | memcpy(enaddr, &sc->sc_srom[20], | |
942 | ETHER_ADDR_LEN); | 942 | ETHER_ADDR_LEN); | |
943 | } | 943 | } | |
944 | 944 | |||
945 | /* | 945 | /* | |
946 | * Davicom chips all have an internal MII interface | 946 | * Davicom chips all have an internal MII interface | |
947 | * and a built-in PHY. DM9102A also has a an external | 947 | * and a built-in PHY. DM9102A also has a an external | |
948 | * MII interface, usually with a HomePNA PHY attached | 948 | * MII interface, usually with a HomePNA PHY attached | |
949 | * to it. | 949 | * to it. | |
950 | */ | 950 | */ | |
951 | sc->sc_mediasw = &tlp_dm9102_mediasw; | 951 | sc->sc_mediasw = &tlp_dm9102_mediasw; | |
952 | break; | 952 | break; | |
953 | 953 | |||
954 | case TULIP_CHIP_AX88140: | 954 | case TULIP_CHIP_AX88140: | |
955 | case TULIP_CHIP_AX88141: | 955 | case TULIP_CHIP_AX88141: | |
956 | /* | 956 | /* | |
957 | * ASIX AX88140/AX88141 Ethernet Address is located at offset | 957 | * ASIX AX88140/AX88141 Ethernet Address is located at offset | |
958 | * 20 of the SROM. | 958 | * 20 of the SROM. | |
959 | */ | 959 | */ | |
960 | memcpy(enaddr, &sc->sc_srom[20], ETHER_ADDR_LEN); | 960 | memcpy(enaddr, &sc->sc_srom[20], ETHER_ADDR_LEN); | |
961 | 961 | |||
962 | /* | 962 | /* | |
963 | * ASIX AX88140A/AX88141 chip can have a built-in PHY or | 963 | * ASIX AX88140A/AX88141 chip can have a built-in PHY or | |
964 | * an external MII interface. | 964 | * an external MII interface. | |
965 | */ | 965 | */ | |
966 | sc->sc_mediasw = &tlp_asix_mediasw; | 966 | sc->sc_mediasw = &tlp_asix_mediasw; | |
967 | break; | 967 | break; | |
968 | 968 | |||
969 | case TULIP_CHIP_RS7112: | 969 | case TULIP_CHIP_RS7112: | |
970 | /* | 970 | /* | |
971 | * RS7112 Ethernet Address is located of offset 0x19a | 971 | * RS7112 Ethernet Address is located of offset 0x19a | |
972 | * of the SROM | 972 | * of the SROM | |
973 | */ | 973 | */ | |
974 | memcpy(enaddr, &sc->sc_srom[0x19a], ETHER_ADDR_LEN); | 974 | memcpy(enaddr, &sc->sc_srom[0x19a], ETHER_ADDR_LEN); | |
975 | 975 | |||
976 | /* RS7112 chip has a PHY at MII address 1 */ | 976 | /* RS7112 chip has a PHY at MII address 1 */ | |
977 | sc->sc_mediasw = &tlp_rs7112_mediasw; | 977 | sc->sc_mediasw = &tlp_rs7112_mediasw; | |
978 | break; | 978 | break; | |
979 | 979 | |||
980 | default: | 980 | default: | |
981 | cant_cope: | 981 | cant_cope: | |
982 | aprint_error_dev(self, "sorry, unable to handle your board\n"); | 982 | aprint_error_dev(self, "sorry, unable to handle your board\n"); | |
983 | goto fail; | 983 | goto fail; | |
984 | } | 984 | } | |
985 | 985 | |||
986 | /* | 986 | /* | |
987 | * Handle shared interrupts. | 987 | * Handle shared interrupts. | |
988 | */ | 988 | */ | |
989 | if (psc->sc_flags & TULIP_PCI_SHAREDINTR) { | 989 | if (psc->sc_flags & TULIP_PCI_SHAREDINTR) { | |
990 | if (psc->sc_master) | 990 | if (psc->sc_master) | |
991 | psc->sc_flags |= TULIP_PCI_SLAVEINTR; | 991 | psc->sc_flags |= TULIP_PCI_SLAVEINTR; | |
992 | else { | 992 | else { | |
993 | tlp_pci_check_slaved(psc, TULIP_PCI_SHAREDINTR, | 993 | tlp_pci_check_slaved(psc, TULIP_PCI_SHAREDINTR, | |
994 | TULIP_PCI_SLAVEINTR); | 994 | TULIP_PCI_SLAVEINTR); | |
995 | if (psc->sc_master == NULL) | 995 | if (psc->sc_master == NULL) | |
996 | psc->sc_master = psc; | 996 | psc->sc_master = psc; | |
997 | } | 997 | } | |
998 | LIST_INSERT_HEAD(&psc->sc_master->sc_intrslaves, | 998 | LIST_INSERT_HEAD(&psc->sc_master->sc_intrslaves, | |
999 | psc, sc_intrq); | 999 | psc, sc_intrq); | |
1000 | } | 1000 | } | |
1001 | 1001 | |||
1002 | if (psc->sc_flags & TULIP_PCI_SLAVEINTR) { | 1002 | if (psc->sc_flags & TULIP_PCI_SLAVEINTR) { | |
1003 | aprint_normal_dev(self, "sharing interrupt with %s\n", | 1003 | aprint_normal_dev(self, "sharing interrupt with %s\n", | |
1004 | device_xname(psc->sc_master->sc_tulip.sc_dev)); | 1004 | device_xname(psc->sc_master->sc_tulip.sc_dev)); | |
1005 | } else { | 1005 | } else { | |
1006 | /* | 1006 | /* | |
1007 | * Map and establish our interrupt. | 1007 | * Map and establish our interrupt. | |
1008 | */ | 1008 | */ | |
1009 | if (pci_intr_map(pa, &ih)) { | 1009 | if (pci_intr_map(pa, &ih)) { | |
1010 | aprint_error_dev(self, "unable to map interrupt\n"); | 1010 | aprint_error_dev(self, "unable to map interrupt\n"); | |
1011 | goto fail; | 1011 | goto fail; | |
1012 | } | 1012 | } | |
1013 | intrstr = pci_intr_string(pc, ih); | 1013 | intrstr = pci_intr_string(pc, ih); | |
1014 | psc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, | 1014 | psc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, | |
1015 | (psc->sc_flags & TULIP_PCI_SHAREDINTR) ? | 1015 | (psc->sc_flags & TULIP_PCI_SHAREDINTR) ? | |
1016 | tlp_pci_shared_intr : tlp_intr, sc); | 1016 | tlp_pci_shared_intr : tlp_intr, sc); | |
1017 | if (psc->sc_ih == NULL) { | 1017 | if (psc->sc_ih == NULL) { | |
1018 | aprint_error_dev(self, "unable to establish interrupt"); | 1018 | aprint_error_dev(self, "unable to establish interrupt"); | |
1019 | if (intrstr != NULL) | 1019 | if (intrstr != NULL) | |
1020 | aprint_error(" at %s", intrstr); | 1020 | aprint_error(" at %s", intrstr); | |
1021 | aprint_error("\n"); | 1021 | aprint_error("\n"); | |
1022 | goto fail; | 1022 | goto fail; | |
1023 | } | 1023 | } | |
1024 | aprint_normal_dev(self, "interrupting at %s\n", | 1024 | aprint_normal_dev(self, "interrupting at %s\n", | |
1025 | intrstr); | 1025 | intrstr); | |
1026 | } | 1026 | } | |
1027 | 1027 | |||
1028 | /* | 1028 | /* | |
1029 | * Finish off the attach. | 1029 | * Finish off the attach. | |
1030 | */ | 1030 | */ | |
1031 | error = tlp_attach(sc, enaddr); | 1031 | error = tlp_attach(sc, enaddr); | |
1032 | if (error) | 1032 | if (error) | |
1033 | goto fail; | 1033 | goto fail; | |
1034 | return; | 1034 | return; | |
1035 | 1035 | |||
1036 | fail: | 1036 | fail: | |
1037 | if (psc->sc_ih != NULL) { | 1037 | if (psc->sc_ih != NULL) { | |
1038 | pci_intr_disestablish(psc->sc_pc, psc->sc_ih); | 1038 | pci_intr_disestablish(psc->sc_pc, psc->sc_ih); | |
1039 | psc->sc_ih = NULL; | 1039 | psc->sc_ih = NULL; | |
1040 | } | 1040 | } | |
1041 | 1041 | |||
1042 | if (ioh_valid) | 1042 | if (ioh_valid) | |
1043 | bus_space_unmap(iot, ioh, iosize); | 1043 | bus_space_unmap(iot, ioh, iosize); | |
1044 | if (memh_valid) | 1044 | if (memh_valid) | |
1045 | bus_space_unmap(memt, memh, memsize); | 1045 | bus_space_unmap(memt, memh, memsize); | |
1046 | psc->sc_mapsize = 0; | 1046 | psc->sc_mapsize = 0; | |
1047 | return; | 1047 | return; | |
1048 | } | 1048 | } | |
1049 | 1049 | |||
1050 | static int | 1050 | static int | |
1051 | tlp_pci_detach(device_t self, int flags) | 1051 | tlp_pci_detach(device_t self, int flags) | |
1052 | { | 1052 | { | |
1053 | struct tulip_pci_softc *psc = device_private(self); | 1053 | struct tulip_pci_softc *psc = device_private(self); | |
1054 | struct tulip_softc *sc = &psc->sc_tulip; | 1054 | struct tulip_softc *sc = &psc->sc_tulip; | |
1055 | int rv; | 1055 | int rv; | |
1056 | 1056 | |||
1057 | rv = tlp_detach(sc); | 1057 | rv = tlp_detach(sc); | |
1058 | if (rv) | 1058 | if (rv) | |
1059 | return rv; | 1059 | return rv; | |
1060 | 1060 | |||
1061 | if (psc->sc_ih != NULL) { | 1061 | if (psc->sc_ih != NULL) { | |
1062 | pci_intr_disestablish(psc->sc_pc, psc->sc_ih); | 1062 | pci_intr_disestablish(psc->sc_pc, psc->sc_ih); | |
1063 | psc->sc_ih = NULL; | 1063 | psc->sc_ih = NULL; | |
1064 | } | 1064 | } | |
1065 | 1065 | |||
1066 | if (psc->sc_mapsize) { | 1066 | if (psc->sc_mapsize) { | |
1067 | bus_space_unmap(sc->sc_st, sc->sc_sh, psc->sc_mapsize); | 1067 | bus_space_unmap(sc->sc_st, sc->sc_sh, psc->sc_mapsize); | |
1068 | psc->sc_mapsize = 0; | 1068 | psc->sc_mapsize = 0; | |
1069 | } | 1069 | } | |
1070 | 1070 | |||
1071 | return 0; | 1071 | return 0; | |
1072 | } | 1072 | } | |
1073 | 1073 | |||
1074 | static int | 1074 | static int | |
1075 | tlp_pci_shared_intr(void *arg) | 1075 | tlp_pci_shared_intr(void *arg) | |
1076 | { | 1076 | { | |
1077 | struct tulip_pci_softc *master = arg, *slave; | 1077 | struct tulip_pci_softc *master = arg, *slave; | |
1078 | int rv = 0; | 1078 | int rv = 0; | |
1079 | 1079 | |||
1080 | for (slave = LIST_FIRST(&master->sc_intrslaves); | 1080 | for (slave = LIST_FIRST(&master->sc_intrslaves); | |
1081 | slave != NULL; | 1081 | slave != NULL; | |
1082 | slave = LIST_NEXT(slave, sc_intrq)) | 1082 | slave = LIST_NEXT(slave, sc_intrq)) | |
1083 | rv |= tlp_intr(&slave->sc_tulip); | 1083 | rv |= tlp_intr(&slave->sc_tulip); | |
1084 | 1084 | |||
1085 | return rv; | 1085 | return rv; | |
1086 | } | 1086 | } | |
1087 | 1087 | |||
1088 | static void | 1088 | static void | |
1089 | tlp_pci_dec_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | 1089 | tlp_pci_dec_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | |
1090 | { | 1090 | { | |
1091 | struct tulip_softc *sc = &psc->sc_tulip; | 1091 | struct tulip_softc *sc = &psc->sc_tulip; | |
1092 | 1092 | |||
1093 | /* | 1093 | /* | |
1094 | * This isn't really a quirk-gathering device, really. We | 1094 | * This isn't really a quirk-gathering device, really. We | |
1095 | * just want to get the spiffy DEC board name from the SROM. | 1095 | * just want to get the spiffy DEC board name from the SROM. | |
1096 | */ | 1096 | */ | |
1097 | strcpy(sc->sc_name, "DEC "); | 1097 | strcpy(sc->sc_name, "DEC "); | |
1098 | 1098 | |||
1099 | if (memcmp(&sc->sc_srom[29], "DE500", 5) == 0 || | 1099 | if (memcmp(&sc->sc_srom[29], "DE500", 5) == 0 || | |
1100 | memcmp(&sc->sc_srom[29], "DE450", 5) == 0) | 1100 | memcmp(&sc->sc_srom[29], "DE450", 5) == 0) | |
1101 | memcpy(&sc->sc_name[4], &sc->sc_srom[29], 8); | 1101 | memcpy(&sc->sc_name[4], &sc->sc_srom[29], 8); | |
1102 | else | 1102 | else | |
1103 | sc->sc_name[3] = '\0'; | 1103 | sc->sc_name[3] = '\0'; | |
1104 | } | 1104 | } | |
1105 | 1105 | |||
1106 | static void | 1106 | static void | |
1107 | tlp_pci_znyx_21040_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | 1107 | tlp_pci_znyx_21040_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | |
1108 | { | 1108 | { | |
1109 | struct tulip_softc *sc = &psc->sc_tulip; | 1109 | struct tulip_softc *sc = &psc->sc_tulip; | |
1110 | uint16_t id = 0; | 1110 | uint16_t id = 0; | |
1111 | 1111 | |||
1112 | /* | 1112 | /* | |
1113 | * If we have a slaved ROM, just copy the bits from the master. | 1113 | * If we have a slaved ROM, just copy the bits from the master. | |
1114 | * This is in case we fail the ROM ID check (older boards) and | 1114 | * This is in case we fail the ROM ID check (older boards) and | |
1115 | * need to fall back on Ethernet address model checking; that | 1115 | * need to fall back on Ethernet address model checking; that | |
1116 | * will fail for slave chips. | 1116 | * will fail for slave chips. | |
1117 | */ | 1117 | */ | |
1118 | if (psc->sc_flags & TULIP_PCI_SLAVEROM) { | 1118 | if (psc->sc_flags & TULIP_PCI_SLAVEROM) { | |
1119 | strcpy(sc->sc_name, psc->sc_master->sc_tulip.sc_name); | 1119 | strcpy(sc->sc_name, psc->sc_master->sc_tulip.sc_name); | |
1120 | sc->sc_mediasw = psc->sc_master->sc_tulip.sc_mediasw; | 1120 | sc->sc_mediasw = psc->sc_master->sc_tulip.sc_mediasw; | |
1121 | psc->sc_flags |= | 1121 | psc->sc_flags |= | |
1122 | psc->sc_master->sc_flags & TULIP_PCI_SHAREDINTR; | 1122 | psc->sc_master->sc_flags & TULIP_PCI_SHAREDINTR; | |
1123 | return; | 1123 | return; | |
1124 | } | 1124 | } | |
1125 | 1125 | |||
1126 | if (sc->sc_srom[32] == 0x4a && sc->sc_srom[33] == 0x52) { | 1126 | if (sc->sc_srom[32] == 0x4a && sc->sc_srom[33] == 0x52) { | |
1127 | id = sc->sc_srom[37] | (sc->sc_srom[36] << 8); | 1127 | id = sc->sc_srom[37] | (sc->sc_srom[36] << 8); | |
1128 | switch (id) { | 1128 | switch (id) { | |
1129 | zx312: | 1129 | zx312: | |
1130 | case 0x0602: /* ZX312 */ | 1130 | case 0x0602: /* ZX312 */ | |
1131 | strcpy(sc->sc_name, "ZNYX ZX312"); | 1131 | strcpy(sc->sc_name, "ZNYX ZX312"); | |
1132 | return; | 1132 | return; | |
1133 | 1133 | |||
1134 | case 0x0622: /* ZX312T */ | 1134 | case 0x0622: /* ZX312T */ | |
1135 | strcpy(sc->sc_name, "ZNYX ZX312T"); | 1135 | strcpy(sc->sc_name, "ZNYX ZX312T"); | |
1136 | sc->sc_mediasw = &tlp_21040_tp_mediasw; | 1136 | sc->sc_mediasw = &tlp_21040_tp_mediasw; | |
1137 | return; | 1137 | return; | |
1138 | 1138 | |||
1139 | zx314_inta: | 1139 | zx314_inta: | |
1140 | case 0x0701: /* ZX314 INTA */ | 1140 | case 0x0701: /* ZX314 INTA */ | |
1141 | psc->sc_flags |= TULIP_PCI_SHAREDINTR; | 1141 | psc->sc_flags |= TULIP_PCI_SHAREDINTR; | |
1142 | /* FALLTHROUGH */ | 1142 | /* FALLTHROUGH */ | |
1143 | case 0x0711: /* ZX314 */ | 1143 | case 0x0711: /* ZX314 */ | |
1144 | strcpy(sc->sc_name, "ZNYX ZX314"); | 1144 | strcpy(sc->sc_name, "ZNYX ZX314"); | |
1145 | psc->sc_flags |= TULIP_PCI_SHAREDROM; | 1145 | psc->sc_flags |= TULIP_PCI_SHAREDROM; | |
1146 | sc->sc_mediasw = &tlp_21040_tp_mediasw; | 1146 | sc->sc_mediasw = &tlp_21040_tp_mediasw; | |
1147 | return; | 1147 | return; | |
1148 | 1148 | |||
1149 | zx315_inta: | 1149 | zx315_inta: | |
1150 | case 0x0801: /* ZX315 INTA */ | 1150 | case 0x0801: /* ZX315 INTA */ | |
1151 | psc->sc_flags |= TULIP_PCI_SHAREDINTR; | 1151 | psc->sc_flags |= TULIP_PCI_SHAREDINTR; | |
1152 | /* FALLTHROUGH */ | 1152 | /* FALLTHROUGH */ | |
1153 | case 0x0811: /* ZX315 */ | 1153 | case 0x0811: /* ZX315 */ | |
1154 | strcpy(sc->sc_name, "ZNYX ZX315"); | 1154 | strcpy(sc->sc_name, "ZNYX ZX315"); | |
1155 | psc->sc_flags |= TULIP_PCI_SHAREDROM; | 1155 | psc->sc_flags |= TULIP_PCI_SHAREDROM; | |
1156 | return; | 1156 | return; | |
1157 | 1157 | |||
1158 | default: | 1158 | default: | |
1159 | id = 0; | 1159 | id = 0; | |
1160 | break; | 1160 | break; | |
1161 | } | 1161 | } | |
1162 | } | 1162 | } | |
1163 | 1163 | |||
1164 | /* | 1164 | /* | |
1165 | * Deal with boards that have broken ROMs. | 1165 | * Deal with boards that have broken ROMs. | |
1166 | */ | 1166 | */ | |
1167 | if (id == 0) { | 1167 | if (id == 0) { | |
1168 | if ((enaddr[3] & ~3) == 0xf0 && (enaddr[5] & 3) == 0x00) | 1168 | if ((enaddr[3] & ~3) == 0xf0 && (enaddr[5] & 3) == 0x00) | |
1169 | goto zx314_inta; | 1169 | goto zx314_inta; | |
1170 | if ((enaddr[3] & ~3) == 0xf4 && (enaddr[5] & 1) == 0x00) | 1170 | if ((enaddr[3] & ~3) == 0xf4 && (enaddr[5] & 1) == 0x00) | |
1171 | goto zx315_inta; | 1171 | goto zx315_inta; | |
1172 | if ((enaddr[3] & ~3) == 0xec) | 1172 | if ((enaddr[3] & ~3) == 0xec) | |
1173 | goto zx312; | 1173 | goto zx312; | |
1174 | } | 1174 | } | |
1175 | 1175 | |||
1176 | strcpy(sc->sc_name, "ZNYX ZX31x"); | 1176 | strcpy(sc->sc_name, "ZNYX ZX31x"); | |
1177 | } | 1177 | } | |
1178 | 1178 | |||
1179 | static void tlp_pci_znyx_21142_qs6611_reset(struct tulip_softc *); | 1179 | static void tlp_pci_znyx_21142_qs6611_reset(struct tulip_softc *); | |
1180 | 1180 | |||
1181 | static void | 1181 | static void | |
1182 | tlp_pci_znyx_21142_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | 1182 | tlp_pci_znyx_21142_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | |
1183 | { | 1183 | { | |
1184 | struct tulip_softc *sc = &psc->sc_tulip; | 1184 | struct tulip_softc *sc = &psc->sc_tulip; | |
1185 | pcireg_t subid; | 1185 | pcireg_t subid; | |
1186 | 1186 | |||
1187 | subid = pci_conf_read(psc->sc_pc, psc->sc_pcitag, PCI_SUBSYS_ID_REG); | 1187 | subid = pci_conf_read(psc->sc_pc, psc->sc_pcitag, PCI_SUBSYS_ID_REG); | |
1188 | 1188 | |||
1189 | if (PCI_VENDOR(subid) != PCI_VENDOR_ZNYX) | 1189 | if (PCI_VENDOR(subid) != PCI_VENDOR_ZNYX) | |
1190 | return; /* ? */ | 1190 | return; /* ? */ | |
1191 | 1191 | |||
1192 | switch (PCI_PRODUCT(subid) & 0xff) { | 1192 | switch (PCI_PRODUCT(subid) & 0xff) { | |
1193 | /* | 1193 | /* | |
1194 | * ZNYX 21143 boards with QS6611 PHY | 1194 | * ZNYX 21143 boards with QS6611 PHY | |
1195 | */ | 1195 | */ | |
1196 | case 0x12: /* ZX345Q */ | 1196 | case 0x12: /* ZX345Q */ | |
1197 | case 0x13: /* ZX346Q */ | 1197 | case 0x13: /* ZX346Q */ | |
1198 | case 0x14: /* ZX348Q */ | 1198 | case 0x14: /* ZX348Q */ | |
1199 | case 0x18: /* ZX414 */ | 1199 | case 0x18: /* ZX414 */ | |
1200 | case 0x19: /* ZX412 */ | 1200 | case 0x19: /* ZX412 */ | |
1201 | case 0x1a: /* ZX444 */ | 1201 | case 0x1a: /* ZX444 */ | |
1202 | case 0x1b: /* ZX442 */ | 1202 | case 0x1b: /* ZX442 */ | |
1203 | case 0x23: /* ZX212 */ | 1203 | case 0x23: /* ZX212 */ | |
1204 | case 0x24: /* ZX214 */ | 1204 | case 0x24: /* ZX214 */ | |
1205 | case 0x29: /* ZX374 */ | 1205 | case 0x29: /* ZX374 */ | |
1206 | case 0x2d: /* ZX372 */ | 1206 | case 0x2d: /* ZX372 */ | |
1207 | case 0x2b: /* ZX244 */ | 1207 | case 0x2b: /* ZX244 */ | |
1208 | case 0x2c: /* ZX424 */ | 1208 | case 0x2c: /* ZX424 */ | |
1209 | case 0x2e: /* ZX422 */ | 1209 | case 0x2e: /* ZX422 */ | |
1210 | aprint_normal_dev(sc->sc_dev, "QS6611 PHY\n"); | 1210 | aprint_normal_dev(sc->sc_dev, "QS6611 PHY\n"); | |
1211 | sc->sc_reset = tlp_pci_znyx_21142_qs6611_reset; | 1211 | sc->sc_reset = tlp_pci_znyx_21142_qs6611_reset; | |
1212 | break; | 1212 | break; | |
1213 | } | 1213 | } | |
1214 | } | 1214 | } | |
1215 | 1215 | |||
1216 | static void | 1216 | static void | |
1217 | tlp_pci_znyx_21142_qs6611_reset(struct tulip_softc *sc) | 1217 | tlp_pci_znyx_21142_qs6611_reset(struct tulip_softc *sc) | |
1218 | { | 1218 | { | |
1219 | 1219 | |||
1220 | /* | 1220 | /* | |
1221 | * Reset QS6611 PHY. | 1221 | * Reset QS6611 PHY. | |
1222 | */ | 1222 | */ | |
1223 | TULIP_WRITE(sc, CSR_SIAGEN, | 1223 | TULIP_WRITE(sc, CSR_SIAGEN, | |
1224 | SIAGEN_CWE | SIAGEN_LGS1 | SIAGEN_ABM | (0xf << 16)); | 1224 | SIAGEN_CWE | SIAGEN_LGS1 | SIAGEN_ABM | (0xf << 16)); | |
1225 | delay(200); | 1225 | delay(200); | |
1226 | TULIP_WRITE(sc, CSR_SIAGEN, (0x4 << 16)); | 1226 | TULIP_WRITE(sc, CSR_SIAGEN, (0x4 << 16)); | |
1227 | delay(10000); | 1227 | delay(10000); | |
1228 | } | 1228 | } | |
1229 | 1229 | |||
1230 | static void | 1230 | static void | |
1231 | tlp_pci_smc_21040_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | 1231 | tlp_pci_smc_21040_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | |
1232 | { | 1232 | { | |
1233 | struct tulip_softc *sc = &psc->sc_tulip; | 1233 | struct tulip_softc *sc = &psc->sc_tulip; | |
1234 | uint16_t id1, id2, ei; | 1234 | uint16_t id1, id2, ei; | |
1235 | int auibnc = 0, utp = 0; | 1235 | int auibnc = 0, utp = 0; | |
1236 | char *cp; | 1236 | char *cp; | |
1237 | 1237 | |||
1238 | id1 = sc->sc_srom[0x60] | (sc->sc_srom[0x61] << 8); | 1238 | id1 = sc->sc_srom[0x60] | (sc->sc_srom[0x61] << 8); | |
1239 | id2 = sc->sc_srom[0x62] | (sc->sc_srom[0x63] << 8); | 1239 | id2 = sc->sc_srom[0x62] | (sc->sc_srom[0x63] << 8); | |
1240 | ei = sc->sc_srom[0x66] | (sc->sc_srom[0x67] << 8); | 1240 | ei = sc->sc_srom[0x66] | (sc->sc_srom[0x67] << 8); | |
1241 | 1241 | |||
1242 | strcpy(sc->sc_name, "SMC 8432"); | 1242 | strcpy(sc->sc_name, "SMC 8432"); | |
1243 | cp = &sc->sc_name[8]; | 1243 | cp = &sc->sc_name[8]; | |
1244 | 1244 | |||
1245 | if ((id1 & 1) == 0) { | 1245 | if ((id1 & 1) == 0) { | |
1246 | *cp++ = 'B'; | 1246 | *cp++ = 'B'; | |
1247 | auibnc = 1; | 1247 | auibnc = 1; | |
1248 | } | 1248 | } | |
1249 | if ((id1 & 0xff) > 0x32) { | 1249 | if ((id1 & 0xff) > 0x32) { | |
1250 | *cp++ = 'T'; | 1250 | *cp++ = 'T'; | |
1251 | utp = 1; | 1251 | utp = 1; | |
1252 | } | 1252 | } | |
1253 | if ((id1 & 0x4000) == 0) { | 1253 | if ((id1 & 0x4000) == 0) { | |
1254 | *cp++ = 'A'; | 1254 | *cp++ = 'A'; | |
1255 | auibnc = 1; | 1255 | auibnc = 1; | |
1256 | } | 1256 | } | |
1257 | if (id2 == 0x15) { | 1257 | if (id2 == 0x15) { | |
1258 | sc->sc_name[7] = '4'; | 1258 | sc->sc_name[7] = '4'; | |
1259 | *cp++ = '-'; | 1259 | *cp++ = '-'; | |
1260 | *cp++ = 'C'; | 1260 | *cp++ = 'C'; | |
1261 | *cp++ = 'H'; | 1261 | *cp++ = 'H'; | |
1262 | *cp++ = ei ? '2' : '1'; | 1262 | *cp++ = ei ? '2' : '1'; | |
1263 | } | 1263 | } | |
1264 | *cp = '\0'; | 1264 | *cp = '\0'; | |
1265 | 1265 | |||
1266 | if (utp != 0 && auibnc == 0) | 1266 | if (utp != 0 && auibnc == 0) | |
1267 | sc->sc_mediasw = &tlp_21040_tp_mediasw; | 1267 | sc->sc_mediasw = &tlp_21040_tp_mediasw; | |
1268 | else if (utp == 0 && auibnc != 0) | 1268 | else if (utp == 0 && auibnc != 0) | |
1269 | sc->sc_mediasw = &tlp_21040_auibnc_mediasw; | 1269 | sc->sc_mediasw = &tlp_21040_auibnc_mediasw; | |
1270 | } | 1270 | } | |
1271 | 1271 | |||
1272 | static void | 1272 | static void | |
1273 | tlp_pci_cogent_21040_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | 1273 | tlp_pci_cogent_21040_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | |
1274 | { | 1274 | { | |
1275 | 1275 | |||
1276 | strcpy(psc->sc_tulip.sc_name, "Cogent multi-port"); | 1276 | strcpy(psc->sc_tulip.sc_name, "Cogent multi-port"); | |
1277 | psc->sc_flags |= TULIP_PCI_SHAREDINTR|TULIP_PCI_SHAREDROM; | 1277 | psc->sc_flags |= TULIP_PCI_SHAREDINTR|TULIP_PCI_SHAREDROM; | |
1278 | } | 1278 | } | |
1279 | 1279 | |||
1280 | static void | 1280 | static void | |
1281 | tlp_pci_accton_21040_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | 1281 | tlp_pci_accton_21040_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | |
1282 | { | 1282 | { | |
1283 | 1283 | |||
1284 | strcpy(psc->sc_tulip.sc_name, "ACCTON EN1203"); | 1284 | strcpy(psc->sc_tulip.sc_name, "ACCTON EN1203"); | |
1285 | } | 1285 | } | |
1286 | 1286 | |||
1287 | static void tlp_pci_asante_21140_reset(struct tulip_softc *); | 1287 | static void tlp_pci_asante_21140_reset(struct tulip_softc *); | |
1288 | 1288 | |||
1289 | static void | 1289 | static void | |
1290 | tlp_pci_asante_21140_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | 1290 | tlp_pci_asante_21140_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | |
1291 | { | 1291 | { | |
1292 | struct tulip_softc *sc = &psc->sc_tulip; | 1292 | struct tulip_softc *sc = &psc->sc_tulip; | |
1293 | 1293 | |||
1294 | /* | 1294 | /* | |
1295 | * Some Asante boards don't use the ISV SROM format. For | 1295 | * Some Asante boards don't use the ISV SROM format. For | |
1296 | * those that don't, we initialize the GPIO direction bits, | 1296 | * those that don't, we initialize the GPIO direction bits, | |
1297 | * and provide our own reset hook, which resets the MII. | 1297 | * and provide our own reset hook, which resets the MII. | |
1298 | * | 1298 | * | |
1299 | * All of these boards use SIO-attached-MII media. | 1299 | * All of these boards use SIO-attached-MII media. | |
1300 | */ | 1300 | */ | |
1301 | if (sc->sc_mediasw == &tlp_2114x_isv_mediasw) | 1301 | if (sc->sc_mediasw == &tlp_2114x_isv_mediasw) | |
1302 | return; | 1302 | return; | |
1303 | 1303 | |||
1304 | strcpy(sc->sc_name, "Asante"); | 1304 | strcpy(sc->sc_name, "Asante"); | |
1305 | 1305 | |||
1306 | sc->sc_gp_dir = 0xbf; | 1306 | sc->sc_gp_dir = 0xbf; | |
1307 | sc->sc_reset = tlp_pci_asante_21140_reset; | 1307 | sc->sc_reset = tlp_pci_asante_21140_reset; | |
1308 | sc->sc_mediasw = &tlp_sio_mii_mediasw; | 1308 | sc->sc_mediasw = &tlp_sio_mii_mediasw; | |
1309 | } | 1309 | } | |
1310 | 1310 | |||
1311 | static void | 1311 | static void | |
1312 | tlp_pci_e100_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | 1312 | tlp_pci_e100_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | |
1313 | { | 1313 | { | |
1314 | struct tulip_softc *sc = &psc->sc_tulip; | 1314 | struct tulip_softc *sc = &psc->sc_tulip; | |
1315 | 1315 | |||
1316 | if (sc->sc_mediasw == &tlp_2114x_isv_mediasw) | 1316 | if (sc->sc_mediasw == &tlp_2114x_isv_mediasw) | |
1317 | return; | 1317 | return; | |
1318 | 1318 | |||
1319 | strcpy(sc->sc_name, "UMAX E100"); | 1319 | strcpy(sc->sc_name, "UMAX E100"); | |
1320 | 1320 | |||
1321 | sc->sc_gp_dir = 0xbf; | 1321 | sc->sc_gp_dir = 0xbf; | |
1322 | sc->sc_reset = tlp_pci_asante_21140_reset; | 1322 | sc->sc_reset = tlp_pci_asante_21140_reset; | |
1323 | sc->sc_mediasw = &tlp_sio_mii_mediasw; | 1323 | sc->sc_mediasw = &tlp_sio_mii_mediasw; | |
1324 | } | 1324 | } | |
1325 | 1325 | |||
1326 | static void | 1326 | static void | |
1327 | tlp_pci_asante_21140_reset(struct tulip_softc *sc) | 1327 | tlp_pci_asante_21140_reset(struct tulip_softc *sc) | |
1328 | { | 1328 | { | |
1329 | 1329 | |||
1330 | TULIP_WRITE(sc, CSR_GPP, GPP_GPC | sc->sc_gp_dir); | 1330 | TULIP_WRITE(sc, CSR_GPP, GPP_GPC | sc->sc_gp_dir); | |
1331 | TULIP_WRITE(sc, CSR_GPP, 0x8); | 1331 | TULIP_WRITE(sc, CSR_GPP, 0x8); | |
1332 | delay(100); | 1332 | delay(100); | |
1333 | TULIP_WRITE(sc, CSR_GPP, 0); | 1333 | TULIP_WRITE(sc, CSR_GPP, 0); | |
1334 | } | 1334 | } | |
1335 | 1335 | |||
1336 | static void tlp_pci_phobos_21140_reset(struct tulip_softc *); | 1336 | static void tlp_pci_phobos_21140_reset(struct tulip_softc *); | |
1337 | 1337 | |||
1338 | static void | 1338 | static void | |
1339 | tlp_pci_phobos_21140_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | 1339 | tlp_pci_phobos_21140_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | |
1340 | { | 1340 | { | |
1341 | struct tulip_softc *sc = &psc->sc_tulip; | 1341 | struct tulip_softc *sc = &psc->sc_tulip; | |
1342 | 1342 | |||
1343 | /* | 1343 | /* | |
1344 | * Phobos boards just use MII-on-SIO. | 1344 | * Phobos boards just use MII-on-SIO. | |
1345 | */ | 1345 | */ | |
1346 | sc->sc_mediasw = &tlp_sio_mii_mediasw; | 1346 | sc->sc_mediasw = &tlp_sio_mii_mediasw; | |
1347 | sc->sc_reset = tlp_pci_phobos_21140_reset; | 1347 | sc->sc_reset = tlp_pci_phobos_21140_reset; | |
1348 | 1348 | |||
1349 | /* | 1349 | /* | |
1350 | * These boards appear solely on sgimips machines behind a special | 1350 | * These boards appear solely on sgimips machines behind a special | |
1351 | * GIO<->PCI ASIC and require the DBO and BLE bits to be set in CSR0. | 1351 | * GIO<->PCI ASIC and require the DBO and BLE bits to be set in CSR0. | |
1352 | */ | 1352 | */ | |
1353 | sc->sc_flags |= (TULIPF_BLE | TULIPF_DBO); | 1353 | sc->sc_flags |= (TULIPF_BLE | TULIPF_DBO); | |
1354 | } | 1354 | } | |
1355 | 1355 | |||
1356 | static void | 1356 | static void | |
1357 | tlp_pci_phobos_21140_reset(struct tulip_softc *sc) | 1357 | tlp_pci_phobos_21140_reset(struct tulip_softc *sc) | |
1358 | { | 1358 | { | |
1359 | 1359 | |||
1360 | TULIP_WRITE(sc, CSR_GPP, GPP_GPC | 0xfd); | 1360 | TULIP_WRITE(sc, CSR_GPP, GPP_GPC | 0xfd); | |
1361 | delay(10); | 1361 | delay(10); | |
1362 | TULIP_WRITE(sc, CSR_GPP, 0xfd); | 1362 | TULIP_WRITE(sc, CSR_GPP, 0xfd); | |
1363 | delay(10); | 1363 | delay(10); | |
1364 | TULIP_WRITE(sc, CSR_GPP, 0); | 1364 | TULIP_WRITE(sc, CSR_GPP, 0); | |
1365 | } | 1365 | } | |
1366 | 1366 | |||
1367 | /* | 1367 | /* | |
1368 | * SMC 9332DST media switch. | 1368 | * SMC 9332DST media switch. | |
1369 | */ | 1369 | */ | |
1370 | static void tlp_smc9332dst_tmsw_init(struct tulip_softc *); | 1370 | static void tlp_smc9332dst_tmsw_init(struct tulip_softc *); | |
1371 | 1371 | |||
1372 | static const struct tulip_mediasw tlp_smc9332dst_mediasw = { | 1372 | static const struct tulip_mediasw tlp_smc9332dst_mediasw = { | |
1373 | tlp_smc9332dst_tmsw_init, | 1373 | tlp_smc9332dst_tmsw_init, | |
1374 | tlp_21140_gpio_get, | 1374 | tlp_21140_gpio_get, | |
1375 | tlp_21140_gpio_set | 1375 | tlp_21140_gpio_set | |
1376 | }; | 1376 | }; | |
1377 | 1377 | |||
1378 | static void | 1378 | static void | |
1379 | tlp_pci_smc_21140_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | 1379 | tlp_pci_smc_21140_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | |
1380 | { | 1380 | { | |
1381 | struct tulip_softc *sc = &psc->sc_tulip; | 1381 | struct tulip_softc *sc = &psc->sc_tulip; | |
1382 | 1382 | |||
1383 | strcpy(psc->sc_tulip.sc_name, "SMC 9332DST"); | 1383 | strcpy(psc->sc_tulip.sc_name, "SMC 9332DST"); | |
1384 | sc->sc_mediasw = &tlp_smc9332dst_mediasw; | 1384 | sc->sc_mediasw = &tlp_smc9332dst_mediasw; | |
1385 | } | 1385 | } | |
1386 | 1386 | |||
1387 | static void | 1387 | static void | |
1388 | tlp_smc9332dst_tmsw_init(struct tulip_softc *sc) | 1388 | tlp_smc9332dst_tmsw_init(struct tulip_softc *sc) | |
1389 | { | 1389 | { | |
1390 | struct tulip_21x4x_media *tm; | 1390 | struct tulip_21x4x_media *tm; | |
1391 | const char *sep = ""; | 1391 | const char *sep = ""; | |
1392 | uint32_t reg; | 1392 | uint32_t reg; | |
1393 | int i, cnt; | 1393 | int i, cnt; | |
1394 | 1394 | |||
1395 | sc->sc_gp_dir = GPP_SMC9332DST_PINS; | 1395 | sc->sc_gp_dir = GPP_SMC9332DST_PINS; | |
1396 | sc->sc_opmode = OPMODE_MBO | OPMODE_PS; | 1396 | sc->sc_opmode = OPMODE_MBO | OPMODE_PS; | |
1397 | TULIP_WRITE(sc, CSR_OPMODE, sc->sc_opmode); | 1397 | TULIP_WRITE(sc, CSR_OPMODE, sc->sc_opmode); | |
1398 | 1398 | |||
1399 | ifmedia_init(&sc->sc_mii.mii_media, 0, tlp_mediachange, | 1399 | ifmedia_init(&sc->sc_mii.mii_media, 0, tlp_mediachange, | |
1400 | tlp_mediastatus); | 1400 | tlp_mediastatus); | |
1401 | aprint_normal_dev(sc->sc_dev, ""); | 1401 | aprint_normal_dev(sc->sc_dev, ""); | |
1402 | 1402 | |||
1403 | #define ADD(m, c) \ | 1403 | #define ADD(m, c) \ | |
1404 | tm = malloc(sizeof(*tm), M_DEVBUF, M_WAITOK|M_ZERO); \ | 1404 | tm = malloc(sizeof(*tm), M_DEVBUF, M_WAITOK|M_ZERO); \ | |
1405 | tm->tm_opmode = (c); \ | 1405 | tm->tm_opmode = (c); \ | |
1406 | tm->tm_gpdata = GPP_SMC9332DST_INIT; \ | 1406 | tm->tm_gpdata = GPP_SMC9332DST_INIT; \ | |
1407 | ifmedia_add(&sc->sc_mii.mii_media, (m), 0, tm) | 1407 | ifmedia_add(&sc->sc_mii.mii_media, (m), 0, tm) | |
1408 | #define PRINT(str) aprint_normal("%s%s", sep, str); sep = ", " | 1408 | #define PRINT(str) aprint_normal("%s%s", sep, str); sep = ", " | |
1409 | 1409 | |||
1410 | ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0), OPMODE_TTM); | 1410 | ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0), OPMODE_TTM); | |
1411 | PRINT("10baseT"); | 1411 | PRINT("10baseT"); | |
1412 | 1412 | |||
1413 | ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, 0), | 1413 | ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, 0), | |
1414 | OPMODE_TTM | OPMODE_FD); | 1414 | OPMODE_TTM | OPMODE_FD); | |
1415 | PRINT("10baseT-FDX"); | 1415 | PRINT("10baseT-FDX"); | |
1416 | 1416 | |||
1417 | ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, 0), | 1417 | ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, 0), | |
1418 | OPMODE_PS | OPMODE_PCS | OPMODE_SCR); | 1418 | OPMODE_PS | OPMODE_PCS | OPMODE_SCR); | |
1419 | PRINT("100baseTX"); | 1419 | PRINT("100baseTX"); | |
1420 | 1420 | |||
1421 | ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, 0), | 1421 | ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, 0), | |
1422 | OPMODE_PS | OPMODE_PCS | OPMODE_SCR | OPMODE_FD); | 1422 | OPMODE_PS | OPMODE_PCS | OPMODE_SCR | OPMODE_FD); | |
1423 | PRINT("100baseTX-FDX"); | 1423 | PRINT("100baseTX-FDX"); | |
1424 | 1424 | |||
1425 | #undef ADD | 1425 | #undef ADD | |
1426 | #undef PRINT | 1426 | #undef PRINT | |
1427 | 1427 | |||
1428 | aprint_normal("\n"); | 1428 | aprint_normal("\n"); | |
1429 | 1429 | |||
1430 | tlp_reset(sc); | 1430 | tlp_reset(sc); | |
1431 | TULIP_WRITE(sc, CSR_OPMODE, sc->sc_opmode | OPMODE_PCS | OPMODE_SCR); | 1431 | TULIP_WRITE(sc, CSR_OPMODE, sc->sc_opmode | OPMODE_PCS | OPMODE_SCR); | |
1432 | TULIP_WRITE(sc, CSR_GPP, GPP_GPC | sc->sc_gp_dir); | 1432 | TULIP_WRITE(sc, CSR_GPP, GPP_GPC | sc->sc_gp_dir); | |
1433 | delay(10); | 1433 | delay(10); | |
1434 | TULIP_WRITE(sc, CSR_GPP, GPP_SMC9332DST_INIT); | 1434 | TULIP_WRITE(sc, CSR_GPP, GPP_SMC9332DST_INIT); | |
1435 | delay(200000); | 1435 | delay(200000); | |
1436 | cnt = 0; | 1436 | cnt = 0; | |
1437 | for (i = 1000; i > 0; i--) { | 1437 | for (i = 1000; i > 0; i--) { | |
1438 | reg = TULIP_READ(sc, CSR_GPP); | 1438 | reg = TULIP_READ(sc, CSR_GPP); | |
1439 | if ((~reg & (GPP_SMC9332DST_OK10 | | 1439 | if ((~reg & (GPP_SMC9332DST_OK10 | | |
1440 | GPP_SMC9332DST_OK100)) == 0) { | 1440 | GPP_SMC9332DST_OK100)) == 0) { | |
1441 | if (cnt++ > 100) { | 1441 | if (cnt++ > 100) { | |
1442 | break; | 1442 | break; | |
1443 | } | 1443 | } | |
1444 | } else if ((reg & GPP_SMC9332DST_OK10) == 0) { | 1444 | } else if ((reg & GPP_SMC9332DST_OK10) == 0) { | |
1445 | break; | 1445 | break; | |
1446 | } else { | 1446 | } else { | |
1447 | cnt = 0; | 1447 | cnt = 0; | |
1448 | } | 1448 | } | |
1449 | delay(1000); | 1449 | delay(1000); | |
1450 | } | 1450 | } | |
1451 | if (cnt > 100) { | 1451 | if (cnt > 100) { | |
1452 | ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_100_TX); | 1452 | ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_100_TX); | |
1453 | } else { | 1453 | } else { | |
1454 | ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_10_T); | 1454 | ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_10_T); | |
1455 | } | 1455 | } | |
1456 | } | 1456 | } | |
1457 | 1457 | |||
1458 | static void | 1458 | static void | |
1459 | tlp_pci_vpc_21140_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | 1459 | tlp_pci_vpc_21140_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | |
1460 | { | 1460 | { | |
1461 | struct tulip_softc *sc = &psc->sc_tulip; | 1461 | struct tulip_softc *sc = &psc->sc_tulip; | |
1462 | char *p1 = (char *) &sc->sc_srom[32]; | 1462 | char *p1 = (char *) &sc->sc_srom[32]; | |
1463 | char *p2 = &sc->sc_name[0]; | 1463 | char *p2 = &sc->sc_name[0]; | |
1464 | 1464 | |||
1465 | do { | 1465 | do { | |
1466 | if ((unsigned char) *p1 & 0x80) | 1466 | if ((unsigned char) *p1 & 0x80) | |
1467 | *p2++ = ' '; | 1467 | *p2++ = ' '; | |
1468 | else | 1468 | else | |
1469 | *p2++ = *p1; | 1469 | *p2++ = *p1; | |
1470 | } while (*p1++); | 1470 | } while (*p1++); | |
1471 | } | 1471 | } | |
1472 | 1472 | |||
1473 | static void tlp_pci_cobalt_21142_reset(struct tulip_softc *); | 1473 | static void tlp_pci_cobalt_21142_reset(struct tulip_softc *); | |
1474 | 1474 | |||
1475 | static void | 1475 | static void | |
1476 | tlp_pci_cobalt_21142_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | 1476 | tlp_pci_cobalt_21142_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | |
1477 | { | 1477 | { | |
1478 | struct tulip_softc *sc = &psc->sc_tulip; | 1478 | struct tulip_softc *sc = &psc->sc_tulip; | |
1479 | 1479 | |||
1480 | /* | 1480 | /* | |
1481 | * Cobalt Networks interfaces are just MII-on-SIO. | 1481 | * Cobalt Networks interfaces are just MII-on-SIO. | |
1482 | */ | 1482 | */ | |
1483 | sc->sc_reset = tlp_pci_cobalt_21142_reset; | 1483 | sc->sc_reset = tlp_pci_cobalt_21142_reset; | |
1484 | sc->sc_mediasw = &tlp_sio_mii_mediasw; | 1484 | sc->sc_mediasw = &tlp_sio_mii_mediasw; | |
1485 | 1485 | |||
1486 | /* | 1486 | /* | |
1487 | * The Cobalt systems tend to fall back to store-and-forward | 1487 | * The Cobalt systems tend to fall back to store-and-forward | |
1488 | * pretty quickly, so we select that from the beginning to | 1488 | * pretty quickly, so we select that from the beginning to | |
1489 | * avoid initial timeouts. | 1489 | * avoid initial timeouts. | |
1490 | */ | 1490 | */ | |
1491 | sc->sc_txthresh = TXTH_SF; | 1491 | sc->sc_txthresh = TXTH_SF; | |
1492 | } | 1492 | } | |
1493 | 1493 | |||
1494 | static void | 1494 | static void | |
1495 | tlp_pci_cobalt_21142_reset(struct tulip_softc *sc) | 1495 | tlp_pci_cobalt_21142_reset(struct tulip_softc *sc) | |
1496 | { | 1496 | { | |
1497 | 1497 | |||
1498 | /* | 1498 | /* | |
1499 | * Reset PHY. | 1499 | * Reset PHY. | |
1500 | */ | 1500 | */ | |
1501 | TULIP_WRITE(sc, CSR_SIAGEN, SIAGEN_CWE | (1 << 16)); | 1501 | TULIP_WRITE(sc, CSR_SIAGEN, SIAGEN_CWE | (1 << 16)); | |
1502 | delay(10); | 1502 | delay(10); | |
1503 | TULIP_WRITE(sc, CSR_SIAGEN, SIAGEN_CWE); | 1503 | TULIP_WRITE(sc, CSR_SIAGEN, SIAGEN_CWE); | |
1504 | delay(10); | 1504 | delay(10); | |
1505 | } | 1505 | } | |
1506 | 1506 | |||
1507 | static void | 1507 | static void | |
1508 | tlp_pci_algor_21142_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | 1508 | tlp_pci_algor_21142_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | |
1509 | { | 1509 | { | |
1510 | struct tulip_softc *sc = &psc->sc_tulip; | 1510 | struct tulip_softc *sc = &psc->sc_tulip; | |
1511 | 1511 | |||
1512 | /* | 1512 | /* | |
1513 | * Algorithmics boards just have MII-on-SIO. | 1513 | * Algorithmics boards just have MII-on-SIO. | |
1514 | * | 1514 | * | |
1515 | * XXX They also have AUI on the serial interface. | 1515 | * XXX They also have AUI on the serial interface. | |
1516 | * XXX Deal with this. | 1516 | * XXX Deal with this. | |
1517 | */ | 1517 | */ | |
1518 | sc->sc_mediasw = &tlp_sio_mii_mediasw; | 1518 | sc->sc_mediasw = &tlp_sio_mii_mediasw; | |
1519 | } | 1519 | } | |
1520 | 1520 | |||
1521 | /* | 1521 | /* | |
1522 | * Cogent EM1x0 (aka. Adaptec ANA-6910) media switch. | 1522 | * Cogent EM1x0 (aka. Adaptec ANA-6910) media switch. | |
1523 | */ | 1523 | */ | |
1524 | static void tlp_cogent_em1x0_tmsw_init(struct tulip_softc *); | 1524 | static void tlp_cogent_em1x0_tmsw_init(struct tulip_softc *); | |
1525 | 1525 | |||
1526 | static const struct tulip_mediasw tlp_cogent_em1x0_mediasw = { | 1526 | static const struct tulip_mediasw tlp_cogent_em1x0_mediasw = { | |
1527 | tlp_cogent_em1x0_tmsw_init, | 1527 | tlp_cogent_em1x0_tmsw_init, | |
1528 | tlp_21140_gpio_get, | 1528 | tlp_21140_gpio_get, | |
1529 | tlp_21140_gpio_set | 1529 | tlp_21140_gpio_set | |
1530 | }; | 1530 | }; | |
1531 | 1531 | |||
1532 | static void | 1532 | static void | |
1533 | tlp_pci_adaptec_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | 1533 | tlp_pci_adaptec_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | |
1534 | { | 1534 | { | |
1535 | struct tulip_softc *sc = &psc->sc_tulip; | 1535 | struct tulip_softc *sc = &psc->sc_tulip; | |
1536 | uint8_t *srom = sc->sc_srom, id0; | 1536 | uint8_t *srom = sc->sc_srom, id0; | |
1537 | uint16_t id1, id2; | 1537 | uint16_t id1, id2; | |
1538 | 1538 | |||
1539 | if (sc->sc_mediasw == NULL) { | 1539 | if (sc->sc_mediasw == NULL) { | |
1540 | id0 = srom[32]; | 1540 | id0 = srom[32]; | |
1541 | switch (id0) { | 1541 | switch (id0) { | |
1542 | case 0x12: | 1542 | case 0x12: | |
1543 | strcpy(psc->sc_tulip.sc_name, "Cogent EM100TX"); | 1543 | strcpy(psc->sc_tulip.sc_name, "Cogent EM100TX"); | |
1544 | sc->sc_mediasw = &tlp_cogent_em1x0_mediasw; | 1544 | sc->sc_mediasw = &tlp_cogent_em1x0_mediasw; | |
1545 | break; | 1545 | break; | |
1546 | 1546 | |||
1547 | case 0x13: | |||
1548 | strcpy(psc->sc_tulip.sc_name, "Cogent ???"); | |||
1549 | sc->sc_mediasw = &tlp_cogent_em1x0_mediasw; | |||
1550 | psc->sc_flags |= TULIP_PCI_SHAREDINTR | | |||
1551 | TULIP_PCI_SHAREDROM; | |||
1552 | break; | |||
1553 | ||||
1547 | case 0x15: | 1554 | case 0x15: | |
1548 | strcpy(psc->sc_tulip.sc_name, "Cogent EM100FX"); | 1555 | strcpy(psc->sc_tulip.sc_name, "Cogent EM100FX"); | |
1549 | sc->sc_mediasw = &tlp_cogent_em1x0_mediasw; | 1556 | sc->sc_mediasw = &tlp_cogent_em1x0_mediasw; | |
1550 | break; | 1557 | break; | |
1551 | 1558 | |||
1552 | #if 0 | 1559 | #if 0 | |
1553 | case XXX: | 1560 | case XXX: | |
1554 | strcpy(psc->sc_tulip.sc_name, "Cogent EM110TX"); | 1561 | strcpy(psc->sc_tulip.sc_name, "Cogent EM110TX"); | |
1555 | sc->sc_mediasw = &tlp_cogent_em1x0_mediasw; | 1562 | sc->sc_mediasw = &tlp_cogent_em1x0_mediasw; | |
1556 | break; | 1563 | break; | |
1557 | #endif | 1564 | #endif | |
1558 | 1565 | |||
1559 | default: | 1566 | default: | |
1560 | printf("%s: unknown Cogent board ID 0x%02x\n", | 1567 | printf("%s: unknown Cogent board ID 0x%02x\n", | |
1561 | device_xname(sc->sc_dev), id0); | 1568 | device_xname(sc->sc_dev), id0); | |
1562 | } | 1569 | } | |
1563 | return; | 1570 | return; | |
1564 | } | 1571 | } | |
1565 | 1572 | |||
1566 | id1 = TULIP_ROM_GETW(srom, 0); | 1573 | id1 = TULIP_ROM_GETW(srom, 0); | |
1567 | id2 = TULIP_ROM_GETW(srom, 2); | 1574 | id2 = TULIP_ROM_GETW(srom, 2); | |
1568 | if (id1 != 0x1109) { | 1575 | if (id1 != 0x1109) { | |
1569 | goto unknown; | 1576 | goto unknown; | |
1570 | } | 1577 | } | |
1571 | 1578 | |||
1572 | switch (id2) { | 1579 | switch (id2) { | |
1573 | case 0x1900: | 1580 | case 0x1900: | |
1574 | strcpy(psc->sc_tulip.sc_name, "Adaptec ANA-6911"); | 1581 | strcpy(psc->sc_tulip.sc_name, "Adaptec ANA-6911"); | |
1575 | break; | 1582 | break; | |
1576 | 1583 | |||
1577 | case 0x2400: | 1584 | case 0x2400: | |
1578 | strcpy(psc->sc_tulip.sc_name, "Adaptec ANA-6944A"); | 1585 | strcpy(psc->sc_tulip.sc_name, "Adaptec ANA-6944A"); | |
1579 | psc->sc_flags |= TULIP_PCI_SHAREDINTR|TULIP_PCI_SHAREDROM; | 1586 | psc->sc_flags |= TULIP_PCI_SHAREDINTR|TULIP_PCI_SHAREDROM; | |
1580 | break; | 1587 | break; | |
1581 | 1588 | |||
1582 | case 0x2b00: | 1589 | case 0x2b00: | |
1583 | strcpy(psc->sc_tulip.sc_name, "Adaptec ANA-6911A"); | 1590 | strcpy(psc->sc_tulip.sc_name, "Adaptec ANA-6911A"); | |
1584 | break; | 1591 | break; | |
1585 | 1592 | |||
1586 | case 0x3000: | 1593 | case 0x3000: | |
1587 | strcpy(psc->sc_tulip.sc_name, "Adaptec ANA-6922"); | 1594 | strcpy(psc->sc_tulip.sc_name, "Adaptec ANA-6922"); | |
1588 | psc->sc_flags |= TULIP_PCI_SHAREDINTR|TULIP_PCI_SHAREDROM; | 1595 | psc->sc_flags |= TULIP_PCI_SHAREDINTR|TULIP_PCI_SHAREDROM; | |
1589 | break; | 1596 | break; | |
1590 | 1597 | |||
1591 | default: | 1598 | default: | |
1592 | unknown: | 1599 | unknown: | |
1593 | printf("%s: unknown Adaptec/Cogent board ID 0x%04x/0x%04x\n", | 1600 | printf("%s: unknown Adaptec/Cogent board ID 0x%04x/0x%04x\n", | |
1594 | device_xname(sc->sc_dev), id1, id2); | 1601 | device_xname(sc->sc_dev), id1, id2); | |
1595 | } | 1602 | } | |
1596 | } | 1603 | } | |
1597 | 1604 | |||
1598 | static void | 1605 | static void | |
1599 | tlp_cogent_em1x0_tmsw_init(struct tulip_softc *sc) | 1606 | tlp_cogent_em1x0_tmsw_init(struct tulip_softc *sc) | |
1600 | { | 1607 | { | |
1601 | struct tulip_21x4x_media *tm; | 1608 | struct tulip_21x4x_media *tm; | |
1602 | const char *sep = ""; | 1609 | const char *sep = ""; | |
1603 | 1610 | |||
1604 | sc->sc_gp_dir = GPP_COGENT_EM1x0_PINS; | 1611 | sc->sc_gp_dir = GPP_COGENT_EM1x0_PINS; | |
1605 | sc->sc_opmode = OPMODE_MBO | OPMODE_PS; | 1612 | sc->sc_opmode = OPMODE_MBO | OPMODE_PS; | |
1606 | TULIP_WRITE(sc, CSR_OPMODE, sc->sc_opmode); | 1613 | TULIP_WRITE(sc, CSR_OPMODE, sc->sc_opmode); | |
1607 | 1614 | |||
1608 | ifmedia_init(&sc->sc_mii.mii_media, 0, tlp_mediachange, | 1615 | ifmedia_init(&sc->sc_mii.mii_media, 0, tlp_mediachange, | |
1609 | tlp_mediastatus); | 1616 | tlp_mediastatus); | |
1610 | aprint_normal_dev(sc->sc_dev, ""); | 1617 | aprint_normal_dev(sc->sc_dev, ""); | |
1611 | 1618 | |||
1612 | #define ADD(m, c) \ | 1619 | #define ADD(m, c) \ | |
1613 | tm = malloc(sizeof(*tm), M_DEVBUF, M_WAITOK|M_ZERO); \ | 1620 | tm = malloc(sizeof(*tm), M_DEVBUF, M_WAITOK|M_ZERO); \ | |
1614 | tm->tm_opmode = (c); \ | 1621 | tm->tm_opmode = (c); \ | |
1615 | tm->tm_gpdata = GPP_COGENT_EM1x0_INIT; \ | 1622 | tm->tm_gpdata = GPP_COGENT_EM1x0_INIT; \ | |
1616 | ifmedia_add(&sc->sc_mii.mii_media, (m), 0, tm) | 1623 | ifmedia_add(&sc->sc_mii.mii_media, (m), 0, tm) | |
1617 | #define PRINT(str) aprint_normal("%s%s", sep, str); sep = ", " | 1624 | #define PRINT(str) aprint_normal("%s%s", sep, str); sep = ", " | |
1618 | 1625 | |||
1619 | if (sc->sc_srom[32] == 0x15) { | 1626 | if (sc->sc_srom[32] == 0x15) { | |
1620 | ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, 0, 0), | 1627 | ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, 0, 0), | |
1621 | OPMODE_PS | OPMODE_PCS); | 1628 | OPMODE_PS | OPMODE_PCS); | |
1622 | PRINT("100baseFX"); | 1629 | PRINT("100baseFX"); | |
1623 | 1630 | |||
1624 | ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, IFM_FDX, 0), | 1631 | ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, IFM_FDX, 0), | |
1625 | OPMODE_PS | OPMODE_PCS | OPMODE_FD); | 1632 | OPMODE_PS | OPMODE_PCS | OPMODE_FD); | |
1626 | PRINT("100baseFX-FDX"); | 1633 | PRINT("100baseFX-FDX"); | |
1627 | aprint_normal("\n"); | 1634 | aprint_normal("\n"); | |
1628 | 1635 | |||
1629 | ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_100_FX); | 1636 | ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_100_FX); | |
1630 | } else { | 1637 | } else { | |
1631 | ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, 0), | 1638 | ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, 0), | |
1632 | OPMODE_PS | OPMODE_PCS | OPMODE_SCR); | 1639 | OPMODE_PS | OPMODE_PCS | OPMODE_SCR); | |
1633 | PRINT("100baseTX"); | 1640 | PRINT("100baseTX"); | |
1634 | 1641 | |||
1635 | ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, IFM_FDX, 0), | 1642 | ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, IFM_FDX, 0), | |
1636 | OPMODE_PS | OPMODE_PCS | OPMODE_SCR | OPMODE_FD); | 1643 | OPMODE_PS | OPMODE_PCS | OPMODE_SCR | OPMODE_FD); | |
1637 | PRINT("100baseTX-FDX"); | 1644 | PRINT("100baseTX-FDX"); | |
1638 | aprint_normal("\n"); | 1645 | aprint_normal("\n"); | |
1639 | 1646 | |||
1640 | ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_100_TX); | 1647 | ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_100_TX); | |
1641 | } | 1648 | } | |
1642 | 1649 | |||
1643 | #undef ADD | 1650 | #undef ADD | |
1644 | #undef PRINT | 1651 | #undef PRINT | |
1645 | } | 1652 | } | |
1646 | 1653 | |||
1647 | static void tlp_pci_netwinder_21142_reset(struct tulip_softc *); | 1654 | static void tlp_pci_netwinder_21142_reset(struct tulip_softc *); | |
1648 | 1655 | |||
1649 | static void | 1656 | static void | |
1650 | tlp_pci_netwinder_21142_quirks(struct tulip_pci_softc *psc, | 1657 | tlp_pci_netwinder_21142_quirks(struct tulip_pci_softc *psc, | |
1651 | const uint8_t *enaddr) | 1658 | const uint8_t *enaddr) | |
1652 | { | 1659 | { | |
1653 | struct tulip_softc *sc = &psc->sc_tulip; | 1660 | struct tulip_softc *sc = &psc->sc_tulip; | |
1654 | 1661 | |||
1655 | /* | 1662 | /* | |
1656 | * Netwinders just use MII-on-SIO. | 1663 | * Netwinders just use MII-on-SIO. | |
1657 | */ | 1664 | */ | |
1658 | sc->sc_mediasw = &tlp_sio_mii_mediasw; | 1665 | sc->sc_mediasw = &tlp_sio_mii_mediasw; | |
1659 | sc->sc_reset = tlp_pci_netwinder_21142_reset; | 1666 | sc->sc_reset = tlp_pci_netwinder_21142_reset; | |
1660 | } | 1667 | } | |
1661 | 1668 | |||
1662 | void | 1669 | void | |
1663 | tlp_pci_netwinder_21142_reset(struct tulip_softc *sc) | 1670 | tlp_pci_netwinder_21142_reset(struct tulip_softc *sc) | |
1664 | { | 1671 | { | |
1665 | 1672 | |||
1666 | /* | 1673 | /* | |
1667 | * Reset the PHY. | 1674 | * Reset the PHY. | |
1668 | */ | 1675 | */ | |
1669 | TULIP_WRITE(sc, CSR_SIAGEN, 0x0821 << 16); | 1676 | TULIP_WRITE(sc, CSR_SIAGEN, 0x0821 << 16); | |
1670 | delay(10); | 1677 | delay(10); | |
1671 | TULIP_WRITE(sc, CSR_SIAGEN, 0x0000 << 16); | 1678 | TULIP_WRITE(sc, CSR_SIAGEN, 0x0000 << 16); | |
1672 | delay(10); | 1679 | delay(10); | |
1673 | TULIP_WRITE(sc, CSR_SIAGEN, 0x0001 << 16); | 1680 | TULIP_WRITE(sc, CSR_SIAGEN, 0x0001 << 16); | |
1674 | delay(10); | 1681 | delay(10); | |
1675 | } | 1682 | } | |
1676 | 1683 | |||
1677 | static void tlp_pci_phobos_21142_reset(struct tulip_softc *); | 1684 | static void tlp_pci_phobos_21142_reset(struct tulip_softc *); | |
1678 | 1685 | |||
1679 | static void | 1686 | static void | |
1680 | tlp_pci_phobos_21142_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | 1687 | tlp_pci_phobos_21142_quirks(struct tulip_pci_softc *psc, const uint8_t *enaddr) | |
1681 | { | 1688 | { | |
1682 | struct tulip_softc *sc = &psc->sc_tulip; | 1689 | struct tulip_softc *sc = &psc->sc_tulip; | |
1683 | 1690 | |||
1684 | /* | 1691 | /* | |
1685 | * Phobos boards just use MII-on-SIO. | 1692 | * Phobos boards just use MII-on-SIO. | |
1686 | */ | 1693 | */ | |
1687 | sc->sc_mediasw = &tlp_sio_mii_mediasw; | 1694 | sc->sc_mediasw = &tlp_sio_mii_mediasw; | |
1688 | sc->sc_reset = tlp_pci_phobos_21142_reset; | 1695 | sc->sc_reset = tlp_pci_phobos_21142_reset; | |
1689 | 1696 | |||
1690 | /* | 1697 | /* | |
1691 | * These boards appear solely on sgimips machines behind a special | 1698 | * These boards appear solely on sgimips machines behind a special | |
1692 | * GIO<->PCI ASIC and require the DBO and BLE bits to be set in CSR0. | 1699 | * GIO<->PCI ASIC and require the DBO and BLE bits to be set in CSR0. | |
1693 | */ | 1700 | */ | |
1694 | sc->sc_flags |= (TULIPF_BLE | TULIPF_DBO); | 1701 | sc->sc_flags |= (TULIPF_BLE | TULIPF_DBO); | |
1695 | } | 1702 | } | |
1696 | 1703 | |||
1697 | static void | 1704 | static void | |
1698 | tlp_pci_phobos_21142_reset(struct tulip_softc *sc) | 1705 | tlp_pci_phobos_21142_reset(struct tulip_softc *sc) | |
1699 | { | 1706 | { | |
1700 | /* | 1707 | /* | |
1701 | * Reset PHY. | 1708 | * Reset PHY. | |
1702 | */ | 1709 | */ | |
1703 | TULIP_WRITE(sc, CSR_SIAGEN, (0x880f << 16)); | 1710 | TULIP_WRITE(sc, CSR_SIAGEN, (0x880f << 16)); | |
1704 | delay(10); | 1711 | delay(10); | |
1705 | TULIP_WRITE(sc, CSR_SIAGEN, (0x800f << 16)); | 1712 | TULIP_WRITE(sc, CSR_SIAGEN, (0x800f << 16)); | |
1706 | delay(10); | 1713 | delay(10); | |
1707 | } | 1714 | } |