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 #pragma ident   "%Z%%M% %I%     %E% SMI"
  31 
  32 #include <sys/note.h>
  33 
  34 #ifdef  __cplusplus
  35 extern "C" {
  36 #endif
  37 
  38 struct ecppunit;
  39 
  40 /*
  41  * Hardware-abstraction structure
  42  */
  43 struct ecpp_hw {
  44         int     (*map_regs)(struct ecppunit *);         /* map registers */
  45         void    (*unmap_regs)(struct ecppunit *);       /* unmap registers */
  46         int     (*config_chip)(struct ecppunit *);      /* configure SuperIO */
  47         void    (*config_mode)(struct ecppunit *);      /* config new mode */
  48         void    (*mask_intr)(struct ecppunit *);        /* mask interrupts */
  49         void    (*unmask_intr)(struct ecppunit *);      /* unmask interrupts */
  50         int     (*dma_start)(struct ecppunit *);        /* start DMA transfer */
  51         int     (*dma_stop)(struct ecppunit *, size_t *); /* stop DMA xfer */
  52         size_t  (*dma_getcnt)(struct ecppunit *);       /* get DMA counter */
  53         ddi_dma_attr_t  *attr;                          /* DMA attributes */
  54 };
  55 
  56 #define ECPP_MAP_REGS(pp)               (pp)->hw->map_regs(pp)
  57 #define ECPP_UNMAP_REGS(pp)             (pp)->hw->unmap_regs(pp)
  58 #define ECPP_CONFIG_CHIP(pp)            (pp)->hw->config_chip(pp)
  59 #define ECPP_CONFIG_MODE(pp)            (pp)->hw->config_mode(pp)
  60 #define ECPP_MASK_INTR(pp)              (pp)->hw->mask_intr(pp)
  61 #define ECPP_UNMASK_INTR(pp)            (pp)->hw->unmask_intr(pp)
  62 #define ECPP_DMA_START(pp)              (pp)->hw->dma_start(pp)
  63 #define ECPP_DMA_STOP(pp, cnt)          (pp)->hw->dma_stop(pp, cnt)
  64 #define ECPP_DMA_GETCNT(pp)             (pp)->hw->dma_getcnt(pp)
  65 
  66 /* NSC 87332/97317 and EBus DMAC */
  67 struct ecpp_ebus {
  68         struct config_reg       *c_reg;         /* configuration registers */
  69         ddi_acc_handle_t        c_handle;       /* handle for conf regs */
  70         struct cheerio_dma_reg  *dmac;          /* ebus dmac registers */
  71         ddi_acc_handle_t        d_handle;       /* handle for dmac registers */
  72         struct config2_reg      *c2_reg;        /* 97317 2nd level conf regs */
  73         ddi_acc_handle_t        c2_handle;      /* handle for c2_reg */
  74 };
  75 
  76 /* Southbridge SuperIO and 8237 DMAC */
  77 struct ecpp_m1553 {
  78         struct isaspace         *isa_space;     /* all of isa space */
  79         ddi_acc_handle_t        d_handle;       /* handle for isa space */
  80         uint8_t                 chn;            /* 8237 dma channel */
  81         int                     isadma_entered; /* Southbridge DMA workaround */
  82 };
  83 
  84 #if defined(__x86)
  85 struct ecpp_x86 {
  86         uint8_t                 chn;
  87 };
  88 #endif
  89 
  90 /*
  91  * Hardware binding structure
  92  */
  93 struct ecpp_hw_bind {
  94         char            *name;          /* binding name */
  95         struct ecpp_hw  *hw;            /* hw description */
  96         char            *info;          /* info string */
  97 };
  98 
  99 /*
 100  * ecpp soft state structure
 101  */
 102 struct ecppunit {
 103         kmutex_t        umutex;         /* lock for this structure */
 104         int             instance;       /* instance number */
 105         dev_info_t      *dip;           /* device information */
 106         ddi_iblock_cookie_t ecpp_trap_cookie;   /* interrupt cookie */
 107         boolean_t       e_busy;         /* ecpp busy flag */
 108         kcondvar_t      pport_cv;       /* cv to signal idle state */
 109         /*
 110          * common SuperIO registers
 111          */
 112         struct info_reg         *i_reg;         /* info registers */
 113         struct fifo_reg         *f_reg;         /* fifo register */
 114         ddi_acc_handle_t        i_handle;
 115         ddi_acc_handle_t        f_handle;
 116         /*
 117          * DMA support
 118          */
 119         ddi_dma_handle_t        dma_handle;     /* DMA handle */
 120         ddi_dma_cookie_t        dma_cookie;     /* current cookie */
 121         uint_t                  dma_cookie_count;       /* # of cookies */
 122         uint_t                  dma_nwin;       /* # of DMA windows */
 123         uint_t                  dma_curwin;     /* current window number */
 124         uint_t                  dma_dir;        /* transfer direction */
 125         /*
 126          * hardware-dependent stuff
 127          */
 128         struct ecpp_hw  *hw;            /* operations/attributes */
 129         union {                         /* hw-dependent data */
 130                 struct ecpp_ebus        ebus;
 131                 struct ecpp_m1553       m1553;
 132 #if defined(__x86)
 133                 struct ecpp_x86         x86;
 134 #endif
 135         } uh;
 136         /*
 137          * DDI/STREAMS stuff
 138          */
 139         boolean_t       oflag;          /* instance open flag */
 140         queue_t         *readq;         /* pointer to readq */
 141         queue_t         *writeq;        /* pointer to writeq */
 142         mblk_t          *msg;           /* current message block */
 143         boolean_t       suspended;      /* driver suspended status */
 144         /*
 145          * Modes of operation
 146          */
 147         int             current_mode;   /* 1284 mode */
 148         uchar_t         current_phase;  /* 1284 phase */
 149         uchar_t         backchannel;    /* backchannel mode supported */
 150         uchar_t         io_mode;        /* transfer mode: PIO/DMA */
 151         /*
 152          * Ioctls support
 153          */
 154         struct ecpp_transfer_parms xfer_parms;  /* transfer parameters */
 155         struct ecpp_regs regs;          /* control/status registers */
 156         uint8_t         saved_dsr;      /* store the dsr returned from TESTIO */
 157         boolean_t       timeout_error;  /* store the timeout for GETERR */
 158         uchar_t         port;           /* xfer type: dma/pio/tfifo */
 159         struct prn_timeouts prn_timeouts; /* prnio timeouts */
 160         /*
 161          * ecpp.conf parameters
 162          */
 163         uchar_t         init_seq;       /* centronics init seq */
 164         uint32_t        wsrv_retry;     /* delay (ms) before next wsrv */
 165         uint32_t        wait_for_busy;  /* wait for BUSY to deassert */
 166         uint32_t        data_setup_time; /* pio centronics handshake */
 167         uint32_t        strobe_pulse_width; /* pio centronics handshake */
 168         uint8_t         fast_centronics; /* DMA/PIO centronics */
 169         uint8_t         fast_compat;    /* DMA/PIO 1284 compatible mode */
 170         uint32_t        ecp_rev_speed;  /* rev xfer speed in ECP, bytes/sec */
 171         uint32_t        rev_watchdog;   /* rev xfer watchdog period, ms */
 172         /*
 173          * Timeouts
 174          */
 175         timeout_id_t    timeout_id;     /* io transfers timer */
 176         timeout_id_t    fifo_timer_id;  /* drain SuperIO FIFO */
 177         timeout_id_t    wsrv_timer_id;  /* wsrv timeout */
 178         /*
 179          * Softintr data
 180          */
 181         ddi_softintr_t  softintr_id;
 182         int             softintr_flags; /* flags indicating softintr task */
 183         uint8_t         softintr_pending;
 184         /*
 185          * Misc stuff
 186          */
 187         caddr_t         ioblock;        /* transfer buffer block */
 188         size_t          xfercnt;        /* # of bytes to transfer */
 189         size_t          resid;          /* # of bytes not transferred */
 190         caddr_t         next_byte;      /* next byte for PIO transfer */
 191         caddr_t         last_byte;      /* last byte for PIO transfer */
 192         uint32_t        ecpp_drain_counter;     /* allows fifo to drain */
 193         uchar_t         dma_cancelled;  /* flushed while dma'ing */
 194         uint8_t         tfifo_intr;     /* TFIFO switch interrupt workaround */
 195         size_t          nread;          /* requested read */
 196         size_t          last_dmacnt;    /* DMA counter value for rev watchdog */
 197         uint32_t        rev_timeout_cnt; /* number of watchdog invocations */
 198         /*
 199          * Spurious interrupt detection
 200          */
 201         hrtime_t        lastspur;       /* last time spurious intrs started */
 202         long            nspur;          /* spurious intrs counter */
 203         /*
 204          * Statistics
 205          */
 206         kstat_t         *ksp;           /* kstat pointer */
 207         kstat_t         *intrstats;     /* kstat interrupt counter */
 208         /*
 209          * number of bytes, transferred in and out in each mode
 210          */
 211         uint32_t        ctxpio_obytes;
 212         uint32_t        obytes[ECPP_EPP_MODE+1];
 213         uint32_t        ibytes[ECPP_EPP_MODE+1];
 214         /*
 215          * other stats
 216          */
 217         uint32_t        to_mode[ECPP_EPP_MODE+1]; /* # transitions to mode */
 218         uint32_t        xfer_tout;      /* # transfer timeouts */
 219         uint32_t        ctx_cf;         /* # periph check failures */
 220         uint32_t        joblen;         /* of bytes xfer'd since open */
 221         uint32_t        isr_reattempt_high;     /* max times isr has looped */
 222         /*
 223          * interrupt stats
 224          */
 225         uint_t          intr_hard;
 226         uint_t          intr_spurious;
 227         uint_t          intr_soft;
 228         /*
 229          * identify second register set for ecp mode on Sx86
 230          */
 231         int             noecpregs;
 232 };
 233 
 234 _NOTE(MUTEX_PROTECTS_DATA(ecppunit::umutex, ecppunit))
 235 _NOTE(DATA_READABLE_WITHOUT_LOCK(ecppunit::dip))
 236 _NOTE(DATA_READABLE_WITHOUT_LOCK(ecppunit::instance))
 237 _NOTE(DATA_READABLE_WITHOUT_LOCK(ecppunit::i_reg))
 238 _NOTE(DATA_READABLE_WITHOUT_LOCK(ecppunit::f_reg))
 239 _NOTE(DATA_READABLE_WITHOUT_LOCK(ecppunit::i_handle))
 240 _NOTE(DATA_READABLE_WITHOUT_LOCK(ecppunit::f_handle))
 241 _NOTE(DATA_READABLE_WITHOUT_LOCK(ecppunit::ecpp_trap_cookie))
 242 _NOTE(DATA_READABLE_WITHOUT_LOCK(ecppunit::readq))
 243 _NOTE(DATA_READABLE_WITHOUT_LOCK(ecppunit::writeq))
 244 
 245 /*
 246  * current_phase values
 247  */
 248 #define ECPP_PHASE_INIT         0x00    /* initialization */
 249 #define ECPP_PHASE_NEGO         0x01    /* negotiation */
 250 #define ECPP_PHASE_TERM         0x02    /* termination */
 251 #define ECPP_PHASE_PO           0x03    /* power-on */
 252 
 253 #define ECPP_PHASE_C_FWD_DMA    0x10    /* cntrx/compat fwd dma xfer */
 254 #define ECPP_PHASE_C_FWD_PIO    0x11    /* cntrx/compat fwd PIO xfer */
 255 #define ECPP_PHASE_C_IDLE       0x12    /* cntrx/compat idle */
 256 
 257 #define ECPP_PHASE_NIBT_REVDATA 0x20    /* nibble/byte reverse data */
 258 #define ECPP_PHASE_NIBT_AVAIL   0x21    /* nibble/byte reverse data available */
 259 #define ECPP_PHASE_NIBT_NAVAIL  0x22    /* nibble/byte reverse data not avail */
 260 #define ECPP_PHASE_NIBT_REVIDLE 0x22    /* nibble/byte reverse idle */
 261 #define ECPP_PHASE_NIBT_REVINTR 0x23    /* nibble/byte reverse interrupt */
 262 
 263 #define ECPP_PHASE_ECP_SETUP    0x30    /* ecp setup */
 264 #define ECPP_PHASE_ECP_FWD_XFER 0x31    /* ecp forward transfer */
 265 #define ECPP_PHASE_ECP_FWD_IDLE 0x32    /* ecp forward idle */
 266 #define ECPP_PHASE_ECP_FWD_REV  0x33    /* ecp forward to reverse */
 267 #define ECPP_PHASE_ECP_REV_XFER 0x34    /* ecp reverse transfer */
 268 #define ECPP_PHASE_ECP_REV_IDLE 0x35    /* ecp reverse idle */
 269 #define ECPP_PHASE_ECP_REV_FWD  0x36    /* ecp reverse to forward */
 270 
 271 #define ECPP_PHASE_EPP_INIT_IDLE 0x40   /* epp init phase */
 272 #define ECPP_PHASE_EPP_IDLE     0x41    /* epp all-round phase */
 273 
 274 #define FAILURE_PHASE           0x80
 275 #define UNDEFINED_PHASE         0x81
 276 
 277 /* ecpp return values */
 278 #define SUCCESS         1
 279 #define FAILURE         2
 280 
 281 /* ecpp e_busy states */
 282 #define ECPP_IDLE       1 /* No ongoing transfers */
 283 #define ECPP_BUSY       2 /* Ongoing transfers on the cable */
 284 #define ECPP_DATA       3 /* Not used */
 285 #define ECPP_ERR        4 /* Bad status in Centronics mode */
 286 #define ECPP_FLUSH      5 /* Currently flushing the q */
 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 */