Deleted Added
full compact
dp83932subr.c (114561) dp83932subr.c (119419)
1/* $FreeBSD: head/sys/dev/snc/dp83932subr.c 114561 2003-05-03 01:47:38Z nyan $ */
2/* $NecBSD: dp83932subr.c,v 1.5.6.2 1999/10/09 05:47:23 kmatsuda Exp $ */
3/* $NetBSD$ */
4
5/*
6 * Copyright (c) 1997, 1998, 1999
7 * Kouichi Matsuda. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Kouichi Matsuda for
20 * NetBSD/pc98.
21 * 4. The name of the author may not be used to endorse or promote products
22 * derived from this software without specific prior written permission
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
1/* $NecBSD: dp83932subr.c,v 1.5.6.2 1999/10/09 05:47:23 kmatsuda Exp $ */
2/* $NetBSD$ */
3
4/*
5 * Copyright (c) 1997, 1998, 1999
6 * Kouichi Matsuda. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Kouichi Matsuda for
19 * NetBSD/pc98.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#include <sys/cdefs.h>
36__FBSDID("$FreeBSD: head/sys/dev/snc/dp83932subr.c 119419 2003-08-24 18:03:45Z obrien $");
35/*
36 * Routines of NEC PC-9801-83, 84, 103, 104, PC-9801N-25 and PC-9801N-J02, J02R
37 * Ethernet interface for NetBSD/pc98, ported by Kouichi Matsuda.
38 *
39 * These cards use National Semiconductor DP83934AVQB as Ethernet Controller
40 * and National Semiconductor NS46C46 as (64 * 16 bits) Microwire Serial EEPROM.
41 */
42
43/*
44 * Modified for FreeBSD(98) 4.0 from NetBSD/pc98 1.4.2 by Motomichi Matsuzaki.
45 */
46
47#include <sys/param.h>
48#include <sys/systm.h>
49#include <sys/protosw.h>
50#include <sys/socket.h>
51
52#include <net/ethernet.h>
53#include <net/if.h>
54#include <net/if_arp.h>
55#include <net/if_media.h>
56
57#ifdef INET
58#include <netinet/in.h>
59#include <netinet/in_systm.h>
60#include <netinet/in_var.h>
61#include <netinet/ip.h>
62#include <netinet/if_inarp.h>
63#endif
64
65
66#include <sys/bus.h>
67#include <machine/bus.h>
68
69#include <dev/snc/dp83932reg.h>
70#include <dev/snc/dp83932var.h>
71#include <dev/snc/if_sncreg.h>
72#include <dev/snc/dp83932subr.h>
73
74integrate u_int16_t snc_nec16_select_bank
75 (struct snc_softc *, u_int32_t, u_int32_t);
76
77/*
78 * Interface exists: make available by filling in network interface
79 * record. System will initialize the interface when it is ready
80 * to accept packets.
81 */
82int
83sncsetup(sc, lladdr)
84 struct snc_softc *sc;
85 u_int8_t *lladdr;
86{
87 u_int32_t p, pp;
88 int i;
89 int offset;
90
91 /*
92 * Put the pup in reset mode (sncinit() will fix it later),
93 * stop the timer, disable all interrupts and clear any interrupts.
94 */
95 NIC_PUT(sc, SNCR_CR, CR_STP);
96 wbflush();
97 NIC_PUT(sc, SNCR_CR, CR_RST);
98 wbflush();
99 NIC_PUT(sc, SNCR_IMR, 0);
100 wbflush();
101 NIC_PUT(sc, SNCR_ISR, ISR_ALL);
102 wbflush();
103
104 /*
105 * because the SONIC is basically 16bit device it 'concatenates'
106 * a higher buffer address to a 16 bit offset--this will cause wrap
107 * around problems near the end of 64k !!
108 */
109 p = pp = 0;
110
111 for (i = 0; i < NRRA; i++) {
112 sc->v_rra[i] = SONIC_GETDMA(p);
113 p += RXRSRC_SIZE(sc);
114 }
115 sc->v_rea = SONIC_GETDMA(p);
116
117 p = SOALIGN(sc, p);
118
119 sc->v_cda = SONIC_GETDMA(p);
120 p += CDA_SIZE(sc);
121
122 p = SOALIGN(sc, p);
123
124 for (i = 0; i < NTDA; i++) {
125 struct mtd *mtdp = &sc->mtda[i];
126 mtdp->mtd_vtxp = SONIC_GETDMA(p);
127 p += TXP_SIZE(sc);
128 }
129
130 p = SOALIGN(sc, p);
131
132 if ((p - pp) > NBPG) {
133 device_printf (sc->sc_dev, "sizeof RRA (%ld) + CDA (%ld) +"
134 "TDA (%ld) > NBPG (%d). Punt!\n",
135 (ulong)sc->v_cda - (ulong)sc->v_rra[0],
136 (ulong)sc->mtda[0].mtd_vtxp - (ulong)sc->v_cda,
137 (ulong)p - (ulong)sc->mtda[0].mtd_vtxp,
138 NBPG);
139 return(1);
140 }
141
142 p = pp + NBPG;
143 pp = p;
144
145 sc->sc_nrda = NBPG / RXPKT_SIZE(sc);
146 sc->v_rda = SONIC_GETDMA(p);
147
148 p = pp + NBPG;
149
150 for (i = 0; i < NRBA; i++) {
151 sc->rbuf[i] = p;
152 p += NBPG;
153 }
154
155 pp = p;
156 offset = TXBSIZE;
157 for (i = 0; i < NTDA; i++) {
158 struct mtd *mtdp = &sc->mtda[i];
159
160 mtdp->mtd_vbuf = SONIC_GETDMA(p);
161 offset += TXBSIZE;
162 if (offset < NBPG) {
163 p += TXBSIZE;
164 } else {
165 p = pp + NBPG;
166 pp = p;
167 offset = TXBSIZE;
168 }
169 }
170
171 return (0);
172}
173
174/*
175 * miscellaneous NEC/SONIC detect functions.
176 */
177
178/*
179 * check if a specified irq is acceptable.
180 */
181u_int8_t
182snc_nec16_validate_irq(irq)
183 int irq;
184{
185 const u_int8_t encoded_irq[16] = {
186 -1, -1, -1, 0, -1, 1, 2, -1, -1, 3, 4, -1, 5, 6, -1, -1
187 };
188
189 return encoded_irq[irq];
190}
191
192/*
193 * specify irq to board.
194 */
195int
196snc_nec16_register_irq(sc, irq)
197 struct snc_softc *sc;
198 int irq;
199{
200 bus_space_tag_t iot = sc->sc_iot;
201 bus_space_handle_t ioh = sc->sc_ioh;
202 u_int8_t encoded_irq;
203
204 encoded_irq = snc_nec16_validate_irq(irq);
205 if (encoded_irq == (u_int8_t) -1) {
206 printf("snc_nec16_register_irq: unsupported irq (%d)\n", irq);
207 return 0;
208 }
209
210 /* select SNECR_IRQSEL register */
211 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_IRQSEL);
212 /* write encoded irq value */
213 bus_space_write_1(iot, ioh, SNEC_CTRLB, encoded_irq);
214
215 return 1;
216}
217
218/*
219 * check if a specified memory base address is acceptable.
220 */
221int
222snc_nec16_validate_mem(maddr)
223 int maddr;
224{
225
226 /* Check on Normal mode with max range, only */
227 if ((maddr & ~0x1E000) != 0xC0000) {
228 printf("snc_nec16_validate_mem: "
229 "unsupported window base (0x%x)\n", maddr);
230 return 0;
231 }
232
233 return 1;
234}
235
236/*
237 * specify memory base address to board and map to first bank.
238 */
239int
240snc_nec16_register_mem(sc, maddr)
241 struct snc_softc *sc;
242 int maddr;
243{
244 bus_space_tag_t iot = sc->sc_iot;
245 bus_space_handle_t ioh = sc->sc_ioh;
246
247 if (snc_nec16_validate_mem(maddr) == 0)
248 return 0;
249
250 /* select SNECR_MEMSEL register */
251 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMSEL);
252 /* write encoded memory base select value */
253 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_MEMSEL_PHYS2EN(maddr));
254
255 /*
256 * set current bank to 0 (bottom) and map
257 */
258 /* select SNECR_MEMBS register */
259 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
260 /* select new bank */
261 bus_space_write_1(iot, ioh, SNEC_CTRLB,
262 SNECR_MEMBS_B2EB(0) | SNECR_MEMBS_BSEN);
263 /* set current bank to 0 */
264 sc->curbank = 0;
265
266 return 1;
267}
268
269int
270snc_nec16_check_memory(iot, ioh, memt, memh)
271 bus_space_tag_t iot;
272 bus_space_handle_t ioh;
273 bus_space_tag_t memt;
274 bus_space_handle_t memh;
275{
276 u_int16_t val;
277 int i, j;
278
279 val = 0;
280 for (i = 0; i < SNEC_NBANK; i++) {
281 /* select new bank */
282 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
283 bus_space_write_1(iot, ioh, SNEC_CTRLB,
284 SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN);
285
286 /* write test pattern */
287 for (j = 0; j < SNEC_NMEMS / 2; j++) {
288 bus_space_write_2(memt, memh, j * 2, val + j);
289 }
290 val += 0x1000;
291 }
292
293 val = 0;
294 for (i = 0; i < SNEC_NBANK; i++) {
295 /* select new bank */
296 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
297 bus_space_write_1(iot, ioh, SNEC_CTRLB,
298 SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN);
299
300 /* read test pattern */
301 for (j = 0; j < SNEC_NMEMS / 2; j++) {
302 if (bus_space_read_2(memt, memh, j * 2) != val + j)
303 break;
304 }
305
306 if (j < SNEC_NMEMS / 2) {
307 printf("snc_nec16_check_memory: "
308 "memory check failed at 0x%04x%04x"
309 "val 0x%04x != expected 0x%04x\n", i, j,
310 bus_space_read_2(memt, memh, j * 2),
311 val + j);
312 return 0;
313 }
314 val += 0x1000;
315 }
316
317 /* zero clear mem */
318 for (i = 0; i < SNEC_NBANK; i++) {
319 /* select new bank */
320 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
321 bus_space_write_1(iot, ioh, SNEC_CTRLB,
322 SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN);
323
324 bus_space_set_region_4(memt, memh, 0, 0, SNEC_NMEMS >> 2);
325 }
326
327 /* again read test if these are 0 */
328 for (i = 0; i < SNEC_NBANK; i++) {
329 /* select new bank */
330 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
331 bus_space_write_1(iot, ioh, SNEC_CTRLB,
332 SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN);
333
334 /* check if cleared */
335 for (j = 0; j < SNEC_NMEMS; j += 2) {
336 if (bus_space_read_2(memt, memh, j) != 0)
337 break;
338 }
339
340 if (j != SNEC_NMEMS) {
341 printf("snc_nec16_check_memory: "
342 "memory zero clear failed at 0x%04x%04x\n", i, j);
343 return 0;
344 }
345 }
346
347 return 1;
348}
349
350int
351snc_nec16_detectsubr(iot, ioh, memt, memh, irq, maddr, type)
352 bus_space_tag_t iot;
353 bus_space_handle_t ioh;
354 bus_space_tag_t memt;
355 bus_space_handle_t memh;
356 int irq;
357 int maddr;
358 u_int8_t type;
359{
360 u_int16_t cr;
361 u_int8_t ident;
362 int rv = 0;
363
364 if (snc_nec16_validate_irq(irq) == (u_int8_t) -1)
365 return 0;
366 /* XXX: maddr already checked */
367 if (snc_nec16_validate_mem(maddr) == 0)
368 return 0;
369
370 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_IDENT);
371 ident = bus_space_read_1(iot, ioh, SNEC_CTRLB);
372 if (ident == 0xff || ident == 0x00) {
373 /* not found */
374 return 0;
375 }
376
377 switch (type) {
378 case SNEC_TYPE_LEGACY:
379 rv = (ident == SNECR_IDENT_LEGACY_CBUS);
380 break;
381 case SNEC_TYPE_PNP:
382 rv = ((ident == SNECR_IDENT_PNP_CBUS) ||
383 (ident == SNECR_IDENT_PNP_PCMCIABUS));
384 break;
385 default:
386 break;
387 }
388
389 if (rv == 0) {
390 printf("snc_nec16_detectsubr: parent bus mismatch\n");
391 return 0;
392 }
393
394 /* select SONIC register SNCR_CR */
395 bus_space_write_1(iot, ioh, SNEC_ADDR, SNCR_CR);
396 bus_space_write_2(iot, ioh, SNEC_CTRL, CR_RXDIS | CR_STP | CR_RST);
397 delay(400);
398
399 cr = bus_space_read_2(iot, ioh, SNEC_CTRL);
400 if (cr != (CR_RXDIS | CR_STP | CR_RST)) {
401#ifdef DIAGNOSTIC
402 printf("snc_nec16_detectsubr: card reset failed, cr = 0x%04x\n",
403 cr);
404#endif
405 return 0;
406 }
407
408 if (snc_nec16_check_memory(iot, ioh, memt, memh) == 0)
409 return 0;
410
411 return 1;
412}
413
414/* XXX */
415#define SNC_VENDOR_NEC 0x00004c
416#define SNC_NEC_SERIES_LEGACY_CBUS 0xa5
417#define SNC_NEC_SERIES_PNP_PCMCIA 0xd5
418#define SNC_NEC_SERIES_PNP_PCMCIA2 0x6d /* XXX */
419#define SNC_NEC_SERIES_PNP_CBUS 0x0d
420#define SNC_NEC_SERIES_PNP_CBUS2 0x3d
421
422u_int8_t *
423snc_nec16_detect_type(myea)
424 u_int8_t *myea;
425{
426 u_int32_t vendor = (myea[0] << 16) | (myea[1] << 8) | myea[2];
427 u_int8_t series = myea[3];
428 u_int8_t type = myea[4] & 0x80;
429 u_int8_t *typestr;
430
431 switch (vendor) {
432 case SNC_VENDOR_NEC:
433 switch (series) {
434 case SNC_NEC_SERIES_LEGACY_CBUS:
435 if (type)
436 typestr = "NEC PC-9801-84";
437 else
438 typestr = "NEC PC-9801-83";
439 break;
440 case SNC_NEC_SERIES_PNP_CBUS:
441 case SNC_NEC_SERIES_PNP_CBUS2:
442 if (type)
443 typestr = "NEC PC-9801-104";
444 else
445 typestr = "NEC PC-9801-103";
446 break;
447 case SNC_NEC_SERIES_PNP_PCMCIA:
448 case SNC_NEC_SERIES_PNP_PCMCIA2:
449 /* XXX: right ? */
450 if (type)
451 typestr = "NEC PC-9801N-J02R";
452 else
453 typestr = "NEC PC-9801N-J02";
454 break;
455 default:
456 typestr = "NEC unknown (PC-9801N-25?)";
457 break;
458 }
459 break;
460 default:
461 typestr = "unknown (3rd vendor?)";
462 break;
463 }
464
465 return typestr;
466}
467
468int
469snc_nec16_get_enaddr(iot, ioh, myea)
470 bus_space_tag_t iot;
471 bus_space_handle_t ioh;
472 u_int8_t *myea;
473{
474 u_int8_t eeprom[SNEC_EEPROM_SIZE];
475 u_int8_t rom_sum, sum = 0x00;
476 int i;
477
478 snc_nec16_read_eeprom(iot, ioh, eeprom);
479
480 for (i = SNEC_EEPROM_KEY0; i < SNEC_EEPROM_CKSUM; i++) {
481 sum = sum ^ eeprom[i];
482 }
483
484 rom_sum = eeprom[SNEC_EEPROM_CKSUM];
485
486 if (sum != rom_sum) {
487 printf("snc_nec16_get_enaddr: "
488 "checksum mismatch; calculated %02x != read %02x",
489 sum, rom_sum);
490 return 0;
491 }
492
493 for (i = 0; i < ETHER_ADDR_LEN; i++)
494 myea[i] = eeprom[SNEC_EEPROM_SA0 + i];
495
496 return 1;
497}
498
499/*
500 * read from NEC/SONIC NIC register.
501 */
502u_int16_t
503snc_nec16_nic_get(sc, reg)
504 struct snc_softc *sc;
505 u_int8_t reg;
506{
507 u_int16_t val;
508
509 /* select SONIC register */
510 bus_space_write_1(sc->sc_iot, sc->sc_ioh, SNEC_ADDR, reg);
511 val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SNEC_CTRL);
512
513 return val;
514}
515
516/*
517 * write to NEC/SONIC NIC register.
518 */
519void
520snc_nec16_nic_put(sc, reg, val)
521 struct snc_softc *sc;
522 u_int8_t reg;
523 u_int16_t val;
524{
525
526 /* select SONIC register */
527 bus_space_write_1(sc->sc_iot, sc->sc_ioh, SNEC_ADDR, reg);
528 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SNEC_CTRL, val);
529}
530
531
532/*
533 * select memory bank and map
534 * where exists specified (internal buffer memory) offset.
535 */
536integrate u_int16_t
537snc_nec16_select_bank(sc, base, offset)
538 struct snc_softc *sc;
539 u_int32_t base;
540 u_int32_t offset;
541{
542 bus_space_tag_t iot = sc->sc_iot;
543 bus_space_handle_t ioh = sc->sc_ioh;
544 u_int8_t bank;
545 u_int16_t noffset;
546
547 /* bitmode is fixed to 16 bit. */
548 bank = (base + offset * 2) >> 13;
549 noffset = (base + offset * 2) & (SNEC_NMEMS - 1);
550
551#ifdef SNCDEBUG
552 if (noffset % 2) {
553 device_printf(sc->sc_dev, "noffset is odd (0x%04x)\n",
554 noffset);
555 }
556#endif /* SNCDEBUG */
557
558 if (sc->curbank != bank) {
559 /* select SNECR_MEMBS register */
560 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
561 /* select new bank */
562 bus_space_write_1(iot, ioh, SNEC_CTRLB,
563 SNECR_MEMBS_B2EB(bank) | SNECR_MEMBS_BSEN);
564 /* update current bank */
565 sc->curbank = bank;
566 }
567
568 return noffset;
569}
570
571/*
572 * write to SONIC descriptors.
573 */
574void
575snc_nec16_writetodesc(sc, base, offset, val)
576 struct snc_softc *sc;
577 u_int32_t base;
578 u_int32_t offset;
579 u_int16_t val;
580{
581 bus_space_tag_t memt = sc->sc_memt;
582 bus_space_handle_t memh = sc->sc_memh;
583 u_int16_t noffset;
584
585 noffset = snc_nec16_select_bank(sc, base, offset);
586
587 bus_space_write_2(memt, memh, noffset, val);
588}
589
590/*
591 * read from SONIC descriptors.
592 */
593u_int16_t
594snc_nec16_readfromdesc(sc, base, offset)
595 struct snc_softc *sc;
596 u_int32_t base;
597 u_int32_t offset;
598{
599 bus_space_tag_t memt = sc->sc_memt;
600 bus_space_handle_t memh = sc->sc_memh;
601 u_int16_t noffset;
602
603 noffset = snc_nec16_select_bank(sc, base, offset);
604
605 return bus_space_read_2(memt, memh, noffset);
606}
607
608/*
609 * read from SONIC data buffer.
610 */
611void
612snc_nec16_copyfrombuf(sc, dst, offset, size)
613 struct snc_softc *sc;
614 void *dst;
615 u_int32_t offset;
616 size_t size;
617{
618 bus_space_tag_t memt = sc->sc_memt;
619 bus_space_handle_t memh = sc->sc_memh;
620 u_int16_t noffset;
621 u_int8_t* bptr = dst;
622
623 noffset = snc_nec16_select_bank(sc, offset, 0);
624
625 /* XXX: should check if offset + size < 0x2000. */
626
627 bus_space_barrier(memt, memh, noffset, size,
628 BUS_SPACE_BARRIER_READ);
629
630 if (size > 3) {
631 if (noffset & 3) {
632 size_t asize = 4 - (noffset & 3);
633
634 bus_space_read_region_1(memt, memh, noffset,
635 bptr, asize);
636 bptr += asize;
637 noffset += asize;
638 size -= asize;
639 }
640 bus_space_read_region_4(memt, memh, noffset,
641 (u_int32_t *) bptr, size >> 2);
642 bptr += size & ~3;
643 noffset += size & ~3;
644 size &= 3;
645 }
646 if (size)
647 bus_space_read_region_1(memt, memh, noffset, bptr, size);
648}
649
650/*
651 * write to SONIC data buffer.
652 */
653void
654snc_nec16_copytobuf(sc, src, offset, size)
655 struct snc_softc *sc;
656 void *src;
657 u_int32_t offset;
658 size_t size;
659{
660 bus_space_tag_t memt = sc->sc_memt;
661 bus_space_handle_t memh = sc->sc_memh;
662 u_int16_t noffset, onoffset;
663 size_t osize = size;
664 u_int8_t* bptr = src;
665
666 noffset = snc_nec16_select_bank(sc, offset, 0);
667 onoffset = noffset;
668
669 /* XXX: should check if offset + size < 0x2000. */
670
671 if (size > 3) {
672 if (noffset & 3) {
673 size_t asize = 4 - (noffset & 3);
674
675 bus_space_write_region_1(memt, memh, noffset,
676 bptr, asize);
677 bptr += asize;
678 noffset += asize;
679 size -= asize;
680 }
681 bus_space_write_region_4(memt, memh, noffset,
682 (u_int32_t *)bptr, size >> 2);
683 bptr += size & ~3;
684 noffset += size & ~3;
685 size -= size & ~3;
686 }
687 if (size)
688 bus_space_write_region_1(memt, memh, noffset, bptr, size);
689
690 bus_space_barrier(memt, memh, onoffset, osize,
691 BUS_SPACE_BARRIER_WRITE);
692}
693
694/*
695 * write (fill) 0 to SONIC data buffer.
696 */
697void
698snc_nec16_zerobuf(sc, offset, size)
699 struct snc_softc *sc;
700 u_int32_t offset;
701 size_t size;
702{
703 bus_space_tag_t memt = sc->sc_memt;
704 bus_space_handle_t memh = sc->sc_memh;
705 u_int16_t noffset, onoffset;
706 size_t osize = size;
707
708 noffset = snc_nec16_select_bank(sc, offset, 0);
709 onoffset = noffset;
710
711 /* XXX: should check if offset + size < 0x2000. */
712
713 if (size > 3) {
714 if (noffset & 3) {
715 size_t asize = 4 - (noffset & 3);
716
717 bus_space_set_region_1(memt, memh, noffset, 0, asize);
718 noffset += asize;
719 size -= asize;
720 }
721 bus_space_set_region_4(memt, memh, noffset, 0, size >> 2);
722 noffset += size & ~3;
723 size -= size & ~3;
724 }
725 if (size)
726 bus_space_set_region_1(memt, memh, noffset, 0, size);
727
728 bus_space_barrier(memt, memh, onoffset, osize,
729 BUS_SPACE_BARRIER_WRITE);
730}
731
732
733/*
734 * Routines to read bytes sequentially from EEPROM through NEC PC-9801-83,
735 * 84, 103, 104, PC-9801N-25 and PC-9801N-J02, J02R for NetBSD/pc98.
736 * Ported by Kouichi Matsuda.
737 *
738 * This algorism is generic to read data sequentially from 4-Wire
739 * Microwire Serial EEPROM.
740 */
741
742#define SNEC_EEP_DELAY 1000
743
744void
745snc_nec16_read_eeprom(iot, ioh, data)
746 bus_space_tag_t iot;
747 bus_space_handle_t ioh;
748 u_int8_t *data;
749{
750 u_int8_t n, val, bit;
751
752 /* Read bytes from EEPROM; two bytes per an iteration. */
753 for (n = 0; n < SNEC_EEPROM_SIZE / 2; n++) {
754 /* select SNECR_EEP */
755 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_EEP);
756
757 bus_space_write_1(iot, ioh, SNEC_CTRLB, 0x00);
758 delay(SNEC_EEP_DELAY);
759
760 /* Start EEPROM access. */
761 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS);
762 delay(SNEC_EEP_DELAY);
763
764 bus_space_write_1(iot, ioh, SNEC_CTRLB,
765 SNECR_EEP_CS | SNECR_EEP_SK);
766 delay(SNEC_EEP_DELAY);
767
768 bus_space_write_1(iot, ioh, SNEC_CTRLB,
769 SNECR_EEP_CS | SNECR_EEP_DI);
770 delay(SNEC_EEP_DELAY);
771
772 bus_space_write_1(iot, ioh, SNEC_CTRLB,
773 SNECR_EEP_CS | SNECR_EEP_SK | SNECR_EEP_DI);
774 delay(SNEC_EEP_DELAY);
775
776 bus_space_write_1(iot, ioh, SNEC_CTRLB,
777 SNECR_EEP_CS | SNECR_EEP_DI);
778 delay(SNEC_EEP_DELAY);
779
780 bus_space_write_1(iot, ioh, SNEC_CTRLB,
781 SNECR_EEP_CS | SNECR_EEP_SK | SNECR_EEP_DI);
782 delay(SNEC_EEP_DELAY);
783
784 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS);
785 delay(SNEC_EEP_DELAY);
786
787 bus_space_write_1(iot, ioh, SNEC_CTRLB,
788 SNECR_EEP_CS | SNECR_EEP_SK);
789 delay(SNEC_EEP_DELAY);
790
791 /* Pass the iteration count to the chip. */
792 for (bit = 0x20; bit != 0x00; bit >>= 1) {
793 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS |
794 ((n & bit) ? SNECR_EEP_DI : 0x00));
795 delay(SNEC_EEP_DELAY);
796
797 bus_space_write_1(iot, ioh, SNEC_CTRLB,
798 SNECR_EEP_CS | SNECR_EEP_SK |
799 ((n & bit) ? SNECR_EEP_DI : 0x00));
800 delay(SNEC_EEP_DELAY);
801 }
802
803 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS);
804 (void) bus_space_read_1(iot, ioh, SNEC_CTRLB); /* ACK */
805 delay(SNEC_EEP_DELAY);
806
807 /* Read a byte. */
808 val = 0;
809 for (bit = 0x80; bit != 0x00; bit >>= 1) {
810 bus_space_write_1(iot, ioh, SNEC_CTRLB,
811 SNECR_EEP_CS | SNECR_EEP_SK);
812 delay(SNEC_EEP_DELAY);
813
814 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS);
815
816 if (bus_space_read_1(iot, ioh, SNEC_CTRLB) & SNECR_EEP_DO)
817 val |= bit;
818 }
819 *data++ = val;
820
821 /* Read one more byte. */
822 val = 0;
823 for (bit = 0x80; bit != 0x00; bit >>= 1) {
824 bus_space_write_1(iot, ioh, SNEC_CTRLB,
825 SNECR_EEP_CS | SNECR_EEP_SK);
826 delay(SNEC_EEP_DELAY);
827
828 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS);
829
830 if (bus_space_read_1(iot, ioh, SNEC_CTRLB) & SNECR_EEP_DO)
831 val |= bit;
832 }
833 *data++ = val;
834
835 bus_space_write_1(iot, ioh, SNEC_CTRLB, 0x00);
836 delay(SNEC_EEP_DELAY);
837 }
838
839#ifdef SNCDEBUG
840 /* Report what we got. */
841 data -= SNEC_EEPROM_SIZE;
842 log(LOG_INFO, "%s: EEPROM:"
843 " %02x%02x%02x%02x %02x%02x%02x%02x -"
844 " %02x%02x%02x%02x %02x%02x%02x%02x -"
845 " %02x%02x%02x%02x %02x%02x%02x%02x -"
846 " %02x%02x%02x%02x %02x%02x%02x%02x\n",
847 "snc_nec16_read_eeprom",
848 data[ 0], data[ 1], data[ 2], data[ 3],
849 data[ 4], data[ 5], data[ 6], data[ 7],
850 data[ 8], data[ 9], data[10], data[11],
851 data[12], data[13], data[14], data[15],
852 data[16], data[17], data[18], data[19],
853 data[20], data[21], data[22], data[23],
854 data[24], data[25], data[26], data[27],
855 data[28], data[29], data[30], data[31]);
856#endif
857}
858
859#ifdef SNCDEBUG
860void
861snc_nec16_dump_reg(iot, ioh)
862 bus_space_tag_t iot;
863 bus_space_handle_t ioh;
864{
865 u_int8_t n;
866 u_int16_t val;
867
868 printf("SONIC registers (word):");
869 for (n = 0; n < SNC_NREGS; n++) {
870 /* select required SONIC register */
871 bus_space_write_1(iot, ioh, SNEC_ADDR, n);
872 delay(10);
873 val = bus_space_read_2(iot, ioh, SNEC_CTRL);
874 if ((n % 0x10) == 0)
875 printf("\n%04x ", val);
876 else
877 printf("%04x ", val);
878 }
879 printf("\n");
880
881 printf("NEC/SONIC registers (byte):\n");
882 for (n = SNECR_MEMBS; n <= SNECR_IDENT; n += 2) {
883 /* select required SONIC register */
884 bus_space_write_1(iot, ioh, SNEC_ADDR, n);
885 delay(10);
886 val = (u_int16_t) bus_space_read_1(iot, ioh, SNEC_CTRLB);
887 printf("%04x ", val);
888 }
889 printf("\n");
890}
891
892#endif /* SNCDEBUG */
37/*
38 * Routines of NEC PC-9801-83, 84, 103, 104, PC-9801N-25 and PC-9801N-J02, J02R
39 * Ethernet interface for NetBSD/pc98, ported by Kouichi Matsuda.
40 *
41 * These cards use National Semiconductor DP83934AVQB as Ethernet Controller
42 * and National Semiconductor NS46C46 as (64 * 16 bits) Microwire Serial EEPROM.
43 */
44
45/*
46 * Modified for FreeBSD(98) 4.0 from NetBSD/pc98 1.4.2 by Motomichi Matsuzaki.
47 */
48
49#include <sys/param.h>
50#include <sys/systm.h>
51#include <sys/protosw.h>
52#include <sys/socket.h>
53
54#include <net/ethernet.h>
55#include <net/if.h>
56#include <net/if_arp.h>
57#include <net/if_media.h>
58
59#ifdef INET
60#include <netinet/in.h>
61#include <netinet/in_systm.h>
62#include <netinet/in_var.h>
63#include <netinet/ip.h>
64#include <netinet/if_inarp.h>
65#endif
66
67
68#include <sys/bus.h>
69#include <machine/bus.h>
70
71#include <dev/snc/dp83932reg.h>
72#include <dev/snc/dp83932var.h>
73#include <dev/snc/if_sncreg.h>
74#include <dev/snc/dp83932subr.h>
75
76integrate u_int16_t snc_nec16_select_bank
77 (struct snc_softc *, u_int32_t, u_int32_t);
78
79/*
80 * Interface exists: make available by filling in network interface
81 * record. System will initialize the interface when it is ready
82 * to accept packets.
83 */
84int
85sncsetup(sc, lladdr)
86 struct snc_softc *sc;
87 u_int8_t *lladdr;
88{
89 u_int32_t p, pp;
90 int i;
91 int offset;
92
93 /*
94 * Put the pup in reset mode (sncinit() will fix it later),
95 * stop the timer, disable all interrupts and clear any interrupts.
96 */
97 NIC_PUT(sc, SNCR_CR, CR_STP);
98 wbflush();
99 NIC_PUT(sc, SNCR_CR, CR_RST);
100 wbflush();
101 NIC_PUT(sc, SNCR_IMR, 0);
102 wbflush();
103 NIC_PUT(sc, SNCR_ISR, ISR_ALL);
104 wbflush();
105
106 /*
107 * because the SONIC is basically 16bit device it 'concatenates'
108 * a higher buffer address to a 16 bit offset--this will cause wrap
109 * around problems near the end of 64k !!
110 */
111 p = pp = 0;
112
113 for (i = 0; i < NRRA; i++) {
114 sc->v_rra[i] = SONIC_GETDMA(p);
115 p += RXRSRC_SIZE(sc);
116 }
117 sc->v_rea = SONIC_GETDMA(p);
118
119 p = SOALIGN(sc, p);
120
121 sc->v_cda = SONIC_GETDMA(p);
122 p += CDA_SIZE(sc);
123
124 p = SOALIGN(sc, p);
125
126 for (i = 0; i < NTDA; i++) {
127 struct mtd *mtdp = &sc->mtda[i];
128 mtdp->mtd_vtxp = SONIC_GETDMA(p);
129 p += TXP_SIZE(sc);
130 }
131
132 p = SOALIGN(sc, p);
133
134 if ((p - pp) > NBPG) {
135 device_printf (sc->sc_dev, "sizeof RRA (%ld) + CDA (%ld) +"
136 "TDA (%ld) > NBPG (%d). Punt!\n",
137 (ulong)sc->v_cda - (ulong)sc->v_rra[0],
138 (ulong)sc->mtda[0].mtd_vtxp - (ulong)sc->v_cda,
139 (ulong)p - (ulong)sc->mtda[0].mtd_vtxp,
140 NBPG);
141 return(1);
142 }
143
144 p = pp + NBPG;
145 pp = p;
146
147 sc->sc_nrda = NBPG / RXPKT_SIZE(sc);
148 sc->v_rda = SONIC_GETDMA(p);
149
150 p = pp + NBPG;
151
152 for (i = 0; i < NRBA; i++) {
153 sc->rbuf[i] = p;
154 p += NBPG;
155 }
156
157 pp = p;
158 offset = TXBSIZE;
159 for (i = 0; i < NTDA; i++) {
160 struct mtd *mtdp = &sc->mtda[i];
161
162 mtdp->mtd_vbuf = SONIC_GETDMA(p);
163 offset += TXBSIZE;
164 if (offset < NBPG) {
165 p += TXBSIZE;
166 } else {
167 p = pp + NBPG;
168 pp = p;
169 offset = TXBSIZE;
170 }
171 }
172
173 return (0);
174}
175
176/*
177 * miscellaneous NEC/SONIC detect functions.
178 */
179
180/*
181 * check if a specified irq is acceptable.
182 */
183u_int8_t
184snc_nec16_validate_irq(irq)
185 int irq;
186{
187 const u_int8_t encoded_irq[16] = {
188 -1, -1, -1, 0, -1, 1, 2, -1, -1, 3, 4, -1, 5, 6, -1, -1
189 };
190
191 return encoded_irq[irq];
192}
193
194/*
195 * specify irq to board.
196 */
197int
198snc_nec16_register_irq(sc, irq)
199 struct snc_softc *sc;
200 int irq;
201{
202 bus_space_tag_t iot = sc->sc_iot;
203 bus_space_handle_t ioh = sc->sc_ioh;
204 u_int8_t encoded_irq;
205
206 encoded_irq = snc_nec16_validate_irq(irq);
207 if (encoded_irq == (u_int8_t) -1) {
208 printf("snc_nec16_register_irq: unsupported irq (%d)\n", irq);
209 return 0;
210 }
211
212 /* select SNECR_IRQSEL register */
213 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_IRQSEL);
214 /* write encoded irq value */
215 bus_space_write_1(iot, ioh, SNEC_CTRLB, encoded_irq);
216
217 return 1;
218}
219
220/*
221 * check if a specified memory base address is acceptable.
222 */
223int
224snc_nec16_validate_mem(maddr)
225 int maddr;
226{
227
228 /* Check on Normal mode with max range, only */
229 if ((maddr & ~0x1E000) != 0xC0000) {
230 printf("snc_nec16_validate_mem: "
231 "unsupported window base (0x%x)\n", maddr);
232 return 0;
233 }
234
235 return 1;
236}
237
238/*
239 * specify memory base address to board and map to first bank.
240 */
241int
242snc_nec16_register_mem(sc, maddr)
243 struct snc_softc *sc;
244 int maddr;
245{
246 bus_space_tag_t iot = sc->sc_iot;
247 bus_space_handle_t ioh = sc->sc_ioh;
248
249 if (snc_nec16_validate_mem(maddr) == 0)
250 return 0;
251
252 /* select SNECR_MEMSEL register */
253 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMSEL);
254 /* write encoded memory base select value */
255 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_MEMSEL_PHYS2EN(maddr));
256
257 /*
258 * set current bank to 0 (bottom) and map
259 */
260 /* select SNECR_MEMBS register */
261 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
262 /* select new bank */
263 bus_space_write_1(iot, ioh, SNEC_CTRLB,
264 SNECR_MEMBS_B2EB(0) | SNECR_MEMBS_BSEN);
265 /* set current bank to 0 */
266 sc->curbank = 0;
267
268 return 1;
269}
270
271int
272snc_nec16_check_memory(iot, ioh, memt, memh)
273 bus_space_tag_t iot;
274 bus_space_handle_t ioh;
275 bus_space_tag_t memt;
276 bus_space_handle_t memh;
277{
278 u_int16_t val;
279 int i, j;
280
281 val = 0;
282 for (i = 0; i < SNEC_NBANK; i++) {
283 /* select new bank */
284 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
285 bus_space_write_1(iot, ioh, SNEC_CTRLB,
286 SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN);
287
288 /* write test pattern */
289 for (j = 0; j < SNEC_NMEMS / 2; j++) {
290 bus_space_write_2(memt, memh, j * 2, val + j);
291 }
292 val += 0x1000;
293 }
294
295 val = 0;
296 for (i = 0; i < SNEC_NBANK; i++) {
297 /* select new bank */
298 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
299 bus_space_write_1(iot, ioh, SNEC_CTRLB,
300 SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN);
301
302 /* read test pattern */
303 for (j = 0; j < SNEC_NMEMS / 2; j++) {
304 if (bus_space_read_2(memt, memh, j * 2) != val + j)
305 break;
306 }
307
308 if (j < SNEC_NMEMS / 2) {
309 printf("snc_nec16_check_memory: "
310 "memory check failed at 0x%04x%04x"
311 "val 0x%04x != expected 0x%04x\n", i, j,
312 bus_space_read_2(memt, memh, j * 2),
313 val + j);
314 return 0;
315 }
316 val += 0x1000;
317 }
318
319 /* zero clear mem */
320 for (i = 0; i < SNEC_NBANK; i++) {
321 /* select new bank */
322 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
323 bus_space_write_1(iot, ioh, SNEC_CTRLB,
324 SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN);
325
326 bus_space_set_region_4(memt, memh, 0, 0, SNEC_NMEMS >> 2);
327 }
328
329 /* again read test if these are 0 */
330 for (i = 0; i < SNEC_NBANK; i++) {
331 /* select new bank */
332 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
333 bus_space_write_1(iot, ioh, SNEC_CTRLB,
334 SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN);
335
336 /* check if cleared */
337 for (j = 0; j < SNEC_NMEMS; j += 2) {
338 if (bus_space_read_2(memt, memh, j) != 0)
339 break;
340 }
341
342 if (j != SNEC_NMEMS) {
343 printf("snc_nec16_check_memory: "
344 "memory zero clear failed at 0x%04x%04x\n", i, j);
345 return 0;
346 }
347 }
348
349 return 1;
350}
351
352int
353snc_nec16_detectsubr(iot, ioh, memt, memh, irq, maddr, type)
354 bus_space_tag_t iot;
355 bus_space_handle_t ioh;
356 bus_space_tag_t memt;
357 bus_space_handle_t memh;
358 int irq;
359 int maddr;
360 u_int8_t type;
361{
362 u_int16_t cr;
363 u_int8_t ident;
364 int rv = 0;
365
366 if (snc_nec16_validate_irq(irq) == (u_int8_t) -1)
367 return 0;
368 /* XXX: maddr already checked */
369 if (snc_nec16_validate_mem(maddr) == 0)
370 return 0;
371
372 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_IDENT);
373 ident = bus_space_read_1(iot, ioh, SNEC_CTRLB);
374 if (ident == 0xff || ident == 0x00) {
375 /* not found */
376 return 0;
377 }
378
379 switch (type) {
380 case SNEC_TYPE_LEGACY:
381 rv = (ident == SNECR_IDENT_LEGACY_CBUS);
382 break;
383 case SNEC_TYPE_PNP:
384 rv = ((ident == SNECR_IDENT_PNP_CBUS) ||
385 (ident == SNECR_IDENT_PNP_PCMCIABUS));
386 break;
387 default:
388 break;
389 }
390
391 if (rv == 0) {
392 printf("snc_nec16_detectsubr: parent bus mismatch\n");
393 return 0;
394 }
395
396 /* select SONIC register SNCR_CR */
397 bus_space_write_1(iot, ioh, SNEC_ADDR, SNCR_CR);
398 bus_space_write_2(iot, ioh, SNEC_CTRL, CR_RXDIS | CR_STP | CR_RST);
399 delay(400);
400
401 cr = bus_space_read_2(iot, ioh, SNEC_CTRL);
402 if (cr != (CR_RXDIS | CR_STP | CR_RST)) {
403#ifdef DIAGNOSTIC
404 printf("snc_nec16_detectsubr: card reset failed, cr = 0x%04x\n",
405 cr);
406#endif
407 return 0;
408 }
409
410 if (snc_nec16_check_memory(iot, ioh, memt, memh) == 0)
411 return 0;
412
413 return 1;
414}
415
416/* XXX */
417#define SNC_VENDOR_NEC 0x00004c
418#define SNC_NEC_SERIES_LEGACY_CBUS 0xa5
419#define SNC_NEC_SERIES_PNP_PCMCIA 0xd5
420#define SNC_NEC_SERIES_PNP_PCMCIA2 0x6d /* XXX */
421#define SNC_NEC_SERIES_PNP_CBUS 0x0d
422#define SNC_NEC_SERIES_PNP_CBUS2 0x3d
423
424u_int8_t *
425snc_nec16_detect_type(myea)
426 u_int8_t *myea;
427{
428 u_int32_t vendor = (myea[0] << 16) | (myea[1] << 8) | myea[2];
429 u_int8_t series = myea[3];
430 u_int8_t type = myea[4] & 0x80;
431 u_int8_t *typestr;
432
433 switch (vendor) {
434 case SNC_VENDOR_NEC:
435 switch (series) {
436 case SNC_NEC_SERIES_LEGACY_CBUS:
437 if (type)
438 typestr = "NEC PC-9801-84";
439 else
440 typestr = "NEC PC-9801-83";
441 break;
442 case SNC_NEC_SERIES_PNP_CBUS:
443 case SNC_NEC_SERIES_PNP_CBUS2:
444 if (type)
445 typestr = "NEC PC-9801-104";
446 else
447 typestr = "NEC PC-9801-103";
448 break;
449 case SNC_NEC_SERIES_PNP_PCMCIA:
450 case SNC_NEC_SERIES_PNP_PCMCIA2:
451 /* XXX: right ? */
452 if (type)
453 typestr = "NEC PC-9801N-J02R";
454 else
455 typestr = "NEC PC-9801N-J02";
456 break;
457 default:
458 typestr = "NEC unknown (PC-9801N-25?)";
459 break;
460 }
461 break;
462 default:
463 typestr = "unknown (3rd vendor?)";
464 break;
465 }
466
467 return typestr;
468}
469
470int
471snc_nec16_get_enaddr(iot, ioh, myea)
472 bus_space_tag_t iot;
473 bus_space_handle_t ioh;
474 u_int8_t *myea;
475{
476 u_int8_t eeprom[SNEC_EEPROM_SIZE];
477 u_int8_t rom_sum, sum = 0x00;
478 int i;
479
480 snc_nec16_read_eeprom(iot, ioh, eeprom);
481
482 for (i = SNEC_EEPROM_KEY0; i < SNEC_EEPROM_CKSUM; i++) {
483 sum = sum ^ eeprom[i];
484 }
485
486 rom_sum = eeprom[SNEC_EEPROM_CKSUM];
487
488 if (sum != rom_sum) {
489 printf("snc_nec16_get_enaddr: "
490 "checksum mismatch; calculated %02x != read %02x",
491 sum, rom_sum);
492 return 0;
493 }
494
495 for (i = 0; i < ETHER_ADDR_LEN; i++)
496 myea[i] = eeprom[SNEC_EEPROM_SA0 + i];
497
498 return 1;
499}
500
501/*
502 * read from NEC/SONIC NIC register.
503 */
504u_int16_t
505snc_nec16_nic_get(sc, reg)
506 struct snc_softc *sc;
507 u_int8_t reg;
508{
509 u_int16_t val;
510
511 /* select SONIC register */
512 bus_space_write_1(sc->sc_iot, sc->sc_ioh, SNEC_ADDR, reg);
513 val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SNEC_CTRL);
514
515 return val;
516}
517
518/*
519 * write to NEC/SONIC NIC register.
520 */
521void
522snc_nec16_nic_put(sc, reg, val)
523 struct snc_softc *sc;
524 u_int8_t reg;
525 u_int16_t val;
526{
527
528 /* select SONIC register */
529 bus_space_write_1(sc->sc_iot, sc->sc_ioh, SNEC_ADDR, reg);
530 bus_space_write_2(sc->sc_iot, sc->sc_ioh, SNEC_CTRL, val);
531}
532
533
534/*
535 * select memory bank and map
536 * where exists specified (internal buffer memory) offset.
537 */
538integrate u_int16_t
539snc_nec16_select_bank(sc, base, offset)
540 struct snc_softc *sc;
541 u_int32_t base;
542 u_int32_t offset;
543{
544 bus_space_tag_t iot = sc->sc_iot;
545 bus_space_handle_t ioh = sc->sc_ioh;
546 u_int8_t bank;
547 u_int16_t noffset;
548
549 /* bitmode is fixed to 16 bit. */
550 bank = (base + offset * 2) >> 13;
551 noffset = (base + offset * 2) & (SNEC_NMEMS - 1);
552
553#ifdef SNCDEBUG
554 if (noffset % 2) {
555 device_printf(sc->sc_dev, "noffset is odd (0x%04x)\n",
556 noffset);
557 }
558#endif /* SNCDEBUG */
559
560 if (sc->curbank != bank) {
561 /* select SNECR_MEMBS register */
562 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
563 /* select new bank */
564 bus_space_write_1(iot, ioh, SNEC_CTRLB,
565 SNECR_MEMBS_B2EB(bank) | SNECR_MEMBS_BSEN);
566 /* update current bank */
567 sc->curbank = bank;
568 }
569
570 return noffset;
571}
572
573/*
574 * write to SONIC descriptors.
575 */
576void
577snc_nec16_writetodesc(sc, base, offset, val)
578 struct snc_softc *sc;
579 u_int32_t base;
580 u_int32_t offset;
581 u_int16_t val;
582{
583 bus_space_tag_t memt = sc->sc_memt;
584 bus_space_handle_t memh = sc->sc_memh;
585 u_int16_t noffset;
586
587 noffset = snc_nec16_select_bank(sc, base, offset);
588
589 bus_space_write_2(memt, memh, noffset, val);
590}
591
592/*
593 * read from SONIC descriptors.
594 */
595u_int16_t
596snc_nec16_readfromdesc(sc, base, offset)
597 struct snc_softc *sc;
598 u_int32_t base;
599 u_int32_t offset;
600{
601 bus_space_tag_t memt = sc->sc_memt;
602 bus_space_handle_t memh = sc->sc_memh;
603 u_int16_t noffset;
604
605 noffset = snc_nec16_select_bank(sc, base, offset);
606
607 return bus_space_read_2(memt, memh, noffset);
608}
609
610/*
611 * read from SONIC data buffer.
612 */
613void
614snc_nec16_copyfrombuf(sc, dst, offset, size)
615 struct snc_softc *sc;
616 void *dst;
617 u_int32_t offset;
618 size_t size;
619{
620 bus_space_tag_t memt = sc->sc_memt;
621 bus_space_handle_t memh = sc->sc_memh;
622 u_int16_t noffset;
623 u_int8_t* bptr = dst;
624
625 noffset = snc_nec16_select_bank(sc, offset, 0);
626
627 /* XXX: should check if offset + size < 0x2000. */
628
629 bus_space_barrier(memt, memh, noffset, size,
630 BUS_SPACE_BARRIER_READ);
631
632 if (size > 3) {
633 if (noffset & 3) {
634 size_t asize = 4 - (noffset & 3);
635
636 bus_space_read_region_1(memt, memh, noffset,
637 bptr, asize);
638 bptr += asize;
639 noffset += asize;
640 size -= asize;
641 }
642 bus_space_read_region_4(memt, memh, noffset,
643 (u_int32_t *) bptr, size >> 2);
644 bptr += size & ~3;
645 noffset += size & ~3;
646 size &= 3;
647 }
648 if (size)
649 bus_space_read_region_1(memt, memh, noffset, bptr, size);
650}
651
652/*
653 * write to SONIC data buffer.
654 */
655void
656snc_nec16_copytobuf(sc, src, offset, size)
657 struct snc_softc *sc;
658 void *src;
659 u_int32_t offset;
660 size_t size;
661{
662 bus_space_tag_t memt = sc->sc_memt;
663 bus_space_handle_t memh = sc->sc_memh;
664 u_int16_t noffset, onoffset;
665 size_t osize = size;
666 u_int8_t* bptr = src;
667
668 noffset = snc_nec16_select_bank(sc, offset, 0);
669 onoffset = noffset;
670
671 /* XXX: should check if offset + size < 0x2000. */
672
673 if (size > 3) {
674 if (noffset & 3) {
675 size_t asize = 4 - (noffset & 3);
676
677 bus_space_write_region_1(memt, memh, noffset,
678 bptr, asize);
679 bptr += asize;
680 noffset += asize;
681 size -= asize;
682 }
683 bus_space_write_region_4(memt, memh, noffset,
684 (u_int32_t *)bptr, size >> 2);
685 bptr += size & ~3;
686 noffset += size & ~3;
687 size -= size & ~3;
688 }
689 if (size)
690 bus_space_write_region_1(memt, memh, noffset, bptr, size);
691
692 bus_space_barrier(memt, memh, onoffset, osize,
693 BUS_SPACE_BARRIER_WRITE);
694}
695
696/*
697 * write (fill) 0 to SONIC data buffer.
698 */
699void
700snc_nec16_zerobuf(sc, offset, size)
701 struct snc_softc *sc;
702 u_int32_t offset;
703 size_t size;
704{
705 bus_space_tag_t memt = sc->sc_memt;
706 bus_space_handle_t memh = sc->sc_memh;
707 u_int16_t noffset, onoffset;
708 size_t osize = size;
709
710 noffset = snc_nec16_select_bank(sc, offset, 0);
711 onoffset = noffset;
712
713 /* XXX: should check if offset + size < 0x2000. */
714
715 if (size > 3) {
716 if (noffset & 3) {
717 size_t asize = 4 - (noffset & 3);
718
719 bus_space_set_region_1(memt, memh, noffset, 0, asize);
720 noffset += asize;
721 size -= asize;
722 }
723 bus_space_set_region_4(memt, memh, noffset, 0, size >> 2);
724 noffset += size & ~3;
725 size -= size & ~3;
726 }
727 if (size)
728 bus_space_set_region_1(memt, memh, noffset, 0, size);
729
730 bus_space_barrier(memt, memh, onoffset, osize,
731 BUS_SPACE_BARRIER_WRITE);
732}
733
734
735/*
736 * Routines to read bytes sequentially from EEPROM through NEC PC-9801-83,
737 * 84, 103, 104, PC-9801N-25 and PC-9801N-J02, J02R for NetBSD/pc98.
738 * Ported by Kouichi Matsuda.
739 *
740 * This algorism is generic to read data sequentially from 4-Wire
741 * Microwire Serial EEPROM.
742 */
743
744#define SNEC_EEP_DELAY 1000
745
746void
747snc_nec16_read_eeprom(iot, ioh, data)
748 bus_space_tag_t iot;
749 bus_space_handle_t ioh;
750 u_int8_t *data;
751{
752 u_int8_t n, val, bit;
753
754 /* Read bytes from EEPROM; two bytes per an iteration. */
755 for (n = 0; n < SNEC_EEPROM_SIZE / 2; n++) {
756 /* select SNECR_EEP */
757 bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_EEP);
758
759 bus_space_write_1(iot, ioh, SNEC_CTRLB, 0x00);
760 delay(SNEC_EEP_DELAY);
761
762 /* Start EEPROM access. */
763 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS);
764 delay(SNEC_EEP_DELAY);
765
766 bus_space_write_1(iot, ioh, SNEC_CTRLB,
767 SNECR_EEP_CS | SNECR_EEP_SK);
768 delay(SNEC_EEP_DELAY);
769
770 bus_space_write_1(iot, ioh, SNEC_CTRLB,
771 SNECR_EEP_CS | SNECR_EEP_DI);
772 delay(SNEC_EEP_DELAY);
773
774 bus_space_write_1(iot, ioh, SNEC_CTRLB,
775 SNECR_EEP_CS | SNECR_EEP_SK | SNECR_EEP_DI);
776 delay(SNEC_EEP_DELAY);
777
778 bus_space_write_1(iot, ioh, SNEC_CTRLB,
779 SNECR_EEP_CS | SNECR_EEP_DI);
780 delay(SNEC_EEP_DELAY);
781
782 bus_space_write_1(iot, ioh, SNEC_CTRLB,
783 SNECR_EEP_CS | SNECR_EEP_SK | SNECR_EEP_DI);
784 delay(SNEC_EEP_DELAY);
785
786 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS);
787 delay(SNEC_EEP_DELAY);
788
789 bus_space_write_1(iot, ioh, SNEC_CTRLB,
790 SNECR_EEP_CS | SNECR_EEP_SK);
791 delay(SNEC_EEP_DELAY);
792
793 /* Pass the iteration count to the chip. */
794 for (bit = 0x20; bit != 0x00; bit >>= 1) {
795 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS |
796 ((n & bit) ? SNECR_EEP_DI : 0x00));
797 delay(SNEC_EEP_DELAY);
798
799 bus_space_write_1(iot, ioh, SNEC_CTRLB,
800 SNECR_EEP_CS | SNECR_EEP_SK |
801 ((n & bit) ? SNECR_EEP_DI : 0x00));
802 delay(SNEC_EEP_DELAY);
803 }
804
805 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS);
806 (void) bus_space_read_1(iot, ioh, SNEC_CTRLB); /* ACK */
807 delay(SNEC_EEP_DELAY);
808
809 /* Read a byte. */
810 val = 0;
811 for (bit = 0x80; bit != 0x00; bit >>= 1) {
812 bus_space_write_1(iot, ioh, SNEC_CTRLB,
813 SNECR_EEP_CS | SNECR_EEP_SK);
814 delay(SNEC_EEP_DELAY);
815
816 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS);
817
818 if (bus_space_read_1(iot, ioh, SNEC_CTRLB) & SNECR_EEP_DO)
819 val |= bit;
820 }
821 *data++ = val;
822
823 /* Read one more byte. */
824 val = 0;
825 for (bit = 0x80; bit != 0x00; bit >>= 1) {
826 bus_space_write_1(iot, ioh, SNEC_CTRLB,
827 SNECR_EEP_CS | SNECR_EEP_SK);
828 delay(SNEC_EEP_DELAY);
829
830 bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS);
831
832 if (bus_space_read_1(iot, ioh, SNEC_CTRLB) & SNECR_EEP_DO)
833 val |= bit;
834 }
835 *data++ = val;
836
837 bus_space_write_1(iot, ioh, SNEC_CTRLB, 0x00);
838 delay(SNEC_EEP_DELAY);
839 }
840
841#ifdef SNCDEBUG
842 /* Report what we got. */
843 data -= SNEC_EEPROM_SIZE;
844 log(LOG_INFO, "%s: EEPROM:"
845 " %02x%02x%02x%02x %02x%02x%02x%02x -"
846 " %02x%02x%02x%02x %02x%02x%02x%02x -"
847 " %02x%02x%02x%02x %02x%02x%02x%02x -"
848 " %02x%02x%02x%02x %02x%02x%02x%02x\n",
849 "snc_nec16_read_eeprom",
850 data[ 0], data[ 1], data[ 2], data[ 3],
851 data[ 4], data[ 5], data[ 6], data[ 7],
852 data[ 8], data[ 9], data[10], data[11],
853 data[12], data[13], data[14], data[15],
854 data[16], data[17], data[18], data[19],
855 data[20], data[21], data[22], data[23],
856 data[24], data[25], data[26], data[27],
857 data[28], data[29], data[30], data[31]);
858#endif
859}
860
861#ifdef SNCDEBUG
862void
863snc_nec16_dump_reg(iot, ioh)
864 bus_space_tag_t iot;
865 bus_space_handle_t ioh;
866{
867 u_int8_t n;
868 u_int16_t val;
869
870 printf("SONIC registers (word):");
871 for (n = 0; n < SNC_NREGS; n++) {
872 /* select required SONIC register */
873 bus_space_write_1(iot, ioh, SNEC_ADDR, n);
874 delay(10);
875 val = bus_space_read_2(iot, ioh, SNEC_CTRL);
876 if ((n % 0x10) == 0)
877 printf("\n%04x ", val);
878 else
879 printf("%04x ", val);
880 }
881 printf("\n");
882
883 printf("NEC/SONIC registers (byte):\n");
884 for (n = SNECR_MEMBS; n <= SNECR_IDENT; n += 2) {
885 /* select required SONIC register */
886 bus_space_write_1(iot, ioh, SNEC_ADDR, n);
887 delay(10);
888 val = (u_int16_t) bus_space_read_1(iot, ioh, SNEC_CTRLB);
889 printf("%04x ", val);
890 }
891 printf("\n");
892}
893
894#endif /* SNCDEBUG */