Home | History | Annotate | Line # | Download | only in boot
if_ze.c revision 1.8
      1  1.8  ragge /*	$NetBSD: if_ze.c,v 1.8 2000/05/09 20:53:52 ragge Exp $	*/
      2  1.1  ragge /*
      3  1.1  ragge  * Copyright (c) 1998 James R. Maynard III.  All rights reserved.
      4  1.1  ragge  *
      5  1.1  ragge  * Redistribution and use in source and binary forms, with or without
      6  1.1  ragge  * modification, are permitted provided that the following conditions
      7  1.1  ragge  * are met:
      8  1.1  ragge  * 1. Redistributions of source code must retain the above copyright
      9  1.1  ragge  *    notice, this list of conditions and the following disclaimer.
     10  1.1  ragge  * 2. Redistributions in binary form must reproduce the above copyright
     11  1.1  ragge  *    notice, this list of conditions and the following disclaimer in the
     12  1.1  ragge  *    documentation and/or other materials provided with the distribution.
     13  1.1  ragge  * 3. All advertising materials mentioning features or use of this software
     14  1.1  ragge  *    must display the following acknowledgement:
     15  1.1  ragge  *	This product includes software developed by James R. Maynard III.
     16  1.1  ragge  * 4. The name of the author may not be used to endorse or promote products
     17  1.1  ragge  *    derived from this software without specific prior written permission
     18  1.1  ragge  *
     19  1.1  ragge  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20  1.1  ragge  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21  1.1  ragge  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22  1.1  ragge  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  1.1  ragge  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     24  1.1  ragge  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  1.1  ragge  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  1.1  ragge  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  1.1  ragge  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28  1.1  ragge  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  1.1  ragge  *
     30  1.1  ragge  *	Standalone routine for the SGEC Ethernet controller.
     31  1.1  ragge  */
     32  1.1  ragge 
     33  1.1  ragge #include <sys/param.h>
     34  1.1  ragge #include <sys/types.h>
     35  1.3  ragge #include <sys/socket.h>
     36  1.3  ragge #include <sys/queue.h>
     37  1.3  ragge 
     38  1.3  ragge #include <net/if.h>
     39  1.3  ragge #include <net/if_ether.h>
     40  1.1  ragge 
     41  1.1  ragge #include <netinet/in.h>
     42  1.1  ragge #include <netinet/in_systm.h>
     43  1.1  ragge 
     44  1.1  ragge #include <lib/libkern/libkern.h>
     45  1.1  ragge #include <lib/libsa/netif.h>
     46  1.1  ragge #include <lib/libsa/stand.h>
     47  1.1  ragge 
     48  1.5  ragge #include <dev/ic/sgecreg.h>
     49  1.1  ragge 
     50  1.5  ragge #include "arch/vax/include/sid.h"
     51  1.8  ragge #include "arch/vax/include/rpb.h"
     52  1.8  ragge 
     53  1.8  ragge #include "vaxstand.h"
     54  1.1  ragge 
     55  1.1  ragge int ze_probe(), ze_match(), ze_get(), ze_put();
     56  1.4  ragge void ze_init(), ze_end();
     57  1.1  ragge 
     58  1.1  ragge struct netif_stats ze_stats;
     59  1.1  ragge 
     60  1.1  ragge struct netif_dif ze_ifs[] = {
     61  1.1  ragge /*	dif_unit	dif_nsel	dif_stats	dif_private	*/
     62  1.1  ragge {	0,		1,		&ze_stats,	},
     63  1.1  ragge };
     64  1.1  ragge 
     65  1.1  ragge struct netif_stats ze_stats;
     66  1.1  ragge 
     67  1.1  ragge struct netif_driver ze_driver = {
     68  1.4  ragge 	"ze", ze_match, ze_probe, ze_init, ze_get, ze_put, ze_end, ze_ifs, 1,
     69  1.1  ragge };
     70  1.1  ragge 
     71  1.6   matt #define NRCV 8				/* allocate 5 receive descriptors */
     72  1.1  ragge #define NXMT 5				/* and 5 transmit - must be >1 */
     73  1.1  ragge #define SETUP_FRAME_LEN 128		/* length of the setup frame */
     74  1.1  ragge 
     75  1.1  ragge /* allocate a buffer on an octaword boundary */
     76  1.1  ragge #define OW_ALLOC(x) ((void *)((int)(alloc((x) + 15) + 15) & ~15))
     77  1.1  ragge 
     78  1.1  ragge static	volatile struct zedevice *addr;
     79  1.1  ragge 
     80  1.1  ragge struct ze_tdes *ze_tdes_list;	/* transmit desc list */
     81  1.1  ragge struct ze_rdes *ze_rdes_list;	/* and receive desc list */
     82  1.1  ragge u_char ze_myaddr[ETHER_ADDR_LEN];	/* my Ethernet address */
     83  1.1  ragge 
     84  1.1  ragge int
     85  1.1  ragge ze_match(nif, machdep_hint)
     86  1.1  ragge 	struct netif *nif;
     87  1.1  ragge 	void *machdep_hint;
     88  1.1  ragge {
     89  1.1  ragge 	return strcmp(machdep_hint, "ze") == 0;
     90  1.1  ragge }
     91  1.1  ragge 
     92  1.1  ragge int
     93  1.1  ragge ze_probe(nif, machdep_hint)
     94  1.1  ragge 	struct netif *nif;
     95  1.1  ragge 	void *machdep_hint;
     96  1.1  ragge {
     97  1.1  ragge 	return 0;
     98  1.1  ragge }
     99  1.1  ragge 
    100  1.1  ragge void
    101  1.1  ragge ze_init(desc, machdep_hint)
    102  1.1  ragge 	struct iodesc *desc;
    103  1.1  ragge 	void *machdep_hint;
    104  1.1  ragge {
    105  1.1  ragge 	u_long nicsr0_work, *nisa_rom;
    106  1.1  ragge 	int i;
    107  1.1  ragge 	u_char *saved_buf;
    108  1.1  ragge 	struct ze_tdes *ze_setup_tdes_list;
    109  1.1  ragge 
    110  1.1  ragge 	/* point to the device in memory */
    111  1.8  ragge 	addr = (struct zedevice *)rpb->csrphy;
    112  1.1  ragge 
    113  1.1  ragge 	/* reset the device and wait for completion */
    114  1.1  ragge 	addr->ze_nicsr6 = ZE_NICSR6_MBO | ZE_NICSR6_RE;
    115  1.1  ragge 	while ((addr->ze_nicsr5 & ZE_NICSR5_ID) == 0)
    116  1.1  ragge 		;
    117  1.1  ragge 	if (addr->ze_nicsr5 & ZE_NICSR5_SF) {
    118  1.1  ragge 		printf("SGEC self-test failed...\n");
    119  1.1  ragge 	}
    120  1.1  ragge 
    121  1.1  ragge 	/* Get our Ethernet address */
    122  1.5  ragge 	if (vax_boardtype == VAX_BTYP_49) {
    123  1.5  ragge 		nisa_rom = (u_long *)0x27800000;
    124  1.5  ragge 		for (i=0; i<ETHER_ADDR_LEN; i++)
    125  1.5  ragge 			ze_myaddr[i] = nisa_rom[i] & 0377;
    126  1.5  ragge 	} else {
    127  1.5  ragge 		nisa_rom = (u_long *)0x20084000;
    128  1.5  ragge 		for (i=0; i<ETHER_ADDR_LEN; i++)
    129  1.7  ragge 			if (vax_boardtype == VAX_BTYP_660)
    130  1.7  ragge 				ze_myaddr[i] = (nisa_rom[i] & 0xff000000) >> 24;
    131  1.7  ragge 			else
    132  1.7  ragge 				ze_myaddr[i] = (nisa_rom[i] & 0x0000ff00) >> 8;
    133  1.5  ragge 	}
    134  1.1  ragge 	bcopy(ze_myaddr,desc->myea,ETHER_ADDR_LEN);
    135  1.1  ragge 
    136  1.1  ragge 	/* initialize SGEC operating mode */
    137  1.1  ragge 	/* disable interrupts here */
    138  1.1  ragge 	nicsr0_work = ZE_NICSR0_IPL14 | ZE_NICSR0_SA | ZE_NICSR0_MBO |
    139  1.1  ragge 		(ZE_NICSR0_IV_MASK & 0x0108);
    140  1.1  ragge 	while (addr->ze_nicsr0 != nicsr0_work)
    141  1.1  ragge 		addr->ze_nicsr0 = nicsr0_work;
    142  1.1  ragge 	if (addr->ze_nicsr5 & ZE_NICSR5_ME)
    143  1.1  ragge 		addr->ze_nicsr5 |= ZE_NICSR5_ME;
    144  1.1  ragge 	/* reenable interrupts here */
    145  1.1  ragge 
    146  1.1  ragge 	/* Allocate space for descriptor lists and buffers,
    147  1.1  ragge 		then initialize them. Set up both lists as a ring. */
    148  1.1  ragge 	ze_rdes_list = OW_ALLOC((NRCV+1) * sizeof(struct ze_rdes));
    149  1.1  ragge 	ze_tdes_list = OW_ALLOC((NXMT+1) * sizeof(struct ze_tdes));
    150  1.1  ragge 	for (i=0; i < NRCV; i++) {
    151  1.1  ragge 		bzero(ze_rdes_list+i,sizeof(struct ze_rdes));
    152  1.1  ragge 		ze_rdes_list[i].ze_framelen = ZE_FRAMELEN_OW;
    153  1.1  ragge 		ze_rdes_list[i].ze_bufsize = ETHER_MAX_LEN;
    154  1.1  ragge 		ze_rdes_list[i].ze_bufaddr = alloc(ETHER_MAX_LEN);
    155  1.1  ragge 	}
    156  1.1  ragge 	bzero(ze_rdes_list+NRCV,sizeof(struct ze_rdes));
    157  1.1  ragge 	ze_rdes_list[NRCV].ze_framelen = ZE_FRAMELEN_OW;
    158  1.1  ragge 	ze_rdes_list[NRCV].ze_rdes1 = ZE_RDES1_CA;
    159  1.1  ragge 	ze_rdes_list[NRCV].ze_bufaddr = (u_char *)ze_rdes_list;
    160  1.1  ragge 	for (i=0; i < NXMT; i++) {
    161  1.1  ragge 		bzero(ze_tdes_list+i,sizeof(struct ze_tdes));
    162  1.1  ragge 		ze_tdes_list[i].ze_tdes1 = ZE_TDES1_FS | ZE_TDES1_LS;
    163  1.1  ragge 		ze_tdes_list[i].ze_bufsize = ETHER_MAX_LEN;
    164  1.1  ragge 		ze_tdes_list[i].ze_bufaddr = alloc(ETHER_MAX_LEN);
    165  1.1  ragge 	}
    166  1.1  ragge 	bzero(ze_tdes_list+NXMT,sizeof(struct ze_tdes));
    167  1.1  ragge 	ze_tdes_list[NXMT].ze_tdes1 = ZE_TDES1_CA;
    168  1.1  ragge 	ze_tdes_list[NXMT].ze_tdr = ZE_TDR_OW;
    169  1.1  ragge 	ze_tdes_list[NXMT].ze_bufaddr = (u_char *)ze_tdes_list;
    170  1.1  ragge 
    171  1.1  ragge 	/* Build setup frame. We set the SGEC to do a
    172  1.1  ragge 		perfect filter on our own address. */
    173  1.1  ragge 	ze_setup_tdes_list = OW_ALLOC(2*sizeof(struct ze_tdes));
    174  1.1  ragge 	bzero(ze_setup_tdes_list+0,2*sizeof(struct ze_tdes));
    175  1.1  ragge 	ze_setup_tdes_list[0].ze_tdr = ZE_TDR_OW;
    176  1.1  ragge 	ze_setup_tdes_list[0].ze_tdes1 = ZE_TDES1_DT_SETUP;
    177  1.1  ragge 	ze_setup_tdes_list[0].ze_bufsize = SETUP_FRAME_LEN;
    178  1.1  ragge 	ze_setup_tdes_list[0].ze_bufaddr = alloc(SETUP_FRAME_LEN);
    179  1.1  ragge 	bzero(ze_setup_tdes_list[0].ze_bufaddr,SETUP_FRAME_LEN);
    180  1.1  ragge 	for (i=0; i < 16; i++)
    181  1.1  ragge 		bcopy(ze_myaddr,ze_setup_tdes_list[0].ze_bufaddr+(8*i),
    182  1.1  ragge 			ETHER_ADDR_LEN);
    183  1.1  ragge 	ze_setup_tdes_list[1].ze_tdes1 = ZE_TDES1_CA;
    184  1.1  ragge 	ze_setup_tdes_list[1].ze_bufaddr = (u_char *)ze_setup_tdes_list;
    185  1.1  ragge 
    186  1.1  ragge 	/* Start the transmitter and initialize almost everything else. */
    187  1.1  ragge 	addr->ze_nicsr4 = ze_setup_tdes_list;
    188  1.1  ragge 	addr->ze_nicsr6 = ZE_NICSR6_MBO | ZE_NICSR6_SE | ZE_NICSR6_ST |
    189  1.1  ragge 		ZE_NICSR6_DC | ZE_NICSR6_BL_4;
    190  1.1  ragge 	while ((addr->ze_nicsr5 & ZE_NICSR5_TS) != ZE_NICSR5_TS_SUSP)
    191  1.1  ragge 		;	/* wait for the frame to be processed */
    192  1.1  ragge 
    193  1.1  ragge 	/* Setup frame is done processing, initialize the receiver and
    194  1.1  ragge 		point the transmitter to the real tdes list. */
    195  1.1  ragge 	addr->ze_nicsr4 = ze_tdes_list;
    196  1.1  ragge 	addr->ze_nicsr3 = ze_rdes_list;
    197  1.1  ragge 	addr->ze_nicsr6 |= ZE_NICSR6_SR;
    198  1.1  ragge 
    199  1.1  ragge 	/* And away-y-y we go! */
    200  1.1  ragge }
    201  1.1  ragge 
    202  1.1  ragge int
    203  1.1  ragge ze_get(desc, pkt, maxlen, timeout)
    204  1.1  ragge 	struct iodesc *desc;
    205  1.1  ragge 	void *pkt;
    206  1.1  ragge 	int maxlen;
    207  1.1  ragge 	time_t timeout;
    208  1.1  ragge {
    209  1.1  ragge 	int timeout_ctr=100000*timeout, len, rdes;
    210  1.1  ragge 
    211  1.1  ragge 	while (timeout_ctr-- > 0) {
    212  1.1  ragge 
    213  1.1  ragge 	/* If there's not a packet waiting for us, just decrement the
    214  1.1  ragge 		timeout counter. */
    215  1.1  ragge 		if (!(addr->ze_nicsr5 & ZE_NICSR5_RI))
    216  1.1  ragge 			continue;
    217  1.1  ragge 
    218  1.1  ragge 	/* Look through the receive descriptor list for the packet. */
    219  1.1  ragge 		for (rdes=0; rdes<NRCV; rdes++) {
    220  1.1  ragge 			if (ze_rdes_list[rdes].ze_framelen & ZE_FRAMELEN_OW)
    221  1.1  ragge 				continue;
    222  1.1  ragge 
    223  1.1  ragge 	/* If the packet has an error, ignore it. */
    224  1.1  ragge 			if (ze_rdes_list[rdes].ze_rdes0 & ZE_RDES0_ES)
    225  1.1  ragge 				len = 0;
    226  1.1  ragge 
    227  1.1  ragge 	/* Copy the packet, up to the length supplied by the caller, to
    228  1.1  ragge 		the caller's buffer. */
    229  1.1  ragge 			else {
    230  1.1  ragge 				if ((len = (ze_rdes_list[rdes].ze_framelen &
    231  1.1  ragge 					(~ ZE_FRAMELEN_OW))) > maxlen)
    232  1.1  ragge 					len = maxlen;
    233  1.1  ragge 				bcopy((void *)ze_rdes_list[rdes].ze_bufaddr,
    234  1.1  ragge 					pkt,len);
    235  1.1  ragge 			}
    236  1.1  ragge 
    237  1.1  ragge 	/* Give ownership of this descriptor back to the SGEC. */
    238  1.1  ragge 			ze_rdes_list[rdes].ze_framelen = ZE_FRAMELEN_OW;
    239  1.1  ragge 
    240  1.1  ragge 	/* If we actually got a good packet, reset the error flags and
    241  1.1  ragge 		tell the SGEC to look for more before returning. */
    242  1.1  ragge 			if (len > 0) {
    243  1.1  ragge 				addr->ze_nicsr5=ZE_NICSR5_RU | ZE_NICSR5_RI |
    244  1.1  ragge 					ZE_NICSR5_IS;
    245  1.1  ragge 				addr->ze_nicsr2=ZE_NICSR2_RXPD;
    246  1.1  ragge 				return len;
    247  1.1  ragge 			}
    248  1.1  ragge 		}
    249  1.1  ragge 	}
    250  1.1  ragge 
    251  1.1  ragge 	/* If we're going to return an error indication, at least reset the
    252  1.1  ragge 		error flags and tell the SGEC to keep receiving first. */
    253  1.1  ragge 	addr->ze_nicsr5=ZE_NICSR5_RU | ZE_NICSR5_RI | ZE_NICSR5_IS;
    254  1.1  ragge 	addr->ze_nicsr2=ZE_NICSR2_RXPD;
    255  1.1  ragge 	return 0;
    256  1.1  ragge }
    257  1.1  ragge 
    258  1.1  ragge int
    259  1.1  ragge ze_put(desc, pkt, len)
    260  1.1  ragge 	struct iodesc *desc;
    261  1.1  ragge 	void *pkt;
    262  1.1  ragge 	int len;
    263  1.1  ragge {
    264  1.1  ragge 	int timeout=100000;
    265  1.1  ragge 
    266  1.1  ragge 	/* The SGEC maintains its position in the transmit descriptor list
    267  1.1  ragge 	for the next frame to transmit. Unfortunately, there's no way to tell
    268  1.1  ragge 	from software just where that is. We're forced to reset the position
    269  1.1  ragge 	whenever we send a frame, which requires waiting for the previous
    270  1.1  ragge 	frame to be sent. Argh. */
    271  1.1  ragge 	while ((addr->ze_nicsr5 & ZE_NICSR5_TS) == ZE_NICSR5_TS_RUN)
    272  1.1  ragge 		;
    273  1.1  ragge 
    274  1.1  ragge 	/* Copy the packet to the buffer we allocated. */
    275  1.1  ragge 	bcopy(pkt, (void *)ze_tdes_list[0].ze_bufaddr, len);
    276  1.1  ragge 
    277  1.1  ragge 	/* Set the packet length in the descriptor, increasing it to the
    278  1.1  ragge 		minimum size if needed. */
    279  1.1  ragge 	ze_tdes_list[0].ze_bufsize = len;
    280  1.1  ragge 	if (len < ETHER_MIN_LEN)
    281  1.1  ragge 		ze_tdes_list[0].ze_bufsize = ETHER_MIN_LEN;
    282  1.1  ragge 
    283  1.1  ragge 	/* Give ownership of the descriptor to the SGEC and tell it to start
    284  1.1  ragge 		transmitting. */
    285  1.1  ragge 	ze_tdes_list[0].ze_tdr = ZE_TDR_OW;
    286  1.1  ragge 	addr->ze_nicsr4 = ze_tdes_list;
    287  1.1  ragge 	addr->ze_nicsr1 = ZE_NICSR1_TXPD;
    288  1.1  ragge 
    289  1.1  ragge 	/* Wait for the frame to be sent, but not too long. */
    290  1.1  ragge 	timeout = 100000;
    291  1.1  ragge 	while ((addr->ze_nicsr5 & ZE_NICSR5_TI == 0) && (--timeout>0))
    292  1.1  ragge 		;
    293  1.1  ragge 
    294  1.1  ragge 	/* Reset the transmitter interrupt pending flag. */
    295  1.1  ragge 	addr->ze_nicsr5 |= ZE_NICSR5_TI;
    296  1.1  ragge 
    297  1.1  ragge 	/* Return good if we didn't timeout, or error if we did. */
    298  1.1  ragge 	if (timeout>0) return len;
    299  1.1  ragge 	return -1;
    300  1.4  ragge }
    301  1.4  ragge 
    302  1.4  ragge void
    303  1.4  ragge ze_end()
    304  1.4  ragge {
    305  1.4  ragge 	addr->ze_nicsr6 = ZE_NICSR6_RE;
    306  1.1  ragge }
    307