Added NEC PC-9801-83, 84, PC-9801-103, 104, PC-9801N-25 and PC-9801N-J02R

support which use National Semiconductor DP8393X (SONIC) as ethernet
controller. Currently, this driver is used on only PC-98.

Submitted by:	Motomichi Matsuzaki <mzaki@e-mail.ne.jp>
Obtained from:	NetBSD/pc98
This commit is contained in:
Yoshihiro Takahashi 2000-10-02 14:27:20 +00:00
parent 7320fd3a30
commit 0a917604f0
19 changed files with 3648 additions and 0 deletions

View File

@ -118,6 +118,7 @@ static struct _devname {
{ DEVICE_TYPE_NETWORK, "lp", "Parallel Port IP (PLIP) peer connection" },
{ DEVICE_TYPE_NETWORK, "lo", "Loop-back (local) network interface" },
#ifdef PC98
{ DEVICE_TYPE_NETWORK, "snc", "SONIC ethernet card" },
{ DEVICE_TYPE_DISK, "wd%d", "IDE disk device", 3, 65538, 8, 16 },
{ DEVICE_TYPE_CDROM, "wcd%dc", "ATAPI IDE CDROM", 69, 2, 8, 4 },
{ DEVICE_TYPE_FLOPPY, "wfd%d", "ATAPI floppy drive unit A", 87, 0, 8, 4 },

View File

@ -105,6 +105,11 @@ dev/kbd/kbd.c optional kbd
dev/kbd/kbd.c optional sc
dev/kbd/kbd.c optional ukbd
dev/kbd/kbd.c count pckbd
dev/snc/dp83932.c optional snc
dev/snc/dp83932subr.c optional snc
dev/snc/if_snc.c optional snc
dev/snc/if_snc_cbus.c optional snc isa
dev/snc/if_snc_pccard.c optional snc card
dev/syscons/schistory.c count sc
dev/syscons/scmouse.c optional sc
dev/syscons/scterm.c optional sc

1231
sys/dev/snc/dp83932.c Normal file

File diff suppressed because it is too large Load Diff

271
sys/dev/snc/dp83932reg.h Normal file
View File

@ -0,0 +1,271 @@
/* $FreeBSD$ */
/* $NecBSD: dp83932reg.h,v 1.2 1999/02/12 05:50:13 kmatsuda Exp $ */
/* $NetBSD: if_snreg.h,v 1.4 1997/06/15 20:20:12 scottr Exp $ */
/*
* Copyright (c) 1991 Algorithmics Ltd (http://www.algor.co.uk)
* You may use, copy, and modify this program so long as you retain the
* copyright line.
*/
/*
* if_snreg.h -- National Semiconductor DP8393X (SONIC) register defs
*/
/*
* SONIC registers as seen by the processor
*/
#define SNCR_CR 0x00 /* Command */
#define SNCR_DCR 0x01 /* Data Configuration */
#define SNCR_RCR 0x02 /* Receive Control */
#define SNCR_TCR 0x03 /* Transmit Control */
#define SNCR_IMR 0x04 /* Interrupt Mask */
#define SNCR_ISR 0x05 /* Interrupt Status */
#define SNCR_UTDA 0x06 /* Upper Transmit Descriptor Address */
#define SNCR_CTDA 0x07 /* Current Transmit Descriptor Address */
#define SNCR_TPS 0x08 /* Transmit Packet Size */
#define SNCR_TFC 0x09 /* Transmit Fragment Count */
#define SNCR_TSA0 0x0a /* Transmit Start Address 0 */
#define SNCR_TSA1 0x0b /* Transmit Start Address 1 */
#define SNCR_TFS 0x0c /* Transmit Fragment Size */
#define SNCR_URDA 0x0d /* Upper Receive Descriptor Address */
#define SNCR_CRDA 0x0e /* Current Receive Descriptor Address */
#define SNCR_CRBA0 0x0f /* Current Receive Buffer Address 0 */
#define SNCR_CRBA1 0x10 /* Current Receive Buffer Address 1 */
#define SNCR_RBWC0 0x11 /* Remaining Buffer Word Count 0 */
#define SNCR_RBWC1 0x12 /* Remaining Buffer Word Count 1 */
#define SNCR_EOBC 0x13 /* End Of Buffer Word Count */
#define SNCR_URRA 0x14 /* Upper Receive Resource Address */
#define SNCR_RSA 0x15 /* Resource Start Address */
#define SNCR_REA 0x16 /* Resource End Address */
#define SNCR_RRP 0x17 /* Resource Read Pointer */
#define SNCR_RWP 0x18 /* Resource Write Pointer */
#define SNCR_TRBA0 0x19 /* Temporary Receive Buffer Address 0 */
#define SNCR_TRBA1 0x1a /* Temporary Receive Buffer Address 1 */
#define SNCR_TBWC0 0x1b /* Temporary Buffer Word Count 0 */
#define SNCR_TBWC1 0x1c /* Temporary Buffer Word Count 1 */
#define SNCR_ADDR0 0x1d /* Address Generator 0 */
#define SNCR_ADDR1 0x1e /* Address Generator 1 */
#define SNCR_LLFA 0x1f /* Last Link Field Address */
#define SNCR_TTDA 0x20 /* Temp Transmit Descriptor Address */
#define SNCR_CEP 0x21 /* CAM Entry Pointer */
#define SNCR_CAP2 0x22 /* CAM Address Port 2 */
#define SNCR_CAP1 0x23 /* CAM Address Port 1 */
#define SNCR_CAP0 0x24 /* CAM Address Port 0 */
#define SNCR_CE 0x25 /* CAM Enable */
#define SNCR_CDP 0x26 /* CAM Descriptor Pointer */
#define SNCR_CDC 0x27 /* CAM Descriptor Count */
#define SNCR_SR 0x28 /* Silicon Revision */
#define SNCR_WT0 0x29 /* Watchdog Timer 0 */
#define SNCR_WT1 0x2a /* Watchdog Timer 1 */
#define SNCR_RSC 0x2b /* Receive Sequence Counter */
#define SNCR_CRCT 0x2c /* CRC Error Tally */
#define SNCR_FAET 0x2d /* FAE Tally */
#define SNCR_MPT 0x2e /* Missed Packet Tally */
#define SNCR_MDT 0x2f /* Maximum Deferral Timer */
#define SNCR_RTC 0x30 /* Receive Test Control */
#define SNCR_TTC 0x31 /* Transmit Test Control */
#define SNCR_DTC 0x32 /* DMA Test Control */
#define SNCR_CC0 0x33 /* CAM Comparison 0 */
#define SNCR_CC1 0x34 /* CAM Comparison 1 */
#define SNCR_CC2 0x35 /* CAM Comparison 2 */
#define SNCR_CM 0x36 /* CAM Match */
#define SNCR_RES1 0x37 /* reserved */
#define SNCR_RES2 0x38 /* reserved */
#define SNCR_RBC 0x39 /* Receiver Byte Count */
#define SNCR_RES3 0x3a /* reserved */
#define SNCR_TBO 0x3b /* Transmitter Backoff Counter */
#define SNCR_TRC 0x3c /* Transmitter Random Counter */
#define SNCR_TBM 0x3d /* Transmitter Backoff Mask */
#define SNCR_RES4 0x3e /* Reserved */
#define SNCR_DCR2 0x3f /* Data Configuration 2 (AVF) */
#define SNC_NREGS 0x40
/*
* Register Interpretations
*/
/*
* The command register is used for issuing commands to the SONIC.
* With the exception of CR_RST, the bit is reset when the operation
* completes.
*/
#define CR_LCAM 0x0200 /* load CAM with descriptor at s_cdp */
#define CR_RRRA 0x0100 /* read next RRA descriptor at s_rrp */
#define CR_RST 0x0080 /* software reset */
#define CR_ST 0x0020 /* start timer */
#define CR_STP 0x0010 /* stop timer */
#define CR_RXEN 0x0008 /* receiver enable */
#define CR_RXDIS 0x0004 /* receiver disable */
#define CR_TXP 0x0002 /* transmit packets */
#define CR_HTX 0x0001 /* halt transmission */
/*
* The data configuration register establishes the SONIC's bus cycle
* operation. This register can only be accessed when the SONIC is in
* reset mode (s_cr.CR_RST is set.)
*/
#define DCR_EXBUS 0x8000 /* extended bus mode (AVF) */
#define DCR_LBR 0x2000 /* latched bus retry */
#define DCR_PO1 0x1000 /* programmable output 1 */
#define DCR_PO0 0x0800 /* programmable output 0 */
#define DCR_STERM 0x0400 /* synchronous termination */
#define DCR_USR1 0x0200 /* reflects USR1 input pin */
#define DCR_USR0 0x0100 /* reflects USR0 input pin */
#define DCR_WC1 0x0080 /* wait state control 1 */
#define DCR_WC0 0x0040 /* wait state control 0 */
#define DCR_DW 0x0020 /* data width select */
#define DCR_BMS 0x0010 /* DMA block mode select */
#define DCR_RFT1 0x0008 /* receive FIFO threshold control 1 */
#define DCR_RFT0 0x0004 /* receive FIFO threshold control 0 */
#define DCR_TFT1 0x0002 /* transmit FIFO threshold control 1 */
#define DCR_TFT0 0x0001 /* transmit FIFO threshold control 0 */
/* data configuration register aliases */
#define DCR_SYNC DCR_STERM /* synchronous (memory cycle 2 clocks) */
#define DCR_ASYNC 0 /* asynchronous (memory cycle 3 clocks) */
#define DCR_WAIT0 0 /* 0 wait states added */
#define DCR_WAIT1 DCR_WC0 /* 1 wait state added */
#define DCR_WAIT2 DCR_WC1 /* 2 wait states added */
#define DCR_WAIT3 (DCR_WC1|DCR_WC0) /* 3 wait states added */
#define DCR_DW16 0 /* use 16-bit DMA accesses */
#define DCR_DW32 DCR_DW /* use 32-bit DMA accesses */
#define DCR_DMAEF 0 /* DMA until TX/RX FIFO has emptied/filled */
#define DCR_DMABLOCK DCR_BMS /* DMA until RX/TX threshold crossed */
#define DCR_RFT4 0 /* receive threshold 4 bytes */
#define DCR_RFT8 DCR_RFT0 /* receive threshold 8 bytes */
#define DCR_RFT16 DCR_RFT1 /* receive threshold 16 bytes */
#define DCR_RFT24 (DCR_RFT1|DCR_RFT0) /* receive threshold 24 bytes */
#define DCR_TFT8 0 /* transmit threshold 8 bytes */
#define DCR_TFT16 DCR_TFT0 /* transmit threshold 16 bytes */
#define DCR_TFT24 DCR_TFT1 /* transmit threshold 24 bytes */
#define DCR_TFT28 (DCR_TFT1|DCR_TFT0) /* transmit threshold 28 bytes */
/*
* The receive control register is used to filter incoming packets and
* provides status information on packets received.
* The contents of the register are copied into the RXpkt.status field
* when a packet is received. RCR_MC - RCR_PRX are then reset.
*/
#define RCR_ERR 0x8000 /* accept packets with CRC errors */
#define RCR_RNT 0x4000 /* accept runt (length < 64) packets */
#define RCR_BRD 0x2000 /* accept broadcast packets */
#define RCR_PRO 0x1000 /* accept all physical address packets */
#define RCR_AMC 0x0800 /* accept all multicast packets */
#define RCR_LB1 0x0400 /* loopback control 1 */
#define RCR_LB0 0x0200 /* loopback control 0 */
#define RCR_MC 0x0100 /* multicast packet received */
#define RCR_BC 0x0080 /* broadcast packet received */
#define RCR_LPKT 0x0040 /* last packet in RBA (RBWC < EOBC) */
#define RCR_CRS 0x0020 /* carrier sense activity */
#define RCR_COL 0x0010 /* collision activity */
#define RCR_CRC 0x0008 /* CRC error */
#define RCR_FAE 0x0004 /* frame alignment error */
#define RCR_LBK 0x0002 /* loopback packet received */
#define RCR_PRX 0x0001 /* packet received without errors */
/* receiver control register aliases */
/* the loopback control bits provide the following options */
#define RCR_LBNONE 0 /* no loopback - normal operation */
#define RCR_LBMAC RCR_LB0 /* MAC loopback */
#define RCR_LBENDEC RCR_LB1 /* ENDEC loopback */
#define RCR_LBTRANS (RCR_LB1|RCR_LB0) /* transceiver loopback */
/*
* The transmit control register controls the SONIC's transmit operations.
* TCR_PINT - TCR_EXDIS are loaded from the TXpkt.config field at the
* start of transmission. TCR_EXD-TCR_PTX are cleared at the beginning
* of transmission and updated when the transmission is completed.
*/
#define TCR_PINT 0x8000 /* interrupt when transmission starts */
#define TCR_POWC 0x4000 /* program out of window collision timer */
#define TCR_CRCI 0x2000 /* transmit packet without 4 byte FCS */
#define TCR_EXDIS 0x1000 /* disable excessive deferral timer */
#define TCR_EXD 0x0400 /* excessive deferrals occurred (>3.2ms) */
#define TCR_DEF 0x0200 /* deferred transmissions occurred */
#define TCR_NCRS 0x0100 /* carrier not present during transmission */
#define TCR_CRSL 0x0080 /* carrier lost during transmission */
#define TCR_EXC 0x0040 /* excessive collisions (>16) detected */
#define TCR_OWC 0x0020 /* out of window (bad) collision occurred */
#define TCR_PMB 0x0008 /* packet monitored bad - the tansmitted
* packet had a bad source address or CRC */
#define TCR_FU 0x0004 /* FIFO underrun (memory access failed) */
#define TCR_BCM 0x0002 /* byte count mismatch (TXpkt.pkt_size
* != sum(TXpkt.frag_size) */
#define TCR_PTX 0x0001 /* packet transmitted without errors */
#define TCR_NC 0xf000 /* after transmission, # of colls */
/* transmit control register aliases */
#define TCR_OWCSFD 0 /* start after start of frame delimiter */
#define TCR_OWCPRE TCR_POWC /* start after first bit of preamble */
/*
* The interrupt mask register masks the interrupts that
* are generated from the interrupt status register.
* All reserved bits should be written with 0.
*/
#define IMR_BREN 0x4000 /* bus retry occurred enable */
#define IMR_HBLEN 0x2000 /* heartbeat lost enable */
#define IMR_LCDEN 0x1000 /* load CAM done interrupt enable */
#define IMR_PINTEN 0x0800 /* programmable interrupt enable */
#define IMR_PRXEN 0x0400 /* packet received enable */
#define IMR_PTXEN 0x0200 /* packet transmitted enable */
#define IMR_TXEREN 0x0100 /* transmit error enable */
#define IMR_TCEN 0x0080 /* timer complete enable */
#define IMR_RDEEN 0x0040 /* receive descriptors exhausted enable */
#define IMR_RBEEN 0x0020 /* receive buffers exhausted enable */
#define IMR_RBAEEN 0x0010 /* receive buffer area exceeded enable */
#define IMR_CRCEN 0x0008 /* CRC tally counter rollover enable */
#define IMR_FAEEN 0x0004 /* FAE tally counter rollover enable */
#define IMR_MPEN 0x0002 /* MP tally counter rollover enable */
#define IMR_RFOEN 0x0001 /* receive FIFO overrun enable */
/*
* The interrupt status register indicates the source of an interrupt when
* the INT pin goes active. The interrupt is acknowledged by writing
* the appropriate bit(s) in this register.
*/
#define ISR_ALL 0x7fff /* all interrupts */
#define ISR_BR 0x4000 /* bus retry occurred */
#define ISR_HBL 0x2000 /* CD heartbeat lost */
#define ISR_LCD 0x1000 /* load CAM command has completed */
#define ISR_PINT 0x0800 /* programmed interrupt from TXpkt.config */
#define ISR_PKTRX 0x0400 /* packet received */
#define ISR_TXDN 0x0200 /* no remaining packets to be transmitted */
#define ISR_TXER 0x0100 /* packet transmission caused error */
#define ISR_TC 0x0080 /* timer complete */
#define ISR_RDE 0x0040 /* receive descriptors exhausted */
#define ISR_RBE 0x0020 /* receive buffers exhausted */
#define ISR_RBAE 0x0010 /* receive buffer area exceeded */
#define ISR_CRC 0x0008 /* CRC tally counter rollover */
#define ISR_FAE 0x0004 /* FAE tally counter rollover */
#define ISR_MP 0x0002 /* MP tally counter rollover */
#define ISR_RFO 0x0001 /* receive FIFO overrun */
/*
* The second data configuration register allows additional user defined
* pins to be controlled. These bits are only available if s_dcr.DCR_EXBUS
* is set.
*/
#define DCR2_EXPO3 0x8000 /* EXUSR3 output */
#define DCR2_EXPO2 0x4000 /* EXUSR2 output */
#define DCR2_EXPO1 0x2000 /* EXUSR1 output */
#define DCR2_EXPO0 0x1000 /* EXUSR0 output */
#define DCR2_HD 0x0800 /* heart beat disable (83934/83936) */
#define DCR2_JD 0x0200 /* TPI jabber timer disable (83934/83936) */
#define DCR2_AUTO 0x0100 /* AUI/TPI auto selection (83934/83936) */
#define DCR2_XWRAP 0x0040 /* TPI transceiver loopback (83934/83936) */
#define DCR2_FD 0x0020 /* full duplex (83936) */
#define DCR2_PHL 0x0010 /* extend HOLD signal by 1/2 clock */
#define DCR2_LRDY 0x0008 /* set latched ready mode */
#define DCR2_PCM 0x0004 /* packet compress on match */
#define DCR2_PCNM 0x0002 /* packet compress on mismatch */
#define DCR2_RJM 0x0001 /* reject on match */

902
sys/dev/snc/dp83932subr.c Normal file
View File

@ -0,0 +1,902 @@
/* $FreeBSD$ */
/* $NecBSD: dp83932subr.c,v 1.5.6.2 1999/10/09 05:47:23 kmatsuda Exp $ */
/* $NetBSD$ */
/*
* Copyright (c) 1997, 1998, 1999
* Kouichi Matsuda. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Kouichi Matsuda for
* NetBSD/pc98.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Routines of NEC PC-9801-83, 84, 103, 104, PC-9801N-25 and PC-9801N-J02, J02R
* Ethernet interface for NetBSD/pc98, ported by Kouichi Matsuda.
*
* These cards use National Semiconductor DP83934AVQB as Ethernet Controller
* and National Semiconductor NS46C46 as (64 * 16 bits) Microwire Serial EEPROM.
*/
/*
* Modified for FreeBSD(98) 4.0 from NetBSD/pc98 1.4.2 by Motomichi Matsuzaki.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/syslog.h>
#include <sys/errno.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/if_media.h>
#ifdef INET
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/in_var.h>
#include <netinet/ip.h>
#include <netinet/if_inarp.h>
#endif
#include <net/bpf.h>
#include <sys/bus.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/bus_pio.h>
#include <machine/bus_memio.h>
#include <machine/bus.h>
#include <dev/snc/dp83932reg.h>
#include <dev/snc/dp83932var.h>
#include <dev/snc/if_sncreg.h>
#include <dev/snc/dp83932subr.h>
integrate u_int16_t snc_nec16_select_bank
__P((struct snc_softc *, u_int32_t, u_int32_t));
/*
* Interface exists: make available by filling in network interface
* record. System will initialize the interface when it is ready
* to accept packets.
*/
int
sncsetup(sc, lladdr)
struct snc_softc *sc;
u_int8_t *lladdr;
{
u_int32_t p, pp;
int i;
int offset;
/*
* Put the pup in reset mode (sncinit() will fix it later),
* stop the timer, disable all interrupts and clear any interrupts.
*/
NIC_PUT(sc, SNCR_CR, CR_STP);
wbflush();
NIC_PUT(sc, SNCR_CR, CR_RST);
wbflush();
NIC_PUT(sc, SNCR_IMR, 0);
wbflush();
NIC_PUT(sc, SNCR_ISR, ISR_ALL);
wbflush();
/*
* because the SONIC is basically 16bit device it 'concatenates'
* a higher buffer address to a 16 bit offset--this will cause wrap
* around problems near the end of 64k !!
*/
p = pp = 0;
for (i = 0; i < NRRA; i++) {
sc->v_rra[i] = SONIC_GETDMA(p);
p += RXRSRC_SIZE(sc);
}
sc->v_rea = SONIC_GETDMA(p);
p = SOALIGN(sc, p);
sc->v_cda = SONIC_GETDMA(p);
p += CDA_SIZE(sc);
p = SOALIGN(sc, p);
for (i = 0; i < NTDA; i++) {
struct mtd *mtdp = &sc->mtda[i];
mtdp->mtd_vtxp = SONIC_GETDMA(p);
p += TXP_SIZE(sc);
}
p = SOALIGN(sc, p);
if ((p - pp) > NBPG) {
device_printf (sc->sc_dev, "sizeof RRA (%ld) + CDA (%ld) +"
"TDA (%ld) > NBPG (%d). Punt!\n",
(ulong)sc->v_cda - (ulong)sc->v_rra[0],
(ulong)sc->mtda[0].mtd_vtxp - (ulong)sc->v_cda,
(ulong)p - (ulong)sc->mtda[0].mtd_vtxp,
NBPG);
return(1);
}
p = pp + NBPG;
pp = p;
sc->sc_nrda = NBPG / RXPKT_SIZE(sc);
sc->v_rda = SONIC_GETDMA(p);
p = pp + NBPG;
for (i = 0; i < NRBA; i++) {
sc->rbuf[i] = p;
p += NBPG;
}
pp = p;
offset = TXBSIZE;
for (i = 0; i < NTDA; i++) {
struct mtd *mtdp = &sc->mtda[i];
mtdp->mtd_vbuf = SONIC_GETDMA(p);
offset += TXBSIZE;
if (offset < NBPG) {
p += TXBSIZE;
} else {
p = pp + NBPG;
pp = p;
offset = TXBSIZE;
}
}
return (0);
}
/*
* miscellaneous NEC/SONIC detect functions.
*/
/*
* check if a specified irq is acceptable.
*/
u_int8_t
snc_nec16_validate_irq(irq)
int irq;
{
const u_int8_t encoded_irq[16] = {
-1, -1, -1, 0, -1, 1, 2, -1, -1, 3, 4, -1, 5, 6, -1, -1
};
return encoded_irq[irq];
}
/*
* specify irq to board.
*/
int
snc_nec16_register_irq(sc, irq)
struct snc_softc *sc;
int irq;
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
u_int8_t encoded_irq;
encoded_irq = snc_nec16_validate_irq(irq);
if (encoded_irq == (u_int8_t) -1) {
printf("snc_nec16_register_irq: unsupported irq (%d)\n", irq);
return 0;
}
/* select SNECR_IRQSEL register */
bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_IRQSEL);
/* write encoded irq value */
bus_space_write_1(iot, ioh, SNEC_CTRLB, encoded_irq);
return 1;
}
/*
* check if a specified memory base address is acceptable.
*/
int
snc_nec16_validate_mem(maddr)
int maddr;
{
/* Check on Normal mode with max range, only */
if ((maddr & ~0x1E000) != 0xC0000) {
printf("snc_nec16_validate_mem: "
"unsupported window base (0x%x)\n", maddr);
return 0;
}
return 1;
}
/*
* specify memory base address to board and map to first bank.
*/
int
snc_nec16_register_mem(sc, maddr)
struct snc_softc *sc;
int maddr;
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
if (snc_nec16_validate_mem(maddr) == 0)
return 0;
/* select SNECR_MEMSEL register */
bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMSEL);
/* write encoded memory base select value */
bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_MEMSEL_PHYS2EN(maddr));
/*
* set current bank to 0 (bottom) and map
*/
/* select SNECR_MEMBS register */
bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
/* select new bank */
bus_space_write_1(iot, ioh, SNEC_CTRLB,
SNECR_MEMBS_B2EB(0) | SNECR_MEMBS_BSEN);
/* set current bank to 0 */
sc->curbank = 0;
return 1;
}
int
snc_nec16_check_memory(iot, ioh, memt, memh)
bus_space_tag_t iot;
bus_space_handle_t ioh;
bus_space_tag_t memt;
bus_space_handle_t memh;
{
u_int16_t val;
int i, j;
val = 0;
for (i = 0; i < SNEC_NBANK; i++) {
/* select new bank */
bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
bus_space_write_1(iot, ioh, SNEC_CTRLB,
SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN);
/* write test pattern */
for (j = 0; j < SNEC_NMEMS / 2; j++) {
bus_space_write_2(memt, memh, j * 2, val + j);
}
val += 0x1000;
}
val = 0;
for (i = 0; i < SNEC_NBANK; i++) {
/* select new bank */
bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
bus_space_write_1(iot, ioh, SNEC_CTRLB,
SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN);
/* read test pattern */
for (j = 0; j < SNEC_NMEMS / 2; j++) {
if (bus_space_read_2(memt, memh, j * 2) != val + j)
break;
}
if (j < SNEC_NMEMS / 2) {
printf("snc_nec16_check_memory: "
"memory check failed at 0x%04x%04x"
"val 0x%04x != expected 0x%04x\n", i, j,
bus_space_read_2(memt, memh, j * 2),
val + j);
return 0;
}
val += 0x1000;
}
/* zero clear mem */
for (i = 0; i < SNEC_NBANK; i++) {
/* select new bank */
bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
bus_space_write_1(iot, ioh, SNEC_CTRLB,
SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN);
bus_space_set_region_4(memt, memh, 0, 0, SNEC_NMEMS >> 2);
}
/* again read test if these are 0 */
for (i = 0; i < SNEC_NBANK; i++) {
/* select new bank */
bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
bus_space_write_1(iot, ioh, SNEC_CTRLB,
SNECR_MEMBS_B2EB(i) | SNECR_MEMBS_BSEN);
/* check if cleared */
for (j = 0; j < SNEC_NMEMS; j += 2) {
if (bus_space_read_2(memt, memh, j) != 0)
break;
}
if (j != SNEC_NMEMS) {
printf("snc_nec16_check_memory: "
"memory zero clear failed at 0x%04x%04x\n", i, j);
return 0;
}
}
return 1;
}
int
snc_nec16_detectsubr(iot, ioh, memt, memh, irq, maddr, type)
bus_space_tag_t iot;
bus_space_handle_t ioh;
bus_space_tag_t memt;
bus_space_handle_t memh;
int irq;
int maddr;
u_int8_t type;
{
u_int16_t cr;
u_int8_t ident;
int rv = 0;
if (snc_nec16_validate_irq(irq) == (u_int8_t) -1)
return 0;
/* XXX: maddr already checked */
if (snc_nec16_validate_mem(maddr) == 0)
return 0;
bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_IDENT);
ident = bus_space_read_1(iot, ioh, SNEC_CTRLB);
if (ident == 0xff || ident == 0x00) {
/* not found */
return 0;
}
switch (type) {
case SNEC_TYPE_LEGACY:
rv = (ident == SNECR_IDENT_LEGACY_CBUS);
break;
case SNEC_TYPE_PNP:
rv = ((ident == SNECR_IDENT_PNP_CBUS) ||
(ident == SNECR_IDENT_PNP_PCMCIABUS));
break;
default:
break;
}
if (rv == 0) {
printf("snc_nec16_detectsubr: parent bus mismatch\n");
return 0;
}
/* select SONIC register SNCR_CR */
bus_space_write_1(iot, ioh, SNEC_ADDR, SNCR_CR);
bus_space_write_2(iot, ioh, SNEC_CTRL, CR_RXDIS | CR_STP | CR_RST);
delay(400);
cr = bus_space_read_2(iot, ioh, SNEC_CTRL);
if (cr != (CR_RXDIS | CR_STP | CR_RST)) {
#ifdef DIAGNOSTIC
printf("snc_nec16_detectsubr: card reset failed, cr = 0x%04x\n",
cr);
#endif
return 0;
}
if (snc_nec16_check_memory(iot, ioh, memt, memh) == 0)
return 0;
return 1;
}
/* XXX */
#define SNC_VENDOR_NEC 0x00004c
#define SNC_NEC_SERIES_LEGACY_CBUS 0xa5
#define SNC_NEC_SERIES_PNP_PCMCIA 0xd5
#define SNC_NEC_SERIES_PNP_PCMCIA2 0x6d /* XXX */
#define SNC_NEC_SERIES_PNP_CBUS 0x0d
#define SNC_NEC_SERIES_PNP_CBUS2 0x3d
u_int8_t *
snc_nec16_detect_type(myea)
u_int8_t *myea;
{
u_int32_t vendor = (myea[0] << 16) | (myea[1] << 8) | myea[2];
u_int8_t series = myea[3];
u_int8_t type = myea[4] & 0x80;
u_int8_t *typestr;
switch (vendor) {
case SNC_VENDOR_NEC:
switch (series) {
case SNC_NEC_SERIES_LEGACY_CBUS:
if (type)
typestr = "NEC PC-9801-84";
else
typestr = "NEC PC-9801-83";
break;
case SNC_NEC_SERIES_PNP_CBUS:
case SNC_NEC_SERIES_PNP_CBUS2:
if (type)
typestr = "NEC PC-9801-104";
else
typestr = "NEC PC-9801-103";
break;
case SNC_NEC_SERIES_PNP_PCMCIA:
case SNC_NEC_SERIES_PNP_PCMCIA2:
/* XXX: right ? */
if (type)
typestr = "NEC PC-9801N-J02R";
else
typestr = "NEC PC-9801N-J02";
break;
default:
typestr = "NEC unknown (PC-9801N-25?)";
break;
}
break;
default:
typestr = "unknown (3rd vendor?)";
break;
}
return typestr;
}
int
snc_nec16_get_enaddr(iot, ioh, myea)
bus_space_tag_t iot;
bus_space_handle_t ioh;
u_int8_t *myea;
{
u_int8_t eeprom[SNEC_EEPROM_SIZE];
u_int8_t rom_sum, sum = 0x00;
int i;
snc_nec16_read_eeprom(iot, ioh, eeprom);
for (i = SNEC_EEPROM_KEY0; i < SNEC_EEPROM_CKSUM; i++) {
sum = sum ^ eeprom[i];
}
rom_sum = eeprom[SNEC_EEPROM_CKSUM];
if (sum != rom_sum) {
printf("snc_nec16_get_enaddr: "
"checksum mismatch; calculated %02x != read %02x",
sum, rom_sum);
return 0;
}
for (i = 0; i < ETHER_ADDR_LEN; i++)
myea[i] = eeprom[SNEC_EEPROM_SA0 + i];
return 1;
}
/*
* read from NEC/SONIC NIC register.
*/
u_int16_t
snc_nec16_nic_get(sc, reg)
struct snc_softc *sc;
u_int8_t reg;
{
u_int16_t val;
/* select SONIC register */
bus_space_write_1(sc->sc_iot, sc->sc_ioh, SNEC_ADDR, reg);
val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SNEC_CTRL);
return val;
}
/*
* write to NEC/SONIC NIC register.
*/
void
snc_nec16_nic_put(sc, reg, val)
struct snc_softc *sc;
u_int8_t reg;
u_int16_t val;
{
/* select SONIC register */
bus_space_write_1(sc->sc_iot, sc->sc_ioh, SNEC_ADDR, reg);
bus_space_write_2(sc->sc_iot, sc->sc_ioh, SNEC_CTRL, val);
}
/*
* select memory bank and map
* where exists specified (internal buffer memory) offset.
*/
integrate u_int16_t
snc_nec16_select_bank(sc, base, offset)
struct snc_softc *sc;
u_int32_t base;
u_int32_t offset;
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
u_int8_t bank;
u_int16_t noffset;
/* bitmode is fixed to 16 bit. */
bank = (base + offset * 2) >> 13;
noffset = (base + offset * 2) & (SNEC_NMEMS - 1);
#ifdef SNCDEBUG
if (noffset % 2) {
device_printf(sc->sc_dev, "noffset is odd (0x%04x)\n",
noffset);
}
#endif /* SNCDEBUG */
if (sc->curbank != bank) {
/* select SNECR_MEMBS register */
bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_MEMBS);
/* select new bank */
bus_space_write_1(iot, ioh, SNEC_CTRLB,
SNECR_MEMBS_B2EB(bank) | SNECR_MEMBS_BSEN);
/* update current bank */
sc->curbank = bank;
}
return noffset;
}
/*
* write to SONIC descriptors.
*/
void
snc_nec16_writetodesc(sc, base, offset, val)
struct snc_softc *sc;
u_int32_t base;
u_int32_t offset;
u_int16_t val;
{
bus_space_tag_t memt = sc->sc_memt;
bus_space_handle_t memh = sc->sc_memh;
u_int16_t noffset;
noffset = snc_nec16_select_bank(sc, base, offset);
bus_space_write_2(memt, memh, noffset, val);
}
/*
* read from SONIC descriptors.
*/
u_int16_t
snc_nec16_readfromdesc(sc, base, offset)
struct snc_softc *sc;
u_int32_t base;
u_int32_t offset;
{
bus_space_tag_t memt = sc->sc_memt;
bus_space_handle_t memh = sc->sc_memh;
u_int16_t noffset;
noffset = snc_nec16_select_bank(sc, base, offset);
return bus_space_read_2(memt, memh, noffset);
}
/*
* read from SONIC data buffer.
*/
void
snc_nec16_copyfrombuf(sc, dst, offset, size)
struct snc_softc *sc;
void *dst;
u_int32_t offset;
size_t size;
{
bus_space_tag_t memt = sc->sc_memt;
bus_space_handle_t memh = sc->sc_memh;
u_int16_t noffset;
u_int8_t* bptr = dst;
noffset = snc_nec16_select_bank(sc, offset, 0);
/* XXX: should check if offset + size < 0x2000. */
bus_space_barrier(memt, memh, noffset, size,
BUS_SPACE_BARRIER_READ);
if (size > 3) {
if (noffset & 3) {
size_t asize = (~noffset & 3);
bus_space_read_region_1(memt, memh, noffset,
bptr, asize);
bptr += asize;
noffset += asize;
size -= asize;
}
bus_space_read_region_4(memt, memh, noffset,
(u_int32_t *) bptr, size >> 2);
bptr += size & ~3;
noffset += size & ~3;
size &= 3;
}
if (size)
bus_space_read_region_1(memt, memh, noffset, bptr, size);
}
/*
* write to SONIC data buffer.
*/
void
snc_nec16_copytobuf(sc, src, offset, size)
struct snc_softc *sc;
void *src;
u_int32_t offset;
size_t size;
{
bus_space_tag_t memt = sc->sc_memt;
bus_space_handle_t memh = sc->sc_memh;
u_int16_t noffset, onoffset;
size_t osize = size;
u_int8_t* bptr = src;
noffset = snc_nec16_select_bank(sc, offset, 0);
onoffset = noffset;
/* XXX: should check if offset + size < 0x2000. */
if (size > 3) {
if (noffset & 3) {
size_t asize = (~noffset & 3);
bus_space_write_region_1(memt, memh, noffset,
bptr, asize);
bptr += asize;
noffset += asize;
size -= asize;
}
bus_space_write_region_4(memt, memh, noffset,
(u_int32_t *)bptr, size >> 2);
bptr += size & ~3;
noffset += size & ~3;
size -= size & ~3;
}
if (size)
bus_space_write_region_1(memt, memh, noffset, bptr, size);
bus_space_barrier(memt, memh, onoffset, osize,
BUS_SPACE_BARRIER_WRITE);
}
/*
* write (fill) 0 to SONIC data buffer.
*/
void
snc_nec16_zerobuf(sc, offset, size)
struct snc_softc *sc;
u_int32_t offset;
size_t size;
{
bus_space_tag_t memt = sc->sc_memt;
bus_space_handle_t memh = sc->sc_memh;
u_int16_t noffset, onoffset;
size_t osize = size;
noffset = snc_nec16_select_bank(sc, offset, 0);
onoffset = noffset;
/* XXX: should check if offset + size < 0x2000. */
if (size > 3) {
if (noffset & 3) {
size_t asize = (~noffset & 3);
bus_space_set_region_1(memt, memh, noffset, 0, asize);
noffset += asize;
size -= asize;
}
bus_space_set_region_4(memt, memh, noffset, 0, size >> 2);
noffset += size & ~3;
size -= size & ~3;
}
if (size)
bus_space_set_region_1(memt, memh, noffset, 0, size);
bus_space_barrier(memt, memh, onoffset, osize,
BUS_SPACE_BARRIER_WRITE);
}
/*
* Routines to read bytes sequentially from EEPROM through NEC PC-9801-83,
* 84, 103, 104, PC-9801N-25 and PC-9801N-J02, J02R for NetBSD/pc98.
* Ported by Kouichi Matsuda.
*
* This algorism is generic to read data sequentially from 4-Wire
* Microwire Serial EEPROM.
*/
#define SNEC_EEP_DELAY 1000
void
snc_nec16_read_eeprom(iot, ioh, data)
bus_space_tag_t iot;
bus_space_handle_t ioh;
u_int8_t *data;
{
u_int8_t n, val, bit;
/* Read bytes from EEPROM; two bytes per an iteration. */
for (n = 0; n < SNEC_EEPROM_SIZE / 2; n++) {
/* select SNECR_EEP */
bus_space_write_1(iot, ioh, SNEC_ADDR, SNECR_EEP);
bus_space_write_1(iot, ioh, SNEC_CTRLB, 0x00);
delay(SNEC_EEP_DELAY);
/* Start EEPROM access. */
bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS);
delay(SNEC_EEP_DELAY);
bus_space_write_1(iot, ioh, SNEC_CTRLB,
SNECR_EEP_CS | SNECR_EEP_SK);
delay(SNEC_EEP_DELAY);
bus_space_write_1(iot, ioh, SNEC_CTRLB,
SNECR_EEP_CS | SNECR_EEP_DI);
delay(SNEC_EEP_DELAY);
bus_space_write_1(iot, ioh, SNEC_CTRLB,
SNECR_EEP_CS | SNECR_EEP_SK | SNECR_EEP_DI);
delay(SNEC_EEP_DELAY);
bus_space_write_1(iot, ioh, SNEC_CTRLB,
SNECR_EEP_CS | SNECR_EEP_DI);
delay(SNEC_EEP_DELAY);
bus_space_write_1(iot, ioh, SNEC_CTRLB,
SNECR_EEP_CS | SNECR_EEP_SK | SNECR_EEP_DI);
delay(SNEC_EEP_DELAY);
bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS);
delay(SNEC_EEP_DELAY);
bus_space_write_1(iot, ioh, SNEC_CTRLB,
SNECR_EEP_CS | SNECR_EEP_SK);
delay(SNEC_EEP_DELAY);
/* Pass the iteration count to the chip. */
for (bit = 0x20; bit != 0x00; bit >>= 1) {
bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS |
((n & bit) ? SNECR_EEP_DI : 0x00));
delay(SNEC_EEP_DELAY);
bus_space_write_1(iot, ioh, SNEC_CTRLB,
SNECR_EEP_CS | SNECR_EEP_SK |
((n & bit) ? SNECR_EEP_DI : 0x00));
delay(SNEC_EEP_DELAY);
}
bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS);
(void) bus_space_read_1(iot, ioh, SNEC_CTRLB); /* ACK */
delay(SNEC_EEP_DELAY);
/* Read a byte. */
val = 0;
for (bit = 0x80; bit != 0x00; bit >>= 1) {
bus_space_write_1(iot, ioh, SNEC_CTRLB,
SNECR_EEP_CS | SNECR_EEP_SK);
delay(SNEC_EEP_DELAY);
bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS);
if (bus_space_read_1(iot, ioh, SNEC_CTRLB) & SNECR_EEP_DO)
val |= bit;
}
*data++ = val;
/* Read one more byte. */
val = 0;
for (bit = 0x80; bit != 0x00; bit >>= 1) {
bus_space_write_1(iot, ioh, SNEC_CTRLB,
SNECR_EEP_CS | SNECR_EEP_SK);
delay(SNEC_EEP_DELAY);
bus_space_write_1(iot, ioh, SNEC_CTRLB, SNECR_EEP_CS);
if (bus_space_read_1(iot, ioh, SNEC_CTRLB) & SNECR_EEP_DO)
val |= bit;
}
*data++ = val;
bus_space_write_1(iot, ioh, SNEC_CTRLB, 0x00);
delay(SNEC_EEP_DELAY);
}
#ifdef SNCDEBUG
/* Report what we got. */
data -= SNEC_EEPROM_SIZE;
log(LOG_INFO, "%s: EEPROM:"
" %02x%02x%02x%02x %02x%02x%02x%02x -"
" %02x%02x%02x%02x %02x%02x%02x%02x -"
" %02x%02x%02x%02x %02x%02x%02x%02x -"
" %02x%02x%02x%02x %02x%02x%02x%02x\n",
"snc_nec16_read_eeprom",
data[ 0], data[ 1], data[ 2], data[ 3],
data[ 4], data[ 5], data[ 6], data[ 7],
data[ 8], data[ 9], data[10], data[11],
data[12], data[13], data[14], data[15],
data[16], data[17], data[18], data[19],
data[20], data[21], data[22], data[23],
data[24], data[25], data[26], data[27],
data[28], data[29], data[30], data[31]);
#endif
}
#ifdef SNCDEBUG
void
snc_nec16_dump_reg(iot, ioh)
bus_space_tag_t iot;
bus_space_handle_t ioh;
{
u_int8_t n;
u_int16_t val;
printf("SONIC registers (word):");
for (n = 0; n < SNC_NREGS; n++) {
/* select required SONIC register */
bus_space_write_1(iot, ioh, SNEC_ADDR, n);
delay(10);
val = bus_space_read_2(iot, ioh, SNEC_CTRL);
if ((n % 0x10) == 0)
printf("\n%04x ", val);
else
printf("%04x ", val);
}
printf("\n");
printf("NEC/SONIC registers (byte):\n");
for (n = SNECR_MEMBS; n <= SNECR_IDENT; n += 2) {
/* select required SONIC register */
bus_space_write_1(iot, ioh, SNEC_ADDR, n);
delay(10);
val = (u_int16_t) bus_space_read_1(iot, ioh, SNEC_CTRLB);
printf("%04x ", val);
}
printf("\n");
}
#endif /* SNCDEBUG */

