FILE
smc37c669.c
File preview with syntax highlighting.
linux-6.19.14/arch/alpha/kernel/smc37c669.c
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#include "proto.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 938#ifndef TRUE 939#define TRUE 1 940#endif 941#ifndef FALSE 942#define FALSE 0 943#endif 944 945#define wb( _x_, _y_ ) outb( _y_, (unsigned int)((unsigned long)_x_) ) 946#define rb( _x_ ) inb( (unsigned int)((unsigned long)_x_) ) 947 948/* 949** Local storage for device configuration information. 950** 951** Since the SMC37c669 does not provide an explicit 952** mechanism for enabling/disabling individual device 953** functions, other than unmapping the device, local 954** storage for device configuration information is 955** allocated here for use in implementing our own 956** function enable/disable scheme. 957*/ 958static struct DEVICE_CONFIG { 959 unsigned int port1; 960 unsigned int port2; 961 int irq; 962 int drq; 963} local_config [NUM_FUNCS]; 964 965/* 966** List of all possible addresses for the Super I/O chip 967*/ 968static unsigned long SMC37c669_Addresses[] __initdata = 969 { 970 0x3F0UL, /* Primary address */ 971 0x370UL, /* Secondary address */ 972 0UL /* End of list */ 973 }; 974 975/* 976** Global Pointer to the Super I/O device 977*/ 978static SMC37c669_CONFIG_REGS *SMC37c669 __initdata = NULL; 979 980/* 981** IRQ Translation Table 982** 983** The IRQ translation table is a list of SMC37c669 device 984** and standard ISA IRQs. 985** 986*/ 987static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_table __initdata; 988 989/* 990** The following definition is for the default IRQ 991** translation table. 992*/ 993static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_default_irq_table[] 994__initdata = 995 { 996 { SMC37c669_DEVICE_IRQ_A, -1 }, 997 { SMC37c669_DEVICE_IRQ_B, -1 }, 998 { SMC37c669_DEVICE_IRQ_C, 7 }, 999 { SMC37c669_DEVICE_IRQ_D, 6 }, 1000 { SMC37c669_DEVICE_IRQ_E, 4 }, 1001 { SMC37c669_DEVICE_IRQ_F, 3 }, 1002 { SMC37c669_DEVICE_IRQ_H, -1 }, 1003 { -1, -1 } /* End of table */ 1004 }; 1005 1006/* 1007** The following definition is for the MONET (XP1000) IRQ 1008** translation table. 1009*/ 1010static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_monet_irq_table[] 1011__initdata = 1012 { 1013 { SMC37c669_DEVICE_IRQ_A, -1 }, 1014 { SMC37c669_DEVICE_IRQ_B, -1 }, 1015 { SMC37c669_DEVICE_IRQ_C, 6 }, 1016 { SMC37c669_DEVICE_IRQ_D, 7 }, 1017 { SMC37c669_DEVICE_IRQ_E, 4 }, 1018 { SMC37c669_DEVICE_IRQ_F, 3 }, 1019 { SMC37c669_DEVICE_IRQ_H, -1 }, 1020 { -1, -1 } /* End of table */ 1021 }; 1022 1023static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_tables[] __initdata = 1024 { 1025 SMC37c669_default_irq_table, 1026 SMC37c669_monet_irq_table 1027 }; 1028 1029/* 1030** DRQ Translation Table 1031** 1032** The DRQ translation table is a list of SMC37c669 device and 1033** ISA DMA channels. 1034** 1035*/ 1036static SMC37c669_DRQ_TRANSLATION_ENTRY *SMC37c669_drq_table __initdata; 1037 1038/* 1039** The following definition is the default DRQ 1040** translation table. 1041*/ 1042static SMC37c669_DRQ_TRANSLATION_ENTRY SMC37c669_default_drq_table[] 1043__initdata = 1044 { 1045 { SMC37c669_DEVICE_DRQ_A, 2 }, 1046 { SMC37c669_DEVICE_DRQ_B, 3 }, 1047 { SMC37c669_DEVICE_DRQ_C, -1 }, 1048 { -1, -1 } /* End of table */ 1049 }; 1050 1051/* 1052** Local Function Prototype Declarations 1053*/ 1054 1055static unsigned int SMC37c669_is_device_enabled( 1056 unsigned int func 1057); 1058 1059#if 0 1060static unsigned int SMC37c669_get_device_config( 1061 unsigned int func, 1062 int *port, 1063 int *irq, 1064 int *drq 1065); 1066#endif 1067 1068static void SMC37c669_config_mode( 1069 unsigned int enable 1070); 1071 1072static unsigned char SMC37c669_read_config( 1073 unsigned char index 1074); 1075 1076static void SMC37c669_write_config( 1077 unsigned char index, 1078 unsigned char data 1079); 1080 1081static void SMC37c669_init_local_config( void ); 1082 1083static struct DEVICE_CONFIG *SMC37c669_get_config( 1084 unsigned int func 1085); 1086 1087static int SMC37c669_xlate_irq( 1088 int irq 1089); 1090 1091static int SMC37c669_xlate_drq( 1092 int drq 1093); 1094 1095static __cacheline_aligned DEFINE_SPINLOCK(smc_lock); 1096 1097/* 1098**++ 1099** FUNCTIONAL DESCRIPTION: 1100** 1101** This function detects the presence of an SMC37c669 Super I/O 1102** controller. 1103** 1104** FORMAL PARAMETERS: 1105** 1106** None 1107** 1108** RETURN VALUE: 1109** 1110** Returns a pointer to the device if found, otherwise, 1111** the NULL pointer is returned. 1112** 1113** SIDE EFFECTS: 1114** 1115** None 1116** 1117**-- 1118*/ 1119SMC37c669_CONFIG_REGS * __init SMC37c669_detect( int index ) 1120{ 1121 int i; 1122 SMC37c669_DEVICE_ID_REGISTER id; 1123 1124 for ( i = 0; SMC37c669_Addresses[i] != 0; i++ ) { 1125/* 1126** Initialize the device pointer even though we don't yet know if 1127** the controller is at this address. The support functions access 1128** the controller through this device pointer so we need to set it 1129** even when we are looking ... 1130*/ 1131 SMC37c669 = ( SMC37c669_CONFIG_REGS * )SMC37c669_Addresses[i]; 1132/* 1133** Enter configuration mode 1134*/ 1135 SMC37c669_config_mode( TRUE ); 1136/* 1137** Read the device id 1138*/ 1139 id.as_uchar = SMC37c669_read_config( SMC37c669_DEVICE_ID_INDEX ); 1140/* 1141** Exit configuration mode 1142*/ 1143 SMC37c669_config_mode( FALSE ); 1144/* 1145** Does the device id match? If so, assume we have found an 1146** SMC37c669 controller at this address. 1147*/ 1148 if ( id.by_field.device_id == SMC37c669_DEVICE_ID ) { 1149/* 1150** Initialize the IRQ and DRQ translation tables. 1151*/ 1152 SMC37c669_irq_table = SMC37c669_irq_tables[ index ]; 1153 SMC37c669_drq_table = SMC37c669_default_drq_table; 1154/* 1155** erfix 1156** 1157** If the platform can't use the IRQ and DRQ defaults set up in this 1158** file, it should call a platform-specific external routine at this 1159** point to reset the IRQ and DRQ translation table pointers to point 1160** at the appropriate tables for the platform. If the defaults are 1161** acceptable, then the external routine should do nothing. 1162*/ 1163 1164/* 1165** Put the chip back into configuration mode 1166*/ 1167 SMC37c669_config_mode( TRUE ); 1168/* 1169** Initialize local storage for configuration information 1170*/ 1171 SMC37c669_init_local_config( ); 1172/* 1173** Exit configuration mode 1174*/ 1175 SMC37c669_config_mode( FALSE ); 1176/* 1177** SMC37c669 controller found, break out of search loop 1178*/ 1179 break; 1180 } 1181 else { 1182/* 1183** Otherwise, we did not find an SMC37c669 controller at this 1184** address so set the device pointer to NULL. 1185*/ 1186 SMC37c669 = NULL; 1187 } 1188 } 1189 return SMC37c669; 1190} 1191 1192 1193/* 1194**++ 1195** FUNCTIONAL DESCRIPTION: 1196** 1197** This function enables an SMC37c669 device function. 1198** 1199** FORMAL PARAMETERS: 1200** 1201** func: 1202** Which device function to enable 1203** 1204** RETURN VALUE: 1205** 1206** Returns TRUE is the device function was enabled, otherwise, FALSE 1207** 1208** SIDE EFFECTS: 1209** 1210** {@description or none@} 1211** 1212** DESIGN: 1213** 1214** Enabling a device function in the SMC37c669 controller involves 1215** setting all of its mappings (port, irq, drq ...). A local 1216** "shadow" copy of the device configuration is kept so we can 1217** just set each mapping to what the local copy says. 1218** 1219** This function ALWAYS updates the local shadow configuration of 1220** the device function being enabled, even if the device is always 1221** enabled. To avoid replication of code, functions such as 1222** configure_device set up the local copy and then call this 1223** function to the update the real device. 1224** 1225**-- 1226*/ 1227unsigned int __init SMC37c669_enable_device ( unsigned int func ) 1228{ 1229 unsigned int ret_val = FALSE; 1230/* 1231** Put the device into configuration mode 1232*/ 1233 SMC37c669_config_mode( TRUE ); 1234 switch ( func ) { 1235 case SERIAL_0: 1236 { 1237 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr; 1238 SMC37c669_SERIAL_IRQ_REGISTER irq; 1239/* 1240** Enable the serial 1 IRQ mapping 1241*/ 1242 irq.as_uchar = 1243 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); 1244 1245 irq.by_field.uart1_irq = 1246 SMC37c669_RAW_DEVICE_IRQ( 1247 SMC37c669_xlate_irq( local_config[ func ].irq ) 1248 ); 1249 1250 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar ); 1251/* 1252** Enable the serial 1 port base address mapping 1253*/ 1254 base_addr.as_uchar = 0; 1255 base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3; 1256 1257 SMC37c669_write_config( 1258 SMC37c669_SERIAL0_BASE_ADDRESS_INDEX, 1259 base_addr.as_uchar 1260 ); 1261 ret_val = TRUE; 1262 break; 1263 } 1264 case SERIAL_1: 1265 { 1266 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr; 1267 SMC37c669_SERIAL_IRQ_REGISTER irq; 1268/* 1269** Enable the serial 2 IRQ mapping 1270*/ 1271 irq.as_uchar = 1272 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); 1273 1274 irq.by_field.uart2_irq = 1275 SMC37c669_RAW_DEVICE_IRQ( 1276 SMC37c669_xlate_irq( local_config[ func ].irq ) 1277 ); 1278 1279 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar ); 1280/* 1281** Enable the serial 2 port base address mapping 1282*/ 1283 base_addr.as_uchar = 0; 1284 base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3; 1285 1286 SMC37c669_write_config( 1287 SMC37c669_SERIAL1_BASE_ADDRESS_INDEX, 1288 base_addr.as_uchar 1289 ); 1290 ret_val = TRUE; 1291 break; 1292 } 1293 case PARALLEL_0: 1294 { 1295 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr; 1296 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq; 1297 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq; 1298/* 1299** Enable the parallel port DMA channel mapping 1300*/ 1301 drq.as_uchar = 1302 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); 1303 1304 drq.by_field.ppt_drq = 1305 SMC37c669_RAW_DEVICE_DRQ( 1306 SMC37c669_xlate_drq( local_config[ func ].drq ) 1307 ); 1308 1309 SMC37c669_write_config( 1310 SMC37c669_PARALLEL_FDC_DRQ_INDEX, 1311 drq.as_uchar 1312 ); 1313/* 1314** Enable the parallel port IRQ mapping 1315*/ 1316 irq.as_uchar = 1317 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); 1318 1319 irq.by_field.ppt_irq = 1320 SMC37c669_RAW_DEVICE_IRQ( 1321 SMC37c669_xlate_irq( local_config[ func ].irq ) 1322 ); 1323 1324 SMC37c669_write_config( 1325 SMC37c669_PARALLEL_FDC_IRQ_INDEX, 1326 irq.as_uchar 1327 ); 1328/* 1329** Enable the parallel port base address mapping 1330*/ 1331 base_addr.as_uchar = 0; 1332 base_addr.by_field.addr9_2 = local_config[ func ].port1 >> 2; 1333 1334 SMC37c669_write_config( 1335 SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX, 1336 base_addr.as_uchar 1337 ); 1338 ret_val = TRUE; 1339 break; 1340 } 1341 case FLOPPY_0: 1342 { 1343 SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr; 1344 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq; 1345 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq; 1346/* 1347** Enable the floppy controller DMA channel mapping 1348*/ 1349 drq.as_uchar = 1350 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); 1351 1352 drq.by_field.fdc_drq = 1353 SMC37c669_RAW_DEVICE_DRQ( 1354 SMC37c669_xlate_drq( local_config[ func ].drq ) 1355 ); 1356 1357 SMC37c669_write_config( 1358 SMC37c669_PARALLEL_FDC_DRQ_INDEX, 1359 drq.as_uchar 1360 ); 1361/* 1362** Enable the floppy controller IRQ mapping 1363*/ 1364 irq.as_uchar = 1365 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); 1366 1367 irq.by_field.fdc_irq = 1368 SMC37c669_RAW_DEVICE_IRQ( 1369 SMC37c669_xlate_irq( local_config[ func ].irq ) 1370 ); 1371 1372 SMC37c669_write_config( 1373 SMC37c669_PARALLEL_FDC_IRQ_INDEX, 1374 irq.as_uchar 1375 ); 1376/* 1377** Enable the floppy controller base address mapping 1378*/ 1379 base_addr.as_uchar = 0; 1380 base_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4; 1381 1382 SMC37c669_write_config( 1383 SMC37c669_FDC_BASE_ADDRESS_INDEX, 1384 base_addr.as_uchar 1385 ); 1386 ret_val = TRUE; 1387 break; 1388 } 1389 case IDE_0: 1390 { 1391 SMC37c669_IDE_ADDRESS_REGISTER ide_addr; 1392/* 1393** Enable the IDE alternate status base address mapping 1394*/ 1395 ide_addr.as_uchar = 0; 1396 ide_addr.by_field.addr9_4 = local_config[ func ].port2 >> 4; 1397 1398 SMC37c669_write_config( 1399 SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX, 1400 ide_addr.as_uchar 1401 ); 1402/* 1403** Enable the IDE controller base address mapping 1404*/ 1405 ide_addr.as_uchar = 0; 1406 ide_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4; 1407 1408 SMC37c669_write_config( 1409 SMC37c669_IDE_BASE_ADDRESS_INDEX, 1410 ide_addr.as_uchar 1411 ); 1412 ret_val = TRUE; 1413 break; 1414 } 1415 } 1416/* 1417** Exit configuration mode and return 1418*/ 1419 SMC37c669_config_mode( FALSE ); 1420 1421 return ret_val; 1422} 1423 1424 1425/* 1426**++ 1427** FUNCTIONAL DESCRIPTION: 1428** 1429** This function disables a device function within the 1430** SMC37c669 Super I/O controller. 1431** 1432** FORMAL PARAMETERS: 1433** 1434** func: 1435** Which function to disable 1436** 1437** RETURN VALUE: 1438** 1439** Return TRUE if the device function was disabled, otherwise, FALSE 1440** 1441** SIDE EFFECTS: 1442** 1443** {@description or none@} 1444** 1445** DESIGN: 1446** 1447** Disabling a function in the SMC37c669 device involves 1448** disabling all the function's mappings (port, irq, drq ...). 1449** A shadow copy of the device configuration is maintained 1450** in local storage so we won't worry aboving saving the 1451** current configuration information. 1452** 1453**-- 1454*/ 1455unsigned int __init SMC37c669_disable_device ( unsigned int func ) 1456{ 1457 unsigned int ret_val = FALSE; 1458 1459/* 1460** Put the device into configuration mode 1461*/ 1462 SMC37c669_config_mode( TRUE ); 1463 switch ( func ) { 1464 case SERIAL_0: 1465 { 1466 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr; 1467 SMC37c669_SERIAL_IRQ_REGISTER irq; 1468/* 1469** Disable the serial 1 IRQ mapping 1470*/ 1471 irq.as_uchar = 1472 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); 1473 1474 irq.by_field.uart1_irq = 0; 1475 1476 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar ); 1477/* 1478** Disable the serial 1 port base address mapping 1479*/ 1480 base_addr.as_uchar = 0; 1481 SMC37c669_write_config( 1482 SMC37c669_SERIAL0_BASE_ADDRESS_INDEX, 1483 base_addr.as_uchar 1484 ); 1485 ret_val = TRUE; 1486 break; 1487 } 1488 case SERIAL_1: 1489 { 1490 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr; 1491 SMC37c669_SERIAL_IRQ_REGISTER irq; 1492/* 1493** Disable the serial 2 IRQ mapping 1494*/ 1495 irq.as_uchar = 1496 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); 1497 1498 irq.by_field.uart2_irq = 0; 1499 1500 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar ); 1501/* 1502** Disable the serial 2 port base address mapping 1503*/ 1504 base_addr.as_uchar = 0; 1505 1506 SMC37c669_write_config( 1507 SMC37c669_SERIAL1_BASE_ADDRESS_INDEX, 1508 base_addr.as_uchar 1509 ); 1510 ret_val = TRUE; 1511 break; 1512 } 1513 case PARALLEL_0: 1514 { 1515 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr; 1516 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq; 1517 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq; 1518/* 1519** Disable the parallel port DMA channel mapping 1520*/ 1521 drq.as_uchar = 1522 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); 1523 1524 drq.by_field.ppt_drq = 0; 1525 1526 SMC37c669_write_config( 1527 SMC37c669_PARALLEL_FDC_DRQ_INDEX, 1528 drq.as_uchar 1529 ); 1530/* 1531** Disable the parallel port IRQ mapping 1532*/ 1533 irq.as_uchar = 1534 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); 1535 1536 irq.by_field.ppt_irq = 0; 1537 1538 SMC37c669_write_config( 1539 SMC37c669_PARALLEL_FDC_IRQ_INDEX, 1540 irq.as_uchar 1541 ); 1542/* 1543** Disable the parallel port base address mapping 1544*/ 1545 base_addr.as_uchar = 0; 1546 1547 SMC37c669_write_config( 1548 SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX, 1549 base_addr.as_uchar 1550 ); 1551 ret_val = TRUE; 1552 break; 1553 } 1554 case FLOPPY_0: 1555 { 1556 SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr; 1557 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq; 1558 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq; 1559/* 1560** Disable the floppy controller DMA channel mapping 1561*/ 1562 drq.as_uchar = 1563 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); 1564 1565 drq.by_field.fdc_drq = 0; 1566 1567 SMC37c669_write_config( 1568 SMC37c669_PARALLEL_FDC_DRQ_INDEX, 1569 drq.as_uchar 1570 ); 1571/* 1572** Disable the floppy controller IRQ mapping 1573*/ 1574 irq.as_uchar = 1575 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); 1576 1577 irq.by_field.fdc_irq = 0; 1578 1579 SMC37c669_write_config( 1580 SMC37c669_PARALLEL_FDC_IRQ_INDEX, 1581 irq.as_uchar 1582 ); 1583/* 1584** Disable the floppy controller base address mapping 1585*/ 1586 base_addr.as_uchar = 0; 1587 1588 SMC37c669_write_config( 1589 SMC37c669_FDC_BASE_ADDRESS_INDEX, 1590 base_addr.as_uchar 1591 ); 1592 ret_val = TRUE; 1593 break; 1594 } 1595 case IDE_0: 1596 { 1597 SMC37c669_IDE_ADDRESS_REGISTER ide_addr; 1598/* 1599** Disable the IDE alternate status base address mapping 1600*/ 1601 ide_addr.as_uchar = 0; 1602 1603 SMC37c669_write_config( 1604 SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX, 1605 ide_addr.as_uchar 1606 ); 1607/* 1608** Disable the IDE controller base address mapping 1609*/ 1610 ide_addr.as_uchar = 0; 1611 1612 SMC37c669_write_config( 1613 SMC37c669_IDE_BASE_ADDRESS_INDEX, 1614 ide_addr.as_uchar 1615 ); 1616 ret_val = TRUE; 1617 break; 1618 } 1619 } 1620/* 1621** Exit configuration mode and return 1622*/ 1623 SMC37c669_config_mode( FALSE ); 1624 1625 return ret_val; 1626} 1627 1628 1629/* 1630**++ 1631** FUNCTIONAL DESCRIPTION: 1632** 1633** This function configures a device function within the 1634** SMC37c669 Super I/O controller. 1635** 1636** FORMAL PARAMETERS: 1637** 1638** func: 1639** Which device function 1640** 1641** port: 1642** I/O port for the function to use 1643** 1644** irq: 1645** IRQ for the device function to use 1646** 1647** drq: 1648** DMA channel for the device function to use 1649** 1650** RETURN VALUE: 1651** 1652** Returns TRUE if the device function was configured, 1653** otherwise, FALSE. 1654** 1655** SIDE EFFECTS: 1656** 1657** {@description or none@} 1658** 1659** DESIGN: 1660** 1661** If this function returns TRUE, the local shadow copy of 1662** the configuration is also updated. If the device function 1663** is currently disabled, only the local shadow copy is 1664** updated and the actual device function will be updated 1665** if/when it is enabled. 1666** 1667**-- 1668*/ 1669unsigned int __init SMC37c669_configure_device ( 1670 unsigned int func, 1671 int port, 1672 int irq, 1673 int drq ) 1674{ 1675 struct DEVICE_CONFIG *cp; 1676 1677/* 1678** Check for a valid configuration 1679*/ 1680 if ( ( cp = SMC37c669_get_config ( func ) ) != NULL ) { 1681/* 1682** Configuration is valid, update the local shadow copy 1683*/ 1684 if ( ( drq & ~0xFF ) == 0 ) { 1685 cp->drq = drq; 1686 } 1687 if ( ( irq & ~0xFF ) == 0 ) { 1688 cp->irq = irq; 1689 } 1690 if ( ( port & ~0xFFFF ) == 0 ) { 1691 cp->port1 = port; 1692 } 1693/* 1694** If the device function is enabled, update the actual 1695** device configuration. 1696*/ 1697 if ( SMC37c669_is_device_enabled( func ) ) { 1698 SMC37c669_enable_device( func ); 1699 } 1700 return TRUE; 1701 } 1702 return FALSE; 1703} 1704 1705 1706/* 1707**++ 1708** FUNCTIONAL DESCRIPTION: 1709** 1710** This function determines whether a device function 1711** within the SMC37c669 controller is enabled. 1712** 1713** FORMAL PARAMETERS: 1714** 1715** func: 1716** Which device function 1717** 1718** RETURN VALUE: 1719** 1720** Returns TRUE if the device function is enabled, otherwise, FALSE 1721** 1722** SIDE EFFECTS: 1723** 1724** {@description or none@} 1725** 1726** DESIGN: 1727** 1728** To check whether a device is enabled we will only look at 1729** the port base address mapping. According to the SMC37c669 1730** specification, all of the port base address mappings are 1731** disabled if the addr<9:8> (bits <7:6> of the register) are 1732** zero. 1733** 1734**-- 1735*/ 1736static unsigned int __init SMC37c669_is_device_enabled ( unsigned int func ) 1737{ 1738 unsigned char base_addr = 0; 1739 unsigned int dev_ok = FALSE; 1740 unsigned int ret_val = FALSE; 1741/* 1742** Enter configuration mode 1743*/ 1744 SMC37c669_config_mode( TRUE ); 1745 1746 switch ( func ) { 1747 case SERIAL_0: 1748 base_addr = 1749 SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX ); 1750 dev_ok = TRUE; 1751 break; 1752 case SERIAL_1: 1753 base_addr = 1754 SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX ); 1755 dev_ok = TRUE; 1756 break; 1757 case PARALLEL_0: 1758 base_addr = 1759 SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX ); 1760 dev_ok = TRUE; 1761 break; 1762 case FLOPPY_0: 1763 base_addr = 1764 SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX ); 1765 dev_ok = TRUE; 1766 break; 1767 case IDE_0: 1768 base_addr = 1769 SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX ); 1770 dev_ok = TRUE; 1771 break; 1772 } 1773/* 1774** If we have a valid device, check base_addr<7:6> to see if the 1775** device is enabled (mapped). 1776*/ 1777 if ( ( dev_ok ) && ( ( base_addr & 0xC0 ) != 0 ) ) { 1778/* 1779** The mapping is not disabled, so assume that the function is 1780** enabled. 1781*/ 1782 ret_val = TRUE; 1783 } 1784/* 1785** Exit configuration mode 1786*/ 1787 SMC37c669_config_mode( FALSE ); 1788 1789 return ret_val; 1790} 1791 1792 1793#if 0 1794/* 1795**++ 1796** FUNCTIONAL DESCRIPTION: 1797** 1798** This function retrieves the configuration information of a 1799** device function within the SMC37c699 Super I/O controller. 1800** 1801** FORMAL PARAMETERS: 1802** 1803** func: 1804** Which device function 1805** 1806** port: 1807** I/O port returned 1808** 1809** irq: 1810** IRQ returned 1811** 1812** drq: 1813** DMA channel returned 1814** 1815** RETURN VALUE: 1816** 1817** Returns TRUE if the device configuration was successfully 1818** retrieved, otherwise, FALSE. 1819** 1820** SIDE EFFECTS: 1821** 1822** The data pointed to by the port, irq, and drq parameters 1823** my be modified even if the configuration is not successfully 1824** retrieved. 1825** 1826** DESIGN: 1827** 1828** The device configuration is fetched from the local shadow 1829** copy. Any unused parameters will be set to -1. Any 1830** parameter which is not desired can specify the NULL 1831** pointer. 1832** 1833**-- 1834*/ 1835static unsigned int __init SMC37c669_get_device_config ( 1836 unsigned int func, 1837 int *port, 1838 int *irq, 1839 int *drq ) 1840{ 1841 struct DEVICE_CONFIG *cp; 1842 unsigned int ret_val = FALSE; 1843/* 1844** Check for a valid device configuration 1845*/ 1846 if ( ( cp = SMC37c669_get_config( func ) ) != NULL ) { 1847 if ( drq != NULL ) { 1848 *drq = cp->drq; 1849 ret_val = TRUE; 1850 } 1851 if ( irq != NULL ) { 1852 *irq = cp->irq; 1853 ret_val = TRUE; 1854 } 1855 if ( port != NULL ) { 1856 *port = cp->port1; 1857 ret_val = TRUE; 1858 } 1859 } 1860 return ret_val; 1861} 1862#endif 1863 1864 1865/* 1866**++ 1867** FUNCTIONAL DESCRIPTION: 1868** 1869** This function displays the current state of the SMC37c699 1870** Super I/O controller's device functions. 1871** 1872** FORMAL PARAMETERS: 1873** 1874** None 1875** 1876** RETURN VALUE: 1877** 1878** None 1879** 1880** SIDE EFFECTS: 1881** 1882** None 1883** 1884**-- 1885*/ 1886void __init SMC37c669_display_device_info ( void ) 1887{ 1888 if ( SMC37c669_is_device_enabled( SERIAL_0 ) ) { 1889 printk( " Serial 0: Enabled [ Port 0x%x, IRQ %d ]\n", 1890 local_config[ SERIAL_0 ].port1, 1891 local_config[ SERIAL_0 ].irq 1892 ); 1893 } 1894 else { 1895 printk( " Serial 0: Disabled\n" ); 1896 } 1897 1898 if ( SMC37c669_is_device_enabled( SERIAL_1 ) ) { 1899 printk( " Serial 1: Enabled [ Port 0x%x, IRQ %d ]\n", 1900 local_config[ SERIAL_1 ].port1, 1901 local_config[ SERIAL_1 ].irq 1902 ); 1903 } 1904 else { 1905 printk( " Serial 1: Disabled\n" ); 1906 } 1907 1908 if ( SMC37c669_is_device_enabled( PARALLEL_0 ) ) { 1909 printk( " Parallel: Enabled [ Port 0x%x, IRQ %d/%d ]\n", 1910 local_config[ PARALLEL_0 ].port1, 1911 local_config[ PARALLEL_0 ].irq, 1912 local_config[ PARALLEL_0 ].drq 1913 ); 1914 } 1915 else { 1916 printk( " Parallel: Disabled\n" ); 1917 } 1918 1919 if ( SMC37c669_is_device_enabled( FLOPPY_0 ) ) { 1920 printk( " Floppy Ctrl: Enabled [ Port 0x%x, IRQ %d/%d ]\n", 1921 local_config[ FLOPPY_0 ].port1, 1922 local_config[ FLOPPY_0 ].irq, 1923 local_config[ FLOPPY_0 ].drq 1924 ); 1925 } 1926 else { 1927 printk( " Floppy Ctrl: Disabled\n" ); 1928 } 1929 1930 if ( SMC37c669_is_device_enabled( IDE_0 ) ) { 1931 printk( " IDE 0: Enabled [ Port 0x%x, IRQ %d ]\n", 1932 local_config[ IDE_0 ].port1, 1933 local_config[ IDE_0 ].irq 1934 ); 1935 } 1936 else { 1937 printk( " IDE 0: Disabled\n" ); 1938 } 1939} 1940 1941 1942/* 1943**++ 1944** FUNCTIONAL DESCRIPTION: 1945** 1946** This function puts the SMC37c669 Super I/O controller into, 1947** and takes it out of, configuration mode. 1948** 1949** FORMAL PARAMETERS: 1950** 1951** enable: 1952** TRUE to enter configuration mode, FALSE to exit. 1953** 1954** RETURN VALUE: 1955** 1956** None 1957** 1958** SIDE EFFECTS: 1959** 1960** The SMC37c669 controller may be left in configuration mode. 1961** 1962**-- 1963*/ 1964static void __init SMC37c669_config_mode( 1965 unsigned int enable ) 1966{ 1967 if ( enable ) { 1968/* 1969** To enter configuration mode, two writes in succession to the index 1970** port are required. If a write to another address or port occurs 1971** between these two writes, the chip does not enter configuration 1972** mode. Therefore, a spinlock is placed around the two writes to 1973** guarantee that they complete uninterrupted. 1974*/ 1975 spin_lock(&smc_lock); 1976 wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY ); 1977 wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY ); 1978 spin_unlock(&smc_lock); 1979 } 1980 else { 1981 wb( &SMC37c669->index_port, SMC37c669_CONFIG_OFF_KEY ); 1982 } 1983} 1984 1985/* 1986**++ 1987** FUNCTIONAL DESCRIPTION: 1988** 1989** This function reads an SMC37c669 Super I/O controller 1990** configuration register. This function assumes that the 1991** device is already in configuration mode. 1992** 1993** FORMAL PARAMETERS: 1994** 1995** index: 1996** Index value of configuration register to read 1997** 1998** RETURN VALUE: 1999** 2000** Data read from configuration register 2001** 2002** SIDE EFFECTS: 2003** 2004** None 2005** 2006**-- 2007*/ 2008static unsigned char __init SMC37c669_read_config( 2009 unsigned char index ) 2010{ 2011 wb(&SMC37c669->index_port, index); 2012 return rb(&SMC37c669->data_port); 2013} 2014 2015/* 2016**++ 2017** FUNCTIONAL DESCRIPTION: 2018** 2019** This function writes an SMC37c669 Super I/O controller 2020** configuration register. This function assumes that the 2021** device is already in configuration mode. 2022** 2023** FORMAL PARAMETERS: 2024** 2025** index: 2026** Index of configuration register to write 2027** 2028** data: 2029** Data to be written 2030** 2031** RETURN VALUE: 2032** 2033** None 2034** 2035** SIDE EFFECTS: 2036** 2037** None 2038** 2039**-- 2040*/ 2041static void __init SMC37c669_write_config( 2042 unsigned char index, 2043 unsigned char data ) 2044{ 2045 wb( &SMC37c669->index_port, index ); 2046 wb( &SMC37c669->data_port, data ); 2047} 2048 2049 2050/* 2051**++ 2052** FUNCTIONAL DESCRIPTION: 2053** 2054** This function initializes the local device 2055** configuration storage. This function assumes 2056** that the device is already in configuration 2057** mode. 2058** 2059** FORMAL PARAMETERS: 2060** 2061** None 2062** 2063** RETURN VALUE: 2064** 2065** None 2066** 2067** SIDE EFFECTS: 2068** 2069** Local storage for device configuration information 2070** is initialized. 2071** 2072**-- 2073*/ 2074static void __init SMC37c669_init_local_config ( void ) 2075{ 2076 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER uart_base; 2077 SMC37c669_SERIAL_IRQ_REGISTER uart_irqs; 2078 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER ppt_base; 2079 SMC37c669_PARALLEL_FDC_IRQ_REGISTER ppt_fdc_irqs; 2080 SMC37c669_PARALLEL_FDC_DRQ_REGISTER ppt_fdc_drqs; 2081 SMC37c669_FDC_BASE_ADDRESS_REGISTER fdc_base; 2082 SMC37c669_IDE_ADDRESS_REGISTER ide_base; 2083 SMC37c669_IDE_ADDRESS_REGISTER ide_alt; 2084 2085/* 2086** Get serial port 1 base address 2087*/ 2088 uart_base.as_uchar = 2089 SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX ); 2090/* 2091** Get IRQs for serial ports 1 & 2 2092*/ 2093 uart_irqs.as_uchar = 2094 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); 2095/* 2096** Store local configuration information for serial port 1 2097*/ 2098 local_config[SERIAL_0].port1 = uart_base.by_field.addr9_3 << 3; 2099 local_config[SERIAL_0].irq = 2100 SMC37c669_xlate_irq( 2101 SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart1_irq ) 2102 ); 2103/* 2104** Get serial port 2 base address 2105*/ 2106 uart_base.as_uchar = 2107 SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX ); 2108/* 2109** Store local configuration information for serial port 2 2110*/ 2111 local_config[SERIAL_1].port1 = uart_base.by_field.addr9_3 << 3; 2112 local_config[SERIAL_1].irq = 2113 SMC37c669_xlate_irq( 2114 SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart2_irq ) 2115 ); 2116/* 2117** Get parallel port base address 2118*/ 2119 ppt_base.as_uchar = 2120 SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX ); 2121/* 2122** Get IRQs for parallel port and floppy controller 2123*/ 2124 ppt_fdc_irqs.as_uchar = 2125 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); 2126/* 2127** Get DRQs for parallel port and floppy controller 2128*/ 2129 ppt_fdc_drqs.as_uchar = 2130 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); 2131/* 2132** Store local configuration information for parallel port 2133*/ 2134 local_config[PARALLEL_0].port1 = ppt_base.by_field.addr9_2 << 2; 2135 local_config[PARALLEL_0].irq = 2136 SMC37c669_xlate_irq( 2137 SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.ppt_irq ) 2138 ); 2139 local_config[PARALLEL_0].drq = 2140 SMC37c669_xlate_drq( 2141 SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.ppt_drq ) 2142 ); 2143/* 2144** Get floppy controller base address 2145*/ 2146 fdc_base.as_uchar = 2147 SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX ); 2148/* 2149** Store local configuration information for floppy controller 2150*/ 2151 local_config[FLOPPY_0].port1 = fdc_base.by_field.addr9_4 << 4; 2152 local_config[FLOPPY_0].irq = 2153 SMC37c669_xlate_irq( 2154 SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.fdc_irq ) 2155 ); 2156 local_config[FLOPPY_0].drq = 2157 SMC37c669_xlate_drq( 2158 SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.fdc_drq ) 2159 ); 2160/* 2161** Get IDE controller base address 2162*/ 2163 ide_base.as_uchar = 2164 SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX ); 2165/* 2166** Get IDE alternate status base address 2167*/ 2168 ide_alt.as_uchar = 2169 SMC37c669_read_config( SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX ); 2170/* 2171** Store local configuration information for IDE controller 2172*/ 2173 local_config[IDE_0].port1 = ide_base.by_field.addr9_4 << 4; 2174 local_config[IDE_0].port2 = ide_alt.by_field.addr9_4 << 4; 2175 local_config[IDE_0].irq = 14; 2176} 2177 2178 2179/* 2180**++ 2181** FUNCTIONAL DESCRIPTION: 2182** 2183** This function returns a pointer to the local shadow 2184** configuration of the requested device function. 2185** 2186** FORMAL PARAMETERS: 2187** 2188** func: 2189** Which device function 2190** 2191** RETURN VALUE: 2192** 2193** Returns a pointer to the DEVICE_CONFIG structure for the 2194** requested function, otherwise, NULL. 2195** 2196** SIDE EFFECTS: 2197** 2198** {@description or none@} 2199** 2200**-- 2201*/ 2202static struct DEVICE_CONFIG * __init SMC37c669_get_config( unsigned int func ) 2203{ 2204 struct DEVICE_CONFIG *cp = NULL; 2205 2206 switch ( func ) { 2207 case SERIAL_0: 2208 cp = &local_config[ SERIAL_0 ]; 2209 break; 2210 case SERIAL_1: 2211 cp = &local_config[ SERIAL_1 ]; 2212 break; 2213 case PARALLEL_0: 2214 cp = &local_config[ PARALLEL_0 ]; 2215 break; 2216 case FLOPPY_0: 2217 cp = &local_config[ FLOPPY_0 ]; 2218 break; 2219 case IDE_0: 2220 cp = &local_config[ IDE_0 ]; 2221 break; 2222 } 2223 return cp; 2224} 2225 2226/* 2227**++ 2228** FUNCTIONAL DESCRIPTION: 2229** 2230** This function translates IRQs back and forth between ISA 2231** IRQs and SMC37c669 device IRQs. 2232** 2233** FORMAL PARAMETERS: 2234** 2235** irq: 2236** The IRQ to translate 2237** 2238** RETURN VALUE: 2239** 2240** Returns the translated IRQ, otherwise, returns -1. 2241** 2242** SIDE EFFECTS: 2243** 2244** {@description or none@} 2245** 2246**-- 2247*/ 2248static int __init SMC37c669_xlate_irq ( int irq ) 2249{ 2250 int i, translated_irq = -1; 2251 2252 if ( SMC37c669_IS_DEVICE_IRQ( irq ) ) { 2253/* 2254** We are translating a device IRQ to an ISA IRQ 2255*/ 2256 for ( i = 0; ( SMC37c669_irq_table[i].device_irq != -1 ) || ( SMC37c669_irq_table[i].isa_irq != -1 ); i++ ) { 2257 if ( irq == SMC37c669_irq_table[i].device_irq ) { 2258 translated_irq = SMC37c669_irq_table[i].isa_irq; 2259 break; 2260 } 2261 } 2262 } 2263 else { 2264/* 2265** We are translating an ISA IRQ to a device IRQ 2266*/ 2267 for ( i = 0; ( SMC37c669_irq_table[i].isa_irq != -1 ) || ( SMC37c669_irq_table[i].device_irq != -1 ); i++ ) { 2268 if ( irq == SMC37c669_irq_table[i].isa_irq ) { 2269 translated_irq = SMC37c669_irq_table[i].device_irq; 2270 break; 2271 } 2272 } 2273 } 2274 return translated_irq; 2275} 2276 2277 2278/* 2279**++ 2280** FUNCTIONAL DESCRIPTION: 2281** 2282** This function translates DMA channels back and forth between 2283** ISA DMA channels and SMC37c669 device DMA channels. 2284** 2285** FORMAL PARAMETERS: 2286** 2287** drq: 2288** The DMA channel to translate 2289** 2290** RETURN VALUE: 2291** 2292** Returns the translated DMA channel, otherwise, returns -1 2293** 2294** SIDE EFFECTS: 2295** 2296** {@description or none@} 2297** 2298**-- 2299*/ 2300static int __init SMC37c669_xlate_drq ( int drq ) 2301{ 2302 int i, translated_drq = -1; 2303 2304 if ( SMC37c669_IS_DEVICE_DRQ( drq ) ) { 2305/* 2306** We are translating a device DMA channel to an ISA DMA channel 2307*/ 2308 for ( i = 0; ( SMC37c669_drq_table[i].device_drq != -1 ) || ( SMC37c669_drq_table[i].isa_drq != -1 ); i++ ) { 2309 if ( drq == SMC37c669_drq_table[i].device_drq ) { 2310 translated_drq = SMC37c669_drq_table[i].isa_drq; 2311 break; 2312 } 2313 } 2314 } 2315 else { 2316/* 2317** We are translating an ISA DMA channel to a device DMA channel 2318*/ 2319 for ( i = 0; ( SMC37c669_drq_table[i].isa_drq != -1 ) || ( SMC37c669_drq_table[i].device_drq != -1 ); i++ ) { 2320 if ( drq == SMC37c669_drq_table[i].isa_drq ) { 2321 translated_drq = SMC37c669_drq_table[i].device_drq; 2322 break; 2323 } 2324 } 2325 } 2326 return translated_drq; 2327} 2328 2329#if 0 2330int __init smcc669_init ( void ) 2331{ 2332 struct INODE *ip; 2333 2334 allocinode( smc_ddb.name, 1, &ip ); 2335 ip->dva = &smc_ddb; 2336 ip->attr = ATTR$M_WRITE | ATTR$M_READ; 2337 ip->len[0] = 0x30; 2338 ip->misc = 0; 2339 INODE_UNLOCK( ip ); 2340 2341 return msg_success; 2342} 2343 2344int __init smcc669_open( struct FILE *fp, char *info, char *next, char *mode ) 2345{ 2346 struct INODE *ip; 2347/* 2348** Allow multiple readers but only one writer. ip->misc keeps track 2349** of the number of writers 2350*/ 2351 ip = fp->ip; 2352 INODE_LOCK( ip ); 2353 if ( fp->mode & ATTR$M_WRITE ) { 2354 if ( ip->misc ) { 2355 INODE_UNLOCK( ip ); 2356 return msg_failure; /* too many writers */ 2357 } 2358 ip->misc++; 2359 } 2360/* 2361** Treat the information field as a byte offset 2362*/ 2363 *fp->offset = xtoi( info ); 2364 INODE_UNLOCK( ip ); 2365 2366 return msg_success; 2367} 2368 2369int __init smcc669_close( struct FILE *fp ) 2370{ 2371 struct INODE *ip; 2372 2373 ip = fp->ip; 2374 if ( fp->mode & ATTR$M_WRITE ) { 2375 INODE_LOCK( ip ); 2376 ip->misc--; 2377 INODE_UNLOCK( ip ); 2378 } 2379 return msg_success; 2380} 2381 2382int __init smcc669_read( struct FILE *fp, int size, int number, unsigned char *buf ) 2383{ 2384 int i; 2385 int length; 2386 int nbytes; 2387 struct INODE *ip; 2388 2389/* 2390** Always access a byte at a time 2391*/ 2392 ip = fp->ip; 2393 length = size * number; 2394 nbytes = 0; 2395 2396 SMC37c669_config_mode( TRUE ); 2397 for ( i = 0; i < length; i++ ) { 2398 if ( !inrange( *fp->offset, 0, ip->len[0] ) ) 2399 break; 2400 *buf++ = SMC37c669_read_config( *fp->offset ); 2401 *fp->offset += 1; 2402 nbytes++; 2403 } 2404 SMC37c669_config_mode( FALSE ); 2405 return nbytes; 2406} 2407 2408int __init smcc669_write( struct FILE *fp, int size, int number, unsigned char *buf ) 2409{ 2410 int i; 2411 int length; 2412 int nbytes; 2413 struct INODE *ip; 2414/* 2415** Always access a byte at a time 2416*/ 2417 ip = fp->ip; 2418 length = size * number; 2419 nbytes = 0; 2420 2421 SMC37c669_config_mode( TRUE ); 2422 for ( i = 0; i < length; i++ ) { 2423 if ( !inrange( *fp->offset, 0, ip->len[0] ) ) 2424 break; 2425 SMC37c669_write_config( *fp->offset, *buf ); 2426 *fp->offset += 1; 2427 buf++; 2428 nbytes++; 2429 } 2430 SMC37c669_config_mode( FALSE ); 2431 return nbytes; 2432} 2433#endif 2434 2435#if SMC_DEBUG 2436static void __init 2437SMC37c669_dump_registers(void) 2438{ 2439 int i; 2440 for (i = 0; i <= 0x29; i++) 2441 printk("-- CR%02x : %02x\n", i, SMC37c669_read_config(i)); 2442} 2443#endif 2444/*+ 2445 * ============================================================================ 2446 * = SMC_init - SMC37c669 Super I/O controller initialization = 2447 * ============================================================================ 2448 * 2449 * OVERVIEW: 2450 * 2451 * This routine configures and enables device functions on the 2452 * SMC37c669 Super I/O controller. 2453 * 2454 * FORM OF CALL: 2455 * 2456 * SMC_init( ); 2457 * 2458 * RETURNS: 2459 * 2460 * Nothing 2461 * 2462 * ARGUMENTS: 2463 * 2464 * None 2465 * 2466 * SIDE EFFECTS: 2467 * 2468 * None 2469 * 2470 */ 2471void __init SMC669_Init ( int index ) 2472{ 2473 SMC37c669_CONFIG_REGS *SMC_base; 2474 unsigned long flags; 2475 2476 local_irq_save(flags); 2477 if ( ( SMC_base = SMC37c669_detect( index ) ) != NULL ) { 2478#if SMC_DEBUG 2479 SMC37c669_config_mode( TRUE ); 2480 SMC37c669_dump_registers( ); 2481 SMC37c669_config_mode( FALSE ); 2482 SMC37c669_display_device_info( ); 2483#endif 2484 SMC37c669_disable_device( SERIAL_0 ); 2485 SMC37c669_configure_device( 2486 SERIAL_0, 2487 COM1_BASE, 2488 COM1_IRQ, 2489 -1 2490 ); 2491 SMC37c669_enable_device( SERIAL_0 ); 2492 2493 SMC37c669_disable_device( SERIAL_1 ); 2494 SMC37c669_configure_device( 2495 SERIAL_1, 2496 COM2_BASE, 2497 COM2_IRQ, 2498 -1 2499 ); 2500 SMC37c669_enable_device( SERIAL_1 ); 2501 2502 SMC37c669_disable_device( PARALLEL_0 ); 2503 SMC37c669_configure_device( 2504 PARALLEL_0, 2505 PARP_BASE, 2506 PARP_IRQ, 2507 PARP_DRQ 2508 ); 2509 SMC37c669_enable_device( PARALLEL_0 ); 2510 2511 SMC37c669_disable_device( FLOPPY_0 ); 2512 SMC37c669_configure_device( 2513 FLOPPY_0, 2514 FDC_BASE, 2515 FDC_IRQ, 2516 FDC_DRQ 2517 ); 2518 SMC37c669_enable_device( FLOPPY_0 ); 2519 2520 /* Wake up sometimes forgotten floppy, especially on DP264. */ 2521 outb(0xc, 0x3f2); 2522 2523 SMC37c669_disable_device( IDE_0 ); 2524 2525#if SMC_DEBUG 2526 SMC37c669_config_mode( TRUE ); 2527 SMC37c669_dump_registers( ); 2528 SMC37c669_config_mode( FALSE ); 2529 SMC37c669_display_device_info( ); 2530#endif 2531 local_irq_restore(flags); 2532 printk( "SMC37c669 Super I/O Controller found @ 0x%p\n", 2533 SMC_base ); 2534 } 2535 else { 2536 local_irq_restore(flags); 2537#if SMC_DEBUG 2538 printk( "No SMC37c669 Super I/O Controller found\n" ); 2539#endif 2540 } 2541}
~/
Read-only file preview.