root/arch/alpha/kernel/smc37c669.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. SMC37c669_detect
  2. SMC37c669_enable_device
  3. SMC37c669_disable_device
  4. SMC37c669_configure_device
  5. SMC37c669_is_device_enabled
  6. SMC37c669_get_device_config
  7. SMC37c669_display_device_info
  8. SMC37c669_config_mode
  9. SMC37c669_read_config
  10. SMC37c669_write_config
  11. SMC37c669_init_local_config
  12. SMC37c669_get_config
  13. SMC37c669_xlate_irq
  14. SMC37c669_xlate_drq
  15. smcc669_init
  16. smcc669_open
  17. smcc669_close
  18. smcc669_read
  19. smcc669_write
  20. SMC37c669_dump_registers
  21. SMC669_Init

   1 /*
   2  * SMC 37C669 initialization code
   3  */
   4 #include <linux/kernel.h>
   5 
   6 #include <linux/mm.h>
   7 #include <linux/init.h>
   8 #include <linux/delay.h>
   9 #include <linux/spinlock.h>
  10 
  11 #include <asm/hwrpb.h>
  12 #include <asm/io.h>
  13 
  14 #if 0
  15 # define DBG_DEVS(args)         printk args
  16 #else
  17 # define DBG_DEVS(args)
  18 #endif
  19 
  20 #define KB              1024
  21 #define MB              (1024*KB)
  22 #define GB              (1024*MB)
  23 
  24 #define SMC_DEBUG   0
  25 
  26 /* File:        smcc669_def.h
  27  *
  28  * Copyright (C) 1997 by
  29  * Digital Equipment Corporation, Maynard, Massachusetts.
  30  * All rights reserved.
  31  *
  32  * This software is furnished under a license and may be used and copied
  33  * only  in  accordance  of  the  terms  of  such  license  and with the
  34  * inclusion of the above copyright notice. This software or  any  other
  35  * copies thereof may not be provided or otherwise made available to any
  36  * other person.  No title to and  ownership of the  software is  hereby
  37  * transferred.
  38  *
  39  * The information in this software is  subject to change without notice
  40  * and  should  not  be  construed  as a commitment by Digital Equipment
  41  * Corporation.
  42  *
  43  * Digital assumes no responsibility for the use  or  reliability of its
  44  * software on equipment which is not supplied by Digital.
  45  *
  46  *
  47  * Abstract:    
  48  *
  49  *      This file contains header definitions for the SMC37c669 
  50  *      Super I/O controller. 
  51  *
  52  * Author:      
  53  *
  54  *      Eric Rasmussen
  55  *
  56  * Modification History:
  57  *
  58  *      er      28-Jan-1997     Initial Entry
  59  */
  60 
  61 #ifndef __SMC37c669_H
  62 #define __SMC37c669_H
  63 
  64 /*
  65 ** Macros for handling device IRQs
  66 **
  67 ** The mask acts as a flag used in mapping actual ISA IRQs (0 - 15) 
  68 ** to device IRQs (A - H).
  69 */
  70 #define SMC37c669_DEVICE_IRQ_MASK       0x80000000
  71 #define SMC37c669_DEVICE_IRQ( __i )     \
  72         ((SMC37c669_DEVICE_IRQ_MASK) | (__i))
  73 #define SMC37c669_IS_DEVICE_IRQ(__i)    \
  74         (((__i) & (SMC37c669_DEVICE_IRQ_MASK)) == (SMC37c669_DEVICE_IRQ_MASK))
  75 #define SMC37c669_RAW_DEVICE_IRQ(__i)   \
  76         ((__i) & ~(SMC37c669_DEVICE_IRQ_MASK))
  77 
  78 /*
  79 ** Macros for handling device DRQs
  80 **
  81 ** The mask acts as a flag used in mapping actual ISA DMA
  82 ** channels to device DMA channels (A - C).
  83 */
  84 #define SMC37c669_DEVICE_DRQ_MASK       0x80000000
  85 #define SMC37c669_DEVICE_DRQ(__d)       \
  86         ((SMC37c669_DEVICE_DRQ_MASK) | (__d))
  87 #define SMC37c669_IS_DEVICE_DRQ(__d)    \
  88         (((__d) & (SMC37c669_DEVICE_DRQ_MASK)) == (SMC37c669_DEVICE_DRQ_MASK))
  89 #define SMC37c669_RAW_DEVICE_DRQ(__d)   \
  90         ((__d) & ~(SMC37c669_DEVICE_DRQ_MASK))
  91 
  92 #define SMC37c669_DEVICE_ID     0x3
  93 
  94 /*
  95 ** SMC37c669 Device Function Definitions
  96 */
  97 #define SERIAL_0        0
  98 #define SERIAL_1        1
  99 #define PARALLEL_0      2
 100 #define FLOPPY_0        3
 101 #define IDE_0           4
 102 #define NUM_FUNCS       5
 103 
 104 /*
 105 ** Default Device Function Mappings
 106 */
 107 #define COM1_BASE       0x3F8
 108 #define COM1_IRQ        4
 109 #define COM2_BASE       0x2F8
 110 #define COM2_IRQ        3
 111 #define PARP_BASE       0x3BC
 112 #define PARP_IRQ        7
 113 #define PARP_DRQ        3
 114 #define FDC_BASE        0x3F0
 115 #define FDC_IRQ         6
 116 #define FDC_DRQ         2
 117 
 118 /*
 119 ** Configuration On/Off Key Definitions
 120 */
 121 #define SMC37c669_CONFIG_ON_KEY         0x55
 122 #define SMC37c669_CONFIG_OFF_KEY        0xAA
 123 
 124 /*
 125 ** SMC 37c669 Device IRQs
 126 */
 127 #define SMC37c669_DEVICE_IRQ_A      ( SMC37c669_DEVICE_IRQ( 0x01 ) )
 128 #define SMC37c669_DEVICE_IRQ_B      ( SMC37c669_DEVICE_IRQ( 0x02 ) )
 129 #define SMC37c669_DEVICE_IRQ_C      ( SMC37c669_DEVICE_IRQ( 0x03 ) )
 130 #define SMC37c669_DEVICE_IRQ_D      ( SMC37c669_DEVICE_IRQ( 0x04 ) )
 131 #define SMC37c669_DEVICE_IRQ_E      ( SMC37c669_DEVICE_IRQ( 0x05 ) )
 132 #define SMC37c669_DEVICE_IRQ_F      ( SMC37c669_DEVICE_IRQ( 0x06 ) )
 133 /*      SMC37c669_DEVICE_IRQ_G      *** RESERVED ***/
 134 #define SMC37c669_DEVICE_IRQ_H      ( SMC37c669_DEVICE_IRQ( 0x08 ) )
 135 
 136 /*
 137 ** SMC 37c669 Device DMA Channel Definitions
 138 */
 139 #define SMC37c669_DEVICE_DRQ_A              ( SMC37c669_DEVICE_DRQ( 0x01 ) )
 140 #define SMC37c669_DEVICE_DRQ_B              ( SMC37c669_DEVICE_DRQ( 0x02 ) )
 141 #define SMC37c669_DEVICE_DRQ_C              ( SMC37c669_DEVICE_DRQ( 0x03 ) )
 142 
 143 /*
 144 ** Configuration Register Index Definitions
 145 */
 146 #define SMC37c669_CR00_INDEX        0x00
 147 #define SMC37c669_CR01_INDEX        0x01
 148 #define SMC37c669_CR02_INDEX        0x02
 149 #define SMC37c669_CR03_INDEX        0x03
 150 #define SMC37c669_CR04_INDEX        0x04
 151 #define SMC37c669_CR05_INDEX        0x05
 152 #define SMC37c669_CR06_INDEX        0x06
 153 #define SMC37c669_CR07_INDEX        0x07
 154 #define SMC37c669_CR08_INDEX        0x08
 155 #define SMC37c669_CR09_INDEX        0x09
 156 #define SMC37c669_CR0A_INDEX        0x0A
 157 #define SMC37c669_CR0B_INDEX        0x0B
 158 #define SMC37c669_CR0C_INDEX        0x0C
 159 #define SMC37c669_CR0D_INDEX        0x0D
 160 #define SMC37c669_CR0E_INDEX        0x0E
 161 #define SMC37c669_CR0F_INDEX        0x0F
 162 #define SMC37c669_CR10_INDEX        0x10
 163 #define SMC37c669_CR11_INDEX        0x11
 164 #define SMC37c669_CR12_INDEX        0x12
 165 #define SMC37c669_CR13_INDEX        0x13
 166 #define SMC37c669_CR14_INDEX        0x14
 167 #define SMC37c669_CR15_INDEX        0x15
 168 #define SMC37c669_CR16_INDEX        0x16
 169 #define SMC37c669_CR17_INDEX        0x17
 170 #define SMC37c669_CR18_INDEX        0x18
 171 #define SMC37c669_CR19_INDEX        0x19
 172 #define SMC37c669_CR1A_INDEX        0x1A
 173 #define SMC37c669_CR1B_INDEX        0x1B
 174 #define SMC37c669_CR1C_INDEX        0x1C
 175 #define SMC37c669_CR1D_INDEX        0x1D
 176 #define SMC37c669_CR1E_INDEX        0x1E
 177 #define SMC37c669_CR1F_INDEX        0x1F
 178 #define SMC37c669_CR20_INDEX        0x20
 179 #define SMC37c669_CR21_INDEX        0x21
 180 #define SMC37c669_CR22_INDEX        0x22
 181 #define SMC37c669_CR23_INDEX        0x23
 182 #define SMC37c669_CR24_INDEX        0x24
 183 #define SMC37c669_CR25_INDEX        0x25
 184 #define SMC37c669_CR26_INDEX        0x26
 185 #define SMC37c669_CR27_INDEX        0x27
 186 #define SMC37c669_CR28_INDEX        0x28
 187 #define SMC37c669_CR29_INDEX        0x29
 188 
 189 /*
 190 ** Configuration Register Alias Definitions
 191 */
 192 #define SMC37c669_DEVICE_ID_INDEX                   SMC37c669_CR0D_INDEX
 193 #define SMC37c669_DEVICE_REVISION_INDEX             SMC37c669_CR0E_INDEX
 194 #define SMC37c669_FDC_BASE_ADDRESS_INDEX            SMC37c669_CR20_INDEX
 195 #define SMC37c669_IDE_BASE_ADDRESS_INDEX            SMC37c669_CR21_INDEX
 196 #define SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX       SMC37c669_CR22_INDEX
 197 #define SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX      SMC37c669_CR23_INDEX
 198 #define SMC37c669_SERIAL0_BASE_ADDRESS_INDEX        SMC37c669_CR24_INDEX
 199 #define SMC37c669_SERIAL1_BASE_ADDRESS_INDEX        SMC37c669_CR25_INDEX
 200 #define SMC37c669_PARALLEL_FDC_DRQ_INDEX            SMC37c669_CR26_INDEX
 201 #define SMC37c669_PARALLEL_FDC_IRQ_INDEX            SMC37c669_CR27_INDEX
 202 #define SMC37c669_SERIAL_IRQ_INDEX                  SMC37c669_CR28_INDEX
 203 
 204 /*
 205 ** Configuration Register Definitions
 206 **
 207 ** The INDEX (write only) and DATA (read/write) ports are effective 
 208 ** only when the chip is in the Configuration State.
 209 */
 210 typedef struct _SMC37c669_CONFIG_REGS {
 211     unsigned char index_port;
 212     unsigned char data_port;
 213 } SMC37c669_CONFIG_REGS;
 214 
 215 /*
 216 ** CR00 - default value 0x28
 217 **
 218 **  IDE_EN (CR00<1:0>):
 219 **      0x - 30ua pull-ups on nIDEEN, nHDCS0, NHDCS1
 220 **      11 - IRQ_H available as IRQ output,
 221 **           IRRX2, IRTX2 available as alternate IR pins
 222 **      10 - nIDEEN, nHDCS0, nHDCS1 used to control IDE
 223 **
 224 **  VALID (CR00<7>):
 225 **      A high level on this software controlled bit can
 226 **      be used to indicate that a valid configuration
 227 **      cycle has occurred.  The control software must
 228 **      take care to set this bit at the appropriate times.
 229 **      Set to zero after power up.  This bit has no
 230 **      effect on any other hardware in the chip.
 231 **
 232 */
 233 typedef union _SMC37c669_CR00 {
 234     unsigned char as_uchar;
 235     struct {
 236         unsigned ide_en : 2;        /* See note above           */
 237         unsigned reserved1 : 1;     /* RAZ                      */
 238         unsigned fdc_pwr : 1;       /* 1 = supply power to FDC  */
 239         unsigned reserved2 : 3;     /* Read as 010b             */
 240         unsigned valid : 1;         /* See note above           */
 241     }   by_field;
 242 } SMC37c669_CR00;
 243 
 244 /*
 245 ** CR01 - default value 0x9C
 246 */
 247 typedef union _SMC37c669_CR01 {
 248     unsigned char as_uchar;
 249     struct {
 250         unsigned reserved1 : 2;     /* RAZ                          */
 251         unsigned ppt_pwr : 1;       /* 1 = supply power to PPT      */
 252         unsigned ppt_mode : 1;      /* 1 = Printer mode, 0 = EPP    */
 253         unsigned reserved2 : 1;     /* Read as 1                    */
 254         unsigned reserved3 : 2;     /* RAZ                          */
 255         unsigned lock_crx: 1;       /* Lock CR00 - CR18             */
 256     }   by_field;
 257 } SMC37c669_CR01;
 258 
 259 /*
 260 ** CR02 - default value 0x88
 261 */
 262 typedef union _SMC37c669_CR02 {
 263     unsigned char as_uchar;
 264     struct {
 265         unsigned reserved1 : 3;     /* RAZ                          */
 266         unsigned uart1_pwr : 1;     /* 1 = supply power to UART1    */
 267         unsigned reserved2 : 3;     /* RAZ                          */
 268         unsigned uart2_pwr : 1;     /* 1 = supply power to UART2    */
 269     }   by_field;
 270 } SMC37c669_CR02;
 271 
 272 /*
 273 ** CR03 - default value 0x78
 274 **
 275 **  CR03<7>     CR03<2>     Pin 94
 276 **  -------     -------     ------
 277 **     0           X        DRV2 (input)
 278 **     1           0        ADRX
 279 **     1           1        IRQ_B
 280 **
 281 **  CR03<6>     CR03<5>     Op Mode
 282 **  -------     -------     -------
 283 **     0           0        Model 30
 284 **     0           1        PS/2
 285 **     1           0        Reserved
 286 **     1           1        AT Mode
 287 */
 288 typedef union _SMC37c669_CR03 {
 289     unsigned char as_uchar;
 290     struct {
 291         unsigned pwrgd_gamecs : 1;  /* 1 = PWRGD, 0 = GAMECS        */
 292         unsigned fdc_mode2 : 1;     /* 1 = Enhanced Mode 2          */
 293         unsigned pin94_0 : 1;       /* See note above               */
 294         unsigned reserved1 : 1;     /* RAZ                          */
 295         unsigned drvden : 1;        /* 1 = high, 0 - output         */
 296         unsigned op_mode : 2;       /* See note above               */
 297         unsigned pin94_1 : 1;       /* See note above               */
 298     }   by_field;
 299 } SMC37c669_CR03;
 300 
 301 /*
 302 ** CR04 - default value 0x00
 303 **
 304 **  PP_EXT_MODE:
 305 **      If CR01<PP_MODE> = 0 and PP_EXT_MODE =
 306 **          00 - Standard and Bidirectional
 307 **          01 - EPP mode and SPP
 308 **          10 - ECP mode
 309 **               In this mode, 2 drives can be supported
 310 **               directly, 3 or 4 drives must use external
 311 **               4 drive support.  SPP can be selected
 312 **               through the ECR register of ECP as mode 000.
 313 **          11 - ECP mode and EPP mode
 314 **               In this mode, 2 drives can be supported
 315 **               directly, 3 or 4 drives must use external
 316 **               4 drive support.  SPP can be selected
 317 **               through the ECR register of ECP as mode 000.
 318 **               In this mode, EPP can be selected through
 319 **               the ECR register of ECP as mode 100.
 320 **
 321 **  PP_FDC:
 322 **      00 - Normal
 323 **      01 - PPFD1
 324 **      10 - PPFD2
 325 **      11 - Reserved
 326 **
 327 **  MIDI1:
 328 **      Serial Clock Select: 
 329 **          A low level on this bit disables MIDI support,
 330 **          clock = divide by 13.  A high level on this 
 331 **          bit enables MIDI support, clock = divide by 12.
 332 **
 333 **      MIDI operates at 31.25 Kbps which can be derived 
 334 **      from 125 KHz (24 MHz / 12 = 2 MHz, 2 MHz / 16 = 125 KHz)
 335 **
 336 **  ALT_IO:
 337 **      0 - Use pins IRRX, IRTX
 338 **      1 - Use pins IRRX2, IRTX2
 339 **
 340 **      If this bit is set, the IR receive and transmit
 341 **      functions will not be available on pins 25 and 26
 342 **      unless CR00<IDE_EN> = 11.
 343 */
 344 typedef union _SMC37c669_CR04 {
 345     unsigned char as_uchar;
 346     struct {
 347         unsigned ppt_ext_mode : 2;  /* See note above               */
 348         unsigned ppt_fdc : 2;       /* See note above               */
 349         unsigned midi1 : 1;         /* See note above               */
 350         unsigned midi2 : 1;         /* See note above               */
 351         unsigned epp_type : 1;      /* 0 = EPP 1.9, 1 = EPP 1.7     */
 352         unsigned alt_io : 1;        /* See note above               */
 353     }   by_field;
 354 } SMC37c669_CR04;
 355 
 356 /*
 357 ** CR05 - default value 0x00
 358 **
 359 **  DEN_SEL:
 360 **      00 - Densel output normal
 361 **      01 - Reserved
 362 **      10 - Densel output 1
 363 **      11 - Densel output 0
 364 **
 365 */
 366 typedef union _SMC37c669_CR05 {
 367     unsigned char as_uchar;
 368     struct {
 369         unsigned reserved1 : 2;     /* RAZ                                      */
 370         unsigned fdc_dma_mode : 1;  /* 0 = burst, 1 = non-burst                 */
 371         unsigned den_sel : 2;       /* See note above                           */
 372         unsigned swap_drv : 1;      /* Swap the FDC motor selects               */
 373         unsigned extx4 : 1;         /* 0 = 2 drive, 1 = external 4 drive decode */
 374         unsigned reserved2 : 1;     /* RAZ                                      */
 375     }   by_field;
 376 } SMC37c669_CR05;
 377 
 378 /*
 379 ** CR06 - default value 0xFF
 380 */
 381 typedef union _SMC37c669_CR06 {
 382     unsigned char as_uchar;
 383     struct {
 384         unsigned floppy_a : 2;      /* Type of floppy drive A       */
 385         unsigned floppy_b : 2;      /* Type of floppy drive B       */
 386         unsigned floppy_c : 2;      /* Type of floppy drive C       */
 387         unsigned floppy_d : 2;      /* Type of floppy drive D       */
 388     }   by_field;
 389 } SMC37c669_CR06;
 390 
 391 /*
 392 ** CR07 - default value 0x00
 393 **
 394 **  Auto Power Management CR07<7:4>:
 395 **      0 - Auto Powerdown disabled (default)
 396 **      1 - Auto Powerdown enabled
 397 **
 398 **      This bit is reset to the default state by POR or
 399 **      a hardware reset.
 400 **
 401 */
 402 typedef union _SMC37c669_CR07 {
 403     unsigned char as_uchar;
 404     struct {
 405         unsigned floppy_boot : 2;   /* 0 = A:, 1 = B:               */
 406         unsigned reserved1 : 2;     /* RAZ                          */
 407         unsigned ppt_en : 1;        /* See note above               */
 408         unsigned uart1_en : 1;      /* See note above               */
 409         unsigned uart2_en : 1;      /* See note above               */
 410         unsigned fdc_en : 1;        /* See note above               */
 411     }   by_field;
 412 } SMC37c669_CR07;
 413 
 414 /*
 415 ** CR08 - default value 0x00
 416 */
 417 typedef union _SMC37c669_CR08 {
 418     unsigned char as_uchar;
 419     struct {
 420         unsigned zero : 4;          /* 0                            */
 421         unsigned addrx7_4 : 4;      /* ADR<7:3> for ADRx decode     */
 422     }   by_field;
 423 } SMC37c669_CR08;
 424 
 425 /*
 426 ** CR09 - default value 0x00
 427 **
 428 **  ADRx_CONFIG:
 429 **      00 - ADRx disabled
 430 **      01 - 1 byte decode A<3:0> = 0000b
 431 **      10 - 8 byte block decode A<3:0> = 0XXXb
 432 **      11 - 16 byte block decode A<3:0> = XXXXb
 433 **
 434 */
 435 typedef union _SMC37c669_CR09 {
 436     unsigned char as_uchar;
 437     struct {
 438         unsigned adra8 : 3;         /* ADR<10:8> for ADRx decode    */
 439         unsigned reserved1 : 3;
 440         unsigned adrx_config : 2;   /* See note above               */
 441     }   by_field;
 442 } SMC37c669_CR09;
 443 
 444 /*
 445 ** CR0A - default value 0x00
 446 */
 447 typedef union _SMC37c669_CR0A {
 448     unsigned char as_uchar;
 449     struct {
 450         unsigned ecp_fifo_threshold : 4;
 451         unsigned reserved1 : 4;
 452     }   by_field;
 453 } SMC37c669_CR0A;
 454 
 455 /*
 456 ** CR0B - default value 0x00
 457 */
 458 typedef union _SMC37c669_CR0B {
 459     unsigned char as_uchar;
 460     struct {
 461         unsigned fdd0_drtx : 2;     /* FDD0 Data Rate Table         */
 462         unsigned fdd1_drtx : 2;     /* FDD1 Data Rate Table         */
 463         unsigned fdd2_drtx : 2;     /* FDD2 Data Rate Table         */
 464         unsigned fdd3_drtx : 2;     /* FDD3 Data Rate Table         */
 465     }   by_field;
 466 } SMC37c669_CR0B;
 467 
 468 /*
 469 ** CR0C - default value 0x00
 470 **
 471 **  UART2_MODE:
 472 **      000 - Standard (default)
 473 **      001 - IrDA (HPSIR)
 474 **      010 - Amplitude Shift Keyed IR @500 KHz
 475 **      011 - Reserved
 476 **      1xx - Reserved
 477 **
 478 */
 479 typedef union _SMC37c669_CR0C {
 480     unsigned char as_uchar;
 481     struct {
 482         unsigned uart2_rcv_polarity : 1;    /* 1 = invert RX            */
 483         unsigned uart2_xmit_polarity : 1;   /* 1 = invert TX            */
 484         unsigned uart2_duplex : 1;          /* 1 = full, 0 = half       */
 485         unsigned uart2_mode : 3;            /* See note above           */
 486         unsigned uart1_speed : 1;           /* 1 = high speed enabled   */
 487         unsigned uart2_speed : 1;           /* 1 = high speed enabled   */
 488     }   by_field;
 489 } SMC37c669_CR0C;
 490 
 491 /*
 492 ** CR0D - default value 0x03
 493 **
 494 **  Device ID Register - read only
 495 */
 496 typedef union _SMC37c669_CR0D {
 497     unsigned char as_uchar;
 498     struct {
 499         unsigned device_id : 8;     /* Returns 0x3 in this field    */
 500     }   by_field;
 501 } SMC37c669_CR0D;
 502 
 503 /*
 504 ** CR0E - default value 0x02
 505 **
 506 **  Device Revision Register - read only
 507 */
 508 typedef union _SMC37c669_CR0E {
 509     unsigned char as_uchar;
 510     struct {
 511         unsigned device_rev : 8;    /* Returns 0x2 in this field    */
 512     }   by_field;
 513 } SMC37c669_CR0E;
 514 
 515 /*
 516 ** CR0F - default value 0x00
 517 */
 518 typedef union _SMC37c669_CR0F {
 519     unsigned char as_uchar;
 520     struct {
 521         unsigned test0 : 1;         /* Reserved - set to 0          */
 522         unsigned test1 : 1;         /* Reserved - set to 0          */
 523         unsigned test2 : 1;         /* Reserved - set to 0          */
 524         unsigned test3 : 1;         /* Reserved - set t0 0          */
 525         unsigned test4 : 1;         /* Reserved - set to 0          */
 526         unsigned test5 : 1;         /* Reserved - set t0 0          */
 527         unsigned test6 : 1;         /* Reserved - set t0 0          */
 528         unsigned test7 : 1;         /* Reserved - set to 0          */
 529     }   by_field;
 530 } SMC37c669_CR0F;
 531 
 532 /*
 533 ** CR10 - default value 0x00
 534 */
 535 typedef union _SMC37c669_CR10 {
 536     unsigned char as_uchar;
 537     struct {
 538         unsigned reserved1 : 3;      /* RAZ                         */
 539         unsigned pll_gain : 1;       /* 1 = 3V, 2 = 5V operation    */
 540         unsigned pll_stop : 1;       /* 1 = stop PLLs               */
 541         unsigned ace_stop : 1;       /* 1 = stop UART clocks        */
 542         unsigned pll_clock_ctrl : 1; /* 0 = 14.318 MHz, 1 = 24 MHz  */
 543         unsigned ir_test : 1;        /* Enable IR test mode         */
 544     }   by_field;
 545 } SMC37c669_CR10;
 546 
 547 /*
 548 ** CR11 - default value 0x00
 549 */
 550 typedef union _SMC37c669_CR11 {
 551     unsigned char as_uchar;
 552     struct {
 553         unsigned ir_loopback : 1;   /* Internal IR loop back                */
 554         unsigned test_10ms : 1;     /* Test 10ms autopowerdown FDC timeout  */
 555         unsigned reserved1 : 6;     /* RAZ                                  */
 556     }   by_field;
 557 } SMC37c669_CR11;
 558 
 559 /*
 560 ** CR12 - CR1D are reserved registers
 561 */
 562 
 563 /*
 564 ** CR1E - default value 0x80
 565 **
 566 **  GAMECS:
 567 **      00 - GAMECS disabled
 568 **      01 - 1 byte decode ADR<3:0> = 0001b
 569 **      10 - 8 byte block decode ADR<3:0> = 0XXXb
 570 **      11 - 16 byte block decode ADR<3:0> = XXXXb
 571 **
 572 */
 573 typedef union _SMC37c66_CR1E {
 574     unsigned char as_uchar;
 575     struct {
 576         unsigned gamecs_config: 2;   /* See note above              */
 577         unsigned gamecs_addr9_4 : 6; /* GAMECS Addr<9:4>            */
 578     }   by_field;
 579 } SMC37c669_CR1E;
 580 
 581 /*
 582 ** CR1F - default value 0x00
 583 **
 584 **  DT0 DT1 DRVDEN0 DRVDEN1 Drive Type
 585 **  --- --- ------- ------- ----------
 586 **   0   0  DENSEL  DRATE0  4/2/1 MB 3.5"
 587 **                          2/1 MB 5.25"
 588 **                          2/1.6/1 MB 3.5" (3-mode)
 589 **   0   1  DRATE1  DRATE0
 590 **   1   0  nDENSEL DRATE0  PS/2
 591 **   1   1  DRATE0  DRATE1
 592 **
 593 **  Note: DENSEL, DRATE1, and DRATE0 map onto two output
 594 **        pins - DRVDEN0 and DRVDEN1.
 595 **
 596 */
 597 typedef union _SMC37c669_CR1F {
 598     unsigned char as_uchar;
 599     struct {
 600         unsigned fdd0_drive_type : 2;   /* FDD0 drive type          */
 601         unsigned fdd1_drive_type : 2;   /* FDD1 drive type          */
 602         unsigned fdd2_drive_type : 2;   /* FDD2 drive type          */
 603         unsigned fdd3_drive_type : 2;   /* FDD3 drive type          */
 604     }   by_field;
 605 } SMC37c669_CR1F;
 606 
 607 /*
 608 ** CR20 - default value 0x3C
 609 **
 610 **  FDC Base Address Register
 611 **      - To disable this decode set Addr<9:8> = 0
 612 **      - A<10> = 0, A<3:0> = 0XXXb to access.
 613 **
 614 */
 615 typedef union _SMC37c669_CR20 {
 616     unsigned char as_uchar;
 617     struct {
 618         unsigned zero : 2;          /* 0                            */
 619         unsigned addr9_4 : 6;       /* FDC Addr<9:4>                */
 620     }   by_field;
 621 } SMC37c669_CR20;
 622 
 623 /*
 624 ** CR21 - default value 0x3C
 625 **
 626 **  IDE Base Address Register
 627 **      - To disable this decode set Addr<9:8> = 0
 628 **      - A<10> = 0, A<3:0> = 0XXXb to access.
 629 **
 630 */
 631 typedef union _SMC37c669_CR21 {
 632     unsigned char as_uchar;
 633     struct {
 634         unsigned zero : 2;          /* 0                            */
 635         unsigned addr9_4 : 6;       /* IDE Addr<9:4>                */
 636     }   by_field;
 637 } SMC37c669_CR21;
 638 
 639 /*
 640 ** CR22 - default value 0x3D
 641 **
 642 **  IDE Alternate Status Base Address Register
 643 **      - To disable this decode set Addr<9:8> = 0
 644 **      - A<10> = 0, A<3:0> = 0110b to access.
 645 **
 646 */
 647 typedef union _SMC37c669_CR22 {
 648     unsigned char as_uchar;
 649     struct {
 650         unsigned zero : 2;          /* 0                            */
 651         unsigned addr9_4 : 6;       /* IDE Alt Status Addr<9:4>     */
 652     }   by_field;
 653 } SMC37c669_CR22;
 654 
 655 /*
 656 ** CR23 - default value 0x00
 657 **
 658 **  Parallel Port Base Address Register
 659 **      - To disable this decode set Addr<9:8> = 0
 660 **      - A<10> = 0 to access.
 661 **      - If EPP is enabled, A<2:0> = XXXb to access.
 662 **        If EPP is NOT enabled, A<1:0> = XXb to access
 663 **
 664 */
 665 typedef union _SMC37c669_CR23 {
 666     unsigned char as_uchar;
 667     struct {
 668         unsigned addr9_2 : 8;       /* Parallel Port Addr<9:2>      */
 669     }   by_field;
 670 } SMC37c669_CR23;
 671 
 672 /*
 673 ** CR24 - default value 0x00
 674 **
 675 **  UART1 Base Address Register
 676 **      - To disable this decode set Addr<9:8> = 0
 677 **      - A<10> = 0, A<2:0> = XXXb to access.
 678 **
 679 */
 680 typedef union _SMC37c669_CR24 {
 681     unsigned char as_uchar;
 682     struct {
 683         unsigned zero : 1;          /* 0                            */
 684         unsigned addr9_3 : 7;       /* UART1 Addr<9:3>              */
 685     }   by_field;
 686 } SMC37c669_CR24;
 687 
 688 /*
 689 ** CR25 - default value 0x00
 690 **
 691 **  UART2 Base Address Register
 692 **      - To disable this decode set Addr<9:8> = 0
 693 **      - A<10> = 0, A<2:0> = XXXb to access.
 694 **
 695 */
 696 typedef union _SMC37c669_CR25 {
 697     unsigned char as_uchar;
 698     struct {
 699         unsigned zero : 1;          /* 0                            */
 700         unsigned addr9_3 : 7;       /* UART2 Addr<9:3>              */
 701     }   by_field;
 702 } SMC37c669_CR25;
 703 
 704 /*
 705 ** CR26 - default value 0x00
 706 **
 707 **  Parallel Port / FDC DMA Select Register
 708 **
 709 **  D3 - D0       DMA
 710 **  D7 - D4     Selected
 711 **  -------     --------
 712 **   0000        None
 713 **   0001        DMA_A
 714 **   0010        DMA_B
 715 **   0011        DMA_C
 716 **
 717 */
 718 typedef union _SMC37c669_CR26 {
 719     unsigned char as_uchar;
 720     struct {
 721         unsigned ppt_drq : 4;       /* See note above               */
 722         unsigned fdc_drq : 4;       /* See note above               */
 723     }   by_field;
 724 } SMC37c669_CR26;
 725 
 726 /*
 727 ** CR27 - default value 0x00
 728 **
 729 **  Parallel Port / FDC IRQ Select Register
 730 **
 731 **  D3 - D0       IRQ
 732 **  D7 - D4     Selected
 733 **  -------     --------
 734 **   0000        None
 735 **   0001        IRQ_A
 736 **   0010        IRQ_B
 737 **   0011        IRQ_C
 738 **   0100        IRQ_D
 739 **   0101        IRQ_E
 740 **   0110        IRQ_F
 741 **   0111        Reserved
 742 **   1000        IRQ_H
 743 **
 744 **  Any unselected IRQ REQ is in tristate
 745 **
 746 */
 747 typedef union _SMC37c669_CR27 {
 748     unsigned char as_uchar;
 749     struct {
 750         unsigned ppt_irq : 4;       /* See note above               */
 751         unsigned fdc_irq : 4;       /* See note above               */
 752     }   by_field;
 753 } SMC37c669_CR27;
 754 
 755 /*
 756 ** CR28 - default value 0x00
 757 **
 758 **  UART IRQ Select Register
 759 **
 760 **  D3 - D0       IRQ
 761 **  D7 - D4     Selected
 762 **  -------     --------
 763 **   0000        None
 764 **   0001        IRQ_A
 765 **   0010        IRQ_B
 766 **   0011        IRQ_C
 767 **   0100        IRQ_D
 768 **   0101        IRQ_E
 769 **   0110        IRQ_F
 770 **   0111        Reserved
 771 **   1000        IRQ_H
 772 **   1111        share with UART1 (only for UART2)
 773 **
 774 **  Any unselected IRQ REQ is in tristate
 775 **
 776 **  To share an IRQ between UART1 and UART2, set
 777 **  UART1 to use the desired IRQ and set UART2 to
 778 **  0xF to enable sharing mechanism.
 779 **
 780 */
 781 typedef union _SMC37c669_CR28 {
 782     unsigned char as_uchar;
 783     struct {
 784         unsigned uart2_irq : 4;     /* See note above               */
 785         unsigned uart1_irq : 4;     /* See note above               */
 786     }   by_field;
 787 } SMC37c669_CR28;
 788 
 789 /*
 790 ** CR29 - default value 0x00
 791 **
 792 **  IRQIN IRQ Select Register
 793 **
 794 **  D3 - D0       IRQ
 795 **  D7 - D4     Selected
 796 **  -------     --------
 797 **   0000        None
 798 **   0001        IRQ_A
 799 **   0010        IRQ_B
 800 **   0011        IRQ_C
 801 **   0100        IRQ_D
 802 **   0101        IRQ_E
 803 **   0110        IRQ_F
 804 **   0111        Reserved
 805 **   1000        IRQ_H
 806 **
 807 **  Any unselected IRQ REQ is in tristate
 808 **
 809 */
 810 typedef union _SMC37c669_CR29 {
 811     unsigned char as_uchar;
 812     struct {
 813         unsigned irqin_irq : 4;     /* See note above               */
 814         unsigned reserved1 : 4;     /* RAZ                          */
 815     }   by_field;
 816 } SMC37c669_CR29;
 817 
 818 /*
 819 ** Aliases of Configuration Register formats (should match
 820 ** the set of index aliases).
 821 **
 822 ** Note that CR24 and CR25 have the same format and are the
 823 ** base address registers for UART1 and UART2.  Because of
 824 ** this we only define 1 alias here - for CR24 - as the serial
 825 ** base address register.
 826 **
 827 ** Note that CR21 and CR22 have the same format and are the
 828 ** base address and alternate status address registers for
 829 ** the IDE controller.  Because of this we only define 1 alias
 830 ** here - for CR21 - as the IDE address register.
 831 **
 832 */
 833 typedef SMC37c669_CR0D SMC37c669_DEVICE_ID_REGISTER;
 834 typedef SMC37c669_CR0E SMC37c669_DEVICE_REVISION_REGISTER;
 835 typedef SMC37c669_CR20 SMC37c669_FDC_BASE_ADDRESS_REGISTER;
 836 typedef SMC37c669_CR21 SMC37c669_IDE_ADDRESS_REGISTER;
 837 typedef SMC37c669_CR23 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER;
 838 typedef SMC37c669_CR24 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER;
 839 typedef SMC37c669_CR26 SMC37c669_PARALLEL_FDC_DRQ_REGISTER;
 840 typedef SMC37c669_CR27 SMC37c669_PARALLEL_FDC_IRQ_REGISTER;
 841 typedef SMC37c669_CR28 SMC37c669_SERIAL_IRQ_REGISTER;
 842 
 843 /*
 844 ** ISA/Device IRQ Translation Table Entry Definition
 845 */
 846 typedef struct _SMC37c669_IRQ_TRANSLATION_ENTRY {
 847     int device_irq;
 848     int isa_irq;
 849 } SMC37c669_IRQ_TRANSLATION_ENTRY;
 850 
 851 /*
 852 ** ISA/Device DMA Translation Table Entry Definition
 853 */
 854 typedef struct _SMC37c669_DRQ_TRANSLATION_ENTRY {
 855     int device_drq;
 856     int isa_drq;
 857 } SMC37c669_DRQ_TRANSLATION_ENTRY;
 858 
 859 /*
 860 ** External Interface Function Prototype Declarations
 861 */
 862 
 863 SMC37c669_CONFIG_REGS *SMC37c669_detect( 
 864     int
 865 );
 866 
 867 unsigned int SMC37c669_enable_device( 
 868     unsigned int func 
 869 );
 870 
 871 unsigned int SMC37c669_disable_device( 
 872     unsigned int func 
 873 );
 874 
 875 unsigned int SMC37c669_configure_device( 
 876     unsigned int func, 
 877     int port, 
 878     int irq, 
 879     int drq 
 880 );
 881 
 882 void SMC37c669_display_device_info( 
 883     void 
 884 );
 885 
 886 #endif  /* __SMC37c669_H */
 887 
 888 /* file:        smcc669.c
 889  *
 890  * Copyright (C) 1997 by
 891  * Digital Equipment Corporation, Maynard, Massachusetts.
 892  * All rights reserved.
 893  *
 894  * This software is furnished under a license and may be used and copied
 895  * only  in  accordance  of  the  terms  of  such  license  and with the
 896  * inclusion of the above copyright notice. This software or  any  other
 897  * copies thereof may not be provided or otherwise made available to any
 898  * other person.  No title to and  ownership of the  software is  hereby
 899  * transferred.
 900  *
 901  * The information in this software is  subject to change without notice
 902  * and  should  not  be  construed  as a commitment by digital equipment
 903  * corporation.
 904  *
 905  * Digital assumes no responsibility for the use  or  reliability of its
 906  * software on equipment which is not supplied by digital.
 907  */
 908 
 909 /*
 910  *++
 911  *  FACILITY:
 912  *
 913  *      Alpha SRM Console Firmware
 914  *
 915  *  MODULE DESCRIPTION:
 916  *
 917  *      SMC37c669 Super I/O controller configuration routines.
 918  *
 919  *  AUTHORS:
 920  *
 921  *      Eric Rasmussen
 922  *
 923  *  CREATION DATE:
 924  *  
 925  *      28-Jan-1997
 926  *
 927  *  MODIFICATION HISTORY:
 928  *      
 929  *      er      01-May-1997     Fixed pointer conversion errors in 
 930  *                              SMC37c669_get_device_config().
 931  *      er      28-Jan-1997     Initial version.
 932  *
 933  *--
 934  */
 935 
 936 #ifndef TRUE
 937 #define TRUE 1
 938 #endif
 939 #ifndef FALSE
 940 #define FALSE 0
 941 #endif
 942 
 943 #define wb( _x_, _y_ )  outb( _y_, (unsigned int)((unsigned long)_x_) )
 944 #define rb( _x_ )       inb( (unsigned int)((unsigned long)_x_) )
 945 
 946 /*
 947 ** Local storage for device configuration information.
 948 **
 949 ** Since the SMC37c669 does not provide an explicit
 950 ** mechanism for enabling/disabling individual device 
 951 ** functions, other than unmapping the device, local 
 952 ** storage for device configuration information is 
 953 ** allocated here for use in implementing our own 
 954 ** function enable/disable scheme.
 955 */
 956 static struct DEVICE_CONFIG {
 957     unsigned int port1;
 958     unsigned int port2;
 959     int irq;
 960     int drq;
 961 } local_config [NUM_FUNCS];
 962 
 963 /*
 964 ** List of all possible addresses for the Super I/O chip
 965 */
 966 static unsigned long SMC37c669_Addresses[] __initdata =
 967     {
 968         0x3F0UL,            /* Primary address      */
 969         0x370UL,            /* Secondary address    */
 970         0UL                 /* End of list          */
 971     };
 972 
 973 /*
 974 ** Global Pointer to the Super I/O device
 975 */
 976 static SMC37c669_CONFIG_REGS *SMC37c669 __initdata = NULL;
 977 
 978 /*
 979 ** IRQ Translation Table
 980 **
 981 ** The IRQ translation table is a list of SMC37c669 device 
 982 ** and standard ISA IRQs.
 983 **
 984 */
 985 static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_table __initdata; 
 986 
 987 /*
 988 ** The following definition is for the default IRQ 
 989 ** translation table.
 990 */
 991 static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_default_irq_table[]
 992 __initdata = 
 993     { 
 994         { SMC37c669_DEVICE_IRQ_A, -1 }, 
 995         { SMC37c669_DEVICE_IRQ_B, -1 }, 
 996         { SMC37c669_DEVICE_IRQ_C, 7 }, 
 997         { SMC37c669_DEVICE_IRQ_D, 6 }, 
 998         { SMC37c669_DEVICE_IRQ_E, 4 }, 
 999         { SMC37c669_DEVICE_IRQ_F, 3 }, 
1000         { SMC37c669_DEVICE_IRQ_H, -1 }, 
1001         { -1, -1 } /* End of table */
1002     };
1003 
1004 /*
1005 ** The following definition is for the MONET (XP1000) IRQ 
1006 ** translation table.
1007 */
1008 static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_monet_irq_table[]
1009 __initdata = 
1010     { 
1011         { SMC37c669_DEVICE_IRQ_A, -1 }, 
1012         { SMC37c669_DEVICE_IRQ_B, -1 }, 
1013         { SMC37c669_DEVICE_IRQ_C, 6 }, 
1014         { SMC37c669_DEVICE_IRQ_D, 7 }, 
1015         { SMC37c669_DEVICE_IRQ_E, 4 }, 
1016         { SMC37c669_DEVICE_IRQ_F, 3 }, 
1017         { SMC37c669_DEVICE_IRQ_H, -1 }, 
1018         { -1, -1 } /* End of table */
1019     };
1020 
1021 static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_tables[] __initdata =
1022     {
1023         SMC37c669_default_irq_table,
1024         SMC37c669_monet_irq_table
1025     }; 
1026 
1027 /*
1028 ** DRQ Translation Table
1029 **
1030 ** The DRQ translation table is a list of SMC37c669 device and
1031 ** ISA DMA channels.
1032 **
1033 */
1034 static SMC37c669_DRQ_TRANSLATION_ENTRY *SMC37c669_drq_table __initdata;
1035 
1036 /*
1037 ** The following definition is the default DRQ
1038 ** translation table.
1039 */
1040 static SMC37c669_DRQ_TRANSLATION_ENTRY SMC37c669_default_drq_table[]
1041 __initdata = 
1042     { 
1043         { SMC37c669_DEVICE_DRQ_A, 2 }, 
1044         { SMC37c669_DEVICE_DRQ_B, 3 }, 
1045         { SMC37c669_DEVICE_DRQ_C, -1 }, 
1046         { -1, -1 } /* End of table */
1047     };
1048 
1049 /*
1050 ** Local Function Prototype Declarations
1051 */
1052 
1053 static unsigned int SMC37c669_is_device_enabled( 
1054     unsigned int func 
1055 );
1056 
1057 #if 0
1058 static unsigned int SMC37c669_get_device_config( 
1059     unsigned int func, 
1060     int *port, 
1061     int *irq, 
1062     int *drq 
1063 );
1064 #endif
1065 
1066 static void SMC37c669_config_mode( 
1067     unsigned int enable 
1068 );
1069 
1070 static unsigned char SMC37c669_read_config( 
1071     unsigned char index 
1072 );
1073 
1074 static void SMC37c669_write_config( 
1075     unsigned char index, 
1076     unsigned char data 
1077 );
1078 
1079 static void SMC37c669_init_local_config( void );
1080 
1081 static struct DEVICE_CONFIG *SMC37c669_get_config(
1082     unsigned int func
1083 );
1084 
1085 static int SMC37c669_xlate_irq(
1086     int irq 
1087 );
1088 
1089 static int SMC37c669_xlate_drq(
1090     int drq 
1091 );
1092 
1093 static  __cacheline_aligned DEFINE_SPINLOCK(smc_lock);
1094 
1095 /*
1096 **++
1097 **  FUNCTIONAL DESCRIPTION:
1098 **
1099 **      This function detects the presence of an SMC37c669 Super I/O
1100 **      controller.
1101 **
1102 **  FORMAL PARAMETERS:
1103 **
1104 **      None
1105 **
1106 **  RETURN VALUE:
1107 **
1108 **      Returns a pointer to the device if found, otherwise,
1109 **      the NULL pointer is returned.
1110 **
1111 **  SIDE EFFECTS:
1112 **
1113 **      None
1114 **
1115 **--
1116 */
1117 SMC37c669_CONFIG_REGS * __init SMC37c669_detect( int index )
1118 {
1119     int i;
1120     SMC37c669_DEVICE_ID_REGISTER id;
1121 
1122     for ( i = 0;  SMC37c669_Addresses[i] != 0;  i++ ) {
1123 /*
1124 ** Initialize the device pointer even though we don't yet know if
1125 ** the controller is at this address.  The support functions access
1126 ** the controller through this device pointer so we need to set it
1127 ** even when we are looking ...
1128 */
1129         SMC37c669 = ( SMC37c669_CONFIG_REGS * )SMC37c669_Addresses[i];
1130 /*
1131 ** Enter configuration mode
1132 */
1133         SMC37c669_config_mode( TRUE );
1134 /*
1135 ** Read the device id
1136 */
1137         id.as_uchar = SMC37c669_read_config( SMC37c669_DEVICE_ID_INDEX );
1138 /*
1139 ** Exit configuration mode
1140 */
1141         SMC37c669_config_mode( FALSE );
1142 /*
1143 ** Does the device id match?  If so, assume we have found an
1144 ** SMC37c669 controller at this address.
1145 */
1146         if ( id.by_field.device_id == SMC37c669_DEVICE_ID ) {
1147 /*
1148 ** Initialize the IRQ and DRQ translation tables.
1149 */
1150             SMC37c669_irq_table = SMC37c669_irq_tables[ index ];
1151             SMC37c669_drq_table = SMC37c669_default_drq_table;
1152 /*
1153 ** erfix
1154 **
1155 ** If the platform can't use the IRQ and DRQ defaults set up in this 
1156 ** file, it should call a platform-specific external routine at this 
1157 ** point to reset the IRQ and DRQ translation table pointers to point 
1158 ** at the appropriate tables for the platform.  If the defaults are 
1159 ** acceptable, then the external routine should do nothing.
1160 */
1161 
1162 /*
1163 ** Put the chip back into configuration mode
1164 */
1165             SMC37c669_config_mode( TRUE );
1166 /*
1167 ** Initialize local storage for configuration information
1168 */
1169             SMC37c669_init_local_config( );
1170 /*
1171 ** Exit configuration mode
1172 */
1173             SMC37c669_config_mode( FALSE );
1174 /*
1175 ** SMC37c669 controller found, break out of search loop
1176 */
1177             break;
1178         }
1179         else {
1180 /*
1181 ** Otherwise, we did not find an SMC37c669 controller at this
1182 ** address so set the device pointer to NULL.
1183 */
1184             SMC37c669 = NULL;
1185         }
1186     }
1187     return SMC37c669;
1188 }
1189 
1190 
1191 /*
1192 **++
1193 **  FUNCTIONAL DESCRIPTION:
1194 **
1195 **      This function enables an SMC37c669 device function.
1196 **
1197 **  FORMAL PARAMETERS:
1198 **
1199 **      func:
1200 **          Which device function to enable
1201 **
1202 **  RETURN VALUE:
1203 **
1204 **      Returns TRUE is the device function was enabled, otherwise, FALSE
1205 **
1206 **  SIDE EFFECTS:
1207 **
1208 **      {@description or none@}
1209 **
1210 **  DESIGN:
1211 **
1212 **      Enabling a device function in the SMC37c669 controller involves
1213 **      setting all of its mappings (port, irq, drq ...).  A local 
1214 **      "shadow" copy of the device configuration is kept so we can
1215 **      just set each mapping to what the local copy says.
1216 **
1217 **      This function ALWAYS updates the local shadow configuration of
1218 **      the device function being enabled, even if the device is always
1219 **      enabled.  To avoid replication of code, functions such as
1220 **      configure_device set up the local copy and then call this 
1221 **      function to the update the real device.
1222 **
1223 **--
1224 */
1225 unsigned int __init SMC37c669_enable_device ( unsigned int func )
1226 {
1227     unsigned int ret_val = FALSE;
1228 /*
1229 ** Put the device into configuration mode
1230 */
1231     SMC37c669_config_mode( TRUE );
1232     switch ( func ) {
1233         case SERIAL_0:
1234             {
1235                 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
1236                 SMC37c669_SERIAL_IRQ_REGISTER irq;
1237 /*
1238 ** Enable the serial 1 IRQ mapping
1239 */
1240                 irq.as_uchar = 
1241                     SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
1242 
1243                 irq.by_field.uart1_irq =
1244                     SMC37c669_RAW_DEVICE_IRQ(
1245                         SMC37c669_xlate_irq( local_config[ func ].irq )
1246                     );
1247 
1248                 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
1249 /*
1250 ** Enable the serial 1 port base address mapping
1251 */
1252                 base_addr.as_uchar = 0;
1253                 base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3;
1254 
1255                 SMC37c669_write_config( 
1256                     SMC37c669_SERIAL0_BASE_ADDRESS_INDEX,
1257                     base_addr.as_uchar
1258                 );
1259                 ret_val = TRUE;
1260                 break;
1261             }
1262         case SERIAL_1:
1263             {
1264                 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
1265                 SMC37c669_SERIAL_IRQ_REGISTER irq;
1266 /*
1267 ** Enable the serial 2 IRQ mapping
1268 */
1269                 irq.as_uchar = 
1270                     SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
1271 
1272                 irq.by_field.uart2_irq =
1273                     SMC37c669_RAW_DEVICE_IRQ(
1274                         SMC37c669_xlate_irq( local_config[ func ].irq )
1275                     );
1276 
1277                 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
1278 /*
1279 ** Enable the serial 2 port base address mapping
1280 */
1281                 base_addr.as_uchar = 0;
1282                 base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3;
1283 
1284                 SMC37c669_write_config( 
1285                     SMC37c669_SERIAL1_BASE_ADDRESS_INDEX,
1286                     base_addr.as_uchar
1287                 );
1288                 ret_val = TRUE;
1289                 break;
1290             }
1291         case PARALLEL_0:
1292             {
1293                 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr;
1294                 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
1295                 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
1296 /*
1297 ** Enable the parallel port DMA channel mapping
1298 */
1299                 drq.as_uchar =
1300                     SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
1301 
1302                 drq.by_field.ppt_drq = 
1303                     SMC37c669_RAW_DEVICE_DRQ(
1304                         SMC37c669_xlate_drq( local_config[ func ].drq )
1305                     );
1306 
1307                 SMC37c669_write_config(
1308                     SMC37c669_PARALLEL_FDC_DRQ_INDEX,
1309                     drq.as_uchar
1310                 );
1311 /*
1312 ** Enable the parallel port IRQ mapping
1313 */
1314                 irq.as_uchar = 
1315                     SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
1316 
1317                 irq.by_field.ppt_irq =
1318                     SMC37c669_RAW_DEVICE_IRQ(
1319                         SMC37c669_xlate_irq( local_config[ func ].irq )
1320                     );
1321 
1322                 SMC37c669_write_config( 
1323                     SMC37c669_PARALLEL_FDC_IRQ_INDEX,
1324                     irq.as_uchar
1325                 );
1326 /*
1327 ** Enable the parallel port base address mapping
1328 */
1329                 base_addr.as_uchar = 0;
1330                 base_addr.by_field.addr9_2 = local_config[ func ].port1 >> 2;
1331 
1332                 SMC37c669_write_config(
1333                     SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX,
1334                     base_addr.as_uchar
1335                 );
1336                 ret_val = TRUE;
1337                 break;
1338             }
1339         case FLOPPY_0:
1340             {
1341                 SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr;
1342                 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
1343                 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
1344 /*
1345 ** Enable the floppy controller DMA channel mapping
1346 */
1347                 drq.as_uchar =
1348                     SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
1349                  
1350                 drq.by_field.fdc_drq =
1351                     SMC37c669_RAW_DEVICE_DRQ(
1352                         SMC37c669_xlate_drq( local_config[ func ].drq )
1353                     );
1354                  
1355                 SMC37c669_write_config( 
1356                     SMC37c669_PARALLEL_FDC_DRQ_INDEX,
1357                     drq.as_uchar
1358                 );
1359 /*
1360 ** Enable the floppy controller IRQ mapping
1361 */
1362                 irq.as_uchar =
1363                     SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
1364                  
1365                 irq.by_field.fdc_irq =
1366                     SMC37c669_RAW_DEVICE_IRQ(
1367                         SMC37c669_xlate_irq( local_config[ func ].irq )
1368                     );
1369                  
1370                 SMC37c669_write_config(
1371                     SMC37c669_PARALLEL_FDC_IRQ_INDEX,
1372                     irq.as_uchar
1373                 );
1374 /*
1375 ** Enable the floppy controller base address mapping
1376 */
1377                 base_addr.as_uchar = 0;
1378                 base_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4;
1379                  
1380                 SMC37c669_write_config(
1381                     SMC37c669_FDC_BASE_ADDRESS_INDEX,
1382                     base_addr.as_uchar
1383                 );
1384                 ret_val = TRUE;
1385                 break;
1386             }
1387         case IDE_0:
1388             {
1389                 SMC37c669_IDE_ADDRESS_REGISTER ide_addr;
1390 /*
1391 ** Enable the IDE alternate status base address mapping
1392 */
1393                 ide_addr.as_uchar = 0;
1394                 ide_addr.by_field.addr9_4 = local_config[ func ].port2 >> 4;
1395                  
1396                 SMC37c669_write_config(
1397                     SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX,
1398                     ide_addr.as_uchar
1399                 );
1400 /*
1401 ** Enable the IDE controller base address mapping
1402 */
1403                 ide_addr.as_uchar = 0;
1404                 ide_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4;
1405                  
1406                 SMC37c669_write_config(
1407                     SMC37c669_IDE_BASE_ADDRESS_INDEX,
1408                     ide_addr.as_uchar
1409                 );
1410                 ret_val = TRUE;
1411                 break;
1412             }
1413     }
1414 /*
1415 ** Exit configuration mode and return
1416 */
1417     SMC37c669_config_mode( FALSE );
1418 
1419     return ret_val;
1420 }
1421 
1422 
1423 /*
1424 **++
1425 **  FUNCTIONAL DESCRIPTION:
1426 **
1427 **      This function disables a device function within the
1428 **      SMC37c669 Super I/O controller.
1429 **
1430 **  FORMAL PARAMETERS:
1431 **
1432 **      func:
1433 **          Which function to disable
1434 **
1435 **  RETURN VALUE:
1436 **
1437 **      Return TRUE if the device function was disabled, otherwise, FALSE
1438 **
1439 **  SIDE EFFECTS:
1440 **
1441 **      {@description or none@}
1442 **
1443 **  DESIGN:
1444 **
1445 **      Disabling a function in the SMC37c669 device involves
1446 **      disabling all the function's mappings (port, irq, drq ...).
1447 **      A shadow copy of the device configuration is maintained
1448 **      in local storage so we won't worry aboving saving the
1449 **      current configuration information.
1450 **
1451 **--
1452 */
1453 unsigned int __init SMC37c669_disable_device ( unsigned int func )
1454 {
1455     unsigned int ret_val = FALSE;
1456 
1457 /*
1458 ** Put the device into configuration mode
1459 */
1460     SMC37c669_config_mode( TRUE );
1461     switch ( func ) {
1462         case SERIAL_0:
1463             {
1464                 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
1465                 SMC37c669_SERIAL_IRQ_REGISTER irq;
1466 /*
1467 ** Disable the serial 1 IRQ mapping
1468 */
1469                 irq.as_uchar = 
1470                     SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
1471 
1472                 irq.by_field.uart1_irq = 0;
1473 
1474                 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
1475 /*
1476 ** Disable the serial 1 port base address mapping
1477 */
1478                 base_addr.as_uchar = 0;
1479                 SMC37c669_write_config( 
1480                     SMC37c669_SERIAL0_BASE_ADDRESS_INDEX,
1481                     base_addr.as_uchar
1482                 );
1483                 ret_val = TRUE;
1484                 break;
1485             }
1486         case SERIAL_1:
1487             {
1488                 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
1489                 SMC37c669_SERIAL_IRQ_REGISTER irq;
1490 /*
1491 ** Disable the serial 2 IRQ mapping
1492 */
1493                 irq.as_uchar = 
1494                     SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
1495 
1496                 irq.by_field.uart2_irq = 0;
1497 
1498                 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
1499 /*
1500 ** Disable the serial 2 port base address mapping
1501 */
1502                 base_addr.as_uchar = 0;
1503 
1504                 SMC37c669_write_config( 
1505                     SMC37c669_SERIAL1_BASE_ADDRESS_INDEX,
1506                     base_addr.as_uchar
1507                 );
1508                 ret_val = TRUE;
1509                 break;
1510             }
1511         case PARALLEL_0:
1512             {
1513                 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr;
1514                 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
1515                 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
1516 /*
1517 ** Disable the parallel port DMA channel mapping
1518 */
1519                 drq.as_uchar =
1520                     SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
1521 
1522                 drq.by_field.ppt_drq = 0;
1523 
1524                 SMC37c669_write_config(
1525                     SMC37c669_PARALLEL_FDC_DRQ_INDEX,
1526                     drq.as_uchar
1527                 );
1528 /*
1529 ** Disable the parallel port IRQ mapping
1530 */
1531                 irq.as_uchar = 
1532                     SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
1533 
1534                 irq.by_field.ppt_irq = 0;
1535 
1536                 SMC37c669_write_config( 
1537                     SMC37c669_PARALLEL_FDC_IRQ_INDEX,
1538                     irq.as_uchar
1539                 );
1540 /*
1541 ** Disable the parallel port base address mapping
1542 */
1543                 base_addr.as_uchar = 0;
1544 
1545                 SMC37c669_write_config(
1546                     SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX,
1547                     base_addr.as_uchar
1548                 );
1549                 ret_val = TRUE;
1550                 break;
1551             }
1552         case FLOPPY_0:
1553             {
1554                 SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr;
1555                 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
1556                 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
1557 /*
1558 ** Disable the floppy controller DMA channel mapping
1559 */
1560                 drq.as_uchar =
1561                     SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
1562                  
1563                 drq.by_field.fdc_drq = 0;
1564                  
1565                 SMC37c669_write_config( 
1566                     SMC37c669_PARALLEL_FDC_DRQ_INDEX,
1567                     drq.as_uchar
1568                 );
1569 /*
1570 ** Disable the floppy controller IRQ mapping
1571 */
1572                 irq.as_uchar =
1573                     SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
1574                  
1575                 irq.by_field.fdc_irq = 0;
1576                  
1577                 SMC37c669_write_config(
1578                     SMC37c669_PARALLEL_FDC_IRQ_INDEX,
1579                     irq.as_uchar
1580                 );
1581 /*
1582 ** Disable the floppy controller base address mapping
1583 */
1584                 base_addr.as_uchar = 0;
1585                  
1586                 SMC37c669_write_config(
1587                     SMC37c669_FDC_BASE_ADDRESS_INDEX,
1588                     base_addr.as_uchar
1589                 );
1590                 ret_val = TRUE;
1591                 break;
1592             }
1593         case IDE_0:
1594             {
1595                 SMC37c669_IDE_ADDRESS_REGISTER ide_addr;
1596 /*
1597 ** Disable the IDE alternate status base address mapping
1598 */
1599                 ide_addr.as_uchar = 0;
1600                  
1601                 SMC37c669_write_config(
1602                     SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX,
1603                     ide_addr.as_uchar
1604                 );
1605 /*
1606 ** Disable the IDE controller base address mapping
1607 */
1608                 ide_addr.as_uchar = 0;
1609                  
1610                 SMC37c669_write_config(
1611                     SMC37c669_IDE_BASE_ADDRESS_INDEX,
1612                     ide_addr.as_uchar
1613                 );
1614                 ret_val = TRUE;
1615                 break;
1616             }
1617     }
1618 /*
1619 ** Exit configuration mode and return
1620 */
1621     SMC37c669_config_mode( FALSE );
1622 
1623     return ret_val;
1624 }
1625 
1626 
1627 /*
1628 **++
1629 **  FUNCTIONAL DESCRIPTION:
1630 **
1631 **      This function configures a device function within the 
1632 **      SMC37c669 Super I/O controller.
1633 **
1634 **  FORMAL PARAMETERS:
1635 **
1636 **      func:
1637 **          Which device function
1638 **       
1639 **      port:
1640 **          I/O port for the function to use
1641 **       
1642 **      irq:
1643 **          IRQ for the device function to use
1644 **       
1645 **      drq:
1646 **          DMA channel for the device function to use
1647 **
1648 **  RETURN VALUE:
1649 **
1650 **      Returns TRUE if the device function was configured, 
1651 **      otherwise, FALSE.
1652 **
1653 **  SIDE EFFECTS:
1654 **
1655 **      {@description or none@}
1656 **
1657 **  DESIGN:
1658 **
1659 **      If this function returns TRUE, the local shadow copy of
1660 **      the configuration is also updated.  If the device function
1661 **      is currently disabled, only the local shadow copy is 
1662 **      updated and the actual device function will be updated
1663 **      if/when it is enabled.
1664 **
1665 **--
1666 */
1667 unsigned int __init SMC37c669_configure_device (
1668     unsigned int func,
1669     int port,
1670     int irq,
1671     int drq )
1672 {
1673     struct DEVICE_CONFIG *cp;
1674 
1675 /*
1676 ** Check for a valid configuration
1677 */
1678     if ( ( cp = SMC37c669_get_config ( func ) ) != NULL ) {
1679 /*
1680 ** Configuration is valid, update the local shadow copy
1681 */
1682         if ( ( drq & ~0xFF ) == 0 ) {
1683             cp->drq = drq;
1684         }
1685         if ( ( irq & ~0xFF ) == 0 ) {
1686             cp->irq = irq;
1687         }
1688         if ( ( port & ~0xFFFF ) == 0 ) {
1689             cp->port1 = port;
1690         }
1691 /*
1692 ** If the device function is enabled, update the actual
1693 ** device configuration.
1694 */
1695         if ( SMC37c669_is_device_enabled( func ) ) {
1696             SMC37c669_enable_device( func );
1697         }
1698         return TRUE;
1699     }
1700     return FALSE;
1701 }
1702 
1703 
1704 /*
1705 **++
1706 **  FUNCTIONAL DESCRIPTION:
1707 **
1708 **      This function determines whether a device function
1709 **      within the SMC37c669 controller is enabled.
1710 **
1711 **  FORMAL PARAMETERS:
1712 **
1713 **      func:
1714 **          Which device function
1715 **
1716 **  RETURN VALUE:
1717 **
1718 **      Returns TRUE if the device function is enabled, otherwise, FALSE
1719 **
1720 **  SIDE EFFECTS:
1721 **
1722 **      {@description or none@}
1723 **
1724 **  DESIGN:
1725 **
1726 **      To check whether a device is enabled we will only look at 
1727 **      the port base address mapping.  According to the SMC37c669
1728 **      specification, all of the port base address mappings are
1729 **      disabled if the addr<9:8> (bits <7:6> of the register) are
1730 **      zero.
1731 **
1732 **--
1733 */
1734 static unsigned int __init SMC37c669_is_device_enabled ( unsigned int func )
1735 {
1736     unsigned char base_addr = 0;
1737     unsigned int dev_ok = FALSE;
1738     unsigned int ret_val = FALSE;
1739 /*
1740 ** Enter configuration mode
1741 */
1742     SMC37c669_config_mode( TRUE );
1743      
1744     switch ( func ) {
1745         case SERIAL_0:
1746             base_addr =
1747                 SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX );
1748             dev_ok = TRUE;
1749             break;
1750         case SERIAL_1:
1751             base_addr =
1752                 SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX );
1753             dev_ok = TRUE;
1754             break;
1755         case PARALLEL_0:
1756             base_addr =
1757                 SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX );
1758             dev_ok = TRUE;
1759             break;
1760         case FLOPPY_0:
1761             base_addr =
1762                 SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX );
1763             dev_ok = TRUE;
1764             break;
1765         case IDE_0:
1766             base_addr =
1767                 SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX );
1768             dev_ok = TRUE;
1769             break;
1770     }
1771 /*
1772 ** If we have a valid device, check base_addr<7:6> to see if the
1773 ** device is enabled (mapped).
1774 */
1775     if ( ( dev_ok ) && ( ( base_addr & 0xC0 ) != 0 ) ) {
1776 /*
1777 ** The mapping is not disabled, so assume that the function is 
1778 ** enabled.
1779 */
1780         ret_val = TRUE;
1781     }
1782 /*
1783 ** Exit configuration mode 
1784 */
1785     SMC37c669_config_mode( FALSE );
1786 
1787     return ret_val;
1788 }
1789 
1790 
1791 #if 0
1792 /*
1793 **++
1794 **  FUNCTIONAL DESCRIPTION:
1795 **
1796 **      This function retrieves the configuration information of a 
1797 **      device function within the SMC37c699 Super I/O controller.
1798 **
1799 **  FORMAL PARAMETERS:
1800 **
1801 **      func:
1802 **          Which device function
1803 **       
1804 **      port:
1805 **          I/O port returned
1806 **       
1807 **      irq:
1808 **          IRQ returned
1809 **       
1810 **      drq:
1811 **          DMA channel returned
1812 **
1813 **  RETURN VALUE:
1814 **
1815 **      Returns TRUE if the device configuration was successfully
1816 **      retrieved, otherwise, FALSE.
1817 **
1818 **  SIDE EFFECTS:
1819 **
1820 **      The data pointed to by the port, irq, and drq parameters
1821 **      my be modified even if the configuration is not successfully
1822 **      retrieved.
1823 **
1824 **  DESIGN:
1825 **
1826 **      The device configuration is fetched from the local shadow
1827 **      copy.  Any unused parameters will be set to -1.  Any
1828 **      parameter which is not desired can specify the NULL
1829 **      pointer.
1830 **
1831 **--
1832 */
1833 static unsigned int __init SMC37c669_get_device_config (
1834     unsigned int func,
1835     int *port,
1836     int *irq,
1837     int *drq )
1838 {
1839     struct DEVICE_CONFIG *cp;
1840     unsigned int ret_val = FALSE;
1841 /*
1842 ** Check for a valid device configuration
1843 */
1844     if ( ( cp = SMC37c669_get_config( func ) ) != NULL ) {
1845         if ( drq != NULL ) {
1846             *drq = cp->drq;
1847             ret_val = TRUE;
1848         }
1849         if ( irq != NULL ) {
1850             *irq = cp->irq;
1851             ret_val = TRUE;
1852         }
1853         if ( port != NULL ) {
1854             *port = cp->port1;
1855             ret_val = TRUE;
1856         }
1857     }
1858     return ret_val;
1859 }
1860 #endif
1861 
1862 
1863 /*
1864 **++
1865 **  FUNCTIONAL DESCRIPTION:
1866 **
1867 **      This function displays the current state of the SMC37c699
1868 **      Super I/O controller's device functions.
1869 **
1870 **  FORMAL PARAMETERS:
1871 **
1872 **      None
1873 **
1874 **  RETURN VALUE:
1875 **
1876 **      None
1877 **
1878 **  SIDE EFFECTS:
1879 **
1880 **      None
1881 **
1882 **--
1883 */
1884 void __init SMC37c669_display_device_info ( void )
1885 {
1886     if ( SMC37c669_is_device_enabled( SERIAL_0 ) ) {
1887         printk( "  Serial 0:    Enabled [ Port 0x%x, IRQ %d ]\n",
1888                  local_config[ SERIAL_0 ].port1,
1889                  local_config[ SERIAL_0 ].irq
1890         );
1891     }
1892     else {
1893         printk( "  Serial 0:    Disabled\n" );
1894     }
1895 
1896     if ( SMC37c669_is_device_enabled( SERIAL_1 ) ) {
1897         printk( "  Serial 1:    Enabled [ Port 0x%x, IRQ %d ]\n",
1898                  local_config[ SERIAL_1 ].port1,
1899                  local_config[ SERIAL_1 ].irq
1900         );
1901     }
1902     else {
1903         printk( "  Serial 1:    Disabled\n" );
1904     }
1905 
1906     if ( SMC37c669_is_device_enabled( PARALLEL_0 ) ) {
1907         printk( "  Parallel:    Enabled [ Port 0x%x, IRQ %d/%d ]\n",
1908                  local_config[ PARALLEL_0 ].port1,
1909                  local_config[ PARALLEL_0 ].irq,
1910                  local_config[ PARALLEL_0 ].drq
1911         );
1912     }
1913     else {
1914         printk( "  Parallel:    Disabled\n" );
1915     }
1916 
1917     if ( SMC37c669_is_device_enabled( FLOPPY_0 ) ) {
1918         printk( "  Floppy Ctrl: Enabled [ Port 0x%x, IRQ %d/%d ]\n",
1919                  local_config[ FLOPPY_0 ].port1,
1920                  local_config[ FLOPPY_0 ].irq,
1921                  local_config[ FLOPPY_0 ].drq
1922         );
1923     }
1924     else {
1925         printk( "  Floppy Ctrl: Disabled\n" );
1926     }
1927 
1928     if ( SMC37c669_is_device_enabled( IDE_0 ) ) {
1929         printk( "  IDE 0:       Enabled [ Port 0x%x, IRQ %d ]\n",
1930                  local_config[ IDE_0 ].port1,
1931                  local_config[ IDE_0 ].irq
1932         );
1933     }
1934     else {
1935         printk( "  IDE 0:       Disabled\n" );
1936     }
1937 }
1938 
1939 
1940 /*
1941 **++
1942 **  FUNCTIONAL DESCRIPTION:
1943 **
1944 **      This function puts the SMC37c669 Super I/O controller into,
1945 **      and takes it out of, configuration mode.
1946 **
1947 **  FORMAL PARAMETERS:
1948 **
1949 **      enable:
1950 **          TRUE to enter configuration mode, FALSE to exit.
1951 **
1952 **  RETURN VALUE:
1953 **
1954 **      None
1955 **
1956 **  SIDE EFFECTS:
1957 **
1958 **      The SMC37c669 controller may be left in configuration mode.
1959 **
1960 **--
1961 */
1962 static void __init SMC37c669_config_mode( 
1963     unsigned int enable )
1964 {
1965     if ( enable ) {
1966 /*
1967 ** To enter configuration mode, two writes in succession to the index
1968 ** port are required.  If a write to another address or port occurs
1969 ** between these two writes, the chip does not enter configuration
1970 ** mode.  Therefore, a spinlock is placed around the two writes to 
1971 ** guarantee that they complete uninterrupted.
1972 */
1973         spin_lock(&smc_lock);
1974         wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY );
1975         wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY );
1976         spin_unlock(&smc_lock);
1977     }
1978     else {
1979         wb( &SMC37c669->index_port, SMC37c669_CONFIG_OFF_KEY );
1980     }
1981 }
1982 
1983 /*
1984 **++
1985 **  FUNCTIONAL DESCRIPTION:
1986 **
1987 **      This function reads an SMC37c669 Super I/O controller
1988 **      configuration register.  This function assumes that the
1989 **      device is already in configuration mode.
1990 **
1991 **  FORMAL PARAMETERS:
1992 **
1993 **      index:
1994 **          Index value of configuration register to read
1995 **
1996 **  RETURN VALUE:
1997 **
1998 **      Data read from configuration register
1999 **
2000 **  SIDE EFFECTS:
2001 **
2002 **      None
2003 **
2004 **--
2005 */
2006 static unsigned char __init SMC37c669_read_config( 
2007     unsigned char index )
2008 {
2009         wb(&SMC37c669->index_port, index);
2010         return rb(&SMC37c669->data_port);
2011 }
2012 
2013 /*
2014 **++
2015 **  FUNCTIONAL DESCRIPTION:
2016 **
2017 **      This function writes an SMC37c669 Super I/O controller
2018 **      configuration register.  This function assumes that the
2019 **      device is already in configuration mode.
2020 **
2021 **  FORMAL PARAMETERS:
2022 **
2023 **      index:
2024 **          Index of configuration register to write
2025 **       
2026 **      data:
2027 **          Data to be written
2028 **
2029 **  RETURN VALUE:
2030 **
2031 **      None
2032 **
2033 **  SIDE EFFECTS:
2034 **
2035 **      None
2036 **
2037 **--
2038 */
2039 static void __init SMC37c669_write_config( 
2040     unsigned char index, 
2041     unsigned char data )
2042 {
2043     wb( &SMC37c669->index_port, index );
2044     wb( &SMC37c669->data_port, data );
2045 }
2046 
2047 
2048 /*
2049 **++
2050 **  FUNCTIONAL DESCRIPTION:
2051 **
2052 **      This function initializes the local device
2053 **      configuration storage.  This function assumes
2054 **      that the device is already in configuration
2055 **      mode.
2056 **
2057 **  FORMAL PARAMETERS:
2058 **
2059 **      None
2060 **
2061 **  RETURN VALUE:
2062 **
2063 **      None
2064 **
2065 **  SIDE EFFECTS:
2066 **
2067 **      Local storage for device configuration information
2068 **      is initialized.
2069 **
2070 **--
2071 */
2072 static void __init SMC37c669_init_local_config ( void )
2073 {
2074     SMC37c669_SERIAL_BASE_ADDRESS_REGISTER uart_base;
2075     SMC37c669_SERIAL_IRQ_REGISTER uart_irqs;
2076     SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER ppt_base;
2077     SMC37c669_PARALLEL_FDC_IRQ_REGISTER ppt_fdc_irqs;
2078     SMC37c669_PARALLEL_FDC_DRQ_REGISTER ppt_fdc_drqs;
2079     SMC37c669_FDC_BASE_ADDRESS_REGISTER fdc_base;
2080     SMC37c669_IDE_ADDRESS_REGISTER ide_base;
2081     SMC37c669_IDE_ADDRESS_REGISTER ide_alt;
2082 
2083 /*
2084 ** Get serial port 1 base address 
2085 */
2086     uart_base.as_uchar = 
2087         SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX );
2088 /*
2089 ** Get IRQs for serial ports 1 & 2
2090 */
2091     uart_irqs.as_uchar = 
2092         SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
2093 /*
2094 ** Store local configuration information for serial port 1
2095 */
2096     local_config[SERIAL_0].port1 = uart_base.by_field.addr9_3 << 3;
2097     local_config[SERIAL_0].irq = 
2098         SMC37c669_xlate_irq( 
2099             SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart1_irq ) 
2100         );
2101 /*
2102 ** Get serial port 2 base address
2103 */
2104     uart_base.as_uchar = 
2105         SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX );
2106 /*
2107 ** Store local configuration information for serial port 2
2108 */
2109     local_config[SERIAL_1].port1 = uart_base.by_field.addr9_3 << 3;
2110     local_config[SERIAL_1].irq = 
2111         SMC37c669_xlate_irq( 
2112             SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart2_irq ) 
2113         );
2114 /*
2115 ** Get parallel port base address
2116 */
2117     ppt_base.as_uchar =
2118         SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX );
2119 /*
2120 ** Get IRQs for parallel port and floppy controller
2121 */
2122     ppt_fdc_irqs.as_uchar =
2123         SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
2124 /*
2125 ** Get DRQs for parallel port and floppy controller
2126 */
2127     ppt_fdc_drqs.as_uchar =
2128         SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
2129 /*
2130 ** Store local configuration information for parallel port
2131 */
2132     local_config[PARALLEL_0].port1 = ppt_base.by_field.addr9_2 << 2;
2133     local_config[PARALLEL_0].irq =
2134         SMC37c669_xlate_irq(
2135             SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.ppt_irq )
2136         );
2137     local_config[PARALLEL_0].drq =
2138         SMC37c669_xlate_drq(
2139             SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.ppt_drq )
2140         );
2141 /*
2142 ** Get floppy controller base address
2143 */
2144     fdc_base.as_uchar = 
2145         SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX );
2146 /*
2147 ** Store local configuration information for floppy controller
2148 */
2149     local_config[FLOPPY_0].port1 = fdc_base.by_field.addr9_4 << 4;
2150     local_config[FLOPPY_0].irq =
2151         SMC37c669_xlate_irq(
2152             SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.fdc_irq )
2153         );
2154     local_config[FLOPPY_0].drq =
2155         SMC37c669_xlate_drq(
2156             SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.fdc_drq )
2157         );
2158 /*
2159 ** Get IDE controller base address
2160 */
2161     ide_base.as_uchar =
2162         SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX );
2163 /*
2164 ** Get IDE alternate status base address
2165 */
2166     ide_alt.as_uchar =
2167         SMC37c669_read_config( SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX );
2168 /*
2169 ** Store local configuration information for IDE controller
2170 */
2171     local_config[IDE_0].port1 = ide_base.by_field.addr9_4 << 4;
2172     local_config[IDE_0].port2 = ide_alt.by_field.addr9_4 << 4;
2173     local_config[IDE_0].irq = 14;
2174 }
2175 
2176 
2177 /*
2178 **++
2179 **  FUNCTIONAL DESCRIPTION:
2180 **
2181 **      This function returns a pointer to the local shadow
2182 **      configuration of the requested device function.
2183 **
2184 **  FORMAL PARAMETERS:
2185 **
2186 **      func:
2187 **          Which device function
2188 **
2189 **  RETURN VALUE:
2190 **
2191 **      Returns a pointer to the DEVICE_CONFIG structure for the
2192 **      requested function, otherwise, NULL.
2193 **
2194 **  SIDE EFFECTS:
2195 **
2196 **      {@description or none@}
2197 **
2198 **--
2199 */
2200 static struct DEVICE_CONFIG * __init SMC37c669_get_config( unsigned int func )
2201 {
2202     struct DEVICE_CONFIG *cp = NULL;
2203 
2204     switch ( func ) {
2205         case SERIAL_0:
2206             cp = &local_config[ SERIAL_0 ];
2207             break;
2208         case SERIAL_1:
2209             cp = &local_config[ SERIAL_1 ];
2210             break;
2211         case PARALLEL_0:
2212             cp = &local_config[ PARALLEL_0 ];
2213             break;
2214         case FLOPPY_0:
2215             cp = &local_config[ FLOPPY_0 ];
2216             break;
2217         case IDE_0:
2218             cp = &local_config[ IDE_0 ];
2219             break;
2220     }
2221     return cp;
2222 }
2223 
2224 /*
2225 **++
2226 **  FUNCTIONAL DESCRIPTION:
2227 **
2228 **      This function translates IRQs back and forth between ISA
2229 **      IRQs and SMC37c669 device IRQs.
2230 **
2231 **  FORMAL PARAMETERS:
2232 **
2233 **      irq:
2234 **          The IRQ to translate
2235 **
2236 **  RETURN VALUE:
2237 **
2238 **      Returns the translated IRQ, otherwise, returns -1.
2239 **
2240 **  SIDE EFFECTS:
2241 **
2242 **      {@description or none@}
2243 **
2244 **--
2245 */
2246 static int __init SMC37c669_xlate_irq ( int irq )
2247 {
2248     int i, translated_irq = -1;
2249 
2250     if ( SMC37c669_IS_DEVICE_IRQ( irq ) ) {
2251 /*
2252 ** We are translating a device IRQ to an ISA IRQ
2253 */
2254         for ( i = 0; ( SMC37c669_irq_table[i].device_irq != -1 ) || ( SMC37c669_irq_table[i].isa_irq != -1 ); i++ ) {
2255             if ( irq == SMC37c669_irq_table[i].device_irq ) {
2256                 translated_irq = SMC37c669_irq_table[i].isa_irq;
2257                 break;
2258             }
2259         }
2260     }
2261     else {
2262 /*
2263 ** We are translating an ISA IRQ to a device IRQ
2264 */
2265         for ( i = 0; ( SMC37c669_irq_table[i].isa_irq != -1 ) || ( SMC37c669_irq_table[i].device_irq != -1 ); i++ ) {
2266             if ( irq == SMC37c669_irq_table[i].isa_irq ) {
2267                 translated_irq = SMC37c669_irq_table[i].device_irq;
2268                 break;
2269             }
2270         }
2271     }
2272     return translated_irq;
2273 }
2274 
2275 
2276 /*
2277 **++
2278 **  FUNCTIONAL DESCRIPTION:
2279 **
2280 **      This function translates DMA channels back and forth between
2281 **      ISA DMA channels and SMC37c669 device DMA channels.
2282 **
2283 **  FORMAL PARAMETERS:
2284 **
2285 **      drq:
2286 **          The DMA channel to translate
2287 **
2288 **  RETURN VALUE:
2289 **
2290 **      Returns the translated DMA channel, otherwise, returns -1
2291 **
2292 **  SIDE EFFECTS:
2293 **
2294 **      {@description or none@}
2295 **
2296 **--
2297 */
2298 static int __init SMC37c669_xlate_drq ( int drq )
2299 {
2300     int i, translated_drq = -1;
2301 
2302     if ( SMC37c669_IS_DEVICE_DRQ( drq ) ) {
2303 /*
2304 ** We are translating a device DMA channel to an ISA DMA channel
2305 */
2306         for ( i = 0; ( SMC37c669_drq_table[i].device_drq != -1 ) || ( SMC37c669_drq_table[i].isa_drq != -1 ); i++ ) {
2307             if ( drq == SMC37c669_drq_table[i].device_drq ) {
2308                 translated_drq = SMC37c669_drq_table[i].isa_drq;
2309                 break;
2310             }
2311         }
2312     }
2313     else {
2314 /*
2315 ** We are translating an ISA DMA channel to a device DMA channel
2316 */
2317         for ( i = 0; ( SMC37c669_drq_table[i].isa_drq != -1 ) || ( SMC37c669_drq_table[i].device_drq != -1 ); i++ ) {
2318             if ( drq == SMC37c669_drq_table[i].isa_drq ) {
2319                 translated_drq = SMC37c669_drq_table[i].device_drq;
2320                 break;
2321             }
2322         }
2323     }
2324     return translated_drq;
2325 }
2326 
2327 #if 0
2328 int __init smcc669_init ( void )
2329 {
2330     struct INODE *ip;
2331 
2332     allocinode( smc_ddb.name, 1, &ip );
2333     ip->dva = &smc_ddb;
2334     ip->attr = ATTR$M_WRITE | ATTR$M_READ;
2335     ip->len[0] = 0x30;
2336     ip->misc = 0;
2337     INODE_UNLOCK( ip );
2338 
2339     return msg_success;
2340 }
2341 
2342 int __init smcc669_open( struct FILE *fp, char *info, char *next, char *mode )
2343 {
2344     struct INODE *ip;
2345 /*
2346 ** Allow multiple readers but only one writer.  ip->misc keeps track
2347 ** of the number of writers
2348 */
2349     ip = fp->ip;
2350     INODE_LOCK( ip );
2351     if ( fp->mode & ATTR$M_WRITE ) {
2352         if ( ip->misc ) {
2353             INODE_UNLOCK( ip );
2354             return msg_failure;     /* too many writers */
2355         }
2356         ip->misc++;
2357     }
2358 /*
2359 ** Treat the information field as a byte offset
2360 */
2361     *fp->offset = xtoi( info );
2362     INODE_UNLOCK( ip );
2363 
2364     return msg_success;
2365 }
2366 
2367 int __init smcc669_close( struct FILE *fp )
2368 {
2369     struct INODE *ip;
2370 
2371     ip = fp->ip;
2372     if ( fp->mode & ATTR$M_WRITE ) {
2373         INODE_LOCK( ip );
2374         ip->misc--;
2375         INODE_UNLOCK( ip );
2376     }
2377     return msg_success;
2378 }
2379 
2380 int __init smcc669_read( struct FILE *fp, int size, int number, unsigned char *buf )
2381 {
2382     int i;
2383     int length;
2384     int nbytes;
2385     struct INODE *ip;
2386 
2387 /*
2388 ** Always access a byte at a time
2389 */
2390     ip = fp->ip;
2391     length = size * number;
2392     nbytes = 0;
2393 
2394     SMC37c669_config_mode( TRUE );
2395     for ( i = 0; i < length; i++ ) {
2396         if ( !inrange( *fp->offset, 0, ip->len[0] ) ) 
2397             break;
2398         *buf++ = SMC37c669_read_config( *fp->offset );
2399         *fp->offset += 1;
2400         nbytes++;
2401     }
2402     SMC37c669_config_mode( FALSE );
2403     return nbytes;
2404 }
2405 
2406 int __init smcc669_write( struct FILE *fp, int size, int number, unsigned char *buf )
2407 {
2408     int i;
2409     int length;
2410     int nbytes;
2411     struct INODE *ip;
2412 /*
2413 ** Always access a byte at a time
2414 */
2415     ip = fp->ip;
2416     length = size * number;
2417     nbytes = 0;
2418 
2419     SMC37c669_config_mode( TRUE );
2420     for ( i = 0; i < length; i++ ) {
2421         if ( !inrange( *fp->offset, 0, ip->len[0] ) ) 
2422             break;
2423         SMC37c669_write_config( *fp->offset, *buf );
2424         *fp->offset += 1;
2425         buf++;
2426         nbytes++;
2427     }
2428     SMC37c669_config_mode( FALSE );
2429     return nbytes;
2430 }
2431 #endif
2432 
2433 void __init
2434 SMC37c669_dump_registers(void)
2435 {
2436   int i;
2437   for (i = 0; i <= 0x29; i++)
2438     printk("-- CR%02x : %02x\n", i, SMC37c669_read_config(i));
2439 }
2440 /*+
2441  * ============================================================================
2442  * = SMC_init - SMC37c669 Super I/O controller initialization                 =
2443  * ============================================================================
2444  *
2445  * OVERVIEW:
2446  *
2447  *      This routine configures and enables device functions on the
2448  *      SMC37c669 Super I/O controller.
2449  *
2450  * FORM OF CALL:
2451  *
2452  *      SMC_init( );
2453  *
2454  * RETURNS:
2455  *
2456  *      Nothing
2457  *
2458  * ARGUMENTS:
2459  *
2460  *      None
2461  *
2462  * SIDE EFFECTS:
2463  *
2464  *      None
2465  *
2466  */
2467 void __init SMC669_Init ( int index )
2468 {
2469     SMC37c669_CONFIG_REGS *SMC_base;
2470     unsigned long flags;
2471 
2472     local_irq_save(flags);
2473     if ( ( SMC_base = SMC37c669_detect( index ) ) != NULL ) {
2474 #if SMC_DEBUG
2475         SMC37c669_config_mode( TRUE );
2476         SMC37c669_dump_registers( );
2477         SMC37c669_config_mode( FALSE );
2478         SMC37c669_display_device_info( );
2479 #endif
2480         SMC37c669_disable_device( SERIAL_0 );
2481         SMC37c669_configure_device(
2482             SERIAL_0,
2483             COM1_BASE,
2484             COM1_IRQ,
2485             -1
2486         );
2487         SMC37c669_enable_device( SERIAL_0 );
2488 
2489         SMC37c669_disable_device( SERIAL_1 );
2490         SMC37c669_configure_device(
2491             SERIAL_1,
2492             COM2_BASE,
2493             COM2_IRQ,
2494             -1
2495         );
2496         SMC37c669_enable_device( SERIAL_1 );
2497 
2498         SMC37c669_disable_device( PARALLEL_0 );
2499         SMC37c669_configure_device(
2500             PARALLEL_0,
2501             PARP_BASE,
2502             PARP_IRQ,
2503             PARP_DRQ
2504         );
2505         SMC37c669_enable_device( PARALLEL_0 );
2506 
2507         SMC37c669_disable_device( FLOPPY_0 );
2508         SMC37c669_configure_device(
2509             FLOPPY_0,
2510             FDC_BASE,
2511             FDC_IRQ,
2512             FDC_DRQ
2513         );
2514         SMC37c669_enable_device( FLOPPY_0 );
2515           
2516         /* Wake up sometimes forgotten floppy, especially on DP264. */
2517         outb(0xc, 0x3f2);
2518 
2519         SMC37c669_disable_device( IDE_0 );
2520 
2521 #if SMC_DEBUG
2522         SMC37c669_config_mode( TRUE );
2523         SMC37c669_dump_registers( );
2524         SMC37c669_config_mode( FALSE );
2525         SMC37c669_display_device_info( );
2526 #endif
2527         local_irq_restore(flags);
2528         printk( "SMC37c669 Super I/O Controller found @ 0x%p\n",
2529                 SMC_base );
2530     }
2531     else {
2532         local_irq_restore(flags);
2533 #if SMC_DEBUG
2534         printk( "No SMC37c669 Super I/O Controller found\n" );
2535 #endif
2536     }
2537 }

/* [<][>][^][v][top][bottom][index][help] */