Annotation of sys/arch/vax/qbus/if_de.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_de.c,v 1.8 2007/05/10 17:59:26 deraadt Exp $ */
2: /* $NetBSD: if_de.c,v 1.11 2001/11/13 07:11:24 lukem Exp $ */
3:
4: /*
5: * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
6: * Copyright (c) 2000 Ludd, University of Lule}, Sweden.
7: * All rights reserved.
8: *
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. Neither the name of the University nor the names of its contributors
19: * may be used to endorse or promote products derived from this software
20: * without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32: * SUCH DAMAGE.
33: *
34: * @(#)if_de.c 7.12 (Berkeley) 12/16/90
35: */
36:
37: /*
38: * DEC DEUNA interface
39: *
40: * Lou Salkind
41: * New York University
42: *
43: * Rewritten by Ragge 30 April 2000 to match new world.
44: *
45: * TODO:
46: * timeout routine (get statistics)
47: */
48:
49: #include "bpfilter.h"
50:
51: #include <sys/param.h>
52: #include <sys/systm.h>
53: #include <sys/mbuf.h>
54: #include <sys/buf.h>
55: #include <sys/protosw.h>
56: #include <sys/socket.h>
57: #include <sys/ioctl.h>
58: #include <sys/errno.h>
59: #include <sys/syslog.h>
60: #include <sys/device.h>
61:
62: #include <net/if.h>
63: #include <net/if_ether.h>
64: #include <net/if_dl.h>
65:
66: #ifdef INET
67: #include <netinet/in.h>
68: #include <netinet/if_inarp.h>
69: #endif
70:
71: #if NBPFILTER > 0
72: #include <net/bpf.h>
73: #include <net/bpfdesc.h>
74: #endif
75:
76: #include <machine/bus.h>
77:
78: #include <dev/qbus/ubavar.h>
79: #include <dev/qbus/if_dereg.h>
80: #include <dev/qbus/if_uba.h>
81:
82: /*
83: * Be careful with transmit/receive buffers, each entry steals 4 map
84: * registers, and there is only 496 on one unibus...
85: */
86: #define NRCV 7 /* number of receive buffers (must be > 1) */
87: #define NXMT 3 /* number of transmit buffers */
88:
89: /*
90: * Structure containing the elements that must be in DMA-safe memory.
91: */
92: struct de_cdata {
93: /* the following structures are always mapped in */
94: struct de_pcbb dc_pcbb; /* port control block */
95: struct de_ring dc_xrent[NXMT]; /* transmit ring entries */
96: struct de_ring dc_rrent[NRCV]; /* receive ring entries */
97: struct de_udbbuf dc_udbbuf; /* UNIBUS data buffer */
98: /* end mapped area */
99: };
100:
101: /*
102: * Ethernet software status per interface.
103: *
104: * Each interface is referenced by a network interface structure,
105: * ds_if, which the routing code uses to locate the interface.
106: * This structure contains the output queue for the interface, its address, ...
107: * We also have, for each interface, a UBA interface structure, which
108: * contains information about the UNIBUS resources held by the interface:
109: * map registers, buffered data paths, etc. Information is cached in this
110: * structure for use by the if_uba.c routines in running the interface
111: * efficiently.
112: */
113: struct de_softc {
114: struct device sc_dev; /* Configuration common part */
115: struct ethercom sc_ec; /* Ethernet common part */
116: #define sc_if sc_ec.ec_if /* network-visible interface */
117: bus_space_tag_t sc_iot;
118: bus_addr_t sc_ioh;
119: bus_dma_tag_t sc_dmat;
120: int sc_flags;
121: #define DSF_MAPPED 1
122: struct ubinfo sc_ui;
123: struct de_cdata *sc_dedata; /* Control structure */
124: struct de_cdata *sc_pdedata; /* Bus-mapped control structure */
125: struct ifubinfo sc_ifuba; /* UNIBUS resources */
126: struct ifrw sc_ifr[NRCV]; /* UNIBUS receive buffer maps */
127: struct ifxmt sc_ifw[NXMT]; /* UNIBUS receive buffer maps */
128:
129: int sc_xindex; /* UNA index into transmit chain */
130: int sc_rindex; /* UNA index into receive chain */
131: int sc_xfree; /* index for next transmit buffer */
132: int sc_nxmit; /* # of transmits in progress */
133: void *sc_sh; /* shutdownhook cookie */
134: };
135:
136: static int dematch(struct device *, struct cfdata *, void *);
137: static void deattach(struct device *, struct device *, void *);
138: static void dewait(struct de_softc *, char *);
139: static int deinit(struct ifnet *);
140: static int deioctl(struct ifnet *, u_long, caddr_t);
141: static void dereset(struct device *);
142: static void destop(struct ifnet *, int);
143: static void destart(struct ifnet *);
144: static void derecv(struct de_softc *);
145: static void deintr(void *);
146: static void deshutdown(void *);
147:
148: struct cfattach de_ca = {
149: sizeof(struct de_softc), dematch, deattach
150: };
151:
152: #define DE_WCSR(csr, val) \
153: bus_space_write_2(sc->sc_iot, sc->sc_ioh, csr, val)
154: #define DE_WLOW(val) \
155: bus_space_write_1(sc->sc_iot, sc->sc_ioh, DE_PCSR0, val)
156: #define DE_WHIGH(val) \
157: bus_space_write_1(sc->sc_iot, sc->sc_ioh, DE_PCSR0 + 1, val)
158: #define DE_RCSR(csr) \
159: bus_space_read_2(sc->sc_iot, sc->sc_ioh, csr)
160:
161: #define LOWORD(x) ((int)(x) & 0xffff)
162: #define HIWORD(x) (((int)(x) >> 16) & 0x3)
163: /*
164: * Interface exists: make available by filling in network interface
165: * record. System will initialize the interface when it is ready
166: * to accept packets. We get the ethernet address here.
167: */
168: void
169: deattach(struct device *parent, struct device *self, void *aux)
170: {
171: struct uba_attach_args *ua = aux;
172: struct de_softc *sc = (struct de_softc *)self;
173: struct ifnet *ifp = &sc->sc_if;
174: u_int8_t myaddr[ETHER_ADDR_LEN];
175: int csr1, error;
176: char *c;
177:
178: sc->sc_iot = ua->ua_iot;
179: sc->sc_ioh = ua->ua_ioh;
180: sc->sc_dmat = ua->ua_dmat;
181:
182: /*
183: * What kind of a board is this?
184: * The error bits 4-6 in pcsr1 are a device id as long as
185: * the high byte is zero.
186: */
187: csr1 = DE_RCSR(DE_PCSR1);
188: if (csr1 & 0xff60)
189: c = "broken";
190: else if (csr1 & 0x10)
191: c = "delua";
192: else
193: c = "deuna";
194:
195: /*
196: * Reset the board and temporarily map
197: * the pcbb buffer onto the Unibus.
198: */
199: DE_WCSR(DE_PCSR0, 0); /* reset INTE */
200: DELAY(100);
201: DE_WCSR(DE_PCSR0, PCSR0_RSET);
202: dewait(sc, "reset");
203:
204: sc->sc_ui.ui_size = sizeof(struct de_cdata);
205: if ((error = ubmemalloc((struct uba_softc *)parent, &sc->sc_ui, 0)))
206: return printf(": failed ubmemalloc(), error = %d\n", error);
207: sc->sc_dedata = (struct de_cdata *)sc->sc_ui.ui_vaddr;
208:
209: /*
210: * Tell the DEUNA about our PCB
211: */
212: DE_WCSR(DE_PCSR2, LOWORD(sc->sc_ui.ui_baddr));
213: DE_WCSR(DE_PCSR3, HIWORD(sc->sc_ui.ui_baddr));
214: DE_WLOW(CMD_GETPCBB);
215: dewait(sc, "pcbb");
216:
217: sc->sc_dedata->dc_pcbb.pcbb0 = FC_RDPHYAD;
218: DE_WLOW(CMD_GETCMD);
219: dewait(sc, "read addr ");
220:
221: bcopy((caddr_t)&sc->sc_dedata->dc_pcbb.pcbb2, myaddr, sizeof (myaddr));
222: printf(": %s, address %s\n", c, ether_sprintf(myaddr));
223:
224: uba_intr_establish(ua->ua_icookie, ua->ua_cvec, deintr, sc,
225: &sc->sc_intrcnt);
226: uba_reset_establish(dereset, &sc->sc_dev);
227:
228: strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, sizeof ifp->if_xname);
229: ifp->if_softc = sc;
230: ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI;
231: ifp->if_ioctl = deioctl;
232: ifp->if_start = destart;
233: ifp->if_init = deinit;
234: ifp->if_stop = destop;
235: IFQ_SET_READY(&ifp->if_snd);
236:
237: if_attach(ifp);
238: ether_ifattach(ifp, myaddr);
239: ubmemfree((struct uba_softc *)parent, &sc->sc_ui);
240:
241: sc->sc_sh = shutdownhook_establish(deshutdown, sc);
242: }
243:
244: void
245: destop(struct ifnet *ifp, int a)
246: {
247: struct de_softc *sc = ifp->if_softc;
248:
249: DE_WLOW(0);
250: DELAY(5000);
251: DE_WLOW(PCSR0_RSET);
252: }
253:
254:
255: /*
256: * Reset of interface after UNIBUS reset.
257: */
258: void
259: dereset(struct device *dev)
260: {
261: struct de_softc *sc = (void *)dev;
262:
263: sc->sc_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
264: sc->sc_flags &= ~DSF_MAPPED;
265: sc->sc_pdedata = NULL; /* All mappings lost */
266: DE_WCSR(DE_PCSR0, PCSR0_RSET);
267: dewait(sc, "reset");
268: deinit(&sc->sc_if);
269: }
270:
271: /*
272: * Initialization of interface; clear recorded pending
273: * operations, and reinitialize UNIBUS usage.
274: */
275: int
276: deinit(struct ifnet *ifp)
277: {
278: struct de_softc *sc = ifp->if_softc;
279: struct de_cdata *dc, *pdc;
280: struct ifrw *ifrw;
281: struct ifxmt *ifxp;
282: struct de_ring *rp;
283: int s, error;
284:
285: if (ifp->if_flags & IFF_RUNNING)
286: return 0;
287: if ((sc->sc_flags & DSF_MAPPED) == 0) {
288: if (if_ubaminit(&sc->sc_ifuba, (void *)sc->sc_dev.dv_parent,
289: MCLBYTES, sc->sc_ifr, NRCV, sc->sc_ifw, NXMT)) {
290: printf("%s: can't initialize\n", sc->sc_dev.dv_xname);
291: ifp->if_flags &= ~IFF_UP;
292: return 0;
293: }
294: sc->sc_ui.ui_size = sizeof(struct de_cdata);
295: if ((error = ubmemalloc((void *)sc->sc_dev.dv_parent,
296: &sc->sc_ui, 0))) {
297: printf(": unable to ubmemalloc(), error = %d\n", error);
298: return 0;
299: }
300: sc->sc_pdedata = (struct de_cdata *)sc->sc_ui.ui_baddr;
301: sc->sc_dedata = (struct de_cdata *)sc->sc_ui.ui_vaddr;
302: sc->sc_flags |= DSF_MAPPED;
303: }
304:
305: /*
306: * Tell the DEUNA about our PCB
307: */
308: DE_WCSR(DE_PCSR2, LOWORD(sc->sc_pdedata));
309: DE_WCSR(DE_PCSR3, HIWORD(sc->sc_pdedata));
310: DE_WLOW(0); /* reset INTE */
311: DELAY(500);
312: DE_WLOW(CMD_GETPCBB);
313: dewait(sc, "pcbb");
314:
315: dc = sc->sc_dedata;
316: pdc = sc->sc_pdedata;
317: /* set the transmit and receive ring header addresses */
318: dc->dc_pcbb.pcbb0 = FC_WTRING;
319: dc->dc_pcbb.pcbb2 = LOWORD(&pdc->dc_udbbuf);
320: dc->dc_pcbb.pcbb4 = HIWORD(&pdc->dc_udbbuf);
321:
322: dc->dc_udbbuf.b_tdrbl = LOWORD(&pdc->dc_xrent[0]);
323: dc->dc_udbbuf.b_tdrbh = HIWORD(&pdc->dc_xrent[0]);
324: dc->dc_udbbuf.b_telen = sizeof (struct de_ring) / sizeof(u_int16_t);
325: dc->dc_udbbuf.b_trlen = NXMT;
326: dc->dc_udbbuf.b_rdrbl = LOWORD(&pdc->dc_rrent[0]);
327: dc->dc_udbbuf.b_rdrbh = HIWORD(&pdc->dc_rrent[0]);
328: dc->dc_udbbuf.b_relen = sizeof (struct de_ring) / sizeof(u_int16_t);
329: dc->dc_udbbuf.b_rrlen = NRCV;
330:
331: DE_WLOW(CMD_GETCMD);
332: dewait(sc, "wtring");
333:
334: sc->sc_dedata->dc_pcbb.pcbb0 = FC_WTMODE;
335: sc->sc_dedata->dc_pcbb.pcbb2 = MOD_TPAD|MOD_HDX|MOD_DRDC|MOD_ENAL;
336: DE_WLOW(CMD_GETCMD);
337: dewait(sc, "wtmode");
338:
339: /* set up the receive and transmit ring entries */
340: ifxp = &sc->sc_ifw[0];
341: for (rp = &dc->dc_xrent[0]; rp < &dc->dc_xrent[NXMT]; rp++) {
342: rp->r_segbl = LOWORD(ifxp->ifw_info);
343: rp->r_segbh = HIWORD(ifxp->ifw_info);
344: rp->r_flags = 0;
345: ifxp++;
346: }
347: ifrw = &sc->sc_ifr[0];
348: for (rp = &dc->dc_rrent[0]; rp < &dc->dc_rrent[NRCV]; rp++) {
349: rp->r_slen = MCLBYTES - 2;
350: rp->r_segbl = LOWORD(ifrw->ifrw_info);
351: rp->r_segbh = HIWORD(ifrw->ifrw_info);
352: rp->r_flags = RFLG_OWN;
353: ifrw++;
354: }
355:
356: /* start up the board (rah rah) */
357: s = splnet();
358: sc->sc_rindex = sc->sc_xindex = sc->sc_xfree = sc->sc_nxmit = 0;
359: sc->sc_if.if_flags |= IFF_RUNNING;
360: DE_WLOW(PCSR0_INTE); /* avoid interlock */
361: destart(&sc->sc_if); /* queue output packets */
362: DE_WLOW(CMD_START|PCSR0_INTE);
363: splx(s);
364: return 0;
365: }
366:
367: /*
368: * Setup output on interface.
369: * Get another datagram to send off of the interface queue,
370: * and map it to the interface before starting the output.
371: * Must be called from ipl >= our interrupt level.
372: */
373: void
374: destart(struct ifnet *ifp)
375: {
376: struct de_softc *sc = ifp->if_softc;
377: struct de_cdata *dc;
378: struct de_ring *rp;
379: struct mbuf *m;
380: int nxmit, len;
381:
382: /*
383: * the following test is necessary, since
384: * the code is not reentrant and we have
385: * multiple transmission buffers.
386: */
387: if (sc->sc_if.if_flags & IFF_OACTIVE)
388: return;
389: dc = sc->sc_dedata;
390: for (nxmit = sc->sc_nxmit; nxmit < NXMT; nxmit++) {
391: IFQ_DEQUEUE(&ifp->if_snd, m);
392: if (m == 0)
393: break;
394:
395: rp = &dc->dc_xrent[sc->sc_xfree];
396: if (rp->r_flags & XFLG_OWN)
397: panic("deuna xmit in progress");
398: #if NBPFILTER > 0
399: if (ifp->if_bpf)
400: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
401: #endif
402:
403: len = if_ubaput(&sc->sc_ifuba, &sc->sc_ifw[sc->sc_xfree], m);
404: rp->r_slen = len;
405: rp->r_tdrerr = 0;
406: rp->r_flags = XFLG_STP|XFLG_ENP|XFLG_OWN;
407:
408: sc->sc_xfree++;
409: if (sc->sc_xfree == NXMT)
410: sc->sc_xfree = 0;
411: }
412: if (sc->sc_nxmit != nxmit) {
413: sc->sc_nxmit = nxmit;
414: if (ifp->if_flags & IFF_RUNNING)
415: DE_WLOW(PCSR0_INTE|CMD_PDMD);
416: }
417: }
418:
419: /*
420: * Command done interrupt.
421: */
422: void
423: deintr(void *arg)
424: {
425: struct ifxmt *ifxp;
426: struct de_cdata *dc;
427: struct de_softc *sc = arg;
428: struct de_ring *rp;
429: short csr0;
430:
431: /* save flags right away - clear out interrupt bits */
432: csr0 = DE_RCSR(DE_PCSR0);
433: DE_WHIGH(csr0 >> 8);
434:
435:
436: sc->sc_if.if_flags |= IFF_OACTIVE; /* prevent entering destart */
437: /*
438: * if receive, put receive buffer on mbuf
439: * and hang the request again
440: */
441: derecv(sc);
442:
443: /*
444: * Poll transmit ring and check status.
445: * Be careful about loopback requests.
446: * Then free buffer space and check for
447: * more transmit requests.
448: */
449: dc = sc->sc_dedata;
450: for ( ; sc->sc_nxmit > 0; sc->sc_nxmit--) {
451: rp = &dc->dc_xrent[sc->sc_xindex];
452: if (rp->r_flags & XFLG_OWN)
453: break;
454:
455: sc->sc_if.if_opackets++;
456: ifxp = &sc->sc_ifw[sc->sc_xindex];
457: /* check for unusual conditions */
458: if (rp->r_flags & (XFLG_ERRS|XFLG_MTCH|XFLG_ONE|XFLG_MORE)) {
459: if (rp->r_flags & XFLG_ERRS) {
460: /* output error */
461: sc->sc_if.if_oerrors++;
462: } else if (rp->r_flags & XFLG_ONE) {
463: /* one collision */
464: sc->sc_if.if_collisions++;
465: } else if (rp->r_flags & XFLG_MORE) {
466: /* more than one collision */
467: sc->sc_if.if_collisions += 2; /* guess */
468: }
469: }
470: if_ubaend(&sc->sc_ifuba, ifxp);
471: /* check if next transmit buffer also finished */
472: sc->sc_xindex++;
473: if (sc->sc_xindex == NXMT)
474: sc->sc_xindex = 0;
475: }
476: sc->sc_if.if_flags &= ~IFF_OACTIVE;
477: destart(&sc->sc_if);
478:
479: if (csr0 & PCSR0_RCBI) {
480: DE_WLOW(PCSR0_INTE|CMD_PDMD);
481: }
482: }
483:
484: /*
485: * Ethernet interface receiver interface.
486: * If input error just drop packet.
487: * Otherwise purge input buffered data path and examine
488: * packet to determine type. If can't determine length
489: * from type, then have to drop packet. Othewise decapsulate
490: * packet based on type and pass to type specific higher-level
491: * input routine.
492: */
493: void
494: derecv(struct de_softc *sc)
495: {
496: struct ifnet *ifp = &sc->sc_if;
497: struct de_ring *rp;
498: struct de_cdata *dc;
499: struct mbuf *m;
500: int len;
501:
502: dc = sc->sc_dedata;
503: rp = &dc->dc_rrent[sc->sc_rindex];
504: while ((rp->r_flags & RFLG_OWN) == 0) {
505: sc->sc_if.if_ipackets++;
506: len = (rp->r_lenerr&RERR_MLEN) - ETHER_CRC_LEN;
507: /* check for errors */
508: if ((rp->r_flags & (RFLG_ERRS|RFLG_FRAM|RFLG_OFLO|RFLG_CRC)) ||
509: (rp->r_lenerr & (RERR_BUFL|RERR_UBTO))) {
510: sc->sc_if.if_ierrors++;
511: goto next;
512: }
513: m = if_ubaget(&sc->sc_ifuba, &sc->sc_ifr[sc->sc_rindex],
514: ifp, len);
515: if (m == 0) {
516: sc->sc_if.if_ierrors++;
517: goto next;
518: }
519: #if NBPFILTER > 0
520: if (ifp->if_bpf)
521: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
522: #endif
523:
524: (*ifp->if_input)(ifp, m);
525:
526: /* hang the receive buffer again */
527: next: rp->r_lenerr = 0;
528: rp->r_flags = RFLG_OWN;
529:
530: /* check next receive buffer */
531: sc->sc_rindex++;
532: if (sc->sc_rindex == NRCV)
533: sc->sc_rindex = 0;
534: rp = &dc->dc_rrent[sc->sc_rindex];
535: }
536: }
537:
538: /*
539: * Process an ioctl request.
540: */
541: int
542: deioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
543: {
544: int s, error = 0;
545:
546: s = splnet();
547:
548: error = ether_ioctl(ifp, cmd, data);
549: if (error == ENETRESET)
550: error = 0;
551:
552: splx(s);
553: return (error);
554: }
555:
556: /*
557: * Await completion of the named function
558: * and check for errors.
559: */
560: void
561: dewait(struct de_softc *sc, char *fn)
562: {
563: int csr0;
564:
565: while ((DE_RCSR(DE_PCSR0) & PCSR0_INTR) == 0)
566: ;
567: csr0 = DE_RCSR(DE_PCSR0);
568: DE_WHIGH(csr0 >> 8);
569: if (csr0 & PCSR0_PCEI) {
570: char bits[64];
571: printf("%s: %s failed, csr0=%s ", sc->sc_dev.dv_xname, fn,
572: bitmask_snprintf(csr0, PCSR0_BITS, bits, sizeof(bits)));
573: printf("csr1=%s\n", bitmask_snprintf(DE_RCSR(DE_PCSR1),
574: PCSR1_BITS, bits, sizeof(bits)));
575: }
576: }
577:
578: int
579: dematch(struct device *parent, struct cfdata *cf, void *aux)
580: {
581: struct uba_attach_args *ua = aux;
582: struct de_softc ssc;
583: struct de_softc *sc = &ssc;
584: int i;
585:
586: sc->sc_iot = ua->ua_iot;
587: sc->sc_ioh = ua->ua_ioh;
588: /*
589: * Make sure self-test is finished before we screw with the board.
590: * Self-test on a DELUA can take 15 seconds (argh).
591: */
592: for (i = 0;
593: (i < 160) &&
594: (DE_RCSR(DE_PCSR0) & PCSR0_FATI) == 0 &&
595: (DE_RCSR(DE_PCSR1) & PCSR1_STMASK) == STAT_RESET;
596: ++i)
597: DELAY(50000);
598: if (((DE_RCSR(DE_PCSR0) & PCSR0_FATI) != 0) ||
599: (((DE_RCSR(DE_PCSR1) & PCSR1_STMASK) != STAT_READY) &&
600: ((DE_RCSR(DE_PCSR1) & PCSR1_STMASK) != STAT_RUN)))
601: return(0);
602:
603: DE_WCSR(DE_PCSR0, 0);
604: DELAY(5000);
605: DE_WCSR(DE_PCSR0, PCSR0_RSET);
606: while ((DE_RCSR(DE_PCSR0) & PCSR0_INTR) == 0)
607: ;
608: /* make board interrupt by executing a GETPCBB command */
609: DE_WCSR(DE_PCSR0, PCSR0_INTE);
610: DE_WCSR(DE_PCSR2, 0);
611: DE_WCSR(DE_PCSR3, 0);
612: DE_WCSR(DE_PCSR0, PCSR0_INTE|CMD_GETPCBB);
613: DELAY(50000);
614:
615: return 1;
616: }
617:
618: void
619: deshutdown(void *arg)
620: {
621: struct de_softc *sc = arg;
622:
623: DE_WCSR(DE_PCSR0, 0);
624: DELAY(1000);
625: DE_WCSR(DE_PCSR0, PCSR0_RSET);
626: dewait(sc, "shutdown");
627: }
CVSweb