2 * SMC 37C669 initialization code
4 #include <linux/kernel.h>
6 #include <linux/slab.h>
8 #include <linux/init.h>
9 #include <linux/delay.h>
10 #include <linux/spinlock.h>
12 #include <asm/hwrpb.h>
14 #include <asm/segment.h>
17 # define DBG_DEVS(args) printk args
19 # define DBG_DEVS(args)
28 /* File: smcc669_def.h
30 * Copyright (C) 1997 by
31 * Digital Equipment Corporation, Maynard, Massachusetts.
32 * All rights reserved.
34 * This software is furnished under a license and may be used and copied
35 * only in accordance of the terms of such license and with the
36 * inclusion of the above copyright notice. This software or any other
37 * copies thereof may not be provided or otherwise made available to any
38 * other person. No title to and ownership of the software is hereby
41 * The information in this software is subject to change without notice
42 * and should not be construed as a commitment by Digital Equipment
45 * Digital assumes no responsibility for the use or reliability of its
46 * software on equipment which is not supplied by Digital.
51 * This file contains header definitions for the SMC37c669
52 * Super I/O controller.
58 * Modification History:
60 * er 28-Jan-1997 Initial Entry
67 ** Macros for handling device IRQs
69 ** The mask acts as a flag used in mapping actual ISA IRQs (0 - 15)
70 ** to device IRQs (A - H).
72 #define SMC37c669_DEVICE_IRQ_MASK 0x80000000
73 #define SMC37c669_DEVICE_IRQ( __i ) \
74 ((SMC37c669_DEVICE_IRQ_MASK) | (__i))
75 #define SMC37c669_IS_DEVICE_IRQ(__i) \
76 (((__i) & (SMC37c669_DEVICE_IRQ_MASK)) == (SMC37c669_DEVICE_IRQ_MASK))
77 #define SMC37c669_RAW_DEVICE_IRQ(__i) \
78 ((__i) & ~(SMC37c669_DEVICE_IRQ_MASK))
81 ** Macros for handling device DRQs
83 ** The mask acts as a flag used in mapping actual ISA DMA
84 ** channels to device DMA channels (A - C).
86 #define SMC37c669_DEVICE_DRQ_MASK 0x80000000
87 #define SMC37c669_DEVICE_DRQ(__d) \
88 ((SMC37c669_DEVICE_DRQ_MASK) | (__d))
89 #define SMC37c669_IS_DEVICE_DRQ(__d) \
90 (((__d) & (SMC37c669_DEVICE_DRQ_MASK)) == (SMC37c669_DEVICE_DRQ_MASK))
91 #define SMC37c669_RAW_DEVICE_DRQ(__d) \
92 ((__d) & ~(SMC37c669_DEVICE_DRQ_MASK))
94 #define SMC37c669_DEVICE_ID 0x3
97 ** SMC37c669 Device Function Definitions
107 ** Default Device Function Mappings
109 #define COM1_BASE 0x3F8
111 #define COM2_BASE 0x2F8
113 #define PARP_BASE 0x3BC
116 #define FDC_BASE 0x3F0
121 ** Configuration On/Off Key Definitions
123 #define SMC37c669_CONFIG_ON_KEY 0x55
124 #define SMC37c669_CONFIG_OFF_KEY 0xAA
127 ** SMC 37c669 Device IRQs
129 #define SMC37c669_DEVICE_IRQ_A ( SMC37c669_DEVICE_IRQ( 0x01 ) )
130 #define SMC37c669_DEVICE_IRQ_B ( SMC37c669_DEVICE_IRQ( 0x02 ) )
131 #define SMC37c669_DEVICE_IRQ_C ( SMC37c669_DEVICE_IRQ( 0x03 ) )
132 #define SMC37c669_DEVICE_IRQ_D ( SMC37c669_DEVICE_IRQ( 0x04 ) )
133 #define SMC37c669_DEVICE_IRQ_E ( SMC37c669_DEVICE_IRQ( 0x05 ) )
134 #define SMC37c669_DEVICE_IRQ_F ( SMC37c669_DEVICE_IRQ( 0x06 ) )
135 /* SMC37c669_DEVICE_IRQ_G *** RESERVED ***/
136 #define SMC37c669_DEVICE_IRQ_H ( SMC37c669_DEVICE_IRQ( 0x08 ) )
139 ** SMC 37c669 Device DMA Channel Definitions
141 #define SMC37c669_DEVICE_DRQ_A ( SMC37c669_DEVICE_DRQ( 0x01 ) )
142 #define SMC37c669_DEVICE_DRQ_B ( SMC37c669_DEVICE_DRQ( 0x02 ) )
143 #define SMC37c669_DEVICE_DRQ_C ( SMC37c669_DEVICE_DRQ( 0x03 ) )
146 ** Configuration Register Index Definitions
148 #define SMC37c669_CR00_INDEX 0x00
149 #define SMC37c669_CR01_INDEX 0x01
150 #define SMC37c669_CR02_INDEX 0x02
151 #define SMC37c669_CR03_INDEX 0x03
152 #define SMC37c669_CR04_INDEX 0x04
153 #define SMC37c669_CR05_INDEX 0x05
154 #define SMC37c669_CR06_INDEX 0x06
155 #define SMC37c669_CR07_INDEX 0x07
156 #define SMC37c669_CR08_INDEX 0x08
157 #define SMC37c669_CR09_INDEX 0x09
158 #define SMC37c669_CR0A_INDEX 0x0A
159 #define SMC37c669_CR0B_INDEX 0x0B
160 #define SMC37c669_CR0C_INDEX 0x0C
161 #define SMC37c669_CR0D_INDEX 0x0D
162 #define SMC37c669_CR0E_INDEX 0x0E
163 #define SMC37c669_CR0F_INDEX 0x0F
164 #define SMC37c669_CR10_INDEX 0x10
165 #define SMC37c669_CR11_INDEX 0x11
166 #define SMC37c669_CR12_INDEX 0x12
167 #define SMC37c669_CR13_INDEX 0x13
168 #define SMC37c669_CR14_INDEX 0x14
169 #define SMC37c669_CR15_INDEX 0x15
170 #define SMC37c669_CR16_INDEX 0x16
171 #define SMC37c669_CR17_INDEX 0x17
172 #define SMC37c669_CR18_INDEX 0x18
173 #define SMC37c669_CR19_INDEX 0x19
174 #define SMC37c669_CR1A_INDEX 0x1A
175 #define SMC37c669_CR1B_INDEX 0x1B
176 #define SMC37c669_CR1C_INDEX 0x1C
177 #define SMC37c669_CR1D_INDEX 0x1D
178 #define SMC37c669_CR1E_INDEX 0x1E
179 #define SMC37c669_CR1F_INDEX 0x1F
180 #define SMC37c669_CR20_INDEX 0x20
181 #define SMC37c669_CR21_INDEX 0x21
182 #define SMC37c669_CR22_INDEX 0x22
183 #define SMC37c669_CR23_INDEX 0x23
184 #define SMC37c669_CR24_INDEX 0x24
185 #define SMC37c669_CR25_INDEX 0x25
186 #define SMC37c669_CR26_INDEX 0x26
187 #define SMC37c669_CR27_INDEX 0x27
188 #define SMC37c669_CR28_INDEX 0x28
189 #define SMC37c669_CR29_INDEX 0x29
192 ** Configuration Register Alias Definitions
194 #define SMC37c669_DEVICE_ID_INDEX SMC37c669_CR0D_INDEX
195 #define SMC37c669_DEVICE_REVISION_INDEX SMC37c669_CR0E_INDEX
196 #define SMC37c669_FDC_BASE_ADDRESS_INDEX SMC37c669_CR20_INDEX
197 #define SMC37c669_IDE_BASE_ADDRESS_INDEX SMC37c669_CR21_INDEX
198 #define SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX SMC37c669_CR22_INDEX
199 #define SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX SMC37c669_CR23_INDEX
200 #define SMC37c669_SERIAL0_BASE_ADDRESS_INDEX SMC37c669_CR24_INDEX
201 #define SMC37c669_SERIAL1_BASE_ADDRESS_INDEX SMC37c669_CR25_INDEX
202 #define SMC37c669_PARALLEL_FDC_DRQ_INDEX SMC37c669_CR26_INDEX
203 #define SMC37c669_PARALLEL_FDC_IRQ_INDEX SMC37c669_CR27_INDEX
204 #define SMC37c669_SERIAL_IRQ_INDEX SMC37c669_CR28_INDEX
207 ** Configuration Register Definitions
209 ** The INDEX (write only) and DATA (read/write) ports are effective
210 ** only when the chip is in the Configuration State.
212 typedef struct _SMC37c669_CONFIG_REGS {
213 unsigned char index_port;
214 unsigned char data_port;
215 } SMC37c669_CONFIG_REGS;
218 ** CR00 - default value 0x28
220 ** IDE_EN (CR00<1:0>):
221 ** 0x - 30ua pull-ups on nIDEEN, nHDCS0, NHDCS1
222 ** 11 - IRQ_H available as IRQ output,
223 ** IRRX2, IRTX2 available as alternate IR pins
224 ** 10 - nIDEEN, nHDCS0, nHDCS1 used to control IDE
227 ** A high level on this software controlled bit can
228 ** be used to indicate that a valid configuration
229 ** cycle has occurred. The control software must
230 ** take care to set this bit at the appropriate times.
231 ** Set to zero after power up. This bit has no
232 ** effect on any other hardware in the chip.
235 typedef union _SMC37c669_CR00 {
236 unsigned char as_uchar;
238 unsigned ide_en : 2; /* See note above */
239 unsigned reserved1 : 1; /* RAZ */
240 unsigned fdc_pwr : 1; /* 1 = supply power to FDC */
241 unsigned reserved2 : 3; /* Read as 010b */
242 unsigned valid : 1; /* See note above */
247 ** CR01 - default value 0x9C
249 typedef union _SMC37c669_CR01 {
250 unsigned char as_uchar;
252 unsigned reserved1 : 2; /* RAZ */
253 unsigned ppt_pwr : 1; /* 1 = supply power to PPT */
254 unsigned ppt_mode : 1; /* 1 = Printer mode, 0 = EPP */
255 unsigned reserved2 : 1; /* Read as 1 */
256 unsigned reserved3 : 2; /* RAZ */
257 unsigned lock_crx: 1; /* Lock CR00 - CR18 */
262 ** CR02 - default value 0x88
264 typedef union _SMC37c669_CR02 {
265 unsigned char as_uchar;
267 unsigned reserved1 : 3; /* RAZ */
268 unsigned uart1_pwr : 1; /* 1 = supply power to UART1 */
269 unsigned reserved2 : 3; /* RAZ */
270 unsigned uart2_pwr : 1; /* 1 = supply power to UART2 */
275 ** CR03 - default value 0x78
277 ** CR03<7> CR03<2> Pin 94
278 ** ------- ------- ------
283 ** CR03<6> CR03<5> Op Mode
284 ** ------- ------- -------
290 typedef union _SMC37c669_CR03 {
291 unsigned char as_uchar;
293 unsigned pwrgd_gamecs : 1; /* 1 = PWRGD, 0 = GAMECS */
294 unsigned fdc_mode2 : 1; /* 1 = Enhanced Mode 2 */
295 unsigned pin94_0 : 1; /* See note above */
296 unsigned reserved1 : 1; /* RAZ */
297 unsigned drvden : 1; /* 1 = high, 0 - output */
298 unsigned op_mode : 2; /* See note above */
299 unsigned pin94_1 : 1; /* See note above */
304 ** CR04 - default value 0x00
307 ** If CR01<PP_MODE> = 0 and PP_EXT_MODE =
308 ** 00 - Standard and Bidirectional
309 ** 01 - EPP mode and SPP
311 ** In this mode, 2 drives can be supported
312 ** directly, 3 or 4 drives must use external
313 ** 4 drive support. SPP can be selected
314 ** through the ECR register of ECP as mode 000.
315 ** 11 - ECP mode and EPP mode
316 ** In this mode, 2 drives can be supported
317 ** directly, 3 or 4 drives must use external
318 ** 4 drive support. SPP can be selected
319 ** through the ECR register of ECP as mode 000.
320 ** In this mode, EPP can be selected through
321 ** the ECR register of ECP as mode 100.
330 ** Serial Clock Select:
331 ** A low level on this bit disables MIDI support,
332 ** clock = divide by 13. A high level on this
333 ** bit enables MIDI support, clock = divide by 12.
335 ** MIDI operates at 31.25 Kbps which can be derived
336 ** from 125 KHz (24 MHz / 12 = 2 MHz, 2 MHz / 16 = 125 KHz)
339 ** 0 - Use pins IRRX, IRTX
340 ** 1 - Use pins IRRX2, IRTX2
342 ** If this bit is set, the IR receive and transmit
343 ** functions will not be available on pins 25 and 26
344 ** unless CR00<IDE_EN> = 11.
346 typedef union _SMC37c669_CR04 {
347 unsigned char as_uchar;
349 unsigned ppt_ext_mode : 2; /* See note above */
350 unsigned ppt_fdc : 2; /* See note above */
351 unsigned midi1 : 1; /* See note above */
352 unsigned midi2 : 1; /* See note above */
353 unsigned epp_type : 1; /* 0 = EPP 1.9, 1 = EPP 1.7 */
354 unsigned alt_io : 1; /* See note above */
359 ** CR05 - default value 0x00
362 ** 00 - Densel output normal
364 ** 10 - Densel output 1
365 ** 11 - Densel output 0
368 typedef union _SMC37c669_CR05 {
369 unsigned char as_uchar;
371 unsigned reserved1 : 2; /* RAZ */
372 unsigned fdc_dma_mode : 1; /* 0 = burst, 1 = non-burst */
373 unsigned den_sel : 2; /* See note above */
374 unsigned swap_drv : 1; /* Swap the FDC motor selects */
375 unsigned extx4 : 1; /* 0 = 2 drive, 1 = external 4 drive decode */
376 unsigned reserved2 : 1; /* RAZ */
381 ** CR06 - default value 0xFF
383 typedef union _SMC37c669_CR06 {
384 unsigned char as_uchar;
386 unsigned floppy_a : 2; /* Type of floppy drive A */
387 unsigned floppy_b : 2; /* Type of floppy drive B */
388 unsigned floppy_c : 2; /* Type of floppy drive C */
389 unsigned floppy_d : 2; /* Type of floppy drive D */
394 ** CR07 - default value 0x00
396 ** Auto Power Management CR07<7:4>:
397 ** 0 - Auto Powerdown disabled (default)
398 ** 1 - Auto Powerdown enabled
400 ** This bit is reset to the default state by POR or
404 typedef union _SMC37c669_CR07 {
405 unsigned char as_uchar;
407 unsigned floppy_boot : 2; /* 0 = A:, 1 = B: */
408 unsigned reserved1 : 2; /* RAZ */
409 unsigned ppt_en : 1; /* See note above */
410 unsigned uart1_en : 1; /* See note above */
411 unsigned uart2_en : 1; /* See note above */
412 unsigned fdc_en : 1; /* See note above */
417 ** CR08 - default value 0x00
419 typedef union _SMC37c669_CR08 {
420 unsigned char as_uchar;
422 unsigned zero : 4; /* 0 */
423 unsigned addrx7_4 : 4; /* ADR<7:3> for ADRx decode */
428 ** CR09 - default value 0x00
431 ** 00 - ADRx disabled
432 ** 01 - 1 byte decode A<3:0> = 0000b
433 ** 10 - 8 byte block decode A<3:0> = 0XXXb
434 ** 11 - 16 byte block decode A<3:0> = XXXXb
437 typedef union _SMC37c669_CR09 {
438 unsigned char as_uchar;
440 unsigned adra8 : 3; /* ADR<10:8> for ADRx decode */
441 unsigned reserved1 : 3;
442 unsigned adrx_config : 2; /* See note above */
447 ** CR0A - default value 0x00
449 typedef union _SMC37c669_CR0A {
450 unsigned char as_uchar;
452 unsigned ecp_fifo_threshold : 4;
453 unsigned reserved1 : 4;
458 ** CR0B - default value 0x00
460 typedef union _SMC37c669_CR0B {
461 unsigned char as_uchar;
463 unsigned fdd0_drtx : 2; /* FDD0 Data Rate Table */
464 unsigned fdd1_drtx : 2; /* FDD1 Data Rate Table */
465 unsigned fdd2_drtx : 2; /* FDD2 Data Rate Table */
466 unsigned fdd3_drtx : 2; /* FDD3 Data Rate Table */
471 ** CR0C - default value 0x00
474 ** 000 - Standard (default)
475 ** 001 - IrDA (HPSIR)
476 ** 010 - Amplitude Shift Keyed IR @500 KHz
481 typedef union _SMC37c669_CR0C {
482 unsigned char as_uchar;
484 unsigned uart2_rcv_polarity : 1; /* 1 = invert RX */
485 unsigned uart2_xmit_polarity : 1; /* 1 = invert TX */
486 unsigned uart2_duplex : 1; /* 1 = full, 0 = half */
487 unsigned uart2_mode : 3; /* See note above */
488 unsigned uart1_speed : 1; /* 1 = high speed enabled */
489 unsigned uart2_speed : 1; /* 1 = high speed enabled */
494 ** CR0D - default value 0x03
496 ** Device ID Register - read only
498 typedef union _SMC37c669_CR0D {
499 unsigned char as_uchar;
501 unsigned device_id : 8; /* Returns 0x3 in this field */
506 ** CR0E - default value 0x02
508 ** Device Revision Register - read only
510 typedef union _SMC37c669_CR0E {
511 unsigned char as_uchar;
513 unsigned device_rev : 8; /* Returns 0x2 in this field */
518 ** CR0F - default value 0x00
520 typedef union _SMC37c669_CR0F {
521 unsigned char as_uchar;
523 unsigned test0 : 1; /* Reserved - set to 0 */
524 unsigned test1 : 1; /* Reserved - set to 0 */
525 unsigned test2 : 1; /* Reserved - set to 0 */
526 unsigned test3 : 1; /* Reserved - set t0 0 */
527 unsigned test4 : 1; /* Reserved - set to 0 */
528 unsigned test5 : 1; /* Reserved - set t0 0 */
529 unsigned test6 : 1; /* Reserved - set t0 0 */
530 unsigned test7 : 1; /* Reserved - set to 0 */
535 ** CR10 - default value 0x00
537 typedef union _SMC37c669_CR10 {
538 unsigned char as_uchar;
540 unsigned reserved1 : 3; /* RAZ */
541 unsigned pll_gain : 1; /* 1 = 3V, 2 = 5V operation */
542 unsigned pll_stop : 1; /* 1 = stop PLLs */
543 unsigned ace_stop : 1; /* 1 = stop UART clocks */
544 unsigned pll_clock_ctrl : 1; /* 0 = 14.318 MHz, 1 = 24 MHz */
545 unsigned ir_test : 1; /* Enable IR test mode */
550 ** CR11 - default value 0x00
552 typedef union _SMC37c669_CR11 {
553 unsigned char as_uchar;
555 unsigned ir_loopback : 1; /* Internal IR loop back */
556 unsigned test_10ms : 1; /* Test 10ms autopowerdown FDC timeout */
557 unsigned reserved1 : 6; /* RAZ */
562 ** CR12 - CR1D are reserved registers
566 ** CR1E - default value 0x80
569 ** 00 - GAMECS disabled
570 ** 01 - 1 byte decode ADR<3:0> = 0001b
571 ** 10 - 8 byte block decode ADR<3:0> = 0XXXb
572 ** 11 - 16 byte block decode ADR<3:0> = XXXXb
575 typedef union _SMC37c66_CR1E {
576 unsigned char as_uchar;
578 unsigned gamecs_config: 2; /* See note above */
579 unsigned gamecs_addr9_4 : 6; /* GAMECS Addr<9:4> */
584 ** CR1F - default value 0x00
586 ** DT0 DT1 DRVDEN0 DRVDEN1 Drive Type
587 ** --- --- ------- ------- ----------
588 ** 0 0 DENSEL DRATE0 4/2/1 MB 3.5"
590 ** 2/1.6/1 MB 3.5" (3-mode)
592 ** 1 0 nDENSEL DRATE0 PS/2
595 ** Note: DENSEL, DRATE1, and DRATE0 map onto two output
596 ** pins - DRVDEN0 and DRVDEN1.
599 typedef union _SMC37c669_CR1F {
600 unsigned char as_uchar;
602 unsigned fdd0_drive_type : 2; /* FDD0 drive type */
603 unsigned fdd1_drive_type : 2; /* FDD1 drive type */
604 unsigned fdd2_drive_type : 2; /* FDD2 drive type */
605 unsigned fdd3_drive_type : 2; /* FDD3 drive type */
610 ** CR20 - default value 0x3C
612 ** FDC Base Address Register
613 ** - To disable this decode set Addr<9:8> = 0
614 ** - A<10> = 0, A<3:0> = 0XXXb to access.
617 typedef union _SMC37c669_CR20 {
618 unsigned char as_uchar;
620 unsigned zero : 2; /* 0 */
621 unsigned addr9_4 : 6; /* FDC Addr<9:4> */
626 ** CR21 - default value 0x3C
628 ** IDE Base Address Register
629 ** - To disable this decode set Addr<9:8> = 0
630 ** - A<10> = 0, A<3:0> = 0XXXb to access.
633 typedef union _SMC37c669_CR21 {
634 unsigned char as_uchar;
636 unsigned zero : 2; /* 0 */
637 unsigned addr9_4 : 6; /* IDE Addr<9:4> */
642 ** CR22 - default value 0x3D
644 ** IDE Alternate Status Base Address Register
645 ** - To disable this decode set Addr<9:8> = 0
646 ** - A<10> = 0, A<3:0> = 0110b to access.
649 typedef union _SMC37c669_CR22 {
650 unsigned char as_uchar;
652 unsigned zero : 2; /* 0 */
653 unsigned addr9_4 : 6; /* IDE Alt Status Addr<9:4> */
658 ** CR23 - default value 0x00
660 ** Parallel Port Base Address Register
661 ** - To disable this decode set Addr<9:8> = 0
662 ** - A<10> = 0 to access.
663 ** - If EPP is enabled, A<2:0> = XXXb to access.
664 ** If EPP is NOT enabled, A<1:0> = XXb to access
667 typedef union _SMC37c669_CR23 {
668 unsigned char as_uchar;
670 unsigned addr9_2 : 8; /* Parallel Port Addr<9:2> */
675 ** CR24 - default value 0x00
677 ** UART1 Base Address Register
678 ** - To disable this decode set Addr<9:8> = 0
679 ** - A<10> = 0, A<2:0> = XXXb to access.
682 typedef union _SMC37c669_CR24 {
683 unsigned char as_uchar;
685 unsigned zero : 1; /* 0 */
686 unsigned addr9_3 : 7; /* UART1 Addr<9:3> */
691 ** CR25 - default value 0x00
693 ** UART2 Base Address Register
694 ** - To disable this decode set Addr<9:8> = 0
695 ** - A<10> = 0, A<2:0> = XXXb to access.
698 typedef union _SMC37c669_CR25 {
699 unsigned char as_uchar;
701 unsigned zero : 1; /* 0 */
702 unsigned addr9_3 : 7; /* UART2 Addr<9:3> */
707 ** CR26 - default value 0x00
709 ** Parallel Port / FDC DMA Select Register
720 typedef union _SMC37c669_CR26 {
721 unsigned char as_uchar;
723 unsigned ppt_drq : 4; /* See note above */
724 unsigned fdc_drq : 4; /* See note above */
729 ** CR27 - default value 0x00
731 ** Parallel Port / FDC IRQ Select Register
746 ** Any unselected IRQ REQ is in tristate
749 typedef union _SMC37c669_CR27 {
750 unsigned char as_uchar;
752 unsigned ppt_irq : 4; /* See note above */
753 unsigned fdc_irq : 4; /* See note above */
758 ** CR28 - default value 0x00
760 ** UART IRQ Select Register
774 ** 1111 share with UART1 (only for UART2)
776 ** Any unselected IRQ REQ is in tristate
778 ** To share an IRQ between UART1 and UART2, set
779 ** UART1 to use the desired IRQ and set UART2 to
780 ** 0xF to enable sharing mechanism.
783 typedef union _SMC37c669_CR28 {
784 unsigned char as_uchar;
786 unsigned uart2_irq : 4; /* See note above */
787 unsigned uart1_irq : 4; /* See note above */
792 ** CR29 - default value 0x00
794 ** IRQIN IRQ Select Register
809 ** Any unselected IRQ REQ is in tristate
812 typedef union _SMC37c669_CR29 {
813 unsigned char as_uchar;
815 unsigned irqin_irq : 4; /* See note above */
816 unsigned reserved1 : 4; /* RAZ */
821 ** Aliases of Configuration Register formats (should match
822 ** the set of index aliases).
824 ** Note that CR24 and CR25 have the same format and are the
825 ** base address registers for UART1 and UART2. Because of
826 ** this we only define 1 alias here - for CR24 - as the serial
827 ** base address register.
829 ** Note that CR21 and CR22 have the same format and are the
830 ** base address and alternate status address registers for
831 ** the IDE controller. Because of this we only define 1 alias
832 ** here - for CR21 - as the IDE address register.
835 typedef SMC37c669_CR0D SMC37c669_DEVICE_ID_REGISTER;
836 typedef SMC37c669_CR0E SMC37c669_DEVICE_REVISION_REGISTER;
837 typedef SMC37c669_CR20 SMC37c669_FDC_BASE_ADDRESS_REGISTER;
838 typedef SMC37c669_CR21 SMC37c669_IDE_ADDRESS_REGISTER;
839 typedef SMC37c669_CR23 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER;
840 typedef SMC37c669_CR24 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER;
841 typedef SMC37c669_CR26 SMC37c669_PARALLEL_FDC_DRQ_REGISTER;
842 typedef SMC37c669_CR27 SMC37c669_PARALLEL_FDC_IRQ_REGISTER;
843 typedef SMC37c669_CR28 SMC37c669_SERIAL_IRQ_REGISTER;
846 ** ISA/Device IRQ Translation Table Entry Definition
848 typedef struct _SMC37c669_IRQ_TRANSLATION_ENTRY {
851 } SMC37c669_IRQ_TRANSLATION_ENTRY;
854 ** ISA/Device DMA Translation Table Entry Definition
856 typedef struct _SMC37c669_DRQ_TRANSLATION_ENTRY {
859 } SMC37c669_DRQ_TRANSLATION_ENTRY;
862 ** External Interface Function Prototype Declarations
865 SMC37c669_CONFIG_REGS *SMC37c669_detect(
869 unsigned int SMC37c669_enable_device(
873 unsigned int SMC37c669_disable_device(
877 unsigned int SMC37c669_configure_device(
884 void SMC37c669_display_device_info(
888 #endif /* __SMC37c669_H */
892 * Copyright (C) 1997 by
893 * Digital Equipment Corporation, Maynard, Massachusetts.
894 * All rights reserved.
896 * This software is furnished under a license and may be used and copied
897 * only in accordance of the terms of such license and with the
898 * inclusion of the above copyright notice. This software or any other
899 * copies thereof may not be provided or otherwise made available to any
900 * other person. No title to and ownership of the software is hereby
903 * The information in this software is subject to change without notice
904 * and should not be construed as a commitment by digital equipment
907 * Digital assumes no responsibility for the use or reliability of its
908 * software on equipment which is not supplied by digital.
915 * Alpha SRM Console Firmware
917 * MODULE DESCRIPTION:
919 * SMC37c669 Super I/O controller configuration routines.
929 * MODIFICATION HISTORY:
931 * er 01-May-1997 Fixed pointer conversion errors in
932 * SMC37c669_get_device_config().
933 * er 28-Jan-1997 Initial version.
938 /* $INCLUDE_OPTIONS$ */
939 #include "cp$inc:platform_io.h"
940 /* $INCLUDE_OPTIONS_END$ */
941 #include "cp$src:common.h"
942 #include "cp$inc:prototypes.h"
943 #include "cp$src:kernel_def.h"
944 #include "cp$src:msg_def.h"
945 #include "cp$src:smcc669_def.h"
946 /* Platform-specific includes */
947 #include "cp$src:platform.h"
957 #define wb( _x_, _y_ ) outb( _y_, (unsigned int)((unsigned long)_x_) )
958 #define rb( _x_ ) inb( (unsigned int)((unsigned long)_x_) )
961 ** Local storage for device configuration information.
963 ** Since the SMC37c669 does not provide an explicit
964 ** mechanism for enabling/disabling individual device
965 ** functions, other than unmapping the device, local
966 ** storage for device configuration information is
967 ** allocated here for use in implementing our own
968 ** function enable/disable scheme.
970 static struct DEVICE_CONFIG {
975 } local_config [NUM_FUNCS];
978 ** List of all possible addresses for the Super I/O chip
980 static unsigned long SMC37c669_Addresses[] __initdata =
982 0x3F0UL, /* Primary address */
983 0x370UL, /* Secondary address */
984 0UL /* End of list */
988 ** Global Pointer to the Super I/O device
990 static SMC37c669_CONFIG_REGS *SMC37c669 __initdata = NULL;
993 ** IRQ Translation Table
995 ** The IRQ translation table is a list of SMC37c669 device
996 ** and standard ISA IRQs.
999 static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_table __initdata;
1002 ** The following definition is for the default IRQ
1003 ** translation table.
1005 static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_default_irq_table[]
1008 { SMC37c669_DEVICE_IRQ_A, -1 },
1009 { SMC37c669_DEVICE_IRQ_B, -1 },
1010 { SMC37c669_DEVICE_IRQ_C, 7 },
1011 { SMC37c669_DEVICE_IRQ_D, 6 },
1012 { SMC37c669_DEVICE_IRQ_E, 4 },
1013 { SMC37c669_DEVICE_IRQ_F, 3 },
1014 { SMC37c669_DEVICE_IRQ_H, -1 },
1015 { -1, -1 } /* End of table */
1019 ** The following definition is for the MONET (XP1000) IRQ
1020 ** translation table.
1022 static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_monet_irq_table[]
1025 { SMC37c669_DEVICE_IRQ_A, -1 },
1026 { SMC37c669_DEVICE_IRQ_B, -1 },
1027 { SMC37c669_DEVICE_IRQ_C, 6 },
1028 { SMC37c669_DEVICE_IRQ_D, 7 },
1029 { SMC37c669_DEVICE_IRQ_E, 4 },
1030 { SMC37c669_DEVICE_IRQ_F, 3 },
1031 { SMC37c669_DEVICE_IRQ_H, -1 },
1032 { -1, -1 } /* End of table */
1035 static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_tables[] __initdata =
1037 SMC37c669_default_irq_table,
1038 SMC37c669_monet_irq_table
1042 ** DRQ Translation Table
1044 ** The DRQ translation table is a list of SMC37c669 device and
1045 ** ISA DMA channels.
1048 static SMC37c669_DRQ_TRANSLATION_ENTRY *SMC37c669_drq_table __initdata;
1051 ** The following definition is the default DRQ
1052 ** translation table.
1054 static SMC37c669_DRQ_TRANSLATION_ENTRY SMC37c669_default_drq_table[]
1057 { SMC37c669_DEVICE_DRQ_A, 2 },
1058 { SMC37c669_DEVICE_DRQ_B, 3 },
1059 { SMC37c669_DEVICE_DRQ_C, -1 },
1060 { -1, -1 } /* End of table */
1064 ** Local Function Prototype Declarations
1067 static unsigned int SMC37c669_is_device_enabled(
1072 static unsigned int SMC37c669_get_device_config(
1080 static void SMC37c669_config_mode(
1084 static unsigned char SMC37c669_read_config(
1088 static void SMC37c669_write_config(
1089 unsigned char index,
1093 static void SMC37c669_init_local_config( void );
1095 static struct DEVICE_CONFIG *SMC37c669_get_config(
1099 static int SMC37c669_xlate_irq(
1103 static int SMC37c669_xlate_drq(
1107 static __cacheline_aligned DEFINE_SPINLOCK(smc_lock);
1111 ** FUNCTIONAL DESCRIPTION:
1113 ** This function detects the presence of an SMC37c669 Super I/O
1116 ** FORMAL PARAMETERS:
1122 ** Returns a pointer to the device if found, otherwise,
1123 ** the NULL pointer is returned.
1131 SMC37c669_CONFIG_REGS * __init SMC37c669_detect( int index )
1134 SMC37c669_DEVICE_ID_REGISTER id;
1136 for ( i = 0; SMC37c669_Addresses[i] != 0; i++ ) {
1138 ** Initialize the device pointer even though we don't yet know if
1139 ** the controller is at this address. The support functions access
1140 ** the controller through this device pointer so we need to set it
1141 ** even when we are looking ...
1143 SMC37c669 = ( SMC37c669_CONFIG_REGS * )SMC37c669_Addresses[i];
1145 ** Enter configuration mode
1147 SMC37c669_config_mode( TRUE );
1149 ** Read the device id
1151 id.as_uchar = SMC37c669_read_config( SMC37c669_DEVICE_ID_INDEX );
1153 ** Exit configuration mode
1155 SMC37c669_config_mode( FALSE );
1157 ** Does the device id match? If so, assume we have found an
1158 ** SMC37c669 controller at this address.
1160 if ( id.by_field.device_id == SMC37c669_DEVICE_ID ) {
1162 ** Initialize the IRQ and DRQ translation tables.
1164 SMC37c669_irq_table = SMC37c669_irq_tables[ index ];
1165 SMC37c669_drq_table = SMC37c669_default_drq_table;
1169 ** If the platform can't use the IRQ and DRQ defaults set up in this
1170 ** file, it should call a platform-specific external routine at this
1171 ** point to reset the IRQ and DRQ translation table pointers to point
1172 ** at the appropriate tables for the platform. If the defaults are
1173 ** acceptable, then the external routine should do nothing.
1177 ** Put the chip back into configuration mode
1179 SMC37c669_config_mode( TRUE );
1181 ** Initialize local storage for configuration information
1183 SMC37c669_init_local_config( );
1185 ** Exit configuration mode
1187 SMC37c669_config_mode( FALSE );
1189 ** SMC37c669 controller found, break out of search loop
1195 ** Otherwise, we did not find an SMC37c669 controller at this
1196 ** address so set the device pointer to NULL.
1207 ** FUNCTIONAL DESCRIPTION:
1209 ** This function enables an SMC37c669 device function.
1211 ** FORMAL PARAMETERS:
1214 ** Which device function to enable
1218 ** Returns TRUE is the device function was enabled, otherwise, FALSE
1222 ** {@description or none@}
1226 ** Enabling a device function in the SMC37c669 controller involves
1227 ** setting all of its mappings (port, irq, drq ...). A local
1228 ** "shadow" copy of the device configuration is kept so we can
1229 ** just set each mapping to what the local copy says.
1231 ** This function ALWAYS updates the local shadow configuration of
1232 ** the device function being enabled, even if the device is always
1233 ** enabled. To avoid replication of code, functions such as
1234 ** configure_device set up the local copy and then call this
1235 ** function to the update the real device.
1239 unsigned int __init SMC37c669_enable_device ( unsigned int func )
1241 unsigned int ret_val = FALSE;
1243 ** Put the device into configuration mode
1245 SMC37c669_config_mode( TRUE );
1249 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
1250 SMC37c669_SERIAL_IRQ_REGISTER irq;
1252 ** Enable the serial 1 IRQ mapping
1255 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
1257 irq.by_field.uart1_irq =
1258 SMC37c669_RAW_DEVICE_IRQ(
1259 SMC37c669_xlate_irq( local_config[ func ].irq )
1262 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
1264 ** Enable the serial 1 port base address mapping
1266 base_addr.as_uchar = 0;
1267 base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3;
1269 SMC37c669_write_config(
1270 SMC37c669_SERIAL0_BASE_ADDRESS_INDEX,
1278 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
1279 SMC37c669_SERIAL_IRQ_REGISTER irq;
1281 ** Enable the serial 2 IRQ mapping
1284 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
1286 irq.by_field.uart2_irq =
1287 SMC37c669_RAW_DEVICE_IRQ(
1288 SMC37c669_xlate_irq( local_config[ func ].irq )
1291 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
1293 ** Enable the serial 2 port base address mapping
1295 base_addr.as_uchar = 0;
1296 base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3;
1298 SMC37c669_write_config(
1299 SMC37c669_SERIAL1_BASE_ADDRESS_INDEX,
1307 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr;
1308 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
1309 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
1311 ** Enable the parallel port DMA channel mapping
1314 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
1316 drq.by_field.ppt_drq =
1317 SMC37c669_RAW_DEVICE_DRQ(
1318 SMC37c669_xlate_drq( local_config[ func ].drq )
1321 SMC37c669_write_config(
1322 SMC37c669_PARALLEL_FDC_DRQ_INDEX,
1326 ** Enable the parallel port IRQ mapping
1329 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
1331 irq.by_field.ppt_irq =
1332 SMC37c669_RAW_DEVICE_IRQ(
1333 SMC37c669_xlate_irq( local_config[ func ].irq )
1336 SMC37c669_write_config(
1337 SMC37c669_PARALLEL_FDC_IRQ_INDEX,
1341 ** Enable the parallel port base address mapping
1343 base_addr.as_uchar = 0;
1344 base_addr.by_field.addr9_2 = local_config[ func ].port1 >> 2;
1346 SMC37c669_write_config(
1347 SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX,
1355 SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr;
1356 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
1357 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
1359 ** Enable the floppy controller DMA channel mapping
1362 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
1364 drq.by_field.fdc_drq =
1365 SMC37c669_RAW_DEVICE_DRQ(
1366 SMC37c669_xlate_drq( local_config[ func ].drq )
1369 SMC37c669_write_config(
1370 SMC37c669_PARALLEL_FDC_DRQ_INDEX,
1374 ** Enable the floppy controller IRQ mapping
1377 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
1379 irq.by_field.fdc_irq =
1380 SMC37c669_RAW_DEVICE_IRQ(
1381 SMC37c669_xlate_irq( local_config[ func ].irq )
1384 SMC37c669_write_config(
1385 SMC37c669_PARALLEL_FDC_IRQ_INDEX,
1389 ** Enable the floppy controller base address mapping
1391 base_addr.as_uchar = 0;
1392 base_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4;
1394 SMC37c669_write_config(
1395 SMC37c669_FDC_BASE_ADDRESS_INDEX,
1403 SMC37c669_IDE_ADDRESS_REGISTER ide_addr;
1405 ** Enable the IDE alternate status base address mapping
1407 ide_addr.as_uchar = 0;
1408 ide_addr.by_field.addr9_4 = local_config[ func ].port2 >> 4;
1410 SMC37c669_write_config(
1411 SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX,
1415 ** Enable the IDE controller base address mapping
1417 ide_addr.as_uchar = 0;
1418 ide_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4;
1420 SMC37c669_write_config(
1421 SMC37c669_IDE_BASE_ADDRESS_INDEX,
1429 ** Exit configuration mode and return
1431 SMC37c669_config_mode( FALSE );
1439 ** FUNCTIONAL DESCRIPTION:
1441 ** This function disables a device function within the
1442 ** SMC37c669 Super I/O controller.
1444 ** FORMAL PARAMETERS:
1447 ** Which function to disable
1451 ** Return TRUE if the device function was disabled, otherwise, FALSE
1455 ** {@description or none@}
1459 ** Disabling a function in the SMC37c669 device involves
1460 ** disabling all the function's mappings (port, irq, drq ...).
1461 ** A shadow copy of the device configuration is maintained
1462 ** in local storage so we won't worry aboving saving the
1463 ** current configuration information.
1467 unsigned int __init SMC37c669_disable_device ( unsigned int func )
1469 unsigned int ret_val = FALSE;
1472 ** Put the device into configuration mode
1474 SMC37c669_config_mode( TRUE );
1478 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
1479 SMC37c669_SERIAL_IRQ_REGISTER irq;
1481 ** Disable the serial 1 IRQ mapping
1484 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
1486 irq.by_field.uart1_irq = 0;
1488 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
1490 ** Disable the serial 1 port base address mapping
1492 base_addr.as_uchar = 0;
1493 SMC37c669_write_config(
1494 SMC37c669_SERIAL0_BASE_ADDRESS_INDEX,
1502 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
1503 SMC37c669_SERIAL_IRQ_REGISTER irq;
1505 ** Disable the serial 2 IRQ mapping
1508 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
1510 irq.by_field.uart2_irq = 0;
1512 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
1514 ** Disable the serial 2 port base address mapping
1516 base_addr.as_uchar = 0;
1518 SMC37c669_write_config(
1519 SMC37c669_SERIAL1_BASE_ADDRESS_INDEX,
1527 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr;
1528 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
1529 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
1531 ** Disable the parallel port DMA channel mapping
1534 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
1536 drq.by_field.ppt_drq = 0;
1538 SMC37c669_write_config(
1539 SMC37c669_PARALLEL_FDC_DRQ_INDEX,
1543 ** Disable the parallel port IRQ mapping
1546 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
1548 irq.by_field.ppt_irq = 0;
1550 SMC37c669_write_config(
1551 SMC37c669_PARALLEL_FDC_IRQ_INDEX,
1555 ** Disable the parallel port base address mapping
1557 base_addr.as_uchar = 0;
1559 SMC37c669_write_config(
1560 SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX,
1568 SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr;
1569 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
1570 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
1572 ** Disable the floppy controller DMA channel mapping
1575 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
1577 drq.by_field.fdc_drq = 0;
1579 SMC37c669_write_config(
1580 SMC37c669_PARALLEL_FDC_DRQ_INDEX,
1584 ** Disable the floppy controller IRQ mapping
1587 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
1589 irq.by_field.fdc_irq = 0;
1591 SMC37c669_write_config(
1592 SMC37c669_PARALLEL_FDC_IRQ_INDEX,
1596 ** Disable the floppy controller base address mapping
1598 base_addr.as_uchar = 0;
1600 SMC37c669_write_config(
1601 SMC37c669_FDC_BASE_ADDRESS_INDEX,
1609 SMC37c669_IDE_ADDRESS_REGISTER ide_addr;
1611 ** Disable the IDE alternate status base address mapping
1613 ide_addr.as_uchar = 0;
1615 SMC37c669_write_config(
1616 SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX,
1620 ** Disable the IDE controller base address mapping
1622 ide_addr.as_uchar = 0;
1624 SMC37c669_write_config(
1625 SMC37c669_IDE_BASE_ADDRESS_INDEX,
1633 ** Exit configuration mode and return
1635 SMC37c669_config_mode( FALSE );
1643 ** FUNCTIONAL DESCRIPTION:
1645 ** This function configures a device function within the
1646 ** SMC37c669 Super I/O controller.
1648 ** FORMAL PARAMETERS:
1651 ** Which device function
1654 ** I/O port for the function to use
1657 ** IRQ for the device function to use
1660 ** DMA channel for the device function to use
1664 ** Returns TRUE if the device function was configured,
1665 ** otherwise, FALSE.
1669 ** {@description or none@}
1673 ** If this function returns TRUE, the local shadow copy of
1674 ** the configuration is also updated. If the device function
1675 ** is currently disabled, only the local shadow copy is
1676 ** updated and the actual device function will be updated
1677 ** if/when it is enabled.
1681 unsigned int __init SMC37c669_configure_device (
1687 struct DEVICE_CONFIG *cp;
1690 ** Check for a valid configuration
1692 if ( ( cp = SMC37c669_get_config ( func ) ) != NULL ) {
1694 ** Configuration is valid, update the local shadow copy
1696 if ( ( drq & ~0xFF ) == 0 ) {
1699 if ( ( irq & ~0xFF ) == 0 ) {
1702 if ( ( port & ~0xFFFF ) == 0 ) {
1706 ** If the device function is enabled, update the actual
1707 ** device configuration.
1709 if ( SMC37c669_is_device_enabled( func ) ) {
1710 SMC37c669_enable_device( func );
1720 ** FUNCTIONAL DESCRIPTION:
1722 ** This function determines whether a device function
1723 ** within the SMC37c669 controller is enabled.
1725 ** FORMAL PARAMETERS:
1728 ** Which device function
1732 ** Returns TRUE if the device function is enabled, otherwise, FALSE
1736 ** {@description or none@}
1740 ** To check whether a device is enabled we will only look at
1741 ** the port base address mapping. According to the SMC37c669
1742 ** specification, all of the port base address mappings are
1743 ** disabled if the addr<9:8> (bits <7:6> of the register) are
1748 static unsigned int __init SMC37c669_is_device_enabled ( unsigned int func )
1750 unsigned char base_addr = 0;
1751 unsigned int dev_ok = FALSE;
1752 unsigned int ret_val = FALSE;
1754 ** Enter configuration mode
1756 SMC37c669_config_mode( TRUE );
1761 SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX );
1766 SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX );
1771 SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX );
1776 SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX );
1781 SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX );
1786 ** If we have a valid device, check base_addr<7:6> to see if the
1787 ** device is enabled (mapped).
1789 if ( ( dev_ok ) && ( ( base_addr & 0xC0 ) != 0 ) ) {
1791 ** The mapping is not disabled, so assume that the function is
1797 ** Exit configuration mode
1799 SMC37c669_config_mode( FALSE );
1808 ** FUNCTIONAL DESCRIPTION:
1810 ** This function retrieves the configuration information of a
1811 ** device function within the SMC37c699 Super I/O controller.
1813 ** FORMAL PARAMETERS:
1816 ** Which device function
1819 ** I/O port returned
1825 ** DMA channel returned
1829 ** Returns TRUE if the device configuration was successfully
1830 ** retrieved, otherwise, FALSE.
1834 ** The data pointed to by the port, irq, and drq parameters
1835 ** my be modified even if the configuration is not successfully
1840 ** The device configuration is fetched from the local shadow
1841 ** copy. Any unused parameters will be set to -1. Any
1842 ** parameter which is not desired can specify the NULL
1847 static unsigned int __init SMC37c669_get_device_config (
1853 struct DEVICE_CONFIG *cp;
1854 unsigned int ret_val = FALSE;
1856 ** Check for a valid device configuration
1858 if ( ( cp = SMC37c669_get_config( func ) ) != NULL ) {
1859 if ( drq != NULL ) {
1863 if ( irq != NULL ) {
1867 if ( port != NULL ) {
1879 ** FUNCTIONAL DESCRIPTION:
1881 ** This function displays the current state of the SMC37c699
1882 ** Super I/O controller's device functions.
1884 ** FORMAL PARAMETERS:
1898 void __init SMC37c669_display_device_info ( void )
1900 if ( SMC37c669_is_device_enabled( SERIAL_0 ) ) {
1901 printk( " Serial 0: Enabled [ Port 0x%x, IRQ %d ]\n",
1902 local_config[ SERIAL_0 ].port1,
1903 local_config[ SERIAL_0 ].irq
1907 printk( " Serial 0: Disabled\n" );
1910 if ( SMC37c669_is_device_enabled( SERIAL_1 ) ) {
1911 printk( " Serial 1: Enabled [ Port 0x%x, IRQ %d ]\n",
1912 local_config[ SERIAL_1 ].port1,
1913 local_config[ SERIAL_1 ].irq
1917 printk( " Serial 1: Disabled\n" );
1920 if ( SMC37c669_is_device_enabled( PARALLEL_0 ) ) {
1921 printk( " Parallel: Enabled [ Port 0x%x, IRQ %d/%d ]\n",
1922 local_config[ PARALLEL_0 ].port1,
1923 local_config[ PARALLEL_0 ].irq,
1924 local_config[ PARALLEL_0 ].drq
1928 printk( " Parallel: Disabled\n" );
1931 if ( SMC37c669_is_device_enabled( FLOPPY_0 ) ) {
1932 printk( " Floppy Ctrl: Enabled [ Port 0x%x, IRQ %d/%d ]\n",
1933 local_config[ FLOPPY_0 ].port1,
1934 local_config[ FLOPPY_0 ].irq,
1935 local_config[ FLOPPY_0 ].drq
1939 printk( " Floppy Ctrl: Disabled\n" );
1942 if ( SMC37c669_is_device_enabled( IDE_0 ) ) {
1943 printk( " IDE 0: Enabled [ Port 0x%x, IRQ %d ]\n",
1944 local_config[ IDE_0 ].port1,
1945 local_config[ IDE_0 ].irq
1949 printk( " IDE 0: Disabled\n" );
1956 ** FUNCTIONAL DESCRIPTION:
1958 ** This function puts the SMC37c669 Super I/O controller into,
1959 ** and takes it out of, configuration mode.
1961 ** FORMAL PARAMETERS:
1964 ** TRUE to enter configuration mode, FALSE to exit.
1972 ** The SMC37c669 controller may be left in configuration mode.
1976 static void __init SMC37c669_config_mode(
1977 unsigned int enable )
1981 ** To enter configuration mode, two writes in succession to the index
1982 ** port are required. If a write to another address or port occurs
1983 ** between these two writes, the chip does not enter configuration
1984 ** mode. Therefore, a spinlock is placed around the two writes to
1985 ** guarantee that they complete uninterrupted.
1987 spin_lock(&smc_lock);
1988 wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY );
1989 wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY );
1990 spin_unlock(&smc_lock);
1993 wb( &SMC37c669->index_port, SMC37c669_CONFIG_OFF_KEY );
1999 ** FUNCTIONAL DESCRIPTION:
2001 ** This function reads an SMC37c669 Super I/O controller
2002 ** configuration register. This function assumes that the
2003 ** device is already in configuration mode.
2005 ** FORMAL PARAMETERS:
2008 ** Index value of configuration register to read
2012 ** Data read from configuration register
2020 static unsigned char __init SMC37c669_read_config(
2021 unsigned char index )
2025 wb( &SMC37c669->index_port, index );
2026 data = rb( &SMC37c669->data_port );
2032 ** FUNCTIONAL DESCRIPTION:
2034 ** This function writes an SMC37c669 Super I/O controller
2035 ** configuration register. This function assumes that the
2036 ** device is already in configuration mode.
2038 ** FORMAL PARAMETERS:
2041 ** Index of configuration register to write
2044 ** Data to be written
2056 static void __init SMC37c669_write_config(
2057 unsigned char index,
2058 unsigned char data )
2060 wb( &SMC37c669->index_port, index );
2061 wb( &SMC37c669->data_port, data );
2067 ** FUNCTIONAL DESCRIPTION:
2069 ** This function initializes the local device
2070 ** configuration storage. This function assumes
2071 ** that the device is already in configuration
2074 ** FORMAL PARAMETERS:
2084 ** Local storage for device configuration information
2089 static void __init SMC37c669_init_local_config ( void )
2091 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER uart_base;
2092 SMC37c669_SERIAL_IRQ_REGISTER uart_irqs;
2093 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER ppt_base;
2094 SMC37c669_PARALLEL_FDC_IRQ_REGISTER ppt_fdc_irqs;
2095 SMC37c669_PARALLEL_FDC_DRQ_REGISTER ppt_fdc_drqs;
2096 SMC37c669_FDC_BASE_ADDRESS_REGISTER fdc_base;
2097 SMC37c669_IDE_ADDRESS_REGISTER ide_base;
2098 SMC37c669_IDE_ADDRESS_REGISTER ide_alt;
2101 ** Get serial port 1 base address
2103 uart_base.as_uchar =
2104 SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX );
2106 ** Get IRQs for serial ports 1 & 2
2108 uart_irqs.as_uchar =
2109 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
2111 ** Store local configuration information for serial port 1
2113 local_config[SERIAL_0].port1 = uart_base.by_field.addr9_3 << 3;
2114 local_config[SERIAL_0].irq =
2115 SMC37c669_xlate_irq(
2116 SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart1_irq )
2119 ** Get serial port 2 base address
2121 uart_base.as_uchar =
2122 SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX );
2124 ** Store local configuration information for serial port 2
2126 local_config[SERIAL_1].port1 = uart_base.by_field.addr9_3 << 3;
2127 local_config[SERIAL_1].irq =
2128 SMC37c669_xlate_irq(
2129 SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart2_irq )
2132 ** Get parallel port base address
2135 SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX );
2137 ** Get IRQs for parallel port and floppy controller
2139 ppt_fdc_irqs.as_uchar =
2140 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
2142 ** Get DRQs for parallel port and floppy controller
2144 ppt_fdc_drqs.as_uchar =
2145 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
2147 ** Store local configuration information for parallel port
2149 local_config[PARALLEL_0].port1 = ppt_base.by_field.addr9_2 << 2;
2150 local_config[PARALLEL_0].irq =
2151 SMC37c669_xlate_irq(
2152 SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.ppt_irq )
2154 local_config[PARALLEL_0].drq =
2155 SMC37c669_xlate_drq(
2156 SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.ppt_drq )
2159 ** Get floppy controller base address
2162 SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX );
2164 ** Store local configuration information for floppy controller
2166 local_config[FLOPPY_0].port1 = fdc_base.by_field.addr9_4 << 4;
2167 local_config[FLOPPY_0].irq =
2168 SMC37c669_xlate_irq(
2169 SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.fdc_irq )
2171 local_config[FLOPPY_0].drq =
2172 SMC37c669_xlate_drq(
2173 SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.fdc_drq )
2176 ** Get IDE controller base address
2179 SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX );
2181 ** Get IDE alternate status base address
2184 SMC37c669_read_config( SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX );
2186 ** Store local configuration information for IDE controller
2188 local_config[IDE_0].port1 = ide_base.by_field.addr9_4 << 4;
2189 local_config[IDE_0].port2 = ide_alt.by_field.addr9_4 << 4;
2190 local_config[IDE_0].irq = 14;
2196 ** FUNCTIONAL DESCRIPTION:
2198 ** This function returns a pointer to the local shadow
2199 ** configuration of the requested device function.
2201 ** FORMAL PARAMETERS:
2204 ** Which device function
2208 ** Returns a pointer to the DEVICE_CONFIG structure for the
2209 ** requested function, otherwise, NULL.
2213 ** {@description or none@}
2217 static struct DEVICE_CONFIG * __init SMC37c669_get_config( unsigned int func )
2219 struct DEVICE_CONFIG *cp = NULL;
2223 cp = &local_config[ SERIAL_0 ];
2226 cp = &local_config[ SERIAL_1 ];
2229 cp = &local_config[ PARALLEL_0 ];
2232 cp = &local_config[ FLOPPY_0 ];
2235 cp = &local_config[ IDE_0 ];
2243 ** FUNCTIONAL DESCRIPTION:
2245 ** This function translates IRQs back and forth between ISA
2246 ** IRQs and SMC37c669 device IRQs.
2248 ** FORMAL PARAMETERS:
2251 ** The IRQ to translate
2255 ** Returns the translated IRQ, otherwise, returns -1.
2259 ** {@description or none@}
2263 static int __init SMC37c669_xlate_irq ( int irq )
2265 int i, translated_irq = -1;
2267 if ( SMC37c669_IS_DEVICE_IRQ( irq ) ) {
2269 ** We are translating a device IRQ to an ISA IRQ
2271 for ( i = 0; ( SMC37c669_irq_table[i].device_irq != -1 ) || ( SMC37c669_irq_table[i].isa_irq != -1 ); i++ ) {
2272 if ( irq == SMC37c669_irq_table[i].device_irq ) {
2273 translated_irq = SMC37c669_irq_table[i].isa_irq;
2280 ** We are translating an ISA IRQ to a device IRQ
2282 for ( i = 0; ( SMC37c669_irq_table[i].isa_irq != -1 ) || ( SMC37c669_irq_table[i].device_irq != -1 ); i++ ) {
2283 if ( irq == SMC37c669_irq_table[i].isa_irq ) {
2284 translated_irq = SMC37c669_irq_table[i].device_irq;
2289 return translated_irq;
2295 ** FUNCTIONAL DESCRIPTION:
2297 ** This function translates DMA channels back and forth between
2298 ** ISA DMA channels and SMC37c669 device DMA channels.
2300 ** FORMAL PARAMETERS:
2303 ** The DMA channel to translate
2307 ** Returns the translated DMA channel, otherwise, returns -1
2311 ** {@description or none@}
2315 static int __init SMC37c669_xlate_drq ( int drq )
2317 int i, translated_drq = -1;
2319 if ( SMC37c669_IS_DEVICE_DRQ( drq ) ) {
2321 ** We are translating a device DMA channel to an ISA DMA channel
2323 for ( i = 0; ( SMC37c669_drq_table[i].device_drq != -1 ) || ( SMC37c669_drq_table[i].isa_drq != -1 ); i++ ) {
2324 if ( drq == SMC37c669_drq_table[i].device_drq ) {
2325 translated_drq = SMC37c669_drq_table[i].isa_drq;
2332 ** We are translating an ISA DMA channel to a device DMA channel
2334 for ( i = 0; ( SMC37c669_drq_table[i].isa_drq != -1 ) || ( SMC37c669_drq_table[i].device_drq != -1 ); i++ ) {
2335 if ( drq == SMC37c669_drq_table[i].isa_drq ) {
2336 translated_drq = SMC37c669_drq_table[i].device_drq;
2341 return translated_drq;
2345 int __init smcc669_init ( void )
2349 allocinode( smc_ddb.name, 1, &ip );
2351 ip->attr = ATTR$M_WRITE | ATTR$M_READ;
2359 int __init smcc669_open( struct FILE *fp, char *info, char *next, char *mode )
2363 ** Allow multiple readers but only one writer. ip->misc keeps track
2364 ** of the number of writers
2368 if ( fp->mode & ATTR$M_WRITE ) {
2371 return msg_failure; /* too many writers */
2376 ** Treat the information field as a byte offset
2378 *fp->offset = xtoi( info );
2384 int __init smcc669_close( struct FILE *fp )
2389 if ( fp->mode & ATTR$M_WRITE ) {
2397 int __init smcc669_read( struct FILE *fp, int size, int number, unsigned char *buf )
2405 ** Always access a byte at a time
2408 length = size * number;
2411 SMC37c669_config_mode( TRUE );
2412 for ( i = 0; i < length; i++ ) {
2413 if ( !inrange( *fp->offset, 0, ip->len[0] ) )
2415 *buf++ = SMC37c669_read_config( *fp->offset );
2419 SMC37c669_config_mode( FALSE );
2423 int __init smcc669_write( struct FILE *fp, int size, int number, unsigned char *buf )
2430 ** Always access a byte at a time
2433 length = size * number;
2436 SMC37c669_config_mode( TRUE );
2437 for ( i = 0; i < length; i++ ) {
2438 if ( !inrange( *fp->offset, 0, ip->len[0] ) )
2440 SMC37c669_write_config( *fp->offset, *buf );
2445 SMC37c669_config_mode( FALSE );
2451 SMC37c669_dump_registers(void)
2454 for (i = 0; i <= 0x29; i++)
2455 printk("-- CR%02x : %02x\n", i, SMC37c669_read_config(i));
2458 * ============================================================================
2459 * = SMC_init - SMC37c669 Super I/O controller initialization =
2460 * ============================================================================
2464 * This routine configures and enables device functions on the
2465 * SMC37c669 Super I/O controller.
2484 void __init SMC669_Init ( int index )
2486 SMC37c669_CONFIG_REGS *SMC_base;
2487 unsigned long flags;
2489 local_irq_save(flags);
2490 if ( ( SMC_base = SMC37c669_detect( index ) ) != NULL ) {
2492 SMC37c669_config_mode( TRUE );
2493 SMC37c669_dump_registers( );
2494 SMC37c669_config_mode( FALSE );
2495 SMC37c669_display_device_info( );
2497 SMC37c669_disable_device( SERIAL_0 );
2498 SMC37c669_configure_device(
2504 SMC37c669_enable_device( SERIAL_0 );
2506 SMC37c669_disable_device( SERIAL_1 );
2507 SMC37c669_configure_device(
2513 SMC37c669_enable_device( SERIAL_1 );
2515 SMC37c669_disable_device( PARALLEL_0 );
2516 SMC37c669_configure_device(
2522 SMC37c669_enable_device( PARALLEL_0 );
2524 SMC37c669_disable_device( FLOPPY_0 );
2525 SMC37c669_configure_device(
2531 SMC37c669_enable_device( FLOPPY_0 );
2533 /* Wake up sometimes forgotten floppy, especially on DP264. */
2536 SMC37c669_disable_device( IDE_0 );
2539 SMC37c669_config_mode( TRUE );
2540 SMC37c669_dump_registers( );
2541 SMC37c669_config_mode( FALSE );
2542 SMC37c669_display_device_info( );
2544 local_irq_restore(flags);
2545 printk( "SMC37c669 Super I/O Controller found @ 0x%p\n",
2549 local_irq_restore(flags);
2551 printk( "No SMC37c669 Super I/O Controller found\n" );