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

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