78
sys/dev/snc/dp83932subr.h Normal file
View File

@ -0,0 +1,78 @@
/* $FreeBSD$ */
/* $NecBSD: dp83932subr.h,v 1.5 1999/02/02 00:47:25 kmatsuda Exp $ */
/* $NetBSD$ */
/*
* Copyright (c) 1997, 1998, 1999
* Kouichi Matsuda. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Kouichi Matsuda for
* NetBSD/pc98.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Routines of NEC PC-9801-83, 84, 103, 104, PC-9801N-25 and PC-9801N-J02, J02R
* Ethernet interface for NetBSD/pc98, ported by Kouichi Matsuda.
*
* These cards use National Semiconductor DP83934AVQB as Ethernet Controller
* and National Semiconductor NS46C46 as (64 * 16 bits) Microwire Serial EEPROM.
*/
int sncsetup __P((struct snc_softc *, u_int8_t *));
u_int8_t snc_nec16_validate_irq __P((int));
int snc_nec16_register_irq __P((struct snc_softc *, int));
int snc_nec16_validate_mem __P((int));
int snc_nec16_register_mem __P((struct snc_softc *, int));
u_int16_t snc_nec16_nic_get __P((struct snc_softc *, u_int8_t));
void snc_nec16_nic_put __P((struct snc_softc *, u_int8_t, u_int16_t));
void snc_nec16_writetodesc
__P((struct snc_softc *, u_int32_t, u_int32_t, u_int16_t));
u_int16_t snc_nec16_readfromdesc
__P((struct snc_softc *, u_int32_t, u_int32_t));
void snc_nec16_copyfrombuf __P((struct snc_softc *, void *, u_int32_t, size_t));
void snc_nec16_copytobuf __P((struct snc_softc *, void *, u_int32_t, size_t));
void snc_nec16_zerobuf __P((struct snc_softc *, u_int32_t, size_t));
int snc_nec16_detectsubr
__P((bus_space_tag_t, bus_space_handle_t, bus_space_tag_t,
bus_space_handle_t, int, int, u_int8_t));
int snc_nec16_check_memory
__P((bus_space_tag_t, bus_space_handle_t, bus_space_tag_t,
bus_space_handle_t));
int snc_nec16_get_enaddr
__P((bus_space_tag_t, bus_space_handle_t, u_int8_t *));
u_int8_t *snc_nec16_detect_type __P((u_int8_t *));
void snc_nec16_read_eeprom
__P((bus_space_tag_t, bus_space_handle_t, u_int8_t *));
#ifdef SNCDEBUG
void snc_nec16_dump_reg __P((bus_space_tag_t, bus_space_handle_t));
#endif /* SNDEBUG */

