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