if_cs.c revision 1.1 1 /* $NetBSD: if_cs.c,v 1.1 2004/01/03 14:31:28 chris Exp $ */
2
3 /*
4 * Copyright 1997
5 * Digital Equipment Corporation. All rights reserved.
6 *
7 * This software is furnished under license and may be used and
8 * copied only in accordance with the following terms and conditions.
9 * Subject to these conditions, you may download, copy, install,
10 * use, modify and distribute this software in source and/or binary
11 * form. No title or ownership is transferred hereby.
12 *
13 * 1) Any source code used, modified or distributed must reproduce
14 * and retain this copyright notice and list of conditions as
15 * they appear in the source file.
16 *
17 * 2) No right is granted to use any trade name, trademark, or logo of
18 * Digital Equipment Corporation. Neither the "Digital Equipment
19 * Corporation" name nor any trademark or logo of Digital Equipment
20 * Corporation may be used to endorse or promote products derived
21 * from this software without the prior written permission of
22 * Digital Equipment Corporation.
23 *
24 * 3) This software is provided "AS-IS" and any express or implied
25 * warranties, including but not limited to, any implied warranties
26 * of merchantability, fitness for a particular purpose, or
27 * non-infringement are disclaimed. In no event shall DIGITAL be
28 * liable for any damages whatsoever, and in particular, DIGITAL
29 * shall not be liable for special, indirect, consequential, or
30 * incidental damages or damages for lost profits, loss of
31 * revenue or loss of use, whether such damages arise in contract,
32 * negligence, tort, under statute, in equity, at law or otherwise,
33 * even if advised of the possibility of such damage.
34 */
35
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: if_cs.c,v 1.1 2004/01/03 14:31:28 chris Exp $");
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/socket.h>
42 #include <sys/device.h>
43
44 #include "rnd.h"
45 #if NRND > 0
46 #include <sys/rnd.h>
47 #endif
48
49 #include <net/if.h>
50 #include <net/if_ether.h>
51 #include <net/if_media.h>
52
53 #include <machine/bus.h>
54 #include <machine/intr.h>
55
56 #include <sys/queue.h>
57 #include <uvm/uvm.h>
58 #include <machine/pmap.h>
59
60 #include <acorn32/eb7500atx/rsbus.h>
61
62 #include <dev/ic/cs89x0reg.h>
63 #include <dev/ic/cs89x0var.h>
64
65 /*
66 * the CS network interface is accessed at the following address locations:
67 * 030104f1 CS8920 PNP Low
68 * 03010600 03010640 CS8920 Default I/O registers
69 * 030114f1 CS8920 PNP High
70 * 03014000 03016000 CS8920 Default Memory
71 *
72 * IRQ is mapped as:
73 * CS8920 IRQ 3 INT5
74 *
75 * It must be configured as the following:
76 * The CS8920 PNP address should be configured for ISA base at 0x300
77 * to achieve the default register mapping as specified.
78 * Note memory addresses are all have bit 23 tied high in hardware.
79 * This only effects the value programmed into the CS8920 memory offset
80 * registers.
81 *
82 * Just to add to the fun the I/O registers are layed out as:
83 * xxxxR1R0
84 * xxxxR3R2
85 * xxxxR5R4
86 *
87 * This makes access to single registers hard (which does happen on a reset,
88 * as we've got to toggle the chip into 16bit mode)
89 *
90 * Network DRQ is connected to DRQ5
91 */
92
93 /*
94 * make a private tag so that we can use mainbus's map/unmap
95 */
96 static struct bus_space cs_rsbus_bs_tag;
97
98 int cs_pioc_probe __P((struct device *, struct cfdata *, void *));
99 void cs_pioc_attach __P((struct device *, struct device *, void *));
100
101 static u_int8_t cs_rbus_read_1(struct cs_softc *, bus_size_t);
102
103 CFATTACH_DECL(cs_rsbus, sizeof(struct cs_softc),
104 cs_pioc_probe, cs_pioc_attach, NULL, NULL);
105
106 /* Available media */
107 int cs_rbus_media [] = {
108 IFM_ETHER|IFM_10_T,
109 IFM_ETHER|IFM_10_T|IFM_FDX
110 };
111
112
113 int
114 cs_pioc_probe(parent, cf, aux)
115 struct device *parent;
116 struct cfdata *cf;
117 void *aux;
118 {
119 /* for now it'll always attach */
120 return 1;
121 }
122 #if 0
123 struct isa_attach_args *ia = aux;
124 bus_space_tag_t iot = ia->ia_iot;
125 bus_space_tag_t memt = ia->ia_memt;
126 bus_space_handle_t ioh, memh;
127 struct cs_softc sc;
128 int rv = 0, have_io = 0, have_mem = 0;
129 u_int16_t isa_cfg, isa_membase;
130 int maddr, irq;
131
132 if (ia->ia_nio < 1)
133 return (0);
134 if (ia->ia_nirq < 1)
135 return (0);
136
137 if (ISA_DIRECT_CONFIG(ia))
138 return (0);
139
140 /*
141 * Disallow wildcarded I/O base.
142 */
143 if (ia->ia_io[0].ir_addr == ISACF_PORT_DEFAULT)
144 return (0);
145
146 if (ia->ia_niomem > 0)
147 maddr = ia->ia_iomem[0].ir_addr;
148 else
149 maddr = ISACF_IOMEM_DEFAULT;
150
151 /*
152 * Map the I/O space.
153 */
154 if (bus_space_map(ia->ia_iot, ia->ia_io[0].ir_addr, CS8900_IOSIZE,
155 0, &ioh))
156 goto out;
157 have_io = 1;
158
159 memset(&sc, 0, sizeof sc);
160 sc.sc_iot = iot;
161 sc.sc_ioh = ioh;
162 /* Verify that it's a Crystal product. */
163 if (CS_READ_PACKET_PAGE_IO(&sc, PKTPG_EISA_NUM) !=
164 EISA_NUM_CRYSTAL)
165 goto out;
166
167 /*
168 * Verify that it's a supported chip.
169 */
170 switch (CS_READ_PACKET_PAGE_IO(&sc, PKTPG_PRODUCT_ID) &
171 PROD_ID_MASK) {
172 case PROD_ID_CS8900:
173 #ifdef notyet
174 case PROD_ID_CS8920:
175 case PROD_ID_CS8920M:
176 #endif
177 rv = 1;
178 }
179
180 /*
181 * If the IRQ or memory address were not specified, read the
182 * ISA_CFG EEPROM location.
183 */
184 if (maddr == ISACF_IOMEM_DEFAULT ||
185 ia->ia_irq[0].ir_irq == ISACF_IRQ_DEFAULT) {
186 if (cs_verify_eeprom(&sc) == CS_ERROR) {
187 printf("cs_isa_probe: EEPROM bad or missing\n");
188 goto out;
189 }
190 if (cs_read_eeprom(&sc, EEPROM_ISA_CFG, &isa_cfg)
191 == CS_ERROR) {
192 printf("cs_isa_probe: unable to read ISA_CFG\n");
193 goto out;
194 }
195 }
196
197 /*
198 * If the IRQ wasn't specified, get it from the EEPROM.
199 */
200 if (ia->ia_irq[0].ir_irq == ISACF_IRQ_DEFAULT) {
201 irq = isa_cfg & ISA_CFG_IRQ_MASK;
202 if (irq == 3)
203 irq = 5;
204 else
205 irq += 10;
206 } else
207 irq = ia->ia_irq[0].ir_irq;
208
209 /*
210 * If the memory address wasn't specified, get it from the EEPROM.
211 */
212 if (maddr == ISACF_IOMEM_DEFAULT) {
213 if ((isa_cfg & ISA_CFG_MEM_MODE) == 0) {
214 /* EEPROM says don't use memory mode. */
215 goto out;
216 }
217 if (cs_read_eeprom(&sc, EEPROM_MEM_BASE, &isa_membase)
218 == CS_ERROR) {
219 printf("cs_isa_probe: unable to read MEM_BASE\n");
220 goto out;
221 }
222
223 isa_membase &= MEM_BASE_MASK;
224 maddr = (int)isa_membase << 8;
225 }
226
227 /*
228 * We now have a valid mem address; attempt to map it.
229 */
230 if (bus_space_map(ia->ia_memt, maddr, CS8900_MEMSIZE, 0, &memh)) {
231 /* Can't map it; fall back on i/o-only mode. */
232 printf("cs_isa_probe: unable to map memory space\n");
233 maddr = ISACF_IOMEM_DEFAULT;
234 } else
235 have_mem = 1;
236
237 out:
238 if (have_io)
239 bus_space_unmap(iot, ioh, CS8900_IOSIZE);
240 if (have_mem)
241 bus_space_unmap(memt, memh, CS8900_MEMSIZE);
242
243 if (rv) {
244 ia->ia_nio = 1;
245 ia->ia_io[0].ir_size = CS8900_IOSIZE;
246
247 if (maddr == ISACF_IOMEM_DEFAULT)
248 ia->ia_niomem = 0;
249 else {
250 ia->ia_niomem = 1;
251 ia->ia_iomem[0].ir_addr = maddr;
252 ia->ia_iomem[0].ir_size = CS8900_MEMSIZE;
253 }
254
255 ia->ia_nirq = 1;
256 ia->ia_irq[0].ir_irq = irq;
257 }
258 return (rv);
259 }
260 #endif
261 void
262 cs_pioc_attach(parent, self, aux)
263 struct device *parent, *self;
264 void *aux;
265 {
266 struct cs_softc *sc = (struct cs_softc *)self;
267 struct rsbus_attach_args *rs = (void *)aux;
268 u_int iobase;
269
270 /* member copy */
271 cs_rsbus_bs_tag = *rs->sa_iot;
272
273 /* registers are 4 byte aligned */
274 cs_rsbus_bs_tag.bs_cookie = (void *) 1;
275
276 sc->sc_iot = sc->sc_memt = &cs_rsbus_bs_tag;
277
278 /*
279 * Do DMA later
280 if (ia->ia_ndrq > 0)
281 isc->sc_drq = ia->ia_drq[0].ir_drq;
282 else
283 isc->sc_drq = -1;
284 */
285
286 /* device always interrupts on 3 but that routes to IRQ 5 */
287 sc->sc_irq = 3;
288
289 printf("\n");
290
291 /*
292 * Map the device.
293 */
294 iobase = 0x03010600;
295 printf("mapping iobase=0x%08x, for 0x%08x\n", iobase, CS8900_IOSIZE * 4);
296 if (bus_space_map(sc->sc_iot, iobase, CS8900_IOSIZE * 4,
297 0, &sc->sc_ioh)) {
298 printf("%s: unable to map i/o space\n", sc->sc_dev.dv_xname);
299 return;
300 }
301
302 #if 0
303 bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, PORT_PKTPG_PTR, PKTPG_EISA_NUM);
304
305 productID = bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, PORT_PKTPG_DATA);
306
307 printf("Result ID = 0x%08x\n", productID);
308 printf("cookie = %p\n", sc->sc_iot->bs_cookie);
309 {
310 volatile uint32_t *ptr = (void*) ((char *)((sc)->sc_ioh) + (PORT_PKTPG_PTR << 1));
311 volatile uint32_t *data =(void *)((char *)((sc)->sc_ioh) + (PORT_PKTPG_DATA << 1));
312 volatile char *pnplow = (char *)trunc_page((sc)->sc_ioh) + 0x4f1;
313 bus_space_handle_t tag2;
314 pt_entry_t *pte;
315
316 printf("ioh = %p, ptr = %p, data = %p\n", (void*)(sc)->sc_ioh, ptr, data);
317 *ptr = PKTPG_EISA_NUM;
318 productID = *data;
319 printf("Result ID2 = 0x%08x\n", productID);
320
321 pte = vtopte(trunc_page((sc)->sc_ioh));
322 printf("pte = %p, *pte = 0x%08x\n", pte, *pte);
323 printf("pnplow = %p, *pnplow = 0x%02x\n", pnplow, *pnplow);
324
325 if (bus_space_map(sc->sc_iot, 0x03011000, 0x1000,
326 0, &tag2)) {
327 printf("%s: unable to map i/o space\n", sc->sc_dev.dv_xname);
328 return;
329 }
330 pnplow = (char *)trunc_page(tag2) + 0x4f1;
331 printf("pnplow = %p, *pnplow = 0x%02x\n", pnplow, *pnplow);
332
333 *pnplow = 0x3;
334
335 *ptr = PKTPG_EISA_NUM;
336 productID = *data;
337 printf("Result ID2 = 0x%08x\n", productID);
338 }
339 #endif
340
341 #if 0
342 /*
343 * Map the memory space if it was specified. If we can do this,
344 * we set ourselves up to use memory mode forever. Otherwise,
345 * we fall back on I/O mode.
346 */
347 if (ia->ia_iomem[0].ir_addr != ISACF_IOMEM_DEFAULT &&
348 ia->ia_iomem[0].ir_size == CS8900_MEMSIZE &&
349 CS8900_MEMBASE_ISVALID(ia->ia_iomem[0].ir_addr)) {
350 #endif
351 #if 0
352 printf("mapping iobase=0x%08x, for 0x%08x\n", iobase + 0x3A00,
353 CS8900_MEMSIZE * 4);
354 if (bus_space_map(sc->sc_memt, iobase + 0x3A00,
355 CS8900_MEMSIZE * 4, 0, &sc->sc_memh)) {
356 printf("%s: unable to map memory space\n",
357 sc->sc_dev.dv_xname);
358 } else {
359 sc->sc_cfgflags |= CFGFLG_MEM_MODE;
360 sc->sc_pktpgaddr = iobase + 0x3A00;
361 }
362 #endif
363
364 printf("Claiming IRQ\n");
365 sc->sc_ih = intr_claim(0x0B, IPL_NET, "cs", cs_intr, sc);
366 if (sc->sc_ih == NULL) {
367 printf("%s: unable to establish interrupt\n",
368 sc->sc_dev.dv_xname);
369 return;
370 }
371
372 /* DMA is for later */
373 sc->sc_dma_chipinit = NULL;
374 sc->sc_dma_attach = NULL;
375 sc->sc_dma_process_rx = NULL;
376
377 printf("Cs attach addr: 0x%04x\n", CS_READ_PACKET_PAGE(sc, PKTPG_IND_ADDR));
378
379 /* don't talk to the EEPROM, it seems that the cs driver doesn't use a
380 * normal layout */
381 sc->sc_cfgflags |= CFGFLG_NOT_EEPROM;
382 sc->sc_io_read_1 = cs_rbus_read_1;
383 cs_attach(sc, NULL, cs_rbus_media, sizeof(cs_rbus_media) / sizeof(cs_rbus_media[0]),
384 IFM_ETHER|IFM_10_T|IFM_FDX);
385 }
386
387 static u_int8_t
388 cs_rbus_read_1(struct cs_softc *sc, bus_size_t a)
389 {
390 bus_size_t offset;
391 /* this is rather warped if it's an even address then just use the
392 * bus_space_read_1
393 */
394 if ((a & 1) == 0)
395 {
396 return bus_space_read_1(sc->sc_iot, sc->sc_ioh, a);
397 }
398 /* otherwise we've get to work out the aligned address and then add
399 * one */
400 /* first work out the offset */
401 offset = (a & ~1) << 1;
402 /* add the one */
403 offset++;
404
405 /* and read it, with no shift */
406 return sc->sc_iot->bs_r_1(0, (sc)->sc_ioh, offset);
407 }
408