307
sys/dev/snc/dp83932var.h Normal file
View File

@ -0,0 +1,307 @@
/* $FreeBSD$ */
/* $NecBSD: dp83932var.h,v 1.3 1999/01/24 01:39:51 kmatsuda Exp $ */
/* $NetBSD: if_snvar.h,v 1.12 1998/05/01 03:42:47 scottr Exp $ */
/*
* [NetBSD for NEC PC-98 series]
* Copyright (c) 1997, 1998, 1999
* Kouichi Matsuda. All rights reserved.
*/
/*
* Copyright (c) 1991 Algorithmics Ltd (http://www.algor.co.uk)
* You may use, copy, and modify this program so long as you retain the
* copyright line.
*/
/*
* if_snvar.h -- National Semiconductor DP8393X (SONIC) NetBSD/mac68k vars
*/
/*
* Modified for NetBSD/pc98 1.2.1 from NetBSD/mac68k 1.2D by Kouichi Matsuda.
* Make adapted for NEC PC-9801-83, 84, PC-9801-103, 104, PC-9801N-25 and
* PC-9801N-J02, J02R, which uses National Semiconductor DP83934AVQB as
* Ethernet Controller and National Semiconductor NS46C46 as
* (64 * 16 bits) Microwire Serial EEPROM.
*/
/* borrow from arch/mac68k/dev/if_mcvar.h for debug. */
#ifdef DDB
#define integrate
#define hide
#else
#define integrate static __inline
#define hide static
#endif
/* NetBSD Emulation */
#ifdef __FreeBSD__
#ifndef NBPG
#define NBPG PAGE_SIZE
#endif
#ifndef PGOFSET
#define PGOFSET PAGE_MASK
#endif
typedef unsigned long ulong;
#define delay(x) DELAY(x)
#endif
/*
* Vendor types
*/
/*
* SONIC buffers need to be aligned 16 or 32 bit aligned.
* These macros calculate and verify alignment.
*/
#define ROUNDUP(p, N) (((int) p + N - 1) & ~(N - 1))
#define SOALIGN(m, array) (m ? (ROUNDUP(array, 4)) : (ROUNDUP(array, 2)))
#define LOWER(x) ((unsigned)(x) & 0xffff)
#define UPPER(x) ((unsigned)(x) >> 16)
/*
* Memory access macros. Since we handle SONIC in 16 bit mode (PB5X0)
* and 32 bit mode (everything else) using a single GENERIC kernel
* binary, all structures have to be accessed using macros which can
* adjust the offsets appropriately.
*/
/* m is not sc->bitmode, we treat m as sc. */
#define SWO(m, a, o, x) (*(m)->sc_writetodesc)((m), (a), (o), (x))
#define SRO(m, a, o) (*(m)->sc_readfromdesc)((m), (a), (o))
/*
* Register access macros. We use bus_space_* to talk to the Sonic
* registers. A mapping table is used in case a particular configuration
* hooked the regs up at non-word offsets.
*/
#define NIC_GET(sc, reg) (*(sc)->sc_nic_get)(sc, reg)
#define NIC_PUT(sc, reg, val) (*(sc)->sc_nic_put)(sc, reg, val)
#define SONIC_GETDMA(p) (p)
/* pc98 does not have any write buffers to flush... */
#define wbflush()
/*
* buffer sizes in 32 bit mode
* 1 TXpkt is 4 hdr words + (3 * FRAGMAX) + 1 link word == 23 words == 92 bytes
*
* 1 RxPkt is 7 words == 28 bytes
* 1 Rda is 4 words == 16 bytes
*
* The CDA is 17 words == 68 bytes
*
* total space in page 0 = NTDA * 92 + NRRA * 16 + NRDA * 28 + 68
*/
#define NRBA 16 /* # receive buffers < NRRA */
#define RBAMASK (NRBA-1)
#define NTDA 16 /* # transmit descriptors */
#define NRRA 64 /* # receive resource descriptors */
#define RRAMASK (NRRA-1) /* the reason why NRRA must be power of two */
#define FCSSIZE 4 /* size of FCS appended to packets */
/*
* maximum receive packet size plus 2 byte pad to make each
* one aligned. 4 byte slop (required for eobc)
*/
#define RBASIZE(sc) (sizeof(struct ether_header) + ETHERMTU + FCSSIZE + \
((sc)->bitmode ? 6 : 2))
/*
* transmit buffer area
*/
#define TXBSIZE 1536 /* 6*2^8 -- the same size as the 8390 TXBUF */
#define SN_NPAGES 2 + NRBA + (NTDA/2)
typedef struct mtd {
u_int32_t mtd_vtxp;
u_int32_t mtd_vbuf;
struct mbuf *mtd_mbuf;
} mtd_t;
/*
* The snc_softc for PC-98 if_snc.
*/
typedef struct snc_softc {
struct arpcom sc_ethercom;
#define sc_if sc_ethercom.ac_if /* network visible interface */
device_t sc_dev;
struct resource * ioport;
int ioport_rid;
struct resource * iomem;
int iomem_rid;
struct resource * irq;
int irq_rid;
void * irq_handle;
bus_space_tag_t sc_iot; /* bus identifier for io */
bus_space_tag_t sc_memt; /* bus identifier for mem */
bus_space_handle_t sc_ioh; /* io handle */
bus_space_handle_t sc_memh; /* bus memory handle */
int bitmode; /* 32 bit mode == 1, 16 == 0 */
u_int16_t sncr_dcr; /* DCR for this instance */
u_int16_t sncr_dcr2; /* DCR2 for this instance */
int sc_rramark; /* index into v_rra of wp */
u_int32_t v_rra[NRRA]; /* DMA addresses of v_rra */
u_int32_t v_rea; /* ptr to the end of the rra space */
int sc_rxmark; /* current hw pos in rda ring */
int sc_rdamark; /* current sw pos in rda ring */
int sc_nrda; /* total number of RDAs */
u_int32_t v_rda;
u_int32_t rbuf[NRBA];
struct mtd mtda[NTDA];
int mtd_hw; /* idx of first mtd given to hw */
int mtd_prev; /* idx of last mtd given to hardware */
int mtd_free; /* next free mtd to use */
int mtd_tlinko; /*
* offset of tlink of last txp given
* to SONIC. Need to clear EOL on
* this word to add a desc.
*/
int mtd_pint; /* Counter to set TXP_PINT */
u_int32_t v_cda;
u_int8_t curbank; /* current window bank */
struct ifmedia sc_media; /* supported media information */
/*
* NIC register access functions:
*/
u_int16_t (*sc_nic_get)
__P((struct snc_softc *, u_int8_t));
void (*sc_nic_put)
__P((struct snc_softc *, u_int8_t, u_int16_t));
/*
* Memory functions:
*
* copy to/from descriptor
* copy to/from buffer
* zero bytes in buffer
*/
void (*sc_writetodesc)
__P((struct snc_softc *, u_int32_t, u_int32_t, u_int16_t));
u_int16_t (*sc_readfromdesc)
__P((struct snc_softc *, u_int32_t, u_int32_t));
void (*sc_copytobuf)
__P((struct snc_softc *, void *, u_int32_t, size_t));
void (*sc_copyfrombuf)
__P((struct snc_softc *, void *, u_int32_t, size_t));
void (*sc_zerobuf)
__P((struct snc_softc *, u_int32_t, size_t));
/*
* Machine-dependent functions:
*
* hardware reset hook - may be NULL
* hardware init hook - may be NULL
* media change hook - may be NULL
*/
void (*sc_hwreset) __P((struct snc_softc *));
void (*sc_hwinit) __P((struct snc_softc *));
int (*sc_mediachange) __P((struct snc_softc *));
void (*sc_mediastatus) __P((struct snc_softc *,
struct ifmediareq *));
int sc_enabled; /* boolean; power enabled on interface */
int (*sc_enable) __P((struct snc_softc *));
void (*sc_disable) __P((struct snc_softc *));
void *sc_sh; /* shutdownhook cookie */
int gone;
#if NRND > 0
rndsource_element_t rnd_source;
#endif
} snc_softc_t;
/*
* Accessing SONIC data structures and registers as 32 bit values
* makes code endianess independent. The SONIC is however always in
* bigendian mode so it is necessary to ensure that data structures shared
* between the CPU and the SONIC are always in bigendian order.
*/
/*
* Receive Resource Descriptor
* This structure describes the buffers into which packets
* will be received. Note that more than one packet may be
* packed into a single buffer if constraints permit.
*/
#define RXRSRC_PTRLO 0 /* buffer address LO */
#define RXRSRC_PTRHI 1 /* buffer address HI */
#define RXRSRC_WCLO 2 /* buffer size (16bit words) LO */
#define RXRSRC_WCHI 3 /* buffer size (16bit words) HI */
#define RXRSRC_SIZE(sc) (sc->bitmode ? (4 * 4) : (4 * 2))
/*
* Receive Descriptor
* This structure holds information about packets received.
*/
#define RXPKT_STATUS 0
#define RXPKT_BYTEC 1
#define RXPKT_PTRLO 2
#define RXPKT_PTRHI 3
#define RXPKT_SEQNO 4
#define RXPKT_RLINK 5
#define RXPKT_INUSE 6
#define RXPKT_SIZE(sc) (sc->bitmode ? (7 * 4) : (7 * 2))
#define RBASEQ(x) (((x)>>8)&0xff)
#define PSNSEQ(x) ((x) & 0xff)
/*
* Transmit Descriptor
* This structure holds information about packets to be transmitted.
*/
#define FRAGMAX 8 /* maximum number of fragments in a packet */
#define TXP_STATUS 0 /* + transmitted packet status */
#define TXP_CONFIG 1 /* transmission configuration */
#define TXP_PKTSIZE 2 /* entire packet size in bytes */
#define TXP_FRAGCNT 3 /* # fragments in packet */
#define TXP_FRAGOFF 4 /* offset to first fragment */
#define TXP_FRAGSIZE 3 /* size of each fragment desc */
#define TXP_FPTRLO 0 /* ptr to packet fragment LO */
#define TXP_FPTRHI 1 /* ptr to packet fragment HI */
#define TXP_FSIZE 2 /* fragment size */
#define TXP_WORDS (TXP_FRAGOFF + (FRAGMAX*TXP_FRAGSIZE) + 1) /* 1 for tlink */
#define TXP_SIZE(sc) ((sc->bitmode) ? (TXP_WORDS*4) : (TXP_WORDS*2))
#define EOL 0x0001 /* end of list marker for link fields */
/*
* CDA, the CAM descriptor area. The SONIC has a 16 entry CAM to
* match incoming addresses against. It is programmed via DMA
* from a memory region.
*/
#define MAXCAM 16 /* number of user entries in CAM */
#define CDA_CAMDESC 4 /* # words i na descriptor */
#define CDA_CAMEP 0 /* CAM Address Port 0 xx-xx-xx-xx-YY-YY */
#define CDA_CAMAP0 1 /* CAM Address Port 1 xx-xx-YY-YY-xx-xx */
#define CDA_CAMAP1 2 /* CAM Address Port 2 YY-YY-xx-xx-xx-xx */
#define CDA_CAMAP2 3
#define CDA_ENABLE 64 /* mask enabling CAM entries */
#define CDA_SIZE(sc) ((4*16 + 1) * ((sc->bitmode) ? 4 : 2))
void sncconfig __P((struct snc_softc *, int *, int, int, u_int8_t *));
void sncintr __P((void *));
void sncshutdown __P((void *));

