smc37c669.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:62k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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