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