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