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