1/*	$NetBSD: iavcreg.h,v 1.3 2005/12/24 20:27:30 perry Exp $	*/
2
3/*
4 * Copyright (c) 2001-2003 Cubical Solutions Ltd. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * capi/iavc/iavc.h	The AVM ISDN controllers' common declarations.
28 *
29 * $FreeBSD: src/sys/i4b/capi/iavc/iavc.h,v 1.1.2.1 2001/08/10 14:08:34 obrien Exp $
30 */
31
32/*
33//  AMCC_{READ,WRITE}
34//      Routines to access the memory mapped registers of the
35//      S5933 DMA controller.
36*/
37
38static __inline u_int32_t AMCC_READ(iavc_softc_t *sc, int off)
39{
40    return bus_space_read_4(sc->sc_mem_bt, sc->sc_mem_bh, off);
41}
42
43static __inline void AMCC_WRITE(iavc_softc_t *sc, int off, u_int32_t value)
44{
45    bus_space_write_4(sc->sc_mem_bt, sc->sc_mem_bh, off, value);
46}
47
48/*
49//  amcc_{put,get}_{byte,word}
50//      Routines to access the DMA buffers byte- or wordwise.
51*/
52
53static __inline u_int8_t* amcc_put_byte(u_int8_t *buf, u_int8_t value)
54{
55    *buf++ = value;
56    return buf;
57}
58
59static __inline u_int8_t* amcc_get_byte(u_int8_t *buf, u_int8_t *value)
60{
61    *value = *buf++;
62    return buf;
63}
64
65static __inline u_int8_t* amcc_put_word(u_int8_t *buf, u_int32_t value)
66{
67    *buf++ = (value & 0xff);
68    *buf++ = (value >> 8) & 0xff;
69    *buf++ = (value >> 16) & 0xff;
70    *buf++ = (value >> 24) & 0xff;
71    return buf;
72}
73
74static __inline u_int8_t* amcc_get_word(u_int8_t *buf, u_int32_t *value)
75{
76    *value = *buf++;
77    *value |= (*buf++ << 8);
78    *value |= (*buf++ << 16);
79    *value |= (*buf++ << 24);
80    return buf;
81}
82
83/*
84//  Controller LLI message numbers.
85*/
86
87#define SEND_POLL           0x72
88#define SEND_INIT           0x11
89#define SEND_REGISTER       0x12
90#define SEND_DATA_B3_REQ    0x13
91#define SEND_RELEASE        0x14
92#define SEND_MESSAGE        0x15
93#define SEND_CONFIG         0x71
94#define SEND_POLLACK        0x73
95
96#define RECEIVE_POLL        0x32
97#define RECEIVE_INIT        0x27
98#define RECEIVE_MESSAGE     0x21
99#define RECEIVE_DATA_B3_IND 0x22
100#define RECEIVE_START       0x23
101#define RECEIVE_STOP        0x24
102#define RECEIVE_NEW_NCCI    0x25
103#define RECEIVE_FREE_NCCI   0x26
104#define RECEIVE_RELEASE     0x26
105#define RECEIVE_TASK_READY  0x31
106#define RECEIVE_DEBUGMSG    0x71
107#define RECEIVE_POLLDWORD   0x75
108
109/* Operation constants */
110
111#define WRITE_REGISTER      0x00
112#define READ_REGISTER       0x01
113
114/* Port offsets in I/O space */
115
116#define B1_READ             0x00
117#define B1_WRITE            0x01
118#define B1_INSTAT           0x02
119#define B1_OUTSTAT          0x03
120#define B1_ANALYSE          0x04
121#define B1_REVISION         0x05
122#define B1_RESET            0x10
123
124#define T1_FASTLINK         0x00
125#define T1_SLOWLINK         0x08
126
127#define T1_READ             B1_READ
128#define T1_WRITE            B1_WRITE
129#define T1_INSTAT           B1_INSTAT
130#define T1_OUTSTAT          B1_OUTSTAT
131#define T1_IRQENABLE        0x05
132#define T1_FIFOSTAT         0x06
133#define T1_RESETLINK        0x10
134#define T1_ANALYSE          0x11
135#define T1_IRQMASTER        0x12
136#define T1_IDENT            0x17
137#define T1_RESETBOARD       0x1f
138
139#define T1F_IREADY          0x01
140#define T1F_IHALF           0x02
141#define T1F_IFULL           0x04
142#define T1F_IEMPTY          0x08
143#define T1F_IFLAGS          0xf0
144
145#define T1F_OREADY          0x10
146#define T1F_OHALF           0x20
147#define T1F_OEMPTY          0x40
148#define T1F_OFULL           0x80
149#define T1F_OFLAGS          0xf0
150
151#define FIFO_OUTBSIZE       256
152#define FIFO_INPBSIZE       512
153
154#define HEMA_VERSION_ID     0
155#define HEMA_PAL_ID         0
156
157/*
158//  S5933 DMA controller register offsets in memory, and bitmasks.
159*/
160
161#define AMCC_RXPTR       0x24
162#define AMCC_RXLEN       0x28
163#define AMCC_TXPTR       0x2c
164#define AMCC_TXLEN       0x30
165
166#define AMCC_INTCSR      0x38
167#define EN_READ_TC_INT   0x00008000
168#define EN_WRITE_TC_INT  0x00004000
169#define EN_TX_TC_INT     EN_READ_TC_INT
170#define EN_RX_TC_INT     EN_WRITE_TC_INT
171#define AVM_FLAG         0x30000000
172
173#define ANY_S5933_INT    0x00800000
174#define READ_TC_INT      0x00080000
175#define WRITE_TC_INT     0x00040000
176#define TX_TC_INT        READ_TC_INT
177#define RX_TC_INT        WRITE_TC_INT
178#define MASTER_ABORT_INT 0x00100000
179#define TARGET_ABORT_INT 0x00200000
180#define BUS_MASTER_INT   0x00200000
181#define ALL_INT          0x000c0000
182
183#define AMCC_MCSR        0x3c
184#define A2P_HI_PRIORITY  0x00000100
185#define EN_A2P_TRANSFERS 0x00000400
186#define P2A_HI_PRIORITY  0x00001000
187#define EN_P2A_TRANSFERS 0x00004000
188#define RESET_A2P_FLAGS  0x04000000
189#define RESET_P2A_FLAGS  0x02000000
190
191/*
192//  (B1IO_WAIT_MAX * B1IO_WAIT_DLY) is the max wait in us for the card
193//  to become ready after an I/O operation. The default is 1 ms.
194*/
195
196#define B1IO_WAIT_MAX    1000
197#define B1IO_WAIT_DLY    1
198
199/*
200//  b1io_outp
201//      Diagnostic output routine, returns the written value via
202//      the device's analysis register.
203//
204//  b1io_rx_full
205//      Returns nonzero if data is readable from the card via the
206//      I/O ports.
207//
208//  b1io_tx_empty
209//      Returns nonzero if data can be written to the card via the
210//      I/O ports.
211*/
212
213static __inline u_int8_t b1io_outp(iavc_softc_t *sc, int off, u_int8_t val)
214{
215    bus_space_write_1(sc->sc_io_bt, sc->sc_io_bh, off, val);
216    DELAY(1);
217    return bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, B1_ANALYSE);
218}
219
220static __inline int b1io_rx_full(iavc_softc_t *sc)
221{
222    u_int8_t val = bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, B1_INSTAT);
223    return (val & 0x01);
224}
225
226static __inline int b1io_tx_empty(iavc_softc_t *sc)
227{
228    u_int8_t val = bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, B1_OUTSTAT);
229    return  (val & 0x01);
230}
231
232/*
233//  b1io_{get,put}_{byte,word}
234//      Routines to read and write the device I/O registers byte- or
235//      wordwise.
236//
237//  b1io_{get,put}_slice
238//      Routines to read and write sequential bytes to the device
239//      I/O registers.
240*/
241
242static __inline u_int8_t b1io_get_byte(iavc_softc_t *sc)
243{
244    int spin = 0;
245    while (!b1io_rx_full(sc) && spin < B1IO_WAIT_MAX) {
246	spin++; DELAY(B1IO_WAIT_DLY);
247    }
248    if (b1io_rx_full(sc))
249	return bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, B1_READ);
250    printf("iavc%d: rx not completed\n", sc->sc_unit);
251    return 0xff;
252}
253
254static __inline int b1io_put_byte(iavc_softc_t *sc, u_int8_t val)
255{
256    int spin = 0;
257    while (!b1io_tx_empty(sc) && spin < B1IO_WAIT_MAX) {
258	spin++; DELAY(B1IO_WAIT_DLY);
259    }
260    if (b1io_tx_empty(sc)) {
261	bus_space_write_1(sc->sc_io_bt, sc->sc_io_bh, B1_WRITE, val);
262	return 0;
263    }
264    printf("iavc%d: tx not emptied\n", sc->sc_unit);
265    return -1;
266}
267
268static __inline int b1io_save_put_byte(iavc_softc_t *sc, u_int8_t val)
269{
270    int spin = 0;
271    while (!b1io_tx_empty(sc) && spin < B1IO_WAIT_MAX) {
272	spin++; DELAY(B1IO_WAIT_DLY);
273    }
274    if (b1io_tx_empty(sc)) {
275	b1io_outp(sc, B1_WRITE, val);
276	return 0;
277    }
278    printf("iavc%d: tx not emptied\n", sc->sc_unit);
279    return -1;
280}
281
282static __inline u_int32_t b1io_get_word(iavc_softc_t *sc)
283{
284    u_int32_t val = 0;
285    val |= b1io_get_byte(sc);
286    val |= (b1io_get_byte(sc) << 8);
287    val |= (b1io_get_byte(sc) << 16);
288    val |= (b1io_get_byte(sc) << 24);
289    return val;
290}
291
292static __inline void b1io_put_word(iavc_softc_t *sc, u_int32_t val)
293{
294    b1io_put_byte(sc, (val & 0xff));
295    b1io_put_byte(sc, (val >> 8) & 0xff);
296    b1io_put_byte(sc, (val >> 16) & 0xff);
297    b1io_put_byte(sc, (val >> 24) & 0xff);
298}
299
300static __inline int b1io_get_slice(iavc_softc_t *sc, u_int8_t *dp)
301{
302    int len, i;
303    len = i = b1io_get_word(sc);
304    while (i--) *dp++ = b1io_get_byte(sc);
305    return len;
306}
307
308static __inline void b1io_put_slice(iavc_softc_t *sc, u_int8_t *dp, int len)
309{
310    b1io_put_word(sc, len);
311    while (len--) b1io_put_byte(sc, *dp++);
312}
313
314/*
315//  b1io_{read,write}_reg
316//      Routines to read and write the device registers via the I/O
317//      ports.
318*/
319
320static __inline u_int32_t b1io_read_reg(iavc_softc_t *sc, int reg)
321{
322    b1io_put_byte(sc, READ_REGISTER);
323    b1io_put_word(sc, reg);
324    return b1io_get_word(sc);
325}
326
327static __inline u_int32_t b1io_write_reg(iavc_softc_t *sc, int reg, u_int32_t val)
328{
329    b1io_put_byte(sc, WRITE_REGISTER);
330    b1io_put_word(sc, reg);
331    b1io_put_word(sc, val);
332    return b1io_get_word(sc);
333}
334
335/*
336//  t1io_outp
337//      I/O port write operation for the T1, which does not seem
338//      to have the analysis port.
339*/
340
341static __inline void t1io_outp(iavc_softc_t *sc, int off, u_int8_t val)
342{
343    bus_space_write_1(sc->sc_io_bt, sc->sc_io_bh, off, val);
344}
345
346static __inline u_int8_t t1io_inp(iavc_softc_t *sc, int off)
347{
348    return bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, off);
349}
350
351static __inline int t1io_isfastlink(iavc_softc_t *sc)
352{
353    return ((bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, T1_IDENT) & ~0x82) == 1);
354}
355
356static __inline u_int8_t t1io_fifostatus(iavc_softc_t *sc)
357{
358    return bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, T1_FIFOSTAT);
359}
360
361static __inline int t1io_get_slice(iavc_softc_t *sc, u_int8_t *dp)
362{
363    int len, i;
364    len = i = b1io_get_word(sc);
365    if (t1io_isfastlink(sc)) {
366	int status;
367	while (i) {
368	    status = t1io_fifostatus(sc) & (T1F_IREADY|T1F_IHALF);
369	    if (i >= FIFO_INPBSIZE) status |= T1F_IFULL;
370
371	    switch (status) {
372	    case T1F_IREADY|T1F_IHALF|T1F_IFULL:
373		bus_space_read_multi_1(sc->sc_io_bt, sc->sc_io_bh,
374				       T1_READ, dp, FIFO_INPBSIZE);
375		dp += FIFO_INPBSIZE;
376		i -= FIFO_INPBSIZE;
377		break;
378
379	    case T1F_IREADY|T1F_IHALF:
380		bus_space_read_multi_1(sc->sc_io_bt, sc->sc_io_bh,
381				       T1_READ, dp, i);
382		dp += i;
383		i = 0;
384		break;
385
386	    default:
387		*dp++ = b1io_get_byte(sc);
388		i--;
389	    }
390	}
391    } else { /* not fastlink */
392	if (i--) *dp++ = b1io_get_byte(sc);
393    }
394    return len;
395}
396
397static __inline void t1io_put_slice(iavc_softc_t *sc, u_int8_t *dp, int len)
398{
399    int i = len;
400    b1io_put_word(sc, i);
401    if (t1io_isfastlink(sc)) {
402	int status;
403	while (i) {
404	    status = t1io_fifostatus(sc) & (T1F_OREADY|T1F_OHALF);
405	    if (i >= FIFO_OUTBSIZE) status |= T1F_OFULL;
406
407	    switch (status) {
408	    case T1F_OREADY|T1F_OHALF|T1F_OFULL:
409		bus_space_write_multi_1(sc->sc_io_bt, sc->sc_io_bh,
410					T1_WRITE, dp, FIFO_OUTBSIZE);
411		dp += FIFO_OUTBSIZE;
412		i -= FIFO_OUTBSIZE;
413		break;
414
415	    case T1F_OREADY|T1F_OHALF:
416		bus_space_write_multi_1(sc->sc_io_bt, sc->sc_io_bh,
417					T1_WRITE, dp, i);
418		dp += i;
419		i = 0;
420		break;
421
422	    default:
423		b1io_put_byte(sc, *dp++);
424		i--;
425	    }
426	}
427    } else {
428	while (i--) b1io_put_byte(sc, *dp++);
429    }
430}
431
432/*
433//  An attempt to bring it all together:
434//  ------------------------------------
435//
436//  iavc_{read,write}_reg
437//      Routines to access the device registers via the I/O port.
438//
439//  iavc_{read,write}_port
440//      Routines to access the device I/O ports.
441//
442//  iavc_tx_empty, iavc_rx_full
443//      Routines to check when the device has drained the last written
444//      byte, or produced a full byte to read.
445//
446//  iavc_{get,put}_byte
447//      Routines to read/write byte values to the device via the I/O port.
448//
449//  iavc_{get,put}_word
450//      Routines to read/write 32-bit words to the device via the I/O port.
451//
452//  iavc_{get,put}_slice
453//      Routines to read/write {length, data} pairs to the device via the
454//      ubiquituous I/O port. Uses the HEMA FIFO on a T1.
455*/
456
457#define iavc_read_reg(sc, reg) b1io_read_reg(sc, reg)
458#define iavc_write_reg(sc, reg, val) b1io_write_reg(sc, reg, val)
459
460#define iavc_read_port(sc, port) \
461        bus_space_read_1(sc->sc_io_bt, sc->sc_io_bh, (port))
462#define iavc_write_port(sc, port, val) \
463        bus_space_write_1(sc->sc_io_bt, sc->sc_io_bh, (port), (val))
464
465#define iavc_tx_empty(sc)      b1io_tx_empty(sc)
466#define iavc_rx_full(sc)       b1io_rx_full(sc)
467
468#define iavc_get_byte(sc)      b1io_get_byte(sc)
469#define iavc_put_byte(sc, val) b1io_put_byte(sc, val)
470#define iavc_get_word(sc)      b1io_get_word(sc)
471#define iavc_put_word(sc, val) b1io_put_word(sc, val)
472
473static __inline u_int32_t iavc_get_slice(iavc_softc_t *sc, u_int8_t *dp)
474{
475    if (sc->sc_t1) return t1io_get_slice(sc, dp);
476    else return b1io_get_slice(sc, dp);
477}
478
479static __inline void iavc_put_slice(iavc_softc_t *sc, u_int8_t *dp, int len)
480{
481    if (sc->sc_t1) t1io_put_slice(sc, dp, len);
482    else b1io_put_slice(sc, dp, len);
483}
484