xref: /illumos-gate/usr/src/uts/common/sys/ecppvar.h (revision 97e81309571898df9fdd94aab1216dfcf23e060b)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef	_SYS_ECPPVAR_H
28 #define	_SYS_ECPPVAR_H
29 
30 #include <sys/note.h>
31 
32 #ifdef	__cplusplus
33 extern "C" {
34 #endif
35 
36 struct ecppunit;
37 
38 /*
39  * Hardware-abstraction structure
40  */
41 struct ecpp_hw {
42 	int	(*map_regs)(struct ecppunit *);		/* map registers */
43 	void	(*unmap_regs)(struct ecppunit *);	/* unmap registers */
44 	int	(*config_chip)(struct ecppunit *);	/* configure SuperIO */
45 	void	(*config_mode)(struct ecppunit *);	/* config new mode */
46 	void	(*mask_intr)(struct ecppunit *);	/* mask interrupts */
47 	void	(*unmask_intr)(struct ecppunit *);	/* unmask interrupts */
48 	int	(*dma_start)(struct ecppunit *);	/* start DMA transfer */
49 	int	(*dma_stop)(struct ecppunit *, size_t *); /* stop DMA xfer */
50 	size_t	(*dma_getcnt)(struct ecppunit *);	/* get DMA counter */
51 	ddi_dma_attr_t	*attr;				/* DMA attributes */
52 };
53 
54 #define	ECPP_MAP_REGS(pp)		(pp)->hw->map_regs(pp)
55 #define	ECPP_UNMAP_REGS(pp)		(pp)->hw->unmap_regs(pp)
56 #define	ECPP_CONFIG_CHIP(pp)		(pp)->hw->config_chip(pp)
57 #define	ECPP_CONFIG_MODE(pp)		(pp)->hw->config_mode(pp)
58 #define	ECPP_MASK_INTR(pp)		(pp)->hw->mask_intr(pp)
59 #define	ECPP_UNMASK_INTR(pp)		(pp)->hw->unmask_intr(pp)
60 #define	ECPP_DMA_START(pp)		(pp)->hw->dma_start(pp)
61 #define	ECPP_DMA_STOP(pp, cnt)		(pp)->hw->dma_stop(pp, cnt)
62 #define	ECPP_DMA_GETCNT(pp)		(pp)->hw->dma_getcnt(pp)
63 
64 /* NSC 87332/97317 and EBus DMAC */
65 struct ecpp_ebus {
66 	struct config_reg	*c_reg; 	/* configuration registers */
67 	ddi_acc_handle_t	c_handle;	/* handle for conf regs */
68 	struct cheerio_dma_reg	*dmac;		/* ebus dmac registers */
69 	ddi_acc_handle_t	d_handle;	/* handle for dmac registers */
70 	struct config2_reg	*c2_reg; 	/* 97317 2nd level conf regs */
71 	ddi_acc_handle_t	c2_handle;	/* handle for c2_reg */
72 };
73 
74 /* Southbridge SuperIO and 8237 DMAC */
75 struct ecpp_m1553 {
76 	struct isaspace		*isa_space;	/* all of isa space */
77 	ddi_acc_handle_t	d_handle;	/* handle for isa space */
78 	uint8_t			chn;		/* 8237 dma channel */
79 	int			isadma_entered;	/* Southbridge DMA workaround */
80 };
81 
82 #if defined(__x86)
83 struct ecpp_x86 {
84 	uint8_t			chn;
85 };
86 #endif
87 
88 /*
89  * Hardware binding structure
90  */
91 struct ecpp_hw_bind {
92 	char		*name;		/* binding name */
93 	struct ecpp_hw	*hw;		/* hw description */
94 	char		*info;		/* info string */
95 };
96 
97 /* ecpp e_busy states */
98 typedef enum {
99 	ECPP_IDLE = 1,	/* No ongoing transfers */
100 	ECPP_BUSY = 2,	/* Ongoing transfers on the cable */
101 	ECPP_DATA = 3,	/* Not used */
102 	ECPP_ERR = 4,	/* Bad status in Centronics mode */
103 	ECPP_FLUSH = 5	/* Currently flushing the q */
104 } ecpp_busy_t;
105 
106 /*
107  * ecpp soft state structure
108  */
109 struct ecppunit {
110 	kmutex_t	umutex;		/* lock for this structure */
111 	int		instance;	/* instance number */
112 	dev_info_t	*dip;		/* device information */
113 	ddi_iblock_cookie_t ecpp_trap_cookie;	/* interrupt cookie */
114 	ecpp_busy_t	e_busy;		/* ecpp busy flag */
115 	kcondvar_t	pport_cv;	/* cv to signal idle state */
116 	/*
117 	 * common SuperIO registers
118 	 */
119 	struct info_reg		*i_reg; 	/* info registers */
120 	struct fifo_reg		*f_reg; 	/* fifo register */
121 	ddi_acc_handle_t	i_handle;
122 	ddi_acc_handle_t	f_handle;
123 	/*
124 	 * DMA support
125 	 */
126 	ddi_dma_handle_t	dma_handle;	/* DMA handle */
127 	ddi_dma_cookie_t	dma_cookie;	/* current cookie */
128 	uint_t			dma_cookie_count;	/* # of cookies */
129 	uint_t			dma_nwin;	/* # of DMA windows */
130 	uint_t			dma_curwin;	/* current window number */
131 	uint_t			dma_dir;	/* transfer direction */
132 	/*
133 	 * hardware-dependent stuff
134 	 */
135 	struct ecpp_hw	*hw;		/* operations/attributes */
136 	union {				/* hw-dependent data */
137 		struct ecpp_ebus	ebus;
138 		struct ecpp_m1553	m1553;
139 #if defined(__x86)
140 		struct ecpp_x86 	x86;
141 #endif
142 	} uh;
143 	/*
144 	 * DDI/STREAMS stuff
145 	 */
146 	boolean_t	oflag;		/* instance open flag */
147 	queue_t		*readq;		/* pointer to readq */
148 	queue_t		*writeq;	/* pointer to writeq */
149 	mblk_t		*msg;		/* current message block */
150 	boolean_t	suspended;	/* driver suspended status */
151 	/*
152 	 * Modes of operation
153 	 */
154 	int		current_mode;	/* 1284 mode */
155 	uchar_t		current_phase;	/* 1284 phase */
156 	uchar_t		backchannel;	/* backchannel mode supported */
157 	uchar_t		io_mode;	/* transfer mode: PIO/DMA */
158 	/*
159 	 * Ioctls support
160 	 */
161 	struct ecpp_transfer_parms xfer_parms;	/* transfer parameters */
162 	struct ecpp_regs regs;		/* control/status registers */
163 	uint8_t		saved_dsr;	/* store the dsr returned from TESTIO */
164 	boolean_t	timeout_error;	/* store the timeout for GETERR */
165 	uchar_t		port;		/* xfer type: dma/pio/tfifo */
166 	struct prn_timeouts prn_timeouts; /* prnio timeouts */
167 	/*
168 	 * ecpp.conf parameters
169 	 */
170 	uchar_t		init_seq;	/* centronics init seq */
171 	uint32_t	wsrv_retry;	/* delay (ms) before next wsrv */
172 	uint32_t	wait_for_busy;	/* wait for BUSY to deassert */
173 	uint32_t	data_setup_time; /* pio centronics handshake */
174 	uint32_t	strobe_pulse_width; /* pio centronics handshake */
175 	uint8_t		fast_centronics; /* DMA/PIO centronics */
176 	uint8_t		fast_compat;	/* DMA/PIO 1284 compatible mode */
177 	uint32_t	ecp_rev_speed;	/* rev xfer speed in ECP, bytes/sec */
178 	uint32_t	rev_watchdog;	/* rev xfer watchdog period, ms */
179 	/*
180 	 * Timeouts
181 	 */
182 	timeout_id_t	timeout_id;	/* io transfers timer */
183 	timeout_id_t	fifo_timer_id;	/* drain SuperIO FIFO */
184 	timeout_id_t	wsrv_timer_id;	/* wsrv timeout */
185 	/*
186 	 * Softintr data
187 	 */
188 	ddi_softintr_t	softintr_id;
189 	int		softintr_flags;	/* flags indicating softintr task */
190 	uint8_t		softintr_pending;
191 	/*
192 	 * Misc stuff
193 	 */
194 	caddr_t		ioblock;	/* transfer buffer block */
195 	size_t		xfercnt;	/* # of bytes to transfer */
196 	size_t		resid;		/* # of bytes not transferred */
197 	caddr_t		next_byte;	/* next byte for PIO transfer */
198 	caddr_t		last_byte;	/* last byte for PIO transfer */
199 	uint32_t	ecpp_drain_counter;	/* allows fifo to drain */
200 	uchar_t		dma_cancelled;	/* flushed while dma'ing */
201 	uint8_t		tfifo_intr;	/* TFIFO switch interrupt workaround */
202 	size_t		nread;		/* requested read */
203 	size_t		last_dmacnt;	/* DMA counter value for rev watchdog */
204 	uint32_t	rev_timeout_cnt; /* number of watchdog invocations */
205 	/*
206 	 * Spurious interrupt detection
207 	 */
208 	hrtime_t	lastspur;	/* last time spurious intrs started */
209 	long		nspur;		/* spurious intrs counter */
210 	/*
211 	 * Statistics
212 	 */
213 	kstat_t		*ksp;		/* kstat pointer */
214 	kstat_t		*intrstats;	/* kstat interrupt counter */
215 	/*
216 	 * number of bytes, transferred in and out in each mode
217 	 */
218 	uint32_t	ctxpio_obytes;
219 	uint32_t	obytes[ECPP_EPP_MODE+1];
220 	uint32_t	ibytes[ECPP_EPP_MODE+1];
221 	/*
222 	 * other stats
223 	 */
224 	uint32_t	to_mode[ECPP_EPP_MODE+1]; /* # transitions to mode */
225 	uint32_t	xfer_tout;	/* # transfer timeouts */
226 	uint32_t	ctx_cf;		/* # periph check failures */
227 	uint32_t	joblen;		/* of bytes xfer'd since open */
228 	uint32_t	isr_reattempt_high;	/* max times isr has looped */
229 	/*
230 	 * interrupt stats
231 	 */
232 	uint_t		intr_hard;
233 	uint_t		intr_spurious;
234 	uint_t		intr_soft;
235 	/*
236 	 * identify second register set for ecp mode on Sx86
237 	 */
238 	int		noecpregs;
239 };
240 
241 _NOTE(MUTEX_PROTECTS_DATA(ecppunit::umutex, ecppunit))
242 _NOTE(DATA_READABLE_WITHOUT_LOCK(ecppunit::dip))
243 _NOTE(DATA_READABLE_WITHOUT_LOCK(ecppunit::instance))
244 _NOTE(DATA_READABLE_WITHOUT_LOCK(ecppunit::i_reg))
245 _NOTE(DATA_READABLE_WITHOUT_LOCK(ecppunit::f_reg))
246 _NOTE(DATA_READABLE_WITHOUT_LOCK(ecppunit::i_handle))
247 _NOTE(DATA_READABLE_WITHOUT_LOCK(ecppunit::f_handle))
248 _NOTE(DATA_READABLE_WITHOUT_LOCK(ecppunit::ecpp_trap_cookie))
249 _NOTE(DATA_READABLE_WITHOUT_LOCK(ecppunit::readq))
250 _NOTE(DATA_READABLE_WITHOUT_LOCK(ecppunit::writeq))
251 
252 /*
253  * current_phase values
254  */
255 #define	ECPP_PHASE_INIT		0x00	/* initialization */
256 #define	ECPP_PHASE_NEGO		0x01	/* negotiation */
257 #define	ECPP_PHASE_TERM		0x02	/* termination */
258 #define	ECPP_PHASE_PO		0x03	/* power-on */
259 
260 #define	ECPP_PHASE_C_FWD_DMA	0x10	/* cntrx/compat fwd dma xfer */
261 #define	ECPP_PHASE_C_FWD_PIO	0x11	/* cntrx/compat fwd PIO xfer */
262 #define	ECPP_PHASE_C_IDLE	0x12	/* cntrx/compat idle */
263 
264 #define	ECPP_PHASE_NIBT_REVDATA	0x20	/* nibble/byte reverse data */
265 #define	ECPP_PHASE_NIBT_AVAIL	0x21	/* nibble/byte reverse data available */
266 #define	ECPP_PHASE_NIBT_NAVAIL	0x22	/* nibble/byte reverse data not avail */
267 #define	ECPP_PHASE_NIBT_REVIDLE	0x22	/* nibble/byte reverse idle */
268 #define	ECPP_PHASE_NIBT_REVINTR	0x23	/* nibble/byte reverse interrupt */
269 
270 #define	ECPP_PHASE_ECP_SETUP	0x30	/* ecp setup */
271 #define	ECPP_PHASE_ECP_FWD_XFER	0x31	/* ecp forward transfer */
272 #define	ECPP_PHASE_ECP_FWD_IDLE	0x32	/* ecp forward idle */
273 #define	ECPP_PHASE_ECP_FWD_REV	0x33	/* ecp forward to reverse */
274 #define	ECPP_PHASE_ECP_REV_XFER	0x34	/* ecp reverse transfer */
275 #define	ECPP_PHASE_ECP_REV_IDLE	0x35	/* ecp reverse idle */
276 #define	ECPP_PHASE_ECP_REV_FWD	0x36	/* ecp reverse to forward */
277 
278 #define	ECPP_PHASE_EPP_INIT_IDLE 0x40	/* epp init phase */
279 #define	ECPP_PHASE_EPP_IDLE	0x41	/* epp all-round phase */
280 
281 #define	FAILURE_PHASE		0x80
282 #define	UNDEFINED_PHASE		0x81
283 
284 /* ecpp return values */
285 #define	SUCCESS		1
286 #define	FAILURE		2
287 
288 #define	TRUE		1
289 #define	FALSE		0
290 
291 /* message type */
292 #define	ECPP_BACKCHANNEL	0x45
293 
294 /* transfer modes */
295 #define	ECPP_DMA		0x1
296 #define	ECPP_PIO		0x2
297 
298 /* tuneable timing defaults */
299 #define	CENTRONICS_RETRY	750	/* 750 milliseconds */
300 #define	WAIT_FOR_BUSY		1000	/* 1000 microseconds */
301 #define	SUSPEND_TOUT		10	/* # seconds before suspend fails */
302 
303 /* Centronics hanshaking defaults */
304 #define	DATA_SETUP_TIME		2	/* 2 uSec Data Setup Time (2x min) */
305 #define	STROBE_PULSE_WIDTH	2	/* 2 uSec Strobe Pulse (2x min) */
306 
307 /* 1284 Extensibility Request values */
308 #define	ECPP_XREQ_NIBBLE	0x00    /* Nibble Mode Rev Channel Transfer */
309 #define	ECPP_XREQ_BYTE		0x01    /* Byte Mode Rev Channel Transfer */
310 #define	ECPP_XREQ_ID		0x04    /* Request Device ID */
311 #define	ECPP_XREQ_ECP		0x10    /* Request ECP Mode */
312 #define	ECPP_XREQ_ECPRLE	0x30    /* Request ECP Mode with RLE */
313 #define	ECPP_XREQ_EPP		0x40	/* Request EPP Mode */
314 #define	ECPP_XREQ_XLINK		0x80    /* Request Extensibility Link */
315 
316 /* softintr flags */
317 #define	ECPP_SOFTINTR_PIONEXT	0x1	/* write next byte in PIO mode */
318 
319 /* Stream  defaults */
320 #define	IO_BLOCK_SZ	1024 * 128	/* transfer buffer size */
321 #define	ECPPHIWAT	32 * 1024  * 6
322 #define	ECPPLOWAT	32 * 1024  * 4
323 
324 /* Loop timers */
325 #define	ECPP_REG_WRITE_MAX_LOOP	100	/* cpu is faster than superio */
326 #define	ECPP_ISR_MAX_DELAY	30	/* DMAC slow PENDING status */
327 
328 /* misc constants */
329 #define	ECPP_FIFO_SZ		16	/* FIFO size */
330 #define	FIFO_DRAIN_PERIOD	250000	/* max FIFO drain period in usec */
331 #define	NIBBLE_REV_BLKSZ	1024	/* send up to # bytes at a time */
332 #define	FWD_TIMEOUT_DEFAULT	90	/* forward xfer timeout in seconds */
333 #define	REV_TIMEOUT_DEFAULT	0	/* reverse xfer timeout in seconds */
334 
335 /* ECP mode constants */
336 #define	ECP_REV_BLKSZ		1024	/* send up to # bytes at a time */
337 #define	ECP_REV_BLKSZ_MAX	(4 * 1024)	/* maximum of # bytes */
338 #define	ECP_REV_SPEED		(1 * 1024 * 1024)	/* bytes/sec */
339 #define	ECP_REV_MINTOUT		5	/* min ECP rev xfer timeout in ms */
340 #define	REV_WATCHDOG		100	/* poll DMA counter every # ms */
341 
342 /* spurious interrupt detection */
343 #define	SPUR_CRITICAL		100	/* number of interrupts... */
344 #define	SPUR_PERIOD		1000000000 /* in # ns */
345 
346 /*
347  * Copyin/copyout states
348  */
349 #define	ECPP_STRUCTIN		0
350 #define	ECPP_STRUCTOUT		1
351 #define	ECPP_ADDRIN 		2
352 #define	ECPP_ADDROUT		3
353 
354 /*
355  * As other ioctls require the same structure, put inner struct's into union
356  */
357 struct ecpp_copystate {
358 	int	state;		/* see above */
359 	void	*uaddr;		/* user address of the following structure */
360 	union {
361 		struct ecpp_device_id		devid;
362 		struct prn_1284_device_id	prn_devid;
363 		struct prn_interface_info	prn_if;
364 	} un;
365 };
366 
367 /*
368  * The structure is dynamically created for each M_IOCTL and is bound to mblk
369  */
370 _NOTE(SCHEME_PROTECTS_DATA("unique per call", ecpp_copystate))
371 
372 /* kstat structure */
373 struct ecppkstat {
374 	/*
375 	 * number of bytes, transferred in and out in each mode
376 	 */
377 	struct kstat_named	ek_ctx_obytes;
378 	struct kstat_named	ek_ctxpio_obytes;
379 	struct kstat_named	ek_nib_ibytes;
380 	struct kstat_named	ek_ecp_obytes;
381 	struct kstat_named	ek_ecp_ibytes;
382 	struct kstat_named	ek_epp_obytes;
383 	struct kstat_named	ek_epp_ibytes;
384 	struct kstat_named	ek_diag_obytes;
385 	/*
386 	 * number of transitions to particular mode
387 	 */
388 	struct kstat_named	ek_to_ctx;
389 	struct kstat_named	ek_to_nib;
390 	struct kstat_named	ek_to_ecp;
391 	struct kstat_named	ek_to_epp;
392 	struct kstat_named	ek_to_diag;
393 	/*
394 	 * other stats
395 	 */
396 	struct kstat_named	ek_xfer_tout;	/* # transfer timeouts */
397 	struct kstat_named	ek_ctx_cf;	/* # periph check failures */
398 	struct kstat_named	ek_joblen;	/* # bytes xfer'd since open */
399 	struct kstat_named	ek_isr_reattempt_high;	/* max # times */
400 							/* isr has looped */
401 	struct kstat_named	ek_mode;	/* 1284 mode */
402 	struct kstat_named	ek_phase;	/* 1284 ECP phase */
403 	struct kstat_named	ek_backchan;	/* backchannel mode supported */
404 	struct kstat_named	ek_iomode;	/* transfer mode: pio/dma */
405 	struct kstat_named	ek_state;	/* ecpp busy flag */
406 };
407 
408 /* Macros for superio programming */
409 #define	PP_PUTB(x, y, z)  	ddi_put8(x, y, z)
410 #define	PP_GETB(x, y)		ddi_get8(x, y)
411 
412 #define	DSR_READ(pp)		PP_GETB((pp)->i_handle, &(pp)->i_reg->dsr)
413 #define	DCR_READ(pp)		PP_GETB((pp)->i_handle, &(pp)->i_reg->dcr)
414 #define	ECR_READ(pp)		\
415 	(pp->noecpregs) ? 0xff : PP_GETB((pp)->f_handle, &(pp)->f_reg->ecr)
416 #define	DATAR_READ(pp)		PP_GETB((pp)->i_handle, &(pp)->i_reg->ir.datar)
417 #define	DFIFO_READ(pp)		\
418 	(pp->noecpregs) ? 0xff : PP_GETB((pp)->f_handle, &(pp)->f_reg->fr.dfifo)
419 #define	TFIFO_READ(pp)		\
420 	(pp->noecpregs) ? 0xff : PP_GETB((pp)->f_handle, &(pp)->f_reg->fr.tfifo)
421 
422 #define	DCR_WRITE(pp, val)	PP_PUTB((pp)->i_handle, &(pp)->i_reg->dcr, val)
423 #define	ECR_WRITE(pp, val)	\
424 	if (!pp->noecpregs) PP_PUTB((pp)->f_handle, &(pp)->f_reg->ecr, val)
425 #define	DATAR_WRITE(pp, val)	\
426 			PP_PUTB((pp)->i_handle, &(pp)->i_reg->ir.datar, val)
427 #define	DFIFO_WRITE(pp, val)	\
428 	if (!pp->noecpregs) PP_PUTB((pp)->f_handle, &(pp)->f_reg->fr.dfifo, val)
429 #define	TFIFO_WRITE(pp, val)	\
430 	if (!pp->noecpregs) PP_PUTB((pp)->f_handle, &(pp)->f_reg->fr.tfifo, val)
431 
432 /*
433  * Macros to manipulate register bits
434  */
435 #define	OR_SET_BYTE_R(handle, addr, val) \
436 {		\
437 	uint8_t tmpval;					\
438 	tmpval = ddi_get8(handle, (uint8_t *)addr);	\
439 	tmpval |= val;					\
440 	ddi_put8(handle, (uint8_t *)addr, tmpval);	\
441 }
442 
443 #define	OR_SET_LONG_R(handle, addr, val) \
444 {		\
445 	uint32_t tmpval;				\
446 	tmpval = ddi_get32(handle, (uint32_t *)addr);	\
447 	tmpval |= val;					\
448 	ddi_put32(handle, (uint32_t *)addr, tmpval);	\
449 }
450 
451 #define	AND_SET_BYTE_R(handle, addr, val) \
452 {		\
453 	uint8_t tmpval;					\
454 	tmpval = ddi_get8(handle, (uint8_t *)addr);	\
455 	tmpval &= val; 					\
456 	ddi_put8(handle, (uint8_t *)addr, tmpval);	\
457 }
458 
459 #define	AND_SET_LONG_R(handle, addr, val) \
460 {		\
461 	uint32_t tmpval;				\
462 	tmpval = ddi_get32(handle, (uint32_t *)addr);	\
463 	tmpval &= val; 					\
464 	ddi_put32(handle, (uint32_t *)addr, tmpval);	\
465 }
466 
467 #define	NOR_SET_LONG_R(handle, addr, val, mask) \
468 {		\
469 	uint32_t tmpval;				\
470 	tmpval = ddi_get32(handle, (uint32_t *)addr);	\
471 	tmpval &= ~(mask);				\
472 	tmpval |= val;					\
473 	ddi_put32(handle, (uint32_t *)addr, tmpval);	\
474 }
475 
476 /*
477  * Macros for Cheerio/RIO DMAC programming
478  */
479 #define	SET_DMAC_CSR(pp, val)	ddi_put32(pp->uh.ebus.d_handle, \
480 				((uint32_t *)&pp->uh.ebus.dmac->csr), \
481 				((uint32_t)val))
482 #define	GET_DMAC_CSR(pp)	ddi_get32(pp->uh.ebus.d_handle, \
483 				(uint32_t *)&(pp->uh.ebus.dmac->csr))
484 
485 #define	SET_DMAC_ACR(pp, val)	ddi_put32(pp->uh.ebus.d_handle, \
486 				((uint32_t *)&pp->uh.ebus.dmac->acr), \
487 				((uint32_t)val))
488 
489 #define	GET_DMAC_ACR(pp)	ddi_get32(pp->uh.ebus.d_handle, \
490 				(uint32_t *)&pp->uh.ebus.dmac->acr)
491 
492 #define	SET_DMAC_BCR(pp, val)	ddi_put32(pp->uh.ebus.d_handle, \
493 				((uint32_t *)&pp->uh.ebus.dmac->bcr), \
494 				((uint32_t)val))
495 
496 #define	GET_DMAC_BCR(pp)	ddi_get32(pp->uh.ebus.d_handle, \
497 				((uint32_t *)&pp->uh.ebus.dmac->bcr))
498 
499 #define	DMAC_RESET_TIMEOUT	10000	/* in usec */
500 
501 /*
502  * Macros to distinguish between PIO and DMA Compatibility mode
503  */
504 #define	COMPAT_PIO(pp) (((pp)->io_mode == ECPP_PIO) &&		\
505 		    ((pp)->current_mode == ECPP_CENTRONICS ||	\
506 		    (pp)->current_mode == ECPP_COMPAT_MODE))
507 
508 #define	COMPAT_DMA(pp) (((pp)->io_mode == ECPP_DMA) &&		\
509 		    ((pp)->current_mode == ECPP_CENTRONICS ||	\
510 		    (pp)->current_mode == ECPP_COMPAT_MODE))
511 
512 /*
513  * Other useful macros
514  */
515 #define	NELEM(a)	(sizeof (a) / sizeof (*(a)))
516 #define	offsetof(s, m)	((size_t)(&(((s *)0)->m)))
517 
518 #ifdef	__cplusplus
519 }
520 #endif
521 
522 #endif	/* _SYS_ECPPVAR_H */
523