Add some 'int' into function definitions where the K&R one didn't specify a type.diff -r1.22 -r1.23 src/sys/arch/alpha/a12/if_xb.c
(dsl)
--- src/sys/arch/alpha/a12/Attic/if_xb.c 2009/03/14 21:04:01 1.22
+++ src/sys/arch/alpha/a12/Attic/if_xb.c 2009/03/17 18:19:15 1.23
@@ -1,752 +1,752 @@ | @@ -1,752 +1,752 @@ | |||
1 | /* $NetBSD: if_xb.c,v 1.22 2009/03/14 21:04:01 dsl Exp $ */ | 1 | /* $NetBSD: if_xb.c,v 1.23 2009/03/17 18:19:15 dsl Exp $ */ | |
2 | 2 | |||
3 | /* [Notice revision 2.2] | 3 | /* [Notice revision 2.2] | |
4 | * Copyright (c) 1997, 1998 Avalon Computer Systems, Inc. | 4 | * Copyright (c) 1997, 1998 Avalon Computer Systems, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Author: Ross Harvey | 7 | * Author: Ross Harvey | |
8 | * | 8 | * | |
9 | * Redistribution and use in source and binary forms, with or without | 9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | 10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | 11 | * are met: | |
12 | * 1. Redistributions of source code must retain the above copyright and | 12 | * 1. Redistributions of source code must retain the above copyright and | |
13 | * author notice, this list of conditions, and the following disclaimer. | 13 | * author notice, this list of conditions, and the following disclaimer. | |
14 | * 2. Redistributions in binary form must reproduce the above copyright | 14 | * 2. Redistributions in binary form must reproduce the above copyright | |
15 | * notice, this list of conditions and the following disclaimer in the | 15 | * notice, this list of conditions and the following disclaimer in the | |
16 | * documentation and/or other materials provided with the distribution. | 16 | * documentation and/or other materials provided with the distribution. | |
17 | * 3. Neither the name of Avalon Computer Systems, Inc. nor the names of | 17 | * 3. Neither the name of Avalon Computer Systems, Inc. nor the names of | |
18 | * its contributors may be used to endorse or promote products derived | 18 | * its contributors may be used to endorse or promote products derived | |
19 | * from this software without specific prior written permission. | 19 | * from this software without specific prior written permission. | |
20 | * 4. This copyright will be assigned to The NetBSD Foundation on | 20 | * 4. This copyright will be assigned to The NetBSD Foundation on | |
21 | * 1/1/2000 unless these terms (including possibly the assignment | 21 | * 1/1/2000 unless these terms (including possibly the assignment | |
22 | * date) are updated in writing by Avalon prior to the latest specified | 22 | * date) are updated in writing by Avalon prior to the latest specified | |
23 | * assignment date. | 23 | * assignment date. | |
24 | * | 24 | * | |
25 | * THIS SOFTWARE IS PROVIDED BY AVALON COMPUTER SYSTEMS, INC. AND CONTRIBUTORS | 25 | * THIS SOFTWARE IS PROVIDED BY AVALON COMPUTER SYSTEMS, INC. AND CONTRIBUTORS | |
26 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 26 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
27 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 27 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
28 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AVALON OR THE CONTRIBUTORS | 28 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AVALON OR THE CONTRIBUTORS | |
29 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 29 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
30 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 30 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
32 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 32 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
33 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 33 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
34 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 34 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
35 | * POSSIBILITY OF SUCH DAMAGE. | 35 | * POSSIBILITY OF SUCH DAMAGE. | |
36 | */ | 36 | */ | |
37 | 37 | |||
38 | /* | 38 | /* | |
39 | * Notes. | 39 | * Notes. | |
40 | * | 40 | * | |
41 | * Since the NetBSD build rules force the use of function prototypes, even on | 41 | * Since the NetBSD build rules force the use of function prototypes, even on | |
42 | * functions that are defined before they are called, I've taken advantage of | 42 | * functions that are defined before they are called, I've taken advantage of | |
43 | * the opportunity and organized this module in top down fashion, with | 43 | * the opportunity and organized this module in top down fashion, with | |
44 | * functions generally calling down the page rather than up. It's different. | 44 | * functions generally calling down the page rather than up. It's different. | |
45 | * I think I'm getting to like it this way. | 45 | * I think I'm getting to like it this way. | |
46 | * | 46 | * | |
47 | * The crossbar interface is not exactly a peripheral device, and it cannot | 47 | * The crossbar interface is not exactly a peripheral device, and it cannot | |
48 | * appear on anything other than an alpha-based Avalon A12. The crossbar | 48 | * appear on anything other than an alpha-based Avalon A12. The crossbar | |
49 | * controller is built into the core logic. | 49 | * controller is built into the core logic. | |
50 | * | 50 | * | |
51 | * If this version of the driver supports MPS transport, it may have some | 51 | * If this version of the driver supports MPS transport, it may have some | |
52 | * large static data declarations. Don't worry about it, as Avalon a12 | 52 | * large static data declarations. Don't worry about it, as Avalon a12 | |
53 | * support should not appear in a GENERIC or INSTALL kernel. | 53 | * support should not appear in a GENERIC or INSTALL kernel. | |
54 | * | 54 | * | |
55 | * (Every A12 ever shipped had 512 MB per CPU except one site, which had 256 | 55 | * (Every A12 ever shipped had 512 MB per CPU except one site, which had 256 | |
56 | * MB. Partly has a result of this, it is unlikely that a kernel configured | 56 | * MB. Partly has a result of this, it is unlikely that a kernel configured | |
57 | * for an A12 would be exactly the thing to use on most workstations, so we | 57 | * for an A12 would be exactly the thing to use on most workstations, so we | |
58 | * don't really need to worry that we might be configured in a generic or | 58 | * don't really need to worry that we might be configured in a generic or | |
59 | * site-wide kernel image.) | 59 | * site-wide kernel image.) | |
60 | * | 60 | * | |
61 | * This preliminary crossbar driver supports IP transport using PIO. Although | 61 | * This preliminary crossbar driver supports IP transport using PIO. Although | |
62 | * it would be nice to have a DMA driver, do note that the crossbar register | 62 | * it would be nice to have a DMA driver, do note that the crossbar register | |
63 | * port is 128 bits wide, so we have 128-bit PIO. (The 21164 write buffer | 63 | * port is 128 bits wide, so we have 128-bit PIO. (The 21164 write buffer | |
64 | * will combine two 64-bit stores before they get off-chip.) Also, the rtmon | 64 | * will combine two 64-bit stores before they get off-chip.) Also, the rtmon | |
65 | * driver wasn't DMA either, so at least the NetBSD driver is as good as any | 65 | * driver wasn't DMA either, so at least the NetBSD driver is as good as any | |
66 | * other that exists now. | 66 | * other that exists now. | |
67 | * | 67 | * | |
68 | * We'll do DMA and specialized transport ops later. Given the high speed of | 68 | * We'll do DMA and specialized transport ops later. Given the high speed of | |
69 | * the PIO mode, no current applications require DMA bandwidth, but everyone | 69 | * the PIO mode, no current applications require DMA bandwidth, but everyone | |
70 | * benefits from low latency. The PIO mode is actually lower in latency | 70 | * benefits from low latency. The PIO mode is actually lower in latency | |
71 | * anyway. | 71 | * anyway. | |
72 | */ | 72 | */ | |
73 | 73 | |||
74 | #include "opt_avalon_a12.h" /* Config options headers */ | 74 | #include "opt_avalon_a12.h" /* Config options headers */ | |
75 | #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ | 75 | #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ | |
76 | 76 | |||
77 | __KERNEL_RCSID(0, "$NetBSD: if_xb.c,v 1.22 2009/03/14 21:04:01 dsl Exp $"); | 77 | __KERNEL_RCSID(0, "$NetBSD: if_xb.c,v 1.23 2009/03/17 18:19:15 dsl Exp $"); | |
78 | 78 | |||
79 | #include <sys/param.h> | 79 | #include <sys/param.h> | |
80 | #include <sys/systm.h> | 80 | #include <sys/systm.h> | |
81 | #include <sys/kernel.h> | 81 | #include <sys/kernel.h> | |
82 | #include <sys/malloc.h> | 82 | #include <sys/malloc.h> | |
83 | #include <sys/device.h> | 83 | #include <sys/device.h> | |
84 | #include <sys/socket.h> | 84 | #include <sys/socket.h> | |
85 | #include <sys/mbuf.h> | 85 | #include <sys/mbuf.h> | |
86 | #include <sys/sockio.h> | 86 | #include <sys/sockio.h> | |
87 | 87 | |||
88 | #include <uvm/uvm_extern.h> | 88 | #include <uvm/uvm_extern.h> | |
89 | 89 | |||
90 | #include <net/if.h> | 90 | #include <net/if.h> | |
91 | #include <net/if_dl.h> | 91 | #include <net/if_dl.h> | |
92 | #include <net/if_types.h> | 92 | #include <net/if_types.h> | |
93 | #include <net/route.h> | 93 | #include <net/route.h> | |
94 | #include <netinet/in.h> | 94 | #include <netinet/in.h> | |
95 | #include <netinet/in_var.h> | 95 | #include <netinet/in_var.h> | |
96 | 96 | |||
97 | #include <machine/autoconf.h> | 97 | #include <machine/autoconf.h> | |
98 | #include <machine/rpb.h> | 98 | #include <machine/rpb.h> | |
99 | 99 | |||
100 | #include <dev/isa/isareg.h> | 100 | #include <dev/isa/isareg.h> | |
101 | #include <dev/isa/isavar.h> | 101 | #include <dev/isa/isavar.h> | |
102 | 102 | |||
103 | #include <dev/pci/pcireg.h> | 103 | #include <dev/pci/pcireg.h> | |
104 | #include <dev/pci/pcivar.h> | 104 | #include <dev/pci/pcivar.h> | |
105 | 105 | |||
106 | #include <alpha/pci/a12creg.h> | 106 | #include <alpha/pci/a12creg.h> | |
107 | #include <alpha/pci/a12cvar.h> | 107 | #include <alpha/pci/a12cvar.h> | |
108 | #include <alpha/pci/pci_a12.h> | 108 | #include <alpha/pci/pci_a12.h> | |
109 | 109 | |||
110 | #if 1 | 110 | #if 1 | |
111 | #define XB_DEBUG xb_debug | 111 | #define XB_DEBUG xb_debug | |
112 | #else | 112 | #else | |
113 | #define XB_DEBUG 0 | 113 | #define XB_DEBUG 0 | |
114 | #endif | 114 | #endif | |
115 | 115 | |||
116 | #undef Static | 116 | #undef Static | |
117 | #if 1 | 117 | #if 1 | |
118 | #define Static | 118 | #define Static | |
119 | #else | 119 | #else | |
120 | #define Static static | 120 | #define Static static | |
121 | #endif | 121 | #endif | |
122 | 122 | |||
123 | #define IF_XB() /* Generate ctags(1) key */ | 123 | #define IF_XB() /* Generate ctags(1) key */ | |
124 | 124 | |||
125 | #define XBAR_MTU (9*1024) /* Quite an arbitrary number */ | 125 | #define XBAR_MTU (9*1024) /* Quite an arbitrary number */ | |
126 | #define XBAR_MAXFRAMEHDR 48 /* Used to compute if_mtu */ | 126 | #define XBAR_MAXFRAMEHDR 48 /* Used to compute if_mtu */ | |
127 | 127 | |||
128 | #define XB_DEFAULT_MTU() (XBAR_MTU - XBAR_MAXFRAMEHDR) | 128 | #define XB_DEFAULT_MTU() (XBAR_MTU - XBAR_MAXFRAMEHDR) | |
129 | 129 | |||
130 | #define FIFO_WORDCOUNT 60 | 130 | #define FIFO_WORDCOUNT 60 | |
131 | 131 | |||
132 | static int xb_put_blk(struct mbuf *); | 132 | static int xb_put_blk(struct mbuf *); | |
133 | static int xb_put(struct mbuf *); | 133 | static int xb_put(struct mbuf *); | |
134 | static long xb_fifo_empty(void); | 134 | static long xb_fifo_empty(void); | |
135 | 135 | |||
136 | int xbmatch(struct device *, struct cfdata *, void *); | 136 | int xbmatch(struct device *, struct cfdata *, void *); | |
137 | void xbattach(struct device *, struct device *, void *); | 137 | void xbattach(struct device *, struct device *, void *); | |
138 | 138 | |||
139 | struct xb_softc { | 139 | struct xb_softc { | |
140 | struct device d; | 140 | struct device d; | |
141 | } xb_softc; | 141 | } xb_softc; | |
142 | 142 | |||
143 | CFATTACH_DECL(xb, sizeof(struct xb_softc), | 143 | CFATTACH_DECL(xb, sizeof(struct xb_softc), | |
144 | xbmatch, xbattach, NULL, NULL); | 144 | xbmatch, xbattach, NULL, NULL); | |
145 | 145 | |||
146 | extern struct cfdriver xb_cd; | 146 | extern struct cfdriver xb_cd; | |
147 | 147 | |||
148 | long *xb_incoming; | 148 | long *xb_incoming; | |
149 | int xb_incoming_max = XBAR_MTU; | 149 | int xb_incoming_max = XBAR_MTU; | |
150 | 150 | |||
151 | typedef struct ccode_struct { | 151 | typedef struct ccode_struct { | |
152 | int64_t lo64, /* magic channel address s-word, high part*/ | 152 | int64_t lo64, /* magic channel address s-word, high part*/ | |
153 | hi64; /* magic channel address s-word, low part */ | 153 | hi64; /* magic channel address s-word, low part */ | |
154 | } ccode_type; | 154 | } ccode_type; | |
155 | /* | 155 | /* | |
156 | * Switch channel codes. Prepending one of these words will get you through | 156 | * Switch channel codes. Prepending one of these words will get you through | |
157 | * the switch, which will eat the word, open the addressed channel, and | 157 | * the switch, which will eat the word, open the addressed channel, and | |
158 | * forward the rest of the switch frame. Obviously, this helps if the second | 158 | * forward the rest of the switch frame. Obviously, this helps if the second | |
159 | * switch word in the frame is the address word for a cascaded switch. (This | 159 | * switch word in the frame is the address word for a cascaded switch. (This | |
160 | * can be repeated for an arbitrary depth of MSN.) The words aren't quite as | 160 | * can be repeated for an arbitrary depth of MSN.) The words aren't quite as | |
161 | * weird as they look: the switch is really lots of narrow switches in an | 161 | * weird as they look: the switch is really lots of narrow switches in an | |
162 | * array, and they don't switch an even number of hex digits. Also, there is | 162 | * array, and they don't switch an even number of hex digits. Also, there is | |
163 | * a parity bit on most of the subunits. | 163 | * a parity bit on most of the subunits. | |
164 | */ | 164 | */ | |
165 | ccode_type channel[]={ | 165 | ccode_type channel[]={ | |
166 | { 0x0000000000000000, 0x0000000000000000 }, | 166 | { 0x0000000000000000, 0x0000000000000000 }, | |
167 | { 0x8882108421084210, 0x1104210842108421 }, | 167 | { 0x8882108421084210, 0x1104210842108421 }, | |
168 | { 0x4441084210842108, 0x2208421084210842 }, | 168 | { 0x4441084210842108, 0x2208421084210842 }, | |
169 | { 0xccc318c6318c6318, 0x330c6318c6318c63 }, | 169 | { 0xccc318c6318c6318, 0x330c6318c6318c63 }, | |
170 | { 0x2220842108421084, 0x4410842108421084 }, | 170 | { 0x2220842108421084, 0x4410842108421084 }, | |
171 | { 0xaaa294a5294a5294, 0x5514a5294a5294a5 }, | 171 | { 0xaaa294a5294a5294, 0x5514a5294a5294a5 }, | |
172 | { 0x66618c6318c6318c, 0x6618c6318c6318c6 }, | 172 | { 0x66618c6318c6318c, 0x6618c6318c6318c6 }, | |
173 | { 0xeee39ce739ce739c, 0x771ce739ce739ce7 }, | 173 | { 0xeee39ce739ce739c, 0x771ce739ce739ce7 }, | |
174 | { 0x1110421084210842, 0x8821084210842108 }, | 174 | { 0x1110421084210842, 0x8821084210842108 }, | |
175 | { 0x99925294a5294a52, 0x9925294a5294a529 }, | 175 | { 0x99925294a5294a52, 0x9925294a5294a529 }, | |
176 | { 0x55514a5294a5294a, 0xaa294a5294a5294a }, | 176 | { 0x55514a5294a5294a, 0xaa294a5294a5294a }, | |
177 | { 0xddd35ad6b5ad6b5a, 0xbb2d6b5ad6b5ad6b }, | 177 | { 0xddd35ad6b5ad6b5a, 0xbb2d6b5ad6b5ad6b }, | |
178 | { 0x3330c6318c6318c6, 0xcc318c6318c6318c }, | 178 | { 0x3330c6318c6318c6, 0xcc318c6318c6318c }, | |
179 | { 0xbbb2d6b5ad6b5ad6, 0xdd35ad6b5ad6b5ad } | 179 | { 0xbbb2d6b5ad6b5ad6, 0xdd35ad6b5ad6b5ad } | |
180 | }; | 180 | }; | |
181 | 181 | |||
182 | Static enum xb_intr_rcv_state_t { | 182 | Static enum xb_intr_rcv_state_t { | |
183 | XBIR_PKTHDR = 0, XBIR_TRANS | 183 | XBIR_PKTHDR = 0, XBIR_TRANS | |
184 | } xb_intr_rcv_state; | 184 | } xb_intr_rcv_state; | |
185 | 185 | |||
186 | struct xb_config { int am_i_used; } xb_configuration; | 186 | struct xb_config { int am_i_used; } xb_configuration; | |
187 | 187 | |||
188 | Static struct ifnet xbi; | 188 | Static struct ifnet xbi; | |
189 | 189 | |||
190 | Static int frame_len; | 190 | Static int frame_len; | |
191 | static int xb_debug; | 191 | static int xb_debug; | |
192 | 192 | |||
193 | Static void xb_start(struct ifnet *); | 193 | Static void xb_start(struct ifnet *); | |
194 | Static void xb_mcrp_write(long *, int, int); | 194 | Static void xb_mcrp_write(long *, int, int); | |
195 | static inline void xb_onefree(void); | 195 | static inline void xb_onefree(void); | |
196 | static long set_interrupt_on_fifo_empty(void); | 196 | static long set_interrupt_on_fifo_empty(void); | |
197 | static void xb_init(struct ifnet *); | 197 | static void xb_init(struct ifnet *); | |
198 | static int xb_intr(void *); | 198 | static int xb_intr(void *); | |
199 | static void xb_intr_rcv(void); | 199 | static void xb_intr_rcv(void); | |
200 | Static void quickload(volatile long *, long *); | 200 | Static void quickload(volatile long *, long *); | |
201 | static void xb_init_config(struct xb_config *, int); | 201 | static void xb_init_config(struct xb_config *, int); | |
202 | static int xb_output(struct ifnet *, struct mbuf *, | 202 | static int xb_output(struct ifnet *, struct mbuf *, | |
203 | const struct sockaddr *, struct rtentry *); | 203 | const struct sockaddr *, struct rtentry *); | |
204 | static int xb_ioctl(struct ifnet *, u_long, void *); | 204 | static int xb_ioctl(struct ifnet *, u_long, void *); | |
205 | static void xb_stop(void); | 205 | static void xb_stop(void); | |
206 | static void a12_xbar_setup(void); | 206 | static void a12_xbar_setup(void); | |
207 | 207 | |||
208 | /* There Can Be Only One */ | 208 | /* There Can Be Only One */ | |
209 | 209 | |||
210 | int xbfound; | 210 | int xbfound; | |
211 | 211 | |||
212 | int | 212 | int | |
213 | xbmatch(struct device *parent, struct cfdata *match, void *aux) | 213 | xbmatch(struct device *parent, struct cfdata *match, void *aux) | |
214 | { | 214 | { | |
215 | 215 | |||
216 | return cputype == ST_AVALON_A12 | 216 | return cputype == ST_AVALON_A12 | |
217 | && !xbfound; | 217 | && !xbfound; | |
218 | } | 218 | } | |
219 | 219 | |||
220 | void | 220 | void | |
221 | xbattach(struct device *parent, struct device *self, void *aux) | 221 | xbattach(struct device *parent, struct device *self, void *aux) | |
222 | { | 222 | { | |
223 | struct xb_config *ccp; | 223 | struct xb_config *ccp; | |
224 | 224 | |||
225 | strcpy(xbi.if_xname, self->dv_xname); | 225 | strcpy(xbi.if_xname, self->dv_xname); | |
226 | xbfound = 1; | 226 | xbfound = 1; | |
227 | ccp = &xb_configuration; | 227 | ccp = &xb_configuration; | |
228 | xb_init_config(ccp, 1); | 228 | xb_init_config(ccp, 1); | |
229 | printf(": driver %s mtu %lu\n", "$Revision: 1.22 $", xbi.if_mtu); | 229 | printf(": driver %s mtu %lu\n", "$Revision: 1.23 $", xbi.if_mtu); | |
230 | } | 230 | } | |
231 | 231 | |||
232 | static void | 232 | static void | |
233 | xb_init_config(struct xb_config *ccp, int mallocsafe) | 233 | xb_init_config(struct xb_config *ccp, int mallocsafe) | |
234 | { | 234 | { | |
235 | /* | 235 | /* | |
236 | * The driver actually only needs about 64 bytes of buffer but with a | 236 | * The driver actually only needs about 64 bytes of buffer but with a | |
237 | * nice contiguous frame we can call m_devget() | 237 | * nice contiguous frame we can call m_devget() | |
238 | */ | 238 | */ | |
239 | if (mallocsafe && xb_incoming == NULL) { | 239 | if (mallocsafe && xb_incoming == NULL) { | |
240 | xb_incoming = malloc(xb_incoming_max, M_DEVBUF, M_NOWAIT); | 240 | xb_incoming = malloc(xb_incoming_max, M_DEVBUF, M_NOWAIT); | |
241 | if (xb_incoming == NULL) | 241 | if (xb_incoming == NULL) | |
242 | DIE(); | 242 | DIE(); | |
243 | } | 243 | } | |
244 | a12_xbar_setup(); | 244 | a12_xbar_setup(); | |
245 | a12_intr_register_xb(xb_intr); | 245 | a12_intr_register_xb(xb_intr); | |
246 | } | 246 | } | |
247 | 247 | |||
248 | /* | 248 | /* | |
249 | * From The A12 Theory of Operation. Used with permission. | 249 | * From The A12 Theory of Operation. Used with permission. | |
250 | * --- --- ------ -- --------- | 250 | * --- --- ------ -- --------- | |
251 | * | 251 | * | |
252 | * Message Channel Status Register | 252 | * Message Channel Status Register | |
253 | * | 253 | * | |
254 | * 31 0 | 254 | * 31 0 | |
255 | * | | | 255 | * | | | |
256 | * 10987654 32109876 54321098 76543210 | 256 | * 10987654 32109876 54321098 76543210 | |
257 | * | 257 | * | |
258 | * ........ ........ 0oiefaAr TR...... MCSR | 258 | * ........ ........ 0oiefaAr TR...... MCSR | |
259 | * | 259 | * | |
260 | * Field Type Name Function | 260 | * Field Type Name Function | |
261 | * | 261 | * | |
262 | * R R,W1C RBC Receive Block Complete | 262 | * R R,W1C RBC Receive Block Complete | |
263 | * T R,W1C TBC Transmit Block Complete | 263 | * T R,W1C TBC Transmit Block Complete | |
264 | * r R IMP Incoming message pending | 264 | * r R IMP Incoming message pending | |
265 | * A R IMFAE Incoming message fifo almost empty | 265 | * A R IMFAE Incoming message fifo almost empty | |
266 | * a R OMFAF Outgoing message fifo almost full | 266 | * a R OMFAF Outgoing message fifo almost full | |
267 | * f R OMFF Outgoing message fifo full | 267 | * f R OMFF Outgoing message fifo full | |
268 | * e R OMFE Outgoing message fifo empty | 268 | * e R OMFE Outgoing message fifo empty | |
269 | * i R DMAin Incoming DMA channel armed | 269 | * i R DMAin Incoming DMA channel armed | |
270 | * o R DMAout Outgoing DMA channel armed | 270 | * o R DMAout Outgoing DMA channel armed | |
271 | * | 271 | * | |
272 | * Interrupts Generated from MCSR | 272 | * Interrupts Generated from MCSR | |
273 | * | 273 | * | |
274 | * IMChInt <= (RBC or IMP) and not DMAin | 274 | * IMChInt <= (RBC or IMP) and not DMAin | |
275 | * OMChInt <= ((TBC and not OMFAF) or (OMFE and OMR.E(6)) | 275 | * OMChInt <= ((TBC and not OMFAF) or (OMFE and OMR.E(6)) | |
276 | * ) and not DMAout | 276 | * ) and not DMAout | |
277 | * | 277 | * | |
278 | */ | 278 | */ | |
279 | static int | 279 | static int | |
280 | xb_intr(void *p) | 280 | xb_intr(void *p) | |
281 | { | 281 | { | |
282 | int n; | 282 | int n; | |
283 | long mcsrval; | 283 | long mcsrval; | |
284 | /* | 284 | /* | |
285 | * The actual conditions under which this interrupt is generated are | 285 | * The actual conditions under which this interrupt is generated are | |
286 | * a bit complicated, and no status flag is available that reads out | 286 | * a bit complicated, and no status flag is available that reads out | |
287 | * the final values of the interrupt inputs. But, it doesn't really | 287 | * the final values of the interrupt inputs. But, it doesn't really | |
288 | * matter. Simply check for receive data and transmitter IFF_OACTIVE. | 288 | * matter. Simply check for receive data and transmitter IFF_OACTIVE. | |
289 | */ | 289 | */ | |
290 | while ((mcsrval = REGVAL(A12_MCSR)) & A12_MCSR_IMP) | 290 | while ((mcsrval = REGVAL(A12_MCSR)) & A12_MCSR_IMP) | |
291 | for(n = mcsrval & A12_MCSR_IMFAE ? 1 : 5; n; --n) | 291 | for(n = mcsrval & A12_MCSR_IMFAE ? 1 : 5; n; --n) | |
292 | xb_intr_rcv(); | 292 | xb_intr_rcv(); | |
293 | 293 | |||
294 | if (xbi.if_flags & IFF_OACTIVE | 294 | if (xbi.if_flags & IFF_OACTIVE | |
295 | && mcsrval & A12_MCSR_OMFE) { | 295 | && mcsrval & A12_MCSR_OMFE) { | |
296 | xbi.if_flags &= ~IFF_OACTIVE; | 296 | xbi.if_flags &= ~IFF_OACTIVE; | |
297 | REGVAL(A12_OMR) &= ~A12_OMR_OMF_ENABLE; | 297 | REGVAL(A12_OMR) &= ~A12_OMR_OMF_ENABLE; | |
298 | alpha_wmb(); | 298 | alpha_wmb(); | |
299 | xb_start(&xbi); | 299 | xb_start(&xbi); | |
300 | } | 300 | } | |
301 | return 0; | 301 | return 0; | |
302 | } | 302 | } | |
303 | /* | 303 | /* | |
304 | * The interface logic will shoot us down with MCE (Missing Close Error) or | 304 | * The interface logic will shoot us down with MCE (Missing Close Error) or | |
305 | * ECE (Embedded Close Error) if we aren't in sync with the hardware w.r.t. | 305 | * ECE (Embedded Close Error) if we aren't in sync with the hardware w.r.t. | |
306 | * frame boundaries. As those are panic-level errors: Don't Get Them. | 306 | * frame boundaries. As those are panic-level errors: Don't Get Them. | |
307 | */ | 307 | */ | |
308 | static void | 308 | static void | |
309 | xb_intr_rcv() | 309 | xb_intr_rcv() | |
310 | { | 310 | { | |
311 | struct mbuf *m; | 311 | struct mbuf *m; | |
312 | long frameword[2]; | 312 | long frameword[2]; | |
313 | static long *xb_ibp; | 313 | static long *xb_ibp; | |
314 | int s = 0; /* XXX gcc */ | 314 | int s = 0; /* XXX gcc */ | |
315 | 315 | |||
316 | switch (xb_intr_rcv_state) { | 316 | switch (xb_intr_rcv_state) { | |
317 | case XBIR_PKTHDR: | 317 | case XBIR_PKTHDR: | |
318 | xb_ibp = xb_incoming; | 318 | xb_ibp = xb_incoming; | |
319 | quickload(REGADDR(A12_FIFO), frameword); /* frame_len >= 16 */ | 319 | quickload(REGADDR(A12_FIFO), frameword); /* frame_len >= 16 */ | |
320 | frame_len = frameword[0]; | 320 | frame_len = frameword[0]; | |
321 | if (!(20 <= frame_len && frame_len+16 <= xb_incoming_max)) | 321 | if (!(20 <= frame_len && frame_len+16 <= xb_incoming_max)) | |
322 | DIE(); | 322 | DIE(); | |
323 | /* | 323 | /* | |
324 | * The extra word when frames are of an aligned size is due | 324 | * The extra word when frames are of an aligned size is due | |
325 | * to the way the output routines work. After the mbuf is | 325 | * to the way the output routines work. After the mbuf is | |
326 | * sent xb_put_blk(NULL) is called. If there is a leftover | 326 | * sent xb_put_blk(NULL) is called. If there is a leftover | |
327 | * 127-bit-or-less fragment then the close word rides on it, | 327 | * 127-bit-or-less fragment then the close word rides on it, | |
328 | * otherwise it gets an entire 128 bits of zeroes. | 328 | * otherwise it gets an entire 128 bits of zeroes. | |
329 | */ | 329 | */ | |
330 | if (frame_len & 0xf) | 330 | if (frame_len & 0xf) | |
331 | frame_len = (frame_len + 0xf) >> 4; | 331 | frame_len = (frame_len + 0xf) >> 4; | |
332 | else frame_len = (frame_len >> 4) + 1; | 332 | else frame_len = (frame_len >> 4) + 1; | |
333 | --frame_len; /* we read the frame len + the first packet int64 */ | 333 | --frame_len; /* we read the frame len + the first packet int64 */ | |
334 | *xb_ibp++ = frameword[1]; | 334 | *xb_ibp++ = frameword[1]; | |
335 | xb_intr_rcv_state = XBIR_TRANS; | 335 | xb_intr_rcv_state = XBIR_TRANS; | |
336 | break; | 336 | break; | |
337 | case XBIR_TRANS: | 337 | case XBIR_TRANS: | |
338 | if (frame_len > 1) | 338 | if (frame_len > 1) | |
339 | quickload(REGADDR(A12_FIFO), frameword); | 339 | quickload(REGADDR(A12_FIFO), frameword); | |
340 | else if (frame_len == 1) { | 340 | else if (frame_len == 1) { | |
341 | quickload(REGADDR(A12_FIFO_LWE), frameword); | 341 | quickload(REGADDR(A12_FIFO_LWE), frameword); | |
342 | xb_intr_rcv_state = XBIR_PKTHDR; | 342 | xb_intr_rcv_state = XBIR_PKTHDR; | |
343 | } else if (XB_DEBUG) | 343 | } else if (XB_DEBUG) | |
344 | DIE(); | 344 | DIE(); | |
345 | --frame_len; | 345 | --frame_len; | |
346 | xb_ibp[0] = frameword[0]; | 346 | xb_ibp[0] = frameword[0]; | |
347 | xb_ibp[1] = frameword[1]; | 347 | xb_ibp[1] = frameword[1]; | |
348 | xb_ibp += 2; | 348 | xb_ibp += 2; | |
349 | if (xb_intr_rcv_state == XBIR_PKTHDR) { | 349 | if (xb_intr_rcv_state == XBIR_PKTHDR) { | |
350 | if (XB_DEBUG) { | 350 | if (XB_DEBUG) { | |
351 | s = splnet(); | 351 | s = splnet(); | |
352 | if (s != splnet()) | 352 | if (s != splnet()) | |
353 | DIE(); | 353 | DIE(); | |
354 | } | 354 | } | |
355 | ++xbi.if_ipackets; | 355 | ++xbi.if_ipackets; | |
356 | if (IF_QFULL(&ipintrq)) { | 356 | if (IF_QFULL(&ipintrq)) { | |
357 | IF_DROP(&ipintrq); | 357 | IF_DROP(&ipintrq); | |
358 | ++xbi.if_iqdrops; | 358 | ++xbi.if_iqdrops; | |
359 | } else { | 359 | } else { | |
360 | m = m_devget((void *)xb_incoming, | 360 | m = m_devget((void *)xb_incoming, | |
361 | (char *)xb_ibp - (char *)xb_incoming, | 361 | (char *)xb_ibp - (char *)xb_incoming, | |
362 | 0, &xbi, 0L); | 362 | 0, &xbi, 0L); | |
363 | if (m) { | 363 | if (m) { | |
364 | xbi.if_ibytes += m->m_pkthdr.len; | 364 | xbi.if_ibytes += m->m_pkthdr.len; | |
365 | IF_ENQUEUE(&ipintrq, m); | 365 | IF_ENQUEUE(&ipintrq, m); | |
366 | } else | 366 | } else | |
367 | ++xbi.if_ierrors; | 367 | ++xbi.if_ierrors; | |
368 | } | 368 | } | |
369 | if (XB_DEBUG) | 369 | if (XB_DEBUG) | |
370 | splx(s); | 370 | splx(s); | |
371 | } | 371 | } | |
372 | break; | 372 | break; | |
373 | default: | 373 | default: | |
374 | DIE(); | 374 | DIE(); | |
375 | } | 375 | } | |
376 | } | 376 | } | |
377 | /* | 377 | /* | |
378 | * Make it easy for gcc to load a[0..1] without interlocking between | 378 | * Make it easy for gcc to load a[0..1] without interlocking between | |
379 | * a[0] and a[1]. (If it did, that would be two external bus cycles.) | 379 | * a[0] and a[1]. (If it did, that would be two external bus cycles.) | |
380 | */ | 380 | */ | |
381 | Static void | 381 | Static void | |
382 | quickload(volatile long *a, long *b) | 382 | quickload(volatile long *a, long *b) | |
383 | { | 383 | { | |
384 | long t1,t2; | 384 | long t1,t2; | |
385 | 385 | |||
386 | t1 = a[0]; | 386 | t1 = a[0]; | |
387 | t2 = a[1]; | 387 | t2 = a[1]; | |
388 | b[0] = t1; | 388 | b[0] = t1; | |
389 | b[1] = t2; | 389 | b[1] = t2; | |
390 | } | 390 | } | |
391 | /* | 391 | /* | |
392 | * Verify during debugging that we have not overflowed the FIFO | 392 | * Verify during debugging that we have not overflowed the FIFO | |
393 | */ | 393 | */ | |
394 | static inline void | 394 | static inline void | |
395 | xb_onefree() | 395 | xb_onefree() | |
396 | { | 396 | { | |
397 | if (XB_DEBUG && REGVAL(A12_MCSR) & A12_MCSR_OMFF) | 397 | if (XB_DEBUG && REGVAL(A12_MCSR) & A12_MCSR_OMFF) | |
398 | DIE(); | 398 | DIE(); | |
399 | } | 399 | } | |
400 | 400 | |||
401 | static void | 401 | static void | |
402 | xb_init(struct ifnet *ifp) | 402 | xb_init(struct ifnet *ifp) | |
403 | { | 403 | { | |
404 | ifp->if_flags |= IFF_RUNNING; | 404 | ifp->if_flags |= IFF_RUNNING; | |
405 | } | 405 | } | |
406 | 406 | |||
407 | static void | 407 | static void | |
408 | xb_stop() | 408 | xb_stop() | |
409 | { | 409 | { | |
410 | } | 410 | } | |
411 | 411 | |||
412 | static int | 412 | static int | |
413 | xb_ioctl(struct ifnet *ifp, unsigned long cmd, void *data) | 413 | xb_ioctl(struct ifnet *ifp, unsigned long cmd, void *data) | |
414 | { | 414 | { | |
415 | struct ifaddr *ifa = (struct ifaddr *)data; | 415 | struct ifaddr *ifa = (struct ifaddr *)data; | |
416 | int s, error = 0; | 416 | int s, error = 0; | |
417 | 417 | |||
418 | s = splnet(); | 418 | s = splnet(); | |
419 | switch (cmd) { | 419 | switch (cmd) { | |
420 | case SIOCINITIFADDR: | 420 | case SIOCINITIFADDR: | |
421 | xbi.if_flags |= IFF_UP; | 421 | xbi.if_flags |= IFF_UP; | |
422 | xb_init(ifp); | 422 | xb_init(ifp); | |
423 | break; | 423 | break; | |
424 | case SIOCSIFFLAGS: | 424 | case SIOCSIFFLAGS: | |
425 | if ((error = ifioctl_common(ifp, cmd, data)) != 0) | 425 | if ((error = ifioctl_common(ifp, cmd, data)) != 0) | |
426 | break; | 426 | break; | |
427 | if ((ifp->if_flags & IFF_UP) == 0 && | 427 | if ((ifp->if_flags & IFF_UP) == 0 && | |
428 | (ifp->if_flags & IFF_RUNNING) != 0) { | 428 | (ifp->if_flags & IFF_RUNNING) != 0) { | |
429 | xb_stop(); | 429 | xb_stop(); | |
430 | ifp->if_flags &= ~IFF_RUNNING; | 430 | ifp->if_flags &= ~IFF_RUNNING; | |
431 | } else if ((ifp->if_flags & IFF_UP) != 0 && | 431 | } else if ((ifp->if_flags & IFF_UP) != 0 && | |
432 | (ifp->if_flags & IFF_RUNNING) == 0) { | 432 | (ifp->if_flags & IFF_RUNNING) == 0) { | |
433 | xb_start(ifp); | 433 | xb_start(ifp); | |
434 | } else | 434 | } else | |
435 | xb_init(ifp); | 435 | xb_init(ifp); | |
436 | if (ifp->if_flags & IFF_DEBUG) | 436 | if (ifp->if_flags & IFF_DEBUG) | |
437 | xb_debug = 1; | 437 | xb_debug = 1; | |
438 | break; | 438 | break; | |
439 | default: | 439 | default: | |
440 | error = ifioctl_common(ifp, cmd, data); | 440 | error = ifioctl_common(ifp, cmd, data); | |
441 | break; | 441 | break; | |
442 | } | 442 | } | |
443 | splx(s); | 443 | splx(s); | |
444 | return error; | 444 | return error; | |
445 | } | 445 | } | |
446 | /* | 446 | /* | |
447 | * XXX - someday, keep a software copy of A12_OMR. We can execute up to | 447 | * XXX - someday, keep a software copy of A12_OMR. We can execute up to | |
448 | * 200 or 300 instructions in the time it takes to do the read part of an | 448 | * 200 or 300 instructions in the time it takes to do the read part of an | |
449 | * external bus cycle RMW op. (Or 10 - 20 cache cycles.) | 449 | * external bus cycle RMW op. (Or 10 - 20 cache cycles.) | |
450 | */ | 450 | */ | |
451 | static inline long | 451 | static inline long | |
452 | xb_fifo_empty(void) | 452 | xb_fifo_empty(void) | |
453 | { | 453 | { | |
454 | return REGVAL(A12_MCSR) & A12_MCSR_OMFE; | 454 | return REGVAL(A12_MCSR) & A12_MCSR_OMFE; | |
455 | } | 455 | } | |
456 | /* | 456 | /* | |
457 | * rtmon frames | 457 | * rtmon frames | |
458 | * | 458 | * | |
459 | * [ (... data) : commid : sourcepid : dstpid : ktype : length : frametype ] | 459 | * [ (... data) : commid : sourcepid : dstpid : ktype : length : frametype ] | |
460 | * | 460 | * | |
461 | * At the moment, NetBSD ip frames are not compatible with rtmon frames: | 461 | * At the moment, NetBSD ip frames are not compatible with rtmon frames: | |
462 | * | 462 | * | |
463 | * [ ... data : length ] | 463 | * [ ... data : length ] | |
464 | */ | 464 | */ | |
465 | static int | 465 | static int | |
466 | xb_output(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst, struct rtentry *rt0) | 466 | xb_output(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst, struct rtentry *rt0) | |
467 | { | 467 | { | |
468 | int i,s; | 468 | int i,s; | |
469 | struct mbuf *m = m0; | 469 | struct mbuf *m = m0; | |
470 | const char *lladdr; | 470 | const char *lladdr; | |
471 | char *xbh; | 471 | char *xbh; | |
472 | long xbo_framesize; | 472 | long xbo_framesize; | |
473 | const struct sockaddr_dl *llsa; | 473 | const struct sockaddr_dl *llsa; | |
474 | int xbaddr; | 474 | int xbaddr; | |
475 | 475 | |||
476 | #ifdef DIAGNOSTIC | 476 | #ifdef DIAGNOSTIC | |
477 | if (ifp != &xbi) | 477 | if (ifp != &xbi) | |
478 | DIE(); | 478 | DIE(); | |
479 | #endif | 479 | #endif | |
480 | if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { | 480 | if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { | |
481 | m_freem(m); | 481 | m_freem(m); | |
482 | return ENETDOWN; | 482 | return ENETDOWN; | |
483 | } | 483 | } | |
484 | /* | 484 | /* | |
485 | * We want an IP packet with a link level route, on a silver platter. | 485 | * We want an IP packet with a link level route, on a silver platter. | |
486 | */ | 486 | */ | |
487 | if (rt0 == NULL | 487 | if (rt0 == NULL | |
488 | || (rt0->rt_flags & (RTF_GATEWAY | RTF_LLINFO)) | 488 | || (rt0->rt_flags & (RTF_GATEWAY | RTF_LLINFO)) | |
489 | || (llsa = satocsdl(rt0->rt_gateway)) == NULL | 489 | || (llsa = satocsdl(rt0->rt_gateway)) == NULL | |
490 | || llsa->sdl_family != AF_LINK | 490 | || llsa->sdl_family != AF_LINK | |
491 | || llsa->sdl_slen != 0) { | 491 | || llsa->sdl_slen != 0) { | |
492 | ++ifp->if_oerrors; | 492 | ++ifp->if_oerrors; | |
493 | m_freem(m); | 493 | m_freem(m); | |
494 | return EHOSTUNREACH; | 494 | return EHOSTUNREACH; | |
495 | } | 495 | } | |
496 | if (dst == NULL | 496 | if (dst == NULL | |
497 | || dst->sa_family != AF_INET) { | 497 | || dst->sa_family != AF_INET) { | |
498 | /* | 498 | /* | |
499 | * This is because we give all received packets to ipintrq | 499 | * This is because we give all received packets to ipintrq | |
500 | * right now. | 500 | * right now. | |
501 | */ | 501 | */ | |
502 | What(); | 502 | What(); | |
503 | m_freem(m); | 503 | m_freem(m); | |
504 | ++ifp->if_noproto; | 504 | ++ifp->if_noproto; | |
505 | return EAFNOSUPPORT; | 505 | return EAFNOSUPPORT; | |
506 | } | 506 | } | |
507 | /* | 507 | /* | |
508 | * The a12MppSwitch is a wormhole routed MSN consisting of a number | 508 | * The a12MppSwitch is a wormhole routed MSN consisting of a number | |
509 | * (usually n==1) of 14 channel crossbar switches. Each route through | 509 | * (usually n==1) of 14 channel crossbar switches. Each route through | |
510 | * a switch requires a 128 bit address word that specifies the channel | 510 | * a switch requires a 128 bit address word that specifies the channel | |
511 | * to emerge on. The address word is eaten by the switch and the | 511 | * to emerge on. The address word is eaten by the switch and the | |
512 | * rest of the packet is routed through. | 512 | * rest of the packet is routed through. | |
513 | */ | 513 | */ | |
514 | lladdr = CLLADDR(llsa); | 514 | lladdr = CLLADDR(llsa); | |
515 | if (llsa->sdl_alen != 1) /* XXX */ | 515 | if (llsa->sdl_alen != 1) /* XXX */ | |
516 | DIE(); /* OK someday, but totally unexpected right now */ | 516 | DIE(); /* OK someday, but totally unexpected right now */ | |
517 | /* | 517 | /* | |
518 | * Alternatively, we could lookup the address word and output | 518 | * Alternatively, we could lookup the address word and output | |
519 | * it with PIO when the mbuf is dequeued | 519 | * it with PIO when the mbuf is dequeued | |
520 | */ | 520 | */ | |
521 | xbo_framesize = m->m_pkthdr.len + 8; | 521 | xbo_framesize = m->m_pkthdr.len + 8; | |
522 | M_PREPEND(m, 16 * llsa->sdl_alen + 8, M_DONTWAIT); | 522 | M_PREPEND(m, 16 * llsa->sdl_alen + 8, M_DONTWAIT); | |
523 | if (m == NULL) | 523 | if (m == NULL) | |
524 | return ENOBUFS; | 524 | return ENOBUFS; | |
525 | xbh = mtod(m, char *); | 525 | xbh = mtod(m, char *); | |
526 | for (i=0; i<llsa->sdl_alen; ++i) { | 526 | for (i=0; i<llsa->sdl_alen; ++i) { | |
527 | xbaddr = (lladdr[i] & 0xff) - 1; | 527 | xbaddr = (lladdr[i] & 0xff) - 1; | |
528 | if (!(0 <= xbaddr && xbaddr <= 11)) /* XXX */ | 528 | if (!(0 <= xbaddr && xbaddr <= 11)) /* XXX */ | |
529 | DIE(); /* 12 or 13 will be OK later */ | 529 | DIE(); /* 12 or 13 will be OK later */ | |
530 | memcpy(xbh, &channel[xbaddr].lo64, 16); | 530 | memcpy(xbh, &channel[xbaddr].lo64, 16); | |
531 | xbh += 16; | 531 | xbh += 16; | |
532 | } | 532 | } | |
533 | memcpy(xbh, &xbo_framesize, 8); | 533 | memcpy(xbh, &xbo_framesize, 8); | |
534 | s = splnet(); | 534 | s = splnet(); | |
535 | if (IF_QFULL(&ifp->if_snd)) { | 535 | if (IF_QFULL(&ifp->if_snd)) { | |
536 | IF_DROP(&ifp->if_snd); | 536 | IF_DROP(&ifp->if_snd); | |
537 | ++ifp->if_oerrors; | 537 | ++ifp->if_oerrors; | |
538 | splx(s); | 538 | splx(s); | |
539 | m_freem(m); | 539 | m_freem(m); | |
540 | return ENOBUFS; | 540 | return ENOBUFS; | |
541 | } | 541 | } | |
542 | ifp->if_obytes += m->m_pkthdr.len; | 542 | ifp->if_obytes += m->m_pkthdr.len; | |
543 | ++ifp->if_opackets; | 543 | ++ifp->if_opackets; | |
544 | IF_ENQUEUE(&ifp->if_snd, m); | 544 | IF_ENQUEUE(&ifp->if_snd, m); | |
545 | if ((ifp->if_flags & IFF_OACTIVE) == 0) | 545 | if ((ifp->if_flags & IFF_OACTIVE) == 0) | |
546 | xb_start(ifp); | 546 | xb_start(ifp); | |
547 | splx(s); | 547 | splx(s); | |
548 | if (m->m_flags & M_MCAST) | 548 | if (m->m_flags & M_MCAST) | |
549 | ifp->if_omcasts++; | 549 | ifp->if_omcasts++; | |
550 | return 0; | 550 | return 0; | |
551 | } | 551 | } | |
552 | 552 | |||
553 | void | 553 | void | |
554 | xb_start(struct ifnet *ifp) | 554 | xb_start(struct ifnet *ifp) | |
555 | { | 555 | { | |
556 | struct mbuf *m; | 556 | struct mbuf *m; | |
557 | 557 | |||
558 | if ((xbi.if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) | 558 | if ((xbi.if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) | |
559 | return; | 559 | return; | |
560 | for (;;) { | 560 | for (;;) { | |
561 | IF_DEQUEUE(&xbi.if_snd, m); | 561 | IF_DEQUEUE(&xbi.if_snd, m); | |
562 | if (m == 0) | 562 | if (m == 0) | |
563 | return; | 563 | return; | |
564 | /* | 564 | /* | |
565 | * XXX The variable-length switch address words cause problems | 565 | * XXX The variable-length switch address words cause problems | |
566 | * for bpf, for now, leave it out. XXX It's not too hard to | 566 | * for bpf, for now, leave it out. XXX It's not too hard to | |
567 | * fix, though, as there are lots of techniques that will | 567 | * fix, though, as there are lots of techniques that will | |
568 | * identify the number of switch address words. | 568 | * identify the number of switch address words. | |
569 | */ | 569 | */ | |
570 | if (!xb_put(m)) { | 570 | if (!xb_put(m)) { | |
571 | xbi.if_flags |= IFF_OACTIVE; | 571 | xbi.if_flags |= IFF_OACTIVE; | |
572 | return; | 572 | return; | |
573 | } | 573 | } | |
574 | } | 574 | } | |
575 | } | 575 | } | |
576 | 576 | |||
577 | static int | 577 | static int | |
578 | xb_put(struct mbuf *m) | 578 | xb_put(struct mbuf *m) | |
579 | { | 579 | { | |
580 | struct mbuf *n; | 580 | struct mbuf *n; | |
581 | int len; | 581 | int len; | |
582 | 582 | |||
583 | if (XB_DEBUG && (alpha_pal_rdps() & 7) < 3) | 583 | if (XB_DEBUG && (alpha_pal_rdps() & 7) < 3) | |
584 | DIE(); /* this "cannot happen", of course */ | 584 | DIE(); /* this "cannot happen", of course */ | |
585 | for (; m; m = n) { | 585 | for (; m; m = n) { | |
586 | len = m->m_len; | 586 | len = m->m_len; | |
587 | if (len == 0 || xb_put_blk(m)) | 587 | if (len == 0 || xb_put_blk(m)) | |
588 | MFREE(m, n); | 588 | MFREE(m, n); | |
589 | else return 0; | 589 | else return 0; | |
590 | } | 590 | } | |
591 | xb_put_blk(NULL); | 591 | xb_put_blk(NULL); | |
592 | return 1; | 592 | return 1; | |
593 | } | 593 | } | |
594 | /* | 594 | /* | |
595 | * Write a single mbuf to the transmit channel fifo. We can only write 128-bit | 595 | * Write a single mbuf to the transmit channel fifo. We can only write 128-bit | |
596 | * words. Right now, we pad at the end. It is possible to pad at the | 596 | * words. Right now, we pad at the end. It is possible to pad at the | |
597 | * beginning, especially since lots of games can be played at the receiver | 597 | * beginning, especially since lots of games can be played at the receiver | |
598 | * with the mbuf data pointer. Padding at the beginning requires a pad-count | 598 | * with the mbuf data pointer. Padding at the beginning requires a pad-count | |
599 | * field in a header, but it means you can always DMA the data, regardless of | 599 | * field in a header, but it means you can always DMA the data, regardless of | |
600 | * alignment. Of course, we don't DMA at all, right now. | 600 | * alignment. Of course, we don't DMA at all, right now. | |
601 | */ | 601 | */ | |
602 | static int | 602 | static int | |
603 | xb_put_blk(struct mbuf *m) | 603 | xb_put_blk(struct mbuf *m) | |
604 | { | 604 | { | |
605 | static long leftover[2]; /* 0-15 bytes from last xb_put_blk() */ | 605 | static long leftover[2]; /* 0-15 bytes from last xb_put_blk() */ | |
606 | static int leftover_len; /* non-aligned amount from last call */ | 606 | static int leftover_len; /* non-aligned amount from last call */ | |
607 | long xfertmp[8]; /* aligned switch word buffer */ | 607 | long xfertmp[8]; /* aligned switch word buffer */ | |
608 | int frag_len, /* fifo stream unit */ | 608 | int frag_len, /* fifo stream unit */ | |
609 | fifo_len, /* space left in fifo */ | 609 | fifo_len, /* space left in fifo */ | |
610 | fillin, /* amount needed to complete a switch word */ | 610 | fillin, /* amount needed to complete a switch word */ | |
611 | full, /* remember to restart on fifo full */ | 611 | full, /* remember to restart on fifo full */ | |
612 | len; /* amount of mbuf left to do */ | 612 | len; /* amount of mbuf left to do */ | |
613 | char *blk; /* location we are at in mbuf */ | 613 | char *blk; /* location we are at in mbuf */ | |
614 | static int fifo_free; /* current # of switch words free in fifo */ | 614 | static int fifo_free; /* current # of switch words free in fifo */ | |
615 | 615 | |||
616 | #define XFERADJ() ((char *)xfertmp + leftover_len) | 616 | #define XFERADJ() ((char *)xfertmp + leftover_len) | |
617 | 617 | |||
618 | /* There is always room for the close word */ | 618 | /* There is always room for the close word */ | |
619 | 619 | |||
620 | if (m == NULL) { | 620 | if (m == NULL) { | |
621 | if (leftover_len) | 621 | if (leftover_len) | |
622 | leftover_len = 0; | 622 | leftover_len = 0; | |
623 | else leftover[0] = leftover[1] = 0; | 623 | else leftover[0] = leftover[1] = 0; | |
624 | xb_mcrp_write(leftover, 1, 1); | 624 | xb_mcrp_write(leftover, 1, 1); | |
625 | --fifo_free; | 625 | --fifo_free; | |
626 | return 1; | 626 | return 1; | |
627 | } | 627 | } | |
628 | 628 | |||
629 | restart: | 629 | restart: | |
630 | if (fifo_free < 2) { | 630 | if (fifo_free < 2) { | |
631 | if (!xb_fifo_empty()) { | 631 | if (!xb_fifo_empty()) { | |
632 | if(!set_interrupt_on_fifo_empty()) { | 632 | if(!set_interrupt_on_fifo_empty()) { | |
633 | /* still empty */ | 633 | /* still empty */ | |
634 | xbi.if_flags |= IFF_OACTIVE; | 634 | xbi.if_flags |= IFF_OACTIVE; | |
635 | IF_PREPEND(&xbi.if_snd, m); | 635 | IF_PREPEND(&xbi.if_snd, m); | |
636 | return 0; | 636 | return 0; | |
637 | } | 637 | } | |
638 | } | 638 | } | |
639 | fifo_free = FIFO_WORDCOUNT; | 639 | fifo_free = FIFO_WORDCOUNT; | |
640 | } | 640 | } | |
641 | len = m->m_len; | 641 | len = m->m_len; | |
642 | if (len == 0) | 642 | if (len == 0) | |
643 | return 1; /* clean finish, nothing left over */ | 643 | return 1; /* clean finish, nothing left over */ | |
644 | blk = mtod(m, char *); | 644 | blk = mtod(m, char *); | |
645 | if (leftover_len) { | 645 | if (leftover_len) { | |
646 | /* See function intro comment regarding padding */ | 646 | /* See function intro comment regarding padding */ | |
647 | if (leftover_len + len < sizeof leftover) { | 647 | if (leftover_len + len < sizeof leftover) { | |
648 | /* Heh, not even enough to write out */ | 648 | /* Heh, not even enough to write out */ | |
649 | memcpy(XFERADJ(), blk, len); | 649 | memcpy(XFERADJ(), blk, len); | |
650 | leftover_len += len; | 650 | leftover_len += len; | |
651 | return 1; | 651 | return 1; | |
652 | } | 652 | } | |
653 | xfertmp[0] = leftover[0]; | 653 | xfertmp[0] = leftover[0]; | |
654 | xfertmp[1] = leftover[1]; | 654 | xfertmp[1] = leftover[1]; | |
655 | fillin = sizeof leftover - leftover_len; | 655 | fillin = sizeof leftover - leftover_len; | |
656 | memcpy(XFERADJ(), blk, fillin); | 656 | memcpy(XFERADJ(), blk, fillin); | |
657 | blk += fillin; | 657 | blk += fillin; | |
658 | len -= fillin; | 658 | len -= fillin; | |
659 | xb_mcrp_write(xfertmp, 1, 0); | 659 | xb_mcrp_write(xfertmp, 1, 0); | |
660 | leftover_len = 0; | 660 | leftover_len = 0; | |
661 | --fifo_free; | 661 | --fifo_free; | |
662 | } | 662 | } | |
663 | /* fifo_free is known to be >= 1 at this point */ | 663 | /* fifo_free is known to be >= 1 at this point */ | |
664 | while (len >= 16) { | 664 | while (len >= 16) { | |
665 | full = 0; | 665 | full = 0; | |
666 | frag_len = sizeof xfertmp; | 666 | frag_len = sizeof xfertmp; | |
667 | if (frag_len > len) | 667 | if (frag_len > len) | |
668 | frag_len = len; | 668 | frag_len = len; | |
669 | fifo_len = fifo_free * 16; | 669 | fifo_len = fifo_free * 16; | |
670 | if (frag_len > fifo_len) { | 670 | if (frag_len > fifo_len) { | |
671 | frag_len = fifo_len; | 671 | frag_len = fifo_len; | |
672 | full = 1; | 672 | full = 1; | |
673 | } | 673 | } | |
674 | frag_len &= ~0xf; | 674 | frag_len &= ~0xf; | |
675 | memcpy(xfertmp, blk, frag_len); | 675 | memcpy(xfertmp, blk, frag_len); | |
676 | frag_len >>= 4; /* Round down to switch word size */ | 676 | frag_len >>= 4; /* Round down to switch word size */ | |
677 | xb_mcrp_write(xfertmp, frag_len, 0); | 677 | xb_mcrp_write(xfertmp, frag_len, 0); | |
678 | fifo_free -= frag_len; | 678 | fifo_free -= frag_len; | |
679 | frag_len <<= 4; | 679 | frag_len <<= 4; | |
680 | len -= frag_len; | 680 | len -= frag_len; | |
681 | blk += frag_len; | 681 | blk += frag_len; | |
682 | if (full) { | 682 | if (full) { | |
683 | m_adj(m, blk - mtod(m, char *)); | 683 | m_adj(m, blk - mtod(m, char *)); | |
684 | goto restart; | 684 | goto restart; | |
685 | } | 685 | } | |
686 | } | 686 | } | |
687 | memcpy(leftover, blk, len); | 687 | memcpy(leftover, blk, len); | |
688 | leftover_len = len; | 688 | leftover_len = len; | |
689 | return 1; | 689 | return 1; | |
690 | } | 690 | } | |
691 | 691 | |||
692 | static long | 692 | static long | |
693 | set_interrupt_on_fifo_empty(void) | 693 | set_interrupt_on_fifo_empty(void) | |
694 | { | 694 | { | |
695 | REGVAL(A12_OMR) |= A12_OMR_OMF_ENABLE; | 695 | REGVAL(A12_OMR) |= A12_OMR_OMF_ENABLE; | |
696 | alpha_mb(); | 696 | alpha_mb(); | |
697 | if(xb_fifo_empty()) { | 697 | if(xb_fifo_empty()) { | |
698 | REGVAL(A12_OMR) &= ~A12_OMR_OMF_ENABLE; | 698 | REGVAL(A12_OMR) &= ~A12_OMR_OMF_ENABLE; | |
699 | alpha_mb(); | 699 | alpha_mb(); | |
700 | return 1; | 700 | return 1; | |
701 | } | 701 | } | |
702 | return 0; | 702 | return 0; | |
703 | } | 703 | } | |
704 | /* | 704 | /* | |
705 | * Write an aligned block of switch words to the FIFO | 705 | * Write an aligned block of switch words to the FIFO | |
706 | */ | 706 | */ | |
707 | Static void | 707 | Static void | |
708 | xb_mcrp_write(long *d, n, islast) | 708 | xb_mcrp_write(long *d, int n, int islast) | |
709 | { | 709 | { | |
710 | volatile long *xb_fifo = islast ? REGADDR(A12_FIFO_LWE) | 710 | volatile long *xb_fifo = islast ? REGADDR(A12_FIFO_LWE) | |
711 | : REGADDR(A12_FIFO); | 711 | : REGADDR(A12_FIFO); | |
712 | int i; | 712 | int i; | |
713 | 713 | |||
714 | if (XB_DEBUG && islast && n != 1) | 714 | if (XB_DEBUG && islast && n != 1) | |
715 | DIE(); | 715 | DIE(); | |
716 | n <<= 1; | 716 | n <<= 1; | |
717 | for (i = 0; i < n; i += 2) { | 717 | for (i = 0; i < n; i += 2) { | |
718 | xb_onefree(); | 718 | xb_onefree(); | |
719 | xb_fifo[0] = d[i]; | 719 | xb_fifo[0] = d[i]; | |
720 | xb_fifo[1] = d[i+1]; | 720 | xb_fifo[1] = d[i+1]; | |
721 | alpha_wmb(); | 721 | alpha_wmb(); | |
722 | } | 722 | } | |
723 | } | 723 | } | |
724 | 724 | |||
725 | /* | 725 | /* | |
726 | const | 726 | const | |
727 | int32_t xbar_bc_addr = XBAR_BROADCAST; | 727 | int32_t xbar_bc_addr = XBAR_BROADCAST; | |
728 | */ | 728 | */ | |
729 | 729 | |||
730 | static void | 730 | static void | |
731 | a12_xbar_setup() | 731 | a12_xbar_setup() | |
732 | { | 732 | { | |
733 | xbi.if_softc = &xb_softc; | 733 | xbi.if_softc = &xb_softc; | |
734 | xbi.if_start = xb_start; | 734 | xbi.if_start = xb_start; | |
735 | xbi.if_ioctl = xb_ioctl; | 735 | xbi.if_ioctl = xb_ioctl; | |
736 | xbi.if_flags = IFF_BROADCAST /* ha ha */ | 736 | xbi.if_flags = IFF_BROADCAST /* ha ha */ | |
737 | | IFF_SIMPLEX; | 737 | | IFF_SIMPLEX; | |
738 | 738 | |||
739 | xbi.if_type = IFT_A12MPPSWITCH; | 739 | xbi.if_type = IFT_A12MPPSWITCH; | |
740 | xbi.if_addrlen = 32; | 740 | xbi.if_addrlen = 32; | |
741 | xbi.if_hdrlen = 32; | 741 | xbi.if_hdrlen = 32; | |
742 | xbi.if_mtu = XB_DEFAULT_MTU(); | 742 | xbi.if_mtu = XB_DEFAULT_MTU(); | |
743 | xbi.if_output = xb_output; | 743 | xbi.if_output = xb_output; | |
744 | /* xbi.if_broadcastaddr = (u_int8_t)&xbar_bc_addr; */ | 744 | /* xbi.if_broadcastaddr = (u_int8_t)&xbar_bc_addr; */ | |
745 | 745 | |||
746 | if_attach(&xbi); | 746 | if_attach(&xbi); | |
747 | if_alloc_sadl(&xbi); | 747 | if_alloc_sadl(&xbi); | |
748 | 748 | |||
749 | #if NBPFILTER > 0 | 749 | #if NBPFILTER > 0 | |
750 | bpfattach(&xbi, DLT_NULL, 0); | 750 | bpfattach(&xbi, DLT_NULL, 0); | |
751 | #endif | 751 | #endif | |
752 | } | 752 | } |
--- src/sys/arch/vax/boot/boot/ctu.c 2009/03/14 21:04:16 1.6
+++ src/sys/arch/vax/boot/boot/ctu.c 2009/03/17 18:19:15 1.7
@@ -1,178 +1,178 @@ | @@ -1,178 +1,178 @@ | |||
1 | /* $NetBSD: ctu.c,v 1.6 2009/03/14 21:04:16 dsl Exp $ */ | 1 | /* $NetBSD: ctu.c,v 1.7 2009/03/17 18:19:15 dsl Exp $ */ | |
2 | /* | 2 | /* | |
3 | * Copyright (c) 1996 Ludd, University of Lule}, Sweden. | 3 | * Copyright (c) 1996 Ludd, University of Lule}, Sweden. | |
4 | * All rights reserved. | 4 | * All rights reserved. | |
5 | * | 5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions | 7 | * modification, are permitted provided that the following conditions | |
8 | * are met: | 8 | * are met: | |
9 | * 1. Redistributions of source code must retain the above copyright | 9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | 10 | * notice, this list of conditions and the following disclaimer. | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | 11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | 12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | 13 | * documentation and/or other materials provided with the distribution. | |
14 | * 3. All advertising materials mentioning features or use of this software | 14 | * 3. All advertising materials mentioning features or use of this software | |
15 | * must display the following acknowledgement: | 15 | * must display the following acknowledgement: | |
16 | * This product includes software developed at Ludd, University of | 16 | * This product includes software developed at Ludd, University of | |
17 | * Lule}, Sweden and its contributors. | 17 | * Lule}, Sweden and its contributors. | |
18 | * 4. The name of the author may not be used to endorse or promote products | 18 | * 4. The name of the author may not be used to endorse or promote products | |
19 | * derived from this software without specific prior written permission | 19 | * derived from this software without specific prior written permission | |
20 | * | 20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 21 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
22 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 22 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
23 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 23 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
24 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 24 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
26 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 26 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
27 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 27 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
28 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 28 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
30 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 30 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | /* | 33 | /* | |
34 | * Standalone device driver for 11/750 Console TU58. | 34 | * Standalone device driver for 11/750 Console TU58. | |
35 | * It can only handle reads, and doesn't calculate checksum. | 35 | * It can only handle reads, and doesn't calculate checksum. | |
36 | */ | 36 | */ | |
37 | 37 | |||
38 | #include <sys/param.h> | 38 | #include <sys/param.h> | |
39 | 39 | |||
40 | #include <lib/libsa/stand.h> | 40 | #include <lib/libsa/stand.h> | |
41 | 41 | |||
42 | #include <machine/mtpr.h> | 42 | #include <machine/mtpr.h> | |
43 | #include <machine/rsp.h> | 43 | #include <machine/rsp.h> | |
44 | 44 | |||
45 | #include "vaxstand.h" | 45 | #include "vaxstand.h" | |
46 | 46 | |||
47 | static short ctu_cksum(unsigned short *, int); | 47 | static short ctu_cksum(unsigned short *, int); | |
48 | 48 | |||
49 | enum tu_state { | 49 | enum tu_state { | |
50 | SC_INIT, | 50 | SC_INIT, | |
51 | SC_READY, | 51 | SC_READY, | |
52 | SC_SEND_CMD, | 52 | SC_SEND_CMD, | |
53 | SC_GET_RESP, | 53 | SC_GET_RESP, | |
54 | }; | 54 | }; | |
55 | 55 | |||
56 | volatile struct tu_softc { | 56 | volatile struct tu_softc { | |
57 | enum tu_state sc_state; | 57 | enum tu_state sc_state; | |
58 | char sc_rsp[15]; /* Should be struct rsb; but don't work */ | 58 | char sc_rsp[15]; /* Should be struct rsb; but don't work */ | |
59 | u_char *sc_xfptr; /* Current char to xfer */ | 59 | u_char *sc_xfptr; /* Current char to xfer */ | |
60 | int sc_nbytes; /* Number of bytes to xfer */ | 60 | int sc_nbytes; /* Number of bytes to xfer */ | |
61 | int sc_xbytes; /* Number of xfer'd bytes */ | 61 | int sc_xbytes; /* Number of xfer'd bytes */ | |
62 | int sc_bbytes; /* Number of xfer'd bytes this block */ | 62 | int sc_bbytes; /* Number of xfer'd bytes this block */ | |
63 | } tu_sc; | 63 | } tu_sc; | |
64 | 64 | |||
65 | void ctutintr(void); | 65 | void ctutintr(void); | |
66 | void cturintr(void); | 66 | void cturintr(void); | |
67 | 67 | |||
68 | int | 68 | int | |
69 | ctuopen(struct open_file *f, adapt, int ctlr, int unit, int part) | 69 | ctuopen(struct open_file *f, int adapt, int ctlr, int unit, int part) | |
70 | { | 70 | { | |
71 | 71 | |||
72 | tu_sc.sc_state = SC_INIT; | 72 | tu_sc.sc_state = SC_INIT; | |
73 | 73 | |||
74 | mtpr(RSP_TYP_INIT, PR_CSTD); | 74 | mtpr(RSP_TYP_INIT, PR_CSTD); | |
75 | cturintr(); | 75 | cturintr(); | |
76 | tu_sc.sc_state = SC_READY; | 76 | tu_sc.sc_state = SC_READY; | |
77 | return 0; | 77 | return 0; | |
78 | 78 | |||
79 | } | 79 | } | |
80 | 80 | |||
81 | int | 81 | int | |
82 | ctustrategy(void *f, int func, daddr_t dblk, size_t size, void *buf, size_t *rsize) | 82 | ctustrategy(void *f, int func, daddr_t dblk, size_t size, void *buf, size_t *rsize) | |
83 | { | 83 | { | |
84 | struct rsp *rsp = (struct rsp *)tu_sc.sc_rsp; | 84 | struct rsp *rsp = (struct rsp *)tu_sc.sc_rsp; | |
85 | 85 | |||
86 | tu_sc.sc_xfptr = buf; | 86 | tu_sc.sc_xfptr = buf; | |
87 | tu_sc.sc_nbytes = size; | 87 | tu_sc.sc_nbytes = size; | |
88 | tu_sc.sc_xbytes = tu_sc.sc_bbytes = 0; | 88 | tu_sc.sc_xbytes = tu_sc.sc_bbytes = 0; | |
89 | 89 | |||
90 | rsp->rsp_typ = RSP_TYP_COMMAND; | 90 | rsp->rsp_typ = RSP_TYP_COMMAND; | |
91 | rsp->rsp_sz = 012; | 91 | rsp->rsp_sz = 012; | |
92 | rsp->rsp_op = RSP_OP_READ; | 92 | rsp->rsp_op = RSP_OP_READ; | |
93 | rsp->rsp_mod = 0; | 93 | rsp->rsp_mod = 0; | |
94 | rsp->rsp_drv = 0; | 94 | rsp->rsp_drv = 0; | |
95 | rsp->rsp_sw = rsp->rsp_xx1 = rsp->rsp_xx2 = 0; | 95 | rsp->rsp_sw = rsp->rsp_xx1 = rsp->rsp_xx2 = 0; | |
96 | rsp->rsp_cnt = tu_sc.sc_nbytes; | 96 | rsp->rsp_cnt = tu_sc.sc_nbytes; | |
97 | rsp->rsp_blk = dblk; | 97 | rsp->rsp_blk = dblk; | |
98 | rsp->rsp_sum = ctu_cksum((u_short *)rsp, 6); | 98 | rsp->rsp_sum = ctu_cksum((u_short *)rsp, 6); | |
99 | tu_sc.sc_state = SC_SEND_CMD; | 99 | tu_sc.sc_state = SC_SEND_CMD; | |
100 | while (tu_sc.sc_state != SC_GET_RESP) | 100 | while (tu_sc.sc_state != SC_GET_RESP) | |
101 | ctutintr(); | 101 | ctutintr(); | |
102 | while (tu_sc.sc_state != SC_READY) | 102 | while (tu_sc.sc_state != SC_READY) | |
103 | cturintr(); | 103 | cturintr(); | |
104 | *rsize = size; | 104 | *rsize = size; | |
105 | return 0; | 105 | return 0; | |
106 | } | 106 | } | |
107 | 107 | |||
108 | void | 108 | void | |
109 | cturintr() | 109 | cturintr() | |
110 | { | 110 | { | |
111 | int status; | 111 | int status; | |
112 | 112 | |||
113 | while ((mfpr(PR_CSRS) & 0x80) == 0) | 113 | while ((mfpr(PR_CSRS) & 0x80) == 0) | |
114 | ; | 114 | ; | |
115 | 115 | |||
116 | status = mfpr(PR_CSRD); | 116 | status = mfpr(PR_CSRD); | |
117 | 117 | |||
118 | switch (tu_sc.sc_state) { | 118 | switch (tu_sc.sc_state) { | |
119 | 119 | |||
120 | case SC_INIT: | 120 | case SC_INIT: | |
121 | break; | 121 | break; | |
122 | 122 | |||
123 | case SC_GET_RESP: | 123 | case SC_GET_RESP: | |
124 | if (tu_sc.sc_xbytes == tu_sc.sc_nbytes) { | 124 | if (tu_sc.sc_xbytes == tu_sc.sc_nbytes) { | |
125 | tu_sc.sc_bbytes++; | 125 | tu_sc.sc_bbytes++; | |
126 | if (tu_sc.sc_bbytes == 146) | 126 | if (tu_sc.sc_bbytes == 146) | |
127 | tu_sc.sc_state = SC_READY; | 127 | tu_sc.sc_state = SC_READY; | |
128 | break; | 128 | break; | |
129 | } | 129 | } | |
130 | tu_sc.sc_bbytes++; | 130 | tu_sc.sc_bbytes++; | |
131 | if (tu_sc.sc_bbytes < 3) /* Data header */ | 131 | if (tu_sc.sc_bbytes < 3) /* Data header */ | |
132 | break; | 132 | break; | |
133 | if (tu_sc.sc_bbytes == 132) { /* Finished */ | 133 | if (tu_sc.sc_bbytes == 132) { /* Finished */ | |
134 | tu_sc.sc_bbytes = 0; | 134 | tu_sc.sc_bbytes = 0; | |
135 | break; | 135 | break; | |
136 | } | 136 | } | |
137 | if (tu_sc.sc_bbytes == 131) /* First checksum */ | 137 | if (tu_sc.sc_bbytes == 131) /* First checksum */ | |
138 | break; | 138 | break; | |
139 | tu_sc.sc_xfptr[tu_sc.sc_xbytes++] = status; | 139 | tu_sc.sc_xfptr[tu_sc.sc_xbytes++] = status; | |
140 | break; | 140 | break; | |
141 | 141 | |||
142 | case SC_READY: | 142 | case SC_READY: | |
143 | case SC_SEND_CMD: | 143 | case SC_SEND_CMD: | |
144 | break; | 144 | break; | |
145 | } | 145 | } | |
146 | 146 | |||
147 | } | 147 | } | |
148 | 148 | |||
149 | void | 149 | void | |
150 | ctutintr() | 150 | ctutintr() | |
151 | { | 151 | { | |
152 | int c; | 152 | int c; | |
153 | 153 | |||
154 | while ((mfpr(PR_CSTS) & 0x80) == 0) | 154 | while ((mfpr(PR_CSTS) & 0x80) == 0) | |
155 | ; | 155 | ; | |
156 | 156 | |||
157 | c = tu_sc.sc_rsp[tu_sc.sc_xbytes++] & 0xff; | 157 | c = tu_sc.sc_rsp[tu_sc.sc_xbytes++] & 0xff; | |
158 | mtpr(c, PR_CSTD); | 158 | mtpr(c, PR_CSTD); | |
159 | if (tu_sc.sc_xbytes > 13) { | 159 | if (tu_sc.sc_xbytes > 13) { | |
160 | tu_sc.sc_state = SC_GET_RESP; | 160 | tu_sc.sc_state = SC_GET_RESP; | |
161 | tu_sc.sc_xbytes = 0; | 161 | tu_sc.sc_xbytes = 0; | |
162 | } | 162 | } | |
163 | } | 163 | } | |
164 | 164 | |||
165 | short | 165 | short | |
166 | ctu_cksum(unsigned short *buf, int words) | 166 | ctu_cksum(unsigned short *buf, int words) | |
167 | { | 167 | { | |
168 | int i, cksum; | 168 | int i, cksum; | |
169 | 169 | |||
170 | for (i = cksum = 0; i < words; i++) | 170 | for (i = cksum = 0; i < words; i++) | |
171 | cksum += buf[i]; | 171 | cksum += buf[i]; | |
172 | 172 | |||
173 | hej: if (cksum > 65535) { | 173 | hej: if (cksum > 65535) { | |
174 | cksum = (cksum & 65535) + (cksum >> 16); | 174 | cksum = (cksum & 65535) + (cksum >> 16); | |
175 | goto hej; | 175 | goto hej; | |
176 | } | 176 | } | |
177 | return cksum; | 177 | return cksum; | |
178 | } | 178 | } |
--- src/sys/arch/vax/boot/boot/mfm.c 2009/03/14 21:04:16 1.8
+++ src/sys/arch/vax/boot/boot/mfm.c 2009/03/17 18:19:15 1.9
@@ -1,655 +1,655 @@ | @@ -1,655 +1,655 @@ | |||
1 | /* $NetBSD: mfm.c,v 1.8 2009/03/14 21:04:16 dsl Exp $ */ | 1 | /* $NetBSD: mfm.c,v 1.9 2009/03/17 18:19:15 dsl Exp $ */ | |
2 | /* | 2 | /* | |
3 | * Copyright (c) 1996 Ludd, University of Lule}, Sweden. | 3 | * Copyright (c) 1996 Ludd, University of Lule}, Sweden. | |
4 | * All rights reserved. | 4 | * All rights reserved. | |
5 | * | 5 | * | |
6 | * This code is derived from software contributed to Ludd by | 6 | * This code is derived from software contributed to Ludd by | |
7 | * Bertram Barth. | 7 | * Bertram Barth. | |
8 | * | 8 | * | |
9 | * Redistribution and use in source and binary forms, with or without | 9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | 10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | 11 | * are met: | |
12 | * 1. Redistributions of source code must retain the above copyright | 12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | 13 | * notice, this list of conditions and the following disclaimer. | |
14 | * 2. Redistributions in binary form must reproduce the above copyright | 14 | * 2. Redistributions in binary form must reproduce the above copyright | |
15 | * notice, this list of conditions and the following disclaimer in the | 15 | * notice, this list of conditions and the following disclaimer in the | |
16 | * documentation and/or other materials provided with the distribution. | 16 | * documentation and/or other materials provided with the distribution. | |
17 | * 3. All advertising materials mentioning features or use of this software | 17 | * 3. All advertising materials mentioning features or use of this software | |
18 | * must display the following acknowledgement: | 18 | * must display the following acknowledgement: | |
19 | * This product includes software developed at Ludd, University of | 19 | * This product includes software developed at Ludd, University of | |
20 | * Lule}, Sweden and its contributors. | 20 | * Lule}, Sweden and its contributors. | |
21 | * 4. The name of the author may not be used to endorse or promote products | 21 | * 4. The name of the author may not be used to endorse or promote products | |
22 | * derived from this software without specific prior written permission | 22 | * derived from this software without specific prior written permission | |
23 | * | 23 | * | |
24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
26 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 26 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
27 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 27 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
28 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 28 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
29 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 29 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
30 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 30 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
31 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 31 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
32 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 32 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
33 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 33 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
34 | */ | 34 | */ | |
35 | 35 | |||
36 | /* | 36 | /* | |
37 | * ToDo: | 37 | * ToDo: | |
38 | * | 38 | * | |
39 | * - insert appropriate delays for diskette-drive where needed | 39 | * - insert appropriate delays for diskette-drive where needed | |
40 | * - allow more than one sector per diskette-read | 40 | * - allow more than one sector per diskette-read | |
41 | * - check for and handle bad sectors | 41 | * - check for and handle bad sectors | |
42 | * - ??? | 42 | * - ??? | |
43 | */ | 43 | */ | |
44 | 44 | |||
45 | #include <sys/param.h> | 45 | #include <sys/param.h> | |
46 | #include <sys/reboot.h> | 46 | #include <sys/reboot.h> | |
47 | #include <sys/disklabel.h> | 47 | #include <sys/disklabel.h> | |
48 | 48 | |||
49 | #include <lib/libsa/stand.h> | 49 | #include <lib/libsa/stand.h> | |
50 | #include <lib/libsa/ufs.h> | 50 | #include <lib/libsa/ufs.h> | |
51 | 51 | |||
52 | #include <lib/libkern/libkern.h> | 52 | #include <lib/libkern/libkern.h> | |
53 | 53 | |||
54 | #include "../include/pte.h" | 54 | #include "../include/pte.h" | |
55 | #include "../include/sid.h" | 55 | #include "../include/sid.h" | |
56 | #include "../include/mtpr.h" | 56 | #include "../include/mtpr.h" | |
57 | #include "../include/reg.h" | 57 | #include "../include/reg.h" | |
58 | #include "../include/rpb.h" | 58 | #include "../include/rpb.h" | |
59 | 59 | |||
60 | #include "ka410.h" | 60 | #include "ka410.h" | |
61 | #include "../vsa/hdc9224.h" | 61 | #include "../vsa/hdc9224.h" | |
62 | 62 | |||
63 | #include "data.h" | 63 | #include "data.h" | |
64 | #include "vaxstand.h" | 64 | #include "vaxstand.h" | |
65 | 65 | |||
66 | #define MAX_WAIT (1000*1000) /* # of loop-instructions in seconds */ | 66 | #define MAX_WAIT (1000*1000) /* # of loop-instructions in seconds */ | |
67 | 67 | |||
68 | struct mfm_softc { | 68 | struct mfm_softc { | |
69 | int part; | 69 | int part; | |
70 | int unit; | 70 | int unit; | |
71 | }; | 71 | }; | |
72 | 72 | |||
73 | static struct disklabel mfmlabel; | 73 | static struct disklabel mfmlabel; | |
74 | static struct mfm_softc mfm_softc; | 74 | static struct mfm_softc mfm_softc; | |
75 | static char io_buf[DEV_BSIZE]; | 75 | static char io_buf[DEV_BSIZE]; | |
76 | 76 | |||
77 | /* | 77 | /* | |
78 | * These should probably be somewhere else, but ka410 is the only | 78 | * These should probably be somewhere else, but ka410 is the only | |
79 | * one with mfm disks anyway... | 79 | * one with mfm disks anyway... | |
80 | */ | 80 | */ | |
81 | volatile unsigned char *ka410_intreq = (void*)0x2008000f; | 81 | volatile unsigned char *ka410_intreq = (void*)0x2008000f; | |
82 | volatile unsigned char *ka410_intclr = (void*)0x2008000f; | 82 | volatile unsigned char *ka410_intclr = (void*)0x2008000f; | |
83 | volatile unsigned char *ka410_intmsk = (void*)0x2008000c; | 83 | volatile unsigned char *ka410_intmsk = (void*)0x2008000c; | |
84 | 84 | |||
85 | static volatile struct hdc9224_DKCreg *dkc = (void *) 0x200c0000; | 85 | static volatile struct hdc9224_DKCreg *dkc = (void *) 0x200c0000; | |
86 | static volatile struct hdc9224_UDCreg sreg; /* input */ | 86 | static volatile struct hdc9224_UDCreg sreg; /* input */ | |
87 | static volatile struct hdc9224_UDCreg creg; /* output */ | 87 | static volatile struct hdc9224_UDCreg creg; /* output */ | |
88 | 88 | |||
89 | static void sreg_read(void); | 89 | static void sreg_read(void); | |
90 | static void creg_write(void); | 90 | static void creg_write(void); | |
91 | static int mfm_rxprepare(void); | 91 | static int mfm_rxprepare(void); | |
92 | static int mfm_command(int cmd); | 92 | static int mfm_command(int cmd); | |
93 | static int mfm_rxselect(int unit); | 93 | static int mfm_rxselect(int unit); | |
94 | static int mfm_rdselect(int unit); | 94 | static int mfm_rdselect(int unit); | |
95 | static int mfm_rxstrategy(void *f, int func, daddr_t dblk, size_t size, void *buf, size_t *rsize); | 95 | static int mfm_rxstrategy(void *f, int func, daddr_t dblk, size_t size, void *buf, size_t *rsize); | |
96 | static int mfm_rdstrategy(void *f, int func, daddr_t dblk, size_t size, void *buf, size_t *rsize); | 96 | static int mfm_rdstrategy(void *f, int func, daddr_t dblk, size_t size, void *buf, size_t *rsize); | |
97 | /* | 97 | /* | |
98 | * we have to wait 0.7 usec between two accesses to any of the | 98 | * we have to wait 0.7 usec between two accesses to any of the | |
99 | * dkc-registers, on a VS2000 with 1 MIPS, this is roughly one | 99 | * dkc-registers, on a VS2000 with 1 MIPS, this is roughly one | |
100 | * instruction. Thus the loop-overhead will be enough... | 100 | * instruction. Thus the loop-overhead will be enough... | |
101 | */ | 101 | */ | |
102 | static void | 102 | static void | |
103 | sreg_read() | 103 | sreg_read() | |
104 | { | 104 | { | |
105 | int i; | 105 | int i; | |
106 | char *p; | 106 | char *p; | |
107 | 107 | |||
108 | dkc->dkc_cmd = 0x40; /* set internal counter to zero */ | 108 | dkc->dkc_cmd = 0x40; /* set internal counter to zero */ | |
109 | p = (void *) &sreg; | 109 | p = (void *) &sreg; | |
110 | for (i = 0; i < 10; i++) | 110 | for (i = 0; i < 10; i++) | |
111 | *p++ = dkc->dkc_reg; /* dkc_reg auto-increments */ | 111 | *p++ = dkc->dkc_reg; /* dkc_reg auto-increments */ | |
112 | } | 112 | } | |
113 | 113 | |||
114 | static void | 114 | static void | |
115 | creg_write() | 115 | creg_write() | |
116 | { | 116 | { | |
117 | int i; | 117 | int i; | |
118 | char *p; | 118 | char *p; | |
119 | 119 | |||
120 | dkc->dkc_cmd = 0x40; /* set internal counter to zero */ | 120 | dkc->dkc_cmd = 0x40; /* set internal counter to zero */ | |
121 | p = (void *) &creg; | 121 | p = (void *) &creg; | |
122 | for (i = 0; i < 10; i++) | 122 | for (i = 0; i < 10; i++) | |
123 | dkc->dkc_reg = *p++; /* dkc_reg auto-increments */ | 123 | dkc->dkc_reg = *p++; /* dkc_reg auto-increments */ | |
124 | } | 124 | } | |
125 | 125 | |||
126 | /* | 126 | /* | |
127 | * floppies are handled in a quite strange way by this controller... | 127 | * floppies are handled in a quite strange way by this controller... | |
128 | * | 128 | * | |
129 | * before reading/writing a sector from/to floppy, we use the SEEK/READ_ID | 129 | * before reading/writing a sector from/to floppy, we use the SEEK/READ_ID | |
130 | * command to place the head at the desired location. Then we wait some | 130 | * command to place the head at the desired location. Then we wait some | |
131 | * time before issuing the real command in order to let the drive become | 131 | * time before issuing the real command in order to let the drive become | |
132 | * ready... | 132 | * ready... | |
133 | */ | 133 | */ | |
134 | int | 134 | int | |
135 | mfm_rxprepare() | 135 | mfm_rxprepare() | |
136 | { | 136 | { | |
137 | int error; | 137 | int error; | |
138 | 138 | |||
139 | error = mfm_command(DKC_CMD_SEEKREADID | 0x04); /* step=1, verify=0 */ | 139 | error = mfm_command(DKC_CMD_SEEKREADID | 0x04); /* step=1, verify=0 */ | |
140 | if (error) { | 140 | if (error) { | |
141 | printf("error while stepping to position %d/%d/%x. Retry...\n", | 141 | printf("error while stepping to position %d/%d/%x. Retry...\n", | |
142 | creg.udc_dsect, creg.udc_dhead, creg.udc_dcyl); | 142 | creg.udc_dsect, creg.udc_dhead, creg.udc_dcyl); | |
143 | error = mfm_command(DKC_CMD_SEEKREADID | 0x04); | 143 | error = mfm_command(DKC_CMD_SEEKREADID | 0x04); | |
144 | } | 144 | } | |
145 | return error; | 145 | return error; | |
146 | } | 146 | } | |
147 | 147 | |||
148 | int | 148 | int | |
149 | mfm_rxselect(int unit) | 149 | mfm_rxselect(int unit) | |
150 | { | 150 | { | |
151 | int error; | 151 | int error; | |
152 | 152 | |||
153 | /* | 153 | /* | |
154 | * bring "creg" in some known-to-work state and | 154 | * bring "creg" in some known-to-work state and | |
155 | * select the drive with the DRIVE SELECT command. | 155 | * select the drive with the DRIVE SELECT command. | |
156 | */ | 156 | */ | |
157 | creg.udc_dma7 = 0; | 157 | creg.udc_dma7 = 0; | |
158 | creg.udc_dma15 = 0; | 158 | creg.udc_dma15 = 0; | |
159 | creg.udc_dma23 = 0; | 159 | creg.udc_dma23 = 0; | |
160 | creg.udc_dsect = 1; /* sectors are numbered 1..15 !!! */ | 160 | creg.udc_dsect = 1; /* sectors are numbered 1..15 !!! */ | |
161 | creg.udc_dhead = 0; | 161 | creg.udc_dhead = 0; | |
162 | creg.udc_dcyl = 0; | 162 | creg.udc_dcyl = 0; | |
163 | creg.udc_scnt = 0; | 163 | creg.udc_scnt = 0; | |
164 | 164 | |||
165 | creg.udc_rtcnt = UDC_RC_RX33READ; | 165 | creg.udc_rtcnt = UDC_RC_RX33READ; | |
166 | creg.udc_mode = UDC_MD_RX33; | 166 | creg.udc_mode = UDC_MD_RX33; | |
167 | creg.udc_term = UDC_TC_FDD; | 167 | creg.udc_term = UDC_TC_FDD; | |
168 | 168 | |||
169 | /* | 169 | /* | |
170 | * this is ... | 170 | * this is ... | |
171 | */ | 171 | */ | |
172 | error = mfm_command(DKC_CMD_DRSEL_RX33 | unit); | 172 | error = mfm_command(DKC_CMD_DRSEL_RX33 | unit); | |
173 | 173 | |||
174 | if ((error != 0) || ((sreg.udc_dstat & UDC_DS_READY) == 0)) { | 174 | if ((error != 0) || ((sreg.udc_dstat & UDC_DS_READY) == 0)) { | |
175 | printf("\nfloppy-drive not ready (new floppy inserted?)\n\n"); | 175 | printf("\nfloppy-drive not ready (new floppy inserted?)\n\n"); | |
176 | 176 | |||
177 | creg.udc_rtcnt &= ~UDC_RC_INVRDY; /* clear INVRDY-flag */ | 177 | creg.udc_rtcnt &= ~UDC_RC_INVRDY; /* clear INVRDY-flag */ | |
178 | error = mfm_command(DKC_CMD_DRSEL_RX33 | unit); | 178 | error = mfm_command(DKC_CMD_DRSEL_RX33 | unit); | |
179 | if ((error != 0) || ((sreg.udc_dstat & UDC_DS_READY) == 0)) { | 179 | if ((error != 0) || ((sreg.udc_dstat & UDC_DS_READY) == 0)) { | |
180 | printf("diskette not ready(1): %x/%x\n", | 180 | printf("diskette not ready(1): %x/%x\n", | |
181 | error, sreg.udc_dstat); | 181 | error, sreg.udc_dstat); | |
182 | printf("floppy-drive offline?\n"); | 182 | printf("floppy-drive offline?\n"); | |
183 | return (-1); | 183 | return (-1); | |
184 | } | 184 | } | |
185 | if (sreg.udc_dstat & UDC_DS_TRK00) | 185 | if (sreg.udc_dstat & UDC_DS_TRK00) | |
186 | error = mfm_command(DKC_CMD_STEPIN_FDD); | 186 | error = mfm_command(DKC_CMD_STEPIN_FDD); | |
187 | else | 187 | else | |
188 | error = mfm_command(DKC_CMD_STEPOUT_FDD); | 188 | error = mfm_command(DKC_CMD_STEPOUT_FDD); | |
189 | 189 | |||
190 | /* | 190 | /* | |
191 | * now ready should be 0, cause INVRDY is not set | 191 | * now ready should be 0, cause INVRDY is not set | |
192 | * (retrying a command makes this fail...) | 192 | * (retrying a command makes this fail...) | |
193 | */ | 193 | */ | |
194 | if ((error != 0) || ((sreg.udc_dstat & UDC_DS_READY) == 1)) { | 194 | if ((error != 0) || ((sreg.udc_dstat & UDC_DS_READY) == 1)) { | |
195 | printf("diskette not ready(2): %x/%x\n", | 195 | printf("diskette not ready(2): %x/%x\n", | |
196 | error, sreg.udc_dstat); | 196 | error, sreg.udc_dstat); | |
197 | } | 197 | } | |
198 | creg.udc_rtcnt |= UDC_RC_INVRDY; | 198 | creg.udc_rtcnt |= UDC_RC_INVRDY; | |
199 | error = mfm_command(DKC_CMD_DRSEL_RX33 | unit); | 199 | error = mfm_command(DKC_CMD_DRSEL_RX33 | unit); | |
200 | 200 | |||
201 | if ((error != 0) || ((sreg.udc_dstat & UDC_DS_READY) == 0)) { | 201 | if ((error != 0) || ((sreg.udc_dstat & UDC_DS_READY) == 0)) { | |
202 | printf("diskette not ready(3): %x/%x\n", | 202 | printf("diskette not ready(3): %x/%x\n", | |
203 | error, sreg.udc_dstat); | 203 | error, sreg.udc_dstat); | |
204 | printf("no floppy inserted or floppy-door open\n"); | 204 | printf("no floppy inserted or floppy-door open\n"); | |
205 | return (-1); | 205 | return (-1); | |
206 | } | 206 | } | |
207 | printf("floppy-drive reselected.\n"); | 207 | printf("floppy-drive reselected.\n"); | |
208 | } | 208 | } | |
209 | return (error); | 209 | return (error); | |
210 | } | 210 | } | |
211 | 211 | |||
212 | int | 212 | int | |
213 | mfm_rdselect(int unit) | 213 | mfm_rdselect(int unit) | |
214 | { | 214 | { | |
215 | int error; | 215 | int error; | |
216 | 216 | |||
217 | /* | 217 | /* | |
218 | * bring "creg" in some known-to-work state and | 218 | * bring "creg" in some known-to-work state and | |
219 | * select the drive with the DRIVE SELECT command. | 219 | * select the drive with the DRIVE SELECT command. | |
220 | */ | 220 | */ | |
221 | creg.udc_dma7 = 0; | 221 | creg.udc_dma7 = 0; | |
222 | creg.udc_dma15 = 0; | 222 | creg.udc_dma15 = 0; | |
223 | creg.udc_dma23 = 0; | 223 | creg.udc_dma23 = 0; | |
224 | creg.udc_dsect = 0; /* sectors are numbered 0..16 */ | 224 | creg.udc_dsect = 0; /* sectors are numbered 0..16 */ | |
225 | creg.udc_dhead = 0; | 225 | creg.udc_dhead = 0; | |
226 | creg.udc_dcyl = 0; | 226 | creg.udc_dcyl = 0; | |
227 | creg.udc_scnt = 0; | 227 | creg.udc_scnt = 0; | |
228 | 228 | |||
229 | creg.udc_rtcnt = UDC_RC_HDD_READ; | 229 | creg.udc_rtcnt = UDC_RC_HDD_READ; | |
230 | creg.udc_mode = UDC_MD_HDD; | 230 | creg.udc_mode = UDC_MD_HDD; | |
231 | creg.udc_term = UDC_TC_HDD; | 231 | creg.udc_term = UDC_TC_HDD; | |
232 | 232 | |||
233 | error = mfm_command(DKC_CMD_DRSEL_HDD | unit); | 233 | error = mfm_command(DKC_CMD_DRSEL_HDD | unit); | |
234 | 234 | |||
235 | return (error); | 235 | return (error); | |
236 | } | 236 | } | |
237 | 237 | |||
238 | static int mfm_retry = 0; | 238 | static int mfm_retry = 0; | |
239 | 239 | |||
240 | int | 240 | int | |
241 | mfm_command(int cmd) | 241 | mfm_command(int cmd) | |
242 | { | 242 | { | |
243 | int termcode, ready, i; | 243 | int termcode, ready, i; | |
244 | 244 | |||
245 | creg_write(); /* write command-registers */ | 245 | creg_write(); /* write command-registers */ | |
246 | *ka410_intclr = INTR_DC; | 246 | *ka410_intclr = INTR_DC; | |
247 | dkc->dkc_cmd = cmd; /* issue command */ | 247 | dkc->dkc_cmd = cmd; /* issue command */ | |
248 | for (i = 0; i < MAX_WAIT; i++) { | 248 | for (i = 0; i < MAX_WAIT; i++) { | |
249 | if (*ka410_intreq & INTR_DC) /* wait for interrupt */ | 249 | if (*ka410_intreq & INTR_DC) /* wait for interrupt */ | |
250 | break; | 250 | break; | |
251 | } | 251 | } | |
252 | if ((*ka410_intreq & INTR_DC) == 0) | 252 | if ((*ka410_intreq & INTR_DC) == 0) | |
253 | printf("timeout in mfm_command...\n"); | 253 | printf("timeout in mfm_command...\n"); | |
254 | 254 | |||
255 | sreg_read(); /* read status-registers */ | 255 | sreg_read(); /* read status-registers */ | |
256 | 256 | |||
257 | if (dkc->dkc_stat == (DKC_ST_DONE | DKC_TC_SUCCESS)) | 257 | if (dkc->dkc_stat == (DKC_ST_DONE | DKC_TC_SUCCESS)) | |
258 | return (0); | 258 | return (0); | |
259 | 259 | |||
260 | if (sreg.udc_cstat & UDC_CS_ECCERR) { | 260 | if (sreg.udc_cstat & UDC_CS_ECCERR) { | |
261 | printf( | 261 | printf( | |
262 | "\nspurious(?) ECC/CRC error at s%d/t%d/c%d [s%d/t%d/c%d(%d)]\n", | 262 | "\nspurious(?) ECC/CRC error at s%d/t%d/c%d [s%d/t%d/c%d(%d)]\n", | |
263 | sreg.udc_csect, sreg.udc_chead, sreg.udc_ccyl, | 263 | sreg.udc_csect, sreg.udc_chead, sreg.udc_ccyl, | |
264 | creg.udc_dsect, creg.udc_dhead, creg.udc_dcyl,creg.udc_scnt); | 264 | creg.udc_dsect, creg.udc_dhead, creg.udc_dcyl,creg.udc_scnt); | |
265 | if (sreg.udc_csect != creg.udc_dsect + creg.udc_scnt - 1) { | 265 | if (sreg.udc_csect != creg.udc_dsect + creg.udc_scnt - 1) { | |
266 | printf("DMA: %x %x %x [%x]\n", | 266 | printf("DMA: %x %x %x [%x]\n", | |
267 | sreg.udc_dma23, sreg.udc_dma15, | 267 | sreg.udc_dma23, sreg.udc_dma15, | |
268 | sreg.udc_dma7, 512 * (sreg.udc_csect - | 268 | sreg.udc_dma7, 512 * (sreg.udc_csect - | |
269 | creg.udc_dsect)); | 269 | creg.udc_dsect)); | |
270 | creg.udc_scnt = creg.udc_scnt - | 270 | creg.udc_scnt = creg.udc_scnt - | |
271 | (sreg.udc_csect - creg.udc_dsect) - 1; | 271 | (sreg.udc_csect - creg.udc_dsect) - 1; | |
272 | creg.udc_dsect = sreg.udc_csect + 1; | 272 | creg.udc_dsect = sreg.udc_csect + 1; | |
273 | creg.udc_dma23 = sreg.udc_dma23; | 273 | creg.udc_dma23 = sreg.udc_dma23; | |
274 | creg.udc_dma15 = sreg.udc_dma15 + 2; | 274 | creg.udc_dma15 = sreg.udc_dma15 + 2; | |
275 | creg.udc_dma7 = 0; | 275 | creg.udc_dma7 = 0; | |
276 | printf("Retry starting from s%d/t%d/c%d (%d). ", | 276 | printf("Retry starting from s%d/t%d/c%d (%d). ", | |
277 | creg.udc_dsect, creg.udc_dhead, creg.udc_dcyl, | 277 | creg.udc_dsect, creg.udc_dhead, creg.udc_dcyl, | |
278 | creg.udc_scnt); | 278 | creg.udc_scnt); | |
279 | } | 279 | } | |
280 | goto retry; | 280 | goto retry; | |
281 | } | 281 | } | |
282 | termcode = (dkc->dkc_stat & DKC_ST_TERMCOD) >> 3; | 282 | termcode = (dkc->dkc_stat & DKC_ST_TERMCOD) >> 3; | |
283 | ready = sreg.udc_dstat & UDC_DS_READY; | 283 | ready = sreg.udc_dstat & UDC_DS_READY; | |
284 | 284 | |||
285 | printf("cmd:0x%x: termcode=0x%x, status=0x%x, cstat=0x%x, dstat=0x%x\n", | 285 | printf("cmd:0x%x: termcode=0x%x, status=0x%x, cstat=0x%x, dstat=0x%x\n", | |
286 | cmd, termcode, dkc->dkc_stat, sreg.udc_cstat, sreg.udc_dstat); | 286 | cmd, termcode, dkc->dkc_stat, sreg.udc_cstat, sreg.udc_dstat); | |
287 | 287 | |||
288 | if (dkc->dkc_stat & DKC_ST_BADSECT) | 288 | if (dkc->dkc_stat & DKC_ST_BADSECT) | |
289 | printf("bad sector found: s%d/t%d/c%d\n", creg.udc_dsect, | 289 | printf("bad sector found: s%d/t%d/c%d\n", creg.udc_dsect, | |
290 | creg.udc_dhead, creg.udc_dcyl); | 290 | creg.udc_dhead, creg.udc_dcyl); | |
291 | retry: | 291 | retry: | |
292 | if ((mfm_retry == 0) && (sreg.udc_cstat & UDC_CS_RETREQ)) { | 292 | if ((mfm_retry == 0) && (sreg.udc_cstat & UDC_CS_RETREQ)) { | |
293 | mfm_retry = 1; | 293 | mfm_retry = 1; | |
294 | printf("Retrying... "); | 294 | printf("Retrying... "); | |
295 | mfm_command(cmd); | 295 | mfm_command(cmd); | |
296 | printf("Retry done.\n"); | 296 | printf("Retry done.\n"); | |
297 | mfm_retry = 0; | 297 | mfm_retry = 0; | |
298 | } | 298 | } | |
299 | return ((dkc->dkc_stat & DKC_ST_TERMCOD) >> 3); | 299 | return ((dkc->dkc_stat & DKC_ST_TERMCOD) >> 3); | |
300 | } | 300 | } | |
301 | 301 | |||
302 | /* | 302 | /* | |
303 | * on-disk geometry block | 303 | * on-disk geometry block | |
304 | */ | 304 | */ | |
305 | #define _aP __attribute__ ((packed)) /* force byte-alignment */ | 305 | #define _aP __attribute__ ((packed)) /* force byte-alignment */ | |
306 | 306 | |||
307 | volatile struct mfm_xbn { | 307 | volatile struct mfm_xbn { | |
308 | char mbz[10];/* 10 bytes of zero */ | 308 | char mbz[10];/* 10 bytes of zero */ | |
309 | long xbn_count _aP; /* number of XBNs */ | 309 | long xbn_count _aP; /* number of XBNs */ | |
310 | long dbn_count _aP; /* number of DBNs */ | 310 | long dbn_count _aP; /* number of DBNs */ | |
311 | long lbn_count _aP; /* number of LBNs (Logical-Block-Numbers) */ | 311 | long lbn_count _aP; /* number of LBNs (Logical-Block-Numbers) */ | |
312 | long rbn_count _aP; /* number of RBNs (Replacement-Block-Numbers) */ | 312 | long rbn_count _aP; /* number of RBNs (Replacement-Block-Numbers) */ | |
313 | short nspt; /* number of sectors per track */ | 313 | short nspt; /* number of sectors per track */ | |
314 | short ntracks;/* number of tracks */ | 314 | short ntracks;/* number of tracks */ | |
315 | short ncylinders; /* number of cylinders */ | 315 | short ncylinders; /* number of cylinders */ | |
316 | short precomp;/* first cylinder for write precompensation */ | 316 | short precomp;/* first cylinder for write precompensation */ | |
317 | short reduced;/* first cylinder for reduced write current */ | 317 | short reduced;/* first cylinder for reduced write current */ | |
318 | short seek_rate; /* seek rate or zero for buffered | 318 | short seek_rate; /* seek rate or zero for buffered | |
319 | * seeks */ | 319 | * seeks */ | |
320 | short crc_eec;/* 0 if CRC is being used or 1 if ECC is | 320 | short crc_eec;/* 0 if CRC is being used or 1 if ECC is | |
321 | * being used */ | 321 | * being used */ | |
322 | short rct; /* "replacement control table" (RCT) */ | 322 | short rct; /* "replacement control table" (RCT) */ | |
323 | short rct_ncopies; /* number of copies of the RCT */ | 323 | short rct_ncopies; /* number of copies of the RCT */ | |
324 | long media_id _aP; /* media identifier */ | 324 | long media_id _aP; /* media identifier */ | |
325 | short interleave; /* sector-to-sector interleave */ | 325 | short interleave; /* sector-to-sector interleave */ | |
326 | short headskew; /* head-to-head skew */ | 326 | short headskew; /* head-to-head skew */ | |
327 | short cylskew;/* cylinder-to-cylinder skew */ | 327 | short cylskew;/* cylinder-to-cylinder skew */ | |
328 | short gap0_size; /* size of GAP 0 in the MFM format */ | 328 | short gap0_size; /* size of GAP 0 in the MFM format */ | |
329 | short gap1_size; /* size of GAP 1 in the MFM format */ | 329 | short gap1_size; /* size of GAP 1 in the MFM format */ | |
330 | short gap2_size; /* size of GAP 2 in the MFM format */ | 330 | short gap2_size; /* size of GAP 2 in the MFM format */ | |
331 | short gap3_size; /* size of GAP 3 in the MFM format */ | 331 | short gap3_size; /* size of GAP 3 in the MFM format */ | |
332 | short sync_value; /* sync value used to start a track | 332 | short sync_value; /* sync value used to start a track | |
333 | * when formatting */ | 333 | * when formatting */ | |
334 | char reserved[32]; /* reserved for use by the RQDX1/2/3 | 334 | char reserved[32]; /* reserved for use by the RQDX1/2/3 | |
335 | * formatter */ | 335 | * formatter */ | |
336 | short serial_number; /* serial number */ | 336 | short serial_number; /* serial number */ | |
337 | char fill[412]; /* Filler bytes to the end of the | 337 | char fill[412]; /* Filler bytes to the end of the | |
338 | * block */ | 338 | * block */ | |
339 | short checksum; /* checksum over the XBN */ | 339 | short checksum; /* checksum over the XBN */ | |
340 | } mfm_xbn; | 340 | } mfm_xbn; | |
341 | 341 | |||
342 | #ifdef verbose | 342 | #ifdef verbose | |
343 | display_xbn(struct mfm_xbn *p) | 343 | display_xbn(struct mfm_xbn *p) | |
344 | { | 344 | { | |
345 | printf("**DiskData** XBNs: %d, DBNs: %d, LBNs: %d, RBNs: %d\n", | 345 | printf("**DiskData** XBNs: %d, DBNs: %d, LBNs: %d, RBNs: %d\n", | |
346 | p->xbn_count, p->dbn_count, p->lbn_count, p->rbn_count); | 346 | p->xbn_count, p->dbn_count, p->lbn_count, p->rbn_count); | |
347 | printf("sect/track: %d, tracks: %d, cyl: %d, precomp/reduced: %d/%d\n", | 347 | printf("sect/track: %d, tracks: %d, cyl: %d, precomp/reduced: %d/%d\n", | |
348 | p->nspt, p->ntracks, p->ncylinders, p->precomp, p->reduced); | 348 | p->nspt, p->ntracks, p->ncylinders, p->precomp, p->reduced); | |
349 | printf("seek-rate: %d, crc/eec: %s, RCT: %d, RCT-copies: %d\n", | 349 | printf("seek-rate: %d, crc/eec: %s, RCT: %d, RCT-copies: %d\n", | |
350 | p->seek_rate, p->crc_eec ? "EEC" : "CRC", p->rct, p->rct_ncopies); | 350 | p->seek_rate, p->crc_eec ? "EEC" : "CRC", p->rct, p->rct_ncopies); | |
351 | printf("media-ID: 0x%x, interleave: %d, headskew: %d, cylskew: %d\n", | 351 | printf("media-ID: 0x%x, interleave: %d, headskew: %d, cylskew: %d\n", | |
352 | &p->media_id, p->interleave, p->headskew, p->cylskew); | 352 | &p->media_id, p->interleave, p->headskew, p->cylskew); | |
353 | printf("gap0: %d, gap1: %d, gap2: %d, gap3: %d, sync-value: %d\n", | 353 | printf("gap0: %d, gap1: %d, gap2: %d, gap3: %d, sync-value: %d\n", | |
354 | p->gap0_size, p->gap1_size, p->gap2_size, p->gap3_size, | 354 | p->gap0_size, p->gap1_size, p->gap2_size, p->gap3_size, | |
355 | p->sync_value); | 355 | p->sync_value); | |
356 | printf("serial: %d, checksum: %d, size: %d, reserved: %32c\n", | 356 | printf("serial: %d, checksum: %d, size: %d, reserved: %32c\n", | |
357 | p->serial_number, p->checksum, sizeof(*p), p->reserved); | 357 | p->serial_number, p->checksum, sizeof(*p), p->reserved); | |
358 | } | 358 | } | |
359 | #endif | 359 | #endif | |
360 | 360 | |||
361 | int | 361 | int | |
362 | mfmopen(struct open_file *f, adapt, int ctlr, int unit, int part) | 362 | mfmopen(struct open_file *f, int adapt, int ctlr, int unit, int part) | |
363 | { | 363 | { | |
364 | char *msg; | 364 | char *msg; | |
365 | struct disklabel *lp = &mfmlabel; | 365 | struct disklabel *lp = &mfmlabel; | |
366 | struct mfm_softc *msc = &mfm_softc; | 366 | struct mfm_softc *msc = &mfm_softc; | |
367 | int err; | 367 | int err; | |
368 | size_t i; | 368 | size_t i; | |
369 | 369 | |||
370 | bzero(lp, sizeof(struct disklabel)); | 370 | bzero(lp, sizeof(struct disklabel)); | |
371 | msc->unit = unit; | 371 | msc->unit = unit; | |
372 | msc->part = part; | 372 | msc->part = part; | |
373 | 373 | |||
374 | err = mfmstrategy(msc, F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i); | 374 | err = mfmstrategy(msc, F_READ, LABELSECTOR, DEV_BSIZE, io_buf, &i); | |
375 | if (err) { | 375 | if (err) { | |
376 | printf("reading disklabel: %s\n", strerror(err)); | 376 | printf("reading disklabel: %s\n", strerror(err)); | |
377 | return 0; | 377 | return 0; | |
378 | } | 378 | } | |
379 | msg = getdisklabel(io_buf + LABELOFFSET, lp); | 379 | msg = getdisklabel(io_buf + LABELOFFSET, lp); | |
380 | if (msg) | 380 | if (msg) | |
381 | printf("getdisklabel: %s\n", msg); | 381 | printf("getdisklabel: %s\n", msg); | |
382 | 382 | |||
383 | f->f_devdata = (void *) msc; | 383 | f->f_devdata = (void *) msc; | |
384 | 384 | |||
385 | { | 385 | { | |
386 | #ifdef verbose | 386 | #ifdef verbose | |
387 | int k; | 387 | int k; | |
388 | unsigned char *ucp; | 388 | unsigned char *ucp; | |
389 | struct mfm_xbn *xp; | 389 | struct mfm_xbn *xp; | |
390 | #endif | 390 | #endif | |
391 | 391 | |||
392 | /* mfmstrategy(msc, F_READ, -16, 8192, io_buf, &i); */ | 392 | /* mfmstrategy(msc, F_READ, -16, 8192, io_buf, &i); */ | |
393 | mfmstrategy(msc, F_READ, -16, 512, io_buf, &i); | 393 | mfmstrategy(msc, F_READ, -16, 512, io_buf, &i); | |
394 | #ifdef verbose | 394 | #ifdef verbose | |
395 | printf("dumping raw disk-block #0:\n"); | 395 | printf("dumping raw disk-block #0:\n"); | |
396 | ucp = io_buf; | 396 | ucp = io_buf; | |
397 | for (k = 0; k < 128; k++) { | 397 | for (k = 0; k < 128; k++) { | |
398 | if (ucp[k] < 0x10) | 398 | if (ucp[k] < 0x10) | |
399 | printf("0"); | 399 | printf("0"); | |
400 | printf("%x ", ucp[k]); | 400 | printf("%x ", ucp[k]); | |
401 | if (k % 8 == 7) | 401 | if (k % 8 == 7) | |
402 | printf(" "); | 402 | printf(" "); | |
403 | if (k % 16 == 15) | 403 | if (k % 16 == 15) | |
404 | printf("\n"); | 404 | printf("\n"); | |
405 | } | 405 | } | |
406 | printf("\n"); | 406 | printf("\n"); | |
407 | 407 | |||
408 | xp = (void *) io_buf; | 408 | xp = (void *) io_buf; | |
409 | display_xbn(xp); | 409 | display_xbn(xp); | |
410 | printf("\n"); | 410 | printf("\n"); | |
411 | #endif | 411 | #endif | |
412 | } | 412 | } | |
413 | 413 | |||
414 | if (unit == 2) { /* floppy! */ | 414 | if (unit == 2) { /* floppy! */ | |
415 | if (lp->d_ntracks != 2) { | 415 | if (lp->d_ntracks != 2) { | |
416 | #ifdef verbose | 416 | #ifdef verbose | |
417 | printf("changing number of tracks from %d to %d.\n", | 417 | printf("changing number of tracks from %d to %d.\n", | |
418 | lp->d_ntracks, 2); | 418 | lp->d_ntracks, 2); | |
419 | #endif | 419 | #endif | |
420 | lp->d_ntracks = 2; | 420 | lp->d_ntracks = 2; | |
421 | } | 421 | } | |
422 | } else { /* hard-disk */ | 422 | } else { /* hard-disk */ | |
423 | unsigned short *usp = (void *) io_buf; | 423 | unsigned short *usp = (void *) io_buf; | |
424 | #ifdef verbose | 424 | #ifdef verbose | |
425 | printf("label says: s/t/c = %d/%d/%d\n", | 425 | printf("label says: s/t/c = %d/%d/%d\n", | |
426 | lp->d_nsectors, lp->d_ntracks, lp->d_ncylinders); | 426 | lp->d_nsectors, lp->d_ntracks, lp->d_ncylinders); | |
427 | #endif | 427 | #endif | |
428 | if (lp->d_nsectors != usp[13]) { | 428 | if (lp->d_nsectors != usp[13]) { | |
429 | #ifdef verbose | 429 | #ifdef verbose | |
430 | printf("changing number of sectors from %d to %d.\n", | 430 | printf("changing number of sectors from %d to %d.\n", | |
431 | lp->d_nsectors, usp[13]); | 431 | lp->d_nsectors, usp[13]); | |
432 | #endif | 432 | #endif | |
433 | lp->d_nsectors = usp[13]; | 433 | lp->d_nsectors = usp[13]; | |
434 | } | 434 | } | |
435 | if (lp->d_ntracks != usp[14]) { | 435 | if (lp->d_ntracks != usp[14]) { | |
436 | #ifdef verbose | 436 | #ifdef verbose | |
437 | printf("changing number of heads/tracks from %d to %d.\n", | 437 | printf("changing number of heads/tracks from %d to %d.\n", | |
438 | lp->d_ntracks, usp[14]); | 438 | lp->d_ntracks, usp[14]); | |
439 | #endif | 439 | #endif | |
440 | lp->d_ntracks = usp[14]; | 440 | lp->d_ntracks = usp[14]; | |
441 | } | 441 | } | |
442 | if (lp->d_ncylinders != usp[15]) { | 442 | if (lp->d_ncylinders != usp[15]) { | |
443 | #ifdef verbose | 443 | #ifdef verbose | |
444 | printf("changing number of cylinders from %d to %d.\n", | 444 | printf("changing number of cylinders from %d to %d.\n", | |
445 | lp->d_ncylinders, usp[15]); | 445 | lp->d_ncylinders, usp[15]); | |
446 | #endif | 446 | #endif | |
447 | lp->d_ncylinders = usp[15]; | 447 | lp->d_ncylinders = usp[15]; | |
448 | } | 448 | } | |
449 | lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; | 449 | lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; | |
450 | } | 450 | } | |
451 | 451 | |||
452 | return (0); | 452 | return (0); | |
453 | } | 453 | } | |
454 | 454 | |||
455 | int | 455 | int | |
456 | mfm_rxstrategy(void *f, int func, daddr_t dblk, size_t size, void *buf, size_t *rsize) { | 456 | mfm_rxstrategy(void *f, int func, daddr_t dblk, size_t size, void *buf, size_t *rsize) { | |
457 | struct mfm_softc *msc = f; | 457 | struct mfm_softc *msc = f; | |
458 | struct disklabel *lp; | 458 | struct disklabel *lp; | |
459 | int block, sect, head, cyl, scount, res; | 459 | int block, sect, head, cyl, scount, res; | |
460 | char *cbuf; | 460 | char *cbuf; | |
461 | 461 | |||
462 | cbuf = (char*)buf; | 462 | cbuf = (char*)buf; | |
463 | 463 | |||
464 | lp = &mfmlabel; | 464 | lp = &mfmlabel; | |
465 | block = (dblk < 0 ? 0 : dblk + lp->d_partitions[msc->part].p_offset); | 465 | block = (dblk < 0 ? 0 : dblk + lp->d_partitions[msc->part].p_offset); | |
466 | 466 | |||
467 | mfm_rxselect(msc->unit); | 467 | mfm_rxselect(msc->unit); | |
468 | 468 | |||
469 | /* | 469 | /* | |
470 | * if label is empty, assume RX33 | 470 | * if label is empty, assume RX33 | |
471 | */ | 471 | */ | |
472 | if (lp->d_nsectors == 0) | 472 | if (lp->d_nsectors == 0) | |
473 | lp->d_nsectors = 15; | 473 | lp->d_nsectors = 15; | |
474 | if (lp->d_ntracks == 0) | 474 | if (lp->d_ntracks == 0) | |
475 | lp->d_ntracks = 2; | 475 | lp->d_ntracks = 2; | |
476 | if (lp->d_secpercyl == 0) | 476 | if (lp->d_secpercyl == 0) | |
477 | lp->d_secpercyl = 30; | 477 | lp->d_secpercyl = 30; | |
478 | 478 | |||
479 | bzero((void *) 0x200D0000, size); | 479 | bzero((void *) 0x200D0000, size); | |
480 | scount = size / 512; | 480 | scount = size / 512; | |
481 | 481 | |||
482 | while (scount) { | 482 | while (scount) { | |
483 | /* | 483 | /* | |
484 | * prepare drive/operation parameter | 484 | * prepare drive/operation parameter | |
485 | */ | 485 | */ | |
486 | cyl = block / lp->d_secpercyl; | 486 | cyl = block / lp->d_secpercyl; | |
487 | sect = block % lp->d_secpercyl; | 487 | sect = block % lp->d_secpercyl; | |
488 | head = sect / lp->d_nsectors; | 488 | head = sect / lp->d_nsectors; | |
489 | sect = sect % lp->d_nsectors; | 489 | sect = sect % lp->d_nsectors; | |
490 | 490 | |||
491 | /* | 491 | /* | |
492 | * *rsize = 512; one sector after the other | 492 | * *rsize = 512; one sector after the other | |
493 | * ... | 493 | * ... | |
494 | */ | 494 | */ | |
495 | *rsize = 512 * min(scount, lp->d_nsectors - sect); | 495 | *rsize = 512 * min(scount, lp->d_nsectors - sect); | |
496 | 496 | |||
497 | /* | 497 | /* | |
498 | * now initialize the register values ... | 498 | * now initialize the register values ... | |
499 | */ | 499 | */ | |
500 | creg.udc_dma7 = 0; | 500 | creg.udc_dma7 = 0; | |
501 | creg.udc_dma15 = 0; | 501 | creg.udc_dma15 = 0; | |
502 | creg.udc_dma23 = 0; | 502 | creg.udc_dma23 = 0; | |
503 | 503 | |||
504 | creg.udc_dsect = sect + 1; /* sectors are numbered 1..15 | 504 | creg.udc_dsect = sect + 1; /* sectors are numbered 1..15 | |
505 | * !!! */ | 505 | * !!! */ | |
506 | head |= (cyl >> 4) & 0x70; | 506 | head |= (cyl >> 4) & 0x70; | |
507 | creg.udc_dhead = head; | 507 | creg.udc_dhead = head; | |
508 | creg.udc_dcyl = cyl; | 508 | creg.udc_dcyl = cyl; | |
509 | 509 | |||
510 | creg.udc_scnt = *rsize / 512; | 510 | creg.udc_scnt = *rsize / 512; | |
511 | 511 | |||
512 | if (func == F_WRITE) { | 512 | if (func == F_WRITE) { | |
513 | creg.udc_rtcnt = UDC_RC_RX33WRT; | 513 | creg.udc_rtcnt = UDC_RC_RX33WRT; | |
514 | creg.udc_mode = UDC_MD_RX33; | 514 | creg.udc_mode = UDC_MD_RX33; | |
515 | creg.udc_term = UDC_TC_FDD; | 515 | creg.udc_term = UDC_TC_FDD; | |
516 | 516 | |||
517 | mfm_rxprepare(); | 517 | mfm_rxprepare(); | |
518 | /* copy from buf */ | 518 | /* copy from buf */ | |
519 | bcopy(cbuf, (void *) 0x200D0000, *rsize); | 519 | bcopy(cbuf, (void *) 0x200D0000, *rsize); | |
520 | res = mfm_command(DKC_CMD_WRITE_RX33); | 520 | res = mfm_command(DKC_CMD_WRITE_RX33); | |
521 | } else { | 521 | } else { | |
522 | creg.udc_rtcnt = UDC_RC_RX33READ; | 522 | creg.udc_rtcnt = UDC_RC_RX33READ; | |
523 | creg.udc_mode = UDC_MD_RX33; | 523 | creg.udc_mode = UDC_MD_RX33; | |
524 | creg.udc_term = UDC_TC_FDD; | 524 | creg.udc_term = UDC_TC_FDD; | |
525 | 525 | |||
526 | mfm_rxprepare(); | 526 | mfm_rxprepare(); | |
527 | /* clear disk buffer */ | 527 | /* clear disk buffer */ | |
528 | bzero((void *) 0x200D0000, *rsize); | 528 | bzero((void *) 0x200D0000, *rsize); | |
529 | res = mfm_command(DKC_CMD_READ_RX33); | 529 | res = mfm_command(DKC_CMD_READ_RX33); | |
530 | /* copy to buf */ | 530 | /* copy to buf */ | |
531 | bcopy((void *) 0x200D0000, cbuf, *rsize); | 531 | bcopy((void *) 0x200D0000, cbuf, *rsize); | |
532 | } | 532 | } | |
533 | 533 | |||
534 | scount -= *rsize / 512; | 534 | scount -= *rsize / 512; | |
535 | block += *rsize / 512; | 535 | block += *rsize / 512; | |
536 | cbuf += *rsize; | 536 | cbuf += *rsize; | |
537 | } | 537 | } | |
538 | 538 | |||
539 | *rsize = size; | 539 | *rsize = size; | |
540 | return 0; | 540 | return 0; | |
541 | } | 541 | } | |
542 | 542 | |||
543 | int | 543 | int | |
544 | mfm_rdstrategy(void *f, int func, daddr_t dblk, size_t size, void *buf, size_t *rsize) { | 544 | mfm_rdstrategy(void *f, int func, daddr_t dblk, size_t size, void *buf, size_t *rsize) { | |
545 | struct mfm_softc *msc = f; | 545 | struct mfm_softc *msc = f; | |
546 | struct disklabel *lp; | 546 | struct disklabel *lp; | |
547 | int block, sect, head, cyl, scount, cmd, res; | 547 | int block, sect, head, cyl, scount, cmd, res; | |
548 | char *cbuf; | 548 | char *cbuf; | |
549 | 549 | |||
550 | cbuf = (char *)buf; | 550 | cbuf = (char *)buf; | |
551 | 551 | |||
552 | lp = &mfmlabel; | 552 | lp = &mfmlabel; | |
553 | block = (dblk < 0 ? 0 : dblk + lp->d_partitions[msc->part].p_offset); | 553 | block = (dblk < 0 ? 0 : dblk + lp->d_partitions[msc->part].p_offset); | |
554 | 554 | |||
555 | /* | 555 | /* | |
556 | * if label is empty, assume RD32 (XXX this must go away!!!) | 556 | * if label is empty, assume RD32 (XXX this must go away!!!) | |
557 | */ | 557 | */ | |
558 | if (lp->d_nsectors == 0) | 558 | if (lp->d_nsectors == 0) | |
559 | lp->d_nsectors = 17; | 559 | lp->d_nsectors = 17; | |
560 | if (lp->d_ntracks == 0) | 560 | if (lp->d_ntracks == 0) | |
561 | lp->d_ntracks = 6; | 561 | lp->d_ntracks = 6; | |
562 | if (lp->d_secpercyl == 0) | 562 | if (lp->d_secpercyl == 0) | |
563 | lp->d_secpercyl = 102; | 563 | lp->d_secpercyl = 102; | |
564 | 564 | |||
565 | mfm_rdselect(msc->unit); | 565 | mfm_rdselect(msc->unit); | |
566 | 566 | |||
567 | bzero((void *) 0x200D0000, size); | 567 | bzero((void *) 0x200D0000, size); | |
568 | scount = size / 512; | 568 | scount = size / 512; | |
569 | 569 | |||
570 | while (scount) { | 570 | while (scount) { | |
571 | /* | 571 | /* | |
572 | * prepare drive/operation parameter | 572 | * prepare drive/operation parameter | |
573 | */ | 573 | */ | |
574 | cyl = block / lp->d_secpercyl; | 574 | cyl = block / lp->d_secpercyl; | |
575 | sect = block % lp->d_secpercyl; | 575 | sect = block % lp->d_secpercyl; | |
576 | head = sect / lp->d_nsectors; | 576 | head = sect / lp->d_nsectors; | |
577 | sect = sect % lp->d_nsectors; | 577 | sect = sect % lp->d_nsectors; | |
578 | 578 | |||
579 | if (dblk < 0) { | 579 | if (dblk < 0) { | |
580 | #ifdef verbose | 580 | #ifdef verbose | |
581 | printf("using raw diskblock-data!\n"); | 581 | printf("using raw diskblock-data!\n"); | |
582 | printf("block %d, dblk %d ==> cyl %d, head %d, sect %d\n", | 582 | printf("block %d, dblk %d ==> cyl %d, head %d, sect %d\n", | |
583 | block, dblk, cyl, sect, head); | 583 | block, dblk, cyl, sect, head); | |
584 | #endif | 584 | #endif | |
585 | } else | 585 | } else | |
586 | cyl += 1; /* first cylinder is reserved for | 586 | cyl += 1; /* first cylinder is reserved for | |
587 | * controller! */ | 587 | * controller! */ | |
588 | 588 | |||
589 | *rsize = 512 * min(scount, lp->d_nsectors - sect); | 589 | *rsize = 512 * min(scount, lp->d_nsectors - sect); | |
590 | /* | 590 | /* | |
591 | * now re-initialize the register values ... | 591 | * now re-initialize the register values ... | |
592 | */ | 592 | */ | |
593 | creg.udc_dma7 = 0; | 593 | creg.udc_dma7 = 0; | |
594 | creg.udc_dma15 = 0; | 594 | creg.udc_dma15 = 0; | |
595 | creg.udc_dma23 = 0; | 595 | creg.udc_dma23 = 0; | |
596 | 596 | |||
597 | creg.udc_dsect = sect; | 597 | creg.udc_dsect = sect; | |
598 | head |= (cyl >> 4) & 0x70; | 598 | head |= (cyl >> 4) & 0x70; | |
599 | creg.udc_dhead = head; | 599 | creg.udc_dhead = head; | |
600 | creg.udc_dcyl = cyl; | 600 | creg.udc_dcyl = cyl; | |
601 | 601 | |||
602 | creg.udc_scnt = *rsize / 512; | 602 | creg.udc_scnt = *rsize / 512; | |
603 | 603 | |||
604 | if (func == F_WRITE) { | 604 | if (func == F_WRITE) { | |
605 | creg.udc_rtcnt = UDC_RC_HDD_WRT; | 605 | creg.udc_rtcnt = UDC_RC_HDD_WRT; | |
606 | creg.udc_mode = UDC_MD_HDD; | 606 | creg.udc_mode = UDC_MD_HDD; | |
607 | creg.udc_term = UDC_TC_HDD; | 607 | creg.udc_term = UDC_TC_HDD; | |
608 | cmd = DKC_CMD_WRITE_HDD; | 608 | cmd = DKC_CMD_WRITE_HDD; | |
609 | 609 | |||
610 | bcopy(cbuf, (void *) 0x200D0000, *rsize); | 610 | bcopy(cbuf, (void *) 0x200D0000, *rsize); | |
611 | res = mfm_command(cmd); | 611 | res = mfm_command(cmd); | |
612 | } else { | 612 | } else { | |
613 | creg.udc_rtcnt = UDC_RC_HDD_READ; | 613 | creg.udc_rtcnt = UDC_RC_HDD_READ; | |
614 | creg.udc_mode = UDC_MD_HDD; | 614 | creg.udc_mode = UDC_MD_HDD; | |
615 | creg.udc_term = UDC_TC_HDD; | 615 | creg.udc_term = UDC_TC_HDD; | |
616 | cmd = DKC_CMD_READ_HDD; | 616 | cmd = DKC_CMD_READ_HDD; | |
617 | 617 | |||
618 | bzero((void *) 0x200D0000, *rsize); | 618 | bzero((void *) 0x200D0000, *rsize); | |
619 | res = mfm_command(cmd); | 619 | res = mfm_command(cmd); | |
620 | bcopy((void *) 0x200D0000, cbuf, *rsize); | 620 | bcopy((void *) 0x200D0000, cbuf, *rsize); | |
621 | } | 621 | } | |
622 | 622 | |||
623 | scount -= *rsize / 512; | 623 | scount -= *rsize / 512; | |
624 | block += *rsize / 512; | 624 | block += *rsize / 512; | |
625 | cbuf += *rsize; | 625 | cbuf += *rsize; | |
626 | } | 626 | } | |
627 | 627 | |||
628 | /* | 628 | /* | |
629 | * unselect the drive ... | 629 | * unselect the drive ... | |
630 | */ | 630 | */ | |
631 | mfm_command(DKC_CMD_DRDESELECT); | 631 | mfm_command(DKC_CMD_DRDESELECT); | |
632 | 632 | |||
633 | *rsize = size; | 633 | *rsize = size; | |
634 | return 0; | 634 | return 0; | |
635 | } | 635 | } | |
636 | 636 | |||
637 | int | 637 | int | |
638 | mfmstrategy(void *f, int func, daddr_t dblk, size_t size, void *buf, size_t *rsize) | 638 | mfmstrategy(void *f, int func, daddr_t dblk, size_t size, void *buf, size_t *rsize) | |
639 | { | 639 | { | |
640 | struct mfm_softc *msc = f; | 640 | struct mfm_softc *msc = f; | |
641 | int res = -1; | 641 | int res = -1; | |
642 | 642 | |||
643 | switch (msc->unit) { | 643 | switch (msc->unit) { | |
644 | case 0: | 644 | case 0: | |
645 | case 1: | 645 | case 1: | |
646 | res = mfm_rdstrategy(f, func, dblk, size, buf, rsize); | 646 | res = mfm_rdstrategy(f, func, dblk, size, buf, rsize); | |
647 | break; | 647 | break; | |
648 | case 2: | 648 | case 2: | |
649 | res = mfm_rxstrategy(f, func, dblk, size, buf, rsize); | 649 | res = mfm_rxstrategy(f, func, dblk, size, buf, rsize); | |
650 | break; | 650 | break; | |
651 | default: | 651 | default: | |
652 | printf("invalid unit %d in mfmstrategy()\n", msc->unit); | 652 | printf("invalid unit %d in mfmstrategy()\n", msc->unit); | |
653 | } | 653 | } | |
654 | return (res); | 654 | return (res); | |
655 | } | 655 | } |
--- src/sys/arch/vax/boot/boot/tmscp.c 2009/03/14 21:04:16 1.7
+++ src/sys/arch/vax/boot/boot/tmscp.c 2009/03/17 18:19:15 1.8
@@ -1,196 +1,196 @@ | @@ -1,196 +1,196 @@ | |||
1 | /* $NetBSD: tmscp.c,v 1.7 2009/03/14 21:04:16 dsl Exp $ */ | 1 | /* $NetBSD: tmscp.c,v 1.8 2009/03/17 18:19:15 dsl Exp $ */ | |
2 | /* | 2 | /* | |
3 | * Copyright (c) 1995 Ludd, University of Lule}, Sweden. | 3 | * Copyright (c) 1995 Ludd, University of Lule}, Sweden. | |
4 | * All rights reserved. | 4 | * All rights reserved. | |
5 | * | 5 | * | |
6 | * Redistribution and use in source and binary forms, with or without | 6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions | 7 | * modification, are permitted provided that the following conditions | |
8 | * are met: | 8 | * are met: | |
9 | * 1. Redistributions of source code must retain the above copyright | 9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | 10 | * notice, this list of conditions and the following disclaimer. | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | 11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | 12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | 13 | * documentation and/or other materials provided with the distribution. | |
14 | * 3. All advertising materials mentioning features or use of this software | 14 | * 3. All advertising materials mentioning features or use of this software | |
15 | * must display the following acknowledgement: | 15 | * must display the following acknowledgement: | |
16 | * This product includes software developed at Ludd, University of Lule}. | 16 | * This product includes software developed at Ludd, University of Lule}. | |
17 | * 4. The name of the author may not be used to endorse or promote products | 17 | * 4. The name of the author may not be used to endorse or promote products | |
18 | * derived from this software without specific prior written permission | 18 | * derived from this software without specific prior written permission | |
19 | * | 19 | * | |
20 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 20 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
21 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 21 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
23 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 23 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 24 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
25 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 25 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
29 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 29 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | /* All bugs are subject to removal without further notice */ | 32 | /* All bugs are subject to removal without further notice */ | |
33 | 33 | |||
34 | #define NRSP 0 /* Kludge */ | 34 | #define NRSP 0 /* Kludge */ | |
35 | #define NCMD 0 /* Kludge */ | 35 | #define NCMD 0 /* Kludge */ | |
36 | 36 | |||
37 | #include <sys/param.h> | 37 | #include <sys/param.h> | |
38 | #include <sys/disklabel.h> | 38 | #include <sys/disklabel.h> | |
39 | 39 | |||
40 | #include <lib/libsa/stand.h> | 40 | #include <lib/libsa/stand.h> | |
41 | 41 | |||
42 | #include "../include/pte.h" | 42 | #include "../include/pte.h" | |
43 | #include <dev/mscp/mscp.h> | 43 | #include <dev/mscp/mscp.h> | |
44 | #include <dev/mscp/mscpreg.h> | 44 | #include <dev/mscp/mscpreg.h> | |
45 | 45 | |||
46 | #include "vaxstand.h" | 46 | #include "vaxstand.h" | |
47 | 47 | |||
48 | static command(int,int); | 48 | static command(int,int); | |
49 | 49 | |||
50 | /* | 50 | /* | |
51 | * These routines for TMSCP tape standalone boot is very simple, | 51 | * These routines for TMSCP tape standalone boot is very simple, | |
52 | * assuming a lots of thing like that we only working at one tape at | 52 | * assuming a lots of thing like that we only working at one tape at | |
53 | * a time, no separate routines for uba driver etc.. | 53 | * a time, no separate routines for uba driver etc.. | |
54 | * This code is directly copied from ra disk driver. | 54 | * This code is directly copied from ra disk driver. | |
55 | */ | 55 | */ | |
56 | 56 | |||
57 | struct ra_softc { | 57 | struct ra_softc { | |
58 | int udaddr; | 58 | int udaddr; | |
59 | int ubaddr; | 59 | int ubaddr; | |
60 | int unit; | 60 | int unit; | |
61 | }; | 61 | }; | |
62 | 62 | |||
63 | static volatile struct uda { | 63 | static volatile struct uda { | |
64 | struct mscp_1ca uda_ca; /* communications area */ | 64 | struct mscp_1ca uda_ca; /* communications area */ | |
65 | struct mscp uda_rsp; /* response packets */ | 65 | struct mscp uda_rsp; /* response packets */ | |
66 | struct mscp uda_cmd; /* command packets */ | 66 | struct mscp uda_cmd; /* command packets */ | |
67 | } uda; | 67 | } uda; | |
68 | 68 | |||
69 | struct udadevice { | 69 | struct udadevice { | |
70 | short udaip; | 70 | short udaip; | |
71 | short udasa; | 71 | short udasa; | |
72 | }; | 72 | }; | |
73 | 73 | |||
74 | static volatile struct uda *ubauda; | 74 | static volatile struct uda *ubauda; | |
75 | static volatile struct udadevice *udacsr; | 75 | static volatile struct udadevice *udacsr; | |
76 | static struct ra_softc ra_softc; | 76 | static struct ra_softc ra_softc; | |
77 | static int curblock; | 77 | static int curblock; | |
78 | 78 | |||
79 | 79 | |||
80 | tmscpopen(struct open_file *f, adapt, int ctlr, int unit, int part) | 80 | tmscpopen(struct open_file *f, int adapt, int ctlr, int unit, int part) | |
81 | { | 81 | { | |
82 | char *msg; | 82 | char *msg; | |
83 | extern u_int tmsaddr; | 83 | extern u_int tmsaddr; | |
84 | volatile struct ra_softc *ra=&ra_softc; | 84 | volatile struct ra_softc *ra=&ra_softc; | |
85 | volatile u_int *nisse; | 85 | volatile u_int *nisse; | |
86 | unsigned short johan; | 86 | unsigned short johan; | |
87 | int i,err; | 87 | int i,err; | |
88 | 88 | |||
89 | curblock = 0; | 89 | curblock = 0; | |
90 | if(adapt>nuba) return(EADAPT); | 90 | if(adapt>nuba) return(EADAPT); | |
91 | if(ctlr>nuda) return(ECTLR); | 91 | if(ctlr>nuda) return(ECTLR); | |
92 | ra->udaddr=uioaddr[adapt]+tmsaddr; | 92 | ra->udaddr=uioaddr[adapt]+tmsaddr; | |
93 | ra->ubaddr=(int)ubaaddr[adapt]; | 93 | ra->ubaddr=(int)ubaaddr[adapt]; | |
94 | ra->unit=unit; | 94 | ra->unit=unit; | |
95 | udacsr=(void*)ra->udaddr; | 95 | udacsr=(void*)ra->udaddr; | |
96 | nisse=((u_int *)ubaaddr[adapt]) + 512; | 96 | nisse=((u_int *)ubaaddr[adapt]) + 512; | |
97 | nisse[494]=PG_V|(((u_int)&uda)>>9); | 97 | nisse[494]=PG_V|(((u_int)&uda)>>9); | |
98 | nisse[495]=nisse[494]+1; | 98 | nisse[495]=nisse[494]+1; | |
99 | ubauda=(void*)0x3dc00+(((u_int)(&uda))&0x1ff); | 99 | ubauda=(void*)0x3dc00+(((u_int)(&uda))&0x1ff); | |
100 | 100 | |||
101 | /* | 101 | /* | |
102 | * Init of this tmscp ctlr. | 102 | * Init of this tmscp ctlr. | |
103 | */ | 103 | */ | |
104 | udacsr->udaip=0; /* Start init */ | 104 | udacsr->udaip=0; /* Start init */ | |
105 | while((udacsr->udasa&MP_STEP1) == 0); | 105 | while((udacsr->udasa&MP_STEP1) == 0); | |
106 | udacsr->udasa=0x8000; | 106 | udacsr->udasa=0x8000; | |
107 | while((udacsr->udasa&MP_STEP2) == 0); | 107 | while((udacsr->udasa&MP_STEP2) == 0); | |
108 | johan=(((u_int)ubauda)&0xffff)+8; | 108 | johan=(((u_int)ubauda)&0xffff)+8; | |
109 | udacsr->udasa=johan; | 109 | udacsr->udasa=johan; | |
110 | while((udacsr->udasa&MP_STEP3) == 0); | 110 | while((udacsr->udasa&MP_STEP3) == 0); | |
111 | udacsr->udasa=3; | 111 | udacsr->udasa=3; | |
112 | while((udacsr->udasa&MP_STEP4) == 0); | 112 | while((udacsr->udasa&MP_STEP4) == 0); | |
113 | udacsr->udasa=0x0001; | 113 | udacsr->udasa=0x0001; | |
114 | 114 | |||
115 | uda.uda_ca.ca_rspdsc=(int)&ubauda->uda_rsp.mscp_cmdref; | 115 | uda.uda_ca.ca_rspdsc=(int)&ubauda->uda_rsp.mscp_cmdref; | |
116 | uda.uda_ca.ca_cmddsc=(int)&ubauda->uda_cmd.mscp_cmdref; | 116 | uda.uda_ca.ca_cmddsc=(int)&ubauda->uda_cmd.mscp_cmdref; | |
117 | uda.uda_cmd.mscp_un.un_seq.seq_addr = (long *)&uda.uda_ca.ca_cmddsc; | 117 | uda.uda_cmd.mscp_un.un_seq.seq_addr = (long *)&uda.uda_ca.ca_cmddsc; | |
118 | uda.uda_rsp.mscp_un.un_seq.seq_addr = (long *)&uda.uda_ca.ca_rspdsc; | 118 | uda.uda_rsp.mscp_un.un_seq.seq_addr = (long *)&uda.uda_ca.ca_rspdsc; | |
119 | uda.uda_cmd.mscp_vcid = 1; | 119 | uda.uda_cmd.mscp_vcid = 1; | |
120 | uda.uda_cmd.mscp_un.un_sccc.sccc_ctlrflags = 0; | 120 | uda.uda_cmd.mscp_un.un_sccc.sccc_ctlrflags = 0; | |
121 | 121 | |||
122 | command(M_OP_SETCTLRC, 0); | 122 | command(M_OP_SETCTLRC, 0); | |
123 | uda.uda_cmd.mscp_unit=ra->unit; | 123 | uda.uda_cmd.mscp_unit=ra->unit; | |
124 | command(M_OP_ONLINE, 0); | 124 | command(M_OP_ONLINE, 0); | |
125 | 125 | |||
126 | if (part) { | 126 | if (part) { | |
127 | uda.uda_cmd.mscp_un.un_seq.seq_buffer = part; | 127 | uda.uda_cmd.mscp_un.un_seq.seq_buffer = part; | |
128 | command(M_OP_POS, 0); | 128 | command(M_OP_POS, 0); | |
129 | uda.uda_cmd.mscp_un.un_seq.seq_buffer = 0; | 129 | uda.uda_cmd.mscp_un.un_seq.seq_buffer = 0; | |
130 | } | 130 | } | |
131 | 131 | |||
132 | f->f_devdata=(void *)ra; | 132 | f->f_devdata=(void *)ra; | |
133 | return(0); | 133 | return(0); | |
134 | } | 134 | } | |
135 | 135 | |||
136 | static | 136 | static | |
137 | command(cmd, arg) | 137 | command(cmd, arg) | |
138 | { | 138 | { | |
139 | volatile int hej; | 139 | volatile int hej; | |
140 | 140 | |||
141 | uda.uda_cmd.mscp_opcode = cmd; | 141 | uda.uda_cmd.mscp_opcode = cmd; | |
142 | uda.uda_cmd.mscp_modifier = arg; | 142 | uda.uda_cmd.mscp_modifier = arg; | |
143 | 143 | |||
144 | uda.uda_cmd.mscp_msglen = MSCP_MSGLEN; | 144 | uda.uda_cmd.mscp_msglen = MSCP_MSGLEN; | |
145 | uda.uda_rsp.mscp_msglen = MSCP_MSGLEN; | 145 | uda.uda_rsp.mscp_msglen = MSCP_MSGLEN; | |
146 | 146 | |||
147 | uda.uda_ca.ca_rspdsc |= MSCP_OWN|MSCP_INT; | 147 | uda.uda_ca.ca_rspdsc |= MSCP_OWN|MSCP_INT; | |
148 | uda.uda_ca.ca_cmddsc |= MSCP_OWN|MSCP_INT; | 148 | uda.uda_ca.ca_cmddsc |= MSCP_OWN|MSCP_INT; | |
149 | hej = udacsr->udaip; | 149 | hej = udacsr->udaip; | |
150 | while (uda.uda_ca.ca_rspdsc < 0) { | 150 | while (uda.uda_ca.ca_rspdsc < 0) { | |
151 | if (uda.uda_ca.ca_cmdint) | 151 | if (uda.uda_ca.ca_cmdint) | |
152 | uda.uda_ca.ca_cmdint = 0; | 152 | uda.uda_ca.ca_cmdint = 0; | |
153 | } | 153 | } | |
154 | 154 | |||
155 | } | 155 | } | |
156 | 156 | |||
157 | tmscpstrategy(struct ra_softc *ra, int func, daddr_t dblk, u_int size, char *buf, u_int *rsize) | 157 | tmscpstrategy(struct ra_softc *ra, int func, daddr_t dblk, u_int size, char *buf, u_int *rsize) | |
158 | { | 158 | { | |
159 | u_int i,j,pfnum, mapnr, nsize, bn, cn, sn, tn; | 159 | u_int i,j,pfnum, mapnr, nsize, bn, cn, sn, tn; | |
160 | volatile struct udadevice *udadev=(void*)ra->udaddr; | 160 | volatile struct udadevice *udadev=(void*)ra->udaddr; | |
161 | volatile u_int *ptmapp = (u_int *)ra->ubaddr + 512; | 161 | volatile u_int *ptmapp = (u_int *)ra->ubaddr + 512; | |
162 | volatile int hej; | 162 | volatile int hej; | |
163 | 163 | |||
164 | pfnum=(u_int)buf>>VAX_PGSHIFT; | 164 | pfnum=(u_int)buf>>VAX_PGSHIFT; | |
165 | 165 | |||
166 | for(mapnr=0, nsize=size;(nsize+VAX_NBPG)>0;nsize-=VAX_NBPG) | 166 | for(mapnr=0, nsize=size;(nsize+VAX_NBPG)>0;nsize-=VAX_NBPG) | |
167 | ptmapp[mapnr++]=PG_V|pfnum++; | 167 | ptmapp[mapnr++]=PG_V|pfnum++; | |
168 | 168 | |||
169 | /* | 169 | /* | |
170 | * First position tape. Remember where we are. | 170 | * First position tape. Remember where we are. | |
171 | */ | 171 | */ | |
172 | if (dblk < curblock) { | 172 | if (dblk < curblock) { | |
173 | uda.uda_cmd.mscp_seq.seq_bytecount = curblock - dblk; | 173 | uda.uda_cmd.mscp_seq.seq_bytecount = curblock - dblk; | |
174 | command(M_OP_POS, 12); /* 12 == step block backward */ | 174 | command(M_OP_POS, 12); /* 12 == step block backward */ | |
175 | } else { | 175 | } else { | |
176 | uda.uda_cmd.mscp_seq.seq_bytecount = dblk - curblock; | 176 | uda.uda_cmd.mscp_seq.seq_bytecount = dblk - curblock; | |
177 | command(M_OP_POS, 4); /* 4 == step block forward */ | 177 | command(M_OP_POS, 4); /* 4 == step block forward */ | |
178 | } | 178 | } | |
179 | curblock = size/512 + dblk; | 179 | curblock = size/512 + dblk; | |
180 | 180 | |||
181 | /* | 181 | /* | |
182 | * Read in the number of blocks we need. | 182 | * Read in the number of blocks we need. | |
183 | * Why doesn't read of multiple blocks work????? | 183 | * Why doesn't read of multiple blocks work????? | |
184 | */ | 184 | */ | |
185 | for (i = 0 ; i < size/512 ; i++) { | 185 | for (i = 0 ; i < size/512 ; i++) { | |
186 | uda.uda_cmd.mscp_seq.seq_lbn = 1; | 186 | uda.uda_cmd.mscp_seq.seq_lbn = 1; | |
187 | uda.uda_cmd.mscp_seq.seq_bytecount = 512; | 187 | uda.uda_cmd.mscp_seq.seq_bytecount = 512; | |
188 | uda.uda_cmd.mscp_seq.seq_buffer = | 188 | uda.uda_cmd.mscp_seq.seq_buffer = | |
189 | (((u_int)buf) & 0x1ff) + i * 512; | 189 | (((u_int)buf) & 0x1ff) + i * 512; | |
190 | uda.uda_cmd.mscp_unit = ra->unit; | 190 | uda.uda_cmd.mscp_unit = ra->unit; | |
191 | command(M_OP_READ, 0); | 191 | command(M_OP_READ, 0); | |
192 | } | 192 | } | |
193 | 193 | |||
194 | *rsize=size; | 194 | *rsize=size; | |
195 | return 0; | 195 | return 0; | |
196 | } | 196 | } |
--- src/sys/dev/isa/Attic/if_hp.c 2009/03/14 21:04:20 1.47
+++ src/sys/dev/isa/Attic/if_hp.c 2009/03/17 18:19:15 1.48
@@ -1,1012 +1,1012 @@ | @@ -1,1012 +1,1012 @@ | |||
1 | /* $NetBSD: if_hp.c,v 1.47 2009/03/14 21:04:20 dsl Exp $ */ | 1 | /* $NetBSD: if_hp.c,v 1.48 2009/03/17 18:19:15 dsl Exp $ */ | |
2 | 2 | |||
3 | /* XXX THIS DRIVER IS BROKEN. IT WILL NOT EVEN COMPILE. */ | 3 | /* XXX THIS DRIVER IS BROKEN. IT WILL NOT EVEN COMPILE. */ | |
4 | 4 | |||
5 | /*- | 5 | /*- | |
6 | * Copyright (c) 1990 The Regents of the University of California. | 6 | * Copyright (c) 1990 The Regents of the University of California. | |
7 | * All rights reserved. | 7 | * All rights reserved. | |
8 | * | 8 | * | |
9 | * Redistribution and use in source and binary forms, with or without | 9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | 10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | 11 | * are met: | |
12 | * 1. Redistributions of source code must retain the above copyright | 12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | 13 | * notice, this list of conditions and the following disclaimer. | |
14 | * 2. Redistributions in binary form must reproduce the above copyright | 14 | * 2. Redistributions in binary form must reproduce the above copyright | |
15 | * notice, this list of conditions and the following disclaimer in the | 15 | * notice, this list of conditions and the following disclaimer in the | |
16 | * documentation and/or other materials provided with the distribution. | 16 | * documentation and/or other materials provided with the distribution. | |
17 | * 3. Neither the name of the University nor the names of its contributors | 17 | * 3. Neither the name of the University nor the names of its contributors | |
18 | * may be used to endorse or promote products derived from this software | 18 | * may be used to endorse or promote products derived from this software | |
19 | * without specific prior written permission. | 19 | * without specific prior written permission. | |
20 | * | 20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | 21 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
31 | * SUCH DAMAGE. | 31 | * SUCH DAMAGE. | |
32 | */ | 32 | */ | |
33 | 33 | |||
34 | /*- | 34 | /*- | |
35 | * Copyright (c) 1990, 1991 William F. Jolitz. | 35 | * Copyright (c) 1990, 1991 William F. Jolitz. | |
36 | * | 36 | * | |
37 | * Redistribution and use in source and binary forms, with or without | 37 | * Redistribution and use in source and binary forms, with or without | |
38 | * modification, are permitted provided that the following conditions | 38 | * modification, are permitted provided that the following conditions | |
39 | * are met: | 39 | * are met: | |
40 | * 1. Redistributions of source code must retain the above copyright | 40 | * 1. Redistributions of source code must retain the above copyright | |
41 | * notice, this list of conditions and the following disclaimer. | 41 | * notice, this list of conditions and the following disclaimer. | |
42 | * 2. Redistributions in binary form must reproduce the above copyright | 42 | * 2. Redistributions in binary form must reproduce the above copyright | |
43 | * notice, this list of conditions and the following disclaimer in the | 43 | * notice, this list of conditions and the following disclaimer in the | |
44 | * documentation and/or other materials provided with the distribution. | 44 | * documentation and/or other materials provided with the distribution. | |
45 | * 3. All advertising materials mentioning features or use of this software | 45 | * 3. All advertising materials mentioning features or use of this software | |
46 | * must display the following acknowledgement: | 46 | * must display the following acknowledgement: | |
47 | * This product includes software developed by the University of | 47 | * This product includes software developed by the University of | |
48 | * California, Berkeley and its contributors. | 48 | * California, Berkeley and its contributors. | |
49 | * 4. Neither the name of the University nor the names of its contributors | 49 | * 4. Neither the name of the University nor the names of its contributors | |
50 | * may be used to endorse or promote products derived from this software | 50 | * may be used to endorse or promote products derived from this software | |
51 | * without specific prior written permission. | 51 | * without specific prior written permission. | |
52 | * | 52 | * | |
53 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | 53 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
54 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 54 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
55 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 55 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
56 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 56 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
57 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 57 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
58 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 58 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
59 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 59 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
60 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 60 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
61 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 61 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
62 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 62 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
63 | * SUCH DAMAGE. | 63 | * SUCH DAMAGE. | |
64 | */ | 64 | */ | |
65 | 65 | |||
66 | /* | 66 | /* | |
67 | * HP LAN Ethernet driver | 67 | * HP LAN Ethernet driver | |
68 | * | 68 | * | |
69 | * Parts inspired from Tim Tucker's if_wd driver for the wd8003, | 69 | * Parts inspired from Tim Tucker's if_wd driver for the wd8003, | |
70 | * insight on the ne2000 gained from Robert Clements PC/FTP driver. | 70 | * insight on the ne2000 gained from Robert Clements PC/FTP driver. | |
71 | * | 71 | * | |
72 | * receive bottom end totally rewritten by Curt Mayer, Dec 1992. | 72 | * receive bottom end totally rewritten by Curt Mayer, Dec 1992. | |
73 | * no longer loses back to back packets. | 73 | * no longer loses back to back packets. | |
74 | * note to driver writers: RTFM! | 74 | * note to driver writers: RTFM! | |
75 | * | 75 | * | |
76 | * hooks for packet filter added by Charles Hannum, 29DEC1992. | 76 | * hooks for packet filter added by Charles Hannum, 29DEC1992. | |
77 | * | 77 | * | |
78 | * Mostly rewritten for HP-labelled EISA controllers by Charles Hannum, | 78 | * Mostly rewritten for HP-labelled EISA controllers by Charles Hannum, | |
79 | * 18JAN1993. | 79 | * 18JAN1993. | |
80 | */ | 80 | */ | |
81 | 81 | |||
82 | #include <sys/cdefs.h> | 82 | #include <sys/cdefs.h> | |
83 | __KERNEL_RCSID(0, "$NetBSD: if_hp.c,v 1.47 2009/03/14 21:04:20 dsl Exp $"); | 83 | __KERNEL_RCSID(0, "$NetBSD: if_hp.c,v 1.48 2009/03/17 18:19:15 dsl Exp $"); | |
84 | 84 | |||
85 | #include "hp.h" | 85 | #include "hp.h" | |
86 | #if NHP > 0 | 86 | #if NHP > 0 | |
87 | 87 | |||
88 | #include "opt_inet.h" | 88 | #include "opt_inet.h" | |
89 | #include "rnd.h" | 89 | #include "rnd.h" | |
90 | 90 | |||
91 | #include <sys/param.h> | 91 | #include <sys/param.h> | |
92 | #include <sys/systm.h> | 92 | #include <sys/systm.h> | |
93 | #include <sys/mbuf.h> | 93 | #include <sys/mbuf.h> | |
94 | #include <sys/buf.h> | 94 | #include <sys/buf.h> | |
95 | #include <sys/protosw.h> | 95 | #include <sys/protosw.h> | |
96 | #include <sys/socket.h> | 96 | #include <sys/socket.h> | |
97 | #include <sys/ioctl.h> | 97 | #include <sys/ioctl.h> | |
98 | #include <sys/errno.h> | 98 | #include <sys/errno.h> | |
99 | #include <sys/syslog.h> | 99 | #include <sys/syslog.h> | |
100 | #if NRND > 0 | 100 | #if NRND > 0 | |
101 | #include <sys/rnd.h> | 101 | #include <sys/rnd.h> | |
102 | #endif | 102 | #endif | |
103 | 103 | |||
104 | #include <net/if.h> | 104 | #include <net/if.h> | |
105 | #include <net/if_ether.h> | 105 | #include <net/if_ether.h> | |
106 | 106 | |||
107 | #ifdef INET | 107 | #ifdef INET | |
108 | #include <netinet/in.h> | 108 | #include <netinet/in.h> | |
109 | #include <netinet/in_systm.h> | 109 | #include <netinet/in_systm.h> | |
110 | #include <netinet/in_var.h> | 110 | #include <netinet/in_var.h> | |
111 | #include <netinet/ip.h> | 111 | #include <netinet/ip.h> | |
112 | #include <netinet/if_inarp.h> | 112 | #include <netinet/if_inarp.h> | |
113 | #endif | 113 | #endif | |
114 | 114 | |||
115 | 115 | |||
116 | #include "bpfilter.h" | 116 | #include "bpfilter.h" | |
117 | #if NBPFILTER > 0 | 117 | #if NBPFILTER > 0 | |
118 | #include <sys/select.h> | 118 | #include <sys/select.h> | |
119 | #include <net/bpf.h> | 119 | #include <net/bpf.h> | |
120 | #include <net/bpfdesc.h> | 120 | #include <net/bpfdesc.h> | |
121 | #endif | 121 | #endif | |
122 | 122 | |||
123 | #include <sys/cpu.h> | 123 | #include <sys/cpu.h> | |
124 | #include <machine/pio.h> | 124 | #include <machine/pio.h> | |
125 | 125 | |||
126 | #include <i386/isa/isa_device.h> /* XXX BROKEN */ | 126 | #include <i386/isa/isa_device.h> /* XXX BROKEN */ | |
127 | #include <dev/isa/if_nereg.h> | 127 | #include <dev/isa/if_nereg.h> | |
128 | #include <i386/isa/icu.h> /* XXX BROKEN */ | 128 | #include <i386/isa/icu.h> /* XXX BROKEN */ | |
129 | 129 | |||
130 | int hpprobe(), hpattach(), hpintr(); | 130 | int hpprobe(), hpattach(), hpintr(); | |
131 | int hpstart(), hpinit(), ether_output(), hpioctl(); | 131 | int hpstart(), hpinit(), ether_output(), hpioctl(); | |
132 | 132 | |||
133 | struct isa_driver hpdriver = | 133 | struct isa_driver hpdriver = | |
134 | { | 134 | { | |
135 | hpprobe, hpattach, "hp", | 135 | hpprobe, hpattach, "hp", | |
136 | }; | 136 | }; | |
137 | 137 | |||
138 | struct mbuf *hpget(); | 138 | struct mbuf *hpget(); | |
139 | 139 | |||
140 | /* | 140 | /* | |
141 | * Ethernet software status per interface. | 141 | * Ethernet software status per interface. | |
142 | * | 142 | * | |
143 | * Each interface is referenced by a network interface structure, | 143 | * Each interface is referenced by a network interface structure, | |
144 | * ns_if, which the routing code uses to locate the interface. | 144 | * ns_if, which the routing code uses to locate the interface. | |
145 | * This structure contains the output queue for the interface, its address, ... | 145 | * This structure contains the output queue for the interface, its address, ... | |
146 | */ | 146 | */ | |
147 | struct hp_softc { | 147 | struct hp_softc { | |
148 | struct ethercom ns_ec; /* Ethernet common part */ | 148 | struct ethercom ns_ec; /* Ethernet common part */ | |
149 | #define ns_if ns_ac.ac_if /* network-visible interface */ | 149 | #define ns_if ns_ac.ac_if /* network-visible interface */ | |
150 | int ns_flags; | 150 | int ns_flags; | |
151 | #define DSF_LOCK 1 /* block re-entering enstart */ | 151 | #define DSF_LOCK 1 /* block re-entering enstart */ | |
152 | int ns_oactive; | 152 | int ns_oactive; | |
153 | int ns_mask; | 153 | int ns_mask; | |
154 | struct prhdr ns_ph; /* hardware header of incoming packet */ | 154 | struct prhdr ns_ph; /* hardware header of incoming packet */ | |
155 | u_char ns_pb[2048]; | 155 | u_char ns_pb[2048]; | |
156 | u_char ns_txstart; /* transmitter buffer start */ | 156 | u_char ns_txstart; /* transmitter buffer start */ | |
157 | u_char ns_rxstart; /* receiver buffer start */ | 157 | u_char ns_rxstart; /* receiver buffer start */ | |
158 | u_char ns_rxend; /* receiver buffer end */ | 158 | u_char ns_rxend; /* receiver buffer end */ | |
159 | u_char hp_type; /* HP board type */ | 159 | u_char hp_type; /* HP board type */ | |
160 | u_char hp_irq; /* interrupt vector */ | 160 | u_char hp_irq; /* interrupt vector */ | |
161 | short ns_port; /* i/o port base */ | 161 | short ns_port; /* i/o port base */ | |
162 | short ns_mode; /* word/byte mode */ | 162 | short ns_mode; /* word/byte mode */ | |
163 | short ns_rcr; | 163 | short ns_rcr; | |
164 | #if NBPFILTER > 0 | 164 | #if NBPFILTER > 0 | |
165 | void *ns_bpf; | 165 | void *ns_bpf; | |
166 | #endif | 166 | #endif | |
167 | u_int8_t ns_addrp[ETHER_ADDR_LEN]; /* hardware Ethernet address */ | 167 | u_int8_t ns_addrp[ETHER_ADDR_LEN]; /* hardware Ethernet address */ | |
168 | 168 | |||
169 | #if NRND > 0 | 169 | #if NRND > 0 | |
170 | rndsource_element_t rnd_source; | 170 | rndsource_element_t rnd_source; | |
171 | #endif | 171 | #endif | |
172 | } | 172 | } | |
173 | hp_softc[NHP]; | 173 | hp_softc[NHP]; | |
174 | #define ENBUFSIZE (sizeof(struct ether_header) + ETHERMTU + 2 + ETHER_MIN_LEN) | 174 | #define ENBUFSIZE (sizeof(struct ether_header) + ETHERMTU + 2 + ETHER_MIN_LEN) | |
175 | 175 | |||
176 | #define PAT(n) (0xa55a + 37*(n)) | 176 | #define PAT(n) (0xa55a + 37*(n)) | |
177 | 177 | |||
178 | u_short boarddata[16]; | 178 | u_short boarddata[16]; | |
179 | 179 | |||
180 | #define hp_option (-8) | 180 | #define hp_option (-8) | |
181 | #define hp_data (-4) | 181 | #define hp_data (-4) | |
182 | #define HP_RUN (0x01) | 182 | #define HP_RUN (0x01) | |
183 | #define HP_DATA (0x10) | 183 | #define HP_DATA (0x10) | |
184 | 184 | |||
185 | hpprobe(struct isa_device *dvp) | 185 | hpprobe(struct isa_device *dvp) | |
186 | { | 186 | { | |
187 | int val, i, s, sum, pat; | 187 | int val, i, s, sum, pat; | |
188 | struct hp_softc *ns = &hp_softc[0]; | 188 | struct hp_softc *ns = &hp_softc[0]; | |
189 | int hpc; | 189 | int hpc; | |
190 | 190 | |||
191 | #ifdef lint | 191 | #ifdef lint | |
192 | hpintr(0); | 192 | hpintr(0); | |
193 | #endif | 193 | #endif | |
194 | 194 | |||
195 | hpc = (ns->ns_port = dvp->id_iobase + 0x10); | 195 | hpc = (ns->ns_port = dvp->id_iobase + 0x10); | |
196 | s = splnet(); | 196 | s = splnet(); | |
197 | 197 | |||
198 | ns->hp_irq = ffs(dvp->id_irq) - 1; | 198 | ns->hp_irq = ffs(dvp->id_irq) - 1; | |
199 | 199 | |||
200 | /* Extract board address */ | 200 | /* Extract board address */ | |
201 | for (i = 0; i < 6; i++) | 201 | for (i = 0; i < 6; i++) | |
202 | ns->ns_addrp[i] = inb(hpc - 0x10 + i); | 202 | ns->ns_addrp[i] = inb(hpc - 0x10 + i); | |
203 | ns->hp_type = inb(hpc - 0x10 + 7); | 203 | ns->hp_type = inb(hpc - 0x10 + 7); | |
204 | 204 | |||
205 | if (ns->ns_addrp[0] != 0x08 || | 205 | if (ns->ns_addrp[0] != 0x08 || | |
206 | ns->ns_addrp[1] != 0x00 || | 206 | ns->ns_addrp[1] != 0x00 || | |
207 | ns->ns_addrp[2] != 0x09) { | 207 | ns->ns_addrp[2] != 0x09) { | |
208 | splx(s); | 208 | splx(s); | |
209 | return 0; | 209 | return 0; | |
210 | } | 210 | } | |
211 | /* Word Transfers, Burst Mode Select, Fifo at 8 bytes */ | 211 | /* Word Transfers, Burst Mode Select, Fifo at 8 bytes */ | |
212 | /* On this board, WTS means 32-bit transfers, which is still | 212 | /* On this board, WTS means 32-bit transfers, which is still | |
213 | * experimental. - mycroft, 18JAN93 */ | 213 | * experimental. - mycroft, 18JAN93 */ | |
214 | #ifdef HP_32BIT | 214 | #ifdef HP_32BIT | |
215 | ns->ns_mode = DSDC_WTS | DSDC_BMS | DSDC_FT1; | 215 | ns->ns_mode = DSDC_WTS | DSDC_BMS | DSDC_FT1; | |
216 | #else | 216 | #else | |
217 | ns->ns_mode = DSDC_BMS | DSDC_FT1; | 217 | ns->ns_mode = DSDC_BMS | DSDC_FT1; | |
218 | #endif | 218 | #endif | |
219 | ns->ns_txstart = 0 * 1024 / DS_PGSIZE; | 219 | ns->ns_txstart = 0 * 1024 / DS_PGSIZE; | |
220 | ns->ns_rxend = 32 * 1024 / DS_PGSIZE; | 220 | ns->ns_rxend = 32 * 1024 / DS_PGSIZE; | |
221 | 221 | |||
222 | ns->ns_rxstart = ns->ns_txstart + (PKTSZ / DS_PGSIZE); | 222 | ns->ns_rxstart = ns->ns_txstart + (PKTSZ / DS_PGSIZE); | |
223 | 223 | |||
224 | outb(hpc + hp_option, HP_RUN); | 224 | outb(hpc + hp_option, HP_RUN); | |
225 | 225 | |||
226 | #if 0 | 226 | #if 0 | |
227 | outb(hpc + ds0_isr, 0xff); | 227 | outb(hpc + ds0_isr, 0xff); | |
228 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_STOP); | 228 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_STOP); | |
229 | delay(1000); | 229 | delay(1000); | |
230 | 230 | |||
231 | /* Check cmd reg and fail if not right */ | 231 | /* Check cmd reg and fail if not right */ | |
232 | if ((i = inb(hpc + ds_cmd)) != (DSCM_NODMA | DSCM_PG0 | DSCM_STOP)) { | 232 | if ((i = inb(hpc + ds_cmd)) != (DSCM_NODMA | DSCM_PG0 | DSCM_STOP)) { | |
233 | splx(s); | 233 | splx(s); | |
234 | return (0); | 234 | return (0); | |
235 | } | 235 | } | |
236 | #endif | 236 | #endif | |
237 | 237 | |||
238 | outb(hpc + hp_option, 0); | 238 | outb(hpc + hp_option, 0); | |
239 | 239 | |||
240 | splx(s); | 240 | splx(s); | |
241 | return (32); | 241 | return (32); | |
242 | } | 242 | } | |
243 | /* | 243 | /* | |
244 | * Fetch from onboard ROM/RAM | 244 | * Fetch from onboard ROM/RAM | |
245 | */ | 245 | */ | |
246 | hpfetch(struct hp_softc *ns, void *up, ad, len) | 246 | hpfetch(struct hp_softc *ns, void *up, int ad, int len) | |
247 | { | 247 | { | |
248 | u_char cmd; | 248 | u_char cmd; | |
249 | int hpc = ns->ns_port; | 249 | int hpc = ns->ns_port; | |
250 | int counter = 100000; | 250 | int counter = 100000; | |
251 | 251 | |||
252 | outb(hpc + hp_option, inb(hpc + hp_option) | HP_DATA); | 252 | outb(hpc + hp_option, inb(hpc + hp_option) | HP_DATA); | |
253 | 253 | |||
254 | cmd = inb(hpc + ds_cmd); | 254 | cmd = inb(hpc + ds_cmd); | |
255 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START); | 255 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START); | |
256 | 256 | |||
257 | /* Setup remote DMA */ | 257 | /* Setup remote DMA */ | |
258 | outb(hpc + ds0_isr, DSIS_RDC); | 258 | outb(hpc + ds0_isr, DSIS_RDC); | |
259 | 259 | |||
260 | if (ns->ns_mode & DSDC_WTS) | 260 | if (ns->ns_mode & DSDC_WTS) | |
261 | len = (len + 3) & ~3; | 261 | len = (len + 3) & ~3; | |
262 | else | 262 | else | |
263 | len = (len + 1) & ~1; | 263 | len = (len + 1) & ~1; | |
264 | 264 | |||
265 | outb(hpc + ds0_rbcr0, len); | 265 | outb(hpc + ds0_rbcr0, len); | |
266 | outb(hpc + ds0_rbcr1, len >> 8); | 266 | outb(hpc + ds0_rbcr1, len >> 8); | |
267 | outb(hpc + ds0_rsar0, ad); | 267 | outb(hpc + ds0_rsar0, ad); | |
268 | outb(hpc + ds0_rsar1, ad >> 8); | 268 | outb(hpc + ds0_rsar1, ad >> 8); | |
269 | 269 | |||
270 | #ifdef HP_DEBUG | 270 | #ifdef HP_DEBUG | |
271 | printf("hpfetch: len=%d ioaddr=0x%03x addr=0x%04x option=0x%02x %d-bit\n", | 271 | printf("hpfetch: len=%d ioaddr=0x%03x addr=0x%04x option=0x%02x %d-bit\n", | |
272 | len, hpc + hp_data, ad, inb(hpc + hp_option), | 272 | len, hpc + hp_data, ad, inb(hpc + hp_option), | |
273 | ns->ns_mode & DSDC_WTS ? 32 : 16); | 273 | ns->ns_mode & DSDC_WTS ? 32 : 16); | |
274 | printf("hpfetch: cmd=0x%02x isr=0x%02x ", | 274 | printf("hpfetch: cmd=0x%02x isr=0x%02x ", | |
275 | inb(hpc + ds_cmd), inb(hpc + ds0_isr)); | 275 | inb(hpc + ds_cmd), inb(hpc + ds0_isr)); | |
276 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG2 | DSCM_START); | 276 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG2 | DSCM_START); | |
277 | printf("imr=0x%02x rcr=0x%02x tcr=0x%02x dcr=0x%02x\n", | 277 | printf("imr=0x%02x rcr=0x%02x tcr=0x%02x dcr=0x%02x\n", | |
278 | inb(hpc + ds0_imr), inb(hpc + ds0_rcr), inb(hpc + ds0_tcr), | 278 | inb(hpc + ds0_imr), inb(hpc + ds0_rcr), inb(hpc + ds0_tcr), | |
279 | inb(hpc + ds0_dcr)); | 279 | inb(hpc + ds0_dcr)); | |
280 | #endif | 280 | #endif | |
281 | 281 | |||
282 | /* Execute & extract from card */ | 282 | /* Execute & extract from card */ | |
283 | outb(hpc + ds_cmd, DSCM_RREAD | DSCM_PG0 | DSCM_START); | 283 | outb(hpc + ds_cmd, DSCM_RREAD | DSCM_PG0 | DSCM_START); | |
284 | 284 | |||
285 | #ifdef HP_32BIT | 285 | #ifdef HP_32BIT | |
286 | if (ns->ns_mode & DSDC_WTS) | 286 | if (ns->ns_mode & DSDC_WTS) | |
287 | len = (void *) insd(hpc + hp_data, up, len >> 2) - up; | 287 | len = (void *) insd(hpc + hp_data, up, len >> 2) - up; | |
288 | else | 288 | else | |
289 | #endif | 289 | #endif | |
290 | len = (void *) insw(hpc + hp_data, up, len >> 1) - up; | 290 | len = (void *) insw(hpc + hp_data, up, len >> 1) - up; | |
291 | 291 | |||
292 | #ifdef HP_DEBUG | 292 | #ifdef HP_DEBUG | |
293 | printf("hpfetch: done len=%d\n", len); | 293 | printf("hpfetch: done len=%d\n", len); | |
294 | #endif | 294 | #endif | |
295 | 295 | |||
296 | /* Wait till done, then shutdown feature */ | 296 | /* Wait till done, then shutdown feature */ | |
297 | while ((inb(hpc + ds0_isr) & DSIS_RDC) == 0 && counter-- > 0); | 297 | while ((inb(hpc + ds0_isr) & DSIS_RDC) == 0 && counter-- > 0); | |
298 | outb(hpc + ds0_isr, DSIS_RDC); | 298 | outb(hpc + ds0_isr, DSIS_RDC); | |
299 | outb(hpc + ds_cmd, cmd); | 299 | outb(hpc + ds_cmd, cmd); | |
300 | 300 | |||
301 | outb(hpc + hp_option, inb(hpc + hp_option) & ~HP_DATA); | 301 | outb(hpc + hp_option, inb(hpc + hp_option) & ~HP_DATA); | |
302 | } | 302 | } | |
303 | /* | 303 | /* | |
304 | * Put to onboard RAM | 304 | * Put to onboard RAM | |
305 | */ | 305 | */ | |
306 | hpput(struct hp_softc *ns, void *up, ad, len) | 306 | hpput(struct hp_softc *ns, void *up, int ad, int len) | |
307 | { | 307 | { | |
308 | u_char cmd; | 308 | u_char cmd; | |
309 | int hpc = ns->ns_port; | 309 | int hpc = ns->ns_port; | |
310 | int counter = 100000; | 310 | int counter = 100000; | |
311 | 311 | |||
312 | outb(hpc + hp_option, inb(hpc + hp_option) | HP_DATA); | 312 | outb(hpc + hp_option, inb(hpc + hp_option) | HP_DATA); | |
313 | 313 | |||
314 | cmd = inb(hpc + ds_cmd); | 314 | cmd = inb(hpc + ds_cmd); | |
315 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START); | 315 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START); | |
316 | 316 | |||
317 | /* Setup for remote DMA */ | 317 | /* Setup for remote DMA */ | |
318 | outb(hpc + ds0_isr, DSIS_RDC); | 318 | outb(hpc + ds0_isr, DSIS_RDC); | |
319 | 319 | |||
320 | if (ns->ns_mode & DSDC_WTS) | 320 | if (ns->ns_mode & DSDC_WTS) | |
321 | len = (len + 3) & ~3; | 321 | len = (len + 3) & ~3; | |
322 | else | 322 | else | |
323 | len = (len + 1) & ~1; | 323 | len = (len + 1) & ~1; | |
324 | 324 | |||
325 | #ifdef HP_DEBUG | 325 | #ifdef HP_DEBUG | |
326 | printf("hpput: len=%d ioaddr=0x%03x addr=0x%04x option=0x%02x %d-bit\n", | 326 | printf("hpput: len=%d ioaddr=0x%03x addr=0x%04x option=0x%02x %d-bit\n", | |
327 | len, hpc + hp_data, ad, inb(hpc + hp_option), | 327 | len, hpc + hp_data, ad, inb(hpc + hp_option), | |
328 | ns->ns_mode & DSDC_WTS ? 32 : 16); | 328 | ns->ns_mode & DSDC_WTS ? 32 : 16); | |
329 | printf("hpput: cmd=0x%02x isr=0x%02x ", | 329 | printf("hpput: cmd=0x%02x isr=0x%02x ", | |
330 | inb(hpc + ds_cmd), inb(hpc + ds0_isr)); | 330 | inb(hpc + ds_cmd), inb(hpc + ds0_isr)); | |
331 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG2 | DSCM_START); | 331 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG2 | DSCM_START); | |
332 | printf("imr=0x%02x rcr=0x%02x tcr=0x%02x dcr=0x%02x\n", | 332 | printf("imr=0x%02x rcr=0x%02x tcr=0x%02x dcr=0x%02x\n", | |
333 | inb(hpc + ds0_imr), inb(hpc + ds0_rcr), inb(hpc + ds0_tcr), | 333 | inb(hpc + ds0_imr), inb(hpc + ds0_rcr), inb(hpc + ds0_tcr), | |
334 | inb(hpc + ds0_dcr)); | 334 | inb(hpc + ds0_dcr)); | |
335 | { | 335 | { | |
336 | unsigned char *p = (unsigned char *) up; | 336 | unsigned char *p = (unsigned char *) up; | |
337 | int n = len; | 337 | int n = len; | |
338 | printf("hpput:"); | 338 | printf("hpput:"); | |
339 | while (n--) | 339 | while (n--) | |
340 | printf(" %02x", *(p++)); | 340 | printf(" %02x", *(p++)); | |
341 | printf("\n"); | 341 | printf("\n"); | |
342 | } | 342 | } | |
343 | #endif | 343 | #endif | |
344 | 344 | |||
345 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START); | 345 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START); | |
346 | outb(hpc + ds0_rbcr0, 0xff); | 346 | outb(hpc + ds0_rbcr0, 0xff); | |
347 | outb(hpc + ds_cmd, DSCM_RREAD | DSCM_PG0 | DSCM_START); | 347 | outb(hpc + ds_cmd, DSCM_RREAD | DSCM_PG0 | DSCM_START); | |
348 | 348 | |||
349 | outb(hpc + ds0_rbcr0, len); | 349 | outb(hpc + ds0_rbcr0, len); | |
350 | outb(hpc + ds0_rbcr1, len >> 8); | 350 | outb(hpc + ds0_rbcr1, len >> 8); | |
351 | outb(hpc + ds0_rsar0, ad); | 351 | outb(hpc + ds0_rsar0, ad); | |
352 | outb(hpc + ds0_rsar1, ad >> 8); | 352 | outb(hpc + ds0_rsar1, ad >> 8); | |
353 | 353 | |||
354 | /* Execute & stuff to card */ | 354 | /* Execute & stuff to card */ | |
355 | outb(hpc + ds_cmd, DSCM_RWRITE | DSCM_PG0 | DSCM_START); | 355 | outb(hpc + ds_cmd, DSCM_RWRITE | DSCM_PG0 | DSCM_START); | |
356 | 356 | |||
357 | #ifdef HP_32BIT | 357 | #ifdef HP_32BIT | |
358 | if (ns->ns_mode & DSDC_WTS) | 358 | if (ns->ns_mode & DSDC_WTS) | |
359 | len = (void *) outsd(hpc + hp_data, up, len >> 2) - up; | 359 | len = (void *) outsd(hpc + hp_data, up, len >> 2) - up; | |
360 | else | 360 | else | |
361 | #endif | 361 | #endif | |
362 | len = (void *) outsw(hpc + hp_data, up, len >> 1) - up; | 362 | len = (void *) outsw(hpc + hp_data, up, len >> 1) - up; | |
363 | 363 | |||
364 | #ifdef HP_DEBUG | 364 | #ifdef HP_DEBUG | |
365 | printf("hpput: done len=%d\n", len); | 365 | printf("hpput: done len=%d\n", len); | |
366 | #endif | 366 | #endif | |
367 | 367 | |||
368 | /* Wait till done, then shutdown feature */ | 368 | /* Wait till done, then shutdown feature */ | |
369 | while ((inb(hpc + ds0_isr) & DSIS_RDC) == 0 && counter-- > 0); | 369 | while ((inb(hpc + ds0_isr) & DSIS_RDC) == 0 && counter-- > 0); | |
370 | outb(hpc + ds0_isr, DSIS_RDC); | 370 | outb(hpc + ds0_isr, DSIS_RDC); | |
371 | outb(hpc + ds_cmd, cmd); | 371 | outb(hpc + ds_cmd, cmd); | |
372 | 372 | |||
373 | outb(hpc + hp_option, inb(hpc + hp_option) & ~HP_DATA); | 373 | outb(hpc + hp_option, inb(hpc + hp_option) & ~HP_DATA); | |
374 | } | 374 | } | |
375 | /* | 375 | /* | |
376 | * Reset of interface. | 376 | * Reset of interface. | |
377 | */ | 377 | */ | |
378 | hpreset(int unit, int uban) | 378 | hpreset(int unit, int uban) | |
379 | { | 379 | { | |
380 | struct hp_softc *ns = &hp_softc[unit]; | 380 | struct hp_softc *ns = &hp_softc[unit]; | |
381 | int hpc = ns->ns_port; | 381 | int hpc = ns->ns_port; | |
382 | if (unit >= NHP) | 382 | if (unit >= NHP) | |
383 | return; | 383 | return; | |
384 | printf("hp%d: reset\n", unit); | 384 | printf("hp%d: reset\n", unit); | |
385 | outb(hpc + hp_option, 0); | 385 | outb(hpc + hp_option, 0); | |
386 | ns->ns_flags &= ~DSF_LOCK; | 386 | ns->ns_flags &= ~DSF_LOCK; | |
387 | hpinit(unit); | 387 | hpinit(unit); | |
388 | } | 388 | } | |
389 | 389 | |||
390 | static char * | 390 | static char * | |
391 | hp_id(u_char type) | 391 | hp_id(u_char type) | |
392 | { | 392 | { | |
393 | static struct { | 393 | static struct { | |
394 | u_char type; | 394 | u_char type; | |
395 | char *name; | 395 | char *name; | |
396 | } boards[] = { | 396 | } boards[] = { | |
397 | { | 397 | { | |
398 | 0x00, "hp27240" | 398 | 0x00, "hp27240" | |
399 | }, { | 399 | }, { | |
400 | 0x10, "hp24240" | 400 | 0x10, "hp24240" | |
401 | }, { | 401 | }, { | |
402 | 0x01, "hp27245" | 402 | 0x01, "hp27245" | |
403 | }, { | 403 | }, { | |
404 | 0x02, "hp27250" | 404 | 0x02, "hp27250" | |
405 | }, { | 405 | }, { | |
406 | 0x81, "hp27247" | 406 | 0x81, "hp27247" | |
407 | }, { | 407 | }, { | |
408 | 0x91, "hp27247r1" | 408 | 0x91, "hp27247r1" | |
409 | } | 409 | } | |
410 | }; | 410 | }; | |
411 | int n = sizeof(boards) / sizeof(boards[0]); | 411 | int n = sizeof(boards) / sizeof(boards[0]); | |
412 | 412 | |||
413 | while (n) | 413 | while (n) | |
414 | if (boards[--n].type == type) | 414 | if (boards[--n].type == type) | |
415 | return boards[n].name; | 415 | return boards[n].name; | |
416 | 416 | |||
417 | return "UNKNOWN"; | 417 | return "UNKNOWN"; | |
418 | } | 418 | } | |
419 | /* | 419 | /* | |
420 | * Interface exists: make available by filling in network interface | 420 | * Interface exists: make available by filling in network interface | |
421 | * record. System will initialize the interface when it is ready | 421 | * record. System will initialize the interface when it is ready | |
422 | * to accept packets. We get the ethernet address here. | 422 | * to accept packets. We get the ethernet address here. | |
423 | */ | 423 | */ | |
424 | hpattach(struct isa_device *dvp) | 424 | hpattach(struct isa_device *dvp) | |
425 | { | 425 | { | |
426 | int unit = dvp->id_unit; | 426 | int unit = dvp->id_unit; | |
427 | struct hp_softc *ns = &hp_softc[unit]; | 427 | struct hp_softc *ns = &hp_softc[unit]; | |
428 | struct ifnet *ifp = &ns->ns_if; | 428 | struct ifnet *ifp = &ns->ns_if; | |
429 | 429 | |||
430 | ifp->if_unit = unit; | 430 | ifp->if_unit = unit; | |
431 | ifp->if_name = hpdriver.name; | 431 | ifp->if_name = hpdriver.name; | |
432 | ifp->if_mtu = ETHERMTU; | 432 | ifp->if_mtu = ETHERMTU; | |
433 | printf("hp%d: %s %d-bit ethernet address %s\n", unit, | 433 | printf("hp%d: %s %d-bit ethernet address %s\n", unit, | |
434 | hp_id(ns->hp_type), ns->ns_mode & DSDC_WTS ? 32 : 16, | 434 | hp_id(ns->hp_type), ns->ns_mode & DSDC_WTS ? 32 : 16, | |
435 | ether_sprintf(ns->ns_addrp)); | 435 | ether_sprintf(ns->ns_addrp)); | |
436 | ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS; | 436 | ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS; | |
437 | ifp->if_output = ether_output; | 437 | ifp->if_output = ether_output; | |
438 | ifp->if_start = hpstart; | 438 | ifp->if_start = hpstart; | |
439 | ifp->if_ioctl = hpioctl; | 439 | ifp->if_ioctl = hpioctl; | |
440 | ifp->if_reset = hpreset; | 440 | ifp->if_reset = hpreset; | |
441 | ifp->if_watchdog = 0; | 441 | ifp->if_watchdog = 0; | |
442 | IFQ_SET_READY(&ifp->if_snd); | 442 | IFQ_SET_READY(&ifp->if_snd); | |
443 | if_attach(ifp); | 443 | if_attach(ifp); | |
444 | 444 | |||
445 | #if NBPFILTER > 0 | 445 | #if NBPFILTER > 0 | |
446 | bpfattach(&ns->ns_bpf, ifp, DLT_EN10MB, | 446 | bpfattach(&ns->ns_bpf, ifp, DLT_EN10MB, | |
447 | sizeof(struct ether_header)); | 447 | sizeof(struct ether_header)); | |
448 | #endif | 448 | #endif | |
449 | 449 | |||
450 | #if NRND > 0 | 450 | #if NRND > 0 | |
451 | rnd_attach_source(&ns->rnd_source, device_xname(&ns->sc_dev), | 451 | rnd_attach_source(&ns->rnd_source, device_xname(&ns->sc_dev), | |
452 | RND_TYPE_NET, 0); | 452 | RND_TYPE_NET, 0); | |
453 | #endif | 453 | #endif | |
454 | 454 | |||
455 | } | 455 | } | |
456 | /* | 456 | /* | |
457 | * Initialization of interface; set up initialization block | 457 | * Initialization of interface; set up initialization block | |
458 | * and transmit/receive descriptor rings. | 458 | * and transmit/receive descriptor rings. | |
459 | */ | 459 | */ | |
460 | hpinit(int unit) | 460 | hpinit(int unit) | |
461 | { | 461 | { | |
462 | struct hp_softc *ns = &hp_softc[unit]; | 462 | struct hp_softc *ns = &hp_softc[unit]; | |
463 | struct ifnet *ifp = &ns->ns_if; | 463 | struct ifnet *ifp = &ns->ns_if; | |
464 | int s; | 464 | int s; | |
465 | int i; | 465 | int i; | |
466 | char *cp; | 466 | char *cp; | |
467 | int hpc = ns->ns_port; | 467 | int hpc = ns->ns_port; | |
468 | 468 | |||
469 | if (IFADDR_EMPTY(ifp)) | 469 | if (IFADDR_EMPTY(ifp)) | |
470 | return; | 470 | return; | |
471 | if (ifp->if_flags & IFF_RUNNING) | 471 | if (ifp->if_flags & IFF_RUNNING) | |
472 | return; | 472 | return; | |
473 | 473 | |||
474 | s = splnet(); | 474 | s = splnet(); | |
475 | 475 | |||
476 | #ifdef HP_DEBUG | 476 | #ifdef HP_DEBUG | |
477 | printf("hpinit: hp%d at 0x%x irq %d\n", unit, hpc, (int) ns->hp_irq); | 477 | printf("hpinit: hp%d at 0x%x irq %d\n", unit, hpc, (int) ns->hp_irq); | |
478 | printf("hpinit: promiscuous mode %s\n", | 478 | printf("hpinit: promiscuous mode %s\n", | |
479 | ns->ns_if.if_flags & IFF_PROMISC ? "on" : "off"); | 479 | ns->ns_if.if_flags & IFF_PROMISC ? "on" : "off"); | |
480 | #endif | 480 | #endif | |
481 | 481 | |||
482 | ns->ns_rcr = (ns->ns_if.if_flags & IFF_BROADCAST ? DSRC_AB : 0) | | 482 | ns->ns_rcr = (ns->ns_if.if_flags & IFF_BROADCAST ? DSRC_AB : 0) | | |
483 | (ns->ns_if.if_flags & IFF_PROMISC ? DSRC_PRO : 0); | 483 | (ns->ns_if.if_flags & IFF_PROMISC ? DSRC_PRO : 0); | |
484 | #ifdef HP_LOG_ERRORS | 484 | #ifdef HP_LOG_ERRORS | |
485 | ns->ns_rcr |= DSRC_SEP; | 485 | ns->ns_rcr |= DSRC_SEP; | |
486 | #endif | 486 | #endif | |
487 | 487 | |||
488 | /* set irq and turn on board */ | 488 | /* set irq and turn on board */ | |
489 | outb(hpc + hp_option, HP_RUN | (ns->hp_irq << 1)); | 489 | outb(hpc + hp_option, HP_RUN | (ns->hp_irq << 1)); | |
490 | 490 | |||
491 | /* init regs */ | 491 | /* init regs */ | |
492 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_STOP); | 492 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_STOP); | |
493 | outb(hpc + ds0_dcr, 0); | 493 | outb(hpc + ds0_dcr, 0); | |
494 | outb(hpc + ds0_rbcr0, 0); | 494 | outb(hpc + ds0_rbcr0, 0); | |
495 | outb(hpc + ds0_rbcr1, 0); | 495 | outb(hpc + ds0_rbcr1, 0); | |
496 | outb(hpc + ds0_rcr, DSRC_MON); | 496 | outb(hpc + ds0_rcr, DSRC_MON); | |
497 | outb(hpc + ds0_tpsr, ns->ns_txstart); | 497 | outb(hpc + ds0_tpsr, ns->ns_txstart); | |
498 | outb(hpc + ds0_imr, 0); | 498 | outb(hpc + ds0_imr, 0); | |
499 | outb(hpc + ds0_tcr, DSTC_LB0); | 499 | outb(hpc + ds0_tcr, DSTC_LB0); | |
500 | outb(hpc + ds0_pstart, ns->ns_rxstart); | 500 | outb(hpc + ds0_pstart, ns->ns_rxstart); | |
501 | outb(hpc + ds0_bnry, ns->ns_rxend - 1); | 501 | outb(hpc + ds0_bnry, ns->ns_rxend - 1); | |
502 | outb(hpc + ds0_pstop, ns->ns_rxend); | 502 | outb(hpc + ds0_pstop, ns->ns_rxend); | |
503 | outb(hpc + ds0_isr, 0xff); | 503 | outb(hpc + ds0_isr, 0xff); | |
504 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG1 | DSCM_STOP); | 504 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG1 | DSCM_STOP); | |
505 | outb(hpc + ds1_curr, ns->ns_rxstart); | 505 | outb(hpc + ds1_curr, ns->ns_rxstart); | |
506 | 506 | |||
507 | /* set physical address on ethernet */ | 507 | /* set physical address on ethernet */ | |
508 | for (i = 0; i < 6; i++) | 508 | for (i = 0; i < 6; i++) | |
509 | outb(hpc + ds1_par0 + i, ns->ns_addrp[i]); | 509 | outb(hpc + ds1_par0 + i, ns->ns_addrp[i]); | |
510 | 510 | |||
511 | /* clr logical address hash filter for now */ | 511 | /* clr logical address hash filter for now */ | |
512 | for (i = 0; i < 8; i++) | 512 | for (i = 0; i < 8; i++) | |
513 | outb(hpc + ds1_mar0 + i, 0xff); | 513 | outb(hpc + ds1_mar0 + i, 0xff); | |
514 | 514 | |||
515 | /* fire it up */ | 515 | /* fire it up */ | |
516 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START); | 516 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START); | |
517 | outb(hpc + ds0_dcr, ns->ns_mode); | 517 | outb(hpc + ds0_dcr, ns->ns_mode); | |
518 | outb(hpc + ds0_rcr, ns->ns_rcr); | 518 | outb(hpc + ds0_rcr, ns->ns_rcr); | |
519 | outb(hpc + ds0_tcr, 0); | 519 | outb(hpc + ds0_tcr, 0); | |
520 | outb(hpc + ds0_imr, 0xff); | 520 | outb(hpc + ds0_imr, 0xff); | |
521 | 521 | |||
522 | ns->ns_if.if_flags |= IFF_RUNNING; | 522 | ns->ns_if.if_flags |= IFF_RUNNING; | |
523 | ns->ns_flags &= ~DSF_LOCK; | 523 | ns->ns_flags &= ~DSF_LOCK; | |
524 | ns->ns_oactive = 0; | 524 | ns->ns_oactive = 0; | |
525 | ns->ns_mask = ~0; | 525 | ns->ns_mask = ~0; | |
526 | hpstart(ifp); | 526 | hpstart(ifp); | |
527 | 527 | |||
528 | #ifdef HP_DEBUG | 528 | #ifdef HP_DEBUG | |
529 | printf("hpinit: done\n", unit, hpc); | 529 | printf("hpinit: done\n", unit, hpc); | |
530 | #endif | 530 | #endif | |
531 | 531 | |||
532 | splx(s); | 532 | splx(s); | |
533 | } | 533 | } | |
534 | /* | 534 | /* | |
535 | * Setup output on interface. | 535 | * Setup output on interface. | |
536 | * Get another datagram to send off of the interface queue, | 536 | * Get another datagram to send off of the interface queue, | |
537 | * and map it to the interface before starting the output. | 537 | * and map it to the interface before starting the output. | |
538 | * called only at splnet or interrupt level. | 538 | * called only at splnet or interrupt level. | |
539 | */ | 539 | */ | |
540 | hpstart(struct ifnet *ifp) | 540 | hpstart(struct ifnet *ifp) | |
541 | { | 541 | { | |
542 | struct hp_softc *ns = &hp_softc[ifp->if_unit]; | 542 | struct hp_softc *ns = &hp_softc[ifp->if_unit]; | |
543 | struct mbuf *m0, *m; | 543 | struct mbuf *m0, *m; | |
544 | int buffer; | 544 | int buffer; | |
545 | int len, i, total; | 545 | int len, i, total; | |
546 | int hpc = ns->ns_port; | 546 | int hpc = ns->ns_port; | |
547 | 547 | |||
548 | /* | 548 | /* | |
549 | * The DS8390 has only one transmit buffer, if it is busy we | 549 | * The DS8390 has only one transmit buffer, if it is busy we | |
550 | * must wait until the transmit interrupt completes. | 550 | * must wait until the transmit interrupt completes. | |
551 | */ | 551 | */ | |
552 | if (ns->ns_flags & DSF_LOCK) | 552 | if (ns->ns_flags & DSF_LOCK) | |
553 | return; | 553 | return; | |
554 | 554 | |||
555 | if (inb(hpc + ds_cmd) & DSCM_TRANS) | 555 | if (inb(hpc + ds_cmd) & DSCM_TRANS) | |
556 | return; | 556 | return; | |
557 | 557 | |||
558 | if ((ns->ns_if.if_flags & IFF_RUNNING) == 0) | 558 | if ((ns->ns_if.if_flags & IFF_RUNNING) == 0) | |
559 | return; | 559 | return; | |
560 | 560 | |||
561 | IFQ_DEQUEUE(&ns->ns_if.if_snd, m); | 561 | IFQ_DEQUEUE(&ns->ns_if.if_snd, m); | |
562 | 562 | |||
563 | if (m == 0) | 563 | if (m == 0) | |
564 | return; | 564 | return; | |
565 | 565 | |||
566 | /* | 566 | /* | |
567 | * Copy the mbuf chain into the transmit buffer | 567 | * Copy the mbuf chain into the transmit buffer | |
568 | */ | 568 | */ | |
569 | 569 | |||
570 | ns->ns_flags |= DSF_LOCK; /* prevent entering hpstart */ | 570 | ns->ns_flags |= DSF_LOCK; /* prevent entering hpstart */ | |
571 | buffer = ns->ns_txstart * DS_PGSIZE; | 571 | buffer = ns->ns_txstart * DS_PGSIZE; | |
572 | i = 0; | 572 | i = 0; | |
573 | total = len = m->m_pkthdr.len; | 573 | total = len = m->m_pkthdr.len; | |
574 | 574 | |||
575 | #ifdef HP_DEBUG | 575 | #ifdef HP_DEBUG | |
576 | printf("hpstart: len=%d\n", len); | 576 | printf("hpstart: len=%d\n", len); | |
577 | #endif | 577 | #endif | |
578 | 578 | |||
579 | #if NBPFILTER > 0 | 579 | #if NBPFILTER > 0 | |
580 | if (ns->ns_bpf) | 580 | if (ns->ns_bpf) | |
581 | bpf_mtap(ns->ns_bpf, m); | 581 | bpf_mtap(ns->ns_bpf, m); | |
582 | #endif | 582 | #endif | |
583 | 583 | |||
584 | for (m0 = m; m != 0;) { | 584 | for (m0 = m; m != 0;) { | |
585 | if (m->m_len & 1 && t > m->m_len) { | 585 | if (m->m_len & 1 && t > m->m_len) { | |
586 | m->m_len -= 1; | 586 | m->m_len -= 1; | |
587 | hpput(ns, mtod(m, void *), buffer, m->m_len); | 587 | hpput(ns, mtod(m, void *), buffer, m->m_len); | |
588 | t -= m->m_len; | 588 | t -= m->m_len; | |
589 | buffer += m->m_len; | 589 | buffer += m->m_len; | |
590 | m->m_data += m->m_len; | 590 | m->m_data += m->m_len; | |
591 | m->m_len = 1; | 591 | m->m_len = 1; | |
592 | m = m_pullup(m, 2); | 592 | m = m_pullup(m, 2); | |
593 | } else { | 593 | } else { | |
594 | hpput(ns, mtod(m, void *), buffer, m->m_len); | 594 | hpput(ns, mtod(m, void *), buffer, m->m_len); | |
595 | t -= m->m_len; | 595 | t -= m->m_len; | |
596 | buffer += m->m_len; | 596 | buffer += m->m_len; | |
597 | MFREE(m, m0); | 597 | MFREE(m, m0); | |
598 | m = m0; | 598 | m = m0; | |
599 | } | 599 | } | |
600 | } | 600 | } | |
601 | 601 | |||
602 | /* | 602 | /* | |
603 | * Init transmit length registers, and set transmit start flag. | 603 | * Init transmit length registers, and set transmit start flag. | |
604 | */ | 604 | */ | |
605 | len = total; | 605 | len = total; | |
606 | if (len < ETHER_MIN_LEN) | 606 | if (len < ETHER_MIN_LEN) | |
607 | len = ETHER_MIN_LEN; | 607 | len = ETHER_MIN_LEN; | |
608 | #error broken here ! need to set to 0 the pad space in buffer ! | 608 | #error broken here ! need to set to 0 the pad space in buffer ! | |
609 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START); | 609 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START); | |
610 | outb(hpc + ds0_tbcr0, len & 0xff); | 610 | outb(hpc + ds0_tbcr0, len & 0xff); | |
611 | outb(hpc + ds0_tbcr1, (len >> 8) & 0xff); | 611 | outb(hpc + ds0_tbcr1, (len >> 8) & 0xff); | |
612 | outb(hpc + ds0_tpsr, ns->ns_txstart); | 612 | outb(hpc + ds0_tpsr, ns->ns_txstart); | |
613 | outb(hpc + ds_cmd, DSCM_TRANS | DSCM_NODMA | DSCM_PG0 | DSCM_START); | 613 | outb(hpc + ds_cmd, DSCM_TRANS | DSCM_NODMA | DSCM_PG0 | DSCM_START); | |
614 | 614 | |||
615 | #ifdef HP_DEBUG | 615 | #ifdef HP_DEBUG | |
616 | printf("hpstart: done\n", hpc); | 616 | printf("hpstart: done\n", hpc); | |
617 | #endif | 617 | #endif | |
618 | } | 618 | } | |
619 | /* | 619 | /* | |
620 | * Controller interrupt. | 620 | * Controller interrupt. | |
621 | */ | 621 | */ | |
622 | hpintr(unit) | 622 | hpintr(unit) | |
623 | { | 623 | { | |
624 | struct hp_softc *ns = &hp_softc[unit]; | 624 | struct hp_softc *ns = &hp_softc[unit]; | |
625 | u_char cmd, isr; | 625 | u_char cmd, isr; | |
626 | int hpc = ns->ns_port; | 626 | int hpc = ns->ns_port; | |
627 | u_char err; | 627 | u_char err; | |
628 | 628 | |||
629 | /* Save cmd, clear interrupt */ | 629 | /* Save cmd, clear interrupt */ | |
630 | cmd = inb(hpc + ds_cmd); | 630 | cmd = inb(hpc + ds_cmd); | |
631 | loop: | 631 | loop: | |
632 | isr = inb(hpc + ds0_isr); | 632 | isr = inb(hpc + ds0_isr); | |
633 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START); | 633 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START); | |
634 | outb(hpc + ds0_isr, isr); | 634 | outb(hpc + ds0_isr, isr); | |
635 | 635 | |||
636 | /* Receiver error */ | 636 | /* Receiver error */ | |
637 | if (isr & DSIS_RXE) { | 637 | if (isr & DSIS_RXE) { | |
638 | /* need to read these registers to clear status */ | 638 | /* need to read these registers to clear status */ | |
639 | err = inb(hpc + ds0_rsr); | 639 | err = inb(hpc + ds0_rsr); | |
640 | (void) inb(hpc + 0xD); | 640 | (void) inb(hpc + 0xD); | |
641 | (void) inb(hpc + 0xE); | 641 | (void) inb(hpc + 0xE); | |
642 | (void) inb(hpc + 0xF); | 642 | (void) inb(hpc + 0xF); | |
643 | ns->ns_if.if_ierrors++; | 643 | ns->ns_if.if_ierrors++; | |
644 | #ifdef HP_LOG_ERRORS | 644 | #ifdef HP_LOG_ERRORS | |
645 | isr |= DSIS_RX; | 645 | isr |= DSIS_RX; | |
646 | #endif | 646 | #endif | |
647 | } | 647 | } | |
648 | /* We received something */ | 648 | /* We received something */ | |
649 | if (isr & DSIS_RX) { | 649 | if (isr & DSIS_RX) { | |
650 | u_char bnry; | 650 | u_char bnry; | |
651 | u_char curr; | 651 | u_char curr; | |
652 | u_short addr; | 652 | u_short addr; | |
653 | int len; | 653 | int len; | |
654 | int i; | 654 | int i; | |
655 | unsigned char c; | 655 | unsigned char c; | |
656 | 656 | |||
657 | while (1) { | 657 | while (1) { | |
658 | outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0); | 658 | outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0); | |
659 | bnry = inb(hpc + ds0_bnry); | 659 | bnry = inb(hpc + ds0_bnry); | |
660 | outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG1); | 660 | outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG1); | |
661 | curr = inb(hpc + ds1_curr); | 661 | curr = inb(hpc + ds1_curr); | |
662 | 662 | |||
663 | #ifdef HP_DEBUG | 663 | #ifdef HP_DEBUG | |
664 | printf("hpintr: receive isr=0x%02x bnry=0x%02x curr=0x%02x\n", | 664 | printf("hpintr: receive isr=0x%02x bnry=0x%02x curr=0x%02x\n", | |
665 | isr, bnry, curr); | 665 | isr, bnry, curr); | |
666 | #endif | 666 | #endif | |
667 | 667 | |||
668 | if (++bnry >= ns->ns_rxend) | 668 | if (++bnry >= ns->ns_rxend) | |
669 | bnry = ns->ns_rxstart; | 669 | bnry = ns->ns_rxstart; | |
670 | 670 | |||
671 | /* if ring empty, done! */ | 671 | /* if ring empty, done! */ | |
672 | if (bnry == curr) | 672 | if (bnry == curr) | |
673 | break; | 673 | break; | |
674 | 674 | |||
675 | addr = bnry * DS_PGSIZE; | 675 | addr = bnry * DS_PGSIZE; | |
676 | 676 | |||
677 | outb(hpc + hp_option, inb(hpc + hp_option) | HP_DATA); | 677 | outb(hpc + hp_option, inb(hpc + hp_option) | HP_DATA); | |
678 | 678 | |||
679 | #if 0 | 679 | #if 0 | |
680 | /* send packet with auto packet release */ | 680 | /* send packet with auto packet release */ | |
681 | outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0); | 681 | outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0); | |
682 | outb(hpc + ds0_rbcr1, 0x0f); | 682 | outb(hpc + ds0_rbcr1, 0x0f); | |
683 | outb(hpc + ds0_dcr, ns->ns_mode | DSDC_AR); | 683 | outb(hpc + ds0_dcr, ns->ns_mode | DSDC_AR); | |
684 | outb(hpc + ds_cmd, DSCM_SENDP | DSCM_PG0 | DSCM_START); | 684 | outb(hpc + ds_cmd, DSCM_SENDP | DSCM_PG0 | DSCM_START); | |
685 | #endif | 685 | #endif | |
686 | 686 | |||
687 | /* get length */ | 687 | /* get length */ | |
688 | hpfetch(ns, (void *) & ns->ns_ph, addr, sizeof ns->ns_ph); | 688 | hpfetch(ns, (void *) & ns->ns_ph, addr, sizeof ns->ns_ph); | |
689 | addr += sizeof ns->ns_ph; | 689 | addr += sizeof ns->ns_ph; | |
690 | 690 | |||
691 | #ifdef HP_DEBUG | 691 | #ifdef HP_DEBUG | |
692 | printf("hpintr: sendp packet hdr: %x %x %x %x\n", | 692 | printf("hpintr: sendp packet hdr: %x %x %x %x\n", | |
693 | ns->ns_ph.pr_status, | 693 | ns->ns_ph.pr_status, | |
694 | ns->ns_ph.pr_nxtpg, | 694 | ns->ns_ph.pr_nxtpg, | |
695 | ns->ns_ph.pr_sz0, | 695 | ns->ns_ph.pr_sz0, | |
696 | ns->ns_ph.pr_sz1); | 696 | ns->ns_ph.pr_sz1); | |
697 | #endif | 697 | #endif | |
698 | 698 | |||
699 | #ifdef HP_LOG_ERRORS | 699 | #ifdef HP_LOG_ERRORS | |
700 | if (ns->ns_ph.pr_status & (DSRS_CRC | DSRS_FO | DSRS_DFR)) { | 700 | if (ns->ns_ph.pr_status & (DSRS_CRC | DSRS_FO | DSRS_DFR)) { | |
701 | /* Get packet header */ | 701 | /* Get packet header */ | |
702 | if (len > 14) | 702 | if (len > 14) | |
703 | len = 14; | 703 | len = 14; | |
704 | hpfetch(ns, (void *) (ns->ns_pb), addr, len); | 704 | hpfetch(ns, (void *) (ns->ns_pb), addr, len); | |
705 | 705 | |||
706 | /* move boundary up */ | 706 | /* move boundary up */ | |
707 | bnry = ns->ns_ph.pr_nxtpg; | 707 | bnry = ns->ns_ph.pr_nxtpg; | |
708 | if (--bnry < ns->ns_rxstart) | 708 | if (--bnry < ns->ns_rxstart) | |
709 | bnry = ns->ns_rxend - 1; | 709 | bnry = ns->ns_rxend - 1; | |
710 | outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0); | 710 | outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0); | |
711 | outb(hpc + ds0_bnry, bnry); | 711 | outb(hpc + ds0_bnry, bnry); | |
712 | 712 | |||
713 | printf("hp%d: receive error status=0x%02x\n", unit, | 713 | printf("hp%d: receive error status=0x%02x\n", unit, | |
714 | ns->ns_ph.pr_status); | 714 | ns->ns_ph.pr_status); | |
715 | printf("hp%d: packet header:", unit); | 715 | printf("hp%d: packet header:", unit); | |
716 | { | 716 | { | |
717 | int n; | 717 | int n; | |
718 | for (n = 0; n < len; n++) | 718 | for (n = 0; n < len; n++) | |
719 | printf(" %02x", ns->ns_pb[n]); | 719 | printf(" %02x", ns->ns_pb[n]); | |
720 | } | 720 | } | |
721 | printf("\n"); | 721 | printf("\n"); | |
722 | 722 | |||
723 | continue; | 723 | continue; | |
724 | } | 724 | } | |
725 | #endif | 725 | #endif | |
726 | 726 | |||
727 | ns->ns_if.if_ipackets++; | 727 | ns->ns_if.if_ipackets++; | |
728 | len = ns->ns_ph.pr_sz0 + (ns->ns_ph.pr_sz1 << 8); | 728 | len = ns->ns_ph.pr_sz0 + (ns->ns_ph.pr_sz1 << 8); | |
729 | if (len < ETHER_MIN_LEN || len > ETHER_MAX_LEN) { | 729 | if (len < ETHER_MIN_LEN || len > ETHER_MAX_LEN) { | |
730 | printf("hpintr: bnry %x curr %x\n", bnry, curr); | 730 | printf("hpintr: bnry %x curr %x\n", bnry, curr); | |
731 | printf("hpintr: packet hdr: %x %x %x %x\n", | 731 | printf("hpintr: packet hdr: %x %x %x %x\n", | |
732 | ns->ns_ph.pr_status, | 732 | ns->ns_ph.pr_status, | |
733 | ns->ns_ph.pr_nxtpg, | 733 | ns->ns_ph.pr_nxtpg, | |
734 | ns->ns_ph.pr_sz0, | 734 | ns->ns_ph.pr_sz0, | |
735 | ns->ns_ph.pr_sz1); | 735 | ns->ns_ph.pr_sz1); | |
736 | printf("isr = 0x%x reg_isr=0x%x\n", | 736 | printf("isr = 0x%x reg_isr=0x%x\n", | |
737 | isr, inb(hpc + ds0_isr)); | 737 | isr, inb(hpc + ds0_isr)); | |
738 | outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0); | 738 | outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0); | |
739 | bnry = inb(hpc + ds0_bnry); | 739 | bnry = inb(hpc + ds0_bnry); | |
740 | outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG1); | 740 | outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG1); | |
741 | curr = inb(hpc + ds1_curr); | 741 | curr = inb(hpc + ds1_curr); | |
742 | printf("hpintr: new bnry %x curr %x\n", bnry, curr); | 742 | printf("hpintr: new bnry %x curr %x\n", bnry, curr); | |
743 | printf("hpintr: bad len %d\n-hanging-\n", | 743 | printf("hpintr: bad len %d\n-hanging-\n", | |
744 | len); | 744 | len); | |
745 | while (1); | 745 | while (1); | |
746 | } | 746 | } | |
747 | /* read packet */ | 747 | /* read packet */ | |
748 | hpfetch(ns, (void *) (ns->ns_pb), addr, len); | 748 | hpfetch(ns, (void *) (ns->ns_pb), addr, len); | |
749 | 749 | |||
750 | /* move boundary up */ | 750 | /* move boundary up */ | |
751 | bnry = ns->ns_ph.pr_nxtpg; | 751 | bnry = ns->ns_ph.pr_nxtpg; | |
752 | if (--bnry < ns->ns_rxstart) | 752 | if (--bnry < ns->ns_rxstart) | |
753 | bnry = ns->ns_rxend - 1; | 753 | bnry = ns->ns_rxend - 1; | |
754 | outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0); | 754 | outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA | DSCM_PG0); | |
755 | outb(hpc + ds0_bnry, bnry); | 755 | outb(hpc + ds0_bnry, bnry); | |
756 | 756 | |||
757 | #ifdef HP_DEBUG | 757 | #ifdef HP_DEBUG | |
758 | printf("hpintr: receive done bnry=0x%02x\n", bnry); | 758 | printf("hpintr: receive done bnry=0x%02x\n", bnry); | |
759 | #endif | 759 | #endif | |
760 | 760 | |||
761 | outb(hpc + hp_option, inb(hpc + hp_option) & ~HP_DATA); | 761 | outb(hpc + hp_option, inb(hpc + hp_option) & ~HP_DATA); | |
762 | 762 | |||
763 | /* adjust for ether header and checksum */ | 763 | /* adjust for ether header and checksum */ | |
764 | len -= sizeof(struct ether_header) + sizeof(long); | 764 | len -= sizeof(struct ether_header) + sizeof(long); | |
765 | 765 | |||
766 | /* process packet */ | 766 | /* process packet */ | |
767 | hpread(ns, (void *) (ns->ns_pb), len); | 767 | hpread(ns, (void *) (ns->ns_pb), len); | |
768 | } | 768 | } | |
769 | } | 769 | } | |
770 | /* Transmit error */ | 770 | /* Transmit error */ | |
771 | if (isr & DSIS_TXE) { | 771 | if (isr & DSIS_TXE) { | |
772 | ns->ns_flags &= ~DSF_LOCK; | 772 | ns->ns_flags &= ~DSF_LOCK; | |
773 | /* Need to read these registers to clear status */ | 773 | /* Need to read these registers to clear status */ | |
774 | ns->ns_if.if_collisions += inb(hpc + ds0_tbcr0); | 774 | ns->ns_if.if_collisions += inb(hpc + ds0_tbcr0); | |
775 | ns->ns_if.if_oerrors++; | 775 | ns->ns_if.if_oerrors++; | |
776 | } | 776 | } | |
777 | /* Packet Transmitted */ | 777 | /* Packet Transmitted */ | |
778 | if (isr & DSIS_TX) { | 778 | if (isr & DSIS_TX) { | |
779 | ns->ns_flags &= ~DSF_LOCK; | 779 | ns->ns_flags &= ~DSF_LOCK; | |
780 | ++ns->ns_if.if_opackets; | 780 | ++ns->ns_if.if_opackets; | |
781 | ns->ns_if.if_collisions += inb(hpc + ds0_tbcr0); | 781 | ns->ns_if.if_collisions += inb(hpc + ds0_tbcr0); | |
782 | } | 782 | } | |
783 | /* Receiver ovverun? */ | 783 | /* Receiver ovverun? */ | |
784 | if (isr & DSIS_ROVRN) { | 784 | if (isr & DSIS_ROVRN) { | |
785 | log(LOG_ERR, "hp%d: error: isr %x\n", ns - hp_softc, isr | 785 | log(LOG_ERR, "hp%d: error: isr %x\n", ns - hp_softc, isr | |
786 | /* , DSIS_BITS */ ); | 786 | /* , DSIS_BITS */ ); | |
787 | outb(hpc + ds0_rbcr0, 0); | 787 | outb(hpc + ds0_rbcr0, 0); | |
788 | outb(hpc + ds0_rbcr1, 0); | 788 | outb(hpc + ds0_rbcr1, 0); | |
789 | outb(hpc + ds0_tcr, DSTC_LB0); | 789 | outb(hpc + ds0_tcr, DSTC_LB0); | |
790 | outb(hpc + ds0_rcr, DSRC_MON); | 790 | outb(hpc + ds0_rcr, DSRC_MON); | |
791 | outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA); | 791 | outb(hpc + ds_cmd, DSCM_START | DSCM_NODMA); | |
792 | outb(hpc + ds0_rcr, ns->ns_rcr); | 792 | outb(hpc + ds0_rcr, ns->ns_rcr); | |
793 | outb(hpc + ds0_tcr, 0); | 793 | outb(hpc + ds0_tcr, 0); | |
794 | } | 794 | } | |
795 | /* Any more to send? */ | 795 | /* Any more to send? */ | |
796 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START); | 796 | outb(hpc + ds_cmd, DSCM_NODMA | DSCM_PG0 | DSCM_START); | |
797 | hpstart(&ns->ns_if); | 797 | hpstart(&ns->ns_if); | |
798 | outb(hpc + ds_cmd, cmd); | 798 | outb(hpc + ds_cmd, cmd); | |
799 | outb(hpc + ds0_imr, 0xff); | 799 | outb(hpc + ds0_imr, 0xff); | |
800 | 800 | |||
801 | #if NRND > 0 | 801 | #if NRND > 0 | |
802 | if (irs) | 802 | if (irs) | |
803 | rnd_add_uint32(&sc->rnd_source, isr); | 803 | rnd_add_uint32(&sc->rnd_source, isr); | |
804 | #endif | 804 | #endif | |
805 | 805 | |||
806 | /* Still more to do? */ | 806 | /* Still more to do? */ | |
807 | isr = inb(hpc + ds0_isr); | 807 | isr = inb(hpc + ds0_isr); | |
808 | if (isr) | 808 | if (isr) | |
809 | goto loop; | 809 | goto loop; | |
810 | } | 810 | } | |
811 | /* | 811 | /* | |
812 | * Pass a packet to the higher levels. | 812 | * Pass a packet to the higher levels. | |
813 | * We deal with the trailer protocol here. | 813 | * We deal with the trailer protocol here. | |
814 | */ | 814 | */ | |
815 | hpread(struct hp_softc *ns, char *buf, int len) | 815 | hpread(struct hp_softc *ns, char *buf, int len) | |
816 | { | 816 | { | |
817 | struct ether_header *eh; | 817 | struct ether_header *eh; | |
818 | struct mbuf *m; | 818 | struct mbuf *m; | |
819 | int off, resid; | 819 | int off, resid; | |
820 | struct ifqueue *inq; | 820 | struct ifqueue *inq; | |
821 | u_short etype; | 821 | u_short etype; | |
822 | 822 | |||
823 | /* | 823 | /* | |
824 | * Deal with trailer protocol: if type is trailer type | 824 | * Deal with trailer protocol: if type is trailer type | |
825 | * get true type from first 16-bit word past data. | 825 | * get true type from first 16-bit word past data. | |
826 | * Remember that type was trailer by setting off. | 826 | * Remember that type was trailer by setting off. | |
827 | */ | 827 | */ | |
828 | eh = (struct ether_header *) buf; | 828 | eh = (struct ether_header *) buf; | |
829 | etype = ntohs((u_short) eh->ether_type); | 829 | etype = ntohs((u_short) eh->ether_type); | |
830 | #define hpdataaddr(eh, off, type) ((type)(((void *)((eh)+1)+(off)))) | 830 | #define hpdataaddr(eh, off, type) ((type)(((void *)((eh)+1)+(off)))) | |
831 | if (etype >= ETHERTYPE_TRAIL && | 831 | if (etype >= ETHERTYPE_TRAIL && | |
832 | etype < ETHERTYPE_TRAIL + ETHERTYPE_NTRAILER) { | 832 | etype < ETHERTYPE_TRAIL + ETHERTYPE_NTRAILER) { | |
833 | off = (etype - ETHERTYPE_TRAIL) * 512; | 833 | off = (etype - ETHERTYPE_TRAIL) * 512; | |
834 | if (off >= ETHERMTU) | 834 | if (off >= ETHERMTU) | |
835 | return; /* sanity */ | 835 | return; /* sanity */ | |
836 | eh->ether_type = *hpdataaddr(eh, off, u_short *); | 836 | eh->ether_type = *hpdataaddr(eh, off, u_short *); | |
837 | resid = ntohs(*(hpdataaddr(eh, off + 2, u_short *))); | 837 | resid = ntohs(*(hpdataaddr(eh, off + 2, u_short *))); | |
838 | if (off + resid > len) | 838 | if (off + resid > len) | |
839 | return; /* sanity */ | 839 | return; /* sanity */ | |
840 | len = off + resid; | 840 | len = off + resid; | |
841 | } else | 841 | } else | |
842 | off = 0; | 842 | off = 0; | |
843 | 843 | |||
844 | if (len == 0) | 844 | if (len == 0) | |
845 | return; | 845 | return; | |
846 | 846 | |||
847 | #if NBPFILTER > 0 | 847 | #if NBPFILTER > 0 | |
848 | if (ns->ns_bpf) | 848 | if (ns->ns_bpf) | |
849 | bpf_tap(ns->ns_bpf, buf, len + sizeof(struct ether_header)); | 849 | bpf_tap(ns->ns_bpf, buf, len + sizeof(struct ether_header)); | |
850 | #endif | 850 | #endif | |
851 | 851 | |||
852 | if ((ns->ns_if.if_flags & IFF_PROMISC) | 852 | if ((ns->ns_if.if_flags & IFF_PROMISC) | |
853 | && memcmp(eh->ether_dhost, ns->ns_addrp, | 853 | && memcmp(eh->ether_dhost, ns->ns_addrp, | |
854 | sizeof(eh->ether_dhost)) != 0 | 854 | sizeof(eh->ether_dhost)) != 0 | |
855 | && memcmp(eh->ether_dhost, etherbroadcastaddr, | 855 | && memcmp(eh->ether_dhost, etherbroadcastaddr, | |
856 | sizeof(eh->ether_dhost)) != 0) | 856 | sizeof(eh->ether_dhost)) != 0) | |
857 | return; | 857 | return; | |
858 | 858 | |||
859 | /* | 859 | /* | |
860 | * Pull packet off interface. Off is nonzero if packet | 860 | * Pull packet off interface. Off is nonzero if packet | |
861 | * has trailing header; hpget will then force this header | 861 | * has trailing header; hpget will then force this header | |
862 | * information to be at the front, but we still have to drop | 862 | * information to be at the front, but we still have to drop | |
863 | * the type and length which are at the front of any trailer data. | 863 | * the type and length which are at the front of any trailer data. | |
864 | */ | 864 | */ | |
865 | m = hpget(buf, len, off, &ns->ns_if); | 865 | m = hpget(buf, len, off, &ns->ns_if); | |
866 | if (m == 0) | 866 | if (m == 0) | |
867 | return; | 867 | return; | |
868 | 868 | |||
869 | ether_input(&ns->ns_if, eh, m); | 869 | ether_input(&ns->ns_if, eh, m); | |
870 | } | 870 | } | |
871 | /* | 871 | /* | |
872 | * Supporting routines | 872 | * Supporting routines | |
873 | */ | 873 | */ | |
874 | 874 | |||
875 | /* | 875 | /* | |
876 | * Pull read data off a interface. | 876 | * Pull read data off a interface. | |
877 | * Len is length of data, with local net header stripped. | 877 | * Len is length of data, with local net header stripped. | |
878 | * Off is non-zero if a trailer protocol was used, and | 878 | * Off is non-zero if a trailer protocol was used, and | |
879 | * gives the offset of the trailer information. | 879 | * gives the offset of the trailer information. | |
880 | * We copy the trailer information and then all the normal | 880 | * We copy the trailer information and then all the normal | |
881 | * data into mbufs. When full cluster sized units are present | 881 | * data into mbufs. When full cluster sized units are present | |
882 | * we copy into clusters. | 882 | * we copy into clusters. | |
883 | */ | 883 | */ | |
884 | struct mbuf * | 884 | struct mbuf * | |
885 | hpget(void *buf, int totlen, int off0, struct ifnet *ifp) | 885 | hpget(void *buf, int totlen, int off0, struct ifnet *ifp) | |
886 | { | 886 | { | |
887 | struct mbuf *top, **mp, *m, *p; | 887 | struct mbuf *top, **mp, *m, *p; | |
888 | int off = off0, len; | 888 | int off = off0, len; | |
889 | void *cp = buf; | 889 | void *cp = buf; | |
890 | char *epkt; | 890 | char *epkt; | |
891 | 891 | |||
892 | buf += sizeof(struct ether_header); | 892 | buf += sizeof(struct ether_header); | |
893 | cp = buf; | 893 | cp = buf; | |
894 | epkt = cp + totlen; | 894 | epkt = cp + totlen; | |
895 | 895 | |||
896 | 896 | |||
897 | if (off) { | 897 | if (off) { | |
898 | cp += off + 2 * sizeof(u_short); | 898 | cp += off + 2 * sizeof(u_short); | |
899 | totlen -= 2 * sizeof(u_short); | 899 | totlen -= 2 * sizeof(u_short); | |
900 | } | 900 | } | |
901 | MGETHDR(m, M_DONTWAIT, MT_DATA); | 901 | MGETHDR(m, M_DONTWAIT, MT_DATA); | |
902 | if (m == 0) | 902 | if (m == 0) | |
903 | return (0); | 903 | return (0); | |
904 | m->m_pkthdr.rcvif = ifp; | 904 | m->m_pkthdr.rcvif = ifp; | |
905 | m->m_pkthdr.len = totlen; | 905 | m->m_pkthdr.len = totlen; | |
906 | m->m_len = MHLEN; | 906 | m->m_len = MHLEN; | |
907 | 907 | |||
908 | top = 0; | 908 | top = 0; | |
909 | mp = ⊤ | 909 | mp = ⊤ | |
910 | while (totlen > 0) { | 910 | while (totlen > 0) { | |
911 | if (top) { | 911 | if (top) { | |
912 | MGET(m, M_DONTWAIT, MT_DATA); | 912 | MGET(m, M_DONTWAIT, MT_DATA); | |
913 | if (m == 0) { | 913 | if (m == 0) { | |
914 | m_freem(top); | 914 | m_freem(top); | |
915 | return (0); | 915 | return (0); | |
916 | } | 916 | } | |
917 | m->m_len = MLEN; | 917 | m->m_len = MLEN; | |
918 | } | 918 | } | |
919 | len = min(totlen, epkt - cp); | 919 | len = min(totlen, epkt - cp); | |
920 | if (len >= MINCLSIZE) { | 920 | if (len >= MINCLSIZE) { | |
921 | MCLGET(m, M_DONTWAIT); | 921 | MCLGET(m, M_DONTWAIT); | |
922 | if (m->m_flags & M_EXT) | 922 | if (m->m_flags & M_EXT) | |
923 | m->m_len = len = min(len, MCLBYTES); | 923 | m->m_len = len = min(len, MCLBYTES); | |
924 | else | 924 | else | |
925 | len = m->m_len; | 925 | len = m->m_len; | |
926 | } else { | 926 | } else { | |
927 | /* | 927 | /* | |
928 | * Place initial small packet/header at end of mbuf. | 928 | * Place initial small packet/header at end of mbuf. | |
929 | */ | 929 | */ | |
930 | if (len < m->m_len) { | 930 | if (len < m->m_len) { | |
931 | if (top == 0 && len + max_linkhdr <= m->m_len) | 931 | if (top == 0 && len + max_linkhdr <= m->m_len) | |
932 | m->m_data += max_linkhdr; | 932 | m->m_data += max_linkhdr; | |
933 | m->m_len = len; | 933 | m->m_len = len; | |
934 | } else | 934 | } else | |
935 | len = m->m_len; | 935 | len = m->m_len; | |
936 | } | 936 | } | |
937 | memcpy(mtod(m, void *), cp, (unsigned) len); | 937 | memcpy(mtod(m, void *), cp, (unsigned) len); | |
938 | cp += len; | 938 | cp += len; | |
939 | *mp = m; | 939 | *mp = m; | |
940 | mp = &m->m_next; | 940 | mp = &m->m_next; | |
941 | totlen -= len; | 941 | totlen -= len; | |
942 | if (cp == epkt) | 942 | if (cp == epkt) | |
943 | cp = buf; | 943 | cp = buf; | |
944 | } | 944 | } | |
945 | return (top); | 945 | return (top); | |
946 | } | 946 | } | |
947 | /* | 947 | /* | |
948 | * Process an ioctl request. | 948 | * Process an ioctl request. | |
949 | */ | 949 | */ | |
950 | hpioctl(struct ifnet *ifp, u_long cmd, void *data) | 950 | hpioctl(struct ifnet *ifp, u_long cmd, void *data) | |
951 | { | 951 | { | |
952 | struct ifaddr *ifa = (struct ifaddr *) data; | 952 | struct ifaddr *ifa = (struct ifaddr *) data; | |
953 | struct hp_softc *ns = &hp_softc[ifp->if_unit]; | 953 | struct hp_softc *ns = &hp_softc[ifp->if_unit]; | |
954 | struct ifreq *ifr = (struct ifreq *) data; | 954 | struct ifreq *ifr = (struct ifreq *) data; | |
955 | int s = splnet(), error = 0; | 955 | int s = splnet(), error = 0; | |
956 | 956 | |||
957 | 957 | |||
958 | switch (cmd) { | 958 | switch (cmd) { | |
959 | 959 | |||
960 | case SIOCINITIFADDR: | 960 | case SIOCINITIFADDR: | |
961 | ifp->if_flags |= IFF_UP; | 961 | ifp->if_flags |= IFF_UP; | |
962 | 962 | |||
963 | hpinit(ifp->if_unit); | 963 | hpinit(ifp->if_unit); | |
964 | switch (ifa->ifa_addr->sa_family) { | 964 | switch (ifa->ifa_addr->sa_family) { | |
965 | #ifdef INET | 965 | #ifdef INET | |
966 | case AF_INET: | 966 | case AF_INET: | |
967 | ((struct arpcom *) ifp)->ac_ipaddr = | 967 | ((struct arpcom *) ifp)->ac_ipaddr = | |
968 | IA_SIN(ifa)->sin_addr; | 968 | IA_SIN(ifa)->sin_addr; | |
969 | arpwhohas((struct arpcom *) ifp, &IA_SIN(ifa)->sin_addr); | 969 | arpwhohas((struct arpcom *) ifp, &IA_SIN(ifa)->sin_addr); | |
970 | break; | 970 | break; | |
971 | #endif | 971 | #endif | |
972 | default: | 972 | default: | |
973 | break; | 973 | break; | |
974 | } | 974 | } | |
975 | break; | 975 | break; | |
976 | 976 | |||
977 | case SIOCSIFFLAGS: | 977 | case SIOCSIFFLAGS: | |
978 | if ((error = ifioctl_common(ifp, cmd, data)) != 0) | 978 | if ((error = ifioctl_common(ifp, cmd, data)) != 0) | |
979 | break; | 979 | break; | |
980 | #ifdef HP_DEBUG | 980 | #ifdef HP_DEBUG | |
981 | printf("hp: setting flags, up: %s, running: %s\n", | 981 | printf("hp: setting flags, up: %s, running: %s\n", | |
982 | ifp->if_flags & IFF_UP ? "yes" : "no", | 982 | ifp->if_flags & IFF_UP ? "yes" : "no", | |
983 | ifp->if_flags & IFF_RUNNING ? "yes" : "no"); | 983 | ifp->if_flags & IFF_RUNNING ? "yes" : "no"); | |
984 | #endif | 984 | #endif | |
985 | /* XXX re-use ether_ioctl() */ | 985 | /* XXX re-use ether_ioctl() */ | |
986 | switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) { | 986 | switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) { | |
987 | case IFF_RUNNING: | 987 | case IFF_RUNNING: | |
988 | ifp->if_flags &= ~IFF_RUNNING; | 988 | ifp->if_flags &= ~IFF_RUNNING; | |
989 | outb(ns->ns_port + ds_cmd, DSCM_STOP | DSCM_NODMA); | 989 | outb(ns->ns_port + ds_cmd, DSCM_STOP | DSCM_NODMA); | |
990 | break; | 990 | break; | |
991 | case IFF_UP: | 991 | case IFF_UP: | |
992 | hpinit(ifp->if_unit); | 992 | hpinit(ifp->if_unit); | |
993 | break; | 993 | break; | |
994 | default: | 994 | default: | |
995 | break; | 995 | break; | |
996 | } | 996 | } | |
997 | break; | 997 | break; | |
998 | 998 | |||
999 | #ifdef notdef | 999 | #ifdef notdef | |
1000 | case SIOCGHWADDR: | 1000 | case SIOCGHWADDR: | |
1001 | memcpy((void *) & ifr->ifr_data, (void *) ns->ns_addrp, | 1001 | memcpy((void *) & ifr->ifr_data, (void *) ns->ns_addrp, | |
1002 | sizeof(ns->ns_addrp)); | 1002 | sizeof(ns->ns_addrp)); | |
1003 | break; | 1003 | break; | |
1004 | #endif | 1004 | #endif | |
1005 | 1005 | |||
1006 | default: | 1006 | default: | |
1007 | error = ether_ioctl(ifp, cmd, data); | 1007 | error = ether_ioctl(ifp, cmd, data); | |
1008 | } | 1008 | } | |
1009 | splx(s); | 1009 | splx(s); | |
1010 | return (error); | 1010 | return (error); | |
1011 | } | 1011 | } | |
1012 | #endif | 1012 | #endif |