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

source code of linux/arch/alpha/kernel/smc37c669.c