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