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