258
sys/dev/snc/if_snc.c Normal file
View File

@ -0,0 +1,258 @@
/*
* Copyright (c) 1995, David Greenman
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/*
* National Semiconductor DP8393X SONIC Driver
*
* This is the bus independent attachment on FreeBSD 4.x
* written by Motomichi Matsuzaki <mzaki@e-mail.ne.jp>
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/syslog.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <machine/resource.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/if_media.h>
#include <net/if_dl.h>
#include <net/if_mib.h>
#include <net/bpf.h>
#include "opt_bdg.h"
#ifdef BRIDGE
#include <net/bridge.h>
#endif
#include <dev/snc/dp83932reg.h>
#include <dev/snc/dp83932var.h>
#include <dev/snc/dp83932subr.h>
#include <dev/snc/if_sncreg.h>
#include <dev/snc/if_sncvar.h>
/* devclass for "snc" */
devclass_t snc_devclass;
/****************************************************************
Resource management functions
****************************************************************/
/*
* Allocate a port resource with the given resource id.
*/
int
snc_alloc_port(dev, rid)
device_t dev;
int rid;
{
struct snc_softc *sc = device_get_softc(dev);
struct resource *res;
res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
0ul, ~0ul, SNEC_NREGS, RF_ACTIVE);
if (res) {
sc->ioport = res;
sc->ioport_rid = rid;
sc->sc_iot = rman_get_bustag(res);
sc->sc_ioh = rman_get_bushandle(res);
return (0);
} else {
u_long start, count;
bus_get_resource(dev, SYS_RES_IOPORT, rid, &start, &count);
printf("snc_alloc_port: can't assign port 0x%lx-0x%lx\n",
start, start + count - 1);
return (ENOENT);
}
}
/*
* Allocate a memory resource with the given resource id.
*/
int
snc_alloc_memory(dev, rid)
device_t dev;
int rid;
{
struct snc_softc *sc = device_get_softc(dev);
struct resource *res;
res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
0ul, ~0ul, SNEC_NMEMS, RF_ACTIVE);
if (res) {
sc->iomem = res;
sc->iomem_rid = rid;
sc->sc_memt = rman_get_bustag(res);
sc->sc_memh = rman_get_bushandle(res);
return (0);
} else {
u_long start, count;
bus_get_resource(dev, SYS_RES_MEMORY, rid, &start, &count);
printf("snc_alloc_memory: can't assign memory 0x%lx-0x%lx\n",
start, start + count - 1);
return (ENOENT);
}
}
/*
* Allocate an irq resource with the given resource id.
*/
int
snc_alloc_irq(dev, rid, flags)
device_t dev;
int rid;
int flags;
{
struct snc_softc *sc = device_get_softc(dev);
struct resource *res;
res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
0ul, ~0ul, 1, (RF_ACTIVE | flags));
if (res) {
sc->irq = res;
sc->irq_rid = rid;
return (0);
} else {
printf("snc_alloc_irq: can't assign irq %ld\n",
bus_get_resource_start(dev, SYS_RES_IRQ, rid));
return (ENOENT);
}
}
/*
* Release all resources
*/
void
snc_release_resources(dev)
device_t dev;
{
struct snc_softc *sc = device_get_softc(dev);
if (sc->ioport) {
bus_release_resource(dev, SYS_RES_IOPORT,
sc->ioport_rid, sc->ioport);
sc->ioport = 0;
}
if (sc->iomem) {
bus_release_resource(dev, SYS_RES_MEMORY,
sc->iomem_rid, sc->iomem);
sc->iomem = 0;
}
if (sc->irq) {
bus_release_resource(dev, SYS_RES_IRQ,
sc->irq_rid, sc->irq);
sc->irq = 0;
}
}
/****************************************************************
Probe routine
****************************************************************/
int
snc_probe(dev, type)
device_t dev;
int type;
{
struct snc_softc *sc = device_get_softc(dev);
return snc_nec16_detectsubr(sc->sc_iot, sc->sc_ioh,
sc->sc_memt, sc->sc_memh,
rman_get_start(sc->irq),
rman_get_start(sc->iomem),
type);
}
/****************************************************************
Attach routine
****************************************************************/
int
snc_attach(dev)
device_t dev;
{
struct snc_softc *sc = device_get_softc(dev);
u_int8_t myea[ETHER_ADDR_LEN];
if (snc_nec16_register_irq(sc, rman_get_start(sc->irq)) == 0 ||
snc_nec16_register_mem(sc, rman_get_start(sc->iomem)) == 0) {
snc_release_resources(dev);
return(ENOENT);
}
snc_nec16_get_enaddr(sc->sc_iot, sc->sc_ioh, myea);
device_printf(dev, "%s Ethernet\n", snc_nec16_detect_type(myea));
sc->sc_dev = dev;
sc->sncr_dcr = DCR_SYNC | DCR_WAIT0 |
DCR_DMABLOCK | DCR_RFT16 | DCR_TFT28;
sc->sncr_dcr2 = 0; /* XXX */
sc->bitmode = 0; /* 16 bit card */
sc->sc_nic_put = snc_nec16_nic_put;
sc->sc_nic_get = snc_nec16_nic_get;
sc->sc_writetodesc = snc_nec16_writetodesc;
sc->sc_readfromdesc = snc_nec16_readfromdesc;
sc->sc_copytobuf = snc_nec16_copytobuf;
sc->sc_copyfrombuf = snc_nec16_copyfrombuf;
sc->sc_zerobuf = snc_nec16_zerobuf;
/* sncsetup returns 1 if something fails */
if (sncsetup(sc, myea)) {
snc_release_resources(dev);
return(ENOENT);
}
sncconfig(sc, NULL, 0, 0, myea);
return 0;
}
/****************************************************************
Shutdown routine
****************************************************************/
void
snc_shutdown(dev)
device_t dev;
{
sncshutdown(device_get_softc(dev));
}

