File: /usr/src/linux/arch/alpha/kernel/smc37c669.c
1 /*
2 * SMC 37C669 initialization code
3 */
4 #include <linux/kernel.h>
5
6 #include <linux/slab.h>
7 #include <linux/mm.h>
8 #include <linux/init.h>
9 #include <linux/delay.h>
10
11 #include <asm/hwrpb.h>
12 #include <asm/io.h>
13 #include <asm/segment.h>
14
15 #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 */
211 typedef 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 */
234 typedef 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 */
248 typedef 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 */
263 typedef 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 */
289 typedef 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 */
345 typedef 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 */
367 typedef 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 */
382 typedef 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 */
403 typedef 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 */
418 typedef 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 */
436 typedef 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 */
448 typedef 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 */
459 typedef 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 */
480 typedef 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 */
497 typedef 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 */
509 typedef 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 */
519 typedef 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 */
536 typedef 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 */
551 typedef 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 */
574 typedef 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 */
598 typedef 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 */
616 typedef 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 */
632 typedef 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 */
648 typedef 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 */
666 typedef 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 */
681 typedef 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 */
697 typedef 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 */
719 typedef 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 */
748 typedef 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 */
782 typedef 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 */
811 typedef 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 */
834 typedef SMC37c669_CR0D SMC37c669_DEVICE_ID_REGISTER;
835 typedef SMC37c669_CR0E SMC37c669_DEVICE_REVISION_REGISTER;
836 typedef SMC37c669_CR20 SMC37c669_FDC_BASE_ADDRESS_REGISTER;
837 typedef SMC37c669_CR21 SMC37c669_IDE_ADDRESS_REGISTER;
838 typedef SMC37c669_CR23 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER;
839 typedef SMC37c669_CR24 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER;
840 typedef SMC37c669_CR26 SMC37c669_PARALLEL_FDC_DRQ_REGISTER;
841 typedef SMC37c669_CR27 SMC37c669_PARALLEL_FDC_IRQ_REGISTER;
842 typedef SMC37c669_CR28 SMC37c669_SERIAL_IRQ_REGISTER;
843
844 /*
845 ** ISA/Device IRQ Translation Table Entry Definition
846 */
847 typedef 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 */
855 typedef 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
864 SMC37c669_CONFIG_REGS *SMC37c669_detect(
865 int
866 );
867
868 unsigned int SMC37c669_enable_device(
869 unsigned int func
870 );
871
872 unsigned int SMC37c669_disable_device(
873 unsigned int func
874 );
875
876 unsigned int SMC37c669_configure_device(
877 unsigned int func,
878 int port,
879 int irq,
880 int drq
881 );
882
883 void 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 */
969 static struct DEVICE_CONFIG {
970 unsigned int port1;
971 unsigned int port2;
972 unsigned int irq;
973 unsigned int drq;
974 } local_config [NUM_FUNCS];
975
976 /*
977 ** List of all possible addresses for the Super I/O chip
978 */
979 static 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 */
989 static 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 */
998 static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_table __initdata = 0;
999
1000 /*
1001 ** The following definition is for the default IRQ
1002 ** translation table.
1003 */
1004 static 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 */
1021 static 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
1034 static 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 */
1047 static SMC37c669_DRQ_TRANSLATION_ENTRY *SMC37c669_drq_table __initdata = 0;
1048
1049 /*
1050 ** The following definition is the default DRQ
1051 ** translation table.
1052 */
1053 static 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
1066 static unsigned int SMC37c669_is_device_enabled(
1067 unsigned int func
1068 );
1069
1070 #if 0
1071 static unsigned int SMC37c669_get_device_config(
1072 unsigned int func,
1073 int *port,
1074 int *irq,
1075 int *drq
1076 );
1077 #endif
1078
1079 static void SMC37c669_config_mode(
1080 unsigned int enable
1081 );
1082
1083 static unsigned char SMC37c669_read_config(
1084 unsigned char index
1085 );
1086
1087 static void SMC37c669_write_config(
1088 unsigned char index,
1089 unsigned char data
1090 );
1091
1092 static void SMC37c669_init_local_config( void );
1093
1094 static struct DEVICE_CONFIG *SMC37c669_get_config(
1095 unsigned int func
1096 );
1097
1098 static int SMC37c669_xlate_irq(
1099 unsigned int irq
1100 );
1101
1102 static int SMC37c669_xlate_drq(
1103 unsigned int drq
1104 );
1105
1106 #if 0
1107 /*
1108 ** External Data Declarations
1109 */
1110
1111 extern struct LOCK spl_atomic;
1112
1113 /*
1114 ** External Function Prototype Declarations
1115 */
1116
1117 /* From kernel_alpha.mar */
1118 extern spinlock(
1119 struct LOCK *spl
1120 );
1121
1122 extern spinunlock(
1123 struct LOCK *spl
1124 );
1125
1126 /* From filesys.c */
1127 int allocinode(
1128 char *name,
1129 int can_create,
1130 struct INODE **ipp
1131 );
1132
1133 extern int null_procedure( void );
1134
1135 int smcc669_init( void );
1136 int smcc669_open( struct FILE *fp, char *info, char *next, char *mode );
1137 int smcc669_read( struct FILE *fp, int size, int number, unsigned char *buf );
1138 int smcc669_write( struct FILE *fp, int size, int number, unsigned char *buf );
1139 int smcc669_close( struct FILE *fp );
1140
1141 struct DDB smc_ddb = {
1142 "smc", /* how this routine wants to be called */
1143 smcc669_read, /* read routine */
1144 smcc669_write, /* write routine */
1145 smcc669_open, /* open routine */
1146 smcc669_close, /* close routine */
1147 null_procedure, /* name expansion routine */
1148 null_procedure, /* delete routine */
1149 null_procedure, /* create routine */
1150 null_procedure, /* setmode */
1151 null_procedure, /* validation routine */
1152 0, /* class specific use */
1153 1, /* allows information */
1154 0, /* must be stacked */
1155 0, /* is a flash update driver */
1156 0, /* is a block device */
1157 0, /* not seekable */
1158 0, /* is an Ethernet device */
1159 0, /* is a filesystem driver */
1160 };
1161 #endif
1162
1163 #define spinlock(x)
1164 #define spinunlock(x)
1165
1166
1167 /*
1168 **++
1169 ** FUNCTIONAL DESCRIPTION:
1170 **
1171 ** This function detects the presence of an SMC37c669 Super I/O
1172 ** controller.
1173 **
1174 ** FORMAL PARAMETERS:
1175 **
1176 ** None
1177 **
1178 ** RETURN VALUE:
1179 **
1180 ** Returns a pointer to the device if found, otherwise,
1181 ** the NULL pointer is returned.
1182 **
1183 ** SIDE EFFECTS:
1184 **
1185 ** None
1186 **
1187 **--
1188 */
1189 SMC37c669_CONFIG_REGS * __init SMC37c669_detect( int index )
1190 {
1191 int i;
1192 SMC37c669_DEVICE_ID_REGISTER id;
1193
1194 for ( i = 0; SMC37c669_Addresses[i] != 0; i++ ) {
1195 /*
1196 ** Initialize the device pointer even though we don't yet know if
1197 ** the controller is at this address. The support functions access
1198 ** the controller through this device pointer so we need to set it
1199 ** even when we are looking ...
1200 */
1201 SMC37c669 = ( SMC37c669_CONFIG_REGS * )SMC37c669_Addresses[i];
1202 /*
1203 ** Enter configuration mode
1204 */
1205 SMC37c669_config_mode( TRUE );
1206 /*
1207 ** Read the device id
1208 */
1209 id.as_uchar = SMC37c669_read_config( SMC37c669_DEVICE_ID_INDEX );
1210 /*
1211 ** Exit configuration mode
1212 */
1213 SMC37c669_config_mode( FALSE );
1214 /*
1215 ** Does the device id match? If so, assume we have found an
1216 ** SMC37c669 controller at this address.
1217 */
1218 if ( id.by_field.device_id == SMC37c669_DEVICE_ID ) {
1219 /*
1220 ** Initialize the IRQ and DRQ translation tables.
1221 */
1222 SMC37c669_irq_table = SMC37c669_irq_tables[ index ];
1223 SMC37c669_drq_table = SMC37c669_default_drq_table;
1224 /*
1225 ** erfix
1226 **
1227 ** If the platform can't use the IRQ and DRQ defaults set up in this
1228 ** file, it should call a platform-specific external routine at this
1229 ** point to reset the IRQ and DRQ translation table pointers to point
1230 ** at the appropriate tables for the platform. If the defaults are
1231 ** acceptable, then the external routine should do nothing.
1232 */
1233
1234 /*
1235 ** Put the chip back into configuration mode
1236 */
1237 SMC37c669_config_mode( TRUE );
1238 /*
1239 ** Initialize local storage for configuration information
1240 */
1241 SMC37c669_init_local_config( );
1242 /*
1243 ** Exit configuration mode
1244 */
1245 SMC37c669_config_mode( FALSE );
1246 /*
1247 ** SMC37c669 controller found, break out of search loop
1248 */
1249 break;
1250 }
1251 else {
1252 /*
1253 ** Otherwise, we did not find an SMC37c669 controller at this
1254 ** address so set the device pointer to NULL.
1255 */
1256 SMC37c669 = NULL;
1257 }
1258 }
1259 return SMC37c669;
1260 }
1261
1262
1263 /*
1264 **++
1265 ** FUNCTIONAL DESCRIPTION:
1266 **
1267 ** This function enables an SMC37c669 device function.
1268 **
1269 ** FORMAL PARAMETERS:
1270 **
1271 ** func:
1272 ** Which device function to enable
1273 **
1274 ** RETURN VALUE:
1275 **
1276 ** Returns TRUE is the device function was enabled, otherwise, FALSE
1277 **
1278 ** SIDE EFFECTS:
1279 **
1280 ** {@description or none@}
1281 **
1282 ** DESIGN:
1283 **
1284 ** Enabling a device function in the SMC37c669 controller involves
1285 ** setting all of its mappings (port, irq, drq ...). A local
1286 ** "shadow" copy of the device configuration is kept so we can
1287 ** just set each mapping to what the local copy says.
1288 **
1289 ** This function ALWAYS updates the local shadow configuration of
1290 ** the device function being enabled, even if the device is always
1291 ** enabled. To avoid replication of code, functions such as
1292 ** configure_device set up the local copy and then call this
1293 ** function to the update the real device.
1294 **
1295 **--
1296 */
1297 unsigned int __init SMC37c669_enable_device ( unsigned int func )
1298 {
1299 unsigned int ret_val = FALSE;
1300 /*
1301 ** Put the device into configuration mode
1302 */
1303 SMC37c669_config_mode( TRUE );
1304 switch ( func ) {
1305 case SERIAL_0:
1306 {
1307 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
1308 SMC37c669_SERIAL_IRQ_REGISTER irq;
1309 /*
1310 ** Enable the serial 1 IRQ mapping
1311 */
1312 irq.as_uchar =
1313 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
1314
1315 irq.by_field.uart1_irq =
1316 SMC37c669_RAW_DEVICE_IRQ(
1317 SMC37c669_xlate_irq( local_config[ func ].irq )
1318 );
1319
1320 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
1321 /*
1322 ** Enable the serial 1 port base address mapping
1323 */
1324 base_addr.as_uchar = 0;
1325 base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3;
1326
1327 SMC37c669_write_config(
1328 SMC37c669_SERIAL0_BASE_ADDRESS_INDEX,
1329 base_addr.as_uchar
1330 );
1331 ret_val = TRUE;
1332 break;
1333 }
1334 case SERIAL_1:
1335 {
1336 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
1337 SMC37c669_SERIAL_IRQ_REGISTER irq;
1338 /*
1339 ** Enable the serial 2 IRQ mapping
1340 */
1341 irq.as_uchar =
1342 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
1343
1344 irq.by_field.uart2_irq =
1345 SMC37c669_RAW_DEVICE_IRQ(
1346 SMC37c669_xlate_irq( local_config[ func ].irq )
1347 );
1348
1349 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
1350 /*
1351 ** Enable the serial 2 port base address mapping
1352 */
1353 base_addr.as_uchar = 0;
1354 base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3;
1355
1356 SMC37c669_write_config(
1357 SMC37c669_SERIAL1_BASE_ADDRESS_INDEX,
1358 base_addr.as_uchar
1359 );
1360 ret_val = TRUE;
1361 break;
1362 }
1363 case PARALLEL_0:
1364 {
1365 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr;
1366 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
1367 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
1368 /*
1369 ** Enable the parallel port DMA channel mapping
1370 */
1371 drq.as_uchar =
1372 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
1373
1374 drq.by_field.ppt_drq =
1375 SMC37c669_RAW_DEVICE_DRQ(
1376 SMC37c669_xlate_drq( local_config[ func ].drq )
1377 );
1378
1379 SMC37c669_write_config(
1380 SMC37c669_PARALLEL_FDC_DRQ_INDEX,
1381 drq.as_uchar
1382 );
1383 /*
1384 ** Enable the parallel port IRQ mapping
1385 */
1386 irq.as_uchar =
1387 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
1388
1389 irq.by_field.ppt_irq =
1390 SMC37c669_RAW_DEVICE_IRQ(
1391 SMC37c669_xlate_irq( local_config[ func ].irq )
1392 );
1393
1394 SMC37c669_write_config(
1395 SMC37c669_PARALLEL_FDC_IRQ_INDEX,
1396 irq.as_uchar
1397 );
1398 /*
1399 ** Enable the parallel port base address mapping
1400 */
1401 base_addr.as_uchar = 0;
1402 base_addr.by_field.addr9_2 = local_config[ func ].port1 >> 2;
1403
1404 SMC37c669_write_config(
1405 SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX,
1406 base_addr.as_uchar
1407 );
1408 ret_val = TRUE;
1409 break;
1410 }
1411 case FLOPPY_0:
1412 {
1413 SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr;
1414 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
1415 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
1416 /*
1417 ** Enable the floppy controller DMA channel mapping
1418 */
1419 drq.as_uchar =
1420 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
1421
1422 drq.by_field.fdc_drq =
1423 SMC37c669_RAW_DEVICE_DRQ(
1424 SMC37c669_xlate_drq( local_config[ func ].drq )
1425 );
1426
1427 SMC37c669_write_config(
1428 SMC37c669_PARALLEL_FDC_DRQ_INDEX,
1429 drq.as_uchar
1430 );
1431 /*
1432 ** Enable the floppy controller IRQ mapping
1433 */
1434 irq.as_uchar =
1435 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
1436
1437 irq.by_field.fdc_irq =
1438 SMC37c669_RAW_DEVICE_IRQ(
1439 SMC37c669_xlate_irq( local_config[ func ].irq )
1440 );
1441
1442 SMC37c669_write_config(
1443 SMC37c669_PARALLEL_FDC_IRQ_INDEX,
1444 irq.as_uchar
1445 );
1446 /*
1447 ** Enable the floppy controller base address mapping
1448 */
1449 base_addr.as_uchar = 0;
1450 base_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4;
1451
1452 SMC37c669_write_config(
1453 SMC37c669_FDC_BASE_ADDRESS_INDEX,
1454 base_addr.as_uchar
1455 );
1456 ret_val = TRUE;
1457 break;
1458 }
1459 case IDE_0:
1460 {
1461 SMC37c669_IDE_ADDRESS_REGISTER ide_addr;
1462 /*
1463 ** Enable the IDE alternate status base address mapping
1464 */
1465 ide_addr.as_uchar = 0;
1466 ide_addr.by_field.addr9_4 = local_config[ func ].port2 >> 4;
1467
1468 SMC37c669_write_config(
1469 SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX,
1470 ide_addr.as_uchar
1471 );
1472 /*
1473 ** Enable the IDE controller base address mapping
1474 */
1475 ide_addr.as_uchar = 0;
1476 ide_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4;
1477
1478 SMC37c669_write_config(
1479 SMC37c669_IDE_BASE_ADDRESS_INDEX,
1480 ide_addr.as_uchar
1481 );
1482 ret_val = TRUE;
1483 break;
1484 }
1485 }
1486 /*
1487 ** Exit configuration mode and return
1488 */
1489 SMC37c669_config_mode( FALSE );
1490
1491 return ret_val;
1492 }
1493
1494
1495 /*
1496 **++
1497 ** FUNCTIONAL DESCRIPTION:
1498 **
1499 ** This function disables a device function within the
1500 ** SMC37c669 Super I/O controller.
1501 **
1502 ** FORMAL PARAMETERS:
1503 **
1504 ** func:
1505 ** Which function to disable
1506 **
1507 ** RETURN VALUE:
1508 **
1509 ** Return TRUE if the device function was disabled, otherwise, FALSE
1510 **
1511 ** SIDE EFFECTS:
1512 **
1513 ** {@description or none@}
1514 **
1515 ** DESIGN:
1516 **
1517 ** Disabling a function in the SMC37c669 device involves
1518 ** disabling all the function's mappings (port, irq, drq ...).
1519 ** A shadow copy of the device configuration is maintained
1520 ** in local storage so we won't worry aboving saving the
1521 ** current configuration information.
1522 **
1523 **--
1524 */
1525 unsigned int __init SMC37c669_disable_device ( unsigned int func )
1526 {
1527 unsigned int ret_val = FALSE;
1528
1529 /*
1530 ** Put the device into configuration mode
1531 */
1532 SMC37c669_config_mode( TRUE );
1533 switch ( func ) {
1534 case SERIAL_0:
1535 {
1536 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
1537 SMC37c669_SERIAL_IRQ_REGISTER irq;
1538 /*
1539 ** Disable the serial 1 IRQ mapping
1540 */
1541 irq.as_uchar =
1542 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
1543
1544 irq.by_field.uart1_irq = 0;
1545
1546 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
1547 /*
1548 ** Disable the serial 1 port base address mapping
1549 */
1550 base_addr.as_uchar = 0;
1551 SMC37c669_write_config(
1552 SMC37c669_SERIAL0_BASE_ADDRESS_INDEX,
1553 base_addr.as_uchar
1554 );
1555 ret_val = TRUE;
1556 break;
1557 }
1558 case SERIAL_1:
1559 {
1560 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
1561 SMC37c669_SERIAL_IRQ_REGISTER irq;
1562 /*
1563 ** Disable the serial 2 IRQ mapping
1564 */
1565 irq.as_uchar =
1566 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
1567
1568 irq.by_field.uart2_irq = 0;
1569
1570 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
1571 /*
1572 ** Disable the serial 2 port base address mapping
1573 */
1574 base_addr.as_uchar = 0;
1575
1576 SMC37c669_write_config(
1577 SMC37c669_SERIAL1_BASE_ADDRESS_INDEX,
1578 base_addr.as_uchar
1579 );
1580 ret_val = TRUE;
1581 break;
1582 }
1583 case PARALLEL_0:
1584 {
1585 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr;
1586 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
1587 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
1588 /*
1589 ** Disable the parallel port DMA channel mapping
1590 */
1591 drq.as_uchar =
1592 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
1593
1594 drq.by_field.ppt_drq = 0;
1595
1596 SMC37c669_write_config(
1597 SMC37c669_PARALLEL_FDC_DRQ_INDEX,
1598 drq.as_uchar
1599 );
1600 /*
1601 ** Disable the parallel port IRQ mapping
1602 */
1603 irq.as_uchar =
1604 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
1605
1606 irq.by_field.ppt_irq = 0;
1607
1608 SMC37c669_write_config(
1609 SMC37c669_PARALLEL_FDC_IRQ_INDEX,
1610 irq.as_uchar
1611 );
1612 /*
1613 ** Disable the parallel port base address mapping
1614 */
1615 base_addr.as_uchar = 0;
1616
1617 SMC37c669_write_config(
1618 SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX,
1619 base_addr.as_uchar
1620 );
1621 ret_val = TRUE;
1622 break;
1623 }
1624 case FLOPPY_0:
1625 {
1626 SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr;
1627 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
1628 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
1629 /*
1630 ** Disable the floppy controller DMA channel mapping
1631 */
1632 drq.as_uchar =
1633 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
1634
1635 drq.by_field.fdc_drq = 0;
1636
1637 SMC37c669_write_config(
1638 SMC37c669_PARALLEL_FDC_DRQ_INDEX,
1639 drq.as_uchar
1640 );
1641 /*
1642 ** Disable the floppy controller IRQ mapping
1643 */
1644 irq.as_uchar =
1645 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
1646
1647 irq.by_field.fdc_irq = 0;
1648
1649 SMC37c669_write_config(
1650 SMC37c669_PARALLEL_FDC_IRQ_INDEX,
1651 irq.as_uchar
1652 );
1653 /*
1654 ** Disable the floppy controller base address mapping
1655 */
1656 base_addr.as_uchar = 0;
1657
1658 SMC37c669_write_config(
1659 SMC37c669_FDC_BASE_ADDRESS_INDEX,
1660 base_addr.as_uchar
1661 );
1662 ret_val = TRUE;
1663 break;
1664 }
1665 case IDE_0:
1666 {
1667 SMC37c669_IDE_ADDRESS_REGISTER ide_addr;
1668 /*
1669 ** Disable the IDE alternate status base address mapping
1670 */
1671 ide_addr.as_uchar = 0;
1672
1673 SMC37c669_write_config(
1674 SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX,
1675 ide_addr.as_uchar
1676 );
1677 /*
1678 ** Disable the IDE controller base address mapping
1679 */
1680 ide_addr.as_uchar = 0;
1681
1682 SMC37c669_write_config(
1683 SMC37c669_IDE_BASE_ADDRESS_INDEX,
1684 ide_addr.as_uchar
1685 );
1686 ret_val = TRUE;
1687 break;
1688 }
1689 }
1690 /*
1691 ** Exit configuration mode and return
1692 */
1693 SMC37c669_config_mode( FALSE );
1694
1695 return ret_val;
1696 }
1697
1698
1699 /*
1700 **++
1701 ** FUNCTIONAL DESCRIPTION:
1702 **
1703 ** This function configures a device function within the
1704 ** SMC37c669 Super I/O controller.
1705 **
1706 ** FORMAL PARAMETERS:
1707 **
1708 ** func:
1709 ** Which device function
1710 **
1711 ** port:
1712 ** I/O port for the function to use
1713 **
1714 ** irq:
1715 ** IRQ for the device function to use
1716 **
1717 ** drq:
1718 ** DMA channel for the device function to use
1719 **
1720 ** RETURN VALUE:
1721 **
1722 ** Returns TRUE if the device function was configured,
1723 ** otherwise, FALSE.
1724 **
1725 ** SIDE EFFECTS:
1726 **
1727 ** {@description or none@}
1728 **
1729 ** DESIGN:
1730 **
1731 ** If this function returns TRUE, the local shadow copy of
1732 ** the configuration is also updated. If the device function
1733 ** is currently disabled, only the local shadow copy is
1734 ** updated and the actual device function will be updated
1735 ** if/when it is enabled.
1736 **
1737 **--
1738 */
1739 unsigned int __init SMC37c669_configure_device (
1740 unsigned int func,
1741 int port,
1742 int irq,
1743 int drq )
1744 {
1745 struct DEVICE_CONFIG *cp;
1746
1747 /*
1748 ** Check for a valid configuration
1749 */
1750 if ( ( cp = SMC37c669_get_config ( func ) ) != NULL ) {
1751 /*
1752 ** Configuration is valid, update the local shadow copy
1753 */
1754 if ( ( drq & ~0xFF ) == 0 ) {
1755 cp->drq = drq;
1756 }
1757 if ( ( irq & ~0xFF ) == 0 ) {
1758 cp->irq = irq;
1759 }
1760 if ( ( port & ~0xFFFF ) == 0 ) {
1761 cp->port1 = port;
1762 }
1763 /*
1764 ** If the device function is enabled, update the actual
1765 ** device configuration.
1766 */
1767 if ( SMC37c669_is_device_enabled( func ) ) {
1768 SMC37c669_enable_device( func );
1769 }
1770 return TRUE;
1771 }
1772 return FALSE;
1773 }
1774
1775
1776 /*
1777 **++
1778 ** FUNCTIONAL DESCRIPTION:
1779 **
1780 ** This function determines whether a device function
1781 ** within the SMC37c669 controller is enabled.
1782 **
1783 ** FORMAL PARAMETERS:
1784 **
1785 ** func:
1786 ** Which device function
1787 **
1788 ** RETURN VALUE:
1789 **
1790 ** Returns TRUE if the device function is enabled, otherwise, FALSE
1791 **
1792 ** SIDE EFFECTS:
1793 **
1794 ** {@description or none@}
1795 **
1796 ** DESIGN:
1797 **
1798 ** To check whether a device is enabled we will only look at
1799 ** the port base address mapping. According to the SMC37c669
1800 ** specification, all of the port base address mappings are
1801 ** disabled if the addr<9:8> (bits <7:6> of the register) are
1802 ** zero.
1803 **
1804 **--
1805 */
1806 static unsigned int __init SMC37c669_is_device_enabled ( unsigned int func )
1807 {
1808 unsigned char base_addr = 0;
1809 unsigned int dev_ok = FALSE;
1810 unsigned int ret_val = FALSE;
1811 /*
1812 ** Enter configuration mode
1813 */
1814 SMC37c669_config_mode( TRUE );
1815
1816 switch ( func ) {
1817 case SERIAL_0:
1818 base_addr =
1819 SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX );
1820 dev_ok = TRUE;
1821 break;
1822 case SERIAL_1:
1823 base_addr =
1824 SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX );
1825 dev_ok = TRUE;
1826 break;
1827 case PARALLEL_0:
1828 base_addr =
1829 SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX );
1830 dev_ok = TRUE;
1831 break;
1832 case FLOPPY_0:
1833 base_addr =
1834 SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX );
1835 dev_ok = TRUE;
1836 break;
1837 case IDE_0:
1838 base_addr =
1839 SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX );
1840 dev_ok = TRUE;
1841 break;
1842 }
1843 /*
1844 ** If we have a valid device, check base_addr<7:6> to see if the
1845 ** device is enabled (mapped).
1846 */
1847 if ( ( dev_ok ) && ( ( base_addr & 0xC0 ) != 0 ) ) {
1848 /*
1849 ** The mapping is not disabled, so assume that the function is
1850 ** enabled.
1851 */
1852 ret_val = TRUE;
1853 }
1854 /*
1855 ** Exit configuration mode
1856 */
1857 SMC37c669_config_mode( FALSE );
1858
1859 return ret_val;
1860 }
1861
1862
1863 #if 0
1864 /*
1865 **++
1866 ** FUNCTIONAL DESCRIPTION:
1867 **
1868 ** This function retrieves the configuration information of a
1869 ** device function within the SMC37c699 Super I/O controller.
1870 **
1871 ** FORMAL PARAMETERS:
1872 **
1873 ** func:
1874 ** Which device function
1875 **
1876 ** port:
1877 ** I/O port returned
1878 **
1879 ** irq:
1880 ** IRQ returned
1881 **
1882 ** drq:
1883 ** DMA channel returned
1884 **
1885 ** RETURN VALUE:
1886 **
1887 ** Returns TRUE if the device configuration was successfully
1888 ** retrieved, otherwise, FALSE.
1889 **
1890 ** SIDE EFFECTS:
1891 **
1892 ** The data pointed to by the port, irq, and drq parameters
1893 ** my be modified even if the configuration is not successfully
1894 ** retrieved.
1895 **
1896 ** DESIGN:
1897 **
1898 ** The device configuration is fetched from the local shadow
1899 ** copy. Any unused parameters will be set to -1. Any
1900 ** parameter which is not desired can specify the NULL
1901 ** pointer.
1902 **
1903 **--
1904 */
1905 static unsigned int __init SMC37c669_get_device_config (
1906 unsigned int func,
1907 int *port,
1908 int *irq,
1909 int *drq )
1910 {
1911 struct DEVICE_CONFIG *cp;
1912 unsigned int ret_val = FALSE;
1913 /*
1914 ** Check for a valid device configuration
1915 */
1916 if ( ( cp = SMC37c669_get_config( func ) ) != NULL ) {
1917 if ( drq != NULL ) {
1918 *drq = cp->drq;
1919 ret_val = TRUE;
1920 }
1921 if ( irq != NULL ) {
1922 *irq = cp->irq;
1923 ret_val = TRUE;
1924 }
1925 if ( port != NULL ) {
1926 *port = cp->port1;
1927 ret_val = TRUE;
1928 }
1929 }
1930 return ret_val;
1931 }
1932 #endif
1933
1934
1935 /*
1936 **++
1937 ** FUNCTIONAL DESCRIPTION:
1938 **
1939 ** This function displays the current state of the SMC37c699
1940 ** Super I/O controller's device functions.
1941 **
1942 ** FORMAL PARAMETERS:
1943 **
1944 ** None
1945 **
1946 ** RETURN VALUE:
1947 **
1948 ** None
1949 **
1950 ** SIDE EFFECTS:
1951 **
1952 ** None
1953 **
1954 **--
1955 */
1956 void __init SMC37c669_display_device_info ( void )
1957 {
1958 if ( SMC37c669_is_device_enabled( SERIAL_0 ) ) {
1959 printk( " Serial 0: Enabled [ Port 0x%x, IRQ %d ]\n",
1960 local_config[ SERIAL_0 ].port1,
1961 local_config[ SERIAL_0 ].irq
1962 );
1963 }
1964 else {
1965 printk( " Serial 0: Disabled\n" );
1966 }
1967
1968 if ( SMC37c669_is_device_enabled( SERIAL_1 ) ) {
1969 printk( " Serial 1: Enabled [ Port 0x%x, IRQ %d ]\n",
1970 local_config[ SERIAL_1 ].port1,
1971 local_config[ SERIAL_1 ].irq
1972 );
1973 }
1974 else {
1975 printk( " Serial 1: Disabled\n" );
1976 }
1977
1978 if ( SMC37c669_is_device_enabled( PARALLEL_0 ) ) {
1979 printk( " Parallel: Enabled [ Port 0x%x, IRQ %d/%d ]\n",
1980 local_config[ PARALLEL_0 ].port1,
1981 local_config[ PARALLEL_0 ].irq,
1982 local_config[ PARALLEL_0 ].drq
1983 );
1984 }
1985 else {
1986 printk( " Parallel: Disabled\n" );
1987 }
1988
1989 if ( SMC37c669_is_device_enabled( FLOPPY_0 ) ) {
1990 printk( " Floppy Ctrl: Enabled [ Port 0x%x, IRQ %d/%d ]\n",
1991 local_config[ FLOPPY_0 ].port1,
1992 local_config[ FLOPPY_0 ].irq,
1993 local_config[ FLOPPY_0 ].drq
1994 );
1995 }
1996 else {
1997 printk( " Floppy Ctrl: Disabled\n" );
1998 }
1999
2000 if ( SMC37c669_is_device_enabled( IDE_0 ) ) {
2001 printk( " IDE 0: Enabled [ Port 0x%x, IRQ %d ]\n",
2002 local_config[ IDE_0 ].port1,
2003 local_config[ IDE_0 ].irq
2004 );
2005 }
2006 else {
2007 printk( " IDE 0: Disabled\n" );
2008 }
2009 }
2010
2011
2012 /*
2013 **++
2014 ** FUNCTIONAL DESCRIPTION:
2015 **
2016 ** This function puts the SMC37c669 Super I/O controller into,
2017 ** and takes it out of, configuration mode.
2018 **
2019 ** FORMAL PARAMETERS:
2020 **
2021 ** enable:
2022 ** TRUE to enter configuration mode, FALSE to exit.
2023 **
2024 ** RETURN VALUE:
2025 **
2026 ** None
2027 **
2028 ** SIDE EFFECTS:
2029 **
2030 ** The SMC37c669 controller may be left in configuration mode.
2031 **
2032 **--
2033 */
2034 static void __init SMC37c669_config_mode(
2035 unsigned int enable )
2036 {
2037 if ( enable ) {
2038 /*
2039 ** To enter configuration mode, two writes in succession to the index
2040 ** port are required. If a write to another address or port occurs
2041 ** between these two writes, the chip does not enter configuration
2042 ** mode. Therefore, a spinlock is placed around the two writes to
2043 ** guarantee that they complete uninterrupted.
2044 */
2045 spinlock( &spl_atomic );
2046 wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY );
2047 wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY );
2048 spinunlock( &spl_atomic );
2049 }
2050 else {
2051 wb( &SMC37c669->index_port, SMC37c669_CONFIG_OFF_KEY );
2052 }
2053 }
2054
2055 /*
2056 **++
2057 ** FUNCTIONAL DESCRIPTION:
2058 **
2059 ** This function reads an SMC37c669 Super I/O controller
2060 ** configuration register. This function assumes that the
2061 ** device is already in configuration mode.
2062 **
2063 ** FORMAL PARAMETERS:
2064 **
2065 ** index:
2066 ** Index value of configuration register to read
2067 **
2068 ** RETURN VALUE:
2069 **
2070 ** Data read from configuration register
2071 **
2072 ** SIDE EFFECTS:
2073 **
2074 ** None
2075 **
2076 **--
2077 */
2078 static unsigned char __init SMC37c669_read_config(
2079 unsigned char index )
2080 {
2081 unsigned char data;
2082
2083 wb( &SMC37c669->index_port, index );
2084 data = rb( &SMC37c669->data_port );
2085 return data;
2086 }
2087
2088 /*
2089 **++
2090 ** FUNCTIONAL DESCRIPTION:
2091 **
2092 ** This function writes an SMC37c669 Super I/O controller
2093 ** configuration register. This function assumes that the
2094 ** device is already in configuration mode.
2095 **
2096 ** FORMAL PARAMETERS:
2097 **
2098 ** index:
2099 ** Index of configuration register to write
2100 **
2101 ** data:
2102 ** Data to be written
2103 **
2104 ** RETURN VALUE:
2105 **
2106 ** None
2107 **
2108 ** SIDE EFFECTS:
2109 **
2110 ** None
2111 **
2112 **--
2113 */
2114 static void __init SMC37c669_write_config(
2115 unsigned char index,
2116 unsigned char data )
2117 {
2118 wb( &SMC37c669->index_port, index );
2119 wb( &SMC37c669->data_port, data );
2120 }
2121
2122
2123 /*
2124 **++
2125 ** FUNCTIONAL DESCRIPTION:
2126 **
2127 ** This function initializes the local device
2128 ** configuration storage. This function assumes
2129 ** that the device is already in configuration
2130 ** mode.
2131 **
2132 ** FORMAL PARAMETERS:
2133 **
2134 ** None
2135 **
2136 ** RETURN VALUE:
2137 **
2138 ** None
2139 **
2140 ** SIDE EFFECTS:
2141 **
2142 ** Local storage for device configuration information
2143 ** is initialized.
2144 **
2145 **--
2146 */
2147 static void __init SMC37c669_init_local_config ( void )
2148 {
2149 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER uart_base;
2150 SMC37c669_SERIAL_IRQ_REGISTER uart_irqs;
2151 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER ppt_base;
2152 SMC37c669_PARALLEL_FDC_IRQ_REGISTER ppt_fdc_irqs;
2153 SMC37c669_PARALLEL_FDC_DRQ_REGISTER ppt_fdc_drqs;
2154 SMC37c669_FDC_BASE_ADDRESS_REGISTER fdc_base;
2155 SMC37c669_IDE_ADDRESS_REGISTER ide_base;
2156 SMC37c669_IDE_ADDRESS_REGISTER ide_alt;
2157
2158 /*
2159 ** Get serial port 1 base address
2160 */
2161 uart_base.as_uchar =
2162 SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX );
2163 /*
2164 ** Get IRQs for serial ports 1 & 2
2165 */
2166 uart_irqs.as_uchar =
2167 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
2168 /*
2169 ** Store local configuration information for serial port 1
2170 */
2171 local_config[SERIAL_0].port1 = uart_base.by_field.addr9_3 << 3;
2172 local_config[SERIAL_0].irq =
2173 SMC37c669_xlate_irq(
2174 SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart1_irq )
2175 );
2176 /*
2177 ** Get serial port 2 base address
2178 */
2179 uart_base.as_uchar =
2180 SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX );
2181 /*
2182 ** Store local configuration information for serial port 2
2183 */
2184 local_config[SERIAL_1].port1 = uart_base.by_field.addr9_3 << 3;
2185 local_config[SERIAL_1].irq =
2186 SMC37c669_xlate_irq(
2187 SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart2_irq )
2188 );
2189 /*
2190 ** Get parallel port base address
2191 */
2192 ppt_base.as_uchar =
2193 SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX );
2194 /*
2195 ** Get IRQs for parallel port and floppy controller
2196 */
2197 ppt_fdc_irqs.as_uchar =
2198 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
2199 /*
2200 ** Get DRQs for parallel port and floppy controller
2201 */
2202 ppt_fdc_drqs.as_uchar =
2203 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
2204 /*
2205 ** Store local configuration information for parallel port
2206 */
2207 local_config[PARALLEL_0].port1 = ppt_base.by_field.addr9_2 << 2;
2208 local_config[PARALLEL_0].irq =
2209 SMC37c669_xlate_irq(
2210 SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.ppt_irq )
2211 );
2212 local_config[PARALLEL_0].drq =
2213 SMC37c669_xlate_drq(
2214 SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.ppt_drq )
2215 );
2216 /*
2217 ** Get floppy controller base address
2218 */
2219 fdc_base.as_uchar =
2220 SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX );
2221 /*
2222 ** Store local configuration information for floppy controller
2223 */
2224 local_config[FLOPPY_0].port1 = fdc_base.by_field.addr9_4 << 4;
2225 local_config[FLOPPY_0].irq =
2226 SMC37c669_xlate_irq(
2227 SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.fdc_irq )
2228 );
2229 local_config[FLOPPY_0].drq =
2230 SMC37c669_xlate_drq(
2231 SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.fdc_drq )
2232 );
2233 /*
2234 ** Get IDE controller base address
2235 */
2236 ide_base.as_uchar =
2237 SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX );
2238 /*
2239 ** Get IDE alternate status base address
2240 */
2241 ide_alt.as_uchar =
2242 SMC37c669_read_config( SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX );
2243 /*
2244 ** Store local configuration information for IDE controller
2245 */
2246 local_config[IDE_0].port1 = ide_base.by_field.addr9_4 << 4;
2247 local_config[IDE_0].port2 = ide_alt.by_field.addr9_4 << 4;
2248 local_config[IDE_0].irq = 14;
2249 }
2250
2251
2252 /*
2253 **++
2254 ** FUNCTIONAL DESCRIPTION:
2255 **
2256 ** This function returns a pointer to the local shadow
2257 ** configuration of the requested device function.
2258 **
2259 ** FORMAL PARAMETERS:
2260 **
2261 ** func:
2262 ** Which device function
2263 **
2264 ** RETURN VALUE:
2265 **
2266 ** Returns a pointer to the DEVICE_CONFIG structure for the
2267 ** requested function, otherwise, NULL.
2268 **
2269 ** SIDE EFFECTS:
2270 **
2271 ** {@description or none@}
2272 **
2273 **--
2274 */
2275 static struct DEVICE_CONFIG * __init SMC37c669_get_config( unsigned int func )
2276 {
2277 struct DEVICE_CONFIG *cp = NULL;
2278
2279 switch ( func ) {
2280 case SERIAL_0:
2281 cp = &local_config[ SERIAL_0 ];
2282 break;
2283 case SERIAL_1:
2284 cp = &local_config[ SERIAL_1 ];
2285 break;
2286 case PARALLEL_0:
2287 cp = &local_config[ PARALLEL_0 ];
2288 break;
2289 case FLOPPY_0:
2290 cp = &local_config[ FLOPPY_0 ];
2291 break;
2292 case IDE_0:
2293 cp = &local_config[ IDE_0 ];
2294 break;
2295 }
2296 return cp;
2297 }
2298
2299 /*
2300 **++
2301 ** FUNCTIONAL DESCRIPTION:
2302 **
2303 ** This function translates IRQs back and forth between ISA
2304 ** IRQs and SMC37c669 device IRQs.
2305 **
2306 ** FORMAL PARAMETERS:
2307 **
2308 ** irq:
2309 ** The IRQ to translate
2310 **
2311 ** RETURN VALUE:
2312 **
2313 ** Returns the translated IRQ, otherwise, returns -1.
2314 **
2315 ** SIDE EFFECTS:
2316 **
2317 ** {@description or none@}
2318 **
2319 **--
2320 */
2321 static int __init SMC37c669_xlate_irq ( unsigned int irq )
2322 {
2323 int i, translated_irq = -1;
2324
2325 if ( SMC37c669_IS_DEVICE_IRQ( irq ) ) {
2326 /*
2327 ** We are translating a device IRQ to an ISA IRQ
2328 */
2329 for ( i = 0; ( SMC37c669_irq_table[i].device_irq != -1 ) || ( SMC37c669_irq_table[i].isa_irq != -1 ); i++ ) {
2330 if ( irq == SMC37c669_irq_table[i].device_irq ) {
2331 translated_irq = SMC37c669_irq_table[i].isa_irq;
2332 break;
2333 }
2334 }
2335 }
2336 else {
2337 /*
2338 ** We are translating an ISA IRQ to a device IRQ
2339 */
2340 for ( i = 0; ( SMC37c669_irq_table[i].isa_irq != -1 ) || ( SMC37c669_irq_table[i].device_irq != -1 ); i++ ) {
2341 if ( irq == SMC37c669_irq_table[i].isa_irq ) {
2342 translated_irq = SMC37c669_irq_table[i].device_irq;
2343 break;
2344 }
2345 }
2346 }
2347 return translated_irq;
2348 }
2349
2350
2351 /*
2352 **++
2353 ** FUNCTIONAL DESCRIPTION:
2354 **
2355 ** This function translates DMA channels back and forth between
2356 ** ISA DMA channels and SMC37c669 device DMA channels.
2357 **
2358 ** FORMAL PARAMETERS:
2359 **
2360 ** drq:
2361 ** The DMA channel to translate
2362 **
2363 ** RETURN VALUE:
2364 **
2365 ** Returns the translated DMA channel, otherwise, returns -1
2366 **
2367 ** SIDE EFFECTS:
2368 **
2369 ** {@description or none@}
2370 **
2371 **--
2372 */
2373 static int __init SMC37c669_xlate_drq ( unsigned int drq )
2374 {
2375 int i, translated_drq = -1;
2376
2377 if ( SMC37c669_IS_DEVICE_DRQ( drq ) ) {
2378 /*
2379 ** We are translating a device DMA channel to an ISA DMA channel
2380 */
2381 for ( i = 0; ( SMC37c669_drq_table[i].device_drq != -1 ) || ( SMC37c669_drq_table[i].isa_drq != -1 ); i++ ) {
2382 if ( drq == SMC37c669_drq_table[i].device_drq ) {
2383 translated_drq = SMC37c669_drq_table[i].isa_drq;
2384 break;
2385 }
2386 }
2387 }
2388 else {
2389 /*
2390 ** We are translating an ISA DMA channel to a device DMA channel
2391 */
2392 for ( i = 0; ( SMC37c669_drq_table[i].isa_drq != -1 ) || ( SMC37c669_drq_table[i].device_drq != -1 ); i++ ) {
2393 if ( drq == SMC37c669_drq_table[i].isa_drq ) {
2394 translated_drq = SMC37c669_drq_table[i].device_drq;
2395 break;
2396 }
2397 }
2398 }
2399 return translated_drq;
2400 }
2401
2402 #if 0
2403 int __init smcc669_init ( void )
2404 {
2405 struct INODE *ip;
2406
2407 allocinode( smc_ddb.name, 1, &ip );
2408 ip->dva = &smc_ddb;
2409 ip->attr = ATTR$M_WRITE | ATTR$M_READ;
2410 ip->len[0] = 0x30;
2411 ip->misc = 0;
2412 INODE_UNLOCK( ip );
2413
2414 return msg_success;
2415 }
2416
2417 int __init smcc669_open( struct FILE *fp, char *info, char *next, char *mode )
2418 {
2419 struct INODE *ip;
2420 /*
2421 ** Allow multiple readers but only one writer. ip->misc keeps track
2422 ** of the number of writers
2423 */
2424 ip = fp->ip;
2425 INODE_LOCK( ip );
2426 if ( fp->mode & ATTR$M_WRITE ) {
2427 if ( ip->misc ) {
2428 INODE_UNLOCK( ip );
2429 return msg_failure; /* too many writers */
2430 }
2431 ip->misc++;
2432 }
2433 /*
2434 ** Treat the information field as a byte offset
2435 */
2436 *fp->offset = xtoi( info );
2437 INODE_UNLOCK( ip );
2438
2439 return msg_success;
2440 }
2441
2442 int __init smcc669_close( struct FILE *fp )
2443 {
2444 struct INODE *ip;
2445
2446 ip = fp->ip;
2447 if ( fp->mode & ATTR$M_WRITE ) {
2448 INODE_LOCK( ip );
2449 ip->misc--;
2450 INODE_UNLOCK( ip );
2451 }
2452 return msg_success;
2453 }
2454
2455 int __init smcc669_read( struct FILE *fp, int size, int number, unsigned char *buf )
2456 {
2457 int i;
2458 int length;
2459 int nbytes;
2460 struct INODE *ip;
2461
2462 /*
2463 ** Always access a byte at a time
2464 */
2465 ip = fp->ip;
2466 length = size * number;
2467 nbytes = 0;
2468
2469 SMC37c669_config_mode( TRUE );
2470 for ( i = 0; i < length; i++ ) {
2471 if ( !inrange( *fp->offset, 0, ip->len[0] ) )
2472 break;
2473 *buf++ = SMC37c669_read_config( *fp->offset );
2474 *fp->offset += 1;
2475 nbytes++;
2476 }
2477 SMC37c669_config_mode( FALSE );
2478 return nbytes;
2479 }
2480
2481 int __init smcc669_write( struct FILE *fp, int size, int number, unsigned char *buf )
2482 {
2483 int i;
2484 int length;
2485 int nbytes;
2486 struct INODE *ip;
2487 /*
2488 ** Always access a byte at a time
2489 */
2490 ip = fp->ip;
2491 length = size * number;
2492 nbytes = 0;
2493
2494 SMC37c669_config_mode( TRUE );
2495 for ( i = 0; i < length; i++ ) {
2496 if ( !inrange( *fp->offset, 0, ip->len[0] ) )
2497 break;
2498 SMC37c669_write_config( *fp->offset, *buf );
2499 *fp->offset += 1;
2500 buf++;
2501 nbytes++;
2502 }
2503 SMC37c669_config_mode( FALSE );
2504 return nbytes;
2505 }
2506 #endif
2507
2508 void __init
2509 SMC37c669_dump_registers(void)
2510 {
2511 int i;
2512 for (i = 0; i <= 0x29; i++)
2513 printk("-- CR%02x : %02x\n", i, SMC37c669_read_config(i));
2514 }
2515 /*+
2516 * ============================================================================
2517 * = SMC_init - SMC37c669 Super I/O controller initialization =
2518 * ============================================================================
2519 *
2520 * OVERVIEW:
2521 *
2522 * This routine configures and enables device functions on the
2523 * SMC37c669 Super I/O controller.
2524 *
2525 * FORM OF CALL:
2526 *
2527 * SMC_init( );
2528 *
2529 * RETURNS:
2530 *
2531 * Nothing
2532 *
2533 * ARGUMENTS:
2534 *
2535 * None
2536 *
2537 * SIDE EFFECTS:
2538 *
2539 * None
2540 *
2541 */
2542 void __init SMC669_Init ( int index )
2543 {
2544 SMC37c669_CONFIG_REGS *SMC_base;
2545 unsigned long flags;
2546
2547 __save_and_cli(flags);
2548 if ( ( SMC_base = SMC37c669_detect( index ) ) != NULL ) {
2549 #if SMC_DEBUG
2550 SMC37c669_config_mode( TRUE );
2551 SMC37c669_dump_registers( );
2552 SMC37c669_config_mode( FALSE );
2553 SMC37c669_display_device_info( );
2554 #endif
2555 SMC37c669_disable_device( SERIAL_0 );
2556 SMC37c669_configure_device(
2557 SERIAL_0,
2558 COM1_BASE,
2559 COM1_IRQ,
2560 -1
2561 );
2562 SMC37c669_enable_device( SERIAL_0 );
2563
2564 SMC37c669_disable_device( SERIAL_1 );
2565 SMC37c669_configure_device(
2566 SERIAL_1,
2567 COM2_BASE,
2568 COM2_IRQ,
2569 -1
2570 );
2571 SMC37c669_enable_device( SERIAL_1 );
2572
2573 SMC37c669_disable_device( PARALLEL_0 );
2574 SMC37c669_configure_device(
2575 PARALLEL_0,
2576 PARP_BASE,
2577 PARP_IRQ,
2578 PARP_DRQ
2579 );
2580 SMC37c669_enable_device( PARALLEL_0 );
2581
2582 SMC37c669_disable_device( FLOPPY_0 );
2583 SMC37c669_configure_device(
2584 FLOPPY_0,
2585 FDC_BASE,
2586 FDC_IRQ,
2587 FDC_DRQ
2588 );
2589 SMC37c669_enable_device( FLOPPY_0 );
2590
2591 /* Wake up sometimes forgotten floppy, especially on DP264. */
2592 outb(0xc, 0x3f2);
2593
2594 SMC37c669_disable_device( IDE_0 );
2595
2596 #if SMC_DEBUG
2597 SMC37c669_config_mode( TRUE );
2598 SMC37c669_dump_registers( );
2599 SMC37c669_config_mode( FALSE );
2600 SMC37c669_display_device_info( );
2601 #endif
2602 __restore_flags(flags);
2603 printk( "SMC37c669 Super I/O Controller found @ 0x%lx\n",
2604 (unsigned long) SMC_base );
2605 }
2606 else {
2607 __restore_flags(flags);
2608 #if SMC_DEBUG
2609 printk( "No SMC37c669 Super I/O Controller found\n" );
2610 #endif
2611 }
2612 }
2613