diff options
author | Thomas Schwinge <tschwinge@gnu.org> | 2006-02-20 19:09:02 +0000 |
---|---|---|
committer | Thomas Schwinge <tschwinge@gnu.org> | 2009-06-18 00:26:33 +0200 |
commit | 6ff755dce12b1e0a45cac04548d3826d6061b03f (patch) | |
tree | 2aaff9e6e11b7cd80f362464b4e8568a1fb73bbc /i386/i386at/if_pc586.c | |
parent | b40d1da0855a87519b5764415aec6519025a8338 (diff) |
2006-02-20 Thomas Schwinge <tschwinge@gnu.org>
Remove unused and unsupported code. Consult the file
`DEVELOPMENT' for details. Partly based on suggestions by
Gianluca Guida <glguida@gmail.com>.
* i386/bogus/pc586.h: Remove file.
* i386/i386at/i82586.h: Likewise.
* i386/i386at/if_pc586.c: Likewise.
* i386/i386at/if_pc586.h: Likewise.
* i386/i386at/autoconf.c: Don't include <pc586.h> anymore and adopt all
users of NPC586 as if it were always defined to `0'.
* i386/i386at/conf.c: Likewise.
Diffstat (limited to 'i386/i386at/if_pc586.c')
-rw-r--r-- | i386/i386at/if_pc586.c | 2076 |
1 files changed, 0 insertions, 2076 deletions
diff --git a/i386/i386at/if_pc586.c b/i386/i386at/if_pc586.c deleted file mode 100644 index 195ce7d..0000000 --- a/i386/i386at/if_pc586.c +++ /dev/null @@ -1,2076 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * Olivetti PC586 Mach Ethernet driver v1.0 - * Copyright Ing. C. Olivetti & C. S.p.A. 1988, 1989 - * All rights reserved. - * - */ - -/* - Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc., -Cupertino, California. - - All Rights Reserved - - Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appears in all -copies and that both the copyright notice and this permission notice -appear in supporting documentation, and that the name of Olivetti -not be used in advertising or publicity pertaining to distribution -of the software without specific, written prior permission. - - OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, -IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR -CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, -NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION -WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/* - Copyright 1988, 1989 by Intel Corporation, Santa Clara, California. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appears in all -copies and that both the copyright notice and this permission notice -appear in supporting documentation, and that the name of Intel -not be used in advertising or publicity pertaining to distribution -of the software without specific, written prior permission. - -INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, -IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR -CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, -NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION -WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -/* - * NOTE: - * by rvb: - * 1. The best book on the 82586 is: - * LAN Components User's Manual by Intel - * The copy I found was dated 1984. This really tells you - * what the state machines are doing - * 2. In the current design, we only do one write at a time, - * though the hardware is capable of chaining and possibly - * even batching. The problem is that we only make one - * transmit buffer available in sram space. - * 3. - * n. Board Memory Map - RFA/FD 0 - 227 0x228 bytes - 226 = 0x19 * 0x16 bytes - RBD 228 - 3813 0x35ec bytes - 35e8 = 0x19 * 0x228 bytes - == 0x0a bytes (bd) + 2 bytes + 21c bytes - CU 3814 - 3913 0x100 bytes - TBD 3914 - 39a3 0x90 bytes - 90 = No 18 * 0x08 bytes - TBUF 39a4 - 3fdd 0x63a bytes (= 1594(10)) - SCB 3fde - 3fed 0x10 bytes - ISCP 3fee - 3ff5 0x08 bytes - SCP 3ff6 - 3fff 0x0a bytes - * - */ - -/* - * NOTE: - * - * Currently this driver doesn't support trailer protocols for - * packets. Once that is added, please remove this comment. - * - * Also, some lacking material includes the DLI code. If you - * are compiling this driver with DLI set, lookout, that code - * has not been looked at. - * - */ - -#define DEBUG -#define IF_CNTRS MACH -#define NDLI 0 - -#include <pc586.h> - -#ifdef MACH_KERNEL -#include <kern/time_out.h> -#include <device/device_types.h> -#include <device/errno.h> -#include <device/io_req.h> -#include <device/if_hdr.h> -#include <device/if_ether.h> -#include <device/net_status.h> -#include <device/net_io.h> -#else MACH_KERNEL -#include <sys/param.h> -#include <mach/machine/vm_param.h> -#include <sys/systm.h> -#include <sys/mbuf.h> -#include <sys/buf.h> -#include <sys/protosw.h> -#include <sys/socket.h> -#include <sys/vmmac.h> -#include <sys/ioctl.h> -#include <sys/errno.h> -#include <sys/syslog.h> - -#include <net/if.h> -#include <net/netisr.h> -#include <net/route.h> - -#ifdef INET -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/in_var.h> -#include <netinet/ip.h> -#include <netinet/if_ether.h> -#endif - -#ifdef NS -#include <netns/ns.h> -#include <netns/ns_if.h> -#endif - -#if DLI -#include <net/dli_var.h> -struct dli_var de_dlv[NDE]; -#endif DLI -#endif MACH_KERNEL - -#include <i386/ipl.h> -#include <mach/vm_param.h> -#include <vm/vm_kern.h> -#include <chips/busses.h> -#include <i386at/if_pc586.h> - -#define SPLNET spl6 -#if __STDC__ -#define CMD(x, y, unit) *(u_short *)(pc_softc[unit].prom + OFFSET_ ## x) = (u_short) (y) -#else __STDC__ -#define CMD(x, y, unit) *(u_short *)(pc_softc[unit].prom + OFFSET_/**/x) = (u_short) (y) -#endif __STDC__ - -#define pc586chatt(unit) CMD(CHANATT, 0x0001, unit) -#define pc586inton(unit) CMD(INTENAB, CMD_1, unit) -#define pc586intoff(unit) CMD(INTENAB, CMD_0, unit) - -int pc586probe(); -void pc586attach(); -int pc586intr(), pc586init(), pc586output(), pc586ioctl(), pc586reset(); -int pc586watch(), pc586rcv(), pc586xmt(), pc586bldcu(); -int pc586diag(), pc586config(); -char *pc586bldru(); -char *ram_to_ptr(); -u_short ptr_to_ram(); - -static vm_offset_t pc586_std[NPC586] = { 0 }; -static struct bus_device *pc586_info[NPC586]; -struct bus_driver pcdriver = - {pc586probe, 0, pc586attach, 0, pc586_std, "pc", pc586_info, 0, 0, 0}; - -char t_packet[ETHERMTU + sizeof(struct ether_header) + sizeof(long)]; -int xmt_watch = 0; - -typedef struct { -#ifdef MACH_KERNEL - struct ifnet ds_if; /* generic interface header */ - u_char ds_addr[6]; /* Ethernet hardware address */ -#else MACH_KERNEL - struct arpcom pc586_ac; -#define ds_if pc586_ac.ac_if -#define ds_addr pc586_ac.ac_enaddr -#endif MACH_KERNEL - int flags; - int seated; - int timer; - int open; - fd_t *begin_fd; - fd_t *end_fd; - rbd_t *end_rbd; - char *prom; - char *sram; - int tbusy; - short mode; -} pc_softc_t; -pc_softc_t pc_softc[NPC586]; - -struct pc586_cntrs { - struct { - u_int xmt, xmti; - u_int defer; - u_int busy; - u_int sleaze, intrinsic, intrinsic_count; - u_int chain; - } xmt; - struct { - u_int rcv; - u_int ovw; - u_int crc; - u_int frame; - u_int rscerrs, ovrnerrs; - u_int partial, bad_chain, fill; - } rcv; - u_int watch; -} pc586_cntrs[NPC586]; - - -#ifdef IF_CNTRS -int pc586_narp = 1, pc586_arp = 0; -int pc586_ein[32], pc586_eout[32]; -int pc586_lin[128/8], pc586_lout[128/8]; -static -log_2(no) -unsigned long no; -{ - return ({ unsigned long _temp__; - asm("bsr %1, %0; jne 0f; xorl %0, %0; 0:" : - "=r" (_temp__) : "a" (no)); - _temp__;}); -} -#endif IF_CNTRS - -/* - * pc586probe: - * - * This function "probes" or checks for the pc586 board on the bus to see - * if it is there. As far as I can tell, the best break between this - * routine and the attach code is to simply determine whether the board - * is configured in properly. Currently my approach to this is to write - * and read a word from the SRAM on the board being probed. If the word - * comes back properly then we assume the board is there. The config - * code expects to see a successful return from the probe routine before - * attach will be called. - * - * input : address device is mapped to, and unit # being checked - * output : a '1' is returned if the board exists, and a 0 otherwise - * - */ -pc586probe(port, dev) -struct bus_device *dev; -{ - caddr_t addr = (caddr_t)dev->address; - int unit = dev->unit; - int len = round_page(0x4000); - int sram_len = round_page(0x4000); - extern vm_offset_t phys_last_addr; - int i; - volatile char *b_prom; - volatile char *b_sram; - volatile u_short*t_ps; - - if ((unit < 0) || (unit > NPC586)) { - printf("pc%d: board out of range [0..%d]\n", - unit, NPC586); - return(0); - } - if ((addr > (caddr_t)0x100000) && (addr < (caddr_t)phys_last_addr)) - return 0; - - if (kmem_alloc_pageable(kernel_map, (vm_offset_t *) &b_prom, len) - != KERN_SUCCESS) { - printf("pc%d: can not allocate memory for prom.\n", unit); - return 0; - } - if (kmem_alloc_pageable(kernel_map, (vm_offset_t *) &b_sram, sram_len) - != KERN_SUCCESS) { - printf("pc%d: can not allocate memory for sram.\n", unit); - return 0; - } - (void)pmap_map(b_prom, (vm_offset_t)addr, - (vm_offset_t)addr+len, - VM_PROT_READ | VM_PROT_WRITE); - if ((int)addr > 0x100000) /* stupid hardware */ - addr += EXTENDED_ADDR; - addr += 0x4000; /* sram space */ - (void)pmap_map(b_sram, (vm_offset_t)addr, - (vm_offset_t)addr+sram_len, - VM_PROT_READ | VM_PROT_WRITE); - - *(b_prom + OFFSET_RESET) = 1; - { int i; for (i = 0; i < 1000; i++); /* 4 clocks at 6Mhz */} - *(b_prom + OFFSET_RESET) = 0; - t_ps = (u_short *)(b_sram + OFFSET_SCB); - *(t_ps) = (u_short)0x5a5a; - if (*(t_ps) != (u_short)0x5a5a) { - kmem_free(kernel_map, b_prom, len); - kmem_free(kernel_map, b_sram, sram_len); - return(0); - } - t_ps = (u_short *)(b_prom + + OFFSET_PROM); -#define ETHER0 0x00 -#define ETHER1 0xaa -#define ETHER2 0x00 - if ((t_ps[0]&0xff) == ETHER0 && - (t_ps[1]&0xff) == ETHER1 && - (t_ps[2]&0xff) == ETHER2) - pc_softc[unit].seated = TRUE; -#undef ETHER0 -#undef ETHER1 -#undef ETHER2 -#define ETHER0 0x00 -#define ETHER1 0x00 -#define ETHER2 0x1c - if ((t_ps[0]&0xff) == ETHER0 || - (t_ps[1]&0xff) == ETHER1 || - (t_ps[2]&0xff) == ETHER2) - pc_softc[unit].seated = TRUE; -#undef ETHER0 -#undef ETHER1 -#undef ETHER2 - if (pc_softc[unit].seated != TRUE) { - kmem_free(kernel_map, b_prom, len); - kmem_free(kernel_map, b_sram, sram_len); - return(0); - } - (volatile char *)pc_softc[unit].prom = (volatile char *)b_prom; - (volatile char *)pc_softc[unit].sram = (volatile char *)b_sram; - return(1); -} - -/* - * pc586attach: - * - * This function attaches a PC586 board to the "system". The rest of - * runtime structures are initialized here (this routine is called after - * a successful probe of the board). Once the ethernet address is read - * and stored, the board's ifnet structure is attached and readied. - * - * input : bus_device structure setup in autoconfig - * output : board structs and ifnet is setup - * - */ -void pc586attach(dev) - struct bus_device *dev; -{ - struct ifnet *ifp; - u_char *addr_p; - u_short *b_addr; - u_char unit = (u_char)dev->unit; - pc_softc_t *sp = &pc_softc[unit]; - volatile scb_t *scb_p; - - take_dev_irq(dev); - printf(", port = %x, spl = %d, pic = %d. ", - dev->address, dev->sysdep, dev->sysdep1); - - sp->timer = -1; - sp->flags = 0; - sp->mode = 0; - sp->open = 0; - CMD(RESET, CMD_1, unit); - { int i; for (i = 0; i < 1000; i++); /* 4 clocks at 6Mhz */} - CMD(RESET, CMD_0, unit); - b_addr = (u_short *)(sp->prom + OFFSET_PROM); - addr_p = (u_char *)sp->ds_addr; - addr_p[0] = b_addr[0]; - addr_p[1] = b_addr[1]; - addr_p[2] = b_addr[2]; - addr_p[3] = b_addr[3]; - addr_p[4] = b_addr[4]; - addr_p[5] = b_addr[5]; - printf("ethernet id [%x:%x:%x:%x:%x:%x]", - addr_p[0], addr_p[1], addr_p[2], - addr_p[3], addr_p[4], addr_p[5]); - - scb_p = (volatile scb_t *)(sp->sram + OFFSET_SCB); - scb_p->scb_crcerrs = 0; /* initialize counters */ - scb_p->scb_alnerrs = 0; - scb_p->scb_rscerrs = 0; - scb_p->scb_ovrnerrs = 0; - - ifp = &(sp->ds_if); - ifp->if_unit = unit; - ifp->if_mtu = ETHERMTU; - ifp->if_flags = IFF_BROADCAST; -#ifdef MACH_KERNEL - ifp->if_header_size = sizeof(struct ether_header); - ifp->if_header_format = HDR_ETHERNET; - ifp->if_address_size = 6; - ifp->if_address = (char *)&sp->ds_addr[0]; - if_init_queues(ifp); -#else MACH_KERNEL - ifp->if_name = "pc"; - ifp->if_init = pc586init; - ifp->if_output = pc586output; - ifp->if_ioctl = pc586ioctl; - ifp->if_reset = pc586reset; - ifp->if_next = NULL; - if_attach(ifp); -#endif MACH_KERNEL -} - -/* - * pc586reset: - * - * This routine is in part an entry point for the "if" code. Since most - * of the actual initialization has already (we hope already) been done - * by calling pc586attach(). - * - * input : unit number or board number to reset - * output : board is reset - * - */ -pc586reset(unit) -int unit; -{ - pc_softc[unit].ds_if.if_flags &= ~IFF_RUNNING; - pc_softc[unit].flags &= ~(DSF_LOCK|DSF_RUNNING); - return(pc586init(unit)); - -} - -/* - * pc586init: - * - * Another routine that interfaces the "if" layer to this driver. - * Simply resets the structures that are used by "upper layers". - * As well as calling pc586hwrst that does reset the pc586 board. - * - * input : board number - * output : structures (if structs) and board are reset - * - */ -pc586init(unit) -int unit; -{ - struct ifnet *ifp; - int stat; - spl_t oldpri; - - ifp = &(pc_softc[unit].ds_if); -#ifdef MACH_KERNEL -#else MACH_KERNEL - if (ifp->if_addrlist == (struct ifaddr *)0) { - return; - } -#endif MACH_KERNEL - oldpri = SPLNET(); - if ((stat = pc586hwrst(unit)) == TRUE) { -#ifdef MACH_KERNEL -#undef HZ -#define HZ hz -#endif MACH_KERNEL - timeout(pc586watch, &(ifp->if_unit), 5*HZ); - pc_softc[unit].timer = 5; - - pc_softc[unit].ds_if.if_flags |= IFF_RUNNING; - pc_softc[unit].flags |= DSF_RUNNING; - pc_softc[unit].tbusy = 0; - pc586start(unit); -#if DLI - dli_init(); -#endif DLI - } else - printf("pc%d init(): trouble resetting board.\n", unit); - splx(oldpri); - return(stat); -} - -#ifdef MACH_KERNEL -/*ARGSUSED*/ -pc586open(dev, flag) - dev_t dev; - int flag; -{ - register int unit; - pc_softc_t *sp; - - unit = minor(dev); /* XXX */ - if (unit < 0 || unit >= NPC586 || !pc_softc[unit].seated) - return (ENXIO); - - pc_softc[unit].ds_if.if_flags |= IFF_UP; - pc586init(unit); - return (0); -} -#endif MACH_KERNEL - -/* - * pc586start: - * - * This is yet another interface routine that simply tries to output a - * in an mbuf after a reset. - * - * input : board number - * output : stuff sent to board if any there - * - */ -pc586start(unit) -int unit; -{ -#ifdef MACH_KERNEL - io_req_t m; -#else MACH_KERNEL - struct mbuf *m; -#endif MACH_KERNEL - struct ifnet *ifp; - register pc_softc_t *is = &pc_softc[unit]; - volatile scb_t *scb_p = (volatile scb_t *)(pc_softc[unit].sram + OFFSET_SCB); - - if (is->tbusy) { - if (!(scb_p->scb_status & 0x0700)) { /* ! IDLE */ - is->tbusy = 0; - pc586_cntrs[unit].xmt.busy++; - /* - * This is probably just a race. The xmt'r is just - * became idle but WE have masked interrupts so ... - */ - if (xmt_watch) printf("!!"); - } else - return; - } - - ifp = &(pc_softc[unit].ds_if); - IF_DEQUEUE(&ifp->if_snd, m); -#ifdef MACH_KERNEL - if (m != 0) -#else MACH_KERNEL - if (m != (struct mbuf *)0) -#endif MACH_KERNEL - { - is->tbusy++; - pc586_cntrs[unit].xmt.xmt++; - pc586xmt(unit, m); - } - return; -} - -/* - * pc586read: - * - * This routine does the actual copy of data (including ethernet header - * structure) from the pc586 to an mbuf chain that will be passed up - * to the "if" (network interface) layer. NOTE: we currently - * don't handle trailer protocols, so if that is needed, it will - * (at least in part) be added here. For simplicities sake, this - * routine copies the receive buffers from the board into a local (stack) - * buffer until the frame has been copied from the board. Once in - * the local buffer, the contents are copied to an mbuf chain that - * is then enqueued onto the appropriate "if" queue. - * - * input : board number, and an frame descriptor pointer - * output : the packet is put into an mbuf chain, and passed up - * assumes : if any errors occur, packet is "dropped on the floor" - * - */ -pc586read(unit, fd_p) -int unit; -fd_t *fd_p; -{ - register pc_softc_t *is = &pc_softc[unit]; - register struct ifnet *ifp = &is->ds_if; - struct ether_header eh; -#ifdef MACH_KERNEL - ipc_kmsg_t new_kmsg; - struct ether_header *ehp; - struct packet_header *pkt; - char *dp; -#else MACH_KERNEL - struct mbuf *m, *tm; -#endif MACH_KERNEL - rbd_t *rbd_p; - u_char *buffer_p; - u_char *mb_p; - u_short mlen, len, clen; - u_short bytes_in_msg, bytes_in_mbuf, bytes; - - - if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { - printf("pc%d read(): board is not running.\n", ifp->if_unit); - pc586intoff(ifp->if_unit); - } - pc586_cntrs[unit].rcv.rcv++; -#ifdef MACH_KERNEL - new_kmsg = net_kmsg_get(); - if (new_kmsg == IKM_NULL) { - /* - * Drop the received packet. - */ - is->ds_if.if_rcvdrops++; - - /* - * not only do we want to return, we need to drop the packet on - * the floor to clear the interrupt. - */ - return 1; - } - ehp = (struct ether_header *) (&net_kmsg(new_kmsg)->header[0]); - pkt = (struct packet_header *)(&net_kmsg(new_kmsg)->packet[0]); - - /* - * Get ether header. - */ - ehp->ether_type = fd_p->length; - len = sizeof(struct ether_header); - bcopy16(fd_p->source, ehp->ether_shost, ETHER_ADD_SIZE); - bcopy16(fd_p->destination, ehp->ether_dhost, ETHER_ADD_SIZE); - - /* - * Get packet body. - */ - dp = (char *)(pkt + 1); - - rbd_p = (rbd_t *)ram_to_ptr(fd_p->rbd_offset, unit); - if (rbd_p == 0) { - printf("pc%d read(): Invalid buffer\n", unit); - if (pc586hwrst(unit) != TRUE) { - printf("pc%d read(): hwrst trouble.\n", unit); - } - net_kmsg_put(new_kmsg); - return 0; - } - - do { - buffer_p = (u_char *)(pc_softc[unit].sram + rbd_p->buffer_addr); - bytes_in_msg = rbd_p->status & RBD_SW_COUNT; - bcopy16((u_short *)buffer_p, - (u_short *)dp, - (bytes_in_msg + 1) & ~1); /* but we know it's even */ - len += bytes_in_msg; - dp += bytes_in_msg; - if (rbd_p->status & RBD_SW_EOF) - break; - rbd_p = (rbd_t *)ram_to_ptr(rbd_p->next_rbd_offset, unit); - } while ((int) rbd_p); - - pkt->type = ehp->ether_type; - pkt->length = - len - sizeof(struct ether_header) - + sizeof(struct packet_header); - - /* - * Send the packet to the network module. - */ - net_packet(ifp, new_kmsg, pkt->length, ethernet_priority(new_kmsg)); - return 1; -#else MACH_KERNEL - eh.ether_type = ntohs(fd_p->length); - bcopy16(fd_p->source, eh.ether_shost, ETHER_ADD_SIZE); - bcopy16(fd_p->destination, eh.ether_dhost, ETHER_ADD_SIZE); - - if ((rbd_p =(rbd_t *)ram_to_ptr(fd_p->rbd_offset, unit))== (rbd_t *)NULL) { - printf("pc%d read(): Invalid buffer\n", unit); - if (pc586hwrst(unit) != TRUE) { - printf("pc%d read(): hwrst trouble.\n", unit); - } - return 0; - } - - bytes_in_msg = rbd_p->status & RBD_SW_COUNT; - buffer_p = (u_char *)(pc_softc[unit].sram + rbd_p->buffer_addr); - MGET(m, M_DONTWAIT, MT_DATA); - tm = m; - if (m == (struct mbuf *)0) { - /* - * not only do we want to return, we need to drop the packet on - * the floor to clear the interrupt. - * - */ - printf("pc%d read(): No mbuf 1st\n", unit); - if (pc586hwrst(unit) != TRUE) { - pc586intoff(unit); - printf("pc%d read(): hwrst trouble.\n", unit); - pc_softc[unit].timer = 0; - } - return 0; - } -m->m_next = (struct mbuf *) 0; - m->m_len = MLEN; - if (bytes_in_msg > 2 * MLEN - sizeof (struct ifnet **)) { - MCLGET(m); - } - /* - * first mbuf in the packet must contain a pointer to the - * ifnet structure. other mbufs that follow and make up - * the packet do not need this pointer in the mbuf. - * - */ - *(mtod(tm, struct ifnet **)) = ifp; - mlen = sizeof (struct ifnet **); - clen = mlen; - bytes_in_mbuf = m->m_len - sizeof(struct ifnet **); - mb_p = mtod(tm, u_char *) + sizeof (struct ifnet **); - bytes = min(bytes_in_mbuf, bytes_in_msg); - do { - if (bytes & 1) - len = bytes + 1; - else - len = bytes; - bcopy16(buffer_p, mb_p, len); - clen += bytes; - mlen += bytes; - - if (!(bytes_in_mbuf -= bytes)) { - MGET(tm->m_next, M_DONTWAIT, MT_DATA); - tm = tm->m_next; - if (tm == (struct mbuf *)0) { - m_freem(m); - printf("pc%d read(): No mbuf nth\n", unit); - if (pc586hwrst(unit) != TRUE) { - pc586intoff(unit); - printf("pc%d read(): hwrst trouble.\n", unit); - pc_softc[unit].timer = 0; - } - return 0; - } - mlen = 0; - tm->m_len = MLEN; - bytes_in_mbuf = MLEN; - mb_p = mtod(tm, u_char *); - } else - mb_p += bytes; - - if (!(bytes_in_msg -= bytes)) { - if (rbd_p->status & RBD_SW_EOF || - (rbd_p = (rbd_t *)ram_to_ptr(rbd_p->next_rbd_offset, unit)) == - NULL) { - tm->m_len = mlen; - break; - } else { - bytes_in_msg = rbd_p->status & RBD_SW_COUNT; - buffer_p = (u_char *)(pc_softc[unit].sram + rbd_p->buffer_addr); - } - } else - buffer_p += bytes; - - bytes = min(bytes_in_mbuf, bytes_in_msg); - } while(1); -#ifdef IF_CNTRS -/* clen -= (sizeof (struct ifnet **) - clen += 4 /* crc */; - clen += sizeof (struct ether_header); - pc586_ein[log_2(clen)]++; - if (clen < 128) pc586_lin[clen>>3]++; - - if (eh.ether_type == ETHERTYPE_ARP) { - pc586_arp++; - if (pc586_narp) { - pc586_ein[log_2(clen)]--; - if (clen < 128) pc586_lin[clen>>3]--; - } - } -#endif IF_CNTRS - /* - * received packet is now in a chain of mbuf's. next step is - * to pass the packet upwards. - * - */ - pc586send_packet_up(m, &eh, is); - return 1; -#endif MACH_KERNEL -} - -/* - * Send a packet composed of an mbuf chain to the higher levels - * - */ -#ifndef MACH_KERNEL -pc586send_packet_up(m, eh, is) -struct mbuf *m; -struct ether_header *eh; -pc_softc_t *is; -{ - register struct ifqueue *inq; - spl_t opri; - - switch (eh->ether_type) { -#ifdef INET - case ETHERTYPE_IP: - schednetisr(NETISR_IP); - inq = &ipintrq; - break; - case ETHERTYPE_ARP: - arpinput(&is->pc586_ac, m); - return; -#endif -#ifdef NS - case ETHERTYPE_NS: - schednetisr(NETISR_NS); - inq = &nsintrq; - break; -#endif - default: -#if DLI - { - eh.ether_type = htons(eh.ether_type); - dli_input(m,eh.ether_type,&eh.ether_shost[0], - &de_dlv[ds->ds_if.if_unit], &eh); - } -#else DLI - m_freem(m); -#endif DLI - return; - } - opri = SPLNET(); - if (IF_QFULL(inq)) { - IF_DROP(inq); - splx(opri); - m_freem(m); - return; - } - IF_ENQUEUE(inq, m); - splx(opri); - return; -} -#endif MACH_KERNEL - -#ifdef MACH_KERNEL -pc586output(dev, ior) - dev_t dev; - io_req_t ior; -{ - register int unit; - - unit = minor(dev); /* XXX */ - if (unit < 0 || unit >= NPC586 || !pc_softc[unit].seated) - return (ENXIO); - - return (net_write(&pc_softc[unit].ds_if, pc586start, ior)); -} - -pc586setinput(dev, receive_port, priority, filter, filter_count) - dev_t dev; - mach_port_t receive_port; - int priority; - filter_t filter[]; - unsigned int filter_count; -{ - register int unit = minor(dev); - if (unit < 0 || unit >= NPC586 || !pc_softc[unit].seated) - return (ENXIO); - - return (net_set_filter(&pc_softc[unit].ds_if, - receive_port, priority, - filter, filter_count)); -} -#else MACH_KERNEL -/* - * pc586output: - * - * This routine is called by the "if" layer to output a packet to - * the network. This code resolves the local ethernet address, and - * puts it into the mbuf if there is room. If not, then a new mbuf - * is allocated with the header information and precedes the data - * to be transmitted. The routines that actually transmit the - * data (pc586xmt()) expect the ethernet structure to precede - * the data in the mbuf. This information is required by the - * 82586's transfer command segment, and thus mbuf's cannot - * be simply "slammed" out onto the network. - * - * input: ifnet structure pointer, an mbuf with data, and address - * to be resolved - * output: mbuf is updated to hold enet address, or a new mbuf - * with the address is added - * - */ -pc586output(ifp, m0, dst) -struct ifnet *ifp; -struct mbuf *m0; -struct sockaddr *dst; -{ - register pc_softc_t *is = &pc_softc[ifp->if_unit]; - register struct mbuf *m = m0; - int type, error; - spl_t opri; - u_char edst[6]; - struct in_addr idst; - register struct ether_header *eh; - register int off; - int usetrailers; - - if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { - printf("pc%d output(): board is not running.\n", ifp->if_unit); - pc586intoff(ifp->if_unit); - error = ENETDOWN; - goto bad; - } - switch (dst->sa_family) { - -#ifdef INET - case AF_INET: - idst = ((struct sockaddr_in *)dst)->sin_addr; - if (!arpresolve(&is->pc586_ac, m, &idst, edst, &usetrailers)){ - return (0); /* if not yet resolved */ - } - off = ntohs((u_short)mtod(m, struct ip *)->ip_len) - m->m_len; - - if (usetrailers && off > 0 && (off & 0x1ff) == 0 && - m->m_off >= MMINOFF + 2 * sizeof (u_short)) { - type = ETHERTYPE_TRAIL + (off>>9); - m->m_off -= 2 * sizeof (u_short); - m->m_len += 2 * sizeof (u_short); - *mtod(m, u_short *) = htons((u_short)ETHERTYPE_IP); - *(mtod(m, u_short *) + 1) = htons((u_short)m->m_len); - goto gottrailertype; - } - type = ETHERTYPE_IP; - off = 0; - goto gottype; -#endif -#ifdef NS - case AF_NS: - type = ETHERTYPE_NS; - bcopy((caddr_t)&(((struct sockaddr_ns *)dst)->sns_addr.x_host), - (caddr_t)edst, sizeof (edst)); - off = 0; - goto gottype; -#endif - -#if DLI - case AF_DLI: - if (m->m_len < sizeof(struct ether_header)) - { - error = EMSGSIZE; - goto bad; - } - eh = mtod(m, struct ether_header *); - bcopy(dst->sa_data, (caddr_t)eh->ether_dhost, - sizeof (eh->ether_dhost)); - goto gotheader; -#endif DLI - - case AF_UNSPEC: - eh = (struct ether_header *)dst->sa_data; - bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); - type = eh->ether_type; - goto gottype; - - default: - printf("pc%d output(): can't handle af%d\n", - ifp->if_unit, dst->sa_family); - error = EAFNOSUPPORT; - goto bad; - } - -gottrailertype: - /* - * Packet to be sent as trailer: move first packet - * (control information) to end of chain. - */ - while (m->m_next) - m = m->m_next; - m->m_next = m0; - m = m0->m_next; - m0->m_next = 0; - m0 = m; - -gottype: - /* - * Add local net header. If no space in first mbuf, - * allocate another. - */ - if (m->m_off > MMAXOFF || - MMINOFF + sizeof (struct ether_header) > m->m_off) { - m = m_get(M_DONTWAIT, MT_HEADER); - if (m == 0) { - error = ENOBUFS; - goto bad; - } - m->m_next = m0; - m->m_off = MMINOFF; - m->m_len = sizeof (struct ether_header); - } else { - m->m_off -= sizeof (struct ether_header); - m->m_len += sizeof (struct ether_header); - } - eh = mtod(m, struct ether_header *); - eh->ether_type = htons((u_short)type); - bcopy((caddr_t)edst, (caddr_t)eh->ether_dhost, sizeof (edst)); - bcopy((caddr_t)is->ds_addr,(caddr_t)eh->ether_shost, sizeof(edst)); -#if DLI -gotheader: -#endif DLI - - /* - * Queue message on interface, and start output if interface - * not yet active. - */ - opri = SPLNET(); - if (IF_QFULL(&ifp->if_snd)) { - IF_DROP(&ifp->if_snd); - splx(opri); - m_freem(m); - return (ENOBUFS); - } - IF_ENQUEUE(&ifp->if_snd, m); - /* - * Some action needs to be added here for checking whether the - * board is already transmitting. If it is, we don't want to - * start it up (ie call pc586start()). We will attempt to send - * packets that are queued up after an interrupt occurs. Some - * flag checking action has to happen here and/or in the start - * routine. This note is here to remind me that some thought - * is needed and there is a potential problem here. - * - */ - pc586start(ifp->if_unit); - splx(opri); - return (0); -bad: - m_freem(m0); - return (error); -} -#endif MACH_KERNEL - -#ifdef MACH_KERNEL -pc586getstat(dev, flavor, status, count) - dev_t dev; - int flavor; - dev_status_t status; /* pointer to OUT array */ - unsigned int *count; /* out */ -{ - register int unit = minor(dev); - register pc_softc_t *sp; - - if (unit < 0 || unit >= NPC586 || !pc_softc[unit].seated) - return (ENXIO); - - sp = &pc_softc[unit]; - return (net_getstat(&sp->ds_if, flavor, status, count)); -} - -pc586setstat(dev, flavor, status, count) - dev_t dev; - int flavor; - dev_status_t status; - unsigned int count; -{ - register int unit = minor(dev); - register pc_softc_t *sp; - - if (unit < 0 || unit >= NPC586 || !pc_softc[unit].seated) - return (ENXIO); - - sp = &pc_softc[unit]; - - switch (flavor) { - case NET_STATUS: - { - /* - * All we can change are flags, and not many of those. - */ - register struct net_status *ns = (struct net_status *)status; - int mode = 0; - - if (count < NET_STATUS_COUNT) - return (D_INVALID_OPERATION); - - if (ns->flags & IFF_ALLMULTI) - mode |= MOD_ENAL; - if (ns->flags & IFF_PROMISC) - mode |= MOD_PROM; - - /* - * Force a complete reset if the receive mode changes - * so that these take effect immediately. - */ - if (sp->mode != mode) { - sp->mode = mode; - if (sp->flags & DSF_RUNNING) { - sp->flags &= ~(DSF_LOCK|DSF_RUNNING); - pc586init(unit); - } - } - break; - } - - default: - return (D_INVALID_OPERATION); - } - return (D_SUCCESS); - -} -#else MACH_KERNEL -/* - * pc586ioctl: - * - * This routine processes an ioctl request from the "if" layer - * above. - * - * input : pointer the appropriate "if" struct, command, and data - * output : based on command appropriate action is taken on the - * pc586 board(s) or related structures - * return : error is returned containing exit conditions - * - */ -pc586ioctl(ifp, cmd, data) -struct ifnet *ifp; -int cmd; -caddr_t data; -{ - register struct ifaddr *ifa = (struct ifaddr *)data; - int unit = ifp->if_unit; - register pc_softc_t *is = &pc_softc[unit]; - short mode = 0; - int error = 0; - spl_t opri; - - opri = SPLNET(); - switch (cmd) { - case SIOCSIFADDR: - ifp->if_flags |= IFF_UP; - pc586init(unit); - switch (ifa->ifa_addr.sa_family) { -#ifdef INET - case AF_INET: - ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr; - arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); - break; -#endif -#ifdef NS - case AF_NS: - { - register struct ns_addr *ina = - &(IA_SNS(ifa)->sns_addr); - if (ns_nullhost(*ina)) - ina->x_host = *(union ns_host *)(ds->ds_addr); - else - pc586setaddr(ina->x_host.c_host, unit); - break; - } -#endif - } - break; - case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_ALLMULTI) - mode |= MOD_ENAL; - if (ifp->if_flags & IFF_PROMISC) - mode |= MOD_PROM; - /* - * force a complete reset if the receive multicast/ - * promiscuous mode changes so that these take - * effect immediately. - * - */ - if (is->mode != mode) { - is->mode = mode; - if (is->flags & DSF_RUNNING) { - is->flags &= ~(DSF_LOCK|DSF_RUNNING); - pc586init(unit); - } - } - if ((ifp->if_flags & IFF_UP) == 0 && is->flags & DSF_RUNNING) { - printf("pc%d ioctl(): board is not running\n", unit); - is->flags &= ~(DSF_LOCK | DSF_RUNNING); - is->timer = -1; - pc586intoff(unit); - } else if (ifp->if_flags & IFF_UP && (is->flags & DSF_RUNNING) == 0) { - pc586init(unit); - } - break; -#ifdef IF_CNTRS - case SIOCCIFCNTRS: - if (!suser()) { - error = EPERM; - break; - } - bzero((caddr_t)pc586_ein, sizeof (pc586_ein)); - bzero((caddr_t)pc586_eout, sizeof (pc586_eout)); - bzero((caddr_t)pc586_lin, sizeof (pc586_lin)); - bzero((caddr_t)pc586_lout, sizeof (pc586_lout)); - bzero((caddr_t)&pc586_arp, sizeof (int)); - bzero((caddr_t)&pc586_cntrs, sizeof (pc586_cntrs)); - break; -#endif IF_CNTRS - default: - error = EINVAL; - } - splx(opri); - return (error); -} -#endif MACH_KERNEL - -/* - * pc586hwrst: - * - * This routine resets the pc586 board that corresponds to the - * board number passed in. - * - * input : board number to do a hardware reset - * output : board is reset - * - */ -pc586hwrst(unit) -int unit; -{ - CMD(CHANATT, CMD_0, unit); - CMD(RESET, CMD_1, unit); - { int i; for (i = 0; i < 1000; i++); /* 4 clocks at 6Mhz */} - CMD(RESET,CMD_0, unit); - -/* - * for (i = 0; i < 1000000; i++); - * with this loop above and with the reset toggle also looping to - * 1000000. We don't see the reset behaving as advertised. DOES - * IT HAPPEN AT ALL. In particular, NORMODE, ENABLE, and XFER - * should all be zero and they have not changed at all. - */ - CMD(INTENAB, CMD_0, unit); - CMD(NORMMODE, CMD_0, unit); - CMD(XFERMODE, CMD_1, unit); - - pc586bldcu(unit); - - if (pc586diag(unit) == FALSE) - return(FALSE); - - if (pc586config(unit) == FALSE) - return(FALSE); - /* - * insert code for loopback test here - * - */ - pc586rustrt(unit); - - pc586inton(unit); - CMD(NORMMODE, CMD_1, unit); - return(TRUE); -} - -/* - * pc586watch(): - * - * This routine is the watchdog timer routine for the pc586 chip. If - * chip wedges, this routine will fire and cause a board reset and - * begin again. - * - * input : which board is timing out - * output : potential board reset if wedged - * - */ -int watch_dead = 0; -pc586watch(b_ptr) -caddr_t b_ptr; -{ - spl_t opri; - int unit = *b_ptr; - - if ((pc_softc[unit].ds_if.if_flags & IFF_UP) == 0) { - return; - } - if (pc_softc[unit].timer == -1) { - timeout(pc586watch, b_ptr, 5*HZ); - return; - } - if (--pc_softc[unit].timer != -1) { - timeout(pc586watch, b_ptr, 1*HZ); - return; - } - - opri = SPLNET(); -#ifdef notdef - printf("pc%d watch(): 6sec timeout no %d\n", unit, ++watch_dead); -#endif notdef - pc586_cntrs[unit].watch++; - if (pc586hwrst(unit) != TRUE) { - printf("pc%d watch(): hwrst trouble.\n", unit); - pc_softc[unit].timer = 0; - } else { - timeout(pc586watch, b_ptr, 1*HZ); - pc_softc[unit].timer = 5; - } - splx(opri); -} - -/* - * pc586intr: - * - * This function is the interrupt handler for the pc586 ethernet - * board. This routine will be called whenever either a packet - * is received, or a packet has successfully been transfered and - * the unit is ready to transmit another packet. - * - * input : board number that interrupted - * output : either a packet is received, or a packet is transfered - * - */ -pc586intr(unit) -int unit; -{ - volatile scb_t *scb_p = (volatile scb_t *)(pc_softc[unit].sram + OFFSET_SCB); - volatile ac_t *cb_p = (volatile ac_t *)(pc_softc[unit].sram + OFFSET_CU); - int next, x; - int i; - u_short int_type; - - if (pc_softc[unit].seated == FALSE) { - printf("pc%d intr(): board not seated\n", unit); - return(-1); - } - - while ((int_type = (scb_p->scb_status & SCB_SW_INT)) != 0) { - pc586ack(unit); - if (int_type & SCB_SW_FR) { - pc586rcv(unit); - watch_dead=0; - } - if (int_type & SCB_SW_RNR) { - pc586_cntrs[unit].rcv.ovw++; -#ifdef notdef - printf("pc%d intr(): receiver overrun! begin_fd = %x\n", - unit, pc_softc[unit].begin_fd); -#endif notdef - pc586rustrt(unit); - } - if (int_type & SCB_SW_CNA) { - /* - * At present, we don't care about CNA's. We - * believe they are a side effect of XMT. - */ - } - if (int_type & SCB_SW_CX) { - /* - * At present, we only request Interrupt for - * XMT. - */ - if ((!(cb_p->ac_status & AC_SW_OK)) || - (cb_p->ac_status & (0xfff^TC_SQE))) { - if (cb_p->ac_status & TC_DEFER) { - if (xmt_watch) printf("DF"); - pc586_cntrs[unit].xmt.defer++; - } else if (cb_p->ac_status & (TC_COLLISION|0xf)) { - if (xmt_watch) printf("%x",cb_p->ac_status & 0xf); - } else if (xmt_watch) - printf("pc%d XMT: %x %x\n", - unit, cb_p->ac_status, cb_p->ac_command); - } - pc586_cntrs[unit].xmt.xmti++; - pc_softc[unit].tbusy = 0; - pc586start(unit); - } - pc_softc[unit].timer = 5; - } - return(0); -} - -/* - * pc586rcv: - * - * This routine is called by the interrupt handler to initiate a - * packet transfer from the board to the "if" layer above this - * driver. This routine checks if a buffer has been successfully - * received by the pc586. If so, the routine pc586read is called - * to do the actual transfer of the board data (including the - * ethernet header) into a packet (consisting of an mbuf chain). - * - * input : number of the board to check - * output : if a packet is available, it is "sent up" - * - */ -pc586rcv(unit) -int unit; -{ - fd_t *fd_p; - - for (fd_p = pc_softc[unit].begin_fd; fd_p != (fd_t *)NULL; - fd_p = pc_softc[unit].begin_fd) { - if (fd_p->status == 0xffff || fd_p->rbd_offset == 0xffff) { - if (pc586hwrst(unit) != TRUE) - printf("pc%d rcv(): hwrst ffff trouble.\n", - unit); - return; - } else if (fd_p->status & AC_SW_C) { - fd_t *bfd = (fd_t *)ram_to_ptr(fd_p->link_offset, unit); - - if (fd_p->status == (RFD_DONE|RFD_RSC)) { - /* lost one */; -#ifdef notdef - printf("pc%d RCV: RSC %x\n", - unit, fd_p->status); -#endif notdef - pc586_cntrs[unit].rcv.partial++; - } else if (!(fd_p->status & RFD_OK)) - printf("pc%d RCV: !OK %x\n", - unit, fd_p->status); - else if (fd_p->status & 0xfff) - printf("pc%d RCV: ERRs %x\n", - unit, fd_p->status); - else - if (!pc586read(unit, fd_p)) - return; - if (!pc586requeue(unit, fd_p)) { /* abort on chain error */ - if (pc586hwrst(unit) != TRUE) - printf("pc%d rcv(): hwrst trouble.\n", unit); - return; - } - pc_softc[unit].begin_fd = bfd; - } else - break; - } - return; -} - -/* - * pc586requeue: - * - * This routine puts rbd's used in the last receive back onto the - * free list for the next receive. - * - */ -pc586requeue(unit, fd_p) -int unit; -fd_t *fd_p; -{ - rbd_t *l_rbdp; - rbd_t *f_rbdp; - -#ifndef REQUEUE_DBG - if (bad_rbd_chain(fd_p->rbd_offset, unit)) - return 0; -#endif REQUEUE_DBG - f_rbdp = (rbd_t *)ram_to_ptr(fd_p->rbd_offset, unit); - if (f_rbdp != NULL) { - l_rbdp = f_rbdp; - while ( (!(l_rbdp->status & RBD_SW_EOF)) && - (l_rbdp->next_rbd_offset != 0xffff)) - { - l_rbdp->status = 0; - l_rbdp = (rbd_t *)ram_to_ptr(l_rbdp->next_rbd_offset, - unit); - } - l_rbdp->next_rbd_offset = PC586NULL; - l_rbdp->status = 0; - l_rbdp->size |= AC_CW_EL; - pc_softc[unit].end_rbd->next_rbd_offset = - ptr_to_ram((char *)f_rbdp, unit); - pc_softc[unit].end_rbd->size &= ~AC_CW_EL; - pc_softc[unit].end_rbd= l_rbdp; - } - - fd_p->status = 0; - fd_p->command = AC_CW_EL; - fd_p->link_offset = PC586NULL; - fd_p->rbd_offset = PC586NULL; - - pc_softc[unit].end_fd->link_offset = ptr_to_ram((char *)fd_p, unit); - pc_softc[unit].end_fd->command = 0; - pc_softc[unit].end_fd = fd_p; - - return 1; -} - -/* - * pc586xmt: - * - * This routine fills in the appropriate registers and memory - * locations on the PC586 board and starts the board off on - * the transmit. - * - * input : board number of interest, and a pointer to the mbuf - * output : board memory and registers are set for xfer and attention - * - */ -#ifdef DEBUG -int xmt_debug = 0; -#endif DEBUG -pc586xmt(unit, m) -int unit; -#ifdef MACH_KERNEL -io_req_t m; -#else MACH_KERNEL -struct mbuf *m; -#endif MACH_KERNEL -{ - pc_softc_t *is = &pc_softc[unit]; - register u_char *xmtdata_p = (u_char *)(is->sram + OFFSET_TBUF); - register u_short *xmtshort_p; -#ifdef MACH_KERNEL - register struct ether_header *eh_p = (struct ether_header *)m->io_data; -#else MACH_KERNEL - struct mbuf *tm_p = m; - register struct ether_header *eh_p = mtod(m, struct ether_header *); - u_char *mb_p = mtod(m, u_char *) + sizeof(struct ether_header); - u_short count = m->m_len - sizeof(struct ether_header); -#endif MACH_KERNEL - volatile scb_t *scb_p = (volatile scb_t *)(is->sram + OFFSET_SCB); - volatile ac_t *cb_p = (volatile ac_t *)(is->sram + OFFSET_CU); - tbd_t *tbd_p = (tbd_t *)(is->sram + OFFSET_TBD); - u_short tbd = OFFSET_TBD; - u_short len, clen = 0; - - cb_p->ac_status = 0; - cb_p->ac_command = (AC_CW_EL|AC_TRANSMIT|AC_CW_I); - cb_p->ac_link_offset = PC586NULL; - cb_p->cmd.transmit.tbd_offset = OFFSET_TBD; - - bcopy16(eh_p->ether_dhost, cb_p->cmd.transmit.dest_addr, ETHER_ADD_SIZE); - cb_p->cmd.transmit.length = (u_short)(eh_p->ether_type); - -#ifndef MACH_KERNEL -#ifdef DEBUG - if (xmt_debug) - printf("XMT mbuf: L%d @%x ", count, mb_p); -#endif DEBUG -#endif MACH_KERNEL - tbd_p->act_count = 0; - tbd_p->buffer_base = 0; - tbd_p->buffer_addr = ptr_to_ram(xmtdata_p, unit); -#ifdef MACH_KERNEL - { int Rlen, Llen; - clen = m->io_count - sizeof(struct ether_header); - Llen = clen & 1; - Rlen = ((int)(m->io_data + sizeof(struct ether_header))) & 1; - - bcopy16(m->io_data + sizeof(struct ether_header) - Rlen, - xmtdata_p, - clen + (Rlen + Llen) ); - xmtdata_p += clen + Llen; - tbd_p->act_count = clen; - tbd_p->buffer_addr += Rlen; - } -#else MACH_KERNEL - do { - if (count) { - if (clen + count > ETHERMTU) - break; - if (count & 1) - len = count + 1; - else - len = count; - bcopy16(mb_p, xmtdata_p, len); - clen += count; - tbd_p->act_count += count; - xmtdata_p += len; - if ((tm_p = tm_p->m_next) == (struct mbuf *)0) - break; - if (count & 1) { - /* go to the next descriptor */ - tbd_p++->next_tbd_offset = (tbd += sizeof (tbd_t)); - tbd_p->act_count = 0; - tbd_p->buffer_base = 0; - tbd_p->buffer_addr = ptr_to_ram(xmtdata_p, unit); - /* at the end -> coallesce remaining mbufs */ - if (tbd == OFFSET_TBD + (N_TBD-1) * sizeof (tbd_t)) { - pc586sftwsleaze(&count, &mb_p, &tm_p, unit); - continue; - } - /* next mbuf short -> coallesce as needed */ - if ( (tm_p->m_next == (struct mbuf *) 0) || -#define HDW_THRESHOLD 55 - tm_p->m_len > HDW_THRESHOLD) - /* ok */; - else { - pc586hdwsleaze(&count, &mb_p, &tm_p, unit); - continue; - } - } - } else if ((tm_p = tm_p->m_next) == (struct mbuf *)0) - break; - count = tm_p->m_len; - mb_p = mtod(tm_p, u_char *); -#ifdef DEBUG - if (xmt_debug) - printf("mbuf+ L%d @%x ", count, mb_p); -#endif DEBUG - } while (1); -#endif MACH_KERNEL -#ifdef DEBUG - if (xmt_debug) - printf("CLEN = %d\n", clen); -#endif DEBUG - if (clen < ETHERMIN) { - tbd_p->act_count += ETHERMIN - clen; - for (xmtshort_p = (u_short *)xmtdata_p; - clen < ETHERMIN; - clen += 2) *xmtshort_p++ = 0; - } - tbd_p->act_count |= TBD_SW_EOF; - tbd_p->next_tbd_offset = PC586NULL; -#ifdef IF_CNTRS - clen += sizeof (struct ether_header) + 4 /* crc */; - pc586_eout[log_2(clen)]++; - if (clen < 128) pc586_lout[clen>>3]++; -#endif IF_CNTRS -#ifdef DEBUG - if (xmt_debug) { - pc586tbd(unit); - printf("\n"); - } -#endif DEBUG - - while (scb_p->scb_command) ; - scb_p->scb_command = SCB_CU_STRT; - pc586chatt(unit); - -#ifdef MACH_KERNEL - iodone(m); -#else MACH_KERNEL - for (count=0; ((count < 6) && (eh_p->ether_dhost[count] == 0xff)); count++) ; - if (count == 6) { - pc586send_packet_up(m, eh_p, is); - } else - m_freem(m); -#endif MACH_KERNEL - return; -} - -/* - * pc586bldcu: - * - * This function builds up the command unit structures. It inits - * the scp, iscp, scb, cb, tbd, and tbuf. - * - */ -pc586bldcu(unit) -{ - char *sram = pc_softc[unit].sram; - scp_t *scp_p = (scp_t *)(sram + OFFSET_SCP); - iscp_t *iscp_p = (iscp_t *)(sram + OFFSET_ISCP); - volatile scb_t *scb_p = (volatile scb_t *)(sram + OFFSET_SCB); - volatile ac_t *cb_p = (volatile ac_t *)(sram + OFFSET_CU); - tbd_t *tbd_p = (tbd_t *)(sram + OFFSET_TBD); - int i; - - scp_p->scp_sysbus = 0; - scp_p->scp_iscp = OFFSET_ISCP; - scp_p->scp_iscp_base = 0; - - iscp_p->iscp_busy = 1; - iscp_p->iscp_scb_offset = OFFSET_SCB; - iscp_p->iscp_scb = 0; - iscp_p->iscp_scb_base = 0; - - pc586_cntrs[unit].rcv.crc += scb_p->scb_crcerrs; - pc586_cntrs[unit].rcv.frame += scb_p->scb_alnerrs; - pc586_cntrs[unit].rcv.rscerrs += scb_p->scb_rscerrs; - pc586_cntrs[unit].rcv.ovrnerrs += scb_p->scb_ovrnerrs; - scb_p->scb_status = 0; - scb_p->scb_command = 0; - scb_p->scb_cbl_offset = OFFSET_CU; - scb_p->scb_rfa_offset = OFFSET_RU; - scb_p->scb_crcerrs = 0; - scb_p->scb_alnerrs = 0; - scb_p->scb_rscerrs = 0; - scb_p->scb_ovrnerrs = 0; - - scb_p->scb_command = SCB_RESET; - pc586chatt(unit); - for (i = 1000000; iscp_p->iscp_busy && (i-- > 0); ); - if (!i) printf("pc%d bldcu(): iscp_busy timeout.\n", unit); - for (i = STATUS_TRIES; i-- > 0; ) { - if (scb_p->scb_status == (SCB_SW_CX|SCB_SW_CNA)) - break; - } - if (!i) - printf("pc%d bldcu(): not ready after reset.\n", unit); - pc586ack(unit); - - cb_p->ac_status = 0; - cb_p->ac_command = AC_CW_EL; - cb_p->ac_link_offset = OFFSET_CU; - - tbd_p->act_count = 0; - tbd_p->next_tbd_offset = PC586NULL; - tbd_p->buffer_addr = 0; - tbd_p->buffer_base = 0; - return; -} - -/* - * pc586bldru: - * - * This function builds the linear linked lists of fd's and - * rbd's. Based on page 4-32 of 1986 Intel microcom handbook. - * - */ -char * -pc586bldru(unit) -int unit; -{ - fd_t *fd_p = (fd_t *)(pc_softc[unit].sram + OFFSET_RU); - ru_t *rbd_p = (ru_t *)(pc_softc[unit].sram + OFFSET_RBD); - int i; - - pc_softc[unit].begin_fd = fd_p; - for(i = 0; i < N_FD; i++, fd_p++) { - fd_p->status = 0; - fd_p->command = 0; - fd_p->link_offset = ptr_to_ram((char *)(fd_p + 1), unit); - fd_p->rbd_offset = PC586NULL; - } - pc_softc[unit].end_fd = --fd_p; - fd_p->link_offset = PC586NULL; - fd_p->command = AC_CW_EL; - fd_p = (fd_t *)(pc_softc[unit].sram + OFFSET_RU); - - fd_p->rbd_offset = ptr_to_ram((char *)rbd_p, unit); - for(i = 0; i < N_RBD; i++, rbd_p = (ru_t *) &(rbd_p->rbuffer[RCVBUFSIZE])) { - rbd_p->r.status = 0; - rbd_p->r.buffer_addr = ptr_to_ram((char *)(rbd_p->rbuffer), - unit); - rbd_p->r.buffer_base = 0; - rbd_p->r.size = RCVBUFSIZE; - if (i != N_RBD-1) { - rbd_p->r.next_rbd_offset=ptr_to_ram(&(rbd_p->rbuffer[RCVBUFSIZE]), - unit); - } else { - rbd_p->r.next_rbd_offset = PC586NULL; - rbd_p->r.size |= AC_CW_EL; - pc_softc[unit].end_rbd = (rbd_t *)rbd_p; - } - } - return (char *)pc_softc[unit].begin_fd; -} - -/* - * pc586rustrt: - * - * This routine starts the receive unit running. First checks if the - * board is actually ready, then the board is instructed to receive - * packets again. - * - */ -pc586rustrt(unit) -int unit; -{ - volatile scb_t *scb_p = (volatile scb_t *)(pc_softc[unit].sram + OFFSET_SCB); - char *strt; - - if ((scb_p->scb_status & SCB_RUS_READY) == SCB_RUS_READY) - return; - - strt = pc586bldru(unit); - scb_p->scb_command = SCB_RU_STRT; - scb_p->scb_rfa_offset = ptr_to_ram(strt, unit); - pc586chatt(unit); - return; -} - -/* - * pc586diag: - * - * This routine does a 586 op-code number 7, and obtains the - * diagnose status for the pc586. - * - */ -pc586diag(unit) -int unit; -{ - volatile scb_t *scb_p = (volatile scb_t *)(pc_softc[unit].sram + OFFSET_SCB); - volatile ac_t *cb_p = (volatile ac_t *)(pc_softc[unit].sram + OFFSET_CU); - int i; - - if (scb_p->scb_status & SCB_SW_INT) { - printf("pc%d diag(): bad initial state %\n", - unit, scb_p->scb_status); - pc586ack(unit); - } - cb_p->ac_status = 0; - cb_p->ac_command = (AC_DIAGNOSE|AC_CW_EL); - scb_p->scb_command = SCB_CU_STRT; - pc586chatt(unit); - - for(i = 0; i < 0xffff; i++) - if ((cb_p->ac_status & AC_SW_C)) - break; - if (i == 0xffff || !(cb_p->ac_status & AC_SW_OK)) { - printf("pc%d: diag failed; status = %x\n", - unit, cb_p->ac_status); - return(FALSE); - } - - if ( (scb_p->scb_status & SCB_SW_INT) && (scb_p->scb_status != SCB_SW_CNA) ) { - printf("pc%d diag(): bad final state %x\n", - unit, scb_p->scb_status); - pc586ack(unit); - } - return(TRUE); -} - -/* - * pc586config: - * - * This routine does a standard config of the pc586 board. - * - */ -pc586config(unit) -int unit; -{ - volatile scb_t *scb_p = (volatile scb_t *)(pc_softc[unit].sram + OFFSET_SCB); - volatile ac_t *cb_p = (volatile ac_t *)(pc_softc[unit].sram + OFFSET_CU); - int i; - - -/* - if ((scb_p->scb_status != SCB_SW_CNA) && (scb_p->scb_status & SCB_SW_INT) ) { - printf("pc%d config(): unexpected initial state %x\n", - unit, scb_p->scb_status); - } -*/ - pc586ack(unit); - - cb_p->ac_status = 0; - cb_p->ac_command = (AC_CONFIGURE|AC_CW_EL); - - /* - * below is the default board configuration from p2-28 from 586 book - */ - cb_p->cmd.configure.fifolim_bytecnt = 0x080c; - cb_p->cmd.configure.addrlen_mode = 0x2600; - cb_p->cmd.configure.linprio_interframe = 0x6000; - cb_p->cmd.configure.slot_time = 0xf200; - cb_p->cmd.configure.hardware = 0x0000; - cb_p->cmd.configure.min_frame_len = 0x0040; - - scb_p->scb_command = SCB_CU_STRT; - pc586chatt(unit); - - for(i = 0; i < 0xffff; i++) - if ((cb_p->ac_status & AC_SW_C)) - break; - if (i == 0xffff || !(cb_p->ac_status & AC_SW_OK)) { - printf("pc%d: config-configure failed; status = %x\n", - unit, cb_p->ac_status); - return(FALSE); - } -/* - if (scb_p->scb_status & SCB_SW_INT) { - printf("pc%d configure(): bad configure state %x\n", - unit, scb_p->scb_status); - pc586ack(unit); - } -*/ - cb_p->ac_status = 0; - cb_p->ac_command = (AC_IASETUP|AC_CW_EL); - - bcopy16(pc_softc[unit].ds_addr, cb_p->cmd.iasetup, ETHER_ADD_SIZE); - - scb_p->scb_command = SCB_CU_STRT; - pc586chatt(unit); - - for (i = 0; i < 0xffff; i++) - if ((cb_p->ac_status & AC_SW_C)) - break; - if (i == 0xffff || !(cb_p->ac_status & AC_SW_OK)) { - printf("pc%d: config-address failed; status = %x\n", - unit, cb_p->ac_status); - return(FALSE); - } -/* - if ((scb_p->scb_status & SCB_SW_INT) != SCB_SW_CNA) { - printf("pc%d configure(): unexpected final state %x\n", - unit, scb_p->scb_status); - } -*/ - pc586ack(unit); - - return(TRUE); -} - -/* - * pc586ack: - */ -pc586ack(unit) -{ - volatile scb_t *scb_p = (volatile scb_t *)(pc_softc[unit].sram + OFFSET_SCB); - int i; - - if (!(scb_p->scb_command = scb_p->scb_status & SCB_SW_INT)) - return; - CMD(CHANATT, 0x0001, unit); - for (i = 1000000; scb_p->scb_command && (i-- > 0); ); - if (!i) - printf("pc%d pc586ack(): board not accepting command.\n", unit); -} - -char * -ram_to_ptr(offset, unit) -int unit; -u_short offset; -{ - if (offset == PC586NULL) - return(NULL); - if (offset > 0x3fff) { - printf("ram_to_ptr(%x, %d)\n", offset, unit); - panic("range"); - return(NULL); - } - return(pc_softc[unit].sram + offset); -} - -#ifndef REQUEUE_DBG -bad_rbd_chain(offset, unit) -{ - rbd_t *rbdp; - char *sram = pc_softc[unit].sram; - - for (;;) { - if (offset == PC586NULL) - return 0; - if (offset > 0x3fff) { - printf("pc%d: bad_rbd_chain offset = %x\n", - unit, offset); - pc586_cntrs[unit].rcv.bad_chain++; - return 1; - } - - rbdp = (rbd_t *)(sram + offset); - offset = rbdp->next_rbd_offset; - } -} -#endif REQUEUE_DBG - -u_short -ptr_to_ram(k_va, unit) -char *k_va; -int unit; -{ - return((u_short)(k_va - pc_softc[unit].sram)); -} - -pc586scb(unit) -{ - volatile scb_t *scb = (volatile scb_t *)(pc_softc[unit].sram + OFFSET_SCB); - volatile u_short*cmd = (volatile u_short *)(pc_softc[unit].prom + OFFSET_NORMMODE); - u_short i; - - i = scb->scb_status; - printf("stat: stat %x, cus %x, rus %x //", - (i&0xf000)>>12, (i&0x0700)>>8, (i&0x0070)>>4); - i = scb->scb_command; - printf(" cmd: ack %x, cuc %x, ruc %x\n", - (i&0xf000)>>12, (i&0x0700)>>8, (i&0x0070)>>4); - - printf("crc %d[%d], align %d[%d], rsc %d[%d], ovr %d[%d]\n", - scb->scb_crcerrs, pc586_cntrs[unit].rcv.crc, - scb->scb_alnerrs, pc586_cntrs[unit].rcv.frame, - scb->scb_rscerrs, pc586_cntrs[unit].rcv.rscerrs, - scb->scb_ovrnerrs, pc586_cntrs[unit].rcv.ovrnerrs); - - printf("cbl %x, rfa %x //", scb->scb_cbl_offset, scb->scb_rfa_offset); - printf(" norm %x, ena %x, xfer %x //", - cmd[0] & 1, cmd[3] & 1, cmd[4] & 1); - printf(" atn %x, reset %x, type %x, stat %x\n", - cmd[1] & 1, cmd[2] & 1, cmd[5] & 1, cmd[6] & 1); -} - -pc586tbd(unit) -{ - pc_softc_t *is = &pc_softc[unit]; - tbd_t *tbd_p = (tbd_t *)(is->sram + OFFSET_TBD); - int i = 0; - int sum = 0; - - do { - sum += (tbd_p->act_count & ~TBD_SW_EOF); - printf("%d: addr %x, count %d (%d), next %x, base %x\n", - i++, tbd_p->buffer_addr, - (tbd_p->act_count & ~TBD_SW_EOF), sum, - tbd_p->next_tbd_offset, - tbd_p->buffer_base); - if (tbd_p->act_count & TBD_SW_EOF) - break; - tbd_p = (tbd_t *)(is->sram + tbd_p->next_tbd_offset); - } while (1); -} - -#ifndef MACH_KERNEL -pc586hdwsleaze(countp, mb_pp, tm_pp, unit) -struct mbuf **tm_pp; -u_char **mb_pp; -u_short *countp; -{ - struct mbuf *tm_p = *tm_pp; - u_char *mb_p = *mb_pp; - u_short count = 0; - u_char *cp; - int len; - - pc586_cntrs[unit].xmt.sleaze++; - /* - * can we get a run that will be coallesced or - * that terminates before breaking - */ - do { - count += tm_p->m_len; - if (tm_p->m_len & 1) - break; - } while ((tm_p = tm_p->m_next) != (struct mbuf *)0); - if ( (tm_p == (struct mbuf *)0) || - count > HDW_THRESHOLD) { - *countp = (*tm_pp)->m_len; - *mb_pp = mtod((*tm_pp), u_char *); - printf("\n"); - return; - } - - /* we need to copy */ - pc586_cntrs[unit].xmt.intrinsic++; - tm_p = *tm_pp; - mb_p = *mb_pp; - count = 0; - cp = (u_char *) t_packet; - do { - bcopy(mtod(tm_p, u_char *), cp, len = tm_p->m_len); - count += len; - if (count > HDW_THRESHOLD) - break; - cp += len; - if (tm_p->m_next == (struct mbuf *)0) - break; - tm_p = tm_p->m_next; - } while (1); - pc586_cntrs[unit].xmt.intrinsic_count += count; - *countp = count; - *mb_pp = (u_char *) t_packet; - *tm_pp = tm_p; - return; -} - -pc586sftwsleaze(countp, mb_pp, tm_pp, unit) -struct mbuf **tm_pp; -u_char **mb_pp; -u_short *countp; -{ - struct mbuf *tm_p = *tm_pp; - u_char *mb_p = *mb_pp; - u_short count = 0; - u_char *cp = (u_char *) t_packet; - int len; - - pc586_cntrs[unit].xmt.chain++; - /* we need to copy */ - do { - bcopy(mtod(tm_p, u_char *), cp, len = tm_p->m_len); - count += len; - cp += len; - if (tm_p->m_next == (struct mbuf *)0) - break; - tm_p = tm_p->m_next; - } while (1); - - *countp = count; - *mb_pp = (u_char *) t_packet; - *tm_pp = tm_p; - return; -} -#endif MACH_KERNEL |