224
sys/dev/snc/if_snc_cbus.c Normal file
View File

@ -0,0 +1,224 @@
/*
* Copyright (c) 1995, David Greenman
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/*
* National Semiconductor DP8393X SONIC Driver
*
* This is the C-bus specific attachment on FreeBSD
* written by Motomichi Matsuzaki <mzaki@e-mail.ne.jp>
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/socket.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <machine/resource.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/if_media.h>
#include <net/if_mib.h>
#include <isa/isavar.h>
#include <isa/pnpvar.h>
#include <sys/malloc.h> /* as dependency for isa/isa_common.h */
#include <isa/isa_common.h> /* for snc_isapnp_reconfig() */
#include <dev/snc/dp83932var.h>
#include <dev/snc/dp83932subr.h>
#include <dev/snc/if_sncreg.h>
#include <dev/snc/if_sncvar.h>
static void snc_isapnp_reconfig __P((device_t));
static int snc_isa_probe __P((device_t));
static int snc_isa_attach __P((device_t));
static struct isa_pnp_id snc_ids[] = {
{ 0x6180a3b8, NULL }, /* NEC8061 NEC PC-9801-104 */
{ 0, NULL }
};
static void
snc_isapnp_reconfig(dev)
device_t dev;
{
struct isa_device *idev = DEVTOISA(dev);
struct isa_config config;
u_long start, count;
int rid;
bzero(&config, sizeof(config));
for (rid = 0; rid < ISA_NMEM; rid++) {
if (bus_get_resource(dev, SYS_RES_MEMORY, rid, &start, &count))
break;
config.ic_mem[rid].ir_start = start;
config.ic_mem[rid].ir_end = start;
config.ic_mem[rid].ir_size = count;
}
config.ic_nmem = rid;
for (rid = 0; rid < ISA_NPORT; rid++) {
if (bus_get_resource(dev, SYS_RES_IOPORT, rid, &start, &count))
break;
config.ic_port[rid].ir_start = start;
config.ic_port[rid].ir_end = start;
config.ic_port[rid].ir_size = count;
}
config.ic_nport = rid;
for (rid = 0; rid < ISA_NIRQ; rid++) {
if (bus_get_resource(dev, SYS_RES_IRQ, rid, &start, &count))
break;
config.ic_irqmask[rid] = 1 << start;
}
config.ic_nirq = rid;
for (rid = 0; rid < ISA_NDRQ; rid++) {
if (bus_get_resource(dev, SYS_RES_DRQ, rid, &start, &count))
break;
config.ic_drqmask[rid] = 1 << start;
}
config.ic_ndrq = rid;
idev->id_config_cb(idev->id_config_arg, &config, 1);
}
static int
snc_isa_probe(dev)
device_t dev;
{
struct snc_softc *sc = device_get_softc(dev);
int type;
int error = 0;
bzero(sc, sizeof(struct snc_softc));
/* Check isapnp ids */
error = ISA_PNP_PROBE(device_get_parent(dev), dev, snc_ids);
/* If the card had a PnP ID that didn't match any we know about */
if (error == ENXIO) {
return(error);
}
switch (error) {
case 0: /* Matched PnP */
type = SNEC_TYPE_PNP;
break;
case ENOENT: /* Legacy ISA */
type = SNEC_TYPE_LEGACY;
break;
default: /* If we had some other problem. */
return(error);
}
if (type == SNEC_TYPE_PNP && isa_get_portsize(dev) == 0) {
int port;
int rid = 0;
struct resource *res = NULL;
for (port = 0x0888; port <= 0x3888; port += 0x1000) {
bus_set_resource(dev, SYS_RES_IOPORT, rid,
port, SNEC_NREGS);
res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
0, ~0, SNEC_NREGS,
0 /* !RF_ACTIVE */);
if (res) break;
}
printf("snc_isa_probe: broken PnP resource, ");
if (res) {
printf("use port 0x%x\n", port);
bus_release_resource(dev, SYS_RES_IOPORT, rid, res);
snc_isapnp_reconfig(dev);
} else {
printf("and can't find port\n");
}
}
error = snc_alloc_port(dev, 0);
error = max(error, snc_alloc_memory(dev, 0));
error = max(error, snc_alloc_irq(dev, 0, 0));
if (!error && !snc_probe(dev, type))
error = ENOENT;
snc_release_resources(dev);
return (error);
}
static int
snc_isa_attach(dev)
device_t dev;
{
struct snc_softc *sc = device_get_softc(dev);
int error;
bzero(sc, sizeof(struct snc_softc));
snc_alloc_port(dev, 0);
snc_alloc_memory(dev, 0);
snc_alloc_irq(dev, 0, 0);
error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET,
sncintr, sc, &sc->irq_handle);
if (error) {
printf("snc_isa_attach: bus_setup_intr() failed\n");
snc_release_resources(dev);
return (error);
}
/* This interface is always enabled. */
sc->sc_enabled = 1;
return snc_attach(dev);
}
static device_method_t snc_isa_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, snc_isa_probe),
DEVMETHOD(device_attach, snc_isa_attach),
DEVMETHOD(device_shutdown, snc_shutdown),
{ 0, 0 }
};
static driver_t snc_isa_driver = {
"snc",
snc_isa_methods,
sizeof(struct snc_softc)
};
DRIVER_MODULE(if_snc, isa, snc_isa_driver, snc_devclass, 0, 0);

