This source file includes following definitions.
- wait_WOC
- read16
- cnw_cmd
- cnw_reset
- cnw_init
- cnw_enable
- cnw_disable
- cnw_match
- cnw_attach
- cnw_start
- cnw_transmit
- cnw_read
- cnw_recv
- cnw_intr
- cnw_ioctl
- cnw_watchdog
- cnw_detach
- cnw_activate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 #include "bpfilter.h"
61
62 #include <sys/param.h>
63 #include <sys/systm.h>
64 #include <sys/device.h>
65 #include <sys/socket.h>
66 #include <sys/mbuf.h>
67 #include <sys/ioctl.h>
68
69 #include <dev/pcmcia/if_cnwreg.h>
70
71 #include <dev/pcmcia/pcmciareg.h>
72 #include <dev/pcmcia/pcmciavar.h>
73 #include <dev/pcmcia/pcmciadevs.h>
74
75 #include <net/if.h>
76 #include <net/if_dl.h>
77
78 #ifdef INET
79 #include <netinet/in.h>
80 #include <netinet/in_systm.h>
81 #include <netinet/in_var.h>
82 #include <netinet/ip.h>
83 #include <netinet/if_ether.h>
84 #endif
85
86 #if NBPFILTER > 0
87 #include <net/bpf.h>
88 #endif
89
90
91
92
93
94
95
96
97 #ifndef CNW_DOMAIN
98 #define CNW_DOMAIN 0x100
99 #endif
100 int cnw_domain = CNW_DOMAIN;
101 #ifndef CNW_SCRAMBLEKEY
102 #define CNW_SCRAMBLEKEY 0
103 #endif
104 int cnw_skey = CNW_SCRAMBLEKEY;
105
106
107 int cnw_match(struct device *, void *, void *);
108 void cnw_attach(struct device *, struct device *, void *);
109 int cnw_detach(struct device *, int);
110 int cnw_activate(struct device *, enum devact);
111
112 struct cnw_softc {
113 struct device sc_dev;
114 struct arpcom sc_arpcom;
115 int sc_domain;
116 int sc_skey;
117
118
119 struct pcmcia_function *sc_pf;
120 struct pcmcia_io_handle sc_pcioh;
121 int sc_iowin;
122 bus_space_tag_t sc_iot;
123 bus_space_handle_t sc_ioh;
124 struct pcmcia_mem_handle sc_pcmemh;
125 bus_addr_t sc_memoff;
126 int sc_memwin;
127 bus_space_tag_t sc_memt;
128 bus_space_handle_t sc_memh;
129 void *sc_ih;
130 };
131
132 struct cfattach cnw_ca = {
133 sizeof(struct cnw_softc), cnw_match, cnw_attach,
134 cnw_detach, cnw_activate
135 };
136
137 struct cfdriver cnw_cd = {
138 NULL, "cnw", DV_IFNET
139 };
140
141 void cnw_reset(struct cnw_softc *);
142 void cnw_init(struct cnw_softc *);
143 int cnw_enable(struct cnw_softc *sc);
144 void cnw_disable(struct cnw_softc *sc);
145 void cnw_config(struct cnw_softc *sc, u_int8_t *);
146 void cnw_start(struct ifnet *);
147 void cnw_transmit(struct cnw_softc *, struct mbuf *);
148 struct mbuf *cnw_read(struct cnw_softc *);
149 void cnw_recv(struct cnw_softc *);
150 int cnw_intr(void *arg);
151 int cnw_ioctl(struct ifnet *, u_long, caddr_t);
152 void cnw_watchdog(struct ifnet *);
153
154
155
156
157 static int wait_WOC(struct cnw_softc *, int);
158 static int read16(struct cnw_softc *, int);
159 static int cnw_cmd(struct cnw_softc *, int, int, int, int);
160
161
162
163
164
165 static int
166 wait_WOC(sc, line)
167 struct cnw_softc *sc;
168 int line;
169 {
170 int i, asr;
171
172 for (i = 0; i < 5000; i++) {
173 asr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CNW_REG_ASR);
174 if (asr & CNW_ASR_WOC)
175 return (0);
176 DELAY(100);
177 }
178 if (line > 0)
179 printf("%s: wedged at line %d\n", sc->sc_dev.dv_xname, line);
180 return (1);
181 }
182 #define WAIT_WOC(sc) wait_WOC(sc, __LINE__)
183
184
185
186
187
188 static int
189 read16(sc, offset)
190 struct cnw_softc *sc;
191 int offset;
192 {
193 int hi, lo;
194
195
196
197
198
199
200 lo = bus_space_read_1(sc->sc_memt, sc->sc_memh,
201 sc->sc_memoff + offset);
202 hi = bus_space_read_1(sc->sc_memt, sc->sc_memh,
203 sc->sc_memoff + offset + 1);
204 return ((hi << 8) | lo);
205 }
206
207
208
209
210
211 int
212 cnw_cmd(sc, cmd, count, arg1, arg2)
213 struct cnw_softc *sc;
214 int cmd, count, arg1, arg2;
215 {
216 int ptr = sc->sc_memoff + CNW_EREG_CB;
217
218 if (wait_WOC(sc, 0)) {
219 printf("%s: wedged when issuing cmd 0x%x\n",
220 sc->sc_dev.dv_xname, cmd);
221
222
223
224
225
226
227 }
228
229 bus_space_write_1(sc->sc_memt, sc->sc_memh, ptr, cmd);
230 if (count > 0) {
231 bus_space_write_1(sc->sc_memt, sc->sc_memh, ptr + 1, arg1);
232 if (count > 1)
233 bus_space_write_1(sc->sc_memt, sc->sc_memh,
234 ptr + 2, arg2);
235 }
236 bus_space_write_1(sc->sc_memt, sc->sc_memh,
237 ptr + count + 1, CNW_CMD_EOC);
238 return (0);
239 }
240 #define CNW_CMD0(sc, cmd) \
241 do { cnw_cmd(sc, cmd, 0, 0, 0); } while (0)
242 #define CNW_CMD1(sc, cmd, arg1) \
243 do { cnw_cmd(sc, cmd, 1, arg1 , 0); } while (0)
244 #define CNW_CMD2(sc, cmd, arg1, arg2) \
245 do { cnw_cmd(sc, cmd, 2, arg1, arg2); } while (0)
246
247
248
249
250
251
252 void
253 cnw_reset(sc)
254 struct cnw_softc *sc;
255 {
256 #ifdef CNW_DEBUG
257 if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
258 printf("%s: resetting\n", sc->sc_dev.dv_xname);
259 #endif
260 wait_WOC(sc, 0);
261 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CNW_REG_PMR, CNW_PMR_RESET);
262 bus_space_write_1(sc->sc_memt, sc->sc_memh,
263 sc->sc_memoff + CNW_EREG_ASCC, CNW_ASR_WOC);
264 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CNW_REG_PMR, 0);
265 }
266
267
268
269
270
271 void
272 cnw_init(sc)
273 struct cnw_softc *sc;
274 {
275
276 cnw_reset(sc);
277
278
279 CNW_CMD0(sc, CNW_CMD_NOP);
280
281
282 CNW_CMD1(sc, CNW_CMD_SRC, CNW_RXCONF_RXENA | CNW_RXCONF_BCAST);
283
284
285 CNW_CMD1(sc, CNW_CMD_STC, CNW_TXCONF_TXENA);
286
287
288 CNW_CMD2(sc, CNW_CMD_SMD, sc->sc_domain, sc->sc_domain >> 8);
289
290
291 CNW_CMD2(sc, CNW_CMD_SSK, sc->sc_skey, sc->sc_skey >> 8);
292
293
294 WAIT_WOC(sc);
295 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
296 CNW_REG_IMR, CNW_IMR_IENA | CNW_IMR_RFU1);
297
298
299 CNW_CMD0(sc, CNW_CMD_ER);
300
301
302 WAIT_WOC(sc);
303 bus_space_write_1(sc->sc_iot, sc->sc_ioh, CNW_REG_COR,
304 CNW_COR_IENA | CNW_COR_LVLREQ);
305 }
306
307
308
309
310
311 int
312 cnw_enable(sc)
313 struct cnw_softc *sc;
314 {
315 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
316
317 sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET,
318 cnw_intr, sc, sc->sc_dev.dv_xname);
319 if (sc->sc_ih == NULL) {
320 printf("%s: couldn't establish interrupt handler\n",
321 sc->sc_dev.dv_xname);
322 return (EIO);
323 }
324 if (pcmcia_function_enable(sc->sc_pf) != 0) {
325 printf("%s: couldn't enable card\n", sc->sc_dev.dv_xname);
326 return (EIO);
327 }
328 cnw_init(sc);
329 ifp->if_flags |= IFF_RUNNING;
330 return (0);
331 }
332
333
334
335
336
337 void
338 cnw_disable(sc)
339 struct cnw_softc *sc;
340 {
341 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
342
343 pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
344 pcmcia_function_disable(sc->sc_pf);
345 ifp->if_flags &= ~IFF_RUNNING;
346 ifp->if_timer = 0;
347 }
348
349
350
351
352
353 int
354 cnw_match(parent, match, aux)
355 struct device *parent;
356 void *match, *aux;
357 {
358 struct pcmcia_attach_args *pa = aux;
359
360 if (pa->manufacturer == PCMCIA_VENDOR_XIRCOM &&
361 pa->product == PCMCIA_PRODUCT_XIRCOM_XIR_CNW_801)
362 return (1);
363 if (pa->manufacturer == PCMCIA_VENDOR_XIRCOM &&
364 pa->product == PCMCIA_PRODUCT_XIRCOM_XIR_CNW_802)
365 return (1);
366 return (0);
367 }
368
369
370
371
372
373 void
374 cnw_attach(parent, self, aux)
375 struct device *parent, *self;
376 void *aux;
377 {
378 struct cnw_softc *sc = (void *) self;
379 struct pcmcia_attach_args *pa = aux;
380 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
381 int i;
382
383
384 sc->sc_pf = pa->pf;
385 pcmcia_function_init(sc->sc_pf, SIMPLEQ_FIRST(&sc->sc_pf->cfe_head));
386 if (pcmcia_function_enable(sc->sc_pf)) {
387 printf(": function enable failed\n");
388 return;
389 }
390
391
392 if (pcmcia_io_alloc(sc->sc_pf, 0, CNW_IO_SIZE, CNW_IO_SIZE,
393 &sc->sc_pcioh) != 0) {
394 printf(": can't allocate i/o space\n");
395 return;
396 }
397 if (pcmcia_io_map(sc->sc_pf, PCMCIA_WIDTH_IO16, 0,
398 CNW_IO_SIZE, &sc->sc_pcioh, &sc->sc_iowin) != 0) {
399 printf(": can't map i/o space\n");
400 return;
401 }
402 sc->sc_iot = sc->sc_pcioh.iot;
403 sc->sc_ioh = sc->sc_pcioh.ioh;
404 if (pcmcia_mem_alloc(sc->sc_pf, CNW_MEM_SIZE, &sc->sc_pcmemh) != 0) {
405 printf(": can't allocate memory\n");
406 return;
407 }
408 if (pcmcia_mem_map(sc->sc_pf, PCMCIA_MEM_COMMON, CNW_MEM_ADDR,
409 CNW_MEM_SIZE, &sc->sc_pcmemh, &sc->sc_memoff,
410 &sc->sc_memwin) != 0) {
411 printf(": can't map memory\n");
412 return;
413 }
414 sc->sc_memt = sc->sc_pcmemh.memt;
415 sc->sc_memh = sc->sc_pcmemh.memh;
416
417
418 sc->sc_domain = cnw_domain;
419 sc->sc_skey = cnw_skey;
420
421
422 cnw_reset(sc);
423 for (i = 0; i < ETHER_ADDR_LEN; i++)
424 sc->sc_arpcom.ac_enaddr[i] = bus_space_read_1(sc->sc_memt,
425 sc->sc_memh, sc->sc_memoff + CNW_EREG_PA + i);
426 printf("%s: address %s\n", sc->sc_dev.dv_xname,
427 ether_sprintf(sc->sc_arpcom.ac_enaddr));
428
429
430 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
431 ifp->if_softc = sc;
432 ifp->if_start = cnw_start;
433 ifp->if_ioctl = cnw_ioctl;
434 ifp->if_watchdog = cnw_watchdog;
435 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
436 IFQ_SET_READY(&ifp->if_snd);
437
438
439 if_attach(ifp);
440 ether_ifattach(ifp);
441
442
443 pcmcia_function_disable(sc->sc_pf);
444 }
445
446
447
448
449 void
450 cnw_start(ifp)
451 struct ifnet *ifp;
452 {
453 struct cnw_softc *sc = ifp->if_softc;
454 struct mbuf *m0;
455 int asr;
456
457 #ifdef CNW_DEBUG
458 if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
459 printf("%s: cnw_start\n", ifp->if_xname);
460 #endif
461
462 for (;;) {
463
464 WAIT_WOC(sc);
465 asr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CNW_REG_ASR);
466 if (!(asr & CNW_ASR_TXBA)) {
467 #ifdef CNW_DEBUG
468 if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
469 printf("%s: no buffer space\n", ifp->if_xname);
470 #endif
471 return;
472 }
473
474 IFQ_DEQUEUE(&ifp->if_snd, m0);
475 if (m0 == 0)
476 return;
477
478 #if NBPFILTER > 0
479 if (ifp->if_bpf)
480 bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
481 #endif
482
483 cnw_transmit(sc, m0);
484 ++ifp->if_opackets;
485 ifp->if_timer = 3;
486 }
487 }
488
489
490
491
492
493 void
494 cnw_transmit(sc, m0)
495 struct cnw_softc *sc;
496 struct mbuf *m0;
497 {
498 int buffer, bufsize, bufoffset, bufptr, bufspace, len, mbytes, n;
499 struct mbuf *m;
500 u_int8_t *mptr;
501
502
503 buffer = read16(sc, CNW_EREG_TDP);
504 bufsize = read16(sc, CNW_EREG_TDP + 2);
505 bufoffset = read16(sc, CNW_EREG_TDP + 4);
506 #ifdef CNW_DEBUG
507 if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
508 printf("%s: cnw_transmit b=0x%x s=%d o=0x%x\n",
509 sc->sc_dev.dv_xname, buffer, bufsize, bufoffset);
510 #endif
511
512
513 bufptr = sc->sc_memoff + buffer + bufoffset;
514 bufspace = bufsize;
515 len = 0;
516 for (m = m0; m; ) {
517 mptr = mtod(m, u_int8_t *);
518 mbytes = m->m_len;
519 len += mbytes;
520 while (mbytes > 0) {
521 if (bufspace == 0) {
522 buffer = read16(sc, buffer);
523 bufptr = sc->sc_memoff + buffer + bufoffset;
524 bufspace = bufsize;
525 #ifdef CNW_DEBUG
526 if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
527 printf("%s: next buffer @0x%x\n",
528 sc->sc_dev.dv_xname, buffer);
529 #endif
530 }
531 n = mbytes <= bufspace ? mbytes : bufspace;
532 bus_space_write_region_1(sc->sc_memt, sc->sc_memh,
533 bufptr, mptr, n);
534 bufptr += n;
535 bufspace -= n;
536 mptr += n;
537 mbytes -= n;
538 }
539 MFREE(m, m0);
540 m = m0;
541 }
542
543
544 CNW_CMD2(sc, CNW_CMD_TL, len, len >> 8);
545 }
546
547
548
549
550
551 struct mbuf *
552 cnw_read(sc)
553 struct cnw_softc *sc;
554 {
555 struct mbuf *m, *top, **mp;
556 int totbytes, buffer, bufbytes, bufptr, mbytes, n;
557 u_int8_t *mptr;
558
559 WAIT_WOC(sc);
560 totbytes = read16(sc, CNW_EREG_RDP);
561 #ifdef CNW_DEBUG
562 if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
563 printf("%s: recv %d bytes\n", sc->sc_dev.dv_xname, totbytes);
564 #endif
565 buffer = CNW_EREG_RDP + 2;
566 bufbytes = 0;
567 bufptr = 0;
568
569 MGETHDR(m, M_DONTWAIT, MT_DATA);
570 if (m == 0)
571 return (0);
572 m->m_pkthdr.rcvif = &sc->sc_arpcom.ac_if;
573 m->m_pkthdr.len = totbytes;
574 mbytes = MHLEN;
575 top = 0;
576 mp = ⊤
577
578 while (totbytes > 0) {
579 if (top) {
580 MGET(m, M_DONTWAIT, MT_DATA);
581 if (m == 0) {
582 m_freem(top);
583 return (0);
584 }
585 mbytes = MLEN;
586 }
587 if (totbytes >= MINCLSIZE) {
588 MCLGET(m, M_DONTWAIT);
589 if ((m->m_flags & M_EXT) == 0) {
590 m_free(m);
591 m_freem(top);
592 return (0);
593 }
594 mbytes = MCLBYTES;
595 }
596 if (!top) {
597 int pad =
598 ALIGN(sizeof(struct ether_header)) -
599 sizeof(struct ether_header);
600 m->m_data += pad;
601 mbytes -= pad;
602 }
603 mptr = mtod(m, u_int8_t *);
604 mbytes = m->m_len = min(totbytes, mbytes);
605 totbytes -= mbytes;
606 while (mbytes > 0) {
607 if (bufbytes == 0) {
608 buffer = read16(sc, buffer);
609 bufbytes = read16(sc, buffer + 2);
610 bufptr = sc->sc_memoff + buffer +
611 read16(sc, buffer + 4);
612 #ifdef CNW_DEBUG
613 if (sc->sc_arpcom.ac_if.if_flags & IFF_DEBUG)
614 printf("%s: %d bytes @0x%x+0x%x\n",
615 sc->sc_dev.dv_xname, bufbytes,
616 buffer, bufptr - buffer -
617 sc->sc_memoff);
618 #endif
619 }
620 n = mbytes <= bufbytes ? mbytes : bufbytes;
621 bus_space_read_region_1(sc->sc_memt, sc->sc_memh,
622 bufptr, mptr, n);
623 bufbytes -= n;
624 bufptr += n;
625 mbytes -= n;
626 mptr += n;
627 }
628 *mp = m;
629 mp = &m->m_next;
630 }
631
632 return (top);
633 }
634
635
636
637
638
639 void
640 cnw_recv(sc)
641 struct cnw_softc *sc;
642 {
643 int rser;
644 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
645 struct mbuf *m;
646 struct ether_header *eh;
647
648 for (;;) {
649 WAIT_WOC(sc);
650 rser = bus_space_read_1(sc->sc_memt, sc->sc_memh,
651 sc->sc_memoff + CNW_EREG_RSER);
652 if (!(rser & CNW_RSER_RXAVAIL))
653 return;
654
655
656 m = cnw_read(sc);
657
658
659 CNW_CMD0(sc, CNW_CMD_SRP);
660
661
662 if (m == 0) {
663 ++ifp->if_ierrors;
664 return;
665 }
666 ++ifp->if_ipackets;
667
668 #if NBPFILTER > 0
669 if (ifp->if_bpf)
670 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
671 #endif
672
673
674
675
676
677
678 eh = mtod(m, struct ether_header *);
679 if ((eh->ether_dhost[0] & 1) == 0 &&
680 bcmp(sc->sc_arpcom.ac_enaddr, eh->ether_dhost,
681 sizeof(eh->ether_dhost)) != 0) {
682 m_freem(m);
683 continue;
684 }
685
686 ether_input_mbuf(ifp, m);
687 }
688 }
689
690
691
692
693
694 int
695 cnw_intr(arg)
696 void *arg;
697 {
698 struct cnw_softc *sc = arg;
699 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
700 int ret, status, rser, tser;
701
702 if (!(sc->sc_arpcom.ac_if.if_flags & IFF_RUNNING))
703 return (0);
704 ifp->if_timer = 0;
705
706 ret = 0;
707 for (;;) {
708 WAIT_WOC(sc);
709 if (!(bus_space_read_1(sc->sc_iot, sc->sc_ioh,
710 CNW_REG_CCSR) & 0x02)) {
711 if (ret == 0)
712 printf("%s: spurious interrupt\n",
713 sc->sc_dev.dv_xname);
714 return (ret);
715 }
716 ret = 1;
717 status = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CNW_REG_ASR);
718
719
720 if (status & CNW_ASR_RXRDY)
721 cnw_recv(sc);
722
723
724 if (status & CNW_ASR_RXERR) {
725
726
727
728
729
730
731 rser = bus_space_read_1(sc->sc_memt, sc->sc_memh,
732 sc->sc_memoff + CNW_EREG_RSER);
733
734 WAIT_WOC(sc);
735 bus_space_write_1(sc->sc_memt, sc->sc_memh,
736 sc->sc_memoff + CNW_EREG_RSERW,
737 CNW_RSER_RXERR |
738 (rser & (CNW_RSER_RXCRC | CNW_RSER_RXBIG)));
739
740 WAIT_WOC(sc);
741 bus_space_write_1(sc->sc_memt, sc->sc_memh,
742 sc->sc_memoff + CNW_EREG_ASCC, CNW_ASR_RXERR);
743 }
744
745
746 if (status & CNW_ASR_TXDN) {
747 tser = bus_space_read_1(sc->sc_memt, sc->sc_memh,
748 CNW_EREG_TSER);
749 if (tser & CNW_TSER_TXOK) {
750 WAIT_WOC(sc);
751 bus_space_write_1(sc->sc_memt, sc->sc_memh,
752 sc->sc_memoff + CNW_EREG_TSERW,
753 CNW_TSER_TXOK | CNW_TSER_RTRY);
754 }
755 if (tser & CNW_TSER_ERROR) {
756 ++ifp->if_oerrors;
757 WAIT_WOC(sc);
758 bus_space_write_1(sc->sc_memt, sc->sc_memh,
759 sc->sc_memoff + CNW_EREG_TSERW,
760 (tser & CNW_TSER_ERROR) |
761 CNW_TSER_RTRY);
762 }
763
764 cnw_start(&sc->sc_arpcom.ac_if);
765 }
766
767 }
768 }
769
770
771
772
773
774 int
775 cnw_ioctl(ifp, cmd, data)
776 register struct ifnet *ifp;
777 u_long cmd;
778 caddr_t data;
779 {
780 struct cnw_softc *sc = ifp->if_softc;
781 struct ifaddr *ifa = (struct ifaddr *)data;
782 int s, error = 0;
783
784 s = splnet();
785
786 switch (cmd) {
787
788 case SIOCSIFADDR:
789 if (!(ifp->if_flags & IFF_RUNNING) &&
790 (error = cnw_enable(sc)) != 0)
791 break;
792 ifp->if_flags |= IFF_UP;
793 switch (ifa->ifa_addr->sa_family) {
794 #ifdef INET
795 case AF_INET:
796 arp_ifinit(&sc->sc_arpcom, ifa);
797 break;
798 #endif
799 }
800 break;
801
802 case SIOCSIFFLAGS:
803 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_RUNNING) {
804
805
806
807
808 cnw_disable(sc);
809 } else if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP){
810
811
812
813
814 error = cnw_enable(sc);
815 }
816 break;
817
818 default:
819 error = EINVAL;
820 break;
821 }
822
823 splx(s);
824 return (error);
825 }
826
827
828
829
830
831
832 void
833 cnw_watchdog(ifp)
834 struct ifnet *ifp;
835 {
836 struct cnw_softc *sc = ifp->if_softc;
837
838 printf("%s: device timeout; card reset\n", sc->sc_dev.dv_xname);
839 ++ifp->if_oerrors;
840 cnw_init(sc);
841 }
842
843
844 int
845 cnw_detach(dev, flags)
846 struct device *dev;
847 int flags;
848 {
849 struct cnw_softc *sc = (struct cnw_softc *)dev;
850 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
851 int rv = 0;
852
853 pcmcia_io_unmap(sc->sc_pf, sc->sc_iowin);
854 pcmcia_io_free(sc->sc_pf, &sc->sc_pcioh);
855 pcmcia_mem_unmap(sc->sc_pf, sc->sc_memwin);
856 pcmcia_mem_free(sc->sc_pf, &sc->sc_pcmemh);
857
858 ether_ifdetach(ifp);
859 if_detach(ifp);
860
861 return (rv);
862 }
863
864 int
865 cnw_activate(dev, act)
866 struct device *dev;
867 enum devact act;
868 {
869 struct cnw_softc *sc = (struct cnw_softc *)dev;
870 struct ifnet *ifp = &sc->sc_arpcom.ac_if;
871 int s;
872
873 s = splnet();
874 switch (act) {
875 case DVACT_ACTIVATE:
876 pcmcia_function_enable(sc->sc_pf);
877 sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET,
878 cnw_intr, sc, sc->sc_dev.dv_xname);
879 cnw_init(sc);
880 break;
881
882 case DVACT_DEACTIVATE:
883 ifp->if_timer = 0;
884 ifp->if_flags &= ~IFF_RUNNING;
885 pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
886 pcmcia_function_disable(sc->sc_pf);
887 break;
888 }
889 splx(s);
890 return (0);
891 }