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