if_sbni.c revision 111119
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 111119 2003-02-19 05:47:46Z imp $
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, sc->arpcom.ac_enaddr);
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	BPF_MTAP(&sc->arpcom.ac_if, sc->tx_buf_p);
697}
698
699
700static void
701drop_xmit_queue(struct sbni_softc *sc)
702{
703	struct mbuf *m;
704
705	if (sc->tx_buf_p) {
706		m_freem(sc->tx_buf_p);
707		sc->tx_buf_p = NULL;
708		sc->arpcom.ac_if.if_oerrors++;
709	}
710
711	for (;;) {
712		IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
713		if (m == NULL)
714			break;
715		m_freem(m);
716		sc->arpcom.ac_if.if_oerrors++;
717	}
718
719	sc->tx_frameno	= 0;
720	sc->framelen	= 0;
721	sc->outpos	= 0;
722	sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
723	sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
724}
725
726
727static void
728send_frame_header(struct sbni_softc *sc, u_int32_t *crc_p)
729{
730	u_int32_t crc;
731	u_int len_field;
732	u_char value;
733
734	crc = *crc_p;
735	len_field = sc->framelen + 6;	/* CRC + frameno + reserved */
736
737	if (sc->state & FL_NEED_RESEND)
738		len_field |= FRAME_RETRY;	/* non-first attempt... */
739
740	if (sc->outpos == 0)
741		len_field |= FRAME_FIRST;
742
743	len_field |= (sc->state & FL_PREV_OK) ? FRAME_SENT_OK : FRAME_SENT_BAD;
744	sbni_outb(sc, DAT, SBNI_SIG);
745
746	value = (u_char)len_field;
747	sbni_outb(sc, DAT, value);
748	crc = CRC32(value, crc);
749	value = (u_char)(len_field >> 8);
750	sbni_outb(sc, DAT, value);
751	crc = CRC32(value, crc);
752
753	sbni_outb(sc, DAT, sc->tx_frameno);
754	crc = CRC32(sc->tx_frameno, crc);
755	sbni_outb(sc, DAT, 0);
756	crc = CRC32(0, crc);
757	*crc_p = crc;
758}
759
760
761/*
762 * if frame tail not needed (incorrect number or received twice),
763 * it won't store, but CRC will be calculated
764 */
765
766static int
767skip_tail(struct sbni_softc *sc, u_int tail_len, u_int32_t crc)
768{
769	while (tail_len--)
770		crc = CRC32(sbni_inb(sc, DAT), crc);
771
772	return (crc == CRC32_REMAINDER);
773}
774
775
776static int
777check_fhdr(struct sbni_softc *sc, u_int *framelen, u_int *frameno,
778	   u_int *ack, u_int *is_first, u_int32_t *crc_p)
779{
780	u_int32_t crc;
781	u_char value;
782
783	crc = *crc_p;
784	if (sbni_inb(sc, DAT) != SBNI_SIG)
785		return (0);
786
787	value = sbni_inb(sc, DAT);
788	*framelen = (u_int)value;
789	crc = CRC32(value, crc);
790	value = sbni_inb(sc, DAT);
791	*framelen |= ((u_int)value) << 8;
792	crc = CRC32(value, crc);
793
794	*ack = *framelen & FRAME_ACK_MASK;
795	*is_first = (*framelen & FRAME_FIRST) != 0;
796
797	if ((*framelen &= FRAME_LEN_MASK) < 6 || *framelen > SBNI_MAX_FRAME - 3)
798		return (0);
799
800	value = sbni_inb(sc, DAT);
801	*frameno = (u_int)value;
802	crc = CRC32(value, crc);
803
804	crc = CRC32(sbni_inb(sc, DAT), crc);		/* reserved byte */
805	*framelen -= 2;
806
807	*crc_p = crc;
808	return (1);
809}
810
811
812static int
813get_rx_buf(struct sbni_softc *sc)
814{
815	struct mbuf *m;
816
817	MGETHDR(m, M_DONTWAIT, MT_DATA);
818	if (m == NULL) {
819		if_printf(&sc->arpcom.ac_if, "cannot allocate header mbuf\n");
820		return (0);
821	}
822
823	/*
824	 * We always put the received packet in a single buffer -
825	 * either with just an mbuf header or in a cluster attached
826	 * to the header. The +2 is to compensate for the alignment
827	 * fixup below.
828	 */
829	if (ETHER_MAX_LEN + 2 > MHLEN) {
830		/* Attach an mbuf cluster */
831		MCLGET(m, M_DONTWAIT);
832		if ((m->m_flags & M_EXT) == 0) {
833			m_freem(m);
834			return (0);
835		}
836	}
837	m->m_pkthdr.len = m->m_len = ETHER_MAX_LEN + 2;
838
839	/*
840	 * The +2 is to longword align the start of the real packet.
841	 * (sizeof ether_header == 14)
842	 * This is important for NFS.
843	 */
844	m_adj(m, 2);
845	sc->rx_buf_p = m;
846	return (1);
847}
848
849
850static void
851indicate_pkt(struct sbni_softc *sc)
852{
853	struct ifnet *ifp = &sc->arpcom.ac_if;
854	struct mbuf *m;
855
856	m = sc->rx_buf_p;
857	m->m_pkthdr.rcvif = ifp;
858	m->m_pkthdr.len   = m->m_len = sc->inppos;
859
860	(*ifp->if_input)(ifp, m);
861	sc->rx_buf_p = NULL;
862}
863
864/* -------------------------------------------------------------------------- */
865
866/*
867 * Routine checks periodically wire activity and regenerates marker if
868 * connect was inactive for a long time.
869 */
870
871static void
872sbni_timeout(void *xsc)
873{
874	struct sbni_softc *sc;
875	int s;
876	u_char csr0;
877
878	sc = (struct sbni_softc *)xsc;
879	s = splimp();
880
881	csr0 = sbni_inb(sc, CSR0);
882	if (csr0 & RC_CHK) {
883
884		if (sc->timer_ticks) {
885			if (csr0 & (RC_RDY | BU_EMP))
886				/* receiving not active */
887				sc->timer_ticks--;
888		} else {
889			sc->in_stats.timeout_number++;
890			if (sc->delta_rxl)
891				timeout_change_level(sc);
892
893			sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
894			csr0 = sbni_inb(sc, CSR0);
895		}
896	}
897
898	sbni_outb(sc, CSR0, csr0 | RC_CHK);
899	sc->wch = timeout(sbni_timeout, sc, hz/SBNI_HZ);
900	splx(s);
901}
902
903/* -------------------------------------------------------------------------- */
904
905static void
906card_start(struct sbni_softc *sc)
907{
908	sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
909	sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
910	sc->state |= FL_PREV_OK;
911
912	sc->inppos = 0;
913	sc->wait_frameno = 0;
914
915	sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
916	sbni_outb(sc, CSR0, EN_INT);
917}
918
919/* -------------------------------------------------------------------------- */
920
921/*
922 * Device timeout/watchdog routine. Entered if the device neglects to
923 *	generate an interrupt after a transmit has been started on it.
924 */
925
926static void
927sbni_watchdog(struct ifnet *ifp)
928{
929	log(LOG_ERR, "sbni%d: device timeout\n", ifp->if_unit);
930	ifp->if_oerrors++;
931}
932
933
934static u_char rxl_tab[] = {
935	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08,
936	0x0a, 0x0c, 0x0f, 0x16, 0x18, 0x1a, 0x1c, 0x1f
937};
938
939#define SIZE_OF_TIMEOUT_RXL_TAB 4
940static u_char timeout_rxl_tab[] = {
941	0x03, 0x05, 0x08, 0x0b
942};
943
944static void
945set_initial_values(struct sbni_softc *sc, struct sbni_flags flags)
946{
947	if (flags.fixed_rxl) {
948		sc->delta_rxl = 0; /* disable receive level autodetection */
949		sc->cur_rxl_index = flags.rxl;
950	} else {
951		sc->delta_rxl = DEF_RXL_DELTA;
952		sc->cur_rxl_index = DEF_RXL;
953	}
954
955	sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
956	sc->csr1.rxl  = rxl_tab[sc->cur_rxl_index];
957	sc->maxframe  = DEFAULT_FRAME_LEN;
958
959	/*
960	 * generate Ethernet address (0x00ff01xxxxxx)
961	 */
962	*(u_int16_t *) sc->arpcom.ac_enaddr = htons(0x00ff);
963	if (flags.mac_addr) {
964		*(u_int32_t *) (sc->arpcom.ac_enaddr + 2) =
965		    htonl(flags.mac_addr | 0x01000000);
966	} else {
967		*(u_char *) (sc->arpcom.ac_enaddr + 2) = 0x01;
968		read_random(sc->arpcom.ac_enaddr + 3, 3);
969	}
970}
971
972
973#ifdef SBNI_DUAL_COMPOUND
974
975struct sbni_softc *
976connect_to_master(struct sbni_softc *sc)
977{
978	struct sbni_softc *p, *p_prev;
979
980	for (p = sbni_headlist, p_prev = NULL; p; p_prev = p, p = p->link) {
981		if (rman_get_start(p->io_res) == rman_get_start(sc->io_res) + 4 ||
982		    rman_get_start(p->io_res) == rman_get_start(sc->io_res) - 4) {
983			p->slave_sc = sc;
984			if (p_prev)
985				p_prev->link = p->link;
986			else
987				sbni_headlist = p->link;
988			return p;
989		}
990	}
991
992	return (NULL);
993}
994
995#endif	/* SBNI_DUAL_COMPOUND */
996
997
998/* Receive level auto-selection */
999
1000static void
1001change_level(struct sbni_softc *sc)
1002{
1003	if (sc->delta_rxl == 0)		/* do not auto-negotiate RxL */
1004		return;
1005
1006	if (sc->cur_rxl_index == 0)
1007		sc->delta_rxl = 1;
1008	else if (sc->cur_rxl_index == 15)
1009		sc->delta_rxl = -1;
1010	else if (sc->cur_rxl_rcvd < sc->prev_rxl_rcvd)
1011		sc->delta_rxl = -sc->delta_rxl;
1012
1013	sc->csr1.rxl = rxl_tab[sc->cur_rxl_index += sc->delta_rxl];
1014	sbni_inb(sc, CSR0);	/* it needed for PCI cards */
1015	sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1016
1017	sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1018	sc->cur_rxl_rcvd  = 0;
1019}
1020
1021
1022static void
1023timeout_change_level(struct sbni_softc *sc)
1024{
1025	sc->cur_rxl_index = timeout_rxl_tab[sc->timeout_rxl];
1026	if (++sc->timeout_rxl >= 4)
1027		sc->timeout_rxl = 0;
1028
1029	sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1030	sbni_inb(sc, CSR0);
1031	sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1032
1033	sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1034	sc->cur_rxl_rcvd  = 0;
1035}
1036
1037/* -------------------------------------------------------------------------- */
1038
1039/*
1040 * Process an ioctl request. This code needs some work - it looks
1041 *	pretty ugly.
1042 */
1043
1044static int
1045sbni_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1046{
1047	struct sbni_softc *sc;
1048	struct ifreq *ifr;
1049	struct thread *td;
1050	struct sbni_in_stats *in_stats;
1051	struct sbni_flags flags;
1052	int error, s;
1053
1054	sc = ifp->if_softc;
1055	ifr = (struct ifreq *)data;
1056	td = curthread;
1057	error = 0;
1058
1059	s = splimp();
1060
1061	switch (command) {
1062	case SIOCSIFFLAGS:
1063		/*
1064		 * If the interface is marked up and stopped, then start it.
1065		 * If it is marked down and running, then stop it.
1066		 */
1067		if (ifp->if_flags & IFF_UP) {
1068			if (!(ifp->if_flags & IFF_RUNNING))
1069				sbni_init(sc);
1070		} else {
1071			if (ifp->if_flags & IFF_RUNNING) {
1072				sbni_stop(sc);
1073				ifp->if_flags &= ~IFF_RUNNING;
1074			}
1075		}
1076		break;
1077
1078	case SIOCADDMULTI:
1079	case SIOCDELMULTI:
1080		/*
1081		 * Multicast list has changed; set the hardware filter
1082		 * accordingly.
1083		 */
1084		error = 0;
1085		/* if (ifr == NULL)
1086			error = EAFNOSUPPORT; */
1087		break;
1088
1089	case SIOCSIFMTU:
1090		if (ifr->ifr_mtu > ETHERMTU)
1091			error = EINVAL;
1092		else
1093			ifp->if_mtu = ifr->ifr_mtu;
1094		break;
1095
1096		/*
1097		 * SBNI specific ioctl
1098		 */
1099	case SIOCGHWFLAGS:	/* get flags */
1100		bcopy((caddr_t) sc->arpcom.ac_enaddr+3, (caddr_t) &flags, 3);
1101		flags.rxl = sc->cur_rxl_index;
1102		flags.rate = sc->csr1.rate;
1103		flags.fixed_rxl = (sc->delta_rxl == 0);
1104		flags.fixed_rate = 1;
1105		ifr->ifr_data = *(caddr_t*) &flags;
1106		break;
1107
1108	case SIOCGINSTATS:
1109		in_stats = (struct sbni_in_stats *)ifr->ifr_data;
1110		bcopy((void *)(&(sc->in_stats)), (void *)in_stats,
1111		      sizeof(struct sbni_in_stats));
1112		break;
1113
1114	case SIOCSHWFLAGS:	/* set flags */
1115		/* root only */
1116		error = suser(td);
1117		if (error)
1118			break;
1119		flags = *(struct sbni_flags*)&ifr->ifr_data;
1120		if (flags.fixed_rxl) {
1121			sc->delta_rxl = 0;
1122			sc->cur_rxl_index = flags.rxl;
1123		} else {
1124			sc->delta_rxl = DEF_RXL_DELTA;
1125			sc->cur_rxl_index = DEF_RXL;
1126		}
1127		sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1128		sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
1129		if (flags.mac_addr)
1130			bcopy((caddr_t) &flags,
1131			      (caddr_t) sc->arpcom.ac_enaddr+3, 3);
1132
1133		/* Don't be afraid... */
1134		sbni_outb(sc, CSR1, *(char*)(&sc->csr1) | PR_RES);
1135		break;
1136
1137	case SIOCRINSTATS:
1138		if (!(error = suser(td)))	/* root only */
1139			bzero(&sc->in_stats, sizeof(struct sbni_in_stats));
1140		break;
1141
1142	default:
1143		error = ether_ioctl(ifp, command, data);
1144		break;
1145	}
1146
1147	splx(s);
1148	return (error);
1149}
1150
1151/* -------------------------------------------------------------------------- */
1152
1153#ifdef ASM_CRC
1154
1155static u_int32_t
1156calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1157{
1158	register u_int32_t  _crc __asm ("ax");
1159	_crc = crc;
1160
1161	__asm __volatile (
1162		"xorl	%%ebx, %%ebx\n"
1163		"movl	%1, %%esi\n"
1164		"movl	%2, %%ecx\n"
1165		"movl	$crc32tab, %%edi\n"
1166		"shrl	$2, %%ecx\n"
1167		"jz	1f\n"
1168
1169		".align 4\n"
1170	"0:\n"
1171		"movb	%%al, %%bl\n"
1172		"movl	(%%esi), %%edx\n"
1173		"shrl	$8, %%eax\n"
1174		"xorb	%%dl, %%bl\n"
1175		"shrl	$8, %%edx\n"
1176		"xorl	(%%edi,%%ebx,4), %%eax\n"
1177
1178		"movb	%%al, %%bl\n"
1179		"shrl	$8, %%eax\n"
1180		"xorb	%%dl, %%bl\n"
1181		"shrl	$8, %%edx\n"
1182		"xorl	(%%edi,%%ebx,4), %%eax\n"
1183
1184		"movb	%%al, %%bl\n"
1185		"shrl	$8, %%eax\n"
1186		"xorb	%%dl, %%bl\n"
1187		"movb	%%dh, %%dl\n"
1188		"xorl	(%%edi,%%ebx,4), %%eax\n"
1189
1190		"movb	%%al, %%bl\n"
1191		"shrl	$8, %%eax\n"
1192		"xorb	%%dl, %%bl\n"
1193		"addl	$4, %%esi\n"
1194		"xorl	(%%edi,%%ebx,4), %%eax\n"
1195
1196		"decl	%%ecx\n"
1197		"jnz	0b\n"
1198
1199	"1:\n"
1200		"movl	%2, %%ecx\n"
1201		"andl	$3, %%ecx\n"
1202		"jz	2f\n"
1203
1204		"movb	%%al, %%bl\n"
1205		"shrl	$8, %%eax\n"
1206		"xorb	(%%esi), %%bl\n"
1207		"xorl	(%%edi,%%ebx,4), %%eax\n"
1208
1209		"decl	%%ecx\n"
1210		"jz	2f\n"
1211
1212		"movb	%%al, %%bl\n"
1213		"shrl	$8, %%eax\n"
1214		"xorb	1(%%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	2(%%esi), %%bl\n"
1223		"xorl	(%%edi,%%ebx,4), %%eax\n"
1224	"2:\n"
1225		:
1226		: "a" (_crc), "g" (p), "g" (len)
1227		: "ax", "bx", "cx", "dx", "si", "di"
1228	);
1229
1230	return (_crc);
1231}
1232
1233#else	/* ASM_CRC */
1234
1235static u_int32_t
1236calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1237{
1238	while (len--)
1239		crc = CRC32(*p++, crc);
1240
1241	return (crc);
1242}
1243
1244#endif	/* ASM_CRC */
1245
1246
1247static u_int32_t crc32tab[] __aligned(8) = {
1248	0xD202EF8D,  0xA505DF1B,  0x3C0C8EA1,  0x4B0BBE37,
1249	0xD56F2B94,  0xA2681B02,  0x3B614AB8,  0x4C667A2E,
1250	0xDCD967BF,  0xABDE5729,  0x32D70693,  0x45D03605,
1251	0xDBB4A3A6,  0xACB39330,  0x35BAC28A,  0x42BDF21C,
1252	0xCFB5FFE9,  0xB8B2CF7F,  0x21BB9EC5,  0x56BCAE53,
1253	0xC8D83BF0,  0xBFDF0B66,  0x26D65ADC,  0x51D16A4A,
1254	0xC16E77DB,  0xB669474D,  0x2F6016F7,  0x58672661,
1255	0xC603B3C2,  0xB1048354,  0x280DD2EE,  0x5F0AE278,
1256	0xE96CCF45,  0x9E6BFFD3,  0x0762AE69,  0x70659EFF,
1257	0xEE010B5C,  0x99063BCA,  0x000F6A70,  0x77085AE6,
1258	0xE7B74777,  0x90B077E1,  0x09B9265B,  0x7EBE16CD,
1259	0xE0DA836E,  0x97DDB3F8,  0x0ED4E242,  0x79D3D2D4,
1260	0xF4DBDF21,  0x83DCEFB7,  0x1AD5BE0D,  0x6DD28E9B,
1261	0xF3B61B38,  0x84B12BAE,  0x1DB87A14,  0x6ABF4A82,
1262	0xFA005713,  0x8D076785,  0x140E363F,  0x630906A9,
1263	0xFD6D930A,  0x8A6AA39C,  0x1363F226,  0x6464C2B0,
1264	0xA4DEAE1D,  0xD3D99E8B,  0x4AD0CF31,  0x3DD7FFA7,
1265	0xA3B36A04,  0xD4B45A92,  0x4DBD0B28,  0x3ABA3BBE,
1266	0xAA05262F,  0xDD0216B9,  0x440B4703,  0x330C7795,
1267	0xAD68E236,  0xDA6FD2A0,  0x4366831A,  0x3461B38C,
1268	0xB969BE79,  0xCE6E8EEF,  0x5767DF55,  0x2060EFC3,
1269	0xBE047A60,  0xC9034AF6,  0x500A1B4C,  0x270D2BDA,
1270	0xB7B2364B,  0xC0B506DD,  0x59BC5767,  0x2EBB67F1,
1271	0xB0DFF252,  0xC7D8C2C4,  0x5ED1937E,  0x29D6A3E8,
1272	0x9FB08ED5,  0xE8B7BE43,  0x71BEEFF9,  0x06B9DF6F,
1273	0x98DD4ACC,  0xEFDA7A5A,  0x76D32BE0,  0x01D41B76,
1274	0x916B06E7,  0xE66C3671,  0x7F6567CB,  0x0862575D,
1275	0x9606C2FE,  0xE101F268,  0x7808A3D2,  0x0F0F9344,
1276	0x82079EB1,  0xF500AE27,  0x6C09FF9D,  0x1B0ECF0B,
1277	0x856A5AA8,  0xF26D6A3E,  0x6B643B84,  0x1C630B12,
1278	0x8CDC1683,  0xFBDB2615,  0x62D277AF,  0x15D54739,
1279	0x8BB1D29A,  0xFCB6E20C,  0x65BFB3B6,  0x12B88320,
1280	0x3FBA6CAD,  0x48BD5C3B,  0xD1B40D81,  0xA6B33D17,
1281	0x38D7A8B4,  0x4FD09822,  0xD6D9C998,  0xA1DEF90E,
1282	0x3161E49F,  0x4666D409,  0xDF6F85B3,  0xA868B525,
1283	0x360C2086,  0x410B1010,  0xD80241AA,  0xAF05713C,
1284	0x220D7CC9,  0x550A4C5F,  0xCC031DE5,  0xBB042D73,
1285	0x2560B8D0,  0x52678846,  0xCB6ED9FC,  0xBC69E96A,
1286	0x2CD6F4FB,  0x5BD1C46D,  0xC2D895D7,  0xB5DFA541,
1287	0x2BBB30E2,  0x5CBC0074,  0xC5B551CE,  0xB2B26158,
1288	0x04D44C65,  0x73D37CF3,  0xEADA2D49,  0x9DDD1DDF,
1289	0x03B9887C,  0x74BEB8EA,  0xEDB7E950,  0x9AB0D9C6,
1290	0x0A0FC457,  0x7D08F4C1,  0xE401A57B,  0x930695ED,
1291	0x0D62004E,  0x7A6530D8,  0xE36C6162,  0x946B51F4,
1292	0x19635C01,  0x6E646C97,  0xF76D3D2D,  0x806A0DBB,
1293	0x1E0E9818,  0x6909A88E,  0xF000F934,  0x8707C9A2,
1294	0x17B8D433,  0x60BFE4A5,  0xF9B6B51F,  0x8EB18589,
1295	0x10D5102A,  0x67D220BC,  0xFEDB7106,  0x89DC4190,
1296	0x49662D3D,  0x3E611DAB,  0xA7684C11,  0xD06F7C87,
1297	0x4E0BE924,  0x390CD9B2,  0xA0058808,  0xD702B89E,
1298	0x47BDA50F,  0x30BA9599,  0xA9B3C423,  0xDEB4F4B5,
1299	0x40D06116,  0x37D75180,  0xAEDE003A,  0xD9D930AC,
1300	0x54D13D59,  0x23D60DCF,  0xBADF5C75,  0xCDD86CE3,
1301	0x53BCF940,  0x24BBC9D6,  0xBDB2986C,  0xCAB5A8FA,
1302	0x5A0AB56B,  0x2D0D85FD,  0xB404D447,  0xC303E4D1,
1303	0x5D677172,  0x2A6041E4,  0xB369105E,  0xC46E20C8,
1304	0x72080DF5,  0x050F3D63,  0x9C066CD9,  0xEB015C4F,
1305	0x7565C9EC,  0x0262F97A,  0x9B6BA8C0,  0xEC6C9856,
1306	0x7CD385C7,  0x0BD4B551,  0x92DDE4EB,  0xE5DAD47D,
1307	0x7BBE41DE,  0x0CB97148,  0x95B020F2,  0xE2B71064,
1308	0x6FBF1D91,  0x18B82D07,  0x81B17CBD,  0xF6B64C2B,
1309	0x68D2D988,  0x1FD5E91E,  0x86DCB8A4,  0xF1DB8832,
1310	0x616495A3,  0x1663A535,  0x8F6AF48F,  0xF86DC419,
1311	0x660951BA,  0x110E612C,  0x88073096,  0xFF000000
1312};
1313