if_mc.c revision 1.5.6.2 1 1.5.6.2 nathanw /* $NetBSD: if_mc.c,v 1.5.6.2 2002/10/18 02:38:35 nathanw Exp $ */
2 1.5.6.2 nathanw
3 1.5.6.2 nathanw /*-
4 1.5.6.2 nathanw * Copyright (c) 1997 David Huang <khym (at) bga.com>
5 1.5.6.2 nathanw * All rights reserved.
6 1.5.6.2 nathanw *
7 1.5.6.2 nathanw * Portions of this code are based on code by Denton Gentry <denny1 (at) home.com>
8 1.5.6.2 nathanw * and Yanagisawa Takeshi <yanagisw (at) aa.ap.titech.ac.jp>.
9 1.5.6.2 nathanw *
10 1.5.6.2 nathanw * Redistribution and use in source and binary forms, with or without
11 1.5.6.2 nathanw * modification, are permitted provided that the following conditions
12 1.5.6.2 nathanw * are met:
13 1.5.6.2 nathanw * 1. Redistributions of source code must retain the above copyright
14 1.5.6.2 nathanw * notice, this list of conditions and the following disclaimer.
15 1.5.6.2 nathanw * 2. The name of the author may not be used to endorse or promote products
16 1.5.6.2 nathanw * derived from this software without specific prior written permission
17 1.5.6.2 nathanw *
18 1.5.6.2 nathanw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 1.5.6.2 nathanw * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 1.5.6.2 nathanw * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 1.5.6.2 nathanw * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 1.5.6.2 nathanw * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 1.5.6.2 nathanw * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 1.5.6.2 nathanw * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 1.5.6.2 nathanw * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 1.5.6.2 nathanw * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 1.5.6.2 nathanw * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 1.5.6.2 nathanw *
29 1.5.6.2 nathanw */
30 1.5.6.2 nathanw
31 1.5.6.2 nathanw /*
32 1.5.6.2 nathanw * Bus attachment and DMA routines for the mc driver (Centris/Quadra
33 1.5.6.2 nathanw * 660av and Quadra 840av onboard ethernet, based on the AMD Am79C940
34 1.5.6.2 nathanw * MACE ethernet chip). Also uses the PSC (Peripheral Subsystem
35 1.5.6.2 nathanw * Controller) for DMA to and from the MACE.
36 1.5.6.2 nathanw */
37 1.5.6.2 nathanw
38 1.5.6.2 nathanw #include <sys/param.h>
39 1.5.6.2 nathanw #include <sys/device.h>
40 1.5.6.2 nathanw #include <sys/malloc.h>
41 1.5.6.2 nathanw #include <sys/socket.h>
42 1.5.6.2 nathanw #include <sys/systm.h>
43 1.5.6.2 nathanw
44 1.5.6.2 nathanw #include <net/if.h>
45 1.5.6.2 nathanw #include <net/if_ether.h>
46 1.5.6.2 nathanw #include <net/if_media.h>
47 1.5.6.2 nathanw
48 1.5.6.2 nathanw #include <uvm/uvm_extern.h>
49 1.5.6.2 nathanw
50 1.5.6.2 nathanw #include <dev/ofw/openfirm.h>
51 1.5.6.2 nathanw
52 1.5.6.2 nathanw #include <machine/pio.h>
53 1.5.6.2 nathanw #include <machine/bus.h>
54 1.5.6.2 nathanw #include <machine/autoconf.h>
55 1.5.6.2 nathanw
56 1.5.6.2 nathanw #include <macppc/dev/am79c950reg.h>
57 1.5.6.2 nathanw #include <macppc/dev/if_mcvar.h>
58 1.5.6.2 nathanw
59 1.5.6.2 nathanw #define MC_BUFSIZE 0x800
60 1.5.6.2 nathanw
61 1.5.6.2 nathanw hide int mc_match __P((struct device *, struct cfdata *, void *));
62 1.5.6.2 nathanw hide void mc_attach __P((struct device *, struct device *, void *));
63 1.5.6.2 nathanw hide void mc_init __P((struct mc_softc *sc));
64 1.5.6.2 nathanw hide void mc_putpacket __P((struct mc_softc *sc, u_int len));
65 1.5.6.2 nathanw hide int mc_dmaintr __P((void *arg));
66 1.5.6.2 nathanw hide void mc_reset_rxdma __P((struct mc_softc *sc));
67 1.5.6.2 nathanw hide void mc_reset_txdma __P((struct mc_softc *sc));
68 1.5.6.2 nathanw hide void mc_select_utp __P((struct mc_softc *sc));
69 1.5.6.2 nathanw hide void mc_select_aui __P((struct mc_softc *sc));
70 1.5.6.2 nathanw hide int mc_mediachange __P((struct mc_softc *sc));
71 1.5.6.2 nathanw hide void mc_mediastatus __P((struct mc_softc *sc, struct ifmediareq *));
72 1.5.6.2 nathanw
73 1.5.6.2 nathanw int mc_supmedia[] = {
74 1.5.6.2 nathanw IFM_ETHER | IFM_10_T,
75 1.5.6.2 nathanw IFM_ETHER | IFM_10_5,
76 1.5.6.2 nathanw /*IFM_ETHER | IFM_AUTO,*/
77 1.5.6.2 nathanw };
78 1.5.6.2 nathanw
79 1.5.6.2 nathanw #define N_SUPMEDIA (sizeof(mc_supmedia) / sizeof(int));
80 1.5.6.2 nathanw
81 1.5.6.2 nathanw CFATTACH_DECL(mc, sizeof(struct mc_softc),
82 1.5.6.2 nathanw mc_match, mc_attach, NULL, NULL);
83 1.5.6.2 nathanw
84 1.5.6.2 nathanw hide int
85 1.5.6.2 nathanw mc_match(parent, cf, aux)
86 1.5.6.2 nathanw struct device *parent;
87 1.5.6.2 nathanw struct cfdata *cf;
88 1.5.6.2 nathanw void *aux;
89 1.5.6.2 nathanw {
90 1.5.6.2 nathanw struct confargs *ca = aux;
91 1.5.6.2 nathanw
92 1.5.6.2 nathanw if (strcmp(ca->ca_name, "mace") != 0)
93 1.5.6.2 nathanw return 0;
94 1.5.6.2 nathanw
95 1.5.6.2 nathanw /* requires 6 regs */
96 1.5.6.2 nathanw if (ca->ca_nreg / sizeof(int) != 6)
97 1.5.6.2 nathanw return 0;
98 1.5.6.2 nathanw
99 1.5.6.2 nathanw /* requires 3 intrs */
100 1.5.6.2 nathanw if (ca->ca_nintr / sizeof(int) != 3)
101 1.5.6.2 nathanw return 0;
102 1.5.6.2 nathanw
103 1.5.6.2 nathanw return 1;
104 1.5.6.2 nathanw }
105 1.5.6.2 nathanw
106 1.5.6.2 nathanw hide void
107 1.5.6.2 nathanw mc_attach(parent, self, aux)
108 1.5.6.2 nathanw struct device *parent, *self;
109 1.5.6.2 nathanw void *aux;
110 1.5.6.2 nathanw {
111 1.5.6.2 nathanw struct confargs *ca = aux;
112 1.5.6.2 nathanw struct mc_softc *sc = (struct mc_softc *)self;
113 1.5.6.2 nathanw u_int8_t myaddr[ETHER_ADDR_LEN];
114 1.5.6.2 nathanw u_int *reg;
115 1.5.6.2 nathanw
116 1.5.6.2 nathanw sc->sc_node = ca->ca_node;
117 1.5.6.2 nathanw
118 1.5.6.2 nathanw reg = ca->ca_reg;
119 1.5.6.2 nathanw reg[0] += ca->ca_baseaddr;
120 1.5.6.2 nathanw reg[2] += ca->ca_baseaddr;
121 1.5.6.2 nathanw reg[4] += ca->ca_baseaddr;
122 1.5.6.2 nathanw
123 1.5.6.2 nathanw sc->sc_txdma = mapiodev(reg[2], reg[3]);
124 1.5.6.2 nathanw sc->sc_rxdma = mapiodev(reg[4], reg[5]);
125 1.5.6.2 nathanw bus_space_map(sc->sc_regt, reg[0], reg[1], 0, &sc->sc_regh);
126 1.5.6.2 nathanw /* XXX sc_regt is uninitialized */
127 1.5.6.2 nathanw sc->sc_tail = 0;
128 1.5.6.2 nathanw sc->sc_txdmacmd = dbdma_alloc(sizeof(dbdma_command_t) * 2);
129 1.5.6.2 nathanw sc->sc_rxdmacmd = (void *)dbdma_alloc(sizeof(dbdma_command_t) * 8);
130 1.5.6.2 nathanw memset(sc->sc_txdmacmd, 0, sizeof(dbdma_command_t) * 2);
131 1.5.6.2 nathanw memset(sc->sc_rxdmacmd, 0, sizeof(dbdma_command_t) * 8);
132 1.5.6.2 nathanw
133 1.5.6.2 nathanw printf(": irq %d,%d,%d",
134 1.5.6.2 nathanw ca->ca_intr[0], ca->ca_intr[1], ca->ca_intr[2]);
135 1.5.6.2 nathanw
136 1.5.6.2 nathanw if (OF_getprop(sc->sc_node, "local-mac-address", myaddr, 6) != 6) {
137 1.5.6.2 nathanw printf(": failed to get MAC address.\n");
138 1.5.6.2 nathanw return;
139 1.5.6.2 nathanw }
140 1.5.6.2 nathanw
141 1.5.6.2 nathanw /* allocate memory for transmit buffer and mark it non-cacheable */
142 1.5.6.2 nathanw sc->sc_txbuf = malloc(NBPG, M_DEVBUF, M_WAITOK);
143 1.5.6.2 nathanw sc->sc_txbuf_phys = kvtop(sc->sc_txbuf);
144 1.5.6.2 nathanw memset(sc->sc_txbuf, 0, NBPG);
145 1.5.6.2 nathanw
146 1.5.6.2 nathanw /*
147 1.5.6.2 nathanw * allocate memory for receive buffer and mark it non-cacheable
148 1.5.6.2 nathanw * XXX This should use the bus_dma interface, since the buffer
149 1.5.6.2 nathanw * needs to be physically contiguous. However, it seems that
150 1.5.6.2 nathanw * at least on my system, malloc() does allocate contiguous
151 1.5.6.2 nathanw * memory. If it's not, suggest reducing the number of buffers
152 1.5.6.2 nathanw * to 2, which will fit in one 4K page.
153 1.5.6.2 nathanw */
154 1.5.6.2 nathanw sc->sc_rxbuf = malloc(MC_NPAGES * NBPG, M_DEVBUF, M_WAITOK);
155 1.5.6.2 nathanw sc->sc_rxbuf_phys = kvtop(sc->sc_rxbuf);
156 1.5.6.2 nathanw memset(sc->sc_rxbuf, 0, MC_NPAGES * NBPG);
157 1.5.6.2 nathanw
158 1.5.6.2 nathanw if ((int)sc->sc_txbuf & PGOFSET)
159 1.5.6.2 nathanw printf("txbuf is not page-aligned\n");
160 1.5.6.2 nathanw if ((int)sc->sc_rxbuf & PGOFSET)
161 1.5.6.2 nathanw printf("rxbuf is not page-aligned\n");
162 1.5.6.2 nathanw
163 1.5.6.2 nathanw sc->sc_bus_init = mc_init;
164 1.5.6.2 nathanw sc->sc_putpacket = mc_putpacket;
165 1.5.6.2 nathanw
166 1.5.6.2 nathanw
167 1.5.6.2 nathanw /* disable receive DMA */
168 1.5.6.2 nathanw dbdma_reset(sc->sc_rxdma);
169 1.5.6.2 nathanw
170 1.5.6.2 nathanw /* disable transmit DMA */
171 1.5.6.2 nathanw dbdma_reset(sc->sc_txdma);
172 1.5.6.2 nathanw
173 1.5.6.2 nathanw /* install interrupt handlers */
174 1.5.6.2 nathanw /*intr_establish(ca->ca_intr[1], IST_LEVEL, IPL_NET, mc_dmaintr, sc);*/
175 1.5.6.2 nathanw intr_establish(ca->ca_intr[2], IST_LEVEL, IPL_NET, mc_dmaintr, sc);
176 1.5.6.2 nathanw intr_establish(ca->ca_intr[0], IST_LEVEL, IPL_NET, mcintr, sc);
177 1.5.6.2 nathanw
178 1.5.6.2 nathanw sc->sc_biucc = XMTSP_64;
179 1.5.6.2 nathanw sc->sc_fifocc = XMTFW_16 | RCVFW_64 | XMTFWU | RCVFWU |
180 1.5.6.2 nathanw XMTBRST | RCVBRST;
181 1.5.6.2 nathanw /*sc->sc_plscc = PORTSEL_10BT;*/
182 1.5.6.2 nathanw sc->sc_plscc = PORTSEL_GPSI | ENPLSIO;
183 1.5.6.2 nathanw
184 1.5.6.2 nathanw /* mcsetup returns 1 if something fails */
185 1.5.6.2 nathanw if (mcsetup(sc, myaddr)) {
186 1.5.6.2 nathanw printf("mcsetup returns non zero\n");
187 1.5.6.2 nathanw return;
188 1.5.6.2 nathanw }
189 1.5.6.2 nathanw #ifdef NOTYET
190 1.5.6.2 nathanw sc->sc_mediachange = mc_mediachange;
191 1.5.6.2 nathanw sc->sc_mediastatus = mc_mediastatus;
192 1.5.6.2 nathanw sc->sc_supmedia = mc_supmedia;
193 1.5.6.2 nathanw sc->sc_nsupmedia = N_SUPMEDIA;
194 1.5.6.2 nathanw sc->sc_defaultmedia = IFM_ETHER | IFM_10_T;
195 1.5.6.2 nathanw #endif
196 1.5.6.2 nathanw }
197 1.5.6.2 nathanw
198 1.5.6.2 nathanw /* Bus-specific initialization */
199 1.5.6.2 nathanw hide void
200 1.5.6.2 nathanw mc_init(sc)
201 1.5.6.2 nathanw struct mc_softc *sc;
202 1.5.6.2 nathanw {
203 1.5.6.2 nathanw mc_reset_rxdma(sc);
204 1.5.6.2 nathanw mc_reset_txdma(sc);
205 1.5.6.2 nathanw }
206 1.5.6.2 nathanw
207 1.5.6.2 nathanw hide void
208 1.5.6.2 nathanw mc_putpacket(sc, len)
209 1.5.6.2 nathanw struct mc_softc *sc;
210 1.5.6.2 nathanw u_int len;
211 1.5.6.2 nathanw {
212 1.5.6.2 nathanw dbdma_command_t *cmd = sc->sc_txdmacmd;
213 1.5.6.2 nathanw
214 1.5.6.2 nathanw DBDMA_BUILD(cmd, DBDMA_CMD_OUT_LAST, 0, len, sc->sc_txbuf_phys,
215 1.5.6.2 nathanw DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
216 1.5.6.2 nathanw
217 1.5.6.2 nathanw dbdma_start(sc->sc_txdma, sc->sc_txdmacmd);
218 1.5.6.2 nathanw }
219 1.5.6.2 nathanw
220 1.5.6.2 nathanw /*
221 1.5.6.2 nathanw * Interrupt handler for the MACE DMA completion interrupts
222 1.5.6.2 nathanw */
223 1.5.6.2 nathanw int
224 1.5.6.2 nathanw mc_dmaintr(arg)
225 1.5.6.2 nathanw void *arg;
226 1.5.6.2 nathanw {
227 1.5.6.2 nathanw struct mc_softc *sc = arg;
228 1.5.6.2 nathanw int status, offset, statoff;
229 1.5.6.2 nathanw int datalen, resid;
230 1.5.6.2 nathanw int i, n;
231 1.5.6.2 nathanw dbdma_command_t *cmd;
232 1.5.6.2 nathanw
233 1.5.6.2 nathanw /* We've received some packets from the MACE */
234 1.5.6.2 nathanw
235 1.5.6.2 nathanw /* Loop through, processing each of the packets */
236 1.5.6.2 nathanw i = sc->sc_tail;
237 1.5.6.2 nathanw for (n = 0; n < MC_RXDMABUFS; n++, i++) {
238 1.5.6.2 nathanw if (i == MC_RXDMABUFS)
239 1.5.6.2 nathanw i = 0;
240 1.5.6.2 nathanw
241 1.5.6.2 nathanw cmd = &sc->sc_rxdmacmd[i];
242 1.5.6.2 nathanw /* flushcache(cmd, sizeof(dbdma_command_t)); */
243 1.5.6.2 nathanw status = dbdma_ld16(&cmd->d_status);
244 1.5.6.2 nathanw resid = dbdma_ld16(&cmd->d_resid);
245 1.5.6.2 nathanw
246 1.5.6.2 nathanw /*if ((status & D_ACTIVE) == 0)*/
247 1.5.6.2 nathanw if ((status & 0x40) == 0)
248 1.5.6.2 nathanw continue;
249 1.5.6.2 nathanw
250 1.5.6.2 nathanw #if 1
251 1.5.6.2 nathanw if (dbdma_ld16(&cmd->d_count) != ETHERMTU + 22)
252 1.5.6.2 nathanw printf("bad d_count\n");
253 1.5.6.2 nathanw #endif
254 1.5.6.2 nathanw
255 1.5.6.2 nathanw datalen = dbdma_ld16(&cmd->d_count) - resid;
256 1.5.6.2 nathanw datalen -= 4; /* 4 == status bytes */
257 1.5.6.2 nathanw
258 1.5.6.2 nathanw if (datalen < 4 + sizeof(struct ether_header)) {
259 1.5.6.2 nathanw printf("short packet len=%d\n", datalen);
260 1.5.6.2 nathanw /* continue; */
261 1.5.6.2 nathanw goto next;
262 1.5.6.2 nathanw }
263 1.5.6.2 nathanw
264 1.5.6.2 nathanw offset = i * MC_BUFSIZE;
265 1.5.6.2 nathanw statoff = offset + datalen;
266 1.5.6.2 nathanw
267 1.5.6.2 nathanw DBDMA_BUILD_CMD(cmd, DBDMA_CMD_STOP, 0, 0, 0, 0);
268 1.5.6.2 nathanw __asm __volatile("eieio");
269 1.5.6.2 nathanw
270 1.5.6.2 nathanw /* flushcache(sc->sc_rxbuf + offset, datalen + 4); */
271 1.5.6.2 nathanw
272 1.5.6.2 nathanw sc->sc_rxframe.rx_rcvcnt = sc->sc_rxbuf[statoff + 0];
273 1.5.6.2 nathanw sc->sc_rxframe.rx_rcvsts = sc->sc_rxbuf[statoff + 1];
274 1.5.6.2 nathanw sc->sc_rxframe.rx_rntpc = sc->sc_rxbuf[statoff + 2];
275 1.5.6.2 nathanw sc->sc_rxframe.rx_rcvcc = sc->sc_rxbuf[statoff + 3];
276 1.5.6.2 nathanw sc->sc_rxframe.rx_frame = sc->sc_rxbuf + offset;
277 1.5.6.2 nathanw
278 1.5.6.2 nathanw mc_rint(sc);
279 1.5.6.2 nathanw
280 1.5.6.2 nathanw next:
281 1.5.6.2 nathanw DBDMA_BUILD_CMD(cmd, DBDMA_CMD_IN_LAST, 0, DBDMA_INT_ALWAYS,
282 1.5.6.2 nathanw DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
283 1.5.6.2 nathanw __asm __volatile("eieio");
284 1.5.6.2 nathanw cmd->d_status = 0;
285 1.5.6.2 nathanw cmd->d_resid = 0;
286 1.5.6.2 nathanw sc->sc_tail = i + 1;
287 1.5.6.2 nathanw }
288 1.5.6.2 nathanw
289 1.5.6.2 nathanw dbdma_continue(sc->sc_rxdma);
290 1.5.6.2 nathanw
291 1.5.6.2 nathanw return 1;
292 1.5.6.2 nathanw }
293 1.5.6.2 nathanw
294 1.5.6.2 nathanw hide void
295 1.5.6.2 nathanw mc_reset_rxdma(sc)
296 1.5.6.2 nathanw struct mc_softc *sc;
297 1.5.6.2 nathanw {
298 1.5.6.2 nathanw dbdma_command_t *cmd = sc->sc_rxdmacmd;
299 1.5.6.2 nathanw dbdma_regmap_t *dmareg = sc->sc_rxdma;
300 1.5.6.2 nathanw int i;
301 1.5.6.2 nathanw u_int8_t maccc;
302 1.5.6.2 nathanw
303 1.5.6.2 nathanw /* Disable receiver, reset the DMA channels */
304 1.5.6.2 nathanw maccc = NIC_GET(sc, MACE_MACCC);
305 1.5.6.2 nathanw NIC_PUT(sc, MACE_MACCC, maccc & ~ENRCV);
306 1.5.6.2 nathanw
307 1.5.6.2 nathanw dbdma_reset(dmareg);
308 1.5.6.2 nathanw
309 1.5.6.2 nathanw for (i = 0; i < MC_RXDMABUFS; i++) {
310 1.5.6.2 nathanw DBDMA_BUILD(cmd, DBDMA_CMD_IN_LAST, 0, ETHERMTU + 22,
311 1.5.6.2 nathanw sc->sc_rxbuf_phys + MC_BUFSIZE * i, DBDMA_INT_ALWAYS,
312 1.5.6.2 nathanw DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
313 1.5.6.2 nathanw cmd++;
314 1.5.6.2 nathanw }
315 1.5.6.2 nathanw
316 1.5.6.2 nathanw DBDMA_BUILD(cmd, DBDMA_CMD_NOP, 0, 0, 0,
317 1.5.6.2 nathanw DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_ALWAYS);
318 1.5.6.2 nathanw dbdma_st32(&cmd->d_cmddep, kvtop((caddr_t)sc->sc_rxdmacmd));
319 1.5.6.2 nathanw cmd++;
320 1.5.6.2 nathanw
321 1.5.6.2 nathanw dbdma_start(dmareg, sc->sc_rxdmacmd);
322 1.5.6.2 nathanw
323 1.5.6.2 nathanw sc->sc_tail = 0;
324 1.5.6.2 nathanw
325 1.5.6.2 nathanw /* Reenable receiver, reenable DMA */
326 1.5.6.2 nathanw NIC_PUT(sc, MACE_MACCC, maccc);
327 1.5.6.2 nathanw }
328 1.5.6.2 nathanw
329 1.5.6.2 nathanw hide void
330 1.5.6.2 nathanw mc_reset_txdma(sc)
331 1.5.6.2 nathanw struct mc_softc *sc;
332 1.5.6.2 nathanw {
333 1.5.6.2 nathanw dbdma_command_t *cmd = sc->sc_txdmacmd;
334 1.5.6.2 nathanw dbdma_regmap_t *dmareg = sc->sc_txdma;
335 1.5.6.2 nathanw u_int8_t maccc;
336 1.5.6.2 nathanw
337 1.5.6.2 nathanw /* disable transmitter */
338 1.5.6.2 nathanw maccc = NIC_GET(sc, MACE_MACCC);
339 1.5.6.2 nathanw NIC_PUT(sc, MACE_MACCC, maccc & ~ENXMT);
340 1.5.6.2 nathanw
341 1.5.6.2 nathanw dbdma_reset(dmareg);
342 1.5.6.2 nathanw
343 1.5.6.2 nathanw DBDMA_BUILD(cmd, DBDMA_CMD_OUT_LAST, 0, 0, sc->sc_txbuf_phys,
344 1.5.6.2 nathanw DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
345 1.5.6.2 nathanw cmd++;
346 1.5.6.2 nathanw DBDMA_BUILD(cmd, DBDMA_CMD_STOP, 0, 0, 0,
347 1.5.6.2 nathanw DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
348 1.5.6.2 nathanw
349 1.5.6.2 nathanw out32rb(&dmareg->d_cmdptrhi, 0);
350 1.5.6.2 nathanw out32rb(&dmareg->d_cmdptrlo, kvtop((caddr_t)sc->sc_txdmacmd));
351 1.5.6.2 nathanw
352 1.5.6.2 nathanw /* restore old value */
353 1.5.6.2 nathanw NIC_PUT(sc, MACE_MACCC, maccc);
354 1.5.6.2 nathanw }
355 1.5.6.2 nathanw
356 1.5.6.2 nathanw void
357 1.5.6.2 nathanw mc_select_utp(sc)
358 1.5.6.2 nathanw struct mc_softc *sc;
359 1.5.6.2 nathanw {
360 1.5.6.2 nathanw sc->sc_plscc = PORTSEL_GPSI | ENPLSIO;
361 1.5.6.2 nathanw }
362 1.5.6.2 nathanw
363 1.5.6.2 nathanw void
364 1.5.6.2 nathanw mc_select_aui(sc)
365 1.5.6.2 nathanw struct mc_softc *sc;
366 1.5.6.2 nathanw {
367 1.5.6.2 nathanw sc->sc_plscc = PORTSEL_AUI;
368 1.5.6.2 nathanw }
369 1.5.6.2 nathanw
370 1.5.6.2 nathanw int
371 1.5.6.2 nathanw mc_mediachange(sc)
372 1.5.6.2 nathanw struct mc_softc *sc;
373 1.5.6.2 nathanw {
374 1.5.6.2 nathanw struct ifmedia *ifm = &sc->sc_media;
375 1.5.6.2 nathanw
376 1.5.6.2 nathanw if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
377 1.5.6.2 nathanw return EINVAL;
378 1.5.6.2 nathanw
379 1.5.6.2 nathanw switch (IFM_SUBTYPE(ifm->ifm_media)) {
380 1.5.6.2 nathanw
381 1.5.6.2 nathanw case IFM_10_T:
382 1.5.6.2 nathanw mc_select_utp(sc);
383 1.5.6.2 nathanw break;
384 1.5.6.2 nathanw
385 1.5.6.2 nathanw case IFM_10_5:
386 1.5.6.2 nathanw mc_select_aui(sc);
387 1.5.6.2 nathanw break;
388 1.5.6.2 nathanw
389 1.5.6.2 nathanw default:
390 1.5.6.2 nathanw return EINVAL;
391 1.5.6.2 nathanw }
392 1.5.6.2 nathanw
393 1.5.6.2 nathanw return 0;
394 1.5.6.2 nathanw }
395 1.5.6.2 nathanw
396 1.5.6.2 nathanw void
397 1.5.6.2 nathanw mc_mediastatus(sc, ifmr)
398 1.5.6.2 nathanw struct mc_softc *sc;
399 1.5.6.2 nathanw struct ifmediareq *ifmr;
400 1.5.6.2 nathanw {
401 1.5.6.2 nathanw if (sc->sc_plscc == PORTSEL_AUI)
402 1.5.6.2 nathanw ifmr->ifm_active = IFM_ETHER | IFM_10_5;
403 1.5.6.2 nathanw else
404 1.5.6.2 nathanw ifmr->ifm_active = IFM_ETHER | IFM_10_T;
405 1.5.6.2 nathanw }
406