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