From dbaca003300c38de22547c5f9a523153ba4892d6 Mon Sep 17 00:00:00 2001 From: yamt Date: Mon, 26 Nov 2001 19:17:05 +0000 Subject: [PATCH] move dev/isa/cs89x0{.c,{var,reg}.h} into dev/ic and split isadma parts into /dev/isa/cs89x0isa*. --- sys/conf/files | 6 +- sys/dev/{isa => ic}/cs89x0.c | 328 ++---------------------------- sys/dev/{isa => ic}/cs89x0reg.h | 8 +- sys/dev/{isa => ic}/cs89x0var.h | 24 ++- sys/dev/isa/cs89x0isa.c | 340 ++++++++++++++++++++++++++++++++ sys/dev/isa/cs89x0isavar.h | 16 ++ sys/dev/isa/files.isa | 9 +- sys/dev/isa/if_cs_isa.c | 20 +- sys/dev/ofisa/files.ofisa | 4 +- sys/dev/ofisa/if_cs_ofisa.c | 24 ++- sys/dev/pcmcia/if_cs_pcmcia.c | 11 +- 11 files changed, 431 insertions(+), 359 deletions(-) rename sys/dev/{isa => ic}/cs89x0.c (85%) rename sys/dev/{isa => ic}/cs89x0reg.h (98%) rename sys/dev/{isa => ic}/cs89x0var.h (93%) create mode 100644 sys/dev/isa/cs89x0isa.c create mode 100644 sys/dev/isa/cs89x0isavar.h diff --git a/sys/conf/files b/sys/conf/files index 1b864c5f0333..d2aab595e7e9 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $NetBSD: files,v 1.470 2001/11/20 14:34:25 lukem Exp $ +# $NetBSD: files,v 1.471 2001/11/26 19:17:05 yamt Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -591,6 +591,10 @@ file dev/ic/we.c we device ate: arp, ether, ifnet, mb86960 file dev/ic/ate_subr.c ate +# Crystal Semiconductor CS8900, CS8920, and CS8920M Ethernet +device cs: arp, ether, ifnet +file dev/ic/cs89x0.c cs + # Definitions for wscons # device attributes: display, display with emulator, keyboard, and mouse define wsdisplaydev {[kbdmux = -1]} diff --git a/sys/dev/isa/cs89x0.c b/sys/dev/ic/cs89x0.c similarity index 85% rename from sys/dev/isa/cs89x0.c rename to sys/dev/ic/cs89x0.c index ca984181706f..e8539088d47b 100644 --- a/sys/dev/isa/cs89x0.c +++ b/sys/dev/ic/cs89x0.c @@ -1,4 +1,4 @@ -/* $NetBSD: cs89x0.c,v 1.22 2001/11/26 11:14:50 yamt Exp $ */ +/* $NetBSD: cs89x0.c,v 1.1 2001/11/26 19:17:08 yamt Exp $ */ /* * Copyright 1997 @@ -186,7 +186,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: cs89x0.c,v 1.22 2001/11/26 11:14:50 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cs89x0.c,v 1.1 2001/11/26 19:17:08 yamt Exp $"); #include "opt_inet.h" @@ -224,12 +224,8 @@ __KERNEL_RCSID(0, "$NetBSD: cs89x0.c,v 1.22 2001/11/26 11:14:50 yamt Exp $"); #include #include -#include -#include -#include - -#include -#include +#include +#include #ifdef SHARK #include @@ -239,8 +235,6 @@ __KERNEL_RCSID(0, "$NetBSD: cs89x0.c,v 1.22 2001/11/26 11:14:50 yamt Exp $"); * MACRO DEFINITIONS */ #define CS_OUTPUT_LOOP_MAX 100 /* max times round notorious tx loop */ -#define DMA_STATUS_BITS 0x0007 /* bit masks for checking DMA status */ -#define DMA_STATUS_OK 0x0004 /* * FUNCTION PROTOTYPES @@ -249,23 +243,19 @@ void cs_get_default_media __P((struct cs_softc *)); int cs_get_params __P((struct cs_softc *)); int cs_get_enaddr __P((struct cs_softc *)); int cs_reset_chip __P((struct cs_softc *)); -int cs_init __P((struct ifnet *)); void cs_reset __P((void *)); int cs_ioctl __P((struct ifnet *, u_long, caddr_t)); void cs_initChip __P((struct cs_softc *)); void cs_buffer_event __P((struct cs_softc *, u_int16_t)); void cs_transmit_event __P((struct cs_softc *, u_int16_t)); void cs_receive_event __P((struct cs_softc *, u_int16_t)); -void cs_ether_input __P((struct cs_softc *, struct mbuf *)); void cs_process_receive __P((struct cs_softc *)); void cs_process_rx_early __P((struct cs_softc *)); -void cs_process_rx_dma __P((struct cs_softc *)); void cs_start_output __P((struct ifnet *)); void cs_copy_tx_frame __P((struct cs_softc *, struct mbuf *)); void cs_set_ladr_filt __P((struct cs_softc *, struct ethercom *)); u_int16_t cs_hash_index __P((char *)); void cs_counter_event __P((struct cs_softc *, u_int16_t)); -void cs_print_rx_errors __P((struct cs_softc *, u_int16_t)); int cs_mediachange __P((struct ifnet *)); void cs_mediastatus __P((struct ifnet *, struct ifmediareq *)); @@ -447,51 +437,8 @@ cs_attach(sc, enaddr, media, nmedia, defmedia) chipname, sc->sc_prodrev + 'A', ether_sprintf(sc->sc_enaddr), medname); - if (sc->sc_drq == ISACF_DRQ_DEFAULT) - printf("%s: DMA channel unspecified, not using DMA\n", - sc->sc_dev.dv_xname); - else if (sc->sc_drq < 5 || sc->sc_drq > 7) - printf("%s: invalid DMA channel, not using DMA\n", - sc->sc_dev.dv_xname); - else { - bus_size_t maxsize; - bus_addr_t dma_addr; - - maxsize = isa_dmamaxsize(sc->sc_ic, sc->sc_drq); - if (maxsize < CS8900_DMASIZE) { - printf("%s: max DMA size %lu is less than required %d\n", - sc->sc_dev.dv_xname, (u_long)maxsize, - CS8900_DMASIZE); - goto after_dma_block; - } - - if (isa_dmamap_create(sc->sc_ic, sc->sc_drq, - CS8900_DMASIZE, BUS_DMA_NOWAIT) != 0) { - printf("%s: unable to create ISA DMA map\n", - sc->sc_dev.dv_xname); - goto after_dma_block; - } - if (isa_dmamem_alloc(sc->sc_ic, sc->sc_drq, - CS8900_DMASIZE, &dma_addr, BUS_DMA_NOWAIT) != 0) { - printf("%s: unable to allocate DMA buffer\n", - sc->sc_dev.dv_xname); - goto after_dma_block; - } - if (isa_dmamem_map(sc->sc_ic, sc->sc_drq, dma_addr, - CS8900_DMASIZE, &sc->sc_dmabase, - BUS_DMA_NOWAIT | BUS_DMA_COHERENT /* XXX */ ) != 0) { - printf("%s: unable to map DMA buffer\n", - sc->sc_dev.dv_xname); - isa_dmamem_free(sc->sc_ic, sc->sc_drq, dma_addr, - CS8900_DMASIZE); - goto after_dma_block; - } - - sc->sc_dmasize = CS8900_DMASIZE; - sc->sc_cfgflags |= CFGFLG_DMA_MODE; - sc->sc_dmaaddr = dma_addr; - } - after_dma_block: + if (sc->sc_dma_attach) + (*sc->sc_dma_attach)(sc); sc->sc_sh = shutdownhook_establish(cs_reset, sc); if (sc->sc_sh == NULL) { @@ -909,40 +856,8 @@ cs_initChip(sc) CS_WRITE_PACKET_PAGE(sc, PKTPG_BUF_CFG, BUF_CFG_TX_UNDR_IE | BUF_CFG_RX_DMA_IE); - if (sc->sc_cfgflags & CFGFLG_DMA_MODE) { - /* - * First we program the DMA controller and ensure the memory - * buffer is valid. If it isn't then we just go on without - * DMA. - */ - if (isa_dmastart(sc->sc_ic, sc->sc_drq, sc->sc_dmabase, - sc->sc_dmasize, NULL, DMAMODE_READ | DMAMODE_LOOPDEMAND, - BUS_DMA_NOWAIT)) { - /* XXX XXX XXX */ - panic("%s: unable to start DMA\n", sc->sc_dev.dv_xname); - } - sc->sc_dmacur = sc->sc_dmabase; - - /* interrupt when a DMA'd frame is received */ - CS_WRITE_PACKET_PAGE(sc, PKTPG_RX_CFG, - RX_CFG_ALL_IE | RX_CFG_RX_DMA_ONLY); - - /* - * set the DMA burst bit so we don't tie up the bus for too - * long. - */ - if (sc->sc_dmasize == 16384) { - CS_WRITE_PACKET_PAGE(sc, PKTPG_BUS_CTL, - ((CS_READ_PACKET_PAGE(sc, PKTPG_BUS_CTL) & - ~BUS_CTL_DMA_SIZE) | BUS_CTL_DMA_BURST)); - } else { /* use 64K */ - CS_WRITE_PACKET_PAGE(sc, PKTPG_BUS_CTL, - CS_READ_PACKET_PAGE(sc, PKTPG_BUS_CTL) | - BUS_CTL_DMA_SIZE | BUS_CTL_DMA_BURST); - } - - CS_WRITE_PACKET_PAGE(sc, PKTPG_DMA_CHANNEL, sc->sc_drq - 5); - } + if (sc->sc_dma_chipinit) + (*sc->sc_dma_chipinit)(sc); /* If memory mode is enabled */ if (sc->sc_cfgflags & CFGFLG_MEM_MODE) { @@ -1436,7 +1351,11 @@ cs_buffer_event(sc, bufEvent) if (bufEvent & BUF_EVENT_RX_DMA) { /* process the receive data */ - cs_process_rx_dma(sc); + if (sc->sc_dma_process_rx) + (*sc->sc_dma_process_rx)(sc); + else + /* should panic? */ + printf("%s: unexpected dma event\n", sc->sc_dev.dv_xname); } if (bufEvent & BUF_EVENT_TX_UNDR) { @@ -1717,225 +1636,6 @@ cs_process_receive(sc) cs_ether_input(sc, m); } -void -cs_process_rx_dma(sc) - struct cs_softc *sc; -{ - struct ifnet *ifp; - u_int16_t num_dma_frames; - u_int16_t pkt_length; - u_int16_t status; - u_int to_copy; - char *dma_mem_ptr; - struct mbuf *m; - u_char *pBuff; - int pad; - - /* initialise the pointers */ - ifp = &sc->sc_ethercom.ec_if; - - /* Read the number of frames DMAed. */ - num_dma_frames = CS_READ_PACKET_PAGE(sc, PKTPG_DMA_FRAME_COUNT); - num_dma_frames &= (u_int16_t) (0x0fff); - - /* - * Loop till number of DMA frames ready to read is zero. After - * reading the frame out of memory we must check if any have been - * received while we were processing - */ - while (num_dma_frames != 0) { - dma_mem_ptr = sc->sc_dmacur; - - /* - * process all of the dma frames in memory - * - * This loop relies on the dma_mem_ptr variable being set to the - * next frames start address. - */ - for (; num_dma_frames > 0; num_dma_frames--) { - - /* - * Get the length and status of the packet. Only the - * status is guarenteed to be at dma_mem_ptr, ie need - * to check for wraparound before reading the length - */ - status = *((unsigned short *) dma_mem_ptr)++; - if (dma_mem_ptr > (sc->sc_dmabase + sc->sc_dmasize)) { - dma_mem_ptr = sc->sc_dmabase; - } - pkt_length = *((unsigned short *) dma_mem_ptr)++; - - /* Do some sanity checks on the length and status. */ - if ((pkt_length > ETHER_MAX_LEN) || - ((status & DMA_STATUS_BITS) != DMA_STATUS_OK)) { - /* - * the SCO driver kills the adapter in this - * situation - */ - /* - * should increment the error count and reset - * the dma operation. - */ - printf("%s: cs_process_rx_dma: DMA buffer out of sync about to reset\n", - sc->sc_dev.dv_xname); - ifp->if_ierrors++; - - /* skip the rest of the DMA buffer */ - isa_dmaabort(sc->sc_ic, sc->sc_drq); - - /* now reset the chip and reinitialise */ - cs_init(&sc->sc_ethercom.ec_if); - return; - } - /* Check the status of the received packet. */ - if (status & RX_EVENT_RX_OK) { - /* get a new mbuf */ - MGETHDR(m, M_DONTWAIT, MT_DATA); - if (m == 0) { - printf("%s: cs_process_rx_dma: unable to allocate mbuf\n", - sc->sc_dev.dv_xname); - ifp->if_ierrors++; - /* - * couldn't allocate an mbuf so - * things are not good, may as well - * drop all the packets I think. - */ - CS_READ_PACKET_PAGE(sc, - PKTPG_DMA_FRAME_COUNT); - - /* now reset DMA operation */ - isa_dmaabort(sc->sc_ic, sc->sc_drq); - - /* - * now reset the chip and - * reinitialise - */ - cs_init(&sc->sc_ethercom.ec_if); - return; - } - /* - * save processing by always using a mbuf - * cluster, guarenteed to fit packet - */ - MCLGET(m, M_DONTWAIT); - if ((m->m_flags & M_EXT) == 0) { - /* couldn't allocate an mbuf cluster */ - printf("%s: cs_process_rx_dma: unable to allocate a cluster\n", - sc->sc_dev.dv_xname); - m_freem(m); - - /* skip the frame */ - CS_READ_PACKET_PAGE(sc, PKTPG_DMA_FRAME_COUNT); - isa_dmaabort(sc->sc_ic, sc->sc_drq); - - /* - * now reset the chip and - * reinitialise - */ - cs_init(&sc->sc_ethercom.ec_if); - return; - } - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = pkt_length; - m->m_len = pkt_length; - - /* - * align ip header on word boundary for - * ipintr - */ - pad = ALIGN(sizeof(struct ether_header)) - - sizeof(struct ether_header); - m->m_data += pad; - - /* - * set up the buffer pointer to point to the - * data area - */ - pBuff = mtod(m, char *); - - /* - * Read the frame into free_pktbuf - * The buffer is circular buffer, either - * 16K or 64K in length. - * - * need to check where the end of the buffer - * is and go back to the start. - */ - if ((dma_mem_ptr + pkt_length) < - (sc->sc_dmabase + sc->sc_dmasize)) { - /* - * No wrap around. Copy the frame - * header - */ - memcpy(pBuff, dma_mem_ptr, pkt_length); - dma_mem_ptr += pkt_length; - } else { - to_copy = (u_int) - ((sc->sc_dmabase + sc->sc_dmasize) - - dma_mem_ptr); - - /* Copy the first half of the frame. */ - memcpy(pBuff, dma_mem_ptr, to_copy); - pBuff += to_copy; - - /* - * Rest of the frame is to be read - * from the first byte of the DMA - * memory. - */ - /* - * Get the number of bytes leftout in - * the frame. - */ - to_copy = pkt_length - to_copy; - - dma_mem_ptr = sc->sc_dmabase; - - /* Copy rest of the frame. */ - memcpy(pBuff, dma_mem_ptr, to_copy); - dma_mem_ptr += to_copy; - } - - cs_ether_input(sc, m); - } - /* (status & RX_OK) */ - else { - /* the frame was not received OK */ - /* Increment the input error count */ - ifp->if_ierrors++; - - /* - * If debugging is enabled then log error - * messages if we got any. - */ - if ((ifp->if_flags & IFF_DEBUG) && - status != REG_NUM_RX_EVENT) - cs_print_rx_errors(sc, status); - } - /* - * now update the current frame pointer. the - * dma_mem_ptr should point to the next packet to be - * received, without the alignment considerations. - * - * The cs8900 pads all frames to start at the next 32bit - * aligned addres. hence we need to pad our offset - * pointer. - */ - dma_mem_ptr += 3; - dma_mem_ptr = (char *) - ((long) dma_mem_ptr & 0xfffffffc); - if (dma_mem_ptr < (sc->sc_dmabase + sc->sc_dmasize)) { - sc->sc_dmacur = dma_mem_ptr; - } else { - dma_mem_ptr = sc->sc_dmacur = sc->sc_dmabase; - } - } /* for all frames */ - /* Read the number of frames DMAed again. */ - num_dma_frames = CS_READ_PACKET_PAGE(sc, PKTPG_DMA_FRAME_COUNT); - num_dma_frames &= (u_int16_t) (0x0fff); - } /* while there are frames left */ -} - void cs_process_rx_early(sc) struct cs_softc *sc; @@ -2372,7 +2072,7 @@ cs_power(why, arg) switch (why) { case PWR_STANDBY: case PWR_SUSPEND: - cs_stop(ifp, 1); + cs_stop(ifp, 0); break; case PWR_RESUME: if (ifp->if_flags & IFF_UP) { diff --git a/sys/dev/isa/cs89x0reg.h b/sys/dev/ic/cs89x0reg.h similarity index 98% rename from sys/dev/isa/cs89x0reg.h rename to sys/dev/ic/cs89x0reg.h index c8ada40a2a8e..1728f0e2321f 100644 --- a/sys/dev/isa/cs89x0reg.h +++ b/sys/dev/ic/cs89x0reg.h @@ -1,4 +1,4 @@ -/* $NetBSD: cs89x0reg.h,v 1.7 2001/11/24 20:18:55 yamt Exp $ */ +/* $NetBSD: cs89x0reg.h,v 1.1 2001/11/26 19:17:08 yamt Exp $ */ /* * Copyright 1997 @@ -54,8 +54,8 @@ **-- */ -#ifndef _DEV_ISA_CS89X0REG_H_ -#define _DEV_ISA_CS89X0REG_H_ +#ifndef _DEV_IC_CS89X0REG_H_ +#define _DEV_IC_CS89X0REG_H_ /* * The CS8900 has 8 2-byte registers in I/O space. @@ -374,4 +374,4 @@ #define RXBUFCOUNT 16 #define MC_LOANED 5 -#endif /* _DEV_ISA_CS89X0REG_H_ */ +#endif /* _DEV_IC_CS89X0REG_H_ */ diff --git a/sys/dev/isa/cs89x0var.h b/sys/dev/ic/cs89x0var.h similarity index 93% rename from sys/dev/isa/cs89x0var.h rename to sys/dev/ic/cs89x0var.h index 4636d1c40fa1..fb1655d20baf 100644 --- a/sys/dev/isa/cs89x0var.h +++ b/sys/dev/ic/cs89x0var.h @@ -1,4 +1,4 @@ -/* $NetBSD: cs89x0var.h,v 1.11 2001/11/26 11:14:50 yamt Exp $ */ +/* $NetBSD: cs89x0var.h,v 1.1 2001/11/26 19:17:08 yamt Exp $ */ /* * Copyright 1997 @@ -54,8 +54,8 @@ **-- */ -#ifndef _DEV_ISA_CS89X0VAR_H_ -#define _DEV_ISA_CS89X0VAR_H_ +#ifndef _DEV_IC_CS89X0VAR_H_ +#define _DEV_IC_CS89X0VAR_H_ /* * Ethernet software status per interface. @@ -78,21 +78,17 @@ struct cs_softc { bus_space_handle_t sc_ioh; /* bus space handles */ bus_space_handle_t sc_memh; +#if 0 isa_chipset_tag_t sc_ic; /* ISA chipset */ +#endif int sc_irq; /* IRQ line */ - int sc_drq; /* DRQ line */ int sc_prodid; /* saved product ID */ int sc_prodrev; /* saved product rev */ bus_addr_t sc_pktpgaddr; /* PacketPage bus memory address */ - bus_size_t sc_dmasize; /* DMA size (16k or 64k) */ - bus_addr_t sc_dmaaddr; /* DMA address */ - caddr_t sc_dmabase; /* base DMA address (KVA) */ - caddr_t sc_dmacur; /* current DMA address (KVA) */ - int sc_cfgflags; /* software configuration flags */ int sc_memorymode; /* are we in memory mode? */ @@ -114,6 +110,11 @@ struct cs_softc { int (*sc_enable) __P((struct cs_softc *)); void (*sc_disable) __P((struct cs_softc *)); void *sc_powerhook; + + /* dma hooks */ + void (*sc_dma_process_rx) __P((struct cs_softc *)); + void (*sc_dma_chipinit) __P((struct cs_softc *)); + void (*sc_dma_attach) __P((struct cs_softc *)); }; @@ -240,7 +241,10 @@ int cs_read_eeprom __P((bus_space_tag_t, bus_space_handle_t, int, u_int16_t *)); int cs_intr __P((void *)); int cs_activate __P((struct device *, enum devact)); +void cs_ether_input __P((struct cs_softc *, struct mbuf *)); +void cs_print_rx_errors __P((struct cs_softc *, u_int16_t)); +int cs_init __P((struct ifnet *)); #define CS_IS_ENABLED(sc) ((sc)->sc_cfgflags & CFGFLG_ENABLED) -#endif /* _DEV_ISA_CS89X0VAR_H_ */ +#endif /* _DEV_IC_CS89X0VAR_H_ */ diff --git a/sys/dev/isa/cs89x0isa.c b/sys/dev/isa/cs89x0isa.c new file mode 100644 index 000000000000..61f86802eb62 --- /dev/null +++ b/sys/dev/isa/cs89x0isa.c @@ -0,0 +1,340 @@ + +/* isa dma routines for cs89x0 */ + +#include +#include +#include +#include +#include + +#include "rnd.h" +#if NRND > 0 +#include +#endif + +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#define DMA_STATUS_BITS 0x0007 /* bit masks for checking DMA status */ +#define DMA_STATUS_OK 0x0004 + +void +cs_isa_dma_attach(struct cs_softc *sc) +{ + struct cs_softc_isa *isc = (void *)sc; + + if (isc->sc_drq == ISACF_DRQ_DEFAULT) + printf("%s: DMA channel unspecified, not using DMA\n", + sc->sc_dev.dv_xname); + else if (isc->sc_drq < 5 || isc->sc_drq > 7) + printf("%s: invalid DMA channel, not using DMA\n", + sc->sc_dev.dv_xname); + else { + bus_size_t maxsize; + bus_addr_t dma_addr; + + maxsize = isa_dmamaxsize(isc->sc_ic, isc->sc_drq); + if (maxsize < CS8900_DMASIZE) { + printf("%s: max DMA size %lu is less than required %d\n", + sc->sc_dev.dv_xname, (u_long)maxsize, + CS8900_DMASIZE); + goto after_dma_block; + } + + if (isa_dmamap_create(isc->sc_ic, isc->sc_drq, + CS8900_DMASIZE, BUS_DMA_NOWAIT) != 0) { + printf("%s: unable to create ISA DMA map\n", + sc->sc_dev.dv_xname); + goto after_dma_block; + } + if (isa_dmamem_alloc(isc->sc_ic, isc->sc_drq, + CS8900_DMASIZE, &dma_addr, BUS_DMA_NOWAIT) != 0) { + printf("%s: unable to allocate DMA buffer\n", + sc->sc_dev.dv_xname); + goto after_dma_block; + } + if (isa_dmamem_map(isc->sc_ic, isc->sc_drq, dma_addr, + CS8900_DMASIZE, &isc->sc_dmabase, + BUS_DMA_NOWAIT | BUS_DMA_COHERENT /* XXX */ ) != 0) { + printf("%s: unable to map DMA buffer\n", + sc->sc_dev.dv_xname); + isa_dmamem_free(isc->sc_ic, isc->sc_drq, dma_addr, + CS8900_DMASIZE); + goto after_dma_block; + } + + isc->sc_dmasize = CS8900_DMASIZE; + sc->sc_cfgflags |= CFGFLG_DMA_MODE; + isc->sc_dmaaddr = dma_addr; +after_dma_block: + } +} + +void cs_isa_dma_chipinit(struct cs_softc *sc) +{ + struct cs_softc_isa *isc = (void *)sc; + + if (sc->sc_cfgflags & CFGFLG_DMA_MODE) { + /* + * First we program the DMA controller and ensure the memory + * buffer is valid. If it isn't then we just go on without + * DMA. + */ + if (isa_dmastart(isc->sc_ic, isc->sc_drq, isc->sc_dmabase, + isc->sc_dmasize, NULL, DMAMODE_READ | DMAMODE_LOOPDEMAND, + BUS_DMA_NOWAIT)) { + /* XXX XXX XXX */ + panic("%s: unable to start DMA\n", sc->sc_dev.dv_xname); + } + isc->sc_dmacur = isc->sc_dmabase; + + /* interrupt when a DMA'd frame is received */ + CS_WRITE_PACKET_PAGE(sc, PKTPG_RX_CFG, + RX_CFG_ALL_IE | RX_CFG_RX_DMA_ONLY); + + /* + * set the DMA burst bit so we don't tie up the bus for too + * long. + */ + if (isc->sc_dmasize == 16384) { + CS_WRITE_PACKET_PAGE(sc, PKTPG_BUS_CTL, + ((CS_READ_PACKET_PAGE(sc, PKTPG_BUS_CTL) & + ~BUS_CTL_DMA_SIZE) | BUS_CTL_DMA_BURST)); + } else { /* use 64K */ + CS_WRITE_PACKET_PAGE(sc, PKTPG_BUS_CTL, + CS_READ_PACKET_PAGE(sc, PKTPG_BUS_CTL) | + BUS_CTL_DMA_SIZE | BUS_CTL_DMA_BURST); + } + + CS_WRITE_PACKET_PAGE(sc, PKTPG_DMA_CHANNEL, isc->sc_drq - 5); + } +} + +void cs_process_rx_dma(struct cs_softc *sc) +{ + struct cs_softc_isa *isc = (void *)sc; + struct ifnet *ifp; + u_int16_t num_dma_frames; + u_int16_t pkt_length; + u_int16_t status; + u_int to_copy; + char *dma_mem_ptr; + struct mbuf *m; + u_char *pBuff; + int pad; + + /* initialise the pointers */ + ifp = &sc->sc_ethercom.ec_if; + + /* Read the number of frames DMAed. */ + num_dma_frames = CS_READ_PACKET_PAGE(sc, PKTPG_DMA_FRAME_COUNT); + num_dma_frames &= (u_int16_t) (0x0fff); + + /* + * Loop till number of DMA frames ready to read is zero. After + * reading the frame out of memory we must check if any have been + * received while we were processing + */ + while (num_dma_frames != 0) { + dma_mem_ptr = isc->sc_dmacur; + + /* + * process all of the dma frames in memory + * + * This loop relies on the dma_mem_ptr variable being set to the + * next frames start address. + */ + for (; num_dma_frames > 0; num_dma_frames--) { + + /* + * Get the length and status of the packet. Only the + * status is guarenteed to be at dma_mem_ptr, ie need + * to check for wraparound before reading the length + */ + status = *((unsigned short *) dma_mem_ptr)++; + if (dma_mem_ptr > (isc->sc_dmabase + isc->sc_dmasize)) { + dma_mem_ptr = isc->sc_dmabase; + } + pkt_length = *((unsigned short *) dma_mem_ptr)++; + + /* Do some sanity checks on the length and status. */ + if ((pkt_length > ETHER_MAX_LEN) || + ((status & DMA_STATUS_BITS) != DMA_STATUS_OK)) { + /* + * the SCO driver kills the adapter in this + * situation + */ + /* + * should increment the error count and reset + * the dma operation. + */ + printf("%s: cs_process_rx_dma: DMA buffer out of sync about to reset\n", + sc->sc_dev.dv_xname); + ifp->if_ierrors++; + + /* skip the rest of the DMA buffer */ + isa_dmaabort(isc->sc_ic, isc->sc_drq); + + /* now reset the chip and reinitialise */ + cs_init(&sc->sc_ethercom.ec_if); + return; + } + /* Check the status of the received packet. */ + if (status & RX_EVENT_RX_OK) { + /* get a new mbuf */ + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m == 0) { + printf("%s: cs_process_rx_dma: unable to allocate mbuf\n", + sc->sc_dev.dv_xname); + ifp->if_ierrors++; + /* + * couldn't allocate an mbuf so + * things are not good, may as well + * drop all the packets I think. + */ + CS_READ_PACKET_PAGE(sc, + PKTPG_DMA_FRAME_COUNT); + + /* now reset DMA operation */ + isa_dmaabort(isc->sc_ic, isc->sc_drq); + + /* + * now reset the chip and + * reinitialise + */ + cs_init(&sc->sc_ethercom.ec_if); + return; + } + /* + * save processing by always using a mbuf + * cluster, guarenteed to fit packet + */ + MCLGET(m, M_DONTWAIT); + if ((m->m_flags & M_EXT) == 0) { + /* couldn't allocate an mbuf cluster */ + printf("%s: cs_process_rx_dma: unable to allocate a cluster\n", + sc->sc_dev.dv_xname); + m_freem(m); + + /* skip the frame */ + CS_READ_PACKET_PAGE(sc, PKTPG_DMA_FRAME_COUNT); + isa_dmaabort(isc->sc_ic, isc->sc_drq); + + /* + * now reset the chip and + * reinitialise + */ + cs_init(&sc->sc_ethercom.ec_if); + return; + } + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = pkt_length; + m->m_len = pkt_length; + + /* + * align ip header on word boundary for + * ipintr + */ + pad = ALIGN(sizeof(struct ether_header)) - + sizeof(struct ether_header); + m->m_data += pad; + + /* + * set up the buffer pointer to point to the + * data area + */ + pBuff = mtod(m, char *); + + /* + * Read the frame into free_pktbuf + * The buffer is circular buffer, either + * 16K or 64K in length. + * + * need to check where the end of the buffer + * is and go back to the start. + */ + if ((dma_mem_ptr + pkt_length) < + (isc->sc_dmabase + isc->sc_dmasize)) { + /* + * No wrap around. Copy the frame + * header + */ + memcpy(pBuff, dma_mem_ptr, pkt_length); + dma_mem_ptr += pkt_length; + } else { + to_copy = (u_int) + ((isc->sc_dmabase + isc->sc_dmasize) - + dma_mem_ptr); + + /* Copy the first half of the frame. */ + memcpy(pBuff, dma_mem_ptr, to_copy); + pBuff += to_copy; + + /* + * Rest of the frame is to be read + * from the first byte of the DMA + * memory. + */ + /* + * Get the number of bytes leftout in + * the frame. + */ + to_copy = pkt_length - to_copy; + + dma_mem_ptr = isc->sc_dmabase; + + /* Copy rest of the frame. */ + memcpy(pBuff, dma_mem_ptr, to_copy); + dma_mem_ptr += to_copy; + } + + cs_ether_input(sc, m); + } + /* (status & RX_OK) */ + else { + /* the frame was not received OK */ + /* Increment the input error count */ + ifp->if_ierrors++; + + /* + * If debugging is enabled then log error + * messages if we got any. + */ + if ((ifp->if_flags & IFF_DEBUG) && + status != REG_NUM_RX_EVENT) + cs_print_rx_errors(sc, status); + } + /* + * now update the current frame pointer. the + * dma_mem_ptr should point to the next packet to be + * received, without the alignment considerations. + * + * The cs8900 pads all frames to start at the next 32bit + * aligned addres. hence we need to pad our offset + * pointer. + */ + dma_mem_ptr += 3; + dma_mem_ptr = (char *) + ((long) dma_mem_ptr & 0xfffffffc); + if (dma_mem_ptr < (isc->sc_dmabase + isc->sc_dmasize)) { + isc->sc_dmacur = dma_mem_ptr; + } else { + dma_mem_ptr = isc->sc_dmacur = isc->sc_dmabase; + } + } /* for all frames */ + /* Read the number of frames DMAed again. */ + num_dma_frames = CS_READ_PACKET_PAGE(sc, PKTPG_DMA_FRAME_COUNT); + num_dma_frames &= (u_int16_t) (0x0fff); + } /* while there are frames left */ +} diff --git a/sys/dev/isa/cs89x0isavar.h b/sys/dev/isa/cs89x0isavar.h new file mode 100644 index 000000000000..5ccbfa6fc9f3 --- /dev/null +++ b/sys/dev/isa/cs89x0isavar.h @@ -0,0 +1,16 @@ + +void cs_process_rx_dma __P((struct cs_softc *)); +void cs_isa_dma_chipinit __P((struct cs_softc *)); +void cs_isa_dma_attach __P((struct cs_softc *)); + +struct cs_softc_isa { + struct cs_softc sc_cs; + + isa_chipset_tag_t sc_ic; /* ISA chipset */ + int sc_drq; /* DRQ line */ + + bus_size_t sc_dmasize; /* DMA size (16k or 64k) */ + bus_addr_t sc_dmaaddr; /* DMA address */ + caddr_t sc_dmabase; /* base DMA address (KVA) */ + caddr_t sc_dmacur; /* current DMA address (KVA) */ +}; diff --git a/sys/dev/isa/files.isa b/sys/dev/isa/files.isa index f8e6478bdf44..9c542227658c 100644 --- a/sys/dev/isa/files.isa +++ b/sys/dev/isa/files.isa @@ -1,4 +1,4 @@ -# $NetBSD: files.isa,v 1.117 2001/11/20 14:34:26 lukem Exp $ +# $NetBSD: files.isa,v 1.118 2001/11/26 19:17:06 yamt Exp $ # # Config file and device description for machine-independent ISA code. # Included by ports that need it. Requires that the SCSI files be @@ -202,10 +202,9 @@ attach ate at isa with ate_isa file dev/isa/if_ate.c ate_isa # Crystal Semiconductor CS8900, CS8920, and CS8920M Ethernet -device cs: arp, ether, ifnet, isadma -file dev/isa/cs89x0.c cs - -attach cs at isa with cs_isa +define cs_isa_common +file dev/isa/cs89x0isa.c cs_isa_common +attach cs at isa with cs_isa: cs_isa_common, isadma file dev/isa/if_cs_isa.c cs_isa # Fujitsu MB86960-based boards diff --git a/sys/dev/isa/if_cs_isa.c b/sys/dev/isa/if_cs_isa.c index d3aedab6757b..7b44d0819bb1 100644 --- a/sys/dev/isa/if_cs_isa.c +++ b/sys/dev/isa/if_cs_isa.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_cs_isa.c,v 1.4 2001/11/13 08:01:16 lukem Exp $ */ +/* $NetBSD: if_cs_isa.c,v 1.5 2001/11/26 19:17:06 yamt Exp $ */ /* * Copyright 1997 @@ -34,7 +34,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: if_cs_isa.c,v 1.4 2001/11/13 08:01:16 lukem Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_cs_isa.c,v 1.5 2001/11/26 19:17:06 yamt Exp $"); #include #include @@ -57,14 +57,15 @@ __KERNEL_RCSID(0, "$NetBSD: if_cs_isa.c,v 1.4 2001/11/13 08:01:16 lukem Exp $"); #include #include -#include -#include +#include +#include +#include int cs_isa_probe __P((struct device *, struct cfdata *, void *)); void cs_isa_attach __P((struct device *, struct device *, void *)); struct cfattach cs_isa_ca = { - sizeof(struct cs_softc), cs_isa_probe, cs_isa_attach + sizeof(struct cs_softc_isa), cs_isa_probe, cs_isa_attach }; int @@ -190,13 +191,14 @@ cs_isa_attach(parent, self, aux) void *aux; { struct cs_softc *sc = (struct cs_softc *) self; + struct cs_softc_isa *isc = (void *) self; struct isa_attach_args *ia = aux; - sc->sc_ic = ia->ia_ic; + isc->sc_ic = ia->ia_ic; sc->sc_iot = ia->ia_iot; sc->sc_memt = ia->ia_memt; - sc->sc_drq = ia->ia_drq; + isc->sc_drq = ia->ia_drq; sc->sc_irq = ia->ia_irq; printf("\n"); @@ -244,5 +246,9 @@ cs_isa_attach(parent, self, aux) return; } + sc->sc_dma_chipinit = cs_isa_dma_chipinit; + sc->sc_dma_attach = cs_isa_dma_attach; + sc->sc_dma_process_rx = cs_process_rx_dma; + cs_attach(sc, NULL, NULL, 0, 0); } diff --git a/sys/dev/ofisa/files.ofisa b/sys/dev/ofisa/files.ofisa index 33a097e4926c..9827a32950e4 100644 --- a/sys/dev/ofisa/files.ofisa +++ b/sys/dev/ofisa/files.ofisa @@ -1,4 +1,4 @@ -# $NetBSD: files.ofisa,v 1.10 2001/02/26 02:39:30 matt Exp $ +# $NetBSD: files.ofisa,v 1.11 2001/11/26 19:17:07 yamt Exp $ # OFW ISA bus support # XXX eventually we should do something with these locators @@ -32,7 +32,7 @@ attach ess at ofisa with ess_ofisa file dev/ofisa/ess_ofisa.c ess_ofisa # attachment of ISA CS8900 driver -attach cs at ofisa with cs_ofisa: of_network_dev +attach cs at ofisa with cs_ofisa: of_network_dev, cs_isa_common, isadma file dev/ofisa/if_cs_ofisa.c cs_ofisa # attachment of ISA Game port driver diff --git a/sys/dev/ofisa/if_cs_ofisa.c b/sys/dev/ofisa/if_cs_ofisa.c index 85c4e56a2a5d..e229ad50d862 100644 --- a/sys/dev/ofisa/if_cs_ofisa.c +++ b/sys/dev/ofisa/if_cs_ofisa.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_cs_ofisa.c,v 1.5 2001/11/13 07:29:45 lukem Exp $ */ +/* $NetBSD: if_cs_ofisa.c,v 1.6 2001/11/26 19:17:07 yamt Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -38,7 +38,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: if_cs_ofisa.c,v 1.5 2001/11/13 07:29:45 lukem Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_cs_ofisa.c,v 1.6 2001/11/26 19:17:07 yamt Exp $"); #include #include @@ -66,14 +66,15 @@ __KERNEL_RCSID(0, "$NetBSD: if_cs_ofisa.c,v 1.5 2001/11/13 07:29:45 lukem Exp $" #include #include -#include -#include +#include +#include +#include int cs_ofisa_match __P((struct device *, struct cfdata *, void *)); void cs_ofisa_attach __P((struct device *, struct device *, void *)); struct cfattach cs_ofisa_ca = { - sizeof(struct cs_softc), cs_ofisa_match, cs_ofisa_attach + sizeof(struct cs_softc_isa), cs_ofisa_match, cs_ofisa_attach }; int @@ -106,6 +107,7 @@ cs_ofisa_attach(parent, self, aux) void *aux; { struct cs_softc *sc = (struct cs_softc *) self; + struct cs_softc_isa *isc = (void *)sc; struct ofisa_attach_args *aa = aux; struct ofisa_reg_desc reg[2]; struct ofisa_intr_desc intr; @@ -116,7 +118,7 @@ cs_ofisa_attach(parent, self, aux) const char *message = NULL; u_int8_t enaddr[6]; - sc->sc_ic = aa->ic; + isc->sc_ic = aa->ic; sc->sc_iot = aa->iot; sc->sc_memt = aa->memt; @@ -184,13 +186,13 @@ cs_ofisa_attach(parent, self, aux) return; } - sc->sc_drq = ISACF_DRQ_DEFAULT; + isc->sc_drq = ISACF_DRQ_DEFAULT; n = ofisa_dma_get(aa->oba.oba_phandle, &dma, 1); #ifdef _CS_OFISA_MD_DMA_FIXUP n = cs_ofisa_md_dma_fixup(parent, self, aux, &dma, 1, n); #endif if (n == 1) - sc->sc_drq = dma.drq; + isc->sc_drq = dma.drq; if (io_addr == (bus_addr_t) -1) { printf(": no I/O space\n"); @@ -251,7 +253,7 @@ cs_ofisa_attach(parent, self, aux) defmedia = media[0]; /* XXX What to do? */ } - sc->sc_ih = isa_intr_establish(sc->sc_ic, sc->sc_irq, intr.share, + sc->sc_ih = isa_intr_establish(isc->sc_ic, sc->sc_irq, intr.share, IPL_NET, cs_intr, sc); if (sc->sc_ih == NULL) { printf("%s: unable to establish interrupt\n", @@ -263,6 +265,10 @@ cs_ofisa_attach(parent, self, aux) sc->sc_cfgflags |= cs_ofisa_md_cfgflags_fixup(parent, self, aux); #endif + sc->sc_dma_chipinit = cs_isa_dma_chipinit; + sc->sc_dma_attach = cs_isa_dma_attach; + sc->sc_dma_process_rx = cs_process_rx_dma; + cs_attach(sc, enaddr, media, nmedia, defmedia); /* This is malloc'd. */ diff --git a/sys/dev/pcmcia/if_cs_pcmcia.c b/sys/dev/pcmcia/if_cs_pcmcia.c index 262ce865e331..4fbb870e59e4 100644 --- a/sys/dev/pcmcia/if_cs_pcmcia.c +++ b/sys/dev/pcmcia/if_cs_pcmcia.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_cs_pcmcia.c,v 1.1 2001/11/26 11:17:34 yamt Exp $ */ +/* $NetBSD: if_cs_pcmcia.c,v 1.2 2001/11/26 19:17:07 yamt Exp $ */ /*- * Copyright (c)2001 YAMAMOTO Takashi, @@ -27,7 +27,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: if_cs_pcmcia.c,v 1.1 2001/11/26 11:17:34 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_cs_pcmcia.c,v 1.2 2001/11/26 19:17:07 yamt Exp $"); #include #include @@ -51,10 +51,8 @@ __KERNEL_RCSID(0, "$NetBSD: if_cs_pcmcia.c,v 1.1 2001/11/26 11:17:34 yamt Exp $" #include #include -#include /*XXX*/ - -#include -#include +#include +#include #define DEVNAME(sc) ((sc)->sc_dev.dv_xname) @@ -145,7 +143,6 @@ cs_pcmcia_attach(struct device *parent, struct device *self, void *aux) sc->sc_iot = psc->sc_pcioh.iot; sc->sc_ioh = psc->sc_pcioh.ioh; - sc->sc_drq = ISACF_DRQ_DEFAULT; sc->sc_irq = -1; #define CS_PCMCIA_HACK_FOR_CARDBUS #ifdef CS_PCMCIA_HACK_FOR_CARDBUS