if_ep_pcmcia.c revision 1.1.2.6 1 #include "bpfilter.h"
2
3 #include <sys/param.h>
4 #include <sys/systm.h>
5 #include <sys/mbuf.h>
6 #include <sys/socket.h>
7 #include <sys/ioctl.h>
8 #include <sys/errno.h>
9 #include <sys/syslog.h>
10 #include <sys/select.h>
11 #include <sys/device.h>
12
13 #include <net/if.h>
14 #include <net/if_dl.h>
15 #include <net/if_ether.h>
16 #include <net/if_media.h>
17
18 #ifdef INET
19 #include <netinet/in.h>
20 #include <netinet/in_systm.h>
21 #include <netinet/in_var.h>
22 #include <netinet/ip.h>
23 #include <netinet/if_inarp.h>
24 #endif
25
26 #ifdef NS
27 #include <netns/ns.h>
28 #include <netns/ns_if.h>
29 #endif
30
31 #if NBPFILTER > 0
32 #include <net/bpf.h>
33 #include <net/bpfdesc.h>
34 #endif
35
36 #include <machine/cpu.h>
37 #include <machine/bus.h>
38 #include <machine/intr.h>
39
40 #include <dev/ic/elink3var.h>
41 #include <dev/ic/elink3reg.h>
42
43 #include <dev/pcmcia/pcmciareg.h>
44 #include <dev/pcmcia/pcmciavar.h>
45
46 #define PCMCIA_MANUFACTURER_3COM 0x101
47 #define PCMCIA_PRODUCT_3COM_3C562 0x562
48 #define PCMCIA_PRODUCT_3COM_3C589 0x589
49
50 #ifdef __BROKEN_INDIRECT_CONFIG
51 int ep_pcmcia_match __P((struct device *, void *, void *));
52 #else
53 int ep_pcmcia_match __P((struct device *, struct cfdata *, void *));
54 #endif
55 void ep_pcmcia_attach __P((struct device *, struct device *, void *));
56
57 int ep_pcmcia_get_enaddr __P((struct pcmcia_tuple *, void *));
58 int ep_pcmcia_enable __P((void *arg));
59 void ep_pcmcia_disable __P((void *arg));
60
61 struct ep_pcmcia_softc {
62 struct ep_softc sc_ep; /* real "ep" softc */
63
64 /* PCMCIA-specific goo */
65 struct pcmcia_io_handle sc_pcioh; /* PCMCIA i/o space info */
66 int sc_io_window; /* our i/o window */
67 struct pcmcia_function *sc_pf; /* our PCMCIA function */
68 };
69
70 struct cfattach ep_pcmcia_ca = {
71 sizeof(struct ep_pcmcia_softc), ep_pcmcia_match, ep_pcmcia_attach
72 };
73
74 int
75 ep_pcmcia_match(parent, match, aux)
76 struct device *parent;
77 #ifdef __BROKEN_INDIRECT_CONFIG
78 void *match;
79 #else
80 struct cfdata *cf;
81 #endif
82 void *aux;
83 {
84 struct pcmcia_attach_args *pa = (struct pcmcia_attach_args *) aux;
85
86 if ((pa->manufacturer == PCMCIA_MANUFACTURER_3COM) &&
87 (pa->product == PCMCIA_PRODUCT_3COM_3C562) &&
88 (pa->pf->number == 0))
89 return(1);
90
91 if ((pa->manufacturer == PCMCIA_MANUFACTURER_3COM) &&
92 (pa->product == PCMCIA_PRODUCT_3COM_3C589) &&
93 (pa->pf->number == 0))
94 return(1);
95
96 return(0);
97 }
98
99 int ep_pcmcia_enable(void *arg)
100 {
101 return(pcmcia_function_enable(arg));
102 }
103
104 void ep_pcmcia_disable(void *arg)
105 {
106 pcmcia_function_disable(arg);
107 }
108
109 void
110 ep_pcmcia_attach(parent, self, aux)
111 struct device *parent, *self;
112 void *aux;
113 {
114 struct ep_pcmcia_softc *psc = (void *) self;
115 struct ep_softc *sc = &psc->sc_ep;
116 struct pcmcia_attach_args *pa = aux;
117 struct pcmcia_config_entry *cfe;
118 int i;
119 u_int8_t myla[ETHER_ADDR_LEN];
120 u_int8_t *enaddr;
121 char *model;
122
123 psc->sc_pf = pa->pf;
124 cfe = pa->pf->cfe_head.sqh_first;
125
126 /* Enable the card. */
127 pcmcia_function_init(pa->pf, cfe);
128 if (pcmcia_function_enable(pa->pf))
129 printf(": function enable failed\n");
130
131 sc->enabled = 1;
132
133 /* turn off the bit which disables the modem */
134 if (pa->product == PCMCIA_PRODUCT_3COM_3C562) {
135 int reg;
136
137 reg = pcmcia_ccr_read(pa->pf, PCMCIA_CCR_OPTION);
138 reg &= ~0x08;
139 pcmcia_ccr_write(pa->pf, PCMCIA_CCR_OPTION, reg);
140 }
141
142 if (cfe->num_memspace != 0)
143 printf(": unexpected number of memory spaces %d should be 0\n",
144 cfe->num_memspace);
145
146 if (cfe->num_iospace != 1)
147 printf(": unexpected number of I/O spaces %d should be 1\n",
148 cfe->num_iospace);
149
150 /* XXX there's a comment in the linux driver about the io address
151 having to be between 0x00 and 0x70 mod 0x100. weird. */
152
153 if (pa->product == PCMCIA_PRODUCT_3COM_3C562) {
154 for (i = 0x300; i < 0x1000; i += ((i%0x100) == 0x70)?0x90:0x10) {
155 if (pcmcia_io_alloc(pa->pf, i, cfe->iospace[0].length,
156 &psc->sc_pcioh) == 0)
157 break;
158 }
159 if (i == 0x1000) {
160 printf(": can't allocate i/o space\n");
161 return;
162 }
163 } else {
164 if (pcmcia_io_alloc(pa->pf, 0, cfe->iospace[0].length,
165 &psc->sc_pcioh))
166 printf(": can't allocate i/o space\n");
167 }
168
169 sc->sc_iot = psc->sc_pcioh.iot;
170 sc->sc_ioh = psc->sc_pcioh.ioh;
171
172 if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
173 PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8),
174 0, cfe->iospace[0].length, &psc->sc_pcioh,
175 &psc->sc_io_window)) {
176 printf(": can't map i/o space\n");
177 return;
178 }
179
180 if (pa->product == PCMCIA_PRODUCT_3COM_3C562) {
181 if (pcmcia_scan_cis(parent, ep_pcmcia_get_enaddr, myla)) {
182 printf(": can't read ethernet address from CIS\n");
183 return;
184 }
185 enaddr = myla;
186 } else {
187 enaddr = NULL;
188 }
189
190 sc->bustype = EP_BUS_PCMCIA;
191
192 switch (pa->product) {
193 case PCMCIA_PRODUCT_3COM_3C589:
194 model = "3Com 3C589 Ethernet";
195 break;
196 case PCMCIA_PRODUCT_3COM_3C562:
197 model = "3Com 3C562 Ethernet";
198 break;
199 default:
200 model = "3Com Ethernet, model unknown";
201 break;
202 }
203
204 printf(": %s\n", model);
205
206 sc->enable = ep_pcmcia_enable;
207 sc->disable = ep_pcmcia_disable;
208 sc->able_arg = pa->pf;
209
210 epconfig(sc, EP_CHIPSET_3C509, enaddr);
211
212 /* establish the interrupt. */
213 sc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_NET, epintr, sc);
214 if (sc->sc_ih == NULL) {
215 printf("%s: couldn't establish interrupt\n",
216 sc->sc_dev.dv_xname);
217 return;
218 }
219
220 sc->enabled = 0;
221
222 pcmcia_function_disable(pa->pf);
223 }
224
225 int
226 ep_pcmcia_get_enaddr(tuple, arg)
227 struct pcmcia_tuple *tuple;
228 void *arg;
229 {
230 u_int8_t *myla = (u_int8_t *) arg;
231 int i;
232
233 /* this is 3c562 magic */
234
235 if (tuple->code == 0x88) {
236 if (tuple->length < ETHER_ADDR_LEN)
237 return(0);
238
239 for (i=0; i<ETHER_ADDR_LEN; i+=2) {
240 myla[i] = pcmcia_tuple_read_1(tuple, i+1);
241 myla[i+1] = pcmcia_tuple_read_1(tuple, i);
242 }
243
244 return(1);
245 }
246
247 return(0);
248 }
249