if_sbni.c revision 104256
1/*
2 * Copyright (c) 1997-2001 Granch, Ltd. All rights reserved.
3 * Author: Denis I.Timofeev <timofeev@granch.ru>
4 *
5 * Redistributon and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice unmodified, this list of conditions, and the following
10 *    disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * $FreeBSD: head/sys/dev/sbni/if_sbni.c 104256 2002-10-01 00:55:22Z brooks $
28 */
29
30/*
31 * Device driver for Granch SBNI12 leased line adapters
32 *
33 * Revision 2.0.0  1997/08/06
34 * Initial revision by Alexey Zverev
35 *
36 * Revision 2.0.1 1997/08/11
37 * Additional internal statistics support (tx statistics)
38 *
39 * Revision 2.0.2 1997/11/05
40 * if_bpf bug has been fixed
41 *
42 * Revision 2.0.3 1998/12/20
43 * Memory leakage has been eliminated in
44 * the sbni_st and sbni_timeout routines.
45 *
46 * Revision 3.0 2000/08/10 by Yaroslav Polyakov
47 * Support for PCI cards. 4.1 modification.
48 *
49 * Revision 3.1 2000/09/12
50 * Removed extra #defines around bpf functions
51 *
52 * Revision 4.0 2000/11/23 by Denis Timofeev
53 * Completely redesigned the buffer management
54 *
55 * Revision 4.1 2001/01/21
56 * Support for PCI Dual cards and new SBNI12D-10, -11 Dual/ISA cards
57 *
58 * Written with reference to NE2000 driver developed by David Greenman.
59 */
60
61
62#include <sys/param.h>
63#include <sys/systm.h>
64#include <sys/socket.h>
65#include <sys/sockio.h>
66#include <sys/mbuf.h>
67#include <sys/kernel.h>
68#include <sys/proc.h>
69#include <sys/callout.h>
70#include <sys/syslog.h>
71#include <sys/random.h>
72
73#include <machine/bus.h>
74#include <sys/rman.h>
75#include <machine/resource.h>
76
77#include <net/if.h>
78#include <net/ethernet.h>
79#include <net/if_arp.h>
80#include <net/bpf.h>
81
82#include <dev/sbni/if_sbnireg.h>
83#include <dev/sbni/if_sbnivar.h>
84
85#define ASM_CRC 1
86
87static void	sbni_init(void *);
88static void	sbni_start(struct ifnet *);
89static int	sbni_ioctl(struct ifnet *, u_long, caddr_t);
90static void	sbni_watchdog(struct ifnet *);
91static void	sbni_stop(struct sbni_softc *);
92static void	handle_channel(struct sbni_softc *);
93
94static void	card_start(struct sbni_softc *);
95static int	recv_frame(struct sbni_softc *);
96static void	send_frame(struct sbni_softc *);
97static int	upload_data(struct sbni_softc *, u_int, u_int, u_int, u_int32_t);
98static int	skip_tail(struct sbni_softc *, u_int, u_int32_t);
99static void	interpret_ack(struct sbni_softc *, u_int);
100static void	download_data(struct sbni_softc *, u_int32_t *);
101static void	prepare_to_send(struct sbni_softc *);
102static void	drop_xmit_queue(struct sbni_softc *);
103static int	get_rx_buf(struct sbni_softc *);
104static void	indicate_pkt(struct sbni_softc *);
105static void	change_level(struct sbni_softc *);
106static int	check_fhdr(struct sbni_softc *, u_int *, u_int *,
107			   u_int *, u_int *, u_int32_t *);
108static int	append_frame_to_pkt(struct sbni_softc *, u_int, u_int32_t);
109static void	timeout_change_level(struct sbni_softc *);
110static void	send_frame_header(struct sbni_softc *, u_int32_t *);
111static void	set_initial_values(struct sbni_softc *, struct sbni_flags);
112
113static u_int32_t	calc_crc32(u_int32_t, caddr_t, u_int);
114static timeout_t	sbni_timeout;
115
116static __inline u_char	sbni_inb(struct sbni_softc *, enum sbni_reg);
117static __inline void	sbni_outb(struct sbni_softc *, enum sbni_reg, u_char);
118static __inline void	sbni_insb(struct sbni_softc *, u_char *, u_int);
119static __inline void	sbni_outsb(struct sbni_softc *, u_char *, u_int);
120
121static u_int32_t crc32tab[];
122
123#ifdef SBNI_DUAL_COMPOUND
124struct sbni_softc *sbni_headlist;
125#endif
126
127u_int32_t next_sbni_unit;
128
129/* -------------------------------------------------------------------------- */
130
131static __inline u_char
132sbni_inb(struct sbni_softc *sc, enum sbni_reg reg)
133{
134	return bus_space_read_1(
135	    rman_get_bustag(sc->io_res),
136	    rman_get_bushandle(sc->io_res),
137	    sc->io_off + reg);
138}
139
140static __inline void
141sbni_outb(struct sbni_softc *sc, enum sbni_reg reg, u_char value)
142{
143	bus_space_write_1(
144	    rman_get_bustag(sc->io_res),
145	    rman_get_bushandle(sc->io_res),
146	    sc->io_off + reg, value);
147}
148
149static __inline void
150sbni_insb(struct sbni_softc *sc, u_char *to, u_int len)
151{
152	bus_space_read_multi_1(
153	    rman_get_bustag(sc->io_res),
154	    rman_get_bushandle(sc->io_res),
155	    sc->io_off + DAT, to, len);
156}
157
158static __inline void
159sbni_outsb(struct sbni_softc *sc, u_char *from, u_int len)
160{
161	bus_space_write_multi_1(
162	    rman_get_bustag(sc->io_res),
163	    rman_get_bushandle(sc->io_res),
164	    sc->io_off + DAT, from, len);
165}
166
167
168/*
169	Valid combinations in CSR0 (for probing):
170
171	VALID_DECODER	0000,0011,1011,1010
172
173				    	; 0   ; -
174				TR_REQ	; 1   ; +
175			TR_RDY	    	; 2   ; -
176			TR_RDY	TR_REQ	; 3   ; +
177		BU_EMP		    	; 4   ; +
178		BU_EMP	     	TR_REQ	; 5   ; +
179		BU_EMP	TR_RDY	    	; 6   ; -
180		BU_EMP	TR_RDY	TR_REQ	; 7   ; +
181	RC_RDY 		     		; 8   ; +
182	RC_RDY			TR_REQ	; 9   ; +
183	RC_RDY		TR_RDY		; 10  ; -
184	RC_RDY		TR_RDY	TR_REQ	; 11  ; -
185	RC_RDY	BU_EMP			; 12  ; -
186	RC_RDY	BU_EMP		TR_REQ	; 13  ; -
187	RC_RDY	BU_EMP	TR_RDY		; 14  ; -
188	RC_RDY	BU_EMP	TR_RDY	TR_REQ	; 15  ; -
189*/
190
191#define VALID_DECODER	(2 + 8 + 0x10 + 0x20 + 0x80 + 0x100 + 0x200)
192
193
194int
195sbni_probe(struct sbni_softc *sc)
196{
197	u_char csr0;
198
199	csr0 = sbni_inb(sc, CSR0);
200	if (csr0 != 0xff && csr0 != 0x00) {
201		csr0 &= ~EN_INT;
202		if (csr0 & BU_EMP)
203			csr0 |= EN_INT;
204
205		if (VALID_DECODER & (1 << (csr0 >> 4)))
206			return (0);
207	}
208
209	return (ENXIO);
210}
211
212
213/*
214 * Install interface into kernel networking data structures
215 */
216void
217sbni_attach(struct sbni_softc *sc, int unit, struct sbni_flags flags)
218{
219	struct ifnet *ifp;
220	u_char csr0;
221
222	ifp = &sc->arpcom.ac_if;
223	sbni_outb(sc, CSR0, 0);
224	set_initial_values(sc, flags);
225
226	callout_handle_init(&sc->wch);
227	if (!ifp->if_name) {
228		/* Initialize ifnet structure */
229		ifp->if_softc	= sc;
230		ifp->if_unit	= unit;
231		ifp->if_name	= "sbni";
232		ifp->if_init	= sbni_init;
233		ifp->if_start	= sbni_start;
234	        ifp->if_output	= ether_output;
235		ifp->if_ioctl	= sbni_ioctl;
236		ifp->if_watchdog	= sbni_watchdog;
237		ifp->if_snd.ifq_maxlen	= IFQ_MAXLEN;
238
239		/* report real baud rate */
240		csr0 = sbni_inb(sc, CSR0);
241		ifp->if_baudrate =
242			(csr0 & 0x01 ? 500000 : 2000000) / (1 << flags.rate);
243
244	        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
245		ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
246	}
247	/* device attach does transition from UNCONFIGURED to IDLE state */
248
249	if_printf(ifp, "speed %ld, address %6D, rxl ",
250	       ifp->if_baudrate, sc->arpcom.ac_enaddr, ":");
251	if (sc->delta_rxl)
252		printf("auto\n");
253	else
254		printf("%d (fixed)\n", sc->cur_rxl_index);
255}
256
257/* -------------------------------------------------------------------------- */
258
259static void
260sbni_init(void *xsc)
261{
262	struct sbni_softc *sc;
263	struct ifnet *ifp;
264	int  s;
265
266	sc = (struct sbni_softc *)xsc;
267	ifp = &sc->arpcom.ac_if;
268
269	/* address not known */
270	if (TAILQ_EMPTY(&ifp->if_addrhead))
271		return;
272
273	/*
274	 * kludge to avoid multiple initialization when more than once
275	 * protocols configured
276	 */
277	if (ifp->if_flags & IFF_RUNNING)
278		return;
279
280	s = splimp();
281	ifp->if_timer = 0;
282	card_start(sc);
283	sc->wch = timeout(sbni_timeout, sc, hz/SBNI_HZ);
284
285	ifp->if_flags |= IFF_RUNNING;
286	ifp->if_flags &= ~IFF_OACTIVE;
287
288	/* attempt to start output */
289	sbni_start(ifp);
290	splx(s);
291}
292
293
294static void
295sbni_start(struct ifnet *ifp)
296{
297	struct sbni_softc *sc = ifp->if_softc;
298	if (sc->tx_frameno == 0)
299		prepare_to_send(sc);
300}
301
302
303static void
304sbni_stop(struct sbni_softc *sc)
305{
306	sbni_outb(sc, CSR0, 0);
307	drop_xmit_queue(sc);
308
309	if (sc->rx_buf_p) {
310		m_freem(sc->rx_buf_p);
311		sc->rx_buf_p = NULL;
312	}
313
314	untimeout(sbni_timeout, sc, sc->wch);
315	sc->wch.callout = NULL;
316}
317
318/* -------------------------------------------------------------------------- */
319
320/* interrupt handler */
321
322/*
323 * 	SBNI12D-10, -11/ISA boards within "common interrupt" mode could not
324 * be looked as two independent single-channel devices. Every channel seems
325 * as Ethernet interface but interrupt handler must be common. Really, first
326 * channel ("master") driver only registers the handler. In it's struct softc
327 * it has got pointer to "slave" channel's struct softc and handles that's
328 * interrupts too.
329 *	softc of successfully attached ISA SBNI boards is linked to list.
330 * While next board driver is initialized, it scans this list. If one
331 * has found softc with same irq and ioaddr different by 4 then it assumes
332 * this board to be "master".
333 */
334
335void
336sbni_intr(void *arg)
337{
338	struct sbni_softc *sc;
339	int repeat;
340
341	sc = (struct sbni_softc *)arg;
342
343	do {
344		repeat = 0;
345		if (sbni_inb(sc, CSR0) & (RC_RDY | TR_RDY)) {
346			handle_channel(sc);
347			repeat = 1;
348		}
349		if (sc->slave_sc && 	/* second channel present */
350		    (sbni_inb(sc->slave_sc, CSR0) & (RC_RDY | TR_RDY))) {
351			handle_channel(sc->slave_sc);
352			repeat = 1;
353		}
354	} while (repeat);
355}
356
357
358static void
359handle_channel(struct sbni_softc *sc)
360{
361	int req_ans;
362	u_char csr0;
363
364	sbni_outb(sc, CSR0, (sbni_inb(sc, CSR0) & ~EN_INT) | TR_REQ);
365
366	sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
367	for (;;) {
368		csr0 = sbni_inb(sc, CSR0);
369		if ((csr0 & (RC_RDY | TR_RDY)) == 0)
370			break;
371
372		req_ans = !(sc->state & FL_PREV_OK);
373
374		if (csr0 & RC_RDY)
375			req_ans = recv_frame(sc);
376
377		/*
378		 * TR_RDY always equals 1 here because we have owned the marker,
379		 * and we set TR_REQ when disabled interrupts
380		 */
381		csr0 = sbni_inb(sc, CSR0);
382		if ((csr0 & TR_RDY) == 0 || (csr0 & RC_RDY) != 0)
383			printf("sbni: internal error!\n");
384
385		/* if state & FL_NEED_RESEND != 0 then tx_frameno != 0 */
386		if (req_ans || sc->tx_frameno != 0)
387			send_frame(sc);
388		else {
389			/* send the marker without any data */
390			sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) & ~TR_REQ);
391		}
392	}
393
394	sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | EN_INT);
395}
396
397
398/*
399 * Routine returns 1 if it need to acknoweledge received frame.
400 * Empty frame received without errors won't be acknoweledged.
401 */
402
403static int
404recv_frame(struct sbni_softc *sc)
405{
406	u_int32_t crc;
407	u_int framelen, frameno, ack;
408	u_int is_first, frame_ok;
409
410	crc = CRC32_INITIAL;
411	if (check_fhdr(sc, &framelen, &frameno, &ack, &is_first, &crc)) {
412		frame_ok = framelen > 4 ?
413		    upload_data(sc, framelen, frameno, is_first, crc) :
414		    skip_tail(sc, framelen, crc);
415		if (frame_ok)
416			interpret_ack(sc, ack);
417	} else
418		frame_ok = 0;
419
420	sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) ^ CT_ZER);
421	if (frame_ok) {
422		sc->state |= FL_PREV_OK;
423		if (framelen > 4)
424			sc->in_stats.all_rx_number++;
425	} else {
426		sc->state &= ~FL_PREV_OK;
427		change_level(sc);
428		sc->in_stats.all_rx_number++;
429		sc->in_stats.bad_rx_number++;
430	}
431
432	return (!frame_ok || framelen > 4);
433}
434
435
436static void
437send_frame(struct sbni_softc *sc)
438{
439	u_int32_t crc;
440	u_char csr0;
441
442	crc = CRC32_INITIAL;
443	if (sc->state & FL_NEED_RESEND) {
444
445		/* if frame was sended but not ACK'ed - resend it */
446		if (sc->trans_errors) {
447			sc->trans_errors--;
448			if (sc->framelen != 0)
449				sc->in_stats.resend_tx_number++;
450		} else {
451			/* cannot xmit with many attempts */
452			drop_xmit_queue(sc);
453			goto do_send;
454		}
455	} else
456		sc->trans_errors = TR_ERROR_COUNT;
457
458	send_frame_header(sc, &crc);
459	sc->state |= FL_NEED_RESEND;
460	/*
461	 * FL_NEED_RESEND will be cleared after ACK, but if empty
462	 * frame sended then in prepare_to_send next frame
463	 */
464
465
466	if (sc->framelen) {
467		download_data(sc, &crc);
468		sc->in_stats.all_tx_number++;
469		sc->state |= FL_WAIT_ACK;
470	}
471
472	sbni_outsb(sc, (u_char *)&crc, sizeof crc);
473
474do_send:
475	csr0 = sbni_inb(sc, CSR0);
476	sbni_outb(sc, CSR0, csr0 & ~TR_REQ);
477
478	if (sc->tx_frameno) {
479		/* next frame exists - request to send */
480		sbni_outb(sc, CSR0, csr0 | TR_REQ);
481	}
482}
483
484
485static void
486download_data(struct sbni_softc *sc, u_int32_t *crc_p)
487{
488	struct mbuf *m;
489	caddr_t	data_p;
490	u_int data_len, pos, slice;
491
492	data_p = NULL;		/* initialized to avoid warn */
493	pos = 0;
494
495	for (m = sc->tx_buf_p;  m != NULL && pos < sc->pktlen;  m = m->m_next) {
496		if (pos + m->m_len > sc->outpos) {
497			data_len = m->m_len - (sc->outpos - pos);
498			data_p = mtod(m, caddr_t) + (sc->outpos - pos);
499
500			goto do_copy;
501		} else
502			pos += m->m_len;
503	}
504
505	data_len = 0;
506
507do_copy:
508	pos = 0;
509	do {
510		if (data_len) {
511			slice = min(data_len, sc->framelen - pos);
512			sbni_outsb(sc, data_p, slice);
513			*crc_p = calc_crc32(*crc_p, data_p, slice);
514
515			pos += slice;
516			if (data_len -= slice)
517				data_p += slice;
518			else {
519				do {
520					m = m->m_next;
521				} while (m != NULL && m->m_len == 0);
522
523				if (m) {
524					data_len = m->m_len;
525					data_p = mtod(m, caddr_t);
526				}
527			}
528		} else {
529			/* frame too short - zero padding */
530
531			pos = sc->framelen - pos;
532			while (pos--) {
533				sbni_outb(sc, DAT, 0);
534				*crc_p = CRC32(0, *crc_p);
535			}
536			return;
537		}
538	} while (pos < sc->framelen);
539}
540
541
542static int
543upload_data(struct sbni_softc *sc, u_int framelen, u_int frameno,
544	    u_int is_first, u_int32_t crc)
545{
546	int frame_ok;
547
548	if (is_first) {
549		sc->wait_frameno = frameno;
550		sc->inppos = 0;
551	}
552
553	if (sc->wait_frameno == frameno) {
554
555		if (sc->inppos + framelen  <=  ETHER_MAX_LEN) {
556			frame_ok = append_frame_to_pkt(sc, framelen, crc);
557
558		/*
559		 * if CRC is right but framelen incorrect then transmitter
560		 * error was occured... drop entire packet
561		 */
562		} else if ((frame_ok = skip_tail(sc, framelen, crc)) != 0) {
563			sc->wait_frameno = 0;
564			sc->inppos = 0;
565			sc->arpcom.ac_if.if_ierrors++;
566			/* now skip all frames until is_first != 0 */
567		}
568	} else
569		frame_ok = skip_tail(sc, framelen, crc);
570
571	if (is_first && !frame_ok) {
572		/*
573		 * Frame has been violated, but we have stored
574		 * is_first already... Drop entire packet.
575		 */
576		sc->wait_frameno = 0;
577		sc->arpcom.ac_if.if_ierrors++;
578	}
579
580	return (frame_ok);
581}
582
583
584static __inline void	send_complete(struct sbni_softc *);
585
586static __inline void
587send_complete(struct sbni_softc *sc)
588{
589	m_freem(sc->tx_buf_p);
590	sc->tx_buf_p = NULL;
591	sc->arpcom.ac_if.if_opackets++;
592}
593
594
595static void
596interpret_ack(struct sbni_softc *sc, u_int ack)
597{
598	if (ack == FRAME_SENT_OK) {
599		sc->state &= ~FL_NEED_RESEND;
600
601		if (sc->state & FL_WAIT_ACK) {
602			sc->outpos += sc->framelen;
603
604			if (--sc->tx_frameno) {
605				sc->framelen = min(
606				    sc->maxframe, sc->pktlen - sc->outpos);
607			} else {
608				send_complete(sc);
609				prepare_to_send(sc);
610			}
611		}
612	}
613
614	sc->state &= ~FL_WAIT_ACK;
615}
616
617
618/*
619 * Glue received frame with previous fragments of packet.
620 * Indicate packet when last frame would be accepted.
621 */
622
623static int
624append_frame_to_pkt(struct sbni_softc *sc, u_int framelen, u_int32_t crc)
625{
626	caddr_t p;
627
628	if (sc->inppos + framelen > ETHER_MAX_LEN)
629		return (0);
630
631	if (!sc->rx_buf_p && !get_rx_buf(sc))
632		return (0);
633
634	p = sc->rx_buf_p->m_data + sc->inppos;
635	sbni_insb(sc, p, framelen);
636	if (calc_crc32(crc, p, framelen) != CRC32_REMAINDER)
637		return (0);
638
639	sc->inppos += framelen - 4;
640	if (--sc->wait_frameno == 0) {		/* last frame received */
641		indicate_pkt(sc);
642		sc->arpcom.ac_if.if_ipackets++;
643	}
644
645	return (1);
646}
647
648
649/*
650 * Prepare to start output on adapter. Current priority must be set to splimp
651 * before this routine is called.
652 * Transmitter will be actually activated when marker has been accepted.
653 */
654
655static void
656prepare_to_send(struct sbni_softc *sc)
657{
658	struct mbuf *m;
659	u_int len;
660
661	/* sc->tx_buf_p == NULL here! */
662	if (sc->tx_buf_p)
663		printf("sbni: memory leak!\n");
664
665	sc->outpos = 0;
666	sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
667
668	for (;;) {
669		IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, sc->tx_buf_p);
670		if (!sc->tx_buf_p) {
671			/* nothing to transmit... */
672			sc->pktlen     = 0;
673			sc->tx_frameno = 0;
674			sc->framelen   = 0;
675			sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
676			return;
677		}
678
679		for (len = 0, m = sc->tx_buf_p;  m;  m = m->m_next)
680			len += m->m_len;
681
682		if (len != 0)
683			break;
684		m_freem(sc->tx_buf_p);
685	}
686
687	if (len < SBNI_MIN_LEN)
688		len = SBNI_MIN_LEN;
689
690	sc->pktlen	= len;
691	sc->tx_frameno	= (len + sc->maxframe - 1) / sc->maxframe;
692	sc->framelen	= min(len, sc->maxframe);
693
694	sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | TR_REQ);
695	sc->arpcom.ac_if.if_flags |= IFF_OACTIVE;
696	if (sc->arpcom.ac_if.if_bpf)
697		bpf_mtap(&sc->arpcom.ac_if, sc->tx_buf_p);
698}
699
700
701static void
702drop_xmit_queue(struct sbni_softc *sc)
703{
704	struct mbuf *m;
705
706	if (sc->tx_buf_p) {
707		m_freem(sc->tx_buf_p);
708		sc->tx_buf_p = NULL;
709		sc->arpcom.ac_if.if_oerrors++;
710	}
711
712	for (;;) {
713		IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
714		if (m == NULL)
715			break;
716		m_freem(m);
717		sc->arpcom.ac_if.if_oerrors++;
718	}
719
720	sc->tx_frameno	= 0;
721	sc->framelen	= 0;
722	sc->outpos	= 0;
723	sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
724	sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
725}
726
727
728static void
729send_frame_header(struct sbni_softc *sc, u_int32_t *crc_p)
730{
731	u_int32_t crc;
732	u_int len_field;
733	u_char value;
734
735	crc = *crc_p;
736	len_field = sc->framelen + 6;	/* CRC + frameno + reserved */
737
738	if (sc->state & FL_NEED_RESEND)
739		len_field |= FRAME_RETRY;	/* non-first attempt... */
740
741	if (sc->outpos == 0)
742		len_field |= FRAME_FIRST;
743
744	len_field |= (sc->state & FL_PREV_OK) ? FRAME_SENT_OK : FRAME_SENT_BAD;
745	sbni_outb(sc, DAT, SBNI_SIG);
746
747	value = (u_char)len_field;
748	sbni_outb(sc, DAT, value);
749	crc = CRC32(value, crc);
750	value = (u_char)(len_field >> 8);
751	sbni_outb(sc, DAT, value);
752	crc = CRC32(value, crc);
753
754	sbni_outb(sc, DAT, sc->tx_frameno);
755	crc = CRC32(sc->tx_frameno, crc);
756	sbni_outb(sc, DAT, 0);
757	crc = CRC32(0, crc);
758	*crc_p = crc;
759}
760
761
762/*
763 * if frame tail not needed (incorrect number or received twice),
764 * it won't store, but CRC will be calculated
765 */
766
767static int
768skip_tail(struct sbni_softc *sc, u_int tail_len, u_int32_t crc)
769{
770	while (tail_len--)
771		crc = CRC32(sbni_inb(sc, DAT), crc);
772
773	return (crc == CRC32_REMAINDER);
774}
775
776
777static int
778check_fhdr(struct sbni_softc *sc, u_int *framelen, u_int *frameno,
779	   u_int *ack, u_int *is_first, u_int32_t *crc_p)
780{
781	u_int32_t crc;
782	u_char value;
783
784	crc = *crc_p;
785	if (sbni_inb(sc, DAT) != SBNI_SIG)
786		return (0);
787
788	value = sbni_inb(sc, DAT);
789	*framelen = (u_int)value;
790	crc = CRC32(value, crc);
791	value = sbni_inb(sc, DAT);
792	*framelen |= ((u_int)value) << 8;
793	crc = CRC32(value, crc);
794
795	*ack = *framelen & FRAME_ACK_MASK;
796	*is_first = (*framelen & FRAME_FIRST) != 0;
797
798	if ((*framelen &= FRAME_LEN_MASK) < 6 || *framelen > SBNI_MAX_FRAME - 3)
799		return (0);
800
801	value = sbni_inb(sc, DAT);
802	*frameno = (u_int)value;
803	crc = CRC32(value, crc);
804
805	crc = CRC32(sbni_inb(sc, DAT), crc);		/* reserved byte */
806	*framelen -= 2;
807
808	*crc_p = crc;
809	return (1);
810}
811
812
813static int
814get_rx_buf(struct sbni_softc *sc)
815{
816	struct mbuf *m;
817
818	MGETHDR(m, M_DONTWAIT, MT_DATA);
819	if (m == NULL) {
820		if_printf(&sc->arpcom.ac_if, "cannot allocate header mbuf\n");
821		return (0);
822	}
823
824	/*
825	 * We always put the received packet in a single buffer -
826	 * either with just an mbuf header or in a cluster attached
827	 * to the header. The +2 is to compensate for the alignment
828	 * fixup below.
829	 */
830	if (ETHER_MAX_LEN + 2 > MHLEN) {
831		/* Attach an mbuf cluster */
832		MCLGET(m, M_DONTWAIT);
833		if ((m->m_flags & M_EXT) == 0) {
834			m_freem(m);
835			return (0);
836		}
837	}
838	m->m_pkthdr.len = m->m_len = ETHER_MAX_LEN + 2;
839
840	/*
841	 * The +2 is to longword align the start of the real packet.
842	 * (sizeof ether_header == 14)
843	 * This is important for NFS.
844	 */
845	m_adj(m, 2);
846	sc->rx_buf_p = m;
847	return (1);
848}
849
850
851static void
852indicate_pkt(struct sbni_softc *sc)
853{
854	struct mbuf *m;
855	struct ether_header *eh;
856
857	m = sc->rx_buf_p;
858	m->m_pkthdr.rcvif = &sc->arpcom.ac_if;
859	m->m_pkthdr.len   = m->m_len = sc->inppos;
860	eh = mtod(m, struct ether_header *);
861
862	/* Remove link layer address and indicate packet */
863	m_adj(m, sizeof(struct ether_header));
864	ether_input(&sc->arpcom.ac_if, eh, m);
865	sc->rx_buf_p = NULL;
866}
867
868/* -------------------------------------------------------------------------- */
869
870/*
871 * Routine checks periodically wire activity and regenerates marker if
872 * connect was inactive for a long time.
873 */
874
875static void
876sbni_timeout(void *xsc)
877{
878	struct sbni_softc *sc;
879	int s;
880	u_char csr0;
881
882	sc = (struct sbni_softc *)xsc;
883	s = splimp();
884
885	csr0 = sbni_inb(sc, CSR0);
886	if (csr0 & RC_CHK) {
887
888		if (sc->timer_ticks) {
889			if (csr0 & (RC_RDY | BU_EMP))
890				/* receiving not active */
891				sc->timer_ticks--;
892		} else {
893			sc->in_stats.timeout_number++;
894			if (sc->delta_rxl)
895				timeout_change_level(sc);
896
897			sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
898			csr0 = sbni_inb(sc, CSR0);
899		}
900	}
901
902	sbni_outb(sc, CSR0, csr0 | RC_CHK);
903	sc->wch = timeout(sbni_timeout, sc, hz/SBNI_HZ);
904	splx(s);
905}
906
907/* -------------------------------------------------------------------------- */
908
909static void
910card_start(struct sbni_softc *sc)
911{
912	sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
913	sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
914	sc->state |= FL_PREV_OK;
915
916	sc->inppos = 0;
917	sc->wait_frameno = 0;
918
919	sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
920	sbni_outb(sc, CSR0, EN_INT);
921}
922
923/* -------------------------------------------------------------------------- */
924
925/*
926 * Device timeout/watchdog routine. Entered if the device neglects to
927 *	generate an interrupt after a transmit has been started on it.
928 */
929
930static void
931sbni_watchdog(struct ifnet *ifp)
932{
933	log(LOG_ERR, "sbni%d: device timeout\n", ifp->if_unit);
934	ifp->if_oerrors++;
935}
936
937
938static u_char rxl_tab[] = {
939	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08,
940	0x0a, 0x0c, 0x0f, 0x16, 0x18, 0x1a, 0x1c, 0x1f
941};
942
943#define SIZE_OF_TIMEOUT_RXL_TAB 4
944static u_char timeout_rxl_tab[] = {
945	0x03, 0x05, 0x08, 0x0b
946};
947
948static void
949set_initial_values(struct sbni_softc *sc, struct sbni_flags flags)
950{
951	if (flags.fixed_rxl) {
952		sc->delta_rxl = 0; /* disable receive level autodetection */
953		sc->cur_rxl_index = flags.rxl;
954	} else {
955		sc->delta_rxl = DEF_RXL_DELTA;
956		sc->cur_rxl_index = DEF_RXL;
957	}
958
959	sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
960	sc->csr1.rxl  = rxl_tab[sc->cur_rxl_index];
961	sc->maxframe  = DEFAULT_FRAME_LEN;
962
963	/*
964	 * generate Ethernet address (0x00ff01xxxxxx)
965	 */
966	*(u_int16_t *) sc->arpcom.ac_enaddr = htons(0x00ff);
967	if (flags.mac_addr) {
968		*(u_int32_t *) (sc->arpcom.ac_enaddr + 2) =
969		    htonl(flags.mac_addr | 0x01000000);
970	} else {
971		*(u_char *) (sc->arpcom.ac_enaddr + 2) = 0x01;
972		read_random(sc->arpcom.ac_enaddr + 3, 3);
973	}
974}
975
976
977#ifdef SBNI_DUAL_COMPOUND
978
979struct sbni_softc *
980connect_to_master(struct sbni_softc *sc)
981{
982	struct sbni_softc *p, *p_prev;
983
984	for (p = sbni_headlist, p_prev = NULL; p; p_prev = p, p = p->link) {
985		if (rman_get_start(p->io_res) == rman_get_start(sc->io_res) + 4 ||
986		    rman_get_start(p->io_res) == rman_get_start(sc->io_res) - 4) {
987			p->slave_sc = sc;
988			if (p_prev)
989				p_prev->link = p->link;
990			else
991				sbni_headlist = p->link;
992			return p;
993		}
994	}
995
996	return (NULL);
997}
998
999#endif	/* SBNI_DUAL_COMPOUND */
1000
1001
1002/* Receive level auto-selection */
1003
1004static void
1005change_level(struct sbni_softc *sc)
1006{
1007	if (sc->delta_rxl == 0)		/* do not auto-negotiate RxL */
1008		return;
1009
1010	if (sc->cur_rxl_index == 0)
1011		sc->delta_rxl = 1;
1012	else if (sc->cur_rxl_index == 15)
1013		sc->delta_rxl = -1;
1014	else if (sc->cur_rxl_rcvd < sc->prev_rxl_rcvd)
1015		sc->delta_rxl = -sc->delta_rxl;
1016
1017	sc->csr1.rxl = rxl_tab[sc->cur_rxl_index += sc->delta_rxl];
1018	sbni_inb(sc, CSR0);	/* it needed for PCI cards */
1019	sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1020
1021	sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1022	sc->cur_rxl_rcvd  = 0;
1023}
1024
1025
1026static void
1027timeout_change_level(struct sbni_softc *sc)
1028{
1029	sc->cur_rxl_index = timeout_rxl_tab[sc->timeout_rxl];
1030	if (++sc->timeout_rxl >= 4)
1031		sc->timeout_rxl = 0;
1032
1033	sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1034	sbni_inb(sc, CSR0);
1035	sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1036
1037	sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1038	sc->cur_rxl_rcvd  = 0;
1039}
1040
1041/* -------------------------------------------------------------------------- */
1042
1043/*
1044 * Process an ioctl request. This code needs some work - it looks
1045 *	pretty ugly.
1046 */
1047
1048static int
1049sbni_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1050{
1051	struct sbni_softc *sc;
1052	struct ifreq *ifr;
1053	struct thread *td;
1054	struct sbni_in_stats *in_stats;
1055	struct sbni_flags flags;
1056	int error, s;
1057
1058	sc = ifp->if_softc;
1059	ifr = (struct ifreq *)data;
1060	td = curthread;
1061	error = 0;
1062
1063	s = splimp();
1064
1065	switch (command) {
1066	case SIOCSIFADDR:
1067	case SIOCGIFADDR:
1068		ether_ioctl(ifp, command, data);
1069		break;
1070
1071	case SIOCSIFFLAGS:
1072		/*
1073		 * If the interface is marked up and stopped, then start it.
1074		 * If it is marked down and running, then stop it.
1075		 */
1076		if (ifp->if_flags & IFF_UP) {
1077			if (!(ifp->if_flags & IFF_RUNNING))
1078				sbni_init(sc);
1079		} else {
1080			if (ifp->if_flags & IFF_RUNNING) {
1081				sbni_stop(sc);
1082				ifp->if_flags &= ~IFF_RUNNING;
1083			}
1084		}
1085		break;
1086
1087	case SIOCADDMULTI:
1088	case SIOCDELMULTI:
1089		/*
1090		 * Multicast list has changed; set the hardware filter
1091		 * accordingly.
1092		 */
1093		error = 0;
1094		/* if (ifr == NULL)
1095			error = EAFNOSUPPORT; */
1096		break;
1097
1098	case SIOCSIFMTU:
1099		if (ifr->ifr_mtu > ETHERMTU)
1100			error = EINVAL;
1101		else
1102			ifp->if_mtu = ifr->ifr_mtu;
1103		break;
1104
1105		/*
1106		 * SBNI specific ioctl
1107		 */
1108	case SIOCGHWFLAGS:	/* get flags */
1109		bcopy((caddr_t) sc->arpcom.ac_enaddr+3, (caddr_t) &flags, 3);
1110		flags.rxl = sc->cur_rxl_index;
1111		flags.rate = sc->csr1.rate;
1112		flags.fixed_rxl = (sc->delta_rxl == 0);
1113		flags.fixed_rate = 1;
1114		ifr->ifr_data = *(caddr_t*) &flags;
1115		break;
1116
1117	case SIOCGINSTATS:
1118		in_stats = (struct sbni_in_stats *)ifr->ifr_data;
1119		bcopy((void *)(&(sc->in_stats)), (void *)in_stats,
1120		      sizeof(struct sbni_in_stats));
1121		break;
1122
1123	case SIOCSHWFLAGS:	/* set flags */
1124		/* root only */
1125		error = suser(td);
1126		if (error)
1127			break;
1128		flags = *(struct sbni_flags*)&ifr->ifr_data;
1129		if (flags.fixed_rxl) {
1130			sc->delta_rxl = 0;
1131			sc->cur_rxl_index = flags.rxl;
1132		} else {
1133			sc->delta_rxl = DEF_RXL_DELTA;
1134			sc->cur_rxl_index = DEF_RXL;
1135		}
1136		sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1137		sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
1138		if (flags.mac_addr)
1139			bcopy((caddr_t) &flags,
1140			      (caddr_t) sc->arpcom.ac_enaddr+3, 3);
1141
1142		/* Don't be afraid... */
1143		sbni_outb(sc, CSR1, *(char*)(&sc->csr1) | PR_RES);
1144		break;
1145
1146	case SIOCRINSTATS:
1147		if (!(error = suser(td)))	/* root only */
1148			bzero(&sc->in_stats, sizeof(struct sbni_in_stats));
1149		break;
1150
1151	default:
1152		error = EINVAL;
1153	}
1154
1155	splx(s);
1156	return (error);
1157}
1158
1159/* -------------------------------------------------------------------------- */
1160
1161#ifdef ASM_CRC
1162
1163static u_int32_t
1164calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1165{
1166	register u_int32_t  _crc __asm ("ax");
1167	_crc = crc;
1168
1169	__asm __volatile (
1170		"xorl	%%ebx, %%ebx\n"
1171		"movl	%1, %%esi\n"
1172		"movl	%2, %%ecx\n"
1173		"movl	$crc32tab, %%edi\n"
1174		"shrl	$2, %%ecx\n"
1175		"jz	1f\n"
1176
1177		".align 4\n"
1178	"0:\n"
1179		"movb	%%al, %%bl\n"
1180		"movl	(%%esi), %%edx\n"
1181		"shrl	$8, %%eax\n"
1182		"xorb	%%dl, %%bl\n"
1183		"shrl	$8, %%edx\n"
1184		"xorl	(%%edi,%%ebx,4), %%eax\n"
1185
1186		"movb	%%al, %%bl\n"
1187		"shrl	$8, %%eax\n"
1188		"xorb	%%dl, %%bl\n"
1189		"shrl	$8, %%edx\n"
1190		"xorl	(%%edi,%%ebx,4), %%eax\n"
1191
1192		"movb	%%al, %%bl\n"
1193		"shrl	$8, %%eax\n"
1194		"xorb	%%dl, %%bl\n"
1195		"movb	%%dh, %%dl\n"
1196		"xorl	(%%edi,%%ebx,4), %%eax\n"
1197
1198		"movb	%%al, %%bl\n"
1199		"shrl	$8, %%eax\n"
1200		"xorb	%%dl, %%bl\n"
1201		"addl	$4, %%esi\n"
1202		"xorl	(%%edi,%%ebx,4), %%eax\n"
1203
1204		"decl	%%ecx\n"
1205		"jnz	0b\n"
1206
1207	"1:\n"
1208		"movl	%2, %%ecx\n"
1209		"andl	$3, %%ecx\n"
1210		"jz	2f\n"
1211
1212		"movb	%%al, %%bl\n"
1213		"shrl	$8, %%eax\n"
1214		"xorb	(%%esi), %%bl\n"
1215		"xorl	(%%edi,%%ebx,4), %%eax\n"
1216
1217		"decl	%%ecx\n"
1218		"jz	2f\n"
1219
1220		"movb	%%al, %%bl\n"
1221		"shrl	$8, %%eax\n"
1222		"xorb	1(%%esi), %%bl\n"
1223		"xorl	(%%edi,%%ebx,4), %%eax\n"
1224
1225		"decl	%%ecx\n"
1226		"jz	2f\n"
1227
1228		"movb	%%al, %%bl\n"
1229		"shrl	$8, %%eax\n"
1230		"xorb	2(%%esi), %%bl\n"
1231		"xorl	(%%edi,%%ebx,4), %%eax\n"
1232	"2:\n"
1233		:
1234		: "a" (_crc), "g" (p), "g" (len)
1235		: "ax", "bx", "cx", "dx", "si", "di"
1236	);
1237
1238	return (_crc);
1239}
1240
1241#else	/* ASM_CRC */
1242
1243static u_int32_t
1244calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1245{
1246	while (len--)
1247		crc = CRC32(*p++, crc);
1248
1249	return (crc);
1250}
1251
1252#endif	/* ASM_CRC */
1253
1254
1255static u_int32_t crc32tab[] __aligned(8) = {
1256	0xD202EF8D,  0xA505DF1B,  0x3C0C8EA1,  0x4B0BBE37,
1257	0xD56F2B94,  0xA2681B02,  0x3B614AB8,  0x4C667A2E,
1258	0xDCD967BF,  0xABDE5729,  0x32D70693,  0x45D03605,
1259	0xDBB4A3A6,  0xACB39330,  0x35BAC28A,  0x42BDF21C,
1260	0xCFB5FFE9,  0xB8B2CF7F,  0x21BB9EC5,  0x56BCAE53,
1261	0xC8D83BF0,  0xBFDF0B66,  0x26D65ADC,  0x51D16A4A,
1262	0xC16E77DB,  0xB669474D,  0x2F6016F7,  0x58672661,
1263	0xC603B3C2,  0xB1048354,  0x280DD2EE,  0x5F0AE278,
1264	0xE96CCF45,  0x9E6BFFD3,  0x0762AE69,  0x70659EFF,
1265	0xEE010B5C,  0x99063BCA,  0x000F6A70,  0x77085AE6,
1266	0xE7B74777,  0x90B077E1,  0x09B9265B,  0x7EBE16CD,
1267	0xE0DA836E,  0x97DDB3F8,  0x0ED4E242,  0x79D3D2D4,
1268	0xF4DBDF21,  0x83DCEFB7,  0x1AD5BE0D,  0x6DD28E9B,
1269	0xF3B61B38,  0x84B12BAE,  0x1DB87A14,  0x6ABF4A82,
1270	0xFA005713,  0x8D076785,  0x140E363F,  0x630906A9,
1271	0xFD6D930A,  0x8A6AA39C,  0x1363F226,  0x6464C2B0,
1272	0xA4DEAE1D,  0xD3D99E8B,  0x4AD0CF31,  0x3DD7FFA7,
1273	0xA3B36A04,  0xD4B45A92,  0x4DBD0B28,  0x3ABA3BBE,
1274	0xAA05262F,  0xDD0216B9,  0x440B4703,  0x330C7795,
1275	0xAD68E236,  0xDA6FD2A0,  0x4366831A,  0x3461B38C,
1276	0xB969BE79,  0xCE6E8EEF,  0x5767DF55,  0x2060EFC3,
1277	0xBE047A60,  0xC9034AF6,  0x500A1B4C,  0x270D2BDA,
1278	0xB7B2364B,  0xC0B506DD,  0x59BC5767,  0x2EBB67F1,
1279	0xB0DFF252,  0xC7D8C2C4,  0x5ED1937E,  0x29D6A3E8,
1280	0x9FB08ED5,  0xE8B7BE43,  0x71BEEFF9,  0x06B9DF6F,
1281	0x98DD4ACC,  0xEFDA7A5A,  0x76D32BE0,  0x01D41B76,
1282	0x916B06E7,  0xE66C3671,  0x7F6567CB,  0x0862575D,
1283	0x9606C2FE,  0xE101F268,  0x7808A3D2,  0x0F0F9344,
1284	0x82079EB1,  0xF500AE27,  0x6C09FF9D,  0x1B0ECF0B,
1285	0x856A5AA8,  0xF26D6A3E,  0x6B643B84,  0x1C630B12,
1286	0x8CDC1683,  0xFBDB2615,  0x62D277AF,  0x15D54739,
1287	0x8BB1D29A,  0xFCB6E20C,  0x65BFB3B6,  0x12B88320,
1288	0x3FBA6CAD,  0x48BD5C3B,  0xD1B40D81,  0xA6B33D17,
1289	0x38D7A8B4,  0x4FD09822,  0xD6D9C998,  0xA1DEF90E,
1290	0x3161E49F,  0x4666D409,  0xDF6F85B3,  0xA868B525,
1291	0x360C2086,  0x410B1010,  0xD80241AA,  0xAF05713C,
1292	0x220D7CC9,  0x550A4C5F,  0xCC031DE5,  0xBB042D73,
1293	0x2560B8D0,  0x52678846,  0xCB6ED9FC,  0xBC69E96A,
1294	0x2CD6F4FB,  0x5BD1C46D,  0xC2D895D7,  0xB5DFA541,
1295	0x2BBB30E2,  0x5CBC0074,  0xC5B551CE,  0xB2B26158,
1296	0x04D44C65,  0x73D37CF3,  0xEADA2D49,  0x9DDD1DDF,
1297	0x03B9887C,  0x74BEB8EA,  0xEDB7E950,  0x9AB0D9C6,
1298	0x0A0FC457,  0x7D08F4C1,  0xE401A57B,  0x930695ED,
1299	0x0D62004E,  0x7A6530D8,  0xE36C6162,  0x946B51F4,
1300	0x19635C01,  0x6E646C97,  0xF76D3D2D,  0x806A0DBB,
1301	0x1E0E9818,  0x6909A88E,  0xF000F934,  0x8707C9A2,
1302	0x17B8D433,  0x60BFE4A5,  0xF9B6B51F,  0x8EB18589,
1303	0x10D5102A,  0x67D220BC,  0xFEDB7106,  0x89DC4190,
1304	0x49662D3D,  0x3E611DAB,  0xA7684C11,  0xD06F7C87,
1305	0x4E0BE924,  0x390CD9B2,  0xA0058808,  0xD702B89E,
1306	0x47BDA50F,  0x30BA9599,  0xA9B3C423,  0xDEB4F4B5,
1307	0x40D06116,  0x37D75180,  0xAEDE003A,  0xD9D930AC,
1308	0x54D13D59,  0x23D60DCF,  0xBADF5C75,  0xCDD86CE3,
1309	0x53BCF940,  0x24BBC9D6,  0xBDB2986C,  0xCAB5A8FA,
1310	0x5A0AB56B,  0x2D0D85FD,  0xB404D447,  0xC303E4D1,
1311	0x5D677172,  0x2A6041E4,  0xB369105E,  0xC46E20C8,
1312	0x72080DF5,  0x050F3D63,  0x9C066CD9,  0xEB015C4F,
1313	0x7565C9EC,  0x0262F97A,  0x9B6BA8C0,  0xEC6C9856,
1314	0x7CD385C7,  0x0BD4B551,  0x92DDE4EB,  0xE5DAD47D,
1315	0x7BBE41DE,  0x0CB97148,  0x95B020F2,  0xE2B71064,
1316	0x6FBF1D91,  0x18B82D07,  0x81B17CBD,  0xF6B64C2B,
1317	0x68D2D988,  0x1FD5E91E,  0x86DCB8A4,  0xF1DB8832,
1318	0x616495A3,  0x1663A535,  0x8F6AF48F,  0xF86DC419,
1319	0x660951BA,  0x110E612C,  0x88073096,  0xFF000000
1320};
1321