160
sys/dev/snc/if_snc_pccard.c Normal file
View File

@ -0,0 +1,160 @@
/*
* Copyright (c) 1995, David Greenman
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/*
* National Semiconductor DP8393X SONIC Driver
*
* This is the PC-Card attachment on FreeBSD
* written by Motomichi Matsuzaki <mzaki@e-mail.ne.jp> and
* Hiroshi Yamashita <bluemoon@msj.biglobe.ne.jp>
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/socket.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/if_media.h>
#include <net/if_mib.h>
#include <dev/pccard/pccardvar.h>
#include <dev/snc/dp83932var.h>
#include <dev/snc/dp83932reg.h>
#include <dev/snc/if_sncvar.h>
#include <dev/snc/if_sncreg.h>
/*
* PC-Card (PCMCIA) specific code.
*/
static int snc_pccard_probe(device_t);
static int snc_pccard_attach(device_t);
static int snc_pccard_detach(device_t);
static device_method_t snc_pccard_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, snc_pccard_probe),
DEVMETHOD(device_attach, snc_pccard_attach),
DEVMETHOD(device_detach, snc_pccard_detach),
{ 0, 0 }
};
static driver_t snc_pccard_driver = {
"snc",
snc_pccard_methods,
sizeof(struct snc_softc)
};
DRIVER_MODULE(if_snc, pccard, snc_pccard_driver, snc_devclass, 0, 0);
/*
* snc_pccard_detach - unload the driver and clear the table.
* XXX TODO:
* This is usually called when the card is ejected, but
* can be caused by a modunload of a controller driver.
* The idea is to reset the driver's view of the device
* and ensure that any driver entry points such as
* read and write do not hang.
*/
static int
snc_pccard_detach(device_t dev)
{
struct snc_softc *sc = device_get_softc(dev);
struct ifnet *ifp = &sc->sc_if;
if (sc->gone) {
device_printf(dev, "already unloaded\n");
return (0);
}
sncshutdown(sc);
ifp->if_flags &= ~IFF_RUNNING;
if_detach(ifp);
sc->gone = 1;
bus_teardown_intr(dev, sc->irq, sc->irq_handle);
snc_release_resources(dev);
return (0);
}
/*
* Probe framework for pccards. Replicates the standard framework,
* minus the pccard driver registration and ignores the ether address
* supplied (from the CIS), relying on the probe to find it instead.
*/
static int
snc_pccard_probe(device_t dev)
{
int error;
error = snc_alloc_port(dev, 0);
error = max(error, snc_alloc_memory(dev, 0));
error = max(error, snc_alloc_irq(dev, 0, 0));
if (!error && !snc_probe(dev, SNEC_TYPE_PNP))
error = ENOENT;
snc_release_resources(dev);
return (error);
}
static int
snc_pccard_attach(device_t dev)
{
struct snc_softc *sc = device_get_softc(dev);
int error;
bzero(sc, sizeof(struct snc_softc));
snc_alloc_port(dev, 0);
snc_alloc_memory(dev, 0);
snc_alloc_irq(dev, 0, 0);
error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET,
sncintr, sc, &sc->irq_handle);
if (error) {
printf("snc_isa_attach: bus_setup_intr() failed\n");
snc_release_resources(dev);
return (error);
}
/* This interface is always enabled. */
sc->sc_enabled = 1;
/* pccard_get_ether(dev, ether_addr); */
return snc_attach(dev);
}

