1139749Simp/*-
2116735Sharti * Copyright (c) 2001-2003
3116735Sharti *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4116735Sharti * 	All rights reserved.
5116735Sharti *
6116735Sharti * Redistribution and use in source and binary forms, with or without
7116735Sharti * modification, are permitted provided that the following conditions
8116735Sharti * are met:
9116735Sharti * 1. Redistributions of source code must retain the above copyright
10116735Sharti *    notice, this list of conditions and the following disclaimer.
11116735Sharti * 2. Redistributions in binary form must reproduce the above copyright
12116735Sharti *    notice, this list of conditions and the following disclaimer in the
13116735Sharti *    documentation and/or other materials provided with the distribution.
14116735Sharti *
15116735Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16116735Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17116735Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18116735Sharti * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19116735Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20116735Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21116735Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22116735Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23116735Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24116735Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25116735Sharti * SUCH DAMAGE.
26116735Sharti *
27116735Sharti * Author: Hartmut Brandt <harti@freebsd.org>
28116735Sharti *
29116735Sharti * $FreeBSD$
30116735Sharti *
31116735Sharti * Fore PCA200E driver definitions.
32116735Sharti */
33116735Sharti/*
34116735Sharti * Debug statistics of the PCA200 driver
35116735Sharti */
36116735Shartistruct istats {
37116735Sharti	uint32_t	cmd_queue_full;
38116735Sharti	uint32_t	get_stat_errors;
39116735Sharti	uint32_t	clr_stat_errors;
40116735Sharti	uint32_t	get_prom_errors;
41116735Sharti	uint32_t	suni_reg_errors;
42116735Sharti	uint32_t	tx_queue_full;
43116735Sharti	uint32_t	tx_queue_almost_full;
44116735Sharti	uint32_t	tx_pdu2big;
45116735Sharti	uint32_t	tx_too_many_segs;
46116735Sharti	uint32_t	tx_retry;
47116735Sharti	uint32_t	fix_empty;
48116735Sharti	uint32_t	fix_addr_copy;
49116735Sharti	uint32_t	fix_addr_noext;
50116735Sharti	uint32_t	fix_addr_ext;
51116735Sharti	uint32_t	fix_len_noext;
52116735Sharti	uint32_t	fix_len_copy;
53116735Sharti	uint32_t	fix_len;
54116735Sharti	uint32_t	rx_badvc;
55116735Sharti	uint32_t	rx_closed;
56116735Sharti};
57116735Sharti
58116735Sharti/*
59116735Sharti * Addresses on the on-board RAM are expressed as offsets to the
60116735Sharti * start of that RAM.
61116735Sharti */
62116735Shartitypedef uint32_t cardoff_t;
63116735Sharti
64116735Sharti/*
65116735Sharti * The card uses a number of queues for communication with the host.
66116735Sharti * Parts of the queue are located on the card (pointers to the status
67116735Sharti * word and the ioblk and the command blocks), the rest in host memory.
68116735Sharti * Each of these queues forms a ring, where the head and tail pointers are
69116735Sharti * managed * either by the card or the host. For the receive queue the
70116735Sharti * head is managed by the card (and not used altogether by the host) and the
71116735Sharti * tail by the host - for all other queues its the other way around.
72116735Sharti * The host resident parts of the queue entries contain pointers to
73116735Sharti * the host resident status and the host resident ioblk (the latter not for
74116735Sharti * the command queue) as well as DMA addresses for supply to the card.
75116735Sharti */
76116735Shartistruct fqelem {
77116735Sharti	cardoff_t	card;		/* corresponding element on card */
78116735Sharti	bus_addr_t	card_ioblk;	/* ioblk address to supply to card */
79116735Sharti	volatile uint32_t *statp;		/* host status pointer */
80116735Sharti	void		*ioblk;		/* host ioblk (not for commands) */
81116735Sharti};
82116735Sharti
83116735Shartistruct fqueue {
84116735Sharti	struct fqelem	*chunk;		/* pointer to the element array */
85116735Sharti	int		head;		/* queue head */
86116735Sharti	int		tail;		/* queue tail */
87116735Sharti};
88116735Sharti
89116735Sharti/*
90116735Sharti * Queue manipulation macros
91116735Sharti */
92116735Sharti#define	NEXT_QUEUE_ENTRY(HEAD,LEN) ((HEAD) = ((HEAD) + 1) % LEN)
93116735Sharti#define	GET_QUEUE(Q,TYPE,IDX)    (&((TYPE *)(Q).chunk)[(IDX)])
94116735Sharti
95116735Sharti/*
96116735Sharti * Now define structures for the different queues. Each of these structures
97116735Sharti * must start with a struct fqelem.
98116735Sharti */
99116735Shartistruct txqueue {		/* transmit queue element */
100116735Sharti	struct fqelem	q;
101116735Sharti	struct mbuf	*m;	/* the chain we are transmitting */
102116735Sharti	bus_dmamap_t	map;	/* map for the packet */
103116735Sharti};
104116735Sharti
105116735Shartistruct rxqueue {		/* receive queue element */
106116735Sharti	struct fqelem	q;
107116735Sharti};
108116735Sharti
109116735Shartistruct supqueue {		/* supply queue element */
110116735Sharti	struct fqelem	q;
111116735Sharti};
112116735Sharti
113116735Shartistruct cmdqueue;
114116735Shartistruct fatm_softc;
115116735Sharti
116116735Shartitypedef void (*completion_cb)(struct fatm_softc *, struct cmdqueue *);
117116735Sharti
118116735Shartistruct cmdqueue {		/* command queue element */
119116735Sharti	struct fqelem	q;
120116735Sharti	completion_cb	cb;	/* call on command completion */
121298955Spfg	int		error;	/* set if error occurred */
122116735Sharti};
123116735Sharti
124116735Sharti/*
125116735Sharti * Card-DMA-able memory is managed by means of the bus_dma* functions.
126116735Sharti * To allocate a chunk of memory with a specific size and alignment one
127116735Sharti * has to:
128116735Sharti *	1. create a DMA tag
129116735Sharti *	2. allocate the memory
130116735Sharti *	3. load the memory into a map.
131116735Sharti * This finally gives the physical address that can be given to the card.
132116735Sharti * The card can DMA the entire 32-bit space without boundaries. We assume,
133116735Sharti * that all the allocations can be mapped in one contiguous segment. This
134116735Sharti * may be wrong in the future if we have more than 32 bit addresses.
135116735Sharti * Allocation is done at attach time and managed by the following structure.
136116735Sharti *
137116735Sharti * This could be done easier with the NetBSD bus_dma* functions. They appear
138116735Sharti * to be more useful and consistent.
139116735Sharti */
140116735Shartistruct fatm_mem {
141116735Sharti	u_int		size;		/* size */
142116735Sharti	u_int		align;		/* alignment */
143116735Sharti	bus_dma_tag_t	dmat;		/* DMA tag */
144116735Sharti	void 		*mem;		/* memory block */
145116735Sharti	bus_addr_t	paddr;		/* pysical address */
146116735Sharti	bus_dmamap_t	map;		/* map */
147116735Sharti};
148116735Sharti
149116735Sharti/*
150116735Sharti * Each of these structures describes one receive buffer while the buffer
151116735Sharti * is on the card or in the receive return queue. These structures are
152116735Sharti * allocated at initialisation time together with the DMA maps. The handle that
153116735Sharti * is given to the card is the index into the array of these structures.
154116735Sharti */
155116735Shartistruct rbuf {
156116735Sharti	struct mbuf	*m;	/* the mbuf while we are on the card */
157116735Sharti	bus_dmamap_t	map;	/* the map */
158116735Sharti	LIST_ENTRY(rbuf) link;	/* the free list link */
159116735Sharti};
160116735ShartiLIST_HEAD(rbuf_list, rbuf);
161116735Sharti
162116735Sharti/*
163116735Sharti * The driver maintains a list of all open VCCs. Because we
164116735Sharti * use only VPI=0 and a maximum VCI of 1024, the list is rather an array
165116735Sharti * than a list. We also store the atm pseudoheader flags here and the
166116735Sharti * rxhand (aka. protocol block).
167116735Sharti */
168116735Shartistruct card_vcc {
169118208Sharti	struct atmio_vcc param;		/* traffic parameters */
170116735Sharti	void		*rxhand;
171118607Sjhb	u_int		vflags;
172118208Sharti	uint32_t	ipackets;
173118208Sharti	uint32_t	opackets;
174118208Sharti	uint32_t	ibytes;
175118208Sharti	uint32_t	obytes;
176116735Sharti};
177116735Sharti
178116735Sharti#define	FATM_VCC_OPEN		0x00010000	/* is open */
179116735Sharti#define	FATM_VCC_TRY_OPEN	0x00020000	/* is currently opening */
180116735Sharti#define	FATM_VCC_TRY_CLOSE	0x00040000	/* is currently closing */
181116735Sharti#define	FATM_VCC_BUSY		0x00070000	/* one of the above */
182118596Sharti#define	FATM_VCC_REOPEN		0x00080000	/* reopening during init */
183116735Sharti
184116735Sharti/*
185116735Sharti * Finally the softc structure
186116735Sharti */
187116735Shartistruct fatm_softc {
188147256Sbrooks	struct ifnet	*ifp;		/* common part */
189116735Sharti	struct mtx	mtx;		/* lock this structure */
190116735Sharti	struct ifmedia	media;		/* media */
191199559Sjhb	struct callout	watchdog_timer;
192116735Sharti
193116735Sharti	int		init_state;	/* initialisation step */
194116735Sharti	int		memid;		/* resource id for card memory */
195116735Sharti	struct resource *memres;	/* resource for card memory */
196116735Sharti	bus_space_handle_t memh;	/* handle for card memory */
197116735Sharti	bus_space_tag_t	memt;		/* tag for card memory */
198116735Sharti	int		irqid;		/* resource id for interrupt */
199116735Sharti	struct resource *irqres;	/* resource for interrupt */
200116735Sharti	void		*ih;		/* interrupt handler */
201116735Sharti
202116735Sharti	bus_dma_tag_t	parent_dmat;	/* parent DMA tag */
203116735Sharti	struct fatm_mem	stat_mem;	/* memory for status blocks */
204116735Sharti	struct fatm_mem	txq_mem;	/* TX descriptor queue */
205116735Sharti	struct fatm_mem	rxq_mem;	/* RX descriptor queue */
206116735Sharti	struct fatm_mem	s1q_mem;	/* Small buffer 1 queue */
207116735Sharti	struct fatm_mem	l1q_mem;	/* Large buffer 1 queue */
208116735Sharti	struct fatm_mem	prom_mem;	/* PROM memory */
209116735Sharti
210116735Sharti	struct fqueue	txqueue;	/* transmission queue */
211116735Sharti	struct fqueue	rxqueue;	/* receive queue */
212116735Sharti	struct fqueue	s1queue;	/* SMALL S1 queue */
213116735Sharti	struct fqueue	l1queue;	/* LARGE S1 queue */
214116735Sharti	struct fqueue	cmdqueue;	/* command queue */
215116735Sharti
216116735Sharti	/* fields for access to the SUNI registers */
217116735Sharti	struct fatm_mem	reg_mem;	/* DMAable memory for readregs */
218116735Sharti	struct cv	cv_regs;	/* to serialize access to reg_mem */
219116735Sharti
220116735Sharti	/* fields for access to statistics */
221116735Sharti	struct fatm_mem	sadi_mem;	/* sadistics memory */
222116735Sharti	struct cv	cv_stat;	/* to serialize access to sadi_mem */
223116735Sharti
224116735Sharti	u_int		flags;
225116735Sharti#define	FATM_STAT_INUSE	0x0001
226116735Sharti#define	FATM_REGS_INUSE	0x0002
227116735Sharti	u_int		txcnt;		/* number of used transmit desc */
228116735Sharti	int		retry_tx;	/* keep mbufs in queue if full */
229116735Sharti
230118208Sharti	struct card_vcc	**vccs;		/* table of vccs */
231116735Sharti	int		open_vccs;	/* number of vccs in use */
232116735Sharti	int		small_cnt;	/* number of buffers owned by card */
233116735Sharti	int		large_cnt;	/* number of buffers owned by card */
234118208Sharti	uma_zone_t	vcc_zone;	/* allocator for VCCs */
235116735Sharti
236116735Sharti	/* receiving */
237116735Sharti	struct rbuf	*rbufs;		/* rbuf array */
238116735Sharti	struct rbuf_list rbuf_free;	/* free rbufs list */
239116735Sharti	struct rbuf_list rbuf_used;	/* used rbufs list */
240116735Sharti	u_int		rbuf_total;	/* total number of buffs */
241116735Sharti	bus_dma_tag_t	rbuf_tag;	/* tag for rbuf mapping */
242116735Sharti
243116735Sharti	/* transmission */
244116735Sharti	bus_dma_tag_t	tx_tag;		/* transmission tag */
245116735Sharti
246116735Sharti	uint32_t	heartbeat;	/* last heartbeat */
247116735Sharti	u_int		stop_cnt;	/* how many times checked */
248116735Sharti
249116735Sharti	struct istats	istats;		/* internal statistics */
250116735Sharti
251116735Sharti	/* SUNI state */
252116735Sharti	struct utopia	utopia;
253116735Sharti
254116735Sharti	/* sysctl support */
255116735Sharti	struct sysctl_ctx_list sysctl_ctx;
256116735Sharti	struct sysctl_oid *sysctl_tree;
257116735Sharti
258116735Sharti#ifdef FATM_DEBUG
259116735Sharti	/* debugging */
260116735Sharti	u_int		debug;
261116735Sharti#endif
262116735Sharti};
263116735Sharti
264116735Sharti#ifndef FATM_DEBUG
265116735Sharti#define	FATM_LOCK(SC)		mtx_lock(&(SC)->mtx)
266116735Sharti#define	FATM_UNLOCK(SC)		mtx_unlock(&(SC)->mtx)
267116735Sharti#else
268116735Sharti#define	FATM_LOCK(SC)	do {					\
269116735Sharti	DBG(SC, LOCK, ("locking in line %d", __LINE__));	\
270116735Sharti	mtx_lock(&(SC)->mtx);					\
271116735Sharti    } while (0)
272116735Sharti#define	FATM_UNLOCK(SC)	do {					\
273116735Sharti	DBG(SC, LOCK, ("unlocking in line %d", __LINE__));	\
274116735Sharti	mtx_unlock(&(SC)->mtx);					\
275116735Sharti    } while (0)
276116735Sharti#endif
277116735Sharti#define	FATM_CHECKLOCK(SC)	mtx_assert(&sc->mtx, MA_OWNED)
278116735Sharti
279116735Sharti/*
280116735Sharti * Macros to access host memory fields that are also access by the card.
281116735Sharti * These fields need to little-endian always.
282116735Sharti */
283116735Sharti#define	H_GETSTAT(STATP)	(le32toh(*(STATP)))
284116735Sharti#define	H_SETSTAT(STATP, S)	do { *(STATP) = htole32(S); } while (0)
285116735Sharti#define	H_SETDESC(DESC, D)	do { (DESC) = htole32(D); } while (0)
286116735Sharti
287116735Sharti#ifdef notyet
288116735Sharti#define	H_SYNCSTAT_POSTREAD(SC, P)					\
289116735Sharti	bus_dmamap_sync_size((SC)->stat_mem.dmat,			\
290116735Sharti	    (SC)->stat_mem.map,						\
291116735Sharti	    (volatile char *)(P) - (volatile char *)(SC)->stat_mem.mem,	\
292116735Sharti	    sizeof(volatile uint32_t), BUS_DMASYNC_POSTREAD)
293116735Sharti
294116735Sharti#define	H_SYNCSTAT_PREWRITE(SC, P)					\
295116735Sharti	bus_dmamap_sync_size((SC)->stat_mem.dmat,			\
296116735Sharti	    (SC)->stat_mem.map,						\
297116735Sharti	    (volatile char *)(P) - (volatile char *)(SC)->stat_mem.mem,	\
298116735Sharti	    sizeof(volatile uint32_t), BUS_DMASYNC_PREWRITE)
299116735Sharti
300116735Sharti#define	H_SYNCQ_PREWRITE(M, P, SZ)					\
301116735Sharti	bus_dmamap_sync_size((M)->dmat, (M)->map,			\
302116735Sharti	    (volatile char *)(P) - (volatile char *)(M)->mem, (SZ),	\
303116735Sharti	    BUS_DMASYNC_PREWRITE)
304116735Sharti
305116735Sharti#define	H_SYNCQ_POSTREAD(M, P, SZ)					\
306116735Sharti	bus_dmamap_sync_size((M)->dmat, (M)->map,			\
307116735Sharti	    (volatile char *)(P) - (volatile char *)(M)->mem, (SZ),	\
308116735Sharti	    BUS_DMASYNC_POSTREAD)
309116735Sharti#else
310116735Sharti#define	H_SYNCSTAT_POSTREAD(SC, P)	do { } while (0)
311116735Sharti#define	H_SYNCSTAT_PREWRITE(SC, P)	do { } while (0)
312116735Sharti#define	H_SYNCQ_PREWRITE(M, P, SZ)	do { } while (0)
313116735Sharti#define	H_SYNCQ_POSTREAD(M, P, SZ)	do { } while (0)
314116735Sharti#endif
315116735Sharti
316116735Sharti/*
317116735Sharti * Macros to manipulate VPVCs
318116735Sharti */
319116735Sharti#define	MKVPVC(VPI,VCI)	(((VPI) << 16) | (VCI))
320116735Sharti#define	GETVPI(VPVC)		(((VPVC) >> 16) & 0xff)
321116735Sharti#define	GETVCI(VPVC)		((VPVC) & 0xffff)
322116735Sharti
323116735Sharti/*
324116735Sharti * These macros encapsulate the bus_space functions for better readabiliy.
325116735Sharti */
326116735Sharti#define	WRITE4(SC, OFF, VAL) bus_space_write_4(SC->memt, SC->memh, OFF, VAL)
327116735Sharti#define	WRITE1(SC, OFF, VAL) bus_space_write_1(SC->memt, SC->memh, OFF, VAL)
328116735Sharti
329116735Sharti#define	READ4(SC, OFF) bus_space_read_4(SC->memt, SC->memh, OFF)
330116735Sharti#define	READ1(SC, OFF) bus_space_read_1(SC->memt, SC->memh, OFF)
331116735Sharti
332116735Sharti#define	BARRIER_R(SC) \
333116735Sharti	bus_space_barrier(SC->memt, SC->memh, 0, FATMO_END, \
334116735Sharti	    BUS_SPACE_BARRIER_READ)
335116735Sharti#define	BARRIER_W(SC) \
336116735Sharti	bus_space_barrier(SC->memt, SC->memh, 0, FATMO_END, \
337116735Sharti	    BUS_SPACE_BARRIER_WRITE)
338116735Sharti#define	BARRIER_RW(SC) \
339116735Sharti	bus_space_barrier(SC->memt, SC->memh, 0, FATMO_END, \
340116735Sharti	    BUS_SPACE_BARRIER_WRITE|BUS_SPACE_BARRIER_READ)
341116735Sharti
342116735Sharti#ifdef FATM_DEBUG
343116735Sharti#define	DBG(SC, FL, PRINT) do {						\
344116735Sharti	if ((SC)->debug & DBG_##FL) { 					\
345116735Sharti		if_printf(&(SC)->ifatm.ifnet, "%s: ", __func__);	\
346116735Sharti		printf PRINT;						\
347116735Sharti		printf("\n");						\
348116735Sharti	}								\
349116735Sharti    } while (0)
350116735Sharti#define	DBGC(SC, FL, PRINT) do {					\
351116735Sharti	if ((SC)->debug & DBG_##FL) 					\
352116735Sharti		printf PRINT;						\
353116735Sharti    } while (0)
354116735Sharti
355116735Shartienum {
356116735Sharti	DBG_RCV		= 0x0001,
357116735Sharti	DBG_XMIT	= 0x0002,
358116735Sharti	DBG_VCC		= 0x0004,
359116735Sharti	DBG_IOCTL	= 0x0008,
360116735Sharti	DBG_ATTACH	= 0x0010,
361116735Sharti	DBG_INIT	= 0x0020,
362116735Sharti	DBG_DMA		= 0x0040,
363116735Sharti	DBG_BEAT	= 0x0080,
364116735Sharti	DBG_UART	= 0x0100,
365116735Sharti	DBG_LOCK	= 0x0200,
366116735Sharti
367116735Sharti	DBG_ALL		= 0xffff
368116735Sharti};
369116735Sharti
370116735Sharti#else
371116735Sharti#define	DBG(SC, FL, PRINT)
372116735Sharti#define	DBGC(SC, FL, PRINT)
373116735Sharti#endif
374116735Sharti
375116735Sharti/*
376116735Sharti * Configuration.
377116735Sharti *
378116735Sharti * This section contains tunable parameters and dependend defines.
379116735Sharti */
380116735Sharti#define	FATM_CMD_QLEN		16		/* command queue length */
381116735Sharti#ifndef TEST_DMA_SYNC
382116735Sharti#define	FATM_TX_QLEN		128		/* transmit queue length */
383116735Sharti#define	FATM_RX_QLEN		64		/* receive queue length */
384116735Sharti#else
385116735Sharti#define	FATM_TX_QLEN		8		/* transmit queue length */
386116735Sharti#define	FATM_RX_QLEN		8		/* receive queue length */
387116735Sharti#endif
388116735Sharti
389116735Sharti#define	SMALL_SUPPLY_QLEN	16
390116735Sharti#define	SMALL_POOL_SIZE		256
391116735Sharti#define	SMALL_SUPPLY_BLKSIZE	8
392116735Sharti
393116735Sharti#define	LARGE_SUPPLY_QLEN	16
394116735Sharti#define	LARGE_POOL_SIZE		128
395116735Sharti#define	LARGE_SUPPLY_BLKSIZE	8
396