diff -u --recursive --new-file v2.1.115/linux/CREDITS linux/CREDITS --- v2.1.115/linux/CREDITS Thu Aug 6 14:06:27 1998 +++ linux/CREDITS Sun Aug 9 12:09:05 1998 @@ -706,8 +706,8 @@ E: rth@cygnus.com E: richard@gnu.org D: Alpha/ELF, gcc, binutils, and glibc -S: 5450 Mayme #25 -S: San Jose, California 95129 +S: 50 E. Middlefield #10 +S: Mountain View, California 94043-3822 S: USA N: Sebastian Hetze diff -u --recursive --new-file v2.1.115/linux/Documentation/devices.tex linux/Documentation/devices.tex --- v2.1.115/linux/Documentation/devices.tex Thu Aug 6 14:06:28 1998 +++ linux/Documentation/devices.tex Sun Aug 16 11:35:51 1998 @@ -1,5 +1,5 @@ \documentstyle{article} -% $Id: devices.tex,v 1.12 1998/08/06 04:52:01 hpa Exp $ +% $Id: devices.tex,v 1.14 1998/08/10 22:39:24 hpa Exp $ % --------------------------------------------------------------------------- % Adopt somewhat reasonable margins, so it doesn't take a million % pages to print... :-) If you're actually putting this in print, you @@ -48,7 +48,7 @@ % \title{{\bf Linux Allocated Devices}} \author{Maintained by H. Peter Anvin $<$hpa@zytor.com$>$} -\date{Last revised: August 5, 1998} +\date{Last revised: August 10, 1998} \maketitle % \noindent @@ -246,7 +246,7 @@ \major{78}{}{char }{PAM Software's multimodem boards} \major{79}{}{char }{PAM Software's multimodem boards -- alternate devices} \major{80}{}{char }{Photometrics AT200 CCD camera} -\major{81}{}{char }{Brooktree Bt848 frame grabbers} +\major{81}{}{char }{video4linux} \major{82}{}{char }{WiNRADiO communications receiver card} \major{83}{}{char }{Teletext/videotext interfaces} \major{84}{}{char }{Ikon 1011[57] Versatec Greensheet Interface} @@ -275,7 +275,8 @@ \major{107}{}{char }{3Dfx Voodoo Graphics device} \major{108}{}{char }{Device independent PPP interface} \major{109}{}{char }{Reserved for logical volume manager} -\major{110}{--119}{}{Unallocated} +\major{110}{}{char }{miroMEDIA Surround board} +\major{111}{--119}{}{Unallocated} \major{120}{--127}{}{Local/experimental use} \major{128}{--135}{char }{Unix98 PTY masters} \major{136}{--143}{char }{Unix98 PTY slaves} @@ -438,19 +439,18 @@ \minor{64}{/dev/ttyS0}{First serial port} \minordots \minor{127}{/dev/ttyS63}{64th serial port} - \minor{128}{/dev/ptyp0}{First old pseudo-tty master} + \minor{128}{/dev/ptyp0}{OBSOLETE} \minordots - \minor{191}{/dev/ptysf}{64th old pseudo-tty master} - \minor{192}{/dev/ttyp0}{First old pseudo-tty slave} + \minor{191}{/dev/ptysf}{OBSOLETE} + \minor{192}{/dev/ttyp0}{OBSOLETE} \minordots - \minor{255}{/dev/ttysf}{64th old pseudo-tty slave} + \minor{255}{/dev/ttysf}{OBSOLETE} \end{devicelist} \noindent -For compatibility with previous versions of Linux, the first 64 PTYs -are replicated under this device number. This use is deprecated with -the release of Linux 2.0 and may be removed in a future version of -Linux. To ensure proper operation, do not mix old and new PTY devices. +Older versions of the Linux kernel used this major number for BSD PTY +devices. As of Linux 2.1.115, this is no longer supported. Use major +numbers 2 and 3. \begin{devicelist} \major{ 5}{}{char }{Alternate TTY devices} @@ -583,9 +583,6 @@ \minor{133}{/dev/exttrp}{External device trap} \minor{134}{/dev/apm\_bios}{Advanced Power Management BIOS} \minor{135}{/dev/rtc}{Real Time Clock} - \minor{136}{/dev/qcam0}{QuickCam on {\file lp0}} - \minor{137}{/dev/qcam1}{QuickCam on {\file lp1}} - \minor{138}{/dev/qcam2}{QuickCam on {\file lp2}} \minor{139}{/dev/openprom}{SPARC OpenBoot PROM} \minor{140}{/dev/relay8}{Berkshire Products Octal relay card} \minor{141}{/dev/relay16}{Berkshire Products ISO-16 relay card} @@ -599,8 +596,8 @@ \minor{149}{/dev/input/mouse}{Linux/SGI Irix emulation mouse} \minor{150}{/dev/input/keyboard}{Linux/SGI Irix emulation keyboard} \minor{151}{/dev/led}{Front panel LEDs} - \minor{152}{/dev/radio}{Radio card (type?)} \minor{153}{/dev/mergemem}{Memory merge device} + \minor{154}{/dev/pmu}{Macintosh PowerBook power manager} \end{devicelist} \begin{devicelist} @@ -1677,16 +1674,19 @@ \end{devicelist} \begin{devicelist} -\major{81}{}{char }{Brooktree Bt848 frame grabbers} - \minor{0}{/dev/bttv0}{First Bt848 card} - \minor{0}{/dev/bttv1}{Second Bt848 card} - \minordots - \minor{16}{/dev/bttvc0}{Control for first Bt848 card} - \minor{17}{/dev/bttvc1}{Control for second Bt848 card} - \minordots - \minor{32}{/dev/bttv-vbi0}{VBI data of first Bt848 card} - \minor{33}{/dev/bttv-vbi1}{VBI data of second Bt848 card} - \minordots +\major{81}{}{char }{video4linux} + \minor{0}{/dev/video0}{Video capture/overlay device} + \minordots + \minor{63}{/dev/video63}{Video capture/overlay device} + \minor{64}{/dev/radio0}{Radio device} + \minordots + \minor{127}{/dev/radio63}{Radio device} + \minor{192}{/dev/vtx0}{Teletext device} + \minordots + \minor{223}{/dev/vtx31}{Teletext device} + \minor{224}{/dev/vbi0}{Vertical blank interupt} + \minordots + \minor{255}{/dev/vbi31}{Vertical blank interupt} \end{devicelist} \begin{devicelist} @@ -1910,7 +1910,14 @@ \end{devicelist} \begin{devicelist} -\major{110}{--119}{}{Unallocated} +\major{110}{}{char }{miroMEDIA Surround board} + \minor{0}{/dev/srnd0}{First miroMEDIA Surround board} + \minor{1}{/dev/srnd1}{First miroMEDIA Surround board} + \minordots +\end{devicelist} + +\begin{devicelist} +\major{111}{--119}{}{Unallocated} \end{devicelist} \begin{devicelist} @@ -1989,6 +1996,8 @@ \link{/dev/core}{/proc/kcore}{symbolic}{Backward compatibility} \link{/dev/ramdisk}{ram0}{symbolic}{Backward compatibility} \link{/dev/ftape}{qft0}{symbolic}{Backward compatibility} +\link{/dev/bttv0}{video0}{symbolic}{Backward compatibility} +\link{/dev/radio}{radio0}{symbolic}{Backward compatibility} \link{/dev/scd?}{sr?}{hard}{Alternate name for CD-ROMs} \end{nodelist} diff -u --recursive --new-file v2.1.115/linux/Documentation/devices.txt linux/Documentation/devices.txt --- v2.1.115/linux/Documentation/devices.txt Thu Aug 6 14:06:28 1998 +++ linux/Documentation/devices.txt Sun Aug 16 11:35:51 1998 @@ -1,7 +1,7 @@ LINUX ALLOCATED DEVICES Maintained by H. Peter Anvin - Last revised: August 5, 1998 + Last revised: August 10, 1998 This list is the Linux Device List, the official registry of allocated device numbers and /dev directory nodes for the Linux operating @@ -184,19 +184,16 @@ 64 = /dev/ttyS0 First serial port ... 127 = /dev/ttyS63 64th serial port - 128 = /dev/ptyp0 First old pseudo-tty master + 128 = /dev/ptyp0 OBSOLETE ... - 191 = /dev/ptysf 64th old pseudo-tty master - 192 = /dev/ttyp0 First old pseudo-tty slave + 191 = /dev/ptysf OBSOLETE + 192 = /dev/ttyp0 OBSOLETE ... - 255 = /dev/ttysf 64th old pseudo-tty slave + 255 = /dev/ttysf OBSOLETE - For compatibility with previous versions of Linux, the - first 64 PTYs are replicated under this device number. - This use is deprecated with the release of Linux 2.0 - and may be removed in a future version of Linux. To - ensure proper operation, do not mix old and new PTY - devices. + Older versions of the Linux kernel used this major + number for BSD PTY devices. As of Linux 2.1.115, this + is no longer supported. Use major numbers 2 and 3. 5 char Alternate TTY devices 0 = /dev/tty Current TTY device @@ -310,9 +307,6 @@ 133 = /dev/exttrp External device trap 134 = /dev/apm_bios Advanced Power Management BIOS 135 = /dev/rtc Real Time Clock - 136 = /dev/qcam0 QuickCam on lp0 - 137 = /dev/qcam1 QuickCam on lp1 - 138 = /dev/qcam2 QuickCam on lp2 139 = /dev/openprom SPARC OpenBoot PROM 140 = /dev/relay8 Berkshire Products Octal relay card 141 = /dev/relay16 Berkshire Products ISO-16 relay card @@ -326,8 +320,8 @@ 149 = /dev/input/mouse Linux/SGI Irix emulation mouse 150 = /dev/input/keyboard Linux/SGI Irix emulation keyboard 151 = /dev/led Front panel LEDs - 152 = /dev/radio Radio card (type?) 153 = /dev/mergemem Memory merge device + 154 = /dev/pmu Macintosh PowerBook power manager 11 char Raw keyboard device 0 = /dev/kbd Raw keyboard device @@ -1163,16 +1157,19 @@ 80 char Photometrics AT200 CCD camera 0 = /dev/at200 Photometrics AT200 CCD camera - 81 char Brooktree Bt848 frame grabbers - 0 = /dev/bttv0 First Bt848 card - 1 = /dev/bttv1 Second Bt848 card + 81 char video4linux + 0 = /dev/video0 Video capture/overlay device + ... + 63 = /dev/video63 Video capture/overlay device + 64 = /dev/radio0 Radio device ... - 16 = /dev/bttvc0 Control for first Bt848 card - 17 = /dev/bttvc1 Control for second Bt848 card + 127 = /dev/radio63 Radio device + 192 = /dev/vtx0 Teletext device ... - 32 = /dev/bttv-vbi0 VBI data of first Bt848 card - 33 = /dev/bttv-vbi1 VBI data of second Bt848 card + 223 = /dev/vtx31 Teletext device + 224 = /dev/vbi0 Vertical blank interrupt ... + 255 = /dev/vbi31 Vertical blank interrupt 82 char WiNRADiO communications receiver card 0 = /dev/winradio0 First WiNRADiO card @@ -1330,7 +1327,12 @@ 109 char Reserved for logical volume manager -108-119 UNALLOCATED +110 char miroMEDIA Surround board + 0 = /dev/srnd0 First miroMEDIA Surround board + 1 = /dev/srnd1 Second miroMEDIA Surround board + ... + +111-119 UNALLOCATED 120-127 LOCAL/EXPERIMENTAL USE @@ -1388,6 +1390,8 @@ /dev/core /proc/kcore symbolic Backward compatibility /dev/ramdisk ram0 symbolic Backward compatibility /dev/ftape qft0 symbolic Backward compatibility +/dev/bttv0 video0 symbolic Backward compatibility +/dev/radio radio0 symbolic Backward compatibility /dev/scd? sr? hard Alternate SCSI CD-ROM name Locally defined links diff -u --recursive --new-file v2.1.115/linux/Documentation/magic-number.txt linux/Documentation/magic-number.txt --- v2.1.115/linux/Documentation/magic-number.txt Tue Sep 23 19:17:35 1997 +++ linux/Documentation/magic-number.txt Sun Aug 9 12:15:49 1998 @@ -26,7 +26,7 @@ discipline, these cases get detected quickly and safely. Theodore Ts'o - 31-Mar-94 + 31 Mar 94 The magic table is current to Linux 2.1.55. @@ -34,42 +34,65 @@ 22 Sep 1997 +Now it should be up to date with Linux 2.1.112. Because +we are in feature freeze time it is very unlikely that +something will change before 2.2.x. The entries are +sorted by number field. + + Krzysztof G. Baranowski + + 29 Jul 1998 - -Magic Name Number Structure File +Magic Name Number Structure File =========================================================================== - +PG_MAGIC 'P' pg_{read,write}_hdr include/linux/pg.h MKISS_DRIVER_MAGIC 0x04bf mkiss_channel drivers/net/mkiss.h RISCOM8_MAGIC 0x0907 riscom_port drivers/char/riscom8.h APM_BIOS_MAGIC 0x4101 apm_bios_struct include/linux/apm_bios.h CYCLADES_MAGIC 0x4359 cyclades_port include/linux/cyclades.h FASYNC_MAGIC 0x4601 fasync_struct include/linux/fs.h +PTY_MAGIC 0x5001 (none at the moment) + drivers/char/pty.c PPP_MAGIC 0x5002 ppp include/linux/if_ppp.h SERIAL_MAGIC 0x5301 async_struct include/linux/serial.h SSTATE_MAGIC 0x5302 serial_state include/linux/serial.h SLIP_MAGIC 0x5302 slip drivers/net/slip.h STRIP_MAGIC 0x5303 strip drivers/net/strip.c X25_ASY_MAGIC 0x5303 x25_asy drivers/net/x25_asy.h +SIXPACK_MAGIC 0x5304 sixpack drivers/net/hamradio/6pack.h AX25_MAGIC 0x5316 ax_disp drivers/net/mkiss.h ESP_MAGIC 0x53ee esp_struct drivers/char/esp.h TTY_MAGIC 0x5401 tty_struct include/linux/tty.h TTY_DRIVER_MAGIC 0x5402 tty_driver include/linux/tty_driver.h TTY_LDISC_MAGIC 0x5403 tty_ldisc include/linux/tty_ldisc.h SCC_MAGIC 0x8530 scc_channel include/linux/scc.h +SPECIALIX_MAGIC 0x0907 specialix_port drivers/char/specialix_io8.h +CG_MAGIC 0x090255 ufs_cylinder_group include/linux/ufs_fs.h RPORT_MAGIC 0x525001 r_port drivers/char/rocket_int.h -SLAB_C_MAGIC 0x4f17a36d kmem_cache_s mm/slab.c +GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str drivers/scsi/gdth_ioctl.h +NBD_REQUEST_MAGIC 0x12560953 nbd_request include/linux/nbd.h SLAB_RED_MAGIC2 0x170fc2a5 (any) mm/slab.c +BAYCOM_MAGIC 0x19730510 baycom_state drivers/net/baycom_epp.c +ISDN_X25IFACE_MAGIC 0x1e75a2b9 isdn_x25iface_proto_data + drivers/isdn/isdn_x25iface.h ECP_MAGIC 0x21504345 cdkecpsig include/linux/cdk.h +LSMAGIC 0x2a3b4d2a ls drivers/fc4/fc.c +LSOMAGIC 0x2a3c4e3c lso drivers/fc4/fc.c +WANPIPE_MAGIC 0x414C4453 sdla_{dump,exec} include/linux/wanpipe.h +CODA_CNODE_MAGIC 0x47114711 coda_inode_info include/linux/coda_fs_i.h ISDN_ASYNC_MAGIC 0x49344C01 modem_info include/linux/isdn.h ISDN_NET_MAGIC 0x49344C02 isdn_net_local_s include/linux/isdn.h STLI_BOARDMAGIC 0x4bc6c825 stlibrd include/linux/istallion.h +SLAB_C_MAGIC 0x4f17a36d kmem_cache_s mm/slab.c ROUTER_MAGIC 0x524d4157 wan_device include/linux/wanrouter.h SLAB_RED_MAGIC1 0x5a2cf071 (any) mm/slab.c STL_PORTMAGIC 0x5a7182c9 stlport include/linux/stallion.h HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state include/linux/hdlcdrv.h -EPCA_MAGIC 0x5c6df104 channel include/linux/epca.h +EPCA_MAGIC 0x5c6df104 channel include/linux/epca.h PCXX_MAGIC 0x5c6df104 channel drivers/char/pcxx.h +LO_MAGIC 0x68797548 nbd_device include/linux/nbd.h STL_PANELMAGIC 0x7ef621a1 stlpanel include/linux/stallion.h +NBD_REPLY_MAGIC 0x96744668 nbd_reply include/linux/nbd.h STL_BOARDMAGIC 0xa2267f52 stlbrd include/linux/stallion.h SLAB_MAGIC_ALLOC 0xa5c32f2b kmem_slab_s mm/slab.c SLAB_MAGIC_DESTROYED 0xb2f23c5a kmem_slab_s mm/slab.c diff -u --recursive --new-file v2.1.115/linux/Documentation/radiotrack.txt linux/Documentation/radiotrack.txt --- v2.1.115/linux/Documentation/radiotrack.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/radiotrack.txt Sun Aug 9 12:15:49 1998 @@ -0,0 +1,147 @@ +NOTES ON RADIOTRACK CARD CONTROL +by Stephen M. Benoit (benoits@servicepro.com) Dec 14, 1996 +---------------------------------------------------------------------------- + +Document version 1.0 + +ACKNOWLEDGMENTS +---------------- +This document was made based on 'C' code for Linux from Gideon le Grange +(legrang@active.co.za or legrang@cs.sun.ac.za) in 1994, and elaborations from +Frans Brinkman (brinkman@esd.nl) in 1996. The results reported here are from +experiments that the author performed on his own setup, so your mileage may +vary... I make no guarantees, claims or warrantees to the suitability or +validity of this information. No other documentation on the AIMS +Lab (http://www.aimslab.com/) RadioTrack card was made available to the +author. This document is offered in the hopes that it might help users who +want to use the RadioTrack card in an environment other than MS Windows. + +WHY THIS DOCUMENT? +------------------ +I have a RadioTrack card from back when I ran an MS-Windows platform. After +converting to Linux, I found Gideon le Grange's command-line software for +running the card, and found that it was good! Frans Brinkman made a +comfortable X-windows interface, and added a scanning feature. For hack +value, I wanted to see if the tuner could be tuned beyond the usual FM radio +broadcast band, so I could pick up the audio carriers from North American +broadcast TV channels, situated just below and above the 87.0-109.0 MHz range. +I did not get much success, but I learned about programming ioports under +Linux and gained some insights about the hardware design used for the card. + +So, without further delay, here are the details. + + +PHYSICAL DESCRIPTION +-------------------- +The RadioTrack card is an ISA 8-bit FM radio card. The radio frequency (RF) +input is simply an antenna lead, and the output is a power audio signal +available through a miniature phono plug. Its RF frequencies of operation are +more or less limited from 87.0 to 109.0 MHz (the commercial FM broadcast +band). Although the registers can be programmed to request frequencies beyond +these limits, experiments did not give promising results. The variable +frequency oscillator (VFO) that demodulates the intermediate frequency (IF) +signal probably has a small range of useful frequencies, and wraps around or +gets clipped beyond the limits mentioned above. + + +CONTROLLING THE CARD WITH IOPORT +-------------------------------- +The RadioTrack (base) ioport is configurable for 0x30c or 0x20c. Only one +ioport seems to be involved. The ioport decoding circuitry must be pretty +simple, as individual ioport bits are directly matched to specific functions +(or blocks) of the radio card. This way, many functions can be changed in +parallel with one write to the ioport. The only feedback available through +the ioports appears to be the "Stereo Detect" bit. + +The bits of the ioport are arranged as follows: + + MSb LSb ++------+------+------+--------+--------+-------+---------+--------+ +| VolA | VolB | ???? | Stereo | Radio | TuneA | TuneB | Tune | +| (+) | (-) | | Detect | Audio | (bit) | (latch) | Update | +| | | | Enable | Enable | | | Enable | ++------+------+------+--------+--------+-------+---------+--------+ + + +VolA . VolB [AB......] +----------- +0 0 : audio mute +0 1 : volume + (some delay required) +1 0 : volume - (some delay required) +1 1 : stay at present volume + +Stereo Detect Enable [...S....] +-------------------- +0 : No Detect +1 : Detect + + Results available by reading ioport >60 msec after last port write. + 0xff ==> no stereo detected, 0xfd ==> stereo detected. + +Radio to Audio (path) Enable [....R...] +---------------------------- +0 : Disable path (silence) +1 : Enable path (audio produced) + +TuneA . TuneB [.....AB.] +------------- +0 0 : "zero" bit phase 1 +0 1 : "zero" bit phase 2 + +1 0 : "one" bit phase 1 +1 1 : "one" bit phase 2 + + 24-bit code, where bits = (freq*40) + 10486188. + The Most Significant 11 bits must be 1010 xxxx 0x0 to be valid. + The bits are shifted in LSb first. + +Tune Update Enable [.......T] +------------------ +0 : Tuner held constant +1 : Tuner updating in progress + + +PROGRAMMING EXAMPLES +-------------------- +Default: BASE <-- 0xc8 (current volume, no stereo detect, + radio enable, tuner adjust disable) + +Card Off: BASE <-- 0x00 (audio mute, no stereo detect, + radio disable, tuner adjust disable) + +Card On: BASE <-- 0x00 (see "Card Off", clears any unfinished business) + BASE <-- 0xc8 (see "Default") + +Volume Down: BASE <-- 0x48 (volume down, no stereo detect, + radio enable, tuner adjust disable) + * wait 10 msec * + BASE <-- 0xc8 (see "Default") + +Volume Up: BASE <-- 0x88 (volume up, no stereo detect, + radio enable, tuner adjust disable) + * wait 10 msec * + BASE <-- 0xc8 (see "Default") + +Check Stereo: BASE <-- 0xd8 (current volume, stereo detect, + radio enable, tuner adjust disable) + * wait 100 msec * + x <-- BASE (read ioport) + BASE <-- 0xc8 (see "Default") + + x=0xff ==> "not stereo", x=0xfd ==> "stereo detected" + +Set Frequency: code = (freq*40) + 10486188 + foreach of the 24 bits in code, + (from Least to Most Significant): + to write a "zero" bit, + BASE <-- 0x01 (audio mute, no stereo detect, radio + disable, "zero" bit phase 1, tuner adjust) + BASE <-- 0x03 (audio mute, no stereo detect, radio + disable, "zero" bit phase 2, tuner adjust) + to write a "one" bit, + BASE <-- 0x05 (audio mute, no stereo detect, radio + disable, "one" bit phase 1, tuner adjust) + BASE <-- 0x07 (audio mute, no stereo detect, radio + disable, "one" bit phase 2, tuner adjust) + +---------------------------------------------------------------------------- diff -u --recursive --new-file v2.1.115/linux/Documentation/sound/ChangeLog.multisound linux/Documentation/sound/ChangeLog.multisound --- v2.1.115/linux/Documentation/sound/ChangeLog.multisound Wed Dec 31 16:00:00 1969 +++ linux/Documentation/sound/ChangeLog.multisound Sun Aug 9 12:15:49 1998 @@ -0,0 +1,137 @@ +1998-08-06 Andrew Veliath + + * Update version to 0.7.2 + + * After A/D calibration, do an explicit set to the line input, + rather than using set_recsrc + +1998-07-20 Andrew Veliath + + * Update version to 0.7.1 + + * Add more OSS ioctls + +1998-07-19 Andrew Veliath + + * Update doc file + + * Bring back DIGITAL1 with digital parameter to msnd_pinnacle.c + and CONFIG_MSNDPIN_DIGITAL. I'm not sure this actually works, + since I find audio playback goes into a very speeded mode of + operation, however it might be due to a lack of a digital + source, which I don't have to test. + +1998-07-18 Andrew Veliath + + * Update version to 0.7.0 + + * Can now compile with Alan Cox' 2.0.34-modular-sound patch (so + now it requires >= 2.1.106 or 2.0.34-ms) (note for 2.0.34-ms it + is in the Experimental section) + + * More modularization, consolidation, also some MIDI hooks + installed for future MIDI modules + + * Write flush + + * Change default speed, channels, bit size to OSS/Free defaults + +1998-06-02 Andrew Veliath + + * Update version to 0.5b + + * Fix version detection + + * Remove underflow and overflow resets (delay was too long) + + * Replace spinlocked bitops with atomic bit ops + +1998-05-27 Andrew Veliath + + * Update version to 0.5a + + * Better recovery from underflow or overflow conditions + + * Fix a deadlock condition with one thread reading and the other + writing + +1998-05-26 Andrew Veliath + + * Update version to 0.5 + + * Separate reset queue functions for play and record + + * Add delays in dsp_halt + +1998-05-24 Andrew Veliath + + * Add a check for Linux >= 2.1.95 + + * Remove DIGITAL1 input until I figure out how to make it work + + * Add HAVE_DSPCODEH which when not defined will load firmware from + files using mod_firmware_load, then release memory after they + are uploaded (requires reorganized OSS). + +1998-05-22 Andrew Veliath + + * Update version to 0.4c + + * Hopefully fix the mixer volume problem + +1998-05-19 Andrew Veliath + + * Add __initfuncs and __initdatas to reduce resident code size + + * Move bunch of code around, remove some protos + + * Integrate preliminary changes for Alan Cox's OSS reorganization + for non-OSS drivers to coexist with OSS devices on the same + major. To compile standalone, must now define STANDALONE. + +1998-05-16 Andrew Veliath + + * Update version to 0.4b + + * Integrated older card support into a unified driver, tested on a + MultiSound Classic c/o Kendrick Vargas. + +1998-05-15 Andrew Veliath + + * Update version to 0.4 + + * Fix read/write return values + +1998-05-13 Andrew Veliath + + * Update version to 0.3 + + * Stop play gracefully + + * Add busy flag + + * Add major and calibrate_signal module parameters + + * Add ADC calibration + + * Add some OSS compatibility ioctls + + * Add mixer record selection + + * Add O_NONBLOCK support, separate read/write wait queues + + * Add sample bit size ioctl, expanded sample rate ioctl + + * Playback suspension now resumes + + * Use signal_pending after interruptible_sleep_on + + * Add recording, change ints to bit flags + +1998-05-11 Andrew Veliath + + * Update version to 0.2 + + * Add preliminary playback support + + * Use new Turtle Beach DSP code \ No newline at end of file diff -u --recursive --new-file v2.1.115/linux/Documentation/sound/MultiSound linux/Documentation/sound/MultiSound --- v2.1.115/linux/Documentation/sound/MultiSound Thu Jul 16 18:09:22 1998 +++ linux/Documentation/sound/MultiSound Sun Aug 9 12:15:49 1998 @@ -9,8 +9,8 @@ ~~~~~~~~~~~~~~~~~~ Currently digital audio and mixer functionality is supported. (memory -mapped digital audio is not yet supported). MultiSound support is -fully modularized, and can only be used as modules: +mapped digital audio is not yet supported). Modular MultiSound +support is composed of the following modules: msnd - MultiSound base (requires soundcore) msnd_classic - Base audio/mixer support for Classic, Monetery and @@ -80,14 +80,28 @@ msnd_classic, msnd_pinnacle Additional Options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -fifosize The digital audio FIFOs, in kilobytes. The default is - 64kB (two FIFOs are allocated, so this uses up 128kB). +fifosize The digital audio FIFOs, in kilobytes. The + default is 64kB (two FIFOs are allocated, so + this uses up 128kB). calibrate_signal Setting this to one calibrates the ADCs to the signal, zero calibrates to the card (defaults to zero). +msnd_pinnacle Additional Options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +digital Specify digital=1 to enable the S/PDIF input + if you have the digital daughterboard + adapter. This will enable access to the + DIGITAL1 input for the soundcard in the mixer. + Some mixer programs might have trouble setting + the DIGITAL1 source as an input. If you have + trouble, you can try the setdigital.c program + at the bottom of this document. + + Obtaining and Creating Firmware Files ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -105,7 +119,9 @@ cp DSPCODE/MSNDPERM.REB /etc/sound/msndperm.bin When configuring the Linux kernel, specify /etc/sound/msndinit.bin and -/etc/sound/msndperm.bin for the two firmware files. +/etc/sound/msndperm.bin for the two firmware files (Linux kernel +versions older than 2.2 do not ask for firmware paths, and are +hardcoded to /etc/sound). For the Pinnacle/Fiji @@ -122,9 +138,9 @@ -- conv.l start -- %% -[ \n\t,\r] ; -\;.* ; -DB ; +[ \n\t,\r] +\;.* +DB [0-9A-Fa-f]+H { int n; sscanf(yytext, "%xH", &n); printf("%c", n); } -- conv.l end -- @@ -143,4 +159,76 @@ The conv (and conv.l) program is not needed after conversion and can be safely deleted. Then, when configuring the Linux kernel, specify /etc/sound/pndspini.bin and /etc/sound/pndsperm.bin for the two -firmware files. +firmware files (Linux kernel versions older than 2.2 do not ask for +firmware paths, and are hardcoded to /etc/sound). + + +Recording from the S/PDIF Input +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you have a Pinnacle or Fiji with S/PDIF input and want to set it as +the input source, you can use this program if you have trouble trying +to do it with a mixer program (be sure to insert the module with the +digital=1 option). + +Compile with: +cc -O setdigital.c -o setdigital + +-- start setdigital.c -- +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + int fd; + unsigned long recmask, recsrc; + + if (argc != 2) { + fprintf(stderr, "usage: setdigital \n"); + exit(1); + } else + + if ((fd = open(argv[1], O_RDWR)) < 0) { + perror(argv[1]); + exit(1); + } + + if (ioctl(fd, SOUND_MIXER_READ_RECMASK, &recmask) < 0) { + fprintf(stderr, "error: ioctl read recmask failed\n"); + perror("ioctl"); + close(fd); + exit(1); + } + + if (!(recmask & SOUND_MASK_DIGITAL1)) { + fprintf(stderr, "error: cannot find DIGITAL1 device in mixer\n"); + close(fd); + exit(1); + } + + if (ioctl(fd, SOUND_MIXER_READ_RECSRC, &recsrc) < 0) { + fprintf(stderr, "error: ioctl read recsrc failed\n"); + perror("ioctl"); + close(fd); + exit(1); + } + + recsrc |= SOUND_MASK_DIGITAL1; + + if (ioctl(fd, SOUND_MIXER_WRITE_RECSRC, &recsrc) < 0) { + fprintf(stderr, "error: ioctl write recsrc failed\n"); + perror("ioctl"); + close(fd); + exit(1); + } + + close(fd); + + return 0; +} +-- end setdigital.c -- diff -u --recursive --new-file v2.1.115/linux/Documentation/sound/OPL3-SA linux/Documentation/sound/OPL3-SA --- v2.1.115/linux/Documentation/sound/OPL3-SA Tue Jul 21 00:15:29 1998 +++ linux/Documentation/sound/OPL3-SA Sun Aug 9 12:15:49 1998 @@ -1,6 +1,12 @@ -OPL3-SA sound driver (opl3sa.o) +OPL3-SA1 sound driver (opl3sa.o) -The Yamaha OPL3-SAx sound chip is usually found built into motherboards, and +--- +Note: This howto only describes how to setup the OPL3-SA1 chip; this info +does not apply to the SA2, SA3, or SA4. Contact hannu@opensound.com for +the support details of these other SAx chips. +--- + +The Yamaha OPL3-SA1 sound chip is usually found built into motherboards, and it's a decent little chip offering a WSS mode, a SB Pro emulation mode, MPU401 and OPL3 FM Synth capabilities. @@ -73,4 +79,3 @@ Questions? Comments? - diff -u --recursive --new-file v2.1.115/linux/Documentation/sound/Wavefront linux/Documentation/sound/Wavefront --- v2.1.115/linux/Documentation/sound/Wavefront Tue Jul 21 00:15:29 1998 +++ linux/Documentation/sound/Wavefront Sun Aug 9 12:15:49 1998 @@ -1,14 +1,17 @@ - An OSS/Free Driver for WaveFront soundcards - (Turtle Beach Maui, Tropez, Tropez Plus) + An OSS/Free Driver for WaveFront soundcards + (Turtle Beach Maui, Tropez, Tropez Plus) - Paul Barton-Davis, July 1998 + Paul Barton-Davis, July 1998 + + VERSION 0.2.4 Driver Status ------------- -Requires: Kernel 2.1.106 or later - -As of 7/3/1998, this driver is currently in *BETA* state. This means +Requires: Kernel 2.1.106 or later (a version of the driver is included +with kernels 2.1.109 and above) + +As of 7/20/1998, this driver is currently in *BETA* state. This means that it compiles and runs, and that I use it on my system (Linux 2.1.106) with some reasonably demanding applications and uses. I believe the code is approaching an initial "finished" state that @@ -17,11 +20,11 @@ Please note that to date, the driver has ONLY been tested on a Tropez Plus. I would very much like to hear (and help out) people with Tropez and Maui cards, since I think the driver can support those cards as -well. +well. -Finally, the driver has not been tested as a static (non-modular) part -of the kernel. Alan Cox's good work in modularizing OSS/Free for Linux -makes this rather unnecessary. +Finally, the driver has not been tested (or even compiled) as a static +(non-modular) part of the kernel. Alan Cox's good work in modularizing +OSS/Free for Linux makes this rather unnecessary. Some Questions -------------- @@ -30,7 +33,7 @@ 0) What does this driver do that the maui driver did not ? ********************************************************************** -* can fully initialize a WaveFront card from cold boot - no DOS +* can fully initialize a WaveFront card from cold boot - no DOS utilities needed * working patch/sample/program loading and unloading (the maui driver didn't document how to make this work, and assumed @@ -40,14 +43,13 @@ * for the Tropez Plus, (primitive) control of the YSS225 FX processor * Virtual MIDI mode supported - 2 MIDI devices accessible via the WaveFront's MPU401/UART emulation. One - accesses the WaveFront synth, the other accesses the - external MIDI connector. Full MIDI read/write semantics - for both devices. + accesses the WaveFront synth, the other accesses the + external MIDI connector. Full MIDI read/write semantics + for both devices. * OSS-compliant /dev/sequencer interface for the WaveFront synth, - including native and GUS-format patch downloading. + including native and GUS-format patch downloading. * semi-intelligent patch management (prototypical at this point) - ********************************************************************** 1) What to do about MIDI interfaces ? ********************************************************************** @@ -81,24 +83,27 @@ Either because its not finished yet, or because you're a better coder than I am, or because you don't understand some aspect of how the card -or the code works. +or the code works. I absolutely welcome comments, criticisms and suggestions about the -design and implementation of the driver. +design and implementation of the driver. ********************************************************************** 3) What files are included ? ********************************************************************** drivers/sound/README.wavefront -- this file - drivers/sound/wavefront.patch -- patches for the 2.1.106 sound driver -s - needed to make the rest of this work + + drivers/sound/wavefront.patch -- patches for the 2.1.106 sound drivers + needed to make the rest of this work + DO NOT USE IF YOU'VE APPLIED THEM + BEFORE, OR HAVE 2.1.109 OR ABOVE + drivers/sound/wavfront.c -- the driver drivers/sound/ys225.h -- data declarations for FX config drivers/sound/ys225.c -- data definitions for FX config - drivers/sound/wf_midi.c -- the "uart401" driver - to support virtual MIDI mode. + drivers/sound/wf_midi.c -- the "uart401" driver + to support virtual MIDI mode. include/wavefront.h -- the header file Documentation/sound/Tropez+ -- short docs on configuration @@ -113,6 +118,9 @@ PART TWO: apply the patches + DO THIS ONLY IF YOU HAVE A KERNEL VERSION BELOW 2.1.109 + AND HAVE NOT ALREADY INSTALLED THE PATCH(ES). + cd drivers/sound patch < wavefront.patch @@ -121,15 +129,14 @@ cd make xconfig (or whichever config option you use) - - choose YES for Sound Support + - choose YES for Sound Support - choose MODULE (M) for OSS Sound Modules - - choose MODULE(M) to Generic OPL2/OPL3 support - choose MODULE(M) to YM3812/OPL3 support - - choose MODULE(M) for WaveFront support - - choose MODULE(M) for CS4232 support + - choose MODULE(M) for WaveFront support + - choose MODULE(M) for CS4232 support - - choose "N" for everything else (unless you have other - soundcards you want support for) + - choose "N" for everything else (unless you have other + soundcards you want support for) make dep @@ -155,7 +162,6 @@ #undef CONFIG_SOUND_PAS #undef CONFIG_SOUND_SB #undef CONFIG_SOUND_ADLIB -#define CONFIG_SOUND_ADLIB_MODULE 1 #undef CONFIG_SOUND_GUS #undef CONFIG_SOUND_MPU401 #undef CONFIG_SOUND_PSS @@ -191,21 +197,22 @@ alias char-major-14 wavefront alias synth0 wavefront alias mixer0 cs4232 + alias audio0 cs4232 pre-install wavefront modprobe "-k" "cs4232" - post-install wavefront modprobe "-k" "adlib_card" + post-install wavefront modprobe "-k" "opl3" options wavefront io=0x200 irq=9 options cs4232 synthirq=9 synthio=0x200 io=0x530 irq=5 dma=1 dma2=0 - options adlib_card io=0x388 + options opl3 io=0x388 -Things to note: +Things to note: the wavefront options "io" and "irq" ***MUST*** match the "synthio" and "synthirq" cs4232 options. - you can do without the adlib_card module if you don't - want to use the OPL/[34] synth on the soundcard + you can do without the opl3 module if you don't + want to use the OPL/[34] FM synth on the soundcard - the adlib_card io parameter is conventionally not adjustable. + the opl3 io parameter is conventionally not adjustable. In theory, any not-in-use IO port address would work, but just use 0x388 and stick with the crowd. @@ -218,7 +225,7 @@ almost certainly have the firmware, and if not, its freely available on their website, at: - http://www.tbeach.com/tbs/downloads/scardsdown.htm#tropezplus + http://www.tbeach.com/tbs/downloads/scardsdown.htm#tropezplus The file is called WFOS2001.MOT (for the Tropez+). @@ -233,7 +240,7 @@ %% ^S[28].*\r$ printf ("%c%.*s", yyleng-1,yyleng-1,yytext); <> { fputc ('\0', stdout); return; } -\n {} +\n {} . {} ---- cut here ------------------------- @@ -241,7 +248,7 @@ shell> flex -ows.c ws.l shell> cc -o ws ws.c - + and then use it like this: ws < my-copy-of-the-oswf.mot-file > /etc/sound/wavefront.os @@ -260,12 +267,11 @@ modprobe wavefront -You should get something like this, directly if you're on a console, and in -/var/log/messages: +You should get something like this in /var/log/messages: WaveFront: firmware 1.20 already loaded. -or +or WaveFront: no response to firmware probe, assume raw. @@ -294,9 +300,9 @@ Kernel: Linux bd 2.1.106 #12 SMP Fri Jul 3 00:37:34 EDT 1998 i486 Config options: 0 -Installed drivers: +Installed drivers: -Card config: +Card config: Audio devices: 0: Crystal audio controller (CS4232) (DUPLEX) @@ -325,7 +331,7 @@ hooked to the soundcard, you can use "-e" to route to the external synth(s) (in theory, -D 1 should work as well, but I think there is a bug in playmidi which prevents this from doing what it -should). +should). ********************************************************************** 8) What are the module parameters ? @@ -333,45 +339,33 @@ Its best to read wavefront.c for this, but here is a summary: -integers: - wf_raw - if set, ignore apparent presence of firmware - loaded onto the ICS2115, reset the whole - board, and initialize it from scratch. (default = 0) +integers: + wf_raw - if set, ignore apparent presence of firmware + loaded onto the ICS2115, reset the whole + board, and initialize it from scratch. (default = 0) fx_raw - if set, always initialize the YSS225 processor - on the Tropez plus. (default = 1) + on the Tropez plus. (default = 1) < The next 4 are basically for kernel hackers to allow - tweaking the driver for testing purposes. > + tweaking the driver for testing purposes. > - wf_short_wait_count - loop counter used when waiting for - status conditions on the board. This - is CPU-specific. After this many - loops, the driver will sleep. - The default is 5000. I have a 66Mhz 486. - - wf_sleep_interval - the driver sleeps for - HZ/wf_sleep_interval seconds per sleep. - The default is 50. - - wf_sleep_tries - the number of times the driver will sleep - when waiting for a status condition on the - board. The default is 100 (2 secs, if - wf_sleep_interval is 50). - - wf_debug_default - debugging flags. See sound/wavefront.h - for WF_DEBUG_* values. Default is zero. - Setting this allows you to debug the - driver during module installation. + wait_usecs - loop timer used when waiting for + status conditions on the board. + The default is 150. + + debug_default - debugging flags. See sound/wavefront.h + for WF_DEBUG_* values. Default is zero. + Setting this allows you to debug the + driver during module installation. strings: - wf_ospath - path to get to the pre-processed OS firmware. - (default: /etc/sound/wavefront.os) + ospath - path to get to the pre-processed OS firmware. + (default: /etc/sound/wavefront.os) ********************************************************************** 9) Who should I contact if I have problems? ********************************************************************** Just me: Paul Barton-Davis - diff -u --recursive --new-file v2.1.115/linux/MAINTAINERS linux/MAINTAINERS --- v2.1.115/linux/MAINTAINERS Mon Aug 3 12:45:43 1998 +++ linux/MAINTAINERS Sun Aug 9 12:15:49 1998 @@ -330,9 +330,9 @@ JOYSTICK DRIVER P: Vojtech Pavlik -M: vojtech@atrey.karlin.mff.cuni.cz -W: http://atrey.karlin.mff.cuni.cz/~vojtech/joystick/ +M: vojtech@ucw.cz L: linux-joystick@atrey.karlin.mff.cuni.cz +W: http://atrey.karlin.mff.cuni.cz/~vojtech/joystick/ S: Maintained KERNEL AUTOMOUNTER (AUTOFS) diff -u --recursive --new-file v2.1.115/linux/Makefile linux/Makefile --- v2.1.115/linux/Makefile Thu Aug 6 14:06:28 1998 +++ linux/Makefile Sun Aug 16 22:41:01 1998 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 115 +SUBLEVEL = 116 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) @@ -228,8 +228,10 @@ scripts/split-include include/linux/autoconf.h include/config; \ fi -linuxsubdirs: dummy - set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i; done +linuxsubdirs: $(patsubst %, _dir_%, $(SUBDIRS)) + +$(patsubst %, _dir_%, $(SUBDIRS)) : dummy + $(MAKE) -C $(patsubst _dir_%, %, $@) $(TOPDIR)/include/linux/version.h: include/linux/version.h $(TOPDIR)/include/linux/compile.h: include/linux/compile.h @@ -271,26 +273,8 @@ init/main.o: init/main.c $(CC) $(CFLAGS) $(PROFILING) -c -o $*.o $< -fs: dummy - $(MAKE) linuxsubdirs SUBDIRS=fs - -lib: dummy - $(MAKE) linuxsubdirs SUBDIRS=lib - -mm: dummy - $(MAKE) linuxsubdirs SUBDIRS=mm - -ipc: dummy - $(MAKE) linuxsubdirs SUBDIRS=ipc - -kernel: dummy - $(MAKE) linuxsubdirs SUBDIRS=kernel - -drivers: dummy - $(MAKE) linuxsubdirs SUBDIRS=drivers - -net: dummy - $(MAKE) linuxsubdirs SUBDIRS=net +fs lib mm ipc kernel drivers net: dummy + $(MAKE) $(subst $@, _dir_$@, $@) MODFLAGS = -DMODULE ifdef CONFIG_MODULES @@ -298,11 +282,10 @@ MODFLAGS += -DMODVERSIONS -include $(HPATH)/linux/modversions.h endif -modules: include/linux/version.h - @set -e; \ - for i in $(SUBDIRS); \ - do $(MAKE) -C $$i CFLAGS="$(CFLAGS) $(MODFLAGS)" MAKING_MODULES=1 modules; \ - done +modules: $(patsubst %, _mod_%, $(SUBDIRS)) + +$(patsubst %, _mod_%, $(SUBDIRS)) : include/linux/version.h + $(MAKE) -C $(patsubst _mod_%, %, $@) CFLAGS="$(CFLAGS) $(MODFLAGS)" MAKING_MODULES=1 modules modules_install: @( \ @@ -396,7 +379,9 @@ dep-files: scripts/mkdep archdep include/linux/version.h scripts/mkdep init/*.c > .depend scripts/mkdep `find $(FINDHPATH) -follow -name \*.h ! -name modversions.h -print` > .hdepend - set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i fastdep; done +# set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i fastdep ;done +# let this be made through the fastdep rule in Rules.make + $(MAKE) $(patsubst %,_sfdep_%,$(SUBDIRS)) _FASTDEP_ALL_SUB_DIRS="$(SUBDIRS)" MODVERFILE := diff -u --recursive --new-file v2.1.115/linux/README linux/README --- v2.1.115/linux/README Wed Jun 24 22:54:02 1998 +++ linux/README Fri Aug 14 10:51:35 1998 @@ -240,7 +240,7 @@ the file MAINTAINERS to see if there is a particular person associated with the part of the kernel that you are having trouble with. If there isn't anyone listed there, then the second best thing is to mail - them to me (Linus.Torvalds@Helsinki.FI), and possibly to any other + them to me (torvalds@transmeta.com), and possibly to any other relevant mailing-list or to the newsgroup. The mailing-lists are useful especially for SCSI and NETworking problems, as I can't test either of those personally anyway. diff -u --recursive --new-file v2.1.115/linux/Rules.make linux/Rules.make --- v2.1.115/linux/Rules.make Wed Jun 24 22:54:02 1998 +++ linux/Rules.make Sun Aug 16 22:41:01 1998 @@ -105,15 +105,23 @@ fastdep: dummy $(TOPDIR)/scripts/mkdep $(wildcard *.[chS] local.h.master) > .depend ifdef ALL_SUB_DIRS - set -e; for i in $(ALL_SUB_DIRS); do $(MAKE) -C $$i fastdep; done + $(MAKE) $(patsubst %,_sfdep_%,$(ALL_SUB_DIRS)) _FASTDEP_ALL_SUB_DIRS="$(ALL_SUB_DIRS)" endif +ifdef _FASTDEP_ALL_SUB_DIRS +$(patsubst %,_sfdep_%,$(_FASTDEP_ALL_SUB_DIRS)): + $(MAKE) -C $(patsubst _sfdep_%,%,$@) fastdep +endif + + # # A rule to make subdirectories # -sub_dirs: dummy +sub_dirs: dummy $(patsubst %,_subdir_%,$(SUB_DIRS)) + ifdef SUB_DIRS - set -e; for i in $(SUB_DIRS); do $(MAKE) -C $$i; done +$(patsubst %,_subdir_%,$(SUB_DIRS)) : dummy + $(MAKE) -C $(patsubst _subdir_%,%,$@) endif # @@ -123,13 +131,20 @@ ifneq "$(strip $(ALL_MOBJS))" "" PDWN=$(shell $(CONFIG_SHELL) $(TOPDIR)/scripts/pathdown.sh) endif -modules: $(ALL_MOBJS) $(MIX_OBJS) $(MI_OBJS) dummy + ifdef MOD_SUB_DIRS - set -e; for i in $(MOD_SUB_DIRS); do $(MAKE) -C $$i modules; done +$(patsubst %,_modsubdir_%,$(MOD_SUB_DIRS)) : dummy + $(MAKE) -C $(patsubst _modsubdir_%,%,$@) modules endif + ifdef MOD_IN_SUB_DIRS - set -e; for i in $(MOD_IN_SUB_DIRS); do $(MAKE) -C $$i modules; done +$(patsubst %,_modinsubdir_%,$(MOD_IN_SUB_DIRS)) : dummy + $(MAKE) -C $(patsubst _modinsubdir_%,%,$@) modules endif + +modules: $(ALL_MOBJS) $(MIX_OBJS) $(MI_OBJS) dummy \ + $(patsubst %,_modsubdir_%,$(MOD_SUB_DIRS)) \ + $(patsubst %,_modinsubdir_%,$(MOD_IN_SUB_DIRS)) ifneq "$(strip $(MOD_LIST_NAME))" "" rm -f $$TOPDIR/modules/$(MOD_LIST_NAME) ifdef MOD_SUB_DIRS diff -u --recursive --new-file v2.1.115/linux/arch/alpha/Makefile linux/arch/alpha/Makefile --- v2.1.115/linux/arch/alpha/Makefile Tue Jul 21 00:15:29 1998 +++ linux/arch/alpha/Makefile Sun Aug 9 12:09:05 1998 @@ -10,35 +10,42 @@ NM := nm -B -ifdef CONFIG_CROSSCOMPILE -# enable this for linking under OSF/1: -LINKFLAGS = -non_shared -T 0xfffffc0000310000 -N -else - elf=$(shell if $(LD) --help | grep elf64alpha >/dev/null; then echo yes; fi) - ifeq ($(elf),yes) - LINKFLAGS = -static -T arch/alpha/vmlinux.lds - else - LINKFLAGS = -static -T arch/alpha/vmlinux.lds -N - endif -# GNU gcc/cc1/as can use pipes instead of temporary files -CFLAGS := $(CFLAGS) -pipe -endif +LINKFLAGS = -static -T arch/alpha/vmlinux.lds -N +CFLAGS := $(CFLAGS) -pipe -mno-fp-regs -ffixed-8 -CFLAGS := $(CFLAGS) -mno-fp-regs -ffixed-8 +# Determine if we can use the BWX instructions with GAS. +old_gas := $(shell if $(AS) --version 2>&1 | grep 'version 2.7' > /dev/null; then echo y; else echo n; fi) -# determine if we can use the BWX instructions with GAS -OLD_GAS := $(shell if $(AS) --version 2>&1 | grep 'version 2.7' > /dev/null; then echo y; else echo n; fi) +# Determine if GCC understands the -mcpu= option. +have_mcpu := $(shell if $(CC) -mcpu=ev5 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi) -# If PYXIS, then enable use of BWIO space -ifneq ($(OLD_GAS),y) - ifeq ($(CONFIG_ALPHA_PYXIS),y) - CFLAGS := $(CFLAGS) -Wa,-m21164a -DBWX_USABLE -DBWIO_ENABLED - endif +# If GENERIC, make sure to turn off any instruction set extensions that +# the host compiler might have on by default. Given that EV4 and EV5 +# have the same instruction set, prefer EV5 because an EV5 schedule is +# more likely to keep an EV4 processor busy than vice-versa. +ifeq ($(CONFIG_ALPHA_GENERIC)$(have_mcpu),yy) + CFLAGS := $(CFLAGS) -mcpu=ev5 endif # If EV6, turn on the proper optimizations. -ifeq ($(CONFIG_ALPHA_EV6),y) - CFLAGS := -mcpu=ev6 $(CFLAGS) +ifeq ($(CONFIG_ALPHA_EV6)$(have_mcpu),yy) + CFLAGS := $(CFLAGS) -mcpu=ev6 +endif + +# For TSUNAMI, we must have the assembler not emulate our instructions. +# BWX is most important, but we don't really want any emulation ever. +ifeq ($(old_gas),y) + ifneq ($(CONFIG_ALPHA_GENERIC)$(CONFIG_ALPHA_TSUNAMI),) + # How do we do #error in make? + CFLAGS := --error-please-upgrade-your-assembler + endif +else + ifeq ($(CONFIG_ALPHA_GENERIC),y) + CFLAGS := $(CFLAGS) -Wa,-mev6 + endif + ifeq ($(CONFIG_ALPHA_PYXIS),y) + CFLAGS := $(CFLAGS) -Wa,-m21164a -DBWIO_ENABLED + endif endif HEAD := arch/alpha/kernel/head.o @@ -59,7 +66,7 @@ @$(MAKEBOOT) rawboot # -# my boot writes directly to a specific disk partition, I doubt most +# My boot writes directly to a specific disk partition, I doubt most # people will want to do that without changes.. # msb my-special-boot: diff -u --recursive --new-file v2.1.115/linux/arch/alpha/config.in linux/arch/alpha/config.in --- v2.1.115/linux/arch/alpha/config.in Thu Aug 6 14:06:28 1998 +++ linux/arch/alpha/config.in Sun Aug 9 12:09:05 1998 @@ -31,30 +31,30 @@ fi choice 'Alpha system type' \ - "Avanti CONFIG_ALPHA_AVANTI \ - Alpha-XL CONFIG_ALPHA_XL \ - Alpha-XLT CONFIG_ALPHA_XLT \ - Cabriolet CONFIG_ALPHA_CABRIOLET \ - EB66 CONFIG_ALPHA_EB66 \ - EB66+ CONFIG_ALPHA_EB66P \ - EB64+ CONFIG_ALPHA_EB64P \ - EB164 CONFIG_ALPHA_EB164 \ - PC164 CONFIG_ALPHA_PC164 \ - LX164 CONFIG_ALPHA_LX164 \ - SX164 CONFIG_ALPHA_SX164 \ - DP264 CONFIG_ALPHA_DP264 \ - Jensen CONFIG_ALPHA_JENSEN \ - Noname CONFIG_ALPHA_NONAME \ - Takara CONFIG_ALPHA_TAKARA \ - Mikasa CONFIG_ALPHA_MIKASA \ - Noritake CONFIG_ALPHA_NORITAKE \ - Alcor CONFIG_ALPHA_ALCOR \ - Miata CONFIG_ALPHA_MIATA \ - Sable CONFIG_ALPHA_SABLE \ - Rawhide CONFIG_ALPHA_RAWHIDE \ - AlphaBook1 CONFIG_ALPHA_BOOK1 \ - Ruffian CONFIG_ALPHA_RUFFIAN \ - Platform2000 CONFIG_ALPHA_P2K" Cabriolet + "Generic CONFIG_ALPHA_GENERIC \ + Alcor/Alpha-XLT CONFIG_ALPHA_ALCOR \ + Alpha-XL CONFIG_ALPHA_XL \ + AlphaBook1 CONFIG_ALPHA_BOOK1 \ + Avanti CONFIG_ALPHA_AVANTI \ + Cabriolet CONFIG_ALPHA_CABRIOLET \ + DP264 CONFIG_ALPHA_DP264 \ + EB164 CONFIG_ALPHA_EB164 \ + EB64+ CONFIG_ALPHA_EB64P \ + EB66 CONFIG_ALPHA_EB66 \ + EB66+ CONFIG_ALPHA_EB66P \ + Jensen CONFIG_ALPHA_JENSEN \ + LX164 CONFIG_ALPHA_LX164 \ + Miata CONFIG_ALPHA_MIATA \ + Mikasa CONFIG_ALPHA_MIKASA \ + Noname CONFIG_ALPHA_NONAME \ + Noritake CONFIG_ALPHA_NORITAKE \ + PC164 CONFIG_ALPHA_PC164 \ + Platform2000 CONFIG_ALPHA_P2K \ + Rawhide CONFIG_ALPHA_RAWHIDE \ + Ruffian CONFIG_ALPHA_RUFFIAN \ + SX164 CONFIG_ALPHA_SX164 \ + Sable CONFIG_ALPHA_SABLE \ + Takara CONFIG_ALPHA_TAKARA" Generic # clear all implied options (don't want default values for those): unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6 @@ -64,6 +64,11 @@ unset CONFIG_ALPHA_TSUNAMI CONFIG_ALPHA_MCPCIA unset CONFIG_ALPHA_NEED_ROUNDING_EMULATION +if [ "$CONFIG_ALPHA_GENERIC" = "y" ] +then + define_bool CONFIG_PCI y + define_bool CONFIG_ALPHA_NEED_ROUNDING_EMULATION y +fi if [ "$CONFIG_ALPHA_BOOK1" = "y" ] then define_bool CONFIG_ALPHA_NONAME y diff -u --recursive --new-file v2.1.115/linux/arch/alpha/defconfig linux/arch/alpha/defconfig --- v2.1.115/linux/arch/alpha/defconfig Thu Aug 6 14:06:28 1998 +++ linux/arch/alpha/defconfig Sun Aug 9 12:14:08 1998 @@ -18,35 +18,32 @@ # General setup # CONFIG_NATIVE=y -# CONFIG_ALPHA_AVANTI is not set +CONFIG_ALPHA_GENERIC=y +# CONFIG_ALPHA_ALCOR is not set # CONFIG_ALPHA_XL is not set -# CONFIG_ALPHA_XLT is not set +# CONFIG_ALPHA_BOOK1 is not set +# CONFIG_ALPHA_AVANTI is not set # CONFIG_ALPHA_CABRIOLET is not set +# CONFIG_ALPHA_DP264 is not set +# CONFIG_ALPHA_EB164 is not set +# CONFIG_ALPHA_EB64P is not set # CONFIG_ALPHA_EB66 is not set # CONFIG_ALPHA_EB66P is not set -# CONFIG_ALPHA_EB64P is not set -# CONFIG_ALPHA_EB164 is not set -# CONFIG_ALPHA_PC164 is not set -# CONFIG_ALPHA_LX164 is not set -# CONFIG_ALPHA_SX164 is not set -# CONFIG_ALPHA_DP264 is not set # CONFIG_ALPHA_JENSEN is not set -# CONFIG_ALPHA_NONAME is not set -# CONFIG_ALPHA_TAKARA is not set +# CONFIG_ALPHA_LX164 is not set +# CONFIG_ALPHA_MIATA is not set # CONFIG_ALPHA_MIKASA is not set +# CONFIG_ALPHA_NONAME is not set # CONFIG_ALPHA_NORITAKE is not set -CONFIG_ALPHA_ALCOR=y -# CONFIG_ALPHA_MIATA is not set -# CONFIG_ALPHA_SABLE is not set +# CONFIG_ALPHA_PC164 is not set +# CONFIG_ALPHA_P2K is not set # CONFIG_ALPHA_RAWHIDE is not set -# CONFIG_ALPHA_BOOK1 is not set # CONFIG_ALPHA_RUFFIAN is not set -# CONFIG_ALPHA_P2K is not set +# CONFIG_ALPHA_SX164 is not set +# CONFIG_ALPHA_SABLE is not set +# CONFIG_ALPHA_TAKARA is not set CONFIG_PCI=y -CONFIG_ALPHA_EV5=y -CONFIG_ALPHA_CIA=y -CONFIG_ALPHA_SRM=y -CONFIG_ALPHA_EISA=y +CONFIG_ALPHA_NEED_ROUNDING_EMULATION=y # CONFIG_PCI_QUIRKS is not set CONFIG_PCI_OLD_PROC=y CONFIG_NET=y diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/Makefile linux/arch/alpha/kernel/Makefile --- v2.1.115/linux/arch/alpha/kernel/Makefile Wed Apr 1 20:11:47 1998 +++ linux/arch/alpha/kernel/Makefile Sun Aug 9 12:09:05 1998 @@ -20,44 +20,101 @@ OX_OBJS := alpha_ksyms.o +ifdef CONFIG_ALPHA_GENERIC + +O_OBJS += core_apecs.o core_cia.o core_lca.o core_mcpcia.o core_pyxis.o \ + core_t2.o core_tsunami.o \ + sys_alcor.o sys_cabriolet.o sys_dp264.o sys_eb64p.o \ + sys_jensen.o sys_miata.o sys_mikasa.o sys_noritake.o \ + sys_rawhide.o sys_ruffian.o sys_sable.o sys_sio.o \ + sys_sx164.o sys_takara.o \ + es1888.o smc37c669.o smc37c93x.o +else + +# Core logic support ifdef CONFIG_ALPHA_APECS -O_OBJS += apecs.o +O_OBJS += core_apecs.o endif ifdef CONFIG_ALPHA_CIA -O_OBJS += cia.o +O_OBJS += core_cia.o endif ifdef CONFIG_ALPHA_LCA -O_OBJS += lca.o +O_OBJS += core_lca.o +endif +ifdef CONFIG_ALPHA_MCPCIA +O_OBJS += core_mcpcia.o endif ifdef CONFIG_ALPHA_PYXIS -O_OBJS += pyxis.o +O_OBJS += core_pyxis.o endif ifdef CONFIG_ALPHA_T2 -O_OBJS += t2.o +O_OBJS += core_t2.o endif ifdef CONFIG_ALPHA_TSUNAMI -O_OBJS += tsunami.o +O_OBJS += core_tsunami.o endif -ifdef CONFIG_ALPHA_MCPCIA -O_OBJS += mcpcia.o + +# Board support +ifneq ($(CONFIG_ALPHA_ALCOR)$(CONFIG_ALPHA_XLT),) +O_OBJS += sys_alcor.o +endif +ifneq ($(CONFIG_ALPHA_CABRIOLET)$(CONFIG_ALPHA_EB164)$(CONFIG_ALPHA_EB66P)$(CONFIG_ALPHA_LX164)$(CONFIG_ALPHA_PC164),) +O_OBJS += sys_cabriolet.o +endif +ifdef CONFIG_ALPHA_DP264 +O_OBJS += sys_dp264.o +endif +ifneq ($(CONFIG_ALPHA_EB64P)$(CONFIG_ALPHA_EB66),) +O_OBJS += sys_eb64p.o +endif +ifdef CONFIG_ALPHA_JENSEN +O_OBJS += sys_jensen.o +endif +ifdef CONFIG_ALPHA_MIATA +O_OBJS += sys_miata.o +endif +ifdef CONFIG_ALPHA_MIKASA +O_OBJS += sys_mikasa.o +endif +ifdef CONFIG_ALPHA_NORITAKE +O_OBJS += sys_noritake.o +endif +ifdef CONFIG_ALPHA_RAWHIDE +O_OBJS += sys_rawhide.o +endif +ifdef CONFIG_ALPHA_RUFFIAN +O_OBJS += sys_ruffian.o +endif +ifdef CONFIG_ALPHA_SABLE +O_OBJS += sys_sable.o +endif +ifneq ($(CONFIG_ALPHA_BOOK1)$(CONFIG_ALPHA_AVANTI)$(CONFIG_ALPHA_NONAME)$(CONFIG_ALPHA_P2K)$(CONFIG_ALPHA_XL),) +O_OBJS += sys_sio.o +endif +ifdef CONFIG_ALPHA_SX164 +O_OBJS += sys_sx164.o +endif +ifdef CONFIG_ALPHA_TAKARA +O_OBJS += sys_takara.o endif -ifneq ($(CONFIG_ALPHA_PC164)$(CONFIG_ALPHA_LX164),nn) -O_OBJS += smc37c93x.o +# Device support +ifdef CONFIG_ALPHA_MIATA +O_OBJS += es1888.o endif -ifneq ($(CONFIG_ALPHA_SX164)$(CONFIG_ALPHA_MIATA)$(CONFIG_ALPHA_DP264),nnn) +ifneq ($(CONFIG_ALPHA_SX164)$(CONFIG_ALPHA_MIATA)$(CONFIG_ALPHA_DP264),) O_OBJS += smc37c669.o endif +ifneq ($(CONFIG_ALPHA_PC164)$(CONFIG_ALPHA_LX164),) +O_OBJS += smc37c93x.o +endif + +endif # GENERIC ifdef SMP O_OBJS += smp.o endif all: kernel.o head.o - -head.o: head.s - -head.s: head.S $(TOPDIR)/include/asm-alpha/system.h - $(CPP) -traditional $(AFLAGS) -o $*.s $< include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c --- v2.1.115/linux/arch/alpha/kernel/alpha_ksyms.c Thu Jul 16 18:09:23 1998 +++ linux/arch/alpha/kernel/alpha_ksyms.c Sun Aug 9 12:09:05 1998 @@ -25,6 +25,7 @@ #include #include #include +#include #define __KERNEL_SYSCALLS__ #include @@ -43,6 +44,7 @@ extern void __divqu (void); extern void __remqu (void); +EXPORT_SYMBOL(alpha_mv); EXPORT_SYMBOL(local_bh_count); EXPORT_SYMBOL(local_irq_count); EXPORT_SYMBOL(enable_irq); @@ -121,7 +123,9 @@ #ifdef CONFIG_MATHEMU_MODULE extern long (*alpha_fp_emul_imprecise)(struct pt_regs *, unsigned long); +extern long (*alpha_fp_emul) (unsigned long pc); EXPORT_SYMBOL(alpha_fp_emul_imprecise); +EXPORT_SYMBOL(alpha_fp_emul); #endif /* diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/apecs.c linux/arch/alpha/kernel/apecs.c --- v2.1.115/linux/arch/alpha/kernel/apecs.c Wed Jun 24 22:54:02 1998 +++ linux/arch/alpha/kernel/apecs.c Wed Dec 31 16:00:00 1969 @@ -1,622 +0,0 @@ -/* - * Code common to all APECS chips. - * - * Rewritten for Apecs from the lca.c from: - * - * Written by David Mosberger (davidm@cs.arizona.edu) with some code - * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit - * bios code. - */ -#include -#include -#include -#include - -#include -#include -#include -#include - -/* - * NOTE: Herein lie back-to-back mb instructions. They are magic. - * One plausible explanation is that the i/o controller does not properly - * handle the system transaction. Another involves timing. Ho hum. - */ - -extern struct hwrpb_struct *hwrpb; -extern asmlinkage void wrmces(unsigned long mces); - -/* - * BIOS32-style PCI interface: - */ - -#ifdef DEBUG -# define DBG(args) printk args -#else -# define DBG(args) -#endif - -#define vuip volatile unsigned int * - -static volatile unsigned int apecs_mcheck_expected = 0; -static volatile unsigned int apecs_mcheck_taken = 0; -static unsigned int apecs_jd, apecs_jd1, apecs_jd2; - -#ifdef CONFIG_ALPHA_SRM_SETUP -unsigned int APECS_DMA_WIN_BASE = APECS_DMA_WIN_BASE_DEFAULT; -unsigned int APECS_DMA_WIN_SIZE = APECS_DMA_WIN_SIZE_DEFAULT; -#endif /* SRM_SETUP */ - -/* - * Given a bus, device, and function number, compute resulting - * configuration space address and setup the APECS_HAXR2 register - * accordingly. It is therefore not safe to have concurrent - * invocations to configuration space access routines, but there - * really shouldn't be any need for this. - * - * Type 0: - * - * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 - * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | | | | | | | | | | | | | | | | | | | | | | |F|F|F|R|R|R|R|R|R|0|0| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * 31:11 Device select bit. - * 10:8 Function number - * 7:2 Register number - * - * Type 1: - * - * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 - * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * 31:24 reserved - * 23:16 bus number (8 bits = 128 possible buses) - * 15:11 Device number (5 bits) - * 10:8 function number - * 7:2 register number - * - * Notes: - * The function number selects which function of a multi-function device - * (e.g., SCSI and Ethernet). - * - * The register selects a DWORD (32 bit) register offset. Hence it - * doesn't get shifted by 2 bits as we want to "drop" the bottom two - * bits. - */ -static int mk_conf_addr(unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned long *pci_addr, - unsigned char *type1) -{ - unsigned long addr; - - DBG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x," - " pci_addr=0x%p, type1=0x%p)\n", - bus, device_fn, where, pci_addr, type1)); - - if (bus == 0) { - int device = device_fn >> 3; - - /* type 0 configuration cycle: */ - - if (device > 20) { - DBG(("mk_conf_addr: device (%d) > 20, returning -1\n", - device)); - return -1; - } - - *type1 = 0; - addr = (device_fn << 8) | (where); - } else { - /* type 1 configuration cycle: */ - *type1 = 1; - addr = (bus << 16) | (device_fn << 8) | (where); - } - *pci_addr = addr; - DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr)); - return 0; -} - - -static unsigned int conf_read(unsigned long addr, unsigned char type1) -{ - unsigned long flags; - unsigned int stat0, value; - unsigned int haxr2 = 0; /* to keep gcc quiet */ - -#ifdef CONFIG_ALPHA_SRM - /* some SRMs step on these registers during a machine check: */ - register long s0 asm ("9"); - register long s1 asm ("10"); - register long s2 asm ("11"); - register long s3 asm ("12"); - register long s4 asm ("13"); - register long s5 asm ("14"); - asm volatile ("# %0" : "r="(s0)); - asm volatile ("# %0" : "r="(s1)); - asm volatile ("# %0" : "r="(s2)); - asm volatile ("# %0" : "r="(s3)); - asm volatile ("# %0" : "r="(s4)); - asm volatile ("# %0" : "r="(s5)); -#endif - - save_flags(flags); /* avoid getting hit by machine check */ - cli(); - - DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1)); - - /* reset status register to avoid losing errors: */ - stat0 = *(vuip)APECS_IOC_DCSR; - *(vuip)APECS_IOC_DCSR = stat0; - mb(); - DBG(("conf_read: APECS DCSR was 0x%x\n", stat0)); - /* if Type1 access, must set HAE #2 */ - if (type1) { - haxr2 = *(vuip)APECS_IOC_HAXR2; - mb(); - *(vuip)APECS_IOC_HAXR2 = haxr2 | 1; - DBG(("conf_read: TYPE1 access\n")); - } - - draina(); - apecs_mcheck_expected = 1; - apecs_mcheck_taken = 0; - mb(); - /* access configuration space: */ - value = *(vuip)addr; - mb(); - mb(); /* magic */ - if (apecs_mcheck_taken) { - apecs_mcheck_taken = 0; - value = 0xffffffffU; - mb(); - } - apecs_mcheck_expected = 0; - mb(); - -#if 1 - /* - * david.rusling@reo.mts.dec.com. This code is needed for the - * EB64+ as it does not generate a machine check (why I don't - * know). When we build kernels for one particular platform - * then we can make this conditional on the type. - */ - draina(); - - /* now look for any errors */ - stat0 = *(vuip)APECS_IOC_DCSR; - DBG(("conf_read: APECS DCSR after read 0x%x\n", stat0)); - if (stat0 & 0xffe0U) { /* is any error bit set? */ - /* if not NDEV, print status */ - if (!(stat0 & 0x0800)) { - printk("apecs.c:conf_read: got stat0=%x\n", stat0); - } - - /* reset error status: */ - *(vuip)APECS_IOC_DCSR = stat0; - mb(); - wrmces(0x7); /* reset machine check */ - value = 0xffffffff; - } -#endif - - /* if Type1 access, must reset HAE #2 so normal IO space ops work */ - if (type1) { - *(vuip)APECS_IOC_HAXR2 = haxr2 & ~1; - mb(); - } - restore_flags(flags); -#ifdef CONFIG_ALPHA_SRM - /* some SRMs step on these registers during a machine check: */ - asm volatile ("# %0" :: "r"(s0)); - asm volatile ("# %0" :: "r"(s1)); - asm volatile ("# %0" :: "r"(s2)); - asm volatile ("# %0" :: "r"(s3)); - asm volatile ("# %0" :: "r"(s4)); - asm volatile ("# %0" :: "r"(s5)); -#endif - return value; -} - - -static void conf_write(unsigned long addr, unsigned int value, unsigned char type1) -{ - unsigned long flags; - unsigned int stat0; - unsigned int haxr2 = 0; /* to keep gcc quiet */ - - save_flags(flags); /* avoid getting hit by machine check */ - cli(); - - /* reset status register to avoid losing errors: */ - stat0 = *(vuip)APECS_IOC_DCSR; - *(vuip)APECS_IOC_DCSR = stat0; - mb(); - - /* if Type1 access, must set HAE #2 */ - if (type1) { - haxr2 = *(vuip)APECS_IOC_HAXR2; - mb(); - *(vuip)APECS_IOC_HAXR2 = haxr2 | 1; - } - - draina(); - apecs_mcheck_expected = 1; - mb(); - /* access configuration space: */ - *(vuip)addr = value; - mb(); - mb(); /* magic */ - apecs_mcheck_expected = 0; - mb(); - -#if 1 - /* - * david.rusling@reo.mts.dec.com. This code is needed for the - * EB64+ as it does not generate a machine check (why I don't - * know). When we build kernels for one particular platform - * then we can make this conditional on the type. - */ - draina(); - - /* now look for any errors */ - stat0 = *(vuip)APECS_IOC_DCSR; - if (stat0 & 0xffe0U) { /* is any error bit set? */ - /* if not NDEV, print status */ - if (!(stat0 & 0x0800)) { - printk("apecs.c:conf_write: got stat0=%x\n", stat0); - } - - /* reset error status: */ - *(vuip)APECS_IOC_DCSR = stat0; - mb(); - wrmces(0x7); /* reset machine check */ - } -#endif - - /* if Type1 access, must reset HAE #2 so normal IO space ops work */ - if (type1) { - *(vuip)APECS_IOC_HAXR2 = haxr2 & ~1; - mb(); - } - restore_flags(flags); -} - - -int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned char *value) -{ - unsigned long addr = APECS_CONF; - unsigned long pci_addr; - unsigned char type1; - - *value = 0xff; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - - addr |= (pci_addr << 5) + 0x00; - - *value = conf_read(addr, type1) >> ((where & 3) * 8); - - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_read_config_word (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short *value) -{ - unsigned long addr = APECS_CONF; - unsigned long pci_addr; - unsigned char type1; - - *value = 0xffff; - - if (where & 0x1) { - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) { - return PCIBIOS_SUCCESSFUL; - } - - addr |= (pci_addr << 5) + 0x08; - - *value = conf_read(addr, type1) >> ((where & 3) * 8); - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int *value) -{ - unsigned long addr = APECS_CONF; - unsigned long pci_addr; - unsigned char type1; - - *value = 0xffffffff; - if (where & 0x3) { - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x18; - *value = conf_read(addr, type1); - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned char value) -{ - unsigned long addr = APECS_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x00; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_write_config_word (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short value) -{ - unsigned long addr = APECS_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x08; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int value) -{ - unsigned long addr = APECS_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x18; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; -} - - -unsigned long apecs_init(unsigned long mem_start, unsigned long mem_end) -{ - -#ifdef CONFIG_ALPHA_XL - /* - * Set up the PCI->physical memory translation windows. - * For the XL we *must* use both windows, in order to - * maximize the amount of physical memory that can be used - * to DMA from the ISA bus, and still allow PCI bus devices - * access to all of host memory. - * - * see for window bases and sizes. - * - * this restriction due to the true XL motherboards' 82379AB SIO - * PCI<->ISA bridge chip which passes only 27 bits of address... - */ - - *(vuip)APECS_IOC_PB1R = 1U<<19 | (APECS_XL_DMA_WIN1_BASE & 0xfff00000U); - *(vuip)APECS_IOC_PM1R = (APECS_XL_DMA_WIN1_SIZE - 1) & 0xfff00000U; - *(vuip)APECS_IOC_TB1R = 0; - - *(vuip)APECS_IOC_PB2R = 1U<<19 | (APECS_XL_DMA_WIN2_BASE & 0xfff00000U); - *(vuip)APECS_IOC_PM2R = (APECS_XL_DMA_WIN2_SIZE - 1) & 0xfff00000U; - *(vuip)APECS_IOC_TB2R = 0; - -#else /* CONFIG_ALPHA_XL */ -#ifdef CONFIG_ALPHA_SRM_SETUP - /* check window 1 for enabled and mapped to 0 */ - if ((*(vuip)APECS_IOC_PB1R & (1U<<19)) && (*(vuip)APECS_IOC_TB1R == 0)) - { - APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB1R & 0xfff00000U; - APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM1R & 0xfff00000U; - APECS_DMA_WIN_SIZE += 0x00100000U; -#if 0 - printk("apecs_init: using Window 1 settings\n"); - printk("apecs_init: PB1R 0x%x PM1R 0x%x TB1R 0x%x\n", - *(vuip)APECS_IOC_PB1R, - *(vuip)APECS_IOC_PM1R, - *(vuip)APECS_IOC_TB1R); -#endif - } - else /* check window 2 for enabled and mapped to 0 */ - if ((*(vuip)APECS_IOC_PB2R & (1U<<19)) && (*(vuip)APECS_IOC_TB2R == 0)) - { - APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB2R & 0xfff00000U; - APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM2R & 0xfff00000U; - APECS_DMA_WIN_SIZE += 0x00100000U; -#if 0 - printk("apecs_init: using Window 2 settings\n"); - printk("apecs_init: PB2R 0x%x PM2R 0x%x TB2R 0x%x\n", - *(vuip)APECS_IOC_PB2R, - *(vuip)APECS_IOC_PM2R, - *(vuip)APECS_IOC_TB2R); -#endif - } - else /* we must use our defaults... */ -#endif /* SRM_SETUP */ - { - /* - * Set up the PCI->physical memory translation windows. - * For now, window 2 is disabled. In the future, we may - * want to use it to do scatter/gather DMA. Window 1 - * goes at 1 GB and is 1 GB large. - */ - *(vuip)APECS_IOC_PB2R = 0U; /* disable window 2 */ - - *(vuip)APECS_IOC_PB1R = 1U<<19 | (APECS_DMA_WIN_BASE & 0xfff00000U); - *(vuip)APECS_IOC_PM1R = (APECS_DMA_WIN_SIZE - 1) & 0xfff00000U; - *(vuip)APECS_IOC_TB1R = 0; - } -#endif /* CONFIG_ALPHA_XL */ - -#ifdef CONFIG_ALPHA_CABRIOLET -#ifdef NO_LONGER_NEEDED_I_HOPE - /* - * JAE: HACK!!! for now, hardwire if configured... - * davidm: Older miniloader versions don't set the clock frequency - * right, so hardcode it for now. - */ - if (hwrpb->sys_type == ST_DEC_EB64P) { - hwrpb->sys_type = ST_DEC_EBPC64; - } - if (hwrpb->cycle_freq == 0) { - hwrpb->cycle_freq = 275000000; - } - - /* update checksum: */ - { - unsigned long *l, sum; - - sum = 0; - for (l = (unsigned long *) hwrpb; - l < (unsigned long *) &hwrpb->chksum; - ++l) - sum += *l; - hwrpb->chksum = sum; - } -#endif /* NO_LONGER_NEEDED_I_HOPE */ -#endif /* CONFIG_ALPHA_CABRIOLET */ - - /* - * Finally, clear the HAXR2 register, which gets used - * for PCI Config Space accesses. That is the way - * we want to use it, and we do not want to depend on - * what ARC or SRM might have left behind... - */ - { -#if 0 - unsigned int haxr2 = *(vuip)APECS_IOC_HAXR2; mb(); - if (haxr2) printk("apecs_init: HAXR2 was 0x%x\n", haxr2); -#endif - *(vuip)APECS_IOC_HAXR2 = 0; mb(); - } - - - return mem_start; -} - -int apecs_pci_clr_err(void) -{ - apecs_jd = *(vuip)APECS_IOC_DCSR; - if (apecs_jd & 0xffe0L) { - apecs_jd1 = *(vuip)APECS_IOC_SEAR; - *(vuip)APECS_IOC_DCSR = apecs_jd | 0xffe1L; - apecs_jd = *(vuip)APECS_IOC_DCSR; - mb(); - } - *(vuip)APECS_IOC_TBIA = (unsigned int)APECS_IOC_TBIA; - apecs_jd2 = *(vuip)APECS_IOC_TBIA; - mb(); - return 0; -} - -void apecs_machine_check(unsigned long vector, unsigned long la_ptr, - struct pt_regs * regs) -{ - struct el_common *mchk_header; - struct el_procdata *mchk_procdata; - struct el_apecs_sysdata_mcheck *mchk_sysdata; - unsigned long *ptr; - int i; - - - mchk_header = (struct el_common *)la_ptr; - mchk_procdata = (struct el_procdata *) - (la_ptr + mchk_header->proc_offset - sizeof(mchk_procdata->paltemp)); - mchk_sysdata = - (struct el_apecs_sysdata_mcheck *)(la_ptr + mchk_header->sys_offset); - -#ifdef DEBUG - printk("apecs_machine_check: vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr); - printk(" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", - regs->pc, mchk_header->size, mchk_header->proc_offset, - mchk_header->sys_offset); - printk("apecs_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n", - apecs_mcheck_expected, mchk_sysdata->epic_dcsr, - mchk_sysdata->epic_pear); - ptr = (unsigned long *)la_ptr; - for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { - printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]); - } -#endif /* DEBUG */ - - /* - * Check if machine check is due to a badaddr() and if so, - * ignore the machine check. - */ -#ifdef CONFIG_ALPHA_MIKASA -#define MCHK_NO_DEVSEL 0x205L -#define MCHK_NO_TABT 0x204L - if (apecs_mcheck_expected && - (((unsigned int)mchk_header->code == MCHK_NO_DEVSEL) || - ((unsigned int)mchk_header->code == MCHK_NO_TABT)) - ) - { -#else - if (apecs_mcheck_expected && (mchk_sysdata->epic_dcsr && 0x0c00UL)) { -#endif - apecs_mcheck_expected = 0; - apecs_mcheck_taken = 1; - mb(); - mb(); /* magic */ - apecs_pci_clr_err(); - wrmces(0x7); - mb(); - draina(); - DBG(("apecs_machine_check: EXPECTED\n")); - } - else if (vector == 0x620 || vector == 0x630) { - wrmces(0x1f); /* disable correctable from now on */ - mb(); - draina(); - printk("apecs_machine_check: HW correctable (0x%lx)\n", - vector); - } - else { - printk(KERN_CRIT "APECS machine check:\n"); - printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr); - printk(KERN_CRIT - " pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", - regs->pc, mchk_header->size, mchk_header->proc_offset, - mchk_header->sys_offset); - printk(KERN_CRIT " expected %d DCSR 0x%lx PEAR 0x%lx\n", - apecs_mcheck_expected, mchk_sysdata->epic_dcsr, - mchk_sysdata->epic_pear); - - ptr = (unsigned long *)la_ptr; - for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { - printk(KERN_CRIT " +%lx %lx %lx\n", - i*sizeof(long), ptr[i], ptr[i+1]); - } -#if 0 - /* doesn't work with MILO */ - show_regs(regs); -#endif - } -} diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c --- v2.1.115/linux/arch/alpha/kernel/bios32.c Tue Jul 21 00:15:29 1998 +++ linux/arch/alpha/kernel/bios32.c Sun Aug 9 12:09:05 1998 @@ -31,9 +31,15 @@ #include #include #include +#include #include -#if 0 +#include "proto.h" +#include "bios32.h" + +#define DEBUG_DEVS 0 + +#if DEBUG_DEVS # define DBG_DEVS(args) printk args #else # define DBG_DEVS(args) @@ -43,161 +49,288 @@ asmlinkage int sys_pciconfig_read() { return -ENOSYS; } asmlinkage int sys_pciconfig_write() { return -ENOSYS; } +void reset_for_srm(void) { } #else /* CONFIG_PCI */ #include #include -#include #include #include #include #include - -#define KB 1024 -#define MB (1024*KB) -#define GB (1024*MB) +/* + * PCI public interfaces. + */ #define MAJOR_REV 0 +#define MINOR_REV 4 /* minor revision 4, add multi-PCI handling */ -/* minor revision 4, add multi-PCI handling */ -#define MINOR_REV 4 -/* - * Align VAL to ALIGN, which must be a power of two. - */ -#define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1)) +int +pcibios_present(void) +{ + return alpha_mv.pci_read_config_byte != NULL; +} +void __init +pcibios_init(void) +{ + printk("Alpha PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV); + if (alpha_use_srm_setup) + printk(" NOT modifying existing (SRM) PCI configuration\n"); -/* - * On multiple PCI bus machines, create a handle from the bus number. - */ -#if defined(CONFIG_ALPHA_MCPCIA) /* || defined(CONFIG_ALPHA_TSUNAMI) */ -extern struct linux_hose_info *bus2hose[256]; -#define HANDLE(b) (((unsigned long)(bus2hose[(b)]->pci_hose_index)&3)<<32) -#define DEV_IS_ON_PRIMARY(dev) \ - (bus2hose[(dev)->bus->number]->pci_first_busno == (dev)->bus->number) -#else -#define HANDLE(b) (0) -#define DEV_IS_ON_PRIMARY(dev) ((dev)->bus->number == 0) -#endif + /* FIXME: Scan for multiple PCI busses here. */ +} -/* - * PCI_MODIFY - * - * Temporary internal macro. If this 0, then do not write to any of - * the PCI registers, merely read them (i.e., use configuration as - * determined by SRM). The SRM seem do be doing a less than perfect - * job in configuring PCI devices, so for now we do it ourselves. - * Reconfiguring PCI devices breaks console (RPB) callbacks, but - * those don't work properly with 64 bit addresses anyways. - * - * The accepted convention seems to be that the console (POST - * software) should fully configure boot devices and configure the - * interrupt routing of *all* devices. In particular, the base - * addresses of non-boot devices need not be initialized. For - * example, on the AXPpci33 board, the base address a #9 GXE PCI - * graphics card reads as zero (this may, however, be due to a bug in - * the graphics card---there have been some rumor that the #9 BIOS - * incorrectly resets that address to 0...). - */ -#ifdef CONFIG_ALPHA_SRM_SETUP -#define PCI_MODIFY 0 -static struct pci_dev *irq_dev_to_reset[16]; -static unsigned char irq_to_reset[16]; -static int irq_reset_count = 0; -static struct pci_dev *io_dev_to_reset[16]; -static unsigned char io_reg_to_reset[16]; -static unsigned int io_to_reset[16]; -static int io_reset_count = 0; -#else /* SRM_SETUP */ -#define PCI_MODIFY 1 -#endif /* SRM_SETUP */ - -extern struct hwrpb_struct *hwrpb; - -/* Forward declarations for some extra fixup routines for specific hardware. */ -#if defined(CONFIG_ALPHA_PC164) || defined(CONFIG_ALPHA_LX164) -extern int SMC93x_Init(void); -#endif -extern int SMC669_Init(void); -#ifdef CONFIG_ALPHA_MIATA -static int es1888_init(void); -#endif +char * __init +pcibios_setup(char *str) +{ + return str; +} + +void __init +pcibios_fixup(void) +{ + alpha_mv.pci_fixup(); +} -#if PCI_MODIFY +void __init +pcibios_fixup_bus(struct pci_bus *bus) +{ +} -/* - * NOTE: we can't just blindly use 64K for machines with EISA busses; they - * may also have PCI-PCI bridges present, and then we'd configure the bridge - * incorrectly. - * - * Also, we start at 0x8000 or 0x9000, in hopes to get all devices' - * IO space areas allocated *before* 0xC000; this is because certain - * BIOSes (Millennium for one) use PCI Config space "mechanism #2" - * accesses to probe the bus. If a device's registers appear at 0xC000, - * it may see an INx/OUTx at that address during BIOS emulation of the - * VGA BIOS, and some cards, notably Adaptec 2940UW, take mortal offense. - * - * Note that we may need this stuff for SRM_SETUP also, since certain - * SRM consoles screw up and allocate I/O space addresses > 64K behind - * PCI-to_PCI bridges, which can't pass I/O addresses larger than 64K, AFAIK. - */ -#if defined(CONFIG_ALPHA_EISA) -#define DEFAULT_IO_BASE 0x9000 /* start above 8th slot */ -#else -#define DEFAULT_IO_BASE 0x8000 /* start at 8th slot */ -#endif -static unsigned int io_base; +int +pcibios_read_config_byte (u8 bus, u8 dev, u8 where, u8 *value) +{ + int r = PCIBIOS_FUNC_NOT_SUPPORTED; + if (alpha_mv.pci_read_config_byte) + r = alpha_mv.pci_read_config_byte(bus, dev, where, value); + return r; +} + +int +pcibios_read_config_word (u8 bus, u8 dev, u8 where, u16 *value) +{ + int r = PCIBIOS_FUNC_NOT_SUPPORTED; + if (alpha_mv.pci_read_config_word) + r = alpha_mv.pci_read_config_word(bus, dev, where, value); + return r; +} + +int +pcibios_read_config_dword (u8 bus, u8 dev, u8 where, u32 *value) +{ + int r = PCIBIOS_FUNC_NOT_SUPPORTED; + if (alpha_mv.pci_read_config_dword) + r = alpha_mv.pci_read_config_dword(bus, dev, where, value); + return r; +} + +int +pcibios_write_config_byte (u8 bus, u8 dev, u8 where, u8 value) +{ + int r = PCIBIOS_FUNC_NOT_SUPPORTED; + if (alpha_mv.pci_write_config_byte) + r = alpha_mv.pci_write_config_byte(bus, dev, where, value); + return r; +} + +int +pcibios_write_config_word (u8 bus, u8 dev, u8 where, u16 value) +{ + int r = PCIBIOS_FUNC_NOT_SUPPORTED; + if (alpha_mv.pci_write_config_word) + r = alpha_mv.pci_write_config_word(bus, dev, where, value); + return r; +} + +int +pcibios_write_config_dword (u8 bus, u8 dev, u8 where, u32 value) +{ + int r = PCIBIOS_FUNC_NOT_SUPPORTED; + if (alpha_mv.pci_write_config_dword) + r = alpha_mv.pci_write_config_dword(bus, dev, where, value); + return r; +} + +asmlinkage int +sys_pciconfig_read(unsigned long bus, unsigned long dfn, + unsigned long off, unsigned long len, + unsigned char *buf) +{ + unsigned char ubyte; + unsigned short ushort; + unsigned int uint; + long err = 0; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!pcibios_present()) + return -ENOSYS; + + lock_kernel(); + switch (len) { + case 1: + err = pcibios_read_config_byte(bus, dfn, off, &ubyte); + if (err != PCIBIOS_SUCCESSFUL) + ubyte = 0xff; + put_user(ubyte, buf); + break; + case 2: + err = pcibios_read_config_word(bus, dfn, off, &ushort); + if (err != PCIBIOS_SUCCESSFUL) + ushort = 0xffff; + put_user(ushort, (unsigned short *)buf); + break; + case 4: + err = pcibios_read_config_dword(bus, dfn, off, &uint); + if (err != PCIBIOS_SUCCESSFUL) + uint = 0xffffffff; + put_user(uint, (unsigned int *)buf); + break; + default: + err = -EINVAL; + break; + } + unlock_kernel(); + return err; +} + +asmlinkage int +sys_pciconfig_write(unsigned long bus, unsigned long dfn, + unsigned long off, unsigned long len, + unsigned char *buf) +{ + unsigned char ubyte; + unsigned short ushort; + unsigned int uint; + long err = 0; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (!pcibios_present()) + return -ENOSYS; + + lock_kernel(); + switch (len) { + case 1: + err = get_user(ubyte, buf); + if (err) + break; + err = pcibios_write_config_byte(bus, dfn, off, ubyte); + if (err != PCIBIOS_SUCCESSFUL) { + err = -EFAULT; + } + break; + case 2: + err = get_user(ushort, (unsigned short *)buf); + if (err) + break; + err = pcibios_write_config_word(bus, dfn, off, ushort); + if (err != PCIBIOS_SUCCESSFUL) { + err = -EFAULT; + } + break; + case 4: + err = get_user(uint, (unsigned int *)buf); + if (err) + break; + err = pcibios_write_config_dword(bus, dfn, off, uint); + if (err != PCIBIOS_SUCCESSFUL) { + err = -EFAULT; + } + break; + default: + err = -EINVAL; + break; + } + unlock_kernel(); + return err; +} -#if defined(CONFIG_ALPHA_XL) -/* - * An XL is AVANTI (APECS) family, *but* it has only 27 bits of ISA address - * that get passed through the PCI<->ISA bridge chip. Although this causes - * us to set the PCI->Mem window bases lower than normal, we still allocate - * PCI bus devices' memory addresses *below* the low DMA mapping window, - * and hope they fit below 64Mb (to avoid conflicts), and so that they can - * be accessed via SPARSE space. - * - * We accept the risk that a broken Myrinet card will be put into a true XL - * and thus can more easily run into the problem described below. - */ -#define DEFAULT_MEM_BASE (16*MB + 2*MB) /* 16M to 64M-1 is avail */ -#elif defined(CONFIG_ALPHA_LCA) || defined(CONFIG_ALPHA_APECS) /* - * We try to make this address *always* have more than 1 bit set. - * this is so that devices like the broken Myrinet card will always have - * a PCI memory address that will never match a IDSEL address in - * PCI Config space, which can cause problems with early rev cards. - * - * However, APECS and LCA have only 34 bits for physical addresses, thus - * limiting PCI bus memory addresses for SPARSE access to be less than 128Mb. + * Gory details start here... */ -#define DEFAULT_MEM_BASE (64*MB + 2*MB) -#else +struct linux_hose_info *bus2hose[256]; + /* - * We try to make this address *always* have more than 1 bit set. - * this is so that devices like the broken Myrinet card will always have - * a PCI memory address that will never match a IDSEL address in - * PCI Config space, which can cause problems with early rev cards. - * - * Because CIA and PYXIS and T2 have more bits for physical addresses, - * they support an expanded range of SPARSE memory addresses. + * Align VAL to ALIGN, which must be a power of two. */ -#define DEFAULT_MEM_BASE (128*MB + 16*MB) +#define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1)) + + +/* + * The following structure records initial configuration of devices + * so that we can reset them on shutdown and so enable clean reboots + * on SRM. It is more trouble than it iw worth to conditionalize this. + */ + +static struct { + struct reset_irq { + struct pci_dev *dev; + u8 irq; + } irq[16]; + int irq_count; + + struct reset_io { + struct pci_dev *dev; + u8 reg; + u32 io; + } io[16]; + int io_count; +} srm_resets; + +/* Apply the collected reset modifications. */ + +void +reset_for_srm(void) +{ + struct pci_dev *dev; + int i; + /* Reset any IRQs that we changed. */ + for (i = 0; i < srm_resets.irq_count; i++) { + dev = srm_resets.irq[i].dev; + + pcibios_write_config_byte(dev->bus->number, dev->devfn, + PCI_INTERRUPT_LINE, + srm_resets.irq[i].irq); +#if 1 + printk("reset_for_srm: bus %d slot 0x%x " + "SRM IRQ 0x%x changed back from 0x%x\n", + dev->bus->number, PCI_SLOT(dev->devfn), + srm_resets.irq[i].irq, dev->irq); #endif -static unsigned int mem_base; + } + + /* Reset any IO addresses that we changed. */ + for (i = 0; i < srm_resets.io_count; i++) { + dev = srm_resets.io[i].dev; + + pcibios_write_config_byte(dev->bus->number, dev->devfn, + srm_resets.io[i].reg, + srm_resets.io[i].io); +#if 1 + printk("reset_for_srm: bus %d slot 0x%x " + "SRM IO restored to 0x%x\n", + dev->bus->number, PCI_SLOT(dev->devfn), + srm_resets.io[i].io); +#endif + } +} + /* * Disable PCI device DEV so that it does not respond to I/O or memory * accesses. */ -static void disable_dev(struct pci_dev *dev) +static void __init +disable_dev(struct pci_dev *dev) { struct pci_bus *bus; unsigned short cmd; @@ -208,12 +341,20 @@ */ if (dev->vendor == PCI_VENDOR_ID_INTEL && dev->device == PCI_DEVICE_ID_INTEL_82375) { + dev->class = PCI_CLASS_BRIDGE_EISA; DBG_DEVS(("disable_dev: ignoring PCEB...\n")); return; } + if (dev->vendor == PCI_VENDOR_ID_INTEL && + dev->device == PCI_DEVICE_ID_INTEL_82378) { + dev->class = PCI_CLASS_BRIDGE_ISA; + DBG_DEVS(("disable_dev: ignoring SIO...\n")); + return; + } + /* - * we don't have code that will init the CYPRESS bridge correctly + * We don't have code that will init the CYPRESS bridge correctly * so we do the next best thing, and depend on the previous * console code to do the right thing, and ignore it here... :-\ */ @@ -223,6 +364,19 @@ return; } +#if DEBUG_DEVS && 0 + /* Worse HACK: Don't disable the video card, so I can see where + it is *really* falling over. */ + if (dev->class >> 16 == PCI_BASE_CLASS_DISPLAY) { + DBG_DEVS(("disable_dev: ignoring video card %04x:%04x\n", + dev->vendor, dev->device)); + return; + } +#endif + + DBG_DEVS(("disable_dev: disabling %04x:%04x\n", + dev->vendor, dev->device)); + bus = dev->bus; pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd); @@ -237,7 +391,11 @@ */ #define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2)) -static void layout_dev(struct pci_dev *dev) +static unsigned int io_base; +static unsigned int mem_base; + +static void __init +layout_dev(struct pci_dev *dev) { struct pci_bus *bus; unsigned short cmd; @@ -251,12 +409,20 @@ */ if (dev->vendor == PCI_VENDOR_ID_INTEL && dev->device == PCI_DEVICE_ID_INTEL_82375) { + dev->class = PCI_CLASS_BRIDGE_EISA; DBG_DEVS(("layout_dev: ignoring PCEB...\n")); return; } + if (dev->vendor == PCI_VENDOR_ID_INTEL && + dev->device == PCI_DEVICE_ID_INTEL_82378) { + dev->class = PCI_CLASS_BRIDGE_ISA; + DBG_DEVS(("layout_dev: ignoring SIO...\n")); + return; + } + /* - * we don't have code that will init the CYPRESS bridge correctly + * We don't have code that will init the CYPRESS bridge correctly * so we do the next best thing, and depend on the previous * console code to do the right thing, and ignore it here... :-\ */ @@ -315,7 +481,7 @@ pcibios_write_config_dword(bus->number, dev->devfn, off, base | 0x1); - handle = HANDLE(bus->number) | base | 1; + handle = PCI_HANDLE(bus->number) | base | 1; dev->base_address[idx] = handle; DBG_DEVS(("layout_dev: dev 0x%x IO @ 0x%lx (0x%x)\n", @@ -400,7 +566,7 @@ mem_base = base + size; pcibios_write_config_dword(bus->number, dev->devfn, off, base); - handle = HANDLE(bus->number) | base; + handle = PCI_HANDLE(bus->number) | base; dev->base_address[idx] = handle; DBG_DEVS(("layout_dev: dev 0x%x MEM @ 0x%lx (0x%x)\n", dev->device, handle, size)); @@ -431,8 +597,8 @@ dev->device, dev->class, cmd|PCI_COMMAND_MASTER)); } - -static int layout_bus(struct pci_bus *bus) +static int __init +layout_bus(struct pci_bus *bus) { unsigned int l, tio, bio, tmem, bmem; struct pci_bus *child; @@ -543,24 +709,44 @@ return found_vga; } -#endif /* !PCI_MODIFY */ - - -int pcibios_present(void) +void __init +layout_all_busses(unsigned long default_io_base, + unsigned long default_mem_base) { - return 1; -} + struct pci_bus *cur; +#if defined(CONFIG_ALPHA_GENERIC) + static struct linux_hose_info dummy_hose; + int i; -void __init -pcibios_init(void) -{ - printk("Alpha PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV); -#if !PCI_MODIFY - printk("...NOT modifying existing (SRM) PCI configuration\n"); + /* + * HACK: Emulate a multi-bus machine to a limited extent + * by initializing bus2hose to point to something that + * has pci_hose_index & pci_first_busno zero. + */ + for (i = 0; i <= 0xff; i++) + bus2hose[i] = &dummy_hose; #endif + + /* + * Scan the tree, allocating PCI memory and I/O space. + */ + /* + * Sigh; check_region() will need changing to accept a PCI_HANDLE, + * if we allocate I/O space addresses on a per-bus basis. + * For now, make the I/O bases unique across all busses, so + * that check_region() will not get confused... ;-} + */ + io_base = default_io_base; + for (cur = &pci_root; cur; cur = cur->next) { + mem_base = default_mem_base; + DBG_DEVS(("layout_all_busses: calling layout_bus()\n")); + layout_bus(cur); + } + DBG_DEVS(("layout_all_busses: done.\n")); } + /* * The SRM console *disables* the IDE interface, this code ensures it's * enabled. @@ -575,7 +761,9 @@ * written twice (I believe this is a safety feature to prevent * accidental modification---fun, isn't it?). */ -static inline void enable_ide(long ide_base) + +void __init +enable_ide(long ide_base) { int data; @@ -586,68 +774,29 @@ outb(data | 0x40, ide_base+1); /* turn on IDE, really! */ } -/* - * A small note about bridges and interrupts. The DECchip 21050 (and later) - * adheres to the PCI-PCI bridge specification. This says that the - * interrupts on the other side of a bridge are swizzled in the following - * manner: - * - * Dev Interrupt Interrupt - * Pin on Pin on - * Device Connector - * - * 4 A A - * B B - * C C - * D D - * - * 5 A B - * B C - * C D - * D A - * - * 6 A C - * B D - * C A - * D B - * - * 7 A D - * B A - * C B - * D C - * - * Where A = pin 1, B = pin 2 and so on and pin=0 = default = A. - * Thus, each swizzle is ((pin-1) + (device#-4)) % 4 - * - * The following code is somewhat simplistic as it assumes only one bridge. - * I will fix it later (david.rusling@reo.mts.dec.com). - */ -static inline unsigned char -bridge_swizzle(unsigned char pin, unsigned int slot) -{ - /* swizzle */ - return (((pin-1) + slot) % 4) + 1; -} - -#ifdef CONFIG_ALPHA_SRM_SETUP -/* look for mis-configured devices' I/O space addresses behind bridges */ -static void check_behind_io(struct pci_dev *dev) +/* Look for mis-configured devices' I/O space addresses behind bridges. */ +static void +check_behind_io(struct pci_dev *dev) { struct pci_bus *bus = dev->bus; unsigned int reg, orig_base, new_base, found_one = 0; + struct reset_io *ior; for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) { - /* read the current setting, check for I/O space and >= 64K */ - pcibios_read_config_dword(bus->number, dev->devfn, reg, &orig_base); + /* Read the current setting, check for I/O space and >= 64K */ + pcibios_read_config_dword(bus->number, dev->devfn, + reg, &orig_base); + if (!orig_base || !(orig_base & PCI_BASE_ADDRESS_SPACE_IO)) continue; /* unused or non-IO */ + if (orig_base < 64*1024) { #if 1 printk("check_behind_io: ALREADY OK! bus %d slot %d base 0x%x\n", bus->number, PCI_SLOT(dev->devfn), orig_base); #endif if (orig_base & ~1) - continue; /* OK! */ + continue; /* OK! */ orig_base = 0x12001; /* HACK! FIXME!! */ } @@ -662,1160 +811,148 @@ pcibios_write_config_dword(bus->number, dev->devfn, reg, new_base); - io_dev_to_reset[io_reset_count] = dev; - io_reg_to_reset[io_reset_count] = reg; - io_to_reset[io_reset_count] = orig_base; - io_reset_count++; + ior = &srm_resets.io[srm_resets.io_count++]; + ior->dev = dev; + ior->reg = reg; + ior->io = orig_base; found_one++; - } /* end for-loop */ + } - /* if any were modified, gotta hack the bridge IO limits too... */ + /* If any were modified, gotta hack the bridge IO limits too. */ if (found_one) { - if (bus->self) { - struct pci_dev *bridge = bus->self; - unsigned int l; - /* - * Set up the top and bottom of the PCI I/O segment - * for this bus. - */ - pcibios_read_config_dword(bridge->bus->number, - bridge->devfn, 0x1c, &l); + if (bus->self) { + struct pci_dev *bridge = bus->self; + unsigned int l; + /* + * Set up the top and bottom of the PCI I/O segment + * for this bus. + */ + pcibios_read_config_dword(bridge->bus->number, + bridge->devfn, 0x1c, &l); #if 1 printk("check_behind_io: ALERT! bus %d slot %d oldLIM 0x%x\n", bus->number, PCI_SLOT(bridge->devfn), l); #endif - l = (l & 0xffff0000U) | 0xf080U; /* give it ALL */ - pcibios_write_config_dword(bridge->bus->number, - bridge->devfn, 0x1c, l); - pcibios_write_config_dword(bridge->bus->number, - bridge->devfn, - 0x3c, 0x00040000); - pcibios_write_config_dword(bridge->bus->number, - bridge->devfn, - 0x4, 0xffff0007); - } else - printk("check_behind_io: WARNING! bus->self NULL\n"); + l = (l & 0xffff0000U) | 0xf080U; /* give it ALL */ + pcibios_write_config_dword(bridge->bus->number, + bridge->devfn, 0x1c, l); + pcibios_write_config_dword(bridge->bus->number, + bridge->devfn, + 0x3c, 0x00040000); + pcibios_write_config_dword(bridge->bus->number, + bridge->devfn, + 0x4, 0xffff0007); + } else + printk("check_behind_io: WARNING! bus->self NULL\n"); } } -#endif /* CONFIG_ALPHA_SRM_SETUP */ + /* - * Most evaluation boards share most of the fixup code, which is isolated - * here. This function is declared "inline" as only one platform will ever - * be selected in any given kernel. If that platform doesn't need this code, - * we don't want it around as dead code. + * Most boards share most of the fixup code, which is isolated here. */ -static inline void -common_fixup(long min_idsel, long max_idsel, long irqs_per_slot, - char irq_tab[max_idsel - min_idsel + 1][irqs_per_slot], - long ide_base) -{ - struct pci_dev *dev, *curr; - unsigned char pin; - unsigned char slot; + +void __init +common_pci_fixup(int (*map_irq)(struct pci_dev *dev, int slot, int pin), + int (*swizzle)(struct pci_dev *dev, int *pin)) +{ + struct pci_dev *dev; + u8 pin, slot, irq_orig; + int irq; /* - * Go through all devices, fixing up irqs as we see fit: + * Go through all devices, fixing up irqs as we see fit. */ for (dev = pci_devices; dev; dev = dev->next) { - if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE || - dev->class >> 8 == PCI_CLASS_BRIDGE_PCMCIA) { - /* - * HACK: the PCI-to-EISA bridge appears not to identify - * itself as a bridge... :-( - */ - if (dev->vendor == PCI_VENDOR_ID_INTEL && - dev->device == PCI_DEVICE_ID_INTEL_82375) { - DBG_DEVS(("common_fixup: ignoring PCEB...\n")); - continue; - } + if ((dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) && + (dev->class >> 8 != PCI_CLASS_BRIDGE_PCMCIA)) + continue; - /* - * This device is not on the primary bus, we need - * to figure out which interrupt pin it will come - * in on. We know which slot it will come in on - * 'cos that slot is where the bridge is. Each - * time the interrupt line passes through a PCI-PCI - * bridge we must apply the swizzle function (see - * the inline static routine above). - */ - dev->irq = 0; - if (!DEV_IS_ON_PRIMARY(dev)) { - /* read the pin and do the PCI-PCI bridge - interrupt pin swizzle */ - pcibios_read_config_byte(dev->bus->number, - dev->devfn, - PCI_INTERRUPT_PIN, - &pin); - /* cope with 0 and illegal */ - if (pin == 0 || pin > 4) - pin = 1; - /* follow the chain of bridges, swizzling - as we go */ - curr = dev; -#if defined(CONFIG_ALPHA_MIATA) - /* check first for the built-in bridge */ - if ((PCI_SLOT(dev->bus->self->devfn) == 8) || - (PCI_SLOT(dev->bus->self->devfn) == 20)) { - slot = PCI_SLOT(dev->devfn) + 5; - DBG_DEVS(("MIATA: bus 1 slot %d pin %d" - " irq %d min_idsel %d\n", - PCI_SLOT(dev->devfn), pin, - irq_tab[slot - min_idsel][pin], - min_idsel)); - } - else /* must be a card-based bridge */ - { - do { - if ((PCI_SLOT(curr->bus->self->devfn) == 8) || - (PCI_SLOT(curr->bus->self->devfn) == 20)) - { - slot = PCI_SLOT(curr->devfn) + 5; - break; - } - /* swizzle */ - pin = bridge_swizzle( - pin, PCI_SLOT(curr->devfn)) ; - /* move up the chain of bridges */ - curr = curr->bus->self ; - /* slot of the next bridge. */ - slot = PCI_SLOT(curr->devfn); - } while (curr->bus->self) ; - } -#elif defined(CONFIG_ALPHA_NORITAKE) - /* check first for the built-in bridge */ - if (PCI_SLOT(dev->bus->self->devfn) == 8) { - slot = PCI_SLOT(dev->devfn) + 15; /* WAG! */ - DBG_DEVS(("NORITAKE: bus 1 slot %d pin %d" - "irq %d min_idsel %ld\n", - PCI_SLOT(dev->devfn), pin, - irq_tab[slot - min_idsel][pin], - min_idsel)); - } - else /* must be a card-based bridge */ - { - do { - if (PCI_SLOT(curr->bus->self->devfn) == 8) { - slot = PCI_SLOT(curr->devfn) + 15; - break; - } - /* swizzle */ - pin = bridge_swizzle( - pin, PCI_SLOT(curr->devfn)) ; - /* move up the chain of bridges */ - curr = curr->bus->self ; - /* slot of the next bridge. */ - slot = PCI_SLOT(curr->devfn); - } while (curr->bus->self) ; - } -#else /* everyone but MIATA and NORITAKE */ - DBG_DEVS(("common_fixup: bus %d slot %d pin %d " - "irq %d min_idsel %ld\n", - curr->bus->number, - PCI_SLOT(dev->devfn), pin, - irq_tab[slot - min_idsel][pin], - min_idsel)); - do { - /* swizzle */ - pin = - bridge_swizzle(pin, PCI_SLOT(curr->devfn)); - /* move up the chain of bridges */ - curr = curr->bus->self; - } while (curr->bus->self); - /* The slot is the slot of the last bridge. */ - slot = PCI_SLOT(curr->devfn); -#endif -#ifdef CONFIG_ALPHA_SRM_SETUP - /* - * must make sure that SRM didn't screw up - * and allocate an address > 64K for I/O - * space behind a PCI-PCI bridge - */ - check_behind_io(dev); -#endif /* CONFIG_ALPHA_SRM_SETUP */ - } else { /* just a device on a primary bus */ - /* work out the slot */ - slot = PCI_SLOT(dev->devfn); - /* read the pin */ - pcibios_read_config_byte(dev->bus->number, - dev->devfn, - PCI_INTERRUPT_PIN, - &pin); - DBG_DEVS(("common_fixup: bus %d slot %d" - " pin %d irq %d min_idsel %ld\n", - dev->bus->number, slot, pin, - irq_tab[slot - min_idsel][pin], - min_idsel)); - /* cope with 0 and illegal */ - if (pin == 0 || pin > 4) - pin = 1; - } - if (irq_tab[slot - min_idsel][pin] != -1) - dev->irq = irq_tab[slot - min_idsel][pin]; -#ifdef CONFIG_ALPHA_RAWHIDE - dev->irq += - 24 * bus2hose[dev->bus->number]->pci_hose_index; -#endif /* RAWHIDE */ -#ifdef CONFIG_ALPHA_SRM - { - unsigned char irq_orig; - /* read the original SRM-set IRQ and tell */ - pcibios_read_config_byte(dev->bus->number, - dev->devfn, - PCI_INTERRUPT_LINE, - &irq_orig); - if (irq_orig != dev->irq) { - DBG_DEVS(("common_fixup: bus %d slot 0x%x " - "SRM IRQ 0x%x changed to 0x%x\n", - dev->bus->number,PCI_SLOT(dev->devfn), - irq_orig, dev->irq)); -#ifdef CONFIG_ALPHA_SRM_SETUP - irq_dev_to_reset[irq_reset_count] = dev; - irq_to_reset[irq_reset_count] = irq_orig; - irq_reset_count++; -#endif /* CONFIG_ALPHA_SRM_SETUP */ - } - } -#endif /* SRM */ + /* + * This device is not on the primary bus, we need + * to figure out which interrupt pin it will come + * in on. We know which slot it will come in on + * 'cos that slot is where the bridge is. Each + * time the interrupt line passes through a PCI-PCI + * bridge we must apply the swizzle function (see + * the inline static routine above). + */ + dev->irq = 0; - /* always tell the device, so the driver knows what is - * the real IRQ to use; the device does not use it. - */ - pcibios_write_config_byte(dev->bus->number, dev->devfn, - PCI_INTERRUPT_LINE, dev->irq); + pcibios_read_config_byte(dev->bus->number, dev->devfn, + PCI_INTERRUPT_PIN, &pin); + /* Cope with 0 and illegal. */ + if (pin == 0 || pin > 4) + pin = 1; + + if (!DEV_IS_ON_PRIMARY(dev)) { + /* Follow the chain of bridges, swizzling as we go. */ + + int spill = pin; + slot = (*swizzle)(dev, &spill); + pin = spill; + + /* Must make sure that SRM didn't screw up + and allocate an address > 64K for I/O + space behind a PCI-PCI bridge. */ + if (alpha_use_srm_setup) + check_behind_io(dev); + } else { + /* Just a device on a primary bus. */ + slot = PCI_SLOT(dev->devfn); + } - DBG_DEVS(("common_fixup: bus %d slot 0x%x" - " VID 0x%x DID 0x%x\n" - " int_slot 0x%x pin 0x%x" - " pirq 0x%x\n", - dev->bus->number, PCI_SLOT(dev->devfn), - dev->vendor, dev->device, - slot, pin, dev->irq)); + irq = (*map_irq)(dev, slot, pin); - /* - * if it's a VGA, enable its BIOS ROM at C0000 - */ - if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) { - /* but if its a Cirrus 543x/544x DISABLE it, */ - /* since enabling ROM disables the memory... */ - if ((dev->vendor == PCI_VENDOR_ID_CIRRUS) && - (dev->device >= 0x00a0) && - (dev->device <= 0x00ac)) { - pcibios_write_config_dword( - dev->bus->number, - dev->devfn, - PCI_ROM_ADDRESS, - 0x00000000); - } else { - pcibios_write_config_dword( - dev->bus->number, - dev->devfn, - PCI_ROM_ADDRESS, - 0x000c0000 | PCI_ROM_ADDRESS_ENABLE); - } - } - /* - * if it's a SCSI, disable its BIOS ROM - */ - if ((dev->class >> 8) == PCI_CLASS_STORAGE_SCSI) { - pcibios_write_config_dword(dev->bus->number, - dev->devfn, - PCI_ROM_ADDRESS, - 0x0000000); + DBG_DEVS(("common_pci_fixup: bus %d slot %d " + "pin %d irq %d\n", + dev->bus->number, slot, pin, irq)); + + if (irq != -1) + dev->irq = irq; + + if (alpha_using_srm) { + /* Read the original SRM-set IRQ and tell. */ + pcibios_read_config_byte(dev->bus->number, + dev->devfn, + PCI_INTERRUPT_LINE, + &irq_orig); + + if (irq_orig != dev->irq) { + struct reset_irq *r; + + DBG_DEVS(("common_pci_fixup: bus %d " + "slot 0x%x SRM IRQ 0x%x " + "changed to 0x%x\n", + dev->bus->number, + PCI_SLOT(dev->devfn), + irq_orig, dev->irq)); + + r = &srm_resets.irq[srm_resets.irq_count++]; + r->dev = dev; + r->irq = irq_orig; } } - } - if (ide_base) { - enable_ide(ide_base); - } -} - -/* - * The EB66+ is very similar to the EB66 except that it does not have - * the on-board NCR and Tulip chips. In the code below, I have used - * slot number to refer to the id select line and *not* the slot - * number used in the EB66+ documentation. However, in the table, - * I've given the slot number, the id select line and the Jxx number - * that's printed on the board. The interrupt pins from the PCI slots - * are wired into 3 interrupt summary registers at 0x804, 0x805 and - * 0x806 ISA. - * - * In the table, -1 means don't assign an IRQ number. This is usually - * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip. - */ -static inline void eb66p_fixup(void) -{ - static char irq_tab[5][5] __initlocaldata = { - /*INT INTA INTB INTC INTD */ - {16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J25 */ - {16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J26 */ - { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */ - {16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 9, slot 2, J27 */ - {16+3, 16+3, 16+8, 16+12, 16+6} /* IdSel 10, slot 3, J28 */ - }; - common_fixup(6, 10, 5, irq_tab, 0x398); -} + /* Always tell the device, so the driver knows what is + the real IRQ to use; the device does not use it. */ + pcibios_write_config_byte(dev->bus->number, dev->devfn, + PCI_INTERRUPT_LINE, dev->irq); -/* - * The PC164 and LX164 have 19 PCI interrupts, four from each of the four - * PCI slots, the SIO, PCI/IDE, and USB. - * - * Each of the interrupts can be individually masked. This is - * accomplished by setting the appropriate bit in the mask register. - * A bit is set by writing a "1" to the desired position in the mask - * register and cleared by writing a "0". There are 3 mask registers - * located at ISA address 804h, 805h and 806h. - * - * An I/O read at ISA address 804h, 805h, 806h will return the - * state of the 11 PCI interrupts and not the state of the MASKED - * interrupts. - * - * Note: A write to I/O 804h, 805h, and 806h the mask register will be - * updated. - * - * - * ISA DATA<7:0> - * ISA +--------------------------------------------------------------+ - * ADDRESS | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | - * +==============================================================+ - * 0x804 | INTB0 | USB | IDE | SIO | INTA3 |INTA2 | INTA1 | INTA0 | - * +--------------------------------------------------------------+ - * 0x805 | INTD0 | INTC3 | INTC2 | INTC1 | INTC0 |INTB3 | INTB2 | INTB1 | - * +--------------------------------------------------------------+ - * 0x806 | Rsrv | Rsrv | Rsrv | Rsrv | Rsrv |INTD3 | INTD2 | INTD1 | - * +--------------------------------------------------------------+ - * * Rsrv = reserved bits - * Note: The mask register is write-only. - * - * IdSel - * 5 32 bit PCI option slot 2 - * 6 64 bit PCI option slot 0 - * 7 64 bit PCI option slot 1 - * 8 Saturn I/O - * 9 32 bit PCI option slot 3 - * 10 USB - * 11 IDE - * - */ - -#if defined(CONFIG_ALPHA_PC164) || defined(CONFIG_ALPHA_LX164) -static inline void alphapc164_fixup(void) -{ - static char irq_tab[7][5] __initlocaldata = { - /*INT INTA INTB INTC INTD */ - { 16+2, 16+2, 16+9, 16+13, 16+17}, /* IdSel 5, slot 2, J20 */ - { 16+0, 16+0, 16+7, 16+11, 16+15}, /* IdSel 6, slot 0, J29 */ - { 16+1, 16+1, 16+8, 16+12, 16+16}, /* IdSel 7, slot 1, J26 */ - { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */ - { 16+3, 16+3, 16+10, 16+14, 16+18}, /* IdSel 9, slot 3, J19 */ - { 16+6, 16+6, 16+6, 16+6, 16+6}, /* IdSel 10, USB */ - { 16+5, 16+5, 16+5, 16+5, 16+5} /* IdSel 11, IDE */ - }; - - common_fixup(5, 11, 5, irq_tab, 0); - SMC93x_Init(); -} -#endif - -/* - * The AlphaPC64 is very similar to the EB66+ except that its slots - * are numbered differently. In the code below, I have used slot - * number to refer to the id select line and *not* the slot number - * used in the AlphaPC64 documentation. However, in the table, I've - * given the slot number, the id select line and the Jxx number that's - * printed on the board. The interrupt pins from the PCI slots are - * wired into 3 interrupt summary registers at 0x804, 0x805 and 0x806 - * ISA. - * - * In the table, -1 means don't assign an IRQ number. This is usually - * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip. - */ -static inline void cabriolet_fixup(void) -{ - static char irq_tab[5][5] __initlocaldata = { - /*INT INTA INTB INTC INTD */ - { 16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 5, slot 2, J21 */ - { 16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J19 */ - { 16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J20 */ - { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */ - { 16+3, 16+3, 16+8, 16+12, 16+16} /* IdSel 9, slot 3, J22 */ - }; - - common_fixup(5, 9, 5, irq_tab, 0x398); -} - - -/* - * Fixup configuration for EB66/EB64+ boards. - * - * Both these boards use the same interrupt summary scheme. There are - * two 8 bit external summary registers as follows: - * - * Summary @ 0x26: - * Bit Meaning - * 0 Interrupt Line A from slot 0 - * 1 Interrupt Line A from slot 1 - * 2 Interrupt Line B from slot 0 - * 3 Interrupt Line B from slot 1 - * 4 Interrupt Line C from slot 0 - * 5 Interrupt line from the two ISA PICs - * 6 Tulip (slot - * 7 NCR SCSI - * - * Summary @ 0x27 - * Bit Meaning - * 0 Interrupt Line C from slot 1 - * 1 Interrupt Line D from slot 0 - * 2 Interrupt Line D from slot 1 - * 3 RAZ - * 4 RAZ - * 5 RAZ - * 6 RAZ - * 7 RAZ - * - * The device to slot mapping looks like: - * - * Slot Device - * 5 NCR SCSI controller - * 6 PCI on board slot 0 - * 7 PCI on board slot 1 - * 8 Intel SIO PCI-ISA bridge chip - * 9 Tulip - DECchip 21040 Ethernet controller - * - * - * This two layered interrupt approach means that we allocate IRQ 16 and - * above for PCI interrupts. The IRQ relates to which bit the interrupt - * comes in on. This makes interrupt processing much easier. - */ -static inline void eb66_and_eb64p_fixup(void) -{ - static char irq_tab[5][5] __initlocaldata = { - /*INT INTA INTB INTC INTD */ - {16+7, 16+7, 16+7, 16+7, 16+7}, /* IdSel 5, slot ?, ?? */ - {16+0, 16+0, 16+2, 16+4, 16+9}, /* IdSel 6, slot ?, ?? */ - {16+1, 16+1, 16+3, 16+8, 16+10}, /* IdSel 7, slot ?, ?? */ - { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */ - {16+6, 16+6, 16+6, 16+6, 16+6}, /* IdSel 9, TULIP */ - }; - common_fixup(5, 9, 5, irq_tab, 0); -} - - -/* - * Fixup configuration for MIKASA (AlphaServer 1000) - * - * Summary @ 0x536: - * Bit Meaning - * 0 Interrupt Line A from slot 0 - * 1 Interrupt Line B from slot 0 - * 2 Interrupt Line C from slot 0 - * 3 Interrupt Line D from slot 0 - * 4 Interrupt Line A from slot 1 - * 5 Interrupt line B from slot 1 - * 6 Interrupt Line C from slot 1 - * 7 Interrupt Line D from slot 1 - * 8 Interrupt Line A from slot 2 - * 9 Interrupt Line B from slot 2 - *10 Interrupt Line C from slot 2 - *11 Interrupt Line D from slot 2 - *12 NCR 810 SCSI - *13 Power Supply Fail - *14 Temperature Warn - *15 Reserved - * - * The device to slot mapping looks like: - * - * Slot Device - * 6 NCR SCSI controller - * 7 Intel PCI-EISA bridge chip - * 11 PCI on board slot 0 - * 12 PCI on board slot 1 - * 13 PCI on board slot 2 - * - * - * This two layered interrupt approach means that we allocate IRQ 16 and - * above for PCI interrupts. The IRQ relates to which bit the interrupt - * comes in on. This makes interrupt processing much easier. - */ -static inline void mikasa_fixup(void) -{ - static char irq_tab[8][5] __initlocaldata = { - /*INT INTA INTB INTC INTD */ - {16+12, 16+12, 16+12, 16+12, 16+12}, /* IdSel 17, SCSI */ - { -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */ - { -1, -1, -1, -1, -1}, /* IdSel 19, ???? */ - { -1, -1, -1, -1, -1}, /* IdSel 20, ???? */ - { -1, -1, -1, -1, -1}, /* IdSel 21, ???? */ - { 16+0, 16+0, 16+1, 16+2, 16+3}, /* IdSel 22, slot 0 */ - { 16+4, 16+4, 16+5, 16+6, 16+7}, /* IdSel 23, slot 1 */ - { 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 24, slot 2 */ - }; - common_fixup(6, 13, 5, irq_tab, 0); -} - -/* - * Fixup configuration for NORITAKE (AlphaServer 1000A) - * - * This is also used for CORELLE (AlphaServer 800) - * and ALCOR Primo (AlphaStation 600A). - * - * Summary @ 0x542, summary register #1: - * Bit Meaning - * 0 All valid ints from summary regs 2 & 3 - * 1 QLOGIC ISP1020A SCSI - * 2 Interrupt Line A from slot 0 - * 3 Interrupt Line B from slot 0 - * 4 Interrupt Line A from slot 1 - * 5 Interrupt line B from slot 1 - * 6 Interrupt Line A from slot 2 - * 7 Interrupt Line B from slot 2 - * 8 Interrupt Line A from slot 3 - * 9 Interrupt Line B from slot 3 - *10 Interrupt Line A from slot 4 - *11 Interrupt Line B from slot 4 - *12 Interrupt Line A from slot 5 - *13 Interrupt Line B from slot 5 - *14 Interrupt Line A from slot 6 - *15 Interrupt Line B from slot 6 - * - * Summary @ 0x544, summary register #2: - * Bit Meaning - * 0 OR of all unmasked ints in SR #2 - * 1 OR of secondary bus ints - * 2 Interrupt Line C from slot 0 - * 3 Interrupt Line D from slot 0 - * 4 Interrupt Line C from slot 1 - * 5 Interrupt line D from slot 1 - * 6 Interrupt Line C from slot 2 - * 7 Interrupt Line D from slot 2 - * 8 Interrupt Line C from slot 3 - * 9 Interrupt Line D from slot 3 - *10 Interrupt Line C from slot 4 - *11 Interrupt Line D from slot 4 - *12 Interrupt Line C from slot 5 - *13 Interrupt Line D from slot 5 - *14 Interrupt Line C from slot 6 - *15 Interrupt Line D from slot 6 - * - * The device to slot mapping looks like: - * - * Slot Device - * 7 Intel PCI-EISA bridge chip - * 8 DEC PCI-PCI bridge chip - * 11 PCI on board slot 0 - * 12 PCI on board slot 1 - * 13 PCI on board slot 2 - * - * - * This two layered interrupt approach means that we allocate IRQ 16 and - * above for PCI interrupts. The IRQ relates to which bit the interrupt - * comes in on. This makes interrupt processing much easier. - */ -static inline void noritake_fixup(void) -{ - static char irq_tab[15][5] __initlocaldata = { - /*INT INTA INTB INTC INTD */ - /* note: IDSELs 16, 17, and 25 are CORELLE only */ - { 16+1, 16+1, 16+1, 16+1, 16+1}, /* IdSel 16, QLOGIC */ - { -1, -1, -1, -1, -1}, /* IdSel 17, S3 Trio64 */ - { -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */ - { -1, -1, -1, -1, -1}, /* IdSel 19, PPB */ - { -1, -1, -1, -1, -1}, /* IdSel 20, ???? */ - { -1, -1, -1, -1, -1}, /* IdSel 21, ???? */ - { 16+2, 16+2, 16+3, 32+2, 32+3}, /* IdSel 22, slot 0 */ - { 16+4, 16+4, 16+5, 32+4, 32+5}, /* IdSel 23, slot 1 */ - { 16+6, 16+6, 16+7, 32+6, 32+7}, /* IdSel 24, slot 2 */ - { 16+8, 16+8, 16+9, 32+8, 32+9}, /* IdSel 25, slot 3 */ - /* the following 5 are actually on PCI bus 1, which is */ - /* across the built-in bridge of the NORITAKE only */ - { 16+1, 16+1, 16+1, 16+1, 16+1}, /* IdSel 16, QLOGIC */ - { 16+8, 16+8, 16+9, 32+8, 32+9}, /* IdSel 17, slot 3 */ - {16+10, 16+10, 16+11, 32+10, 32+11}, /* IdSel 18, slot 4 */ - {16+12, 16+12, 16+13, 32+12, 32+13}, /* IdSel 19, slot 5 */ - {16+14, 16+14, 16+15, 32+14, 32+15}, /* IdSel 20, slot 6 */ - }; - common_fixup(5, 19, 5, irq_tab, 0); -} - -/* - * Fixup configuration for ALCOR and XLT (XL-300/366/433) - * - * Summary @ GRU_INT_REQ: - * Bit Meaning - * 0 Interrupt Line A from slot 2 - * 1 Interrupt Line B from slot 2 - * 2 Interrupt Line C from slot 2 - * 3 Interrupt Line D from slot 2 - * 4 Interrupt Line A from slot 1 - * 5 Interrupt line B from slot 1 - * 6 Interrupt Line C from slot 1 - * 7 Interrupt Line D from slot 1 - * 8 Interrupt Line A from slot 0 - * 9 Interrupt Line B from slot 0 - *10 Interrupt Line C from slot 0 - *11 Interrupt Line D from slot 0 - *12 Interrupt Line A from slot 4 - *13 Interrupt Line B from slot 4 - *14 Interrupt Line C from slot 4 - *15 Interrupt Line D from slot 4 - *16 Interrupt Line D from slot 3 - *17 Interrupt Line D from slot 3 - *18 Interrupt Line D from slot 3 - *19 Interrupt Line D from slot 3 - *20-30 Reserved - *31 EISA interrupt - * - * The device to slot mapping looks like: - * - * Slot Device - * 6 built-in TULIP (XLT only) - * 7 PCI on board slot 0 - * 8 PCI on board slot 3 - * 9 PCI on board slot 4 - * 10 PCEB (PCI-EISA bridge) - * 11 PCI on board slot 2 - * 12 PCI on board slot 1 - * - * - * This two layered interrupt approach means that we allocate IRQ 16 and - * above for PCI interrupts. The IRQ relates to which bit the interrupt - * comes in on. This makes interrupt processing much easier. - */ -static inline void alcor_fixup(void) -{ - static char irq_tab[7][5] __initlocaldata = { - /*INT INTA INTB INTC INTD */ - /* note: IDSEL 17 is XLT only */ - {16+13, 16+13, 16+13, 16+13, 16+13}, /* IdSel 17, TULIP */ - { 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 18, slot 0 */ - {16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 19, slot 3 */ - {16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 20, slot 4 */ - { -1, -1, -1, -1, -1}, /* IdSel 21, PCEB */ - { 16+0, 16+0, 16+1, 16+2, 16+3}, /* IdSel 22, slot 2 */ - { 16+4, 16+4, 16+5, 16+6, 16+7}, /* IdSel 23, slot 1 */ - }; - common_fixup(6, 12, 5, irq_tab, 0); -} - -/* - * Fixup configuration for ALPHA SABLE (2100) - 2100A is different ?? - * - * Summary Registers (536/53a/53c): - * Bit Meaning - *----------------- - * 0 PCI slot 0 - * 1 NCR810 (builtin) - * 2 TULIP (builtin) - * 3 mouse - * 4 PCI slot 1 - * 5 PCI slot 2 - * 6 keyboard - * 7 floppy - * 8 COM2 - * 9 parallel port - *10 EISA irq 3 - *11 EISA irq 4 - *12 EISA irq 5 - *13 EISA irq 6 - *14 EISA irq 7 - *15 COM1 - *16 EISA irq 9 - *17 EISA irq 10 - *18 EISA irq 11 - *19 EISA irq 12 - *20 EISA irq 13 - *21 EISA irq 14 - *22 NC - *23 IIC - * - * The device to slot mapping looks like: - * - * Slot Device - * 0 TULIP - * 1 SCSI - * 2 PCI-EISA bridge - * 3 none - * 4 none - * 5 none - * 6 PCI on board slot 0 - * 7 PCI on board slot 1 - * 8 PCI on board slot 2 - * - * - * This two layered interrupt approach means that we allocate IRQ 16 and - * above for PCI interrupts. The IRQ relates to which bit the interrupt - * comes in on. This makes interrupt processing much easier. - */ -/* - * NOTE: the IRQ assignments below are arbitrary, but need to be consistent - * with the values in the sable_irq_to_mask[] and sable_mask_to_irq[] tables - * in irq.c - */ -static inline void sable_fixup(void) -{ - static char irq_tab[9][5] __initlocaldata = { - /*INT INTA INTB INTC INTD */ - { 32+0, 32+0, 32+0, 32+0, 32+0}, /* IdSel 0, TULIP */ - { 32+1, 32+1, 32+1, 32+1, 32+1}, /* IdSel 1, SCSI */ - { -1, -1, -1, -1, -1}, /* IdSel 2, SIO */ - { -1, -1, -1, -1, -1}, /* IdSel 3, none */ - { -1, -1, -1, -1, -1}, /* IdSel 4, none */ - { -1, -1, -1, -1, -1}, /* IdSel 5, none */ - { 32+2, 32+2, 32+2, 32+2, 32+2}, /* IdSel 6, slot 0 */ - { 32+3, 32+3, 32+3, 32+3, 32+3}, /* IdSel 7, slot 1 */ - { 32+4, 32+4, 32+4, 32+4, 32+4}, /* IdSel 8, slot 2 */ - }; - common_fixup(0, 8, 5, irq_tab, 0); -} - -/* - * Fixup configuration for MIATA (EV56+PYXIS) - * - * Summary @ PYXIS_INT_REQ: - * Bit Meaning - * 0 Fan Fault - * 1 NMI - * 2 Halt/Reset switch - * 3 none - * 4 CID0 (Riser ID) - * 5 CID1 (Riser ID) - * 6 Interval timer - * 7 PCI-ISA Bridge - * 8 Ethernet - * 9 EIDE (deprecated, ISA 14/15 used) - *10 none - *11 USB - *12 Interrupt Line A from slot 4 - *13 Interrupt Line B from slot 4 - *14 Interrupt Line C from slot 4 - *15 Interrupt Line D from slot 4 - *16 Interrupt Line A from slot 5 - *17 Interrupt line B from slot 5 - *18 Interrupt Line C from slot 5 - *19 Interrupt Line D from slot 5 - *20 Interrupt Line A from slot 1 - *21 Interrupt Line B from slot 1 - *22 Interrupt Line C from slot 1 - *23 Interrupt Line D from slot 1 - *24 Interrupt Line A from slot 2 - *25 Interrupt Line B from slot 2 - *26 Interrupt Line C from slot 2 - *27 Interrupt Line D from slot 2 - *27 Interrupt Line A from slot 3 - *29 Interrupt Line B from slot 3 - *30 Interrupt Line C from slot 3 - *31 Interrupt Line D from slot 3 - * - * The device to slot mapping looks like: - * - * Slot Device - * 3 DC21142 Ethernet - * 4 EIDE CMD646 - * 5 none - * 6 USB - * 7 PCI-ISA bridge - * 8 PCI-PCI Bridge (SBU Riser) - * 9 none - * 10 none - * 11 PCI on board slot 4 (SBU Riser) - * 12 PCI on board slot 5 (SBU Riser) - * - * These are behind the bridge, so I'm not sure what to do... - * - * 13 PCI on board slot 1 (SBU Riser) - * 14 PCI on board slot 2 (SBU Riser) - * 15 PCI on board slot 3 (SBU Riser) - * - * - * This two layered interrupt approach means that we allocate IRQ 16 and - * above for PCI interrupts. The IRQ relates to which bit the interrupt - * comes in on. This makes interrupt processing much easier. - */ - -#ifdef CONFIG_ALPHA_MIATA -static inline void miata_fixup(void) -{ - static char irq_tab[18][5] __initlocaldata = { - /*INT INTA INTB INTC INTD */ - {16+ 8, 16+ 8, 16+ 8, 16+ 8, 16+ 8}, /* IdSel 14, DC21142 */ - { -1, -1, -1, -1, -1}, /* IdSel 15, EIDE */ - { -1, -1, -1, -1, -1}, /* IdSel 16, none */ - { -1, -1, -1, -1, -1}, /* IdSel 17, none */ -/* {16+11, 16+11, 16+11, 16+11, 16+11},*//* IdSel 17, USB ?? */ - { -1, -1, -1, -1, -1}, /* IdSel 18, PCI-ISA */ - { -1, -1, -1, -1, -1}, /* IdSel 19, PCI-PCI */ - { -1, -1, -1, -1, -1}, /* IdSel 20, none */ - { -1, -1, -1, -1, -1}, /* IdSel 21, none */ - {16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 22, slot 4 */ - {16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 23, slot 5 */ - /* The following are actually on bus 1, which is */ - /* across the builtin PCI-PCI bridge */ - {16+20, 16+20, 16+21, 16+22, 16+23}, /* IdSel 24, slot 1 */ - {16+24, 16+24, 16+25, 16+26, 16+27}, /* IdSel 25, slot 2 */ - {16+28, 16+28, 16+29, 16+30, 16+31}, /* IdSel 26, slot 3 */ - { -1, -1, -1, -1, -1}, /* IdSel 27, none */ - { -1, -1, -1, -1, -1}, /* IdSel 28, none */ - { -1, -1, -1, -1, -1}, /* IdSel 29, none */ - { -1, -1, -1, -1, -1}, /* IdSel 30, none */ - { -1, -1, -1, -1, -1}, /* IdSel 31, PCI-PCI */ - }; - common_fixup(3, 20, 5, irq_tab, 0); - SMC669_Init(); /* it might be a GL (fails harmlessly if not) */ - es1888_init(); -} -#endif - -/* - * Fixup configuration for SX164 (PCA56+PYXIS) - * - * Summary @ PYXIS_INT_REQ: - * Bit Meaning - * 0 RSVD - * 1 NMI - * 2 Halt/Reset switch - * 3 MBZ - * 4 RAZ - * 5 RAZ - * 6 Interval timer (RTC) - * 7 PCI-ISA Bridge - * 8 Interrupt Line A from slot 3 - * 9 Interrupt Line A from slot 2 - *10 Interrupt Line A from slot 1 - *11 Interrupt Line A from slot 0 - *12 Interrupt Line B from slot 3 - *13 Interrupt Line B from slot 2 - *14 Interrupt Line B from slot 1 - *15 Interrupt line B from slot 0 - *16 Interrupt Line C from slot 3 - *17 Interrupt Line C from slot 2 - *18 Interrupt Line C from slot 1 - *19 Interrupt Line C from slot 0 - *20 Interrupt Line D from slot 3 - *21 Interrupt Line D from slot 2 - *22 Interrupt Line D from slot 1 - *23 Interrupt Line D from slot 0 - * - * IdSel - * 5 32 bit PCI option slot 2 - * 6 64 bit PCI option slot 0 - * 7 64 bit PCI option slot 1 - * 8 Cypress I/O - * 9 32 bit PCI option slot 3 - * - */ - -static inline void sx164_fixup(void) -{ - static char irq_tab[5][5] __initlocaldata = { - /*INT INTA INTB INTC INTD */ - { 16+ 9, 16+ 9, 16+13, 16+17, 16+21}, /* IdSel 5 slot 2 J17 */ - { 16+11, 16+11, 16+15, 16+19, 16+23}, /* IdSel 6 slot 0 J19 */ - { 16+10, 16+10, 16+14, 16+18, 16+22}, /* IdSel 7 slot 1 J18 */ - { -1, -1, -1, -1, -1}, /* IdSel 8 SIO */ - { 16+ 8, 16+ 8, 16+12, 16+16, 16+20} /* IdSel 9 slot 3 J15 */ - }; - common_fixup(5, 9, 5, irq_tab, 0); - SMC669_Init(); -} - -/* - * Fixup configuration for DP264 (EV6+TSUNAMI) - * - * Summary @ TSUNAMI_CSR_DIM0: - * Bit Meaning - * 0-17 Unused - *18 Interrupt SCSI B (Adaptec 7895 builtin) - *19 Interrupt SCSI A (Adaptec 7895 builtin) - *20 Interrupt Line D from slot 2 PCI0 - *21 Interrupt Line C from slot 2 PCI0 - *22 Interrupt Line B from slot 2 PCI0 - *23 Interrupt Line A from slot 2 PCI0 - *24 Interrupt Line D from slot 1 PCI0 - *25 Interrupt Line C from slot 1 PCI0 - *26 Interrupt Line B from slot 1 PCI0 - *27 Interrupt Line A from slot 1 PCI0 - *28 Interrupt Line D from slot 0 PCI0 - *29 Interrupt Line C from slot 0 PCI0 - *30 Interrupt Line B from slot 0 PCI0 - *31 Interrupt Line A from slot 0 PCI0 - * - *32 Interrupt Line D from slot 3 PCI1 - *33 Interrupt Line C from slot 3 PCI1 - *34 Interrupt Line B from slot 3 PCI1 - *35 Interrupt Line A from slot 3 PCI1 - *36 Interrupt Line D from slot 2 PCI1 - *37 Interrupt Line C from slot 2 PCI1 - *38 Interrupt Line B from slot 2 PCI1 - *39 Interrupt Line A from slot 2 PCI1 - *40 Interrupt Line D from slot 1 PCI1 - *41 Interrupt Line C from slot 1 PCI1 - *42 Interrupt Line B from slot 1 PCI1 - *43 Interrupt Line A from slot 1 PCI1 - *44 Interrupt Line D from slot 0 PCI1 - *45 Interrupt Line C from slot 0 PCI1 - *46 Interrupt Line B from slot 0 PCI1 - *47 Interrupt Line A from slot 0 PCI1 - *48-52 Unused - *53 PCI0 NMI (from Cypress) - *54 PCI0 SMI INT (from Cypress) - *55 PCI0 ISA Interrupt (from Cypress) - *56-60 Unused - *61 PCI1 Bus Error - *62 PCI0 Bus Error - *63 Reserved - * - * IdSel - * 5 Cypress Bridge I/O - * 6 SCSI Adaptec builtin - * 7 64 bit PCI option slot 0 - * 8 64 bit PCI option slot 1 - * 9 64 bit PCI option slot 2 - * - */ - -static inline void dp264_fixup(void) -{ - static char irq_tab[5][5] __initlocaldata = { - /*INT INTA INTB INTC INTD */ - { -1, -1, -1, -1, -1}, /* IdSel 5 ISA Bridge */ - { 16+ 2, 16+ 2, 16+ 2, 16+ 2, 16+ 2}, /* IdSel 6 SCSI builtin */ - { 16+15, 16+15, 16+14, 16+13, 16+12}, /* IdSel 7 slot 0 */ - { 16+11, 16+11, 16+10, 16+ 9, 16+ 8}, /* IdSel 8 slot 1 */ - { 16+ 7, 16+ 7, 16+ 6, 16+ 5, 16+ 4} /* IdSel 9 slot 2 */ - }; - common_fixup(5, 9, 5, irq_tab, 0); - SMC669_Init(); -} - -/* - * Fixup configuration for RAWHIDE - * - * Summary @ MCPCIA_PCI0_INT_REQ: - * Bit Meaning - *0 Interrupt Line A from slot 2 PCI0 - *1 Interrupt Line B from slot 2 PCI0 - *2 Interrupt Line C from slot 2 PCI0 - *3 Interrupt Line D from slot 2 PCI0 - *4 Interrupt Line A from slot 3 PCI0 - *5 Interrupt Line B from slot 3 PCI0 - *6 Interrupt Line C from slot 3 PCI0 - *7 Interrupt Line D from slot 3 PCI0 - *8 Interrupt Line A from slot 4 PCI0 - *9 Interrupt Line B from slot 4 PCI0 - *10 Interrupt Line C from slot 4 PCI0 - *11 Interrupt Line D from slot 4 PCI0 - *12 Interrupt Line A from slot 5 PCI0 - *13 Interrupt Line B from slot 5 PCI0 - *14 Interrupt Line C from slot 5 PCI0 - *15 Interrupt Line D from slot 5 PCI0 - *16 EISA interrupt (PCI 0) or SCSI interrupt (PCI 1) - *17-23 NA - * - * IdSel - * 1 EISA bridge (PCI bus 0 only) - * 2 PCI option slot 2 - * 3 PCI option slot 3 - * 4 PCI option slot 4 - * 5 PCI option slot 5 - * - */ - -static inline void rawhide_fixup(void) -{ - static char irq_tab[5][5] __initlocaldata = { - /*INT INTA INTB INTC INTD */ - { 16+16, 16+16, 16+16, 16+16, 16+16}, /* IdSel 1 SCSI PCI 1 only */ - { 16+ 0, 16+ 0, 16+ 1, 16+ 2, 16+ 3}, /* IdSel 2 slot 2 */ - { 16+ 4, 16+ 4, 16+ 5, 16+ 6, 16+ 7}, /* IdSel 3 slot 3 */ - { 16+ 8, 16+ 8, 16+ 9, 16+10, 16+11}, /* IdSel 4 slot 4 */ - { 16+12, 16+12, 16+13, 16+14, 16+15} /* IdSel 5 slot 5 */ - }; - common_fixup(1, 5, 5, irq_tab, 0); -} - -/* - * The Takara has PCI devices 1, 2, and 3 configured to slots 20, - * 19, and 18 respectively, in the default configuration. They can - * also be jumpered to slots 8, 7, and 6 respectively, which is fun - * because the SIO ISA bridge can also be slot 7. However, the SIO - * doesn't explicitly generate PCI-type interrupts, so we can - * assign it whatever the hell IRQ we like and it doesn't matter. - */ -static inline void takara_fixup(void) -{ - static char irq_tab[15][5] __initlocaldata = { - { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 6 == device 3 */ - { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 7 == device 2 */ - { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 8 == device 1 */ - { -1, -1, -1, -1, -1}, /* slot 9 == nothing */ - { -1, -1, -1, -1, -1}, /* slot 10 == nothing */ - { -1, -1, -1, -1, -1}, /* slot 11 == nothing */ - { -1, -1, -1, -1, -1}, /* slot 12 == nothing */ - { -1, -1, -1, -1, -1}, /* slot 13 == nothing */ - { -1, -1, -1, -1, -1}, /* slot 14 == nothing */ - { -1, -1, -1, -1, -1}, /* slot 15 == nothing */ - { -1, -1, -1, -1, -1}, /* slot 16 == nothing */ - { -1, -1, -1, -1, -1}, /* slot 17 == nothing */ - { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 18 == device 3 */ - { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 19 == device 2 */ - { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 20 == device 1 */ - }; - common_fixup(6, 20, 5, irq_tab, 0x26e); -} - -/* - * Fixup configuration for all boards that route the PCI interrupts - * through the SIO PCI/ISA bridge. This includes Noname (AXPpci33), - * Avanti (AlphaStation) and Kenetics's Platform 2000. - */ -static inline void sio_fixup(void) -{ - struct pci_dev *dev; - /* - * The Noname board has 5 PCI slots with each of the 4 - * interrupt pins routed to different pins on the PCI/ISA - * bridge (PIRQ0-PIRQ3). The table below is based on - * information available at: - * - * http://ftp.digital.com/pub/DEC/axppci/ref_interrupts.txt - * - * I have no information on the Avanti interrupt routing, but - * the routing seems to be identical to the Noname except - * that the Avanti has an additional slot whose routing I'm - * unsure of. - * - * pirq_tab[0] is a fake entry to deal with old PCI boards - * that have the interrupt pin number hardwired to 0 (meaning - * that they use the default INTA line, if they are interrupt - * driven at all). - */ - static const char pirq_tab[][5] __initlocaldata = { - /*INT A B C D */ -#ifdef CONFIG_ALPHA_P2K - { 0, 0, -1, -1, -1}, /* idsel 6 (53c810) */ - {-1, -1, -1, -1, -1}, /* idsel 7 (SIO: PCI/ISA bridge) */ - { 1, 1, 2, 3, 0}, /* idsel 8 (slot A) */ - { 2, 2, 3, 0, 1}, /* idsel 9 (slot B) */ - {-1, -1, -1, -1, -1}, /* idsel 10 (unused) */ - {-1, -1, -1, -1, -1}, /* idsel 11 (unused) */ - { 3, 3, -1, -1, -1}, /* idsel 12 (CMD0646) */ -#else - { 3, 3, 3, 3, 3}, /* idsel 6 (53c810) */ - {-1, -1, -1, -1, -1}, /* idsel 7 (SIO: PCI/ISA bridge) */ - { 2, 2, -1, -1, -1}, /* idsel 8 (Noname hack: slot closest to ISA) */ - {-1, -1, -1, -1, -1}, /* idsel 9 (unused) */ - {-1, -1, -1, -1, -1}, /* idsel 10 (unused) */ - { 0, 0, 2, 1, 0}, /* idsel 11 KN25_PCI_SLOT0 */ - { 1, 1, 0, 2, 1}, /* idsel 12 KN25_PCI_SLOT1 */ - { 2, 2, 1, 0, 2}, /* idsel 13 KN25_PCI_SLOT2 */ - { 0, 0, 0, 0, 0}, /* idsel 14 AS255 TULIP */ -#endif - }; - const size_t pirq_tab_len = sizeof(pirq_tab)/sizeof(pirq_tab[0]); - - /* - * route_tab selects irq routing in PCI/ISA bridge so that: - * PIRQ0 -> irq 15 - * PIRQ1 -> irq 9 - * PIRQ2 -> irq 10 - * PIRQ3 -> irq 11 - * - * This probably ought to be configurable via MILO. For - * example, sound boards seem to like using IRQ 9. - */ - -#if defined(CONFIG_ALPHA_BOOK1) - /* for the AlphaBook1, NCR810 SCSI is 14, PCMCIA controller is 15 */ - const unsigned int new_route_tab = 0x0e0f0a0a; - -#elif defined(CONFIG_ALPHA_NONAME) - /* - * For UDB, the only available PCI slot must not map to IRQ 9, - * since that's the builtin MSS sound chip. That PCI slot - * will map to PIRQ1 (for INTA at least), so we give it IRQ 15 - * instead. - * - * Unfortunately we have to do this for NONAME as well, since - * they are co-indicated when the platform type "Noname" is - * selected... :-( - */ - const unsigned int new_route_tab = 0x0b0a0f09; -#else - const unsigned int new_route_tab = 0x0b0a090f; -#endif - unsigned int route_tab, old_route_tab; - unsigned int level_bits, old_level_bits; - unsigned char pin, slot; - int pirq; - - pcibios_read_config_dword(0, PCI_DEVFN(7, 0), 0x60, &old_route_tab); - DBG_DEVS(("sio_fixup: old pirq route table: 0x%08x\n", - old_route_tab)); -#if PCI_MODIFY - route_tab = new_route_tab; - pcibios_write_config_dword(0, PCI_DEVFN(7, 0), 0x60, route_tab); -#else - route_tab = old_route_tab; -#endif - - /* - * Go through all devices, fixing up irqs as we see fit: - */ - level_bits = 0; - for (dev = pci_devices; dev; dev = dev->next) { - if ((dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) && - (dev->class >> 8 != PCI_CLASS_BRIDGE_PCMCIA)) - continue; - - dev->irq = 0; - if (dev->bus->number != 0) { - struct pci_dev *curr = dev; - /* - * read the pin and do the PCI-PCI bridge - * interrupt pin swizzle - */ - pcibios_read_config_byte(dev->bus->number, dev->devfn, - PCI_INTERRUPT_PIN, &pin); - /* cope with 0 */ - if (pin == 0) - pin = 1; - /* follow the chain of bridges, swizzling as we go */ - do { - /* swizzle */ - pin = bridge_swizzle(pin, PCI_SLOT(curr->devfn)); - /* move up the chain of bridges */ - curr = curr->bus->self; - } while (curr->bus->self); - /* The slot is the slot of the last bridge. */ - slot = PCI_SLOT(curr->devfn); - } else { - /* work out the slot */ - slot = PCI_SLOT(dev->devfn); - /* read the pin */ - pcibios_read_config_byte(dev->bus->number, dev->devfn, - PCI_INTERRUPT_PIN, &pin); - } - - if (slot < 6 || slot >= 6 + pirq_tab_len) { - printk("bios32.sio_fixup: " - "weird, found device %04x:%04x in" - " non-existent slot %d!!\n", - dev->vendor, dev->device, slot); - continue; - } - pirq = pirq_tab[slot - 6][pin]; + DBG_DEVS(("common_pci_fixup: bus %d slot 0x%x" + " VID 0x%x DID 0x%x\n" + " int_slot 0x%x pin 0x%x" + " pirq 0x%x\n", + dev->bus->number, PCI_SLOT(dev->devfn), + dev->vendor, dev->device, + slot, pin, dev->irq)); - DBG_DEVS(("sio_fixup: bus %d slot 0x%x VID 0x%x DID 0x%x\n" - " int_slot 0x%x pin 0x%x pirq 0x%x\n", - dev->bus->number, PCI_SLOT(dev->devfn), dev->vendor, - dev->device, slot, pin, pirq)); /* - * if it's a VGA, enable its BIOS ROM at C0000 + * If it's a VGA, enable its BIOS ROM at C0000. */ if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) { - /* but if its a Cirrus 543x/544x DISABLE it, */ - /* since enabling ROM disables the memory... */ + /* But if its a Cirrus 543x/544x DISABLE it, + since enabling ROM disables the memory... */ if ((dev->vendor == PCI_VENDOR_ID_CIRRUS) && (dev->device >= 0x00a0) && (dev->device <= 0x00ac)) { @@ -1827,401 +964,37 @@ } else { pcibios_write_config_dword( dev->bus->number, - dev->devfn, - PCI_ROM_ADDRESS, - 0x000c0000 | PCI_ROM_ADDRESS_ENABLE); - } - } - if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { - continue; /* for now, displays get no IRQ */ - } - - if (pirq < 0) { - DBG_DEVS(("bios32.sio_fixup: " - "weird, device %04x:%04x coming in on" - " slot %d has no irq line!!\n", - dev->vendor, dev->device, slot)); - continue; - } - - dev->irq = (route_tab >> (8 * pirq)) & 0xff; - -#ifndef CONFIG_ALPHA_BOOK1 - /* do not set *ANY* level triggers for AlphaBook1 */ - /* must set the PCI IRQs to level triggered */ - level_bits |= (1 << dev->irq); -#endif /* !CONFIG_ALPHA_BOOK1 */ - -#if PCI_MODIFY - /* tell the device: */ - pcibios_write_config_byte(dev->bus->number, dev->devfn, - PCI_INTERRUPT_LINE, dev->irq); -#endif - -#ifdef CONFIG_ALPHA_BOOK1 - /* - * On the AlphaBook1, the PCMCIA chip (Cirrus 6729) - * is sensitive to PCI bus bursts, so we must DISABLE - * burst mode for the NCR 8xx SCSI... :-( - * - * Note that the NCR810 SCSI driver must preserve the - * setting of the bit in order for this to work. At the - * moment (2.0.29), ncr53c8xx.c does NOT do this, but - * 53c7,8xx.c DOES. - */ - if (dev->vendor == PCI_VENDOR_ID_NCR && - (dev->device == PCI_DEVICE_ID_NCR_53C810 || - dev->device == PCI_DEVICE_ID_NCR_53C815 || - dev->device == PCI_DEVICE_ID_NCR_53C820 || - dev->device == PCI_DEVICE_ID_NCR_53C825)) { - unsigned int io_port; - unsigned char ctest4; - - pcibios_read_config_dword(dev->bus->number, - dev->devfn, - PCI_BASE_ADDRESS_0, - &io_port); - io_port &= PCI_BASE_ADDRESS_IO_MASK; - ctest4 = inb(io_port+0x21); - if (!(ctest4 & 0x80)) { - printk("AlphaBook1 NCR init: setting" - " burst disable\n"); - outb(ctest4 | 0x80, io_port+0x21); + dev->devfn, + PCI_ROM_ADDRESS, + 0x000c0000 | PCI_ROM_ADDRESS_ENABLE); } - } -#endif /* CONFIG_ALPHA_BOOK1 */ - } /* end for-devs */ - - /* - * Now, make all PCI interrupts level sensitive. Notice: - * these registers must be accessed byte-wise. inw()/outw() - * don't work. - * - * Make sure to turn off any level bits set for IRQs 9,10,11,15, - * so that the only bits getting set are for devices actually found. - * Note that we do preserve the remainder of the bits, which we hope - * will be set correctly by ARC/SRM. - * - * Note: we at least preserve any level-set bits on AlphaBook1 - */ - old_level_bits = inb(0x4d0) | (inb(0x4d1) << 8); - DBG_DEVS(("sio_fixup: old irq level bits: 0x%04x\n", - old_level_bits)); - level_bits |= (old_level_bits & 0x71ff); - DBG_DEVS(("sio_fixup: new irq level bits: 0x%04x\n", - level_bits)); - outb((level_bits >> 0) & 0xff, 0x4d0); - outb((level_bits >> 8) & 0xff, 0x4d1); - -#ifdef CONFIG_ALPHA_BOOK1 - { - unsigned char orig, config; - /* On the AlphaBook1, make sure that register PR1 - indicates 1Mb mem */ - outb(0x0f, 0x3ce); orig = inb(0x3cf); /* read PR5 */ - outb(0x0f, 0x3ce); outb(0x05, 0x3cf); /* unlock PR0-4 */ - outb(0x0b, 0x3ce); config = inb(0x3cf); /* read PR1 */ - if ((config & 0xc0) != 0xc0) { - printk("AlphaBook1 VGA init: setting 1Mb memory\n"); - config |= 0xc0; - outb(0x0b, 0x3ce); outb(config, 0x3cf); /* write PR1 */ } - outb(0x0f, 0x3ce); outb(orig, 0x3cf); /* (re)lock PR0-4 */ - } -#endif /* CONFIG_ALPHA_BOOK1 */ - -#ifndef CONFIG_ALPHA_BOOK1 - /* Do not do IDE init for AlphaBook1 */ - enable_ide(0x26e); -#endif -} - - -__initfunc(void -pcibios_fixup(void)) -{ - struct pci_bus *cur; - -#ifdef CONFIG_ALPHA_MCPCIA - /* must do massive setup for multiple PCI busses here... */ - DBG_DEVS(("pcibios_fixup: calling mcpcia_fixup()...\n")); - mcpcia_fixup(); -#endif /* MCPCIA */ - -#ifdef CONFIG_ALPHA_TSUNAMI - /* must do massive setup for multiple PCI busses here... */ - /* tsunami_fixup(); */ -#endif /* TSUNAMI */ - -#if PCI_MODIFY && !defined(CONFIG_ALPHA_RUFFIAN) - /* - * Scan the tree, allocating PCI memory and I/O space. - */ - /* - * Sigh; check_region() will need changing to accept a HANDLE, - * if we allocate I/O space addresses on a per-bus basis. - * For now, make the I/O bases unique across all busses, so - * that check_region() will not get confused... ;-} - */ - io_base = DEFAULT_IO_BASE; - for (cur = &pci_root; cur; cur = cur->next) { - mem_base = DEFAULT_MEM_BASE; - DBG_DEVS(("pcibios_fixup: calling layout_bus()\n")); - layout_bus(cur); - } -#endif - - /* - * Now is the time to do all those dirty little deeds... - */ -#if defined(CONFIG_ALPHA_NONAME) || defined(CONFIG_ALPHA_AVANTI) || \ - defined(CONFIG_ALPHA_P2K) - sio_fixup(); -#elif defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB164) - cabriolet_fixup(); -#elif defined(CONFIG_ALPHA_PC164) || defined(CONFIG_ALPHA_LX164) - alphapc164_fixup(); -#elif defined(CONFIG_ALPHA_EB66P) - eb66p_fixup(); -#elif defined(CONFIG_ALPHA_EB66) - eb66_and_eb64p_fixup(); -#elif defined(CONFIG_ALPHA_EB64P) - eb66_and_eb64p_fixup(); -#elif defined(CONFIG_ALPHA_MIKASA) - mikasa_fixup(); -#elif defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT) - alcor_fixup(); -#elif defined(CONFIG_ALPHA_SABLE) - sable_fixup(); -#elif defined(CONFIG_ALPHA_MIATA) - miata_fixup(); -#elif defined(CONFIG_ALPHA_NORITAKE) - noritake_fixup(); -#elif defined(CONFIG_ALPHA_SX164) - sx164_fixup(); -#elif defined(CONFIG_ALPHA_DP264) - dp264_fixup(); -#elif defined(CONFIG_ALPHA_RAWHIDE) - rawhide_fixup(); -#elif defined(CONFIG_ALPHA_TAKARA) - takara_fixup(); -#elif defined(CONFIG_ALPHA_RUFFIAN) - /* no fixup needed */ -#else -# error "You must tell me what kind of platform you want." -#endif -} - - -__initfunc(void -pcibios_fixup_bus(struct pci_bus *bus)) -{ -} - - -asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn, - unsigned long off, unsigned long len, - unsigned char *buf) -{ - unsigned char ubyte; - unsigned short ushort; - unsigned int uint; - long err = 0; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - lock_kernel(); - switch (len) { - case 1: - err = pcibios_read_config_byte(bus, dfn, off, &ubyte); - if (err != PCIBIOS_SUCCESSFUL) - ubyte = 0xff; - put_user(ubyte, buf); - break; - case 2: - err = pcibios_read_config_word(bus, dfn, off, &ushort); - if (err != PCIBIOS_SUCCESSFUL) - ushort = 0xffff; - put_user(ushort, (unsigned short *)buf); - break; - case 4: - err = pcibios_read_config_dword(bus, dfn, off, &uint); - if (err != PCIBIOS_SUCCESSFUL) - uint = 0xffffffff; - put_user(uint, (unsigned int *)buf); - break; - default: - err = -EINVAL; - break; - } - unlock_kernel(); - return err; -} - - -asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn, - unsigned long off, unsigned long len, - unsigned char *buf) -{ - unsigned char ubyte; - unsigned short ushort; - unsigned int uint; - long err = 0; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - lock_kernel(); - switch (len) { - case 1: - err = get_user(ubyte, buf); - if (err) - break; - err = pcibios_write_config_byte(bus, dfn, off, ubyte); - if (err != PCIBIOS_SUCCESSFUL) { - err = -EFAULT; - } - break; - case 2: - err = get_user(ushort, (unsigned short *)buf); - if (err) - break; - err = pcibios_write_config_word(bus, dfn, off, ushort); - if (err != PCIBIOS_SUCCESSFUL) { - err = -EFAULT; - } - break; - case 4: - err = get_user(uint, (unsigned int *)buf); - if (err) - break; - err = pcibios_write_config_dword(bus, dfn, off, uint); - if (err != PCIBIOS_SUCCESSFUL) { - err = -EFAULT; + /* + * If it's a SCSI, disable its BIOS ROM. + */ + if ((dev->class >> 8) == PCI_CLASS_STORAGE_SCSI) { + pcibios_write_config_dword(dev->bus->number, + dev->devfn, + PCI_ROM_ADDRESS, + 0x0000000); } - break; - default: - err = -EINVAL; - break; } - unlock_kernel(); - return err; } -#if (defined(CONFIG_ALPHA_PC164) || \ - defined(CONFIG_ALPHA_LX164) || \ - defined(CONFIG_ALPHA_SX164) || \ - defined(CONFIG_ALPHA_EB164) || \ - defined(CONFIG_ALPHA_EB66P) || \ - defined(CONFIG_ALPHA_CABRIOLET)) && defined(CONFIG_ALPHA_SRM) +/* Most Alphas have straight-forward swizzling needs. */ -/* - on the above machines, under SRM console, we must use the CSERVE PALcode - routine to manage the interrupt mask for us, otherwise, the kernel/HW get - out of sync with what the PALcode thinks it needs to deliver/ignore - */ -void -cserve_update_hw(unsigned long irq, unsigned long mask) +int __init +common_swizzle(struct pci_dev *dev, int *pinp) { - extern void cserve_ena(unsigned long); - extern void cserve_dis(unsigned long); + int pin = *pinp; + do { + pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); + /* Move up the chain of bridges. */ + dev = dev->bus->self; + } while (dev->bus->self); + *pinp = pin; - if (mask & (1UL << irq)) - /* disable */ - cserve_dis(irq - 16); - else - /* enable */ - cserve_ena(irq - 16); - return; + /* The slot is the slot of the last bridge. */ + return PCI_SLOT(dev->devfn); } -#endif /* (PC164 || LX164 || SX164 || EB164 || CABRIO) && SRM */ - -#ifdef CONFIG_ALPHA_MIATA -/* - * Init the built-in ES1888 sound chip (SB16 compatible) - */ -static int __init -es1888_init(void) -{ - /* Sequence of IO reads to init the audio controller */ - inb(0x0229); - inb(0x0229); - inb(0x0229); - inb(0x022b); - inb(0x0229); - inb(0x022b); - inb(0x0229); - inb(0x0229); - inb(0x022b); - inb(0x0229); - inb(0x0220); /* This sets the base address to 0x220 */ - - /* Sequence to set DMA channels */ - outb(0x01, 0x0226); /* reset */ - inb(0x0226); /* pause */ - outb(0x00, 0x0226); /* release reset */ - while (!(inb(0x022e) & 0x80)) /* wait for bit 7 to assert*/ - continue; - inb(0x022a); /* pause */ - outb(0xc6, 0x022c); /* enable extended mode */ - while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */ - continue; - outb(0xb1, 0x022c); /* setup for write to Interrupt CR */ - while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */ - continue; - outb(0x14, 0x022c); /* set IRQ 5 */ - while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */ - continue; - outb(0xb2, 0x022c); /* setup for write to DMA CR */ - while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */ - continue; - outb(0x18, 0x022c); /* set DMA channel 1 */ - - return 0; -} -#endif /* CONFIG_ALPHA_MIATA */ - -__initfunc(char *pcibios_setup(char *str)) -{ - return str; -} - -#ifdef CONFIG_ALPHA_SRM_SETUP -void reset_for_srm(void) -{ - struct pci_dev *dev; - int i; - - /* reset any IRQs that we changed */ - for (i = 0; i < irq_reset_count; i++) { - dev = irq_dev_to_reset[i]; - - pcibios_write_config_byte(dev->bus->number, dev->devfn, - PCI_INTERRUPT_LINE, irq_to_reset[i]); -#if 1 - printk("reset_for_srm: bus %d slot 0x%x " - "SRM IRQ 0x%x changed back from 0x%x\n", - dev->bus->number, PCI_SLOT(dev->devfn), - irq_to_reset[i], dev->irq); -#endif - } - - /* reset any IO addresses that we changed */ - for (i = 0; i < io_reset_count; i++) { - dev = io_dev_to_reset[i]; - - pcibios_write_config_byte(dev->bus->number, dev->devfn, - io_reg_to_reset[i], io_to_reset[i]); -#if 1 - printk("reset_for_srm: bus %d slot 0x%x " - "SRM IO restored to 0x%x\n", - dev->bus->number, PCI_SLOT(dev->devfn), - io_to_reset[i]); -#endif -} - /* FIXME: reset the video origin. */ -} -#endif /* CONFIG_ALPHA_SRM_SETUP */ - #endif /* CONFIG_PCI */ diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/bios32.h linux/arch/alpha/kernel/bios32.h --- v2.1.115/linux/arch/alpha/kernel/bios32.h Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/bios32.h Sun Aug 9 12:09:05 1998 @@ -0,0 +1,155 @@ +/* + * linux/arch/alpha/kernel/bios32.h + * + * This file contains declarations and inline functions for interfacing + * with the PCI initialization routines in bios32.c. + */ + + +#define KB 1024 +#define MB (1024*KB) +#define GB (1024*MB) + +/* + * We can't just blindly use 64K for machines with EISA busses; they + * may also have PCI-PCI bridges present, and then we'd configure the + * bridge incorrectly. + * + * Also, we start at 0x8000 or 0x9000, in hopes to get all devices' + * IO space areas allocated *before* 0xC000; this is because certain + * BIOSes (Millennium for one) use PCI Config space "mechanism #2" + * accesses to probe the bus. If a device's registers appear at 0xC000, + * it may see an INx/OUTx at that address during BIOS emulation of the + * VGA BIOS, and some cards, notably Adaptec 2940UW, take mortal offense. + * + * Note that we may need this stuff for SRM_SETUP also, since certain + * SRM consoles screw up and allocate I/O space addresses > 64K behind + * PCI-to_PCI bridges, which can't pass I/O addresses larger than 64K, + * AFAIK. + */ + +#define EISA_DEFAULT_IO_BASE 0x9000 /* start above 8th slot */ +#define DEFAULT_IO_BASE 0x8000 /* start at 8th slot */ + +/* + * An XL is AVANTI (APECS) family, *but* it has only 27 bits of ISA address + * that get passed through the PCI<->ISA bridge chip. Although this causes + * us to set the PCI->Mem window bases lower than normal, we still allocate + * PCI bus devices' memory addresses *below* the low DMA mapping window, + * and hope they fit below 64Mb (to avoid conflicts), and so that they can + * be accessed via SPARSE space. + * + * We accept the risk that a broken Myrinet card will be put into a true XL + * and thus can more easily run into the problem described below. + */ +#define XL_DEFAULT_MEM_BASE (16*MB + 2*MB) /* 16M to 64M-1 is avail */ + +/* + * We try to make this address *always* have more than 1 bit set. + * this is so that devices like the broken Myrinet card will always have + * a PCI memory address that will never match a IDSEL address in + * PCI Config space, which can cause problems with early rev cards. + * + * However, APECS and LCA have only 34 bits for physical addresses, thus + * limiting PCI bus memory addresses for SPARSE access to be less than 128Mb. + */ +#define APECS_AND_LCA_DEFAULT_MEM_BASE (64*MB + 2*MB) + +/* + * We try to make this address *always* have more than 1 bit set. + * this is so that devices like the broken Myrinet card will always have + * a PCI memory address that will never match a IDSEL address in + * PCI Config space, which can cause problems with early rev cards. + * + * Because CIA and PYXIS and T2 have more bits for physical addresses, + * they support an expanded range of SPARSE memory addresses. + */ +#define DEFAULT_MEM_BASE (128*MB + 16*MB) + + +/* + * PCI_MODIFY + * + * If this 0, then do not write to any of the PCI registers, merely + * read them (i.e., use configuration as determined by SRM). The SRM + * seem do be doing a less than perfect job in configuring PCI + * devices, so for now we do it ourselves. Reconfiguring PCI devices + * breaks console (RPB) callbacks, but those don't work properly with + * 64 bit addresses anyways. + * + * The accepted convention seems to be that the console (POST + * software) should fully configure boot devices and configure the + * interrupt routing of *all* devices. In particular, the base + * addresses of non-boot devices need not be initialized. For + * example, on the AXPpci33 board, the base address a #9 GXE PCI + * graphics card reads as zero (this may, however, be due to a bug in + * the graphics card---there have been some rumor that the #9 BIOS + * incorrectly resets that address to 0...). + */ + +#define PCI_MODIFY (!alpha_use_srm_setup) + + +/* + * A small note about bridges and interrupts. The DECchip 21050 (and + * later) adheres to the PCI-PCI bridge specification. This says that + * the interrupts on the other side of a bridge are swizzled in the + * following manner: + * + * Dev Interrupt Interrupt + * Pin on Pin on + * Device Connector + * + * 4 A A + * B B + * C C + * D D + * + * 5 A B + * B C + * C D + * D A + * + * 6 A C + * B D + * C A + * D B + * + * 7 A D + * B A + * C B + * D C + * + * Where A = pin 1, B = pin 2 and so on and pin=0 = default = A. + * Thus, each swizzle is ((pin-1) + (device#-4)) % 4 + * + * The following code swizzles for exactly one bridge. The routine + * common_swizzle below handles multiple bridges. But there are a + * couple boards that do strange things, so we define this here. + */ + +static inline unsigned char +bridge_swizzle(unsigned char pin, unsigned int slot) +{ + return (((pin-1) + slot) % 4) + 1; +} + +extern void layout_all_busses(unsigned long io_base, unsigned long mem_base); +extern void enable_ide(long ide_base); + +struct pci_dev; + +extern void +common_pci_fixup(int (*map_irq)(struct pci_dev *dev, int slot, int pin), + int (*swizzle)(struct pci_dev *dev, int *pin)); + +extern int common_swizzle(struct pci_dev *dev, int *pinp); + +/* The following macro is used to implement the table-based irq mapping + function for all single-bus Alphas. */ + +#define COMMON_TABLE_LOOKUP \ +({ long _ctl_ = -1; \ + if (slot >= min_idsel && slot <= max_idsel && pin < irqs_per_slot) \ + _ctl_ = irq_tab[slot - min_idsel][pin]; \ + _ctl_; }) diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/cia.c linux/arch/alpha/kernel/cia.c --- v2.1.115/linux/arch/alpha/kernel/cia.c Wed Jun 24 22:54:02 1998 +++ linux/arch/alpha/kernel/cia.c Wed Dec 31 16:00:00 1969 @@ -1,735 +0,0 @@ -/* - * Code common to all CIA chips. - * - * Written by David A Rusling (david.rusling@reo.mts.dec.com). - * December 1995. - * - */ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * NOTE: Herein lie back-to-back mb instructions. They are magic. - * One plausible explanation is that the i/o controller does not properly - * handle the system transaction. Another involves timing. Ho hum. - */ - -extern struct hwrpb_struct *hwrpb; -extern asmlinkage void wrmces(unsigned long mces); - -/* - * Machine check reasons. Defined according to PALcode sources - * (osf.h and platform.h). - */ -#define MCHK_K_TPERR 0x0080 -#define MCHK_K_TCPERR 0x0082 -#define MCHK_K_HERR 0x0084 -#define MCHK_K_ECC_C 0x0086 -#define MCHK_K_ECC_NC 0x0088 -#define MCHK_K_OS_BUGCHECK 0x008A -#define MCHK_K_PAL_BUGCHECK 0x0090 - -/* - * BIOS32-style PCI interface: - */ - -/* #define DEBUG_MCHECK */ -/* #define DEBUG_CONFIG */ -/* #define DEBUG_DUMP_REGS */ - -#ifdef DEBUG_MCHECK -# define DBGM(args) printk args -#else -# define DBGM(args) -#endif -#ifdef DEBUG_CONFIG -# define DBGC(args) printk args -#else -# define DBGC(args) -#endif - -#define vuip volatile unsigned int * - -static volatile unsigned int CIA_mcheck_expected = 0; -static volatile unsigned int CIA_mcheck_taken = 0; -static unsigned int CIA_jd; - -#ifdef CONFIG_ALPHA_SRM_SETUP -unsigned int CIA_DMA_WIN_BASE = CIA_DMA_WIN_BASE_DEFAULT; -unsigned int CIA_DMA_WIN_SIZE = CIA_DMA_WIN_SIZE_DEFAULT; -unsigned long cia_sm_base_r1, cia_sm_base_r2, cia_sm_base_r3; -#endif /* SRM_SETUP */ - -/* - * Given a bus, device, and function number, compute resulting - * configuration space address and setup the CIA_HAXR2 register - * accordingly. It is therefore not safe to have concurrent - * invocations to configuration space access routines, but there - * really shouldn't be any need for this. - * - * Type 0: - * - * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 - * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * 31:11 Device select bit. - * 10:8 Function number - * 7:2 Register number - * - * Type 1: - * - * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 - * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * 31:24 reserved - * 23:16 bus number (8 bits = 128 possible buses) - * 15:11 Device number (5 bits) - * 10:8 function number - * 7:2 register number - * - * Notes: - * The function number selects which function of a multi-function device - * (e.g., SCSI and Ethernet). - * - * The register selects a DWORD (32 bit) register offset. Hence it - * doesn't get shifted by 2 bits as we want to "drop" the bottom two - * bits. - */ -static int mk_conf_addr(unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned long *pci_addr, - unsigned char *type1) -{ - unsigned long addr; - - DBGC(("mk_conf_addr(bus=%d, device_fn=0x%x, where=0x%x, " - "pci_addr=0x%p, type1=0x%p)\n", - bus, device_fn, where, pci_addr, type1)); - - if (bus == 0) { - int device = device_fn >> 3; - - /* type 0 configuration cycle: */ - - if (device > 20) { - DBGC(("mk_conf_addr: device (%d) > 20, returning -1\n", - device)); - return -1; - } - - *type1 = 0; - addr = (device_fn << 8) | (where); - } else { - /* type 1 configuration cycle: */ - *type1 = 1; - addr = (bus << 16) | (device_fn << 8) | (where); - } - *pci_addr = addr; - DBGC(("mk_conf_addr: returning pci_addr 0x%lx\n", addr)); - return 0; -} - - -static unsigned int conf_read(unsigned long addr, unsigned char type1) -{ - unsigned long flags; - unsigned int stat0, value; - unsigned int cia_cfg = 0; /* to keep gcc quiet */ - - value = 0xffffffffU; - mb(); - - save_flags(flags); /* avoid getting hit by machine check */ - cli(); - - DBGC(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1)); - - /* reset status register to avoid losing errors: */ - stat0 = *(vuip)CIA_IOC_CIA_ERR; - *(vuip)CIA_IOC_CIA_ERR = stat0; - mb(); - DBGC(("conf_read: CIA ERR was 0x%x\n", stat0)); - /* if Type1 access, must set CIA CFG */ - if (type1) { - cia_cfg = *(vuip)CIA_IOC_CFG; - *(vuip)CIA_IOC_CFG = cia_cfg | 1; - mb(); - DBGC(("conf_read: TYPE1 access\n")); - } - - mb(); - draina(); - CIA_mcheck_expected = 1; - CIA_mcheck_taken = 0; - mb(); - /* access configuration space: */ - value = *(vuip)addr; - mb(); - mb(); /* magic */ - if (CIA_mcheck_taken) { - CIA_mcheck_taken = 0; - value = 0xffffffffU; - mb(); - } - CIA_mcheck_expected = 0; - mb(); - -#if 0 - /* - this code might be necessary if machine checks aren't taken, - but I can't get it to work on CIA-2, so its disabled. - */ - draina(); - - /* now look for any errors */ - stat0 = *(vuip)CIA_IOC_CIA_ERR; - DBGC(("conf_read: CIA ERR after read 0x%x\n", stat0)); - if (stat0 & 0x8FEF0FFFU) { /* is any error bit set? */ - /* if not MAS_ABT, print status */ - if (!(stat0 & 0x0080)) { - printk("CIA.c:conf_read: got stat0=%x\n", stat0); - } - - /* reset error status: */ - *(vuip)CIA_IOC_CIA_ERR = stat0; - mb(); - wrmces(0x7); /* reset machine check */ - value = 0xffffffff; - } -#endif - - /* if Type1 access, must reset IOC CFG so normal IO space ops work */ - if (type1) { - *(vuip)CIA_IOC_CFG = cia_cfg & ~1; - mb(); - } - - DBGC(("conf_read(): finished\n")); - - restore_flags(flags); - return value; -} - - -static void conf_write(unsigned long addr, unsigned int value, - unsigned char type1) -{ - unsigned long flags; - unsigned int stat0; - unsigned int cia_cfg = 0; /* to keep gcc quiet */ - - save_flags(flags); /* avoid getting hit by machine check */ - cli(); - - /* reset status register to avoid losing errors: */ - stat0 = *(vuip)CIA_IOC_CIA_ERR; - *(vuip)CIA_IOC_CIA_ERR = stat0; - mb(); - DBGC(("conf_write: CIA ERR was 0x%x\n", stat0)); - /* if Type1 access, must set CIA CFG */ - if (type1) { - cia_cfg = *(vuip)CIA_IOC_CFG; - *(vuip)CIA_IOC_CFG = cia_cfg | 1; - mb(); - DBGC(("conf_write: TYPE1 access\n")); - } - - draina(); - CIA_mcheck_expected = 1; - mb(); - /* access configuration space: */ - *(vuip)addr = value; - mb(); - mb(); /* magic */ - - CIA_mcheck_expected = 0; - mb(); - -#if 0 - /* - * This code might be necessary if machine checks aren't taken, - * but I can't get it to work on CIA-2, so its disabled. - */ - draina(); - - /* Now look for any errors */ - stat0 = *(vuip)CIA_IOC_CIA_ERR; - DBGC(("conf_write: CIA ERR after write 0x%x\n", stat0)); - if (stat0 & 0x8FEF0FFFU) { /* is any error bit set? */ - /* If not MAS_ABT, print status */ - if (!(stat0 & 0x0080)) { - printk("CIA.c:conf_read: got stat0=%x\n", stat0); - } - - /* reset error status: */ - *(vuip)CIA_IOC_CIA_ERR = stat0; - mb(); - wrmces(0x7); /* reset machine check */ - value = 0xffffffff; - } -#endif - - /* if Type1 access, must reset IOC CFG so normal IO space ops work */ - if (type1) { - *(vuip)CIA_IOC_CFG = cia_cfg & ~1; - mb(); - } - - DBGC(("conf_write(): finished\n")); - restore_flags(flags); -} - - -int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned char *value) -{ - unsigned long addr = CIA_CONF; - unsigned long pci_addr; - unsigned char type1; - - *value = 0xff; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - - addr |= (pci_addr << 5) + 0x00; - - *value = conf_read(addr, type1) >> ((where & 3) * 8); - - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_read_config_word (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short *value) -{ - unsigned long addr = CIA_CONF; - unsigned long pci_addr; - unsigned char type1; - - *value = 0xffff; - - if (where & 0x1) { - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) { - return PCIBIOS_SUCCESSFUL; - } - - addr |= (pci_addr << 5) + 0x08; - - *value = conf_read(addr, type1) >> ((where & 3) * 8); - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int *value) -{ - unsigned long addr = CIA_CONF; - unsigned long pci_addr; - unsigned char type1; - - *value = 0xffffffff; - if (where & 0x3) { - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x18; - *value = conf_read(addr, type1); - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned char value) -{ - unsigned long addr = CIA_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x00; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_write_config_word (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short value) -{ - unsigned long addr = CIA_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x08; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int value) -{ - unsigned long addr = CIA_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x18; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; -} - - -unsigned long cia_init(unsigned long mem_start, unsigned long mem_end) -{ - unsigned int cia_tmp; - -#ifdef DEBUG_DUMP_REGS - { - unsigned int temp; - temp = *(vuip)CIA_IOC_CIA_REV; mb(); - printk("CIA_init: CIA_REV was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_PCI_LAT; mb(); - printk("CIA_init: CIA_PCI_LAT was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_CIA_CTRL; mb(); - printk("CIA_init: CIA_CTRL was 0x%x\n", temp); - temp = *(vuip)0xfffffc8740000140UL; mb(); - printk("CIA_init: CIA_CTRL1 was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_HAE_MEM; mb(); - printk("CIA_init: CIA_HAE_MEM was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_HAE_IO; mb(); - printk("CIA_init: CIA_HAE_IO was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_CFG; mb(); - printk("CIA_init: CIA_CFG was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_CACK_EN; mb(); - printk("CIA_init: CIA_CACK_EN was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_CFG; mb(); - printk("CIA_init: CIA_CFG was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_CIA_DIAG; mb(); - printk("CIA_init: CIA_DIAG was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_DIAG_CHECK; mb(); - printk("CIA_init: CIA_DIAG_CHECK was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_PERF_MONITOR; mb(); - printk("CIA_init: CIA_PERF_MONITOR was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_PERF_CONTROL; mb(); - printk("CIA_init: CIA_PERF_CONTROL was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_CIA_ERR; mb(); - printk("CIA_init: CIA_ERR was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_CIA_STAT; mb(); - printk("CIA_init: CIA_STAT was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_MCR; mb(); - printk("CIA_init: CIA_MCR was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_CIA_CTRL; mb(); - printk("CIA_init: CIA_CTRL was 0x%x\n", temp); - temp = *(vuip)CIA_IOC_ERR_MASK; mb(); - printk("CIA_init: CIA_ERR_MASK was 0x%x\n", temp); - temp = *((vuip)CIA_IOC_PCI_W0_BASE); mb(); - printk("CIA_init: W0_BASE was 0x%x\n", temp); - temp = *((vuip)CIA_IOC_PCI_W1_BASE); mb(); - printk("CIA_init: W1_BASE was 0x%x\n", temp); - temp = *((vuip)CIA_IOC_PCI_W2_BASE); mb(); - printk("CIA_init: W2_BASE was 0x%x\n", temp); - temp = *((vuip)CIA_IOC_PCI_W3_BASE); mb(); - printk("CIA_init: W3_BASE was 0x%x\n", temp); - } -#endif /* DEBUG_DUMP_REGS */ - - /* - * Set up error reporting. - */ - cia_tmp = *(vuip)CIA_IOC_CIA_ERR; - cia_tmp |= 0x180; /* master, target abort */ - *(vuip)CIA_IOC_CIA_ERR = cia_tmp; - mb(); - - cia_tmp = *(vuip)CIA_IOC_CIA_CTRL; - cia_tmp |= 0x400; /* turn on FILL_ERR to get mchecks */ - *(vuip)CIA_IOC_CIA_CTRL = cia_tmp; - mb(); - -#ifdef CONFIG_ALPHA_SRM_SETUP - /* check window 0 for enabled and mapped to 0 */ - if (((*(vuip)CIA_IOC_PCI_W0_BASE & 3) == 1) && - (*(vuip)CIA_IOC_PCI_T0_BASE == 0)) - { - CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W0_BASE & 0xfff00000U; - CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W0_MASK & 0xfff00000U; - CIA_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("cia_init: using Window 0 settings\n"); - printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)CIA_IOC_PCI_W0_BASE, - *(vuip)CIA_IOC_PCI_W0_MASK, - *(vuip)CIA_IOC_PCI_T0_BASE); -#endif - } - else /* check window 1 for enabled and mapped to 0 */ - if (((*(vuip)CIA_IOC_PCI_W1_BASE & 3) == 1) && - (*(vuip)CIA_IOC_PCI_T1_BASE == 0)) - { - CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W1_BASE & 0xfff00000U; - CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W1_MASK & 0xfff00000U; - CIA_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("cia_init: using Window 1 settings\n"); - printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)CIA_IOC_PCI_W1_BASE, - *(vuip)CIA_IOC_PCI_W1_MASK, - *(vuip)CIA_IOC_PCI_T1_BASE); -#endif - } - else /* check window 2 for enabled and mapped to 0 */ - if (((*(vuip)CIA_IOC_PCI_W2_BASE & 3) == 1) && - (*(vuip)CIA_IOC_PCI_T2_BASE == 0)) - { - CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W2_BASE & 0xfff00000U; - CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W2_MASK & 0xfff00000U; - CIA_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("cia_init: using Window 2 settings\n"); - printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)CIA_IOC_PCI_W2_BASE, - *(vuip)CIA_IOC_PCI_W2_MASK, - *(vuip)CIA_IOC_PCI_T2_BASE); -#endif - } - else /* check window 3 for enabled and mapped to 0 */ - if (((*(vuip)CIA_IOC_PCI_W3_BASE & 3) == 1) && - (*(vuip)CIA_IOC_PCI_T3_BASE == 0)) - { - CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W3_BASE & 0xfff00000U; - CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W3_MASK & 0xfff00000U; - CIA_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("cia_init: using Window 3 settings\n"); - printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)CIA_IOC_PCI_W3_BASE, - *(vuip)CIA_IOC_PCI_W3_MASK, - *(vuip)CIA_IOC_PCI_T3_BASE); -#endif - } - else /* we must use our defaults which were pre-initialized... */ -#endif /* SRM_SETUP */ - { - /* - * Set up the PCI->physical memory translation windows. - * For now, windows 1,2 and 3 are disabled. In the future, we may - * want to use them to do scatter/gather DMA. Window 0 - * goes at 1 GB and is 1 GB large. - */ - - *(vuip)CIA_IOC_PCI_W0_BASE = 1U | (CIA_DMA_WIN_BASE & 0xfff00000U); - *(vuip)CIA_IOC_PCI_W0_MASK = (CIA_DMA_WIN_SIZE - 1) & 0xfff00000U; - *(vuip)CIA_IOC_PCI_T0_BASE = 0; - - *(vuip)CIA_IOC_PCI_W1_BASE = 0x0; - *(vuip)CIA_IOC_PCI_W2_BASE = 0x0; - *(vuip)CIA_IOC_PCI_W3_BASE = 0x0; - } - - /* - * check ASN in HWRPB for validity, report if bad - */ - if (hwrpb->max_asn != MAX_ASN) { - printk("CIA_init: max ASN from HWRPB is bad (0x%lx)\n", - hwrpb->max_asn); - hwrpb->max_asn = MAX_ASN; - } - - /* - * Next, clear the CIA_CFG register, which gets used - * for PCI Config Space accesses. That is the way - * we want to use it, and we do not want to depend on - * what ARC or SRM might have left behind... - */ - { - unsigned int cia_cfg = *((vuip)CIA_IOC_CFG); mb(); - if (cia_cfg) { - printk("CIA_init: CFG was 0x%x\n", cia_cfg); - *((vuip)CIA_IOC_CFG) = 0; mb(); - } - } - - { - unsigned int cia_hae_mem = *((vuip)CIA_IOC_HAE_MEM); - unsigned int cia_hae_io = *((vuip)CIA_IOC_HAE_IO); -#if 0 - printk("CIA_init: HAE_MEM was 0x%x\n", cia_hae_mem); - printk("CIA_init: HAE_IO was 0x%x\n", cia_hae_io); -#endif -#ifdef CONFIG_ALPHA_SRM_SETUP - /* - sigh... For the SRM setup, unless we know apriori what the HAE - contents will be, we need to setup the arbitrary region bases - so we can test against the range of addresses and tailor the - region chosen for the SPARSE memory access. - - see include/asm-alpha/cia.h for the SPARSE mem read/write - */ - cia_sm_base_r1 = (cia_hae_mem ) & 0xe0000000UL; /* region 1 */ - cia_sm_base_r2 = (cia_hae_mem << 16) & 0xf8000000UL; /* region 2 */ - cia_sm_base_r3 = (cia_hae_mem << 24) & 0xfc000000UL; /* region 3 */ - - /* - Set the HAE cache, so that setup_arch() code - will use the SRM setting always. Our readb/writeb - code in cia.h expects never to have to change - the contents of the HAE. - */ - hae.cache = cia_hae_mem; -#else /* SRM_SETUP */ - *((vuip)CIA_IOC_HAE_MEM) = 0; mb(); - cia_hae_mem = *((vuip)CIA_IOC_HAE_MEM); - *((vuip)CIA_IOC_HAE_IO) = 0; mb(); - cia_hae_io = *((vuip)CIA_IOC_HAE_IO); -#endif /* SRM_SETUP */ - } - - return mem_start; -} - -int cia_pci_clr_err(void) -{ - CIA_jd = *(vuip)CIA_IOC_CIA_ERR; - DBGM(("CIA_pci_clr_err: CIA ERR after read 0x%x\n", CIA_jd)); - *(vuip)CIA_IOC_CIA_ERR = 0x0180; - mb(); - return 0; -} - -void cia_machine_check(unsigned long vector, unsigned long la_ptr, - struct pt_regs * regs) -{ - struct el_common *mchk_header; - struct el_procdata *mchk_procdata; - struct el_CIA_sysdata_mcheck *mchk_sysdata; - unsigned long * ptr; - const char * reason; - char buf[128]; - long i; - - mchk_header = (struct el_common *)la_ptr; - mchk_procdata = (struct el_procdata *) - (la_ptr + mchk_header->proc_offset); - mchk_sysdata = (struct el_CIA_sysdata_mcheck *) - (la_ptr + mchk_header->sys_offset); - - DBGM(("cia_machine_check: vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr)); - DBGM((" pc=0x%lx size=0x%x procoffset=0x%x " - "sysoffset 0x%x\n", regs->pc, mchk_header->size, - mchk_header->proc_offset, mchk_header->sys_offset)); - DBGM(("cia_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n", - CIA_mcheck_expected, mchk_sysdata->epic_dcsr, - mchk_sysdata->epic_pear)); - -#ifdef DEBUG_MCHECK - { - unsigned long *ptr; - int i; - - ptr = (unsigned long *)la_ptr; - for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { - printk(" +%lx %lx %lx\n", i*sizeof(long), - ptr[i], ptr[i+1]); - } - } -#endif - - /* - * Check if machine check is due to a badaddr() and if so, - * ignore the machine check. - */ - mb(); - mb(); /* magic */ - if (CIA_mcheck_expected) { - DBGM(("CIA machine check expected\n")); - CIA_mcheck_expected = 0; - CIA_mcheck_taken = 1; - mb(); - mb(); /* magic */ - draina(); - cia_pci_clr_err(); - wrmces(0x7); - mb(); - return; - } - - switch ((unsigned int) mchk_header->code) { - case MCHK_K_TPERR: reason = "tag parity error"; break; - case MCHK_K_TCPERR: reason = "tag control parity error"; break; - case MCHK_K_HERR: reason = "generic hard error"; break; - case MCHK_K_ECC_C: reason = "correctable ECC error"; break; - case MCHK_K_ECC_NC: reason = "uncorrectable ECC error"; break; - case MCHK_K_OS_BUGCHECK: reason = "OS-specific PAL bugcheck"; break; - case MCHK_K_PAL_BUGCHECK: reason = "callsys in kernel mode"; break; - case 0x96: reason = "i-cache read retryable error"; break; - case 0x98: reason = "processor detected hard error"; break; - - /* system specific (these are for Alcor, at least): */ - case 0x203: reason = "system detected uncorrectable ECC error"; break; - case 0x205: reason = "parity error detected by CIA"; break; - case 0x207: reason = "non-existent memory error"; break; - case 0x209: reason = "PCI SERR detected"; break; - case 0x20b: reason = "PCI data parity error detected"; break; - case 0x20d: reason = "PCI address parity error detected"; break; - case 0x20f: reason = "PCI master abort error"; break; - case 0x211: reason = "PCI target abort error"; break; - case 0x213: reason = "scatter/gather PTE invalid error"; break; - case 0x215: reason = "flash ROM write error"; break; - case 0x217: reason = "IOA timeout detected"; break; - case 0x219: reason = "IOCHK#, EISA add-in board parity or other catastrophic error"; break; - case 0x21b: reason = "EISA fail-safe timer timeout"; break; - case 0x21d: reason = "EISA bus time-out"; break; - case 0x21f: reason = "EISA software generated NMI"; break; - case 0x221: reason = "unexpected ev5 IRQ[3] interrupt"; break; - default: - sprintf(buf, "reason for machine-check unknown (0x%x)", - (unsigned int) mchk_header->code); - reason = buf; - break; - } - wrmces(rdmces()); /* reset machine check pending flag */ - mb(); - - printk(KERN_CRIT " CIA machine check: %s%s\n", - reason, mchk_header->retry ? " (retryable)" : ""); - printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx pc=0x%lx\n", - vector, la_ptr, regs->pc); - - /* dump the logout area to give all info: */ - - ptr = (unsigned long *)la_ptr; - for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { - printk(KERN_CRIT " +%8lx %016lx %016lx\n", - i*sizeof(long), ptr[i], ptr[i+1]); - } -} diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/core_apecs.c linux/arch/alpha/kernel/core_apecs.c --- v2.1.115/linux/arch/alpha/kernel/core_apecs.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/core_apecs.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,542 @@ +/* + * linux/arch/alpha/kernel/core_apecs.c + * + * Code common to all APECS core logic chips. + * + * Rewritten for Apecs from the lca.c from: + * + * Written by David Mosberger (davidm@cs.arizona.edu) with some code + * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit + * bios code. + */ +#include +#include +#include +#include +#include + +#include +#include + +#define __EXTERN_INLINE inline +#include +#include +#undef __EXTERN_INLINE + +#include "proto.h" + +/* + * NOTE: Herein lie back-to-back mb instructions. They are magic. + * One plausible explanation is that the i/o controller does not properly + * handle the system transaction. Another involves timing. Ho hum. + */ + +/* + * BIOS32-style PCI interface: + */ + +#ifdef DEBUG +# define DBG(args) printk args +#else +# define DBG(args) +#endif + +#define vuip volatile unsigned int * + +volatile unsigned int apecs_mcheck_expected = 0; +volatile unsigned int apecs_mcheck_taken = 0; +static unsigned int apecs_jd, apecs_jd1, apecs_jd2; + + +/* + * Given a bus, device, and function number, compute resulting + * configuration space address and setup the APECS_HAXR2 register + * accordingly. It is therefore not safe to have concurrent + * invocations to configuration space access routines, but there + * really shouldn't be any need for this. + * + * Type 0: + * + * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 + * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | | | | | | | | | | | | | | | | | | | | | |F|F|F|R|R|R|R|R|R|0|0| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 31:11 Device select bit. + * 10:8 Function number + * 7:2 Register number + * + * Type 1: + * + * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 + * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 31:24 reserved + * 23:16 bus number (8 bits = 128 possible buses) + * 15:11 Device number (5 bits) + * 10:8 function number + * 7:2 register number + * + * Notes: + * The function number selects which function of a multi-function device + * (e.g., SCSI and Ethernet). + * + * The register selects a DWORD (32 bit) register offset. Hence it + * doesn't get shifted by 2 bits as we want to "drop" the bottom two + * bits. + */ + +static int +mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, + unsigned char *type1) +{ + unsigned long addr; + + DBG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x," + " pci_addr=0x%p, type1=0x%p)\n", + bus, device_fn, where, pci_addr, type1)); + + if (bus == 0) { + int device = device_fn >> 3; + + /* type 0 configuration cycle: */ + + if (device > 20) { + DBG(("mk_conf_addr: device (%d) > 20, returning -1\n", + device)); + return -1; + } + + *type1 = 0; + addr = (device_fn << 8) | (where); + } else { + /* type 1 configuration cycle: */ + *type1 = 1; + addr = (bus << 16) | (device_fn << 8) | (where); + } + *pci_addr = addr; + DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr)); + return 0; +} + +static unsigned int +conf_read(unsigned long addr, unsigned char type1) +{ + unsigned long flags; + unsigned int stat0, value; + unsigned int haxr2 = 0; + + save_flags(flags); /* avoid getting hit by machine check */ + cli(); + + DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1)); + + /* Reset status register to avoid losing errors. */ + stat0 = *(vuip)APECS_IOC_DCSR; + *(vuip)APECS_IOC_DCSR = stat0; + mb(); + DBG(("conf_read: APECS DCSR was 0x%x\n", stat0)); + + /* If Type1 access, must set HAE #2. */ + if (type1) { + haxr2 = *(vuip)APECS_IOC_HAXR2; + mb(); + *(vuip)APECS_IOC_HAXR2 = haxr2 | 1; + DBG(("conf_read: TYPE1 access\n")); + } + + draina(); + apecs_mcheck_expected = 1; + apecs_mcheck_taken = 0; + mb(); + + /* Access configuration space. */ + + /* Some SRMs step on these registers during a machine check. */ + asm volatile("ldl %0,%1; mb; mb" : "=r"(value) : "m"(*(vuip)addr) + : "$9", "$10", "$11", "$12", "$13", "$14", "memory"); + + if (apecs_mcheck_taken) { + apecs_mcheck_taken = 0; + value = 0xffffffffU; + mb(); + } + apecs_mcheck_expected = 0; + mb(); + +#if 1 + /* + * david.rusling@reo.mts.dec.com. This code is needed for the + * EB64+ as it does not generate a machine check (why I don't + * know). When we build kernels for one particular platform + * then we can make this conditional on the type. + */ + draina(); + + /* Now look for any errors. */ + stat0 = *(vuip)APECS_IOC_DCSR; + DBG(("conf_read: APECS DCSR after read 0x%x\n", stat0)); + + /* Is any error bit set? */ + if (stat0 & 0xffe0U) { + /* If not NDEV, print status. */ + if (!(stat0 & 0x0800)) { + printk("apecs.c:conf_read: got stat0=%x\n", stat0); + } + + /* Reset error status. */ + *(vuip)APECS_IOC_DCSR = stat0; + mb(); + wrmces(0x7); /* reset machine check */ + value = 0xffffffff; + } +#endif + + /* If Type1 access, must reset HAE #2 so normal IO space ops work. */ + if (type1) { + *(vuip)APECS_IOC_HAXR2 = haxr2 & ~1; + mb(); + } + restore_flags(flags); + + return value; +} + +static void +conf_write(unsigned long addr, unsigned int value, unsigned char type1) +{ + unsigned long flags; + unsigned int stat0; + unsigned int haxr2 = 0; + + save_flags(flags); /* avoid getting hit by machine check */ + cli(); + + /* Reset status register to avoid losing errors. */ + stat0 = *(vuip)APECS_IOC_DCSR; + *(vuip)APECS_IOC_DCSR = stat0; + mb(); + + /* If Type1 access, must set HAE #2. */ + if (type1) { + haxr2 = *(vuip)APECS_IOC_HAXR2; + mb(); + *(vuip)APECS_IOC_HAXR2 = haxr2 | 1; + } + + draina(); + apecs_mcheck_expected = 1; + mb(); + + /* Access configuration space. */ + *(vuip)addr = value; + mb(); + mb(); /* magic */ + apecs_mcheck_expected = 0; + mb(); + +#if 1 + /* + * david.rusling@reo.mts.dec.com. This code is needed for the + * EB64+ as it does not generate a machine check (why I don't + * know). When we build kernels for one particular platform + * then we can make this conditional on the type. + */ + draina(); + + /* Now look for any errors. */ + stat0 = *(vuip)APECS_IOC_DCSR; + + /* Is any error bit set? */ + if (stat0 & 0xffe0U) { + /* If not NDEV, print status. */ + if (!(stat0 & 0x0800)) { + printk("apecs.c:conf_write: got stat0=%x\n", stat0); + } + + /* Reset error status. */ + *(vuip)APECS_IOC_DCSR = stat0; + mb(); + wrmces(0x7); /* reset machine check */ + } +#endif + + /* If Type1 access, must reset HAE #2 so normal IO space ops work. */ + if (type1) { + *(vuip)APECS_IOC_HAXR2 = haxr2 & ~1; + mb(); + } + restore_flags(flags); +} + +int +apecs_pcibios_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value) +{ + unsigned long addr = APECS_CONF; + unsigned long pci_addr; + unsigned char type1; + + *value = 0xff; + + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x00; + + *value = conf_read(addr, type1) >> ((where & 3) * 8); + + return PCIBIOS_SUCCESSFUL; +} + +int +apecs_pcibios_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value) +{ + unsigned long addr = APECS_CONF; + unsigned long pci_addr; + unsigned char type1; + + *value = 0xffff; + + if (where & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x08; + + *value = conf_read(addr, type1) >> ((where & 3) * 8); + return PCIBIOS_SUCCESSFUL; +} + +int +apecs_pcibios_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value) +{ + unsigned long addr = APECS_CONF; + unsigned long pci_addr; + unsigned char type1; + + *value = 0xffffffff; + if (where & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x18; + *value = conf_read(addr, type1); + return PCIBIOS_SUCCESSFUL; +} + +int +apecs_pcibios_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value) +{ + unsigned long addr = APECS_CONF; + unsigned long pci_addr; + unsigned char type1; + + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x00; + conf_write(addr, value << ((where & 3) * 8), type1); + return PCIBIOS_SUCCESSFUL; +} + +int +apecs_pcibios_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value) +{ + unsigned long addr = APECS_CONF; + unsigned long pci_addr; + unsigned char type1; + + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x08; + conf_write(addr, value << ((where & 3) * 8), type1); + return PCIBIOS_SUCCESSFUL; +} + +int +apecs_pcibios_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value) +{ + unsigned long addr = APECS_CONF; + unsigned long pci_addr; + unsigned char type1; + + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x18; + conf_write(addr, value << ((where & 3) * 8), type1); + return PCIBIOS_SUCCESSFUL; +} + +void __init +apecs_init_arch(unsigned long *mem_start, unsigned long *mem_end) +{ + switch (alpha_use_srm_setup) + { + default: +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) + /* Check window 1 for enabled and mapped to 0. */ + if ((*(vuip)APECS_IOC_PB1R & (1U<<19)) + && (*(vuip)APECS_IOC_TB1R == 0)) { + APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB1R & 0xfff00000U; + APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM1R & 0xfff00000U; + APECS_DMA_WIN_SIZE += 0x00100000U; +#if 1 + printk("apecs_init: using Window 1 settings\n"); + printk("apecs_init: PB1R 0x%x PM1R 0x%x TB1R 0x%x\n", + *(vuip)APECS_IOC_PB1R, + *(vuip)APECS_IOC_PM1R, + *(vuip)APECS_IOC_TB1R); +#endif + break; + } + + /* Check window 2 for enabled and mapped to 0. */ + if ((*(vuip)APECS_IOC_PB2R & (1U<<19)) + && (*(vuip)APECS_IOC_TB2R == 0)) { + APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB2R & 0xfff00000U; + APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM2R & 0xfff00000U; + APECS_DMA_WIN_SIZE += 0x00100000U; +#if 1 + printk("apecs_init: using Window 2 settings\n"); + printk("apecs_init: PB2R 0x%x PM2R 0x%x TB2R 0x%x\n", + *(vuip)APECS_IOC_PB2R, + *(vuip)APECS_IOC_PM2R, + *(vuip)APECS_IOC_TB2R); +#endif + break; + } + + /* Otherwise, we must use our defaults. */ + APECS_DMA_WIN_BASE = APECS_DMA_WIN_BASE_DEFAULT; + APECS_DMA_WIN_SIZE = APECS_DMA_WIN_SIZE_DEFAULT; +#endif + case 0: + /* + * Set up the PCI->physical memory translation windows. + * For now, window 2 is disabled. In the future, we may + * want to use it to do scatter/gather DMA. Window 1 + * goes at 1 GB and is 1 GB large. + */ + *(vuip)APECS_IOC_PB2R = 0U; /* disable window 2 */ + + *(vuip)APECS_IOC_PB1R = 1U<<19 | (APECS_DMA_WIN_BASE_DEFAULT & 0xfff00000U); + *(vuip)APECS_IOC_PM1R = (APECS_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U; + *(vuip)APECS_IOC_TB1R = 0; + break; + } + + /* + * Finally, clear the HAXR2 register, which gets used + * for PCI Config Space accesses. That is the way + * we want to use it, and we do not want to depend on + * what ARC or SRM might have left behind... + */ + *(vuip)APECS_IOC_HAXR2 = 0; mb(); +} + +int +apecs_pci_clr_err(void) +{ + apecs_jd = *(vuip)APECS_IOC_DCSR; + if (apecs_jd & 0xffe0L) { + apecs_jd1 = *(vuip)APECS_IOC_SEAR; + *(vuip)APECS_IOC_DCSR = apecs_jd | 0xffe1L; + apecs_jd = *(vuip)APECS_IOC_DCSR; + mb(); + } + *(vuip)APECS_IOC_TBIA = (unsigned int)APECS_IOC_TBIA; + apecs_jd2 = *(vuip)APECS_IOC_TBIA; + mb(); + return 0; +} + +void +apecs_machine_check(unsigned long vector, unsigned long la_ptr, + struct pt_regs * regs) +{ + struct el_common *mchk_header; + struct el_apecs_procdata *mchk_procdata; + struct el_apecs_sysdata_mcheck *mchk_sysdata; + unsigned long *ptr; + int i; + + mchk_header = (struct el_common *)la_ptr; + + mchk_procdata = (struct el_apecs_procdata *) + (la_ptr + mchk_header->proc_offset + - sizeof(mchk_procdata->paltemp)); + + mchk_sysdata = (struct el_apecs_sysdata_mcheck *) + (la_ptr + mchk_header->sys_offset); + +#ifdef DEBUG + printk("apecs_machine_check: vector=0x%lx la_ptr=0x%lx\n", + vector, la_ptr); + printk(" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", + regs->pc, mchk_header->size, mchk_header->proc_offset, + mchk_header->sys_offset); + printk("apecs_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n", + apecs_mcheck_expected, mchk_sysdata->epic_dcsr, + mchk_sysdata->epic_pear); + ptr = (unsigned long *)la_ptr; + for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { + printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]); + } +#endif + + /* + * Check if machine check is due to a badaddr() and if so, + * ignore the machine check. + */ + + if (apecs_mcheck_expected + && (mchk_sysdata->epic_dcsr & 0x0c00UL)) { + apecs_mcheck_expected = 0; + apecs_mcheck_taken = 1; + mb(); + mb(); /* magic */ + apecs_pci_clr_err(); + wrmces(0x7); + mb(); + draina(); + DBG(("apecs_machine_check: EXPECTED\n")); + } + else if (vector == 0x620 || vector == 0x630) { + /* Disable correctable from now on. */ + wrmces(0x1f); + mb(); + draina(); + printk("apecs_machine_check: HW correctable (0x%lx)\n", + vector); + } + else { + printk(KERN_CRIT "APECS machine check:\n"); + printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx\n", + vector, la_ptr); + printk(KERN_CRIT + " pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", + regs->pc, mchk_header->size, mchk_header->proc_offset, + mchk_header->sys_offset); + printk(KERN_CRIT " expected %d DCSR 0x%lx PEAR 0x%lx\n", + apecs_mcheck_expected, mchk_sysdata->epic_dcsr, + mchk_sysdata->epic_pear); + + ptr = (unsigned long *)la_ptr; + for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { + printk(KERN_CRIT " +%lx %lx %lx\n", + i*sizeof(long), ptr[i], ptr[i+1]); + } +#if 0 + /* doesn't work with MILO */ + show_regs(regs); +#endif + } +} diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/core_cia.c linux/arch/alpha/kernel/core_cia.c --- v2.1.115/linux/arch/alpha/kernel/core_cia.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/core_cia.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,727 @@ +/* + * linux/arch/alpha/kernel/core_cia.c + * + * Code common to all CIA core logic chips. + * + * Written by David A Rusling (david.rusling@reo.mts.dec.com). + * December 1995. + * + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +#define __EXTERN_INLINE inline +#include +#include +#undef __EXTERN_INLINE + +#include "proto.h" + +/* + * NOTE: Herein lie back-to-back mb instructions. They are magic. + * One plausible explanation is that the i/o controller does not properly + * handle the system transaction. Another involves timing. Ho hum. + */ + +extern asmlinkage void wrmces(unsigned long mces); + +/* + * Machine check reasons. Defined according to PALcode sources + * (osf.h and platform.h). + */ +#define MCHK_K_TPERR 0x0080 +#define MCHK_K_TCPERR 0x0082 +#define MCHK_K_HERR 0x0084 +#define MCHK_K_ECC_C 0x0086 +#define MCHK_K_ECC_NC 0x0088 +#define MCHK_K_OS_BUGCHECK 0x008A +#define MCHK_K_PAL_BUGCHECK 0x0090 + +/* + * BIOS32-style PCI interface: + */ + +#define DEBUG_MCHECK 0 +#define DEBUG_CONFIG 0 +/* #define DEBUG_DUMP_REGS */ + +#if DEBUG_MCHECK +# define DBGM(args) printk args +#else +# define DBGM(args) +#endif +#if DEBUG_CONFIG +# define DBGC(args) printk args +#else +# define DBGC(args) +#endif + +#define vuip volatile unsigned int * + +static volatile unsigned int CIA_mcheck_expected = 0; +static volatile unsigned int CIA_mcheck_taken = 0; +static unsigned int CIA_jd; + + +/* + * Given a bus, device, and function number, compute resulting + * configuration space address and setup the CIA_HAXR2 register + * accordingly. It is therefore not safe to have concurrent + * invocations to configuration space access routines, but there + * really shouldn't be any need for this. + * + * Type 0: + * + * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 + * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 31:11 Device select bit. + * 10:8 Function number + * 7:2 Register number + * + * Type 1: + * + * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 + * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 31:24 reserved + * 23:16 bus number (8 bits = 128 possible buses) + * 15:11 Device number (5 bits) + * 10:8 function number + * 7:2 register number + * + * Notes: + * The function number selects which function of a multi-function device + * (e.g., SCSI and Ethernet). + * + * The register selects a DWORD (32 bit) register offset. Hence it + * doesn't get shifted by 2 bits as we want to "drop" the bottom two + * bits. + */ + +static int +mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, + unsigned char *type1) +{ + unsigned long addr; + + DBGC(("mk_conf_addr(bus=%d, device_fn=0x%x, where=0x%x, " + "pci_addr=0x%p, type1=0x%p)\n", + bus, device_fn, where, pci_addr, type1)); + + if (bus == 0) { + int device = device_fn >> 3; + + /* Type 0 configuration cycle. */ + + if (device > 20) { + DBGC(("mk_conf_addr: device (%d) > 20, returning -1\n", + device)); + return -1; + } + + *type1 = 0; + addr = (device_fn << 8) | (where); + } else { + /* Type 1 configuration cycle. */ + *type1 = 1; + addr = (bus << 16) | (device_fn << 8) | (where); + } + *pci_addr = addr; + DBGC(("mk_conf_addr: returning pci_addr 0x%lx\n", addr)); + return 0; +} + +static unsigned int +conf_read(unsigned long addr, unsigned char type1) +{ + unsigned long flags; + unsigned int stat0, value; + unsigned int cia_cfg = 0; + + value = 0xffffffffU; + mb(); + + save_flags(flags); /* avoid getting hit by machine check */ + cli(); + + DBGC(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1)); + + /* Reset status register to avoid losing errors. */ + stat0 = *(vuip)CIA_IOC_CIA_ERR; + *(vuip)CIA_IOC_CIA_ERR = stat0; + mb(); + DBGC(("conf_read: CIA ERR was 0x%x\n", stat0)); + + /* If Type1 access, must set CIA CFG. */ + if (type1) { + cia_cfg = *(vuip)CIA_IOC_CFG; + *(vuip)CIA_IOC_CFG = cia_cfg | 1; + mb(); + DBGC(("conf_read: TYPE1 access\n")); + } + + mb(); + draina(); + CIA_mcheck_expected = 1; + CIA_mcheck_taken = 0; + mb(); + + /* Access configuration space. */ + value = *(vuip)addr; + mb(); + mb(); /* magic */ + if (CIA_mcheck_taken) { + CIA_mcheck_taken = 0; + value = 0xffffffffU; + mb(); + } + CIA_mcheck_expected = 0; + mb(); + +#if 0 + /* This code might be necessary if machine checks aren't taken, + but I can't get it to work on CIA-2, so its disabled. */ + draina(); + + /* Now look for any errors. */ + stat0 = *(vuip)CIA_IOC_CIA_ERR; + DBGC(("conf_read: CIA ERR after read 0x%x\n", stat0)); + + /* Is any error bit set? */ + if (stat0 & 0x8FEF0FFFU) { + /* If not MAS_ABT, print status. */ + if (!(stat0 & 0x0080)) { + printk("CIA.c:conf_read: got stat0=%x\n", stat0); + } + + /* reset error status: */ + *(vuip)CIA_IOC_CIA_ERR = stat0; + mb(); + wrmces(0x7); /* reset machine check */ + value = 0xffffffff; + } +#endif + + /* If Type1 access, must reset IOC CFG so normal IO space ops work. */ + if (type1) { + *(vuip)CIA_IOC_CFG = cia_cfg & ~1; + mb(); + } + + DBGC(("conf_read(): finished\n")); + + restore_flags(flags); + return value; +} + +static void +conf_write(unsigned long addr, unsigned int value, unsigned char type1) +{ + unsigned long flags; + unsigned int stat0; + unsigned int cia_cfg = 0; + + save_flags(flags); /* avoid getting hit by machine check */ + cli(); + + /* Reset status register to avoid losing errors. */ + stat0 = *(vuip)CIA_IOC_CIA_ERR; + *(vuip)CIA_IOC_CIA_ERR = stat0; + mb(); + DBGC(("conf_write: CIA ERR was 0x%x\n", stat0)); + + /* If Type1 access, must set CIA CFG. */ + if (type1) { + cia_cfg = *(vuip)CIA_IOC_CFG; + *(vuip)CIA_IOC_CFG = cia_cfg | 1; + mb(); + DBGC(("conf_write: TYPE1 access\n")); + } + + draina(); + CIA_mcheck_expected = 1; + mb(); + + /* Access configuration space. */ + *(vuip)addr = value; + mb(); + mb(); /* magic */ + + CIA_mcheck_expected = 0; + mb(); + +#if 0 + /* This code might be necessary if machine checks aren't taken, + but I can't get it to work on CIA-2, so its disabled. */ + draina(); + + /* Now look for any errors */ + stat0 = *(vuip)CIA_IOC_CIA_ERR; + DBGC(("conf_write: CIA ERR after write 0x%x\n", stat0)); + + /* Is any error bit set? */ + if (stat0 & 0x8FEF0FFFU) { + /* If not MAS_ABT, print status */ + if (!(stat0 & 0x0080)) { + printk("CIA.c:conf_read: got stat0=%x\n", stat0); + } + + /* Reset error status. */ + *(vuip)CIA_IOC_CIA_ERR = stat0; + mb(); + wrmces(0x7); /* reset machine check */ + value = 0xffffffff; + } +#endif + + /* If Type1 access, must reset IOC CFG so normal IO space ops work. */ + if (type1) { + *(vuip)CIA_IOC_CFG = cia_cfg & ~1; + mb(); + } + + DBGC(("conf_write(): finished\n")); + restore_flags(flags); +} + +int +cia_pcibios_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value) +{ + unsigned long addr = CIA_CONF; + unsigned long pci_addr; + unsigned char type1; + + *value = 0xff; + + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x00; + *value = conf_read(addr, type1) >> ((where & 3) * 8); + return PCIBIOS_SUCCESSFUL; +} + +int +cia_pcibios_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value) +{ + unsigned long addr = CIA_CONF; + unsigned long pci_addr; + unsigned char type1; + + *value = 0xffff; + + if (where & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x08; + *value = conf_read(addr, type1) >> ((where & 3) * 8); + return PCIBIOS_SUCCESSFUL; +} + +int +cia_pcibios_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value) +{ + unsigned long addr = CIA_CONF; + unsigned long pci_addr; + unsigned char type1; + + *value = 0xffffffff; + if (where & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x18; + *value = conf_read(addr, type1); + return PCIBIOS_SUCCESSFUL; +} + +int +cia_pcibios_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value) +{ + unsigned long addr = CIA_CONF; + unsigned long pci_addr; + unsigned char type1; + + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x00; + conf_write(addr, value << ((where & 3) * 8), type1); + return PCIBIOS_SUCCESSFUL; +} + +int +cia_pcibios_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value) +{ + unsigned long addr = CIA_CONF; + unsigned long pci_addr; + unsigned char type1; + + if (where & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x08; + conf_write(addr, value << ((where & 3) * 8), type1); + return PCIBIOS_SUCCESSFUL; +} + +int +cia_pcibios_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value) +{ + unsigned long addr = CIA_CONF; + unsigned long pci_addr; + unsigned char type1; + + if (where & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x18; + conf_write(addr, value << ((where & 3) * 8), type1); + return PCIBIOS_SUCCESSFUL; +} + +void __init +cia_init_arch(unsigned long *mem_start, unsigned long *mem_end) +{ + unsigned int cia_tmp; + +#ifdef DEBUG_DUMP_REGS + { + unsigned int temp; + temp = *(vuip)CIA_IOC_CIA_REV; mb(); + printk("cia_init: CIA_REV was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_PCI_LAT; mb(); + printk("cia_init: CIA_PCI_LAT was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_CIA_CTRL; mb(); + printk("cia_init: CIA_CTRL was 0x%x\n", temp); + temp = *(vuip)0xfffffc8740000140UL; mb(); + printk("cia_init: CIA_CTRL1 was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_HAE_MEM; mb(); + printk("cia_init: CIA_HAE_MEM was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_HAE_IO; mb(); + printk("cia_init: CIA_HAE_IO was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_CFG; mb(); + printk("cia_init: CIA_CFG was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_CACK_EN; mb(); + printk("cia_init: CIA_CACK_EN was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_CFG; mb(); + printk("cia_init: CIA_CFG was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_CIA_DIAG; mb(); + printk("cia_init: CIA_DIAG was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_DIAG_CHECK; mb(); + printk("cia_init: CIA_DIAG_CHECK was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_PERF_MONITOR; mb(); + printk("cia_init: CIA_PERF_MONITOR was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_PERF_CONTROL; mb(); + printk("cia_init: CIA_PERF_CONTROL was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_CIA_ERR; mb(); + printk("cia_init: CIA_ERR was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_CIA_STAT; mb(); + printk("cia_init: CIA_STAT was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_MCR; mb(); + printk("cia_init: CIA_MCR was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_CIA_CTRL; mb(); + printk("cia_init: CIA_CTRL was 0x%x\n", temp); + temp = *(vuip)CIA_IOC_ERR_MASK; mb(); + printk("cia_init: CIA_ERR_MASK was 0x%x\n", temp); + temp = *((vuip)CIA_IOC_PCI_W0_BASE); mb(); + printk("cia_init: W0_BASE was 0x%x\n", temp); + temp = *((vuip)CIA_IOC_PCI_W1_BASE); mb(); + printk("cia_init: W1_BASE was 0x%x\n", temp); + temp = *((vuip)CIA_IOC_PCI_W2_BASE); mb(); + printk("cia_init: W2_BASE was 0x%x\n", temp); + temp = *((vuip)CIA_IOC_PCI_W3_BASE); mb(); + printk("cia_init: W3_BASE was 0x%x\n", temp); + } +#endif /* DEBUG_DUMP_REGS */ + + /* + * Set up error reporting. + */ + cia_tmp = *(vuip)CIA_IOC_CIA_ERR; + cia_tmp |= 0x180; /* master, target abort */ + *(vuip)CIA_IOC_CIA_ERR = cia_tmp; + mb(); + + cia_tmp = *(vuip)CIA_IOC_CIA_CTRL; + cia_tmp |= 0x400; /* turn on FILL_ERR to get mchecks */ + *(vuip)CIA_IOC_CIA_CTRL = cia_tmp; + mb(); + + switch (alpha_use_srm_setup) + { + default: +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) + /* Check window 0 for enabled and mapped to 0 */ + if (((*(vuip)CIA_IOC_PCI_W0_BASE & 3) == 1) + && (*(vuip)CIA_IOC_PCI_T0_BASE == 0)) { + CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W0_BASE & 0xfff00000U; + CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W0_MASK & 0xfff00000U; + CIA_DMA_WIN_SIZE += 0x00100000U; +#if 1 + printk("cia_init: using Window 0 settings\n"); + printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", + *(vuip)CIA_IOC_PCI_W0_BASE, + *(vuip)CIA_IOC_PCI_W0_MASK, + *(vuip)CIA_IOC_PCI_T0_BASE); +#endif + break; + } + + /* Check window 1 for enabled and mapped to 0. */ + if (((*(vuip)CIA_IOC_PCI_W1_BASE & 3) == 1) + && (*(vuip)CIA_IOC_PCI_T1_BASE == 0)) { + CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W1_BASE & 0xfff00000U; + CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W1_MASK & 0xfff00000U; + CIA_DMA_WIN_SIZE += 0x00100000U; +#if 1 + printk("cia_init: using Window 1 settings\n"); + printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", + *(vuip)CIA_IOC_PCI_W1_BASE, + *(vuip)CIA_IOC_PCI_W1_MASK, + *(vuip)CIA_IOC_PCI_T1_BASE); +#endif + break; + } + + /* Check window 2 for enabled and mapped to 0. */ + if (((*(vuip)CIA_IOC_PCI_W2_BASE & 3) == 1) + && (*(vuip)CIA_IOC_PCI_T2_BASE == 0)) { + CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W2_BASE & 0xfff00000U; + CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W2_MASK & 0xfff00000U; + CIA_DMA_WIN_SIZE += 0x00100000U; +#if 1 + printk("cia_init: using Window 2 settings\n"); + printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", + *(vuip)CIA_IOC_PCI_W2_BASE, + *(vuip)CIA_IOC_PCI_W2_MASK, + *(vuip)CIA_IOC_PCI_T2_BASE); +#endif + break; + } + + /* Check window 3 for enabled and mapped to 0. */ + if (((*(vuip)CIA_IOC_PCI_W3_BASE & 3) == 1) + && (*(vuip)CIA_IOC_PCI_T3_BASE == 0)) { + CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W3_BASE & 0xfff00000U; + CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W3_MASK & 0xfff00000U; + CIA_DMA_WIN_SIZE += 0x00100000U; +#if 1 + printk("cia_init: using Window 3 settings\n"); + printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", + *(vuip)CIA_IOC_PCI_W3_BASE, + *(vuip)CIA_IOC_PCI_W3_MASK, + *(vuip)CIA_IOC_PCI_T3_BASE); +#endif + break; + } + + /* Otherwise, we must use our defaults. */ + CIA_DMA_WIN_BASE = CIA_DMA_WIN_BASE_DEFAULT; + CIA_DMA_WIN_SIZE = CIA_DMA_WIN_SIZE_DEFAULT; +#endif + case 0: + /* + * Set up the PCI->physical memory translation windows. + * For now, windows 1,2 and 3 are disabled. In the future, + * we may want to use them to do scatter/gather DMA. + * + * Window 0 goes at 1 GB and is 1 GB large. + */ + + *(vuip)CIA_IOC_PCI_W0_BASE = 1U | (CIA_DMA_WIN_BASE_DEFAULT & 0xfff00000U); + *(vuip)CIA_IOC_PCI_W0_MASK = (CIA_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U; + *(vuip)CIA_IOC_PCI_T0_BASE = 0; + + *(vuip)CIA_IOC_PCI_W1_BASE = 0x0; + *(vuip)CIA_IOC_PCI_W2_BASE = 0x0; + *(vuip)CIA_IOC_PCI_W3_BASE = 0x0; + break; + } + + /* + * Next, clear the CIA_CFG register, which gets used + * for PCI Config Space accesses. That is the way + * we want to use it, and we do not want to depend on + * what ARC or SRM might have left behind... + */ + *((vuip)CIA_IOC_CFG) = 0; mb(); + + + /* + * Sigh... For the SRM setup, unless we know apriori what the HAE + * contents will be, we need to setup the arbitrary region bases + * so we can test against the range of addresses and tailor the + * region chosen for the SPARSE memory access. + * + * See include/asm-alpha/cia.h for the SPARSE mem read/write. + */ + if (alpha_use_srm_setup) { + unsigned int cia_hae_mem = *((vuip)CIA_IOC_HAE_MEM); + + alpha_mv.sm_base_r1 = (cia_hae_mem ) & 0xe0000000UL; + alpha_mv.sm_base_r2 = (cia_hae_mem << 16) & 0xf8000000UL; + alpha_mv.sm_base_r3 = (cia_hae_mem << 24) & 0xfc000000UL; + + /* + * Set the HAE cache, so that setup_arch() code + * will use the SRM setting always. Our readb/writeb + * code in cia.h expects never to have to change + * the contents of the HAE. + */ + alpha_mv.hae_cache = cia_hae_mem; + + alpha_mv.mv_readb = cia_srm_readb; + alpha_mv.mv_readw = cia_srm_readw; + alpha_mv.mv_writeb = cia_srm_writeb; + alpha_mv.mv_writew = cia_srm_writew; + } else { + *((vuip)CIA_IOC_HAE_MEM) = 0; mb(); + *((vuip)CIA_IOC_HAE_MEM); /* read it back. */ + *((vuip)CIA_IOC_HAE_IO) = 0; mb(); + *((vuip)CIA_IOC_HAE_IO); /* read it back. */ + } +} + +static int +cia_pci_clr_err(void) +{ + CIA_jd = *(vuip)CIA_IOC_CIA_ERR; + DBGM(("CIA_pci_clr_err: CIA ERR after read 0x%x\n", CIA_jd)); + *(vuip)CIA_IOC_CIA_ERR = 0x0180; + mb(); + return 0; +} + +void +cia_machine_check(unsigned long vector, unsigned long la_ptr, + struct pt_regs * regs) +{ + struct el_common *mchk_header; + struct el_CIA_procdata *mchk_procdata; + struct el_CIA_sysdata_mcheck *mchk_sysdata; + unsigned long * ptr; + const char * reason; + char buf[128]; + long i; + + mchk_header = (struct el_common *)la_ptr; + + mchk_procdata = (struct el_CIA_procdata *) + (la_ptr + mchk_header->proc_offset); + + mchk_sysdata = (struct el_CIA_sysdata_mcheck *) + (la_ptr + mchk_header->sys_offset); + + DBGM(("cia_machine_check: vector=0x%lx la_ptr=0x%lx\n", + vector, la_ptr)); + DBGM((" pc=0x%lx size=0x%x procoffset=0x%x " + "sysoffset 0x%x\n", regs->pc, mchk_header->size, + mchk_header->proc_offset, mchk_header->sys_offset)); + DBGM(("cia_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n", + CIA_mcheck_expected, mchk_sysdata->epic_dcsr, + mchk_sysdata->epic_pear)); + +#if DEBUG_MCHECK + { + unsigned long *ptr; + int i; + + ptr = (unsigned long *)la_ptr; + for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { + printk(" +%lx %lx %lx\n", i*sizeof(long), + ptr[i], ptr[i+1]); + } + } +#endif + + /* + * Check if machine check is due to a badaddr() and if so, + * ignore the machine check. + */ + mb(); + mb(); /* magic */ + if (CIA_mcheck_expected) { + DBGM(("CIA machine check expected\n")); + CIA_mcheck_expected = 0; + CIA_mcheck_taken = 1; + mb(); + mb(); /* magic */ + draina(); + cia_pci_clr_err(); + wrmces(0x7); + mb(); + return; + } + + switch ((unsigned int) mchk_header->code) { + case MCHK_K_TPERR: reason = "tag parity error"; break; + case MCHK_K_TCPERR: reason = "tag control parity error"; break; + case MCHK_K_HERR: reason = "generic hard error"; break; + case MCHK_K_ECC_C: reason = "correctable ECC error"; break; + case MCHK_K_ECC_NC: reason = "uncorrectable ECC error"; break; + case MCHK_K_OS_BUGCHECK: reason = "OS-specific PAL bugcheck"; break; + case MCHK_K_PAL_BUGCHECK: reason = "callsys in kernel mode"; break; + case 0x96: reason = "i-cache read retryable error"; break; + case 0x98: reason = "processor detected hard error"; break; + + /* System specific (these are for Alcor, at least): */ + case 0x203: reason = "system detected uncorrectable ECC error"; break; + case 0x205: reason = "parity error detected by CIA"; break; + case 0x207: reason = "non-existent memory error"; break; + case 0x209: reason = "PCI SERR detected"; break; + case 0x20b: reason = "PCI data parity error detected"; break; + case 0x20d: reason = "PCI address parity error detected"; break; + case 0x20f: reason = "PCI master abort error"; break; + case 0x211: reason = "PCI target abort error"; break; + case 0x213: reason = "scatter/gather PTE invalid error"; break; + case 0x215: reason = "flash ROM write error"; break; + case 0x217: reason = "IOA timeout detected"; break; + case 0x219: reason = "IOCHK#, EISA add-in board parity or other catastrophic error"; break; + case 0x21b: reason = "EISA fail-safe timer timeout"; break; + case 0x21d: reason = "EISA bus time-out"; break; + case 0x21f: reason = "EISA software generated NMI"; break; + case 0x221: reason = "unexpected ev5 IRQ[3] interrupt"; break; + default: + sprintf(buf, "reason for machine-check unknown (0x%x)", + (unsigned int) mchk_header->code); + reason = buf; + break; + } + wrmces(rdmces()); /* reset machine check pending flag */ + mb(); + + printk(KERN_CRIT "CIA machine check: %s%s\n", + reason, mchk_header->retry ? " (retryable)" : ""); + printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx pc=0x%lx\n", + vector, la_ptr, regs->pc); + + /* Dump the logout area to give all info. */ + + ptr = (unsigned long *)la_ptr; + for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { + printk(KERN_CRIT " +%8lx %016lx %016lx\n", + i*sizeof(long), ptr[i], ptr[i+1]); + } +} diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/core_lca.c linux/arch/alpha/kernel/core_lca.c --- v2.1.115/linux/arch/alpha/kernel/core_lca.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/core_lca.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,570 @@ +/* + * linux/arch/alpha/kernel/core_lca.c + * + * Code common to all LCA core logic chips. + * + * Written by David Mosberger (davidm@cs.arizona.edu) with some code + * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit + * bios code. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define __EXTERN_INLINE inline +#include +#include +#undef __EXTERN_INLINE + +#include "proto.h" + +/* + * BIOS32-style PCI interface: + */ + +/* + * Machine check reasons. Defined according to PALcode sources + * (osf.h and platform.h). + */ +#define MCHK_K_TPERR 0x0080 +#define MCHK_K_TCPERR 0x0082 +#define MCHK_K_HERR 0x0084 +#define MCHK_K_ECC_C 0x0086 +#define MCHK_K_ECC_NC 0x0088 +#define MCHK_K_UNKNOWN 0x008A +#define MCHK_K_CACKSOFT 0x008C +#define MCHK_K_BUGCHECK 0x008E +#define MCHK_K_OS_BUGCHECK 0x0090 +#define MCHK_K_DCPERR 0x0092 +#define MCHK_K_ICPERR 0x0094 + + +/* + * Platform-specific machine-check reasons: + */ +#define MCHK_K_SIO_SERR 0x204 /* all platforms so far */ +#define MCHK_K_SIO_IOCHK 0x206 /* all platforms so far */ +#define MCHK_K_DCSR 0x208 /* all but Noname */ + + +/* + * Given a bus, device, and function number, compute resulting + * configuration space address and setup the LCA_IOC_CONF register + * accordingly. It is therefore not safe to have concurrent + * invocations to configuration space access routines, but there + * really shouldn't be any need for this. + * + * Type 0: + * + * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 + * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | | | | | | | | | | | | | | | | | | | | | |F|F|F|R|R|R|R|R|R|0|0| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 31:11 Device select bit. + * 10:8 Function number + * 7:2 Register number + * + * Type 1: + * + * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 + * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 31:24 reserved + * 23:16 bus number (8 bits = 128 possible buses) + * 15:11 Device number (5 bits) + * 10:8 function number + * 7:2 register number + * + * Notes: + * The function number selects which function of a multi-function device + * (e.g., SCSI and Ethernet). + * + * The register selects a DWORD (32 bit) register offset. Hence it + * doesn't get shifted by 2 bits as we want to "drop" the bottom two + * bits. + */ + +static int +mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr) +{ + unsigned long addr; + + if (bus == 0) { + int device = device_fn >> 3; + int func = device_fn & 0x7; + + /* Type 0 configuration cycle. */ + + if (device > 12) { + return -1; + } + + *(vulp)LCA_IOC_CONF = 0; + addr = (1 << (11 + device)) | (func << 8) | where; + } else { + /* Type 1 configuration cycle. */ + *(vulp)LCA_IOC_CONF = 1; + addr = (bus << 16) | (device_fn << 8) | where; + } + *pci_addr = addr; + return 0; +} + +static unsigned int +conf_read(unsigned long addr) +{ + unsigned long flags, code, stat0; + unsigned int value; + + save_flags(flags); + cli(); + + /* Reset status register to avoid loosing errors. */ + stat0 = *(vulp)LCA_IOC_STAT0; + *(vulp)LCA_IOC_STAT0 = stat0; + mb(); + + /* Access configuration space. */ + value = *(vuip)addr; + draina(); + + stat0 = *(vulp)LCA_IOC_STAT0; + if (stat0 & LCA_IOC_STAT0_ERR) { + code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT) + & LCA_IOC_STAT0_CODE_MASK); + if (code != 1) { + printk("lca.c:conf_read: got stat0=%lx\n", stat0); + } + + /* Reset error status. */ + *(vulp)LCA_IOC_STAT0 = stat0; + mb(); + + /* Reset machine check. */ + wrmces(0x7); + + value = 0xffffffff; + } + restore_flags(flags); + return value; +} + +static void +conf_write(unsigned long addr, unsigned int value) +{ + unsigned long flags, code, stat0; + + save_flags(flags); /* avoid getting hit by machine check */ + cli(); + + /* Reset status register to avoid loosing errors. */ + stat0 = *(vulp)LCA_IOC_STAT0; + *(vulp)LCA_IOC_STAT0 = stat0; + mb(); + + /* Access configuration space. */ + *(vuip)addr = value; + draina(); + + stat0 = *(vulp)LCA_IOC_STAT0; + if (stat0 & LCA_IOC_STAT0_ERR) { + code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT) + & LCA_IOC_STAT0_CODE_MASK); + if (code != 1) { + printk("lca.c:conf_write: got stat0=%lx\n", stat0); + } + + /* Reset error status. */ + *(vulp)LCA_IOC_STAT0 = stat0; + mb(); + + /* Reset machine check. */ + wrmces(0x7); + } + restore_flags(flags); +} + +int +lca_pcibios_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value) +{ + unsigned long addr = LCA_CONF; + unsigned long pci_addr; + + *value = 0xff; + + if (mk_conf_addr(bus, device_fn, where, &pci_addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x00; + *value = conf_read(addr) >> ((where & 3) * 8); + return PCIBIOS_SUCCESSFUL; +} + +int +lca_pcibios_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value) +{ + unsigned long addr = LCA_CONF; + unsigned long pci_addr; + + *value = 0xffff; + + if (where & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &pci_addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x08; + *value = conf_read(addr) >> ((where & 3) * 8); + return PCIBIOS_SUCCESSFUL; +} + +int +lca_pcibios_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value) +{ + unsigned long addr = LCA_CONF; + unsigned long pci_addr; + + *value = 0xffffffff; + if (where & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &pci_addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x18; + *value = conf_read(addr); + return PCIBIOS_SUCCESSFUL; +} + +int +lca_pcibios_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value) +{ + unsigned long addr = LCA_CONF; + unsigned long pci_addr; + + if (mk_conf_addr(bus, device_fn, where, &pci_addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x00; + conf_write(addr, value << ((where & 3) * 8)); + return PCIBIOS_SUCCESSFUL; +} + +int +lca_pcibios_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value) +{ + unsigned long addr = LCA_CONF; + unsigned long pci_addr; + + if (where & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &pci_addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x08; + conf_write(addr, value << ((where & 3) * 8)); + return PCIBIOS_SUCCESSFUL; +} + +int +lca_pcibios_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value) +{ + unsigned long addr = LCA_CONF; + unsigned long pci_addr; + + if (where & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &pci_addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x18; + conf_write(addr, value << ((where & 3) * 8)); + return PCIBIOS_SUCCESSFUL; +} + +void __init +lca_init_arch(unsigned long *mem_start, unsigned long *mem_end) +{ + switch (alpha_use_srm_setup) + { + default: +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) + /* Check window 0 for enabled and mapped to 0. */ + if ((*(vulp)LCA_IOC_W_BASE0 & (1UL<<33)) + && (*(vulp)LCA_IOC_T_BASE0 == 0)) { + LCA_DMA_WIN_BASE = *(vulp)LCA_IOC_W_BASE0 & 0xffffffffUL; + LCA_DMA_WIN_SIZE = *(vulp)LCA_IOC_W_MASK0 & 0xffffffffUL; + LCA_DMA_WIN_SIZE += 1; +#if 0 + printk("lca_init: using Window 0 settings\n"); + printk("lca_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n", + *(vulp)LCA_IOC_W_BASE0, + *(vulp)LCA_IOC_W_MASK0, + *(vulp)LCA_IOC_T_BASE0); +#endif + break; + } + + /* Check window 2 for enabled and mapped to 0. */ + if ((*(vulp)LCA_IOC_W_BASE1 & (1UL<<33)) + && (*(vulp)LCA_IOC_T_BASE1 == 0)) { + LCA_DMA_WIN_BASE = *(vulp)LCA_IOC_W_BASE1 & 0xffffffffUL; + LCA_DMA_WIN_SIZE = *(vulp)LCA_IOC_W_MASK1 & 0xffffffffUL; + LCA_DMA_WIN_SIZE += 1; +#if 1 + printk("lca_init: using Window 1 settings\n"); + printk("lca_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n", + *(vulp)LCA_IOC_W_BASE1, + *(vulp)LCA_IOC_W_MASK1, + *(vulp)LCA_IOC_T_BASE1); +#endif + break; + } + + /* Otherwise, we must use our defaults. */ + LCA_DMA_WIN_BASE = LCA_DMA_WIN_BASE_DEFAULT; + LCA_DMA_WIN_SIZE = LCA_DMA_WIN_SIZE_DEFAULT; +#endif + case 0: + /* + * Set up the PCI->physical memory translation windows. + * For now, window 1 is disabled. In the future, we may + * want to use it to do scatter/gather DMA. + * + * Window 0 goes at 1 GB and is 1 GB large. + */ + *(vulp)LCA_IOC_W_BASE1 = 0UL<<33; + + *(vulp)LCA_IOC_W_BASE0 = 1UL<<33 | LCA_DMA_WIN_BASE_DEFAULT; + *(vulp)LCA_IOC_W_MASK0 = LCA_DMA_WIN_SIZE_DEFAULT - 1; + *(vulp)LCA_IOC_T_BASE0 = 0; + break; + } + + /* + * Disable PCI parity for now. The NCR53c810 chip has + * troubles meeting the PCI spec which results in + * data parity errors. + */ + *(vulp)LCA_IOC_PAR_DIS = 1UL<<5; +} + +/* + * Constants used during machine-check handling. I suppose these + * could be moved into lca.h but I don't see much reason why anybody + * else would want to use them. + */ + +#define ESR_EAV (1UL<< 0) /* error address valid */ +#define ESR_CEE (1UL<< 1) /* correctable error */ +#define ESR_UEE (1UL<< 2) /* uncorrectable error */ +#define ESR_WRE (1UL<< 3) /* write-error */ +#define ESR_SOR (1UL<< 4) /* error source */ +#define ESR_CTE (1UL<< 7) /* cache-tag error */ +#define ESR_MSE (1UL<< 9) /* multiple soft errors */ +#define ESR_MHE (1UL<<10) /* multiple hard errors */ +#define ESR_NXM (1UL<<12) /* non-existent memory */ + +#define IOC_ERR ( 1<<4) /* ioc logs an error */ +#define IOC_CMD_SHIFT 0 +#define IOC_CMD (0xf<> IOC_CODE_SHIFT; + unsigned cmd = (stat0 & IOC_CMD) >> IOC_CMD_SHIFT; + + printk(" %s initiated PCI %s cycle to address %x" + " failed due to %s.\n", + code > 3 ? "PCI" : "CPU", pci_cmd[cmd], stat1, err_name[code]); + + if (code == 5 || code == 6) { + printk(" (Error occurred at PCI memory address %x.)\n", + (stat0 & ~IOC_P_NBR)); + } + if (stat0 & IOC_LOST) { + printk(" Other PCI errors occurred simultaneously.\n"); + } +} + +void +lca_machine_check (unsigned long vector, unsigned long la, + struct pt_regs *regs) +{ + unsigned long * ptr; + const char * reason; + union el_lca el; + char buf[128]; + long i; + + printk(KERN_CRIT "lca: machine check (la=0x%lx,pc=0x%lx)\n", + la, regs->pc); + el.c = (struct el_common *) la; + + /* + * The first quadword after the common header always seems to + * be the machine check reason---don't know why this isn't + * part of the common header instead. In the case of a long + * logout frame, the upper 32 bits is the machine check + * revision level, which we ignore for now. + */ + switch (el.c->code & 0xffffffff) { + case MCHK_K_TPERR: reason = "tag parity error"; break; + case MCHK_K_TCPERR: reason = "tag control parity error"; break; + case MCHK_K_HERR: reason = "access to non-existent memory"; break; + case MCHK_K_ECC_C: reason = "correctable ECC error"; break; + case MCHK_K_ECC_NC: reason = "non-correctable ECC error"; break; + case MCHK_K_CACKSOFT: reason = "MCHK_K_CACKSOFT"; break; /* what's this? */ + case MCHK_K_BUGCHECK: reason = "illegal exception in PAL mode"; break; + case MCHK_K_OS_BUGCHECK: reason = "callsys in kernel mode"; break; + case MCHK_K_DCPERR: reason = "d-cache parity error"; break; + case MCHK_K_ICPERR: reason = "i-cache parity error"; break; + case MCHK_K_SIO_SERR: reason = "SIO SERR occurred on on PCI bus"; break; + case MCHK_K_SIO_IOCHK: reason = "SIO IOCHK occurred on ISA bus"; break; + case MCHK_K_DCSR: reason = "MCHK_K_DCSR"; break; + case MCHK_K_UNKNOWN: + default: + sprintf(buf, "reason for machine-check unknown (0x%lx)", + el.c->code & 0xffffffff); + reason = buf; + break; + } + + wrmces(rdmces()); /* reset machine check pending flag */ + + switch (el.c->size) { + case sizeof(struct el_lca_mcheck_short): + printk(KERN_CRIT + " Reason: %s (short frame%s, dc_stat=%lx):\n", + reason, el.c->retry ? ", retryable" : "", + el.s->dc_stat); + if (el.s->esr & ESR_EAV) { + mem_error(el.s->esr, el.s->ear); + } + if (el.s->ioc_stat0 & IOC_ERR) { + ioc_error(el.s->ioc_stat0, el.s->ioc_stat1); + } + break; + + case sizeof(struct el_lca_mcheck_long): + printk(KERN_CRIT " Reason: %s (long frame%s):\n", + reason, el.c->retry ? ", retryable" : ""); + printk(KERN_CRIT + " reason: %lx exc_addr: %lx dc_stat: %lx\n", + el.l->pt[0], el.l->exc_addr, el.l->dc_stat); + printk(KERN_CRIT " car: %lx\n", el.l->car); + if (el.l->esr & ESR_EAV) { + mem_error(el.l->esr, el.l->ear); + } + if (el.l->ioc_stat0 & IOC_ERR) { + ioc_error(el.l->ioc_stat0, el.l->ioc_stat1); + } + break; + + default: + printk(KERN_CRIT " Unknown errorlog size %d\n", el.c->size); + } + + /* Dump the logout area to give all info. */ + + ptr = (unsigned long *) la; + for (i = 0; i < el.c->size / sizeof(long); i += 2) { + printk(KERN_CRIT " +%8lx %016lx %016lx\n", + i*sizeof(long), ptr[i], ptr[i+1]); + } +} + +/* + * The following routines are needed to support the SPEED changing + * necessary to successfully manage the thermal problem on the AlphaBook1. + */ + +void +lca_clock_print(void) +{ + long pmr_reg; + + pmr_reg = LCA_READ_PMR; + + printk("Status of clock control:\n"); + printk("\tPrimary clock divisor\t0x%lx\n", LCA_GET_PRIMARY(pmr_reg)); + printk("\tOverride clock divisor\t0x%lx\n", LCA_GET_OVERRIDE(pmr_reg)); + printk("\tInterrupt override is %s\n", + (pmr_reg & LCA_PMR_INTO) ? "on" : "off"); + printk("\tDMA override is %s\n", + (pmr_reg & LCA_PMR_DMAO) ? "on" : "off"); + +} + +int +lca_get_clock(void) +{ + long pmr_reg; + + pmr_reg = LCA_READ_PMR; + return(LCA_GET_PRIMARY(pmr_reg)); + +} + +void +lca_clock_fiddle(int divisor) +{ + long pmr_reg; + + pmr_reg = LCA_READ_PMR; + LCA_SET_PRIMARY_CLOCK(pmr_reg, divisor); + /* lca_norm_clock = divisor; */ + LCA_WRITE_PMR(pmr_reg); + mb(); +} diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/core_mcpcia.c linux/arch/alpha/kernel/core_mcpcia.c --- v2.1.115/linux/arch/alpha/kernel/core_mcpcia.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/core_mcpcia.c Thu Aug 13 15:36:01 1998 @@ -0,0 +1,970 @@ +/* + * linux/arch/alpha/kernel/core_mcpcia.c + * + * Code common to all MCbus-PCI Adaptor core logic chipsets + * + * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com). + * + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define __EXTERN_INLINE inline +#include +#include +#undef __EXTERN_INLINE + +#include "proto.h" + +/* + * NOTE: Herein lie back-to-back mb instructions. They are magic. + * One plausible explanation is that the i/o controller does not properly + * handle the system transaction. Another involves timing. Ho hum. + */ + +extern asmlinkage void wrmces(unsigned long mces); + +/* + * BIOS32-style PCI interface: + */ + +#undef DEBUG_CFG + +#ifdef DEBUG_CFG +# define DBG_CFG(args) printk args +#else +# define DBG_CFG(args) +#endif + +#undef DEBUG_PCI + +#ifdef DEBUG_PCI +# define DBG_PCI(args) printk args +#else +# define DBG_PCI(args) +#endif + +#define DEBUG_MCHECK + +#ifdef DEBUG_MCHECK +# define DBG_MCK(args) printk args +# define DEBUG_MCHECK_DUMP +#else +# define DBG_MCK(args) +#endif + +#define vuip volatile unsigned int * +#define vulp volatile unsigned long * + +static volatile unsigned int MCPCIA_mcheck_expected[NR_CPUS]; +static volatile unsigned int MCPCIA_mcheck_taken[NR_CPUS]; +static unsigned int MCPCIA_jd[NR_CPUS]; + +#define MCPCIA_MAX_HOSES 2 +static int mcpcia_num_hoses = 0; + +static int pci_probe_enabled = 0; /* disable to start */ + +static struct linux_hose_info *mcpcia_root = NULL, *mcpcia_last_hose; + +static inline unsigned long long_align(unsigned long addr) +{ + return ((addr + (sizeof(unsigned long) - 1)) & + ~(sizeof(unsigned long) - 1)); +} + + +/* + * Given a bus, device, and function number, compute resulting + * configuration space address and setup the MCPCIA_HAXR2 register + * accordingly. It is therefore not safe to have concurrent + * invocations to configuration space access routines, but there + * really shouldn't be any need for this. + * + * Type 0: + * + * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 + * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 31:11 Device select bit. + * 10:8 Function number + * 7:2 Register number + * + * Type 1: + * + * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 + * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 31:24 reserved + * 23:16 bus number (8 bits = 128 possible buses) + * 15:11 Device number (5 bits) + * 10:8 function number + * 7:2 register number + * + * Notes: + * The function number selects which function of a multi-function device + * (e.g., SCSI and Ethernet). + * + * The register selects a DWORD (32 bit) register offset. Hence it + * doesn't get shifted by 2 bits as we want to "drop" the bottom two + * bits. + */ + +static unsigned int +conf_read(unsigned long addr, unsigned char type1, + struct linux_hose_info *hose) +{ + unsigned long flags; + unsigned long hoseno = hose->pci_hose_index; + unsigned int stat0, value, temp, cpu; + + cpu = smp_processor_id(); + + save_and_cli(flags); + + DBG_CFG(("conf_read(addr=0x%lx, type1=%d, hose=%d)\n", + addr, type1, hoseno)); + + /* Reset status register to avoid losing errors. */ + stat0 = *(vuip)MCPCIA_CAP_ERR(hoseno); + *(vuip)MCPCIA_CAP_ERR(hoseno) = stat0; mb(); + temp = *(vuip)MCPCIA_CAP_ERR(hoseno); + DBG_CFG(("conf_read: MCPCIA CAP_ERR(%d) was 0x%x\n", hoseno, stat0)); + + mb(); + draina(); + MCPCIA_mcheck_expected[cpu] = 1; + MCPCIA_mcheck_taken[cpu] = 0; + mb(); + + /* Access configuration space. */ + value = *((vuip)addr); + mb(); + mb(); /* magic */ + + if (MCPCIA_mcheck_taken[cpu]) { + MCPCIA_mcheck_taken[cpu] = 0; + value = 0xffffffffU; + mb(); + } + MCPCIA_mcheck_expected[cpu] = 0; + mb(); + + DBG_CFG(("conf_read(): finished\n")); + + restore_flags(flags); + return value; +} + +static void +conf_write(unsigned long addr, unsigned int value, unsigned char type1, + struct linux_hose_info *hose) +{ + unsigned long flags; + unsigned long hoseno = hose->pci_hose_index; + unsigned int stat0, temp, cpu; + + cpu = smp_processor_id(); + + save_and_cli(flags); /* avoid getting hit by machine check */ + + /* Reset status register to avoid losing errors. */ + stat0 = *(vuip)MCPCIA_CAP_ERR(hoseno); + *(vuip)MCPCIA_CAP_ERR(hoseno) = stat0; mb(); + temp = *(vuip)MCPCIA_CAP_ERR(hoseno); + DBG_CFG(("conf_write: MCPCIA CAP_ERR(%d) was 0x%x\n", hoseno, stat0)); + + draina(); + MCPCIA_mcheck_expected[cpu] = 1; + mb(); + + /* Access configuration space. */ + *((vuip)addr) = value; + mb(); + mb(); /* magic */ + temp = *(vuip)MCPCIA_CAP_ERR(hoseno); /* read to force the write */ + MCPCIA_mcheck_expected[cpu] = 0; + mb(); + + DBG_CFG(("conf_write(): finished\n")); + restore_flags(flags); +} + +static int +mk_conf_addr(struct linux_hose_info *hose, + u8 bus, u8 device_fn, u8 where, + unsigned long *pci_addr, unsigned char *type1) +{ + unsigned long addr; + + if (!pci_probe_enabled) /* if doing standard pci_init(), ignore */ + return -1; + + DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x," + " pci_addr=0x%p, type1=0x%p)\n", + bus, device_fn, where, pci_addr, type1)); + + /* Type 1 configuration cycle for *ALL* busses. */ + *type1 = 1; + + if (hose->pci_first_busno == bus) + bus = 0; + addr = (bus << 16) | (device_fn << 8) | (where); + addr <<= 5; /* swizzle for SPARSE */ + addr |= hose->pci_config_space; + + *pci_addr = addr; + DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr)); + return 0; +} + +/* FIXME: At some point we should update these routines to use the new + PCI interface, which can jump through these hoops for us. */ + +static inline int +hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value, + struct linux_hose_info *hose) +{ + unsigned long addr; + unsigned char type1; + + *value = 0xff; + + if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= 0x00; + *value = conf_read(addr, type1, hose) >> ((where & 3) * 8); + return PCIBIOS_SUCCESSFUL; +} + +static inline int +hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value, + struct linux_hose_info *hose) +{ + unsigned long addr; + unsigned char type1; + + *value = 0xffff; + + if (where & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= 0x08; + *value = conf_read(addr, type1, hose) >> ((where & 3) * 8); + return PCIBIOS_SUCCESSFUL; +} + +static inline int +hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value, + struct linux_hose_info *hose) +{ + unsigned long addr; + unsigned char type1; + + *value = 0xffffffff; + + if (where & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= 0x18; + *value = conf_read(addr, type1, hose); + return PCIBIOS_SUCCESSFUL; +} + +static inline int +hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value, + struct linux_hose_info *hose) +{ + unsigned long addr; + unsigned char type1; + + if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= 0x00; + conf_write(addr, value << ((where & 3) * 8), type1, hose); + return PCIBIOS_SUCCESSFUL; +} + +static inline int +hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value, + struct linux_hose_info *hose) +{ + unsigned long addr; + unsigned char type1; + + if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= 0x08; + conf_write(addr, value << ((where & 3) * 8), type1, hose); + return PCIBIOS_SUCCESSFUL; +} + +static inline int +hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value, + struct linux_hose_info *hose) +{ + unsigned long addr; + unsigned char type1; + + if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= 0x18; + conf_write(addr, value << ((where & 3) * 8), type1, hose); + return PCIBIOS_SUCCESSFUL; +} + +int +mcpcia_pcibios_read_config_byte (u8 bus, u8 devfn, u8 where, u8 *value) +{ + return hose_read_config_byte(bus, devfn, where, value, bus2hose[bus]); +} + +int +mcpcia_pcibios_read_config_word (u8 bus, u8 devfn, u8 where, u16 *value) +{ + return hose_read_config_word(bus, devfn, where, value, bus2hose[bus]); +} + +int +mcpcia_pcibios_read_config_dword (u8 bus, u8 devfn, u8 where, u32 *value) +{ + return hose_read_config_dword(bus, devfn, where, value, bus2hose[bus]); +} + +int +mcpcia_pcibios_write_config_byte (u8 bus, u8 devfn, u8 where, u8 value) +{ + return hose_write_config_byte(bus, devfn, where, value, bus2hose[bus]); +} + +int +mcpcia_pcibios_write_config_word (u8 bus, u8 devfn, u8 where, u16 value) +{ + return hose_write_config_word(bus, devfn, where, value, bus2hose[bus]); +} + +int +mcpcia_pcibios_write_config_dword (u8 bus, u8 devfn, u8 where, u32 val) +{ + return hose_write_config_dword(bus, devfn, where, val, bus2hose[bus]); +} + +void __init +mcpcia_init_arch(unsigned long *mem_start, unsigned long *mem_end) +{ + struct linux_hose_info *hose; + unsigned int mcpcia_err; + unsigned int pci_rev; + int h; + + *mem_start = long_align(*mem_start); + + for (h = 0; h < NR_CPUS; h++) { + MCPCIA_mcheck_expected[h] = 0; + MCPCIA_mcheck_taken[h] = 0; + } + + /* First, find how many hoses we have. */ + for (h = 0; h < MCPCIA_MAX_HOSES; h++) { + pci_rev = *(vuip)MCPCIA_REV(h); +#if 0 + printk("mcpcia_init: got 0x%x for PCI_REV for hose %d\n", + pci_rev, h); +#endif + if ((pci_rev >> 16) == PCI_CLASS_BRIDGE_HOST) { + mcpcia_num_hoses++; + + hose = (struct linux_hose_info *)*mem_start; + *mem_start = long_align(*mem_start + sizeof(*hose)); + + memset(hose, 0, sizeof(*hose)); + + if (mcpcia_root) + mcpcia_last_hose->next = hose; + else + mcpcia_root = hose; + mcpcia_last_hose = hose; + + hose->pci_io_space = MCPCIA_IO(h); + hose->pci_mem_space = MCPCIA_DENSE(h); + hose->pci_config_space = MCPCIA_CONF(h); + hose->pci_sparse_space = MCPCIA_SPARSE(h); + hose->pci_hose_index = h; + hose->pci_first_busno = 255; + hose->pci_last_busno = 0; + } + } + +#if 1 + printk("mcpcia_init: found %d hoses\n", mcpcia_num_hoses); +#endif + + /* Now do init for each hose. */ + for (hose = mcpcia_root; hose; hose = hose->next) { + h = hose->pci_hose_index; +#if 0 + printk("mcpcia_init: -------- hose %d --------\n",h); + printk("MCPCIA_REV 0x%x\n", *(vuip)MCPCIA_REV(h)); + printk("MCPCIA_WHOAMI 0x%x\n", *(vuip)MCPCIA_WHOAMI(h)); + printk("MCPCIA_HAE_MEM 0x%x\n", *(vuip)MCPCIA_HAE_MEM(h)); + printk("MCPCIA_HAE_IO 0x%x\n", *(vuip)MCPCIA_HAE_IO(h)); + printk("MCPCIA_HAE_DENSE 0x%x\n", *(vuip)MCPCIA_HAE_DENSE(h)); + printk("MCPCIA_INT_CTL 0x%x\n", *(vuip)MCPCIA_INT_CTL(h)); + printk("MCPCIA_INT_REQ 0x%x\n", *(vuip)MCPCIA_INT_REQ(h)); + printk("MCPCIA_INT_TARG 0x%x\n", *(vuip)MCPCIA_INT_TARG(h)); + printk("MCPCIA_INT_ADR 0x%x\n", *(vuip)MCPCIA_INT_ADR(h)); + printk("MCPCIA_INT_ADR_EXT 0x%x\n", *(vuip)MCPCIA_INT_ADR_EXT(h)); + printk("MCPCIA_INT_MASK0 0x%x\n", *(vuip)MCPCIA_INT_MASK0(h)); + printk("MCPCIA_INT_MASK1 0x%x\n", *(vuip)MCPCIA_INT_MASK1(h)); + printk("MCPCIA_HBASE 0x%x\n", *(vuip)MCPCIA_HBASE(h)); +#endif + + /* + * Set up error reporting. Make sure CPU_PE is OFF in the mask. + */ +#if 0 + mcpcia_err = *(vuip)MCPCIA_ERR_MASK(h); + mcpcia_err &= ~4; + *(vuip)MCPCIA_ERR_MASK(h) = mcpcia_err; + mb(); + mcpcia_err = *(vuip)MCPCIA_ERR_MASK; +#endif + + mcpcia_err = *(vuip)MCPCIA_CAP_ERR(h); + mcpcia_err |= 0x0006; /* master/target abort */ + *(vuip)MCPCIA_CAP_ERR(h) = mcpcia_err; + mb() ; + mcpcia_err = *(vuip)MCPCIA_CAP_ERR(h); + + switch (alpha_use_srm_setup) + { + default: +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) + /* Check window 0 for enabled and mapped to 0. */ + if (((*(vuip)MCPCIA_W0_BASE(h) & 3) == 1) + && (*(vuip)MCPCIA_T0_BASE(h) == 0) + && ((*(vuip)MCPCIA_W0_MASK(h) & 0xfff00000U) > 0x0ff00000U)) { + MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W0_BASE(h) & 0xfff00000U; + MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W0_MASK(h) & 0xfff00000U; + MCPCIA_DMA_WIN_SIZE += 0x00100000U; +#if 1 + printk("mcpcia_init: using Window 0 settings\n"); + printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", + *(vuip)MCPCIA_W0_BASE(h), + *(vuip)MCPCIA_W0_MASK(h), + *(vuip)MCPCIA_T0_BASE(h)); +#endif + break; + } + + /* Check window 1 for enabled and mapped to 0. */ + if (((*(vuip)MCPCIA_W1_BASE(h) & 3) == 1) + && (*(vuip)MCPCIA_T1_BASE(h) == 0) + && ((*(vuip)MCPCIA_W1_MASK(h) & 0xfff00000U) > 0x0ff00000U)) { + MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W1_BASE(h) & 0xfff00000U; + MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W1_MASK(h) & 0xfff00000U; + MCPCIA_DMA_WIN_SIZE += 0x00100000U; +#if 1 + printk("mcpcia_init: using Window 1 settings\n"); + printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", + *(vuip)MCPCIA_W1_BASE(h), + *(vuip)MCPCIA_W1_MASK(h), + *(vuip)MCPCIA_T1_BASE(h)); +#endif + break; + } + + /* Check window 2 for enabled and mapped to 0. */ + if (((*(vuip)MCPCIA_W2_BASE(h) & 3) == 1) + && (*(vuip)MCPCIA_T2_BASE(h) == 0) + && ((*(vuip)MCPCIA_W2_MASK(h) & 0xfff00000U) > 0x0ff00000U)) { + MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W2_BASE(h) & 0xfff00000U; + MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W2_MASK(h) & 0xfff00000U; + MCPCIA_DMA_WIN_SIZE += 0x00100000U; +#if 1 + printk("mcpcia_init: using Window 2 settings\n"); + printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", + *(vuip)MCPCIA_W2_BASE(h), + *(vuip)MCPCIA_W2_MASK(h), + *(vuip)MCPCIA_T2_BASE(h)); +#endif + break; + } + + /* Check window 3 for enabled and mapped to 0. */ + if (((*(vuip)MCPCIA_W3_BASE(h) & 3) == 1) + && (*(vuip)MCPCIA_T3_BASE(h) == 0) + && ((*(vuip)MCPCIA_W3_MASK(h) & 0xfff00000U) > 0x0ff00000U)) { + MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W3_BASE(h) & 0xfff00000U; + MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W3_MASK(h) & 0xfff00000U; + MCPCIA_DMA_WIN_SIZE += 0x00100000U; +#if 1 + printk("mcpcia_init: using Window 3 settings\n"); + printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", + *(vuip)MCPCIA_W3_BASE(h), + *(vuip)MCPCIA_W3_MASK(h), + *(vuip)MCPCIA_T3_BASE(h)); +#endif + break; + } + + /* Otherwise, we must use our defaults. */ + MCPCIA_DMA_WIN_BASE = MCPCIA_DMA_WIN_BASE_DEFAULT; + MCPCIA_DMA_WIN_SIZE = MCPCIA_DMA_WIN_SIZE_DEFAULT; +#endif + case 0: + /* + * Set up the PCI->physical memory translation windows. + * For now, windows 1,2 and 3 are disabled. In the + * future, we may want to use them to do scatter/ + * gather DMA. + * + * Window 0 goes at 1 GB and is 1 GB large. + */ + + *(vuip)MCPCIA_W0_BASE(h) = 1U | (MCPCIA_DMA_WIN_BASE_DEFAULT & 0xfff00000U); + *(vuip)MCPCIA_W0_MASK(h) = (MCPCIA_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U; + *(vuip)MCPCIA_T0_BASE(h) = 0; + + *(vuip)MCPCIA_W1_BASE(h) = 0x0 ; + *(vuip)MCPCIA_W2_BASE(h) = 0x0 ; + *(vuip)MCPCIA_W3_BASE(h) = 0x0 ; + + *(vuip)MCPCIA_HBASE(h) = 0x0 ; + mb(); + break; + } +#if 0 + { + unsigned int mcpcia_int_ctl = *((vuip)MCPCIA_INT_CTL(h)); + printk("mcpcia_init: INT_CTL was 0x%x\n", mcpcia_int_ctl); + *(vuip)MCPCIA_INT_CTL(h) = 1U; mb(); + mcpcia_int_ctl = *(vuip)MCPCIA_INT_CTL(h); + } +#endif + + /* + * Sigh... For the SRM setup, unless we know apriori what the HAE + * contents will be, we need to setup the arbitrary region bases + * so we can test against the range of addresses and tailor the + * region chosen for the SPARSE memory access. + * + * See include/asm-alpha/mcpcia.h for the SPARSE mem read/write. + */ + if (alpha_use_srm_setup) { + unsigned int mcpcia_hae_mem = *(vuip)MCPCIA_HAE_MEM(h); + + alpha_mv.sm_base_r1 = (mcpcia_hae_mem ) & 0xe0000000UL; + alpha_mv.sm_base_r2 = (mcpcia_hae_mem << 16) & 0xf8000000UL; + alpha_mv.sm_base_r3 = (mcpcia_hae_mem << 24) & 0xfc000000UL; + + /* + * Set the HAE cache, so that setup_arch() code + * will use the SRM setting always. Our readb/writeb + * code in mcpcia.h expects never to have to change + * the contents of the HAE. + */ + alpha_mv.hae_cache = mcpcia_hae_mem; + + alpha_mv.mv_readb = mcpcia_srm_readb; + alpha_mv.mv_readw = mcpcia_srm_readw; + alpha_mv.mv_writeb = mcpcia_srm_writeb; + alpha_mv.mv_writew = mcpcia_srm_writew; + } else { + *(vuip)MCPCIA_HAE_MEM(h) = 0U; mb(); + *(vuip)MCPCIA_HAE_MEM(h); /* read it back. */ + *(vuip)MCPCIA_HAE_IO(h) = 0; mb(); + *(vuip)MCPCIA_HAE_IO(h); /* read it back. */ + } + } +} + +static int +mcpcia_pci_clr_err(int h) +{ + unsigned int cpu = smp_processor_id(); + + MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(h); +#if 0 + DBG_MCK(("MCPCIA_pci_clr_err: MCPCIA CAP_ERR(%d) after read 0x%x\n", + h, MCPCIA_jd[cpu])); +#endif + *(vuip)MCPCIA_CAP_ERR(h) = 0xffffffff; mb(); /* clear them all */ + MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(h); + return 0; +} + +static void +mcpcia_print_uncorrectable(struct el_MCPCIA_uncorrected_frame_mcheck *logout) +{ + struct el_common_EV5_uncorrectable_mcheck *frame; + int i; + + frame = &logout->procdata; + + /* Print PAL fields */ + for (i = 0; i < 24; i += 2) { + printk("\tpal temp[%d-%d]\t\t= %16lx %16lx\n\r", + i, i+1, frame->paltemp[i], frame->paltemp[i+1]); + } + for (i = 0; i < 8; i += 2) { + printk("\tshadow[%d-%d]\t\t= %16lx %16lx\n\r", + i, i+1, frame->shadow[i], + frame->shadow[i+1]); + } + printk("\tAddr of excepting instruction\t= %16lx\n\r", + frame->exc_addr); + printk("\tSummary of arithmetic traps\t= %16lx\n\r", + frame->exc_sum); + printk("\tException mask\t\t\t= %16lx\n\r", + frame->exc_mask); + printk("\tBase address for PALcode\t= %16lx\n\r", + frame->pal_base); + printk("\tInterrupt Status Reg\t\t= %16lx\n\r", + frame->isr); + printk("\tCURRENT SETUP OF EV5 IBOX\t= %16lx\n\r", + frame->icsr); + printk("\tI-CACHE Reg %s parity error\t= %16lx\n\r", + (frame->ic_perr_stat & 0x800L) ? + "Data" : "Tag", + frame->ic_perr_stat); + printk("\tD-CACHE error Reg\t\t= %16lx\n\r", + frame->dc_perr_stat); + if (frame->dc_perr_stat & 0x2) { + switch (frame->dc_perr_stat & 0x03c) { + case 8: + printk("\t\tData error in bank 1\n\r"); + break; + case 4: + printk("\t\tData error in bank 0\n\r"); + break; + case 20: + printk("\t\tTag error in bank 1\n\r"); + break; + case 10: + printk("\t\tTag error in bank 0\n\r"); + break; + } + } + printk("\tEffective VA\t\t\t= %16lx\n\r", + frame->va); + printk("\tReason for D-stream\t\t= %16lx\n\r", + frame->mm_stat); + printk("\tEV5 SCache address\t\t= %16lx\n\r", + frame->sc_addr); + printk("\tEV5 SCache TAG/Data parity\t= %16lx\n\r", + frame->sc_stat); + printk("\tEV5 BC_TAG_ADDR\t\t\t= %16lx\n\r", + frame->bc_tag_addr); + printk("\tEV5 EI_ADDR: Phys addr of Xfer\t= %16lx\n\r", + frame->ei_addr); + printk("\tFill Syndrome\t\t\t= %16lx\n\r", + frame->fill_syndrome); + printk("\tEI_STAT reg\t\t\t= %16lx\n\r", + frame->ei_stat); + printk("\tLD_LOCK\t\t\t\t= %16lx\n\r", + frame->ld_lock); +} + +void +mcpcia_machine_check(unsigned long type, unsigned long la_ptr, + struct pt_regs * regs) +{ +#if 0 + printk("mcpcia machine check ignored\n") ; +#else + struct el_common *mchk_header; + struct el_MCPCIA_uncorrected_frame_mcheck *mchk_logout; + unsigned int cpu = smp_processor_id(); + int h = 0; + + mchk_header = (struct el_common *)la_ptr; + mchk_logout = (struct el_MCPCIA_uncorrected_frame_mcheck *)la_ptr; + +#if 0 + DBG_MCK(("mcpcia_machine_check: type=0x%lx la_ptr=0x%lx\n", + type, la_ptr)); + DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", + regs->pc, mchk_header->size, mchk_header->proc_offset, + mchk_header->sys_offset)); +#endif + /* + * Check if machine check is due to a badaddr() and if so, + * ignore the machine check. + */ + mb(); + mb(); /* magic */ + if (MCPCIA_mcheck_expected[cpu]) { +#if 0 + DBG_MCK(("MCPCIA machine check expected\n")); +#endif + MCPCIA_mcheck_expected[cpu] = 0; + MCPCIA_mcheck_taken[cpu] = 1; + mb(); + mb(); /* magic */ + draina(); + mcpcia_pci_clr_err(h); + wrmces(0x7); + mb(); + } +#if 1 + else { + printk("MCPCIA machine check NOT expected on CPU %d\n", cpu); + DBG_MCK(("mcpcia_machine_check: type=0x%lx pc=0x%lx" + " code=0x%lx\n", + type, regs->pc, mchk_header->code)); + + MCPCIA_mcheck_expected[cpu] = 0; + MCPCIA_mcheck_taken[cpu] = 1; + mb(); + mb(); /* magic */ + draina(); + mcpcia_pci_clr_err(h); + wrmces(0x7); + mb(); +#ifdef DEBUG_MCHECK_DUMP + if (type == 0x620) + printk("MCPCIA machine check: system CORRECTABLE!\n"); + else if (type == 0x630) + printk("MCPCIA machine check: processor CORRECTABLE!\n"); + else + mcpcia_print_uncorrectable(mchk_logout); +#endif /* DEBUG_MCHECK_DUMP */ + } +#endif +#endif +} + +/*==========================================================================*/ + +#define PRIMARY(b) ((b)&0xff) +#define SECONDARY(b) (((b)>>8)&0xff) +#define SUBORDINATE(b) (((b)>>16)&0xff) + +static int __init +hose_scan_bridges(struct linux_hose_info *hose, unsigned char bus) +{ + unsigned int devfn, l, class; + unsigned char hdr_type = 0; + unsigned int found = 0; + + for (devfn = 0; devfn < 0xff; ++devfn) { + if (PCI_FUNC(devfn) == 0) { + hose_read_config_byte(bus, devfn, PCI_HEADER_TYPE, + &hdr_type, hose); + } else if (!(hdr_type & 0x80)) { + /* not a multi-function device */ + continue; + } + + /* Check if there is anything here. */ + hose_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l, hose); + if (l == 0xffffffff || l == 0x00000000) { + hdr_type = 0; + continue; + } + + /* See if this is a bridge device. */ + hose_read_config_dword(bus, devfn, PCI_CLASS_REVISION, + &class, hose); + + if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) { + unsigned int busses; + + found++; + + hose_read_config_dword(bus, devfn, PCI_PRIMARY_BUS, + &busses, hose); + + DBG_PCI(("hose_scan_bridges: hose %d bus %d " + "slot %d busses 0x%x\n", + hose->pci_hose_index, bus, PCI_SLOT(devfn), + busses)); + + /* + * Do something with first_busno and last_busno + */ + if (hose->pci_first_busno > PRIMARY(busses)) { + hose->pci_first_busno = PRIMARY(busses); + DBG_PCI(("hose_scan_bridges: hose %d bus %d " + "slot %d change first to %d\n", + hose->pci_hose_index, bus, + PCI_SLOT(devfn), PRIMARY(busses))); + } + if (hose->pci_last_busno < SUBORDINATE(busses)) { + hose->pci_last_busno = SUBORDINATE(busses); + DBG_PCI(("hose_scan_bridges: hose %d bus %d " + "slot %d change last to %d\n", + hose->pci_hose_index, bus, + PCI_SLOT(devfn), + SUBORDINATE(busses))); + } + /* + * Now scan everything underneath the bridge. + */ + hose_scan_bridges(hose, SECONDARY(busses)); + } + } + return found; +} + +static void __init +hose_reconfigure_bridges(struct linux_hose_info *hose, unsigned char bus) +{ + unsigned int devfn, l, class; + unsigned char hdr_type = 0; + + for (devfn = 0; devfn < 0xff; ++devfn) { + if (PCI_FUNC(devfn) == 0) { + hose_read_config_byte(bus, devfn, PCI_HEADER_TYPE, + &hdr_type, hose); + } else if (!(hdr_type & 0x80)) { + /* not a multi-function device */ + continue; + } + + /* Check if there is anything here. */ + hose_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l, hose); + if (l == 0xffffffff || l == 0x00000000) { + hdr_type = 0; + continue; + } + + /* See if this is a bridge device. */ + hose_read_config_dword(bus, devfn, PCI_CLASS_REVISION, + &class, hose); + + if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) { + unsigned int busses; + + hose_read_config_dword(bus, devfn, PCI_PRIMARY_BUS, + &busses, hose); + + /* + * First reconfigure everything underneath the bridge. + */ + hose_reconfigure_bridges(hose, (busses >> 8) & 0xff); + + /* + * Unconfigure this bridges bus numbers, + * pci_scan_bus() will fix this up properly. + */ + busses &= 0xff000000; + hose_write_config_dword(bus, devfn, PCI_PRIMARY_BUS, + busses, hose); + } + } +} + +static void __init +mcpcia_fixup_busno(struct linux_hose_info *hose, unsigned char bus) +{ + unsigned int nbus; + + /* + * First, scan for all bridge devices underneath this hose, + * to determine the first and last busnos. + */ + if (!hose_scan_bridges(hose, 0)) { + /* none found, exit */ + hose->pci_first_busno = bus; + hose->pci_last_busno = bus; + } else { + /* + * Reconfigure all bridge devices underneath this hose. + */ + hose_reconfigure_bridges(hose, hose->pci_first_busno); + } + + /* + * Now reconfigure the hose to it's new bus number and set up + * our bus2hose mapping for this hose. + */ + nbus = hose->pci_last_busno - hose->pci_first_busno; + + hose->pci_first_busno = bus; + + DBG_PCI(("mcpcia_fixup_busno: hose %d startbus %d nbus %d\n", + hose->pci_hose_index, bus, nbus)); + + do { + bus2hose[bus++] = hose; + } while (nbus-- > 0); +} + +static void __init +mcpcia_probe(struct linux_hose_info *hose) +{ + static struct pci_bus *pchain = NULL; + struct pci_bus *pbus = &hose->pci_bus; + static unsigned char busno = 0; + + /* + * Hoses include child PCI bridges in bus-range property, + * but we don't scan each of those ourselves, Linux generic PCI + * probing code will find child bridges and link them into this + * hose's root PCI device hierarchy. + */ + + pbus->number = pbus->secondary = busno; + pbus->sysdata = hose; + + mcpcia_fixup_busno(hose, busno); + + pbus->subordinate = pci_scan_bus(pbus); /* the original! */ + + /* + * Set the maximum subordinate bus of this hose. + */ + hose->pci_last_busno = pbus->subordinate; +#if 0 + hose_write_config_byte(busno, 0, 0x41, hose->pci_last_busno, hose); +#endif + busno = pbus->subordinate + 1; + + /* + * Fixup the chain of primary PCI busses. + */ + if (pchain) { + pchain->next = &hose->pci_bus; + pchain = pchain->next; + } else { + pchain = &pci_root; + memcpy(pchain, &hose->pci_bus, sizeof(pci_root)); + } +} + +void __init +mcpcia_pci_fixup(void) +{ + struct linux_hose_info *hose; + + /* Turn on Config space access finally! */ + pci_probe_enabled = 1; + + /* For each hose, probe and setup the devices on the hose. */ + for (hose = mcpcia_root; hose; hose = hose->next) + mcpcia_probe(hose); +} diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/core_pyxis.c linux/arch/alpha/kernel/core_pyxis.c --- v2.1.115/linux/arch/alpha/kernel/core_pyxis.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/core_pyxis.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,634 @@ +/* + * linux/arch/alpha/kernel/core_pyxis.c + * + * Code common to all PYXIS core logic chips. + * + * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com). + * + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +#define __EXTERN_INLINE inline +#include +#include +#undef __EXTERN_INLINE + +#include "proto.h" + +/* NOTE: Herein are back-to-back mb instructions. They are magic. + One plausible explanation is that the I/O controller does not properly + handle the system transaction. Another involves timing. Ho hum. */ + +extern asmlinkage void wrmces(unsigned long mces); + +/* + * BIOS32-style PCI interface: + */ + +#ifdef DEBUG +# define DBG(args) printk args +#else +# define DBG(args) +#endif + +#define DEBUG_MCHECK +#ifdef DEBUG_MCHECK +# define DBG_MCK(args) printk args +#define DEBUG_MCHECK_DUMP +#else +# define DBG_MCK(args) +#endif + + +static volatile unsigned int PYXIS_mcheck_expected = 0; +static volatile unsigned int PYXIS_mcheck_taken = 0; +static unsigned int PYXIS_jd; + + +/* + * Given a bus, device, and function number, compute resulting + * configuration space address and setup the PYXIS_HAXR2 register + * accordingly. It is therefore not safe to have concurrent + * invocations to configuration space access routines, but there + * really shouldn't be any need for this. + * + * Type 0: + * + * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 + * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 31:11 Device select bit. + * 10:8 Function number + * 7:2 Register number + * + * Type 1: + * + * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 + * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 31:24 reserved + * 23:16 bus number (8 bits = 128 possible buses) + * 15:11 Device number (5 bits) + * 10:8 function number + * 7:2 register number + * + * Notes: + * The function number selects which function of a multi-function device + * (e.g., SCSI and Ethernet). + * + * The register selects a DWORD (32 bit) register offset. Hence it + * doesn't get shifted by 2 bits as we want to "drop" the bottom two + * bits. + */ + +static int +mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, + unsigned char *type1) +{ + unsigned long addr; + + DBG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x," + " pci_addr=0x%p, type1=0x%p)\n", + bus, device_fn, where, pci_addr, type1)); + + if (bus == 0) { + int device; + + device = device_fn >> 3; + /* Type 0 configuration cycle. */ +#if NOT_NOW + if (device > 20) { + DBG(("mk_conf_addr: device (%d) > 20, returning -1\n", + device)); + return -1; + } +#endif + *type1 = 0; + addr = (device_fn << 8) | (where); + } else { + /* Type 1 configuration cycle. */ + *type1 = 1; + addr = (bus << 16) | (device_fn << 8) | (where); + } + *pci_addr = addr; + DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr)); + return 0; +} + +static unsigned int +conf_read(unsigned long addr, unsigned char type1) +{ + unsigned long flags; + unsigned int stat0, value, temp; + unsigned int pyxis_cfg = 0; + + save_and_cli(flags); /* avoid getting hit by machine check */ + + DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1)); + + /* Reset status register to avoid losing errors. */ + stat0 = *(vuip)PYXIS_ERR; + *(vuip)PYXIS_ERR = stat0; mb(); + temp = *(vuip)PYXIS_ERR; /* re-read to force write */ + DBG(("conf_read: PYXIS ERR was 0x%x\n", stat0)); + + /* If Type1 access, must set PYXIS CFG. */ + if (type1) { + pyxis_cfg = *(vuip)PYXIS_CFG; + *(vuip)PYXIS_CFG = pyxis_cfg | 1; mb(); + temp = *(vuip)PYXIS_CFG; /* re-read to force write */ + DBG(("conf_read: TYPE1 access\n")); + } + + mb(); + draina(); + PYXIS_mcheck_expected = 1; + PYXIS_mcheck_taken = 0; + mb(); + + /* Access configuration space. */ + value = *(vuip)addr; + mb(); + mb(); /* magic */ + + if (PYXIS_mcheck_taken) { + PYXIS_mcheck_taken = 0; + value = 0xffffffffU; + mb(); + } + PYXIS_mcheck_expected = 0; + mb(); + + /* If Type1 access, must reset IOC CFG so normal IO space ops work. */ + if (type1) { + *(vuip)PYXIS_CFG = pyxis_cfg & ~1; mb(); + temp = *(vuip)PYXIS_CFG; /* re-read to force write */ + } + + DBG(("conf_read(): finished\n")); + + restore_flags(flags); + return value; +} + +static void +conf_write(unsigned long addr, unsigned int value, unsigned char type1) +{ + unsigned long flags; + unsigned int stat0, temp; + unsigned int pyxis_cfg = 0; + + save_and_cli(flags); /* avoid getting hit by machine check */ + + /* Reset status register to avoid losing errors. */ + stat0 = *(vuip)PYXIS_ERR; + *(vuip)PYXIS_ERR = stat0; mb(); + temp = *(vuip)PYXIS_ERR; /* re-read to force write */ + DBG(("conf_write: PYXIS ERR was 0x%x\n", stat0)); + + /* If Type1 access, must set PYXIS CFG. */ + if (type1) { + pyxis_cfg = *(vuip)PYXIS_CFG; + *(vuip)PYXIS_CFG = pyxis_cfg | 1; mb(); + temp = *(vuip)PYXIS_CFG; /* re-read to force write */ + DBG(("conf_read: TYPE1 access\n")); + } + + draina(); + PYXIS_mcheck_expected = 1; + mb(); + + /* Access configuration space. */ + *(vuip)addr = value; + mb(); + mb(); /* magic */ + temp = *(vuip)PYXIS_ERR; /* do a PYXIS read to force the write */ + PYXIS_mcheck_expected = 0; + mb(); + + /* If Type1 access, must reset IOC CFG so normal IO space ops work. */ + if (type1) { + *(vuip)PYXIS_CFG = pyxis_cfg & ~1; mb(); + temp = *(vuip)PYXIS_CFG; /* re-read to force write */ + } + + DBG(("conf_write(): finished\n")); + restore_flags(flags); +} + +int +pyxis_pcibios_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value) +{ + unsigned long addr = PYXIS_CONF; + unsigned long pci_addr; + unsigned char type1; + + *value = 0xff; + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x00; + *value = conf_read(addr, type1) >> ((where & 3) * 8); + return PCIBIOS_SUCCESSFUL; +} + +int +pyxis_pcibios_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value) +{ + unsigned long addr = PYXIS_CONF; + unsigned long pci_addr; + unsigned char type1; + + *value = 0xffff; + if (where & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x08; + *value = conf_read(addr, type1) >> ((where & 3) * 8); + return PCIBIOS_SUCCESSFUL; +} + +int +pyxis_pcibios_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value) +{ + unsigned long addr = PYXIS_CONF; + unsigned long pci_addr; + unsigned char type1; + + *value = 0xffffffff; + if (where & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x18; + *value = conf_read(addr, type1); + return PCIBIOS_SUCCESSFUL; +} + +int +pyxis_pcibios_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value) +{ + unsigned long addr = PYXIS_CONF; + unsigned long pci_addr; + unsigned char type1; + + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x00; + conf_write(addr, value << ((where & 3) * 8), type1); + return PCIBIOS_SUCCESSFUL; +} + +int +pyxis_pcibios_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value) +{ + unsigned long addr = PYXIS_CONF; + unsigned long pci_addr; + unsigned char type1; + + if (where & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x08; + conf_write(addr, value << ((where & 3) * 8), type1); + return PCIBIOS_SUCCESSFUL; +} + +int +pyxis_pcibios_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value) +{ + unsigned long addr = PYXIS_CONF; + unsigned long pci_addr; + unsigned char type1; + + if (where & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x18; + conf_write(addr, value << ((where & 3) * 8), type1); + return PCIBIOS_SUCCESSFUL; +} + +void __init +pyxis_enable_errors (void) +{ + unsigned int pyxis_err; + +#if 0 + printk("pyxis_init: PYXIS_ERR_MASK 0x%x\n", *(vuip)PYXIS_ERR_MASK); + printk("pyxis_init: PYXIS_ERR 0x%x\n", *(vuip)PYXIS_ERR); + printk("pyxis_init: PYXIS_INT_REQ 0x%lx\n", *(vulp)PYXIS_INT_REQ); + printk("pyxis_init: PYXIS_INT_MASK 0x%lx\n", *(vulp)PYXIS_INT_MASK); + printk("pyxis_init: PYXIS_INT_ROUTE 0x%lx\n", *(vulp)PYXIS_INT_ROUTE); + printk("pyxis_init: PYXIS_INT_HILO 0x%lx\n", *(vulp)PYXIS_INT_HILO); + printk("pyxis_init: PYXIS_INT_CNFG 0x%x\n", *(vuip)PYXIS_INT_CNFG); + printk("pyxis_init: PYXIS_RT_COUNT 0x%lx\n", *(vulp)PYXIS_RT_COUNT); +#endif + + /* + * Set up error reporting. Make sure CPU_PE is OFF in the mask. + */ + pyxis_err = *(vuip)PYXIS_ERR_MASK; + pyxis_err &= ~4; + *(vuip)PYXIS_ERR_MASK = pyxis_err; mb(); + pyxis_err = *(vuip)PYXIS_ERR_MASK; /* re-read to force write */ + + pyxis_err = *(vuip)PYXIS_ERR ; + pyxis_err |= 0x180; /* master/target abort */ + *(vuip)PYXIS_ERR = pyxis_err; mb(); + pyxis_err = *(vuip)PYXIS_ERR; /* re-read to force write */ +} + +int __init +pyxis_srm_window_setup (void) +{ + switch (alpha_use_srm_setup) + { + default: +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) + /* Check window 0 for enabled and mapped to 0. */ + if (((*(vuip)PYXIS_W0_BASE & 3) == 1) + && (*(vuip)PYXIS_T0_BASE == 0) + && ((*(vuip)PYXIS_W0_MASK & 0xfff00000U) > 0x0ff00000U)) { + PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W0_BASE & 0xfff00000U; + PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W0_MASK & 0xfff00000U; + PYXIS_DMA_WIN_SIZE += 0x00100000U; +#if 1 + printk("pyxis_init: using Window 0 settings\n"); + printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", + *(vuip)PYXIS_W0_BASE, + *(vuip)PYXIS_W0_MASK, + *(vuip)PYXIS_T0_BASE); +#endif + break; + } + + /* Check window 1 for enabled and mapped to 0. */ + if (((*(vuip)PYXIS_W1_BASE & 3) == 1) + && (*(vuip)PYXIS_T1_BASE == 0) + && ((*(vuip)PYXIS_W1_MASK & 0xfff00000U) > 0x0ff00000U)) { + PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W1_BASE & 0xfff00000U; + PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W1_MASK & 0xfff00000U; + PYXIS_DMA_WIN_SIZE += 0x00100000U; +#if 1 + printk("pyxis_init: using Window 1 settings\n"); + printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", + *(vuip)PYXIS_W1_BASE, + *(vuip)PYXIS_W1_MASK, + *(vuip)PYXIS_T1_BASE); +#endif + break; + } + + /* Check window 2 for enabled and mapped to 0. */ + if (((*(vuip)PYXIS_W2_BASE & 3) == 1) + && (*(vuip)PYXIS_T2_BASE == 0) + && ((*(vuip)PYXIS_W2_MASK & 0xfff00000U) > 0x0ff00000U)) { + PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W2_BASE & 0xfff00000U; + PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W2_MASK & 0xfff00000U; + PYXIS_DMA_WIN_SIZE += 0x00100000U; +#if 1 + printk("pyxis_init: using Window 2 settings\n"); + printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", + *(vuip)PYXIS_W2_BASE, + *(vuip)PYXIS_W2_MASK, + *(vuip)PYXIS_T2_BASE); +#endif + break; + } + + /* Check window 3 for enabled and mapped to 0. */ + if (((*(vuip)PYXIS_W3_BASE & 3) == 1) + && (*(vuip)PYXIS_T3_BASE == 0) + && ((*(vuip)PYXIS_W3_MASK & 0xfff00000U) > 0x0ff00000U)) { + PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W3_BASE & 0xfff00000U; + PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W3_MASK & 0xfff00000U; + PYXIS_DMA_WIN_SIZE += 0x00100000U; +#if 1 + printk("pyxis_init: using Window 3 settings\n"); + printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", + *(vuip)PYXIS_W3_BASE, + *(vuip)PYXIS_W3_MASK, + *(vuip)PYXIS_T3_BASE); +#endif + break; + } + + /* Otherwise, we must use our defaults. */ + PYXIS_DMA_WIN_BASE = PYXIS_DMA_WIN_BASE_DEFAULT; + PYXIS_DMA_WIN_SIZE = PYXIS_DMA_WIN_SIZE_DEFAULT; +#endif + case 0: + return 0; + } + return 1; +} + +void __init +pyxis_native_window_setup(void) +{ + /* + * Set up the PCI->physical memory translation windows. + * For now, windows 1,2 and 3 are disabled. In the future, we may + * want to use them to do scatter/gather DMA. + * + * Window 0 goes at 1 GB and is 1 GB large. + */ + + *(vuip)PYXIS_W0_BASE = 1U | (PYXIS_DMA_WIN_BASE_DEFAULT & 0xfff00000U); + *(vuip)PYXIS_W0_MASK = (PYXIS_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U; + *(vuip)PYXIS_T0_BASE = 0; + + *(vuip)PYXIS_W1_BASE = 0x0 ; + *(vuip)PYXIS_W2_BASE = 0x0 ; + *(vuip)PYXIS_W3_BASE = 0x0 ; + mb(); +} + +void __init +pyxis_finish_init_arch(void) +{ + /* + * Next, clear the PYXIS_CFG register, which gets used + * for PCI Config Space accesses. That is the way + * we want to use it, and we do not want to depend on + * what ARC or SRM might have left behind... + */ + { + unsigned int pyxis_cfg, temp; + pyxis_cfg = *(vuip)PYXIS_CFG; mb(); + if (pyxis_cfg != 0) { +#if 1 + printk("PYXIS_init: CFG was 0x%x\n", pyxis_cfg); +#endif + *(vuip)PYXIS_CFG = 0; mb(); + temp = *(vuip)PYXIS_CFG; /* re-read to force write */ + } + } + + /* + * Sigh... For the SRM setup, unless we know apriori what the HAE + * contents will be, we need to setup the arbitrary region bases + * so we can test against the range of addresses and tailor the + * region chosen for the SPARSE memory access. + * + * See include/asm-alpha/pyxis.h for the SPARSE mem read/write. + */ + if (alpha_use_srm_setup) { + unsigned int pyxis_hae_mem = *(vuip)PYXIS_HAE_MEM; + + alpha_mv.sm_base_r1 = (pyxis_hae_mem ) & 0xe0000000UL; + alpha_mv.sm_base_r2 = (pyxis_hae_mem << 16) & 0xf8000000UL; + alpha_mv.sm_base_r3 = (pyxis_hae_mem << 24) & 0xfc000000UL; + + /* + * Set the HAE cache, so that setup_arch() code + * will use the SRM setting always. Our readb/writeb + * code in pyxis.h expects never to have to change + * the contents of the HAE. + */ + alpha_mv.hae_cache = pyxis_hae_mem; + +#ifndef CONFIG_ALPHA_GENERIC + /* In a generic kernel, we can always use BWIO. */ + alpha_mv.mv_readb = pyxis_srm_readb; + alpha_mv.mv_readw = pyxis_srm_readw; + alpha_mv.mv_writeb = pyxis_srm_writeb; + alpha_mv.mv_writew = pyxis_srm_writew; +#endif + } else { + *(vuip)PYXIS_HAE_MEM = 0U; mb(); + *(vuip)PYXIS_HAE_MEM; /* re-read to force write */ + *(vuip)PYXIS_HAE_IO = 0; mb(); + *(vuip)PYXIS_HAE_IO; /* re-read to force write */ + } + + /* + * Finally, check that the PYXIS_CTRL1 has IOA_BEN set for + * enabling byte/word PCI bus space(s) access. + */ + { + unsigned int ctrl1; + ctrl1 = *(vuip) PYXIS_CTRL1; + if (!(ctrl1 & 1)) { +#if 1 + printk("PYXIS_init: enabling byte/word PCI space\n"); +#endif + *(vuip) PYXIS_CTRL1 = ctrl1 | 1; mb(); + ctrl1 = *(vuip)PYXIS_CTRL1; /* re-read */ + } + } +} + +void __init +pyxis_init_arch(unsigned long *mem_start, unsigned long *mem_end) +{ + pyxis_enable_errors(); + if (!pyxis_srm_window_setup()) + pyxis_native_window_setup(); + pyxis_finish_init_arch(); +} + +static int +pyxis_pci_clr_err(void) +{ + PYXIS_jd = *(vuip)PYXIS_ERR; + DBG(("PYXIS_pci_clr_err: PYXIS ERR after read 0x%x\n", PYXIS_jd)); + *(vuip)PYXIS_ERR = 0x0180; mb(); + PYXIS_jd = *(vuip)PYXIS_ERR; /* re-read to force write */ + return 0; +} + +void +pyxis_machine_check(unsigned long vector, unsigned long la_ptr, + struct pt_regs * regs) +{ + struct el_common *mchk_header; + struct el_PYXIS_sysdata_mcheck *mchk_sysdata; + + mchk_header = (struct el_common *)la_ptr; + + mchk_sysdata = (struct el_PYXIS_sysdata_mcheck *) + (la_ptr + mchk_header->sys_offset); + +#if 0 + DBG_MCK(("pyxis_machine_check: vector=0x%lx la_ptr=0x%lx\n", + vector, la_ptr)); + DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", + regs->pc, mchk_header->size, mchk_header->proc_offset, + mchk_header->sys_offset)); + DBG_MCK(("pyxis_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n", + PYXIS_mcheck_expected, mchk_sysdata->epic_dcsr, + mchk_sysdata->epic_pear)); +#endif +#ifdef DEBUG_MCHECK_DUMP + { + unsigned long *ptr; + int i; + + ptr = (unsigned long *)la_ptr; + for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { + printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]); + } + } +#endif /* DEBUG_MCHECK_DUMP */ + + /* + * Check if machine check is due to a badaddr() and if so, + * ignore the machine check. + */ + mb(); + mb(); /* magic */ + if (PYXIS_mcheck_expected) { + DBG(("PYXIS machine check expected\n")); + PYXIS_mcheck_expected = 0; + PYXIS_mcheck_taken = 1; + mb(); + mb(); /* magic */ + draina(); + pyxis_pci_clr_err(); + wrmces(0x7); + mb(); + } +#if 1 + else { + printk("PYXIS machine check NOT expected\n") ; + DBG_MCK(("pyxis_machine_check: vector=0x%lx la_ptr=0x%lx\n", + vector, la_ptr)); + DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x" + " sysoffset 0x%x\n", + regs->pc, mchk_header->size, mchk_header->proc_offset, + mchk_header->sys_offset)); + PYXIS_mcheck_expected = 0; + PYXIS_mcheck_taken = 1; + mb(); + mb(); /* magic */ + draina(); + pyxis_pci_clr_err(); + wrmces(0x7); + mb(); + } +#endif +} diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/core_t2.c linux/arch/alpha/kernel/core_t2.c --- v2.1.115/linux/arch/alpha/kernel/core_t2.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/core_t2.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,628 @@ +/* + * linux/arch/alpha/kernel/core_t2.c + * + * Code common to all T2 core logic chips. + * + * Written by Jay A Estabrook (jestabro@amt.tay1.dec.com). + * December 1996. + * + * based on CIA code by David A Rusling (david.rusling@reo.mts.dec.com) + * + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +#define __EXTERN_INLINE +#include +#include +#undef __EXTERN_INLINE + +#include "proto.h" + +/* + * NOTE: Herein lie back-to-back mb instructions. They are magic. + * One plausible explanation is that the i/o controller does not properly + * handle the system transaction. Another involves timing. Ho hum. + */ + +/* + * Machine check reasons. Defined according to PALcode sources + * (osf.h and platform.h). + */ +#define MCHK_K_TPERR 0x0080 +#define MCHK_K_TCPERR 0x0082 +#define MCHK_K_HERR 0x0084 +#define MCHK_K_ECC_C 0x0086 +#define MCHK_K_ECC_NC 0x0088 +#define MCHK_K_OS_BUGCHECK 0x008A +#define MCHK_K_PAL_BUGCHECK 0x0090 + +/* + * BIOS32-style PCI interface: + */ + +#ifdef DEBUG_CONF +# define DBG(args) printk args +#else +# define DBG(args) +#endif + +#ifdef DEBUG_MCHECK +# define DBGMC(args) printk args +#else +# define DBGMC(args) +#endif + +static volatile unsigned int T2_mcheck_expected[NR_CPUS]; +static volatile unsigned int T2_mcheck_taken[NR_CPUS]; + + +/* + * Given a bus, device, and function number, compute resulting + * configuration space address and setup the T2_HAXR2 register + * accordingly. It is therefore not safe to have concurrent + * invocations to configuration space access routines, but there + * really shouldn't be any need for this. + * + * Type 0: + * + * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 + * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 31:11 Device select bit. + * 10:8 Function number + * 7:2 Register number + * + * Type 1: + * + * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 + * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 31:24 reserved + * 23:16 bus number (8 bits = 128 possible buses) + * 15:11 Device number (5 bits) + * 10:8 function number + * 7:2 register number + * + * Notes: + * The function number selects which function of a multi-function device + * (e.g., SCSI and Ethernet). + * + * The register selects a DWORD (32 bit) register offset. Hence it + * doesn't get shifted by 2 bits as we want to "drop" the bottom two + * bits. + */ + +static int +mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, + unsigned char *type1) +{ + unsigned long addr; + + DBG(("mk_conf_addr(bus=%d, dfn=0x%x, where=0x%x," + " addr=0x%lx, type1=0x%x)\n", + bus, device_fn, where, pci_addr, type1)); + + if (bus == 0) { + int device = device_fn >> 3; + + /* Type 0 configuration cycle. */ + + if (device > 8) { + DBG(("mk_conf_addr: device (%d)>20, returning -1\n", + device)); + return -1; + } + + *type1 = 0; + addr = (0x0800L << device) | ((device_fn & 7) << 8) | (where); + } else { + /* Type 1 configuration cycle. */ + *type1 = 1; + addr = (bus << 16) | (device_fn << 8) | (where); + } + *pci_addr = addr; + DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr)); + return 0; +} + +static unsigned int +conf_read(unsigned long addr, unsigned char type1) +{ + unsigned long flags; + unsigned int stat0, value, cpu; + unsigned long t2_cfg = 0; + + cpu = smp_processor_id(); + + save_flags(flags); /* avoid getting hit by machine check */ + cli(); + + DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1)); + +#if 0 + /* Reset status register to avoid losing errors. */ + stat0 = *(vulp)T2_IOCSR; + *(vulp)T2_IOCSR = stat0; + mb(); + DBG(("conf_read: T2 IOCSR was 0x%x\n", stat0)); +#endif + + /* If Type1 access, must set T2 CFG. */ + if (type1) { + t2_cfg = *(vulp)T2_HAE_3 & ~0xc0000000UL; + *(vulp)T2_HAE_3 = 0x40000000UL | t2_cfg; + mb(); + DBG(("conf_read: TYPE1 access\n")); + } + mb(); + draina(); + + T2_mcheck_expected[cpu] = 1; + T2_mcheck_taken[cpu] = 0; + mb(); + + /* Access configuration space. */ + value = *(vuip)addr; + mb(); + mb(); /* magic */ + + if (T2_mcheck_taken[cpu]) { + T2_mcheck_taken[cpu] = 0; + value = 0xffffffffU; + mb(); + } + T2_mcheck_expected[cpu] = 0; + mb(); + + /* If Type1 access, must reset T2 CFG so normal IO space ops work. */ + if (type1) { + *(vulp)T2_HAE_3 = t2_cfg; + mb(); + } + DBG(("conf_read(): finished\n")); + + restore_flags(flags); + return value; +} + +static void +conf_write(unsigned long addr, unsigned int value, unsigned char type1) +{ + unsigned long flags; + unsigned int stat0, cpu; + unsigned long t2_cfg = 0; + + cpu = smp_processor_id(); + + save_flags(flags); /* avoid getting hit by machine check */ + cli(); + +#if 0 + /* Reset status register to avoid losing errors. */ + stat0 = *(vulp)T2_IOCSR; + *(vulp)T2_IOCSR = stat0; + mb(); + DBG(("conf_write: T2 ERR was 0x%x\n", stat0)); +#endif + + /* If Type1 access, must set T2 CFG. */ + if (type1) { + t2_cfg = *(vulp)T2_HAE_3 & ~0xc0000000UL; + *(vulp)T2_HAE_3 = t2_cfg | 0x40000000UL; + mb(); + DBG(("conf_write: TYPE1 access\n")); + } + mb(); + draina(); + + T2_mcheck_expected[cpu] = 1; + mb(); + + /* Access configuration space. */ + *(vuip)addr = value; + mb(); + mb(); /* magic */ + + T2_mcheck_expected[cpu] = 0; + mb(); + + /* If Type1 access, must reset T2 CFG so normal IO space ops work. */ + if (type1) { + *(vulp)T2_HAE_3 = t2_cfg; + mb(); + } + DBG(("conf_write(): finished\n")); + restore_flags(flags); +} + + +int +t2_pcibios_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value) +{ + unsigned long addr = T2_CONF; + unsigned long pci_addr; + unsigned char type1; + + *value = 0xff; + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x00; + *value = conf_read(addr, type1) >> ((where & 3) * 8); + return PCIBIOS_SUCCESSFUL; +} + +int +t2_pcibios_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value) +{ + unsigned long addr = T2_CONF; + unsigned long pci_addr; + unsigned char type1; + + *value = 0xffff; + if (where & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x08; + *value = conf_read(addr, type1) >> ((where & 3) * 8); + return PCIBIOS_SUCCESSFUL; +} + +int +t2_pcibios_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value) +{ + unsigned long addr = T2_CONF; + unsigned long pci_addr; + unsigned char type1; + + *value = 0xffffffff; + if (where & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x18; + *value = conf_read(addr, type1); + return PCIBIOS_SUCCESSFUL; +} + +int +t2_pcibios_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value) +{ + unsigned long addr = T2_CONF; + unsigned long pci_addr; + unsigned char type1; + + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x00; + conf_write(addr, value << ((where & 3) * 8), type1); + return PCIBIOS_SUCCESSFUL; +} + +int +t2_pcibios_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value) +{ + unsigned long addr = T2_CONF; + unsigned long pci_addr; + unsigned char type1; + + if (where & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x08; + conf_write(addr, value << ((where & 3) * 8), type1); + return PCIBIOS_SUCCESSFUL; +} + +int +t2_pcibios_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value) +{ + unsigned long addr = T2_CONF; + unsigned long pci_addr; + unsigned char type1; + + if (where & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr |= (pci_addr << 5) + 0x18; + conf_write(addr, value << ((where & 3) * 8), type1); + return PCIBIOS_SUCCESSFUL; +} + +void __init +t2_init_arch(unsigned long *mem_start, unsigned long *mem_end) +{ + unsigned long t2_err; + unsigned int i; + + for (i = 0; i < NR_CPUS; i++) { + T2_mcheck_expected[i] = 0; + T2_mcheck_taken[i] = 0; + } + +#if 0 + /* + * Set up error reporting. + */ + t2_err = *(vulp)T2_IOCSR ; + t2_err |= (0x1 << 7) ; /* master abort */ + *(vulp)T2_IOCSR = t2_err ; + mb() ; +#endif + + printk("t2_init: HBASE was 0x%lx\n", *(vulp)T2_HBASE); +#if 0 + printk("t2_init: WBASE1=0x%lx WMASK1=0x%lx TBASE1=0x%lx\n", + *(vulp)T2_WBASE1, + *(vulp)T2_WMASK1, + *(vulp)T2_TBASE1); + printk("t2_init: WBASE2=0x%lx WMASK2=0x%lx TBASE2=0x%lx\n", + *(vulp)T2_WBASE2, + *(vulp)T2_WMASK2, + *(vulp)T2_TBASE2); +#endif + + switch (alpha_use_srm_setup) + { + default: +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) + /* Check window 1 for enabled and mapped to 0. */ + if (((*(vulp)T2_WBASE1 & (3UL<<18)) == (2UL<<18)) + && (*(vulp)T2_TBASE1 == 0)) { + T2_DMA_WIN_BASE = *(vulp)T2_WBASE1 & 0xfff00000UL; + T2_DMA_WIN_SIZE = *(vulp)T2_WMASK1 & 0xfff00000UL; + T2_DMA_WIN_SIZE += 0x00100000UL; + /* DISABLE window 2!! ?? */ +#if 1 + printk("t2_init: using Window 1 settings\n"); + printk("t2_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n", + *(vulp)T2_WBASE1, + *(vulp)T2_WMASK1, + *(vulp)T2_TBASE1); +#endif + break; + } + + /* Check window 2 for enabled and mapped to 0. */ + if (((*(vulp)T2_WBASE2 & (3UL<<18)) == (2UL<<18)) + && (*(vulp)T2_TBASE2 == 0)) { + T2_DMA_WIN_BASE = *(vulp)T2_WBASE2 & 0xfff00000UL; + T2_DMA_WIN_SIZE = *(vulp)T2_WMASK2 & 0xfff00000UL; + T2_DMA_WIN_SIZE += 0x00100000UL; + /* DISABLE window 1!! ?? */ +#if 1 + printk("t2_init: using Window 2 settings\n"); + printk("t2_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n", + *(vulp)T2_WBASE2, + *(vulp)T2_WMASK2, + *(vulp)T2_TBASE2); +#endif + break; + } + + /* Otherwise, we must use our defaults. */ + T2_DMA_WIN_BASE = T2_DMA_WIN_BASE_DEFAULT; + T2_DMA_WIN_SIZE = T2_DMA_WIN_SIZE_DEFAULT; +#endif + case 0: + /* + * Set up the PCI->physical memory translation windows. + * For now, window 2 is disabled. In the future, we may + * want to use it to do scatter/gather DMA. + * + * Window 1 goes at 1 GB and is 1 GB large. + */ + + /* WARNING!! must correspond to the DMA_WIN params!!! */ + *(vulp)T2_WBASE1 = 0x400807ffU; + *(vulp)T2_WMASK1 = 0x3ff00000U; + *(vulp)T2_TBASE1 = 0; + + *(vulp)T2_WBASE2 = 0x0; + *(vulp)T2_HBASE = 0x0; + break; + } + + /* + * Sigh... For the SRM setup, unless we know apriori what the HAE + * contents will be, we need to setup the arbitrary region bases + * so we can test against the range of addresses and tailor the + * region chosen for the SPARSE memory access. + * + * See include/asm-alpha/t2.h for the SPARSE mem read/write. + */ + if (alpha_use_srm_setup) { + unsigned long t2_hae_1 = *(vulp)T2_HAE_1; + + alpha_mv.sm_base_r1 = (t2_hae_1 << 27) & 0xf8000000UL; + + /* + * Set the HAE cache, so that setup_arch() code + * will use the SRM setting always. Our readb/writeb + * code in .h expects never to have to change + * the contents of the HAE. + */ + alpha_mv.hae_cache = t2_hae_1; + + alpha_mv.mv_readb = t2_srm_readb; + alpha_mv.mv_readw = t2_srm_readw; + alpha_mv.mv_writeb = t2_srm_writeb; + alpha_mv.mv_writew = t2_srm_writew; + } else { + *(vulp)T2_HAE_1 = 0; mb(); + *(vulp)T2_HAE_2 = 0; mb(); + *(vulp)T2_HAE_3 = 0; mb(); +#if 0 + *(vulp)T2_HAE_4 = 0; mb(); /* do not touch this */ +#endif + } +} + +#define SIC_SEIC (1UL << 33) /* System Event Clear */ + +static int +t2_clear_errors(void) +{ + unsigned int cpu = smp_processor_id(); + static struct sable_cpu_csr *cpu_regs = NULL; + + switch (cpu) + { + case 0: cpu_regs = (struct sable_cpu_csr *)T2_CPU0_BASE; break; + case 1: cpu_regs = (struct sable_cpu_csr *)T2_CPU1_BASE; break; + case 2: cpu_regs = (struct sable_cpu_csr *)T2_CPU2_BASE; break; + case 3: cpu_regs = (struct sable_cpu_csr *)T2_CPU3_BASE; break; + } + + DBGMC(("???????? t2_clear_errors\n")); + + cpu_regs->sic &= ~SIC_SEIC; + + /* + * clear CPU errors + */ + cpu_regs->bcce |= cpu_regs->bcce; + cpu_regs->cbe |= cpu_regs->cbe; + cpu_regs->bcue |= cpu_regs->bcue; + cpu_regs->dter |= cpu_regs->dter; + + *(vulp)T2_CERR1 |= *(vulp)T2_CERR1; + *(vulp)T2_PERR1 |= *(vulp)T2_PERR1; + + mb(); + mb(); /* magic */ + return 0; +} + +void +t2_machine_check(unsigned long vector, unsigned long la_ptr, + struct pt_regs * regs) +{ + struct el_t2_logout_header *mchk_header; + struct el_t2_procdata_mcheck *mchk_procdata; + struct el_t2_sysdata_mcheck *mchk_sysdata; + unsigned long * ptr; + const char * reason; + char buf[128]; + long i; + unsigned int cpu = smp_processor_id(); + + DBGMC(("t2_machine_check: vector=0x%lx la_ptr=0x%lx\n", + vector, la_ptr)); + + mchk_header = (struct el_t2_logout_header *)la_ptr; + + DBGMC(("t2_machine_check: susoffset=0x%lx procoffset=0x%lx\n", + mchk_header->elfl_sysoffset, mchk_header->elfl_procoffset)); + + mchk_sysdata = (struct el_t2_sysdata_mcheck *) + (la_ptr + mchk_header->elfl_sysoffset); + mchk_procdata = (struct el_t2_procdata_mcheck *) + (la_ptr + mchk_header->elfl_procoffset - sizeof(unsigned long)*32); + + DBGMC((" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", + regs->pc, mchk_header->elfl_size, mchk_header->elfl_procoffset, + mchk_header->elfl_sysoffset)); + DBGMC(("t2_machine_check: expected %d\n", T2_mcheck_expected[cpu])); + +#ifdef DEBUG_DUMP + { + unsigned long *ptr; + int i; + + ptr = (unsigned long *)la_ptr; + for (i = 0; i < mchk_header->elfl_size/sizeof(long); i += 2) { + printk(" +%lx %lx %lx\n", i*sizeof(long), + ptr[i], ptr[i+1]); + } + } +#endif /* DEBUG_DUMP */ + + /* + * Check if machine check is due to a badaddr() and if so, + * ignore the machine check. + */ + mb(); + mb(); /* magic */ + if (T2_mcheck_expected[cpu]) { + DBGMC(("T2 machine check expected\n")); + T2_mcheck_taken[cpu] = 1; + t2_clear_errors(); + T2_mcheck_expected[cpu] = 0; + mb(); + mb(); /* magic */ + wrmces(rdmces()|1);/* ??? */ + draina(); + return; + } + + switch ((unsigned int) mchk_header->elfl_error_type) { + case MCHK_K_TPERR: reason = "tag parity error"; break; + case MCHK_K_TCPERR: reason = "tag control parity error"; break; + case MCHK_K_HERR: reason = "generic hard error"; break; + case MCHK_K_ECC_C: reason = "correctable ECC error"; break; + case MCHK_K_ECC_NC: reason = "uncorrectable ECC error"; break; + case MCHK_K_OS_BUGCHECK: reason = "OS-specific PAL bugcheck"; break; + case MCHK_K_PAL_BUGCHECK: reason = "callsys in kernel mode"; break; + case 0x96: reason = "i-cache read retryable error"; break; + case 0x98: reason = "processor detected hard error"; break; + + /* System specific (these are for Alcor, at least): */ + case 0x203: reason = "system detected uncorrectable ECC error"; break; + case 0x205: reason = "parity error detected by T2"; break; + case 0x207: reason = "non-existent memory error"; break; + case 0x209: reason = "PCI SERR detected"; break; + case 0x20b: reason = "PCI data parity error detected"; break; + case 0x20d: reason = "PCI address parity error detected"; break; + case 0x20f: reason = "PCI master abort error"; break; + case 0x211: reason = "PCI target abort error"; break; + case 0x213: reason = "scatter/gather PTE invalid error"; break; + case 0x215: reason = "flash ROM write error"; break; + case 0x217: reason = "IOA timeout detected"; break; + case 0x219: reason = "IOCHK#, EISA add-in board parity or other catastrophic error"; break; + case 0x21b: reason = "EISA fail-safe timer timeout"; break; + case 0x21d: reason = "EISA bus time-out"; break; + case 0x21f: reason = "EISA software generated NMI"; break; + case 0x221: reason = "unexpected ev5 IRQ[3] interrupt"; break; + default: + sprintf(buf, "reason for machine-check unknown (0x%x)", + (unsigned int) mchk_header->elfl_error_type); + reason = buf; + break; + } + wrmces(rdmces()|1); /* reset machine check pending flag */ + mb(); + + printk(KERN_CRIT " T2 machine check: %s%s\n", + reason, mchk_header->elfl_retry ? " (retryable)" : ""); + + /* Dump the logout area to give all info. */ + + ptr = (unsigned long *)la_ptr; + for (i = 0; i < mchk_header->elfl_size / sizeof(long); i += 2) { + printk(KERN_CRIT " +%8lx %016lx %016lx\n", + i*sizeof(long), ptr[i], ptr[i+1]); + } +} diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/core_tsunami.c linux/arch/alpha/kernel/core_tsunami.c --- v2.1.115/linux/arch/alpha/kernel/core_tsunami.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/core_tsunami.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,446 @@ +/* + * linux/arch/alpha/kernel/core_tsunami.c + * + * Code common to all TSUNAMI core logic chips. + * + * Based on code written by David A. Rusling (david.rusling@reo.mts.dec.com). + * + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +#define __EXTERN_INLINE inline +#include +#include +#undef __EXTERN_INLINE + +#include "proto.h" + +/* + * NOTE: Herein lie back-to-back mb instructions. They are magic. + * One plausible explanation is that the I/O controller does not properly + * handle the system transaction. Another involves timing. Ho hum. + */ + +/* + * BIOS32-style PCI interface: + */ + +#ifdef DEBUG +# define DBG(args) printk args +#else +# define DBG(args) +#endif + +#define DEBUG_MCHECK +#ifdef DEBUG_MCHECK +# define DBG_MCK(args) printk args +#define DEBUG_MCHECK_DUMP +#else +# define DBG_MCK(args) +#endif + +static volatile unsigned int TSUNAMI_mcheck_expected[NR_CPUS]; +static volatile unsigned int TSUNAMI_mcheck_taken[NR_CPUS]; +static unsigned int TSUNAMI_jd[NR_CPUS]; + + +/* + * Given a bus, device, and function number, compute resulting + * configuration space address + * accordingly. It is therefore not safe to have concurrent + * invocations to configuration space access routines, but there + * really shouldn't be any need for this. + * + * Note that all config space accesses use Type 1 address format. + * + * Note also that type 1 is determined by non-zero bus number. + * + * Type 1: + * + * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 + * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 31:24 reserved + * 23:16 bus number (8 bits = 128 possible buses) + * 15:11 Device number (5 bits) + * 10:8 function number + * 7:2 register number + * + * Notes: + * The function number selects which function of a multi-function device + * (e.g., SCSI and Ethernet). + * + * The register selects a DWORD (32 bit) register offset. Hence it + * doesn't get shifted by 2 bits as we want to "drop" the bottom two + * bits. + */ + +static int +mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, + unsigned char *type1) +{ + unsigned long addr; + + DBG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, " + "pci_addr=0x%p, type1=0x%p)\n", + bus, device_fn, where, pci_addr, type1)); + + if (bus == 0) { + *type1 = 0; + } else { + /* Type 1 configuration cycle. */ + *type1 = 1; + } + addr = (bus << 16) | (device_fn << 8) | (where); + *pci_addr = addr; + DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr)); + return 0; +} + +int +tsunami_pcibios_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value) +{ + unsigned long addr; + unsigned char type1; + + *value = 0xff; + if (mk_conf_addr(bus, device_fn, where, &addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + *value = __kernel_ldbu(*(vucp)(addr+TSUNAMI_PCI0_CONF)); + return PCIBIOS_SUCCESSFUL; +} + +int +tsunami_pcibios_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value) +{ + unsigned long addr; + unsigned char type1; + + *value = 0xffff; + if (where & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + *value = __kernel_ldwu(*(vusp)(addr+TSUNAMI_PCI0_CONF)); + return PCIBIOS_SUCCESSFUL; +} + +int +tsunami_pcibios_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value) +{ + unsigned long addr; + unsigned char type1; + + *value = 0xffffffff; + if (where & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + *value = *(vuip)(addr+TSUNAMI_PCI0_CONF); + return PCIBIOS_SUCCESSFUL; +} + +int +tsunami_pcibios_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value) +{ + unsigned long addr; + unsigned char type1; + + if (mk_conf_addr(bus, device_fn, where, &addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + __kernel_stb(value, *(vucp)(addr+TSUNAMI_PCI0_CONF)); + return PCIBIOS_SUCCESSFUL; +} + +int +tsunami_pcibios_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value) +{ + unsigned long addr; + unsigned char type1; + + if (where & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + __kernel_stw(value, *(vusp)(addr+TSUNAMI_PCI0_CONF)); + return PCIBIOS_SUCCESSFUL; +} + +int +tsunami_pcibios_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value) +{ + unsigned long addr; + unsigned char type1; + + if (where & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (mk_conf_addr(bus, device_fn, where, &addr, &type1)) + return PCIBIOS_DEVICE_NOT_FOUND; + + *(vuip)(addr+TSUNAMI_PCI0_CONF) = value; + return PCIBIOS_SUCCESSFUL; +} + +void __init +tsunami_init_arch(unsigned long *mem_start, unsigned long *mem_end) +{ + unsigned long tsunami_err; + unsigned int i; + +#if 0 + printk("tsunami_init: CChip registers:\n"); + printk("CSR_CSC 0x%lx\n", *(vulp)TSUNAMI_CSR_CSC); + printk("CSR_MTR 0x%lx\n", *(vulp)TSUNAMI_CSR_MTR); + printk("CSR_MISC 0x%lx\n", *(vulp)TSUNAMI_CSR_MISC); + printk("CSR_DIM0 0x%lx\n", *(vulp)TSUNAMI_CSR_DIM0); + printk("CSR_DIM1 0x%lx\n", *(vulp)TSUNAMI_CSR_DIM1); + printk("CSR_DIR0 0x%lx\n", *(vulp)TSUNAMI_CSR_DIR0); + printk("CSR_DIR1 0x%lx\n", *(vulp)TSUNAMI_CSR_DIR1); + printk("CSR_DRIR 0x%lx\n", *(vulp)TSUNAMI_CSR_DRIR); + + printk("tsunami_init: DChip registers:\n"); + printk("CSR_DSC 0x%lx\n", *(vulp)TSUNAMI_CSR_DSC); + printk("CSR_STR 0x%lx\n", *(vulp)TSUNAMI_CSR_STR); + printk("CSR_DREV 0x%lx\n", *(vulp)TSUNAMI_CSR_DREV); + + printk("tsunami_init: PChip registers:\n"); + printk("PCHIP0_WSBA0 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA0); + printk("PCHIP0_WSBA1 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA1); + printk("PCHIP0_WSBA2 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA2); + printk("PCHIP0_WSBA3 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA3); + printk("PCHIP0_WSM0 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM0); + printk("PCHIP0_WSM1 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM1); + printk("PCHIP0_WSM2 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM2); + printk("PCHIP0_WSM3 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM3); + printk("PCHIP0_TBA0 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA0); + printk("PCHIP0_TBA1 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA1); + printk("PCHIP0_TBA2 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA2); + printk("PCHIP0_TBA3 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA3); + printk("PCHIP0_PCTL 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PCTL); + printk("PCHIP0_PLAT 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PLAT); + printk("PCHIP0_PERROR 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PERROR); + printk("PCHIP0_PERRMASK 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PERRMASK); +#endif + + for (i = 0; i < NR_CPUS; i++) { + TSUNAMI_mcheck_expected[i] = 0; + TSUNAMI_mcheck_taken[i] = 0; + } + +#ifdef NOT_YET + /* + * Set up error reporting. Make sure CPU_PE is OFF in the mask. + */ + tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERRMASK; + tsunami_err &= ~20; + *(vulp)TSUNAMI_PCHIP0_PERRMASK = tsunami_err; + mb(); + tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERRMASK; + + tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERROR ; + tsunami_err |= 0x40; /* master/target abort */ + *(vulp)TSUNAMI_PCHIP0_PERROR = tsunami_err ; + mb() ; + tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERROR ; +#endif /* NOT_YET */ + + switch (alpha_use_srm_setup) + { + default: +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) + /* Check window 0 for enabled and mapped to 0. */ + if (((*(vulp)TSUNAMI_PCHIP0_WSBA0 & 3) == 1) + && (*(vulp)TSUNAMI_PCHIP0_TBA0 == 0) + && ((*(vulp)TSUNAMI_PCHIP0_WSM0 & 0xfff00000U) > 0x0ff00000U)) { + TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA0 & 0xfff00000U; + TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM0 & 0xfff00000U; + TSUNAMI_DMA_WIN_SIZE += 0x00100000U; +#if 1 + printk("tsunami_init: using Window 0 settings\n"); + printk("tsunami_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n", + *(vulp)TSUNAMI_PCHIP0_WSBA0, + *(vulp)TSUNAMI_PCHIP0_WSM0, + *(vulp)TSUNAMI_PCHIP0_TBA0); +#endif + break; + } + + /* Check window 1 for enabled and mapped to 0. */ + if (((*(vulp)TSUNAMI_PCHIP0_WSBA1 & 3) == 1) + && (*(vulp)TSUNAMI_PCHIP0_TBA1 == 0) + && ((*(vulp)TSUNAMI_PCHIP0_WSM1 & 0xfff00000U) > 0x0ff00000U)) { + TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA1 & 0xfff00000U; + TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM1 & 0xfff00000U; + TSUNAMI_DMA_WIN_SIZE += 0x00100000U; +#if 1 + printk("tsunami_init: using Window 1 settings\n"); + printk("tsunami_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n", + *(vulp)TSUNAMI_PCHIP0_WSBA1, + *(vulp)TSUNAMI_PCHIP0_WSM1, + *(vulp)TSUNAMI_PCHIP0_TBA1); +#endif + break; + } + + /* Check window 2 for enabled and mapped to 0. */ + if (((*(vulp)TSUNAMI_PCHIP0_WSBA2 & 3) == 1) + && (*(vulp)TSUNAMI_PCHIP0_TBA2 == 0) + && ((*(vulp)TSUNAMI_PCHIP0_WSM2 & 0xfff00000U) > 0x0ff00000U)) { + TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA2 & 0xfff00000U; + TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM2 & 0xfff00000U; + TSUNAMI_DMA_WIN_SIZE += 0x00100000U; +#if 1 + printk("tsunami_init: using Window 2 settings\n"); + printk("tsunami_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n", + *(vulp)TSUNAMI_PCHIP0_WSBA2, + *(vulp)TSUNAMI_PCHIP0_WSM2, + *(vulp)TSUNAMI_PCHIP0_TBA2); +#endif + break; + } + + /* Check window 3 for enabled and mapped to 0. */ + if (((*(vulp)TSUNAMI_PCHIP0_WSBA3 & 3) == 1) + && (*(vulp)TSUNAMI_PCHIP0_TBA3 == 0) + && ((*(vulp)TSUNAMI_PCHIP0_WSM3 & 0xfff00000U) > 0x0ff00000U)) { + TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA3 & 0xfff00000U; + TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM3 & 0xfff00000U; + TSUNAMI_DMA_WIN_SIZE += 0x00100000U; +#if 1 + printk("tsunami_init: using Window 3 settings\n"); + printk("tsunami_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n", + *(vulp)TSUNAMI_PCHIP0_WSBA3, + *(vulp)TSUNAMI_PCHIP0_WSM3, + *(vulp)TSUNAMI_PCHIP0_TBA3); +#endif + break; + } + + /* Otherwise, we must use our defaults. */ + TSUNAMI_DMA_WIN_BASE = TSUNAMI_DMA_WIN_BASE_DEFAULT; + TSUNAMI_DMA_WIN_SIZE = TSUNAMI_DMA_WIN_SIZE_DEFAULT; +#endif + case 0: + /* + * Set up the PCI->physical memory translation windows. + * For now, windows 1,2 and 3 are disabled. In the future, + * we may want to use them to do scatter/gather DMA. + * + * Window 0 goes at 1 GB and is 1 GB large. + */ + + *(vulp)TSUNAMI_PCHIP0_WSBA0 + = 1L | (TSUNAMI_DMA_WIN_BASE_DEFAULT & 0xfff00000U); + *(vulp)TSUNAMI_PCHIP0_WSM0 + = (TSUNAMI_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000UL; + *(vulp)TSUNAMI_PCHIP0_TBA0 = 0UL; + + *(vulp)TSUNAMI_PCHIP0_WSBA1 = 0UL; + *(vulp)TSUNAMI_PCHIP0_WSBA2 = 0UL; + *(vulp)TSUNAMI_PCHIP0_WSBA3 = 0UL; + mb(); + } +} + +static int +tsunami_pci_clr_err(void) +{ + unsigned int cpu = smp_processor_id(); + + TSUNAMI_jd[cpu] = *((vulp)TSUNAMI_PCHIP0_PERROR); + DBG(("TSUNAMI_pci_clr_err: PERROR after read 0x%x\n",TSUNAMI_jd[cpu])); + *((vulp)TSUNAMI_PCHIP0_PERROR) = 0x040; mb(); + TSUNAMI_jd[cpu] = *((vulp)TSUNAMI_PCHIP0_PERROR); + return 0; +} + +void +tsunami_machine_check(unsigned long vector, unsigned long la_ptr, + struct pt_regs * regs) +{ +#if 1 + printk("TSUNAMI machine check ignored\n") ; +#else + struct el_common *mchk_header; + struct el_TSUNAMI_sysdata_mcheck *mchk_sysdata; + unsigned int cpu = smp_processor_id(); + + mchk_header = (struct el_common *)la_ptr; + + mchk_sysdata = (struct el_TSUNAMI_sysdata_mcheck *) + (la_ptr + mchk_header->sys_offset); + +#if 0 + DBG_MCK(("tsunami_machine_check: vector=0x%lx la_ptr=0x%lx\n", + vector, la_ptr)); + DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", + regs->pc, mchk_header->size, mchk_header->proc_offset, + mchk_header->sys_offset)); + DBG_MCK(("tsunami_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n", + TSUNAMI_mcheck_expected[cpu], mchk_sysdata->epic_dcsr, + mchk_sysdata->epic_pear)); +#endif +#ifdef DEBUG_MCHECK_DUMP + { + unsigned long *ptr; + int i; + + ptr = (unsigned long *)la_ptr; + for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { + printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]); + } + } +#endif /* DEBUG_MCHECK_DUMP */ + /* + * Check if machine check is due to a badaddr() and if so, + * ignore the machine check. + */ + mb(); + mb(); /* magic */ + if (TSUNAMI_mcheck_expected[cpu]) { + DBG(("TSUNAMI machine check expected\n")); + TSUNAMI_mcheck_expected[cpu] = 0; + TSUNAMI_mcheck_taken[cpu] = 1; + mb(); + mb(); /* magic */ + draina(); + tsunami_pci_clr_err(); + wrmces(0x7); + mb(); + } +#if 1 + else { + printk("TSUNAMI machine check NOT expected\n") ; + DBG_MCK(("tsunami_machine_check: vector=0x%lx la_ptr=0x%lx\n", + vector, la_ptr)); + DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", + regs->pc, mchk_header->size, mchk_header->proc_offset, + mchk_header->sys_offset)); + TSUNAMI_mcheck_expected[cpu] = 0; + TSUNAMI_mcheck_taken[cpu] = 1; + mb(); + mb(); /* magic */ + draina(); + tsunami_pci_clr_err(); + wrmces(0x7); + mb(); + } +#endif +#endif +} diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S --- v2.1.115/linux/arch/alpha/kernel/entry.S Sun Jul 26 11:57:14 1998 +++ linux/arch/alpha/kernel/entry.S Sun Aug 9 12:25:11 1998 @@ -15,7 +15,7 @@ #define osf_vfork sys_fork /* - * These offsets must match with "struct hae" in io.h: + * These offsets must match with alpha_mv in . */ #define HAE_CACHE 0 #define HAE_REG 8 @@ -109,7 +109,7 @@ stq $3,24($30); \ stq $4,32($30); \ stq $28,144($30); \ - lda $2,hae; \ + lda $2,alpha_mv; \ stq $5,40($30); \ stq $6,48($30); \ stq $7,56($30); \ @@ -130,7 +130,7 @@ stq $18,176($30) #define RESTORE_ALL \ - lda $19,hae; \ + lda $19,alpha_mv; \ ldq $0,0($30); \ ldq $1,8($30); \ ldq $2,16($30); \ @@ -1135,7 +1135,7 @@ .quad sys_sysinfo .quad sys_sysctl .quad sys_idle /* 320 */ - .quad sys_umount + .quad sys_oldumount .quad sys_swapon .quad sys_times .quad sys_personality diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/es1888.c linux/arch/alpha/kernel/es1888.c --- v2.1.115/linux/arch/alpha/kernel/es1888.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/es1888.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,47 @@ +/* + * linux/arch/alpha/kernel/es1888.c + * + * Init the built-in ES1888 sound chip (SB16 compatible) + */ + +#include +#include +#include "proto.h" + +void __init +es1888_init(void) +{ + /* Sequence of IO reads to init the audio controller */ + inb(0x0229); + inb(0x0229); + inb(0x0229); + inb(0x022b); + inb(0x0229); + inb(0x022b); + inb(0x0229); + inb(0x0229); + inb(0x022b); + inb(0x0229); + inb(0x0220); /* This sets the base address to 0x220 */ + + /* Sequence to set DMA channels */ + outb(0x01, 0x0226); /* reset */ + inb(0x0226); /* pause */ + outb(0x00, 0x0226); /* release reset */ + while (!(inb(0x022e) & 0x80)) /* wait for bit 7 to assert*/ + continue; + inb(0x022a); /* pause */ + outb(0xc6, 0x022c); /* enable extended mode */ + while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */ + continue; + outb(0xb1, 0x022c); /* setup for write to Interrupt CR */ + while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */ + continue; + outb(0x14, 0x022c); /* set IRQ 5 */ + while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */ + continue; + outb(0xb2, 0x022c); /* setup for write to DMA CR */ + while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */ + continue; + outb(0x18, 0x022c); /* set DMA channel 1 */ +} diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/fpreg.c linux/arch/alpha/kernel/fpreg.c --- v2.1.115/linux/arch/alpha/kernel/fpreg.c Tue Feb 17 13:12:44 1998 +++ linux/arch/alpha/kernel/fpreg.c Sun Aug 9 12:09:05 1998 @@ -4,62 +4,58 @@ * (C) Copyright 1998 Linus Torvalds */ +#ifdef __alpha_cix__ +#define STT(reg,val) asm volatile ("ftoit $f"#reg",%0" : "=r"(val)); +#else +#define STT(reg,val) asm volatile ("stt $f"#reg",%0" : "=m"(val)); +#endif + unsigned long alpha_read_fp_reg (unsigned long reg) { - unsigned long r; + unsigned long val; switch (reg) { - case 0: asm ("stt $f0,%0" : "m="(r)); break; - case 1: asm ("stt $f1,%0" : "m="(r)); break; - case 2: asm ("stt $f2,%0" : "m="(r)); break; - case 3: asm ("stt $f3,%0" : "m="(r)); break; - case 4: asm ("stt $f4,%0" : "m="(r)); break; - case 5: asm ("stt $f5,%0" : "m="(r)); break; - case 6: asm ("stt $f6,%0" : "m="(r)); break; - case 7: asm ("stt $f7,%0" : "m="(r)); break; - case 8: asm ("stt $f8,%0" : "m="(r)); break; - case 9: asm ("stt $f9,%0" : "m="(r)); break; - case 10: asm ("stt $f10,%0" : "m="(r)); break; - case 11: asm ("stt $f11,%0" : "m="(r)); break; - case 12: asm ("stt $f12,%0" : "m="(r)); break; - case 13: asm ("stt $f13,%0" : "m="(r)); break; - case 14: asm ("stt $f14,%0" : "m="(r)); break; - case 15: asm ("stt $f15,%0" : "m="(r)); break; - case 16: asm ("stt $f16,%0" : "m="(r)); break; - case 17: asm ("stt $f17,%0" : "m="(r)); break; - case 18: asm ("stt $f18,%0" : "m="(r)); break; - case 19: asm ("stt $f19,%0" : "m="(r)); break; - case 20: asm ("stt $f20,%0" : "m="(r)); break; - case 21: asm ("stt $f21,%0" : "m="(r)); break; - case 22: asm ("stt $f22,%0" : "m="(r)); break; - case 23: asm ("stt $f23,%0" : "m="(r)); break; - case 24: asm ("stt $f24,%0" : "m="(r)); break; - case 25: asm ("stt $f25,%0" : "m="(r)); break; - case 26: asm ("stt $f26,%0" : "m="(r)); break; - case 27: asm ("stt $f27,%0" : "m="(r)); break; - case 28: asm ("stt $f28,%0" : "m="(r)); break; - case 29: asm ("stt $f29,%0" : "m="(r)); break; - case 30: asm ("stt $f30,%0" : "m="(r)); break; - case 31: asm ("stt $f31,%0" : "m="(r)); break; - default: - break; + case 0: STT( 0, val); break; + case 1: STT( 1, val); break; + case 2: STT( 2, val); break; + case 3: STT( 3, val); break; + case 4: STT( 4, val); break; + case 5: STT( 5, val); break; + case 6: STT( 6, val); break; + case 7: STT( 7, val); break; + case 8: STT( 8, val); break; + case 9: STT( 9, val); break; + case 10: STT(10, val); break; + case 11: STT(11, val); break; + case 12: STT(12, val); break; + case 13: STT(13, val); break; + case 14: STT(14, val); break; + case 15: STT(15, val); break; + case 16: STT(16, val); break; + case 17: STT(17, val); break; + case 18: STT(18, val); break; + case 19: STT(19, val); break; + case 20: STT(20, val); break; + case 21: STT(21, val); break; + case 22: STT(22, val); break; + case 23: STT(23, val); break; + case 24: STT(24, val); break; + case 25: STT(25, val); break; + case 26: STT(26, val); break; + case 27: STT(27, val); break; + case 28: STT(28, val); break; + case 29: STT(29, val); break; + case 30: STT(30, val); break; + case 31: STT(31, val); break; } - return r; + return val; } -#if 1 -/* - * This is IMHO the better way of implementing LDT(). But it - * has the disadvantage that gcc 2.7.0 refuses to compile it - * (invalid operand constraints), so instead, we use the uglier - * macro below. - */ -# define LDT(reg,val) \ - asm volatile ("ldt $f"#reg",%0" : : "m"(val)); +#ifdef __alpha_cix__ +#define LDT(reg,val) asm volatile ("itoft %0,$f"#reg : : "r"(val)); #else -# define LDT(reg,val) \ - asm volatile ("ldt $f"#reg",0(%0)" : : "r"(&val)); +#define LDT(reg,val) asm volatile ("ldt $f"#reg",%0" : : "m"(val)); #endif void @@ -98,7 +94,5 @@ case 29: LDT(29, val); break; case 30: LDT(30, val); break; case 31: LDT(31, val); break; - default: - break; } } diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/head.S linux/arch/alpha/kernel/head.S --- v2.1.115/linux/arch/alpha/kernel/head.S Sun Jun 7 11:16:26 1998 +++ linux/arch/alpha/kernel/head.S Sun Aug 9 12:09:05 1998 @@ -7,7 +7,6 @@ * the kernel global pointer and jump to the kernel entry-point. */ -#define __ASSEMBLY__ #include #define halt call_pal PAL_halt diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c --- v2.1.115/linux/arch/alpha/kernel/irq.c Wed Jun 24 22:54:02 1998 +++ linux/arch/alpha/kernel/irq.c Sun Aug 9 12:09:05 1998 @@ -25,14 +25,17 @@ #include #include #include -#include +#include + +#include "proto.h" +#include "irq.h" #define vulp volatile unsigned long * #define vuip volatile unsigned int * -extern void timer_interrupt(struct pt_regs * regs); -extern void cserve_update_hw(unsigned long, unsigned long); -extern void handle_ipi(struct pt_regs *); +unsigned int local_irq_count[NR_CPUS]; +unsigned int local_bh_count[NR_CPUS]; + #define RTC_IRQ 8 #ifdef CONFIG_RTC @@ -45,497 +48,169 @@ # error Unable to handle more than 64 irq levels. #endif -/* PROBE_MASK is the bitset of irqs that we consider for autoprobing: */ -#if defined(CONFIG_ALPHA_P2K) - /* always mask out unused timer irq 0 and RTC irq 8 */ -# define PROBE_MASK (((1UL << NR_IRQS) - 1) & ~0x101UL) -#elif defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT) - /* always mask out unused timer irq 0, "irqs" 20-30, and the EISA cascade: */ -# define PROBE_MASK (((1UL << NR_IRQS) - 1) & ~0xfff000000001UL) -#elif defined(CONFIG_ALPHA_RUFFIAN) - /* must leave timer irq 0 in the mask */ -# define PROBE_MASK ((1UL << NR_IRQS) - 1) -#elif NR_IRQS == 64 - /* always mask out unused timer irq 0: */ -# define PROBE_MASK (~1UL) +#ifdef CONFIG_ALPHA_GENERIC +#define ACTUAL_NR_IRQS alpha_mv.nr_irqs #else - /* always mask out unused timer irq 0: */ -# define PROBE_MASK (((1UL << NR_IRQS) - 1) & ~1UL) +#define ACTUAL_NR_IRQS NR_IRQS #endif /* Reserved interrupts. These must NEVER be requested by any driver! - */ -#define IS_RESERVED_IRQ(irq) ((irq)==2) /* IRQ 2 used by hw cascade */ + IRQ 2 used by hw cascade */ +#define IS_RESERVED_IRQ(irq) ((irq)==2) -/* - * Shadow-copy of masked interrupts. - * The bits are used as follows: - * 0.. 7 first (E)ISA PIC (irq level 0..7) - * 8..15 second (E)ISA PIC (irq level 8..15) - * Systems with PCI interrupt lines managed by GRU (e.g., Alcor, XLT) - * or PYXIS (e.g. Miata, PC164-LX): - * 16..47 PCI interrupts 0..31 (int at xxx_INT_MASK) - * Mikasa: - * 16..31 PCI interrupts 0..15 (short at I/O port 536) - * Other systems (not Mikasa) with 16 PCI interrupt lines: - * 16..23 PCI interrupts 0.. 7 (char at I/O port 26) - * 24..31 PCI interrupts 8..15 (char at I/O port 27) - * Systems with 17 PCI interrupt lines (e.g., Cabriolet and eb164): - * 16..32 PCI interrupts 0..31 (int at I/O port 804) - * For SABLE, which is really baroque, we manage 40 IRQ's, but the - * hardware really only supports 24, not via normal ISA PIC, - * but cascaded custom 8259's, etc. - * 0-7 (char at 536) - * 8-15 (char at 53a) - * 16-23 (char at 53c) - */ -static unsigned long irq_mask = ~0UL; -#ifdef CONFIG_ALPHA_SABLE /* - * Note that the vector reported by the SRM PALcode corresponds to the - * interrupt mask bits, but we have to manage via more normal IRQs. - * - * We have to be able to go back and forth between MASK bits and IRQ: - * these tables help us do so. + * Shadow-copy of masked interrupts. */ -static char sable_irq_to_mask[NR_IRQS] = { - -1, 6, -1, 8, 15, 12, 7, 9, /* pseudo PIC 0-7 */ - -1, 16, 17, 18, 3, -1, 21, 22, /* pseudo PIC 8-15 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 0-7 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 8-15 */ - 2, 1, 0, 4, 5, -1, -1, -1, /* pseudo PCI */ -}; -#define IRQ_TO_MASK(irq) (sable_irq_to_mask[(irq)]) -static char sable_mask_to_irq[NR_IRQS] = { - 34, 33, 32, 12, 35, 36, 1, 6, /* mask 0-7 */ - 3, 7, -1, -1, 5, -1, -1, 4, /* mask 8-15 */ - 9, 10, 11, -1, -1, 14, 15, -1, /* mask 16-23 */ -}; -#else /* CONFIG_ALPHA_SABLE */ -#define IRQ_TO_MASK(irq) (irq) -#endif /* CONFIG_ALPHA_SABLE */ +unsigned long alpha_irq_mask = ~0UL; /* - * Update the hardware with the irq mask passed in MASK. The function - * exploits the fact that it is known that only bit IRQ has changed. + * The ack_irq routine used by 80% of the systems. */ -static inline void -sable_update_hw(unsigned long irq, unsigned long mask) +void +generic_ack_irq(unsigned long irq) { - /* The "irq" argument is really the mask bit number */ - switch (irq) { - case 16 ... 23: - outb(mask >> 16, 0x53d); - break; - case 8 ... 15: - outb(mask >> 8, 0x53b); - break; - case 0 ... 7: - outb(mask, 0x537); - break; + if (irq < 16) { + /* Ack the interrupt making it the lowest priority */ + /* First the slave .. */ + if (irq > 7) { + outb(0xE0 | (irq - 8), 0xa0); + irq = 2; + } + /* .. then the master */ + outb(0xE0 | irq, 0x20); } } -static inline void -noritake_update_hw(unsigned long irq, unsigned long mask) -{ - switch (irq) { - case 32 ... 47: - outw(~(mask >> 32), 0x54c); - break; - case 16 ... 31: - outw(~(mask >> 16), 0x54a); - break; - case 8 ... 15: /* ISA PIC2 */ - outb(mask >> 8, 0xA1); - break; - case 0 ... 7: /* ISA PIC1 */ - outb(mask, 0x21); - break; - } -} +/* + * Dispatch device interrupts. + */ -#ifdef CONFIG_ALPHA_MIATA -static inline void -miata_update_hw(unsigned long irq, unsigned long mask) -{ - switch (irq) { - case 16 ... 47: - /* Make CERTAIN none of the bogus ints get enabled... */ - *(vulp)PYXIS_INT_MASK = - ~((long)mask >> 16) & ~0x4000000000000e3bUL; - mb(); - /* ... and read it back to make sure it got written. */ - *(vulp)PYXIS_INT_MASK; - break; - case 8 ... 15: /* ISA PIC2 */ - outb(mask >> 8, 0xA1); - break; - case 0 ... 7: /* ISA PIC1 */ - outb(mask, 0x21); - break; - } -} -#endif +/* Handle ISA interrupt via the PICs. */ -#if defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT) -static inline void -alcor_and_xlt_update_hw(unsigned long irq, unsigned long mask) -{ - switch (irq) { - case 16 ... 47: - /* On Alcor, at least, lines 20..30 are not connected and can - generate spurrious interrupts if we turn them on while IRQ - probing. So explicitly mask them out. */ - mask |= 0x7ff000000000UL; - - /* Note inverted sense of mask bits: */ - *(vuip)GRU_INT_MASK = ~(mask >> 16); - mb(); - break; - case 8 ... 15: /* ISA PIC2 */ - outb(mask >> 8, 0xA1); - break; - case 0 ... 7: /* ISA PIC1 */ - outb(mask, 0x21); - break; - } -} +#if defined(CONFIG_ALPHA_GENERIC) +# define IACK_SC alpha_mv.iack_sc +#elif defined(CONFIG_ALPHA_APECS) +# define IACK_SC APECS_IACK_SC +#elif defined(CONFIG_ALPHA_LCA) +# define IACK_SC LCA_IACK_SC +#elif defined(CONFIG_ALPHA_CIA) +# define IACK_SC CIA_IACK_SC +#elif defined(CONFIG_ALPHA_PYXIS) +# define IACK_SC PYXIS_IACK_SC +#elif defined(CONFIG_ALPHA_TSUNAMI) +# define IACK_SC TSUNAMI_PCI0_IACK_SC +#else + /* This is bogus but necessary to get it to compile on all platforms. */ +# define IACK_SC 1L #endif -static inline void -mikasa_update_hw(unsigned long irq, unsigned long mask) -{ - switch (irq) { - case 16 ... 31: - outw(~(mask >> 16), 0x536); /* note invert */ - break; - case 8 ... 15: /* ISA PIC2 */ - outb(mask >> 8, 0xA1); - break; - case 0 ... 7: /* ISA PIC1 */ - outb(mask, 0x21); - break; - } -} - -#if defined(CONFIG_ALPHA_RUFFIAN) -static inline void -ruffian_update_hw(unsigned long irq, unsigned long mask) +void +isa_device_interrupt(unsigned long vector, struct pt_regs * regs) { - switch (irq) { - case 16 ... 47: - /* Note inverted sense of mask bits: */ - /* Make CERTAIN none of the bogus ints get enabled... */ - *(vulp)PYXIS_INT_MASK = - ~((long)mask >> 16) & 0x00000000ffffffbfUL; mb(); - /* ... and read it back to make sure it got written. */ - *(vulp)PYXIS_INT_MASK; - break; - case 8 ... 15: /* ISA PIC2 */ - outb(mask >> 8, 0xA1); - break; - case 0 ... 7: /* ISA PIC1 */ - outb(mask, 0x21); - break; +#if 1 + /* + * Generate a PCI interrupt acknowledge cycle. The PIC will + * respond with the interrupt vector of the highest priority + * interrupt that is pending. The PALcode sets up the + * interrupts vectors such that irq level L generates vector L. + */ + int j = *(vuip) IACK_SC; + j &= 0xff; + if (j == 7) { + if (!(inb(0x20) & 0x80)) { + /* It's only a passive release... */ + return; + } } -} -#endif /* RUFFIAN */ - -#if defined(CONFIG_ALPHA_SX164) -static inline void -sx164_update_hw(unsigned long irq, unsigned long mask) -{ - switch (irq) { - case 16 ... 39: -#if defined(CONFIG_ALPHA_SRM) - cserve_update_hw(irq, mask); + handle_irq(j, j, regs); #else - /* make CERTAIN none of the bogus ints get enabled */ - *(vulp)PYXIS_INT_MASK = - ~((long)mask >> 16) & ~0x000000000000003bUL; mb(); - /* ... and read it back to make sure it got written. */ - *(vulp)PYXIS_INT_MASK; -#endif /* SRM */ - break; - case 8 ... 15: /* ISA PIC2 */ - outb(mask >> 8, 0xA1); - break; - case 0 ... 7: /* ISA PIC1 */ - outb(mask, 0x21); - break; - } + unsigned long pic; -} -#endif /* SX164 */ + /* + * It seems to me that the probability of two or more *device* + * interrupts occurring at almost exactly the same time is + * pretty low. So why pay the price of checking for + * additional interrupts here if the common case can be + * handled so much easier? + */ + /* + * The first read of gives you *all* interrupting lines. + * Therefore, read the mask register and and out those lines + * not enabled. Note that some documentation has 21 and a1 + * write only. This is not true. + */ + pic = inb(0x20) | (inb(0xA0) << 8); /* read isr */ + pic &= ~alpha_irq_mask; /* apply mask */ + pic &= 0xFFFB; /* mask out cascade & hibits */ -#if defined(CONFIG_ALPHA_DP264) -static inline void -dp264_update_hw(unsigned long irq, unsigned long mask) -{ - switch (irq) { - case 16 ... 63: - /* make CERTAIN none of the bogus ints get enabled */ - /* HACK ALERT! only CPU#0 is used currently */ - *(vulp)TSUNAMI_CSR_DIM0 = - ~(mask) & ~0x0000000000000000UL; mb(); - /* ... and read it back to make sure it got written. */ - *(vulp)TSUNAMI_CSR_DIM0; - break; - case 8 ... 15: /* ISA PIC2 */ - outb(mask >> 8, 0xA1); - break; - case 0 ... 7: /* ISA PIC1 */ - outb(mask, 0x21); - break; + while (pic) { + int j = ffz(~pic); + pic &= pic - 1; + handle_irq(j, j, regs); } +#endif } -#endif /* DP264 */ -#if defined(CONFIG_ALPHA_RAWHIDE) -static inline void -rawhide_update_hw(unsigned long irq, unsigned long mask) -{ - switch (irq) { - case 16 ... 39: /* PCI bus 0 with EISA bridge */ - *(vuip)MCPCIA_INT_MASK0(0) = - (~((mask) >> 16) & 0x00ffffffU) | 0x00ff0000U; mb(); - /* ... and read it back to make sure it got written. */ - *(vuip)MCPCIA_INT_MASK0(0); - break; - case 40 ... 63: /* PCI bus 1 with builtin NCR810 SCSI */ - *(vuip)MCPCIA_INT_MASK0(1) = - (~((mask) >> 40) & 0x00ffffffU) | 0x00fe0000U; mb(); - /* ... and read it back to make sure it got written. */ - *(vuip)MCPCIA_INT_MASK0(1); - break; - case 8 ... 15: /* ISA PIC2 */ - outb(mask >> 8, 0xA1); - break; - case 0 ... 7: /* ISA PIC1 */ - outb(mask, 0x21); - break; - } -} -#endif /* RAWHIDE */ +/* Handle interrupts from the SRM, assuming no additional weirdness. */ -/* - * HW update code for the following platforms: - * - * CABRIOLET (AlphaPC64) - * EB66P - * EB164 - * PC164 - * LX164 - */ -static inline void -update_hw_35(unsigned long irq, unsigned long mask) +void +srm_device_interrupt(unsigned long vector, struct pt_regs * regs) { - switch (irq) { - case 16 ... 34: -#if defined(CONFIG_ALPHA_SRM) - cserve_update_hw(irq, mask); -#else /* SRM */ - outl(irq_mask >> 16, 0x804); -#endif /* SRM */ - break; - case 8 ... 15: /* ISA PIC2 */ - outb(mask >> 8, 0xA1); - break; - case 0 ... 7: /* ISA PIC1 */ - outb(mask, 0x21); - break; - } -} + int irq, ack; + unsigned long flags; -static inline void -update_hw_32(unsigned long irq, unsigned long mask) -{ - switch (irq) { - case 24 ... 31: - outb(mask >> 24, 0x27); - break; - case 16 ... 23: - outb(mask >> 16, 0x26); - break; - case 8 ... 15: /* ISA PIC2 */ - outb(mask >> 8, 0xA1); - break; - case 0 ... 7: /* ISA PIC1 */ - outb(mask, 0x21); - break; -} -} + __save_and_cli(flags); + ack = irq = (vector - 0x800) >> 4; -static inline void -update_hw_16(unsigned long irq, unsigned long mask) -{ - switch (irq) { - case 8 ... 15: /* ISA PIC2 */ - outb(mask >> 8, 0xA1); - break; - case 0 ... 7: /* ISA PIC1 */ - outb(mask, 0x21); - break; -} + handle_irq(irq, ack, regs); + __restore_flags(flags); } + /* - * We manipulate the hardware ourselves. + * Initial irq handlers. */ -static void update_hw(unsigned long irq, unsigned long mask) -{ -#if defined(CONFIG_ALPHA_SABLE) - sable_update_hw(irq, mask); -#elif defined(CONFIG_ALPHA_MIATA) - miata_update_hw(irq, mask); -#elif defined(CONFIG_ALPHA_NORITAKE) - noritake_update_hw(irq, mask); -#elif defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT) - alcor_and_xlt_update_hw(irq, mask); -#elif defined(CONFIG_ALPHA_MIKASA) - mikasa_update_hw(irq, mask); -#elif defined(CONFIG_ALPHA_SX164) - sx164_update_hw(irq, mask); -#elif defined(CONFIG_ALPHA_RUFFIAN) - ruffian_update_hw(irq, mask); -#elif defined(CONFIG_ALPHA_DP264) - dp264_update_hw(irq, mask); -#elif defined(CONFIG_ALPHA_RAWHIDE) - rawhide_update_hw(irq, mask); -#elif defined(CONFIG_ALPHA_CABRIOLET) || \ - defined(CONFIG_ALPHA_EB66P) || \ - defined(CONFIG_ALPHA_EB164) || \ - defined(CONFIG_ALPHA_PC164) || \ - defined(CONFIG_ALPHA_LX164) - update_hw_35(irq, mask); -#elif defined(CONFIG_ALPHA_EB66) || \ - defined(CONFIG_ALPHA_EB64P) - update_hw_32(irq, mask); -#elif NR_IRQS == 16 - update_hw_16(irq, mask); -#else -#error "How do I update the IRQ hardware?" -#endif -} +static struct irqaction timer_irq = { NULL, 0, 0, NULL, NULL, NULL}; +static struct irqaction *irq_action[NR_IRQS]; -static inline void mask_irq(unsigned long irq) + +static inline void +mask_irq(unsigned long irq) { - irq_mask |= (1UL << irq); - update_hw(irq, irq_mask); + alpha_mv.update_irq_hw(irq, alpha_irq_mask |= 1UL << irq, 0); } -static inline void unmask_irq(unsigned long irq) +static inline void +unmask_irq(unsigned long irq) { - irq_mask &= ~(1UL << irq); - update_hw(irq, irq_mask); + alpha_mv.update_irq_hw(irq, alpha_irq_mask &= ~(1UL << irq), 1); } -void disable_irq(unsigned int irq_nr) +void +disable_irq(unsigned int irq_nr) { unsigned long flags; save_and_cli(flags); - mask_irq(IRQ_TO_MASK(irq_nr)); + mask_irq(irq_nr); restore_flags(flags); } -void enable_irq(unsigned int irq_nr) +void +enable_irq(unsigned int irq_nr) { unsigned long flags; save_and_cli(flags); - unmask_irq(IRQ_TO_MASK(irq_nr)); + unmask_irq(irq_nr); restore_flags(flags); } -/* - * Initial irq handlers. - */ -static struct irqaction timer_irq = { NULL, 0, 0, NULL, NULL, NULL}; -static struct irqaction *irq_action[NR_IRQS]; - -int get_irq_list(char *buf) -{ - int i, len = 0; - struct irqaction * action; - int cpu = smp_processor_id(); - - for (i = 0; i < NR_IRQS; i++) { - action = irq_action[i]; - if (!action) - continue; - len += sprintf(buf+len, "%2d: %10u %c %s", - i, kstat.irqs[cpu][i], - (action->flags & SA_INTERRUPT) ? '+' : ' ', - action->name); - for (action=action->next; action; action = action->next) { - len += sprintf(buf+len, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", - action->name); - } - len += sprintf(buf+len, "\n"); - } - return len; -} - -static inline void ack_irq(int irq) -{ -#ifdef CONFIG_ALPHA_SABLE - /* Note that the "irq" here is really the mask bit number */ - switch (irq) { - case 0 ... 7: - outb(0xE0 | (irq - 0), 0x536); - outb(0xE0 | 1, 0x534); /* slave 0 */ - break; - case 8 ... 15: - outb(0xE0 | (irq - 8), 0x53a); - outb(0xE0 | 3, 0x534); /* slave 1 */ - break; - case 16 ... 24: - outb(0xE0 | (irq - 16), 0x53c); - outb(0xE0 | 4, 0x534); /* slave 2 */ - break; - } -#elif defined(CONFIG_ALPHA_RUFFIAN) - if (irq < 16) { - /* Ack PYXIS ISA interrupt. */ - *(vulp)PYXIS_INT_REQ = 1L << 7; mb(); - /* ... and read it back to make sure it got written. */ - *(vulp)PYXIS_INT_REQ; - if (irq > 7) { - outb(0x20, 0xa0); - } - outb(0x20, 0x20); - } else { - /* Ack PYXIS PCI interrupt. */ - *(vulp)PYXIS_INT_REQ = (1UL << (irq - 16)); - /* ... and read it back to make sure it got written. */ - *(vulp)PYXIS_INT_REQ; - } -#else - if (irq < 16) { - /* Ack the interrupt making it the lowest priority */ - /* First the slave .. */ - if (irq > 7) { - outb(0xE0 | (irq - 8), 0xa0); - irq = 2; - } - /* .. then the master */ - outb(0xE0 | irq, 0x20); -#if defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT) - /* on ALCOR/XLT, need to dismiss interrupt via GRU */ - *(vuip)GRU_INT_CLEAR = 0x80000000; mb(); - *(vuip)GRU_INT_CLEAR = 0x00000000; mb(); -#endif /* ALCOR || XLT */ - } -#endif -} - -int check_irq(unsigned int irq) +int +check_irq(unsigned int irq) { struct irqaction **p; @@ -545,22 +220,21 @@ return -EBUSY; } -int request_irq(unsigned int irq, - void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, - const char * devname, - void *dev_id) +int +request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, const char * devname, void *dev_id) { int shared = 0; struct irqaction * action, **p; unsigned long flags; - if (irq >= NR_IRQS) + if (irq >= ACTUAL_NR_IRQS) return -EINVAL; if (IS_RESERVED_IRQ(irq)) return -EINVAL; if (!handler) return -EINVAL; + p = irq_action + irq; action = *p; if (action) { @@ -580,11 +254,11 @@ shared = 1; } - if (irq == TIMER_IRQ) - action = &timer_irq; - else - action = (struct irqaction *)kmalloc(sizeof(struct irqaction), - GFP_KERNEL); + action = &timer_irq; + if (irq != TIMER_IRQ) { + action = (struct irqaction *) + kmalloc(sizeof(struct irqaction), GFP_KERNEL); + } if (!action) return -ENOMEM; @@ -602,18 +276,19 @@ *p = action; if (!shared) - unmask_irq(IRQ_TO_MASK(irq)); + unmask_irq(irq); restore_flags(flags); return 0; } -void free_irq(unsigned int irq, void *dev_id) +void +free_irq(unsigned int irq, void *dev_id) { struct irqaction * action, **p; unsigned long flags; - if (irq >= NR_IRQS) { + if (irq >= ACTUAL_NR_IRQS) { printk("Trying to free IRQ%d\n",irq); return; } @@ -629,7 +304,7 @@ save_and_cli(flags); *p = action->next; if (!irq[irq_action]) - mask_irq(IRQ_TO_MASK(irq)); + mask_irq(irq); restore_flags(flags); kfree(action); return; @@ -637,14 +312,29 @@ printk("Trying to free free IRQ%d\n",irq); } -static inline void handle_nmi(struct pt_regs * regs) +int get_irq_list(char *buf) { - printk("Whee.. NMI received. Probable hardware error\n"); - printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461)); -} + int i, len = 0; + struct irqaction * action; + int cpu = smp_processor_id(); -unsigned int local_irq_count[NR_CPUS]; -unsigned int local_bh_count[NR_CPUS]; + for (i = 0; i < NR_IRQS; i++) { + action = irq_action[i]; + if (!action) + continue; + len += sprintf(buf+len, "%2d: %10u %c %s", + i, kstat.irqs[cpu][i], + (action->flags & SA_INTERRUPT) ? '+' : ' ', + action->name); + for (action=action->next; action; action = action->next) { + len += sprintf(buf+len, ", %s%s", + (action->flags & SA_INTERRUPT) ? "+":"", + action->name); + } + len += sprintf(buf+len, "\n"); + } + return len; +} #ifdef __SMP__ /* Who has global_irq_lock. */ @@ -666,10 +356,17 @@ #define INIT_STUCK 100000000 #undef STUCK -#define STUCK \ -if (!--stuck) {printk("wait_on_irq CPU#%d stuck at %08lx, waiting for %08lx (local=%d, global=%d)\n", cpu, where, previous_irqholder, local_count, atomic_read(&global_irq_count)); stuck = INIT_STUCK; } +#define STUCK \ + if (!--stuck) { \ + printk("wait_on_irq CPU#%d stuck at %08lx, " \ + "waiting for %08lx (local=%d, global=%d)\n", \ + cpu, where, previous_irqholder, local_count, \ + atomic_read(&global_irq_count)); \ + stuck = INIT_STUCK; \ + } -static inline void wait_on_irq(int cpu, unsigned long where) +static inline void +wait_on_irq(int cpu, unsigned long where) { int stuck = INIT_STUCK; int local_count = local_irq_count[cpu]; @@ -706,10 +403,15 @@ #define INIT_STUCK 10000000 #undef STUCK -#define STUCK \ -if (!--stuck) {printk("get_irqlock stuck at %08lx, waiting for %08lx\n", where, previous_irqholder); stuck = INIT_STUCK;} +#define STUCK \ + if (!--stuck) { \ + printk("get_irqlock stuck at %08lx, waiting for %08lx\n", \ + where, previous_irqholder); \ + stuck = INIT_STUCK; \ + } -static inline void get_irqlock(int cpu, unsigned long where) +static inline void +get_irqlock(int cpu, unsigned long where) { int stuck = INIT_STUCK; @@ -745,7 +447,8 @@ previous_irqholder = where; } -void __global_cli(void) +void +__global_cli(void) { int cpu = smp_processor_id(); unsigned long where; @@ -754,27 +457,30 @@ __cli(); if (!local_irq_count[cpu]) - get_irqlock(smp_processor_id(), where); + get_irqlock(smp_processor_id(), where); } -void __global_sti(void) +void +__global_sti(void) { int cpu = smp_processor_id(); if (!local_irq_count[cpu]) - release_irqlock(smp_processor_id()); + release_irqlock(smp_processor_id()); __sti(); } #if 0 -unsigned long __global_save_flags(void) +unsigned long +__global_save_flags(void) { return global_irq_holder == (unsigned char) smp_processor_id(); } #endif -void __global_restore_flags(unsigned long flags) +void +__global_restore_flags(unsigned long flags) { if (flags & 1) { __global_cli(); @@ -793,12 +499,17 @@ #define INIT_STUCK 200000000 #undef STUCK -#define STUCK \ -if (!--stuck) {printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n",irq,cpu,global_irq_holder); stuck = INIT_STUCK;} +#define STUCK \ + if (!--stuck) { \ + printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n", \ + irq, cpu,global_irq_holder); \ + stuck = INIT_STUCK; \ + } #undef VERBOSE_IRQLOCK_DEBUGGING -void irq_enter(int cpu, int irq) +void +irq_enter(int cpu, int irq) { #ifdef VERBOSE_IRQLOCK_DEBUGGING extern void smp_show_backtrace_all_cpus(void); @@ -813,10 +524,10 @@ int globl_icount = atomic_read(&global_irq_count); int local_count = local_irq_count[cpu]; - /* It is very important that we load the state variables - * before we do the first call to printk() as printk() - * could end up changing them... - */ + /* It is very important that we load the state + variables before we do the first call to + printk() as printk() could end up changing + them... */ #if 0 printk("CPU[%d]: BAD! Local IRQ's enabled," @@ -838,13 +549,15 @@ } } -void irq_exit(int cpu, int irq) +void +irq_exit(int cpu, int irq) { hardirq_exit(cpu); release_irqlock(cpu); } -static void show(char * str) +static void +show(char * str) { #if 0 int i; @@ -873,7 +586,8 @@ #define MAXCOUNT 100000000 -static inline void wait_on_bh(void) +static inline void +wait_on_bh(void) { int count = MAXCOUNT; do { @@ -893,7 +607,8 @@ * Don't wait if we're already running in an interrupt * context or are inside a bh handler. */ -void synchronize_bh(void) +void +synchronize_bh(void) { if (atomic_read(&global_bh_count)) { int cpu = smp_processor_id(); @@ -904,7 +619,8 @@ } /* There has to be a better way. */ -void synchronize_irq(void) +void +synchronize_irq(void) { int cpu = smp_processor_id(); int local_count = local_irq_count[cpu]; @@ -918,26 +634,35 @@ } } -#else +#else /* !__SMP__ */ + #define irq_enter(cpu, irq) (++local_irq_count[cpu]) #define irq_exit(cpu, irq) (--local_irq_count[cpu]) -#endif -static void unexpected_irq(int irq, struct pt_regs * regs) +#endif /* __SMP__ */ + +static void +unexpected_irq(int irq, struct pt_regs * regs) { +#if 0 +#if 1 + printk("device_interrupt: unexpected interrupt %d\n", irq); +#else struct irqaction *action; int i; printk("IO device interrupt, irq = %d\n", irq); printk("PC = %016lx PS=%04lx\n", regs->pc, regs->ps); printk("Expecting: "); - for (i = 0; i < 16; i++) + for (i = 0; i < ACTUAL_NR_IRQS; i++) if ((action = irq_action[i])) while (action->handler) { printk("[%s:%d] ", action->name, i); action = action->next; } printk("\n"); +#endif +#endif #if defined(CONFIG_ALPHA_JENSEN) /* ??? Is all this just debugging, or are the inb's and outb's @@ -951,32 +676,15 @@ #endif } -static inline void handle_irq(int irq, struct pt_regs * regs) +void +handle_irq(int irq, int ack, struct pt_regs * regs) { - struct irqaction * action = irq_action[irq]; + struct irqaction * action; int cpu = smp_processor_id(); - irq_enter(cpu, irq); - kstat.irqs[cpu][irq] += 1; - if (!action) { - unexpected_irq(irq, regs); - } else { - do { - action->handler(irq, action->dev_id, regs); - action = action->next; - } while (action); - } - irq_exit(cpu, irq); -} - -static inline void device_interrupt(int irq, int ack, struct pt_regs * regs) -{ - struct irqaction * action; - int cpu = smp_processor_id(); - - if ((unsigned) irq > NR_IRQS) { - printk("device_interrupt: illegal interrupt %d\n", irq); - return; + if ((unsigned) irq > ACTUAL_NR_IRQS) { + printk("device_interrupt: illegal interrupt %d\n", irq); + return; } irq_enter(cpu, irq); @@ -992,8 +700,10 @@ * never unmasked. The autoirq stuff depends on this (it looks * at the masks before and after doing the probing). */ - mask_irq(ack); - ack_irq(ack); + if (ack >= 0) { + mask_irq(ack); + alpha_mv.ack_irq(ack); + } if (action) { if (action->flags & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); @@ -1001,622 +711,28 @@ action->handler(irq, action->dev_id, regs); action = action->next; } while (action); - unmask_irq(ack); + if (ack >= 0) + unmask_irq(ack); } else { -#if 1 - printk("device_interrupt: unexpected interrupt %d\n", irq); -#endif + unexpected_irq(irq, regs); } irq_exit(cpu, irq); } -#ifdef CONFIG_PCI - -/* - * Handle ISA interrupt via the PICs. - */ -static inline void isa_device_interrupt(unsigned long vector, - struct pt_regs * regs) -{ -#if defined(CONFIG_ALPHA_APECS) -# define IACK_SC APECS_IACK_SC -#elif defined(CONFIG_ALPHA_LCA) -# define IACK_SC LCA_IACK_SC -#elif defined(CONFIG_ALPHA_CIA) -# define IACK_SC CIA_IACK_SC -#elif defined(CONFIG_ALPHA_PYXIS) -# define IACK_SC PYXIS_IACK_SC -#elif defined(CONFIG_ALPHA_TSUNAMI) -# define IACK_SC TSUNAMI_PCI0_IACK_SC -#else - /* - * This is bogus but necessary to get it to compile - * on all platforms. If you try to use this on any - * other than the intended platforms, you'll notice - * real fast... - */ -# define IACK_SC 1L -#endif - int j; - -#if 1 - /* - * Generate a PCI interrupt acknowledge cycle. The PIC will - * respond with the interrupt vector of the highest priority - * interrupt that is pending. The PALcode sets up the - * interrupts vectors such that irq level L generates vector L. - */ - j = *(vuip) IACK_SC; - j &= 0xff; - if (j == 7) { - if (!(inb(0x20) & 0x80)) { - /* It's only a passive release... */ - return; - } - } - device_interrupt(j, j, regs); -#else - unsigned long pic; - - /* - * It seems to me that the probability of two or more *device* - * interrupts occurring at almost exactly the same time is - * pretty low. So why pay the price of checking for - * additional interrupts here if the common case can be - * handled so much easier? - */ - /* - * The first read of gives you *all* interrupting lines. - * Therefore, read the mask register and and out those lines - * not enabled. Note that some documentation has 21 and a1 - * write only. This is not true. - */ - pic = inb(0x20) | (inb(0xA0) << 8); /* read isr */ - pic &= ~irq_mask; /* apply mask */ - pic &= 0xFFFB; /* mask out cascade & hibits */ - - while (pic) { - j = ffz(~pic); - pic &= pic - 1; - device_interrupt(j, j, regs); - } -#endif -} - -#if defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT) -/* We have to conditionally compile this because of GRU_xxx symbols */ -static inline void -alcor_and_xlt_device_interrupt(unsigned long vector, struct pt_regs *regs) -{ - unsigned long pld; - unsigned int i; - unsigned long flags; - - save_and_cli(flags); - - /* Read the interrupt summary register of the GRU */ - pld = (*(vuip)GRU_INT_REQ) & GRU_INT_REQ_BITS; - -#if 0 - printk("[0x%08lx/0x%04x]", pld, inb(0x20) | (inb(0xA0) << 8)); -#endif - - /* - * Now for every possible bit set, work through them and call - * the appropriate interrupt handler. - */ - while (pld) { - i = ffz(~pld); - pld &= pld - 1; /* clear least bit set */ - if (i == 31) { - isa_device_interrupt(vector, regs); - } else { - device_interrupt(16 + i, 16 + i, regs); - } - } - restore_flags(flags); -} -#endif /* ALCOR || XLT */ - -static inline void -cabriolet_and_eb66p_device_interrupt(unsigned long vector, - struct pt_regs *regs) -{ - unsigned long pld; - unsigned int i; - unsigned long flags; - - save_and_cli(flags); - - /* Read the interrupt summary registers */ - pld = inb(0x804) | (inb(0x805) << 8) | (inb(0x806) << 16); - -#if 0 - printk("[0x%04X/0x%04X]", pld, inb(0x20) | (inb(0xA0) << 8)); -#endif - - /* - * Now for every possible bit set, work through them and call - * the appropriate interrupt handler. - */ - while (pld) { - i = ffz(~pld); - pld &= pld - 1; /* clear least bit set */ - if (i == 4) { - isa_device_interrupt(vector, regs); - } else { - device_interrupt(16 + i, 16 + i, regs); - } - } - restore_flags(flags); -} - -static inline void -mikasa_device_interrupt(unsigned long vector, struct pt_regs *regs) -{ - unsigned long pld; - unsigned int i; - unsigned long flags; - - save_and_cli(flags); - - /* Read the interrupt summary registers */ - pld = (((unsigned long) (~inw(0x534)) & 0x0000ffffUL) << 16) | - (((unsigned long) inb(0xa0)) << 8) | - ((unsigned long) inb(0x20)); - -#if 0 - printk("[0x%08lx]", pld); -#endif - - /* - * Now for every possible bit set, work through them and call - * the appropriate interrupt handler. - */ - while (pld) { - i = ffz(~pld); - pld &= pld - 1; /* clear least bit set */ - if (i < 16) { - isa_device_interrupt(vector, regs); - } else { - device_interrupt(i, i, regs); - } - } - restore_flags(flags); -} - -static inline void -eb66_and_eb64p_device_interrupt(unsigned long vector, struct pt_regs *regs) -{ - unsigned long pld; - unsigned int i; - unsigned long flags; - - save_and_cli(flags); - - /* Read the interrupt summary registers */ - pld = inb(0x26) | (inb(0x27) << 8); - /* - * Now, for every possible bit set, work through - * them and call the appropriate interrupt handler. - */ - while (pld) { - i = ffz(~pld); - pld &= pld - 1; /* clear least bit set */ - - if (i == 5) { - isa_device_interrupt(vector, regs); - } else { - device_interrupt(16 + i, 16 + i, regs); - } - } - restore_flags(flags); -} - -#if defined(CONFIG_ALPHA_MIATA) || defined(CONFIG_ALPHA_SX164) -/* We have to conditionally compile this because of PYXIS_xxx symbols */ -static inline void -miata_device_interrupt(unsigned long vector, struct pt_regs *regs) -{ - unsigned long pld, tmp; - unsigned int i; - unsigned long flags; - - save_and_cli(flags); - - /* Read the interrupt summary register of PYXIS */ - pld = *(vulp)PYXIS_INT_REQ; - -#if 0 - printk("[0x%08lx/0x%08lx/0x%04x]", pld, - *(vulp)PYXIS_INT_MASK, inb(0x20) | (inb(0xA0) << 8)); -#endif - -#ifdef CONFIG_ALPHA_MIATA - /* - * For now, AND off any bits we are not interested in: - * HALT (2), timer (6), ISA Bridge (7), 21142/3 (8) - * then all the PCI slots/INTXs (12-31). - */ - /* Maybe HALT should only be used for SRM console boots? */ - pld &= 0x00000000fffff1c4UL; -#endif -#ifdef CONFIG_ALPHA_SX164 - /* - * For now, AND off any bits we are not interested in: - * HALT (2), timer (6), ISA Bridge (7) - * then all the PCI slots/INTXs (8-23) - */ - /* Maybe HALT should only be used for SRM console boots? */ - pld &= 0x0000000000ffffc0UL; -#endif /* SX164 */ - - /* - * Now for every possible bit set, work through them and call - * the appropriate interrupt handler. - */ - while (pld) { - i = ffz(~pld); - pld &= pld - 1; /* clear least bit set */ - if (i == 7) { - isa_device_interrupt(vector, regs); - } else if (i == 6) - continue; - else { /* if not timer int */ - device_interrupt(16 + i, 16 + i, regs); - } - *(vulp)PYXIS_INT_REQ = 1UL << i; mb(); - tmp = *(vulp)PYXIS_INT_REQ; - } - restore_flags(flags); -} -#endif /* MIATA || SX164 */ - -static inline void -noritake_device_interrupt(unsigned long vector, struct pt_regs *regs) -{ - unsigned long pld; - unsigned int i; - unsigned long flags; - - save_and_cli(flags); - - /* Read the interrupt summary registers of NORITAKE */ - pld = ((unsigned long) inw(0x54c) << 32) | - ((unsigned long) inw(0x54a) << 16) | - ((unsigned long) inb(0xa0) << 8) | - ((unsigned long) inb(0x20)); - -#if 0 - printk("[0x%08lx]", pld); -#endif - - /* - * Now for every possible bit set, work through them and call - * the appropriate interrupt handler. - */ - while (pld) { - i = ffz(~pld); - pld &= pld - 1; /* clear least bit set */ - if (i < 16) { - isa_device_interrupt(vector, regs); - } else { - device_interrupt(i, i, regs); - } - } - restore_flags(flags); -} - -#if defined(CONFIG_ALPHA_DP264) -/* we have to conditionally compile this because of TSUNAMI_xxx symbols */ -static inline void dp264_device_interrupt(unsigned long vector, - struct pt_regs * regs) -{ - unsigned long pld, tmp; - unsigned int i; - unsigned long flags; - - __save_and_cli(flags); - - /* Read the interrupt summary register of TSUNAMI */ - pld = (*(vulp)TSUNAMI_CSR_DIR0); - -#if 0 - printk("[0x%08lx/0x%08lx/0x%04x]", pld, - *(vulp)TSUNAMI_CSR_DIM0, - inb(0x20) | (inb(0xA0) << 8)); -#endif - - /* - * Now for every possible bit set, work through them and call - * the appropriate interrupt handler. - */ - while (pld) { - i = ffz(~pld); - pld &= pld - 1; /* clear least bit set */ - if (i == 55) { - isa_device_interrupt(vector, regs); - } else { /* if not timer int */ - device_interrupt(16 + i, 16 + i, regs); - } -#if 0 - *(vulp)TSUNAMI_CSR_DIR0 = 1UL << i; mb(); - tmp = *(vulp)TSUNAMI_CSR_DIR0; -#endif - } - __restore_flags(flags); -} -#endif /* DP264 */ - -#if defined(CONFIG_ALPHA_RAWHIDE) -/* we have to conditionally compile this because of MCPCIA_xxx symbols */ -static inline void rawhide_device_interrupt(unsigned long vector, - struct pt_regs * regs) -{ -#if 0 - unsigned long pld; - unsigned int i; - unsigned long flags; - - __save_and_cli(flags); - - /* PLACEHOLDER, perhaps never used if we always do SRM */ - - __restore_flags(flags); -#endif -} -#endif /* RAWHIDE */ - -#if defined(CONFIG_ALPHA_RUFFIAN) -static inline void -ruffian_device_interrupt(unsigned long vector, struct pt_regs *regs) - -{ - unsigned long pld; - unsigned int i; - unsigned long flags; - - save_and_cli(flags); - - /* Read the interrupt summary register of PYXIS */ - pld = *(vulp)PYXIS_INT_REQ; - - /* For now, AND off any bits we are not interested in: - * HALT (2), timer (6), ISA Bridge (7), 21142 (8) - * then all the PCI slots/INTXs (12-31) - * flash(5) :DWH: - */ - pld &= 0x00000000ffffff9fUL;/* was ffff7f */ - - /* - * Now for every possible bit set, work through them and call - * the appropriate interrupt handler. - */ - - while (pld) { - i = ffz(~pld); - pld &= pld - 1; /* clear least bit set */ - if (i == 7) { - /* Copy this bit from isa_device_interrupt cause - we need to hook into int 0 for the timer. I - refuse to soil device_interrupt with ifdefs. */ - - /* Generate a PCI interrupt acknowledge cycle. - The PIC will respond with the interrupt - vector of the highest priority interrupt - that is pending. The PALcode sets up the - interrupts vectors such that irq level L - generates vector L. */ - - unsigned int j = *(vuip)PYXIS_IACK_SC & 0xff; - if (j == 7 && !(inb(0x20) & 0x80)) { - /* It's only a passive release... */ - } else if (j == 0) { - timer_interrupt(regs); - ack_irq(0); - } else { - device_interrupt(j, j, regs); - } - } else { /* if not timer int */ - device_interrupt(16 + i, 16 + i, regs); - } - - *(vulp)PYXIS_INT_REQ = 1UL << i; mb(); - *(vulp)PYXIS_INT_REQ; /* read to force the write */ - } - restore_flags(flags); -} -#endif /* RUFFIAN */ - -static inline void takara_device_interrupt(unsigned long vector, - struct pt_regs * regs) -{ - unsigned long flags; - unsigned intstatus; - - save_and_cli(flags); - - /* - * The PALcode will have passed us vectors 0x800 or 0x810, - * which are fairly arbitrary values and serve only to tell - * us whether an interrupt has come in on IRQ0 or IRQ1. If - * it's IRQ1 it's a PCI interrupt; if it's IRQ0, it's - * probably ISA, but PCI interrupts can come through IRQ0 - * as well if the interrupt controller isn't in accelerated - * mode. - * - * OTOH, the accelerator thing doesn't seem to be working - * overly well, so what we'll do instead is try directly - * examining the Master Interrupt Register to see if it's a - * PCI interrupt, and if _not_ then we'll pass it on to the - * ISA handler. - */ - - intstatus = inw(0x500) & 15; - if (intstatus) { - /* - * This is a PCI interrupt. Check each bit and - * despatch an interrupt if it's set. - */ - if (intstatus & 8) device_interrupt(16+3, 16+3, regs); - if (intstatus & 4) device_interrupt(16+2, 16+2, regs); - if (intstatus & 2) device_interrupt(16+1, 16+1, regs); - if (intstatus & 1) device_interrupt(16+0, 16+0, regs); - } else - isa_device_interrupt (vector, regs); - - restore_flags(flags); -} - -#endif /* CONFIG_PCI */ - -/* - * Jensen is special: the vector is 0x8X0 for EISA interrupt X, and - * 0x9X0 for the local motherboard interrupts.. - * - * 0x660 - NMI - * - * 0x800 - IRQ0 interval timer (not used, as we use the RTC timer) - * 0x810 - IRQ1 line printer (duh..) - * 0x860 - IRQ6 floppy disk - * 0x8E0 - IRQ14 SCSI controller - * - * 0x900 - COM1 - * 0x920 - COM2 - * 0x980 - keyboard - * 0x990 - mouse - * - * PCI-based systems are more sane: they don't have the local - * interrupts at all, and have only normal PCI interrupts from - * devices. Happily it's easy enough to do a sane mapping from the - * Jensen.. Note that this means that we may have to do a hardware - * "ack" to a different interrupt than we report to the rest of the - * world. - */ -static inline void -srm_device_interrupt(unsigned long vector, struct pt_regs * regs) -{ - int irq, ack; - unsigned long flags; - - __save_and_cli(flags); - -#ifdef __SMP__ -if (smp_processor_id()) printk("srm_device_interrupt on other CPU\n"); -#endif - - ack = irq = (vector - 0x800) >> 4; - -#ifdef CONFIG_ALPHA_JENSEN - switch (vector) { - case 0x660: handle_nmi(regs); return; - /* local device interrupts: */ - case 0x900: handle_irq(4, regs); return; /* com1 -> irq 4 */ - case 0x920: handle_irq(3, regs); return; /* com2 -> irq 3 */ - case 0x980: handle_irq(1, regs); return; /* kbd -> irq 1 */ - case 0x990: handle_irq(9, regs); return; /* mouse -> irq 9 */ - default: - if (vector > 0x900) { - printk("Unknown local interrupt %lx\n", vector); - } - } - /* irq1 is supposed to be the keyboard, silly Jensen - (is this really needed??) */ - if (irq == 1) - irq = 7; -#endif /* CONFIG_ALPHA_JENSEN */ - -#ifdef CONFIG_ALPHA_MIATA - /* - * I really hate to do this, but the MIATA SRM console ignores the - * low 8 bits in the interrupt summary register, and reports the - * vector 0x80 *lower* than I expected from the bit numbering in - * the documentation. - * This was done because the low 8 summary bits really aren't used - * for reporting any interrupts (the PCI-ISA bridge, bit 7, isn't - * used for this purpose, as PIC interrupts are delivered as the - * vectors 0x800-0x8f0). - * But I really don't want to change the fixup code for allocation - * of IRQs, nor the irq_mask maintenance stuff, both of which look - * nice and clean now. - * So, here's this grotty hack... :-( - */ - if (irq >= 16) - ack = irq = irq + 8; -#endif /* CONFIG_ALPHA_MIATA */ - -#ifdef CONFIG_ALPHA_NORITAKE - /* - * I really hate to do this, too, but the NORITAKE SRM console also - * reports PCI vectors *lower* than I expected from the bit numbers - * in the documentation. - * But I really don't want to change the fixup code for allocation - * of IRQs, nor the irq_mask maintenance stuff, both of which look - * nice and clean now. - * So, here's this additional grotty hack... :-( - */ - if (irq >= 16) - ack = irq = irq + 1; -#endif /* CONFIG_ALPHA_NORITAKE */ - -#ifdef CONFIG_ALPHA_SABLE - irq = sable_mask_to_irq[(ack)]; -#if 0 - if (irq == 5 || irq == 9 || irq == 10 || irq == 11 || - irq == 14 || irq == 15) - printk("srm_device_interrupt: vector=0x%lx ack=0x%x" - " irq=0x%x\n", vector, ack, irq); -#endif -#endif /* CONFIG_ALPHA_SABLE */ - -#ifdef CONFIG_ALPHA_DP264 - /* - * the DP264 SRM console reports PCI interrupts with a vector - * 0x100 *higher* than one might expect, as PCI IRQ 0 (ie bit 0) - * shows up as IRQ 16, etc, etc. We adjust it down by 16 to have - * it line up with the actual bit numbers from the DIM registers, - * which is how we manage the interrupts/mask. Sigh... - */ - if (irq >= 32) - ack = irq = irq - 16; -#endif /* DP264 */ - -#ifdef CONFIG_ALPHA_RAWHIDE - /* - * the RAWHIDE SRM console reports PCI interrupts with a vector - * 0x80 *higher* than one might expect, as PCI IRQ 0 (ie bit 0) - * shows up as IRQ 24, etc, etc. We adjust it down by 8 to have - * it line up with the actual bit numbers from the REQ registers, - * which is how we manage the interrupts/mask. Sigh... - * - * also, PCI #1 interrupts are offset some more... :-( - */ - if (irq == 52) - ack = irq = 56; /* SCSI on PCI 1 is special */ - else { - if (irq >= 24) /* adjust all PCI interrupts down 8 */ - ack = irq = irq - 8; - if (irq >= 48) /* adjust PCI bus 1 interrupts down another 8 */ - ack = irq = irq - 8; - } -#endif /* RAWHIDE */ - - device_interrupt(irq, ack, regs); - - __restore_flags(flags); -} /* * Start listening for interrupts.. */ -unsigned long probe_irq_on(void) + +unsigned long +probe_irq_on(void) { struct irqaction * action; unsigned long irqs = 0; unsigned long delay; unsigned int i; - for (i = NR_IRQS - 1; i > 0; i--) { + for (i = ACTUAL_NR_IRQS - 1; i > 0; i--) { if (!(PROBE_MASK & (1UL << i))) { continue; } @@ -1634,8 +750,8 @@ for (delay = jiffies + HZ/10; delay > jiffies; ) barrier(); - /* now filter out any obviously spurious interrupts */ - return irqs & ~irq_mask; + /* Now filter out any obviously spurious interrupts. */ + return irqs & ~alpha_irq_mask; } /* @@ -1643,11 +759,13 @@ * we have several candidates (but we return the lowest-numbered * one). */ -int probe_irq_off(unsigned long irqs) + +int +probe_irq_off(unsigned long irqs) { int i; - irqs &= irq_mask; + irqs &= alpha_irq_mask; if (!irqs) return 0; i = ffz(~irqs); @@ -1656,42 +774,10 @@ return i; } -extern void lca_machine_check (unsigned long vector, unsigned long la, - struct pt_regs *regs); -extern void apecs_machine_check(unsigned long vector, unsigned long la, - struct pt_regs * regs); -extern void cia_machine_check(unsigned long vector, unsigned long la, - struct pt_regs * regs); -extern void pyxis_machine_check(unsigned long vector, unsigned long la, - struct pt_regs * regs); -extern void t2_machine_check(unsigned long vector, unsigned long la, - struct pt_regs * regs); -extern void tsunami_machine_check(unsigned long vector, unsigned long la, - struct pt_regs * regs); -extern void mcpcia_machine_check(unsigned long vector, unsigned long la, - struct pt_regs * regs); -static void -machine_check(unsigned long vector, unsigned long la, struct pt_regs *regs) -{ -#if defined(CONFIG_ALPHA_LCA) - lca_machine_check(vector, la, regs); -#elif defined(CONFIG_ALPHA_APECS) - apecs_machine_check(vector, la, regs); -#elif defined(CONFIG_ALPHA_CIA) - cia_machine_check(vector, la, regs); -#elif defined(CONFIG_ALPHA_PYXIS) - pyxis_machine_check(vector, la, regs); -#elif defined(CONFIG_ALPHA_T2) - t2_machine_check(vector, la, regs); -#elif defined(CONFIG_ALPHA_TSUNAMI) - tsunami_machine_check(vector, la, regs); -#elif defined(CONFIG_ALPHA_MCPCIA) - mcpcia_machine_check(vector, la, regs); -#else - printk("Machine check\n"); -#endif -} +/* + * The main interrupt entry point. + */ asmlinkage void do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr, @@ -1701,56 +787,20 @@ switch (type) { case 0: #ifdef __SMP__ -/* irq_enter(smp_processor_id(), 0); ??????? */ handle_ipi(®s); -/* irq_exit(smp_processor_id(), 0); ??????? */ return; -#else /* __SMP__ */ +#else printk("Interprocessor interrupt? You must be kidding\n"); -#endif /* __SMP__ */ +#endif break; case 1: - handle_irq(RTC_IRQ, ®s); + handle_irq(RTC_IRQ, -1, ®s); return; case 2: - machine_check(vector, la_ptr, ®s); + alpha_mv.machine_check(vector, la_ptr, ®s); return; case 3: -#if defined(CONFIG_ALPHA_JENSEN) || \ - defined(CONFIG_ALPHA_NONAME) || \ - defined(CONFIG_ALPHA_P2K) || \ - defined(CONFIG_ALPHA_SRM) - srm_device_interrupt(vector, ®s); -#elif defined(CONFIG_ALPHA_MIATA) || \ - defined(CONFIG_ALPHA_SX164) - miata_device_interrupt(vector, ®s); -#elif defined(CONFIG_ALPHA_NORITAKE) - noritake_device_interrupt(vector, ®s); -#elif defined(CONFIG_ALPHA_ALCOR) || \ - defined(CONFIG_ALPHA_XLT) - alcor_and_xlt_device_interrupt(vector, ®s); -#elif defined(CONFIG_ALPHA_CABRIOLET) || \ - defined(CONFIG_ALPHA_EB66P) || \ - defined(CONFIG_ALPHA_EB164) || \ - defined(CONFIG_ALPHA_PC164) || \ - defined(CONFIG_ALPHA_LX164) - cabriolet_and_eb66p_device_interrupt(vector, ®s); -#elif defined(CONFIG_ALPHA_MIKASA) - mikasa_device_interrupt(vector, ®s); -#elif defined(CONFIG_ALPHA_EB66) || \ - defined(CONFIG_ALPHA_EB64P) - eb66_and_eb64p_device_interrupt(vector, ®s); -#elif defined(CONFIG_ALPHA_RUFFIAN) - ruffian_device_interrupt(vector, ®s); -#elif defined(CONFIG_ALPHA_DP264) - dp264_device_interrupt(vector, ®s); -#elif defined(CONFIG_ALPHA_RAWHIDE) - rawhide_device_interrupt(vector, ®s); -#elif defined(CONFIG_ALPHA_TAKARA) - takara_device_interrupt(vector, ®s); -#elif NR_IRQS == 16 - isa_device_interrupt(vector, ®s); -#endif + alpha_mv.device_interrupt(vector, ®s); return; case 4: printk("Performance counter interrupt\n"); @@ -1761,226 +811,9 @@ printk("PC = %016lx PS=%04lx\n", regs.pc, regs.ps); } -extern asmlinkage void entInt(void); - -static inline void sable_init_IRQ(void) -{ - outb(irq_mask , 0x537); /* slave 0 */ - outb(irq_mask >> 8, 0x53b); /* slave 1 */ - outb(irq_mask >> 16, 0x53d); /* slave 2 */ - outb(0x44, 0x535); /* enable cascades in master */ -} - -#if defined(CONFIG_ALPHA_SX164) -static inline void sx164_init_IRQ(void) -{ -#if !defined(CONFIG_ALPHA_SRM) - /* note invert on MASK bits */ - *(vulp)PYXIS_INT_MASK = ~((long)irq_mask >> 16); mb(); - *(vulp)PYXIS_INT_MASK; -#endif /* !SRM */ - enable_irq(16 + 6); /* enable timer */ - enable_irq(16 + 7); /* enable ISA PIC cascade */ - enable_irq(2); /* enable cascade */ -} -#endif /* SX164 */ - -#if defined(CONFIG_ALPHA_RUFFIAN) -static inline void ruffian_init_IRQ(void) -{ - /* invert 6&7 for i82371 */ - *(vulp)PYXIS_INT_HILO = 0x000000c0UL; mb(); - *(vulp)PYXIS_INT_CNFG = 0x00002064UL; mb(); /* all clear */ - *(vulp)PYXIS_INT_MASK = 0x00000000UL; mb(); - *(vulp)PYXIS_INT_REQ = 0xffffffffUL; mb(); - - outb(0x11,0xA0); - outb(0x08,0xA1); - outb(0x02,0xA1); - outb(0x01,0xA1); - outb(0xFF,0xA1); - - outb(0x11,0x20); - outb(0x00,0x21); - outb(0x04,0x21); - outb(0x01,0x21); - outb(0xFF,0x21); - - /* Send -INTA pulses to clear any pending interrupts ...*/ - *(vuip) IACK_SC; - - /* Finish writing the 82C59A PIC Operation Control Words */ - outb(0x20,0xA0); - outb(0x20,0x20); - - /* Turn on the interrupt controller, the timer interrupt */ - enable_irq(16 + 7); /* enable ISA PIC cascade */ - enable_irq(0); /* enable timer */ - enable_irq(2); /* enable 2nd PIC cascade */ -} -#endif /* RUFFIAN */ - -#ifdef CONFIG_ALPHA_MIATA -static inline void miata_init_IRQ(void) -{ - /* note invert on MASK bits */ - *(vulp)PYXIS_INT_MASK = ~((long)irq_mask >> 16); mb(); /* invert */ -#if 0 - /* these break on MiataGL so we'll try not to do it at all */ - *(vulp)PYXIS_INT_HILO = 0x000000B2UL; mb(); /* ISA/NMI HI */ - *(vulp)PYXIS_RT_COUNT = 0UL; mb(); /* clear count */ -#endif - /* clear upper timer */ - *(vulp)PYXIS_INT_REQ = 0x4000000000000000UL; mb(); - - enable_irq(16 + 2); /* enable HALT switch - SRM only? */ - enable_irq(16 + 6); /* enable timer */ - enable_irq(16 + 7); /* enable ISA PIC cascade */ - enable_irq(2); /* enable cascade */ -} -#endif - -static inline void noritake_init_IRQ(void) -{ - outw(~(irq_mask >> 16), 0x54a); /* note invert */ - outw(~(irq_mask >> 32), 0x54c); /* note invert */ - enable_irq(2); /* enable cascade */ -} - -#if defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT) -static inline void alcor_and_xlt_init_IRQ(void) -{ - *(vuip)GRU_INT_MASK = ~(irq_mask >> 16); mb(); /* note invert */ - *(vuip)GRU_INT_EDGE = 0U; mb(); /* all are level */ - *(vuip)GRU_INT_HILO = 0x80000000U; mb(); /* ISA only HI */ - *(vuip)GRU_INT_CLEAR = 0UL; mb(); /* all clear */ - - enable_irq(16 + 31); /* enable (E)ISA PIC cascade */ - enable_irq(2); /* enable cascade */ -} -#endif /* ALCOR || XLT */ - -static inline void mikasa_init_IRQ(void) -{ - outw(~(irq_mask >> 16), 0x536); /* note invert */ - enable_irq(2); /* enable cascade */ -} - -#if defined(CONFIG_ALPHA_DP264) -static inline void dp264_init_IRQ(void) -{ - /* note invert on MASK bits */ - *(vulp)TSUNAMI_CSR_DIM0 = - ~(irq_mask) & ~0x0000000000000000UL; mb(); - *(vulp)TSUNAMI_CSR_DIM0; - enable_irq(55); /* enable CYPRESS interrupt controller (ISA) */ - enable_irq(2); -} -#endif /* DP264 */ - -#if defined(CONFIG_ALPHA_RAWHIDE) -static inline void rawhide_init_IRQ(void) -{ - /* HACK ALERT! only PCI busses 0 and 1 are used currently, - and routing is only to CPU #1*/ - - *(vuip)MCPCIA_INT_MASK0(0) = - (~((irq_mask) >> 16) & 0x00ffffffU) | 0x00ff0000U; mb(); - /* ... and read it back to make sure it got written. */ - *(vuip)MCPCIA_INT_MASK0(0); - - *(vuip)MCPCIA_INT_MASK0(1) = - (~((irq_mask) >> 40) & 0x00ffffffU) | 0x00fe0000U; mb(); - /* ... and read it back to make sure it got written. */ - *(vuip)MCPCIA_INT_MASK0(1); - enable_irq(2); -} -#endif /* RAWHIDE */ - -static inline void takara_init_IRQ(void) -{ - unsigned int ctlreg = inl(0x500); - - ctlreg &= ~0x8000; /* return to non-accelerated mode */ - outw(ctlreg >> 16, 0x502); - outw(ctlreg & 0xFFFF, 0x500); - ctlreg = 0x05107c00; /* enable the PCI interrupt register */ - printk("Setting to 0x%08x\n", ctlreg); - outw(ctlreg >> 16, 0x502); - outw(ctlreg & 0xFFFF, 0x500); - enable_irq(2); -} - -static inline void init_IRQ_35(void) -{ -#if !defined(CONFIG_ALPHA_SRM) - outl(irq_mask >> 16, 0x804); -#endif /* !SRM */ - enable_irq(16 + 4); /* enable SIO cascade */ - enable_irq(2); /* enable cascade */ -} - -static inline void init_IRQ_32(void) -{ - outb(irq_mask >> 16, 0x26); - outb(irq_mask >> 24, 0x27); - enable_irq(16 + 5); /* enable SIO cascade */ - enable_irq(2); /* enable cascade */ -} - -static inline void init_IRQ_16(void) -{ - enable_irq(2); /* enable cascade */ -} - void __init init_IRQ(void) { wrent(entInt, 0); - -/* FIXME FIXME FIXME FIXME FIXME */ -#if !defined(CONFIG_ALPHA_DP264) - /* we need to figure out why these fail on the DP264 */ - outb(0, DMA1_RESET_REG); - outb(0, DMA2_RESET_REG); -#endif /* !DP264 */ -/* FIXME FIXME FIXME FIXME FIXME */ -#if !defined(CONFIG_ALPHA_SX164) && !defined(CONFIG_ALPHA_DP264) - outb(0, DMA1_CLR_MASK_REG); - /* we need to figure out why this fails on the SX164 */ - outb(0, DMA2_CLR_MASK_REG); -#endif /* !SX164 && !DP264 */ -/* end FIXMEs */ - -#if defined(CONFIG_ALPHA_SABLE) - sable_init_IRQ(); -#elif defined(CONFIG_ALPHA_MIATA) - miata_init_IRQ(); -#elif defined(CONFIG_ALPHA_SX164) - sx164_init_IRQ(); -#elif defined(CONFIG_ALPHA_NORITAKE) - noritake_init_IRQ(); -#elif defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT) - alcor_and_xlt_init_IRQ(); -#elif defined(CONFIG_ALPHA_MIKASA) - mikasa_init_IRQ(); -#elif defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P) || \ - defined(CONFIG_ALPHA_PC164) || defined(CONFIG_ALPHA_LX164) || \ - defined(CONFIG_ALPHA_EB164) - init_IRQ_35(); -#elif defined(CONFIG_ALPHA_RUFFIAN) - ruffian_init_IRQ(); -#elif defined(CONFIG_ALPHA_DP264) - dp264_init_IRQ(); -#elif defined(CONFIG_ALPHA_RAWHIDE) - rawhide_init_IRQ(); -#elif defined(CONFIG_ALPHA_TAKARA) - takara_init_IRQ(); -#elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P) - init_IRQ_32(); -#elif NR_IRQS == 16 - init_IRQ_16(); -#else -#error "How do I initialize the interrupt hardware?" -#endif + alpha_mv.init_irq(); } diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/irq.h linux/arch/alpha/kernel/irq.h --- v2.1.115/linux/arch/alpha/kernel/irq.h Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/irq.h Sun Aug 9 12:09:05 1998 @@ -0,0 +1,27 @@ +/* + * linux/arch/alpha/kernel/irq.h + * + * Copyright (C) 1995 Linus Torvalds + * Copyright (C) 1998 Richard Henderson + * + * This file contains declarations and inline functions for interfacing + * with the IRQ handling routines in irq.c. + */ + + +/* FIXME FIXME FIXME FIXME FIXME */ +/* We need to figure out why these fail on the DP264 & SX164. Otherwise + we'd just do this in init_IRQ(). */ +#define STANDARD_INIT_IRQ_PROLOG \ + outb(0, DMA1_RESET_REG); \ + outb(0, DMA2_RESET_REG); \ + outb(0, DMA1_CLR_MASK_REG); \ + outb(0, DMA2_CLR_MASK_REG) + +extern unsigned long alpha_irq_mask; + +extern void generic_ack_irq(unsigned long irq); +extern void isa_device_interrupt(unsigned long vector, struct pt_regs * regs); +extern void srm_device_interrupt(unsigned long vector, struct pt_regs * regs); + +extern void handle_irq(int irq, int ack, struct pt_regs * regs); diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/lca.c linux/arch/alpha/kernel/lca.c --- v2.1.115/linux/arch/alpha/kernel/lca.c Tue Jul 21 00:15:29 1998 +++ linux/arch/alpha/kernel/lca.c Wed Dec 31 16:00:00 1969 @@ -1,559 +0,0 @@ -/* - * Code common to all LCA chips. - * - * Written by David Mosberger (davidm@cs.arizona.edu) with some code - * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit - * bios code. - */ -#include -#include -#include -#include - -#include -#include -#include -#include - -/* - * BIOS32-style PCI interface: - */ - -#define vulp volatile unsigned long * -#define vuip volatile unsigned int * - -/* - * Machine check reasons. Defined according to PALcode sources - * (osf.h and platform.h). - */ -#define MCHK_K_TPERR 0x0080 -#define MCHK_K_TCPERR 0x0082 -#define MCHK_K_HERR 0x0084 -#define MCHK_K_ECC_C 0x0086 -#define MCHK_K_ECC_NC 0x0088 -#define MCHK_K_UNKNOWN 0x008A -#define MCHK_K_CACKSOFT 0x008C -#define MCHK_K_BUGCHECK 0x008E -#define MCHK_K_OS_BUGCHECK 0x0090 -#define MCHK_K_DCPERR 0x0092 -#define MCHK_K_ICPERR 0x0094 - -/* - * Platform-specific machine-check reasons: - */ -#define MCHK_K_SIO_SERR 0x204 /* all platforms so far */ -#define MCHK_K_SIO_IOCHK 0x206 /* all platforms so far */ -#define MCHK_K_DCSR 0x208 /* all but Noname */ - -#ifdef CONFIG_ALPHA_SRM_SETUP -unsigned int LCA_DMA_WIN_BASE = LCA_DMA_WIN_BASE_DEFAULT; -unsigned int LCA_DMA_WIN_SIZE = LCA_DMA_WIN_SIZE_DEFAULT; -#endif /* SRM_SETUP */ - -/* - * Given a bus, device, and function number, compute resulting - * configuration space address and setup the LCA_IOC_CONF register - * accordingly. It is therefore not safe to have concurrent - * invocations to configuration space access routines, but there - * really shouldn't be any need for this. - * - * Type 0: - * - * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 - * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | | | | | | | | | | | | | | | | | | | | | | |F|F|F|R|R|R|R|R|R|0|0| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * 31:11 Device select bit. - * 10:8 Function number - * 7:2 Register number - * - * Type 1: - * - * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 - * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * 31:24 reserved - * 23:16 bus number (8 bits = 128 possible buses) - * 15:11 Device number (5 bits) - * 10:8 function number - * 7:2 register number - * - * Notes: - * The function number selects which function of a multi-function device - * (e.g., SCSI and Ethernet). - * - * The register selects a DWORD (32 bit) register offset. Hence it - * doesn't get shifted by 2 bits as we want to "drop" the bottom two - * bits. - */ -static int mk_conf_addr(unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned long *pci_addr) -{ - unsigned long addr; - - if (bus == 0) { - int device = device_fn >> 3; - int func = device_fn & 0x7; - - /* type 0 configuration cycle: */ - - if (device > 12) { - return -1; - } - - *(vulp)LCA_IOC_CONF = 0; - addr = (1 << (11 + device)) | (func << 8) | where; - } else { - /* type 1 configuration cycle: */ - *(vulp)LCA_IOC_CONF = 1; - addr = (bus << 16) | (device_fn << 8) | where; - } - *pci_addr = addr; - return 0; -} - - -static unsigned int conf_read(unsigned long addr) -{ - unsigned long flags, code, stat0; - unsigned int value; - - save_flags(flags); - cli(); - - /* reset status register to avoid loosing errors: */ - stat0 = *(vulp)LCA_IOC_STAT0; - *(vulp)LCA_IOC_STAT0 = stat0; - mb(); - - /* access configuration space: */ - - value = *(vuip)addr; - draina(); - - stat0 = *(vulp)LCA_IOC_STAT0; - if (stat0 & LCA_IOC_STAT0_ERR) { - code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT) - & LCA_IOC_STAT0_CODE_MASK); - if (code != 1) { - printk("lca.c:conf_read: got stat0=%lx\n", stat0); - } - - /* reset error status: */ - *(vulp)LCA_IOC_STAT0 = stat0; - mb(); - wrmces(0x7); /* reset machine check */ - - value = 0xffffffff; - } - restore_flags(flags); - return value; -} - - -static void conf_write(unsigned long addr, unsigned int value) -{ - unsigned long flags, code, stat0; - - save_flags(flags); /* avoid getting hit by machine check */ - cli(); - - /* reset status register to avoid loosing errors: */ - stat0 = *(vulp)LCA_IOC_STAT0; - *(vulp)LCA_IOC_STAT0 = stat0; - mb(); - - /* access configuration space: */ - - *(vuip)addr = value; - draina(); - - stat0 = *(vulp)LCA_IOC_STAT0; - if (stat0 & LCA_IOC_STAT0_ERR) { - code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT) - & LCA_IOC_STAT0_CODE_MASK); - if (code != 1) { - printk("lca.c:conf_write: got stat0=%lx\n", stat0); - } - - /* reset error status: */ - *(vulp)LCA_IOC_STAT0 = stat0; - mb(); - wrmces(0x7); /* reset machine check */ - } - restore_flags(flags); -} - - -int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned char *value) -{ - unsigned long addr = LCA_CONF; - unsigned long pci_addr; - - *value = 0xff; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x00; - *value = conf_read(addr) >> ((where & 3) * 8); - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_read_config_word (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short *value) -{ - unsigned long addr = LCA_CONF; - unsigned long pci_addr; - - *value = 0xffff; - - if (where & 0x1) { - return PCIBIOS_BAD_REGISTER_NUMBER; - } - if (mk_conf_addr(bus, device_fn, where, &pci_addr)) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x08; - *value = conf_read(addr) >> ((where & 3) * 8); - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int *value) -{ - unsigned long addr = LCA_CONF; - unsigned long pci_addr; - - *value = 0xffffffff; - if (where & 0x3) { - return PCIBIOS_BAD_REGISTER_NUMBER; - } - if (mk_conf_addr(bus, device_fn, where, &pci_addr)) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x18; - *value = conf_read(addr); - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned char value) -{ - unsigned long addr = LCA_CONF; - unsigned long pci_addr; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x00; - conf_write(addr, value << ((where & 3) * 8)); - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_write_config_word (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short value) -{ - unsigned long addr = LCA_CONF; - unsigned long pci_addr; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x08; - conf_write(addr, value << ((where & 3) * 8)); - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int value) -{ - unsigned long addr = LCA_CONF; - unsigned long pci_addr; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x18; - conf_write(addr, value << ((where & 3) * 8)); - return PCIBIOS_SUCCESSFUL; -} - - -unsigned long lca_init(unsigned long mem_start, unsigned long mem_end) -{ -#ifdef CONFIG_ALPHA_SRM_SETUP - /* check window 0 for enabled and mapped to 0 */ - if ((*(vulp)LCA_IOC_W_BASE0 & (1UL<<33)) && - (*(vulp)LCA_IOC_T_BASE0 == 0)) - { - LCA_DMA_WIN_BASE = *(vulp)LCA_IOC_W_BASE0 & 0xffffffffUL; - LCA_DMA_WIN_SIZE = *(vulp)LCA_IOC_W_MASK0 & 0xffffffffUL; - LCA_DMA_WIN_SIZE += 1; -#if 1 - printk("lca_init: using Window 0 settings\n"); - printk("lca_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n", - *(vulp)LCA_IOC_W_BASE0, - *(vulp)LCA_IOC_W_MASK0, - *(vulp)LCA_IOC_T_BASE0); -#endif - } - else /* check window 2 for enabled and mapped to 0 */ - if ((*(vulp)LCA_IOC_W_BASE1 & (1UL<<33)) && - (*(vulp)LCA_IOC_T_BASE1 == 0)) - { - LCA_DMA_WIN_BASE = *(vulp)LCA_IOC_W_BASE1 & 0xffffffffUL; - LCA_DMA_WIN_SIZE = *(vulp)LCA_IOC_W_MASK1 & 0xffffffffUL; - LCA_DMA_WIN_SIZE += 1; -#if 1 - printk("lca_init: using Window 1 settings\n"); - printk("lca_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n", - *(vulp)LCA_IOC_W_BASE1, - *(vulp)LCA_IOC_W_MASK1, - *(vulp)LCA_IOC_T_BASE1); -#endif - } - else /* we must use our defaults... */ -#endif /* SRM_SETUP */ - { - /* - * Set up the PCI->physical memory translation windows. - * For now, window 1 is disabled. In the future, we may - * want to use it to do scatter/gather DMA. Window 0 - * goes at 1 GB and is 1 GB large. - */ - *(vulp)LCA_IOC_W_BASE1 = 0UL<<33; - - *(vulp)LCA_IOC_W_BASE0 = 1UL<<33 | LCA_DMA_WIN_BASE; - *(vulp)LCA_IOC_W_MASK0 = LCA_DMA_WIN_SIZE - 1; - *(vulp)LCA_IOC_T_BASE0 = 0; - } - - /* - * Disable PCI parity for now. The NCR53c810 chip has - * troubles meeting the PCI spec which results in - * data parity errors. - */ - *(vulp)LCA_IOC_PAR_DIS = 1UL<<5; - return mem_start; -} - - -/* - * Constants used during machine-check handling. I suppose these - * could be moved into lca.h but I don't see much reason why anybody - * else would want to use them. - */ - -#define ESR_EAV (1UL<< 0) /* error address valid */ -#define ESR_CEE (1UL<< 1) /* correctable error */ -#define ESR_UEE (1UL<< 2) /* uncorrectable error */ -#define ESR_WRE (1UL<< 3) /* write-error */ -#define ESR_SOR (1UL<< 4) /* error source */ -#define ESR_CTE (1UL<< 7) /* cache-tag error */ -#define ESR_MSE (1UL<< 9) /* multiple soft errors */ -#define ESR_MHE (1UL<<10) /* multiple hard errors */ -#define ESR_NXM (1UL<<12) /* non-existent memory */ - -#define IOC_ERR ( 1<<4) /* ioc logs an error */ -#define IOC_CMD_SHIFT 0 -#define IOC_CMD (0xf<> IOC_CODE_SHIFT; - unsigned cmd = (stat0 & IOC_CMD) >> IOC_CMD_SHIFT; - - printk(" %s initiated PCI %s cycle to address %x" - " failed due to %s.\n", - code > 3 ? "PCI" : "CPU", pci_cmd[cmd], stat1, err_name[code]); - - if (code == 5 || code == 6) { - printk(" (Error occurred at PCI memory address %x.)\n", - (stat0 & ~IOC_P_NBR)); - } - if (stat0 & IOC_LOST) { - printk(" Other PCI errors occurred simultaneously.\n"); - } -} - - -void lca_machine_check (unsigned long vector, unsigned long la, - struct pt_regs *regs) -{ - unsigned long * ptr; - const char * reason; - union el_lca el; - char buf[128]; - long i; - - printk(KERN_CRIT "lca: machine check (la=0x%lx,pc=0x%lx)\n", - la, regs->pc); - el.c = (struct el_common *) la; - /* - * The first quadword after the common header always seems to - * be the machine check reason---don't know why this isn't - * part of the common header instead. In the case of a long - * logout frame, the upper 32 bits is the machine check - * revision level, which we ignore for now. - */ - switch (el.c->code & 0xffffffff) { - case MCHK_K_TPERR: reason = "tag parity error"; break; - case MCHK_K_TCPERR: reason = "tag control parity error"; break; - case MCHK_K_HERR: reason = "access to non-existent memory"; break; - case MCHK_K_ECC_C: reason = "correctable ECC error"; break; - case MCHK_K_ECC_NC: reason = "non-correctable ECC error"; break; - case MCHK_K_CACKSOFT: reason = "MCHK_K_CACKSOFT"; break; /* what's this? */ - case MCHK_K_BUGCHECK: reason = "illegal exception in PAL mode"; break; - case MCHK_K_OS_BUGCHECK: reason = "callsys in kernel mode"; break; - case MCHK_K_DCPERR: reason = "d-cache parity error"; break; - case MCHK_K_ICPERR: reason = "i-cache parity error"; break; - case MCHK_K_SIO_SERR: reason = "SIO SERR occurred on on PCI bus"; break; - case MCHK_K_SIO_IOCHK: reason = "SIO IOCHK occurred on ISA bus"; break; - case MCHK_K_DCSR: reason = "MCHK_K_DCSR"; break; - case MCHK_K_UNKNOWN: - default: - sprintf(buf, "reason for machine-check unknown (0x%lx)", - el.c->code & 0xffffffff); - reason = buf; - break; - } - - wrmces(rdmces()); /* reset machine check pending flag */ - - switch (el.c->size) { - case sizeof(struct el_lca_mcheck_short): - printk(KERN_CRIT - " Reason: %s (short frame%s, dc_stat=%lx):\n", - reason, el.c->retry ? ", retryable" : "", - el.s->dc_stat); - if (el.s->esr & ESR_EAV) { - mem_error(el.s->esr, el.s->ear); - } - if (el.s->ioc_stat0 & IOC_ERR) { - ioc_error(el.s->ioc_stat0, el.s->ioc_stat1); - } - break; - - case sizeof(struct el_lca_mcheck_long): - printk(KERN_CRIT " Reason: %s (long frame%s):\n", - reason, el.c->retry ? ", retryable" : ""); - printk(KERN_CRIT - " reason: %lx exc_addr: %lx dc_stat: %lx\n", - el.l->pt[0], el.l->exc_addr, el.l->dc_stat); - printk(KERN_CRIT " car: %lx\n", el.l->car); - if (el.l->esr & ESR_EAV) { - mem_error(el.l->esr, el.l->ear); - } - if (el.l->ioc_stat0 & IOC_ERR) { - ioc_error(el.l->ioc_stat0, el.l->ioc_stat1); - } - break; - - default: - printk(KERN_CRIT " Unknown errorlog size %d\n", el.c->size); - } - - /* dump the logout area to give all info: */ - - ptr = (unsigned long *) la; - for (i = 0; i < el.c->size / sizeof(long); i += 2) { - printk(KERN_CRIT " +%8lx %016lx %016lx\n", - i*sizeof(long), ptr[i], ptr[i+1]); - } -} - -/* - * The following routines are needed to support the SPEED changing - * necessary to successfully manage the thermal problem on the AlphaBook1. - */ - -void -lca_clock_print(void) -{ - long pmr_reg; - - pmr_reg = READ_PMR; - - printk("Status of clock control:\n"); - printk("\tPrimary clock divisor\t0x%x\n", GET_PRIMARY(pmr_reg)); - printk("\tOverride clock divisor\t0x%x\n", GET_OVERRIDE(pmr_reg)); - printk("\tInterrupt override is %s\n", - (pmr_reg & LCA_PMR_INTO) ? "on" : "off"); - printk("\tDMA override is %s\n", - (pmr_reg & LCA_PMR_DMAO) ? "on" : "off"); - -} - -int -lca_get_clock(void) -{ - long pmr_reg; - - pmr_reg = READ_PMR; - return(GET_PRIMARY(pmr_reg)); - -} - -void -lca_clock_fiddle(int divisor) -{ - long pmr_reg; - - pmr_reg = READ_PMR; - SET_PRIMARY_CLOCK(pmr_reg, divisor); - /* lca_norm_clock = divisor; */ - WRITE_PMR(pmr_reg); - mb(); -} diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/machvec.h linux/arch/alpha/kernel/machvec.h --- v2.1.115/linux/arch/alpha/kernel/machvec.h Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/machvec.h Thu Aug 13 15:36:30 1998 @@ -0,0 +1,137 @@ +/* + * linux/arch/alpha/kernel/machvec.h + * + * Copyright (C) 1997, 1998 Richard Henderson + * + * This file has goodies to help simplify instantiation of machine vectors. + */ + +#include + +/* Whee. TSUNAMI doesn't have an HAE. Fix things up for the GENERIC + kernel by defining the HAE address to be that of the cache. Now + we can read and write it as we like. ;-) */ +#define TSUNAMI_HAE_ADDRESS (&alpha_mv.hae_cache) + +/* Only a few systems don't define IACK_SC, handling all interrupts through + the SRM console. But splitting out that one case from IO() below + seems like such a pain. Define this to get things to compile. */ +#define JENSEN_IACK_SC 1 +#define T2_IACK_SC 1 + + +/* + * Some helpful macros for filling in the blanks. + */ + +#define CAT1(x,y) x##y +#define CAT(x,y) CAT1(x,y) + +#define DO_DEFAULT_RTC \ + rtc_port: 0x70, rtc_addr: 0x80 + +#define DO_EV4_MMU \ + max_asn: EV4_MAX_ASN, \ + mmu_context_mask: ~0UL, \ + mv_get_mmu_context: ev4_get_mmu_context, \ + mv_flush_tlb_current: ev4_flush_tlb_current, \ + mv_flush_tlb_other: ev4_flush_tlb_other, \ + mv_flush_tlb_current_page: ev4_flush_tlb_current_page + +#define DO_EV5_MMU \ + max_asn: EV5_MAX_ASN, \ + mmu_context_mask: ~0UL, \ + mv_get_mmu_context: ev5_get_mmu_context, \ + mv_flush_tlb_current: ev5_flush_tlb_current, \ + mv_flush_tlb_other: ev5_flush_tlb_other, \ + mv_flush_tlb_current_page: ev5_flush_tlb_current_page + +#define DO_EV6_MMU \ + max_asn: EV5_MAX_ASN, \ + mmu_context_mask: 0xfffffffffful, \ + mv_get_mmu_context: ev5_get_mmu_context, \ + mv_flush_tlb_current: ev5_flush_tlb_current, \ + mv_flush_tlb_other: ev5_flush_tlb_other, \ + mv_flush_tlb_current_page: ev5_flush_tlb_current_page + +#define IO_LITE(UP,low1,low2) \ + hae_register: (unsigned long *) CAT(UP,_HAE_ADDRESS), \ + iack_sc: CAT(UP,_IACK_SC), \ + mv_inb: CAT(low1,_inb), \ + mv_inw: CAT(low1,_inw), \ + mv_inl: CAT(low1,_inl), \ + mv_outb: CAT(low1,_outb), \ + mv_outw: CAT(low1,_outw), \ + mv_outl: CAT(low1,_outl), \ + mv_readb: CAT(low1,_readb), \ + mv_readw: CAT(low1,_readw), \ + mv_readl: CAT(low1,_readl), \ + mv_readq: CAT(low1,_readq), \ + mv_writeb: CAT(low1,_writeb), \ + mv_writew: CAT(low1,_writew), \ + mv_writel: CAT(low1,_writel), \ + mv_writeq: CAT(low1,_writeq), \ + mv_dense_mem: CAT(low2,_dense_mem) + +#define IO(UP,low1,low2) \ + IO_LITE(UP,low1,low2), \ + pci_read_config_byte: CAT(low2,_pcibios_read_config_byte), \ + pci_read_config_word: CAT(low2,_pcibios_read_config_word), \ + pci_read_config_dword: CAT(low2,_pcibios_read_config_dword), \ + pci_write_config_byte: CAT(low2,_pcibios_write_config_byte), \ + pci_write_config_word: CAT(low2,_pcibios_write_config_word), \ + pci_write_config_dword: CAT(low2,_pcibios_write_config_dword), \ + dma_win_base: CAT(UP,_DMA_WIN_BASE_DEFAULT), \ + dma_win_size: CAT(UP,_DMA_WIN_SIZE_DEFAULT) + +/* Any assembler that can generate a GENERIC kernel can generate BWX + instructions. So always use them for PYXIS I/O. */ + +#define DO_APECS_IO IO(APECS,apecs,apecs) +#define DO_CIA_IO IO(CIA,cia,cia) +#define DO_LCA_IO IO(LCA,lca,lca) +#define DO_MCPCIA_IO IO(MCPCIA,mcpcia,mcpcia) +#define DO_PYXIS_IO IO(PYXIS,pyxis_bw,pyxis) +#define DO_T2_IO IO(T2,t2,t2) +#define DO_TSUNAMI_IO IO(TSUNAMI,tsunami,tsunami) + +#define BUS(which) \ + mv_virt_to_bus: CAT(which,_virt_to_bus), \ + mv_bus_to_virt: CAT(which,_bus_to_virt) + +#define DO_APECS_BUS BUS(apecs) +#define DO_CIA_BUS BUS(cia) +#define DO_LCA_BUS BUS(lca) +#define DO_MCPCIA_BUS BUS(mcpcia) +#define DO_PYXIS_BUS BUS(pyxis) +#define DO_T2_BUS BUS(t2) +#define DO_TSUNAMI_BUS BUS(tsunami) + + +/* + * In a GENERIC kernel, we have lots of these vectors floating about, + * all but one of which we want to go away. In a non-GENERIC kernel, + * we want only one, ever. + * + * Accomplish this in the GENERIC kernel by puting all of the vectors + * in the .init.data section where they'll go away. We'll copy the + * one we want to the real alpha_mv vector in setup_arch. + * + * Accomplish this in a non-GENERIC kernel by ifdef'ing out all but + * one of the vectors, which will not reside in .init.data. We then + * alias this one vector to alpha_mv, so no copy is needed. + * + * Upshot: set __initdata to nothing for non-GENERIC kernels. + */ + +#ifdef CONFIG_ALPHA_GENERIC +#define __initmv __initdata +#define ALIAS_MV(x) +#else +#define __initmv + +/* GCC actually has a syntax for defining aliases, but is under some + delusion that you shouldn't be able to declare it extern somewhere + else beforehand. Fine. We'll do it ourselves. */ +#define ALIAS_MV(system) asm(".global alpha_mv\nalpha_mv = " #system "_mv"); +#endif diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/mcpcia.c linux/arch/alpha/kernel/mcpcia.c --- v2.1.115/linux/arch/alpha/kernel/mcpcia.c Tue Jul 21 00:15:29 1998 +++ linux/arch/alpha/kernel/mcpcia.c Wed Dec 31 16:00:00 1969 @@ -1,975 +0,0 @@ -/* - * Code common to all MCbus-PCI adaptor chipsets - * - * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com). - * - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * NOTE: Herein lie back-to-back mb instructions. They are magic. - * One plausible explanation is that the i/o controller does not properly - * handle the system transaction. Another involves timing. Ho hum. - */ - -extern struct hwrpb_struct *hwrpb; -extern asmlinkage void wrmces(unsigned long mces); - -/* - * BIOS32-style PCI interface: - */ - -#ifdef CONFIG_ALPHA_MCPCIA - -#undef DEBUG_CFG - -#ifdef DEBUG_CFG -# define DBG_CFG(args) printk args -#else -# define DBG_CFG(args) -#endif - -#undef DEBUG_PCI - -#ifdef DEBUG_PCI -# define DBG_PCI(args) printk args -#else -# define DBG_PCI(args) -#endif - -#define DEBUG_MCHECK - -#ifdef DEBUG_MCHECK -# define DBG_MCK(args) printk args -# define DEBUG_MCHECK_DUMP -#else -# define DBG_MCK(args) -#endif - -#define vuip volatile unsigned int * -#define vulp volatile unsigned long * - -static volatile unsigned int MCPCIA_mcheck_expected[NR_CPUS]; -static volatile unsigned int MCPCIA_mcheck_taken[NR_CPUS]; -static unsigned int MCPCIA_jd[NR_CPUS]; - -#define MCPCIA_MAX_HOSES 2 -static int mcpcia_num_hoses = 0; - -static int pci_probe_enabled = 0; /* disable to start */ - -static struct linux_hose_info *mcpcia_root = NULL, *mcpcia_last_hose; - -struct linux_hose_info *bus2hose[256]; - -static inline unsigned long long_align(unsigned long addr) -{ - return ((addr + (sizeof(unsigned long) - 1)) & - ~(sizeof(unsigned long) - 1)); -} - -#ifdef CONFIG_ALPHA_SRM_SETUP -unsigned int MCPCIA_DMA_WIN_BASE = MCPCIA_DMA_WIN_BASE_DEFAULT; -unsigned int MCPCIA_DMA_WIN_SIZE = MCPCIA_DMA_WIN_SIZE_DEFAULT; -unsigned long mcpcia_sm_base_r1, mcpcia_sm_base_r2, mcpcia_sm_base_r3; -#endif /* SRM_SETUP */ - -/* - * Given a bus, device, and function number, compute resulting - * configuration space address and setup the MCPCIA_HAXR2 register - * accordingly. It is therefore not safe to have concurrent - * invocations to configuration space access routines, but there - * really shouldn't be any need for this. - * - * Type 0: - * - * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 - * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * 31:11 Device select bit. - * 10:8 Function number - * 7:2 Register number - * - * Type 1: - * - * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 - * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * 31:24 reserved - * 23:16 bus number (8 bits = 128 possible buses) - * 15:11 Device number (5 bits) - * 10:8 function number - * 7:2 register number - * - * Notes: - * The function number selects which function of a multi-function device - * (e.g., SCSI and Ethernet). - * - * The register selects a DWORD (32 bit) register offset. Hence it - * doesn't get shifted by 2 bits as we want to "drop" the bottom two - * bits. - */ - -static unsigned int -conf_read(unsigned long addr, unsigned char type1, - struct linux_hose_info *hose) -{ - unsigned long flags; - unsigned long hoseno = hose->pci_hose_index; - unsigned int stat0, value, temp, cpu; - - cpu = smp_processor_id(); - - save_and_cli(flags); - - DBG_CFG(("conf_read(addr=0x%lx, type1=%d, hose=%d)\n", - addr, type1, hoseno)); - - /* reset status register to avoid losing errors: */ - stat0 = *(vuip)MCPCIA_CAP_ERR(hoseno); - *(vuip)MCPCIA_CAP_ERR(hoseno) = stat0; mb(); - temp = *(vuip)MCPCIA_CAP_ERR(hoseno); - DBG_CFG(("conf_read: MCPCIA CAP_ERR(%d) was 0x%x\n", hoseno, stat0)); - - mb(); - draina(); - MCPCIA_mcheck_expected[cpu] = 1; - MCPCIA_mcheck_taken[cpu] = 0; - mb(); - /* access configuration space: */ - value = *((vuip)addr); - mb(); - mb(); /* magic */ - if (MCPCIA_mcheck_taken[cpu]) { - MCPCIA_mcheck_taken[cpu] = 0; - value = 0xffffffffU; - mb(); - } - MCPCIA_mcheck_expected[cpu] = 0; - mb(); - - DBG_CFG(("conf_read(): finished\n")); - - restore_flags(flags); - return value; -} - - -static void -conf_write(unsigned long addr, unsigned int value, unsigned char type1, - struct linux_hose_info *hose) -{ - unsigned long flags; - unsigned long hoseno = hose->pci_hose_index; - unsigned int stat0, temp, cpu; - - cpu = smp_processor_id(); - - save_and_cli(flags); /* avoid getting hit by machine check */ - - /* reset status register to avoid losing errors: */ - stat0 = *(vuip)MCPCIA_CAP_ERR(hoseno); - *(vuip)MCPCIA_CAP_ERR(hoseno) = stat0; mb(); - temp = *(vuip)MCPCIA_CAP_ERR(hoseno); - DBG_CFG(("conf_write: MCPCIA CAP_ERR(%d) was 0x%x\n", hoseno, stat0)); - - draina(); - MCPCIA_mcheck_expected[cpu] = 1; - mb(); - /* access configuration space: */ - *((vuip)addr) = value; - mb(); - mb(); /* magic */ - temp = *(vuip)MCPCIA_CAP_ERR(hoseno); /* read to force the write */ - MCPCIA_mcheck_expected[cpu] = 0; - mb(); - - DBG_CFG(("conf_write(): finished\n")); - restore_flags(flags); -} - -static int mk_conf_addr(struct linux_hose_info *hose, - unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned long *pci_addr, - unsigned char *type1) -{ - unsigned long addr; - - if (!pci_probe_enabled) /* if doing standard pci_init(), ignore */ - return -1; - - DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x," - " pci_addr=0x%p, type1=0x%p)\n", - bus, device_fn, where, pci_addr, type1)); - - /* type 1 configuration cycle for *ALL* busses */ - *type1 = 1; - - if (hose->pci_first_busno == bus) - bus = 0; - addr = (bus << 16) | (device_fn << 8) | (where); - addr <<= 5; /* swizzle for SPARSE */ - addr |= hose->pci_config_space; - - *pci_addr = addr; - DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr)); - return 0; -} - - -int hose_read_config_byte (struct linux_hose_info *hose, - unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned char *value) -{ - unsigned long addr; - unsigned char type1; - - *value = 0xff; - - if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - - addr |= 0x00; /* or in length */ - - *value = conf_read(addr, type1, hose) >> ((where & 3) * 8); - return PCIBIOS_SUCCESSFUL; -} - - -int hose_read_config_word (struct linux_hose_info *hose, - unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short *value) -{ - unsigned long addr; - unsigned char type1; - - *value = 0xffff; - - if (where & 0x1) { - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1)) { - return PCIBIOS_SUCCESSFUL; - } - - addr |= 0x08; /* or in length */ - - *value = conf_read(addr, type1, hose) >> ((where & 3) * 8); - return PCIBIOS_SUCCESSFUL; -} - - -int hose_read_config_dword (struct linux_hose_info *hose, - unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int *value) -{ - unsigned long addr; - unsigned char type1; - - *value = 0xffffffff; - - if (where & 0x3) { - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1)) { - return PCIBIOS_SUCCESSFUL; - } - addr |= 0x18; /* or in length */ - - *value = conf_read(addr, type1, hose); - return PCIBIOS_SUCCESSFUL; -} - - -int hose_write_config_byte (struct linux_hose_info *hose, - unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned char value) -{ - unsigned long addr; - unsigned char type1; - - if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - - addr |= 0x00; /* or in length */ - - conf_write(addr, value << ((where & 3) * 8), type1, hose); - return PCIBIOS_SUCCESSFUL; -} - - -int hose_write_config_word (struct linux_hose_info *hose, - unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short value) -{ - unsigned long addr; - unsigned char type1; - - if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - - addr |= 0x08; /* or in length */ - - conf_write(addr, value << ((where & 3) * 8), type1, hose); - return PCIBIOS_SUCCESSFUL; -} - - -int hose_write_config_dword (struct linux_hose_info *hose, - unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int value) -{ - unsigned long addr; - unsigned char type1; - - if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - - addr |= 0x18; /* or in length */ - - conf_write(addr, value << ((where & 3) * 8), type1, hose); - return PCIBIOS_SUCCESSFUL; -} - -int pcibios_read_config_byte (unsigned char bus, unsigned char devfn, - unsigned char where, unsigned char *value) -{ - return hose_read_config_byte(bus2hose[bus], bus, devfn, where, value); -} - -int pcibios_read_config_word (unsigned char bus, unsigned char devfn, - unsigned char where, unsigned short *value) -{ - return hose_read_config_word(bus2hose[bus], bus, devfn, where, value); -} - -int pcibios_read_config_dword (unsigned char bus, unsigned char devfn, - unsigned char where, unsigned int *value) -{ - return hose_read_config_dword(bus2hose[bus], bus, devfn, where, value); -} - -int pcibios_write_config_byte (unsigned char bus, unsigned char devfn, - unsigned char where, unsigned char value) -{ - return hose_write_config_byte(bus2hose[bus], bus, devfn, where, value); -} - -int pcibios_write_config_word (unsigned char bus, unsigned char devfn, - unsigned char where, unsigned short value) -{ - return hose_write_config_word(bus2hose[bus], bus, devfn, where, value); -} - -int pcibios_write_config_dword (unsigned char bus, unsigned char devfn, - unsigned char where, unsigned int value) -{ - return hose_write_config_dword(bus2hose[bus], bus, devfn, where, value); -} - -unsigned long mcpcia_init(unsigned long mem_start, unsigned long mem_end) -{ - struct linux_hose_info *hose; - unsigned int mcpcia_err; - unsigned int pci_rev; - int h; - - mem_start = long_align(mem_start); - - for (h = 0; h < NR_CPUS; h++) { - MCPCIA_mcheck_expected[h] = 0; - MCPCIA_mcheck_taken[h] = 0; - } - - /* first, find how many hoses we have */ - for (h = 0; h < MCPCIA_MAX_HOSES; h++) { - pci_rev = *(vuip)MCPCIA_REV(h); -#if 0 - printk("mcpcia_init: got 0x%x for PCI_REV for hose %d\n", - pci_rev, h); -#endif - if ((pci_rev >> 16) == PCI_CLASS_BRIDGE_HOST) { - mcpcia_num_hoses++; - - hose = (struct linux_hose_info *)mem_start; - mem_start = long_align(mem_start + sizeof(*hose)); - - memset(hose, 0, sizeof(*hose)); - - if (mcpcia_root) - mcpcia_last_hose->next = hose; - else - mcpcia_root = hose; - mcpcia_last_hose = hose; - - hose->pci_io_space = MCPCIA_IO(h); - hose->pci_mem_space = MCPCIA_DENSE(h); - hose->pci_config_space = MCPCIA_CONF(h); - hose->pci_sparse_space = MCPCIA_SPARSE(h); - hose->pci_hose_index = h; - hose->pci_first_busno = 255; - hose->pci_last_busno = 0; - } - } - -#if 1 - printk("mcpcia_init: found %d hoses\n", mcpcia_num_hoses); -#endif - - /* now do init for each hose */ - for (hose = mcpcia_root; hose; hose = hose->next) { - h = hose->pci_hose_index; -#if 0 -#define PRINTK printk -PRINTK("mcpcia_init: -------- hose %d --------\n",h); -PRINTK("mcpcia_init: MCPCIA_REV 0x%x\n", *(vuip)MCPCIA_REV(h)); -PRINTK("mcpcia_init: MCPCIA_WHOAMI 0x%x\n", *(vuip)MCPCIA_WHOAMI(h)); -PRINTK("mcpcia_init: MCPCIA_HAE_MEM 0x%x\n", *(vuip)MCPCIA_HAE_MEM(h)); -PRINTK("mcpcia_init: MCPCIA_HAE_IO 0x%x\n", *(vuip)MCPCIA_HAE_IO(h)); -PRINTK("mcpcia_init: MCPCIA_HAE_DENSE 0x%x\n", *(vuip)MCPCIA_HAE_DENSE(h)); -PRINTK("mcpcia_init: MCPCIA_INT_CTL 0x%x\n", *(vuip)MCPCIA_INT_CTL(h)); -PRINTK("mcpcia_init: MCPCIA_INT_REQ 0x%x\n", *(vuip)MCPCIA_INT_REQ(h)); -PRINTK("mcpcia_init: MCPCIA_INT_TARG 0x%x\n", *(vuip)MCPCIA_INT_TARG(h)); -PRINTK("mcpcia_init: MCPCIA_INT_ADR 0x%x\n", *(vuip)MCPCIA_INT_ADR(h)); -PRINTK("mcpcia_init: MCPCIA_INT_ADR_EXT 0x%x\n", *(vuip)MCPCIA_INT_ADR_EXT(h)); -PRINTK("mcpcia_init: MCPCIA_INT_MASK0 0x%x\n", *(vuip)MCPCIA_INT_MASK0(h)); -PRINTK("mcpcia_init: MCPCIA_INT_MASK1 0x%x\n", *(vuip)MCPCIA_INT_MASK1(h)); -PRINTK("mcpcia_init: MCPCIA_HBASE 0x%x\n", *(vuip)MCPCIA_HBASE(h)); -#endif - - /* - * Set up error reporting. Make sure CPU_PE is OFF in the mask. - */ -#if 0 - mcpcia_err = *(vuip)MCPCIA_ERR_MASK(h); - mcpcia_err &= ~4; - *(vuip)MCPCIA_ERR_MASK(h) = mcpcia_err; - mb(); - mcpcia_err = *(vuip)MCPCIA_ERR_MASK; -#endif - - mcpcia_err = *(vuip)MCPCIA_CAP_ERR(h); - mcpcia_err |= 0x0006; /* master/target abort */ - *(vuip)MCPCIA_CAP_ERR(h) = mcpcia_err; - mb() ; - mcpcia_err = *(vuip)MCPCIA_CAP_ERR(h); - -#ifdef CONFIG_ALPHA_SRM_SETUP - /* check window 0 for enabled and mapped to 0 */ - if (((*(vuip)MCPCIA_W0_BASE(h) & 3) == 1) && - (*(vuip)MCPCIA_T0_BASE(h) == 0) && - ((*(vuip)MCPCIA_W0_MASK(h) & 0xfff00000U) > 0x0ff00000U)) - { - MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W0_BASE(h) & 0xfff00000U; - MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W0_MASK(h) & 0xfff00000U; - MCPCIA_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("mcpcia_init: using Window 0 settings\n"); - printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)MCPCIA_W0_BASE(h), - *(vuip)MCPCIA_W0_MASK(h), - *(vuip)MCPCIA_T0_BASE(h)); -#endif - } - else /* check window 1 for enabled and mapped to 0 */ - if (((*(vuip)MCPCIA_W1_BASE(h) & 3) == 1) && - (*(vuip)MCPCIA_T1_BASE(h) == 0) && - ((*(vuip)MCPCIA_W1_MASK(h) & 0xfff00000U) > 0x0ff00000U)) -{ - MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W1_BASE(h) & 0xfff00000U; - MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W1_MASK(h) & 0xfff00000U; - MCPCIA_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("mcpcia_init: using Window 1 settings\n"); - printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)MCPCIA_W1_BASE(h), - *(vuip)MCPCIA_W1_MASK(h), - *(vuip)MCPCIA_T1_BASE(h)); -#endif - } - else /* check window 2 for enabled and mapped to 0 */ - if (((*(vuip)MCPCIA_W2_BASE(h) & 3) == 1) && - (*(vuip)MCPCIA_T2_BASE(h) == 0) && - ((*(vuip)MCPCIA_W2_MASK(h) & 0xfff00000U) > 0x0ff00000U)) - { - MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W2_BASE(h) & 0xfff00000U; - MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W2_MASK(h) & 0xfff00000U; - MCPCIA_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("mcpcia_init: using Window 2 settings\n"); - printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)MCPCIA_W2_BASE(h), - *(vuip)MCPCIA_W2_MASK(h), - *(vuip)MCPCIA_T2_BASE(h)); -#endif - } - else /* check window 3 for enabled and mapped to 0 */ - if (((*(vuip)MCPCIA_W3_BASE(h) & 3) == 1) && - (*(vuip)MCPCIA_T3_BASE(h) == 0) && - ((*(vuip)MCPCIA_W3_MASK(h) & 0xfff00000U) > 0x0ff00000U)) - { - MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W3_BASE(h) & 0xfff00000U; - MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W3_MASK(h) & 0xfff00000U; - MCPCIA_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("mcpcia_init: using Window 3 settings\n"); - printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)MCPCIA_W3_BASE(h), - *(vuip)MCPCIA_W3_MASK(h), - *(vuip)MCPCIA_T3_BASE(h)); -#endif - } - else /* we must use our defaults which were pre-initialized... */ -#endif /* SRM_SETUP */ - { - /* - * Set up the PCI->physical memory translation windows. - * For now, windows 1,2 and 3 are disabled. In the future, we may - * want to use them to do scatter/gather DMA. Window 0 - * goes at 1 GB and is 1 GB large. - */ - - *(vuip)MCPCIA_W0_BASE(h) = 1U | (MCPCIA_DMA_WIN_BASE & 0xfff00000U); - *(vuip)MCPCIA_W0_MASK(h) = (MCPCIA_DMA_WIN_SIZE - 1) & 0xfff00000U; - *(vuip)MCPCIA_T0_BASE(h) = 0; - - *(vuip)MCPCIA_W1_BASE(h) = 0x0 ; - *(vuip)MCPCIA_W2_BASE(h) = 0x0 ; - *(vuip)MCPCIA_W3_BASE(h) = 0x0 ; - - *(vuip)MCPCIA_HBASE(h) = 0x0 ; - mb(); - } - - /* - * check ASN in HWRPB for validity, report if bad - */ - if (hwrpb->max_asn != MAX_ASN) { - printk("mcpcia_init: max ASN from HWRPB is bad (0x%lx)\n", - hwrpb->max_asn); - hwrpb->max_asn = MAX_ASN; - } - -#if 0 - { - unsigned int mcpcia_int_ctl = *((vuip)MCPCIA_INT_CTL(h)); - printk("mcpcia_init: INT_CTL was 0x%x\n", mcpcia_int_ctl); - *(vuip)MCPCIA_INT_CTL(h) = 1U; mb(); - mcpcia_int_ctl = *(vuip)MCPCIA_INT_CTL(h); - } -#endif - - { - unsigned int mcpcia_hae_mem = *(vuip)MCPCIA_HAE_MEM(h); - unsigned int mcpcia_hae_io = *(vuip)MCPCIA_HAE_IO(h); -#if 0 - printk("mcpcia_init: HAE_MEM was 0x%x\n", mcpcia_hae_mem); - printk("mcpcia_init: HAE_IO was 0x%x\n", mcpcia_hae_io); -#endif -#ifdef CONFIG_ALPHA_SRM_SETUP - /* - sigh... For the SRM setup, unless we know apriori what the HAE - contents will be, we need to setup the arbitrary region bases - so we can test against the range of addresses and tailor the - region chosen for the SPARSE memory access. - - see include/asm-alpha/mcpcia.h for the SPARSE mem read/write - */ - mcpcia_sm_base_r1 = (mcpcia_hae_mem ) & 0xe0000000UL;/* reg 1 */ - mcpcia_sm_base_r2 = (mcpcia_hae_mem << 16) & 0xf8000000UL;/* reg 2 */ - mcpcia_sm_base_r3 = (mcpcia_hae_mem << 24) & 0xfc000000UL;/* reg 3 */ - /* - Set the HAE cache, so that setup_arch() code - will use the SRM setting always. Our readb/writeb - code in mcpcia.h expects never to have to change - the contents of the HAE. - */ - hae.cache = mcpcia_hae_mem; -#else /* SRM_SETUP */ - *(vuip)MCPCIA_HAE_MEM(h) = 0U; mb(); - mcpcia_hae_mem = *(vuip)MCPCIA_HAE_MEM(h); - *(vuip)MCPCIA_HAE_IO(h) = 0; mb(); - mcpcia_hae_io = *(vuip)MCPCIA_HAE_IO(h); -#endif /* SRM_SETUP */ - } - } /* end for-loop on hoses */ - return mem_start; -} - -int mcpcia_pci_clr_err(int h) -{ - unsigned int cpu = smp_processor_id(); - - MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(h); -#if 0 - DBG_MCK(("MCPCIA_pci_clr_err: MCPCIA CAP_ERR(%d) after read 0x%x\n", - h, MCPCIA_jd[cpu])); -#endif - *(vuip)MCPCIA_CAP_ERR(h) = 0xffffffff; mb(); /* clear them all */ - MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(h); - return 0; -} - -static void -mcpcia_print_uncorrectable(struct el_MCPCIA_uncorrected_frame_mcheck *logout) -{ - struct el_common_EV5_uncorrectable_mcheck *frame; - int i; - - frame = &logout->procdata; - - /* Print PAL fields */ - for (i = 0; i < 24; i += 2) { - printk("\tpal temp[%d-%d]\t\t= %16lx %16lx\n\r", - i, i+1, frame->paltemp[i], frame->paltemp[i+1]); - } - for (i = 0; i < 8; i += 2) { - printk("\tshadow[%d-%d]\t\t= %16lx %16lx\n\r", - i, i+1, frame->shadow[i], - frame->shadow[i+1]); - } - printk("\tAddr of excepting instruction\t= %16lx\n\r", - frame->exc_addr); - printk("\tSummary of arithmetic traps\t= %16lx\n\r", - frame->exc_sum); - printk("\tException mask\t\t\t= %16lx\n\r", - frame->exc_mask); - printk("\tBase address for PALcode\t= %16lx\n\r", - frame->pal_base); - printk("\tInterrupt Status Reg\t\t= %16lx\n\r", - frame->isr); - printk("\tCURRENT SETUP OF EV5 IBOX\t= %16lx\n\r", - frame->icsr); - printk("\tI-CACHE Reg %s parity error\t= %16lx\n\r", - (frame->ic_perr_stat & 0x800L) ? - "Data" : "Tag", - frame->ic_perr_stat); - printk("\tD-CACHE error Reg\t\t= %16lx\n\r", - frame->dc_perr_stat); - if (frame->dc_perr_stat & 0x2) { - switch (frame->dc_perr_stat & 0x03c) { - case 8: - printk("\t\tData error in bank 1\n\r"); - break; - case 4: - printk("\t\tData error in bank 0\n\r"); - break; - case 20: - printk("\t\tTag error in bank 1\n\r"); - break; - case 10: - printk("\t\tTag error in bank 0\n\r"); - break; - } - } - printk("\tEffective VA\t\t\t= %16lx\n\r", - frame->va); - printk("\tReason for D-stream\t\t= %16lx\n\r", - frame->mm_stat); - printk("\tEV5 SCache address\t\t= %16lx\n\r", - frame->sc_addr); - printk("\tEV5 SCache TAG/Data parity\t= %16lx\n\r", - frame->sc_stat); - printk("\tEV5 BC_TAG_ADDR\t\t\t= %16lx\n\r", - frame->bc_tag_addr); - printk("\tEV5 EI_ADDR: Phys addr of Xfer\t= %16lx\n\r", - frame->ei_addr); - printk("\tFill Syndrome\t\t\t= %16lx\n\r", - frame->fill_syndrome); - printk("\tEI_STAT reg\t\t\t= %16lx\n\r", - frame->ei_stat); - printk("\tLD_LOCK\t\t\t\t= %16lx\n\r", - frame->ld_lock); -} - -void mcpcia_machine_check(unsigned long type, unsigned long la_ptr, - struct pt_regs * regs) -{ -#if 0 - printk("mcpcia machine check ignored\n") ; -#else - struct el_common *mchk_header; - struct el_MCPCIA_uncorrected_frame_mcheck *mchk_logout; - unsigned int cpu = smp_processor_id(); - int h = 0; - - mchk_header = (struct el_common *)la_ptr; - mchk_logout = (struct el_MCPCIA_uncorrected_frame_mcheck *)la_ptr; - -#if 0 - DBG_MCK(("mcpcia_machine_check: type=0x%lx la_ptr=0x%lx\n", - type, la_ptr)); - DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", - regs->pc, mchk_header->size, mchk_header->proc_offset, - mchk_header->sys_offset)); -#endif - /* - * Check if machine check is due to a badaddr() and if so, - * ignore the machine check. - */ - mb(); - mb(); /* magic */ - if (MCPCIA_mcheck_expected[cpu]) { -#if 0 - DBG_MCK(("MCPCIA machine check expected\n")); -#endif - MCPCIA_mcheck_expected[cpu] = 0; - MCPCIA_mcheck_taken[cpu] = 1; - mb(); - mb(); /* magic */ - draina(); - mcpcia_pci_clr_err(h); - wrmces(0x7); - mb(); - } -#if 1 - else { - printk("MCPCIA machine check NOT expected on CPU %d\n", cpu); - DBG_MCK(("mcpcia_machine_check: type=0x%lx pc=0x%lx" - " code=0x%lx\n", - type, regs->pc, mchk_header->code)); - - MCPCIA_mcheck_expected[cpu] = 0; - MCPCIA_mcheck_taken[cpu] = 1; - mb(); - mb(); /* magic */ - draina(); - mcpcia_pci_clr_err(h); - wrmces(0x7); - mb(); -#ifdef DEBUG_MCHECK_DUMP - if (type == 0x620) - printk("MCPCIA machine check: system CORRECTABLE!\n"); - else if (type == 0x630) - printk("MCPCIA machine check: processor CORRECTABLE!\n"); - else - mcpcia_print_uncorrectable(mchk_logout); -#endif /* DEBUG_MCHECK_DUMP */ - } -#endif -#endif -} - -/*==========================================================================*/ - -#define PRIMARY(b) ((b)&0xff) -#define SECONDARY(b) (((b)>>8)&0xff) -#define SUBORDINATE(b) (((b)>>16)&0xff) - -static int -hose_scan_bridges(struct linux_hose_info *hose, unsigned char bus) -{ - unsigned int devfn, l, class; - unsigned char hdr_type = 0; - unsigned int found = 0; - - for (devfn = 0; devfn < 0xff; ++devfn) { - if (PCI_FUNC(devfn) == 0) { - hose_read_config_byte(hose, bus, devfn, - PCI_HEADER_TYPE, &hdr_type); - } else if (!(hdr_type & 0x80)) { - /* not a multi-function device */ - continue; - } - - /* Check if there is anything here. */ - hose_read_config_dword(hose, bus, devfn, PCI_VENDOR_ID, &l); - if (l == 0xffffffff || l == 0x00000000) { - hdr_type = 0; - continue; - } - - /* See if this is a bridge device. */ - hose_read_config_dword(hose, bus, devfn, - PCI_CLASS_REVISION, &class); - - if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) { - unsigned int busses; - - found++; - - hose_read_config_dword(hose, bus, devfn, - PCI_PRIMARY_BUS, &busses); - -DBG_PCI(("hose_scan_bridges: hose %d bus %d slot %d busses 0x%x\n", - hose->pci_hose_index, bus, PCI_SLOT(devfn), busses)); - /* - * do something with first_busno and last_busno - */ - if (hose->pci_first_busno > PRIMARY(busses)) { - hose->pci_first_busno = PRIMARY(busses); -DBG_PCI(("hose_scan_bridges: hose %d bus %d slot %d change first to %d\n", - hose->pci_hose_index, bus, PCI_SLOT(devfn), PRIMARY(busses))); - } - if (hose->pci_last_busno < SUBORDINATE(busses)) { - hose->pci_last_busno = SUBORDINATE(busses); -DBG_PCI(("hose_scan_bridges: hose %d bus %d slot %d change last to %d\n", - hose->pci_hose_index, bus, PCI_SLOT(devfn), SUBORDINATE(busses))); - } - /* - * Now scan everything underneath the bridge. - */ - hose_scan_bridges(hose, SECONDARY(busses)); - } - } - return found; -} - -static void -hose_reconfigure_bridges(struct linux_hose_info *hose, unsigned char bus) -{ - unsigned int devfn, l, class; - unsigned char hdr_type = 0; - - for (devfn = 0; devfn < 0xff; ++devfn) { - if (PCI_FUNC(devfn) == 0) { - hose_read_config_byte(hose, bus, devfn, - PCI_HEADER_TYPE, &hdr_type); - } else if (!(hdr_type & 0x80)) { - /* not a multi-function device */ - continue; - } - - /* Check if there is anything here. */ - hose_read_config_dword(hose, bus, devfn, PCI_VENDOR_ID, &l); - if (l == 0xffffffff || l == 0x00000000) { - hdr_type = 0; - continue; - } - - /* See if this is a bridge device. */ - hose_read_config_dword(hose, bus, devfn, - PCI_CLASS_REVISION, &class); - - if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) { - unsigned int busses; - - hose_read_config_dword(hose, bus, devfn, - PCI_PRIMARY_BUS, &busses); - - /* - * First reconfigure everything underneath the bridge. - */ - hose_reconfigure_bridges(hose, (busses >> 8) & 0xff); - - /* - * Unconfigure this bridges bus numbers, - * pci_scan_bus() will fix this up properly. - */ - busses &= 0xff000000; - hose_write_config_dword(hose, bus, devfn, - PCI_PRIMARY_BUS, busses); - } - } -} - -static void mcpcia_fixup_busno(struct linux_hose_info *hose, unsigned char bus) -{ - unsigned int nbus; - - /* - * First, scan for all bridge devices underneath this hose, - * to determine the first and last busnos. - */ - if (!hose_scan_bridges(hose, 0)) { - /* none found, exit */ - hose->pci_first_busno = bus; - hose->pci_last_busno = bus; - } else { - /* - * Reconfigure all bridge devices underneath this hose. - */ - hose_reconfigure_bridges(hose, hose->pci_first_busno); - } - - /* - * Now reconfigure the hose to it's new bus number and set up - * our bus2hose mapping for this hose. - */ - nbus = hose->pci_last_busno - hose->pci_first_busno; - - hose->pci_first_busno = bus; - -DBG_PCI(("mcpcia_fixup_busno: hose %d startbus %d nbus %d\n", - hose->pci_hose_index, bus, nbus)); - - do { - bus2hose[bus++] = hose; - } while (nbus-- > 0); -} - -static void mcpcia_probe(struct linux_hose_info *hose) -{ - static struct pci_bus *pchain = NULL; - struct pci_bus *pbus = &hose->pci_bus; - static unsigned char busno = 0; - - /* Hoses include child PCI bridges in bus-range property, - * but we don't scan each of those ourselves, Linux generic PCI - * probing code will find child bridges and link them into this - * hose's root PCI device hierarchy. - */ - - pbus->number = pbus->secondary = busno; - pbus->sysdata = hose; - - mcpcia_fixup_busno(hose, busno); - - pbus->subordinate = pci_scan_bus(pbus); /* the original! */ - - /* - * Set the maximum subordinate bus of this hose. - */ - hose->pci_last_busno = pbus->subordinate; -#if 0 - hose_write_config_byte(hose, busno, 0, 0x41, hose->pci_last_busno); -#endif - busno = pbus->subordinate + 1; - - /* - * Fixup the chain of primary PCI busses. - */ - if (pchain) { - pchain->next = &hose->pci_bus; - pchain = pchain->next; - } else { - pchain = &pci_root; - memcpy(pchain, &hose->pci_bus, sizeof(pci_root)); - } -} - -void mcpcia_fixup(void) -{ - struct linux_hose_info *hose; - - /* turn on Config space access finally! */ - pci_probe_enabled = 1; - - /* for each hose, probe and setup the devices on the hose */ - for (hose = mcpcia_root; hose; hose = hose->next) - mcpcia_probe(hose); -} -#endif /* CONFIG_ALPHA_MCPCIA */ diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c --- v2.1.115/linux/arch/alpha/kernel/osf_sys.c Thu Aug 6 14:06:28 1998 +++ linux/arch/alpha/kernel/osf_sys.c Sun Aug 9 12:25:11 1998 @@ -47,7 +47,7 @@ extern kdev_t get_unnamed_dev(void); extern void put_unnamed_dev(kdev_t); -extern asmlinkage int sys_umount(char *); +extern asmlinkage int sys_umount(char *, int); extern asmlinkage int sys_swapon(const char *specialfile, int swap_flags); extern asmlinkage unsigned long sys_brk(unsigned long); @@ -542,7 +542,7 @@ int ret; lock_kernel(); - ret = sys_umount(path); + ret = sys_umount(path,flag); unlock_kernel(); return ret; } diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c --- v2.1.115/linux/arch/alpha/kernel/process.c Thu Aug 6 14:06:28 1998 +++ linux/arch/alpha/kernel/process.c Sun Aug 9 12:09:05 1998 @@ -28,6 +28,7 @@ #include #include #include +#include #ifdef CONFIG_RTC #include @@ -41,6 +42,9 @@ #include #include +#include "proto.h" +#include "bios32.h" + /* * Initial task structure. Make this a per-architecture thing, * because different architectures tend to have different @@ -62,20 +66,20 @@ /* * No need to acquire the kernel lock, we're entirely local.. */ -asmlinkage int sys_sethae(unsigned long hae, unsigned long a1, unsigned long a2, - unsigned long a3, unsigned long a4, unsigned long a5, - struct pt_regs regs) +asmlinkage int +sys_sethae(unsigned long hae, unsigned long a1, unsigned long a2, + unsigned long a3, unsigned long a4, unsigned long a5, + struct pt_regs regs) { -#if !defined(CONFIG_ALPHA_TSUNAMI) (®s)->hae = hae; -#endif return 0; } #ifdef __SMP__ /* This is being executed in task 0 'user space'. */ #define resched_needed() 1 -int cpu_idle(void *unused) +int +cpu_idle(void *unused) { extern volatile int smp_commenced; @@ -90,7 +94,8 @@ } } -asmlinkage int sys_idle(void) +asmlinkage int +sys_idle(void) { if(current->pid != 0) return -EPERM; @@ -101,7 +106,8 @@ #else /* __SMP__ */ -asmlinkage int sys_idle(void) +asmlinkage int +sys_idle(void) { int ret = -EPERM; @@ -122,90 +128,101 @@ } #endif /* __SMP__ */ -#if defined(CONFIG_ALPHA_SRM_SETUP) -extern void reset_for_srm(void); -extern unsigned long srm_hae; -#endif - -static void finish_shutdown(void) +void +generic_kill_arch (int mode, char *restart_cmd) { -#ifdef CONFIG_RTC /* reset rtc to defaults */ - unsigned char control; - unsigned long flags; - - /* i'm not sure if i really need to disable interrupts here */ - save_and_cli(flags); - - /* reset periodic interrupt frequency */ - CMOS_WRITE(0x26, RTC_FREQ_SELECT); - - /* turn on periodic interrupts */ - control = CMOS_READ(RTC_CONTROL); - control |= RTC_PIE; - CMOS_WRITE(control, RTC_CONTROL); - CMOS_READ(RTC_INTR_FLAGS); - restore_flags(flags); + /* The following currently only has any effect on SRM. We should + fix MILO to understand it. Should be pretty easy. Also we can + support RESTART2 via the ipc_buffer machinations pictured below, + which SRM ignores. */ + + if (alpha_using_srm) { + struct percpu_struct *cpup; + unsigned long flags; + + cpup = (struct percpu_struct *) + ((unsigned long)hwrpb + hwrpb->processor_offset); + + flags = cpup->flags; + + /* Clear reason to "default"; clear "bootstrap in progress". */ + flags &= ~0x00ff0001UL; + + if (mode == LINUX_REBOOT_CMD_RESTART) { + if (!restart_cmd) { + flags |= 0x00020000UL; /* "cold bootstrap" */ + cpup->ipc_buffer[0] = 0; + } else { + flags |= 0x00030000UL; /* "warm bootstrap" */ + strncpy(cpup->ipc_buffer, restart_cmd, + sizeof(cpup->ipc_buffer)); + } + } + else { + flags |= 0x00040000UL; /* "remain halted" */ + } + + cpup->flags = flags; + mb(); + + if (alpha_use_srm_setup) { + reset_for_srm(); + set_hae(srm_hae); + } + +#ifdef CONFIG_DUMMY_CONSOLE + /* This has the effect of reseting the VGA video origin. */ + take_over_console(&dummy_con, 0, MAX_NR_CONSOLES-1, 1); #endif -#if defined(CONFIG_ALPHA_SRM) && defined(CONFIG_ALPHA_ALCOR) - /* who said DEC engineer's have no sense of humor? ;-)) */ - *(int *) GRU_RESET = 0x0000dead; - mb(); + } + +#ifdef CONFIG_RTC + /* Reset rtc to defaults. */ + { + unsigned char control; + unsigned long flags; + + /* I'm not sure if i really need to disable interrupts here. */ + save_and_cli(flags); + + /* Reset periodic interrupt frequency. */ + CMOS_WRITE(0x26, RTC_FREQ_SELECT); + + /* Turn on periodic interrupts. */ + control = CMOS_READ(RTC_CONTROL); + control |= RTC_PIE; + CMOS_WRITE(control, RTC_CONTROL); + CMOS_READ(RTC_INTR_FLAGS); + + restore_flags(flags); + } #endif + + if (!alpha_using_srm && mode != LINUX_REBOOT_CMD_RESTART) { + /* Unfortunately, since MILO doesn't currently understand + the hwrpb bits above, we can't reliably halt the + processor and keep it halted. So just loop. */ + return; + } + halt(); } -void machine_restart(char * __unused) +void +machine_restart(char *restart_cmd) { -#if defined(CONFIG_ALPHA_SRM) - extern struct hwrpb_struct *hwrpb; - struct percpu_struct *cpup; - unsigned long flags; - - cpup = (struct percpu_struct *) - ((unsigned long)hwrpb + hwrpb->processor_offset); - flags = cpup->flags; - flags &= ~0x0000000000ff0001UL; /* clear reason to "default" */ - flags |= 0x0000000000020000UL; /* this is "cold bootstrap" */ -/* flags |= 0x0000000000030000UL; *//* this is "warm bootstrap" */ - cpup->flags = flags; - mb(); -#if defined(CONFIG_ALPHA_SRM_SETUP) - reset_for_srm(); - set_hae(srm_hae); -#endif -#endif /* SRM */ - - finish_shutdown(); + alpha_mv.kill_arch(LINUX_REBOOT_CMD_RESTART, restart_cmd); } -void machine_halt(void) +void +machine_halt(void) { -#if defined(CONFIG_ALPHA_SRM) - extern struct hwrpb_struct *hwrpb; - struct percpu_struct *cpup; - unsigned long flags; - - cpup = (struct percpu_struct *) - ((unsigned long)hwrpb + hwrpb->processor_offset); - flags = cpup->flags; - flags &= ~0x0000000000ff0001UL; /* clear reason to "default" */ - flags |= 0x0000000000040000UL; /* this is "remain halted" */ - cpup->flags = flags; - mb(); -#if defined(CONFIG_ALPHA_SRM_SETUP) - reset_for_srm(); - set_hae(srm_hae); -#endif - - finish_shutdown(); -#endif /* SRM */ + alpha_mv.kill_arch(LINUX_REBOOT_CMD_HALT, NULL); } void machine_power_off(void) { - /* None of the machines we support, at least, has switchable - power supplies. */ - machine_halt(); + alpha_mv.kill_arch(LINUX_REBOOT_CMD_POWER_OFF, NULL); } void show_regs(struct pt_regs * regs) diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/proto.h linux/arch/alpha/kernel/proto.h --- v2.1.115/linux/arch/alpha/kernel/proto.h Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/proto.h Sun Aug 9 12:09:05 1998 @@ -0,0 +1,131 @@ +/* Prototypes of functions used across modules here in this directory. */ + +#define vucp volatile unsigned char * +#define vusp volatile unsigned short * +#define vip volatile int * +#define vuip volatile unsigned int * +#define vulp volatile unsigned long * + +/* core_apecs.c */ +extern int apecs_pcibios_read_config_byte (u8, u8, u8, u8 *value); +extern int apecs_pcibios_read_config_word (u8, u8, u8, u16 *value); +extern int apecs_pcibios_read_config_dword (u8, u8, u8, u32 *value); +extern int apecs_pcibios_write_config_byte (u8, u8, u8, u8 value); +extern int apecs_pcibios_write_config_word (u8, u8, u8, u16 value); +extern int apecs_pcibios_write_config_dword (u8, u8, u8, u32 value); +extern void apecs_init_arch(unsigned long *, unsigned long *); + +extern volatile unsigned int apecs_mcheck_expected; +extern volatile unsigned int apecs_mcheck_taken; +extern int apecs_pci_clr_err(void); +extern void apecs_machine_check(u64, u64, struct pt_regs *); + +/* core_cia.c */ +extern int cia_pcibios_read_config_byte (u8, u8, u8, u8 *value); +extern int cia_pcibios_read_config_word (u8, u8, u8, u16 *value); +extern int cia_pcibios_read_config_dword (u8, u8, u8, u32 *value); +extern int cia_pcibios_write_config_byte (u8, u8, u8, u8 value); +extern int cia_pcibios_write_config_word (u8, u8, u8, u16 value); +extern int cia_pcibios_write_config_dword (u8, u8, u8, u32 value); +extern void cia_init_arch(unsigned long *, unsigned long *); +extern void cia_machine_check(u64, u64, struct pt_regs *); + +/* core_lca.c */ +extern int lca_pcibios_read_config_byte (u8, u8, u8, u8 *value); +extern int lca_pcibios_read_config_word (u8, u8, u8, u16 *value); +extern int lca_pcibios_read_config_dword (u8, u8, u8, u32 *value); +extern int lca_pcibios_write_config_byte (u8, u8, u8, u8 value); +extern int lca_pcibios_write_config_word (u8, u8, u8, u16 value); +extern int lca_pcibios_write_config_dword (u8, u8, u8, u32 value); +extern void lca_init_arch(unsigned long *, unsigned long *); +extern void lca_machine_check(u64, u64, struct pt_regs *); + +/* core_mcpcia.c */ +extern int mcpcia_pcibios_read_config_byte (u8, u8, u8, u8 *value); +extern int mcpcia_pcibios_read_config_word (u8, u8, u8, u16 *value); +extern int mcpcia_pcibios_read_config_dword (u8, u8, u8, u32 *value); +extern int mcpcia_pcibios_write_config_byte (u8, u8, u8, u8 value); +extern int mcpcia_pcibios_write_config_word (u8, u8, u8, u16 value); +extern int mcpcia_pcibios_write_config_dword (u8, u8, u8, u32 value); +extern void mcpcia_init_arch(unsigned long *, unsigned long *); +extern void mcpcia_machine_check(u64, u64, struct pt_regs *); +extern void mcpcia_pci_fixup(void); + +/* core_pyxis.c */ +extern int pyxis_pcibios_read_config_byte (u8, u8, u8, u8 *value); +extern int pyxis_pcibios_read_config_word (u8, u8, u8, u16 *value); +extern int pyxis_pcibios_read_config_dword (u8, u8, u8, u32 *value); +extern int pyxis_pcibios_write_config_byte (u8, u8, u8, u8 value); +extern int pyxis_pcibios_write_config_word (u8, u8, u8, u16 value); +extern int pyxis_pcibios_write_config_dword (u8, u8, u8, u32 value); +extern void pyxis_enable_errors (void); +extern int pyxis_srm_window_setup (void); +extern void pyxis_native_window_setup(void); +extern void pyxis_finish_init_arch(void); +extern void pyxis_init_arch(unsigned long *, unsigned long *); +extern void pyxis_machine_check(u64, u64, struct pt_regs *); + +/* core_t2.c */ +extern int t2_pcibios_read_config_byte (u8, u8, u8, u8 *value); +extern int t2_pcibios_read_config_word (u8, u8, u8, u16 *value); +extern int t2_pcibios_read_config_dword (u8, u8, u8, u32 *value); +extern int t2_pcibios_write_config_byte (u8, u8, u8, u8 value); +extern int t2_pcibios_write_config_word (u8, u8, u8, u16 value); +extern int t2_pcibios_write_config_dword (u8, u8, u8, u32 value); +extern void t2_init_arch(unsigned long *, unsigned long *); +extern void t2_machine_check(u64, u64, struct pt_regs *); + +/* core_tsunami.c */ +extern int tsunami_pcibios_read_config_byte (u8, u8, u8, u8 *value); +extern int tsunami_pcibios_read_config_word (u8, u8, u8, u16 *value); +extern int tsunami_pcibios_read_config_dword (u8, u8, u8, u32 *value); +extern int tsunami_pcibios_write_config_byte (u8, u8, u8, u8 value); +extern int tsunami_pcibios_write_config_word (u8, u8, u8, u16 value); +extern int tsunami_pcibios_write_config_dword (u8, u8, u8, u32 value); +extern void tsunami_init_arch(unsigned long *, unsigned long *); +extern void tsunami_machine_check(u64, u64, struct pt_regs *); + +/* setup.c */ +extern void init_pit_rest(void); +extern void generic_init_pit (void); +extern unsigned long srm_hae; + +/* smp.c */ +extern void setup_smp(void); +extern char *smp_info(void); +extern void handle_ipi(struct pt_regs *); + +/* bios32.c */ +extern void reset_for_srm(void); + +/* time.c */ +extern void timer_interrupt(struct pt_regs * regs); + +/* smc37c93x.c */ +extern void SMC93x_Init(void); + +/* smc37c669.c */ +extern void SMC669_Init(void); + +/* es1888.c */ +extern void es1888_init(void); + +/* fpregs.c */ +extern void alpha_write_fp_reg (unsigned long reg, unsigned long val); +extern unsigned long alpha_read_fp_reg (unsigned long reg); + +/* head.S */ +extern void wrmces(unsigned long mces); +extern void cserve_ena(unsigned long); +extern void cserve_dis(unsigned long); + +/* entry.S */ +extern void entArith(void); +extern void entIF(void); +extern void entInt(void); +extern void entMM(void); +extern void entSys(void); +extern void entUna(void); + +/* process.c */ +void generic_kill_arch (int mode, char *reboot_cmd); diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/ptrace.c linux/arch/alpha/kernel/ptrace.c --- v2.1.115/linux/arch/alpha/kernel/ptrace.c Mon Aug 3 12:45:43 1998 +++ linux/arch/alpha/kernel/ptrace.c Sun Aug 9 12:09:05 1998 @@ -281,10 +281,8 @@ struct vm_area_struct * vma = find_extend_vma(tsk, addr); DBG(DBG_MEM_ALL, ("in read_long\n")); - if (!vma) { - printk("Unable to find vma for addr 0x%lx\n",addr); + if (!vma) return -EIO; - } if ((addr & ~PAGE_MASK) > (PAGE_SIZE - sizeof(long))) { struct vm_area_struct * vma_high = vma; unsigned long low, align; diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/pyxis.c linux/arch/alpha/kernel/pyxis.c --- v2.1.115/linux/arch/alpha/kernel/pyxis.c Wed Jun 24 22:54:03 1998 +++ linux/arch/alpha/kernel/pyxis.c Wed Dec 31 16:00:00 1969 @@ -1,663 +0,0 @@ -/* - * Code common to all PYXIS chips. - * - * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com). - * - */ -#include /* CONFIG_ALPHA_RUFFIAN. */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* NOTE: Herein are back-to-back mb instructions. They are magic. - One plausible explanation is that the I/O controller does not properly - handle the system transaction. Another involves timing. Ho hum. */ - -extern struct hwrpb_struct *hwrpb; -extern asmlinkage void wrmces(unsigned long mces); - -/* - * BIOS32-style PCI interface: - */ - -#ifdef DEBUG -# define DBG(args) printk args -#else -# define DBG(args) -#endif - -#define DEBUG_MCHECK -#ifdef DEBUG_MCHECK -# define DBG_MCK(args) printk args -#define DEBUG_MCHECK_DUMP -#else -# define DBG_MCK(args) -#endif - -#define vulp volatile unsigned long * -#define vuip volatile unsigned int * - -static volatile unsigned int PYXIS_mcheck_expected = 0; -static volatile unsigned int PYXIS_mcheck_taken = 0; -static unsigned int PYXIS_jd; - -#ifdef CONFIG_ALPHA_SRM_SETUP -unsigned int PYXIS_DMA_WIN_BASE = PYXIS_DMA_WIN_BASE_DEFAULT; -unsigned int PYXIS_DMA_WIN_SIZE = PYXIS_DMA_WIN_SIZE_DEFAULT; -unsigned long pyxis_sm_base_r1, pyxis_sm_base_r2, pyxis_sm_base_r3; -#endif /* SRM_SETUP */ - -/* - * Given a bus, device, and function number, compute resulting - * configuration space address and setup the PYXIS_HAXR2 register - * accordingly. It is therefore not safe to have concurrent - * invocations to configuration space access routines, but there - * really shouldn't be any need for this. - * - * Type 0: - * - * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 - * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * 31:11 Device select bit. - * 10:8 Function number - * 7:2 Register number - * - * Type 1: - * - * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 - * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * 31:24 reserved - * 23:16 bus number (8 bits = 128 possible buses) - * 15:11 Device number (5 bits) - * 10:8 function number - * 7:2 register number - * - * Notes: - * The function number selects which function of a multi-function device - * (e.g., SCSI and Ethernet). - * - * The register selects a DWORD (32 bit) register offset. Hence it - * doesn't get shifted by 2 bits as we want to "drop" the bottom two - * bits. - */ -static int mk_conf_addr(unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned long *pci_addr, - unsigned char *type1) -{ - unsigned long addr; - - DBG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x," - " pci_addr=0x%p, type1=0x%p)\n", - bus, device_fn, where, pci_addr, type1)); - - if (bus == 0) { - int device; - - device = device_fn >> 3; - /* type 0 configuration cycle: */ -#if NOT_NOW - if (device > 20) { - DBG(("mk_conf_addr: device (%d) > 20, returning -1\n", - device)); - return -1; - } -#endif - *type1 = 0; - addr = (device_fn << 8) | (where); - } else { - /* type 1 configuration cycle: */ - *type1 = 1; - addr = (bus << 16) | (device_fn << 8) | (where); - } - *pci_addr = addr; - DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr)); - return 0; -} - - -static unsigned int conf_read(unsigned long addr, unsigned char type1) -{ - unsigned long flags; - unsigned int stat0, value, temp; - unsigned int pyxis_cfg = 0; /* to keep gcc quiet */ - - save_and_cli(flags); /* avoid getting hit by machine check */ - - DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1)); - - /* reset status register to avoid losing errors: */ - stat0 = *(vuip)PYXIS_ERR; - *(vuip)PYXIS_ERR = stat0; mb(); - temp = *(vuip)PYXIS_ERR; /* re-read to force write */ - DBG(("conf_read: PYXIS ERR was 0x%x\n", stat0)); - /* if Type1 access, must set PYXIS CFG */ - if (type1) { - pyxis_cfg = *(vuip)PYXIS_CFG; - *(vuip)PYXIS_CFG = pyxis_cfg | 1; mb(); - temp = *(vuip)PYXIS_CFG; /* re-read to force write */ - DBG(("conf_read: TYPE1 access\n")); - } - - mb(); - draina(); - PYXIS_mcheck_expected = 1; - PYXIS_mcheck_taken = 0; - mb(); - /* access configuration space: */ - value = *(vuip)addr; - mb(); - mb(); /* magic */ - if (PYXIS_mcheck_taken) { - PYXIS_mcheck_taken = 0; - value = 0xffffffffU; - mb(); - } - PYXIS_mcheck_expected = 0; - mb(); - - /* if Type1 access, must reset IOC CFG so normal IO space ops work */ - if (type1) { - *(vuip)PYXIS_CFG = pyxis_cfg & ~1; mb(); - temp = *(vuip)PYXIS_CFG; /* re-read to force write */ - } - - DBG(("conf_read(): finished\n")); - - restore_flags(flags); - return value; -} - - -static void conf_write(unsigned long addr, unsigned int value, - unsigned char type1) -{ - unsigned long flags; - unsigned int stat0, temp; - unsigned int pyxis_cfg = 0; /* to keep gcc quiet */ - - save_and_cli(flags); /* avoid getting hit by machine check */ - - /* reset status register to avoid losing errors: */ - stat0 = *(vuip)PYXIS_ERR; - *(vuip)PYXIS_ERR = stat0; mb(); - temp = *(vuip)PYXIS_ERR; /* re-read to force write */ - DBG(("conf_write: PYXIS ERR was 0x%x\n", stat0)); - /* if Type1 access, must set PYXIS CFG */ - if (type1) { - pyxis_cfg = *(vuip)PYXIS_CFG; - *(vuip)PYXIS_CFG = pyxis_cfg | 1; mb(); - temp = *(vuip)PYXIS_CFG; /* re-read to force write */ - DBG(("conf_read: TYPE1 access\n")); - } - - draina(); - PYXIS_mcheck_expected = 1; - mb(); - /* access configuration space: */ - *(vuip)addr = value; - mb(); - mb(); /* magic */ - temp = *(vuip)PYXIS_ERR; /* do a PYXIS read to force the write */ - PYXIS_mcheck_expected = 0; - mb(); - - /* if Type1 access, must reset IOC CFG so normal IO space ops work */ - if (type1) { - *(vuip)PYXIS_CFG = pyxis_cfg & ~1; mb(); - temp = *(vuip)PYXIS_CFG; /* re-read to force write */ - } - - DBG(("conf_write(): finished\n")); - restore_flags(flags); -} - - -int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned char *value) -{ - unsigned long addr = PYXIS_CONF; - unsigned long pci_addr; - unsigned char type1; - - *value = 0xff; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - - addr |= (pci_addr << 5) + 0x00; - - *value = conf_read(addr, type1) >> ((where & 3) * 8); - - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_read_config_word (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short *value) -{ - unsigned long addr = PYXIS_CONF; - unsigned long pci_addr; - unsigned char type1; - - *value = 0xffff; - - if (where & 0x1) { - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) { - return PCIBIOS_SUCCESSFUL; - } - - addr |= (pci_addr << 5) + 0x08; - - *value = conf_read(addr, type1) >> ((where & 3) * 8); - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int *value) -{ - unsigned long addr = PYXIS_CONF; - unsigned long pci_addr; - unsigned char type1; - - *value = 0xffffffff; - if (where & 0x3) { - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x18; - *value = conf_read(addr, type1); - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned char value) -{ - unsigned long addr = PYXIS_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x00; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_write_config_word (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short value) -{ - unsigned long addr = PYXIS_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x08; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int value) -{ - unsigned long addr = PYXIS_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x18; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; -} - - -unsigned long pyxis_init(unsigned long mem_start, unsigned long mem_end) -{ - unsigned int pyxis_err ; - -#if 0 -printk("pyxis_init: PYXIS_ERR_MASK 0x%x\n", *(vuip)PYXIS_ERR_MASK); -printk("pyxis_init: PYXIS_ERR 0x%x\n", *(vuip)PYXIS_ERR); - -printk("pyxis_init: PYXIS_INT_REQ 0x%lx\n", *(vulp)PYXIS_INT_REQ); -printk("pyxis_init: PYXIS_INT_MASK 0x%lx\n", *(vulp)PYXIS_INT_MASK); -printk("pyxis_init: PYXIS_INT_ROUTE 0x%lx\n", *(vulp)PYXIS_INT_ROUTE); -printk("pyxis_init: PYXIS_INT_HILO 0x%lx\n", *(vulp)PYXIS_INT_HILO); -printk("pyxis_init: PYXIS_INT_CNFG 0x%x\n", *(vuip)PYXIS_INT_CNFG); -printk("pyxis_init: PYXIS_RT_COUNT 0x%lx\n", *(vulp)PYXIS_RT_COUNT); -#endif - - /* - * Set up error reporting. Make sure CPU_PE is OFF in the mask. - */ - pyxis_err = *(vuip)PYXIS_ERR_MASK; - pyxis_err &= ~4; - *(vuip)PYXIS_ERR_MASK = pyxis_err; mb(); - pyxis_err = *(vuip)PYXIS_ERR_MASK; /* re-read to force write */ - - pyxis_err = *(vuip)PYXIS_ERR ; - pyxis_err |= 0x180; /* master/target abort */ - *(vuip)PYXIS_ERR = pyxis_err; mb(); - pyxis_err = *(vuip)PYXIS_ERR; /* re-read to force write */ - -#ifdef CONFIG_ALPHA_SRM_SETUP - /* check window 0 for enabled and mapped to 0 */ - if (((*(vuip)PYXIS_W0_BASE & 3) == 1) && - (*(vuip)PYXIS_T0_BASE == 0) && - ((*(vuip)PYXIS_W0_MASK & 0xfff00000U) > 0x0ff00000U)) - { - PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W0_BASE & 0xfff00000U; - PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W0_MASK & 0xfff00000U; - PYXIS_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("pyxis_init: using Window 0 settings\n"); - printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)PYXIS_W0_BASE, - *(vuip)PYXIS_W0_MASK, - *(vuip)PYXIS_T0_BASE); -#endif - } - else /* check window 1 for enabled and mapped to 0 */ - if (((*(vuip)PYXIS_W1_BASE & 3) == 1) && - (*(vuip)PYXIS_T1_BASE == 0) && - ((*(vuip)PYXIS_W1_MASK & 0xfff00000U) > 0x0ff00000U)) -{ - PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W1_BASE & 0xfff00000U; - PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W1_MASK & 0xfff00000U; - PYXIS_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("pyxis_init: using Window 1 settings\n"); - printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)PYXIS_W1_BASE, - *(vuip)PYXIS_W1_MASK, - *(vuip)PYXIS_T1_BASE); -#endif - } - else /* check window 2 for enabled and mapped to 0 */ - if (((*(vuip)PYXIS_W2_BASE & 3) == 1) && - (*(vuip)PYXIS_T2_BASE == 0) && - ((*(vuip)PYXIS_W2_MASK & 0xfff00000U) > 0x0ff00000U)) - { - PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W2_BASE & 0xfff00000U; - PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W2_MASK & 0xfff00000U; - PYXIS_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("pyxis_init: using Window 2 settings\n"); - printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)PYXIS_W2_BASE, - *(vuip)PYXIS_W2_MASK, - *(vuip)PYXIS_T2_BASE); -#endif - } - else /* check window 3 for enabled and mapped to 0 */ - if (((*(vuip)PYXIS_W3_BASE & 3) == 1) && - (*(vuip)PYXIS_T3_BASE == 0) && - ((*(vuip)PYXIS_W3_MASK & 0xfff00000U) > 0x0ff00000U)) - { - PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W3_BASE & 0xfff00000U; - PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W3_MASK & 0xfff00000U; - PYXIS_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("pyxis_init: using Window 3 settings\n"); - printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vuip)PYXIS_W3_BASE, - *(vuip)PYXIS_W3_MASK, - *(vuip)PYXIS_T3_BASE); -#endif - } - else /* we must use our defaults which were pre-initialized... */ -#endif /* SRM_SETUP */ - { -#if defined(CONFIG_ALPHA_RUFFIAN) -#if 1 - printk("pyxis_init: skipping window register rewrites... " - " trust DeskStation firmware!\n"); -#endif -#else /* RUFFIAN */ - /* - * Set up the PCI->physical memory translation windows. - * For now, windows 1,2 and 3 are disabled. In the future, we may - * want to use them to do scatter/gather DMA. Window 0 - * goes at 1 GB and is 1 GB large. - */ - - *(vuip)PYXIS_W0_BASE = 1U | (PYXIS_DMA_WIN_BASE & 0xfff00000U); - *(vuip)PYXIS_W0_MASK = (PYXIS_DMA_WIN_SIZE - 1) & 0xfff00000U; - *(vuip)PYXIS_T0_BASE = 0; - - *(vuip)PYXIS_W1_BASE = 0x0 ; - *(vuip)PYXIS_W2_BASE = 0x0 ; - *(vuip)PYXIS_W3_BASE = 0x0 ; - mb(); -#endif /* RUFFIAN */ - } - - /* - * check ASN in HWRPB for validity, report if bad - */ - if (hwrpb->max_asn != MAX_ASN) { - printk("PYXIS_init: max ASN from HWRPB is bad (0x%lx)\n", - hwrpb->max_asn); - hwrpb->max_asn = MAX_ASN; - } - - /* - * Next, clear the PYXIS_CFG register, which gets used - * for PCI Config Space accesses. That is the way - * we want to use it, and we do not want to depend on - * what ARC or SRM might have left behind... - */ - { - unsigned int pyxis_cfg, temp; - pyxis_cfg = *(vuip)PYXIS_CFG; mb(); - if (pyxis_cfg != 0) { -#if 1 - printk("PYXIS_init: CFG was 0x%x\n", pyxis_cfg); -#endif - *(vuip)PYXIS_CFG = 0; mb(); - temp = *(vuip)PYXIS_CFG; /* re-read to force write */ - } - } - - { - unsigned int pyxis_hae_mem = *(vuip)PYXIS_HAE_MEM; - unsigned int pyxis_hae_io = *(vuip)PYXIS_HAE_IO; -#if 0 - printk("PYXIS_init: HAE_MEM was 0x%x\n", pyxis_hae_mem); - printk("PYXIS_init: HAE_IO was 0x%x\n", pyxis_hae_io); -#endif -#ifdef CONFIG_ALPHA_SRM_SETUP - /* - * sigh... For the SRM setup, unless we know apriori what the HAE - * contents will be, we need to setup the arbitrary region bases - * so we can test against the range of addresses and tailor the - * region chosen for the SPARSE memory access. - * - * see include/asm-alpha/pyxis.h for the SPARSE mem read/write - */ - pyxis_sm_base_r1 = (pyxis_hae_mem ) & 0xe0000000UL;/* region 1 */ - pyxis_sm_base_r2 = (pyxis_hae_mem << 16) & 0xf8000000UL;/* region 2 */ - pyxis_sm_base_r3 = (pyxis_hae_mem << 24) & 0xfc000000UL;/* region 3 */ - - /* - Set the HAE cache, so that setup_arch() code - will use the SRM setting always. Our readb/writeb - code in pyxis.h expects never to have to change - the contents of the HAE. - */ - hae.cache = pyxis_hae_mem; -#else /* SRM_SETUP */ - *(vuip)PYXIS_HAE_MEM = 0U; mb(); - pyxis_hae_mem = *(vuip)PYXIS_HAE_MEM; /* re-read to force write */ - *(vuip)PYXIS_HAE_IO = 0; mb(); - pyxis_hae_io = *(vuip)PYXIS_HAE_IO; /* re-read to force write */ -#endif /* SRM_SETUP */ - } - - /* - * Finally, check that the PYXIS_CTRL1 has IOA_BEN set for - * enabling byte/word PCI bus space(s) access. - */ - { - unsigned int ctrl1; - ctrl1 = *(vuip) PYXIS_CTRL1; - if (!(ctrl1 & 1)) { -#if 1 - printk("PYXIS_init: enabling byte/word PCI space\n"); -#endif - *(vuip) PYXIS_CTRL1 = ctrl1 | 1; mb(); - ctrl1 = *(vuip)PYXIS_CTRL1; /* re-read to force write */ - } - } - - return mem_start; -} - -int pyxis_pci_clr_err(void) -{ - PYXIS_jd = *(vuip)PYXIS_ERR; - DBG(("PYXIS_pci_clr_err: PYXIS ERR after read 0x%x\n", PYXIS_jd)); - *(vuip)PYXIS_ERR = 0x0180; mb(); - PYXIS_jd = *(vuip)PYXIS_ERR; /* re-read to force write */ - return 0; -} - -void pyxis_machine_check(unsigned long vector, unsigned long la_ptr, - struct pt_regs * regs) -{ - struct el_common *mchk_header; - struct el_PYXIS_sysdata_mcheck *mchk_sysdata; - - mchk_header = (struct el_common *)la_ptr; - - mchk_sysdata = (struct el_PYXIS_sysdata_mcheck *) - (la_ptr + mchk_header->sys_offset); - -#if 0 - DBG_MCK(("pyxis_machine_check: vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr)); - DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", - regs->pc, mchk_header->size, mchk_header->proc_offset, - mchk_header->sys_offset)); - DBG_MCK(("pyxis_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n", - PYXIS_mcheck_expected, mchk_sysdata->epic_dcsr, - mchk_sysdata->epic_pear)); -#endif -#ifdef DEBUG_MCHECK_DUMP - { - unsigned long *ptr; - int i; - - ptr = (unsigned long *)la_ptr; - for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { - printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]); - } - } -#endif /* DEBUG_MCHECK_DUMP */ - - /* - * Check if machine check is due to a badaddr() and if so, - * ignore the machine check. - */ - mb(); - mb(); /* magic */ - if (PYXIS_mcheck_expected) { - DBG(("PYXIS machine check expected\n")); - PYXIS_mcheck_expected = 0; - PYXIS_mcheck_taken = 1; - mb(); - mb(); /* magic */ - draina(); - pyxis_pci_clr_err(); - wrmces(0x7); - mb(); - } -#if 1 - else { - printk("PYXIS machine check NOT expected\n") ; - DBG_MCK(("pyxis_machine_check: vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr)); - DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x" - " sysoffset 0x%x\n", - regs->pc, mchk_header->size, mchk_header->proc_offset, - mchk_header->sys_offset)); - PYXIS_mcheck_expected = 0; - PYXIS_mcheck_taken = 1; - mb(); - mb(); /* magic */ - draina(); - pyxis_pci_clr_err(); - wrmces(0x7); - mb(); - } -#endif -} - -#if defined(CONFIG_ALPHA_RUFFIAN) -/* Note: This is only used by MILO, AFAIK... */ -/* - * The DeskStation Ruffian motherboard firmware does not place - * the memory size in the PALimpure area. Therefore, we use - * the Bank Configuration Registers in PYXIS to obtain the size. - */ -unsigned long pyxis_get_bank_size(unsigned long offset) -{ - unsigned long bank_addr, bank, ret = 0; - - /* Valid offsets are: 0x800, 0x840 and 0x880 - since Ruffian only uses three banks. */ - bank_addr = (unsigned long)PYXIS_MCR + offset; - bank = *(vulp)bank_addr; - - /* Check BANK_ENABLE */ - if (bank & 0x01) { - static unsigned long size[] = { - 0x40000000UL, /* 0x00, 1G */ - 0x20000000UL, /* 0x02, 512M */ - 0x10000000UL, /* 0x04, 256M */ - 0x08000000UL, /* 0x06, 128M */ - 0x04000000UL, /* 0x08, 64M */ - 0x02000000UL, /* 0x0a, 32M */ - 0x01000000UL, /* 0x0c, 16M */ - 0x00800000UL, /* 0x0e, 8M */ - 0x80000000UL, /* 0x10, 2G */ - }; - - bank = (bank & 0x1e) >> 1; - if (bank < sizeof(size)/sizeof(*size)) - ret = size[bank]; - } - - return ret; -} -#endif /* CONFIG_ALPHA_RUFFIAN */ diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c --- v2.1.115/linux/arch/alpha/kernel/setup.c Thu Aug 6 14:06:28 1998 +++ linux/arch/alpha/kernel/setup.c Sun Aug 9 12:10:58 1998 @@ -5,10 +5,9 @@ */ /* - * bootup setup stuff.. + * Bootup setup stuff. */ -#include #include #include #include @@ -24,6 +23,9 @@ #include #include #include +#include +#include +#include #ifdef CONFIG_RTC #include @@ -36,8 +38,8 @@ #include #include -extern void setup_smp(void); -extern char *smp_info(void); + +#include "proto.h" #if 1 # define DBG_SRM(args) printk args @@ -45,19 +47,23 @@ # define DBG_SRM(args) #endif -struct hae hae = { - 0, - (unsigned long*) HAE_ADDRESS -}; - -#ifdef CONFIG_ALPHA_SRM_SETUP +struct hwrpb_struct *hwrpb; unsigned long srm_hae; -#endif -struct hwrpb_struct *hwrpb; +#ifdef CONFIG_ALPHA_GENERIC +struct alpha_machine_vector alpha_mv; +int alpha_using_srm, alpha_use_srm_setup; +#endif unsigned char aux_device_present = 0xaa; +#define N(a) (sizeof(a)/sizeof(a[0])) + +static unsigned long find_end_memory(void); +static struct alpha_machine_vector *get_sysvec(long, long, long); +static struct alpha_machine_vector *get_sysvec_byname(const char *); +static void get_sysnames(long, long, char **, char **); + /* * This is setup by the secondary bootstrap loader. Because * the zero page is zeroed out as soon as the vm system is @@ -68,161 +74,241 @@ #define COMMAND_LINE ((char*)(PARAM + 0x0000)) #define COMMAND_LINE_SIZE 256 -static char command_line[COMMAND_LINE_SIZE] = { 0, }; - char saved_command_line[COMMAND_LINE_SIZE]; +static char command_line[COMMAND_LINE_SIZE]; +char saved_command_line[COMMAND_LINE_SIZE]; + /* * The format of "screen_info" is strange, and due to early * i386-setup code. This is just enough to make the console * code think we're on a VGA color display. */ + struct screen_info screen_info = { -#if defined(CONFIG_ALPHA_BOOK1) - /* the AlphaBook1 has LCD video fixed at 800x600, 37 rows and 100 cols */ - 0, 37, /* orig-x, orig-y */ - { 0, 0 }, /* unused */ - 0, /* orig-video-page */ - 0, /* orig-video-mode */ - 100, /* orig-video-cols */ - 0,0,0, /* ega_ax, ega_bx, ega_cx */ - 37, /* orig-video-lines */ - 1, /* orig-video-isVGA */ - 16 /* orig-video-points */ -#else - 0, 25, /* orig-x, orig-y */ - 0, /* unused */ - 0, /* orig-video-page */ - 0, /* orig-video-mode */ - 80, /* orig-video-cols */ - 0,0,0, /* ega_ax, ega_bx, ega_cx */ - 25, /* orig-video-lines */ - 1, /* orig-video-isVGA */ - 16 /* orig-video-points */ -#endif + orig_x: 0, + orig_y: 25, + orig_video_cols: 80, + orig_video_lines: 25, + orig_video_isVGA: 1, + orig_video_points: 16 }; + /* * Initialize Programmable Interval Timers with standard values. Some * drivers depend on them being initialized (e.g., joystick driver). */ -static void init_pit (void) + +/* It is (normally) only counter 1 that presents config problems, so + provide this support function to do the rest of the job. */ + +void inline +init_pit_rest(void) { #if 0 - /* - * Leave refresh timer alone---nobody should depend on - * a particular value anyway. - */ - outb(0x54, 0x43); /* counter 1: refresh timer */ - outb(0x18, 0x41); -#endif - -#ifdef CONFIG_RTC /* setup interval timer if /dev/rtc is being used */ - outb(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */ - outb(LATCH & 0xff, 0x40); /* LSB */ - outb(LATCH >> 8, 0x40); /* MSB */ - request_region(0x40, 0x20, "timer"); /* reserve pit */ -#else /* RTC */ -#if !defined(CONFIG_ALPHA_RUFFIAN) - /* Ruffian depends on the system timer established in MILO!! */ - outb(0x36, 0x43); /* counter 0: system timer */ - outb(0x00, 0x40); - outb(0x00, 0x40); -#endif /* RUFFIAN */ - request_region(0x70, 0x10, "timer"); /* reserve rtc */ -#endif /* RTC */ - - outb(0xb6, 0x43); /* counter 2: speaker */ - outb(0x31, 0x42); - outb(0x13, 0x42); + /* Leave refresh timer alone---nobody should depend on a + particular value anyway. */ + outb(0x54, 0x43); /* counter 1: refresh timer */ + outb(0x18, 0x41); +#endif + + outb(0xb6, 0x43); /* counter 2: speaker */ + outb(0x31, 0x42); + outb(0x13, 0x42); + + if ((CMOS_READ(RTC_FREQ_SELECT) & 0x3f) != 0x26) { + printk("Setting RTC_FREQ to 1024 Hz\n"); + CMOS_WRITE(0x26, RTC_FREQ_SELECT); + } } -static unsigned long find_end_memory(void) +#ifdef CONFIG_RTC +static inline void +rtc_init_pit (void) { - int i; - unsigned long high = 0; - struct memclust_struct * cluster; - struct memdesc_struct * memdesc; + /* Setup interval timer if /dev/rtc is being used */ + outb(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */ + outb(LATCH & 0xff, 0x40); /* LSB */ + outb(LATCH >> 8, 0x40); /* MSB */ + request_region(0x40, 0x20, "timer"); /* reserve pit */ - memdesc = (struct memdesc_struct *) - (INIT_HWRPB->mddt_offset + (unsigned long) INIT_HWRPB); - cluster = memdesc->cluster; - for (i = memdesc->numclusters ; i > 0; i--, cluster++) { - unsigned long tmp; - tmp = (cluster->start_pfn + cluster->numpages) << PAGE_SHIFT; - if (tmp > high) - high = tmp; - } - /* round it up to an even number of pages.. */ - high = (high + PAGE_SIZE) & (PAGE_MASK*2); - return PAGE_OFFSET + high; + init_pit_rest(); } +#endif -void setup_arch(char **cmdline_p, - unsigned long * memory_start_p, unsigned long * memory_end_p) +void +generic_init_pit (void) { - extern int _end; + outb(0x36, 0x43); /* counter 0: system timer */ + outb(0x00, 0x40); + outb(0x00, 0x40); + request_region(RTC_PORT(0), 0x10, "timer"); /* reserve rtc */ - init_pit(); + init_pit_rest(); +} - if ((CMOS_READ(RTC_FREQ_SELECT) & 0x3f) != 0x26) { - printk("setup_arch: setting RTC_FREQ to 1024/sec\n"); - CMOS_WRITE(0x26, RTC_FREQ_SELECT); - } +/* This probably isn't Right, but it is what the old code did. */ +#if defined(CONFIG_RTC) +# define init_pit rtc_init_pit +#else +# define init_pit alpha_mv.init_pit +#endif + + +/* + * Declare all of the machine vectors. + */ + +extern struct alpha_machine_vector alcor_mv; +extern struct alpha_machine_vector alphabook1_mv; +extern struct alpha_machine_vector avanti_mv; +extern struct alpha_machine_vector cabriolet_mv; +extern struct alpha_machine_vector dp264_mv; +extern struct alpha_machine_vector eb164_mv; +extern struct alpha_machine_vector eb64p_mv; +extern struct alpha_machine_vector eb66_mv; +extern struct alpha_machine_vector eb66p_mv; +extern struct alpha_machine_vector jensen_mv; +extern struct alpha_machine_vector lx164_mv; +extern struct alpha_machine_vector miata_mv; +extern struct alpha_machine_vector mikasa_mv; +extern struct alpha_machine_vector mikasa_primo_mv; +extern struct alpha_machine_vector noname_mv; +extern struct alpha_machine_vector noritake_mv; +extern struct alpha_machine_vector noritake_primo_mv; +extern struct alpha_machine_vector p2k_mv; +extern struct alpha_machine_vector pc164_mv; +extern struct alpha_machine_vector rawhide_mv; +extern struct alpha_machine_vector ruffian_mv; +extern struct alpha_machine_vector sable_mv; +extern struct alpha_machine_vector sable_gamma_mv; +extern struct alpha_machine_vector sx164_mv; +extern struct alpha_machine_vector takara_mv; +extern struct alpha_machine_vector xl_mv; +extern struct alpha_machine_vector xlt_mv; + + +void __init +setup_arch(char **cmdline_p, unsigned long * memory_start_p, + unsigned long * memory_end_p) +{ + extern char _end[]; + + struct alpha_machine_vector *vec = NULL; + struct percpu_struct *cpu; + char *type_name, *var_name, *p; hwrpb = (struct hwrpb_struct*)(IDENT_ADDR + INIT_HWRPB->phys_addr); -#if !defined(CONFIG_ALPHA_TSUNAMI) -#ifdef CONFIG_ALPHA_SRM_SETUP - srm_hae = *hae.reg; /* save SRM setting for restoration */ - DBG_SRM(("setup_arch: old HAE base: 0x%016lx\n", srm_hae)); -#endif /* SRM_SETUP */ - set_hae(hae.cache); /* sync HAE register w/hae_cache */ -#endif /* !TSUNAMI */ - - wrmces(0x7); /* reset enable correctable error reports */ - - ROOT_DEV = to_kdev_t(0x0802); /* sda2 */ - command_line[COMMAND_LINE_SIZE - 1] = '\0'; - - /* Hack for Jensen... since we're restricted to 8 or 16 - * chars for boot flags depending on the boot mode, - * we need some shorthand. This should do for - * installation. Later we'll add other abbreviations - * as well... + /* + * Locate the command line. */ + + /* Hack for Jensen... since we're restricted to 8 or 16 chars for + boot flags depending on the boot mode, we need some shorthand. + This should do for installation. Later we'll add other + abbreviations as well... */ if (strcmp(COMMAND_LINE, "INSTALL") == 0) { strcpy(command_line, "root=/dev/fd0 load_ramdisk=1"); - strcpy(saved_command_line, command_line); } else { - strcpy(command_line, COMMAND_LINE); - strcpy(saved_command_line, COMMAND_LINE); + strncpy(command_line, COMMAND_LINE, sizeof command_line); + command_line[sizeof(command_line)-1] = 0; } - printk("Command line: %s\n", command_line); - + strcpy(saved_command_line, command_line); *cmdline_p = command_line; - *memory_start_p = (unsigned long) &_end; - *memory_end_p = find_end_memory(); -#if defined(CONFIG_ALPHA_LCA) - *memory_start_p = lca_init(*memory_start_p, *memory_end_p); -#elif defined(CONFIG_ALPHA_APECS) - *memory_start_p = apecs_init(*memory_start_p, *memory_end_p); -#elif defined(CONFIG_ALPHA_CIA) - *memory_start_p = cia_init(*memory_start_p, *memory_end_p); -#elif defined(CONFIG_ALPHA_PYXIS) - *memory_start_p = pyxis_init(*memory_start_p, *memory_end_p); -#elif defined(CONFIG_ALPHA_T2) - *memory_start_p = t2_init(*memory_start_p, *memory_end_p); -#elif defined(CONFIG_ALPHA_TSUNAMI) - *memory_start_p = tsunami_init(*memory_start_p, *memory_end_p); -#elif defined(CONFIG_ALPHA_MCPCIA) - *memory_start_p = mcpcia_init(*memory_start_p, *memory_end_p); + /* + * Process command-line arguments. + */ + + for (p = strtok(command_line, " \t"); p ; p = strtok(NULL, " \t")) { +#ifndef alpha_use_srm_setup + /* Allow a command-line option to respect the + SRM's configuration. */ + if (strncmp(p, "srm_setup=", 10) == 0) { + alpha_use_srm_setup = (p[10] != '0'); + continue; + } #endif -#ifdef __SMP__ - setup_smp(); + if (strncmp(p, "alpha_mv=", 9) == 0) { + vec = get_sysvec_byname(p+9); + continue; + } + } + + /* Replace the command line, not that we've killed it with strtok. */ + strcpy(command_line, saved_command_line); + + /* + * Indentify and reconfigure for the current system. + */ + + get_sysnames(hwrpb->sys_type, hwrpb->sys_variation, + &type_name, &var_name); + if (*var_name == '0') + var_name = ""; + + if (!vec) { + cpu = (struct percpu_struct*) + ((char*)hwrpb + hwrpb->processor_offset); + vec = get_sysvec(hwrpb->sys_type, hwrpb->sys_variation, + cpu->type); + } + +#ifdef CONFIG_ALPHA_GENERIC + if (!vec) { + panic("Unsupported system type: %s%s%s (%ld %ld)\n", + type_name, (*var_name ? " variation " : ""), var_name, + hwrpb->sys_type, hwrpb->sys_variation); + } + alpha_mv = *vec; + + /* Assume that we've booted from SRM if we havn't booted from MILO. + Detect the later by looking for "MILO" in the system serial nr. */ + alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0; +#else + /* Once we're sure we can reliably identify systems, we should + simply panic as we do above. */ + if (vec != &alpha_mv) { + printk("WARNING: Not configured for system type: %s%s%s " + "(%ld %ld)\nContinuing with trepidation...\n", + type_name, (*var_name ? " variation " : ""), var_name, + hwrpb->sys_type, hwrpb->sys_variation); + } #endif + /* + * Sync with the HAE + */ + + /* Save the SRM's current value for restoration. */ + srm_hae = *alpha_mv.hae_register; + __set_hae(alpha_mv.hae_cache); + + /* Reset enable correctable error reports. */ + wrmces(0x7); + + /* Find our memory. */ + *memory_end_p = find_end_memory(); + *memory_start_p = (unsigned long) _end; + + /* Initialize the machine. Usually has to do with setting up + DMA windows and the like. */ + if (alpha_mv.init_arch) + alpha_mv.init_arch(memory_start_p, memory_end_p); + + /* Initialize the timers. */ + init_pit(); + + /* Default root filesystem to sda2. */ + ROOT_DEV = to_kdev_t(0x0802); + + /* + * Give us a default console. TGA users will see nothing until + * chr_dev_init is called, rather late in the boot sequence. + */ + #ifdef CONFIG_VT #if defined(CONFIG_VGA_CONSOLE) conswitchp = &vga_con; @@ -230,81 +316,284 @@ conswitchp = &dummy_con; #endif #endif -} + /* Delayed so that we've initialized the machine first. */ + printk("Booting on %s%s%s using machine vector %s\n", + type_name, (*var_name ? " variation " : ""), + var_name, alpha_mv.vector_name); + printk("Command line: %s\n", command_line); -#define N(a) (sizeof(a)/sizeof(a[0])) + /* + * Check ASN in HWRPB for validity, report if bad. + * FIXME: how was this failing? Should we trust it instead, + * and copy the value into alpha_mv.max_asn? + */ + + if (hwrpb->max_asn != MAX_ASN) { + printk("Max ASN from HWRPB is bad (0x%lx)\n", hwrpb->max_asn); + } -/* A change was made to the HWRPB via an ECO and the following code tracks - * a part of the ECO. In HWRPB versions less than 5, the ECO was not - * implemented in the console firmware. If it's revision 5 or greater we can - * get the name of the platform as an ASCII string from the HWRPB. That's what - * this function does. It checks the revision level and if the string is in - * the HWRPB it returns the address of the string--a pointer to the name of the - * platform. - * - * Returns: - * - Pointer to a ASCII string if it's in the HWRPB - * - Pointer to a blank string if the data is not in the HWRPB. - */ -static char * -platform_string(void) + /* + * Identify the flock of penguins. + */ + +#ifdef __SMP__ + setup_smp(); +#endif +} + +static unsigned long __init +find_end_memory(void) { - struct dsr_struct *dsr; - static char unk_system_string[] = "N/A"; + int i; + unsigned long high = 0; + struct memclust_struct * cluster; + struct memdesc_struct * memdesc; - /* Go to the console for the string pointer. - * If the rpb_vers is not 5 or greater the rpb - * is old and does not have this data in it. - */ - if (hwrpb->revision < 5) - return (unk_system_string); - else { - /* The Dynamic System Recognition struct - * has the system platform name starting - * after the character count of the string. - */ - dsr = ((struct dsr_struct *) - ((char *)hwrpb + hwrpb->dsr_offset)); - return ((char *)dsr + (dsr->sysname_off + - sizeof(long))); - } + memdesc = (struct memdesc_struct *) + (INIT_HWRPB->mddt_offset + (unsigned long) INIT_HWRPB); + cluster = memdesc->cluster; + + for (i = memdesc->numclusters ; i > 0; i--, cluster++) { + unsigned long tmp; + tmp = (cluster->start_pfn + cluster->numpages) << PAGE_SHIFT; + if (tmp > high) + high = tmp; + } + + /* Round it up to an even number of pages. */ + high = (high + PAGE_SIZE) & (PAGE_MASK*2); + return PAGE_OFFSET + high; } -static void -get_sysnames(long type, long variation, - char **type_name, char **variation_name) + +static char sys_unknown[] = "Unknown"; +static char systype_names[][16] = { + "0", + "ADU", "Cobra", "Ruby", "Flamingo", "Mannequin", "Jensen", + "Pelican", "Morgan", "Sable", "Medulla", "Noname", + "Turbolaser", "Avanti", "Mustang", "Alcor", "Tradewind", + "Mikasa", "EB64", "EB66", "EB64+", "AlphaBook1", + "Rawhide", "K2", "Lynx", "XL", "EB164", "Noritake", + "Cortex", "29", "Miata", "XXM", "Takara", "Yukon", + "Tsunami", "Wildfire", "CUSCO" +}; + +static char unofficial_names[][8] = {"100", "Ruffian"}; + +static char eb164_names[][8] = {"EB164", "PC164", "LX164", "SX164"}; +static int eb164_indices[] = {0,0,0,1,1,1,1,1,2,2,2,2,3,3,3,3}; + +static char alcor_names[][16] = {"Alcor", "Maverick", "Bret"}; +static int alcor_indices[] = {0,0,0,1,1,1,0,0,0,0,0,0,2,2,2,2,2,2}; + +static char eb64p_names[][16] = {"EB64+", "Cabriolet", "AlphaPCI64"}; +static int eb64p_indices[] = {0,0,1,2}; + +static char eb66_names[][8] = {"EB66", "EB66+"}; +static int eb66_indices[] = {0,0,1}; + +static char rawhide_names[][16] = { + "Dodge", "Wrangler", "Durango", "Tincup", "DaVinci" +}; +static int rawhide_indices[] = {0,0,0,1,1,2,2,3,3,4,4}; + + +static struct alpha_machine_vector * __init +get_sysvec(long type, long variation, long cpu) { - static char *sys_unknown = "Unknown"; - static char *systype_names[] = { - "0", - "ADU", "Cobra", "Ruby", "Flamingo", "Mannequin", "Jensen", - "Pelican", "Morgan", "Sable", "Medulla", "Noname", - "Turbolaser", "Avanti", "Mustang", "Alcor", "Tradewind", - "Mikasa", "EB64", "EB66", "EB64+", "AlphaBook1", - "Rawhide", "K2", "Lynx", "XL", "EB164", "Noritake", - "Cortex", "29", "Miata", "XXM", "Takara", "Yukon", - "Tsunami", "Wildfire", "CUSCO" +#ifdef CONFIG_ALPHA_GENERIC + static struct alpha_machine_vector *systype_vecs[] __initlocaldata = + { + NULL, /* 0 */ + NULL, /* ADU */ + NULL, /* Cobra */ + NULL, /* Ruby */ + NULL, /* Flamingo */ + NULL, /* Mannequin */ + &jensen_mv, + NULL, /* Pelican */ + NULL, /* Morgan */ + NULL, /* Sable -- see below. */ + NULL, /* Medulla */ + &noname_mv, + NULL, /* Turbolaser */ + &avanti_mv, + NULL, /* Mustang */ + &alcor_mv, /* Alcor, Bret, Maverick. */ + NULL, /* Tradewind */ + NULL, /* Mikasa -- see below. */ + NULL, /* EB64 */ + NULL, /* EB66 -- see variation. */ + NULL, /* EB64+ -- see variation. */ + &alphabook1_mv, + &rawhide_mv, + NULL, /* K2 */ + NULL, /* Lynx */ + &xl_mv, + NULL, /* EB164 -- see variation. */ + NULL, /* Noritake -- see below. */ + NULL, /* Cortex */ + NULL, /* 29 */ + &miata_mv, + NULL, /* XXM */ + &takara_mv, + NULL, /* Yukon */ + &dp264_mv, + NULL, /* Wildfire */ + NULL, /* CUSCO */ }; - static char *unofficial_names[] = {"100", "Ruffian"}; + static struct alpha_machine_vector *unofficial_vecs[] __initlocaldata = + { + NULL, /* 100 */ + &ruffian_mv, + }; - static char * eb164_names[] = {"EB164", "PC164", "LX164", "SX164"}; - static int eb164_indices[] = {0,0,0,1,1,1,1,1,2,2,2,2,3,3,3,3}; + static struct alpha_machine_vector *alcor_vecs[] __initlocaldata = + { + &alcor_mv, &xlt_mv, &xlt_mv + }; - static char * alcor_names[] = {"Alcor", "Maverick", "Bret"}; - static int alcor_indices[] = {0,0,0,1,1,1,0,0,0,0,0,0,2,2,2,2,2,2}; + static struct alpha_machine_vector *eb164_vecs[] __initlocaldata = + { + &eb164_mv, &pc164_mv, &lx164_mv, &sx164_mv + }; - static char * eb64p_names[] = {"EB64+", "Cabriolet", "AlphaPCI64"}; - static int eb64p_indices[] = {0,0,1,2}; + static struct alpha_machine_vector *eb64p_vecs[] __initlocaldata = + { + &eb64p_mv, + &cabriolet_mv, + NULL /* AlphaPCI64 */ + }; - static char * eb66_names[] = {"EB66", "EB66+"}; - static int eb66_indices[] = {0,0,1}; + static struct alpha_machine_vector *eb66_vecs[] __initlocaldata = + { + &eb66_mv, + &eb66p_mv + }; + + /* ??? Do we need to distinguish between Rawhides? */ - static char * rawhide_names[] = {"Dodge", "Wrangler", "Durango", - "Tincup", "DaVinci"}; - static int rawhide_indices[] = {0,0,0,1,1,2,2,3,3,4,4}; + struct alpha_machine_vector *vec; + /* Restore real CABRIO and EB66+ family names, ie EB64+ and EB66 */ + if (type < 0) + type = -type; + + /* Search the system tables first... */ + vec = NULL; + if (type < N(systype_vecs)) { + vec = systype_vecs[type]; + } else if ((type > ST_UNOFFICIAL_BIAS) && + (type - ST_UNOFFICIAL_BIAS) < N(unofficial_vecs)) { + vec = unofficial_vecs[type - ST_UNOFFICIAL_BIAS]; + } + + /* If we've not found one, try for a variation. */ + + if (!vec) { + /* Member ID is a bit-field. */ + long member = (variation >> 10) & 0x3f; + + switch (type) { + case ST_DEC_ALCOR: + if (member < N(alcor_indices)) + vec = alcor_vecs[alcor_indices[member]]; + break; + case ST_DEC_EB164: + if (member < N(eb164_indices)) + vec = eb164_vecs[eb164_indices[member]]; + break; + case ST_DEC_EB64P: + if (member < N(eb64p_indices)) + vec = eb64p_vecs[eb64p_indices[member]]; + break; + case ST_DEC_EB66: + if (member < N(eb66_indices)) + vec = eb66_vecs[eb66_indices[member]]; + break; + case ST_DEC_1000: + if (cpu == EV5_CPU) + vec = &mikasa_primo_mv; + else + vec = &mikasa_mv; + break; + case ST_DEC_NORITAKE: + if (cpu == EV5_CPU) + vec = &noritake_primo_mv; + else + vec = &noritake_mv; + break; + case ST_DEC_2100_A500: + if (cpu == EV5_CPU) + vec = &sable_gamma_mv; + else + vec = &sable_mv; + break; + } + } + return vec; +#else + /* TODO: verify that the system is of the type for which we + were configured. For now, cop out and return success. */ + return &alpha_mv; +#endif /* GENERIC */ +} + +static struct alpha_machine_vector * __init +get_sysvec_byname(const char *name) +{ +#ifdef CONFIG_ALPHA_GENERIC + static struct alpha_machine_vector *all_vecs[] __initlocaldata = + { + &alcor_mv, + &alphabook1_mv, + &avanti_mv, + &cabriolet_mv, + &dp264_mv, + &eb164_mv, + &eb64p_mv, + &eb66_mv, + &eb66p_mv, + &jensen_mv, + &lx164_mv, + &miata_mv, + &mikasa_mv, + &mikasa_primo_mv, + &noname_mv, + &noritake_mv, + &noritake_primo_mv, + &p2k_mv, + &pc164_mv, + &rawhide_mv, + &ruffian_mv, + &sable_mv, + &sable_gamma_mv, + &sx164_mv, + &takara_mv, + &xl_mv, + &xlt_mv + }; + + int i, n = sizeof(all_vecs)/sizeof(*all_vecs); + for (i = 0; i < n; ++i) { + struct alpha_machine_vector *mv = all_vecs[i]; + if (strcasecmp(mv->vector_name, name) == 0) + return mv; + } + return NULL; +#else + if (strcasecmp(alpha_mv.vector_name, name) == 0) + return &alpha_mv; + return NULL; +#endif +} + +static void +get_sysnames(long type, long variation, + char **type_name, char **variation_name) +{ long member; /* Restore real CABRIO and EB66+ family names, ie EB64+ and EB66 */ @@ -353,9 +642,47 @@ break; case ST_DEC_RAWHIDE: if (member < N(rawhide_indices)) - *variation_name = rawhide_names[rawhide_indices[member]]; + *variation_name = rawhide_names[rawhide_indices[member]]; break; - } /* end family switch */ + } +} + +/* + * A change was made to the HWRPB via an ECO and the following code + * tracks a part of the ECO. In HWRPB versions less than 5, the ECO + * was not implemented in the console firmware. If it's revision 5 or + * greater we can get the name of the platform as an ASCII string from + * the HWRPB. That's what this function does. It checks the revision + * level and if the string is in the HWRPB it returns the address of + * the string--a pointer to the name of the platform. + * + * Returns: + * - Pointer to a ASCII string if it's in the HWRPB + * - Pointer to a blank string if the data is not in the HWRPB. + */ + +static char * +platform_string(void) +{ + struct dsr_struct *dsr; + static char unk_system_string[] = "N/A"; + + /* Go to the console for the string pointer. + * If the rpb_vers is not 5 or greater the rpb + * is old and does not have this data in it. + */ + if (hwrpb->revision < 5) + return (unk_system_string); + else { + /* The Dynamic System Recognition struct + * has the system platform name starting + * after the character count of the string. + */ + dsr = ((struct dsr_struct *) + ((char *)hwrpb + hwrpb->dsr_offset)); + return ((char *)dsr + (dsr->sysname_off + + sizeof(long))); + } } /* @@ -363,20 +690,21 @@ */ int get_cpuinfo(char *buffer) { - static char *cpu_names[] = { - "EV3", "EV4", "Unknown", "LCA4", "EV5", "EV45", "EV56", - "EV6", "PCA56", "PCA57" - }; - extern struct unaligned_stat { unsigned long count, va, pc; } unaligned[2]; + static char cpu_names[][8] = { + "EV3", "EV4", "Unknown", "LCA4", "EV5", "EV45", "EV56", + "EV6", "PCA56", "PCA57" + }; + struct percpu_struct *cpu; unsigned int cpu_index; char *cpu_name; char *systype_name; char *sysvariation_name; + int len; cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset); cpu_index = (unsigned) (cpu->type - 1); @@ -387,30 +715,25 @@ get_sysnames(hwrpb->sys_type, hwrpb->sys_variation, &systype_name, &sysvariation_name); - return sprintf(buffer, - "cpu\t\t\t: Alpha\n" - "cpu model\t\t: %s\n" - "cpu variation\t\t: %ld\n" - "cpu revision\t\t: %ld\n" - "cpu serial number\t: %s\n" - "system type\t\t: %s\n" - "system variation\t: %s\n" - "system revision\t\t: %ld\n" - "system serial number\t: %s\n" - "cycle frequency [Hz]\t: %lu\n" - "timer frequency [Hz]\t: %lu.%02lu\n" - "page size [bytes]\t: %ld\n" - "phys. address bits\t: %ld\n" - "max. addr. space #\t: %ld\n" - "BogoMIPS\t\t: %lu.%02lu\n" - "kernel unaligned acc\t: %ld (pc=%lx,va=%lx)\n" - "user unaligned acc\t: %ld (pc=%lx,va=%lx)\n" - "platform string\t\t: %s\n" -#ifdef __SMP__ - "%s" -#endif - , - + len = sprintf(buffer, + "cpu\t\t\t: Alpha\n" + "cpu model\t\t: %s\n" + "cpu variation\t\t: %ld\n" + "cpu revision\t\t: %ld\n" + "cpu serial number\t: %s\n" + "system type\t\t: %s\n" + "system variation\t: %s\n" + "system revision\t\t: %ld\n" + "system serial number\t: %s\n" + "cycle frequency [Hz]\t: %lu\n" + "timer frequency [Hz]\t: %lu.%02lu\n" + "page size [bytes]\t: %ld\n" + "phys. address bits\t: %ld\n" + "max. addr. space #\t: %ld\n" + "BogoMIPS\t\t: %lu.%02lu\n" + "kernel unaligned acc\t: %ld (pc=%lx,va=%lx)\n" + "user unaligned acc\t: %ld (pc=%lx,va=%lx)\n" + "platform string\t\t: %s\n", cpu_name, cpu->variation, cpu->revision, (char*)cpu->serial_no, systype_name, sysvariation_name, hwrpb->sys_revision, @@ -424,9 +747,11 @@ loops_per_sec / 500000, (loops_per_sec / 5000) % 100, unaligned[0].count, unaligned[0].pc, unaligned[0].va, unaligned[1].count, unaligned[1].pc, unaligned[1].va, - platform_string() + platform_string()); + #ifdef __SMP__ - , smp_info() + return len + smp_info(buffer+len); +#else + return len; #endif - ); } diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c --- v2.1.115/linux/arch/alpha/kernel/smp.c Thu Aug 6 14:06:28 1998 +++ linux/arch/alpha/kernel/smp.c Sun Aug 9 12:09:05 1998 @@ -24,6 +24,8 @@ #define __KERNEL_SYSCALLS__ #include +#include "proto.h" + struct ipi_msg_flush_tb_struct ipi_msg_flush_tb; struct cpuinfo_alpha cpu_data[NR_CPUS]; @@ -735,15 +737,11 @@ } } -static char smp_buf[256]; - -char *smp_info(void) +int smp_info(char *buffer) { - sprintf(smp_buf, "CPUs probed %d active %d map 0x%x AKP %d\n", - smp_num_probed, smp_num_cpus, cpu_present_map, - klock_info.akp); - - return smp_buf; + return sprintf(buffer, "CPUs probed %d active %d map 0x%x AKP %d\n", + smp_num_probed, smp_num_cpus, cpu_present_map, + klock_info.akp); } /* wrapper for call from panic() */ diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/sys_alcor.c linux/arch/alpha/kernel/sys_alcor.c --- v2.1.115/linux/arch/alpha/kernel/sys_alcor.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/sys_alcor.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,263 @@ +/* + * linux/arch/alpha/kernel/sys_alcor.c + * + * Copyright (C) 1995 David A Rusling + * Copyright (C) 1996 Jay A Estabrook + * Copyright (C) 1998 Richard Henderson + * + * Code supporting the ALCOR and XLT (XL-300/366/433). + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "proto.h" +#include "irq.h" +#include "bios32.h" +#include "machvec.h" + + +static void +alcor_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) +{ + if (irq >= 16) { + /* On Alcor, at least, lines 20..30 are not connected and can + generate spurrious interrupts if we turn them on while IRQ + probing. So explicitly mask them out. */ + mask |= 0x7ff000000000UL; + + /* Note inverted sense of mask bits: */ + *(vuip)GRU_INT_MASK = ~(mask >> 16); + mb(); + } + else if (irq >= 8) + outb(mask >> 8, 0xA1); /* ISA PIC2 */ + else + outb(mask, 0x21); /* ISA PIC1 */ +} + +static void +alcor_ack_irq(unsigned long irq) +{ + if (irq < 16) { + /* Ack the interrupt making it the lowest priority */ + /* First the slave .. */ + if (irq > 7) { + outb(0xE0 | (irq - 8), 0xa0); + irq = 2; + } + /* .. then the master */ + outb(0xE0 | irq, 0x20); + + /* On ALCOR/XLT, need to dismiss interrupt via GRU. */ + *(vuip)GRU_INT_CLEAR = 0x80000000; mb(); + *(vuip)GRU_INT_CLEAR = 0x00000000; mb(); + } +} + +static void +alcor_device_interrupt(unsigned long vector, struct pt_regs *regs) +{ + unsigned long pld; + unsigned int i; + unsigned long flags; + + save_and_cli(flags); + + /* Read the interrupt summary register of the GRU */ + pld = (*(vuip)GRU_INT_REQ) & GRU_INT_REQ_BITS; + + /* + * Now for every possible bit set, work through them and call + * the appropriate interrupt handler. + */ + while (pld) { + i = ffz(~pld); + pld &= pld - 1; /* clear least bit set */ + if (i == 31) { + isa_device_interrupt(vector, regs); + } else { + handle_irq(16 + i, 16 + i, regs); + } + } + restore_flags(flags); +} + +static void +alcor_init_irq(void) +{ + STANDARD_INIT_IRQ_PROLOG; + + if (alpha_using_srm) + alpha_mv.device_interrupt = srm_device_interrupt; + + *(vuip)GRU_INT_MASK = ~(alpha_irq_mask >> 16); mb(); /* invert */ + *(vuip)GRU_INT_EDGE = 0U; mb(); /* all are level */ + *(vuip)GRU_INT_HILO = 0x80000000U; mb(); /* ISA only HI */ + *(vuip)GRU_INT_CLEAR = 0UL; mb(); /* all clear */ + + enable_irq(16 + 31); /* enable (E)ISA PIC cascade */ + enable_irq(2); /* enable cascade */ +} + + +/* + * PCI Fixup configuration. + * + * Summary @ GRU_INT_REQ: + * Bit Meaning + * 0 Interrupt Line A from slot 2 + * 1 Interrupt Line B from slot 2 + * 2 Interrupt Line C from slot 2 + * 3 Interrupt Line D from slot 2 + * 4 Interrupt Line A from slot 1 + * 5 Interrupt line B from slot 1 + * 6 Interrupt Line C from slot 1 + * 7 Interrupt Line D from slot 1 + * 8 Interrupt Line A from slot 0 + * 9 Interrupt Line B from slot 0 + *10 Interrupt Line C from slot 0 + *11 Interrupt Line D from slot 0 + *12 Interrupt Line A from slot 4 + *13 Interrupt Line B from slot 4 + *14 Interrupt Line C from slot 4 + *15 Interrupt Line D from slot 4 + *16 Interrupt Line D from slot 3 + *17 Interrupt Line D from slot 3 + *18 Interrupt Line D from slot 3 + *19 Interrupt Line D from slot 3 + *20-30 Reserved + *31 EISA interrupt + * + * The device to slot mapping looks like: + * + * Slot Device + * 6 built-in TULIP (XLT only) + * 7 PCI on board slot 0 + * 8 PCI on board slot 3 + * 9 PCI on board slot 4 + * 10 PCEB (PCI-EISA bridge) + * 11 PCI on board slot 2 + * 12 PCI on board slot 1 + * + * + * This two layered interrupt approach means that we allocate IRQ 16 and + * above for PCI interrupts. The IRQ relates to which bit the interrupt + * comes in on. This makes interrupt processing much easier. + */ + +static int __init +alcor_map_irq(struct pci_dev *dev, int slot, int pin) +{ + static char irq_tab[7][5] __initlocaldata = { + /*INT INTA INTB INTC INTD */ + /* note: IDSEL 17 is XLT only */ + {16+13, 16+13, 16+13, 16+13, 16+13}, /* IdSel 17, TULIP */ + { 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 18, slot 0 */ + {16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 19, slot 3 */ + {16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 20, slot 4 */ + { -1, -1, -1, -1, -1}, /* IdSel 21, PCEB */ + { 16+0, 16+0, 16+1, 16+2, 16+3}, /* IdSel 22, slot 2 */ + { 16+4, 16+4, 16+5, 16+6, 16+7}, /* IdSel 23, slot 1 */ + }; + const long min_idsel = 6, max_idsel = 12, irqs_per_slot = 5; + return COMMON_TABLE_LOOKUP; +} + +static void __init +alcor_pci_fixup(void) +{ + layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE); + common_pci_fixup(alcor_map_irq, common_swizzle); +} + + +static void +alcor_kill_arch (int mode, char *reboot_cmd) +{ + /* Who said DEC engineer's have no sense of humor? ;-) */ + if (alpha_using_srm) { + *(vuip) GRU_RESET = 0x0000dead; + mb(); + } + + generic_kill_arch(mode, reboot_cmd); +} + + +/* + * The System Vectors + */ + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_ALCOR) +struct alpha_machine_vector alcor_mv __initmv = { + vector_name: "Alcor", + DO_EV5_MMU, + DO_DEFAULT_RTC, + DO_CIA_IO, + DO_CIA_BUS, + machine_check: cia_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 48, + irq_probe_mask: ALCOR_PROBE_MASK, + update_irq_hw: alcor_update_irq_hw, + ack_irq: alcor_ack_irq, + device_interrupt: alcor_device_interrupt, + + init_arch: cia_init_arch, + init_irq: alcor_init_irq, + init_pit: generic_init_pit, + pci_fixup: alcor_pci_fixup, + kill_arch: alcor_kill_arch, + + sys: { cia: { + gru_int_req_bits: ALCOR_GRU_INT_REQ_BITS + }} +}; +ALIAS_MV(alcor) +#endif + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_XLT) +struct alpha_machine_vector xlt_mv __initmv = { + vector_name: "XLT", + DO_EV5_MMU, + DO_DEFAULT_RTC, + DO_CIA_IO, + DO_CIA_BUS, + machine_check: cia_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 48, + irq_probe_mask: ALCOR_PROBE_MASK, + update_irq_hw: alcor_update_irq_hw, + ack_irq: alcor_ack_irq, + device_interrupt: alcor_device_interrupt, + + init_arch: cia_init_arch, + init_irq: alcor_init_irq, + init_pit: generic_init_pit, + pci_fixup: alcor_pci_fixup, + kill_arch: alcor_kill_arch, + + sys: { cia: { + gru_int_req_bits: XLT_GRU_INT_REQ_BITS + }} +}; +ALIAS_MV(xlt) +#endif diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/sys_cabriolet.c linux/arch/alpha/kernel/sys_cabriolet.c --- v2.1.115/linux/arch/alpha/kernel/sys_cabriolet.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/sys_cabriolet.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,395 @@ +/* + * linux/arch/alpha/kernel/sys_cabriolet.c + * + * Copyright (C) 1995 David A Rusling + * Copyright (C) 1996 Jay A Estabrook + * Copyright (C) 1998 Richard Henderson + * + * Code supporting the Cabriolet (AlphaPC64), EB66+, and EB164, + * PC164 and LX164. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "proto.h" +#include "irq.h" +#include "bios32.h" +#include "machvec.h" + + +static void +cabriolet_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) +{ + if (irq >= 16) + outl(alpha_irq_mask >> 16, 0x804); + else if (irq >= 8) + outb(mask >> 8, 0xA1); + else + outb(mask, 0x21); +} + + +/* Under SRM console, we must use the CSERVE PALcode routine to manage + the interrupt mask for us. Otherwise, the kernel/HW get out of + sync with what the PALcode thinks it needs to deliver/ignore. */ + +static void +cabriolet_srm_update_irq_hw(unsigned long irq, unsigned long mask, int unmaskp) +{ + if (irq >= 16) { + if (unmaskp) + cserve_ena(irq - 16); + else + cserve_dis(irq - 16); + } + else if (irq >= 8) + outb(mask >> 8, 0xA1); + else + outb(mask, 0x21); +} + +static void +cabriolet_device_interrupt(unsigned long v, struct pt_regs *r) +{ + unsigned long pld; + unsigned int i; + unsigned long flags; + + save_and_cli(flags); + + /* Read the interrupt summary registers */ + pld = inb(0x804) | (inb(0x805) << 8) | (inb(0x806) << 16); + + /* + * Now for every possible bit set, work through them and call + * the appropriate interrupt handler. + */ + while (pld) { + i = ffz(~pld); + pld &= pld - 1; /* clear least bit set */ + if (i == 4) { + isa_device_interrupt(v, r); + } else { + handle_irq(16 + i, 16 + i, r); + } + } + restore_flags(flags); +} + +static void +cabriolet_init_irq(void) +{ + STANDARD_INIT_IRQ_PROLOG; + + if (alpha_using_srm) { + alpha_mv.update_irq_hw = cabriolet_srm_update_irq_hw; + alpha_mv.device_interrupt = srm_device_interrupt; + } + else { + outl(alpha_irq_mask >> 16, 0x804); + } + + enable_irq(16 + 4); /* enable SIO cascade */ + enable_irq(2); /* enable cascade */ +} + + +/* + * The EB66+ is very similar to the EB66 except that it does not have + * the on-board NCR and Tulip chips. In the code below, I have used + * slot number to refer to the id select line and *not* the slot + * number used in the EB66+ documentation. However, in the table, + * I've given the slot number, the id select line and the Jxx number + * that's printed on the board. The interrupt pins from the PCI slots + * are wired into 3 interrupt summary registers at 0x804, 0x805 and + * 0x806 ISA. + * + * In the table, -1 means don't assign an IRQ number. This is usually + * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip. + */ + +static inline int __init +eb66p_map_irq(struct pci_dev *dev, int slot, int pin) +{ + static char irq_tab[5][5] __initlocaldata = { + /*INT INTA INTB INTC INTD */ + {16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J25 */ + {16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J26 */ + { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */ + {16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 9, slot 2, J27 */ + {16+3, 16+3, 16+8, 16+12, 16+6} /* IdSel 10, slot 3, J28 */ + }; + const long min_idsel = 6, max_idsel = 10, irqs_per_slot = 5; + return COMMON_TABLE_LOOKUP; +} + +static inline void __init +eb66p_pci_fixup(void) +{ + layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE); + common_pci_fixup(eb66p_map_irq, common_swizzle); + enable_ide(0x398); +} + + +/* + * The AlphaPC64 is very similar to the EB66+ except that its slots + * are numbered differently. In the code below, I have used slot + * number to refer to the id select line and *not* the slot number + * used in the AlphaPC64 documentation. However, in the table, I've + * given the slot number, the id select line and the Jxx number that's + * printed on the board. The interrupt pins from the PCI slots are + * wired into 3 interrupt summary registers at 0x804, 0x805 and 0x806 + * ISA. + * + * In the table, -1 means don't assign an IRQ number. This is usually + * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip. + */ + +static inline int __init +cabriolet_map_irq(struct pci_dev *dev, int slot, int pin) +{ + static char irq_tab[5][5] __initlocaldata = { + /*INT INTA INTB INTC INTD */ + { 16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 5, slot 2, J21 */ + { 16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J19 */ + { 16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J20 */ + { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */ + { 16+3, 16+3, 16+8, 16+12, 16+16} /* IdSel 9, slot 3, J22 */ + }; + const long min_idsel = 5, max_idsel = 9, irqs_per_slot = 5; + return COMMON_TABLE_LOOKUP; +} + +static inline void __init +cabriolet_pci_fixup(void) +{ + layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE); + common_pci_fixup(cabriolet_map_irq, common_swizzle); + enable_ide(0x398); +} + +static inline void __init +eb164_pci_fixup(void) +{ + layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); + common_pci_fixup(cabriolet_map_irq, common_swizzle); + enable_ide(0x398); +} + + +/* + * The PC164 and LX164 have 19 PCI interrupts, four from each of the four + * PCI slots, the SIO, PCI/IDE, and USB. + * + * Each of the interrupts can be individually masked. This is + * accomplished by setting the appropriate bit in the mask register. + * A bit is set by writing a "1" to the desired position in the mask + * register and cleared by writing a "0". There are 3 mask registers + * located at ISA address 804h, 805h and 806h. + * + * An I/O read at ISA address 804h, 805h, 806h will return the + * state of the 11 PCI interrupts and not the state of the MASKED + * interrupts. + * + * Note: A write to I/O 804h, 805h, and 806h the mask register will be + * updated. + * + * + * ISA DATA<7:0> + * ISA +--------------------------------------------------------------+ + * ADDRESS | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | + * +==============================================================+ + * 0x804 | INTB0 | USB | IDE | SIO | INTA3 |INTA2 | INTA1 | INTA0 | + * +--------------------------------------------------------------+ + * 0x805 | INTD0 | INTC3 | INTC2 | INTC1 | INTC0 |INTB3 | INTB2 | INTB1 | + * +--------------------------------------------------------------+ + * 0x806 | Rsrv | Rsrv | Rsrv | Rsrv | Rsrv |INTD3 | INTD2 | INTD1 | + * +--------------------------------------------------------------+ + * * Rsrv = reserved bits + * Note: The mask register is write-only. + * + * IdSel + * 5 32 bit PCI option slot 2 + * 6 64 bit PCI option slot 0 + * 7 64 bit PCI option slot 1 + * 8 Saturn I/O + * 9 32 bit PCI option slot 3 + * 10 USB + * 11 IDE + * + */ + +static inline int __init +alphapc164_map_irq(struct pci_dev *dev, int slot, int pin) +{ + static char irq_tab[7][5] __initlocaldata = { + /*INT INTA INTB INTC INTD */ + { 16+2, 16+2, 16+9, 16+13, 16+17}, /* IdSel 5, slot 2, J20 */ + { 16+0, 16+0, 16+7, 16+11, 16+15}, /* IdSel 6, slot 0, J29 */ + { 16+1, 16+1, 16+8, 16+12, 16+16}, /* IdSel 7, slot 1, J26 */ + { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */ + { 16+3, 16+3, 16+10, 16+14, 16+18}, /* IdSel 9, slot 3, J19 */ + { 16+6, 16+6, 16+6, 16+6, 16+6}, /* IdSel 10, USB */ + { 16+5, 16+5, 16+5, 16+5, 16+5} /* IdSel 11, IDE */ + }; + const long min_idsel = 5, max_idsel = 11, irqs_per_slot = 5; + return COMMON_TABLE_LOOKUP; +} + +static inline void __init +alphapc164_pci_fixup(void) +{ + layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); + common_pci_fixup(alphapc164_map_irq, common_swizzle); + SMC93x_Init(); +} + +/* + * The System Vector + */ + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_CABRIOLET) +struct alpha_machine_vector cabriolet_mv __initmv = { + vector_name: "Cabriolet", + DO_EV4_MMU, + DO_DEFAULT_RTC, + DO_APECS_IO, + DO_APECS_BUS, + machine_check: apecs_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 35, + irq_probe_mask: _PROBE_MASK(35), + update_irq_hw: cabriolet_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: cabriolet_device_interrupt, + + init_arch: apecs_init_arch, + init_irq: cabriolet_init_irq, + init_pit: generic_init_pit, + pci_fixup: cabriolet_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(cabriolet) +#endif + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB164) +struct alpha_machine_vector eb164_mv __initmv = { + vector_name: "EB164", + DO_EV5_MMU, + DO_DEFAULT_RTC, + DO_CIA_IO, + DO_CIA_BUS, + machine_check: cia_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 35, + irq_probe_mask: _PROBE_MASK(35), + update_irq_hw: cabriolet_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: cabriolet_device_interrupt, + + init_arch: cia_init_arch, + init_irq: cabriolet_init_irq, + init_pit: generic_init_pit, + pci_fixup: eb164_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(eb164) +#endif + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB66P) +struct alpha_machine_vector eb66p_mv __initmv = { + vector_name: "EB66+", + DO_EV4_MMU, + DO_DEFAULT_RTC, + DO_LCA_IO, + DO_LCA_BUS, + machine_check: lca_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 35, + irq_probe_mask: _PROBE_MASK(35), + update_irq_hw: cabriolet_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: cabriolet_device_interrupt, + + init_arch: lca_init_arch, + init_irq: cabriolet_init_irq, + init_pit: generic_init_pit, + pci_fixup: eb66p_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(eb66p) +#endif + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LX164) +struct alpha_machine_vector lx164_mv __initmv = { + vector_name: "LX164", + DO_EV5_MMU, + DO_DEFAULT_RTC, + DO_PYXIS_IO, + DO_PYXIS_BUS, + machine_check: pyxis_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 35, + irq_probe_mask: _PROBE_MASK(35), + update_irq_hw: cabriolet_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: cabriolet_device_interrupt, + + init_arch: pyxis_init_arch, + init_irq: cabriolet_init_irq, + init_pit: generic_init_pit, + pci_fixup: alphapc164_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(lx164) +#endif + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PC164) +struct alpha_machine_vector pc164_mv __initmv = { + vector_name: "PC164", + DO_EV5_MMU, + DO_DEFAULT_RTC, + DO_CIA_IO, + DO_CIA_BUS, + machine_check: cia_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 35, + irq_probe_mask: _PROBE_MASK(35), + update_irq_hw: cabriolet_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: cabriolet_device_interrupt, + + init_arch: cia_init_arch, + init_irq: cabriolet_init_irq, + init_pit: generic_init_pit, + pci_fixup: alphapc164_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(pc164) +#endif + diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/sys_dp264.c linux/arch/alpha/kernel/sys_dp264.c --- v2.1.115/linux/arch/alpha/kernel/sys_dp264.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/sys_dp264.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,231 @@ +/* + * linux/arch/alpha/kernel/sys_dp264.c + * + * Copyright (C) 1995 David A Rusling + * Copyright (C) 1996 Jay A Estabrook + * Copyright (C) 1998 Richard Henderson + * + * Code supporting the DP264 (EV6+TSUNAMI). + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "proto.h" +#include "irq.h" +#include "bios32.h" +#include "machvec.h" + + +/* + * HACK ALERT! only CPU#0 is used currently + */ + +static void +dp264_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) +{ + if (irq >= 16) { + /* Make CERTAIN none of the bogus ints get enabled */ + *(vulp)TSUNAMI_CSR_DIM0 = + ~(mask) & ~0x0000000000000000UL; + mb(); + /* ... and read it back to make sure it got written. */ + *(vulp)TSUNAMI_CSR_DIM0; + } + else if (irq >= 8) + outb(mask >> 8, 0xA1); /* ISA PIC2 */ + else + outb(mask, 0x21); /* ISA PIC1 */ +} + +static void +dp264_device_interrupt(unsigned long vector, struct pt_regs * regs) +{ + unsigned long pld; + unsigned int i; + unsigned long flags; + + __save_and_cli(flags); + + /* Read the interrupt summary register of TSUNAMI */ + pld = (*(vulp)TSUNAMI_CSR_DIR0); + + /* + * Now for every possible bit set, work through them and call + * the appropriate interrupt handler. + */ + while (pld) { + i = ffz(~pld); + pld &= pld - 1; /* clear least bit set */ + if (i == 55) { + isa_device_interrupt(vector, regs); + } else { /* if not timer int */ + handle_irq(16 + i, 16 + i, regs); + } +#if 0 + *(vulp)TSUNAMI_CSR_DIR0 = 1UL << i; mb(); + tmp = *(vulp)TSUNAMI_CSR_DIR0; +#endif + } + __restore_flags(flags); +} + +static void +dp264_srm_device_interrupt(unsigned long vector, struct pt_regs * regs) +{ + int irq, ack; + unsigned long flags; + + __save_and_cli(flags); + ack = irq = (vector - 0x800) >> 4; + + /* + * The DP264 SRM console reports PCI interrupts with a vector + * 0x100 *higher* than one might expect, as PCI IRQ 0 (ie bit 0) + * shows up as IRQ 16, etc, etc. We adjust it down by 16 to have + * it line up with the actual bit numbers from the DIM registers, + * which is how we manage the interrupts/mask. Sigh... + */ + if (irq >= 32) + ack = irq = irq - 16; + + handle_irq(irq, ack, regs); + __restore_flags(flags); +} + +static void __init +dp264_init_irq(void) +{ + STANDARD_INIT_IRQ_PROLOG; + + if (alpha_using_srm) + alpha_mv.device_interrupt = dp264_srm_device_interrupt; + + /* Note invert on MASK bits. */ + *(vulp)TSUNAMI_CSR_DIM0 = ~(alpha_irq_mask) & ~0UL; mb(); + *(vulp)TSUNAMI_CSR_DIM0; + + enable_irq(55); /* Enable CYPRESS interrupt controller (ISA). */ + enable_irq(2); +} + + +/* + * PCI Fixup configuration. + * + * Summary @ TSUNAMI_CSR_DIM0: + * Bit Meaning + * 0-17 Unused + *18 Interrupt SCSI B (Adaptec 7895 builtin) + *19 Interrupt SCSI A (Adaptec 7895 builtin) + *20 Interrupt Line D from slot 2 PCI0 + *21 Interrupt Line C from slot 2 PCI0 + *22 Interrupt Line B from slot 2 PCI0 + *23 Interrupt Line A from slot 2 PCI0 + *24 Interrupt Line D from slot 1 PCI0 + *25 Interrupt Line C from slot 1 PCI0 + *26 Interrupt Line B from slot 1 PCI0 + *27 Interrupt Line A from slot 1 PCI0 + *28 Interrupt Line D from slot 0 PCI0 + *29 Interrupt Line C from slot 0 PCI0 + *30 Interrupt Line B from slot 0 PCI0 + *31 Interrupt Line A from slot 0 PCI0 + * + *32 Interrupt Line D from slot 3 PCI1 + *33 Interrupt Line C from slot 3 PCI1 + *34 Interrupt Line B from slot 3 PCI1 + *35 Interrupt Line A from slot 3 PCI1 + *36 Interrupt Line D from slot 2 PCI1 + *37 Interrupt Line C from slot 2 PCI1 + *38 Interrupt Line B from slot 2 PCI1 + *39 Interrupt Line A from slot 2 PCI1 + *40 Interrupt Line D from slot 1 PCI1 + *41 Interrupt Line C from slot 1 PCI1 + *42 Interrupt Line B from slot 1 PCI1 + *43 Interrupt Line A from slot 1 PCI1 + *44 Interrupt Line D from slot 0 PCI1 + *45 Interrupt Line C from slot 0 PCI1 + *46 Interrupt Line B from slot 0 PCI1 + *47 Interrupt Line A from slot 0 PCI1 + *48-52 Unused + *53 PCI0 NMI (from Cypress) + *54 PCI0 SMI INT (from Cypress) + *55 PCI0 ISA Interrupt (from Cypress) + *56-60 Unused + *61 PCI1 Bus Error + *62 PCI0 Bus Error + *63 Reserved + * + * IdSel + * 5 Cypress Bridge I/O + * 6 SCSI Adaptec builtin + * 7 64 bit PCI option slot 0 + * 8 64 bit PCI option slot 1 + * 9 64 bit PCI option slot 2 + * + */ + +static int __init +dp264_map_irq(struct pci_dev *dev, int slot, int pin) +{ + static char irq_tab[5][5] __initlocaldata = { + /*INT INTA INTB INTC INTD */ + { -1, -1, -1, -1, -1}, /* IdSel 5 ISA Bridge */ + { 16+ 2, 16+ 2, 16+ 2, 16+ 2, 16+ 2}, /* IdSel 6 SCSI builtin*/ + { 16+15, 16+15, 16+14, 16+13, 16+12}, /* IdSel 7 slot 0 */ + { 16+11, 16+11, 16+10, 16+ 9, 16+ 8}, /* IdSel 8 slot 1 */ + { 16+ 7, 16+ 7, 16+ 6, 16+ 5, 16+ 4} /* IdSel 9 slot 2 */ + }; + const long min_idsel = 5, max_idsel = 9, irqs_per_slot = 5; + return COMMON_TABLE_LOOKUP; +} + +static void __init +dp264_pci_fixup(void) +{ + layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); + common_pci_fixup(dp264_map_irq, common_swizzle); + SMC669_Init(); +} + + +/* + * The System Vector + */ + +struct alpha_machine_vector dp264_mv __initmv = { + vector_name: "DP264", + DO_EV6_MMU, + DO_DEFAULT_RTC, + DO_TSUNAMI_IO, + DO_TSUNAMI_BUS, + machine_check: tsunami_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 64, + irq_probe_mask: _PROBE_MASK(64), + update_irq_hw: dp264_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: dp264_device_interrupt, + + init_arch: tsunami_init_arch, + init_irq: dp264_init_irq, + init_pit: generic_init_pit, + pci_fixup: dp264_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(dp264) diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/sys_eb64p.c linux/arch/alpha/kernel/sys_eb64p.c --- v2.1.115/linux/arch/alpha/kernel/sys_eb64p.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/sys_eb64p.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,206 @@ +/* + * linux/arch/alpha/kernel/sys_eb64p.c + * + * Copyright (C) 1995 David A Rusling + * Copyright (C) 1996 Jay A Estabrook + * Copyright (C) 1998 Richard Henderson + * + * Code supporting the EB64+ and EB66. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "proto.h" +#include "irq.h" +#include "bios32.h" +#include "machvec.h" + + +static void +eb64p_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) +{ + if (irq >= 16) + if (irq >= 24) + outb(mask >> 24, 0x27); + else + outb(mask >> 16, 0x26); + else if (irq >= 8) + outb(mask >> 8, 0xA1); + else + outb(mask, 0x21); +} + +static void +eb64p_device_interrupt(unsigned long vector, struct pt_regs *regs) +{ + unsigned long pld; + unsigned int i; + unsigned long flags; + + save_and_cli(flags); + + /* Read the interrupt summary registers */ + pld = inb(0x26) | (inb(0x27) << 8); + /* + * Now, for every possible bit set, work through + * them and call the appropriate interrupt handler. + */ + while (pld) { + i = ffz(~pld); + pld &= pld - 1; /* clear least bit set */ + + if (i == 5) { + isa_device_interrupt(vector, regs); + } else { + handle_irq(16 + i, 16 + i, regs); + } + } + restore_flags(flags); +} + +static void __init +eb64p_init_irq(void) +{ + STANDARD_INIT_IRQ_PROLOG; + + outb(alpha_irq_mask >> 16, 0x26); + outb(alpha_irq_mask >> 24, 0x27); + enable_irq(16 + 5); /* enable SIO cascade */ + enable_irq(2); /* enable cascade */ +} + +/* + * PCI Fixup configuration. + * + * There are two 8 bit external summary registers as follows: + * + * Summary @ 0x26: + * Bit Meaning + * 0 Interrupt Line A from slot 0 + * 1 Interrupt Line A from slot 1 + * 2 Interrupt Line B from slot 0 + * 3 Interrupt Line B from slot 1 + * 4 Interrupt Line C from slot 0 + * 5 Interrupt line from the two ISA PICs + * 6 Tulip (slot + * 7 NCR SCSI + * + * Summary @ 0x27 + * Bit Meaning + * 0 Interrupt Line C from slot 1 + * 1 Interrupt Line D from slot 0 + * 2 Interrupt Line D from slot 1 + * 3 RAZ + * 4 RAZ + * 5 RAZ + * 6 RAZ + * 7 RAZ + * + * The device to slot mapping looks like: + * + * Slot Device + * 5 NCR SCSI controller + * 6 PCI on board slot 0 + * 7 PCI on board slot 1 + * 8 Intel SIO PCI-ISA bridge chip + * 9 Tulip - DECchip 21040 Ethernet controller + * + * + * This two layered interrupt approach means that we allocate IRQ 16 and + * above for PCI interrupts. The IRQ relates to which bit the interrupt + * comes in on. This makes interrupt processing much easier. + */ + +static int __init +eb64p_map_irq(struct pci_dev *dev, int slot, int pin) +{ + static char irq_tab[5][5] __initlocaldata = { + /*INT INTA INTB INTC INTD */ + {16+7, 16+7, 16+7, 16+7, 16+7}, /* IdSel 5, slot ?, ?? */ + {16+0, 16+0, 16+2, 16+4, 16+9}, /* IdSel 6, slot ?, ?? */ + {16+1, 16+1, 16+3, 16+8, 16+10}, /* IdSel 7, slot ?, ?? */ + { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */ + {16+6, 16+6, 16+6, 16+6, 16+6}, /* IdSel 9, TULIP */ + }; + const long min_idsel = 5, max_idsel = 9, irqs_per_slot = 5; + return COMMON_TABLE_LOOKUP; +} + +static void __init +eb64p_pci_fixup(void) +{ + layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE); + common_pci_fixup(eb64p_map_irq, common_swizzle); +} + + +/* + * The System Vector + */ + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB64P) +struct alpha_machine_vector eb64p_mv __initmv = { + vector_name: "EB64+", + DO_EV4_MMU, + DO_DEFAULT_RTC, + DO_APECS_IO, + DO_APECS_BUS, + machine_check: apecs_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 32, + irq_probe_mask: _PROBE_MASK(32), + update_irq_hw: eb64p_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: eb64p_device_interrupt, + + init_arch: apecs_init_arch, + init_irq: eb64p_init_irq, + init_pit: generic_init_pit, + pci_fixup: eb64p_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(eb64p) +#endif + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB66) +struct alpha_machine_vector eb66_mv __initmv = { + vector_name: "EB66", + DO_EV4_MMU, + DO_DEFAULT_RTC, + DO_LCA_IO, + DO_LCA_BUS, + machine_check: lca_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 32, + irq_probe_mask: _PROBE_MASK(32), + update_irq_hw: eb64p_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: eb64p_device_interrupt, + + init_arch: lca_init_arch, + init_irq: eb64p_init_irq, + init_pit: generic_init_pit, + pci_fixup: eb64p_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(eb66) +#endif diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/sys_jensen.c linux/arch/alpha/kernel/sys_jensen.c --- v2.1.115/linux/arch/alpha/kernel/sys_jensen.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/sys_jensen.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,146 @@ +/* + * linux/arch/alpha/kernel/sys_jensen.c + * + * Copyright (C) 1995 Linus Torvalds + * Copyright (C) 1998 Richard Henderson + * + * Code supporting the Jensen. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define __EXTERN_INLINE inline +#include +#include +#undef __EXTERN_INLINE + +#include +#include +#include +#include + +#include "proto.h" +#include "irq.h" +#include "machvec.h" + + +static void +jensen_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) +{ + if (irq >= 8) + outb(mask >> 8, 0xA1); + else + outb(mask, 0x21); +} + +/* + * Jensen is special: the vector is 0x8X0 for EISA interrupt X, and + * 0x9X0 for the local motherboard interrupts.. + * + * 0x660 - NMI + * + * 0x800 - IRQ0 interval timer (not used, as we use the RTC timer) + * 0x810 - IRQ1 line printer (duh..) + * 0x860 - IRQ6 floppy disk + * 0x8E0 - IRQ14 SCSI controller + * + * 0x900 - COM1 + * 0x920 - COM2 + * 0x980 - keyboard + * 0x990 - mouse + * + * PCI-based systems are more sane: they don't have the local + * interrupts at all, and have only normal PCI interrupts from + * devices. Happily it's easy enough to do a sane mapping from the + * Jensen.. Note that this means that we may have to do a hardware + * "ack" to a different interrupt than we report to the rest of the + * world. + */ + +static void +handle_nmi(struct pt_regs * regs) +{ + printk("Whee.. NMI received. Probable hardware error\n"); + printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461)); +} + +static void +jensen_device_interrupt(unsigned long vector, struct pt_regs * regs) +{ + int irq, ack; + unsigned long flags; + + __save_and_cli(flags); + ack = irq = (vector - 0x800) >> 4; + + switch (vector) { + case 0x660: handle_nmi(regs); return; + + /* local device interrupts: */ + case 0x900: irq = 4, ack = -1; break; /* com1 -> irq 4 */ + case 0x920: irq = 3, ack = -1; break; /* com2 -> irq 3 */ + case 0x980: irq = 1, ack = -1; break; /* kbd -> irq 1 */ + case 0x990: irq = 9, ack = -1; break; /* mouse -> irq 9 */ + default: + if (vector > 0x900) { + printk("Unknown local interrupt %lx\n", vector); + } + + /* irq1 is supposed to be the keyboard, silly Jensen + (is this really needed??) */ + if (irq == 1) + irq = 7; + break; + } + + handle_irq(irq, ack, regs); + __restore_flags(flags); +} + +static void +jensen_init_irq(void) +{ + STANDARD_INIT_IRQ_PROLOG; + + enable_irq(2); /* enable cascade */ +} + +static void +jensen_machine_check (u64 vector, u64 la, struct pt_regs *regs) +{ + printk(KERN_CRIT "Machine check\n"); +} + + +/* + * The System Vector + */ + +struct alpha_machine_vector jensen_mv __initmv = { + vector_name: "Jensen", + DO_EV4_MMU, + IO_LITE(JENSEN,jensen,jensen), + BUS(jensen), + machine_check: jensen_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 16, + irq_probe_mask: _PROBE_MASK(16), + update_irq_hw: jensen_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: jensen_device_interrupt, + + init_arch: NULL, + init_irq: jensen_init_irq, + init_pit: generic_init_pit, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(jensen) diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/sys_miata.c linux/arch/alpha/kernel/sys_miata.c --- v2.1.115/linux/arch/alpha/kernel/sys_miata.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/sys_miata.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,307 @@ +/* + * linux/arch/alpha/kernel/sys_miata.c + * + * Copyright (C) 1995 David A Rusling + * Copyright (C) 1996 Jay A Estabrook + * Copyright (C) 1998 Richard Henderson + * + * Code supporting the MIATA (EV56+PYXIS). + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "proto.h" +#include "irq.h" +#include "bios32.h" +#include "machvec.h" + + +static void +miata_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) +{ + if (irq >= 16) { + /* Make CERTAIN none of the bogus ints get enabled... */ + *(vulp)PYXIS_INT_MASK = + ~((long)mask >> 16) & ~0x4000000000000e3bUL; + mb(); + /* ... and read it back to make sure it got written. */ + *(vulp)PYXIS_INT_MASK; + } + else if (irq >= 8) + outb(mask >> 8, 0xA1); /* ISA PIC2 */ + else + outb(mask, 0x21); /* ISA PIC1 */ +} + +static void +miata_device_interrupt(unsigned long vector, struct pt_regs *regs) +{ + unsigned long pld, tmp; + unsigned int i; + unsigned long flags; + + save_and_cli(flags); + + /* Read the interrupt summary register of PYXIS */ + pld = *(vulp)PYXIS_INT_REQ; + + /* + * For now, AND off any bits we are not interested in: + * HALT (2), timer (6), ISA Bridge (7), 21142/3 (8) + * then all the PCI slots/INTXs (12-31). + */ + /* Maybe HALT should only be used for SRM console boots? */ + pld &= 0x00000000fffff1c4UL; + + /* + * Now for every possible bit set, work through them and call + * the appropriate interrupt handler. + */ + while (pld) { + i = ffz(~pld); + pld &= pld - 1; /* clear least bit set */ + if (i == 7) { + isa_device_interrupt(vector, regs); + } else if (i == 6) { + continue; + } else { + /* if not timer int */ + handle_irq(16 + i, 16 + i, regs); + } + *(vulp)PYXIS_INT_REQ = 1UL << i; mb(); + tmp = *(vulp)PYXIS_INT_REQ; + } + restore_flags(flags); +} + +static void +miata_srm_device_interrupt(unsigned long vector, struct pt_regs * regs) +{ + int irq, ack; + unsigned long flags; + + __save_and_cli(flags); + ack = irq = (vector - 0x800) >> 4; + + /* + * I really hate to do this, but the MIATA SRM console ignores the + * low 8 bits in the interrupt summary register, and reports the + * vector 0x80 *lower* than I expected from the bit numbering in + * the documentation. + * This was done because the low 8 summary bits really aren't used + * for reporting any interrupts (the PCI-ISA bridge, bit 7, isn't + * used for this purpose, as PIC interrupts are delivered as the + * vectors 0x800-0x8f0). + * But I really don't want to change the fixup code for allocation + * of IRQs, nor the alpha_irq_mask maintenance stuff, both of which look + * nice and clean now. + * So, here's this grotty hack... :-( + */ + if (irq >= 16) + ack = irq = irq + 8; + + handle_irq(irq, ack, regs); + __restore_flags(flags); +} + +static void __init +miata_init_irq(void) +{ + STANDARD_INIT_IRQ_PROLOG; + + if (alpha_using_srm) + alpha_mv.device_interrupt = miata_srm_device_interrupt; + + /* Note invert on MASK bits. */ + *(vulp)PYXIS_INT_MASK = ~((long)alpha_irq_mask >> 16); mb(); +#if 0 + /* These break on MiataGL so we'll try not to do it at all. */ + *(vulp)PYXIS_INT_HILO = 0x000000B2UL; mb(); /* ISA/NMI HI */ + *(vulp)PYXIS_RT_COUNT = 0UL; mb(); /* clear count */ +#endif + /* Clear upper timer. */ + *(vulp)PYXIS_INT_REQ = 0x4000000000000000UL; mb(); + + enable_irq(16 + 2); /* enable HALT switch - SRM only? */ + enable_irq(16 + 6); /* enable timer */ + enable_irq(16 + 7); /* enable ISA PIC cascade */ + enable_irq(2); /* enable cascade */ +} + + +/* + * PCI Fixup configuration. + * + * Summary @ PYXIS_INT_REQ: + * Bit Meaning + * 0 Fan Fault + * 1 NMI + * 2 Halt/Reset switch + * 3 none + * 4 CID0 (Riser ID) + * 5 CID1 (Riser ID) + * 6 Interval timer + * 7 PCI-ISA Bridge + * 8 Ethernet + * 9 EIDE (deprecated, ISA 14/15 used) + *10 none + *11 USB + *12 Interrupt Line A from slot 4 + *13 Interrupt Line B from slot 4 + *14 Interrupt Line C from slot 4 + *15 Interrupt Line D from slot 4 + *16 Interrupt Line A from slot 5 + *17 Interrupt line B from slot 5 + *18 Interrupt Line C from slot 5 + *19 Interrupt Line D from slot 5 + *20 Interrupt Line A from slot 1 + *21 Interrupt Line B from slot 1 + *22 Interrupt Line C from slot 1 + *23 Interrupt Line D from slot 1 + *24 Interrupt Line A from slot 2 + *25 Interrupt Line B from slot 2 + *26 Interrupt Line C from slot 2 + *27 Interrupt Line D from slot 2 + *27 Interrupt Line A from slot 3 + *29 Interrupt Line B from slot 3 + *30 Interrupt Line C from slot 3 + *31 Interrupt Line D from slot 3 + * + * The device to slot mapping looks like: + * + * Slot Device + * 3 DC21142 Ethernet + * 4 EIDE CMD646 + * 5 none + * 6 USB + * 7 PCI-ISA bridge + * 8 PCI-PCI Bridge (SBU Riser) + * 9 none + * 10 none + * 11 PCI on board slot 4 (SBU Riser) + * 12 PCI on board slot 5 (SBU Riser) + * + * These are behind the bridge, so I'm not sure what to do... + * + * 13 PCI on board slot 1 (SBU Riser) + * 14 PCI on board slot 2 (SBU Riser) + * 15 PCI on board slot 3 (SBU Riser) + * + * + * This two layered interrupt approach means that we allocate IRQ 16 and + * above for PCI interrupts. The IRQ relates to which bit the interrupt + * comes in on. This makes interrupt processing much easier. + */ + +static int __init +miata_map_irq(struct pci_dev *dev, int slot, int pin) +{ + static char irq_tab[18][5] __initlocaldata = { + /*INT INTA INTB INTC INTD */ + {16+ 8, 16+ 8, 16+ 8, 16+ 8, 16+ 8}, /* IdSel 14, DC21142 */ + { -1, -1, -1, -1, -1}, /* IdSel 15, EIDE */ + { -1, -1, -1, -1, -1}, /* IdSel 16, none */ + { -1, -1, -1, -1, -1}, /* IdSel 17, none */ + /* {16+11, 16+11, 16+11, 16+11, 16+11},*//* IdSel 17, USB ?? */ + { -1, -1, -1, -1, -1}, /* IdSel 18, PCI-ISA */ + { -1, -1, -1, -1, -1}, /* IdSel 19, PCI-PCI */ + { -1, -1, -1, -1, -1}, /* IdSel 20, none */ + { -1, -1, -1, -1, -1}, /* IdSel 21, none */ + {16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 22, slot 4 */ + {16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 23, slot 5 */ + /* The following are actually on bus 1, which is + across the builtin PCI-PCI bridge. */ + {16+20, 16+20, 16+21, 16+22, 16+23}, /* IdSel 24, slot 1 */ + {16+24, 16+24, 16+25, 16+26, 16+27}, /* IdSel 25, slot 2 */ + {16+28, 16+28, 16+29, 16+30, 16+31}, /* IdSel 26, slot 3 */ + { -1, -1, -1, -1, -1}, /* IdSel 27, none */ + { -1, -1, -1, -1, -1}, /* IdSel 28, none */ + { -1, -1, -1, -1, -1}, /* IdSel 29, none */ + { -1, -1, -1, -1, -1}, /* IdSel 30, none */ + { -1, -1, -1, -1, -1}, /* IdSel 31, PCI-PCI */ + }; + const long min_idsel = 3, max_idsel = 20, irqs_per_slot = 5; + return COMMON_TABLE_LOOKUP; +} + +static int __init +miata_swizzle(struct pci_dev *dev, int *pinp) +{ + int slot, pin = *pinp; + + /* Check first for the built-in bridge. */ + if ((PCI_SLOT(dev->bus->self->devfn) == 8) || + (PCI_SLOT(dev->bus->self->devfn) == 20)) { + slot = PCI_SLOT(dev->devfn) + 5; + } + else + { + /* Must be a card-based bridge. */ + do { + if ((PCI_SLOT(dev->bus->self->devfn) == 8) || + (PCI_SLOT(dev->bus->self->devfn) == 20)) { + slot = PCI_SLOT(dev->devfn) + 5; + break; + } + pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); + + /* Move up the chain of bridges. */ + dev = dev->bus->self; + /* Slot of the next bridge. */ + slot = PCI_SLOT(dev->devfn); + } while (dev->bus->self); + } + *pinp = pin; + return slot; +} + +static void __init +miata_pci_fixup(void) +{ + layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); + common_pci_fixup(miata_map_irq, miata_swizzle); + SMC669_Init(); /* it might be a GL (fails harmlessly if not) */ + es1888_init(); +} + + +/* + * The System Vector + */ + +struct alpha_machine_vector miata_mv __initmv = { + vector_name: "Miata", + DO_EV5_MMU, + DO_DEFAULT_RTC, + DO_PYXIS_IO, + DO_PYXIS_BUS, + machine_check: pyxis_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 48, + irq_probe_mask: _PROBE_MASK(48), + update_irq_hw: miata_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: miata_device_interrupt, + + init_arch: pyxis_init_arch, + init_irq: miata_init_irq, + init_pit: generic_init_pit, + pci_fixup: miata_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(miata) diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/sys_mikasa.c linux/arch/alpha/kernel/sys_mikasa.c --- v2.1.115/linux/arch/alpha/kernel/sys_mikasa.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/sys_mikasa.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,297 @@ +/* + * linux/arch/alpha/kernel/sys_mikasa.c + * + * Copyright (C) 1995 David A Rusling + * Copyright (C) 1996 Jay A Estabrook + * Copyright (C) 1998 Richard Henderson + * + * Code supporting the MIKASA (AlphaServer 1000). + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "proto.h" +#include "irq.h" +#include "bios32.h" +#include "machvec.h" + +static void +mikasa_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) +{ + if (irq >= 16) + outw(~(mask >> 16), 0x536); /* note invert */ + else if (irq >= 8) + outb(mask >> 8, 0xA1); + else + outb(mask, 0x21); +} + +static void +mikasa_device_interrupt(unsigned long vector, struct pt_regs *regs) +{ + unsigned long pld; + unsigned int i; + unsigned long flags; + + save_and_cli(flags); + + /* Read the interrupt summary registers */ + pld = (((unsigned long) (~inw(0x534)) & 0x0000ffffUL) << 16) | + (((unsigned long) inb(0xa0)) << 8) | + ((unsigned long) inb(0x20)); + + /* + * Now for every possible bit set, work through them and call + * the appropriate interrupt handler. + */ + while (pld) { + i = ffz(~pld); + pld &= pld - 1; /* clear least bit set */ + if (i < 16) { + isa_device_interrupt(vector, regs); + } else { + handle_irq(i, i, regs); + } + } + restore_flags(flags); +} + +static void __init +mikasa_init_irq(void) +{ + STANDARD_INIT_IRQ_PROLOG; + + if (alpha_using_srm) + alpha_mv.device_interrupt = srm_device_interrupt; + + outw(~(alpha_irq_mask >> 16), 0x536); /* note invert */ + enable_irq(2); /* enable cascade */ +} + + +/* + * PCI Fixup configuration. + * + * Summary @ 0x536: + * Bit Meaning + * 0 Interrupt Line A from slot 0 + * 1 Interrupt Line B from slot 0 + * 2 Interrupt Line C from slot 0 + * 3 Interrupt Line D from slot 0 + * 4 Interrupt Line A from slot 1 + * 5 Interrupt line B from slot 1 + * 6 Interrupt Line C from slot 1 + * 7 Interrupt Line D from slot 1 + * 8 Interrupt Line A from slot 2 + * 9 Interrupt Line B from slot 2 + *10 Interrupt Line C from slot 2 + *11 Interrupt Line D from slot 2 + *12 NCR 810 SCSI + *13 Power Supply Fail + *14 Temperature Warn + *15 Reserved + * + * The device to slot mapping looks like: + * + * Slot Device + * 6 NCR SCSI controller + * 7 Intel PCI-EISA bridge chip + * 11 PCI on board slot 0 + * 12 PCI on board slot 1 + * 13 PCI on board slot 2 + * + * + * This two layered interrupt approach means that we allocate IRQ 16 and + * above for PCI interrupts. The IRQ relates to which bit the interrupt + * comes in on. This makes interrupt processing much easier. + */ + +static int __init +mikasa_map_irq(struct pci_dev *dev, int slot, int pin) +{ + static char irq_tab[8][5] __initlocaldata = { + /*INT INTA INTB INTC INTD */ + {16+12, 16+12, 16+12, 16+12, 16+12}, /* IdSel 17, SCSI */ + { -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */ + { -1, -1, -1, -1, -1}, /* IdSel 19, ???? */ + { -1, -1, -1, -1, -1}, /* IdSel 20, ???? */ + { -1, -1, -1, -1, -1}, /* IdSel 21, ???? */ + { 16+0, 16+0, 16+1, 16+2, 16+3}, /* IdSel 22, slot 0 */ + { 16+4, 16+4, 16+5, 16+6, 16+7}, /* IdSel 23, slot 1 */ + { 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 24, slot 2 */ + }; + const long min_idsel = 6, max_idsel = 13, irqs_per_slot = 5; + return COMMON_TABLE_LOOKUP; +} + +static void __init +mikasa_pci_fixup(void) +{ + layout_all_busses(EISA_DEFAULT_IO_BASE,APECS_AND_LCA_DEFAULT_MEM_BASE); + common_pci_fixup(mikasa_map_irq, common_swizzle); +} + +static void __init +mikasa_primo_pci_fixup(void) +{ + layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE); + common_pci_fixup(mikasa_map_irq, common_swizzle); +} + +static void +mikasa_machine_check(unsigned long vector, unsigned long la_ptr, + struct pt_regs * regs) +{ +#define MCHK_NO_DEVSEL 0x205L +#define MCHK_NO_TABT 0x204L + + struct el_common *mchk_header; + struct el_apecs_procdata *mchk_procdata; + struct el_apecs_mikasa_sysdata_mcheck *mchk_sysdata; + unsigned long *ptr; + int i; + + mchk_header = (struct el_common *)la_ptr; + + mchk_procdata = (struct el_apecs_procdata *) + (la_ptr + mchk_header->proc_offset + - sizeof(mchk_procdata->paltemp)); + + mchk_sysdata = (struct el_apecs_mikasa_sysdata_mcheck *) + (la_ptr + mchk_header->sys_offset); + +#ifdef DEBUG + printk("mikasa_machine_check: vector=0x%lx la_ptr=0x%lx\n", + vector, la_ptr); + printk(" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", + regs->pc, mchk_header->size, mchk_header->proc_offset, + mchk_header->sys_offset); + printk("mikasa_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n", + apecs_mcheck_expected, mchk_sysdata->epic_dcsr, + mchk_sysdata->epic_pear); + ptr = (unsigned long *)la_ptr; + for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { + printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]); + } +#endif + + /* + * Check if machine check is due to a badaddr() and if so, + * ignore the machine check. + */ + + if (apecs_mcheck_expected + && ((unsigned int)mchk_header->code == MCHK_NO_DEVSEL + || (unsigned int)mchk_header->code == MCHK_NO_TABT)) { + apecs_mcheck_expected = 0; + apecs_mcheck_taken = 1; + mb(); + mb(); /* magic */ + apecs_pci_clr_err(); + wrmces(0x7); + mb(); + draina(); + } + else if (vector == 0x620 || vector == 0x630) { + /* Disable correctable from now on. */ + wrmces(0x1f); + mb(); + draina(); + printk("mikasa_machine_check: HW correctable (0x%lx)\n", + vector); + } + else { + printk(KERN_CRIT "APECS machine check:\n"); + printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx\n", + vector, la_ptr); + printk(KERN_CRIT + " pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", + regs->pc, mchk_header->size, mchk_header->proc_offset, + mchk_header->sys_offset); + printk(KERN_CRIT " expected %d DCSR 0x%lx PEAR 0x%lx\n", + apecs_mcheck_expected, mchk_sysdata->epic_dcsr, + mchk_sysdata->epic_pear); + + ptr = (unsigned long *)la_ptr; + for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { + printk(KERN_CRIT " +%lx %lx %lx\n", + i*sizeof(long), ptr[i], ptr[i+1]); + } +#if 0 + /* doesn't work with MILO */ + show_regs(regs); +#endif + } +} + + +/* + * The System Vector + */ + +#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO) +struct alpha_machine_vector mikasa_mv __initmv = { + vector_name: "Mikasa", + DO_EV4_MMU, + DO_DEFAULT_RTC, + DO_APECS_IO, + DO_APECS_BUS, + machine_check: mikasa_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 32, + irq_probe_mask: _PROBE_MASK(32), + update_irq_hw: mikasa_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: mikasa_device_interrupt, + + init_arch: apecs_init_arch, + init_irq: mikasa_init_irq, + init_pit: generic_init_pit, + pci_fixup: mikasa_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(mikasa) +#endif + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PRIMO) +struct alpha_machine_vector mikasa_primo_mv __initmv = { + vector_name: "Mikasa-Primo", + DO_EV5_MMU, + DO_DEFAULT_RTC, + DO_CIA_IO, + DO_CIA_BUS, + machine_check: mikasa_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 32, + irq_probe_mask: _PROBE_MASK(32), + update_irq_hw: mikasa_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: mikasa_device_interrupt, + + init_arch: cia_init_arch, + init_irq: mikasa_init_irq, + init_pit: generic_init_pit, + pci_fixup: mikasa_primo_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(mikasa_primo) +#endif diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/sys_noritake.c linux/arch/alpha/kernel/sys_noritake.c --- v2.1.115/linux/arch/alpha/kernel/sys_noritake.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/sys_noritake.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,301 @@ +/* + * linux/arch/alpha/kernel/sys_noritake.c + * + * Copyright (C) 1995 David A Rusling + * Copyright (C) 1996 Jay A Estabrook + * Copyright (C) 1998 Richard Henderson + * + * Code supporting the NORITAKE (AlphaServer 1000A), + * CORELLE (AlphaServer 800), and ALCOR Primo (AlphaStation 600A). + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "proto.h" +#include "irq.h" +#include "bios32.h" +#include "machvec.h" + + +static void +noritake_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) +{ + if (irq <= 15) + if (irq <= 7) + outb(mask, 0x21); /* ISA PIC1 */ + else + outb(mask >> 8, 0xA1); /* ISA PIC2 */ + else if (irq <= 31) + outw(~(mask >> 16), 0x54a); + else + outw(~(mask >> 32), 0x54c); +} + +static void +noritake_device_interrupt(unsigned long vector, struct pt_regs *regs) +{ + unsigned long pld; + unsigned int i; + unsigned long flags; + + save_and_cli(flags); + + /* Read the interrupt summary registers of NORITAKE */ + pld = ((unsigned long) inw(0x54c) << 32) | + ((unsigned long) inw(0x54a) << 16) | + ((unsigned long) inb(0xa0) << 8) | + ((unsigned long) inb(0x20)); + + /* + * Now for every possible bit set, work through them and call + * the appropriate interrupt handler. + */ + while (pld) { + i = ffz(~pld); + pld &= pld - 1; /* clear least bit set */ + if (i < 16) { + isa_device_interrupt(vector, regs); + } else { + handle_irq(i, i, regs); + } + } + restore_flags(flags); +} + +static void +noritake_srm_device_interrupt(unsigned long vector, struct pt_regs * regs) +{ + int irq, ack; + unsigned long flags; + + __save_and_cli(flags); + ack = irq = (vector - 0x800) >> 4; + + /* + * I really hate to do this, too, but the NORITAKE SRM console also + * reports PCI vectors *lower* than I expected from the bit numbers + * in the documentation. + * But I really don't want to change the fixup code for allocation + * of IRQs, nor the alpha_irq_mask maintenance stuff, both of which + * look nice and clean now. + * So, here's this additional grotty hack... :-( + */ + if (irq >= 16) + ack = irq = irq + 1; + + handle_irq(irq, ack, regs); + __restore_flags(flags); +} + +static void __init +noritake_init_irq(void) +{ + STANDARD_INIT_IRQ_PROLOG; + + if (alpha_using_srm) + alpha_mv.device_interrupt = noritake_srm_device_interrupt; + + outw(~(alpha_irq_mask >> 16), 0x54a); /* note invert */ + outw(~(alpha_irq_mask >> 32), 0x54c); /* note invert */ + enable_irq(2); /* enable cascade */ +} + + +/* + * PCI Fixup configuration. + * + * Summary @ 0x542, summary register #1: + * Bit Meaning + * 0 All valid ints from summary regs 2 & 3 + * 1 QLOGIC ISP1020A SCSI + * 2 Interrupt Line A from slot 0 + * 3 Interrupt Line B from slot 0 + * 4 Interrupt Line A from slot 1 + * 5 Interrupt line B from slot 1 + * 6 Interrupt Line A from slot 2 + * 7 Interrupt Line B from slot 2 + * 8 Interrupt Line A from slot 3 + * 9 Interrupt Line B from slot 3 + *10 Interrupt Line A from slot 4 + *11 Interrupt Line B from slot 4 + *12 Interrupt Line A from slot 5 + *13 Interrupt Line B from slot 5 + *14 Interrupt Line A from slot 6 + *15 Interrupt Line B from slot 6 + * + * Summary @ 0x544, summary register #2: + * Bit Meaning + * 0 OR of all unmasked ints in SR #2 + * 1 OR of secondary bus ints + * 2 Interrupt Line C from slot 0 + * 3 Interrupt Line D from slot 0 + * 4 Interrupt Line C from slot 1 + * 5 Interrupt line D from slot 1 + * 6 Interrupt Line C from slot 2 + * 7 Interrupt Line D from slot 2 + * 8 Interrupt Line C from slot 3 + * 9 Interrupt Line D from slot 3 + *10 Interrupt Line C from slot 4 + *11 Interrupt Line D from slot 4 + *12 Interrupt Line C from slot 5 + *13 Interrupt Line D from slot 5 + *14 Interrupt Line C from slot 6 + *15 Interrupt Line D from slot 6 + * + * The device to slot mapping looks like: + * + * Slot Device + * 7 Intel PCI-EISA bridge chip + * 8 DEC PCI-PCI bridge chip + * 11 PCI on board slot 0 + * 12 PCI on board slot 1 + * 13 PCI on board slot 2 + * + * + * This two layered interrupt approach means that we allocate IRQ 16 and + * above for PCI interrupts. The IRQ relates to which bit the interrupt + * comes in on. This makes interrupt processing much easier. + */ + +static int __init +noritake_map_irq(struct pci_dev *dev, int slot, int pin) +{ + static char irq_tab[15][5] __initlocaldata = { + /*INT INTA INTB INTC INTD */ + /* note: IDSELs 16, 17, and 25 are CORELLE only */ + { 16+1, 16+1, 16+1, 16+1, 16+1}, /* IdSel 16, QLOGIC */ + { -1, -1, -1, -1, -1}, /* IdSel 17, S3 Trio64 */ + { -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */ + { -1, -1, -1, -1, -1}, /* IdSel 19, PPB */ + { -1, -1, -1, -1, -1}, /* IdSel 20, ???? */ + { -1, -1, -1, -1, -1}, /* IdSel 21, ???? */ + { 16+2, 16+2, 16+3, 32+2, 32+3}, /* IdSel 22, slot 0 */ + { 16+4, 16+4, 16+5, 32+4, 32+5}, /* IdSel 23, slot 1 */ + { 16+6, 16+6, 16+7, 32+6, 32+7}, /* IdSel 24, slot 2 */ + { 16+8, 16+8, 16+9, 32+8, 32+9}, /* IdSel 25, slot 3 */ + /* The following 5 are actually on PCI bus 1, which is + across the built-in bridge of the NORITAKE only. */ + { 16+1, 16+1, 16+1, 16+1, 16+1}, /* IdSel 16, QLOGIC */ + { 16+8, 16+8, 16+9, 32+8, 32+9}, /* IdSel 17, slot 3 */ + {16+10, 16+10, 16+11, 32+10, 32+11}, /* IdSel 18, slot 4 */ + {16+12, 16+12, 16+13, 32+12, 32+13}, /* IdSel 19, slot 5 */ + {16+14, 16+14, 16+15, 32+14, 32+15}, /* IdSel 20, slot 6 */ + }; + const long min_idsel = 5, max_idsel = 19, irqs_per_slot = 5; + return COMMON_TABLE_LOOKUP; +} + +static int __init +noritake_swizzle(struct pci_dev *dev, int *pinp) +{ + int slot, pin = *pinp; + + /* Check first for the built-in bridge */ + if (PCI_SLOT(dev->bus->self->devfn) == 8) { + slot = PCI_SLOT(dev->devfn) + 15; /* WAG! */ + } + else + { + /* Must be a card-based bridge. */ + do { + if (PCI_SLOT(dev->bus->self->devfn) == 8) { + slot = PCI_SLOT(dev->devfn) + 15; + break; + } + pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)) ; + + /* Move up the chain of bridges. */ + dev = dev->bus->self; + /* Slot of the next bridge. */ + slot = PCI_SLOT(dev->devfn); + } while (dev->bus->self); + } + *pinp = pin; + return slot; +} + +static void __init +noritake_pci_fixup(void) +{ + layout_all_busses(EISA_DEFAULT_IO_BASE,APECS_AND_LCA_DEFAULT_MEM_BASE); + common_pci_fixup(noritake_map_irq, noritake_swizzle); +} + +static void __init +noritake_primo_pci_fixup(void) +{ + layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE); + common_pci_fixup(noritake_map_irq, noritake_swizzle); +} + + +/* + * The System Vectors + */ + +#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO) +struct alpha_machine_vector noritake_mv __initmv = { + vector_name: "Noritake", + DO_EV4_MMU, + DO_DEFAULT_RTC, + DO_APECS_IO, + DO_APECS_BUS, + machine_check: apecs_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 48, + irq_probe_mask: _PROBE_MASK(48), + update_irq_hw: noritake_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: noritake_device_interrupt, + + init_arch: apecs_init_arch, + init_irq: noritake_init_irq, + init_pit: generic_init_pit, + pci_fixup: noritake_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(noritake) +#endif + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PRIMO) +struct alpha_machine_vector noritake_primo_mv __initmv = { + vector_name: "Noritake-Primo", + DO_EV5_MMU, + DO_DEFAULT_RTC, + DO_CIA_IO, + DO_CIA_BUS, + machine_check: cia_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 48, + irq_probe_mask: _PROBE_MASK(48), + update_irq_hw: noritake_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: noritake_device_interrupt, + + init_arch: cia_init_arch, + init_irq: noritake_init_irq, + init_pit: generic_init_pit, + pci_fixup: noritake_primo_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(noritake_primo) +#endif diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/sys_rawhide.c linux/arch/alpha/kernel/sys_rawhide.c --- v2.1.115/linux/arch/alpha/kernel/sys_rawhide.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/sys_rawhide.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,195 @@ +/* + * linux/arch/alpha/kernel/sys_rawhide.c + * + * Copyright (C) 1995 David A Rusling + * Copyright (C) 1996 Jay A Estabrook + * Copyright (C) 1998 Richard Henderson + * + * Code supporting the RAWHIDE. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "proto.h" +#include "irq.h" +#include "bios32.h" +#include "machvec.h" + + +static void +rawhide_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) +{ + if (irq >= 40) { + /* PCI bus 1 with builtin NCR810 SCSI */ + *(vuip)MCPCIA_INT_MASK0(1) = + (~((mask) >> 40) & 0x00ffffffU) | 0x00fe0000U; + mb(); + /* ... and read it back to make sure it got written. */ + *(vuip)MCPCIA_INT_MASK0(1); + } + else if (irq >= 16) { + /* PCI bus 0 with EISA bridge */ + *(vuip)MCPCIA_INT_MASK0(0) = + (~((mask) >> 16) & 0x00ffffffU) | 0x00ff0000U; + mb(); + /* ... and read it back to make sure it got written. */ + *(vuip)MCPCIA_INT_MASK0(0); + } + else if (irq >= 8) + outb(mask >> 8, 0xA1); /* ISA PIC2 */ + else + outb(mask, 0x21); /* ISA PIC1 */ +} + +static void +rawhide_srm_device_interrupt(unsigned long vector, struct pt_regs * regs) +{ + int irq, ack; + unsigned long flags; + + __save_and_cli(flags); + ack = irq = (vector - 0x800) >> 4; + + /* + * The RAWHIDE SRM console reports PCI interrupts with a vector + * 0x80 *higher* than one might expect, as PCI IRQ 0 (ie bit 0) + * shows up as IRQ 24, etc, etc. We adjust it down by 8 to have + * it line up with the actual bit numbers from the REQ registers, + * which is how we manage the interrupts/mask. Sigh... + * + * also, PCI #1 interrupts are offset some more... :-( + */ + if (irq == 52) + ack = irq = 56; /* SCSI on PCI 1 is special */ + else { + if (irq >= 24) /* adjust all PCI interrupts down 8 */ + ack = irq = irq - 8; + if (irq >= 48) /* adjust PCI bus 1 interrupts down another 8 */ + ack = irq = irq - 8; + } + + handle_irq(irq, ack, regs); + __restore_flags(flags); +} + +static void __init +rawhide_init_irq(void) +{ + STANDARD_INIT_IRQ_PROLOG; + + /* HACK ALERT! only PCI busses 0 and 1 are used currently, + and routing is only to CPU #1*/ + + *(vuip)MCPCIA_INT_MASK0(0) = + (~((alpha_irq_mask) >> 16) & 0x00ffffffU) | 0x00ff0000U; mb(); + /* ... and read it back to make sure it got written. */ + *(vuip)MCPCIA_INT_MASK0(0); + + *(vuip)MCPCIA_INT_MASK0(1) = + (~((alpha_irq_mask) >> 40) & 0x00ffffffU) | 0x00fe0000U; mb(); + /* ... and read it back to make sure it got written. */ + *(vuip)MCPCIA_INT_MASK0(1); + + enable_irq(2); +} + +/* + * PCI Fixup configuration. + * + * Summary @ MCPCIA_PCI0_INT_REQ: + * Bit Meaning + * 0 Interrupt Line A from slot 2 PCI0 + * 1 Interrupt Line B from slot 2 PCI0 + * 2 Interrupt Line C from slot 2 PCI0 + * 3 Interrupt Line D from slot 2 PCI0 + * 4 Interrupt Line A from slot 3 PCI0 + * 5 Interrupt Line B from slot 3 PCI0 + * 6 Interrupt Line C from slot 3 PCI0 + * 7 Interrupt Line D from slot 3 PCI0 + * 8 Interrupt Line A from slot 4 PCI0 + * 9 Interrupt Line B from slot 4 PCI0 + * 10 Interrupt Line C from slot 4 PCI0 + * 11 Interrupt Line D from slot 4 PCI0 + * 12 Interrupt Line A from slot 5 PCI0 + * 13 Interrupt Line B from slot 5 PCI0 + * 14 Interrupt Line C from slot 5 PCI0 + * 15 Interrupt Line D from slot 5 PCI0 + * 16 EISA interrupt (PCI 0) or SCSI interrupt (PCI 1) + * 17-23 NA + * + * IdSel + * 1 EISA bridge (PCI bus 0 only) + * 2 PCI option slot 2 + * 3 PCI option slot 3 + * 4 PCI option slot 4 + * 5 PCI option slot 5 + * + */ + +static int __init +rawhide_map_irq(struct pci_dev *dev, int slot, int pin) +{ + static char irq_tab[5][5] __initlocaldata = { + /*INT INTA INTB INTC INTD */ + { 16+16, 16+16, 16+16, 16+16, 16+16}, /* IdSel 1 SCSI PCI 1 */ + { 16+ 0, 16+ 0, 16+ 1, 16+ 2, 16+ 3}, /* IdSel 2 slot 2 */ + { 16+ 4, 16+ 4, 16+ 5, 16+ 6, 16+ 7}, /* IdSel 3 slot 3 */ + { 16+ 8, 16+ 8, 16+ 9, 16+10, 16+11}, /* IdSel 4 slot 4 */ + { 16+12, 16+12, 16+13, 16+14, 16+15} /* IdSel 5 slot 5 */ + }; + const long min_idsel = 1, max_idsel = 5, irqs_per_slot = 5; + int irq = COMMON_TABLE_LOOKUP; + if (irq >= 0) + irq += 24 * bus2hose[dev->bus->number]->pci_hose_index; + return irq; +} + +static void __init +rawhide_pci_fixup(void) +{ + mcpcia_pci_fixup(); + common_pci_fixup(rawhide_map_irq, common_swizzle); +} + + +/* + * The System Vector + */ + +struct alpha_machine_vector rawhide_mv __initmv = { + vector_name: "Rawhide", + DO_EV5_MMU, + DO_DEFAULT_RTC, + DO_MCPCIA_IO, + DO_MCPCIA_BUS, + machine_check: mcpcia_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 64, + irq_probe_mask: _PROBE_MASK(64), + update_irq_hw: rawhide_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: rawhide_srm_device_interrupt, + + init_arch: mcpcia_init_arch, + init_irq: rawhide_init_irq, + init_pit: generic_init_pit, + pci_fixup: rawhide_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(rawhide) diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/sys_ruffian.c linux/arch/alpha/kernel/sys_ruffian.c --- v2.1.115/linux/arch/alpha/kernel/sys_ruffian.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/sys_ruffian.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,267 @@ +/* + * linux/arch/alpha/kernel/sys_ruffian.c + * + * Copyright (C) 1995 David A Rusling + * Copyright (C) 1996 Jay A Estabrook + * Copyright (C) 1998 Richard Henderson + * + * Code supporting the RUFFIAN. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "proto.h" +#include "irq.h" +#include "bios32.h" +#include "machvec.h" + + +static void +ruffian_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) +{ + if (irq >= 16) { + /* Note inverted sense of mask bits: */ + /* Make CERTAIN none of the bogus ints get enabled... */ + *(vulp)PYXIS_INT_MASK = + ~((long)mask >> 16) & 0x00000000ffffffbfUL; + mb(); + /* ... and read it back to make sure it got written. */ + *(vulp)PYXIS_INT_MASK; + } + else if (irq >= 8) + outb(mask >> 8, 0xA1); /* ISA PIC2 */ + else + outb(mask, 0x21); /* ISA PIC1 */ +} + +static void +ruffian_ack_irq(unsigned long irq) +{ + if (irq < 16) { + /* Ack PYXIS ISA interrupt. */ + *(vulp)PYXIS_INT_REQ = 1L << 7; mb(); + /* ... and read it back to make sure it got written. */ + *(vulp)PYXIS_INT_REQ; + if (irq > 7) { + outb(0x20, 0xa0); + } + outb(0x20, 0x20); + } else { + /* Ack PYXIS PCI interrupt. */ + *(vulp)PYXIS_INT_REQ = (1UL << (irq - 16)); + /* ... and read it back to make sure it got written. */ + *(vulp)PYXIS_INT_REQ; + } +} + +static void +ruffian_device_interrupt(unsigned long vector, struct pt_regs *regs) +{ + unsigned long pld; + unsigned int i; + unsigned long flags; + + save_and_cli(flags); + + /* Read the interrupt summary register of PYXIS */ + pld = *(vulp)PYXIS_INT_REQ; + + /* For now, AND off any bits we are not interested in: + * HALT (2), timer (6), ISA Bridge (7), 21142 (8) + * then all the PCI slots/INTXs (12-31) + * flash(5) :DWH: + */ + pld &= 0x00000000ffffff9fUL; /* was ffff7f */ + + /* + * Now for every possible bit set, work through them and call + * the appropriate interrupt handler. + */ + while (pld) { + i = ffz(~pld); + pld &= pld - 1; /* clear least bit set */ + if (i == 7) { + /* Copy this bit from isa_device_interrupt cause + we need to hook into int 0 for the timer. I + refuse to soil device_interrupt with ifdefs. */ + + /* Generate a PCI interrupt acknowledge cycle. + The PIC will respond with the interrupt + vector of the highest priority interrupt + that is pending. The PALcode sets up the + interrupts vectors such that irq level L + generates vector L. */ + + unsigned int j = *(vuip)PYXIS_IACK_SC & 0xff; + if (j == 7 && !(inb(0x20) & 0x80)) { + /* It's only a passive release... */ + } else if (j == 0) { + timer_interrupt(regs); + ruffian_ack_irq(0); + } else { + handle_irq(j, j, regs); + } + } else { + /* if not timer int */ + handle_irq(16 + i, 16 + i, regs); + } + + *(vulp)PYXIS_INT_REQ = 1UL << i; mb(); + *(vulp)PYXIS_INT_REQ; /* read to force the write */ + } + restore_flags(flags); +} + +static void __init +ruffian_init_irq(void) +{ + STANDARD_INIT_IRQ_PROLOG; + + /* Invert 6&7 for i82371 */ + *(vulp)PYXIS_INT_HILO = 0x000000c0UL; mb(); + *(vulp)PYXIS_INT_CNFG = 0x00002064UL; mb(); /* all clear */ + *(vulp)PYXIS_INT_MASK = 0x00000000UL; mb(); + *(vulp)PYXIS_INT_REQ = 0xffffffffUL; mb(); + + outb(0x11,0xA0); + outb(0x08,0xA1); + outb(0x02,0xA1); + outb(0x01,0xA1); + outb(0xFF,0xA1); + + outb(0x11,0x20); + outb(0x00,0x21); + outb(0x04,0x21); + outb(0x01,0x21); + outb(0xFF,0x21); + + /* Send -INTA pulses to clear any pending interrupts ...*/ + *(vuip) PYXIS_IACK_SC; + + /* Finish writing the 82C59A PIC Operation Control Words */ + outb(0x20,0xA0); + outb(0x20,0x20); + + /* Turn on the interrupt controller, the timer interrupt */ + enable_irq(16 + 7); /* enable ISA PIC cascade */ + enable_irq(0); /* enable timer */ + enable_irq(2); /* enable 2nd PIC cascade */ +} + + +/* + * For RUFFIAN, we do not want to make any modifications to the PCI + * setup. So just scan the busses. + */ + +static void __init +ruffian_pci_fixup(void) +{ + layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); +} + + +/* + * The DeskStation Ruffian motherboard firmware does not place + * the memory size in the PALimpure area. Therefore, we use + * the Bank Configuration Registers in PYXIS to obtain the size. + */ +static unsigned long __init +ruffian_get_bank_size(unsigned long offset) +{ + unsigned long bank_addr, bank, ret = 0; + + /* Valid offsets are: 0x800, 0x840 and 0x880 + since Ruffian only uses three banks. */ + bank_addr = (unsigned long)PYXIS_MCR + offset; + bank = *(vulp)bank_addr; + + /* Check BANK_ENABLE */ + if (bank & 0x01) { + static unsigned long size[] __initdata = { + 0x40000000UL, /* 0x00, 1G */ + 0x20000000UL, /* 0x02, 512M */ + 0x10000000UL, /* 0x04, 256M */ + 0x08000000UL, /* 0x06, 128M */ + 0x04000000UL, /* 0x08, 64M */ + 0x02000000UL, /* 0x0a, 32M */ + 0x01000000UL, /* 0x0c, 16M */ + 0x00800000UL, /* 0x0e, 8M */ + 0x80000000UL, /* 0x10, 2G */ + }; + + bank = (bank & 0x1e) >> 1; + if (bank < sizeof(size)/sizeof(*size)) + ret = size[bank]; + } + + return ret; +} + +static void __init +ruffian_init_arch(unsigned long *mem_start, unsigned long *mem_end) +{ + /* FIXME: What do we do with ruffian_get_bank_size above? */ + + pyxis_enable_errors(); + if (!pyxis_srm_window_setup()) { + printk("ruffian_init_arch: Skipping window register rewrites." + "\n... Trust DeskStation firmware!\n"); + } + pyxis_finish_init_arch(); +} + + +static void +ruffian_init_pit (void) +{ + /* Ruffian depends on the system timer established in MILO! */ + request_region(0x70, 0x10, "timer"); + init_pit_rest(); +} + + +/* + * The System Vector + */ + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_RUFFIAN) +struct alpha_machine_vector ruffian_mv __initmv = { + vector_name: "Ruffian", + DO_EV5_MMU, + DO_DEFAULT_RTC, + DO_PYXIS_IO, + DO_PYXIS_BUS, + machine_check: pyxis_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 48, + irq_probe_mask: RUFFIAN_PROBE_MASK, + update_irq_hw: ruffian_update_irq_hw, + ack_irq: ruffian_ack_irq, + device_interrupt: ruffian_device_interrupt, + + init_arch: ruffian_init_arch, + init_irq: ruffian_init_irq, + init_pit: ruffian_init_pit, + pci_fixup: ruffian_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(ruffian) +#endif diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/sys_sable.c linux/arch/alpha/kernel/sys_sable.c --- v2.1.115/linux/arch/alpha/kernel/sys_sable.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/sys_sable.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,297 @@ +/* + * linux/arch/alpha/kernel/sys_sable.c + * + * Copyright (C) 1995 David A Rusling + * Copyright (C) 1996 Jay A Estabrook + * Copyright (C) 1998 Richard Henderson + * + * Code supporting the Sable and Sable-Gamma systems. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "proto.h" +#include "irq.h" +#include "bios32.h" +#include "machvec.h" + + +/* + * For SABLE, which is really baroque, we manage 40 IRQ's, but the + * hardware really only supports 24, not via normal ISA PIC, + * but cascaded custom 8259's, etc. + * 0-7 (char at 536) + * 8-15 (char at 53a) + * 16-23 (char at 53c) + */ + +/* Note that the vector reported by the SRM PALcode corresponds to the + interrupt mask bits, but we have to manage via more normal IRQs. */ + +static struct +{ + char irq_to_mask[40]; + char mask_to_irq[40]; + unsigned long shadow_mask; +} sable_irq_swizzle = { + { + -1, 6, -1, 8, 15, 12, 7, 9, /* pseudo PIC 0-7 */ + -1, 16, 17, 18, 3, -1, 21, 22, /* pseudo PIC 8-15 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 0-7 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 8-15 */ + 2, 1, 0, 4, 5, -1, -1, -1, /* pseudo PCI */ + }, + { + 34, 33, 32, 12, 35, 36, 1, 6, /* mask 0-7 */ + 3, 7, -1, -1, 5, -1, -1, 4, /* mask 8-15 */ + 9, 10, 11, -1, -1, 14, 15, -1, /* mask 16-23 */ + }, + 0 +}; + + +static void +sable_update_irq_hw(unsigned long irq, unsigned long unused_mask, int unmask_p) +{ + unsigned long bit, mask; + + /* The "irq" argument is really the irq, but we need it to + be the mask bit number. Convert it now. */ + + irq = sable_irq_swizzle.irq_to_mask[irq]; + bit = 1UL << irq; + mask = sable_irq_swizzle.shadow_mask | bit; + if (unmask_p) + mask &= ~bit; + sable_irq_swizzle.shadow_mask = mask; + + /* The "irq" argument is now really the mask bit number. */ + if (irq <= 7) + outb(mask, 0x537); + else if (irq <= 15) + outb(mask >> 8, 0x53b); + else + outb(mask >> 16, 0x53d); +} + +static void +sable_ack_irq(unsigned long irq) +{ + /* Note that the "irq" here is really the mask bit number */ + switch (irq) { + case 0 ... 7: + outb(0xE0 | (irq - 0), 0x536); + outb(0xE0 | 1, 0x534); /* slave 0 */ + break; + case 8 ... 15: + outb(0xE0 | (irq - 8), 0x53a); + outb(0xE0 | 3, 0x534); /* slave 1 */ + break; + case 16 ... 24: + outb(0xE0 | (irq - 16), 0x53c); + outb(0xE0 | 4, 0x534); /* slave 2 */ + break; + } +} + +static void +sable_srm_device_interrupt(unsigned long vector, struct pt_regs * regs) +{ + /* Note that the vector reported by the SRM PALcode corresponds + to the interrupt mask bits, but we have to manage via more + normal IRQs. */ + + int irq, ack; + unsigned long flags; + + __save_and_cli(flags); + ack = irq = (vector - 0x800) >> 4; + + irq = sable_irq_swizzle.mask_to_irq[(ack)]; +#if 0 + if (irq == 5 || irq == 9 || irq == 10 || irq == 11 || + irq == 14 || irq == 15) + printk("srm_device_interrupt: vector=0x%lx ack=0x%x" + " irq=0x%x\n", vector, ack, irq); +#endif + + handle_irq(irq, ack, regs); + __restore_flags(flags); +} + +static void __init +sable_init_irq(void) +{ + STANDARD_INIT_IRQ_PROLOG; + + outb(alpha_irq_mask , 0x537); /* slave 0 */ + outb(alpha_irq_mask >> 8, 0x53b); /* slave 1 */ + outb(alpha_irq_mask >> 16, 0x53d); /* slave 2 */ + outb(0x44, 0x535); /* enable cascades in master */ +} + + +/* + * PCI Fixup configuration for ALPHA SABLE (2100) - 2100A is different ?? + * + * Summary Registers (536/53a/53c): + * Bit Meaning + *----------------- + * 0 PCI slot 0 + * 1 NCR810 (builtin) + * 2 TULIP (builtin) + * 3 mouse + * 4 PCI slot 1 + * 5 PCI slot 2 + * 6 keyboard + * 7 floppy + * 8 COM2 + * 9 parallel port + *10 EISA irq 3 + *11 EISA irq 4 + *12 EISA irq 5 + *13 EISA irq 6 + *14 EISA irq 7 + *15 COM1 + *16 EISA irq 9 + *17 EISA irq 10 + *18 EISA irq 11 + *19 EISA irq 12 + *20 EISA irq 13 + *21 EISA irq 14 + *22 NC + *23 IIC + * + * The device to slot mapping looks like: + * + * Slot Device + * 0 TULIP + * 1 SCSI + * 2 PCI-EISA bridge + * 3 none + * 4 none + * 5 none + * 6 PCI on board slot 0 + * 7 PCI on board slot 1 + * 8 PCI on board slot 2 + * + * + * This two layered interrupt approach means that we allocate IRQ 16 and + * above for PCI interrupts. The IRQ relates to which bit the interrupt + * comes in on. This makes interrupt processing much easier. + */ +/* + * NOTE: the IRQ assignments below are arbitrary, but need to be consistent + * with the values in the irq swizzling tables above. + */ + +static int __init +sable_map_irq(struct pci_dev *dev, int slot, int pin) +{ + static char irq_tab[9][5] __initlocaldata = { + /*INT INTA INTB INTC INTD */ + { 32+0, 32+0, 32+0, 32+0, 32+0}, /* IdSel 0, TULIP */ + { 32+1, 32+1, 32+1, 32+1, 32+1}, /* IdSel 1, SCSI */ + { -1, -1, -1, -1, -1}, /* IdSel 2, SIO */ + { -1, -1, -1, -1, -1}, /* IdSel 3, none */ + { -1, -1, -1, -1, -1}, /* IdSel 4, none */ + { -1, -1, -1, -1, -1}, /* IdSel 5, none */ + { 32+2, 32+2, 32+2, 32+2, 32+2}, /* IdSel 6, slot 0 */ + { 32+3, 32+3, 32+3, 32+3, 32+3}, /* IdSel 7, slot 1 */ + { 32+4, 32+4, 32+4, 32+4, 32+4}, /* IdSel 8, slot 2 */ + }; + const long min_idsel = 0, max_idsel = 8, irqs_per_slot = 5; + return COMMON_TABLE_LOOKUP; +} + +void __init +sable_pci_fixup(void) +{ + layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE); + common_pci_fixup(sable_map_irq, common_swizzle); +} + + +/* + * The System Vectors + * + * In order that T2_HAE_ADDRESS should be a constant, we play + * these games with GAMMA_BIAS. + */ + +#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_GAMMA) +#undef GAMMA_BIAS +#define GAMMA_BIAS 0 +struct alpha_machine_vector sable_mv __initmv = { + vector_name: "Sable", + DO_EV4_MMU, + DO_DEFAULT_RTC, + DO_T2_IO, + DO_T2_BUS, + machine_check: t2_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 40, + irq_probe_mask: _PROBE_MASK(40), + update_irq_hw: sable_update_irq_hw, + ack_irq: sable_ack_irq, + device_interrupt: sable_srm_device_interrupt, + + init_arch: t2_init_arch, + init_irq: sable_init_irq, + init_pit: generic_init_pit, + pci_fixup: sable_pci_fixup, + kill_arch: generic_kill_arch, + + sys: { t2: { + gamma_bias: 0 + } } +}; +ALIAS_MV(sable) +#endif + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_GAMMA) +#undef GAMMA_BIAS +#define GAMMA_BIAS _GAMMA_BIAS +struct alpha_machine_vector sable_gamma_mv __initmv = { + vector_name: "Sable-Gamma", + DO_EV5_MMU, + DO_DEFAULT_RTC, + DO_T2_IO, + DO_T2_BUS, + machine_check: t2_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 40, + irq_probe_mask: _PROBE_MASK(40), + update_irq_hw: sable_update_irq_hw, + ack_irq: sable_ack_irq, + device_interrupt: sable_srm_device_interrupt, + + init_arch: t2_init_arch, + init_irq: sable_init_irq, + init_pit: generic_init_pit, + pci_fixup: sable_pci_fixup, + kill_arch: generic_kill_arch, + + sys: { t2: { + gamma_bias: _GAMMA_BIAS + } } +}; +ALIAS_MV(sable_gamma) +#endif diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/sys_sio.c linux/arch/alpha/kernel/sys_sio.c --- v2.1.115/linux/arch/alpha/kernel/sys_sio.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/sys_sio.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,470 @@ +/* + * linux/arch/alpha/kernel/sys_sio.c + * + * Copyright (C) 1995 David A Rusling + * Copyright (C) 1996 Jay A Estabrook + * Copyright (C) 1998 Richard Henderson + * + * Code for all boards that route the PCI interrupts through the SIO + * PCI/ISA bridge. This includes Noname (AXPpci33), Multia (UDB), + * Kenetics's Platform 2000, Avanti (AlphaStation), XL, and AlphaBook1. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "proto.h" +#include "irq.h" +#include "bios32.h" +#include "machvec.h" + +static void +sio_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) +{ + if (irq >= 8) + outb(mask >> 8, 0xA1); + else + outb(mask, 0x21); +} + +static void __init +sio_init_irq(void) +{ + STANDARD_INIT_IRQ_PROLOG; + + if (alpha_using_srm) + alpha_mv.device_interrupt = srm_device_interrupt; + + enable_irq(2); /* enable cascade */ +} + +static inline void __init +xl_init_arch(unsigned long *mem_start, unsigned long *mem_end) +{ + /* + * Set up the PCI->physical memory translation windows. For + * the XL we *must* use both windows, in order to maximize the + * amount of physical memory that can be used to DMA from the + * ISA bus, and still allow PCI bus devices access to all of + * host memory. + * + * See for window bases and sizes. + * + * This restriction due to the true XL motherboards' 82379AB SIO + * PCI<->ISA bridge chip which passes only 27 bits of address... + */ + + *(vuip)APECS_IOC_PB1R = 1<<19 | (APECS_XL_DMA_WIN1_BASE & 0xfff00000U); + *(vuip)APECS_IOC_PM1R = (APECS_XL_DMA_WIN1_SIZE - 1) & 0xfff00000U; + *(vuip)APECS_IOC_TB1R = 0; + + *(vuip)APECS_IOC_PB2R = 1<<19 | (APECS_XL_DMA_WIN2_BASE & 0xfff00000U); + *(vuip)APECS_IOC_PM2R = (APECS_XL_DMA_WIN2_SIZE - 1) & 0xfff00000U; + *(vuip)APECS_IOC_TB2R = 0; + + /* + * Finally, clear the HAXR2 register, which gets used for PCI + * Config Space accesses. That is the way we want to use it, + * and we do not want to depend on what ARC or SRM might have + * left behind... + */ + + *(vuip)APECS_IOC_HAXR2 = 0; mb(); +} + +static inline void __init +alphabook1_init_arch(unsigned long *mem_start, unsigned long *mem_end) +{ + /* The AlphaBook1 has LCD video fixed at 800x600, + 37 rows and 100 cols. */ + screen_info.orig_y = 37; + screen_info.orig_video_cols = 100; + screen_info.orig_video_lines = 37; + + lca_init_arch(mem_start, mem_end); +} + + +/* + * sio_route_tab selects irq routing in PCI/ISA bridge so that: + * PIRQ0 -> irq 15 + * PIRQ1 -> irq 9 + * PIRQ2 -> irq 10 + * PIRQ3 -> irq 11 + * + * This probably ought to be configurable via MILO. For + * example, sound boards seem to like using IRQ 9. + */ +static unsigned long sio_route_tab __initdata = 0; + +static void __init +sio_pci_fixup(int (*map_irq)(struct pci_dev *dev, int sel, int pin), + unsigned long new_route_tab) +{ + unsigned int route_tab; + + /* Examine or update the PCI routing table. */ + pcibios_read_config_dword(0, PCI_DEVFN(7, 0), 0x60, &route_tab); + + sio_route_tab = route_tab; + if (PCI_MODIFY) { + sio_route_tab = new_route_tab; + pcibios_write_config_dword(0, PCI_DEVFN(7, 0), 0x60, + new_route_tab); + } + + /* Update all the IRQs. */ + common_pci_fixup(map_irq, common_swizzle); +} + +static unsigned int __init +sio_collect_irq_levels(void) +{ + unsigned int level_bits = 0; + struct pci_dev *dev; + + /* Iterate through the devices, collecting IRQ levels. */ + for (dev = pci_devices; dev; dev = dev->next) { + if ((dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) && + (dev->class >> 8 != PCI_CLASS_BRIDGE_PCMCIA)) + continue; + + if (dev->irq) + level_bits |= (1 << dev->irq); + } + return level_bits; +} + +static void __init +sio_fixup_irq_levels(unsigned int level_bits) +{ + unsigned int old_level_bits; + + /* + * Now, make all PCI interrupts level sensitive. Notice: + * these registers must be accessed byte-wise. inw()/outw() + * don't work. + * + * Make sure to turn off any level bits set for IRQs 9,10,11,15, + * so that the only bits getting set are for devices actually found. + * Note that we do preserve the remainder of the bits, which we hope + * will be set correctly by ARC/SRM. + * + * Note: we at least preserve any level-set bits on AlphaBook1 + */ + old_level_bits = inb(0x4d0) | (inb(0x4d1) << 8); + + level_bits |= (old_level_bits & 0x71ff); + + outb((level_bits >> 0) & 0xff, 0x4d0); + outb((level_bits >> 8) & 0xff, 0x4d1); +} + +static inline int __init +noname_map_irq(struct pci_dev *dev, int slot, int pin) +{ + /* + * The Noname board has 5 PCI slots with each of the 4 + * interrupt pins routed to different pins on the PCI/ISA + * bridge (PIRQ0-PIRQ3). The table below is based on + * information available at: + * + * http://ftp.digital.com/pub/DEC/axppci/ref_interrupts.txt + * + * I have no information on the Avanti interrupt routing, but + * the routing seems to be identical to the Noname except + * that the Avanti has an additional slot whose routing I'm + * unsure of. + * + * pirq_tab[0] is a fake entry to deal with old PCI boards + * that have the interrupt pin number hardwired to 0 (meaning + * that they use the default INTA line, if they are interrupt + * driven at all). + */ + static char irq_tab[][5] __initlocaldata = { + /*INT A B C D */ + { 3, 3, 3, 3, 3}, /* idsel 6 (53c810) */ + {-1, -1, -1, -1, -1}, /* idsel 7 (SIO: PCI/ISA bridge) */ + { 2, 2, -1, -1, -1}, /* idsel 8 (Hack: slot closest ISA) */ + {-1, -1, -1, -1, -1}, /* idsel 9 (unused) */ + {-1, -1, -1, -1, -1}, /* idsel 10 (unused) */ + { 0, 0, 2, 1, 0}, /* idsel 11 KN25_PCI_SLOT0 */ + { 1, 1, 0, 2, 1}, /* idsel 12 KN25_PCI_SLOT1 */ + { 2, 2, 1, 0, 2}, /* idsel 13 KN25_PCI_SLOT2 */ + { 0, 0, 0, 0, 0}, /* idsel 14 AS255 TULIP */ + }; + const long min_idsel = 6, max_idsel = 14, irqs_per_slot = 5; + int irq = COMMON_TABLE_LOOKUP, tmp; + tmp = __kernel_extbl(sio_route_tab, irq); + return irq >= 0 ? tmp : -1; +} + +static inline void __init +noname_pci_fixup(void) +{ + /* + * For UDB, the only available PCI slot must not map to IRQ 9, + * since that's the builtin MSS sound chip. That PCI slot + * will map to PIRQ1 (for INTA at least), so we give it IRQ 15 + * instead. + * + * Unfortunately we have to do this for NONAME as well, since + * they are co-indicated when the platform type "Noname" is + * selected... :-( + */ + layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE); + sio_pci_fixup(noname_map_irq, 0x0b0a0f09); + sio_fixup_irq_levels(sio_collect_irq_levels()); + enable_ide(0x26e); +} + +static inline void __init +avanti_pci_fixup(void) +{ + layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE); + sio_pci_fixup(noname_map_irq, 0x0b0a090f); + sio_fixup_irq_levels(sio_collect_irq_levels()); + enable_ide(0x26e); +} + +static inline void __init +xl_pci_fixup(void) +{ + layout_all_busses(DEFAULT_IO_BASE, XL_DEFAULT_MEM_BASE); + sio_pci_fixup(noname_map_irq, 0x0b0a090f); + sio_fixup_irq_levels(sio_collect_irq_levels()); + enable_ide(0x26e); +} + +static inline int __init +p2k_map_irq(struct pci_dev *dev, int slot, int pin) +{ + static char irq_tab[][5] __initlocaldata = { + /*INT A B C D */ + { 0, 0, -1, -1, -1}, /* idsel 6 (53c810) */ + {-1, -1, -1, -1, -1}, /* idsel 7 (SIO: PCI/ISA bridge) */ + { 1, 1, 2, 3, 0}, /* idsel 8 (slot A) */ + { 2, 2, 3, 0, 1}, /* idsel 9 (slot B) */ + {-1, -1, -1, -1, -1}, /* idsel 10 (unused) */ + {-1, -1, -1, -1, -1}, /* idsel 11 (unused) */ + { 3, 3, -1, -1, -1}, /* idsel 12 (CMD0646) */ + }; + const long min_idsel = 6, max_idsel = 12, irqs_per_slot = 5; + int irq = COMMON_TABLE_LOOKUP, tmp; + tmp = __kernel_extbl(sio_route_tab, irq); + return irq >= 0 ? tmp : -1; +} + +static inline void __init +p2k_pci_fixup(void) +{ + layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE); + sio_pci_fixup(p2k_map_irq, 0x0b0a090f); + sio_fixup_irq_levels(sio_collect_irq_levels()); + enable_ide(0x26e); +} + +static inline void __init +alphabook1_pci_fixup(void) +{ + struct pci_dev *dev; + unsigned char orig, config; + + layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE); + + /* For the AlphaBook1, NCR810 SCSI is 14, PCMCIA controller is 15. */ + sio_pci_fixup(noname_map_irq, 0x0e0f0a0a); + + /* + * On the AlphaBook1, the PCMCIA chip (Cirrus 6729) + * is sensitive to PCI bus bursts, so we must DISABLE + * burst mode for the NCR 8xx SCSI... :-( + * + * Note that the NCR810 SCSI driver must preserve the + * setting of the bit in order for this to work. At the + * moment (2.0.29), ncr53c8xx.c does NOT do this, but + * 53c7,8xx.c DOES. + */ + for (dev = pci_devices; dev; dev = dev->next) { + if (dev->vendor == PCI_VENDOR_ID_NCR && + (dev->device == PCI_DEVICE_ID_NCR_53C810 || + dev->device == PCI_DEVICE_ID_NCR_53C815 || + dev->device == PCI_DEVICE_ID_NCR_53C820 || + dev->device == PCI_DEVICE_ID_NCR_53C825)) { + unsigned int io_port; + unsigned char ctest4; + + pcibios_read_config_dword(dev->bus->number, + dev->devfn, + PCI_BASE_ADDRESS_0, + &io_port); + io_port &= PCI_BASE_ADDRESS_IO_MASK; + ctest4 = inb(io_port+0x21); + if (!(ctest4 & 0x80)) { + printk("AlphaBook1 NCR init: setting" + " burst disable\n"); + outb(ctest4 | 0x80, io_port+0x21); + } + } + } + + /* Do not set *ANY* level triggers for AlphaBook1. */ + sio_fixup_irq_levels(0); + + /* Make sure that register PR1 indicates 1Mb mem */ + outb(0x0f, 0x3ce); orig = inb(0x3cf); /* read PR5 */ + outb(0x0f, 0x3ce); outb(0x05, 0x3cf); /* unlock PR0-4 */ + outb(0x0b, 0x3ce); config = inb(0x3cf); /* read PR1 */ + if ((config & 0xc0) != 0xc0) { + printk("AlphaBook1 VGA init: setting 1Mb memory\n"); + config |= 0xc0; + outb(0x0b, 0x3ce); outb(config, 0x3cf); /* write PR1 */ + } + outb(0x0f, 0x3ce); outb(orig, 0x3cf); /* (re)lock PR0-4 */ +} + + +/* + * The System Vectors + */ + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_BOOK1) +struct alpha_machine_vector alphabook1_mv __initmv = { + vector_name: "AlphaBook1", + DO_EV4_MMU, + DO_DEFAULT_RTC, + DO_LCA_IO, + DO_LCA_BUS, + machine_check: lca_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 16, + irq_probe_mask: _PROBE_MASK(16), + update_irq_hw: sio_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: isa_device_interrupt, + + init_arch: alphabook1_init_arch, + init_irq: sio_init_irq, + init_pit: generic_init_pit, + pci_fixup: alphabook1_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(alphabook1) +#endif + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_AVANTI) +struct alpha_machine_vector avanti_mv __initmv = { + vector_name: "Avanti", + DO_EV4_MMU, + DO_DEFAULT_RTC, + DO_APECS_IO, + DO_APECS_BUS, + machine_check: apecs_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 16, + irq_probe_mask: _PROBE_MASK(16), + update_irq_hw: sio_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: isa_device_interrupt, + + init_arch: apecs_init_arch, + init_irq: sio_init_irq, + init_pit: generic_init_pit, + pci_fixup: avanti_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(avanti) +#endif + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_NONAME) +struct alpha_machine_vector noname_mv __initmv = { + vector_name: "Noname", + DO_EV4_MMU, + DO_DEFAULT_RTC, + DO_LCA_IO, + DO_LCA_BUS, + machine_check: lca_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 16, + irq_probe_mask: _PROBE_MASK(16), + update_irq_hw: sio_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: srm_device_interrupt, + + init_arch: lca_init_arch, + init_irq: sio_init_irq, + init_pit: generic_init_pit, + pci_fixup: noname_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(noname) +#endif + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_P2K) +struct alpha_machine_vector p2k_mv __initmv = { + vector_name: "Platform2000", + DO_EV4_MMU, + DO_DEFAULT_RTC, + DO_LCA_IO, + DO_LCA_BUS, + machine_check: lca_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 16, + irq_probe_mask: P2K_PROBE_MASK, + update_irq_hw: sio_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: srm_device_interrupt, + + init_arch: lca_init_arch, + init_irq: sio_init_irq, + init_pit: generic_init_pit, + pci_fixup: p2k_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(p2k) +#endif + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_XL) +struct alpha_machine_vector xl_mv __initmv = { + vector_name: "XL", + DO_EV4_MMU, + DO_DEFAULT_RTC, + DO_APECS_IO, + BUS(apecs_xl), + machine_check: apecs_machine_check, + max_dma_address: ALPHA_XL_MAX_DMA_ADDRESS, + + nr_irqs: 16, + irq_probe_mask: _PROBE_MASK(16), + update_irq_hw: sio_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: isa_device_interrupt, + + init_arch: xl_init_arch, + init_irq: sio_init_irq, + init_pit: generic_init_pit, + pci_fixup: xl_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(xl) +#endif diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/sys_sx164.c linux/arch/alpha/kernel/sys_sx164.c --- v2.1.115/linux/arch/alpha/kernel/sys_sx164.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/sys_sx164.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,217 @@ +/* + * linux/arch/alpha/kernel/sys_sx164.c + * + * Copyright (C) 1995 David A Rusling + * Copyright (C) 1996 Jay A Estabrook + * Copyright (C) 1998 Richard Henderson + * + * Code supporting the SX164 (PCA56+PYXIS). + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "proto.h" +#include "irq.h" +#include "bios32.h" +#include "machvec.h" + + +static void +sx164_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) +{ + if (irq >= 16) { + /* Make CERTAIN none of the bogus ints get enabled */ + *(vulp)PYXIS_INT_MASK = + ~((long)mask >> 16) & ~0x000000000000003bUL; + mb(); + /* ... and read it back to make sure it got written. */ + *(vulp)PYXIS_INT_MASK; + } + else if (irq >= 8) + outb(mask >> 8, 0xA1); /* ISA PIC2 */ + else + outb(mask, 0x21); /* ISA PIC1 */ +} + +static void +sx164_srm_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p) +{ + if (irq >= 16) { + if (unmask_p) + cserve_ena(irq - 16); + else + cserve_dis(irq - 16); + } + else if (irq >= 8) + outb(mask >> 8, 0xA1); /* ISA PIC2 */ + else + outb(mask, 0x21); /* ISA PIC1 */ +} + +static void +sx164_device_interrupt(unsigned long vector, struct pt_regs *regs) +{ + unsigned long pld, tmp; + unsigned int i; + unsigned long flags; + + save_and_cli(flags); + + /* Read the interrupt summary register of PYXIS */ + pld = *(vulp)PYXIS_INT_REQ; + + /* + * For now, AND off any bits we are not interested in: + * HALT (2), timer (6), ISA Bridge (7) + * then all the PCI slots/INTXs (8-23) + */ + /* Maybe HALT should only be used for SRM console boots? */ + pld &= 0x0000000000ffffc0UL; + + /* + * Now for every possible bit set, work through them and call + * the appropriate interrupt handler. + */ + while (pld) { + i = ffz(~pld); + pld &= pld - 1; /* clear least bit set */ + if (i == 7) { + isa_device_interrupt(vector, regs); + } else if (i == 6) { + continue; + } else { + /* if not timer int */ + handle_irq(16 + i, 16 + i, regs); + } + *(vulp)PYXIS_INT_REQ = 1UL << i; mb(); + tmp = *(vulp)PYXIS_INT_REQ; + } + restore_flags(flags); +} + +static void +sx164_init_irq(void) +{ + outb(0, DMA1_RESET_REG); + outb(0, DMA2_RESET_REG); + + if (alpha_using_srm) { + alpha_mv.update_irq_hw = sx164_srm_update_irq_hw; + alpha_mv.device_interrupt = srm_device_interrupt; + } + else { + /* Note invert on MASK bits. */ + *(vulp)PYXIS_INT_MASK = ~((long)alpha_irq_mask >> 16); + mb(); + *(vulp)PYXIS_INT_MASK; + } + + enable_irq(16 + 6); /* enable timer */ + enable_irq(16 + 7); /* enable ISA PIC cascade */ + enable_irq(2); /* enable cascade */ +} + +/* + * PCI Fixup configuration. + * + * Summary @ PYXIS_INT_REQ: + * Bit Meaning + * 0 RSVD + * 1 NMI + * 2 Halt/Reset switch + * 3 MBZ + * 4 RAZ + * 5 RAZ + * 6 Interval timer (RTC) + * 7 PCI-ISA Bridge + * 8 Interrupt Line A from slot 3 + * 9 Interrupt Line A from slot 2 + *10 Interrupt Line A from slot 1 + *11 Interrupt Line A from slot 0 + *12 Interrupt Line B from slot 3 + *13 Interrupt Line B from slot 2 + *14 Interrupt Line B from slot 1 + *15 Interrupt line B from slot 0 + *16 Interrupt Line C from slot 3 + *17 Interrupt Line C from slot 2 + *18 Interrupt Line C from slot 1 + *19 Interrupt Line C from slot 0 + *20 Interrupt Line D from slot 3 + *21 Interrupt Line D from slot 2 + *22 Interrupt Line D from slot 1 + *23 Interrupt Line D from slot 0 + * + * IdSel + * 5 32 bit PCI option slot 2 + * 6 64 bit PCI option slot 0 + * 7 64 bit PCI option slot 1 + * 8 Cypress I/O + * 9 32 bit PCI option slot 3 + * + */ + +static int __init +sx164_map_irq(struct pci_dev *dev, int slot, int pin) +{ + static char irq_tab[5][5] __initlocaldata = { + /*INT INTA INTB INTC INTD */ + { 16+ 9, 16+ 9, 16+13, 16+17, 16+21}, /* IdSel 5 slot 2 J17 */ + { 16+11, 16+11, 16+15, 16+19, 16+23}, /* IdSel 6 slot 0 J19 */ + { 16+10, 16+10, 16+14, 16+18, 16+22}, /* IdSel 7 slot 1 J18 */ + { -1, -1, -1, -1, -1}, /* IdSel 8 SIO */ + { 16+ 8, 16+ 8, 16+12, 16+16, 16+20} /* IdSel 9 slot 3 J15 */ + }; + const long min_idsel = 5, max_idsel = 9, irqs_per_slot = 5; + return COMMON_TABLE_LOOKUP; +} + +void __init +sx164_pci_fixup(void) +{ + layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); + common_pci_fixup(sx164_map_irq, common_swizzle); + SMC669_Init(); +} + + +/* + * The System Vector + */ + +struct alpha_machine_vector sx164_mv __initmv = { + vector_name: "SX164", + DO_EV5_MMU, + DO_DEFAULT_RTC, + DO_PYXIS_IO, + DO_PYXIS_BUS, + machine_check: pyxis_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 40, + irq_probe_mask: _PROBE_MASK(40), + update_irq_hw: sx164_update_irq_hw, + ack_irq: generic_ack_irq, + device_interrupt: sx164_device_interrupt, + + init_arch: pyxis_init_arch, + init_irq: sx164_init_irq, + init_pit: generic_init_pit, + pci_fixup: sx164_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(sx164) diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/sys_takara.c linux/arch/alpha/kernel/sys_takara.c --- v2.1.115/linux/arch/alpha/kernel/sys_takara.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/sys_takara.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,165 @@ +/* + * linux/arch/alpha/kernel/sys_takara.c + * + * Copyright (C) 1995 David A Rusling + * Copyright (C) 1996 Jay A Estabrook + * Copyright (C) 1998 Richard Henderson + * + * Code supporting the TAKARA. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "proto.h" +#include "irq.h" +#include "bios32.h" +#include "machvec.h" + + +/* + * WARNING WARNING WARNING + * + * This port is missing an update_irq_hw implementation. + */ + +static void +takara_device_interrupt(unsigned long vector, struct pt_regs *regs) +{ + unsigned long flags; + unsigned intstatus; + + save_and_cli(flags); + + /* + * The PALcode will have passed us vectors 0x800 or 0x810, + * which are fairly arbitrary values and serve only to tell + * us whether an interrupt has come in on IRQ0 or IRQ1. If + * it's IRQ1 it's a PCI interrupt; if it's IRQ0, it's + * probably ISA, but PCI interrupts can come through IRQ0 + * as well if the interrupt controller isn't in accelerated + * mode. + * + * OTOH, the accelerator thing doesn't seem to be working + * overly well, so what we'll do instead is try directly + * examining the Master Interrupt Register to see if it's a + * PCI interrupt, and if _not_ then we'll pass it on to the + * ISA handler. + */ + + intstatus = inw(0x500) & 15; + if (intstatus) { + /* + * This is a PCI interrupt. Check each bit and + * despatch an interrupt if it's set. + */ + + if (intstatus & 8) handle_irq(16+3, 16+3, regs); + if (intstatus & 4) handle_irq(16+2, 16+2, regs); + if (intstatus & 2) handle_irq(16+1, 16+1, regs); + if (intstatus & 1) handle_irq(16+0, 16+0, regs); + } else + isa_device_interrupt (vector, regs); + + restore_flags(flags); +} + +static void __init +takara_init_irq(void) +{ + unsigned int ctlreg; + + STANDARD_INIT_IRQ_PROLOG; + + ctlreg = inl(0x500); + ctlreg &= ~0x8000; /* return to non-accelerated mode */ + outw(ctlreg >> 16, 0x502); + outw(ctlreg & 0xFFFF, 0x500); + ctlreg = 0x05107c00; /* enable the PCI interrupt register */ + outw(ctlreg >> 16, 0x502); + outw(ctlreg & 0xFFFF, 0x500); + enable_irq(2); +} + + +/* + * The Takara has PCI devices 1, 2, and 3 configured to slots 20, + * 19, and 18 respectively, in the default configuration. They can + * also be jumpered to slots 8, 7, and 6 respectively, which is fun + * because the SIO ISA bridge can also be slot 7. However, the SIO + * doesn't explicitly generate PCI-type interrupts, so we can + * assign it whatever the hell IRQ we like and it doesn't matter. + */ + +static int __init +takara_map_irq(struct pci_dev *dev, int slot, int pin) +{ + static char irq_tab[15][5] __initlocaldata = { + { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 6 == device 3 */ + { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 7 == device 2 */ + { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 8 == device 1 */ + { -1, -1, -1, -1, -1}, /* slot 9 == nothing */ + { -1, -1, -1, -1, -1}, /* slot 10 == nothing */ + { -1, -1, -1, -1, -1}, /* slot 11 == nothing */ + { -1, -1, -1, -1, -1}, /* slot 12 == nothing */ + { -1, -1, -1, -1, -1}, /* slot 13 == nothing */ + { -1, -1, -1, -1, -1}, /* slot 14 == nothing */ + { -1, -1, -1, -1, -1}, /* slot 15 == nothing */ + { -1, -1, -1, -1, -1}, /* slot 16 == nothing */ + { -1, -1, -1, -1, -1}, /* slot 17 == nothing */ + { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 18 == device 3 */ + { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 19 == device 2 */ + { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 20 == device 1 */ + }; + const long min_idsel = 6, max_idsel = 20, irqs_per_slot = 5; + return COMMON_TABLE_LOOKUP; +} + +static void __init +takara_pci_fixup(void) +{ + layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE); + common_pci_fixup(takara_map_irq, common_swizzle); + enable_ide(0x26e); +} + + +/* + * The System Vector + */ + +struct alpha_machine_vector takara_mv __initmv = { + vector_name: "Takara", + DO_EV5_MMU, + DO_DEFAULT_RTC, + DO_CIA_IO, + DO_CIA_BUS, + machine_check: cia_machine_check, + max_dma_address: ALPHA_MAX_DMA_ADDRESS, + + nr_irqs: 20, + irq_probe_mask: _PROBE_MASK(20), + update_irq_hw: NULL, + ack_irq: generic_ack_irq, + device_interrupt: takara_device_interrupt, + + init_arch: cia_init_arch, + init_irq: takara_init_irq, + init_pit: generic_init_pit, + pci_fixup: takara_pci_fixup, + kill_arch: generic_kill_arch, +}; +ALIAS_MV(takara) diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/t2.c linux/arch/alpha/kernel/t2.c --- v2.1.115/linux/arch/alpha/kernel/t2.c Wed Jun 24 22:54:03 1998 +++ linux/arch/alpha/kernel/t2.c Wed Dec 31 16:00:00 1969 @@ -1,646 +0,0 @@ -/* - * Code common to all T2 chips. - * - * Written by Jay A Estabrook (jestabro@amt.tay1.dec.com). - * December 1996. - * - * based on CIA code by David A Rusling (david.rusling@reo.mts.dec.com) - * - */ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * NOTE: Herein lie back-to-back mb instructions. They are magic. - * One plausible explanation is that the i/o controller does not properly - * handle the system transaction. Another involves timing. Ho hum. - */ - -extern struct hwrpb_struct *hwrpb; -extern asmlinkage void wrmces(unsigned long mces); - -/* - * Machine check reasons. Defined according to PALcode sources - * (osf.h and platform.h). - */ -#define MCHK_K_TPERR 0x0080 -#define MCHK_K_TCPERR 0x0082 -#define MCHK_K_HERR 0x0084 -#define MCHK_K_ECC_C 0x0086 -#define MCHK_K_ECC_NC 0x0088 -#define MCHK_K_OS_BUGCHECK 0x008A -#define MCHK_K_PAL_BUGCHECK 0x0090 - -/* - * BIOS32-style PCI interface: - */ - -#ifdef DEBUG_CONF -# define DBG(args) printk args -#else -# define DBG(args) -#endif - -#ifdef DEBUG_MCHECK -# define DBGMC(args) printk args -#else -# define DBGMC(args) -#endif - -#define vulp volatile unsigned long * -#define vuip volatile unsigned int * - -static volatile unsigned int T2_mcheck_expected[NR_CPUS]; -static volatile unsigned int T2_mcheck_taken[NR_CPUS]; - -#ifdef CONFIG_ALPHA_SRM_SETUP -unsigned int T2_DMA_WIN_BASE = T2_DMA_WIN_BASE_DEFAULT; -unsigned int T2_DMA_WIN_SIZE = T2_DMA_WIN_SIZE_DEFAULT; -unsigned long t2_sm_base; -#endif /* SRM_SETUP */ - -/* - * Given a bus, device, and function number, compute resulting - * configuration space address and setup the T2_HAXR2 register - * accordingly. It is therefore not safe to have concurrent - * invocations to configuration space access routines, but there - * really shouldn't be any need for this. - * - * Type 0: - * - * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 - * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * 31:11 Device select bit. - * 10:8 Function number - * 7:2 Register number - * - * Type 1: - * - * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 - * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * 31:24 reserved - * 23:16 bus number (8 bits = 128 possible buses) - * 15:11 Device number (5 bits) - * 10:8 function number - * 7:2 register number - * - * Notes: - * The function number selects which function of a multi-function device - * (e.g., SCSI and Ethernet). - * - * The register selects a DWORD (32 bit) register offset. Hence it - * doesn't get shifted by 2 bits as we want to "drop" the bottom two - * bits. - */ -static int mk_conf_addr(unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned long *pci_addr, - unsigned char *type1) -{ - unsigned long addr; - - DBG(("mk_conf_addr(bus=%d, dfn=0x%x, where=0x%x," - " addr=0x%lx, type1=0x%x)\n", - bus, device_fn, where, pci_addr, type1)); - - if (bus == 0) { - int device = device_fn >> 3; - - /* type 0 configuration cycle: */ - - if (device > 8) { - DBG(("mk_conf_addr: device (%d)>20, returning -1\n", - device)); - return -1; - } - - *type1 = 0; - addr = (0x0800L << device) | ((device_fn & 7) << 8) | (where); - } else { - /* type 1 configuration cycle: */ - *type1 = 1; - addr = (bus << 16) | (device_fn << 8) | (where); - } - *pci_addr = addr; - DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr)); - return 0; -} - - -static unsigned int conf_read(unsigned long addr, unsigned char type1) -{ - unsigned long flags; - unsigned int stat0, value, cpu; - unsigned long t2_cfg = 0; /* to keep gcc quiet */ - - cpu = smp_processor_id(); - - save_flags(flags); /* avoid getting hit by machine check */ - cli(); - - DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1)); - -#if 0 - /* reset status register to avoid losing errors: */ - stat0 = *(vulp)T2_IOCSR; - *(vulp)T2_IOCSR = stat0; - mb(); - DBG(("conf_read: T2 IOCSR was 0x%x\n", stat0)); -#endif - /* if Type1 access, must set T2 CFG */ - if (type1) { - t2_cfg = *(vulp)T2_HAE_3 & ~0xc0000000UL; - *(vulp)T2_HAE_3 = 0x40000000UL | t2_cfg; - mb(); - DBG(("conf_read: TYPE1 access\n")); - } - mb(); - draina(); - - T2_mcheck_expected[cpu] = 1; - T2_mcheck_taken[cpu] = 0; - mb(); - /* access configuration space: */ - value = *(vuip)addr; - mb(); - mb(); /* magic */ - if (T2_mcheck_taken[cpu]) { - T2_mcheck_taken[cpu] = 0; - value = 0xffffffffU; - mb(); - } - T2_mcheck_expected[cpu] = 0; - mb(); - - /* if Type1 access, must reset T2 CFG so normal IO space ops work */ - if (type1) { - *(vulp)T2_HAE_3 = t2_cfg; - mb(); - } - DBG(("conf_read(): finished\n")); - - restore_flags(flags); - return value; -} - - -static void conf_write(unsigned long addr, unsigned int value, - unsigned char type1) -{ - unsigned long flags; - unsigned int stat0, cpu; - unsigned long t2_cfg = 0; /* to keep gcc quiet */ - - cpu = smp_processor_id(); - - save_flags(flags); /* avoid getting hit by machine check */ - cli(); - -#if 0 - /* reset status register to avoid losing errors: */ - stat0 = *(vulp)T2_IOCSR; - *(vulp)T2_IOCSR = stat0; - mb(); - DBG(("conf_write: T2 ERR was 0x%x\n", stat0)); -#endif - /* if Type1 access, must set T2 CFG */ - if (type1) { - t2_cfg = *(vulp)T2_HAE_3 & ~0xc0000000UL; - *(vulp)T2_HAE_3 = t2_cfg | 0x40000000UL; - mb(); - DBG(("conf_write: TYPE1 access\n")); - } - mb(); - draina(); - - T2_mcheck_expected[cpu] = 1; - mb(); - /* access configuration space: */ - *(vuip)addr = value; - mb(); - mb(); /* magic */ - T2_mcheck_expected[cpu] = 0; - mb(); - - /* if Type1 access, must reset T2 CFG so normal IO space ops work */ - if (type1) { - *(vulp)T2_HAE_3 = t2_cfg; - mb(); - } - DBG(("conf_write(): finished\n")); - restore_flags(flags); -} - - -int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned char *value) -{ - unsigned long addr = T2_CONF; - unsigned long pci_addr; - unsigned char type1; - - *value = 0xff; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - - addr |= (pci_addr << 5) + 0x00; - - *value = conf_read(addr, type1) >> ((where & 3) * 8); - - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_read_config_word (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short *value) -{ - unsigned long addr = T2_CONF; - unsigned long pci_addr; - unsigned char type1; - - *value = 0xffff; - - if (where & 0x1) { - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) { - return PCIBIOS_SUCCESSFUL; - } - - addr |= (pci_addr << 5) + 0x08; - - *value = conf_read(addr, type1) >> ((where & 3) * 8); - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int *value) -{ - unsigned long addr = T2_CONF; - unsigned long pci_addr; - unsigned char type1; - - *value = 0xffffffff; - if (where & 0x3) { - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x18; - *value = conf_read(addr, type1); - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned char value) -{ - unsigned long addr = T2_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x00; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_write_config_word (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short value) -{ - unsigned long addr = T2_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x08; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int value) -{ - unsigned long addr = T2_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - addr |= (pci_addr << 5) + 0x18; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; -} - - -unsigned long t2_init(unsigned long mem_start, unsigned long mem_end) -{ - unsigned long t2_err; - unsigned int i; - - for (i = 0; i < NR_CPUS; i++) { - T2_mcheck_expected[i] = 0; - T2_mcheck_taken[i] = 0; - } - -#if 0 - /* - * Set up error reporting. - */ - t2_err = *(vulp)T2_IOCSR ; - t2_err |= (0x1 << 7) ; /* master abort */ - *(vulp)T2_IOCSR = t2_err ; - mb() ; -#endif - - printk("t2_init: HBASE was 0x%lx\n", *(vulp)T2_HBASE); -#if 0 - printk("t2_init: WBASE1=0x%lx WMASK1=0x%lx TBASE1=0x%lx\n", - *(vulp)T2_WBASE1, - *(vulp)T2_WMASK1, - *(vulp)T2_TBASE1); - printk("t2_init: WBASE2=0x%lx WMASK2=0x%lx TBASE2=0x%lx\n", - *(vulp)T2_WBASE2, - *(vulp)T2_WMASK2, - *(vulp)T2_TBASE2); -#endif - -#ifdef CONFIG_ALPHA_SRM_SETUP - /* check window 1 for enabled and mapped to 0 */ - if (((*(vulp)T2_WBASE1 & (3UL<<18)) == (2UL<<18)) && - (*(vulp)T2_TBASE1 == 0)) - { - T2_DMA_WIN_BASE = *(vulp)T2_WBASE1 & 0xfff00000UL; - T2_DMA_WIN_SIZE = *(vulp)T2_WMASK1 & 0xfff00000UL; - T2_DMA_WIN_SIZE += 0x00100000UL; -/* DISABLE window 2!! ?? */ -#if 1 - printk("t2_init: using Window 1 settings\n"); - printk("t2_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n", - *(vulp)T2_WBASE1, - *(vulp)T2_WMASK1, - *(vulp)T2_TBASE1); -#endif - } - else /* check window 2 for enabled and mapped to 0 */ - if (((*(vulp)T2_WBASE2 & (3UL<<18)) == (2UL<<18)) && - (*(vulp)T2_TBASE2 == 0)) - { - T2_DMA_WIN_BASE = *(vulp)T2_WBASE2 & 0xfff00000UL; - T2_DMA_WIN_SIZE = *(vulp)T2_WMASK2 & 0xfff00000UL; - T2_DMA_WIN_SIZE += 0x00100000UL; -/* DISABLE window 1!! ?? */ -#if 1 - printk("t2_init: using Window 2 settings\n"); - printk("t2_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n", - *(vulp)T2_WBASE2, - *(vulp)T2_WMASK2, - *(vulp)T2_TBASE2); -#endif - } - else /* we must use our defaults... */ -#endif /* SRM_SETUP */ - { - /* - * Set up the PCI->physical memory translation windows. - * For now, window 2 is disabled. In the future, we may - * want to use it to do scatter/gather DMA. Window 1 - * goes at 1 GB and is 1 GB large. - */ - - /* WARNING!! must correspond to the DMA_WIN params!!! */ - *(vulp)T2_WBASE1 = 0x400807ffU; - *(vulp)T2_WMASK1 = 0x3ff00000U; - *(vulp)T2_TBASE1 = 0; - - *(vulp)T2_WBASE2 = 0x0; - *(vulp)T2_HBASE = 0x0; - } - - /* - * check ASN in HWRPB for validity, report if bad - */ - if (hwrpb->max_asn != MAX_ASN) { - printk("T2_init: max ASN from HWRPB is bad (0x%lx)\n", - hwrpb->max_asn); - hwrpb->max_asn = MAX_ASN; - } - - /* - * Finally, clear the T2_HAE_3 register, which gets used - * for PCI Config Space accesses. That is the way - * we want to use it, and we do not want to depend on - * what ARC or SRM might have left behind... - */ - { - unsigned long t2_hae_1 = *(vulp)T2_HAE_1; - unsigned long t2_hae_2 = *(vulp)T2_HAE_2; - unsigned long t2_hae_3 = *(vulp)T2_HAE_3; - unsigned long t2_hae_4 = *(vulp)T2_HAE_4; -#if 1 - printk("T2_init: HAE1 was 0x%lx\n", t2_hae_1); - printk("T2_init: HAE2 was 0x%lx\n", t2_hae_2); - printk("T2_init: HAE3 was 0x%lx\n", t2_hae_3); - printk("T2_init: HAE4 was 0x%lx\n", t2_hae_4); -#endif -#ifdef CONFIG_ALPHA_SRM_SETUP - /* - * sigh... For the SRM setup, unless we know apriori what the HAE - * contents will be, we need to setup the arbitrary region bases - * so we can test against the range of addresses and tailor the - * region chosen for the SPARSE memory access. - * - * see include/asm-alpha/t2.h for the SPARSE mem read/write - */ - t2_sm_base = (t2_hae_1 << 27) & 0xf8000000UL; - /* - Set the HAE cache, so that setup_arch() code - will use the SRM setting always. Our readb/writeb - code in .h expects never to have to change - the contents of the HAE. - */ - hae.cache = t2_hae_1; -#else /* SRM_SETUP */ - *(vulp)T2_HAE_1 = 0; mb(); - *(vulp)T2_HAE_2 = 0; mb(); - *(vulp)T2_HAE_3 = 0; mb(); -#if 0 - *(vulp)T2_HAE_4 = 0; mb(); /* do not touch this */ -#endif -#endif /* SRM_SETUP */ - } - - return mem_start; -} - -#define SIC_SEIC (1UL << 33) /* System Event Clear */ - -static struct sable_cpu_csr *sable_cpu_regs[4] = { - (struct sable_cpu_csr *)CPU0_BASE, - (struct sable_cpu_csr *)CPU1_BASE, - (struct sable_cpu_csr *)CPU2_BASE, - (struct sable_cpu_csr *)CPU3_BASE, -}; - -int t2_clear_errors(void) -{ - unsigned int cpu = smp_processor_id(); - - DBGMC(("???????? t2_clear_errors\n")); - - sable_cpu_regs[cpu]->sic &= ~SIC_SEIC; - - /* - * clear CPU errors - */ - sable_cpu_regs[cpu]->bcce |= sable_cpu_regs[cpu]->bcce; - sable_cpu_regs[cpu]->cbe |= sable_cpu_regs[cpu]->cbe; - sable_cpu_regs[cpu]->bcue |= sable_cpu_regs[cpu]->bcue; - sable_cpu_regs[cpu]->dter |= sable_cpu_regs[cpu]->dter; - - *(vulp)T2_CERR1 |= *(vulp)T2_CERR1; - *(vulp)T2_PERR1 |= *(vulp)T2_PERR1; - - mb(); - mb(); /* magic */ - return 0; -} - -void t2_machine_check(unsigned long vector, unsigned long la_ptr, - struct pt_regs * regs) -{ - struct el_t2_logout_header *mchk_header; - struct el_t2_procdata_mcheck *mchk_procdata; - struct el_t2_sysdata_mcheck *mchk_sysdata; - unsigned long * ptr; - const char * reason; - char buf[128]; - long i; - unsigned int cpu = smp_processor_id(); - - DBGMC(("t2_machine_check: vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr)); - - mchk_header = (struct el_t2_logout_header *)la_ptr; - - DBGMC(("t2_machine_check: susoffset=0x%lx procoffset=0x%lx\n", - mchk_header->elfl_sysoffset, mchk_header->elfl_procoffset)); - - mchk_sysdata = (struct el_t2_sysdata_mcheck *) - (la_ptr + mchk_header->elfl_sysoffset); - mchk_procdata = (struct el_t2_procdata_mcheck *) - (la_ptr + mchk_header->elfl_procoffset - sizeof(unsigned long)*32); - - DBGMC((" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", - regs->pc, mchk_header->elfl_size, mchk_header->elfl_procoffset, - mchk_header->elfl_sysoffset)); - DBGMC(("t2_machine_check: expected %d\n", T2_mcheck_expected[cpu])); - -#ifdef DEBUG_DUMP - { - unsigned long *ptr; - int i; - - ptr = (unsigned long *)la_ptr; - for (i = 0; i < mchk_header->elfl_size/sizeof(long); i += 2) { - printk(" +%lx %lx %lx\n", i*sizeof(long), - ptr[i], ptr[i+1]); - } - } -#endif /* DEBUG_DUMP */ - - /* - * Check if machine check is due to a badaddr() and if so, - * ignore the machine check. - */ - mb(); - mb(); /* magic */ - if (T2_mcheck_expected[cpu]) { - DBGMC(("T2 machine check expected\n")); - T2_mcheck_taken[cpu] = 1; - t2_clear_errors(); - T2_mcheck_expected[cpu] = 0; - mb(); - mb(); /* magic */ - wrmces(rdmces()|1);/* ??? */ - draina(); - return; - } - - switch ((unsigned int) mchk_header->elfl_error_type) { - case MCHK_K_TPERR: reason = "tag parity error"; break; - case MCHK_K_TCPERR: reason = "tag control parity error"; break; - case MCHK_K_HERR: reason = "generic hard error"; break; - case MCHK_K_ECC_C: reason = "correctable ECC error"; break; - case MCHK_K_ECC_NC: reason = "uncorrectable ECC error"; break; - case MCHK_K_OS_BUGCHECK: reason = "OS-specific PAL bugcheck"; break; - case MCHK_K_PAL_BUGCHECK: reason = "callsys in kernel mode"; break; - case 0x96: reason = "i-cache read retryable error"; break; - case 0x98: reason = "processor detected hard error"; break; - - /* System specific (these are for Alcor, at least): */ - case 0x203: reason = "system detected uncorrectable ECC error"; break; - case 0x205: reason = "parity error detected by T2"; break; - case 0x207: reason = "non-existent memory error"; break; - case 0x209: reason = "PCI SERR detected"; break; - case 0x20b: reason = "PCI data parity error detected"; break; - case 0x20d: reason = "PCI address parity error detected"; break; - case 0x20f: reason = "PCI master abort error"; break; - case 0x211: reason = "PCI target abort error"; break; - case 0x213: reason = "scatter/gather PTE invalid error"; break; - case 0x215: reason = "flash ROM write error"; break; - case 0x217: reason = "IOA timeout detected"; break; - case 0x219: reason = "IOCHK#, EISA add-in board parity or other catastrophic error"; break; - case 0x21b: reason = "EISA fail-safe timer timeout"; break; - case 0x21d: reason = "EISA bus time-out"; break; - case 0x21f: reason = "EISA software generated NMI"; break; - case 0x221: reason = "unexpected ev5 IRQ[3] interrupt"; break; - default: - sprintf(buf, "reason for machine-check unknown (0x%x)", - (unsigned int) mchk_header->elfl_error_type); - reason = buf; - break; - } - wrmces(rdmces()|1); /* reset machine check pending flag */ - mb(); - - printk(KERN_CRIT " T2 machine check: %s%s\n", - reason, mchk_header->elfl_retry ? " (retryable)" : ""); - - /* dump the logout area to give all info: */ - - ptr = (unsigned long *)la_ptr; - for (i = 0; i < mchk_header->elfl_size / sizeof(long); i += 2) { - printk(KERN_CRIT " +%8lx %016lx %016lx\n", - i*sizeof(long), ptr[i], ptr[i+1]); - } -} diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c --- v2.1.115/linux/arch/alpha/kernel/traps.c Tue Jul 28 14:21:07 1998 +++ linux/arch/alpha/kernel/traps.c Sun Aug 9 12:09:05 1998 @@ -20,8 +20,10 @@ #include #include +#include "proto.h" -static void dik_show_regs(struct pt_regs *regs, unsigned long *r9_15) +static void +dik_show_regs(struct pt_regs *regs, unsigned long *r9_15) { printk("pc = [<%016lx>] ra = [<%016lx>] ps = %04lx\n", regs->pc, regs->r26, regs->ps); @@ -51,7 +53,8 @@ printk("gp = %016lx sp = %p\n", regs->gp, regs+1); } -static void dik_show_code(unsigned int *pc) +static void +dik_show_code(unsigned int *pc) { long i; @@ -65,7 +68,8 @@ printk("\n"); } -static void dik_show_trace(unsigned long *sp) +static void +dik_show_trace(unsigned long *sp) { long i = 0; printk("Trace:"); @@ -86,8 +90,8 @@ printk("\n"); } -void die_if_kernel(char * str, struct pt_regs *regs, long err, - unsigned long *r9_15) +void +die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15) { if (regs->ps & 8) return; @@ -106,21 +110,20 @@ } #ifndef CONFIG_MATHEMU -static long dummy_alpha_fp_emul_imprecise(struct pt_regs *r, unsigned long wm) -{ - return 0; -} - +static long dummy_emul() { return 0; } long (*alpha_fp_emul_imprecise)(struct pt_regs *regs, unsigned long writemask) - = dummy_alpha_fp_emul_imprecise; + = (void *)dummy_emul; +long (*alpha_fp_emul) (unsigned long pc) + = (void *)dummy_emul; #else long alpha_fp_emul_imprecise(struct pt_regs *regs, unsigned long writemask); +long alpha_fp_emul (unsigned long pc); #endif -asmlinkage void do_entArith(unsigned long summary, unsigned long write_mask, - unsigned long a2, unsigned long a3, - unsigned long a4, unsigned long a5, - struct pt_regs regs) +asmlinkage void +do_entArith(unsigned long summary, unsigned long write_mask, unsigned long a2, + unsigned long a3, unsigned long a4, unsigned long a5, + struct pt_regs regs) { if ((summary & 1)) { /* @@ -133,8 +136,10 @@ } lock_kernel(); +#if 0 printk("%s: arithmetic trap at %016lx: %02lx %016lx\n", current->comm, regs.pc, summary, write_mask); +#endif die_if_kernel("Arithmetic fault", ®s, 0, 0); force_sig(SIGFPE, current); unlock_kernel(); @@ -202,7 +207,6 @@ case 4: /* opDEC */ #ifdef CONFIG_ALPHA_NEED_ROUNDING_EMULATION { - extern long alpha_fp_emul (unsigned long pc); unsigned int opcode; /* get opcode of faulting instruction: */ @@ -255,9 +259,10 @@ #define una_reg(r) (regs.regs[(r) >= 16 && (r) <= 18 ? (r)+19 : (r)]) -asmlinkage void do_entUna(void * va, unsigned long opcode, unsigned long reg, - unsigned long a3, unsigned long a4, unsigned long a5, - struct allregs regs) +asmlinkage void +do_entUna(void * va, unsigned long opcode, unsigned long reg, + unsigned long a3, unsigned long a4, unsigned long a5, + struct allregs regs) { long error, tmp1, tmp2, tmp3, tmp4; unsigned long pc = regs.pc - 4; @@ -497,7 +502,8 @@ * needs to be remapped to preserve non-finite values * (infinities, not-a-numbers, denormals). */ -static inline unsigned long s_mem_to_reg (unsigned long s_mem) +static inline unsigned long +s_mem_to_reg (unsigned long s_mem) { unsigned long frac = (s_mem >> 0) & 0x7fffff; unsigned long sign = (s_mem >> 31) & 0x1; @@ -524,7 +530,8 @@ * Convert an s-floating point value in register format to the * corresponding value in memory format. */ -static inline unsigned long s_reg_to_mem (unsigned long s_reg) +static inline unsigned long +s_reg_to_mem (unsigned long s_reg) { return ((s_reg >> 62) << 30) | ((s_reg << 5) >> 34); } @@ -571,12 +578,10 @@ #undef R -asmlinkage void do_entUnaUser(void * va, unsigned long opcode, - unsigned long reg, struct pt_regs *regs) +asmlinkage void +do_entUnaUser(void * va, unsigned long opcode, + unsigned long reg, struct pt_regs *regs) { - extern void alpha_write_fp_reg (unsigned long reg, unsigned long val); - extern unsigned long alpha_read_fp_reg (unsigned long reg); - static int cnt = 0; static long last_time = 0; @@ -868,10 +873,10 @@ /* * Unimplemented system calls. */ -asmlinkage long alpha_ni_syscall(unsigned long a0, unsigned long a1, - unsigned long a2, unsigned long a3, - unsigned long a4, unsigned long a5, - struct pt_regs regs) +asmlinkage long +alpha_ni_syscall(unsigned long a0, unsigned long a1, unsigned long a2, + unsigned long a3, unsigned long a4, unsigned long a5, + struct pt_regs regs) { /* We only get here for OSF system calls, minus #112; the rest go to sys_ni_syscall. */ @@ -879,17 +884,11 @@ return -ENOSYS; } -extern asmlinkage void entMM(void); -extern asmlinkage void entIF(void); -extern asmlinkage void entArith(void); -extern asmlinkage void entUna(void); -extern asmlinkage void entSys(void); - -register unsigned long gptr __asm__("$29"); - -void trap_init(void) +void +trap_init(void) { /* Tell PAL-code what global pointer we want in the kernel. */ + register unsigned long gptr __asm__("$29"); wrkgp(gptr); wrent(entArith, 1); diff -u --recursive --new-file v2.1.115/linux/arch/alpha/kernel/tsunami.c linux/arch/alpha/kernel/tsunami.c --- v2.1.115/linux/arch/alpha/kernel/tsunami.c Wed Jun 24 22:54:03 1998 +++ linux/arch/alpha/kernel/tsunami.c Wed Dec 31 16:00:00 1969 @@ -1,503 +0,0 @@ -/* - * Code common to all TSUNAMI chips. - * - * Based on code written by David A. Rusling (david.rusling@reo.mts.dec.com). - * - */ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * NOTE: Herein lie back-to-back mb instructions. They are magic. - * One plausible explanation is that the I/O controller does not properly - * handle the system transaction. Another involves timing. Ho hum. - */ - -extern struct hwrpb_struct *hwrpb; -extern asmlinkage void wrmces(unsigned long mces); - -/* - * BIOS32-style PCI interface: - */ - -#ifdef CONFIG_ALPHA_TSUNAMI - -#ifdef DEBUG -# define DBG(args) printk args -#else -# define DBG(args) -#endif - -#define DEBUG_MCHECK -#ifdef DEBUG_MCHECK -# define DBG_MCK(args) printk args -#define DEBUG_MCHECK_DUMP -#else -# define DBG_MCK(args) -#endif - -#define vuip volatile unsigned int * -#define vulp volatile unsigned long * - -static volatile unsigned int TSUNAMI_mcheck_expected[NR_CPUS]; -static volatile unsigned int TSUNAMI_mcheck_taken[NR_CPUS]; -static unsigned int TSUNAMI_jd[NR_CPUS]; - -#ifdef CONFIG_ALPHA_SRM_SETUP -unsigned int TSUNAMI_DMA_WIN_BASE = TSUNAMI_DMA_WIN_BASE_DEFAULT; -unsigned int TSUNAMI_DMA_WIN_SIZE = TSUNAMI_DMA_WIN_SIZE_DEFAULT; -#endif /* SRM_SETUP */ - -/* - * Given a bus, device, and function number, compute resulting - * configuration space address - * accordingly. It is therefore not safe to have concurrent - * invocations to configuration space access routines, but there - * really shouldn't be any need for this. - * - * Note that all config space accesses use Type 1 address format. - * - * Note also that type 1 is determined by non-zero bus number. - * - * Type 1: - * - * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 - * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * 31:24 reserved - * 23:16 bus number (8 bits = 128 possible buses) - * 15:11 Device number (5 bits) - * 10:8 function number - * 7:2 register number - * - * Notes: - * The function number selects which function of a multi-function device - * (e.g., SCSI and Ethernet). - * - * The register selects a DWORD (32 bit) register offset. Hence it - * doesn't get shifted by 2 bits as we want to "drop" the bottom two - * bits. - */ -static int mk_conf_addr(unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned long *pci_addr, - unsigned char *type1) -{ - unsigned long addr; - - DBG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, pci_addr=0x%p, type1=0x%p)\n", - bus, device_fn, where, pci_addr, type1)); - - if (bus == 0) { - *type1 = 0; - } else { - /* type 1 configuration cycle: */ - *type1 = 1; - } - addr = (bus << 16) | (device_fn << 8) | (where); - *pci_addr = addr; - DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr)); - return 0; -} - -int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned char *value) -{ - unsigned long addr; - unsigned char type1; - unsigned char result; - - *value = 0xff; - - if (mk_conf_addr(bus, device_fn, where, &addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - - __asm__ __volatile__ ( - "ldbu %0,%1" - : "=r" (result) - : "m" (*(unsigned char *)(addr+TSUNAMI_PCI0_CONF))); - - *value = result; - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_read_config_word (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short *value) -{ - unsigned long addr; - unsigned char type1; - unsigned short result; - - *value = 0xffff; - - if (where & 0x1) { - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - if (mk_conf_addr(bus, device_fn, where, &addr, &type1)) { - return PCIBIOS_SUCCESSFUL; - } - - __asm__ __volatile__ ( - "ldwu %0,%1" - : "=r" (result) - : "m" (*(unsigned short *)(addr+TSUNAMI_PCI0_CONF))); - - *value = result; - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int *value) -{ - unsigned long addr; - unsigned char type1; - unsigned int result; - - *value = 0xffffffff; - if (where & 0x3) { - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - if (mk_conf_addr(bus, device_fn, where, &addr, &type1)) { - return PCIBIOS_SUCCESSFUL; - } - - __asm__ __volatile__ ( - "ldl %0,%1" - : "=r" (result) - : "m" (*(unsigned int *)(addr+TSUNAMI_PCI0_CONF))); - - *value = result; - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned char value) -{ - unsigned long addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - - __asm__ __volatile__ ( - "stb %1,%0\n\t" - "mb" - : : "m" (*(unsigned char *)(addr+TSUNAMI_PCI0_CONF)), - "r" (value)); - - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_write_config_word (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned short value) -{ - unsigned long addr; - unsigned char type1; - - if (where & 0x1) { - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - if (mk_conf_addr(bus, device_fn, where, &addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - - __asm__ __volatile__ ( - "stw %1,%0\n\t" - "mb" - : : "m" (*(unsigned short *)(addr+TSUNAMI_PCI0_CONF)), - "r" (value)); - - return PCIBIOS_SUCCESSFUL; -} - - -int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn, - unsigned char where, unsigned int value) -{ - unsigned long addr; - unsigned char type1; - - if (where & 0x3) { - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - if (mk_conf_addr(bus, device_fn, where, &addr, &type1) < 0) { - return PCIBIOS_SUCCESSFUL; - } - - __asm__ __volatile__ ( - "stl %1,%0\n\t" - "mb" - : : "m" (*(unsigned int *)(addr+TSUNAMI_PCI0_CONF)), - "r" (value)); - - return PCIBIOS_SUCCESSFUL; -} - - -unsigned long tsunami_init(unsigned long mem_start, unsigned long mem_end) -{ - unsigned long tsunami_err; - unsigned int i; - -#if 0 -printk("tsunami_init: CChip registers:\n"); -printk("tsunami_init: CSR_CSC 0x%lx\n", *(vulp)TSUNAMI_CSR_CSC); -printk("tsunami_init: CSR_MTR 0x%lx\n", *(vulp)TSUNAMI_CSR_MTR); -printk("tsunami_init: CSR_MISC 0x%lx\n", *(vulp)TSUNAMI_CSR_MISC); -printk("tsunami_init: CSR_DIM0 0x%lx\n", *(vulp)TSUNAMI_CSR_DIM0); -printk("tsunami_init: CSR_DIM1 0x%lx\n", *(vulp)TSUNAMI_CSR_DIM1); -printk("tsunami_init: CSR_DIR0 0x%lx\n", *(vulp)TSUNAMI_CSR_DIR0); -printk("tsunami_init: CSR_DIR1 0x%lx\n", *(vulp)TSUNAMI_CSR_DIR1); -printk("tsunami_init: CSR_DRIR 0x%lx\n", *(vulp)TSUNAMI_CSR_DRIR); - -printk("tsunami_init: DChip registers:\n"); -printk("tsunami_init: CSR_DSC 0x%lx\n", *(vulp)TSUNAMI_CSR_DSC); -printk("tsunami_init: CSR_STR 0x%lx\n", *(vulp)TSUNAMI_CSR_STR); -printk("tsunami_init: CSR_DREV 0x%lx\n", *(vulp)TSUNAMI_CSR_DREV); - -printk("tsunami_init: PChip registers:\n"); -printk("tsunami_init: PCHIP0_WSBA0 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA0); -printk("tsunami_init: PCHIP0_WSBA1 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA1); -printk("tsunami_init: PCHIP0_WSBA2 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA2); -printk("tsunami_init: PCHIP0_WSBA3 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA3); -printk("tsunami_init: PCHIP0_WSM0 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM0); -printk("tsunami_init: PCHIP0_WSM1 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM1); -printk("tsunami_init: PCHIP0_WSM2 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM2); -printk("tsunami_init: PCHIP0_WSM3 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM3); -printk("tsunami_init: PCHIP0_TBA0 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA0); -printk("tsunami_init: PCHIP0_TBA1 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA1); -printk("tsunami_init: PCHIP0_TBA2 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA2); -printk("tsunami_init: PCHIP0_TBA3 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA3); - -printk("tsunami_init: PCHIP0_PCTL 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PCTL); -printk("tsunami_init: PCHIP0_PLAT 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PLAT); -printk("tsunami_init: PCHIP0_PERROR 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PERROR); -printk("tsunami_init: PCHIP0_PERRMASK 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PERRMASK); - -#endif - - for (i = 0; i < NR_CPUS; i++) { - TSUNAMI_mcheck_expected[i] = 0; - TSUNAMI_mcheck_taken[i] = 0; - } -#ifdef NOT_YET - /* - * Set up error reporting. Make sure CPU_PE is OFF in the mask. - */ - tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERRMASK; - tsunami_err &= ~20; - *(vulp)TSUNAMI_PCHIP0_PERRMASK = tsunami_err; - mb(); - tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERRMASK; - - tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERROR ; - tsunami_err |= 0x40; /* master/target abort */ - *(vulp)TSUNAMI_PCHIP0_PERROR = tsunami_err ; - mb() ; - tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERROR ; -#endif /* NOT_YET */ - -#ifdef CONFIG_ALPHA_SRM_SETUP - /* check window 0 for enabled and mapped to 0 */ - if (((*(vulp)TSUNAMI_PCHIP0_WSBA0 & 3) == 1) && - (*(vulp)TSUNAMI_PCHIP0_TBA0 == 0) && - ((*(vulp)TSUNAMI_PCHIP0_WSM0 & 0xfff00000U) > 0x0ff00000U)) - { - TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA0 & 0xfff00000U; - TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM0 & 0xfff00000U; - TSUNAMI_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("tsunami_init: using Window 0 settings\n"); - printk("tsunami_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vulp)TSUNAMI_PCHIP0_WSBA0, - *(vulp)TSUNAMI_PCHIP0_WSM0, - *(vulp)TSUNAMI_PCHIP0_TBA0); -#endif - } - else /* check window 1 for enabled and mapped to 0 */ - if (((*(vulp)TSUNAMI_PCHIP0_WSBA1 & 3) == 1) && - (*(vulp)TSUNAMI_PCHIP0_TBA1 == 0) && - ((*(vulp)TSUNAMI_PCHIP0_WSM1 & 0xfff00000U) > 0x0ff00000U)) -{ - TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA1 & 0xfff00000U; - TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM1 & 0xfff00000U; - TSUNAMI_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("tsunami_init: using Window 1 settings\n"); - printk("tsunami_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vulp)TSUNAMI_PCHIP0_WSBA1, - *(vulp)TSUNAMI_PCHIP0_WSM1, - *(vulp)TSUNAMI_PCHIP0_TBA1); -#endif - } - else /* check window 2 for enabled and mapped to 0 */ - if (((*(vulp)TSUNAMI_PCHIP0_WSBA2 & 3) == 1) && - (*(vulp)TSUNAMI_PCHIP0_TSB2 == 0) && - ((*(vulp)TSUNAMI_PCHIP0_WSM2 & 0xfff00000U) > 0x0ff00000U)) - { - TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA2 & 0xfff00000U; - TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM2 & 0xfff00000U; - TSUNAMI_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("tsunami_init: using Window 2 settings\n"); - printk("tsunami_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vulp)TSUNAMI_PCHIP0_WSBA2, - *(vulp)TSUNAMI_PCHIP0_WSM2, - *(vulp)TSUNAMI_PCHIP0_TSB2); -#endif - } - else /* check window 3 for enabled and mapped to 0 */ - if (((*(vulp)TSUNAMI_PCHIP0_WSBA3 & 3) == 1) && - (*(vulp)TSUNAMI_PCHIP0_TBA3 == 0) && - ((*(vulp)TSUNAMI_PCHIP0_WSM3 & 0xfff00000U) > 0x0ff00000U)) - { - TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA3 & 0xfff00000U; - TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM3 & 0xfff00000U; - TSUNAMI_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("tsunami_init: using Window 3 settings\n"); - printk("tsunami_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n", - *(vulp)TSUNAMI_PCHIP0_WSBA3, - *(vulp)TSUNAMI_PCHIP0_WSM3, - *(vulp)TSUNAMI_PCHIP0_TBA3); -#endif - } - else /* we must use our defaults which were pre-initialized... */ -#endif /* SRM_SETUP */ - { - /* - * Set up the PCI->physical memory translation windows. - * For now, windows 1,2 and 3 are disabled. In the future, we may - * want to use them to do scatter/gather DMA. Window 0 - * goes at 1 GB and is 1 GB large. - */ - - *(vulp)TSUNAMI_PCHIP0_WSBA0 = 1L | (TSUNAMI_DMA_WIN_BASE & 0xfff00000U); - *(vulp)TSUNAMI_PCHIP0_WSM0 = (TSUNAMI_DMA_WIN_SIZE - 1) & 0xfff00000UL; - *(vulp)TSUNAMI_PCHIP0_TBA0 = 0UL; - - *(vulp)TSUNAMI_PCHIP0_WSBA1 = 0UL; - *(vulp)TSUNAMI_PCHIP0_WSBA2 = 0UL; - *(vulp)TSUNAMI_PCHIP0_WSBA3 = 0UL; - mb(); - } - - /* - * check ASN in HWRPB for validity, report if bad - */ - if (hwrpb->max_asn != MAX_ASN) { - printk("TSUNAMI_init: max ASN from HWRPB is bad (0x%lx)\n", - hwrpb->max_asn); - hwrpb->max_asn = MAX_ASN; - } - - return mem_start; -} - -int tsunami_pci_clr_err(void) -{ - unsigned int cpu = smp_processor_id(); - - TSUNAMI_jd[cpu] = *((vulp)TSUNAMI_PCHIP0_PERROR); - DBG(("TSUNAMI_pci_clr_err: PERROR after read 0x%x\n", TSUNAMI_jd[cpu])); - *((vulp)TSUNAMI_PCHIP0_PERROR) = 0x040; mb(); - TSUNAMI_jd[cpu] = *((vulp)TSUNAMI_PCHIP0_PERROR); - return 0; -} - -void tsunami_machine_check(unsigned long vector, unsigned long la_ptr, - struct pt_regs * regs) -{ -#if 1 - printk("TSUNAMI machine check ignored\n") ; -#else - struct el_common *mchk_header; - struct el_TSUNAMI_sysdata_mcheck *mchk_sysdata; - unsigned int cpu = smp_processor_id(); - - mchk_header = (struct el_common *)la_ptr; - - mchk_sysdata = - (struct el_TSUNAMI_sysdata_mcheck *)(la_ptr + mchk_header->sys_offset); - -#if 0 - DBG_MCK(("tsunami_machine_check: vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr)); - DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", - regs->pc, mchk_header->size, mchk_header->proc_offset, - mchk_header->sys_offset)); - DBG_MCK(("tsunami_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n", - TSUNAMI_mcheck_expected[cpu], mchk_sysdata->epic_dcsr, - mchk_sysdata->epic_pear)); -#endif -#ifdef DEBUG_MCHECK_DUMP - { - unsigned long *ptr; - int i; - - ptr = (unsigned long *)la_ptr; - for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { - printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]); - } - } -#endif /* DEBUG_MCHECK_DUMP */ - /* - * Check if machine check is due to a badaddr() and if so, - * ignore the machine check. - */ - mb(); - mb(); /* magic */ - if (TSUNAMI_mcheck_expected[cpu]) { - DBG(("TSUNAMI machine check expected\n")); - TSUNAMI_mcheck_expected[cpu] = 0; - TSUNAMI_mcheck_taken[cpu] = 1; - mb(); - mb(); /* magic */ - draina(); - tsunami_pci_clr_err(); - wrmces(0x7); - mb(); - } -#if 1 - else { - printk("TSUNAMI machine check NOT expected\n") ; - DBG_MCK(("tsunami_machine_check: vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr)); - DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", - regs->pc, mchk_header->size, mchk_header->proc_offset, - mchk_header->sys_offset)); - TSUNAMI_mcheck_expected[cpu] = 0; - TSUNAMI_mcheck_taken[cpu] = 1; - mb(); - mb(); /* magic */ - draina(); - tsunami_pci_clr_err(); - wrmces(0x7); - mb(); - } -#endif -#endif -} - -#endif /* CONFIG_ALPHA_TSUNAMI */ diff -u --recursive --new-file v2.1.115/linux/arch/alpha/lib/Makefile linux/arch/alpha/lib/Makefile --- v2.1.115/linux/arch/alpha/lib/Makefile Thu Feb 12 20:56:04 1998 +++ linux/arch/alpha/lib/Makefile Sun Aug 9 12:09:05 1998 @@ -7,7 +7,7 @@ strcat.o strcpy.o strncat.o strncpy.o stxcpy.o stxncpy.o \ strchr.o strrchr.o \ copy_user.o clear_user.o strncpy_from_user.o strlen_user.o \ - csum_ipv6_magic.o + csum_ipv6_magic.o strcasecmp.o lib.a: $(OBJS) $(AR) rcs lib.a $(OBJS) diff -u --recursive --new-file v2.1.115/linux/arch/alpha/lib/io.c linux/arch/alpha/lib/io.c --- v2.1.115/linux/arch/alpha/lib/io.c Tue Jul 21 00:15:29 1998 +++ linux/arch/alpha/lib/io.c Sun Aug 9 12:09:05 1998 @@ -6,23 +6,6 @@ #include #include -/* - * Jensen has a separate "local" and "bus" IO space for - * byte-wide IO. - */ -#ifdef __is_local - -unsigned int _bus_inb(unsigned long addr) -{ - return __bus_inb(addr); -} - -void _bus_outb(unsigned char b, unsigned long addr) -{ - __bus_outb(b, addr); -} -#endif - unsigned int _inb(unsigned long addr) { return __inb(addr); @@ -470,47 +453,57 @@ /* * "memset" on IO memory space. - * This needs to be optimized. */ void _memset_c_io(unsigned long to, unsigned long c, long count) { + /* Handle any initial odd byte */ if (count > 0 && (to & 1)) { writeb(c, to); to++; count--; } + + /* Handle any initial odd halfword */ if (count >= 2 && (to & 2)) { writew(c, to); to += 2; count -= 2; } + + /* Handle any initial odd word */ if (count >= 4 && (to & 4)) { writel(c, to); to += 4; count -= 4; } - if ((to & 7) == 0) { - count -= 8; - while (count >= 0) { + + /* Handle all full-sized quadwords: we're aligned (or have a small count) */ + count -= 8; + if (count >= 0) { + do { writeq(c, to); to += 8; count -= 8; - } - count += 8; + } while (count >= 0); } - if (count >= 4 && (to & 4)) { + count += 8; + + /* The tail is word-aligned if we still have count >= 4 */ + if (count >= 4) { writel(c, to); to += 4; count -= 4; } - if (count >= 2 && (to & 2)) { + + /* The tail is half-word aligned if we have count >= 2 */ + if (count >= 2) { writew(c, to); to += 2; count -= 2; } - while (count > 0) { + + /* And finally, one last byte.. */ + if (count) { writeb(c, to); - count--; - to++; } } diff -u --recursive --new-file v2.1.115/linux/arch/alpha/lib/strcasecmp.c linux/arch/alpha/lib/strcasecmp.c --- v2.1.115/linux/arch/alpha/lib/strcasecmp.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/lib/strcasecmp.c Sun Aug 9 12:09:05 1998 @@ -0,0 +1,26 @@ +/* + * linux/arch/alpha/lib/strcasecmp.c + */ + +#include + + +/* We handle nothing here except the C locale. Since this is used in + only one place, on strings known to contain only 7 bit ASCII, this + is ok. */ + +int strcasecmp(const char *a, const char *b) +{ + int ca, cb; + + do { + ca = *a++ & 0xff; + cb = *b++ & 0xff; + if (ca >= 'A' && ca <= 'Z') + ca += 'a' - 'A'; + if (cb >= 'A' && cb <= 'Z') + cb += 'a' - 'A'; + } while (ca == cb && ca != '\0'); + + return ca - cb; +} diff -u --recursive --new-file v2.1.115/linux/arch/alpha/math-emu/fp-emul.c linux/arch/alpha/math-emu/fp-emul.c --- v2.1.115/linux/arch/alpha/math-emu/fp-emul.c Tue Jul 21 00:15:29 1998 +++ linux/arch/alpha/math-emu/fp-emul.c Sun Aug 9 12:09:06 1998 @@ -61,23 +61,33 @@ MODULE_DESCRIPTION("FP Software completion module"); extern long (*alpha_fp_emul_imprecise)(struct pt_regs *, unsigned long); -static long (*save_emul)(struct pt_regs *, unsigned long); +extern long (*alpha_fp_emul) (unsigned long pc); + +static long (*save_emul_imprecise)(struct pt_regs *, unsigned long); +static long (*save_emul) (unsigned long pc); + long do_alpha_fp_emul_imprecise(struct pt_regs *, unsigned long); +long do_alpha_fp_emul(unsigned long); int init_module(void) { - save_emul = alpha_fp_emul_imprecise; + save_emul_imprecise = alpha_fp_emul_imprecise; + save_emul = alpha_fp_emul; alpha_fp_emul_imprecise = do_alpha_fp_emul_imprecise; + alpha_fp_emul = do_alpha_fp_emul; return 0; } void cleanup_module(void) { - alpha_fp_emul_imprecise = save_emul; + alpha_fp_emul_imprecise = save_emul_imprecise; + alpha_fp_emul = save_emul; } -#undef alpha_fp_emul_imprecise -#define alpha_fp_emul_imprecise do_alpha_fp_emul_imprecise +#undef alpha_fp_emul_imprecise +#define alpha_fp_emul_imprecise do_alpha_fp_emul_imprecise +#undef alpha_fp_emul +#define alpha_fp_emul do_alpha_fp_emul #endif /* MODULE */ @@ -96,6 +106,8 @@ unsigned long va, vb, vc, res, fpcr; __u32 insn; + MOD_INC_USE_COUNT; + get_user(insn, (__u32*)pc); fc = (insn >> 0) & 0x1f; /* destination register */ func = (insn >> 5) & 0x7ff; @@ -105,8 +117,8 @@ va = alpha_read_fp_reg(fa); vb = alpha_read_fp_reg(fb); - fpcr = rdfpcr(); + /* * Try the operation in software. First, obtain the rounding * mode... @@ -213,8 +225,10 @@ default: printk("alpha_fp_emul: unexpected function code %#lx at %#lx\n", func & 0x3f, pc); + MOD_DEC_USE_COUNT; return 0; } + /* * Take the appropriate action for each possible * floating-point result: @@ -237,8 +251,10 @@ wrfpcr(fpcr); /* Do we generate a signal? */ - if (res >> 51 & fpcw & IEEE_TRAP_ENABLE_MASK) + if (res >> 51 & fpcw & IEEE_TRAP_ENABLE_MASK) { + MOD_DEC_USE_COUNT; return 0; + } } /* @@ -247,6 +263,8 @@ * result: */ alpha_write_fp_reg(fc, vc); + + MOD_DEC_USE_COUNT; return 1; } diff -u --recursive --new-file v2.1.115/linux/arch/alpha/mm/fault.c linux/arch/alpha/mm/fault.c --- v2.1.115/linux/arch/alpha/mm/fault.c Wed Jun 24 22:54:03 1998 +++ linux/arch/alpha/mm/fault.c Thu Aug 13 15:36:46 1998 @@ -4,23 +4,30 @@ * Copyright (C) 1995 Linus Torvalds */ -#include #include -#include #include +#include + +#define __EXTERN_INLINE inline +#include +#include +#undef __EXTERN_INLINE + +#include +#include #include #include #include #include #include -#include #include #include #include #include -#include -#include + +extern void die_if_kernel(char *,struct pt_regs *,long, unsigned long *); + #ifdef __SMP__ unsigned long last_asn[NR_CPUS] = { /* gag */ @@ -61,21 +68,26 @@ unsigned long asn_cache = ASN_FIRST_VERSION; #endif /* __SMP__ */ -#ifndef BROKEN_ASN /* - * Select a new ASN and reload the context. This is - * not inlined as this expands to a pretty large - * function. + * Select a new ASN for a task. */ -void get_new_asn_and_reload(struct task_struct *tsk, struct mm_struct *mm) + +void +get_new_mmu_context(struct task_struct *p, struct mm_struct *mm) { - mm->context = 0; - get_new_mmu_context(tsk, mm); - reload_context(tsk); -} -#endif + unsigned long asn = asn_cache; -extern void die_if_kernel(char *,struct pt_regs *,long, unsigned long *); + if ((asn & HARDWARE_ASN_MASK) < MAX_ASN) + ++asn; + else { + tbiap(); + imb(); + asn = (asn & ~HARDWARE_ASN_MASK) + ASN_FIRST_VERSION; + } + asn_cache = asn; + mm->context = asn; /* full version + asn */ + p->tss.asn = asn & HARDWARE_ASN_MASK; /* just asn */ +} /* * This routine handles page faults. It determines the address, @@ -99,12 +111,13 @@ */ /* Macro for exception fixup code to access integer registers. */ -#define dpf_reg(r) \ - (((unsigned long *)regs)[(r) <= 8 ? (r) : (r) <= 15 ? (r)-16 : \ +#define dpf_reg(r) \ + (((unsigned long *)regs)[(r) <= 8 ? (r) : (r) <= 15 ? (r)-16 : \ (r) <= 18 ? (r)+8 : (r)-10]) -asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr, - long cause, struct pt_regs *regs) +asmlinkage void +do_page_fault(unsigned long address, unsigned long mmcsr, + long cause, struct pt_regs *regs) { struct vm_area_struct * vma; struct mm_struct *mm = current->mm; diff -u --recursive --new-file v2.1.115/linux/arch/alpha/mm/init.c linux/arch/alpha/mm/init.c --- v2.1.115/linux/arch/alpha/mm/init.c Thu Aug 6 14:06:28 1998 +++ linux/arch/alpha/mm/init.c Sun Aug 9 12:09:06 1998 @@ -32,19 +32,22 @@ struct pgtable_cache_struct quicklists; #endif -void __bad_pmd(pgd_t *pgd) +void +__bad_pmd(pgd_t *pgd) { printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd)); pgd_set(pgd, BAD_PAGETABLE); } -void __bad_pte(pmd_t *pmd) +void +__bad_pte(pmd_t *pmd) { printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); pmd_set(pmd, (pte_t *) BAD_PAGETABLE); } -pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset) +pmd_t * +get_pmd_slow(pgd_t *pgd, unsigned long offset) { pmd_t *pmd; @@ -66,7 +69,8 @@ return (pmd_t *) pgd_page(*pgd) + offset; } -pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) +pte_t * +get_pte_slow(pmd_t *pmd, unsigned long offset) { pte_t *pte; @@ -117,22 +121,25 @@ * ZERO_PAGE is a special page that is used for zero-initialized * data and COW. */ -pmd_t * __bad_pagetable(void) +pmd_t * +__bad_pagetable(void) { memset((void *) EMPTY_PGT, 0, PAGE_SIZE); return (pmd_t *) EMPTY_PGT; } -pte_t __bad_page(void) +pte_t +__bad_page(void) { memset((void *) EMPTY_PGE, 0, PAGE_SIZE); return pte_mkdirty(mk_pte((unsigned long) EMPTY_PGE, PAGE_SHARED)); } -void show_mem(void) +void +show_mem(void) { - int i,free = 0,total = 0,reserved = 0; - int shared = 0, cached = 0; + long i,free = 0,total = 0,reserved = 0; + long shared = 0, cached = 0; printk("\nMem-info:\n"); show_free_areas(); @@ -149,12 +156,12 @@ else shared += atomic_read(&mem_map[i].count) - 1; } - printk("%d pages of RAM\n",total); - printk("%d free pages\n",free); - printk("%d reserved pages\n",reserved); - printk("%d pages shared\n",shared); - printk("%d pages swap cached\n",cached); - printk("%d pages in page table cache\n",pgtable_cache_size); + printk("%ld pages of RAM\n",total); + printk("%ld free pages\n",free); + printk("%ld reserved pages\n",reserved); + printk("%ld pages shared\n",shared); + printk("%ld pages swap cached\n",cached); + printk("%ld pages in page table cache\n",pgtable_cache_size); show_buffers(); #ifdef CONFIG_NET show_net_buffers(); @@ -163,29 +170,20 @@ extern unsigned long free_area_init(unsigned long, unsigned long); -static struct thread_struct * load_PCB(struct thread_struct * pcb) +static struct thread_struct * +load_PCB(struct thread_struct * pcb) { - struct thread_struct *old_pcb; - - __asm__ __volatile__( - "stq $30,0(%1)\n\t" - "bis %1,%1,$16\n\t" -#ifdef CONFIG_ALPHA_DP264 - "zap $16,0xe0,$16\n\t" -#endif /* DP264 */ - "call_pal %2\n\t" - "bis $0,$0,%0" - : "=r" (old_pcb) - : "r" (pcb), "i" (PAL_swpctx) - : "$0", "$1", "$16", "$22", "$23", "$24", "$25"); - return old_pcb; + register unsigned long sp __asm__("$30"); + pcb->ksp = sp; + return __reload_tss(pcb); } /* * paging_init() sets up the page tables: in the alpha version this actually * unmaps the bootup page table (as we're now in KSEG, so we don't need it). */ -unsigned long paging_init(unsigned long start_mem, unsigned long end_mem) +unsigned long +paging_init(unsigned long start_mem, unsigned long end_mem) { int i; unsigned long newptbr; @@ -242,7 +240,8 @@ * note that current should be pointing at the idle thread task struct * for this CPU. */ -void paging_init_secondary(void) +void +paging_init_secondary(void) { current->tss.ptbr = init_task.tss.ptbr; current->tss.pal_flags = 1; @@ -260,7 +259,8 @@ } #endif /* __SMP__ */ -void mem_init(unsigned long start_mem, unsigned long end_mem) +void +mem_init(unsigned long start_mem, unsigned long end_mem) { unsigned long tmp; @@ -291,7 +291,8 @@ return; } -void free_initmem (void) +void +free_initmem (void) { extern char __init_begin, __init_end; unsigned long addr; @@ -306,7 +307,8 @@ (&__init_end - &__init_begin) >> 10); } -void si_meminfo(struct sysinfo *val) +void +si_meminfo(struct sysinfo *val) { int i; diff -u --recursive --new-file v2.1.115/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S --- v2.1.115/linux/arch/i386/kernel/entry.S Thu Aug 6 14:06:28 1998 +++ linux/arch/i386/kernel/entry.S Tue Aug 18 16:48:38 1998 @@ -106,19 +106,22 @@ 1: popl %ds; \ 2: popl %es; \ 3: addl $4,%esp; \ - iret; \ +4: iret; \ .section fixup,"ax"; \ -4: pushl $0; \ +5: pushl $0; \ popl %ds; \ jmp 2b; \ -5: pushl $0; \ +6: pushl $0; \ popl %es; \ jmp 3b; \ +7: pushl $11; \ + call do_exit; \ .previous; \ .section __ex_table,"a";\ .align 4; \ - .long 1b,4b; \ - .long 2b,5b; \ + .long 1b,5b; \ + .long 2b,6b; \ + .long 4b,7b; \ .previous #define GET_CURRENT(reg) \ @@ -255,19 +258,8 @@ decl %eax # eax = -1 pushl %ecx pushl %ebx -#if 1 - xorl %ecx,%ecx # zero ecx - cld - mov %es,%cx # get the lower order bits of es -#else cld -# Some older processors leave the top 16 bits of the 32 bit destination -# register undefined, rather than zeroed in the following instruction. -# This won't matter when restoring or loading a segment register from the -# stack. It may be a problem if any code reads the full 32 bit value. -# dosemu? kernel? Would somebody like to verify that this way is really OK? movl %es,%cx -#endif xchgl %eax, ORIG_EAX(%esp) # orig_eax (get the error code. ) movl %esp,%edx xchgl %ecx, ES(%esp) # get the address and save es. @@ -396,7 +388,7 @@ .long SYMBOL_NAME(sys_lseek) .long SYMBOL_NAME(sys_getpid) /* 20 */ .long SYMBOL_NAME(sys_mount) - .long SYMBOL_NAME(sys_umount) + .long SYMBOL_NAME(sys_oldumount) .long SYMBOL_NAME(sys_setuid) .long SYMBOL_NAME(sys_getuid) .long SYMBOL_NAME(sys_stime) /* 25 */ @@ -426,7 +418,7 @@ .long SYMBOL_NAME(sys_geteuid) .long SYMBOL_NAME(sys_getegid) /* 50 */ .long SYMBOL_NAME(sys_acct) - .long SYMBOL_NAME(sys_ni_syscall) /* old phys syscall holder */ + .long SYMBOL_NAME(sys_umount) /* recycled never used phys() */ .long SYMBOL_NAME(sys_ni_syscall) /* old lock syscall holder */ .long SYMBOL_NAME(sys_ioctl) .long SYMBOL_NAME(sys_fcntl) /* 55 */ diff -u --recursive --new-file v2.1.115/linux/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S --- v2.1.115/linux/arch/i386/kernel/head.S Thu Jul 16 18:09:23 1998 +++ linux/arch/i386/kernel/head.S Sat Aug 8 10:44:15 1998 @@ -241,9 +241,6 @@ #endif xorl %eax,%eax lldt %ax - pushl %eax # These are the parameters to main :-) - pushl %eax - pushl %eax cld # gcc2 wants the direction flag cleared at all times call SYMBOL_NAME(start_kernel) L6: diff -u --recursive --new-file v2.1.115/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c --- v2.1.115/linux/arch/i386/kernel/io_apic.c Thu Aug 6 14:06:28 1998 +++ linux/arch/i386/kernel/io_apic.c Mon Aug 10 09:06:00 1998 @@ -1177,7 +1177,7 @@ pirqs_enabled) { printk("ENABLING IO-APIC IRQs\n"); - io_apic_irqs = ~((1<<2)|(1<<13)); + io_apic_irqs = ~((1<<2)|(1<<9)|(1<<13)); } else { if (ioapic_blacklisted()) printk(" blacklisted board, DISABLING IO-APIC IRQs\n"); diff -u --recursive --new-file v2.1.115/linux/arch/i386/kernel/ldt.c linux/arch/i386/kernel/ldt.c --- v2.1.115/linux/arch/i386/kernel/ldt.c Thu Jul 16 18:09:23 1998 +++ linux/arch/i386/kernel/ldt.c Sat Aug 15 16:34:52 1998 @@ -36,9 +36,7 @@ static int write_ldt(void * ptr, unsigned long bytecount, int oldmode) { struct mm_struct * mm = current->mm; - void * ldt; __u32 entry_1, entry_2, *lp; - __u16 selector, reg_fs, reg_gs; int error; struct modify_ldt_ldt_s ldt_info; @@ -70,8 +68,8 @@ * For no good reason except historical, the GDT index of the LDT * is chosen to follow the index number in the task[] array. */ - ldt = mm->segments; - if (!ldt) { + if (!mm->segments) { + void * ldt; error = -ENOMEM; ldt = vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE); if (!ldt) @@ -85,7 +83,7 @@ mm->segments = ldt; set_ldt_desc(gdt+(i<<1)+FIRST_LDT_ENTRY, ldt, LDT_ENTRIES); load_ldt(i); - if (mm->count > 1) + if (atomic_read(&mm->count) > 1) printk(KERN_WARNING "LDT allocated for cloned task!\n"); } else { @@ -93,19 +91,7 @@ } } - /* - * Check whether the entry to be changed is currently in use. - * If it is, we may need extra validation checks in case the - * kernel is forced to save and restore the selector. - * - * Note: we check the fs and gs values as well, as these are - * loaded by the signal code and during a task switch. - */ - selector = (ldt_info.entry_number << 3) | 4; - __asm__("movw %%fs,%0" : "=r"(reg_fs)); - __asm__("movw %%gs,%0" : "=r"(reg_gs)); - - lp = (__u32 *) ((selector & ~7) + (char *) ldt); + lp = (__u32 *) ((ldt_info.entry_number << 3) + (char *) mm->segments); /* Allow LDTs to be cleared by the user. */ if (ldt_info.base_addr == 0 && ldt_info.limit == 0) { @@ -118,7 +104,7 @@ ldt_info.useable == 0 )) { entry_1 = 0; entry_2 = 0; - goto out_check; + goto install; } } @@ -136,8 +122,8 @@ if (!oldmode) entry_2 |= (ldt_info.useable << 20); -out_check: - /* OK to change the entry ... */ + /* Install the new entry ... */ +install: *lp = entry_1; *(lp+1) = entry_2; error = 0; diff -u --recursive --new-file v2.1.115/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c --- v2.1.115/linux/arch/i386/kernel/process.c Thu Aug 6 14:06:28 1998 +++ linux/arch/i386/kernel/process.c Thu Aug 13 10:11:23 1998 @@ -582,27 +582,6 @@ #define savesegment(seg,value) \ asm volatile("movl %%" #seg ",%0":"=m" (*(int *)&(value))) -/* - * Load a segment. Fall back on loading the zero - * segment if something goes wrong.. - */ -#define loadsegment(seg,value) \ - asm volatile("\n" \ - "1:\t" \ - "movl %0,%%" #seg "\n" \ - "2:\n" \ - ".section fixup,\"ax\"\n" \ - "3:\t" \ - "pushl $0\n\t" \ - "popl %%" #seg "\n\t" \ - "jmp 2b\n" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n\t" \ - ".align 4\n\t" \ - ".long 1b,3b\n" \ - ".previous" \ - : :"m" (*(unsigned int *)&(value))) - int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, struct task_struct * p, struct pt_regs * regs) { diff -u --recursive --new-file v2.1.115/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- v2.1.115/linux/arch/i386/kernel/setup.c Tue Jul 21 00:15:30 1998 +++ linux/arch/i386/kernel/setup.c Mon Aug 10 09:12:56 1998 @@ -36,6 +36,7 @@ #include #include #include +#include #include /* @@ -81,12 +82,10 @@ extern int root_mountflags; extern int _etext, _edata, _end; -extern char empty_zero_page[PAGE_SIZE]; - /* * This is set up by the setup-routine at boot-time */ -#define PARAM empty_zero_page +#define PARAM ((unsigned char *)empty_zero_page) #define EXT_MEM_K (*(unsigned short *) (PARAM+2)) #define ALT_MEM_K (*(unsigned long *) (PARAM+0x1e0)) #ifdef CONFIG_APM diff -u --recursive --new-file v2.1.115/linux/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c --- v2.1.115/linux/arch/i386/kernel/signal.c Thu Jul 16 18:09:23 1998 +++ linux/arch/i386/kernel/signal.c Thu Aug 13 10:17:59 1998 @@ -178,12 +178,13 @@ static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *peax) { - unsigned int tmp, err = 0; + unsigned int err = 0; #define COPY(x) err |= __get_user(regs->x, &sc->x) #define COPY_SEG(seg) \ - { err |= __get_user(tmp, &sc->seg); \ + { unsigned short tmp; \ + err |= __get_user(tmp, &sc->seg); \ if ((tmp & 0xfffc) /* not a NULL selectors */ \ && (tmp & 0x4) != 0x4 /* not a LDT selector */ \ && (tmp & 3) != 3) /* not a RPL3 GDT selector */ \ @@ -191,17 +192,19 @@ regs->x##seg = tmp; } #define COPY_SEG_STRICT(seg) \ - { err |= __get_user(tmp, &sc->seg); \ + { unsigned short tmp; \ + err |= __get_user(tmp, &sc->seg); \ if ((tmp & 0xfffc) && (tmp & 3) != 3) goto badframe; \ regs->x##seg = tmp; } #define GET_SEG(seg) \ - { err |= __get_user(tmp, &sc->seg); \ + { unsigned short tmp; \ + err |= __get_user(tmp, &sc->seg); \ if ((tmp & 0xfffc) /* not a NULL selectors */ \ && (tmp & 0x4) != 0x4 /* not a LDT selector */ \ && (tmp & 3) != 3) /* not a RPL3 GDT selector */ \ goto badframe; \ - __asm__ __volatile__("movl %w0,%%" #seg : : "r"(tmp)); } + loadsegment(seg,tmp); } GET_SEG(gs); GET_SEG(fs); @@ -218,16 +221,21 @@ COPY_SEG_STRICT(cs); COPY_SEG_STRICT(ss); - err |= __get_user(tmp, &sc->eflags); - regs->eflags = (regs->eflags & ~0x40DD5) | (tmp & 0x40DD5); - regs->orig_eax = -1; /* disable syscall checks */ - - err |= __get_user(tmp, (unsigned long *)&sc->fpstate); - if (tmp) { - struct _fpstate * buf = (struct _fpstate *) tmp; - if (verify_area(VERIFY_READ, buf, sizeof(*buf))) - goto badframe; - err |= restore_i387(buf); + { + unsigned int tmpflags; + err |= __get_user(tmpflags, &sc->eflags); + regs->eflags = (regs->eflags & ~0x40DD5) | (tmpflags & 0x40DD5); + regs->orig_eax = -1; /* disable syscall checks */ + } + + { + struct _fpstate * buf; + err |= __get_user(buf, &sc->fpstate); + if (buf) { + if (verify_area(VERIFY_READ, buf, sizeof(*buf))) + goto badframe; + err |= restore_i387(buf); + } } err |= __get_user(*peax, &sc->eax); diff -u --recursive --new-file v2.1.115/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c --- v2.1.115/linux/arch/i386/kernel/smp.c Tue Jul 28 14:21:07 1998 +++ linux/arch/i386/kernel/smp.c Sat Aug 15 00:40:21 1998 @@ -658,6 +658,7 @@ { unsigned long apic_phys, ioapic_phys; + memory_start = PAGE_ALIGN(memory_start); if (smp_found_config) { apic_phys = mp_lapic_addr; ioapic_phys = mp_ioapic_addr; @@ -749,7 +750,11 @@ /* * We don't actually need to load the full TSS, * basically just the stack pointer and the eip. + * + * Get the scheduler lock, because we're going + * to release it as part of the "reschedule" return. */ + spin_lock(&scheduler_lock); asm volatile("lldt %%ax": :"a" (p->ldt)); asm volatile("ltr %%ax": :"a" (p->tr)); asm volatile( diff -u --recursive --new-file v2.1.115/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c --- v2.1.115/linux/arch/i386/kernel/traps.c Mon Aug 3 17:48:26 1998 +++ linux/arch/i386/kernel/traps.c Mon Aug 10 13:46:50 1998 @@ -42,12 +42,10 @@ #define DO_ERROR(trapnr, signr, str, name, tsk) \ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ { \ - lock_kernel(); \ tsk->tss.error_code = error_code; \ tsk->tss.trap_no = trapnr; \ force_sig(signr, tsk); \ - die_if_kernel(str,regs,error_code); \ - unlock_kernel(); \ + die_if_no_fixup(str,regs,error_code); \ } #define DO_VM86_ERROR(trapnr, signr, str, name, tsk) \ @@ -191,6 +189,20 @@ die(str, regs, err); } +static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err) +{ + if (!(regs->eflags & VM_MASK) && !(3 & regs->xcs)) + { + unsigned long fixup; + fixup = search_exception_table(regs->eip); + if (fixup) { + regs->eip = fixup; + return; + } + die(str, regs, err); + } +} + DO_VM86_ERROR( 0, SIGFPE, "divide error", divide_error, current) DO_VM86_ERROR( 3, SIGTRAP, "int3", int3, current) DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow, current) @@ -228,10 +240,9 @@ if (!(regs->xcs & 3)) goto gp_in_kernel; - lock_kernel(); current->tss.error_code = error_code; current->tss.trap_no = 13; - force_sig(SIGSEGV, current); + force_sig(SIGSEGV, current); return; gp_in_vm86: @@ -453,9 +464,7 @@ /* * Allocate a new page in virtual address space, - * and move the IDT to have entry #7 starting at - * the beginning of the page. We'll force a page - * fault for IDT entries #0-#6.. + * move the IDT into it and write protect this page. */ page = (unsigned long) vmalloc(PAGE_SIZE); memcpy((void *) page, idt_table, 256*8); diff -u --recursive --new-file v2.1.115/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c --- v2.1.115/linux/arch/i386/mm/init.c Thu Aug 6 14:06:28 1998 +++ linux/arch/i386/mm/init.c Mon Aug 10 17:03:47 1998 @@ -210,15 +210,15 @@ /* * allocate page table(s) for compile-time fixed mappings */ -static unsigned long fixmap_init (unsigned long start_mem) +static unsigned long __init fixmap_init(unsigned long start_mem) { pgd_t * pg_dir; unsigned int idx; unsigned long address; - start_mem &= PAGE_MASK; + start_mem = PAGE_ALIGN(start_mem); - for (idx=1; idx < __end_of_fixed_addresses; idx += PTRS_PER_PTE) + for (idx=1; idx <= __end_of_fixed_addresses; idx += PTRS_PER_PTE) { address = fix_to_virt(__end_of_fixed_addresses-idx); pg_dir = swapper_pg_dir + (address >> PGDIR_SHIFT); diff -u --recursive --new-file v2.1.115/linux/arch/m68k/config.in linux/arch/m68k/config.in --- v2.1.115/linux/arch/m68k/config.in Thu Aug 6 14:06:28 1998 +++ linux/arch/m68k/config.in Mon Aug 10 11:02:24 1998 @@ -235,11 +235,23 @@ tristate 'PAMsNet support' CONFIG_ATARI_PAMSNET fi fi +fi endmenu fi + +source fs/Config.in + +if [ "$CONFIG_VME" = "n" ]; then + define_bool CONFIG_FB y + mainmenu_option next_comment + comment 'Console drivers' + source drivers/video/Config.in + endmenu fi +source fs/nls/Config.in + mainmenu_option next_comment comment 'Character devices' @@ -254,7 +266,7 @@ define_bool CONFIG_NVRAM y fi -tristate 'Parallel printer support' CONFIG_PRINTER +tristate 'Parallel printer support' CONFIG_M68K_PRINTER if [ "$CONFIG_ZORRO" = "y" ]; then dep_tristate 'Multiface Card III parallel support' CONFIG_MULTIFACE_III_LP $CONFIG_PRINTER fi @@ -334,14 +346,6 @@ fi endmenu -source fs/Config.in - -if [ "$CONFIG_VME" = "n" ]; then - define_bool CONFIG_FB y - source drivers/video/Config.in -fi - -source fs/nls/Config.in mainmenu_option next_comment comment 'Sound support' diff -u --recursive --new-file v2.1.115/linux/arch/m68k/defconfig linux/arch/m68k/defconfig --- v2.1.115/linux/arch/m68k/defconfig Thu Aug 6 14:06:28 1998 +++ linux/arch/m68k/defconfig Mon Aug 10 11:02:24 1998 @@ -196,7 +196,7 @@ # CONFIG_VT=y CONFIG_VT_CONSOLE=y -# CONFIG_PRINTER is not set +# CONFIG_M68K_PRINTER is not set CONFIG_AMIGAMOUSE=y CONFIG_ATARIMOUSE=y CONFIG_AMIGA_BUILTIN_SERIAL=y diff -u --recursive --new-file v2.1.115/linux/arch/m68k/fpsp040/skeleton.S linux/arch/m68k/fpsp040/skeleton.S --- v2.1.115/linux/arch/m68k/fpsp040/skeleton.S Mon Jun 16 16:35:53 1997 +++ linux/arch/m68k/fpsp040/skeleton.S Mon Aug 10 11:02:24 1998 @@ -378,14 +378,12 @@ beq Lnotkern rte Lnotkern: - tstl SYMBOL_NAME(need_resched) - bne Lmustsched - rte -Lmustsched: SAVE_ALL_INT GET_CURRENT(%d0) - bral SYMBOL_NAME(ret_from_exception) | deliver signals, reschedule etc.. - + tstl %curptr@(LTASK_NEEDRESCHED) + jne SYMBOL_NAME(ret_from_exception) | deliver signals, + | reschedule etc.. + RESTORE_ALL | | mem_write --- write to user or supervisor address space diff -u --recursive --new-file v2.1.115/linux/arch/m68k/kernel/entry.S linux/arch/m68k/kernel/entry.S --- v2.1.115/linux/arch/m68k/kernel/entry.S Mon Aug 3 12:45:44 1998 +++ linux/arch/m68k/kernel/entry.S Mon Aug 10 11:02:24 1998 @@ -583,6 +583,10 @@ .long SYMBOL_NAME(sys_capget) .long SYMBOL_NAME(sys_capset) /* 185 */ .long SYMBOL_NAME(sys_sigaltstack) + .long SYMBOL_NAME(sys_sendfile) + .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */ + .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */ + .rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4 .long SYMBOL_NAME(sys_ni_syscall) .endr diff -u --recursive --new-file v2.1.115/linux/arch/m68k/kernel/m68k_defs.h linux/arch/m68k/kernel/m68k_defs.h --- v2.1.115/linux/arch/m68k/kernel/m68k_defs.h Mon Aug 3 12:45:44 1998 +++ linux/arch/m68k/kernel/m68k_defs.h Mon Aug 10 11:02:24 1998 @@ -3,6 +3,6 @@ */ #define TS_MAGICKEY 0x5a5a5a5a -#define TS_TSS 462 -#define TS_ESP0 482 -#define TS_FPU 486 +#define TS_TSS 478 +#define TS_ESP0 498 +#define TS_FPU 502 diff -u --recursive --new-file v2.1.115/linux/arch/m68k/kernel/m68k_ksyms.c linux/arch/m68k/kernel/m68k_ksyms.c --- v2.1.115/linux/arch/m68k/kernel/m68k_ksyms.c Wed Jul 1 19:38:53 1998 +++ linux/arch/m68k/kernel/m68k_ksyms.c Mon Aug 10 11:02:24 1998 @@ -7,7 +7,6 @@ #include #include #include -#include #include #include diff -u --recursive --new-file v2.1.115/linux/arch/m68k/kernel/sys_m68k.c linux/arch/m68k/kernel/sys_m68k.c --- v2.1.115/linux/arch/m68k/kernel/sys_m68k.c Mon Aug 3 12:45:44 1998 +++ linux/arch/m68k/kernel/sys_m68k.c Mon Aug 10 11:02:24 1998 @@ -66,12 +66,11 @@ struct file * file = NULL; struct mmap_arg_struct a; - down(¤t->mm->mmap_sem); - lock_kernel(); - error = -EFAULT; if (copy_from_user(&a, arg, sizeof(a))) - goto out; + return -EFAULT; + down(¤t->mm->mmap_sem); + lock_kernel(); if (!(a.flags & MAP_ANONYMOUS)) { error = -EBADF; file = fget(a.fd); diff -u --recursive --new-file v2.1.115/linux/arch/m68k/mac/adb-bus.c linux/arch/m68k/mac/adb-bus.c --- v2.1.115/linux/arch/m68k/mac/adb-bus.c Tue Jun 23 10:01:21 1998 +++ linux/arch/m68k/mac/adb-bus.c Mon Aug 10 11:02:24 1998 @@ -107,6 +107,7 @@ static void adb_input(unsigned char *buf, int nb, struct pt_regs *regs); static void adb_hw_setup_IIsi(void); +static void adb_hw_setup_cuda(void); /* * debug level 10 required for ADB logging (should be && debug_adb, ideally) @@ -206,10 +207,14 @@ */ case MAC_ADB_CUDA: printk("adb: CUDA interface.\n"); +#if 0 /* don't know what to set up here ... */ adb_state = idle; /* Set the lines up. We want TREQ as input TACK|TIP as output */ via_write(via1, vDirB, ((via_read(via1,vDirB)|TACK|TIP)&~TREQ)); +#endif + adb_hw_setup_cuda(); + adb_state = idle; request_irq(IRQ_MAC_ADB, adb_cuda_interrupt, IRQ_FLG_LOCK, "adb CUDA interrupt", adb_cuda_interrupt); break; @@ -281,6 +286,115 @@ restore_flags(flags); } +void adb_hw_setup_cuda(void) +{ + int x; + unsigned long flags; + + printk("CUDA: HW Setup:"); + + save_flags(flags); + cli(); + + if (console_loglevel == 10) + printk(" 1,"); + + /* Set the direction of the cuda signals, TIP+TACK are output TREQ is an input */ + via_write( via1, vDirB, via_read( via1, vDirB ) | TIP | TACK ); + via_write( via1, vDirB, via_read( via1, vDirB ) & ~TREQ ); + + if (console_loglevel == 10) + printk("2,"); + + /* Set the clock control. Set to shift data in by external clock CB1 */ + via_write( via1, vACR, ( via_read(via1, vACR ) | SR_EXT ) & ~SR_OUT ); + + if (console_loglevel == 10) + printk("3,"); + + /* Clear any possible Cuda interrupt */ + x = via_read( via1, vSR ); + + if (console_loglevel == 10) + printk("4,"); + + /* Terminate transaction and set idle state */ + via_write( via1, vBufB, via_read( via1, vBufB ) | TIP | TACK ); + + if (console_loglevel == 10) + printk("5,"); + + /* Delay 4 mS for ADB reset to complete */ + udelay(4000); + + if (console_loglevel == 10) + printk("6,"); + + /* Clear pending interrupts... */ + x = via_read( via1, vSR ); + + if (console_loglevel == 10) + printk("7,"); + /* Issue a sync transaction, TACK asserted while TIP negated */ + via_write( via1, vBufB, via_read( via1, vBufB ) & ~TACK ); + + if (console_loglevel == 10) + printk("8,"); + + /* Wait for the sync acknowledgement, Cuda to assert TREQ */ + while( ( via_read( via1, vBufB ) & TREQ ) != 0 ) + barrier(); + + if (console_loglevel == 10) + printk("9,"); + + /* Wait for the sync acknowledment interrupt */ + while( ( via_read( via1, vIFR ) & SR_INT ) == 0 ) + barrier(); + + if (console_loglevel == 10) + printk("10,"); + + /* Clear pending interrupts... */ + x = via_read( via1, vSR ); + + if (console_loglevel == 10) + printk("11,"); + + /* Terminate the sync cycle by negating TACK */ + via_write( via1, vBufB, via_read( via1, vBufB ) | TACK ); + + if (console_loglevel == 10) + printk("12,"); + + /* Wait for the sync termination acknowledgement, Cuda to negate TREQ */ + while( ( via_read( via1, vBufB ) & TREQ ) == 0 ) + barrier(); + + if (console_loglevel == 10) + printk("13,"); + + /* Wait for the sync termination acknowledment interrupt */ + while( ( via_read( via1, vIFR ) & SR_INT ) == 0 ) + barrier(); + + if (console_loglevel == 10) + printk("14,"); + + /* Terminate transaction and set idle state, TIP+TACK negate */ + via_write( via1, vBufB, via_read( via1, vBufB ) | TIP ); + + if (console_loglevel == 10) + printk("15 !"); + + /* Clear pending interrupts... */ + x = via_read( via1, vSR ); + + restore_flags(flags); + + printk("\nCUDA: HW Setup done!\n"); +} + void adb_hw_setup_IIsi(void) { int dummy; diff -u --recursive --new-file v2.1.115/linux/arch/m68k/mac/config.c linux/arch/m68k/mac/config.c --- v2.1.115/linux/arch/m68k/mac/config.c Mon Aug 3 12:45:44 1998 +++ linux/arch/m68k/mac/config.c Mon Aug 10 11:02:24 1998 @@ -35,6 +35,7 @@ #include #include +#include #include "via6522.h" @@ -60,24 +61,43 @@ /* The phys. video addr. - might be bogus on some machines */ unsigned long mac_orig_videoaddr; +/* Mac specific keyboard functions */ extern int mac_keyb_init(void); extern int mac_kbdrate(struct kbd_repeat *k); extern void mac_kbd_leds(unsigned int leds); extern void mac_kbd_reset_setup(char*, int); +/* Mac specific irq functions */ +extern void mac_init_IRQ (void); +extern void (*mac_handlers[]) (int, void *, struct pt_regs *); +extern int mac_request_irq (unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long flags, const char *devname, + void *dev_id); +extern void mac_free_irq (unsigned int irq, void *dev_id); +extern void mac_enable_irq (unsigned int); +extern void mac_disable_irq (unsigned int); +static void mac_get_model(char *model); +/*static int mac_get_hardware_list(char *buffer);*/ +extern int mac_get_irq_list (char *); + +/* Mac specific timer functions */ +extern unsigned long mac_gettimeoffset (void); +extern void mac_gettod (int *, int *, int *, int *, int *, int *); +extern int mac_hwclk (int, struct hwclk_time *); +extern int mac_set_clock_mmss (unsigned long); +extern void via_init_clock(void (*func)(int, void *, struct pt_regs *)); + extern void (*kd_mksound)(unsigned int, unsigned int); extern void mac_mksound(unsigned int, unsigned int); extern int mac_floppy_init(void); extern void mac_floppy_setup(char *,int *); -extern void mac_gettod (int *, int *, int *, int *, int *, int *); - extern void nubus_sweep_video(void); -extern void via_init_clock(void (*func)(int, void *, struct pt_regs *)); -extern void mac_debugging_long(int, long); /* Mac specific debug functions (in debug.c) */ extern void mac_debug_init(void); +extern void mac_debugging_long(int, long); #ifdef CONFIG_MAGIC_SYSRQ @@ -108,17 +128,11 @@ via_init_clock(vector); } -unsigned long mac_gettimeoffset (void) -{ - return 0L; -} - extern int console_loglevel; /* * This function translates the boot timeval into a proper date, to initialize * the system time. - * Known problem: off by one after Feb. 27 on leap years */ void mac_gettod (int *yearp, int *monp, int *dayp, @@ -174,6 +188,26 @@ return; } +/* + * TBI: read and write hwclock + */ + +int mac_hwclk( int op, struct hwclk_time *t ) +{ + return 0; +} + +/* + * TBI: set minutes/seconds in hwclock + */ + +int mac_set_clock_mmss (unsigned long nowtime) +{ + short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60; + + return 0; +} + void mac_waitbut (void) { ; @@ -272,6 +306,8 @@ mach_get_irq_list = mac_get_irq_list; mach_gettimeoffset = mac_gettimeoffset; mach_gettod = mac_gettod; + mach_hwclk = mac_hwclk; + mach_set_clock_mmss = mac_set_clock_mmss; #if 0 mach_mksound = mac_mksound; #endif @@ -379,7 +415,7 @@ * 0xF9000000, via is like a MacII. We label it differently as some of the * stuff connected to VIA2 seems different. Better SCSI chip and ???? onboard ethernet * in all cases using a NatSemi SONIC. The 700, 900 and 950 have some I/O chips in the wrong - * place to confuse us. The 840 seems to have a scsi location of its own + * place to confuse us. The 840AV seems to have a scsi location of its own */ { MAC_MODEL_Q605, "Quadra 605", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, @@ -389,9 +425,9 @@ /* The Q700 does have a NS Sonic */ { MAC_MODEL_Q700, "Quadra 700", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2, MAC_ETHER_SONIC, MAC_NUBUS}, { MAC_MODEL_Q800, "Quadra 800", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS}, - /* Does the 840 have ethernet ??? documents seem to indicate its not quite a + /* Does the 840AV have ethernet ??? documents seem to indicate its not quite a Quadra in this respect ? */ - { MAC_MODEL_Q840, "Quadra 840", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_Q840, "Quadra 840AV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS}, /* These might have IOP problems */ { MAC_MODEL_Q900, "Quadra 900", MAC_ADB_IISI, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_IOP, MAC_ETHER_SONIC, MAC_NUBUS}, { MAC_MODEL_Q950, "Quadra 950", MAC_ADB_IISI, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_IOP, MAC_ETHER_SONIC, MAC_NUBUS}, @@ -418,7 +454,7 @@ { MAC_MODEL_C610, "Centris 610", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, { MAC_MODEL_C650, "Centris 650", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, - { MAC_MODEL_C660, "Centris 660AV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, + { MAC_MODEL_C660, "Centris 660AV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS}, /* * Power books - seem similar to early Quadras ? (most have 030 though) @@ -497,10 +533,10 @@ * Report booter data: */ printk (" Penguin bootinfo data:\n"); - printk (" Video: addr 0x%lx row 0x%lx depth %lx dimensions %d x %d\n", + printk (" Video: addr 0x%lx row 0x%lx depth %lx dimensions %ld x %ld\n", mac_bi_data.videoaddr, mac_bi_data.videorow, - mac_bi_data.videodepth, mac_bi_data.dimensions & 0xFFFF, - mac_bi_data.dimensions >> 16); + mac_bi_data.videodepth, (int) (mac_bi_data.dimensions & 0xFFFF), + (int) (mac_bi_data.dimensions >> 16)); printk (" Videological 0x%lx phys. 0x%lx, SCC at 0x%lx \n", mac_bi_data.videological, mac_orig_videoaddr, mac_bi_data.sccbase); @@ -522,6 +558,25 @@ /* * TODO: set the various fields in macintosh_config->hw_present here! */ + switch (macintosh_config->scsi_type) { + case MAC_SCSI_OLD: + MACHW_SET(MAC_SCSI_80); + break; + case MAC_SCSI_QUADRA: + case MAC_SCSI_QUADRA2: + case MAC_SCSI_QUADRA3: + MACHW_SET(MAC_SCSI_96); + if ((macintosh_config->ident == MAC_MODEL_Q900) || + (macintosh_config->ident == MAC_MODEL_Q950)) + MACHW_SET(MAC_SCSI_96_2); + break; + default: + printk("config.c: wtf: unknown scsi, using 53c80\n"); + MACHW_SET(MAC_SCSI_80); + break; + + } + } diff -u --recursive --new-file v2.1.115/linux/arch/m68k/mac/macints.c linux/arch/m68k/mac/macints.c --- v2.1.115/linux/arch/m68k/mac/macints.c Wed Jul 1 19:38:53 1998 +++ linux/arch/m68k/mac/macints.c Mon Aug 10 11:02:24 1998 @@ -189,6 +189,12 @@ void psc_irq(int irq, void *dev_id, struct pt_regs *regs); /* + * PSC hooks + */ + +extern void psc_init(void); + +/* * console_loglevel determines NMI handler function */ @@ -241,8 +247,7 @@ /* no real VIA2, the OSS seems _very_different */ via2_is_oss = 1; /* IIfx has OSS, at a different base address than RBV */ - if (macintosh_config->ident == MAC_MODEL_IIFX) - rbv_regp = (unsigned char *) OSS_BAS; + rbv_regp = (unsigned char *) OSS_BAS; sys_request_irq(2, oss_irq, IRQ_FLG_LOCK, "oss", oss_irq); } else { /* VIA2 is part of the RBV: different base, other offsets */ @@ -318,7 +323,7 @@ param_table[0] = &via1_param[0]; mac_irqs[0] = &via1_irqs[0]; - if (via2_is_rbv) { + if (via2_is_rbv || via2_is_oss) { via_table[1] = rbv_regp; handler_table[1] = &rbv_handler[0]; param_table[1] = &rbv_param[0]; @@ -656,10 +661,28 @@ int mac_irq_pending( unsigned int irq ) { + int pending = 0; + volatile unsigned char *via; + int srcidx = ((irq & IRQ_SRC_MASK)>>3) - 1; int irqidx = (irq & IRQ_IDX_MASK); - return (irq_flags[srcidx].pending & (1<= SRC_VIA2) + pending |= via_read(via, (0x100 + 0x10*srcidx))&(1<pc, fp->sr, fp); #endif for (i=0; i<100; i++) udelay(1000); + + if (in_nmi == 1) { + nmi_hold = 1; + printk("... pausing, press NMI to resume ..."); + } else { + printk(" ok!\n"); + nmi_hold = 0; + } + + barrier(); + + while (nmi_hold == 1) + udelay(1000); + +#if 0 scsi_mac_polled(); +#endif if ( console_loglevel >= 8 ) { #if 0 @@ -804,6 +848,7 @@ /* printk("NMI "); */ #endif } + in_nmi--; } /* @@ -1511,8 +1556,10 @@ #endif /* IDE hack for Quadra: uses Nubus interrupt without any slot bit set */ +#ifdef CONFIG_BLK_DEV_MAC_IDE if (mac_ide_intr_hook) mac_ide_intr_hook(IRQ_MAC_NUBUS, via, regs); +#endif while(1) { @@ -1523,9 +1570,11 @@ printk("nubus_irq: map %x mask %x\n", map, nubus_active); #endif if( (map = (map&nubus_active)) ==0 ) { +#ifdef CONFIG_BLK_DEV_MAC_IDE if (!mac_ide_intr_hook) printk("nubus_irq: nothing pending, map %x mask %x\n", map, nubus_active); +#endif nubus_irqs[7]++; break; } diff -u --recursive --new-file v2.1.115/linux/arch/m68k/mac/mackeyb.c linux/arch/m68k/mac/mackeyb.c --- v2.1.115/linux/arch/m68k/mac/mackeyb.c Mon Aug 3 12:45:44 1998 +++ linux/arch/m68k/mac/mackeyb.c Mon Aug 10 11:02:24 1998 @@ -642,11 +642,12 @@ ct=0; while (!autopoll_req.got_reply && ++ct<1000) { - adb_poll(); udelay(10); } - if(ct==1000) + if(ct==1000) { printk("Keyboard timed out.\n"); + autopoll_req.got_reply = 1; + } } /* @@ -654,7 +655,7 @@ * care of that for other Macs. */ - printk("Configuring keyboard\n"); + printk("Configuring keyboard:\n"); /* * turn on all leds - the keyboard driver will turn them back off @@ -668,17 +669,17 @@ * The polling stuff should go away as soon as the ADB driver is stable */ ct = 0; - adb_poll(); while (!led_request.got_reply && ++ct<1000) { - adb_poll(); udelay(10); } - if(ct==1000) - printk("Keyboard timed out.\n"); + if(ct==1000) { + printk("keyboard timed out.\n"); + led_request.got_reply = 1; + } #if 1 - printk("Configuring coding mode ...\n"); + printk("configuring coding mode ...\n"); /* * get the keyboard to send separate codes for @@ -688,14 +689,14 @@ ADB_WRITEREG(ADB_KEYBOARD, 3), 0, 3); ct=0; - adb_poll(); while (!confcod_req.got_reply && ++ct<1000) { - adb_poll(); udelay(10); } - if(ct==1000) - printk("Keyboard timed out.\n"); + if(ct==1000) { + printk("keyboard timed out.\n"); + confcod_req.got_reply = 1; + } #endif #if 0 /* seems to hurt, at least Geert's Mac */ @@ -710,10 +711,8 @@ ADB_WRITEREG(ADB_MOUSE, 3), 0x23, 4 ); ct=0; - adb_poll(); while (!mouse_req.got_reply && ++ct<1000) { - adb_poll(); udelay(10); } if(ct==1000) @@ -734,21 +733,15 @@ ADB_READREG(ADB_KEYBOARD, KEYB_KEYREG)); #endif - /* - * fake 'request done' for the driver if requests timed out - */ - - autopoll_req.got_reply = 1; -#if 0 - /* XXX: results in race and hang with mac_kbd_leds and serial (why ?) */ - led_request.got_reply = 1; -#endif - confcod_req.got_reply = 1; - in_keybinit = 0; - printk("Keyboard init done\n"); + printk("keyboard init done\n"); return 0; +} + +/* for "kbd-reset" cmdline param */ +__initfunc(void mac_kbd_reset_setup(char *str, int *ints)) +{ } /* for "kbd-reset" cmdline param */ diff -u --recursive --new-file v2.1.115/linux/arch/m68k/mac/via6522.c linux/arch/m68k/mac/via6522.c --- v2.1.115/linux/arch/m68k/mac/via6522.c Wed Jul 1 19:38:53 1998 +++ linux/arch/m68k/mac/via6522.c Mon Aug 10 11:02:24 1998 @@ -179,6 +179,32 @@ } /* + * get time offset between scheduling timer ticks + * Code stolen from arch/m68k/atari/time.c; underflow check probably + * wrong. + */ +#define TICK_SIZE 10000 + +/* This is always executed with interrupts disabled. */ +unsigned long mac_gettimeoffset (void) +{ + unsigned long ticks, offset = 0; + + /* read VIA1 timer 2 current value */ + ticks = via_read(via1, vT1CL) + (via_read(via1, vT1CH)<<8); + /* The probability of underflow is less than 2% */ + if (ticks > MAC_CLOCK_TICK - MAC_CLOCK_TICK / 50) + /* Check for pending timer interrupt in VIA1 IFR */ + if (via_read(via1, vIFR) & 0x40) + offset = TICK_SIZE; + + ticks = MAC_CLOCK_TICK - ticks; + ticks = ticks * 10000L / MAC_CLOCK_TICK; + + return ticks + offset; +} + +/* * PSC (AV Macs; level 3-6): initialize interrupt enable registers */ diff -u --recursive --new-file v2.1.115/linux/arch/m68k/mm/memory.c linux/arch/m68k/mm/memory.c --- v2.1.115/linux/arch/m68k/mm/memory.c Thu Aug 6 14:06:28 1998 +++ linux/arch/m68k/mm/memory.c Mon Aug 10 11:02:24 1998 @@ -82,27 +82,25 @@ } -static struct ptable_desc { - struct ptable_desc *prev; - struct ptable_desc *next; - unsigned long page; - unsigned char alloced; -} ptable_list = { &ptable_list, &ptable_list, 0, 0xff }; - -#define PD_NONEFREE(dp) ((dp)->alloced == 0xff) -#define PD_ALLFREE(dp) ((dp)->alloced == 0) -#define PD_TABLEFREE(dp,i) (!((dp)->alloced & (1<<(i)))) -#define PD_MARKUSED(dp,i) ((dp)->alloced |= (1<<(i))) -#define PD_MARKFREE(dp,i) ((dp)->alloced &= ~(1<<(i))) +/* ++andreas: {get,free}_pointer_table rewritten to use unused fields from + struct page instead of separately kmalloced struct. Stolen from + arch/sparc/mm/srmmu.c ... */ + +typedef struct page ptable_desc; +static ptable_desc ptable_list = { &ptable_list, &ptable_list }; + +#define PD_MARKBITS(dp) (*(unsigned char *)&(dp)->offset) +#define PD_PAGE(dp) (PAGE_OFFSET + ((dp)->map_nr << PAGE_SHIFT)) +#define PAGE_PD(page) ((ptable_desc *)&mem_map[MAP_NR(page)]) #define PTABLE_SIZE (PTRS_PER_PMD * sizeof(pmd_t)) pmd_t *get_pointer_table (void) { - pmd_t *pmdp = NULL; - unsigned long flags; - struct ptable_desc *dp = ptable_list.next; - int i; + ptable_desc *dp = ptable_list.next; + unsigned char mask = PD_MARKBITS (dp); + unsigned char tmp; + unsigned int off; /* * For a pointer table for a user process address space, a @@ -110,103 +108,70 @@ * page can hold 8 pointer tables. The page is remapped in * virtual address space to be noncacheable. */ - if (PD_NONEFREE (dp)) { + if (mask == 0) { + unsigned long page; + ptable_desc *new; - if (!(dp = kmalloc (sizeof(struct ptable_desc),GFP_KERNEL))) { + if (!(page = get_free_page (GFP_KERNEL))) return 0; - } - if (!(dp->page = get_free_page (GFP_KERNEL))) { - kfree (dp); - return 0; - } - - flush_tlb_kernel_page((unsigned long) dp->page); - nocache_page (dp->page); + flush_tlb_kernel_page(page); + nocache_page (page); - dp->alloced = 0; - /* put at head of list */ - save_flags(flags); - cli(); - dp->next = ptable_list.next; - dp->prev = ptable_list.next->prev; - ptable_list.next->prev = dp; - ptable_list.next = dp; - restore_flags(flags); + new = PAGE_PD(page); + PD_MARKBITS(new) = 0xfe; + (new->prev = dp->prev)->next = new; + (new->next = dp)->prev = new; + return (pmd_t *)page; } - for (i = 0; i < 8; i++) - if (PD_TABLEFREE (dp, i)) { - PD_MARKUSED (dp, i); - pmdp = (pmd_t *)(dp->page + PTABLE_SIZE*i); - break; - } + for (tmp = 1, off = 0; (mask & tmp) == 0; tmp <<= 1, off += PTABLE_SIZE); + PD_MARKBITS(dp) = mask & ~tmp; + if (!PD_MARKBITS(dp)) { + ptable_desc *last, *next; - if (PD_NONEFREE (dp)) { /* move to end of list */ - save_flags(flags); - cli(); - dp->prev->next = dp->next; - dp->next->prev = dp->prev; - - dp->next = ptable_list.next->prev; - dp->prev = ptable_list.prev; - ptable_list.prev->next = dp; - ptable_list.prev = dp; - restore_flags(flags); - } - - memset (pmdp, 0, PTABLE_SIZE); + next = dp->next; + (next->prev = dp->prev)->next = next; - return pmdp; + last = ptable_list.prev; + (dp->next = last->next)->prev = dp; + (dp->prev = last)->next = dp; + } + return (pmd_t *) (PD_PAGE(dp) + off); } int free_pointer_table (pmd_t *ptable) { - struct ptable_desc *dp; + ptable_desc *dp, *first; unsigned long page = (unsigned long)ptable & PAGE_MASK; - int index = ((unsigned long)ptable - page)/PTABLE_SIZE; - unsigned long flags; - - for (dp = ptable_list.next; dp->page && dp->page != page; dp = dp->next) - ; + unsigned char mask = 1 << (((unsigned long)ptable - page)/PTABLE_SIZE); - if (!dp->page) - panic ("unable to find desc for ptable %p on list!", ptable); - - if (PD_TABLEFREE (dp, index)) + dp = PAGE_PD(page); + if (PD_MARKBITS (dp) & mask) panic ("table already free!"); - PD_MARKFREE (dp, index); + PD_MARKBITS (dp) |= mask; - if (PD_ALLFREE (dp)) { + if (PD_MARKBITS(dp) == 0xff) { /* all tables in page are free, free page */ - save_flags(flags); - cli(); - dp->prev->next = dp->next; - dp->next->prev = dp->prev; - restore_flags(flags); - cache_page (dp->page); - free_page (dp->page); - kfree (dp); + ptable_desc *next = dp->next; + (next->prev = dp->prev)->next = next; + cache_page (page); + free_page (page); return 1; - } else { + } else if ((first = ptable_list.next) != dp) { /* * move this descriptor to the front of the list, since * it has one or more free tables. */ - save_flags(flags); - cli(); - dp->prev->next = dp->next; - dp->next->prev = dp->prev; - - dp->next = ptable_list.next; - dp->prev = ptable_list.next->prev; - ptable_list.next->prev = dp; - ptable_list.next = dp; - restore_flags(flags); - return 0; + ptable_desc *next = dp->next; + (next->prev = dp->prev)->next = next; + + (dp->prev = first->prev)->next = dp; + (dp->next = first)->prev = dp; } + return 0; } /* maximum pages used for kpointer tables */ diff -u --recursive --new-file v2.1.115/linux/drivers/block/Config.in linux/drivers/block/Config.in --- v2.1.115/linux/drivers/block/Config.in Thu Aug 6 14:06:31 1998 +++ linux/drivers/block/Config.in Mon Aug 10 09:29:14 1998 @@ -32,7 +32,6 @@ bool ' RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000 bool ' Generic PCI IDE chipset support' CONFIG_BLK_DEV_IDEPCI if [ "$CONFIG_BLK_DEV_IDEPCI" = "y" ]; then - # Either the DMA code is buggy or the DMA hardware is unreliable. FIXME. bool ' Generic PCI bus-master DMA support' CONFIG_BLK_DEV_IDEDMA if [ "$CONFIG_BLK_DEV_IDEDMA" = "y" ]; then bool ' Use DMA by default when available' CONFIG_IDEDMA_AUTO diff -u --recursive --new-file v2.1.115/linux/drivers/block/genhd.c linux/drivers/block/genhd.c --- v2.1.115/linux/drivers/block/genhd.c Thu Aug 6 14:06:31 1998 +++ linux/drivers/block/genhd.c Sun Aug 16 11:48:40 1998 @@ -414,7 +414,8 @@ * This is necessary for drives for situations where * the translated geometry is unavailable from the BIOS. */ - for (i = 0; i < 4 ; i++) { + int xlate_done = 0; + for (i = 0; i < 4 && !xlate_done; i++) { struct partition *q = &p[i]; if (NR_SECTS(q) && (q->sector & 63) == 1 @@ -423,10 +424,16 @@ if (heads == 32 || heads == 64 || heads == 128 || heads == 255) { (void) ide_xlate_1024(dev, heads, " [PTBL]"); - break; + xlate_done = 1; } } } + if (!xlate_done) { + /* + * Default translation is equivalent of "BIOS LBA": + */ + ide_xlate_1024(dev, -2, " [LBA]"); + } } } #endif /* CONFIG_BLK_DEV_IDE */ @@ -1101,7 +1108,6 @@ extern int soc_probe(void); #endif struct gendisk *p; - int nr=0; #ifdef CONFIG_PARPORT parport_init(); @@ -1123,10 +1129,9 @@ console_map_init(); #endif - for (p = gendisk_head ; p ; p=p->next) { + for (p = gendisk_head ; p ; p=p->next) setup_dev(p); - nr += p->nr_real; - } + #ifdef CONFIG_BLK_DEV_RAM #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start && mount_initrd) initrd_load(); @@ -1138,3 +1143,25 @@ md_setup_drive(); #endif } + +#ifdef CONFIG_PROC_FS +int get_partition_list(char * page) +{ + struct gendisk *p; + char buf[8]; + int n, len; + + len = sprintf(page, "major minor #blocks name\n\n"); + for (p = gendisk_head; p; p = p->next) { + for (n=0; n < (p->nr_real << p->minor_shift); n++) { + if (p->part[n].nr_sects && len < PAGE_SIZE - 80) { + len += sprintf(page+len, + "%4d %4d %10d %s\n", + p->major, n, p->sizes[n], + disk_name(p, n, buf)); + } + } + } + return len; +} +#endif diff -u --recursive --new-file v2.1.115/linux/drivers/block/ide-probe.c linux/drivers/block/ide-probe.c --- v2.1.115/linux/drivers/block/ide-probe.c Thu Aug 6 14:06:31 1998 +++ linux/drivers/block/ide-probe.c Sat Aug 15 16:01:13 1998 @@ -45,8 +45,8 @@ int bswap = 1; struct hd_driveid *id; - id = drive->id = kmalloc (SECTOR_WORDS*4, GFP_KERNEL); - ide_input_data(drive, id, SECTOR_WORDS); /* read 512 bytes of id info */ + id = drive->id = kmalloc (SECTOR_WORDS*4, GFP_ATOMIC); /* called with interrupts disabled! */ + ide_input_data(drive, id, SECTOR_WORDS); /* read 512 bytes of id info */ ide__sti(); /* local CPU only */ ide_fix_driveid(id); diff -u --recursive --new-file v2.1.115/linux/drivers/block/ide.c linux/drivers/block/ide.c --- v2.1.115/linux/drivers/block/ide.c Mon Aug 3 12:45:44 1998 +++ linux/drivers/block/ide.c Sun Aug 16 11:48:40 1998 @@ -1,5 +1,5 @@ /* - * linux/drivers/block/ide.c Version 6.17 March 29, 1998 + * linux/drivers/block/ide.c Version 6.18 August 16, 1998 * * Copyright (C) 1994-1998 Linus Torvalds & authors (see below) */ @@ -89,6 +89,7 @@ * Version 6.15 added SMP awareness to IDE drivers * Version 6.16 fixed various bugs; even more SMP friendly * Version 6.17 fix for newest EZ-Drive problem + * Version 6.18 default unpartitioned-disk translation now "BIOS LBA" * * Some additional driver compile-time options are in ide.h * @@ -2562,7 +2563,7 @@ printk("%s ", msg); - if (xparm == -1 && (drive->bios_cyl * drive->bios_head * drive->bios_sect) < (1024 * 16 * 63)) + if (xparm < 0 && (drive->bios_cyl * drive->bios_head * drive->bios_sect) < (1024 * 16 * 63)) return 0; /* small disk: no translation needed */ if (drive->id) { @@ -2590,15 +2591,14 @@ #if FAKE_FDISK_FOR_EZDRIVE if (xparm == -1) { drive->remap_0_to_1 = 1; - msg = "0->1"; + printk("[remap 0->1] "); } else #endif /* FAKE_FDISK_FOR_EZDRIVE */ if (xparm == 1) { drive->sect0 = 63; drive->bios_cyl = (tracks - 1) / drive->bios_head; - msg = "+63"; + printk("[remap +63] "); } - printk("[remap %s] ", msg); } drive->part[0].nr_sects = current_capacity(drive); printk("[%d/%d/%d]", drive->bios_cyl, drive->bios_head, drive->bios_sect); diff -u --recursive --new-file v2.1.115/linux/drivers/block/loop.c linux/drivers/block/loop.c --- v2.1.115/linux/drivers/block/loop.c Tue Jul 21 00:15:30 1998 +++ linux/drivers/block/loop.c Fri Aug 7 17:56:09 1998 @@ -6,14 +6,13 @@ * Copyright 1993 by Theodore Ts'o. Redistribution of this file is * permitted under the GNU Public License. * - * more DES encryption plus IDEA encryption by Nicholas J. Leon, June 20, 1996 * DES encryption plus some minor changes by Werner Almesberger, 30-MAY-1993 + * more DES encryption plus IDEA encryption by Nicholas J. Leon, June 20, 1996 * * Modularized and updated for 1.1.16 kernel - Mitch Dsouza 28th May 1994 - * * Adapted for 1.3.59 kernel - Andries Brouwer, 1 Feb 1996 * - * Fixed do_loop_request() re-entrancy - Mar 20, 1997 + * Fixed do_loop_request() re-entrancy - Vincent.Renardias@waw.com Mar 20, 1997 * * Handle sparse backing files correctly - Kenn Humborg, Jun 28, 1998 */ @@ -427,7 +426,11 @@ lo->lo_backing_file->f_op = file->f_op; lo->lo_backing_file->private_data = file->private_data; - error = 0; + error = get_write_access(inode); /* cannot fail */ + if (error) { + fput(lo->lo_backing_file); + lo->lo_backing_file = NULL; + } } } if (error) diff -u --recursive --new-file v2.1.115/linux/drivers/block/nbd.c linux/drivers/block/nbd.c --- v2.1.115/linux/drivers/block/nbd.c Mon Aug 3 17:48:26 1998 +++ linux/drivers/block/nbd.c Sun Aug 16 12:09:04 1998 @@ -16,6 +16,7 @@ * once to be processed * 97-4-11 Making protocol independent of endianity etc. * 97-9-13 Cosmetic changes + * 98-5-13 Attempt to make 64-bit-clean on 64-bit machines * * possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall * why not: would need verify_area and friends, would share yet another @@ -24,18 +25,24 @@ #define PARANOIA #include -#define MAJOR_NR NBD_MAJOR -#include #include +#include #include #include #include #include +#include #include #include +#include + +#define MAJOR_NR NBD_MAJOR +#include + +#define LO_MAGIC 0x68797548 static int nbd_blksizes[MAX_NBD] = {1024, 1024,}; static int nbd_sizes[MAX_NBD] = {0x7fffffff, 0x7fffffff,}; @@ -68,8 +75,7 @@ /* * Send or receive packet. */ -static -int nbd_xmit(int send, struct socket *sock, char *buf, int size) +static int nbd_xmit(int send, struct socket *sock, char *buf, int size) { mm_segment_t oldfs; int result; @@ -132,7 +138,7 @@ DEBUG("NBD: sending control, "); request.magic = htonl(NBD_REQUEST_MAGIC); request.type = htonl(req->cmd); - request.from = htonl(req->sector * 512); + request.from = cpu_to_be64( (u64) req->sector * (u64) 512); request.len = htonl(req->current_nr_sectors << 9); memcpy(request.handle, &req, sizeof(req)); @@ -153,8 +159,8 @@ } #define HARDFAIL( s ) { printk( KERN_ERR "NBD: " s "(result %d)\n", result ); lo->harderror = result; return NULL; } -struct request * /* NULL returned = something went wrong, inform userspace */ - nbd_read_stat(struct nbd_device *lo) +struct request *nbd_read_stat(struct nbd_device *lo) + /* NULL returned = something went wrong, inform userspace */ { int result; struct nbd_reply reply; @@ -425,8 +431,8 @@ { int i; - if (sizeof(struct nbd_request) != 24) { - printk(KERN_CRIT "Sizeof nbd_request needs to be 24 in order to work!\n" ); + if (sizeof(struct nbd_request) != 28) { + printk(KERN_CRIT "Sizeof nbd_request needs to be 28 in order to work!\n" ); return -EIO; } diff -u --recursive --new-file v2.1.115/linux/drivers/block/trm290.c linux/drivers/block/trm290.c --- v2.1.115/linux/drivers/block/trm290.c Thu May 7 22:51:48 1998 +++ linux/drivers/block/trm290.c Fri Aug 7 17:56:09 1998 @@ -249,7 +249,7 @@ ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3); hwif->dmaproc = &trm290_dmaproc; hwif->selectproc = &trm290_selectproc; - hwif->no_autodma = 1; /* play it safe for now */ + hwif->autodma = 0; /* play it safe for now */ #if 1 { /* diff -u --recursive --new-file v2.1.115/linux/drivers/char/apm_bios.c linux/drivers/char/apm_bios.c --- v2.1.115/linux/drivers/char/apm_bios.c Sun Jun 7 11:16:29 1998 +++ linux/drivers/char/apm_bios.c Sun Aug 9 10:42:41 1998 @@ -515,6 +515,8 @@ return APM_SUCCESS; } +#if 0 +/* not used anywhere */ static int apm_get_battery_status(u_short which, u_short *bat, u_short *life, u_short *nbat) { @@ -532,6 +534,7 @@ return (error >> 8); return APM_SUCCESS; } +#endif static inline int apm_engage_power_management(u_short device) { diff -u --recursive --new-file v2.1.115/linux/drivers/char/bttv.c linux/drivers/char/bttv.c --- v2.1.115/linux/drivers/char/bttv.c Sun Jul 26 11:57:15 1998 +++ linux/drivers/char/bttv.c Sun Aug 9 12:16:36 1998 @@ -156,6 +156,7 @@ mem=vmalloc(size); if (mem) { + memset(mem, 0, size); /* Clear the ram out, no junk to the user */ adr=(unsigned long) mem; while (size > 0) { @@ -642,7 +643,16 @@ BT848_COLOR_FMT_RGB24, BT848_COLOR_FMT_RGB32, BT848_COLOR_FMT_RGB15, + BT848_COLOR_FMT_YUY2, + BT848_COLOR_FMT_BtYUV, + -1, + -1, + -1, + BT848_COLOR_FMT_RAW, + BT848_COLOR_FMT_YCrCb422, + BT848_COLOR_FMT_YCrCb411, }; +#define PALETTEFMT_MAX 11 static int make_rawrisctab(struct bttv *btv, unsigned int *ro, unsigned int *re, unsigned int *vbuf) @@ -1044,13 +1054,18 @@ */ vbuf=(unsigned int *)(btv->fbuffer+BTTV_MAX_FBUF*mp->frame); - if (!(btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)) - return -EAGAIN; +/* if (!(btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC)) + return -EAGAIN; */ ro=btv->grisc+(((btv->grabcount++)&1) ? 4096 :0); re=ro+2048; btv->gwidth=mp->width; btv->gheight=mp->height; - btv->gfmt=mp->format; + if (mp->format > PALETTEFMT_MAX) + return -EINVAL; + btv->gfmt=palette2fmt[mp->format]; + if(btv->gfmt==-1) + return -EINVAL; + make_vrisctab(btv, ro, re, vbuf, btv->gwidth, btv->gheight, btv->gfmt); /* bt848_set_risc_jmps(btv); */ btor(3, BT848_CAP_CTL); @@ -1561,6 +1576,7 @@ v.rangehigh=0xFFFFFFFF; v.flags=VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM; v.mode = btv->win.norm; + v.signal = (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) ? 0xFFFF : 0; if(copy_to_user(arg,&v,sizeof(v))) return -EFAULT; return 0; @@ -1927,6 +1943,7 @@ bttv_close, bttv_read, bttv_write, + NULL, /* poll */ bttv_ioctl, bttv_mmap, bttv_init_done, @@ -1980,6 +1997,20 @@ return count; } +static unsigned int vbi_poll(struct video_device *dev, struct file *file, + poll_table *wait) +{ + struct bttv *btv=(struct bttv *)(dev-2); + unsigned int mask = 0; + + poll_wait(file, &btv->vbiq, wait); + + if (btv->vbip < VBIBUF_SIZE) + mask |= (POLLIN | POLLRDNORM); + + return mask; +} + static int vbi_open(struct video_device *dev, int flags) { struct bttv *btv=(struct bttv *)(dev-2); @@ -2017,6 +2048,7 @@ vbi_close, vbi_read, bttv_write, + vbi_poll, vbi_ioctl, NULL, /* no mmap yet */ bttv_init_done, @@ -2113,6 +2145,7 @@ radio_close, radio_read, /* just returns -EINVAL */ bttv_write, /* just returns -EINVAL */ + NULL, /* no poll */ radio_ioctl, NULL, /* no mmap */ bttv_init_done, /* just returns 0 */ @@ -2176,7 +2209,7 @@ for (dev = pci_devices; dev != NULL; dev = dev->next) { if (dev->class != PCI_CLASS_NOT_DEFINED_VGA && - (dev->class) >> 8 != PCI_BASE_CLASS_DISPLAY) + ((dev->class) >> 16 != PCI_BASE_CLASS_DISPLAY)) { continue; } @@ -2196,40 +2229,40 @@ badr=vbs[i].badr; break; } - if (!badr) - { - printk(KERN_ERR "bttv: Unknown video memory base address.\n"); - continue; - } - pci_read_config_dword(dev, badr, &vidadr); - if (vidadr & PCI_BASE_ADDRESS_SPACE_IO) - { - printk(KERN_ERR "bttv: Memory seems to be I/O memory.\n"); - printk(KERN_ERR "bttv: Check entry for your card type in bttv.c vidbases struct.\n"); - continue; - } - vidadr &= PCI_BASE_ADDRESS_MEM_MASK; - if (!vidadr) - { - printk(KERN_ERR "bttv: Memory @ 0, must be something wrong!"); - continue; - } - - if (dev->vendor == PCI_VENDOR_ID_DEC && - dev->device == PCI_DEVICE_ID_DEC_TGA) + } + if (!badr) + { + printk(KERN_ERR "bttv: Unknown video memory base address.\n"); + continue; + } + pci_read_config_dword(dev, badr, &vidadr); + if (vidadr & PCI_BASE_ADDRESS_SPACE_IO) + { + printk(KERN_ERR "bttv: Memory seems to be I/O memory.\n"); + printk(KERN_ERR "bttv: Check entry for your card type in bttv.c vidbases struct.\n"); + continue; + } + vidadr &= PCI_BASE_ADDRESS_MEM_MASK; + if (!vidadr) + { + printk(KERN_ERR "bttv: Memory @ 0, must be something wrong!"); + continue; + } + + if (dev->vendor == PCI_VENDOR_ID_DEC && + dev->device == PCI_DEVICE_ID_DEC_TGA) + { + tga_type = (readl((unsigned long)vidadr) >> 12) & 0x0f; + if (tga_type != 0 && tga_type != 1 && tga_type != 3) { - tga_type = (readl((unsigned long)vidadr) >> 12) & 0x0f; - if (tga_type != 0 && tga_type != 1 && tga_type != 3) - { - printk(KERN_ERR "bttv: TGA type (0x%x) unrecognized!\n", tga_type); - found--; - } - vidadr+=dec_offsets[tga_type]; + printk(KERN_ERR "bttv: TGA type (0x%x) unrecognized!\n", tga_type); + found--; } - DEBUG(printk(KERN_DEBUG "bttv: memory @ 0x%08x, ", vidadr)); - DEBUG(printk(KERN_DEBUG "devfn: 0x%04x.\n", dev->devfn)); - found++; + vidadr+=dec_offsets[tga_type]; } + DEBUG(printk(KERN_DEBUG "bttv: memory @ 0x%08x, ", vidadr)); + DEBUG(printk(KERN_DEBUG "devfn: 0x%04x.\n", dev->devfn)); + found++; } if (vidmem) @@ -2548,6 +2581,8 @@ if (!(btv->grisc=(unsigned int *) kmalloc(32768, GFP_KERNEL))) return -1; + memset(btv->vbibuf, 0, VBIBUF_SIZE); /* We don't want to return random + memory to the user */ btv->fbuffer=NULL; bt848_muxsel(btv, 1); diff -u --recursive --new-file v2.1.115/linux/drivers/char/bw-qcam.c linux/drivers/char/bw-qcam.c --- v2.1.115/linux/drivers/char/bw-qcam.c Sun Jun 7 11:16:29 1998 +++ linux/drivers/char/bw-qcam.c Sun Aug 9 12:17:56 1998 @@ -842,6 +842,7 @@ qcam_close, qcam_read, qcam_write, + NULL, qcam_ioctl, NULL, qcam_init_done, diff -u --recursive --new-file v2.1.115/linux/drivers/char/c-qcam.c linux/drivers/char/c-qcam.c --- v2.1.115/linux/drivers/char/c-qcam.c Tue Jul 21 00:15:31 1998 +++ linux/drivers/char/c-qcam.c Sun Aug 9 12:20:30 1998 @@ -646,6 +646,7 @@ qcam_close, qcam_read, qcam_write, + NULL, qcam_ioctl, NULL, qcam_init_done, diff -u --recursive --new-file v2.1.115/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c --- v2.1.115/linux/drivers/char/cyclades.c Thu Aug 6 14:06:31 1998 +++ linux/drivers/char/cyclades.c Mon Aug 10 22:01:15 1998 @@ -1,7 +1,7 @@ #define BLOCKMOVE #define Z_WAKE static char rcsid[] = -"$Revision: 2.2.1.4 $$Date: 1998/08/04 11:02:50 $"; +"$Revision: 2.2.1.5 $$Date: 1998/08/10 18:10:28 $"; /* * linux/drivers/char/cyclades.c @@ -31,6 +31,9 @@ * void cleanup_module(void); * * $Log: cyclades.c,v $ + * Revision 2.2.1.5 1998/08/10 18:10:28 ivan + * Fixed Cyclom-4Yo hardware detection bug. + * * Revision 2.2.1.4 1998/08/04 11:02:50 ivan * /proc/cyclades implementation with great collaboration of * Marc Lewis ; @@ -583,7 +586,7 @@ #define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif -#define IS_CYC_Z(card) ((card).num_chips == 1) +#define IS_CYC_Z(card) ((card).num_chips == -1) #define Z_FPGA_CHECK(card) \ ((cy_readl(&((struct RUNTIME_9060 *) \ @@ -599,7 +602,7 @@ #define STD_COM_FLAGS (0) -#define JIFFIES_DIFF(n, j) ((n) >= (j) ? (n) - (j) : ULONG_MAX - (n) + (j)) +#define JIFFIES_DIFF(n, j) ((n) - (j)) static DECLARE_TASK_QUEUE(tq_cyclades); @@ -3472,7 +3475,7 @@ } else { base_addr = (unsigned char*) (cy_card[card].base_addr); - if (cy_card[card].num_chips != 1){ + if (cy_card[card].num_chips != -1){ return -EINVAL; } @@ -4784,7 +4787,7 @@ cy_card[j].irq = (int) cy_pci_irq; cy_card[j].bus_index = 1; cy_card[j].first_line = cy_next_channel; - cy_card[j].num_chips = 1; + cy_card[j].num_chips = -1; IRQ_cards[cy_pci_irq] = &cy_card[j]; /* print message */ @@ -4867,7 +4870,7 @@ cy_card[j].irq = (int) cy_pci_irq; cy_card[j].bus_index = 1; cy_card[j].first_line = cy_next_channel; - cy_card[j].num_chips = 1; + cy_card[j].num_chips = -1; IRQ_cards[cy_pci_irq] = &cy_card[j]; /* print message */ @@ -4941,7 +4944,7 @@ if (info->count) size = sprintf(buf+len, - "%3d %8lu %10lu %8lu %10lu %8lu %9lu %6ld\n", + "%3d %8lu %10lu %8lu %10lu %8lu %9lu %6d\n", info->line, JIFFIES_DIFF(info->idle_stats.in_use, cur_jifs) / HZ, info->idle_stats.xmit_bytes, @@ -4949,7 +4952,7 @@ info->idle_stats.recv_bytes, JIFFIES_DIFF(info->idle_stats.recv_idle, cur_jifs) / HZ, info->idle_stats.overruns, - info->tty->ldisc.num); + (long) info->tty->ldisc.num); else size = sprintf(buf+len, "%3d %8lu %10lu %8lu %10lu %8lu %9lu %6ld\n", @@ -5108,7 +5111,7 @@ /* initialize per-port data structures for each valid board found */ for (board = 0 ; board < cy_nboard ; board++) { cinfo = &cy_card[board]; - if (cinfo->num_chips == 1){ /* Cyclades-Z */ + if (cinfo->num_chips == -1){ /* Cyclades-Z */ number_z_boards++; mailbox = cy_readl(&((struct RUNTIME_9060 *) cy_card[board].ctl_addr)->mail_box_0); diff -u --recursive --new-file v2.1.115/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c --- v2.1.115/linux/drivers/char/keyboard.c Thu Aug 6 14:06:31 1998 +++ linux/drivers/char/keyboard.c Fri Aug 7 17:56:09 1998 @@ -11,8 +11,8 @@ * Diacriticals redone & other small changes, aeb@cwi.nl, June 1993 * Added decr/incr_console, dynamic keymaps, Unicode support, * dynamic function/string keys, led setting, Sept 1994 - * * `Sticky' modifier keys, 951006. + * * 11-11-96: SAK should now work in the raw mode (Martin Mares) * * Modified to provide 'generic' keyboard support by Hamish Macdonald @@ -590,6 +590,7 @@ if (ch == ' ' || ch == d) return d; + put_queue(d); return ch; } diff -u --recursive --new-file v2.1.115/linux/drivers/char/lp.c linux/drivers/char/lp.c --- v2.1.115/linux/drivers/char/lp.c Sun Jul 26 11:57:15 1998 +++ linux/drivers/char/lp.c Fri Aug 7 18:02:41 1998 @@ -564,7 +564,7 @@ return -ENXIO; if ((LP_F(minor) & LP_EXIST) == 0) return -ENXIO; - if (test_and_set_bit(LP_BUSY_BIT_POS, &LP_F(minor)) & LP_BUSY) + if (test_and_set_bit(LP_BUSY_BIT_POS, &LP_F(minor))) return -EBUSY; MOD_INC_USE_COUNT; diff -u --recursive --new-file v2.1.115/linux/drivers/char/msp3400.c linux/drivers/char/msp3400.c --- v2.1.115/linux/drivers/char/msp3400.c Tue Jul 28 14:21:08 1998 +++ linux/drivers/char/msp3400.c Sun Aug 9 12:18:37 1998 @@ -58,7 +58,7 @@ #endif -int debug = 0; /* insmod parameter */ +static int debug = 0; /* insmod parameter */ struct msp3400c { struct i2c_bus *bus; @@ -542,7 +542,8 @@ LOCK_I2C_BUS(msp->bus); msp3400c_setvolume(msp->bus, 0, 0); msp3400c_setmode(msp, MSP_MODE_AM_DETECT); - val1 = val2 = max1 = max2 = 0; + val1 = val2 = 0; + max1 = max2 = -1; del_timer(&msp->wake_stereo); msp->watch_stereo = 0; diff -u --recursive --new-file v2.1.115/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c --- v2.1.115/linux/drivers/char/pc_keyb.c Thu Aug 6 14:06:31 1998 +++ linux/drivers/char/pc_keyb.c Fri Aug 7 17:56:09 1998 @@ -50,7 +50,7 @@ */ /* - * Some x86 BIOSes do not correctly initializes the keyboard, so the + * Some x86 BIOSes do not correctly initialize the keyboard, so the * "kbd-reset" command line options can be given to force a reset. * [Ranger] */ diff -u --recursive --new-file v2.1.115/linux/drivers/char/pms.c linux/drivers/char/pms.c --- v2.1.115/linux/drivers/char/pms.c Sun Jun 7 11:16:30 1998 +++ linux/drivers/char/pms.c Sun Aug 9 12:18:37 1998 @@ -893,6 +893,7 @@ pms_close, pms_read, pms_write, + NULL, /* FIXME - we can use POLL on this board with the irq */ pms_ioctl, NULL, pms_init_done, diff -u --recursive --new-file v2.1.115/linux/drivers/char/pty.c linux/drivers/char/pty.c --- v2.1.115/linux/drivers/char/pty.c Thu Aug 6 14:06:31 1998 +++ linux/drivers/char/pty.c Sun Aug 16 11:35:33 1998 @@ -7,6 +7,7 @@ * -- C. Scott Ananian , 14-Jan-1998 */ +#include #include /* For EXPORT_SYMBOL */ #include @@ -85,7 +86,15 @@ if (tty->driver.subtype == PTY_TYPE_MASTER) { tty_hangup(tty->link); set_bit(TTY_OTHER_CLOSED, &tty->flags); - devpts_pty_kill(MINOR(tty->device) - tty->driver.minor_start); +#ifdef CONFIG_UNIX98_PTYS + { + unsigned int major = MAJOR(tty->device) - UNIX98_PTY_MASTER_MAJOR; + if ( major < UNIX98_NR_MAJORS ) { + devpts_pty_kill( MINOR(tty->device) + - tty->driver.minor_start + tty->driver.name_base ); + } + } +#endif } } @@ -214,16 +223,20 @@ return ((count < N_TTY_BUF_SIZE/2) ? 0 : count); } -/* - * Return the minor device number of a given pty. This lets us - * open a master pty with the multi-headed ptmx device, then - * find out which one we got after it is open, with an ioctl. +/* + * Return the device number of a Unix98 PTY (only!). This lets us open a + * master pty with the multi-headed ptmx device, then find out which + * one we got after it is open, with an ioctl. */ -static int pty_get_device_minor(struct tty_struct *tty, unsigned int *value) +#ifdef CONFIG_UNIX98_PTYS +static int pty_get_device_number(struct tty_struct *tty, unsigned int *value) { - unsigned int result = MINOR(tty->device); + unsigned int result = MINOR(tty->device) + - tty->driver.minor_start + tty->driver.name_base; return put_user(result, value); } +#endif + /* Set the lock flag on a pty */ static int pty_set_lock(struct tty_struct *tty, int * arg) { @@ -237,22 +250,37 @@ return 0; } -static int pty_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) +static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) { if (!tty) { printk("pty_ioctl called with NULL tty!\n"); return -EIO; } switch(cmd) { - case TIOCGPTN: /* Get PT Number */ - return pty_get_device_minor(tty, (unsigned int *)arg); case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ return pty_set_lock(tty, (int *) arg); } return -ENOIOCTLCMD; } +#ifdef CONFIG_UNIX98_PTYS +static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + if (!tty) { + printk("pty_unix98_ioctl called with NULL tty!\n"); + return -EIO; + } + switch(cmd) { + case TIOCGPTN: /* Get PT Number */ + return pty_get_device_number(tty, (unsigned int *)arg); + } + + return pty_bsd_ioctl(tty,file,cmd,arg); +} +#endif + static void pty_flush_buffer(struct tty_struct *tty) { struct tty_struct *to = tty->link; @@ -369,7 +397,7 @@ * assign it here, instead of up with the rest of the * pty_driver initialization. */ - pty_driver.ioctl = pty_ioctl; + pty_driver.ioctl = pty_bsd_ioctl; /* Unix98 devices */ #ifdef CONFIG_UNIX98_PTYS @@ -380,6 +408,7 @@ ptm_driver[i].proc_entry = 0; ptm_driver[i].major = UNIX98_PTY_MASTER_MAJOR+i; ptm_driver[i].minor_start = 0; + ptm_driver[i].name_base = i*NR_PTYS; ptm_driver[i].num = NR_PTYS; ptm_driver[i].other = &pts_driver[i]; ptm_driver[i].table = ptm_table[i]; @@ -392,6 +421,7 @@ pts_driver[i].proc_entry = 0; pts_driver[i].major = UNIX98_PTY_SLAVE_MAJOR+i; pts_driver[i].minor_start = 0; + pts_driver[i].name_base = i*NR_PTYS; pts_driver[i].num = ptm_driver[i].num; pts_driver[i].other = &ptm_driver[i]; pts_driver[i].table = pts_table[i]; @@ -399,7 +429,7 @@ pts_driver[i].termios_locked = pts_termios_locked[i]; pts_driver[i].driver_state = ptm_state[i]; - ptm_driver[i].ioctl = pty_ioctl; + ptm_driver[i].ioctl = pty_unix98_ioctl; if (tty_register_driver(&ptm_driver[i])) panic("Couldn't register Unix98 ptm driver major %d", diff -u --recursive --new-file v2.1.115/linux/drivers/char/radio-aimslab.c linux/drivers/char/radio-aimslab.c --- v2.1.115/linux/drivers/char/radio-aimslab.c Thu Aug 6 14:06:31 1998 +++ linux/drivers/char/radio-aimslab.c Sun Aug 9 12:18:37 1998 @@ -155,7 +155,11 @@ /* adapted from radio-aztech.c */ - freq = (freq * 100) / 16; /* massage the data a little */ + /* We want to compute x * 100 / 16 without overflow + * So we compute x*6 + (x/100)*25 to give x*6.25 + */ + + freq = freq * 6 + freq/4; /* massage the data a little */ freq += 1070; /* IF = 10.7 MHz */ freq /= 5; /* ref = 25 kHz */ @@ -308,6 +312,7 @@ rt_close, NULL, /* Can't read (no capture ability) */ NULL, /* Can't write */ + NULL, /* No poll */ rt_ioctl, NULL, NULL diff -u --recursive --new-file v2.1.115/linux/drivers/char/radio-aztech.c linux/drivers/char/radio-aztech.c --- v2.1.115/linux/drivers/char/radio-aztech.c Thu Aug 6 14:06:31 1998 +++ linux/drivers/char/radio-aztech.c Sun Aug 9 12:18:37 1998 @@ -113,7 +113,8 @@ { int i; - frequency = (frequency * 100) / 16; /* massage data a bit */ + /* 6.25 * */ + frequency = frequency*6 + frequency/4; /* massage data a bit */ frequency += 1070; /* tuning needs 24 data bits */ frequency /= 5; @@ -269,6 +270,7 @@ az_close, NULL, /* Can't read (no capture ability) */ NULL, /* Can't write */ + NULL, /* No poll */ az_ioctl, NULL, NULL diff -u --recursive --new-file v2.1.115/linux/drivers/char/radio-rtrack2.c linux/drivers/char/radio-rtrack2.c --- v2.1.115/linux/drivers/char/radio-rtrack2.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/radio-rtrack2.c Sun Aug 9 12:18:37 1998 @@ -0,0 +1,272 @@ +/* RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff + * + * Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood + * Coverted to new API by Alan Cox + * Various bugfixes and enhancements by Russell Kroll + * + * TODO: Allow for more than one of these foolish entities :-) + * + */ + +#include /* Modules */ +#include /* Initdata */ +#include /* check_region, request_region */ +#include /* udelay */ +#include /* outb, outb_p */ +#include /* copy to/from user */ +#include /* kernel radio structs */ +#include /* CONFIG_RADIO_RTRACK2_PORT */ + +#ifndef CONFIG_RADIO_RTRACK2_PORT +#define CONFIG_RADIO_RTRACK2_PORT -1 +#endif + +static int io = CONFIG_RADIO_RTRACK2_PORT; +static int users = 0; + +struct rt_device +{ + int port; + unsigned long curfreq; + int muted; +}; + + +/* local things */ + +static void rt_mute(struct rt_device *dev) +{ + if(dev->muted) + return; + outb(1, io); + dev->muted = 1; +} + +static void rt_unmute(struct rt_device *dev) +{ + if(dev->muted == 0) + return; + outb(0, io); + dev->muted = 0; +} + +static void zero(void) +{ + outb_p(1, io); + outb_p(3, io); + outb_p(1, io); +} + +static void one(void) +{ + outb_p(5, io); + outb_p(7, io); + outb_p(5, io); +} + +static int rt_setfreq(struct rt_device *dev, unsigned long freq) +{ + int i; + + freq = freq / 200 + 856; + + outb_p(0xc8, io); + outb_p(0xc9, io); + outb_p(0xc9, io); + + for (i = 0; i < 10; i++) + zero (); + + for (i = 14; i >= 0; i--) + if (freq & (1 << i)) + one (); + else + zero (); + + outb_p(0xc8, io); + if (!dev->muted) + outb_p(0, io); + return 0; +} + +int rt_getsigstr(struct rt_device *dev) +{ + if (inb(io) & 2) /* bit set = no signal present */ + return 0; + return 1; /* signal present */ +} + +static int rt_ioctl(struct video_device *dev, unsigned int cmd, void *arg) +{ + struct rt_device *rt=dev->priv; + + switch(cmd) + { + case VIDIOCGCAP: + { + struct video_capability v; + v.type=VID_TYPE_TUNER; + v.channels=1; + v.audios=1; + /* No we don't do pictures */ + v.maxwidth=0; + v.maxheight=0; + v.minwidth=0; + v.minheight=0; + if(copy_to_user(arg,&v,sizeof(v))) + return -EFAULT; + return 0; + } + case VIDIOCGTUNER: + { + struct video_tuner v; + if(copy_from_user(&v, arg,sizeof(v))!=0) + return -EFAULT; + if(v.tuner) /* Only 1 tuner */ + return -EINVAL; + v.rangelow=88*16000; + v.rangehigh=108*16000; + v.flags=VIDEO_TUNER_LOW; + v.mode=VIDEO_MODE_AUTO; + v.signal=0xFFFF*rt_getsigstr(rt); + if(copy_to_user(arg,&v, sizeof(v))) + return -EFAULT; + return 0; + } + case VIDIOCSTUNER: + { + struct video_tuner v; + if(copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + if(v.tuner!=0) + return -EINVAL; + /* Only 1 tuner so no setting needed ! */ + return 0; + } + case VIDIOCGFREQ: + if(copy_to_user(arg, &rt->curfreq, sizeof(rt->curfreq))) + return -EFAULT; + return 0; + case VIDIOCSFREQ: + if(copy_from_user(&rt->curfreq, arg,sizeof(rt->curfreq))) + return -EFAULT; + rt_setfreq(rt, rt->curfreq); + return 0; + case VIDIOCGAUDIO: + { + struct video_audio v; + memset(&v,0, sizeof(v)); + v.flags|=VIDEO_AUDIO_MUTABLE; + v.volume=1; + strcpy(v.name, "Radio"); + if(copy_to_user(arg,&v, sizeof(v))) + return -EFAULT; + return 0; + } + case VIDIOCSAUDIO: + { + struct video_audio v; + if(copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + if(v.audio) + return -EINVAL; + + if(v.flags&VIDEO_AUDIO_MUTE) + rt_mute(rt); + else + rt_unmute(rt); + + return 0; + } + default: + return -ENOIOCTLCMD; + } +} + +static int rt_open(struct video_device *dev, int flags) +{ + if(users) + return -EBUSY; + users++; + MOD_INC_USE_COUNT; + return 0; +} + +static void rt_close(struct video_device *dev) +{ + users--; + MOD_DEC_USE_COUNT; +} + +static struct rt_device rtrack2_unit; + +static struct video_device rtrack2_radio= +{ + "RadioTrack II radio", + VID_TYPE_TUNER, + VID_HARDWARE_RTRACK2, + rt_open, + rt_close, + NULL, /* Can't read (no capture ability) */ + NULL, /* Can't write */ + NULL, /* Can't poll */ + rt_ioctl, + NULL, + NULL +}; + +__initfunc(int rtrack2_init(struct video_init *v)) +{ + if (check_region(io, 4)) + { + printk(KERN_ERR "rtrack2: port 0x%x already in use\n", io); + return -EBUSY; + } + + rtrack2_radio.priv=&rtrack2_unit; + + if(video_register_device(&rtrack2_radio, VFL_TYPE_RADIO)==-1) + return -EINVAL; + + request_region(io, 4, "rtrack2"); + printk(KERN_INFO "AIMSlab Radiotrack II card driver.\n"); + + /* mute card - prevents noisy bootups */ + outb(1, io); + rtrack2_unit.muted = 1; + + return 0; +} + +#ifdef MODULE + +MODULE_AUTHOR("Ben Pfaff"); +MODULE_DESCRIPTION("A driver for the RadioTrack II radio card."); +MODULE_PARM(io, "i"); +MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)"); + +EXPORT_NO_SYMBOLS; + +int init_module(void) +{ + if(io==-1) + { + printk(KERN_ERR "You must set an I/O address with io=0x20c or io=0x30c\n"); + return -EINVAL; + } + return rtrack2_init(NULL); +} + +void cleanup_module(void) +{ + video_unregister_device(&rtrack2_radio); + release_region(io,4); +} + +#endif + +/* + Local variables: + compile-command: "gcc -c -DMODVERSIONS -D__KERNEL__ -DMODULE -O6 -Wall -Wstrict-prototypes -I /home/blp/tmp/linux-2.1.111-rtrack/include radio-rtrack2.c" + End: +*/ diff -u --recursive --new-file v2.1.115/linux/drivers/char/radio-sf16fmi.c linux/drivers/char/radio-sf16fmi.c --- v2.1.115/linux/drivers/char/radio-sf16fmi.c Tue Jul 21 00:15:31 1998 +++ linux/drivers/char/radio-sf16fmi.c Sun Aug 9 12:18:37 1998 @@ -29,6 +29,7 @@ int port; int curvol; unsigned long curfreq; + int flags; }; #ifndef CONFIG_RADIO_SF16FMI_PORT @@ -39,7 +40,8 @@ static int users = 0; /* local things */ -#define RSF16_ENCODE(x) ((x*(1000/4)+10700)/50) +/* freq in 1/16kHz to internal number */ +#define RSF16_ENCODE(x) ((x/16+10700)/50) static void outbits(int bits, int data, int port) { @@ -69,8 +71,6 @@ outb(0x08, port); } -/* FREQ is in 1/16ths of a MHz so this is probably wrong atm */ - static int fmi_setfreq(struct fmi_device *dev, unsigned long freq) { int myport = dev->port; @@ -124,9 +124,14 @@ return -EFAULT; if(v.tuner) /* Only 1 tuner */ return -EINVAL; - v.rangelow=(int)(87.5*16); - v.rangehigh=(int)(108.0*16); - v.flags=0; + if (fmi->flags & VIDEO_TUNER_LOW) { + v.rangelow = 87500 * 16; + v.rangehigh = 108000 * 16; + } else { + v.rangelow=(int)(175*8 /* 87.5 *16 */); + v.rangehigh=(int)(108*16); + } + v.flags=fmi->flags; v.mode=VIDEO_MODE_AUTO; v.signal=0xFFFF*fmi_getsigstr(fmi); if(copy_to_user(arg,&v, sizeof(v))) @@ -140,18 +145,30 @@ return -EFAULT; if(v.tuner!=0) return -EINVAL; + fmi->flags = v.flags & VIDEO_TUNER_LOW; /* Only 1 tuner so no setting needed ! */ return 0; } case VIDIOCGFREQ: - if(copy_to_user(arg, &fmi->curfreq, sizeof(fmi->curfreq))) + { + unsigned long tmp = fmi->curfreq; + if (!(fmi->flags & VIDEO_TUNER_LOW)) + tmp /= 1000; + if(copy_to_user(arg, &tmp, sizeof(tmp))) return -EFAULT; return 0; + } case VIDIOCSFREQ: - if(copy_from_user(&fmi->curfreq, arg,sizeof(fmi->curfreq))) + { + unsigned long tmp; + if(copy_from_user(&tmp, arg, sizeof(tmp))) return -EFAULT; + if (!(fmi->flags & VIDEO_TUNER_LOW)) + tmp *= 1000; + fmi->curfreq = tmp; fmi_setfreq(fmi, fmi->curfreq); return 0; + } case VIDIOCGAUDIO: { struct video_audio v; @@ -211,6 +228,7 @@ fmi_close, NULL, /* Can't read (no capture ability) */ NULL, /* Can't write */ + NULL, /* Can't poll */ fmi_ioctl, NULL, NULL @@ -225,6 +243,7 @@ } fmi_unit.port=io; + fmi_unit.flags = VIDEO_TUNER_LOW; fmi_radio.priv=&fmi_unit; if(video_register_device(&fmi_radio, VFL_TYPE_RADIO)==-1) diff -u --recursive --new-file v2.1.115/linux/drivers/char/radio-zoltrix.c linux/drivers/char/radio-zoltrix.c --- v2.1.115/linux/drivers/char/radio-zoltrix.c Tue Jul 21 00:15:31 1998 +++ linux/drivers/char/radio-zoltrix.c Sun Aug 9 12:18:37 1998 @@ -2,14 +2,14 @@ * (c) 1998 C. van Schaik * * BUGS - * The signal strength query is unsurprisingly inaccurate. And it seems - * to indicate that (on my card, at least) the frequency setting isn't - * too great. It seems to work in a similar way to a car stereo which - * flickers when it is near or on a station... + * Due to the inconsistancy in reading from the signal flags + * it is difficult to get an accurate tuned signal. * * There seems to be a problem with the volume setting that I must still - * figure out. This is a minor problem... It still works but you may - * have to set the card lounder to get the same volume. + * figure out. + * It seems that the card has is not linear to 0 volume. It cuts off + * at a low frequency, and it is not possible (at least I have not found) + * to get fine volume control over the low volume range. * * Some code derived from code by Frans Brinkman */ @@ -62,31 +62,31 @@ inb(io + 3); /* Zoltrix needs to be read to confirm */ } -static int zol_setvol(struct zol_device *dev, int vol) +static void zol_on(int vol) { - int l; + int l; + outb(vol, io); + sleep_delay(10000); + l = inb(io + 2); +} +static int zol_setvol(struct zol_device *dev, int vol) +{ if (vol == dev->curvol) { /* requested volume = current */ if (dev->muted) { /* user is unmuting the card */ dev->muted = 0; - outb(vol, io); - sleep_delay(20000); - l = inb(io + 2); + zol_on(vol); } return 0; } if (vol == 0) { /* volume = 0 means mute the card */ - outb(0, io); - outb(0, io); - l = inb(io + 3); + zol_mute(dev); return 0; } dev->muted = 0; dev->curvol = vol; - outb(vol, io); - sleep_delay(20000); - l = inb(io + 2); + zol_on(vol); return 0; } @@ -95,7 +95,7 @@ { /* tunes the radio to the desired frequency */ unsigned long long bitmask, f, m; - int i, l; + int i; m = (freq * 25 / 4 - 8800) * 2; f = (unsigned long long) m + 0x4d1c; @@ -103,10 +103,8 @@ bitmask = 0xc480402c10080000ull; i = 45; - outb(0x00, io); - outb(0x00, io); - sleep_delay(10000); - inb(io + 3); + zol_mute(dev); + outb(0x40, io); outb(0xc0, io); @@ -133,29 +131,26 @@ outb(0x80, io); outb(0xc0, io); outb(0x40, io); - outb(0x00, io); - sleep_delay(10000); - l = inb(io + 2); - sleep_delay(10000); - l = inb(io + 1); - outb(dev->curvol, io); - sleep_delay(10000); - l = inb(io + 2); + zol_on(dev->curvol); return 0; } -/* Get signal strenght */ +/* Get signal strength */ + int zol_getsigstr(struct zol_device *dev) { int a, b; - outb(0x00, io); - sleep_delay(10000); - a = inb(io + 2); + + outb(0x00, io); /* This stuff I found to do nothing */ + outb(dev->curvol, io); sleep_delay(20000); - b = inb(io + 1); - outb(0x00, io); - if (((a | b) & 255) != 0x0ff) + a = inb(io); + sleep_delay(1000); + b = inb(io); + + if ((a == b) && (a == 0xdf)) /* I found this out by playing */ + /* with a binary scanner on the card io */ return (1); else return (0); @@ -225,7 +220,7 @@ struct video_audio v; memset(&v, 0, sizeof(v)); v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME; - v.volume = rt->curvol * 6554; + v.volume = rt->curvol * 4095; strcpy(v.name, "Radio"); if (copy_to_user(arg, &v, sizeof(v))) return -EFAULT; @@ -242,7 +237,7 @@ if (v.flags & VIDEO_AUDIO_MUTE) zol_mute(rt); else - zol_setvol(rt, v.volume / 6554); + zol_setvol(rt, v.volume / 4096); return 0; } @@ -277,6 +272,7 @@ zol_close, NULL, /* Can't read (no capture ability) */ NULL, /* Can't write */ + NULL, zol_ioctl, NULL, NULL diff -u --recursive --new-file v2.1.115/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v2.1.115/linux/drivers/char/tty_io.c Thu Aug 6 14:06:31 1998 +++ linux/drivers/char/tty_io.c Sun Aug 16 11:35:33 1998 @@ -1238,7 +1238,7 @@ #ifdef CONFIG_UNIX98_PTYS if (device == PTMX_DEV) { /* find a free pty. */ - int major, minor, line; + int major, minor; struct tty_driver *driver; /* find a device that is not in use. */ @@ -1255,9 +1255,8 @@ return -EIO; /* no free ptys */ ptmx_found: set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ - line = minor - driver->minor_start; - devpts_pty_new(line + major*NR_PTYS, MKDEV(driver->other->major, - line+driver->other->minor_start)); + minor -= driver->minor_start; + devpts_pty_new(driver->other->name_base + minor, MKDEV(driver->other->major, minor + driver->other->minor_start)); noctty = 1; goto init_dev_done; } diff -u --recursive --new-file v2.1.115/linux/drivers/char/videodev.c linux/drivers/char/videodev.c --- v2.1.115/linux/drivers/char/videodev.c Tue Jul 21 00:15:31 1998 +++ linux/drivers/char/videodev.c Sun Aug 9 12:18:37 1998 @@ -108,7 +108,6 @@ } - /* * Write for now does nothing. No reason it shouldnt do overlay setting * for some boards I guess.. @@ -124,6 +123,21 @@ return 0; } + +/* + * Poll to see if we're readable, can probably be used for timing on incoming + * frames, etc.. + */ + +static unsigned int video_poll(struct file *file, poll_table * wait) +{ + struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)]; + if(vfl->poll) + return vfl->poll(vfl, file, wait); + else + return 0; +} + /* * Open a video device. */ @@ -297,7 +311,7 @@ video_read, video_write, NULL, /* readdir */ - NULL, /* poll */ + video_poll, /* poll */ video_ioctl, video_mmap, video_open, diff -u --recursive --new-file v2.1.115/linux/drivers/net/3c505.h linux/drivers/net/3c505.h --- v2.1.115/linux/drivers/net/3c505.h Wed Jun 24 22:54:06 1998 +++ linux/drivers/net/3c505.h Thu Aug 13 10:03:00 1998 @@ -65,7 +65,7 @@ #define DMA_BRST 0x01 /* DMA burst */ /* - * maximum amount of data data allowed in a PCB + * maximum amount of data allowed in a PCB */ #define MAX_PCB_DATA 62 diff -u --recursive --new-file v2.1.115/linux/drivers/net/3c509.c linux/drivers/net/3c509.c --- v2.1.115/linux/drivers/net/3c509.c Tue Jul 28 14:21:08 1998 +++ linux/drivers/net/3c509.c Sun Aug 9 10:42:41 1998 @@ -178,6 +178,9 @@ } #ifdef CONFIG_MCA +#warning "The MCA code in drivers/net/3c509.c does not compile" +#warning "See http://glycerine.itsmm.uni.edu/mca/ for patches." +#if 0 if (MCA_bus) { mca_adaptor_select_mode(1); for (i = 0; i < 8; i++) @@ -195,6 +198,7 @@ } #endif +#endif /* Reset the ISA PnP mechanism on 3c509b. */ outb(0x02, 0x279); /* Select PnP config control register. */ @@ -208,7 +212,7 @@ if (inb(id_port) & 0x01) break; } - if (id_port >= 0x200) { /* GCC optimizes this test out. */ + if (id_port >= 0x200) { /* Rare -- do we really need a warning? */ printk(" WARNING: No I/O port available for 3c509 activation.\n"); return -ENODEV; diff -u --recursive --new-file v2.1.115/linux/drivers/net/de4x5.c linux/drivers/net/de4x5.c --- v2.1.115/linux/drivers/net/de4x5.c Thu Jul 16 18:09:25 1998 +++ linux/drivers/net/de4x5.c Fri Aug 14 22:36:07 1998 @@ -2197,7 +2197,7 @@ } } - if (loading_module) lastPCI = NO_MORE_PCI; + lastPCI = NO_MORE_PCI; return; } @@ -3898,7 +3898,7 @@ static int EISA_signature(char *name, s32 eisa_id) { - c_char *signatures[] = DE4X5_SIGNATURE; + static c_char *signatures[] = DE4X5_SIGNATURE; char ManCode[DE4X5_STRLEN]; union { s32 ID; @@ -3933,7 +3933,7 @@ static int PCI_signature(char *name, struct bus_type *lp) { - c_char *de4x5_signatures[] = DE4X5_SIGNATURE; + static c_char *de4x5_signatures[] = DE4X5_SIGNATURE; int i, status = 0, siglen = sizeof(de4x5_signatures)/sizeof(c_char *); if (lp->chipset == DC21040) { diff -u --recursive --new-file v2.1.115/linux/drivers/net/plip.c linux/drivers/net/plip.c --- v2.1.115/linux/drivers/net/plip.c Tue Jul 28 14:21:08 1998 +++ linux/drivers/net/plip.c Sun Aug 9 12:27:52 1998 @@ -382,7 +382,7 @@ return TIMEOUT; } c0 = inb(PAR_STATUS(dev)); - printk("%s: transmit timeout(%d,%02x)\n", + printk(KERN_WARNING "%s: transmit timeout(%d,%02x)\n", dev->name, snd->state, c0); } nl->enet_stats.tx_errors++; @@ -400,7 +400,7 @@ return TIMEOUT; } c0 = inb(PAR_STATUS(dev)); - printk("%s: receive timeout(%d,%02x)\n", + printk(KERN_WARNING "%s: receive timeout(%d,%02x)\n", dev->name, rcv->state, c0); } nl->enet_stats.rx_dropped++; @@ -501,7 +501,7 @@ dev->interrupt = 0; outb(0x01, PAR_DATA(dev)); /* send ACK */ if (net_debug > 2) - printk("%s: receive start\n", dev->name); + printk(KERN_DEBUG "%s: receive start\n", dev->name); rcv->state = PLIP_PK_LENGTH_LSB; rcv->nibble = PLIP_NB_BEGIN; @@ -531,13 +531,13 @@ return TIMEOUT; if (rcv->length.h > dev->mtu + dev->hard_header_len || rcv->length.h < 8) { - printk("%s: bogus packet size %d.\n", dev->name, rcv->length.h); + printk(KERN_WARNING "%s: bogus packet size %d.\n", dev->name, rcv->length.h); return ERROR; } /* Malloc up new buffer. */ rcv->skb = dev_alloc_skb(rcv->length.h); if (rcv->skb == NULL) { - printk("%s: Memory squeeze.\n", dev->name); + printk(KERN_WARNING "%s: Memory squeeze.\n", dev->name); return ERROR; } skb_put(rcv->skb,rcv->length.h); @@ -565,7 +565,7 @@ if (rcv->data != rcv->checksum) { nl->enet_stats.rx_crc_errors++; if (net_debug) - printk("%s: checksum error\n", dev->name); + printk(KERN_DEBUG "%s: checksum error\n", dev->name); return ERROR; } rcv->state = PLIP_PK_DONE; @@ -578,7 +578,7 @@ nl->enet_stats.rx_packets++; rcv->skb = NULL; if (net_debug > 2) - printk("%s: receive end\n", dev->name); + printk(KERN_DEBUG "%s: receive end\n", dev->name); /* Close the connection. */ outb (0x00, PAR_DATA(dev)); @@ -662,7 +662,7 @@ unsigned int cx; if (snd->skb == NULL || (lbuf = snd->skb->data) == NULL) { - printk("%s: send skb lost\n", dev->name); + printk(KERN_ERR "%s: send skb lost\n", dev->name); snd->state = PLIP_PK_DONE; snd->skb = NULL; return ERROR; @@ -699,7 +699,7 @@ } outb(PAR_INTR_OFF, PAR_CONTROL(dev)); if (net_debug > 2) - printk("%s: send start\n", dev->name); + printk(KERN_DEBUG "%s: send start\n", dev->name); snd->state = PLIP_PK_LENGTH_LSB; snd->nibble = PLIP_NB_BEGIN; nl->timeout_count = 0; @@ -752,7 +752,7 @@ outb (0x00, data_addr); snd->skb = NULL; if (net_debug > 2) - printk("%s: send end\n", dev->name); + printk(KERN_DEBUG "%s: send end\n", dev->name); nl->connection = PLIP_CN_CLOSING; nl->is_deferred = 1; queue_task(&nl->deferred, &tq_timer); @@ -791,7 +791,7 @@ status = inb(PAR_STATUS(dev)); if ((status & 0xf8) == 0x80) { if (net_debug > 2) - printk("%s: reset interface.\n", dev->name); + printk(KERN_DEBUG "%s: reset interface.\n", dev->name); nl->connection = PLIP_CN_NONE; nl->should_relinquish = 0; dev->tbusy = 0; @@ -817,7 +817,7 @@ unsigned char c0; if (dev == NULL) { - printk("plip_interrupt: irq %d for unknown device.\n", irq); + printk(KERN_ERR "plip_interrupt: irq %d for unknown device.\n", irq); return; } @@ -830,12 +830,12 @@ c0 = inb(PAR_STATUS(dev)); if ((c0 & 0xf8) != 0xc0) { if (net_debug > 1) - printk("%s: spurious interrupt\n", dev->name); + printk(KERN_DEBUG "%s: spurious interrupt\n", dev->name); return; } dev->interrupt = 1; if (net_debug > 3) - printk("%s: interrupt.\n", dev->name); + printk(KERN_DEBUG "%s: interrupt.\n", dev->name); spin_lock_irq(&nl->lock); switch (nl->connection) { @@ -861,7 +861,7 @@ case PLIP_CN_ERROR: spin_unlock_irq(&nl->lock); - printk("%s: receive interrupt in error state\n", dev->name); + printk(KERN_WARNING "%s: receive interrupt in error state\n", dev->name); break; } } @@ -899,18 +899,18 @@ } if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - printk("%s: Transmitter access conflict.\n", dev->name); + printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name); return 1; } if (skb->len > dev->mtu + dev->hard_header_len) { - printk("%s: packet too big, %d.\n", dev->name, (int)skb->len); + printk(KERN_WARNING "%s: packet too big, %d.\n", dev->name, (int)skb->len); dev->tbusy = 0; return 0; } if (net_debug > 2) - printk("%s: send request\n", dev->name); + printk(KERN_DEBUG "%s: send request\n", dev->name); spin_lock_irq(&nl->lock); dev->trans_start = jiffies; @@ -1083,8 +1083,7 @@ return r; } -static int -plip_config(struct device *dev, struct ifmap *map) +static int plip_config(struct device *dev, struct ifmap *map) { struct net_local *nl = (struct net_local *) dev->priv; struct pardevice *pardev = nl->pardev; @@ -1092,8 +1091,8 @@ if (dev->flags & IFF_UP) return -EBUSY; - printk(KERN_WARNING "plip: Warning, changing irq with ifconfig will be obsoleted.\n"); - printk("plip: Next time, please set with /proc/parport/*/irq instead.\n"); + printk(KERN_INFO "plip: Warning, changing irq with ifconfig will be obsoleted.\n"); + printk(KERN_INFO "plip: Next time, please set with /proc/parport/*/irq instead.\n"); if (map->irq != (unsigned char)-1) { pardev->port->irq = dev->irq = map->irq; diff -u --recursive --new-file v2.1.115/linux/drivers/net/shaper.c linux/drivers/net/shaper.c --- v2.1.115/linux/drivers/net/shaper.c Tue Jun 9 11:57:30 1998 +++ linux/drivers/net/shaper.c Sun Aug 9 12:27:52 1998 @@ -128,6 +128,7 @@ static void shaper_setspeed(struct shaper *shaper, int bitspersec) { + shaper->bitspersec=bitspersec; shaper->bytespertick=(bitspersec/HZ)/8; if(!shaper->bytespertick) shaper->bytespertick++; @@ -549,17 +550,27 @@ { struct shaperconf *ss= (struct shaperconf *)&ifr->ifr_data; struct shaper *sh=dev->priv; - struct device *them=dev_get(ss->ss_name); switch(ss->ss_cmd) { case SHAPER_SET_DEV: + { + struct device *them=dev_get(ss->ss_name); if(them==NULL) return -ENODEV; if(sh->dev) return -EBUSY; return shaper_attach(dev,dev->priv, them); + } + case SHAPER_GET_DEV: + if(sh->dev==NULL) + return -ENODEV; + memcpy(ss->ss_name, sh->dev->name, sizeof(ss->ss_name)); + return 0; case SHAPER_SET_SPEED: shaper_setspeed(sh,ss->ss_speed); + return 0; + case SHAPER_GET_SPEED: + ss->ss_speed=sh->bitspersec; return 0; default: return -EINVAL; diff -u --recursive --new-file v2.1.115/linux/drivers/net/tlan.c linux/drivers/net/tlan.c --- v2.1.115/linux/drivers/net/tlan.c Sun Jul 26 11:57:16 1998 +++ linux/drivers/net/tlan.c Sun Aug 9 10:42:41 1998 @@ -48,15 +48,16 @@ static struct device *TLanDevices = NULL; static int TLanDevicesInstalled = 0; +static int aui = 0; +static int sa_int = 0; +static int duplex = 0; +static int speed = 0; + #endif static int debug = 0; -static int aui = 0; -static int sa_int = 0; static int bbuf = 0; -static int duplex = 0; -static int speed = 0; static u8 *TLanPadBuffer; static char TLanSignature[] = "TLAN"; static int TLanVersionMajor = 1; diff -u --recursive --new-file v2.1.115/linux/drivers/net/tlan.h linux/drivers/net/tlan.h --- v2.1.115/linux/drivers/net/tlan.h Tue Jul 21 00:15:31 1998 +++ linux/drivers/net/tlan.h Sun Aug 9 10:42:41 1998 @@ -496,6 +496,24 @@ #define TLan_GetBit( bit, port ) ((int) (inb_p(port) & bit)) #define TLan_SetBit( bit, port ) outb_p(inb_p(port) | bit, port) +#ifdef I_LIKE_A_FAST_HASH_FUNCTION +/* given 6 bytes, view them as 8 6-bit numbers and return the XOR of those */ +/* the code below is about seven times as fast as the original code */ +inline u32 TLan_HashFunc( u8 *a ) +{ + u8 hash; + + hash = (a[0]^a[3]); /* & 077 */ + hash ^= ((a[0]^a[3])>>6); /* & 003 */ + hash ^= ((a[1]^a[4])<<2); /* & 074 */ + hash ^= ((a[1]^a[4])>>4); /* & 017 */ + hash ^= ((a[2]^a[5])<<4); /* & 060 */ + hash ^= ((a[2]^a[5])>>2); /* & 077 */ + + return (hash & 077); +} + +#else /* original code */ inline u32 xor( u32 a, u32 b ) { @@ -519,7 +537,5 @@ } - - - +#endif /* I_LIKE_A_FAST_HASH_FUNCTION */ #endif diff -u --recursive --new-file v2.1.115/linux/drivers/scsi/BusLogic.c linux/drivers/scsi/BusLogic.c --- v2.1.115/linux/drivers/scsi/BusLogic.c Sat May 2 14:19:53 1998 +++ linux/drivers/scsi/BusLogic.c Mon Aug 17 01:01:01 1998 @@ -26,13 +26,14 @@ */ -#define BusLogic_DriverVersion "2.1.13" -#define BusLogic_DriverDate "17 April 1998" +#define BusLogic_DriverVersion "2.1.15" +#define BusLogic_DriverDate "17 August 1998" #include #include #include +#include #include #include #include @@ -1178,7 +1179,8 @@ BusLogic_ProbeInfoCount - FlashPointCount; memcpy(SavedProbeInfo, BusLogic_ProbeInfoList, - sizeof(BusLogic_ProbeInfoList)); + BusLogic_ProbeInfoCount + * sizeof(BusLogic_ProbeInfo_T)); memcpy(&BusLogic_ProbeInfoList[0], &SavedProbeInfo[FlashPointCount], MultiMasterCount * sizeof(BusLogic_ProbeInfo_T)); @@ -3136,25 +3138,25 @@ HostAdapter->TargetStatistics[CCB->TargetID] .CommandsCompleted++; if (BusLogic_GlobalOptions.TraceErrors) - { - int i; - BusLogic_Notice("CCB #%ld Target %d: Result %X Host " - "Adapter Status %02X " - "Target Status %02X\n", - HostAdapter, CCB->SerialNumber, - CCB->TargetID, Command->result, - CCB->HostAdapterStatus, - CCB->TargetDeviceStatus); - BusLogic_Notice("CDB ", HostAdapter); - for (i = 0; i < CCB->CDB_Length; i++) - BusLogic_Notice(" %02X", HostAdapter, CCB->CDB[i]); - BusLogic_Notice("\n", HostAdapter); - BusLogic_Notice("Sense ", HostAdapter); - for (i = 0; i < CCB->SenseDataLength; i++) - BusLogic_Notice(" %02X", HostAdapter, - Command->sense_buffer[i]); - BusLogic_Notice("\n", HostAdapter); - } + { + int i; + BusLogic_Notice("CCB #%ld Target %d: Result %X Host " + "Adapter Status %02X " + "Target Status %02X\n", + HostAdapter, CCB->SerialNumber, + CCB->TargetID, Command->result, + CCB->HostAdapterStatus, + CCB->TargetDeviceStatus); + BusLogic_Notice("CDB ", HostAdapter); + for (i = 0; i < CCB->CDB_Length; i++) + BusLogic_Notice(" %02X", HostAdapter, CCB->CDB[i]); + BusLogic_Notice("\n", HostAdapter); + BusLogic_Notice("Sense ", HostAdapter); + for (i = 0; i < CCB->SenseDataLength; i++) + BusLogic_Notice(" %02X", HostAdapter, + Command->sense_buffer[i]); + BusLogic_Notice("\n", HostAdapter); + } } break; } @@ -4206,7 +4208,6 @@ BusLogic_TargetStatistics_T *TargetStatistics; int TargetID, Length; char *Buffer; - if (WriteFlag) return 0; for (HostAdapter = BusLogic_FirstRegisteredHostAdapter; HostAdapter != NULL; HostAdapter = HostAdapter->Next) @@ -4218,6 +4219,14 @@ return 0; } TargetStatistics = HostAdapter->TargetStatistics; + if (WriteFlag) + { + HostAdapter->ExternalHostAdapterResets = 0; + HostAdapter->HostAdapterInternalErrors = 0; + memset(TargetStatistics, 0, + BusLogic_MaxTargetDevices * sizeof(BusLogic_TargetStatistics_T)); + return 0; + } Buffer = HostAdapter->MessageBuffer; Length = HostAdapter->MessageBufferLength; Length += sprintf(&Buffer[Length], "\n\ diff -u --recursive --new-file v2.1.115/linux/drivers/scsi/BusLogic.h linux/drivers/scsi/BusLogic.h --- v2.1.115/linux/drivers/scsi/BusLogic.h Fri Jul 31 17:07:58 1998 +++ linux/drivers/scsi/BusLogic.h Tue Aug 18 17:49:20 1998 @@ -1772,4 +1772,43 @@ static void BusLogic_ParseDriverOptions(char *); +/* + Declare the Initialization Functions. +*/ + +static void BusLogic_AnnounceDriver(BusLogic_HostAdapter_T *) __init; +static void BusLogic_RegisterHostAdapter(BusLogic_HostAdapter_T *) __init; +static void BusLogic_UnregisterHostAdapter(BusLogic_HostAdapter_T *) __init; +static boolean BusLogic_CreateInitialCCBs(BusLogic_HostAdapter_T *) __init; +static void BusLogic_DestroyCCBs(BusLogic_HostAdapter_T *) __init; +static void BusLogic_AppendProbeAddressISA(BusLogic_IO_Address_T) __init; +static void +BusLogic_InitializeProbeInfoListISA(BusLogic_HostAdapter_T *) __init; +static void BusLogic_SortProbeInfo(BusLogic_ProbeInfo_T *, int) __init; +static int +BusLogic_InitializeMultiMasterProbeInfo(BusLogic_HostAdapter_T *) __init; +static int +BusLogic_InitializeFlashPointProbeInfo(BusLogic_HostAdapter_T *) __init; +static void BusLogic_InitializeProbeInfoList(BusLogic_HostAdapter_T *) __init; +static boolean BusLogic_Failure(BusLogic_HostAdapter_T *, char *) __init; +static boolean BusLogic_ProbeHostAdapter(BusLogic_HostAdapter_T *) __init; +static boolean BusLogic_CheckHostAdapter(BusLogic_HostAdapter_T *) __init; +static boolean +BusLogic_ReadHostAdapterConfiguration(BusLogic_HostAdapter_T *) __init; +static boolean +BusLogic_ReportHostAdapterConfiguration(BusLogic_HostAdapter_T *) __init; +static boolean BusLogic_AcquireResources(BusLogic_HostAdapter_T *) __init; +static void BusLogic_ReleaseResources(BusLogic_HostAdapter_T *) __init; +static boolean BusLogic_TargetDeviceInquiry(BusLogic_HostAdapter_T *) __init; +static void BusLogic_ReportTargetDeviceInfo(BusLogic_HostAdapter_T *) __init; +static void BusLogic_InitializeHostStructure(BusLogic_HostAdapter_T *, + SCSI_Host_T *) __init; +static void BusLogic_SelectQueueDepths(SCSI_Host_T *, SCSI_Device_T *) __init; +int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *) __init; +int BusLogic_ReleaseHostAdapter(SCSI_Host_T *) __init; +static boolean BusLogic_ParseKeyword(char **, char *) __init; +static void BusLogic_ParseDriverOptions(char *) __init; +void BusLogic_Setup(char *, int *) __init; + + #endif /* BusLogic_DriverVersion */ diff -u --recursive --new-file v2.1.115/linux/drivers/scsi/FlashPoint.c linux/drivers/scsi/FlashPoint.c --- v2.1.115/linux/drivers/scsi/FlashPoint.c Tue Feb 17 13:12:47 1998 +++ linux/drivers/scsi/FlashPoint.c Mon Aug 17 01:01:01 1998 @@ -3165,11 +3165,11 @@ if(RD_HARPOON(ioport + hp_page_ctrl) & BIOS_SHADOW) { - pAdapterInfo->ai_FlashRomSize = 64 * 1024; /* 64k Rom */ + pAdapterInfo->ai_FlashRomSize = 64 * 1024; /* 64k ROM */ } else { - pAdapterInfo->ai_FlashRomSize = 32 * 1024; /* 32k Rom */ + pAdapterInfo->ai_FlashRomSize = 32 * 1024; /* 32k ROM */ } pAdapterInfo->ai_stateinfo |= (FAST20_ENA | TAG_QUEUE_ENA); @@ -4944,7 +4944,7 @@ * * Function: Sccb_bad_isr * - * Description: Some type of interrupt has occured which is slightly + * Description: Some type of interrupt has occurred which is slightly * out of the ordinary. We will now decode it fully, in * this routine. This is broken up in an attempt to save * processing time. @@ -7038,7 +7038,7 @@ * * Function: sssyncv * - * Description: Write the desired value to the Sync Regisiter for the + * Description: Write the desired value to the Sync Register for the * ID specified. * *---------------------------------------------------------------------*/ diff -u --recursive --new-file v2.1.115/linux/drivers/scsi/README.BusLogic linux/drivers/scsi/README.BusLogic --- v2.1.115/linux/drivers/scsi/README.BusLogic Wed Apr 1 20:11:52 1998 +++ linux/drivers/scsi/README.BusLogic Mon Aug 17 01:01:01 1998 @@ -1,16 +1,17 @@ BusLogic MultiMaster and FlashPoint SCSI Driver for Linux - Version 2.0.12 for Linux 2.0 + Version 2.0.15 for Linux 2.0 + Version 2.1.15 for Linux 2.1 PRODUCTION RELEASE - 29 March 1998 + 17 August 1998 Leonard N. Zubkoff Dandelion Digital lnz@dandelion.com - Copyright 1995 by Leonard N. Zubkoff + Copyright 1995-1998 by Leonard N. Zubkoff INTRODUCTION @@ -80,7 +81,7 @@ Mylex Corporation is located at 34551 Ardenwood Blvd., Fremont, California 94555, USA and can be reached at 510/796-6100 or on the World Wide Web at -http://www.mylex.com. Mylex Technical Support can be reached by electronic +http://www.mylex.com. Mylex HBA Technical Support can be reached by electronic mail at techsup@mylex.com, by Voice at 510/608-2400, or by FAX at 510/745-7715. Contact information for offices in Europe and Japan is available on the Web site. @@ -584,16 +585,16 @@ DRIVER INSTALLATION -This distribution was prepared for Linux kernel version 2.0.33, but should be +This distribution was prepared for Linux kernel version 2.0.35, but should be compatible with 2.0.4 or any later 2.0 series kernel. To install the new BusLogic SCSI driver, you may use the following commands, replacing "/usr/src" with wherever you keep your Linux kernel source tree: cd /usr/src - tar -xvzf BusLogic-2.0.12.tar.gz + tar -xvzf BusLogic-2.0.15.tar.gz mv README.* LICENSE.* BusLogic.[ch] FlashPoint.c linux/drivers/scsi - patch -p < BusLogic.patch + patch -p0 < BusLogic.patch (only for 2.0.33 and below) cd linux make config make depend diff -u --recursive --new-file v2.1.115/linux/drivers/scsi/README.Mylex linux/drivers/scsi/README.Mylex --- v2.1.115/linux/drivers/scsi/README.Mylex Tue Feb 17 13:12:47 1998 +++ linux/drivers/scsi/README.Mylex Mon Aug 17 01:01:01 1998 @@ -1,6 +1,5 @@ Please see the file README.BusLogic for information about Linux support for Mylex (formerly BusLogic) MultiMaster and FlashPoint SCSI Host Adapters. -The Mylex DAC960 PCI RAID Controllers are not supported at the present time, -but work on a Linux driver for the DAC960 is in progress. Please consult +The Mylex DAC960 PCI RAID Controllers are now supported. Please consult http://www.dandelion.com/Linux/ for further information on the DAC960 driver. diff -u --recursive --new-file v2.1.115/linux/drivers/video/tgafb.c linux/drivers/video/tgafb.c --- v2.1.115/linux/drivers/video/tgafb.c Mon Aug 3 12:45:47 1998 +++ linux/drivers/video/tgafb.c Sun Aug 9 12:09:06 1998 @@ -688,7 +688,7 @@ fb_var.xres = fb_var.xres_virtual = 640; fb_var.yres = fb_var.yres_virtual = 480; fb_fix.line_length = 80*fb_var.bits_per_pixel; - fb_fix.smem_start = (char *)__pa(tga_fb_base + DENSE_MEM(tga_fb_base)); + fb_fix.smem_start = (char *)__pa(tga_fb_base + dense_mem(tga_fb_base)); fb_fix.smem_len = fb_fix.line_length*fb_var.yres; fb_fix.type = FB_TYPE_PACKED_PIXELS; fb_fix.type_aux = 0; @@ -729,7 +729,7 @@ disp.cmap.start = 0; disp.cmap.len = 0; disp.cmap.red = disp.cmap.green = disp.cmap.blue = disp.cmap.transp = NULL; - disp.screen_base = (char *)tga_fb_base + DENSE_MEM(tga_fb_base); + disp.screen_base = (char *)tga_fb_base + dense_mem(tga_fb_base); disp.visual = fb_fix.visual; disp.type = fb_fix.type; disp.type_aux = fb_fix.type_aux; diff -u --recursive --new-file v2.1.115/linux/drivers/video/vgacon.c linux/drivers/video/vgacon.c --- v2.1.115/linux/drivers/video/vgacon.c Thu Aug 6 14:06:33 1998 +++ linux/drivers/video/vgacon.c Sun Aug 9 12:06:00 1998 @@ -453,6 +453,8 @@ */ vga_video_num_columns = c->vc_cols; vga_video_num_lines = c->vc_rows; + if (vga_is_gfx) + return 1; scr_memcpyw_to((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf, c->vc_screenbuf_size); return 0; /* Redrawing not needed */ } @@ -933,6 +935,8 @@ c->vc_x = ORIG_X; c->vc_y = ORIG_Y; } + if (vga_is_gfx) + return; scr_memcpyw_from((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin, c->vc_screenbuf_size); } diff -u --recursive --new-file v2.1.115/linux/fs/autofs/autofs_i.h linux/fs/autofs/autofs_i.h --- v2.1.115/linux/fs/autofs/autofs_i.h Fri Jul 31 17:10:33 1998 +++ linux/fs/autofs/autofs_i.h Tue Aug 18 17:49:21 1998 @@ -129,7 +129,7 @@ /* Expiration-handling functions */ void autofs_update_usage(struct autofs_dirhash *,struct autofs_dir_ent *); -struct autofs_dir_ent *autofs_expire(struct autofs_dirhash *,unsigned long); +struct autofs_dir_ent *autofs_expire(struct super_block *,struct autofs_sb_info *); /* Operations structures */ diff -u --recursive --new-file v2.1.115/linux/fs/autofs/dirhash.c linux/fs/autofs/dirhash.c --- v2.1.115/linux/fs/autofs/dirhash.c Wed Feb 4 11:36:01 1998 +++ linux/fs/autofs/dirhash.c Tue Aug 18 13:12:17 1998 @@ -37,15 +37,72 @@ autofs_init_usage(dh,ent); /* Relink at queue tail */ } -struct autofs_dir_ent *autofs_expire(struct autofs_dirhash *dh, - unsigned long timeout) +struct autofs_dir_ent *autofs_expire(struct super_block *sb, + struct autofs_sb_info *sbi) { + struct autofs_dirhash *dh = &sbi->dirhash; struct autofs_dir_ent *ent; + struct dentry *dentry; + unsigned long timeout = sbi->exp_timeout; ent = dh->expiry_head.exp_next; - if ( ent == &(dh->expiry_head) ) return NULL; - return (jiffies - ent->last_usage >= timeout) ? ent : NULL; + if ( ent == &(dh->expiry_head) ) + return NULL; /* No entries */ + + while ( jiffies - ent->last_usage >= timeout ) { + /* Move to end of list in case expiry isn't desirable */ + autofs_update_usage(dh, ent); + + /* Check to see that entry is expirable */ + if ( ent->ino < AUTOFS_FIRST_DIR_INO ) + return ent; /* Symlinks are always expirable */ + + /* Get the dentry for the autofs subdirectory */ + dentry = lookup_dentry(ent->name, dget(sb->s_root), 0); + + if ( IS_ERR(dentry) ) { + printk("autofs: no such dentry on expiry queue: %s\n", + ent->name); + autofs_delete_usage(ent); + continue; + } + + if ( !dentry->d_inode ) { + dput(dentry); + printk("autofs: negative dentry on expiry queue: %s\n", + ent->name); + autofs_delete_usage(ent); + continue; + } + + /* Make sure entry is mounted and unused; note that dentry will + point to the mounted-on-top root. */ + if ( !S_ISDIR(dentry->d_inode->i_mode) + || dentry->d_covers == dentry ) { + dput(dentry); + DPRINTK(("autofs: not expirable (not a mounted directory): %s\n", ent->name)); + continue; + } + + /* + * Now, this is known to be a mount point; therefore the dentry + * will be held by the superblock. is_root_busy() will break if + * we hold a use count here, so we have to dput() it before calling + * is_root_busy(). However, since it is a mount point (already + * verified), dput() will be a nonblocking operation and the use + * count will not go to zero; therefore the call to is_root_busy() + * here is legal. + */ + dput(dentry); + + if ( !is_root_busy(dentry) ) { + DPRINTK(("autofs: signaling expire on %s\n", ent->name)); + return ent; /* Expirable! */ + } + DPRINTK(("autofs: didn't expire due to is_root_busy: %s\n", ent->name)); + } + return NULL; /* No expirable entries */ } void autofs_initialize_hash(struct autofs_dirhash *dh) { diff -u --recursive --new-file v2.1.115/linux/fs/autofs/root.c linux/fs/autofs/root.c --- v2.1.115/linux/fs/autofs/root.c Thu May 7 22:51:52 1998 +++ linux/fs/autofs/root.c Tue Aug 18 13:12:17 1998 @@ -289,7 +289,7 @@ return -ENOSPC; } - ent->name = kmalloc(dentry->d_name.len, GFP_KERNEL); + ent->name = kmalloc(dentry->d_name.len+1, GFP_KERNEL); if ( !ent->name ) { kfree(sl->data); kfree(ent); @@ -302,7 +302,7 @@ ent->ino = AUTOFS_FIRST_SYMLINK + n; ent->hash = dentry->d_name.hash; - memcpy(ent->name, dentry->d_name.name,ent->len = dentry->d_name.len); + memcpy(ent->name, dentry->d_name.name, 1+(ent->len = dentry->d_name.len)); autofs_hash_insert(dh,ent); d_instantiate(dentry, iget(dir->i_sb,ent->ino)); @@ -392,14 +392,14 @@ if ( !ent ) return -ENOSPC; - ent->name = kmalloc(dentry->d_name.len, GFP_KERNEL); + ent->name = kmalloc(dentry->d_name.len+1, GFP_KERNEL); if ( !ent->name ) { kfree(ent); return -ENOSPC; } ent->hash = dentry->d_name.hash; - memcpy(ent->name, dentry->d_name.name, ent->len = dentry->d_name.len); + memcpy(ent->name, dentry->d_name.name, 1+(ent->len = dentry->d_name.len)); ent->ino = sbi->next_dir_ino++; autofs_hash_insert(dh,ent); dir->i_nlink++; @@ -434,20 +434,20 @@ } /* Perform an expiry operation */ -static inline int autofs_expire_run(struct autofs_sb_info *sbi, +static inline int autofs_expire_run(struct super_block *sb, + struct autofs_sb_info *sbi, struct autofs_packet_expire *pkt_p) { struct autofs_dir_ent *ent; struct autofs_packet_expire pkt; - struct autofs_dirhash *dh = &(sbi->dirhash); - + memset(&pkt,0,sizeof pkt); pkt.hdr.proto_version = AUTOFS_PROTO_VERSION; pkt.hdr.type = autofs_ptype_expire; if ( !sbi->exp_timeout || - !(ent = autofs_expire(dh,sbi->exp_timeout)) ) + !(ent = autofs_expire(sb,sbi)) ) return -EAGAIN; pkt.len = ent->len; @@ -456,8 +456,6 @@ if ( copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)) ) return -EFAULT; - - autofs_update_usage(dh,ent); return 0; } @@ -494,7 +492,8 @@ case AUTOFS_IOC_SETTIMEOUT: return autofs_get_set_timeout(sbi,(unsigned long *)arg); case AUTOFS_IOC_EXPIRE: - return autofs_expire_run(sbi,(struct autofs_packet_expire *)arg); + return autofs_expire_run(inode->i_sb,sbi, + (struct autofs_packet_expire *)arg); default: return -ENOSYS; } diff -u --recursive --new-file v2.1.115/linux/fs/binfmt_aout.c linux/fs/binfmt_aout.c --- v2.1.115/linux/fs/binfmt_aout.c Tue Jun 23 10:01:24 1998 +++ linux/fs/binfmt_aout.c Sat Aug 15 16:34:52 1998 @@ -101,7 +101,7 @@ # define START_STACK(u) (u.start_stack) #endif - if (!current->dumpable || current->mm->count != 1) + if (!current->dumpable || atomic_read(¤t->mm->count) != 1) return 0; current->dumpable = 0; diff -u --recursive --new-file v2.1.115/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c --- v2.1.115/linux/fs/binfmt_elf.c Wed Jun 24 22:54:08 1998 +++ linux/fs/binfmt_elf.c Tue Aug 18 13:15:51 1998 @@ -1054,14 +1054,16 @@ struct vm_area_struct *vma; struct elfhdr elf; off_t offset = 0, dataoff; - long limit = current->rlim[RLIMIT_CORE].rlim_cur; + unsigned long limit = current->rlim[RLIMIT_CORE].rlim_cur; int numnote = 4; struct memelfnote notes[4]; struct elf_prstatus prstatus; /* NT_PRSTATUS */ elf_fpregset_t fpu; /* NT_PRFPREG */ struct elf_prpsinfo psinfo; /* NT_PRPSINFO */ - if (!current->dumpable || limit < ELF_EXEC_PAGESIZE || current->mm->count != 1) + if (!current->dumpable || + limit < ELF_EXEC_PAGESIZE || + atomic_read(¤t->mm->count) != 1) return 0; current->dumpable = 0; @@ -1075,7 +1077,7 @@ for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { if (maydump(vma)) { - int sz = vma->vm_end-vma->vm_start; + unsigned long sz = vma->vm_end-vma->vm_start; if (size+sz >= limit) break; diff -u --recursive --new-file v2.1.115/linux/fs/dcache.c linux/fs/dcache.c --- v2.1.115/linux/fs/dcache.c Sun Jul 26 11:57:18 1998 +++ linux/fs/dcache.c Tue Aug 18 13:12:17 1998 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -29,6 +30,8 @@ extern int inodes_stat[]; #define nr_inodes (inodes_stat[0]) +kmem_cache_t *dentry_cache; + /* * This is the single most critical data structure when it comes * to the dcache: the hashtable for lookups. Somebody should try @@ -56,8 +59,9 @@ { if (dentry->d_op && dentry->d_op->d_release) dentry->d_op->d_release(dentry); - kfree(dentry->d_name.name); - kfree(dentry); + if (dname_external(dentry)) + kfree(dentry->d_name.name); + kmem_cache_free(dentry_cache, dentry); } /* @@ -398,7 +402,7 @@ this_parent = this_parent->d_parent; goto resume; } - return (count == 1); /* one remaining use count? */ + return (count > 1); /* remaining users? */ } /* @@ -498,15 +502,18 @@ free_inode_memory(8); } - dentry = kmalloc(sizeof(struct dentry), GFP_KERNEL); + dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL); if (!dentry) return NULL; - str = kmalloc(NAME_ALLOC_LEN(name->len), GFP_KERNEL); - if (!str) { - kfree(dentry); - return NULL; - } + if (name->len > DNAME_INLINE_LEN-1) { + str = kmalloc(NAME_ALLOC_LEN(name->len), GFP_KERNEL); + if (!str) { + kmem_cache_free(dentry_cache, dentry); + return NULL; + } + } else + str = dentry->d_iname; memcpy(str, name->name, name->len); str[name->len] = 0; @@ -692,6 +699,32 @@ x = y; y = __tmp; } while (0) /* + * When switching names, the actual string doesn't strictly have to + * be preserved in the target - because we're dropping the target + * anyway. As such, we can just do a simple memcpy() to copy over + * the new name before we switch. + * + * Note that we have to be a lot more careful about getting the hash + * switched - we have to switch the hash value properly even if it + * then no longer matches the actual (corrupted) string of the target. + * The has value has to match the hash queue that the dentry is on.. + */ +static inline void switch_names(struct dentry * dentry, struct dentry * target) +{ + const unsigned char *old_name, *new_name; + + memcpy(dentry->d_iname, target->d_iname, DNAME_INLINE_LEN); + old_name = target->d_name.name; + new_name = dentry->d_name.name; + if (old_name == target->d_iname) + old_name = dentry->d_iname; + if (new_name == dentry->d_iname) + new_name = target->d_iname; + target->d_name.name = new_name; + dentry->d_name.name = old_name; +} + +/* * We cannibalize "target" when moving dentry on top of it, * because it's going to be thrown away anyway. We could be more * polite about it, though. @@ -723,10 +756,12 @@ list_del(&target->d_child); /* Switch the parents and the names.. */ + switch_names(dentry, target); do_switch(dentry->d_parent, target->d_parent); - do_switch(dentry->d_name.name, target->d_name.name); do_switch(dentry->d_name.len, target->d_name.len); do_switch(dentry->d_name.hash, target->d_name.hash); + + /* And add them back to the (new) parent lists */ list_add(&target->d_child, &target->d_parent->d_subdirs); list_add(&dentry->d_child, &dentry->d_parent->d_subdirs); } @@ -884,6 +919,22 @@ { int i; struct list_head *d = dentry_hashtable; + + /* + * A constructor could be added for stable state like the lists, + * but it is probably not worth it because of the cache nature + * of the dcache. + * If fragmentation is too bad then the SLAB_HWCACHE_ALIGN + * flag could be removed here, to hint to the allocator that + * it should not try to get multiple page regions. + */ + dentry_cache = kmem_cache_create("dentry_cache", + sizeof(struct dentry), + 0, + SLAB_HWCACHE_ALIGN, + NULL, NULL); + if (!dentry_cache) + panic("Cannot create dentry cache"); i = D_HASHSIZE; do { diff -u --recursive --new-file v2.1.115/linux/fs/exec.c linux/fs/exec.c --- v2.1.115/linux/fs/exec.c Sun Jun 7 11:16:36 1998 +++ linux/fs/exec.c Sat Aug 15 16:34:52 1998 @@ -392,9 +392,9 @@ static int exec_mmap(void) { struct mm_struct * mm, * old_mm; - int retval; + int retval, nr; - if (current->mm->count == 1) { + if (atomic_read(¤t->mm->count) == 1) { flush_cache_mm(current->mm); exit_mmap(current->mm); clear_page_tables(current); @@ -411,9 +411,16 @@ mm = mm_alloc(); if (!mm) goto fail_nomem; + mm->cpu_vm_mask = (1UL << smp_processor_id()); mm->total_vm = 0; mm->rss = 0; + /* + * Make sure we have a private ldt if needed ... + */ + nr = current->tarray_ptr - &task[0]; + copy_segments(nr, current, mm); + old_mm = current->mm; current->mm = mm; retval = new_page_tables(current); @@ -431,6 +438,8 @@ /* The pgd belongs to the parent ... don't free it! */ mm->pgd = NULL; current->mm = old_mm; + /* restore the ldt for this task */ + copy_segments(nr, current, NULL); mmput(mm); fail_nomem: @@ -657,9 +666,9 @@ /* (current->mm->count > 1 is ok, as we'll get a new mm anyway) */ if (IS_NOSUID(inode) || (current->flags & PF_PTRACED) - || (current->fs->count > 1) + || (atomic_read(¤t->fs->count) > 1) || (atomic_read(¤t->sig->count) > 1) - || (current->files->count > 1)) { + || (atomic_read(¤t->files->count) > 1)) { if (id_change && !capable(CAP_SETUID)) return -EPERM; if (cap_raised && !capable(CAP_SETPCAP)) diff -u --recursive --new-file v2.1.115/linux/fs/ext2/namei.c linux/fs/ext2/namei.c --- v2.1.115/linux/fs/ext2/namei.c Fri May 8 23:14:53 1998 +++ linux/fs/ext2/namei.c Sat Aug 15 11:16:10 1998 @@ -41,14 +41,17 @@ /* * NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure. + * + * `len <= EXT2_NAME_LEN' is guaranteed by caller. + * `de != NULL' is guaranteed by caller. */ static inline int ext2_match (int len, const char * const name, struct ext2_dir_entry_2 * de) { - if (!de || !le32_to_cpu(de->inode) || len > EXT2_NAME_LEN) - return 0; if (len != de->name_len) return 0; + if (!de->inode) + return 0; return !memcmp(name, de->name, len); } @@ -121,10 +124,17 @@ de = (struct ext2_dir_entry_2 *) bh->b_data; dlimit = bh->b_data + sb->s_blocksize; while ((char *) de < dlimit) { - if (!ext2_check_dir_entry ("ext2_find_entry", dir, - de, bh, offset)) - goto failure; - if (ext2_match (namelen, name, de)) { + /* this code is executed quadratically often */ + /* do minimal checking `by hand' */ + int de_len; + + if ((char *) de + namelen <= dlimit && + ext2_match (namelen, name, de)) { + /* found a match - + just to be sure, do a full check */ + if (!ext2_check_dir_entry("ext2_find_entry", + dir, de, bh, offset)) + goto failure; for (i = 0; i < NAMEI_RA_SIZE; ++i) { if (bh_use[i] != bh) brelse (bh_use[i]); @@ -132,9 +142,13 @@ *res_dir = de; return bh; } - offset += le16_to_cpu(de->rec_len); + /* prevent looping on a bad block */ + de_len = le16_to_cpu(de->rec_len); + if (de_len <= 0) + goto failure; + offset += de_len; de = (struct ext2_dir_entry_2 *) - ((char *) de + le16_to_cpu(de->rec_len)); + ((char *) de + de_len); } brelse (bh); diff -u --recursive --new-file v2.1.115/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c --- v2.1.115/linux/fs/nfsd/vfs.c Tue Jul 21 00:15:32 1998 +++ linux/fs/nfsd/vfs.c Thu Aug 6 22:15:29 1998 @@ -1157,10 +1157,7 @@ /* If we didn't fill the buffer completely, we're at EOF */ eof = !cd.eob; - /* Hewlett Packard ignores the eof flag on READDIR. Some - * fs-specific readdir implementations seem to reset f_pos to 0 - * at EOF however, causing an endless loop. */ - if (cd.offset && !eof) + if (cd.offset) *cd.offset = htonl(file.f_pos); p = cd.buffer; diff -u --recursive --new-file v2.1.115/linux/fs/ntfs/super.c linux/fs/ntfs/super.c --- v2.1.115/linux/fs/ntfs/super.c Wed May 20 19:10:40 1998 +++ linux/fs/ntfs/super.c Tue Aug 18 13:14:17 1998 @@ -32,7 +32,7 @@ int ntfs_fixup_record(ntfs_volume *vol, char *record, char *magic, int size) { int start, count, offset; - short fixup; + unsigned short fixup; if(!IS_MAGIC(record,magic)) return 0; diff -u --recursive --new-file v2.1.115/linux/fs/proc/array.c linux/fs/proc/array.c --- v2.1.115/linux/fs/proc/array.c Mon Aug 3 12:45:47 1998 +++ linux/fs/proc/array.c Sat Aug 15 16:34:52 1998 @@ -35,6 +35,8 @@ * - Incorporation and non-SMP safe operation * of forissier patch in 2.1.78 by * Hans Marcus + * + * aeb@cwi.nl : /proc/partitions */ #include @@ -1059,7 +1061,7 @@ goto getlen_out; /* Check whether the mmaps could change if we sleep */ - volatile_task = (p != current || p->mm->count > 1); + volatile_task = (p != current || atomic_read(&p->mm->count) > 1); /* decode f_pos */ lineno = *ppos >> MAPS_LINE_SHIFT; @@ -1191,6 +1193,7 @@ extern int get_ksyms_list(char *, char **, off_t, int); #endif extern int get_device_list(char *); +extern int get_partition_list(char *); extern int get_filesystem_list(char *); extern int get_filesystem_info( char * ); extern int get_irq_list(char *); @@ -1249,6 +1252,9 @@ case PROC_DEVICES: return get_device_list(page); + + case PROC_PARTITIONS: + return get_partition_list(page); case PROC_INTERRUPTS: return get_irq_list(page); diff -u --recursive --new-file v2.1.115/linux/fs/proc/generic.c linux/fs/proc/generic.c --- v2.1.115/linux/fs/proc/generic.c Sun Jul 26 11:57:18 1998 +++ linux/fs/proc/generic.c Sun Aug 9 10:42:41 1998 @@ -283,7 +283,11 @@ extern void free_proc_entry(struct proc_dir_entry *); void free_proc_entry(struct proc_dir_entry *de) { - kfree(de); + int ino = de->low_ino; + + if (ino >= PROC_DYNAMIC_FIRST && + ino < PROC_DYNAMIC_FIRST+PROC_NDYNAMIC) + kfree(de); } /* diff -u --recursive --new-file v2.1.115/linux/fs/proc/root.c linux/fs/proc/root.c --- v2.1.115/linux/fs/proc/root.c Mon Aug 3 12:45:47 1998 +++ linux/fs/proc/root.c Wed Aug 12 16:19:50 1998 @@ -560,6 +560,11 @@ S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_array_inode_operations }; +static struct proc_dir_entry proc_root_partitions = { + PROC_PARTITIONS, 10, "partitions", + S_IFREG | S_IRUGO, 1, 0, 0, + 0, &proc_array_inode_operations +}; static struct proc_dir_entry proc_root_interrupts = { PROC_INTERRUPTS, 10,"interrupts", S_IFREG | S_IRUGO, 1, 0, 0, @@ -667,6 +672,7 @@ #endif proc_register(&proc_root, &proc_root_stat); proc_register(&proc_root, &proc_root_devices); + proc_register(&proc_root, &proc_root_partitions); proc_register(&proc_root, &proc_root_interrupts); proc_register(&proc_root, &proc_root_filesystems); proc_register(&proc_root, &proc_root_fs); @@ -813,16 +819,14 @@ } read_lock(&tasklist_lock); p = find_task_by_pid(pid); + read_unlock(&tasklist_lock); inode = NULL; if (pid && p) { unsigned long ino = (pid << 16) + PROC_PID_INO; inode = proc_get_inode(dir->i_sb, ino, &proc_pid); - if (!inode) { - read_unlock(&tasklist_lock); + if (!inode) return -EINVAL; - } } - read_unlock(&tasklist_lock); dentry->d_op = &proc_dentry_operations; d_add(dentry, inode); @@ -889,46 +893,68 @@ return 1; } -#define NUMBUF 10 +#define PROC_NUMBUF 10 +#define PROC_MAXPIDS 20 + +/* + * Get a few pid's to return for filldir - we need to hold the + * tasklist lock while doing this, and we must release it before + * we actually do the filldir itself, so we use a temp buffer.. + */ +static int get_pid_list(unsigned int index, unsigned int *pids) +{ + struct task_struct *p; + int nr = FIRST_PROCESS_ENTRY; + int nr_pids = 0; + + read_lock(&tasklist_lock); + for_each_task(p) { + int pid; + if (nr++ < index) + continue; + pid = p->pid; + if (!pid) + continue; + pids[nr_pids] = pid; + nr_pids++; + if (nr_pids >= PROC_MAXPIDS) + break; + } + read_unlock(&tasklist_lock); + return nr_pids; +} static int proc_root_readdir(struct file * filp, void * dirent, filldir_t filldir) { - struct task_struct *p; - char buf[NUMBUF]; + unsigned int pid_array[PROC_MAXPIDS]; + char buf[PROC_NUMBUF]; unsigned int nr = filp->f_pos; + unsigned int nr_pids, i; if (nr < FIRST_PROCESS_ENTRY) { int error = proc_readdir(filp, dirent, filldir); if (error <= 0) return error; - filp->f_pos = FIRST_PROCESS_ENTRY; + filp->f_pos = nr = FIRST_PROCESS_ENTRY; } - nr = FIRST_PROCESS_ENTRY; - read_lock(&tasklist_lock); - for_each_task(p) { - unsigned int pid; + nr_pids = get_pid_list(nr, pid_array); - if(nr++ < filp->f_pos) - continue; + for (i = 0; i < nr_pids; i++) { + int pid = pid_array[i]; + unsigned long j = PROC_NUMBUF; + + do { + j--; + buf[j] = '0' + (pid % 10); + pid /= 10; + } while (pid); - if((pid = p->pid) != 0) { - unsigned long j = NUMBUF, i = pid; - - do { - j--; - buf[j] = '0' + (i % 10); - i /= 10; - } while (i); - - if (filldir(dirent, buf+j, NUMBUF-j, - filp->f_pos, (pid << 16) + PROC_PID_INO) < 0) - break; - } + if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, (pid << 16) + PROC_PID_INO) < 0) + break; filp->f_pos++; } - read_unlock(&tasklist_lock); return 0; } diff -u --recursive --new-file v2.1.115/linux/fs/read_write.c linux/fs/read_write.c --- v2.1.115/linux/fs/read_write.c Fri May 8 23:14:53 1998 +++ linux/fs/read_write.c Mon Aug 10 22:33:55 1998 @@ -106,7 +106,7 @@ offset = llseek(file, ((loff_t) offset_high << 32) | offset_low, origin); - retval = (int)offset & INT_MAX; + retval = (int)offset; if (offset >= 0) { retval = -EFAULT; if (!copy_to_user(result, &offset, sizeof(offset))) diff -u --recursive --new-file v2.1.115/linux/fs/smbfs/proc.c linux/fs/smbfs/proc.c --- v2.1.115/linux/fs/smbfs/proc.c Thu May 7 22:51:54 1998 +++ linux/fs/smbfs/proc.c Sun Aug 9 19:06:26 1998 @@ -179,13 +179,13 @@ static time_t utc2local(time_t time) { - return time - sys_tz.tz_minuteswest * 60; + return time - sys_tz.tz_minuteswest * 60 - (sys_tz.tz_dsttime ? 3600 :0); } static time_t local2utc(time_t time) { - return time + sys_tz.tz_minuteswest * 60; + return time + sys_tz.tz_minuteswest * 60 + (sys_tz.tz_dsttime ? 3600 : 0); } /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */ diff -u --recursive --new-file v2.1.115/linux/fs/super.c linux/fs/super.c --- v2.1.115/linux/fs/super.c Tue Jul 21 00:15:32 1998 +++ linux/fs/super.c Sun Aug 9 12:25:12 1998 @@ -633,7 +633,7 @@ dentry->d_covers = covered; } -static int do_umount(kdev_t dev, int unmount_root) +static int do_umount(kdev_t dev, int unmount_root, int flags) { struct super_block * sb; int retval; @@ -665,7 +665,7 @@ * about for the moment. */ - if(sb->s_op->umount_begin) + if( (flags&MNT_FORCE) && sb->s_op->umount_begin) sb->s_op->umount_begin(sb); /* @@ -717,7 +717,7 @@ return retval; } -static int umount_dev(kdev_t dev) +static int umount_dev(kdev_t dev, int flags) { int retval; struct inode * inode = get_empty_inode(); @@ -735,7 +735,7 @@ down(&mount_sem); - retval = do_umount(dev,0); + retval = do_umount(dev, 0, flags); if (!retval) { fsync_dev(dev); if (dev != ROOT_DEV) { @@ -761,10 +761,11 @@ * If any other fields are ever needed by any block device release * functions, they should be faked here. -- jrs * - * For 2.3.x we want a new sys_umount syscall with flags (ie 'force') + * We now support a flag for forced unmount like the other 'big iron' + * unixes. Our API is identical to OSF/1 to avoid making a mess of AMD */ -asmlinkage int sys_umount(char * name) +asmlinkage int sys_umount(char * name, int flags) { struct dentry * dentry; int retval; @@ -794,13 +795,22 @@ dput(dentry); if (!retval) - retval = umount_dev(dev); + retval = umount_dev(dev, flags); } unlock_kernel(); return retval; } /* + * The 2.0 compatible umount. No flags. + */ + +asmlinkage int sys_oldumount(char * name) +{ + return sys_umount(name,0); +} + +/* * Check whether we can mount the specified device. */ int fs_may_mount(kdev_t dev) @@ -1263,7 +1273,7 @@ int umount_error; printk(KERN_NOTICE "Trying to unmount old root ... "); - umount_error = do_umount(old_root_dev,1); + umount_error = do_umount(old_root_dev,1, 0); if (!umount_error) { printk("okay\n"); invalidate_buffers(old_root_dev); diff -u --recursive --new-file v2.1.115/linux/fs/vfat/namei.c linux/fs/vfat/namei.c --- v2.1.115/linux/fs/vfat/namei.c Thu Jul 16 18:09:28 1998 +++ linux/fs/vfat/namei.c Sun Aug 9 19:35:26 1998 @@ -1771,6 +1771,8 @@ MSDOS_I(new_inode)->i_logstart = MSDOS_I(old_inode)->i_logstart; MSDOS_I(new_inode)->i_attrs = MSDOS_I(old_inode)->i_attrs; + old_inode->i_nlink = 0; + fat_cache_inval_inode(old_inode); mark_inode_dirty(new_inode); diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/apecs.h linux/include/asm-alpha/apecs.h --- v2.1.115/linux/include/asm-alpha/apecs.h Tue Jul 21 00:15:32 1998 +++ linux/include/asm-alpha/apecs.h Wed Dec 31 16:00:00 1969 @@ -1,588 +0,0 @@ -#ifndef __ALPHA_APECS__H__ -#define __ALPHA_APECS__H__ - -#include - -/* - * APECS is the internal name for the 2107x chipset which provides - * memory controller and PCI access for the 21064 chip based systems. - * - * This file is based on: - * - * DECchip 21071-AA and DECchip 21072-AA Core Logic Chipsets - * Data Sheet - * - * EC-N0648-72 - * - * - * david.rusling@reo.mts.dec.com Initial Version. - * - */ -#include - -#ifdef CONFIG_ALPHA_XL -/* - An AVANTI *might* be an XL, and an XL has only 27 bits of ISA address - that get passed through the PCI<->ISA bridge chip. So we've gotta use - both windows to max out the physical memory we can DMA to. Sigh... - - If we try a window at 0 for 1GB as a work-around, we run into conflicts - with ISA/PCI bus memory which can't be relocated, like VGA aperture and - BIOS ROMs. So we must put the windows high enough to avoid these areas. - - We put window 1 at BUS 64Mb for 64Mb, mapping physical 0 to 64Mb-1, - and window 2 at BUS 1Gb for 1Gb, mapping physical 0 to 1Gb-1. - Yes, this does map 0 to 64Mb-1 twice, but only window 1 will actually - be used for that range (via virt_to_bus()). - - Note that we actually fudge the window 1 maximum as 48Mb instead of 64Mb, - to keep virt_to_bus() from returning an address in the first window, for - a data area that goes beyond the 64Mb first DMA window. Sigh... - The fudge factor MUST match with MAX_DMA_ADDRESS, but - we can't just use that here, because of header file looping... :-( - - Window 1 will be used for all DMA from the ISA bus; yes, that does - limit what memory an ISA floppy or sound card or Ethernet can touch, but - it's also a known limitation on other platforms as well. We use the - same technique that is used on INTEL platforms with similar limitation: - set MAX_DMA_ADDRESS and clear some pages' DMAable flags during mem_init(). - We trust that any ISA bus device drivers will *always* ask for DMAable - memory explicitly via kmalloc()/get_free_pages() flags arguments. - - Note that most PCI bus devices' drivers do *not* explicitly ask for - DMAable memory; they count on being able to DMA to any memory they - get from kmalloc()/get_free_pages(). They will also use window 1 for - any physical memory accesses below 64Mb; the rest will be handled by - window 2, maxing out at 1Gb of memory. I trust this is enough... :-) - - We hope that the area before the first window is large enough so that - there will be no overlap at the top end (64Mb). We *must* locate the - PCI cards' memory just below window 1, so that there's still the - possibility of being able to access it via SPARSE space. This is - important for cards such as the Matrox Millennium, whose Xserver - wants to access memory-mapped registers in byte and short lengths. - - Note that the XL is treated differently from the AVANTI, even though - for most other things they are identical. It didn't seem reasonable to - make the AVANTI support pay for the limitations of the XL. It is true, - however, that an XL kernel will run on an AVANTI without problems. - -*/ -#define APECS_XL_DMA_WIN1_BASE (64*1024*1024) -#define APECS_XL_DMA_WIN1_SIZE (64*1024*1024) -#define APECS_XL_DMA_WIN1_SIZE_PARANOID (48*1024*1024) -#define APECS_XL_DMA_WIN2_BASE (1024*1024*1024) -#define APECS_XL_DMA_WIN2_SIZE (1024*1024*1024) - -#else /* CONFIG_ALPHA_XL */ - -/* these are for normal APECS family machines, AVANTI/MUSTANG/EB64/PC64 */ -#ifdef CONFIG_ALPHA_SRM_SETUP -/* if we are using the SRM PCI setup, we'll need to use variables instead */ -#define APECS_DMA_WIN_BASE_DEFAULT (1024*1024*1024) -#define APECS_DMA_WIN_SIZE_DEFAULT (1024*1024*1024) - -extern unsigned int APECS_DMA_WIN_BASE; -extern unsigned int APECS_DMA_WIN_SIZE; - -#else /* SRM_SETUP */ -#define APECS_DMA_WIN_BASE (1024*1024*1024) -#define APECS_DMA_WIN_SIZE (1024*1024*1024) -#endif /* SRM_SETUP */ - -#endif /* CONFIG_ALPHA_XL */ - -/* - * 21071-DA Control and Status registers. - * These are used for PCI memory access. - */ -#define APECS_IOC_DCSR (IDENT_ADDR + 0x1A0000000UL) -#define APECS_IOC_PEAR (IDENT_ADDR + 0x1A0000020UL) -#define APECS_IOC_SEAR (IDENT_ADDR + 0x1A0000040UL) -#define APECS_IOC_DR1 (IDENT_ADDR + 0x1A0000060UL) -#define APECS_IOC_DR2 (IDENT_ADDR + 0x1A0000080UL) -#define APECS_IOC_DR3 (IDENT_ADDR + 0x1A00000A0UL) - -#define APECS_IOC_TB1R (IDENT_ADDR + 0x1A00000C0UL) -#define APECS_IOC_TB2R (IDENT_ADDR + 0x1A00000E0UL) - -#define APECS_IOC_PB1R (IDENT_ADDR + 0x1A0000100UL) -#define APECS_IOC_PB2R (IDENT_ADDR + 0x1A0000120UL) - -#define APECS_IOC_PM1R (IDENT_ADDR + 0x1A0000140UL) -#define APECS_IOC_PM2R (IDENT_ADDR + 0x1A0000160UL) - -#define APECS_IOC_HAXR0 (IDENT_ADDR + 0x1A0000180UL) -#define APECS_IOC_HAXR1 (IDENT_ADDR + 0x1A00001A0UL) -#define APECS_IOC_HAXR2 (IDENT_ADDR + 0x1A00001C0UL) - -#define APECS_IOC_PMLT (IDENT_ADDR + 0x1A00001E0UL) - -#define APECS_IOC_TLBTAG0 (IDENT_ADDR + 0x1A0000200UL) -#define APECS_IOC_TLBTAG1 (IDENT_ADDR + 0x1A0000220UL) -#define APECS_IOC_TLBTAG2 (IDENT_ADDR + 0x1A0000240UL) -#define APECS_IOC_TLBTAG3 (IDENT_ADDR + 0x1A0000260UL) -#define APECS_IOC_TLBTAG4 (IDENT_ADDR + 0x1A0000280UL) -#define APECS_IOC_TLBTAG5 (IDENT_ADDR + 0x1A00002A0UL) -#define APECS_IOC_TLBTAG6 (IDENT_ADDR + 0x1A00002C0UL) -#define APECS_IOC_TLBTAG7 (IDENT_ADDR + 0x1A00002E0UL) - -#define APECS_IOC_TLBDATA0 (IDENT_ADDR + 0x1A0000300UL) -#define APECS_IOC_TLBDATA1 (IDENT_ADDR + 0x1A0000320UL) -#define APECS_IOC_TLBDATA2 (IDENT_ADDR + 0x1A0000340UL) -#define APECS_IOC_TLBDATA3 (IDENT_ADDR + 0x1A0000360UL) -#define APECS_IOC_TLBDATA4 (IDENT_ADDR + 0x1A0000380UL) -#define APECS_IOC_TLBDATA5 (IDENT_ADDR + 0x1A00003A0UL) -#define APECS_IOC_TLBDATA6 (IDENT_ADDR + 0x1A00003C0UL) -#define APECS_IOC_TLBDATA7 (IDENT_ADDR + 0x1A00003E0UL) - -#define APECS_IOC_TBIA (IDENT_ADDR + 0x1A0000400UL) - - -/* - * 21071-CA Control and Status registers. - * These are used to program memory timing, - * configure memory and initialise the B-Cache. - */ -#define APECS_MEM_GCR (IDENT_ADDR + 0x180000000UL) -#define APECS_MEM_EDSR (IDENT_ADDR + 0x180000040UL) -#define APECS_MEM_TAR (IDENT_ADDR + 0x180000060UL) -#define APECS_MEM_ELAR (IDENT_ADDR + 0x180000080UL) -#define APECS_MEM_EHAR (IDENT_ADDR + 0x1800000a0UL) -#define APECS_MEM_SFT_RST (IDENT_ADDR + 0x1800000c0UL) -#define APECS_MEM_LDxLAR (IDENT_ADDR + 0x1800000e0UL) -#define APECS_MEM_LDxHAR (IDENT_ADDR + 0x180000100UL) -#define APECS_MEM_GTR (IDENT_ADDR + 0x180000200UL) -#define APECS_MEM_RTR (IDENT_ADDR + 0x180000220UL) -#define APECS_MEM_VFPR (IDENT_ADDR + 0x180000240UL) -#define APECS_MEM_PDLDR (IDENT_ADDR + 0x180000260UL) -#define APECS_MEM_PDhDR (IDENT_ADDR + 0x180000280UL) - -/* Bank x Base Address Register */ -#define APECS_MEM_B0BAR (IDENT_ADDR + 0x180000800UL) -#define APECS_MEM_B1BAR (IDENT_ADDR + 0x180000820UL) -#define APECS_MEM_B2BAR (IDENT_ADDR + 0x180000840UL) -#define APECS_MEM_B3BAR (IDENT_ADDR + 0x180000860UL) -#define APECS_MEM_B4BAR (IDENT_ADDR + 0x180000880UL) -#define APECS_MEM_B5BAR (IDENT_ADDR + 0x1800008A0UL) -#define APECS_MEM_B6BAR (IDENT_ADDR + 0x1800008C0UL) -#define APECS_MEM_B7BAR (IDENT_ADDR + 0x1800008E0UL) -#define APECS_MEM_B8BAR (IDENT_ADDR + 0x180000900UL) - -/* Bank x Configuration Register */ -#define APECS_MEM_B0BCR (IDENT_ADDR + 0x180000A00UL) -#define APECS_MEM_B1BCR (IDENT_ADDR + 0x180000A20UL) -#define APECS_MEM_B2BCR (IDENT_ADDR + 0x180000A40UL) -#define APECS_MEM_B3BCR (IDENT_ADDR + 0x180000A60UL) -#define APECS_MEM_B4BCR (IDENT_ADDR + 0x180000A80UL) -#define APECS_MEM_B5BCR (IDENT_ADDR + 0x180000AA0UL) -#define APECS_MEM_B6BCR (IDENT_ADDR + 0x180000AC0UL) -#define APECS_MEM_B7BCR (IDENT_ADDR + 0x180000AE0UL) -#define APECS_MEM_B8BCR (IDENT_ADDR + 0x180000B00UL) - -/* Bank x Timing Register A */ -#define APECS_MEM_B0TRA (IDENT_ADDR + 0x180000C00UL) -#define APECS_MEM_B1TRA (IDENT_ADDR + 0x180000C20UL) -#define APECS_MEM_B2TRA (IDENT_ADDR + 0x180000C40UL) -#define APECS_MEM_B3TRA (IDENT_ADDR + 0x180000C60UL) -#define APECS_MEM_B4TRA (IDENT_ADDR + 0x180000C80UL) -#define APECS_MEM_B5TRA (IDENT_ADDR + 0x180000CA0UL) -#define APECS_MEM_B6TRA (IDENT_ADDR + 0x180000CC0UL) -#define APECS_MEM_B7TRA (IDENT_ADDR + 0x180000CE0UL) -#define APECS_MEM_B8TRA (IDENT_ADDR + 0x180000D00UL) - -/* Bank x Timing Register B */ -#define APECS_MEM_B0TRB (IDENT_ADDR + 0x180000E00UL) -#define APECS_MEM_B1TRB (IDENT_ADDR + 0x180000E20UL) -#define APECS_MEM_B2TRB (IDENT_ADDR + 0x180000E40UL) -#define APECS_MEM_B3TRB (IDENT_ADDR + 0x180000E60UL) -#define APECS_MEM_B4TRB (IDENT_ADDR + 0x180000E80UL) -#define APECS_MEM_B5TRB (IDENT_ADDR + 0x180000EA0UL) -#define APECS_MEM_B6TRB (IDENT_ADDR + 0x180000EC0UL) -#define APECS_MEM_B7TRB (IDENT_ADDR + 0x180000EE0UL) -#define APECS_MEM_B8TRB (IDENT_ADDR + 0x180000F00UL) - - -/* - * Memory spaces: - */ -#define APECS_IACK_SC (IDENT_ADDR + 0x1b0000000UL) -#define APECS_CONF (IDENT_ADDR + 0x1e0000000UL) -#define APECS_IO (IDENT_ADDR + 0x1c0000000UL) -#define APECS_SPARSE_MEM (IDENT_ADDR + 0x200000000UL) -#define APECS_DENSE_MEM (IDENT_ADDR + 0x300000000UL) -#define DENSE_MEM(addr) APECS_DENSE_MEM - -/* - * Bit definitions for I/O Controller status register 0: - */ -#define APECS_IOC_STAT0_CMD 0xf -#define APECS_IOC_STAT0_ERR (1<<4) -#define APECS_IOC_STAT0_LOST (1<<5) -#define APECS_IOC_STAT0_THIT (1<<6) -#define APECS_IOC_STAT0_TREF (1<<7) -#define APECS_IOC_STAT0_CODE_SHIFT 8 -#define APECS_IOC_STAT0_CODE_MASK 0x7 -#define APECS_IOC_STAT0_P_NBR_SHIFT 13 -#define APECS_IOC_STAT0_P_NBR_MASK 0x7ffff - -#define HAE_ADDRESS APECS_IOC_HAXR1 - -#ifdef __KERNEL__ - -/* - * Translate physical memory address as seen on (PCI) bus into - * a kernel virtual address and vv. - */ -/* NOTE: we fudge the window 1 maximum as 48Mb instead of 64Mb, to prevent - virt_to_bus() from returning an address in the first window, for a - data area that goes beyond the 64Mb first DMA window. Sigh... - This MUST match with MAX_DMA_ADDRESS for consistency, but - we can't just use that here, because of header file looping... :-( -*/ -extern inline unsigned long virt_to_bus(void * address) -{ - unsigned long paddr = virt_to_phys(address); -#ifdef CONFIG_ALPHA_XL - if (paddr < APECS_XL_DMA_WIN1_SIZE_PARANOID) - return paddr + APECS_XL_DMA_WIN1_BASE; - else - return paddr + APECS_XL_DMA_WIN2_BASE; /* win 2 xlates to 0 also */ -#else /* CONFIG_ALPHA_XL */ - return paddr + APECS_DMA_WIN_BASE; -#endif /* CONFIG_ALPHA_XL */ -} - -extern inline void * bus_to_virt(unsigned long address) -{ - /* - * This check is a sanity check but also ensures that bus - * address 0 maps to virtual address 0 which is useful to - * detect null "pointers" (the NCR driver is much simpler if - * NULL pointers are preserved). - */ -#ifdef CONFIG_ALPHA_XL - if (address < APECS_XL_DMA_WIN1_BASE) - return 0; - else if (address < (APECS_XL_DMA_WIN1_BASE + APECS_XL_DMA_WIN1_SIZE)) - return phys_to_virt(address - APECS_XL_DMA_WIN1_BASE); - else /* should be more checking here, maybe? */ - return phys_to_virt(address - APECS_XL_DMA_WIN2_BASE); -#else /* CONFIG_ALPHA_XL */ - if (address < APECS_DMA_WIN_BASE) - return 0; - return phys_to_virt(address - APECS_DMA_WIN_BASE); -#endif /* CONFIG_ALPHA_XL */ -} - -/* - * I/O functions: - * - * Unlike Jensen, the APECS machines have no concept of local - * I/O---everything goes over the PCI bus. - * - * There is plenty room for optimization here. In particular, - * the Alpha's insb/insw/extb/extw should be useful in moving - * data to/from the right byte-lanes. - */ - -#define vuip volatile unsigned int * -#define vulp volatile unsigned long * - -extern inline unsigned int __inb(unsigned long addr) -{ - long result = *(vuip) ((addr << 5) + APECS_IO + 0x00); - result >>= (addr & 3) * 8; - return 0xffUL & result; -} - -extern inline void __outb(unsigned char b, unsigned long addr) -{ - unsigned int w; - - w = __kernel_insbl(b, addr & 3); - *(vuip) ((addr << 5) + APECS_IO + 0x00) = w; - mb(); -} - -extern inline unsigned int __inw(unsigned long addr) -{ - long result = *(vuip) ((addr << 5) + APECS_IO + 0x08); - result >>= (addr & 3) * 8; - return 0xffffUL & result; -} - -extern inline void __outw(unsigned short b, unsigned long addr) -{ - unsigned int w; - - w = __kernel_inswl(b, addr & 3); - *(vuip) ((addr << 5) + APECS_IO + 0x08) = w; - mb(); -} - -extern inline unsigned int __inl(unsigned long addr) -{ - return *(vuip) ((addr << 5) + APECS_IO + 0x18); -} - -extern inline void __outl(unsigned int b, unsigned long addr) -{ - *(vuip) ((addr << 5) + APECS_IO + 0x18) = b; - mb(); -} - - -/* - * Memory functions. 64-bit and 32-bit accesses are done through - * dense memory space, everything else through sparse space. - */ -extern inline unsigned long __readb(unsigned long addr) -{ - unsigned long result, shift, msb; - - shift = (addr & 0x3) * 8; - if (addr >= (1UL << 24)) { - msb = addr & 0xf8000000; - addr -= msb; - if (msb != hae.cache) { - set_hae(msb); - } - } - result = *(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x00); - result >>= shift; - return 0xffUL & result; -} - -extern inline unsigned long __readw(unsigned long addr) -{ - unsigned long result, shift, msb; - - shift = (addr & 0x3) * 8; - if (addr >= (1UL << 24)) { - msb = addr & 0xf8000000; - addr -= msb; - if (msb != hae.cache) { - set_hae(msb); - } - } - result = *(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x08); - result >>= shift; - return 0xffffUL & result; -} - -extern inline unsigned long __readl(unsigned long addr) -{ - return *(vuip) (addr + APECS_DENSE_MEM); -} - -extern inline unsigned long __readq(unsigned long addr) -{ - return *(vulp) (addr + APECS_DENSE_MEM); -} - -extern inline void __writeb(unsigned char b, unsigned long addr) -{ - unsigned long msb; - - if (addr >= (1UL << 24)) { - msb = addr & 0xf8000000; - addr -= msb; - if (msb != hae.cache) { - set_hae(msb); - } - } - *(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x00) = b * 0x01010101; -} - -extern inline void __writew(unsigned short b, unsigned long addr) -{ - unsigned long msb; - - if (addr >= (1UL << 24)) { - msb = addr & 0xf8000000; - addr -= msb; - if (msb != hae.cache) { - set_hae(msb); - } - } - *(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x08) = b * 0x00010001; -} - -extern inline void __writel(unsigned int b, unsigned long addr) -{ - *(vuip) (addr + APECS_DENSE_MEM) = b; -} - -extern inline void __writeq(unsigned long b, unsigned long addr) -{ - *(vulp) (addr + APECS_DENSE_MEM) = b; -} - -#define inb(port) \ -(__builtin_constant_p((port))?__inb(port):_inb(port)) - -#define outb(x, port) \ -(__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port))) - -#define readl(a) __readl((unsigned long)(a)) -#define readq(a) __readq((unsigned long)(a)) -#define writel(v,a) __writel((v),(unsigned long)(a)) -#define writeq(v,a) __writeq((v),(unsigned long)(a)) - -#undef vuip -#undef vulp - -extern unsigned long apecs_init (unsigned long mem_start, - unsigned long mem_end); - -#endif /* __KERNEL__ */ - -/* - * Data structure for handling APECS machine checks: - */ -#ifdef CONFIG_ALPHA_MIKASA -struct el_apecs_sysdata_mcheck { - unsigned long coma_gcr; - unsigned long coma_edsr; - unsigned long coma_ter; - unsigned long coma_elar; - unsigned long coma_ehar; - unsigned long coma_ldlr; - unsigned long coma_ldhr; - unsigned long coma_base0; - unsigned long coma_base1; - unsigned long coma_base2; - unsigned long coma_base3; - unsigned long coma_cnfg0; - unsigned long coma_cnfg1; - unsigned long coma_cnfg2; - unsigned long coma_cnfg3; - unsigned long epic_dcsr; - unsigned long epic_pear; - unsigned long epic_sear; - unsigned long epic_tbr1; - unsigned long epic_tbr2; - unsigned long epic_pbr1; - unsigned long epic_pbr2; - unsigned long epic_pmr1; - unsigned long epic_pmr2; - unsigned long epic_harx1; - unsigned long epic_harx2; - unsigned long epic_pmlt; - unsigned long epic_tag0; - unsigned long epic_tag1; - unsigned long epic_tag2; - unsigned long epic_tag3; - unsigned long epic_tag4; - unsigned long epic_tag5; - unsigned long epic_tag6; - unsigned long epic_tag7; - unsigned long epic_data0; - unsigned long epic_data1; - unsigned long epic_data2; - unsigned long epic_data3; - unsigned long epic_data4; - unsigned long epic_data5; - unsigned long epic_data6; - unsigned long epic_data7; - - unsigned long pceb_vid; - unsigned long pceb_did; - unsigned long pceb_revision; - unsigned long pceb_command; - unsigned long pceb_status; - unsigned long pceb_latency; - unsigned long pceb_control; - unsigned long pceb_arbcon; - unsigned long pceb_arbpri; - - unsigned long esc_id; - unsigned long esc_revision; - unsigned long esc_int0; - unsigned long esc_int1; - unsigned long esc_elcr0; - unsigned long esc_elcr1; - unsigned long esc_last_eisa; - unsigned long esc_nmi_stat; - - unsigned long pci_ir; - unsigned long pci_imr; - unsigned long svr_mgr; -}; -#else /* CONFIG_ALPHA_MIKASA */ -/* this for the normal APECS machines */ -struct el_apecs_sysdata_mcheck { - unsigned long coma_gcr; - unsigned long coma_edsr; - unsigned long coma_ter; - unsigned long coma_elar; - unsigned long coma_ehar; - unsigned long coma_ldlr; - unsigned long coma_ldhr; - unsigned long coma_base0; - unsigned long coma_base1; - unsigned long coma_base2; - unsigned long coma_cnfg0; - unsigned long coma_cnfg1; - unsigned long coma_cnfg2; - unsigned long epic_dcsr; - unsigned long epic_pear; - unsigned long epic_sear; - unsigned long epic_tbr1; - unsigned long epic_tbr2; - unsigned long epic_pbr1; - unsigned long epic_pbr2; - unsigned long epic_pmr1; - unsigned long epic_pmr2; - unsigned long epic_harx1; - unsigned long epic_harx2; - unsigned long epic_pmlt; - unsigned long epic_tag0; - unsigned long epic_tag1; - unsigned long epic_tag2; - unsigned long epic_tag3; - unsigned long epic_tag4; - unsigned long epic_tag5; - unsigned long epic_tag6; - unsigned long epic_tag7; - unsigned long epic_data0; - unsigned long epic_data1; - unsigned long epic_data2; - unsigned long epic_data3; - unsigned long epic_data4; - unsigned long epic_data5; - unsigned long epic_data6; - unsigned long epic_data7; -}; -#endif /* CONFIG_ALPHA_MIKASA */ - -struct el_procdata { - unsigned long paltemp[32]; /* PAL TEMP REGS. */ - /* EV4-specific fields */ - unsigned long exc_addr; /* Address of excepting instruction. */ - unsigned long exc_sum; /* Summary of arithmetic traps. */ - unsigned long exc_mask; /* Exception mask (from exc_sum). */ - unsigned long iccsr; /* IBox hardware enables. */ - unsigned long pal_base; /* Base address for PALcode. */ - unsigned long hier; /* Hardware Interrupt Enable. */ - unsigned long hirr; /* Hardware Interrupt Request. */ - unsigned long csr; /* D-stream fault info. */ - unsigned long dc_stat; /* D-cache status (ECC/Parity Err). */ - unsigned long dc_addr; /* EV3 Phys Addr for ECC/DPERR. */ - unsigned long abox_ctl; /* ABox Control Register. */ - unsigned long biu_stat; /* BIU Status. */ - unsigned long biu_addr; /* BUI Address. */ - unsigned long biu_ctl; /* BIU Control. */ - unsigned long fill_syndrome;/* For correcting ECC errors. */ - unsigned long fill_addr; /* Cache block which was being read */ - unsigned long va; /* Effective VA of fault or miss. */ - unsigned long bc_tag; /* Backup Cache Tag Probe Results.*/ -}; - - -#define RTC_PORT(x) (0x70 + (x)) -#define RTC_ADDR(x) (0x80 | (x)) -#define RTC_ALWAYS_BCD 0 - -#endif /* __ALPHA_APECS__H__ */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/bitops.h linux/include/asm-alpha/bitops.h --- v2.1.115/linux/include/asm-alpha/bitops.h Tue Jul 21 00:15:32 1998 +++ linux/include/asm-alpha/bitops.h Sun Aug 9 12:09:06 1998 @@ -46,10 +46,10 @@ __asm__ __volatile__( "1: ldl_l %0,%1\n" - " and %0,%3,%2\n\t" - " beq %2,2f\n\t" - " xor %0,%3,%0\n\t" - " stl_c %0,%1\n\t" + " and %0,%3,%2\n" + " beq %2,2f\n" + " xor %0,%3,%0\n" + " stl_c %0,%1\n" " beq %0,3f\n" "2:\n" ".section .text2,\"ax\"\n" @@ -66,8 +66,8 @@ __asm__ __volatile__( "1: ldl_l %0,%1\n" - " xor %0,%2,%0\n\t" - " stl_c %0,%1\n\t" + " xor %0,%2,%0\n" + " stl_c %0,%1\n" " beq %0,3f\n" ".section .text2,\"ax\"\n" "3: br 1b\n" @@ -109,10 +109,10 @@ __asm__ __volatile__( "1: ldl_l %0,%1\n" - " and %0,%3,%2\n\t" - " beq %2,2f\n\t" - " xor %0,%3,%0\n\t" - " stl_c %0,%1\n\t" + " and %0,%3,%2\n" + " beq %2,2f\n" + " xor %0,%3,%0\n" + " stl_c %0,%1\n" " beq %0,3f\n" "2:\n" ".section .text2,\"ax\"\n" @@ -133,9 +133,9 @@ __asm__ __volatile__( "1: ldl_l %0,%1\n" - " and %0,%3,%2\n\t" - " xor %0,%3,%0\n\t" - " stl_c %0,%1\n\t" + " and %0,%3,%2\n" + " xor %0,%3,%0\n" + " stl_c %0,%1\n" " beq %0,3f\n" ".section .text2,\"ax\"\n" "3: br 1b\n" @@ -172,6 +172,11 @@ extern inline unsigned long ffz(unsigned long word) { +#ifdef __alpha_cix__ + /* Whee. EV6 can calculate it directly. */ + unsigned long result; + __asm__("ctlz %1,%0" : "=r"(result) : "r"(~word)); +#else unsigned long bits, qofs, bofs; __asm__("cmpbge %1,%2,%0" : "=r"(bits) : "r"(word), "r"(~0UL)); @@ -180,6 +185,7 @@ bofs = ffz_b(bits); return qofs*8 + bofs; +#endif } #ifdef __KERNEL__ @@ -190,16 +196,34 @@ * differs in spirit from the above ffz (man ffs). */ -#define ffs(x) generic_ffs(x) +extern inline int ffs(int word) +{ + int result = ffz(~word); + return word ? result+1 : 0; +} /* * hweightN: returns the hamming weight (i.e. the number * of bits set) of a N-bit word */ +#ifdef __alpha_cix__ +/* Whee. EV6 can calculate it directly. */ +extern __inline__ unsigned long hweight64(unsigned long w) +{ + unsigned long result; + __asm__("ctpop %1,%0" : "=r"(result) : "r"(w)); + return result; +} + +#define hweight32(x) hweight64((x) & 0xfffffffful) +#define hweight16(x) hweight64((x) & 0xfffful) +#define hweight8(x) hweight64((x) & 0xfful) +#else #define hweight32(x) generic_hweight32(x) #define hweight16(x) generic_hweight16(x) -#define hweight8(x) generic_hweight8(x) +#define hweight8(x) generic_hweight8(x) +#endif #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/cia.h linux/include/asm-alpha/cia.h --- v2.1.115/linux/include/asm-alpha/cia.h Tue Jul 21 00:15:32 1998 +++ linux/include/asm-alpha/cia.h Wed Dec 31 16:00:00 1969 @@ -1,606 +0,0 @@ -#ifndef __ALPHA_CIA__H__ -#define __ALPHA_CIA__H__ - -#include -#include - -/* - * CIA is the internal name for the 2117x chipset which provides - * memory controller and PCI access for the 21164 chip based systems. - * - * This file is based on: - * - * DECchip 21171 Core Logic Chipset - * Technical Reference Manual - * - * EC-QE18B-TE - * - * david.rusling@reo.mts.dec.com Initial Version. - * - */ - -/*------------------------------------------------------------------------** -** ** -** EB164 I/O procedures ** -** ** -** inport[b|w|t|l], outport[b|w|t|l] 8:16:24:32 IO xfers ** -** inportbxt: 8 bits only ** -** inport: alias of inportw ** -** outport: alias of outportw ** -** ** -** inmem[b|w|t|l], outmem[b|w|t|l] 8:16:24:32 ISA memory xfers ** -** inmembxt: 8 bits only ** -** inmem: alias of inmemw ** -** outmem: alias of outmemw ** -** ** -**------------------------------------------------------------------------*/ - - -/* CIA ADDRESS BIT DEFINITIONS - * - * 3 3 3 3|3 3 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 - * 9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * |1| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |0|0|0| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | \_/ \_/ - * | | | - * +-- IO space, not cached. Byte Enable --+ | - * Transfer Length --+ - * - * - * - * Byte Transfer - * Enable Length Transfer Byte Address - * adr<6:5> adr<4:3> Length Enable Adder - * --------------------------------------------- - * 00 00 Byte 1110 0x000 - * 01 00 Byte 1101 0x020 - * 10 00 Byte 1011 0x040 - * 11 00 Byte 0111 0x060 - * - * 00 01 Word 1100 0x008 - * 01 01 Word 1001 0x028 <= Not supported in this code. - * 10 01 Word 0011 0x048 - * - * 00 10 Tribyte 1000 0x010 - * 01 10 Tribyte 0001 0x030 - * - * 10 11 Longword 0000 0x058 - * - * Note that byte enables are asserted low. - * - */ - -#define BYTE_ENABLE_SHIFT 5 -#define TRANSFER_LENGTH_SHIFT 3 - -#define MEM_R1_MASK 0x1fffffff /* SPARSE Mem region 1 mask is 29 bits */ -#define MEM_R2_MASK 0x07ffffff /* SPARSE Mem region 2 mask is 27 bits */ -#define MEM_R3_MASK 0x03ffffff /* SPARSE Mem region 3 mask is 26 bits */ - -#ifdef CONFIG_ALPHA_SRM_SETUP -/* if we are using the SRM PCI setup, we'll need to use variables instead */ -#define CIA_DMA_WIN_BASE_DEFAULT (1024*1024*1024) -#define CIA_DMA_WIN_SIZE_DEFAULT (1024*1024*1024) - -extern unsigned int CIA_DMA_WIN_BASE; -extern unsigned int CIA_DMA_WIN_SIZE; - -#else /* SRM_SETUP */ -#define CIA_DMA_WIN_BASE (1024*1024*1024) -#define CIA_DMA_WIN_SIZE (1024*1024*1024) -#endif /* SRM_SETUP */ - -/* - * 21171-CA Control and Status Registers (p4-1) - */ -#define CIA_IOC_CIA_REV (IDENT_ADDR + 0x8740000080UL) -#define CIA_IOC_PCI_LAT (IDENT_ADDR + 0x87400000C0UL) -#define CIA_IOC_CIA_CTRL (IDENT_ADDR + 0x8740000100UL) -#define CIA_IOC_CIA_CNFG (IDENT_ADDR + 0x8740000140UL) -#define CIA_IOC_HAE_MEM (IDENT_ADDR + 0x8740000400UL) -#define CIA_IOC_HAE_IO (IDENT_ADDR + 0x8740000440UL) -#define CIA_IOC_CFG (IDENT_ADDR + 0x8740000480UL) -#define CIA_IOC_CACK_EN (IDENT_ADDR + 0x8740000600UL) - -/* - * 21171-CA Diagnostic Registers (p4-2) - */ -#define CIA_IOC_CIA_DIAG (IDENT_ADDR + 0x8740002000UL) -#define CIA_IOC_DIAG_CHECK (IDENT_ADDR + 0x8740003000UL) - -/* - * 21171-CA Performance Monitor registers (p4-3) - */ -#define CIA_IOC_PERF_MONITOR (IDENT_ADDR + 0x8740004000UL) -#define CIA_IOC_PERF_CONTROL (IDENT_ADDR + 0x8740004040UL) - -/* - * 21171-CA Error registers (p4-3) - */ -#define CIA_IOC_CPU_ERR0 (IDENT_ADDR + 0x8740008000UL) -#define CIA_IOC_CPU_ERR1 (IDENT_ADDR + 0x8740008040UL) -#define CIA_IOC_CIA_ERR (IDENT_ADDR + 0x8740008200UL) -#define CIA_IOC_CIA_STAT (IDENT_ADDR + 0x8740008240UL) -#define CIA_IOC_ERR_MASK (IDENT_ADDR + 0x8740008280UL) -#define CIA_IOC_CIA_SYN (IDENT_ADDR + 0x8740008300UL) -#define CIA_IOC_MEM_ERR0 (IDENT_ADDR + 0x8740008400UL) -#define CIA_IOC_MEM_ERR1 (IDENT_ADDR + 0x8740008440UL) -#define CIA_IOC_PCI_ERR0 (IDENT_ADDR + 0x8740008800UL) -#define CIA_IOC_PCI_ERR1 (IDENT_ADDR + 0x8740008840UL) -#define CIA_IOC_PCI_ERR3 (IDENT_ADDR + 0x8740008880UL) - -/* - * 2117A-CA PCI Address Translation Registers. - */ -#define CIA_IOC_PCI_TBIA (IDENT_ADDR + 0x8760000100UL) - -#define CIA_IOC_PCI_W0_BASE (IDENT_ADDR + 0x8760000400UL) -#define CIA_IOC_PCI_W0_MASK (IDENT_ADDR + 0x8760000440UL) -#define CIA_IOC_PCI_T0_BASE (IDENT_ADDR + 0x8760000480UL) - -#define CIA_IOC_PCI_W1_BASE (IDENT_ADDR + 0x8760000500UL) -#define CIA_IOC_PCI_W1_MASK (IDENT_ADDR + 0x8760000540UL) -#define CIA_IOC_PCI_T1_BASE (IDENT_ADDR + 0x8760000580UL) - -#define CIA_IOC_PCI_W2_BASE (IDENT_ADDR + 0x8760000600UL) -#define CIA_IOC_PCI_W2_MASK (IDENT_ADDR + 0x8760000640UL) -#define CIA_IOC_PCI_T2_BASE (IDENT_ADDR + 0x8760000680UL) - -#define CIA_IOC_PCI_W3_BASE (IDENT_ADDR + 0x8760000700UL) -#define CIA_IOC_PCI_W3_MASK (IDENT_ADDR + 0x8760000740UL) -#define CIA_IOC_PCI_T3_BASE (IDENT_ADDR + 0x8760000780UL) - -/* - * 21171-CA System configuration registers (p4-3) - */ -#define CIA_IOC_MCR (IDENT_ADDR + 0x8750000000UL) -#define CIA_IOC_MBA0 (IDENT_ADDR + 0x8750000600UL) -#define CIA_IOC_MBA2 (IDENT_ADDR + 0x8750000680UL) -#define CIA_IOC_MBA4 (IDENT_ADDR + 0x8750000700UL) -#define CIA_IOC_MBA6 (IDENT_ADDR + 0x8750000780UL) -#define CIA_IOC_MBA8 (IDENT_ADDR + 0x8750000800UL) -#define CIA_IOC_MBAA (IDENT_ADDR + 0x8750000880UL) -#define CIA_IOC_MBAC (IDENT_ADDR + 0x8750000900UL) -#define CIA_IOC_MBAE (IDENT_ADDR + 0x8750000980UL) -#define CIA_IOC_TMG0 (IDENT_ADDR + 0x8750000B00UL) -#define CIA_IOC_TMG1 (IDENT_ADDR + 0x8750000B40UL) -#define CIA_IOC_TMG2 (IDENT_ADDR + 0x8750000B80UL) - -/* - * Memory spaces: - */ -#define CIA_IACK_SC (IDENT_ADDR + 0x8720000000UL) -#define CIA_CONF (IDENT_ADDR + 0x8700000000UL) -#define CIA_IO (IDENT_ADDR + 0x8580000000UL) -#define CIA_SPARSE_MEM (IDENT_ADDR + 0x8000000000UL) -#define CIA_SPARSE_MEM_R2 (IDENT_ADDR + 0x8400000000UL) -#define CIA_SPARSE_MEM_R3 (IDENT_ADDR + 0x8500000000UL) -#define CIA_DENSE_MEM (IDENT_ADDR + 0x8600000000UL) -#define DENSE_MEM(addr) CIA_DENSE_MEM - -/* - * ALCOR's GRU ASIC registers - */ -#define GRU_INT_REQ (IDENT_ADDR + 0x8780000000UL) -#define GRU_INT_MASK (IDENT_ADDR + 0x8780000040UL) -#define GRU_INT_EDGE (IDENT_ADDR + 0x8780000080UL) -#define GRU_INT_HILO (IDENT_ADDR + 0x87800000C0UL) -#define GRU_INT_CLEAR (IDENT_ADDR + 0x8780000100UL) - -#define GRU_CACHE_CNFG (IDENT_ADDR + 0x8780000200UL) -#define GRU_SCR (IDENT_ADDR + 0x8780000300UL) -#define GRU_LED (IDENT_ADDR + 0x8780000800UL) -#define GRU_RESET (IDENT_ADDR + 0x8780000900UL) - -#if defined(CONFIG_ALPHA_ALCOR) -#define GRU_INT_REQ_BITS 0x800fffffUL -#elif defined(CONFIG_ALPHA_XLT) -#define GRU_INT_REQ_BITS 0x80003fffUL -#else -#define GRU_INT_REQ_BITS 0xffffffffUL -#endif - -/* - * Bit definitions for I/O Controller status register 0: - */ -#define CIA_IOC_STAT0_CMD 0xf -#define CIA_IOC_STAT0_ERR (1<<4) -#define CIA_IOC_STAT0_LOST (1<<5) -#define CIA_IOC_STAT0_THIT (1<<6) -#define CIA_IOC_STAT0_TREF (1<<7) -#define CIA_IOC_STAT0_CODE_SHIFT 8 -#define CIA_IOC_STAT0_CODE_MASK 0x7 -#define CIA_IOC_STAT0_P_NBR_SHIFT 13 -#define CIA_IOC_STAT0_P_NBR_MASK 0x7ffff - -#define HAE_ADDRESS CIA_IOC_HAE_MEM - -#ifdef __KERNEL__ - -/* - * Translate physical memory address as seen on (PCI) bus into - * a kernel virtual address and vv. - */ -extern inline unsigned long virt_to_bus(void * address) -{ - return virt_to_phys(address) + CIA_DMA_WIN_BASE; -} - -extern inline void * bus_to_virt(unsigned long address) -{ - return phys_to_virt(address - CIA_DMA_WIN_BASE); -} - -/* - * I/O functions: - * - * CIA (the 2117x PCI/memory support chipset for the EV5 (21164) - * series of processors uses a sparse address mapping scheme to - * get at PCI memory and I/O. - */ - -#define vuip volatile unsigned int * -#define vulp volatile unsigned long * - -extern inline unsigned int __inb(unsigned long addr) -{ - long result = *(vuip) ((addr << 5) + CIA_IO + 0x00); - result >>= (addr & 3) * 8; - return 0xffUL & result; -} - -extern inline void __outb(unsigned char b, unsigned long addr) -{ - unsigned int w; - - w = __kernel_insbl(b, addr & 3); - *(vuip) ((addr << 5) + CIA_IO + 0x00) = w; - mb(); -} - -extern inline unsigned int __inw(unsigned long addr) -{ - long result = *(vuip) ((addr << 5) + CIA_IO + 0x08); - result >>= (addr & 3) * 8; - return 0xffffUL & result; -} - -extern inline void __outw(unsigned short b, unsigned long addr) -{ - unsigned int w; - - w = __kernel_inswl(b, addr & 3); - *(vuip) ((addr << 5) + CIA_IO + 0x08) = w; - mb(); -} - -extern inline unsigned int __inl(unsigned long addr) -{ - return *(vuip) ((addr << 5) + CIA_IO + 0x18); -} - -extern inline void __outl(unsigned int b, unsigned long addr) -{ - *(vuip) ((addr << 5) + CIA_IO + 0x18) = b; - mb(); -} - - -/* - * Memory functions. 64-bit and 32-bit accesses are done through - * dense memory space, everything else through sparse space. - * - * For reading and writing 8 and 16 bit quantities we need to - * go through one of the three sparse address mapping regions - * and use the HAE_MEM CSR to provide some bits of the address. - * The following few routines use only sparse address region 1 - * which gives 1Gbyte of accessible space which relates exactly - * to the amount of PCI memory mapping *into* system address space. - * See p 6-17 of the specification but it looks something like this: - * - * 21164 Address: - * - * 3 2 1 - * 9876543210987654321098765432109876543210 - * 1ZZZZ0.PCI.QW.Address............BBLL - * - * ZZ = SBZ - * BB = Byte offset - * LL = Transfer length - * - * PCI Address: - * - * 3 2 1 - * 10987654321098765432109876543210 - * HHH....PCI.QW.Address........ 00 - * - * HHH = 31:29 HAE_MEM CSR - * - */ - -#ifdef CONFIG_ALPHA_SRM_SETUP - -extern unsigned long cia_sm_base_r1, cia_sm_base_r2, cia_sm_base_r3; - -extern inline unsigned long __readb(unsigned long addr) -{ - unsigned long result, shift, work; - - if ((addr >= cia_sm_base_r1) && - (addr <= (cia_sm_base_r1 + MEM_R1_MASK))) - work = (((addr & MEM_R1_MASK) << 5) + CIA_SPARSE_MEM + 0x00); - else - if ((addr >= cia_sm_base_r2) && - (addr <= (cia_sm_base_r2 + MEM_R2_MASK))) - work = (((addr & MEM_R2_MASK) << 5) + CIA_SPARSE_MEM_R2 + 0x00); - else - if ((addr >= cia_sm_base_r3) && - (addr <= (cia_sm_base_r3 + MEM_R3_MASK))) - work = (((addr & MEM_R3_MASK) << 5) + CIA_SPARSE_MEM_R3 + 0x00); - else - { -#if 0 - printk("__readb: address 0x%lx not covered by HAE\n", addr); -#endif - return 0x0ffUL; - } - shift = (addr & 0x3) << 3; - result = *(vuip) work; - result >>= shift; - return 0x0ffUL & result; -} - -extern inline unsigned long __readw(unsigned long addr) -{ - unsigned long result, shift, work; - - if ((addr >= cia_sm_base_r1) && - (addr <= (cia_sm_base_r1 + MEM_R1_MASK))) - work = (((addr & MEM_R1_MASK) << 5) + CIA_SPARSE_MEM + 0x08); - else - if ((addr >= cia_sm_base_r2) && - (addr <= (cia_sm_base_r2 + MEM_R2_MASK))) - work = (((addr & MEM_R2_MASK) << 5) + CIA_SPARSE_MEM_R2 + 0x08); - else - if ((addr >= cia_sm_base_r3) && - (addr <= (cia_sm_base_r3 + MEM_R3_MASK))) - work = (((addr & MEM_R3_MASK) << 5) + CIA_SPARSE_MEM_R3 + 0x08); - else - { -#if 0 - printk("__readw: address 0x%lx not covered by HAE\n", addr); -#endif - return 0x0ffffUL; - } - shift = (addr & 0x3) << 3; - result = *(vuip) work; - result >>= shift; - return 0x0ffffUL & result; -} - -extern inline void __writeb(unsigned char b, unsigned long addr) -{ - unsigned long work; - - if ((addr >= cia_sm_base_r1) && - (addr <= (cia_sm_base_r1 + MEM_R1_MASK))) - work = (((addr & MEM_R1_MASK) << 5) + CIA_SPARSE_MEM + 0x00); - else - if ((addr >= cia_sm_base_r2) && - (addr <= (cia_sm_base_r2 + MEM_R2_MASK))) - work = (((addr & MEM_R2_MASK) << 5) + CIA_SPARSE_MEM_R2 + 0x00); - else - if ((addr >= cia_sm_base_r3) && - (addr <= (cia_sm_base_r3 + MEM_R3_MASK))) - work = (((addr & MEM_R3_MASK) << 5) + CIA_SPARSE_MEM_R3 + 0x00); - else - { -#if 0 - printk("__writeb: address 0x%lx not covered by HAE\n", addr); -#endif - return; - } - *(vuip) work = b * 0x01010101; -} - -extern inline void __writew(unsigned short b, unsigned long addr) -{ - unsigned long work; - - if ((addr >= cia_sm_base_r1) && - (addr <= (cia_sm_base_r1 + MEM_R1_MASK))) - work = (((addr & MEM_R1_MASK) << 5) + CIA_SPARSE_MEM + 0x00); - else - if ((addr >= cia_sm_base_r2) && - (addr <= (cia_sm_base_r2 + MEM_R2_MASK))) - work = (((addr & MEM_R2_MASK) << 5) + CIA_SPARSE_MEM_R2 + 0x00); - else - if ((addr >= cia_sm_base_r3) && - (addr <= (cia_sm_base_r3 + MEM_R3_MASK))) - work = (((addr & MEM_R3_MASK) << 5) + CIA_SPARSE_MEM_R3 + 0x00); - else - { -#if 0 - printk("__writew: address 0x%lx not covered by HAE\n", addr); -#endif - return; - } - *(vuip) work = b * 0x00010001; -} - -#else /* SRM_SETUP */ - -extern inline unsigned long __readb(unsigned long addr) -{ - unsigned long result, shift, msb; - - shift = (addr & 0x3) * 8 ; - msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } - result = *(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x00) ; - result >>= shift; - return 0xffUL & result; -} - -extern inline unsigned long __readw(unsigned long addr) -{ - unsigned long result, shift, msb; - - shift = (addr & 0x3) * 8; - msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } - result = *(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x08); - result >>= shift; - return 0xffffUL & result; -} - -extern inline void __writeb(unsigned char b, unsigned long addr) -{ - unsigned long msb ; - - msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } - *(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x00) = b * 0x01010101; -} - -extern inline void __writew(unsigned short b, unsigned long addr) -{ - unsigned long msb ; - - msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } - *(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x08) = b * 0x00010001; -} - -#endif /* SRM_SETUP */ - -extern inline unsigned long __readl(unsigned long addr) -{ - return *(vuip) (addr + CIA_DENSE_MEM); -} - -extern inline unsigned long __readq(unsigned long addr) -{ - return *(vulp) (addr + CIA_DENSE_MEM); -} - -extern inline void __writel(unsigned int b, unsigned long addr) -{ - *(vuip) (addr + CIA_DENSE_MEM) = b; -} - -extern inline void __writeq(unsigned long b, unsigned long addr) -{ - *(vulp) (addr + CIA_DENSE_MEM) = b; -} - -#define inb(port) \ -(__builtin_constant_p((port))?__inb(port):_inb(port)) - -#define outb(x, port) \ -(__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port))) - -#define readl(a) __readl((unsigned long)(a)) -#define readq(a) __readq((unsigned long)(a)) -#define writel(v,a) __writel((v),(unsigned long)(a)) -#define writeq(v,a) __writeq((v),(unsigned long)(a)) - -#undef vuip -#undef vulp - -extern unsigned long cia_init (unsigned long mem_start, - unsigned long mem_end); - -#endif /* __KERNEL__ */ - -/* - * Data structure for handling CIA machine checks: - */ -/* ev5-specific info: */ -struct el_procdata { - unsigned long shadow[8]; /* PALmode shadow registers */ - unsigned long paltemp[24]; /* PAL temporary registers */ - /* EV5-specific fields */ - unsigned long exc_addr; /* Address of excepting instruction. */ - unsigned long exc_sum; /* Summary of arithmetic traps. */ - unsigned long exc_mask; /* Exception mask (from exc_sum). */ - unsigned long exc_base; /* PALbase at time of exception. */ - unsigned long isr; /* Interrupt summary register. */ - unsigned long icsr; /* Ibox control register. */ - unsigned long ic_perr_stat; - unsigned long dc_perr_stat; - unsigned long va; /* Effective VA of fault or miss. */ - unsigned long mm_stat; - unsigned long sc_addr; - unsigned long sc_stat; - unsigned long bc_tag_addr; - unsigned long ei_addr; - unsigned long fill_syn; - unsigned long ei_stat; - unsigned long ld_lock; -}; - -/* system-specific info: */ -struct el_CIA_sysdata_mcheck { - unsigned long coma_gcr; - unsigned long coma_edsr; - unsigned long coma_ter; - unsigned long coma_elar; - unsigned long coma_ehar; - unsigned long coma_ldlr; - unsigned long coma_ldhr; - unsigned long coma_base0; - unsigned long coma_base1; - unsigned long coma_base2; - unsigned long coma_cnfg0; - unsigned long coma_cnfg1; - unsigned long coma_cnfg2; - unsigned long epic_dcsr; - unsigned long epic_pear; - unsigned long epic_sear; - unsigned long epic_tbr1; - unsigned long epic_tbr2; - unsigned long epic_pbr1; - unsigned long epic_pbr2; - unsigned long epic_pmr1; - unsigned long epic_pmr2; - unsigned long epic_harx1; - unsigned long epic_harx2; - unsigned long epic_pmlt; - unsigned long epic_tag0; - unsigned long epic_tag1; - unsigned long epic_tag2; - unsigned long epic_tag3; - unsigned long epic_tag4; - unsigned long epic_tag5; - unsigned long epic_tag6; - unsigned long epic_tag7; - unsigned long epic_data0; - unsigned long epic_data1; - unsigned long epic_data2; - unsigned long epic_data3; - unsigned long epic_data4; - unsigned long epic_data5; - unsigned long epic_data6; - unsigned long epic_data7; -}; - -#define RTC_PORT(x) (0x70 + (x)) -#define RTC_ADDR(x) (0x80 | (x)) -#define RTC_ALWAYS_BCD 0 - -#endif /* __ALPHA_CIA__H__ */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/compiler.h linux/include/asm-alpha/compiler.h --- v2.1.115/linux/include/asm-alpha/compiler.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-alpha/compiler.h Sun Aug 9 12:09:06 1998 @@ -0,0 +1,74 @@ +#ifndef __ALPHA_COMPILER_H +#define __ALPHA_COMPILER_H + +/* + * Herein are macros we use when describing various patterns we want to GCC. + * In all cases we can get better schedules out of the compiler if we hide + * as little as possible inside inline assembly. However, we want to be + * able to know what we'll get out before giving up inline assembly. Thus + * these tests and macros. + */ + +/* + * EGCS (of varying versions) does a good job of using insxl and extxl. + */ + +#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91 +#define __kernel_insbl(val, shift) \ + (((unsigned long)(val) & 0xfful) << ((shift) * 8)) +#define __kernel_inswl(val, shift) \ + (((unsigned long)(val) & 0xfffful) << ((shift) * 8)) +#else +#define __kernel_insbl(val, shift) \ + ({ unsigned long __kir; \ + __asm__("insbl %2,%1,%0" : "=r"(__kir) : "rI"(shift), "r"(val)); \ + __kir; }) +#define __kernel_inswl(val, shift) \ + ({ unsigned long __kir; \ + __asm__("inswl %2,%1,%0" : "=r"(__kir) : "rI"(shift), "r"(val)); \ + __kir; }) +#endif + +#if __GNUC__ > 2 || __GNUC_MINOR__ >= 92 +#define __kernel_extbl(val, shift) (((val) >> (((shift) & 7) * 8)) & 0xfful) +#define __kernel_extwl(val, shift) (((val) >> (((shift) & 7) * 8)) & 0xfffful) +#else +#define __kernel_extbl(val, shift) \ + ({ unsigned long __kir; \ + __asm__("extbl %2,%1,%0" : "=r"(__kir) : "rI"(shift), "r"(val)); \ + __kir; }) +#define __kernel_extwl(val, shift) \ + ({ unsigned long __kir; \ + __asm__("extwl %2,%1,%0" : "=r"(__kir) : "rI"(shift), "r"(val)); \ + __kir; }) +#endif + + +/* + * Beginning with EGCS 1.1, GCC defines __alpha_bwx__ when the BWX + * extension is enabled. Previous versions did not define anything + * we could test during compilation, so allow users to tell us when + * the compiler will DTRT. + */ + +#if defined(HAVE_BWX) || defined(__alpha_bwx__) +#define __kernel_ldbu(mem) (mem) +#define __kernel_ldwu(mem) (mem) +#define __kernel_stb(val,mem) ((mem) = (val)) +#define __kernel_stw(val,mem) ((mem) = (val)) +#else +#define __kernel_ldbu(mem) \ + ({ unsigned char __kir; \ + __asm__("ldbu %0,%1" : "=r"(__kir) : "m"(mem)); \ + __kir; }) +#define __kernel_ldwu(mem) \ + ({ unsigned short __kir; \ + __asm__("ldwu %0,%1" : "=r"(__kir) : "m"(mem)); \ + __kir; }) +#define __kernel_stb(val,mem) \ + __asm__("stb %1,%0" : "=m"(mem) : "r"(val)) +#define __kernel_stw(val,mem) \ + __asm__("stw %1,%0" : "=m"(mem) : "r"(val)) +#endif + +#endif /* __ALPHA_COMPILER_H */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/core_apecs.h linux/include/asm-alpha/core_apecs.h --- v2.1.115/linux/include/asm-alpha/core_apecs.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-alpha/core_apecs.h Sun Aug 9 12:09:06 1998 @@ -0,0 +1,627 @@ +#ifndef __ALPHA_APECS__H__ +#define __ALPHA_APECS__H__ + +#include +#include +#include + +/* + * APECS is the internal name for the 2107x chipset which provides + * memory controller and PCI access for the 21064 chip based systems. + * + * This file is based on: + * + * DECchip 21071-AA and DECchip 21072-AA Core Logic Chipsets + * Data Sheet + * + * EC-N0648-72 + * + * + * david.rusling@reo.mts.dec.com Initial Version. + * + */ + +/* + An AVANTI *might* be an XL, and an XL has only 27 bits of ISA address + that get passed through the PCI<->ISA bridge chip. So we've gotta use + both windows to max out the physical memory we can DMA to. Sigh... + + If we try a window at 0 for 1GB as a work-around, we run into conflicts + with ISA/PCI bus memory which can't be relocated, like VGA aperture and + BIOS ROMs. So we must put the windows high enough to avoid these areas. + + We put window 1 at BUS 64Mb for 64Mb, mapping physical 0 to 64Mb-1, + and window 2 at BUS 1Gb for 1Gb, mapping physical 0 to 1Gb-1. + Yes, this does map 0 to 64Mb-1 twice, but only window 1 will actually + be used for that range (via virt_to_bus()). + + Note that we actually fudge the window 1 maximum as 48Mb instead of 64Mb, + to keep virt_to_bus() from returning an address in the first window, for + a data area that goes beyond the 64Mb first DMA window. Sigh... + The fudge factor MUST match with MAX_DMA_ADDRESS, but + we can't just use that here, because of header file looping... :-( + + Window 1 will be used for all DMA from the ISA bus; yes, that does + limit what memory an ISA floppy or sound card or Ethernet can touch, but + it's also a known limitation on other platforms as well. We use the + same technique that is used on INTEL platforms with similar limitation: + set MAX_DMA_ADDRESS and clear some pages' DMAable flags during mem_init(). + We trust that any ISA bus device drivers will *always* ask for DMAable + memory explicitly via kmalloc()/get_free_pages() flags arguments. + + Note that most PCI bus devices' drivers do *not* explicitly ask for + DMAable memory; they count on being able to DMA to any memory they + get from kmalloc()/get_free_pages(). They will also use window 1 for + any physical memory accesses below 64Mb; the rest will be handled by + window 2, maxing out at 1Gb of memory. I trust this is enough... :-) + + We hope that the area before the first window is large enough so that + there will be no overlap at the top end (64Mb). We *must* locate the + PCI cards' memory just below window 1, so that there's still the + possibility of being able to access it via SPARSE space. This is + important for cards such as the Matrox Millennium, whose Xserver + wants to access memory-mapped registers in byte and short lengths. + + Note that the XL is treated differently from the AVANTI, even though + for most other things they are identical. It didn't seem reasonable to + make the AVANTI support pay for the limitations of the XL. It is true, + however, that an XL kernel will run on an AVANTI without problems. +*/ +#define APECS_XL_DMA_WIN1_BASE (64*1024*1024) +#define APECS_XL_DMA_WIN1_SIZE (64*1024*1024) +#define APECS_XL_DMA_WIN1_SIZE_PARANOID (48*1024*1024) +#define APECS_XL_DMA_WIN2_BASE (1024*1024*1024) +#define APECS_XL_DMA_WIN2_SIZE (1024*1024*1024) + + +/* These are for normal APECS family machines, AVANTI/MUSTANG/EB64/PC64. */ + +#define APECS_DMA_WIN_BASE_DEFAULT (1024*1024*1024) +#define APECS_DMA_WIN_SIZE_DEFAULT (1024*1024*1024) + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) +#define APECS_DMA_WIN_BASE alpha_mv.dma_win_base +#define APECS_DMA_WIN_SIZE alpha_mv.dma_win_size +#else +#define APECS_DMA_WIN_BASE APECS_DMA_WIN_BASE_DEFAULT +#define APECS_DMA_WIN_SIZE APECS_DMA_WIN_SIZE_DEFAULT +#endif + + +/* + * 21071-DA Control and Status registers. + * These are used for PCI memory access. + */ +#define APECS_IOC_DCSR (IDENT_ADDR + 0x1A0000000UL) +#define APECS_IOC_PEAR (IDENT_ADDR + 0x1A0000020UL) +#define APECS_IOC_SEAR (IDENT_ADDR + 0x1A0000040UL) +#define APECS_IOC_DR1 (IDENT_ADDR + 0x1A0000060UL) +#define APECS_IOC_DR2 (IDENT_ADDR + 0x1A0000080UL) +#define APECS_IOC_DR3 (IDENT_ADDR + 0x1A00000A0UL) + +#define APECS_IOC_TB1R (IDENT_ADDR + 0x1A00000C0UL) +#define APECS_IOC_TB2R (IDENT_ADDR + 0x1A00000E0UL) + +#define APECS_IOC_PB1R (IDENT_ADDR + 0x1A0000100UL) +#define APECS_IOC_PB2R (IDENT_ADDR + 0x1A0000120UL) + +#define APECS_IOC_PM1R (IDENT_ADDR + 0x1A0000140UL) +#define APECS_IOC_PM2R (IDENT_ADDR + 0x1A0000160UL) + +#define APECS_IOC_HAXR0 (IDENT_ADDR + 0x1A0000180UL) +#define APECS_IOC_HAXR1 (IDENT_ADDR + 0x1A00001A0UL) +#define APECS_IOC_HAXR2 (IDENT_ADDR + 0x1A00001C0UL) + +#define APECS_IOC_PMLT (IDENT_ADDR + 0x1A00001E0UL) + +#define APECS_IOC_TLBTAG0 (IDENT_ADDR + 0x1A0000200UL) +#define APECS_IOC_TLBTAG1 (IDENT_ADDR + 0x1A0000220UL) +#define APECS_IOC_TLBTAG2 (IDENT_ADDR + 0x1A0000240UL) +#define APECS_IOC_TLBTAG3 (IDENT_ADDR + 0x1A0000260UL) +#define APECS_IOC_TLBTAG4 (IDENT_ADDR + 0x1A0000280UL) +#define APECS_IOC_TLBTAG5 (IDENT_ADDR + 0x1A00002A0UL) +#define APECS_IOC_TLBTAG6 (IDENT_ADDR + 0x1A00002C0UL) +#define APECS_IOC_TLBTAG7 (IDENT_ADDR + 0x1A00002E0UL) + +#define APECS_IOC_TLBDATA0 (IDENT_ADDR + 0x1A0000300UL) +#define APECS_IOC_TLBDATA1 (IDENT_ADDR + 0x1A0000320UL) +#define APECS_IOC_TLBDATA2 (IDENT_ADDR + 0x1A0000340UL) +#define APECS_IOC_TLBDATA3 (IDENT_ADDR + 0x1A0000360UL) +#define APECS_IOC_TLBDATA4 (IDENT_ADDR + 0x1A0000380UL) +#define APECS_IOC_TLBDATA5 (IDENT_ADDR + 0x1A00003A0UL) +#define APECS_IOC_TLBDATA6 (IDENT_ADDR + 0x1A00003C0UL) +#define APECS_IOC_TLBDATA7 (IDENT_ADDR + 0x1A00003E0UL) + +#define APECS_IOC_TBIA (IDENT_ADDR + 0x1A0000400UL) + + +/* + * 21071-CA Control and Status registers. + * These are used to program memory timing, + * configure memory and initialise the B-Cache. + */ +#define APECS_MEM_GCR (IDENT_ADDR + 0x180000000UL) +#define APECS_MEM_EDSR (IDENT_ADDR + 0x180000040UL) +#define APECS_MEM_TAR (IDENT_ADDR + 0x180000060UL) +#define APECS_MEM_ELAR (IDENT_ADDR + 0x180000080UL) +#define APECS_MEM_EHAR (IDENT_ADDR + 0x1800000a0UL) +#define APECS_MEM_SFT_RST (IDENT_ADDR + 0x1800000c0UL) +#define APECS_MEM_LDxLAR (IDENT_ADDR + 0x1800000e0UL) +#define APECS_MEM_LDxHAR (IDENT_ADDR + 0x180000100UL) +#define APECS_MEM_GTR (IDENT_ADDR + 0x180000200UL) +#define APECS_MEM_RTR (IDENT_ADDR + 0x180000220UL) +#define APECS_MEM_VFPR (IDENT_ADDR + 0x180000240UL) +#define APECS_MEM_PDLDR (IDENT_ADDR + 0x180000260UL) +#define APECS_MEM_PDhDR (IDENT_ADDR + 0x180000280UL) + +/* Bank x Base Address Register */ +#define APECS_MEM_B0BAR (IDENT_ADDR + 0x180000800UL) +#define APECS_MEM_B1BAR (IDENT_ADDR + 0x180000820UL) +#define APECS_MEM_B2BAR (IDENT_ADDR + 0x180000840UL) +#define APECS_MEM_B3BAR (IDENT_ADDR + 0x180000860UL) +#define APECS_MEM_B4BAR (IDENT_ADDR + 0x180000880UL) +#define APECS_MEM_B5BAR (IDENT_ADDR + 0x1800008A0UL) +#define APECS_MEM_B6BAR (IDENT_ADDR + 0x1800008C0UL) +#define APECS_MEM_B7BAR (IDENT_ADDR + 0x1800008E0UL) +#define APECS_MEM_B8BAR (IDENT_ADDR + 0x180000900UL) + +/* Bank x Configuration Register */ +#define APECS_MEM_B0BCR (IDENT_ADDR + 0x180000A00UL) +#define APECS_MEM_B1BCR (IDENT_ADDR + 0x180000A20UL) +#define APECS_MEM_B2BCR (IDENT_ADDR + 0x180000A40UL) +#define APECS_MEM_B3BCR (IDENT_ADDR + 0x180000A60UL) +#define APECS_MEM_B4BCR (IDENT_ADDR + 0x180000A80UL) +#define APECS_MEM_B5BCR (IDENT_ADDR + 0x180000AA0UL) +#define APECS_MEM_B6BCR (IDENT_ADDR + 0x180000AC0UL) +#define APECS_MEM_B7BCR (IDENT_ADDR + 0x180000AE0UL) +#define APECS_MEM_B8BCR (IDENT_ADDR + 0x180000B00UL) + +/* Bank x Timing Register A */ +#define APECS_MEM_B0TRA (IDENT_ADDR + 0x180000C00UL) +#define APECS_MEM_B1TRA (IDENT_ADDR + 0x180000C20UL) +#define APECS_MEM_B2TRA (IDENT_ADDR + 0x180000C40UL) +#define APECS_MEM_B3TRA (IDENT_ADDR + 0x180000C60UL) +#define APECS_MEM_B4TRA (IDENT_ADDR + 0x180000C80UL) +#define APECS_MEM_B5TRA (IDENT_ADDR + 0x180000CA0UL) +#define APECS_MEM_B6TRA (IDENT_ADDR + 0x180000CC0UL) +#define APECS_MEM_B7TRA (IDENT_ADDR + 0x180000CE0UL) +#define APECS_MEM_B8TRA (IDENT_ADDR + 0x180000D00UL) + +/* Bank x Timing Register B */ +#define APECS_MEM_B0TRB (IDENT_ADDR + 0x180000E00UL) +#define APECS_MEM_B1TRB (IDENT_ADDR + 0x180000E20UL) +#define APECS_MEM_B2TRB (IDENT_ADDR + 0x180000E40UL) +#define APECS_MEM_B3TRB (IDENT_ADDR + 0x180000E60UL) +#define APECS_MEM_B4TRB (IDENT_ADDR + 0x180000E80UL) +#define APECS_MEM_B5TRB (IDENT_ADDR + 0x180000EA0UL) +#define APECS_MEM_B6TRB (IDENT_ADDR + 0x180000EC0UL) +#define APECS_MEM_B7TRB (IDENT_ADDR + 0x180000EE0UL) +#define APECS_MEM_B8TRB (IDENT_ADDR + 0x180000F00UL) + + +/* + * Memory spaces: + */ +#define APECS_IACK_SC (IDENT_ADDR + 0x1b0000000UL) +#define APECS_CONF (IDENT_ADDR + 0x1e0000000UL) +#define APECS_IO (IDENT_ADDR + 0x1c0000000UL) +#define APECS_SPARSE_MEM (IDENT_ADDR + 0x200000000UL) +#define APECS_DENSE_MEM (IDENT_ADDR + 0x300000000UL) + + +/* + * Bit definitions for I/O Controller status register 0: + */ +#define APECS_IOC_STAT0_CMD 0xf +#define APECS_IOC_STAT0_ERR (1<<4) +#define APECS_IOC_STAT0_LOST (1<<5) +#define APECS_IOC_STAT0_THIT (1<<6) +#define APECS_IOC_STAT0_TREF (1<<7) +#define APECS_IOC_STAT0_CODE_SHIFT 8 +#define APECS_IOC_STAT0_CODE_MASK 0x7 +#define APECS_IOC_STAT0_P_NBR_SHIFT 13 +#define APECS_IOC_STAT0_P_NBR_MASK 0x7ffff + +#define APECS_HAE_ADDRESS APECS_IOC_HAXR1 + + +/* + * Data structure for handling APECS machine checks: + */ + +struct el_apecs_mikasa_sysdata_mcheck +{ + unsigned long coma_gcr; + unsigned long coma_edsr; + unsigned long coma_ter; + unsigned long coma_elar; + unsigned long coma_ehar; + unsigned long coma_ldlr; + unsigned long coma_ldhr; + unsigned long coma_base0; + unsigned long coma_base1; + unsigned long coma_base2; + unsigned long coma_base3; + unsigned long coma_cnfg0; + unsigned long coma_cnfg1; + unsigned long coma_cnfg2; + unsigned long coma_cnfg3; + unsigned long epic_dcsr; + unsigned long epic_pear; + unsigned long epic_sear; + unsigned long epic_tbr1; + unsigned long epic_tbr2; + unsigned long epic_pbr1; + unsigned long epic_pbr2; + unsigned long epic_pmr1; + unsigned long epic_pmr2; + unsigned long epic_harx1; + unsigned long epic_harx2; + unsigned long epic_pmlt; + unsigned long epic_tag0; + unsigned long epic_tag1; + unsigned long epic_tag2; + unsigned long epic_tag3; + unsigned long epic_tag4; + unsigned long epic_tag5; + unsigned long epic_tag6; + unsigned long epic_tag7; + unsigned long epic_data0; + unsigned long epic_data1; + unsigned long epic_data2; + unsigned long epic_data3; + unsigned long epic_data4; + unsigned long epic_data5; + unsigned long epic_data6; + unsigned long epic_data7; + + unsigned long pceb_vid; + unsigned long pceb_did; + unsigned long pceb_revision; + unsigned long pceb_command; + unsigned long pceb_status; + unsigned long pceb_latency; + unsigned long pceb_control; + unsigned long pceb_arbcon; + unsigned long pceb_arbpri; + + unsigned long esc_id; + unsigned long esc_revision; + unsigned long esc_int0; + unsigned long esc_int1; + unsigned long esc_elcr0; + unsigned long esc_elcr1; + unsigned long esc_last_eisa; + unsigned long esc_nmi_stat; + + unsigned long pci_ir; + unsigned long pci_imr; + unsigned long svr_mgr; +}; + +/* This for the normal APECS machines. */ +struct el_apecs_sysdata_mcheck +{ + unsigned long coma_gcr; + unsigned long coma_edsr; + unsigned long coma_ter; + unsigned long coma_elar; + unsigned long coma_ehar; + unsigned long coma_ldlr; + unsigned long coma_ldhr; + unsigned long coma_base0; + unsigned long coma_base1; + unsigned long coma_base2; + unsigned long coma_cnfg0; + unsigned long coma_cnfg1; + unsigned long coma_cnfg2; + unsigned long epic_dcsr; + unsigned long epic_pear; + unsigned long epic_sear; + unsigned long epic_tbr1; + unsigned long epic_tbr2; + unsigned long epic_pbr1; + unsigned long epic_pbr2; + unsigned long epic_pmr1; + unsigned long epic_pmr2; + unsigned long epic_harx1; + unsigned long epic_harx2; + unsigned long epic_pmlt; + unsigned long epic_tag0; + unsigned long epic_tag1; + unsigned long epic_tag2; + unsigned long epic_tag3; + unsigned long epic_tag4; + unsigned long epic_tag5; + unsigned long epic_tag6; + unsigned long epic_tag7; + unsigned long epic_data0; + unsigned long epic_data1; + unsigned long epic_data2; + unsigned long epic_data3; + unsigned long epic_data4; + unsigned long epic_data5; + unsigned long epic_data6; + unsigned long epic_data7; +}; + +struct el_apecs_procdata +{ + unsigned long paltemp[32]; /* PAL TEMP REGS. */ + /* EV4-specific fields */ + unsigned long exc_addr; /* Address of excepting instruction. */ + unsigned long exc_sum; /* Summary of arithmetic traps. */ + unsigned long exc_mask; /* Exception mask (from exc_sum). */ + unsigned long iccsr; /* IBox hardware enables. */ + unsigned long pal_base; /* Base address for PALcode. */ + unsigned long hier; /* Hardware Interrupt Enable. */ + unsigned long hirr; /* Hardware Interrupt Request. */ + unsigned long csr; /* D-stream fault info. */ + unsigned long dc_stat; /* D-cache status (ECC/Parity Err). */ + unsigned long dc_addr; /* EV3 Phys Addr for ECC/DPERR. */ + unsigned long abox_ctl; /* ABox Control Register. */ + unsigned long biu_stat; /* BIU Status. */ + unsigned long biu_addr; /* BUI Address. */ + unsigned long biu_ctl; /* BIU Control. */ + unsigned long fill_syndrome;/* For correcting ECC errors. */ + unsigned long fill_addr; /* Cache block which was being read */ + unsigned long va; /* Effective VA of fault or miss. */ + unsigned long bc_tag; /* Backup Cache Tag Probe Results.*/ +}; + + +#ifdef __KERNEL__ + +#ifndef __EXTERN_INLINE +#define __EXTERN_INLINE extern inline +#define __IO_EXTERN_INLINE +#endif + +/* + * Translate physical memory address as seen on (PCI) bus into + * a kernel virtual address and vv. + */ + +/* + * NOTE: we fudge the window 1 maximum as 48Mb instead of 64Mb, to prevent + * virt_to_bus() from returning an address in the first window, for a + * data area that goes beyond the 64Mb first DMA window. Sigh... + * This MUST match with MAX_DMA_ADDRESS for consistency, but + * we can't just use that here, because of header file looping... :-( + */ + +__EXTERN_INLINE unsigned long apecs_virt_to_bus(void * address) +{ + unsigned long paddr = virt_to_phys(address); + return paddr + APECS_DMA_WIN_BASE; +} + +static inline unsigned long apecs_xl_virt_to_bus(void * address) +{ + unsigned long paddr = virt_to_phys(address); + if (paddr < APECS_XL_DMA_WIN1_SIZE_PARANOID) + return paddr + APECS_XL_DMA_WIN1_BASE; + else + return paddr + APECS_XL_DMA_WIN2_BASE; /* win 2 xlates to 0 also */ +} + +__EXTERN_INLINE void * apecs_bus_to_virt(unsigned long address) +{ + /* + * This check is a sanity check but also ensures that bus + * address 0 maps to virtual address 0 which is useful to + * detect null "pointers" (the NCR driver is much simpler if + * NULL pointers are preserved). + */ + if (address < APECS_DMA_WIN_BASE) + return 0; + return phys_to_virt(address - APECS_DMA_WIN_BASE); +} + +static inline void * apecs_xl_bus_to_virt(unsigned long address) +{ + /* + * This check is a sanity check but also ensures that bus + * address 0 maps to virtual address 0 which is useful to + * detect null "pointers" (the NCR driver is much simpler if + * NULL pointers are preserved). + */ + if (address < APECS_XL_DMA_WIN1_BASE) + return 0; + else if (address < (APECS_XL_DMA_WIN1_BASE + APECS_XL_DMA_WIN1_SIZE)) + address -= APECS_XL_DMA_WIN1_BASE; + else /* should be more checking here, maybe? */ + address -= APECS_XL_DMA_WIN2_BASE; + return phys_to_virt(address); +} + +/* + * I/O functions: + * + * Unlike Jensen, the APECS machines have no concept of local + * I/O---everything goes over the PCI bus. + * + * There is plenty room for optimization here. In particular, + * the Alpha's insb/insw/extb/extw should be useful in moving + * data to/from the right byte-lanes. + */ + +#define vip volatile int * +#define vuip volatile unsigned int * +#define vulp volatile unsigned long * + +__EXTERN_INLINE unsigned int apecs_inb(unsigned long addr) +{ + long result = *(vip) ((addr << 5) + APECS_IO + 0x00); + return __kernel_extbl(result, addr & 3); +} + +__EXTERN_INLINE void apecs_outb(unsigned char b, unsigned long addr) +{ + unsigned int w; + + w = __kernel_insbl(b, addr & 3); + *(vuip) ((addr << 5) + APECS_IO + 0x00) = w; + mb(); +} + +__EXTERN_INLINE unsigned int apecs_inw(unsigned long addr) +{ + long result = *(vip) ((addr << 5) + APECS_IO + 0x08); + return __kernel_extwl(result, addr & 3); +} + +__EXTERN_INLINE void apecs_outw(unsigned short b, unsigned long addr) +{ + unsigned int w; + + w = __kernel_inswl(b, addr & 3); + *(vuip) ((addr << 5) + APECS_IO + 0x08) = w; + mb(); +} + +__EXTERN_INLINE unsigned int apecs_inl(unsigned long addr) +{ + return *(vuip) ((addr << 5) + APECS_IO + 0x18); +} + +__EXTERN_INLINE void apecs_outl(unsigned int b, unsigned long addr) +{ + *(vuip) ((addr << 5) + APECS_IO + 0x18) = b; + mb(); +} + + +/* + * Memory functions. 64-bit and 32-bit accesses are done through + * dense memory space, everything else through sparse space. + */ + +__EXTERN_INLINE unsigned long apecs_readb(unsigned long addr) +{ + unsigned long result, msb; + + if (addr >= (1UL << 24)) { + msb = addr & 0xf8000000; + addr -= msb; + set_hae(msb); + } + result = *(vip) ((addr << 5) + APECS_SPARSE_MEM + 0x00); + return __kernel_extbl(result, addr & 3); +} + +__EXTERN_INLINE unsigned long apecs_readw(unsigned long addr) +{ + unsigned long result, msb; + + if (addr >= (1UL << 24)) { + msb = addr & 0xf8000000; + addr -= msb; + set_hae(msb); + } + result = *(vip) ((addr << 5) + APECS_SPARSE_MEM + 0x08); + return __kernel_extwl(result, addr & 3); +} + +__EXTERN_INLINE unsigned long apecs_readl(unsigned long addr) +{ + return *(vuip) (addr + APECS_DENSE_MEM); +} + +__EXTERN_INLINE unsigned long apecs_readq(unsigned long addr) +{ + return *(vulp) (addr + APECS_DENSE_MEM); +} + +__EXTERN_INLINE void apecs_writeb(unsigned char b, unsigned long addr) +{ + unsigned long msb; + + if (addr >= (1UL << 24)) { + msb = addr & 0xf8000000; + addr -= msb; + set_hae(msb); + } + *(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x00) = b * 0x01010101; +} + +__EXTERN_INLINE void apecs_writew(unsigned short b, unsigned long addr) +{ + unsigned long msb; + + if (addr >= (1UL << 24)) { + msb = addr & 0xf8000000; + addr -= msb; + set_hae(msb); + } + *(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x08) = b * 0x00010001; +} + +__EXTERN_INLINE void apecs_writel(unsigned int b, unsigned long addr) +{ + *(vuip) (addr + APECS_DENSE_MEM) = b; +} + +__EXTERN_INLINE void apecs_writeq(unsigned long b, unsigned long addr) +{ + *(vulp) (addr + APECS_DENSE_MEM) = b; +} + +/* Find the DENSE memory area for a given bus address. */ + +__EXTERN_INLINE unsigned long apecs_dense_mem(unsigned long addr) +{ + return APECS_DENSE_MEM; +} + +#undef vip +#undef vuip +#undef vulp + +#ifdef __WANT_IO_DEF + +#ifdef CONFIG_ALPHA_XL +#define virt_to_bus apecs_xl_virt_to_bus +#define bus_to_virt apecs_xl_bus_to_virt +#else +#define virt_to_bus apecs_virt_to_bus +#define bus_to_virt apecs_bus_to_virt +#endif + +#define __inb apecs_inb +#define __inw apecs_inw +#define __inl apecs_inl +#define __outb apecs_outb +#define __outw apecs_outw +#define __outl apecs_outl +#define __readb apecs_readb +#define __readw apecs_readw +#define __readl apecs_readl +#define __readq apecs_readq +#define __writeb apecs_writeb +#define __writew apecs_writew +#define __writel apecs_writel +#define __writeq apecs_writeq +#define dense_mem apecs_dense_mem + +#define inb(port) \ +(__builtin_constant_p((port))?__inb(port):_inb(port)) + +#define outb(x, port) \ +(__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port))) + +#define readl(a) __readl((unsigned long)(a)) +#define readq(a) __readq((unsigned long)(a)) +#define writel(v,a) __writel((v),(unsigned long)(a)) +#define writeq(v,a) __writeq((v),(unsigned long)(a)) + +#endif /* __WANT_IO_DEF */ + +#ifdef __IO_EXTERN_INLINE +#undef __EXTERN_INLINE +#undef __IO_EXTERN_INLINE +#endif + +#endif /* __KERNEL__ */ + +#endif /* __ALPHA_APECS__H__ */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/core_cia.h linux/include/asm-alpha/core_cia.h --- v2.1.115/linux/include/asm-alpha/core_cia.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-alpha/core_cia.h Sun Aug 9 12:09:06 1998 @@ -0,0 +1,601 @@ +#ifndef __ALPHA_CIA__H__ +#define __ALPHA_CIA__H__ + +#include +#include +#include + +/* + * CIA is the internal name for the 2117x chipset which provides + * memory controller and PCI access for the 21164 chip based systems. + * + * This file is based on: + * + * DECchip 21171 Core Logic Chipset + * Technical Reference Manual + * + * EC-QE18B-TE + * + * david.rusling@reo.mts.dec.com Initial Version. + * + */ + +/*------------------------------------------------------------------------** +** ** +** EB164 I/O procedures ** +** ** +** inport[b|w|t|l], outport[b|w|t|l] 8:16:24:32 IO xfers ** +** inportbxt: 8 bits only ** +** inport: alias of inportw ** +** outport: alias of outportw ** +** ** +** inmem[b|w|t|l], outmem[b|w|t|l] 8:16:24:32 ISA memory xfers ** +** inmembxt: 8 bits only ** +** inmem: alias of inmemw ** +** outmem: alias of outmemw ** +** ** +**------------------------------------------------------------------------*/ + + +/* CIA ADDRESS BIT DEFINITIONS + * + * 3 3 3 3|3 3 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 + * 9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |1| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |0|0|0| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | \_/ \_/ + * | | | + * +-- IO space, not cached. Byte Enable --+ | + * Transfer Length --+ + * + * + * + * Byte Transfer + * Enable Length Transfer Byte Address + * adr<6:5> adr<4:3> Length Enable Adder + * --------------------------------------------- + * 00 00 Byte 1110 0x000 + * 01 00 Byte 1101 0x020 + * 10 00 Byte 1011 0x040 + * 11 00 Byte 0111 0x060 + * + * 00 01 Word 1100 0x008 + * 01 01 Word 1001 0x028 <= Not supported in this code. + * 10 01 Word 0011 0x048 + * + * 00 10 Tribyte 1000 0x010 + * 01 10 Tribyte 0001 0x030 + * + * 10 11 Longword 0000 0x058 + * + * Note that byte enables are asserted low. + * + */ + +#define CIA_MEM_R1_MASK 0x1fffffff /* SPARSE Mem region 1 mask is 29 bits */ +#define CIA_MEM_R2_MASK 0x07ffffff /* SPARSE Mem region 2 mask is 27 bits */ +#define CIA_MEM_R3_MASK 0x03ffffff /* SPARSE Mem region 3 mask is 26 bits */ + +#define CIA_DMA_WIN_BASE_DEFAULT (1024*1024*1024) +#define CIA_DMA_WIN_SIZE_DEFAULT (1024*1024*1024) + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) +#define CIA_DMA_WIN_BASE alpha_mv.dma_win_base +#define CIA_DMA_WIN_SIZE alpha_mv.dma_win_size +#else +#define CIA_DMA_WIN_BASE CIA_DMA_WIN_SIZE_DEFAULT +#define CIA_DMA_WIN_SIZE CIA_DMA_WIN_SIZE_DEFAULT +#endif + +/* + * 21171-CA Control and Status Registers (p4-1) + */ +#define CIA_IOC_CIA_REV (IDENT_ADDR + 0x8740000080UL) +#define CIA_IOC_PCI_LAT (IDENT_ADDR + 0x87400000C0UL) +#define CIA_IOC_CIA_CTRL (IDENT_ADDR + 0x8740000100UL) +#define CIA_IOC_CIA_CNFG (IDENT_ADDR + 0x8740000140UL) +#define CIA_IOC_HAE_MEM (IDENT_ADDR + 0x8740000400UL) +#define CIA_IOC_HAE_IO (IDENT_ADDR + 0x8740000440UL) +#define CIA_IOC_CFG (IDENT_ADDR + 0x8740000480UL) +#define CIA_IOC_CACK_EN (IDENT_ADDR + 0x8740000600UL) + +/* + * 21171-CA Diagnostic Registers (p4-2) + */ +#define CIA_IOC_CIA_DIAG (IDENT_ADDR + 0x8740002000UL) +#define CIA_IOC_DIAG_CHECK (IDENT_ADDR + 0x8740003000UL) + +/* + * 21171-CA Performance Monitor registers (p4-3) + */ +#define CIA_IOC_PERF_MONITOR (IDENT_ADDR + 0x8740004000UL) +#define CIA_IOC_PERF_CONTROL (IDENT_ADDR + 0x8740004040UL) + +/* + * 21171-CA Error registers (p4-3) + */ +#define CIA_IOC_CPU_ERR0 (IDENT_ADDR + 0x8740008000UL) +#define CIA_IOC_CPU_ERR1 (IDENT_ADDR + 0x8740008040UL) +#define CIA_IOC_CIA_ERR (IDENT_ADDR + 0x8740008200UL) +#define CIA_IOC_CIA_STAT (IDENT_ADDR + 0x8740008240UL) +#define CIA_IOC_ERR_MASK (IDENT_ADDR + 0x8740008280UL) +#define CIA_IOC_CIA_SYN (IDENT_ADDR + 0x8740008300UL) +#define CIA_IOC_MEM_ERR0 (IDENT_ADDR + 0x8740008400UL) +#define CIA_IOC_MEM_ERR1 (IDENT_ADDR + 0x8740008440UL) +#define CIA_IOC_PCI_ERR0 (IDENT_ADDR + 0x8740008800UL) +#define CIA_IOC_PCI_ERR1 (IDENT_ADDR + 0x8740008840UL) +#define CIA_IOC_PCI_ERR3 (IDENT_ADDR + 0x8740008880UL) + +/* + * 2117A-CA PCI Address Translation Registers. + */ +#define CIA_IOC_PCI_TBIA (IDENT_ADDR + 0x8760000100UL) + +#define CIA_IOC_PCI_W0_BASE (IDENT_ADDR + 0x8760000400UL) +#define CIA_IOC_PCI_W0_MASK (IDENT_ADDR + 0x8760000440UL) +#define CIA_IOC_PCI_T0_BASE (IDENT_ADDR + 0x8760000480UL) + +#define CIA_IOC_PCI_W1_BASE (IDENT_ADDR + 0x8760000500UL) +#define CIA_IOC_PCI_W1_MASK (IDENT_ADDR + 0x8760000540UL) +#define CIA_IOC_PCI_T1_BASE (IDENT_ADDR + 0x8760000580UL) + +#define CIA_IOC_PCI_W2_BASE (IDENT_ADDR + 0x8760000600UL) +#define CIA_IOC_PCI_W2_MASK (IDENT_ADDR + 0x8760000640UL) +#define CIA_IOC_PCI_T2_BASE (IDENT_ADDR + 0x8760000680UL) + +#define CIA_IOC_PCI_W3_BASE (IDENT_ADDR + 0x8760000700UL) +#define CIA_IOC_PCI_W3_MASK (IDENT_ADDR + 0x8760000740UL) +#define CIA_IOC_PCI_T3_BASE (IDENT_ADDR + 0x8760000780UL) + +/* + * 21171-CA System configuration registers (p4-3) + */ +#define CIA_IOC_MCR (IDENT_ADDR + 0x8750000000UL) +#define CIA_IOC_MBA0 (IDENT_ADDR + 0x8750000600UL) +#define CIA_IOC_MBA2 (IDENT_ADDR + 0x8750000680UL) +#define CIA_IOC_MBA4 (IDENT_ADDR + 0x8750000700UL) +#define CIA_IOC_MBA6 (IDENT_ADDR + 0x8750000780UL) +#define CIA_IOC_MBA8 (IDENT_ADDR + 0x8750000800UL) +#define CIA_IOC_MBAA (IDENT_ADDR + 0x8750000880UL) +#define CIA_IOC_MBAC (IDENT_ADDR + 0x8750000900UL) +#define CIA_IOC_MBAE (IDENT_ADDR + 0x8750000980UL) +#define CIA_IOC_TMG0 (IDENT_ADDR + 0x8750000B00UL) +#define CIA_IOC_TMG1 (IDENT_ADDR + 0x8750000B40UL) +#define CIA_IOC_TMG2 (IDENT_ADDR + 0x8750000B80UL) + +/* + * Memory spaces: + */ +#define CIA_IACK_SC (IDENT_ADDR + 0x8720000000UL) +#define CIA_CONF (IDENT_ADDR + 0x8700000000UL) +#define CIA_IO (IDENT_ADDR + 0x8580000000UL) +#define CIA_SPARSE_MEM (IDENT_ADDR + 0x8000000000UL) +#define CIA_SPARSE_MEM_R2 (IDENT_ADDR + 0x8400000000UL) +#define CIA_SPARSE_MEM_R3 (IDENT_ADDR + 0x8500000000UL) +#define CIA_DENSE_MEM (IDENT_ADDR + 0x8600000000UL) + +/* + * ALCOR's GRU ASIC registers + */ +#define GRU_INT_REQ (IDENT_ADDR + 0x8780000000UL) +#define GRU_INT_MASK (IDENT_ADDR + 0x8780000040UL) +#define GRU_INT_EDGE (IDENT_ADDR + 0x8780000080UL) +#define GRU_INT_HILO (IDENT_ADDR + 0x87800000C0UL) +#define GRU_INT_CLEAR (IDENT_ADDR + 0x8780000100UL) + +#define GRU_CACHE_CNFG (IDENT_ADDR + 0x8780000200UL) +#define GRU_SCR (IDENT_ADDR + 0x8780000300UL) +#define GRU_LED (IDENT_ADDR + 0x8780000800UL) +#define GRU_RESET (IDENT_ADDR + 0x8780000900UL) + +#define ALCOR_GRU_INT_REQ_BITS 0x800fffffUL +#define XLT_GRU_INT_REQ_BITS 0x80003fffUL +#define GRU_INT_REQ_BITS (alpha_mv.sys.cia.gru_int_req_bits+0) + + +/* + * Bit definitions for I/O Controller status register 0: + */ +#define CIA_IOC_STAT0_CMD 0xf +#define CIA_IOC_STAT0_ERR (1<<4) +#define CIA_IOC_STAT0_LOST (1<<5) +#define CIA_IOC_STAT0_THIT (1<<6) +#define CIA_IOC_STAT0_TREF (1<<7) +#define CIA_IOC_STAT0_CODE_SHIFT 8 +#define CIA_IOC_STAT0_CODE_MASK 0x7 +#define CIA_IOC_STAT0_P_NBR_SHIFT 13 +#define CIA_IOC_STAT0_P_NBR_MASK 0x7ffff + +#define CIA_HAE_ADDRESS CIA_IOC_HAE_MEM + +/* + * Data structure for handling CIA machine checks. + */ + +/* EV5-specific info. */ +struct el_CIA_procdata { + unsigned long shadow[8]; /* PALmode shadow registers */ + unsigned long paltemp[24]; /* PAL temporary registers */ + /* EV5-specific fields */ + unsigned long exc_addr; /* Address of excepting instruction. */ + unsigned long exc_sum; /* Summary of arithmetic traps. */ + unsigned long exc_mask; /* Exception mask (from exc_sum). */ + unsigned long exc_base; /* PALbase at time of exception. */ + unsigned long isr; /* Interrupt summary register. */ + unsigned long icsr; /* Ibox control register. */ + unsigned long ic_perr_stat; + unsigned long dc_perr_stat; + unsigned long va; /* Effective VA of fault or miss. */ + unsigned long mm_stat; + unsigned long sc_addr; + unsigned long sc_stat; + unsigned long bc_tag_addr; + unsigned long ei_addr; + unsigned long fill_syn; + unsigned long ei_stat; + unsigned long ld_lock; +}; + +/* System-specific info. */ +struct el_CIA_sysdata_mcheck { + unsigned long coma_gcr; + unsigned long coma_edsr; + unsigned long coma_ter; + unsigned long coma_elar; + unsigned long coma_ehar; + unsigned long coma_ldlr; + unsigned long coma_ldhr; + unsigned long coma_base0; + unsigned long coma_base1; + unsigned long coma_base2; + unsigned long coma_cnfg0; + unsigned long coma_cnfg1; + unsigned long coma_cnfg2; + unsigned long epic_dcsr; + unsigned long epic_pear; + unsigned long epic_sear; + unsigned long epic_tbr1; + unsigned long epic_tbr2; + unsigned long epic_pbr1; + unsigned long epic_pbr2; + unsigned long epic_pmr1; + unsigned long epic_pmr2; + unsigned long epic_harx1; + unsigned long epic_harx2; + unsigned long epic_pmlt; + unsigned long epic_tag0; + unsigned long epic_tag1; + unsigned long epic_tag2; + unsigned long epic_tag3; + unsigned long epic_tag4; + unsigned long epic_tag5; + unsigned long epic_tag6; + unsigned long epic_tag7; + unsigned long epic_data0; + unsigned long epic_data1; + unsigned long epic_data2; + unsigned long epic_data3; + unsigned long epic_data4; + unsigned long epic_data5; + unsigned long epic_data6; + unsigned long epic_data7; +}; + + +#ifdef __KERNEL__ + +#ifndef __EXTERN_INLINE +#define __EXTERN_INLINE extern inline +#define __IO_EXTERN_INLINE +#endif + +/* + * Translate physical memory address as seen on (PCI) bus into + * a kernel virtual address and vv. + */ + +__EXTERN_INLINE unsigned long cia_virt_to_bus(void * address) +{ + return virt_to_phys(address) + CIA_DMA_WIN_BASE; +} + +__EXTERN_INLINE void * cia_bus_to_virt(unsigned long address) +{ + return phys_to_virt(address - CIA_DMA_WIN_BASE); +} + +/* + * I/O functions: + * + * CIA (the 2117x PCI/memory support chipset for the EV5 (21164) + * series of processors uses a sparse address mapping scheme to + * get at PCI memory and I/O. + */ + +#define vip volatile int * +#define vuip volatile unsigned int * +#define vulp volatile unsigned long * + +__EXTERN_INLINE unsigned int cia_inb(unsigned long addr) +{ + long result; + result = *(vip) ((addr << 5) + CIA_IO + 0x00); + return __kernel_extbl(result, addr & 3); +} + +__EXTERN_INLINE void cia_outb(unsigned char b, unsigned long addr) +{ + unsigned int w = __kernel_insbl(b, addr & 3); + *(vuip) ((addr << 5) + CIA_IO + 0x00) = w; + wmb(); +} + +__EXTERN_INLINE unsigned int cia_inw(unsigned long addr) +{ + long result; + result = *(vip) ((addr << 5) + CIA_IO + 0x08); + return __kernel_extwl(result, addr & 3); +} + +__EXTERN_INLINE void cia_outw(unsigned short b, unsigned long addr) +{ + unsigned int w = __kernel_inswl(b, addr & 3); + *(vuip) ((addr << 5) + CIA_IO + 0x08) = w; + wmb(); +} + +__EXTERN_INLINE unsigned int cia_inl(unsigned long addr) +{ + return *(vuip) ((addr << 5) + CIA_IO + 0x18); +} + +__EXTERN_INLINE void cia_outl(unsigned int b, unsigned long addr) +{ + *(vuip) ((addr << 5) + CIA_IO + 0x18) = b; + wmb(); +} + + +/* + * Memory functions. 64-bit and 32-bit accesses are done through + * dense memory space, everything else through sparse space. + * + * For reading and writing 8 and 16 bit quantities we need to + * go through one of the three sparse address mapping regions + * and use the HAE_MEM CSR to provide some bits of the address. + * The following few routines use only sparse address region 1 + * which gives 1Gbyte of accessible space which relates exactly + * to the amount of PCI memory mapping *into* system address space. + * See p 6-17 of the specification but it looks something like this: + * + * 21164 Address: + * + * 3 2 1 + * 9876543210987654321098765432109876543210 + * 1ZZZZ0.PCI.QW.Address............BBLL + * + * ZZ = SBZ + * BB = Byte offset + * LL = Transfer length + * + * PCI Address: + * + * 3 2 1 + * 10987654321098765432109876543210 + * HHH....PCI.QW.Address........ 00 + * + * HHH = 31:29 HAE_MEM CSR + * + */ + +__EXTERN_INLINE unsigned long cia_srm_base(unsigned long addr) +{ + unsigned long mask, base; + + if (addr >= alpha_mv.sm_base_r1 + && addr <= alpha_mv.sm_base_r1 + CIA_MEM_R1_MASK) { + mask = CIA_MEM_R1_MASK; + base = CIA_SPARSE_MEM; + } + else if (addr >= alpha_mv.sm_base_r2 + && addr <= alpha_mv.sm_base_r2 + CIA_MEM_R2_MASK) { + mask = CIA_MEM_R2_MASK; + base = CIA_SPARSE_MEM_R2; + } + else if (addr >= alpha_mv.sm_base_r3 + && addr <= alpha_mv.sm_base_r3 + CIA_MEM_R3_MASK) { + mask = CIA_MEM_R3_MASK; + base = CIA_SPARSE_MEM_R3; + } + else + { +#if 0 + printk("cia: address 0x%lx not covered by HAE\n", addr); +#endif + return 0; + } + + return ((addr & mask) << 5) + base; +} + +__EXTERN_INLINE unsigned long cia_srm_readb(unsigned long addr) +{ + unsigned long result, work; + + if ((work = cia_srm_base(addr)) == 0) + return 0xff; + work += 0x00; /* add transfer length */ + + result = *(vip) work; + return __kernel_extbl(result, addr & 3); +} + +__EXTERN_INLINE unsigned long cia_srm_readw(unsigned long addr) +{ + unsigned long result, work; + + if ((work = cia_srm_base(addr)) == 0) + return 0xffff; + work += 0x08; /* add transfer length */ + + result = *(vip) work; + return __kernel_extwl(result, addr & 3); +} + +__EXTERN_INLINE void cia_srm_writeb(unsigned char b, unsigned long addr) +{ + unsigned long work = cia_srm_base(addr), w; + if (work) { + work += 0x00; /* add transfer length */ + w = __kernel_insbl(b, addr & 3); + *(vuip) work = w; + } +} + +__EXTERN_INLINE void cia_srm_writew(unsigned short b, unsigned long addr) +{ + unsigned long work = cia_srm_base(addr), w; + if (work) { + work += 0x08; /* add transfer length */ + w = __kernel_inswl(b, addr & 3); + *(vuip) work = w; + } +} + +__EXTERN_INLINE unsigned long cia_readb(unsigned long addr) +{ + unsigned long result, msb; + + msb = addr & 0xE0000000; + addr &= CIA_MEM_R1_MASK; + set_hae(msb); + + result = *(vip) ((addr << 5) + CIA_SPARSE_MEM + 0x00); + return __kernel_extbl(result, addr & 3); +} + +__EXTERN_INLINE unsigned long cia_readw(unsigned long addr) +{ + unsigned long result, msb; + + msb = addr & 0xE0000000; + addr &= CIA_MEM_R1_MASK; + set_hae(msb); + + result = *(vip) ((addr << 5) + CIA_SPARSE_MEM + 0x08); + return __kernel_extwl(result, addr & 3); +} + +__EXTERN_INLINE void cia_writeb(unsigned char b, unsigned long addr) +{ + unsigned long msb, w; + + msb = addr & 0xE0000000; + addr &= CIA_MEM_R1_MASK; + set_hae(msb); + + w = __kernel_insbl(b, addr & 3); + *(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x00) = w; +} + +__EXTERN_INLINE void cia_writew(unsigned short b, unsigned long addr) +{ + unsigned long msb, w; + + msb = addr & 0xE0000000; + addr &= CIA_MEM_R1_MASK; + set_hae(msb); + + w = __kernel_inswl(b, addr & 3); + *(vuip) ((addr << 5) + CIA_SPARSE_MEM + 0x08) = w; +} + +__EXTERN_INLINE unsigned long cia_readl(unsigned long addr) +{ + return *(vuip) (addr + CIA_DENSE_MEM); +} + +__EXTERN_INLINE unsigned long cia_readq(unsigned long addr) +{ + return *(vulp) (addr + CIA_DENSE_MEM); +} + +__EXTERN_INLINE void cia_writel(unsigned int b, unsigned long addr) +{ + *(vuip) (addr + CIA_DENSE_MEM) = b; +} + +__EXTERN_INLINE void cia_writeq(unsigned long b, unsigned long addr) +{ + *(vulp) (addr + CIA_DENSE_MEM) = b; +} + +/* Find the DENSE memory area for a given bus address. */ + +__EXTERN_INLINE unsigned long cia_dense_mem(unsigned long addr) +{ + return CIA_DENSE_MEM; +} + +#undef vip +#undef vuip +#undef vulp + +#ifdef __WANT_IO_DEF + +#define virt_to_bus cia_virt_to_bus +#define bus_to_virt cia_bus_to_virt +#define __inb cia_inb +#define __inw cia_inw +#define __inl cia_inl +#define __outb cia_outb +#define __outw cia_outw +#define __outl cia_outl + +#ifdef CONFIG_ALPHA_SRM_SETUP +#define __readb cia_srm_readb +#define __readw cia_srm_readw +#define __writeb cia_srm_writeb +#define __writew cia_srm_writew +#else +#define __readb cia_readb +#define __readw cia_readw +#define __writeb cia_writeb +#define __writew cia_writew +#endif + +#define __readl cia_readl +#define __readq cia_readq +#define __writel cia_writel +#define __writeq cia_writeq +#define dense_mem cia_dense_mem + +#define inb(port) \ +(__builtin_constant_p((port))?__inb(port):_inb(port)) +#define outb(x, port) \ +(__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port))) + +#define inw(port) \ +(__builtin_constant_p((port))?__inw(port):_inw(port)) +#define outw(x, port) \ +(__builtin_constant_p((port))?__outw((x),(port)):_outw((x),(port))) + +#define inl(port) __inl(port) +#define outl(x,port) __outl((x),(port)) + +#define readl(a) __readl((unsigned long)(a)) +#define readq(a) __readq((unsigned long)(a)) +#define writel(v,a) __writel((v),(unsigned long)(a)) +#define writeq(v,a) __writeq((v),(unsigned long)(a)) + +#endif /* __WANT_IO_DEF */ + +#ifdef __IO_EXTERN_INLINE +#undef __EXTERN_INLINE +#undef __IO_EXTERN_INLINE +#endif + +#endif /* __KERNEL__ */ + +#endif /* __ALPHA_CIA__H__ */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/core_lca.h linux/include/asm-alpha/core_lca.h --- v2.1.115/linux/include/asm-alpha/core_lca.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-alpha/core_lca.h Sun Aug 9 12:09:06 1998 @@ -0,0 +1,429 @@ +#ifndef __ALPHA_LCA__H__ +#define __ALPHA_LCA__H__ + +#include +#include +#include + +/* + * Low Cost Alpha (LCA) definitions (these apply to 21066 and 21068, + * for example). + * + * This file is based on: + * + * DECchip 21066 and DECchip 21068 Alpha AXP Microprocessors + * Hardware Reference Manual; Digital Equipment Corp.; May 1994; + * Maynard, MA; Order Number: EC-N2681-71. + */ + +/* + * NOTE: The LCA uses a Host Address Extension (HAE) register to access + * PCI addresses that are beyond the first 27 bits of address + * space. Updating the HAE requires an external cycle (and + * a memory barrier), which tends to be slow. Instead of updating + * it on each sparse memory access, we keep the current HAE value + * cached in variable cache_hae. Only if the cached HAE differs + * from the desired HAE value do we actually updated HAE register. + * The HAE register is preserved by the interrupt handler entry/exit + * code, so this scheme works even in the presence of interrupts. + * + * Dense memory space doesn't require the HAE, but is restricted to + * aligned 32 and 64 bit accesses. Special Cycle and Interrupt + * Acknowledge cycles may also require the use of the HAE. The LCA + * limits I/O address space to the bottom 24 bits of address space, + * but this easily covers the 16 bit ISA I/O address space. + */ + +/* + * NOTE 2! The memory operations do not set any memory barriers, as + * it's not needed for cases like a frame buffer that is essentially + * memory-like. You need to do them by hand if the operations depend + * on ordering. + * + * Similarly, the port I/O operations do a "mb" only after a write + * operation: if an mb is needed before (as in the case of doing + * memory mapped I/O first, and then a port I/O operation to the same + * device), it needs to be done by hand. + * + * After the above has bitten me 100 times, I'll give up and just do + * the mb all the time, but right now I'm hoping this will work out. + * Avoiding mb's may potentially be a noticeable speed improvement, + * but I can't honestly say I've tested it. + * + * Handling interrupts that need to do mb's to synchronize to + * non-interrupts is another fun race area. Don't do it (because if + * you do, I'll have to do *everything* with interrupts disabled, + * ugh). + */ + +#define LCA_DMA_WIN_BASE_DEFAULT (1024*1024*1024) +#define LCA_DMA_WIN_SIZE_DEFAULT (1024*1024*1024) + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) +#define LCA_DMA_WIN_BASE alpha_mv.dma_win_base +#define LCA_DMA_WIN_SIZE alpha_mv.dma_win_size +#else +#define LCA_DMA_WIN_BASE LCA_DMA_WIN_BASE_DEFAULT +#define LCA_DMA_WIN_SIZE LCA_DMA_WIN_SIZE_DEFAULT +#endif + +/* + * Memory Controller registers: + */ +#define LCA_MEM_BCR0 (IDENT_ADDR + 0x120000000UL) +#define LCA_MEM_BCR1 (IDENT_ADDR + 0x120000008UL) +#define LCA_MEM_BCR2 (IDENT_ADDR + 0x120000010UL) +#define LCA_MEM_BCR3 (IDENT_ADDR + 0x120000018UL) +#define LCA_MEM_BMR0 (IDENT_ADDR + 0x120000020UL) +#define LCA_MEM_BMR1 (IDENT_ADDR + 0x120000028UL) +#define LCA_MEM_BMR2 (IDENT_ADDR + 0x120000030UL) +#define LCA_MEM_BMR3 (IDENT_ADDR + 0x120000038UL) +#define LCA_MEM_BTR0 (IDENT_ADDR + 0x120000040UL) +#define LCA_MEM_BTR1 (IDENT_ADDR + 0x120000048UL) +#define LCA_MEM_BTR2 (IDENT_ADDR + 0x120000050UL) +#define LCA_MEM_BTR3 (IDENT_ADDR + 0x120000058UL) +#define LCA_MEM_GTR (IDENT_ADDR + 0x120000060UL) +#define LCA_MEM_ESR (IDENT_ADDR + 0x120000068UL) +#define LCA_MEM_EAR (IDENT_ADDR + 0x120000070UL) +#define LCA_MEM_CAR (IDENT_ADDR + 0x120000078UL) +#define LCA_MEM_VGR (IDENT_ADDR + 0x120000080UL) +#define LCA_MEM_PLM (IDENT_ADDR + 0x120000088UL) +#define LCA_MEM_FOR (IDENT_ADDR + 0x120000090UL) + +/* + * I/O Controller registers: + */ +#define LCA_IOC_HAE (IDENT_ADDR + 0x180000000UL) +#define LCA_IOC_CONF (IDENT_ADDR + 0x180000020UL) +#define LCA_IOC_STAT0 (IDENT_ADDR + 0x180000040UL) +#define LCA_IOC_STAT1 (IDENT_ADDR + 0x180000060UL) +#define LCA_IOC_TBIA (IDENT_ADDR + 0x180000080UL) +#define LCA_IOC_TB_ENA (IDENT_ADDR + 0x1800000a0UL) +#define LCA_IOC_SFT_RST (IDENT_ADDR + 0x1800000c0UL) +#define LCA_IOC_PAR_DIS (IDENT_ADDR + 0x1800000e0UL) +#define LCA_IOC_W_BASE0 (IDENT_ADDR + 0x180000100UL) +#define LCA_IOC_W_BASE1 (IDENT_ADDR + 0x180000120UL) +#define LCA_IOC_W_MASK0 (IDENT_ADDR + 0x180000140UL) +#define LCA_IOC_W_MASK1 (IDENT_ADDR + 0x180000160UL) +#define LCA_IOC_T_BASE0 (IDENT_ADDR + 0x180000180UL) +#define LCA_IOC_T_BASE1 (IDENT_ADDR + 0x1800001a0UL) +#define LCA_IOC_TB_TAG0 (IDENT_ADDR + 0x188000000UL) +#define LCA_IOC_TB_TAG1 (IDENT_ADDR + 0x188000020UL) +#define LCA_IOC_TB_TAG2 (IDENT_ADDR + 0x188000040UL) +#define LCA_IOC_TB_TAG3 (IDENT_ADDR + 0x188000060UL) +#define LCA_IOC_TB_TAG4 (IDENT_ADDR + 0x188000070UL) +#define LCA_IOC_TB_TAG5 (IDENT_ADDR + 0x1880000a0UL) +#define LCA_IOC_TB_TAG6 (IDENT_ADDR + 0x1880000c0UL) +#define LCA_IOC_TB_TAG7 (IDENT_ADDR + 0x1880000e0UL) + +/* + * Memory spaces: + */ +#define LCA_IACK_SC (IDENT_ADDR + 0x1a0000000UL) +#define LCA_CONF (IDENT_ADDR + 0x1e0000000UL) +#define LCA_IO (IDENT_ADDR + 0x1c0000000UL) +#define LCA_SPARSE_MEM (IDENT_ADDR + 0x200000000UL) +#define LCA_DENSE_MEM (IDENT_ADDR + 0x300000000UL) + +/* + * Bit definitions for I/O Controller status register 0: + */ +#define LCA_IOC_STAT0_CMD 0xf +#define LCA_IOC_STAT0_ERR (1<<4) +#define LCA_IOC_STAT0_LOST (1<<5) +#define LCA_IOC_STAT0_THIT (1<<6) +#define LCA_IOC_STAT0_TREF (1<<7) +#define LCA_IOC_STAT0_CODE_SHIFT 8 +#define LCA_IOC_STAT0_CODE_MASK 0x7 +#define LCA_IOC_STAT0_P_NBR_SHIFT 13 +#define LCA_IOC_STAT0_P_NBR_MASK 0x7ffff + +#define LCA_HAE_ADDRESS LCA_IOC_HAE + +/* LCA PMR Power Management register defines */ +#define LCA_PMR_ADDR (IDENT_ADDR + 0x120000098UL) +#define LCA_PMR_PDIV 0x7 /* Primary clock divisor */ +#define LCA_PMR_ODIV 0x38 /* Override clock divisor */ +#define LCA_PMR_INTO 0x40 /* Interrupt override */ +#define LCA_PMR_DMAO 0x80 /* DMA override */ +#define LCA_PMR_OCCEB 0xffff0000L /* Override cycle counter - even bits */ +#define LCA_PMR_OCCOB 0xffff000000000000L /* Override cycle counter - even bits */ +#define LCA_PMR_PRIMARY_MASK 0xfffffffffffffff8 + +/* LCA PMR Macros */ + +#define LCA_READ_PMR (*(volatile unsigned long *)LCA_PMR_ADDR) +#define LCA_WRITE_PMR(d) (*((volatile unsigned long *)LCA_PMR_ADDR) = (d)) + +#define LCA_GET_PRIMARY(r) ((r) & LCA_PMR_PDIV) +#define LCA_GET_OVERRIDE(r) (((r) >> 3) & LCA_PMR_PDIV) +#define LCA_SET_PRIMARY_CLOCK(r, c) ((r) = (((r) & LCA_PMR_PRIMARY_MASK)|(c))) + +/* LCA PMR Divisor values */ +#define LCA_PMR_DIV_1 0x0 +#define LCA_PMR_DIV_1_5 0x1 +#define LCA_PMR_DIV_2 0x2 +#define LCA_PMR_DIV_4 0x3 +#define LCA_PMR_DIV_8 0x4 +#define LCA_PMR_DIV_16 0x5 +#define LCA_PMR_DIV_MIN DIV_1 +#define LCA_PMR_DIV_MAX DIV_16 + + +/* + * Data structure for handling LCA machine checks. Correctable errors + * result in a short logout frame, uncorrectable ones in a long one. + */ +struct el_lca_mcheck_short { + struct el_common h; /* common logout header */ + unsigned long esr; /* error-status register */ + unsigned long ear; /* error-address register */ + unsigned long dc_stat; /* dcache status register */ + unsigned long ioc_stat0; /* I/O controller status register 0 */ + unsigned long ioc_stat1; /* I/O controller status register 1 */ +}; + +struct el_lca_mcheck_long { + struct el_common h; /* common logout header */ + unsigned long pt[31]; /* PAL temps */ + unsigned long exc_addr; /* exception address */ + unsigned long pad1[3]; + unsigned long pal_base; /* PALcode base address */ + unsigned long hier; /* hw interrupt enable */ + unsigned long hirr; /* hw interrupt request */ + unsigned long mm_csr; /* MMU control & status */ + unsigned long dc_stat; /* data cache status */ + unsigned long dc_addr; /* data cache addr register */ + unsigned long abox_ctl; /* address box control register */ + unsigned long esr; /* error status register */ + unsigned long ear; /* error address register */ + unsigned long car; /* cache control register */ + unsigned long ioc_stat0; /* I/O controller status register 0 */ + unsigned long ioc_stat1; /* I/O controller status register 1 */ + unsigned long va; /* virtual address register */ +}; + +union el_lca { + struct el_common * c; + struct el_lca_mcheck_long * l; + struct el_lca_mcheck_short * s; +}; + +#ifdef __KERNEL__ + +#ifndef __EXTERN_INLINE +#define __EXTERN_INLINE extern inline +#define __IO_EXTERN_INLINE +#endif + +/* + * Translate physical memory address as seen on (PCI) bus into + * a kernel virtual address and vv. + */ + +__EXTERN_INLINE unsigned long lca_virt_to_bus(void * address) +{ + return virt_to_phys(address) + LCA_DMA_WIN_BASE; +} + +__EXTERN_INLINE void * lca_bus_to_virt(unsigned long address) +{ + /* + * This check is a sanity check but also ensures that bus + * address 0 maps to virtual address 0 which is useful to + * detect null "pointers" (the NCR driver is much simpler if + * NULL pointers are preserved). + */ + if (address < LCA_DMA_WIN_BASE) + return 0; + return phys_to_virt(address - LCA_DMA_WIN_BASE); +} + +/* + * I/O functions: + * + * Unlike Jensen, the Noname machines have no concept of local + * I/O---everything goes over the PCI bus. + * + * There is plenty room for optimization here. In particular, + * the Alpha's insb/insw/extb/extw should be useful in moving + * data to/from the right byte-lanes. + */ + +#define vip volatile int * +#define vuip volatile unsigned int * +#define vulp volatile unsigned long * + +__EXTERN_INLINE unsigned int lca_inb(unsigned long addr) +{ + long result = *(vip) ((addr << 5) + LCA_IO + 0x00); + return __kernel_extbl(result, addr & 3); +} + +__EXTERN_INLINE void lca_outb(unsigned char b, unsigned long addr) +{ + unsigned int w; + + w = __kernel_insbl(b, addr & 3); + *(vuip) ((addr << 5) + LCA_IO + 0x00) = w; + mb(); +} + +__EXTERN_INLINE unsigned int lca_inw(unsigned long addr) +{ + long result = *(vip) ((addr << 5) + LCA_IO + 0x08); + return __kernel_extwl(result, addr & 3); +} + +__EXTERN_INLINE void lca_outw(unsigned short b, unsigned long addr) +{ + unsigned int w; + + w = __kernel_inswl(b, addr & 3); + *(vuip) ((addr << 5) + LCA_IO + 0x08) = w; + mb(); +} + +__EXTERN_INLINE unsigned int lca_inl(unsigned long addr) +{ + return *(vuip) ((addr << 5) + LCA_IO + 0x18); +} + +__EXTERN_INLINE void lca_outl(unsigned int b, unsigned long addr) +{ + *(vuip) ((addr << 5) + LCA_IO + 0x18) = b; + mb(); +} + + +/* + * Memory functions. 64-bit and 32-bit accesses are done through + * dense memory space, everything else through sparse space. + */ + +__EXTERN_INLINE unsigned long lca_readb(unsigned long addr) +{ + unsigned long result, msb; + + if (addr >= (1UL << 24)) { + msb = addr & 0xf8000000; + addr -= msb; + set_hae(msb); + } + result = *(vip) ((addr << 5) + LCA_SPARSE_MEM + 0x00); + return __kernel_extbl(result, addr & 3); +} + +__EXTERN_INLINE unsigned long lca_readw(unsigned long addr) +{ + unsigned long result, msb; + + if (addr >= (1UL << 24)) { + msb = addr & 0xf8000000; + addr -= msb; + set_hae(msb); + } + result = *(vip) ((addr << 5) + LCA_SPARSE_MEM + 0x08); + return __kernel_extwl(result, addr & 3); +} + +__EXTERN_INLINE unsigned long lca_readl(unsigned long addr) +{ + return *(vuip) (addr + LCA_DENSE_MEM); +} + +__EXTERN_INLINE unsigned long lca_readq(unsigned long addr) +{ + return *(vulp) (addr + LCA_DENSE_MEM); +} + +__EXTERN_INLINE void lca_writeb(unsigned char b, unsigned long addr) +{ + unsigned long msb; + unsigned int w; + + if (addr >= (1UL << 24)) { + msb = addr & 0xf8000000; + addr -= msb; + set_hae(msb); + } + w = __kernel_insbl(b, addr & 3); + *(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x00) = w; +} + +__EXTERN_INLINE void lca_writew(unsigned short b, unsigned long addr) +{ + unsigned long msb; + unsigned int w; + + if (addr >= (1UL << 24)) { + msb = addr & 0xf8000000; + addr -= msb; + set_hae(msb); + } + w = __kernel_inswl(b, addr & 3); + *(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x08) = w; +} + +__EXTERN_INLINE void lca_writel(unsigned int b, unsigned long addr) +{ + *(vuip) (addr + LCA_DENSE_MEM) = b; +} + +__EXTERN_INLINE void lca_writeq(unsigned long b, unsigned long addr) +{ + *(vulp) (addr + LCA_DENSE_MEM) = b; +} + +/* Find the DENSE memory area for a given bus address. */ + +__EXTERN_INLINE unsigned long lca_dense_mem(unsigned long addr) +{ + return LCA_DENSE_MEM; +} + +#undef vip +#undef vuip +#undef vulp + +#ifdef __WANT_IO_DEF + +#define virt_to_bus lca_virt_to_bus +#define bus_to_virt lca_bus_to_virt +#define __inb lca_inb +#define __inw lca_inw +#define __inl lca_inl +#define __outb lca_outb +#define __outw lca_outw +#define __outl lca_outl +#define __readb lca_readb +#define __readw lca_readw +#define __writeb lca_writeb +#define __writew lca_writew +#define __readl lca_readl +#define __readq lca_readq +#define __writel lca_writel +#define __writeq lca_writeq +#define dense_mem lca_dense_mem + +#define inb(port) \ +(__builtin_constant_p((port))?__inb(port):_inb(port)) + +#define outb(x, port) \ +(__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port))) + +#define readl(a) __readl((unsigned long)(a)) +#define readq(a) __readq((unsigned long)(a)) +#define writel(v,a) __writel((v),(unsigned long)(a)) +#define writeq(v,a) __writeq((v),(unsigned long)(a)) + +#endif /* __WANT_IO_DEF */ + +#ifdef __IO_EXTERN_INLINE +#undef __EXTERN_INLINE +#undef __IO_EXTERN_INLINE +#endif + +#endif /* __KERNEL__ */ + +#endif /* __ALPHA_LCA__H__ */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/core_mcpcia.h linux/include/asm-alpha/core_mcpcia.h --- v2.1.115/linux/include/asm-alpha/core_mcpcia.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-alpha/core_mcpcia.h Sun Aug 9 12:09:06 1998 @@ -0,0 +1,632 @@ +#ifndef __ALPHA_MCPCIA__H__ +#define __ALPHA_MCPCIA__H__ + +#include +#include +#include +#include + +/* + * MCPCIA is the internal name for a core logic chipset which provides + * PCI access for the RAWHIDE family of systems. + * + * This file is based on: + * + * RAWHIDE System Programmer's Manual + * 16-May-96 + * Rev. 1.4 + * + */ + +/*------------------------------------------------------------------------** +** ** +** I/O procedures ** +** ** +** inport[b|w|t|l], outport[b|w|t|l] 8:16:24:32 IO xfers ** +** inportbxt: 8 bits only ** +** inport: alias of inportw ** +** outport: alias of outportw ** +** ** +** inmem[b|w|t|l], outmem[b|w|t|l] 8:16:24:32 ISA memory xfers ** +** inmembxt: 8 bits only ** +** inmem: alias of inmemw ** +** outmem: alias of outmemw ** +** ** +**------------------------------------------------------------------------*/ + + +/* MCPCIA ADDRESS BIT DEFINITIONS + * + * 3 3 3 3|3 3 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 + * 9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |1| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |0|0|0| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | \_/ \_/ + * | | | + * +-- IO space, not cached. Byte Enable --+ | + * Transfer Length --+ + * + * + * + * Byte Transfer + * Enable Length Transfer Byte Address + * adr<6:5> adr<4:3> Length Enable Adder + * --------------------------------------------- + * 00 00 Byte 1110 0x000 + * 01 00 Byte 1101 0x020 + * 10 00 Byte 1011 0x040 + * 11 00 Byte 0111 0x060 + * + * 00 01 Word 1100 0x008 + * 01 01 Word 1001 0x028 <= Not supported in this code. + * 10 01 Word 0011 0x048 + * + * 00 10 Tribyte 1000 0x010 + * 01 10 Tribyte 0001 0x030 + * + * 10 11 Longword 0000 0x058 + * + * Note that byte enables are asserted low. + * + */ + +#define MCPCIA_MEM_R1_MASK 0x1fffffff /* SPARSE Mem region 1 mask is 29 bits */ +#define MCPCIA_MEM_R2_MASK 0x07ffffff /* SPARSE Mem region 2 mask is 27 bits */ +#define MCPCIA_MEM_R3_MASK 0x03ffffff /* SPARSE Mem region 3 mask is 26 bits */ + +#define MCPCIA_DMA_WIN_BASE_DEFAULT (2*1024*1024*1024U) +#define MCPCIA_DMA_WIN_SIZE_DEFAULT (2*1024*1024*1024U) + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) +#define MCPCIA_DMA_WIN_BASE alpha_mv.dma_win_base +#define MCPCIA_DMA_WIN_SIZE alpha_mv.dma_win_size +#else +#define MCPCIA_DMA_WIN_BASE MCPCIA_DMA_WIN_BASE_DEFAULT +#define MCPCIA_DMA_WIN_SIZE MCPCIA_DMA_WIN_SIZE_DEFAULT +#endif + +#define HOSE(h) (((unsigned long)(h)) << 33) + +/* + * General Registers + */ +#define MCPCIA_REV(h) (IDENT_ADDR + 0xf9e0000000UL + HOSE(h)) +#define MCPCIA_WHOAMI(h) (IDENT_ADDR + 0xf9e0000040UL + HOSE(h)) +#define MCPCIA_PCI_LAT(h) (IDENT_ADDR + 0xf9e0000080UL + HOSE(h)) +#define MCPCIA_CAP_CTRL(h) (IDENT_ADDR + 0xf9e0000100UL + HOSE(h)) +#define MCPCIA_HAE_MEM(h) (IDENT_ADDR + 0xf9e0000400UL + HOSE(h)) +#define MCPCIA_HAE_IO(h) (IDENT_ADDR + 0xf9e0000440UL + HOSE(h)) +#if 0 +#define MCPCIA_IACK_SC(h) (IDENT_ADDR + 0xf9e0000480UL + HOSE(h)) +#endif +#define MCPCIA_HAE_DENSE(h) (IDENT_ADDR + 0xf9e00004c0UL + HOSE(h)) + +/* + * Interrupt Control registers + */ +#define MCPCIA_INT_CTL(h) (IDENT_ADDR + 0xf9e0000500UL + HOSE(h)) +#define MCPCIA_INT_REQ(h) (IDENT_ADDR + 0xf9e0000540UL + HOSE(h)) +#define MCPCIA_INT_TARG(h) (IDENT_ADDR + 0xf9e0000580UL + HOSE(h)) +#define MCPCIA_INT_ADR(h) (IDENT_ADDR + 0xf9e00005c0UL + HOSE(h)) +#define MCPCIA_INT_ADR_EXT(h) (IDENT_ADDR + 0xf9e0000600UL + HOSE(h)) +#define MCPCIA_INT_MASK0(h) (IDENT_ADDR + 0xf9e0000640UL + HOSE(h)) +#define MCPCIA_INT_MASK1(h) (IDENT_ADDR + 0xf9e0000680UL + HOSE(h)) +#define MCPCIA_INT_ACK0(h) (IDENT_ADDR + 0xf9f0003f00UL + HOSE(h)) +#define MCPCIA_INT_ACK1(h) (IDENT_ADDR + 0xf9e0003f40UL + HOSE(h)) + +/* + * Performance Monitor registers + */ +#define MCPCIA_PERF_MONITOR(h) (IDENT_ADDR + 0xf9e0000300UL + HOSE(h)) +#define MCPCIA_PERF_CONTROL(h) (IDENT_ADDR + 0xf9e0000340UL + HOSE(h)) + +/* + * Diagnostic Registers + */ +#define MCPCIA_CAP_DIAG(h) (IDENT_ADDR + 0xf9e0000700UL + HOSE(h)) +#define MCPCIA_TOP_OF_MEM(h) (IDENT_ADDR + 0xf9e00007c0UL + HOSE(h)) + +/* + * Error registers + */ +#define MCPCIA_CAP_ERR(h) (IDENT_ADDR + 0xf9e0000880UL + HOSE(h)) +#define MCPCIA_PCI_ERR1(h) (IDENT_ADDR + 0xf9e0001040UL + HOSE(h)) + +/* + * PCI Address Translation Registers. + */ +#define MCPCIA_SG_TBIA(h) (IDENT_ADDR + 0xf9e0001300UL + HOSE(h)) +#define MCPCIA_HBASE(h) (IDENT_ADDR + 0xf9e0001340UL + HOSE(h)) + +#define MCPCIA_W0_BASE(h) (IDENT_ADDR + 0xf9e0001400UL + HOSE(h)) +#define MCPCIA_W0_MASK(h) (IDENT_ADDR + 0xf9e0001440UL + HOSE(h)) +#define MCPCIA_T0_BASE(h) (IDENT_ADDR + 0xf9e0001480UL + HOSE(h)) + +#define MCPCIA_W1_BASE(h) (IDENT_ADDR + 0xf9e0001500UL + HOSE(h)) +#define MCPCIA_W1_MASK(h) (IDENT_ADDR + 0xf9e0001540UL + HOSE(h)) +#define MCPCIA_T1_BASE(h) (IDENT_ADDR + 0xf9e0001580UL + HOSE(h)) + +#define MCPCIA_W2_BASE(h) (IDENT_ADDR + 0xf9e0001600UL + HOSE(h)) +#define MCPCIA_W2_MASK(h) (IDENT_ADDR + 0xf9e0001640UL + HOSE(h)) +#define MCPCIA_T2_BASE(h) (IDENT_ADDR + 0xf9e0001680UL + HOSE(h)) + +#define MCPCIA_W3_BASE(h) (IDENT_ADDR + 0xf9e0001700UL + HOSE(h)) +#define MCPCIA_W3_MASK(h) (IDENT_ADDR + 0xf9e0001740UL + HOSE(h)) +#define MCPCIA_T3_BASE(h) (IDENT_ADDR + 0xf9e0001780UL + HOSE(h)) + +/* + * Memory spaces: + */ +#define MCPCIA_CONF(h) (IDENT_ADDR + 0xf9c0000000UL + HOSE(h)) +#define MCPCIA_IO(h) (IDENT_ADDR + 0xf980000000UL + HOSE(h)) +#define MCPCIA_SPARSE(h) (IDENT_ADDR + 0xf800000000UL + HOSE(h)) +#define MCPCIA_DENSE(h) (IDENT_ADDR + 0xf900000000UL + HOSE(h)) +#define _MCPCIA_IACK_SC(h) (IDENT_ADDR + 0xf9f0003f00UL + HOSE(h)) + +#define MCPCIA_HAE_ADDRESS MCPCIA_HAE_MEM(0) +#define MCPCIA_IACK_SC _MCPCIA_IACK_SC(0) + +/* + * Data structure for handling MCPCIA machine checks: + */ +struct el_MCPCIA_uncorrected_frame_mcheck { + struct el_common header; + struct el_common_EV5_uncorrectable_mcheck procdata; +}; + + +#ifdef __KERNEL__ + +#ifndef __EXTERN_INLINE +#define __EXTERN_INLINE extern inline +#define __IO_EXTERN_INLINE +#endif + +/* + * Translate physical memory address as seen on (PCI) bus into + * a kernel virtual address and vv. + */ + +__EXTERN_INLINE unsigned long mcpcia_virt_to_bus(void * address) +{ + return virt_to_phys(address) + MCPCIA_DMA_WIN_BASE; +} + +__EXTERN_INLINE void * mcpcia_bus_to_virt(unsigned long address) +{ + return phys_to_virt(address - MCPCIA_DMA_WIN_BASE); +} + +/* + * I/O functions: + * + * MCPCIA, the RAWHIDE family PCI/memory support chipset for the EV5 (21164) + * and EV56 (21164a) processors, can use either a sparse address mapping + * scheme, or the so-called byte-word PCI address space, to get at PCI memory + * and I/O. + * + * Unfortunately, we can't use BWIO with EV5, so for now, we always use SPARSE. + */ + +#define vucp volatile unsigned char * +#define vusp volatile unsigned short * +#define vip volatile int * +#define vuip volatile unsigned int * +#define vulp volatile unsigned long * + +#if 0 /* BWIO */ +__EXTERN_INLINE unsigned int mcpcia_bw_inb(unsigned long addr) +{ + return __kernel_ldbu(*(vucp)(addr+MCPCIA_BW_IO)); +} + +__EXTERN_INLINE void mcpcia_bw_outb(unsigned char b, unsigned long addr) +{ + __kernel_stb(b, *(vucp)(addr+MCPCIA_BW_IO)); + mb(); +} + +__EXTERN_INLINE unsigned int mcpcia_bw_inw(unsigned long addr) +{ + return __kernel_ldwu(*(vusp)(addr+MCPCIA_BW_IO)); +} + +__EXTERN_INLINE void mcpcia_bw_outw(unsigned short b, unsigned long addr) +{ + __kernel_stw(b, *(vusp)(addr+MCPCIA_BW_IO)); + mb(); +} + +__EXTERN_INLINE unsigned int mcpcia_bw_inl(unsigned long addr) +{ + return *(vuip)(addr+MCPCIA_BW_IO); +} + +__EXTERN_INLINE void mcpcia_bw_outl(unsigned int b, unsigned long addr) +{ + *(vuip)(addr+MCPCIA_BW_IO) = b; + mb(); +} +#endif + +__EXTERN_INLINE unsigned int mcpcia_inb(unsigned long in_addr) +{ + unsigned long addr = in_addr & 0xffffffffUL; + unsigned long hose = (in_addr >> 32) & 3; + long result = *(vip) ((addr << 5) + MCPCIA_IO(hose) + 0x00); + return __kernel_extbl(result, addr & 3); +} + +__EXTERN_INLINE void mcpcia_outb(unsigned char b, unsigned long in_addr) +{ + unsigned long addr = in_addr & 0xffffffffUL; + unsigned long hose = (in_addr >> 32) & 3; + unsigned int w; + + w = __kernel_insbl(b, addr & 3); + *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x00) = w; + mb(); +} + +__EXTERN_INLINE unsigned int mcpcia_inw(unsigned long in_addr) +{ + unsigned long addr = in_addr & 0xffffffffUL; + unsigned long hose = (in_addr >> 32) & 3; + long result = *(vip) ((addr << 5) + MCPCIA_IO(hose) + 0x08); + return __kernel_extwl(result, addr & 3); +} + +__EXTERN_INLINE void mcpcia_outw(unsigned short b, unsigned long in_addr) +{ + unsigned long addr = in_addr & 0xffffffffUL; + unsigned long hose = (in_addr >> 32) & 3; + unsigned int w; + + w = __kernel_inswl(b, addr & 3); + *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x08) = w; + mb(); +} + +__EXTERN_INLINE unsigned int mcpcia_inl(unsigned long in_addr) +{ + unsigned long addr = in_addr & 0xffffffffUL; + unsigned long hose = (in_addr >> 32) & 3; + return *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x18); +} + +__EXTERN_INLINE void mcpcia_outl(unsigned int b, unsigned long in_addr) +{ + unsigned long addr = in_addr & 0xffffffffUL; + unsigned long hose = (in_addr >> 32) & 3; + *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x18) = b; + mb(); +} + + +/* + * Memory functions. 64-bit and 32-bit accesses are done through + * dense memory space, everything else through sparse space. + * + * For reading and writing 8 and 16 bit quantities we need to + * go through one of the three sparse address mapping regions + * and use the HAE_MEM CSR to provide some bits of the address. + * The following few routines use only sparse address region 1 + * which gives 1Gbyte of accessible space which relates exactly + * to the amount of PCI memory mapping *into* system address space. + * See p 6-17 of the specification but it looks something like this: + * + * 21164 Address: + * + * 3 2 1 + * 9876543210987654321098765432109876543210 + * 1ZZZZ0.PCI.QW.Address............BBLL + * + * ZZ = SBZ + * BB = Byte offset + * LL = Transfer length + * + * PCI Address: + * + * 3 2 1 + * 10987654321098765432109876543210 + * HHH....PCI.QW.Address........ 00 + * + * HHH = 31:29 HAE_MEM CSR + * + */ + +#if 0 /* BWIO */ +__EXTERN_INLINE unsigned long mcpcia_bw_readb(unsigned long addr) +{ + return __kernel_ldbu(*(vucp)(addr+MCPCIA_BW_MEM)); +} + +__EXTERN_INLINE unsigned long mcpcia_bw_readw(unsigned long addr) +{ + return __kernel_ldbw(*(vusp)(addr+MCPCIA_BW_MEM)); +} + +__EXTERN_INLINE unsigned long mcpcia_bw_readl(unsigned long addr) +{ + return *(vuip)(addr + MCPCIA_BW_MEM); +} + +__EXTERN_INLINE unsigned long mcpcia_bw_readq(unsigned long addr) +{ + return *(vulp)(addr + MCPCIA_BW_MEM); +} + +__EXTERN_INLINE void mcpcia_bw_writeb(unsigned char b, unsigned long addr) +{ + __kernel_stb(b, *(vucp)(addr+MCPCIA_BW_MEM)); +} + +__EXTERN_INLINE void mcpcia_bw_writew(unsigned short b, unsigned long addr) +{ + __kernel_stw(b, *(vusp)(addr+MCPCIA_BW_MEM)); +} + +__EXTERN_INLINE void mcpcia_bw_writel(unsigned int b, unsigned long addr) +{ + *(vuip)(addr+MCPCIA_BW_MEM) = b; +} + +__EXTERN_INLINE void mcpcia_bw_writeq(unsigned long b, unsigned long addr) +{ + *(vulp)(addr+MCPCIA_BW_MEM) = b; +} +#endif + +__EXTERN_INLINE unsigned long mcpcia_srm_base(unsigned long addr) +{ + unsigned long mask, base; + unsigned long hose = (addr >> 32) & 3; + + if (addr >= alpha_mv.sm_base_r1 + && addr <= alpha_mv.sm_base_r1 + MCPCIA_MEM_R1_MASK) { + mask = MCPCIA_MEM_R1_MASK; + base = MCPCIA_SPARSE(hose); + } +#if 0 + /* FIXME FIXME FIXME: SPARSE_MEM_R2 and R3 are not defined? */ + else if (addr >= alpha_mv.sm_base_r2 + && addr <= alpha_mv.sm_base_r2 + MCPCIA_MEM_R2_MASK) { + mask = MCPCIA_MEM_R2_MASK; + base = MCPCIA_SPARSE_MEM_R2; + } + else if (addr >= alpha_mv.sm_base_r3 + && addr <= alpha_mv.sm_base_r3 + MCPCIA_MEM_R3_MASK) { + mask = MCPCIA_MEM_R3_MASK; + base = MCPCIA_SPARSE_MEM_R3; + } +#endif + else + { +#if 0 + printk("mcpcia: address 0x%lx not covered by HAE\n", addr); +#endif + return 0; + } + + return ((addr & mask) << 5) + base; +} + +__EXTERN_INLINE unsigned long mcpcia_srm_readb(unsigned long addr) +{ + unsigned long result, work; + + if ((work = mcpcia_srm_base(addr)) == 0) + return 0xff; + work += 0x00; /* add transfer length */ + + result = *(vip) work; + return __kernel_extbl(result, addr & 3); +} + +__EXTERN_INLINE unsigned long mcpcia_srm_readw(unsigned long addr) +{ + unsigned long result, work; + + if ((work = mcpcia_srm_base(addr)) == 0) + return 0xffff; + work += 0x08; /* add transfer length */ + + result = *(vip) work; + return __kernel_extwl(result, addr & 3); +} + +__EXTERN_INLINE void mcpcia_srm_writeb(unsigned char b, unsigned long addr) +{ + unsigned long work = mcpcia_srm_base(addr); + if (work) { + work += 0x00; /* add transfer length */ + *(vuip) work = b * 0x01010101; + } +} + +__EXTERN_INLINE void mcpcia_srm_writew(unsigned short b, unsigned long addr) +{ + unsigned long work = mcpcia_srm_base(addr); + if (work) { + work += 0x08; /* add transfer length */ + *(vuip) work = b * 0x00010001; + } +} + +__EXTERN_INLINE unsigned long mcpcia_readb(unsigned long in_addr) +{ + unsigned long addr = in_addr & 0xffffffffUL; + unsigned long hose = (in_addr >> 32) & 3; + unsigned long result, msb, work, temp; + + msb = addr & 0xE0000000UL; + temp = addr & MCPCIA_MEM_R1_MASK; + set_hae(msb); + + work = ((temp << 5) + MCPCIA_SPARSE(hose) + 0x00); + result = *(vip) work; + return __kernel_extbl(result, addr & 3); +} + +__EXTERN_INLINE unsigned long mcpcia_readw(unsigned long in_addr) +{ + unsigned long addr = in_addr & 0xffffffffUL; + unsigned long hose = (in_addr >> 32) & 3; + unsigned long result, msb, work, temp; + + msb = addr & 0xE0000000UL; + temp = addr & MCPCIA_MEM_R1_MASK ; + set_hae(msb); + + work = ((temp << 5) + MCPCIA_SPARSE(hose) + 0x08); + result = *(vip) work; + return __kernel_extwl(result, addr & 3); +} + +__EXTERN_INLINE void mcpcia_writeb(unsigned char b, unsigned long in_addr) +{ + unsigned long addr = in_addr & 0xffffffffUL; + unsigned long hose = (in_addr >> 32) & 3; + unsigned long msb; + + msb = addr & 0xE0000000; + addr &= MCPCIA_MEM_R1_MASK; + set_hae(msb); + + *(vuip) ((addr << 5) + MCPCIA_SPARSE(hose) + 0x00) = b * 0x01010101; +} + +__EXTERN_INLINE void mcpcia_writew(unsigned short b, unsigned long in_addr) +{ + unsigned long addr = in_addr & 0xffffffffUL; + unsigned long hose = (in_addr >> 32) & 3; + unsigned long msb ; + + msb = addr & 0xE0000000 ; + addr &= MCPCIA_MEM_R1_MASK ; + set_hae(msb); + + *(vuip) ((addr << 5) + MCPCIA_SPARSE(hose) + 0x08) = b * 0x00010001; +} + +__EXTERN_INLINE unsigned long mcpcia_readl(unsigned long in_addr) +{ + unsigned long addr = in_addr & 0xffffffffUL; + unsigned long hose = (in_addr >> 32) & 3; + return *(vuip) (addr + MCPCIA_DENSE(hose)); +} + +__EXTERN_INLINE unsigned long mcpcia_readq(unsigned long in_addr) +{ + unsigned long addr = in_addr & 0xffffffffUL; + unsigned long hose = (in_addr >> 32) & 3; + return *(vulp) (addr + MCPCIA_DENSE(hose)); +} + +__EXTERN_INLINE void mcpcia_writel(unsigned int b, unsigned long in_addr) +{ + unsigned long addr = in_addr & 0xffffffffUL; + unsigned long hose = (in_addr >> 32) & 3; + *(vuip) (addr + MCPCIA_DENSE(hose)) = b; +} + +__EXTERN_INLINE void mcpcia_writeq(unsigned long b, unsigned long in_addr) +{ + unsigned long addr = in_addr & 0xffffffffUL; + unsigned long hose = (in_addr >> 32) & 3; + *(vulp) (addr + MCPCIA_DENSE(hose)) = b; +} + +/* Find the DENSE memory area for a given bus address. */ + +__EXTERN_INLINE unsigned long mcpcia_dense_mem(unsigned long addr) +{ + return MCPCIA_DENSE((addr >> 32) & 3); +} + +#undef vucp +#undef vusp +#undef vip +#undef vuip +#undef vulp + +#ifdef __WANT_IO_DEF + +#define virt_to_bus mcpcia_virt_to_bus +#define bus_to_virt mcpcia_bus_to_virt + +#if 0 /* BWIO */ +# define __inb mcpcia_bw_inb +# define __inw mcpcia_bw_inw +# define __inl mcpcia_bw_inl +# define __outb mcpcia_bw_outb +# define __outw mcpcia_bw_outw +# define __outl mcpcia_bw_outl +# define __readb mcpcia_bw_readb +# define __readw mcpcia_bw_readw +# define __writeb mcpcia_bw_writeb +# define __writew mcpcia_bw_writew +# define __readl mcpcia_bw_readl +# define __readq mcpcia_bw_readq +# define __writel mcpcia_bw_writel +# define __writeq mcpcia_bw_writeq +#else +# define __inb mcpcia_inb +# define __inw mcpcia_inw +# define __inl mcpcia_inl +# define __outb mcpcia_outb +# define __outw mcpcia_outw +# define __outl mcpcia_outl +# ifdef CONFIG_ALPHA_SRM_SETUP +# define __readb mcpcia_srm_readb +# define __readw mcpcia_srm_readw +# define __writeb mcpcia_srm_writeb +# define __writew mcpcia_srm_writew +# else +# define __readb mcpcia_readb +# define __readw mcpcia_readw +# define __writeb mcpcia_writeb +# define __writew mcpcia_writew +# endif +# define __readl mcpcia_readl +# define __readq mcpcia_readq +# define __writel mcpcia_writel +# define __writeq mcpcia_writeq +#endif /* BWIO */ + +#define dense_mem mcpcia_dense_mem + +#if 0 /* BWIO */ +# define inb(port) __inb((port)) +# define inw(port) __inw((port)) +# define inl(port) __inl((port)) +# define outb(x, port) __outb((x),(port)) +# define outw(x, port) __outw((x),(port)) +# define outl(x, port) __outl((x),(port)) +# define readb(addr) __readb((addr)) +# define readw(addr) __readw((addr)) +# define writeb(b, addr) __writeb((b),(addr)) +# define writew(b, addr) __writew((b),(addr)) +#else +# define inb(port) \ + (__builtin_constant_p((port))?__inb(port):_inb(port)) +# define outb(x, port) \ + (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port))) +#endif /* BWIO */ + +#define readl(a) __readl((unsigned long)(a)) +#define readq(a) __readq((unsigned long)(a)) +#define writel(v,a) __writel((v),(unsigned long)(a)) +#define writeq(v,a) __writeq((v),(unsigned long)(a)) + +#endif /* __WANT_IO_DEF */ + +#ifdef __IO_EXTERN_INLINE +#undef __EXTERN_INLINE +#undef __IO_EXTERN_INLINE +#endif + +#endif /* __KERNEL__ */ + +#endif /* __ALPHA_MCPCIA__H__ */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/core_pyxis.h linux/include/asm-alpha/core_pyxis.h --- v2.1.115/linux/include/asm-alpha/core_pyxis.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-alpha/core_pyxis.h Sun Aug 9 12:09:06 1998 @@ -0,0 +1,684 @@ +#ifndef __ALPHA_PYXIS__H__ +#define __ALPHA_PYXIS__H__ + +#include +#include +#include + +/* + * PYXIS is the internal name for a core logic chipset which provides + * memory controller and PCI access for the 21164A chip based systems. + * + * This file is based on: + * + * Pyxis Chipset Spec + * 14-Jun-96 + * Rev. X2.0 + * + */ + +/*------------------------------------------------------------------------** +** ** +** I/O procedures ** +** ** +** inport[b|w|t|l], outport[b|w|t|l] 8:16:24:32 IO xfers ** +** inportbxt: 8 bits only ** +** inport: alias of inportw ** +** outport: alias of outportw ** +** ** +** inmem[b|w|t|l], outmem[b|w|t|l] 8:16:24:32 ISA memory xfers ** +** inmembxt: 8 bits only ** +** inmem: alias of inmemw ** +** outmem: alias of outmemw ** +** ** +**------------------------------------------------------------------------*/ + + +/* CIA ADDRESS BIT DEFINITIONS + * + * 3 3 3 3|3 3 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 + * 9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |1| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |0|0|0| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | \_/ \_/ + * | | | + * +-- IO space, not cached. Byte Enable --+ | + * Transfer Length --+ + * + * + * + * Byte Transfer + * Enable Length Transfer Byte Address + * adr<6:5> adr<4:3> Length Enable Adder + * --------------------------------------------- + * 00 00 Byte 1110 0x000 + * 01 00 Byte 1101 0x020 + * 10 00 Byte 1011 0x040 + * 11 00 Byte 0111 0x060 + * + * 00 01 Word 1100 0x008 + * 01 01 Word 1001 0x028 <= Not supported in this code. + * 10 01 Word 0011 0x048 + * + * 00 10 Tribyte 1000 0x010 + * 01 10 Tribyte 0001 0x030 + * + * 10 11 Longword 0000 0x058 + * + * Note that byte enables are asserted low. + * + */ + +#define PYXIS_MEM_R1_MASK 0x1fffffff /* SPARSE Mem region 1 mask is 29 bits */ +#define PYXIS_MEM_R2_MASK 0x07ffffff /* SPARSE Mem region 2 mask is 27 bits */ +#define PYXIS_MEM_R3_MASK 0x03ffffff /* SPARSE Mem region 3 mask is 26 bits */ + +#define PYXIS_DMA_WIN_BASE_DEFAULT (1024*1024*1024) +#define PYXIS_DMA_WIN_SIZE_DEFAULT (1024*1024*1024) + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) +#define PYXIS_DMA_WIN_BASE alpha_mv.dma_win_base +#define PYXIS_DMA_WIN_SIZE alpha_mv.dma_win_size +#else +#define PYXIS_DMA_WIN_BASE PYXIS_DMA_WIN_BASE_DEFAULT +#define PYXIS_DMA_WIN_SIZE PYXIS_DMA_WIN_SIZE_DEFAULT +#endif + +/* + * General Registers + */ +#define PYXIS_REV (IDENT_ADDR + 0x8740000080UL) +#define PYXIS_PCI_LAT (IDENT_ADDR + 0x87400000C0UL) +#define PYXIS_CTRL (IDENT_ADDR + 0x8740000100UL) +#define PYXIS_CTRL1 (IDENT_ADDR + 0x8740000140UL) +#define PYXIS_FLASH_CTRL (IDENT_ADDR + 0x8740000200UL) + +#define PYXIS_HAE_MEM (IDENT_ADDR + 0x8740000400UL) +#define PYXIS_HAE_IO (IDENT_ADDR + 0x8740000440UL) +#define PYXIS_CFG (IDENT_ADDR + 0x8740000480UL) + +/* + * Diagnostic Registers + */ +#define PYXIS_DIAG (IDENT_ADDR + 0x8740002000UL) +#define PYXIS_DIAG_CHECK (IDENT_ADDR + 0x8740003000UL) + +/* + * Performance Monitor registers + */ +#define PYXIS_PERF_MONITOR (IDENT_ADDR + 0x8740004000UL) +#define PYXIS_PERF_CONTROL (IDENT_ADDR + 0x8740004040UL) + +/* + * Error registers + */ +#define PYXIS_ERR (IDENT_ADDR + 0x8740008200UL) +#define PYXIS_STAT (IDENT_ADDR + 0x8740008240UL) +#define PYXIS_ERR_MASK (IDENT_ADDR + 0x8740008280UL) +#define PYXIS_SYN (IDENT_ADDR + 0x8740008300UL) +#define PYXIS_ERR_DATA (IDENT_ADDR + 0x8740008308UL) + +#define PYXIS_MEAR (IDENT_ADDR + 0x8740008400UL) +#define PYXIS_MESR (IDENT_ADDR + 0x8740008440UL) +#define PYXIS_PCI_ERR0 (IDENT_ADDR + 0x8740008800UL) +#define PYXIS_PCI_ERR1 (IDENT_ADDR + 0x8740008840UL) +#define PYXIS_PCI_ERR2 (IDENT_ADDR + 0x8740008880UL) + +/* + * PCI Address Translation Registers. + */ +#define PYXIS_TBIA (IDENT_ADDR + 0x8760000100UL) + +#define PYXIS_W0_BASE (IDENT_ADDR + 0x8760000400UL) +#define PYXIS_W0_MASK (IDENT_ADDR + 0x8760000440UL) +#define PYXIS_T0_BASE (IDENT_ADDR + 0x8760000480UL) + +#define PYXIS_W1_BASE (IDENT_ADDR + 0x8760000500UL) +#define PYXIS_W1_MASK (IDENT_ADDR + 0x8760000540UL) +#define PYXIS_T1_BASE (IDENT_ADDR + 0x8760000580UL) + +#define PYXIS_W2_BASE (IDENT_ADDR + 0x8760000600UL) +#define PYXIS_W2_MASK (IDENT_ADDR + 0x8760000640UL) +#define PYXIS_T2_BASE (IDENT_ADDR + 0x8760000680UL) + +#define PYXIS_W3_BASE (IDENT_ADDR + 0x8760000700UL) +#define PYXIS_W3_MASK (IDENT_ADDR + 0x8760000740UL) +#define PYXIS_T3_BASE (IDENT_ADDR + 0x8760000780UL) + +/* + * Memory Control registers + */ +#define PYXIS_MCR (IDENT_ADDR + 0x8750000000UL) + +/* + * Memory spaces: + */ +#define PYXIS_IACK_SC (IDENT_ADDR + 0x8720000000UL) +#define PYXIS_CONF (IDENT_ADDR + 0x8700000000UL) +#define PYXIS_IO (IDENT_ADDR + 0x8580000000UL) +#define PYXIS_SPARSE_MEM (IDENT_ADDR + 0x8000000000UL) +#define PYXIS_SPARSE_MEM_R2 (IDENT_ADDR + 0x8400000000UL) +#define PYXIS_SPARSE_MEM_R3 (IDENT_ADDR + 0x8500000000UL) +#define PYXIS_DENSE_MEM (IDENT_ADDR + 0x8600000000UL) + +/* + * Byte/Word PCI Memory Spaces: + */ +#define PYXIS_BW_MEM (IDENT_ADDR + 0x8800000000UL) +#define PYXIS_BW_IO (IDENT_ADDR + 0x8900000000UL) +#define PYXIS_BW_CFG_0 (IDENT_ADDR + 0x8a00000000UL) +#define PYXIS_BW_CFG_1 (IDENT_ADDR + 0x8b00000000UL) + +/* + * Interrupt Control registers + */ +#define PYXIS_INT_REQ (IDENT_ADDR + 0x87A0000000UL) +#define PYXIS_INT_MASK (IDENT_ADDR + 0x87A0000040UL) +#define PYXIS_INT_HILO (IDENT_ADDR + 0x87A00000C0UL) +#define PYXIS_INT_ROUTE (IDENT_ADDR + 0x87A0000140UL) +#define PYXIS_GPO (IDENT_ADDR + 0x87A0000180UL) +#define PYXIS_INT_CNFG (IDENT_ADDR + 0x87A00001C0UL) +#define PYXIS_RT_COUNT (IDENT_ADDR + 0x87A0000200UL) +#define PYXIS_INT_TIME (IDENT_ADDR + 0x87A0000240UL) +#define PYXIS_IIC_CTRL (IDENT_ADDR + 0x87A00002C0UL) + +/* + * Bit definitions for I/O Controller status register 0: + */ +#define PYXIS_STAT0_CMD 0xf +#define PYXIS_STAT0_ERR (1<<4) +#define PYXIS_STAT0_LOST (1<<5) +#define PYXIS_STAT0_THIT (1<<6) +#define PYXIS_STAT0_TREF (1<<7) +#define PYXIS_STAT0_CODE_SHIFT 8 +#define PYXIS_STAT0_CODE_MASK 0x7 +#define PYXIS_STAT0_P_NBR_SHIFT 13 +#define PYXIS_STAT0_P_NBR_MASK 0x7ffff + +#define PYXIS_HAE_ADDRESS PYXIS_HAE_MEM + +/* + * Data structure for handling PYXIS machine checks: + */ +struct el_PYXIS_sysdata_mcheck { + u_long coma_gcr; + u_long coma_edsr; + u_long coma_ter; + u_long coma_elar; + u_long coma_ehar; + u_long coma_ldlr; + u_long coma_ldhr; + u_long coma_base0; + u_long coma_base1; + u_long coma_base2; + u_long coma_cnfg0; + u_long coma_cnfg1; + u_long coma_cnfg2; + u_long epic_dcsr; + u_long epic_pear; + u_long epic_sear; + u_long epic_tbr1; + u_long epic_tbr2; + u_long epic_pbr1; + u_long epic_pbr2; + u_long epic_pmr1; + u_long epic_pmr2; + u_long epic_harx1; + u_long epic_harx2; + u_long epic_pmlt; + u_long epic_tag0; + u_long epic_tag1; + u_long epic_tag2; + u_long epic_tag3; + u_long epic_tag4; + u_long epic_tag5; + u_long epic_tag6; + u_long epic_tag7; + u_long epic_data0; + u_long epic_data1; + u_long epic_data2; + u_long epic_data3; + u_long epic_data4; + u_long epic_data5; + u_long epic_data6; + u_long epic_data7; +}; + + +#ifdef __KERNEL__ + +#ifndef __EXTERN_INLINE +#define __EXTERN_INLINE extern inline +#define __IO_EXTERN_INLINE +#endif + +/* + * Translate physical memory address as seen on (PCI) bus into + * a kernel virtual address and vv. + */ + +/* Ruffian doesn't do 1G PCI window */ + +static inline unsigned long pyxis_ruffian_virt_to_bus(void * address) +{ + return virt_to_phys(address); +} + +static inline void * pyxis_ruffian_bus_to_virt(unsigned long address) +{ + return phys_to_virt(address); +} + +__EXTERN_INLINE unsigned long pyxis_virt_to_bus(void * address) +{ + return virt_to_phys(address) + PYXIS_DMA_WIN_BASE; +} + +__EXTERN_INLINE void * pyxis_bus_to_virt(unsigned long address) +{ + return phys_to_virt(address - PYXIS_DMA_WIN_BASE); +} + + +/* + * I/O functions: + * + * PYXIS, the 21174 PCI/memory support chipset for the EV56 (21164A) + * and PCA56 (21164PC) processors, can use either a sparse address + * mapping scheme, or the so-called byte-word PCI address space, to + * get at PCI memory and I/O. + */ + +#define vucp volatile unsigned char * +#define vusp volatile unsigned short * +#define vip volatile int * +#define vuip volatile unsigned int * +#define vulp volatile unsigned long * + +__EXTERN_INLINE unsigned int pyxis_bw_inb(unsigned long addr) +{ + return __kernel_ldbu(*(vucp)(addr+PYXIS_BW_IO)); +} + +__EXTERN_INLINE void pyxis_bw_outb(unsigned char b, unsigned long addr) +{ + __kernel_stb(b, *(vucp)(addr+PYXIS_BW_IO)); + mb(); +} + +__EXTERN_INLINE unsigned int pyxis_bw_inw(unsigned long addr) +{ + return __kernel_ldwu(*(vusp)(addr+PYXIS_BW_IO)); +} + +__EXTERN_INLINE void pyxis_bw_outw(unsigned short b, unsigned long addr) +{ + __kernel_stw(b, *(vusp)(addr+PYXIS_BW_IO)); + mb(); +} + +__EXTERN_INLINE unsigned int pyxis_bw_inl(unsigned long addr) +{ + return *(vuip)(addr+PYXIS_BW_IO); +} + +__EXTERN_INLINE void pyxis_bw_outl(unsigned int b, unsigned long addr) +{ + *(vuip)(addr+PYXIS_BW_IO) = b; + mb(); +} + +__EXTERN_INLINE unsigned int pyxis_inb(unsigned long addr) +{ + long result = *(vip) ((addr << 5) + PYXIS_IO + 0x00); + return __kernel_extbl(result, addr & 3); +} + +__EXTERN_INLINE void pyxis_outb(unsigned char b, unsigned long addr) +{ + unsigned int w; + + w = __kernel_insbl(b, addr & 3); + *(vuip) ((addr << 5) + PYXIS_IO + 0x00) = w; + mb(); +} + +__EXTERN_INLINE unsigned int pyxis_inw(unsigned long addr) +{ + long result = *(vip) ((addr << 5) + PYXIS_IO + 0x08); + return __kernel_extwl(result, addr & 3); +} + +__EXTERN_INLINE void pyxis_outw(unsigned short b, unsigned long addr) +{ + unsigned int w; + + w = __kernel_inswl(b, addr & 3); + *(vuip) ((addr << 5) + PYXIS_IO + 0x08) = w; + mb(); +} + +__EXTERN_INLINE unsigned int pyxis_inl(unsigned long addr) +{ + return *(vuip) ((addr << 5) + PYXIS_IO + 0x18); +} + +__EXTERN_INLINE void pyxis_outl(unsigned int b, unsigned long addr) +{ + *(vuip) ((addr << 5) + PYXIS_IO + 0x18) = b; + mb(); +} + + +/* + * Memory functions. 64-bit and 32-bit accesses are done through + * dense memory space, everything else through sparse space. + * + * For reading and writing 8 and 16 bit quantities we need to + * go through one of the three sparse address mapping regions + * and use the HAE_MEM CSR to provide some bits of the address. + * The following few routines use only sparse address region 1 + * which gives 1Gbyte of accessible space which relates exactly + * to the amount of PCI memory mapping *into* system address space. + * See p 6-17 of the specification but it looks something like this: + * + * 21164 Address: + * + * 3 2 1 + * 9876543210987654321098765432109876543210 + * 1ZZZZ0.PCI.QW.Address............BBLL + * + * ZZ = SBZ + * BB = Byte offset + * LL = Transfer length + * + * PCI Address: + * + * 3 2 1 + * 10987654321098765432109876543210 + * HHH....PCI.QW.Address........ 00 + * + * HHH = 31:29 HAE_MEM CSR + * + */ + +__EXTERN_INLINE unsigned long pyxis_bw_readb(unsigned long addr) +{ + return __kernel_ldbu(*(vucp)(addr+PYXIS_BW_MEM)); +} + +__EXTERN_INLINE unsigned long pyxis_bw_readw(unsigned long addr) +{ + return __kernel_ldwu(*(vusp)(addr+PYXIS_BW_MEM)); +} + +__EXTERN_INLINE unsigned long pyxis_bw_readl(unsigned long addr) +{ + return *(vuip)(addr+PYXIS_BW_MEM); +} + +__EXTERN_INLINE unsigned long pyxis_bw_readq(unsigned long addr) +{ + return *(vulp)(addr+PYXIS_BW_MEM); +} + +__EXTERN_INLINE void pyxis_bw_writeb(unsigned char b, unsigned long addr) +{ + __kernel_stb(b, *(vucp)(addr+PYXIS_BW_MEM)); + mb(); +} + +__EXTERN_INLINE void pyxis_bw_writew(unsigned short b, unsigned long addr) +{ + __kernel_stw(b, *(vusp)(addr+PYXIS_BW_MEM)); + mb(); +} + +__EXTERN_INLINE void pyxis_bw_writel(unsigned int b, unsigned long addr) +{ + *(vuip)(addr+PYXIS_BW_MEM) = b; +} + +__EXTERN_INLINE void pyxis_bw_writeq(unsigned long b, unsigned long addr) +{ + *(vulp)(addr+PYXIS_BW_MEM) = b; +} + +__EXTERN_INLINE unsigned long pyxis_srm_base(unsigned long addr) +{ + unsigned long mask, base; + + if (addr >= alpha_mv.sm_base_r1 + && addr <= alpha_mv.sm_base_r1 + PYXIS_MEM_R1_MASK) { + mask = PYXIS_MEM_R1_MASK; + base = PYXIS_SPARSE_MEM; + } + else if (addr >= alpha_mv.sm_base_r2 + && addr <= alpha_mv.sm_base_r2 + PYXIS_MEM_R2_MASK) { + mask = PYXIS_MEM_R2_MASK; + base = PYXIS_SPARSE_MEM_R2; + } + else if (addr >= alpha_mv.sm_base_r3 + && addr <= alpha_mv.sm_base_r3 + PYXIS_MEM_R3_MASK) { + mask = PYXIS_MEM_R3_MASK; + base = PYXIS_SPARSE_MEM_R3; + } + else + { +#if 0 + printk("pyxis: address 0x%lx not covered by HAE\n", addr); +#endif + return 0; + } + + return ((addr & mask) << 5) + base; +} + +__EXTERN_INLINE unsigned long pyxis_srm_readb(unsigned long addr) +{ + unsigned long result, work; + + if ((work = pyxis_srm_base(addr)) == 0) + return 0xff; + work += 0x00; /* add transfer length */ + + result = *(vip) work; + return __kernel_extbl(result, addr & 3); +} + +__EXTERN_INLINE unsigned long pyxis_srm_readw(unsigned long addr) +{ + unsigned long result, work; + + if ((work = pyxis_srm_base(addr)) == 0) + return 0xffff; + work += 0x08; /* add transfer length */ + + result = *(vip) work; + return __kernel_extwl(result, addr & 3); +} + +__EXTERN_INLINE void pyxis_srm_writeb(unsigned char b, unsigned long addr) +{ + unsigned long work = pyxis_srm_base(addr); + if (work) { + work += 0x00; /* add transfer length */ + *(vuip) work = b * 0x01010101; + } +} + +__EXTERN_INLINE void pyxis_srm_writew(unsigned short b, unsigned long addr) +{ + unsigned long work = pyxis_srm_base(addr); + if (work) { + work += 0x08; /* add transfer length */ + *(vuip) work = b * 0x00010001; + } +} + +__EXTERN_INLINE unsigned long pyxis_readb(unsigned long addr) +{ + unsigned long result, msb, work, temp; + + msb = addr & 0xE0000000UL; + temp = addr & PYXIS_MEM_R1_MASK ; + set_hae(msb); + + work = ((temp << 5) + PYXIS_SPARSE_MEM + 0x00); + result = *(vip) work; + return __kernel_extbl(result, addr & 3); +} + +__EXTERN_INLINE unsigned long pyxis_readw(unsigned long addr) +{ + unsigned long result, msb, work, temp; + + msb = addr & 0xE0000000UL; + temp = addr & PYXIS_MEM_R1_MASK ; + set_hae(msb); + + work = ((temp << 5) + PYXIS_SPARSE_MEM + 0x08); + result = *(vip) work; + return __kernel_extwl(result, addr & 3); +} + +__EXTERN_INLINE void pyxis_writeb(unsigned char b, unsigned long addr) +{ + unsigned long msb ; + + msb = addr & 0xE0000000 ; + addr &= PYXIS_MEM_R1_MASK ; + set_hae(msb); + + *(vuip) ((addr << 5) + PYXIS_SPARSE_MEM + 0x00) = b * 0x01010101; +} + +__EXTERN_INLINE void pyxis_writew(unsigned short b, unsigned long addr) +{ + unsigned long msb ; + + msb = addr & 0xE0000000 ; + addr &= PYXIS_MEM_R1_MASK ; + set_hae(msb); + + *(vuip) ((addr << 5) + PYXIS_SPARSE_MEM + 0x08) = b * 0x00010001; +} + +__EXTERN_INLINE unsigned long pyxis_readl(unsigned long addr) +{ + return *(vuip) (addr + PYXIS_DENSE_MEM); +} + +__EXTERN_INLINE unsigned long pyxis_readq(unsigned long addr) +{ + return *(vulp) (addr + PYXIS_DENSE_MEM); +} + +__EXTERN_INLINE void pyxis_writel(unsigned int b, unsigned long addr) +{ + *(vuip) (addr + PYXIS_DENSE_MEM) = b; +} + +__EXTERN_INLINE void pyxis_writeq(unsigned long b, unsigned long addr) +{ + *(vulp) (addr + PYXIS_DENSE_MEM) = b; +} + +/* Find the DENSE memory area for a given bus address. */ + +__EXTERN_INLINE unsigned long pyxis_dense_mem(unsigned long addr) +{ + return PYXIS_DENSE_MEM; +} + +#undef vucp +#undef vusp +#undef vip +#undef vuip +#undef vulp + +#ifdef __WANT_IO_DEF + +#ifdef CONFIG_ALPHA_RUFFIAN +#define virt_to_bus pyxis_ruffian_virt_to_bus +#define bus_to_virt pyxis_ruffian_bus_to_virt +#else +#define virt_to_bus pyxis_virt_to_bus +#define bus_to_virt pyxis_bus_to_virt +#endif + +#ifdef BWIO_ENABLED +# define __inb pyxis_bw_inb +# define __inw pyxis_bw_inw +# define __inl pyxis_bw_inl +# define __outb pyxis_bw_outb +# define __outw pyxis_bw_outw +# define __outl pyxis_bw_outl +# define __readb pyxis_bw_readb +# define __readw pyxis_bw_readw +# define __writeb pyxis_bw_writeb +# define __writew pyxis_bw_writew +# define __readl pyxis_bw_readl +# define __readq pyxis_bw_readq +# define __writel pyxis_bw_writel +# define __writeq pyxis_bw_writeq +#else +# define __inb pyxis_inb +# define __inw pyxis_inw +# define __inl pyxis_inl +# define __outb pyxis_outb +# define __outw pyxis_outw +# define __outl pyxis_outl +# ifdef CONFIG_ALPHA_SRM_SETUP +# define __readb pyxis_srm_readb +# define __readw pyxis_srm_readw +# define __writeb pyxis_srm_writeb +# define __writew pyxis_srm_writew +# else +# define __readb pyxis_readb +# define __readw pyxis_readw +# define __writeb pyxis_writeb +# define __writew pyxis_writew +# endif +# define __readl pyxis_readl +# define __readq pyxis_readq +# define __writel pyxis_writel +# define __writeq pyxis_writeq +#endif /* BWIO */ + +#define dense_mem pyxis_dense_mem + +#ifdef BWIO_ENABLED +# define inb(port) __inb((port)) +# define inw(port) __inw((port)) +# define inl(port) __inl((port)) +# define outb(x, port) __outb((x),(port)) +# define outw(x, port) __outw((x),(port)) +# define outl(x, port) __outl((x),(port)) +# define readb(addr) __readb((addr)) +# define readw(addr) __readw((addr)) +# define writeb(b, addr) __writeb((b),(addr)) +# define writew(b, addr) __writew((b),(addr)) +#else +# define inb(port) \ + (__builtin_constant_p((port))?__inb(port):_inb(port)) +# define outb(x, port) \ + (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port))) +#endif /* BWIO */ + +#define readl(a) __readl((unsigned long)(a)) +#define readq(a) __readq((unsigned long)(a)) +#define writel(v,a) __writel((v),(unsigned long)(a)) +#define writeq(v,a) __writeq((v),(unsigned long)(a)) + +#endif /* __WANT_IO_DEF */ + +#ifdef __IO_EXTERN_INLINE +#undef __EXTERN_INLINE +#undef __IO_EXTERN_INLINE +#endif + +#endif /* __KERNEL__ */ + +#endif /* __ALPHA_PYXIS__H__ */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/core_t2.h linux/include/asm-alpha/core_t2.h --- v2.1.115/linux/include/asm-alpha/core_t2.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-alpha/core_t2.h Sun Aug 9 12:09:06 1998 @@ -0,0 +1,691 @@ +#ifndef __ALPHA_T2__H__ +#define __ALPHA_T2__H__ + +#include +#include +#include + + +/* + * T2 is the internal name for the core logic chipset which provides + * memory controller and PCI access for the SABLE-based systems. + * + * This file is based on: + * + * SABLE I/O Specification + * Revision/Update Information: 1.3 + * + * jestabro@amt.tay1.dec.com Initial Version. + * + */ + +#define T2_MEM_R1_MASK 0x03ffffff /* Mem sparse region 1 mask is 26 bits */ + +#define T2_DMA_WIN_BASE_DEFAULT (1024*1024*1024) +#define T2_DMA_WIN_SIZE_DEFAULT (1024*1024*1024) + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) +#define T2_DMA_WIN_BASE alpha_mv.dma_win_base +#define T2_DMA_WIN_SIZE alpha_mv.dma_win_size +#else +#define T2_DMA_WIN_BASE T2_DMA_WIN_BASE_DEFAULT +#define T2_DMA_WIN_SIZE T2_DMA_WIN_SIZE_DEFAULT +#endif + +/* GAMMA-SABLE is a SABLE with EV5-based CPUs */ +#define _GAMMA_BIAS 0x8000000000UL + +#if defined(CONFIG_ALPHA_GENERIC) +#define GAMMA_BIAS alpha_mv.sys.t2.gamma_bias +#elif defined(CONFIG_ALPHA_GAMMA) +#define GAMMA_BIAS _GAMMA_BIAS +#else +#define GAMMA_BIAS 0 +#endif + +/* + * Memory spaces: + */ +#define T2_CONF (IDENT_ADDR + GAMMA_BIAS + 0x390000000UL) +#define T2_IO (IDENT_ADDR + GAMMA_BIAS + 0x3a0000000UL) +#define T2_SPARSE_MEM (IDENT_ADDR + GAMMA_BIAS + 0x200000000UL) +#define T2_DENSE_MEM (IDENT_ADDR + GAMMA_BIAS + 0x3c0000000UL) + +#define T2_IOCSR (IDENT_ADDR + GAMMA_BIAS + 0x38e000000UL) +#define T2_CERR1 (IDENT_ADDR + GAMMA_BIAS + 0x38e000020UL) +#define T2_CERR2 (IDENT_ADDR + GAMMA_BIAS + 0x38e000040UL) +#define T2_CERR3 (IDENT_ADDR + GAMMA_BIAS + 0x38e000060UL) +#define T2_PERR1 (IDENT_ADDR + GAMMA_BIAS + 0x38e000080UL) +#define T2_PERR2 (IDENT_ADDR + GAMMA_BIAS + 0x38e0000a0UL) +#define T2_PSCR (IDENT_ADDR + GAMMA_BIAS + 0x38e0000c0UL) +#define T2_HAE_1 (IDENT_ADDR + GAMMA_BIAS + 0x38e0000e0UL) +#define T2_HAE_2 (IDENT_ADDR + GAMMA_BIAS + 0x38e000100UL) +#define T2_HBASE (IDENT_ADDR + GAMMA_BIAS + 0x38e000120UL) +#define T2_WBASE1 (IDENT_ADDR + GAMMA_BIAS + 0x38e000140UL) +#define T2_WMASK1 (IDENT_ADDR + GAMMA_BIAS + 0x38e000160UL) +#define T2_TBASE1 (IDENT_ADDR + GAMMA_BIAS + 0x38e000180UL) +#define T2_WBASE2 (IDENT_ADDR + GAMMA_BIAS + 0x38e0001a0UL) +#define T2_WMASK2 (IDENT_ADDR + GAMMA_BIAS + 0x38e0001c0UL) +#define T2_TBASE2 (IDENT_ADDR + GAMMA_BIAS + 0x38e0001e0UL) +#define T2_TLBBR (IDENT_ADDR + GAMMA_BIAS + 0x38e000200UL) + +#define T2_HAE_3 (IDENT_ADDR + GAMMA_BIAS + 0x38e000240UL) +#define T2_HAE_4 (IDENT_ADDR + GAMMA_BIAS + 0x38e000260UL) + +#define T2_HAE_ADDRESS T2_HAE_1 + +/* T2 CSRs are in the non-cachable primary IO space from 3.8000.0000 to + 3.8fff.ffff + * + * +--------------+ 3 8000 0000 + * | CPU 0 CSRs | + * +--------------+ 3 8100 0000 + * | CPU 1 CSRs | + * +--------------+ 3 8200 0000 + * | CPU 2 CSRs | + * +--------------+ 3 8300 0000 + * | CPU 3 CSRs | + * +--------------+ 3 8400 0000 + * | CPU Reserved | + * +--------------+ 3 8700 0000 + * | Mem Reserved | + * +--------------+ 3 8800 0000 + * | Mem 0 CSRs | + * +--------------+ 3 8900 0000 + * | Mem 1 CSRs | + * +--------------+ 3 8a00 0000 + * | Mem 2 CSRs | + * +--------------+ 3 8b00 0000 + * | Mem 3 CSRs | + * +--------------+ 3 8c00 0000 + * | Mem Reserved | + * +--------------+ 3 8e00 0000 + * | PCI Bridge | + * +--------------+ 3 8f00 0000 + * | Expansion IO | + * +--------------+ 3 9000 0000 + * + * + */ +#define T2_CPU0_BASE (IDENT_ADDR + GAMMA_BIAS + 0x380000000L) +#define T2_CPU1_BASE (IDENT_ADDR + GAMMA_BIAS + 0x381000000L) +#define T2_CPU2_BASE (IDENT_ADDR + GAMMA_BIAS + 0x382000000L) +#define T2_CPU3_BASE (IDENT_ADDR + GAMMA_BIAS + 0x383000000L) +#define T2_MEM0_BASE (IDENT_ADDR + GAMMA_BIAS + 0x388000000L) +#define T2_MEM1_BASE (IDENT_ADDR + GAMMA_BIAS + 0x389000000L) +#define T2_MEM2_BASE (IDENT_ADDR + GAMMA_BIAS + 0x38a000000L) +#define T2_MEM3_BASE (IDENT_ADDR + GAMMA_BIAS + 0x38b000000L) + + +/* + * Sable CPU Module CSRS + * + * These are CSRs for hardware other than the CPU chip on the CPU module. + * The CPU module has Backup Cache control logic, Cbus control logic, and + * interrupt control logic on it. There is a duplicate tag store to speed + * up maintaining cache coherency. + */ + +struct sable_cpu_csr { + unsigned long bcc; long fill_00[3]; /* Backup Cache Control */ + unsigned long bcce; long fill_01[3]; /* Backup Cache Correctable Error */ + unsigned long bccea; long fill_02[3]; /* B-Cache Corr Err Address Latch */ + unsigned long bcue; long fill_03[3]; /* B-Cache Uncorrectable Error */ + unsigned long bcuea; long fill_04[3]; /* B-Cache Uncorr Err Addr Latch */ + unsigned long dter; long fill_05[3]; /* Duplicate Tag Error */ + unsigned long cbctl; long fill_06[3]; /* CBus Control */ + unsigned long cbe; long fill_07[3]; /* CBus Error */ + unsigned long cbeal; long fill_08[3]; /* CBus Error Addr Latch low */ + unsigned long cbeah; long fill_09[3]; /* CBus Error Addr Latch high */ + unsigned long pmbx; long fill_10[3]; /* Processor Mailbox */ + unsigned long ipir; long fill_11[3]; /* Inter-Processor Int Request */ + unsigned long sic; long fill_12[3]; /* System Interrupt Clear */ + unsigned long adlk; long fill_13[3]; /* Address Lock (LDxL/STxC) */ + unsigned long madrl; long fill_14[3]; /* CBus Miss Address */ + unsigned long rev; long fill_15[3]; /* CMIC Revision */ +}; + +/* + * Data structure for handling T2 machine checks: + */ +struct el_t2_frame_header { + unsigned int elcf_fid; /* Frame ID (from above) */ + unsigned int elcf_size; /* Size of frame in bytes */ +}; + +struct el_t2_procdata_mcheck { + unsigned long elfmc_paltemp[32]; /* PAL TEMP REGS. */ + /* EV4-specific fields */ + unsigned long elfmc_exc_addr; /* Addr of excepting insn. */ + unsigned long elfmc_exc_sum; /* Summary of arith traps. */ + unsigned long elfmc_exc_mask; /* Exception mask (from exc_sum). */ + unsigned long elfmc_iccsr; /* IBox hardware enables. */ + unsigned long elfmc_pal_base; /* Base address for PALcode. */ + unsigned long elfmc_hier; /* Hardware Interrupt Enable. */ + unsigned long elfmc_hirr; /* Hardware Interrupt Request. */ + unsigned long elfmc_mm_csr; /* D-stream fault info. */ + unsigned long elfmc_dc_stat; /* D-cache status (ECC/Parity Err). */ + unsigned long elfmc_dc_addr; /* EV3 Phys Addr for ECC/DPERR. */ + unsigned long elfmc_abox_ctl; /* ABox Control Register. */ + unsigned long elfmc_biu_stat; /* BIU Status. */ + unsigned long elfmc_biu_addr; /* BUI Address. */ + unsigned long elfmc_biu_ctl; /* BIU Control. */ + unsigned long elfmc_fill_syndrome; /* For correcting ECC errors. */ + unsigned long elfmc_fill_addr;/* Cache block which was being read. */ + unsigned long elfmc_va; /* Effective VA of fault or miss. */ + unsigned long elfmc_bc_tag; /* Backup Cache Tag Probe Results. */ +}; + +/* + * Sable processor specific Machine Check Data segment. + */ + +struct el_t2_logout_header { + unsigned int elfl_size; /* size in bytes of logout area. */ + int elfl_sbz1:31; /* Should be zero. */ + char elfl_retry:1; /* Retry flag. */ + unsigned int elfl_procoffset; /* Processor-specific offset. */ + unsigned int elfl_sysoffset; /* Offset of system-specific. */ + unsigned int elfl_error_type; /* PAL error type code. */ + unsigned int elfl_frame_rev; /* PAL Frame revision. */ +}; +struct el_t2_sysdata_mcheck { + unsigned long elcmc_bcc; /* CSR 0 */ + unsigned long elcmc_bcce; /* CSR 1 */ + unsigned long elcmc_bccea; /* CSR 2 */ + unsigned long elcmc_bcue; /* CSR 3 */ + unsigned long elcmc_bcuea; /* CSR 4 */ + unsigned long elcmc_dter; /* CSR 5 */ + unsigned long elcmc_cbctl; /* CSR 6 */ + unsigned long elcmc_cbe; /* CSR 7 */ + unsigned long elcmc_cbeal; /* CSR 8 */ + unsigned long elcmc_cbeah; /* CSR 9 */ + unsigned long elcmc_pmbx; /* CSR 10 */ + unsigned long elcmc_ipir; /* CSR 11 */ + unsigned long elcmc_sic; /* CSR 12 */ + unsigned long elcmc_adlk; /* CSR 13 */ + unsigned long elcmc_madrl; /* CSR 14 */ + unsigned long elcmc_crrev4; /* CSR 15 */ +}; + +/* + * Sable memory error frame - sable pfms section 3.42 + */ +struct el_t2_data_memory { + struct el_t2_frame_header elcm_hdr; /* ID$MEM-FERR = 0x08 */ + unsigned int elcm_module; /* Module id. */ + unsigned int elcm_res04; /* Reserved. */ + unsigned long elcm_merr; /* CSR0: Error Reg 1. */ + unsigned long elcm_mcmd1; /* CSR1: Command Trap 1. */ + unsigned long elcm_mcmd2; /* CSR2: Command Trap 2. */ + unsigned long elcm_mconf; /* CSR3: Configuration. */ + unsigned long elcm_medc1; /* CSR4: EDC Status 1. */ + unsigned long elcm_medc2; /* CSR5: EDC Status 2. */ + unsigned long elcm_medcc; /* CSR6: EDC Control. */ + unsigned long elcm_msctl; /* CSR7: Stream Buffer Control. */ + unsigned long elcm_mref; /* CSR8: Refresh Control. */ + unsigned long elcm_filter; /* CSR9: CRD Filter Control. */ +}; + + +/* + * Sable other CPU error frame - sable pfms section 3.43 + */ +struct el_t2_data_other_cpu { + short elco_cpuid; /* CPU ID */ + short elco_res02[3]; + unsigned long elco_bcc; /* CSR 0 */ + unsigned long elco_bcce; /* CSR 1 */ + unsigned long elco_bccea; /* CSR 2 */ + unsigned long elco_bcue; /* CSR 3 */ + unsigned long elco_bcuea; /* CSR 4 */ + unsigned long elco_dter; /* CSR 5 */ + unsigned long elco_cbctl; /* CSR 6 */ + unsigned long elco_cbe; /* CSR 7 */ + unsigned long elco_cbeal; /* CSR 8 */ + unsigned long elco_cbeah; /* CSR 9 */ + unsigned long elco_pmbx; /* CSR 10 */ + unsigned long elco_ipir; /* CSR 11 */ + unsigned long elco_sic; /* CSR 12 */ + unsigned long elco_adlk; /* CSR 13 */ + unsigned long elco_madrl; /* CSR 14 */ + unsigned long elco_crrev4; /* CSR 15 */ +}; + +/* + * Sable other CPU error frame - sable pfms section 3.44 + */ +struct el_t2_data_t2{ + struct el_t2_frame_header elct_hdr; /* ID$T2-FRAME */ + unsigned long elct_iocsr; /* IO Control and Status Register */ + unsigned long elct_cerr1; /* Cbus Error Register 1 */ + unsigned long elct_cerr2; /* Cbus Error Register 2 */ + unsigned long elct_cerr3; /* Cbus Error Register 3 */ + unsigned long elct_perr1; /* PCI Error Register 1 */ + unsigned long elct_perr2; /* PCI Error Register 2 */ + unsigned long elct_hae0_1; /* High Address Extension Register 1 */ + unsigned long elct_hae0_2; /* High Address Extension Register 2 */ + unsigned long elct_hbase; /* High Base Register */ + unsigned long elct_wbase1; /* Window Base Register 1 */ + unsigned long elct_wmask1; /* Window Mask Register 1 */ + unsigned long elct_tbase1; /* Translated Base Register 1 */ + unsigned long elct_wbase2; /* Window Base Register 2 */ + unsigned long elct_wmask2; /* Window Mask Register 2 */ + unsigned long elct_tbase2; /* Translated Base Register 2 */ + unsigned long elct_tdr0; /* TLB Data Register 0 */ + unsigned long elct_tdr1; /* TLB Data Register 1 */ + unsigned long elct_tdr2; /* TLB Data Register 2 */ + unsigned long elct_tdr3; /* TLB Data Register 3 */ + unsigned long elct_tdr4; /* TLB Data Register 4 */ + unsigned long elct_tdr5; /* TLB Data Register 5 */ + unsigned long elct_tdr6; /* TLB Data Register 6 */ + unsigned long elct_tdr7; /* TLB Data Register 7 */ +}; + +/* + * Sable error log data structure - sable pfms section 3.40 + */ +struct el_t2_data_corrected { + unsigned long elcpb_biu_stat; + unsigned long elcpb_biu_addr; + unsigned long elcpb_biu_ctl; + unsigned long elcpb_fill_syndrome; + unsigned long elcpb_fill_addr; + unsigned long elcpb_bc_tag; +}; + +/* + * Sable error log data structure + * Note there are 4 memory slots on sable (see t2.h) + */ +struct el_t2_frame_mcheck { + struct el_t2_frame_header elfmc_header; /* ID$P-FRAME_MCHECK */ + struct el_t2_logout_header elfmc_hdr; + struct el_t2_procdata_mcheck elfmc_procdata; + struct el_t2_sysdata_mcheck elfmc_sysdata; + struct el_t2_data_t2 elfmc_t2data; + struct el_t2_data_memory elfmc_memdata[4]; + struct el_t2_frame_header elfmc_footer; /* empty */ +}; + + +/* + * Sable error log data structures on memory errors + */ +struct el_t2_frame_corrected { + struct el_t2_frame_header elfcc_header; /* ID$P-BC-COR */ + struct el_t2_logout_header elfcc_hdr; + struct el_t2_data_corrected elfcc_procdata; +/* struct el_t2_data_t2 elfcc_t2data; */ +/* struct el_t2_data_memory elfcc_memdata[4]; */ + struct el_t2_frame_header elfcc_footer; /* empty */ +}; + + +#ifdef __KERNEL__ + +#ifndef __EXTERN_INLINE +#define __EXTERN_INLINE extern inline +#define __IO_EXTERN_INLINE +#endif + +/* + * Translate physical memory address as seen on (PCI) bus into + * a kernel virtual address and vv. + */ + +__EXTERN_INLINE unsigned long t2_virt_to_bus(void * address) +{ + return virt_to_phys(address) + T2_DMA_WIN_BASE; +} + +__EXTERN_INLINE void * t2_bus_to_virt(unsigned long address) +{ + return phys_to_virt(address - T2_DMA_WIN_BASE); +} + +/* + * I/O functions: + * + * T2 (the core logic PCI/memory support chipset for the SABLE + * series of processors uses a sparse address mapping scheme to + * get at PCI memory and I/O. + */ + +#define vip volatile int * +#define vuip volatile unsigned int * + +__EXTERN_INLINE unsigned int t2_inb(unsigned long addr) +{ + long result = *(vip) ((addr << 5) + T2_IO + 0x00); + return __kernel_extbl(result, addr & 3); +} + +__EXTERN_INLINE void t2_outb(unsigned char b, unsigned long addr) +{ + unsigned long w; + + w = __kernel_insbl(b, addr & 3); + *(vuip) ((addr << 5) + T2_IO + 0x00) = w; + mb(); +} + +__EXTERN_INLINE unsigned int t2_inw(unsigned long addr) +{ + long result = *(vip) ((addr << 5) + T2_IO + 0x08); + return __kernel_extwl(result, addr & 3); +} + +__EXTERN_INLINE void t2_outw(unsigned short b, unsigned long addr) +{ + unsigned int w; + + w = __kernel_inswl(b, addr & 3); + *(vuip) ((addr << 5) + T2_IO + 0x08) = w; + mb(); +} + +__EXTERN_INLINE unsigned int t2_inl(unsigned long addr) +{ + return *(vuip) ((addr << 5) + T2_IO + 0x18); +} + +__EXTERN_INLINE void t2_outl(unsigned int b, unsigned long addr) +{ + *(vuip) ((addr << 5) + T2_IO + 0x18) = b; + mb(); +} + + +/* + * Memory functions. 64-bit and 32-bit accesses are done through + * dense memory space, everything else through sparse space. + * + * For reading and writing 8 and 16 bit quantities we need to + * go through one of the three sparse address mapping regions + * and use the HAE_MEM CSR to provide some bits of the address. + * The following few routines use only sparse address region 1 + * which gives 1Gbyte of accessible space which relates exactly + * to the amount of PCI memory mapping *into* system address space. + * See p 6-17 of the specification but it looks something like this: + * + * 21164 Address: + * + * 3 2 1 + * 9876543210987654321098765432109876543210 + * 1ZZZZ0.PCI.QW.Address............BBLL + * + * ZZ = SBZ + * BB = Byte offset + * LL = Transfer length + * + * PCI Address: + * + * 3 2 1 + * 10987654321098765432109876543210 + * HHH....PCI.QW.Address........ 00 + * + * HHH = 31:29 HAE_MEM CSR + * + */ + +__EXTERN_INLINE unsigned long t2_srm_base(unsigned long addr) +{ + if ((addr >= alpha_mv.sm_base_r1 + && addr <= alpha_mv.sm_base_r1 + T2_MEM_R1_MASK) + || (addr >= 512*1024 && addr < 1024*1024)) { + return ((addr & T2_MEM_R1_MASK) << 5) + T2_SPARSE_MEM; + } +#if 0 + printk("T2: address 0x%lx not covered by HAE\n", addr); +#endif + return 0; +} + +__EXTERN_INLINE unsigned long t2_srm_readb(unsigned long addr) +{ + unsigned long result, work; + + if ((work = t2_srm_base(addr)) == 0) + return 0xff; + work += 0x00; /* add transfer length */ + + result = *(vip) work; + return __kernel_extbl(result, addr & 3); +} + +__EXTERN_INLINE unsigned long t2_srm_readw(unsigned long addr) +{ + unsigned long result, work; + + if ((work = t2_srm_base(addr)) == 0) + return 0xffff; + work += 0x08; /* add transfer length */ + + result = *(vip) work; + return __kernel_extwl(result, addr & 3); +} + +/* On SABLE with T2, we must use SPARSE memory even for 32-bit access ... */ +__EXTERN_INLINE unsigned long t2_srm_readl(unsigned long addr) +{ + unsigned long work; + + if ((work = t2_srm_base(addr)) == 0) + return 0xffffffff; + work += 0x18; /* add transfer length */ + + return *(vuip) work; +} + +/* ... which makes me wonder why we advertise we have DENSE memory at all. + Anyway, guess that means we should emulate 64-bit access as two cycles. */ +__EXTERN_INLINE unsigned long t2_srm_readq(unsigned long addr) +{ + unsigned long work, r0, r1; + + if ((work = t2_srm_base(addr)) == 0) + return ~0UL; + work += 0x18; /* add transfer length */ + + r0 = *(vuip) work; + r1 = *(vuip) (work + (4 << 5)); + return r1 << 32 | r0; +} + +__EXTERN_INLINE void t2_srm_writeb(unsigned char b, unsigned long addr) +{ + unsigned long work = t2_srm_base(addr); + if (work) { + work += 0x00; /* add transfer length */ + *(vuip) work = b * 0x01010101; + } +} + +__EXTERN_INLINE void t2_srm_writew(unsigned short b, unsigned long addr) +{ + unsigned long work = t2_srm_base(addr); + if (work) { + work += 0x08; /* add transfer length */ + *(vuip) work = b * 0x00010001; + } +} + +/* On SABLE with T2, we must use SPARSE memory even for 32-bit access ... */ +__EXTERN_INLINE void t2_srm_writel(unsigned int b, unsigned long addr) +{ + unsigned long work = t2_srm_base(addr); + if (work) { + work += 0x18; /* add transfer length */ + *(vuip) work = b; + } +} + +/* ... which makes me wonder why we advertise we have DENSE memory at all. + Anyway, guess that means we should emulate 64-bit access as two cycles. */ +__EXTERN_INLINE void t2_srm_writeq(unsigned long b, unsigned long addr) +{ + unsigned long work = t2_srm_base(addr); + if (work) { + work += 0x18; /* add transfer length */ + *(vuip) work = b; + *(vuip) (work + (4 << 5)) = b >> 32; + } +} + +__EXTERN_INLINE unsigned long t2_readb(unsigned long addr) +{ + unsigned long result, msb; + + msb = addr & 0xE0000000 ; + addr &= T2_MEM_R1_MASK ; + set_hae(msb); + + result = *(vip) ((addr << 5) + T2_SPARSE_MEM + 0x00) ; + return __kernel_extbl(result, addr & 3); +} + +__EXTERN_INLINE unsigned long t2_readw(unsigned long addr) +{ + unsigned long result, msb; + + msb = addr & 0xE0000000 ; + addr &= T2_MEM_R1_MASK ; + set_hae(msb); + + result = *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08); + return __kernel_extwl(result, addr & 3); +} + +/* On SABLE with T2, we must use SPARSE memory even for 32-bit access. */ +__EXTERN_INLINE unsigned long t2_readl(unsigned long addr) +{ + unsigned long msb; + + msb = addr & 0xE0000000 ; + addr &= T2_MEM_R1_MASK ; + set_hae(msb); + + return *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18); +} + +__EXTERN_INLINE unsigned long t2_readq(unsigned long addr) +{ + unsigned long r0, r1, work, msb; + + msb = addr & 0xE0000000 ; + addr &= T2_MEM_R1_MASK ; + set_hae(msb); + + work = (addr << 5) + T2_SPARSE_MEM + 0x18; + r0 = *(vuip)(work); + r1 = *(vuip)(work + (4 << 5)); + return r1 << 32 | r0; +} + +__EXTERN_INLINE void t2_writeb(unsigned char b, unsigned long addr) +{ + unsigned long msb ; + + msb = addr & 0xE0000000 ; + addr &= T2_MEM_R1_MASK ; + set_hae(msb); + + *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x00) = b * 0x01010101; +} + +__EXTERN_INLINE void t2_writew(unsigned short b, unsigned long addr) +{ + unsigned long msb ; + + msb = addr & 0xE0000000 ; + addr &= T2_MEM_R1_MASK ; + set_hae(msb); + + *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08) = b * 0x00010001; +} + +/* On SABLE with T2, we must use SPARSE memory even for 32-bit access. */ +__EXTERN_INLINE void t2_writel(unsigned int b, unsigned long addr) +{ + unsigned long msb ; + + msb = addr & 0xE0000000 ; + addr &= T2_MEM_R1_MASK ; + set_hae(msb); + + *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18) = b; +} + +__EXTERN_INLINE void t2_writeq(unsigned long b, unsigned long addr) +{ + unsigned long msb, work; + + msb = addr & 0xE0000000 ; + addr &= T2_MEM_R1_MASK ; + set_hae(msb); + + work = (addr << 5) + T2_SPARSE_MEM + 0x18; + *(vuip)work = b; + *(vuip)(work + (4 << 5)) = b >> 32; +} + +/* Find the DENSE memory area for a given bus address. */ + +__EXTERN_INLINE unsigned long t2_dense_mem(unsigned long addr) +{ + return T2_DENSE_MEM; +} + +#undef vip +#undef vuip + +#ifdef __WANT_IO_DEF + +#define virt_to_bus t2_virt_to_bus +#define bus_to_virt t2_bus_to_virt +#define __inb t2_inb +#define __inw t2_inw +#define __inl t2_inl +#define __outb t2_outb +#define __outw t2_outw +#define __outl t2_outl + +#ifdef CONFIG_ALPHA_SRM_SETUP +#define __readb t2_srm_readb +#define __readw t2_srm_readw +#define __readl t2_srm_readl +#define __readq t2_srm_readq +#define __writeb t2_srm_writeb +#define __writew t2_srm_writew +#define __writel t2_srm_writel +#define __writeq t2_srm_writeq +#else +#define __readb t2_readb +#define __readw t2_readw +#define __readl t2_readl +#define __readq t2_readq +#define __writeb t2_writeb +#define __writew t2_writew +#define __writel t2_writel +#define __writeq t2_writeq +#endif + +#define dense_mem t2_dense_mem + +#define inb(port) \ +(__builtin_constant_p((port))?__inb(port):_inb(port)) + +#define outb(x, port) \ +(__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port))) + +#endif /* __WANT_IO_DEF */ + +#ifdef __IO_EXTERN_INLINE +#undef __EXTERN_INLINE +#undef __IO_EXTERN_INLINE +#endif + +#endif /* __KERNEL__ */ + +#endif /* __ALPHA_T2__H__ */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/core_tsunami.h linux/include/asm-alpha/core_tsunami.h --- v2.1.115/linux/include/asm-alpha/core_tsunami.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-alpha/core_tsunami.h Sun Aug 9 12:09:06 1998 @@ -0,0 +1,478 @@ +#ifndef __ALPHA_TSUNAMI__H__ +#define __ALPHA_TSUNAMI__H__ + +#include +#include +#include + +/* + * TSUNAMI/TYPHOON are the internal names for the core logic chipset which + * provides memory controller and PCI access for the 21264 based systems. + * + * This file is based on: + * + * Tsunami System Programmers Manual + * Preliminary, Chapters 2-5 + * + */ + +#define TSUNAMI_DMA_WIN_BASE_DEFAULT (1024*1024*1024) +#define TSUNAMI_DMA_WIN_SIZE_DEFAULT (1024*1024*1024) + +#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) +#define TSUNAMI_DMA_WIN_BASE alpha_mv.dma_win_base +#define TSUNAMI_DMA_WIN_SIZE alpha_mv.dma_win_size +#else +#define TSUNAMI_DMA_WIN_BASE TSUNAMI_DMA_WIN_BASE_DEFAULT +#define TSUNAMI_DMA_WIN_SIZE TSUNAMI_DMA_WIN_SIZE_DEFAULT +#endif + +/* XXX: Do we need to conditionalize on this? */ +#ifdef USE_48_BIT_KSEG +#define TS_BIAS 0x80000000000UL +#else +#define TS_BIAS 0x10000000000UL +#endif + +/* + * CChip and DChip registers + */ +#define TSUNAMI_CSR_CSC (IDENT_ADDR + TS_BIAS + 0x1A0000000UL) +#define TSUNAMI_CSR_MTR (IDENT_ADDR + TS_BIAS + 0x1A0000040UL) +#define TSUNAMI_CSR_MISC (IDENT_ADDR + TS_BIAS + 0x1A0000080UL) +#define TSUNAMI_CSR_MPD (IDENT_ADDR + TS_BIAS + 0x1A00000C0UL) +#define TSUNAMI_CSR_AAR0 (IDENT_ADDR + TS_BIAS + 0x1A0000100UL) +#define TSUNAMI_CSR_AAR1 (IDENT_ADDR + TS_BIAS + 0x1A0000140UL) +#define TSUNAMI_CSR_AAR2 (IDENT_ADDR + TS_BIAS + 0x1A0000180UL) +#define TSUNAMI_CSR_AAR3 (IDENT_ADDR + TS_BIAS + 0x1A00001C0UL) +#define TSUNAMI_CSR_DIM0 (IDENT_ADDR + TS_BIAS + 0x1A0000200UL) +#define TSUNAMI_CSR_DIM1 (IDENT_ADDR + TS_BIAS + 0x1A0000240UL) +#define TSUNAMI_CSR_DIR0 (IDENT_ADDR + TS_BIAS + 0x1A0000280UL) +#define TSUNAMI_CSR_DIR1 (IDENT_ADDR + TS_BIAS + 0x1A00002C0UL) + +#define TSUNAMI_CSR_DRIR (IDENT_ADDR + TS_BIAS + 0x1A0000300UL) +#define TSUNAMI_CSR_PRBEN (IDENT_ADDR + TS_BIAS + 0x1A0000340UL) +#define TSUNAMI_CSR_IIC (IDENT_ADDR + TS_BIAS + 0x1A0000380UL) +#define TSUNAMI_CSR_WDR (IDENT_ADDR + TS_BIAS + 0x1A00003C0UL) +#define TSUNAMI_CSR_MPR0 (IDENT_ADDR + TS_BIAS + 0x1A0000400UL) +#define TSUNAMI_CSR_MPR1 (IDENT_ADDR + TS_BIAS + 0x1A0000440UL) +#define TSUNAMI_CSR_MPR2 (IDENT_ADDR + TS_BIAS + 0x1A0000480UL) +#define TSUNAMI_CSR_MPR3 (IDENT_ADDR + TS_BIAS + 0x1A00004C0UL) +#define TSUNAMI_CSR_TTR (IDENT_ADDR + TS_BIAS + 0x1A0000580UL) +#define TSUNAMI_CSR_TDR (IDENT_ADDR + TS_BIAS + 0x1A00005C0UL) +#define TSUNAMI_CSR_DSC (IDENT_ADDR + TS_BIAS + 0x1B0000800UL) +#define TSUNAMI_CSR_STR (IDENT_ADDR + TS_BIAS + 0x1B0000840UL) +#define TSUNAMI_CSR_DREV (IDENT_ADDR + TS_BIAS + 0x1B0000880UL) + +/* + * PChip registers + */ +#define TSUNAMI_PCHIP0_WSBA0 (IDENT_ADDR + TS_BIAS + 0x180000000UL) +#define TSUNAMI_PCHIP0_WSBA1 (IDENT_ADDR + TS_BIAS + 0x180000040UL) +#define TSUNAMI_PCHIP0_WSBA2 (IDENT_ADDR + TS_BIAS + 0x180000080UL) +#define TSUNAMI_PCHIP0_WSBA3 (IDENT_ADDR + TS_BIAS + 0x1800000C0UL) + +#define TSUNAMI_PCHIP0_WSM0 (IDENT_ADDR + TS_BIAS + 0x180000100UL) +#define TSUNAMI_PCHIP0_WSM1 (IDENT_ADDR + TS_BIAS + 0x180000140UL) +#define TSUNAMI_PCHIP0_WSM2 (IDENT_ADDR + TS_BIAS + 0x180000180UL) +#define TSUNAMI_PCHIP0_WSM3 (IDENT_ADDR + TS_BIAS + 0x1800001C0UL) +#define TSUNAMI_PCHIP0_TBA0 (IDENT_ADDR + TS_BIAS + 0x180000200UL) +#define TSUNAMI_PCHIP0_TBA1 (IDENT_ADDR + TS_BIAS + 0x180000240UL) +#define TSUNAMI_PCHIP0_TBA2 (IDENT_ADDR + TS_BIAS + 0x180000280UL) +#define TSUNAMI_PCHIP0_TBA3 (IDENT_ADDR + TS_BIAS + 0x1800002C0UL) + +#define TSUNAMI_PCHIP0_PCTL (IDENT_ADDR + TS_BIAS + 0x180000300UL) +#define TSUNAMI_PCHIP0_PLAT (IDENT_ADDR + TS_BIAS + 0x180000340UL) +#define TSUNAMI_PCHIP0_RESERVED (IDENT_ADDR + TS_BIAS + 0x180000380UL) +#define TSUNAMI_PCHIP0_PERROR (IDENT_ADDR + TS_BIAS + 0x1800003c0UL) +#define TSUNAMI_PCHIP0_PERRMASK (IDENT_ADDR + TS_BIAS + 0x180000400UL) +#define TSUNAMI_PCHIP0_PERRSET (IDENT_ADDR + TS_BIAS + 0x180000440UL) +#define TSUNAMI_PCHIP0_TLBIV (IDENT_ADDR + TS_BIAS + 0x180000480UL) +#define TSUNAMI_PCHIP0_TLBIA (IDENT_ADDR + TS_BIAS + 0x1800004C0UL) +#define TSUNAMI_PCHIP0_PMONCTL (IDENT_ADDR + TS_BIAS + 0x180000500UL) +#define TSUNAMI_PCHIP0_PMONCNT (IDENT_ADDR + TS_BIAS + 0x180000540UL) + +#define TSUNAMI_PCHIP1_WSBA0 (IDENT_ADDR + TS_BIAS + 0x380000000UL) +#define TSUNAMI_PCHIP1_WSBA1 (IDENT_ADDR + TS_BIAS + 0x380000040UL) +#define TSUNAMI_PCHIP1_WSBA2 (IDENT_ADDR + TS_BIAS + 0x380000080UL) +#define TSUNAMI_PCHIP1_WSBA3 (IDENT_ADDR + TS_BIAS + 0x3800000C0UL) +#define TSUNAMI_PCHIP1_WSM0 (IDENT_ADDR + TS_BIAS + 0x380000100UL) +#define TSUNAMI_PCHIP1_WSM1 (IDENT_ADDR + TS_BIAS + 0x380000140UL) +#define TSUNAMI_PCHIP1_WSM2 (IDENT_ADDR + TS_BIAS + 0x380000180UL) +#define TSUNAMI_PCHIP1_WSM3 (IDENT_ADDR + TS_BIAS + 0x3800001C0UL) + +#define TSUNAMI_PCHIP1_TBA0 (IDENT_ADDR + TS_BIAS + 0x380000200UL) +#define TSUNAMI_PCHIP1_TBA1 (IDENT_ADDR + TS_BIAS + 0x380000240UL) +#define TSUNAMI_PCHIP1_TBA2 (IDENT_ADDR + TS_BIAS + 0x380000280UL) +#define TSUNAMI_PCHIP1_TBA3 (IDENT_ADDR + TS_BIAS + 0x3800002C0UL) + +#define TSUNAMI_PCHIP1_PCTL (IDENT_ADDR + TS_BIAS + 0x380000300UL) +#define TSUNAMI_PCHIP1_PLAT (IDENT_ADDR + TS_BIAS + 0x380000340UL) +#define TSUNAMI_PCHIP1_RESERVED (IDENT_ADDR + TS_BIAS + 0x380000380UL) +#define TSUNAMI_PCHIP1_PERROR (IDENT_ADDR + TS_BIAS + 0x3800003c0UL) +#define TSUNAMI_PCHIP1_PERRMASK (IDENT_ADDR + TS_BIAS + 0x380000400UL) +#define TSUNAMI_PCHIP1_PERRSET (IDENT_ADDR + TS_BIAS + 0x380000440UL) +#define TSUNAMI_PCHIP1_TLBIV (IDENT_ADDR + TS_BIAS + 0x380000480UL) +#define TSUNAMI_PCHIP1_TLBIA (IDENT_ADDR + TS_BIAS + 0x3800004C0UL) +#define TSUNAMI_PCHIP1_PMONCTL (IDENT_ADDR + TS_BIAS + 0x380000500UL) +#define TSUNAMI_PCHIP1_PMONCNT (IDENT_ADDR + TS_BIAS + 0x380000540UL) + +/* */ +/* TSUNAMI Pchip Error register. */ +/* */ +#define perror_m_lost 0x1 +#define perror_m_serr 0x2 +#define perror_m_perr 0x4 +#define perror_m_dcrto 0x8 +#define perror_m_sge 0x10 +#define perror_m_ape 0x20 +#define perror_m_ta 0x40 +#define perror_m_rdpe 0x80 +#define perror_m_nds 0x100 +#define perror_m_rto 0x200 +#define perror_m_uecc 0x400 +#define perror_m_cre 0x800 +#define perror_m_addrl 0xFFFFFFFF0000UL +#define perror_m_addrh 0x7000000000000UL +#define perror_m_cmd 0xF0000000000000UL +#define perror_m_syn 0xFF00000000000000UL +union TPchipPERROR { + struct { + unsigned int perror_v_lost : 1; + unsigned perror_v_serr : 1; + unsigned perror_v_perr : 1; + unsigned perror_v_dcrto : 1; + unsigned perror_v_sge : 1; + unsigned perror_v_ape : 1; + unsigned perror_v_ta : 1; + unsigned perror_v_rdpe : 1; + unsigned perror_v_nds : 1; + unsigned perror_v_rto : 1; + unsigned perror_v_uecc : 1; + unsigned perror_v_cre : 1; + unsigned perror_v_rsvd1 : 4; + unsigned perror_v_addrl : 32; + unsigned perror_v_addrh : 3; + unsigned perror_v_rsvd2 : 1; + unsigned perror_v_cmd : 4; + unsigned perror_v_syn : 8; + } perror_r_bits; + int perror_q_whole [2]; + } ; +/* */ +/* TSUNAMI Pchip Window Space Base Address register. */ +/* */ +#define wsba_m_ena 0x1 +#define wsba_m_sg 0x2 +#define wsba_m_ptp 0x4 +#define wsba_m_addr 0xFFF00000 +#define wmask_k_sz1gb 0x3FF00000 +union TPchipWSBA { + struct { + unsigned wsba_v_ena : 1; + unsigned wsba_v_sg : 1; + unsigned wsba_v_ptp : 1; + unsigned wsba_v_rsvd1 : 17; + unsigned wsba_v_addr : 12; + unsigned wsba_v_rsvd2 : 32; + } wsba_r_bits; + int wsba_q_whole [2]; + } ; +/* */ +/* TSUNAMI Pchip Control Register */ +/* */ +#define pctl_m_fdsc 0x1 +#define pctl_m_fbtb 0x2 +#define pctl_m_thdis 0x4 +#define pctl_m_chaindis 0x8 +#define pctl_m_tgtlat 0x10 +#define pctl_m_hole 0x20 +#define pctl_m_mwin 0x40 +#define pctl_m_arbena 0x80 +#define pctl_m_prigrp 0x7F00 +#define pctl_m_ppri 0x8000 +#define pctl_m_rsvd1 0x30000 +#define pctl_m_eccen 0x40000 +#define pctl_m_padm 0x80000 +#define pctl_m_cdqmax 0xF00000 +#define pctl_m_rev 0xFF000000 +#define pctl_m_crqmax 0xF00000000UL +#define pctl_m_ptpmax 0xF000000000UL +#define pctl_m_pclkx 0x30000000000UL +#define pctl_m_fdsdis 0x40000000000UL +#define pctl_m_fdwdis 0x80000000000UL +#define pctl_m_ptevrfy 0x100000000000UL +#define pctl_m_rpp 0x200000000000UL +#define pctl_m_pid 0xC00000000000UL +#define pctl_m_rsvd2 0xFFFF000000000000UL + +union TPchipPCTL { + struct { + unsigned pctl_v_fdsc : 1; + unsigned pctl_v_fbtb : 1; + unsigned pctl_v_thdis : 1; + unsigned pctl_v_chaindis : 1; + unsigned pctl_v_tgtlat : 1; + unsigned pctl_v_hole : 1; + unsigned pctl_v_mwin : 1; + unsigned pctl_v_arbena : 1; + unsigned pctl_v_prigrp : 7; + unsigned pctl_v_ppri : 1; + unsigned pctl_v_rsvd1 : 2; + unsigned pctl_v_eccen : 1; + unsigned pctl_v_padm : 1; + unsigned pctl_v_cdqmax : 4; + unsigned pctl_v_rev : 8; + unsigned pctl_v_crqmax : 4; + unsigned pctl_v_ptpmax : 4; + unsigned pctl_v_pclkx : 2; + unsigned pctl_v_fdsdis : 1; + unsigned pctl_v_fdwdis : 1; + unsigned pctl_v_ptevrfy : 1; + unsigned pctl_v_rpp : 1; + unsigned pctl_v_pid : 2; + unsigned pctl_v_rsvd2 : 16; + } pctl_r_bits; + int pctl_q_whole [2]; +} ; +/* */ +/* TSUNAMI Pchip Error Mask Register. */ +/* */ +#define perrmask_m_lost 0x1 +#define perrmask_m_serr 0x2 +#define perrmask_m_perr 0x4 +#define perrmask_m_dcrto 0x8 +#define perrmask_m_sge 0x10 +#define perrmask_m_ape 0x20 +#define perrmask_m_ta 0x40 +#define perrmask_m_rdpe 0x80 +#define perrmask_m_nds 0x100 +#define perrmask_m_rto 0x200 +#define perrmask_m_uecc 0x400 +#define perrmask_m_cre 0x800 +#define perrmask_m_rsvd 0xFFFFFFFFFFFFF000UL +union TPchipPERRMASK { + struct { + unsigned int perrmask_v_lost : 1; + unsigned perrmask_v_serr : 1; + unsigned perrmask_v_perr : 1; + unsigned perrmask_v_dcrto : 1; + unsigned perrmask_v_sge : 1; + unsigned perrmask_v_ape : 1; + unsigned perrmask_v_ta : 1; + unsigned perrmask_v_rdpe : 1; + unsigned perrmask_v_nds : 1; + unsigned perrmask_v_rto : 1; + unsigned perrmask_v_uecc : 1; + unsigned perrmask_v_cre : 1; + unsigned perrmask_v_rsvd1 : 20; + unsigned perrmask_v_rsvd2 : 32; + } perrmask_r_bits; + int perrmask_q_whole [2]; + } ; + +/* + * Memory spaces: + */ +#define TSUNAMI_PCI0_MEM (IDENT_ADDR + TS_BIAS + 0x000000000UL) +#define TSUNAMI_PCI0_IACK_SC (IDENT_ADDR + TS_BIAS + 0x1F8000000UL) +#define TSUNAMI_PCI0_IO (IDENT_ADDR + TS_BIAS + 0x1FC000000UL) +#define TSUNAMI_PCI0_CONF (IDENT_ADDR + TS_BIAS + 0x1FE000000UL) + +#define TSUNAMI_PCI1_MEM (IDENT_ADDR + TS_BIAS + 0x200000000UL) +#define TSUNAMI_PCI1_IACK_SC (IDENT_ADDR + TS_BIAS + 0x3F8000000UL) +#define TSUNAMI_PCI1_IO (IDENT_ADDR + TS_BIAS + 0x3FC000000UL) +#define TSUNAMI_PCI1_CONF (IDENT_ADDR + TS_BIAS + 0x3FE000000UL) + +/* + * Data structure for handling TSUNAMI machine checks: + */ +struct el_TSUNAMI_sysdata_mcheck { +}; + + +#ifdef __KERNEL__ + +#ifndef __EXTERN_INLINE +#define __EXTERN_INLINE extern inline +#define __IO_EXTERN_INLINE +#endif + +/* + * Translate physical memory address as seen on (PCI) bus into + * a kernel virtual address and vv. + */ +__EXTERN_INLINE unsigned long tsunami_virt_to_bus(void * address) +{ + return virt_to_phys(address) + TSUNAMI_DMA_WIN_BASE; +} + +__EXTERN_INLINE void * tsunami_bus_to_virt(unsigned long address) +{ + return phys_to_virt(address - TSUNAMI_DMA_WIN_BASE); +} + +/* + * I/O functions: + * + * TSUNAMI, the 21??? PCI/memory support chipset for the EV6 (21264) + * can only use linear accesses to get at PCI memory and I/O spaces. + */ + +/* HACK ALERT! HACK ALERT! */ +/* HACK ALERT! HACK ALERT! */ + +/* Only using PCI bus 0 for now in all routines. */ + +#define TSUNAMI_IACK_SC TSUNAMI_PCI0_IACK_SC + +/* HACK ALERT! HACK ALERT! */ +/* HACK ALERT! HACK ALERT! */ + +#define vucp volatile unsigned char * +#define vusp volatile unsigned short * +#define vuip volatile unsigned int * +#define vulp volatile unsigned long * + +__EXTERN_INLINE unsigned int tsunami_inb(unsigned long addr) +{ + return __kernel_ldbu(*(vucp)(addr + TSUNAMI_PCI0_IO)); +} + +__EXTERN_INLINE void tsunami_outb(unsigned char b, unsigned long addr) +{ + __kernel_stb(b, *(vucp)(addr + TSUNAMI_PCI0_IO)); + mb(); +} + +__EXTERN_INLINE unsigned int tsunami_inw(unsigned long addr) +{ + return __kernel_ldwu(*(vusp)(addr+TSUNAMI_PCI0_IO)); +} + +__EXTERN_INLINE void tsunami_outw(unsigned short b, unsigned long addr) +{ + __kernel_stw(b, *(vusp)(addr+TSUNAMI_PCI0_IO)); + mb(); +} + +__EXTERN_INLINE unsigned int tsunami_inl(unsigned long addr) +{ + return *(vuip)(addr+TSUNAMI_PCI0_IO); +} + +__EXTERN_INLINE void tsunami_outl(unsigned int b, unsigned long addr) +{ + *(vuip)(addr+TSUNAMI_PCI0_IO) = b; + mb(); +} + +/* + * Memory functions. all accesses are done through linear space. + */ + +__EXTERN_INLINE unsigned long tsunami_readb(unsigned long addr) +{ + return __kernel_ldbu(*(vucp)(addr+TSUNAMI_PCI0_MEM)); +} + +__EXTERN_INLINE unsigned long tsunami_readw(unsigned long addr) +{ + return __kernel_ldwu(*(vusp)(addr+TSUNAMI_PCI0_MEM)); +} + +__EXTERN_INLINE unsigned long tsunami_readl(unsigned long addr) +{ + return *(vuip)(addr+TSUNAMI_PCI0_MEM); +} + +__EXTERN_INLINE unsigned long tsunami_readq(unsigned long addr) +{ + return *(vulp)(addr+TSUNAMI_PCI0_MEM); +} + +__EXTERN_INLINE void tsunami_writeb(unsigned char b, unsigned long addr) +{ + __kernel_stb(b, *(vucp)(addr+TSUNAMI_PCI0_MEM)); + mb(); +} + +__EXTERN_INLINE void tsunami_writew(unsigned short b, unsigned long addr) +{ + __kernel_stw(b, *(vusp)(addr+TSUNAMI_PCI0_MEM)); + mb(); +} + +__EXTERN_INLINE void tsunami_writel(unsigned int b, unsigned long addr) +{ + *(vuip)(addr+TSUNAMI_PCI0_MEM) = b; + mb(); +} + +__EXTERN_INLINE void tsunami_writeq(unsigned long b, unsigned long addr) +{ + *(vulp)(addr+TSUNAMI_PCI0_MEM) = b; + mb(); +} + +/* Find the DENSE memory area for a given bus address. */ + +__EXTERN_INLINE unsigned long tsunami_dense_mem(unsigned long addr) +{ + return TSUNAMI_PCI0_MEM; +} + +#undef vucp +#undef vusp +#undef vuip +#undef vulp + +#ifdef __WANT_IO_DEF + +#define virt_to_bus tsunami_virt_to_bus +#define bus_to_virt tsunami_bus_to_virt + +#define __inb tsunami_inb +#define __inw tsunami_inw +#define __inl tsunami_inl +#define __outb tsunami_outb +#define __outw tsunami_outw +#define __outl tsunami_outl +#define __readb tsunami_readb +#define __readw tsunami_readw +#define __writeb tsunami_writeb +#define __writew tsunami_writew +#define __readl tsunami_readl +#define __readq tsunami_readq +#define __writel tsunami_writel +#define __writeq tsunami_writeq +#define dense_mem tsunami_dense_mem + +#define inb(port) __inb((port)) +#define inw(port) __inw((port)) +#define inl(port) __inl((port)) + +#define outb(v, port) __outb((v),(port)) +#define outw(v, port) __outw((v),(port)) +#define outl(v, port) __outl((v),(port)) + +#define readb(a) __readb((unsigned long)(a)) +#define readw(a) __readw((unsigned long)(a)) +#define readl(a) __readl((unsigned long)(a)) +#define readq(a) __readq((unsigned long)(a)) + +#define writeb(v,a) __writeb((v),(unsigned long)(a)) +#define writew(v,a) __writew((v),(unsigned long)(a)) +#define writel(v,a) __writel((v),(unsigned long)(a)) +#define writeq(v,a) __writeq((v),(unsigned long)(a)) + +#endif /* __WANT_IO_DEF */ + +#ifdef __IO_EXTERN_INLINE +#undef __EXTERN_INLINE +#undef __IO_EXTERN_INLINE +#endif + +#endif /* __KERNEL__ */ + +#endif /* __ALPHA_TSUNAMI__H__ */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/dma.h linux/include/asm-alpha/dma.h --- v2.1.115/linux/include/asm-alpha/dma.h Mon Feb 23 18:12:11 1998 +++ linux/include/asm-alpha/dma.h Sun Aug 9 12:09:06 1998 @@ -19,8 +19,7 @@ #define _ASM_DMA_H #include - -#include /* need byte IO */ +#include #define dma_outb outb #define dma_inb inb @@ -75,7 +74,6 @@ #define MAX_DMA_CHANNELS 8 -#ifdef CONFIG_ALPHA_XL /* The maximum address that we can perform a DMA transfer to on Alpha XL, due to a hardware SIO (PCI<->ISA bus bridge) chip limitation, is 64MB. See for more info. @@ -86,12 +84,18 @@ We MUST coordinate the maximum with for consistency. For now, this limit is set to 48Mb... */ -#define MAX_DMA_ADDRESS (0xfffffc0003000000UL) -#else /* CONFIG_ALPHA_XL */ -/* The maximum address that we can perform a DMA transfer to on normal - Alpha platforms */ -#define MAX_DMA_ADDRESS (~0UL) -#endif /* CONFIG_ALPHA_XL */ +#define ALPHA_XL_MAX_DMA_ADDRESS (0xfffffc0003000000UL) +#define ALPHA_MAX_DMA_ADDRESS (~0UL) + +#ifdef CONFIG_ALPHA_GENERIC +# define MAX_DMA_ADDRESS (alpha_mv.max_dma_address) +#else +# ifdef CONFIG_ALPHA_XL +# define MAX_DMA_ADDRESS ALPHA_XL_MAX_DMA_ADDRESS +# else +# define MAX_DMA_ADDRESS ALPHA_MAX_DMA_ADDRESS +# endif +#endif /* 8237 DMA controllers */ #define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/floppy.h linux/include/asm-alpha/floppy.h --- v2.1.115/linux/include/asm-alpha/floppy.h Sat Sep 6 10:09:56 1997 +++ linux/include/asm-alpha/floppy.h Sun Aug 9 12:09:06 1998 @@ -51,13 +51,24 @@ #define FLOPPY_MOTOR_MASK 0xf0 /* - * Most Alphas have no problems with floppy DMA crossing 64k borders. Sigh... + * Most Alphas have no problems with floppy DMA crossing 64k borders, + * except for XL. It is also the only one with DMA limits, so we use + * that to test in the generic kernel. */ -#ifdef CONFIG_ALPHA_XL -#define CROSS_64KB(a,s) \ - ((unsigned long)(a)/0x10000 != ((unsigned long)(a) + (s) - 1) / 0x10000) -#else /* CONFIG_ALPHA_XL */ -#define CROSS_64KB(a,s) (0) -#endif /* CONFIG_ALPHA_XL */ + +#define __CROSS_64KB(a,s) \ +({ unsigned long __s64 = (unsigned long)(a); \ + unsigned long __e64 = __s64 + (unsigned long)(s) - 1; \ + (__s64 ^ __e64) & ~0xfffful; }) + +#ifdef CONFIG_ALPHA_GENERIC +# define CROSS_64KB(a,s) (__CROSS_64KB(a,s) && ~alpha_mv.max_dma_address) +#else +# ifdef CONFIG_ALPHA_XL +# define CROSS_64KB(a,s) __CROSS_64KB(a,s) +# else +# define CROSS_64KB(a,s) (0) +# endif +#endif #endif /* __ASM_ALPHA_FLOPPY_H */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/hwrpb.h linux/include/asm-alpha/hwrpb.h --- v2.1.115/linux/include/asm-alpha/hwrpb.h Wed Apr 1 20:11:53 1998 +++ linux/include/asm-alpha/hwrpb.h Sun Aug 9 12:09:06 1998 @@ -1,5 +1,5 @@ -#ifndef _HWRPB_H -#define _HWRPB_H +#ifndef __ALPHA_HWRPB_H +#define __ALPHA_HWRPB_H #define INIT_HWRPB ((struct hwrpb_struct *) 0x10000000) @@ -34,6 +34,7 @@ #define ST_DEC_AXPPCI_33 11 /* NoName system type */ #define ST_DEC_TLASER 12 /* Turbolaser systype */ #define ST_DEC_2100_A50 13 /* Avanti systype */ +#define ST_DEC_MUSTANG 14 /* Mustang systype */ #define ST_DEC_ALCOR 15 /* Alcor (EV5) systype */ #define ST_DEC_1000 17 /* Mikasa systype */ #define ST_DEC_EB64 18 /* EB64 systype */ @@ -92,7 +93,7 @@ unsigned long halt_pv; unsigned long halt_reason; unsigned long res; - unsigned long ipc_buffer[21]; + char ipc_buffer[168]; unsigned long palcode_avail[16]; unsigned long compatibility; }; @@ -184,4 +185,6 @@ unsigned long dsr_offset; /* "Dynamic System Recognition Data Block Table" */ }; -#endif +extern struct hwrpb_struct *hwrpb; + +#endif /* __ALPHA_HWRPB_H */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/init.h linux/include/asm-alpha/init.h --- v2.1.115/linux/include/asm-alpha/init.h Thu Mar 26 15:57:05 1998 +++ linux/include/asm-alpha/init.h Sun Aug 9 12:09:06 1998 @@ -7,12 +7,6 @@ __arginit __init; \ __arginit -#if __GNUC__ >= 2 && __GNUC_MINOR__ >= 8 -#define __initlocaldata __initdata -#else -#define __initlocaldata -#endif - /* For assembly routines */ #define __INIT .section .text.init,"ax" #define __FINIT .previous diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/io.h linux/include/asm-alpha/io.h --- v2.1.115/linux/include/asm-alpha/io.h Tue Jul 21 00:15:32 1998 +++ linux/include/asm-alpha/io.h Sun Aug 9 12:09:06 1998 @@ -2,29 +2,17 @@ #define __ALPHA_IO_H #include - #include +#include /* We don't use IO slowdowns on the Alpha, but.. */ #define __SLOW_DOWN_IO do { } while (0) #define SLOW_DOWN_IO do { } while (0) /* - * The hae (hardware address extension) register is used to - * access high IO addresses. To avoid doing an external cycle - * every time we need to set the hae, we have a hae cache in - * memory. The kernel entry code makes sure that the hae is - * preserved across interrupts, so it is safe to set the hae - * once and then depend on it staying the same in kernel code. - */ -extern struct hae { - unsigned long cache; - unsigned long *reg; -} hae; - -/* * Virtual -> physical identity mapping starts at this offset */ +/* XXX: Do we need to conditionalize on this? */ #ifdef USE_48_BIT_KSEG #define IDENT_ADDR (0xffff800000000000UL) #else @@ -40,25 +28,34 @@ * register not being up-to-date with respect to the hardware * value. */ -extern inline void set_hae(unsigned long new_hae) +static inline void __set_hae(unsigned long new_hae) { unsigned long ipl = swpipl(7); - hae.cache = new_hae; - *hae.reg = new_hae; + + alpha_mv.hae_cache = new_hae; + *alpha_mv.hae_register = new_hae; mb(); - new_hae = *hae.reg; /* read to make sure it was written */ + + /* Re-read to make sure it was written. */ + new_hae = *alpha_mv.hae_register; setipl(ipl); } +static inline void set_hae(unsigned long new_hae) +{ + if (new_hae != alpha_mv.hae_cache) + __set_hae(new_hae); +} + /* * Change virtual addresses to physical addresses and vv. */ -extern inline unsigned long virt_to_phys(volatile void * address) +static inline unsigned long virt_to_phys(volatile void * address) { return 0xffffffffUL & (unsigned long) address; } -extern inline void * phys_to_virt(unsigned long address) +static inline void * phys_to_virt(unsigned long address) { return (void *) (address + IDENT_ADDR); } @@ -76,45 +73,79 @@ #endif /* !__KERNEL__ */ /* - * EGCS 1.1 does a good job of using insxl. Expose this bit of - * the I/O process to the compiler. + * There are different chipsets to interface the Alpha CPUs to the world. */ -#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91 -# define __kernel_insbl(val, shift) (((val) & 0xfful) << ((shift) * 8)) -# define __kernel_inswl(val, shift) (((val) & 0xfffful) << ((shift) * 8)) +#ifdef CONFIG_ALPHA_GENERIC + +/* In a generic kernel, we always go through the machine vector. */ + +# define virt_to_bus(a) alpha_mv.mv_virt_to_bus(a) +# define bus_to_virt(a) alpha_mv.mv_bus_to_virt(a) + +# define __inb alpha_mv.mv_inb +# define __inw alpha_mv.mv_inw +# define __inl alpha_mv.mv_inl +# define __outb alpha_mv.mv_outb +# define __outw alpha_mv.mv_outw +# define __outl alpha_mv.mv_outl + +# define __readb(a) alpha_mv.mv_readb((unsigned long)(a)) +# define __readw(a) alpha_mv.mv_readw((unsigned long)(a)) +# define __readl(a) alpha_mv.mv_readl((unsigned long)(a)) +# define __readq(a) alpha_mv.mv_readq((unsigned long)(a)) +# define __writeb(v,a) alpha_mv.mv_writeb((v),(unsigned long)(a)) +# define __writew(v,a) alpha_mv.mv_writew((v),(unsigned long)(a)) +# define __writel(v,a) alpha_mv.mv_writel((v),(unsigned long)(a)) +# define __writeq(v,a) alpha_mv.mv_writeq((v),(unsigned long)(a)) + +# define inb __inb +# define inw __inw +# define inl __inl +# define outb __outb +# define outw __outw +# define outl __outl + +# define readb __readb +# define readw __readw +# define readl __readl +# define readq __readq +# define writeb __writeb +# define writew __writew +# define writel __writel +# define writeq __writeq + +# define dense_mem(a) alpha_mv.mv_dense_mem(a) + #else -# define __kernel_insbl(val, shift) \ - ({ unsigned long __kir; \ - __asm__("insbl %2,%1,%0" : "=r"(__kir) : "ri"(shift), "r"(val)); \ - __kir; }) -# define __kernel_inswl(val, shift) \ - ({ unsigned long __kir; \ - __asm__("inswl %2,%1,%0" : "=r"(__kir) : "ri"(shift), "r"(val)); \ - __kir; }) -#endif - -/* - * There are different chipsets to interface the Alpha CPUs to the world. - */ -#if defined(CONFIG_ALPHA_LCA) -# include /* get chip-specific definitions */ -#elif defined(CONFIG_ALPHA_APECS) -# include /* get chip-specific definitions */ + +/* Control how and what gets defined within the core logic headers. */ +#define __WANT_IO_DEF + +#if defined(CONFIG_ALPHA_APECS) +# include #elif defined(CONFIG_ALPHA_CIA) -# include /* get chip-specific definitions */ -#elif defined(CONFIG_ALPHA_T2) -# include /* get chip-specific definitions */ +# include +#elif defined(CONFIG_ALPHA_LCA) +# include +#elif defined(CONFIG_ALPHA_MCPCIA) +# include #elif defined(CONFIG_ALPHA_PYXIS) -# include /* get chip-specific definitions */ +# include +#elif defined(CONFIG_ALPHA_T2) +# include #elif defined(CONFIG_ALPHA_TSUNAMI) -# include /* get chip-specific definitions */ -#elif defined(CONFIG_ALPHA_MCPCIA) -# include /* get chip-specific definitions */ -#else +# include +#elif defined(CONFIG_ALPHA_JENSEN) # include +#else +#error "What system is this?" #endif +#undef __WANT_IO_DEF + +#endif /* GENERIC */ + /* * The convention used for inb/outb etc. is that names starting with * two underscores are the inline versions, names starting with a @@ -190,12 +221,12 @@ * On the alpha, we have the whole physical address space mapped at all * times, so "ioremap()" and "iounmap()" do not need to do anything. */ -extern inline void * ioremap(unsigned long offset, unsigned long size) +static inline void * ioremap(unsigned long offset, unsigned long size) { return (void *) offset; } -extern inline void iounmap(void *addr) +static inline void iounmap(void *addr) { } @@ -263,8 +294,9 @@ #define eth_io_copy_and_sum(skb,src,len,unused) \ memcpy_fromio((skb)->data,(src),(len)) -static inline int check_signature(unsigned long io_addr, - const unsigned char *signature, int length) +static inline int +check_signature(unsigned long io_addr, const unsigned char *signature, + int length) { int retval = 0; do { @@ -279,6 +311,29 @@ return retval; } -#endif /* __KERNEL__ */ +/* + * The Alpha Jensen hardware for some rather strange reason puts + * the RTC clock at 0x170 instead of 0x70. Probably due to some + * misguided idea about using 0x70 for NMI stuff. + * + * These defines will override the defaults when doing RTC queries + */ +#ifdef CONFIG_ALPHA_GENERIC +# define RTC_PORT(x) ((x) + alpha_mv.rtc_port) +# define RTC_ADDR(x) ((x) | alpha_mv.rtc_addr) +#else +# ifdef CONFIG_ALPHA_JENSEN +# define RTC_PORT(x) (0x170+(x)) +# define RTC_ADDR(x) (x) +# else +# define RTC_PORT(x) (0x70 + (x)) +# define RTC_ADDR(x) (0x80 | (x)) +# endif #endif + +#define RTC_ALWAYS_BCD 0 + +#endif /* __KERNEL__ */ + +#endif /* __ALPHA_IO_H */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/irq.h linux/include/asm-alpha/irq.h --- v2.1.115/linux/include/asm-alpha/irq.h Thu Apr 23 20:21:37 1998 +++ linux/include/asm-alpha/irq.h Sun Aug 9 12:09:06 1998 @@ -10,18 +10,24 @@ #include #include -#if defined(CONFIG_ALPHA_CABRIOLET) || \ +#if defined(CONFIG_ALPHA_GENERIC) + +/* Here NR_IRQS is not exact, but rather an upper bound. This is used + many places throughout the kernel to size static arrays. That's ok, + we'll use alpha_mv.nr_irqs when we want the real thing. */ + +# define NR_IRQS 64 + +#elif defined(CONFIG_ALPHA_CABRIOLET) || \ defined(CONFIG_ALPHA_EB66P) || \ defined(CONFIG_ALPHA_EB164) || \ defined(CONFIG_ALPHA_PC164) || \ - defined(CONFIG_ALPHA_LX164) - + defined(CONFIG_ALPHA_LX164) # define NR_IRQS 35 #elif defined(CONFIG_ALPHA_EB66) || \ defined(CONFIG_ALPHA_EB64P) || \ - defined(CONFIG_ALPHA_MIKASA) - + defined(CONFIG_ALPHA_MIKASA) # define NR_IRQS 32 #elif defined(CONFIG_ALPHA_ALCOR) || \ @@ -29,29 +35,52 @@ defined(CONFIG_ALPHA_MIATA) || \ defined(CONFIG_ALPHA_RUFFIAN) || \ defined(CONFIG_ALPHA_NORITAKE) - # define NR_IRQS 48 #elif defined(CONFIG_ALPHA_SABLE) || \ defined(CONFIG_ALPHA_SX164) - # define NR_IRQS 40 #elif defined(CONFIG_ALPHA_DP264) || \ defined(CONFIG_ALPHA_RAWHIDE) - # define NR_IRQS 64 #elif defined(CONFIG_ALPHA_TAKARA) - # define NR_IRQS 20 #else /* everyone else */ - # define NR_IRQS 16 +#endif +/* + * PROBE_MASK is the bitset of irqs that we consider for autoprobing. + */ + +/* The normal mask includes all the IRQs except the timer. */ +#define _PROBE_MASK(nr_irqs) (((1UL << (nr_irqs & 63)) - 1) & ~1UL) + +/* Mask out unused timer irq 0 and RTC irq 8. */ +#define P2K_PROBE_MASK (_PROBE_MASK(16) & ~0x101UL) + +/* Mask out unused timer irq 0, "irqs" 20-30, and the EISA cascade. */ +#define ALCOR_PROBE_MASK (_PROBE_MASK(48) & ~0xfff000000001UL) + +/* Leave timer irq 0 in the mask. */ +#define RUFFIAN_PROBE_MASK (_PROBE_MASK(48) | 1UL) + +#if defined(CONFIG_ALPHA_GENERIC) +# define PROBE_MASK alpha_mv.irq_probe_mask +#elif defined(CONFIG_ALPHA_P2K) +# define PROBE_MASK P2K_PROBE_MASK +#elif defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT) +# define PROBE_MASK ALCOR_PROBE_MASK +#elif defined(CONFIG_ALPHA_RUFFIAN) +# define PROBE_MASK RUFFIAN_PROBE_MASK +#else +# define PROBE_MASK _PROBE_MASK(NR_IRQS) #endif + static __inline__ int irq_cannonicalize(int irq) { /* @@ -64,4 +93,4 @@ extern void disable_irq(unsigned int); extern void enable_irq(unsigned int); -#endif +#endif /* _ALPHA_IRQ_H */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/jensen.h linux/include/asm-alpha/jensen.h --- v2.1.115/linux/include/asm-alpha/jensen.h Tue Jul 21 00:15:32 1998 +++ linux/include/asm-alpha/jensen.h Sun Aug 9 12:09:06 1998 @@ -1,6 +1,8 @@ #ifndef __ALPHA_JENSEN_H #define __ALPHA_JENSEN_H +#include + /* * Defines for the AlphaPC EISA IO and memory address space. */ @@ -66,6 +68,14 @@ */ #define EISA_IO (IDENT_ADDR + 0x300000000UL) + +#ifdef __KERNEL__ + +#ifndef __EXTERN_INLINE +#define __EXTERN_INLINE extern inline +#define __IO_EXTERN_INLINE +#endif + /* * Change virtual addresses to bus addresses and vv. * @@ -73,10 +83,16 @@ * as the bus address, but this is not necessarily true on * other alpha hardware. */ -#define virt_to_bus virt_to_phys -#define bus_to_virt phys_to_virt +__EXTERN_INLINE unsigned long jensen_virt_to_bus(void * address) +{ + return virt_to_phys(address); +} + +__EXTERN_INLINE void * jensen_bus_to_virt(unsigned long address) +{ + return phys_to_virt(address); +} -#define HAE_ADDRESS EISA_HAE /* * Handle the "host address register". This needs to be set @@ -86,16 +102,19 @@ * * HAE isn't needed for the local IO operations, though. */ -#define __HAE_MASK 0x1ffffff -extern inline void __set_hae(unsigned long addr) + +#define JENSEN_HAE_ADDRESS EISA_HAE +#define JENSEN_HAE_MASK 0x1ffffff + +__EXTERN_INLINE void jensen_set_hae(unsigned long addr) { /* hae on the Jensen is bits 31:25 shifted right */ addr >>= 25; - if (addr != hae.cache) + if (addr != alpha_mv.hae_cache) set_hae(addr); } -#ifdef __KERNEL__ +#define vuip volatile unsigned int * /* * IO functions @@ -108,36 +127,31 @@ * gone in the PCI version. I hope I can get DEC suckered^H^H^H^H^H^H^H^H * convinced that I need one of the newer machines. */ -extern inline unsigned int __local_inb(unsigned long addr) + +static inline unsigned int jensen_local_inb(unsigned long addr) { - long result = *(volatile int *) ((addr << 9) + EISA_VL82C106); - return 0xffUL & result; + return 0xff & *(vuip)((addr << 9) + EISA_VL82C106); } -extern inline void __local_outb(unsigned char b, unsigned long addr) +static inline void jensen_local_outb(unsigned char b, unsigned long addr) { - *(volatile unsigned int *) ((addr << 9) + EISA_VL82C106) = b; + *(vuip)((addr << 9) + EISA_VL82C106) = b; mb(); } -extern unsigned int _bus_inb(unsigned long addr); - -extern inline unsigned int __bus_inb(unsigned long addr) +static inline unsigned int jensen_bus_inb(unsigned long addr) { long result; - __set_hae(0); - result = *(volatile int *) ((addr << 7) + EISA_IO + 0x00); - result >>= (addr & 3) * 8; - return 0xffUL & result; + jensen_set_hae(0); + result = *(volatile int *)((addr << 7) + EISA_IO + 0x00); + return __kernel_extbl(result, addr & 3); } -extern void _bus_outb(unsigned char b, unsigned long addr); - -extern inline void __bus_outb(unsigned char b, unsigned long addr) +static inline void jensen_bus_outb(unsigned char b, unsigned long addr) { - __set_hae(0); - *(volatile unsigned int *) ((addr << 7) + EISA_IO + 0x00) = b * 0x01010101; + jensen_set_hae(0); + *(vuip)((addr << 7) + EISA_IO + 0x00) = b * 0x01010101; mb(); } @@ -146,131 +160,165 @@ * operations that result in operations across inline functions. * Which is why this is a macro. */ -#define __is_local(addr) ( \ + +#define jensen_is_local(addr) ( \ /* keyboard */ (addr == 0x60 || addr == 0x64) || \ /* RTC */ (addr == 0x170 || addr == 0x171) || \ /* mb COM2 */ (addr >= 0x2f8 && addr <= 0x2ff) || \ /* mb LPT1 */ (addr >= 0x3bc && addr <= 0x3be) || \ /* mb COM2 */ (addr >= 0x3f8 && addr <= 0x3ff)) -extern inline unsigned int __inb(unsigned long addr) +__EXTERN_INLINE unsigned int jensen_inb(unsigned long addr) { - if (__is_local(addr)) - return __local_inb(addr); - return _bus_inb(addr); + if (jensen_is_local(addr)) + return jensen_local_inb(addr); + else + return jensen_bus_inb(addr); } -extern inline void __outb(unsigned char b, unsigned long addr) +__EXTERN_INLINE void jensen_outb(unsigned char b, unsigned long addr) { - if (__is_local(addr)) - __local_outb(b, addr); + if (jensen_is_local(addr)) + jensen_local_outb(b, addr); else - _bus_outb(b, addr); + jensen_bus_outb(b, addr); } -extern inline unsigned int __inw(unsigned long addr) +__EXTERN_INLINE unsigned int jensen_inw(unsigned long addr) { long result; - __set_hae(0); + jensen_set_hae(0); result = *(volatile int *) ((addr << 7) + EISA_IO + 0x20); result >>= (addr & 3) * 8; return 0xffffUL & result; } -extern inline unsigned int __inl(unsigned long addr) +__EXTERN_INLINE unsigned int jensen_inl(unsigned long addr) { - __set_hae(0); - return *(volatile unsigned int *) ((addr << 7) + EISA_IO + 0x60); + jensen_set_hae(0); + return *(vuip) ((addr << 7) + EISA_IO + 0x60); } -extern inline void __outw(unsigned short b, unsigned long addr) +__EXTERN_INLINE void jensen_outw(unsigned short b, unsigned long addr) { - __set_hae(0); - *(volatile unsigned int *) ((addr << 7) + EISA_IO + 0x20) = b * 0x00010001; + jensen_set_hae(0); + *(vuip) ((addr << 7) + EISA_IO + 0x20) = b * 0x00010001; mb(); } -extern inline void __outl(unsigned int b, unsigned long addr) +__EXTERN_INLINE void jensen_outl(unsigned int b, unsigned long addr) { - __set_hae(0); - *(volatile unsigned int *) ((addr << 7) + EISA_IO + 0x60) = b; + jensen_set_hae(0); + *(vuip) ((addr << 7) + EISA_IO + 0x60) = b; mb(); } /* * Memory functions. */ -extern inline unsigned long __readb(unsigned long addr) + +__EXTERN_INLINE unsigned long jensen_readb(unsigned long addr) { long result; - __set_hae(addr); - addr &= __HAE_MASK; + jensen_set_hae(addr); + addr &= JENSEN_HAE_MASK; result = *(volatile int *) ((addr << 7) + EISA_MEM + 0x00); result >>= (addr & 3) * 8; return 0xffUL & result; } -extern inline unsigned long __readw(unsigned long addr) +__EXTERN_INLINE unsigned long jensen_readw(unsigned long addr) { long result; - __set_hae(addr); - addr &= __HAE_MASK; + jensen_set_hae(addr); + addr &= JENSEN_HAE_MASK; result = *(volatile int *) ((addr << 7) + EISA_MEM + 0x20); result >>= (addr & 3) * 8; return 0xffffUL & result; } -extern inline unsigned long __readl(unsigned long addr) +__EXTERN_INLINE unsigned long jensen_readl(unsigned long addr) { - __set_hae(addr); - addr &= __HAE_MASK; - return *(volatile unsigned int *) ((addr << 7) + EISA_MEM + 0x60); + jensen_set_hae(addr); + addr &= JENSEN_HAE_MASK; + return *(vuip) ((addr << 7) + EISA_MEM + 0x60); } -extern inline unsigned long __readq(unsigned long addr) +__EXTERN_INLINE unsigned long jensen_readq(unsigned long addr) { unsigned long r0, r1; - __set_hae(addr); - addr &= __HAE_MASK; + + jensen_set_hae(addr); + addr &= JENSEN_HAE_MASK; addr = (addr << 7) + EISA_MEM + 0x60; - r0 = *(volatile unsigned int *) (addr); - r1 = *(volatile unsigned int *) (addr + (4 << 7)); + r0 = *(vuip) (addr); + r1 = *(vuip) (addr + (4 << 7)); return r1 << 32 | r0; } -extern inline void __writeb(unsigned short b, unsigned long addr) +__EXTERN_INLINE void jensen_writeb(unsigned char b, unsigned long addr) { - __set_hae(addr); - addr &= __HAE_MASK; - *(volatile unsigned int *) ((addr << 7) + EISA_MEM + 0x00) = b * 0x01010101; + jensen_set_hae(addr); + addr &= JENSEN_HAE_MASK; + *(vuip) ((addr << 7) + EISA_MEM + 0x00) = b * 0x01010101; } -extern inline void __writew(unsigned short b, unsigned long addr) +__EXTERN_INLINE void jensen_writew(unsigned short b, unsigned long addr) { - __set_hae(addr); - addr &= __HAE_MASK; - *(volatile unsigned int *) ((addr << 7) + EISA_MEM + 0x20) = b * 0x00010001; + jensen_set_hae(addr); + addr &= JENSEN_HAE_MASK; + *(vuip) ((addr << 7) + EISA_MEM + 0x20) = b * 0x00010001; } -extern inline void __writel(unsigned int b, unsigned long addr) +__EXTERN_INLINE void jensen_writel(unsigned int b, unsigned long addr) { - __set_hae(addr); - addr &= __HAE_MASK; - *(volatile unsigned int *) ((addr << 7) + EISA_MEM + 0x60) = b; + jensen_set_hae(addr); + addr &= JENSEN_HAE_MASK; + *(vuip) ((addr << 7) + EISA_MEM + 0x60) = b; } -extern inline void __writeq(unsigned long b, unsigned long addr) +__EXTERN_INLINE void jensen_writeq(unsigned long b, unsigned long addr) { - __set_hae(addr); - addr &= __HAE_MASK; + jensen_set_hae(addr); + addr &= JENSEN_HAE_MASK; addr = (addr << 7) + EISA_MEM + 0x60; - *(volatile unsigned int *) (addr) = b; - *(volatile unsigned int *) (addr + (4 << 7)) = b >> 32; + *(vuip) (addr) = b; + *(vuip) (addr + (4 << 7)) = b >> 32; } +/* Find the DENSE memory area for a given bus address. + Whee, there is none. */ + +__EXTERN_INLINE unsigned long jensen_dense_mem(unsigned long addr) +{ + return 0; +} + +#undef vuip + +#ifdef __WANT_IO_DEF + +#define virt_to_bus jensen_virt_to_bus +#define bus_to_virt jensen_bus_to_virt +#define __inb jensen_inb +#define __inw jensen_inw +#define __inl jensen_inl +#define __outb jensen_outb +#define __outw jensen_outw +#define __outl jensen_outl +#define __readb jensen_readb +#define __readw jensen_readw +#define __writeb jensen_writeb +#define __writew jensen_writew +#define __readl jensen_readl +#define __readq jensen_readq +#define __writel jensen_writel +#define __writeq jensen_writeq +#define dense_mem jensen_dense_mem + /* * The above have so much overhead that it probably doesn't make * sense to have them inlined (better icache behaviour). @@ -281,17 +329,13 @@ #define outb(x, port) \ (__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port))) -#endif /* __KERNEL__ */ - -/* - * The Alpha Jensen hardware for some rather strange reason puts - * the RTC clock at 0x170 instead of 0x70. Probably due to some - * misguided idea about using 0x70 for NMI stuff. - * - * These defines will override the defaults when doing RTC queries - */ -#define RTC_PORT(x) (0x170+(x)) -#define RTC_ADDR(x) (x) -#define RTC_ALWAYS_BCD 0 +#endif /* __WANT_IO_DEF */ +#ifdef __IO_EXTERN_INLINE +#undef __EXTERN_INLINE +#undef __IO_EXTERN_INLINE #endif + +#endif /* __KERNEL__ */ + +#endif /* __ALPHA_JENSEN_H */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/lca.h linux/include/asm-alpha/lca.h --- v2.1.115/linux/include/asm-alpha/lca.h Tue Jul 21 00:15:32 1998 +++ linux/include/asm-alpha/lca.h Wed Dec 31 16:00:00 1969 @@ -1,414 +0,0 @@ -#ifndef __ALPHA_LCA__H__ -#define __ALPHA_LCA__H__ - -/* - * Low Cost Alpha (LCA) definitions (these apply to 21066 and 21068, - * for example). - * - * This file is based on: - * - * DECchip 21066 and DECchip 21068 Alpha AXP Microprocessors - * Hardware Reference Manual; Digital Equipment Corp.; May 1994; - * Maynard, MA; Order Number: EC-N2681-71. - */ - -/* - * NOTE: The LCA uses a Host Address Extension (HAE) register to access - * PCI addresses that are beyond the first 27 bits of address - * space. Updating the HAE requires an external cycle (and - * a memory barrier), which tends to be slow. Instead of updating - * it on each sparse memory access, we keep the current HAE value - * cached in variable cache_hae. Only if the cached HAE differs - * from the desired HAE value do we actually updated HAE register. - * The HAE register is preserved by the interrupt handler entry/exit - * code, so this scheme works even in the presence of interrupts. - * - * Dense memory space doesn't require the HAE, but is restricted to - * aligned 32 and 64 bit accesses. Special Cycle and Interrupt - * Acknowledge cycles may also require the use of the HAE. The LCA - * limits I/O address space to the bottom 24 bits of address space, - * but this easily covers the 16 bit ISA I/O address space. - */ - -/* - * NOTE 2! The memory operations do not set any memory barriers, as - * it's not needed for cases like a frame buffer that is essentially - * memory-like. You need to do them by hand if the operations depend - * on ordering. - * - * Similarly, the port I/O operations do a "mb" only after a write - * operation: if an mb is needed before (as in the case of doing - * memory mapped I/O first, and then a port I/O operation to the same - * device), it needs to be done by hand. - * - * After the above has bitten me 100 times, I'll give up and just do - * the mb all the time, but right now I'm hoping this will work out. - * Avoiding mb's may potentially be a noticeable speed improvement, - * but I can't honestly say I've tested it. - * - * Handling interrupts that need to do mb's to synchronize to - * non-interrupts is another fun race area. Don't do it (because if - * you do, I'll have to do *everything* with interrupts disabled, - * ugh). - */ - -#include -#include - -#ifdef CONFIG_ALPHA_SRM_SETUP -/* if we are using the SRM PCI setup, we'll need to use variables instead */ -#define LCA_DMA_WIN_BASE_DEFAULT (1024*1024*1024) -#define LCA_DMA_WIN_SIZE_DEFAULT (1024*1024*1024) - -extern unsigned int LCA_DMA_WIN_BASE; -extern unsigned int LCA_DMA_WIN_SIZE; - -#else /* SRM_SETUP */ -#define LCA_DMA_WIN_BASE (1024*1024*1024) -#define LCA_DMA_WIN_SIZE (1024*1024*1024) -#endif /* SRM_SETUP */ - -/* - * Memory Controller registers: - */ -#define LCA_MEM_BCR0 (IDENT_ADDR + 0x120000000UL) -#define LCA_MEM_BCR1 (IDENT_ADDR + 0x120000008UL) -#define LCA_MEM_BCR2 (IDENT_ADDR + 0x120000010UL) -#define LCA_MEM_BCR3 (IDENT_ADDR + 0x120000018UL) -#define LCA_MEM_BMR0 (IDENT_ADDR + 0x120000020UL) -#define LCA_MEM_BMR1 (IDENT_ADDR + 0x120000028UL) -#define LCA_MEM_BMR2 (IDENT_ADDR + 0x120000030UL) -#define LCA_MEM_BMR3 (IDENT_ADDR + 0x120000038UL) -#define LCA_MEM_BTR0 (IDENT_ADDR + 0x120000040UL) -#define LCA_MEM_BTR1 (IDENT_ADDR + 0x120000048UL) -#define LCA_MEM_BTR2 (IDENT_ADDR + 0x120000050UL) -#define LCA_MEM_BTR3 (IDENT_ADDR + 0x120000058UL) -#define LCA_MEM_GTR (IDENT_ADDR + 0x120000060UL) -#define LCA_MEM_ESR (IDENT_ADDR + 0x120000068UL) -#define LCA_MEM_EAR (IDENT_ADDR + 0x120000070UL) -#define LCA_MEM_CAR (IDENT_ADDR + 0x120000078UL) -#define LCA_MEM_VGR (IDENT_ADDR + 0x120000080UL) -#define LCA_MEM_PLM (IDENT_ADDR + 0x120000088UL) -#define LCA_MEM_FOR (IDENT_ADDR + 0x120000090UL) - -/* - * I/O Controller registers: - */ -#define LCA_IOC_HAE (IDENT_ADDR + 0x180000000UL) -#define LCA_IOC_CONF (IDENT_ADDR + 0x180000020UL) -#define LCA_IOC_STAT0 (IDENT_ADDR + 0x180000040UL) -#define LCA_IOC_STAT1 (IDENT_ADDR + 0x180000060UL) -#define LCA_IOC_TBIA (IDENT_ADDR + 0x180000080UL) -#define LCA_IOC_TB_ENA (IDENT_ADDR + 0x1800000a0UL) -#define LCA_IOC_SFT_RST (IDENT_ADDR + 0x1800000c0UL) -#define LCA_IOC_PAR_DIS (IDENT_ADDR + 0x1800000e0UL) -#define LCA_IOC_W_BASE0 (IDENT_ADDR + 0x180000100UL) -#define LCA_IOC_W_BASE1 (IDENT_ADDR + 0x180000120UL) -#define LCA_IOC_W_MASK0 (IDENT_ADDR + 0x180000140UL) -#define LCA_IOC_W_MASK1 (IDENT_ADDR + 0x180000160UL) -#define LCA_IOC_T_BASE0 (IDENT_ADDR + 0x180000180UL) -#define LCA_IOC_T_BASE1 (IDENT_ADDR + 0x1800001a0UL) -#define LCA_IOC_TB_TAG0 (IDENT_ADDR + 0x188000000UL) -#define LCA_IOC_TB_TAG1 (IDENT_ADDR + 0x188000020UL) -#define LCA_IOC_TB_TAG2 (IDENT_ADDR + 0x188000040UL) -#define LCA_IOC_TB_TAG3 (IDENT_ADDR + 0x188000060UL) -#define LCA_IOC_TB_TAG4 (IDENT_ADDR + 0x188000070UL) -#define LCA_IOC_TB_TAG5 (IDENT_ADDR + 0x1880000a0UL) -#define LCA_IOC_TB_TAG6 (IDENT_ADDR + 0x1880000c0UL) -#define LCA_IOC_TB_TAG7 (IDENT_ADDR + 0x1880000e0UL) - -/* - * Memory spaces: - */ -#define LCA_IACK_SC (IDENT_ADDR + 0x1a0000000UL) -#define LCA_CONF (IDENT_ADDR + 0x1e0000000UL) -#define LCA_IO (IDENT_ADDR + 0x1c0000000UL) -#define LCA_SPARSE_MEM (IDENT_ADDR + 0x200000000UL) -#define LCA_DENSE_MEM (IDENT_ADDR + 0x300000000UL) -#define DENSE_MEM(addr) LCA_DENSE_MEM - -/* - * Bit definitions for I/O Controller status register 0: - */ -#define LCA_IOC_STAT0_CMD 0xf -#define LCA_IOC_STAT0_ERR (1<<4) -#define LCA_IOC_STAT0_LOST (1<<5) -#define LCA_IOC_STAT0_THIT (1<<6) -#define LCA_IOC_STAT0_TREF (1<<7) -#define LCA_IOC_STAT0_CODE_SHIFT 8 -#define LCA_IOC_STAT0_CODE_MASK 0x7 -#define LCA_IOC_STAT0_P_NBR_SHIFT 13 -#define LCA_IOC_STAT0_P_NBR_MASK 0x7ffff - -#define HAE_ADDRESS LCA_IOC_HAE - -/* LCA PMR Power Management register defines */ -#define LCA_PMR_ADDR (IDENT_ADDR + 0x120000098UL) -#define LCA_PMR_PDIV 0x7 /* Primary clock divisor */ -#define LCA_PMR_ODIV 0x38 /* Override clock divisor */ -#define LCA_PMR_INTO 0x40 /* Interrupt override */ -#define LCA_PMR_DMAO 0x80 /* DMA override */ -#define LCA_PMR_OCCEB 0xffff0000L /* Override cycle counter - even - bits */ -#define LCA_PMR_OCCOB 0xffff000000000000L /* Override cycle counter - even - bits */ -#define LCA_PMR_PRIMARY_MASK 0xfffffffffffffff8 -/* LCA PMR Macros */ - -#define READ_PMR (*(volatile unsigned long *)LCA_PMR_ADDR) -#define WRITE_PMR(d) (*((volatile unsigned long *)LCA_PMR_ADDR) = (d)) - -#define GET_PRIMARY(r) ((r) & LCA_PMR_PDIV) -#define GET_OVERRIDE(r) (((r) >> 3) & LCA_PMR_PDIV) -#define SET_PRIMARY_CLOCK(r, c) ((r) = (((r) & LCA_PMR_PRIMARY_MASK) | (c))) - -/* LCA PMR Divisor values */ -#define DIV_1 0x0 -#define DIV_1_5 0x1 -#define DIV_2 0x2 -#define DIV_4 0x3 -#define DIV_8 0x4 -#define DIV_16 0x5 -#define DIV_MIN DIV_1 -#define DIV_MAX DIV_16 - - -#ifdef __KERNEL__ - -/* - * Translate physical memory address as seen on (PCI) bus into - * a kernel virtual address and vv. - */ -extern inline unsigned long virt_to_bus(void * address) -{ - return virt_to_phys(address) + LCA_DMA_WIN_BASE; -} - -extern inline void * bus_to_virt(unsigned long address) -{ - /* - * This check is a sanity check but also ensures that bus - * address 0 maps to virtual address 0 which is useful to - * detect null "pointers" (the NCR driver is much simpler if - * NULL pointers are preserved). - */ - if (address < LCA_DMA_WIN_BASE) - return 0; - return phys_to_virt(address - LCA_DMA_WIN_BASE); -} - -/* - * I/O functions: - * - * Unlike Jensen, the Noname machines have no concept of local - * I/O---everything goes over the PCI bus. - * - * There is plenty room for optimization here. In particular, - * the Alpha's insb/insw/extb/extw should be useful in moving - * data to/from the right byte-lanes. - */ - -#define vuip volatile unsigned int * -#define vulp volatile unsigned long * - -extern inline unsigned int __inb(unsigned long addr) -{ - long result = *(vuip) ((addr << 5) + LCA_IO + 0x00); - result >>= (addr & 3) * 8; - return 0xffUL & result; -} - -extern inline void __outb(unsigned char b, unsigned long addr) -{ - unsigned int w; - - w = __kernel_insbl(b, addr & 3); - *(vuip) ((addr << 5) + LCA_IO + 0x00) = w; - mb(); -} - -extern inline unsigned int __inw(unsigned long addr) -{ - long result = *(vuip) ((addr << 5) + LCA_IO + 0x08); - result >>= (addr & 3) * 8; - return 0xffffUL & result; -} - -extern inline void __outw(unsigned short b, unsigned long addr) -{ - unsigned int w; - - w = __kernel_inswl(b, addr & 3); - *(vuip) ((addr << 5) + LCA_IO + 0x08) = w; - mb(); -} - -extern inline unsigned int __inl(unsigned long addr) -{ - return *(vuip) ((addr << 5) + LCA_IO + 0x18); -} - -extern inline void __outl(unsigned int b, unsigned long addr) -{ - *(vuip) ((addr << 5) + LCA_IO + 0x18) = b; - mb(); -} - - -/* - * Memory functions. 64-bit and 32-bit accesses are done through - * dense memory space, everything else through sparse space. - */ -extern inline unsigned long __readb(unsigned long addr) -{ - unsigned long result, shift, msb; - - shift = (addr & 0x3) * 8; - if (addr >= (1UL << 24)) { - msb = addr & 0xf8000000; - addr -= msb; - if (msb != hae.cache) { - set_hae(msb); - } - } - result = *(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x00); - result >>= shift; - return 0xffUL & result; -} - -extern inline unsigned long __readw(unsigned long addr) -{ - unsigned long result, shift, msb; - - shift = (addr & 0x3) * 8; - if (addr >= (1UL << 24)) { - msb = addr & 0xf8000000; - addr -= msb; - if (msb != hae.cache) { - set_hae(msb); - } - } - result = *(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x08); - result >>= shift; - return 0xffffUL & result; -} - -extern inline unsigned long __readl(unsigned long addr) -{ - return *(vuip) (addr + LCA_DENSE_MEM); -} - -extern inline unsigned long __readq(unsigned long addr) -{ - return *(vulp) (addr + LCA_DENSE_MEM); -} - -extern inline void __writeb(unsigned char b, unsigned long addr) -{ - unsigned long msb; - unsigned int w; - - if (addr >= (1UL << 24)) { - msb = addr & 0xf8000000; - addr -= msb; - if (msb != hae.cache) { - set_hae(msb); - } - } - asm ("insbl %2,%1,%0" : "r="(w) : "ri"(addr & 0x3), "r"(b)); - *(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x00) = w; -} - -extern inline void __writew(unsigned short b, unsigned long addr) -{ - unsigned long msb; - unsigned int w; - - if (addr >= (1UL << 24)) { - msb = addr & 0xf8000000; - addr -= msb; - if (msb != hae.cache) { - set_hae(msb); - } - } - asm ("inswl %2,%1,%0" : "r="(w) : "ri"(addr & 0x3), "r"(b)); - *(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x08) = w; -} - -extern inline void __writel(unsigned int b, unsigned long addr) -{ - *(vuip) (addr + LCA_DENSE_MEM) = b; -} - -extern inline void __writeq(unsigned long b, unsigned long addr) -{ - *(vulp) (addr + LCA_DENSE_MEM) = b; -} - -/* - * Most of the above have so much overhead that it probably doesn't - * make sense to have them inlined (better icache behavior). - */ - -#define inb(port) \ -(__builtin_constant_p((port))?__inb(port):_inb(port)) - -#define outb(x, port) \ -(__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port))) - -#define readl(a) __readl((unsigned long)(a)) -#define readq(a) __readq((unsigned long)(a)) -#define writel(v,a) __writel((v),(unsigned long)(a)) -#define writeq(v,a) __writeq((v),(unsigned long)(a)) - -#undef vuip -#undef vulp - -extern unsigned long lca_init (unsigned long mem_start, unsigned long mem_end); - -#endif /* __KERNEL__ */ - -/* - * Data structure for handling LCA machine checks. Correctable errors - * result in a short logout frame, uncorrectable ones in a long one. - */ -struct el_lca_mcheck_short { - struct el_common h; /* common logout header */ - unsigned long esr; /* error-status register */ - unsigned long ear; /* error-address register */ - unsigned long dc_stat; /* dcache status register */ - unsigned long ioc_stat0; /* I/O controller status register 0 */ - unsigned long ioc_stat1; /* I/O controller status register 1 */ -}; - -struct el_lca_mcheck_long { - struct el_common h; /* common logout header */ - unsigned long pt[31]; /* PAL temps */ - unsigned long exc_addr; /* exception address */ - unsigned long pad1[3]; - unsigned long pal_base; /* PALcode base address */ - unsigned long hier; /* hw interrupt enable */ - unsigned long hirr; /* hw interrupt request */ - unsigned long mm_csr; /* MMU control & status */ - unsigned long dc_stat; /* data cache status */ - unsigned long dc_addr; /* data cache addr register */ - unsigned long abox_ctl; /* address box control register */ - unsigned long esr; /* error status register */ - unsigned long ear; /* error address register */ - unsigned long car; /* cache control register */ - unsigned long ioc_stat0; /* I/O controller status register 0 */ - unsigned long ioc_stat1; /* I/O controller status register 1 */ - unsigned long va; /* virtual address register */ -}; - -union el_lca { - struct el_common * c; - struct el_lca_mcheck_long * l; - struct el_lca_mcheck_short * s; -}; - -#define RTC_PORT(x) (0x70 + (x)) -#define RTC_ADDR(x) (0x80 | (x)) -#define RTC_ALWAYS_BCD 0 - -#endif /* __ALPHA_LCA__H__ */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/machvec.h linux/include/asm-alpha/machvec.h --- v2.1.115/linux/include/asm-alpha/machvec.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-alpha/machvec.h Sun Aug 9 12:09:06 1998 @@ -0,0 +1,118 @@ +#ifndef __ALPHA_MACHVEC_H +#define __ALPHA_MACHVEC_H 1 + +#include +#include + + +/* The following structure vectors all of the I/O and IRQ manipulation + from the generic kernel to the hardware specific backend. */ + +struct task_struct; +struct mm_struct; +struct pt_regs; +struct vm_area_struct; + +struct alpha_machine_vector +{ + /* This "belongs" down below with the rest of the runtime + variables, but it is convenient for entry.S if these + two slots are at the beginning of the struct. */ + unsigned long hae_cache; + unsigned long *hae_register; + + unsigned long max_dma_address; + unsigned int nr_irqs; + unsigned int rtc_port, rtc_addr; + unsigned int max_asn; + unsigned long mmu_context_mask; + unsigned long irq_probe_mask; + unsigned long iack_sc; + + unsigned long (*mv_virt_to_bus)(void *); + void * (*mv_bus_to_virt)(unsigned long); + + unsigned int (*mv_inb)(unsigned long); + unsigned int (*mv_inw)(unsigned long); + unsigned int (*mv_inl)(unsigned long); + + void (*mv_outb)(unsigned char, unsigned long); + void (*mv_outw)(unsigned short, unsigned long); + void (*mv_outl)(unsigned int, unsigned long); + + unsigned long (*mv_readb)(unsigned long); + unsigned long (*mv_readw)(unsigned long); + unsigned long (*mv_readl)(unsigned long); + unsigned long (*mv_readq)(unsigned long); + + void (*mv_writeb)(unsigned char, unsigned long); + void (*mv_writew)(unsigned short, unsigned long); + void (*mv_writel)(unsigned int, unsigned long); + void (*mv_writeq)(unsigned long, unsigned long); + + unsigned long (*mv_dense_mem)(unsigned long); + + int (*pci_read_config_byte)(u8, u8, u8, u8 *value); + int (*pci_read_config_word)(u8, u8, u8, u16 *value); + int (*pci_read_config_dword)(u8, u8, u8, u32 *value); + + int (*pci_write_config_byte)(u8, u8, u8, u8 value); + int (*pci_write_config_word)(u8, u8, u8, u16 value); + int (*pci_write_config_dword)(u8, u8, u8, u32 value); + + void (*mv_get_mmu_context)(struct task_struct *); + void (*mv_flush_tlb_current)(struct mm_struct *); + void (*mv_flush_tlb_other)(struct mm_struct *); + void (*mv_flush_tlb_current_page)(struct mm_struct * mm, + struct vm_area_struct *vma, + unsigned long addr); + + void (*update_irq_hw)(unsigned long, unsigned long, int); + void (*ack_irq)(unsigned long); + void (*device_interrupt)(unsigned long vector, struct pt_regs *regs); + void (*machine_check)(u64 vector, u64 la, struct pt_regs *regs); + + void (*init_arch)(unsigned long *, unsigned long *); + void (*init_irq)(void); + void (*init_pit)(void); + void (*pci_fixup)(void); + void (*kill_arch)(int, char *); + + const char *vector_name; + + /* System specific parameters. */ + union { + struct { + unsigned long gru_int_req_bits; + } cia; + + struct { + unsigned long gamma_bias; + } t2; + } sys; + + /* Runtime variables it is handy to keep close. */ + unsigned long dma_win_base; + unsigned long dma_win_size; + unsigned long sm_base_r1, sm_base_r2, sm_base_r3; +}; + +extern struct alpha_machine_vector alpha_mv; + +#ifdef CONFIG_ALPHA_GENERIC +extern int alpha_using_srm; +extern int alpha_use_srm_setup; +#else +#ifdef CONFIG_ALPHA_SRM +#define alpha_using_srm 1 +#else +#define alpha_using_srm 0 +#endif +#if defined(CONFIG_ALPHA_SRM_SETUP) +#define alpha_use_srm_setup 1 +#else +#define alpha_use_srm_setup 0 +#endif +#endif /* GENERIC */ + +#endif /* __ALPHA_MACHVEC_H */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/mcpcia.h linux/include/asm-alpha/mcpcia.h --- v2.1.115/linux/include/asm-alpha/mcpcia.h Tue Jul 21 00:15:32 1998 +++ linux/include/asm-alpha/mcpcia.h Wed Dec 31 16:00:00 1969 @@ -1,690 +0,0 @@ -#ifndef __ALPHA_MCPCIA__H__ -#define __ALPHA_MCPCIA__H__ - -#include -#include -#include - -/* - * MCPCIA is the internal name for a core logic chipset which provides - * PCI access for the RAWHIDE family of systems. - * - * This file is based on: - * - * RAWHIDE System Programmer's Manual - * 16-May-96 - * Rev. 1.4 - * - */ - -/*------------------------------------------------------------------------** -** ** -** I/O procedures ** -** ** -** inport[b|w|t|l], outport[b|w|t|l] 8:16:24:32 IO xfers ** -** inportbxt: 8 bits only ** -** inport: alias of inportw ** -** outport: alias of outportw ** -** ** -** inmem[b|w|t|l], outmem[b|w|t|l] 8:16:24:32 ISA memory xfers ** -** inmembxt: 8 bits only ** -** inmem: alias of inmemw ** -** outmem: alias of outmemw ** -** ** -**------------------------------------------------------------------------*/ - - -/* MCPCIA ADDRESS BIT DEFINITIONS - * - * 3 3 3 3|3 3 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 - * 9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * |1| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |0|0|0| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | \_/ \_/ - * | | | - * +-- IO space, not cached. Byte Enable --+ | - * Transfer Length --+ - * - * - * - * Byte Transfer - * Enable Length Transfer Byte Address - * adr<6:5> adr<4:3> Length Enable Adder - * --------------------------------------------- - * 00 00 Byte 1110 0x000 - * 01 00 Byte 1101 0x020 - * 10 00 Byte 1011 0x040 - * 11 00 Byte 0111 0x060 - * - * 00 01 Word 1100 0x008 - * 01 01 Word 1001 0x028 <= Not supported in this code. - * 10 01 Word 0011 0x048 - * - * 00 10 Tribyte 1000 0x010 - * 01 10 Tribyte 0001 0x030 - * - * 10 11 Longword 0000 0x058 - * - * Note that byte enables are asserted low. - * - */ - -#define BYTE_ENABLE_SHIFT 5 -#define TRANSFER_LENGTH_SHIFT 3 - -#define MEM_R1_MASK 0x1fffffff /* SPARSE Mem region 1 mask is 29 bits */ -#define MEM_R2_MASK 0x07ffffff /* SPARSE Mem region 2 mask is 27 bits */ -#define MEM_R3_MASK 0x03ffffff /* SPARSE Mem region 3 mask is 26 bits */ - -#ifdef CONFIG_ALPHA_SRM_SETUP -/* if we are using the SRM PCI setup, we'll need to use variables instead */ -#define MCPCIA_DMA_WIN_BASE_DEFAULT (2*1024*1024*1024U) -#define MCPCIA_DMA_WIN_SIZE_DEFAULT (2*1024*1024*1024U) - -extern unsigned int MCPCIA_DMA_WIN_BASE; -extern unsigned int MCPCIA_DMA_WIN_SIZE; - -#else /* SRM_SETUP */ -#define MCPCIA_DMA_WIN_BASE (2*1024*1024*1024UL) -#define MCPCIA_DMA_WIN_SIZE (2*1024*1024*1024UL) -#endif /* SRM_SETUP */ - -#define HOSE(h) (((unsigned long)(h)) << 33) -/* - * General Registers - */ -#define MCPCIA_REV(h) (IDENT_ADDR + 0xf9e0000000UL + HOSE(h)) -#define MCPCIA_WHOAMI(h) (IDENT_ADDR + 0xf9e0000040UL + HOSE(h)) -#define MCPCIA_PCI_LAT(h) (IDENT_ADDR + 0xf9e0000080UL + HOSE(h)) -#define MCPCIA_CAP_CTRL(h) (IDENT_ADDR + 0xf9e0000100UL + HOSE(h)) -#define MCPCIA_HAE_MEM(h) (IDENT_ADDR + 0xf9e0000400UL + HOSE(h)) -#define MCPCIA_HAE_IO(h) (IDENT_ADDR + 0xf9e0000440UL + HOSE(h)) -#if 0 -#define MCPCIA_IACK_SC(h) (IDENT_ADDR + 0xf9e0000480UL + HOSE(h)) -#endif -#define MCPCIA_HAE_DENSE(h) (IDENT_ADDR + 0xf9e00004c0UL + HOSE(h)) - -/* - * Interrupt Control registers - */ -#define MCPCIA_INT_CTL(h) (IDENT_ADDR + 0xf9e0000500UL + HOSE(h)) -#define MCPCIA_INT_REQ(h) (IDENT_ADDR + 0xf9e0000540UL + HOSE(h)) -#define MCPCIA_INT_TARG(h) (IDENT_ADDR + 0xf9e0000580UL + HOSE(h)) -#define MCPCIA_INT_ADR(h) (IDENT_ADDR + 0xf9e00005c0UL + HOSE(h)) -#define MCPCIA_INT_ADR_EXT(h) (IDENT_ADDR + 0xf9e0000600UL + HOSE(h)) -#define MCPCIA_INT_MASK0(h) (IDENT_ADDR + 0xf9e0000640UL + HOSE(h)) -#define MCPCIA_INT_MASK1(h) (IDENT_ADDR + 0xf9e0000680UL + HOSE(h)) -#define MCPCIA_INT_ACK0(h) (IDENT_ADDR + 0xf9f0003f00UL + HOSE(h)) -#define MCPCIA_INT_ACK1(h) (IDENT_ADDR + 0xf9e0003f40UL + HOSE(h)) - -/* - * Performance Monitor registers - */ -#define MCPCIA_PERF_MONITOR(h) (IDENT_ADDR + 0xf9e0000300UL + HOSE(h)) -#define MCPCIA_PERF_CONTROL(h) (IDENT_ADDR + 0xf9e0000340UL + HOSE(h)) - -/* - * Diagnostic Registers - */ -#define MCPCIA_CAP_DIAG(h) (IDENT_ADDR + 0xf9e0000700UL + HOSE(h)) -#define MCPCIA_TOP_OF_MEM(h) (IDENT_ADDR + 0xf9e00007c0UL + HOSE(h)) - -/* - * Error registers - */ -#define MCPCIA_CAP_ERR(h) (IDENT_ADDR + 0xf9e0000880UL + HOSE(h)) -#define MCPCIA_PCI_ERR1(h) (IDENT_ADDR + 0xf9e0001040UL + HOSE(h)) - -/* - * PCI Address Translation Registers. - */ -#define MCPCIA_SG_TBIA(h) (IDENT_ADDR + 0xf9e0001300UL + HOSE(h)) -#define MCPCIA_HBASE(h) (IDENT_ADDR + 0xf9e0001340UL + HOSE(h)) - -#define MCPCIA_W0_BASE(h) (IDENT_ADDR + 0xf9e0001400UL + HOSE(h)) -#define MCPCIA_W0_MASK(h) (IDENT_ADDR + 0xf9e0001440UL + HOSE(h)) -#define MCPCIA_T0_BASE(h) (IDENT_ADDR + 0xf9e0001480UL + HOSE(h)) - -#define MCPCIA_W1_BASE(h) (IDENT_ADDR + 0xf9e0001500UL + HOSE(h)) -#define MCPCIA_W1_MASK(h) (IDENT_ADDR + 0xf9e0001540UL + HOSE(h)) -#define MCPCIA_T1_BASE(h) (IDENT_ADDR + 0xf9e0001580UL + HOSE(h)) - -#define MCPCIA_W2_BASE(h) (IDENT_ADDR + 0xf9e0001600UL + HOSE(h)) -#define MCPCIA_W2_MASK(h) (IDENT_ADDR + 0xf9e0001640UL + HOSE(h)) -#define MCPCIA_T2_BASE(h) (IDENT_ADDR + 0xf9e0001680UL + HOSE(h)) - -#define MCPCIA_W3_BASE(h) (IDENT_ADDR + 0xf9e0001700UL + HOSE(h)) -#define MCPCIA_W3_MASK(h) (IDENT_ADDR + 0xf9e0001740UL + HOSE(h)) -#define MCPCIA_T3_BASE(h) (IDENT_ADDR + 0xf9e0001780UL + HOSE(h)) - -/* - * Memory spaces: - */ -#define MCPCIA_CONF(h) (IDENT_ADDR + 0xf9c0000000UL + HOSE(h)) -#define MCPCIA_IO(h) (IDENT_ADDR + 0xf980000000UL + HOSE(h)) -#define MCPCIA_SPARSE(h) (IDENT_ADDR + 0xf800000000UL + HOSE(h)) -#define MCPCIA_DENSE(h) (IDENT_ADDR + 0xf900000000UL + HOSE(h)) -#define MCPCIA_IACK_SC(h) (IDENT_ADDR + 0xf9f0003f00UL + HOSE(h)) - -#define DENSE_MEM(addr) MCPCIA_DENSE(((unsigned long)(addr) >> 32) & 3) - -#define HAE_ADDRESS MCPCIA_HAE_MEM(0) - -#ifdef __KERNEL__ - -/* - * Translate physical memory address as seen on (PCI) bus into - * a kernel virtual address and vv. - */ -extern inline unsigned long virt_to_bus(void * address) -{ - return virt_to_phys(address) + MCPCIA_DMA_WIN_BASE; -} - -extern inline void * bus_to_virt(unsigned long address) -{ - return phys_to_virt(address - MCPCIA_DMA_WIN_BASE); -} - -/* - * I/O functions: - * - * MCPCIA, the RAWHIDE family PCI/memory support chipset for the EV5 (21164) - * and EV56 (21164a) processors, can use either a sparse address mapping - * scheme, or the so-called byte-word PCI address space, to get at PCI memory - * and I/O. - * - * Unfortunately, we can't use BWIO with EV5, so for now, we always use SPARSE. - */ - -#define vuip volatile unsigned int * -#define vulp volatile unsigned long * - -#ifdef DISABLE_BWIO_ENABLED - -extern inline unsigned int __inb(unsigned long addr) -{ - register unsigned long result; - - __asm__ __volatile__ ( - "ldbu %0,%1" - : "=r" (result) - : "m" (*(unsigned char *)(addr+MCPCIA_BW_IO))); - - return result; -} - -extern inline void __outb(unsigned char b, unsigned long addr) -{ - __asm__ __volatile__ ( - "stb %1,%0\n\t" - "mb" - : : "m" (*(unsigned char *)(addr+MCPCIA_BW_IO)), "r" (b)); -} - -extern inline unsigned int __inw(unsigned long addr) -{ - register unsigned long result; - - __asm__ __volatile__ ( - "ldwu %0,%1" - : "=r" (result) - : "m" (*(unsigned short *)(addr+MCPCIA_BW_IO))); - - return result; -} - -extern inline void __outw(unsigned short b, unsigned long addr) -{ - __asm__ __volatile__ ( - "stw %1,%0\n\t" - "mb" - : : "m" (*(unsigned short *)(addr+MCPCIA_BW_IO)), "r" (b)); -} - -extern inline unsigned int __inl(unsigned long addr) -{ - register unsigned long result; - - __asm__ __volatile__ ( - "ldl %0,%1" - : "=r" (result) - : "m" (*(unsigned int *)(addr+MCPCIA_BW_IO))); - - return result; -} - -extern inline void __outl(unsigned int b, unsigned long addr) -{ - __asm__ __volatile__ ( - "stl %1,%0\n\t" - "mb" - : : "m" (*(unsigned int *)(addr+MCPCIA_BW_IO)), "r" (b)); -} - -#define inb(port) __inb((port)) -#define inw(port) __inw((port)) -#define inl(port) __inl((port)) - -#define outb(x, port) __outb((x),(port)) -#define outw(x, port) __outw((x),(port)) -#define outl(x, port) __outl((x),(port)) - -#else /* BWIO_ENABLED */ - -extern inline unsigned int __inb(unsigned long in_addr) -{ - unsigned long addr = in_addr & 0xffffffffUL; - unsigned long hose = (in_addr >> 32) & 3; - long result = *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x00); - result >>= (addr & 3) * 8; - return 0xffUL & result; -} - -extern inline void __outb(unsigned char b, unsigned long in_addr) -{ - unsigned long addr = in_addr & 0xffffffffUL; - unsigned long hose = (in_addr >> 32) & 3; - unsigned int w; - - w = __kernel_insbl(b, addr & 3); - *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x00) = w; - mb(); -} - -extern inline unsigned int __inw(unsigned long in_addr) -{ - unsigned long addr = in_addr & 0xffffffffUL; - unsigned long hose = (in_addr >> 32) & 3; - long result = *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x08); - result >>= (addr & 3) * 8; - return 0xffffUL & result; -} - -extern inline void __outw(unsigned short b, unsigned long in_addr) -{ - unsigned long addr = in_addr & 0xffffffffUL; - unsigned long hose = (in_addr >> 32) & 3; - unsigned int w; - - w = __kernel_inswl(b, addr & 3); - *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x08) = w; - mb(); -} - -extern inline unsigned int __inl(unsigned long in_addr) -{ - unsigned long addr = in_addr & 0xffffffffUL; - unsigned long hose = (in_addr >> 32) & 3; - return *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x18); -} - -extern inline void __outl(unsigned int b, unsigned long in_addr) -{ - unsigned long addr = in_addr & 0xffffffffUL; - unsigned long hose = (in_addr >> 32) & 3; - *(vuip) ((addr << 5) + MCPCIA_IO(hose) + 0x18) = b; - mb(); -} - -#define inb(port) \ -(__builtin_constant_p((port))?__inb(port):_inb(port)) - -#define outb(x, port) \ -(__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port))) - -#endif /* BWIO_ENABLED */ - - -/* - * Memory functions. 64-bit and 32-bit accesses are done through - * dense memory space, everything else through sparse space. - * - * For reading and writing 8 and 16 bit quantities we need to - * go through one of the three sparse address mapping regions - * and use the HAE_MEM CSR to provide some bits of the address. - * The following few routines use only sparse address region 1 - * which gives 1Gbyte of accessible space which relates exactly - * to the amount of PCI memory mapping *into* system address space. - * See p 6-17 of the specification but it looks something like this: - * - * 21164 Address: - * - * 3 2 1 - * 9876543210987654321098765432109876543210 - * 1ZZZZ0.PCI.QW.Address............BBLL - * - * ZZ = SBZ - * BB = Byte offset - * LL = Transfer length - * - * PCI Address: - * - * 3 2 1 - * 10987654321098765432109876543210 - * HHH....PCI.QW.Address........ 00 - * - * HHH = 31:29 HAE_MEM CSR - * - */ - -#ifdef DISABLE_BWIO_ENABLED - -extern inline unsigned long __readb(unsigned long addr) -{ - register unsigned long result; - - __asm__ __volatile__ ( - "ldbu %0,%1" - : "=r" (result) - : "m" (*(volatile unsigned char *)(addr+MCPCIA_BW_MEM))); - - return result; -} - -extern inline unsigned long __readw(unsigned long addr) -{ - register unsigned long result; - - __asm__ __volatile__ ( - "ldwu %0,%1" - : "=r" (result) - : "m" (*(volatile unsigned short *)(addr+MCPCIA_BW_MEM))); - - return result; -} - -extern inline unsigned long __readl(unsigned long addr) -{ - return *(vuip)(addr + MCPCIA_BW_MEM); -} - -extern inline unsigned long __readq(unsigned long addr) -{ - return *(vulp)(addr + MCPCIA_BW_MEM); -} - -extern inline void __writeb(unsigned char b, unsigned long addr) -{ - __asm__ __volatile__ ( - "stb %1,%0\n\t" - "mb" - : "m" (*(volatile unsigned char *)(addr+MCPCIA_BW_MEM)) - : "r" (b)); -} - -extern inline void __writew(unsigned short b, unsigned long addr) -{ - __asm__ __volatile__ ( - "stw %1,%0\n\t" - "mb" - : "m" (*(volatile unsigned short *)(addr+MCPCIA_BW_MEM)) - : "r" (b)); -} - -extern inline void __writel(unsigned int b, unsigned long addr) -{ - *(vuip)(addr+MCPCIA_BW_MEM) = b; - mb(); -} - -extern inline void __writeq(unsigned long b, unsigned long addr) -{ - *(vulp)(addr+MCPCIA_BW_MEM) = b; - mb(); -} - -#define readb(addr) __readb((addr)) -#define readw(addr) __readw((addr)) - -#define writeb(b, addr) __writeb((b),(addr)) -#define writew(b, addr) __writew((b),(addr)) - -#else /* BWIO_ENABLED */ - -#ifdef CONFIG_ALPHA_SRM_SETUP - -extern unsigned long mcpcia_sm_base_r1, mcpcia_sm_base_r2, mcpcia_sm_base_r3; - -extern inline unsigned long __readb(unsigned long addr) -{ - unsigned long result, shift, work; - - if ((addr >= mcpcia_sm_base_r1) && - (addr <= (mcpcia_sm_base_r1 + MEM_R1_MASK))) - work = (((addr & MEM_R1_MASK) << 5) + MCPCIA_SPARSE_MEM + 0x00); - else - if ((addr >= mcpcia_sm_base_r2) && - (addr <= (mcpcia_sm_base_r2 + MEM_R2_MASK))) - work = (((addr & MEM_R2_MASK) << 5) + MCPCIA_SPARSE_MEM_R2 + 0x00); - else - if ((addr >= mcpcia_sm_base_r3) && - (addr <= (mcpcia_sm_base_r3 + MEM_R3_MASK))) - work = (((addr & MEM_R3_MASK) << 5) + MCPCIA_SPARSE_MEM_R3 + 0x00); - else - { -#if 0 - printk("__readb: address 0x%lx not covered by HAE\n", addr); -#endif - return 0x0ffUL; - } - shift = (addr & 0x3) << 3; - result = *(vuip) work; - result >>= shift; - return 0x0ffUL & result; -} - -extern inline unsigned long __readw(unsigned long addr) -{ - unsigned long result, shift, work; - - if ((addr >= mcpcia_sm_base_r1) && - (addr <= (mcpcia_sm_base_r1 + MEM_R1_MASK))) - work = (((addr & MEM_R1_MASK) << 5) + MCPCIA_SPARSE_MEM + 0x08); - else - if ((addr >= mcpcia_sm_base_r2) && - (addr <= (mcpcia_sm_base_r2 + MEM_R2_MASK))) - work = (((addr & MEM_R2_MASK) << 5) + MCPCIA_SPARSE_MEM_R2 + 0x08); - else - if ((addr >= mcpcia_sm_base_r3) && - (addr <= (mcpcia_sm_base_r3 + MEM_R3_MASK))) - work = (((addr & MEM_R3_MASK) << 5) + MCPCIA_SPARSE_MEM_R3 + 0x08); - else - { -#if 0 - printk("__readw: address 0x%lx not covered by HAE\n", addr); -#endif - return 0x0ffffUL; - } - shift = (addr & 0x3) << 3; - result = *(vuip) work; - result >>= shift; - return 0x0ffffUL & result; -} - -extern inline void __writeb(unsigned char b, unsigned long addr) -{ - unsigned long work; - - if ((addr >= mcpcia_sm_base_r1) && - (addr <= (mcpcia_sm_base_r1 + MEM_R1_MASK))) - work = (((addr & MEM_R1_MASK) << 5) + MCPCIA_SPARSE_MEM + 0x00); - else - if ((addr >= mcpcia_sm_base_r2) && - (addr <= (mcpcia_sm_base_r2 + MEM_R2_MASK))) - work = (((addr & MEM_R2_MASK) << 5) + MCPCIA_SPARSE_MEM_R2 + 0x00); - else - if ((addr >= mcpcia_sm_base_r3) && - (addr <= (mcpcia_sm_base_r3 + MEM_R3_MASK))) - work = (((addr & MEM_R3_MASK) << 5) + MCPCIA_SPARSE_MEM_R3 + 0x00); - else - { -#if 0 - printk("__writeb: address 0x%lx not covered by HAE\n", addr); -#endif - return; - } - *(vuip) work = b * 0x01010101; -} - -extern inline void __writew(unsigned short b, unsigned long addr) -{ - unsigned long work; - - if ((addr >= mcpcia_sm_base_r1) && - (addr <= (mcpcia_sm_base_r1 + MEM_R1_MASK))) - work = (((addr & MEM_R1_MASK) << 5) + MCPCIA_SPARSE_MEM + 0x00); - else - if ((addr >= mcpcia_sm_base_r2) && - (addr <= (mcpcia_sm_base_r2 + MEM_R2_MASK))) - work = (((addr & MEM_R2_MASK) << 5) + MCPCIA_SPARSE_MEM_R2 + 0x00); - else - if ((addr >= mcpcia_sm_base_r3) && - (addr <= (mcpcia_sm_base_r3 + MEM_R3_MASK))) - work = (((addr & MEM_R3_MASK) << 5) + MCPCIA_SPARSE_MEM_R3 + 0x00); - else - { -#if 0 - printk("__writew: address 0x%lx not covered by HAE\n", addr); -#endif - return; - } - *(vuip) work = b * 0x00010001; -} - -#else /* SRM_SETUP */ - -extern inline unsigned long __readb(unsigned long in_addr) -{ - unsigned long addr = in_addr & 0xffffffffUL; - unsigned long hose = (in_addr >> 32) & 3; - unsigned long result, shift, msb, work, temp; - - shift = (addr & 0x3) << 3; - msb = addr & 0xE0000000UL; - temp = addr & MEM_R1_MASK; - if (msb != hae.cache) { - set_hae(msb); - } - work = ((temp << 5) + MCPCIA_SPARSE(hose) + 0x00); - result = *(vuip) work; - result >>= shift; - return 0x0ffUL & result; -} - -extern inline unsigned long __readw(unsigned long in_addr) -{ - unsigned long addr = in_addr & 0xffffffffUL; - unsigned long hose = (in_addr >> 32) & 3; - unsigned long result, shift, msb, work, temp; - - shift = (addr & 0x3) << 3; - msb = addr & 0xE0000000UL; - temp = addr & MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } - work = ((temp << 5) + MCPCIA_SPARSE(hose) + 0x08); - result = *(vuip) work; - result >>= shift; - return 0x0ffffUL & result; -} - -extern inline void __writeb(unsigned char b, unsigned long in_addr) -{ - unsigned long addr = in_addr & 0xffffffffUL; - unsigned long hose = (in_addr >> 32) & 3; - unsigned long msb; - - msb = addr & 0xE0000000; - addr &= MEM_R1_MASK; - if (msb != hae.cache) { - set_hae(msb); - } - *(vuip) ((addr << 5) + MCPCIA_SPARSE(hose) + 0x00) = b * 0x01010101; -} - -extern inline void __writew(unsigned short b, unsigned long in_addr) -{ - unsigned long addr = in_addr & 0xffffffffUL; - unsigned long hose = (in_addr >> 32) & 3; - unsigned long msb ; - - msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } - *(vuip) ((addr << 5) + MCPCIA_SPARSE(hose) + 0x08) = b * 0x00010001; -} -#endif /* SRM_SETUP */ - -extern inline unsigned long __readl(unsigned long in_addr) -{ - unsigned long addr = in_addr & 0xffffffffUL; - unsigned long hose = (in_addr >> 32) & 3; - return *(vuip) (addr + MCPCIA_DENSE(hose)); -} - -extern inline unsigned long __readq(unsigned long in_addr) -{ - unsigned long addr = in_addr & 0xffffffffUL; - unsigned long hose = (in_addr >> 32) & 3; - return *(vulp) (addr + MCPCIA_DENSE(hose)); -} - -extern inline void __writel(unsigned int b, unsigned long in_addr) -{ - unsigned long addr = in_addr & 0xffffffffUL; - unsigned long hose = (in_addr >> 32) & 3; - *(vuip) (addr + MCPCIA_DENSE(hose)) = b; -} - -extern inline void __writeq(unsigned long b, unsigned long in_addr) -{ - unsigned long addr = in_addr & 0xffffffffUL; - unsigned long hose = (in_addr >> 32) & 3; - *(vulp) (addr + MCPCIA_DENSE(hose)) = b; -} - -#endif /* BWIO_ENABLED */ - -#define readl(a) __readl((unsigned long)(a)) -#define readq(a) __readq((unsigned long)(a)) -#define writel(v,a) __writel((v),(unsigned long)(a)) -#define writeq(v,a) __writeq((v),(unsigned long)(a)) - -#undef vuip -#undef vulp - -struct linux_hose_info { - struct pci_bus pci_bus; - struct linux_hose_info *next; - unsigned long pci_io_space; - unsigned long pci_mem_space; - unsigned long pci_config_space; - unsigned long pci_sparse_space; - unsigned int pci_first_busno; - unsigned int pci_last_busno; - unsigned int pci_hose_index; -}; - -extern unsigned long mcpcia_init (unsigned long, unsigned long); -extern void mcpcia_fixup (void); - -#endif /* __KERNEL__ */ - -/* - * Data structure for handling MCPCIA machine checks: - */ -struct el_MCPCIA_uncorrected_frame_mcheck { - struct el_common header; - struct el_common_EV5_uncorrectable_mcheck procdata; -}; - -#define RTC_PORT(x) (0x70 + (x)) -#define RTC_ADDR(x) (0x80 | (x)) -#define RTC_ALWAYS_BCD 0 - -#endif /* __ALPHA_MCPCIA__H__ */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/mmu_context.h linux/include/asm-alpha/mmu_context.h --- v2.1.115/linux/include/asm-alpha/mmu_context.h Thu May 7 22:51:54 1998 +++ linux/include/asm-alpha/mmu_context.h Sun Aug 9 12:09:06 1998 @@ -9,6 +9,7 @@ #include #include +#include /* * The maximum ASN's the processor supports. On the EV4 this is 63 @@ -32,11 +33,17 @@ * work correctly and can thus not be used (explaining the lack of PAL-code * support). */ -#ifdef CONFIG_ALPHA_EV5 -#define MAX_ASN 127 +#define EV4_MAX_ASN 63 +#define EV5_MAX_ASN 127 + +#ifdef CONFIG_ALPHA_GENERIC +# define MAX_ASN (alpha_mv.max_asn) #else -#define MAX_ASN 63 -#define BROKEN_ASN 1 +# ifdef CONFIG_ALPHA_EV4 +# define MAX_ASN EV4_MAX_ASN +# else +# define MAX_ASN EV5_MAX_ASN +# endif #endif #ifdef __SMP__ @@ -78,26 +85,21 @@ * force a new asn for any other processes the next time they want to * run. */ -extern inline void -get_new_mmu_context(struct task_struct *p, struct mm_struct *mm) -{ - unsigned long asn = asn_cache; - if ((asn & HARDWARE_ASN_MASK) < MAX_ASN) - ++asn; - else { - tbiap(); - imb(); - asn = (asn & ~HARDWARE_ASN_MASK) + ASN_FIRST_VERSION; - } - asn_cache = asn; - mm->context = asn; /* full version + asn */ - p->tss.asn = asn & HARDWARE_ASN_MASK; /* just asn */ +#ifndef __EXTERN_INLINE +#define __EXTERN_INLINE extern inline +#define __MMU_EXTERN_INLINE +#endif + +extern void get_new_mmu_context(struct task_struct *p, struct mm_struct *mm); + +__EXTERN_INLINE void ev4_get_mmu_context(struct task_struct *p) +{ + /* As described, ASN's are broken. */ } -extern inline void get_mmu_context(struct task_struct *p) +__EXTERN_INLINE void ev5_get_mmu_context(struct task_struct *p) { -#ifndef BROKEN_ASN struct mm_struct * mm = p->mm; if (mm) { @@ -106,27 +108,81 @@ if ((mm->context ^ asn) & ~HARDWARE_ASN_MASK) get_new_mmu_context(p, mm); } -#endif } +#ifdef CONFIG_ALPHA_GENERIC +# define get_mmu_context (alpha_mv.mv_get_mmu_context) +#else +# ifdef CONFIG_ALPHA_EV4 +# define get_mmu_context ev4_get_mmu_context +# else +# define get_mmu_context ev5_get_mmu_context +# endif +#endif + extern inline void init_new_context(struct mm_struct *mm) { mm->context = 0; } -#define destroy_context(mm) do { } while(0) +extern inline void destroy_context(struct mm_struct *mm) +{ + /* Nothing to do. */ +} + /* - * After we have set current->mm to a new value, this activates - * the context for the new mm so we see the new mappings. - * Ideally this would be an extern inline function, but reload_context - * is declared in pgtable.h, which includes this file. :-( - */ -#define activate_context(tsk) \ - do { \ - get_mmu_context(tsk); \ - reload_context(tsk); \ - } while (0) + * Force a context reload. This is needed when we change the page + * table pointer or when we update the ASN of the current process. + */ + +#if defined(CONFIG_ALPHA_GENERIC) +#define MASK_CONTEXT(tss) \ + ((struct thread_struct *)((unsigned long)(tss) & alpha_mv.mmu_context_mask)) +#elif defined(CONFIG_ALPHA_DP264) +#define MASK_CONTEXT(tss) \ + ((struct thread_struct *)((unsigned long)(tss) & 0xfffffffffful)) +#else +#define MASK_CONTEXT(tss) (tss) +#endif + +__EXTERN_INLINE struct thread_struct * +__reload_tss(struct thread_struct *tss) +{ + register struct thread_struct *a0 __asm__("$16"); + register struct thread_struct *v0 __asm__("$0"); + + a0 = MASK_CONTEXT(tss); + + __asm__ __volatile__( + "call_pal %2" : "=r"(v0), "=r"(a0) + : "i"(PAL_swpctx), "r"(a0) + : "$1", "$16", "$22", "$23", "$24", "$25"); + + return v0; +} + +__EXTERN_INLINE void +reload_context(struct task_struct *task) +{ + __reload_tss(&task->tss); +} + +/* + * After we have set current->mm to a new value, this activates the + * context for the new mm so we see the new mappings. + */ + +__EXTERN_INLINE void +activate_context(struct task_struct *task) +{ + get_mmu_context(task); + reload_context(task); +} +#ifdef __MMU_EXTERN_INLINE +#undef __EXTERN_INLINE +#undef __MMU_EXTERN_INLINE #endif +#endif /* __ALPHA_MMU_CONTEXT_H */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/pci.h linux/include/asm-alpha/pci.h --- v2.1.115/linux/include/asm-alpha/pci.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-alpha/pci.h Sun Aug 9 12:09:06 1998 @@ -0,0 +1,48 @@ +#ifndef __ALPHA_PCI_H +#define __ALPHA_PCI_H + +#include +#include + + +/* + * The following structure is used to manage multiple PCI busses. + * + * XXX: We should solve thos problem in an architecture independant + * way, rather than hacking something up here. + */ + +struct linux_hose_info { + struct pci_bus pci_bus; + struct linux_hose_info *next; + unsigned long pci_io_space; + unsigned long pci_mem_space; + unsigned long pci_config_space; + unsigned long pci_sparse_space; + unsigned int pci_first_busno; + unsigned int pci_last_busno; + unsigned int pci_hose_index; +}; + +/* This is indexed by a pseudo- PCI bus number to obtain the real deal. */ +extern struct linux_hose_info *bus2hose[256]; + +/* Create a handle that is OR-ed into the reported I/O space address + for a device. We use this later to find the bus a device lives on. */ + +#if defined(CONFIG_ALPHA_GENERIC) \ + || defined(CONFIG_ALPHA_MCPCIA) \ + /* || defined(CONFIG_ALPHA_TSUNAMI) */ + +#define PCI_HANDLE(bus) ((bus2hose[bus]->pci_hose_index & 3UL) << 32) +#define DEV_IS_ON_PRIMARY(dev) \ + (bus2hose[(dev)->bus->number]->pci_first_busno == (dev)->bus->number) + +#else + +#define PCI_HANDLE(bus) 0 +#define DEV_IS_ON_PRIMARY(dev) ((dev)->bus->number == 0) + +#endif /* Multiple busses */ + +#endif /* __ALPHA_PCI_H */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/pgtable.h linux/include/asm-alpha/pgtable.h --- v2.1.115/linux/include/asm-alpha/pgtable.h Thu Aug 6 14:06:33 1998 +++ linux/include/asm-alpha/pgtable.h Sun Aug 9 12:09:06 1998 @@ -13,6 +13,8 @@ #include #include /* For TASK_SIZE */ #include +#include + /* Caches aren't brain-dead on the Alpha. */ #define flush_cache_all() do { } while (0) @@ -23,60 +25,86 @@ #define flush_icache_range(start, end) do { } while (0) /* - * Force a context reload. This is needed when we - * change the page table pointer or when we update - * the ASN of the current process. - */ -static inline void reload_context(struct task_struct *task) -{ - __asm__ __volatile__( -#ifdef CONFIG_ALPHA_DP264 - "zap %0,0xe0,$16\n\t" -#else - "bis %0,%0,$16\n\t" -#endif - "call_pal %1" - : /* no outputs */ - : "r" (&task->tss), "i" (PAL_swpctx) - : "$0", "$1", "$16", "$22", "$23", "$24", "$25"); -} - -/* * Use a few helper functions to hide the ugly broken ASN * numbers on early Alphas (ev4 and ev45) */ -#ifdef BROKEN_ASN -#define flush_tlb_current(x) tbiap() -#define flush_tlb_other(x) do { } while (0) +#ifndef __EXTERN_INLINE +#define __EXTERN_INLINE extern inline +#define __MMU_EXTERN_INLINE +#endif -#else +__EXTERN_INLINE void +ev4_flush_tlb_current(struct mm_struct *mm) +{ + tbiap(); +} -extern void get_new_asn_and_reload(struct task_struct *, struct mm_struct *); +__EXTERN_INLINE void +ev4_flush_tlb_other(struct mm_struct *mm) +{ +} -#define flush_tlb_current(mm) get_new_asn_and_reload(current, mm) -#define flush_tlb_other(mm) do { (mm)->context = 0; } while (0) +__EXTERN_INLINE void +ev5_flush_tlb_current(struct mm_struct *mm) +{ + mm->context = 0; + get_new_mmu_context(current, mm); + reload_context(current); +} -#endif +__EXTERN_INLINE void +ev5_flush_tlb_other(struct mm_struct *mm) +{ + mm->context = 0; +} /* * Flush just one page in the current TLB set. * We need to be very careful about the icache here, there * is no way to invalidate a specific icache page.. */ -static inline void flush_tlb_current_page(struct mm_struct * mm, - struct vm_area_struct *vma, - unsigned long addr) + +__EXTERN_INLINE void +ev4_flush_tlb_current_page(struct mm_struct * mm, + struct vm_area_struct *vma, + unsigned long addr) { -#ifdef BROKEN_ASN tbi(2 + ((vma->vm_flags & VM_EXEC) != 0), addr); -#else +} + +__EXTERN_INLINE void +ev5_flush_tlb_current_page(struct mm_struct * mm, + struct vm_area_struct *vma, + unsigned long addr) +{ if (vma->vm_flags & VM_EXEC) - flush_tlb_current(mm); + ev5_flush_tlb_current(mm); else tbi(2, addr); -#endif } + + +#ifdef CONFIG_ALPHA_GENERIC +# define flush_tlb_current alpha_mv.mv_flush_tlb_current +# define flush_tlb_other alpha_mv.mv_flush_tlb_other +# define flush_tlb_current_page alpha_mv.mv_flush_tlb_current_page +#else +# ifdef CONFIG_ALPHA_EV4 +# define flush_tlb_current ev4_flush_tlb_current +# define flush_tlb_other ev4_flush_tlb_other +# define flush_tlb_current_page ev4_flush_tlb_current_page +# else +# define flush_tlb_current ev5_flush_tlb_current +# define flush_tlb_other ev5_flush_tlb_other +# define flush_tlb_current_page ev5_flush_tlb_current_page +# endif +#endif + +#ifdef __MMU_EXTERN_INLINE +#undef __EXTERN_INLINE +#undef __MMU_EXTERN_INLINE +#endif /* * Flush current user mapping. diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/posix_types.h linux/include/asm-alpha/posix_types.h --- v2.1.115/linux/include/asm-alpha/posix_types.h Mon Dec 8 23:58:04 1997 +++ linux/include/asm-alpha/posix_types.h Sun Aug 9 12:09:06 1998 @@ -34,6 +34,8 @@ int val[2]; } __kernel_fsid_t; +#ifdef __KERNEL__ + #ifndef __GNUC__ #define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d)) @@ -108,5 +110,7 @@ } #endif /* __GNUC__ */ + +#endif /* __KERNEL__ */ #endif /* _ALPHA_POSIX_TYPES_H */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/processor.h linux/include/asm-alpha/processor.h --- v2.1.115/linux/include/asm-alpha/processor.h Sun Jul 26 11:57:19 1998 +++ linux/include/asm-alpha/processor.h Sun Aug 9 12:09:06 1998 @@ -82,13 +82,23 @@ * holds provided the thread blocked through a call to schedule() ($15 * is the frame pointer in schedule() and $15 is saved at offset 48 by * entry.S:do_switch_stack). + * + * Under heavy swap load I've seen this loose in an ugly way. So do + * some extra sanity checking on the ranges we expect these pointers + * to be in so that we can fail gracefully. This is just for ps after + * all. -- r~ */ extern inline unsigned long thread_saved_pc(struct thread_struct *t) { - unsigned long fp; + unsigned long fp, sp = t->ksp, base = (unsigned long)t; + + if (sp > base && sp+6*8 < base + 16*1024) { + fp = ((unsigned long*)sp)[6]; + if (fp > sp && fp < base + 16*1024) + return *(unsigned long *)fp; + } - fp = ((unsigned long*)t->ksp)[6]; - return *(unsigned long*)fp; + return 0; } /* diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/pyxis.h linux/include/asm-alpha/pyxis.h --- v2.1.115/linux/include/asm-alpha/pyxis.h Tue Jul 21 00:15:32 1998 +++ linux/include/asm-alpha/pyxis.h Wed Dec 31 16:00:00 1969 @@ -1,724 +0,0 @@ -#ifndef __ALPHA_PYXIS__H__ -#define __ALPHA_PYXIS__H__ - -#include -#include - -/* - * PYXIS is the internal name for a core logic chipset which provides - * memory controller and PCI access for the 21164A chip based systems. - * - * This file is based on: - * - * Pyxis Chipset Spec - * 14-Jun-96 - * Rev. X2.0 - * - */ - -/*------------------------------------------------------------------------** -** ** -** I/O procedures ** -** ** -** inport[b|w|t|l], outport[b|w|t|l] 8:16:24:32 IO xfers ** -** inportbxt: 8 bits only ** -** inport: alias of inportw ** -** outport: alias of outportw ** -** ** -** inmem[b|w|t|l], outmem[b|w|t|l] 8:16:24:32 ISA memory xfers ** -** inmembxt: 8 bits only ** -** inmem: alias of inmemw ** -** outmem: alias of outmemw ** -** ** -**------------------------------------------------------------------------*/ - - -/* CIA ADDRESS BIT DEFINITIONS - * - * 3 3 3 3|3 3 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 - * 9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * |1| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |0|0|0| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | \_/ \_/ - * | | | - * +-- IO space, not cached. Byte Enable --+ | - * Transfer Length --+ - * - * - * - * Byte Transfer - * Enable Length Transfer Byte Address - * adr<6:5> adr<4:3> Length Enable Adder - * --------------------------------------------- - * 00 00 Byte 1110 0x000 - * 01 00 Byte 1101 0x020 - * 10 00 Byte 1011 0x040 - * 11 00 Byte 0111 0x060 - * - * 00 01 Word 1100 0x008 - * 01 01 Word 1001 0x028 <= Not supported in this code. - * 10 01 Word 0011 0x048 - * - * 00 10 Tribyte 1000 0x010 - * 01 10 Tribyte 0001 0x030 - * - * 10 11 Longword 0000 0x058 - * - * Note that byte enables are asserted low. - * - */ - -#define BYTE_ENABLE_SHIFT 5 -#define TRANSFER_LENGTH_SHIFT 3 - -#define MEM_R1_MASK 0x1fffffff /* SPARSE Mem region 1 mask is 29 bits */ -#define MEM_R2_MASK 0x07ffffff /* SPARSE Mem region 2 mask is 27 bits */ -#define MEM_R3_MASK 0x03ffffff /* SPARSE Mem region 3 mask is 26 bits */ - -#ifdef CONFIG_ALPHA_SRM_SETUP -/* if we are using the SRM PCI setup, we'll need to use variables instead */ -#define PYXIS_DMA_WIN_BASE_DEFAULT (1024*1024*1024) -#define PYXIS_DMA_WIN_SIZE_DEFAULT (1024*1024*1024) - -extern unsigned int PYXIS_DMA_WIN_BASE; -extern unsigned int PYXIS_DMA_WIN_SIZE; - -#else /* SRM_SETUP */ -#define PYXIS_DMA_WIN_BASE (1024*1024*1024) -#define PYXIS_DMA_WIN_SIZE (1024*1024*1024) -#endif /* SRM_SETUP */ - -/* - * General Registers - */ -#define PYXIS_REV (IDENT_ADDR + 0x8740000080UL) -#define PYXIS_PCI_LAT (IDENT_ADDR + 0x87400000C0UL) -#define PYXIS_CTRL (IDENT_ADDR + 0x8740000100UL) -#define PYXIS_CTRL1 (IDENT_ADDR + 0x8740000140UL) -#define PYXIS_FLASH_CTRL (IDENT_ADDR + 0x8740000200UL) - -#define PYXIS_HAE_MEM (IDENT_ADDR + 0x8740000400UL) -#define PYXIS_HAE_IO (IDENT_ADDR + 0x8740000440UL) -#define PYXIS_CFG (IDENT_ADDR + 0x8740000480UL) - -/* - * Diagnostic Registers - */ -#define PYXIS_DIAG (IDENT_ADDR + 0x8740002000UL) -#define PYXIS_DIAG_CHECK (IDENT_ADDR + 0x8740003000UL) - -/* - * Performance Monitor registers - */ -#define PYXIS_PERF_MONITOR (IDENT_ADDR + 0x8740004000UL) -#define PYXIS_PERF_CONTROL (IDENT_ADDR + 0x8740004040UL) - -/* - * Error registers - */ -#define PYXIS_ERR (IDENT_ADDR + 0x8740008200UL) -#define PYXIS_STAT (IDENT_ADDR + 0x8740008240UL) -#define PYXIS_ERR_MASK (IDENT_ADDR + 0x8740008280UL) -#define PYXIS_SYN (IDENT_ADDR + 0x8740008300UL) -#define PYXIS_ERR_DATA (IDENT_ADDR + 0x8740008308UL) - -#define PYXIS_MEAR (IDENT_ADDR + 0x8740008400UL) -#define PYXIS_MESR (IDENT_ADDR + 0x8740008440UL) -#define PYXIS_PCI_ERR0 (IDENT_ADDR + 0x8740008800UL) -#define PYXIS_PCI_ERR1 (IDENT_ADDR + 0x8740008840UL) -#define PYXIS_PCI_ERR2 (IDENT_ADDR + 0x8740008880UL) - -/* - * PCI Address Translation Registers. - */ -#define PYXIS_TBIA (IDENT_ADDR + 0x8760000100UL) - -#define PYXIS_W0_BASE (IDENT_ADDR + 0x8760000400UL) -#define PYXIS_W0_MASK (IDENT_ADDR + 0x8760000440UL) -#define PYXIS_T0_BASE (IDENT_ADDR + 0x8760000480UL) - -#define PYXIS_W1_BASE (IDENT_ADDR + 0x8760000500UL) -#define PYXIS_W1_MASK (IDENT_ADDR + 0x8760000540UL) -#define PYXIS_T1_BASE (IDENT_ADDR + 0x8760000580UL) - -#define PYXIS_W2_BASE (IDENT_ADDR + 0x8760000600UL) -#define PYXIS_W2_MASK (IDENT_ADDR + 0x8760000640UL) -#define PYXIS_T2_BASE (IDENT_ADDR + 0x8760000680UL) - -#define PYXIS_W3_BASE (IDENT_ADDR + 0x8760000700UL) -#define PYXIS_W3_MASK (IDENT_ADDR + 0x8760000740UL) -#define PYXIS_T3_BASE (IDENT_ADDR + 0x8760000780UL) - -/* - * Memory Control registers - */ -#define PYXIS_MCR (IDENT_ADDR + 0x8750000000UL) - -/* - * Memory spaces: - */ -#define PYXIS_IACK_SC (IDENT_ADDR + 0x8720000000UL) -#define PYXIS_CONF (IDENT_ADDR + 0x8700000000UL) -#define PYXIS_IO (IDENT_ADDR + 0x8580000000UL) -#define PYXIS_SPARSE_MEM (IDENT_ADDR + 0x8000000000UL) -#define PYXIS_SPARSE_MEM_R2 (IDENT_ADDR + 0x8400000000UL) -#define PYXIS_SPARSE_MEM_R3 (IDENT_ADDR + 0x8500000000UL) -#define PYXIS_DENSE_MEM (IDENT_ADDR + 0x8600000000UL) -#define DENSE_MEM(addr) PYXIS_DENSE_MEM - -/* - * Byte/Word PCI Memory Spaces: - */ -#define PYXIS_BW_MEM (IDENT_ADDR + 0x8800000000UL) -#define PYXIS_BW_IO (IDENT_ADDR + 0x8900000000UL) -#define PYXIS_BW_CFG_0 (IDENT_ADDR + 0x8a00000000UL) -#define PYXIS_BW_CFG_1 (IDENT_ADDR + 0x8b00000000UL) - -/* - * Interrupt Control registers - */ -#define PYXIS_INT_REQ (IDENT_ADDR + 0x87A0000000UL) -#define PYXIS_INT_MASK (IDENT_ADDR + 0x87A0000040UL) -#define PYXIS_INT_HILO (IDENT_ADDR + 0x87A00000C0UL) -#define PYXIS_INT_ROUTE (IDENT_ADDR + 0x87A0000140UL) -#define PYXIS_GPO (IDENT_ADDR + 0x87A0000180UL) -#define PYXIS_INT_CNFG (IDENT_ADDR + 0x87A00001C0UL) -#define PYXIS_RT_COUNT (IDENT_ADDR + 0x87A0000200UL) -#define PYXIS_INT_TIME (IDENT_ADDR + 0x87A0000240UL) -#define PYXIS_IIC_CTRL (IDENT_ADDR + 0x87A00002C0UL) - -/* - * Bit definitions for I/O Controller status register 0: - */ -#define PYXIS_STAT0_CMD 0xf -#define PYXIS_STAT0_ERR (1<<4) -#define PYXIS_STAT0_LOST (1<<5) -#define PYXIS_STAT0_THIT (1<<6) -#define PYXIS_STAT0_TREF (1<<7) -#define PYXIS_STAT0_CODE_SHIFT 8 -#define PYXIS_STAT0_CODE_MASK 0x7 -#define PYXIS_STAT0_P_NBR_SHIFT 13 -#define PYXIS_STAT0_P_NBR_MASK 0x7ffff - -#define HAE_ADDRESS PYXIS_HAE_MEM - -#ifdef __KERNEL__ - -/* - * Translate physical memory address as seen on (PCI) bus into - * a kernel virtual address and vv. - */ -#if defined(CONFIG_ALPHA_RUFFIAN) -/* Ruffian doesn't do 1G PCI window */ - -extern inline unsigned long virt_to_bus(void * address) -{ - return virt_to_phys(address); -} - -extern inline void * bus_to_virt(unsigned long address) -{ - return phys_to_virt(address); -} -#else /* RUFFIAN */ -extern inline unsigned long virt_to_bus(void * address) -{ - return virt_to_phys(address) + PYXIS_DMA_WIN_BASE; -} - -extern inline void * bus_to_virt(unsigned long address) -{ - return phys_to_virt(address - PYXIS_DMA_WIN_BASE); -} -#endif /* RUFFIAN */ - -/* - * I/O functions: - * - * PYXIS, the 21174 PCI/memory support chipset for the EV56 (21164A) - * and PCA56 (21164PC) processors, can use either a sparse address - * mapping scheme, or the so-called byte-word PCI address space, to - * get at PCI memory and I/O. - */ - -#define vuip volatile unsigned int * -#define vulp volatile unsigned long * - -#ifdef BWIO_ENABLED - -extern inline unsigned int __inb(unsigned long addr) -{ - register unsigned long result; - - __asm__ __volatile__ ( - "ldbu %0,%1" - : "=r" (result) - : "m" (*(volatile unsigned char *)(addr+PYXIS_BW_IO))); - - return result; -} - -extern inline void __outb(unsigned char b, unsigned long addr) -{ - __asm__ __volatile__ ( - "stb %1,%0\n\t" - "mb" - : "=m" (*(volatile unsigned char *)(addr+PYXIS_BW_IO)) - : "r" (b)); -} - -extern inline unsigned int __inw(unsigned long addr) -{ - register unsigned long result; - - __asm__ __volatile__ ( - "ldwu %0,%1" - : "=r" (result) - : "m" (*(volatile unsigned short *)(addr+PYXIS_BW_IO))); - - return result; -} - -extern inline void __outw(unsigned short b, unsigned long addr) -{ - __asm__ __volatile__ ( - "stw %1,%0\n\t" - "mb" - : "=m" (*(volatile unsigned short *)(addr+PYXIS_BW_IO)) - : "r" (b)); -} - -extern inline unsigned int __inl(unsigned long addr) -{ - return *(vuip)(addr+PYXIS_BW_IO); -} - -extern inline void __outl(unsigned int b, unsigned long addr) -{ - *(vuip)(addr+PYXIS_BW_IO) = b; - mb(); -} - -#define inb(port) __inb((port)) -#define inw(port) __inw((port)) -#define inl(port) __inl((port)) - -#define outb(x, port) __outb((x),(port)) -#define outw(x, port) __outw((x),(port)) -#define outl(x, port) __outl((x),(port)) - -#else /* BWIO_ENABLED */ - -extern inline unsigned int __inb(unsigned long addr) -{ - long result = *(vuip) ((addr << 5) + PYXIS_IO + 0x00); - result >>= (addr & 3) * 8; - return 0xffUL & result; -} - -extern inline void __outb(unsigned char b, unsigned long addr) -{ - unsigned int w; - - w = __kernel_insbl(b, addr & 3); - *(vuip) ((addr << 5) + PYXIS_IO + 0x00) = w; - mb(); -} - -extern inline unsigned int __inw(unsigned long addr) -{ - long result = *(vuip) ((addr << 5) + PYXIS_IO + 0x08); - result >>= (addr & 3) * 8; - return 0xffffUL & result; -} - -extern inline void __outw(unsigned short b, unsigned long addr) -{ - unsigned int w; - - w = __kernel_inswl(b, addr & 3); - *(vuip) ((addr << 5) + PYXIS_IO + 0x08) = w; - mb(); -} - -extern inline unsigned int __inl(unsigned long addr) -{ - return *(vuip) ((addr << 5) + PYXIS_IO + 0x18); -} - -extern inline void __outl(unsigned int b, unsigned long addr) -{ - *(vuip) ((addr << 5) + PYXIS_IO + 0x18) = b; - mb(); -} - -#define inb(port) \ -(__builtin_constant_p((port))?__inb(port):_inb(port)) - -#define outb(x, port) \ -(__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port))) - -#endif /* BWIO_ENABLED */ - - -/* - * Memory functions. 64-bit and 32-bit accesses are done through - * dense memory space, everything else through sparse space. - * - * For reading and writing 8 and 16 bit quantities we need to - * go through one of the three sparse address mapping regions - * and use the HAE_MEM CSR to provide some bits of the address. - * The following few routines use only sparse address region 1 - * which gives 1Gbyte of accessible space which relates exactly - * to the amount of PCI memory mapping *into* system address space. - * See p 6-17 of the specification but it looks something like this: - * - * 21164 Address: - * - * 3 2 1 - * 9876543210987654321098765432109876543210 - * 1ZZZZ0.PCI.QW.Address............BBLL - * - * ZZ = SBZ - * BB = Byte offset - * LL = Transfer length - * - * PCI Address: - * - * 3 2 1 - * 10987654321098765432109876543210 - * HHH....PCI.QW.Address........ 00 - * - * HHH = 31:29 HAE_MEM CSR - * - */ - -#ifdef BWIO_ENABLED - -extern inline unsigned long __readb(unsigned long addr) -{ - register unsigned long result; - - __asm__ __volatile__ ( - "ldbu %0,%1" - : "=r" (result) - : "m" (*(volatile unsigned char *)(addr+PYXIS_BW_MEM))); - - return result; -} - -extern inline unsigned long __readw(unsigned long addr) -{ - register unsigned long result; - - __asm__ __volatile__ ( - "ldwu %0,%1" - : "=r" (result) - : "m" (*(volatile unsigned short *)(addr+PYXIS_BW_MEM))); - - return result; -} - -extern inline unsigned long __readl(unsigned long addr) -{ - return *(vuip)(addr+PYXIS_BW_MEM); -} - -extern inline unsigned long __readq(unsigned long addr) -{ - return *(vulp)(addr+PYXIS_BW_MEM); -} - -extern inline void __writeb(unsigned char b, unsigned long addr) -{ - __asm__ __volatile__ ( - "stb %1,%0\n\t" - "mb" - : "=m" (*(volatile unsigned char *)(addr+PYXIS_BW_MEM)) - : "r" (b)); -} - -extern inline void __writew(unsigned short b, unsigned long addr) -{ - __asm__ __volatile__ ( - "stw %1,%0\n\t" - "mb" - : "=m" (*(volatile unsigned short *)(addr+PYXIS_BW_MEM)) - : "r" (b)); -} - -extern inline void __writel(unsigned int b, unsigned long addr) -{ - *(vuip)(addr+PYXIS_BW_MEM) = b; -} - -extern inline void __writeq(unsigned long b, unsigned long addr) -{ - *(vulp)(addr+PYXIS_BW_MEM) = b; -} - -#define readb(addr) __readb((addr)) -#define readw(addr) __readw((addr)) - -#define writeb(b, addr) __writeb((b),(addr)) -#define writew(b, addr) __writew((b),(addr)) - -#else /* BWIO_ENABLED */ - -#ifdef CONFIG_ALPHA_SRM_SETUP - -extern unsigned long pyxis_sm_base_r1, pyxis_sm_base_r2, pyxis_sm_base_r3; - -extern inline unsigned long __readb(unsigned long addr) -{ - unsigned long result, shift, work; - - if ((addr >= pyxis_sm_base_r1) && - (addr <= (pyxis_sm_base_r1 + MEM_R1_MASK))) - work = (((addr & MEM_R1_MASK) << 5) + PYXIS_SPARSE_MEM + 0x00); - else - if ((addr >= pyxis_sm_base_r2) && - (addr <= (pyxis_sm_base_r2 + MEM_R2_MASK))) - work = (((addr & MEM_R2_MASK) << 5) + PYXIS_SPARSE_MEM_R2 + 0x00); - else - if ((addr >= pyxis_sm_base_r3) && - (addr <= (pyxis_sm_base_r3 + MEM_R3_MASK))) - work = (((addr & MEM_R3_MASK) << 5) + PYXIS_SPARSE_MEM_R3 + 0x00); - else - { -#if 0 - printk("__readb: address 0x%lx not covered by HAE\n", addr); -#endif - return 0x0ffUL; - } - shift = (addr & 0x3) << 3; - result = *(vuip) work; - result >>= shift; - return 0x0ffUL & result; -} - -extern inline unsigned long __readw(unsigned long addr) -{ - unsigned long result, shift, work; - - if ((addr >= pyxis_sm_base_r1) && - (addr <= (pyxis_sm_base_r1 + MEM_R1_MASK))) - work = (((addr & MEM_R1_MASK) << 5) + PYXIS_SPARSE_MEM + 0x08); - else - if ((addr >= pyxis_sm_base_r2) && - (addr <= (pyxis_sm_base_r2 + MEM_R2_MASK))) - work = (((addr & MEM_R2_MASK) << 5) + PYXIS_SPARSE_MEM_R2 + 0x08); - else - if ((addr >= pyxis_sm_base_r3) && - (addr <= (pyxis_sm_base_r3 + MEM_R3_MASK))) - work = (((addr & MEM_R3_MASK) << 5) + PYXIS_SPARSE_MEM_R3 + 0x08); - else - { -#if 0 - printk("__readw: address 0x%lx not covered by HAE\n", addr); -#endif - return 0x0ffffUL; - } - shift = (addr & 0x3) << 3; - result = *(vuip) work; - result >>= shift; - return 0x0ffffUL & result; -} - -extern inline void __writeb(unsigned char b, unsigned long addr) -{ - unsigned long work; - - if ((addr >= pyxis_sm_base_r1) && - (addr <= (pyxis_sm_base_r1 + MEM_R1_MASK))) - work = (((addr & MEM_R1_MASK) << 5) + PYXIS_SPARSE_MEM + 0x00); - else - if ((addr >= pyxis_sm_base_r2) && - (addr <= (pyxis_sm_base_r2 + MEM_R2_MASK))) - work = (((addr & MEM_R2_MASK) << 5) + PYXIS_SPARSE_MEM_R2 + 0x00); - else - if ((addr >= pyxis_sm_base_r3) && - (addr <= (pyxis_sm_base_r3 + MEM_R3_MASK))) - work = (((addr & MEM_R3_MASK) << 5) + PYXIS_SPARSE_MEM_R3 + 0x00); - else - { -#if 0 - printk("__writeb: address 0x%lx not covered by HAE\n", addr); -#endif - return; - } - *(vuip) work = b * 0x01010101; -} - -extern inline void __writew(unsigned short b, unsigned long addr) -{ - unsigned long work; - - if ((addr >= pyxis_sm_base_r1) && - (addr <= (pyxis_sm_base_r1 + MEM_R1_MASK))) - work = (((addr & MEM_R1_MASK) << 5) + PYXIS_SPARSE_MEM + 0x00); - else - if ((addr >= pyxis_sm_base_r2) && - (addr <= (pyxis_sm_base_r2 + MEM_R2_MASK))) - work = (((addr & MEM_R2_MASK) << 5) + PYXIS_SPARSE_MEM_R2 + 0x00); - else - if ((addr >= pyxis_sm_base_r3) && - (addr <= (pyxis_sm_base_r3 + MEM_R3_MASK))) - work = (((addr & MEM_R3_MASK) << 5) + PYXIS_SPARSE_MEM_R3 + 0x00); - else - { -#if 0 - printk("__writew: address 0x%lx not covered by HAE\n", addr); -#endif - return; - } - *(vuip) work = b * 0x00010001; -} - -#else /* SRM_SETUP */ - -extern inline unsigned long __readb(unsigned long addr) -{ - unsigned long result, shift, msb, work, temp; - - shift = (addr & 0x3) << 3; - msb = addr & 0xE0000000UL; - temp = addr & MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } - work = ((temp << 5) + PYXIS_SPARSE_MEM + 0x00); - result = *(vuip) work; - result >>= shift; - return 0x0ffUL & result; -} - -extern inline unsigned long __readw(unsigned long addr) -{ - unsigned long result, shift, msb, work, temp; - - shift = (addr & 0x3) << 3; - msb = addr & 0xE0000000UL; - temp = addr & MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } - work = ((temp << 5) + PYXIS_SPARSE_MEM + 0x08); - result = *(vuip) work; - result >>= shift; - return 0x0ffffUL & result; -} - -extern inline void __writeb(unsigned char b, unsigned long addr) -{ - unsigned long msb ; - - msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } - *(vuip) ((addr << 5) + PYXIS_SPARSE_MEM + 0x00) = b * 0x01010101; -} - -extern inline void __writew(unsigned short b, unsigned long addr) -{ - unsigned long msb ; - - msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } - *(vuip) ((addr << 5) + PYXIS_SPARSE_MEM + 0x08) = b * 0x00010001; -} -#endif /* SRM_SETUP */ - -extern inline unsigned long __readl(unsigned long addr) -{ - return *(vuip) (addr + PYXIS_DENSE_MEM); -} - -extern inline unsigned long __readq(unsigned long addr) -{ - return *(vulp) (addr + PYXIS_DENSE_MEM); -} - -extern inline void __writel(unsigned int b, unsigned long addr) -{ - *(vuip) (addr + PYXIS_DENSE_MEM) = b; -} - -extern inline void __writeq(unsigned long b, unsigned long addr) -{ - *(vulp) (addr + PYXIS_DENSE_MEM) = b; -} - -#endif /* BWIO_ENABLED */ - -#define readl(a) __readl((unsigned long)(a)) -#define readq(a) __readq((unsigned long)(a)) -#define writel(v,a) __writel((v),(unsigned long)(a)) -#define writeq(v,a) __writeq((v),(unsigned long)(a)) - -#undef vuip -#undef vulp - -extern unsigned long pyxis_init (unsigned long mem_start, - unsigned long mem_end); - -#endif /* __KERNEL__ */ - -/* - * Data structure for handling PYXIS machine checks: - */ -struct el_PYXIS_sysdata_mcheck { - u_long coma_gcr; - u_long coma_edsr; - u_long coma_ter; - u_long coma_elar; - u_long coma_ehar; - u_long coma_ldlr; - u_long coma_ldhr; - u_long coma_base0; - u_long coma_base1; - u_long coma_base2; - u_long coma_cnfg0; - u_long coma_cnfg1; - u_long coma_cnfg2; - u_long epic_dcsr; - u_long epic_pear; - u_long epic_sear; - u_long epic_tbr1; - u_long epic_tbr2; - u_long epic_pbr1; - u_long epic_pbr2; - u_long epic_pmr1; - u_long epic_pmr2; - u_long epic_harx1; - u_long epic_harx2; - u_long epic_pmlt; - u_long epic_tag0; - u_long epic_tag1; - u_long epic_tag2; - u_long epic_tag3; - u_long epic_tag4; - u_long epic_tag5; - u_long epic_tag6; - u_long epic_tag7; - u_long epic_data0; - u_long epic_data1; - u_long epic_data2; - u_long epic_data3; - u_long epic_data4; - u_long epic_data5; - u_long epic_data6; - u_long epic_data7; -}; - -#define RTC_PORT(x) (0x70 + (x)) -#define RTC_ADDR(x) (0x80 | (x)) -#define RTC_ALWAYS_BCD 0 - -#endif /* __ALPHA_PYXIS__H__ */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/string.h linux/include/asm-alpha/string.h --- v2.1.115/linux/include/asm-alpha/string.h Tue Jul 21 00:15:32 1998 +++ linux/include/asm-alpha/string.h Sun Aug 9 12:09:06 1998 @@ -56,6 +56,8 @@ ? __constant_c_memset((s),0x0001000100010001UL*(unsigned short)(c),(n)) \ : __memsetw((s),(c),(n))) +extern int strcasecmp(const char *, const char *); + #endif /* __KERNEL__ */ #endif /* __ALPHA_STRING_H__ */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/system.h linux/include/asm-alpha/system.h --- v2.1.115/linux/include/asm-alpha/system.h Wed Apr 1 20:11:54 1998 +++ linux/include/asm-alpha/system.h Sun Aug 9 12:09:06 1998 @@ -100,13 +100,16 @@ #define switch_to(prev,next) do { \ current = next; \ - alpha_switch_to((unsigned long) ¤t->tss - 0xfffffc0000000000); \ + alpha_switch_to((unsigned long) ¤t->tss - IDENT_ADDR); \ } while (0) extern void alpha_switch_to(unsigned long pctxp); #define mb() \ __asm__ __volatile__("mb": : :"memory") + +#define wmb() \ +__asm__ __volatile__("wmb": : :"memory") #define imb() \ __asm__ __volatile__ ("call_pal %0" : : "i" (PAL_imb) : "memory") diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/t2.h linux/include/asm-alpha/t2.h --- v2.1.115/linux/include/asm-alpha/t2.h Tue Jul 21 00:15:32 1998 +++ linux/include/asm-alpha/t2.h Wed Dec 31 16:00:00 1969 @@ -1,671 +0,0 @@ -#ifndef __ALPHA_T2__H__ -#define __ALPHA_T2__H__ - -#include -#include - -/* - * T2 is the internal name for the core logic chipset which provides - * memory controller and PCI access for the SABLE-based systems. - * - * This file is based on: - * - * SABLE I/O Specification - * Revision/Update Information: 1.3 - * - * jestabro@amt.tay1.dec.com Initial Version. - * - */ - -#define BYTE_ENABLE_SHIFT 5 -#define TRANSFER_LENGTH_SHIFT 3 -#define MEM_R1_MASK 0x03ffffff /* Mem sparse space region 1 mask is 26 bits */ - -#ifdef CONFIG_ALPHA_SRM_SETUP -/* if we are using the SRM PCI setup, we'll need to use variables instead */ -#define T2_DMA_WIN_BASE_DEFAULT (1024*1024*1024) -#define T2_DMA_WIN_SIZE_DEFAULT (1024*1024*1024) - -extern unsigned int T2_DMA_WIN_BASE; -extern unsigned int T2_DMA_WIN_SIZE; - -#else /* SRM_SETUP */ -#define T2_DMA_WIN_BASE (1024*1024*1024) -#define T2_DMA_WIN_SIZE (1024*1024*1024) -#endif /* SRM_SETUP */ - -/* GAMMA-SABLE is a SABLE with EV5-based CPUs */ -#ifdef CONFIG_ALPHA_GAMMA -# define GAMMA_BIAS 0x8000000000UL -#else /* GAMMA */ -# define GAMMA_BIAS 0x0000000000UL -#endif /* GAMMA */ - -/* - * Memory spaces: - */ -#define T2_CONF (IDENT_ADDR + GAMMA_BIAS + 0x390000000UL) -#define T2_IO (IDENT_ADDR + GAMMA_BIAS + 0x3a0000000UL) -#define T2_SPARSE_MEM (IDENT_ADDR + GAMMA_BIAS + 0x200000000UL) -#define T2_DENSE_MEM (IDENT_ADDR + GAMMA_BIAS + 0x3c0000000UL) -#define DENSE_MEM(addr) T2_DENSE_MEM - -#define T2_IOCSR (IDENT_ADDR + GAMMA_BIAS + 0x38e000000UL) -#define T2_CERR1 (IDENT_ADDR + GAMMA_BIAS + 0x38e000020UL) -#define T2_CERR2 (IDENT_ADDR + GAMMA_BIAS + 0x38e000040UL) -#define T2_CERR3 (IDENT_ADDR + GAMMA_BIAS + 0x38e000060UL) -#define T2_PERR1 (IDENT_ADDR + GAMMA_BIAS + 0x38e000080UL) -#define T2_PERR2 (IDENT_ADDR + GAMMA_BIAS + 0x38e0000a0UL) -#define T2_PSCR (IDENT_ADDR + GAMMA_BIAS + 0x38e0000c0UL) -#define T2_HAE_1 (IDENT_ADDR + GAMMA_BIAS + 0x38e0000e0UL) -#define T2_HAE_2 (IDENT_ADDR + GAMMA_BIAS + 0x38e000100UL) -#define T2_HBASE (IDENT_ADDR + GAMMA_BIAS + 0x38e000120UL) -#define T2_WBASE1 (IDENT_ADDR + GAMMA_BIAS + 0x38e000140UL) -#define T2_WMASK1 (IDENT_ADDR + GAMMA_BIAS + 0x38e000160UL) -#define T2_TBASE1 (IDENT_ADDR + GAMMA_BIAS + 0x38e000180UL) -#define T2_WBASE2 (IDENT_ADDR + GAMMA_BIAS + 0x38e0001a0UL) -#define T2_WMASK2 (IDENT_ADDR + GAMMA_BIAS + 0x38e0001c0UL) -#define T2_TBASE2 (IDENT_ADDR + GAMMA_BIAS + 0x38e0001e0UL) -#define T2_TLBBR (IDENT_ADDR + GAMMA_BIAS + 0x38e000200UL) - -#define T2_HAE_3 (IDENT_ADDR + GAMMA_BIAS + 0x38e000240UL) -#define T2_HAE_4 (IDENT_ADDR + GAMMA_BIAS + 0x38e000260UL) - -#define HAE_ADDRESS T2_HAE_1 - -/* T2 CSRs are in the non-cachable primary IO space from 3.8000.0000 to - 3.8fff.ffff - * - * +--------------+ 3 8000 0000 - * | CPU 0 CSRs | - * +--------------+ 3 8100 0000 - * | CPU 1 CSRs | - * +--------------+ 3 8200 0000 - * | CPU 2 CSRs | - * +--------------+ 3 8300 0000 - * | CPU 3 CSRs | - * +--------------+ 3 8400 0000 - * | CPU Reserved | - * +--------------+ 3 8700 0000 - * | Mem Reserved | - * +--------------+ 3 8800 0000 - * | Mem 0 CSRs | - * +--------------+ 3 8900 0000 - * | Mem 1 CSRs | - * +--------------+ 3 8a00 0000 - * | Mem 2 CSRs | - * +--------------+ 3 8b00 0000 - * | Mem 3 CSRs | - * +--------------+ 3 8c00 0000 - * | Mem Reserved | - * +--------------+ 3 8e00 0000 - * | PCI Bridge | - * +--------------+ 3 8f00 0000 - * | Expansion IO | - * +--------------+ 3 9000 0000 - * - * - */ -#define CPU0_BASE (IDENT_ADDR + GAMMA_BIAS + 0x380000000L) -#define CPU1_BASE (IDENT_ADDR + GAMMA_BIAS + 0x381000000L) -#define CPU2_BASE (IDENT_ADDR + GAMMA_BIAS + 0x382000000L) -#define CPU3_BASE (IDENT_ADDR + GAMMA_BIAS + 0x383000000L) -#define MEM0_BASE (IDENT_ADDR + GAMMA_BIAS + 0x388000000L) -#define MEM1_BASE (IDENT_ADDR + GAMMA_BIAS + 0x389000000L) -#define MEM2_BASE (IDENT_ADDR + GAMMA_BIAS + 0x38a000000L) -#define MEM3_BASE (IDENT_ADDR + GAMMA_BIAS + 0x38b000000L) - -#ifdef __KERNEL__ - -/* - * Translate physical memory address as seen on (PCI) bus into - * a kernel virtual address and vv. - */ -extern inline unsigned long virt_to_bus(void * address) -{ - return virt_to_phys(address) + T2_DMA_WIN_BASE; -} - -extern inline void * bus_to_virt(unsigned long address) -{ - return phys_to_virt(address - T2_DMA_WIN_BASE); -} - -/* - * I/O functions: - * - * T2 (the core logic PCI/memory support chipset for the SABLE - * series of processors uses a sparse address mapping scheme to - * get at PCI memory and I/O. - */ - -#define vuip volatile unsigned int * - -extern inline unsigned int __inb(unsigned long addr) -{ - long result = *(vuip) ((addr << 5) + T2_IO + 0x00); - result >>= (addr & 3) * 8; - return 0xffUL & result; -} - -extern inline void __outb(unsigned char b, unsigned long addr) -{ - unsigned int w; - - w = __kernel_insbl(b, addr & 3); - *(vuip) ((addr << 5) + T2_IO + 0x00) = w; - mb(); -} - -extern inline unsigned int __inw(unsigned long addr) -{ - long result = *(vuip) ((addr << 5) + T2_IO + 0x08); - result >>= (addr & 3) * 8; - return 0xffffUL & result; -} - -extern inline void __outw(unsigned short b, unsigned long addr) -{ - unsigned int w; - - w = __kernel_inswl(b, addr & 3); - *(vuip) ((addr << 5) + T2_IO + 0x08) = w; - mb(); -} - -extern inline unsigned int __inl(unsigned long addr) -{ - return *(vuip) ((addr << 5) + T2_IO + 0x18); -} - -extern inline void __outl(unsigned int b, unsigned long addr) -{ - *(vuip) ((addr << 5) + T2_IO + 0x18) = b; - mb(); -} - - -/* - * Memory functions. 64-bit and 32-bit accesses are done through - * dense memory space, everything else through sparse space. - * - * For reading and writing 8 and 16 bit quantities we need to - * go through one of the three sparse address mapping regions - * and use the HAE_MEM CSR to provide some bits of the address. - * The following few routines use only sparse address region 1 - * which gives 1Gbyte of accessible space which relates exactly - * to the amount of PCI memory mapping *into* system address space. - * See p 6-17 of the specification but it looks something like this: - * - * 21164 Address: - * - * 3 2 1 - * 9876543210987654321098765432109876543210 - * 1ZZZZ0.PCI.QW.Address............BBLL - * - * ZZ = SBZ - * BB = Byte offset - * LL = Transfer length - * - * PCI Address: - * - * 3 2 1 - * 10987654321098765432109876543210 - * HHH....PCI.QW.Address........ 00 - * - * HHH = 31:29 HAE_MEM CSR - * - */ -#ifdef CONFIG_ALPHA_SRM_SETUP - -extern unsigned long t2_sm_base; - -extern int __t2_ioaddr_check(unsigned long addr) -{ - if ((addr >= t2_sm_base && addr <= t2_sm_base + MEM_R1_MASK) - || (addr >= 512*1024 && addr < 1024*1024)) - return 1; -#if 0 - printk("T2: address 0x%lx not covered by HAE\n", addr); -#endif - return 0; -} - - -extern inline unsigned long __readb(unsigned long addr) -{ - unsigned long result, shift, work; - - if (!__t2_addr_check(addr)) - return 0xFF; - - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x00); - result = *(vuip) work; - shift = (addr & 0x3) << 3; - return (result >> shift) & 0xFF; -} - -extern inline unsigned long __readw(unsigned long addr) -{ - unsigned long result, shift, work; - - if (!__t2_addr_check(addr)) - return 0xFFFF; - - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x08); - result = *(vuip) work; - shift = (addr & 0x3) << 3; - return (result >> shift) & 0xFF; -} - -/* On SABLE with T2, we must use SPARSE memory even for 32-bit access ... */ -extern inline unsigned long __readl(unsigned long addr) -{ - unsigned long work; - - if (!__t2_addr_check(addr)) - return 0xFFFFFFFF; - - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18); - return *(vuip) work; -} - -/* ... which makes me wonder why we advertise we have DENSE memory at all. - Anyway, guess that means we should emulate 64-bit access as two cycles. */ -extern inline unsigned long __readq(unsigned long addr) -{ - unsigned long work, r0, r1; - - if (!__t2_addr_check(addr)) - return ~0UL; - - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18); - r0 = *(vuip) work0; - r1 = *(vuip) (work0 + (4 << 5)); - return r1 << 32 | r0; -} - -extern inline void __writeb(unsigned char b, unsigned long addr) -{ - unsigned long work; - - if (!__t2_addr_check(addr)) - return; - - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x00); - *(vuip) work = b * 0x01010101; -} - -extern inline void __writew(unsigned short b, unsigned long addr) -{ - unsigned long work; - - if (!__t2_addr_check(addr)) - return; - - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x08); - *(vuip) work = b * 0x00010001; -} - -/* On SABLE with T2, we must use SPARSE memory even for 32-bit access ... */ -extern inline void __writel(unsigned int b, unsigned long addr) -{ - unsigned long work; - - if (!__t2_addr_check(addr)) - return; - - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18); - *(vuip) work = b; -} - -/* ... which makes me wonder why we advertise we have DENSE memory at all. - Anyway, guess that means we should emulate 64-bit access as two cycles. */ -extern inline void __writeq(unsigned long b, unsigned long addr) -{ - unsigned long work; - - if (!__t2_addr_check(addr)) - return; - - work = (((addr & MEM_R1_MASK) << 5) + T2_SPARSE_MEM + 0x18); - *(vuip) work0 = b; - *(vuip) (work0 + (4 << 5)) = (b >> 32); -} - -#else /* SRM_SETUP */ - -extern inline unsigned long __readb(unsigned long addr) -{ - unsigned long result, shift, msb; - - shift = (addr & 0x3) * 8 ; - msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } - result = *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x00) ; - result >>= shift; - return 0xffUL & result; -} - -extern inline unsigned long __readw(unsigned long addr) -{ - unsigned long result, shift, msb; - - shift = (addr & 0x3) * 8; - msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } - result = *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08); - result >>= shift; - return 0xffffUL & result; -} - -/* on SABLE with T2, we must use SPARSE memory even for 32-bit access */ -extern inline unsigned long __readl(unsigned long addr) -{ - unsigned long result, msb; - - msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } - result = *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18); - return 0xffffffffUL & result; -} - -extern inline unsigned long __readq(unsigned long addr) -{ - unsigned long r0, r1, work, msb; - - msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } - work = (addr << 5) + T2_SPARSE_MEM + 0x18; - r0 = *(vuip)(work); - r1 = *(vuip)(work + (4 << 5)); - return r1 << 32 | r0; -} -extern inline void __writeb(unsigned char b, unsigned long addr) -{ - unsigned long msb ; - - msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } - *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x00) = b * 0x01010101; -} - -extern inline void __writew(unsigned short b, unsigned long addr) -{ - unsigned long msb ; - - msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } - *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08) = b * 0x00010001; -} - -/* on SABLE with T2, we must use SPARSE memory even for 32-bit access */ -extern inline void __writel(unsigned int b, unsigned long addr) -{ - unsigned long msb ; - - msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } - *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18) = b; -} - -extern inline void __writeq(unsigned long b, unsigned long addr) -{ - unsigned long msb, work; - - msb = addr & 0xE0000000 ; - addr &= MEM_R1_MASK ; - if (msb != hae.cache) { - set_hae(msb); - } - work = (addr << 5) + T2_SPARSE_MEM + 0x18; - *(vuip)work = b; - *(vuip)(work + (4 << 5)) = b >> 32; -} - -#endif /* SRM_SETUP */ - -#define inb(port) \ -(__builtin_constant_p((port))?__inb(port):_inb(port)) - -#define outb(x, port) \ -(__builtin_constant_p((port))?__outb((x),(port)):_outb((x),(port))) - -#undef vuip - -extern unsigned long t2_init (unsigned long mem_start, - unsigned long mem_end); - -#endif /* __KERNEL__ */ - -/* - * Sable CPU Module CSRS - * - * These are CSRs for hardware other than the CPU chip on the CPU module. - * The CPU module has Backup Cache control logic, Cbus control logic, and - * interrupt control logic on it. There is a duplicate tag store to speed - * up maintaining cache coherency. - */ - -struct sable_cpu_csr { -unsigned long bcc; long fill_00[3]; /* Backup Cache Control */ -unsigned long bcce; long fill_01[3]; /* Backup Cache Correctable Error */ -unsigned long bccea; long fill_02[3]; /* B-Cache Corr Err Address Latch */ -unsigned long bcue; long fill_03[3]; /* B-Cache Uncorrectable Error */ -unsigned long bcuea; long fill_04[3]; /* B-Cache Uncorr Err Addr Latch */ -unsigned long dter; long fill_05[3]; /* Duplicate Tag Error */ -unsigned long cbctl; long fill_06[3]; /* CBus Control */ -unsigned long cbe; long fill_07[3]; /* CBus Error */ -unsigned long cbeal; long fill_08[3]; /* CBus Error Addr Latch low */ -unsigned long cbeah; long fill_09[3]; /* CBus Error Addr Latch high */ -unsigned long pmbx; long fill_10[3]; /* Processor Mailbox */ -unsigned long ipir; long fill_11[3]; /* Inter-Processor Int Request */ -unsigned long sic; long fill_12[3]; /* System Interrupt Clear */ -unsigned long adlk; long fill_13[3]; /* Address Lock (LDxL/STxC) */ -unsigned long madrl; long fill_14[3]; /* CBus Miss Address */ -unsigned long rev; long fill_15[3]; /* CMIC Revision */ -}; - -/* - * Data structure for handling T2 machine checks: - */ -struct el_t2_frame_header { - unsigned int elcf_fid; /* Frame ID (from above) */ - unsigned int elcf_size; /* Size of frame in bytes */ -}; - -struct el_t2_procdata_mcheck { - unsigned long elfmc_paltemp[32]; /* PAL TEMP REGS. */ - /* EV4-specific fields */ - unsigned long elfmc_exc_addr; /* Addr of excepting insn. */ - unsigned long elfmc_exc_sum; /* Summary of arith traps. */ - unsigned long elfmc_exc_mask; /* Exception mask (from exc_sum). */ - unsigned long elfmc_iccsr; /* IBox hardware enables. */ - unsigned long elfmc_pal_base; /* Base address for PALcode. */ - unsigned long elfmc_hier; /* Hardware Interrupt Enable. */ - unsigned long elfmc_hirr; /* Hardware Interrupt Request. */ - unsigned long elfmc_mm_csr; /* D-stream fault info. */ - unsigned long elfmc_dc_stat; /* D-cache status (ECC/Parity Err). */ - unsigned long elfmc_dc_addr; /* EV3 Phys Addr for ECC/DPERR. */ - unsigned long elfmc_abox_ctl; /* ABox Control Register. */ - unsigned long elfmc_biu_stat; /* BIU Status. */ - unsigned long elfmc_biu_addr; /* BUI Address. */ - unsigned long elfmc_biu_ctl; /* BIU Control. */ - unsigned long elfmc_fill_syndrome; /* For correcting ECC errors. */ - unsigned long elfmc_fill_addr;/* Cache block which was being read. */ - unsigned long elfmc_va; /* Effective VA of fault or miss. */ - unsigned long elfmc_bc_tag; /* Backup Cache Tag Probe Results. */ -}; - -/* - * Sable processor specific Machine Check Data segment. - */ - -struct el_t2_logout_header { - unsigned int elfl_size; /* size in bytes of logout area. */ - int elfl_sbz1:31; /* Should be zero. */ - char elfl_retry:1; /* Retry flag. */ - unsigned int elfl_procoffset; /* Processor-specific offset. */ - unsigned int elfl_sysoffset; /* Offset of system-specific. */ - unsigned int elfl_error_type; /* PAL error type code. */ - unsigned int elfl_frame_rev; /* PAL Frame revision. */ -}; -struct el_t2_sysdata_mcheck { - unsigned long elcmc_bcc; /* CSR 0 */ - unsigned long elcmc_bcce; /* CSR 1 */ - unsigned long elcmc_bccea; /* CSR 2 */ - unsigned long elcmc_bcue; /* CSR 3 */ - unsigned long elcmc_bcuea; /* CSR 4 */ - unsigned long elcmc_dter; /* CSR 5 */ - unsigned long elcmc_cbctl; /* CSR 6 */ - unsigned long elcmc_cbe; /* CSR 7 */ - unsigned long elcmc_cbeal; /* CSR 8 */ - unsigned long elcmc_cbeah; /* CSR 9 */ - unsigned long elcmc_pmbx; /* CSR 10 */ - unsigned long elcmc_ipir; /* CSR 11 */ - unsigned long elcmc_sic; /* CSR 12 */ - unsigned long elcmc_adlk; /* CSR 13 */ - unsigned long elcmc_madrl; /* CSR 14 */ - unsigned long elcmc_crrev4; /* CSR 15 */ -}; - -/* - * Sable memory error frame - sable pfms section 3.42 - */ -struct el_t2_data_memory { - struct el_t2_frame_header elcm_hdr; /* ID$MEM-FERR = 0x08 */ - unsigned int elcm_module; /* Module id. */ - unsigned int elcm_res04; /* Reserved. */ - unsigned long elcm_merr; /* CSR0: Error Reg 1. */ - unsigned long elcm_mcmd1; /* CSR1: Command Trap 1. */ - unsigned long elcm_mcmd2; /* CSR2: Command Trap 2. */ - unsigned long elcm_mconf; /* CSR3: Configuration. */ - unsigned long elcm_medc1; /* CSR4: EDC Status 1. */ - unsigned long elcm_medc2; /* CSR5: EDC Status 2. */ - unsigned long elcm_medcc; /* CSR6: EDC Control. */ - unsigned long elcm_msctl; /* CSR7: Stream Buffer Control. */ - unsigned long elcm_mref; /* CSR8: Refresh Control. */ - unsigned long elcm_filter; /* CSR9: CRD Filter Control. */ -}; - - -/* - * Sable other CPU error frame - sable pfms section 3.43 - */ -struct el_t2_data_other_cpu { - short elco_cpuid; /* CPU ID */ - short elco_res02[3]; - unsigned long elco_bcc; /* CSR 0 */ - unsigned long elco_bcce; /* CSR 1 */ - unsigned long elco_bccea; /* CSR 2 */ - unsigned long elco_bcue; /* CSR 3 */ - unsigned long elco_bcuea; /* CSR 4 */ - unsigned long elco_dter; /* CSR 5 */ - unsigned long elco_cbctl; /* CSR 6 */ - unsigned long elco_cbe; /* CSR 7 */ - unsigned long elco_cbeal; /* CSR 8 */ - unsigned long elco_cbeah; /* CSR 9 */ - unsigned long elco_pmbx; /* CSR 10 */ - unsigned long elco_ipir; /* CSR 11 */ - unsigned long elco_sic; /* CSR 12 */ - unsigned long elco_adlk; /* CSR 13 */ - unsigned long elco_madrl; /* CSR 14 */ - unsigned long elco_crrev4; /* CSR 15 */ -}; - -/* - * Sable other CPU error frame - sable pfms section 3.44 - */ -struct el_t2_data_t2{ - struct el_t2_frame_header elct_hdr; /* ID$T2-FRAME */ - unsigned long elct_iocsr; /* IO Control and Status Register */ - unsigned long elct_cerr1; /* Cbus Error Register 1 */ - unsigned long elct_cerr2; /* Cbus Error Register 2 */ - unsigned long elct_cerr3; /* Cbus Error Register 3 */ - unsigned long elct_perr1; /* PCI Error Register 1 */ - unsigned long elct_perr2; /* PCI Error Register 2 */ - unsigned long elct_hae0_1; /* High Address Extension Register 1 */ - unsigned long elct_hae0_2; /* High Address Extension Register 2 */ - unsigned long elct_hbase; /* High Base Register */ - unsigned long elct_wbase1; /* Window Base Register 1 */ - unsigned long elct_wmask1; /* Window Mask Register 1 */ - unsigned long elct_tbase1; /* Translated Base Register 1 */ - unsigned long elct_wbase2; /* Window Base Register 2 */ - unsigned long elct_wmask2; /* Window Mask Register 2 */ - unsigned long elct_tbase2; /* Translated Base Register 2 */ - unsigned long elct_tdr0; /* TLB Data Register 0 */ - unsigned long elct_tdr1; /* TLB Data Register 1 */ - unsigned long elct_tdr2; /* TLB Data Register 2 */ - unsigned long elct_tdr3; /* TLB Data Register 3 */ - unsigned long elct_tdr4; /* TLB Data Register 4 */ - unsigned long elct_tdr5; /* TLB Data Register 5 */ - unsigned long elct_tdr6; /* TLB Data Register 6 */ - unsigned long elct_tdr7; /* TLB Data Register 7 */ -}; - -/* - * Sable error log data structure - sable pfms section 3.40 - */ -struct el_t2_data_corrected { - unsigned long elcpb_biu_stat; - unsigned long elcpb_biu_addr; - unsigned long elcpb_biu_ctl; - unsigned long elcpb_fill_syndrome; - unsigned long elcpb_fill_addr; - unsigned long elcpb_bc_tag; -}; - -/* - * Sable error log data structure - * Note there are 4 memory slots on sable (see t2.h) - */ -struct el_t2_frame_mcheck { - struct el_t2_frame_header elfmc_header; /* ID$P-FRAME_MCHECK */ - struct el_t2_logout_header elfmc_hdr; - struct el_t2_procdata_mcheck elfmc_procdata; - struct el_t2_sysdata_mcheck elfmc_sysdata; - struct el_t2_data_t2 elfmc_t2data; - struct el_t2_data_memory elfmc_memdata[4]; - struct el_t2_frame_header elfmc_footer; /* empty */ -}; - - -/* - * Sable error log data structures on memory errors - */ -struct el_t2_frame_corrected { - struct el_t2_frame_header elfcc_header; /* ID$P-BC-COR */ - struct el_t2_logout_header elfcc_hdr; - struct el_t2_data_corrected elfcc_procdata; -/* struct el_t2_data_t2 elfcc_t2data; */ -/* struct el_t2_data_memory elfcc_memdata[4]; */ - struct el_t2_frame_header elfcc_footer; /* empty */ -}; - - -#define RTC_PORT(x) (0x70 + (x)) -#define RTC_ADDR(x) (0x80 | (x)) -#define RTC_ALWAYS_BCD 0 - -#endif /* __ALPHA_T2__H__ */ diff -u --recursive --new-file v2.1.115/linux/include/asm-alpha/tsunami.h linux/include/asm-alpha/tsunami.h --- v2.1.115/linux/include/asm-alpha/tsunami.h Tue Jul 21 00:15:32 1998 +++ linux/include/asm-alpha/tsunami.h Wed Dec 31 16:00:00 1969 @@ -1,451 +0,0 @@ -#ifndef __ALPHA_TSUNAMI__H__ -#define __ALPHA_TSUNAMI__H__ - -#include -#include - -/* - * TSUNAMI/TYPHOON are the internal names for the core logic chipset which - * provides memory controller and PCI access for the 21264 based systems. - * - * This file is based on: - * - * Tsunami System Programmers Manual - * Preliminary, Chapters 2-5 - * - */ - -#define BYTE_ENABLE_SHIFT 5 -#define TRANSFER_LENGTH_SHIFT 3 - -#ifdef CONFIG_ALPHA_SRM_SETUP -/* if we are using the SRM PCI setup, we'll need to use variables instead */ -#define TSUNAMI_DMA_WIN_BASE_DEFAULT (1024*1024*1024) -#define TSUNAMI_DMA_WIN_SIZE_DEFAULT (1024*1024*1024) - -extern unsigned int TSUNAMI_DMA_WIN_BASE; -extern unsigned int TSUNAMI_DMA_WIN_SIZE; - -#else /* SRM_SETUP */ -#define TSUNAMI_DMA_WIN_BASE (1024*1024*1024) -#define TSUNAMI_DMA_WIN_SIZE (1024*1024*1024) -#endif /* SRM_SETUP */ - -#ifdef USE_48_BIT_KSEG -#define TS_BIAS 0x80000000000UL -#else -#define TS_BIAS 0x10000000000UL -#endif - -/* - * CChip and DChip registers - */ -#define TSUNAMI_CSR_CSC (IDENT_ADDR + TS_BIAS + 0x1A0000000UL) -#define TSUNAMI_CSR_MTR (IDENT_ADDR + TS_BIAS + 0x1A0000040UL) -#define TSUNAMI_CSR_MISC (IDENT_ADDR + TS_BIAS + 0x1A0000080UL) -#define TSUNAMI_CSR_MPD (IDENT_ADDR + TS_BIAS + 0x1A00000C0UL) -#define TSUNAMI_CSR_AAR0 (IDENT_ADDR + TS_BIAS + 0x1A0000100UL) -#define TSUNAMI_CSR_AAR1 (IDENT_ADDR + TS_BIAS + 0x1A0000140UL) -#define TSUNAMI_CSR_AAR2 (IDENT_ADDR + TS_BIAS + 0x1A0000180UL) -#define TSUNAMI_CSR_AAR3 (IDENT_ADDR + TS_BIAS + 0x1A00001C0UL) -#define TSUNAMI_CSR_DIM0 (IDENT_ADDR + TS_BIAS + 0x1A0000200UL) -#define TSUNAMI_CSR_DIM1 (IDENT_ADDR + TS_BIAS + 0x1A0000240UL) -#define TSUNAMI_CSR_DIR0 (IDENT_ADDR + TS_BIAS + 0x1A0000280UL) -#define TSUNAMI_CSR_DIR1 (IDENT_ADDR + TS_BIAS + 0x1A00002C0UL) - -#define TSUNAMI_CSR_DRIR (IDENT_ADDR + TS_BIAS + 0x1A0000300UL) -#define TSUNAMI_CSR_PRBEN (IDENT_ADDR + TS_BIAS + 0x1A0000340UL) -#define TSUNAMI_CSR_IIC (IDENT_ADDR + TS_BIAS + 0x1A0000380UL) -#define TSUNAMI_CSR_WDR (IDENT_ADDR + TS_BIAS + 0x1A00003C0UL) -#define TSUNAMI_CSR_MPR0 (IDENT_ADDR + TS_BIAS + 0x1A0000400UL) -#define TSUNAMI_CSR_MPR1 (IDENT_ADDR + TS_BIAS + 0x1A0000440UL) -#define TSUNAMI_CSR_MPR2 (IDENT_ADDR + TS_BIAS + 0x1A0000480UL) -#define TSUNAMI_CSR_MPR3 (IDENT_ADDR + TS_BIAS + 0x1A00004C0UL) -#define TSUNAMI_CSR_TTR (IDENT_ADDR + TS_BIAS + 0x1A0000580UL) -#define TSUNAMI_CSR_TDR (IDENT_ADDR + TS_BIAS + 0x1A00005C0UL) -#define TSUNAMI_CSR_DSC (IDENT_ADDR + TS_BIAS + 0x1B0000800UL) -#define TSUNAMI_CSR_STR (IDENT_ADDR + TS_BIAS + 0x1B0000840UL) -#define TSUNAMI_CSR_DREV (IDENT_ADDR + TS_BIAS + 0x1B0000880UL) - -/* - * PChip registers - */ -#define TSUNAMI_PCHIP0_WSBA0 (IDENT_ADDR + TS_BIAS + 0x180000000UL) -#define TSUNAMI_PCHIP0_WSBA1 (IDENT_ADDR + TS_BIAS + 0x180000040UL) -#define TSUNAMI_PCHIP0_WSBA2 (IDENT_ADDR + TS_BIAS + 0x180000080UL) -#define TSUNAMI_PCHIP0_WSBA3 (IDENT_ADDR + TS_BIAS + 0x1800000C0UL) - -#define TSUNAMI_PCHIP0_WSM0 (IDENT_ADDR + TS_BIAS + 0x180000100UL) -#define TSUNAMI_PCHIP0_WSM1 (IDENT_ADDR + TS_BIAS + 0x180000140UL) -#define TSUNAMI_PCHIP0_WSM2 (IDENT_ADDR + TS_BIAS + 0x180000180UL) -#define TSUNAMI_PCHIP0_WSM3 (IDENT_ADDR + TS_BIAS + 0x1800001C0UL) -#define TSUNAMI_PCHIP0_TBA0 (IDENT_ADDR + TS_BIAS + 0x180000200UL) -#define TSUNAMI_PCHIP0_TBA1 (IDENT_ADDR + TS_BIAS + 0x180000240UL) -#define TSUNAMI_PCHIP0_TBA2 (IDENT_ADDR + TS_BIAS + 0x180000280UL) -#define TSUNAMI_PCHIP0_TBA3 (IDENT_ADDR + TS_BIAS + 0x1800002C0UL) - -#define TSUNAMI_PCHIP0_PCTL (IDENT_ADDR + TS_BIAS + 0x180000300UL) -#define TSUNAMI_PCHIP0_PLAT (IDENT_ADDR + TS_BIAS + 0x180000340UL) -#define TSUNAMI_PCHIP0_RESERVED (IDENT_ADDR + TS_BIAS + 0x180000380UL) -#define TSUNAMI_PCHIP0_PERROR (IDENT_ADDR + TS_BIAS + 0x1800003c0UL) -#define TSUNAMI_PCHIP0_PERRMASK (IDENT_ADDR + TS_BIAS + 0x180000400UL) -#define TSUNAMI_PCHIP0_PERRSET (IDENT_ADDR + TS_BIAS + 0x180000440UL) -#define TSUNAMI_PCHIP0_TLBIV (IDENT_ADDR + TS_BIAS + 0x180000480UL) -#define TSUNAMI_PCHIP0_TLBIA (IDENT_ADDR + TS_BIAS + 0x1800004C0UL) -#define TSUNAMI_PCHIP0_PMONCTL (IDENT_ADDR + TS_BIAS + 0x180000500UL) -#define TSUNAMI_PCHIP0_PMONCNT (IDENT_ADDR + TS_BIAS + 0x180000540UL) - -#define TSUNAMI_PCHIP1_WSBA0 (IDENT_ADDR + TS_BIAS + 0x380000000UL) -#define TSUNAMI_PCHIP1_WSBA1 (IDENT_ADDR + TS_BIAS + 0x380000040UL) -#define TSUNAMI_PCHIP1_WSBA2 (IDENT_ADDR + TS_BIAS + 0x380000080UL) -#define TSUNAMI_PCHIP1_WSBA3 (IDENT_ADDR + TS_BIAS + 0x3800000C0UL) -#define TSUNAMI_PCHIP1_WSM0 (IDENT_ADDR + TS_BIAS + 0x380000100UL) -#define TSUNAMI_PCHIP1_WSM1 (IDENT_ADDR + TS_BIAS + 0x380000140UL) -#define TSUNAMI_PCHIP1_WSM2 (IDENT_ADDR + TS_BIAS + 0x380000180UL) -#define TSUNAMI_PCHIP1_WSM3 (IDENT_ADDR + TS_BIAS + 0x3800001C0UL) - -#define TSUNAMI_PCHIP1_TBA0 (IDENT_ADDR + TS_BIAS + 0x380000200UL) -#define TSUNAMI_PCHIP1_TBA1 (IDENT_ADDR + TS_BIAS + 0x380000240UL) -#define TSUNAMI_PCHIP1_TBA2 (IDENT_ADDR + TS_BIAS + 0x380000280UL) -#define TSUNAMI_PCHIP1_TBA3 (IDENT_ADDR + TS_BIAS + 0x3800002C0UL) - -#define TSUNAMI_PCHIP1_PCTL (IDENT_ADDR + TS_BIAS + 0x380000300UL) -#define TSUNAMI_PCHIP1_PLAT (IDENT_ADDR + TS_BIAS + 0x380000340UL) -#define TSUNAMI_PCHIP1_RESERVED (IDENT_ADDR + TS_BIAS + 0x380000380UL) -#define TSUNAMI_PCHIP1_PERROR (IDENT_ADDR + TS_BIAS + 0x3800003c0UL) -#define TSUNAMI_PCHIP1_PERRMASK (IDENT_ADDR + TS_BIAS + 0x380000400UL) -#define TSUNAMI_PCHIP1_PERRSET (IDENT_ADDR + TS_BIAS + 0x380000440UL) -#define TSUNAMI_PCHIP1_TLBIV (IDENT_ADDR + TS_BIAS + 0x380000480UL) -#define TSUNAMI_PCHIP1_TLBIA (IDENT_ADDR + TS_BIAS + 0x3800004C0UL) -#define TSUNAMI_PCHIP1_PMONCTL (IDENT_ADDR + TS_BIAS + 0x380000500UL) -#define TSUNAMI_PCHIP1_PMONCNT (IDENT_ADDR + TS_BIAS + 0x380000540UL) - -/* */ -/* TSUNAMI Pchip Error register. */ -/* */ -#define perror_m_lost 0x1 -#define perror_m_serr 0x2 -#define perror_m_perr 0x4 -#define perror_m_dcrto 0x8 -#define perror_m_sge 0x10 -#define perror_m_ape 0x20 -#define perror_m_ta 0x40 -#define perror_m_rdpe 0x80 -#define perror_m_nds 0x100 -#define perror_m_rto 0x200 -#define perror_m_uecc 0x400 -#define perror_m_cre 0x800 -#define perror_m_addrl 0xFFFFFFFF0000UL -#define perror_m_addrh 0x7000000000000UL -#define perror_m_cmd 0xF0000000000000UL -#define perror_m_syn 0xFF00000000000000UL -union TPchipPERROR { - struct { - unsigned int perror_v_lost : 1; - unsigned perror_v_serr : 1; - unsigned perror_v_perr : 1; - unsigned perror_v_dcrto : 1; - unsigned perror_v_sge : 1; - unsigned perror_v_ape : 1; - unsigned perror_v_ta : 1; - unsigned perror_v_rdpe : 1; - unsigned perror_v_nds : 1; - unsigned perror_v_rto : 1; - unsigned perror_v_uecc : 1; - unsigned perror_v_cre : 1; - unsigned perror_v_rsvd1 : 4; - unsigned perror_v_addrl : 32; - unsigned perror_v_addrh : 3; - unsigned perror_v_rsvd2 : 1; - unsigned perror_v_cmd : 4; - unsigned perror_v_syn : 8; - } perror_r_bits; - int perror_q_whole [2]; - } ; -/* */ -/* TSUNAMI Pchip Window Space Base Address register. */ -/* */ -#define wsba_m_ena 0x1 -#define wsba_m_sg 0x2 -#define wsba_m_ptp 0x4 -#define wsba_m_addr 0xFFF00000 -#define wmask_k_sz1gb 0x3FF00000 -union TPchipWSBA { - struct { - unsigned wsba_v_ena : 1; - unsigned wsba_v_sg : 1; - unsigned wsba_v_ptp : 1; - unsigned wsba_v_rsvd1 : 17; - unsigned wsba_v_addr : 12; - unsigned wsba_v_rsvd2 : 32; - } wsba_r_bits; - int wsba_q_whole [2]; - } ; -/* */ -/* TSUNAMI Pchip Control Register */ -/* */ -#define pctl_m_fdsc 0x1 -#define pctl_m_fbtb 0x2 -#define pctl_m_thdis 0x4 -#define pctl_m_chaindis 0x8 -#define pctl_m_tgtlat 0x10 -#define pctl_m_hole 0x20 -#define pctl_m_mwin 0x40 -#define pctl_m_arbena 0x80 -#define pctl_m_prigrp 0x7F00 -#define pctl_m_ppri 0x8000 -#define pctl_m_rsvd1 0x30000 -#define pctl_m_eccen 0x40000 -#define pctl_m_padm 0x80000 -#define pctl_m_cdqmax 0xF00000 -#define pctl_m_rev 0xFF000000 -#define pctl_m_crqmax 0xF00000000UL -#define pctl_m_ptpmax 0xF000000000UL -#define pctl_m_pclkx 0x30000000000UL -#define pctl_m_fdsdis 0x40000000000UL -#define pctl_m_fdwdis 0x80000000000UL -#define pctl_m_ptevrfy 0x100000000000UL -#define pctl_m_rpp 0x200000000000UL -#define pctl_m_pid 0xC00000000000UL -#define pctl_m_rsvd2 0xFFFF000000000000UL - -union TPchipPCTL { - struct { - unsigned pctl_v_fdsc : 1; - unsigned pctl_v_fbtb : 1; - unsigned pctl_v_thdis : 1; - unsigned pctl_v_chaindis : 1; - unsigned pctl_v_tgtlat : 1; - unsigned pctl_v_hole : 1; - unsigned pctl_v_mwin : 1; - unsigned pctl_v_arbena : 1; - unsigned pctl_v_prigrp : 7; - unsigned pctl_v_ppri : 1; - unsigned pctl_v_rsvd1 : 2; - unsigned pctl_v_eccen : 1; - unsigned pctl_v_padm : 1; - unsigned pctl_v_cdqmax : 4; - unsigned pctl_v_rev : 8; - unsigned pctl_v_crqmax : 4; - unsigned pctl_v_ptpmax : 4; - unsigned pctl_v_pclkx : 2; - unsigned pctl_v_fdsdis : 1; - unsigned pctl_v_fdwdis : 1; - unsigned pctl_v_ptevrfy : 1; - unsigned pctl_v_rpp : 1; - unsigned pctl_v_pid : 2; - unsigned pctl_v_rsvd2 : 16; - } pctl_r_bits; - int pctl_q_whole [2]; -} ; -/* */ -/* TSUNAMI Pchip Error Mask Register. */ -/* */ -#define perrmask_m_lost 0x1 -#define perrmask_m_serr 0x2 -#define perrmask_m_perr 0x4 -#define perrmask_m_dcrto 0x8 -#define perrmask_m_sge 0x10 -#define perrmask_m_ape 0x20 -#define perrmask_m_ta 0x40 -#define perrmask_m_rdpe 0x80 -#define perrmask_m_nds 0x100 -#define perrmask_m_rto 0x200 -#define perrmask_m_uecc 0x400 -#define perrmask_m_cre 0x800 -#define perrmask_m_rsvd 0xFFFFFFFFFFFFF000UL -union TPchipPERRMASK { - struct { - unsigned int perrmask_v_lost : 1; - unsigned perrmask_v_serr : 1; - unsigned perrmask_v_perr : 1; - unsigned perrmask_v_dcrto : 1; - unsigned perrmask_v_sge : 1; - unsigned perrmask_v_ape : 1; - unsigned perrmask_v_ta : 1; - unsigned perrmask_v_rdpe : 1; - unsigned perrmask_v_nds : 1; - unsigned perrmask_v_rto : 1; - unsigned perrmask_v_uecc : 1; - unsigned perrmask_v_cre : 1; - unsigned perrmask_v_rsvd1 : 20; - unsigned perrmask_v_rsvd2 : 32; - } perrmask_r_bits; - int perrmask_q_whole [2]; - } ; - -/* - * Memory spaces: - */ -#define TSUNAMI_PCI0_MEM (IDENT_ADDR + TS_BIAS + 0x000000000UL) -#define TSUNAMI_PCI0_IACK_SC (IDENT_ADDR + TS_BIAS + 0x1F8000000UL) -#define TSUNAMI_PCI0_IO (IDENT_ADDR + TS_BIAS + 0x1FC000000UL) -#define TSUNAMI_PCI0_CONF (IDENT_ADDR + TS_BIAS + 0x1FE000000UL) - -#define TSUNAMI_PCI1_MEM (IDENT_ADDR + TS_BIAS + 0x200000000UL) -#define TSUNAMI_PCI1_IACK_SC (IDENT_ADDR + TS_BIAS + 0x3F8000000UL) -#define TSUNAMI_PCI1_IO (IDENT_ADDR + TS_BIAS + 0x3FC000000UL) -#define TSUNAMI_PCI1_CONF (IDENT_ADDR + TS_BIAS + 0x3FE000000UL) - -#define HAE_ADDRESS 0 - -#ifdef __KERNEL__ - -/* - * Translate physical memory address as seen on (PCI) bus into - * a kernel virtual address and vv. - */ -extern inline unsigned long virt_to_bus(void * address) -{ - return virt_to_phys(address) + TSUNAMI_DMA_WIN_BASE; -} - -extern inline void * bus_to_virt(unsigned long address) -{ - return phys_to_virt(address - TSUNAMI_DMA_WIN_BASE); -} - -/* - * I/O functions: - * - * TSUNAMI, the 21??? PCI/memory support chipset for the EV6 (21264) - * can only use linear accesses to get at PCI memory and I/O spaces. - */ - -/* HACK ALERT! HACK ALERT! */ -/* HACK ALERT! HACK ALERT! */ - -/* only using PCI bus 0 for now in all routines */ - -#define DENSE_MEM(addr) TSUNAMI_PCI0_MEM - -/* HACK ALERT! HACK ALERT! */ -/* HACK ALERT! HACK ALERT! */ - -/* Also assume we are optimizing for EV6, and so the compiler knows about - byte/word instructions. */ - -#define vucp volatile unsigned char * -#define vusp volatile unsigned short * -#define vuip volatile unsigned int * -#define vulp volatile unsigned long * - -extern inline unsigned int __inb(unsigned long addr) -{ - return *(vucp)(addr + TSUNAMI_PCI0_IO); -} - -extern inline void __outb(unsigned char b, unsigned long addr) -{ - *(vucp)(addr + TSUNAMI_PCI0_IO) = b; - mb(); -} - -extern inline unsigned int __inw(unsigned long addr) -{ - return *(vusp)(addr+TSUNAMI_PCI0_IO); -} - -extern inline void __outw(unsigned short b, unsigned long addr) -{ - *(vusp)(addr+TSUNAMI_PCI0_IO) = b; - mb(); -} - -extern inline unsigned int __inl(unsigned long addr) -{ - return *(vuip)(addr+TSUNAMI_PCI0_IO); -} - -extern inline void __outl(unsigned int b, unsigned long addr) -{ - *(vuip)(addr+TSUNAMI_PCI0_IO) = b; - mb(); -} - -/* - * Memory functions. all accesses are done through linear space. - */ - -extern inline unsigned long __readb(unsigned long addr) -{ - return *(vucp)(addr+TSUNAMI_PCI0_MEM); -} - -extern inline unsigned long __readw(unsigned long addr) -{ - return *(vusp)(addr+TSUNAMI_PCI0_MEM); -} - -extern inline unsigned long __readl(unsigned long addr) -{ - return *(vuip)(addr+TSUNAMI_PCI0_MEM); -} - -extern inline unsigned long __readq(unsigned long addr) -{ - return *(vulp)(addr+TSUNAMI_PCI0_MEM); -} - -extern inline void __writeb(unsigned char b, unsigned long addr) -{ - *(vucp)(addr+TSUNAMI_PCI0_MEM) = b; - mb(); -} - -extern inline void __writew(unsigned short b, unsigned long addr) -{ - *(vusp)(addr+TSUNAMI_PCI0_MEM) = b; - mb(); -} - -extern inline void __writel(unsigned int b, unsigned long addr) -{ - *(vuip)(addr+TSUNAMI_PCI0_MEM) = b; - mb(); -} - -extern inline void __writeq(unsigned long b, unsigned long addr) -{ - *(vulp)(addr+TSUNAMI_PCI0_MEM) = b; - mb(); -} - -#define inb(port) __inb((port)) -#define inw(port) __inw((port)) -#define inl(port) __inl((port)) - -#define outb(v, port) __outb((v),(port)) -#define outw(v, port) __outw((v),(port)) -#define outl(v, port) __outl((v),(port)) - -#define readb(a) __readb((unsigned long)(a)) -#define readw(a) __readw((unsigned long)(a)) -#define readl(a) __readl((unsigned long)(a)) -#define readq(a) __readq((unsigned long)(a)) - -#define writeb(v,a) __writeb((v),(unsigned long)(a)) -#define writew(v,a) __writew((v),(unsigned long)(a)) -#define writel(v,a) __writel((v),(unsigned long)(a)) -#define writeq(v,a) __writeq((v),(unsigned long)(a)) - -#undef vucp -#undef vusp -#undef vuip -#undef vulp - -extern unsigned long tsunami_init (unsigned long, unsigned long); - -#endif /* __KERNEL__ */ - -/* - * Data structure for handling TSUNAMI machine checks: - */ -struct el_TSUNAMI_sysdata_mcheck { -}; - -#define RTC_PORT(x) (0x70 + (x)) -#define RTC_ADDR(x) (0x80 | (x)) -#define RTC_ALWAYS_BCD 0 - -#endif /* __ALPHA_TSUNAMI__H__ */ diff -u --recursive --new-file v2.1.115/linux/include/asm-i386/bugs.h linux/include/asm-i386/bugs.h --- v2.1.115/linux/include/asm-i386/bugs.h Fri Jul 31 17:05:52 1998 +++ linux/include/asm-i386/bugs.h Tue Aug 18 17:48:06 1998 @@ -281,12 +281,13 @@ if (boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX && (boot_cpu_data.x86_model & 0xf0) == 0x30) { /* 6x86(L) */ int dummy; - unsigned char ccr3, ccr5; + unsigned char ccr3, ccr4, ccr5; cli(); ccr3 = getCx86(CX86_CCR3); setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */ - setCx86(CX86_CCR4, getCx86(CX86_CCR4) | 0x80); /* enable cpuid */ + ccr4 = getCx86(CX86_CCR4); + setCx86(CX86_CCR4, ccr4 | 0x80); /* enable cpuid */ ccr5 = getCx86(CX86_CCR5); if (ccr5 & 2) /* reset SLOP if needed, old BIOS do this wrong */ setCx86(CX86_CCR5, ccr5 & 0xfd); diff -u --recursive --new-file v2.1.115/linux/include/asm-i386/current.h linux/include/asm-i386/current.h --- v2.1.115/linux/include/asm-i386/current.h Thu May 14 19:47:43 1998 +++ linux/include/asm-i386/current.h Fri Aug 14 16:35:22 1998 @@ -1,6 +1,8 @@ #ifndef _I386_CURRENT_H #define _I386_CURRENT_H +struct task_struct; + static inline struct task_struct * get_current(void) { struct task_struct *current; diff -u --recursive --new-file v2.1.115/linux/include/asm-i386/pgtable.h linux/include/asm-i386/pgtable.h --- v2.1.115/linux/include/asm-i386/pgtable.h Thu Aug 6 14:06:33 1998 +++ linux/include/asm-i386/pgtable.h Tue Aug 18 17:48:06 1998 @@ -100,7 +100,8 @@ static inline void flush_tlb_current_task(void) { - if (current->mm->count == 1) /* just one copy of this mm */ + /* just one copy of this mm? */ + if (atomic_read(¤t->mm->count) == 1) local_flush_tlb(); /* and that's us, so.. */ else smp_flush_tlb(); @@ -112,7 +113,7 @@ static inline void flush_tlb_mm(struct mm_struct * mm) { - if (mm == current->mm && mm->count == 1) + if (mm == current->mm && atomic_read(&mm->count) == 1) local_flush_tlb(); else smp_flush_tlb(); @@ -121,7 +122,7 @@ static inline void flush_tlb_page(struct vm_area_struct * vma, unsigned long va) { - if (vma->vm_mm == current->mm && current->mm->count == 1) + if (vma->vm_mm == current->mm && atomic_read(¤t->mm->count) == 1) __flush_tlb_one(va); else smp_flush_tlb(); diff -u --recursive --new-file v2.1.115/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h --- v2.1.115/linux/include/asm-i386/processor.h Tue Jul 21 00:15:33 1998 +++ linux/include/asm-i386/processor.h Mon Aug 10 09:12:56 1998 @@ -127,22 +127,12 @@ * Cyrix CPU indexed register access macros */ -extern inline unsigned char getCx86(unsigned char reg) -{ - unsigned char data; +#define getCx86(reg) ({ outb((reg), 0x22); inb(0x23); }) - __asm__ __volatile__("movb %1,%%al\n\t" - "outb %%al,$0x22\n\t" - "inb $0x23,%%al" : "=a" (data) : "q" (reg)); - return data; -} - -extern inline void setCx86(unsigned char reg, unsigned char data) -{ - __asm__ __volatile__("outb %%al,$0x22\n\t" - "movb %1,%%al\n\t" - "outb %%al,$0x23" : : "a" (reg), "q" (data)); -} +#define setCx86(reg, data) do { \ + outb((reg), 0x22); \ + outb((data), 0x23); \ +} while (0) /* * Bus types (default is ISA, but people can check others with these..) diff -u --recursive --new-file v2.1.115/linux/include/asm-i386/system.h linux/include/asm-i386/system.h --- v2.1.115/linux/include/asm-i386/system.h Thu Jul 16 18:09:29 1998 +++ linux/include/asm-i386/system.h Thu Aug 13 10:11:23 1998 @@ -36,6 +36,8 @@ :"=a" (n) \ :"0" (0),"i" (FIRST_TSS_ENTRY<<3)) +#ifdef __KERNEL__ + struct task_struct; /* one of the stranger aspects of C forward declarations.. */ extern void FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next)); @@ -109,15 +111,26 @@ #define get_base(ldt) _get_base( ((char *)&(ldt)) ) -static inline unsigned long get_limit(unsigned long segment) -{ - unsigned long __limit; - __asm__("lsll %1,%0" - :"=r" (__limit):"r" (segment)); - return __limit+1; -} - -#define nop() __asm__ __volatile__ ("nop") +/* + * Load a segment. Fall back on loading the zero + * segment if something goes wrong.. + */ +#define loadsegment(seg,value) \ + asm volatile("\n" \ + "1:\t" \ + "movl %0,%%" #seg "\n" \ + "2:\n" \ + ".section fixup,\"ax\"\n" \ + "3:\t" \ + "pushl $0\n\t" \ + "popl %%" #seg "\n\t" \ + "jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n\t" \ + ".align 4\n\t" \ + ".long 1b,3b\n" \ + ".previous" \ + : :"m" (*(unsigned int *)&(value))) /* * Clear and set 'TS' bit respectively @@ -132,6 +145,17 @@ : /* no inputs */ \ :"ax") +#endif /* __KERNEL__ */ + +static inline unsigned long get_limit(unsigned long segment) +{ + unsigned long __limit; + __asm__("lsll %1,%0" + :"=r" (__limit):"r" (segment)); + return __limit+1; +} + +#define nop() __asm__ __volatile__ ("nop") #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) #define tas(ptr) (xchg((ptr),1)) diff -u --recursive --new-file v2.1.115/linux/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h --- v2.1.115/linux/include/asm-i386/unistd.h Thu Aug 6 14:06:33 1998 +++ linux/include/asm-i386/unistd.h Sun Aug 9 12:25:12 1998 @@ -27,7 +27,7 @@ #define __NR_lseek 19 #define __NR_getpid 20 #define __NR_mount 21 -#define __NR_umount 22 +#define __NR_oldumount 22 #define __NR_setuid 23 #define __NR_getuid 24 #define __NR_stime 25 @@ -57,7 +57,7 @@ #define __NR_geteuid 49 #define __NR_getegid 50 #define __NR_acct 51 -#define __NR_phys 52 +#define __NR_umount 52 #define __NR_lock 53 #define __NR_ioctl 54 #define __NR_fcntl 55 diff -u --recursive --new-file v2.1.115/linux/include/asm-m68k/bitops.h linux/include/asm-m68k/bitops.h --- v2.1.115/linux/include/asm-m68k/bitops.h Mon Aug 3 12:45:47 1998 +++ linux/include/asm-m68k/bitops.h Mon Aug 10 11:02:24 1998 @@ -218,23 +218,6 @@ * differs in spirit from the above ffz (man ffs). */ -#define ffs(x) generic_ffs(x) - -/* - * hweightN: returns the hamming weight (i.e. the number - * of bits set) of a N-bit word - */ - -#define hweight32(x) generic_hweight32(x) -#define hweight16(x) generic_hweight16(x) -#define hweight8(x) generic_hweight8(x) - -/* - * ffs: find first bit set. This is defined the same way as - * the libc and compiler builtin ffs routines, therefore - * differs in spirit from the above ffz (man ffs). - */ - extern __inline__ int ffs(int x) { int cnt; diff -u --recursive --new-file v2.1.115/linux/include/asm-m68k/bootinfo.h linux/include/asm-m68k/bootinfo.h --- v2.1.115/linux/include/asm-m68k/bootinfo.h Tue Jun 23 10:01:28 1998 +++ linux/include/asm-m68k/bootinfo.h Mon Aug 10 11:02:24 1998 @@ -262,10 +262,6 @@ #ifndef __ASSEMBLY__ -#define MACHW_DECLARE(name) unsigned name : 1 -#define MACHW_SET(name) (boot_info.bi_mac.hw_present.name = 1) -#define MACHW_PRESENT(name) (boot_info.bi_mac.hw_present.name) - struct compat_bi_Macintosh { unsigned long videoaddr; @@ -290,25 +286,6 @@ unsigned long rombase; unsigned long adbdelay; unsigned long timedbra; - struct { - /* video hardware */ - /* sound hardware */ - /* disk storage interfaces */ - MACHW_DECLARE(MAC_SCSI); /* Directly mapped NCR5380 */ - MACHW_DECLARE(IDE); /* IDE Interface */ - /* other I/O hardware */ - MACHW_DECLARE(SCC); /* Serial Communications Contr. */ - /* DMA */ - MACHW_DECLARE(SCSI_DMA); /* DMA for the NCR5380 */ - /* real time clocks */ - MACHW_DECLARE(RTC_CLK); /* clock chip */ - /* supporting hardware */ - MACHW_DECLARE(VIA1); /* Versatile Interface Ad. 1 */ - MACHW_DECLARE(VIA2); /* Versatile Interface Ad. 2 */ - MACHW_DECLARE(RBV); /* Versatile Interface Ad. 2+ */ - /* NUBUS */ - MACHW_DECLARE(NUBUS); /* NUBUS */ - } hw_present; }; #else diff -u --recursive --new-file v2.1.115/linux/include/asm-m68k/keyboard.h linux/include/asm-m68k/keyboard.h --- v2.1.115/linux/include/asm-m68k/keyboard.h Mon Feb 23 18:12:11 1998 +++ linux/include/asm-m68k/keyboard.h Mon Aug 10 11:02:24 1998 @@ -24,7 +24,7 @@ static __inline__ int kbd_getkeycode(unsigned int scancode) { - return -EOPNOTSUPP; + return scancode > 127 ? -EINVAL : scancode; } static __inline__ int kbd_pretranslate(unsigned char scancode, char raw_mode) diff -u --recursive --new-file v2.1.115/linux/include/asm-m68k/machw.h linux/include/asm-m68k/machw.h --- v2.1.115/linux/include/asm-m68k/machw.h Tue Jun 23 10:01:28 1998 +++ linux/include/asm-m68k/machw.h Mon Aug 10 11:02:24 1998 @@ -99,7 +99,7 @@ # define via_1 ((*(volatile struct VIA *)VIA1_BAS)) # define via_2 ((*(volatile struct VIA *)VIA2_BAS)) -# define via1_regp ((volatile unsigned char *)VIA1_BAS) +# define via1_regp ((volatile unsigned char *)VIA1_BAS) /* * OSS/RBV base address @@ -111,5 +111,36 @@ /* move to oss.h?? */ #define nIFR 0x203 #define oIFR 0x202 + + +/* hardware stuff */ + +#define MACHW_DECLARE(name) unsigned name : 1 +#define MACHW_SET(name) (mac_hw_present.name = 1) +#define MACHW_PRESENT(name) (mac_hw_present.name) + +struct { + /* video hardware */ + /* sound hardware */ + /* disk storage interfaces */ + MACHW_DECLARE(MAC_SCSI_80); /* Directly mapped NCR5380 */ + MACHW_DECLARE(MAC_SCSI_96); /* 53c9[46] */ + MACHW_DECLARE(MAC_SCSI_96_2); /* 2nd 53c9[46] Q900 and Q950 */ + MACHW_DECLARE(IDE); /* IDE Interface */ + /* other I/O hardware */ + MACHW_DECLARE(SCC); /* Serial Communications Contr. */ + /* DMA */ + MACHW_DECLARE(SCSI_DMA); /* DMA for the NCR5380 */ + /* real time clocks */ + MACHW_DECLARE(RTC_CLK); /* clock chip */ + /* supporting hardware */ + MACHW_DECLARE(VIA1); /* Versatile Interface Ad. 1 */ + MACHW_DECLARE(VIA2); /* Versatile Interface Ad. 2 */ + MACHW_DECLARE(RBV); /* Versatile Interface Ad. 2+ */ + /* NUBUS */ + MACHW_DECLARE(NUBUS); /* NUBUS */ +} mac_hw_present; + +/* extern struct mac_hw_present mac_hw_present; */ #endif /* linux/machw.h */ diff -u --recursive --new-file v2.1.115/linux/include/asm-m68k/pgtable.h linux/include/asm-m68k/pgtable.h --- v2.1.115/linux/include/asm-m68k/pgtable.h Thu Aug 6 14:06:33 1998 +++ linux/include/asm-m68k/pgtable.h Mon Aug 10 11:02:24 1998 @@ -852,4 +852,7 @@ #define module_map vmalloc #define module_unmap vfree +/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ +#define PageSkip(page) (0) + #endif /* _M68K_PGTABLE_H */ diff -u --recursive --new-file v2.1.115/linux/include/asm-m68k/posix_types.h linux/include/asm-m68k/posix_types.h --- v2.1.115/linux/include/asm-m68k/posix_types.h Mon Dec 8 23:58:04 1997 +++ linux/include/asm-m68k/posix_types.h Mon Aug 10 11:02:24 1998 @@ -37,6 +37,8 @@ #endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */ } __kernel_fsid_t; +#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) + #undef __FD_SET #define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d)) @@ -48,5 +50,7 @@ #undef __FD_ZERO #define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp))) + +#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ #endif diff -u --recursive --new-file v2.1.115/linux/include/asm-m68k/softirq.h linux/include/asm-m68k/softirq.h --- v2.1.115/linux/include/asm-m68k/softirq.h Tue Feb 17 13:12:49 1998 +++ linux/include/asm-m68k/softirq.h Mon Aug 10 11:02:24 1998 @@ -61,5 +61,6 @@ /* These are for the irq's testing the lock */ #define softirq_trylock(cpu) (local_bh_count[cpu] ? 0 : (local_bh_count[cpu]=1)) #define softirq_endlock(cpu) (local_bh_count[cpu] = 0) +#define synchronize_bh() do { } while (0) #endif diff -u --recursive --new-file v2.1.115/linux/include/asm-m68k/uaccess.h linux/include/asm-m68k/uaccess.h --- v2.1.115/linux/include/asm-m68k/uaccess.h Wed Apr 23 19:01:28 1997 +++ linux/include/asm-m68k/uaccess.h Mon Aug 10 11:02:25 1998 @@ -200,6 +200,7 @@ "5:\n" ".section .fixup,\"ax\"\n" " .even\n" + "60:addql #1,%2\n" "6: lsll #2,%2\n" " addl %4,%2\n" " jra 5b\n" @@ -210,9 +211,11 @@ ".previous\n" ".section __ex_table,\"a\"\n" " .align 4\n" + " .long 1b,60b\n" " .long 22b,6b\n" " .long 2b,6b\n" " .long 24b,7b\n" + " .long 3b,60b\n" " .long 4b,7b\n" " .long 25b,8b\n" " .long 5b,8b\n" @@ -458,16 +461,20 @@ "31: movesl %%d0,(%0)+\n" \ "11: subql #1,%2\n" \ " jne 10b\n" \ + "41:\n" \ ".section .fixup,\"ax\"\n" \ " .even\n" \ + "22: addql #1,%2\n" \ "12: lsll #2,%2\n" \ fixup "\n" \ " jra 13f\n" \ ".previous\n" \ ".section __ex_table,\"a\"\n" \ " .align 4\n" \ + " .long 10b,22b\n" \ " .long 31b,12b\n" \ " .long 11b,12b\n" \ + " .long 41b,22b\n" \ ".previous\n" \ copy "\n" \ "13:" \ @@ -803,6 +810,7 @@ "5:\n" ".section .fixup,\"ax\"\n" " .even\n" + "61:addql #1,%1\n" "6: lsll #2,%1\n" " addl %2,%1\n" " jra 5b\n" @@ -813,8 +821,9 @@ ".previous\n" ".section __ex_table,\"a\"\n" " .align 4\n" - " .long 1b,6b\n" + " .long 1b,61b\n" " .long 2b,6b\n" + " .long 3b,61b\n" " .long 24b,7b\n" " .long 4b,7b\n" " .long 25b,8b\n" diff -u --recursive --new-file v2.1.115/linux/include/asm-m68k/unistd.h linux/include/asm-m68k/unistd.h --- v2.1.115/linux/include/asm-m68k/unistd.h Mon Aug 3 12:45:47 1998 +++ linux/include/asm-m68k/unistd.h Mon Aug 10 11:02:25 1998 @@ -27,7 +27,7 @@ #define __NR_lseek 19 #define __NR_getpid 20 #define __NR_mount 21 -#define __NR_umount 22 +#define __NR_oldumount 22 #define __NR_setuid 23 #define __NR_getuid 24 #define __NR_stime 25 @@ -57,7 +57,7 @@ #define __NR_geteuid 49 #define __NR_getegid 50 #define __NR_acct 51 -#define __NR_phys 52 +#define __NR_umount 52 #define __NR_lock 53 #define __NR_ioctl 54 #define __NR_fcntl 55 @@ -191,6 +191,9 @@ #define __NR_capget 184 #define __NR_capset 185 #define __NR_sigaltstack 186 +#define __NR_sendfile 187 +#define __NR_streams1 188 /* some people actually want it */ +#define __NR_streams2 189 /* some people actually want it */ /* user-visible error numbers are in the range -1 - -122: see */ diff -u --recursive --new-file v2.1.115/linux/include/linux/cyclades.h linux/include/linux/cyclades.h --- v2.1.115/linux/include/linux/cyclades.h Thu Aug 6 14:06:34 1998 +++ linux/include/linux/cyclades.h Mon Aug 10 22:01:16 1998 @@ -1,4 +1,4 @@ -/* $Revision: 2.5 $$Date: 1998/08/03 16:57:01 $ +/* $Revision: 2.6 $$Date: 1998/08/10 16:57:01 $ * linux/include/linux/cyclades.h * * This file is maintained by Ivan Passos , @@ -492,7 +492,7 @@ long base_addr; long ctl_addr; int irq; - int num_chips; /* 0 if card absent, 1 if Z/PCI, else Y */ + int num_chips; /* 0 if card absent, -1 if Z/PCI, else Y */ int first_line; /* minor number of first channel on card */ int bus_index; /* address shift - 0 for ISA, 1 for PCI */ int inact_ctrl; /* FW Inactivity control - 0 disabled, 1 enabled */ diff -u --recursive --new-file v2.1.115/linux/include/linux/dcache.h linux/include/linux/dcache.h --- v2.1.115/linux/include/linux/dcache.h Sun Jul 26 11:57:19 1998 +++ linux/include/linux/dcache.h Tue Aug 11 13:47:02 1998 @@ -50,6 +50,8 @@ return end_name_hash(hash); } +#define DNAME_INLINE_LEN 16 + struct dentry { int d_count; unsigned int d_flags; @@ -68,6 +70,7 @@ struct super_block * d_sb; /* The root of the dentry tree */ unsigned long d_reftime; /* last time referenced */ void * d_fsdata; /* fs-specific data */ + unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */ }; struct dentry_operations { @@ -112,6 +115,11 @@ { list_del(&dentry->d_hash); INIT_LIST_HEAD(&dentry->d_hash); +} + +static __inline__ int dname_external(struct dentry *d) +{ + return d->d_name.name != d->d_iname; } /* diff -u --recursive --new-file v2.1.115/linux/include/linux/genhd.h linux/include/linux/genhd.h --- v2.1.115/linux/include/linux/genhd.h Mon Jan 5 00:22:44 1998 +++ linux/include/linux/genhd.h Sun Aug 9 10:42:41 1998 @@ -26,6 +26,7 @@ #define DOS_EXTENDED_PARTITION 5 #define LINUX_EXTENDED_PARTITION 0x85 #define WIN98_EXTENDED_PARTITION 0x0f + #define LINUX_SWAP_PARTITION 0x82 #ifdef CONFIG_SOLARIS_X86_PARTITION diff -u --recursive --new-file v2.1.115/linux/include/linux/if_shaper.h linux/include/linux/if_shaper.h --- v2.1.115/linux/include/linux/if_shaper.h Tue Mar 10 10:03:35 1998 +++ linux/include/linux/if_shaper.h Sun Aug 9 12:27:53 1998 @@ -18,6 +18,7 @@ { struct sk_buff_head sendq; __u32 bytespertick; + __u32 bitspersec; __u32 shapelatency; __u32 shapeclock; __u32 recovery; /* Time we can next clock a packet out on @@ -44,6 +45,8 @@ #define SHAPER_SET_DEV 0x0001 #define SHAPER_SET_SPEED 0x0002 +#define SHAPER_GET_DEV 0x0003 +#define SHAPER_GET_SPEED 0x0004 struct shaperconf { diff -u --recursive --new-file v2.1.115/linux/include/linux/if_wic.h linux/include/linux/if_wic.h --- v2.1.115/linux/include/linux/if_wic.h Thu Apr 11 23:49:46 1996 +++ linux/include/linux/if_wic.h Wed Dec 31 16:00:00 1969 @@ -1,102 +0,0 @@ -#ifndef _LINUX_IF_WIC_H -#define _LINUX_IF_WIC_H - -#include - -#define SIOCDEVWIC SIOCDEVPRIVATE - -struct wicconf -{ - unsigned char pcmd; - unsigned char data[120]; - unsigned char len; -}; - -/* WIC host to controller commands */ - -#define WIC_AYT 0x10 /* test dki */ -#define WIC_RESET 0x11 /* reset controller */ -#define WIC_SETSN 0x21 /* set station name */ -#define WIC_SETPS 0x22 /* set power saving mode */ -#define WIC_SETAF 0x23 /* set announce filter */ -#define WIC_SETGPF 0x24 /* set GPSP filter */ -#define WIC_GETVERH 0x61 /* get interface controller version */ -#define WIC_GETNL 0x62 /* get neighbor list */ -#define WIC_GETSN 0x65 /* get station name */ -#define WIC_CLRSTATS 0x83 /* clear controller statistics */ -#define WIC_SETNET 0x84 /* set network configuration */ -#define WIC_SETSYS 0x85 /* set system configuration */ -#define WIC_GETSTATS 0xc1 /* get statistics */ -#define WIC_GETVERM 0xc3 /* get MAC version */ -#define WIC_GETNET 0xc4 /* get network configuration */ -#define WIC_GETSYS 0xc5 /* get system configuration */ - -/* - * structure used for the GETNET/SETNET command - */ - -struct wic_net { - unsigned char ula[6]; /* ula of interface */ - unsigned char mode; /* operating mode */ -#define NET_MODE_ME 0x01 /* receive my ula */ -#define NET_MODE_BCAST 0x02 /* receive bcasts */ -#define NET_MODE_MCAST 0x04 /* receive mcasts */ -#define NET_MODE_PROM 0x08 /* promiscuous */ -#define NET_MODE_HC 0x10 /* is a hop coordinator */ -#define NET_MODE_HC_VALID 0x20 /* hc address is valid */ -#define NET_MODE_HCAP 0x40 /* hc is also ap */ -#define NET_MODE_HC_KNOWN 0x80 /* hc is known */ - unsigned char rts_lo; /* rts threshold */ - unsigned char rts_hi; /* rts threshold */ - unsigned char retry; /* retry limit */ - unsigned char hc_ula[6]; /* ula of hc */ - unsigned char key[4]; /* network key */ - unsigned char dsl; /* direct send limit */ - unsigned char res1; /* reserved */ -}; - -/* - * structure used for the GETSYS/SETSYS command - */ - -struct wic_sys { - unsigned char mode; /* set operating mode */ -#define SYS_MODE_ANT_DIV 0x00 /* use antenna diversity */ -#define SYS_MODE_ANT_1 0x01 /* use ant 1 for tx */ -#define SYS_MODE_ANT_2 0x02 /* use ant 2 for tx */ -#define SYS_MODE_HC_LOCK 0x04 /* lock onto current hc */ -#define SYS_MODE_DEBUG 0x08 /* upload failed frames */ -#define SYS_MODE_IAM_AP 0x10 /* I am AP */ -#define SYS_MODE_IAM_HC 0x20 /* I am HC */ -#define SYS_MODE_USE_SKIP 0x40 /* use skipping mechanism */ -#define SYS_MODE_AUTO 0x80 /* station is in auto mode */ - unsigned char switches; /* radio/controller switches */ -#define SYS_SWITCH_STDBY 0x01 /* switch radio to standby */ -#define SYS_SWITCH_TXRX 0x02 /* 1 = tx, manual mode only */ -#define SYS_SWITCH_PA 0x04 /* 1 = enable PA on radio */ -#define SYS_SWITCH_PWR 0x10 /* 1 = hi, 0 = lo power output */ -#define SYS_SWITCH_RES1 0x20 /* reserved, must be 0 */ -#define SYS_SWITCH_LIGHTS 0x40 /* light for tx & rx */ -#define SYS_SWITCH_LIGHTS_HC 0x80 /* light for rx while coordinated */ - unsigned char hop_min; /* hop range */ - unsigned char hop_max; /* hop range */ - unsigned char pre_len; /* preamble length (bytes) */ - unsigned char pre_match; /* valid preamble match (bytes) */ - unsigned char mod; /* data mod: 1 = 8:1, 0 = none */ - unsigned char cca_mode; /* cca flags */ -#define CCA_PKT_DET_BSY 0x01 /* busy if packet is detected */ -#define CCA_VIRT_CARR 0x02 /* use virtual carrier */ -#define CCA_RSSI_BSY 0x04 /* busy if rssi > threshold */ -#define CCA_DATA_BSY 0x08 /* busy if valid data > XXX usec */ - unsigned char dwell_hi; /* dwell time */ - unsigned char dwell_lo; /* dwell time */ - unsigned char hc_timeout; /* HC timeout */ - unsigned char rssi; /* rssi threshold */ - unsigned char hc_rssi; /* rssi of last hc frame */ - unsigned char hc_rssi_chan; /* channel of hc rssi value */ -}; - - -#endif /* _LINUX_IF_WIC_H */ - - diff -u --recursive --new-file v2.1.115/linux/include/linux/mm.h linux/include/linux/mm.h --- v2.1.115/linux/include/linux/mm.h Thu Aug 6 14:06:34 1998 +++ linux/include/linux/mm.h Tue Aug 18 17:51:32 1998 @@ -258,6 +258,7 @@ * Decide if we should try to do some swapout.. */ extern int free_memory_available(void); +extern struct wait_queue * kswapd_wait; #define free_page(addr) free_pages((addr),0) extern void FASTCALL(free_pages(unsigned long addr, unsigned long order)); @@ -312,8 +313,7 @@ * GFP bitmasks.. */ #define __GFP_WAIT 0x01 -#define __GFP_IO 0x02 -#define __GFP_LOW 0x00 +#define __GFP_LOW 0x02 #define __GFP_MED 0x04 #define __GFP_HIGH 0x08 @@ -321,9 +321,9 @@ #define GFP_BUFFER (__GFP_LOW | __GFP_WAIT) #define GFP_ATOMIC (__GFP_HIGH) -#define GFP_USER (__GFP_LOW | __GFP_WAIT | __GFP_IO) -#define GFP_KERNEL (__GFP_MED | __GFP_WAIT | __GFP_IO) -#define GFP_NFS (__GFP_HIGH | __GFP_WAIT | __GFP_IO) +#define GFP_USER (__GFP_LOW | __GFP_WAIT) +#define GFP_KERNEL (__GFP_MED | __GFP_WAIT) +#define GFP_NFS (__GFP_HIGH | __GFP_WAIT) /* Flag - indicates that the buffer will be suitable for DMA. Ignored on some platforms, used as appropriate on others */ diff -u --recursive --new-file v2.1.115/linux/include/linux/mount.h linux/include/linux/mount.h --- v2.1.115/linux/include/linux/mount.h Fri May 8 23:14:56 1998 +++ linux/include/linux/mount.h Sun Aug 9 12:25:12 1998 @@ -37,4 +37,10 @@ struct vfsmount *lookup_vfsmnt(kdev_t dev); +/* + * Umount options + */ + +#define MNT_FORCE 0x00000001 /* Attempt to forcibily umount */ + #endif /* _LINUX_MOUNT_H */ diff -u --recursive --new-file v2.1.115/linux/include/linux/nbd.h linux/include/linux/nbd.h --- v2.1.115/linux/include/linux/nbd.h Sat Nov 29 10:33:21 1997 +++ linux/include/linux/nbd.h Sun Aug 16 12:09:04 1998 @@ -1,16 +1,13 @@ #ifndef LINUX_NBD_H #define LINUX_NBD_H -#include -#include - -#define NBD_SET_SOCK _IO( 0xab, 0 ) -#define NBD_SET_BLKSIZE _IO( 0xab, 1 ) -#define NBD_SET_SIZE _IO( 0xab, 2 ) -#define NBD_DO_IT _IO( 0xab, 3 ) -#define NBD_CLEAR_SOCK _IO( 0xab, 4 ) -#define NBD_CLEAR_QUE _IO( 0xab, 5 ) -#define NBD_PRINT_DEBUG _IO( 0xab, 6 ) +#define NBD_SET_SOCK _IO( 0xab, 0 ) +#define NBD_SET_BLKSIZE _IO( 0xab, 1 ) +#define NBD_SET_SIZE _IO( 0xab, 2 ) +#define NBD_DO_IT _IO( 0xab, 3 ) +#define NBD_CLEAR_SOCK _IO( 0xab, 4 ) +#define NBD_CLEAR_QUE _IO( 0xab, 5 ) +#define NBD_PRINT_DEBUG _IO( 0xab, 6 ) #ifdef MAJOR_NR @@ -54,21 +51,23 @@ /* This now IS in some kind of include file... */ -#define NBD_REQUEST_MAGIC 0x12560953 -#define NBD_REPLY_MAGIC 0x96744668 -#define LO_MAGIC 0x68797548 +/* These are send over network in request/reply magic field */ + +#define NBD_REQUEST_MAGIC 0x25609513 +#define NBD_REPLY_MAGIC 0x67446698 +/* Do *not* use magics: 0x12560953 0x96744668. */ struct nbd_request { - __u32 magic; - __u32 from; - __u32 len; + u32 magic; + u32 type; /* == READ || == WRITE */ char handle[8]; - __u32 type; /* == READ || == WRITE */ + u64 from; + u32 len; }; struct nbd_reply { - __u32 magic; + u32 magic; + u32 error; /* 0 = ok, else error */ char handle[8]; /* handle you got from request */ - __u32 error; /* 0 = ok, else error */ }; #endif diff -u --recursive --new-file v2.1.115/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h --- v2.1.115/linux/include/linux/proc_fs.h Mon Aug 3 12:45:47 1998 +++ linux/include/linux/proc_fs.h Tue Aug 18 17:51:34 1998 @@ -31,6 +31,7 @@ PROC_MODULES, PROC_STAT, PROC_DEVICES, + PROC_PARTITIONS, PROC_INTERRUPTS, PROC_FILESYSTEMS, PROC_KSYMS, diff -u --recursive --new-file v2.1.115/linux/include/linux/sched.h linux/include/linux/sched.h --- v2.1.115/linux/include/linux/sched.h Thu Aug 6 14:06:34 1998 +++ linux/include/linux/sched.h Tue Aug 18 17:51:32 1998 @@ -127,7 +127,7 @@ * Open file table structure */ struct files_struct { - int count; + atomic_t count; int max_fds; struct file ** fd; /* current fd array */ fd_set close_on_exec; @@ -135,7 +135,7 @@ }; #define INIT_FILES { \ - 1, \ + ATOMIC_INIT(1), \ NR_OPEN, \ &init_fd_array[0], \ { { 0, } }, \ @@ -143,13 +143,13 @@ } struct fs_struct { - int count; + atomic_t count; int umask; struct dentry * root, * pwd; }; #define INIT_FS { \ - 1, \ + ATOMIC_INIT(1), \ 0022, \ NULL, NULL \ } @@ -160,7 +160,8 @@ struct mm_struct { struct vm_area_struct *mmap, *mmap_cache; pgd_t * pgd; - int count, map_count; + atomic_t count; + int map_count; struct semaphore mmap_sem; unsigned long context; unsigned long start_code, end_code, start_data, end_data; @@ -177,7 +178,8 @@ }; #define INIT_MM { \ - &init_mmap, NULL, swapper_pg_dir, 1, 1, \ + &init_mmap, NULL, swapper_pg_dir, \ + ATOMIC_INIT(1), 1, \ MUTEX, \ 0, \ 0, 0, 0, 0, \ @@ -198,6 +200,13 @@ { {{0,}}, }, \ SPIN_LOCK_UNLOCKED } +/* + * Some day this will be a full-fledged user tracking system.. + * Right now it is only used to track how many processes a + * user has, but it has the potential to track memory usage etc. + */ +struct user_struct; + struct task_struct { /* these are hardcoded - don't touch */ volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ @@ -270,6 +279,7 @@ int ngroups; gid_t groups[NGROUPS]; kernel_cap_t cap_effective, cap_inheritable, cap_permitted; + struct user_struct *user; /* limits */ struct rlimit rlim[RLIM_NLIMITS]; unsigned short used_math; @@ -310,6 +320,7 @@ #define PF_SUPERPRIV 0x00000100 /* used super-user privileges */ #define PF_DUMPCORE 0x00000200 /* dumped core */ #define PF_SIGNALED 0x00000400 /* killed by a signal */ +#define PF_MEMALLOC 0x00000800 /* Allocating memory */ #define PF_USEDFPU 0x00100000 /* task used FPU this quantum (SMP) */ #define PF_DTRACE 0x00200000 /* delayed trace (used on m68k) */ @@ -348,6 +359,7 @@ /* uid etc */ 0,0,0,0,0,0,0,0, \ /* suppl grps*/ 0, {0,}, \ /* caps */ CAP_INIT_EFF_SET,CAP_INIT_INH_SET,CAP_FULL_SET, \ +/* user */ NULL, \ /* rlimits */ INIT_RLIMITS, \ /* math */ 0, \ /* comm */ "swapper", \ @@ -427,7 +439,8 @@ } /* per-UID process charging. */ -extern int charge_uid(struct task_struct *p, int count); +extern int alloc_uid(struct task_struct *p); +void free_uid(struct task_struct *p); #include @@ -587,7 +600,7 @@ extern struct mm_struct * mm_alloc(void); static inline void mmget(struct mm_struct * mm) { - mm->count++; + atomic_inc(&mm->count); } extern void mmput(struct mm_struct *); diff -u --recursive --new-file v2.1.115/linux/include/linux/sunrpc/clnt.h linux/include/linux/sunrpc/clnt.h --- v2.1.115/linux/include/linux/sunrpc/clnt.h Fri Jul 31 17:09:54 1998 +++ linux/include/linux/sunrpc/clnt.h Tue Aug 18 17:48:58 1998 @@ -127,6 +127,9 @@ xprt_set_timeout(&clnt->cl_timeout, retr, incr); } +extern void rpciod_tcp_dispatcher(void); +extern void rpciod_wake_up(void); + /* * Helper function for NFSroot support */ diff -u --recursive --new-file v2.1.115/linux/include/linux/videodev.h linux/include/linux/videodev.h --- v2.1.115/linux/include/linux/videodev.h Sun Jul 26 11:57:19 1998 +++ linux/include/linux/videodev.h Sun Aug 9 12:18:38 1998 @@ -3,6 +3,8 @@ #ifdef __KERNEL__ +#include + struct video_device { char name[32]; @@ -14,6 +16,7 @@ long (*read)(struct video_device *, char *, unsigned long, int noblock); /* Do we need a write method ? */ long (*write)(struct video_device *, const char *, unsigned long, int noblock); + unsigned int (*poll)(struct video_device *, struct file *, poll_table *); int (*ioctl)(struct video_device *, unsigned int , void *); int (*mmap)(struct video_device *, const char *, unsigned long); int (*initialize)(struct video_device *); @@ -109,6 +112,10 @@ #define VIDEO_PALETTE_YUYV 8 #define VIDEO_PALETTE_UYVY 9 /* The great thing about standards is ... */ #define VIDEO_PALETTE_YUV420 10 +#define VIDEO_PALETTE_YUV411 11 /* YUV411 capture */ +#define VIDEO_PALETTE_RAW 12 /* RAW capture (BT848) */ +#define VIDEO_PALETTE_YUV422P 13 /* YUV 4:2:2 Planar */ +#define VIDEO_PALETTE_YUV411P 14 /* YUV 4:1:1 Planar */ }; struct video_audio @@ -160,7 +167,7 @@ { unsigned int frame; /* Frame (0 or 1) for double buffer */ int height,width; - unsigned int format; + unsigned int format; /* should be VIDEO_PALETTE_* */ }; struct video_key @@ -205,6 +212,7 @@ #define VID_HARDWARE_ZOLTRIX 10 #define VID_HARDWARE_SAA7146 11 #define VID_HARDWARE_VIDEUM 12 /* Reserved for Winnov videum */ +#define VID_HARDWARE_RTRACK2 13 /* * Initialiser list diff -u --recursive --new-file v2.1.115/linux/ipc/msg.c linux/ipc/msg.c --- v2.1.115/linux/ipc/msg.c Thu May 7 22:51:55 1998 +++ linux/ipc/msg.c Sat Aug 15 22:36:25 1998 @@ -1,6 +1,13 @@ /* * linux/ipc/msg.c * Copyright (C) 1992 Krishna Balasubramanian + * + * Removed all the remaining kerneld mess + * Catch the -EFAULT stuff properly + * Use GFP_KERNEL for messages as in 1.2 + * Fixed up the unchecked user space derefs + * Copyright (C) 1998 Alan Cox & Andi Kleen + * */ #include @@ -29,7 +36,7 @@ static int max_msqid = 0; static struct wait_queue *msg_lock = NULL; -__initfunc(void msg_init (void)) +void __init msg_init (void) { int id; @@ -42,21 +49,16 @@ static int real_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg) { - int id, err; + int id; struct msqid_ds *msq; struct ipc_perm *ipcp; struct msg *msgh; long mtype; - unsigned long flags; if (msgsz > MSGMAX || (long) msgsz < 0 || msqid < 0) return -EINVAL; - if (!msgp) - return -EFAULT; - err = verify_area (VERIFY_READ, msgp->mtext, msgsz); - if (err) - return err; - get_user(mtype, &msgp->mtype); + if (get_user(mtype, &msgp->mtype)) + return -EFAULT; if (mtype < 1) return -EINVAL; id = (unsigned int) msqid % MSGMNI; @@ -85,12 +87,16 @@ } /* allocate message header and text space*/ - msgh = (struct msg *) kmalloc (sizeof(*msgh) + msgsz, GFP_ATOMIC); + msgh = (struct msg *) kmalloc (sizeof(*msgh) + msgsz, GFP_KERNEL); if (!msgh) return -ENOMEM; msgh->msg_spot = (char *) (msgh + 1); - copy_from_user (msgh->msg_spot, msgp->mtext, msgsz); + if (copy_from_user(msgh->msg_spot, msgp->mtext, msgsz)) + { + kfree(msgh); + return -EFAULT; + } if (msgque[id] == IPC_UNUSED || msgque[id] == IPC_NOID || msq->msg_perm.seq != (unsigned int) msqid / MSGMNI) { @@ -103,8 +109,6 @@ msgh->msg_type = mtype; msgh->msg_stime = CURRENT_TIME; - save_flags(flags); - cli(); if (!msq->msg_first) msq->msg_first = msq->msg_last = msgh; else { @@ -117,7 +121,6 @@ msq->msg_qnum++; msq->msg_lspid = current->pid; msq->msg_stime = CURRENT_TIME; - restore_flags(flags); wake_up (&msq->rwait); return 0; } @@ -128,17 +131,10 @@ struct ipc_perm *ipcp; struct msg *tmsg, *leastp = NULL; struct msg *nmsg = NULL; - int id, err; - unsigned long flags; + int id; if (msqid < 0 || (long) msgsz < 0) return -EINVAL; - if (!msgp || !msgp->mtext) - return -EFAULT; - - err = verify_area (VERIFY_WRITE, msgp->mtext, msgsz); - if (err) - return err; id = (unsigned int) msqid % MSGMNI; msq = msgque [id]; @@ -160,8 +156,6 @@ return -EACCES; } - save_flags(flags); - cli(); if (msgtyp == 0) nmsg = msq->msg_first; else if (msgtyp > 0) { @@ -186,15 +180,12 @@ if (leastp && leastp->msg_type <= - msgtyp) nmsg = leastp; } - restore_flags(flags); if (nmsg) { /* done finding a message */ if ((msgsz < nmsg->msg_ts) && !(msgflg & MSG_NOERROR)) { return -E2BIG; } msgsz = (msgsz > nmsg->msg_ts)? nmsg->msg_ts : msgsz; - save_flags(flags); - cli(); if (nmsg == msq->msg_first) msq->msg_first = nmsg->msg_next; else { @@ -214,10 +205,10 @@ msgbytes -= nmsg->msg_ts; msghdrs--; msq->msg_cbytes -= nmsg->msg_ts; - restore_flags(flags); wake_up (&msq->wwait); - put_user (nmsg->msg_type, &msgp->mtype); - copy_to_user (msgp->mtext, nmsg->msg_spot, msgsz); + if (put_user (nmsg->msg_type, &msgp->mtype) || + copy_to_user (msgp->mtext, nmsg->msg_spot, msgsz)) + msgsz = -EFAULT; kfree(nmsg); return msgsz; } else { /* did not find a message */ @@ -395,19 +386,16 @@ msginfo.msgmap = msghdrs; msginfo.msgtql = msgbytes; } - err = verify_area (VERIFY_WRITE, buf, sizeof (struct msginfo)); - if (err) - goto out; - copy_to_user (buf, &msginfo, sizeof(struct msginfo)); + + err = -EFAULT; + if (copy_to_user (buf, &msginfo, sizeof(struct msginfo))) + goto out; err = max_msqid; goto out; } case MSG_STAT: if (!buf) goto out; - err = verify_area (VERIFY_WRITE, buf, sizeof (*buf)); - if (err) - goto out; err = -EINVAL; if (msqid > max_msqid) goto out; @@ -427,23 +415,21 @@ tbuf.msg_qbytes = msq->msg_qbytes; tbuf.msg_lspid = msq->msg_lspid; tbuf.msg_lrpid = msq->msg_lrpid; - copy_to_user (buf, &tbuf, sizeof(*buf)); + err = -EFAULT; + if (copy_to_user (buf, &tbuf, sizeof(*buf))) + goto out; err = id; goto out; case IPC_SET: if (!buf) goto out; - err = verify_area (VERIFY_READ, buf, sizeof (*buf)); - if (err) - goto out; - copy_from_user (&tbuf, buf, sizeof (*buf)); + err = -EFAULT; + if (!copy_from_user (&tbuf, buf, sizeof (*buf))) + err = 0; break; case IPC_STAT: if (!buf) goto out; - err = verify_area (VERIFY_WRITE, buf, sizeof(*buf)); - if (err) - goto out; break; } @@ -471,8 +457,9 @@ tbuf.msg_qbytes = msq->msg_qbytes; tbuf.msg_lspid = msq->msg_lspid; tbuf.msg_lrpid = msq->msg_lrpid; - copy_to_user (buf, &tbuf, sizeof (*buf)); - err = 0; + err = -EFAULT; + if (!copy_to_user (buf, &tbuf, sizeof (*buf))) + err = 0; goto out; case IPC_SET: err = -EPERM; diff -u --recursive --new-file v2.1.115/linux/kernel/capability.c linux/kernel/capability.c --- v2.1.115/linux/kernel/capability.c Sun Jun 7 11:16:39 1998 +++ linux/kernel/capability.c Sun Aug 16 11:51:51 1998 @@ -14,17 +14,7 @@ #include -static inline void cap_fromuser(kernel_cap_t *k, __u32 *u) -{ - copy_from_user(k, u, sizeof(*k)); -} - - -static inline void cap_touser(__u32 *u, const kernel_cap_t *k) -{ - copy_to_user(u, k, sizeof(*k)); -} - +/* Note: never hold tasklist_lock while spinning for this one */ spinlock_t task_capability_lock; /* @@ -33,65 +23,58 @@ * uninteresting and/or not to be changed. */ -asmlinkage int sys_capget(cap_user_header_t header, cap_user_data_t data) +asmlinkage int sys_capget(cap_user_header_t header, cap_user_data_t dataptr) { - int error = -EINVAL, pid; + int error, pid; __u32 version; struct task_struct *target; + struct __user_cap_data_struct data; - if (!access_ok(VERIFY_WRITE, &header->version, sizeof(*header))) { - /* not large enough for current header so indicate error */ - if (access_ok(VERIFY_WRITE, &header->version, - sizeof(header->version))) { - return error; - } - goto all_done; - } - - copy_from_user(&version, &header->version, sizeof(header->version)); + if (get_user(version, &header->version)) + return -EFAULT; + + error = -EINVAL; if (version != _LINUX_CAPABILITY_VERSION) { - /* if enough space for kernel version, write that */ - - all_done: version = _LINUX_CAPABILITY_VERSION; - copy_to_user(&header->version, &version, - sizeof(header->version)); + if (put_user(version, &header->version)) + error = -EFAULT; return error; } - if (!access_ok(VERIFY_WRITE, data, sizeof(*data))) { - return error; - } + if (get_user(pid, &header->pid)) + return -EFAULT; - copy_from_user(&pid, &header->pid, sizeof(header->pid)); - if (pid < 0) { - return error; - } + if (pid < 0) + return -EINVAL; + + error = 0; spin_lock(&task_capability_lock); if (pid && pid != current->pid) { - read_lock(&tasklist_lock); + read_lock(&tasklist_lock); target = find_task_by_pid(pid); /* identify target of query */ - if (!target) { + if (!target) error = -ESRCH; - goto out; - } } else { target = current; } - cap_touser(&data->permitted, &target->cap_permitted); - cap_touser(&data->inheritable, &target->cap_inheritable); - cap_touser(&data->effective, &target->cap_effective); + if (!error) { + data.permitted = target->cap_permitted.cap; + data.inheritable = target->cap_inheritable.cap; + data.effective = target->cap_effective.cap; + } - error = 0; + if (target != current) + read_unlock(&tasklist_lock); + spin_unlock(&task_capability_lock); -out: - if (target != current) { - read_unlock(&tasklist_lock); + if (!error) { + if (copy_to_user(dataptr, &data, sizeof data)) + return -EFAULT; } - spin_unlock(&task_capability_lock); + return error; } @@ -152,38 +135,31 @@ kernel_cap_t inheritable, permitted, effective; __u32 version; struct task_struct *target; - int error = -EINVAL, pid; + int error, pid; - if (!access_ok(VERIFY_WRITE, &header->version, sizeof(*header))) { - /* not large enough for current header so indicate error */ - if (!access_ok(VERIFY_WRITE, &header->version, - sizeof(header->version))) { - return error; - } - goto all_done; - } + if (get_user(version, &header->version)) + return -EFAULT; - copy_from_user(&version, &header->version, sizeof(header->version)); if (version != _LINUX_CAPABILITY_VERSION) { - - all_done: version = _LINUX_CAPABILITY_VERSION; - copy_to_user(&header->version, &version, - sizeof(header->version)); - return error; - } - - if (!access_ok(VERIFY_READ, data, sizeof(*data))) { - return error; + if (put_user(version, &header->version)) + return -EFAULT; + return -EINVAL; } /* may want to set other processes at some point -- for now demand 0 */ - copy_from_user(&pid, &header->pid, sizeof(pid)); + if (get_user(pid, &header->pid)) + return -EFAULT; - error = -EPERM; if (pid && !capable(CAP_SETPCAP)) - return error; + return -EPERM; + if (copy_from_user(&effective, &data->effective, sizeof(effective)) || + copy_from_user(&inheritable, &data->inheritable, sizeof(inheritable)) || + copy_from_user(&permitted, &data->permitted, sizeof(permitted))) + return -EFAULT; + + error = -EPERM; spin_lock(&task_capability_lock); if (pid > 0 && pid != current->pid) { @@ -191,16 +167,12 @@ target = find_task_by_pid(pid); /* identify target of query */ if (!target) { error = -ESRCH; - goto out; - } + goto out; + } } else { target = current; } - /* copy from userspace */ - cap_fromuser(&effective, &data->effective); - cap_fromuser(&inheritable, &data->inheritable); - cap_fromuser(&permitted, &data->permitted); /* verify restrictions on target's new Inheritable set */ if (!cap_issubset(inheritable, diff -u --recursive --new-file v2.1.115/linux/kernel/exit.c linux/kernel/exit.c --- v2.1.115/linux/kernel/exit.c Mon Aug 3 17:48:28 1998 +++ linux/kernel/exit.c Sat Aug 15 16:34:52 1998 @@ -52,7 +52,7 @@ } while (p->has_cpu); } #endif - charge_uid(p, -1); + free_uid(p); nr_tasks--; add_free_taskslot(p->tarray_ptr); @@ -196,7 +196,7 @@ if (files) { tsk->files = NULL; - if (!--files->count) { + if (atomic_dec_and_test(&files->count)) { close_files(files); /* * Free the fd array as appropriate ... @@ -221,7 +221,7 @@ if (fs) { tsk->fs = NULL; - if (!--fs->count) { + if (atomic_dec_and_test(&fs->count)) { dput(fs->root); dput(fs->pwd); kfree(fs); diff -u --recursive --new-file v2.1.115/linux/kernel/fork.c linux/kernel/fork.c --- v2.1.115/linux/kernel/fork.c Mon Aug 3 17:48:28 1998 +++ linux/kernel/fork.c Tue Aug 18 17:15:47 1998 @@ -50,10 +50,10 @@ */ #define UIDHASH_SZ (PIDHASH_SZ >> 2) -static struct uid_taskcount { - struct uid_taskcount *next, **pprev; - unsigned short uid; - int task_count; +static struct user_struct { + atomic_t count; + struct user_struct *next, **pprev; + unsigned int uid; } *uidhash[UIDHASH_SZ]; spinlock_t uidhash_lock = SPIN_LOCK_UNLOCKED; @@ -62,7 +62,7 @@ #define uidhashfn(uid) (((uid >> 8) ^ uid) & (UIDHASH_SZ - 1)) -static inline void uid_hash_insert(struct uid_taskcount *up, unsigned int hashent) +static inline void uid_hash_insert(struct user_struct *up, unsigned int hashent) { spin_lock(&uidhash_lock); if((up->next = uidhash[hashent]) != NULL) @@ -72,7 +72,7 @@ spin_unlock(&uidhash_lock); } -static inline void uid_hash_remove(struct uid_taskcount *up) +static inline void uid_hash_remove(struct user_struct *up) { spin_lock(&uidhash_lock); if(up->next) @@ -81,9 +81,9 @@ spin_unlock(&uidhash_lock); } -static inline struct uid_taskcount *uid_find(unsigned short uid, unsigned int hashent) +static inline struct user_struct *uid_find(unsigned short uid, unsigned int hashent) { - struct uid_taskcount *up; + struct user_struct *up; spin_lock(&uidhash_lock); for(up = uidhash[hashent]; (up && up->uid != uid); up = up->next) @@ -92,31 +92,36 @@ return up; } -int charge_uid(struct task_struct *p, int count) +void free_uid(struct task_struct *p) { - unsigned int hashent = uidhashfn(p->uid); - struct uid_taskcount *up = uid_find(p->uid, hashent); - - if(up) { - int limit = p->rlim[RLIMIT_NPROC].rlim_cur; - int newcnt = up->task_count + count; + struct user_struct *up = p->user; - if(newcnt > limit) - return -EAGAIN; - else if(newcnt == 0) { + if (up) { + p->user = NULL; + if (atomic_dec_and_test(&up->count)) { uid_hash_remove(up); kmem_cache_free(uid_cachep, up); - return 0; } - } else { + } +} + +int alloc_uid(struct task_struct *p) +{ + unsigned int hashent = uidhashfn(p->uid); + struct user_struct *up = uid_find(p->uid, hashent); + + p->user = up; + if (!up) { up = kmem_cache_alloc(uid_cachep, SLAB_KERNEL); - if(!up) + if (!up) return -EAGAIN; + p->user = up; up->uid = p->uid; - up->task_count = 0; + atomic_set(&up->count, 0); uid_hash_insert(up, hashent); } - up->task_count += count; + + atomic_inc(&up->count); return 0; } @@ -124,7 +129,7 @@ { int i; - uid_cachep = kmem_cache_create("uid_cache", sizeof(struct uid_taskcount), + uid_cachep = kmem_cache_create("uid_cache", sizeof(struct user_struct), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if(!uid_cachep) @@ -134,22 +139,13 @@ uidhash[i] = 0; } -static inline int find_empty_process(void) +static inline struct task_struct ** find_empty_process(void) { - struct task_struct **tslot; + struct task_struct **tslot = NULL; - if(current->uid) { - int error; - - if(nr_tasks >= NR_TASKS - MIN_TASKS_LEFT_FOR_ROOT) - return -EAGAIN; - if((error = charge_uid(current, 1)) < 0) - return error; - } - tslot = get_free_taskslot(); - if(tslot) - return tslot - &task[0]; - return -EAGAIN; + if (!current->uid || (nr_tasks < NR_TASKS - MIN_TASKS_LEFT_FOR_ROOT)) + tslot = get_free_taskslot(); + return tslot; } /* Protects next_safe and last_pid. */ @@ -270,7 +266,7 @@ if (mm) { *mm = *current->mm; init_new_context(mm); - mm->count = 1; + atomic_set(&mm->count, 1); mm->map_count = 0; mm->def_flags = 0; mm->mmap_sem = MUTEX_LOCKED; @@ -293,7 +289,7 @@ */ void mmput(struct mm_struct *mm) { - if (!--mm->count) { + if (atomic_dec_and_test(&mm->count)) { release_segments(mm); exit_mmap(mm); free_page_tables(mm); @@ -347,13 +343,13 @@ static inline int copy_fs(unsigned long clone_flags, struct task_struct * tsk) { if (clone_flags & CLONE_FS) { - current->fs->count++; + atomic_inc(¤t->fs->count); return 0; } tsk->fs = kmalloc(sizeof(*tsk->fs), GFP_KERNEL); if (!tsk->fs) return -1; - tsk->fs->count = 1; + atomic_set(&tsk->fs->count, 1); tsk->fs->umask = current->fs->umask; tsk->fs->root = dget(current->fs->root); tsk->fs->pwd = dget(current->fs->pwd); @@ -394,7 +390,7 @@ goto out; if (clone_flags & CLONE_FILES) { - oldf->count++; + atomic_inc(&oldf->count); goto out; } @@ -417,7 +413,7 @@ goto out_release; memset((void *) new_fds, 0, size); - newf->count = 1; + atomic_set(&newf->count, 1); newf->max_fds = NR_OPEN; newf->fd = new_fds; newf->close_on_exec = oldf->close_on_exec; @@ -479,19 +475,31 @@ int retval = -ENOMEM; struct task_struct *p; - down(¤t->mm->mmap_sem); - lock_kernel(); p = alloc_task_struct(); if (!p) - goto bad_fork; - - retval = -EAGAIN; - nr = find_empty_process(); - if (nr < 0) - goto bad_fork_free; + goto fork_out; *p = *current; + down(¤t->mm->mmap_sem); + lock_kernel(); + + if (p->user) { + if (atomic_read(&p->user->count) >= p->rlim[RLIMIT_NPROC].rlim_cur) + goto bad_fork_free; + } + + { + struct task_struct **tslot; + tslot = find_empty_process(); + retval = -EAGAIN; + if (!tslot) + goto bad_fork_free; + p->tarray_ptr = tslot; + *tslot = p; + nr = tslot - &task[0]; + } + if (p->exec_domain && p->exec_domain->module) __MOD_INC_USE_COUNT(p->exec_domain->module); if (p->binfmt && p->binfmt->module) @@ -545,8 +553,6 @@ #endif p->lock_depth = -1; /* -1 = no lock */ p->start_time = jiffies; - p->tarray_ptr = &task[nr]; - *p->tarray_ptr = p; { /* This makes it visible to the rest of the system */ @@ -558,6 +564,8 @@ } nr_tasks++; + if (p->user) + atomic_inc(&p->user->count); retval = -ENOMEM; /* copy all the process information */ @@ -599,6 +607,7 @@ bad_fork: up(¤t->mm->mmap_sem); unlock_kernel(); +fork_out: return retval; bad_fork_cleanup_sighand: @@ -608,12 +617,10 @@ bad_fork_cleanup_files: exit_files(p); /* blocking */ bad_fork_cleanup: - charge_uid(current, -1); if (p->exec_domain && p->exec_domain->module) __MOD_DEC_USE_COUNT(p->exec_domain->module); if (p->binfmt && p->binfmt->module) __MOD_DEC_USE_COUNT(p->binfmt->module); - add_free_taskslot(p->tarray_ptr); { unsigned long flags; @@ -623,7 +630,10 @@ write_unlock_irqrestore(&tasklist_lock, flags); } + if (p->user) + atomic_dec(&p->user->count); nr_tasks--; + add_free_taskslot(p->tarray_ptr); bad_fork_free: free_task_struct(p); goto bad_fork; diff -u --recursive --new-file v2.1.115/linux/kernel/kmod.c linux/kernel/kmod.c --- v2.1.115/linux/kernel/kmod.c Tue Jul 28 14:21:10 1998 +++ linux/kernel/kmod.c Mon Aug 17 16:46:06 1998 @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -22,7 +23,6 @@ modprobe_path is set via /proc/sys. */ char modprobe_path[256] = "/sbin/modprobe"; -static char * envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL }; /* exec_modprobe is spawned from a kernel-mode user process, @@ -41,14 +41,15 @@ /* don't use the user's root, use init's root instead */ exit_fs(current); /* current->fs->count--; */ current->fs = task_init->fs; - current->fs->count++; + atomic_inc(¤t->fs->count); unlock_kernel(); } static int exec_modprobe(void * module_name) { - char *argv[] = { modprobe_path, "-s", "-k", (char*)module_name, NULL}; + static char * envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL }; + char *argv[] = { modprobe_path, "-s", "-k", (char*)module_name, NULL }; int i; use_init_file_context(); @@ -68,8 +69,8 @@ if (current->files->fd[i]) close(i); } - /* kernel_thread() -> ... -> charge_uid(current, 1) workaround */ - charge_uid(current, -1); + /* Drop the "current user" thing */ + free_uid(current); /* Give kmod all privileges.. */ current->uid = current->euid = current->fsuid = 0; @@ -97,6 +98,7 @@ { int pid; int waitpid_result; + sigset_t tmpsig; /* Don't allow request_module() before the root fs is mounted! */ if ( ! current->fs->root ) { @@ -107,10 +109,25 @@ pid = kernel_thread(exec_modprobe, (void*) module_name, CLONE_FS); if (pid < 0) { - printk(KERN_ERR "kmod: fork failed, errno %d\n", -pid); + printk(KERN_ERR "request_module[%s]: fork failed, errno %d\n", module_name, -pid); return pid; } + + /* Block everything but SIGKILL/SIGSTOP */ + spin_lock_irq(¤t->sigmask_lock); + tmpsig = current->blocked; + siginitset(¤t->blocked, ~(sigmask(SIGKILL)|sigmask(SIGSTOP))); + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + waitpid_result = waitpid(pid, NULL, __WCLONE); + + /* Allow signals again.. */ + spin_lock_irq(¤t->sigmask_lock); + current->blocked = tmpsig; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + if (waitpid_result != pid) { printk (KERN_ERR "kmod: waitpid(%d,NULL,0) failed, returning %d.\n", pid, waitpid_result); diff -u --recursive --new-file v2.1.115/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v2.1.115/linux/kernel/ksyms.c Thu Aug 6 14:06:34 1998 +++ linux/kernel/ksyms.c Sun Aug 9 12:23:47 1998 @@ -51,6 +51,7 @@ #include #include #include +#include extern unsigned char aux_device_present, pckbd_read_mask; @@ -389,7 +390,7 @@ #ifdef CONFIG_BLK_DEV_MD EXPORT_SYMBOL(disk_name); /* for md.c */ #endif - + /* binfmt_aout */ EXPORT_SYMBOL(get_write_access); EXPORT_SYMBOL(put_write_access); @@ -397,3 +398,6 @@ /* dynamic registering of consoles */ EXPORT_SYMBOL(register_console); EXPORT_SYMBOL(unregister_console); + +/* time */ +EXPORT_SYMBOL(get_fast_time); diff -u --recursive --new-file v2.1.115/linux/kernel/sys.c linux/kernel/sys.c --- v2.1.115/linux/kernel/sys.c Wed Jun 24 22:54:12 1998 +++ linux/kernel/sys.c Sat Aug 15 16:01:13 1998 @@ -405,10 +405,9 @@ * cheaply with the new uid cache, so if it matters * we should be checking for it. -DaveM */ - charge_uid(current, -1); + free_uid(current); current->uid = new_ruid; - if(new_ruid) - charge_uid(current, 1); + alloc_uid(current); } if (!issecure(SECURE_NO_SETUID_FIXUP)) { @@ -450,10 +449,9 @@ if (new_ruid != old_ruid) { /* See comment above about NPROC rlimit issues... */ - charge_uid(current, -1); + free_uid(current); current->uid = new_ruid; - if(new_ruid) - charge_uid(current, 1); + alloc_uid(current); } if (!issecure(SECURE_NO_SETUID_FIXUP)) { @@ -473,7 +471,8 @@ int old_ruid = current->uid; int old_euid = current->euid; int old_suid = current->suid; - if (!capable(CAP_SETUID)) { + + if (!capable(CAP_SETUID)) { if ((ruid != (uid_t) -1) && (ruid != current->uid) && (ruid != current->euid) && (ruid != current->suid)) return -EPERM; @@ -486,10 +485,9 @@ } if (ruid != (uid_t) -1) { /* See above commentary about NPROC rlimit issues here. */ - charge_uid(current, -1); + free_uid(current); current->uid = ruid; - if(ruid) - charge_uid(current, 1); + alloc_uid(current); } if (euid != (uid_t) -1) { if (euid != current->euid) diff -u --recursive --new-file v2.1.115/linux/mm/filemap.c linux/mm/filemap.c --- v2.1.115/linux/mm/filemap.c Thu Aug 6 14:06:34 1998 +++ linux/mm/filemap.c Tue Aug 18 13:21:49 1998 @@ -172,10 +172,12 @@ break; } age_page(page); +#if 0 if (page->age) break; if (page_cache_size * 100 < (page_cache.min_percent * num_physpages)) break; +#endif if (PageSwapCache(page)) { delete_from_swap_cache(page); return 1; @@ -189,7 +191,7 @@ break; /* is it a buffer cache page? */ - if ((gfp_mask & __GFP_IO) && bh && try_to_free_buffer(bh, &bh, 6)) + if (bh && try_to_free_buffer(bh, &bh, 6)) return 1; break; @@ -211,8 +213,8 @@ struct page * page; int count_max, count_min; - count_max = (limit<<2) >> (priority>>1); - count_min = (limit<<2) >> (priority); + count_max = (limit<<1) >> (priority>>1); + count_min = (limit<<1) >> (priority); page = mem_map + clock; do { @@ -327,6 +329,7 @@ */ page = mem_map + MAP_NR(page_cache); add_to_page_cache(page, inode, offset, hash); + set_bit(PG_referenced, &page->flags); inode->i_op->readpage(file, page); page_cache = 0; } diff -u --recursive --new-file v2.1.115/linux/mm/page_alloc.c linux/mm/page_alloc.c --- v2.1.115/linux/mm/page_alloc.c Tue Jul 21 00:15:33 1998 +++ linux/mm/page_alloc.c Tue Aug 18 16:42:57 1998 @@ -263,6 +263,16 @@ spin_lock_irqsave(&page_alloc_lock, flags); RMQUEUE(order, (gfp_mask & GFP_DMA)); spin_unlock_irqrestore(&page_alloc_lock, flags); + + /* + * If we failed to find anything, we'll return NULL, but we'll + * wake up kswapd _now_ ad even wait for it synchronously if + * we can.. This way we'll at least make some forward progress + * over time. + */ + wake_up(&kswapd_wait); + if (gfp_mask & __GFP_WAIT) + schedule(); nopage: return 0; } diff -u --recursive --new-file v2.1.115/linux/mm/swap.c linux/mm/swap.c --- v2.1.115/linux/mm/swap.c Wed Jun 24 22:54:14 1998 +++ linux/mm/swap.c Sun Aug 9 11:17:49 1998 @@ -67,9 +67,9 @@ swapstat_t swapstats = {0}; buffer_mem_t buffer_mem = { - 3, /* minimum percent buffer */ - 10, /* borrow percent buffer */ - 30 /* maximum percent buffer */ + 5, /* minimum percent buffer */ + 25, /* borrow percent buffer */ + 50 /* maximum percent buffer */ }; buffer_mem_t page_cache = { diff -u --recursive --new-file v2.1.115/linux/mm/vmscan.c linux/mm/vmscan.c --- v2.1.115/linux/mm/vmscan.c Tue Jul 21 00:15:33 1998 +++ linux/mm/vmscan.c Tue Aug 18 15:19:42 1998 @@ -42,7 +42,7 @@ /* * The wait queue for waking up the pageout daemon: */ -static struct wait_queue * kswapd_wait = NULL; +struct wait_queue * kswapd_wait = NULL; static void init_swap_timer(void); @@ -469,7 +469,7 @@ return 1; state = 1; case 1: - if ((gfp_mask & __GFP_IO) && shm_swap(i, gfp_mask)) + if (shm_swap(i, gfp_mask)) return 1; state = 2; case 2: @@ -525,7 +525,7 @@ /* Give kswapd a realtime priority. */ current->policy = SCHED_FIFO; - current->priority = 32; /* Fixme --- we need to standardise our + current->rt_priority = 32; /* Fixme --- we need to standardise our namings for POSIX.4 realtime scheduling priorities. */ @@ -558,22 +558,18 @@ */ tries = pager_daemon.tries_base; tries >>= 4*free_memory_available(); - - while (tries--) { - int gfp_mask; - if (free_memory_available() > 1) - break; - gfp_mask = __GFP_IO; - do_try_to_free_page(gfp_mask); + do { + do_try_to_free_page(0); /* * Syncing large chunks is faster than swapping * synchronously (less head movement). -- Rik. */ if (atomic_read(&nr_async_pages) >= pager_daemon.swap_cluster) run_task_queue(&tq_disk); - - } + if (free_memory_available() > 1) + break; + } while (--tries > 0); } /* As if we could ever get here - maybe we want to make this killable */ remove_wait_queue(&kswapd_wait, &wait); @@ -582,23 +578,30 @@ } /* - * This is REALLY ugly. - * * We need to make the locks finer granularity, but right * now we need this so that we can do page allocations * without holding the kernel lock etc. + * + * The "PF_MEMALLOC" flag protects us against recursion: + * if we need more memory as part of a swap-out effort we + * will just silently return "success" to tell the page + * allocator to accept the allocation. */ int try_to_free_pages(unsigned int gfp_mask, int count) { - int retval; + int retval = 1; lock_kernel(); - do { - retval = do_try_to_free_page(gfp_mask); - if (!retval) - break; - count--; - } while (count > 0); + if (current->flags & PF_MEMALLOC) { + current->flags |= PF_MEMALLOC; + do { + retval = do_try_to_free_page(gfp_mask); + if (!retval) + break; + count--; + } while (count > 0); + current->flags &= PF_MEMALLOC; + } unlock_kernel(); return retval; } diff -u --recursive --new-file v2.1.115/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c --- v2.1.115/linux/net/ax25/af_ax25.c Tue Jul 28 14:21:10 1998 +++ linux/net/ax25/af_ax25.c Sun Aug 9 12:23:47 1998 @@ -1009,7 +1009,10 @@ if (sk->zapped == 0) return -EINVAL; - if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25)) + if (addr_len < sizeof(struct sockaddr_ax25) || addr_len > sizeof(struct full_sockaddr_ax25)) + return -EINVAL; + + if (addr_len < (addr->fsa_ax25.sax25_ndigis * sizeof(ax25_address) + sizeof(struct sockaddr_ax25))) return -EINVAL; if (addr->fsa_ax25.sax25_family != AF_AX25) diff -u --recursive --new-file v2.1.115/linux/net/core/dev.c linux/net/core/dev.c --- v2.1.115/linux/net/core/dev.c Tue Jun 23 10:01:30 1998 +++ linux/net/core/dev.c Wed Aug 12 00:59:03 1998 @@ -740,21 +740,20 @@ * recovering the MAC header first. */ - int offset=skb->data-skb->mac.raw; - cli(); + int offset; + + skb=skb_clone(skb, GFP_ATOMIC); + if(skb==NULL) + return; + + offset=skb->data-skb->mac.raw; skb_push(skb,offset); /* Put header back on for bridge */ + if(br_receive_frame(skb)) - { - sti(); return; - } - /* - * Pull the MAC header off for the copy going to - * the upper layers. - */ - skb_pull(skb,offset); - sti(); + kfree_skb(skb, FREE_READ); } + return; } #endif @@ -809,7 +808,7 @@ while (!skb_queue_empty(&backlog)) { - struct sk_buff * skb = backlog.next; + struct sk_buff * skb; /* Give chance to other bottom halves to run */ if (jiffies - start_time > 1) @@ -818,9 +817,7 @@ /* * We have a packet. Therefore the queue has shrunk */ - cli(); - __skb_unlink(skb, &backlog); - sti(); + skb = skb_dequeue(&backlog); #ifdef CONFIG_CPU_IS_SLOW if (ave_busy > 128*16) { diff -u --recursive --new-file v2.1.115/linux/net/core/sock.c linux/net/core/sock.c --- v2.1.115/linux/net/core/sock.c Tue Jul 28 14:21:10 1998 +++ linux/net/core/sock.c Tue Aug 18 17:02:40 1998 @@ -543,8 +543,8 @@ atomic_add(skb->truesize, &sk->wmem_alloc); skb->destructor = sock_wfree; skb->sk = sk; + return skb; } - return skb; } return NULL; } @@ -557,8 +557,8 @@ atomic_add(skb->truesize, &sk->rmem_alloc); skb->destructor = sock_rfree; skb->sk = sk; + return skb; } - return skb; } return NULL; } diff -u --recursive --new-file v2.1.115/linux/net/econet/econet.c linux/net/econet/econet.c --- v2.1.115/linux/net/econet/econet.c Tue Jul 28 14:21:10 1998 +++ linux/net/econet/econet.c Sun Aug 9 12:23:47 1998 @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,8 @@ static struct proto_ops econet_ops; static struct sock *econet_sklist; +static spinlock_t aun_queue_lock; + #ifdef CONFIG_ECONET_AUNUDP static struct socket *udpsock; #define AUN_PORT 0x8000 @@ -343,7 +346,7 @@ eb->cookie = saddr->cookie; eb->sec = *saddr; - eb->sent - ec_tx_done; + eb->sent = ec_tx_done; if (dev->hard_header) { int res; @@ -965,7 +968,6 @@ * drop the packet. */ -static spinlock_t aun_queue_lock; static void ab_cleanup(unsigned long h) { diff -u --recursive --new-file v2.1.115/linux/net/ipv4/arp.c linux/net/ipv4/arp.c --- v2.1.115/linux/net/ipv4/arp.c Tue Jul 28 14:21:10 1998 +++ linux/net/ipv4/arp.c Sun Aug 9 12:23:47 1998 @@ -163,7 +163,7 @@ dev_queue_xmit }; -#if defined(CONFIG_AX25) || defined(CONFIG_AX25) || \ +#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) || \ defined(CONFIG_SHAPER) || defined(CONFIG_SHAPER_MODULE) struct neigh_ops arp_broken_ops = { @@ -261,7 +261,7 @@ default: break; case ARPHRD_ROSE: -#if defined(CONFIG_AX25) || defined(CONFIG_AX25) +#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) case ARPHRD_AX25: #if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE) case ARPHRD_NETROM: diff -u --recursive --new-file v2.1.115/linux/net/ipv4/ip_fragment.c linux/net/ipv4/ip_fragment.c --- v2.1.115/linux/net/ipv4/ip_fragment.c Tue Jul 28 14:21:10 1998 +++ linux/net/ipv4/ip_fragment.c Tue Aug 18 16:16:30 1998 @@ -370,6 +370,16 @@ skb->pkt_type = qp->fragments->skb->pkt_type; skb->protocol = qp->fragments->skb->protocol; + /* + * Clearly bogus, because security markings of the individual + * fragments should have been checked for consistency before + * gluing, and intermediate coalescing of fragments may have + * taken place in ip_defrag() before ip_glue() ever got called. + * If we're not going to do the consistency checking, we might + * as well take the value associated with the first fragment. + * --rct + */ + skb->security = qp->fragments->skb->security; /* Done with all fragments. Fixup the new IP header. */ iph = skb->nh.iph; diff -u --recursive --new-file v2.1.115/linux/net/packet/af_packet.c linux/net/packet/af_packet.c --- v2.1.115/linux/net/packet/af_packet.c Tue Jul 28 14:21:10 1998 +++ linux/net/packet/af_packet.c Sun Aug 9 12:23:47 1998 @@ -1204,8 +1204,8 @@ packet_release, packet_bind, sock_no_connect, - NULL, - NULL, + sock_no_socketpair, + sock_no_accept, packet_getname, datagram_poll, packet_ioctl, diff -u --recursive --new-file v2.1.115/linux/net/sunrpc/auth_unix.c linux/net/sunrpc/auth_unix.c --- v2.1.115/linux/net/sunrpc/auth_unix.c Thu Mar 26 15:57:25 1998 +++ linux/net/sunrpc/auth_unix.c Wed Aug 12 13:51:17 1998 @@ -178,6 +178,11 @@ base = p++; *p++ = htonl(jiffies/HZ); #ifndef DONT_FILLIN_HOSTNAME + /* + * Problem: The UTS name could change under us. We can't lock + * here to handle this. On the other hand we can't really + * go building a bad RPC! + */ if ((n = strlen((char *) system_utsname.nodename)) > UNX_MAXNODENAME) n = UNX_MAXNODENAME; *p++ = htonl(n); diff -u --recursive --new-file v2.1.115/linux/net/sunrpc/sched.c linux/net/sunrpc/sched.c --- v2.1.115/linux/net/sunrpc/sched.c Tue Jul 21 00:15:33 1998 +++ linux/net/sunrpc/sched.c Wed Aug 12 13:51:17 1998 @@ -176,6 +176,21 @@ task->tk_flags |= RPC_TASK_RUNNING; } + +/* + * For other people who may need to wake the I/O daemon + * but should (for now) know nothing about its innards + */ + +void rpciod_wake_up(void) +{ + if(rpciod_pid==0) + { + printk(KERN_ERR "rpciod: wot no daemon?\n"); + } + wake_up(&rpciod_idle); +} + /* * Prepare for sleeping on a wait queue. * By always appending tasks to the list we ensure FIFO behavior. @@ -795,6 +810,7 @@ dprintk("RPC: rpciod back to sleep\n"); interruptible_sleep_on(&rpciod_idle); dprintk("RPC: switch to rpciod\n"); + rpciod_tcp_dispatcher(); rounds = 0; } restore_flags(oldflags); diff -u --recursive --new-file v2.1.115/linux/net/sunrpc/xprt.c linux/net/sunrpc/xprt.c --- v2.1.115/linux/net/sunrpc/xprt.c Mon Aug 3 12:45:48 1998 +++ linux/net/sunrpc/xprt.c Wed Aug 12 13:51:17 1998 @@ -324,6 +324,12 @@ fput(xprt->file); else sock_release(xprt->sock); + /* + * TCP doesnt require the rpciod now - other things may + * but rpciod handles that not us. + */ + if(xprt->stream) + rpciod_down(); } /* @@ -700,19 +706,17 @@ static struct rpc_xprt *rpc_xprt_pending = NULL; /* Chain by rx_pending of rpc_xprt's */ -static struct tq_struct rpc_tcp_tqueue = { 0, 0, 0, 0 }; - - /* - * This is protected from tcp_data_ready by the bh atomicity guarantees + * This is protected from tcp_data_ready and the stack as its run + * inside of the RPC I/O daemon */ -static void tcp_rpc_bh_run(void) +void rpciod_tcp_dispatcher(void) { struct rpc_xprt *xprt; int result; - dprintk("tcp_rpc_bh_run: Queue Running\n"); + dprintk("rpciod_tcp_dispatcher: Queue Running\n"); /* * Empty each pending socket @@ -725,7 +729,7 @@ rpc_xprt_pending=xprt->rx_pending; xprt->rx_pending_flag=0; - dprintk("tcp_rpc_run_bh: Processing %p\n", xprt); + dprintk("rpciod_tcp_dispatcher: Processing %p\n", xprt); do { @@ -750,12 +754,9 @@ } -static void tcp_rpc_bh_queue(void) +extern inline void tcp_rpciod_queue(void) { - rpc_tcp_tqueue.routine=(void *)(void *)tcp_rpc_bh_run; - queue_task(&rpc_tcp_tqueue, &tq_immediate); - dprintk("RPC: tcp_rpc_bh_queue: immediate op queued\n"); - mark_bh(IMMEDIATE_BH); + rpciod_wake_up(); } /* @@ -787,7 +788,7 @@ { dprintk("RPC: xprt queue\n"); if(rpc_xprt_pending==NULL) - tcp_rpc_bh_queue(); + tcp_rpciod_queue(); xprt->rx_pending_flag=1; xprt->rx_pending=rpc_xprt_pending; rpc_xprt_pending=xprt; @@ -1279,6 +1280,12 @@ xprt->free = xprt->slot; dprintk("RPC: created transport %p\n", xprt); + + /* + * TCP requires the rpc I/O daemon is present + */ + if(proto==IPPROTO_TCP) + rpciod_up(); return xprt; } diff -u --recursive --new-file v2.1.115/linux/net/wanrouter/wanmain.c linux/net/wanrouter/wanmain.c --- v2.1.115/linux/net/wanrouter/wanmain.c Wed Jun 24 22:54:14 1998 +++ linux/net/wanrouter/wanmain.c Sun Aug 16 13:34:44 1998 @@ -25,6 +25,7 @@ * Oct 15, 1997 Farhan Thawar changed wan_encapsulate to add a pad byte of 0 * Apr 20, 1998 Alan Cox Fixed 2.1 symbols * May 17, 1998 K. Baranowski Fixed SNAP encapsulation in wan_encapsulate +* Aug 15, 1998 Arnaldo C. Melo Fixed device_setup return value *****************************************************************************/ #include /* offsetof(), etc. */ @@ -466,7 +467,7 @@ if(!copy_from_user(data, conf->data, conf->data_size)) { conf->data=data; - wandev->setup(wandev,conf); + err = wandev->setup(wandev,conf); } else err = -ENOBUFS;