140
sys/dev/snc/if_sncreg.h Normal file
View File

@ -0,0 +1,140 @@
/* $FreeBSD$ */
/* $NecBSD: if_snreg.h,v 1.3 1999/01/24 01:39:52 kmatsuda Exp $ */
/* $NetBSD$ */
/*
* Copyright (c) 1997, 1998, 1999
* Kouichi Matsuda. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Kouichi Matsuda for
* NetBSD/pc98.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Modified for NetBSD/pc98 1.2.1 from NetBSD/mac68k 1.2D by Kouichi Matsuda.
* Make adapted for NEC PC-9801-83, 84, PC-9801-103, 104, PC-9801N-25 and
* PC-9801N-J02R, which uses National Semiconductor DP83934AVQB as
* Ethernet Controller and National Semiconductor NS46C46 as (64 * 16 bits)
* Microwire Serial EEPROM.
*/
/*
* XXX: Should not be HERE. (Should be shared with...)
*/
/*
* NEC/SONIC port mappings, offset from iobase.
*/
#define SNEC_CTRL 0 /* SONIC control port (word) */
#define SNEC_CTRLB 1 /* NEC/SONIC control port (byte) */
#define SNEC_RSVD0 2 /* not used */
#define SNEC_ADDR 3 /* SONIC, NEC/SONIC register address set port */
#define SNEC_RSVD1 4 /* not used */
#define SNEC_RSVD2 5 /* not used */
#define SNEC_NREGS 6
/* bank memory size */
#define SNEC_NMEMS (NBPG * 2)
/* how many bank */
#define SNEC_NBANK 0x10
/* internal buffer size */
#define SNEC_NBUF (SNEC_NMEMS * SNEC_NBANK)
/*
* NEC/SONIC specific internal registers.
*/
/*
* Memory Bank Select Register (MEMBS)
*/
#define SNECR_MEMBS 0x80
#define SNECR_MEMBS_BSEN 0x01 /* enable memory bank select */
#define SNECR_MEMBS_EBNMSK 0x1c /* encoded bank select number */
/* Translate bank number to encoded bank select number. */
#define SNECR_MEMBS_B2EB(bank) (bank << 2)
#define SNECR_MEMBS_PCMCIABUS 0x80 /* bus type identification */
/*
* Memory Base Address Select Register (MEMSEL)
*/
#define SNECR_MEMSEL 0x82
/* Translate base phys address to encoded select number. */
#define SNECR_MEMSEL_PHYS2EN(maddr) ((maddr >> 13) & 0x0f)
/*
* Encoded Irq Select Register (IRQSEL)
*/
#define SNECR_IRQSEL 0x84
/*
* EEPROM Access Register (EEP)
*/
#define SNECR_EEP 0x86
#define SNECR_EEP_DI 0x10 /* EEPROM Serial Data Input (high) */
#define SNECR_EEP_CS 0x20 /* EEPROM Chip Select (high) */
#define SNECR_EEP_SK 0x40 /* EEPROM Serial Data Clock (high) */
#define SNECR_EEP_DO 0x80 /* EEPROM Serial Data Output (high) */
/* EEPROM data locations */
#define SNEC_EEPROM_KEY0 6 /* Station Address Check Sum Key #1 */
#define SNEC_EEPROM_KEY1 7 /* Station Address Check Sum Key #2 */
#define SNEC_EEPROM_SA0 8 /* Station Address #1 */
#define SNEC_EEPROM_SA1 9 /* Station Address #2 */
#define SNEC_EEPROM_SA2 10 /* Station Address #3 */
#define SNEC_EEPROM_SA3 11 /* Station Address #4 */
#define SNEC_EEPROM_SA4 12 /* Station Address #5 */
#define SNEC_EEPROM_SA5 13 /* Station Address #6 */
#define SNEC_EEPROM_CKSUM 14 /* Station Address Check Sum */
#define SNEC_EEPROM_SIZE 32 /* valid EEPROM data (max 128 bytes) */
/*
* Bus and Mode Identification Register (IDENT)
*/
#define SNECR_IDENT 0x88
/* Bit 0: Bus Identification. */
#define SNECR_IDENT_CBUS 0x01 /* on PC-98 C-Bus */
#define SNECR_IDENT_PCMCIABUS 0x00 /* on PCMCIA Bus */
/* Bit 2: always 1 */
#define SNECR_IDENT_MAGIC 0x04
/* Bit 4: Bus Configuration Mode Identification. */
#define SNECR_IDENT_PNP 0x10 /* Plug and Play (C-Bus and PCMCIA) */
#define SNECR_IDENT_LEGACY 0x00 /* Legacy C-Bus */
#define SNECR_IDENT_LEGACY_CBUS \
(SNECR_IDENT_LEGACY | SNECR_IDENT_MAGIC | SNECR_IDENT_CBUS)
#define SNECR_IDENT_PNP_CBUS \
(SNECR_IDENT_PNP | SNECR_IDENT_MAGIC | SNECR_IDENT_CBUS)
#define SNECR_IDENT_PNP_PCMCIABUS \
(SNECR_IDENT_PNP | SNECR_IDENT_MAGIC | SNECR_IDENT_PCMCIABUS)
/*
* XXX: parent bus type aliases
*/
#define SNEC_TYPE_LEGACY 0
#define SNEC_TYPE_PNP 1

