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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
|
/*
* Product specific probe and attach routines for:
* 3COM 3C579 and 3C509(in eisa config mode) ethernet controllers
*
* Copyright (c) 1996 Justin T. Gibbs
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice immediately at the beginning of the file, without modification,
* this list of conditions, and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Absolutely no warranty of function or purpose is made by the author
* Justin T. Gibbs.
* 4. Modifications may be freely made to this file if the above conditions
* are met.
*
* $Id: 3c5x9.c,v 1.1 1996/02/26 01:01:37 gibbs Exp $
*/
#include "eisa.h"
#if NEISA > 0
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/devconf.h>
#include <sys/kernel.h>
#include <machine/clock.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <i386/isa/if_epreg.h>
#include <i386/isa/isa_device.h> /* For kdc_isa0 */
#include <i386/eisa/eisaconf.h>
#define EISA_DEVICE_ID_3COM_3C509_TP 0x506d5090
#define EISA_DEVICE_ID_3COM_3C509_BNC 0x506d5091
#define EISA_DEVICE_ID_3COM_3C579_TP 0x506d5092
#define EISA_DEVICE_ID_3COM_3C579_BNC 0x506d5093
#define EISA_DEVICE_ID_3COM_3C509_COMBO 0x506d5094
#define EISA_DEVICE_ID_3COM_3C509_TPO 0x506d5095
#define EP_EISA_SLOT_OFFSET 0x0c80
#define EP_EISA_IOSIZE 0x000a
#define EISA_IOCONF 0x0008
#define IRQ_CHANNEL 0xf000
#define INT_3 0x3000
#define INT_5 0x5000
#define INT_7 0x7000
#define INT_9 0x9000
#define INT_10 0xa000
#define INT_11 0xb000
#define INT_12 0xc000
#define INT_15 0xf000
#define EISA_BPROM_MEDIA_CONF 0x0006
#define TRANS_TYPE 0xc000
#define TRANS_TP 0x0000
#define TRANS_AUI 0x4000
#define TRANS_BNC 0xc000
static int ep_eisa_probe __P((void));
static int ep_eisa_attach __P((struct eisa_device *e_dev));
struct eisa_driver ep_eisa_driver = {
"ep",
ep_eisa_probe,
ep_eisa_attach,
/*shutdown*/NULL,
&ep_unit
};
DATA_SET (eisadriver_set, ep_eisa_driver);
static struct kern_devconf kdc_eisa_ep = {
0, 0, 0, /* filled in by dev_attach */
"ep", 0, { MDDT_EISA, 0, "net" },
eisa_generic_externalize, 0, 0, EISA_EXTERNALLEN,
&kdc_eisa0, /* parent */
0, /* parentdata */
DC_UNCONFIGURED, /* always start out here */
NULL,
DC_CLS_MISC /* host adapters aren't special */
};
static char *ep_match __P((eisa_id_t type));
static char*
ep_match(type)
eisa_id_t type;
{
switch(type) {
case EISA_DEVICE_ID_3COM_3C509_TP:
return "3Com 3C509-TP Network Adapter";
break;
case EISA_DEVICE_ID_3COM_3C509_BNC:
return "3Com 3C509-BNC Network Adapter";
break;
case EISA_DEVICE_ID_3COM_3C579_TP:
return "3Com 3C579-TP EISA Network Adapter";
break;
case EISA_DEVICE_ID_3COM_3C579_BNC:
return "3Com 3C579-BNC EISA Network Adapter";
break;
case EISA_DEVICE_ID_3COM_3C509_COMBO:
return "3Com 3C509-Combo Network Adapter";
break;
case EISA_DEVICE_ID_3COM_3C509_TPO:
return "3Com 3C509-TPO Network Adapter";
break;
default:
break;
}
return (NULL);
}
static int
ep_eisa_probe(void)
{
u_long iobase;
struct eisa_device *e_dev = NULL;
int stat = 0;
int count;
count = 0;
while ((e_dev = eisa_match_dev(e_dev, ep_match))) {
u_short conf;
u_long port;
int irq;
port = (e_dev->ioconf.slot * EISA_SLOT_SIZE);
iobase = port + EP_EISA_SLOT_OFFSET;
/* We must be in EISA configuration mode */
if ((inw(iobase + EP_W0_ADDRESS_CFG) & 0x1f) != 0x1f)
continue;
eisa_add_iospace(e_dev, iobase, EP_EISA_IOSIZE, RESVADDR_NONE);
eisa_add_iospace(e_dev, port, EP_IOSIZE, RESVADDR_NONE);
conf = inw(iobase + EISA_IOCONF);
/* Determine our IRQ */
switch (conf & IRQ_CHANNEL) {
case INT_3:
irq = 3;
break;
case INT_5:
irq = 5;
break;
case INT_7:
irq = 7;
break;
case INT_9:
irq = 9;
break;
case INT_10:
irq = 10;
break;
case INT_11:
irq = 11;
break;
case INT_12:
irq = 12;
break;
case INT_15:
irq = 15;
break;
default:
/* Disabled */
printf("ep: 3COM Network Adapter at "
"slot %d has its IRQ disabled. "
"Probe failed.\n",
e_dev->ioconf.slot);
continue;
}
eisa_add_intr(e_dev, irq);
eisa_registerdev(e_dev, &ep_eisa_driver, &kdc_eisa_ep);
if(e_dev->id != EISA_DEVICE_ID_3COM_3C579_TP &&
e_dev->id != EISA_DEVICE_ID_3COM_3C579_BNC) {
/* Our real parent is the isa bus. Say so. */
e_dev->kdc->kdc_parent = &kdc_isa0;
}
count++;
}
return count;
}
static int
ep_eisa_attach(e_dev)
struct eisa_device *e_dev;
{
struct ep_softc *sc;
struct ep_board *epb;
int unit = e_dev->unit;
int irq = ffs(e_dev->ioconf.irq) - 1;
resvaddr_t *ioport;
resvaddr_t *eisa_ioport;
u_char level_intr;
u_short conf;
int i;
/*
* The addresses are sorted in increasing order
* so we know the port to pass to the core ep
* driver comes first.
*/
ioport = e_dev->ioconf.ioaddrs.lh_first;
if(!ioport)
return -1;
eisa_ioport = ioport->links.le_next;
if(!eisa_ioport)
return -1;
eisa_reg_start(e_dev);
if(eisa_reg_iospace(e_dev, ioport))
return -1;
if(eisa_reg_iospace(e_dev, eisa_ioport))
return -1;
epb = &ep_board[ep_boards];
epb->epb_addr = ioport->addr;
epb->epb_used = 1;
if(!(sc = ep_alloc(unit, epb)))
return -1;
ep_boards++;
sc->stat = 0;
sc->kdc = e_dev->kdc;
level_intr = FALSE;
switch(e_dev->id) {
case EISA_DEVICE_ID_3COM_3C509_TP:
sc->ep_connectors = UTP|AUI;
break;
case EISA_DEVICE_ID_3COM_3C509_BNC:
sc->ep_connectors = BNC|AUI;
break;
case EISA_DEVICE_ID_3COM_3C579_TP:
sc->ep_connectors = UTP|AUI;
sc->stat = F_ACCESS_32_BITS;
level_intr = TRUE;
break;
case EISA_DEVICE_ID_3COM_3C579_BNC:
sc->ep_connectors = BNC|AUI;
sc->stat = F_ACCESS_32_BITS;
level_intr = TRUE;
break;
case EISA_DEVICE_ID_3COM_3C509_COMBO:
sc->ep_connectors = UTP|BNC|AUI;
break;
case EISA_DEVICE_ID_3COM_3C509_TPO:
sc->ep_connectors = UTP;
break;
default:
break;
}
/*
* Set the eisa config selected media type
*/
sc->ep_connector = inw(eisa_ioport->addr + EISA_BPROM_MEDIA_CONF)
>> ACF_CONNECTOR_BITS;
if(eisa_reg_intr(e_dev, irq, ep_intr, (void *)sc, &net_imask,
/*shared ==*/level_intr)) {
ep_free(sc);
return -1;
}
eisa_reg_end(e_dev);
/* Reset and Enable the card */
outb(eisa_ioport->addr + EP_W0_CONFIG_CTRL, W0_P4_CMD_RESET_ADAPTER);
DELAY(1000); /* we must wait at least 1 ms */
outb(eisa_ioport->addr + EP_W0_CONFIG_CTRL, W0_P4_CMD_ENABLE_ADAPTER);
/* Now the registers are availible through the lower ioport */
/*
* Retrieve our ethernet address
*/
GO_WINDOW(0);
for(i = 0; i < 3; i++)
sc->epb->eth_addr[i] = get_e(sc, i);
ep_attach(sc);
if(eisa_enable_intr(e_dev, irq)) {
ep_free(sc);
eisa_release_intr(e_dev, irq, ep_intr);
return -1;
}
return 0;
}
#endif /* NEISA > 0 */
|