Author | Tokens | Token Proportion | Commits | Commit Proportion |
---|---|---|---|---|
Linus Torvalds (pre-git) | 4744 | 99.54% | 30 | 83.33% |
Martin Dalecki | 6 | 0.13% | 1 | 2.78% |
Al Viro | 6 | 0.13% | 1 | 2.78% |
Thomas Gleixner | 5 | 0.10% | 1 | 2.78% |
Ingo Molnar | 3 | 0.06% | 1 | 2.78% |
Randy Dunlap | 1 | 0.02% | 1 | 2.78% |
Masahiro Yamada | 1 | 0.02% | 1 | 2.78% |
Total | 4766 | 36 |
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541
/* * SMC 37C669 initialization code */ #include <linux/kernel.h> #include <linux/mm.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/spinlock.h> #include <asm/hwrpb.h> #include <asm/io.h> #include "proto.h" #if 0 # define DBG_DEVS(args) printk args #else # define DBG_DEVS(args) #endif #define KB 1024 #define MB (1024*KB) #define GB (1024*MB) #define SMC_DEBUG 0 /* File: smcc669_def.h * * Copyright (C) 1997 by * Digital Equipment Corporation, Maynard, Massachusetts. * All rights reserved. * * This software is furnished under a license and may be used and copied * only in accordance of the terms of such license and with the * inclusion of the above copyright notice. This software or any other * copies thereof may not be provided or otherwise made available to any * other person. No title to and ownership of the software is hereby * transferred. * * The information in this software is subject to change without notice * and should not be construed as a commitment by Digital Equipment * Corporation. * * Digital assumes no responsibility for the use or reliability of its * software on equipment which is not supplied by Digital. * * * Abstract: * * This file contains header definitions for the SMC37c669 * Super I/O controller. * * Author: * * Eric Rasmussen * * Modification History: * * er 28-Jan-1997 Initial Entry */ #ifndef __SMC37c669_H #define __SMC37c669_H /* ** Macros for handling device IRQs ** ** The mask acts as a flag used in mapping actual ISA IRQs (0 - 15) ** to device IRQs (A - H). */ #define SMC37c669_DEVICE_IRQ_MASK 0x80000000 #define SMC37c669_DEVICE_IRQ( __i ) \ ((SMC37c669_DEVICE_IRQ_MASK) | (__i)) #define SMC37c669_IS_DEVICE_IRQ(__i) \ (((__i) & (SMC37c669_DEVICE_IRQ_MASK)) == (SMC37c669_DEVICE_IRQ_MASK)) #define SMC37c669_RAW_DEVICE_IRQ(__i) \ ((__i) & ~(SMC37c669_DEVICE_IRQ_MASK)) /* ** Macros for handling device DRQs ** ** The mask acts as a flag used in mapping actual ISA DMA ** channels to device DMA channels (A - C). */ #define SMC37c669_DEVICE_DRQ_MASK 0x80000000 #define SMC37c669_DEVICE_DRQ(__d) \ ((SMC37c669_DEVICE_DRQ_MASK) | (__d)) #define SMC37c669_IS_DEVICE_DRQ(__d) \ (((__d) & (SMC37c669_DEVICE_DRQ_MASK)) == (SMC37c669_DEVICE_DRQ_MASK)) #define SMC37c669_RAW_DEVICE_DRQ(__d) \ ((__d) & ~(SMC37c669_DEVICE_DRQ_MASK)) #define SMC37c669_DEVICE_ID 0x3 /* ** SMC37c669 Device Function Definitions */ #define SERIAL_0 0 #define SERIAL_1 1 #define PARALLEL_0 2 #define FLOPPY_0 3 #define IDE_0 4 #define NUM_FUNCS 5 /* ** Default Device Function Mappings */ #define COM1_BASE 0x3F8 #define COM1_IRQ 4 #define COM2_BASE 0x2F8 #define COM2_IRQ 3 #define PARP_BASE 0x3BC #define PARP_IRQ 7 #define PARP_DRQ 3 #define FDC_BASE 0x3F0 #define FDC_IRQ 6 #define FDC_DRQ 2 /* ** Configuration On/Off Key Definitions */ #define SMC37c669_CONFIG_ON_KEY 0x55 #define SMC37c669_CONFIG_OFF_KEY 0xAA /* ** SMC 37c669 Device IRQs */ #define SMC37c669_DEVICE_IRQ_A ( SMC37c669_DEVICE_IRQ( 0x01 ) ) #define SMC37c669_DEVICE_IRQ_B ( SMC37c669_DEVICE_IRQ( 0x02 ) ) #define SMC37c669_DEVICE_IRQ_C ( SMC37c669_DEVICE_IRQ( 0x03 ) ) #define SMC37c669_DEVICE_IRQ_D ( SMC37c669_DEVICE_IRQ( 0x04 ) ) #define SMC37c669_DEVICE_IRQ_E ( SMC37c669_DEVICE_IRQ( 0x05 ) ) #define SMC37c669_DEVICE_IRQ_F ( SMC37c669_DEVICE_IRQ( 0x06 ) ) /* SMC37c669_DEVICE_IRQ_G *** RESERVED ***/ #define SMC37c669_DEVICE_IRQ_H ( SMC37c669_DEVICE_IRQ( 0x08 ) ) /* ** SMC 37c669 Device DMA Channel Definitions */ #define SMC37c669_DEVICE_DRQ_A ( SMC37c669_DEVICE_DRQ( 0x01 ) ) #define SMC37c669_DEVICE_DRQ_B ( SMC37c669_DEVICE_DRQ( 0x02 ) ) #define SMC37c669_DEVICE_DRQ_C ( SMC37c669_DEVICE_DRQ( 0x03 ) ) /* ** Configuration Register Index Definitions */ #define SMC37c669_CR00_INDEX 0x00 #define SMC37c669_CR01_INDEX 0x01 #define SMC37c669_CR02_INDEX 0x02 #define SMC37c669_CR03_INDEX 0x03 #define SMC37c669_CR04_INDEX 0x04 #define SMC37c669_CR05_INDEX 0x05 #define SMC37c669_CR06_INDEX 0x06 #define SMC37c669_CR07_INDEX 0x07 #define SMC37c669_CR08_INDEX 0x08 #define SMC37c669_CR09_INDEX 0x09 #define SMC37c669_CR0A_INDEX 0x0A #define SMC37c669_CR0B_INDEX 0x0B #define SMC37c669_CR0C_INDEX 0x0C #define SMC37c669_CR0D_INDEX 0x0D #define SMC37c669_CR0E_INDEX 0x0E #define SMC37c669_CR0F_INDEX 0x0F #define SMC37c669_CR10_INDEX 0x10 #define SMC37c669_CR11_INDEX 0x11 #define SMC37c669_CR12_INDEX 0x12 #define SMC37c669_CR13_INDEX 0x13 #define SMC37c669_CR14_INDEX 0x14 #define SMC37c669_CR15_INDEX 0x15 #define SMC37c669_CR16_INDEX 0x16 #define SMC37c669_CR17_INDEX 0x17 #define SMC37c669_CR18_INDEX 0x18 #define SMC37c669_CR19_INDEX 0x19 #define SMC37c669_CR1A_INDEX 0x1A #define SMC37c669_CR1B_INDEX 0x1B #define SMC37c669_CR1C_INDEX 0x1C #define SMC37c669_CR1D_INDEX 0x1D #define SMC37c669_CR1E_INDEX 0x1E #define SMC37c669_CR1F_INDEX 0x1F #define SMC37c669_CR20_INDEX 0x20 #define SMC37c669_CR21_INDEX 0x21 #define SMC37c669_CR22_INDEX 0x22 #define SMC37c669_CR23_INDEX 0x23 #define SMC37c669_CR24_INDEX 0x24 #define SMC37c669_CR25_INDEX 0x25 #define SMC37c669_CR26_INDEX 0x26 #define SMC37c669_CR27_INDEX 0x27 #define SMC37c669_CR28_INDEX 0x28 #define SMC37c669_CR29_INDEX 0x29 /* ** Configuration Register Alias Definitions */ #define SMC37c669_DEVICE_ID_INDEX SMC37c669_CR0D_INDEX #define SMC37c669_DEVICE_REVISION_INDEX SMC37c669_CR0E_INDEX #define SMC37c669_FDC_BASE_ADDRESS_INDEX SMC37c669_CR20_INDEX #define SMC37c669_IDE_BASE_ADDRESS_INDEX SMC37c669_CR21_INDEX #define SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX SMC37c669_CR22_INDEX #define SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX SMC37c669_CR23_INDEX #define SMC37c669_SERIAL0_BASE_ADDRESS_INDEX SMC37c669_CR24_INDEX #define SMC37c669_SERIAL1_BASE_ADDRESS_INDEX SMC37c669_CR25_INDEX #define SMC37c669_PARALLEL_FDC_DRQ_INDEX SMC37c669_CR26_INDEX #define SMC37c669_PARALLEL_FDC_IRQ_INDEX SMC37c669_CR27_INDEX #define SMC37c669_SERIAL_IRQ_INDEX SMC37c669_CR28_INDEX /* ** Configuration Register Definitions ** ** The INDEX (write only) and DATA (read/write) ports are effective ** only when the chip is in the Configuration State. */ typedef struct _SMC37c669_CONFIG_REGS { unsigned char index_port; unsigned char data_port; } SMC37c669_CONFIG_REGS; /* ** CR00 - default value 0x28 ** ** IDE_EN (CR00<1:0>): ** 0x - 30ua pull-ups on nIDEEN, nHDCS0, NHDCS1 ** 11 - IRQ_H available as IRQ output, ** IRRX2, IRTX2 available as alternate IR pins ** 10 - nIDEEN, nHDCS0, nHDCS1 used to control IDE ** ** VALID (CR00<7>): ** A high level on this software controlled bit can ** be used to indicate that a valid configuration ** cycle has occurred. The control software must ** take care to set this bit at the appropriate times. ** Set to zero after power up. This bit has no ** effect on any other hardware in the chip. ** */ typedef union _SMC37c669_CR00 { unsigned char as_uchar; struct { unsigned ide_en : 2; /* See note above */ unsigned reserved1 : 1; /* RAZ */ unsigned fdc_pwr : 1; /* 1 = supply power to FDC */ unsigned reserved2 : 3; /* Read as 010b */ unsigned valid : 1; /* See note above */ } by_field; } SMC37c669_CR00; /* ** CR01 - default value 0x9C */ typedef union _SMC37c669_CR01 { unsigned char as_uchar; struct { unsigned reserved1 : 2; /* RAZ */ unsigned ppt_pwr : 1; /* 1 = supply power to PPT */ unsigned ppt_mode : 1; /* 1 = Printer mode, 0 = EPP */ unsigned reserved2 : 1; /* Read as 1 */ unsigned reserved3 : 2; /* RAZ */ unsigned lock_crx: 1; /* Lock CR00 - CR18 */ } by_field; } SMC37c669_CR01; /* ** CR02 - default value 0x88 */ typedef union _SMC37c669_CR02 { unsigned char as_uchar; struct { unsigned reserved1 : 3; /* RAZ */ unsigned uart1_pwr : 1; /* 1 = supply power to UART1 */ unsigned reserved2 : 3; /* RAZ */ unsigned uart2_pwr : 1; /* 1 = supply power to UART2 */ } by_field; } SMC37c669_CR02; /* ** CR03 - default value 0x78 ** ** CR03<7> CR03<2> Pin 94 ** ------- ------- ------ ** 0 X DRV2 (input) ** 1 0 ADRX ** 1 1 IRQ_B ** ** CR03<6> CR03<5> Op Mode ** ------- ------- ------- ** 0 0 Model 30 ** 0 1 PS/2 ** 1 0 Reserved ** 1 1 AT Mode */ typedef union _SMC37c669_CR03 { unsigned char as_uchar; struct { unsigned pwrgd_gamecs : 1; /* 1 = PWRGD, 0 = GAMECS */ unsigned fdc_mode2 : 1; /* 1 = Enhanced Mode 2 */ unsigned pin94_0 : 1; /* See note above */ unsigned reserved1 : 1; /* RAZ */ unsigned drvden : 1; /* 1 = high, 0 - output */ unsigned op_mode : 2; /* See note above */ unsigned pin94_1 : 1; /* See note above */ } by_field; } SMC37c669_CR03; /* ** CR04 - default value 0x00 ** ** PP_EXT_MODE: ** If CR01<PP_MODE> = 0 and PP_EXT_MODE = ** 00 - Standard and Bidirectional ** 01 - EPP mode and SPP ** 10 - ECP mode ** In this mode, 2 drives can be supported ** directly, 3 or 4 drives must use external ** 4 drive support. SPP can be selected ** through the ECR register of ECP as mode 000. ** 11 - ECP mode and EPP mode ** In this mode, 2 drives can be supported ** directly, 3 or 4 drives must use external ** 4 drive support. SPP can be selected ** through the ECR register of ECP as mode 000. ** In this mode, EPP can be selected through ** the ECR register of ECP as mode 100. ** ** PP_FDC: ** 00 - Normal ** 01 - PPFD1 ** 10 - PPFD2 ** 11 - Reserved ** ** MIDI1: ** Serial Clock Select: ** A low level on this bit disables MIDI support, ** clock = divide by 13. A high level on this ** bit enables MIDI support, clock = divide by 12. ** ** MIDI operates at 31.25 Kbps which can be derived ** from 125 KHz (24 MHz / 12 = 2 MHz, 2 MHz / 16 = 125 KHz) ** ** ALT_IO: ** 0 - Use pins IRRX, IRTX ** 1 - Use pins IRRX2, IRTX2 ** ** If this bit is set, the IR receive and transmit ** functions will not be available on pins 25 and 26 ** unless CR00<IDE_EN> = 11. */ typedef union _SMC37c669_CR04 { unsigned char as_uchar; struct { unsigned ppt_ext_mode : 2; /* See note above */ unsigned ppt_fdc : 2; /* See note above */ unsigned midi1 : 1; /* See note above */ unsigned midi2 : 1; /* See note above */ unsigned epp_type : 1; /* 0 = EPP 1.9, 1 = EPP 1.7 */ unsigned alt_io : 1; /* See note above */ } by_field; } SMC37c669_CR04; /* ** CR05 - default value 0x00 ** ** DEN_SEL: ** 00 - Densel output normal ** 01 - Reserved ** 10 - Densel output 1 ** 11 - Densel output 0 ** */ typedef union _SMC37c669_CR05 { unsigned char as_uchar; struct { unsigned reserved1 : 2; /* RAZ */ unsigned fdc_dma_mode : 1; /* 0 = burst, 1 = non-burst */ unsigned den_sel : 2; /* See note above */ unsigned swap_drv : 1; /* Swap the FDC motor selects */ unsigned extx4 : 1; /* 0 = 2 drive, 1 = external 4 drive decode */ unsigned reserved2 : 1; /* RAZ */ } by_field; } SMC37c669_CR05; /* ** CR06 - default value 0xFF */ typedef union _SMC37c669_CR06 { unsigned char as_uchar; struct { unsigned floppy_a : 2; /* Type of floppy drive A */ unsigned floppy_b : 2; /* Type of floppy drive B */ unsigned floppy_c : 2; /* Type of floppy drive C */ unsigned floppy_d : 2; /* Type of floppy drive D */ } by_field; } SMC37c669_CR06; /* ** CR07 - default value 0x00 ** ** Auto Power Management CR07<7:4>: ** 0 - Auto Powerdown disabled (default) ** 1 - Auto Powerdown enabled ** ** This bit is reset to the default state by POR or ** a hardware reset. ** */ typedef union _SMC37c669_CR07 { unsigned char as_uchar; struct { unsigned floppy_boot : 2; /* 0 = A:, 1 = B: */ unsigned reserved1 : 2; /* RAZ */ unsigned ppt_en : 1; /* See note above */ unsigned uart1_en : 1; /* See note above */ unsigned uart2_en : 1; /* See note above */ unsigned fdc_en : 1; /* See note above */ } by_field; } SMC37c669_CR07; /* ** CR08 - default value 0x00 */ typedef union _SMC37c669_CR08 { unsigned char as_uchar; struct { unsigned zero : 4; /* 0 */ unsigned addrx7_4 : 4; /* ADR<7:3> for ADRx decode */ } by_field; } SMC37c669_CR08; /* ** CR09 - default value 0x00 ** ** ADRx_CONFIG: ** 00 - ADRx disabled ** 01 - 1 byte decode A<3:0> = 0000b ** 10 - 8 byte block decode A<3:0> = 0XXXb ** 11 - 16 byte block decode A<3:0> = XXXXb ** */ typedef union _SMC37c669_CR09 { unsigned char as_uchar; struct { unsigned adra8 : 3; /* ADR<10:8> for ADRx decode */ unsigned reserved1 : 3; unsigned adrx_config : 2; /* See note above */ } by_field; } SMC37c669_CR09; /* ** CR0A - default value 0x00 */ typedef union _SMC37c669_CR0A { unsigned char as_uchar; struct { unsigned ecp_fifo_threshold : 4; unsigned reserved1 : 4; } by_field; } SMC37c669_CR0A; /* ** CR0B - default value 0x00 */ typedef union _SMC37c669_CR0B { unsigned char as_uchar; struct { unsigned fdd0_drtx : 2; /* FDD0 Data Rate Table */ unsigned fdd1_drtx : 2; /* FDD1 Data Rate Table */ unsigned fdd2_drtx : 2; /* FDD2 Data Rate Table */ unsigned fdd3_drtx : 2; /* FDD3 Data Rate Table */ } by_field; } SMC37c669_CR0B; /* ** CR0C - default value 0x00 ** ** UART2_MODE: ** 000 - Standard (default) ** 001 - IrDA (HPSIR) ** 010 - Amplitude Shift Keyed IR @500 KHz ** 011 - Reserved ** 1xx - Reserved ** */ typedef union _SMC37c669_CR0C { unsigned char as_uchar; struct { unsigned uart2_rcv_polarity : 1; /* 1 = invert RX */ unsigned uart2_xmit_polarity : 1; /* 1 = invert TX */ unsigned uart2_duplex : 1; /* 1 = full, 0 = half */ unsigned uart2_mode : 3; /* See note above */ unsigned uart1_speed : 1; /* 1 = high speed enabled */ unsigned uart2_speed : 1; /* 1 = high speed enabled */ } by_field; } SMC37c669_CR0C; /* ** CR0D - default value 0x03 ** ** Device ID Register - read only */ typedef union _SMC37c669_CR0D { unsigned char as_uchar; struct { unsigned device_id : 8; /* Returns 0x3 in this field */ } by_field; } SMC37c669_CR0D; /* ** CR0E - default value 0x02 ** ** Device Revision Register - read only */ typedef union _SMC37c669_CR0E { unsigned char as_uchar; struct { unsigned device_rev : 8; /* Returns 0x2 in this field */ } by_field; } SMC37c669_CR0E; /* ** CR0F - default value 0x00 */ typedef union _SMC37c669_CR0F { unsigned char as_uchar; struct { unsigned test0 : 1; /* Reserved - set to 0 */ unsigned test1 : 1; /* Reserved - set to 0 */ unsigned test2 : 1; /* Reserved - set to 0 */ unsigned test3 : 1; /* Reserved - set t0 0 */ unsigned test4 : 1; /* Reserved - set to 0 */ unsigned test5 : 1; /* Reserved - set t0 0 */ unsigned test6 : 1; /* Reserved - set t0 0 */ unsigned test7 : 1; /* Reserved - set to 0 */ } by_field; } SMC37c669_CR0F; /* ** CR10 - default value 0x00 */ typedef union _SMC37c669_CR10 { unsigned char as_uchar; struct { unsigned reserved1 : 3; /* RAZ */ unsigned pll_gain : 1; /* 1 = 3V, 2 = 5V operation */ unsigned pll_stop : 1; /* 1 = stop PLLs */ unsigned ace_stop : 1; /* 1 = stop UART clocks */ unsigned pll_clock_ctrl : 1; /* 0 = 14.318 MHz, 1 = 24 MHz */ unsigned ir_test : 1; /* Enable IR test mode */ } by_field; } SMC37c669_CR10; /* ** CR11 - default value 0x00 */ typedef union _SMC37c669_CR11 { unsigned char as_uchar; struct { unsigned ir_loopback : 1; /* Internal IR loop back */ unsigned test_10ms : 1; /* Test 10ms autopowerdown FDC timeout */ unsigned reserved1 : 6; /* RAZ */ } by_field; } SMC37c669_CR11; /* ** CR12 - CR1D are reserved registers */ /* ** CR1E - default value 0x80 ** ** GAMECS: ** 00 - GAMECS disabled ** 01 - 1 byte decode ADR<3:0> = 0001b ** 10 - 8 byte block decode ADR<3:0> = 0XXXb ** 11 - 16 byte block decode ADR<3:0> = XXXXb ** */ typedef union _SMC37c66_CR1E { unsigned char as_uchar; struct { unsigned gamecs_config: 2; /* See note above */ unsigned gamecs_addr9_4 : 6; /* GAMECS Addr<9:4> */ } by_field; } SMC37c669_CR1E; /* ** CR1F - default value 0x00 ** ** DT0 DT1 DRVDEN0 DRVDEN1 Drive Type ** --- --- ------- ------- ---------- ** 0 0 DENSEL DRATE0 4/2/1 MB 3.5" ** 2/1 MB 5.25" ** 2/1.6/1 MB 3.5" (3-mode) ** 0 1 DRATE1 DRATE0 ** 1 0 nDENSEL DRATE0 PS/2 ** 1 1 DRATE0 DRATE1 ** ** Note: DENSEL, DRATE1, and DRATE0 map onto two output ** pins - DRVDEN0 and DRVDEN1. ** */ typedef union _SMC37c669_CR1F { unsigned char as_uchar; struct { unsigned fdd0_drive_type : 2; /* FDD0 drive type */ unsigned fdd1_drive_type : 2; /* FDD1 drive type */ unsigned fdd2_drive_type : 2; /* FDD2 drive type */ unsigned fdd3_drive_type : 2; /* FDD3 drive type */ } by_field; } SMC37c669_CR1F; /* ** CR20 - default value 0x3C ** ** FDC Base Address Register ** - To disable this decode set Addr<9:8> = 0 ** - A<10> = 0, A<3:0> = 0XXXb to access. ** */ typedef union _SMC37c669_CR20 { unsigned char as_uchar; struct { unsigned zero : 2; /* 0 */ unsigned addr9_4 : 6; /* FDC Addr<9:4> */ } by_field; } SMC37c669_CR20; /* ** CR21 - default value 0x3C ** ** IDE Base Address Register ** - To disable this decode set Addr<9:8> = 0 ** - A<10> = 0, A<3:0> = 0XXXb to access. ** */ typedef union _SMC37c669_CR21 { unsigned char as_uchar; struct { unsigned zero : 2; /* 0 */ unsigned addr9_4 : 6; /* IDE Addr<9:4> */ } by_field; } SMC37c669_CR21; /* ** CR22 - default value 0x3D ** ** IDE Alternate Status Base Address Register ** - To disable this decode set Addr<9:8> = 0 ** - A<10> = 0, A<3:0> = 0110b to access. ** */ typedef union _SMC37c669_CR22 { unsigned char as_uchar; struct { unsigned zero : 2; /* 0 */ unsigned addr9_4 : 6; /* IDE Alt Status Addr<9:4> */ } by_field; } SMC37c669_CR22; /* ** CR23 - default value 0x00 ** ** Parallel Port Base Address Register ** - To disable this decode set Addr<9:8> = 0 ** - A<10> = 0 to access. ** - If EPP is enabled, A<2:0> = XXXb to access. ** If EPP is NOT enabled, A<1:0> = XXb to access ** */ typedef union _SMC37c669_CR23 { unsigned char as_uchar; struct { unsigned addr9_2 : 8; /* Parallel Port Addr<9:2> */ } by_field; } SMC37c669_CR23; /* ** CR24 - default value 0x00 ** ** UART1 Base Address Register ** - To disable this decode set Addr<9:8> = 0 ** - A<10> = 0, A<2:0> = XXXb to access. ** */ typedef union _SMC37c669_CR24 { unsigned char as_uchar; struct { unsigned zero : 1; /* 0 */ unsigned addr9_3 : 7; /* UART1 Addr<9:3> */ } by_field; } SMC37c669_CR24; /* ** CR25 - default value 0x00 ** ** UART2 Base Address Register ** - To disable this decode set Addr<9:8> = 0 ** - A<10> = 0, A<2:0> = XXXb to access. ** */ typedef union _SMC37c669_CR25 { unsigned char as_uchar; struct { unsigned zero : 1; /* 0 */ unsigned addr9_3 : 7; /* UART2 Addr<9:3> */ } by_field; } SMC37c669_CR25; /* ** CR26 - default value 0x00 ** ** Parallel Port / FDC DMA Select Register ** ** D3 - D0 DMA ** D7 - D4 Selected ** ------- -------- ** 0000 None ** 0001 DMA_A ** 0010 DMA_B ** 0011 DMA_C ** */ typedef union _SMC37c669_CR26 { unsigned char as_uchar; struct { unsigned ppt_drq : 4; /* See note above */ unsigned fdc_drq : 4; /* See note above */ } by_field; } SMC37c669_CR26; /* ** CR27 - default value 0x00 ** ** Parallel Port / FDC IRQ Select Register ** ** D3 - D0 IRQ ** D7 - D4 Selected ** ------- -------- ** 0000 None ** 0001 IRQ_A ** 0010 IRQ_B ** 0011 IRQ_C ** 0100 IRQ_D ** 0101 IRQ_E ** 0110 IRQ_F ** 0111 Reserved ** 1000 IRQ_H ** ** Any unselected IRQ REQ is in tristate ** */ typedef union _SMC37c669_CR27 { unsigned char as_uchar; struct { unsigned ppt_irq : 4; /* See note above */ unsigned fdc_irq : 4; /* See note above */ } by_field; } SMC37c669_CR27; /* ** CR28 - default value 0x00 ** ** UART IRQ Select Register ** ** D3 - D0 IRQ ** D7 - D4 Selected ** ------- -------- ** 0000 None ** 0001 IRQ_A ** 0010 IRQ_B ** 0011 IRQ_C ** 0100 IRQ_D ** 0101 IRQ_E ** 0110 IRQ_F ** 0111 Reserved ** 1000 IRQ_H ** 1111 share with UART1 (only for UART2) ** ** Any unselected IRQ REQ is in tristate ** ** To share an IRQ between UART1 and UART2, set ** UART1 to use the desired IRQ and set UART2 to ** 0xF to enable sharing mechanism. ** */ typedef union _SMC37c669_CR28 { unsigned char as_uchar; struct { unsigned uart2_irq : 4; /* See note above */ unsigned uart1_irq : 4; /* See note above */ } by_field; } SMC37c669_CR28; /* ** CR29 - default value 0x00 ** ** IRQIN IRQ Select Register ** ** D3 - D0 IRQ ** D7 - D4 Selected ** ------- -------- ** 0000 None ** 0001 IRQ_A ** 0010 IRQ_B ** 0011 IRQ_C ** 0100 IRQ_D ** 0101 IRQ_E ** 0110 IRQ_F ** 0111 Reserved ** 1000 IRQ_H ** ** Any unselected IRQ REQ is in tristate ** */ typedef union _SMC37c669_CR29 { unsigned char as_uchar; struct { unsigned irqin_irq : 4; /* See note above */ unsigned reserved1 : 4; /* RAZ */ } by_field; } SMC37c669_CR29; /* ** Aliases of Configuration Register formats (should match ** the set of index aliases). ** ** Note that CR24 and CR25 have the same format and are the ** base address registers for UART1 and UART2. Because of ** this we only define 1 alias here - for CR24 - as the serial ** base address register. ** ** Note that CR21 and CR22 have the same format and are the ** base address and alternate status address registers for ** the IDE controller. Because of this we only define 1 alias ** here - for CR21 - as the IDE address register. ** */ typedef SMC37c669_CR0D SMC37c669_DEVICE_ID_REGISTER; typedef SMC37c669_CR0E SMC37c669_DEVICE_REVISION_REGISTER; typedef SMC37c669_CR20 SMC37c669_FDC_BASE_ADDRESS_REGISTER; typedef SMC37c669_CR21 SMC37c669_IDE_ADDRESS_REGISTER; typedef SMC37c669_CR23 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER; typedef SMC37c669_CR24 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER; typedef SMC37c669_CR26 SMC37c669_PARALLEL_FDC_DRQ_REGISTER; typedef SMC37c669_CR27 SMC37c669_PARALLEL_FDC_IRQ_REGISTER; typedef SMC37c669_CR28 SMC37c669_SERIAL_IRQ_REGISTER; /* ** ISA/Device IRQ Translation Table Entry Definition */ typedef struct _SMC37c669_IRQ_TRANSLATION_ENTRY { int device_irq; int isa_irq; } SMC37c669_IRQ_TRANSLATION_ENTRY; /* ** ISA/Device DMA Translation Table Entry Definition */ typedef struct _SMC37c669_DRQ_TRANSLATION_ENTRY { int device_drq; int isa_drq; } SMC37c669_DRQ_TRANSLATION_ENTRY; /* ** External Interface Function Prototype Declarations */ SMC37c669_CONFIG_REGS *SMC37c669_detect( int ); unsigned int SMC37c669_enable_device( unsigned int func ); unsigned int SMC37c669_disable_device( unsigned int func ); unsigned int SMC37c669_configure_device( unsigned int func, int port, int irq, int drq ); void SMC37c669_display_device_info( void ); #endif /* __SMC37c669_H */ /* file: smcc669.c * * Copyright (C) 1997 by * Digital Equipment Corporation, Maynard, Massachusetts. * All rights reserved. * * This software is furnished under a license and may be used and copied * only in accordance of the terms of such license and with the * inclusion of the above copyright notice. This software or any other * copies thereof may not be provided or otherwise made available to any * other person. No title to and ownership of the software is hereby * transferred. * * The information in this software is subject to change without notice * and should not be construed as a commitment by digital equipment * corporation. * * Digital assumes no responsibility for the use or reliability of its * software on equipment which is not supplied by digital. */ /* *++ * FACILITY: * * Alpha SRM Console Firmware * * MODULE DESCRIPTION: * * SMC37c669 Super I/O controller configuration routines. * * AUTHORS: * * Eric Rasmussen * * CREATION DATE: * * 28-Jan-1997 * * MODIFICATION HISTORY: * * er 01-May-1997 Fixed pointer conversion errors in * SMC37c669_get_device_config(). * er 28-Jan-1997 Initial version. * *-- */ #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #define wb( _x_, _y_ ) outb( _y_, (unsigned int)((unsigned long)_x_) ) #define rb( _x_ ) inb( (unsigned int)((unsigned long)_x_) ) /* ** Local storage for device configuration information. ** ** Since the SMC37c669 does not provide an explicit ** mechanism for enabling/disabling individual device ** functions, other than unmapping the device, local ** storage for device configuration information is ** allocated here for use in implementing our own ** function enable/disable scheme. */ static struct DEVICE_CONFIG { unsigned int port1; unsigned int port2; int irq; int drq; } local_config [NUM_FUNCS]; /* ** List of all possible addresses for the Super I/O chip */ static unsigned long SMC37c669_Addresses[] __initdata = { 0x3F0UL, /* Primary address */ 0x370UL, /* Secondary address */ 0UL /* End of list */ }; /* ** Global Pointer to the Super I/O device */ static SMC37c669_CONFIG_REGS *SMC37c669 __initdata = NULL; /* ** IRQ Translation Table ** ** The IRQ translation table is a list of SMC37c669 device ** and standard ISA IRQs. ** */ static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_table __initdata; /* ** The following definition is for the default IRQ ** translation table. */ static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_default_irq_table[] __initdata = { { SMC37c669_DEVICE_IRQ_A, -1 }, { SMC37c669_DEVICE_IRQ_B, -1 }, { SMC37c669_DEVICE_IRQ_C, 7 }, { SMC37c669_DEVICE_IRQ_D, 6 }, { SMC37c669_DEVICE_IRQ_E, 4 }, { SMC37c669_DEVICE_IRQ_F, 3 }, { SMC37c669_DEVICE_IRQ_H, -1 }, { -1, -1 } /* End of table */ }; /* ** The following definition is for the MONET (XP1000) IRQ ** translation table. */ static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_monet_irq_table[] __initdata = { { SMC37c669_DEVICE_IRQ_A, -1 }, { SMC37c669_DEVICE_IRQ_B, -1 }, { SMC37c669_DEVICE_IRQ_C, 6 }, { SMC37c669_DEVICE_IRQ_D, 7 }, { SMC37c669_DEVICE_IRQ_E, 4 }, { SMC37c669_DEVICE_IRQ_F, 3 }, { SMC37c669_DEVICE_IRQ_H, -1 }, { -1, -1 } /* End of table */ }; static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_tables[] __initdata = { SMC37c669_default_irq_table, SMC37c669_monet_irq_table }; /* ** DRQ Translation Table ** ** The DRQ translation table is a list of SMC37c669 device and ** ISA DMA channels. ** */ static SMC37c669_DRQ_TRANSLATION_ENTRY *SMC37c669_drq_table __initdata; /* ** The following definition is the default DRQ ** translation table. */ static SMC37c669_DRQ_TRANSLATION_ENTRY SMC37c669_default_drq_table[] __initdata = { { SMC37c669_DEVICE_DRQ_A, 2 }, { SMC37c669_DEVICE_DRQ_B, 3 }, { SMC37c669_DEVICE_DRQ_C, -1 }, { -1, -1 } /* End of table */ }; /* ** Local Function Prototype Declarations */ static unsigned int SMC37c669_is_device_enabled( unsigned int func ); #if 0 static unsigned int SMC37c669_get_device_config( unsigned int func, int *port, int *irq, int *drq ); #endif static void SMC37c669_config_mode( unsigned int enable ); static unsigned char SMC37c669_read_config( unsigned char index ); static void SMC37c669_write_config( unsigned char index, unsigned char data ); static void SMC37c669_init_local_config( void ); static struct DEVICE_CONFIG *SMC37c669_get_config( unsigned int func ); static int SMC37c669_xlate_irq( int irq ); static int SMC37c669_xlate_drq( int drq ); static __cacheline_aligned DEFINE_SPINLOCK(smc_lock); /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function detects the presence of an SMC37c669 Super I/O ** controller. ** ** FORMAL PARAMETERS: ** ** None ** ** RETURN VALUE: ** ** Returns a pointer to the device if found, otherwise, ** the NULL pointer is returned. ** ** SIDE EFFECTS: ** ** None ** **-- */ SMC37c669_CONFIG_REGS * __init SMC37c669_detect( int index ) { int i; SMC37c669_DEVICE_ID_REGISTER id; for ( i = 0; SMC37c669_Addresses[i] != 0; i++ ) { /* ** Initialize the device pointer even though we don't yet know if ** the controller is at this address. The support functions access ** the controller through this device pointer so we need to set it ** even when we are looking ... */ SMC37c669 = ( SMC37c669_CONFIG_REGS * )SMC37c669_Addresses[i]; /* ** Enter configuration mode */ SMC37c669_config_mode( TRUE ); /* ** Read the device id */ id.as_uchar = SMC37c669_read_config( SMC37c669_DEVICE_ID_INDEX ); /* ** Exit configuration mode */ SMC37c669_config_mode( FALSE ); /* ** Does the device id match? If so, assume we have found an ** SMC37c669 controller at this address. */ if ( id.by_field.device_id == SMC37c669_DEVICE_ID ) { /* ** Initialize the IRQ and DRQ translation tables. */ SMC37c669_irq_table = SMC37c669_irq_tables[ index ]; SMC37c669_drq_table = SMC37c669_default_drq_table; /* ** erfix ** ** If the platform can't use the IRQ and DRQ defaults set up in this ** file, it should call a platform-specific external routine at this ** point to reset the IRQ and DRQ translation table pointers to point ** at the appropriate tables for the platform. If the defaults are ** acceptable, then the external routine should do nothing. */ /* ** Put the chip back into configuration mode */ SMC37c669_config_mode( TRUE ); /* ** Initialize local storage for configuration information */ SMC37c669_init_local_config( ); /* ** Exit configuration mode */ SMC37c669_config_mode( FALSE ); /* ** SMC37c669 controller found, break out of search loop */ break; } else { /* ** Otherwise, we did not find an SMC37c669 controller at this ** address so set the device pointer to NULL. */ SMC37c669 = NULL; } } return SMC37c669; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function enables an SMC37c669 device function. ** ** FORMAL PARAMETERS: ** ** func: ** Which device function to enable ** ** RETURN VALUE: ** ** Returns TRUE is the device function was enabled, otherwise, FALSE ** ** SIDE EFFECTS: ** ** {@description or none@} ** ** DESIGN: ** ** Enabling a device function in the SMC37c669 controller involves ** setting all of its mappings (port, irq, drq ...). A local ** "shadow" copy of the device configuration is kept so we can ** just set each mapping to what the local copy says. ** ** This function ALWAYS updates the local shadow configuration of ** the device function being enabled, even if the device is always ** enabled. To avoid replication of code, functions such as ** configure_device set up the local copy and then call this ** function to the update the real device. ** **-- */ unsigned int __init SMC37c669_enable_device ( unsigned int func ) { unsigned int ret_val = FALSE; /* ** Put the device into configuration mode */ SMC37c669_config_mode( TRUE ); switch ( func ) { case SERIAL_0: { SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr; SMC37c669_SERIAL_IRQ_REGISTER irq; /* ** Enable the serial 1 IRQ mapping */ irq.as_uchar = SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); irq.by_field.uart1_irq = SMC37c669_RAW_DEVICE_IRQ( SMC37c669_xlate_irq( local_config[ func ].irq ) ); SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar ); /* ** Enable the serial 1 port base address mapping */ base_addr.as_uchar = 0; base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3; SMC37c669_write_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX, base_addr.as_uchar ); ret_val = TRUE; break; } case SERIAL_1: { SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr; SMC37c669_SERIAL_IRQ_REGISTER irq; /* ** Enable the serial 2 IRQ mapping */ irq.as_uchar = SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); irq.by_field.uart2_irq = SMC37c669_RAW_DEVICE_IRQ( SMC37c669_xlate_irq( local_config[ func ].irq ) ); SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar ); /* ** Enable the serial 2 port base address mapping */ base_addr.as_uchar = 0; base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3; SMC37c669_write_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX, base_addr.as_uchar ); ret_val = TRUE; break; } case PARALLEL_0: { SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr; SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq; SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq; /* ** Enable the parallel port DMA channel mapping */ drq.as_uchar = SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); drq.by_field.ppt_drq = SMC37c669_RAW_DEVICE_DRQ( SMC37c669_xlate_drq( local_config[ func ].drq ) ); SMC37c669_write_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX, drq.as_uchar ); /* ** Enable the parallel port IRQ mapping */ irq.as_uchar = SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); irq.by_field.ppt_irq = SMC37c669_RAW_DEVICE_IRQ( SMC37c669_xlate_irq( local_config[ func ].irq ) ); SMC37c669_write_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX, irq.as_uchar ); /* ** Enable the parallel port base address mapping */ base_addr.as_uchar = 0; base_addr.by_field.addr9_2 = local_config[ func ].port1 >> 2; SMC37c669_write_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX, base_addr.as_uchar ); ret_val = TRUE; break; } case FLOPPY_0: { SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr; SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq; SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq; /* ** Enable the floppy controller DMA channel mapping */ drq.as_uchar = SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); drq.by_field.fdc_drq = SMC37c669_RAW_DEVICE_DRQ( SMC37c669_xlate_drq( local_config[ func ].drq ) ); SMC37c669_write_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX, drq.as_uchar ); /* ** Enable the floppy controller IRQ mapping */ irq.as_uchar = SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); irq.by_field.fdc_irq = SMC37c669_RAW_DEVICE_IRQ( SMC37c669_xlate_irq( local_config[ func ].irq ) ); SMC37c669_write_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX, irq.as_uchar ); /* ** Enable the floppy controller base address mapping */ base_addr.as_uchar = 0; base_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4; SMC37c669_write_config( SMC37c669_FDC_BASE_ADDRESS_INDEX, base_addr.as_uchar ); ret_val = TRUE; break; } case IDE_0: { SMC37c669_IDE_ADDRESS_REGISTER ide_addr; /* ** Enable the IDE alternate status base address mapping */ ide_addr.as_uchar = 0; ide_addr.by_field.addr9_4 = local_config[ func ].port2 >> 4; SMC37c669_write_config( SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX, ide_addr.as_uchar ); /* ** Enable the IDE controller base address mapping */ ide_addr.as_uchar = 0; ide_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4; SMC37c669_write_config( SMC37c669_IDE_BASE_ADDRESS_INDEX, ide_addr.as_uchar ); ret_val = TRUE; break; } } /* ** Exit configuration mode and return */ SMC37c669_config_mode( FALSE ); return ret_val; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function disables a device function within the ** SMC37c669 Super I/O controller. ** ** FORMAL PARAMETERS: ** ** func: ** Which function to disable ** ** RETURN VALUE: ** ** Return TRUE if the device function was disabled, otherwise, FALSE ** ** SIDE EFFECTS: ** ** {@description or none@} ** ** DESIGN: ** ** Disabling a function in the SMC37c669 device involves ** disabling all the function's mappings (port, irq, drq ...). ** A shadow copy of the device configuration is maintained ** in local storage so we won't worry aboving saving the ** current configuration information. ** **-- */ unsigned int __init SMC37c669_disable_device ( unsigned int func ) { unsigned int ret_val = FALSE; /* ** Put the device into configuration mode */ SMC37c669_config_mode( TRUE ); switch ( func ) { case SERIAL_0: { SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr; SMC37c669_SERIAL_IRQ_REGISTER irq; /* ** Disable the serial 1 IRQ mapping */ irq.as_uchar = SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); irq.by_field.uart1_irq = 0; SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar ); /* ** Disable the serial 1 port base address mapping */ base_addr.as_uchar = 0; SMC37c669_write_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX, base_addr.as_uchar ); ret_val = TRUE; break; } case SERIAL_1: { SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr; SMC37c669_SERIAL_IRQ_REGISTER irq; /* ** Disable the serial 2 IRQ mapping */ irq.as_uchar = SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); irq.by_field.uart2_irq = 0; SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar ); /* ** Disable the serial 2 port base address mapping */ base_addr.as_uchar = 0; SMC37c669_write_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX, base_addr.as_uchar ); ret_val = TRUE; break; } case PARALLEL_0: { SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr; SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq; SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq; /* ** Disable the parallel port DMA channel mapping */ drq.as_uchar = SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); drq.by_field.ppt_drq = 0; SMC37c669_write_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX, drq.as_uchar ); /* ** Disable the parallel port IRQ mapping */ irq.as_uchar = SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); irq.by_field.ppt_irq = 0; SMC37c669_write_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX, irq.as_uchar ); /* ** Disable the parallel port base address mapping */ base_addr.as_uchar = 0; SMC37c669_write_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX, base_addr.as_uchar ); ret_val = TRUE; break; } case FLOPPY_0: { SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr; SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq; SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq; /* ** Disable the floppy controller DMA channel mapping */ drq.as_uchar = SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); drq.by_field.fdc_drq = 0; SMC37c669_write_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX, drq.as_uchar ); /* ** Disable the floppy controller IRQ mapping */ irq.as_uchar = SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); irq.by_field.fdc_irq = 0; SMC37c669_write_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX, irq.as_uchar ); /* ** Disable the floppy controller base address mapping */ base_addr.as_uchar = 0; SMC37c669_write_config( SMC37c669_FDC_BASE_ADDRESS_INDEX, base_addr.as_uchar ); ret_val = TRUE; break; } case IDE_0: { SMC37c669_IDE_ADDRESS_REGISTER ide_addr; /* ** Disable the IDE alternate status base address mapping */ ide_addr.as_uchar = 0; SMC37c669_write_config( SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX, ide_addr.as_uchar ); /* ** Disable the IDE controller base address mapping */ ide_addr.as_uchar = 0; SMC37c669_write_config( SMC37c669_IDE_BASE_ADDRESS_INDEX, ide_addr.as_uchar ); ret_val = TRUE; break; } } /* ** Exit configuration mode and return */ SMC37c669_config_mode( FALSE ); return ret_val; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function configures a device function within the ** SMC37c669 Super I/O controller. ** ** FORMAL PARAMETERS: ** ** func: ** Which device function ** ** port: ** I/O port for the function to use ** ** irq: ** IRQ for the device function to use ** ** drq: ** DMA channel for the device function to use ** ** RETURN VALUE: ** ** Returns TRUE if the device function was configured, ** otherwise, FALSE. ** ** SIDE EFFECTS: ** ** {@description or none@} ** ** DESIGN: ** ** If this function returns TRUE, the local shadow copy of ** the configuration is also updated. If the device function ** is currently disabled, only the local shadow copy is ** updated and the actual device function will be updated ** if/when it is enabled. ** **-- */ unsigned int __init SMC37c669_configure_device ( unsigned int func, int port, int irq, int drq ) { struct DEVICE_CONFIG *cp; /* ** Check for a valid configuration */ if ( ( cp = SMC37c669_get_config ( func ) ) != NULL ) { /* ** Configuration is valid, update the local shadow copy */ if ( ( drq & ~0xFF ) == 0 ) { cp->drq = drq; } if ( ( irq & ~0xFF ) == 0 ) { cp->irq = irq; } if ( ( port & ~0xFFFF ) == 0 ) { cp->port1 = port; } /* ** If the device function is enabled, update the actual ** device configuration. */ if ( SMC37c669_is_device_enabled( func ) ) { SMC37c669_enable_device( func ); } return TRUE; } return FALSE; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function determines whether a device function ** within the SMC37c669 controller is enabled. ** ** FORMAL PARAMETERS: ** ** func: ** Which device function ** ** RETURN VALUE: ** ** Returns TRUE if the device function is enabled, otherwise, FALSE ** ** SIDE EFFECTS: ** ** {@description or none@} ** ** DESIGN: ** ** To check whether a device is enabled we will only look at ** the port base address mapping. According to the SMC37c669 ** specification, all of the port base address mappings are ** disabled if the addr<9:8> (bits <7:6> of the register) are ** zero. ** **-- */ static unsigned int __init SMC37c669_is_device_enabled ( unsigned int func ) { unsigned char base_addr = 0; unsigned int dev_ok = FALSE; unsigned int ret_val = FALSE; /* ** Enter configuration mode */ SMC37c669_config_mode( TRUE ); switch ( func ) { case SERIAL_0: base_addr = SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX ); dev_ok = TRUE; break; case SERIAL_1: base_addr = SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX ); dev_ok = TRUE; break; case PARALLEL_0: base_addr = SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX ); dev_ok = TRUE; break; case FLOPPY_0: base_addr = SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX ); dev_ok = TRUE; break; case IDE_0: base_addr = SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX ); dev_ok = TRUE; break; } /* ** If we have a valid device, check base_addr<7:6> to see if the ** device is enabled (mapped). */ if ( ( dev_ok ) && ( ( base_addr & 0xC0 ) != 0 ) ) { /* ** The mapping is not disabled, so assume that the function is ** enabled. */ ret_val = TRUE; } /* ** Exit configuration mode */ SMC37c669_config_mode( FALSE ); return ret_val; } #if 0 /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function retrieves the configuration information of a ** device function within the SMC37c699 Super I/O controller. ** ** FORMAL PARAMETERS: ** ** func: ** Which device function ** ** port: ** I/O port returned ** ** irq: ** IRQ returned ** ** drq: ** DMA channel returned ** ** RETURN VALUE: ** ** Returns TRUE if the device configuration was successfully ** retrieved, otherwise, FALSE. ** ** SIDE EFFECTS: ** ** The data pointed to by the port, irq, and drq parameters ** my be modified even if the configuration is not successfully ** retrieved. ** ** DESIGN: ** ** The device configuration is fetched from the local shadow ** copy. Any unused parameters will be set to -1. Any ** parameter which is not desired can specify the NULL ** pointer. ** **-- */ static unsigned int __init SMC37c669_get_device_config ( unsigned int func, int *port, int *irq, int *drq ) { struct DEVICE_CONFIG *cp; unsigned int ret_val = FALSE; /* ** Check for a valid device configuration */ if ( ( cp = SMC37c669_get_config( func ) ) != NULL ) { if ( drq != NULL ) { *drq = cp->drq; ret_val = TRUE; } if ( irq != NULL ) { *irq = cp->irq; ret_val = TRUE; } if ( port != NULL ) { *port = cp->port1; ret_val = TRUE; } } return ret_val; } #endif /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function displays the current state of the SMC37c699 ** Super I/O controller's device functions. ** ** FORMAL PARAMETERS: ** ** None ** ** RETURN VALUE: ** ** None ** ** SIDE EFFECTS: ** ** None ** **-- */ void __init SMC37c669_display_device_info ( void ) { if ( SMC37c669_is_device_enabled( SERIAL_0 ) ) { printk( " Serial 0: Enabled [ Port 0x%x, IRQ %d ]\n", local_config[ SERIAL_0 ].port1, local_config[ SERIAL_0 ].irq ); } else { printk( " Serial 0: Disabled\n" ); } if ( SMC37c669_is_device_enabled( SERIAL_1 ) ) { printk( " Serial 1: Enabled [ Port 0x%x, IRQ %d ]\n", local_config[ SERIAL_1 ].port1, local_config[ SERIAL_1 ].irq ); } else { printk( " Serial 1: Disabled\n" ); } if ( SMC37c669_is_device_enabled( PARALLEL_0 ) ) { printk( " Parallel: Enabled [ Port 0x%x, IRQ %d/%d ]\n", local_config[ PARALLEL_0 ].port1, local_config[ PARALLEL_0 ].irq, local_config[ PARALLEL_0 ].drq ); } else { printk( " Parallel: Disabled\n" ); } if ( SMC37c669_is_device_enabled( FLOPPY_0 ) ) { printk( " Floppy Ctrl: Enabled [ Port 0x%x, IRQ %d/%d ]\n", local_config[ FLOPPY_0 ].port1, local_config[ FLOPPY_0 ].irq, local_config[ FLOPPY_0 ].drq ); } else { printk( " Floppy Ctrl: Disabled\n" ); } if ( SMC37c669_is_device_enabled( IDE_0 ) ) { printk( " IDE 0: Enabled [ Port 0x%x, IRQ %d ]\n", local_config[ IDE_0 ].port1, local_config[ IDE_0 ].irq ); } else { printk( " IDE 0: Disabled\n" ); } } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function puts the SMC37c669 Super I/O controller into, ** and takes it out of, configuration mode. ** ** FORMAL PARAMETERS: ** ** enable: ** TRUE to enter configuration mode, FALSE to exit. ** ** RETURN VALUE: ** ** None ** ** SIDE EFFECTS: ** ** The SMC37c669 controller may be left in configuration mode. ** **-- */ static void __init SMC37c669_config_mode( unsigned int enable ) { if ( enable ) { /* ** To enter configuration mode, two writes in succession to the index ** port are required. If a write to another address or port occurs ** between these two writes, the chip does not enter configuration ** mode. Therefore, a spinlock is placed around the two writes to ** guarantee that they complete uninterrupted. */ spin_lock(&smc_lock); wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY ); wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY ); spin_unlock(&smc_lock); } else { wb( &SMC37c669->index_port, SMC37c669_CONFIG_OFF_KEY ); } } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function reads an SMC37c669 Super I/O controller ** configuration register. This function assumes that the ** device is already in configuration mode. ** ** FORMAL PARAMETERS: ** ** index: ** Index value of configuration register to read ** ** RETURN VALUE: ** ** Data read from configuration register ** ** SIDE EFFECTS: ** ** None ** **-- */ static unsigned char __init SMC37c669_read_config( unsigned char index ) { wb(&SMC37c669->index_port, index); return rb(&SMC37c669->data_port); } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function writes an SMC37c669 Super I/O controller ** configuration register. This function assumes that the ** device is already in configuration mode. ** ** FORMAL PARAMETERS: ** ** index: ** Index of configuration register to write ** ** data: ** Data to be written ** ** RETURN VALUE: ** ** None ** ** SIDE EFFECTS: ** ** None ** **-- */ static void __init SMC37c669_write_config( unsigned char index, unsigned char data ) { wb( &SMC37c669->index_port, index ); wb( &SMC37c669->data_port, data ); } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function initializes the local device ** configuration storage. This function assumes ** that the device is already in configuration ** mode. ** ** FORMAL PARAMETERS: ** ** None ** ** RETURN VALUE: ** ** None ** ** SIDE EFFECTS: ** ** Local storage for device configuration information ** is initialized. ** **-- */ static void __init SMC37c669_init_local_config ( void ) { SMC37c669_SERIAL_BASE_ADDRESS_REGISTER uart_base; SMC37c669_SERIAL_IRQ_REGISTER uart_irqs; SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER ppt_base; SMC37c669_PARALLEL_FDC_IRQ_REGISTER ppt_fdc_irqs; SMC37c669_PARALLEL_FDC_DRQ_REGISTER ppt_fdc_drqs; SMC37c669_FDC_BASE_ADDRESS_REGISTER fdc_base; SMC37c669_IDE_ADDRESS_REGISTER ide_base; SMC37c669_IDE_ADDRESS_REGISTER ide_alt; /* ** Get serial port 1 base address */ uart_base.as_uchar = SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX ); /* ** Get IRQs for serial ports 1 & 2 */ uart_irqs.as_uchar = SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); /* ** Store local configuration information for serial port 1 */ local_config[SERIAL_0].port1 = uart_base.by_field.addr9_3 << 3; local_config[SERIAL_0].irq = SMC37c669_xlate_irq( SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart1_irq ) ); /* ** Get serial port 2 base address */ uart_base.as_uchar = SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX ); /* ** Store local configuration information for serial port 2 */ local_config[SERIAL_1].port1 = uart_base.by_field.addr9_3 << 3; local_config[SERIAL_1].irq = SMC37c669_xlate_irq( SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart2_irq ) ); /* ** Get parallel port base address */ ppt_base.as_uchar = SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX ); /* ** Get IRQs for parallel port and floppy controller */ ppt_fdc_irqs.as_uchar = SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); /* ** Get DRQs for parallel port and floppy controller */ ppt_fdc_drqs.as_uchar = SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); /* ** Store local configuration information for parallel port */ local_config[PARALLEL_0].port1 = ppt_base.by_field.addr9_2 << 2; local_config[PARALLEL_0].irq = SMC37c669_xlate_irq( SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.ppt_irq ) ); local_config[PARALLEL_0].drq = SMC37c669_xlate_drq( SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.ppt_drq ) ); /* ** Get floppy controller base address */ fdc_base.as_uchar = SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX ); /* ** Store local configuration information for floppy controller */ local_config[FLOPPY_0].port1 = fdc_base.by_field.addr9_4 << 4; local_config[FLOPPY_0].irq = SMC37c669_xlate_irq( SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.fdc_irq ) ); local_config[FLOPPY_0].drq = SMC37c669_xlate_drq( SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.fdc_drq ) ); /* ** Get IDE controller base address */ ide_base.as_uchar = SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX ); /* ** Get IDE alternate status base address */ ide_alt.as_uchar = SMC37c669_read_config( SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX ); /* ** Store local configuration information for IDE controller */ local_config[IDE_0].port1 = ide_base.by_field.addr9_4 << 4; local_config[IDE_0].port2 = ide_alt.by_field.addr9_4 << 4; local_config[IDE_0].irq = 14; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function returns a pointer to the local shadow ** configuration of the requested device function. ** ** FORMAL PARAMETERS: ** ** func: ** Which device function ** ** RETURN VALUE: ** ** Returns a pointer to the DEVICE_CONFIG structure for the ** requested function, otherwise, NULL. ** ** SIDE EFFECTS: ** ** {@description or none@} ** **-- */ static struct DEVICE_CONFIG * __init SMC37c669_get_config( unsigned int func ) { struct DEVICE_CONFIG *cp = NULL; switch ( func ) { case SERIAL_0: cp = &local_config[ SERIAL_0 ]; break; case SERIAL_1: cp = &local_config[ SERIAL_1 ]; break; case PARALLEL_0: cp = &local_config[ PARALLEL_0 ]; break; case FLOPPY_0: cp = &local_config[ FLOPPY_0 ]; break; case IDE_0: cp = &local_config[ IDE_0 ]; break; } return cp; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function translates IRQs back and forth between ISA ** IRQs and SMC37c669 device IRQs. ** ** FORMAL PARAMETERS: ** ** irq: ** The IRQ to translate ** ** RETURN VALUE: ** ** Returns the translated IRQ, otherwise, returns -1. ** ** SIDE EFFECTS: ** ** {@description or none@} ** **-- */ static int __init SMC37c669_xlate_irq ( int irq ) { int i, translated_irq = -1; if ( SMC37c669_IS_DEVICE_IRQ( irq ) ) { /* ** We are translating a device IRQ to an ISA IRQ */ for ( i = 0; ( SMC37c669_irq_table[i].device_irq != -1 ) || ( SMC37c669_irq_table[i].isa_irq != -1 ); i++ ) { if ( irq == SMC37c669_irq_table[i].device_irq ) { translated_irq = SMC37c669_irq_table[i].isa_irq; break; } } } else { /* ** We are translating an ISA IRQ to a device IRQ */ for ( i = 0; ( SMC37c669_irq_table[i].isa_irq != -1 ) || ( SMC37c669_irq_table[i].device_irq != -1 ); i++ ) { if ( irq == SMC37c669_irq_table[i].isa_irq ) { translated_irq = SMC37c669_irq_table[i].device_irq; break; } } } return translated_irq; } /* **++ ** FUNCTIONAL DESCRIPTION: ** ** This function translates DMA channels back and forth between ** ISA DMA channels and SMC37c669 device DMA channels. ** ** FORMAL PARAMETERS: ** ** drq: ** The DMA channel to translate ** ** RETURN VALUE: ** ** Returns the translated DMA channel, otherwise, returns -1 ** ** SIDE EFFECTS: ** ** {@description or none@} ** **-- */ static int __init SMC37c669_xlate_drq ( int drq ) { int i, translated_drq = -1; if ( SMC37c669_IS_DEVICE_DRQ( drq ) ) { /* ** We are translating a device DMA channel to an ISA DMA channel */ for ( i = 0; ( SMC37c669_drq_table[i].device_drq != -1 ) || ( SMC37c669_drq_table[i].isa_drq != -1 ); i++ ) { if ( drq == SMC37c669_drq_table[i].device_drq ) { translated_drq = SMC37c669_drq_table[i].isa_drq; break; } } } else { /* ** We are translating an ISA DMA channel to a device DMA channel */ for ( i = 0; ( SMC37c669_drq_table[i].isa_drq != -1 ) || ( SMC37c669_drq_table[i].device_drq != -1 ); i++ ) { if ( drq == SMC37c669_drq_table[i].isa_drq ) { translated_drq = SMC37c669_drq_table[i].device_drq; break; } } } return translated_drq; } #if 0 int __init smcc669_init ( void ) { struct INODE *ip; allocinode( smc_ddb.name, 1, &ip ); ip->dva = &smc_ddb; ip->attr = ATTR$M_WRITE | ATTR$M_READ; ip->len[0] = 0x30; ip->misc = 0; INODE_UNLOCK( ip ); return msg_success; } int __init smcc669_open( struct FILE *fp, char *info, char *next, char *mode ) { struct INODE *ip; /* ** Allow multiple readers but only one writer. ip->misc keeps track ** of the number of writers */ ip = fp->ip; INODE_LOCK( ip ); if ( fp->mode & ATTR$M_WRITE ) { if ( ip->misc ) { INODE_UNLOCK( ip ); return msg_failure; /* too many writers */ } ip->misc++; } /* ** Treat the information field as a byte offset */ *fp->offset = xtoi( info ); INODE_UNLOCK( ip ); return msg_success; } int __init smcc669_close( struct FILE *fp ) { struct INODE *ip; ip = fp->ip; if ( fp->mode & ATTR$M_WRITE ) { INODE_LOCK( ip ); ip->misc--; INODE_UNLOCK( ip ); } return msg_success; } int __init smcc669_read( struct FILE *fp, int size, int number, unsigned char *buf ) { int i; int length; int nbytes; struct INODE *ip; /* ** Always access a byte at a time */ ip = fp->ip; length = size * number; nbytes = 0; SMC37c669_config_mode( TRUE ); for ( i = 0; i < length; i++ ) { if ( !inrange( *fp->offset, 0, ip->len[0] ) ) break; *buf++ = SMC37c669_read_config( *fp->offset ); *fp->offset += 1; nbytes++; } SMC37c669_config_mode( FALSE ); return nbytes; } int __init smcc669_write( struct FILE *fp, int size, int number, unsigned char *buf ) { int i; int length; int nbytes; struct INODE *ip; /* ** Always access a byte at a time */ ip = fp->ip; length = size * number; nbytes = 0; SMC37c669_config_mode( TRUE ); for ( i = 0; i < length; i++ ) { if ( !inrange( *fp->offset, 0, ip->len[0] ) ) break; SMC37c669_write_config( *fp->offset, *buf ); *fp->offset += 1; buf++; nbytes++; } SMC37c669_config_mode( FALSE ); return nbytes; } #endif #if SMC_DEBUG static void __init SMC37c669_dump_registers(void) { int i; for (i = 0; i <= 0x29; i++) printk("-- CR%02x : %02x\n", i, SMC37c669_read_config(i)); } #endif /*+ * ============================================================================ * = SMC_init - SMC37c669 Super I/O controller initialization = * ============================================================================ * * OVERVIEW: * * This routine configures and enables device functions on the * SMC37c669 Super I/O controller. * * FORM OF CALL: * * SMC_init( ); * * RETURNS: * * Nothing * * ARGUMENTS: * * None * * SIDE EFFECTS: * * None * */ void __init SMC669_Init ( int index ) { SMC37c669_CONFIG_REGS *SMC_base; unsigned long flags; local_irq_save(flags); if ( ( SMC_base = SMC37c669_detect( index ) ) != NULL ) { #if SMC_DEBUG SMC37c669_config_mode( TRUE ); SMC37c669_dump_registers( ); SMC37c669_config_mode( FALSE ); SMC37c669_display_device_info( ); #endif SMC37c669_disable_device( SERIAL_0 ); SMC37c669_configure_device( SERIAL_0, COM1_BASE, COM1_IRQ, -1 ); SMC37c669_enable_device( SERIAL_0 ); SMC37c669_disable_device( SERIAL_1 ); SMC37c669_configure_device( SERIAL_1, COM2_BASE, COM2_IRQ, -1 ); SMC37c669_enable_device( SERIAL_1 ); SMC37c669_disable_device( PARALLEL_0 ); SMC37c669_configure_device( PARALLEL_0, PARP_BASE, PARP_IRQ, PARP_DRQ ); SMC37c669_enable_device( PARALLEL_0 ); SMC37c669_disable_device( FLOPPY_0 ); SMC37c669_configure_device( FLOPPY_0, FDC_BASE, FDC_IRQ, FDC_DRQ ); SMC37c669_enable_device( FLOPPY_0 ); /* Wake up sometimes forgotten floppy, especially on DP264. */ outb(0xc, 0x3f2); SMC37c669_disable_device( IDE_0 ); #if SMC_DEBUG SMC37c669_config_mode( TRUE ); SMC37c669_dump_registers( ); SMC37c669_config_mode( FALSE ); SMC37c669_display_device_info( ); #endif local_irq_restore(flags); printk( "SMC37c669 Super I/O Controller found @ 0x%p\n", SMC_base ); } else { local_irq_restore(flags); #if SMC_DEBUG printk( "No SMC37c669 Super I/O Controller found\n" ); #endif } }
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1