freebsd-dev/sys/dev/fatm/if_fatmvar.h
John Baldwin 7cf545d0a1 - Add a private timer to drive the transmit watchdog instead of using
if_watchdog and if_timer.
- Fix some issues in detach for sn(4), ste(4), and ti(4).  Primarily this
  means calling ether_ifdetach() before anything else.
2009-11-19 22:06:40 +00:00

396 lines
12 KiB
C

/*-
* Copyright (c) 2001-2003
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* 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.
*
* 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.
*
* Author: Hartmut Brandt <harti@freebsd.org>
*
* $FreeBSD$
*
* Fore PCA200E driver definitions.
*/
/*
* Debug statistics of the PCA200 driver
*/
struct istats {
uint32_t cmd_queue_full;
uint32_t get_stat_errors;
uint32_t clr_stat_errors;
uint32_t get_prom_errors;
uint32_t suni_reg_errors;
uint32_t tx_queue_full;
uint32_t tx_queue_almost_full;
uint32_t tx_pdu2big;
uint32_t tx_too_many_segs;
uint32_t tx_retry;
uint32_t fix_empty;
uint32_t fix_addr_copy;
uint32_t fix_addr_noext;
uint32_t fix_addr_ext;
uint32_t fix_len_noext;
uint32_t fix_len_copy;
uint32_t fix_len;
uint32_t rx_badvc;
uint32_t rx_closed;
};
/*
* Addresses on the on-board RAM are expressed as offsets to the
* start of that RAM.
*/
typedef uint32_t cardoff_t;
/*
* The card uses a number of queues for communication with the host.
* Parts of the queue are located on the card (pointers to the status
* word and the ioblk and the command blocks), the rest in host memory.
* Each of these queues forms a ring, where the head and tail pointers are
* managed * either by the card or the host. For the receive queue the
* head is managed by the card (and not used altogether by the host) and the
* tail by the host - for all other queues its the other way around.
* The host resident parts of the queue entries contain pointers to
* the host resident status and the host resident ioblk (the latter not for
* the command queue) as well as DMA addresses for supply to the card.
*/
struct fqelem {
cardoff_t card; /* corresponding element on card */
bus_addr_t card_ioblk; /* ioblk address to supply to card */
volatile uint32_t *statp; /* host status pointer */
void *ioblk; /* host ioblk (not for commands) */
};
struct fqueue {
struct fqelem *chunk; /* pointer to the element array */
int head; /* queue head */
int tail; /* queue tail */
};
/*
* Queue manipulation macros
*/
#define NEXT_QUEUE_ENTRY(HEAD,LEN) ((HEAD) = ((HEAD) + 1) % LEN)
#define GET_QUEUE(Q,TYPE,IDX) (&((TYPE *)(Q).chunk)[(IDX)])
/*
* Now define structures for the different queues. Each of these structures
* must start with a struct fqelem.
*/
struct txqueue { /* transmit queue element */
struct fqelem q;
struct mbuf *m; /* the chain we are transmitting */
bus_dmamap_t map; /* map for the packet */
};
struct rxqueue { /* receive queue element */
struct fqelem q;
};
struct supqueue { /* supply queue element */
struct fqelem q;
};
struct cmdqueue;
struct fatm_softc;
typedef void (*completion_cb)(struct fatm_softc *, struct cmdqueue *);
struct cmdqueue { /* command queue element */
struct fqelem q;
completion_cb cb; /* call on command completion */
int error; /* set if error occured */
};
/*
* Card-DMA-able memory is managed by means of the bus_dma* functions.
* To allocate a chunk of memory with a specific size and alignment one
* has to:
* 1. create a DMA tag
* 2. allocate the memory
* 3. load the memory into a map.
* This finally gives the physical address that can be given to the card.
* The card can DMA the entire 32-bit space without boundaries. We assume,
* that all the allocations can be mapped in one contiguous segment. This
* may be wrong in the future if we have more than 32 bit addresses.
* Allocation is done at attach time and managed by the following structure.
*
* This could be done easier with the NetBSD bus_dma* functions. They appear
* to be more useful and consistent.
*/
struct fatm_mem {
u_int size; /* size */
u_int align; /* alignment */
bus_dma_tag_t dmat; /* DMA tag */
void *mem; /* memory block */
bus_addr_t paddr; /* pysical address */
bus_dmamap_t map; /* map */
};
/*
* Each of these structures describes one receive buffer while the buffer
* is on the card or in the receive return queue. These structures are
* allocated at initialisation time together with the DMA maps. The handle that
* is given to the card is the index into the array of these structures.
*/
struct rbuf {
struct mbuf *m; /* the mbuf while we are on the card */
bus_dmamap_t map; /* the map */
LIST_ENTRY(rbuf) link; /* the free list link */
};
LIST_HEAD(rbuf_list, rbuf);
/*
* The driver maintains a list of all open VCCs. Because we
* use only VPI=0 and a maximum VCI of 1024, the list is rather an array
* than a list. We also store the atm pseudoheader flags here and the
* rxhand (aka. protocol block).
*/
struct card_vcc {
struct atmio_vcc param; /* traffic parameters */
void *rxhand;
u_int vflags;
uint32_t ipackets;
uint32_t opackets;
uint32_t ibytes;
uint32_t obytes;
};
#define FATM_VCC_OPEN 0x00010000 /* is open */
#define FATM_VCC_TRY_OPEN 0x00020000 /* is currently opening */
#define FATM_VCC_TRY_CLOSE 0x00040000 /* is currently closing */
#define FATM_VCC_BUSY 0x00070000 /* one of the above */
#define FATM_VCC_REOPEN 0x00080000 /* reopening during init */
/*
* Finally the softc structure
*/
struct fatm_softc {
struct ifnet *ifp; /* common part */
struct mtx mtx; /* lock this structure */
struct ifmedia media; /* media */
struct callout watchdog_timer;
int init_state; /* initialisation step */
int memid; /* resource id for card memory */
struct resource *memres; /* resource for card memory */
bus_space_handle_t memh; /* handle for card memory */
bus_space_tag_t memt; /* tag for card memory */
int irqid; /* resource id for interrupt */
struct resource *irqres; /* resource for interrupt */
void *ih; /* interrupt handler */
bus_dma_tag_t parent_dmat; /* parent DMA tag */
struct fatm_mem stat_mem; /* memory for status blocks */
struct fatm_mem txq_mem; /* TX descriptor queue */
struct fatm_mem rxq_mem; /* RX descriptor queue */
struct fatm_mem s1q_mem; /* Small buffer 1 queue */
struct fatm_mem l1q_mem; /* Large buffer 1 queue */
struct fatm_mem prom_mem; /* PROM memory */
struct fqueue txqueue; /* transmission queue */
struct fqueue rxqueue; /* receive queue */
struct fqueue s1queue; /* SMALL S1 queue */
struct fqueue l1queue; /* LARGE S1 queue */
struct fqueue cmdqueue; /* command queue */
/* fields for access to the SUNI registers */
struct fatm_mem reg_mem; /* DMAable memory for readregs */
struct cv cv_regs; /* to serialize access to reg_mem */
/* fields for access to statistics */
struct fatm_mem sadi_mem; /* sadistics memory */
struct cv cv_stat; /* to serialize access to sadi_mem */
u_int flags;
#define FATM_STAT_INUSE 0x0001
#define FATM_REGS_INUSE 0x0002
u_int txcnt; /* number of used transmit desc */
int retry_tx; /* keep mbufs in queue if full */
struct card_vcc **vccs; /* table of vccs */
int open_vccs; /* number of vccs in use */
int small_cnt; /* number of buffers owned by card */
int large_cnt; /* number of buffers owned by card */
uma_zone_t vcc_zone; /* allocator for VCCs */
/* receiving */
struct rbuf *rbufs; /* rbuf array */
struct rbuf_list rbuf_free; /* free rbufs list */
struct rbuf_list rbuf_used; /* used rbufs list */
u_int rbuf_total; /* total number of buffs */
bus_dma_tag_t rbuf_tag; /* tag for rbuf mapping */
/* transmission */
bus_dma_tag_t tx_tag; /* transmission tag */
uint32_t heartbeat; /* last heartbeat */
u_int stop_cnt; /* how many times checked */
struct istats istats; /* internal statistics */
/* SUNI state */
struct utopia utopia;
/* sysctl support */
struct sysctl_ctx_list sysctl_ctx;
struct sysctl_oid *sysctl_tree;
#ifdef FATM_DEBUG
/* debugging */
u_int debug;
#endif
};
#ifndef FATM_DEBUG
#define FATM_LOCK(SC) mtx_lock(&(SC)->mtx)
#define FATM_UNLOCK(SC) mtx_unlock(&(SC)->mtx)
#else
#define FATM_LOCK(SC) do { \
DBG(SC, LOCK, ("locking in line %d", __LINE__)); \
mtx_lock(&(SC)->mtx); \
} while (0)
#define FATM_UNLOCK(SC) do { \
DBG(SC, LOCK, ("unlocking in line %d", __LINE__)); \
mtx_unlock(&(SC)->mtx); \
} while (0)
#endif
#define FATM_CHECKLOCK(SC) mtx_assert(&sc->mtx, MA_OWNED)
/*
* Macros to access host memory fields that are also access by the card.
* These fields need to little-endian always.
*/
#define H_GETSTAT(STATP) (le32toh(*(STATP)))
#define H_SETSTAT(STATP, S) do { *(STATP) = htole32(S); } while (0)
#define H_SETDESC(DESC, D) do { (DESC) = htole32(D); } while (0)
#ifdef notyet
#define H_SYNCSTAT_POSTREAD(SC, P) \
bus_dmamap_sync_size((SC)->stat_mem.dmat, \
(SC)->stat_mem.map, \
(volatile char *)(P) - (volatile char *)(SC)->stat_mem.mem, \
sizeof(volatile uint32_t), BUS_DMASYNC_POSTREAD)
#define H_SYNCSTAT_PREWRITE(SC, P) \
bus_dmamap_sync_size((SC)->stat_mem.dmat, \
(SC)->stat_mem.map, \
(volatile char *)(P) - (volatile char *)(SC)->stat_mem.mem, \
sizeof(volatile uint32_t), BUS_DMASYNC_PREWRITE)
#define H_SYNCQ_PREWRITE(M, P, SZ) \
bus_dmamap_sync_size((M)->dmat, (M)->map, \
(volatile char *)(P) - (volatile char *)(M)->mem, (SZ), \
BUS_DMASYNC_PREWRITE)
#define H_SYNCQ_POSTREAD(M, P, SZ) \
bus_dmamap_sync_size((M)->dmat, (M)->map, \
(volatile char *)(P) - (volatile char *)(M)->mem, (SZ), \
BUS_DMASYNC_POSTREAD)
#else
#define H_SYNCSTAT_POSTREAD(SC, P) do { } while (0)
#define H_SYNCSTAT_PREWRITE(SC, P) do { } while (0)
#define H_SYNCQ_PREWRITE(M, P, SZ) do { } while (0)
#define H_SYNCQ_POSTREAD(M, P, SZ) do { } while (0)
#endif
/*
* Macros to manipulate VPVCs
*/
#define MKVPVC(VPI,VCI) (((VPI) << 16) | (VCI))
#define GETVPI(VPVC) (((VPVC) >> 16) & 0xff)
#define GETVCI(VPVC) ((VPVC) & 0xffff)
/*
* These macros encapsulate the bus_space functions for better readabiliy.
*/
#define WRITE4(SC, OFF, VAL) bus_space_write_4(SC->memt, SC->memh, OFF, VAL)
#define WRITE1(SC, OFF, VAL) bus_space_write_1(SC->memt, SC->memh, OFF, VAL)
#define READ4(SC, OFF) bus_space_read_4(SC->memt, SC->memh, OFF)
#define READ1(SC, OFF) bus_space_read_1(SC->memt, SC->memh, OFF)
#define BARRIER_R(SC) \
bus_space_barrier(SC->memt, SC->memh, 0, FATMO_END, \
BUS_SPACE_BARRIER_READ)
#define BARRIER_W(SC) \
bus_space_barrier(SC->memt, SC->memh, 0, FATMO_END, \
BUS_SPACE_BARRIER_WRITE)
#define BARRIER_RW(SC) \
bus_space_barrier(SC->memt, SC->memh, 0, FATMO_END, \
BUS_SPACE_BARRIER_WRITE|BUS_SPACE_BARRIER_READ)
#ifdef FATM_DEBUG
#define DBG(SC, FL, PRINT) do { \
if ((SC)->debug & DBG_##FL) { \
if_printf(&(SC)->ifatm.ifnet, "%s: ", __func__); \
printf PRINT; \
printf("\n"); \
} \
} while (0)
#define DBGC(SC, FL, PRINT) do { \
if ((SC)->debug & DBG_##FL) \
printf PRINT; \
} while (0)
enum {
DBG_RCV = 0x0001,
DBG_XMIT = 0x0002,
DBG_VCC = 0x0004,
DBG_IOCTL = 0x0008,
DBG_ATTACH = 0x0010,
DBG_INIT = 0x0020,
DBG_DMA = 0x0040,
DBG_BEAT = 0x0080,
DBG_UART = 0x0100,
DBG_LOCK = 0x0200,
DBG_ALL = 0xffff
};
#else
#define DBG(SC, FL, PRINT)
#define DBGC(SC, FL, PRINT)
#endif
/*
* Configuration.
*
* This section contains tunable parameters and dependend defines.
*/
#define FATM_CMD_QLEN 16 /* command queue length */
#ifndef TEST_DMA_SYNC
#define FATM_TX_QLEN 128 /* transmit queue length */
#define FATM_RX_QLEN 64 /* receive queue length */
#else
#define FATM_TX_QLEN 8 /* transmit queue length */
#define FATM_RX_QLEN 8 /* receive queue length */
#endif
#define SMALL_SUPPLY_QLEN 16
#define SMALL_POOL_SIZE 256
#define SMALL_SUPPLY_BLKSIZE 8
#define LARGE_SUPPLY_QLEN 16
#define LARGE_POOL_SIZE 128
#define LARGE_SUPPLY_BLKSIZE 8