2 * SMC 37C669 initialization code
4 #include <linux/kernel.h>
7 #include <linux/init.h>
8 #include <linux/delay.h>
9 #include <linux/spinlock.h>
11 #include <asm/hwrpb.h>
15 # define DBG_DEVS(args) printk args
17 # define DBG_DEVS(args)
26 /* File: smcc669_def.h
28 * Copyright (C) 1997 by
29 * Digital Equipment Corporation, Maynard, Massachusetts.
30 * All rights reserved.
32 * This software is furnished under a license and may be used and copied
33 * only in accordance of the terms of such license and with the
34 * inclusion of the above copyright notice. This software or any other
35 * copies thereof may not be provided or otherwise made available to any
36 * other person. No title to and ownership of the software is hereby
39 * The information in this software is subject to change without notice
40 * and should not be construed as a commitment by Digital Equipment
43 * Digital assumes no responsibility for the use or reliability of its
44 * software on equipment which is not supplied by Digital.
49 * This file contains header definitions for the SMC37c669
50 * Super I/O controller.
56 * Modification History:
58 * er 28-Jan-1997 Initial Entry
65 ** Macros for handling device IRQs
67 ** The mask acts as a flag used in mapping actual ISA IRQs (0 - 15)
68 ** to device IRQs (A - H).
70 #define SMC37c669_DEVICE_IRQ_MASK 0x80000000
71 #define SMC37c669_DEVICE_IRQ( __i ) \
72 ((SMC37c669_DEVICE_IRQ_MASK) | (__i))
73 #define SMC37c669_IS_DEVICE_IRQ(__i) \
74 (((__i) & (SMC37c669_DEVICE_IRQ_MASK)) == (SMC37c669_DEVICE_IRQ_MASK))
75 #define SMC37c669_RAW_DEVICE_IRQ(__i) \
76 ((__i) & ~(SMC37c669_DEVICE_IRQ_MASK))
79 ** Macros for handling device DRQs
81 ** The mask acts as a flag used in mapping actual ISA DMA
82 ** channels to device DMA channels (A - C).
84 #define SMC37c669_DEVICE_DRQ_MASK 0x80000000
85 #define SMC37c669_DEVICE_DRQ(__d) \
86 ((SMC37c669_DEVICE_DRQ_MASK) | (__d))
87 #define SMC37c669_IS_DEVICE_DRQ(__d) \
88 (((__d) & (SMC37c669_DEVICE_DRQ_MASK)) == (SMC37c669_DEVICE_DRQ_MASK))
89 #define SMC37c669_RAW_DEVICE_DRQ(__d) \
90 ((__d) & ~(SMC37c669_DEVICE_DRQ_MASK))
92 #define SMC37c669_DEVICE_ID 0x3
95 ** SMC37c669 Device Function Definitions
105 ** Default Device Function Mappings
107 #define COM1_BASE 0x3F8
109 #define COM2_BASE 0x2F8
111 #define PARP_BASE 0x3BC
114 #define FDC_BASE 0x3F0
119 ** Configuration On/Off Key Definitions
121 #define SMC37c669_CONFIG_ON_KEY 0x55
122 #define SMC37c669_CONFIG_OFF_KEY 0xAA
125 ** SMC 37c669 Device IRQs
127 #define SMC37c669_DEVICE_IRQ_A ( SMC37c669_DEVICE_IRQ( 0x01 ) )
128 #define SMC37c669_DEVICE_IRQ_B ( SMC37c669_DEVICE_IRQ( 0x02 ) )
129 #define SMC37c669_DEVICE_IRQ_C ( SMC37c669_DEVICE_IRQ( 0x03 ) )
130 #define SMC37c669_DEVICE_IRQ_D ( SMC37c669_DEVICE_IRQ( 0x04 ) )
131 #define SMC37c669_DEVICE_IRQ_E ( SMC37c669_DEVICE_IRQ( 0x05 ) )
132 #define SMC37c669_DEVICE_IRQ_F ( SMC37c669_DEVICE_IRQ( 0x06 ) )
133 /* SMC37c669_DEVICE_IRQ_G *** RESERVED ***/
134 #define SMC37c669_DEVICE_IRQ_H ( SMC37c669_DEVICE_IRQ( 0x08 ) )
137 ** SMC 37c669 Device DMA Channel Definitions
139 #define SMC37c669_DEVICE_DRQ_A ( SMC37c669_DEVICE_DRQ( 0x01 ) )
140 #define SMC37c669_DEVICE_DRQ_B ( SMC37c669_DEVICE_DRQ( 0x02 ) )
141 #define SMC37c669_DEVICE_DRQ_C ( SMC37c669_DEVICE_DRQ( 0x03 ) )
144 ** Configuration Register Index Definitions
146 #define SMC37c669_CR00_INDEX 0x00
147 #define SMC37c669_CR01_INDEX 0x01
148 #define SMC37c669_CR02_INDEX 0x02
149 #define SMC37c669_CR03_INDEX 0x03
150 #define SMC37c669_CR04_INDEX 0x04
151 #define SMC37c669_CR05_INDEX 0x05
152 #define SMC37c669_CR06_INDEX 0x06
153 #define SMC37c669_CR07_INDEX 0x07
154 #define SMC37c669_CR08_INDEX 0x08
155 #define SMC37c669_CR09_INDEX 0x09
156 #define SMC37c669_CR0A_INDEX 0x0A
157 #define SMC37c669_CR0B_INDEX 0x0B
158 #define SMC37c669_CR0C_INDEX 0x0C
159 #define SMC37c669_CR0D_INDEX 0x0D
160 #define SMC37c669_CR0E_INDEX 0x0E
161 #define SMC37c669_CR0F_INDEX 0x0F
162 #define SMC37c669_CR10_INDEX 0x10
163 #define SMC37c669_CR11_INDEX 0x11
164 #define SMC37c669_CR12_INDEX 0x12
165 #define SMC37c669_CR13_INDEX 0x13
166 #define SMC37c669_CR14_INDEX 0x14
167 #define SMC37c669_CR15_INDEX 0x15
168 #define SMC37c669_CR16_INDEX 0x16
169 #define SMC37c669_CR17_INDEX 0x17
170 #define SMC37c669_CR18_INDEX 0x18
171 #define SMC37c669_CR19_INDEX 0x19
172 #define SMC37c669_CR1A_INDEX 0x1A
173 #define SMC37c669_CR1B_INDEX 0x1B
174 #define SMC37c669_CR1C_INDEX 0x1C
175 #define SMC37c669_CR1D_INDEX 0x1D
176 #define SMC37c669_CR1E_INDEX 0x1E
177 #define SMC37c669_CR1F_INDEX 0x1F
178 #define SMC37c669_CR20_INDEX 0x20
179 #define SMC37c669_CR21_INDEX 0x21
180 #define SMC37c669_CR22_INDEX 0x22
181 #define SMC37c669_CR23_INDEX 0x23
182 #define SMC37c669_CR24_INDEX 0x24
183 #define SMC37c669_CR25_INDEX 0x25
184 #define SMC37c669_CR26_INDEX 0x26
185 #define SMC37c669_CR27_INDEX 0x27
186 #define SMC37c669_CR28_INDEX 0x28
187 #define SMC37c669_CR29_INDEX 0x29
190 ** Configuration Register Alias Definitions
192 #define SMC37c669_DEVICE_ID_INDEX SMC37c669_CR0D_INDEX
193 #define SMC37c669_DEVICE_REVISION_INDEX SMC37c669_CR0E_INDEX
194 #define SMC37c669_FDC_BASE_ADDRESS_INDEX SMC37c669_CR20_INDEX
195 #define SMC37c669_IDE_BASE_ADDRESS_INDEX SMC37c669_CR21_INDEX
196 #define SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX SMC37c669_CR22_INDEX
197 #define SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX SMC37c669_CR23_INDEX
198 #define SMC37c669_SERIAL0_BASE_ADDRESS_INDEX SMC37c669_CR24_INDEX
199 #define SMC37c669_SERIAL1_BASE_ADDRESS_INDEX SMC37c669_CR25_INDEX
200 #define SMC37c669_PARALLEL_FDC_DRQ_INDEX SMC37c669_CR26_INDEX
201 #define SMC37c669_PARALLEL_FDC_IRQ_INDEX SMC37c669_CR27_INDEX
202 #define SMC37c669_SERIAL_IRQ_INDEX SMC37c669_CR28_INDEX
205 ** Configuration Register Definitions
207 ** The INDEX (write only) and DATA (read/write) ports are effective
208 ** only when the chip is in the Configuration State.
210 typedef struct _SMC37c669_CONFIG_REGS
{
211 unsigned char index_port
;
212 unsigned char data_port
;
213 } SMC37c669_CONFIG_REGS
;
216 ** CR00 - default value 0x28
218 ** IDE_EN (CR00<1:0>):
219 ** 0x - 30ua pull-ups on nIDEEN, nHDCS0, NHDCS1
220 ** 11 - IRQ_H available as IRQ output,
221 ** IRRX2, IRTX2 available as alternate IR pins
222 ** 10 - nIDEEN, nHDCS0, nHDCS1 used to control IDE
225 ** A high level on this software controlled bit can
226 ** be used to indicate that a valid configuration
227 ** cycle has occurred. The control software must
228 ** take care to set this bit at the appropriate times.
229 ** Set to zero after power up. This bit has no
230 ** effect on any other hardware in the chip.
233 typedef union _SMC37c669_CR00
{
234 unsigned char as_uchar
;
236 unsigned ide_en
: 2; /* See note above */
237 unsigned reserved1
: 1; /* RAZ */
238 unsigned fdc_pwr
: 1; /* 1 = supply power to FDC */
239 unsigned reserved2
: 3; /* Read as 010b */
240 unsigned valid
: 1; /* See note above */
245 ** CR01 - default value 0x9C
247 typedef union _SMC37c669_CR01
{
248 unsigned char as_uchar
;
250 unsigned reserved1
: 2; /* RAZ */
251 unsigned ppt_pwr
: 1; /* 1 = supply power to PPT */
252 unsigned ppt_mode
: 1; /* 1 = Printer mode, 0 = EPP */
253 unsigned reserved2
: 1; /* Read as 1 */
254 unsigned reserved3
: 2; /* RAZ */
255 unsigned lock_crx
: 1; /* Lock CR00 - CR18 */
260 ** CR02 - default value 0x88
262 typedef union _SMC37c669_CR02
{
263 unsigned char as_uchar
;
265 unsigned reserved1
: 3; /* RAZ */
266 unsigned uart1_pwr
: 1; /* 1 = supply power to UART1 */
267 unsigned reserved2
: 3; /* RAZ */
268 unsigned uart2_pwr
: 1; /* 1 = supply power to UART2 */
273 ** CR03 - default value 0x78
275 ** CR03<7> CR03<2> Pin 94
276 ** ------- ------- ------
281 ** CR03<6> CR03<5> Op Mode
282 ** ------- ------- -------
288 typedef union _SMC37c669_CR03
{
289 unsigned char as_uchar
;
291 unsigned pwrgd_gamecs
: 1; /* 1 = PWRGD, 0 = GAMECS */
292 unsigned fdc_mode2
: 1; /* 1 = Enhanced Mode 2 */
293 unsigned pin94_0
: 1; /* See note above */
294 unsigned reserved1
: 1; /* RAZ */
295 unsigned drvden
: 1; /* 1 = high, 0 - output */
296 unsigned op_mode
: 2; /* See note above */
297 unsigned pin94_1
: 1; /* See note above */
302 ** CR04 - default value 0x00
305 ** If CR01<PP_MODE> = 0 and PP_EXT_MODE =
306 ** 00 - Standard and Bidirectional
307 ** 01 - EPP mode and SPP
309 ** In this mode, 2 drives can be supported
310 ** directly, 3 or 4 drives must use external
311 ** 4 drive support. SPP can be selected
312 ** through the ECR register of ECP as mode 000.
313 ** 11 - ECP mode and EPP mode
314 ** In this mode, 2 drives can be supported
315 ** directly, 3 or 4 drives must use external
316 ** 4 drive support. SPP can be selected
317 ** through the ECR register of ECP as mode 000.
318 ** In this mode, EPP can be selected through
319 ** the ECR register of ECP as mode 100.
328 ** Serial Clock Select:
329 ** A low level on this bit disables MIDI support,
330 ** clock = divide by 13. A high level on this
331 ** bit enables MIDI support, clock = divide by 12.
333 ** MIDI operates at 31.25 Kbps which can be derived
334 ** from 125 KHz (24 MHz / 12 = 2 MHz, 2 MHz / 16 = 125 KHz)
337 ** 0 - Use pins IRRX, IRTX
338 ** 1 - Use pins IRRX2, IRTX2
340 ** If this bit is set, the IR receive and transmit
341 ** functions will not be available on pins 25 and 26
342 ** unless CR00<IDE_EN> = 11.
344 typedef union _SMC37c669_CR04
{
345 unsigned char as_uchar
;
347 unsigned ppt_ext_mode
: 2; /* See note above */
348 unsigned ppt_fdc
: 2; /* See note above */
349 unsigned midi1
: 1; /* See note above */
350 unsigned midi2
: 1; /* See note above */
351 unsigned epp_type
: 1; /* 0 = EPP 1.9, 1 = EPP 1.7 */
352 unsigned alt_io
: 1; /* See note above */
357 ** CR05 - default value 0x00
360 ** 00 - Densel output normal
362 ** 10 - Densel output 1
363 ** 11 - Densel output 0
366 typedef union _SMC37c669_CR05
{
367 unsigned char as_uchar
;
369 unsigned reserved1
: 2; /* RAZ */
370 unsigned fdc_dma_mode
: 1; /* 0 = burst, 1 = non-burst */
371 unsigned den_sel
: 2; /* See note above */
372 unsigned swap_drv
: 1; /* Swap the FDC motor selects */
373 unsigned extx4
: 1; /* 0 = 2 drive, 1 = external 4 drive decode */
374 unsigned reserved2
: 1; /* RAZ */
379 ** CR06 - default value 0xFF
381 typedef union _SMC37c669_CR06
{
382 unsigned char as_uchar
;
384 unsigned floppy_a
: 2; /* Type of floppy drive A */
385 unsigned floppy_b
: 2; /* Type of floppy drive B */
386 unsigned floppy_c
: 2; /* Type of floppy drive C */
387 unsigned floppy_d
: 2; /* Type of floppy drive D */
392 ** CR07 - default value 0x00
394 ** Auto Power Management CR07<7:4>:
395 ** 0 - Auto Powerdown disabled (default)
396 ** 1 - Auto Powerdown enabled
398 ** This bit is reset to the default state by POR or
402 typedef union _SMC37c669_CR07
{
403 unsigned char as_uchar
;
405 unsigned floppy_boot
: 2; /* 0 = A:, 1 = B: */
406 unsigned reserved1
: 2; /* RAZ */
407 unsigned ppt_en
: 1; /* See note above */
408 unsigned uart1_en
: 1; /* See note above */
409 unsigned uart2_en
: 1; /* See note above */
410 unsigned fdc_en
: 1; /* See note above */
415 ** CR08 - default value 0x00
417 typedef union _SMC37c669_CR08
{
418 unsigned char as_uchar
;
420 unsigned zero
: 4; /* 0 */
421 unsigned addrx7_4
: 4; /* ADR<7:3> for ADRx decode */
426 ** CR09 - default value 0x00
429 ** 00 - ADRx disabled
430 ** 01 - 1 byte decode A<3:0> = 0000b
431 ** 10 - 8 byte block decode A<3:0> = 0XXXb
432 ** 11 - 16 byte block decode A<3:0> = XXXXb
435 typedef union _SMC37c669_CR09
{
436 unsigned char as_uchar
;
438 unsigned adra8
: 3; /* ADR<10:8> for ADRx decode */
439 unsigned reserved1
: 3;
440 unsigned adrx_config
: 2; /* See note above */
445 ** CR0A - default value 0x00
447 typedef union _SMC37c669_CR0A
{
448 unsigned char as_uchar
;
450 unsigned ecp_fifo_threshold
: 4;
451 unsigned reserved1
: 4;
456 ** CR0B - default value 0x00
458 typedef union _SMC37c669_CR0B
{
459 unsigned char as_uchar
;
461 unsigned fdd0_drtx
: 2; /* FDD0 Data Rate Table */
462 unsigned fdd1_drtx
: 2; /* FDD1 Data Rate Table */
463 unsigned fdd2_drtx
: 2; /* FDD2 Data Rate Table */
464 unsigned fdd3_drtx
: 2; /* FDD3 Data Rate Table */
469 ** CR0C - default value 0x00
472 ** 000 - Standard (default)
473 ** 001 - IrDA (HPSIR)
474 ** 010 - Amplitude Shift Keyed IR @500 KHz
479 typedef union _SMC37c669_CR0C
{
480 unsigned char as_uchar
;
482 unsigned uart2_rcv_polarity
: 1; /* 1 = invert RX */
483 unsigned uart2_xmit_polarity
: 1; /* 1 = invert TX */
484 unsigned uart2_duplex
: 1; /* 1 = full, 0 = half */
485 unsigned uart2_mode
: 3; /* See note above */
486 unsigned uart1_speed
: 1; /* 1 = high speed enabled */
487 unsigned uart2_speed
: 1; /* 1 = high speed enabled */
492 ** CR0D - default value 0x03
494 ** Device ID Register - read only
496 typedef union _SMC37c669_CR0D
{
497 unsigned char as_uchar
;
499 unsigned device_id
: 8; /* Returns 0x3 in this field */
504 ** CR0E - default value 0x02
506 ** Device Revision Register - read only
508 typedef union _SMC37c669_CR0E
{
509 unsigned char as_uchar
;
511 unsigned device_rev
: 8; /* Returns 0x2 in this field */
516 ** CR0F - default value 0x00
518 typedef union _SMC37c669_CR0F
{
519 unsigned char as_uchar
;
521 unsigned test0
: 1; /* Reserved - set to 0 */
522 unsigned test1
: 1; /* Reserved - set to 0 */
523 unsigned test2
: 1; /* Reserved - set to 0 */
524 unsigned test3
: 1; /* Reserved - set t0 0 */
525 unsigned test4
: 1; /* Reserved - set to 0 */
526 unsigned test5
: 1; /* Reserved - set t0 0 */
527 unsigned test6
: 1; /* Reserved - set t0 0 */
528 unsigned test7
: 1; /* Reserved - set to 0 */
533 ** CR10 - default value 0x00
535 typedef union _SMC37c669_CR10
{
536 unsigned char as_uchar
;
538 unsigned reserved1
: 3; /* RAZ */
539 unsigned pll_gain
: 1; /* 1 = 3V, 2 = 5V operation */
540 unsigned pll_stop
: 1; /* 1 = stop PLLs */
541 unsigned ace_stop
: 1; /* 1 = stop UART clocks */
542 unsigned pll_clock_ctrl
: 1; /* 0 = 14.318 MHz, 1 = 24 MHz */
543 unsigned ir_test
: 1; /* Enable IR test mode */
548 ** CR11 - default value 0x00
550 typedef union _SMC37c669_CR11
{
551 unsigned char as_uchar
;
553 unsigned ir_loopback
: 1; /* Internal IR loop back */
554 unsigned test_10ms
: 1; /* Test 10ms autopowerdown FDC timeout */
555 unsigned reserved1
: 6; /* RAZ */
560 ** CR12 - CR1D are reserved registers
564 ** CR1E - default value 0x80
567 ** 00 - GAMECS disabled
568 ** 01 - 1 byte decode ADR<3:0> = 0001b
569 ** 10 - 8 byte block decode ADR<3:0> = 0XXXb
570 ** 11 - 16 byte block decode ADR<3:0> = XXXXb
573 typedef union _SMC37c66_CR1E
{
574 unsigned char as_uchar
;
576 unsigned gamecs_config
: 2; /* See note above */
577 unsigned gamecs_addr9_4
: 6; /* GAMECS Addr<9:4> */
582 ** CR1F - default value 0x00
584 ** DT0 DT1 DRVDEN0 DRVDEN1 Drive Type
585 ** --- --- ------- ------- ----------
586 ** 0 0 DENSEL DRATE0 4/2/1 MB 3.5"
588 ** 2/1.6/1 MB 3.5" (3-mode)
590 ** 1 0 nDENSEL DRATE0 PS/2
593 ** Note: DENSEL, DRATE1, and DRATE0 map onto two output
594 ** pins - DRVDEN0 and DRVDEN1.
597 typedef union _SMC37c669_CR1F
{
598 unsigned char as_uchar
;
600 unsigned fdd0_drive_type
: 2; /* FDD0 drive type */
601 unsigned fdd1_drive_type
: 2; /* FDD1 drive type */
602 unsigned fdd2_drive_type
: 2; /* FDD2 drive type */
603 unsigned fdd3_drive_type
: 2; /* FDD3 drive type */
608 ** CR20 - default value 0x3C
610 ** FDC Base Address Register
611 ** - To disable this decode set Addr<9:8> = 0
612 ** - A<10> = 0, A<3:0> = 0XXXb to access.
615 typedef union _SMC37c669_CR20
{
616 unsigned char as_uchar
;
618 unsigned zero
: 2; /* 0 */
619 unsigned addr9_4
: 6; /* FDC Addr<9:4> */
624 ** CR21 - default value 0x3C
626 ** IDE Base Address Register
627 ** - To disable this decode set Addr<9:8> = 0
628 ** - A<10> = 0, A<3:0> = 0XXXb to access.
631 typedef union _SMC37c669_CR21
{
632 unsigned char as_uchar
;
634 unsigned zero
: 2; /* 0 */
635 unsigned addr9_4
: 6; /* IDE Addr<9:4> */
640 ** CR22 - default value 0x3D
642 ** IDE Alternate Status Base Address Register
643 ** - To disable this decode set Addr<9:8> = 0
644 ** - A<10> = 0, A<3:0> = 0110b to access.
647 typedef union _SMC37c669_CR22
{
648 unsigned char as_uchar
;
650 unsigned zero
: 2; /* 0 */
651 unsigned addr9_4
: 6; /* IDE Alt Status Addr<9:4> */
656 ** CR23 - default value 0x00
658 ** Parallel Port Base Address Register
659 ** - To disable this decode set Addr<9:8> = 0
660 ** - A<10> = 0 to access.
661 ** - If EPP is enabled, A<2:0> = XXXb to access.
662 ** If EPP is NOT enabled, A<1:0> = XXb to access
665 typedef union _SMC37c669_CR23
{
666 unsigned char as_uchar
;
668 unsigned addr9_2
: 8; /* Parallel Port Addr<9:2> */
673 ** CR24 - default value 0x00
675 ** UART1 Base Address Register
676 ** - To disable this decode set Addr<9:8> = 0
677 ** - A<10> = 0, A<2:0> = XXXb to access.
680 typedef union _SMC37c669_CR24
{
681 unsigned char as_uchar
;
683 unsigned zero
: 1; /* 0 */
684 unsigned addr9_3
: 7; /* UART1 Addr<9:3> */
689 ** CR25 - default value 0x00
691 ** UART2 Base Address Register
692 ** - To disable this decode set Addr<9:8> = 0
693 ** - A<10> = 0, A<2:0> = XXXb to access.
696 typedef union _SMC37c669_CR25
{
697 unsigned char as_uchar
;
699 unsigned zero
: 1; /* 0 */
700 unsigned addr9_3
: 7; /* UART2 Addr<9:3> */
705 ** CR26 - default value 0x00
707 ** Parallel Port / FDC DMA Select Register
718 typedef union _SMC37c669_CR26
{
719 unsigned char as_uchar
;
721 unsigned ppt_drq
: 4; /* See note above */
722 unsigned fdc_drq
: 4; /* See note above */
727 ** CR27 - default value 0x00
729 ** Parallel Port / FDC IRQ Select Register
744 ** Any unselected IRQ REQ is in tristate
747 typedef union _SMC37c669_CR27
{
748 unsigned char as_uchar
;
750 unsigned ppt_irq
: 4; /* See note above */
751 unsigned fdc_irq
: 4; /* See note above */
756 ** CR28 - default value 0x00
758 ** UART IRQ Select Register
772 ** 1111 share with UART1 (only for UART2)
774 ** Any unselected IRQ REQ is in tristate
776 ** To share an IRQ between UART1 and UART2, set
777 ** UART1 to use the desired IRQ and set UART2 to
778 ** 0xF to enable sharing mechanism.
781 typedef union _SMC37c669_CR28
{
782 unsigned char as_uchar
;
784 unsigned uart2_irq
: 4; /* See note above */
785 unsigned uart1_irq
: 4; /* See note above */
790 ** CR29 - default value 0x00
792 ** IRQIN IRQ Select Register
807 ** Any unselected IRQ REQ is in tristate
810 typedef union _SMC37c669_CR29
{
811 unsigned char as_uchar
;
813 unsigned irqin_irq
: 4; /* See note above */
814 unsigned reserved1
: 4; /* RAZ */
819 ** Aliases of Configuration Register formats (should match
820 ** the set of index aliases).
822 ** Note that CR24 and CR25 have the same format and are the
823 ** base address registers for UART1 and UART2. Because of
824 ** this we only define 1 alias here - for CR24 - as the serial
825 ** base address register.
827 ** Note that CR21 and CR22 have the same format and are the
828 ** base address and alternate status address registers for
829 ** the IDE controller. Because of this we only define 1 alias
830 ** here - for CR21 - as the IDE address register.
833 typedef SMC37c669_CR0D SMC37c669_DEVICE_ID_REGISTER
;
834 typedef SMC37c669_CR0E SMC37c669_DEVICE_REVISION_REGISTER
;
835 typedef SMC37c669_CR20 SMC37c669_FDC_BASE_ADDRESS_REGISTER
;
836 typedef SMC37c669_CR21 SMC37c669_IDE_ADDRESS_REGISTER
;
837 typedef SMC37c669_CR23 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER
;
838 typedef SMC37c669_CR24 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER
;
839 typedef SMC37c669_CR26 SMC37c669_PARALLEL_FDC_DRQ_REGISTER
;
840 typedef SMC37c669_CR27 SMC37c669_PARALLEL_FDC_IRQ_REGISTER
;
841 typedef SMC37c669_CR28 SMC37c669_SERIAL_IRQ_REGISTER
;
844 ** ISA/Device IRQ Translation Table Entry Definition
846 typedef struct _SMC37c669_IRQ_TRANSLATION_ENTRY
{
849 } SMC37c669_IRQ_TRANSLATION_ENTRY
;
852 ** ISA/Device DMA Translation Table Entry Definition
854 typedef struct _SMC37c669_DRQ_TRANSLATION_ENTRY
{
857 } SMC37c669_DRQ_TRANSLATION_ENTRY
;
860 ** External Interface Function Prototype Declarations
863 SMC37c669_CONFIG_REGS
*SMC37c669_detect(
867 unsigned int SMC37c669_enable_device(
871 unsigned int SMC37c669_disable_device(
875 unsigned int SMC37c669_configure_device(
882 void SMC37c669_display_device_info(
886 #endif /* __SMC37c669_H */
890 * Copyright (C) 1997 by
891 * Digital Equipment Corporation, Maynard, Massachusetts.
892 * All rights reserved.
894 * This software is furnished under a license and may be used and copied
895 * only in accordance of the terms of such license and with the
896 * inclusion of the above copyright notice. This software or any other
897 * copies thereof may not be provided or otherwise made available to any
898 * other person. No title to and ownership of the software is hereby
901 * The information in this software is subject to change without notice
902 * and should not be construed as a commitment by digital equipment
905 * Digital assumes no responsibility for the use or reliability of its
906 * software on equipment which is not supplied by digital.
913 * Alpha SRM Console Firmware
915 * MODULE DESCRIPTION:
917 * SMC37c669 Super I/O controller configuration routines.
927 * MODIFICATION HISTORY:
929 * er 01-May-1997 Fixed pointer conversion errors in
930 * SMC37c669_get_device_config().
931 * er 28-Jan-1997 Initial version.
943 #define wb( _x_, _y_ ) outb( _y_, (unsigned int)((unsigned long)_x_) )
944 #define rb( _x_ ) inb( (unsigned int)((unsigned long)_x_) )
947 ** Local storage for device configuration information.
949 ** Since the SMC37c669 does not provide an explicit
950 ** mechanism for enabling/disabling individual device
951 ** functions, other than unmapping the device, local
952 ** storage for device configuration information is
953 ** allocated here for use in implementing our own
954 ** function enable/disable scheme.
956 static struct DEVICE_CONFIG
{
961 } local_config
[NUM_FUNCS
];
964 ** List of all possible addresses for the Super I/O chip
966 static unsigned long SMC37c669_Addresses
[] __initdata
=
968 0x3F0UL
, /* Primary address */
969 0x370UL
, /* Secondary address */
970 0UL /* End of list */
974 ** Global Pointer to the Super I/O device
976 static SMC37c669_CONFIG_REGS
*SMC37c669 __initdata
= NULL
;
979 ** IRQ Translation Table
981 ** The IRQ translation table is a list of SMC37c669 device
982 ** and standard ISA IRQs.
985 static SMC37c669_IRQ_TRANSLATION_ENTRY
*SMC37c669_irq_table __initdata
;
988 ** The following definition is for the default IRQ
989 ** translation table.
991 static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_default_irq_table
[]
994 { SMC37c669_DEVICE_IRQ_A
, -1 },
995 { SMC37c669_DEVICE_IRQ_B
, -1 },
996 { SMC37c669_DEVICE_IRQ_C
, 7 },
997 { SMC37c669_DEVICE_IRQ_D
, 6 },
998 { SMC37c669_DEVICE_IRQ_E
, 4 },
999 { SMC37c669_DEVICE_IRQ_F
, 3 },
1000 { SMC37c669_DEVICE_IRQ_H
, -1 },
1001 { -1, -1 } /* End of table */
1005 ** The following definition is for the MONET (XP1000) IRQ
1006 ** translation table.
1008 static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_monet_irq_table
[]
1011 { SMC37c669_DEVICE_IRQ_A
, -1 },
1012 { SMC37c669_DEVICE_IRQ_B
, -1 },
1013 { SMC37c669_DEVICE_IRQ_C
, 6 },
1014 { SMC37c669_DEVICE_IRQ_D
, 7 },
1015 { SMC37c669_DEVICE_IRQ_E
, 4 },
1016 { SMC37c669_DEVICE_IRQ_F
, 3 },
1017 { SMC37c669_DEVICE_IRQ_H
, -1 },
1018 { -1, -1 } /* End of table */
1021 static SMC37c669_IRQ_TRANSLATION_ENTRY
*SMC37c669_irq_tables
[] __initdata
=
1023 SMC37c669_default_irq_table
,
1024 SMC37c669_monet_irq_table
1028 ** DRQ Translation Table
1030 ** The DRQ translation table is a list of SMC37c669 device and
1031 ** ISA DMA channels.
1034 static SMC37c669_DRQ_TRANSLATION_ENTRY
*SMC37c669_drq_table __initdata
;
1037 ** The following definition is the default DRQ
1038 ** translation table.
1040 static SMC37c669_DRQ_TRANSLATION_ENTRY SMC37c669_default_drq_table
[]
1043 { SMC37c669_DEVICE_DRQ_A
, 2 },
1044 { SMC37c669_DEVICE_DRQ_B
, 3 },
1045 { SMC37c669_DEVICE_DRQ_C
, -1 },
1046 { -1, -1 } /* End of table */
1050 ** Local Function Prototype Declarations
1053 static unsigned int SMC37c669_is_device_enabled(
1058 static unsigned int SMC37c669_get_device_config(
1066 static void SMC37c669_config_mode(
1070 static unsigned char SMC37c669_read_config(
1074 static void SMC37c669_write_config(
1075 unsigned char index
,
1079 static void SMC37c669_init_local_config( void );
1081 static struct DEVICE_CONFIG
*SMC37c669_get_config(
1085 static int SMC37c669_xlate_irq(
1089 static int SMC37c669_xlate_drq(
1093 static __cacheline_aligned
DEFINE_SPINLOCK(smc_lock
);
1097 ** FUNCTIONAL DESCRIPTION:
1099 ** This function detects the presence of an SMC37c669 Super I/O
1102 ** FORMAL PARAMETERS:
1108 ** Returns a pointer to the device if found, otherwise,
1109 ** the NULL pointer is returned.
1117 SMC37c669_CONFIG_REGS
* __init
SMC37c669_detect( int index
)
1120 SMC37c669_DEVICE_ID_REGISTER id
;
1122 for ( i
= 0; SMC37c669_Addresses
[i
] != 0; i
++ ) {
1124 ** Initialize the device pointer even though we don't yet know if
1125 ** the controller is at this address. The support functions access
1126 ** the controller through this device pointer so we need to set it
1127 ** even when we are looking ...
1129 SMC37c669
= ( SMC37c669_CONFIG_REGS
* )SMC37c669_Addresses
[i
];
1131 ** Enter configuration mode
1133 SMC37c669_config_mode( TRUE
);
1135 ** Read the device id
1137 id
.as_uchar
= SMC37c669_read_config( SMC37c669_DEVICE_ID_INDEX
);
1139 ** Exit configuration mode
1141 SMC37c669_config_mode( FALSE
);
1143 ** Does the device id match? If so, assume we have found an
1144 ** SMC37c669 controller at this address.
1146 if ( id
.by_field
.device_id
== SMC37c669_DEVICE_ID
) {
1148 ** Initialize the IRQ and DRQ translation tables.
1150 SMC37c669_irq_table
= SMC37c669_irq_tables
[ index
];
1151 SMC37c669_drq_table
= SMC37c669_default_drq_table
;
1155 ** If the platform can't use the IRQ and DRQ defaults set up in this
1156 ** file, it should call a platform-specific external routine at this
1157 ** point to reset the IRQ and DRQ translation table pointers to point
1158 ** at the appropriate tables for the platform. If the defaults are
1159 ** acceptable, then the external routine should do nothing.
1163 ** Put the chip back into configuration mode
1165 SMC37c669_config_mode( TRUE
);
1167 ** Initialize local storage for configuration information
1169 SMC37c669_init_local_config( );
1171 ** Exit configuration mode
1173 SMC37c669_config_mode( FALSE
);
1175 ** SMC37c669 controller found, break out of search loop
1181 ** Otherwise, we did not find an SMC37c669 controller at this
1182 ** address so set the device pointer to NULL.
1193 ** FUNCTIONAL DESCRIPTION:
1195 ** This function enables an SMC37c669 device function.
1197 ** FORMAL PARAMETERS:
1200 ** Which device function to enable
1204 ** Returns TRUE is the device function was enabled, otherwise, FALSE
1208 ** {@description or none@}
1212 ** Enabling a device function in the SMC37c669 controller involves
1213 ** setting all of its mappings (port, irq, drq ...). A local
1214 ** "shadow" copy of the device configuration is kept so we can
1215 ** just set each mapping to what the local copy says.
1217 ** This function ALWAYS updates the local shadow configuration of
1218 ** the device function being enabled, even if the device is always
1219 ** enabled. To avoid replication of code, functions such as
1220 ** configure_device set up the local copy and then call this
1221 ** function to the update the real device.
1225 unsigned int __init
SMC37c669_enable_device ( unsigned int func
)
1227 unsigned int ret_val
= FALSE
;
1229 ** Put the device into configuration mode
1231 SMC37c669_config_mode( TRUE
);
1235 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr
;
1236 SMC37c669_SERIAL_IRQ_REGISTER irq
;
1238 ** Enable the serial 1 IRQ mapping
1241 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX
);
1243 irq
.by_field
.uart1_irq
=
1244 SMC37c669_RAW_DEVICE_IRQ(
1245 SMC37c669_xlate_irq( local_config
[ func
].irq
)
1248 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX
, irq
.as_uchar
);
1250 ** Enable the serial 1 port base address mapping
1252 base_addr
.as_uchar
= 0;
1253 base_addr
.by_field
.addr9_3
= local_config
[ func
].port1
>> 3;
1255 SMC37c669_write_config(
1256 SMC37c669_SERIAL0_BASE_ADDRESS_INDEX
,
1264 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr
;
1265 SMC37c669_SERIAL_IRQ_REGISTER irq
;
1267 ** Enable the serial 2 IRQ mapping
1270 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX
);
1272 irq
.by_field
.uart2_irq
=
1273 SMC37c669_RAW_DEVICE_IRQ(
1274 SMC37c669_xlate_irq( local_config
[ func
].irq
)
1277 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX
, irq
.as_uchar
);
1279 ** Enable the serial 2 port base address mapping
1281 base_addr
.as_uchar
= 0;
1282 base_addr
.by_field
.addr9_3
= local_config
[ func
].port1
>> 3;
1284 SMC37c669_write_config(
1285 SMC37c669_SERIAL1_BASE_ADDRESS_INDEX
,
1293 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr
;
1294 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq
;
1295 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq
;
1297 ** Enable the parallel port DMA channel mapping
1300 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX
);
1302 drq
.by_field
.ppt_drq
=
1303 SMC37c669_RAW_DEVICE_DRQ(
1304 SMC37c669_xlate_drq( local_config
[ func
].drq
)
1307 SMC37c669_write_config(
1308 SMC37c669_PARALLEL_FDC_DRQ_INDEX
,
1312 ** Enable the parallel port IRQ mapping
1315 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX
);
1317 irq
.by_field
.ppt_irq
=
1318 SMC37c669_RAW_DEVICE_IRQ(
1319 SMC37c669_xlate_irq( local_config
[ func
].irq
)
1322 SMC37c669_write_config(
1323 SMC37c669_PARALLEL_FDC_IRQ_INDEX
,
1327 ** Enable the parallel port base address mapping
1329 base_addr
.as_uchar
= 0;
1330 base_addr
.by_field
.addr9_2
= local_config
[ func
].port1
>> 2;
1332 SMC37c669_write_config(
1333 SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX
,
1341 SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr
;
1342 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq
;
1343 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq
;
1345 ** Enable the floppy controller DMA channel mapping
1348 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX
);
1350 drq
.by_field
.fdc_drq
=
1351 SMC37c669_RAW_DEVICE_DRQ(
1352 SMC37c669_xlate_drq( local_config
[ func
].drq
)
1355 SMC37c669_write_config(
1356 SMC37c669_PARALLEL_FDC_DRQ_INDEX
,
1360 ** Enable the floppy controller IRQ mapping
1363 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX
);
1365 irq
.by_field
.fdc_irq
=
1366 SMC37c669_RAW_DEVICE_IRQ(
1367 SMC37c669_xlate_irq( local_config
[ func
].irq
)
1370 SMC37c669_write_config(
1371 SMC37c669_PARALLEL_FDC_IRQ_INDEX
,
1375 ** Enable the floppy controller base address mapping
1377 base_addr
.as_uchar
= 0;
1378 base_addr
.by_field
.addr9_4
= local_config
[ func
].port1
>> 4;
1380 SMC37c669_write_config(
1381 SMC37c669_FDC_BASE_ADDRESS_INDEX
,
1389 SMC37c669_IDE_ADDRESS_REGISTER ide_addr
;
1391 ** Enable the IDE alternate status base address mapping
1393 ide_addr
.as_uchar
= 0;
1394 ide_addr
.by_field
.addr9_4
= local_config
[ func
].port2
>> 4;
1396 SMC37c669_write_config(
1397 SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX
,
1401 ** Enable the IDE controller base address mapping
1403 ide_addr
.as_uchar
= 0;
1404 ide_addr
.by_field
.addr9_4
= local_config
[ func
].port1
>> 4;
1406 SMC37c669_write_config(
1407 SMC37c669_IDE_BASE_ADDRESS_INDEX
,
1415 ** Exit configuration mode and return
1417 SMC37c669_config_mode( FALSE
);
1425 ** FUNCTIONAL DESCRIPTION:
1427 ** This function disables a device function within the
1428 ** SMC37c669 Super I/O controller.
1430 ** FORMAL PARAMETERS:
1433 ** Which function to disable
1437 ** Return TRUE if the device function was disabled, otherwise, FALSE
1441 ** {@description or none@}
1445 ** Disabling a function in the SMC37c669 device involves
1446 ** disabling all the function's mappings (port, irq, drq ...).
1447 ** A shadow copy of the device configuration is maintained
1448 ** in local storage so we won't worry aboving saving the
1449 ** current configuration information.
1453 unsigned int __init
SMC37c669_disable_device ( unsigned int func
)
1455 unsigned int ret_val
= FALSE
;
1458 ** Put the device into configuration mode
1460 SMC37c669_config_mode( TRUE
);
1464 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr
;
1465 SMC37c669_SERIAL_IRQ_REGISTER irq
;
1467 ** Disable the serial 1 IRQ mapping
1470 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX
);
1472 irq
.by_field
.uart1_irq
= 0;
1474 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX
, irq
.as_uchar
);
1476 ** Disable the serial 1 port base address mapping
1478 base_addr
.as_uchar
= 0;
1479 SMC37c669_write_config(
1480 SMC37c669_SERIAL0_BASE_ADDRESS_INDEX
,
1488 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr
;
1489 SMC37c669_SERIAL_IRQ_REGISTER irq
;
1491 ** Disable the serial 2 IRQ mapping
1494 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX
);
1496 irq
.by_field
.uart2_irq
= 0;
1498 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX
, irq
.as_uchar
);
1500 ** Disable the serial 2 port base address mapping
1502 base_addr
.as_uchar
= 0;
1504 SMC37c669_write_config(
1505 SMC37c669_SERIAL1_BASE_ADDRESS_INDEX
,
1513 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr
;
1514 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq
;
1515 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq
;
1517 ** Disable the parallel port DMA channel mapping
1520 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX
);
1522 drq
.by_field
.ppt_drq
= 0;
1524 SMC37c669_write_config(
1525 SMC37c669_PARALLEL_FDC_DRQ_INDEX
,
1529 ** Disable the parallel port IRQ mapping
1532 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX
);
1534 irq
.by_field
.ppt_irq
= 0;
1536 SMC37c669_write_config(
1537 SMC37c669_PARALLEL_FDC_IRQ_INDEX
,
1541 ** Disable the parallel port base address mapping
1543 base_addr
.as_uchar
= 0;
1545 SMC37c669_write_config(
1546 SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX
,
1554 SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr
;
1555 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq
;
1556 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq
;
1558 ** Disable the floppy controller DMA channel mapping
1561 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX
);
1563 drq
.by_field
.fdc_drq
= 0;
1565 SMC37c669_write_config(
1566 SMC37c669_PARALLEL_FDC_DRQ_INDEX
,
1570 ** Disable the floppy controller IRQ mapping
1573 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX
);
1575 irq
.by_field
.fdc_irq
= 0;
1577 SMC37c669_write_config(
1578 SMC37c669_PARALLEL_FDC_IRQ_INDEX
,
1582 ** Disable the floppy controller base address mapping
1584 base_addr
.as_uchar
= 0;
1586 SMC37c669_write_config(
1587 SMC37c669_FDC_BASE_ADDRESS_INDEX
,
1595 SMC37c669_IDE_ADDRESS_REGISTER ide_addr
;
1597 ** Disable the IDE alternate status base address mapping
1599 ide_addr
.as_uchar
= 0;
1601 SMC37c669_write_config(
1602 SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX
,
1606 ** Disable the IDE controller base address mapping
1608 ide_addr
.as_uchar
= 0;
1610 SMC37c669_write_config(
1611 SMC37c669_IDE_BASE_ADDRESS_INDEX
,
1619 ** Exit configuration mode and return
1621 SMC37c669_config_mode( FALSE
);
1629 ** FUNCTIONAL DESCRIPTION:
1631 ** This function configures a device function within the
1632 ** SMC37c669 Super I/O controller.
1634 ** FORMAL PARAMETERS:
1637 ** Which device function
1640 ** I/O port for the function to use
1643 ** IRQ for the device function to use
1646 ** DMA channel for the device function to use
1650 ** Returns TRUE if the device function was configured,
1651 ** otherwise, FALSE.
1655 ** {@description or none@}
1659 ** If this function returns TRUE, the local shadow copy of
1660 ** the configuration is also updated. If the device function
1661 ** is currently disabled, only the local shadow copy is
1662 ** updated and the actual device function will be updated
1663 ** if/when it is enabled.
1667 unsigned int __init
SMC37c669_configure_device (
1673 struct DEVICE_CONFIG
*cp
;
1676 ** Check for a valid configuration
1678 if ( ( cp
= SMC37c669_get_config ( func
) ) != NULL
) {
1680 ** Configuration is valid, update the local shadow copy
1682 if ( ( drq
& ~0xFF ) == 0 ) {
1685 if ( ( irq
& ~0xFF ) == 0 ) {
1688 if ( ( port
& ~0xFFFF ) == 0 ) {
1692 ** If the device function is enabled, update the actual
1693 ** device configuration.
1695 if ( SMC37c669_is_device_enabled( func
) ) {
1696 SMC37c669_enable_device( func
);
1706 ** FUNCTIONAL DESCRIPTION:
1708 ** This function determines whether a device function
1709 ** within the SMC37c669 controller is enabled.
1711 ** FORMAL PARAMETERS:
1714 ** Which device function
1718 ** Returns TRUE if the device function is enabled, otherwise, FALSE
1722 ** {@description or none@}
1726 ** To check whether a device is enabled we will only look at
1727 ** the port base address mapping. According to the SMC37c669
1728 ** specification, all of the port base address mappings are
1729 ** disabled if the addr<9:8> (bits <7:6> of the register) are
1734 static unsigned int __init
SMC37c669_is_device_enabled ( unsigned int func
)
1736 unsigned char base_addr
= 0;
1737 unsigned int dev_ok
= FALSE
;
1738 unsigned int ret_val
= FALSE
;
1740 ** Enter configuration mode
1742 SMC37c669_config_mode( TRUE
);
1747 SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX
);
1752 SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX
);
1757 SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX
);
1762 SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX
);
1767 SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX
);
1772 ** If we have a valid device, check base_addr<7:6> to see if the
1773 ** device is enabled (mapped).
1775 if ( ( dev_ok
) && ( ( base_addr
& 0xC0 ) != 0 ) ) {
1777 ** The mapping is not disabled, so assume that the function is
1783 ** Exit configuration mode
1785 SMC37c669_config_mode( FALSE
);
1794 ** FUNCTIONAL DESCRIPTION:
1796 ** This function retrieves the configuration information of a
1797 ** device function within the SMC37c699 Super I/O controller.
1799 ** FORMAL PARAMETERS:
1802 ** Which device function
1805 ** I/O port returned
1811 ** DMA channel returned
1815 ** Returns TRUE if the device configuration was successfully
1816 ** retrieved, otherwise, FALSE.
1820 ** The data pointed to by the port, irq, and drq parameters
1821 ** my be modified even if the configuration is not successfully
1826 ** The device configuration is fetched from the local shadow
1827 ** copy. Any unused parameters will be set to -1. Any
1828 ** parameter which is not desired can specify the NULL
1833 static unsigned int __init
SMC37c669_get_device_config (
1839 struct DEVICE_CONFIG
*cp
;
1840 unsigned int ret_val
= FALSE
;
1842 ** Check for a valid device configuration
1844 if ( ( cp
= SMC37c669_get_config( func
) ) != NULL
) {
1845 if ( drq
!= NULL
) {
1849 if ( irq
!= NULL
) {
1853 if ( port
!= NULL
) {
1865 ** FUNCTIONAL DESCRIPTION:
1867 ** This function displays the current state of the SMC37c699
1868 ** Super I/O controller's device functions.
1870 ** FORMAL PARAMETERS:
1884 void __init
SMC37c669_display_device_info ( void )
1886 if ( SMC37c669_is_device_enabled( SERIAL_0
) ) {
1887 printk( " Serial 0: Enabled [ Port 0x%x, IRQ %d ]\n",
1888 local_config
[ SERIAL_0
].port1
,
1889 local_config
[ SERIAL_0
].irq
1893 printk( " Serial 0: Disabled\n" );
1896 if ( SMC37c669_is_device_enabled( SERIAL_1
) ) {
1897 printk( " Serial 1: Enabled [ Port 0x%x, IRQ %d ]\n",
1898 local_config
[ SERIAL_1
].port1
,
1899 local_config
[ SERIAL_1
].irq
1903 printk( " Serial 1: Disabled\n" );
1906 if ( SMC37c669_is_device_enabled( PARALLEL_0
) ) {
1907 printk( " Parallel: Enabled [ Port 0x%x, IRQ %d/%d ]\n",
1908 local_config
[ PARALLEL_0
].port1
,
1909 local_config
[ PARALLEL_0
].irq
,
1910 local_config
[ PARALLEL_0
].drq
1914 printk( " Parallel: Disabled\n" );
1917 if ( SMC37c669_is_device_enabled( FLOPPY_0
) ) {
1918 printk( " Floppy Ctrl: Enabled [ Port 0x%x, IRQ %d/%d ]\n",
1919 local_config
[ FLOPPY_0
].port1
,
1920 local_config
[ FLOPPY_0
].irq
,
1921 local_config
[ FLOPPY_0
].drq
1925 printk( " Floppy Ctrl: Disabled\n" );
1928 if ( SMC37c669_is_device_enabled( IDE_0
) ) {
1929 printk( " IDE 0: Enabled [ Port 0x%x, IRQ %d ]\n",
1930 local_config
[ IDE_0
].port1
,
1931 local_config
[ IDE_0
].irq
1935 printk( " IDE 0: Disabled\n" );
1942 ** FUNCTIONAL DESCRIPTION:
1944 ** This function puts the SMC37c669 Super I/O controller into,
1945 ** and takes it out of, configuration mode.
1947 ** FORMAL PARAMETERS:
1950 ** TRUE to enter configuration mode, FALSE to exit.
1958 ** The SMC37c669 controller may be left in configuration mode.
1962 static void __init
SMC37c669_config_mode(
1963 unsigned int enable
)
1967 ** To enter configuration mode, two writes in succession to the index
1968 ** port are required. If a write to another address or port occurs
1969 ** between these two writes, the chip does not enter configuration
1970 ** mode. Therefore, a spinlock is placed around the two writes to
1971 ** guarantee that they complete uninterrupted.
1973 spin_lock(&smc_lock
);
1974 wb( &SMC37c669
->index_port
, SMC37c669_CONFIG_ON_KEY
);
1975 wb( &SMC37c669
->index_port
, SMC37c669_CONFIG_ON_KEY
);
1976 spin_unlock(&smc_lock
);
1979 wb( &SMC37c669
->index_port
, SMC37c669_CONFIG_OFF_KEY
);
1985 ** FUNCTIONAL DESCRIPTION:
1987 ** This function reads an SMC37c669 Super I/O controller
1988 ** configuration register. This function assumes that the
1989 ** device is already in configuration mode.
1991 ** FORMAL PARAMETERS:
1994 ** Index value of configuration register to read
1998 ** Data read from configuration register
2006 static unsigned char __init
SMC37c669_read_config(
2007 unsigned char index
)
2009 wb(&SMC37c669
->index_port
, index
);
2010 return rb(&SMC37c669
->data_port
);
2015 ** FUNCTIONAL DESCRIPTION:
2017 ** This function writes an SMC37c669 Super I/O controller
2018 ** configuration register. This function assumes that the
2019 ** device is already in configuration mode.
2021 ** FORMAL PARAMETERS:
2024 ** Index of configuration register to write
2027 ** Data to be written
2039 static void __init
SMC37c669_write_config(
2040 unsigned char index
,
2041 unsigned char data
)
2043 wb( &SMC37c669
->index_port
, index
);
2044 wb( &SMC37c669
->data_port
, data
);
2050 ** FUNCTIONAL DESCRIPTION:
2052 ** This function initializes the local device
2053 ** configuration storage. This function assumes
2054 ** that the device is already in configuration
2057 ** FORMAL PARAMETERS:
2067 ** Local storage for device configuration information
2072 static void __init
SMC37c669_init_local_config ( void )
2074 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER uart_base
;
2075 SMC37c669_SERIAL_IRQ_REGISTER uart_irqs
;
2076 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER ppt_base
;
2077 SMC37c669_PARALLEL_FDC_IRQ_REGISTER ppt_fdc_irqs
;
2078 SMC37c669_PARALLEL_FDC_DRQ_REGISTER ppt_fdc_drqs
;
2079 SMC37c669_FDC_BASE_ADDRESS_REGISTER fdc_base
;
2080 SMC37c669_IDE_ADDRESS_REGISTER ide_base
;
2081 SMC37c669_IDE_ADDRESS_REGISTER ide_alt
;
2084 ** Get serial port 1 base address
2086 uart_base
.as_uchar
=
2087 SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX
);
2089 ** Get IRQs for serial ports 1 & 2
2091 uart_irqs
.as_uchar
=
2092 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX
);
2094 ** Store local configuration information for serial port 1
2096 local_config
[SERIAL_0
].port1
= uart_base
.by_field
.addr9_3
<< 3;
2097 local_config
[SERIAL_0
].irq
=
2098 SMC37c669_xlate_irq(
2099 SMC37c669_DEVICE_IRQ( uart_irqs
.by_field
.uart1_irq
)
2102 ** Get serial port 2 base address
2104 uart_base
.as_uchar
=
2105 SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX
);
2107 ** Store local configuration information for serial port 2
2109 local_config
[SERIAL_1
].port1
= uart_base
.by_field
.addr9_3
<< 3;
2110 local_config
[SERIAL_1
].irq
=
2111 SMC37c669_xlate_irq(
2112 SMC37c669_DEVICE_IRQ( uart_irqs
.by_field
.uart2_irq
)
2115 ** Get parallel port base address
2118 SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX
);
2120 ** Get IRQs for parallel port and floppy controller
2122 ppt_fdc_irqs
.as_uchar
=
2123 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX
);
2125 ** Get DRQs for parallel port and floppy controller
2127 ppt_fdc_drqs
.as_uchar
=
2128 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX
);
2130 ** Store local configuration information for parallel port
2132 local_config
[PARALLEL_0
].port1
= ppt_base
.by_field
.addr9_2
<< 2;
2133 local_config
[PARALLEL_0
].irq
=
2134 SMC37c669_xlate_irq(
2135 SMC37c669_DEVICE_IRQ( ppt_fdc_irqs
.by_field
.ppt_irq
)
2137 local_config
[PARALLEL_0
].drq
=
2138 SMC37c669_xlate_drq(
2139 SMC37c669_DEVICE_DRQ( ppt_fdc_drqs
.by_field
.ppt_drq
)
2142 ** Get floppy controller base address
2145 SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX
);
2147 ** Store local configuration information for floppy controller
2149 local_config
[FLOPPY_0
].port1
= fdc_base
.by_field
.addr9_4
<< 4;
2150 local_config
[FLOPPY_0
].irq
=
2151 SMC37c669_xlate_irq(
2152 SMC37c669_DEVICE_IRQ( ppt_fdc_irqs
.by_field
.fdc_irq
)
2154 local_config
[FLOPPY_0
].drq
=
2155 SMC37c669_xlate_drq(
2156 SMC37c669_DEVICE_DRQ( ppt_fdc_drqs
.by_field
.fdc_drq
)
2159 ** Get IDE controller base address
2162 SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX
);
2164 ** Get IDE alternate status base address
2167 SMC37c669_read_config( SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX
);
2169 ** Store local configuration information for IDE controller
2171 local_config
[IDE_0
].port1
= ide_base
.by_field
.addr9_4
<< 4;
2172 local_config
[IDE_0
].port2
= ide_alt
.by_field
.addr9_4
<< 4;
2173 local_config
[IDE_0
].irq
= 14;
2179 ** FUNCTIONAL DESCRIPTION:
2181 ** This function returns a pointer to the local shadow
2182 ** configuration of the requested device function.
2184 ** FORMAL PARAMETERS:
2187 ** Which device function
2191 ** Returns a pointer to the DEVICE_CONFIG structure for the
2192 ** requested function, otherwise, NULL.
2196 ** {@description or none@}
2200 static struct DEVICE_CONFIG
* __init
SMC37c669_get_config( unsigned int func
)
2202 struct DEVICE_CONFIG
*cp
= NULL
;
2206 cp
= &local_config
[ SERIAL_0
];
2209 cp
= &local_config
[ SERIAL_1
];
2212 cp
= &local_config
[ PARALLEL_0
];
2215 cp
= &local_config
[ FLOPPY_0
];
2218 cp
= &local_config
[ IDE_0
];
2226 ** FUNCTIONAL DESCRIPTION:
2228 ** This function translates IRQs back and forth between ISA
2229 ** IRQs and SMC37c669 device IRQs.
2231 ** FORMAL PARAMETERS:
2234 ** The IRQ to translate
2238 ** Returns the translated IRQ, otherwise, returns -1.
2242 ** {@description or none@}
2246 static int __init
SMC37c669_xlate_irq ( int irq
)
2248 int i
, translated_irq
= -1;
2250 if ( SMC37c669_IS_DEVICE_IRQ( irq
) ) {
2252 ** We are translating a device IRQ to an ISA IRQ
2254 for ( i
= 0; ( SMC37c669_irq_table
[i
].device_irq
!= -1 ) || ( SMC37c669_irq_table
[i
].isa_irq
!= -1 ); i
++ ) {
2255 if ( irq
== SMC37c669_irq_table
[i
].device_irq
) {
2256 translated_irq
= SMC37c669_irq_table
[i
].isa_irq
;
2263 ** We are translating an ISA IRQ to a device IRQ
2265 for ( i
= 0; ( SMC37c669_irq_table
[i
].isa_irq
!= -1 ) || ( SMC37c669_irq_table
[i
].device_irq
!= -1 ); i
++ ) {
2266 if ( irq
== SMC37c669_irq_table
[i
].isa_irq
) {
2267 translated_irq
= SMC37c669_irq_table
[i
].device_irq
;
2272 return translated_irq
;
2278 ** FUNCTIONAL DESCRIPTION:
2280 ** This function translates DMA channels back and forth between
2281 ** ISA DMA channels and SMC37c669 device DMA channels.
2283 ** FORMAL PARAMETERS:
2286 ** The DMA channel to translate
2290 ** Returns the translated DMA channel, otherwise, returns -1
2294 ** {@description or none@}
2298 static int __init
SMC37c669_xlate_drq ( int drq
)
2300 int i
, translated_drq
= -1;
2302 if ( SMC37c669_IS_DEVICE_DRQ( drq
) ) {
2304 ** We are translating a device DMA channel to an ISA DMA channel
2306 for ( i
= 0; ( SMC37c669_drq_table
[i
].device_drq
!= -1 ) || ( SMC37c669_drq_table
[i
].isa_drq
!= -1 ); i
++ ) {
2307 if ( drq
== SMC37c669_drq_table
[i
].device_drq
) {
2308 translated_drq
= SMC37c669_drq_table
[i
].isa_drq
;
2315 ** We are translating an ISA DMA channel to a device DMA channel
2317 for ( i
= 0; ( SMC37c669_drq_table
[i
].isa_drq
!= -1 ) || ( SMC37c669_drq_table
[i
].device_drq
!= -1 ); i
++ ) {
2318 if ( drq
== SMC37c669_drq_table
[i
].isa_drq
) {
2319 translated_drq
= SMC37c669_drq_table
[i
].device_drq
;
2324 return translated_drq
;
2328 int __init
smcc669_init ( void )
2332 allocinode( smc_ddb
.name
, 1, &ip
);
2334 ip
->attr
= ATTR$M_WRITE
| ATTR$M_READ
;
2342 int __init
smcc669_open( struct FILE *fp
, char *info
, char *next
, char *mode
)
2346 ** Allow multiple readers but only one writer. ip->misc keeps track
2347 ** of the number of writers
2351 if ( fp
->mode
& ATTR$M_WRITE
) {
2354 return msg_failure
; /* too many writers */
2359 ** Treat the information field as a byte offset
2361 *fp
->offset
= xtoi( info
);
2367 int __init
smcc669_close( struct FILE *fp
)
2372 if ( fp
->mode
& ATTR$M_WRITE
) {
2380 int __init
smcc669_read( struct FILE *fp
, int size
, int number
, unsigned char *buf
)
2388 ** Always access a byte at a time
2391 length
= size
* number
;
2394 SMC37c669_config_mode( TRUE
);
2395 for ( i
= 0; i
< length
; i
++ ) {
2396 if ( !inrange( *fp
->offset
, 0, ip
->len
[0] ) )
2398 *buf
++ = SMC37c669_read_config( *fp
->offset
);
2402 SMC37c669_config_mode( FALSE
);
2406 int __init
smcc669_write( struct FILE *fp
, int size
, int number
, unsigned char *buf
)
2413 ** Always access a byte at a time
2416 length
= size
* number
;
2419 SMC37c669_config_mode( TRUE
);
2420 for ( i
= 0; i
< length
; i
++ ) {
2421 if ( !inrange( *fp
->offset
, 0, ip
->len
[0] ) )
2423 SMC37c669_write_config( *fp
->offset
, *buf
);
2428 SMC37c669_config_mode( FALSE
);
2434 SMC37c669_dump_registers(void)
2437 for (i
= 0; i
<= 0x29; i
++)
2438 printk("-- CR%02x : %02x\n", i
, SMC37c669_read_config(i
));
2441 * ============================================================================
2442 * = SMC_init - SMC37c669 Super I/O controller initialization =
2443 * ============================================================================
2447 * This routine configures and enables device functions on the
2448 * SMC37c669 Super I/O controller.
2467 void __init
SMC669_Init ( int index
)
2469 SMC37c669_CONFIG_REGS
*SMC_base
;
2470 unsigned long flags
;
2472 local_irq_save(flags
);
2473 if ( ( SMC_base
= SMC37c669_detect( index
) ) != NULL
) {
2475 SMC37c669_config_mode( TRUE
);
2476 SMC37c669_dump_registers( );
2477 SMC37c669_config_mode( FALSE
);
2478 SMC37c669_display_device_info( );
2480 SMC37c669_disable_device( SERIAL_0
);
2481 SMC37c669_configure_device(
2487 SMC37c669_enable_device( SERIAL_0
);
2489 SMC37c669_disable_device( SERIAL_1
);
2490 SMC37c669_configure_device(
2496 SMC37c669_enable_device( SERIAL_1
);
2498 SMC37c669_disable_device( PARALLEL_0
);
2499 SMC37c669_configure_device(
2505 SMC37c669_enable_device( PARALLEL_0
);
2507 SMC37c669_disable_device( FLOPPY_0
);
2508 SMC37c669_configure_device(
2514 SMC37c669_enable_device( FLOPPY_0
);
2516 /* Wake up sometimes forgotten floppy, especially on DP264. */
2519 SMC37c669_disable_device( IDE_0
);
2522 SMC37c669_config_mode( TRUE
);
2523 SMC37c669_dump_registers( );
2524 SMC37c669_config_mode( FALSE
);
2525 SMC37c669_display_device_info( );
2527 local_irq_restore(flags
);
2528 printk( "SMC37c669 Super I/O Controller found @ 0x%p\n",
2532 local_irq_restore(flags
);
2534 printk( "No SMC37c669 Super I/O Controller found\n" );