47
sys/dev/snc/if_sncvar.h Normal file
View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 1995, David Greenman
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/*
* National Semiconductor DP8393X SONIC Driver
*
* This is the machine dependent attachment on FreeBSD 4.x
* written by Motomichi Matsuzaki <mzaki@e-mail.ne.jp>
*/
extern devclass_t snc_devclass;
void snc_release_resources __P((device_t));
int snc_alloc_port __P((device_t, int));
int snc_alloc_memory __P((device_t, int));
int snc_alloc_irq __P((device_t, int, int));
int snc_probe __P((device_t, int));
int snc_attach __P((device_t));
void snc_shutdown __P((device_t));

View File

@ -21,6 +21,10 @@ SUBDIR+=aac asr bktr coff fpu gnufpu ibcs2 linprocfs linux mly splash streams \
svr4 vesa wi
.endif
.if ${MACHINE} == "pc98"
SUBDIR+=snc
.endif
.if ${MACHINE_ARCH} == "alpha"
SUBDIR+=osf1
.endif

11
sys/modules/snc/Makefile Normal file
View File

@ -0,0 +1,11 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../dev/snc
KMOD = if_snc
SRCS = if_snc.c if_snc_cbus.c if_snc_pccard.c dp83932.c dp83932subr.c
SRCS += opt_inet.h opt_bdg.h device_if.h bus_if.h isa_if.h
opt_inet.h:
echo "#define INET 1" > ${.TARGET}
.include <bsd.kmod.mk>

View File

@ -181,6 +181,7 @@ device fe
device ep
device lnc
device sn
device snc
# WaveLAN/IEEE 802.11 wireless NICs. Note: the WaveLAN/IEEE really
# exists only as a PCMCIA device, so there is no ISA attatement needed

View File

@ -275,6 +275,11 @@ hint.lnc.0.at="isa"
hint.lnc.0.port="0x03d0"
hint.lnc.0.irq="6"
hint.snc.0.at="isa"
hint.snc.0.port="0x888"
hint.snc.0.irq="6"
hint.snc.0.maddr="0xc0000"
# The VoxWare sound drivers
#hint.sb.0.at="isa"
#hint.sb.0.port="0x20d2"

View File

@ -370,6 +370,7 @@ static DEV_INFO device_info[] = {
{"le", "DEC Etherworks 2 and 3 Ethernet adapters", 0, CLS_NETWORK},
{"lnc", "Isolan, Novell NE2100/NE32-VL Ethernet adapters", 0,CLS_NETWORK},
{"sn", "SMC/Megahertz Ethernet adapters", 0,CLS_NETWORK},
{"snc", "SONIC Ethernet adapters", 0,CLS_NETWORK},
{"xe", "Xircom PC Card Ethernet adapter", 0, CLS_NETWORK},
{"rdp", "RealTek RTL8002 Pocket Ethernet", 0, CLS_NETWORK},

View File

@ -118,6 +118,7 @@ static struct _devname {
{ DEVICE_TYPE_NETWORK, "lp", "Parallel Port IP (PLIP) peer connection" },
{ DEVICE_TYPE_NETWORK, "lo", "Loop-back (local) network interface" },
#ifdef PC98
{ DEVICE_TYPE_NETWORK, "snc", "SONIC ethernet card" },
{ DEVICE_TYPE_DISK, "wd%d", "IDE disk device", 3, 65538, 8, 16 },
{ DEVICE_TYPE_CDROM, "wcd%dc", "ATAPI IDE CDROM", 69, 2, 8, 4 },
{ DEVICE_TYPE_FLOPPY, "wfd%d", "ATAPI floppy drive unit A", 87, 0, 8, 4 },

View File

@ -118,6 +118,7 @@ static struct _devname {
{ DEVICE_TYPE_NETWORK, "lp", "Parallel Port IP (PLIP) peer connection" },
{ DEVICE_TYPE_NETWORK, "lo", "Loop-back (local) network interface" },
#ifdef PC98
{ DEVICE_TYPE_NETWORK, "snc", "SONIC ethernet card" },
{ DEVICE_TYPE_DISK, "wd%d", "IDE disk device", 3, 65538, 8, 16 },
{ DEVICE_TYPE_CDROM, "wcd%dc", "ATAPI IDE CDROM", 69, 2, 8, 4 },
{ DEVICE_TYPE_FLOPPY, "wfd%d", "ATAPI floppy drive unit A", 87, 0, 8, 4 },