linux/drivers/char/scc.h
<<
>>
Prefs
   1/*
   2 * atari_SCC.h: Definitions for the Am8530 Serial Communications Controller
   3 *
   4 * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
   5 *
   6 * This file is subject to the terms and conditions of the GNU General Public
   7 * License.  See the file COPYING in the main directory of this archive
   8 * for more details.
   9 *
  10 */
  11
  12
  13#ifndef _SCC_H
  14#define _SCC_H
  15
  16#include <linux/delay.h>
  17
  18/* Special configuration ioctls for the Atari SCC5380 Serial
  19 * Communications Controller
  20 */
  21
  22/* ioctl command codes */
  23
  24#define TIOCGATSCC      0x54c0  /* get SCC configuration */
  25#define TIOCSATSCC      0x54c1  /* set SCC configuration */
  26#define TIOCDATSCC      0x54c2  /* reset configuration to defaults */
  27
  28/* Clock sources */
  29
  30#define CLK_RTxC        0
  31#define CLK_TRxC        1
  32#define CLK_PCLK        2
  33
  34/* baud_bases for the common clocks in the Atari. These are the real
  35 * frequencies divided by 16.
  36 */
  37   
  38#define SCC_BAUD_BASE_TIMC      19200   /* 0.3072 MHz from TT-MFP, Timer C */
  39#define SCC_BAUD_BASE_BCLK      153600  /* 2.4576 MHz */
  40#define SCC_BAUD_BASE_PCLK4     229500  /* 3.6720 MHz */
  41#define SCC_BAUD_BASE_PCLK      503374  /* 8.0539763 MHz */
  42#define SCC_BAUD_BASE_NONE      0       /* for not connected or unused
  43                                         * clock sources */
  44
  45/* The SCC clock configuration structure */
  46
  47struct scc_clock_config {
  48        unsigned        RTxC_base;      /* base_baud of RTxC */
  49        unsigned        TRxC_base;      /* base_baud of TRxC */
  50        unsigned        PCLK_base;      /* base_baud of PCLK, both channels! */
  51        struct {
  52                unsigned clksrc;        /* CLK_RTxC, CLK_TRxC or CLK_PCLK */
  53                unsigned divisor;       /* divisor for base baud, valid values:
  54                                         * see below */
  55        } baud_table[17];               /* For 50, 75, 110, 135, 150, 200, 300,
  56                                         * 600, 1200, 1800, 2400, 4800, 9600,
  57                                         * 19200, 38400, 57600 and 115200 bps.
  58                                         * The last two could be replaced by
  59                                         * other rates > 38400 if they're not
  60                                         * possible.
  61                                         */
  62};
  63
  64/* The following divisors are valid:
  65 *
  66 *   - CLK_RTxC: 1 or even (1, 2 and 4 are the direct modes, > 4 use
  67 *               the BRG)
  68 *
  69 *   - CLK_TRxC: 1, 2 or 4 (no BRG, only direct modes possible)
  70 *
  71 *   - CLK_PCLK: >= 4 and even (no direct modes, only BRG)
  72 *
  73 */
  74
  75struct scc_port {
  76        struct gs_port          gs;
  77        volatile unsigned char  *ctrlp;
  78        volatile unsigned char  *datap;
  79        int                     x_char;         /* xon/xoff character */
  80        int                     c_dcd;
  81        int                     channel;
  82        struct scc_port         *port_a;        /* Reference to port A and B */
  83        struct scc_port         *port_b;        /*   structs for reg access  */
  84};
  85
  86#define SCC_MAGIC       0x52696368
  87
  88/***********************************************************************/
  89/*                                                                     */
  90/*                             Register Names                          */
  91/*                                                                     */
  92/***********************************************************************/
  93
  94/* The SCC documentation gives no explicit names to the registers,
  95 * they're just called WR0..15 and RR0..15. To make the source code
  96 * better readable and make the transparent write reg read access (see
  97 * below) possible, I christen them here with self-invented names.
  98 * Note that (real) read registers are assigned numbers 16..31. WR7'
  99 * has number 33.
 100 */
 101
 102#define COMMAND_REG             0       /* wo */
 103#define INT_AND_DMA_REG         1       /* wo */
 104#define INT_VECTOR_REG          2       /* rw, common to both channels */
 105#define RX_CTRL_REG             3       /* rw */
 106#define AUX1_CTRL_REG           4       /* rw */
 107#define TX_CTRL_REG             5       /* rw */
 108#define SYNC_ADR_REG            6       /* wo */
 109#define SYNC_CHAR_REG           7       /* wo */
 110#define SDLC_OPTION_REG         33      /* wo */
 111#define TX_DATA_REG             8       /* wo */
 112#define MASTER_INT_CTRL         9       /* wo, common to both channels */
 113#define AUX2_CTRL_REG           10      /* rw */
 114#define CLK_CTRL_REG            11      /* wo */
 115#define TIMER_LOW_REG           12      /* rw */
 116#define TIMER_HIGH_REG          13      /* rw */
 117#define DPLL_CTRL_REG           14      /* wo */
 118#define INT_CTRL_REG            15      /* rw */
 119
 120#define STATUS_REG              16      /* ro */
 121#define SPCOND_STATUS_REG       17      /* wo */
 122/* RR2 is WR2 for Channel A, Channel B gives vector + current status: */
 123#define CURR_VECTOR_REG         18      /* Ch. B only, Ch. A for rw */
 124#define INT_PENDING_REG         19      /* Channel A only! */
 125/* RR4 is WR4, if b6(MR7') == 1 */
 126/* RR5 is WR5, if b6(MR7') == 1 */
 127#define FS_FIFO_LOW_REG         22      /* ro */
 128#define FS_FIFO_HIGH_REG        23      /* ro */
 129#define RX_DATA_REG             24      /* ro */
 130/* RR9 is WR3, if b6(MR7') == 1 */
 131#define DPLL_STATUS_REG         26      /* ro */
 132/* RR11 is WR10, if b6(MR7') == 1 */
 133/* RR12 is WR12 */
 134/* RR13 is WR13 */
 135/* RR14 not present */
 136/* RR15 is WR15 */
 137
 138
 139/***********************************************************************/
 140/*                                                                     */
 141/*                             Register Values                         */
 142/*                                                                     */
 143/***********************************************************************/
 144
 145
 146/* WR0: COMMAND_REG "CR" */
 147
 148#define CR_RX_CRC_RESET         0x40
 149#define CR_TX_CRC_RESET         0x80
 150#define CR_TX_UNDERRUN_RESET    0xc0
 151
 152#define CR_EXTSTAT_RESET        0x10
 153#define CR_SEND_ABORT           0x18
 154#define CR_ENAB_INT_NEXT_RX     0x20
 155#define CR_TX_PENDING_RESET     0x28
 156#define CR_ERROR_RESET          0x30
 157#define CR_HIGHEST_IUS_RESET    0x38
 158
 159
 160/* WR1: INT_AND_DMA_REG "IDR" */
 161
 162#define IDR_EXTSTAT_INT_ENAB    0x01
 163#define IDR_TX_INT_ENAB         0x02
 164#define IDR_PARERR_AS_SPCOND    0x04
 165
 166#define IDR_RX_INT_DISAB        0x00
 167#define IDR_RX_INT_FIRST        0x08
 168#define IDR_RX_INT_ALL          0x10
 169#define IDR_RX_INT_SPCOND       0x18
 170#define IDR_RX_INT_MASK         0x18
 171
 172#define IDR_WAITREQ_RX          0x20
 173#define IDR_WAITREQ_IS_REQ      0x40
 174#define IDR_WAITREQ_ENAB        0x80
 175
 176
 177/* WR3: RX_CTRL_REG "RCR" */
 178
 179#define RCR_RX_ENAB             0x01
 180#define RCR_DISCARD_SYNC_CHARS  0x02
 181#define RCR_ADDR_SEARCH         0x04
 182#define RCR_CRC_ENAB            0x08
 183#define RCR_SEARCH_MODE         0x10
 184#define RCR_AUTO_ENAB_MODE      0x20
 185
 186#define RCR_CHSIZE_MASK         0xc0
 187#define RCR_CHSIZE_5            0x00
 188#define RCR_CHSIZE_6            0x40
 189#define RCR_CHSIZE_7            0x80
 190#define RCR_CHSIZE_8            0xc0
 191
 192
 193/* WR4: AUX1_CTRL_REG "A1CR" */
 194
 195#define A1CR_PARITY_MASK        0x03
 196#define A1CR_PARITY_NONE        0x00
 197#define A1CR_PARITY_ODD         0x01
 198#define A1CR_PARITY_EVEN        0x03
 199
 200#define A1CR_MODE_MASK          0x0c
 201#define A1CR_MODE_SYNCR         0x00
 202#define A1CR_MODE_ASYNC_1       0x04
 203#define A1CR_MODE_ASYNC_15      0x08
 204#define A1CR_MODE_ASYNC_2       0x0c
 205
 206#define A1CR_SYNCR_MODE_MASK    0x30
 207#define A1CR_SYNCR_MONOSYNC     0x00
 208#define A1CR_SYNCR_BISYNC       0x10
 209#define A1CR_SYNCR_SDLC         0x20
 210#define A1CR_SYNCR_EXTCSYNC     0x30
 211
 212#define A1CR_CLKMODE_MASK       0xc0
 213#define A1CR_CLKMODE_x1         0x00
 214#define A1CR_CLKMODE_x16        0x40
 215#define A1CR_CLKMODE_x32        0x80
 216#define A1CR_CLKMODE_x64        0xc0
 217
 218
 219/* WR5: TX_CTRL_REG "TCR" */
 220
 221#define TCR_TX_CRC_ENAB         0x01
 222#define TCR_RTS                 0x02
 223#define TCR_USE_CRC_CCITT       0x00
 224#define TCR_USE_CRC_16          0x04
 225#define TCR_TX_ENAB             0x08
 226#define TCR_SEND_BREAK          0x10
 227
 228#define TCR_CHSIZE_MASK         0x60
 229#define TCR_CHSIZE_5            0x00
 230#define TCR_CHSIZE_6            0x20
 231#define TCR_CHSIZE_7            0x40
 232#define TCR_CHSIZE_8            0x60
 233
 234#define TCR_DTR                 0x80
 235
 236
 237/* WR7': SLDC_OPTION_REG "SOR" */
 238
 239#define SOR_AUTO_TX_ENAB        0x01
 240#define SOR_AUTO_EOM_RESET      0x02
 241#define SOR_AUTO_RTS_MODE       0x04
 242#define SOR_NRZI_DISAB_HIGH     0x08
 243#define SOR_ALT_DTRREQ_TIMING   0x10
 244#define SOR_READ_CRC_CHARS      0x20
 245#define SOR_EXTENDED_REG_ACCESS 0x40
 246
 247
 248/* WR9: MASTER_INT_CTRL "MIC" */
 249
 250#define MIC_VEC_INCL_STAT       0x01
 251#define MIC_NO_VECTOR           0x02
 252#define MIC_DISAB_LOWER_CHAIN   0x04
 253#define MIC_MASTER_INT_ENAB     0x08
 254#define MIC_STATUS_HIGH         0x10
 255#define MIC_IGN_INTACK          0x20
 256
 257#define MIC_NO_RESET            0x00
 258#define MIC_CH_A_RESET          0x40
 259#define MIC_CH_B_RESET          0x80
 260#define MIC_HARD_RESET          0xc0
 261
 262
 263/* WR10: AUX2_CTRL_REG "A2CR" */
 264
 265#define A2CR_SYNC_6             0x01
 266#define A2CR_LOOP_MODE          0x02
 267#define A2CR_ABORT_ON_UNDERRUN  0x04
 268#define A2CR_MARK_IDLE          0x08
 269#define A2CR_GO_ACTIVE_ON_POLL  0x10
 270
 271#define A2CR_CODING_MASK        0x60
 272#define A2CR_CODING_NRZ         0x00
 273#define A2CR_CODING_NRZI        0x20
 274#define A2CR_CODING_FM1         0x40
 275#define A2CR_CODING_FM0         0x60
 276
 277#define A2CR_PRESET_CRC_1       0x80
 278
 279
 280/* WR11: CLK_CTRL_REG "CCR" */
 281
 282#define CCR_TRxCOUT_MASK        0x03
 283#define CCR_TRxCOUT_XTAL        0x00
 284#define CCR_TRxCOUT_TXCLK       0x01
 285#define CCR_TRxCOUT_BRG         0x02
 286#define CCR_TRxCOUT_DPLL        0x03
 287
 288#define CCR_TRxC_OUTPUT         0x04
 289
 290#define CCR_TXCLK_MASK          0x18
 291#define CCR_TXCLK_RTxC          0x00
 292#define CCR_TXCLK_TRxC          0x08
 293#define CCR_TXCLK_BRG           0x10
 294#define CCR_TXCLK_DPLL          0x18
 295
 296#define CCR_RXCLK_MASK          0x60
 297#define CCR_RXCLK_RTxC          0x00
 298#define CCR_RXCLK_TRxC          0x20
 299#define CCR_RXCLK_BRG           0x40
 300#define CCR_RXCLK_DPLL          0x60
 301
 302#define CCR_RTxC_XTAL           0x80
 303
 304
 305/* WR14: DPLL_CTRL_REG "DCR" */
 306
 307#define DCR_BRG_ENAB            0x01
 308#define DCR_BRG_USE_PCLK        0x02
 309#define DCR_DTRREQ_IS_REQ       0x04
 310#define DCR_AUTO_ECHO           0x08
 311#define DCR_LOCAL_LOOPBACK      0x10
 312
 313#define DCR_DPLL_EDGE_SEARCH    0x20
 314#define DCR_DPLL_ERR_RESET      0x40
 315#define DCR_DPLL_DISAB          0x60
 316#define DCR_DPLL_CLK_BRG        0x80
 317#define DCR_DPLL_CLK_RTxC       0xa0
 318#define DCR_DPLL_FM             0xc0
 319#define DCR_DPLL_NRZI           0xe0
 320
 321
 322/* WR15: INT_CTRL_REG "ICR" */
 323
 324#define ICR_OPTIONREG_SELECT    0x01
 325#define ICR_ENAB_BRG_ZERO_INT   0x02
 326#define ICR_USE_FS_FIFO         0x04
 327#define ICR_ENAB_DCD_INT        0x08
 328#define ICR_ENAB_SYNC_INT       0x10
 329#define ICR_ENAB_CTS_INT        0x20
 330#define ICR_ENAB_UNDERRUN_INT   0x40
 331#define ICR_ENAB_BREAK_INT      0x80
 332
 333
 334/* RR0: STATUS_REG "SR" */
 335
 336#define SR_CHAR_AVAIL           0x01
 337#define SR_BRG_ZERO             0x02
 338#define SR_TX_BUF_EMPTY         0x04
 339#define SR_DCD                  0x08
 340#define SR_SYNC_ABORT           0x10
 341#define SR_CTS                  0x20
 342#define SR_TX_UNDERRUN          0x40
 343#define SR_BREAK                0x80
 344
 345
 346/* RR1: SPCOND_STATUS_REG "SCSR" */
 347
 348#define SCSR_ALL_SENT           0x01
 349#define SCSR_RESIDUAL_MASK      0x0e
 350#define SCSR_PARITY_ERR         0x10
 351#define SCSR_RX_OVERRUN         0x20
 352#define SCSR_CRC_FRAME_ERR      0x40
 353#define SCSR_END_OF_FRAME       0x80
 354
 355
 356/* RR3: INT_PENDING_REG "IPR" */
 357
 358#define IPR_B_EXTSTAT           0x01
 359#define IPR_B_TX                0x02
 360#define IPR_B_RX                0x04
 361#define IPR_A_EXTSTAT           0x08
 362#define IPR_A_TX                0x10
 363#define IPR_A_RX                0x20
 364
 365
 366/* RR7: FS_FIFO_HIGH_REG "FFHR" */
 367
 368#define FFHR_CNT_MASK           0x3f
 369#define FFHR_IS_FROM_FIFO       0x40
 370#define FFHR_FIFO_OVERRUN       0x80
 371
 372
 373/* RR10: DPLL_STATUS_REG "DSR" */
 374
 375#define DSR_ON_LOOP             0x02
 376#define DSR_ON_LOOP_SENDING     0x10
 377#define DSR_TWO_CLK_MISSING     0x40
 378#define DSR_ONE_CLK_MISSING     0x80
 379
 380/***********************************************************************/
 381/*                                                                     */
 382/*                             Register Access                         */
 383/*                                                                     */
 384/***********************************************************************/
 385
 386
 387/* The SCC needs 3.5 PCLK cycles recovery time between to register
 388 * accesses. PCLK runs with 8 MHz on an Atari, so this delay is 3.5 *
 389 * 125 ns = 437.5 ns. This is too short for udelay().
 390 * 10/16/95: A tstb st_mfp.par_dt_reg takes 600ns (sure?) and thus should be
 391 * quite right
 392 */
 393
 394#define scc_reg_delay() \
 395    do {                        \
 396        if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147)     \
 397                __asm__ __volatile__ ( " nop; nop");                    \
 398        else if (MACH_IS_ATARI)                                         \
 399                __asm__ __volatile__ ( "tstb %0" : : "g" (*_scc_del) : "cc" );\
 400    } while (0)
 401
 402static unsigned char scc_shadow[2][16];
 403
 404/* The following functions should relax the somehow complicated
 405 * register access of the SCC. _SCCwrite() stores all written values
 406 * (except for WR0 and WR8) in shadow registers for later recall. This
 407 * removes the burden of remembering written values as needed. The
 408 * extra work of storing the value doesn't count, since a delay is
 409 * needed after a SCC access anyway. Additionally, _SCCwrite() manages
 410 * writes to WR0 and WR8 differently, because these can be accessed
 411 * directly with less overhead. Another special case are WR7 and WR7'.
 412 * _SCCwrite automatically checks what of this registers is selected
 413 * and changes b0 of WR15 if needed.
 414 * 
 415 * _SCCread() for standard read registers is straightforward, except
 416 * for RR2 (split into two "virtual" registers: one for the value
 417 * written to WR2 (from the shadow) and one for the vector including
 418 * status from RR2, Ch. B) and RR3. The latter must be read from
 419 * Channel A, because it reads as all zeros on Ch. B. RR0 and RR8 can
 420 * be accessed directly as before.
 421 * 
 422 * The two inline function contain complicated switch statements. But
 423 * I rely on regno and final_delay being constants, so gcc can reduce
 424 * the whole stuff to just some assembler statements.
 425 * 
 426 * _SCCwrite and _SCCread aren't intended to be used directly under
 427 * normal circumstances. The macros SCCread[_ND] and SCCwrite[_ND] are
 428 * for that purpose. They assume that a local variable 'port' is
 429 * declared and pointing to the port's scc_struct entry. The
 430 * variants with "_NB" appended should be used if no other SCC
 431 * accesses follow immediately (within 0.5 usecs). They just skip the
 432 * final delay nops.
 433 * 
 434 * Please note that accesses to SCC registers should only take place
 435 * when interrupts are turned off (at least if SCC interrupts are
 436 * enabled). Otherwise, an interrupt could interfere with the
 437 * two-stage accessing process.
 438 *
 439 */
 440
 441
 442static __inline__ void _SCCwrite(
 443        struct scc_port *port,
 444        unsigned char *shadow,
 445        volatile unsigned char *_scc_del,
 446        int regno,
 447        unsigned char val, int final_delay )
 448{
 449        switch( regno ) {
 450
 451          case COMMAND_REG:
 452                /* WR0 can be written directly without pointing */
 453                *port->ctrlp = val;
 454                break;
 455
 456          case SYNC_CHAR_REG:
 457                /* For WR7, first set b0 of WR15 to 0, if needed */
 458                if (shadow[INT_CTRL_REG] & ICR_OPTIONREG_SELECT) {
 459                        *port->ctrlp = 15;
 460                        shadow[INT_CTRL_REG] &= ~ICR_OPTIONREG_SELECT;
 461                        scc_reg_delay();
 462                        *port->ctrlp = shadow[INT_CTRL_REG];
 463                        scc_reg_delay();
 464                }
 465                goto normal_case;
 466                
 467          case SDLC_OPTION_REG:
 468                /* For WR7', first set b0 of WR15 to 1, if needed */
 469                if (!(shadow[INT_CTRL_REG] & ICR_OPTIONREG_SELECT)) {
 470                        *port->ctrlp = 15;
 471                        shadow[INT_CTRL_REG] |= ICR_OPTIONREG_SELECT;
 472                        scc_reg_delay();
 473                        *port->ctrlp = shadow[INT_CTRL_REG];
 474                        scc_reg_delay();
 475                }
 476                *port->ctrlp = 7;
 477                shadow[8] = val;        /* WR7' shadowed at WR8 */
 478                scc_reg_delay();
 479                *port->ctrlp = val;
 480                break;
 481
 482          case TX_DATA_REG:             /* WR8 */
 483                /* TX_DATA_REG can be accessed directly on some h/w */
 484                if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147)
 485                {
 486                        *port->ctrlp = regno;
 487                        scc_reg_delay();
 488                        *port->ctrlp = val;
 489                }
 490                else
 491                        *port->datap = val;
 492                break;
 493
 494          case MASTER_INT_CTRL:
 495                *port->ctrlp = regno;
 496                val &= 0x3f;    /* bits 6..7 are the reset commands */
 497                scc_shadow[0][regno] = val;
 498                scc_reg_delay();
 499                *port->ctrlp = val;
 500                break;
 501
 502          case DPLL_CTRL_REG:
 503                *port->ctrlp = regno;
 504                val &= 0x1f;                    /* bits 5..7 are the DPLL commands */
 505                shadow[regno] = val;
 506                scc_reg_delay();
 507                *port->ctrlp = val;
 508                break;
 509
 510          case 1 ... 6: 
 511          case 10 ... 13:
 512          case 15:
 513          normal_case:
 514                *port->ctrlp = regno;
 515                shadow[regno] = val;
 516                scc_reg_delay();
 517                *port->ctrlp = val;
 518                break;
 519                
 520          default:
 521                printk( "Bad SCC write access to WR%d\n", regno );
 522                break;
 523                
 524        }
 525
 526        if (final_delay)
 527                scc_reg_delay();
 528}
 529
 530
 531static __inline__ unsigned char _SCCread(
 532        struct scc_port *port,
 533        unsigned char *shadow,
 534        volatile unsigned char *_scc_del,
 535        int regno, int final_delay )
 536{
 537        unsigned char rv;
 538
 539        switch( regno ) {
 540
 541                /* --- real read registers --- */
 542          case STATUS_REG:
 543                rv = *port->ctrlp;
 544                break;
 545
 546          case INT_PENDING_REG:
 547                /* RR3: read only from Channel A! */
 548                port = port->port_a;
 549                goto normal_case;
 550
 551          case RX_DATA_REG:
 552                /* RR8 can be accessed directly on some h/w */
 553                if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147)
 554                {
 555                        *port->ctrlp = 8;
 556                        scc_reg_delay();
 557                        rv = *port->ctrlp;
 558                }
 559                else
 560                        rv = *port->datap;
 561                break;
 562
 563          case CURR_VECTOR_REG:
 564                /* RR2 (vector including status) from Ch. B */
 565                port = port->port_b;
 566                goto normal_case;
 567                
 568                /* --- reading write registers: access the shadow --- */
 569          case 1 ... 7:
 570          case 10 ... 15:
 571                return shadow[regno]; /* no final delay! */
 572
 573                /* WR7' is special, because it is shadowed at the place of WR8 */
 574          case SDLC_OPTION_REG:
 575                return shadow[8]; /* no final delay! */
 576
 577                /* WR9 is special too, because it is common for both channels */
 578          case MASTER_INT_CTRL:
 579                return scc_shadow[0][9]; /* no final delay! */
 580
 581          default:
 582                printk( "Bad SCC read access to %cR%d\n", (regno & 16) ? 'R' : 'W',
 583                                regno & ~16 );
 584                break;
 585                
 586          case SPCOND_STATUS_REG:
 587          case FS_FIFO_LOW_REG:
 588          case FS_FIFO_HIGH_REG:
 589          case DPLL_STATUS_REG:
 590          normal_case:
 591                *port->ctrlp = regno & 0x0f;
 592                scc_reg_delay();
 593                rv = *port->ctrlp;
 594                break;
 595                
 596        }
 597
 598        if (final_delay)
 599                scc_reg_delay();
 600        return rv;
 601}
 602
 603#define SCC_ACCESS_INIT(port)                                           \
 604        unsigned char *_scc_shadow = &scc_shadow[port->channel][0]
 605
 606#define SCCwrite(reg,val)       _SCCwrite(port,_scc_shadow,scc_del,(reg),(val),1)
 607#define SCCwrite_NB(reg,val)    _SCCwrite(port,_scc_shadow,scc_del,(reg),(val),0)
 608#define SCCread(reg)            _SCCread(port,_scc_shadow,scc_del,(reg),1)
 609#define SCCread_NB(reg)         _SCCread(port,_scc_shadow,scc_del,(reg),0)
 610
 611#define SCCmod(reg,and,or)      SCCwrite((reg),(SCCread(reg)&(and))|(or))
 612
 613#endif /* _SCC_H */
 614