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 */