Home | History | Annotate | Line # | Download | only in boot
if_ze.c revision 1.12
      1  1.12  ragge /*	$NetBSD: if_ze.c,v 1.12 2002/05/27 16:54:18 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/libsa/netif.h>
     45   1.1  ragge #include <lib/libsa/stand.h>
     46  1.12  ragge #include <lib/libsa/net.h>
     47   1.1  ragge 
     48  1.10  ragge #include "lib/libkern/libkern.h"
     49  1.10  ragge 
     50   1.5  ragge #include <dev/ic/sgecreg.h>
     51   1.1  ragge 
     52   1.5  ragge #include "arch/vax/include/sid.h"
     53   1.8  ragge #include "arch/vax/include/rpb.h"
     54   1.8  ragge 
     55   1.8  ragge #include "vaxstand.h"
     56   1.1  ragge 
     57  1.10  ragge static int ze_get(struct iodesc *, void *, size_t, time_t);
     58  1.10  ragge static int ze_put(struct iodesc *, void *, size_t);
     59   1.1  ragge 
     60   1.1  ragge 
     61   1.1  ragge struct netif_driver ze_driver = {
     62  1.10  ragge 	0, 0, 0, 0, ze_get, ze_put,
     63   1.1  ragge };
     64   1.1  ragge 
     65   1.9   matt #define NRCV 8				/* allocate 8 receive descriptors */
     66   1.9   matt #define NXMT 4				/* and 4 transmit - must be >1 */
     67   1.1  ragge #define SETUP_FRAME_LEN 128		/* length of the setup frame */
     68   1.1  ragge 
     69   1.1  ragge /* allocate a buffer on an octaword boundary */
     70  1.10  ragge #define OW_ALLOC(x) ((void *)((int)((int)alloc((x) + 15) + 15) & ~15))
     71   1.1  ragge 
     72   1.1  ragge static	volatile struct zedevice *addr;
     73   1.1  ragge 
     74   1.1  ragge struct ze_tdes *ze_tdes_list;	/* transmit desc list */
     75   1.1  ragge struct ze_rdes *ze_rdes_list;	/* and receive desc list */
     76   1.1  ragge u_char ze_myaddr[ETHER_ADDR_LEN];	/* my Ethernet address */
     77   1.1  ragge 
     78   1.1  ragge int
     79  1.10  ragge zeopen(struct open_file *f, int adapt, int ctlr, int unit, int part)
     80   1.1  ragge {
     81   1.1  ragge 	u_long nicsr0_work, *nisa_rom;
     82  1.10  ragge 	struct ze_tdes *ze_setup_tdes_list;
     83   1.1  ragge 	int i;
     84   1.1  ragge 
     85   1.1  ragge 	/* point to the device in memory */
     86  1.10  ragge 	if (askname == 0) /* Override if autoboot */
     87  1.10  ragge 		addr = (struct zedevice *)bootrpb.csrphy;
     88  1.10  ragge 	else
     89  1.10  ragge 		addr = (struct zedevice *)0x20008000;
     90   1.1  ragge 
     91   1.1  ragge 	/* reset the device and wait for completion */
     92   1.1  ragge 	addr->ze_nicsr6 = ZE_NICSR6_MBO | ZE_NICSR6_RE;
     93   1.1  ragge 	while ((addr->ze_nicsr5 & ZE_NICSR5_ID) == 0)
     94   1.1  ragge 		;
     95   1.1  ragge 	if (addr->ze_nicsr5 & ZE_NICSR5_SF) {
     96   1.1  ragge 		printf("SGEC self-test failed...\n");
     97  1.10  ragge 		return 1;
     98   1.1  ragge 	}
     99   1.1  ragge 
    100   1.1  ragge 	/* Get our Ethernet address */
    101  1.12  ragge 	if (vax_boardtype == VAX_BTYP_49) {
    102  1.12  ragge 		nisa_rom = (u_long *)0x27800000;
    103   1.5  ragge 		for (i=0; i<ETHER_ADDR_LEN; i++)
    104   1.5  ragge 			ze_myaddr[i] = nisa_rom[i] & 0377;
    105  1.12  ragge 	} else if (vax_boardtype == VAX_BTYP_VXT) {
    106  1.12  ragge 		nisa_rom = (u_long *)0x200c4000;
    107  1.12  ragge 		for (i=0; i<ETHER_ADDR_LEN; i++)
    108  1.12  ragge 			ze_myaddr[i] = nisa_rom[i] & 0xff;
    109   1.5  ragge 	} else {
    110   1.5  ragge 		nisa_rom = (u_long *)0x20084000;
    111   1.5  ragge 		for (i=0; i<ETHER_ADDR_LEN; i++)
    112   1.7  ragge 			if (vax_boardtype == VAX_BTYP_660)
    113   1.7  ragge 				ze_myaddr[i] = (nisa_rom[i] & 0xff000000) >> 24;
    114   1.7  ragge 			else
    115   1.7  ragge 				ze_myaddr[i] = (nisa_rom[i] & 0x0000ff00) >> 8;
    116   1.5  ragge 	}
    117  1.12  ragge 	printf("SGEC: Ethernet address %s\n", ether_sprintf(ze_myaddr));
    118   1.1  ragge 
    119   1.1  ragge 	/* initialize SGEC operating mode */
    120   1.1  ragge 	/* disable interrupts here */
    121   1.1  ragge 	nicsr0_work = ZE_NICSR0_IPL14 | ZE_NICSR0_SA | ZE_NICSR0_MBO |
    122   1.1  ragge 		(ZE_NICSR0_IV_MASK & 0x0108);
    123   1.1  ragge 	while (addr->ze_nicsr0 != nicsr0_work)
    124   1.1  ragge 		addr->ze_nicsr0 = nicsr0_work;
    125   1.1  ragge 	if (addr->ze_nicsr5 & ZE_NICSR5_ME)
    126   1.1  ragge 		addr->ze_nicsr5 |= ZE_NICSR5_ME;
    127   1.1  ragge 	/* reenable interrupts here */
    128   1.1  ragge 
    129   1.1  ragge 	/* Allocate space for descriptor lists and buffers,
    130   1.1  ragge 		then initialize them. Set up both lists as a ring. */
    131   1.1  ragge 	ze_rdes_list = OW_ALLOC((NRCV+1) * sizeof(struct ze_rdes));
    132   1.1  ragge 	ze_tdes_list = OW_ALLOC((NXMT+1) * sizeof(struct ze_tdes));
    133   1.1  ragge 	for (i=0; i < NRCV; i++) {
    134   1.1  ragge 		bzero(ze_rdes_list+i,sizeof(struct ze_rdes));
    135   1.1  ragge 		ze_rdes_list[i].ze_framelen = ZE_FRAMELEN_OW;
    136   1.1  ragge 		ze_rdes_list[i].ze_bufsize = ETHER_MAX_LEN;
    137   1.1  ragge 		ze_rdes_list[i].ze_bufaddr = alloc(ETHER_MAX_LEN);
    138   1.1  ragge 	}
    139   1.1  ragge 	bzero(ze_rdes_list+NRCV,sizeof(struct ze_rdes));
    140   1.1  ragge 	ze_rdes_list[NRCV].ze_framelen = ZE_FRAMELEN_OW;
    141   1.1  ragge 	ze_rdes_list[NRCV].ze_rdes1 = ZE_RDES1_CA;
    142   1.1  ragge 	ze_rdes_list[NRCV].ze_bufaddr = (u_char *)ze_rdes_list;
    143   1.1  ragge 	for (i=0; i < NXMT; i++) {
    144   1.1  ragge 		bzero(ze_tdes_list+i,sizeof(struct ze_tdes));
    145   1.1  ragge 		ze_tdes_list[i].ze_tdes1 = ZE_TDES1_FS | ZE_TDES1_LS;
    146   1.1  ragge 		ze_tdes_list[i].ze_bufsize = ETHER_MAX_LEN;
    147   1.1  ragge 		ze_tdes_list[i].ze_bufaddr = alloc(ETHER_MAX_LEN);
    148   1.1  ragge 	}
    149   1.1  ragge 	bzero(ze_tdes_list+NXMT,sizeof(struct ze_tdes));
    150   1.1  ragge 	ze_tdes_list[NXMT].ze_tdes1 = ZE_TDES1_CA;
    151   1.1  ragge 	ze_tdes_list[NXMT].ze_tdr = ZE_TDR_OW;
    152   1.1  ragge 	ze_tdes_list[NXMT].ze_bufaddr = (u_char *)ze_tdes_list;
    153   1.1  ragge 
    154   1.1  ragge 	/* Build setup frame. We set the SGEC to do a
    155   1.1  ragge 		perfect filter on our own address. */
    156   1.1  ragge 	ze_setup_tdes_list = OW_ALLOC(2*sizeof(struct ze_tdes));
    157   1.1  ragge 	bzero(ze_setup_tdes_list+0,2*sizeof(struct ze_tdes));
    158   1.1  ragge 	ze_setup_tdes_list[0].ze_tdr = ZE_TDR_OW;
    159   1.1  ragge 	ze_setup_tdes_list[0].ze_tdes1 = ZE_TDES1_DT_SETUP;
    160   1.1  ragge 	ze_setup_tdes_list[0].ze_bufsize = SETUP_FRAME_LEN;
    161   1.1  ragge 	ze_setup_tdes_list[0].ze_bufaddr = alloc(SETUP_FRAME_LEN);
    162   1.1  ragge 	bzero(ze_setup_tdes_list[0].ze_bufaddr,SETUP_FRAME_LEN);
    163   1.1  ragge 	for (i=0; i < 16; i++)
    164   1.1  ragge 		bcopy(ze_myaddr,ze_setup_tdes_list[0].ze_bufaddr+(8*i),
    165   1.1  ragge 			ETHER_ADDR_LEN);
    166   1.1  ragge 	ze_setup_tdes_list[1].ze_tdes1 = ZE_TDES1_CA;
    167   1.1  ragge 	ze_setup_tdes_list[1].ze_bufaddr = (u_char *)ze_setup_tdes_list;
    168   1.1  ragge 
    169   1.1  ragge 	/* Start the transmitter and initialize almost everything else. */
    170   1.1  ragge 	addr->ze_nicsr4 = ze_setup_tdes_list;
    171   1.1  ragge 	addr->ze_nicsr6 = ZE_NICSR6_MBO | ZE_NICSR6_SE | ZE_NICSR6_ST |
    172   1.1  ragge 		ZE_NICSR6_DC | ZE_NICSR6_BL_4;
    173   1.1  ragge 	while ((addr->ze_nicsr5 & ZE_NICSR5_TS) != ZE_NICSR5_TS_SUSP)
    174   1.1  ragge 		;	/* wait for the frame to be processed */
    175   1.1  ragge 
    176   1.1  ragge 	/* Setup frame is done processing, initialize the receiver and
    177   1.1  ragge 		point the transmitter to the real tdes list. */
    178   1.1  ragge 	addr->ze_nicsr4 = ze_tdes_list;
    179   1.1  ragge 	addr->ze_nicsr3 = ze_rdes_list;
    180   1.1  ragge 	addr->ze_nicsr6 |= ZE_NICSR6_SR;
    181   1.1  ragge 
    182   1.1  ragge 	/* And away-y-y we go! */
    183  1.10  ragge 
    184  1.10  ragge 	net_devinit(f, &ze_driver, ze_myaddr);
    185  1.10  ragge 	return 0;
    186   1.1  ragge }
    187   1.1  ragge 
    188   1.1  ragge int
    189   1.1  ragge ze_get(desc, pkt, maxlen, timeout)
    190   1.1  ragge 	struct iodesc *desc;
    191   1.1  ragge 	void *pkt;
    192  1.10  ragge 	size_t maxlen;
    193   1.1  ragge 	time_t timeout;
    194   1.1  ragge {
    195   1.1  ragge 	int timeout_ctr=100000*timeout, len, rdes;
    196   1.1  ragge 
    197   1.1  ragge 	while (timeout_ctr-- > 0) {
    198   1.1  ragge 
    199   1.1  ragge 	/* If there's not a packet waiting for us, just decrement the
    200   1.1  ragge 		timeout counter. */
    201   1.1  ragge 		if (!(addr->ze_nicsr5 & ZE_NICSR5_RI))
    202   1.1  ragge 			continue;
    203   1.1  ragge 
    204   1.1  ragge 	/* Look through the receive descriptor list for the packet. */
    205   1.1  ragge 		for (rdes=0; rdes<NRCV; rdes++) {
    206   1.1  ragge 			if (ze_rdes_list[rdes].ze_framelen & ZE_FRAMELEN_OW)
    207   1.1  ragge 				continue;
    208   1.1  ragge 
    209   1.1  ragge 	/* If the packet has an error, ignore it. */
    210   1.1  ragge 			if (ze_rdes_list[rdes].ze_rdes0 & ZE_RDES0_ES)
    211   1.1  ragge 				len = 0;
    212   1.1  ragge 
    213   1.1  ragge 	/* Copy the packet, up to the length supplied by the caller, to
    214   1.1  ragge 		the caller's buffer. */
    215   1.1  ragge 			else {
    216   1.1  ragge 				if ((len = (ze_rdes_list[rdes].ze_framelen &
    217   1.1  ragge 					(~ ZE_FRAMELEN_OW))) > maxlen)
    218   1.1  ragge 					len = maxlen;
    219   1.1  ragge 				bcopy((void *)ze_rdes_list[rdes].ze_bufaddr,
    220   1.1  ragge 					pkt,len);
    221   1.1  ragge 			}
    222   1.1  ragge 
    223   1.1  ragge 	/* Give ownership of this descriptor back to the SGEC. */
    224   1.1  ragge 			ze_rdes_list[rdes].ze_framelen = ZE_FRAMELEN_OW;
    225   1.1  ragge 
    226   1.1  ragge 	/* If we actually got a good packet, reset the error flags and
    227   1.1  ragge 		tell the SGEC to look for more before returning. */
    228   1.1  ragge 			if (len > 0) {
    229   1.1  ragge 				addr->ze_nicsr5=ZE_NICSR5_RU | ZE_NICSR5_RI |
    230   1.1  ragge 					ZE_NICSR5_IS;
    231   1.1  ragge 				addr->ze_nicsr2=ZE_NICSR2_RXPD;
    232   1.1  ragge 				return len;
    233   1.1  ragge 			}
    234   1.1  ragge 		}
    235   1.1  ragge 	}
    236   1.1  ragge 
    237   1.1  ragge 	/* If we're going to return an error indication, at least reset the
    238   1.1  ragge 		error flags and tell the SGEC to keep receiving first. */
    239   1.1  ragge 	addr->ze_nicsr5=ZE_NICSR5_RU | ZE_NICSR5_RI | ZE_NICSR5_IS;
    240   1.1  ragge 	addr->ze_nicsr2=ZE_NICSR2_RXPD;
    241   1.1  ragge 	return 0;
    242   1.1  ragge }
    243   1.1  ragge 
    244   1.1  ragge int
    245   1.1  ragge ze_put(desc, pkt, len)
    246   1.1  ragge 	struct iodesc *desc;
    247   1.1  ragge 	void *pkt;
    248  1.10  ragge 	size_t len;
    249   1.1  ragge {
    250   1.1  ragge 	int timeout=100000;
    251   1.1  ragge 
    252   1.1  ragge 	/* The SGEC maintains its position in the transmit descriptor list
    253   1.1  ragge 	for the next frame to transmit. Unfortunately, there's no way to tell
    254   1.1  ragge 	from software just where that is. We're forced to reset the position
    255   1.1  ragge 	whenever we send a frame, which requires waiting for the previous
    256   1.1  ragge 	frame to be sent. Argh. */
    257   1.1  ragge 	while ((addr->ze_nicsr5 & ZE_NICSR5_TS) == ZE_NICSR5_TS_RUN)
    258   1.1  ragge 		;
    259   1.1  ragge 
    260   1.1  ragge 	/* Copy the packet to the buffer we allocated. */
    261   1.1  ragge 	bcopy(pkt, (void *)ze_tdes_list[0].ze_bufaddr, len);
    262   1.1  ragge 
    263   1.1  ragge 	/* Set the packet length in the descriptor, increasing it to the
    264   1.1  ragge 		minimum size if needed. */
    265   1.1  ragge 	ze_tdes_list[0].ze_bufsize = len;
    266   1.1  ragge 	if (len < ETHER_MIN_LEN)
    267   1.1  ragge 		ze_tdes_list[0].ze_bufsize = ETHER_MIN_LEN;
    268   1.1  ragge 
    269   1.1  ragge 	/* Give ownership of the descriptor to the SGEC and tell it to start
    270   1.1  ragge 		transmitting. */
    271   1.1  ragge 	ze_tdes_list[0].ze_tdr = ZE_TDR_OW;
    272   1.1  ragge 	addr->ze_nicsr4 = ze_tdes_list;
    273   1.1  ragge 	addr->ze_nicsr1 = ZE_NICSR1_TXPD;
    274   1.1  ragge 
    275   1.1  ragge 	/* Wait for the frame to be sent, but not too long. */
    276   1.1  ragge 	timeout = 100000;
    277  1.10  ragge 	while (((addr->ze_nicsr5 & ZE_NICSR5_TI) == 0) && (--timeout>0))
    278   1.1  ragge 		;
    279   1.1  ragge 
    280   1.1  ragge 	/* Reset the transmitter interrupt pending flag. */
    281   1.1  ragge 	addr->ze_nicsr5 |= ZE_NICSR5_TI;
    282   1.1  ragge 
    283   1.1  ragge 	/* Return good if we didn't timeout, or error if we did. */
    284   1.1  ragge 	if (timeout>0) return len;
    285   1.1  ragge 	return -1;
    286   1.4  ragge }
    287   1.4  ragge 
    288  1.10  ragge int
    289  1.10  ragge zeclose(struct open_file *f)
    290   1.4  ragge {
    291   1.4  ragge 	addr->ze_nicsr6 = ZE_NICSR6_RE;
    292  1.10  ragge 
    293  1.10  ragge 	return 0;
    294   1.1  ragge }
    295