aboutsummaryrefslogtreecommitdiffstats
path: root/arch/alpha
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/alpha
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/alpha')
-rw-r--r--arch/alpha/Kconfig606
-rw-r--r--arch/alpha/Kconfig.debug59
-rw-r--r--arch/alpha/Makefile130
-rw-r--r--arch/alpha/boot/Makefile116
-rw-r--r--arch/alpha/boot/bootloader.lds24
-rw-r--r--arch/alpha/boot/bootp.c214
-rw-r--r--arch/alpha/boot/bootpz.c469
-rw-r--r--arch/alpha/boot/head.S123
-rw-r--r--arch/alpha/boot/main.c191
-rw-r--r--arch/alpha/boot/misc.c207
-rw-r--r--arch/alpha/boot/tools/mkbb.c151
-rw-r--r--arch/alpha/boot/tools/objstrip.c281
-rw-r--r--arch/alpha/defconfig927
-rw-r--r--arch/alpha/kernel/Makefile104
-rw-r--r--arch/alpha/kernel/alpha_ksyms.c235
-rw-r--r--arch/alpha/kernel/asm-offsets.c43
-rw-r--r--arch/alpha/kernel/console.c66
-rw-r--r--arch/alpha/kernel/core_apecs.c418
-rw-r--r--arch/alpha/kernel/core_cia.c1212
-rw-r--r--arch/alpha/kernel/core_irongate.c416
-rw-r--r--arch/alpha/kernel/core_lca.c515
-rw-r--r--arch/alpha/kernel/core_marvel.c1154
-rw-r--r--arch/alpha/kernel/core_mcpcia.c618
-rw-r--r--arch/alpha/kernel/core_polaris.c203
-rw-r--r--arch/alpha/kernel/core_t2.c622
-rw-r--r--arch/alpha/kernel/core_titan.c806
-rw-r--r--arch/alpha/kernel/core_tsunami.c459
-rw-r--r--arch/alpha/kernel/core_wildfire.c658
-rw-r--r--arch/alpha/kernel/entry.S957
-rw-r--r--arch/alpha/kernel/err_common.c321
-rw-r--r--arch/alpha/kernel/err_ev6.c274
-rw-r--r--arch/alpha/kernel/err_ev7.c289
-rw-r--r--arch/alpha/kernel/err_impl.h85
-rw-r--r--arch/alpha/kernel/err_marvel.c1159
-rw-r--r--arch/alpha/kernel/err_titan.c756
-rw-r--r--arch/alpha/kernel/es1888.c49
-rw-r--r--arch/alpha/kernel/gct.c48
-rw-r--r--arch/alpha/kernel/head.S99
-rw-r--r--arch/alpha/kernel/init_task.c23
-rw-r--r--arch/alpha/kernel/io.c630
-rw-r--r--arch/alpha/kernel/irq.c774
-rw-r--r--arch/alpha/kernel/irq_alpha.c252
-rw-r--r--arch/alpha/kernel/irq_i8259.c183
-rw-r--r--arch/alpha/kernel/irq_impl.h42
-rw-r--r--arch/alpha/kernel/irq_pyxis.c127
-rw-r--r--arch/alpha/kernel/irq_srm.c79
-rw-r--r--arch/alpha/kernel/machvec_impl.h150
-rw-r--r--arch/alpha/kernel/module.c311
-rw-r--r--arch/alpha/kernel/ns87312.c38
-rw-r--r--arch/alpha/kernel/osf_sys.c1345
-rw-r--r--arch/alpha/kernel/pci-noop.c214
-rw-r--r--arch/alpha/kernel/pci.c561
-rw-r--r--arch/alpha/kernel/pci_impl.h209
-rw-r--r--arch/alpha/kernel/pci_iommu.c971
-rw-r--r--arch/alpha/kernel/process.c528
-rw-r--r--arch/alpha/kernel/proto.h210
-rw-r--r--arch/alpha/kernel/ptrace.c415
-rw-r--r--arch/alpha/kernel/semaphore.c224
-rw-r--r--arch/alpha/kernel/setup.c1486
-rw-r--r--arch/alpha/kernel/signal.c672
-rw-r--r--arch/alpha/kernel/smc37c669.c2554
-rw-r--r--arch/alpha/kernel/smc37c93x.c277
-rw-r--r--arch/alpha/kernel/smp.c1163
-rw-r--r--arch/alpha/kernel/srm_env.c335
-rw-r--r--arch/alpha/kernel/srmcons.c326
-rw-r--r--arch/alpha/kernel/sys_alcor.c326
-rw-r--r--arch/alpha/kernel/sys_cabriolet.c448
-rw-r--r--arch/alpha/kernel/sys_dp264.c689
-rw-r--r--arch/alpha/kernel/sys_eb64p.c256
-rw-r--r--arch/alpha/kernel/sys_eiger.c242
-rw-r--r--arch/alpha/kernel/sys_jensen.c274
-rw-r--r--arch/alpha/kernel/sys_marvel.c499
-rw-r--r--arch/alpha/kernel/sys_miata.c289
-rw-r--r--arch/alpha/kernel/sys_mikasa.c265
-rw-r--r--arch/alpha/kernel/sys_nautilus.c269
-rw-r--r--arch/alpha/kernel/sys_noritake.c347
-rw-r--r--arch/alpha/kernel/sys_rawhide.c270
-rw-r--r--arch/alpha/kernel/sys_ruffian.c240
-rw-r--r--arch/alpha/kernel/sys_rx164.c220
-rw-r--r--arch/alpha/kernel/sys_sable.c653
-rw-r--r--arch/alpha/kernel/sys_sio.c438
-rw-r--r--arch/alpha/kernel/sys_sx164.c178
-rw-r--r--arch/alpha/kernel/sys_takara.c296
-rw-r--r--arch/alpha/kernel/sys_titan.c420
-rw-r--r--arch/alpha/kernel/sys_wildfire.c361
-rw-r--r--arch/alpha/kernel/systbls.S468
-rw-r--r--arch/alpha/kernel/time.c591
-rw-r--r--arch/alpha/kernel/traps.c1092
-rw-r--r--arch/alpha/kernel/vmlinux.lds.S149
-rw-r--r--arch/alpha/lib/Makefile58
-rw-r--r--arch/alpha/lib/callback_srm.S104
-rw-r--r--arch/alpha/lib/checksum.c186
-rw-r--r--arch/alpha/lib/clear_page.S39
-rw-r--r--arch/alpha/lib/clear_user.S113
-rw-r--r--arch/alpha/lib/copy_page.S49
-rw-r--r--arch/alpha/lib/copy_user.S145
-rw-r--r--arch/alpha/lib/csum_ipv6_magic.S92
-rw-r--r--arch/alpha/lib/csum_partial_copy.c391
-rw-r--r--arch/alpha/lib/dbg_current.S29
-rw-r--r--arch/alpha/lib/dbg_stackcheck.S27
-rw-r--r--arch/alpha/lib/dbg_stackkill.S35
-rw-r--r--arch/alpha/lib/dec_and_lock.c42
-rw-r--r--arch/alpha/lib/divide.S195
-rw-r--r--arch/alpha/lib/ev6-clear_page.S54
-rw-r--r--arch/alpha/lib/ev6-clear_user.S225
-rw-r--r--arch/alpha/lib/ev6-copy_page.S203
-rw-r--r--arch/alpha/lib/ev6-copy_user.S259
-rw-r--r--arch/alpha/lib/ev6-csum_ipv6_magic.S126
-rw-r--r--arch/alpha/lib/ev6-divide.S259
-rw-r--r--arch/alpha/lib/ev6-memchr.S191
-rw-r--r--arch/alpha/lib/ev6-memcpy.S248
-rw-r--r--arch/alpha/lib/ev6-memset.S597
-rw-r--r--arch/alpha/lib/ev6-strncpy_from_user.S424
-rw-r--r--arch/alpha/lib/ev6-stxcpy.S321
-rw-r--r--arch/alpha/lib/ev6-stxncpy.S397
-rw-r--r--arch/alpha/lib/ev67-strcat.S54
-rw-r--r--arch/alpha/lib/ev67-strchr.S88
-rw-r--r--arch/alpha/lib/ev67-strlen.S49
-rw-r--r--arch/alpha/lib/ev67-strlen_user.S107
-rw-r--r--arch/alpha/lib/ev67-strncat.S94
-rw-r--r--arch/alpha/lib/ev67-strrchr.S109
-rw-r--r--arch/alpha/lib/fpreg.c193
-rw-r--r--arch/alpha/lib/memchr.S164
-rw-r--r--arch/alpha/lib/memcpy.c163
-rw-r--r--arch/alpha/lib/memmove.S181
-rw-r--r--arch/alpha/lib/memset.S124
-rw-r--r--arch/alpha/lib/srm_printk.c41
-rw-r--r--arch/alpha/lib/srm_puts.c23
-rw-r--r--arch/alpha/lib/stacktrace.c103
-rw-r--r--arch/alpha/lib/strcasecmp.c26
-rw-r--r--arch/alpha/lib/strcat.S52
-rw-r--r--arch/alpha/lib/strchr.S70
-rw-r--r--arch/alpha/lib/strcpy.S23
-rw-r--r--arch/alpha/lib/strlen.S57
-rw-r--r--arch/alpha/lib/strlen_user.S91
-rw-r--r--arch/alpha/lib/strncat.S84
-rw-r--r--arch/alpha/lib/strncpy.S81
-rw-r--r--arch/alpha/lib/strncpy_from_user.S339
-rw-r--r--arch/alpha/lib/strrchr.S87
-rw-r--r--arch/alpha/lib/stxcpy.S289
-rw-r--r--arch/alpha/lib/stxncpy.S345
-rw-r--r--arch/alpha/lib/udelay.c55
-rw-r--r--arch/alpha/math-emu/Makefile9
-rw-r--r--arch/alpha/math-emu/math.c400
-rw-r--r--arch/alpha/math-emu/qrnnd.S163
-rw-r--r--arch/alpha/math-emu/sfp-util.h35
-rw-r--r--arch/alpha/mm/Makefile9
-rw-r--r--arch/alpha/mm/extable.c34
-rw-r--r--arch/alpha/mm/fault.c247
-rw-r--r--arch/alpha/mm/init.c382
-rw-r--r--arch/alpha/mm/numa.c395
-rw-r--r--arch/alpha/mm/remap.c90
-rw-r--r--arch/alpha/oprofile/Kconfig23
-rw-r--r--arch/alpha/oprofile/Makefile19
-rw-r--r--arch/alpha/oprofile/common.c189
-rw-r--r--arch/alpha/oprofile/op_impl.h55
-rw-r--r--arch/alpha/oprofile/op_model_ev4.c116
-rw-r--r--arch/alpha/oprofile/op_model_ev5.c211
-rw-r--r--arch/alpha/oprofile/op_model_ev6.c103
-rw-r--r--arch/alpha/oprofile/op_model_ev67.c263
160 files changed, 49087 insertions, 0 deletions
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
new file mode 100644
index 000000000000..0c79b9d95f74
--- /dev/null
+++ b/arch/alpha/Kconfig
@@ -0,0 +1,606 @@
1#
2# For a description of the syntax of this configuration file,
3# see Documentation/kbuild/kconfig-language.txt.
4#
5config ALPHA
6 bool
7 default y
8 help
9 The Alpha is a 64-bit general-purpose processor designed and
10 marketed by the Digital Equipment Corporation of blessed memory,
11 now Hewlett-Packard. The Alpha Linux project has a home page at
12 <http://www.alphalinux.org/>.
13
14config 64BIT
15 def_bool y
16
17config MMU
18 bool
19 default y
20
21config UID16
22 bool
23
24config RWSEM_GENERIC_SPINLOCK
25 bool
26
27config RWSEM_XCHGADD_ALGORITHM
28 bool
29 default y
30
31config GENERIC_CALIBRATE_DELAY
32 bool
33 default y
34
35config GENERIC_ISA_DMA
36 bool
37 default y
38
39config GENERIC_IOMAP
40 bool
41 default n
42
43source "init/Kconfig"
44
45
46menu "System setup"
47
48choice
49 prompt "Alpha system type"
50 default ALPHA_GENERIC
51 ---help---
52 This is the system type of your hardware. A "generic" kernel will
53 run on any supported Alpha system. However, if you configure a
54 kernel for your specific system, it will be faster and smaller.
55
56 To find out what type of Alpha system you have, you may want to
57 check out the Linux/Alpha FAQ, accessible on the WWW from
58 <http://www.alphalinux.org/>. In summary:
59
60 Alcor/Alpha-XLT AS 600
61 Alpha-XL XL-233, XL-266
62 AlphaBook1 Alpha laptop
63 Avanti AS 200, AS 205, AS 250, AS 255, AS 300, AS 400
64 Cabriolet AlphaPC64, AlphaPCI64
65 DP264 DP264
66 EB164 EB164 21164 evaluation board
67 EB64+ EB64+ 21064 evaluation board
68 EB66 EB66 21066 evaluation board
69 EB66+ EB66+ 21066 evaluation board
70 Jensen DECpc 150, DEC 2000 model 300,
71 DEC 2000 model 500
72 LX164 AlphaPC164-LX
73 Lynx AS 2100A
74 Miata Personal Workstation 433a, 433au, 500a,
75 500au, 600a, or 600au
76 Marvel AlphaServer ES47 / ES80 / GS1280
77 Mikasa AS 1000
78 Noname AXPpci33, UDB (Multia)
79 Noritake AS 1000A, AS 600A, AS 800
80 PC164 AlphaPC164
81 Rawhide AS 1200, AS 4000, AS 4100
82 Ruffian RPX164-2, AlphaPC164-UX, AlphaPC164-BX
83 SX164 AlphaPC164-SX
84 Sable AS 2000, AS 2100
85 Shark DS 20L
86 Takara Takara
87 Titan AlphaServer ES45 / DS25
88 Wildfire AlphaServer GS 40/80/160/320
89
90 If you don't know what to do, choose "generic".
91
92config ALPHA_GENERIC
93 bool "Generic"
94 help
95 A generic kernel will run on all supported Alpha hardware.
96
97config ALPHA_ALCOR
98 bool "Alcor/Alpha-XLT"
99 help
100 For systems using the Digital ALCOR chipset: 5 chips (4, 64-bit data
101 slices (Data Switch, DSW) - 208-pin PQFP and 1 control (Control, I/O
102 Address, CIA) - a 383 pin plastic PGA). It provides a DRAM
103 controller (256-bit memory bus) and a PCI interface. It also does
104 all the work required to support an external Bcache and to maintain
105 memory coherence when a PCI device DMAs into (or out of) memory.
106
107config ALPHA_XL
108 bool "Alpha-XL"
109 help
110 XL-233 and XL-266-based Alpha systems.
111
112config ALPHA_BOOK1
113 bool "AlphaBook1"
114 help
115 Dec AlphaBook1/Burns Alpha-based laptops.
116
117config ALPHA_AVANTI_CH
118 bool "Avanti"
119
120config ALPHA_CABRIOLET
121 bool "Cabriolet"
122 help
123 Cabriolet AlphaPC64, AlphaPCI64 systems. Derived from EB64+ but now
124 baby-AT with Flash boot ROM, no on-board SCSI or Ethernet. 3 ISA
125 slots, 4 PCI slots (one pair are on a shared slot), uses plug-in
126 Bcache SIMMs. Requires power supply with 3.3V output.
127
128config ALPHA_DP264
129 bool "DP264"
130 help
131 Various 21264 systems with the tsunami core logic chipset.
132 API Networks: 264DP, UP2000(+), CS20;
133 Compaq: DS10(E,L), XP900, XP1000, DS20(E), ES40.
134
135config ALPHA_EB164
136 bool "EB164"
137 help
138 EB164 21164 evaluation board from DEC. Uses 21164 and ALCOR. Has
139 ISA and PCI expansion (3 ISA slots, 2 64-bit PCI slots (one is
140 shared with an ISA slot) and 2 32-bit PCI slots. Uses plus-in
141 Bcache SIMMs. I/O sub-system provides SuperI/O (2S, 1P, FD), KBD,
142 MOUSE (PS2 style), RTC/NVRAM. Boot ROM is Flash. PC-AT-sized
143 motherboard. Requires power supply with 3.3V output.
144
145config ALPHA_EB64P_CH
146 bool "EB64+"
147
148config ALPHA_EB66
149 bool "EB66"
150 help
151 A Digital DS group board. Uses 21066 or 21066A. I/O sub-system is
152 identical to EB64+. Baby PC-AT size. Runs from standard PC power
153 supply. The EB66 schematic was published as a marketing poster
154 advertising the 21066 as "the first microprocessor in the world with
155 embedded PCI".
156
157config ALPHA_EB66P
158 bool "EB66+"
159 help
160 Later variant of the EB66 board.
161
162config ALPHA_EIGER
163 bool "Eiger"
164 help
165 Apparently an obscure OEM single-board computer based on the
166 Typhoon/Tsunami chipset family. Information on it is scanty.
167
168config ALPHA_JENSEN
169 bool "Jensen"
170 help
171 DEC PC 150 AXP (aka Jensen): This is a very old Digital system - one
172 of the first-generation Alpha systems. A number of these systems
173 seem to be available on the second- hand market. The Jensen is a
174 floor-standing tower system which originally used a 150MHz 21064 It
175 used programmable logic to interface a 486 EISA I/O bridge to the
176 CPU.
177
178config ALPHA_LX164
179 bool "LX164"
180 help
181 A technical overview of this board is available at
182 <http://www.unix-ag.org/Linux-Alpha/Architectures/LX164.html>.
183
184config ALPHA_LYNX
185 bool "Lynx"
186 help
187 AlphaServer 2100A-based systems.
188
189config ALPHA_MARVEL
190 bool "Marvel"
191 help
192 AlphaServer ES47 / ES80 / GS1280 based on EV7.
193
194config ALPHA_MIATA
195 bool "Miata"
196 help
197 The Digital PersonalWorkStation (PWS 433a, 433au, 500a, 500au, 600a,
198 or 600au). There is an Installation HOWTO for this hardware at
199 <http://eijk.homelinux.org/~stefan/miata.html>.
200
201config ALPHA_MIKASA
202 bool "Mikasa"
203 help
204 AlphaServer 1000-based Alpha systems.
205
206config ALPHA_NAUTILUS
207 bool "Nautilus"
208 help
209 Alpha systems based on the AMD 751 & ALI 1543C chipsets.
210
211config ALPHA_NONAME_CH
212 bool "Noname"
213
214config ALPHA_NORITAKE
215 bool "Noritake"
216 help
217 AlphaServer 1000A, AlphaServer 600A, and AlphaServer 800-based
218 systems.
219
220config ALPHA_PC164
221 bool "PC164"
222
223config ALPHA_P2K
224 bool "Platform2000"
225
226config ALPHA_RAWHIDE
227 bool "Rawhide"
228 help
229 AlphaServer 1200, AlphaServer 4000 and AlphaServer 4100 machines.
230 See HOWTO at
231 <http://www.alphalinux.org/docs/rawhide/4100_install.shtml>.
232
233config ALPHA_RUFFIAN
234 bool "Ruffian"
235 help
236 Samsung APC164UX. There is a page on known problems and workarounds
237 at <http://www.alphalinux.org/faq/FAQ-11.html>.
238
239config ALPHA_RX164
240 bool "RX164"
241
242config ALPHA_SX164
243 bool "SX164"
244
245config ALPHA_SABLE
246 bool "Sable"
247 help
248 Digital AlphaServer 2000 and 2100-based systems.
249
250config ALPHA_SHARK
251 bool "Shark"
252
253config ALPHA_TAKARA
254 bool "Takara"
255 help
256 Alpha 11164-based OEM single-board computer.
257
258config ALPHA_TITAN
259 bool "Titan"
260 help
261 AlphaServer ES45/DS25 SMP based on EV68 and Titan chipset.
262
263config ALPHA_WILDFIRE
264 bool "Wildfire"
265 help
266 AlphaServer GS 40/80/160/320 SMP based on the EV67 core.
267
268endchoice
269
270# clear all implied options (don't want default values for those):
271# Most of these machines have ISA slots; not exactly sure which don't,
272# and this doesn't activate hordes of code, so do it always.
273config ISA
274 bool
275 default y
276 help
277 Find out whether you have ISA slots on your motherboard. ISA is the
278 name of a bus system, i.e. the way the CPU talks to the other stuff
279 inside your box. Other bus systems are PCI, EISA, MicroChannel
280 (MCA) or VESA. ISA is an older system, now being displaced by PCI;
281 newer boards don't support it. If you have ISA, say Y, otherwise N.
282
283config PCI
284 bool
285 depends on !ALPHA_JENSEN
286 default y
287 help
288 Find out whether you have a PCI motherboard. PCI is the name of a
289 bus system, i.e. the way the CPU talks to the other stuff inside
290 your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
291 VESA. If you have PCI, say Y, otherwise N.
292
293 The PCI-HOWTO, available from
294 <http://www.tldp.org/docs.html#howto>, contains valuable
295 information about which PCI hardware does work under Linux and which
296 doesn't.
297
298config PCI_DOMAINS
299 bool
300 default y
301
302config ALPHA_CORE_AGP
303 bool
304 depends on ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL
305 default y
306
307config ALPHA_NONAME
308 bool
309 depends on ALPHA_BOOK1 || ALPHA_NONAME_CH
310 default y
311 help
312 The AXPpci33 (aka NoName), is based on the EB66 (includes the Multia
313 UDB). This design was produced by Digital's Technical OEM (TOEM)
314 group. It uses the 21066 processor running at 166MHz or 233MHz. It
315 is a baby-AT size, and runs from a standard PC power supply. It has
316 5 ISA slots and 3 PCI slots (one pair are a shared slot). There are
317 2 versions, with either PS/2 or large DIN connectors for the
318 keyboard.
319
320config ALPHA_EV4
321 bool
322 depends on ALPHA_JENSEN || (ALPHA_SABLE && !ALPHA_GAMMA) || ALPHA_LYNX || ALPHA_NORITAKE && !ALPHA_PRIMO || ALPHA_MIKASA && !ALPHA_PRIMO || ALPHA_CABRIOLET || ALPHA_AVANTI_CH || ALPHA_EB64P_CH || ALPHA_XL || ALPHA_NONAME || ALPHA_EB66 || ALPHA_EB66P || ALPHA_P2K
323 default y if !ALPHA_LYNX
324
325config ALPHA_LCA
326 bool
327 depends on ALPHA_NONAME || ALPHA_EB66 || ALPHA_EB66P || ALPHA_P2K
328 default y
329
330config ALPHA_APECS
331 bool
332 depends on !ALPHA_PRIMO && (ALPHA_NORITAKE || ALPHA_MIKASA) || ALPHA_CABRIOLET || ALPHA_AVANTI_CH || ALPHA_EB64P_CH || ALPHA_XL
333 default y
334
335config ALPHA_EB64P
336 bool
337 depends on ALPHA_CABRIOLET || ALPHA_EB64P_CH
338 default y
339 help
340 Uses 21064 or 21064A and APECs. Has ISA and PCI expansion (3 ISA,
341 2 PCI, one pair are on a shared slot). Supports 36-bit DRAM SIMs.
342 ISA bus generated by Intel SaturnI/O PCI-ISA bridge. On-board SCSI
343 (NCR 810 on PCI) Ethernet (Digital 21040), KBD, MOUSE (PS2 style),
344 SuperI/O (2S, 1P, FD), RTC/NVRAM. Boot ROM is EPROM. PC-AT size.
345 Runs from standard PC power supply.
346
347config ALPHA_EV5
348 bool "EV5 CPU(s) (model 5/xxx)?" if ALPHA_LYNX
349 default y if ALPHA_RX164 || ALPHA_RAWHIDE || ALPHA_MIATA || ALPHA_LX164 || ALPHA_SX164 || ALPHA_RUFFIAN || ALPHA_SABLE && ALPHA_GAMMA || ALPHA_NORITAKE && ALPHA_PRIMO || ALPHA_MIKASA && ALPHA_PRIMO || ALPHA_PC164 || ALPHA_TAKARA || ALPHA_EB164 || ALPHA_ALCOR
350
351config ALPHA_EV4
352 bool
353 default y if ALPHA_LYNX && !ALPHA_EV5
354
355config ALPHA_CIA
356 bool
357 depends on ALPHA_MIATA || ALPHA_LX164 || ALPHA_SX164 || ALPHA_RUFFIAN || ALPHA_NORITAKE && ALPHA_PRIMO || ALPHA_MIKASA && ALPHA_PRIMO || ALPHA_PC164 || ALPHA_TAKARA || ALPHA_EB164 || ALPHA_ALCOR
358 default y
359
360config ALPHA_EV56
361 bool "EV56 CPU (speed >= 366MHz)?" if ALPHA_ALCOR
362 default y if ALPHA_RX164 || ALPHA_MIATA || ALPHA_LX164 || ALPHA_SX164 || ALPHA_RUFFIAN || ALPHA_PC164 || ALPHA_TAKARA
363
364config ALPHA_EV56
365 prompt "EV56 CPU (speed >= 333MHz)?"
366 depends on ALPHA_NORITAKE && ALPHA_PRIMO
367
368config ALPHA_EV56
369 prompt "EV56 CPU (speed >= 400MHz)?"
370 depends on ALPHA_RAWHIDE
371
372config ALPHA_PRIMO
373 bool "EV5 CPU daughtercard (model 5/xxx)?"
374 depends on ALPHA_NORITAKE || ALPHA_MIKASA
375 help
376 Say Y if you have an AS 1000 5/xxx or an AS 1000A 5/xxx.
377
378config ALPHA_GAMMA
379 bool "EV5 CPU(s) (model 5/xxx)?"
380 depends on ALPHA_SABLE
381 help
382 Say Y if you have an AS 2000 5/xxx or an AS 2100 5/xxx.
383
384config ALPHA_GAMMA
385 bool
386 depends on ALPHA_LYNX
387 default y
388
389config ALPHA_T2
390 bool
391 depends on ALPHA_SABLE || ALPHA_LYNX
392 default y
393
394config ALPHA_PYXIS
395 bool
396 depends on ALPHA_MIATA || ALPHA_LX164 || ALPHA_SX164 || ALPHA_RUFFIAN
397 default y
398
399config ALPHA_EV6
400 bool
401 depends on ALPHA_NAUTILUS || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_SHARK || ALPHA_DP264 || ALPHA_EIGER || ALPHA_MARVEL
402 default y
403
404config ALPHA_TSUNAMI
405 bool
406 depends on ALPHA_SHARK || ALPHA_DP264 || ALPHA_EIGER
407 default y
408
409config ALPHA_EV67
410 bool "EV67 (or later) CPU (speed > 600MHz)?" if ALPHA_DP264 || ALPHA_EIGER
411 default y if ALPHA_NAUTILUS || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_SHARK || ALPHA_MARVEL
412 help
413 Is this a machine based on the EV67 core? If in doubt, select N here
414 and the machine will be treated as an EV6.
415
416config ALPHA_EV7
417 bool
418 depends on ALPHA_MARVEL
419 default y
420
421config ALPHA_MCPCIA
422 bool
423 depends on ALPHA_RAWHIDE
424 default y
425
426config ALPHA_POLARIS
427 bool
428 depends on ALPHA_RX164
429 default y
430
431config ALPHA_IRONGATE
432 bool
433 depends on ALPHA_NAUTILUS
434 default y
435
436config ALPHA_AVANTI
437 bool
438 depends on ALPHA_XL || ALPHA_AVANTI_CH
439 default y
440 help
441 Avanti AS 200, AS 205, AS 250, AS 255, AS 300, and AS 400-based
442 Alphas. Info at
443 <http://www.unix-ag.org/Linux-Alpha/Architectures/Avanti.html>.
444
445config ALPHA_BROKEN_IRQ_MASK
446 bool
447 depends on ALPHA_GENERIC || ALPHA_PC164
448 default y
449
450config ALPHA_SRM
451 bool "Use SRM as bootloader" if ALPHA_CABRIOLET || ALPHA_AVANTI_CH || ALPHA_EB64P || ALPHA_PC164 || ALPHA_TAKARA || ALPHA_EB164 || ALPHA_ALCOR || ALPHA_MIATA || ALPHA_LX164 || ALPHA_SX164 || ALPHA_NAUTILUS || ALPHA_NONAME
452 default y if ALPHA_JENSEN || ALPHA_MIKASA || ALPHA_SABLE || ALPHA_LYNX || ALPHA_NORITAKE || ALPHA_DP264 || ALPHA_RAWHIDE || ALPHA_EIGER || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_SHARK || ALPHA_MARVEL
453 ---help---
454 There are two different types of booting firmware on Alphas: SRM,
455 which is command line driven, and ARC, which uses menus and arrow
456 keys. Details about the Linux/Alpha booting process are contained in
457 the Linux/Alpha FAQ, accessible on the WWW from
458 <http://www.alphalinux.org/>.
459
460 The usual way to load Linux on an Alpha machine is to use MILO
461 (a bootloader that lets you pass command line parameters to the
462 kernel just like lilo does for the x86 architecture) which can be
463 loaded either from ARC or can be installed directly as a permanent
464 firmware replacement from floppy (which requires changing a certain
465 jumper on the motherboard). If you want to do either of these, say N
466 here. If MILO doesn't work on your system (true for Jensen
467 motherboards), you can bypass it altogether and boot Linux directly
468 from an SRM console; say Y here in order to do that. Note that you
469 won't be able to boot from an IDE disk using SRM.
470
471 If unsure, say N.
472
473config EISA
474 bool
475 depends on ALPHA_GENERIC || ALPHA_JENSEN || ALPHA_ALCOR || ALPHA_MIKASA || ALPHA_SABLE || ALPHA_LYNX || ALPHA_NORITAKE || ALPHA_RAWHIDE
476 default y
477
478config SMP
479 bool "Symmetric multi-processing support"
480 depends on ALPHA_SABLE || ALPHA_LYNX || ALPHA_RAWHIDE || ALPHA_DP264 || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_GENERIC || ALPHA_SHARK || ALPHA_MARVEL
481 ---help---
482 This enables support for systems with more than one CPU. If you have
483 a system with only one CPU, like most personal computers, say N. If
484 you have a system with more than one CPU, say Y.
485
486 If you say N here, the kernel will run on single and multiprocessor
487 machines, but will use only one CPU of a multiprocessor machine. If
488 you say Y here, the kernel will run on many, but not all,
489 singleprocessor machines. On a singleprocessor machine, the kernel
490 will run faster if you say N here.
491
492 See also the <file:Documentation/smp.txt>, and the SMP-HOWTO
493 available at <http://www.tldp.org/docs.html#howto>.
494
495 If you don't know what to do here, say N.
496
497config HAVE_DEC_LOCK
498 bool
499 depends on SMP
500 default y
501
502config NR_CPUS
503 int "Maximum number of CPUs (2-64)"
504 range 2 64
505 depends on SMP
506 default "64"
507
508config DISCONTIGMEM
509 bool "Discontiguous Memory Support (EXPERIMENTAL)"
510 depends on EXPERIMENTAL
511 help
512 Say Y to upport efficient handling of discontiguous physical memory,
513 for architectures which are either NUMA (Non-Uniform Memory Access)
514 or have huge holes in the physical address space for other reasons.
515 See <file:Documentation/vm/numa> for more.
516
517config NUMA
518 bool "NUMA Support (EXPERIMENTAL)"
519 depends on DISCONTIGMEM
520 help
521 Say Y to compile the kernel to support NUMA (Non-Uniform Memory
522 Access). This option is for configuring high-end multiprocessor
523 server machines. If in doubt, say N.
524
525# LARGE_VMALLOC is racy, if you *really* need it then fix it first
526config ALPHA_LARGE_VMALLOC
527 bool
528 ---help---
529 Process creation and other aspects of virtual memory management can
530 be streamlined if we restrict the kernel to one PGD for all vmalloc
531 allocations. This equates to about 8GB.
532
533 Under normal circumstances, this is so far and above what is needed
534 as to be laughable. However, there are certain applications (such
535 as benchmark-grade in-kernel web serving) that can make use of as
536 much vmalloc space as is available.
537
538 Say N unless you know you need gobs and gobs of vmalloc space.
539
540config VERBOSE_MCHECK
541 bool "Verbose Machine Checks"
542
543config VERBOSE_MCHECK_ON
544 int "Verbose Printing Mode (0=off, 1=on, 2=all)"
545 depends on VERBOSE_MCHECK
546 default 1
547 ---help---
548 This option allows the default printing mode to be set, and then
549 possibly overridden by a boot command argument.
550
551 For example, if one wanted the option of printing verbose
552 machine checks, but wanted the default to be as if verbose
553 machine check printing was turned off, then one would choose
554 the printing mode to be 0. Then, upon reboot, one could add
555 the boot command line "verbose_mcheck=1" to get the normal
556 verbose machine check printing, or "verbose_mcheck=2" to get
557 the maximum information available.
558
559 Take the default (1) unless you want more control or more info.
560
561source "drivers/pci/Kconfig"
562source "drivers/eisa/Kconfig"
563
564source "drivers/pcmcia/Kconfig"
565
566config SRM_ENV
567 tristate "SRM environment through procfs"
568 depends on PROC_FS
569 ---help---
570 If you enable this option, a subdirectory inside /proc called
571 /proc/srm_environment will give you access to the all important
572 SRM environment variables (those which have a name) and also
573 to all others (by their internal number).
574
575 SRM is something like a BIOS for Alpha machines. There are some
576 other such BIOSes, like AlphaBIOS, which this driver cannot
577 support (hey, that's not SRM!).
578
579 Despite the fact that this driver doesn't work on all Alphas (but
580 only on those which have SRM as their firmware), it's save to
581 build it even if your particular machine doesn't know about SRM
582 (or if you intend to compile a generic kernel). It will simply
583 not create those subdirectory in /proc (and give you some warning,
584 of course).
585
586 This driver is also available as a module and will be called
587 srm_env then.
588
589source "fs/Kconfig.binfmt"
590
591endmenu
592
593source "drivers/Kconfig"
594
595source "fs/Kconfig"
596
597source "arch/alpha/oprofile/Kconfig"
598
599source "arch/alpha/Kconfig.debug"
600
601source "security/Kconfig"
602
603source "crypto/Kconfig"
604
605source "lib/Kconfig"
606
diff --git a/arch/alpha/Kconfig.debug b/arch/alpha/Kconfig.debug
new file mode 100644
index 000000000000..36d0106c32eb
--- /dev/null
+++ b/arch/alpha/Kconfig.debug
@@ -0,0 +1,59 @@
1menu "Kernel hacking"
2
3source "lib/Kconfig.debug"
4
5config EARLY_PRINTK
6 bool
7 depends on ALPHA_GENERIC || ALPHA_SRM
8 default y
9
10config DEBUG_RWLOCK
11 bool "Read-write spinlock debugging"
12 depends on DEBUG_KERNEL
13 help
14 If you say Y here then read-write lock processing will count how many
15 times it has tried to get the lock and issue an error message after
16 too many attempts. If you suspect a rwlock problem or a kernel
17 hacker asks for this option then say Y. Otherwise say N.
18
19config DEBUG_SEMAPHORE
20 bool "Semaphore debugging"
21 depends on DEBUG_KERNEL
22 help
23 If you say Y here then semaphore processing will issue lots of
24 verbose debugging messages. If you suspect a semaphore problem or a
25 kernel hacker asks for this option then say Y. Otherwise say N.
26
27config ALPHA_LEGACY_START_ADDRESS
28 bool "Legacy kernel start address"
29 depends on ALPHA_GENERIC
30 default n
31 ---help---
32 The 2.4 kernel changed the kernel start address from 0x310000
33 to 0x810000 to make room for the Wildfire's larger SRM console.
34 Recent consoles on Titan and Marvel machines also require the
35 extra room.
36
37 If you're using aboot 0.7 or later, the bootloader will examine the
38 ELF headers to determine where to transfer control. Unfortunately,
39 most older bootloaders -- APB or MILO -- hardcoded the kernel start
40 address rather than examining the ELF headers, and the result is a
41 hard lockup.
42
43 Say Y if you have a broken bootloader. Say N if you do not, or if
44 you wish to run on Wildfire, Titan, or Marvel.
45
46config ALPHA_LEGACY_START_ADDRESS
47 bool
48 depends on !ALPHA_GENERIC && !ALPHA_TITAN && !ALPHA_MARVEL && !ALPHA_WILDFIRE
49 default y
50
51config MATHEMU
52 tristate "Kernel FP software completion" if DEBUG_KERNEL && !SMP
53 default y if !DEBUG_KERNEL || SMP
54 help
55 This option is required for IEEE compliant floating point arithmetic
56 on the Alpha. The only time you would ever not say Y is to say M in
57 order to debug the code. Say Y unless you know what you are doing.
58
59endmenu
diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile
new file mode 100644
index 000000000000..22ebfb2be0e4
--- /dev/null
+++ b/arch/alpha/Makefile
@@ -0,0 +1,130 @@
1#
2# alpha/Makefile
3#
4# This file is subject to the terms and conditions of the GNU General Public
5# License. See the file "COPYING" in the main directory of this archive
6# for more details.
7#
8# Copyright (C) 1994 by Linus Torvalds
9#
10
11NM := $(NM) -B
12
13LDFLAGS_vmlinux := -static -N #-relax
14CHECKFLAGS += -D__alpha__ -m64
15cflags-y := -pipe -mno-fp-regs -ffixed-8
16
17# Determine if we can use the BWX instructions with GAS.
18old_gas := $(shell if $(AS) --version 2>&1 | grep 'version 2.7' > /dev/null; then echo y; else echo n; fi)
19
20ifeq ($(old_gas),y)
21$(error The assembler '$(AS)' does not support the BWX instruction)
22endif
23
24# Determine if GCC understands the -mcpu= option.
25have_mcpu := $(call cc-option-yn, -mcpu=ev5)
26have_mcpu_pca56 := $(call cc-option-yn, -mcpu=pca56)
27have_mcpu_ev6 := $(call cc-option-yn, -mcpu=ev6)
28have_mcpu_ev67 := $(call cc-option-yn, -mcpu=ev67)
29have_msmall_data := $(call cc-option-yn, -msmall-data)
30
31cflags-$(have_msmall_data) += -msmall-data
32
33# Turn on the proper cpu optimizations.
34ifeq ($(have_mcpu),y)
35 mcpu_done := n
36 # If GENERIC, make sure to turn off any instruction set extensions that
37 # the host compiler might have on by default. Given that EV4 and EV5
38 # have the same instruction set, prefer EV5 because an EV5 schedule is
39 # more likely to keep an EV4 processor busy than vice-versa.
40 ifeq ($(CONFIG_ALPHA_GENERIC),y)
41 mcpu := ev5
42 mcpu_done := y
43 endif
44 ifeq ($(mcpu_done)$(CONFIG_ALPHA_SX164)$(have_mcpu_pca56),nyy)
45 mcpu := pca56
46 mcpu_done := y
47 endif
48 ifeq ($(mcpu_done)$(CONFIG_ALPHA_POLARIS)$(have_mcpu_pca56),nyy)
49 mcpu := pca56
50 mcpu_done := y
51 endif
52 ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV4),ny)
53 mcpu := ev4
54 mcpu_done := y
55 endif
56 ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV56),ny)
57 mcpu := ev56
58 mcpu_done := y
59 endif
60 ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV5),ny)
61 mcpu := ev5
62 mcpu_done := y
63 endif
64 ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV67)$(have_mcpu_ev67),nyy)
65 mcpu := ev67
66 mcpu_done := y
67 endif
68 ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV6),ny)
69 ifeq ($(have_mcpu_ev6),y)
70 mcpu := ev6
71 else
72 ifeq ($(have_mcpu_pca56),y)
73 mcpu := pca56
74 else
75 mcpu=ev56
76 endif
77 endif
78 mcpu_done := y
79 endif
80 cflags-$(mcpu_done) += -mcpu=$(mcpu)
81endif
82
83
84# For TSUNAMI, we must have the assembler not emulate our instructions.
85# The same is true for IRONGATE, POLARIS, PYXIS.
86# BWX is most important, but we don't really want any emulation ever.
87CFLAGS += $(cflags-y) -Wa,-mev6
88
89head-y := arch/alpha/kernel/head.o
90
91core-y += arch/alpha/kernel/ arch/alpha/mm/
92core-$(CONFIG_MATHEMU) += arch/alpha/math-emu/
93drivers-$(CONFIG_OPROFILE) += arch/alpha/oprofile/
94libs-y += arch/alpha/lib/
95
96# export what is needed by arch/alpha/boot/Makefile
97LIBS_Y := $(patsubst %/, %/lib.a, $(libs-y))
98export LIBS_Y
99
100boot := arch/alpha/boot
101
102#Default target when executing make with no arguments
103all boot: $(boot)/vmlinux.gz
104
105$(boot)/vmlinux.gz: vmlinux
106 $(Q)$(MAKE) $(build)=$(boot) $@
107
108bootimage bootpfile bootpzfile: vmlinux
109 $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
110
111
112prepare: include/asm-$(ARCH)/asm_offsets.h
113
114arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
115 include/config/MARKER
116
117include/asm-$(ARCH)/asm_offsets.h: arch/$(ARCH)/kernel/asm-offsets.s
118 $(call filechk,gen-asm-offsets)
119
120archclean:
121 $(Q)$(MAKE) $(clean)=$(boot)
122
123CLEAN_FILES += include/asm-$(ARCH)/asm_offsets.h
124
125define archhelp
126 echo '* boot - Compressed kernel image (arch/alpha/boot/vmlinux.gz)'
127 echo ' bootimage - SRM bootable image (arch/alpha/boot/bootimage)'
128 echo ' bootpfile - BOOTP bootable image (arch/alpha/boot/bootpfile)'
129 echo ' bootpzfile - compressed kernel BOOTP image (arch/alpha/boot/bootpzfile)'
130endef
diff --git a/arch/alpha/boot/Makefile b/arch/alpha/boot/Makefile
new file mode 100644
index 000000000000..e1ae14cd2b4e
--- /dev/null
+++ b/arch/alpha/boot/Makefile
@@ -0,0 +1,116 @@
1#
2# arch/alpha/boot/Makefile
3#
4# This file is subject to the terms and conditions of the GNU General Public
5# License. See the file "COPYING" in the main directory of this archive
6# for more details.
7#
8# Copyright (C) 1994 by Linus Torvalds
9#
10
11hostprogs-y := tools/mkbb tools/objstrip
12targets := vmlinux.gz vmlinux \
13 vmlinux.nh tools/lxboot tools/bootlx tools/bootph \
14 tools/bootpzh bootloader bootpheader bootpzheader
15OBJSTRIP := $(obj)/tools/objstrip
16
17# SRM bootable image. Copy to offset 512 of a partition.
18$(obj)/bootimage: $(addprefix $(obj)/tools/,mkbb lxboot bootlx) $(obj)/vmlinux.nh
19 ( cat $(obj)/tools/lxboot $(obj)/tools/bootlx $(obj)/vmlinux.nh ) > $@
20 $(obj)/tools/mkbb $@ $(obj)/tools/lxboot
21 @echo ' Bootimage $@ is ready'
22
23# BOOTP bootable image. Define INITRD during make to append initrd image.
24$(obj)/bootpfile: $(obj)/tools/bootph $(obj)/vmlinux.nh
25 cat $(obj)/tools/bootph $(obj)/vmlinux.nh > $@
26ifdef INITRD
27 cat $(INITRD) >> $@
28endif
29
30# Compressed kernel BOOTP bootable image.
31# Define INITRD during make to append initrd image.
32$(obj)/bootpzfile: $(obj)/tools/bootpzh $(obj)/vmlinux.nh.gz
33 cat $(obj)/tools/bootpzh $(obj)/vmlinux.nh.gz > $@
34ifdef INITRD
35 cat $(INITRD) >> $@
36endif
37
38# Compressed kernel image
39$(obj)/vmlinux.gz: $(obj)/vmlinux FORCE
40 $(call if_changed,gzip)
41 @echo ' Kernel $@ is ready'
42
43$(obj)/main.o: $(obj)/ksize.h
44$(obj)/bootp.o: $(obj)/ksize.h
45$(obj)/bootpz.o: $(obj)/kzsize.h
46
47$(obj)/ksize.h: $(obj)/vmlinux.nh FORCE
48 echo "#define KERNEL_SIZE `ls -l $(obj)/vmlinux.nh | awk '{print $$5}'`" > $@T
49ifdef INITRD
50 [ -f $(INITRD) ] || exit 1
51 echo "#define INITRD_IMAGE_SIZE `ls -l $(INITRD) | awk '{print $$5}'`" >> $@T
52endif
53 cmp -s $@T $@ || mv -f $@T $@
54 rm -f $@T
55
56$(obj)/kzsize.h: $(obj)/vmlinux.nh.gz FORCE
57 echo "#define KERNEL_SIZE `ls -l $(obj)/vmlinux.nh | awk '{print $$5}'`" > $@T
58 echo "#define KERNEL_Z_SIZE `ls -l $(obj)/vmlinux.nh.gz | awk '{print $$5}'`" >> $@T
59ifdef INITRD
60 [ -f $(INITRD) ] || exit 1
61 echo "#define INITRD_IMAGE_SIZE `ls -l $(INITRD) | awk '{print $$5}'`" >> $@T
62endif
63 cmp -s $@T $@ || mv -f $@T $@
64 rm -f $@T
65
66quiet_cmd_strip = STRIP $@
67 cmd_strip = $(STRIP) -o $@ $<
68
69$(obj)/vmlinux: vmlinux FORCE
70 $(call if_changed,strip)
71
72quiet_cmd_objstrip = OBJSTRIP $@
73 cmd_objstrip = $(OBJSTRIP) $(OSFLAGS_$(@F)) $< $@
74
75OSFLAGS_vmlinux.nh := -v
76OSFLAGS_lxboot := -p
77OSFLAGS_bootlx := -vb
78OSFLAGS_bootph := -vb
79OSFLAGS_bootpzh := -vb
80
81$(obj)/vmlinux.nh: vmlinux $(OBJSTRIP) FORCE
82 $(call if_changed,objstrip)
83
84$(obj)/vmlinux.nh.gz: $(obj)/vmlinux.nh FORCE
85 $(call if_changed,gzip)
86
87$(obj)/tools/lxboot: $(obj)/bootloader $(OBJSTRIP) FORCE
88 $(call if_changed,objstrip)
89
90$(obj)/tools/bootlx: $(obj)/bootloader $(OBJSTRIP) FORCE
91 $(call if_changed,objstrip)
92
93$(obj)/tools/bootph: $(obj)/bootpheader $(OBJSTRIP) FORCE
94 $(call if_changed,objstrip)
95
96$(obj)/tools/bootpzh: $(obj)/bootpzheader $(OBJSTRIP) FORCE
97 $(call if_changed,objstrip)
98
99LDFLAGS_bootloader := -static -uvsprintf -T #-N -relax
100LDFLAGS_bootpheader := -static -uvsprintf -T #-N -relax
101LDFLAGS_bootpzheader := -static -uvsprintf -T #-N -relax
102
103OBJ_bootlx := $(obj)/head.o $(obj)/main.o
104OBJ_bootph := $(obj)/head.o $(obj)/bootp.o
105OBJ_bootpzh := $(obj)/head.o $(obj)/bootpz.o $(obj)/misc.o
106
107$(obj)/bootloader: $(obj)/bootloader.lds $(OBJ_bootlx) FORCE
108 $(call if_changed,ld)
109
110$(obj)/bootpheader: $(obj)/bootloader.lds $(OBJ_bootph) $(LIBS_Y) FORCE
111 $(call if_changed,ld)
112
113$(obj)/bootpzheader: $(obj)/bootloader.lds $(OBJ_bootpzh) $(LIBS_Y) FORCE
114 $(call if_changed,ld)
115
116$(obj)/misc.o: lib/inflate.c
diff --git a/arch/alpha/boot/bootloader.lds b/arch/alpha/boot/bootloader.lds
new file mode 100644
index 000000000000..31c081ce1d50
--- /dev/null
+++ b/arch/alpha/boot/bootloader.lds
@@ -0,0 +1,24 @@
1OUTPUT_FORMAT("elf64-alpha")
2ENTRY(__start)
3printk = srm_printk;
4SECTIONS
5{
6 . = 0x20000000;
7 .text : { *(.text) }
8 _etext = .;
9 PROVIDE (etext = .);
10 .rodata : { *(.rodata) *(.rodata.*) }
11 .data : { *(.data) CONSTRUCTORS }
12 .got : { *(.got) }
13 .sdata : { *(.sdata) }
14 _edata = .;
15 PROVIDE (edata = .);
16 .sbss : { *(.sbss) *(.scommon) }
17 .bss : { *(.bss) *(COMMON) }
18 _end = . ;
19 PROVIDE (end = .);
20
21 .mdebug 0 : { *(.mdebug) }
22 .note 0 : { *(.note) }
23 .comment 0 : { *(.comment) }
24}
diff --git a/arch/alpha/boot/bootp.c b/arch/alpha/boot/bootp.c
new file mode 100644
index 000000000000..ec53c28e33de
--- /dev/null
+++ b/arch/alpha/boot/bootp.c
@@ -0,0 +1,214 @@
1/*
2 * arch/alpha/boot/bootp.c
3 *
4 * Copyright (C) 1997 Jay Estabrook
5 *
6 * This file is used for creating a bootp file for the Linux/AXP kernel
7 *
8 * based significantly on the arch/alpha/boot/main.c of Linus Torvalds
9 */
10#include <linux/kernel.h>
11#include <linux/string.h>
12#include <linux/version.h>
13#include <linux/mm.h>
14
15#include <asm/system.h>
16#include <asm/console.h>
17#include <asm/hwrpb.h>
18#include <asm/pgtable.h>
19#include <asm/io.h>
20
21#include <stdarg.h>
22
23#include "ksize.h"
24
25extern unsigned long switch_to_osf_pal(unsigned long nr,
26 struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
27 unsigned long *vptb);
28
29extern void move_stack(unsigned long new_stack);
30
31struct hwrpb_struct *hwrpb = INIT_HWRPB;
32static struct pcb_struct pcb_va[1];
33
34/*
35 * Find a physical address of a virtual object..
36 *
37 * This is easy using the virtual page table address.
38 */
39
40static inline void *
41find_pa(unsigned long *vptb, void *ptr)
42{
43 unsigned long address = (unsigned long) ptr;
44 unsigned long result;
45
46 result = vptb[address >> 13];
47 result >>= 32;
48 result <<= 13;
49 result |= address & 0x1fff;
50 return (void *) result;
51}
52
53/*
54 * This function moves into OSF/1 pal-code, and has a temporary
55 * PCB for that. The kernel proper should replace this PCB with
56 * the real one as soon as possible.
57 *
58 * The page table muckery in here depends on the fact that the boot
59 * code has the L1 page table identity-map itself in the second PTE
60 * in the L1 page table. Thus the L1-page is virtually addressable
61 * itself (through three levels) at virtual address 0x200802000.
62 */
63
64#define VPTB ((unsigned long *) 0x200000000)
65#define L1 ((unsigned long *) 0x200802000)
66
67void
68pal_init(void)
69{
70 unsigned long i, rev;
71 struct percpu_struct * percpu;
72 struct pcb_struct * pcb_pa;
73
74 /* Create the dummy PCB. */
75 pcb_va->ksp = 0;
76 pcb_va->usp = 0;
77 pcb_va->ptbr = L1[1] >> 32;
78 pcb_va->asn = 0;
79 pcb_va->pcc = 0;
80 pcb_va->unique = 0;
81 pcb_va->flags = 1;
82 pcb_va->res1 = 0;
83 pcb_va->res2 = 0;
84 pcb_pa = find_pa(VPTB, pcb_va);
85
86 /*
87 * a0 = 2 (OSF)
88 * a1 = return address, but we give the asm the vaddr of the PCB
89 * a2 = physical addr of PCB
90 * a3 = new virtual page table pointer
91 * a4 = KSP (but the asm sets it)
92 */
93 srm_printk("Switching to OSF PAL-code .. ");
94
95 i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB);
96 if (i) {
97 srm_printk("failed, code %ld\n", i);
98 __halt();
99 }
100
101 percpu = (struct percpu_struct *)
102 (INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB);
103 rev = percpu->pal_revision = percpu->palcode_avail[2];
104
105 srm_printk("Ok (rev %lx)\n", rev);
106
107 tbia(); /* do it directly in case we are SMP */
108}
109
110static inline void
111load(unsigned long dst, unsigned long src, unsigned long count)
112{
113 memcpy((void *)dst, (void *)src, count);
114}
115
116/*
117 * Start the kernel.
118 */
119static inline void
120runkernel(void)
121{
122 __asm__ __volatile__(
123 "bis %0,%0,$27\n\t"
124 "jmp ($27)"
125 : /* no outputs: it doesn't even return */
126 : "r" (START_ADDR));
127}
128
129extern char _end;
130#define KERNEL_ORIGIN \
131 ((((unsigned long)&_end) + 511) & ~511)
132
133void
134start_kernel(void)
135{
136 /*
137 * Note that this crufty stuff with static and envval
138 * and envbuf is because:
139 *
140 * 1. Frequently, the stack is short, and we don't want to overrun;
141 * 2. Frequently the stack is where we are going to copy the kernel to;
142 * 3. A certain SRM console required the GET_ENV output to stack.
143 * ??? A comment in the aboot sources indicates that the GET_ENV
144 * destination must be quadword aligned. Might this explain the
145 * behaviour, rather than requiring output to the stack, which
146 * seems rather far-fetched.
147 */
148 static long nbytes;
149 static char envval[256] __attribute__((aligned(8)));
150 static unsigned long initrd_start;
151
152 srm_printk("Linux/AXP bootp loader for Linux " UTS_RELEASE "\n");
153 if (INIT_HWRPB->pagesize != 8192) {
154 srm_printk("Expected 8kB pages, got %ldkB\n",
155 INIT_HWRPB->pagesize >> 10);
156 return;
157 }
158 if (INIT_HWRPB->vptb != (unsigned long) VPTB) {
159 srm_printk("Expected vptb at %p, got %p\n",
160 VPTB, (void *)INIT_HWRPB->vptb);
161 return;
162 }
163 pal_init();
164
165 /* The initrd must be page-aligned. See below for the
166 cause of the magic number 5. */
167 initrd_start = ((START_ADDR + 5*KERNEL_SIZE + PAGE_SIZE) |
168 (PAGE_SIZE-1)) + 1;
169#ifdef INITRD_IMAGE_SIZE
170 srm_printk("Initrd positioned at %#lx\n", initrd_start);
171#endif
172
173 /*
174 * Move the stack to a safe place to ensure it won't be
175 * overwritten by kernel image.
176 */
177 move_stack(initrd_start - PAGE_SIZE);
178
179 nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
180 if (nbytes < 0 || nbytes >= sizeof(envval)) {
181 nbytes = 0;
182 }
183 envval[nbytes] = '\0';
184 srm_printk("Loading the kernel...'%s'\n", envval);
185
186 /* NOTE: *no* callbacks or printouts from here on out!!! */
187
188 /* This is a hack, as some consoles seem to get virtual 20000000 (ie
189 * where the SRM console puts the kernel bootp image) memory
190 * overlapping physical memory where the kernel wants to be put,
191 * which causes real problems when attempting to copy the former to
192 * the latter... :-(
193 *
194 * So, we first move the kernel virtual-to-physical way above where
195 * we physically want the kernel to end up, then copy it from there
196 * to its final resting place... ;-}
197 *
198 * Sigh... */
199
200#ifdef INITRD_IMAGE_SIZE
201 load(initrd_start, KERNEL_ORIGIN+KERNEL_SIZE, INITRD_IMAGE_SIZE);
202#endif
203 load(START_ADDR+(4*KERNEL_SIZE), KERNEL_ORIGIN, KERNEL_SIZE);
204 load(START_ADDR, START_ADDR+(4*KERNEL_SIZE), KERNEL_SIZE);
205
206 memset((char*)ZERO_PGE, 0, PAGE_SIZE);
207 strcpy((char*)ZERO_PGE, envval);
208#ifdef INITRD_IMAGE_SIZE
209 ((long *)(ZERO_PGE+256))[0] = initrd_start;
210 ((long *)(ZERO_PGE+256))[1] = INITRD_IMAGE_SIZE;
211#endif
212
213 runkernel();
214}
diff --git a/arch/alpha/boot/bootpz.c b/arch/alpha/boot/bootpz.c
new file mode 100644
index 000000000000..a6657f2cf9bd
--- /dev/null
+++ b/arch/alpha/boot/bootpz.c
@@ -0,0 +1,469 @@
1/*
2 * arch/alpha/boot/bootpz.c
3 *
4 * Copyright (C) 1997 Jay Estabrook
5 *
6 * This file is used for creating a compressed BOOTP file for the
7 * Linux/AXP kernel
8 *
9 * based significantly on the arch/alpha/boot/main.c of Linus Torvalds
10 * and the decompression code from MILO.
11 */
12#include <linux/kernel.h>
13#include <linux/string.h>
14#include <linux/version.h>
15#include <linux/mm.h>
16
17#include <asm/system.h>
18#include <asm/console.h>
19#include <asm/hwrpb.h>
20#include <asm/pgtable.h>
21#include <asm/io.h>
22
23#include <stdarg.h>
24
25#include "kzsize.h"
26
27/* FIXME FIXME FIXME */
28#define MALLOC_AREA_SIZE 0x200000 /* 2MB for now */
29/* FIXME FIXME FIXME */
30
31
32/*
33 WARNING NOTE
34
35 It is very possible that turning on additional messages may cause
36 kernel image corruption due to stack usage to do the printing.
37
38*/
39
40#undef DEBUG_CHECK_RANGE
41#undef DEBUG_ADDRESSES
42#undef DEBUG_LAST_STEPS
43
44extern unsigned long switch_to_osf_pal(unsigned long nr,
45 struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
46 unsigned long *vptb);
47
48extern int decompress_kernel(void* destination, void *source,
49 size_t ksize, size_t kzsize);
50
51extern void move_stack(unsigned long new_stack);
52
53struct hwrpb_struct *hwrpb = INIT_HWRPB;
54static struct pcb_struct pcb_va[1];
55
56/*
57 * Find a physical address of a virtual object..
58 *
59 * This is easy using the virtual page table address.
60 */
61#define VPTB ((unsigned long *) 0x200000000)
62
63static inline unsigned long
64find_pa(unsigned long address)
65{
66 unsigned long result;
67
68 result = VPTB[address >> 13];
69 result >>= 32;
70 result <<= 13;
71 result |= address & 0x1fff;
72 return result;
73}
74
75int
76check_range(unsigned long vstart, unsigned long vend,
77 unsigned long kstart, unsigned long kend)
78{
79 unsigned long vaddr, kaddr;
80
81#ifdef DEBUG_CHECK_RANGE
82 srm_printk("check_range: V[0x%lx:0x%lx] K[0x%lx:0x%lx]\n",
83 vstart, vend, kstart, kend);
84#endif
85 /* do some range checking for detecting an overlap... */
86 for (vaddr = vstart; vaddr <= vend; vaddr += PAGE_SIZE)
87 {
88 kaddr = (find_pa(vaddr) | PAGE_OFFSET);
89 if (kaddr >= kstart && kaddr <= kend)
90 {
91#ifdef DEBUG_CHECK_RANGE
92 srm_printk("OVERLAP: vaddr 0x%lx kaddr 0x%lx"
93 " [0x%lx:0x%lx]\n",
94 vaddr, kaddr, kstart, kend);
95#endif
96 return 1;
97 }
98 }
99 return 0;
100}
101
102/*
103 * This function moves into OSF/1 pal-code, and has a temporary
104 * PCB for that. The kernel proper should replace this PCB with
105 * the real one as soon as possible.
106 *
107 * The page table muckery in here depends on the fact that the boot
108 * code has the L1 page table identity-map itself in the second PTE
109 * in the L1 page table. Thus the L1-page is virtually addressable
110 * itself (through three levels) at virtual address 0x200802000.
111 */
112
113#define L1 ((unsigned long *) 0x200802000)
114
115void
116pal_init(void)
117{
118 unsigned long i, rev;
119 struct percpu_struct * percpu;
120 struct pcb_struct * pcb_pa;
121
122 /* Create the dummy PCB. */
123 pcb_va->ksp = 0;
124 pcb_va->usp = 0;
125 pcb_va->ptbr = L1[1] >> 32;
126 pcb_va->asn = 0;
127 pcb_va->pcc = 0;
128 pcb_va->unique = 0;
129 pcb_va->flags = 1;
130 pcb_va->res1 = 0;
131 pcb_va->res2 = 0;
132 pcb_pa = (struct pcb_struct *)find_pa((unsigned long)pcb_va);
133
134 /*
135 * a0 = 2 (OSF)
136 * a1 = return address, but we give the asm the vaddr of the PCB
137 * a2 = physical addr of PCB
138 * a3 = new virtual page table pointer
139 * a4 = KSP (but the asm sets it)
140 */
141 srm_printk("Switching to OSF PAL-code... ");
142
143 i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB);
144 if (i) {
145 srm_printk("failed, code %ld\n", i);
146 __halt();
147 }
148
149 percpu = (struct percpu_struct *)
150 (INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB);
151 rev = percpu->pal_revision = percpu->palcode_avail[2];
152
153 srm_printk("OK (rev %lx)\n", rev);
154
155 tbia(); /* do it directly in case we are SMP */
156}
157
158/*
159 * Start the kernel.
160 */
161static inline void
162runkernel(void)
163{
164 __asm__ __volatile__(
165 "bis %0,%0,$27\n\t"
166 "jmp ($27)"
167 : /* no outputs: it doesn't even return */
168 : "r" (START_ADDR));
169}
170
171/* Must record the SP (it is virtual) on entry, so we can make sure
172 not to overwrite it during movement or decompression. */
173unsigned long SP_on_entry;
174
175/* Calculate the kernel image address based on the end of the BOOTP
176 bootstrapper (ie this program).
177*/
178extern char _end;
179#define KERNEL_ORIGIN \
180 ((((unsigned long)&_end) + 511) & ~511)
181
182/* Round address to next higher page boundary. */
183#define NEXT_PAGE(a) (((a) | (PAGE_SIZE - 1)) + 1)
184
185#ifdef INITRD_IMAGE_SIZE
186# define REAL_INITRD_SIZE INITRD_IMAGE_SIZE
187#else
188# define REAL_INITRD_SIZE 0
189#endif
190
191/* Defines from include/asm-alpha/system.h
192
193 BOOT_ADDR Virtual address at which the consoles loads
194 the BOOTP image.
195
196 KERNEL_START KSEG address at which the kernel is built to run,
197 which includes some initial data pages before the
198 code.
199
200 START_ADDR KSEG address of the entry point of kernel code.
201
202 ZERO_PGE KSEG address of page full of zeroes, but
203 upon entry to kerne cvan be expected
204 to hold the parameter list and possible
205 INTRD information.
206
207 These are used in the local defines below.
208*/
209
210
211/* Virtual addresses for the BOOTP image. Note that this includes the
212 bootstrapper code as well as the compressed kernel image, and
213 possibly the INITRD image.
214
215 Oh, and do NOT forget the STACK, which appears to be placed virtually
216 beyond the end of the loaded image.
217*/
218#define V_BOOT_IMAGE_START BOOT_ADDR
219#define V_BOOT_IMAGE_END SP_on_entry
220
221/* Virtual addresses for just the bootstrapper part of the BOOTP image. */
222#define V_BOOTSTRAPPER_START BOOT_ADDR
223#define V_BOOTSTRAPPER_END KERNEL_ORIGIN
224
225/* Virtual addresses for just the data part of the BOOTP
226 image. This may also include the INITRD image, but always
227 includes the STACK.
228*/
229#define V_DATA_START KERNEL_ORIGIN
230#define V_INITRD_START (KERNEL_ORIGIN + KERNEL_Z_SIZE)
231#define V_INTRD_END (V_INITRD_START + REAL_INITRD_SIZE)
232#define V_DATA_END V_BOOT_IMAGE_END
233
234/* KSEG addresses for the uncompressed kernel.
235
236 Note that the end address includes workspace for the decompression.
237 Note also that the DATA_START address is ZERO_PGE, to which we write
238 just before jumping to the kernel image at START_ADDR.
239 */
240#define K_KERNEL_DATA_START ZERO_PGE
241#define K_KERNEL_IMAGE_START START_ADDR
242#define K_KERNEL_IMAGE_END (START_ADDR + KERNEL_SIZE)
243
244/* Define to where we may have to decompress the kernel image, before
245 we move it to the final position, in case of overlap. This will be
246 above the final position of the kernel.
247
248 Regardless of overlap, we move the INITRD image to the end of this
249 copy area, because there needs to be a buffer area after the kernel
250 for "bootmem" anyway.
251*/
252#define K_COPY_IMAGE_START NEXT_PAGE(K_KERNEL_IMAGE_END)
253/* Reserve one page below INITRD for the new stack. */
254#define K_INITRD_START \
255 NEXT_PAGE(K_COPY_IMAGE_START + KERNEL_SIZE + PAGE_SIZE)
256#define K_COPY_IMAGE_END \
257 (K_INITRD_START + REAL_INITRD_SIZE + MALLOC_AREA_SIZE)
258#define K_COPY_IMAGE_SIZE \
259 NEXT_PAGE(K_COPY_IMAGE_END - K_COPY_IMAGE_START)
260
261void
262start_kernel(void)
263{
264 int must_move = 0;
265
266 /* Initialize these for the decompression-in-place situation,
267 which is the smallest amount of work and most likely to
268 occur when using the normal START_ADDR of the kernel
269 (currently set to 16MB, to clear all console code.
270 */
271 unsigned long uncompressed_image_start = K_KERNEL_IMAGE_START;
272 unsigned long uncompressed_image_end = K_KERNEL_IMAGE_END;
273
274 unsigned long initrd_image_start = K_INITRD_START;
275
276 /*
277 * Note that this crufty stuff with static and envval
278 * and envbuf is because:
279 *
280 * 1. Frequently, the stack is short, and we don't want to overrun;
281 * 2. Frequently the stack is where we are going to copy the kernel to;
282 * 3. A certain SRM console required the GET_ENV output to stack.
283 * ??? A comment in the aboot sources indicates that the GET_ENV
284 * destination must be quadword aligned. Might this explain the
285 * behaviour, rather than requiring output to the stack, which
286 * seems rather far-fetched.
287 */
288 static long nbytes;
289 static char envval[256] __attribute__((aligned(8)));
290 register unsigned long asm_sp asm("30");
291
292 SP_on_entry = asm_sp;
293
294 srm_printk("Linux/Alpha BOOTPZ Loader for Linux " UTS_RELEASE "\n");
295
296 /* Validity check the HWRPB. */
297 if (INIT_HWRPB->pagesize != 8192) {
298 srm_printk("Expected 8kB pages, got %ldkB\n",
299 INIT_HWRPB->pagesize >> 10);
300 return;
301 }
302 if (INIT_HWRPB->vptb != (unsigned long) VPTB) {
303 srm_printk("Expected vptb at %p, got %p\n",
304 VPTB, (void *)INIT_HWRPB->vptb);
305 return;
306 }
307
308 /* PALcode (re)initialization. */
309 pal_init();
310
311 /* Get the parameter list from the console environment variable. */
312 nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
313 if (nbytes < 0 || nbytes >= sizeof(envval)) {
314 nbytes = 0;
315 }
316 envval[nbytes] = '\0';
317
318#ifdef DEBUG_ADDRESSES
319 srm_printk("START_ADDR 0x%lx\n", START_ADDR);
320 srm_printk("KERNEL_ORIGIN 0x%lx\n", KERNEL_ORIGIN);
321 srm_printk("KERNEL_SIZE 0x%x\n", KERNEL_SIZE);
322 srm_printk("KERNEL_Z_SIZE 0x%x\n", KERNEL_Z_SIZE);
323#endif
324
325 /* Since all the SRM consoles load the BOOTP image at virtual
326 * 0x20000000, we have to ensure that the physical memory
327 * pages occupied by that image do NOT overlap the physical
328 * address range where the kernel wants to be run. This
329 * causes real problems when attempting to cdecompress the
330 * former into the latter... :-(
331 *
332 * So, we may have to decompress/move the kernel/INITRD image
333 * virtual-to-physical someplace else first before moving
334 * kernel /INITRD to their final resting places... ;-}
335 *
336 * Sigh...
337 */
338
339 /* First, check to see if the range of addresses occupied by
340 the bootstrapper part of the BOOTP image include any of the
341 physical pages into which the kernel will be placed for
342 execution.
343
344 We only need check on the final kernel image range, since we
345 will put the INITRD someplace that we can be sure is not
346 in conflict.
347 */
348 if (check_range(V_BOOTSTRAPPER_START, V_BOOTSTRAPPER_END,
349 K_KERNEL_DATA_START, K_KERNEL_IMAGE_END))
350 {
351 srm_printk("FATAL ERROR: overlap of bootstrapper code\n");
352 __halt();
353 }
354
355 /* Next, check to see if the range of addresses occupied by
356 the compressed kernel/INITRD/stack portion of the BOOTP
357 image include any of the physical pages into which the
358 decompressed kernel or the INITRD will be placed for
359 execution.
360 */
361 if (check_range(V_DATA_START, V_DATA_END,
362 K_KERNEL_IMAGE_START, K_COPY_IMAGE_END))
363 {
364#ifdef DEBUG_ADDRESSES
365 srm_printk("OVERLAP: cannot decompress in place\n");
366#endif
367 uncompressed_image_start = K_COPY_IMAGE_START;
368 uncompressed_image_end = K_COPY_IMAGE_END;
369 must_move = 1;
370
371 /* Finally, check to see if the range of addresses
372 occupied by the compressed kernel/INITRD part of
373 the BOOTP image include any of the physical pages
374 into which that part is to be copied for
375 decompression.
376 */
377 while (check_range(V_DATA_START, V_DATA_END,
378 uncompressed_image_start,
379 uncompressed_image_end))
380 {
381#if 0
382 uncompressed_image_start += K_COPY_IMAGE_SIZE;
383 uncompressed_image_end += K_COPY_IMAGE_SIZE;
384 initrd_image_start += K_COPY_IMAGE_SIZE;
385#else
386 /* Keep as close as possible to end of BOOTP image. */
387 uncompressed_image_start += PAGE_SIZE;
388 uncompressed_image_end += PAGE_SIZE;
389 initrd_image_start += PAGE_SIZE;
390#endif
391 }
392 }
393
394 srm_printk("Starting to load the kernel with args '%s'\n", envval);
395
396#ifdef DEBUG_ADDRESSES
397 srm_printk("Decompressing the kernel...\n"
398 "...from 0x%lx to 0x%lx size 0x%x\n",
399 V_DATA_START,
400 uncompressed_image_start,
401 KERNEL_SIZE);
402#endif
403 decompress_kernel((void *)uncompressed_image_start,
404 (void *)V_DATA_START,
405 KERNEL_SIZE, KERNEL_Z_SIZE);
406
407 /*
408 * Now, move things to their final positions, if/as required.
409 */
410
411#ifdef INITRD_IMAGE_SIZE
412
413 /* First, we always move the INITRD image, if present. */
414#ifdef DEBUG_ADDRESSES
415 srm_printk("Moving the INITRD image...\n"
416 " from 0x%lx to 0x%lx size 0x%x\n",
417 V_INITRD_START,
418 initrd_image_start,
419 INITRD_IMAGE_SIZE);
420#endif
421 memcpy((void *)initrd_image_start, (void *)V_INITRD_START,
422 INITRD_IMAGE_SIZE);
423
424#endif /* INITRD_IMAGE_SIZE */
425
426 /* Next, we may have to move the uncompressed kernel to the
427 final destination.
428 */
429 if (must_move) {
430#ifdef DEBUG_ADDRESSES
431 srm_printk("Moving the uncompressed kernel...\n"
432 "...from 0x%lx to 0x%lx size 0x%x\n",
433 uncompressed_image_start,
434 K_KERNEL_IMAGE_START,
435 (unsigned)KERNEL_SIZE);
436#endif
437 /*
438 * Move the stack to a safe place to ensure it won't be
439 * overwritten by kernel image.
440 */
441 move_stack(initrd_image_start - PAGE_SIZE);
442
443 memcpy((void *)K_KERNEL_IMAGE_START,
444 (void *)uncompressed_image_start, KERNEL_SIZE);
445 }
446
447 /* Clear the zero page, then move the argument list in. */
448#ifdef DEBUG_LAST_STEPS
449 srm_printk("Preparing ZERO_PGE...\n");
450#endif
451 memset((char*)ZERO_PGE, 0, PAGE_SIZE);
452 strcpy((char*)ZERO_PGE, envval);
453
454#ifdef INITRD_IMAGE_SIZE
455
456#ifdef DEBUG_LAST_STEPS
457 srm_printk("Preparing INITRD info...\n");
458#endif
459 /* Finally, set the INITRD paramenters for the kernel. */
460 ((long *)(ZERO_PGE+256))[0] = initrd_image_start;
461 ((long *)(ZERO_PGE+256))[1] = INITRD_IMAGE_SIZE;
462
463#endif /* INITRD_IMAGE_SIZE */
464
465#ifdef DEBUG_LAST_STEPS
466 srm_printk("Doing 'runkernel()'...\n");
467#endif
468 runkernel();
469}
diff --git a/arch/alpha/boot/head.S b/arch/alpha/boot/head.S
new file mode 100644
index 000000000000..f3d98089b3dc
--- /dev/null
+++ b/arch/alpha/boot/head.S
@@ -0,0 +1,123 @@
1/*
2 * arch/alpha/boot/head.S
3 *
4 * initial bootloader stuff..
5 */
6
7#include <asm/system.h>
8
9 .set noreorder
10 .globl __start
11 .ent __start
12__start:
13 br $29,2f
142: ldgp $29,0($29)
15 jsr $26,start_kernel
16 call_pal PAL_halt
17 .end __start
18
19 .align 5
20 .globl wrent
21 .ent wrent
22wrent:
23 .prologue 0
24 call_pal PAL_wrent
25 ret ($26)
26 .end wrent
27
28 .align 5
29 .globl wrkgp
30 .ent wrkgp
31wrkgp:
32 .prologue 0
33 call_pal PAL_wrkgp
34 ret ($26)
35 .end wrkgp
36
37 .align 5
38 .globl switch_to_osf_pal
39 .ent switch_to_osf_pal
40switch_to_osf_pal:
41 subq $30,128,$30
42 .frame $30,128,$26
43 stq $26,0($30)
44 stq $1,8($30)
45 stq $2,16($30)
46 stq $3,24($30)
47 stq $4,32($30)
48 stq $5,40($30)
49 stq $6,48($30)
50 stq $7,56($30)
51 stq $8,64($30)
52 stq $9,72($30)
53 stq $10,80($30)
54 stq $11,88($30)
55 stq $12,96($30)
56 stq $13,104($30)
57 stq $14,112($30)
58 stq $15,120($30)
59 .prologue 0
60
61 stq $30,0($17) /* save KSP in PCB */
62
63 bis $30,$30,$20 /* a4 = KSP */
64 br $17,1f
65
66 ldq $26,0($30)
67 ldq $1,8($30)
68 ldq $2,16($30)
69 ldq $3,24($30)
70 ldq $4,32($30)
71 ldq $5,40($30)
72 ldq $6,48($30)
73 ldq $7,56($30)
74 ldq $8,64($30)
75 ldq $9,72($30)
76 ldq $10,80($30)
77 ldq $11,88($30)
78 ldq $12,96($30)
79 ldq $13,104($30)
80 ldq $14,112($30)
81 ldq $15,120($30)
82 addq $30,128,$30
83 ret ($26)
841: call_pal PAL_swppal
85 .end switch_to_osf_pal
86
87 .align 3
88 .globl tbi
89 .ent tbi
90tbi:
91 .prologue 0
92 call_pal PAL_tbi
93 ret ($26)
94 .end tbi
95
96 .align 3
97 .globl halt
98 .ent halt
99halt:
100 .prologue 0
101 call_pal PAL_halt
102 .end halt
103
104/* $16 - new stack page */
105 .align 3
106 .globl move_stack
107 .ent move_stack
108move_stack:
109 .prologue 0
110 lda $0, 0x1fff($31)
111 and $0, $30, $1 /* Stack offset */
112 or $1, $16, $16 /* New stack pointer */
113 mov $30, $1
114 mov $16, $2
1151: ldq $3, 0($1) /* Move the stack */
116 addq $1, 8, $1
117 stq $3, 0($2)
118 and $0, $1, $4
119 addq $2, 8, $2
120 bne $4, 1b
121 mov $16, $30
122 ret ($26)
123 .end move_stack
diff --git a/arch/alpha/boot/main.c b/arch/alpha/boot/main.c
new file mode 100644
index 000000000000..78c9b0b6eea7
--- /dev/null
+++ b/arch/alpha/boot/main.c
@@ -0,0 +1,191 @@
1/*
2 * arch/alpha/boot/main.c
3 *
4 * Copyright (C) 1994, 1995 Linus Torvalds
5 *
6 * This file is the bootloader for the Linux/AXP kernel
7 */
8#include <linux/kernel.h>
9#include <linux/string.h>
10#include <linux/version.h>
11#include <linux/mm.h>
12
13#include <asm/system.h>
14#include <asm/console.h>
15#include <asm/hwrpb.h>
16#include <asm/pgtable.h>
17
18#include <stdarg.h>
19
20#include "ksize.h"
21
22extern int vsprintf(char *, const char *, va_list);
23extern unsigned long switch_to_osf_pal(unsigned long nr,
24 struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
25 unsigned long *vptb);
26struct hwrpb_struct *hwrpb = INIT_HWRPB;
27static struct pcb_struct pcb_va[1];
28
29/*
30 * Find a physical address of a virtual object..
31 *
32 * This is easy using the virtual page table address.
33 */
34
35static inline void *
36find_pa(unsigned long *vptb, void *ptr)
37{
38 unsigned long address = (unsigned long) ptr;
39 unsigned long result;
40
41 result = vptb[address >> 13];
42 result >>= 32;
43 result <<= 13;
44 result |= address & 0x1fff;
45 return (void *) result;
46}
47
48/*
49 * This function moves into OSF/1 pal-code, and has a temporary
50 * PCB for that. The kernel proper should replace this PCB with
51 * the real one as soon as possible.
52 *
53 * The page table muckery in here depends on the fact that the boot
54 * code has the L1 page table identity-map itself in the second PTE
55 * in the L1 page table. Thus the L1-page is virtually addressable
56 * itself (through three levels) at virtual address 0x200802000.
57 */
58
59#define VPTB ((unsigned long *) 0x200000000)
60#define L1 ((unsigned long *) 0x200802000)
61
62void
63pal_init(void)
64{
65 unsigned long i, rev;
66 struct percpu_struct * percpu;
67 struct pcb_struct * pcb_pa;
68
69 /* Create the dummy PCB. */
70 pcb_va->ksp = 0;
71 pcb_va->usp = 0;
72 pcb_va->ptbr = L1[1] >> 32;
73 pcb_va->asn = 0;
74 pcb_va->pcc = 0;
75 pcb_va->unique = 0;
76 pcb_va->flags = 1;
77 pcb_va->res1 = 0;
78 pcb_va->res2 = 0;
79 pcb_pa = find_pa(VPTB, pcb_va);
80
81 /*
82 * a0 = 2 (OSF)
83 * a1 = return address, but we give the asm the vaddr of the PCB
84 * a2 = physical addr of PCB
85 * a3 = new virtual page table pointer
86 * a4 = KSP (but the asm sets it)
87 */
88 srm_printk("Switching to OSF PAL-code .. ");
89
90 i = switch_to_osf_pal(2, pcb_va, pcb_pa, VPTB);
91 if (i) {
92 srm_printk("failed, code %ld\n", i);
93 __halt();
94 }
95
96 percpu = (struct percpu_struct *)
97 (INIT_HWRPB->processor_offset + (unsigned long) INIT_HWRPB);
98 rev = percpu->pal_revision = percpu->palcode_avail[2];
99
100 srm_printk("Ok (rev %lx)\n", rev);
101
102 tbia(); /* do it directly in case we are SMP */
103}
104
105static inline long openboot(void)
106{
107 char bootdev[256];
108 long result;
109
110 result = callback_getenv(ENV_BOOTED_DEV, bootdev, 255);
111 if (result < 0)
112 return result;
113 return callback_open(bootdev, result & 255);
114}
115
116static inline long close(long dev)
117{
118 return callback_close(dev);
119}
120
121static inline long load(long dev, unsigned long addr, unsigned long count)
122{
123 char bootfile[256];
124 extern char _end;
125 long result, boot_size = &_end - (char *) BOOT_ADDR;
126
127 result = callback_getenv(ENV_BOOTED_FILE, bootfile, 255);
128 if (result < 0)
129 return result;
130 result &= 255;
131 bootfile[result] = '\0';
132 if (result)
133 srm_printk("Boot file specification (%s) not implemented\n",
134 bootfile);
135 return callback_read(dev, count, addr, boot_size/512 + 1);
136}
137
138/*
139 * Start the kernel.
140 */
141static void runkernel(void)
142{
143 __asm__ __volatile__(
144 "bis %1,%1,$30\n\t"
145 "bis %0,%0,$26\n\t"
146 "ret ($26)"
147 : /* no outputs: it doesn't even return */
148 : "r" (START_ADDR),
149 "r" (PAGE_SIZE + INIT_STACK));
150}
151
152void start_kernel(void)
153{
154 long i;
155 long dev;
156 int nbytes;
157 char envval[256];
158
159 srm_printk("Linux/AXP bootloader for Linux " UTS_RELEASE "\n");
160 if (INIT_HWRPB->pagesize != 8192) {
161 srm_printk("Expected 8kB pages, got %ldkB\n", INIT_HWRPB->pagesize >> 10);
162 return;
163 }
164 pal_init();
165 dev = openboot();
166 if (dev < 0) {
167 srm_printk("Unable to open boot device: %016lx\n", dev);
168 return;
169 }
170 dev &= 0xffffffff;
171 srm_printk("Loading vmlinux ...");
172 i = load(dev, START_ADDR, KERNEL_SIZE);
173 close(dev);
174 if (i != KERNEL_SIZE) {
175 srm_printk("Failed (%lx)\n", i);
176 return;
177 }
178
179 nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
180 if (nbytes < 0) {
181 nbytes = 0;
182 }
183 envval[nbytes] = '\0';
184 strcpy((char*)ZERO_PGE, envval);
185
186 srm_printk(" Ok\nNow booting the kernel\n");
187 runkernel();
188 for (i = 0 ; i < 0x100000000 ; i++)
189 /* nothing */;
190 __halt();
191}
diff --git a/arch/alpha/boot/misc.c b/arch/alpha/boot/misc.c
new file mode 100644
index 000000000000..1d65adf5691e
--- /dev/null
+++ b/arch/alpha/boot/misc.c
@@ -0,0 +1,207 @@
1/*
2 * misc.c
3 *
4 * This is a collection of several routines from gzip-1.0.3
5 * adapted for Linux.
6 *
7 * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
8 *
9 * Modified for ARM Linux by Russell King
10 *
11 * Nicolas Pitre <nico@visuaide.com> 1999/04/14 :
12 * For this code to run directly from Flash, all constant variables must
13 * be marked with 'const' and all other variables initialized at run-time
14 * only. This way all non constant variables will end up in the bss segment,
15 * which should point to addresses in RAM and cleared to 0 on start.
16 * This allows for a much quicker boot time.
17 *
18 * Modified for Alpha, from the ARM version, by Jay Estabrook 2003.
19 */
20
21#include <linux/kernel.h>
22
23#include <asm/uaccess.h>
24
25#define memzero(s,n) memset ((s),0,(n))
26#define puts srm_printk
27extern long srm_printk(const char *, ...)
28 __attribute__ ((format (printf, 1, 2)));
29
30/*
31 * gzip delarations
32 */
33#define OF(args) args
34#define STATIC static
35
36typedef unsigned char uch;
37typedef unsigned short ush;
38typedef unsigned long ulg;
39
40#define WSIZE 0x8000 /* Window size must be at least 32k, */
41 /* and a power of two */
42
43static uch *inbuf; /* input buffer */
44static uch *window; /* Sliding window buffer */
45
46static unsigned insize; /* valid bytes in inbuf */
47static unsigned inptr; /* index of next byte to be processed in inbuf */
48static unsigned outcnt; /* bytes in output buffer */
49
50/* gzip flag byte */
51#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
52#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
53#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
54#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
55#define COMMENT 0x10 /* bit 4 set: file comment present */
56#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
57#define RESERVED 0xC0 /* bit 6,7: reserved */
58
59#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
60
61/* Diagnostic functions */
62#ifdef DEBUG
63# define Assert(cond,msg) {if(!(cond)) error(msg);}
64# define Trace(x) fprintf x
65# define Tracev(x) {if (verbose) fprintf x ;}
66# define Tracevv(x) {if (verbose>1) fprintf x ;}
67# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
68# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
69#else
70# define Assert(cond,msg)
71# define Trace(x)
72# define Tracev(x)
73# define Tracevv(x)
74# define Tracec(c,x)
75# define Tracecv(c,x)
76#endif
77
78static int fill_inbuf(void);
79static void flush_window(void);
80static void error(char *m);
81static void gzip_mark(void **);
82static void gzip_release(void **);
83
84static char *input_data;
85static int input_data_size;
86
87static uch *output_data;
88static ulg output_ptr;
89static ulg bytes_out;
90
91static void *malloc(int size);
92static void free(void *where);
93static void error(char *m);
94static void gzip_mark(void **);
95static void gzip_release(void **);
96
97extern int end;
98static ulg free_mem_ptr;
99static ulg free_mem_ptr_end;
100
101#define HEAP_SIZE 0x2000
102
103#include "../../../lib/inflate.c"
104
105static void *malloc(int size)
106{
107 void *p;
108
109 if (size <0) error("Malloc error");
110 if (free_mem_ptr <= 0) error("Memory error");
111
112 free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */
113
114 p = (void *)free_mem_ptr;
115 free_mem_ptr += size;
116
117 if (free_mem_ptr >= free_mem_ptr_end)
118 error("Out of memory");
119 return p;
120}
121
122static void free(void *where)
123{ /* gzip_mark & gzip_release do the free */
124}
125
126static void gzip_mark(void **ptr)
127{
128 *ptr = (void *) free_mem_ptr;
129}
130
131static void gzip_release(void **ptr)
132{
133 free_mem_ptr = (long) *ptr;
134}
135
136/* ===========================================================================
137 * Fill the input buffer. This is called only when the buffer is empty
138 * and at least one byte is really needed.
139 */
140int fill_inbuf(void)
141{
142 if (insize != 0)
143 error("ran out of input data");
144
145 inbuf = input_data;
146 insize = input_data_size;
147
148 inptr = 1;
149 return inbuf[0];
150}
151
152/* ===========================================================================
153 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
154 * (Used for the decompressed data only.)
155 */
156void flush_window(void)
157{
158 ulg c = crc;
159 unsigned n;
160 uch *in, *out, ch;
161
162 in = window;
163 out = &output_data[output_ptr];
164 for (n = 0; n < outcnt; n++) {
165 ch = *out++ = *in++;
166 c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
167 }
168 crc = c;
169 bytes_out += (ulg)outcnt;
170 output_ptr += (ulg)outcnt;
171 outcnt = 0;
172/* puts("."); */
173}
174
175static void error(char *x)
176{
177 puts("\n\n");
178 puts(x);
179 puts("\n\n -- System halted");
180
181 while(1); /* Halt */
182}
183
184unsigned int
185decompress_kernel(void *output_start,
186 void *input_start,
187 size_t ksize,
188 size_t kzsize)
189{
190 output_data = (uch *)output_start;
191 input_data = (uch *)input_start;
192 input_data_size = kzsize; /* use compressed size */
193
194 /* FIXME FIXME FIXME */
195 free_mem_ptr = (ulg)output_start + ksize;
196 free_mem_ptr_end = (ulg)output_start + ksize + 0x200000;
197 /* FIXME FIXME FIXME */
198
199 /* put in temp area to reduce initial footprint */
200 window = malloc(WSIZE);
201
202 makecrc();
203/* puts("Uncompressing Linux..."); */
204 gunzip();
205/* puts(" done, booting the kernel.\n"); */
206 return output_ptr;
207}
diff --git a/arch/alpha/boot/tools/mkbb.c b/arch/alpha/boot/tools/mkbb.c
new file mode 100644
index 000000000000..23c7190b047c
--- /dev/null
+++ b/arch/alpha/boot/tools/mkbb.c
@@ -0,0 +1,151 @@
1/* This utility makes a bootblock suitable for the SRM console/miniloader */
2
3/* Usage:
4 * mkbb <device> <lxboot>
5 *
6 * Where <device> is the name of the device to install the bootblock on,
7 * and <lxboot> is the name of a bootblock to merge in. This bootblock
8 * contains the offset and size of the bootloader. It must be exactly
9 * 512 bytes long.
10 */
11
12#include <fcntl.h>
13#include <unistd.h>
14#include <stdio.h>
15
16/* Minimal definition of disklabel, so we don't have to include
17 * asm/disklabel.h (confuses make)
18 */
19#ifndef MAXPARTITIONS
20#define MAXPARTITIONS 8 /* max. # of partitions */
21#endif
22
23#ifndef u8
24#define u8 unsigned char
25#endif
26
27#ifndef u16
28#define u16 unsigned short
29#endif
30
31#ifndef u32
32#define u32 unsigned int
33#endif
34
35struct disklabel {
36 u32 d_magic; /* must be DISKLABELMAGIC */
37 u16 d_type, d_subtype;
38 u8 d_typename[16];
39 u8 d_packname[16];
40 u32 d_secsize;
41 u32 d_nsectors;
42 u32 d_ntracks;
43 u32 d_ncylinders;
44 u32 d_secpercyl;
45 u32 d_secprtunit;
46 u16 d_sparespertrack;
47 u16 d_sparespercyl;
48 u32 d_acylinders;
49 u16 d_rpm, d_interleave, d_trackskew, d_cylskew;
50 u32 d_headswitch, d_trkseek, d_flags;
51 u32 d_drivedata[5];
52 u32 d_spare[5];
53 u32 d_magic2; /* must be DISKLABELMAGIC */
54 u16 d_checksum;
55 u16 d_npartitions;
56 u32 d_bbsize, d_sbsize;
57 struct d_partition {
58 u32 p_size;
59 u32 p_offset;
60 u32 p_fsize;
61 u8 p_fstype;
62 u8 p_frag;
63 u16 p_cpg;
64 } d_partitions[MAXPARTITIONS];
65};
66
67
68typedef union __bootblock {
69 struct {
70 char __pad1[64];
71 struct disklabel __label;
72 } __u1;
73 struct {
74 unsigned long __pad2[63];
75 unsigned long __checksum;
76 } __u2;
77 char bootblock_bytes[512];
78 unsigned long bootblock_quadwords[64];
79} bootblock;
80
81#define bootblock_label __u1.__label
82#define bootblock_checksum __u2.__checksum
83
84main(int argc, char ** argv)
85{
86 bootblock bootblock_from_disk;
87 bootblock bootloader_image;
88 int dev, fd;
89 int i;
90 int nread;
91
92 /* Make sure of the arg count */
93 if(argc != 3) {
94 fprintf(stderr, "Usage: %s device lxboot\n", argv[0]);
95 exit(0);
96 }
97
98 /* First, open the device and make sure it's accessible */
99 dev = open(argv[1], O_RDWR);
100 if(dev < 0) {
101 perror(argv[1]);
102 exit(0);
103 }
104
105 /* Now open the lxboot and make sure it's reasonable */
106 fd = open(argv[2], O_RDONLY);
107 if(fd < 0) {
108 perror(argv[2]);
109 close(dev);
110 exit(0);
111 }
112
113 /* Read in the lxboot */
114 nread = read(fd, &bootloader_image, sizeof(bootblock));
115 if(nread != sizeof(bootblock)) {
116 perror("lxboot read");
117 fprintf(stderr, "expected %d, got %d\n", sizeof(bootblock), nread);
118 exit(0);
119 }
120
121 /* Read in the bootblock from disk. */
122 nread = read(dev, &bootblock_from_disk, sizeof(bootblock));
123 if(nread != sizeof(bootblock)) {
124 perror("bootblock read");
125 fprintf(stderr, "expected %d, got %d\n", sizeof(bootblock), nread);
126 exit(0);
127 }
128
129 /* Swap the bootblock's disklabel into the bootloader */
130 bootloader_image.bootblock_label = bootblock_from_disk.bootblock_label;
131
132 /* Calculate the bootblock checksum */
133 bootloader_image.bootblock_checksum = 0;
134 for(i = 0; i < 63; i++) {
135 bootloader_image.bootblock_checksum +=
136 bootloader_image.bootblock_quadwords[i];
137 }
138
139 /* Write the whole thing out! */
140 lseek(dev, 0L, SEEK_SET);
141 if(write(dev, &bootloader_image, sizeof(bootblock)) != sizeof(bootblock)) {
142 perror("bootblock write");
143 exit(0);
144 }
145
146 close(fd);
147 close(dev);
148 exit(0);
149}
150
151
diff --git a/arch/alpha/boot/tools/objstrip.c b/arch/alpha/boot/tools/objstrip.c
new file mode 100644
index 000000000000..67beb1b45e4f
--- /dev/null
+++ b/arch/alpha/boot/tools/objstrip.c
@@ -0,0 +1,281 @@
1/*
2 * arch/alpha/boot/tools/objstrip.c
3 *
4 * Strip the object file headers/trailers from an executable (ELF or ECOFF).
5 *
6 * Copyright (C) 1996 David Mosberger-Tang.
7 */
8/*
9 * Converts an ECOFF or ELF object file into a bootable file. The
10 * object file must be a OMAGIC file (i.e., data and bss follow immediately
11 * behind the text). See DEC "Assembly Language Programmer's Guide"
12 * documentation for details. The SRM boot process is documented in
13 * the Alpha AXP Architecture Reference Manual, Second Edition by
14 * Richard L. Sites and Richard T. Witek.
15 */
16#include <stdio.h>
17#include <string.h>
18#include <stdlib.h>
19#include <unistd.h>
20
21#include <sys/fcntl.h>
22#include <sys/stat.h>
23#include <sys/types.h>
24
25#include <linux/a.out.h>
26#include <linux/coff.h>
27#include <linux/param.h>
28#include <linux/string.h>
29#ifdef __ELF__
30# include <linux/elf.h>
31#endif
32
33/* bootfile size must be multiple of BLOCK_SIZE: */
34#define BLOCK_SIZE 512
35
36const char * prog_name;
37
38
39void
40usage (void)
41{
42 fprintf(stderr,
43 "usage: %s [-v] -p file primary\n"
44 " %s [-vb] file [secondary]\n", prog_name, prog_name);
45 exit(1);
46}
47
48
49int
50main (int argc, char *argv[])
51{
52 size_t nwritten, tocopy, n, mem_size, fil_size, pad = 0;
53 int fd, ofd, i, j, verbose = 0, primary = 0;
54 char buf[8192], *inname;
55 struct exec * aout; /* includes file & aout header */
56 long offset;
57#ifdef __ELF__
58 struct elfhdr *elf;
59 struct elf_phdr *elf_phdr; /* program header */
60 unsigned long long e_entry;
61#endif
62
63 prog_name = argv[0];
64
65 for (i = 1; i < argc && argv[i][0] == '-'; ++i) {
66 for (j = 1; argv[i][j]; ++j) {
67 switch (argv[i][j]) {
68 case 'v':
69 verbose = ~verbose;
70 break;
71
72 case 'b':
73 pad = BLOCK_SIZE;
74 break;
75
76 case 'p':
77 primary = 1; /* make primary bootblock */
78 break;
79 }
80 }
81 }
82
83 if (i >= argc) {
84 usage();
85 }
86 inname = argv[i++];
87
88 fd = open(inname, O_RDONLY);
89 if (fd == -1) {
90 perror("open");
91 exit(1);
92 }
93
94 ofd = 1;
95 if (i < argc) {
96 ofd = open(argv[i++], O_WRONLY | O_CREAT | O_TRUNC, 0666);
97 if (fd == -1) {
98 perror("open");
99 exit(1);
100 }
101 }
102
103 if (primary) {
104 /* generate bootblock for primary loader */
105
106 unsigned long bb[64], sum = 0;
107 struct stat st;
108 off_t size;
109 int i;
110
111 if (ofd == 1) {
112 usage();
113 }
114
115 if (fstat(fd, &st) == -1) {
116 perror("fstat");
117 exit(1);
118 }
119
120 size = (st.st_size + BLOCK_SIZE - 1) & ~(BLOCK_SIZE - 1);
121 memset(bb, 0, sizeof(bb));
122 strcpy((char *) bb, "Linux SRM bootblock");
123 bb[60] = size / BLOCK_SIZE; /* count */
124 bb[61] = 1; /* starting sector # */
125 bb[62] = 0; /* flags---must be 0 */
126 for (i = 0; i < 63; ++i) {
127 sum += bb[i];
128 }
129 bb[63] = sum;
130 if (write(ofd, bb, sizeof(bb)) != sizeof(bb)) {
131 perror("boot-block write");
132 exit(1);
133 }
134 printf("%lu\n", size);
135 return 0;
136 }
137
138 /* read and inspect exec header: */
139
140 if (read(fd, buf, sizeof(buf)) < 0) {
141 perror("read");
142 exit(1);
143 }
144
145#ifdef __ELF__
146 elf = (struct elfhdr *) buf;
147
148 if (elf->e_ident[0] == 0x7f && strncmp(elf->e_ident + 1, "ELF", 3) == 0) {
149 if (elf->e_type != ET_EXEC) {
150 fprintf(stderr, "%s: %s is not an ELF executable\n",
151 prog_name, inname);
152 exit(1);
153 }
154 if (!elf_check_arch(elf)) {
155 fprintf(stderr, "%s: is not for this processor (e_machine=%d)\n",
156 prog_name, elf->e_machine);
157 exit(1);
158 }
159 if (elf->e_phnum != 1) {
160 fprintf(stderr,
161 "%s: %d program headers (forgot to link with -N?)\n",
162 prog_name, elf->e_phnum);
163 }
164
165 e_entry = elf->e_entry;
166
167 lseek(fd, elf->e_phoff, SEEK_SET);
168 if (read(fd, buf, sizeof(*elf_phdr)) != sizeof(*elf_phdr)) {
169 perror("read");
170 exit(1);
171 }
172
173 elf_phdr = (struct elf_phdr *) buf;
174 offset = elf_phdr->p_offset;
175 mem_size = elf_phdr->p_memsz;
176 fil_size = elf_phdr->p_filesz;
177
178 /* work around ELF bug: */
179 if (elf_phdr->p_vaddr < e_entry) {
180 unsigned long delta = e_entry - elf_phdr->p_vaddr;
181 offset += delta;
182 mem_size -= delta;
183 fil_size -= delta;
184 elf_phdr->p_vaddr += delta;
185 }
186
187 if (verbose) {
188 fprintf(stderr, "%s: extracting %#016lx-%#016lx (at %lx)\n",
189 prog_name, (long) elf_phdr->p_vaddr,
190 elf_phdr->p_vaddr + fil_size, offset);
191 }
192 } else
193#endif
194 {
195 aout = (struct exec *) buf;
196
197 if (!(aout->fh.f_flags & COFF_F_EXEC)) {
198 fprintf(stderr, "%s: %s is not in executable format\n",
199 prog_name, inname);
200 exit(1);
201 }
202
203 if (aout->fh.f_opthdr != sizeof(aout->ah)) {
204 fprintf(stderr, "%s: %s has unexpected optional header size\n",
205 prog_name, inname);
206 exit(1);
207 }
208
209 if (N_MAGIC(*aout) != OMAGIC) {
210 fprintf(stderr, "%s: %s is not an OMAGIC file\n",
211 prog_name, inname);
212 exit(1);
213 }
214 offset = N_TXTOFF(*aout);
215 fil_size = aout->ah.tsize + aout->ah.dsize;
216 mem_size = fil_size + aout->ah.bsize;
217
218 if (verbose) {
219 fprintf(stderr, "%s: extracting %#016lx-%#016lx (at %lx)\n",
220 prog_name, aout->ah.text_start,
221 aout->ah.text_start + fil_size, offset);
222 }
223 }
224
225 if (lseek(fd, offset, SEEK_SET) != offset) {
226 perror("lseek");
227 exit(1);
228 }
229
230 if (verbose) {
231 fprintf(stderr, "%s: copying %lu byte from %s\n",
232 prog_name, (unsigned long) fil_size, inname);
233 }
234
235 tocopy = fil_size;
236 while (tocopy > 0) {
237 n = tocopy;
238 if (n > sizeof(buf)) {
239 n = sizeof(buf);
240 }
241 tocopy -= n;
242 if ((size_t) read(fd, buf, n) != n) {
243 perror("read");
244 exit(1);
245 }
246 do {
247 nwritten = write(ofd, buf, n);
248 if ((ssize_t) nwritten == -1) {
249 perror("write");
250 exit(1);
251 }
252 n -= nwritten;
253 } while (n > 0);
254 }
255
256 if (pad) {
257 mem_size = ((mem_size + pad - 1) / pad) * pad;
258 }
259
260 tocopy = mem_size - fil_size;
261 if (tocopy > 0) {
262 fprintf(stderr,
263 "%s: zero-filling bss and aligning to %lu with %lu bytes\n",
264 prog_name, pad, (unsigned long) tocopy);
265
266 memset(buf, 0x00, sizeof(buf));
267 do {
268 n = tocopy;
269 if (n > sizeof(buf)) {
270 n = sizeof(buf);
271 }
272 nwritten = write(ofd, buf, n);
273 if ((ssize_t) nwritten == -1) {
274 perror("write");
275 exit(1);
276 }
277 tocopy -= nwritten;
278 } while (tocopy > 0);
279 }
280 return 0;
281}
diff --git a/arch/alpha/defconfig b/arch/alpha/defconfig
new file mode 100644
index 000000000000..5e39b7a7c8f4
--- /dev/null
+++ b/arch/alpha/defconfig
@@ -0,0 +1,927 @@
1#
2# Automatically generated make config: don't edit
3# Linux kernel version: 2.6.9-rc2
4# Sat Sep 25 15:38:35 2004
5#
6CONFIG_ALPHA=y
7CONFIG_64BIT=y
8CONFIG_MMU=y
9CONFIG_RWSEM_XCHGADD_ALGORITHM=y
10CONFIG_GENERIC_ISA_DMA=y
11# CONFIG_GENERIC_IOMAP is not set
12
13#
14# Code maturity level options
15#
16CONFIG_EXPERIMENTAL=y
17CONFIG_CLEAN_COMPILE=y
18CONFIG_BROKEN_ON_SMP=y
19
20#
21# General setup
22#
23CONFIG_LOCALVERSION=""
24CONFIG_SWAP=y
25CONFIG_SYSVIPC=y
26CONFIG_POSIX_MQUEUE=y
27# CONFIG_BSD_PROCESS_ACCT is not set
28CONFIG_SYSCTL=y
29# CONFIG_AUDIT is not set
30CONFIG_LOG_BUF_SHIFT=14
31# CONFIG_HOTPLUG is not set
32# CONFIG_IKCONFIG is not set
33# CONFIG_EMBEDDED is not set
34CONFIG_KALLSYMS=y
35CONFIG_KALLSYMS_ALL=y
36# CONFIG_KALLSYMS_EXTRA_PASS is not set
37CONFIG_FUTEX=y
38CONFIG_EPOLL=y
39CONFIG_IOSCHED_NOOP=y
40CONFIG_IOSCHED_AS=y
41CONFIG_IOSCHED_DEADLINE=y
42CONFIG_IOSCHED_CFQ=y
43# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
44CONFIG_SHMEM=y
45# CONFIG_TINY_SHMEM is not set
46
47#
48# Loadable module support
49#
50CONFIG_MODULES=y
51CONFIG_MODULE_UNLOAD=y
52# CONFIG_MODULE_FORCE_UNLOAD is not set
53CONFIG_OBSOLETE_MODPARM=y
54# CONFIG_MODVERSIONS is not set
55CONFIG_KMOD=y
56
57#
58# System setup
59#
60CONFIG_ALPHA_GENERIC=y
61# CONFIG_ALPHA_ALCOR is not set
62# CONFIG_ALPHA_XL is not set
63# CONFIG_ALPHA_BOOK1 is not set
64# CONFIG_ALPHA_AVANTI_CH is not set
65# CONFIG_ALPHA_CABRIOLET is not set
66# CONFIG_ALPHA_DP264 is not set
67# CONFIG_ALPHA_EB164 is not set
68# CONFIG_ALPHA_EB64P_CH is not set
69# CONFIG_ALPHA_EB66 is not set
70# CONFIG_ALPHA_EB66P is not set
71# CONFIG_ALPHA_EIGER is not set
72# CONFIG_ALPHA_JENSEN is not set
73# CONFIG_ALPHA_LX164 is not set
74# CONFIG_ALPHA_LYNX is not set
75# CONFIG_ALPHA_MARVEL is not set
76# CONFIG_ALPHA_MIATA is not set
77# CONFIG_ALPHA_MIKASA is not set
78# CONFIG_ALPHA_NAUTILUS is not set
79# CONFIG_ALPHA_NONAME_CH is not set
80# CONFIG_ALPHA_NORITAKE is not set
81# CONFIG_ALPHA_PC164 is not set
82# CONFIG_ALPHA_P2K is not set
83# CONFIG_ALPHA_RAWHIDE is not set
84# CONFIG_ALPHA_RUFFIAN is not set
85# CONFIG_ALPHA_RX164 is not set
86# CONFIG_ALPHA_SX164 is not set
87# CONFIG_ALPHA_SABLE is not set
88# CONFIG_ALPHA_SHARK is not set
89# CONFIG_ALPHA_TAKARA is not set
90# CONFIG_ALPHA_TITAN is not set
91# CONFIG_ALPHA_WILDFIRE is not set
92CONFIG_ISA=y
93CONFIG_PCI=y
94CONFIG_PCI_DOMAINS=y
95CONFIG_ALPHA_CORE_AGP=y
96CONFIG_ALPHA_BROKEN_IRQ_MASK=y
97CONFIG_EISA=y
98# CONFIG_SMP is not set
99# CONFIG_DISCONTIGMEM is not set
100CONFIG_VERBOSE_MCHECK=y
101CONFIG_VERBOSE_MCHECK_ON=1
102CONFIG_PCI_LEGACY_PROC=y
103CONFIG_PCI_NAMES=y
104CONFIG_EISA_PCI_EISA=y
105CONFIG_EISA_VIRTUAL_ROOT=y
106CONFIG_EISA_NAMES=y
107CONFIG_SRM_ENV=m
108CONFIG_BINFMT_ELF=y
109# CONFIG_BINFMT_AOUT is not set
110# CONFIG_BINFMT_EM86 is not set
111# CONFIG_BINFMT_MISC is not set
112
113#
114# Device Drivers
115#
116
117#
118# Generic Driver Options
119#
120CONFIG_STANDALONE=y
121CONFIG_PREVENT_FIRMWARE_BUILD=y
122# CONFIG_DEBUG_DRIVER is not set
123
124#
125# Memory Technology Devices (MTD)
126#
127# CONFIG_MTD is not set
128
129#
130# Parallel port support
131#
132# CONFIG_PARPORT is not set
133
134#
135# Plug and Play support
136#
137CONFIG_PNP=y
138# CONFIG_PNP_DEBUG is not set
139
140#
141# Protocols
142#
143CONFIG_ISAPNP=y
144
145#
146# Block devices
147#
148CONFIG_BLK_DEV_FD=y
149# CONFIG_BLK_DEV_XD is not set
150# CONFIG_BLK_CPQ_DA is not set
151# CONFIG_BLK_CPQ_CISS_DA is not set
152# CONFIG_BLK_DEV_DAC960 is not set
153# CONFIG_BLK_DEV_UMEM is not set
154CONFIG_BLK_DEV_LOOP=m
155# CONFIG_BLK_DEV_CRYPTOLOOP is not set
156# CONFIG_BLK_DEV_NBD is not set
157# CONFIG_BLK_DEV_SX8 is not set
158# CONFIG_BLK_DEV_RAM is not set
159
160#
161# ATA/ATAPI/MFM/RLL support
162#
163CONFIG_IDE=y
164CONFIG_IDE_MAX_HWIFS=4
165CONFIG_BLK_DEV_IDE=y
166
167#
168# Please see Documentation/ide.txt for help/info on IDE drives
169#
170# CONFIG_BLK_DEV_IDE_SATA is not set
171CONFIG_BLK_DEV_IDEDISK=y
172CONFIG_IDEDISK_MULTI_MODE=y
173CONFIG_BLK_DEV_IDECD=y
174# CONFIG_BLK_DEV_IDETAPE is not set
175# CONFIG_BLK_DEV_IDEFLOPPY is not set
176# CONFIG_BLK_DEV_IDESCSI is not set
177# CONFIG_IDE_TASK_IOCTL is not set
178# CONFIG_IDE_TASKFILE_IO is not set
179
180#
181# IDE chipset support/bugfixes
182#
183CONFIG_IDE_GENERIC=y
184# CONFIG_BLK_DEV_IDEPNP is not set
185CONFIG_BLK_DEV_IDEPCI=y
186# CONFIG_IDEPCI_SHARE_IRQ is not set
187# CONFIG_BLK_DEV_OFFBOARD is not set
188CONFIG_BLK_DEV_GENERIC=y
189# CONFIG_BLK_DEV_OPTI621 is not set
190CONFIG_BLK_DEV_IDEDMA_PCI=y
191# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
192CONFIG_IDEDMA_PCI_AUTO=y
193# CONFIG_IDEDMA_ONLYDISK is not set
194# CONFIG_BLK_DEV_AEC62XX is not set
195CONFIG_BLK_DEV_ALI15X3=y
196# CONFIG_WDC_ALI15X3 is not set
197# CONFIG_BLK_DEV_AMD74XX is not set
198CONFIG_BLK_DEV_CMD64X=y
199# CONFIG_BLK_DEV_TRIFLEX is not set
200CONFIG_BLK_DEV_CY82C693=y
201# CONFIG_BLK_DEV_CS5520 is not set
202# CONFIG_BLK_DEV_CS5530 is not set
203# CONFIG_BLK_DEV_HPT34X is not set
204# CONFIG_BLK_DEV_HPT366 is not set
205# CONFIG_BLK_DEV_SC1200 is not set
206# CONFIG_BLK_DEV_PIIX is not set
207# CONFIG_BLK_DEV_NS87415 is not set
208# CONFIG_BLK_DEV_PDC202XX_OLD is not set
209# CONFIG_BLK_DEV_PDC202XX_NEW is not set
210# CONFIG_BLK_DEV_SVWKS is not set
211# CONFIG_BLK_DEV_SIIMAGE is not set
212# CONFIG_BLK_DEV_SLC90E66 is not set
213# CONFIG_BLK_DEV_TRM290 is not set
214# CONFIG_BLK_DEV_VIA82CXXX is not set
215# CONFIG_IDE_ARM is not set
216# CONFIG_IDE_CHIPSETS is not set
217CONFIG_BLK_DEV_IDEDMA=y
218# CONFIG_IDEDMA_IVB is not set
219CONFIG_IDEDMA_AUTO=y
220# CONFIG_BLK_DEV_HD is not set
221
222#
223# SCSI device support
224#
225CONFIG_SCSI=y
226CONFIG_SCSI_PROC_FS=y
227
228#
229# SCSI support type (disk, tape, CD-ROM)
230#
231CONFIG_BLK_DEV_SD=y
232# CONFIG_CHR_DEV_ST is not set
233# CONFIG_CHR_DEV_OSST is not set
234CONFIG_BLK_DEV_SR=y
235CONFIG_BLK_DEV_SR_VENDOR=y
236# CONFIG_CHR_DEV_SG is not set
237
238#
239# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
240#
241# CONFIG_SCSI_MULTI_LUN is not set
242# CONFIG_SCSI_CONSTANTS is not set
243# CONFIG_SCSI_LOGGING is not set
244
245#
246# SCSI Transport Attributes
247#
248# CONFIG_SCSI_SPI_ATTRS is not set
249# CONFIG_SCSI_FC_ATTRS is not set
250
251#
252# SCSI low-level drivers
253#
254# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
255# CONFIG_SCSI_3W_9XXX is not set
256# CONFIG_SCSI_7000FASST is not set
257# CONFIG_SCSI_ACARD is not set
258# CONFIG_SCSI_AHA1542 is not set
259# CONFIG_SCSI_AHA1740 is not set
260# CONFIG_SCSI_AACRAID is not set
261CONFIG_SCSI_AIC7XXX=m
262CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
263CONFIG_AIC7XXX_RESET_DELAY_MS=5000
264# CONFIG_AIC7XXX_PROBE_EISA_VL is not set
265# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
266CONFIG_AIC7XXX_DEBUG_MASK=0
267CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
268# CONFIG_SCSI_AIC7XXX_OLD is not set
269# CONFIG_SCSI_AIC79XX is not set
270# CONFIG_SCSI_IN2000 is not set
271# CONFIG_MEGARAID_NEWGEN is not set
272# CONFIG_MEGARAID_LEGACY is not set
273# CONFIG_SCSI_SATA is not set
274# CONFIG_SCSI_BUSLOGIC is not set
275# CONFIG_SCSI_DMX3191D is not set
276# CONFIG_SCSI_DTC3280 is not set
277# CONFIG_SCSI_EATA is not set
278# CONFIG_SCSI_EATA_PIO is not set
279# CONFIG_SCSI_FUTURE_DOMAIN is not set
280# CONFIG_SCSI_GDTH is not set
281# CONFIG_SCSI_GENERIC_NCR5380 is not set
282# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
283# CONFIG_SCSI_IPS is not set
284# CONFIG_SCSI_INIA100 is not set
285# CONFIG_SCSI_NCR53C406A is not set
286# CONFIG_SCSI_SYM53C8XX_2 is not set
287# CONFIG_SCSI_IPR is not set
288# CONFIG_SCSI_PAS16 is not set
289# CONFIG_SCSI_PSI240I is not set
290# CONFIG_SCSI_QLOGIC_FAS is not set
291# CONFIG_SCSI_QLOGIC_ISP is not set
292# CONFIG_SCSI_QLOGIC_FC is not set
293# CONFIG_SCSI_QLOGIC_1280 is not set
294CONFIG_SCSI_QLA2XXX=y
295# CONFIG_SCSI_QLA21XX is not set
296# CONFIG_SCSI_QLA22XX is not set
297# CONFIG_SCSI_QLA2300 is not set
298# CONFIG_SCSI_QLA2322 is not set
299# CONFIG_SCSI_QLA6312 is not set
300# CONFIG_SCSI_QLA6322 is not set
301# CONFIG_SCSI_SIM710 is not set
302# CONFIG_SCSI_SYM53C416 is not set
303# CONFIG_SCSI_DC395x is not set
304# CONFIG_SCSI_DC390T is not set
305# CONFIG_SCSI_T128 is not set
306# CONFIG_SCSI_U14_34F is not set
307# CONFIG_SCSI_DEBUG is not set
308
309#
310# Old CD-ROM drivers (not SCSI, not IDE)
311#
312# CONFIG_CD_NO_IDESCSI is not set
313
314#
315# Multi-device support (RAID and LVM)
316#
317# CONFIG_MD is not set
318
319#
320# Fusion MPT device support
321#
322# CONFIG_FUSION is not set
323
324#
325# IEEE 1394 (FireWire) support
326#
327# CONFIG_IEEE1394 is not set
328
329#
330# I2O device support
331#
332# CONFIG_I2O is not set
333
334#
335# Networking support
336#
337CONFIG_NET=y
338
339#
340# Networking options
341#
342CONFIG_PACKET=y
343# CONFIG_PACKET_MMAP is not set
344CONFIG_NETLINK_DEV=y
345CONFIG_UNIX=y
346CONFIG_NET_KEY=m
347CONFIG_INET=y
348CONFIG_IP_MULTICAST=y
349# CONFIG_IP_ADVANCED_ROUTER is not set
350# CONFIG_IP_PNP is not set
351# CONFIG_NET_IPIP is not set
352# CONFIG_NET_IPGRE is not set
353# CONFIG_IP_MROUTE is not set
354# CONFIG_ARPD is not set
355# CONFIG_SYN_COOKIES is not set
356CONFIG_INET_AH=m
357CONFIG_INET_ESP=m
358# CONFIG_INET_IPCOMP is not set
359# CONFIG_INET_TUNNEL is not set
360
361#
362# IP: Virtual Server Configuration
363#
364# CONFIG_IP_VS is not set
365# CONFIG_IPV6 is not set
366CONFIG_NETFILTER=y
367# CONFIG_NETFILTER_DEBUG is not set
368
369#
370# IP: Netfilter Configuration
371#
372CONFIG_IP_NF_CONNTRACK=m
373# CONFIG_IP_NF_CT_ACCT is not set
374# CONFIG_IP_NF_CT_PROTO_SCTP is not set
375CONFIG_IP_NF_FTP=m
376CONFIG_IP_NF_IRC=m
377# CONFIG_IP_NF_TFTP is not set
378# CONFIG_IP_NF_AMANDA is not set
379CONFIG_IP_NF_QUEUE=m
380CONFIG_IP_NF_IPTABLES=m
381# CONFIG_IP_NF_MATCH_LIMIT is not set
382# CONFIG_IP_NF_MATCH_IPRANGE is not set
383# CONFIG_IP_NF_MATCH_MAC is not set
384# CONFIG_IP_NF_MATCH_PKTTYPE is not set
385# CONFIG_IP_NF_MATCH_MARK is not set
386# CONFIG_IP_NF_MATCH_MULTIPORT is not set
387# CONFIG_IP_NF_MATCH_TOS is not set
388# CONFIG_IP_NF_MATCH_RECENT is not set
389# CONFIG_IP_NF_MATCH_ECN is not set
390# CONFIG_IP_NF_MATCH_DSCP is not set
391# CONFIG_IP_NF_MATCH_AH_ESP is not set
392# CONFIG_IP_NF_MATCH_LENGTH is not set
393# CONFIG_IP_NF_MATCH_TTL is not set
394# CONFIG_IP_NF_MATCH_TCPMSS is not set
395# CONFIG_IP_NF_MATCH_HELPER is not set
396# CONFIG_IP_NF_MATCH_STATE is not set
397# CONFIG_IP_NF_MATCH_CONNTRACK is not set
398# CONFIG_IP_NF_MATCH_OWNER is not set
399# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
400# CONFIG_IP_NF_MATCH_REALM is not set
401# CONFIG_IP_NF_MATCH_SCTP is not set
402# CONFIG_IP_NF_MATCH_COMMENT is not set
403CONFIG_IP_NF_FILTER=m
404# CONFIG_IP_NF_TARGET_REJECT is not set
405# CONFIG_IP_NF_TARGET_LOG is not set
406# CONFIG_IP_NF_TARGET_ULOG is not set
407# CONFIG_IP_NF_TARGET_TCPMSS is not set
408CONFIG_IP_NF_NAT=m
409CONFIG_IP_NF_NAT_NEEDED=y
410CONFIG_IP_NF_TARGET_MASQUERADE=m
411# CONFIG_IP_NF_TARGET_REDIRECT is not set
412# CONFIG_IP_NF_TARGET_NETMAP is not set
413# CONFIG_IP_NF_TARGET_SAME is not set
414# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
415CONFIG_IP_NF_NAT_IRC=m
416CONFIG_IP_NF_NAT_FTP=m
417# CONFIG_IP_NF_MANGLE is not set
418# CONFIG_IP_NF_RAW is not set
419# CONFIG_IP_NF_ARPTABLES is not set
420CONFIG_IP_NF_COMPAT_IPCHAINS=y
421CONFIG_XFRM=y
422CONFIG_XFRM_USER=m
423
424#
425# SCTP Configuration (EXPERIMENTAL)
426#
427# CONFIG_IP_SCTP is not set
428# CONFIG_ATM is not set
429# CONFIG_BRIDGE is not set
430CONFIG_VLAN_8021Q=m
431# CONFIG_DECNET is not set
432# CONFIG_LLC2 is not set
433# CONFIG_IPX is not set
434# CONFIG_ATALK is not set
435# CONFIG_X25 is not set
436# CONFIG_LAPB is not set
437# CONFIG_NET_DIVERT is not set
438# CONFIG_ECONET is not set
439# CONFIG_WAN_ROUTER is not set
440# CONFIG_NET_HW_FLOWCONTROL is not set
441
442#
443# QoS and/or fair queueing
444#
445# CONFIG_NET_SCHED is not set
446# CONFIG_NET_CLS_ROUTE is not set
447
448#
449# Network testing
450#
451# CONFIG_NET_PKTGEN is not set
452# CONFIG_NETPOLL is not set
453# CONFIG_NET_POLL_CONTROLLER is not set
454# CONFIG_HAMRADIO is not set
455# CONFIG_IRDA is not set
456# CONFIG_BT is not set
457CONFIG_NETDEVICES=y
458CONFIG_DUMMY=m
459# CONFIG_BONDING is not set
460# CONFIG_EQUALIZER is not set
461# CONFIG_TUN is not set
462# CONFIG_ETHERTAP is not set
463# CONFIG_NET_SB1000 is not set
464
465#
466# ARCnet devices
467#
468# CONFIG_ARCNET is not set
469
470#
471# Ethernet (10 or 100Mbit)
472#
473CONFIG_NET_ETHERNET=y
474CONFIG_MII=y
475# CONFIG_HAPPYMEAL is not set
476# CONFIG_SUNGEM is not set
477CONFIG_NET_VENDOR_3COM=y
478# CONFIG_EL1 is not set
479# CONFIG_EL2 is not set
480# CONFIG_ELPLUS is not set
481# CONFIG_EL16 is not set
482# CONFIG_EL3 is not set
483# CONFIG_3C515 is not set
484CONFIG_VORTEX=y
485# CONFIG_TYPHOON is not set
486# CONFIG_LANCE is not set
487# CONFIG_NET_VENDOR_SMC is not set
488# CONFIG_NET_VENDOR_RACAL is not set
489
490#
491# Tulip family network device support
492#
493CONFIG_NET_TULIP=y
494CONFIG_DE2104X=m
495CONFIG_TULIP=y
496# CONFIG_TULIP_MWI is not set
497CONFIG_TULIP_MMIO=y
498# CONFIG_TULIP_NAPI is not set
499# CONFIG_DE4X5 is not set
500# CONFIG_WINBOND_840 is not set
501# CONFIG_DM9102 is not set
502# CONFIG_AT1700 is not set
503# CONFIG_DEPCA is not set
504# CONFIG_HP100 is not set
505# CONFIG_NET_ISA is not set
506CONFIG_NET_PCI=y
507# CONFIG_PCNET32 is not set
508# CONFIG_AMD8111_ETH is not set
509# CONFIG_ADAPTEC_STARFIRE is not set
510# CONFIG_AC3200 is not set
511# CONFIG_APRICOT is not set
512# CONFIG_B44 is not set
513# CONFIG_FORCEDETH is not set
514# CONFIG_CS89x0 is not set
515# CONFIG_DGRS is not set
516# CONFIG_EEPRO100 is not set
517# CONFIG_E100 is not set
518# CONFIG_LNE390 is not set
519# CONFIG_FEALNX is not set
520# CONFIG_NATSEMI is not set
521# CONFIG_NE2K_PCI is not set
522# CONFIG_NE3210 is not set
523# CONFIG_ES3210 is not set
524# CONFIG_8139CP is not set
525# CONFIG_8139TOO is not set
526# CONFIG_SIS900 is not set
527# CONFIG_EPIC100 is not set
528# CONFIG_SUNDANCE is not set
529# CONFIG_VIA_RHINE is not set
530# CONFIG_VIA_VELOCITY is not set
531# CONFIG_NET_POCKET is not set
532
533#
534# Ethernet (1000 Mbit)
535#
536# CONFIG_ACENIC is not set
537# CONFIG_DL2K is not set
538# CONFIG_E1000 is not set
539# CONFIG_NS83820 is not set
540# CONFIG_HAMACHI is not set
541CONFIG_YELLOWFIN=y
542# CONFIG_R8169 is not set
543# CONFIG_SK98LIN is not set
544# CONFIG_TIGON3 is not set
545
546#
547# Ethernet (10000 Mbit)
548#
549# CONFIG_IXGB is not set
550# CONFIG_S2IO is not set
551
552#
553# Token Ring devices
554#
555# CONFIG_TR is not set
556
557#
558# Wireless LAN (non-hamradio)
559#
560# CONFIG_NET_RADIO is not set
561
562#
563# Wan interfaces
564#
565# CONFIG_WAN is not set
566# CONFIG_FDDI is not set
567# CONFIG_HIPPI is not set
568# CONFIG_PPP is not set
569# CONFIG_SLIP is not set
570# CONFIG_NET_FC is not set
571# CONFIG_SHAPER is not set
572# CONFIG_NETCONSOLE is not set
573
574#
575# ISDN subsystem
576#
577# CONFIG_ISDN is not set
578
579#
580# Telephony Support
581#
582# CONFIG_PHONE is not set
583
584#
585# Input device support
586#
587CONFIG_INPUT=y
588
589#
590# Userland interfaces
591#
592CONFIG_INPUT_MOUSEDEV=y
593CONFIG_INPUT_MOUSEDEV_PSAUX=y
594CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
595CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
596# CONFIG_INPUT_JOYDEV is not set
597# CONFIG_INPUT_TSDEV is not set
598# CONFIG_INPUT_EVDEV is not set
599# CONFIG_INPUT_EVBUG is not set
600
601#
602# Input I/O drivers
603#
604# CONFIG_GAMEPORT is not set
605CONFIG_SOUND_GAMEPORT=y
606CONFIG_SERIO=y
607CONFIG_SERIO_I8042=y
608CONFIG_SERIO_SERPORT=y
609# CONFIG_SERIO_CT82C710 is not set
610# CONFIG_SERIO_PCIPS2 is not set
611# CONFIG_SERIO_RAW is not set
612
613#
614# Input Device Drivers
615#
616CONFIG_INPUT_KEYBOARD=y
617CONFIG_KEYBOARD_ATKBD=y
618# CONFIG_KEYBOARD_SUNKBD is not set
619# CONFIG_KEYBOARD_LKKBD is not set
620# CONFIG_KEYBOARD_XTKBD is not set
621# CONFIG_KEYBOARD_NEWTON is not set
622CONFIG_INPUT_MOUSE=y
623CONFIG_MOUSE_PS2=y
624# CONFIG_MOUSE_SERIAL is not set
625# CONFIG_MOUSE_INPORT is not set
626# CONFIG_MOUSE_LOGIBM is not set
627# CONFIG_MOUSE_PC110PAD is not set
628# CONFIG_MOUSE_VSXXXAA is not set
629# CONFIG_INPUT_JOYSTICK is not set
630# CONFIG_INPUT_TOUCHSCREEN is not set
631# CONFIG_INPUT_MISC is not set
632
633#
634# Character devices
635#
636CONFIG_VT=y
637CONFIG_VT_CONSOLE=y
638CONFIG_HW_CONSOLE=y
639# CONFIG_SERIAL_NONSTANDARD is not set
640
641#
642# Serial drivers
643#
644CONFIG_SERIAL_8250=y
645CONFIG_SERIAL_8250_CONSOLE=y
646CONFIG_SERIAL_8250_NR_UARTS=4
647# CONFIG_SERIAL_8250_EXTENDED is not set
648
649#
650# Non-8250 serial port support
651#
652CONFIG_SERIAL_CORE=y
653CONFIG_SERIAL_CORE_CONSOLE=y
654CONFIG_UNIX98_PTYS=y
655CONFIG_LEGACY_PTYS=y
656CONFIG_LEGACY_PTY_COUNT=256
657
658#
659# IPMI
660#
661# CONFIG_IPMI_HANDLER is not set
662
663#
664# Watchdog Cards
665#
666# CONFIG_WATCHDOG is not set
667CONFIG_RTC=y
668# CONFIG_DTLK is not set
669# CONFIG_R3964 is not set
670# CONFIG_APPLICOM is not set
671
672#
673# Ftape, the floppy tape device driver
674#
675# CONFIG_FTAPE is not set
676# CONFIG_AGP is not set
677# CONFIG_DRM is not set
678# CONFIG_RAW_DRIVER is not set
679
680#
681# I2C support
682#
683# CONFIG_I2C is not set
684
685#
686# Dallas's 1-wire bus
687#
688# CONFIG_W1 is not set
689
690#
691# Misc devices
692#
693
694#
695# Multimedia devices
696#
697# CONFIG_VIDEO_DEV is not set
698
699#
700# Digital Video Broadcasting Devices
701#
702# CONFIG_DVB is not set
703
704#
705# Graphics support
706#
707# CONFIG_FB is not set
708
709#
710# Console display driver support
711#
712CONFIG_VGA_CONSOLE=y
713# CONFIG_MDA_CONSOLE is not set
714CONFIG_DUMMY_CONSOLE=y
715
716#
717# Sound
718#
719# CONFIG_SOUND is not set
720
721#
722# USB support
723#
724# CONFIG_USB is not set
725
726#
727# USB Gadget Support
728#
729# CONFIG_USB_GADGET is not set
730
731#
732# File systems
733#
734CONFIG_EXT2_FS=y
735# CONFIG_EXT2_FS_XATTR is not set
736# CONFIG_EXT3_FS is not set
737# CONFIG_JBD is not set
738CONFIG_REISERFS_FS=m
739# CONFIG_REISERFS_CHECK is not set
740# CONFIG_REISERFS_PROC_INFO is not set
741# CONFIG_REISERFS_FS_XATTR is not set
742# CONFIG_JFS_FS is not set
743# CONFIG_XFS_FS is not set
744# CONFIG_MINIX_FS is not set
745# CONFIG_ROMFS_FS is not set
746# CONFIG_QUOTA is not set
747CONFIG_AUTOFS_FS=m
748# CONFIG_AUTOFS4_FS is not set
749
750#
751# CD-ROM/DVD Filesystems
752#
753CONFIG_ISO9660_FS=y
754# CONFIG_JOLIET is not set
755# CONFIG_ZISOFS is not set
756# CONFIG_UDF_FS is not set
757
758#
759# DOS/FAT/NT Filesystems
760#
761CONFIG_FAT_FS=y
762CONFIG_MSDOS_FS=y
763CONFIG_VFAT_FS=y
764CONFIG_FAT_DEFAULT_CODEPAGE=437
765CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
766# CONFIG_NTFS_FS is not set
767
768#
769# Pseudo filesystems
770#
771CONFIG_PROC_FS=y
772CONFIG_PROC_KCORE=y
773CONFIG_SYSFS=y
774# CONFIG_DEVFS_FS is not set
775# CONFIG_DEVPTS_FS_XATTR is not set
776CONFIG_TMPFS=y
777# CONFIG_HUGETLB_PAGE is not set
778CONFIG_RAMFS=y
779
780#
781# Miscellaneous filesystems
782#
783# CONFIG_ADFS_FS is not set
784# CONFIG_AFFS_FS is not set
785# CONFIG_HFS_FS is not set
786# CONFIG_HFSPLUS_FS is not set
787# CONFIG_BEFS_FS is not set
788# CONFIG_BFS_FS is not set
789# CONFIG_EFS_FS is not set
790# CONFIG_CRAMFS is not set
791# CONFIG_VXFS_FS is not set
792# CONFIG_HPFS_FS is not set
793# CONFIG_QNX4FS_FS is not set
794# CONFIG_SYSV_FS is not set
795# CONFIG_UFS_FS is not set
796
797#
798# Network File Systems
799#
800CONFIG_NFS_FS=m
801CONFIG_NFS_V3=y
802# CONFIG_NFS_V4 is not set
803# CONFIG_NFS_DIRECTIO is not set
804CONFIG_NFSD=m
805CONFIG_NFSD_V3=y
806# CONFIG_NFSD_V4 is not set
807CONFIG_NFSD_TCP=y
808CONFIG_LOCKD=m
809CONFIG_LOCKD_V4=y
810CONFIG_EXPORTFS=m
811CONFIG_SUNRPC=m
812# CONFIG_RPCSEC_GSS_KRB5 is not set
813# CONFIG_RPCSEC_GSS_SPKM3 is not set
814# CONFIG_SMB_FS is not set
815# CONFIG_CIFS is not set
816# CONFIG_NCP_FS is not set
817# CONFIG_CODA_FS is not set
818# CONFIG_AFS_FS is not set
819
820#
821# Partition Types
822#
823# CONFIG_PARTITION_ADVANCED is not set
824CONFIG_OSF_PARTITION=y
825CONFIG_MSDOS_PARTITION=y
826
827#
828# Native Language Support
829#
830CONFIG_NLS=y
831CONFIG_NLS_DEFAULT="iso8859-1"
832CONFIG_NLS_CODEPAGE_437=y
833# CONFIG_NLS_CODEPAGE_737 is not set
834# CONFIG_NLS_CODEPAGE_775 is not set
835# CONFIG_NLS_CODEPAGE_850 is not set
836# CONFIG_NLS_CODEPAGE_852 is not set
837# CONFIG_NLS_CODEPAGE_855 is not set
838# CONFIG_NLS_CODEPAGE_857 is not set
839# CONFIG_NLS_CODEPAGE_860 is not set
840# CONFIG_NLS_CODEPAGE_861 is not set
841# CONFIG_NLS_CODEPAGE_862 is not set
842# CONFIG_NLS_CODEPAGE_863 is not set
843# CONFIG_NLS_CODEPAGE_864 is not set
844# CONFIG_NLS_CODEPAGE_865 is not set
845# CONFIG_NLS_CODEPAGE_866 is not set
846# CONFIG_NLS_CODEPAGE_869 is not set
847# CONFIG_NLS_CODEPAGE_936 is not set
848# CONFIG_NLS_CODEPAGE_950 is not set
849# CONFIG_NLS_CODEPAGE_932 is not set
850# CONFIG_NLS_CODEPAGE_949 is not set
851# CONFIG_NLS_CODEPAGE_874 is not set
852# CONFIG_NLS_ISO8859_8 is not set
853# CONFIG_NLS_CODEPAGE_1250 is not set
854# CONFIG_NLS_CODEPAGE_1251 is not set
855# CONFIG_NLS_ASCII is not set
856# CONFIG_NLS_ISO8859_1 is not set
857# CONFIG_NLS_ISO8859_2 is not set
858# CONFIG_NLS_ISO8859_3 is not set
859# CONFIG_NLS_ISO8859_4 is not set
860# CONFIG_NLS_ISO8859_5 is not set
861# CONFIG_NLS_ISO8859_6 is not set
862# CONFIG_NLS_ISO8859_7 is not set
863# CONFIG_NLS_ISO8859_9 is not set
864# CONFIG_NLS_ISO8859_13 is not set
865# CONFIG_NLS_ISO8859_14 is not set
866# CONFIG_NLS_ISO8859_15 is not set
867# CONFIG_NLS_KOI8_R is not set
868# CONFIG_NLS_KOI8_U is not set
869# CONFIG_NLS_UTF8 is not set
870
871#
872# Profiling support
873#
874# CONFIG_PROFILING is not set
875
876#
877# Kernel hacking
878#
879CONFIG_DEBUG_KERNEL=y
880CONFIG_MAGIC_SYSRQ=y
881# CONFIG_DEBUG_SLAB is not set
882# CONFIG_DEBUG_SPINLOCK is not set
883CONFIG_DEBUG_INFO=y
884CONFIG_EARLY_PRINTK=y
885# CONFIG_DEBUG_RWLOCK is not set
886# CONFIG_DEBUG_SEMAPHORE is not set
887CONFIG_ALPHA_LEGACY_START_ADDRESS=y
888CONFIG_MATHEMU=y
889
890#
891# Security options
892#
893# CONFIG_SECURITY is not set
894
895#
896# Cryptographic options
897#
898CONFIG_CRYPTO=y
899CONFIG_CRYPTO_HMAC=y
900# CONFIG_CRYPTO_NULL is not set
901# CONFIG_CRYPTO_MD4 is not set
902CONFIG_CRYPTO_MD5=m
903CONFIG_CRYPTO_SHA1=m
904# CONFIG_CRYPTO_SHA256 is not set
905# CONFIG_CRYPTO_SHA512 is not set
906# CONFIG_CRYPTO_WHIRLPOOL is not set
907CONFIG_CRYPTO_DES=m
908# CONFIG_CRYPTO_BLOWFISH is not set
909# CONFIG_CRYPTO_TWOFISH is not set
910# CONFIG_CRYPTO_SERPENT is not set
911# CONFIG_CRYPTO_AES is not set
912# CONFIG_CRYPTO_CAST5 is not set
913# CONFIG_CRYPTO_CAST6 is not set
914# CONFIG_CRYPTO_TEA is not set
915# CONFIG_CRYPTO_ARC4 is not set
916# CONFIG_CRYPTO_KHAZAD is not set
917# CONFIG_CRYPTO_DEFLATE is not set
918# CONFIG_CRYPTO_MICHAEL_MIC is not set
919# CONFIG_CRYPTO_CRC32C is not set
920# CONFIG_CRYPTO_TEST is not set
921
922#
923# Library routines
924#
925# CONFIG_CRC_CCITT is not set
926CONFIG_CRC32=y
927# CONFIG_LIBCRC32C is not set
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
new file mode 100644
index 000000000000..ab6fa54b3860
--- /dev/null
+++ b/arch/alpha/kernel/Makefile
@@ -0,0 +1,104 @@
1#
2# Makefile for the linux kernel.
3#
4
5extra-y := head.o vmlinux.lds
6EXTRA_AFLAGS := $(CFLAGS)
7EXTRA_CFLAGS := -Werror -Wno-sign-compare
8
9obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
10 irq_alpha.o signal.o setup.o ptrace.o time.o semaphore.o \
11 alpha_ksyms.o systbls.o err_common.o io.o
12
13obj-$(CONFIG_VGA_HOSE) += console.o
14obj-$(CONFIG_SMP) += smp.o
15obj-$(CONFIG_PCI) += pci.o pci_iommu.o
16obj-$(CONFIG_SRM_ENV) += srm_env.o
17obj-$(CONFIG_MODULES) += module.o
18
19ifdef CONFIG_ALPHA_GENERIC
20
21obj-y += core_apecs.o core_cia.o core_irongate.o core_lca.o \
22 core_mcpcia.o core_polaris.o core_t2.o \
23 core_tsunami.o
24
25obj-y += sys_alcor.o sys_cabriolet.o sys_dp264.o sys_eb64p.o sys_eiger.o \
26 sys_jensen.o sys_miata.o sys_mikasa.o sys_nautilus.o \
27 sys_noritake.o sys_rawhide.o sys_ruffian.o sys_rx164.o \
28 sys_sable.o sys_sio.o sys_sx164.o sys_takara.o
29
30ifndef CONFIG_ALPHA_LEGACY_START_ADDRESS
31obj-y += core_marvel.o core_titan.o core_wildfire.o
32obj-y += sys_marvel.o sys_titan.o sys_wildfire.o
33obj-y += err_ev7.o err_titan.o err_marvel.o
34endif
35
36obj-y += irq_pyxis.o irq_i8259.o irq_srm.o
37obj-y += err_ev6.o
38obj-y += es1888.o smc37c669.o smc37c93x.o ns87312.o gct.o
39obj-y += srmcons.o
40
41else
42
43# Misc support
44obj-$(CONFIG_ALPHA_SRM) += srmcons.o
45
46# Core logic support
47obj-$(CONFIG_ALPHA_APECS) += core_apecs.o
48obj-$(CONFIG_ALPHA_CIA) += core_cia.o
49obj-$(CONFIG_ALPHA_IRONGATE) += core_irongate.o
50obj-$(CONFIG_ALPHA_LCA) += core_lca.o
51obj-$(CONFIG_ALPHA_MARVEL) += core_marvel.o gct.o
52obj-$(CONFIG_ALPHA_MCPCIA) += core_mcpcia.o
53obj-$(CONFIG_ALPHA_POLARIS) += core_polaris.o
54obj-$(CONFIG_ALPHA_T2) += core_t2.o
55obj-$(CONFIG_ALPHA_TSUNAMI) += core_tsunami.o
56obj-$(CONFIG_ALPHA_TITAN) += core_titan.o
57obj-$(CONFIG_ALPHA_WILDFIRE) += core_wildfire.o
58
59# Board support
60obj-$(CONFIG_ALPHA_ALCOR) += sys_alcor.o irq_i8259.o irq_srm.o
61obj-$(CONFIG_ALPHA_CABRIOLET) += sys_cabriolet.o irq_i8259.o irq_srm.o \
62 ns87312.o
63obj-$(CONFIG_ALPHA_EB164) += sys_cabriolet.o irq_i8259.o irq_srm.o \
64 ns87312.o
65obj-$(CONFIG_ALPHA_EB66P) += sys_cabriolet.o irq_i8259.o irq_srm.o \
66 ns87312.o
67obj-$(CONFIG_ALPHA_LX164) += sys_cabriolet.o irq_i8259.o irq_srm.o \
68 smc37c93x.o
69obj-$(CONFIG_ALPHA_PC164) += sys_cabriolet.o irq_i8259.o irq_srm.o \
70 smc37c93x.o
71obj-$(CONFIG_ALPHA_DP264) += sys_dp264.o irq_i8259.o es1888.o smc37c669.o
72obj-$(CONFIG_ALPHA_SHARK) += sys_dp264.o irq_i8259.o es1888.o smc37c669.o
73obj-$(CONFIG_ALPHA_TITAN) += sys_titan.o irq_i8259.o smc37c669.o
74obj-$(CONFIG_ALPHA_EB64P) += sys_eb64p.o irq_i8259.o
75obj-$(CONFIG_ALPHA_EB66) += sys_eb64p.o irq_i8259.o
76obj-$(CONFIG_ALPHA_EIGER) += sys_eiger.o irq_i8259.o
77obj-$(CONFIG_ALPHA_JENSEN) += sys_jensen.o pci-noop.o irq_i8259.o
78obj-$(CONFIG_ALPHA_MARVEL) += sys_marvel.o
79obj-$(CONFIG_ALPHA_MIATA) += sys_miata.o irq_pyxis.o irq_i8259.o \
80 es1888.o smc37c669.o
81obj-$(CONFIG_ALPHA_MIKASA) += sys_mikasa.o irq_i8259.o irq_srm.o
82obj-$(CONFIG_ALPHA_NAUTILUS) += sys_nautilus.o irq_i8259.o irq_srm.o
83obj-$(CONFIG_ALPHA_NORITAKE) += sys_noritake.o irq_i8259.o
84obj-$(CONFIG_ALPHA_RAWHIDE) += sys_rawhide.o irq_i8259.o
85obj-$(CONFIG_ALPHA_RUFFIAN) += sys_ruffian.o irq_pyxis.o irq_i8259.o
86obj-$(CONFIG_ALPHA_RX164) += sys_rx164.o irq_i8259.o
87obj-$(CONFIG_ALPHA_SABLE) += sys_sable.o
88obj-$(CONFIG_ALPHA_LYNX) += sys_sable.o
89obj-$(CONFIG_ALPHA_BOOK1) += sys_sio.o irq_i8259.o irq_srm.o ns87312.o
90obj-$(CONFIG_ALPHA_AVANTI) += sys_sio.o irq_i8259.o irq_srm.o ns87312.o
91obj-$(CONFIG_ALPHA_NONAME) += sys_sio.o irq_i8259.o irq_srm.o ns87312.o
92obj-$(CONFIG_ALPHA_P2K) += sys_sio.o irq_i8259.o irq_srm.o ns87312.o
93obj-$(CONFIG_ALPHA_XL) += sys_sio.o irq_i8259.o irq_srm.o ns87312.o
94obj-$(CONFIG_ALPHA_SX164) += sys_sx164.o irq_pyxis.o irq_i8259.o \
95 irq_srm.o smc37c669.o
96obj-$(CONFIG_ALPHA_TAKARA) += sys_takara.o irq_i8259.o ns87312.o
97obj-$(CONFIG_ALPHA_WILDFIRE) += sys_wildfire.o irq_i8259.o
98
99# Error support
100obj-$(CONFIG_ALPHA_MARVEL) += err_ev7.o err_marvel.o
101obj-$(CONFIG_ALPHA_NAUTILUS) += err_ev6.o
102obj-$(CONFIG_ALPHA_TITAN) += err_ev6.o err_titan.o
103
104endif # GENERIC
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
new file mode 100644
index 000000000000..fc5ef90c4fc9
--- /dev/null
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -0,0 +1,235 @@
1/*
2 * linux/arch/alpha/kernel/ksyms.c
3 *
4 * Export the alpha-specific functions that are needed for loadable
5 * modules.
6 */
7
8#include <linux/config.h>
9#include <linux/module.h>
10#include <linux/string.h>
11#include <linux/user.h>
12#include <linux/elfcore.h>
13#include <linux/socket.h>
14#include <linux/syscalls.h>
15#include <linux/in.h>
16#include <linux/in6.h>
17#include <linux/pci.h>
18#include <linux/tty.h>
19#include <linux/mm.h>
20#include <linux/delay.h>
21#include <linux/dma-mapping.h>
22
23#include <asm/io.h>
24#include <asm/console.h>
25#include <asm/hwrpb.h>
26#include <asm/uaccess.h>
27#include <asm/processor.h>
28#include <asm/checksum.h>
29#include <linux/interrupt.h>
30#include <asm/fpu.h>
31#include <asm/irq.h>
32#include <asm/machvec.h>
33#include <asm/pgalloc.h>
34#include <asm/semaphore.h>
35#include <asm/tlbflush.h>
36#include <asm/cacheflush.h>
37#include <asm/vga.h>
38
39#define __KERNEL_SYSCALLS__
40#include <asm/unistd.h>
41
42extern struct hwrpb_struct *hwrpb;
43extern void dump_thread(struct pt_regs *, struct user *);
44extern spinlock_t rtc_lock;
45
46/* these are C runtime functions with special calling conventions: */
47extern void __divl (void);
48extern void __reml (void);
49extern void __divq (void);
50extern void __remq (void);
51extern void __divlu (void);
52extern void __remlu (void);
53extern void __divqu (void);
54extern void __remqu (void);
55
56EXPORT_SYMBOL(alpha_mv);
57EXPORT_SYMBOL(enable_irq);
58EXPORT_SYMBOL(disable_irq);
59EXPORT_SYMBOL(disable_irq_nosync);
60EXPORT_SYMBOL(probe_irq_mask);
61EXPORT_SYMBOL(screen_info);
62EXPORT_SYMBOL(perf_irq);
63EXPORT_SYMBOL(callback_getenv);
64EXPORT_SYMBOL(callback_setenv);
65EXPORT_SYMBOL(callback_save_env);
66#ifdef CONFIG_ALPHA_GENERIC
67EXPORT_SYMBOL(alpha_using_srm);
68#endif /* CONFIG_ALPHA_GENERIC */
69
70/* platform dependent support */
71EXPORT_SYMBOL(strcat);
72EXPORT_SYMBOL(strcmp);
73EXPORT_SYMBOL(strcpy);
74EXPORT_SYMBOL(strlen);
75EXPORT_SYMBOL(strncmp);
76EXPORT_SYMBOL(strncpy);
77EXPORT_SYMBOL(strnlen);
78EXPORT_SYMBOL(strncat);
79EXPORT_SYMBOL(strstr);
80EXPORT_SYMBOL(strpbrk);
81EXPORT_SYMBOL(strchr);
82EXPORT_SYMBOL(strrchr);
83EXPORT_SYMBOL(memcmp);
84EXPORT_SYMBOL(memmove);
85EXPORT_SYMBOL(memscan);
86EXPORT_SYMBOL(__memcpy);
87EXPORT_SYMBOL(__memset);
88EXPORT_SYMBOL(__memsetw);
89EXPORT_SYMBOL(__constant_c_memset);
90EXPORT_SYMBOL(copy_page);
91EXPORT_SYMBOL(clear_page);
92
93EXPORT_SYMBOL(__direct_map_base);
94EXPORT_SYMBOL(__direct_map_size);
95
96#ifdef CONFIG_PCI
97EXPORT_SYMBOL(pci_alloc_consistent);
98EXPORT_SYMBOL(pci_free_consistent);
99EXPORT_SYMBOL(pci_map_single);
100EXPORT_SYMBOL(pci_map_page);
101EXPORT_SYMBOL(pci_unmap_single);
102EXPORT_SYMBOL(pci_unmap_page);
103EXPORT_SYMBOL(pci_map_sg);
104EXPORT_SYMBOL(pci_unmap_sg);
105EXPORT_SYMBOL(pci_dma_supported);
106EXPORT_SYMBOL(pci_dac_dma_supported);
107EXPORT_SYMBOL(pci_dac_page_to_dma);
108EXPORT_SYMBOL(pci_dac_dma_to_page);
109EXPORT_SYMBOL(pci_dac_dma_to_offset);
110EXPORT_SYMBOL(alpha_gendev_to_pci);
111#endif
112EXPORT_SYMBOL(dma_set_mask);
113
114EXPORT_SYMBOL(dump_thread);
115EXPORT_SYMBOL(dump_elf_thread);
116EXPORT_SYMBOL(dump_elf_task);
117EXPORT_SYMBOL(dump_elf_task_fp);
118EXPORT_SYMBOL(hwrpb);
119EXPORT_SYMBOL(start_thread);
120EXPORT_SYMBOL(alpha_read_fp_reg);
121EXPORT_SYMBOL(alpha_read_fp_reg_s);
122EXPORT_SYMBOL(alpha_write_fp_reg);
123EXPORT_SYMBOL(alpha_write_fp_reg_s);
124
125/* In-kernel system calls. */
126EXPORT_SYMBOL(kernel_thread);
127EXPORT_SYMBOL(sys_open);
128EXPORT_SYMBOL(sys_dup);
129EXPORT_SYMBOL(sys_exit);
130EXPORT_SYMBOL(sys_write);
131EXPORT_SYMBOL(sys_read);
132EXPORT_SYMBOL(sys_lseek);
133EXPORT_SYMBOL(execve);
134EXPORT_SYMBOL(sys_setsid);
135EXPORT_SYMBOL(sys_wait4);
136
137/* Networking helper routines. */
138EXPORT_SYMBOL(csum_tcpudp_magic);
139EXPORT_SYMBOL(ip_compute_csum);
140EXPORT_SYMBOL(ip_fast_csum);
141EXPORT_SYMBOL(csum_partial_copy_nocheck);
142EXPORT_SYMBOL(csum_partial_copy_from_user);
143EXPORT_SYMBOL(csum_ipv6_magic);
144
145#ifdef CONFIG_MATHEMU_MODULE
146extern long (*alpha_fp_emul_imprecise)(struct pt_regs *, unsigned long);
147extern long (*alpha_fp_emul) (unsigned long pc);
148EXPORT_SYMBOL(alpha_fp_emul_imprecise);
149EXPORT_SYMBOL(alpha_fp_emul);
150#endif
151
152#ifdef CONFIG_ALPHA_BROKEN_IRQ_MASK
153EXPORT_SYMBOL(__min_ipl);
154#endif
155
156/*
157 * The following are specially called from the uaccess assembly stubs.
158 */
159EXPORT_SYMBOL(__copy_user);
160EXPORT_SYMBOL(__do_clear_user);
161EXPORT_SYMBOL(__strncpy_from_user);
162EXPORT_SYMBOL(__strnlen_user);
163
164/* Semaphore helper functions. */
165EXPORT_SYMBOL(__down_failed);
166EXPORT_SYMBOL(__down_failed_interruptible);
167EXPORT_SYMBOL(__up_wakeup);
168EXPORT_SYMBOL(down);
169EXPORT_SYMBOL(down_interruptible);
170EXPORT_SYMBOL(down_trylock);
171EXPORT_SYMBOL(up);
172
173/*
174 * SMP-specific symbols.
175 */
176
177#ifdef CONFIG_SMP
178EXPORT_SYMBOL(synchronize_irq);
179EXPORT_SYMBOL(flush_tlb_mm);
180EXPORT_SYMBOL(flush_tlb_range);
181EXPORT_SYMBOL(flush_tlb_page);
182EXPORT_SYMBOL(smp_imb);
183EXPORT_SYMBOL(cpu_data);
184EXPORT_SYMBOL(smp_num_cpus);
185EXPORT_SYMBOL(smp_call_function);
186EXPORT_SYMBOL(smp_call_function_on_cpu);
187EXPORT_SYMBOL(_atomic_dec_and_lock);
188#ifdef CONFIG_DEBUG_SPINLOCK
189EXPORT_SYMBOL(_raw_spin_unlock);
190EXPORT_SYMBOL(debug_spin_lock);
191EXPORT_SYMBOL(debug_spin_trylock);
192#endif
193#ifdef CONFIG_DEBUG_RWLOCK
194EXPORT_SYMBOL(_raw_write_lock);
195EXPORT_SYMBOL(_raw_read_lock);
196#endif
197EXPORT_SYMBOL(cpu_present_mask);
198#endif /* CONFIG_SMP */
199
200/*
201 * NUMA specific symbols
202 */
203#ifdef CONFIG_DISCONTIGMEM
204EXPORT_SYMBOL(node_data);
205#endif /* CONFIG_DISCONTIGMEM */
206
207EXPORT_SYMBOL(rtc_lock);
208
209/*
210 * The following are special because they're not called
211 * explicitly (the C compiler or assembler generates them in
212 * response to division operations). Fortunately, their
213 * interface isn't gonna change any time soon now, so it's OK
214 * to leave it out of version control.
215 */
216# undef memcpy
217# undef memset
218EXPORT_SYMBOL(__divl);
219EXPORT_SYMBOL(__divlu);
220EXPORT_SYMBOL(__divq);
221EXPORT_SYMBOL(__divqu);
222EXPORT_SYMBOL(__reml);
223EXPORT_SYMBOL(__remlu);
224EXPORT_SYMBOL(__remq);
225EXPORT_SYMBOL(__remqu);
226EXPORT_SYMBOL(memcpy);
227EXPORT_SYMBOL(memset);
228EXPORT_SYMBOL(memchr);
229
230EXPORT_SYMBOL(get_wchan);
231
232#ifdef CONFIG_ALPHA_IRONGATE
233EXPORT_SYMBOL(irongate_ioremap);
234EXPORT_SYMBOL(irongate_iounmap);
235#endif
diff --git a/arch/alpha/kernel/asm-offsets.c b/arch/alpha/kernel/asm-offsets.c
new file mode 100644
index 000000000000..8f2e5c718b50
--- /dev/null
+++ b/arch/alpha/kernel/asm-offsets.c
@@ -0,0 +1,43 @@
1/*
2 * Generate definitions needed by assembly language modules.
3 * This code generates raw asm output which is post-processed to extract
4 * and format the required data.
5 */
6
7#include <linux/types.h>
8#include <linux/stddef.h>
9#include <linux/sched.h>
10#include <linux/ptrace.h>
11#include <asm/io.h>
12
13#define DEFINE(sym, val) \
14 asm volatile("\n->" #sym " %0 " #val : : "i" (val))
15
16#define BLANK() asm volatile("\n->" : : )
17
18void foo(void)
19{
20 DEFINE(TI_TASK, offsetof(struct thread_info, task));
21 DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
22 DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
23 BLANK();
24
25 DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
26 DEFINE(TASK_UID, offsetof(struct task_struct, uid));
27 DEFINE(TASK_EUID, offsetof(struct task_struct, euid));
28 DEFINE(TASK_GID, offsetof(struct task_struct, gid));
29 DEFINE(TASK_EGID, offsetof(struct task_struct, egid));
30 DEFINE(TASK_REAL_PARENT, offsetof(struct task_struct, real_parent));
31 DEFINE(TASK_TGID, offsetof(struct task_struct, tgid));
32 BLANK();
33
34 DEFINE(SIZEOF_PT_REGS, sizeof(struct pt_regs));
35 DEFINE(PT_PTRACED, PT_PTRACED);
36 DEFINE(CLONE_VM, CLONE_VM);
37 DEFINE(CLONE_UNTRACED, CLONE_UNTRACED);
38 DEFINE(SIGCHLD, SIGCHLD);
39 BLANK();
40
41 DEFINE(HAE_CACHE, offsetof(struct alpha_machine_vector, hae_cache));
42 DEFINE(HAE_REG, offsetof(struct alpha_machine_vector, hae_register));
43}
diff --git a/arch/alpha/kernel/console.c b/arch/alpha/kernel/console.c
new file mode 100644
index 000000000000..cb3e739fbad8
--- /dev/null
+++ b/arch/alpha/kernel/console.c
@@ -0,0 +1,66 @@
1/*
2 * linux/arch/alpha/kernel/console.c
3 *
4 * Architecture-specific specific support for VGA device on
5 * non-0 I/O hose
6 */
7
8#include <linux/config.h>
9#include <linux/pci.h>
10#include <linux/init.h>
11#include <linux/tty.h>
12#include <linux/console.h>
13#include <asm/vga.h>
14#include <asm/machvec.h>
15
16#ifdef CONFIG_VGA_HOSE
17
18/*
19 * Externally-visible vga hose bases
20 */
21unsigned long __vga_hose_io_base = 0; /* base for default hose */
22unsigned long __vga_hose_mem_base = 0; /* base for default hose */
23
24static struct pci_controller * __init
25default_vga_hose_select(struct pci_controller *h1, struct pci_controller *h2)
26{
27 if (h2->index < h1->index)
28 return h2;
29
30 return h1;
31}
32
33void __init
34set_vga_hose(struct pci_controller *hose)
35{
36 if (hose) {
37 __vga_hose_io_base = hose->io_space->start;
38 __vga_hose_mem_base = hose->mem_space->start;
39 }
40}
41
42void __init
43locate_and_init_vga(void *(*sel_func)(void *, void *))
44{
45 struct pci_controller *hose = NULL;
46 struct pci_dev *dev = NULL;
47
48 if (!sel_func) sel_func = (void *)default_vga_hose_select;
49
50 for(dev=NULL; (dev=pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, dev));) {
51 if (!hose) hose = dev->sysdata;
52 else hose = sel_func(hose, dev->sysdata);
53 }
54
55 /* Did we already inititialize the correct one? */
56 if (conswitchp == &vga_con &&
57 __vga_hose_io_base == hose->io_space->start &&
58 __vga_hose_mem_base == hose->mem_space->start)
59 return;
60
61 /* Set the VGA hose and init the new console */
62 set_vga_hose(hose);
63 take_over_console(&vga_con, 0, MAX_NR_CONSOLES-1, 1);
64}
65
66#endif
diff --git a/arch/alpha/kernel/core_apecs.c b/arch/alpha/kernel/core_apecs.c
new file mode 100644
index 000000000000..a27ba12ba35e
--- /dev/null
+++ b/arch/alpha/kernel/core_apecs.c
@@ -0,0 +1,418 @@
1/*
2 * linux/arch/alpha/kernel/core_apecs.c
3 *
4 * Rewritten for Apecs from the lca.c from:
5 *
6 * Written by David Mosberger (davidm@cs.arizona.edu) with some code
7 * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit
8 * bios code.
9 *
10 * Code common to all APECS core logic chips.
11 */
12
13#define __EXTERN_INLINE inline
14#include <asm/io.h>
15#include <asm/core_apecs.h>
16#undef __EXTERN_INLINE
17
18#include <linux/types.h>
19#include <linux/pci.h>
20#include <linux/init.h>
21
22#include <asm/ptrace.h>
23#include <asm/smp.h>
24
25#include "proto.h"
26#include "pci_impl.h"
27
28/*
29 * NOTE: Herein lie back-to-back mb instructions. They are magic.
30 * One plausible explanation is that the i/o controller does not properly
31 * handle the system transaction. Another involves timing. Ho hum.
32 */
33
34/*
35 * BIOS32-style PCI interface:
36 */
37
38#define DEBUG_CONFIG 0
39
40#if DEBUG_CONFIG
41# define DBGC(args) printk args
42#else
43# define DBGC(args)
44#endif
45
46#define vuip volatile unsigned int *
47
48/*
49 * Given a bus, device, and function number, compute resulting
50 * configuration space address and setup the APECS_HAXR2 register
51 * accordingly. It is therefore not safe to have concurrent
52 * invocations to configuration space access routines, but there
53 * really shouldn't be any need for this.
54 *
55 * Type 0:
56 *
57 * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
58 * 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
59 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60 * | | | | | | | | | | | | | | | | | | | | | | | |F|F|F|R|R|R|R|R|R|0|0|
61 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62 *
63 * 31:11 Device select bit.
64 * 10:8 Function number
65 * 7:2 Register number
66 *
67 * Type 1:
68 *
69 * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
70 * 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
71 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
72 * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
73 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
74 *
75 * 31:24 reserved
76 * 23:16 bus number (8 bits = 128 possible buses)
77 * 15:11 Device number (5 bits)
78 * 10:8 function number
79 * 7:2 register number
80 *
81 * Notes:
82 * The function number selects which function of a multi-function device
83 * (e.g., SCSI and Ethernet).
84 *
85 * The register selects a DWORD (32 bit) register offset. Hence it
86 * doesn't get shifted by 2 bits as we want to "drop" the bottom two
87 * bits.
88 */
89
90static int
91mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
92 unsigned long *pci_addr, unsigned char *type1)
93{
94 unsigned long addr;
95 u8 bus = pbus->number;
96
97 DBGC(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
98 " pci_addr=0x%p, type1=0x%p)\n",
99 bus, device_fn, where, pci_addr, type1));
100
101 if (bus == 0) {
102 int device = device_fn >> 3;
103
104 /* type 0 configuration cycle: */
105
106 if (device > 20) {
107 DBGC(("mk_conf_addr: device (%d) > 20, returning -1\n",
108 device));
109 return -1;
110 }
111
112 *type1 = 0;
113 addr = (device_fn << 8) | (where);
114 } else {
115 /* type 1 configuration cycle: */
116 *type1 = 1;
117 addr = (bus << 16) | (device_fn << 8) | (where);
118 }
119 *pci_addr = addr;
120 DBGC(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
121 return 0;
122}
123
124static unsigned int
125conf_read(unsigned long addr, unsigned char type1)
126{
127 unsigned long flags;
128 unsigned int stat0, value;
129 unsigned int haxr2 = 0;
130
131 local_irq_save(flags); /* avoid getting hit by machine check */
132
133 DBGC(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
134
135 /* Reset status register to avoid losing errors. */
136 stat0 = *(vuip)APECS_IOC_DCSR;
137 *(vuip)APECS_IOC_DCSR = stat0;
138 mb();
139 DBGC(("conf_read: APECS DCSR was 0x%x\n", stat0));
140
141 /* If Type1 access, must set HAE #2. */
142 if (type1) {
143 haxr2 = *(vuip)APECS_IOC_HAXR2;
144 mb();
145 *(vuip)APECS_IOC_HAXR2 = haxr2 | 1;
146 DBGC(("conf_read: TYPE1 access\n"));
147 }
148
149 draina();
150 mcheck_expected(0) = 1;
151 mcheck_taken(0) = 0;
152 mb();
153
154 /* Access configuration space. */
155
156 /* Some SRMs step on these registers during a machine check. */
157 asm volatile("ldl %0,%1; mb; mb" : "=r"(value) : "m"(*(vuip)addr)
158 : "$9", "$10", "$11", "$12", "$13", "$14", "memory");
159
160 if (mcheck_taken(0)) {
161 mcheck_taken(0) = 0;
162 value = 0xffffffffU;
163 mb();
164 }
165 mcheck_expected(0) = 0;
166 mb();
167
168#if 1
169 /*
170 * david.rusling@reo.mts.dec.com. This code is needed for the
171 * EB64+ as it does not generate a machine check (why I don't
172 * know). When we build kernels for one particular platform
173 * then we can make this conditional on the type.
174 */
175 draina();
176
177 /* Now look for any errors. */
178 stat0 = *(vuip)APECS_IOC_DCSR;
179 DBGC(("conf_read: APECS DCSR after read 0x%x\n", stat0));
180
181 /* Is any error bit set? */
182 if (stat0 & 0xffe0U) {
183 /* If not NDEV, print status. */
184 if (!(stat0 & 0x0800)) {
185 printk("apecs.c:conf_read: got stat0=%x\n", stat0);
186 }
187
188 /* Reset error status. */
189 *(vuip)APECS_IOC_DCSR = stat0;
190 mb();
191 wrmces(0x7); /* reset machine check */
192 value = 0xffffffff;
193 }
194#endif
195
196 /* If Type1 access, must reset HAE #2 so normal IO space ops work. */
197 if (type1) {
198 *(vuip)APECS_IOC_HAXR2 = haxr2 & ~1;
199 mb();
200 }
201 local_irq_restore(flags);
202
203 return value;
204}
205
206static void
207conf_write(unsigned long addr, unsigned int value, unsigned char type1)
208{
209 unsigned long flags;
210 unsigned int stat0;
211 unsigned int haxr2 = 0;
212
213 local_irq_save(flags); /* avoid getting hit by machine check */
214
215 /* Reset status register to avoid losing errors. */
216 stat0 = *(vuip)APECS_IOC_DCSR;
217 *(vuip)APECS_IOC_DCSR = stat0;
218 mb();
219
220 /* If Type1 access, must set HAE #2. */
221 if (type1) {
222 haxr2 = *(vuip)APECS_IOC_HAXR2;
223 mb();
224 *(vuip)APECS_IOC_HAXR2 = haxr2 | 1;
225 }
226
227 draina();
228 mcheck_expected(0) = 1;
229 mb();
230
231 /* Access configuration space. */
232 *(vuip)addr = value;
233 mb();
234 mb(); /* magic */
235 mcheck_expected(0) = 0;
236 mb();
237
238#if 1
239 /*
240 * david.rusling@reo.mts.dec.com. This code is needed for the
241 * EB64+ as it does not generate a machine check (why I don't
242 * know). When we build kernels for one particular platform
243 * then we can make this conditional on the type.
244 */
245 draina();
246
247 /* Now look for any errors. */
248 stat0 = *(vuip)APECS_IOC_DCSR;
249
250 /* Is any error bit set? */
251 if (stat0 & 0xffe0U) {
252 /* If not NDEV, print status. */
253 if (!(stat0 & 0x0800)) {
254 printk("apecs.c:conf_write: got stat0=%x\n", stat0);
255 }
256
257 /* Reset error status. */
258 *(vuip)APECS_IOC_DCSR = stat0;
259 mb();
260 wrmces(0x7); /* reset machine check */
261 }
262#endif
263
264 /* If Type1 access, must reset HAE #2 so normal IO space ops work. */
265 if (type1) {
266 *(vuip)APECS_IOC_HAXR2 = haxr2 & ~1;
267 mb();
268 }
269 local_irq_restore(flags);
270}
271
272static int
273apecs_read_config(struct pci_bus *bus, unsigned int devfn, int where,
274 int size, u32 *value)
275{
276 unsigned long addr, pci_addr;
277 unsigned char type1;
278 long mask;
279 int shift;
280
281 if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1))
282 return PCIBIOS_DEVICE_NOT_FOUND;
283
284 mask = (size - 1) * 8;
285 shift = (where & 3) * 8;
286 addr = (pci_addr << 5) + mask + APECS_CONF;
287 *value = conf_read(addr, type1) >> (shift);
288 return PCIBIOS_SUCCESSFUL;
289}
290
291static int
292apecs_write_config(struct pci_bus *bus, unsigned int devfn, int where,
293 int size, u32 value)
294{
295 unsigned long addr, pci_addr;
296 unsigned char type1;
297 long mask;
298
299 if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1))
300 return PCIBIOS_DEVICE_NOT_FOUND;
301
302 mask = (size - 1) * 8;
303 addr = (pci_addr << 5) + mask + APECS_CONF;
304 conf_write(addr, value << ((where & 3) * 8), type1);
305 return PCIBIOS_SUCCESSFUL;
306}
307
308struct pci_ops apecs_pci_ops =
309{
310 .read = apecs_read_config,
311 .write = apecs_write_config,
312};
313
314void
315apecs_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
316{
317 wmb();
318 *(vip)APECS_IOC_TBIA = 0;
319 mb();
320}
321
322void __init
323apecs_init_arch(void)
324{
325 struct pci_controller *hose;
326
327 /*
328 * Create our single hose.
329 */
330
331 pci_isa_hose = hose = alloc_pci_controller();
332 hose->io_space = &ioport_resource;
333 hose->mem_space = &iomem_resource;
334 hose->index = 0;
335
336 hose->sparse_mem_base = APECS_SPARSE_MEM - IDENT_ADDR;
337 hose->dense_mem_base = APECS_DENSE_MEM - IDENT_ADDR;
338 hose->sparse_io_base = APECS_IO - IDENT_ADDR;
339 hose->dense_io_base = 0;
340
341 /*
342 * Set up the PCI to main memory translation windows.
343 *
344 * Window 1 is direct access 1GB at 1GB
345 * Window 2 is scatter-gather 8MB at 8MB (for isa)
346 */
347 hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
348 hose->sg_pci = NULL;
349 __direct_map_base = 0x40000000;
350 __direct_map_size = 0x40000000;
351
352 *(vuip)APECS_IOC_PB1R = __direct_map_base | 0x00080000;
353 *(vuip)APECS_IOC_PM1R = (__direct_map_size - 1) & 0xfff00000U;
354 *(vuip)APECS_IOC_TB1R = 0;
355
356 *(vuip)APECS_IOC_PB2R = hose->sg_isa->dma_base | 0x000c0000;
357 *(vuip)APECS_IOC_PM2R = (hose->sg_isa->size - 1) & 0xfff00000;
358 *(vuip)APECS_IOC_TB2R = virt_to_phys(hose->sg_isa->ptes) >> 1;
359
360 apecs_pci_tbi(hose, 0, -1);
361
362 /*
363 * Finally, clear the HAXR2 register, which gets used
364 * for PCI Config Space accesses. That is the way
365 * we want to use it, and we do not want to depend on
366 * what ARC or SRM might have left behind...
367 */
368 *(vuip)APECS_IOC_HAXR2 = 0;
369 mb();
370}
371
372void
373apecs_pci_clr_err(void)
374{
375 unsigned int jd;
376
377 jd = *(vuip)APECS_IOC_DCSR;
378 if (jd & 0xffe0L) {
379 *(vuip)APECS_IOC_SEAR;
380 *(vuip)APECS_IOC_DCSR = jd | 0xffe1L;
381 mb();
382 *(vuip)APECS_IOC_DCSR;
383 }
384 *(vuip)APECS_IOC_TBIA = (unsigned int)APECS_IOC_TBIA;
385 mb();
386 *(vuip)APECS_IOC_TBIA;
387}
388
389void
390apecs_machine_check(unsigned long vector, unsigned long la_ptr,
391 struct pt_regs * regs)
392{
393 struct el_common *mchk_header;
394 struct el_apecs_procdata *mchk_procdata;
395 struct el_apecs_sysdata_mcheck *mchk_sysdata;
396
397 mchk_header = (struct el_common *)la_ptr;
398
399 mchk_procdata = (struct el_apecs_procdata *)
400 (la_ptr + mchk_header->proc_offset
401 - sizeof(mchk_procdata->paltemp));
402
403 mchk_sysdata = (struct el_apecs_sysdata_mcheck *)
404 (la_ptr + mchk_header->sys_offset);
405
406
407 /* Clear the error before any reporting. */
408 mb();
409 mb(); /* magic */
410 draina();
411 apecs_pci_clr_err();
412 wrmces(0x7); /* reset machine check pending flag */
413 mb();
414
415 process_mcheck_info(vector, la_ptr, regs, "APECS",
416 (mcheck_expected(0)
417 && (mchk_sysdata->epic_dcsr & 0x0c00UL)));
418}
diff --git a/arch/alpha/kernel/core_cia.c b/arch/alpha/kernel/core_cia.c
new file mode 100644
index 000000000000..fd563064363c
--- /dev/null
+++ b/arch/alpha/kernel/core_cia.c
@@ -0,0 +1,1212 @@
1/*
2 * linux/arch/alpha/kernel/core_cia.c
3 *
4 * Written by David A Rusling (david.rusling@reo.mts.dec.com).
5 * December 1995.
6 *
7 * Copyright (C) 1995 David A Rusling
8 * Copyright (C) 1997, 1998 Jay Estabrook
9 * Copyright (C) 1998, 1999, 2000 Richard Henderson
10 *
11 * Code common to all CIA core logic chips.
12 */
13
14#define __EXTERN_INLINE inline
15#include <asm/io.h>
16#include <asm/core_cia.h>
17#undef __EXTERN_INLINE
18
19#include <linux/types.h>
20#include <linux/pci.h>
21#include <linux/sched.h>
22#include <linux/init.h>
23#include <linux/bootmem.h>
24
25#include <asm/ptrace.h>
26
27#include "proto.h"
28#include "pci_impl.h"
29
30
31/*
32 * NOTE: Herein lie back-to-back mb instructions. They are magic.
33 * One plausible explanation is that the i/o controller does not properly
34 * handle the system transaction. Another involves timing. Ho hum.
35 */
36
37#define DEBUG_CONFIG 0
38#if DEBUG_CONFIG
39# define DBGC(args) printk args
40#else
41# define DBGC(args)
42#endif
43
44#define vip volatile int *
45
46/*
47 * Given a bus, device, and function number, compute resulting
48 * configuration space address. It is therefore not safe to have
49 * concurrent invocations to configuration space access routines, but
50 * there really shouldn't be any need for this.
51 *
52 * Type 0:
53 *
54 * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
55 * 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
56 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57 * | | |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|
58 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59 *
60 * 31:11 Device select bit.
61 * 10:8 Function number
62 * 7:2 Register number
63 *
64 * Type 1:
65 *
66 * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
67 * 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
68 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69 * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
70 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
71 *
72 * 31:24 reserved
73 * 23:16 bus number (8 bits = 128 possible buses)
74 * 15:11 Device number (5 bits)
75 * 10:8 function number
76 * 7:2 register number
77 *
78 * Notes:
79 * The function number selects which function of a multi-function device
80 * (e.g., SCSI and Ethernet).
81 *
82 * The register selects a DWORD (32 bit) register offset. Hence it
83 * doesn't get shifted by 2 bits as we want to "drop" the bottom two
84 * bits.
85 */
86
87static int
88mk_conf_addr(struct pci_bus *bus_dev, unsigned int device_fn, int where,
89 unsigned long *pci_addr, unsigned char *type1)
90{
91 u8 bus = bus_dev->number;
92
93 *type1 = (bus != 0);
94 *pci_addr = (bus << 16) | (device_fn << 8) | where;
95
96 DBGC(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
97 " returning address 0x%p\n"
98 bus, device_fn, where, *pci_addr));
99
100 return 0;
101}
102
103static unsigned int
104conf_read(unsigned long addr, unsigned char type1)
105{
106 unsigned long flags;
107 int stat0, value;
108 int cia_cfg = 0;
109
110 DBGC(("conf_read(addr=0x%lx, type1=%d) ", addr, type1));
111 local_irq_save(flags);
112
113 /* Reset status register to avoid losing errors. */
114 stat0 = *(vip)CIA_IOC_CIA_ERR;
115 *(vip)CIA_IOC_CIA_ERR = stat0;
116 mb();
117 *(vip)CIA_IOC_CIA_ERR; /* re-read to force write */
118
119 /* If Type1 access, must set CIA CFG. */
120 if (type1) {
121 cia_cfg = *(vip)CIA_IOC_CFG;
122 *(vip)CIA_IOC_CFG = (cia_cfg & ~3) | 1;
123 mb();
124 *(vip)CIA_IOC_CFG;
125 }
126
127 mb();
128 draina();
129 mcheck_expected(0) = 1;
130 mcheck_taken(0) = 0;
131 mb();
132
133 /* Access configuration space. */
134 value = *(vip)addr;
135 mb();
136 mb(); /* magic */
137 if (mcheck_taken(0)) {
138 mcheck_taken(0) = 0;
139 value = 0xffffffff;
140 mb();
141 }
142 mcheck_expected(0) = 0;
143 mb();
144
145 /* If Type1 access, must reset IOC CFG so normal IO space ops work. */
146 if (type1) {
147 *(vip)CIA_IOC_CFG = cia_cfg;
148 mb();
149 *(vip)CIA_IOC_CFG;
150 }
151
152 local_irq_restore(flags);
153 DBGC(("done\n"));
154
155 return value;
156}
157
158static void
159conf_write(unsigned long addr, unsigned int value, unsigned char type1)
160{
161 unsigned long flags;
162 int stat0, cia_cfg = 0;
163
164 DBGC(("conf_write(addr=0x%lx, type1=%d) ", addr, type1));
165 local_irq_save(flags);
166
167 /* Reset status register to avoid losing errors. */
168 stat0 = *(vip)CIA_IOC_CIA_ERR;
169 *(vip)CIA_IOC_CIA_ERR = stat0;
170 mb();
171 *(vip)CIA_IOC_CIA_ERR; /* re-read to force write */
172
173 /* If Type1 access, must set CIA CFG. */
174 if (type1) {
175 cia_cfg = *(vip)CIA_IOC_CFG;
176 *(vip)CIA_IOC_CFG = (cia_cfg & ~3) | 1;
177 mb();
178 *(vip)CIA_IOC_CFG;
179 }
180
181 mb();
182 draina();
183 mcheck_expected(0) = 1;
184 mcheck_taken(0) = 0;
185 mb();
186
187 /* Access configuration space. */
188 *(vip)addr = value;
189 mb();
190 *(vip)addr; /* read back to force the write */
191
192 mcheck_expected(0) = 0;
193 mb();
194
195 /* If Type1 access, must reset IOC CFG so normal IO space ops work. */
196 if (type1) {
197 *(vip)CIA_IOC_CFG = cia_cfg;
198 mb();
199 *(vip)CIA_IOC_CFG;
200 }
201
202 local_irq_restore(flags);
203 DBGC(("done\n"));
204}
205
206static int
207cia_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size,
208 u32 *value)
209{
210 unsigned long addr, pci_addr;
211 long mask;
212 unsigned char type1;
213 int shift;
214
215 if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1))
216 return PCIBIOS_DEVICE_NOT_FOUND;
217
218 mask = (size - 1) * 8;
219 shift = (where & 3) * 8;
220 addr = (pci_addr << 5) + mask + CIA_CONF;
221 *value = conf_read(addr, type1) >> (shift);
222 return PCIBIOS_SUCCESSFUL;
223}
224
225static int
226cia_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size,
227 u32 value)
228{
229 unsigned long addr, pci_addr;
230 long mask;
231 unsigned char type1;
232
233 if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1))
234 return PCIBIOS_DEVICE_NOT_FOUND;
235
236 mask = (size - 1) * 8;
237 addr = (pci_addr << 5) + mask + CIA_CONF;
238 conf_write(addr, value << ((where & 3) * 8), type1);
239 return PCIBIOS_SUCCESSFUL;
240}
241
242struct pci_ops cia_pci_ops =
243{
244 .read = cia_read_config,
245 .write = cia_write_config,
246};
247
248/*
249 * CIA Pass 1 and PYXIS Pass 1 and 2 have a broken scatter-gather tlb.
250 * It cannot be invalidated. Rather than hard code the pass numbers,
251 * actually try the tbia to see if it works.
252 */
253
254void
255cia_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
256{
257 wmb();
258 *(vip)CIA_IOC_PCI_TBIA = 3; /* Flush all locked and unlocked. */
259 mb();
260 *(vip)CIA_IOC_PCI_TBIA;
261}
262
263/*
264 * On PYXIS, even if the tbia works, we cannot use it. It effectively locks
265 * the chip (as well as direct write to the tag registers) if there is a
266 * SG DMA operation in progress. This is true at least for PYXIS rev. 1,
267 * so always use the method below.
268 */
269/*
270 * This is the method NT and NetBSD use.
271 *
272 * Allocate mappings, and put the chip into DMA loopback mode to read a
273 * garbage page. This works by causing TLB misses, causing old entries to
274 * be purged to make room for the new entries coming in for the garbage page.
275 */
276
277#define CIA_BROKEN_TBIA_BASE 0x30000000
278#define CIA_BROKEN_TBIA_SIZE 1024
279
280/* Always called with interrupts disabled */
281void
282cia_pci_tbi_try2(struct pci_controller *hose,
283 dma_addr_t start, dma_addr_t end)
284{
285 void __iomem *bus_addr;
286 int ctrl;
287
288 /* Put the chip into PCI loopback mode. */
289 mb();
290 ctrl = *(vip)CIA_IOC_CIA_CTRL;
291 *(vip)CIA_IOC_CIA_CTRL = ctrl | CIA_CTRL_PCI_LOOP_EN;
292 mb();
293 *(vip)CIA_IOC_CIA_CTRL;
294 mb();
295
296 /* Read from PCI dense memory space at TBI_ADDR, skipping 32k on
297 each read. This forces SG TLB misses. NetBSD claims that the
298 TLB entries are not quite LRU, meaning that we need to read more
299 times than there are actual tags. The 2117x docs claim strict
300 round-robin. Oh well, we've come this far... */
301 /* Even better - as seen on the PYXIS rev 1 the TLB tags 0-3 can
302 be filled by the TLB misses *only once* after being invalidated
303 (by tbia or direct write). Next misses won't update them even
304 though the lock bits are cleared. Tags 4-7 are "quite LRU" though,
305 so use them and read at window 3 base exactly 4 times. Reading
306 more sometimes makes the chip crazy. -ink */
307
308 bus_addr = cia_ioremap(CIA_BROKEN_TBIA_BASE, 32768 * 4);
309
310 cia_readl(bus_addr + 0x00000);
311 cia_readl(bus_addr + 0x08000);
312 cia_readl(bus_addr + 0x10000);
313 cia_readl(bus_addr + 0x18000);
314
315 cia_iounmap(bus_addr);
316
317 /* Restore normal PCI operation. */
318 mb();
319 *(vip)CIA_IOC_CIA_CTRL = ctrl;
320 mb();
321 *(vip)CIA_IOC_CIA_CTRL;
322 mb();
323}
324
325static inline void
326cia_prepare_tbia_workaround(int window)
327{
328 unsigned long *ppte, pte;
329 long i;
330
331 /* Use minimal 1K map. */
332 ppte = __alloc_bootmem(CIA_BROKEN_TBIA_SIZE, 32768, 0);
333 pte = (virt_to_phys(ppte) >> (PAGE_SHIFT - 1)) | 1;
334
335 for (i = 0; i < CIA_BROKEN_TBIA_SIZE / sizeof(unsigned long); ++i)
336 ppte[i] = pte;
337
338 *(vip)CIA_IOC_PCI_Wn_BASE(window) = CIA_BROKEN_TBIA_BASE | 3;
339 *(vip)CIA_IOC_PCI_Wn_MASK(window)
340 = (CIA_BROKEN_TBIA_SIZE*1024 - 1) & 0xfff00000;
341 *(vip)CIA_IOC_PCI_Tn_BASE(window) = virt_to_phys(ppte) >> 2;
342}
343
344static void __init
345verify_tb_operation(void)
346{
347 static int page[PAGE_SIZE/4]
348 __attribute__((aligned(PAGE_SIZE)))
349 __initdata = { 0 };
350
351 struct pci_iommu_arena *arena = pci_isa_hose->sg_isa;
352 int ctrl, addr0, tag0, pte0, data0;
353 int temp, use_tbia_try2 = 0;
354 void __iomem *bus_addr;
355
356 /* pyxis -- tbia is broken */
357 if (pci_isa_hose->dense_io_base)
358 use_tbia_try2 = 1;
359
360 /* Put the chip into PCI loopback mode. */
361 mb();
362 ctrl = *(vip)CIA_IOC_CIA_CTRL;
363 *(vip)CIA_IOC_CIA_CTRL = ctrl | CIA_CTRL_PCI_LOOP_EN;
364 mb();
365 *(vip)CIA_IOC_CIA_CTRL;
366 mb();
367
368 /* Write a valid entry directly into the TLB registers. */
369
370 addr0 = arena->dma_base;
371 tag0 = addr0 | 1;
372 pte0 = (virt_to_phys(page) >> (PAGE_SHIFT - 1)) | 1;
373
374 *(vip)CIA_IOC_TB_TAGn(0) = tag0;
375 *(vip)CIA_IOC_TB_TAGn(1) = 0;
376 *(vip)CIA_IOC_TB_TAGn(2) = 0;
377 *(vip)CIA_IOC_TB_TAGn(3) = 0;
378 *(vip)CIA_IOC_TB_TAGn(4) = 0;
379 *(vip)CIA_IOC_TB_TAGn(5) = 0;
380 *(vip)CIA_IOC_TB_TAGn(6) = 0;
381 *(vip)CIA_IOC_TB_TAGn(7) = 0;
382 *(vip)CIA_IOC_TBn_PAGEm(0,0) = pte0;
383 *(vip)CIA_IOC_TBn_PAGEm(0,1) = 0;
384 *(vip)CIA_IOC_TBn_PAGEm(0,2) = 0;
385 *(vip)CIA_IOC_TBn_PAGEm(0,3) = 0;
386 mb();
387
388 /* Get a usable bus address */
389 bus_addr = cia_ioremap(addr0, 8*PAGE_SIZE);
390
391 /* First, verify we can read back what we've written. If
392 this fails, we can't be sure of any of the other testing
393 we're going to do, so bail. */
394 /* ??? Actually, we could do the work with machine checks.
395 By passing this register update test, we pretty much
396 guarantee that cia_pci_tbi_try1 works. If this test
397 fails, cia_pci_tbi_try2 might still work. */
398
399 temp = *(vip)CIA_IOC_TB_TAGn(0);
400 if (temp != tag0) {
401 printk("pci: failed tb register update test "
402 "(tag0 %#x != %#x)\n", temp, tag0);
403 goto failed;
404 }
405 temp = *(vip)CIA_IOC_TB_TAGn(1);
406 if (temp != 0) {
407 printk("pci: failed tb register update test "
408 "(tag1 %#x != 0)\n", temp);
409 goto failed;
410 }
411 temp = *(vip)CIA_IOC_TBn_PAGEm(0,0);
412 if (temp != pte0) {
413 printk("pci: failed tb register update test "
414 "(pte0 %#x != %#x)\n", temp, pte0);
415 goto failed;
416 }
417 printk("pci: passed tb register update test\n");
418
419 /* Second, verify we can actually do I/O through this entry. */
420
421 data0 = 0xdeadbeef;
422 page[0] = data0;
423 mcheck_expected(0) = 1;
424 mcheck_taken(0) = 0;
425 mb();
426 temp = cia_readl(bus_addr);
427 mb();
428 mcheck_expected(0) = 0;
429 mb();
430 if (mcheck_taken(0)) {
431 printk("pci: failed sg loopback i/o read test (mcheck)\n");
432 goto failed;
433 }
434 if (temp != data0) {
435 printk("pci: failed sg loopback i/o read test "
436 "(%#x != %#x)\n", temp, data0);
437 goto failed;
438 }
439 printk("pci: passed sg loopback i/o read test\n");
440
441 /* Third, try to invalidate the TLB. */
442
443 if (! use_tbia_try2) {
444 cia_pci_tbi(arena->hose, 0, -1);
445 temp = *(vip)CIA_IOC_TB_TAGn(0);
446 if (temp & 1) {
447 use_tbia_try2 = 1;
448 printk("pci: failed tbia test; workaround available\n");
449 } else {
450 printk("pci: passed tbia test\n");
451 }
452 }
453
454 /* Fourth, verify the TLB snoops the EV5's caches when
455 doing a tlb fill. */
456
457 data0 = 0x5adda15e;
458 page[0] = data0;
459 arena->ptes[4] = pte0;
460 mcheck_expected(0) = 1;
461 mcheck_taken(0) = 0;
462 mb();
463 temp = cia_readl(bus_addr + 4*PAGE_SIZE);
464 mb();
465 mcheck_expected(0) = 0;
466 mb();
467 if (mcheck_taken(0)) {
468 printk("pci: failed pte write cache snoop test (mcheck)\n");
469 goto failed;
470 }
471 if (temp != data0) {
472 printk("pci: failed pte write cache snoop test "
473 "(%#x != %#x)\n", temp, data0);
474 goto failed;
475 }
476 printk("pci: passed pte write cache snoop test\n");
477
478 /* Fifth, verify that a previously invalid PTE entry gets
479 filled from the page table. */
480
481 data0 = 0xabcdef12;
482 page[0] = data0;
483 arena->ptes[5] = pte0;
484 mcheck_expected(0) = 1;
485 mcheck_taken(0) = 0;
486 mb();
487 temp = cia_readl(bus_addr + 5*PAGE_SIZE);
488 mb();
489 mcheck_expected(0) = 0;
490 mb();
491 if (mcheck_taken(0)) {
492 printk("pci: failed valid tag invalid pte reload test "
493 "(mcheck; workaround available)\n");
494 /* Work around this bug by aligning new allocations
495 on 4 page boundaries. */
496 arena->align_entry = 4;
497 } else if (temp != data0) {
498 printk("pci: failed valid tag invalid pte reload test "
499 "(%#x != %#x)\n", temp, data0);
500 goto failed;
501 } else {
502 printk("pci: passed valid tag invalid pte reload test\n");
503 }
504
505 /* Sixth, verify machine checks are working. Test invalid
506 pte under the same valid tag as we used above. */
507
508 mcheck_expected(0) = 1;
509 mcheck_taken(0) = 0;
510 mb();
511 temp = cia_readl(bus_addr + 6*PAGE_SIZE);
512 mb();
513 mcheck_expected(0) = 0;
514 mb();
515 printk("pci: %s pci machine check test\n",
516 mcheck_taken(0) ? "passed" : "failed");
517
518 /* Clean up after the tests. */
519 arena->ptes[4] = 0;
520 arena->ptes[5] = 0;
521
522 if (use_tbia_try2) {
523 alpha_mv.mv_pci_tbi = cia_pci_tbi_try2;
524
525 /* Tags 0-3 must be disabled if we use this workaraund. */
526 wmb();
527 *(vip)CIA_IOC_TB_TAGn(0) = 2;
528 *(vip)CIA_IOC_TB_TAGn(1) = 2;
529 *(vip)CIA_IOC_TB_TAGn(2) = 2;
530 *(vip)CIA_IOC_TB_TAGn(3) = 2;
531
532 printk("pci: tbia workaround enabled\n");
533 }
534 alpha_mv.mv_pci_tbi(arena->hose, 0, -1);
535
536exit:
537 /* unmap the bus addr */
538 cia_iounmap(bus_addr);
539
540 /* Restore normal PCI operation. */
541 mb();
542 *(vip)CIA_IOC_CIA_CTRL = ctrl;
543 mb();
544 *(vip)CIA_IOC_CIA_CTRL;
545 mb();
546 return;
547
548failed:
549 printk("pci: disabling sg translation window\n");
550 *(vip)CIA_IOC_PCI_W0_BASE = 0;
551 *(vip)CIA_IOC_PCI_W1_BASE = 0;
552 pci_isa_hose->sg_isa = NULL;
553 alpha_mv.mv_pci_tbi = NULL;
554 goto exit;
555}
556
557#if defined(ALPHA_RESTORE_SRM_SETUP)
558/* Save CIA configuration data as the console had it set up. */
559struct
560{
561 unsigned int hae_mem;
562 unsigned int hae_io;
563 unsigned int pci_dac_offset;
564 unsigned int err_mask;
565 unsigned int cia_ctrl;
566 unsigned int cia_cnfg;
567 struct {
568 unsigned int w_base;
569 unsigned int w_mask;
570 unsigned int t_base;
571 } window[4];
572} saved_config __attribute((common));
573
574void
575cia_save_srm_settings(int is_pyxis)
576{
577 int i;
578
579 /* Save some important registers. */
580 saved_config.err_mask = *(vip)CIA_IOC_ERR_MASK;
581 saved_config.cia_ctrl = *(vip)CIA_IOC_CIA_CTRL;
582 saved_config.hae_mem = *(vip)CIA_IOC_HAE_MEM;
583 saved_config.hae_io = *(vip)CIA_IOC_HAE_IO;
584 saved_config.pci_dac_offset = *(vip)CIA_IOC_PCI_W_DAC;
585
586 if (is_pyxis)
587 saved_config.cia_cnfg = *(vip)CIA_IOC_CIA_CNFG;
588 else
589 saved_config.cia_cnfg = 0;
590
591 /* Save DMA windows configuration. */
592 for (i = 0; i < 4; i++) {
593 saved_config.window[i].w_base = *(vip)CIA_IOC_PCI_Wn_BASE(i);
594 saved_config.window[i].w_mask = *(vip)CIA_IOC_PCI_Wn_MASK(i);
595 saved_config.window[i].t_base = *(vip)CIA_IOC_PCI_Tn_BASE(i);
596 }
597 mb();
598}
599
600void
601cia_restore_srm_settings(void)
602{
603 int i;
604
605 for (i = 0; i < 4; i++) {
606 *(vip)CIA_IOC_PCI_Wn_BASE(i) = saved_config.window[i].w_base;
607 *(vip)CIA_IOC_PCI_Wn_MASK(i) = saved_config.window[i].w_mask;
608 *(vip)CIA_IOC_PCI_Tn_BASE(i) = saved_config.window[i].t_base;
609 }
610
611 *(vip)CIA_IOC_HAE_MEM = saved_config.hae_mem;
612 *(vip)CIA_IOC_HAE_IO = saved_config.hae_io;
613 *(vip)CIA_IOC_PCI_W_DAC = saved_config.pci_dac_offset;
614 *(vip)CIA_IOC_ERR_MASK = saved_config.err_mask;
615 *(vip)CIA_IOC_CIA_CTRL = saved_config.cia_ctrl;
616
617 if (saved_config.cia_cnfg) /* Must be pyxis. */
618 *(vip)CIA_IOC_CIA_CNFG = saved_config.cia_cnfg;
619
620 mb();
621}
622#else /* ALPHA_RESTORE_SRM_SETUP */
623#define cia_save_srm_settings(p) do {} while (0)
624#define cia_restore_srm_settings() do {} while (0)
625#endif /* ALPHA_RESTORE_SRM_SETUP */
626
627
628static void __init
629do_init_arch(int is_pyxis)
630{
631 struct pci_controller *hose;
632 int temp, cia_rev, tbia_window;
633
634 cia_rev = *(vip)CIA_IOC_CIA_REV & CIA_REV_MASK;
635 printk("pci: cia revision %d%s\n",
636 cia_rev, is_pyxis ? " (pyxis)" : "");
637
638 if (alpha_using_srm)
639 cia_save_srm_settings(is_pyxis);
640
641 /* Set up error reporting. */
642 temp = *(vip)CIA_IOC_ERR_MASK;
643 temp &= ~(CIA_ERR_CPU_PE | CIA_ERR_MEM_NEM | CIA_ERR_PA_PTE_INV
644 | CIA_ERR_RCVD_MAS_ABT | CIA_ERR_RCVD_TAR_ABT);
645 *(vip)CIA_IOC_ERR_MASK = temp;
646
647 /* Clear all currently pending errors. */
648 temp = *(vip)CIA_IOC_CIA_ERR;
649 *(vip)CIA_IOC_CIA_ERR = temp;
650
651 /* Turn on mchecks. */
652 temp = *(vip)CIA_IOC_CIA_CTRL;
653 temp |= CIA_CTRL_FILL_ERR_EN | CIA_CTRL_MCHK_ERR_EN;
654 *(vip)CIA_IOC_CIA_CTRL = temp;
655
656 /* Clear the CFG register, which gets used for PCI config space
657 accesses. That is the way we want to use it, and we do not
658 want to depend on what ARC or SRM might have left behind. */
659 *(vip)CIA_IOC_CFG = 0;
660
661 /* Zero the HAEs. */
662 *(vip)CIA_IOC_HAE_MEM = 0;
663 *(vip)CIA_IOC_HAE_IO = 0;
664
665 /* For PYXIS, we always use BWX bus and i/o accesses. To that end,
666 make sure they're enabled on the controller. At the same time,
667 enable the monster window. */
668 if (is_pyxis) {
669 temp = *(vip)CIA_IOC_CIA_CNFG;
670 temp |= CIA_CNFG_IOA_BWEN | CIA_CNFG_PCI_MWEN;
671 *(vip)CIA_IOC_CIA_CNFG = temp;
672 }
673
674 /* Synchronize with all previous changes. */
675 mb();
676 *(vip)CIA_IOC_CIA_REV;
677
678 /*
679 * Create our single hose.
680 */
681
682 pci_isa_hose = hose = alloc_pci_controller();
683 hose->io_space = &ioport_resource;
684 hose->mem_space = &iomem_resource;
685 hose->index = 0;
686
687 if (! is_pyxis) {
688 struct resource *hae_mem = alloc_resource();
689 hose->mem_space = hae_mem;
690
691 hae_mem->start = 0;
692 hae_mem->end = CIA_MEM_R1_MASK;
693 hae_mem->name = pci_hae0_name;
694 hae_mem->flags = IORESOURCE_MEM;
695
696 if (request_resource(&iomem_resource, hae_mem) < 0)
697 printk(KERN_ERR "Failed to request HAE_MEM\n");
698
699 hose->sparse_mem_base = CIA_SPARSE_MEM - IDENT_ADDR;
700 hose->dense_mem_base = CIA_DENSE_MEM - IDENT_ADDR;
701 hose->sparse_io_base = CIA_IO - IDENT_ADDR;
702 hose->dense_io_base = 0;
703 } else {
704 hose->sparse_mem_base = 0;
705 hose->dense_mem_base = CIA_BW_MEM - IDENT_ADDR;
706 hose->sparse_io_base = 0;
707 hose->dense_io_base = CIA_BW_IO - IDENT_ADDR;
708 }
709
710 /*
711 * Set up the PCI to main memory translation windows.
712 *
713 * Window 0 is S/G 8MB at 8MB (for isa)
714 * Window 1 is S/G 1MB at 768MB (for tbia) (unused for CIA rev 1)
715 * Window 2 is direct access 2GB at 2GB
716 * Window 3 is DAC access 4GB at 8GB (or S/G for tbia if CIA rev 1)
717 *
718 * ??? NetBSD hints that page tables must be aligned to 32K,
719 * possibly due to a hardware bug. This is over-aligned
720 * from the 8K alignment one would expect for an 8MB window.
721 * No description of what revisions affected.
722 */
723
724 hose->sg_pci = NULL;
725 hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 32768);
726
727 __direct_map_base = 0x80000000;
728 __direct_map_size = 0x80000000;
729
730 *(vip)CIA_IOC_PCI_W0_BASE = hose->sg_isa->dma_base | 3;
731 *(vip)CIA_IOC_PCI_W0_MASK = (hose->sg_isa->size - 1) & 0xfff00000;
732 *(vip)CIA_IOC_PCI_T0_BASE = virt_to_phys(hose->sg_isa->ptes) >> 2;
733
734 *(vip)CIA_IOC_PCI_W2_BASE = __direct_map_base | 1;
735 *(vip)CIA_IOC_PCI_W2_MASK = (__direct_map_size - 1) & 0xfff00000;
736 *(vip)CIA_IOC_PCI_T2_BASE = 0 >> 2;
737
738 /* On PYXIS we have the monster window, selected by bit 40, so
739 there is no need for window3 to be enabled.
740
741 On CIA, we don't have true arbitrary addressing -- bits <39:32>
742 are compared against W_DAC. We can, however, directly map 4GB,
743 which is better than before. However, due to assumptions made
744 elsewhere, we should not claim that we support DAC unless that
745 4GB covers all of physical memory.
746
747 On CIA rev 1, apparently W1 and W2 can't be used for SG.
748 At least, there are reports that it doesn't work for Alcor.
749 In that case, we have no choice but to use W3 for the TBIA
750 workaround, which means we can't use DAC at all. */
751
752 tbia_window = 1;
753 if (is_pyxis) {
754 *(vip)CIA_IOC_PCI_W3_BASE = 0;
755 } else if (cia_rev == 1) {
756 *(vip)CIA_IOC_PCI_W1_BASE = 0;
757 tbia_window = 3;
758 } else if (max_low_pfn > (0x100000000UL >> PAGE_SHIFT)) {
759 *(vip)CIA_IOC_PCI_W3_BASE = 0;
760 } else {
761 *(vip)CIA_IOC_PCI_W3_BASE = 0x00000000 | 1 | 8;
762 *(vip)CIA_IOC_PCI_W3_MASK = 0xfff00000;
763 *(vip)CIA_IOC_PCI_T3_BASE = 0 >> 2;
764
765 alpha_mv.pci_dac_offset = 0x200000000UL;
766 *(vip)CIA_IOC_PCI_W_DAC = alpha_mv.pci_dac_offset >> 32;
767 }
768
769 /* Prepare workaround for apparently broken tbia. */
770 cia_prepare_tbia_workaround(tbia_window);
771}
772
773void __init
774cia_init_arch(void)
775{
776 do_init_arch(0);
777}
778
779void __init
780pyxis_init_arch(void)
781{
782 /* On pyxis machines we can precisely calculate the
783 CPU clock frequency using pyxis real time counter.
784 It's especially useful for SX164 with broken RTC.
785
786 Both CPU and chipset are driven by the single 16.666M
787 or 16.667M crystal oscillator. PYXIS_RT_COUNT clock is
788 66.66 MHz. -ink */
789
790 unsigned int cc0, cc1;
791 unsigned long pyxis_cc;
792
793 __asm__ __volatile__ ("rpcc %0" : "=r"(cc0));
794 pyxis_cc = *(vulp)PYXIS_RT_COUNT;
795 do { } while(*(vulp)PYXIS_RT_COUNT - pyxis_cc < 4096);
796 __asm__ __volatile__ ("rpcc %0" : "=r"(cc1));
797 cc1 -= cc0;
798 hwrpb->cycle_freq = ((cc1 >> 11) * 100000000UL) / 3;
799 hwrpb_update_checksum(hwrpb);
800
801 do_init_arch(1);
802}
803
804void
805cia_kill_arch(int mode)
806{
807 if (alpha_using_srm)
808 cia_restore_srm_settings();
809}
810
811void __init
812cia_init_pci(void)
813{
814 /* Must delay this from init_arch, as we need machine checks. */
815 verify_tb_operation();
816 common_init_pci();
817}
818
819static inline void
820cia_pci_clr_err(void)
821{
822 int jd;
823
824 jd = *(vip)CIA_IOC_CIA_ERR;
825 *(vip)CIA_IOC_CIA_ERR = jd;
826 mb();
827 *(vip)CIA_IOC_CIA_ERR; /* re-read to force write. */
828}
829
830#ifdef CONFIG_VERBOSE_MCHECK
831static void
832cia_decode_pci_error(struct el_CIA_sysdata_mcheck *cia, const char *msg)
833{
834 static const char * const pci_cmd_desc[16] = {
835 "Interrupt Acknowledge", "Special Cycle", "I/O Read",
836 "I/O Write", "Reserved 0x4", "Reserved 0x5", "Memory Read",
837 "Memory Write", "Reserved 0x8", "Reserved 0x9",
838 "Configuration Read", "Configuration Write",
839 "Memory Read Multiple", "Dual Address Cycle",
840 "Memory Read Line", "Memory Write and Invalidate"
841 };
842
843 if (cia->cia_err & (CIA_ERR_COR_ERR
844 | CIA_ERR_UN_COR_ERR
845 | CIA_ERR_MEM_NEM
846 | CIA_ERR_PA_PTE_INV)) {
847 static const char * const window_desc[6] = {
848 "No window active", "Window 0 hit", "Window 1 hit",
849 "Window 2 hit", "Window 3 hit", "Monster window hit"
850 };
851
852 const char *window;
853 const char *cmd;
854 unsigned long addr, tmp;
855 int lock, dac;
856
857 cmd = pci_cmd_desc[cia->pci_err0 & 0x7];
858 lock = (cia->pci_err0 >> 4) & 1;
859 dac = (cia->pci_err0 >> 5) & 1;
860
861 tmp = (cia->pci_err0 >> 8) & 0x1F;
862 tmp = ffs(tmp);
863 window = window_desc[tmp];
864
865 addr = cia->pci_err1;
866 if (dac) {
867 tmp = *(vip)CIA_IOC_PCI_W_DAC & 0xFFUL;
868 addr |= tmp << 32;
869 }
870
871 printk(KERN_CRIT "CIA machine check: %s\n", msg);
872 printk(KERN_CRIT " DMA command: %s\n", cmd);
873 printk(KERN_CRIT " PCI address: %#010lx\n", addr);
874 printk(KERN_CRIT " %s, Lock: %d, DAC: %d\n",
875 window, lock, dac);
876 } else if (cia->cia_err & (CIA_ERR_PERR
877 | CIA_ERR_PCI_ADDR_PE
878 | CIA_ERR_RCVD_MAS_ABT
879 | CIA_ERR_RCVD_TAR_ABT
880 | CIA_ERR_IOA_TIMEOUT)) {
881 static const char * const master_st_desc[16] = {
882 "Idle", "Drive bus", "Address step cycle",
883 "Address cycle", "Data cycle", "Last read data cycle",
884 "Last write data cycle", "Read stop cycle",
885 "Write stop cycle", "Read turnaround cycle",
886 "Write turnaround cycle", "Reserved 0xB",
887 "Reserved 0xC", "Reserved 0xD", "Reserved 0xE",
888 "Unknown state"
889 };
890 static const char * const target_st_desc[16] = {
891 "Idle", "Busy", "Read data cycle", "Write data cycle",
892 "Read stop cycle", "Write stop cycle",
893 "Read turnaround cycle", "Write turnaround cycle",
894 "Read wait cycle", "Write wait cycle",
895 "Reserved 0xA", "Reserved 0xB", "Reserved 0xC",
896 "Reserved 0xD", "Reserved 0xE", "Unknown state"
897 };
898
899 const char *cmd;
900 const char *master, *target;
901 unsigned long addr, tmp;
902 int dac;
903
904 master = master_st_desc[(cia->pci_err0 >> 16) & 0xF];
905 target = target_st_desc[(cia->pci_err0 >> 20) & 0xF];
906 cmd = pci_cmd_desc[(cia->pci_err0 >> 24) & 0xF];
907 dac = (cia->pci_err0 >> 28) & 1;
908
909 addr = cia->pci_err2;
910 if (dac) {
911 tmp = *(volatile int *)CIA_IOC_PCI_W_DAC & 0xFFUL;
912 addr |= tmp << 32;
913 }
914
915 printk(KERN_CRIT "CIA machine check: %s\n", msg);
916 printk(KERN_CRIT " PCI command: %s\n", cmd);
917 printk(KERN_CRIT " Master state: %s, Target state: %s\n",
918 master, target);
919 printk(KERN_CRIT " PCI address: %#010lx, DAC: %d\n",
920 addr, dac);
921 } else {
922 printk(KERN_CRIT "CIA machine check: %s\n", msg);
923 printk(KERN_CRIT " Unknown PCI error\n");
924 printk(KERN_CRIT " PCI_ERR0 = %#08lx", cia->pci_err0);
925 printk(KERN_CRIT " PCI_ERR1 = %#08lx", cia->pci_err1);
926 printk(KERN_CRIT " PCI_ERR2 = %#08lx", cia->pci_err2);
927 }
928}
929
930static void
931cia_decode_mem_error(struct el_CIA_sysdata_mcheck *cia, const char *msg)
932{
933 unsigned long mem_port_addr;
934 unsigned long mem_port_mask;
935 const char *mem_port_cmd;
936 const char *seq_state;
937 const char *set_select;
938 unsigned long tmp;
939
940 /* If this is a DMA command, also decode the PCI bits. */
941 if ((cia->mem_err1 >> 20) & 1)
942 cia_decode_pci_error(cia, msg);
943 else
944 printk(KERN_CRIT "CIA machine check: %s\n", msg);
945
946 mem_port_addr = cia->mem_err0 & 0xfffffff0;
947 mem_port_addr |= (cia->mem_err1 & 0x83UL) << 32;
948
949 mem_port_mask = (cia->mem_err1 >> 12) & 0xF;
950
951 tmp = (cia->mem_err1 >> 8) & 0xF;
952 tmp |= ((cia->mem_err1 >> 20) & 1) << 4;
953 if ((tmp & 0x1E) == 0x06)
954 mem_port_cmd = "WRITE BLOCK or WRITE BLOCK LOCK";
955 else if ((tmp & 0x1C) == 0x08)
956 mem_port_cmd = "READ MISS or READ MISS MODIFY";
957 else if (tmp == 0x1C)
958 mem_port_cmd = "BC VICTIM";
959 else if ((tmp & 0x1E) == 0x0E)
960 mem_port_cmd = "READ MISS MODIFY";
961 else if ((tmp & 0x1C) == 0x18)
962 mem_port_cmd = "DMA READ or DMA READ MODIFY";
963 else if ((tmp & 0x1E) == 0x12)
964 mem_port_cmd = "DMA WRITE";
965 else
966 mem_port_cmd = "Unknown";
967
968 tmp = (cia->mem_err1 >> 16) & 0xF;
969 switch (tmp) {
970 case 0x0:
971 seq_state = "Idle";
972 break;
973 case 0x1:
974 seq_state = "DMA READ or DMA WRITE";
975 break;
976 case 0x2: case 0x3:
977 seq_state = "READ MISS (or READ MISS MODIFY) with victim";
978 break;
979 case 0x4: case 0x5: case 0x6:
980 seq_state = "READ MISS (or READ MISS MODIFY) with no victim";
981 break;
982 case 0x8: case 0x9: case 0xB:
983 seq_state = "Refresh";
984 break;
985 case 0xC:
986 seq_state = "Idle, waiting for DMA pending read";
987 break;
988 case 0xE: case 0xF:
989 seq_state = "Idle, ras precharge";
990 break;
991 default:
992 seq_state = "Unknown";
993 break;
994 }
995
996 tmp = (cia->mem_err1 >> 24) & 0x1F;
997 switch (tmp) {
998 case 0x00: set_select = "Set 0 selected"; break;
999 case 0x01: set_select = "Set 1 selected"; break;
1000 case 0x02: set_select = "Set 2 selected"; break;
1001 case 0x03: set_select = "Set 3 selected"; break;
1002 case 0x04: set_select = "Set 4 selected"; break;
1003 case 0x05: set_select = "Set 5 selected"; break;
1004 case 0x06: set_select = "Set 6 selected"; break;
1005 case 0x07: set_select = "Set 7 selected"; break;
1006 case 0x08: set_select = "Set 8 selected"; break;
1007 case 0x09: set_select = "Set 9 selected"; break;
1008 case 0x0A: set_select = "Set A selected"; break;
1009 case 0x0B: set_select = "Set B selected"; break;
1010 case 0x0C: set_select = "Set C selected"; break;
1011 case 0x0D: set_select = "Set D selected"; break;
1012 case 0x0E: set_select = "Set E selected"; break;
1013 case 0x0F: set_select = "Set F selected"; break;
1014 case 0x10: set_select = "No set selected"; break;
1015 case 0x1F: set_select = "Refresh cycle"; break;
1016 default: set_select = "Unknown"; break;
1017 }
1018
1019 printk(KERN_CRIT " Memory port command: %s\n", mem_port_cmd);
1020 printk(KERN_CRIT " Memory port address: %#010lx, mask: %#lx\n",
1021 mem_port_addr, mem_port_mask);
1022 printk(KERN_CRIT " Memory sequencer state: %s\n", seq_state);
1023 printk(KERN_CRIT " Memory set: %s\n", set_select);
1024}
1025
1026static void
1027cia_decode_ecc_error(struct el_CIA_sysdata_mcheck *cia, const char *msg)
1028{
1029 long syn;
1030 long i;
1031 const char *fmt;
1032
1033 cia_decode_mem_error(cia, msg);
1034
1035 syn = cia->cia_syn & 0xff;
1036 if (syn == (syn & -syn)) {
1037 fmt = KERN_CRIT " ECC syndrome %#x -- check bit %d\n";
1038 i = ffs(syn) - 1;
1039 } else {
1040 static unsigned char const data_bit[64] = {
1041 0xCE, 0xCB, 0xD3, 0xD5,
1042 0xD6, 0xD9, 0xDA, 0xDC,
1043 0x23, 0x25, 0x26, 0x29,
1044 0x2A, 0x2C, 0x31, 0x34,
1045 0x0E, 0x0B, 0x13, 0x15,
1046 0x16, 0x19, 0x1A, 0x1C,
1047 0xE3, 0xE5, 0xE6, 0xE9,
1048 0xEA, 0xEC, 0xF1, 0xF4,
1049 0x4F, 0x4A, 0x52, 0x54,
1050 0x57, 0x58, 0x5B, 0x5D,
1051 0xA2, 0xA4, 0xA7, 0xA8,
1052 0xAB, 0xAD, 0xB0, 0xB5,
1053 0x8F, 0x8A, 0x92, 0x94,
1054 0x97, 0x98, 0x9B, 0x9D,
1055 0x62, 0x64, 0x67, 0x68,
1056 0x6B, 0x6D, 0x70, 0x75
1057 };
1058
1059 for (i = 0; i < 64; ++i)
1060 if (data_bit[i] == syn)
1061 break;
1062
1063 if (i < 64)
1064 fmt = KERN_CRIT " ECC syndrome %#x -- data bit %d\n";
1065 else
1066 fmt = KERN_CRIT " ECC syndrome %#x -- unknown bit\n";
1067 }
1068
1069 printk (fmt, syn, i);
1070}
1071
1072static void
1073cia_decode_parity_error(struct el_CIA_sysdata_mcheck *cia)
1074{
1075 static const char * const cmd_desc[16] = {
1076 "NOP", "LOCK", "FETCH", "FETCH_M", "MEMORY BARRIER",
1077 "SET DIRTY", "WRITE BLOCK", "WRITE BLOCK LOCK",
1078 "READ MISS0", "READ MISS1", "READ MISS MOD0",
1079 "READ MISS MOD1", "BCACHE VICTIM", "Spare",
1080 "READ MISS MOD STC0", "READ MISS MOD STC1"
1081 };
1082
1083 unsigned long addr;
1084 unsigned long mask;
1085 const char *cmd;
1086 int par;
1087
1088 addr = cia->cpu_err0 & 0xfffffff0;
1089 addr |= (cia->cpu_err1 & 0x83UL) << 32;
1090 cmd = cmd_desc[(cia->cpu_err1 >> 8) & 0xF];
1091 mask = (cia->cpu_err1 >> 12) & 0xF;
1092 par = (cia->cpu_err1 >> 21) & 1;
1093
1094 printk(KERN_CRIT "CIA machine check: System bus parity error\n");
1095 printk(KERN_CRIT " Command: %s, Parity bit: %d\n", cmd, par);
1096 printk(KERN_CRIT " Address: %#010lx, Mask: %#lx\n", addr, mask);
1097}
1098#endif /* CONFIG_VERBOSE_MCHECK */
1099
1100
1101static int
1102cia_decode_mchk(unsigned long la_ptr)
1103{
1104 struct el_common *com;
1105 struct el_CIA_sysdata_mcheck *cia;
1106
1107 com = (void *)la_ptr;
1108 cia = (void *)(la_ptr + com->sys_offset);
1109
1110 if ((cia->cia_err & CIA_ERR_VALID) == 0)
1111 return 0;
1112
1113#ifdef CONFIG_VERBOSE_MCHECK
1114 if (!alpha_verbose_mcheck)
1115 return 1;
1116
1117 switch (ffs(cia->cia_err & 0xfff) - 1) {
1118 case 0: /* CIA_ERR_COR_ERR */
1119 cia_decode_ecc_error(cia, "Corrected ECC error");
1120 break;
1121 case 1: /* CIA_ERR_UN_COR_ERR */
1122 cia_decode_ecc_error(cia, "Uncorrected ECC error");
1123 break;
1124 case 2: /* CIA_ERR_CPU_PE */
1125 cia_decode_parity_error(cia);
1126 break;
1127 case 3: /* CIA_ERR_MEM_NEM */
1128 cia_decode_mem_error(cia, "Access to nonexistent memory");
1129 break;
1130 case 4: /* CIA_ERR_PCI_SERR */
1131 cia_decode_pci_error(cia, "PCI bus system error");
1132 break;
1133 case 5: /* CIA_ERR_PERR */
1134 cia_decode_pci_error(cia, "PCI data parity error");
1135 break;
1136 case 6: /* CIA_ERR_PCI_ADDR_PE */
1137 cia_decode_pci_error(cia, "PCI address parity error");
1138 break;
1139 case 7: /* CIA_ERR_RCVD_MAS_ABT */
1140 cia_decode_pci_error(cia, "PCI master abort");
1141 break;
1142 case 8: /* CIA_ERR_RCVD_TAR_ABT */
1143 cia_decode_pci_error(cia, "PCI target abort");
1144 break;
1145 case 9: /* CIA_ERR_PA_PTE_INV */
1146 cia_decode_pci_error(cia, "PCI invalid PTE");
1147 break;
1148 case 10: /* CIA_ERR_FROM_WRT_ERR */
1149 cia_decode_mem_error(cia, "Write to flash ROM attempted");
1150 break;
1151 case 11: /* CIA_ERR_IOA_TIMEOUT */
1152 cia_decode_pci_error(cia, "I/O timeout");
1153 break;
1154 }
1155
1156 if (cia->cia_err & CIA_ERR_LOST_CORR_ERR)
1157 printk(KERN_CRIT "CIA lost machine check: "
1158 "Correctable ECC error\n");
1159 if (cia->cia_err & CIA_ERR_LOST_UN_CORR_ERR)
1160 printk(KERN_CRIT "CIA lost machine check: "
1161 "Uncorrectable ECC error\n");
1162 if (cia->cia_err & CIA_ERR_LOST_CPU_PE)
1163 printk(KERN_CRIT "CIA lost machine check: "
1164 "System bus parity error\n");
1165 if (cia->cia_err & CIA_ERR_LOST_MEM_NEM)
1166 printk(KERN_CRIT "CIA lost machine check: "
1167 "Access to nonexistent memory\n");
1168 if (cia->cia_err & CIA_ERR_LOST_PERR)
1169 printk(KERN_CRIT "CIA lost machine check: "
1170 "PCI data parity error\n");
1171 if (cia->cia_err & CIA_ERR_LOST_PCI_ADDR_PE)
1172 printk(KERN_CRIT "CIA lost machine check: "
1173 "PCI address parity error\n");
1174 if (cia->cia_err & CIA_ERR_LOST_RCVD_MAS_ABT)
1175 printk(KERN_CRIT "CIA lost machine check: "
1176 "PCI master abort\n");
1177 if (cia->cia_err & CIA_ERR_LOST_RCVD_TAR_ABT)
1178 printk(KERN_CRIT "CIA lost machine check: "
1179 "PCI target abort\n");
1180 if (cia->cia_err & CIA_ERR_LOST_PA_PTE_INV)
1181 printk(KERN_CRIT "CIA lost machine check: "
1182 "PCI invalid PTE\n");
1183 if (cia->cia_err & CIA_ERR_LOST_FROM_WRT_ERR)
1184 printk(KERN_CRIT "CIA lost machine check: "
1185 "Write to flash ROM attempted\n");
1186 if (cia->cia_err & CIA_ERR_LOST_IOA_TIMEOUT)
1187 printk(KERN_CRIT "CIA lost machine check: "
1188 "I/O timeout\n");
1189#endif /* CONFIG_VERBOSE_MCHECK */
1190
1191 return 1;
1192}
1193
1194void
1195cia_machine_check(unsigned long vector, unsigned long la_ptr,
1196 struct pt_regs * regs)
1197{
1198 int expected;
1199
1200 /* Clear the error before any reporting. */
1201 mb();
1202 mb(); /* magic */
1203 draina();
1204 cia_pci_clr_err();
1205 wrmces(rdmces()); /* reset machine check pending flag. */
1206 mb();
1207
1208 expected = mcheck_expected(0);
1209 if (!expected && vector == 0x660)
1210 expected = cia_decode_mchk(la_ptr);
1211 process_mcheck_info(vector, la_ptr, regs, "CIA", expected);
1212}
diff --git a/arch/alpha/kernel/core_irongate.c b/arch/alpha/kernel/core_irongate.c
new file mode 100644
index 000000000000..138d497d1cca
--- /dev/null
+++ b/arch/alpha/kernel/core_irongate.c
@@ -0,0 +1,416 @@
1/*
2 * linux/arch/alpha/kernel/core_irongate.c
3 *
4 * Based on code written by David A. Rusling (david.rusling@reo.mts.dec.com).
5 *
6 * Copyright (C) 1999 Alpha Processor, Inc.,
7 * (David Daniel, Stig Telfer, Soohoon Lee)
8 *
9 * Code common to all IRONGATE core logic chips.
10 */
11
12#define __EXTERN_INLINE inline
13#include <asm/io.h>
14#include <asm/core_irongate.h>
15#undef __EXTERN_INLINE
16
17#include <linux/types.h>
18#include <linux/pci.h>
19#include <linux/sched.h>
20#include <linux/init.h>
21#include <linux/initrd.h>
22#include <linux/bootmem.h>
23
24#include <asm/ptrace.h>
25#include <asm/pci.h>
26#include <asm/cacheflush.h>
27#include <asm/tlbflush.h>
28
29#include "proto.h"
30#include "pci_impl.h"
31
32/*
33 * BIOS32-style PCI interface:
34 */
35
36#define DEBUG_CONFIG 0
37
38#if DEBUG_CONFIG
39# define DBG_CFG(args) printk args
40#else
41# define DBG_CFG(args)
42#endif
43
44igcsr32 *IronECC;
45
46/*
47 * Given a bus, device, and function number, compute resulting
48 * configuration space address accordingly. It is therefore not safe
49 * to have concurrent invocations to configuration space access
50 * routines, but there really shouldn't be any need for this.
51 *
52 * addr[31:24] reserved
53 * addr[23:16] bus number (8 bits = 128 possible buses)
54 * addr[15:11] Device number (5 bits)
55 * addr[10: 8] function number
56 * addr[ 7: 2] register number
57 *
58 * For IRONGATE:
59 * if (bus = addr[23:16]) == 0
60 * then
61 * type 0 config cycle:
62 * addr_on_pci[31:11] = id selection for device = addr[15:11]
63 * addr_on_pci[10: 2] = addr[10: 2] ???
64 * addr_on_pci[ 1: 0] = 00
65 * else
66 * type 1 config cycle (pass on with no decoding):
67 * addr_on_pci[31:24] = 0
68 * addr_on_pci[23: 2] = addr[23: 2]
69 * addr_on_pci[ 1: 0] = 01
70 * fi
71 *
72 * Notes:
73 * The function number selects which function of a multi-function device
74 * (e.g., SCSI and Ethernet).
75 *
76 * The register selects a DWORD (32 bit) register offset. Hence it
77 * doesn't get shifted by 2 bits as we want to "drop" the bottom two
78 * bits.
79 */
80
81static int
82mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
83 unsigned long *pci_addr, unsigned char *type1)
84{
85 unsigned long addr;
86 u8 bus = pbus->number;
87
88 DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, "
89 "pci_addr=0x%p, type1=0x%p)\n",
90 bus, device_fn, where, pci_addr, type1));
91
92 *type1 = (bus != 0);
93
94 addr = (bus << 16) | (device_fn << 8) | where;
95 addr |= IRONGATE_CONF;
96
97 *pci_addr = addr;
98 DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
99 return 0;
100}
101
102static int
103irongate_read_config(struct pci_bus *bus, unsigned int devfn, int where,
104 int size, u32 *value)
105{
106 unsigned long addr;
107 unsigned char type1;
108
109 if (mk_conf_addr(bus, devfn, where, &addr, &type1))
110 return PCIBIOS_DEVICE_NOT_FOUND;
111
112 switch (size) {
113 case 1:
114 *value = __kernel_ldbu(*(vucp)addr);
115 break;
116 case 2:
117 *value = __kernel_ldwu(*(vusp)addr);
118 break;
119 case 4:
120 *value = *(vuip)addr;
121 break;
122 }
123
124 return PCIBIOS_SUCCESSFUL;
125}
126
127static int
128irongate_write_config(struct pci_bus *bus, unsigned int devfn, int where,
129 int size, u32 value)
130{
131 unsigned long addr;
132 unsigned char type1;
133
134 if (mk_conf_addr(bus, devfn, where, &addr, &type1))
135 return PCIBIOS_DEVICE_NOT_FOUND;
136
137 switch (size) {
138 case 1:
139 __kernel_stb(value, *(vucp)addr);
140 mb();
141 __kernel_ldbu(*(vucp)addr);
142 break;
143 case 2:
144 __kernel_stw(value, *(vusp)addr);
145 mb();
146 __kernel_ldwu(*(vusp)addr);
147 break;
148 case 4:
149 *(vuip)addr = value;
150 mb();
151 *(vuip)addr;
152 break;
153 }
154
155 return PCIBIOS_SUCCESSFUL;
156}
157
158struct pci_ops irongate_pci_ops =
159{
160 .read = irongate_read_config,
161 .write = irongate_write_config,
162};
163
164int
165irongate_pci_clr_err(void)
166{
167 unsigned int nmi_ctl=0;
168 unsigned int IRONGATE_jd;
169
170again:
171 IRONGATE_jd = IRONGATE0->stat_cmd;
172 printk("Iron stat_cmd %x\n", IRONGATE_jd);
173 IRONGATE0->stat_cmd = IRONGATE_jd; /* write again clears error bits */
174 mb();
175 IRONGATE_jd = IRONGATE0->stat_cmd; /* re-read to force write */
176
177 IRONGATE_jd = *IronECC;
178 printk("Iron ECC %x\n", IRONGATE_jd);
179 *IronECC = IRONGATE_jd; /* write again clears error bits */
180 mb();
181 IRONGATE_jd = *IronECC; /* re-read to force write */
182
183 /* Clear ALI NMI */
184 nmi_ctl = inb(0x61);
185 nmi_ctl |= 0x0c;
186 outb(nmi_ctl, 0x61);
187 nmi_ctl &= ~0x0c;
188 outb(nmi_ctl, 0x61);
189
190 IRONGATE_jd = *IronECC;
191 if (IRONGATE_jd & 0x300) goto again;
192
193 return 0;
194}
195
196#define IRONGATE_3GB 0xc0000000UL
197
198/* On Albacore (aka UP1500) with 4Gb of RAM we have to reserve some
199 memory for PCI. At this point we just reserve memory above 3Gb. Most
200 of this memory will be freed after PCI setup is done. */
201static void __init
202albacore_init_arch(void)
203{
204 unsigned long memtop = max_low_pfn << PAGE_SHIFT;
205 unsigned long pci_mem = (memtop + 0x1000000UL) & ~0xffffffUL;
206 struct percpu_struct *cpu;
207 int pal_rev, pal_var;
208
209 cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset);
210 pal_rev = cpu->pal_revision & 0xffff;
211 pal_var = (cpu->pal_revision >> 16) & 0xff;
212
213 /* Consoles earlier than A5.6-18 (OSF PALcode v1.62-2) set up
214 the CPU incorrectly (leave speculative stores enabled),
215 which causes memory corruption under certain conditions.
216 Issue a warning for such consoles. */
217 if (alpha_using_srm &&
218 (pal_rev < 0x13e || (pal_rev == 0x13e && pal_var < 2)))
219 printk(KERN_WARNING "WARNING! Upgrade to SRM A5.6-19 "
220 "or later\n");
221
222 if (pci_mem > IRONGATE_3GB)
223 pci_mem = IRONGATE_3GB;
224 IRONGATE0->pci_mem = pci_mem;
225 alpha_mv.min_mem_address = pci_mem;
226 if (memtop > pci_mem) {
227#ifdef CONFIG_BLK_DEV_INITRD
228 extern unsigned long initrd_start, initrd_end;
229 extern void *move_initrd(unsigned long);
230
231 /* Move the initrd out of the way. */
232 if (initrd_end && __pa(initrd_end) > pci_mem) {
233 unsigned long size;
234
235 size = initrd_end - initrd_start;
236 free_bootmem_node(NODE_DATA(0), __pa(initrd_start),
237 PAGE_ALIGN(size));
238 if (!move_initrd(pci_mem))
239 printk("irongate_init_arch: initrd too big "
240 "(%ldK)\ndisabling initrd\n",
241 size / 1024);
242 }
243#endif
244 reserve_bootmem_node(NODE_DATA(0), pci_mem, memtop - pci_mem);
245 printk("irongate_init_arch: temporarily reserving "
246 "region %08lx-%08lx for PCI\n", pci_mem, memtop - 1);
247 }
248}
249
250static void __init
251irongate_setup_agp(void)
252{
253 /* Disable the GART window. AGPGART doesn't work due to yet
254 unresolved memory coherency issues... */
255 IRONGATE0->agpva = IRONGATE0->agpva & ~0xf;
256 alpha_agpgart_size = 0;
257}
258
259void __init
260irongate_init_arch(void)
261{
262 struct pci_controller *hose;
263 int amd761 = (IRONGATE0->dev_vendor >> 16) > 0x7006; /* Albacore? */
264
265 IronECC = amd761 ? &IRONGATE0->bacsr54_eccms761 : &IRONGATE0->dramms;
266
267 irongate_pci_clr_err();
268
269 if (amd761)
270 albacore_init_arch();
271
272 irongate_setup_agp();
273
274 /*
275 * Create our single hose.
276 */
277
278 pci_isa_hose = hose = alloc_pci_controller();
279 hose->io_space = &ioport_resource;
280 hose->mem_space = &iomem_resource;
281 hose->index = 0;
282
283 /* This is for userland consumption. For some reason, the 40-bit
284 PIO bias that we use in the kernel through KSEG didn't work for
285 the page table based user mappings. So make sure we get the
286 43-bit PIO bias. */
287 hose->sparse_mem_base = 0;
288 hose->sparse_io_base = 0;
289 hose->dense_mem_base
290 = (IRONGATE_MEM & 0xffffffffffUL) | 0x80000000000UL;
291 hose->dense_io_base
292 = (IRONGATE_IO & 0xffffffffffUL) | 0x80000000000UL;
293
294 hose->sg_isa = hose->sg_pci = NULL;
295 __direct_map_base = 0;
296 __direct_map_size = 0xffffffff;
297}
298
299/*
300 * IO map and AGP support
301 */
302#include <linux/vmalloc.h>
303#include <linux/agp_backend.h>
304#include <linux/agpgart.h>
305#include <asm/pgalloc.h>
306
307#define GET_PAGE_DIR_OFF(addr) (addr >> 22)
308#define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr))
309
310#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12)
311#define GET_GATT(addr) (gatt_pages[GET_PAGE_DIR_IDX(addr)])
312
313void __iomem *
314irongate_ioremap(unsigned long addr, unsigned long size)
315{
316 struct vm_struct *area;
317 unsigned long vaddr;
318 unsigned long baddr, last;
319 u32 *mmio_regs, *gatt_pages, *cur_gatt, pte;
320 unsigned long gart_bus_addr;
321
322 if (!alpha_agpgart_size)
323 return (void __iomem *)(addr + IRONGATE_MEM);
324
325 gart_bus_addr = (unsigned long)IRONGATE0->bar0 &
326 PCI_BASE_ADDRESS_MEM_MASK;
327
328 /*
329 * Check for within the AGP aperture...
330 */
331 do {
332 /*
333 * Check the AGP area
334 */
335 if (addr >= gart_bus_addr && addr + size - 1 <
336 gart_bus_addr + alpha_agpgart_size)
337 break;
338
339 /*
340 * Not found - assume legacy ioremap
341 */
342 return (void __iomem *)(addr + IRONGATE_MEM);
343 } while(0);
344
345 mmio_regs = (u32 *)(((unsigned long)IRONGATE0->bar1 &
346 PCI_BASE_ADDRESS_MEM_MASK) + IRONGATE_MEM);
347
348 gatt_pages = (u32 *)(phys_to_virt(mmio_regs[1])); /* FIXME */
349
350 /*
351 * Adjust the limits (mappings must be page aligned)
352 */
353 if (addr & ~PAGE_MASK) {
354 printk("AGP ioremap failed... addr not page aligned (0x%lx)\n",
355 addr);
356 return (void __iomem *)(addr + IRONGATE_MEM);
357 }
358 last = addr + size - 1;
359 size = PAGE_ALIGN(last) - addr;
360
361#if 0
362 printk("irongate_ioremap(0x%lx, 0x%lx)\n", addr, size);
363 printk("irongate_ioremap: gart_bus_addr 0x%lx\n", gart_bus_addr);
364 printk("irongate_ioremap: gart_aper_size 0x%lx\n", gart_aper_size);
365 printk("irongate_ioremap: mmio_regs %p\n", mmio_regs);
366 printk("irongate_ioremap: gatt_pages %p\n", gatt_pages);
367
368 for(baddr = addr; baddr <= last; baddr += PAGE_SIZE)
369 {
370 cur_gatt = phys_to_virt(GET_GATT(baddr) & ~1);
371 pte = cur_gatt[GET_GATT_OFF(baddr)] & ~1;
372 printk("irongate_ioremap: cur_gatt %p pte 0x%x\n",
373 cur_gatt, pte);
374 }
375#endif
376
377 /*
378 * Map it
379 */
380 area = get_vm_area(size, VM_IOREMAP);
381 if (!area) return NULL;
382
383 for(baddr = addr, vaddr = (unsigned long)area->addr;
384 baddr <= last;
385 baddr += PAGE_SIZE, vaddr += PAGE_SIZE)
386 {
387 cur_gatt = phys_to_virt(GET_GATT(baddr) & ~1);
388 pte = cur_gatt[GET_GATT_OFF(baddr)] & ~1;
389
390 if (__alpha_remap_area_pages(vaddr,
391 pte, PAGE_SIZE, 0)) {
392 printk("AGP ioremap: FAILED to map...\n");
393 vfree(area->addr);
394 return NULL;
395 }
396 }
397
398 flush_tlb_all();
399
400 vaddr = (unsigned long)area->addr + (addr & ~PAGE_MASK);
401#if 0
402 printk("irongate_ioremap(0x%lx, 0x%lx) returning 0x%lx\n",
403 addr, size, vaddr);
404#endif
405 return (void __iomem *)vaddr;
406}
407
408void
409irongate_iounmap(volatile void __iomem *xaddr)
410{
411 unsigned long addr = (unsigned long) xaddr;
412 if (((long)addr >> 41) == -2)
413 return; /* kseg map, nothing to do */
414 if (addr)
415 return vfree((void *)(PAGE_MASK & addr));
416}
diff --git a/arch/alpha/kernel/core_lca.c b/arch/alpha/kernel/core_lca.c
new file mode 100644
index 000000000000..6a5a9145c676
--- /dev/null
+++ b/arch/alpha/kernel/core_lca.c
@@ -0,0 +1,515 @@
1/*
2 * linux/arch/alpha/kernel/core_lca.c
3 *
4 * Written by David Mosberger (davidm@cs.arizona.edu) with some code
5 * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit
6 * bios code.
7 *
8 * Code common to all LCA core logic chips.
9 */
10
11#define __EXTERN_INLINE inline
12#include <asm/io.h>
13#include <asm/core_lca.h>
14#undef __EXTERN_INLINE
15
16#include <linux/types.h>
17#include <linux/pci.h>
18#include <linux/init.h>
19#include <linux/tty.h>
20
21#include <asm/ptrace.h>
22#include <asm/smp.h>
23
24#include "proto.h"
25#include "pci_impl.h"
26
27
28/*
29 * BIOS32-style PCI interface:
30 */
31
32/*
33 * Machine check reasons. Defined according to PALcode sources
34 * (osf.h and platform.h).
35 */
36#define MCHK_K_TPERR 0x0080
37#define MCHK_K_TCPERR 0x0082
38#define MCHK_K_HERR 0x0084
39#define MCHK_K_ECC_C 0x0086
40#define MCHK_K_ECC_NC 0x0088
41#define MCHK_K_UNKNOWN 0x008A
42#define MCHK_K_CACKSOFT 0x008C
43#define MCHK_K_BUGCHECK 0x008E
44#define MCHK_K_OS_BUGCHECK 0x0090
45#define MCHK_K_DCPERR 0x0092
46#define MCHK_K_ICPERR 0x0094
47
48
49/*
50 * Platform-specific machine-check reasons:
51 */
52#define MCHK_K_SIO_SERR 0x204 /* all platforms so far */
53#define MCHK_K_SIO_IOCHK 0x206 /* all platforms so far */
54#define MCHK_K_DCSR 0x208 /* all but Noname */
55
56
57/*
58 * Given a bus, device, and function number, compute resulting
59 * configuration space address and setup the LCA_IOC_CONF register
60 * accordingly. It is therefore not safe to have concurrent
61 * invocations to configuration space access routines, but there
62 * really shouldn't be any need for this.
63 *
64 * Type 0:
65 *
66 * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
67 * 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
68 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69 * | | | | | | | | | | | | | | | | | | | | | | | |F|F|F|R|R|R|R|R|R|0|0|
70 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
71 *
72 * 31:11 Device select bit.
73 * 10:8 Function number
74 * 7:2 Register number
75 *
76 * Type 1:
77 *
78 * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
79 * 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
80 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
81 * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
82 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
83 *
84 * 31:24 reserved
85 * 23:16 bus number (8 bits = 128 possible buses)
86 * 15:11 Device number (5 bits)
87 * 10:8 function number
88 * 7:2 register number
89 *
90 * Notes:
91 * The function number selects which function of a multi-function device
92 * (e.g., SCSI and Ethernet).
93 *
94 * The register selects a DWORD (32 bit) register offset. Hence it
95 * doesn't get shifted by 2 bits as we want to "drop" the bottom two
96 * bits.
97 */
98
99static int
100mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
101 unsigned long *pci_addr)
102{
103 unsigned long addr;
104 u8 bus = pbus->number;
105
106 if (bus == 0) {
107 int device = device_fn >> 3;
108 int func = device_fn & 0x7;
109
110 /* Type 0 configuration cycle. */
111
112 if (device > 12) {
113 return -1;
114 }
115
116 *(vulp)LCA_IOC_CONF = 0;
117 addr = (1 << (11 + device)) | (func << 8) | where;
118 } else {
119 /* Type 1 configuration cycle. */
120 *(vulp)LCA_IOC_CONF = 1;
121 addr = (bus << 16) | (device_fn << 8) | where;
122 }
123 *pci_addr = addr;
124 return 0;
125}
126
127static unsigned int
128conf_read(unsigned long addr)
129{
130 unsigned long flags, code, stat0;
131 unsigned int value;
132
133 local_irq_save(flags);
134
135 /* Reset status register to avoid loosing errors. */
136 stat0 = *(vulp)LCA_IOC_STAT0;
137 *(vulp)LCA_IOC_STAT0 = stat0;
138 mb();
139
140 /* Access configuration space. */
141 value = *(vuip)addr;
142 draina();
143
144 stat0 = *(vulp)LCA_IOC_STAT0;
145 if (stat0 & LCA_IOC_STAT0_ERR) {
146 code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT)
147 & LCA_IOC_STAT0_CODE_MASK);
148 if (code != 1) {
149 printk("lca.c:conf_read: got stat0=%lx\n", stat0);
150 }
151
152 /* Reset error status. */
153 *(vulp)LCA_IOC_STAT0 = stat0;
154 mb();
155
156 /* Reset machine check. */
157 wrmces(0x7);
158
159 value = 0xffffffff;
160 }
161 local_irq_restore(flags);
162 return value;
163}
164
165static void
166conf_write(unsigned long addr, unsigned int value)
167{
168 unsigned long flags, code, stat0;
169
170 local_irq_save(flags); /* avoid getting hit by machine check */
171
172 /* Reset status register to avoid loosing errors. */
173 stat0 = *(vulp)LCA_IOC_STAT0;
174 *(vulp)LCA_IOC_STAT0 = stat0;
175 mb();
176
177 /* Access configuration space. */
178 *(vuip)addr = value;
179 draina();
180
181 stat0 = *(vulp)LCA_IOC_STAT0;
182 if (stat0 & LCA_IOC_STAT0_ERR) {
183 code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT)
184 & LCA_IOC_STAT0_CODE_MASK);
185 if (code != 1) {
186 printk("lca.c:conf_write: got stat0=%lx\n", stat0);
187 }
188
189 /* Reset error status. */
190 *(vulp)LCA_IOC_STAT0 = stat0;
191 mb();
192
193 /* Reset machine check. */
194 wrmces(0x7);
195 }
196 local_irq_restore(flags);
197}
198
199static int
200lca_read_config(struct pci_bus *bus, unsigned int devfn, int where,
201 int size, u32 *value)
202{
203 unsigned long addr, pci_addr;
204 long mask;
205 int shift;
206
207 if (mk_conf_addr(bus, devfn, where, &pci_addr))
208 return PCIBIOS_DEVICE_NOT_FOUND;
209
210 shift = (where & 3) * 8;
211 mask = (size - 1) * 8;
212 addr = (pci_addr << 5) + mask + LCA_CONF;
213 *value = conf_read(addr) >> (shift);
214 return PCIBIOS_SUCCESSFUL;
215}
216
217static int
218lca_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size,
219 u32 value)
220{
221 unsigned long addr, pci_addr;
222 long mask;
223
224 if (mk_conf_addr(bus, devfn, where, &pci_addr))
225 return PCIBIOS_DEVICE_NOT_FOUND;
226
227 mask = (size - 1) * 8;
228 addr = (pci_addr << 5) + mask + LCA_CONF;
229 conf_write(addr, value << ((where & 3) * 8));
230 return PCIBIOS_SUCCESSFUL;
231}
232
233struct pci_ops lca_pci_ops =
234{
235 .read = lca_read_config,
236 .write = lca_write_config,
237};
238
239void
240lca_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
241{
242 wmb();
243 *(vulp)LCA_IOC_TBIA = 0;
244 mb();
245}
246
247void __init
248lca_init_arch(void)
249{
250 struct pci_controller *hose;
251
252 /*
253 * Create our single hose.
254 */
255
256 pci_isa_hose = hose = alloc_pci_controller();
257 hose->io_space = &ioport_resource;
258 hose->mem_space = &iomem_resource;
259 hose->index = 0;
260
261 hose->sparse_mem_base = LCA_SPARSE_MEM - IDENT_ADDR;
262 hose->dense_mem_base = LCA_DENSE_MEM - IDENT_ADDR;
263 hose->sparse_io_base = LCA_IO - IDENT_ADDR;
264 hose->dense_io_base = 0;
265
266 /*
267 * Set up the PCI to main memory translation windows.
268 *
269 * Mimic the SRM settings for the direct-map window.
270 * Window 0 is scatter-gather 8MB at 8MB (for isa).
271 * Window 1 is direct access 1GB at 1GB.
272 *
273 * Note that we do not try to save any of the DMA window CSRs
274 * before setting them, since we cannot read those CSRs on LCA.
275 */
276 hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
277 hose->sg_pci = NULL;
278 __direct_map_base = 0x40000000;
279 __direct_map_size = 0x40000000;
280
281 *(vulp)LCA_IOC_W_BASE0 = hose->sg_isa->dma_base | (3UL << 32);
282 *(vulp)LCA_IOC_W_MASK0 = (hose->sg_isa->size - 1) & 0xfff00000;
283 *(vulp)LCA_IOC_T_BASE0 = virt_to_phys(hose->sg_isa->ptes);
284
285 *(vulp)LCA_IOC_W_BASE1 = __direct_map_base | (2UL << 32);
286 *(vulp)LCA_IOC_W_MASK1 = (__direct_map_size - 1) & 0xfff00000;
287 *(vulp)LCA_IOC_T_BASE1 = 0;
288
289 *(vulp)LCA_IOC_TB_ENA = 0x80;
290
291 lca_pci_tbi(hose, 0, -1);
292
293 /*
294 * Disable PCI parity for now. The NCR53c810 chip has
295 * troubles meeting the PCI spec which results in
296 * data parity errors.
297 */
298 *(vulp)LCA_IOC_PAR_DIS = 1UL<<5;
299
300 /*
301 * Finally, set up for restoring the correct HAE if using SRM.
302 * Again, since we cannot read many of the CSRs on the LCA,
303 * one of which happens to be the HAE, we save the value that
304 * the SRM will expect...
305 */
306 if (alpha_using_srm)
307 srm_hae = 0x80000000UL;
308}
309
310/*
311 * Constants used during machine-check handling. I suppose these
312 * could be moved into lca.h but I don't see much reason why anybody
313 * else would want to use them.
314 */
315
316#define ESR_EAV (1UL<< 0) /* error address valid */
317#define ESR_CEE (1UL<< 1) /* correctable error */
318#define ESR_UEE (1UL<< 2) /* uncorrectable error */
319#define ESR_WRE (1UL<< 3) /* write-error */
320#define ESR_SOR (1UL<< 4) /* error source */
321#define ESR_CTE (1UL<< 7) /* cache-tag error */
322#define ESR_MSE (1UL<< 9) /* multiple soft errors */
323#define ESR_MHE (1UL<<10) /* multiple hard errors */
324#define ESR_NXM (1UL<<12) /* non-existent memory */
325
326#define IOC_ERR ( 1<<4) /* ioc logs an error */
327#define IOC_CMD_SHIFT 0
328#define IOC_CMD (0xf<<IOC_CMD_SHIFT)
329#define IOC_CODE_SHIFT 8
330#define IOC_CODE (0xf<<IOC_CODE_SHIFT)
331#define IOC_LOST ( 1<<5)
332#define IOC_P_NBR ((__u32) ~((1<<13) - 1))
333
334static void
335mem_error(unsigned long esr, unsigned long ear)
336{
337 printk(" %s %s error to %s occurred at address %x\n",
338 ((esr & ESR_CEE) ? "Correctable" :
339 (esr & ESR_UEE) ? "Uncorrectable" : "A"),
340 (esr & ESR_WRE) ? "write" : "read",
341 (esr & ESR_SOR) ? "memory" : "b-cache",
342 (unsigned) (ear & 0x1ffffff8));
343 if (esr & ESR_CTE) {
344 printk(" A b-cache tag parity error was detected.\n");
345 }
346 if (esr & ESR_MSE) {
347 printk(" Several other correctable errors occurred.\n");
348 }
349 if (esr & ESR_MHE) {
350 printk(" Several other uncorrectable errors occurred.\n");
351 }
352 if (esr & ESR_NXM) {
353 printk(" Attempted to access non-existent memory.\n");
354 }
355}
356
357static void
358ioc_error(__u32 stat0, __u32 stat1)
359{
360 static const char * const pci_cmd[] = {
361 "Interrupt Acknowledge", "Special", "I/O Read", "I/O Write",
362 "Rsvd 1", "Rsvd 2", "Memory Read", "Memory Write", "Rsvd3",
363 "Rsvd4", "Configuration Read", "Configuration Write",
364 "Memory Read Multiple", "Dual Address", "Memory Read Line",
365 "Memory Write and Invalidate"
366 };
367 static const char * const err_name[] = {
368 "exceeded retry limit", "no device", "bad data parity",
369 "target abort", "bad address parity", "page table read error",
370 "invalid page", "data error"
371 };
372 unsigned code = (stat0 & IOC_CODE) >> IOC_CODE_SHIFT;
373 unsigned cmd = (stat0 & IOC_CMD) >> IOC_CMD_SHIFT;
374
375 printk(" %s initiated PCI %s cycle to address %x"
376 " failed due to %s.\n",
377 code > 3 ? "PCI" : "CPU", pci_cmd[cmd], stat1, err_name[code]);
378
379 if (code == 5 || code == 6) {
380 printk(" (Error occurred at PCI memory address %x.)\n",
381 (stat0 & ~IOC_P_NBR));
382 }
383 if (stat0 & IOC_LOST) {
384 printk(" Other PCI errors occurred simultaneously.\n");
385 }
386}
387
388void
389lca_machine_check(unsigned long vector, unsigned long la_ptr,
390 struct pt_regs *regs)
391{
392 const char * reason;
393 union el_lca el;
394
395 el.c = (struct el_common *) la_ptr;
396
397 wrmces(rdmces()); /* reset machine check pending flag */
398
399 printk(KERN_CRIT "LCA machine check: vector=%#lx pc=%#lx code=%#x\n",
400 vector, regs->pc, (unsigned int) el.c->code);
401
402 /*
403 * The first quadword after the common header always seems to
404 * be the machine check reason---don't know why this isn't
405 * part of the common header instead. In the case of a long
406 * logout frame, the upper 32 bits is the machine check
407 * revision level, which we ignore for now.
408 */
409 switch ((unsigned int) el.c->code) {
410 case MCHK_K_TPERR: reason = "tag parity error"; break;
411 case MCHK_K_TCPERR: reason = "tag control parity error"; break;
412 case MCHK_K_HERR: reason = "access to non-existent memory"; break;
413 case MCHK_K_ECC_C: reason = "correctable ECC error"; break;
414 case MCHK_K_ECC_NC: reason = "non-correctable ECC error"; break;
415 case MCHK_K_CACKSOFT: reason = "MCHK_K_CACKSOFT"; break;
416 case MCHK_K_BUGCHECK: reason = "illegal exception in PAL mode"; break;
417 case MCHK_K_OS_BUGCHECK: reason = "callsys in kernel mode"; break;
418 case MCHK_K_DCPERR: reason = "d-cache parity error"; break;
419 case MCHK_K_ICPERR: reason = "i-cache parity error"; break;
420 case MCHK_K_SIO_SERR: reason = "SIO SERR occurred on PCI bus"; break;
421 case MCHK_K_SIO_IOCHK: reason = "SIO IOCHK occurred on ISA bus"; break;
422 case MCHK_K_DCSR: reason = "MCHK_K_DCSR"; break;
423 case MCHK_K_UNKNOWN:
424 default: reason = "unknown"; break;
425 }
426
427 switch (el.c->size) {
428 case sizeof(struct el_lca_mcheck_short):
429 printk(KERN_CRIT
430 " Reason: %s (short frame%s, dc_stat=%#lx):\n",
431 reason, el.c->retry ? ", retryable" : "",
432 el.s->dc_stat);
433 if (el.s->esr & ESR_EAV) {
434 mem_error(el.s->esr, el.s->ear);
435 }
436 if (el.s->ioc_stat0 & IOC_ERR) {
437 ioc_error(el.s->ioc_stat0, el.s->ioc_stat1);
438 }
439 break;
440
441 case sizeof(struct el_lca_mcheck_long):
442 printk(KERN_CRIT " Reason: %s (long frame%s):\n",
443 reason, el.c->retry ? ", retryable" : "");
444 printk(KERN_CRIT
445 " reason: %#lx exc_addr: %#lx dc_stat: %#lx\n",
446 el.l->pt[0], el.l->exc_addr, el.l->dc_stat);
447 printk(KERN_CRIT " car: %#lx\n", el.l->car);
448 if (el.l->esr & ESR_EAV) {
449 mem_error(el.l->esr, el.l->ear);
450 }
451 if (el.l->ioc_stat0 & IOC_ERR) {
452 ioc_error(el.l->ioc_stat0, el.l->ioc_stat1);
453 }
454 break;
455
456 default:
457 printk(KERN_CRIT " Unknown errorlog size %d\n", el.c->size);
458 }
459
460 /* Dump the logout area to give all info. */
461#ifdef CONFIG_VERBOSE_MCHECK
462 if (alpha_verbose_mcheck > 1) {
463 unsigned long * ptr = (unsigned long *) la_ptr;
464 long i;
465 for (i = 0; i < el.c->size / sizeof(long); i += 2) {
466 printk(KERN_CRIT " +%8lx %016lx %016lx\n",
467 i*sizeof(long), ptr[i], ptr[i+1]);
468 }
469 }
470#endif /* CONFIG_VERBOSE_MCHECK */
471}
472
473/*
474 * The following routines are needed to support the SPEED changing
475 * necessary to successfully manage the thermal problem on the AlphaBook1.
476 */
477
478void
479lca_clock_print(void)
480{
481 long pmr_reg;
482
483 pmr_reg = LCA_READ_PMR;
484
485 printk("Status of clock control:\n");
486 printk("\tPrimary clock divisor\t0x%lx\n", LCA_GET_PRIMARY(pmr_reg));
487 printk("\tOverride clock divisor\t0x%lx\n", LCA_GET_OVERRIDE(pmr_reg));
488 printk("\tInterrupt override is %s\n",
489 (pmr_reg & LCA_PMR_INTO) ? "on" : "off");
490 printk("\tDMA override is %s\n",
491 (pmr_reg & LCA_PMR_DMAO) ? "on" : "off");
492
493}
494
495int
496lca_get_clock(void)
497{
498 long pmr_reg;
499
500 pmr_reg = LCA_READ_PMR;
501 return(LCA_GET_PRIMARY(pmr_reg));
502
503}
504
505void
506lca_clock_fiddle(int divisor)
507{
508 long pmr_reg;
509
510 pmr_reg = LCA_READ_PMR;
511 LCA_SET_PRIMARY_CLOCK(pmr_reg, divisor);
512 /* lca_norm_clock = divisor; */
513 LCA_WRITE_PMR(pmr_reg);
514 mb();
515}
diff --git a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c
new file mode 100644
index 000000000000..44866cb26a80
--- /dev/null
+++ b/arch/alpha/kernel/core_marvel.c
@@ -0,0 +1,1154 @@
1/*
2 * linux/arch/alpha/kernel/core_marvel.c
3 *
4 * Code common to all Marvel based systems.
5 */
6
7#define __EXTERN_INLINE inline
8#include <asm/io.h>
9#include <asm/core_marvel.h>
10#undef __EXTERN_INLINE
11
12#include <linux/types.h>
13#include <linux/pci.h>
14#include <linux/sched.h>
15#include <linux/init.h>
16#include <linux/vmalloc.h>
17#include <linux/mc146818rtc.h>
18#include <linux/rtc.h>
19#include <linux/module.h>
20#include <linux/bootmem.h>
21
22#include <asm/ptrace.h>
23#include <asm/smp.h>
24#include <asm/gct.h>
25#include <asm/pgalloc.h>
26#include <asm/tlbflush.h>
27#include <asm/rtc.h>
28
29#include "proto.h"
30#include "pci_impl.h"
31
32
33/*
34 * Debug helpers
35 */
36#define DEBUG_CONFIG 0
37
38#if DEBUG_CONFIG
39# define DBG_CFG(args) printk args
40#else
41# define DBG_CFG(args)
42#endif
43
44
45/*
46 * Private data
47 */
48static struct io7 *io7_head = NULL;
49
50
51/*
52 * Helper functions
53 */
54static unsigned long __attribute__ ((unused))
55read_ev7_csr(int pe, unsigned long offset)
56{
57 ev7_csr *ev7csr = EV7_CSR_KERN(pe, offset);
58 unsigned long q;
59
60 mb();
61 q = ev7csr->csr;
62 mb();
63
64 return q;
65}
66
67static void __attribute__ ((unused))
68write_ev7_csr(int pe, unsigned long offset, unsigned long q)
69{
70 ev7_csr *ev7csr = EV7_CSR_KERN(pe, offset);
71
72 mb();
73 ev7csr->csr = q;
74 mb();
75}
76
77static char * __init
78mk_resource_name(int pe, int port, char *str)
79{
80 char tmp[80];
81 char *name;
82
83 sprintf(tmp, "PCI %s PE %d PORT %d", str, pe, port);
84 name = alloc_bootmem(strlen(tmp) + 1);
85 strcpy(name, tmp);
86
87 return name;
88}
89
90inline struct io7 *
91marvel_next_io7(struct io7 *prev)
92{
93 return (prev ? prev->next : io7_head);
94}
95
96struct io7 *
97marvel_find_io7(int pe)
98{
99 struct io7 *io7;
100
101 for (io7 = io7_head; io7 && io7->pe != pe; io7 = io7->next)
102 continue;
103
104 return io7;
105}
106
107static struct io7 * __init
108alloc_io7(unsigned int pe)
109{
110 struct io7 *io7;
111 struct io7 *insp;
112 int h;
113
114 if (marvel_find_io7(pe)) {
115 printk(KERN_WARNING "IO7 at PE %d already allocated!\n", pe);
116 return NULL;
117 }
118
119 io7 = alloc_bootmem(sizeof(*io7));
120 io7->pe = pe;
121 spin_lock_init(&io7->irq_lock);
122
123 for (h = 0; h < 4; h++) {
124 io7->ports[h].io7 = io7;
125 io7->ports[h].port = h;
126 io7->ports[h].enabled = 0; /* default to disabled */
127 }
128
129 /*
130 * Insert in pe sorted order.
131 */
132 if (NULL == io7_head) /* empty list */
133 io7_head = io7;
134 else if (io7_head->pe > io7->pe) { /* insert at head */
135 io7->next = io7_head;
136 io7_head = io7;
137 } else { /* insert at position */
138 for (insp = io7_head; insp; insp = insp->next) {
139 if (insp->pe == io7->pe) {
140 printk(KERN_ERR "Too many IO7s at PE %d\n",
141 io7->pe);
142 return NULL;
143 }
144
145 if (NULL == insp->next ||
146 insp->next->pe > io7->pe) { /* insert here */
147 io7->next = insp->next;
148 insp->next = io7;
149 break;
150 }
151 }
152
153 if (NULL == insp) { /* couldn't insert ?!? */
154 printk(KERN_WARNING "Failed to insert IO7 at PE %d "
155 " - adding at head of list\n", io7->pe);
156 io7->next = io7_head;
157 io7_head = io7;
158 }
159 }
160
161 return io7;
162}
163
164void
165io7_clear_errors(struct io7 *io7)
166{
167 io7_port7_csrs *p7csrs;
168 io7_ioport_csrs *csrs;
169 int port;
170
171
172 /*
173 * First the IO ports.
174 */
175 for (port = 0; port < 4; port++) {
176 csrs = IO7_CSRS_KERN(io7->pe, port);
177
178 csrs->POx_ERR_SUM.csr = -1UL;
179 csrs->POx_TLB_ERR.csr = -1UL;
180 csrs->POx_SPL_COMPLT.csr = -1UL;
181 csrs->POx_TRANS_SUM.csr = -1UL;
182 }
183
184 /*
185 * Then the common ones.
186 */
187 p7csrs = IO7_PORT7_CSRS_KERN(io7->pe);
188
189 p7csrs->PO7_ERROR_SUM.csr = -1UL;
190 p7csrs->PO7_UNCRR_SYM.csr = -1UL;
191 p7csrs->PO7_CRRCT_SYM.csr = -1UL;
192}
193
194
195/*
196 * IO7 PCI, PCI/X, AGP configuration.
197 */
198static void __init
199io7_init_hose(struct io7 *io7, int port)
200{
201 static int hose_index = 0;
202
203 struct pci_controller *hose = alloc_pci_controller();
204 struct io7_port *io7_port = &io7->ports[port];
205 io7_ioport_csrs *csrs = IO7_CSRS_KERN(io7->pe, port);
206 int i;
207
208 hose->index = hose_index++; /* arbitrary */
209
210 /*
211 * We don't have an isa or legacy hose, but glibc expects to be
212 * able to use the bus == 0 / dev == 0 form of the iobase syscall
213 * to determine information about the i/o system. Since XFree86
214 * relies on glibc's determination to tell whether or not to use
215 * sparse access, we need to point the pci_isa_hose at a real hose
216 * so at least that determination is correct.
217 */
218 if (hose->index == 0)
219 pci_isa_hose = hose;
220
221 io7_port->csrs = csrs;
222 io7_port->hose = hose;
223 hose->sysdata = io7_port;
224
225 hose->io_space = alloc_resource();
226 hose->mem_space = alloc_resource();
227
228 /*
229 * Base addresses for userland consumption. Since these are going
230 * to be mapped, they are pure physical addresses.
231 */
232 hose->sparse_mem_base = hose->sparse_io_base = 0;
233 hose->dense_mem_base = IO7_MEM_PHYS(io7->pe, port);
234 hose->dense_io_base = IO7_IO_PHYS(io7->pe, port);
235
236 /*
237 * Base addresses and resource ranges for kernel consumption.
238 */
239 hose->config_space_base = (unsigned long)IO7_CONF_KERN(io7->pe, port);
240
241 hose->io_space->start = (unsigned long)IO7_IO_KERN(io7->pe, port);
242 hose->io_space->end = hose->io_space->start + IO7_IO_SPACE - 1;
243 hose->io_space->name = mk_resource_name(io7->pe, port, "IO");
244 hose->io_space->flags = IORESOURCE_IO;
245
246 hose->mem_space->start = (unsigned long)IO7_MEM_KERN(io7->pe, port);
247 hose->mem_space->end = hose->mem_space->start + IO7_MEM_SPACE - 1;
248 hose->mem_space->name = mk_resource_name(io7->pe, port, "MEM");
249 hose->mem_space->flags = IORESOURCE_MEM;
250
251 if (request_resource(&ioport_resource, hose->io_space) < 0)
252 printk(KERN_ERR "Failed to request IO on hose %d\n",
253 hose->index);
254 if (request_resource(&iomem_resource, hose->mem_space) < 0)
255 printk(KERN_ERR "Failed to request MEM on hose %d\n",
256 hose->index);
257
258 /*
259 * Save the existing DMA window settings for later restoration.
260 */
261 for (i = 0; i < 4; i++) {
262 io7_port->saved_wbase[i] = csrs->POx_WBASE[i].csr;
263 io7_port->saved_wmask[i] = csrs->POx_WMASK[i].csr;
264 io7_port->saved_tbase[i] = csrs->POx_TBASE[i].csr;
265 }
266
267 /*
268 * Set up the PCI to main memory translation windows.
269 *
270 * Window 0 is scatter-gather 8MB at 8MB
271 * Window 1 is direct access 1GB at 2GB
272 * Window 2 is scatter-gather (up-to) 1GB at 3GB
273 * Window 3 is disabled
274 */
275
276 /*
277 * TBIA before modifying windows.
278 */
279 marvel_pci_tbi(hose, 0, -1);
280
281 /*
282 * Set up window 0 for scatter-gather 8MB at 8MB.
283 */
284 hose->sg_isa = iommu_arena_new_node(marvel_cpuid_to_nid(io7->pe),
285 hose, 0x00800000, 0x00800000, 0);
286 hose->sg_isa->align_entry = 8; /* cache line boundary */
287 csrs->POx_WBASE[0].csr =
288 hose->sg_isa->dma_base | wbase_m_ena | wbase_m_sg;
289 csrs->POx_WMASK[0].csr = (hose->sg_isa->size - 1) & wbase_m_addr;
290 csrs->POx_TBASE[0].csr = virt_to_phys(hose->sg_isa->ptes);
291
292 /*
293 * Set up window 1 for direct-mapped 1GB at 2GB.
294 */
295 csrs->POx_WBASE[1].csr = __direct_map_base | wbase_m_ena;
296 csrs->POx_WMASK[1].csr = (__direct_map_size - 1) & wbase_m_addr;
297 csrs->POx_TBASE[1].csr = 0;
298
299 /*
300 * Set up window 2 for scatter-gather (up-to) 1GB at 3GB.
301 */
302 hose->sg_pci = iommu_arena_new_node(marvel_cpuid_to_nid(io7->pe),
303 hose, 0xc0000000, 0x40000000, 0);
304 hose->sg_pci->align_entry = 8; /* cache line boundary */
305 csrs->POx_WBASE[2].csr =
306 hose->sg_pci->dma_base | wbase_m_ena | wbase_m_sg;
307 csrs->POx_WMASK[2].csr = (hose->sg_pci->size - 1) & wbase_m_addr;
308 csrs->POx_TBASE[2].csr = virt_to_phys(hose->sg_pci->ptes);
309
310 /*
311 * Disable window 3.
312 */
313 csrs->POx_WBASE[3].csr = 0;
314
315 /*
316 * Make sure that the AGP Monster Window is disabled.
317 */
318 csrs->POx_CTRL.csr &= ~(1UL << 61);
319
320#if 1
321 printk("FIXME: disabling master aborts\n");
322 csrs->POx_MSK_HEI.csr &= ~(3UL << 14);
323#endif
324 /*
325 * TBIA after modifying windows.
326 */
327 marvel_pci_tbi(hose, 0, -1);
328}
329
330static void __init
331marvel_init_io7(struct io7 *io7)
332{
333 int i;
334
335 printk("Initializing IO7 at PID %d\n", io7->pe);
336
337 /*
338 * Get the Port 7 CSR pointer.
339 */
340 io7->csrs = IO7_PORT7_CSRS_KERN(io7->pe);
341
342 /*
343 * Init this IO7's hoses.
344 */
345 for (i = 0; i < IO7_NUM_PORTS; i++) {
346 io7_ioport_csrs *csrs = IO7_CSRS_KERN(io7->pe, i);
347 if (csrs->POx_CACHE_CTL.csr == 8) {
348 io7->ports[i].enabled = 1;
349 io7_init_hose(io7, i);
350 }
351 }
352}
353
354void
355marvel_io7_present(gct6_node *node)
356{
357 int pe;
358
359 if (node->type != GCT_TYPE_HOSE ||
360 node->subtype != GCT_SUBTYPE_IO_PORT_MODULE)
361 return;
362
363 pe = (node->id >> 8) & 0xff;
364 printk("Found an IO7 at PID %d\n", pe);
365
366 alloc_io7(pe);
367}
368
369static void __init
370marvel_init_vga_hose(void)
371{
372#ifdef CONFIG_VGA_HOSE
373 u64 *pu64 = (u64 *)((u64)hwrpb + hwrpb->ctbt_offset);
374
375 if (pu64[7] == 3) { /* TERM_TYPE == graphics */
376 struct pci_controller *hose = NULL;
377 int h = (pu64[30] >> 24) & 0xff; /* TERM_OUT_LOC, hose # */
378 struct io7 *io7;
379 int pid, port;
380
381 /* FIXME - encoding is going to have to change for Marvel
382 * since hose will be able to overflow a byte...
383 * need to fix this decode when the console
384 * changes its encoding
385 */
386 printk("console graphics is on hose %d (console)\n", h);
387
388 /*
389 * The console's hose numbering is:
390 *
391 * hose<n:2>: PID
392 * hose<1:0>: PORT
393 *
394 * We need to find the hose at that pid and port
395 */
396 pid = h >> 2;
397 port = h & 3;
398 if ((io7 = marvel_find_io7(pid)))
399 hose = io7->ports[port].hose;
400
401 if (hose) {
402 printk("Console graphics on hose %d\n", hose->index);
403 pci_vga_hose = hose;
404 }
405 }
406#endif /* CONFIG_VGA_HOSE */
407}
408
409gct6_search_struct gct_wanted_node_list[] = {
410 { GCT_TYPE_HOSE, GCT_SUBTYPE_IO_PORT_MODULE, marvel_io7_present },
411 { 0, 0, NULL }
412};
413
414/*
415 * In case the GCT is not complete, let the user specify PIDs with IO7s
416 * at boot time. Syntax is 'io7=a,b,c,...,n' where a-n are the PIDs (decimal)
417 * where IO7s are connected
418 */
419static int __init
420marvel_specify_io7(char *str)
421{
422 unsigned long pid;
423 struct io7 *io7;
424 char *pchar;
425
426 do {
427 pid = simple_strtoul(str, &pchar, 0);
428 if (pchar != str) {
429 printk("User-specified IO7 at PID %lu\n", pid);
430 io7 = alloc_io7(pid);
431 if (io7) marvel_init_io7(io7);
432 }
433
434 if (pchar == str) pchar++;
435 str = pchar;
436 } while(*str);
437
438 return 0;
439}
440__setup("io7=", marvel_specify_io7);
441
442void __init
443marvel_init_arch(void)
444{
445 struct io7 *io7;
446
447 /* With multiple PCI busses, we play with I/O as physical addrs. */
448 ioport_resource.end = ~0UL;
449
450 /* PCI DMA Direct Mapping is 1GB at 2GB. */
451 __direct_map_base = 0x80000000;
452 __direct_map_size = 0x40000000;
453
454 /* Parse the config tree. */
455 gct6_find_nodes(GCT_NODE_PTR(0), gct_wanted_node_list);
456
457 /* Init the io7s. */
458 for (io7 = NULL; NULL != (io7 = marvel_next_io7(io7)); )
459 marvel_init_io7(io7);
460
461 /* Check for graphic console location (if any). */
462 marvel_init_vga_hose();
463}
464
465void
466marvel_kill_arch(int mode)
467{
468}
469
470
471/*
472 * PCI Configuration Space access functions
473 *
474 * Configuration space addresses have the following format:
475 *
476 * |2 2 2 2|1 1 1 1|1 1 1 1|1 1
477 * |3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
478 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
479 * |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|R|R|
480 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
481 *
482 * n:24 reserved for hose base
483 * 23:16 bus number (8 bits = 128 possible buses)
484 * 15:11 Device number (5 bits)
485 * 10:8 function number
486 * 7:2 register number
487 *
488 * Notes:
489 * IO7 determines whether to use a type 0 or type 1 config cycle
490 * based on the bus number. Therefore the bus number must be set
491 * to 0 for the root bus on any hose.
492 *
493 * The function number selects which function of a multi-function device
494 * (e.g., SCSI and Ethernet).
495 *
496 */
497
498static inline unsigned long
499build_conf_addr(struct pci_controller *hose, u8 bus,
500 unsigned int devfn, int where)
501{
502 return (hose->config_space_base | (bus << 16) | (devfn << 8) | where);
503}
504
505static unsigned long
506mk_conf_addr(struct pci_bus *pbus, unsigned int devfn, int where)
507{
508 struct pci_controller *hose = pbus->sysdata;
509 struct io7_port *io7_port;
510 unsigned long addr = 0;
511 u8 bus = pbus->number;
512
513 if (!hose)
514 return addr;
515
516 /* Check for enabled. */
517 io7_port = hose->sysdata;
518 if (!io7_port->enabled)
519 return addr;
520
521 if (!pbus->parent) { /* No parent means peer PCI bus. */
522 /* Don't support idsel > 20 on primary bus. */
523 if (devfn >= PCI_DEVFN(21, 0))
524 return addr;
525 bus = 0;
526 }
527
528 addr = build_conf_addr(hose, bus, devfn, where);
529
530 DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
531 return addr;
532}
533
534static int
535marvel_read_config(struct pci_bus *bus, unsigned int devfn, int where,
536 int size, u32 *value)
537{
538 unsigned long addr;
539
540 if (0 == (addr = mk_conf_addr(bus, devfn, where)))
541 return PCIBIOS_DEVICE_NOT_FOUND;
542
543 switch(size) {
544 case 1:
545 *value = __kernel_ldbu(*(vucp)addr);
546 break;
547 case 2:
548 *value = __kernel_ldwu(*(vusp)addr);
549 break;
550 case 4:
551 *value = *(vuip)addr;
552 break;
553 default:
554 return PCIBIOS_FUNC_NOT_SUPPORTED;
555 }
556
557 return PCIBIOS_SUCCESSFUL;
558}
559
560static int
561marvel_write_config(struct pci_bus *bus, unsigned int devfn, int where,
562 int size, u32 value)
563{
564 unsigned long addr;
565
566 if (0 == (addr = mk_conf_addr(bus, devfn, where)))
567 return PCIBIOS_DEVICE_NOT_FOUND;
568
569 switch (size) {
570 case 1:
571 __kernel_stb(value, *(vucp)addr);
572 mb();
573 __kernel_ldbu(*(vucp)addr);
574 break;
575 case 2:
576 __kernel_stw(value, *(vusp)addr);
577 mb();
578 __kernel_ldwu(*(vusp)addr);
579 break;
580 case 4:
581 *(vuip)addr = value;
582 mb();
583 *(vuip)addr;
584 break;
585 default:
586 return PCIBIOS_FUNC_NOT_SUPPORTED;
587 }
588
589 return PCIBIOS_SUCCESSFUL;
590}
591
592struct pci_ops marvel_pci_ops =
593{
594 .read = marvel_read_config,
595 .write = marvel_write_config,
596};
597
598
599/*
600 * Other PCI helper functions.
601 */
602void
603marvel_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
604{
605 io7_ioport_csrs *csrs = ((struct io7_port *)hose->sysdata)->csrs;
606
607 wmb();
608 csrs->POx_SG_TBIA.csr = 0;
609 mb();
610 csrs->POx_SG_TBIA.csr;
611}
612
613
614
615/*
616 * RTC Support
617 */
618struct marvel_rtc_access_info {
619 unsigned long function;
620 unsigned long index;
621 unsigned long data;
622};
623
624static void
625__marvel_access_rtc(void *info)
626{
627 struct marvel_rtc_access_info *rtc_access = info;
628
629 register unsigned long __r0 __asm__("$0");
630 register unsigned long __r16 __asm__("$16") = rtc_access->function;
631 register unsigned long __r17 __asm__("$17") = rtc_access->index;
632 register unsigned long __r18 __asm__("$18") = rtc_access->data;
633
634 __asm__ __volatile__(
635 "call_pal %4 # cserve rtc"
636 : "=r"(__r16), "=r"(__r17), "=r"(__r18), "=r"(__r0)
637 : "i"(PAL_cserve), "0"(__r16), "1"(__r17), "2"(__r18)
638 : "$1", "$22", "$23", "$24", "$25");
639
640 rtc_access->data = __r0;
641}
642
643static u8
644__marvel_rtc_io(u8 b, unsigned long addr, int write)
645{
646 static u8 index = 0;
647
648 struct marvel_rtc_access_info rtc_access;
649 u8 ret = 0;
650
651 switch(addr) {
652 case 0x70: /* RTC_PORT(0) */
653 if (write) index = b;
654 ret = index;
655 break;
656
657 case 0x71: /* RTC_PORT(1) */
658 rtc_access.index = index;
659 rtc_access.data = BCD_TO_BIN(b);
660 rtc_access.function = 0x48 + !write; /* GET/PUT_TOY */
661
662#ifdef CONFIG_SMP
663 if (smp_processor_id() != boot_cpuid)
664 smp_call_function_on_cpu(__marvel_access_rtc,
665 &rtc_access, 1, 1,
666 cpumask_of_cpu(boot_cpuid));
667 else
668 __marvel_access_rtc(&rtc_access);
669#else
670 __marvel_access_rtc(&rtc_access);
671#endif
672 ret = BIN_TO_BCD(rtc_access.data);
673 break;
674
675 default:
676 printk(KERN_WARNING "Illegal RTC port %lx\n", addr);
677 break;
678 }
679
680 return ret;
681}
682
683
684/*
685 * IO map support.
686 */
687
688#define __marvel_is_mem_vga(a) (((a) >= 0xa0000) && ((a) <= 0xc0000))
689
690void __iomem *
691marvel_ioremap(unsigned long addr, unsigned long size)
692{
693 struct pci_controller *hose;
694 unsigned long baddr, last;
695 struct vm_struct *area;
696 unsigned long vaddr;
697 unsigned long *ptes;
698 unsigned long pfn;
699
700 /*
701 * Adjust the addr.
702 */
703#ifdef CONFIG_VGA_HOSE
704 if (pci_vga_hose && __marvel_is_mem_vga(addr)) {
705 addr += pci_vga_hose->mem_space->start;
706 }
707#endif
708
709 /*
710 * Find the hose.
711 */
712 for (hose = hose_head; hose; hose = hose->next) {
713 if ((addr >> 32) == (hose->mem_space->start >> 32))
714 break;
715 }
716 if (!hose)
717 return NULL;
718
719 /*
720 * We have the hose - calculate the bus limits.
721 */
722 baddr = addr - hose->mem_space->start;
723 last = baddr + size - 1;
724
725 /*
726 * Is it direct-mapped?
727 */
728 if ((baddr >= __direct_map_base) &&
729 ((baddr + size - 1) < __direct_map_base + __direct_map_size)) {
730 addr = IDENT_ADDR | (baddr - __direct_map_base);
731 return (void __iomem *) addr;
732 }
733
734 /*
735 * Check the scatter-gather arena.
736 */
737 if (hose->sg_pci &&
738 baddr >= (unsigned long)hose->sg_pci->dma_base &&
739 last < (unsigned long)hose->sg_pci->dma_base + hose->sg_pci->size) {
740
741 /*
742 * Adjust the limits (mappings must be page aligned)
743 */
744 baddr -= hose->sg_pci->dma_base;
745 last -= hose->sg_pci->dma_base;
746 baddr &= PAGE_MASK;
747 size = PAGE_ALIGN(last) - baddr;
748
749 /*
750 * Map it.
751 */
752 area = get_vm_area(size, VM_IOREMAP);
753 if (!area)
754 return NULL;
755
756 ptes = hose->sg_pci->ptes;
757 for (vaddr = (unsigned long)area->addr;
758 baddr <= last;
759 baddr += PAGE_SIZE, vaddr += PAGE_SIZE) {
760 pfn = ptes[baddr >> PAGE_SHIFT];
761 if (!(pfn & 1)) {
762 printk("ioremap failed... pte not valid...\n");
763 vfree(area->addr);
764 return NULL;
765 }
766 pfn >>= 1; /* make it a true pfn */
767
768 if (__alpha_remap_area_pages(vaddr,
769 pfn << PAGE_SHIFT,
770 PAGE_SIZE, 0)) {
771 printk("FAILED to map...\n");
772 vfree(area->addr);
773 return NULL;
774 }
775 }
776
777 flush_tlb_all();
778
779 vaddr = (unsigned long)area->addr + (addr & ~PAGE_MASK);
780
781 return (void __iomem *) vaddr;
782 }
783
784 return NULL;
785}
786
787void
788marvel_iounmap(volatile void __iomem *xaddr)
789{
790 unsigned long addr = (unsigned long) xaddr;
791 if (addr >= VMALLOC_START)
792 vfree((void *)(PAGE_MASK & addr));
793}
794
795int
796marvel_is_mmio(const volatile void __iomem *xaddr)
797{
798 unsigned long addr = (unsigned long) xaddr;
799
800 if (addr >= VMALLOC_START)
801 return 1;
802 else
803 return (addr & 0xFF000000UL) == 0;
804}
805
806#define __marvel_is_port_vga(a) \
807 (((a) >= 0x3b0) && ((a) < 0x3e0) && ((a) != 0x3b3) && ((a) != 0x3d3))
808#define __marvel_is_port_kbd(a) (((a) == 0x60) || ((a) == 0x64))
809#define __marvel_is_port_rtc(a) (((a) == 0x70) || ((a) == 0x71))
810
811void __iomem *marvel_ioportmap (unsigned long addr)
812{
813 if (__marvel_is_port_rtc (addr) || __marvel_is_port_kbd(addr))
814 ;
815#ifdef CONFIG_VGA_HOSE
816 else if (__marvel_is_port_vga (addr) && pci_vga_hose)
817 addr += pci_vga_hose->io_space->start;
818#endif
819 else
820 return NULL;
821 return (void __iomem *)addr;
822}
823
824unsigned int
825marvel_ioread8(void __iomem *xaddr)
826{
827 unsigned long addr = (unsigned long) xaddr;
828 if (__marvel_is_port_kbd(addr))
829 return 0;
830 else if (__marvel_is_port_rtc(addr))
831 return __marvel_rtc_io(0, addr, 0);
832 else
833 return __kernel_ldbu(*(vucp)addr);
834}
835
836void
837marvel_iowrite8(u8 b, void __iomem *xaddr)
838{
839 unsigned long addr = (unsigned long) xaddr;
840 if (__marvel_is_port_kbd(addr))
841 return;
842 else if (__marvel_is_port_rtc(addr))
843 __marvel_rtc_io(b, addr, 1);
844 else
845 __kernel_stb(b, *(vucp)addr);
846}
847
848#ifndef CONFIG_ALPHA_GENERIC
849EXPORT_SYMBOL(marvel_ioremap);
850EXPORT_SYMBOL(marvel_iounmap);
851EXPORT_SYMBOL(marvel_is_mmio);
852EXPORT_SYMBOL(marvel_ioportmap);
853EXPORT_SYMBOL(marvel_ioread8);
854EXPORT_SYMBOL(marvel_iowrite8);
855#endif
856
857/*
858 * NUMA Support
859 */
860/**********
861 * FIXME - for now each cpu is a node by itself
862 * -- no real support for striped mode
863 **********
864 */
865int
866marvel_pa_to_nid(unsigned long pa)
867{
868 int cpuid;
869
870 if ((pa >> 43) & 1) /* I/O */
871 cpuid = (~(pa >> 35) & 0xff);
872 else /* mem */
873 cpuid = ((pa >> 34) & 0x3) | ((pa >> (37 - 2)) & (0x1f << 2));
874
875 return marvel_cpuid_to_nid(cpuid);
876}
877
878int
879marvel_cpuid_to_nid(int cpuid)
880{
881 return cpuid;
882}
883
884unsigned long
885marvel_node_mem_start(int nid)
886{
887 unsigned long pa;
888
889 pa = (nid & 0x3) | ((nid & (0x1f << 2)) << 1);
890 pa <<= 34;
891
892 return pa;
893}
894
895unsigned long
896marvel_node_mem_size(int nid)
897{
898 return 16UL * 1024 * 1024 * 1024; /* 16GB */
899}
900
901
902/*
903 * AGP GART Support.
904 */
905#include <linux/agp_backend.h>
906#include <asm/agp_backend.h>
907#include <linux/slab.h>
908#include <linux/delay.h>
909
910struct marvel_agp_aperture {
911 struct pci_iommu_arena *arena;
912 long pg_start;
913 long pg_count;
914};
915
916static int
917marvel_agp_setup(alpha_agp_info *agp)
918{
919 struct marvel_agp_aperture *aper;
920
921 if (!alpha_agpgart_size)
922 return -ENOMEM;
923
924 aper = kmalloc(sizeof(*aper), GFP_KERNEL);
925 if (aper == NULL) return -ENOMEM;
926
927 aper->arena = agp->hose->sg_pci;
928 aper->pg_count = alpha_agpgart_size / PAGE_SIZE;
929 aper->pg_start = iommu_reserve(aper->arena, aper->pg_count,
930 aper->pg_count - 1);
931
932 if (aper->pg_start < 0) {
933 printk(KERN_ERR "Failed to reserve AGP memory\n");
934 kfree(aper);
935 return -ENOMEM;
936 }
937
938 agp->aperture.bus_base =
939 aper->arena->dma_base + aper->pg_start * PAGE_SIZE;
940 agp->aperture.size = aper->pg_count * PAGE_SIZE;
941 agp->aperture.sysdata = aper;
942
943 return 0;
944}
945
946static void
947marvel_agp_cleanup(alpha_agp_info *agp)
948{
949 struct marvel_agp_aperture *aper = agp->aperture.sysdata;
950 int status;
951
952 status = iommu_release(aper->arena, aper->pg_start, aper->pg_count);
953 if (status == -EBUSY) {
954 printk(KERN_WARNING
955 "Attempted to release bound AGP memory - unbinding\n");
956 iommu_unbind(aper->arena, aper->pg_start, aper->pg_count);
957 status = iommu_release(aper->arena, aper->pg_start,
958 aper->pg_count);
959 }
960 if (status < 0)
961 printk(KERN_ERR "Failed to release AGP memory\n");
962
963 kfree(aper);
964 kfree(agp);
965}
966
967static int
968marvel_agp_configure(alpha_agp_info *agp)
969{
970 io7_ioport_csrs *csrs = ((struct io7_port *)agp->hose->sysdata)->csrs;
971 struct io7 *io7 = ((struct io7_port *)agp->hose->sysdata)->io7;
972 unsigned int new_rate = 0;
973 unsigned long agp_pll;
974
975 /*
976 * Check the requested mode against the PLL setting.
977 * The agpgart_be code has not programmed the card yet,
978 * so we can still tweak mode here.
979 */
980 agp_pll = io7->csrs->POx_RST[IO7_AGP_PORT].csr;
981 switch(IO7_PLL_RNGB(agp_pll)) {
982 case 0x4: /* 2x only */
983 /*
984 * The PLL is only programmed for 2x, so adjust the
985 * rate to 2x, if necessary.
986 */
987 if (agp->mode.bits.rate != 2)
988 new_rate = 2;
989 break;
990
991 case 0x6: /* 1x / 4x */
992 /*
993 * The PLL is programmed for 1x or 4x. Don't go faster
994 * than requested, so if the requested rate is 2x, use 1x.
995 */
996 if (agp->mode.bits.rate == 2)
997 new_rate = 1;
998 break;
999
1000 default: /* ??????? */
1001 /*
1002 * Don't know what this PLL setting is, take the requested
1003 * rate, but warn the user.
1004 */
1005 printk("%s: unknown PLL setting RNGB=%lx (PLL6_CTL=%016lx)\n",
1006 __FUNCTION__, IO7_PLL_RNGB(agp_pll), agp_pll);
1007 break;
1008 }
1009
1010 /*
1011 * Set the new rate, if necessary.
1012 */
1013 if (new_rate) {
1014 printk("Requested AGP Rate %dX not compatible "
1015 "with PLL setting - using %dX\n",
1016 agp->mode.bits.rate,
1017 new_rate);
1018
1019 agp->mode.bits.rate = new_rate;
1020 }
1021
1022 printk("Enabling AGP on hose %d: %dX%s RQ %d\n",
1023 agp->hose->index, agp->mode.bits.rate,
1024 agp->mode.bits.sba ? " - SBA" : "", agp->mode.bits.rq);
1025
1026 csrs->AGP_CMD.csr = agp->mode.lw;
1027
1028 return 0;
1029}
1030
1031static int
1032marvel_agp_bind_memory(alpha_agp_info *agp, off_t pg_start, struct agp_memory *mem)
1033{
1034 struct marvel_agp_aperture *aper = agp->aperture.sysdata;
1035 return iommu_bind(aper->arena, aper->pg_start + pg_start,
1036 mem->page_count, mem->memory);
1037}
1038
1039static int
1040marvel_agp_unbind_memory(alpha_agp_info *agp, off_t pg_start, struct agp_memory *mem)
1041{
1042 struct marvel_agp_aperture *aper = agp->aperture.sysdata;
1043 return iommu_unbind(aper->arena, aper->pg_start + pg_start,
1044 mem->page_count);
1045}
1046
1047static unsigned long
1048marvel_agp_translate(alpha_agp_info *agp, dma_addr_t addr)
1049{
1050 struct marvel_agp_aperture *aper = agp->aperture.sysdata;
1051 unsigned long baddr = addr - aper->arena->dma_base;
1052 unsigned long pte;
1053
1054 if (addr < agp->aperture.bus_base ||
1055 addr >= agp->aperture.bus_base + agp->aperture.size) {
1056 printk("%s: addr out of range\n", __FUNCTION__);
1057 return -EINVAL;
1058 }
1059
1060 pte = aper->arena->ptes[baddr >> PAGE_SHIFT];
1061 if (!(pte & 1)) {
1062 printk("%s: pte not valid\n", __FUNCTION__);
1063 return -EINVAL;
1064 }
1065 return (pte >> 1) << PAGE_SHIFT;
1066}
1067
1068struct alpha_agp_ops marvel_agp_ops =
1069{
1070 .setup = marvel_agp_setup,
1071 .cleanup = marvel_agp_cleanup,
1072 .configure = marvel_agp_configure,
1073 .bind = marvel_agp_bind_memory,
1074 .unbind = marvel_agp_unbind_memory,
1075 .translate = marvel_agp_translate
1076};
1077
1078alpha_agp_info *
1079marvel_agp_info(void)
1080{
1081 struct pci_controller *hose;
1082 io7_ioport_csrs *csrs;
1083 alpha_agp_info *agp;
1084 struct io7 *io7;
1085
1086 /*
1087 * Find the first IO7 with an AGP card.
1088 *
1089 * FIXME -- there should be a better way (we want to be able to
1090 * specify and what if the agp card is not video???)
1091 */
1092 hose = NULL;
1093 for (io7 = NULL; (io7 = marvel_next_io7(io7)) != NULL; ) {
1094 struct pci_controller *h;
1095 vuip addr;
1096
1097 if (!io7->ports[IO7_AGP_PORT].enabled)
1098 continue;
1099
1100 h = io7->ports[IO7_AGP_PORT].hose;
1101 addr = (vuip)build_conf_addr(h, 0, PCI_DEVFN(5, 0), 0);
1102
1103 if (*addr != 0xffffffffu) {
1104 hose = h;
1105 break;
1106 }
1107 }
1108
1109 if (!hose || !hose->sg_pci)
1110 return NULL;
1111
1112 printk("MARVEL - using hose %d as AGP\n", hose->index);
1113
1114 /*
1115 * Get the csrs from the hose.
1116 */
1117 csrs = ((struct io7_port *)hose->sysdata)->csrs;
1118
1119 /*
1120 * Allocate the info structure.
1121 */
1122 agp = kmalloc(sizeof(*agp), GFP_KERNEL);
1123
1124 /*
1125 * Fill it in.
1126 */
1127 agp->hose = hose;
1128 agp->private = NULL;
1129 agp->ops = &marvel_agp_ops;
1130
1131 /*
1132 * Aperture - not configured until ops.setup().
1133 */
1134 agp->aperture.bus_base = 0;
1135 agp->aperture.size = 0;
1136 agp->aperture.sysdata = NULL;
1137
1138 /*
1139 * Capabilities.
1140 *
1141 * NOTE: IO7 reports through AGP_STAT that it can support a read queue
1142 * depth of 17 (rq = 0x10). It actually only supports a depth of
1143 * 16 (rq = 0xf).
1144 */
1145 agp->capability.lw = csrs->AGP_STAT.csr;
1146 agp->capability.bits.rq = 0xf;
1147
1148 /*
1149 * Mode.
1150 */
1151 agp->mode.lw = csrs->AGP_CMD.csr;
1152
1153 return agp;
1154}
diff --git a/arch/alpha/kernel/core_mcpcia.c b/arch/alpha/kernel/core_mcpcia.c
new file mode 100644
index 000000000000..28849c894153
--- /dev/null
+++ b/arch/alpha/kernel/core_mcpcia.c
@@ -0,0 +1,618 @@
1/*
2 * linux/arch/alpha/kernel/core_mcpcia.c
3 *
4 * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com).
5 *
6 * Code common to all MCbus-PCI Adaptor core logic chipsets
7 */
8
9#define __EXTERN_INLINE inline
10#include <asm/io.h>
11#include <asm/core_mcpcia.h>
12#undef __EXTERN_INLINE
13
14#include <linux/types.h>
15#include <linux/pci.h>
16#include <linux/sched.h>
17#include <linux/init.h>
18#include <linux/delay.h>
19
20#include <asm/ptrace.h>
21
22#include "proto.h"
23#include "pci_impl.h"
24
25/*
26 * NOTE: Herein lie back-to-back mb instructions. They are magic.
27 * One plausible explanation is that the i/o controller does not properly
28 * handle the system transaction. Another involves timing. Ho hum.
29 */
30
31/*
32 * BIOS32-style PCI interface:
33 */
34
35#define DEBUG_CFG 0
36
37#if DEBUG_CFG
38# define DBG_CFG(args) printk args
39#else
40# define DBG_CFG(args)
41#endif
42
43#define MCPCIA_MAX_HOSES 4
44
45/*
46 * Given a bus, device, and function number, compute resulting
47 * configuration space address and setup the MCPCIA_HAXR2 register
48 * accordingly. It is therefore not safe to have concurrent
49 * invocations to configuration space access routines, but there
50 * really shouldn't be any need for this.
51 *
52 * Type 0:
53 *
54 * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
55 * 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
56 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57 * | | |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|
58 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59 *
60 * 31:11 Device select bit.
61 * 10:8 Function number
62 * 7:2 Register number
63 *
64 * Type 1:
65 *
66 * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
67 * 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
68 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69 * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
70 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
71 *
72 * 31:24 reserved
73 * 23:16 bus number (8 bits = 128 possible buses)
74 * 15:11 Device number (5 bits)
75 * 10:8 function number
76 * 7:2 register number
77 *
78 * Notes:
79 * The function number selects which function of a multi-function device
80 * (e.g., SCSI and Ethernet).
81 *
82 * The register selects a DWORD (32 bit) register offset. Hence it
83 * doesn't get shifted by 2 bits as we want to "drop" the bottom two
84 * bits.
85 */
86
87static unsigned int
88conf_read(unsigned long addr, unsigned char type1,
89 struct pci_controller *hose)
90{
91 unsigned long flags;
92 unsigned long mid = MCPCIA_HOSE2MID(hose->index);
93 unsigned int stat0, value, temp, cpu;
94
95 cpu = smp_processor_id();
96
97 local_irq_save(flags);
98
99 DBG_CFG(("conf_read(addr=0x%lx, type1=%d, hose=%d)\n",
100 addr, type1, mid));
101
102 /* Reset status register to avoid losing errors. */
103 stat0 = *(vuip)MCPCIA_CAP_ERR(mid);
104 *(vuip)MCPCIA_CAP_ERR(mid) = stat0;
105 mb();
106 temp = *(vuip)MCPCIA_CAP_ERR(mid);
107 DBG_CFG(("conf_read: MCPCIA_CAP_ERR(%d) was 0x%x\n", mid, stat0));
108
109 mb();
110 draina();
111 mcheck_expected(cpu) = 1;
112 mcheck_taken(cpu) = 0;
113 mcheck_extra(cpu) = mid;
114 mb();
115
116 /* Access configuration space. */
117 value = *((vuip)addr);
118 mb();
119 mb(); /* magic */
120
121 if (mcheck_taken(cpu)) {
122 mcheck_taken(cpu) = 0;
123 value = 0xffffffffU;
124 mb();
125 }
126 mcheck_expected(cpu) = 0;
127 mb();
128
129 DBG_CFG(("conf_read(): finished\n"));
130
131 local_irq_restore(flags);
132 return value;
133}
134
135static void
136conf_write(unsigned long addr, unsigned int value, unsigned char type1,
137 struct pci_controller *hose)
138{
139 unsigned long flags;
140 unsigned long mid = MCPCIA_HOSE2MID(hose->index);
141 unsigned int stat0, temp, cpu;
142
143 cpu = smp_processor_id();
144
145 local_irq_save(flags); /* avoid getting hit by machine check */
146
147 /* Reset status register to avoid losing errors. */
148 stat0 = *(vuip)MCPCIA_CAP_ERR(mid);
149 *(vuip)MCPCIA_CAP_ERR(mid) = stat0; mb();
150 temp = *(vuip)MCPCIA_CAP_ERR(mid);
151 DBG_CFG(("conf_write: MCPCIA CAP_ERR(%d) was 0x%x\n", mid, stat0));
152
153 draina();
154 mcheck_expected(cpu) = 1;
155 mcheck_extra(cpu) = mid;
156 mb();
157
158 /* Access configuration space. */
159 *((vuip)addr) = value;
160 mb();
161 mb(); /* magic */
162 temp = *(vuip)MCPCIA_CAP_ERR(mid); /* read to force the write */
163 mcheck_expected(cpu) = 0;
164 mb();
165
166 DBG_CFG(("conf_write(): finished\n"));
167 local_irq_restore(flags);
168}
169
170static int
171mk_conf_addr(struct pci_bus *pbus, unsigned int devfn, int where,
172 struct pci_controller *hose, unsigned long *pci_addr,
173 unsigned char *type1)
174{
175 u8 bus = pbus->number;
176 unsigned long addr;
177
178 DBG_CFG(("mk_conf_addr(bus=%d,devfn=0x%x,hose=%d,where=0x%x,"
179 " pci_addr=0x%p, type1=0x%p)\n",
180 bus, devfn, hose->index, where, pci_addr, type1));
181
182 /* Type 1 configuration cycle for *ALL* busses. */
183 *type1 = 1;
184
185 if (!pbus->parent) /* No parent means peer PCI bus. */
186 bus = 0;
187 addr = (bus << 16) | (devfn << 8) | (where);
188 addr <<= 5; /* swizzle for SPARSE */
189 addr |= hose->config_space_base;
190
191 *pci_addr = addr;
192 DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
193 return 0;
194}
195
196static int
197mcpcia_read_config(struct pci_bus *bus, unsigned int devfn, int where,
198 int size, u32 *value)
199{
200 struct pci_controller *hose = bus->sysdata;
201 unsigned long addr, w;
202 unsigned char type1;
203
204 if (mk_conf_addr(bus, devfn, where, hose, &addr, &type1))
205 return PCIBIOS_DEVICE_NOT_FOUND;
206
207 addr |= (size - 1) * 8;
208 w = conf_read(addr, type1, hose);
209 switch (size) {
210 case 1:
211 *value = __kernel_extbl(w, where & 3);
212 break;
213 case 2:
214 *value = __kernel_extwl(w, where & 3);
215 break;
216 case 4:
217 *value = w;
218 break;
219 }
220 return PCIBIOS_SUCCESSFUL;
221}
222
223static int
224mcpcia_write_config(struct pci_bus *bus, unsigned int devfn, int where,
225 int size, u32 value)
226{
227 struct pci_controller *hose = bus->sysdata;
228 unsigned long addr;
229 unsigned char type1;
230
231 if (mk_conf_addr(bus, devfn, where, hose, &addr, &type1))
232 return PCIBIOS_DEVICE_NOT_FOUND;
233
234 addr |= (size - 1) * 8;
235 value = __kernel_insql(value, where & 3);
236 conf_write(addr, value, type1, hose);
237 return PCIBIOS_SUCCESSFUL;
238}
239
240struct pci_ops mcpcia_pci_ops =
241{
242 .read = mcpcia_read_config,
243 .write = mcpcia_write_config,
244};
245
246void
247mcpcia_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
248{
249 wmb();
250 *(vuip)MCPCIA_SG_TBIA(MCPCIA_HOSE2MID(hose->index)) = 0;
251 mb();
252}
253
254static int __init
255mcpcia_probe_hose(int h)
256{
257 int cpu = smp_processor_id();
258 int mid = MCPCIA_HOSE2MID(h);
259 unsigned int pci_rev;
260
261 /* Gotta be REAL careful. If hose is absent, we get an mcheck. */
262
263 mb();
264 mb();
265 draina();
266 wrmces(7);
267
268 mcheck_expected(cpu) = 2; /* indicates probing */
269 mcheck_taken(cpu) = 0;
270 mcheck_extra(cpu) = mid;
271 mb();
272
273 /* Access the bus revision word. */
274 pci_rev = *(vuip)MCPCIA_REV(mid);
275
276 mb();
277 mb(); /* magic */
278 if (mcheck_taken(cpu)) {
279 mcheck_taken(cpu) = 0;
280 pci_rev = 0xffffffff;
281 mb();
282 }
283 mcheck_expected(cpu) = 0;
284 mb();
285
286 return (pci_rev >> 16) == PCI_CLASS_BRIDGE_HOST;
287}
288
289static void __init
290mcpcia_new_hose(int h)
291{
292 struct pci_controller *hose;
293 struct resource *io, *mem, *hae_mem;
294 int mid = MCPCIA_HOSE2MID(h);
295
296 hose = alloc_pci_controller();
297 if (h == 0)
298 pci_isa_hose = hose;
299 io = alloc_resource();
300 mem = alloc_resource();
301 hae_mem = alloc_resource();
302
303 hose->io_space = io;
304 hose->mem_space = hae_mem;
305 hose->sparse_mem_base = MCPCIA_SPARSE(mid) - IDENT_ADDR;
306 hose->dense_mem_base = MCPCIA_DENSE(mid) - IDENT_ADDR;
307 hose->sparse_io_base = MCPCIA_IO(mid) - IDENT_ADDR;
308 hose->dense_io_base = 0;
309 hose->config_space_base = MCPCIA_CONF(mid);
310 hose->index = h;
311
312 io->start = MCPCIA_IO(mid) - MCPCIA_IO_BIAS;
313 io->end = io->start + 0xffff;
314 io->name = pci_io_names[h];
315 io->flags = IORESOURCE_IO;
316
317 mem->start = MCPCIA_DENSE(mid) - MCPCIA_MEM_BIAS;
318 mem->end = mem->start + 0xffffffff;
319 mem->name = pci_mem_names[h];
320 mem->flags = IORESOURCE_MEM;
321
322 hae_mem->start = mem->start;
323 hae_mem->end = mem->start + MCPCIA_MEM_MASK;
324 hae_mem->name = pci_hae0_name;
325 hae_mem->flags = IORESOURCE_MEM;
326
327 if (request_resource(&ioport_resource, io) < 0)
328 printk(KERN_ERR "Failed to request IO on hose %d\n", h);
329 if (request_resource(&iomem_resource, mem) < 0)
330 printk(KERN_ERR "Failed to request MEM on hose %d\n", h);
331 if (request_resource(mem, hae_mem) < 0)
332 printk(KERN_ERR "Failed to request HAE_MEM on hose %d\n", h);
333}
334
335static void
336mcpcia_pci_clr_err(int mid)
337{
338 *(vuip)MCPCIA_CAP_ERR(mid);
339 *(vuip)MCPCIA_CAP_ERR(mid) = 0xffffffff; /* Clear them all. */
340 mb();
341 *(vuip)MCPCIA_CAP_ERR(mid); /* Re-read for force write. */
342}
343
344static void __init
345mcpcia_startup_hose(struct pci_controller *hose)
346{
347 int mid = MCPCIA_HOSE2MID(hose->index);
348 unsigned int tmp;
349
350 mcpcia_pci_clr_err(mid);
351
352 /*
353 * Set up error reporting.
354 */
355 tmp = *(vuip)MCPCIA_CAP_ERR(mid);
356 tmp |= 0x0006; /* master/target abort */
357 *(vuip)MCPCIA_CAP_ERR(mid) = tmp;
358 mb();
359 tmp = *(vuip)MCPCIA_CAP_ERR(mid);
360
361 /*
362 * Set up the PCI->physical memory translation windows.
363 *
364 * Window 0 is scatter-gather 8MB at 8MB (for isa)
365 * Window 1 is scatter-gather (up to) 1GB at 1GB (for pci)
366 * Window 2 is direct access 2GB at 2GB
367 */
368 hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
369 hose->sg_pci = iommu_arena_new(hose, 0x40000000,
370 size_for_memory(0x40000000), 0);
371
372 __direct_map_base = 0x80000000;
373 __direct_map_size = 0x80000000;
374
375 *(vuip)MCPCIA_W0_BASE(mid) = hose->sg_isa->dma_base | 3;
376 *(vuip)MCPCIA_W0_MASK(mid) = (hose->sg_isa->size - 1) & 0xfff00000;
377 *(vuip)MCPCIA_T0_BASE(mid) = virt_to_phys(hose->sg_isa->ptes) >> 8;
378
379 *(vuip)MCPCIA_W1_BASE(mid) = hose->sg_pci->dma_base | 3;
380 *(vuip)MCPCIA_W1_MASK(mid) = (hose->sg_pci->size - 1) & 0xfff00000;
381 *(vuip)MCPCIA_T1_BASE(mid) = virt_to_phys(hose->sg_pci->ptes) >> 8;
382
383 *(vuip)MCPCIA_W2_BASE(mid) = __direct_map_base | 1;
384 *(vuip)MCPCIA_W2_MASK(mid) = (__direct_map_size - 1) & 0xfff00000;
385 *(vuip)MCPCIA_T2_BASE(mid) = 0;
386
387 *(vuip)MCPCIA_W3_BASE(mid) = 0x0;
388
389 mcpcia_pci_tbi(hose, 0, -1);
390
391 *(vuip)MCPCIA_HBASE(mid) = 0x0;
392 mb();
393
394 *(vuip)MCPCIA_HAE_MEM(mid) = 0U;
395 mb();
396 *(vuip)MCPCIA_HAE_MEM(mid); /* read it back. */
397 *(vuip)MCPCIA_HAE_IO(mid) = 0;
398 mb();
399 *(vuip)MCPCIA_HAE_IO(mid); /* read it back. */
400}
401
402void __init
403mcpcia_init_arch(void)
404{
405 /* With multiple PCI busses, we play with I/O as physical addrs. */
406 ioport_resource.end = ~0UL;
407
408 /* Allocate hose 0. That's the one that all the ISA junk hangs
409 off of, from which we'll be registering stuff here in a bit.
410 Other hose detection is done in mcpcia_init_hoses, which is
411 called from init_IRQ. */
412
413 mcpcia_new_hose(0);
414}
415
416/* This is called from init_IRQ, since we cannot take interrupts
417 before then. Which means we cannot do this in init_arch. */
418
419void __init
420mcpcia_init_hoses(void)
421{
422 struct pci_controller *hose;
423 int hose_count;
424 int h;
425
426 /* First, find how many hoses we have. */
427 hose_count = 0;
428 for (h = 0; h < MCPCIA_MAX_HOSES; ++h) {
429 if (mcpcia_probe_hose(h)) {
430 if (h != 0)
431 mcpcia_new_hose(h);
432 hose_count++;
433 }
434 }
435
436 printk("mcpcia_init_hoses: found %d hoses\n", hose_count);
437
438 /* Now do init for each hose. */
439 for (hose = hose_head; hose; hose = hose->next)
440 mcpcia_startup_hose(hose);
441}
442
443static void
444mcpcia_print_uncorrectable(struct el_MCPCIA_uncorrected_frame_mcheck *logout)
445{
446 struct el_common_EV5_uncorrectable_mcheck *frame;
447 int i;
448
449 frame = &logout->procdata;
450
451 /* Print PAL fields */
452 for (i = 0; i < 24; i += 2) {
453 printk(" paltmp[%d-%d] = %16lx %16lx\n",
454 i, i+1, frame->paltemp[i], frame->paltemp[i+1]);
455 }
456 for (i = 0; i < 8; i += 2) {
457 printk(" shadow[%d-%d] = %16lx %16lx\n",
458 i, i+1, frame->shadow[i],
459 frame->shadow[i+1]);
460 }
461 printk(" Addr of excepting instruction = %16lx\n",
462 frame->exc_addr);
463 printk(" Summary of arithmetic traps = %16lx\n",
464 frame->exc_sum);
465 printk(" Exception mask = %16lx\n",
466 frame->exc_mask);
467 printk(" Base address for PALcode = %16lx\n",
468 frame->pal_base);
469 printk(" Interrupt Status Reg = %16lx\n",
470 frame->isr);
471 printk(" CURRENT SETUP OF EV5 IBOX = %16lx\n",
472 frame->icsr);
473 printk(" I-CACHE Reg %s parity error = %16lx\n",
474 (frame->ic_perr_stat & 0x800L) ?
475 "Data" : "Tag",
476 frame->ic_perr_stat);
477 printk(" D-CACHE error Reg = %16lx\n",
478 frame->dc_perr_stat);
479 if (frame->dc_perr_stat & 0x2) {
480 switch (frame->dc_perr_stat & 0x03c) {
481 case 8:
482 printk(" Data error in bank 1\n");
483 break;
484 case 4:
485 printk(" Data error in bank 0\n");
486 break;
487 case 20:
488 printk(" Tag error in bank 1\n");
489 break;
490 case 10:
491 printk(" Tag error in bank 0\n");
492 break;
493 }
494 }
495 printk(" Effective VA = %16lx\n",
496 frame->va);
497 printk(" Reason for D-stream = %16lx\n",
498 frame->mm_stat);
499 printk(" EV5 SCache address = %16lx\n",
500 frame->sc_addr);
501 printk(" EV5 SCache TAG/Data parity = %16lx\n",
502 frame->sc_stat);
503 printk(" EV5 BC_TAG_ADDR = %16lx\n",
504 frame->bc_tag_addr);
505 printk(" EV5 EI_ADDR: Phys addr of Xfer = %16lx\n",
506 frame->ei_addr);
507 printk(" Fill Syndrome = %16lx\n",
508 frame->fill_syndrome);
509 printk(" EI_STAT reg = %16lx\n",
510 frame->ei_stat);
511 printk(" LD_LOCK = %16lx\n",
512 frame->ld_lock);
513}
514
515static void
516mcpcia_print_system_area(unsigned long la_ptr)
517{
518 struct el_common *frame;
519 struct pci_controller *hose;
520
521 struct IOD_subpacket {
522 unsigned long base;
523 unsigned int whoami;
524 unsigned int rsvd1;
525 unsigned int pci_rev;
526 unsigned int cap_ctrl;
527 unsigned int hae_mem;
528 unsigned int hae_io;
529 unsigned int int_ctl;
530 unsigned int int_reg;
531 unsigned int int_mask0;
532 unsigned int int_mask1;
533 unsigned int mc_err0;
534 unsigned int mc_err1;
535 unsigned int cap_err;
536 unsigned int rsvd2;
537 unsigned int pci_err1;
538 unsigned int mdpa_stat;
539 unsigned int mdpa_syn;
540 unsigned int mdpb_stat;
541 unsigned int mdpb_syn;
542 unsigned int rsvd3;
543 unsigned int rsvd4;
544 unsigned int rsvd5;
545 } *iodpp;
546
547 frame = (struct el_common *)la_ptr;
548 iodpp = (struct IOD_subpacket *) (la_ptr + frame->sys_offset);
549
550 for (hose = hose_head; hose; hose = hose->next, iodpp++) {
551
552 printk("IOD %d Register Subpacket - Bridge Base Address %16lx\n",
553 hose->index, iodpp->base);
554 printk(" WHOAMI = %8x\n", iodpp->whoami);
555 printk(" PCI_REV = %8x\n", iodpp->pci_rev);
556 printk(" CAP_CTRL = %8x\n", iodpp->cap_ctrl);
557 printk(" HAE_MEM = %8x\n", iodpp->hae_mem);
558 printk(" HAE_IO = %8x\n", iodpp->hae_io);
559 printk(" INT_CTL = %8x\n", iodpp->int_ctl);
560 printk(" INT_REG = %8x\n", iodpp->int_reg);
561 printk(" INT_MASK0 = %8x\n", iodpp->int_mask0);
562 printk(" INT_MASK1 = %8x\n", iodpp->int_mask1);
563 printk(" MC_ERR0 = %8x\n", iodpp->mc_err0);
564 printk(" MC_ERR1 = %8x\n", iodpp->mc_err1);
565 printk(" CAP_ERR = %8x\n", iodpp->cap_err);
566 printk(" PCI_ERR1 = %8x\n", iodpp->pci_err1);
567 printk(" MDPA_STAT = %8x\n", iodpp->mdpa_stat);
568 printk(" MDPA_SYN = %8x\n", iodpp->mdpa_syn);
569 printk(" MDPB_STAT = %8x\n", iodpp->mdpb_stat);
570 printk(" MDPB_SYN = %8x\n", iodpp->mdpb_syn);
571 }
572}
573
574void
575mcpcia_machine_check(unsigned long vector, unsigned long la_ptr,
576 struct pt_regs * regs)
577{
578 struct el_common *mchk_header;
579 struct el_MCPCIA_uncorrected_frame_mcheck *mchk_logout;
580 unsigned int cpu = smp_processor_id();
581 int expected;
582
583 mchk_header = (struct el_common *)la_ptr;
584 mchk_logout = (struct el_MCPCIA_uncorrected_frame_mcheck *)la_ptr;
585 expected = mcheck_expected(cpu);
586
587 mb();
588 mb(); /* magic */
589 draina();
590
591 switch (expected) {
592 case 0:
593 {
594 /* FIXME: how do we figure out which hose the
595 error was on? */
596 struct pci_controller *hose;
597 for (hose = hose_head; hose; hose = hose->next)
598 mcpcia_pci_clr_err(MCPCIA_HOSE2MID(hose->index));
599 break;
600 }
601 case 1:
602 mcpcia_pci_clr_err(mcheck_extra(cpu));
603 break;
604 default:
605 /* Otherwise, we're being called from mcpcia_probe_hose
606 and there's no hose clear an error from. */
607 break;
608 }
609
610 wrmces(0x7);
611 mb();
612
613 process_mcheck_info(vector, la_ptr, regs, "MCPCIA", expected != 0);
614 if (!expected && vector != 0x620 && vector != 0x630) {
615 mcpcia_print_uncorrectable(mchk_logout);
616 mcpcia_print_system_area(la_ptr);
617 }
618}
diff --git a/arch/alpha/kernel/core_polaris.c b/arch/alpha/kernel/core_polaris.c
new file mode 100644
index 000000000000..277674a500ff
--- /dev/null
+++ b/arch/alpha/kernel/core_polaris.c
@@ -0,0 +1,203 @@
1/*
2 * linux/arch/alpha/kernel/core_polaris.c
3 *
4 * POLARIS chip-specific code
5 */
6
7#define __EXTERN_INLINE inline
8#include <asm/io.h>
9#include <asm/core_polaris.h>
10#undef __EXTERN_INLINE
11
12#include <linux/types.h>
13#include <linux/pci.h>
14#include <linux/sched.h>
15#include <linux/init.h>
16
17#include <asm/ptrace.h>
18
19#include "proto.h"
20#include "pci_impl.h"
21
22/*
23 * BIOS32-style PCI interface:
24 */
25
26#define DEBUG_CONFIG 0
27
28#if DEBUG_CONFIG
29# define DBG_CFG(args) printk args
30#else
31# define DBG_CFG(args)
32#endif
33
34
35/*
36 * Given a bus, device, and function number, compute resulting
37 * configuration space address. This is fairly straightforward
38 * on POLARIS, since the chip itself generates Type 0 or Type 1
39 * cycles automatically depending on the bus number (Bus 0 is
40 * hardwired to Type 0, all others are Type 1. Peer bridges
41 * are not supported).
42 *
43 * All types:
44 *
45 * 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
46 * 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
47 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48 * |1|1|1|1|1|0|0|1|1|1|1|1|1|1|1|0|B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|x|x|
49 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50 *
51 * 23:16 bus number (8 bits = 128 possible buses)
52 * 15:11 Device number (5 bits)
53 * 10:8 function number
54 * 7:2 register number
55 *
56 * Notes:
57 * The function number selects which function of a multi-function device
58 * (e.g., scsi and ethernet).
59 *
60 * The register selects a DWORD (32 bit) register offset. Hence it
61 * doesn't get shifted by 2 bits as we want to "drop" the bottom two
62 * bits.
63 */
64
65static int
66mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
67 unsigned long *pci_addr, u8 *type1)
68{
69 u8 bus = pbus->number;
70
71 *type1 = (bus == 0) ? 0 : 1;
72 *pci_addr = (bus << 16) | (device_fn << 8) | (where) |
73 POLARIS_DENSE_CONFIG_BASE;
74
75 DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
76 " returning address 0x%p\n"
77 bus, device_fn, where, *pci_addr));
78
79 return 0;
80}
81
82static int
83polaris_read_config(struct pci_bus *bus, unsigned int devfn, int where,
84 int size, u32 *value)
85{
86 unsigned long addr;
87 unsigned char type1;
88
89 if (mk_conf_addr(bus, devfn, where, &addr, &type1))
90 return PCIBIOS_DEVICE_NOT_FOUND;
91
92 switch (size) {
93 case 1:
94 *value = __kernel_ldbu(*(vucp)addr);
95 break;
96 case 2:
97 *value = __kernel_ldwu(*(vusp)addr);
98 break;
99 case 4:
100 *value = *(vuip)addr;
101 break;
102 }
103
104 return PCIBIOS_SUCCESSFUL;
105}
106
107
108static int
109polaris_write_config(struct pci_bus *bus, unsigned int devfn, int where,
110 int size, u32 value)
111{
112 unsigned long addr;
113 unsigned char type1;
114
115 if (mk_conf_addr(bus, devfn, where, &addr, &type1))
116 return PCIBIOS_DEVICE_NOT_FOUND;
117
118 switch (size) {
119 case 1:
120 __kernel_stb(value, *(vucp)addr);
121 mb();
122 __kernel_ldbu(*(vucp)addr);
123 break;
124 case 2:
125 __kernel_stw(value, *(vusp)addr);
126 mb();
127 __kernel_ldwu(*(vusp)addr);
128 break;
129 case 4:
130 *(vuip)addr = value;
131 mb();
132 *(vuip)addr;
133 break;
134 }
135
136 return PCIBIOS_SUCCESSFUL;
137}
138
139struct pci_ops polaris_pci_ops =
140{
141 .read = polaris_read_config,
142 .write = polaris_write_config,
143};
144
145void __init
146polaris_init_arch(void)
147{
148 struct pci_controller *hose;
149
150 /* May need to initialize error reporting (see PCICTL0/1), but
151 * for now assume that the firmware has done the right thing
152 * already.
153 */
154#if 0
155 printk("polaris_init_arch(): trusting firmware for setup\n");
156#endif
157
158 /*
159 * Create our single hose.
160 */
161
162 pci_isa_hose = hose = alloc_pci_controller();
163 hose->io_space = &ioport_resource;
164 hose->mem_space = &iomem_resource;
165 hose->index = 0;
166
167 hose->sparse_mem_base = 0;
168 hose->dense_mem_base = POLARIS_DENSE_MEM_BASE - IDENT_ADDR;
169 hose->sparse_io_base = 0;
170 hose->dense_io_base = POLARIS_DENSE_IO_BASE - IDENT_ADDR;
171
172 hose->sg_isa = hose->sg_pci = NULL;
173
174 /* The I/O window is fixed at 2G @ 2G. */
175 __direct_map_base = 0x80000000;
176 __direct_map_size = 0x80000000;
177}
178
179static inline void
180polaris_pci_clr_err(void)
181{
182 *(vusp)POLARIS_W_STATUS;
183 /* Write 1's to settable bits to clear errors */
184 *(vusp)POLARIS_W_STATUS = 0x7800;
185 mb();
186 *(vusp)POLARIS_W_STATUS;
187}
188
189void
190polaris_machine_check(unsigned long vector, unsigned long la_ptr,
191 struct pt_regs * regs)
192{
193 /* Clear the error before any reporting. */
194 mb();
195 mb();
196 draina();
197 polaris_pci_clr_err();
198 wrmces(0x7);
199 mb();
200
201 process_mcheck_info(vector, la_ptr, regs, "POLARIS",
202 mcheck_expected(0));
203}
diff --git a/arch/alpha/kernel/core_t2.c b/arch/alpha/kernel/core_t2.c
new file mode 100644
index 000000000000..ecce09e3626a
--- /dev/null
+++ b/arch/alpha/kernel/core_t2.c
@@ -0,0 +1,622 @@
1/*
2 * linux/arch/alpha/kernel/core_t2.c
3 *
4 * Written by Jay A Estabrook (jestabro@amt.tay1.dec.com).
5 * December 1996.
6 *
7 * based on CIA code by David A Rusling (david.rusling@reo.mts.dec.com)
8 *
9 * Code common to all T2 core logic chips.
10 */
11
12#define __EXTERN_INLINE
13#include <asm/io.h>
14#include <asm/core_t2.h>
15#undef __EXTERN_INLINE
16
17#include <linux/types.h>
18#include <linux/pci.h>
19#include <linux/sched.h>
20#include <linux/init.h>
21
22#include <asm/ptrace.h>
23#include <asm/delay.h>
24
25#include "proto.h"
26#include "pci_impl.h"
27
28/* For dumping initial DMA window settings. */
29#define DEBUG_PRINT_INITIAL_SETTINGS 0
30
31/* For dumping final DMA window settings. */
32#define DEBUG_PRINT_FINAL_SETTINGS 0
33
34/*
35 * By default, we direct-map starting at 2GB, in order to allow the
36 * maximum size direct-map window (2GB) to match the maximum amount of
37 * memory (2GB) that can be present on SABLEs. But that limits the
38 * floppy to DMA only via the scatter/gather window set up for 8MB
39 * ISA DMA, since the maximum ISA DMA address is 2GB-1.
40 *
41 * For now, this seems a reasonable trade-off: even though most SABLEs
42 * have less than 1GB of memory, floppy usage/performance will not
43 * really be affected by forcing it to go via scatter/gather...
44 */
45#define T2_DIRECTMAP_2G 1
46
47#if T2_DIRECTMAP_2G
48# define T2_DIRECTMAP_START 0x80000000UL
49# define T2_DIRECTMAP_LENGTH 0x80000000UL
50#else
51# define T2_DIRECTMAP_START 0x40000000UL
52# define T2_DIRECTMAP_LENGTH 0x40000000UL
53#endif
54
55/* The ISA scatter/gather window settings. */
56#define T2_ISA_SG_START 0x00800000UL
57#define T2_ISA_SG_LENGTH 0x00800000UL
58
59/*
60 * NOTE: Herein lie back-to-back mb instructions. They are magic.
61 * One plausible explanation is that the i/o controller does not properly
62 * handle the system transaction. Another involves timing. Ho hum.
63 */
64
65/*
66 * BIOS32-style PCI interface:
67 */
68
69#define DEBUG_CONFIG 0
70
71#if DEBUG_CONFIG
72# define DBG(args) printk args
73#else
74# define DBG(args)
75#endif
76
77static volatile unsigned int t2_mcheck_any_expected;
78static volatile unsigned int t2_mcheck_last_taken;
79
80/* Place to save the DMA Window registers as set up by SRM
81 for restoration during shutdown. */
82static struct
83{
84 struct {
85 unsigned long wbase;
86 unsigned long wmask;
87 unsigned long tbase;
88 } window[2];
89 unsigned long hae_1;
90 unsigned long hae_2;
91 unsigned long hae_3;
92 unsigned long hae_4;
93 unsigned long hbase;
94} t2_saved_config __attribute((common));
95
96/*
97 * Given a bus, device, and function number, compute resulting
98 * configuration space address and setup the T2_HAXR2 register
99 * accordingly. It is therefore not safe to have concurrent
100 * invocations to configuration space access routines, but there
101 * really shouldn't be any need for this.
102 *
103 * Type 0:
104 *
105 * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
106 * 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
107 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
108 * | | |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|
109 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
110 *
111 * 31:11 Device select bit.
112 * 10:8 Function number
113 * 7:2 Register number
114 *
115 * Type 1:
116 *
117 * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
118 * 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
119 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
120 * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
121 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
122 *
123 * 31:24 reserved
124 * 23:16 bus number (8 bits = 128 possible buses)
125 * 15:11 Device number (5 bits)
126 * 10:8 function number
127 * 7:2 register number
128 *
129 * Notes:
130 * The function number selects which function of a multi-function device
131 * (e.g., SCSI and Ethernet).
132 *
133 * The register selects a DWORD (32 bit) register offset. Hence it
134 * doesn't get shifted by 2 bits as we want to "drop" the bottom two
135 * bits.
136 */
137
138static int
139mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
140 unsigned long *pci_addr, unsigned char *type1)
141{
142 unsigned long addr;
143 u8 bus = pbus->number;
144
145 DBG(("mk_conf_addr(bus=%d, dfn=0x%x, where=0x%x,"
146 " addr=0x%lx, type1=0x%x)\n",
147 bus, device_fn, where, pci_addr, type1));
148
149 if (bus == 0) {
150 int device = device_fn >> 3;
151
152 /* Type 0 configuration cycle. */
153
154 if (device > 8) {
155 DBG(("mk_conf_addr: device (%d)>20, returning -1\n",
156 device));
157 return -1;
158 }
159
160 *type1 = 0;
161 addr = (0x0800L << device) | ((device_fn & 7) << 8) | (where);
162 } else {
163 /* Type 1 configuration cycle. */
164 *type1 = 1;
165 addr = (bus << 16) | (device_fn << 8) | (where);
166 }
167 *pci_addr = addr;
168 DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
169 return 0;
170}
171
172/*
173 * NOTE: both conf_read() and conf_write() may set HAE_3 when needing
174 * to do type1 access. This is protected by the use of spinlock IRQ
175 * primitives in the wrapper functions pci_{read,write}_config_*()
176 * defined in drivers/pci/pci.c.
177 */
178static unsigned int
179conf_read(unsigned long addr, unsigned char type1)
180{
181 unsigned int value, cpu, taken;
182 unsigned long t2_cfg = 0;
183
184 cpu = smp_processor_id();
185
186 DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
187
188 /* If Type1 access, must set T2 CFG. */
189 if (type1) {
190 t2_cfg = *(vulp)T2_HAE_3 & ~0xc0000000UL;
191 *(vulp)T2_HAE_3 = 0x40000000UL | t2_cfg;
192 mb();
193 }
194 mb();
195 draina();
196
197 mcheck_expected(cpu) = 1;
198 mcheck_taken(cpu) = 0;
199 t2_mcheck_any_expected |= (1 << cpu);
200 mb();
201
202 /* Access configuration space. */
203 value = *(vuip)addr;
204 mb();
205 mb(); /* magic */
206
207 /* Wait for possible mcheck. Also, this lets other CPUs clear
208 their mchecks as well, as they can reliably tell when
209 another CPU is in the midst of handling a real mcheck via
210 the "taken" function. */
211 udelay(100);
212
213 if ((taken = mcheck_taken(cpu))) {
214 mcheck_taken(cpu) = 0;
215 t2_mcheck_last_taken |= (1 << cpu);
216 value = 0xffffffffU;
217 mb();
218 }
219 mcheck_expected(cpu) = 0;
220 t2_mcheck_any_expected = 0;
221 mb();
222
223 /* If Type1 access, must reset T2 CFG so normal IO space ops work. */
224 if (type1) {
225 *(vulp)T2_HAE_3 = t2_cfg;
226 mb();
227 }
228
229 return value;
230}
231
232static void
233conf_write(unsigned long addr, unsigned int value, unsigned char type1)
234{
235 unsigned int cpu, taken;
236 unsigned long t2_cfg = 0;
237
238 cpu = smp_processor_id();
239
240 /* If Type1 access, must set T2 CFG. */
241 if (type1) {
242 t2_cfg = *(vulp)T2_HAE_3 & ~0xc0000000UL;
243 *(vulp)T2_HAE_3 = t2_cfg | 0x40000000UL;
244 mb();
245 }
246 mb();
247 draina();
248
249 mcheck_expected(cpu) = 1;
250 mcheck_taken(cpu) = 0;
251 t2_mcheck_any_expected |= (1 << cpu);
252 mb();
253
254 /* Access configuration space. */
255 *(vuip)addr = value;
256 mb();
257 mb(); /* magic */
258
259 /* Wait for possible mcheck. Also, this lets other CPUs clear
260 their mchecks as well, as they can reliably tell when
261 this CPU is in the midst of handling a real mcheck via
262 the "taken" function. */
263 udelay(100);
264
265 if ((taken = mcheck_taken(cpu))) {
266 mcheck_taken(cpu) = 0;
267 t2_mcheck_last_taken |= (1 << cpu);
268 mb();
269 }
270 mcheck_expected(cpu) = 0;
271 t2_mcheck_any_expected = 0;
272 mb();
273
274 /* If Type1 access, must reset T2 CFG so normal IO space ops work. */
275 if (type1) {
276 *(vulp)T2_HAE_3 = t2_cfg;
277 mb();
278 }
279}
280
281static int
282t2_read_config(struct pci_bus *bus, unsigned int devfn, int where,
283 int size, u32 *value)
284{
285 unsigned long addr, pci_addr;
286 unsigned char type1;
287 int shift;
288 long mask;
289
290 if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1))
291 return PCIBIOS_DEVICE_NOT_FOUND;
292
293 mask = (size - 1) * 8;
294 shift = (where & 3) * 8;
295 addr = (pci_addr << 5) + mask + T2_CONF;
296 *value = conf_read(addr, type1) >> (shift);
297 return PCIBIOS_SUCCESSFUL;
298}
299
300static int
301t2_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size,
302 u32 value)
303{
304 unsigned long addr, pci_addr;
305 unsigned char type1;
306 long mask;
307
308 if (mk_conf_addr(bus, devfn, where, &pci_addr, &type1))
309 return PCIBIOS_DEVICE_NOT_FOUND;
310
311 mask = (size - 1) * 8;
312 addr = (pci_addr << 5) + mask + T2_CONF;
313 conf_write(addr, value << ((where & 3) * 8), type1);
314 return PCIBIOS_SUCCESSFUL;
315}
316
317struct pci_ops t2_pci_ops =
318{
319 .read = t2_read_config,
320 .write = t2_write_config,
321};
322
323static void __init
324t2_direct_map_window1(unsigned long base, unsigned long length)
325{
326 unsigned long temp;
327
328 __direct_map_base = base;
329 __direct_map_size = length;
330
331 temp = (base & 0xfff00000UL) | ((base + length - 1) >> 20);
332 *(vulp)T2_WBASE1 = temp | 0x80000UL; /* OR in ENABLE bit */
333 temp = (length - 1) & 0xfff00000UL;
334 *(vulp)T2_WMASK1 = temp;
335 *(vulp)T2_TBASE1 = 0;
336
337#if DEBUG_PRINT_FINAL_SETTINGS
338 printk("%s: setting WBASE1=0x%lx WMASK1=0x%lx TBASE1=0x%lx\n",
339 __FUNCTION__,
340 *(vulp)T2_WBASE1,
341 *(vulp)T2_WMASK1,
342 *(vulp)T2_TBASE1);
343#endif
344}
345
346static void __init
347t2_sg_map_window2(struct pci_controller *hose,
348 unsigned long base,
349 unsigned long length)
350{
351 unsigned long temp;
352
353 /* Note we can only do 1 SG window, as the other is for direct, so
354 do an ISA SG area, especially for the floppy. */
355 hose->sg_isa = iommu_arena_new(hose, base, length, 0);
356 hose->sg_pci = NULL;
357
358 temp = (base & 0xfff00000UL) | ((base + length - 1) >> 20);
359 *(vulp)T2_WBASE2 = temp | 0xc0000UL; /* OR in ENABLE/SG bits */
360 temp = (length - 1) & 0xfff00000UL;
361 *(vulp)T2_WMASK2 = temp;
362 *(vulp)T2_TBASE2 = virt_to_phys(hose->sg_isa->ptes) >> 1;
363 mb();
364
365 t2_pci_tbi(hose, 0, -1); /* flush TLB all */
366
367#if DEBUG_PRINT_FINAL_SETTINGS
368 printk("%s: setting WBASE2=0x%lx WMASK2=0x%lx TBASE2=0x%lx\n",
369 __FUNCTION__,
370 *(vulp)T2_WBASE2,
371 *(vulp)T2_WMASK2,
372 *(vulp)T2_TBASE2);
373#endif
374}
375
376static void __init
377t2_save_configuration(void)
378{
379#if DEBUG_PRINT_INITIAL_SETTINGS
380 printk("%s: HAE_1 was 0x%lx\n", __FUNCTION__, srm_hae); /* HW is 0 */
381 printk("%s: HAE_2 was 0x%lx\n", __FUNCTION__, *(vulp)T2_HAE_2);
382 printk("%s: HAE_3 was 0x%lx\n", __FUNCTION__, *(vulp)T2_HAE_3);
383 printk("%s: HAE_4 was 0x%lx\n", __FUNCTION__, *(vulp)T2_HAE_4);
384 printk("%s: HBASE was 0x%lx\n", __FUNCTION__, *(vulp)T2_HBASE);
385
386 printk("%s: WBASE1=0x%lx WMASK1=0x%lx TBASE1=0x%lx\n", __FUNCTION__,
387 *(vulp)T2_WBASE1, *(vulp)T2_WMASK1, *(vulp)T2_TBASE1);
388 printk("%s: WBASE2=0x%lx WMASK2=0x%lx TBASE2=0x%lx\n", __FUNCTION__,
389 *(vulp)T2_WBASE2, *(vulp)T2_WMASK2, *(vulp)T2_TBASE2);
390#endif
391
392 /*
393 * Save the DMA Window registers.
394 */
395 t2_saved_config.window[0].wbase = *(vulp)T2_WBASE1;
396 t2_saved_config.window[0].wmask = *(vulp)T2_WMASK1;
397 t2_saved_config.window[0].tbase = *(vulp)T2_TBASE1;
398 t2_saved_config.window[1].wbase = *(vulp)T2_WBASE2;
399 t2_saved_config.window[1].wmask = *(vulp)T2_WMASK2;
400 t2_saved_config.window[1].tbase = *(vulp)T2_TBASE2;
401
402 t2_saved_config.hae_1 = srm_hae; /* HW is already set to 0 */
403 t2_saved_config.hae_2 = *(vulp)T2_HAE_2;
404 t2_saved_config.hae_3 = *(vulp)T2_HAE_3;
405 t2_saved_config.hae_4 = *(vulp)T2_HAE_4;
406 t2_saved_config.hbase = *(vulp)T2_HBASE;
407}
408
409void __init
410t2_init_arch(void)
411{
412 struct pci_controller *hose;
413 unsigned long temp;
414 unsigned int i;
415
416 for (i = 0; i < NR_CPUS; i++) {
417 mcheck_expected(i) = 0;
418 mcheck_taken(i) = 0;
419 }
420 t2_mcheck_any_expected = 0;
421 t2_mcheck_last_taken = 0;
422
423 /* Enable scatter/gather TLB use. */
424 temp = *(vulp)T2_IOCSR;
425 if (!(temp & (0x1UL << 26))) {
426 printk("t2_init_arch: enabling SG TLB, IOCSR was 0x%lx\n",
427 temp);
428 *(vulp)T2_IOCSR = temp | (0x1UL << 26);
429 mb();
430 *(vulp)T2_IOCSR; /* read it back to make sure */
431 }
432
433 t2_save_configuration();
434
435 /*
436 * Create our single hose.
437 */
438 pci_isa_hose = hose = alloc_pci_controller();
439 hose->io_space = &ioport_resource;
440 hose->mem_space = &iomem_resource;
441 hose->index = 0;
442
443 hose->sparse_mem_base = T2_SPARSE_MEM - IDENT_ADDR;
444 hose->dense_mem_base = T2_DENSE_MEM - IDENT_ADDR;
445 hose->sparse_io_base = T2_IO - IDENT_ADDR;
446 hose->dense_io_base = 0;
447
448 /*
449 * Set up the PCI->physical memory translation windows.
450 *
451 * Window 1 is direct mapped.
452 * Window 2 is scatter/gather (for ISA).
453 */
454
455 t2_direct_map_window1(T2_DIRECTMAP_START, T2_DIRECTMAP_LENGTH);
456
457 /* Always make an ISA DMA window. */
458 t2_sg_map_window2(hose, T2_ISA_SG_START, T2_ISA_SG_LENGTH);
459
460 *(vulp)T2_HBASE = 0x0; /* Disable HOLES. */
461
462 /* Zero HAE. */
463 *(vulp)T2_HAE_1 = 0; mb(); /* Sparse MEM HAE */
464 *(vulp)T2_HAE_2 = 0; mb(); /* Sparse I/O HAE */
465 *(vulp)T2_HAE_3 = 0; mb(); /* Config Space HAE */
466
467 /*
468 * We also now zero out HAE_4, the dense memory HAE, so that
469 * we need not account for its "offset" when accessing dense
470 * memory resources which we allocated in our normal way. This
471 * HAE would need to stay untouched were we to keep the SRM
472 * resource settings.
473 *
474 * Thus we can now run standard X servers on SABLE/LYNX. :-)
475 */
476 *(vulp)T2_HAE_4 = 0; mb();
477}
478
479void
480t2_kill_arch(int mode)
481{
482 /*
483 * Restore the DMA Window registers.
484 */
485 *(vulp)T2_WBASE1 = t2_saved_config.window[0].wbase;
486 *(vulp)T2_WMASK1 = t2_saved_config.window[0].wmask;
487 *(vulp)T2_TBASE1 = t2_saved_config.window[0].tbase;
488 *(vulp)T2_WBASE2 = t2_saved_config.window[1].wbase;
489 *(vulp)T2_WMASK2 = t2_saved_config.window[1].wmask;
490 *(vulp)T2_TBASE2 = t2_saved_config.window[1].tbase;
491 mb();
492
493 *(vulp)T2_HAE_1 = srm_hae;
494 *(vulp)T2_HAE_2 = t2_saved_config.hae_2;
495 *(vulp)T2_HAE_3 = t2_saved_config.hae_3;
496 *(vulp)T2_HAE_4 = t2_saved_config.hae_4;
497 *(vulp)T2_HBASE = t2_saved_config.hbase;
498 mb();
499 *(vulp)T2_HBASE; /* READ it back to ensure WRITE occurred. */
500}
501
502void
503t2_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
504{
505 unsigned long t2_iocsr;
506
507 t2_iocsr = *(vulp)T2_IOCSR;
508
509 /* set the TLB Clear bit */
510 *(vulp)T2_IOCSR = t2_iocsr | (0x1UL << 28);
511 mb();
512 *(vulp)T2_IOCSR; /* read it back to make sure */
513
514 /* clear the TLB Clear bit */
515 *(vulp)T2_IOCSR = t2_iocsr & ~(0x1UL << 28);
516 mb();
517 *(vulp)T2_IOCSR; /* read it back to make sure */
518}
519
520#define SIC_SEIC (1UL << 33) /* System Event Clear */
521
522static void
523t2_clear_errors(int cpu)
524{
525 struct sable_cpu_csr *cpu_regs;
526
527 cpu_regs = (struct sable_cpu_csr *)T2_CPUn_BASE(cpu);
528
529 cpu_regs->sic &= ~SIC_SEIC;
530
531 /* Clear CPU errors. */
532 cpu_regs->bcce |= cpu_regs->bcce;
533 cpu_regs->cbe |= cpu_regs->cbe;
534 cpu_regs->bcue |= cpu_regs->bcue;
535 cpu_regs->dter |= cpu_regs->dter;
536
537 *(vulp)T2_CERR1 |= *(vulp)T2_CERR1;
538 *(vulp)T2_PERR1 |= *(vulp)T2_PERR1;
539
540 mb();
541 mb(); /* magic */
542}
543
544/*
545 * SABLE seems to have a "broadcast" style machine check, in that all
546 * CPUs receive it. And, the issuing CPU, in the case of PCI Config
547 * space read/write faults, will also receive a second mcheck, upon
548 * lowering IPL during completion processing in pci_read_config_byte()
549 * et al.
550 *
551 * Hence all the taken/expected/any_expected/last_taken stuff...
552 */
553void
554t2_machine_check(unsigned long vector, unsigned long la_ptr,
555 struct pt_regs * regs)
556{
557 int cpu = smp_processor_id();
558#ifdef CONFIG_VERBOSE_MCHECK
559 struct el_common *mchk_header = (struct el_common *)la_ptr;
560#endif
561
562 /* Clear the error before any reporting. */
563 mb();
564 mb(); /* magic */
565 draina();
566 t2_clear_errors(cpu);
567
568 /* This should not actually be done until the logout frame is
569 examined, but, since we don't do that, go on and do this... */
570 wrmces(0x7);
571 mb();
572
573 /* Now, do testing for the anomalous conditions. */
574 if (!mcheck_expected(cpu) && t2_mcheck_any_expected) {
575 /*
576 * FUNKY: Received mcheck on a CPU and not
577 * expecting it, but another CPU is expecting one.
578 *
579 * Just dismiss it for now on this CPU...
580 */
581#ifdef CONFIG_VERBOSE_MCHECK
582 if (alpha_verbose_mcheck > 1) {
583 printk("t2_machine_check(cpu%d): any_expected 0x%x -"
584 " (assumed) spurious -"
585 " code 0x%x\n", cpu, t2_mcheck_any_expected,
586 (unsigned int)mchk_header->code);
587 }
588#endif
589 return;
590 }
591
592 if (!mcheck_expected(cpu) && !t2_mcheck_any_expected) {
593 if (t2_mcheck_last_taken & (1 << cpu)) {
594#ifdef CONFIG_VERBOSE_MCHECK
595 if (alpha_verbose_mcheck > 1) {
596 printk("t2_machine_check(cpu%d): last_taken 0x%x - "
597 "unexpected mcheck - code 0x%x\n",
598 cpu, t2_mcheck_last_taken,
599 (unsigned int)mchk_header->code);
600 }
601#endif
602 t2_mcheck_last_taken = 0;
603 mb();
604 return;
605 } else {
606 t2_mcheck_last_taken = 0;
607 mb();
608 }
609 }
610
611#ifdef CONFIG_VERBOSE_MCHECK
612 if (alpha_verbose_mcheck > 1) {
613 printk("%s t2_mcheck(cpu%d): last_taken 0x%x - "
614 "any_expected 0x%x - code 0x%x\n",
615 (mcheck_expected(cpu) ? "EX" : "UN"), cpu,
616 t2_mcheck_last_taken, t2_mcheck_any_expected,
617 (unsigned int)mchk_header->code);
618 }
619#endif
620
621 process_mcheck_info(vector, la_ptr, regs, "T2", mcheck_expected(cpu));
622}
diff --git a/arch/alpha/kernel/core_titan.c b/arch/alpha/kernel/core_titan.c
new file mode 100644
index 000000000000..3662fef7db9a
--- /dev/null
+++ b/arch/alpha/kernel/core_titan.c
@@ -0,0 +1,806 @@
1/*
2 * linux/arch/alpha/kernel/core_titan.c
3 *
4 * Code common to all TITAN core logic chips.
5 */
6
7#define __EXTERN_INLINE inline
8#include <asm/io.h>
9#include <asm/core_titan.h>
10#undef __EXTERN_INLINE
11
12#include <linux/module.h>
13#include <linux/types.h>
14#include <linux/pci.h>
15#include <linux/sched.h>
16#include <linux/init.h>
17#include <linux/vmalloc.h>
18#include <linux/bootmem.h>
19
20#include <asm/ptrace.h>
21#include <asm/smp.h>
22#include <asm/pgalloc.h>
23#include <asm/tlbflush.h>
24
25#include "proto.h"
26#include "pci_impl.h"
27
28/* Save Titan configuration data as the console had it set up. */
29
30struct
31{
32 unsigned long wsba[4];
33 unsigned long wsm[4];
34 unsigned long tba[4];
35} saved_config[4] __attribute__((common));
36
37/*
38 * BIOS32-style PCI interface:
39 */
40
41#define DEBUG_CONFIG 0
42
43#if DEBUG_CONFIG
44# define DBG_CFG(args) printk args
45#else
46# define DBG_CFG(args)
47#endif
48
49
50/*
51 * Routines to access TIG registers.
52 */
53static inline volatile unsigned long *
54mk_tig_addr(int offset)
55{
56 return (volatile unsigned long *)(TITAN_TIG_SPACE + (offset << 6));
57}
58
59static inline u8
60titan_read_tig(int offset, u8 value)
61{
62 volatile unsigned long *tig_addr = mk_tig_addr(offset);
63 return (u8)(*tig_addr & 0xff);
64}
65
66static inline void
67titan_write_tig(int offset, u8 value)
68{
69 volatile unsigned long *tig_addr = mk_tig_addr(offset);
70 *tig_addr = (unsigned long)value;
71}
72
73
74/*
75 * Given a bus, device, and function number, compute resulting
76 * configuration space address
77 * accordingly. It is therefore not safe to have concurrent
78 * invocations to configuration space access routines, but there
79 * really shouldn't be any need for this.
80 *
81 * Note that all config space accesses use Type 1 address format.
82 *
83 * Note also that type 1 is determined by non-zero bus number.
84 *
85 * Type 1:
86 *
87 * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
88 * 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
89 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
90 * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
91 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
92 *
93 * 31:24 reserved
94 * 23:16 bus number (8 bits = 128 possible buses)
95 * 15:11 Device number (5 bits)
96 * 10:8 function number
97 * 7:2 register number
98 *
99 * Notes:
100 * The function number selects which function of a multi-function device
101 * (e.g., SCSI and Ethernet).
102 *
103 * The register selects a DWORD (32 bit) register offset. Hence it
104 * doesn't get shifted by 2 bits as we want to "drop" the bottom two
105 * bits.
106 */
107
108static int
109mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
110 unsigned long *pci_addr, unsigned char *type1)
111{
112 struct pci_controller *hose = pbus->sysdata;
113 unsigned long addr;
114 u8 bus = pbus->number;
115
116 DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, "
117 "pci_addr=0x%p, type1=0x%p)\n",
118 bus, device_fn, where, pci_addr, type1));
119
120 if (!pbus->parent) /* No parent means peer PCI bus. */
121 bus = 0;
122 *type1 = (bus != 0);
123
124 addr = (bus << 16) | (device_fn << 8) | where;
125 addr |= hose->config_space_base;
126
127 *pci_addr = addr;
128 DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
129 return 0;
130}
131
132static int
133titan_read_config(struct pci_bus *bus, unsigned int devfn, int where,
134 int size, u32 *value)
135{
136 unsigned long addr;
137 unsigned char type1;
138
139 if (mk_conf_addr(bus, devfn, where, &addr, &type1))
140 return PCIBIOS_DEVICE_NOT_FOUND;
141
142 switch (size) {
143 case 1:
144 *value = __kernel_ldbu(*(vucp)addr);
145 break;
146 case 2:
147 *value = __kernel_ldwu(*(vusp)addr);
148 break;
149 case 4:
150 *value = *(vuip)addr;
151 break;
152 }
153
154 return PCIBIOS_SUCCESSFUL;
155}
156
157static int
158titan_write_config(struct pci_bus *bus, unsigned int devfn, int where,
159 int size, u32 value)
160{
161 unsigned long addr;
162 unsigned char type1;
163
164 if (mk_conf_addr(bus, devfn, where, &addr, &type1))
165 return PCIBIOS_DEVICE_NOT_FOUND;
166
167 switch (size) {
168 case 1:
169 __kernel_stb(value, *(vucp)addr);
170 mb();
171 __kernel_ldbu(*(vucp)addr);
172 break;
173 case 2:
174 __kernel_stw(value, *(vusp)addr);
175 mb();
176 __kernel_ldwu(*(vusp)addr);
177 break;
178 case 4:
179 *(vuip)addr = value;
180 mb();
181 *(vuip)addr;
182 break;
183 }
184
185 return PCIBIOS_SUCCESSFUL;
186}
187
188struct pci_ops titan_pci_ops =
189{
190 .read = titan_read_config,
191 .write = titan_write_config,
192};
193
194
195void
196titan_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
197{
198 titan_pachip *pachip =
199 (hose->index & 1) ? TITAN_pachip1 : TITAN_pachip0;
200 titan_pachip_port *port;
201 volatile unsigned long *csr;
202 unsigned long value;
203
204 /* Get the right hose. */
205 port = &pachip->g_port;
206 if (hose->index & 2)
207 port = &pachip->a_port;
208
209 /* We can invalidate up to 8 tlb entries in a go. The flush
210 matches against <31:16> in the pci address.
211 Note that gtlbi* and atlbi* are in the same place in the g_port
212 and a_port, respectively, so the g_port offset can be used
213 even if hose is an a_port */
214 csr = &port->port_specific.g.gtlbia.csr;
215 if (((start ^ end) & 0xffff0000) == 0)
216 csr = &port->port_specific.g.gtlbiv.csr;
217
218 /* For TBIA, it doesn't matter what value we write. For TBI,
219 it's the shifted tag bits. */
220 value = (start & 0xffff0000) >> 12;
221
222 wmb();
223 *csr = value;
224 mb();
225 *csr;
226}
227
228static int
229titan_query_agp(titan_pachip_port *port)
230{
231 union TPAchipPCTL pctl;
232
233 /* set up APCTL */
234 pctl.pctl_q_whole = port->pctl.csr;
235
236 return pctl.pctl_r_bits.apctl_v_agp_present;
237
238}
239
240static void __init
241titan_init_one_pachip_port(titan_pachip_port *port, int index)
242{
243 struct pci_controller *hose;
244
245 hose = alloc_pci_controller();
246 if (index == 0)
247 pci_isa_hose = hose;
248 hose->io_space = alloc_resource();
249 hose->mem_space = alloc_resource();
250
251 /*
252 * This is for userland consumption. The 40-bit PIO bias that we
253 * use in the kernel through KSEG doesn't work in the page table
254 * based user mappings. (43-bit KSEG sign extends the physical
255 * address from bit 40 to hit the I/O bit - mapped addresses don't).
256 * So make sure we get the 43-bit PIO bias.
257 */
258 hose->sparse_mem_base = 0;
259 hose->sparse_io_base = 0;
260 hose->dense_mem_base
261 = (TITAN_MEM(index) & 0xffffffffffUL) | 0x80000000000UL;
262 hose->dense_io_base
263 = (TITAN_IO(index) & 0xffffffffffUL) | 0x80000000000UL;
264
265 hose->config_space_base = TITAN_CONF(index);
266 hose->index = index;
267
268 hose->io_space->start = TITAN_IO(index) - TITAN_IO_BIAS;
269 hose->io_space->end = hose->io_space->start + TITAN_IO_SPACE - 1;
270 hose->io_space->name = pci_io_names[index];
271 hose->io_space->flags = IORESOURCE_IO;
272
273 hose->mem_space->start = TITAN_MEM(index) - TITAN_MEM_BIAS;
274 hose->mem_space->end = hose->mem_space->start + 0xffffffff;
275 hose->mem_space->name = pci_mem_names[index];
276 hose->mem_space->flags = IORESOURCE_MEM;
277
278 if (request_resource(&ioport_resource, hose->io_space) < 0)
279 printk(KERN_ERR "Failed to request IO on hose %d\n", index);
280 if (request_resource(&iomem_resource, hose->mem_space) < 0)
281 printk(KERN_ERR "Failed to request MEM on hose %d\n", index);
282
283 /*
284 * Save the existing PCI window translations. SRM will
285 * need them when we go to reboot.
286 */
287 saved_config[index].wsba[0] = port->wsba[0].csr;
288 saved_config[index].wsm[0] = port->wsm[0].csr;
289 saved_config[index].tba[0] = port->tba[0].csr;
290
291 saved_config[index].wsba[1] = port->wsba[1].csr;
292 saved_config[index].wsm[1] = port->wsm[1].csr;
293 saved_config[index].tba[1] = port->tba[1].csr;
294
295 saved_config[index].wsba[2] = port->wsba[2].csr;
296 saved_config[index].wsm[2] = port->wsm[2].csr;
297 saved_config[index].tba[2] = port->tba[2].csr;
298
299 saved_config[index].wsba[3] = port->wsba[3].csr;
300 saved_config[index].wsm[3] = port->wsm[3].csr;
301 saved_config[index].tba[3] = port->tba[3].csr;
302
303 /*
304 * Set up the PCI to main memory translation windows.
305 *
306 * Note: Window 3 on Titan is Scatter-Gather ONLY.
307 *
308 * Window 0 is scatter-gather 8MB at 8MB (for isa)
309 * Window 1 is direct access 1GB at 2GB
310 * Window 2 is scatter-gather 1GB at 3GB
311 */
312 hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
313 hose->sg_isa->align_entry = 8; /* 64KB for ISA */
314
315 hose->sg_pci = iommu_arena_new(hose, 0xc0000000, 0x40000000, 0);
316 hose->sg_pci->align_entry = 4; /* Titan caches 4 PTEs at a time */
317
318 port->wsba[0].csr = hose->sg_isa->dma_base | 3;
319 port->wsm[0].csr = (hose->sg_isa->size - 1) & 0xfff00000;
320 port->tba[0].csr = virt_to_phys(hose->sg_isa->ptes);
321
322 port->wsba[1].csr = __direct_map_base | 1;
323 port->wsm[1].csr = (__direct_map_size - 1) & 0xfff00000;
324 port->tba[1].csr = 0;
325
326 port->wsba[2].csr = hose->sg_pci->dma_base | 3;
327 port->wsm[2].csr = (hose->sg_pci->size - 1) & 0xfff00000;
328 port->tba[2].csr = virt_to_phys(hose->sg_pci->ptes);
329
330 port->wsba[3].csr = 0;
331
332 /* Enable the Monster Window to make DAC pci64 possible. */
333 port->pctl.csr |= pctl_m_mwin;
334
335 /*
336 * If it's an AGP port, initialize agplastwr.
337 */
338 if (titan_query_agp(port))
339 port->port_specific.a.agplastwr.csr = __direct_map_base;
340
341 titan_pci_tbi(hose, 0, -1);
342}
343
344static void __init
345titan_init_pachips(titan_pachip *pachip0, titan_pachip *pachip1)
346{
347 int pchip1_present = TITAN_cchip->csc.csr & 1L<<14;
348
349 /* Init the ports in hose order... */
350 titan_init_one_pachip_port(&pachip0->g_port, 0); /* hose 0 */
351 if (pchip1_present)
352 titan_init_one_pachip_port(&pachip1->g_port, 1);/* hose 1 */
353 titan_init_one_pachip_port(&pachip0->a_port, 2); /* hose 2 */
354 if (pchip1_present)
355 titan_init_one_pachip_port(&pachip1->a_port, 3);/* hose 3 */
356}
357
358static void __init
359titan_init_vga_hose(void)
360{
361#ifdef CONFIG_VGA_HOSE
362 u64 *pu64 = (u64 *)((u64)hwrpb + hwrpb->ctbt_offset);
363
364 if (pu64[7] == 3) { /* TERM_TYPE == graphics */
365 struct pci_controller *hose;
366 int h = (pu64[30] >> 24) & 0xff; /* console hose # */
367
368 /*
369 * Our hose numbering matches the console's, so just find
370 * the right one...
371 */
372 for (hose = hose_head; hose; hose = hose->next) {
373 if (hose->index == h) break;
374 }
375
376 if (hose) {
377 printk("Console graphics on hose %d\n", hose->index);
378 pci_vga_hose = hose;
379 }
380 }
381#endif /* CONFIG_VGA_HOSE */
382}
383
384void __init
385titan_init_arch(void)
386{
387#if 0
388 printk("%s: titan_init_arch()\n", __FUNCTION__);
389 printk("%s: CChip registers:\n", __FUNCTION__);
390 printk("%s: CSR_CSC 0x%lx\n", __FUNCTION__, TITAN_cchip->csc.csr);
391 printk("%s: CSR_MTR 0x%lx\n", __FUNCTION__, TITAN_cchip->mtr.csr);
392 printk("%s: CSR_MISC 0x%lx\n", __FUNCTION__, TITAN_cchip->misc.csr);
393 printk("%s: CSR_DIM0 0x%lx\n", __FUNCTION__, TITAN_cchip->dim0.csr);
394 printk("%s: CSR_DIM1 0x%lx\n", __FUNCTION__, TITAN_cchip->dim1.csr);
395 printk("%s: CSR_DIR0 0x%lx\n", __FUNCTION__, TITAN_cchip->dir0.csr);
396 printk("%s: CSR_DIR1 0x%lx\n", __FUNCTION__, TITAN_cchip->dir1.csr);
397 printk("%s: CSR_DRIR 0x%lx\n", __FUNCTION__, TITAN_cchip->drir.csr);
398
399 printk("%s: DChip registers:\n", __FUNCTION__);
400 printk("%s: CSR_DSC 0x%lx\n", __FUNCTION__, TITAN_dchip->dsc.csr);
401 printk("%s: CSR_STR 0x%lx\n", __FUNCTION__, TITAN_dchip->str.csr);
402 printk("%s: CSR_DREV 0x%lx\n", __FUNCTION__, TITAN_dchip->drev.csr);
403#endif
404
405 boot_cpuid = __hard_smp_processor_id();
406
407 /* With multiple PCI busses, we play with I/O as physical addrs. */
408 ioport_resource.end = ~0UL;
409
410 /* PCI DMA Direct Mapping is 1GB at 2GB. */
411 __direct_map_base = 0x80000000;
412 __direct_map_size = 0x40000000;
413
414 /* Init the PA chip(s). */
415 titan_init_pachips(TITAN_pachip0, TITAN_pachip1);
416
417 /* Check for graphic console location (if any). */
418 titan_init_vga_hose();
419}
420
421static void
422titan_kill_one_pachip_port(titan_pachip_port *port, int index)
423{
424 port->wsba[0].csr = saved_config[index].wsba[0];
425 port->wsm[0].csr = saved_config[index].wsm[0];
426 port->tba[0].csr = saved_config[index].tba[0];
427
428 port->wsba[1].csr = saved_config[index].wsba[1];
429 port->wsm[1].csr = saved_config[index].wsm[1];
430 port->tba[1].csr = saved_config[index].tba[1];
431
432 port->wsba[2].csr = saved_config[index].wsba[2];
433 port->wsm[2].csr = saved_config[index].wsm[2];
434 port->tba[2].csr = saved_config[index].tba[2];
435
436 port->wsba[3].csr = saved_config[index].wsba[3];
437 port->wsm[3].csr = saved_config[index].wsm[3];
438 port->tba[3].csr = saved_config[index].tba[3];
439}
440
441static void
442titan_kill_pachips(titan_pachip *pachip0, titan_pachip *pachip1)
443{
444 int pchip1_present = TITAN_cchip->csc.csr & 1L<<14;
445
446 if (pchip1_present) {
447 titan_kill_one_pachip_port(&pachip1->g_port, 1);
448 titan_kill_one_pachip_port(&pachip1->a_port, 3);
449 }
450 titan_kill_one_pachip_port(&pachip0->g_port, 0);
451 titan_kill_one_pachip_port(&pachip0->a_port, 2);
452}
453
454void
455titan_kill_arch(int mode)
456{
457 titan_kill_pachips(TITAN_pachip0, TITAN_pachip1);
458}
459
460
461/*
462 * IO map support.
463 */
464
465void __iomem *
466titan_ioremap(unsigned long addr, unsigned long size)
467{
468 int h = (addr & TITAN_HOSE_MASK) >> TITAN_HOSE_SHIFT;
469 unsigned long baddr = addr & ~TITAN_HOSE_MASK;
470 unsigned long last = baddr + size - 1;
471 struct pci_controller *hose;
472 struct vm_struct *area;
473 unsigned long vaddr;
474 unsigned long *ptes;
475 unsigned long pfn;
476
477 /*
478 * Adjust the addr.
479 */
480#ifdef CONFIG_VGA_HOSE
481 if (pci_vga_hose && __titan_is_mem_vga(addr)) {
482 h = pci_vga_hose->index;
483 addr += pci_vga_hose->mem_space->start;
484 }
485#endif
486
487 /*
488 * Find the hose.
489 */
490 for (hose = hose_head; hose; hose = hose->next)
491 if (hose->index == h)
492 break;
493 if (!hose)
494 return NULL;
495
496 /*
497 * Is it direct-mapped?
498 */
499 if ((baddr >= __direct_map_base) &&
500 ((baddr + size - 1) < __direct_map_base + __direct_map_size)) {
501 vaddr = addr - __direct_map_base + TITAN_MEM_BIAS;
502 return (void __iomem *) vaddr;
503 }
504
505 /*
506 * Check the scatter-gather arena.
507 */
508 if (hose->sg_pci &&
509 baddr >= (unsigned long)hose->sg_pci->dma_base &&
510 last < (unsigned long)hose->sg_pci->dma_base + hose->sg_pci->size){
511
512 /*
513 * Adjust the limits (mappings must be page aligned)
514 */
515 baddr -= hose->sg_pci->dma_base;
516 last -= hose->sg_pci->dma_base;
517 baddr &= PAGE_MASK;
518 size = PAGE_ALIGN(last) - baddr;
519
520 /*
521 * Map it
522 */
523 area = get_vm_area(size, VM_IOREMAP);
524 if (!area)
525 return NULL;
526
527 ptes = hose->sg_pci->ptes;
528 for (vaddr = (unsigned long)area->addr;
529 baddr <= last;
530 baddr += PAGE_SIZE, vaddr += PAGE_SIZE) {
531 pfn = ptes[baddr >> PAGE_SHIFT];
532 if (!(pfn & 1)) {
533 printk("ioremap failed... pte not valid...\n");
534 vfree(area->addr);
535 return NULL;
536 }
537 pfn >>= 1; /* make it a true pfn */
538
539 if (__alpha_remap_area_pages(vaddr,
540 pfn << PAGE_SHIFT,
541 PAGE_SIZE, 0)) {
542 printk("FAILED to map...\n");
543 vfree(area->addr);
544 return NULL;
545 }
546 }
547
548 flush_tlb_all();
549
550 vaddr = (unsigned long)area->addr + (addr & ~PAGE_MASK);
551 return (void __iomem *) vaddr;
552 }
553
554 return NULL;
555}
556
557void
558titan_iounmap(volatile void __iomem *xaddr)
559{
560 unsigned long addr = (unsigned long) xaddr;
561 if (addr >= VMALLOC_START)
562 vfree((void *)(PAGE_MASK & addr));
563}
564
565int
566titan_is_mmio(const volatile void __iomem *xaddr)
567{
568 unsigned long addr = (unsigned long) xaddr;
569
570 if (addr >= VMALLOC_START)
571 return 1;
572 else
573 return (addr & 0x100000000UL) == 0;
574}
575
576#ifndef CONFIG_ALPHA_GENERIC
577EXPORT_SYMBOL(titan_ioremap);
578EXPORT_SYMBOL(titan_iounmap);
579EXPORT_SYMBOL(titan_is_mmio);
580#endif
581
582/*
583 * AGP GART Support.
584 */
585#include <linux/agp_backend.h>
586#include <asm/agp_backend.h>
587#include <linux/slab.h>
588#include <linux/delay.h>
589
590struct titan_agp_aperture {
591 struct pci_iommu_arena *arena;
592 long pg_start;
593 long pg_count;
594};
595
596static int
597titan_agp_setup(alpha_agp_info *agp)
598{
599 struct titan_agp_aperture *aper;
600
601 if (!alpha_agpgart_size)
602 return -ENOMEM;
603
604 aper = kmalloc(sizeof(struct titan_agp_aperture), GFP_KERNEL);
605 if (aper == NULL)
606 return -ENOMEM;
607
608 aper->arena = agp->hose->sg_pci;
609 aper->pg_count = alpha_agpgart_size / PAGE_SIZE;
610 aper->pg_start = iommu_reserve(aper->arena, aper->pg_count,
611 aper->pg_count - 1);
612 if (aper->pg_start < 0) {
613 printk(KERN_ERR "Failed to reserve AGP memory\n");
614 kfree(aper);
615 return -ENOMEM;
616 }
617
618 agp->aperture.bus_base =
619 aper->arena->dma_base + aper->pg_start * PAGE_SIZE;
620 agp->aperture.size = aper->pg_count * PAGE_SIZE;
621 agp->aperture.sysdata = aper;
622
623 return 0;
624}
625
626static void
627titan_agp_cleanup(alpha_agp_info *agp)
628{
629 struct titan_agp_aperture *aper = agp->aperture.sysdata;
630 int status;
631
632 status = iommu_release(aper->arena, aper->pg_start, aper->pg_count);
633 if (status == -EBUSY) {
634 printk(KERN_WARNING
635 "Attempted to release bound AGP memory - unbinding\n");
636 iommu_unbind(aper->arena, aper->pg_start, aper->pg_count);
637 status = iommu_release(aper->arena, aper->pg_start,
638 aper->pg_count);
639 }
640 if (status < 0)
641 printk(KERN_ERR "Failed to release AGP memory\n");
642
643 kfree(aper);
644 kfree(agp);
645}
646
647static int
648titan_agp_configure(alpha_agp_info *agp)
649{
650 union TPAchipPCTL pctl;
651 titan_pachip_port *port = agp->private;
652 pctl.pctl_q_whole = port->pctl.csr;
653
654 /* Side-Band Addressing? */
655 pctl.pctl_r_bits.apctl_v_agp_sba_en = agp->mode.bits.sba;
656
657 /* AGP Rate? */
658 pctl.pctl_r_bits.apctl_v_agp_rate = 0; /* 1x */
659 if (agp->mode.bits.rate & 2)
660 pctl.pctl_r_bits.apctl_v_agp_rate = 1; /* 2x */
661#if 0
662 if (agp->mode.bits.rate & 4)
663 pctl.pctl_r_bits.apctl_v_agp_rate = 2; /* 4x */
664#endif
665
666 /* RQ Depth? */
667 pctl.pctl_r_bits.apctl_v_agp_hp_rd = 2;
668 pctl.pctl_r_bits.apctl_v_agp_lp_rd = 7;
669
670 /*
671 * AGP Enable.
672 */
673 pctl.pctl_r_bits.apctl_v_agp_en = agp->mode.bits.enable;
674
675 /* Tell the user. */
676 printk("Enabling AGP: %dX%s\n",
677 1 << pctl.pctl_r_bits.apctl_v_agp_rate,
678 pctl.pctl_r_bits.apctl_v_agp_sba_en ? " - SBA" : "");
679
680 /* Write it. */
681 port->pctl.csr = pctl.pctl_q_whole;
682
683 /* And wait at least 5000 66MHz cycles (per Titan spec). */
684 udelay(100);
685
686 return 0;
687}
688
689static int
690titan_agp_bind_memory(alpha_agp_info *agp, off_t pg_start, struct agp_memory *mem)
691{
692 struct titan_agp_aperture *aper = agp->aperture.sysdata;
693 return iommu_bind(aper->arena, aper->pg_start + pg_start,
694 mem->page_count, mem->memory);
695}
696
697static int
698titan_agp_unbind_memory(alpha_agp_info *agp, off_t pg_start, struct agp_memory *mem)
699{
700 struct titan_agp_aperture *aper = agp->aperture.sysdata;
701 return iommu_unbind(aper->arena, aper->pg_start + pg_start,
702 mem->page_count);
703}
704
705static unsigned long
706titan_agp_translate(alpha_agp_info *agp, dma_addr_t addr)
707{
708 struct titan_agp_aperture *aper = agp->aperture.sysdata;
709 unsigned long baddr = addr - aper->arena->dma_base;
710 unsigned long pte;
711
712 if (addr < agp->aperture.bus_base ||
713 addr >= agp->aperture.bus_base + agp->aperture.size) {
714 printk("%s: addr out of range\n", __FUNCTION__);
715 return -EINVAL;
716 }
717
718 pte = aper->arena->ptes[baddr >> PAGE_SHIFT];
719 if (!(pte & 1)) {
720 printk("%s: pte not valid\n", __FUNCTION__);
721 return -EINVAL;
722 }
723
724 return (pte >> 1) << PAGE_SHIFT;
725}
726
727struct alpha_agp_ops titan_agp_ops =
728{
729 .setup = titan_agp_setup,
730 .cleanup = titan_agp_cleanup,
731 .configure = titan_agp_configure,
732 .bind = titan_agp_bind_memory,
733 .unbind = titan_agp_unbind_memory,
734 .translate = titan_agp_translate
735};
736
737alpha_agp_info *
738titan_agp_info(void)
739{
740 alpha_agp_info *agp;
741 struct pci_controller *hose;
742 titan_pachip_port *port;
743 int hosenum = -1;
744 union TPAchipPCTL pctl;
745
746 /*
747 * Find the AGP port.
748 */
749 port = &TITAN_pachip0->a_port;
750 if (titan_query_agp(port))
751 hosenum = 2;
752 if (hosenum < 0 &&
753 titan_query_agp(port = &TITAN_pachip1->a_port))
754 hosenum = 3;
755
756 /*
757 * Find the hose the port is on.
758 */
759 for (hose = hose_head; hose; hose = hose->next)
760 if (hose->index == hosenum)
761 break;
762
763 if (!hose || !hose->sg_pci)
764 return NULL;
765
766 /*
767 * Allocate the info structure.
768 */
769 agp = kmalloc(sizeof(*agp), GFP_KERNEL);
770
771 /*
772 * Fill it in.
773 */
774 agp->hose = hose;
775 agp->private = port;
776 agp->ops = &titan_agp_ops;
777
778 /*
779 * Aperture - not configured until ops.setup().
780 *
781 * FIXME - should we go ahead and allocate it here?
782 */
783 agp->aperture.bus_base = 0;
784 agp->aperture.size = 0;
785 agp->aperture.sysdata = NULL;
786
787 /*
788 * Capabilities.
789 */
790 agp->capability.lw = 0;
791 agp->capability.bits.rate = 3; /* 2x, 1x */
792 agp->capability.bits.sba = 1;
793 agp->capability.bits.rq = 7; /* 8 - 1 */
794
795 /*
796 * Mode.
797 */
798 pctl.pctl_q_whole = port->pctl.csr;
799 agp->mode.lw = 0;
800 agp->mode.bits.rate = 1 << pctl.pctl_r_bits.apctl_v_agp_rate;
801 agp->mode.bits.sba = pctl.pctl_r_bits.apctl_v_agp_sba_en;
802 agp->mode.bits.rq = 7; /* RQ Depth? */
803 agp->mode.bits.enable = pctl.pctl_r_bits.apctl_v_agp_en;
804
805 return agp;
806}
diff --git a/arch/alpha/kernel/core_tsunami.c b/arch/alpha/kernel/core_tsunami.c
new file mode 100644
index 000000000000..8aa305bd6a2c
--- /dev/null
+++ b/arch/alpha/kernel/core_tsunami.c
@@ -0,0 +1,459 @@
1/*
2 * linux/arch/alpha/kernel/core_tsunami.c
3 *
4 * Based on code written by David A. Rusling (david.rusling@reo.mts.dec.com).
5 *
6 * Code common to all TSUNAMI core logic chips.
7 */
8
9#define __EXTERN_INLINE inline
10#include <asm/io.h>
11#include <asm/core_tsunami.h>
12#undef __EXTERN_INLINE
13
14#include <linux/types.h>
15#include <linux/pci.h>
16#include <linux/sched.h>
17#include <linux/init.h>
18#include <linux/bootmem.h>
19
20#include <asm/ptrace.h>
21#include <asm/smp.h>
22
23#include "proto.h"
24#include "pci_impl.h"
25
26/* Save Tsunami configuration data as the console had it set up. */
27
28struct
29{
30 unsigned long wsba[4];
31 unsigned long wsm[4];
32 unsigned long tba[4];
33} saved_config[2] __attribute__((common));
34
35/*
36 * NOTE: Herein lie back-to-back mb instructions. They are magic.
37 * One plausible explanation is that the I/O controller does not properly
38 * handle the system transaction. Another involves timing. Ho hum.
39 */
40
41/*
42 * BIOS32-style PCI interface:
43 */
44
45#define DEBUG_CONFIG 0
46
47#if DEBUG_CONFIG
48# define DBG_CFG(args) printk args
49#else
50# define DBG_CFG(args)
51#endif
52
53
54/*
55 * Given a bus, device, and function number, compute resulting
56 * configuration space address
57 * accordingly. It is therefore not safe to have concurrent
58 * invocations to configuration space access routines, but there
59 * really shouldn't be any need for this.
60 *
61 * Note that all config space accesses use Type 1 address format.
62 *
63 * Note also that type 1 is determined by non-zero bus number.
64 *
65 * Type 1:
66 *
67 * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
68 * 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
69 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
70 * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
71 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
72 *
73 * 31:24 reserved
74 * 23:16 bus number (8 bits = 128 possible buses)
75 * 15:11 Device number (5 bits)
76 * 10:8 function number
77 * 7:2 register number
78 *
79 * Notes:
80 * The function number selects which function of a multi-function device
81 * (e.g., SCSI and Ethernet).
82 *
83 * The register selects a DWORD (32 bit) register offset. Hence it
84 * doesn't get shifted by 2 bits as we want to "drop" the bottom two
85 * bits.
86 */
87
88static int
89mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
90 unsigned long *pci_addr, unsigned char *type1)
91{
92 struct pci_controller *hose = pbus->sysdata;
93 unsigned long addr;
94 u8 bus = pbus->number;
95
96 DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, "
97 "pci_addr=0x%p, type1=0x%p)\n",
98 bus, device_fn, where, pci_addr, type1));
99
100 if (!pbus->parent) /* No parent means peer PCI bus. */
101 bus = 0;
102 *type1 = (bus != 0);
103
104 addr = (bus << 16) | (device_fn << 8) | where;
105 addr |= hose->config_space_base;
106
107 *pci_addr = addr;
108 DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
109 return 0;
110}
111
112static int
113tsunami_read_config(struct pci_bus *bus, unsigned int devfn, int where,
114 int size, u32 *value)
115{
116 unsigned long addr;
117 unsigned char type1;
118
119 if (mk_conf_addr(bus, devfn, where, &addr, &type1))
120 return PCIBIOS_DEVICE_NOT_FOUND;
121
122 switch (size) {
123 case 1:
124 *value = __kernel_ldbu(*(vucp)addr);
125 break;
126 case 2:
127 *value = __kernel_ldwu(*(vusp)addr);
128 break;
129 case 4:
130 *value = *(vuip)addr;
131 break;
132 }
133
134 return PCIBIOS_SUCCESSFUL;
135}
136
137static int
138tsunami_write_config(struct pci_bus *bus, unsigned int devfn, int where,
139 int size, u32 value)
140{
141 unsigned long addr;
142 unsigned char type1;
143
144 if (mk_conf_addr(bus, devfn, where, &addr, &type1))
145 return PCIBIOS_DEVICE_NOT_FOUND;
146
147 switch (size) {
148 case 1:
149 __kernel_stb(value, *(vucp)addr);
150 mb();
151 __kernel_ldbu(*(vucp)addr);
152 break;
153 case 2:
154 __kernel_stw(value, *(vusp)addr);
155 mb();
156 __kernel_ldwu(*(vusp)addr);
157 break;
158 case 4:
159 *(vuip)addr = value;
160 mb();
161 *(vuip)addr;
162 break;
163 }
164
165 return PCIBIOS_SUCCESSFUL;
166}
167
168struct pci_ops tsunami_pci_ops =
169{
170 .read = tsunami_read_config,
171 .write = tsunami_write_config,
172};
173
174void
175tsunami_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
176{
177 tsunami_pchip *pchip = hose->index ? TSUNAMI_pchip1 : TSUNAMI_pchip0;
178 volatile unsigned long *csr;
179 unsigned long value;
180
181 /* We can invalidate up to 8 tlb entries in a go. The flush
182 matches against <31:16> in the pci address. */
183 csr = &pchip->tlbia.csr;
184 if (((start ^ end) & 0xffff0000) == 0)
185 csr = &pchip->tlbiv.csr;
186
187 /* For TBIA, it doesn't matter what value we write. For TBI,
188 it's the shifted tag bits. */
189 value = (start & 0xffff0000) >> 12;
190
191 *csr = value;
192 mb();
193 *csr;
194}
195
196#ifdef NXM_MACHINE_CHECKS_ON_TSUNAMI
197static long __init
198tsunami_probe_read(volatile unsigned long *vaddr)
199{
200 long dont_care, probe_result;
201 int cpu = smp_processor_id();
202 int s = swpipl(IPL_MCHECK - 1);
203
204 mcheck_taken(cpu) = 0;
205 mcheck_expected(cpu) = 1;
206 mb();
207 dont_care = *vaddr;
208 draina();
209 mcheck_expected(cpu) = 0;
210 probe_result = !mcheck_taken(cpu);
211 mcheck_taken(cpu) = 0;
212 setipl(s);
213
214 printk("dont_care == 0x%lx\n", dont_care);
215
216 return probe_result;
217}
218
219static long __init
220tsunami_probe_write(volatile unsigned long *vaddr)
221{
222 long true_contents, probe_result = 1;
223
224 TSUNAMI_cchip->misc.csr |= (1L << 28); /* clear NXM... */
225 true_contents = *vaddr;
226 *vaddr = 0;
227 draina();
228 if (TSUNAMI_cchip->misc.csr & (1L << 28)) {
229 int source = (TSUNAMI_cchip->misc.csr >> 29) & 7;
230 TSUNAMI_cchip->misc.csr |= (1L << 28); /* ...and unlock NXS. */
231 probe_result = 0;
232 printk("tsunami_probe_write: unit %d at 0x%016lx\n", source,
233 (unsigned long)vaddr);
234 }
235 if (probe_result)
236 *vaddr = true_contents;
237 return probe_result;
238}
239#else
240#define tsunami_probe_read(ADDR) 1
241#endif /* NXM_MACHINE_CHECKS_ON_TSUNAMI */
242
243#define FN __FUNCTION__
244
245static void __init
246tsunami_init_one_pchip(tsunami_pchip *pchip, int index)
247{
248 struct pci_controller *hose;
249
250 if (tsunami_probe_read(&pchip->pctl.csr) == 0)
251 return;
252
253 hose = alloc_pci_controller();
254 if (index == 0)
255 pci_isa_hose = hose;
256 hose->io_space = alloc_resource();
257 hose->mem_space = alloc_resource();
258
259 /* This is for userland consumption. For some reason, the 40-bit
260 PIO bias that we use in the kernel through KSEG didn't work for
261 the page table based user mappings. So make sure we get the
262 43-bit PIO bias. */
263 hose->sparse_mem_base = 0;
264 hose->sparse_io_base = 0;
265 hose->dense_mem_base
266 = (TSUNAMI_MEM(index) & 0xffffffffffL) | 0x80000000000L;
267 hose->dense_io_base
268 = (TSUNAMI_IO(index) & 0xffffffffffL) | 0x80000000000L;
269
270 hose->config_space_base = TSUNAMI_CONF(index);
271 hose->index = index;
272
273 hose->io_space->start = TSUNAMI_IO(index) - TSUNAMI_IO_BIAS;
274 hose->io_space->end = hose->io_space->start + TSUNAMI_IO_SPACE - 1;
275 hose->io_space->name = pci_io_names[index];
276 hose->io_space->flags = IORESOURCE_IO;
277
278 hose->mem_space->start = TSUNAMI_MEM(index) - TSUNAMI_MEM_BIAS;
279 hose->mem_space->end = hose->mem_space->start + 0xffffffff;
280 hose->mem_space->name = pci_mem_names[index];
281 hose->mem_space->flags = IORESOURCE_MEM;
282
283 if (request_resource(&ioport_resource, hose->io_space) < 0)
284 printk(KERN_ERR "Failed to request IO on hose %d\n", index);
285 if (request_resource(&iomem_resource, hose->mem_space) < 0)
286 printk(KERN_ERR "Failed to request MEM on hose %d\n", index);
287
288 /*
289 * Save the existing PCI window translations. SRM will
290 * need them when we go to reboot.
291 */
292
293 saved_config[index].wsba[0] = pchip->wsba[0].csr;
294 saved_config[index].wsm[0] = pchip->wsm[0].csr;
295 saved_config[index].tba[0] = pchip->tba[0].csr;
296
297 saved_config[index].wsba[1] = pchip->wsba[1].csr;
298 saved_config[index].wsm[1] = pchip->wsm[1].csr;
299 saved_config[index].tba[1] = pchip->tba[1].csr;
300
301 saved_config[index].wsba[2] = pchip->wsba[2].csr;
302 saved_config[index].wsm[2] = pchip->wsm[2].csr;
303 saved_config[index].tba[2] = pchip->tba[2].csr;
304
305 saved_config[index].wsba[3] = pchip->wsba[3].csr;
306 saved_config[index].wsm[3] = pchip->wsm[3].csr;
307 saved_config[index].tba[3] = pchip->tba[3].csr;
308
309 /*
310 * Set up the PCI to main memory translation windows.
311 *
312 * Note: Window 3 is scatter-gather only
313 *
314 * Window 0 is scatter-gather 8MB at 8MB (for isa)
315 * Window 1 is scatter-gather (up to) 1GB at 1GB
316 * Window 2 is direct access 2GB at 2GB
317 *
318 * NOTE: we need the align_entry settings for Acer devices on ES40,
319 * specifically floppy and IDE when memory is larger than 2GB.
320 */
321 hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
322 /* Initially set for 4 PTEs, but will be overridden to 64K for ISA. */
323 hose->sg_isa->align_entry = 4;
324
325 hose->sg_pci = iommu_arena_new(hose, 0x40000000,
326 size_for_memory(0x40000000), 0);
327 hose->sg_pci->align_entry = 4; /* Tsunami caches 4 PTEs at a time */
328
329 __direct_map_base = 0x80000000;
330 __direct_map_size = 0x80000000;
331
332 pchip->wsba[0].csr = hose->sg_isa->dma_base | 3;
333 pchip->wsm[0].csr = (hose->sg_isa->size - 1) & 0xfff00000;
334 pchip->tba[0].csr = virt_to_phys(hose->sg_isa->ptes);
335
336 pchip->wsba[1].csr = hose->sg_pci->dma_base | 3;
337 pchip->wsm[1].csr = (hose->sg_pci->size - 1) & 0xfff00000;
338 pchip->tba[1].csr = virt_to_phys(hose->sg_pci->ptes);
339
340 pchip->wsba[2].csr = 0x80000000 | 1;
341 pchip->wsm[2].csr = (0x80000000 - 1) & 0xfff00000;
342 pchip->tba[2].csr = 0;
343
344 pchip->wsba[3].csr = 0;
345
346 /* Enable the Monster Window to make DAC pci64 possible. */
347 pchip->pctl.csr |= pctl_m_mwin;
348
349 tsunami_pci_tbi(hose, 0, -1);
350}
351
352void __init
353tsunami_init_arch(void)
354{
355#ifdef NXM_MACHINE_CHECKS_ON_TSUNAMI
356 unsigned long tmp;
357
358 /* Ho hum.. init_arch is called before init_IRQ, but we need to be
359 able to handle machine checks. So install the handler now. */
360 wrent(entInt, 0);
361
362 /* NXMs just don't matter to Tsunami--unless they make it
363 choke completely. */
364 tmp = (unsigned long)(TSUNAMI_cchip - 1);
365 printk("%s: probing bogus address: 0x%016lx\n", FN, bogus_addr);
366 printk("\tprobe %s\n",
367 tsunami_probe_write((unsigned long *)bogus_addr)
368 ? "succeeded" : "failed");
369#endif /* NXM_MACHINE_CHECKS_ON_TSUNAMI */
370
371#if 0
372 printk("%s: CChip registers:\n", FN);
373 printk("%s: CSR_CSC 0x%lx\n", FN, TSUNAMI_cchip->csc.csr);
374 printk("%s: CSR_MTR 0x%lx\n", FN, TSUNAMI_cchip.mtr.csr);
375 printk("%s: CSR_MISC 0x%lx\n", FN, TSUNAMI_cchip->misc.csr);
376 printk("%s: CSR_DIM0 0x%lx\n", FN, TSUNAMI_cchip->dim0.csr);
377 printk("%s: CSR_DIM1 0x%lx\n", FN, TSUNAMI_cchip->dim1.csr);
378 printk("%s: CSR_DIR0 0x%lx\n", FN, TSUNAMI_cchip->dir0.csr);
379 printk("%s: CSR_DIR1 0x%lx\n", FN, TSUNAMI_cchip->dir1.csr);
380 printk("%s: CSR_DRIR 0x%lx\n", FN, TSUNAMI_cchip->drir.csr);
381
382 printk("%s: DChip registers:\n");
383 printk("%s: CSR_DSC 0x%lx\n", FN, TSUNAMI_dchip->dsc.csr);
384 printk("%s: CSR_STR 0x%lx\n", FN, TSUNAMI_dchip->str.csr);
385 printk("%s: CSR_DREV 0x%lx\n", FN, TSUNAMI_dchip->drev.csr);
386#endif
387 /* With multiple PCI busses, we play with I/O as physical addrs. */
388 ioport_resource.end = ~0UL;
389
390 /* Find how many hoses we have, and initialize them. TSUNAMI
391 and TYPHOON can have 2, but might only have 1 (DS10). */
392
393 tsunami_init_one_pchip(TSUNAMI_pchip0, 0);
394 if (TSUNAMI_cchip->csc.csr & 1L<<14)
395 tsunami_init_one_pchip(TSUNAMI_pchip1, 1);
396}
397
398static void
399tsunami_kill_one_pchip(tsunami_pchip *pchip, int index)
400{
401 pchip->wsba[0].csr = saved_config[index].wsba[0];
402 pchip->wsm[0].csr = saved_config[index].wsm[0];
403 pchip->tba[0].csr = saved_config[index].tba[0];
404
405 pchip->wsba[1].csr = saved_config[index].wsba[1];
406 pchip->wsm[1].csr = saved_config[index].wsm[1];
407 pchip->tba[1].csr = saved_config[index].tba[1];
408
409 pchip->wsba[2].csr = saved_config[index].wsba[2];
410 pchip->wsm[2].csr = saved_config[index].wsm[2];
411 pchip->tba[2].csr = saved_config[index].tba[2];
412
413 pchip->wsba[3].csr = saved_config[index].wsba[3];
414 pchip->wsm[3].csr = saved_config[index].wsm[3];
415 pchip->tba[3].csr = saved_config[index].tba[3];
416}
417
418void
419tsunami_kill_arch(int mode)
420{
421 tsunami_kill_one_pchip(TSUNAMI_pchip0, 0);
422 if (TSUNAMI_cchip->csc.csr & 1L<<14)
423 tsunami_kill_one_pchip(TSUNAMI_pchip1, 1);
424}
425
426static inline void
427tsunami_pci_clr_err_1(tsunami_pchip *pchip)
428{
429 pchip->perror.csr;
430 pchip->perror.csr = 0x040;
431 mb();
432 pchip->perror.csr;
433}
434
435static inline void
436tsunami_pci_clr_err(void)
437{
438 tsunami_pci_clr_err_1(TSUNAMI_pchip0);
439
440 /* TSUNAMI and TYPHOON can have 2, but might only have 1 (DS10) */
441 if (TSUNAMI_cchip->csc.csr & 1L<<14)
442 tsunami_pci_clr_err_1(TSUNAMI_pchip1);
443}
444
445void
446tsunami_machine_check(unsigned long vector, unsigned long la_ptr,
447 struct pt_regs * regs)
448{
449 /* Clear error before any reporting. */
450 mb();
451 mb(); /* magic */
452 draina();
453 tsunami_pci_clr_err();
454 wrmces(0x7);
455 mb();
456
457 process_mcheck_info(vector, la_ptr, regs, "TSUNAMI",
458 mcheck_expected(smp_processor_id()));
459}
diff --git a/arch/alpha/kernel/core_wildfire.c b/arch/alpha/kernel/core_wildfire.c
new file mode 100644
index 000000000000..2b767a1bad96
--- /dev/null
+++ b/arch/alpha/kernel/core_wildfire.c
@@ -0,0 +1,658 @@
1/*
2 * linux/arch/alpha/kernel/core_wildfire.c
3 *
4 * Wildfire support.
5 *
6 * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
7 */
8
9#define __EXTERN_INLINE inline
10#include <asm/io.h>
11#include <asm/core_wildfire.h>
12#undef __EXTERN_INLINE
13
14#include <linux/types.h>
15#include <linux/pci.h>
16#include <linux/sched.h>
17#include <linux/init.h>
18
19#include <asm/ptrace.h>
20#include <asm/smp.h>
21
22#include "proto.h"
23#include "pci_impl.h"
24
25#define DEBUG_CONFIG 0
26#define DEBUG_DUMP_REGS 0
27#define DEBUG_DUMP_CONFIG 1
28
29#if DEBUG_CONFIG
30# define DBG_CFG(args) printk args
31#else
32# define DBG_CFG(args)
33#endif
34
35#if DEBUG_DUMP_REGS
36static void wildfire_dump_pci_regs(int qbbno, int hoseno);
37static void wildfire_dump_pca_regs(int qbbno, int pcano);
38static void wildfire_dump_qsa_regs(int qbbno);
39static void wildfire_dump_qsd_regs(int qbbno);
40static void wildfire_dump_iop_regs(int qbbno);
41static void wildfire_dump_gp_regs(int qbbno);
42#endif
43#if DEBUG_DUMP_CONFIG
44static void wildfire_dump_hardware_config(void);
45#endif
46
47unsigned char wildfire_hard_qbb_map[WILDFIRE_MAX_QBB];
48unsigned char wildfire_soft_qbb_map[WILDFIRE_MAX_QBB];
49#define QBB_MAP_EMPTY 0xff
50
51unsigned long wildfire_hard_qbb_mask;
52unsigned long wildfire_soft_qbb_mask;
53unsigned long wildfire_gp_mask;
54unsigned long wildfire_hs_mask;
55unsigned long wildfire_iop_mask;
56unsigned long wildfire_ior_mask;
57unsigned long wildfire_pca_mask;
58unsigned long wildfire_cpu_mask;
59unsigned long wildfire_mem_mask;
60
61void __init
62wildfire_init_hose(int qbbno, int hoseno)
63{
64 struct pci_controller *hose;
65 wildfire_pci *pci;
66
67 hose = alloc_pci_controller();
68 hose->io_space = alloc_resource();
69 hose->mem_space = alloc_resource();
70
71 /* This is for userland consumption. */
72 hose->sparse_mem_base = 0;
73 hose->sparse_io_base = 0;
74 hose->dense_mem_base = WILDFIRE_MEM(qbbno, hoseno);
75 hose->dense_io_base = WILDFIRE_IO(qbbno, hoseno);
76
77 hose->config_space_base = WILDFIRE_CONF(qbbno, hoseno);
78 hose->index = (qbbno << 3) + hoseno;
79
80 hose->io_space->start = WILDFIRE_IO(qbbno, hoseno) - WILDFIRE_IO_BIAS;
81 hose->io_space->end = hose->io_space->start + WILDFIRE_IO_SPACE - 1;
82 hose->io_space->name = pci_io_names[hoseno];
83 hose->io_space->flags = IORESOURCE_IO;
84
85 hose->mem_space->start = WILDFIRE_MEM(qbbno, hoseno)-WILDFIRE_MEM_BIAS;
86 hose->mem_space->end = hose->mem_space->start + 0xffffffff;
87 hose->mem_space->name = pci_mem_names[hoseno];
88 hose->mem_space->flags = IORESOURCE_MEM;
89
90 if (request_resource(&ioport_resource, hose->io_space) < 0)
91 printk(KERN_ERR "Failed to request IO on qbb %d hose %d\n",
92 qbbno, hoseno);
93 if (request_resource(&iomem_resource, hose->mem_space) < 0)
94 printk(KERN_ERR "Failed to request MEM on qbb %d hose %d\n",
95 qbbno, hoseno);
96
97#if DEBUG_DUMP_REGS
98 wildfire_dump_pci_regs(qbbno, hoseno);
99#endif
100
101 /*
102 * Set up the PCI to main memory translation windows.
103 *
104 * Note: Window 3 is scatter-gather only
105 *
106 * Window 0 is scatter-gather 8MB at 8MB (for isa)
107 * Window 1 is direct access 1GB at 1GB
108 * Window 2 is direct access 1GB at 2GB
109 * Window 3 is scatter-gather 128MB at 3GB
110 * ??? We ought to scale window 3 memory.
111 *
112 */
113 hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000, 0);
114 hose->sg_pci = iommu_arena_new(hose, 0xc0000000, 0x08000000, 0);
115
116 pci = WILDFIRE_pci(qbbno, hoseno);
117
118 pci->pci_window[0].wbase.csr = hose->sg_isa->dma_base | 3;
119 pci->pci_window[0].wmask.csr = (hose->sg_isa->size - 1) & 0xfff00000;
120 pci->pci_window[0].tbase.csr = virt_to_phys(hose->sg_isa->ptes);
121
122 pci->pci_window[1].wbase.csr = 0x40000000 | 1;
123 pci->pci_window[1].wmask.csr = (0x40000000 -1) & 0xfff00000;
124 pci->pci_window[1].tbase.csr = 0;
125
126 pci->pci_window[2].wbase.csr = 0x80000000 | 1;
127 pci->pci_window[2].wmask.csr = (0x40000000 -1) & 0xfff00000;
128 pci->pci_window[2].tbase.csr = 0x40000000;
129
130 pci->pci_window[3].wbase.csr = hose->sg_pci->dma_base | 3;
131 pci->pci_window[3].wmask.csr = (hose->sg_pci->size - 1) & 0xfff00000;
132 pci->pci_window[3].tbase.csr = virt_to_phys(hose->sg_pci->ptes);
133
134 wildfire_pci_tbi(hose, 0, 0); /* Flush TLB at the end. */
135}
136
137void __init
138wildfire_init_pca(int qbbno, int pcano)
139{
140
141 /* Test for PCA existence first. */
142 if (!WILDFIRE_PCA_EXISTS(qbbno, pcano))
143 return;
144
145#if DEBUG_DUMP_REGS
146 wildfire_dump_pca_regs(qbbno, pcano);
147#endif
148
149 /* Do both hoses of the PCA. */
150 wildfire_init_hose(qbbno, (pcano << 1) + 0);
151 wildfire_init_hose(qbbno, (pcano << 1) + 1);
152}
153
154void __init
155wildfire_init_qbb(int qbbno)
156{
157 int pcano;
158
159 /* Test for QBB existence first. */
160 if (!WILDFIRE_QBB_EXISTS(qbbno))
161 return;
162
163#if DEBUG_DUMP_REGS
164 wildfire_dump_qsa_regs(qbbno);
165 wildfire_dump_qsd_regs(qbbno);
166 wildfire_dump_iop_regs(qbbno);
167 wildfire_dump_gp_regs(qbbno);
168#endif
169
170 /* Init all PCAs here. */
171 for (pcano = 0; pcano < WILDFIRE_PCA_PER_QBB; pcano++) {
172 wildfire_init_pca(qbbno, pcano);
173 }
174}
175
176void __init
177wildfire_hardware_probe(void)
178{
179 unsigned long temp;
180 unsigned int hard_qbb, soft_qbb;
181 wildfire_fast_qsd *fast = WILDFIRE_fast_qsd();
182 wildfire_qsd *qsd;
183 wildfire_qsa *qsa;
184 wildfire_iop *iop;
185 wildfire_gp *gp;
186 wildfire_ne *ne;
187 wildfire_fe *fe;
188 int i;
189
190 temp = fast->qsd_whami.csr;
191#if 0
192 printk(KERN_ERR "fast QSD_WHAMI at base %p is 0x%lx\n", fast, temp);
193#endif
194
195 hard_qbb = (temp >> 8) & 7;
196 soft_qbb = (temp >> 4) & 7;
197
198 /* Init the HW configuration variables. */
199 wildfire_hard_qbb_mask = (1 << hard_qbb);
200 wildfire_soft_qbb_mask = (1 << soft_qbb);
201
202 wildfire_gp_mask = 0;
203 wildfire_hs_mask = 0;
204 wildfire_iop_mask = 0;
205 wildfire_ior_mask = 0;
206 wildfire_pca_mask = 0;
207
208 wildfire_cpu_mask = 0;
209 wildfire_mem_mask = 0;
210
211 memset(wildfire_hard_qbb_map, QBB_MAP_EMPTY, WILDFIRE_MAX_QBB);
212 memset(wildfire_soft_qbb_map, QBB_MAP_EMPTY, WILDFIRE_MAX_QBB);
213
214 /* First, determine which QBBs are present. */
215 qsa = WILDFIRE_qsa(soft_qbb);
216
217 temp = qsa->qsa_qbb_id.csr;
218#if 0
219 printk(KERN_ERR "QSA_QBB_ID at base %p is 0x%lx\n", qsa, temp);
220#endif
221
222 if (temp & 0x40) /* Is there an HS? */
223 wildfire_hs_mask = 1;
224
225 if (temp & 0x20) { /* Is there a GP? */
226 gp = WILDFIRE_gp(soft_qbb);
227 temp = 0;
228 for (i = 0; i < 4; i++) {
229 temp |= gp->gpa_qbb_map[i].csr << (i * 8);
230#if 0
231 printk(KERN_ERR "GPA_QBB_MAP[%d] at base %p is 0x%lx\n",
232 i, gp, temp);
233#endif
234 }
235
236 for (hard_qbb = 0; hard_qbb < WILDFIRE_MAX_QBB; hard_qbb++) {
237 if (temp & 8) { /* Is there a QBB? */
238 soft_qbb = temp & 7;
239 wildfire_hard_qbb_mask |= (1 << hard_qbb);
240 wildfire_soft_qbb_mask |= (1 << soft_qbb);
241 }
242 temp >>= 4;
243 }
244 wildfire_gp_mask = wildfire_soft_qbb_mask;
245 }
246
247 /* Next determine each QBBs resources. */
248 for (soft_qbb = 0; soft_qbb < WILDFIRE_MAX_QBB; soft_qbb++) {
249 if (WILDFIRE_QBB_EXISTS(soft_qbb)) {
250 qsd = WILDFIRE_qsd(soft_qbb);
251 temp = qsd->qsd_whami.csr;
252#if 0
253 printk(KERN_ERR "QSD_WHAMI at base %p is 0x%lx\n", qsd, temp);
254#endif
255 hard_qbb = (temp >> 8) & 7;
256 wildfire_hard_qbb_map[hard_qbb] = soft_qbb;
257 wildfire_soft_qbb_map[soft_qbb] = hard_qbb;
258
259 qsa = WILDFIRE_qsa(soft_qbb);
260 temp = qsa->qsa_qbb_pop[0].csr;
261#if 0
262 printk(KERN_ERR "QSA_QBB_POP_0 at base %p is 0x%lx\n", qsa, temp);
263#endif
264 wildfire_cpu_mask |= ((temp >> 0) & 0xf) << (soft_qbb << 2);
265 wildfire_mem_mask |= ((temp >> 4) & 0xf) << (soft_qbb << 2);
266
267 temp = qsa->qsa_qbb_pop[1].csr;
268#if 0
269 printk(KERN_ERR "QSA_QBB_POP_1 at base %p is 0x%lx\n", qsa, temp);
270#endif
271 wildfire_iop_mask |= (1 << soft_qbb);
272 wildfire_ior_mask |= ((temp >> 4) & 0xf) << (soft_qbb << 2);
273
274 temp = qsa->qsa_qbb_id.csr;
275#if 0
276 printk(KERN_ERR "QSA_QBB_ID at %p is 0x%lx\n", qsa, temp);
277#endif
278 if (temp & 0x20)
279 wildfire_gp_mask |= (1 << soft_qbb);
280
281 /* Probe for PCA existence here. */
282 for (i = 0; i < WILDFIRE_PCA_PER_QBB; i++) {
283 iop = WILDFIRE_iop(soft_qbb);
284 ne = WILDFIRE_ne(soft_qbb, i);
285 fe = WILDFIRE_fe(soft_qbb, i);
286
287 if ((iop->iop_hose[i].init.csr & 1) == 1 &&
288 ((ne->ne_what_am_i.csr & 0xf00000300UL) == 0x100000300UL) &&
289 ((fe->fe_what_am_i.csr & 0xf00000300UL) == 0x100000200UL))
290 {
291 wildfire_pca_mask |= 1 << ((soft_qbb << 2) + i);
292 }
293 }
294
295 }
296 }
297#if DEBUG_DUMP_CONFIG
298 wildfire_dump_hardware_config();
299#endif
300}
301
302void __init
303wildfire_init_arch(void)
304{
305 int qbbno;
306
307 /* With multiple PCI buses, we play with I/O as physical addrs. */
308 ioport_resource.end = ~0UL;
309
310
311 /* Probe the hardware for info about configuration. */
312 wildfire_hardware_probe();
313
314 /* Now init all the found QBBs. */
315 for (qbbno = 0; qbbno < WILDFIRE_MAX_QBB; qbbno++) {
316 wildfire_init_qbb(qbbno);
317 }
318
319 /* Normal direct PCI DMA mapping. */
320 __direct_map_base = 0x40000000UL;
321 __direct_map_size = 0x80000000UL;
322}
323
324void
325wildfire_machine_check(unsigned long vector, unsigned long la_ptr,
326 struct pt_regs * regs)
327{
328 mb();
329 mb(); /* magic */
330 draina();
331 /* FIXME: clear pci errors */
332 wrmces(0x7);
333 mb();
334
335 process_mcheck_info(vector, la_ptr, regs, "WILDFIRE",
336 mcheck_expected(smp_processor_id()));
337}
338
339void
340wildfire_kill_arch(int mode)
341{
342}
343
344void
345wildfire_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
346{
347 int qbbno = hose->index >> 3;
348 int hoseno = hose->index & 7;
349 wildfire_pci *pci = WILDFIRE_pci(qbbno, hoseno);
350
351 mb();
352 pci->pci_flush_tlb.csr; /* reading does the trick */
353}
354
355static int
356mk_conf_addr(struct pci_bus *pbus, unsigned int device_fn, int where,
357 unsigned long *pci_addr, unsigned char *type1)
358{
359 struct pci_controller *hose = pbus->sysdata;
360 unsigned long addr;
361 u8 bus = pbus->number;
362
363 DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, "
364 "pci_addr=0x%p, type1=0x%p)\n",
365 bus, device_fn, where, pci_addr, type1));
366
367 if (!pbus->parent) /* No parent means peer PCI bus. */
368 bus = 0;
369 *type1 = (bus != 0);
370
371 addr = (bus << 16) | (device_fn << 8) | where;
372 addr |= hose->config_space_base;
373
374 *pci_addr = addr;
375 DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
376 return 0;
377}
378
379static int
380wildfire_read_config(struct pci_bus *bus, unsigned int devfn, int where,
381 int size, u32 *value)
382{
383 unsigned long addr;
384 unsigned char type1;
385
386 if (mk_conf_addr(bus, devfn, where, &addr, &type1))
387 return PCIBIOS_DEVICE_NOT_FOUND;
388
389 switch (size) {
390 case 1:
391 *value = __kernel_ldbu(*(vucp)addr);
392 break;
393 case 2:
394 *value = __kernel_ldwu(*(vusp)addr);
395 break;
396 case 4:
397 *value = *(vuip)addr;
398 break;
399 }
400
401 return PCIBIOS_SUCCESSFUL;
402}
403
404static int
405wildfire_write_config(struct pci_bus *bus, unsigned int devfn, int where,
406 int size, u32 value)
407{
408 unsigned long addr;
409 unsigned char type1;
410
411 if (mk_conf_addr(bus, devfn, where, &addr, &type1))
412 return PCIBIOS_DEVICE_NOT_FOUND;
413
414 switch (size) {
415 case 1:
416 __kernel_stb(value, *(vucp)addr);
417 mb();
418 __kernel_ldbu(*(vucp)addr);
419 break;
420 case 2:
421 __kernel_stw(value, *(vusp)addr);
422 mb();
423 __kernel_ldwu(*(vusp)addr);
424 break;
425 case 4:
426 *(vuip)addr = value;
427 mb();
428 *(vuip)addr;
429 break;
430 }
431
432 return PCIBIOS_SUCCESSFUL;
433}
434
435struct pci_ops wildfire_pci_ops =
436{
437 .read = wildfire_read_config,
438 .write = wildfire_write_config,
439};
440
441
442/*
443 * NUMA Support
444 */
445int wildfire_pa_to_nid(unsigned long pa)
446{
447 return pa >> 36;
448}
449
450int wildfire_cpuid_to_nid(int cpuid)
451{
452 /* assume 4 CPUs per node */
453 return cpuid >> 2;
454}
455
456unsigned long wildfire_node_mem_start(int nid)
457{
458 /* 64GB per node */
459 return (unsigned long)nid * (64UL * 1024 * 1024 * 1024);
460}
461
462unsigned long wildfire_node_mem_size(int nid)
463{
464 /* 64GB per node */
465 return 64UL * 1024 * 1024 * 1024;
466}
467
468#if DEBUG_DUMP_REGS
469
470static void __init
471wildfire_dump_pci_regs(int qbbno, int hoseno)
472{
473 wildfire_pci *pci = WILDFIRE_pci(qbbno, hoseno);
474 int i;
475
476 printk(KERN_ERR "PCI registers for QBB %d hose %d (%p)\n",
477 qbbno, hoseno, pci);
478
479 printk(KERN_ERR " PCI_IO_ADDR_EXT: 0x%16lx\n",
480 pci->pci_io_addr_ext.csr);
481 printk(KERN_ERR " PCI_CTRL: 0x%16lx\n", pci->pci_ctrl.csr);
482 printk(KERN_ERR " PCI_ERR_SUM: 0x%16lx\n", pci->pci_err_sum.csr);
483 printk(KERN_ERR " PCI_ERR_ADDR: 0x%16lx\n", pci->pci_err_addr.csr);
484 printk(KERN_ERR " PCI_STALL_CNT: 0x%16lx\n", pci->pci_stall_cnt.csr);
485 printk(KERN_ERR " PCI_PEND_INT: 0x%16lx\n", pci->pci_pend_int.csr);
486 printk(KERN_ERR " PCI_SENT_INT: 0x%16lx\n", pci->pci_sent_int.csr);
487
488 printk(KERN_ERR " DMA window registers for QBB %d hose %d (%p)\n",
489 qbbno, hoseno, pci);
490 for (i = 0; i < 4; i++) {
491 printk(KERN_ERR " window %d: 0x%16lx 0x%16lx 0x%16lx\n", i,
492 pci->pci_window[i].wbase.csr,
493 pci->pci_window[i].wmask.csr,
494 pci->pci_window[i].tbase.csr);
495 }
496 printk(KERN_ERR "\n");
497}
498
499static void __init
500wildfire_dump_pca_regs(int qbbno, int pcano)
501{
502 wildfire_pca *pca = WILDFIRE_pca(qbbno, pcano);
503 int i;
504
505 printk(KERN_ERR "PCA registers for QBB %d PCA %d (%p)\n",
506 qbbno, pcano, pca);
507
508 printk(KERN_ERR " PCA_WHAT_AM_I: 0x%16lx\n", pca->pca_what_am_i.csr);
509 printk(KERN_ERR " PCA_ERR_SUM: 0x%16lx\n", pca->pca_err_sum.csr);
510 printk(KERN_ERR " PCA_PEND_INT: 0x%16lx\n", pca->pca_pend_int.csr);
511 printk(KERN_ERR " PCA_SENT_INT: 0x%16lx\n", pca->pca_sent_int.csr);
512 printk(KERN_ERR " PCA_STDIO_EL: 0x%16lx\n",
513 pca->pca_stdio_edge_level.csr);
514
515 printk(KERN_ERR " PCA target registers for QBB %d PCA %d (%p)\n",
516 qbbno, pcano, pca);
517 for (i = 0; i < 4; i++) {
518 printk(KERN_ERR " target %d: 0x%16lx 0x%16lx\n", i,
519 pca->pca_int[i].target.csr,
520 pca->pca_int[i].enable.csr);
521 }
522
523 printk(KERN_ERR "\n");
524}
525
526static void __init
527wildfire_dump_qsa_regs(int qbbno)
528{
529 wildfire_qsa *qsa = WILDFIRE_qsa(qbbno);
530 int i;
531
532 printk(KERN_ERR "QSA registers for QBB %d (%p)\n", qbbno, qsa);
533
534 printk(KERN_ERR " QSA_QBB_ID: 0x%16lx\n", qsa->qsa_qbb_id.csr);
535 printk(KERN_ERR " QSA_PORT_ENA: 0x%16lx\n", qsa->qsa_port_ena.csr);
536 printk(KERN_ERR " QSA_REF_INT: 0x%16lx\n", qsa->qsa_ref_int.csr);
537
538 for (i = 0; i < 5; i++)
539 printk(KERN_ERR " QSA_CONFIG_%d: 0x%16lx\n",
540 i, qsa->qsa_config[i].csr);
541
542 for (i = 0; i < 2; i++)
543 printk(KERN_ERR " QSA_QBB_POP_%d: 0x%16lx\n",
544 i, qsa->qsa_qbb_pop[0].csr);
545
546 printk(KERN_ERR "\n");
547}
548
549static void __init
550wildfire_dump_qsd_regs(int qbbno)
551{
552 wildfire_qsd *qsd = WILDFIRE_qsd(qbbno);
553
554 printk(KERN_ERR "QSD registers for QBB %d (%p)\n", qbbno, qsd);
555
556 printk(KERN_ERR " QSD_WHAMI: 0x%16lx\n", qsd->qsd_whami.csr);
557 printk(KERN_ERR " QSD_REV: 0x%16lx\n", qsd->qsd_rev.csr);
558 printk(KERN_ERR " QSD_PORT_PRESENT: 0x%16lx\n",
559 qsd->qsd_port_present.csr);
560 printk(KERN_ERR " QSD_PORT_ACTUVE: 0x%16lx\n",
561 qsd->qsd_port_active.csr);
562 printk(KERN_ERR " QSD_FAULT_ENA: 0x%16lx\n",
563 qsd->qsd_fault_ena.csr);
564 printk(KERN_ERR " QSD_CPU_INT_ENA: 0x%16lx\n",
565 qsd->qsd_cpu_int_ena.csr);
566 printk(KERN_ERR " QSD_MEM_CONFIG: 0x%16lx\n",
567 qsd->qsd_mem_config.csr);
568 printk(KERN_ERR " QSD_ERR_SUM: 0x%16lx\n",
569 qsd->qsd_err_sum.csr);
570
571 printk(KERN_ERR "\n");
572}
573
574static void __init
575wildfire_dump_iop_regs(int qbbno)
576{
577 wildfire_iop *iop = WILDFIRE_iop(qbbno);
578 int i;
579
580 printk(KERN_ERR "IOP registers for QBB %d (%p)\n", qbbno, iop);
581
582 printk(KERN_ERR " IOA_CONFIG: 0x%16lx\n", iop->ioa_config.csr);
583 printk(KERN_ERR " IOD_CONFIG: 0x%16lx\n", iop->iod_config.csr);
584 printk(KERN_ERR " IOP_SWITCH_CREDITS: 0x%16lx\n",
585 iop->iop_switch_credits.csr);
586 printk(KERN_ERR " IOP_HOSE_CREDITS: 0x%16lx\n",
587 iop->iop_hose_credits.csr);
588
589 for (i = 0; i < 4; i++)
590 printk(KERN_ERR " IOP_HOSE_%d_INIT: 0x%16lx\n",
591 i, iop->iop_hose[i].init.csr);
592 for (i = 0; i < 4; i++)
593 printk(KERN_ERR " IOP_DEV_INT_TARGET_%d: 0x%16lx\n",
594 i, iop->iop_dev_int[i].target.csr);
595
596 printk(KERN_ERR "\n");
597}
598
599static void __init
600wildfire_dump_gp_regs(int qbbno)
601{
602 wildfire_gp *gp = WILDFIRE_gp(qbbno);
603 int i;
604
605 printk(KERN_ERR "GP registers for QBB %d (%p)\n", qbbno, gp);
606 for (i = 0; i < 4; i++)
607 printk(KERN_ERR " GPA_QBB_MAP_%d: 0x%16lx\n",
608 i, gp->gpa_qbb_map[i].csr);
609
610 printk(KERN_ERR " GPA_MEM_POP_MAP: 0x%16lx\n",
611 gp->gpa_mem_pop_map.csr);
612 printk(KERN_ERR " GPA_SCRATCH: 0x%16lx\n", gp->gpa_scratch.csr);
613 printk(KERN_ERR " GPA_DIAG: 0x%16lx\n", gp->gpa_diag.csr);
614 printk(KERN_ERR " GPA_CONFIG_0: 0x%16lx\n", gp->gpa_config_0.csr);
615 printk(KERN_ERR " GPA_INIT_ID: 0x%16lx\n", gp->gpa_init_id.csr);
616 printk(KERN_ERR " GPA_CONFIG_2: 0x%16lx\n", gp->gpa_config_2.csr);
617
618 printk(KERN_ERR "\n");
619}
620#endif /* DUMP_REGS */
621
622#if DEBUG_DUMP_CONFIG
623static void __init
624wildfire_dump_hardware_config(void)
625{
626 int i;
627
628 printk(KERN_ERR "Probed Hardware Configuration\n");
629
630 printk(KERN_ERR " hard_qbb_mask: 0x%16lx\n", wildfire_hard_qbb_mask);
631 printk(KERN_ERR " soft_qbb_mask: 0x%16lx\n", wildfire_soft_qbb_mask);
632
633 printk(KERN_ERR " gp_mask: 0x%16lx\n", wildfire_gp_mask);
634 printk(KERN_ERR " hs_mask: 0x%16lx\n", wildfire_hs_mask);
635 printk(KERN_ERR " iop_mask: 0x%16lx\n", wildfire_iop_mask);
636 printk(KERN_ERR " ior_mask: 0x%16lx\n", wildfire_ior_mask);
637 printk(KERN_ERR " pca_mask: 0x%16lx\n", wildfire_pca_mask);
638
639 printk(KERN_ERR " cpu_mask: 0x%16lx\n", wildfire_cpu_mask);
640 printk(KERN_ERR " mem_mask: 0x%16lx\n", wildfire_mem_mask);
641
642 printk(" hard_qbb_map: ");
643 for (i = 0; i < WILDFIRE_MAX_QBB; i++)
644 if (wildfire_hard_qbb_map[i] == QBB_MAP_EMPTY)
645 printk("--- ");
646 else
647 printk("%3d ", wildfire_hard_qbb_map[i]);
648 printk("\n");
649
650 printk(" soft_qbb_map: ");
651 for (i = 0; i < WILDFIRE_MAX_QBB; i++)
652 if (wildfire_soft_qbb_map[i] == QBB_MAP_EMPTY)
653 printk("--- ");
654 else
655 printk("%3d ", wildfire_soft_qbb_map[i]);
656 printk("\n");
657}
658#endif /* DUMP_CONFIG */
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
new file mode 100644
index 000000000000..f0927ee53f29
--- /dev/null
+++ b/arch/alpha/kernel/entry.S
@@ -0,0 +1,957 @@
1/*
2 * arch/alpha/kernel/entry.S
3 *
4 * Kernel entry-points.
5 */
6
7#include <linux/config.h>
8#include <asm/asm_offsets.h>
9#include <asm/thread_info.h>
10#include <asm/pal.h>
11#include <asm/errno.h>
12#include <asm/unistd.h>
13
14 .text
15 .set noat
16
17/* Stack offsets. */
18#define SP_OFF 184
19#define SWITCH_STACK_SIZE 320
20
21/*
22 * This defines the normal kernel pt-regs layout.
23 *
24 * regs 9-15 preserved by C code
25 * regs 16-18 saved by PAL-code
26 * regs 29-30 saved and set up by PAL-code
27 * JRP - Save regs 16-18 in a special area of the stack, so that
28 * the palcode-provided values are available to the signal handler.
29 */
30
31#define SAVE_ALL \
32 subq $sp, SP_OFF, $sp; \
33 stq $0, 0($sp); \
34 stq $1, 8($sp); \
35 stq $2, 16($sp); \
36 stq $3, 24($sp); \
37 stq $4, 32($sp); \
38 stq $28, 144($sp); \
39 lda $2, alpha_mv; \
40 stq $5, 40($sp); \
41 stq $6, 48($sp); \
42 stq $7, 56($sp); \
43 stq $8, 64($sp); \
44 stq $19, 72($sp); \
45 stq $20, 80($sp); \
46 stq $21, 88($sp); \
47 ldq $2, HAE_CACHE($2); \
48 stq $22, 96($sp); \
49 stq $23, 104($sp); \
50 stq $24, 112($sp); \
51 stq $25, 120($sp); \
52 stq $26, 128($sp); \
53 stq $27, 136($sp); \
54 stq $2, 152($sp); \
55 stq $16, 160($sp); \
56 stq $17, 168($sp); \
57 stq $18, 176($sp)
58
59#define RESTORE_ALL \
60 lda $19, alpha_mv; \
61 ldq $0, 0($sp); \
62 ldq $1, 8($sp); \
63 ldq $2, 16($sp); \
64 ldq $3, 24($sp); \
65 ldq $21, 152($sp); \
66 ldq $20, HAE_CACHE($19); \
67 ldq $4, 32($sp); \
68 ldq $5, 40($sp); \
69 ldq $6, 48($sp); \
70 ldq $7, 56($sp); \
71 subq $20, $21, $20; \
72 ldq $8, 64($sp); \
73 beq $20, 99f; \
74 ldq $20, HAE_REG($19); \
75 stq $21, HAE_CACHE($19); \
76 stq $21, 0($20); \
77 ldq $0, 0($sp); \
78 ldq $1, 8($sp); \
7999:; \
80 ldq $19, 72($sp); \
81 ldq $20, 80($sp); \
82 ldq $21, 88($sp); \
83 ldq $22, 96($sp); \
84 ldq $23, 104($sp); \
85 ldq $24, 112($sp); \
86 ldq $25, 120($sp); \
87 ldq $26, 128($sp); \
88 ldq $27, 136($sp); \
89 ldq $28, 144($sp); \
90 addq $sp, SP_OFF, $sp
91
92/*
93 * Non-syscall kernel entry points.
94 */
95
96 .align 4
97 .globl entInt
98 .ent entInt
99entInt:
100 SAVE_ALL
101 lda $8, 0x3fff
102 lda $26, ret_from_sys_call
103 bic $sp, $8, $8
104 mov $sp, $19
105 jsr $31, do_entInt
106.end entInt
107
108 .align 4
109 .globl entArith
110 .ent entArith
111entArith:
112 SAVE_ALL
113 lda $8, 0x3fff
114 lda $26, ret_from_sys_call
115 bic $sp, $8, $8
116 mov $sp, $18
117 jsr $31, do_entArith
118.end entArith
119
120 .align 4
121 .globl entMM
122 .ent entMM
123entMM:
124 SAVE_ALL
125/* save $9 - $15 so the inline exception code can manipulate them. */
126 subq $sp, 56, $sp
127 stq $9, 0($sp)
128 stq $10, 8($sp)
129 stq $11, 16($sp)
130 stq $12, 24($sp)
131 stq $13, 32($sp)
132 stq $14, 40($sp)
133 stq $15, 48($sp)
134 addq $sp, 56, $19
135/* handle the fault */
136 lda $8, 0x3fff
137 bic $sp, $8, $8
138 jsr $26, do_page_fault
139/* reload the registers after the exception code played. */
140 ldq $9, 0($sp)
141 ldq $10, 8($sp)
142 ldq $11, 16($sp)
143 ldq $12, 24($sp)
144 ldq $13, 32($sp)
145 ldq $14, 40($sp)
146 ldq $15, 48($sp)
147 addq $sp, 56, $sp
148/* finish up the syscall as normal. */
149 br ret_from_sys_call
150.end entMM
151
152 .align 4
153 .globl entIF
154 .ent entIF
155entIF:
156 SAVE_ALL
157 lda $8, 0x3fff
158 lda $26, ret_from_sys_call
159 bic $sp, $8, $8
160 mov $sp, $17
161 jsr $31, do_entIF
162.end entIF
163
164 .align 4
165 .globl entUna
166 .ent entUna
167entUna:
168 lda $sp, -256($sp)
169 stq $0, 0($sp)
170 ldq $0, 256($sp) /* get PS */
171 stq $1, 8($sp)
172 stq $2, 16($sp)
173 stq $3, 24($sp)
174 and $0, 8, $0 /* user mode? */
175 stq $4, 32($sp)
176 bne $0, entUnaUser /* yup -> do user-level unaligned fault */
177 stq $5, 40($sp)
178 stq $6, 48($sp)
179 stq $7, 56($sp)
180 stq $8, 64($sp)
181 stq $9, 72($sp)
182 stq $10, 80($sp)
183 stq $11, 88($sp)
184 stq $12, 96($sp)
185 stq $13, 104($sp)
186 stq $14, 112($sp)
187 stq $15, 120($sp)
188 /* 16-18 PAL-saved */
189 stq $19, 152($sp)
190 stq $20, 160($sp)
191 stq $21, 168($sp)
192 stq $22, 176($sp)
193 stq $23, 184($sp)
194 stq $24, 192($sp)
195 stq $25, 200($sp)
196 stq $26, 208($sp)
197 stq $27, 216($sp)
198 stq $28, 224($sp)
199 stq $gp, 232($sp)
200 lda $8, 0x3fff
201 stq $31, 248($sp)
202 bic $sp, $8, $8
203 jsr $26, do_entUna
204 ldq $0, 0($sp)
205 ldq $1, 8($sp)
206 ldq $2, 16($sp)
207 ldq $3, 24($sp)
208 ldq $4, 32($sp)
209 ldq $5, 40($sp)
210 ldq $6, 48($sp)
211 ldq $7, 56($sp)
212 ldq $8, 64($sp)
213 ldq $9, 72($sp)
214 ldq $10, 80($sp)
215 ldq $11, 88($sp)
216 ldq $12, 96($sp)
217 ldq $13, 104($sp)
218 ldq $14, 112($sp)
219 ldq $15, 120($sp)
220 /* 16-18 PAL-saved */
221 ldq $19, 152($sp)
222 ldq $20, 160($sp)
223 ldq $21, 168($sp)
224 ldq $22, 176($sp)
225 ldq $23, 184($sp)
226 ldq $24, 192($sp)
227 ldq $25, 200($sp)
228 ldq $26, 208($sp)
229 ldq $27, 216($sp)
230 ldq $28, 224($sp)
231 ldq $gp, 232($sp)
232 lda $sp, 256($sp)
233 call_pal PAL_rti
234.end entUna
235
236 .align 4
237 .ent entUnaUser
238entUnaUser:
239 ldq $0, 0($sp) /* restore original $0 */
240 lda $sp, 256($sp) /* pop entUna's stack frame */
241 SAVE_ALL /* setup normal kernel stack */
242 lda $sp, -56($sp)
243 stq $9, 0($sp)
244 stq $10, 8($sp)
245 stq $11, 16($sp)
246 stq $12, 24($sp)
247 stq $13, 32($sp)
248 stq $14, 40($sp)
249 stq $15, 48($sp)
250 lda $8, 0x3fff
251 addq $sp, 56, $19
252 bic $sp, $8, $8
253 jsr $26, do_entUnaUser
254 ldq $9, 0($sp)
255 ldq $10, 8($sp)
256 ldq $11, 16($sp)
257 ldq $12, 24($sp)
258 ldq $13, 32($sp)
259 ldq $14, 40($sp)
260 ldq $15, 48($sp)
261 lda $sp, 56($sp)
262 br ret_from_sys_call
263.end entUnaUser
264
265 .align 4
266 .globl entDbg
267 .ent entDbg
268entDbg:
269 SAVE_ALL
270 lda $8, 0x3fff
271 lda $26, ret_from_sys_call
272 bic $sp, $8, $8
273 mov $sp, $16
274 jsr $31, do_entDbg
275.end entDbg
276
277/*
278 * The system call entry point is special. Most importantly, it looks
279 * like a function call to userspace as far as clobbered registers. We
280 * do preserve the argument registers (for syscall restarts) and $26
281 * (for leaf syscall functions).
282 *
283 * So much for theory. We don't take advantage of this yet.
284 *
285 * Note that a0-a2 are not saved by PALcode as with the other entry points.
286 */
287
288 .align 4
289 .globl entSys
290 .globl ret_from_sys_call
291 .ent entSys
292entSys:
293 SAVE_ALL
294 lda $8, 0x3fff
295 bic $sp, $8, $8
296 lda $4, NR_SYSCALLS($31)
297 stq $16, SP_OFF+24($sp)
298 lda $5, sys_call_table
299 lda $27, sys_ni_syscall
300 cmpult $0, $4, $4
301 ldl $3, TI_FLAGS($8)
302 stq $17, SP_OFF+32($sp)
303 s8addq $0, $5, $5
304 stq $18, SP_OFF+40($sp)
305 blbs $3, strace
306 beq $4, 1f
307 ldq $27, 0($5)
3081: jsr $26, ($27), alpha_ni_syscall
309 ldgp $gp, 0($26)
310 blt $0, $syscall_error /* the call failed */
311 stq $0, 0($sp)
312 stq $31, 72($sp) /* a3=0 => no error */
313
314 .align 4
315ret_from_sys_call:
316 cmovne $26, 0, $19 /* $19 = 0 => non-restartable */
317 ldq $0, SP_OFF($sp)
318 and $0, 8, $0
319 beq $0, restore_all
320ret_from_reschedule:
321 /* Make sure need_resched and sigpending don't change between
322 sampling and the rti. */
323 lda $16, 7
324 call_pal PAL_swpipl
325 ldl $5, TI_FLAGS($8)
326 and $5, _TIF_WORK_MASK, $2
327 bne $5, work_pending
328restore_all:
329 RESTORE_ALL
330 call_pal PAL_rti
331
332 .align 3
333$syscall_error:
334 /*
335 * Some system calls (e.g., ptrace) can return arbitrary
336 * values which might normally be mistaken as error numbers.
337 * Those functions must zero $0 (v0) directly in the stack
338 * frame to indicate that a negative return value wasn't an
339 * error number..
340 */
341 ldq $19, 0($sp) /* old syscall nr (zero if success) */
342 beq $19, $ret_success
343
344 ldq $20, 72($sp) /* .. and this a3 */
345 subq $31, $0, $0 /* with error in v0 */
346 addq $31, 1, $1 /* set a3 for errno return */
347 stq $0, 0($sp)
348 mov $31, $26 /* tell "ret_from_sys_call" we can restart */
349 stq $1, 72($sp) /* a3 for return */
350 br ret_from_sys_call
351
352$ret_success:
353 stq $0, 0($sp)
354 stq $31, 72($sp) /* a3=0 => no error */
355 br ret_from_sys_call
356.end entSys
357
358/*
359 * Do all cleanup when returning from all interrupts and system calls.
360 *
361 * Arguments:
362 * $5: TI_FLAGS.
363 * $8: current.
364 * $19: The old syscall number, or zero if this is not a return
365 * from a syscall that errored and is possibly restartable.
366 * $20: Error indication.
367 */
368
369 .align 4
370 .ent work_pending
371work_pending:
372 and $5, _TIF_NEED_RESCHED, $2
373 beq $2, $work_notifysig
374
375$work_resched:
376 subq $sp, 16, $sp
377 stq $19, 0($sp) /* save syscall nr */
378 stq $20, 8($sp) /* and error indication (a3) */
379 jsr $26, schedule
380 ldq $19, 0($sp)
381 ldq $20, 8($sp)
382 addq $sp, 16, $sp
383 /* Make sure need_resched and sigpending don't change between
384 sampling and the rti. */
385 lda $16, 7
386 call_pal PAL_swpipl
387 ldl $5, TI_FLAGS($8)
388 and $5, _TIF_WORK_MASK, $2
389 beq $2, restore_all
390 and $5, _TIF_NEED_RESCHED, $2
391 bne $2, $work_resched
392
393$work_notifysig:
394 mov $sp, $17
395 br $1, do_switch_stack
396 mov $5, $21
397 mov $sp, $18
398 mov $31, $16
399 jsr $26, do_notify_resume
400 bsr $1, undo_switch_stack
401 br restore_all
402.end work_pending
403
404/*
405 * PTRACE syscall handler
406 */
407
408 .align 4
409 .ent strace
410strace:
411 /* set up signal stack, call syscall_trace */
412 bsr $1, do_switch_stack
413 jsr $26, syscall_trace
414 bsr $1, undo_switch_stack
415
416 /* get the system call number and the arguments back.. */
417 ldq $0, 0($sp)
418 ldq $16, SP_OFF+24($sp)
419 ldq $17, SP_OFF+32($sp)
420 ldq $18, SP_OFF+40($sp)
421 ldq $19, 72($sp)
422 ldq $20, 80($sp)
423 ldq $21, 88($sp)
424
425 /* get the system call pointer.. */
426 lda $1, NR_SYSCALLS($31)
427 lda $2, sys_call_table
428 lda $27, alpha_ni_syscall
429 cmpult $0, $1, $1
430 s8addq $0, $2, $2
431 beq $1, 1f
432 ldq $27, 0($2)
4331: jsr $26, ($27), sys_gettimeofday
434 ldgp $gp, 0($26)
435
436 /* check return.. */
437 blt $0, $strace_error /* the call failed */
438 stq $31, 72($sp) /* a3=0 => no error */
439$strace_success:
440 stq $0, 0($sp) /* save return value */
441
442 bsr $1, do_switch_stack
443 jsr $26, syscall_trace
444 bsr $1, undo_switch_stack
445 br $31, ret_from_sys_call
446
447 .align 3
448$strace_error:
449 ldq $19, 0($sp) /* old syscall nr (zero if success) */
450 beq $19, $strace_success
451 ldq $20, 72($sp) /* .. and this a3 */
452
453 subq $31, $0, $0 /* with error in v0 */
454 addq $31, 1, $1 /* set a3 for errno return */
455 stq $0, 0($sp)
456 stq $1, 72($sp) /* a3 for return */
457
458 bsr $1, do_switch_stack
459 mov $19, $9 /* save old syscall number */
460 mov $20, $10 /* save old a3 */
461 jsr $26, syscall_trace
462 mov $9, $19
463 mov $10, $20
464 bsr $1, undo_switch_stack
465
466 mov $31, $26 /* tell "ret_from_sys_call" we can restart */
467 br ret_from_sys_call
468.end strace
469
470/*
471 * Save and restore the switch stack -- aka the balance of the user context.
472 */
473
474 .align 4
475 .ent do_switch_stack
476do_switch_stack:
477 lda $sp, -SWITCH_STACK_SIZE($sp)
478 stq $9, 0($sp)
479 stq $10, 8($sp)
480 stq $11, 16($sp)
481 stq $12, 24($sp)
482 stq $13, 32($sp)
483 stq $14, 40($sp)
484 stq $15, 48($sp)
485 stq $26, 56($sp)
486 stt $f0, 64($sp)
487 stt $f1, 72($sp)
488 stt $f2, 80($sp)
489 stt $f3, 88($sp)
490 stt $f4, 96($sp)
491 stt $f5, 104($sp)
492 stt $f6, 112($sp)
493 stt $f7, 120($sp)
494 stt $f8, 128($sp)
495 stt $f9, 136($sp)
496 stt $f10, 144($sp)
497 stt $f11, 152($sp)
498 stt $f12, 160($sp)
499 stt $f13, 168($sp)
500 stt $f14, 176($sp)
501 stt $f15, 184($sp)
502 stt $f16, 192($sp)
503 stt $f17, 200($sp)
504 stt $f18, 208($sp)
505 stt $f19, 216($sp)
506 stt $f20, 224($sp)
507 stt $f21, 232($sp)
508 stt $f22, 240($sp)
509 stt $f23, 248($sp)
510 stt $f24, 256($sp)
511 stt $f25, 264($sp)
512 stt $f26, 272($sp)
513 stt $f27, 280($sp)
514 mf_fpcr $f0 # get fpcr
515 stt $f28, 288($sp)
516 stt $f29, 296($sp)
517 stt $f30, 304($sp)
518 stt $f0, 312($sp) # save fpcr in slot of $f31
519 ldt $f0, 64($sp) # dont let "do_switch_stack" change fp state.
520 ret $31, ($1), 1
521.end do_switch_stack
522
523 .align 4
524 .ent undo_switch_stack
525undo_switch_stack:
526 ldq $9, 0($sp)
527 ldq $10, 8($sp)
528 ldq $11, 16($sp)
529 ldq $12, 24($sp)
530 ldq $13, 32($sp)
531 ldq $14, 40($sp)
532 ldq $15, 48($sp)
533 ldq $26, 56($sp)
534 ldt $f30, 312($sp) # get saved fpcr
535 ldt $f0, 64($sp)
536 ldt $f1, 72($sp)
537 ldt $f2, 80($sp)
538 ldt $f3, 88($sp)
539 mt_fpcr $f30 # install saved fpcr
540 ldt $f4, 96($sp)
541 ldt $f5, 104($sp)
542 ldt $f6, 112($sp)
543 ldt $f7, 120($sp)
544 ldt $f8, 128($sp)
545 ldt $f9, 136($sp)
546 ldt $f10, 144($sp)
547 ldt $f11, 152($sp)
548 ldt $f12, 160($sp)
549 ldt $f13, 168($sp)
550 ldt $f14, 176($sp)
551 ldt $f15, 184($sp)
552 ldt $f16, 192($sp)
553 ldt $f17, 200($sp)
554 ldt $f18, 208($sp)
555 ldt $f19, 216($sp)
556 ldt $f20, 224($sp)
557 ldt $f21, 232($sp)
558 ldt $f22, 240($sp)
559 ldt $f23, 248($sp)
560 ldt $f24, 256($sp)
561 ldt $f25, 264($sp)
562 ldt $f26, 272($sp)
563 ldt $f27, 280($sp)
564 ldt $f28, 288($sp)
565 ldt $f29, 296($sp)
566 ldt $f30, 304($sp)
567 lda $sp, SWITCH_STACK_SIZE($sp)
568 ret $31, ($1), 1
569.end undo_switch_stack
570
571/*
572 * The meat of the context switch code.
573 */
574
575 .align 4
576 .globl alpha_switch_to
577 .ent alpha_switch_to
578alpha_switch_to:
579 .prologue 0
580 bsr $1, do_switch_stack
581 call_pal PAL_swpctx
582 lda $8, 0x3fff
583 bsr $1, undo_switch_stack
584 bic $sp, $8, $8
585 mov $17, $0
586 ret
587.end alpha_switch_to
588
589/*
590 * New processes begin life here.
591 */
592
593 .globl ret_from_fork
594 .align 4
595 .ent ret_from_fork
596ret_from_fork:
597 lda $26, ret_from_sys_call
598 mov $17, $16
599 jmp $31, schedule_tail
600.end ret_from_fork
601
602/*
603 * kernel_thread(fn, arg, clone_flags)
604 */
605 .align 4
606 .globl kernel_thread
607 .ent kernel_thread
608kernel_thread:
609 /* We can be called from a module. */
610 ldgp $gp, 0($27)
611 .prologue 1
612 subq $sp, SP_OFF+6*8, $sp
613 br $1, 2f /* load start address */
614
615 /* We've now "returned" from a fake system call. */
616 unop
617 blt $0, 1f /* error? */
618 ldi $1, 0x3fff
619 beq $20, 1f /* parent or child? */
620
621 bic $sp, $1, $8 /* in child. */
622 jsr $26, ($27)
623 ldgp $gp, 0($26)
624 mov $0, $16
625 mov $31, $26
626 jmp $31, sys_exit
627
6281: ret /* in parent. */
629
630 .align 4
6312: /* Fake a system call stack frame, as we can't do system calls
632 from kernel space. Note that we store FN and ARG as they
633 need to be set up in the child for the call. Also store $8
634 and $26 for use in the parent. */
635 stq $31, SP_OFF($sp) /* ps */
636 stq $1, SP_OFF+8($sp) /* pc */
637 stq $gp, SP_OFF+16($sp) /* gp */
638 stq $16, 136($sp) /* $27; FN for child */
639 stq $17, SP_OFF+24($sp) /* $16; ARG for child */
640 stq $8, 64($sp) /* $8 */
641 stq $26, 128($sp) /* $26 */
642 /* Avoid the HAE being gratuitously wrong, to avoid restoring it. */
643 ldq $2, alpha_mv+HAE_CACHE
644 stq $2, 152($sp) /* HAE */
645
646 /* Shuffle FLAGS to the front; add CLONE_VM. */
647 ldi $1, CLONE_VM|CLONE_UNTRACED
648 or $18, $1, $16
649 bsr $26, sys_clone
650
651 /* We don't actually care for a3 success widgetry in the kernel.
652 Not for positive errno values. */
653 stq $0, 0($sp) /* $0 */
654 br restore_all
655.end kernel_thread
656
657/*
658 * execve(path, argv, envp)
659 */
660 .align 4
661 .globl execve
662 .ent execve
663execve:
664 /* We can be called from a module. */
665 ldgp $gp, 0($27)
666 lda $sp, -(32+SIZEOF_PT_REGS+8)($sp)
667 .frame $sp, 32+SIZEOF_PT_REGS+8, $26, 0
668 stq $26, 0($sp)
669 stq $16, 8($sp)
670 stq $17, 16($sp)
671 stq $18, 24($sp)
672 .prologue 1
673
674 lda $16, 32($sp)
675 lda $17, 0
676 lda $18, SIZEOF_PT_REGS
677 bsr $26, memset !samegp
678
679 /* Avoid the HAE being gratuitously wrong, which would cause us
680 to do the whole turn off interrupts thing and restore it. */
681 ldq $2, alpha_mv+HAE_CACHE
682 stq $2, 152+32($sp)
683
684 ldq $16, 8($sp)
685 ldq $17, 16($sp)
686 ldq $18, 24($sp)
687 lda $19, 32($sp)
688 bsr $26, do_execve !samegp
689
690 ldq $26, 0($sp)
691 bne $0, 1f /* error! */
692
693 /* Move the temporary pt_regs struct from its current location
694 to the top of the kernel stack frame. See copy_thread for
695 details for a normal process. */
696 lda $16, 0x4000 - SIZEOF_PT_REGS($8)
697 lda $17, 32($sp)
698 lda $18, SIZEOF_PT_REGS
699 bsr $26, memmove !samegp
700
701 /* Take that over as our new stack frame and visit userland! */
702 lda $sp, 0x4000 - SIZEOF_PT_REGS($8)
703 br $31, ret_from_sys_call
704
7051: lda $sp, 32+SIZEOF_PT_REGS+8($sp)
706 ret
707.end execve
708
709
710/*
711 * Special system calls. Most of these are special in that they either
712 * have to play switch_stack games or in some way use the pt_regs struct.
713 */
714 .align 4
715 .globl sys_fork
716 .ent sys_fork
717sys_fork:
718 .prologue 0
719 mov $sp, $21
720 bsr $1, do_switch_stack
721 bis $31, SIGCHLD, $16
722 mov $31, $17
723 mov $31, $18
724 mov $31, $19
725 mov $31, $20
726 jsr $26, alpha_clone
727 bsr $1, undo_switch_stack
728 ret
729.end sys_fork
730
731 .align 4
732 .globl sys_clone
733 .ent sys_clone
734sys_clone:
735 .prologue 0
736 mov $sp, $21
737 bsr $1, do_switch_stack
738 /* $16, $17, $18, $19, $20 come from the user. */
739 jsr $26, alpha_clone
740 bsr $1, undo_switch_stack
741 ret
742.end sys_clone
743
744 .align 4
745 .globl sys_vfork
746 .ent sys_vfork
747sys_vfork:
748 .prologue 0
749 mov $sp, $16
750 bsr $1, do_switch_stack
751 jsr $26, alpha_vfork
752 bsr $1, undo_switch_stack
753 ret
754.end sys_vfork
755
756 .align 4
757 .globl sys_sigreturn
758 .ent sys_sigreturn
759sys_sigreturn:
760 .prologue 0
761 mov $sp, $17
762 lda $18, -SWITCH_STACK_SIZE($sp)
763 lda $sp, -SWITCH_STACK_SIZE($sp)
764 jsr $26, do_sigreturn
765 br $1, undo_switch_stack
766 br ret_from_sys_call
767.end sys_sigreturn
768
769 .align 4
770 .globl sys_rt_sigreturn
771 .ent sys_rt_sigreturn
772sys_rt_sigreturn:
773 .prologue 0
774 mov $sp, $17
775 lda $18, -SWITCH_STACK_SIZE($sp)
776 lda $sp, -SWITCH_STACK_SIZE($sp)
777 jsr $26, do_rt_sigreturn
778 br $1, undo_switch_stack
779 br ret_from_sys_call
780.end sys_rt_sigreturn
781
782 .align 4
783 .globl sys_sigsuspend
784 .ent sys_sigsuspend
785sys_sigsuspend:
786 .prologue 0
787 mov $sp, $17
788 br $1, do_switch_stack
789 mov $sp, $18
790 subq $sp, 16, $sp
791 stq $26, 0($sp)
792 jsr $26, do_sigsuspend
793 ldq $26, 0($sp)
794 lda $sp, SWITCH_STACK_SIZE+16($sp)
795 ret
796.end sys_sigsuspend
797
798 .align 4
799 .globl sys_rt_sigsuspend
800 .ent sys_rt_sigsuspend
801sys_rt_sigsuspend:
802 .prologue 0
803 mov $sp, $18
804 br $1, do_switch_stack
805 mov $sp, $19
806 subq $sp, 16, $sp
807 stq $26, 0($sp)
808 jsr $26, do_rt_sigsuspend
809 ldq $26, 0($sp)
810 lda $sp, SWITCH_STACK_SIZE+16($sp)
811 ret
812.end sys_rt_sigsuspend
813
814 .align 4
815 .globl sys_sethae
816 .ent sys_sethae
817sys_sethae:
818 .prologue 0
819 stq $16, 152($sp)
820 ret
821.end sys_sethae
822
823 .align 4
824 .globl osf_getpriority
825 .ent osf_getpriority
826osf_getpriority:
827 lda $sp, -16($sp)
828 stq $26, 0($sp)
829 .prologue 0
830
831 jsr $26, sys_getpriority
832
833 ldq $26, 0($sp)
834 blt $0, 1f
835
836 /* Return value is the unbiased priority, i.e. 20 - prio.
837 This does result in negative return values, so signal
838 no error by writing into the R0 slot. */
839 lda $1, 20
840 stq $31, 16($sp)
841 subl $1, $0, $0
842 unop
843
8441: lda $sp, 16($sp)
845 ret
846.end osf_getpriority
847
848 .align 4
849 .globl sys_getxuid
850 .ent sys_getxuid
851sys_getxuid:
852 .prologue 0
853 ldq $2, TI_TASK($8)
854 ldl $0, TASK_UID($2)
855 ldl $1, TASK_EUID($2)
856 stq $1, 80($sp)
857 ret
858.end sys_getxuid
859
860 .align 4
861 .globl sys_getxgid
862 .ent sys_getxgid
863sys_getxgid:
864 .prologue 0
865 ldq $2, TI_TASK($8)
866 ldl $0, TASK_GID($2)
867 ldl $1, TASK_EGID($2)
868 stq $1, 80($sp)
869 ret
870.end sys_getxgid
871
872 .align 4
873 .globl sys_getxpid
874 .ent sys_getxpid
875sys_getxpid:
876 .prologue 0
877 ldq $2, TI_TASK($8)
878
879 /* See linux/kernel/timer.c sys_getppid for discussion
880 about this loop. */
881 ldq $3, TASK_REAL_PARENT($2)
8821: ldl $1, TASK_TGID($3)
883#ifdef CONFIG_SMP
884 mov $3, $4
885 mb
886 ldq $3, TASK_REAL_PARENT($2)
887 cmpeq $3, $4, $4
888 beq $4, 1b
889#endif
890 stq $1, 80($sp)
891 ldl $0, TASK_TGID($2)
892 ret
893.end sys_getxpid
894
895 .align 4
896 .globl sys_pipe
897 .ent sys_pipe
898sys_pipe:
899 lda $sp, -16($sp)
900 stq $26, 0($sp)
901 .prologue 0
902
903 lda $16, 8($sp)
904 jsr $26, do_pipe
905
906 ldq $26, 0($sp)
907 bne $0, 1f
908
909 /* The return values are in $0 and $20. */
910 ldl $1, 12($sp)
911 ldl $0, 8($sp)
912
913 stq $1, 80+16($sp)
9141: lda $sp, 16($sp)
915 ret
916.end sys_pipe
917
918 .align 4
919 .globl sys_ptrace
920 .ent sys_ptrace
921sys_ptrace:
922 .prologue 0
923 mov $sp, $20
924 jmp $31, do_sys_ptrace
925.end sys_ptrace
926
927 .align 4
928 .globl sys_execve
929 .ent sys_execve
930sys_execve:
931 .prologue 0
932 mov $sp, $19
933 jmp $31, do_sys_execve
934.end sys_execve
935
936 .align 4
937 .globl osf_sigprocmask
938 .ent osf_sigprocmask
939osf_sigprocmask:
940 .prologue 0
941 mov $sp, $18
942 jmp $31, do_osf_sigprocmask
943.end osf_sigprocmask
944
945 .align 4
946 .globl alpha_ni_syscall
947 .ent alpha_ni_syscall
948alpha_ni_syscall:
949 .prologue 0
950 /* Special because it also implements overflow handling via
951 syscall number 0. And if you recall, zero is a special
952 trigger for "not an error". Store large non-zero there. */
953 lda $0, -ENOSYS
954 unop
955 stq $0, 0($sp)
956 ret
957.end alpha_ni_syscall
diff --git a/arch/alpha/kernel/err_common.c b/arch/alpha/kernel/err_common.c
new file mode 100644
index 000000000000..687580b16b41
--- /dev/null
+++ b/arch/alpha/kernel/err_common.c
@@ -0,0 +1,321 @@
1/*
2 * linux/arch/alpha/kernel/err_common.c
3 *
4 * Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation)
5 *
6 * Error handling code supporting Alpha systems
7 */
8
9#include <linux/init.h>
10#include <linux/pci.h>
11#include <linux/sched.h>
12
13#include <asm/io.h>
14#include <asm/hwrpb.h>
15#include <asm/smp.h>
16#include <asm/err_common.h>
17
18#include "err_impl.h"
19#include "proto.h"
20
21/*
22 * err_print_prefix -- error handling print routines should prefix
23 * all prints with this
24 */
25char *err_print_prefix = KERN_NOTICE;
26
27
28/*
29 * Generic
30 */
31void
32mchk_dump_mem(void *data, size_t length, char **annotation)
33{
34 unsigned long *ldata = data;
35 size_t i;
36
37 for (i = 0; (i * sizeof(*ldata)) < length; i++) {
38 if (annotation && !annotation[i])
39 annotation = NULL;
40 printk("%s %08x: %016lx %s\n",
41 err_print_prefix,
42 (unsigned)(i * sizeof(*ldata)), ldata[i],
43 annotation ? annotation[i] : "");
44 }
45}
46
47void
48mchk_dump_logout_frame(struct el_common *mchk_header)
49{
50 printk("%s -- Frame Header --\n"
51 " Frame Size: %d (0x%x) bytes\n"
52 " Flags: %s%s\n"
53 " MCHK Code: 0x%x\n"
54 " Frame Rev: %d\n"
55 " Proc Offset: 0x%08x\n"
56 " Sys Offset: 0x%08x\n"
57 " -- Processor Region --\n",
58 err_print_prefix,
59 mchk_header->size, mchk_header->size,
60 mchk_header->retry ? "RETRY " : "",
61 mchk_header->err2 ? "SECOND_ERR " : "",
62 mchk_header->code,
63 mchk_header->frame_rev,
64 mchk_header->proc_offset,
65 mchk_header->sys_offset);
66
67 mchk_dump_mem((void *)
68 ((unsigned long)mchk_header + mchk_header->proc_offset),
69 mchk_header->sys_offset - mchk_header->proc_offset,
70 NULL);
71
72 printk("%s -- System Region --\n", err_print_prefix);
73 mchk_dump_mem((void *)
74 ((unsigned long)mchk_header + mchk_header->sys_offset),
75 mchk_header->size - mchk_header->sys_offset,
76 NULL);
77 printk("%s -- End of Frame --\n", err_print_prefix);
78}
79
80
81/*
82 * Console Data Log
83 */
84/* Data */
85static struct el_subpacket_handler *subpacket_handler_list = NULL;
86static struct el_subpacket_annotation *subpacket_annotation_list = NULL;
87
88static struct el_subpacket *
89el_process_header_subpacket(struct el_subpacket *header)
90{
91 union el_timestamp timestamp;
92 char *name = "UNKNOWN EVENT";
93 int packet_count = 0;
94 int length = 0;
95
96 if (header->class != EL_CLASS__HEADER) {
97 printk("%s** Unexpected header CLASS %d TYPE %d, aborting\n",
98 err_print_prefix,
99 header->class, header->type);
100 return NULL;
101 }
102
103 switch(header->type) {
104 case EL_TYPE__HEADER__SYSTEM_ERROR_FRAME:
105 name = "SYSTEM ERROR";
106 length = header->by_type.sys_err.frame_length;
107 packet_count =
108 header->by_type.sys_err.frame_packet_count;
109 timestamp.as_int = 0;
110 break;
111 case EL_TYPE__HEADER__SYSTEM_EVENT_FRAME:
112 name = "SYSTEM EVENT";
113 length = header->by_type.sys_event.frame_length;
114 packet_count =
115 header->by_type.sys_event.frame_packet_count;
116 timestamp = header->by_type.sys_event.timestamp;
117 break;
118 case EL_TYPE__HEADER__HALT_FRAME:
119 name = "ERROR HALT";
120 length = header->by_type.err_halt.frame_length;
121 packet_count =
122 header->by_type.err_halt.frame_packet_count;
123 timestamp = header->by_type.err_halt.timestamp;
124 break;
125 case EL_TYPE__HEADER__LOGOUT_FRAME:
126 name = "LOGOUT FRAME";
127 length = header->by_type.logout_header.frame_length;
128 packet_count = 1;
129 timestamp.as_int = 0;
130 break;
131 default: /* Unknown */
132 printk("%s** Unknown header - CLASS %d TYPE %d, aborting\n",
133 err_print_prefix,
134 header->class, header->type);
135 return NULL;
136 }
137
138 printk("%s*** %s:\n"
139 " CLASS %d, TYPE %d\n",
140 err_print_prefix,
141 name,
142 header->class, header->type);
143 el_print_timestamp(&timestamp);
144
145 /*
146 * Process the subpackets
147 */
148 el_process_subpackets(header, packet_count);
149
150 /* return the next header */
151 header = (struct el_subpacket *)
152 ((unsigned long)header + header->length + length);
153 return header;
154}
155
156static struct el_subpacket *
157el_process_subpacket_reg(struct el_subpacket *header)
158{
159 struct el_subpacket *next = NULL;
160 struct el_subpacket_handler *h = subpacket_handler_list;
161
162 for (; h && h->class != header->class; h = h->next);
163 if (h) next = h->handler(header);
164
165 return next;
166}
167
168void
169el_print_timestamp(union el_timestamp *timestamp)
170{
171 if (timestamp->as_int)
172 printk("%s TIMESTAMP: %d/%d/%02d %d:%02d:%0d\n",
173 err_print_prefix,
174 timestamp->b.month, timestamp->b.day,
175 timestamp->b.year, timestamp->b.hour,
176 timestamp->b.minute, timestamp->b.second);
177}
178
179void
180el_process_subpackets(struct el_subpacket *header, int packet_count)
181{
182 struct el_subpacket *subpacket;
183 int i;
184
185 subpacket = (struct el_subpacket *)
186 ((unsigned long)header + header->length);
187
188 for (i = 0; subpacket && i < packet_count; i++) {
189 printk("%sPROCESSING SUBPACKET %d\n", err_print_prefix, i);
190 subpacket = el_process_subpacket(subpacket);
191 }
192}
193
194struct el_subpacket *
195el_process_subpacket(struct el_subpacket *header)
196{
197 struct el_subpacket *next = NULL;
198
199 switch(header->class) {
200 case EL_CLASS__TERMINATION:
201 /* Termination packet, there are no more */
202 break;
203 case EL_CLASS__HEADER:
204 next = el_process_header_subpacket(header);
205 break;
206 default:
207 if (NULL == (next = el_process_subpacket_reg(header))) {
208 printk("%s** Unexpected header CLASS %d TYPE %d"
209 " -- aborting.\n",
210 err_print_prefix,
211 header->class, header->type);
212 }
213 break;
214 }
215
216 return next;
217}
218
219void
220el_annotate_subpacket(struct el_subpacket *header)
221{
222 struct el_subpacket_annotation *a;
223 char **annotation = NULL;
224
225 for (a = subpacket_annotation_list; a; a = a->next) {
226 if (a->class == header->class &&
227 a->type == header->type &&
228 a->revision == header->revision) {
229 /*
230 * We found the annotation
231 */
232 annotation = a->annotation;
233 printk("%s %s\n", err_print_prefix, a->description);
234 break;
235 }
236 }
237
238 mchk_dump_mem(header, header->length, annotation);
239}
240
241static void __init
242cdl_process_console_data_log(int cpu, struct percpu_struct *pcpu)
243{
244 struct el_subpacket *header = (struct el_subpacket *)
245 (IDENT_ADDR | pcpu->console_data_log_pa);
246 int err;
247
248 printk("%s******* CONSOLE DATA LOG FOR CPU %d. *******\n"
249 "*** Error(s) were logged on a previous boot\n",
250 err_print_prefix, cpu);
251
252 for (err = 0; header && (header->class != EL_CLASS__TERMINATION); err++)
253 header = el_process_subpacket(header);
254
255 /* let the console know it's ok to clear the error(s) at restart */
256 pcpu->console_data_log_pa = 0;
257
258 printk("%s*** %d total error(s) logged\n"
259 "**** END OF CONSOLE DATA LOG FOR CPU %d ****\n",
260 err_print_prefix, err, cpu);
261}
262
263void __init
264cdl_check_console_data_log(void)
265{
266 struct percpu_struct *pcpu;
267 unsigned long cpu;
268
269 for (cpu = 0; cpu < hwrpb->nr_processors; cpu++) {
270 pcpu = (struct percpu_struct *)
271 ((unsigned long)hwrpb + hwrpb->processor_offset
272 + cpu * hwrpb->processor_size);
273 if (pcpu->console_data_log_pa)
274 cdl_process_console_data_log(cpu, pcpu);
275 }
276
277}
278
279int __init
280cdl_register_subpacket_annotation(struct el_subpacket_annotation *new)
281{
282 struct el_subpacket_annotation *a = subpacket_annotation_list;
283
284 if (a == NULL) subpacket_annotation_list = new;
285 else {
286 for (; a->next != NULL; a = a->next) {
287 if ((a->class == new->class && a->type == new->type) ||
288 a == new) {
289 printk("Attempted to re-register "
290 "subpacket annotation\n");
291 return -EINVAL;
292 }
293 }
294 a->next = new;
295 }
296 new->next = NULL;
297
298 return 0;
299}
300
301int __init
302cdl_register_subpacket_handler(struct el_subpacket_handler *new)
303{
304 struct el_subpacket_handler *h = subpacket_handler_list;
305
306 if (h == NULL) subpacket_handler_list = new;
307 else {
308 for (; h->next != NULL; h = h->next) {
309 if (h->class == new->class || h == new) {
310 printk("Attempted to re-register "
311 "subpacket handler\n");
312 return -EINVAL;
313 }
314 }
315 h->next = new;
316 }
317 new->next = NULL;
318
319 return 0;
320}
321
diff --git a/arch/alpha/kernel/err_ev6.c b/arch/alpha/kernel/err_ev6.c
new file mode 100644
index 000000000000..64f59f2fcf5c
--- /dev/null
+++ b/arch/alpha/kernel/err_ev6.c
@@ -0,0 +1,274 @@
1/*
2 * linux/arch/alpha/kernel/err_ev6.c
3 *
4 * Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation)
5 *
6 * Error handling code supporting Alpha systems
7 */
8
9#include <linux/init.h>
10#include <linux/pci.h>
11#include <linux/sched.h>
12
13#include <asm/io.h>
14#include <asm/hwrpb.h>
15#include <asm/smp.h>
16#include <asm/err_common.h>
17#include <asm/err_ev6.h>
18
19#include "err_impl.h"
20#include "proto.h"
21
22static int
23ev6_parse_ibox(u64 i_stat, int print)
24{
25 int status = MCHK_DISPOSITION_REPORT;
26
27#define EV6__I_STAT__PAR (1UL << 29)
28#define EV6__I_STAT__ERRMASK (EV6__I_STAT__PAR)
29
30 if (!(i_stat & EV6__I_STAT__ERRMASK))
31 return MCHK_DISPOSITION_UNKNOWN_ERROR;
32
33 if (!print)
34 return status;
35
36 if (i_stat & EV6__I_STAT__PAR)
37 printk("%s Icache parity error\n", err_print_prefix);
38
39 return status;
40}
41
42static int
43ev6_parse_mbox(u64 mm_stat, u64 d_stat, u64 c_stat, int print)
44{
45 int status = MCHK_DISPOSITION_REPORT;
46
47#define EV6__MM_STAT__DC_TAG_PERR (1UL << 10)
48#define EV6__MM_STAT__ERRMASK (EV6__MM_STAT__DC_TAG_PERR)
49#define EV6__D_STAT__TPERR_P0 (1UL << 0)
50#define EV6__D_STAT__TPERR_P1 (1UL << 1)
51#define EV6__D_STAT__ECC_ERR_ST (1UL << 2)
52#define EV6__D_STAT__ECC_ERR_LD (1UL << 3)
53#define EV6__D_STAT__SEO (1UL << 4)
54#define EV6__D_STAT__ERRMASK (EV6__D_STAT__TPERR_P0 | \
55 EV6__D_STAT__TPERR_P1 | \
56 EV6__D_STAT__ECC_ERR_ST | \
57 EV6__D_STAT__ECC_ERR_LD | \
58 EV6__D_STAT__SEO)
59
60 if (!(d_stat & EV6__D_STAT__ERRMASK) &&
61 !(mm_stat & EV6__MM_STAT__ERRMASK))
62 return MCHK_DISPOSITION_UNKNOWN_ERROR;
63
64 if (!print)
65 return status;
66
67 if (mm_stat & EV6__MM_STAT__DC_TAG_PERR)
68 printk("%s Dcache tag parity error on probe\n",
69 err_print_prefix);
70 if (d_stat & EV6__D_STAT__TPERR_P0)
71 printk("%s Dcache tag parity error - pipe 0\n",
72 err_print_prefix);
73 if (d_stat & EV6__D_STAT__TPERR_P1)
74 printk("%s Dcache tag parity error - pipe 1\n",
75 err_print_prefix);
76 if (d_stat & EV6__D_STAT__ECC_ERR_ST)
77 printk("%s ECC error occurred on a store\n",
78 err_print_prefix);
79 if (d_stat & EV6__D_STAT__ECC_ERR_LD)
80 printk("%s ECC error occurred on a %s load\n",
81 err_print_prefix,
82 c_stat ? "" : "speculative ");
83 if (d_stat & EV6__D_STAT__SEO)
84 printk("%s Dcache second error\n", err_print_prefix);
85
86 return status;
87}
88
89static int
90ev6_parse_cbox(u64 c_addr, u64 c1_syn, u64 c2_syn,
91 u64 c_stat, u64 c_sts, int print)
92{
93 char *sourcename[] = { "UNKNOWN", "UNKNOWN", "UNKNOWN",
94 "MEMORY", "BCACHE", "DCACHE",
95 "BCACHE PROBE", "BCACHE PROBE" };
96 char *streamname[] = { "D", "I" };
97 char *bitsname[] = { "SINGLE", "DOUBLE" };
98 int status = MCHK_DISPOSITION_REPORT;
99 int source = -1, stream = -1, bits = -1;
100
101#define EV6__C_STAT__BC_PERR (0x01)
102#define EV6__C_STAT__DC_PERR (0x02)
103#define EV6__C_STAT__DSTREAM_MEM_ERR (0x03)
104#define EV6__C_STAT__DSTREAM_BC_ERR (0x04)
105#define EV6__C_STAT__DSTREAM_DC_ERR (0x05)
106#define EV6__C_STAT__PROBE_BC_ERR0 (0x06) /* both 6 and 7 indicate... */
107#define EV6__C_STAT__PROBE_BC_ERR1 (0x07) /* ...probe bc error. */
108#define EV6__C_STAT__ISTREAM_MEM_ERR (0x0B)
109#define EV6__C_STAT__ISTREAM_BC_ERR (0x0C)
110#define EV6__C_STAT__DSTREAM_MEM_DBL (0x13)
111#define EV6__C_STAT__DSTREAM_BC_DBL (0x14)
112#define EV6__C_STAT__ISTREAM_MEM_DBL (0x1B)
113#define EV6__C_STAT__ISTREAM_BC_DBL (0x1C)
114#define EV6__C_STAT__SOURCE_MEMORY (0x03)
115#define EV6__C_STAT__SOURCE_BCACHE (0x04)
116#define EV6__C_STAT__SOURCE__S (0)
117#define EV6__C_STAT__SOURCE__M (0x07)
118#define EV6__C_STAT__ISTREAM__S (3)
119#define EV6__C_STAT__ISTREAM__M (0x01)
120#define EV6__C_STAT__DOUBLE__S (4)
121#define EV6__C_STAT__DOUBLE__M (0x01)
122#define EV6__C_STAT__ERRMASK (0x1F)
123#define EV6__C_STS__SHARED (1 << 0)
124#define EV6__C_STS__DIRTY (1 << 1)
125#define EV6__C_STS__VALID (1 << 2)
126#define EV6__C_STS__PARITY (1 << 3)
127
128 if (!(c_stat & EV6__C_STAT__ERRMASK))
129 return MCHK_DISPOSITION_UNKNOWN_ERROR;
130
131 if (!print)
132 return status;
133
134 source = EXTRACT(c_stat, EV6__C_STAT__SOURCE);
135 stream = EXTRACT(c_stat, EV6__C_STAT__ISTREAM);
136 bits = EXTRACT(c_stat, EV6__C_STAT__DOUBLE);
137
138 if (c_stat & EV6__C_STAT__BC_PERR) {
139 printk("%s Bcache tag parity error\n", err_print_prefix);
140 source = -1;
141 }
142
143 if (c_stat & EV6__C_STAT__DC_PERR) {
144 printk("%s Dcache tag parity error\n", err_print_prefix);
145 source = -1;
146 }
147
148 if (c_stat == EV6__C_STAT__PROBE_BC_ERR0 ||
149 c_stat == EV6__C_STAT__PROBE_BC_ERR1) {
150 printk("%s Bcache single-bit error on a probe hit\n",
151 err_print_prefix);
152 source = -1;
153 }
154
155 if (source != -1)
156 printk("%s %s-STREAM %s-BIT ECC error from %s\n",
157 err_print_prefix,
158 streamname[stream], bitsname[bits], sourcename[source]);
159
160 printk("%s Address: 0x%016lx\n"
161 " Syndrome[upper.lower]: %02lx.%02lx\n",
162 err_print_prefix,
163 c_addr,
164 c2_syn, c1_syn);
165
166 if (source == EV6__C_STAT__SOURCE_MEMORY ||
167 source == EV6__C_STAT__SOURCE_BCACHE)
168 printk("%s Block status: %s%s%s%s\n",
169 err_print_prefix,
170 (c_sts & EV6__C_STS__SHARED) ? "SHARED " : "",
171 (c_sts & EV6__C_STS__DIRTY) ? "DIRTY " : "",
172 (c_sts & EV6__C_STS__VALID) ? "VALID " : "",
173 (c_sts & EV6__C_STS__PARITY) ? "PARITY " : "");
174
175 return status;
176}
177
178void
179ev6_register_error_handlers(void)
180{
181 /* None right now. */
182}
183
184int
185ev6_process_logout_frame(struct el_common *mchk_header, int print)
186{
187 struct el_common_EV6_mcheck *ev6mchk =
188 (struct el_common_EV6_mcheck *)mchk_header;
189 int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
190
191 status |= ev6_parse_ibox(ev6mchk->I_STAT, print);
192 status |= ev6_parse_mbox(ev6mchk->MM_STAT, ev6mchk->DC_STAT,
193 ev6mchk->C_STAT, print);
194 status |= ev6_parse_cbox(ev6mchk->C_ADDR, ev6mchk->DC1_SYNDROME,
195 ev6mchk->DC0_SYNDROME, ev6mchk->C_STAT,
196 ev6mchk->C_STS, print);
197
198 if (!print)
199 return status;
200
201 if (status != MCHK_DISPOSITION_DISMISS) {
202 char *saved_err_prefix = err_print_prefix;
203
204 /*
205 * Dump some additional information from the frame
206 */
207 printk("%s EXC_ADDR: 0x%016lx IER_CM: 0x%016lx"
208 " ISUM: 0x%016lx\n"
209 " PAL_BASE: 0x%016lx I_CTL: 0x%016lx"
210 " PCTX: 0x%016lx\n",
211 err_print_prefix,
212 ev6mchk->EXC_ADDR, ev6mchk->IER_CM, ev6mchk->ISUM,
213 ev6mchk->PAL_BASE, ev6mchk->I_CTL, ev6mchk->PCTX);
214
215 if (status == MCHK_DISPOSITION_UNKNOWN_ERROR) {
216 printk("%s UNKNOWN error, frame follows:\n",
217 err_print_prefix);
218 } else {
219 /* had decode -- downgrade print level for frame */
220 err_print_prefix = KERN_NOTICE;
221 }
222
223 mchk_dump_logout_frame(mchk_header);
224
225 err_print_prefix = saved_err_prefix;
226 }
227
228 return status;
229}
230
231void
232ev6_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
233{
234 struct el_common *mchk_header = (struct el_common *)la_ptr;
235
236 /*
237 * Sync the processor
238 */
239 mb();
240 draina();
241
242 /*
243 * Parse the logout frame without printing first. If the only error(s)
244 * found are have a disposition of "dismiss", then just dismiss them
245 * and don't print any message
246 */
247 if (ev6_process_logout_frame(mchk_header, 0) !=
248 MCHK_DISPOSITION_DISMISS) {
249 char *saved_err_prefix = err_print_prefix;
250 err_print_prefix = KERN_CRIT;
251
252 /*
253 * Either a nondismissable error was detected or no
254 * recognized error was detected in the logout frame
255 * -- report the error in either case
256 */
257 printk("%s*CPU %s Error (Vector 0x%x) reported on CPU %d:\n",
258 err_print_prefix,
259 (vector == SCB_Q_PROCERR)?"Correctable":"Uncorrectable",
260 (unsigned int)vector, (int)smp_processor_id());
261
262 ev6_process_logout_frame(mchk_header, 1);
263 dik_show_regs(regs, NULL);
264
265 err_print_prefix = saved_err_prefix;
266 }
267
268 /*
269 * Release the logout frame
270 */
271 wrmces(0x7);
272 mb();
273}
274
diff --git a/arch/alpha/kernel/err_ev7.c b/arch/alpha/kernel/err_ev7.c
new file mode 100644
index 000000000000..bf52ba691957
--- /dev/null
+++ b/arch/alpha/kernel/err_ev7.c
@@ -0,0 +1,289 @@
1/*
2 * linux/arch/alpha/kernel/err_ev7.c
3 *
4 * Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation)
5 *
6 * Error handling code supporting Alpha systems
7 */
8
9#include <linux/init.h>
10#include <linux/pci.h>
11#include <linux/sched.h>
12
13#include <asm/io.h>
14#include <asm/hwrpb.h>
15#include <asm/smp.h>
16#include <asm/err_common.h>
17#include <asm/err_ev7.h>
18
19#include "err_impl.h"
20#include "proto.h"
21
22struct ev7_lf_subpackets *
23ev7_collect_logout_frame_subpackets(struct el_subpacket *el_ptr,
24 struct ev7_lf_subpackets *lf_subpackets)
25{
26 struct el_subpacket *subpacket;
27 int i;
28
29 /*
30 * A Marvel machine check frame is always packaged in an
31 * el_subpacket of class HEADER, type LOGOUT_FRAME.
32 */
33 if (el_ptr->class != EL_CLASS__HEADER ||
34 el_ptr->type != EL_TYPE__HEADER__LOGOUT_FRAME)
35 return NULL;
36
37 /*
38 * It is a logout frame header. Look at the one subpacket.
39 */
40 el_ptr = (struct el_subpacket *)
41 ((unsigned long)el_ptr + el_ptr->length);
42
43 /*
44 * It has to be class PAL, type LOGOUT_FRAME.
45 */
46 if (el_ptr->class != EL_CLASS__PAL ||
47 el_ptr->type != EL_TYPE__PAL__LOGOUT_FRAME)
48 return NULL;
49
50 lf_subpackets->logout = (struct ev7_pal_logout_subpacket *)
51 el_ptr->by_type.raw.data_start;
52
53 /*
54 * Process the subpackets.
55 */
56 subpacket = (struct el_subpacket *)
57 ((unsigned long)el_ptr + el_ptr->length);
58 for (i = 0;
59 subpacket && i < lf_subpackets->logout->subpacket_count;
60 subpacket = (struct el_subpacket *)
61 ((unsigned long)subpacket + subpacket->length), i++) {
62 /*
63 * All subpackets should be class PAL.
64 */
65 if (subpacket->class != EL_CLASS__PAL) {
66 printk("%s**UNEXPECTED SUBPACKET CLASS %d "
67 "IN LOGOUT FRAME (packet %d\n",
68 err_print_prefix, subpacket->class, i);
69 return NULL;
70 }
71
72 /*
73 * Remember the subpacket.
74 */
75 switch(subpacket->type) {
76 case EL_TYPE__PAL__EV7_PROCESSOR:
77 lf_subpackets->ev7 =
78 (struct ev7_pal_processor_subpacket *)
79 subpacket->by_type.raw.data_start;
80 break;
81
82 case EL_TYPE__PAL__EV7_RBOX:
83 lf_subpackets->rbox = (struct ev7_pal_rbox_subpacket *)
84 subpacket->by_type.raw.data_start;
85 break;
86
87 case EL_TYPE__PAL__EV7_ZBOX:
88 lf_subpackets->zbox = (struct ev7_pal_zbox_subpacket *)
89 subpacket->by_type.raw.data_start;
90 break;
91
92 case EL_TYPE__PAL__EV7_IO:
93 lf_subpackets->io = (struct ev7_pal_io_subpacket *)
94 subpacket->by_type.raw.data_start;
95 break;
96
97 case EL_TYPE__PAL__ENV__AMBIENT_TEMPERATURE:
98 case EL_TYPE__PAL__ENV__AIRMOVER_FAN:
99 case EL_TYPE__PAL__ENV__VOLTAGE:
100 case EL_TYPE__PAL__ENV__INTRUSION:
101 case EL_TYPE__PAL__ENV__POWER_SUPPLY:
102 case EL_TYPE__PAL__ENV__LAN:
103 case EL_TYPE__PAL__ENV__HOT_PLUG:
104 lf_subpackets->env[ev7_lf_env_index(subpacket->type)] =
105 (struct ev7_pal_environmental_subpacket *)
106 subpacket->by_type.raw.data_start;
107 break;
108
109 default:
110 /*
111 * Don't know what kind of frame this is.
112 */
113 return NULL;
114 }
115 }
116
117 return lf_subpackets;
118}
119
120void
121ev7_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
122{
123 struct el_subpacket *el_ptr = (struct el_subpacket *)la_ptr;
124 char *saved_err_prefix = err_print_prefix;
125
126 /*
127 * Sync the processor
128 */
129 mb();
130 draina();
131
132 err_print_prefix = KERN_CRIT;
133 printk("%s*CPU %s Error (Vector 0x%x) reported on CPU %d\n",
134 err_print_prefix,
135 (vector == SCB_Q_PROCERR) ? "Correctable" : "Uncorrectable",
136 (unsigned int)vector, (int)smp_processor_id());
137 el_process_subpacket(el_ptr);
138 err_print_prefix = saved_err_prefix;
139
140 /*
141 * Release the logout frame
142 */
143 wrmces(0x7);
144 mb();
145}
146
147static char *el_ev7_processor_subpacket_annotation[] = {
148 "Subpacket Header", "I_STAT", "DC_STAT",
149 "C_ADDR", "C_SYNDROME_1", "C_SYNDROME_0",
150 "C_STAT", "C_STS", "MM_STAT",
151 "EXC_ADDR", "IER_CM", "ISUM",
152 "PAL_BASE", "I_CTL", "PROCESS_CONTEXT",
153 "CBOX_CTL", "CBOX_STP_CTL", "CBOX_ACC_CTL",
154 "CBOX_LCL_SET", "CBOX_GLB_SET", "BBOX_CTL",
155 "BBOX_ERR_STS", "BBOX_ERR_IDX", "CBOX_DDP_ERR_STS",
156 "BBOX_DAT_RMP", NULL
157};
158
159static char *el_ev7_zbox_subpacket_annotation[] = {
160 "Subpacket Header",
161 "ZBOX(0): DRAM_ERR_STATUS_2 / DRAM_ERR_STATUS_1",
162 "ZBOX(0): DRAM_ERROR_CTL / DRAM_ERR_STATUS_3",
163 "ZBOX(0): DIFT_TIMEOUT / DRAM_ERR_ADR",
164 "ZBOX(0): FRC_ERR_ADR / DRAM_MAPPER_CTL",
165 "ZBOX(0): reserved / DIFT_ERR_STATUS",
166 "ZBOX(1): DRAM_ERR_STATUS_2 / DRAM_ERR_STATUS_1",
167 "ZBOX(1): DRAM_ERROR_CTL / DRAM_ERR_STATUS_3",
168 "ZBOX(1): DIFT_TIMEOUT / DRAM_ERR_ADR",
169 "ZBOX(1): FRC_ERR_ADR / DRAM_MAPPER_CTL",
170 "ZBOX(1): reserved / DIFT_ERR_STATUS",
171 "CBOX_CTL", "CBOX_STP_CTL",
172 "ZBOX(0)_ERROR_PA", "ZBOX(1)_ERROR_PA",
173 "ZBOX(0)_ORED_SYNDROME","ZBOX(1)_ORED_SYNDROME",
174 NULL
175};
176
177static char *el_ev7_rbox_subpacket_annotation[] = {
178 "Subpacket Header", "RBOX_CFG", "RBOX_N_CFG",
179 "RBOX_S_CFG", "RBOX_E_CFG", "RBOX_W_CFG",
180 "RBOX_N_ERR", "RBOX_S_ERR", "RBOX_E_ERR",
181 "RBOX_W_ERR", "RBOX_IO_CFG", "RBOX_IO_ERR",
182 "RBOX_L_ERR", "RBOX_WHOAMI", "RBOX_IMASL",
183 "RBOX_INTQ", "RBOX_INT", NULL
184};
185
186static char *el_ev7_io_subpacket_annotation[] = {
187 "Subpacket Header", "IO_ASIC_REV", "IO_SYS_REV",
188 "IO7_UPH", "HPI_CTL", "CRD_CTL",
189 "HEI_CTL", "PO7_ERROR_SUM","PO7_UNCRR_SYM",
190 "PO7_CRRCT_SYM", "PO7_UGBGE_SYM","PO7_ERR_PKT0",
191 "PO7_ERR_PKT1", "reserved", "reserved",
192 "PO0_ERR_SUM", "PO0_TLB_ERR", "PO0_SPL_COMPLT",
193 "PO0_TRANS_SUM", "PO0_FIRST_ERR","PO0_MULT_ERR",
194 "DM CSR PH", "DM CSR PH", "DM CSR PH",
195 "DM CSR PH", "reserved",
196 "PO1_ERR_SUM", "PO1_TLB_ERR", "PO1_SPL_COMPLT",
197 "PO1_TRANS_SUM", "PO1_FIRST_ERR","PO1_MULT_ERR",
198 "DM CSR PH", "DM CSR PH", "DM CSR PH",
199 "DM CSR PH", "reserved",
200 "PO2_ERR_SUM", "PO2_TLB_ERR", "PO2_SPL_COMPLT",
201 "PO2_TRANS_SUM", "PO2_FIRST_ERR","PO2_MULT_ERR",
202 "DM CSR PH", "DM CSR PH", "DM CSR PH",
203 "DM CSR PH", "reserved",
204 "PO3_ERR_SUM", "PO3_TLB_ERR", "PO3_SPL_COMPLT",
205 "PO3_TRANS_SUM", "PO3_FIRST_ERR","PO3_MULT_ERR",
206 "DM CSR PH", "DM CSR PH", "DM CSR PH",
207 "DM CSR PH", "reserved",
208 NULL
209};
210
211static struct el_subpacket_annotation el_ev7_pal_annotations[] = {
212 SUBPACKET_ANNOTATION(EL_CLASS__PAL,
213 EL_TYPE__PAL__EV7_PROCESSOR,
214 1,
215 "EV7 Processor Subpacket",
216 el_ev7_processor_subpacket_annotation),
217 SUBPACKET_ANNOTATION(EL_CLASS__PAL,
218 EL_TYPE__PAL__EV7_ZBOX,
219 1,
220 "EV7 ZBOX Subpacket",
221 el_ev7_zbox_subpacket_annotation),
222 SUBPACKET_ANNOTATION(EL_CLASS__PAL,
223 EL_TYPE__PAL__EV7_RBOX,
224 1,
225 "EV7 RBOX Subpacket",
226 el_ev7_rbox_subpacket_annotation),
227 SUBPACKET_ANNOTATION(EL_CLASS__PAL,
228 EL_TYPE__PAL__EV7_IO,
229 1,
230 "EV7 IO Subpacket",
231 el_ev7_io_subpacket_annotation)
232};
233
234static struct el_subpacket *
235ev7_process_pal_subpacket(struct el_subpacket *header)
236{
237 struct ev7_pal_subpacket *packet;
238
239 if (header->class != EL_CLASS__PAL) {
240 printk("%s ** Unexpected header CLASS %d TYPE %d, aborting\n",
241 err_print_prefix,
242 header->class, header->type);
243 return NULL;
244 }
245
246 packet = (struct ev7_pal_subpacket *)header->by_type.raw.data_start;
247
248 switch(header->type) {
249 case EL_TYPE__PAL__LOGOUT_FRAME:
250 printk("%s*** MCHK occurred on LPID %ld (RBOX %lx)\n",
251 err_print_prefix,
252 packet->by_type.logout.whami,
253 packet->by_type.logout.rbox_whami);
254 el_print_timestamp(&packet->by_type.logout.timestamp);
255 printk("%s EXC_ADDR: %016lx\n"
256 " HALT_CODE: %lx\n",
257 err_print_prefix,
258 packet->by_type.logout.exc_addr,
259 packet->by_type.logout.halt_code);
260 el_process_subpackets(header,
261 packet->by_type.logout.subpacket_count);
262 break;
263 default:
264 printk("%s ** PAL TYPE %d SUBPACKET\n",
265 err_print_prefix,
266 header->type);
267 el_annotate_subpacket(header);
268 break;
269 }
270
271 return (struct el_subpacket *)((unsigned long)header + header->length);
272}
273
274struct el_subpacket_handler ev7_pal_subpacket_handler =
275 SUBPACKET_HANDLER_INIT(EL_CLASS__PAL, ev7_process_pal_subpacket);
276
277void
278ev7_register_error_handlers(void)
279{
280 int i;
281
282 for(i = 0;
283 i<sizeof(el_ev7_pal_annotations)/sizeof(el_ev7_pal_annotations[1]);
284 i++) {
285 cdl_register_subpacket_annotation(&el_ev7_pal_annotations[i]);
286 }
287 cdl_register_subpacket_handler(&ev7_pal_subpacket_handler);
288}
289
diff --git a/arch/alpha/kernel/err_impl.h b/arch/alpha/kernel/err_impl.h
new file mode 100644
index 000000000000..64e9b73809fa
--- /dev/null
+++ b/arch/alpha/kernel/err_impl.h
@@ -0,0 +1,85 @@
1/*
2 * linux/arch/alpha/kernel/err_impl.h
3 *
4 * Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation)
5 *
6 * Contains declarations and macros to support Alpha error handling
7 * implementations.
8 */
9
10union el_timestamp;
11struct el_subpacket;
12struct ev7_lf_subpackets;
13
14struct el_subpacket_annotation {
15 struct el_subpacket_annotation *next;
16 u16 class;
17 u16 type;
18 u16 revision;
19 char *description;
20 char **annotation;
21};
22#define SUBPACKET_ANNOTATION(c, t, r, d, a) {NULL, (c), (t), (r), (d), (a)}
23
24struct el_subpacket_handler {
25 struct el_subpacket_handler *next;
26 u16 class;
27 struct el_subpacket *(*handler)(struct el_subpacket *);
28};
29#define SUBPACKET_HANDLER_INIT(c, h) {NULL, (c), (h)}
30
31/*
32 * Manipulate a field from a register given it's name. defines
33 * for the LSB (__S - shift count) and bitmask (__M) are required
34 *
35 * EXTRACT(u, f) - extracts the field and places it at bit position 0
36 * GEN_MASK(f) - creates an in-position mask for the field
37 */
38#define EXTRACT(u, f) (((u) >> f##__S) & f##__M)
39#define GEN_MASK(f) ((u64)f##__M << f##__S)
40
41/*
42 * err_common.c
43 */
44extern char *err_print_prefix;
45
46extern void mchk_dump_mem(void *, size_t, char **);
47extern void mchk_dump_logout_frame(struct el_common *);
48extern void el_print_timestamp(union el_timestamp *);
49extern void el_process_subpackets(struct el_subpacket *, int);
50extern struct el_subpacket *el_process_subpacket(struct el_subpacket *);
51extern void el_annotate_subpacket(struct el_subpacket *);
52extern void cdl_check_console_data_log(void);
53extern int cdl_register_subpacket_annotation(struct el_subpacket_annotation *);
54extern int cdl_register_subpacket_handler(struct el_subpacket_handler *);
55
56/*
57 * err_ev7.c
58 */
59extern struct ev7_lf_subpackets *
60ev7_collect_logout_frame_subpackets(struct el_subpacket *,
61 struct ev7_lf_subpackets *);
62extern void ev7_register_error_handlers(void);
63extern void ev7_machine_check(u64, u64, struct pt_regs *);
64
65/*
66 * err_ev6.c
67 */
68extern void ev6_register_error_handlers(void);
69extern int ev6_process_logout_frame(struct el_common *, int);
70extern void ev6_machine_check(u64, u64, struct pt_regs *);
71
72/*
73 * err_marvel.c
74 */
75extern void marvel_machine_check(u64, u64, struct pt_regs *);
76extern void marvel_register_error_handlers(void);
77
78/*
79 * err_titan.c
80 */
81extern int titan_process_logout_frame(struct el_common *, int);
82extern void titan_machine_check(u64, u64, struct pt_regs *);
83extern void titan_register_error_handlers(void);
84extern int privateer_process_logout_frame(struct el_common *, int);
85extern void privateer_machine_check(u64, u64, struct pt_regs *);
diff --git a/arch/alpha/kernel/err_marvel.c b/arch/alpha/kernel/err_marvel.c
new file mode 100644
index 000000000000..70b38b1d2af3
--- /dev/null
+++ b/arch/alpha/kernel/err_marvel.c
@@ -0,0 +1,1159 @@
1/*
2 * linux/arch/alpha/kernel/err_marvel.c
3 *
4 * Copyright (C) 2001 Jeff Wiedemeier (Compaq Computer Corporation)
5 *
6 */
7
8#include <linux/init.h>
9#include <linux/pci.h>
10#include <linux/sched.h>
11
12#include <asm/io.h>
13#include <asm/console.h>
14#include <asm/core_marvel.h>
15#include <asm/hwrpb.h>
16#include <asm/smp.h>
17#include <asm/err_common.h>
18#include <asm/err_ev7.h>
19
20#include "err_impl.h"
21#include "proto.h"
22
23static void
24marvel_print_680_frame(struct ev7_lf_subpackets *lf_subpackets)
25{
26#ifdef CONFIG_VERBOSE_MCHECK
27 struct ev7_pal_environmental_subpacket *env;
28 struct { int type; char *name; } ev_packets[] = {
29 { EL_TYPE__PAL__ENV__AMBIENT_TEMPERATURE,
30 "Ambient Temperature" },
31 { EL_TYPE__PAL__ENV__AIRMOVER_FAN,
32 "AirMover / Fan" },
33 { EL_TYPE__PAL__ENV__VOLTAGE,
34 "Voltage" },
35 { EL_TYPE__PAL__ENV__INTRUSION,
36 "Intrusion" },
37 { EL_TYPE__PAL__ENV__POWER_SUPPLY,
38 "Power Supply" },
39 { EL_TYPE__PAL__ENV__LAN,
40 "LAN" },
41 { EL_TYPE__PAL__ENV__HOT_PLUG,
42 "Hot Plug" },
43 { 0, NULL }
44 };
45 int i;
46
47 for (i = 0; ev_packets[i].type != 0; i++) {
48 env = lf_subpackets->env[ev7_lf_env_index(ev_packets[i].type)];
49 if (!env)
50 continue;
51
52 printk("%s**%s event (cabinet %d, drawer %d)\n",
53 err_print_prefix,
54 ev_packets[i].name,
55 env->cabinet,
56 env->drawer);
57 printk("%s Module Type: 0x%x - Unit ID 0x%x - "
58 "Condition 0x%x\n",
59 err_print_prefix,
60 env->module_type,
61 env->unit_id,
62 env->condition);
63 }
64#endif /* CONFIG_VERBOSE_MCHECK */
65}
66
67static int
68marvel_process_680_frame(struct ev7_lf_subpackets *lf_subpackets, int print)
69{
70 int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
71 int i;
72
73 for (i = ev7_lf_env_index(EL_TYPE__PAL__ENV__AMBIENT_TEMPERATURE);
74 i <= ev7_lf_env_index(EL_TYPE__PAL__ENV__HOT_PLUG);
75 i++) {
76 if (lf_subpackets->env[i])
77 status = MCHK_DISPOSITION_REPORT;
78 }
79
80 if (print)
81 marvel_print_680_frame(lf_subpackets);
82
83 return status;
84}
85
86#ifdef CONFIG_VERBOSE_MCHECK
87
88static void
89marvel_print_err_cyc(u64 err_cyc)
90{
91 static char *packet_desc[] = {
92 "No Error",
93 "UNKNOWN",
94 "1 cycle (1 or 2 flit packet)",
95 "2 cycles (3 flit packet)",
96 "9 cycles (18 flit packet)",
97 "10 cycles (19 flit packet)",
98 "UNKNOWN",
99 "UNKNOWN",
100 "UNKNOWN"
101 };
102
103#define IO7__ERR_CYC__ODD_FLT (1UL << 0)
104#define IO7__ERR_CYC__EVN_FLT (1UL << 1)
105#define IO7__ERR_CYC__PACKET__S (6)
106#define IO7__ERR_CYC__PACKET__M (0x7)
107#define IO7__ERR_CYC__LOC (1UL << 5)
108#define IO7__ERR_CYC__CYCLE__S (2)
109#define IO7__ERR_CYC__CYCLE__M (0x7)
110
111 printk("%s Packet In Error: %s\n"
112 "%s Error in %s, cycle %ld%s%s\n",
113 err_print_prefix,
114 packet_desc[EXTRACT(err_cyc, IO7__ERR_CYC__PACKET)],
115 err_print_prefix,
116 (err_cyc & IO7__ERR_CYC__LOC) ? "DATA" : "HEADER",
117 EXTRACT(err_cyc, IO7__ERR_CYC__CYCLE),
118 (err_cyc & IO7__ERR_CYC__ODD_FLT) ? " [ODD Flit]": "",
119 (err_cyc & IO7__ERR_CYC__EVN_FLT) ? " [Even Flit]": "");
120}
121
122static void
123marvel_print_po7_crrct_sym(u64 crrct_sym)
124{
125#define IO7__PO7_CRRCT_SYM__SYN__S (0)
126#define IO7__PO7_CRRCT_SYM__SYN__M (0x7f)
127#define IO7__PO7_CRRCT_SYM__ERR_CYC__S (7) /* ERR_CYC + ODD_FLT + EVN_FLT */
128#define IO7__PO7_CRRCT_SYM__ERR_CYC__M (0x1ff)
129
130
131 printk("%s Correctable Error Symptoms:\n"
132 "%s Syndrome: 0x%lx\n",
133 err_print_prefix,
134 err_print_prefix, EXTRACT(crrct_sym, IO7__PO7_CRRCT_SYM__SYN));
135 marvel_print_err_cyc(EXTRACT(crrct_sym, IO7__PO7_CRRCT_SYM__ERR_CYC));
136}
137
138static void
139marvel_print_po7_uncrr_sym(u64 uncrr_sym, u64 valid_mask)
140{
141 static char *clk_names[] = { "_h[0]", "_h[1]", "_n[0]", "_n[1]" };
142 static char *clk_decode[] = {
143 "No Error",
144 "One extra rising edge",
145 "Two extra rising edges",
146 "Lost one clock"
147 };
148 static char *port_names[] = { "Port 0", "Port 1",
149 "Port 2", "Port 3",
150 "Unknown Port", "Unknown Port",
151 "Unknown Port", "Port 7" };
152 int scratch, i;
153
154#define IO7__PO7_UNCRR_SYM__SYN__S (0)
155#define IO7__PO7_UNCRR_SYM__SYN__M (0x7f)
156#define IO7__PO7_UNCRR_SYM__ERR_CYC__S (7) /* ERR_CYC + ODD_FLT... */
157#define IO7__PO7_UNCRR_SYM__ERR_CYC__M (0x1ff) /* ... + EVN_FLT */
158#define IO7__PO7_UNCRR_SYM__CLK__S (16)
159#define IO7__PO7_UNCRR_SYM__CLK__M (0xff)
160#define IO7__PO7_UNCRR_SYM__CDT_OVF_TO__REQ (1UL << 24)
161#define IO7__PO7_UNCRR_SYM__CDT_OVF_TO__RIO (1UL << 25)
162#define IO7__PO7_UNCRR_SYM__CDT_OVF_TO__WIO (1UL << 26)
163#define IO7__PO7_UNCRR_SYM__CDT_OVF_TO__BLK (1UL << 27)
164#define IO7__PO7_UNCRR_SYM__CDT_OVF_TO__NBK (1UL << 28)
165#define IO7__PO7_UNCRR_SYM__OVF__READIO (1UL << 29)
166#define IO7__PO7_UNCRR_SYM__OVF__WRITEIO (1UL << 30)
167#define IO7__PO7_UNCRR_SYM__OVF__FWD (1UL << 31)
168#define IO7__PO7_UNCRR_SYM__VICTIM_SP__S (32)
169#define IO7__PO7_UNCRR_SYM__VICTIM_SP__M (0xff)
170#define IO7__PO7_UNCRR_SYM__DETECT_SP__S (40)
171#define IO7__PO7_UNCRR_SYM__DETECT_SP__M (0xff)
172#define IO7__PO7_UNCRR_SYM__STRV_VTR__S (48)
173#define IO7__PO7_UNCRR_SYM__STRV_VTR__M (0x3ff)
174
175#define IO7__STRV_VTR__LSI__INTX__S (0)
176#define IO7__STRV_VTR__LSI__INTX__M (0x3)
177#define IO7__STRV_VTR__LSI__SLOT__S (2)
178#define IO7__STRV_VTR__LSI__SLOT__M (0x7)
179#define IO7__STRV_VTR__LSI__BUS__S (5)
180#define IO7__STRV_VTR__LSI__BUS__M (0x3)
181#define IO7__STRV_VTR__MSI__INTNUM__S (0)
182#define IO7__STRV_VTR__MSI__INTNUM__M (0x1ff)
183#define IO7__STRV_VTR__IS_MSI (1UL << 9)
184
185 printk("%s Uncorrectable Error Symptoms:\n", err_print_prefix);
186 uncrr_sym &= valid_mask;
187
188 if (EXTRACT(valid_mask, IO7__PO7_UNCRR_SYM__SYN))
189 printk("%s Syndrome: 0x%lx\n",
190 err_print_prefix,
191 EXTRACT(uncrr_sym, IO7__PO7_UNCRR_SYM__SYN));
192
193 if (EXTRACT(valid_mask, IO7__PO7_UNCRR_SYM__ERR_CYC))
194 marvel_print_err_cyc(EXTRACT(uncrr_sym,
195 IO7__PO7_UNCRR_SYM__ERR_CYC));
196
197 scratch = EXTRACT(uncrr_sym, IO7__PO7_UNCRR_SYM__CLK);
198 for (i = 0; i < 4; i++, scratch >>= 2) {
199 if (scratch & 0x3)
200 printk("%s Clock %s: %s\n",
201 err_print_prefix,
202 clk_names[i], clk_decode[scratch & 0x3]);
203 }
204
205 if (uncrr_sym & IO7__PO7_UNCRR_SYM__CDT_OVF_TO__REQ)
206 printk("%s REQ Credit Timeout or Overflow\n",
207 err_print_prefix);
208 if (uncrr_sym & IO7__PO7_UNCRR_SYM__CDT_OVF_TO__RIO)
209 printk("%s RIO Credit Timeout or Overflow\n",
210 err_print_prefix);
211 if (uncrr_sym & IO7__PO7_UNCRR_SYM__CDT_OVF_TO__WIO)
212 printk("%s WIO Credit Timeout or Overflow\n",
213 err_print_prefix);
214 if (uncrr_sym & IO7__PO7_UNCRR_SYM__CDT_OVF_TO__BLK)
215 printk("%s BLK Credit Timeout or Overflow\n",
216 err_print_prefix);
217 if (uncrr_sym & IO7__PO7_UNCRR_SYM__CDT_OVF_TO__NBK)
218 printk("%s NBK Credit Timeout or Overflow\n",
219 err_print_prefix);
220
221 if (uncrr_sym & IO7__PO7_UNCRR_SYM__OVF__READIO)
222 printk("%s Read I/O Buffer Overflow\n",
223 err_print_prefix);
224 if (uncrr_sym & IO7__PO7_UNCRR_SYM__OVF__WRITEIO)
225 printk("%s Write I/O Buffer Overflow\n",
226 err_print_prefix);
227 if (uncrr_sym & IO7__PO7_UNCRR_SYM__OVF__FWD)
228 printk("%s FWD Buffer Overflow\n",
229 err_print_prefix);
230
231 if ((scratch = EXTRACT(uncrr_sym, IO7__PO7_UNCRR_SYM__VICTIM_SP))) {
232 int lost = scratch & (1UL << 4);
233 scratch &= ~lost;
234 for (i = 0; i < 8; i++, scratch >>= 1) {
235 if (!(scratch & 1))
236 continue;
237 printk("%s Error Response sent to %s",
238 err_print_prefix, port_names[i]);
239 }
240 if (lost)
241 printk("%s Lost Error sent somewhere else\n",
242 err_print_prefix);
243 }
244
245 if ((scratch = EXTRACT(uncrr_sym, IO7__PO7_UNCRR_SYM__DETECT_SP))) {
246 for (i = 0; i < 8; i++, scratch >>= 1) {
247 if (!(scratch & 1))
248 continue;
249 printk("%s Error Reported by %s",
250 err_print_prefix, port_names[i]);
251 }
252 }
253
254 if (EXTRACT(valid_mask, IO7__PO7_UNCRR_SYM__STRV_VTR)) {
255 char starvation_message[80];
256
257 scratch = EXTRACT(uncrr_sym, IO7__PO7_UNCRR_SYM__STRV_VTR);
258 if (scratch & IO7__STRV_VTR__IS_MSI)
259 sprintf(starvation_message,
260 "MSI Interrupt 0x%x",
261 EXTRACT(scratch, IO7__STRV_VTR__MSI__INTNUM));
262 else
263 sprintf(starvation_message,
264 "LSI INT%c for Bus:Slot (%d:%d)\n",
265 'A' + EXTRACT(scratch,
266 IO7__STRV_VTR__LSI__INTX),
267 EXTRACT(scratch, IO7__STRV_VTR__LSI__BUS),
268 EXTRACT(scratch, IO7__STRV_VTR__LSI__SLOT));
269
270 printk("%s Starvation Int Trigger By: %s\n",
271 err_print_prefix, starvation_message);
272 }
273}
274
275static void
276marvel_print_po7_ugbge_sym(u64 ugbge_sym)
277{
278 char opcode_str[10];
279
280#define IO7__PO7_UGBGE_SYM__UPH_PKT_OFF__S (6)
281#define IO7__PO7_UGBGE_SYM__UPH_PKT_OFF__M (0xfffffffful)
282#define IO7__PO7_UGBGE_SYM__UPH_OPCODE__S (40)
283#define IO7__PO7_UGBGE_SYM__UPH_OPCODE__M (0xff)
284#define IO7__PO7_UGBGE_SYM__UPH_SRC_PORT__S (48)
285#define IO7__PO7_UGBGE_SYM__UPH_SRC_PORT__M (0xf)
286#define IO7__PO7_UGBGE_SYM__UPH_DEST_PID__S (52)
287#define IO7__PO7_UGBGE_SYM__UPH_DEST_PID__M (0x7ff)
288#define IO7__PO7_UGBGE_SYM__VALID (1UL << 63)
289
290 if (!(ugbge_sym & IO7__PO7_UGBGE_SYM__VALID))
291 return;
292
293 switch(EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_OPCODE)) {
294 case 0x51:
295 sprintf(opcode_str, "Wr32");
296 break;
297 case 0x50:
298 sprintf(opcode_str, "WrQW");
299 break;
300 case 0x54:
301 sprintf(opcode_str, "WrIPR");
302 break;
303 case 0xD8:
304 sprintf(opcode_str, "Victim");
305 break;
306 case 0xC5:
307 sprintf(opcode_str, "BlkIO");
308 break;
309 default:
310 sprintf(opcode_str, "0x%lx\n",
311 EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_OPCODE));
312 break;
313 }
314
315 printk("%s Up Hose Garbage Symptom:\n"
316 "%s Source Port: %ld - Dest PID: %ld - OpCode: %s\n",
317 err_print_prefix,
318 err_print_prefix,
319 EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_SRC_PORT),
320 EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_DEST_PID),
321 opcode_str);
322
323 if (0xC5 != EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_OPCODE))
324 printk("%s Packet Offset 0x%08lx\n",
325 err_print_prefix,
326 EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_PKT_OFF));
327}
328
329static void
330marvel_print_po7_err_sum(struct ev7_pal_io_subpacket *io)
331{
332 u64 uncrr_sym_valid = 0;
333
334#define IO7__PO7_ERRSUM__CR_SBE (1UL << 32)
335#define IO7__PO7_ERRSUM__CR_SBE2 (1UL << 33)
336#define IO7__PO7_ERRSUM__CR_PIO_WBYTE (1UL << 34)
337#define IO7__PO7_ERRSUM__CR_CSR_NXM (1UL << 35)
338#define IO7__PO7_ERRSUM__CR_RPID_ACV (1UL << 36)
339#define IO7__PO7_ERRSUM__CR_RSP_NXM (1UL << 37)
340#define IO7__PO7_ERRSUM__CR_ERR_RESP (1UL << 38)
341#define IO7__PO7_ERRSUM__CR_CLK_DERR (1UL << 39)
342#define IO7__PO7_ERRSUM__CR_DAT_DBE (1UL << 40)
343#define IO7__PO7_ERRSUM__CR_DAT_GRBG (1UL << 41)
344#define IO7__PO7_ERRSUM__MAF_TO (1UL << 42)
345#define IO7__PO7_ERRSUM__UGBGE (1UL << 43)
346#define IO7__PO7_ERRSUM__UN_MAF_LOST (1UL << 44)
347#define IO7__PO7_ERRSUM__UN_PKT_OVF (1UL << 45)
348#define IO7__PO7_ERRSUM__UN_CDT_OVF (1UL << 46)
349#define IO7__PO7_ERRSUM__UN_DEALLOC (1UL << 47)
350#define IO7__PO7_ERRSUM__BH_CDT_TO (1UL << 51)
351#define IO7__PO7_ERRSUM__BH_CLK_HDR (1UL << 52)
352#define IO7__PO7_ERRSUM__BH_DBE_HDR (1UL << 53)
353#define IO7__PO7_ERRSUM__BH_GBG_HDR (1UL << 54)
354#define IO7__PO7_ERRSUM__BH_BAD_CMD (1UL << 55)
355#define IO7__PO7_ERRSUM__HLT_INT (1UL << 56)
356#define IO7__PO7_ERRSUM__HP_INT (1UL << 57)
357#define IO7__PO7_ERRSUM__CRD_INT (1UL << 58)
358#define IO7__PO7_ERRSUM__STV_INT (1UL << 59)
359#define IO7__PO7_ERRSUM__HRD_INT (1UL << 60)
360#define IO7__PO7_ERRSUM__BH_SUM (1UL << 61)
361#define IO7__PO7_ERRSUM__ERR_LST (1UL << 62)
362#define IO7__PO7_ERRSUM__ERR_VALID (1UL << 63)
363
364#define IO7__PO7_ERRSUM__ERR_MASK (IO7__PO7_ERRSUM__ERR_VALID | \
365 IO7__PO7_ERRSUM__CR_SBE)
366
367 /*
368 * Single bit errors aren't covered by ERR_VALID.
369 */
370 if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_SBE) {
371 printk("%s %sSingle Bit Error(s) detected/corrected\n",
372 err_print_prefix,
373 (io->po7_error_sum & IO7__PO7_ERRSUM__CR_SBE2)
374 ? "Multiple " : "");
375 marvel_print_po7_crrct_sym(io->po7_crrct_sym);
376 }
377
378 /*
379 * Neither are the interrupt status bits
380 */
381 if (io->po7_error_sum & IO7__PO7_ERRSUM__HLT_INT)
382 printk("%s Halt Interrupt posted", err_print_prefix);
383 if (io->po7_error_sum & IO7__PO7_ERRSUM__HP_INT) {
384 printk("%s Hot Plug Event Interrupt posted",
385 err_print_prefix);
386 uncrr_sym_valid |= GEN_MASK(IO7__PO7_UNCRR_SYM__DETECT_SP);
387 }
388 if (io->po7_error_sum & IO7__PO7_ERRSUM__CRD_INT)
389 printk("%s Correctable Error Interrupt posted",
390 err_print_prefix);
391 if (io->po7_error_sum & IO7__PO7_ERRSUM__STV_INT) {
392 printk("%s Starvation Interrupt posted", err_print_prefix);
393 uncrr_sym_valid |= GEN_MASK(IO7__PO7_UNCRR_SYM__STRV_VTR);
394 }
395 if (io->po7_error_sum & IO7__PO7_ERRSUM__HRD_INT) {
396 printk("%s Hard Error Interrupt posted", err_print_prefix);
397 uncrr_sym_valid |= GEN_MASK(IO7__PO7_UNCRR_SYM__DETECT_SP);
398 }
399
400 /*
401 * Everything else is valid only with ERR_VALID, so skip to the end
402 * (uncrr_sym check) unless ERR_VALID is set.
403 */
404 if (!(io->po7_error_sum & IO7__PO7_ERRSUM__ERR_VALID))
405 goto check_uncrr_sym;
406
407 /*
408 * Since ERR_VALID is set, VICTIM_SP in uncrr_sym is valid.
409 * For bits [29:0] to also be valid, the following bits must
410 * not be set:
411 * CR_PIO_WBYTE CR_CSR_NXM CR_RSP_NXM
412 * CR_ERR_RESP MAF_TO
413 */
414 uncrr_sym_valid |= GEN_MASK(IO7__PO7_UNCRR_SYM__VICTIM_SP);
415 if (!(io->po7_error_sum & (IO7__PO7_ERRSUM__CR_PIO_WBYTE |
416 IO7__PO7_ERRSUM__CR_CSR_NXM |
417 IO7__PO7_ERRSUM__CR_RSP_NXM |
418 IO7__PO7_ERRSUM__CR_ERR_RESP |
419 IO7__PO7_ERRSUM__MAF_TO)))
420 uncrr_sym_valid |= 0x3ffffffful;
421
422 if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_PIO_WBYTE)
423 printk("%s Write byte into IO7 CSR\n", err_print_prefix);
424 if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_CSR_NXM)
425 printk("%s PIO to non-existent CSR\n", err_print_prefix);
426 if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_RPID_ACV)
427 printk("%s Bus Requester PID (Access Violation)\n",
428 err_print_prefix);
429 if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_RSP_NXM)
430 printk("%s Received NXM response from EV7\n",
431 err_print_prefix);
432 if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_ERR_RESP)
433 printk("%s Received ERROR RESPONSE\n", err_print_prefix);
434 if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_CLK_DERR)
435 printk("%s Clock error on data flit\n", err_print_prefix);
436 if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_DAT_DBE)
437 printk("%s Double Bit Error Data Error Detected\n",
438 err_print_prefix);
439 if (io->po7_error_sum & IO7__PO7_ERRSUM__CR_DAT_GRBG)
440 printk("%s Garbage Encoding Detected on the data\n",
441 err_print_prefix);
442 if (io->po7_error_sum & IO7__PO7_ERRSUM__UGBGE) {
443 printk("%s Garbage Encoding sent up hose\n",
444 err_print_prefix);
445 marvel_print_po7_ugbge_sym(io->po7_ugbge_sym);
446 }
447 if (io->po7_error_sum & IO7__PO7_ERRSUM__UN_MAF_LOST)
448 printk("%s Orphan response (unexpected response)\n",
449 err_print_prefix);
450 if (io->po7_error_sum & IO7__PO7_ERRSUM__UN_PKT_OVF)
451 printk("%s Down hose packet overflow\n", err_print_prefix);
452 if (io->po7_error_sum & IO7__PO7_ERRSUM__UN_CDT_OVF)
453 printk("%s Down hose credit overflow\n", err_print_prefix);
454 if (io->po7_error_sum & IO7__PO7_ERRSUM__UN_DEALLOC)
455 printk("%s Unexpected or bad dealloc field\n",
456 err_print_prefix);
457
458 /*
459 * The black hole events.
460 */
461 if (io->po7_error_sum & IO7__PO7_ERRSUM__MAF_TO)
462 printk("%s BLACK HOLE: Timeout for all responses\n",
463 err_print_prefix);
464 if (io->po7_error_sum & IO7__PO7_ERRSUM__BH_CDT_TO)
465 printk("%s BLACK HOLE: Credit Timeout\n", err_print_prefix);
466 if (io->po7_error_sum & IO7__PO7_ERRSUM__BH_CLK_HDR)
467 printk("%s BLACK HOLE: Clock check on header\n",
468 err_print_prefix);
469 if (io->po7_error_sum & IO7__PO7_ERRSUM__BH_DBE_HDR)
470 printk("%s BLACK HOLE: Uncorrectable Error on header\n",
471 err_print_prefix);
472 if (io->po7_error_sum & IO7__PO7_ERRSUM__BH_GBG_HDR)
473 printk("%s BLACK HOLE: Garbage on header\n",
474 err_print_prefix);
475 if (io->po7_error_sum & IO7__PO7_ERRSUM__BH_BAD_CMD)
476 printk("%s BLACK HOLE: Bad EV7 command\n",
477 err_print_prefix);
478
479 if (io->po7_error_sum & IO7__PO7_ERRSUM__ERR_LST)
480 printk("%s Lost Error\n", err_print_prefix);
481
482 printk("%s Failing Packet:\n"
483 "%s Cycle 1: %016lx\n"
484 "%s Cycle 2: %016lx\n",
485 err_print_prefix,
486 err_print_prefix, io->po7_err_pkt0,
487 err_print_prefix, io->po7_err_pkt1);
488 /*
489 * If there are any valid bits in UNCRR sym for this err,
490 * print UNCRR_SYM as well.
491 */
492check_uncrr_sym:
493 if (uncrr_sym_valid)
494 marvel_print_po7_uncrr_sym(io->po7_uncrr_sym, uncrr_sym_valid);
495}
496
497static void
498marvel_print_pox_tlb_err(u64 tlb_err)
499{
500 static char *tlb_errors[] = {
501 "No Error",
502 "North Port Signaled Error fetching TLB entry",
503 "PTE invalid or UCC or GBG error on this entry",
504 "Address did not hit any DMA window"
505 };
506
507#define IO7__POX_TLBERR__ERR_VALID (1UL << 63)
508#define IO7__POX_TLBERR__ERRCODE__S (0)
509#define IO7__POX_TLBERR__ERRCODE__M (0x3)
510#define IO7__POX_TLBERR__ERR_TLB_PTR__S (3)
511#define IO7__POX_TLBERR__ERR_TLB_PTR__M (0x7)
512#define IO7__POX_TLBERR__FADDR__S (6)
513#define IO7__POX_TLBERR__FADDR__M (0x3fffffffffful)
514
515 if (!(tlb_err & IO7__POX_TLBERR__ERR_VALID))
516 return;
517
518 printk("%s TLB Error on index 0x%lx:\n"
519 "%s - %s\n"
520 "%s - Addr: 0x%016lx\n",
521 err_print_prefix,
522 EXTRACT(tlb_err, IO7__POX_TLBERR__ERR_TLB_PTR),
523 err_print_prefix,
524 tlb_errors[EXTRACT(tlb_err, IO7__POX_TLBERR__ERRCODE)],
525 err_print_prefix,
526 EXTRACT(tlb_err, IO7__POX_TLBERR__FADDR) << 6);
527}
528
529static void
530marvel_print_pox_spl_cmplt(u64 spl_cmplt)
531{
532 char message[80];
533
534#define IO7__POX_SPLCMPLT__MESSAGE__S (0)
535#define IO7__POX_SPLCMPLT__MESSAGE__M (0x0fffffffful)
536#define IO7__POX_SPLCMPLT__SOURCE_BUS__S (40)
537#define IO7__POX_SPLCMPLT__SOURCE_BUS__M (0xfful)
538#define IO7__POX_SPLCMPLT__SOURCE_DEV__S (35)
539#define IO7__POX_SPLCMPLT__SOURCE_DEV__M (0x1ful)
540#define IO7__POX_SPLCMPLT__SOURCE_FUNC__S (32)
541#define IO7__POX_SPLCMPLT__SOURCE_FUNC__M (0x07ul)
542
543#define IO7__POX_SPLCMPLT__MSG_CLASS__S (28)
544#define IO7__POX_SPLCMPLT__MSG_CLASS__M (0xf)
545#define IO7__POX_SPLCMPLT__MSG_INDEX__S (20)
546#define IO7__POX_SPLCMPLT__MSG_INDEX__M (0xff)
547#define IO7__POX_SPLCMPLT__MSG_CLASSINDEX__S (20)
548#define IO7__POX_SPLCMPLT__MSG_CLASSINDEX__M (0xfff)
549#define IO7__POX_SPLCMPLT__REM_LOWER_ADDR__S (12)
550#define IO7__POX_SPLCMPLT__REM_LOWER_ADDR__M (0x7f)
551#define IO7__POX_SPLCMPLT__REM_BYTE_COUNT__S (0)
552#define IO7__POX_SPLCMPLT__REM_BYTE_COUNT__M (0xfff)
553
554 printk("%s Split Completion Error:\n"
555 "%s Source (Bus:Dev:Func): %ld:%ld:%ld\n",
556 err_print_prefix,
557 err_print_prefix,
558 EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__SOURCE_BUS),
559 EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__SOURCE_DEV),
560 EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__SOURCE_FUNC));
561
562 switch(EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__MSG_CLASSINDEX)) {
563 case 0x000:
564 sprintf(message, "Normal completion");
565 break;
566 case 0x100:
567 sprintf(message, "Bridge - Master Abort");
568 break;
569 case 0x101:
570 sprintf(message, "Bridge - Target Abort");
571 break;
572 case 0x102:
573 sprintf(message, "Bridge - Uncorrectable Write Data Error");
574 break;
575 case 0x200:
576 sprintf(message, "Byte Count Out of Range");
577 break;
578 case 0x201:
579 sprintf(message, "Uncorrectable Split Write Data Error");
580 break;
581 default:
582 sprintf(message, "%08lx\n",
583 EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__MESSAGE));
584 break;
585 }
586 printk("%s Message: %s\n", err_print_prefix, message);
587}
588
589static void
590marvel_print_pox_trans_sum(u64 trans_sum)
591{
592 char *pcix_cmd[] = { "Interrupt Acknowledge",
593 "Special Cycle",
594 "I/O Read",
595 "I/O Write",
596 "Reserved",
597 "Reserved / Device ID Message",
598 "Memory Read",
599 "Memory Write",
600 "Reserved / Alias to Memory Read Block",
601 "Reserved / Alias to Memory Write Block",
602 "Configuration Read",
603 "Configuration Write",
604 "Memory Read Multiple / Split Completion",
605 "Dual Address Cycle",
606 "Memory Read Line / Memory Read Block",
607 "Memory Write and Invalidate / Memory Write Block"
608 };
609
610#define IO7__POX_TRANSUM__PCI_ADDR__S (0)
611#define IO7__POX_TRANSUM__PCI_ADDR__M (0x3fffffffffffful)
612#define IO7__POX_TRANSUM__DAC (1UL << 50)
613#define IO7__POX_TRANSUM__PCIX_MASTER_SLOT__S (52)
614#define IO7__POX_TRANSUM__PCIX_MASTER_SLOT__M (0xf)
615#define IO7__POX_TRANSUM__PCIX_CMD__S (56)
616#define IO7__POX_TRANSUM__PCIX_CMD__M (0xf)
617#define IO7__POX_TRANSUM__ERR_VALID (1UL << 63)
618
619 if (!(trans_sum & IO7__POX_TRANSUM__ERR_VALID))
620 return;
621
622 printk("%s Transaction Summary:\n"
623 "%s Command: 0x%lx - %s\n"
624 "%s Address: 0x%016lx%s\n"
625 "%s PCI-X Master Slot: 0x%lx\n",
626 err_print_prefix,
627 err_print_prefix,
628 EXTRACT(trans_sum, IO7__POX_TRANSUM__PCIX_CMD),
629 pcix_cmd[EXTRACT(trans_sum, IO7__POX_TRANSUM__PCIX_CMD)],
630 err_print_prefix,
631 EXTRACT(trans_sum, IO7__POX_TRANSUM__PCI_ADDR),
632 (trans_sum & IO7__POX_TRANSUM__DAC) ? " (DAC)" : "",
633 err_print_prefix,
634 EXTRACT(trans_sum, IO7__POX_TRANSUM__PCIX_MASTER_SLOT));
635}
636
637static void
638marvel_print_pox_err(u64 err_sum, struct ev7_pal_io_one_port *port)
639{
640#define IO7__POX_ERRSUM__AGP_REQQ_OVFL (1UL << 4)
641#define IO7__POX_ERRSUM__AGP_SYNC_ERR (1UL << 5)
642#define IO7__POX_ERRSUM__MRETRY_TO (1UL << 6)
643#define IO7__POX_ERRSUM__PCIX_UX_SPL (1UL << 7)
644#define IO7__POX_ERRSUM__PCIX_SPLIT_TO (1UL << 8)
645#define IO7__POX_ERRSUM__PCIX_DISCARD_SPL (1UL << 9)
646#define IO7__POX_ERRSUM__DMA_RD_TO (1UL << 10)
647#define IO7__POX_ERRSUM__CSR_NXM_RD (1UL << 11)
648#define IO7__POX_ERRSUM__CSR_NXM_WR (1UL << 12)
649#define IO7__POX_ERRSUM__DMA_TO (1UL << 13)
650#define IO7__POX_ERRSUM__ALL_MABORTS (1UL << 14)
651#define IO7__POX_ERRSUM__MABORT (1UL << 15)
652#define IO7__POX_ERRSUM__MABORT_MASK (IO7__POX_ERRSUM__ALL_MABORTS|\
653 IO7__POX_ERRSUM__MABORT)
654#define IO7__POX_ERRSUM__PT_TABORT (1UL << 16)
655#define IO7__POX_ERRSUM__PM_TABORT (1UL << 17)
656#define IO7__POX_ERRSUM__TABORT_MASK (IO7__POX_ERRSUM__PT_TABORT | \
657 IO7__POX_ERRSUM__PM_TABORT)
658#define IO7__POX_ERRSUM__SERR (1UL << 18)
659#define IO7__POX_ERRSUM__ADDRERR_STB (1UL << 19)
660#define IO7__POX_ERRSUM__DETECTED_SERR (1UL << 20)
661#define IO7__POX_ERRSUM__PERR (1UL << 21)
662#define IO7__POX_ERRSUM__DATAERR_STB_NIOW (1UL << 22)
663#define IO7__POX_ERRSUM__DETECTED_PERR (1UL << 23)
664#define IO7__POX_ERRSUM__PM_PERR (1UL << 24)
665#define IO7__POX_ERRSUM__PT_SCERROR (1UL << 26)
666#define IO7__POX_ERRSUM__HUNG_BUS (1UL << 28)
667#define IO7__POX_ERRSUM__UPE_ERROR__S (51)
668#define IO7__POX_ERRSUM__UPE_ERROR__M (0xffUL)
669#define IO7__POX_ERRSUM__UPE_ERROR GEN_MASK(IO7__POX_ERRSUM__UPE_ERROR)
670#define IO7__POX_ERRSUM__TLB_ERR (1UL << 59)
671#define IO7__POX_ERRSUM__ERR_VALID (1UL << 63)
672
673#define IO7__POX_ERRSUM__TRANS_SUM__MASK (IO7__POX_ERRSUM__MRETRY_TO | \
674 IO7__POX_ERRSUM__PCIX_UX_SPL | \
675 IO7__POX_ERRSUM__PCIX_SPLIT_TO | \
676 IO7__POX_ERRSUM__DMA_TO | \
677 IO7__POX_ERRSUM__MABORT_MASK | \
678 IO7__POX_ERRSUM__TABORT_MASK | \
679 IO7__POX_ERRSUM__SERR | \
680 IO7__POX_ERRSUM__ADDRERR_STB | \
681 IO7__POX_ERRSUM__PERR | \
682 IO7__POX_ERRSUM__DATAERR_STB_NIOW |\
683 IO7__POX_ERRSUM__DETECTED_PERR | \
684 IO7__POX_ERRSUM__PM_PERR | \
685 IO7__POX_ERRSUM__PT_SCERROR | \
686 IO7__POX_ERRSUM__UPE_ERROR)
687
688 if (!(err_sum & IO7__POX_ERRSUM__ERR_VALID))
689 return;
690
691 /*
692 * First the transaction summary errors
693 */
694 if (err_sum & IO7__POX_ERRSUM__MRETRY_TO)
695 printk("%s IO7 Master Retry Timeout expired\n",
696 err_print_prefix);
697 if (err_sum & IO7__POX_ERRSUM__PCIX_UX_SPL)
698 printk("%s Unexpected Split Completion\n",
699 err_print_prefix);
700 if (err_sum & IO7__POX_ERRSUM__PCIX_SPLIT_TO)
701 printk("%s IO7 Split Completion Timeout expired\n",
702 err_print_prefix);
703 if (err_sum & IO7__POX_ERRSUM__DMA_TO)
704 printk("%s Hung bus during DMA transaction\n",
705 err_print_prefix);
706 if (err_sum & IO7__POX_ERRSUM__MABORT_MASK)
707 printk("%s Master Abort\n", err_print_prefix);
708 if (err_sum & IO7__POX_ERRSUM__PT_TABORT)
709 printk("%s IO7 Asserted Target Abort\n", err_print_prefix);
710 if (err_sum & IO7__POX_ERRSUM__PM_TABORT)
711 printk("%s IO7 Received Target Abort\n", err_print_prefix);
712 if (err_sum & IO7__POX_ERRSUM__ADDRERR_STB) {
713 printk("%s Address or PCI-X Attribute Parity Error\n",
714 err_print_prefix);
715 if (err_sum & IO7__POX_ERRSUM__SERR)
716 printk("%s IO7 Asserted SERR\n", err_print_prefix);
717 }
718 if (err_sum & IO7__POX_ERRSUM__PERR) {
719 if (err_sum & IO7__POX_ERRSUM__DATAERR_STB_NIOW)
720 printk("%s IO7 Detected Data Parity Error\n",
721 err_print_prefix);
722 else
723 printk("%s Split Completion Response with "
724 "Parity Error\n", err_print_prefix);
725 }
726 if (err_sum & IO7__POX_ERRSUM__DETECTED_PERR)
727 printk("%s PERR detected\n", err_print_prefix);
728 if (err_sum & IO7__POX_ERRSUM__PM_PERR)
729 printk("%s PERR while IO7 is master\n", err_print_prefix);
730 if (err_sum & IO7__POX_ERRSUM__PT_SCERROR) {
731 printk("%s IO7 Received Split Completion Error message\n",
732 err_print_prefix);
733 marvel_print_pox_spl_cmplt(port->pox_spl_cmplt);
734 }
735 if (err_sum & IO7__POX_ERRSUM__UPE_ERROR) {
736 unsigned int upe_error = EXTRACT(err_sum,
737 IO7__POX_ERRSUM__UPE_ERROR);
738 int i;
739 static char *upe_errors[] = {
740 "Parity Error on MSI write data",
741 "MSI read (MSI window is write only",
742 "TLB - Invalid WR transaction",
743 "TLB - Invalid RD transaction",
744 "DMA - WR error (see north port)",
745 "DMA - RD error (see north port)",
746 "PPR - WR error (see north port)",
747 "PPR - RD error (see north port)"
748 };
749
750 printk("%s UPE Error:\n", err_print_prefix);
751 for (i = 0; i < 8; i++) {
752 if (upe_error & (1 << i))
753 printk("%s %s\n", err_print_prefix,
754 upe_errors[i]);
755 }
756 }
757
758 /*
759 * POx_TRANS_SUM, if appropriate.
760 */
761 if (err_sum & IO7__POX_ERRSUM__TRANS_SUM__MASK)
762 marvel_print_pox_trans_sum(port->pox_trans_sum);
763
764 /*
765 * Then TLB_ERR.
766 */
767 if (err_sum & IO7__POX_ERRSUM__TLB_ERR) {
768 printk("%s TLB ERROR\n", err_print_prefix);
769 marvel_print_pox_tlb_err(port->pox_tlb_err);
770 }
771
772 /*
773 * And the single bit status errors.
774 */
775 if (err_sum & IO7__POX_ERRSUM__AGP_REQQ_OVFL)
776 printk("%s AGP Request Queue Overflow\n", err_print_prefix);
777 if (err_sum & IO7__POX_ERRSUM__AGP_SYNC_ERR)
778 printk("%s AGP Sync Error\n", err_print_prefix);
779 if (err_sum & IO7__POX_ERRSUM__PCIX_DISCARD_SPL)
780 printk("%s Discarded split completion\n", err_print_prefix);
781 if (err_sum & IO7__POX_ERRSUM__DMA_RD_TO)
782 printk("%s DMA Read Timeout\n", err_print_prefix);
783 if (err_sum & IO7__POX_ERRSUM__CSR_NXM_RD)
784 printk("%s CSR NXM READ\n", err_print_prefix);
785 if (err_sum & IO7__POX_ERRSUM__CSR_NXM_WR)
786 printk("%s CSR NXM WRITE\n", err_print_prefix);
787 if (err_sum & IO7__POX_ERRSUM__DETECTED_SERR)
788 printk("%s SERR detected\n", err_print_prefix);
789 if (err_sum & IO7__POX_ERRSUM__HUNG_BUS)
790 printk("%s HUNG BUS detected\n", err_print_prefix);
791}
792
793#endif /* CONFIG_VERBOSE_MCHECK */
794
795static struct ev7_pal_io_subpacket *
796marvel_find_io7_with_error(struct ev7_lf_subpackets *lf_subpackets)
797{
798 struct ev7_pal_io_subpacket *io = lf_subpackets->io;
799 struct io7 *io7;
800 int i;
801
802 /*
803 * Caller must provide the packet to fill
804 */
805 if (!io)
806 return NULL;
807
808 /*
809 * Fill the subpacket with the console's standard fill pattern
810 */
811 memset(io, 0x55, sizeof(*io));
812
813 for (io7 = NULL; NULL != (io7 = marvel_next_io7(io7)); ) {
814 unsigned long err_sum = 0;
815
816 err_sum |= io7->csrs->PO7_ERROR_SUM.csr;
817 for (i = 0; i < IO7_NUM_PORTS; i++) {
818 if (!io7->ports[i].enabled)
819 continue;
820 err_sum |= io7->ports[i].csrs->POx_ERR_SUM.csr;
821 }
822
823 /*
824 * Is there at least one error?
825 */
826 if (err_sum & (1UL << 63))
827 break;
828 }
829
830 /*
831 * Did we find an IO7 with an error?
832 */
833 if (!io7)
834 return NULL;
835
836 /*
837 * We have an IO7 with an error.
838 *
839 * Fill in the IO subpacket.
840 */
841 io->io_asic_rev = io7->csrs->IO_ASIC_REV.csr;
842 io->io_sys_rev = io7->csrs->IO_SYS_REV.csr;
843 io->io7_uph = io7->csrs->IO7_UPH.csr;
844 io->hpi_ctl = io7->csrs->HPI_CTL.csr;
845 io->crd_ctl = io7->csrs->CRD_CTL.csr;
846 io->hei_ctl = io7->csrs->HEI_CTL.csr;
847 io->po7_error_sum = io7->csrs->PO7_ERROR_SUM.csr;
848 io->po7_uncrr_sym = io7->csrs->PO7_UNCRR_SYM.csr;
849 io->po7_crrct_sym = io7->csrs->PO7_CRRCT_SYM.csr;
850 io->po7_ugbge_sym = io7->csrs->PO7_UGBGE_SYM.csr;
851 io->po7_err_pkt0 = io7->csrs->PO7_ERR_PKT[0].csr;
852 io->po7_err_pkt1 = io7->csrs->PO7_ERR_PKT[1].csr;
853
854 for (i = 0; i < IO7_NUM_PORTS; i++) {
855 io7_ioport_csrs *csrs = io7->ports[i].csrs;
856
857 if (!io7->ports[i].enabled)
858 continue;
859
860 io->ports[i].pox_err_sum = csrs->POx_ERR_SUM.csr;
861 io->ports[i].pox_tlb_err = csrs->POx_TLB_ERR.csr;
862 io->ports[i].pox_spl_cmplt = csrs->POx_SPL_COMPLT.csr;
863 io->ports[i].pox_trans_sum = csrs->POx_TRANS_SUM.csr;
864 io->ports[i].pox_first_err = csrs->POx_FIRST_ERR.csr;
865 io->ports[i].pox_mult_err = csrs->POx_MULT_ERR.csr;
866 io->ports[i].pox_dm_source = csrs->POx_DM_SOURCE.csr;
867 io->ports[i].pox_dm_dest = csrs->POx_DM_DEST.csr;
868 io->ports[i].pox_dm_size = csrs->POx_DM_SIZE.csr;
869 io->ports[i].pox_dm_ctrl = csrs->POx_DM_CTRL.csr;
870
871 /*
872 * Ack this port's errors, if any. POx_ERR_SUM must be last.
873 *
874 * Most of the error registers get cleared and unlocked when
875 * the associated bits in POx_ERR_SUM are cleared (by writing
876 * 1). POx_TLB_ERR is an exception and must be explicitly
877 * cleared.
878 */
879 csrs->POx_TLB_ERR.csr = io->ports[i].pox_tlb_err;
880 csrs->POx_ERR_SUM.csr = io->ports[i].pox_err_sum;
881 mb();
882 csrs->POx_ERR_SUM.csr;
883 }
884
885 /*
886 * Ack any port 7 error(s).
887 */
888 io7->csrs->PO7_ERROR_SUM.csr = io->po7_error_sum;
889 mb();
890 io7->csrs->PO7_ERROR_SUM.csr;
891
892 /*
893 * Correct the io7_pid.
894 */
895 lf_subpackets->io_pid = io7->pe;
896
897 return io;
898}
899
900static int
901marvel_process_io_error(struct ev7_lf_subpackets *lf_subpackets, int print)
902{
903 int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
904
905#ifdef CONFIG_VERBOSE_MCHECK
906 struct ev7_pal_io_subpacket *io = lf_subpackets->io;
907 int i;
908#endif /* CONFIG_VERBOSE_MCHECK */
909
910#define MARVEL_IO_ERR_VALID(x) ((x) & (1UL << 63))
911
912 if (!lf_subpackets->logout || !lf_subpackets->io)
913 return status;
914
915 /*
916 * The PALcode only builds an IO subpacket if there is a
917 * locally connected IO7. In the cases of
918 * 1) a uniprocessor kernel
919 * 2) an mp kernel before the local secondary has called in
920 * error interrupts are all directed to the primary processor.
921 * In that case, we may not have an IO subpacket at all and, event
922 * if we do, it may not be the right now.
923 *
924 * If the RBOX indicates an I/O error interrupt, make sure we have
925 * the correct IO7 information. If we don't have an IO subpacket
926 * or it's the wrong one, try to find the right one.
927 *
928 * RBOX I/O error interrupts are indicated by RBOX_INT<29> and
929 * RBOX_INT<10>.
930 */
931 if ((lf_subpackets->io->po7_error_sum & (1UL << 32)) ||
932 ((lf_subpackets->io->po7_error_sum |
933 lf_subpackets->io->ports[0].pox_err_sum |
934 lf_subpackets->io->ports[1].pox_err_sum |
935 lf_subpackets->io->ports[2].pox_err_sum |
936 lf_subpackets->io->ports[3].pox_err_sum) & (1UL << 63))) {
937 /*
938 * Either we have no IO subpacket or no error is
939 * indicated in the one we do have. Try find the
940 * one with the error.
941 */
942 if (!marvel_find_io7_with_error(lf_subpackets))
943 return status;
944 }
945
946 /*
947 * We have an IO7 indicating an error - we're going to report it
948 */
949 status = MCHK_DISPOSITION_REPORT;
950
951#ifdef CONFIG_VERBOSE_MCHECK
952
953 if (!print)
954 return status;
955
956 printk("%s*Error occurred on IO7 at PID %u\n",
957 err_print_prefix, lf_subpackets->io_pid);
958
959 /*
960 * Check port 7 first
961 */
962 if (lf_subpackets->io->po7_error_sum & IO7__PO7_ERRSUM__ERR_MASK) {
963 marvel_print_po7_err_sum(io);
964
965#if 0
966 printk("%s PORT 7 ERROR:\n"
967 "%s PO7_ERROR_SUM: %016lx\n"
968 "%s PO7_UNCRR_SYM: %016lx\n"
969 "%s PO7_CRRCT_SYM: %016lx\n"
970 "%s PO7_UGBGE_SYM: %016lx\n"
971 "%s PO7_ERR_PKT0: %016lx\n"
972 "%s PO7_ERR_PKT1: %016lx\n",
973 err_print_prefix,
974 err_print_prefix, io->po7_error_sum,
975 err_print_prefix, io->po7_uncrr_sym,
976 err_print_prefix, io->po7_crrct_sym,
977 err_print_prefix, io->po7_ugbge_sym,
978 err_print_prefix, io->po7_err_pkt0,
979 err_print_prefix, io->po7_err_pkt1);
980#endif
981 }
982
983 /*
984 * Then loop through the ports
985 */
986 for (i = 0; i < IO7_NUM_PORTS; i++) {
987 if (!MARVEL_IO_ERR_VALID(io->ports[i].pox_err_sum))
988 continue;
989
990 printk("%s PID %u PORT %d POx_ERR_SUM: %016lx\n",
991 err_print_prefix,
992 lf_subpackets->io_pid, i, io->ports[i].pox_err_sum);
993 marvel_print_pox_err(io->ports[i].pox_err_sum, &io->ports[i]);
994
995 printk("%s [ POx_FIRST_ERR: %016lx ]\n",
996 err_print_prefix, io->ports[i].pox_first_err);
997 marvel_print_pox_err(io->ports[i].pox_first_err,
998 &io->ports[i]);
999
1000 }
1001
1002
1003#endif /* CONFIG_VERBOSE_MCHECK */
1004
1005 return status;
1006}
1007
1008static int
1009marvel_process_logout_frame(struct ev7_lf_subpackets *lf_subpackets, int print)
1010{
1011 int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
1012
1013 /*
1014 * I/O error?
1015 */
1016#define EV7__RBOX_INT__IO_ERROR__MASK 0x20000400ul
1017 if (lf_subpackets->logout &&
1018 (lf_subpackets->logout->rbox_int & 0x20000400ul))
1019 status = marvel_process_io_error(lf_subpackets, print);
1020
1021 /*
1022 * Probing behind PCI-X bridges can cause machine checks on
1023 * Marvel when the probe is handled by the bridge as a split
1024 * completion transaction. The symptom is an ERROR_RESPONSE
1025 * to a CONFIG address. Since these errors will happen in
1026 * normal operation, dismiss them.
1027 *
1028 * Dismiss if:
1029 * C_STAT = 0x14 (Error Reponse)
1030 * C_STS<3> = 0 (C_ADDR valid)
1031 * C_ADDR<42> = 1 (I/O)
1032 * C_ADDR<31:22> = 111110xxb (PCI Config space)
1033 */
1034 if (lf_subpackets->ev7 &&
1035 (lf_subpackets->ev7->c_stat == 0x14) &&
1036 !(lf_subpackets->ev7->c_sts & 0x8) &&
1037 ((lf_subpackets->ev7->c_addr & 0x400ff000000ul)
1038 == 0x400fe000000ul))
1039 status = MCHK_DISPOSITION_DISMISS;
1040
1041 return status;
1042}
1043
1044void
1045marvel_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
1046{
1047 struct el_subpacket *el_ptr = (struct el_subpacket *)la_ptr;
1048 int (*process_frame)(struct ev7_lf_subpackets *, int) = NULL;
1049 struct ev7_lf_subpackets subpacket_collection = { NULL, };
1050 struct ev7_pal_io_subpacket scratch_io_packet = { 0, };
1051 struct ev7_lf_subpackets *lf_subpackets = NULL;
1052 int disposition = MCHK_DISPOSITION_UNKNOWN_ERROR;
1053 char *saved_err_prefix = err_print_prefix;
1054 char *error_type = NULL;
1055
1056 /*
1057 * Sync the processor
1058 */
1059 mb();
1060 draina();
1061
1062 switch(vector) {
1063 case SCB_Q_SYSEVENT:
1064 process_frame = marvel_process_680_frame;
1065 error_type = "System Event";
1066 break;
1067
1068 case SCB_Q_SYSMCHK:
1069 process_frame = marvel_process_logout_frame;
1070 error_type = "System Uncorrectable Error";
1071 break;
1072
1073 case SCB_Q_SYSERR:
1074 process_frame = marvel_process_logout_frame;
1075 error_type = "System Correctable Error";
1076 break;
1077
1078 default:
1079 /* Don't know it - pass it up. */
1080 ev7_machine_check(vector, la_ptr, regs);
1081 return;
1082 }
1083
1084 /*
1085 * A system event or error has occured, handle it here.
1086 *
1087 * Any errors in the logout frame have already been cleared by the
1088 * PALcode, so just parse it.
1089 */
1090 err_print_prefix = KERN_CRIT;
1091
1092 /*
1093 * Parse the logout frame without printing first. If the only error(s)
1094 * found are classified as "dismissable", then just dismiss them and
1095 * don't print any message
1096 */
1097 lf_subpackets =
1098 ev7_collect_logout_frame_subpackets(el_ptr,
1099 &subpacket_collection);
1100 if (process_frame && lf_subpackets && lf_subpackets->logout) {
1101 /*
1102 * We might not have the correct (or any) I/O subpacket.
1103 * [ See marvel_process_io_error() for explanation. ]
1104 * If we don't have one, point the io subpacket in
1105 * lf_subpackets at scratch_io_packet so that
1106 * marvel_find_io7_with_error() will have someplace to
1107 * store the info.
1108 */
1109 if (!lf_subpackets->io)
1110 lf_subpackets->io = &scratch_io_packet;
1111
1112 /*
1113 * Default io_pid to the processor reporting the error
1114 * [this will get changed in marvel_find_io7_with_error()
1115 * if a different one is needed]
1116 */
1117 lf_subpackets->io_pid = lf_subpackets->logout->whami;
1118
1119 /*
1120 * Evaluate the frames.
1121 */
1122 disposition = process_frame(lf_subpackets, 0);
1123 }
1124 switch(disposition) {
1125 case MCHK_DISPOSITION_DISMISS:
1126 /* Nothing to do. */
1127 break;
1128
1129 case MCHK_DISPOSITION_REPORT:
1130 /* Recognized error, report it. */
1131 printk("%s*%s (Vector 0x%x) reported on CPU %d\n",
1132 err_print_prefix, error_type,
1133 (unsigned int)vector, (int)smp_processor_id());
1134 el_print_timestamp(&lf_subpackets->logout->timestamp);
1135 process_frame(lf_subpackets, 1);
1136 break;
1137
1138 default:
1139 /* Unknown - dump the annotated subpackets. */
1140 printk("%s*%s (Vector 0x%x) reported on CPU %d\n",
1141 err_print_prefix, error_type,
1142 (unsigned int)vector, (int)smp_processor_id());
1143 el_process_subpacket(el_ptr);
1144 break;
1145
1146 }
1147
1148 err_print_prefix = saved_err_prefix;
1149
1150 /* Release the logout frame. */
1151 wrmces(0x7);
1152 mb();
1153}
1154
1155void
1156marvel_register_error_handlers(void)
1157{
1158 ev7_register_error_handlers();
1159}
diff --git a/arch/alpha/kernel/err_titan.c b/arch/alpha/kernel/err_titan.c
new file mode 100644
index 000000000000..7e6720d45f02
--- /dev/null
+++ b/arch/alpha/kernel/err_titan.c
@@ -0,0 +1,756 @@
1/*
2 * linux/arch/alpha/kernel/err_titan.c
3 *
4 * Copyright (C) 2000 Jeff Wiedemeier (Compaq Computer Corporation)
5 *
6 * Error handling code supporting TITAN systems
7 */
8
9#include <linux/init.h>
10#include <linux/pci.h>
11#include <linux/sched.h>
12
13#include <asm/io.h>
14#include <asm/core_titan.h>
15#include <asm/hwrpb.h>
16#include <asm/smp.h>
17#include <asm/err_common.h>
18#include <asm/err_ev6.h>
19
20#include "err_impl.h"
21#include "proto.h"
22
23
24static int
25titan_parse_c_misc(u64 c_misc, int print)
26{
27#ifdef CONFIG_VERBOSE_MCHECK
28 char *src;
29 int nxs = 0;
30#endif
31 int status = MCHK_DISPOSITION_REPORT;
32
33#define TITAN__CCHIP_MISC__NXM (1UL << 28)
34#define TITAN__CCHIP_MISC__NXS__S (29)
35#define TITAN__CCHIP_MISC__NXS__M (0x7)
36
37 if (!(c_misc & TITAN__CCHIP_MISC__NXM))
38 return MCHK_DISPOSITION_UNKNOWN_ERROR;
39
40#ifdef CONFIG_VERBOSE_MCHECK
41 if (!print)
42 return status;
43
44 nxs = EXTRACT(c_misc, TITAN__CCHIP_MISC__NXS);
45 switch(nxs) {
46 case 0: /* CPU 0 */
47 case 1: /* CPU 1 */
48 case 2: /* CPU 2 */
49 case 3: /* CPU 3 */
50 src = "CPU";
51 /* num is already the CPU number */
52 break;
53 case 4: /* Pchip 0 */
54 case 5: /* Pchip 1 */
55 src = "Pchip";
56 nxs -= 4;
57 break;
58 default:/* reserved */
59 src = "Unknown, NXS =";
60 /* leave num untouched */
61 break;
62 }
63
64 printk("%s Non-existent memory access from: %s %d\n",
65 err_print_prefix, src, nxs);
66#endif /* CONFIG_VERBOSE_MCHECK */
67
68 return status;
69}
70
71static int
72titan_parse_p_serror(int which, u64 serror, int print)
73{
74 int status = MCHK_DISPOSITION_REPORT;
75
76#ifdef CONFIG_VERBOSE_MCHECK
77 char *serror_src[] = {"GPCI", "APCI", "AGP HP", "AGP LP"};
78 char *serror_cmd[] = {"DMA Read", "DMA RMW", "SGTE Read", "Reserved"};
79#endif /* CONFIG_VERBOSE_MCHECK */
80
81#define TITAN__PCHIP_SERROR__LOST_UECC (1UL << 0)
82#define TITAN__PCHIP_SERROR__UECC (1UL << 1)
83#define TITAN__PCHIP_SERROR__CRE (1UL << 2)
84#define TITAN__PCHIP_SERROR__NXIO (1UL << 3)
85#define TITAN__PCHIP_SERROR__LOST_CRE (1UL << 4)
86#define TITAN__PCHIP_SERROR__ECCMASK (TITAN__PCHIP_SERROR__UECC | \
87 TITAN__PCHIP_SERROR__CRE)
88#define TITAN__PCHIP_SERROR__ERRMASK (TITAN__PCHIP_SERROR__LOST_UECC | \
89 TITAN__PCHIP_SERROR__UECC | \
90 TITAN__PCHIP_SERROR__CRE | \
91 TITAN__PCHIP_SERROR__NXIO | \
92 TITAN__PCHIP_SERROR__LOST_CRE)
93#define TITAN__PCHIP_SERROR__SRC__S (52)
94#define TITAN__PCHIP_SERROR__SRC__M (0x3)
95#define TITAN__PCHIP_SERROR__CMD__S (54)
96#define TITAN__PCHIP_SERROR__CMD__M (0x3)
97#define TITAN__PCHIP_SERROR__SYN__S (56)
98#define TITAN__PCHIP_SERROR__SYN__M (0xff)
99#define TITAN__PCHIP_SERROR__ADDR__S (15)
100#define TITAN__PCHIP_SERROR__ADDR__M (0xffffffffUL)
101
102 if (!(serror & TITAN__PCHIP_SERROR__ERRMASK))
103 return MCHK_DISPOSITION_UNKNOWN_ERROR;
104
105#ifdef CONFIG_VERBOSE_MCHECK
106 if (!print)
107 return status;
108
109 printk("%s PChip %d SERROR: %016lx\n",
110 err_print_prefix, which, serror);
111 if (serror & TITAN__PCHIP_SERROR__ECCMASK) {
112 printk("%s %sorrectable ECC Error:\n"
113 " Source: %-6s Command: %-8s Syndrome: 0x%08x\n"
114 " Address: 0x%lx\n",
115 err_print_prefix,
116 (serror & TITAN__PCHIP_SERROR__UECC) ? "Unc" : "C",
117 serror_src[EXTRACT(serror, TITAN__PCHIP_SERROR__SRC)],
118 serror_cmd[EXTRACT(serror, TITAN__PCHIP_SERROR__CMD)],
119 (unsigned)EXTRACT(serror, TITAN__PCHIP_SERROR__SYN),
120 EXTRACT(serror, TITAN__PCHIP_SERROR__ADDR));
121 }
122 if (serror & TITAN__PCHIP_SERROR__NXIO)
123 printk("%s Non Existent I/O Error\n", err_print_prefix);
124 if (serror & TITAN__PCHIP_SERROR__LOST_UECC)
125 printk("%s Lost Uncorrectable ECC Error\n",
126 err_print_prefix);
127 if (serror & TITAN__PCHIP_SERROR__LOST_CRE)
128 printk("%s Lost Correctable ECC Error\n", err_print_prefix);
129#endif /* CONFIG_VERBOSE_MCHECK */
130
131 return status;
132}
133
134static int
135titan_parse_p_perror(int which, int port, u64 perror, int print)
136{
137 int cmd;
138 unsigned long addr;
139 int status = MCHK_DISPOSITION_REPORT;
140
141#ifdef CONFIG_VERBOSE_MCHECK
142 char *perror_cmd[] = { "Interrupt Acknowledge", "Special Cycle",
143 "I/O Read", "I/O Write",
144 "Reserved", "Reserved",
145 "Memory Read", "Memory Write",
146 "Reserved", "Reserved",
147 "Configuration Read", "Configuration Write",
148 "Memory Read Multiple", "Dual Address Cycle",
149 "Memory Read Line","Memory Write and Invalidate"
150 };
151#endif /* CONFIG_VERBOSE_MCHECK */
152
153#define TITAN__PCHIP_PERROR__LOST (1UL << 0)
154#define TITAN__PCHIP_PERROR__SERR (1UL << 1)
155#define TITAN__PCHIP_PERROR__PERR (1UL << 2)
156#define TITAN__PCHIP_PERROR__DCRTO (1UL << 3)
157#define TITAN__PCHIP_PERROR__SGE (1UL << 4)
158#define TITAN__PCHIP_PERROR__APE (1UL << 5)
159#define TITAN__PCHIP_PERROR__TA (1UL << 6)
160#define TITAN__PCHIP_PERROR__DPE (1UL << 7)
161#define TITAN__PCHIP_PERROR__NDS (1UL << 8)
162#define TITAN__PCHIP_PERROR__IPTPR (1UL << 9)
163#define TITAN__PCHIP_PERROR__IPTPW (1UL << 10)
164#define TITAN__PCHIP_PERROR__ERRMASK (TITAN__PCHIP_PERROR__LOST | \
165 TITAN__PCHIP_PERROR__SERR | \
166 TITAN__PCHIP_PERROR__PERR | \
167 TITAN__PCHIP_PERROR__DCRTO | \
168 TITAN__PCHIP_PERROR__SGE | \
169 TITAN__PCHIP_PERROR__APE | \
170 TITAN__PCHIP_PERROR__TA | \
171 TITAN__PCHIP_PERROR__DPE | \
172 TITAN__PCHIP_PERROR__NDS | \
173 TITAN__PCHIP_PERROR__IPTPR | \
174 TITAN__PCHIP_PERROR__IPTPW)
175#define TITAN__PCHIP_PERROR__DAC (1UL << 47)
176#define TITAN__PCHIP_PERROR__MWIN (1UL << 48)
177#define TITAN__PCHIP_PERROR__CMD__S (52)
178#define TITAN__PCHIP_PERROR__CMD__M (0x0f)
179#define TITAN__PCHIP_PERROR__ADDR__S (14)
180#define TITAN__PCHIP_PERROR__ADDR__M (0x1fffffffful)
181
182 if (!(perror & TITAN__PCHIP_PERROR__ERRMASK))
183 return MCHK_DISPOSITION_UNKNOWN_ERROR;
184
185 cmd = EXTRACT(perror, TITAN__PCHIP_PERROR__CMD);
186 addr = EXTRACT(perror, TITAN__PCHIP_PERROR__ADDR) << 2;
187
188 /*
189 * Initializing the BIOS on a video card on a bus without
190 * a south bridge (subtractive decode agent) can result in
191 * master aborts as the BIOS probes the capabilities of the
192 * card. XFree86 does such initialization. If the error
193 * is a master abort (No DevSel as PCI Master) and the command
194 * is an I/O read or write below the address where we start
195 * assigning PCI I/O spaces (SRM uses 0x1000), then mark the
196 * error as dismissable so starting XFree86 doesn't result
197 * in a series of uncorrectable errors being reported. Also
198 * dismiss master aborts to VGA frame buffer space
199 * (0xA0000 - 0xC0000) and legacy BIOS space (0xC0000 - 0x100000)
200 * for the same reason.
201 *
202 * Also mark the error dismissible if it looks like the right
203 * error but only the Lost bit is set. Since the BIOS initialization
204 * can cause multiple master aborts and the error interrupt can
205 * be handled on a different CPU than the BIOS code is run on,
206 * it is possible for a second master abort to occur between the
207 * time the PALcode reads PERROR and the time it writes PERROR
208 * to acknowledge the error. If this timing happens, a second
209 * error will be signalled after the first, and if no additional
210 * errors occur, will look like a Lost error with no additional
211 * errors on the same transaction as the previous error.
212 */
213 if (((perror & TITAN__PCHIP_PERROR__NDS) ||
214 ((perror & TITAN__PCHIP_PERROR__ERRMASK) ==
215 TITAN__PCHIP_PERROR__LOST)) &&
216 ((((cmd & 0xE) == 2) && (addr < 0x1000)) ||
217 (((cmd & 0xE) == 6) && (addr >= 0xA0000) && (addr < 0x100000)))) {
218 status = MCHK_DISPOSITION_DISMISS;
219 }
220
221#ifdef CONFIG_VERBOSE_MCHECK
222 if (!print)
223 return status;
224
225 printk("%s PChip %d %cPERROR: %016lx\n",
226 err_print_prefix, which,
227 port ? 'A' : 'G', perror);
228 if (perror & TITAN__PCHIP_PERROR__IPTPW)
229 printk("%s Invalid Peer-to-Peer Write\n", err_print_prefix);
230 if (perror & TITAN__PCHIP_PERROR__IPTPR)
231 printk("%s Invalid Peer-to-Peer Read\n", err_print_prefix);
232 if (perror & TITAN__PCHIP_PERROR__NDS)
233 printk("%s No DEVSEL as PCI Master [Master Abort]\n",
234 err_print_prefix);
235 if (perror & TITAN__PCHIP_PERROR__DPE)
236 printk("%s Data Parity Error\n", err_print_prefix);
237 if (perror & TITAN__PCHIP_PERROR__TA)
238 printk("%s Target Abort\n", err_print_prefix);
239 if (perror & TITAN__PCHIP_PERROR__APE)
240 printk("%s Address Parity Error\n", err_print_prefix);
241 if (perror & TITAN__PCHIP_PERROR__SGE)
242 printk("%s Scatter-Gather Error, Invalid PTE\n",
243 err_print_prefix);
244 if (perror & TITAN__PCHIP_PERROR__DCRTO)
245 printk("%s Delayed-Completion Retry Timeout\n",
246 err_print_prefix);
247 if (perror & TITAN__PCHIP_PERROR__PERR)
248 printk("%s PERR Asserted\n", err_print_prefix);
249 if (perror & TITAN__PCHIP_PERROR__SERR)
250 printk("%s SERR Asserted\n", err_print_prefix);
251 if (perror & TITAN__PCHIP_PERROR__LOST)
252 printk("%s Lost Error\n", err_print_prefix);
253 printk("%s Command: 0x%x - %s\n"
254 " Address: 0x%lx\n",
255 err_print_prefix,
256 cmd, perror_cmd[cmd],
257 addr);
258 if (perror & TITAN__PCHIP_PERROR__DAC)
259 printk("%s Dual Address Cycle\n", err_print_prefix);
260 if (perror & TITAN__PCHIP_PERROR__MWIN)
261 printk("%s Hit in Monster Window\n", err_print_prefix);
262#endif /* CONFIG_VERBOSE_MCHECK */
263
264 return status;
265}
266
267static int
268titan_parse_p_agperror(int which, u64 agperror, int print)
269{
270 int status = MCHK_DISPOSITION_REPORT;
271#ifdef CONFIG_VERBOSE_MCHECK
272 int cmd, len;
273 unsigned long addr;
274
275 char *agperror_cmd[] = { "Read (low-priority)", "Read (high-priority)",
276 "Write (low-priority)",
277 "Write (high-priority)",
278 "Reserved", "Reserved",
279 "Flush", "Fence"
280 };
281#endif /* CONFIG_VERBOSE_MCHECK */
282
283#define TITAN__PCHIP_AGPERROR__LOST (1UL << 0)
284#define TITAN__PCHIP_AGPERROR__LPQFULL (1UL << 1)
285#define TITAN__PCHIP_AGPERROR__HPQFULL (1UL << 2)
286#define TITAN__PCHIP_AGPERROR__RESCMD (1UL << 3)
287#define TITAN__PCHIP_AGPERROR__IPTE (1UL << 4)
288#define TITAN__PCHIP_AGPERROR__PTP (1UL << 5)
289#define TITAN__PCHIP_AGPERROR__NOWINDOW (1UL << 6)
290#define TITAN__PCHIP_AGPERROR__ERRMASK (TITAN__PCHIP_AGPERROR__LOST | \
291 TITAN__PCHIP_AGPERROR__LPQFULL | \
292 TITAN__PCHIP_AGPERROR__HPQFULL | \
293 TITAN__PCHIP_AGPERROR__RESCMD | \
294 TITAN__PCHIP_AGPERROR__IPTE | \
295 TITAN__PCHIP_AGPERROR__PTP | \
296 TITAN__PCHIP_AGPERROR__NOWINDOW)
297#define TITAN__PCHIP_AGPERROR__DAC (1UL << 48)
298#define TITAN__PCHIP_AGPERROR__MWIN (1UL << 49)
299#define TITAN__PCHIP_AGPERROR__FENCE (1UL << 59)
300#define TITAN__PCHIP_AGPERROR__CMD__S (50)
301#define TITAN__PCHIP_AGPERROR__CMD__M (0x07)
302#define TITAN__PCHIP_AGPERROR__ADDR__S (15)
303#define TITAN__PCHIP_AGPERROR__ADDR__M (0xffffffffUL)
304#define TITAN__PCHIP_AGPERROR__LEN__S (53)
305#define TITAN__PCHIP_AGPERROR__LEN__M (0x3f)
306
307 if (!(agperror & TITAN__PCHIP_AGPERROR__ERRMASK))
308 return MCHK_DISPOSITION_UNKNOWN_ERROR;
309
310#ifdef CONFIG_VERBOSE_MCHECK
311 if (!print)
312 return status;
313
314 cmd = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__CMD);
315 addr = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__ADDR) << 3;
316 len = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__LEN);
317
318 printk("%s PChip %d AGPERROR: %016lx\n", err_print_prefix,
319 which, agperror);
320 if (agperror & TITAN__PCHIP_AGPERROR__NOWINDOW)
321 printk("%s No Window\n", err_print_prefix);
322 if (agperror & TITAN__PCHIP_AGPERROR__PTP)
323 printk("%s Peer-to-Peer set\n", err_print_prefix);
324 if (agperror & TITAN__PCHIP_AGPERROR__IPTE)
325 printk("%s Invalid PTE\n", err_print_prefix);
326 if (agperror & TITAN__PCHIP_AGPERROR__RESCMD)
327 printk("%s Reserved Command\n", err_print_prefix);
328 if (agperror & TITAN__PCHIP_AGPERROR__HPQFULL)
329 printk("%s HP Transaction Received while Queue Full\n",
330 err_print_prefix);
331 if (agperror & TITAN__PCHIP_AGPERROR__LPQFULL)
332 printk("%s LP Transaction Received while Queue Full\n",
333 err_print_prefix);
334 if (agperror & TITAN__PCHIP_AGPERROR__LOST)
335 printk("%s Lost Error\n", err_print_prefix);
336 printk("%s Command: 0x%x - %s, %d Quadwords%s\n"
337 " Address: 0x%lx\n",
338 err_print_prefix, cmd, agperror_cmd[cmd], len,
339 (agperror & TITAN__PCHIP_AGPERROR__FENCE) ? ", FENCE" : "",
340 addr);
341 if (agperror & TITAN__PCHIP_AGPERROR__DAC)
342 printk("%s Dual Address Cycle\n", err_print_prefix);
343 if (agperror & TITAN__PCHIP_AGPERROR__MWIN)
344 printk("%s Hit in Monster Window\n", err_print_prefix);
345#endif /* CONFIG_VERBOSE_MCHECK */
346
347 return status;
348}
349
350static int
351titan_parse_p_chip(int which, u64 serror, u64 gperror,
352 u64 aperror, u64 agperror, int print)
353{
354 int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
355 status |= titan_parse_p_serror(which, serror, print);
356 status |= titan_parse_p_perror(which, 0, gperror, print);
357 status |= titan_parse_p_perror(which, 1, aperror, print);
358 status |= titan_parse_p_agperror(which, agperror, print);
359 return status;
360}
361
362int
363titan_process_logout_frame(struct el_common *mchk_header, int print)
364{
365 struct el_TITAN_sysdata_mcheck *tmchk =
366 (struct el_TITAN_sysdata_mcheck *)
367 ((unsigned long)mchk_header + mchk_header->sys_offset);
368 int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
369
370 status |= titan_parse_c_misc(tmchk->c_misc, print);
371 status |= titan_parse_p_chip(0, tmchk->p0_serror, tmchk->p0_gperror,
372 tmchk->p0_aperror, tmchk->p0_agperror,
373 print);
374 status |= titan_parse_p_chip(1, tmchk->p1_serror, tmchk->p1_gperror,
375 tmchk->p1_aperror, tmchk->p1_agperror,
376 print);
377
378 return status;
379}
380
381void
382titan_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
383{
384 struct el_common *mchk_header = (struct el_common *)la_ptr;
385 struct el_TITAN_sysdata_mcheck *tmchk =
386 (struct el_TITAN_sysdata_mcheck *)
387 ((unsigned long)mchk_header + mchk_header->sys_offset);
388 u64 irqmask;
389
390 /*
391 * Mask of Titan interrupt sources which are reported as machine checks
392 *
393 * 63 - CChip Error
394 * 62 - PChip 0 H_Error
395 * 61 - PChip 1 H_Error
396 * 60 - PChip 0 C_Error
397 * 59 - PChip 1 C_Error
398 */
399#define TITAN_MCHECK_INTERRUPT_MASK 0xF800000000000000UL
400
401 /*
402 * Sync the processor
403 */
404 mb();
405 draina();
406
407 /*
408 * Only handle system errors here
409 */
410 if ((vector != SCB_Q_SYSMCHK) && (vector != SCB_Q_SYSERR)) {
411 ev6_machine_check(vector, la_ptr, regs);
412 return;
413 }
414
415 /*
416 * It's a system error, handle it here
417 *
418 * The PALcode has already cleared the error, so just parse it
419 */
420
421 /*
422 * Parse the logout frame without printing first. If the only error(s)
423 * found are classified as "dismissable", then just dismiss them and
424 * don't print any message
425 */
426 if (titan_process_logout_frame(mchk_header, 0) !=
427 MCHK_DISPOSITION_DISMISS) {
428 char *saved_err_prefix = err_print_prefix;
429 err_print_prefix = KERN_CRIT;
430
431 /*
432 * Either a nondismissable error was detected or no
433 * recognized error was detected in the logout frame
434 * -- report the error in either case
435 */
436 printk("%s"
437 "*System %s Error (Vector 0x%x) reported on CPU %d:\n",
438 err_print_prefix,
439 (vector == SCB_Q_SYSERR)?"Correctable":"Uncorrectable",
440 (unsigned int)vector, (int)smp_processor_id());
441
442#ifdef CONFIG_VERBOSE_MCHECK
443 titan_process_logout_frame(mchk_header, alpha_verbose_mcheck);
444 if (alpha_verbose_mcheck)
445 dik_show_regs(regs, NULL);
446#endif /* CONFIG_VERBOSE_MCHECK */
447
448 err_print_prefix = saved_err_prefix;
449
450 /*
451 * Convert any pending interrupts which report as system
452 * machine checks to interrupts
453 */
454 irqmask = tmchk->c_dirx & TITAN_MCHECK_INTERRUPT_MASK;
455 titan_dispatch_irqs(irqmask, regs);
456 }
457
458
459 /*
460 * Release the logout frame
461 */
462 wrmces(0x7);
463 mb();
464}
465
466/*
467 * Subpacket Annotations
468 */
469static char *el_titan_pchip0_extended_annotation[] = {
470 "Subpacket Header", "P0_SCTL", "P0_SERREN",
471 "P0_APCTL", "P0_APERREN", "P0_AGPERREN",
472 "P0_ASPRST", "P0_AWSBA0", "P0_AWSBA1",
473 "P0_AWSBA2", "P0_AWSBA3", "P0_AWSM0",
474 "P0_AWSM1", "P0_AWSM2", "P0_AWSM3",
475 "P0_ATBA0", "P0_ATBA1", "P0_ATBA2",
476 "P0_ATBA3", "P0_GPCTL", "P0_GPERREN",
477 "P0_GSPRST", "P0_GWSBA0", "P0_GWSBA1",
478 "P0_GWSBA2", "P0_GWSBA3", "P0_GWSM0",
479 "P0_GWSM1", "P0_GWSM2", "P0_GWSM3",
480 "P0_GTBA0", "P0_GTBA1", "P0_GTBA2",
481 "P0_GTBA3", NULL
482};
483static char *el_titan_pchip1_extended_annotation[] = {
484 "Subpacket Header", "P1_SCTL", "P1_SERREN",
485 "P1_APCTL", "P1_APERREN", "P1_AGPERREN",
486 "P1_ASPRST", "P1_AWSBA0", "P1_AWSBA1",
487 "P1_AWSBA2", "P1_AWSBA3", "P1_AWSM0",
488 "P1_AWSM1", "P1_AWSM2", "P1_AWSM3",
489 "P1_ATBA0", "P1_ATBA1", "P1_ATBA2",
490 "P1_ATBA3", "P1_GPCTL", "P1_GPERREN",
491 "P1_GSPRST", "P1_GWSBA0", "P1_GWSBA1",
492 "P1_GWSBA2", "P1_GWSBA3", "P1_GWSM0",
493 "P1_GWSM1", "P1_GWSM2", "P1_GWSM3",
494 "P1_GTBA0", "P1_GTBA1", "P1_GTBA2",
495 "P1_GTBA3", NULL
496};
497static char *el_titan_memory_extended_annotation[] = {
498 "Subpacket Header", "AAR0", "AAR1",
499 "AAR2", "AAR3", "P0_SCTL",
500 "P0_GPCTL", "P0_APCTL", "P1_SCTL",
501 "P1_GPCTL", "P1_SCTL", NULL
502};
503
504static struct el_subpacket_annotation el_titan_annotations[] = {
505 SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
506 EL_TYPE__REGATTA__TITAN_PCHIP0_EXTENDED,
507 1,
508 "Titan PChip 0 Extended Frame",
509 el_titan_pchip0_extended_annotation),
510 SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
511 EL_TYPE__REGATTA__TITAN_PCHIP1_EXTENDED,
512 1,
513 "Titan PChip 1 Extended Frame",
514 el_titan_pchip1_extended_annotation),
515 SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
516 EL_TYPE__REGATTA__TITAN_MEMORY_EXTENDED,
517 1,
518 "Titan Memory Extended Frame",
519 el_titan_memory_extended_annotation),
520 SUBPACKET_ANNOTATION(EL_CLASS__REGATTA_FAMILY,
521 EL_TYPE__TERMINATION__TERMINATION,
522 1,
523 "Termination Subpacket",
524 NULL)
525};
526
527static struct el_subpacket *
528el_process_regatta_subpacket(struct el_subpacket *header)
529{
530 int status;
531
532 if (header->class != EL_CLASS__REGATTA_FAMILY) {
533 printk("%s ** Unexpected header CLASS %d TYPE %d, aborting\n",
534 err_print_prefix,
535 header->class, header->type);
536 return NULL;
537 }
538
539 switch(header->type) {
540 case EL_TYPE__REGATTA__PROCESSOR_ERROR_FRAME:
541 case EL_TYPE__REGATTA__SYSTEM_ERROR_FRAME:
542 case EL_TYPE__REGATTA__ENVIRONMENTAL_FRAME:
543 case EL_TYPE__REGATTA__PROCESSOR_DBL_ERROR_HALT:
544 case EL_TYPE__REGATTA__SYSTEM_DBL_ERROR_HALT:
545 printk("%s ** Occurred on CPU %d:\n",
546 err_print_prefix,
547 (int)header->by_type.regatta_frame.cpuid);
548 status = privateer_process_logout_frame((struct el_common *)
549 header->by_type.regatta_frame.data_start, 1);
550 break;
551 default:
552 printk("%s ** REGATTA TYPE %d SUBPACKET\n",
553 err_print_prefix, header->type);
554 el_annotate_subpacket(header);
555 break;
556 }
557
558
559 return (struct el_subpacket *)((unsigned long)header + header->length);
560}
561
562static struct el_subpacket_handler titan_subpacket_handler =
563 SUBPACKET_HANDLER_INIT(EL_CLASS__REGATTA_FAMILY,
564 el_process_regatta_subpacket);
565
566void
567titan_register_error_handlers(void)
568{
569 size_t i;
570
571 for (i = 0; i < ARRAY_SIZE (el_titan_annotations); i++)
572 cdl_register_subpacket_annotation(&el_titan_annotations[i]);
573
574 cdl_register_subpacket_handler(&titan_subpacket_handler);
575
576 ev6_register_error_handlers();
577}
578
579
580/*
581 * Privateer
582 */
583
584static int
585privateer_process_680_frame(struct el_common *mchk_header, int print)
586{
587 int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
588#ifdef CONFIG_VERBOSE_MCHECK
589 struct el_PRIVATEER_envdata_mcheck *emchk =
590 (struct el_PRIVATEER_envdata_mcheck *)
591 ((unsigned long)mchk_header + mchk_header->sys_offset);
592
593 /* TODO - catagorize errors, for now, no error */
594
595 if (!print)
596 return status;
597
598 /* TODO - decode instead of just dumping... */
599 printk("%s Summary Flags: %016lx\n"
600 " CChip DIRx: %016lx\n"
601 " System Management IR: %016lx\n"
602 " CPU IR: %016lx\n"
603 " Power Supply IR: %016lx\n"
604 " LM78 Fault Status: %016lx\n"
605 " System Doors: %016lx\n"
606 " Temperature Warning: %016lx\n"
607 " Fan Control: %016lx\n"
608 " Fatal Power Down Code: %016lx\n",
609 err_print_prefix,
610 emchk->summary,
611 emchk->c_dirx,
612 emchk->smir,
613 emchk->cpuir,
614 emchk->psir,
615 emchk->fault,
616 emchk->sys_doors,
617 emchk->temp_warn,
618 emchk->fan_ctrl,
619 emchk->code);
620#endif /* CONFIG_VERBOSE_MCHECK */
621
622 return status;
623}
624
625int
626privateer_process_logout_frame(struct el_common *mchk_header, int print)
627{
628 struct el_common_EV6_mcheck *ev6mchk =
629 (struct el_common_EV6_mcheck *)mchk_header;
630 int status = MCHK_DISPOSITION_UNKNOWN_ERROR;
631
632 /*
633 * Machine check codes
634 */
635#define PRIVATEER_MCHK__CORR_ECC 0x86 /* 630 */
636#define PRIVATEER_MCHK__DC_TAG_PERR 0x9E /* 630 */
637#define PRIVATEER_MCHK__PAL_BUGCHECK 0x8E /* 670 */
638#define PRIVATEER_MCHK__OS_BUGCHECK 0x90 /* 670 */
639#define PRIVATEER_MCHK__PROC_HRD_ERR 0x98 /* 670 */
640#define PRIVATEER_MCHK__ISTREAM_CMOV_PRX 0xA0 /* 670 */
641#define PRIVATEER_MCHK__ISTREAM_CMOV_FLT 0xA2 /* 670 */
642#define PRIVATEER_MCHK__SYS_HRD_ERR 0x202 /* 660 */
643#define PRIVATEER_MCHK__SYS_CORR_ERR 0x204 /* 620 */
644#define PRIVATEER_MCHK__SYS_ENVIRON 0x206 /* 680 */
645
646 switch(ev6mchk->MCHK_Code) {
647 /*
648 * Vector 630 - Processor, Correctable
649 */
650 case PRIVATEER_MCHK__CORR_ECC:
651 case PRIVATEER_MCHK__DC_TAG_PERR:
652 /*
653 * Fall through to vector 670 for processing...
654 */
655 /*
656 * Vector 670 - Processor, Uncorrectable
657 */
658 case PRIVATEER_MCHK__PAL_BUGCHECK:
659 case PRIVATEER_MCHK__OS_BUGCHECK:
660 case PRIVATEER_MCHK__PROC_HRD_ERR:
661 case PRIVATEER_MCHK__ISTREAM_CMOV_PRX:
662 case PRIVATEER_MCHK__ISTREAM_CMOV_FLT:
663 status |= ev6_process_logout_frame(mchk_header, print);
664 break;
665
666 /*
667 * Vector 620 - System, Correctable
668 */
669 case PRIVATEER_MCHK__SYS_CORR_ERR:
670 /*
671 * Fall through to vector 660 for processing...
672 */
673 /*
674 * Vector 660 - System, Uncorrectable
675 */
676 case PRIVATEER_MCHK__SYS_HRD_ERR:
677 status |= titan_process_logout_frame(mchk_header, print);
678 break;
679
680 /*
681 * Vector 680 - System, Environmental
682 */
683 case PRIVATEER_MCHK__SYS_ENVIRON: /* System, Environmental */
684 status |= privateer_process_680_frame(mchk_header, print);
685 break;
686
687 /*
688 * Unknown
689 */
690 default:
691 status |= MCHK_DISPOSITION_REPORT;
692 if (print) {
693 printk("%s** Unknown Error, frame follows\n",
694 err_print_prefix);
695 mchk_dump_logout_frame(mchk_header);
696 }
697
698 }
699
700 return status;
701}
702
703void
704privateer_machine_check(u64 vector, u64 la_ptr, struct pt_regs *regs)
705{
706 struct el_common *mchk_header = (struct el_common *)la_ptr;
707 struct el_TITAN_sysdata_mcheck *tmchk =
708 (struct el_TITAN_sysdata_mcheck *)
709 (la_ptr + mchk_header->sys_offset);
710 u64 irqmask;
711 char *saved_err_prefix = err_print_prefix;
712
713#define PRIVATEER_680_INTERRUPT_MASK (0xE00UL)
714#define PRIVATEER_HOTPLUG_INTERRUPT_MASK (0xE00UL)
715
716 /*
717 * Sync the processor.
718 */
719 mb();
720 draina();
721
722 /*
723 * Only handle system events here.
724 */
725 if (vector != SCB_Q_SYSEVENT)
726 return titan_machine_check(vector, la_ptr, regs);
727
728 /*
729 * Report the event - System Events should be reported even if no
730 * error is indicated since the event could indicate the return
731 * to normal status.
732 */
733 err_print_prefix = KERN_CRIT;
734 printk("%s*System Event (Vector 0x%x) reported on CPU %d:\n",
735 err_print_prefix,
736 (unsigned int)vector, (int)smp_processor_id());
737 privateer_process_680_frame(mchk_header, 1);
738 err_print_prefix = saved_err_prefix;
739
740 /*
741 * Convert any pending interrupts which report as 680 machine
742 * checks to interrupts.
743 */
744 irqmask = tmchk->c_dirx & PRIVATEER_680_INTERRUPT_MASK;
745
746 /*
747 * Dispatch the interrupt(s).
748 */
749 titan_dispatch_irqs(irqmask, regs);
750
751 /*
752 * Release the logout frame.
753 */
754 wrmces(0x7);
755 mb();
756}
diff --git a/arch/alpha/kernel/es1888.c b/arch/alpha/kernel/es1888.c
new file mode 100644
index 000000000000..d584c85fea7a
--- /dev/null
+++ b/arch/alpha/kernel/es1888.c
@@ -0,0 +1,49 @@
1/*
2 * linux/arch/alpha/kernel/es1888.c
3 *
4 * Init the built-in ES1888 sound chip (SB16 compatible)
5 */
6
7#include <linux/init.h>
8#include <asm/io.h>
9#include "proto.h"
10
11void __init
12es1888_init(void)
13{
14 /* Sequence of IO reads to init the audio controller */
15 inb(0x0229);
16 inb(0x0229);
17 inb(0x0229);
18 inb(0x022b);
19 inb(0x0229);
20 inb(0x022b);
21 inb(0x0229);
22 inb(0x0229);
23 inb(0x022b);
24 inb(0x0229);
25 inb(0x0220); /* This sets the base address to 0x220 */
26
27 /* Sequence to set DMA channels */
28 outb(0x01, 0x0226); /* reset */
29 inb(0x0226); /* pause */
30 outb(0x00, 0x0226); /* release reset */
31 while (!(inb(0x022e) & 0x80)) /* wait for bit 7 to assert*/
32 continue;
33 inb(0x022a); /* pause */
34 outb(0xc6, 0x022c); /* enable extended mode */
35 inb(0x022a); /* pause, also forces the write */
36 while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
37 continue;
38 outb(0xb1, 0x022c); /* setup for write to Interrupt CR */
39 while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
40 continue;
41 outb(0x14, 0x022c); /* set IRQ 5 */
42 while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
43 continue;
44 outb(0xb2, 0x022c); /* setup for write to DMA CR */
45 while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
46 continue;
47 outb(0x18, 0x022c); /* set DMA channel 1 */
48 inb(0x022c); /* force the write */
49}
diff --git a/arch/alpha/kernel/gct.c b/arch/alpha/kernel/gct.c
new file mode 100644
index 000000000000..8827687b9f89
--- /dev/null
+++ b/arch/alpha/kernel/gct.c
@@ -0,0 +1,48 @@
1/*
2 * linux/arch/alpha/kernel/gct.c
3 */
4
5#include <linux/config.h>
6#include <linux/kernel.h>
7#include <linux/types.h>
8#include <linux/errno.h>
9
10#include <asm/hwrpb.h>
11#include <asm/gct.h>
12
13int
14gct6_find_nodes(gct6_node *node, gct6_search_struct *search)
15{
16 gct6_search_struct *wanted;
17 int status = 0;
18
19 /* First check the magic number. */
20 if (node->magic != GCT_NODE_MAGIC) {
21 printk(KERN_ERR "GCT Node MAGIC incorrect - GCT invalid\n");
22 return -EINVAL;
23 }
24
25 /* Check against the search struct. */
26 for (wanted = search;
27 wanted && (wanted->type | wanted->subtype);
28 wanted++) {
29 if (node->type != wanted->type)
30 continue;
31 if (node->subtype != wanted->subtype)
32 continue;
33
34 /* Found it -- call out. */
35 if (wanted->callout)
36 wanted->callout(node);
37 }
38
39 /* Now walk the tree, siblings first. */
40 if (node->next)
41 status |= gct6_find_nodes(GCT_NODE_PTR(node->next), search);
42
43 /* Then the children. */
44 if (node->child)
45 status |= gct6_find_nodes(GCT_NODE_PTR(node->child), search);
46
47 return status;
48}
diff --git a/arch/alpha/kernel/head.S b/arch/alpha/kernel/head.S
new file mode 100644
index 000000000000..4ca2e404708a
--- /dev/null
+++ b/arch/alpha/kernel/head.S
@@ -0,0 +1,99 @@
1/*
2 * alpha/boot/head.S
3 *
4 * initial boot stuff.. At this point, the bootloader has already
5 * switched into OSF/1 PAL-code, and loaded us at the correct address
6 * (START_ADDR). So there isn't much left for us to do: just set up
7 * the kernel global pointer and jump to the kernel entry-point.
8 */
9
10#include <linux/config.h>
11#include <asm/system.h>
12#include <asm/asm_offsets.h>
13
14.globl swapper_pg_dir
15.globl _stext
16swapper_pg_dir=SWAPPER_PGD
17
18 .set noreorder
19 .globl __start
20 .ent __start
21_stext:
22__start:
23 .prologue 0
24 br $27,1f
251: ldgp $29,0($27)
26 /* We need to get current_task_info loaded up... */
27 lda $8,init_thread_union
28 /* ... and find our stack ... */
29 lda $30,0x4000 - SIZEOF_PT_REGS($8)
30 /* ... and then we can start the kernel. */
31 jsr $26,start_kernel
32 call_pal PAL_halt
33 .end __start
34
35#ifdef CONFIG_SMP
36 .align 3
37 .globl __smp_callin
38 .ent __smp_callin
39 /* On entry here from SRM console, the HWPCB of the per-cpu
40 slot for this processor has been loaded. We've arranged
41 for the UNIQUE value for this process to contain the PCBB
42 of the target idle task. */
43__smp_callin:
44 .prologue 1
45 ldgp $29,0($27) # First order of business, load the GP.
46
47 call_pal PAL_rduniq # Grab the target PCBB.
48 mov $0,$16 # Install it.
49 call_pal PAL_swpctx
50
51 lda $8,0x3fff # Find "current".
52 bic $30,$8,$8
53
54 jsr $26,smp_callin
55 call_pal PAL_halt
56 .end __smp_callin
57#endif /* CONFIG_SMP */
58
59 #
60 # The following two functions are needed for supporting SRM PALcode
61 # on the PC164 (at least), since that PALcode manages the interrupt
62 # masking, and we cannot duplicate the effort without causing problems
63 #
64
65 .align 3
66 .globl cserve_ena
67 .ent cserve_ena
68cserve_ena:
69 .prologue 0
70 bis $16,$16,$17
71 lda $16,52($31)
72 call_pal PAL_cserve
73 ret ($26)
74 .end cserve_ena
75
76 .align 3
77 .globl cserve_dis
78 .ent cserve_dis
79cserve_dis:
80 .prologue 0
81 bis $16,$16,$17
82 lda $16,53($31)
83 call_pal PAL_cserve
84 ret ($26)
85 .end cserve_dis
86
87 #
88 # It is handy, on occasion, to make halt actually just loop.
89 # Putting it here means we dont have to recompile the whole
90 # kernel.
91 #
92
93 .align 3
94 .globl halt
95 .ent halt
96halt:
97 .prologue 0
98 call_pal PAL_halt
99 .end halt
diff --git a/arch/alpha/kernel/init_task.c b/arch/alpha/kernel/init_task.c
new file mode 100644
index 000000000000..835d09a7b332
--- /dev/null
+++ b/arch/alpha/kernel/init_task.c
@@ -0,0 +1,23 @@
1#include <linux/mm.h>
2#include <linux/module.h>
3#include <linux/sched.h>
4#include <linux/init.h>
5#include <linux/init_task.h>
6#include <linux/fs.h>
7#include <linux/mqueue.h>
8#include <asm/uaccess.h>
9
10
11static struct fs_struct init_fs = INIT_FS;
12static struct files_struct init_files = INIT_FILES;
13static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
14static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
15struct mm_struct init_mm = INIT_MM(init_mm);
16struct task_struct init_task = INIT_TASK(init_task);
17
18EXPORT_SYMBOL(init_mm);
19EXPORT_SYMBOL(init_task);
20
21union thread_union init_thread_union
22 __attribute__((section(".data.init_thread")))
23 = { INIT_THREAD_INFO(init_task) };
diff --git a/arch/alpha/kernel/io.c b/arch/alpha/kernel/io.c
new file mode 100644
index 000000000000..19c5875ab398
--- /dev/null
+++ b/arch/alpha/kernel/io.c
@@ -0,0 +1,630 @@
1/*
2 * Alpha IO and memory functions.
3 */
4
5#include <linux/kernel.h>
6#include <linux/types.h>
7#include <linux/string.h>
8#include <linux/module.h>
9#include <asm/io.h>
10
11/* Out-of-line versions of the i/o routines that redirect into the
12 platform-specific version. Note that "platform-specific" may mean
13 "generic", which bumps through the machine vector. */
14
15unsigned int
16ioread8(void __iomem *addr)
17{
18 unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr);
19 mb();
20 return ret;
21}
22
23unsigned int ioread16(void __iomem *addr)
24{
25 unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr);
26 mb();
27 return ret;
28}
29
30unsigned int ioread32(void __iomem *addr)
31{
32 unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr);
33 mb();
34 return ret;
35}
36
37void iowrite8(u8 b, void __iomem *addr)
38{
39 IO_CONCAT(__IO_PREFIX,iowrite8)(b, addr);
40 mb();
41}
42
43void iowrite16(u16 b, void __iomem *addr)
44{
45 IO_CONCAT(__IO_PREFIX,iowrite16)(b, addr);
46 mb();
47}
48
49void iowrite32(u32 b, void __iomem *addr)
50{
51 IO_CONCAT(__IO_PREFIX,iowrite32)(b, addr);
52 mb();
53}
54
55EXPORT_SYMBOL(ioread8);
56EXPORT_SYMBOL(ioread16);
57EXPORT_SYMBOL(ioread32);
58EXPORT_SYMBOL(iowrite8);
59EXPORT_SYMBOL(iowrite16);
60EXPORT_SYMBOL(iowrite32);
61
62u8 inb(unsigned long port)
63{
64 return ioread8(ioport_map(port, 1));
65}
66
67u16 inw(unsigned long port)
68{
69 return ioread16(ioport_map(port, 2));
70}
71
72u32 inl(unsigned long port)
73{
74 return ioread32(ioport_map(port, 4));
75}
76
77void outb(u8 b, unsigned long port)
78{
79 iowrite8(b, ioport_map(port, 1));
80}
81
82void outw(u16 b, unsigned long port)
83{
84 iowrite16(b, ioport_map(port, 2));
85}
86
87void outl(u32 b, unsigned long port)
88{
89 iowrite32(b, ioport_map(port, 4));
90}
91
92EXPORT_SYMBOL(inb);
93EXPORT_SYMBOL(inw);
94EXPORT_SYMBOL(inl);
95EXPORT_SYMBOL(outb);
96EXPORT_SYMBOL(outw);
97EXPORT_SYMBOL(outl);
98
99u8 __raw_readb(const volatile void __iomem *addr)
100{
101 return IO_CONCAT(__IO_PREFIX,readb)(addr);
102}
103
104u16 __raw_readw(const volatile void __iomem *addr)
105{
106 return IO_CONCAT(__IO_PREFIX,readw)(addr);
107}
108
109u32 __raw_readl(const volatile void __iomem *addr)
110{
111 return IO_CONCAT(__IO_PREFIX,readl)(addr);
112}
113
114u64 __raw_readq(const volatile void __iomem *addr)
115{
116 return IO_CONCAT(__IO_PREFIX,readq)(addr);
117}
118
119void __raw_writeb(u8 b, volatile void __iomem *addr)
120{
121 IO_CONCAT(__IO_PREFIX,writeb)(b, addr);
122}
123
124void __raw_writew(u16 b, volatile void __iomem *addr)
125{
126 IO_CONCAT(__IO_PREFIX,writew)(b, addr);
127}
128
129void __raw_writel(u32 b, volatile void __iomem *addr)
130{
131 IO_CONCAT(__IO_PREFIX,writel)(b, addr);
132}
133
134void __raw_writeq(u64 b, volatile void __iomem *addr)
135{
136 IO_CONCAT(__IO_PREFIX,writeq)(b, addr);
137}
138
139EXPORT_SYMBOL(__raw_readb);
140EXPORT_SYMBOL(__raw_readw);
141EXPORT_SYMBOL(__raw_readl);
142EXPORT_SYMBOL(__raw_readq);
143EXPORT_SYMBOL(__raw_writeb);
144EXPORT_SYMBOL(__raw_writew);
145EXPORT_SYMBOL(__raw_writel);
146EXPORT_SYMBOL(__raw_writeq);
147
148u8 readb(const volatile void __iomem *addr)
149{
150 u8 ret = __raw_readb(addr);
151 mb();
152 return ret;
153}
154
155u16 readw(const volatile void __iomem *addr)
156{
157 u16 ret = __raw_readw(addr);
158 mb();
159 return ret;
160}
161
162u32 readl(const volatile void __iomem *addr)
163{
164 u32 ret = __raw_readl(addr);
165 mb();
166 return ret;
167}
168
169u64 readq(const volatile void __iomem *addr)
170{
171 u64 ret = __raw_readq(addr);
172 mb();
173 return ret;
174}
175
176void writeb(u8 b, volatile void __iomem *addr)
177{
178 __raw_writeb(b, addr);
179 mb();
180}
181
182void writew(u16 b, volatile void __iomem *addr)
183{
184 __raw_writew(b, addr);
185 mb();
186}
187
188void writel(u32 b, volatile void __iomem *addr)
189{
190 __raw_writel(b, addr);
191 mb();
192}
193
194void writeq(u64 b, volatile void __iomem *addr)
195{
196 __raw_writeq(b, addr);
197 mb();
198}
199
200EXPORT_SYMBOL(readb);
201EXPORT_SYMBOL(readw);
202EXPORT_SYMBOL(readl);
203EXPORT_SYMBOL(readq);
204EXPORT_SYMBOL(writeb);
205EXPORT_SYMBOL(writew);
206EXPORT_SYMBOL(writel);
207EXPORT_SYMBOL(writeq);
208
209
210/*
211 * Read COUNT 8-bit bytes from port PORT into memory starting at SRC.
212 */
213void ioread8_rep(void __iomem *port, void *dst, unsigned long count)
214{
215 while ((unsigned long)dst & 0x3) {
216 if (!count)
217 return;
218 count--;
219 *(unsigned char *)dst = ioread8(port);
220 dst += 1;
221 }
222
223 while (count >= 4) {
224 unsigned int w;
225 count -= 4;
226 w = ioread8(port);
227 w |= ioread8(port) << 8;
228 w |= ioread8(port) << 16;
229 w |= ioread8(port) << 24;
230 *(unsigned int *)dst = w;
231 dst += 4;
232 }
233
234 while (count) {
235 --count;
236 *(unsigned char *)dst = ioread8(port);
237 dst += 1;
238 }
239}
240
241void insb(unsigned long port, void *dst, unsigned long count)
242{
243 ioread8_rep(ioport_map(port, 1), dst, count);
244}
245
246EXPORT_SYMBOL(ioread8_rep);
247EXPORT_SYMBOL(insb);
248
249/*
250 * Read COUNT 16-bit words from port PORT into memory starting at
251 * SRC. SRC must be at least short aligned. This is used by the
252 * IDE driver to read disk sectors. Performance is important, but
253 * the interfaces seems to be slow: just using the inlined version
254 * of the inw() breaks things.
255 */
256void ioread16_rep(void __iomem *port, void *dst, unsigned long count)
257{
258 if (unlikely((unsigned long)dst & 0x3)) {
259 if (!count)
260 return;
261 BUG_ON((unsigned long)dst & 0x1);
262 count--;
263 *(unsigned short *)dst = ioread16(port);
264 dst += 2;
265 }
266
267 while (count >= 2) {
268 unsigned int w;
269 count -= 2;
270 w = ioread16(port);
271 w |= ioread16(port) << 16;
272 *(unsigned int *)dst = w;
273 dst += 4;
274 }
275
276 if (count) {
277 *(unsigned short*)dst = ioread16(port);
278 }
279}
280
281void insw(unsigned long port, void *dst, unsigned long count)
282{
283 ioread16_rep(ioport_map(port, 2), dst, count);
284}
285
286EXPORT_SYMBOL(ioread16_rep);
287EXPORT_SYMBOL(insw);
288
289
290/*
291 * Read COUNT 32-bit words from port PORT into memory starting at
292 * SRC. Now works with any alignment in SRC. Performance is important,
293 * but the interfaces seems to be slow: just using the inlined version
294 * of the inl() breaks things.
295 */
296void ioread32_rep(void __iomem *port, void *dst, unsigned long count)
297{
298 if (unlikely((unsigned long)dst & 0x3)) {
299 while (count--) {
300 struct S { int x __attribute__((packed)); };
301 ((struct S *)dst)->x = ioread32(port);
302 dst += 4;
303 }
304 } else {
305 /* Buffer 32-bit aligned. */
306 while (count--) {
307 *(unsigned int *)dst = ioread32(port);
308 dst += 4;
309 }
310 }
311}
312
313void insl(unsigned long port, void *dst, unsigned long count)
314{
315 ioread32_rep(ioport_map(port, 4), dst, count);
316}
317
318EXPORT_SYMBOL(ioread32_rep);
319EXPORT_SYMBOL(insl);
320
321
322/*
323 * Like insb but in the opposite direction.
324 * Don't worry as much about doing aligned memory transfers:
325 * doing byte reads the "slow" way isn't nearly as slow as
326 * doing byte writes the slow way (no r-m-w cycle).
327 */
328void iowrite8_rep(void __iomem *port, const void *xsrc, unsigned long count)
329{
330 const unsigned char *src = xsrc;
331 while (count--)
332 iowrite8(*src++, port);
333}
334
335void outsb(unsigned long port, const void *src, unsigned long count)
336{
337 iowrite8_rep(ioport_map(port, 1), src, count);
338}
339
340EXPORT_SYMBOL(iowrite8_rep);
341EXPORT_SYMBOL(outsb);
342
343
344/*
345 * Like insw but in the opposite direction. This is used by the IDE
346 * driver to write disk sectors. Performance is important, but the
347 * interfaces seems to be slow: just using the inlined version of the
348 * outw() breaks things.
349 */
350void iowrite16_rep(void __iomem *port, const void *src, unsigned long count)
351{
352 if (unlikely((unsigned long)src & 0x3)) {
353 if (!count)
354 return;
355 BUG_ON((unsigned long)src & 0x1);
356 iowrite16(*(unsigned short *)src, port);
357 src += 2;
358 --count;
359 }
360
361 while (count >= 2) {
362 unsigned int w;
363 count -= 2;
364 w = *(unsigned int *)src;
365 src += 4;
366 iowrite16(w >> 0, port);
367 iowrite16(w >> 16, port);
368 }
369
370 if (count) {
371 iowrite16(*(unsigned short *)src, port);
372 }
373}
374
375void outsw(unsigned long port, const void *src, unsigned long count)
376{
377 iowrite16_rep(ioport_map(port, 2), src, count);
378}
379
380EXPORT_SYMBOL(iowrite16_rep);
381EXPORT_SYMBOL(outsw);
382
383
384/*
385 * Like insl but in the opposite direction. This is used by the IDE
386 * driver to write disk sectors. Works with any alignment in SRC.
387 * Performance is important, but the interfaces seems to be slow:
388 * just using the inlined version of the outl() breaks things.
389 */
390void iowrite32_rep(void __iomem *port, const void *src, unsigned long count)
391{
392 if (unlikely((unsigned long)src & 0x3)) {
393 while (count--) {
394 struct S { int x __attribute__((packed)); };
395 iowrite32(((struct S *)src)->x, port);
396 src += 4;
397 }
398 } else {
399 /* Buffer 32-bit aligned. */
400 while (count--) {
401 iowrite32(*(unsigned int *)src, port);
402 src += 4;
403 }
404 }
405}
406
407void outsl(unsigned long port, const void *src, unsigned long count)
408{
409 iowrite32_rep(ioport_map(port, 4), src, count);
410}
411
412EXPORT_SYMBOL(iowrite32_rep);
413EXPORT_SYMBOL(outsl);
414
415
416/*
417 * Copy data from IO memory space to "real" memory space.
418 * This needs to be optimized.
419 */
420void memcpy_fromio(void *to, const volatile void __iomem *from, long count)
421{
422 /* Optimize co-aligned transfers. Everything else gets handled
423 a byte at a time. */
424
425 if (count >= 8 && ((u64)to & 7) == ((u64)from & 7)) {
426 count -= 8;
427 do {
428 *(u64 *)to = __raw_readq(from);
429 count -= 8;
430 to += 8;
431 from += 8;
432 } while (count >= 0);
433 count += 8;
434 }
435
436 if (count >= 4 && ((u64)to & 3) == ((u64)from & 3)) {
437 count -= 4;
438 do {
439 *(u32 *)to = __raw_readl(from);
440 count -= 4;
441 to += 4;
442 from += 4;
443 } while (count >= 0);
444 count += 4;
445 }
446
447 if (count >= 2 && ((u64)to & 1) == ((u64)from & 1)) {
448 count -= 2;
449 do {
450 *(u16 *)to = __raw_readw(from);
451 count -= 2;
452 to += 2;
453 from += 2;
454 } while (count >= 0);
455 count += 2;
456 }
457
458 while (count > 0) {
459 *(u8 *) to = __raw_readb(from);
460 count--;
461 to++;
462 from++;
463 }
464 mb();
465}
466
467EXPORT_SYMBOL(memcpy_fromio);
468
469
470/*
471 * Copy data from "real" memory space to IO memory space.
472 * This needs to be optimized.
473 */
474void memcpy_toio(volatile void __iomem *to, const void *from, long count)
475{
476 /* Optimize co-aligned transfers. Everything else gets handled
477 a byte at a time. */
478 /* FIXME -- align FROM. */
479
480 if (count >= 8 && ((u64)to & 7) == ((u64)from & 7)) {
481 count -= 8;
482 do {
483 __raw_writeq(*(const u64 *)from, to);
484 count -= 8;
485 to += 8;
486 from += 8;
487 } while (count >= 0);
488 count += 8;
489 }
490
491 if (count >= 4 && ((u64)to & 3) == ((u64)from & 3)) {
492 count -= 4;
493 do {
494 __raw_writel(*(const u32 *)from, to);
495 count -= 4;
496 to += 4;
497 from += 4;
498 } while (count >= 0);
499 count += 4;
500 }
501
502 if (count >= 2 && ((u64)to & 1) == ((u64)from & 1)) {
503 count -= 2;
504 do {
505 __raw_writew(*(const u16 *)from, to);
506 count -= 2;
507 to += 2;
508 from += 2;
509 } while (count >= 0);
510 count += 2;
511 }
512
513 while (count > 0) {
514 __raw_writeb(*(const u8 *) from, to);
515 count--;
516 to++;
517 from++;
518 }
519 mb();
520}
521
522EXPORT_SYMBOL(memcpy_toio);
523
524
525/*
526 * "memset" on IO memory space.
527 */
528void _memset_c_io(volatile void __iomem *to, unsigned long c, long count)
529{
530 /* Handle any initial odd byte */
531 if (count > 0 && ((u64)to & 1)) {
532 __raw_writeb(c, to);
533 to++;
534 count--;
535 }
536
537 /* Handle any initial odd halfword */
538 if (count >= 2 && ((u64)to & 2)) {
539 __raw_writew(c, to);
540 to += 2;
541 count -= 2;
542 }
543
544 /* Handle any initial odd word */
545 if (count >= 4 && ((u64)to & 4)) {
546 __raw_writel(c, to);
547 to += 4;
548 count -= 4;
549 }
550
551 /* Handle all full-sized quadwords: we're aligned
552 (or have a small count) */
553 count -= 8;
554 if (count >= 0) {
555 do {
556 __raw_writeq(c, to);
557 to += 8;
558 count -= 8;
559 } while (count >= 0);
560 }
561 count += 8;
562
563 /* The tail is word-aligned if we still have count >= 4 */
564 if (count >= 4) {
565 __raw_writel(c, to);
566 to += 4;
567 count -= 4;
568 }
569
570 /* The tail is half-word aligned if we have count >= 2 */
571 if (count >= 2) {
572 __raw_writew(c, to);
573 to += 2;
574 count -= 2;
575 }
576
577 /* And finally, one last byte.. */
578 if (count) {
579 __raw_writeb(c, to);
580 }
581 mb();
582}
583
584EXPORT_SYMBOL(_memset_c_io);
585
586/* A version of memcpy used by the vga console routines to move data around
587 arbitrarily between screen and main memory. */
588
589void
590scr_memcpyw(u16 *d, const u16 *s, unsigned int count)
591{
592 const u16 __iomem *ios = (const u16 __iomem *) s;
593 u16 __iomem *iod = (u16 __iomem *) d;
594 int s_isio = __is_ioaddr(s);
595 int d_isio = __is_ioaddr(d);
596
597 if (s_isio) {
598 if (d_isio) {
599 /* FIXME: Should handle unaligned ops and
600 operation widening. */
601
602 count /= 2;
603 while (count--) {
604 u16 tmp = __raw_readw(ios++);
605 __raw_writew(tmp, iod++);
606 }
607 }
608 else
609 memcpy_fromio(d, ios, count);
610 } else {
611 if (d_isio)
612 memcpy_toio(iod, s, count);
613 else
614 memcpy(d, s, count);
615 }
616}
617
618EXPORT_SYMBOL(scr_memcpyw);
619
620void __iomem *ioport_map(unsigned long port, unsigned int size)
621{
622 return IO_CONCAT(__IO_PREFIX,ioportmap) (port);
623}
624
625void ioport_unmap(void __iomem *addr)
626{
627}
628
629EXPORT_SYMBOL(ioport_map);
630EXPORT_SYMBOL(ioport_unmap);
diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
new file mode 100644
index 000000000000..b6114f5c0d2b
--- /dev/null
+++ b/arch/alpha/kernel/irq.c
@@ -0,0 +1,774 @@
1/*
2 * linux/arch/alpha/kernel/irq.c
3 *
4 * Copyright (C) 1995 Linus Torvalds
5 *
6 * This file contains the code used by various IRQ handling routines:
7 * asking for different IRQ's should be done through these routines
8 * instead of just grabbing them. Thus setups with different IRQ numbers
9 * shouldn't result in any weird surprises, and installing new handlers
10 * should be easier.
11 */
12
13#include <linux/config.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/errno.h>
17#include <linux/kernel_stat.h>
18#include <linux/signal.h>
19#include <linux/sched.h>
20#include <linux/ptrace.h>
21#include <linux/interrupt.h>
22#include <linux/slab.h>
23#include <linux/random.h>
24#include <linux/init.h>
25#include <linux/irq.h>
26#include <linux/proc_fs.h>
27#include <linux/seq_file.h>
28#include <linux/profile.h>
29#include <linux/bitops.h>
30
31#include <asm/system.h>
32#include <asm/io.h>
33#include <asm/uaccess.h>
34
35/*
36 * Controller mappings for all interrupt sources:
37 */
38irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = {
39 [0 ... NR_IRQS-1] = {
40 .handler = &no_irq_type,
41 .lock = SPIN_LOCK_UNLOCKED
42 }
43};
44
45static void register_irq_proc(unsigned int irq);
46
47volatile unsigned long irq_err_count;
48
49/*
50 * Special irq handlers.
51 */
52
53irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs)
54{
55 return IRQ_NONE;
56}
57
58/*
59 * Generic no controller code
60 */
61
62static void no_irq_enable_disable(unsigned int irq) { }
63static unsigned int no_irq_startup(unsigned int irq) { return 0; }
64
65static void
66no_irq_ack(unsigned int irq)
67{
68 irq_err_count++;
69 printk(KERN_CRIT "Unexpected IRQ trap at vector %u\n", irq);
70}
71
72struct hw_interrupt_type no_irq_type = {
73 .typename = "none",
74 .startup = no_irq_startup,
75 .shutdown = no_irq_enable_disable,
76 .enable = no_irq_enable_disable,
77 .disable = no_irq_enable_disable,
78 .ack = no_irq_ack,
79 .end = no_irq_enable_disable,
80};
81
82int
83handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
84 struct irqaction *action)
85{
86 int status = 1; /* Force the "do bottom halves" bit */
87 int ret;
88
89 do {
90 if (!(action->flags & SA_INTERRUPT))
91 local_irq_enable();
92 else
93 local_irq_disable();
94
95 ret = action->handler(irq, action->dev_id, regs);
96 if (ret == IRQ_HANDLED)
97 status |= action->flags;
98 action = action->next;
99 } while (action);
100 if (status & SA_SAMPLE_RANDOM)
101 add_interrupt_randomness(irq);
102 local_irq_disable();
103
104 return status;
105}
106
107/*
108 * Generic enable/disable code: this just calls
109 * down into the PIC-specific version for the actual
110 * hardware disable after having gotten the irq
111 * controller lock.
112 */
113void inline
114disable_irq_nosync(unsigned int irq)
115{
116 irq_desc_t *desc = irq_desc + irq;
117 unsigned long flags;
118
119 spin_lock_irqsave(&desc->lock, flags);
120 if (!desc->depth++) {
121 desc->status |= IRQ_DISABLED;
122 desc->handler->disable(irq);
123 }
124 spin_unlock_irqrestore(&desc->lock, flags);
125}
126
127/*
128 * Synchronous version of the above, making sure the IRQ is
129 * no longer running on any other IRQ..
130 */
131void
132disable_irq(unsigned int irq)
133{
134 disable_irq_nosync(irq);
135 synchronize_irq(irq);
136}
137
138void
139enable_irq(unsigned int irq)
140{
141 irq_desc_t *desc = irq_desc + irq;
142 unsigned long flags;
143
144 spin_lock_irqsave(&desc->lock, flags);
145 switch (desc->depth) {
146 case 1: {
147 unsigned int status = desc->status & ~IRQ_DISABLED;
148 desc->status = status;
149 if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
150 desc->status = status | IRQ_REPLAY;
151 hw_resend_irq(desc->handler,irq);
152 }
153 desc->handler->enable(irq);
154 /* fall-through */
155 }
156 default:
157 desc->depth--;
158 break;
159 case 0:
160 printk(KERN_ERR "enable_irq() unbalanced from %p\n",
161 __builtin_return_address(0));
162 }
163 spin_unlock_irqrestore(&desc->lock, flags);
164}
165
166int
167setup_irq(unsigned int irq, struct irqaction * new)
168{
169 int shared = 0;
170 struct irqaction *old, **p;
171 unsigned long flags;
172 irq_desc_t *desc = irq_desc + irq;
173
174 if (desc->handler == &no_irq_type)
175 return -ENOSYS;
176
177 /*
178 * Some drivers like serial.c use request_irq() heavily,
179 * so we have to be careful not to interfere with a
180 * running system.
181 */
182 if (new->flags & SA_SAMPLE_RANDOM) {
183 /*
184 * This function might sleep, we want to call it first,
185 * outside of the atomic block.
186 * Yes, this might clear the entropy pool if the wrong
187 * driver is attempted to be loaded, without actually
188 * installing a new handler, but is this really a problem,
189 * only the sysadmin is able to do this.
190 */
191 rand_initialize_irq(irq);
192 }
193
194 /*
195 * The following block of code has to be executed atomically
196 */
197 spin_lock_irqsave(&desc->lock,flags);
198 p = &desc->action;
199 if ((old = *p) != NULL) {
200 /* Can't share interrupts unless both agree to */
201 if (!(old->flags & new->flags & SA_SHIRQ)) {
202 spin_unlock_irqrestore(&desc->lock,flags);
203 return -EBUSY;
204 }
205
206 /* add new interrupt at end of irq queue */
207 do {
208 p = &old->next;
209 old = *p;
210 } while (old);
211 shared = 1;
212 }
213
214 *p = new;
215
216 if (!shared) {
217 desc->depth = 0;
218 desc->status &=
219 ~(IRQ_DISABLED|IRQ_AUTODETECT|IRQ_WAITING|IRQ_INPROGRESS);
220 desc->handler->startup(irq);
221 }
222 spin_unlock_irqrestore(&desc->lock,flags);
223
224 return 0;
225}
226
227static struct proc_dir_entry * root_irq_dir;
228static struct proc_dir_entry * irq_dir[NR_IRQS];
229
230#ifdef CONFIG_SMP
231static struct proc_dir_entry * smp_affinity_entry[NR_IRQS];
232static char irq_user_affinity[NR_IRQS];
233static cpumask_t irq_affinity[NR_IRQS] = { [0 ... NR_IRQS-1] = CPU_MASK_ALL };
234
235static void
236select_smp_affinity(int irq)
237{
238 static int last_cpu;
239 int cpu = last_cpu + 1;
240
241 if (! irq_desc[irq].handler->set_affinity || irq_user_affinity[irq])
242 return;
243
244 while (!cpu_possible(cpu))
245 cpu = (cpu < (NR_CPUS-1) ? cpu + 1 : 0);
246 last_cpu = cpu;
247
248 irq_affinity[irq] = cpumask_of_cpu(cpu);
249 irq_desc[irq].handler->set_affinity(irq, cpumask_of_cpu(cpu));
250}
251
252static int
253irq_affinity_read_proc (char *page, char **start, off_t off,
254 int count, int *eof, void *data)
255{
256 int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]);
257 if (count - len < 2)
258 return -EINVAL;
259 len += sprintf(page + len, "\n");
260 return len;
261}
262
263static int
264irq_affinity_write_proc(struct file *file, const char __user *buffer,
265 unsigned long count, void *data)
266{
267 int irq = (long) data, full_count = count, err;
268 cpumask_t new_value;
269
270 if (!irq_desc[irq].handler->set_affinity)
271 return -EIO;
272
273 err = cpumask_parse(buffer, count, new_value);
274
275 /* The special value 0 means release control of the
276 affinity to kernel. */
277 cpus_and(new_value, new_value, cpu_online_map);
278 if (cpus_empty(new_value)) {
279 irq_user_affinity[irq] = 0;
280 select_smp_affinity(irq);
281 }
282 /* Do not allow disabling IRQs completely - it's a too easy
283 way to make the system unusable accidentally :-) At least
284 one online CPU still has to be targeted. */
285 else {
286 irq_affinity[irq] = new_value;
287 irq_user_affinity[irq] = 1;
288 irq_desc[irq].handler->set_affinity(irq, new_value);
289 }
290
291 return full_count;
292}
293
294#endif /* CONFIG_SMP */
295
296#define MAX_NAMELEN 10
297
298static void
299register_irq_proc (unsigned int irq)
300{
301 char name [MAX_NAMELEN];
302
303 if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) ||
304 irq_dir[irq])
305 return;
306
307 memset(name, 0, MAX_NAMELEN);
308 sprintf(name, "%d", irq);
309
310 /* create /proc/irq/1234 */
311 irq_dir[irq] = proc_mkdir(name, root_irq_dir);
312
313#ifdef CONFIG_SMP
314 if (irq_desc[irq].handler->set_affinity) {
315 struct proc_dir_entry *entry;
316 /* create /proc/irq/1234/smp_affinity */
317 entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
318
319 if (entry) {
320 entry->nlink = 1;
321 entry->data = (void *)(long)irq;
322 entry->read_proc = irq_affinity_read_proc;
323 entry->write_proc = irq_affinity_write_proc;
324 }
325
326 smp_affinity_entry[irq] = entry;
327 }
328#endif
329}
330
331void
332init_irq_proc (void)
333{
334 int i;
335
336 /* create /proc/irq */
337 root_irq_dir = proc_mkdir("irq", NULL);
338
339#ifdef CONFIG_SMP
340 /* create /proc/irq/prof_cpu_mask */
341 create_prof_cpu_mask(root_irq_dir);
342#endif
343
344 /*
345 * Create entries for all existing IRQs.
346 */
347 for (i = 0; i < ACTUAL_NR_IRQS; i++) {
348 if (irq_desc[i].handler == &no_irq_type)
349 continue;
350 register_irq_proc(i);
351 }
352}
353
354int
355request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
356 unsigned long irqflags, const char * devname, void *dev_id)
357{
358 int retval;
359 struct irqaction * action;
360
361 if (irq >= ACTUAL_NR_IRQS)
362 return -EINVAL;
363 if (!handler)
364 return -EINVAL;
365
366#if 1
367 /*
368 * Sanity-check: shared interrupts should REALLY pass in
369 * a real dev-ID, otherwise we'll have trouble later trying
370 * to figure out which interrupt is which (messes up the
371 * interrupt freeing logic etc).
372 */
373 if ((irqflags & SA_SHIRQ) && !dev_id) {
374 printk(KERN_ERR
375 "Bad boy: %s (at %p) called us without a dev_id!\n",
376 devname, __builtin_return_address(0));
377 }
378#endif
379
380 action = (struct irqaction *)
381 kmalloc(sizeof(struct irqaction), GFP_KERNEL);
382 if (!action)
383 return -ENOMEM;
384
385 action->handler = handler;
386 action->flags = irqflags;
387 cpus_clear(action->mask);
388 action->name = devname;
389 action->next = NULL;
390 action->dev_id = dev_id;
391
392#ifdef CONFIG_SMP
393 select_smp_affinity(irq);
394#endif
395
396 retval = setup_irq(irq, action);
397 if (retval)
398 kfree(action);
399 return retval;
400}
401
402EXPORT_SYMBOL(request_irq);
403
404void
405free_irq(unsigned int irq, void *dev_id)
406{
407 irq_desc_t *desc;
408 struct irqaction **p;
409 unsigned long flags;
410
411 if (irq >= ACTUAL_NR_IRQS) {
412 printk(KERN_CRIT "Trying to free IRQ%d\n", irq);
413 return;
414 }
415
416 desc = irq_desc + irq;
417 spin_lock_irqsave(&desc->lock,flags);
418 p = &desc->action;
419 for (;;) {
420 struct irqaction * action = *p;
421 if (action) {
422 struct irqaction **pp = p;
423 p = &action->next;
424 if (action->dev_id != dev_id)
425 continue;
426
427 /* Found - now remove it from the list of entries. */
428 *pp = action->next;
429 if (!desc->action) {
430 desc->status |= IRQ_DISABLED;
431 desc->handler->shutdown(irq);
432 }
433 spin_unlock_irqrestore(&desc->lock,flags);
434
435#ifdef CONFIG_SMP
436 /* Wait to make sure it's not being used on
437 another CPU. */
438 while (desc->status & IRQ_INPROGRESS)
439 barrier();
440#endif
441 kfree(action);
442 return;
443 }
444 printk(KERN_ERR "Trying to free free IRQ%d\n",irq);
445 spin_unlock_irqrestore(&desc->lock,flags);
446 return;
447 }
448}
449
450EXPORT_SYMBOL(free_irq);
451
452int
453show_interrupts(struct seq_file *p, void *v)
454{
455#ifdef CONFIG_SMP
456 int j;
457#endif
458 int i = *(loff_t *) v;
459 struct irqaction * action;
460 unsigned long flags;
461
462#ifdef CONFIG_SMP
463 if (i == 0) {
464 seq_puts(p, " ");
465 for (i = 0; i < NR_CPUS; i++)
466 if (cpu_online(i))
467 seq_printf(p, "CPU%d ", i);
468 seq_putc(p, '\n');
469 }
470#endif
471
472 if (i < ACTUAL_NR_IRQS) {
473 spin_lock_irqsave(&irq_desc[i].lock, flags);
474 action = irq_desc[i].action;
475 if (!action)
476 goto unlock;
477 seq_printf(p, "%3d: ",i);
478#ifndef CONFIG_SMP
479 seq_printf(p, "%10u ", kstat_irqs(i));
480#else
481 for (j = 0; j < NR_CPUS; j++)
482 if (cpu_online(j))
483 seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
484#endif
485 seq_printf(p, " %14s", irq_desc[i].handler->typename);
486 seq_printf(p, " %c%s",
487 (action->flags & SA_INTERRUPT)?'+':' ',
488 action->name);
489
490 for (action=action->next; action; action = action->next) {
491 seq_printf(p, ", %c%s",
492 (action->flags & SA_INTERRUPT)?'+':' ',
493 action->name);
494 }
495
496 seq_putc(p, '\n');
497unlock:
498 spin_unlock_irqrestore(&irq_desc[i].lock, flags);
499 } else if (i == ACTUAL_NR_IRQS) {
500#ifdef CONFIG_SMP
501 seq_puts(p, "IPI: ");
502 for (i = 0; i < NR_CPUS; i++)
503 if (cpu_online(i))
504 seq_printf(p, "%10lu ", cpu_data[i].ipi_count);
505 seq_putc(p, '\n');
506#endif
507 seq_printf(p, "ERR: %10lu\n", irq_err_count);
508 }
509 return 0;
510}
511
512
513/*
514 * handle_irq handles all normal device IRQ's (the special
515 * SMP cross-CPU interrupts have their own specific
516 * handlers).
517 */
518
519#define MAX_ILLEGAL_IRQS 16
520
521void
522handle_irq(int irq, struct pt_regs * regs)
523{
524 /*
525 * We ack quickly, we don't want the irq controller
526 * thinking we're snobs just because some other CPU has
527 * disabled global interrupts (we have already done the
528 * INT_ACK cycles, it's too late to try to pretend to the
529 * controller that we aren't taking the interrupt).
530 *
531 * 0 return value means that this irq is already being
532 * handled by some other CPU. (or is disabled)
533 */
534 int cpu = smp_processor_id();
535 irq_desc_t *desc = irq_desc + irq;
536 struct irqaction * action;
537 unsigned int status;
538 static unsigned int illegal_count=0;
539
540 if ((unsigned) irq > ACTUAL_NR_IRQS && illegal_count < MAX_ILLEGAL_IRQS ) {
541 irq_err_count++;
542 illegal_count++;
543 printk(KERN_CRIT "device_interrupt: invalid interrupt %d\n",
544 irq);
545 return;
546 }
547
548 irq_enter();
549 kstat_cpu(cpu).irqs[irq]++;
550 spin_lock_irq(&desc->lock); /* mask also the higher prio events */
551 desc->handler->ack(irq);
552 /*
553 * REPLAY is when Linux resends an IRQ that was dropped earlier.
554 * WAITING is used by probe to mark irqs that are being tested.
555 */
556 status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
557 status |= IRQ_PENDING; /* we _want_ to handle it */
558
559 /*
560 * If the IRQ is disabled for whatever reason, we cannot
561 * use the action we have.
562 */
563 action = NULL;
564 if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
565 action = desc->action;
566 status &= ~IRQ_PENDING; /* we commit to handling */
567 status |= IRQ_INPROGRESS; /* we are handling it */
568 }
569 desc->status = status;
570
571 /*
572 * If there is no IRQ handler or it was disabled, exit early.
573 * Since we set PENDING, if another processor is handling
574 * a different instance of this same irq, the other processor
575 * will take care of it.
576 */
577 if (!action)
578 goto out;
579
580 /*
581 * Edge triggered interrupts need to remember pending events.
582 * This applies to any hw interrupts that allow a second
583 * instance of the same irq to arrive while we are in handle_irq
584 * or in the handler. But the code here only handles the _second_
585 * instance of the irq, not the third or fourth. So it is mostly
586 * useful for irq hardware that does not mask cleanly in an
587 * SMP environment.
588 */
589 for (;;) {
590 spin_unlock(&desc->lock);
591 handle_IRQ_event(irq, regs, action);
592 spin_lock(&desc->lock);
593
594 if (!(desc->status & IRQ_PENDING)
595 || (desc->status & IRQ_LEVEL))
596 break;
597 desc->status &= ~IRQ_PENDING;
598 }
599 desc->status &= ~IRQ_INPROGRESS;
600out:
601 /*
602 * The ->end() handler has to deal with interrupts which got
603 * disabled while the handler was running.
604 */
605 desc->handler->end(irq);
606 spin_unlock(&desc->lock);
607
608 irq_exit();
609}
610
611/*
612 * IRQ autodetection code..
613 *
614 * This depends on the fact that any interrupt that
615 * comes in on to an unassigned handler will get stuck
616 * with "IRQ_WAITING" cleared and the interrupt
617 * disabled.
618 */
619unsigned long
620probe_irq_on(void)
621{
622 int i;
623 irq_desc_t *desc;
624 unsigned long delay;
625 unsigned long val;
626
627 /* Something may have generated an irq long ago and we want to
628 flush such a longstanding irq before considering it as spurious. */
629 for (i = NR_IRQS-1; i >= 0; i--) {
630 desc = irq_desc + i;
631
632 spin_lock_irq(&desc->lock);
633 if (!irq_desc[i].action)
634 irq_desc[i].handler->startup(i);
635 spin_unlock_irq(&desc->lock);
636 }
637
638 /* Wait for longstanding interrupts to trigger. */
639 for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
640 /* about 20ms delay */ barrier();
641
642 /* enable any unassigned irqs (we must startup again here because
643 if a longstanding irq happened in the previous stage, it may have
644 masked itself) first, enable any unassigned irqs. */
645 for (i = NR_IRQS-1; i >= 0; i--) {
646 desc = irq_desc + i;
647
648 spin_lock_irq(&desc->lock);
649 if (!desc->action) {
650 desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
651 if (desc->handler->startup(i))
652 desc->status |= IRQ_PENDING;
653 }
654 spin_unlock_irq(&desc->lock);
655 }
656
657 /*
658 * Wait for spurious interrupts to trigger
659 */
660 for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
661 /* about 100ms delay */ barrier();
662
663 /*
664 * Now filter out any obviously spurious interrupts
665 */
666 val = 0;
667 for (i=0; i<NR_IRQS; i++) {
668 irq_desc_t *desc = irq_desc + i;
669 unsigned int status;
670
671 spin_lock_irq(&desc->lock);
672 status = desc->status;
673
674 if (status & IRQ_AUTODETECT) {
675 /* It triggered already - consider it spurious. */
676 if (!(status & IRQ_WAITING)) {
677 desc->status = status & ~IRQ_AUTODETECT;
678 desc->handler->shutdown(i);
679 } else
680 if (i < 32)
681 val |= 1 << i;
682 }
683 spin_unlock_irq(&desc->lock);
684 }
685
686 return val;
687}
688
689EXPORT_SYMBOL(probe_irq_on);
690
691/*
692 * Return a mask of triggered interrupts (this
693 * can handle only legacy ISA interrupts).
694 */
695unsigned int
696probe_irq_mask(unsigned long val)
697{
698 int i;
699 unsigned int mask;
700
701 mask = 0;
702 for (i = 0; i < NR_IRQS; i++) {
703 irq_desc_t *desc = irq_desc + i;
704 unsigned int status;
705
706 spin_lock_irq(&desc->lock);
707 status = desc->status;
708
709 if (status & IRQ_AUTODETECT) {
710 /* We only react to ISA interrupts */
711 if (!(status & IRQ_WAITING)) {
712 if (i < 16)
713 mask |= 1 << i;
714 }
715
716 desc->status = status & ~IRQ_AUTODETECT;
717 desc->handler->shutdown(i);
718 }
719 spin_unlock_irq(&desc->lock);
720 }
721
722 return mask & val;
723}
724
725/*
726 * Get the result of the IRQ probe.. A negative result means that
727 * we have several candidates (but we return the lowest-numbered
728 * one).
729 */
730
731int
732probe_irq_off(unsigned long val)
733{
734 int i, irq_found, nr_irqs;
735
736 nr_irqs = 0;
737 irq_found = 0;
738 for (i=0; i<NR_IRQS; i++) {
739 irq_desc_t *desc = irq_desc + i;
740 unsigned int status;
741
742 spin_lock_irq(&desc->lock);
743 status = desc->status;
744
745 if (status & IRQ_AUTODETECT) {
746 if (!(status & IRQ_WAITING)) {
747 if (!nr_irqs)
748 irq_found = i;
749 nr_irqs++;
750 }
751 desc->status = status & ~IRQ_AUTODETECT;
752 desc->handler->shutdown(i);
753 }
754 spin_unlock_irq(&desc->lock);
755 }
756
757 if (nr_irqs > 1)
758 irq_found = -irq_found;
759 return irq_found;
760}
761
762EXPORT_SYMBOL(probe_irq_off);
763
764#ifdef CONFIG_SMP
765void synchronize_irq(unsigned int irq)
766{
767 /* is there anything to synchronize with? */
768 if (!irq_desc[irq].action)
769 return;
770
771 while (irq_desc[irq].status & IRQ_INPROGRESS)
772 barrier();
773}
774#endif
diff --git a/arch/alpha/kernel/irq_alpha.c b/arch/alpha/kernel/irq_alpha.c
new file mode 100644
index 000000000000..e6ded33c6e22
--- /dev/null
+++ b/arch/alpha/kernel/irq_alpha.c
@@ -0,0 +1,252 @@
1/*
2 * Alpha specific irq code.
3 */
4
5#include <linux/config.h>
6#include <linux/init.h>
7#include <linux/sched.h>
8#include <linux/irq.h>
9#include <linux/kernel_stat.h>
10
11#include <asm/machvec.h>
12#include <asm/dma.h>
13
14#include "proto.h"
15#include "irq_impl.h"
16
17/* Hack minimum IPL during interrupt processing for broken hardware. */
18#ifdef CONFIG_ALPHA_BROKEN_IRQ_MASK
19int __min_ipl;
20#endif
21
22/*
23 * Performance counter hook. A module can override this to
24 * do something useful.
25 */
26static void
27dummy_perf(unsigned long vector, struct pt_regs *regs)
28{
29 irq_err_count++;
30 printk(KERN_CRIT "Performance counter interrupt!\n");
31}
32
33void (*perf_irq)(unsigned long, struct pt_regs *) = dummy_perf;
34
35/*
36 * The main interrupt entry point.
37 */
38
39asmlinkage void
40do_entInt(unsigned long type, unsigned long vector,
41 unsigned long la_ptr, struct pt_regs *regs)
42{
43 switch (type) {
44 case 0:
45#ifdef CONFIG_SMP
46 handle_ipi(regs);
47 return;
48#else
49 irq_err_count++;
50 printk(KERN_CRIT "Interprocessor interrupt? "
51 "You must be kidding!\n");
52#endif
53 break;
54 case 1:
55#ifdef CONFIG_SMP
56 {
57 long cpu;
58 smp_percpu_timer_interrupt(regs);
59 cpu = smp_processor_id();
60 if (cpu != boot_cpuid) {
61 kstat_cpu(cpu).irqs[RTC_IRQ]++;
62 } else {
63 handle_irq(RTC_IRQ, regs);
64 }
65 }
66#else
67 handle_irq(RTC_IRQ, regs);
68#endif
69 return;
70 case 2:
71 alpha_mv.machine_check(vector, la_ptr, regs);
72 return;
73 case 3:
74 alpha_mv.device_interrupt(vector, regs);
75 return;
76 case 4:
77 perf_irq(la_ptr, regs);
78 return;
79 default:
80 printk(KERN_CRIT "Hardware intr %ld %lx? Huh?\n",
81 type, vector);
82 }
83 printk(KERN_CRIT "PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
84}
85
86void __init
87common_init_isa_dma(void)
88{
89 outb(0, DMA1_RESET_REG);
90 outb(0, DMA2_RESET_REG);
91 outb(0, DMA1_CLR_MASK_REG);
92 outb(0, DMA2_CLR_MASK_REG);
93}
94
95void __init
96init_IRQ(void)
97{
98 /* Just in case the platform init_irq() causes interrupts/mchecks
99 (as is the case with RAWHIDE, at least). */
100 wrent(entInt, 0);
101
102 alpha_mv.init_irq();
103}
104
105/*
106 * machine error checks
107 */
108#define MCHK_K_TPERR 0x0080
109#define MCHK_K_TCPERR 0x0082
110#define MCHK_K_HERR 0x0084
111#define MCHK_K_ECC_C 0x0086
112#define MCHK_K_ECC_NC 0x0088
113#define MCHK_K_OS_BUGCHECK 0x008A
114#define MCHK_K_PAL_BUGCHECK 0x0090
115
116#ifndef CONFIG_SMP
117struct mcheck_info __mcheck_info;
118#endif
119
120void
121process_mcheck_info(unsigned long vector, unsigned long la_ptr,
122 struct pt_regs *regs, const char *machine,
123 int expected)
124{
125 struct el_common *mchk_header;
126 const char *reason;
127
128 /*
129 * See if the machine check is due to a badaddr() and if so,
130 * ignore it.
131 */
132
133#ifdef CONFIG_VERBOSE_MCHECK
134 if (alpha_verbose_mcheck > 1) {
135 printk(KERN_CRIT "%s machine check %s\n", machine,
136 expected ? "expected." : "NOT expected!!!");
137 }
138#endif
139
140 if (expected) {
141 int cpu = smp_processor_id();
142 mcheck_expected(cpu) = 0;
143 mcheck_taken(cpu) = 1;
144 return;
145 }
146
147 mchk_header = (struct el_common *)la_ptr;
148
149 printk(KERN_CRIT "%s machine check: vector=0x%lx pc=0x%lx code=0x%x\n",
150 machine, vector, regs->pc, mchk_header->code);
151
152 switch (mchk_header->code) {
153 /* Machine check reasons. Defined according to PALcode sources. */
154 case 0x80: reason = "tag parity error"; break;
155 case 0x82: reason = "tag control parity error"; break;
156 case 0x84: reason = "generic hard error"; break;
157 case 0x86: reason = "correctable ECC error"; break;
158 case 0x88: reason = "uncorrectable ECC error"; break;
159 case 0x8A: reason = "OS-specific PAL bugcheck"; break;
160 case 0x90: reason = "callsys in kernel mode"; break;
161 case 0x96: reason = "i-cache read retryable error"; break;
162 case 0x98: reason = "processor detected hard error"; break;
163
164 /* System specific (these are for Alcor, at least): */
165 case 0x202: reason = "system detected hard error"; break;
166 case 0x203: reason = "system detected uncorrectable ECC error"; break;
167 case 0x204: reason = "SIO SERR occurred on PCI bus"; break;
168 case 0x205: reason = "parity error detected by core logic"; break;
169 case 0x206: reason = "SIO IOCHK occurred on ISA bus"; break;
170 case 0x207: reason = "non-existent memory error"; break;
171 case 0x208: reason = "MCHK_K_DCSR"; break;
172 case 0x209: reason = "PCI SERR detected"; break;
173 case 0x20b: reason = "PCI data parity error detected"; break;
174 case 0x20d: reason = "PCI address parity error detected"; break;
175 case 0x20f: reason = "PCI master abort error"; break;
176 case 0x211: reason = "PCI target abort error"; break;
177 case 0x213: reason = "scatter/gather PTE invalid error"; break;
178 case 0x215: reason = "flash ROM write error"; break;
179 case 0x217: reason = "IOA timeout detected"; break;
180 case 0x219: reason = "IOCHK#, EISA add-in board parity or other catastrophic error"; break;
181 case 0x21b: reason = "EISA fail-safe timer timeout"; break;
182 case 0x21d: reason = "EISA bus time-out"; break;
183 case 0x21f: reason = "EISA software generated NMI"; break;
184 case 0x221: reason = "unexpected ev5 IRQ[3] interrupt"; break;
185 default: reason = "unknown"; break;
186 }
187
188 printk(KERN_CRIT "machine check type: %s%s\n",
189 reason, mchk_header->retry ? " (retryable)" : "");
190
191 dik_show_regs(regs, NULL);
192
193#ifdef CONFIG_VERBOSE_MCHECK
194 if (alpha_verbose_mcheck > 1) {
195 /* Dump the logout area to give all info. */
196 unsigned long *ptr = (unsigned long *)la_ptr;
197 long i;
198 for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
199 printk(KERN_CRIT " +%8lx %016lx %016lx\n",
200 i*sizeof(long), ptr[i], ptr[i+1]);
201 }
202 }
203#endif /* CONFIG_VERBOSE_MCHECK */
204}
205
206/*
207 * The special RTC interrupt type. The interrupt itself was
208 * processed by PALcode, and comes in via entInt vector 1.
209 */
210
211static void rtc_enable_disable(unsigned int irq) { }
212static unsigned int rtc_startup(unsigned int irq) { return 0; }
213
214struct irqaction timer_irqaction = {
215 .handler = timer_interrupt,
216 .flags = SA_INTERRUPT,
217 .name = "timer",
218};
219
220static struct hw_interrupt_type rtc_irq_type = {
221 .typename = "RTC",
222 .startup = rtc_startup,
223 .shutdown = rtc_enable_disable,
224 .enable = rtc_enable_disable,
225 .disable = rtc_enable_disable,
226 .ack = rtc_enable_disable,
227 .end = rtc_enable_disable,
228};
229
230void __init
231init_rtc_irq(void)
232{
233 irq_desc[RTC_IRQ].status = IRQ_DISABLED;
234 irq_desc[RTC_IRQ].handler = &rtc_irq_type;
235 setup_irq(RTC_IRQ, &timer_irqaction);
236}
237
238/* Dummy irqactions. */
239struct irqaction isa_cascade_irqaction = {
240 .handler = no_action,
241 .name = "isa-cascade"
242};
243
244struct irqaction timer_cascade_irqaction = {
245 .handler = no_action,
246 .name = "timer-cascade"
247};
248
249struct irqaction halt_switch_irqaction = {
250 .handler = no_action,
251 .name = "halt-switch"
252};
diff --git a/arch/alpha/kernel/irq_i8259.c b/arch/alpha/kernel/irq_i8259.c
new file mode 100644
index 000000000000..b188683b83fd
--- /dev/null
+++ b/arch/alpha/kernel/irq_i8259.c
@@ -0,0 +1,183 @@
1/*
2 * linux/arch/alpha/kernel/irq_i8259.c
3 *
4 * This is the 'legacy' 8259A Programmable Interrupt Controller,
5 * present in the majority of PC/AT boxes.
6 *
7 * Started hacking from linux-2.3.30pre6/arch/i386/kernel/i8259.c.
8 */
9
10#include <linux/config.h>
11#include <linux/init.h>
12#include <linux/cache.h>
13#include <linux/sched.h>
14#include <linux/irq.h>
15#include <linux/interrupt.h>
16
17#include <asm/io.h>
18
19#include "proto.h"
20#include "irq_impl.h"
21
22
23/* Note mask bit is true for DISABLED irqs. */
24static unsigned int cached_irq_mask = 0xffff;
25static DEFINE_SPINLOCK(i8259_irq_lock);
26
27static inline void
28i8259_update_irq_hw(unsigned int irq, unsigned long mask)
29{
30 int port = 0x21;
31 if (irq & 8) mask >>= 8;
32 if (irq & 8) port = 0xA1;
33 outb(mask, port);
34}
35
36inline void
37i8259a_enable_irq(unsigned int irq)
38{
39 spin_lock(&i8259_irq_lock);
40 i8259_update_irq_hw(irq, cached_irq_mask &= ~(1 << irq));
41 spin_unlock(&i8259_irq_lock);
42}
43
44static inline void
45__i8259a_disable_irq(unsigned int irq)
46{
47 i8259_update_irq_hw(irq, cached_irq_mask |= 1 << irq);
48}
49
50void
51i8259a_disable_irq(unsigned int irq)
52{
53 spin_lock(&i8259_irq_lock);
54 __i8259a_disable_irq(irq);
55 spin_unlock(&i8259_irq_lock);
56}
57
58void
59i8259a_mask_and_ack_irq(unsigned int irq)
60{
61 spin_lock(&i8259_irq_lock);
62 __i8259a_disable_irq(irq);
63
64 /* Ack the interrupt making it the lowest priority. */
65 if (irq >= 8) {
66 outb(0xE0 | (irq - 8), 0xa0); /* ack the slave */
67 irq = 2;
68 }
69 outb(0xE0 | irq, 0x20); /* ack the master */
70 spin_unlock(&i8259_irq_lock);
71}
72
73unsigned int
74i8259a_startup_irq(unsigned int irq)
75{
76 i8259a_enable_irq(irq);
77 return 0; /* never anything pending */
78}
79
80void
81i8259a_end_irq(unsigned int irq)
82{
83 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
84 i8259a_enable_irq(irq);
85}
86
87struct hw_interrupt_type i8259a_irq_type = {
88 .typename = "XT-PIC",
89 .startup = i8259a_startup_irq,
90 .shutdown = i8259a_disable_irq,
91 .enable = i8259a_enable_irq,
92 .disable = i8259a_disable_irq,
93 .ack = i8259a_mask_and_ack_irq,
94 .end = i8259a_end_irq,
95};
96
97void __init
98init_i8259a_irqs(void)
99{
100 static struct irqaction cascade = {
101 .handler = no_action,
102 .name = "cascade",
103 };
104
105 long i;
106
107 outb(0xff, 0x21); /* mask all of 8259A-1 */
108 outb(0xff, 0xA1); /* mask all of 8259A-2 */
109
110 for (i = 0; i < 16; i++) {
111 irq_desc[i].status = IRQ_DISABLED;
112 irq_desc[i].handler = &i8259a_irq_type;
113 }
114
115 setup_irq(2, &cascade);
116}
117
118
119#if defined(CONFIG_ALPHA_GENERIC)
120# define IACK_SC alpha_mv.iack_sc
121#elif defined(CONFIG_ALPHA_APECS)
122# define IACK_SC APECS_IACK_SC
123#elif defined(CONFIG_ALPHA_LCA)
124# define IACK_SC LCA_IACK_SC
125#elif defined(CONFIG_ALPHA_CIA)
126# define IACK_SC CIA_IACK_SC
127#elif defined(CONFIG_ALPHA_PYXIS)
128# define IACK_SC PYXIS_IACK_SC
129#elif defined(CONFIG_ALPHA_TITAN)
130# define IACK_SC TITAN_IACK_SC
131#elif defined(CONFIG_ALPHA_TSUNAMI)
132# define IACK_SC TSUNAMI_IACK_SC
133#elif defined(CONFIG_ALPHA_IRONGATE)
134# define IACK_SC IRONGATE_IACK_SC
135#endif
136/* Note that CONFIG_ALPHA_POLARIS is intentionally left out here, since
137 sys_rx164 wants to use isa_no_iack_sc_device_interrupt for some reason. */
138
139#if defined(IACK_SC)
140void
141isa_device_interrupt(unsigned long vector, struct pt_regs *regs)
142{
143 /*
144 * Generate a PCI interrupt acknowledge cycle. The PIC will
145 * respond with the interrupt vector of the highest priority
146 * interrupt that is pending. The PALcode sets up the
147 * interrupts vectors such that irq level L generates vector L.
148 */
149 int j = *(vuip) IACK_SC;
150 j &= 0xff;
151 handle_irq(j, regs);
152}
153#endif
154
155#if defined(CONFIG_ALPHA_GENERIC) || !defined(IACK_SC)
156void
157isa_no_iack_sc_device_interrupt(unsigned long vector, struct pt_regs *regs)
158{
159 unsigned long pic;
160
161 /*
162 * It seems to me that the probability of two or more *device*
163 * interrupts occurring at almost exactly the same time is
164 * pretty low. So why pay the price of checking for
165 * additional interrupts here if the common case can be
166 * handled so much easier?
167 */
168 /*
169 * The first read of gives you *all* interrupting lines.
170 * Therefore, read the mask register and and out those lines
171 * not enabled. Note that some documentation has 21 and a1
172 * write only. This is not true.
173 */
174 pic = inb(0x20) | (inb(0xA0) << 8); /* read isr */
175 pic &= 0xFFFB; /* mask out cascade & hibits */
176
177 while (pic) {
178 int j = ffz(~pic);
179 pic &= pic - 1;
180 handle_irq(j, regs);
181 }
182}
183#endif
diff --git a/arch/alpha/kernel/irq_impl.h b/arch/alpha/kernel/irq_impl.h
new file mode 100644
index 000000000000..f201d8ffc0d9
--- /dev/null
+++ b/arch/alpha/kernel/irq_impl.h
@@ -0,0 +1,42 @@
1/*
2 * linux/arch/alpha/kernel/irq_impl.h
3 *
4 * Copyright (C) 1995 Linus Torvalds
5 * Copyright (C) 1998, 2000 Richard Henderson
6 *
7 * This file contains declarations and inline functions for interfacing
8 * with the IRQ handling routines in irq.c.
9 */
10
11#include <linux/interrupt.h>
12#include <linux/irq.h>
13#include <linux/profile.h>
14
15
16#define RTC_IRQ 8
17
18extern void isa_device_interrupt(unsigned long, struct pt_regs *);
19extern void isa_no_iack_sc_device_interrupt(unsigned long, struct pt_regs *);
20extern void srm_device_interrupt(unsigned long, struct pt_regs *);
21extern void pyxis_device_interrupt(unsigned long, struct pt_regs *);
22
23extern struct irqaction timer_irqaction;
24extern struct irqaction isa_cascade_irqaction;
25extern struct irqaction timer_cascade_irqaction;
26extern struct irqaction halt_switch_irqaction;
27
28extern void init_srm_irqs(long, unsigned long);
29extern void init_pyxis_irqs(unsigned long);
30extern void init_rtc_irq(void);
31
32extern void common_init_isa_dma(void);
33
34extern void i8259a_enable_irq(unsigned int);
35extern void i8259a_disable_irq(unsigned int);
36extern void i8259a_mask_and_ack_irq(unsigned int);
37extern unsigned int i8259a_startup_irq(unsigned int);
38extern void i8259a_end_irq(unsigned int);
39extern struct hw_interrupt_type i8259a_irq_type;
40extern void init_i8259a_irqs(void);
41
42extern void handle_irq(int irq, struct pt_regs * regs);
diff --git a/arch/alpha/kernel/irq_pyxis.c b/arch/alpha/kernel/irq_pyxis.c
new file mode 100644
index 000000000000..146a20b9e3d5
--- /dev/null
+++ b/arch/alpha/kernel/irq_pyxis.c
@@ -0,0 +1,127 @@
1/*
2 * linux/arch/alpha/kernel/irq_pyxis.c
3 *
4 * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com).
5 *
6 * IRQ Code common to all PYXIS core logic chips.
7 */
8
9#include <linux/init.h>
10#include <linux/sched.h>
11#include <linux/irq.h>
12
13#include <asm/io.h>
14#include <asm/core_cia.h>
15
16#include "proto.h"
17#include "irq_impl.h"
18
19
20/* Note mask bit is true for ENABLED irqs. */
21static unsigned long cached_irq_mask;
22
23static inline void
24pyxis_update_irq_hw(unsigned long mask)
25{
26 *(vulp)PYXIS_INT_MASK = mask;
27 mb();
28 *(vulp)PYXIS_INT_MASK;
29}
30
31static inline void
32pyxis_enable_irq(unsigned int irq)
33{
34 pyxis_update_irq_hw(cached_irq_mask |= 1UL << (irq - 16));
35}
36
37static void
38pyxis_disable_irq(unsigned int irq)
39{
40 pyxis_update_irq_hw(cached_irq_mask &= ~(1UL << (irq - 16)));
41}
42
43static unsigned int
44pyxis_startup_irq(unsigned int irq)
45{
46 pyxis_enable_irq(irq);
47 return 0;
48}
49
50static void
51pyxis_end_irq(unsigned int irq)
52{
53 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
54 pyxis_enable_irq(irq);
55}
56
57static void
58pyxis_mask_and_ack_irq(unsigned int irq)
59{
60 unsigned long bit = 1UL << (irq - 16);
61 unsigned long mask = cached_irq_mask &= ~bit;
62
63 /* Disable the interrupt. */
64 *(vulp)PYXIS_INT_MASK = mask;
65 wmb();
66 /* Ack PYXIS PCI interrupt. */
67 *(vulp)PYXIS_INT_REQ = bit;
68 mb();
69 /* Re-read to force both writes. */
70 *(vulp)PYXIS_INT_MASK;
71}
72
73static struct hw_interrupt_type pyxis_irq_type = {
74 .typename = "PYXIS",
75 .startup = pyxis_startup_irq,
76 .shutdown = pyxis_disable_irq,
77 .enable = pyxis_enable_irq,
78 .disable = pyxis_disable_irq,
79 .ack = pyxis_mask_and_ack_irq,
80 .end = pyxis_end_irq,
81};
82
83void
84pyxis_device_interrupt(unsigned long vector, struct pt_regs *regs)
85{
86 unsigned long pld;
87 unsigned int i;
88
89 /* Read the interrupt summary register of PYXIS */
90 pld = *(vulp)PYXIS_INT_REQ;
91 pld &= cached_irq_mask;
92
93 /*
94 * Now for every possible bit set, work through them and call
95 * the appropriate interrupt handler.
96 */
97 while (pld) {
98 i = ffz(~pld);
99 pld &= pld - 1; /* clear least bit set */
100 if (i == 7)
101 isa_device_interrupt(vector, regs);
102 else
103 handle_irq(16+i, regs);
104 }
105}
106
107void __init
108init_pyxis_irqs(unsigned long ignore_mask)
109{
110 long i;
111
112 *(vulp)PYXIS_INT_MASK = 0; /* disable all */
113 *(vulp)PYXIS_INT_REQ = -1; /* flush all */
114 mb();
115
116 /* Send -INTA pulses to clear any pending interrupts ...*/
117 *(vuip) CIA_IACK_SC;
118
119 for (i = 16; i < 48; ++i) {
120 if ((ignore_mask >> i) & 1)
121 continue;
122 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
123 irq_desc[i].handler = &pyxis_irq_type;
124 }
125
126 setup_irq(16+7, &isa_cascade_irqaction);
127}
diff --git a/arch/alpha/kernel/irq_srm.c b/arch/alpha/kernel/irq_srm.c
new file mode 100644
index 000000000000..0a87e466918c
--- /dev/null
+++ b/arch/alpha/kernel/irq_srm.c
@@ -0,0 +1,79 @@
1/*
2 * Handle interrupts from the SRM, assuming no additional weirdness.
3 */
4
5#include <linux/init.h>
6#include <linux/sched.h>
7#include <linux/irq.h>
8
9#include "proto.h"
10#include "irq_impl.h"
11
12
13/*
14 * Is the palcode SMP safe? In other words: can we call cserve_ena/dis
15 * at the same time in multiple CPUs? To be safe I added a spinlock
16 * but it can be removed trivially if the palcode is robust against smp.
17 */
18DEFINE_SPINLOCK(srm_irq_lock);
19
20static inline void
21srm_enable_irq(unsigned int irq)
22{
23 spin_lock(&srm_irq_lock);
24 cserve_ena(irq - 16);
25 spin_unlock(&srm_irq_lock);
26}
27
28static void
29srm_disable_irq(unsigned int irq)
30{
31 spin_lock(&srm_irq_lock);
32 cserve_dis(irq - 16);
33 spin_unlock(&srm_irq_lock);
34}
35
36static unsigned int
37srm_startup_irq(unsigned int irq)
38{
39 srm_enable_irq(irq);
40 return 0;
41}
42
43static void
44srm_end_irq(unsigned int irq)
45{
46 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
47 srm_enable_irq(irq);
48}
49
50/* Handle interrupts from the SRM, assuming no additional weirdness. */
51static struct hw_interrupt_type srm_irq_type = {
52 .typename = "SRM",
53 .startup = srm_startup_irq,
54 .shutdown = srm_disable_irq,
55 .enable = srm_enable_irq,
56 .disable = srm_disable_irq,
57 .ack = srm_disable_irq,
58 .end = srm_end_irq,
59};
60
61void __init
62init_srm_irqs(long max, unsigned long ignore_mask)
63{
64 long i;
65
66 for (i = 16; i < max; ++i) {
67 if (i < 64 && ((ignore_mask >> i) & 1))
68 continue;
69 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
70 irq_desc[i].handler = &srm_irq_type;
71 }
72}
73
74void
75srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
76{
77 int irq = (vector - 0x800) >> 4;
78 handle_irq(irq, regs);
79}
diff --git a/arch/alpha/kernel/machvec_impl.h b/arch/alpha/kernel/machvec_impl.h
new file mode 100644
index 000000000000..4959b7a3e1e6
--- /dev/null
+++ b/arch/alpha/kernel/machvec_impl.h
@@ -0,0 +1,150 @@
1/*
2 * linux/arch/alpha/kernel/machvec.h
3 *
4 * Copyright (C) 1997, 1998 Richard Henderson
5 *
6 * This file has goodies to help simplify instantiation of machine vectors.
7 */
8
9#include <linux/config.h>
10#include <asm/pgalloc.h>
11
12/* Whee. These systems don't have an HAE:
13 IRONGATE, MARVEL, POLARIS, TSUNAMI, TITAN, WILDFIRE
14 Fix things up for the GENERIC kernel by defining the HAE address
15 to be that of the cache. Now we can read and write it as we like. ;-) */
16#define IRONGATE_HAE_ADDRESS (&alpha_mv.hae_cache)
17#define MARVEL_HAE_ADDRESS (&alpha_mv.hae_cache)
18#define POLARIS_HAE_ADDRESS (&alpha_mv.hae_cache)
19#define TSUNAMI_HAE_ADDRESS (&alpha_mv.hae_cache)
20#define TITAN_HAE_ADDRESS (&alpha_mv.hae_cache)
21#define WILDFIRE_HAE_ADDRESS (&alpha_mv.hae_cache)
22
23#ifdef CIA_ONE_HAE_WINDOW
24#define CIA_HAE_ADDRESS (&alpha_mv.hae_cache)
25#endif
26#ifdef MCPCIA_ONE_HAE_WINDOW
27#define MCPCIA_HAE_ADDRESS (&alpha_mv.hae_cache)
28#endif
29
30/* Only a few systems don't define IACK_SC, handling all interrupts through
31 the SRM console. But splitting out that one case from IO() below
32 seems like such a pain. Define this to get things to compile. */
33#define JENSEN_IACK_SC 1
34#define T2_IACK_SC 1
35#define WILDFIRE_IACK_SC 1 /* FIXME */
36
37/*
38 * Some helpful macros for filling in the blanks.
39 */
40
41#define CAT1(x,y) x##y
42#define CAT(x,y) CAT1(x,y)
43
44#define DO_DEFAULT_RTC rtc_port: 0x70
45
46#define DO_EV4_MMU \
47 .max_asn = EV4_MAX_ASN, \
48 .mv_switch_mm = ev4_switch_mm, \
49 .mv_activate_mm = ev4_activate_mm, \
50 .mv_flush_tlb_current = ev4_flush_tlb_current, \
51 .mv_flush_tlb_current_page = ev4_flush_tlb_current_page
52
53#define DO_EV5_MMU \
54 .max_asn = EV5_MAX_ASN, \
55 .mv_switch_mm = ev5_switch_mm, \
56 .mv_activate_mm = ev5_activate_mm, \
57 .mv_flush_tlb_current = ev5_flush_tlb_current, \
58 .mv_flush_tlb_current_page = ev5_flush_tlb_current_page
59
60#define DO_EV6_MMU \
61 .max_asn = EV6_MAX_ASN, \
62 .mv_switch_mm = ev5_switch_mm, \
63 .mv_activate_mm = ev5_activate_mm, \
64 .mv_flush_tlb_current = ev5_flush_tlb_current, \
65 .mv_flush_tlb_current_page = ev5_flush_tlb_current_page
66
67#define DO_EV7_MMU \
68 .max_asn = EV6_MAX_ASN, \
69 .mv_switch_mm = ev5_switch_mm, \
70 .mv_activate_mm = ev5_activate_mm, \
71 .mv_flush_tlb_current = ev5_flush_tlb_current, \
72 .mv_flush_tlb_current_page = ev5_flush_tlb_current_page
73
74#define IO_LITE(UP,low) \
75 .hae_register = (unsigned long *) CAT(UP,_HAE_ADDRESS), \
76 .iack_sc = CAT(UP,_IACK_SC), \
77 .mv_ioread8 = CAT(low,_ioread8), \
78 .mv_ioread16 = CAT(low,_ioread16), \
79 .mv_ioread32 = CAT(low,_ioread32), \
80 .mv_iowrite8 = CAT(low,_iowrite8), \
81 .mv_iowrite16 = CAT(low,_iowrite16), \
82 .mv_iowrite32 = CAT(low,_iowrite32), \
83 .mv_readb = CAT(low,_readb), \
84 .mv_readw = CAT(low,_readw), \
85 .mv_readl = CAT(low,_readl), \
86 .mv_readq = CAT(low,_readq), \
87 .mv_writeb = CAT(low,_writeb), \
88 .mv_writew = CAT(low,_writew), \
89 .mv_writel = CAT(low,_writel), \
90 .mv_writeq = CAT(low,_writeq), \
91 .mv_ioportmap = CAT(low,_ioportmap), \
92 .mv_ioremap = CAT(low,_ioremap), \
93 .mv_iounmap = CAT(low,_iounmap), \
94 .mv_is_ioaddr = CAT(low,_is_ioaddr), \
95 .mv_is_mmio = CAT(low,_is_mmio) \
96
97#define IO(UP,low) \
98 IO_LITE(UP,low), \
99 .pci_ops = &CAT(low,_pci_ops), \
100 .mv_pci_tbi = CAT(low,_pci_tbi)
101
102#define DO_APECS_IO IO(APECS,apecs)
103#define DO_CIA_IO IO(CIA,cia)
104#define DO_IRONGATE_IO IO(IRONGATE,irongate)
105#define DO_LCA_IO IO(LCA,lca)
106#define DO_MARVEL_IO IO(MARVEL,marvel)
107#define DO_MCPCIA_IO IO(MCPCIA,mcpcia)
108#define DO_POLARIS_IO IO(POLARIS,polaris)
109#define DO_T2_IO IO(T2,t2)
110#define DO_TSUNAMI_IO IO(TSUNAMI,tsunami)
111#define DO_TITAN_IO IO(TITAN,titan)
112#define DO_WILDFIRE_IO IO(WILDFIRE,wildfire)
113
114#define DO_PYXIS_IO IO_LITE(CIA,cia_bwx), \
115 .pci_ops = &cia_pci_ops, \
116 .mv_pci_tbi = cia_pci_tbi
117
118/*
119 * In a GENERIC kernel, we have lots of these vectors floating about,
120 * all but one of which we want to go away. In a non-GENERIC kernel,
121 * we want only one, ever.
122 *
123 * Accomplish this in the GENERIC kernel by putting all of the vectors
124 * in the .init.data section where they'll go away. We'll copy the
125 * one we want to the real alpha_mv vector in setup_arch.
126 *
127 * Accomplish this in a non-GENERIC kernel by ifdef'ing out all but
128 * one of the vectors, which will not reside in .init.data. We then
129 * alias this one vector to alpha_mv, so no copy is needed.
130 *
131 * Upshot: set __initdata to nothing for non-GENERIC kernels.
132 */
133
134#ifdef CONFIG_ALPHA_GENERIC
135#define __initmv __initdata
136#define ALIAS_MV(x)
137#else
138#define __initmv
139
140/* GCC actually has a syntax for defining aliases, but is under some
141 delusion that you shouldn't be able to declare it extern somewhere
142 else beforehand. Fine. We'll do it ourselves. */
143#if 0
144#define ALIAS_MV(system) \
145 struct alpha_machine_vector alpha_mv __attribute__((alias(#system "_mv")));
146#else
147#define ALIAS_MV(system) \
148 asm(".global alpha_mv\nalpha_mv = " #system "_mv");
149#endif
150#endif /* GENERIC */
diff --git a/arch/alpha/kernel/module.c b/arch/alpha/kernel/module.c
new file mode 100644
index 000000000000..fc271e316a38
--- /dev/null
+++ b/arch/alpha/kernel/module.c
@@ -0,0 +1,311 @@
1/* Kernel module help for Alpha.
2 Copyright (C) 2002 Richard Henderson.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17*/
18#include <linux/moduleloader.h>
19#include <linux/elf.h>
20#include <linux/vmalloc.h>
21#include <linux/fs.h>
22#include <linux/string.h>
23#include <linux/kernel.h>
24#include <linux/slab.h>
25
26#if 0
27#define DEBUGP printk
28#else
29#define DEBUGP(fmt...)
30#endif
31
32void *
33module_alloc(unsigned long size)
34{
35 if (size == 0)
36 return NULL;
37 return vmalloc(size);
38}
39
40void
41module_free(struct module *mod, void *module_region)
42{
43 vfree(module_region);
44}
45
46/* Allocate the GOT at the end of the core sections. */
47
48struct got_entry {
49 struct got_entry *next;
50 Elf64_Addr r_offset;
51 int got_offset;
52};
53
54static inline void
55process_reloc_for_got(Elf64_Rela *rela,
56 struct got_entry *chains, Elf64_Xword *poffset)
57{
58 unsigned long r_sym = ELF64_R_SYM (rela->r_info);
59 unsigned long r_type = ELF64_R_TYPE (rela->r_info);
60 Elf64_Addr r_offset = rela->r_offset;
61 struct got_entry *g;
62
63 if (r_type != R_ALPHA_LITERAL)
64 return;
65
66 for (g = chains + r_sym; g ; g = g->next)
67 if (g->r_offset == r_offset) {
68 if (g->got_offset == 0) {
69 g->got_offset = *poffset;
70 *poffset += 8;
71 }
72 goto found_entry;
73 }
74
75 g = kmalloc (sizeof (*g), GFP_KERNEL);
76 g->next = chains[r_sym].next;
77 g->r_offset = r_offset;
78 g->got_offset = *poffset;
79 *poffset += 8;
80 chains[r_sym].next = g;
81
82 found_entry:
83 /* Trick: most of the ELF64_R_TYPE field is unused. There are
84 42 valid relocation types, and a 32-bit field. Co-opt the
85 bits above 256 to store the got offset for this reloc. */
86 rela->r_info |= g->got_offset << 8;
87}
88
89int
90module_frob_arch_sections(Elf64_Ehdr *hdr, Elf64_Shdr *sechdrs,
91 char *secstrings, struct module *me)
92{
93 struct got_entry *chains;
94 Elf64_Rela *rela;
95 Elf64_Shdr *esechdrs, *symtab, *s, *got;
96 unsigned long nsyms, nrela, i;
97
98 esechdrs = sechdrs + hdr->e_shnum;
99 symtab = got = NULL;
100
101 /* Find out how large the symbol table is. Allocate one got_entry
102 head per symbol. Normally this will be enough, but not always.
103 We'll chain different offsets for the symbol down each head. */
104 for (s = sechdrs; s < esechdrs; ++s)
105 if (s->sh_type == SHT_SYMTAB)
106 symtab = s;
107 else if (!strcmp(".got", secstrings + s->sh_name)) {
108 got = s;
109 me->arch.gotsecindex = s - sechdrs;
110 }
111
112 if (!symtab) {
113 printk(KERN_ERR "module %s: no symbol table\n", me->name);
114 return -ENOEXEC;
115 }
116 if (!got) {
117 printk(KERN_ERR "module %s: no got section\n", me->name);
118 return -ENOEXEC;
119 }
120
121 nsyms = symtab->sh_size / sizeof(Elf64_Sym);
122 chains = kmalloc(nsyms * sizeof(struct got_entry), GFP_KERNEL);
123 memset(chains, 0, nsyms * sizeof(struct got_entry));
124
125 got->sh_size = 0;
126 got->sh_addralign = 8;
127 got->sh_type = SHT_NOBITS;
128
129 /* Examine all LITERAL relocations to find out what GOT entries
130 are required. This sizes the GOT section as well. */
131 for (s = sechdrs; s < esechdrs; ++s)
132 if (s->sh_type == SHT_RELA) {
133 nrela = s->sh_size / sizeof(Elf64_Rela);
134 rela = (void *)hdr + s->sh_offset;
135 for (i = 0; i < nrela; ++i)
136 process_reloc_for_got(rela+i, chains,
137 &got->sh_size);
138 }
139
140 /* Free the memory we allocated. */
141 for (i = 0; i < nsyms; ++i) {
142 struct got_entry *g, *n;
143 for (g = chains[i].next; g ; g = n) {
144 n = g->next;
145 kfree(g);
146 }
147 }
148 kfree(chains);
149
150 return 0;
151}
152
153int
154apply_relocate(Elf64_Shdr *sechdrs, const char *strtab, unsigned int symindex,
155 unsigned int relsec, struct module *me)
156{
157 printk(KERN_ERR "module %s: REL relocation unsupported\n", me->name);
158 return -ENOEXEC;
159}
160
161int
162apply_relocate_add(Elf64_Shdr *sechdrs, const char *strtab,
163 unsigned int symindex, unsigned int relsec,
164 struct module *me)
165{
166 Elf64_Rela *rela = (void *)sechdrs[relsec].sh_addr;
167 unsigned long i, n = sechdrs[relsec].sh_size / sizeof(*rela);
168 Elf64_Sym *symtab, *sym;
169 void *base, *location;
170 unsigned long got, gp;
171
172 DEBUGP("Applying relocate section %u to %u\n", relsec,
173 sechdrs[relsec].sh_info);
174
175 base = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr;
176 symtab = (Elf64_Sym *)sechdrs[symindex].sh_addr;
177
178 /* The small sections were sorted to the end of the segment.
179 The following should definitely cover them. */
180 gp = (u64)me->module_core + me->core_size - 0x8000;
181 got = sechdrs[me->arch.gotsecindex].sh_addr;
182
183 for (i = 0; i < n; i++) {
184 unsigned long r_sym = ELF64_R_SYM (rela[i].r_info);
185 unsigned long r_type = ELF64_R_TYPE (rela[i].r_info);
186 unsigned long r_got_offset = r_type >> 8;
187 unsigned long value, hi, lo;
188 r_type &= 0xff;
189
190 /* This is where to make the change. */
191 location = base + rela[i].r_offset;
192
193 /* This is the symbol it is referring to. Note that all
194 unresolved symbols have been resolved. */
195 sym = symtab + r_sym;
196 value = sym->st_value + rela[i].r_addend;
197
198 switch (r_type) {
199 case R_ALPHA_NONE:
200 break;
201 case R_ALPHA_REFQUAD:
202 /* BUG() can produce misaligned relocations. */
203 ((u32 *)location)[0] = value;
204 ((u32 *)location)[1] = value >> 32;
205 break;
206 case R_ALPHA_GPREL32:
207 value -= gp;
208 if ((int)value != value)
209 goto reloc_overflow;
210 *(u32 *)location = value;
211 break;
212 case R_ALPHA_LITERAL:
213 hi = got + r_got_offset;
214 lo = hi - gp;
215 if ((short)lo != lo)
216 goto reloc_overflow;
217 *(u16 *)location = lo;
218 *(u64 *)hi = value;
219 break;
220 case R_ALPHA_LITUSE:
221 break;
222 case R_ALPHA_GPDISP:
223 value = gp - (u64)location;
224 lo = (short)value;
225 hi = (int)(value - lo);
226 if (hi + lo != value)
227 goto reloc_overflow;
228 *(u16 *)location = hi >> 16;
229 *(u16 *)(location + rela[i].r_addend) = lo;
230 break;
231 case R_ALPHA_BRSGP:
232 /* BRSGP is only allowed to bind to local symbols.
233 If the section is undef, this means that the
234 value was resolved from somewhere else. */
235 if (sym->st_shndx == SHN_UNDEF)
236 goto reloc_overflow;
237 if ((sym->st_other & STO_ALPHA_STD_GPLOAD) ==
238 STO_ALPHA_STD_GPLOAD)
239 /* Omit the prologue. */
240 value += 8;
241 /* FALLTHRU */
242 case R_ALPHA_BRADDR:
243 value -= (u64)location + 4;
244 if (value & 3)
245 goto reloc_overflow;
246 value = (long)value >> 2;
247 if (value + (1<<21) >= 1<<22)
248 goto reloc_overflow;
249 value &= 0x1fffff;
250 value |= *(u32 *)location & ~0x1fffff;
251 *(u32 *)location = value;
252 break;
253 case R_ALPHA_HINT:
254 break;
255 case R_ALPHA_SREL32:
256 value -= (u64)location;
257 if ((int)value != value)
258 goto reloc_overflow;
259 *(u32 *)location = value;
260 break;
261 case R_ALPHA_SREL64:
262 value -= (u64)location;
263 *(u64 *)location = value;
264 break;
265 case R_ALPHA_GPRELHIGH:
266 value = (long)(value - gp + 0x8000) >> 16;
267 if ((short) value != value)
268 goto reloc_overflow;
269 *(u16 *)location = value;
270 break;
271 case R_ALPHA_GPRELLOW:
272 value -= gp;
273 *(u16 *)location = value;
274 break;
275 case R_ALPHA_GPREL16:
276 value -= gp;
277 if ((short) value != value)
278 goto reloc_overflow;
279 *(u16 *)location = value;
280 break;
281 default:
282 printk(KERN_ERR "module %s: Unknown relocation: %lu\n",
283 me->name, r_type);
284 return -ENOEXEC;
285 reloc_overflow:
286 if (ELF64_ST_TYPE (sym->st_info) == STT_SECTION)
287 printk(KERN_ERR
288 "module %s: Relocation overflow vs section %d\n",
289 me->name, sym->st_shndx);
290 else
291 printk(KERN_ERR
292 "module %s: Relocation overflow vs %s\n",
293 me->name, strtab + sym->st_name);
294 return -ENOEXEC;
295 }
296 }
297
298 return 0;
299}
300
301int
302module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
303 struct module *me)
304{
305 return 0;
306}
307
308void
309module_arch_cleanup(struct module *mod)
310{
311}
diff --git a/arch/alpha/kernel/ns87312.c b/arch/alpha/kernel/ns87312.c
new file mode 100644
index 000000000000..342b56d24c20
--- /dev/null
+++ b/arch/alpha/kernel/ns87312.c
@@ -0,0 +1,38 @@
1/*
2 * linux/arch/alpha/kernel/ns87312.c
3 */
4
5#include <linux/init.h>
6#include <asm/io.h>
7#include "proto.h"
8
9
10/*
11 * The SRM console *disables* the IDE interface, this code ensures it's
12 * enabled.
13 *
14 * This code bangs on a control register of the 87312 Super I/O chip
15 * that implements parallel port/serial ports/IDE/FDI. Depending on
16 * the motherboard, the Super I/O chip can be configured through a
17 * pair of registers that are located either at I/O ports 0x26e/0x26f
18 * or 0x398/0x399. Unfortunately, autodetecting which base address is
19 * in use works only once (right after a reset). The Super I/O chip
20 * has the additional quirk that configuration register data must be
21 * written twice (I believe this is a safety feature to prevent
22 * accidental modification---fun, isn't it?).
23 */
24
25void __init
26ns87312_enable_ide(long ide_base)
27{
28 int data;
29 unsigned long flags;
30
31 local_irq_save(flags);
32 outb(0, ide_base); /* set the index register for reg #0 */
33 data = inb(ide_base+1); /* read the current contents */
34 outb(0, ide_base); /* set the index register for reg #0 */
35 outb(data | 0x40, ide_base+1); /* turn on IDE */
36 outb(data | 0x40, ide_base+1); /* turn on IDE, really! */
37 local_irq_restore(flags);
38}
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
new file mode 100644
index 000000000000..b5d0fd2bb10a
--- /dev/null
+++ b/arch/alpha/kernel/osf_sys.c
@@ -0,0 +1,1345 @@
1/*
2 * linux/arch/alpha/kernel/osf_sys.c
3 *
4 * Copyright (C) 1995 Linus Torvalds
5 */
6
7/*
8 * This file handles some of the stranger OSF/1 system call interfaces.
9 * Some of the system calls expect a non-C calling standard, others have
10 * special parameter blocks..
11 */
12
13#include <linux/errno.h>
14#include <linux/sched.h>
15#include <linux/kernel.h>
16#include <linux/mm.h>
17#include <linux/smp.h>
18#include <linux/smp_lock.h>
19#include <linux/stddef.h>
20#include <linux/syscalls.h>
21#include <linux/unistd.h>
22#include <linux/ptrace.h>
23#include <linux/slab.h>
24#include <linux/user.h>
25#include <linux/a.out.h>
26#include <linux/utsname.h>
27#include <linux/time.h>
28#include <linux/timex.h>
29#include <linux/major.h>
30#include <linux/stat.h>
31#include <linux/mman.h>
32#include <linux/shm.h>
33#include <linux/poll.h>
34#include <linux/file.h>
35#include <linux/types.h>
36#include <linux/ipc.h>
37#include <linux/namei.h>
38#include <linux/uio.h>
39#include <linux/vfs.h>
40
41#include <asm/fpu.h>
42#include <asm/io.h>
43#include <asm/uaccess.h>
44#include <asm/system.h>
45#include <asm/sysinfo.h>
46#include <asm/hwrpb.h>
47#include <asm/processor.h>
48
49extern int do_pipe(int *);
50
51/*
52 * Brk needs to return an error. Still support Linux's brk(0) query idiom,
53 * which OSF programs just shouldn't be doing. We're still not quite
54 * identical to OSF as we don't return 0 on success, but doing otherwise
55 * would require changes to libc. Hopefully this is good enough.
56 */
57asmlinkage unsigned long
58osf_brk(unsigned long brk)
59{
60 unsigned long retval = sys_brk(brk);
61 if (brk && brk != retval)
62 retval = -ENOMEM;
63 return retval;
64}
65
66/*
67 * This is pure guess-work..
68 */
69asmlinkage int
70osf_set_program_attributes(unsigned long text_start, unsigned long text_len,
71 unsigned long bss_start, unsigned long bss_len)
72{
73 struct mm_struct *mm;
74
75 lock_kernel();
76 mm = current->mm;
77 mm->end_code = bss_start + bss_len;
78 mm->brk = bss_start + bss_len;
79#if 0
80 printk("set_program_attributes(%lx %lx %lx %lx)\n",
81 text_start, text_len, bss_start, bss_len);
82#endif
83 unlock_kernel();
84 return 0;
85}
86
87/*
88 * OSF/1 directory handling functions...
89 *
90 * The "getdents()" interface is much more sane: the "basep" stuff is
91 * braindamage (it can't really handle filesystems where the directory
92 * offset differences aren't the same as "d_reclen").
93 */
94#define NAME_OFFSET offsetof (struct osf_dirent, d_name)
95#define ROUND_UP(x) (((x)+3) & ~3)
96
97struct osf_dirent {
98 unsigned int d_ino;
99 unsigned short d_reclen;
100 unsigned short d_namlen;
101 char d_name[1];
102};
103
104struct osf_dirent_callback {
105 struct osf_dirent __user *dirent;
106 long __user *basep;
107 unsigned int count;
108 int error;
109};
110
111static int
112osf_filldir(void *__buf, const char *name, int namlen, loff_t offset,
113 ino_t ino, unsigned int d_type)
114{
115 struct osf_dirent __user *dirent;
116 struct osf_dirent_callback *buf = (struct osf_dirent_callback *) __buf;
117 unsigned int reclen = ROUND_UP(NAME_OFFSET + namlen + 1);
118
119 buf->error = -EINVAL; /* only used if we fail */
120 if (reclen > buf->count)
121 return -EINVAL;
122 if (buf->basep) {
123 if (put_user(offset, buf->basep))
124 return -EFAULT;
125 buf->basep = NULL;
126 }
127 dirent = buf->dirent;
128 put_user(ino, &dirent->d_ino);
129 put_user(namlen, &dirent->d_namlen);
130 put_user(reclen, &dirent->d_reclen);
131 if (copy_to_user(dirent->d_name, name, namlen) ||
132 put_user(0, dirent->d_name + namlen))
133 return -EFAULT;
134 dirent = (void __user *)dirent + reclen;
135 buf->dirent = dirent;
136 buf->count -= reclen;
137 return 0;
138}
139
140asmlinkage int
141osf_getdirentries(unsigned int fd, struct osf_dirent __user *dirent,
142 unsigned int count, long __user *basep)
143{
144 int error;
145 struct file *file;
146 struct osf_dirent_callback buf;
147
148 error = -EBADF;
149 file = fget(fd);
150 if (!file)
151 goto out;
152
153 buf.dirent = dirent;
154 buf.basep = basep;
155 buf.count = count;
156 buf.error = 0;
157
158 error = vfs_readdir(file, osf_filldir, &buf);
159 if (error < 0)
160 goto out_putf;
161
162 error = buf.error;
163 if (count != buf.count)
164 error = count - buf.count;
165
166 out_putf:
167 fput(file);
168 out:
169 return error;
170}
171
172#undef ROUND_UP
173#undef NAME_OFFSET
174
175asmlinkage unsigned long
176osf_mmap(unsigned long addr, unsigned long len, unsigned long prot,
177 unsigned long flags, unsigned long fd, unsigned long off)
178{
179 struct file *file = NULL;
180 unsigned long ret = -EBADF;
181
182#if 0
183 if (flags & (_MAP_HASSEMAPHORE | _MAP_INHERIT | _MAP_UNALIGNED))
184 printk("%s: unimplemented OSF mmap flags %04lx\n",
185 current->comm, flags);
186#endif
187 if (!(flags & MAP_ANONYMOUS)) {
188 file = fget(fd);
189 if (!file)
190 goto out;
191 }
192 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
193 down_write(&current->mm->mmap_sem);
194 ret = do_mmap(file, addr, len, prot, flags, off);
195 up_write(&current->mm->mmap_sem);
196 if (file)
197 fput(file);
198 out:
199 return ret;
200}
201
202
203/*
204 * The OSF/1 statfs structure is much larger, but this should
205 * match the beginning, at least.
206 */
207struct osf_statfs {
208 short f_type;
209 short f_flags;
210 int f_fsize;
211 int f_bsize;
212 int f_blocks;
213 int f_bfree;
214 int f_bavail;
215 int f_files;
216 int f_ffree;
217 __kernel_fsid_t f_fsid;
218};
219
220static int
221linux_to_osf_statfs(struct kstatfs *linux_stat, struct osf_statfs __user *osf_stat,
222 unsigned long bufsiz)
223{
224 struct osf_statfs tmp_stat;
225
226 tmp_stat.f_type = linux_stat->f_type;
227 tmp_stat.f_flags = 0; /* mount flags */
228 tmp_stat.f_fsize = linux_stat->f_frsize;
229 tmp_stat.f_bsize = linux_stat->f_bsize;
230 tmp_stat.f_blocks = linux_stat->f_blocks;
231 tmp_stat.f_bfree = linux_stat->f_bfree;
232 tmp_stat.f_bavail = linux_stat->f_bavail;
233 tmp_stat.f_files = linux_stat->f_files;
234 tmp_stat.f_ffree = linux_stat->f_ffree;
235 tmp_stat.f_fsid = linux_stat->f_fsid;
236 if (bufsiz > sizeof(tmp_stat))
237 bufsiz = sizeof(tmp_stat);
238 return copy_to_user(osf_stat, &tmp_stat, bufsiz) ? -EFAULT : 0;
239}
240
241static int
242do_osf_statfs(struct dentry * dentry, struct osf_statfs __user *buffer,
243 unsigned long bufsiz)
244{
245 struct kstatfs linux_stat;
246 int error = vfs_statfs(dentry->d_inode->i_sb, &linux_stat);
247 if (!error)
248 error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz);
249 return error;
250}
251
252asmlinkage int
253osf_statfs(char __user *path, struct osf_statfs __user *buffer, unsigned long bufsiz)
254{
255 struct nameidata nd;
256 int retval;
257
258 retval = user_path_walk(path, &nd);
259 if (!retval) {
260 retval = do_osf_statfs(nd.dentry, buffer, bufsiz);
261 path_release(&nd);
262 }
263 return retval;
264}
265
266asmlinkage int
267osf_fstatfs(unsigned long fd, struct osf_statfs __user *buffer, unsigned long bufsiz)
268{
269 struct file *file;
270 int retval;
271
272 retval = -EBADF;
273 file = fget(fd);
274 if (file) {
275 retval = do_osf_statfs(file->f_dentry, buffer, bufsiz);
276 fput(file);
277 }
278 return retval;
279}
280
281/*
282 * Uhh.. OSF/1 mount parameters aren't exactly obvious..
283 *
284 * Although to be frank, neither are the native Linux/i386 ones..
285 */
286struct ufs_args {
287 char __user *devname;
288 int flags;
289 uid_t exroot;
290};
291
292struct cdfs_args {
293 char __user *devname;
294 int flags;
295 uid_t exroot;
296
297 /* This has lots more here, which Linux handles with the option block
298 but I'm too lazy to do the translation into ASCII. */
299};
300
301struct procfs_args {
302 char __user *devname;
303 int flags;
304 uid_t exroot;
305};
306
307/*
308 * We can't actually handle ufs yet, so we translate UFS mounts to
309 * ext2fs mounts. I wouldn't mind a UFS filesystem, but the UFS
310 * layout is so braindead it's a major headache doing it.
311 *
312 * Just how long ago was it written? OTOH our UFS driver may be still
313 * unhappy with OSF UFS. [CHECKME]
314 */
315static int
316osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
317{
318 int retval;
319 struct cdfs_args tmp;
320 char *devname;
321
322 retval = -EFAULT;
323 if (copy_from_user(&tmp, args, sizeof(tmp)))
324 goto out;
325 devname = getname(tmp.devname);
326 retval = PTR_ERR(devname);
327 if (IS_ERR(devname))
328 goto out;
329 retval = do_mount(devname, dirname, "ext2", flags, NULL);
330 putname(devname);
331 out:
332 return retval;
333}
334
335static int
336osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
337{
338 int retval;
339 struct cdfs_args tmp;
340 char *devname;
341
342 retval = -EFAULT;
343 if (copy_from_user(&tmp, args, sizeof(tmp)))
344 goto out;
345 devname = getname(tmp.devname);
346 retval = PTR_ERR(devname);
347 if (IS_ERR(devname))
348 goto out;
349 retval = do_mount(devname, dirname, "iso9660", flags, NULL);
350 putname(devname);
351 out:
352 return retval;
353}
354
355static int
356osf_procfs_mount(char *dirname, struct procfs_args __user *args, int flags)
357{
358 struct procfs_args tmp;
359
360 if (copy_from_user(&tmp, args, sizeof(tmp)))
361 return -EFAULT;
362
363 return do_mount("", dirname, "proc", flags, NULL);
364}
365
366asmlinkage int
367osf_mount(unsigned long typenr, char __user *path, int flag, void __user *data)
368{
369 int retval = -EINVAL;
370 char *name;
371
372 lock_kernel();
373
374 name = getname(path);
375 retval = PTR_ERR(name);
376 if (IS_ERR(name))
377 goto out;
378 switch (typenr) {
379 case 1:
380 retval = osf_ufs_mount(name, data, flag);
381 break;
382 case 6:
383 retval = osf_cdfs_mount(name, data, flag);
384 break;
385 case 9:
386 retval = osf_procfs_mount(name, data, flag);
387 break;
388 default:
389 printk("osf_mount(%ld, %x)\n", typenr, flag);
390 }
391 putname(name);
392 out:
393 unlock_kernel();
394 return retval;
395}
396
397asmlinkage int
398osf_utsname(char __user *name)
399{
400 int error;
401
402 down_read(&uts_sem);
403 error = -EFAULT;
404 if (copy_to_user(name + 0, system_utsname.sysname, 32))
405 goto out;
406 if (copy_to_user(name + 32, system_utsname.nodename, 32))
407 goto out;
408 if (copy_to_user(name + 64, system_utsname.release, 32))
409 goto out;
410 if (copy_to_user(name + 96, system_utsname.version, 32))
411 goto out;
412 if (copy_to_user(name + 128, system_utsname.machine, 32))
413 goto out;
414
415 error = 0;
416 out:
417 up_read(&uts_sem);
418 return error;
419}
420
421asmlinkage unsigned long
422sys_getpagesize(void)
423{
424 return PAGE_SIZE;
425}
426
427asmlinkage unsigned long
428sys_getdtablesize(void)
429{
430 return NR_OPEN;
431}
432
433/*
434 * For compatibility with OSF/1 only. Use utsname(2) instead.
435 */
436asmlinkage int
437osf_getdomainname(char __user *name, int namelen)
438{
439 unsigned len;
440 int i;
441
442 if (!access_ok(VERIFY_WRITE, name, namelen))
443 return -EFAULT;
444
445 len = namelen;
446 if (namelen > 32)
447 len = 32;
448
449 down_read(&uts_sem);
450 for (i = 0; i < len; ++i) {
451 __put_user(system_utsname.domainname[i], name + i);
452 if (system_utsname.domainname[i] == '\0')
453 break;
454 }
455 up_read(&uts_sem);
456
457 return 0;
458}
459
460asmlinkage long
461osf_shmat(int shmid, void __user *shmaddr, int shmflg)
462{
463 unsigned long raddr;
464 long err;
465
466 err = do_shmat(shmid, shmaddr, shmflg, &raddr);
467
468 /*
469 * This works because all user-level addresses are
470 * non-negative longs!
471 */
472 return err ? err : (long)raddr;
473}
474
475
476/*
477 * The following stuff should move into a header file should it ever
478 * be labeled "officially supported." Right now, there is just enough
479 * support to avoid applications (such as tar) printing error
480 * messages. The attributes are not really implemented.
481 */
482
483/*
484 * Values for Property list entry flag
485 */
486#define PLE_PROPAGATE_ON_COPY 0x1 /* cp(1) will copy entry
487 by default */
488#define PLE_FLAG_MASK 0x1 /* Valid flag values */
489#define PLE_FLAG_ALL -1 /* All flag value */
490
491struct proplistname_args {
492 unsigned int pl_mask;
493 unsigned int pl_numnames;
494 char **pl_names;
495};
496
497union pl_args {
498 struct setargs {
499 char __user *path;
500 long follow;
501 long nbytes;
502 char __user *buf;
503 } set;
504 struct fsetargs {
505 long fd;
506 long nbytes;
507 char __user *buf;
508 } fset;
509 struct getargs {
510 char __user *path;
511 long follow;
512 struct proplistname_args __user *name_args;
513 long nbytes;
514 char __user *buf;
515 int __user *min_buf_size;
516 } get;
517 struct fgetargs {
518 long fd;
519 struct proplistname_args __user *name_args;
520 long nbytes;
521 char __user *buf;
522 int __user *min_buf_size;
523 } fget;
524 struct delargs {
525 char __user *path;
526 long follow;
527 struct proplistname_args __user *name_args;
528 } del;
529 struct fdelargs {
530 long fd;
531 struct proplistname_args __user *name_args;
532 } fdel;
533};
534
535enum pl_code {
536 PL_SET = 1, PL_FSET = 2,
537 PL_GET = 3, PL_FGET = 4,
538 PL_DEL = 5, PL_FDEL = 6
539};
540
541asmlinkage long
542osf_proplist_syscall(enum pl_code code, union pl_args __user *args)
543{
544 long error;
545 int __user *min_buf_size_ptr;
546
547 lock_kernel();
548 switch (code) {
549 case PL_SET:
550 if (get_user(error, &args->set.nbytes))
551 error = -EFAULT;
552 break;
553 case PL_FSET:
554 if (get_user(error, &args->fset.nbytes))
555 error = -EFAULT;
556 break;
557 case PL_GET:
558 error = get_user(min_buf_size_ptr, &args->get.min_buf_size);
559 if (error)
560 break;
561 error = put_user(0, min_buf_size_ptr);
562 break;
563 case PL_FGET:
564 error = get_user(min_buf_size_ptr, &args->fget.min_buf_size);
565 if (error)
566 break;
567 error = put_user(0, min_buf_size_ptr);
568 break;
569 case PL_DEL:
570 case PL_FDEL:
571 error = 0;
572 break;
573 default:
574 error = -EOPNOTSUPP;
575 break;
576 };
577 unlock_kernel();
578 return error;
579}
580
581asmlinkage int
582osf_sigstack(struct sigstack __user *uss, struct sigstack __user *uoss)
583{
584 unsigned long usp = rdusp();
585 unsigned long oss_sp = current->sas_ss_sp + current->sas_ss_size;
586 unsigned long oss_os = on_sig_stack(usp);
587 int error;
588
589 if (uss) {
590 void __user *ss_sp;
591
592 error = -EFAULT;
593 if (get_user(ss_sp, &uss->ss_sp))
594 goto out;
595
596 /* If the current stack was set with sigaltstack, don't
597 swap stacks while we are on it. */
598 error = -EPERM;
599 if (current->sas_ss_sp && on_sig_stack(usp))
600 goto out;
601
602 /* Since we don't know the extent of the stack, and we don't
603 track onstack-ness, but rather calculate it, we must
604 presume a size. Ho hum this interface is lossy. */
605 current->sas_ss_sp = (unsigned long)ss_sp - SIGSTKSZ;
606 current->sas_ss_size = SIGSTKSZ;
607 }
608
609 if (uoss) {
610 error = -EFAULT;
611 if (! access_ok(VERIFY_WRITE, uoss, sizeof(*uoss))
612 || __put_user(oss_sp, &uoss->ss_sp)
613 || __put_user(oss_os, &uoss->ss_onstack))
614 goto out;
615 }
616
617 error = 0;
618 out:
619 return error;
620}
621
622asmlinkage long
623osf_sysinfo(int command, char __user *buf, long count)
624{
625 static char * sysinfo_table[] = {
626 system_utsname.sysname,
627 system_utsname.nodename,
628 system_utsname.release,
629 system_utsname.version,
630 system_utsname.machine,
631 "alpha", /* instruction set architecture */
632 "dummy", /* hardware serial number */
633 "dummy", /* hardware manufacturer */
634 "dummy", /* secure RPC domain */
635 };
636 unsigned long offset;
637 char *res;
638 long len, err = -EINVAL;
639
640 offset = command-1;
641 if (offset >= sizeof(sysinfo_table)/sizeof(char *)) {
642 /* Digital UNIX has a few unpublished interfaces here */
643 printk("sysinfo(%d)", command);
644 goto out;
645 }
646
647 down_read(&uts_sem);
648 res = sysinfo_table[offset];
649 len = strlen(res)+1;
650 if (len > count)
651 len = count;
652 if (copy_to_user(buf, res, len))
653 err = -EFAULT;
654 else
655 err = 0;
656 up_read(&uts_sem);
657 out:
658 return err;
659}
660
661asmlinkage unsigned long
662osf_getsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes,
663 int __user *start, void __user *arg)
664{
665 unsigned long w;
666 struct percpu_struct *cpu;
667
668 switch (op) {
669 case GSI_IEEE_FP_CONTROL:
670 /* Return current software fp control & status bits. */
671 /* Note that DU doesn't verify available space here. */
672
673 w = current_thread_info()->ieee_state & IEEE_SW_MASK;
674 w = swcr_update_status(w, rdfpcr());
675 if (put_user(w, (unsigned long __user *) buffer))
676 return -EFAULT;
677 return 0;
678
679 case GSI_IEEE_STATE_AT_SIGNAL:
680 /*
681 * Not sure anybody will ever use this weird stuff. These
682 * ops can be used (under OSF/1) to set the fpcr that should
683 * be used when a signal handler starts executing.
684 */
685 break;
686
687 case GSI_UACPROC:
688 if (nbytes < sizeof(unsigned int))
689 return -EINVAL;
690 w = (current_thread_info()->flags >> UAC_SHIFT) & UAC_BITMASK;
691 if (put_user(w, (unsigned int __user *)buffer))
692 return -EFAULT;
693 return 1;
694
695 case GSI_PROC_TYPE:
696 if (nbytes < sizeof(unsigned long))
697 return -EINVAL;
698 cpu = (struct percpu_struct*)
699 ((char*)hwrpb + hwrpb->processor_offset);
700 w = cpu->type;
701 if (put_user(w, (unsigned long __user*)buffer))
702 return -EFAULT;
703 return 1;
704
705 case GSI_GET_HWRPB:
706 if (nbytes < sizeof(*hwrpb))
707 return -EINVAL;
708 if (copy_to_user(buffer, hwrpb, nbytes) != 0)
709 return -EFAULT;
710 return 1;
711
712 default:
713 break;
714 }
715
716 return -EOPNOTSUPP;
717}
718
719asmlinkage unsigned long
720osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes,
721 int __user *start, void __user *arg)
722{
723 switch (op) {
724 case SSI_IEEE_FP_CONTROL: {
725 unsigned long swcr, fpcr;
726 unsigned int *state;
727
728 /*
729 * Alpha Architecture Handbook 4.7.7.3:
730 * To be fully IEEE compiant, we must track the current IEEE
731 * exception state in software, because spurrious bits can be
732 * set in the trap shadow of a software-complete insn.
733 */
734
735 if (get_user(swcr, (unsigned long __user *)buffer))
736 return -EFAULT;
737 state = &current_thread_info()->ieee_state;
738
739 /* Update softare trap enable bits. */
740 *state = (*state & ~IEEE_SW_MASK) | (swcr & IEEE_SW_MASK);
741
742 /* Update the real fpcr. */
743 fpcr = rdfpcr() & FPCR_DYN_MASK;
744 fpcr |= ieee_swcr_to_fpcr(swcr);
745 wrfpcr(fpcr);
746
747 return 0;
748 }
749
750 case SSI_IEEE_RAISE_EXCEPTION: {
751 unsigned long exc, swcr, fpcr, fex;
752 unsigned int *state;
753
754 if (get_user(exc, (unsigned long __user *)buffer))
755 return -EFAULT;
756 state = &current_thread_info()->ieee_state;
757 exc &= IEEE_STATUS_MASK;
758
759 /* Update softare trap enable bits. */
760 swcr = (*state & IEEE_SW_MASK) | exc;
761 *state |= exc;
762
763 /* Update the real fpcr. */
764 fpcr = rdfpcr();
765 fpcr |= ieee_swcr_to_fpcr(swcr);
766 wrfpcr(fpcr);
767
768 /* If any exceptions set by this call, and are unmasked,
769 send a signal. Old exceptions are not signaled. */
770 fex = (exc >> IEEE_STATUS_TO_EXCSUM_SHIFT) & swcr;
771 if (fex) {
772 siginfo_t info;
773 int si_code = 0;
774
775 if (fex & IEEE_TRAP_ENABLE_DNO) si_code = FPE_FLTUND;
776 if (fex & IEEE_TRAP_ENABLE_INE) si_code = FPE_FLTRES;
777 if (fex & IEEE_TRAP_ENABLE_UNF) si_code = FPE_FLTUND;
778 if (fex & IEEE_TRAP_ENABLE_OVF) si_code = FPE_FLTOVF;
779 if (fex & IEEE_TRAP_ENABLE_DZE) si_code = FPE_FLTDIV;
780 if (fex & IEEE_TRAP_ENABLE_INV) si_code = FPE_FLTINV;
781
782 info.si_signo = SIGFPE;
783 info.si_errno = 0;
784 info.si_code = si_code;
785 info.si_addr = NULL; /* FIXME */
786 send_sig_info(SIGFPE, &info, current);
787 }
788 return 0;
789 }
790
791 case SSI_IEEE_STATE_AT_SIGNAL:
792 case SSI_IEEE_IGNORE_STATE_AT_SIGNAL:
793 /*
794 * Not sure anybody will ever use this weird stuff. These
795 * ops can be used (under OSF/1) to set the fpcr that should
796 * be used when a signal handler starts executing.
797 */
798 break;
799
800 case SSI_NVPAIRS: {
801 unsigned long v, w, i;
802 unsigned int old, new;
803
804 for (i = 0; i < nbytes; ++i) {
805
806 if (get_user(v, 2*i + (unsigned int __user *)buffer))
807 return -EFAULT;
808 if (get_user(w, 2*i + 1 + (unsigned int __user *)buffer))
809 return -EFAULT;
810 switch (v) {
811 case SSIN_UACPROC:
812 again:
813 old = current_thread_info()->flags;
814 new = old & ~(UAC_BITMASK << UAC_SHIFT);
815 new = new | (w & UAC_BITMASK) << UAC_SHIFT;
816 if (cmpxchg(&current_thread_info()->flags,
817 old, new) != old)
818 goto again;
819 break;
820
821 default:
822 return -EOPNOTSUPP;
823 }
824 }
825 return 0;
826 }
827
828 default:
829 break;
830 }
831
832 return -EOPNOTSUPP;
833}
834
835/* Translations due to the fact that OSF's time_t is an int. Which
836 affects all sorts of things, like timeval and itimerval. */
837
838extern struct timezone sys_tz;
839extern int do_adjtimex(struct timex *);
840
841struct timeval32
842{
843 int tv_sec, tv_usec;
844};
845
846struct itimerval32
847{
848 struct timeval32 it_interval;
849 struct timeval32 it_value;
850};
851
852static inline long
853get_tv32(struct timeval *o, struct timeval32 __user *i)
854{
855 return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
856 (__get_user(o->tv_sec, &i->tv_sec) |
857 __get_user(o->tv_usec, &i->tv_usec)));
858}
859
860static inline long
861put_tv32(struct timeval32 __user *o, struct timeval *i)
862{
863 return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
864 (__put_user(i->tv_sec, &o->tv_sec) |
865 __put_user(i->tv_usec, &o->tv_usec)));
866}
867
868static inline long
869get_it32(struct itimerval *o, struct itimerval32 __user *i)
870{
871 return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
872 (__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |
873 __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) |
874 __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) |
875 __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));
876}
877
878static inline long
879put_it32(struct itimerval32 __user *o, struct itimerval *i)
880{
881 return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
882 (__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
883 __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) |
884 __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) |
885 __put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
886}
887
888static inline void
889jiffies_to_timeval32(unsigned long jiffies, struct timeval32 *value)
890{
891 value->tv_usec = (jiffies % HZ) * (1000000L / HZ);
892 value->tv_sec = jiffies / HZ;
893}
894
895asmlinkage int
896osf_gettimeofday(struct timeval32 __user *tv, struct timezone __user *tz)
897{
898 if (tv) {
899 struct timeval ktv;
900 do_gettimeofday(&ktv);
901 if (put_tv32(tv, &ktv))
902 return -EFAULT;
903 }
904 if (tz) {
905 if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
906 return -EFAULT;
907 }
908 return 0;
909}
910
911asmlinkage int
912osf_settimeofday(struct timeval32 __user *tv, struct timezone __user *tz)
913{
914 struct timespec kts;
915 struct timezone ktz;
916
917 if (tv) {
918 if (get_tv32((struct timeval *)&kts, tv))
919 return -EFAULT;
920 }
921 if (tz) {
922 if (copy_from_user(&ktz, tz, sizeof(*tz)))
923 return -EFAULT;
924 }
925
926 kts.tv_nsec *= 1000;
927
928 return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
929}
930
931asmlinkage int
932osf_getitimer(int which, struct itimerval32 __user *it)
933{
934 struct itimerval kit;
935 int error;
936
937 error = do_getitimer(which, &kit);
938 if (!error && put_it32(it, &kit))
939 error = -EFAULT;
940
941 return error;
942}
943
944asmlinkage int
945osf_setitimer(int which, struct itimerval32 __user *in, struct itimerval32 __user *out)
946{
947 struct itimerval kin, kout;
948 int error;
949
950 if (in) {
951 if (get_it32(&kin, in))
952 return -EFAULT;
953 } else
954 memset(&kin, 0, sizeof(kin));
955
956 error = do_setitimer(which, &kin, out ? &kout : NULL);
957 if (error || !out)
958 return error;
959
960 if (put_it32(out, &kout))
961 return -EFAULT;
962
963 return 0;
964
965}
966
967asmlinkage int
968osf_utimes(char __user *filename, struct timeval32 __user *tvs)
969{
970 struct timeval ktvs[2];
971
972 if (tvs) {
973 if (get_tv32(&ktvs[0], &tvs[0]) ||
974 get_tv32(&ktvs[1], &tvs[1]))
975 return -EFAULT;
976 }
977
978 return do_utimes(filename, tvs ? ktvs : NULL);
979}
980
981#define MAX_SELECT_SECONDS \
982 ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
983
984asmlinkage int
985osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp,
986 struct timeval32 __user *tvp)
987{
988 fd_set_bits fds;
989 char *bits;
990 size_t size;
991 long timeout;
992 int ret = -EINVAL;
993
994 timeout = MAX_SCHEDULE_TIMEOUT;
995 if (tvp) {
996 time_t sec, usec;
997
998 if (!access_ok(VERIFY_READ, tvp, sizeof(*tvp))
999 || __get_user(sec, &tvp->tv_sec)
1000 || __get_user(usec, &tvp->tv_usec)) {
1001 ret = -EFAULT;
1002 goto out_nofds;
1003 }
1004
1005 if (sec < 0 || usec < 0)
1006 goto out_nofds;
1007
1008 if ((unsigned long) sec < MAX_SELECT_SECONDS) {
1009 timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
1010 timeout += sec * (unsigned long) HZ;
1011 }
1012 }
1013
1014 if (n < 0 || n > current->files->max_fdset)
1015 goto out_nofds;
1016
1017 /*
1018 * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
1019 * since we used fdset we need to allocate memory in units of
1020 * long-words.
1021 */
1022 ret = -ENOMEM;
1023 size = FDS_BYTES(n);
1024 bits = kmalloc(6 * size, GFP_KERNEL);
1025 if (!bits)
1026 goto out_nofds;
1027 fds.in = (unsigned long *) bits;
1028 fds.out = (unsigned long *) (bits + size);
1029 fds.ex = (unsigned long *) (bits + 2*size);
1030 fds.res_in = (unsigned long *) (bits + 3*size);
1031 fds.res_out = (unsigned long *) (bits + 4*size);
1032 fds.res_ex = (unsigned long *) (bits + 5*size);
1033
1034 if ((ret = get_fd_set(n, inp->fds_bits, fds.in)) ||
1035 (ret = get_fd_set(n, outp->fds_bits, fds.out)) ||
1036 (ret = get_fd_set(n, exp->fds_bits, fds.ex)))
1037 goto out;
1038 zero_fd_set(n, fds.res_in);
1039 zero_fd_set(n, fds.res_out);
1040 zero_fd_set(n, fds.res_ex);
1041
1042 ret = do_select(n, &fds, &timeout);
1043
1044 /* OSF does not copy back the remaining time. */
1045
1046 if (ret < 0)
1047 goto out;
1048 if (!ret) {
1049 ret = -ERESTARTNOHAND;
1050 if (signal_pending(current))
1051 goto out;
1052 ret = 0;
1053 }
1054
1055 if (set_fd_set(n, inp->fds_bits, fds.res_in) ||
1056 set_fd_set(n, outp->fds_bits, fds.res_out) ||
1057 set_fd_set(n, exp->fds_bits, fds.res_ex))
1058 ret = -EFAULT;
1059
1060 out:
1061 kfree(bits);
1062 out_nofds:
1063 return ret;
1064}
1065
1066struct rusage32 {
1067 struct timeval32 ru_utime; /* user time used */
1068 struct timeval32 ru_stime; /* system time used */
1069 long ru_maxrss; /* maximum resident set size */
1070 long ru_ixrss; /* integral shared memory size */
1071 long ru_idrss; /* integral unshared data size */
1072 long ru_isrss; /* integral unshared stack size */
1073 long ru_minflt; /* page reclaims */
1074 long ru_majflt; /* page faults */
1075 long ru_nswap; /* swaps */
1076 long ru_inblock; /* block input operations */
1077 long ru_oublock; /* block output operations */
1078 long ru_msgsnd; /* messages sent */
1079 long ru_msgrcv; /* messages received */
1080 long ru_nsignals; /* signals received */
1081 long ru_nvcsw; /* voluntary context switches */
1082 long ru_nivcsw; /* involuntary " */
1083};
1084
1085asmlinkage int
1086osf_getrusage(int who, struct rusage32 __user *ru)
1087{
1088 struct rusage32 r;
1089
1090 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
1091 return -EINVAL;
1092
1093 memset(&r, 0, sizeof(r));
1094 switch (who) {
1095 case RUSAGE_SELF:
1096 jiffies_to_timeval32(current->utime, &r.ru_utime);
1097 jiffies_to_timeval32(current->stime, &r.ru_stime);
1098 r.ru_minflt = current->min_flt;
1099 r.ru_majflt = current->maj_flt;
1100 break;
1101 case RUSAGE_CHILDREN:
1102 jiffies_to_timeval32(current->signal->cutime, &r.ru_utime);
1103 jiffies_to_timeval32(current->signal->cstime, &r.ru_stime);
1104 r.ru_minflt = current->signal->cmin_flt;
1105 r.ru_majflt = current->signal->cmaj_flt;
1106 break;
1107 }
1108
1109 return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
1110}
1111
1112asmlinkage long
1113osf_wait4(pid_t pid, int __user *ustatus, int options,
1114 struct rusage32 __user *ur)
1115{
1116 struct rusage r;
1117 long ret, err;
1118 mm_segment_t old_fs;
1119
1120 if (!ur)
1121 return sys_wait4(pid, ustatus, options, NULL);
1122
1123 old_fs = get_fs();
1124
1125 set_fs (KERNEL_DS);
1126 ret = sys_wait4(pid, ustatus, options, (struct rusage __user *) &r);
1127 set_fs (old_fs);
1128
1129 if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur)))
1130 return -EFAULT;
1131
1132 err = 0;
1133 err |= __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec);
1134 err |= __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec);
1135 err |= __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec);
1136 err |= __put_user(r.ru_stime.tv_usec, &ur->ru_stime.tv_usec);
1137 err |= __put_user(r.ru_maxrss, &ur->ru_maxrss);
1138 err |= __put_user(r.ru_ixrss, &ur->ru_ixrss);
1139 err |= __put_user(r.ru_idrss, &ur->ru_idrss);
1140 err |= __put_user(r.ru_isrss, &ur->ru_isrss);
1141 err |= __put_user(r.ru_minflt, &ur->ru_minflt);
1142 err |= __put_user(r.ru_majflt, &ur->ru_majflt);
1143 err |= __put_user(r.ru_nswap, &ur->ru_nswap);
1144 err |= __put_user(r.ru_inblock, &ur->ru_inblock);
1145 err |= __put_user(r.ru_oublock, &ur->ru_oublock);
1146 err |= __put_user(r.ru_msgsnd, &ur->ru_msgsnd);
1147 err |= __put_user(r.ru_msgrcv, &ur->ru_msgrcv);
1148 err |= __put_user(r.ru_nsignals, &ur->ru_nsignals);
1149 err |= __put_user(r.ru_nvcsw, &ur->ru_nvcsw);
1150 err |= __put_user(r.ru_nivcsw, &ur->ru_nivcsw);
1151
1152 return err ? err : ret;
1153}
1154
1155/*
1156 * I don't know what the parameters are: the first one
1157 * seems to be a timeval pointer, and I suspect the second
1158 * one is the time remaining.. Ho humm.. No documentation.
1159 */
1160asmlinkage int
1161osf_usleep_thread(struct timeval32 __user *sleep, struct timeval32 __user *remain)
1162{
1163 struct timeval tmp;
1164 unsigned long ticks;
1165
1166 if (get_tv32(&tmp, sleep))
1167 goto fault;
1168
1169 ticks = tmp.tv_usec;
1170 ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ);
1171 ticks += tmp.tv_sec * HZ;
1172
1173 current->state = TASK_INTERRUPTIBLE;
1174 ticks = schedule_timeout(ticks);
1175
1176 if (remain) {
1177 tmp.tv_sec = ticks / HZ;
1178 tmp.tv_usec = ticks % HZ;
1179 if (put_tv32(remain, &tmp))
1180 goto fault;
1181 }
1182
1183 return 0;
1184 fault:
1185 return -EFAULT;
1186}
1187
1188
1189struct timex32 {
1190 unsigned int modes; /* mode selector */
1191 long offset; /* time offset (usec) */
1192 long freq; /* frequency offset (scaled ppm) */
1193 long maxerror; /* maximum error (usec) */
1194 long esterror; /* estimated error (usec) */
1195 int status; /* clock command/status */
1196 long constant; /* pll time constant */
1197 long precision; /* clock precision (usec) (read only) */
1198 long tolerance; /* clock frequency tolerance (ppm)
1199 * (read only)
1200 */
1201 struct timeval32 time; /* (read only) */
1202 long tick; /* (modified) usecs between clock ticks */
1203
1204 long ppsfreq; /* pps frequency (scaled ppm) (ro) */
1205 long jitter; /* pps jitter (us) (ro) */
1206 int shift; /* interval duration (s) (shift) (ro) */
1207 long stabil; /* pps stability (scaled ppm) (ro) */
1208 long jitcnt; /* jitter limit exceeded (ro) */
1209 long calcnt; /* calibration intervals (ro) */
1210 long errcnt; /* calibration errors (ro) */
1211 long stbcnt; /* stability limit exceeded (ro) */
1212
1213 int :32; int :32; int :32; int :32;
1214 int :32; int :32; int :32; int :32;
1215 int :32; int :32; int :32; int :32;
1216};
1217
1218asmlinkage int
1219sys_old_adjtimex(struct timex32 __user *txc_p)
1220{
1221 struct timex txc;
1222 int ret;
1223
1224 /* copy relevant bits of struct timex. */
1225 if (copy_from_user(&txc, txc_p, offsetof(struct timex32, time)) ||
1226 copy_from_user(&txc.tick, &txc_p->tick, sizeof(struct timex32) -
1227 offsetof(struct timex32, time)))
1228 return -EFAULT;
1229
1230 ret = do_adjtimex(&txc);
1231 if (ret < 0)
1232 return ret;
1233
1234 /* copy back to timex32 */
1235 if (copy_to_user(txc_p, &txc, offsetof(struct timex32, time)) ||
1236 (copy_to_user(&txc_p->tick, &txc.tick, sizeof(struct timex32) -
1237 offsetof(struct timex32, tick))) ||
1238 (put_tv32(&txc_p->time, &txc.time)))
1239 return -EFAULT;
1240
1241 return ret;
1242}
1243
1244/* Get an address range which is currently unmapped. Similar to the
1245 generic version except that we know how to honor ADDR_LIMIT_32BIT. */
1246
1247static unsigned long
1248arch_get_unmapped_area_1(unsigned long addr, unsigned long len,
1249 unsigned long limit)
1250{
1251 struct vm_area_struct *vma = find_vma(current->mm, addr);
1252
1253 while (1) {
1254 /* At this point: (!vma || addr < vma->vm_end). */
1255 if (limit - len < addr)
1256 return -ENOMEM;
1257 if (!vma || addr + len <= vma->vm_start)
1258 return addr;
1259 addr = vma->vm_end;
1260 vma = vma->vm_next;
1261 }
1262}
1263
1264unsigned long
1265arch_get_unmapped_area(struct file *filp, unsigned long addr,
1266 unsigned long len, unsigned long pgoff,
1267 unsigned long flags)
1268{
1269 unsigned long limit;
1270
1271 /* "32 bit" actually means 31 bit, since pointers sign extend. */
1272 if (current->personality & ADDR_LIMIT_32BIT)
1273 limit = 0x80000000;
1274 else
1275 limit = TASK_SIZE;
1276
1277 if (len > limit)
1278 return -ENOMEM;
1279
1280 /* First, see if the given suggestion fits.
1281
1282 The OSF/1 loader (/sbin/loader) relies on us returning an
1283 address larger than the requested if one exists, which is
1284 a terribly broken way to program.
1285
1286 That said, I can see the use in being able to suggest not
1287 merely specific addresses, but regions of memory -- perhaps
1288 this feature should be incorporated into all ports? */
1289
1290 if (addr) {
1291 addr = arch_get_unmapped_area_1 (PAGE_ALIGN(addr), len, limit);
1292 if (addr != (unsigned long) -ENOMEM)
1293 return addr;
1294 }
1295
1296 /* Next, try allocating at TASK_UNMAPPED_BASE. */
1297 addr = arch_get_unmapped_area_1 (PAGE_ALIGN(TASK_UNMAPPED_BASE),
1298 len, limit);
1299 if (addr != (unsigned long) -ENOMEM)
1300 return addr;
1301
1302 /* Finally, try allocating in low memory. */
1303 addr = arch_get_unmapped_area_1 (PAGE_SIZE, len, limit);
1304
1305 return addr;
1306}
1307
1308#ifdef CONFIG_OSF4_COMPAT
1309
1310/* Clear top 32 bits of iov_len in the user's buffer for
1311 compatibility with old versions of OSF/1 where iov_len
1312 was defined as int. */
1313static int
1314osf_fix_iov_len(const struct iovec __user *iov, unsigned long count)
1315{
1316 unsigned long i;
1317
1318 for (i = 0 ; i < count ; i++) {
1319 int __user *iov_len_high = (int __user *)&iov[i].iov_len + 1;
1320
1321 if (put_user(0, iov_len_high))
1322 return -EFAULT;
1323 }
1324 return 0;
1325}
1326
1327asmlinkage ssize_t
1328osf_readv(unsigned long fd, const struct iovec __user * vector, unsigned long count)
1329{
1330 if (unlikely(personality(current->personality) == PER_OSF4))
1331 if (osf_fix_iov_len(vector, count))
1332 return -EFAULT;
1333 return sys_readv(fd, vector, count);
1334}
1335
1336asmlinkage ssize_t
1337osf_writev(unsigned long fd, const struct iovec __user * vector, unsigned long count)
1338{
1339 if (unlikely(personality(current->personality) == PER_OSF4))
1340 if (osf_fix_iov_len(vector, count))
1341 return -EFAULT;
1342 return sys_writev(fd, vector, count);
1343}
1344
1345#endif
diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c
new file mode 100644
index 000000000000..582a3519fb28
--- /dev/null
+++ b/arch/alpha/kernel/pci-noop.c
@@ -0,0 +1,214 @@
1/*
2 * linux/arch/alpha/kernel/pci-noop.c
3 *
4 * Stub PCI interfaces for Jensen-specific kernels.
5 */
6
7#include <linux/pci.h>
8#include <linux/init.h>
9#include <linux/bootmem.h>
10#include <linux/mm.h>
11#include <linux/errno.h>
12#include <linux/sched.h>
13#include <linux/dma-mapping.h>
14
15#include "proto.h"
16
17
18/*
19 * The PCI controller list.
20 */
21
22struct pci_controller *hose_head, **hose_tail = &hose_head;
23struct pci_controller *pci_isa_hose;
24
25
26struct pci_controller * __init
27alloc_pci_controller(void)
28{
29 struct pci_controller *hose;
30
31 hose = alloc_bootmem(sizeof(*hose));
32
33 *hose_tail = hose;
34 hose_tail = &hose->next;
35
36 return hose;
37}
38
39struct resource * __init
40alloc_resource(void)
41{
42 struct resource *res;
43
44 res = alloc_bootmem(sizeof(*res));
45
46 return res;
47}
48
49asmlinkage long
50sys_pciconfig_iobase(long which, unsigned long bus, unsigned long dfn)
51{
52 struct pci_controller *hose;
53
54 /* from hose or from bus.devfn */
55 if (which & IOBASE_FROM_HOSE) {
56 for (hose = hose_head; hose; hose = hose->next)
57 if (hose->index == bus)
58 break;
59 if (!hose)
60 return -ENODEV;
61 } else {
62 /* Special hook for ISA access. */
63 if (bus == 0 && dfn == 0)
64 hose = pci_isa_hose;
65 else
66 return -ENODEV;
67 }
68
69 switch (which & ~IOBASE_FROM_HOSE) {
70 case IOBASE_HOSE:
71 return hose->index;
72 case IOBASE_SPARSE_MEM:
73 return hose->sparse_mem_base;
74 case IOBASE_DENSE_MEM:
75 return hose->dense_mem_base;
76 case IOBASE_SPARSE_IO:
77 return hose->sparse_io_base;
78 case IOBASE_DENSE_IO:
79 return hose->dense_io_base;
80 case IOBASE_ROOT_BUS:
81 return hose->bus->number;
82 }
83
84 return -EOPNOTSUPP;
85}
86
87asmlinkage long
88sys_pciconfig_read(unsigned long bus, unsigned long dfn,
89 unsigned long off, unsigned long len, void *buf)
90{
91 if (!capable(CAP_SYS_ADMIN))
92 return -EPERM;
93 else
94 return -ENODEV;
95}
96
97asmlinkage long
98sys_pciconfig_write(unsigned long bus, unsigned long dfn,
99 unsigned long off, unsigned long len, void *buf)
100{
101 if (!capable(CAP_SYS_ADMIN))
102 return -EPERM;
103 else
104 return -ENODEV;
105}
106
107/* Stubs for the routines in pci_iommu.c: */
108
109void *
110pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp)
111{
112 return NULL;
113}
114
115void
116pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu_addr,
117 dma_addr_t dma_addr)
118{
119}
120
121dma_addr_t
122pci_map_single(struct pci_dev *pdev, void *cpu_addr, size_t size,
123 int direction)
124{
125 return (dma_addr_t) 0;
126}
127
128void
129pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
130 int direction)
131{
132}
133
134int
135pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
136 int direction)
137{
138 return 0;
139}
140
141void
142pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
143 int direction)
144{
145}
146
147int
148pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask)
149{
150 return 0;
151}
152
153/* Generic DMA mapping functions: */
154
155void *
156dma_alloc_coherent(struct device *dev, size_t size,
157 dma_addr_t *dma_handle, int gfp)
158{
159 void *ret;
160
161 if (!dev || *dev->dma_mask >= 0xffffffffUL)
162 gfp &= ~GFP_DMA;
163 ret = (void *)__get_free_pages(gfp, get_order(size));
164 if (ret) {
165 memset(ret, 0, size);
166 *dma_handle = virt_to_bus(ret);
167 }
168 return ret;
169}
170
171EXPORT_SYMBOL(dma_alloc_coherent);
172
173int
174dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
175 enum dma_data_direction direction)
176{
177 int i;
178
179 for (i = 0; i < nents; i++ ) {
180 void *va;
181
182 BUG_ON(!sg[i].page);
183 va = page_address(sg[i].page) + sg[i].offset;
184 sg_dma_address(sg + i) = (dma_addr_t)virt_to_bus(va);
185 sg_dma_len(sg + i) = sg[i].length;
186 }
187
188 return nents;
189}
190
191EXPORT_SYMBOL(dma_map_sg);
192
193int
194dma_set_mask(struct device *dev, u64 mask)
195{
196 if (!dev->dma_mask || !dma_supported(dev, mask))
197 return -EIO;
198
199 *dev->dma_mask = mask;
200
201 return 0;
202}
203
204void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
205{
206 return NULL;
207}
208
209void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
210{
211}
212
213EXPORT_SYMBOL(pci_iomap);
214EXPORT_SYMBOL(pci_iounmap);
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
new file mode 100644
index 000000000000..1f36bbd0ed5d
--- /dev/null
+++ b/arch/alpha/kernel/pci.c
@@ -0,0 +1,561 @@
1/*
2 * linux/arch/alpha/kernel/pci.c
3 *
4 * Extruded from code written by
5 * Dave Rusling (david.rusling@reo.mts.dec.com)
6 * David Mosberger (davidm@cs.arizona.edu)
7 */
8
9/* 2.3.x PCI/resources, 1999 Andrea Arcangeli <andrea@suse.de> */
10
11/*
12 * Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
13 * PCI-PCI bridges cleanup
14 */
15#include <linux/config.h>
16#include <linux/string.h>
17#include <linux/pci.h>
18#include <linux/init.h>
19#include <linux/ioport.h>
20#include <linux/kernel.h>
21#include <linux/bootmem.h>
22#include <linux/module.h>
23#include <linux/cache.h>
24#include <linux/slab.h>
25#include <asm/machvec.h>
26
27#include "proto.h"
28#include "pci_impl.h"
29
30
31/*
32 * Some string constants used by the various core logics.
33 */
34
35const char *const pci_io_names[] = {
36 "PCI IO bus 0", "PCI IO bus 1", "PCI IO bus 2", "PCI IO bus 3",
37 "PCI IO bus 4", "PCI IO bus 5", "PCI IO bus 6", "PCI IO bus 7"
38};
39
40const char *const pci_mem_names[] = {
41 "PCI mem bus 0", "PCI mem bus 1", "PCI mem bus 2", "PCI mem bus 3",
42 "PCI mem bus 4", "PCI mem bus 5", "PCI mem bus 6", "PCI mem bus 7"
43};
44
45const char pci_hae0_name[] = "HAE0";
46
47/* Indicate whether we respect the PCI setup left by console. */
48/*
49 * Make this long-lived so that we know when shutting down
50 * whether we probed only or not.
51 */
52int pci_probe_only;
53
54/*
55 * The PCI controller list.
56 */
57
58struct pci_controller *hose_head, **hose_tail = &hose_head;
59struct pci_controller *pci_isa_hose;
60
61/*
62 * Quirks.
63 */
64
65static void __init
66quirk_isa_bridge(struct pci_dev *dev)
67{
68 dev->class = PCI_CLASS_BRIDGE_ISA << 8;
69}
70DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, quirk_isa_bridge);
71
72static void __init
73quirk_cypress(struct pci_dev *dev)
74{
75 /* The Notorious Cy82C693 chip. */
76
77 /* The Cypress IDE controller doesn't support native mode, but it
78 has programmable addresses of IDE command/control registers.
79 This violates PCI specifications, confuses the IDE subsystem and
80 causes resource conflicts between the primary HD_CMD register and
81 the floppy controller. Ugh. Fix that. */
82 if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE) {
83 dev->resource[0].flags = 0;
84 dev->resource[1].flags = 0;
85 }
86
87 /* The Cypress bridge responds on the PCI bus in the address range
88 0xffff0000-0xffffffff (conventional x86 BIOS ROM). There is no
89 way to turn this off. The bridge also supports several extended
90 BIOS ranges (disabled after power-up), and some consoles do turn
91 them on. So if we use a large direct-map window, or a large SG
92 window, we must avoid the entire 0xfff00000-0xffffffff region. */
93 else if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA) {
94 if (__direct_map_base + __direct_map_size >= 0xfff00000UL)
95 __direct_map_size = 0xfff00000UL - __direct_map_base;
96 else {
97 struct pci_controller *hose = dev->sysdata;
98 struct pci_iommu_arena *pci = hose->sg_pci;
99 if (pci && pci->dma_base + pci->size >= 0xfff00000UL)
100 pci->size = 0xfff00000UL - pci->dma_base;
101 }
102 }
103}
104DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, quirk_cypress);
105
106/* Called for each device after PCI setup is done. */
107static void __init
108pcibios_fixup_final(struct pci_dev *dev)
109{
110 unsigned int class = dev->class >> 8;
111
112 if (class == PCI_CLASS_BRIDGE_ISA || class == PCI_CLASS_BRIDGE_EISA) {
113 dev->dma_mask = MAX_ISA_DMA_ADDRESS - 1;
114 isa_bridge = dev;
115 }
116}
117DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_final);
118
119/* Just declaring that the power-of-ten prefixes are actually the
120 power-of-two ones doesn't make it true :) */
121#define KB 1024
122#define MB (1024*KB)
123#define GB (1024*MB)
124
125void
126pcibios_align_resource(void *data, struct resource *res,
127 unsigned long size, unsigned long align)
128{
129 struct pci_dev *dev = data;
130 struct pci_controller *hose = dev->sysdata;
131 unsigned long alignto;
132 unsigned long start = res->start;
133
134 if (res->flags & IORESOURCE_IO) {
135 /* Make sure we start at our min on all hoses */
136 if (start - hose->io_space->start < PCIBIOS_MIN_IO)
137 start = PCIBIOS_MIN_IO + hose->io_space->start;
138
139 /*
140 * Put everything into 0x00-0xff region modulo 0x400
141 */
142 if (start & 0x300)
143 start = (start + 0x3ff) & ~0x3ff;
144 }
145 else if (res->flags & IORESOURCE_MEM) {
146 /* Make sure we start at our min on all hoses */
147 if (start - hose->mem_space->start < PCIBIOS_MIN_MEM)
148 start = PCIBIOS_MIN_MEM + hose->mem_space->start;
149
150 /*
151 * The following holds at least for the Low Cost
152 * Alpha implementation of the PCI interface:
153 *
154 * In sparse memory address space, the first
155 * octant (16MB) of every 128MB segment is
156 * aliased to the very first 16 MB of the
157 * address space (i.e., it aliases the ISA
158 * memory address space). Thus, we try to
159 * avoid allocating PCI devices in that range.
160 * Can be allocated in 2nd-7th octant only.
161 * Devices that need more than 112MB of
162 * address space must be accessed through
163 * dense memory space only!
164 */
165
166 /* Align to multiple of size of minimum base. */
167 alignto = max(0x1000UL, align);
168 start = ALIGN(start, alignto);
169 if (hose->sparse_mem_base && size <= 7 * 16*MB) {
170 if (((start / (16*MB)) & 0x7) == 0) {
171 start &= ~(128*MB - 1);
172 start += 16*MB;
173 start = ALIGN(start, alignto);
174 }
175 if (start/(128*MB) != (start + size - 1)/(128*MB)) {
176 start &= ~(128*MB - 1);
177 start += (128 + 16)*MB;
178 start = ALIGN(start, alignto);
179 }
180 }
181 }
182
183 res->start = start;
184}
185#undef KB
186#undef MB
187#undef GB
188
189static int __init
190pcibios_init(void)
191{
192 if (alpha_mv.init_pci)
193 alpha_mv.init_pci();
194 return 0;
195}
196
197subsys_initcall(pcibios_init);
198
199char * __init
200pcibios_setup(char *str)
201{
202 return str;
203}
204
205#ifdef ALPHA_RESTORE_SRM_SETUP
206static struct pdev_srm_saved_conf *srm_saved_configs;
207
208void __init
209pdev_save_srm_config(struct pci_dev *dev)
210{
211 struct pdev_srm_saved_conf *tmp;
212 static int printed = 0;
213
214 if (!alpha_using_srm || pci_probe_only)
215 return;
216
217 if (!printed) {
218 printk(KERN_INFO "pci: enabling save/restore of SRM state\n");
219 printed = 1;
220 }
221
222 tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
223 if (!tmp) {
224 printk(KERN_ERR "%s: kmalloc() failed!\n", __FUNCTION__);
225 return;
226 }
227 tmp->next = srm_saved_configs;
228 tmp->dev = dev;
229
230 pci_save_state(dev);
231
232 srm_saved_configs = tmp;
233}
234
235void
236pci_restore_srm_config(void)
237{
238 struct pdev_srm_saved_conf *tmp;
239
240 /* No need to restore if probed only. */
241 if (pci_probe_only)
242 return;
243
244 /* Restore SRM config. */
245 for (tmp = srm_saved_configs; tmp; tmp = tmp->next) {
246 pci_restore_state(tmp->dev);
247 }
248}
249#endif
250
251void __init
252pcibios_fixup_resource(struct resource *res, struct resource *root)
253{
254 res->start += root->start;
255 res->end += root->start;
256}
257
258void __init
259pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus)
260{
261 /* Update device resources. */
262 struct pci_controller *hose = (struct pci_controller *)bus->sysdata;
263 int i;
264
265 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
266 if (!dev->resource[i].start)
267 continue;
268 if (dev->resource[i].flags & IORESOURCE_IO)
269 pcibios_fixup_resource(&dev->resource[i],
270 hose->io_space);
271 else if (dev->resource[i].flags & IORESOURCE_MEM)
272 pcibios_fixup_resource(&dev->resource[i],
273 hose->mem_space);
274 }
275}
276
277void __init
278pcibios_fixup_bus(struct pci_bus *bus)
279{
280 /* Propagate hose info into the subordinate devices. */
281
282 struct pci_controller *hose = bus->sysdata;
283 struct pci_dev *dev = bus->self;
284
285 if (!dev) {
286 /* Root bus. */
287 u32 pci_mem_end;
288 u32 sg_base = hose->sg_pci ? hose->sg_pci->dma_base : ~0;
289 unsigned long end;
290
291 bus->resource[0] = hose->io_space;
292 bus->resource[1] = hose->mem_space;
293
294 /* Adjust hose mem_space limit to prevent PCI allocations
295 in the iommu windows. */
296 pci_mem_end = min((u32)__direct_map_base, sg_base) - 1;
297 end = hose->mem_space->start + pci_mem_end;
298 if (hose->mem_space->end > end)
299 hose->mem_space->end = end;
300 } else if (pci_probe_only &&
301 (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
302 pci_read_bridge_bases(bus);
303 pcibios_fixup_device_resources(dev, bus);
304 }
305
306 list_for_each_entry(dev, &bus->devices, bus_list) {
307 pdev_save_srm_config(dev);
308 if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
309 pcibios_fixup_device_resources(dev, bus);
310 }
311}
312
313void __init
314pcibios_update_irq(struct pci_dev *dev, int irq)
315{
316 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
317}
318
319/* Most Alphas have straight-forward swizzling needs. */
320
321u8 __init
322common_swizzle(struct pci_dev *dev, u8 *pinp)
323{
324 u8 pin = *pinp;
325
326 while (dev->bus->parent) {
327 pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
328 /* Move up the chain of bridges. */
329 dev = dev->bus->self;
330 }
331 *pinp = pin;
332
333 /* The slot is the slot of the last bridge. */
334 return PCI_SLOT(dev->devfn);
335}
336
337void __devinit
338pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
339 struct resource *res)
340{
341 struct pci_controller *hose = (struct pci_controller *)dev->sysdata;
342 unsigned long offset = 0;
343
344 if (res->flags & IORESOURCE_IO)
345 offset = hose->io_space->start;
346 else if (res->flags & IORESOURCE_MEM)
347 offset = hose->mem_space->start;
348
349 region->start = res->start - offset;
350 region->end = res->end - offset;
351}
352
353#ifdef CONFIG_HOTPLUG
354EXPORT_SYMBOL(pcibios_resource_to_bus);
355#endif
356
357int
358pcibios_enable_device(struct pci_dev *dev, int mask)
359{
360 u16 cmd, oldcmd;
361 int i;
362
363 pci_read_config_word(dev, PCI_COMMAND, &cmd);
364 oldcmd = cmd;
365
366 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
367 struct resource *res = &dev->resource[i];
368
369 if (res->flags & IORESOURCE_IO)
370 cmd |= PCI_COMMAND_IO;
371 else if (res->flags & IORESOURCE_MEM)
372 cmd |= PCI_COMMAND_MEMORY;
373 }
374
375 if (cmd != oldcmd) {
376 printk(KERN_DEBUG "PCI: Enabling device: (%s), cmd %x\n",
377 pci_name(dev), cmd);
378 /* Enable the appropriate bits in the PCI command register. */
379 pci_write_config_word(dev, PCI_COMMAND, cmd);
380 }
381 return 0;
382}
383
384/*
385 * If we set up a device for bus mastering, we need to check the latency
386 * timer as certain firmware forgets to set it properly, as seen
387 * on SX164 and LX164 with SRM.
388 */
389void
390pcibios_set_master(struct pci_dev *dev)
391{
392 u8 lat;
393 pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
394 if (lat >= 16) return;
395 printk("PCI: Setting latency timer of device %s to 64\n",
396 pci_name(dev));
397 pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
398}
399
400static void __init
401pcibios_claim_one_bus(struct pci_bus *b)
402{
403 struct pci_dev *dev;
404 struct pci_bus *child_bus;
405
406 list_for_each_entry(dev, &b->devices, bus_list) {
407 int i;
408
409 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
410 struct resource *r = &dev->resource[i];
411
412 if (r->parent || !r->start || !r->flags)
413 continue;
414 pci_claim_resource(dev, i);
415 }
416 }
417
418 list_for_each_entry(child_bus, &b->children, node)
419 pcibios_claim_one_bus(child_bus);
420}
421
422static void __init
423pcibios_claim_console_setup(void)
424{
425 struct pci_bus *b;
426
427 list_for_each_entry(b, &pci_root_buses, node)
428 pcibios_claim_one_bus(b);
429}
430
431void __init
432common_init_pci(void)
433{
434 struct pci_controller *hose;
435 struct pci_bus *bus;
436 int next_busno;
437 int need_domain_info = 0;
438
439 /* Scan all of the recorded PCI controllers. */
440 for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
441 bus = pci_scan_bus(next_busno, alpha_mv.pci_ops, hose);
442 hose->bus = bus;
443 hose->need_domain_info = need_domain_info;
444 next_busno = bus->subordinate + 1;
445 /* Don't allow 8-bit bus number overflow inside the hose -
446 reserve some space for bridges. */
447 if (next_busno > 224) {
448 next_busno = 0;
449 need_domain_info = 1;
450 }
451 }
452
453 if (pci_probe_only)
454 pcibios_claim_console_setup();
455
456 pci_assign_unassigned_resources();
457 pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
458}
459
460
461struct pci_controller * __init
462alloc_pci_controller(void)
463{
464 struct pci_controller *hose;
465
466 hose = alloc_bootmem(sizeof(*hose));
467
468 *hose_tail = hose;
469 hose_tail = &hose->next;
470
471 return hose;
472}
473
474struct resource * __init
475alloc_resource(void)
476{
477 struct resource *res;
478
479 res = alloc_bootmem(sizeof(*res));
480
481 return res;
482}
483
484
485/* Provide information on locations of various I/O regions in physical
486 memory. Do this on a per-card basis so that we choose the right hose. */
487
488asmlinkage long
489sys_pciconfig_iobase(long which, unsigned long bus, unsigned long dfn)
490{
491 struct pci_controller *hose;
492 struct pci_dev *dev;
493
494 /* from hose or from bus.devfn */
495 if (which & IOBASE_FROM_HOSE) {
496 for(hose = hose_head; hose; hose = hose->next)
497 if (hose->index == bus) break;
498 if (!hose) return -ENODEV;
499 } else {
500 /* Special hook for ISA access. */
501 if (bus == 0 && dfn == 0) {
502 hose = pci_isa_hose;
503 } else {
504 dev = pci_find_slot(bus, dfn);
505 if (!dev)
506 return -ENODEV;
507 hose = dev->sysdata;
508 }
509 }
510
511 switch (which & ~IOBASE_FROM_HOSE) {
512 case IOBASE_HOSE:
513 return hose->index;
514 case IOBASE_SPARSE_MEM:
515 return hose->sparse_mem_base;
516 case IOBASE_DENSE_MEM:
517 return hose->dense_mem_base;
518 case IOBASE_SPARSE_IO:
519 return hose->sparse_io_base;
520 case IOBASE_DENSE_IO:
521 return hose->dense_io_base;
522 case IOBASE_ROOT_BUS:
523 return hose->bus->number;
524 }
525
526 return -EOPNOTSUPP;
527}
528
529/* Create an __iomem token from a PCI BAR. Copied from lib/iomap.c with
530 no changes, since we don't want the other things in that object file. */
531
532void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
533{
534 unsigned long start = pci_resource_start(dev, bar);
535 unsigned long len = pci_resource_len(dev, bar);
536 unsigned long flags = pci_resource_flags(dev, bar);
537
538 if (!len || !start)
539 return NULL;
540 if (maxlen && len > maxlen)
541 len = maxlen;
542 if (flags & IORESOURCE_IO)
543 return ioport_map(start, len);
544 if (flags & IORESOURCE_MEM) {
545 /* Not checking IORESOURCE_CACHEABLE because alpha does
546 not distinguish between ioremap and ioremap_nocache. */
547 return ioremap(start, len);
548 }
549 return NULL;
550}
551
552/* Destroy that token. Not copied from lib/iomap.c. */
553
554void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
555{
556 if (__is_mmio(addr))
557 iounmap(addr);
558}
559
560EXPORT_SYMBOL(pci_iomap);
561EXPORT_SYMBOL(pci_iounmap);
diff --git a/arch/alpha/kernel/pci_impl.h b/arch/alpha/kernel/pci_impl.h
new file mode 100644
index 000000000000..f8b74995a002
--- /dev/null
+++ b/arch/alpha/kernel/pci_impl.h
@@ -0,0 +1,209 @@
1/*
2 * linux/arch/alpha/kernel/pci_impl.h
3 *
4 * This file contains declarations and inline functions for interfacing
5 * with the PCI initialization routines.
6 */
7
8struct pci_dev;
9struct pci_controller;
10struct pci_iommu_arena;
11
12/*
13 * We can't just blindly use 64K for machines with EISA busses; they
14 * may also have PCI-PCI bridges present, and then we'd configure the
15 * bridge incorrectly.
16 *
17 * Also, we start at 0x8000 or 0x9000, in hopes to get all devices'
18 * IO space areas allocated *before* 0xC000; this is because certain
19 * BIOSes (Millennium for one) use PCI Config space "mechanism #2"
20 * accesses to probe the bus. If a device's registers appear at 0xC000,
21 * it may see an INx/OUTx at that address during BIOS emulation of the
22 * VGA BIOS, and some cards, notably Adaptec 2940UW, take mortal offense.
23 */
24
25#define EISA_DEFAULT_IO_BASE 0x9000 /* start above 8th slot */
26#define DEFAULT_IO_BASE 0x8000 /* start at 8th slot */
27
28/*
29 * We try to make the DEFAULT_MEM_BASE addresses *always* have more than
30 * a single bit set. This is so that devices like the broken Myrinet card
31 * will always have a PCI memory address that will never match a IDSEL
32 * address in PCI Config space, which can cause problems with early rev cards.
33 */
34
35/*
36 * An XL is AVANTI (APECS) family, *but* it has only 27 bits of ISA address
37 * that get passed through the PCI<->ISA bridge chip. Although this causes
38 * us to set the PCI->Mem window bases lower than normal, we still allocate
39 * PCI bus devices' memory addresses *below* the low DMA mapping window,
40 * and hope they fit below 64Mb (to avoid conflicts), and so that they can
41 * be accessed via SPARSE space.
42 *
43 * We accept the risk that a broken Myrinet card will be put into a true XL
44 * and thus can more easily run into the problem described below.
45 */
46#define XL_DEFAULT_MEM_BASE ((16+2)*1024*1024) /* 16M to 64M-1 is avail */
47
48/*
49 * APECS and LCA have only 34 bits for physical addresses, thus limiting PCI
50 * bus memory addresses for SPARSE access to be less than 128Mb.
51 */
52#define APECS_AND_LCA_DEFAULT_MEM_BASE ((16+2)*1024*1024)
53
54/*
55 * Because MCPCIA and T2 core logic support more bits for
56 * physical addresses, they should allow an expanded range of SPARSE
57 * memory addresses. However, we do not use them all, in order to
58 * avoid the HAE manipulation that would be needed.
59 */
60#define MCPCIA_DEFAULT_MEM_BASE ((32+2)*1024*1024)
61#define T2_DEFAULT_MEM_BASE ((16+1)*1024*1024)
62
63/*
64 * Because CIA and PYXIS have more bits for physical addresses,
65 * they support an expanded range of SPARSE memory addresses.
66 */
67#define DEFAULT_MEM_BASE ((128+16)*1024*1024)
68
69/* ??? Experimenting with no HAE for CIA. */
70#define CIA_DEFAULT_MEM_BASE ((32+2)*1024*1024)
71
72#define IRONGATE_DEFAULT_MEM_BASE ((256*8-16)*1024*1024)
73
74#define DEFAULT_AGP_APER_SIZE (64*1024*1024)
75
76/*
77 * A small note about bridges and interrupts. The DECchip 21050 (and
78 * later) adheres to the PCI-PCI bridge specification. This says that
79 * the interrupts on the other side of a bridge are swizzled in the
80 * following manner:
81 *
82 * Dev Interrupt Interrupt
83 * Pin on Pin on
84 * Device Connector
85 *
86 * 4 A A
87 * B B
88 * C C
89 * D D
90 *
91 * 5 A B
92 * B C
93 * C D
94 * D A
95 *
96 * 6 A C
97 * B D
98 * C A
99 * D B
100 *
101 * 7 A D
102 * B A
103 * C B
104 * D C
105 *
106 * Where A = pin 1, B = pin 2 and so on and pin=0 = default = A.
107 * Thus, each swizzle is ((pin-1) + (device#-4)) % 4
108 *
109 * The following code swizzles for exactly one bridge. The routine
110 * common_swizzle below handles multiple bridges. But there are a
111 * couple boards that do strange things, so we define this here.
112 */
113
114static inline u8 bridge_swizzle(u8 pin, u8 slot)
115{
116 return (((pin-1) + slot) % 4) + 1;
117}
118
119
120/* The following macro is used to implement the table-based irq mapping
121 function for all single-bus Alphas. */
122
123#define COMMON_TABLE_LOOKUP \
124({ long _ctl_ = -1; \
125 if (slot >= min_idsel && slot <= max_idsel && pin < irqs_per_slot) \
126 _ctl_ = irq_tab[slot - min_idsel][pin]; \
127 _ctl_; })
128
129
130/* A PCI IOMMU allocation arena. There are typically two of these
131 regions per bus. */
132/* ??? The 8400 has a 32-byte pte entry, and the entire table apparently
133 lives directly on the host bridge (no tlb?). We don't support this
134 machine, but if we ever did, we'd need to parameterize all this quite
135 a bit further. Probably with per-bus operation tables. */
136
137struct pci_iommu_arena
138{
139 spinlock_t lock;
140 struct pci_controller *hose;
141#define IOMMU_INVALID_PTE 0x2 /* 32:63 bits MBZ */
142#define IOMMU_RESERVED_PTE 0xface
143 unsigned long *ptes;
144 dma_addr_t dma_base;
145 unsigned int size;
146 unsigned int next_entry;
147 unsigned int align_entry;
148};
149
150#if defined(CONFIG_ALPHA_SRM) && \
151 (defined(CONFIG_ALPHA_CIA) || defined(CONFIG_ALPHA_LCA))
152# define NEED_SRM_SAVE_RESTORE
153#else
154# undef NEED_SRM_SAVE_RESTORE
155#endif
156
157#if defined(CONFIG_ALPHA_GENERIC) || defined(NEED_SRM_SAVE_RESTORE)
158# define ALPHA_RESTORE_SRM_SETUP
159#else
160# undef ALPHA_RESTORE_SRM_SETUP
161#endif
162
163#ifdef ALPHA_RESTORE_SRM_SETUP
164/* Store PCI device configuration left by SRM here. */
165struct pdev_srm_saved_conf
166{
167 struct pdev_srm_saved_conf *next;
168 struct pci_dev *dev;
169};
170
171extern void pci_restore_srm_config(void);
172#else
173#define pdev_save_srm_config(dev) do {} while (0)
174#define pci_restore_srm_config() do {} while (0)
175#endif
176
177/* The hose list. */
178extern struct pci_controller *hose_head, **hose_tail;
179extern struct pci_controller *pci_isa_hose;
180
181/* Indicate that we trust the console to configure things properly. */
182extern int pci_probe_only;
183
184extern unsigned long alpha_agpgart_size;
185
186extern void common_init_pci(void);
187extern u8 common_swizzle(struct pci_dev *, u8 *);
188extern struct pci_controller *alloc_pci_controller(void);
189extern struct resource *alloc_resource(void);
190
191extern struct pci_iommu_arena *iommu_arena_new_node(int,
192 struct pci_controller *,
193 dma_addr_t, unsigned long,
194 unsigned long);
195extern struct pci_iommu_arena *iommu_arena_new(struct pci_controller *,
196 dma_addr_t, unsigned long,
197 unsigned long);
198extern const char *const pci_io_names[];
199extern const char *const pci_mem_names[];
200extern const char pci_hae0_name[];
201
202extern unsigned long size_for_memory(unsigned long max);
203
204extern int iommu_reserve(struct pci_iommu_arena *, long, long);
205extern int iommu_release(struct pci_iommu_arena *, long, long);
206extern int iommu_bind(struct pci_iommu_arena *, long, long, unsigned long *);
207extern int iommu_unbind(struct pci_iommu_arena *, long, long);
208
209
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
new file mode 100644
index 000000000000..7cb23f12ecbd
--- /dev/null
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -0,0 +1,971 @@
1/*
2 * linux/arch/alpha/kernel/pci_iommu.c
3 */
4
5#include <linux/kernel.h>
6#include <linux/mm.h>
7#include <linux/pci.h>
8#include <linux/slab.h>
9#include <linux/bootmem.h>
10
11#include <asm/io.h>
12#include <asm/hwrpb.h>
13
14#include "proto.h"
15#include "pci_impl.h"
16
17
18#define DEBUG_ALLOC 0
19#if DEBUG_ALLOC > 0
20# define DBGA(args...) printk(KERN_DEBUG args)
21#else
22# define DBGA(args...)
23#endif
24#if DEBUG_ALLOC > 1
25# define DBGA2(args...) printk(KERN_DEBUG args)
26#else
27# define DBGA2(args...)
28#endif
29
30#define DEBUG_NODIRECT 0
31#define DEBUG_FORCEDAC 0
32
33#define ISA_DMA_MASK 0x00ffffff
34
35static inline unsigned long
36mk_iommu_pte(unsigned long paddr)
37{
38 return (paddr >> (PAGE_SHIFT-1)) | 1;
39}
40
41static inline long
42calc_npages(long bytes)
43{
44 return (bytes + PAGE_SIZE - 1) >> PAGE_SHIFT;
45}
46
47
48/* Return the minimum of MAX or the first power of two larger
49 than main memory. */
50
51unsigned long
52size_for_memory(unsigned long max)
53{
54 unsigned long mem = max_low_pfn << PAGE_SHIFT;
55 if (mem < max)
56 max = 1UL << ceil_log2(mem);
57 return max;
58}
59
60struct pci_iommu_arena *
61iommu_arena_new_node(int nid, struct pci_controller *hose, dma_addr_t base,
62 unsigned long window_size, unsigned long align)
63{
64 unsigned long mem_size;
65 struct pci_iommu_arena *arena;
66
67 mem_size = window_size / (PAGE_SIZE / sizeof(unsigned long));
68
69 /* Note that the TLB lookup logic uses bitwise concatenation,
70 not addition, so the required arena alignment is based on
71 the size of the window. Retain the align parameter so that
72 particular systems can over-align the arena. */
73 if (align < mem_size)
74 align = mem_size;
75
76
77#ifdef CONFIG_DISCONTIGMEM
78
79 if (!NODE_DATA(nid) ||
80 (NULL == (arena = alloc_bootmem_node(NODE_DATA(nid),
81 sizeof(*arena))))) {
82 printk("%s: couldn't allocate arena from node %d\n"
83 " falling back to system-wide allocation\n",
84 __FUNCTION__, nid);
85 arena = alloc_bootmem(sizeof(*arena));
86 }
87
88 if (!NODE_DATA(nid) ||
89 (NULL == (arena->ptes = __alloc_bootmem_node(NODE_DATA(nid),
90 mem_size,
91 align,
92 0)))) {
93 printk("%s: couldn't allocate arena ptes from node %d\n"
94 " falling back to system-wide allocation\n",
95 __FUNCTION__, nid);
96 arena->ptes = __alloc_bootmem(mem_size, align, 0);
97 }
98
99#else /* CONFIG_DISCONTIGMEM */
100
101 arena = alloc_bootmem(sizeof(*arena));
102 arena->ptes = __alloc_bootmem(mem_size, align, 0);
103
104#endif /* CONFIG_DISCONTIGMEM */
105
106 spin_lock_init(&arena->lock);
107 arena->hose = hose;
108 arena->dma_base = base;
109 arena->size = window_size;
110 arena->next_entry = 0;
111
112 /* Align allocations to a multiple of a page size. Not needed
113 unless there are chip bugs. */
114 arena->align_entry = 1;
115
116 return arena;
117}
118
119struct pci_iommu_arena *
120iommu_arena_new(struct pci_controller *hose, dma_addr_t base,
121 unsigned long window_size, unsigned long align)
122{
123 return iommu_arena_new_node(0, hose, base, window_size, align);
124}
125
126/* Must be called with the arena lock held */
127static long
128iommu_arena_find_pages(struct pci_iommu_arena *arena, long n, long mask)
129{
130 unsigned long *ptes;
131 long i, p, nent;
132
133 /* Search forward for the first mask-aligned sequence of N free ptes */
134 ptes = arena->ptes;
135 nent = arena->size >> PAGE_SHIFT;
136 p = (arena->next_entry + mask) & ~mask;
137 i = 0;
138 while (i < n && p+i < nent) {
139 if (ptes[p+i])
140 p = (p + i + 1 + mask) & ~mask, i = 0;
141 else
142 i = i + 1;
143 }
144
145 if (i < n) {
146 /* Reached the end. Flush the TLB and restart the
147 search from the beginning. */
148 alpha_mv.mv_pci_tbi(arena->hose, 0, -1);
149
150 p = 0, i = 0;
151 while (i < n && p+i < nent) {
152 if (ptes[p+i])
153 p = (p + i + 1 + mask) & ~mask, i = 0;
154 else
155 i = i + 1;
156 }
157
158 if (i < n)
159 return -1;
160 }
161
162 /* Success. It's the responsibility of the caller to mark them
163 in use before releasing the lock */
164 return p;
165}
166
167static long
168iommu_arena_alloc(struct pci_iommu_arena *arena, long n, unsigned int align)
169{
170 unsigned long flags;
171 unsigned long *ptes;
172 long i, p, mask;
173
174 spin_lock_irqsave(&arena->lock, flags);
175
176 /* Search for N empty ptes */
177 ptes = arena->ptes;
178 mask = max(align, arena->align_entry) - 1;
179 p = iommu_arena_find_pages(arena, n, mask);
180 if (p < 0) {
181 spin_unlock_irqrestore(&arena->lock, flags);
182 return -1;
183 }
184
185 /* Success. Mark them all in use, ie not zero and invalid
186 for the iommu tlb that could load them from under us.
187 The chip specific bits will fill this in with something
188 kosher when we return. */
189 for (i = 0; i < n; ++i)
190 ptes[p+i] = IOMMU_INVALID_PTE;
191
192 arena->next_entry = p + n;
193 spin_unlock_irqrestore(&arena->lock, flags);
194
195 return p;
196}
197
198static void
199iommu_arena_free(struct pci_iommu_arena *arena, long ofs, long n)
200{
201 unsigned long *p;
202 long i;
203
204 p = arena->ptes + ofs;
205 for (i = 0; i < n; ++i)
206 p[i] = 0;
207}
208
209/* Map a single buffer of the indicated size for PCI DMA in streaming
210 mode. The 32-bit PCI bus mastering address to use is returned.
211 Once the device is given the dma address, the device owns this memory
212 until either pci_unmap_single or pci_dma_sync_single is performed. */
213
214static dma_addr_t
215pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size,
216 int dac_allowed)
217{
218 struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose;
219 dma_addr_t max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK;
220 struct pci_iommu_arena *arena;
221 long npages, dma_ofs, i;
222 unsigned long paddr;
223 dma_addr_t ret;
224 unsigned int align = 0;
225
226 paddr = __pa(cpu_addr);
227
228#if !DEBUG_NODIRECT
229 /* First check to see if we can use the direct map window. */
230 if (paddr + size + __direct_map_base - 1 <= max_dma
231 && paddr + size <= __direct_map_size) {
232 ret = paddr + __direct_map_base;
233
234 DBGA2("pci_map_single: [%p,%lx] -> direct %lx from %p\n",
235 cpu_addr, size, ret, __builtin_return_address(0));
236
237 return ret;
238 }
239#endif
240
241 /* Next, use DAC if selected earlier. */
242 if (dac_allowed) {
243 ret = paddr + alpha_mv.pci_dac_offset;
244
245 DBGA2("pci_map_single: [%p,%lx] -> DAC %lx from %p\n",
246 cpu_addr, size, ret, __builtin_return_address(0));
247
248 return ret;
249 }
250
251 /* If the machine doesn't define a pci_tbi routine, we have to
252 assume it doesn't support sg mapping, and, since we tried to
253 use direct_map above, it now must be considered an error. */
254 if (! alpha_mv.mv_pci_tbi) {
255 static int been_here = 0; /* Only print the message once. */
256 if (!been_here) {
257 printk(KERN_WARNING "pci_map_single: no HW sg\n");
258 been_here = 1;
259 }
260 return 0;
261 }
262
263 arena = hose->sg_pci;
264 if (!arena || arena->dma_base + arena->size - 1 > max_dma)
265 arena = hose->sg_isa;
266
267 npages = calc_npages((paddr & ~PAGE_MASK) + size);
268
269 /* Force allocation to 64KB boundary for ISA bridges. */
270 if (pdev && pdev == isa_bridge)
271 align = 8;
272 dma_ofs = iommu_arena_alloc(arena, npages, align);
273 if (dma_ofs < 0) {
274 printk(KERN_WARNING "pci_map_single failed: "
275 "could not allocate dma page tables\n");
276 return 0;
277 }
278
279 paddr &= PAGE_MASK;
280 for (i = 0; i < npages; ++i, paddr += PAGE_SIZE)
281 arena->ptes[i + dma_ofs] = mk_iommu_pte(paddr);
282
283 ret = arena->dma_base + dma_ofs * PAGE_SIZE;
284 ret += (unsigned long)cpu_addr & ~PAGE_MASK;
285
286 DBGA2("pci_map_single: [%p,%lx] np %ld -> sg %lx from %p\n",
287 cpu_addr, size, npages, ret, __builtin_return_address(0));
288
289 return ret;
290}
291
292dma_addr_t
293pci_map_single(struct pci_dev *pdev, void *cpu_addr, size_t size, int dir)
294{
295 int dac_allowed;
296
297 if (dir == PCI_DMA_NONE)
298 BUG();
299
300 dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
301 return pci_map_single_1(pdev, cpu_addr, size, dac_allowed);
302}
303
304dma_addr_t
305pci_map_page(struct pci_dev *pdev, struct page *page, unsigned long offset,
306 size_t size, int dir)
307{
308 int dac_allowed;
309
310 if (dir == PCI_DMA_NONE)
311 BUG();
312
313 dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
314 return pci_map_single_1(pdev, (char *)page_address(page) + offset,
315 size, dac_allowed);
316}
317
318/* Unmap a single streaming mode DMA translation. The DMA_ADDR and
319 SIZE must match what was provided for in a previous pci_map_single
320 call. All other usages are undefined. After this call, reads by
321 the cpu to the buffer are guaranteed to see whatever the device
322 wrote there. */
323
324void
325pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
326 int direction)
327{
328 unsigned long flags;
329 struct pci_controller *hose = pdev ? pdev->sysdata : pci_isa_hose;
330 struct pci_iommu_arena *arena;
331 long dma_ofs, npages;
332
333 if (direction == PCI_DMA_NONE)
334 BUG();
335
336 if (dma_addr >= __direct_map_base
337 && dma_addr < __direct_map_base + __direct_map_size) {
338 /* Nothing to do. */
339
340 DBGA2("pci_unmap_single: direct [%lx,%lx] from %p\n",
341 dma_addr, size, __builtin_return_address(0));
342
343 return;
344 }
345
346 if (dma_addr > 0xffffffff) {
347 DBGA2("pci64_unmap_single: DAC [%lx,%lx] from %p\n",
348 dma_addr, size, __builtin_return_address(0));
349 return;
350 }
351
352 arena = hose->sg_pci;
353 if (!arena || dma_addr < arena->dma_base)
354 arena = hose->sg_isa;
355
356 dma_ofs = (dma_addr - arena->dma_base) >> PAGE_SHIFT;
357 if (dma_ofs * PAGE_SIZE >= arena->size) {
358 printk(KERN_ERR "Bogus pci_unmap_single: dma_addr %lx "
359 " base %lx size %x\n", dma_addr, arena->dma_base,
360 arena->size);
361 return;
362 BUG();
363 }
364
365 npages = calc_npages((dma_addr & ~PAGE_MASK) + size);
366
367 spin_lock_irqsave(&arena->lock, flags);
368
369 iommu_arena_free(arena, dma_ofs, npages);
370
371 /* If we're freeing ptes above the `next_entry' pointer (they
372 may have snuck back into the TLB since the last wrap flush),
373 we need to flush the TLB before reallocating the latter. */
374 if (dma_ofs >= arena->next_entry)
375 alpha_mv.mv_pci_tbi(hose, dma_addr, dma_addr + size - 1);
376
377 spin_unlock_irqrestore(&arena->lock, flags);
378
379 DBGA2("pci_unmap_single: sg [%lx,%lx] np %ld from %p\n",
380 dma_addr, size, npages, __builtin_return_address(0));
381}
382
383void
384pci_unmap_page(struct pci_dev *pdev, dma_addr_t dma_addr,
385 size_t size, int direction)
386{
387 pci_unmap_single(pdev, dma_addr, size, direction);
388}
389
390/* Allocate and map kernel buffer using consistent mode DMA for PCI
391 device. Returns non-NULL cpu-view pointer to the buffer if
392 successful and sets *DMA_ADDRP to the pci side dma address as well,
393 else DMA_ADDRP is undefined. */
394
395void *
396pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp)
397{
398 void *cpu_addr;
399 long order = get_order(size);
400 int gfp = GFP_ATOMIC;
401
402try_again:
403 cpu_addr = (void *)__get_free_pages(gfp, order);
404 if (! cpu_addr) {
405 printk(KERN_INFO "pci_alloc_consistent: "
406 "get_free_pages failed from %p\n",
407 __builtin_return_address(0));
408 /* ??? Really atomic allocation? Otherwise we could play
409 with vmalloc and sg if we can't find contiguous memory. */
410 return NULL;
411 }
412 memset(cpu_addr, 0, size);
413
414 *dma_addrp = pci_map_single_1(pdev, cpu_addr, size, 0);
415 if (*dma_addrp == 0) {
416 free_pages((unsigned long)cpu_addr, order);
417 if (alpha_mv.mv_pci_tbi || (gfp & GFP_DMA))
418 return NULL;
419 /* The address doesn't fit required mask and we
420 do not have iommu. Try again with GFP_DMA. */
421 gfp |= GFP_DMA;
422 goto try_again;
423 }
424
425 DBGA2("pci_alloc_consistent: %lx -> [%p,%x] from %p\n",
426 size, cpu_addr, *dma_addrp, __builtin_return_address(0));
427
428 return cpu_addr;
429}
430
431/* Free and unmap a consistent DMA buffer. CPU_ADDR and DMA_ADDR must
432 be values that were returned from pci_alloc_consistent. SIZE must
433 be the same as what as passed into pci_alloc_consistent.
434 References to the memory and mappings associated with CPU_ADDR or
435 DMA_ADDR past this call are illegal. */
436
437void
438pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu_addr,
439 dma_addr_t dma_addr)
440{
441 pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL);
442 free_pages((unsigned long)cpu_addr, get_order(size));
443
444 DBGA2("pci_free_consistent: [%x,%lx] from %p\n",
445 dma_addr, size, __builtin_return_address(0));
446}
447
448
449/* Classify the elements of the scatterlist. Write dma_address
450 of each element with:
451 0 : Followers all physically adjacent.
452 1 : Followers all virtually adjacent.
453 -1 : Not leader, physically adjacent to previous.
454 -2 : Not leader, virtually adjacent to previous.
455 Write dma_length of each leader with the combined lengths of
456 the mergable followers. */
457
458#define SG_ENT_VIRT_ADDRESS(SG) (page_address((SG)->page) + (SG)->offset)
459#define SG_ENT_PHYS_ADDRESS(SG) __pa(SG_ENT_VIRT_ADDRESS(SG))
460
461static void
462sg_classify(struct scatterlist *sg, struct scatterlist *end, int virt_ok)
463{
464 unsigned long next_paddr;
465 struct scatterlist *leader;
466 long leader_flag, leader_length;
467
468 leader = sg;
469 leader_flag = 0;
470 leader_length = leader->length;
471 next_paddr = SG_ENT_PHYS_ADDRESS(leader) + leader_length;
472
473 for (++sg; sg < end; ++sg) {
474 unsigned long addr, len;
475 addr = SG_ENT_PHYS_ADDRESS(sg);
476 len = sg->length;
477
478 if (next_paddr == addr) {
479 sg->dma_address = -1;
480 leader_length += len;
481 } else if (((next_paddr | addr) & ~PAGE_MASK) == 0 && virt_ok) {
482 sg->dma_address = -2;
483 leader_flag = 1;
484 leader_length += len;
485 } else {
486 leader->dma_address = leader_flag;
487 leader->dma_length = leader_length;
488 leader = sg;
489 leader_flag = 0;
490 leader_length = len;
491 }
492
493 next_paddr = addr + len;
494 }
495
496 leader->dma_address = leader_flag;
497 leader->dma_length = leader_length;
498}
499
500/* Given a scatterlist leader, choose an allocation method and fill
501 in the blanks. */
502
503static int
504sg_fill(struct scatterlist *leader, struct scatterlist *end,
505 struct scatterlist *out, struct pci_iommu_arena *arena,
506 dma_addr_t max_dma, int dac_allowed)
507{
508 unsigned long paddr = SG_ENT_PHYS_ADDRESS(leader);
509 long size = leader->dma_length;
510 struct scatterlist *sg;
511 unsigned long *ptes;
512 long npages, dma_ofs, i;
513
514#if !DEBUG_NODIRECT
515 /* If everything is physically contiguous, and the addresses
516 fall into the direct-map window, use it. */
517 if (leader->dma_address == 0
518 && paddr + size + __direct_map_base - 1 <= max_dma
519 && paddr + size <= __direct_map_size) {
520 out->dma_address = paddr + __direct_map_base;
521 out->dma_length = size;
522
523 DBGA(" sg_fill: [%p,%lx] -> direct %lx\n",
524 __va(paddr), size, out->dma_address);
525
526 return 0;
527 }
528#endif
529
530 /* If physically contiguous and DAC is available, use it. */
531 if (leader->dma_address == 0 && dac_allowed) {
532 out->dma_address = paddr + alpha_mv.pci_dac_offset;
533 out->dma_length = size;
534
535 DBGA(" sg_fill: [%p,%lx] -> DAC %lx\n",
536 __va(paddr), size, out->dma_address);
537
538 return 0;
539 }
540
541 /* Otherwise, we'll use the iommu to make the pages virtually
542 contiguous. */
543
544 paddr &= ~PAGE_MASK;
545 npages = calc_npages(paddr + size);
546 dma_ofs = iommu_arena_alloc(arena, npages, 0);
547 if (dma_ofs < 0) {
548 /* If we attempted a direct map above but failed, die. */
549 if (leader->dma_address == 0)
550 return -1;
551
552 /* Otherwise, break up the remaining virtually contiguous
553 hunks into individual direct maps and retry. */
554 sg_classify(leader, end, 0);
555 return sg_fill(leader, end, out, arena, max_dma, dac_allowed);
556 }
557
558 out->dma_address = arena->dma_base + dma_ofs*PAGE_SIZE + paddr;
559 out->dma_length = size;
560
561 DBGA(" sg_fill: [%p,%lx] -> sg %lx np %ld\n",
562 __va(paddr), size, out->dma_address, npages);
563
564 /* All virtually contiguous. We need to find the length of each
565 physically contiguous subsegment to fill in the ptes. */
566 ptes = &arena->ptes[dma_ofs];
567 sg = leader;
568 do {
569#if DEBUG_ALLOC > 0
570 struct scatterlist *last_sg = sg;
571#endif
572
573 size = sg->length;
574 paddr = SG_ENT_PHYS_ADDRESS(sg);
575
576 while (sg+1 < end && (int) sg[1].dma_address == -1) {
577 size += sg[1].length;
578 sg++;
579 }
580
581 npages = calc_npages((paddr & ~PAGE_MASK) + size);
582
583 paddr &= PAGE_MASK;
584 for (i = 0; i < npages; ++i, paddr += PAGE_SIZE)
585 *ptes++ = mk_iommu_pte(paddr);
586
587#if DEBUG_ALLOC > 0
588 DBGA(" (%ld) [%p,%x] np %ld\n",
589 last_sg - leader, SG_ENT_VIRT_ADDRESS(last_sg),
590 last_sg->length, npages);
591 while (++last_sg <= sg) {
592 DBGA(" (%ld) [%p,%x] cont\n",
593 last_sg - leader, SG_ENT_VIRT_ADDRESS(last_sg),
594 last_sg->length);
595 }
596#endif
597 } while (++sg < end && (int) sg->dma_address < 0);
598
599 return 1;
600}
601
602int
603pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
604 int direction)
605{
606 struct scatterlist *start, *end, *out;
607 struct pci_controller *hose;
608 struct pci_iommu_arena *arena;
609 dma_addr_t max_dma;
610 int dac_allowed;
611
612 if (direction == PCI_DMA_NONE)
613 BUG();
614
615 dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
616
617 /* Fast path single entry scatterlists. */
618 if (nents == 1) {
619 sg->dma_length = sg->length;
620 sg->dma_address
621 = pci_map_single_1(pdev, SG_ENT_VIRT_ADDRESS(sg),
622 sg->length, dac_allowed);
623 return sg->dma_address != 0;
624 }
625
626 start = sg;
627 end = sg + nents;
628
629 /* First, prepare information about the entries. */
630 sg_classify(sg, end, alpha_mv.mv_pci_tbi != 0);
631
632 /* Second, figure out where we're going to map things. */
633 if (alpha_mv.mv_pci_tbi) {
634 hose = pdev ? pdev->sysdata : pci_isa_hose;
635 max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK;
636 arena = hose->sg_pci;
637 if (!arena || arena->dma_base + arena->size - 1 > max_dma)
638 arena = hose->sg_isa;
639 } else {
640 max_dma = -1;
641 arena = NULL;
642 hose = NULL;
643 }
644
645 /* Third, iterate over the scatterlist leaders and allocate
646 dma space as needed. */
647 for (out = sg; sg < end; ++sg) {
648 if ((int) sg->dma_address < 0)
649 continue;
650 if (sg_fill(sg, end, out, arena, max_dma, dac_allowed) < 0)
651 goto error;
652 out++;
653 }
654
655 /* Mark the end of the list for pci_unmap_sg. */
656 if (out < end)
657 out->dma_length = 0;
658
659 if (out - start == 0)
660 printk(KERN_WARNING "pci_map_sg failed: no entries?\n");
661 DBGA("pci_map_sg: %ld entries\n", out - start);
662
663 return out - start;
664
665 error:
666 printk(KERN_WARNING "pci_map_sg failed: "
667 "could not allocate dma page tables\n");
668
669 /* Some allocation failed while mapping the scatterlist
670 entries. Unmap them now. */
671 if (out > start)
672 pci_unmap_sg(pdev, start, out - start, direction);
673 return 0;
674}
675
676/* Unmap a set of streaming mode DMA translations. Again, cpu read
677 rules concerning calls here are the same as for pci_unmap_single()
678 above. */
679
680void
681pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
682 int direction)
683{
684 unsigned long flags;
685 struct pci_controller *hose;
686 struct pci_iommu_arena *arena;
687 struct scatterlist *end;
688 dma_addr_t max_dma;
689 dma_addr_t fbeg, fend;
690
691 if (direction == PCI_DMA_NONE)
692 BUG();
693
694 if (! alpha_mv.mv_pci_tbi)
695 return;
696
697 hose = pdev ? pdev->sysdata : pci_isa_hose;
698 max_dma = pdev ? pdev->dma_mask : ISA_DMA_MASK;
699 arena = hose->sg_pci;
700 if (!arena || arena->dma_base + arena->size - 1 > max_dma)
701 arena = hose->sg_isa;
702
703 fbeg = -1, fend = 0;
704
705 spin_lock_irqsave(&arena->lock, flags);
706
707 for (end = sg + nents; sg < end; ++sg) {
708 dma64_addr_t addr;
709 size_t size;
710 long npages, ofs;
711 dma_addr_t tend;
712
713 addr = sg->dma_address;
714 size = sg->dma_length;
715 if (!size)
716 break;
717
718 if (addr > 0xffffffff) {
719 /* It's a DAC address -- nothing to do. */
720 DBGA(" (%ld) DAC [%lx,%lx]\n",
721 sg - end + nents, addr, size);
722 continue;
723 }
724
725 if (addr >= __direct_map_base
726 && addr < __direct_map_base + __direct_map_size) {
727 /* Nothing to do. */
728 DBGA(" (%ld) direct [%lx,%lx]\n",
729 sg - end + nents, addr, size);
730 continue;
731 }
732
733 DBGA(" (%ld) sg [%lx,%lx]\n",
734 sg - end + nents, addr, size);
735
736 npages = calc_npages((addr & ~PAGE_MASK) + size);
737 ofs = (addr - arena->dma_base) >> PAGE_SHIFT;
738 iommu_arena_free(arena, ofs, npages);
739
740 tend = addr + size - 1;
741 if (fbeg > addr) fbeg = addr;
742 if (fend < tend) fend = tend;
743 }
744
745 /* If we're freeing ptes above the `next_entry' pointer (they
746 may have snuck back into the TLB since the last wrap flush),
747 we need to flush the TLB before reallocating the latter. */
748 if ((fend - arena->dma_base) >> PAGE_SHIFT >= arena->next_entry)
749 alpha_mv.mv_pci_tbi(hose, fbeg, fend);
750
751 spin_unlock_irqrestore(&arena->lock, flags);
752
753 DBGA("pci_unmap_sg: %ld entries\n", nents - (end - sg));
754}
755
756
757/* Return whether the given PCI device DMA address mask can be
758 supported properly. */
759
760int
761pci_dma_supported(struct pci_dev *pdev, u64 mask)
762{
763 struct pci_controller *hose;
764 struct pci_iommu_arena *arena;
765
766 /* If there exists a direct map, and the mask fits either
767 the entire direct mapped space or the total system memory as
768 shifted by the map base */
769 if (__direct_map_size != 0
770 && (__direct_map_base + __direct_map_size - 1 <= mask ||
771 __direct_map_base + (max_low_pfn << PAGE_SHIFT) - 1 <= mask))
772 return 1;
773
774 /* Check that we have a scatter-gather arena that fits. */
775 hose = pdev ? pdev->sysdata : pci_isa_hose;
776 arena = hose->sg_isa;
777 if (arena && arena->dma_base + arena->size - 1 <= mask)
778 return 1;
779 arena = hose->sg_pci;
780 if (arena && arena->dma_base + arena->size - 1 <= mask)
781 return 1;
782
783 /* As last resort try ZONE_DMA. */
784 if (!__direct_map_base && MAX_DMA_ADDRESS - IDENT_ADDR - 1 <= mask)
785 return 1;
786
787 return 0;
788}
789
790
791/*
792 * AGP GART extensions to the IOMMU
793 */
794int
795iommu_reserve(struct pci_iommu_arena *arena, long pg_count, long align_mask)
796{
797 unsigned long flags;
798 unsigned long *ptes;
799 long i, p;
800
801 if (!arena) return -EINVAL;
802
803 spin_lock_irqsave(&arena->lock, flags);
804
805 /* Search for N empty ptes. */
806 ptes = arena->ptes;
807 p = iommu_arena_find_pages(arena, pg_count, align_mask);
808 if (p < 0) {
809 spin_unlock_irqrestore(&arena->lock, flags);
810 return -1;
811 }
812
813 /* Success. Mark them all reserved (ie not zero and invalid)
814 for the iommu tlb that could load them from under us.
815 They will be filled in with valid bits by _bind() */
816 for (i = 0; i < pg_count; ++i)
817 ptes[p+i] = IOMMU_RESERVED_PTE;
818
819 arena->next_entry = p + pg_count;
820 spin_unlock_irqrestore(&arena->lock, flags);
821
822 return p;
823}
824
825int
826iommu_release(struct pci_iommu_arena *arena, long pg_start, long pg_count)
827{
828 unsigned long *ptes;
829 long i;
830
831 if (!arena) return -EINVAL;
832
833 ptes = arena->ptes;
834
835 /* Make sure they're all reserved first... */
836 for(i = pg_start; i < pg_start + pg_count; i++)
837 if (ptes[i] != IOMMU_RESERVED_PTE)
838 return -EBUSY;
839
840 iommu_arena_free(arena, pg_start, pg_count);
841 return 0;
842}
843
844int
845iommu_bind(struct pci_iommu_arena *arena, long pg_start, long pg_count,
846 unsigned long *physaddrs)
847{
848 unsigned long flags;
849 unsigned long *ptes;
850 long i, j;
851
852 if (!arena) return -EINVAL;
853
854 spin_lock_irqsave(&arena->lock, flags);
855
856 ptes = arena->ptes;
857
858 for(j = pg_start; j < pg_start + pg_count; j++) {
859 if (ptes[j] != IOMMU_RESERVED_PTE) {
860 spin_unlock_irqrestore(&arena->lock, flags);
861 return -EBUSY;
862 }
863 }
864
865 for(i = 0, j = pg_start; i < pg_count; i++, j++)
866 ptes[j] = mk_iommu_pte(physaddrs[i]);
867
868 spin_unlock_irqrestore(&arena->lock, flags);
869
870 return 0;
871}
872
873int
874iommu_unbind(struct pci_iommu_arena *arena, long pg_start, long pg_count)
875{
876 unsigned long *p;
877 long i;
878
879 if (!arena) return -EINVAL;
880
881 p = arena->ptes + pg_start;
882 for(i = 0; i < pg_count; i++)
883 p[i] = IOMMU_RESERVED_PTE;
884
885 return 0;
886}
887
888/* True if the machine supports DAC addressing, and DEV can
889 make use of it given MASK. */
890
891int
892pci_dac_dma_supported(struct pci_dev *dev, u64 mask)
893{
894 dma64_addr_t dac_offset = alpha_mv.pci_dac_offset;
895 int ok = 1;
896
897 /* If this is not set, the machine doesn't support DAC at all. */
898 if (dac_offset == 0)
899 ok = 0;
900
901 /* The device has to be able to address our DAC bit. */
902 if ((dac_offset & dev->dma_mask) != dac_offset)
903 ok = 0;
904
905 /* If both conditions above are met, we are fine. */
906 DBGA("pci_dac_dma_supported %s from %p\n",
907 ok ? "yes" : "no", __builtin_return_address(0));
908
909 return ok;
910}
911
912dma64_addr_t
913pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page,
914 unsigned long offset, int direction)
915{
916 return (alpha_mv.pci_dac_offset
917 + __pa(page_address(page))
918 + (dma64_addr_t) offset);
919}
920
921struct page *
922pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr)
923{
924 unsigned long paddr = (dma_addr & PAGE_MASK) - alpha_mv.pci_dac_offset;
925 return virt_to_page(__va(paddr));
926}
927
928unsigned long
929pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr)
930{
931 return (dma_addr & ~PAGE_MASK);
932}
933
934
935/* Helper for generic DMA-mapping functions. */
936
937struct pci_dev *
938alpha_gendev_to_pci(struct device *dev)
939{
940 if (dev && dev->bus == &pci_bus_type)
941 return to_pci_dev(dev);
942
943 /* Assume that non-PCI devices asking for DMA are either ISA or EISA,
944 BUG() otherwise. */
945 BUG_ON(!isa_bridge);
946
947 /* Assume non-busmaster ISA DMA when dma_mask is not set (the ISA
948 bridge is bus master then). */
949 if (!dev || !dev->dma_mask || !*dev->dma_mask)
950 return isa_bridge;
951
952 /* For EISA bus masters, return isa_bridge (it might have smaller
953 dma_mask due to wiring limitations). */
954 if (*dev->dma_mask >= isa_bridge->dma_mask)
955 return isa_bridge;
956
957 /* This assumes ISA bus master with dma_mask 0xffffff. */
958 return NULL;
959}
960
961int
962dma_set_mask(struct device *dev, u64 mask)
963{
964 if (!dev->dma_mask ||
965 !pci_dma_supported(alpha_gendev_to_pci(dev), mask))
966 return -EIO;
967
968 *dev->dma_mask = mask;
969
970 return 0;
971}
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
new file mode 100644
index 000000000000..4933f3ce5833
--- /dev/null
+++ b/arch/alpha/kernel/process.c
@@ -0,0 +1,528 @@
1/*
2 * linux/arch/alpha/kernel/process.c
3 *
4 * Copyright (C) 1995 Linus Torvalds
5 */
6
7/*
8 * This file handles the architecture-dependent parts of process handling.
9 */
10
11#include <linux/config.h>
12#include <linux/errno.h>
13#include <linux/module.h>
14#include <linux/sched.h>
15#include <linux/kernel.h>
16#include <linux/mm.h>
17#include <linux/smp.h>
18#include <linux/smp_lock.h>
19#include <linux/stddef.h>
20#include <linux/unistd.h>
21#include <linux/ptrace.h>
22#include <linux/slab.h>
23#include <linux/user.h>
24#include <linux/a.out.h>
25#include <linux/utsname.h>
26#include <linux/time.h>
27#include <linux/major.h>
28#include <linux/stat.h>
29#include <linux/mman.h>
30#include <linux/elfcore.h>
31#include <linux/reboot.h>
32#include <linux/tty.h>
33#include <linux/console.h>
34
35#include <asm/reg.h>
36#include <asm/uaccess.h>
37#include <asm/system.h>
38#include <asm/io.h>
39#include <asm/pgtable.h>
40#include <asm/hwrpb.h>
41#include <asm/fpu.h>
42
43#include "proto.h"
44#include "pci_impl.h"
45
46void default_idle(void)
47{
48 barrier();
49}
50
51void
52cpu_idle(void)
53{
54 while (1) {
55 void (*idle)(void) = default_idle;
56 /* FIXME -- EV6 and LCA45 know how to power down
57 the CPU. */
58
59 while (!need_resched())
60 idle();
61 schedule();
62 }
63}
64
65
66struct halt_info {
67 int mode;
68 char *restart_cmd;
69};
70
71static void
72common_shutdown_1(void *generic_ptr)
73{
74 struct halt_info *how = (struct halt_info *)generic_ptr;
75 struct percpu_struct *cpup;
76 unsigned long *pflags, flags;
77 int cpuid = smp_processor_id();
78
79 /* No point in taking interrupts anymore. */
80 local_irq_disable();
81
82 cpup = (struct percpu_struct *)
83 ((unsigned long)hwrpb + hwrpb->processor_offset
84 + hwrpb->processor_size * cpuid);
85 pflags = &cpup->flags;
86 flags = *pflags;
87
88 /* Clear reason to "default"; clear "bootstrap in progress". */
89 flags &= ~0x00ff0001UL;
90
91#ifdef CONFIG_SMP
92 /* Secondaries halt here. */
93 if (cpuid != boot_cpuid) {
94 flags |= 0x00040000UL; /* "remain halted" */
95 *pflags = flags;
96 clear_bit(cpuid, &cpu_present_mask);
97 halt();
98 }
99#endif
100
101 if (how->mode == LINUX_REBOOT_CMD_RESTART) {
102 if (!how->restart_cmd) {
103 flags |= 0x00020000UL; /* "cold bootstrap" */
104 } else {
105 /* For SRM, we could probably set environment
106 variables to get this to work. We'd have to
107 delay this until after srm_paging_stop unless
108 we ever got srm_fixup working.
109
110 At the moment, SRM will use the last boot device,
111 but the file and flags will be the defaults, when
112 doing a "warm" bootstrap. */
113 flags |= 0x00030000UL; /* "warm bootstrap" */
114 }
115 } else {
116 flags |= 0x00040000UL; /* "remain halted" */
117 }
118 *pflags = flags;
119
120#ifdef CONFIG_SMP
121 /* Wait for the secondaries to halt. */
122 cpu_clear(boot_cpuid, cpu_possible_map);
123 while (cpus_weight(cpu_possible_map))
124 barrier();
125#endif
126
127 /* If booted from SRM, reset some of the original environment. */
128 if (alpha_using_srm) {
129#ifdef CONFIG_DUMMY_CONSOLE
130 /* This has the effect of resetting the VGA video origin. */
131 take_over_console(&dummy_con, 0, MAX_NR_CONSOLES-1, 1);
132#endif
133 pci_restore_srm_config();
134 set_hae(srm_hae);
135 }
136
137 if (alpha_mv.kill_arch)
138 alpha_mv.kill_arch(how->mode);
139
140 if (! alpha_using_srm && how->mode != LINUX_REBOOT_CMD_RESTART) {
141 /* Unfortunately, since MILO doesn't currently understand
142 the hwrpb bits above, we can't reliably halt the
143 processor and keep it halted. So just loop. */
144 return;
145 }
146
147 if (alpha_using_srm)
148 srm_paging_stop();
149
150 halt();
151}
152
153static void
154common_shutdown(int mode, char *restart_cmd)
155{
156 struct halt_info args;
157 args.mode = mode;
158 args.restart_cmd = restart_cmd;
159 on_each_cpu(common_shutdown_1, &args, 1, 0);
160}
161
162void
163machine_restart(char *restart_cmd)
164{
165 common_shutdown(LINUX_REBOOT_CMD_RESTART, restart_cmd);
166}
167
168EXPORT_SYMBOL(machine_restart);
169
170void
171machine_halt(void)
172{
173 common_shutdown(LINUX_REBOOT_CMD_HALT, NULL);
174}
175
176EXPORT_SYMBOL(machine_halt);
177
178void
179machine_power_off(void)
180{
181 common_shutdown(LINUX_REBOOT_CMD_POWER_OFF, NULL);
182}
183
184EXPORT_SYMBOL(machine_power_off);
185
186/* Used by sysrq-p, among others. I don't believe r9-r15 are ever
187 saved in the context it's used. */
188
189void
190show_regs(struct pt_regs *regs)
191{
192 dik_show_regs(regs, NULL);
193}
194
195/*
196 * Re-start a thread when doing execve()
197 */
198void
199start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
200{
201 set_fs(USER_DS);
202 regs->pc = pc;
203 regs->ps = 8;
204 wrusp(sp);
205}
206
207/*
208 * Free current thread data structures etc..
209 */
210void
211exit_thread(void)
212{
213}
214
215void
216flush_thread(void)
217{
218 /* Arrange for each exec'ed process to start off with a clean slate
219 with respect to the FPU. This is all exceptions disabled. */
220 current_thread_info()->ieee_state = 0;
221 wrfpcr(FPCR_DYN_NORMAL | ieee_swcr_to_fpcr(0));
222
223 /* Clean slate for TLS. */
224 current_thread_info()->pcb.unique = 0;
225}
226
227void
228release_thread(struct task_struct *dead_task)
229{
230}
231
232/*
233 * "alpha_clone()".. By the time we get here, the
234 * non-volatile registers have also been saved on the
235 * stack. We do some ugly pointer stuff here.. (see
236 * also copy_thread)
237 *
238 * Notice that "fork()" is implemented in terms of clone,
239 * with parameters (SIGCHLD, 0).
240 */
241int
242alpha_clone(unsigned long clone_flags, unsigned long usp,
243 int __user *parent_tid, int __user *child_tid,
244 unsigned long tls_value, struct pt_regs *regs)
245{
246 if (!usp)
247 usp = rdusp();
248
249 return do_fork(clone_flags, usp, regs, 0, parent_tid, child_tid);
250}
251
252int
253alpha_vfork(struct pt_regs *regs)
254{
255 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(),
256 regs, 0, NULL, NULL);
257}
258
259/*
260 * Copy an alpha thread..
261 *
262 * Note the "stack_offset" stuff: when returning to kernel mode, we need
263 * to have some extra stack-space for the kernel stack that still exists
264 * after the "ret_from_fork". When returning to user mode, we only want
265 * the space needed by the syscall stack frame (ie "struct pt_regs").
266 * Use the passed "regs" pointer to determine how much space we need
267 * for a kernel fork().
268 */
269
270int
271copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
272 unsigned long unused,
273 struct task_struct * p, struct pt_regs * regs)
274{
275 extern void ret_from_fork(void);
276
277 struct thread_info *childti = p->thread_info;
278 struct pt_regs * childregs;
279 struct switch_stack * childstack, *stack;
280 unsigned long stack_offset, settls;
281
282 stack_offset = PAGE_SIZE - sizeof(struct pt_regs);
283 if (!(regs->ps & 8))
284 stack_offset = (PAGE_SIZE-1) & (unsigned long) regs;
285 childregs = (struct pt_regs *)
286 (stack_offset + PAGE_SIZE + (long) childti);
287
288 *childregs = *regs;
289 settls = regs->r20;
290 childregs->r0 = 0;
291 childregs->r19 = 0;
292 childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */
293 regs->r20 = 0;
294 stack = ((struct switch_stack *) regs) - 1;
295 childstack = ((struct switch_stack *) childregs) - 1;
296 *childstack = *stack;
297 childstack->r26 = (unsigned long) ret_from_fork;
298 childti->pcb.usp = usp;
299 childti->pcb.ksp = (unsigned long) childstack;
300 childti->pcb.flags = 1; /* set FEN, clear everything else */
301
302 /* Set a new TLS for the child thread? Peek back into the
303 syscall arguments that we saved on syscall entry. Oops,
304 except we'd have clobbered it with the parent/child set
305 of r20. Read the saved copy. */
306 /* Note: if CLONE_SETTLS is not set, then we must inherit the
307 value from the parent, which will have been set by the block
308 copy in dup_task_struct. This is non-intuitive, but is
309 required for proper operation in the case of a threaded
310 application calling fork. */
311 if (clone_flags & CLONE_SETTLS)
312 childti->pcb.unique = settls;
313
314 return 0;
315}
316
317/*
318 * Fill in the user structure for an ECOFF core dump.
319 */
320void
321dump_thread(struct pt_regs * pt, struct user * dump)
322{
323 /* switch stack follows right below pt_regs: */
324 struct switch_stack * sw = ((struct switch_stack *) pt) - 1;
325
326 dump->magic = CMAGIC;
327 dump->start_code = current->mm->start_code;
328 dump->start_data = current->mm->start_data;
329 dump->start_stack = rdusp() & ~(PAGE_SIZE - 1);
330 dump->u_tsize = ((current->mm->end_code - dump->start_code)
331 >> PAGE_SHIFT);
332 dump->u_dsize = ((current->mm->brk + PAGE_SIZE-1 - dump->start_data)
333 >> PAGE_SHIFT);
334 dump->u_ssize = (current->mm->start_stack - dump->start_stack
335 + PAGE_SIZE-1) >> PAGE_SHIFT;
336
337 /*
338 * We store the registers in an order/format that is
339 * compatible with DEC Unix/OSF/1 as this makes life easier
340 * for gdb.
341 */
342 dump->regs[EF_V0] = pt->r0;
343 dump->regs[EF_T0] = pt->r1;
344 dump->regs[EF_T1] = pt->r2;
345 dump->regs[EF_T2] = pt->r3;
346 dump->regs[EF_T3] = pt->r4;
347 dump->regs[EF_T4] = pt->r5;
348 dump->regs[EF_T5] = pt->r6;
349 dump->regs[EF_T6] = pt->r7;
350 dump->regs[EF_T7] = pt->r8;
351 dump->regs[EF_S0] = sw->r9;
352 dump->regs[EF_S1] = sw->r10;
353 dump->regs[EF_S2] = sw->r11;
354 dump->regs[EF_S3] = sw->r12;
355 dump->regs[EF_S4] = sw->r13;
356 dump->regs[EF_S5] = sw->r14;
357 dump->regs[EF_S6] = sw->r15;
358 dump->regs[EF_A3] = pt->r19;
359 dump->regs[EF_A4] = pt->r20;
360 dump->regs[EF_A5] = pt->r21;
361 dump->regs[EF_T8] = pt->r22;
362 dump->regs[EF_T9] = pt->r23;
363 dump->regs[EF_T10] = pt->r24;
364 dump->regs[EF_T11] = pt->r25;
365 dump->regs[EF_RA] = pt->r26;
366 dump->regs[EF_T12] = pt->r27;
367 dump->regs[EF_AT] = pt->r28;
368 dump->regs[EF_SP] = rdusp();
369 dump->regs[EF_PS] = pt->ps;
370 dump->regs[EF_PC] = pt->pc;
371 dump->regs[EF_GP] = pt->gp;
372 dump->regs[EF_A0] = pt->r16;
373 dump->regs[EF_A1] = pt->r17;
374 dump->regs[EF_A2] = pt->r18;
375 memcpy((char *)dump->regs + EF_SIZE, sw->fp, 32 * 8);
376}
377
378/*
379 * Fill in the user structure for a ELF core dump.
380 */
381void
382dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt, struct thread_info *ti)
383{
384 /* switch stack follows right below pt_regs: */
385 struct switch_stack * sw = ((struct switch_stack *) pt) - 1;
386
387 dest[ 0] = pt->r0;
388 dest[ 1] = pt->r1;
389 dest[ 2] = pt->r2;
390 dest[ 3] = pt->r3;
391 dest[ 4] = pt->r4;
392 dest[ 5] = pt->r5;
393 dest[ 6] = pt->r6;
394 dest[ 7] = pt->r7;
395 dest[ 8] = pt->r8;
396 dest[ 9] = sw->r9;
397 dest[10] = sw->r10;
398 dest[11] = sw->r11;
399 dest[12] = sw->r12;
400 dest[13] = sw->r13;
401 dest[14] = sw->r14;
402 dest[15] = sw->r15;
403 dest[16] = pt->r16;
404 dest[17] = pt->r17;
405 dest[18] = pt->r18;
406 dest[19] = pt->r19;
407 dest[20] = pt->r20;
408 dest[21] = pt->r21;
409 dest[22] = pt->r22;
410 dest[23] = pt->r23;
411 dest[24] = pt->r24;
412 dest[25] = pt->r25;
413 dest[26] = pt->r26;
414 dest[27] = pt->r27;
415 dest[28] = pt->r28;
416 dest[29] = pt->gp;
417 dest[30] = rdusp();
418 dest[31] = pt->pc;
419
420 /* Once upon a time this was the PS value. Which is stupid
421 since that is always 8 for usermode. Usurped for the more
422 useful value of the thread's UNIQUE field. */
423 dest[32] = ti->pcb.unique;
424}
425
426int
427dump_elf_task(elf_greg_t *dest, struct task_struct *task)
428{
429 struct thread_info *ti;
430 struct pt_regs *pt;
431
432 ti = task->thread_info;
433 pt = (struct pt_regs *)((unsigned long)ti + 2*PAGE_SIZE) - 1;
434
435 dump_elf_thread(dest, pt, ti);
436
437 return 1;
438}
439
440int
441dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task)
442{
443 struct thread_info *ti;
444 struct pt_regs *pt;
445 struct switch_stack *sw;
446
447 ti = task->thread_info;
448 pt = (struct pt_regs *)((unsigned long)ti + 2*PAGE_SIZE) - 1;
449 sw = (struct switch_stack *)pt - 1;
450
451 memcpy(dest, sw->fp, 32 * 8);
452
453 return 1;
454}
455
456/*
457 * sys_execve() executes a new program.
458 */
459asmlinkage int
460do_sys_execve(char __user *ufilename, char __user * __user *argv,
461 char __user * __user *envp, struct pt_regs *regs)
462{
463 int error;
464 char *filename;
465
466 filename = getname(ufilename);
467 error = PTR_ERR(filename);
468 if (IS_ERR(filename))
469 goto out;
470 error = do_execve(filename, argv, envp, regs);
471 putname(filename);
472out:
473 return error;
474}
475
476/*
477 * Return saved PC of a blocked thread. This assumes the frame
478 * pointer is the 6th saved long on the kernel stack and that the
479 * saved return address is the first long in the frame. This all
480 * holds provided the thread blocked through a call to schedule() ($15
481 * is the frame pointer in schedule() and $15 is saved at offset 48 by
482 * entry.S:do_switch_stack).
483 *
484 * Under heavy swap load I've seen this lose in an ugly way. So do
485 * some extra sanity checking on the ranges we expect these pointers
486 * to be in so that we can fail gracefully. This is just for ps after
487 * all. -- r~
488 */
489
490unsigned long
491thread_saved_pc(task_t *t)
492{
493 unsigned long base = (unsigned long)t->thread_info;
494 unsigned long fp, sp = t->thread_info->pcb.ksp;
495
496 if (sp > base && sp+6*8 < base + 16*1024) {
497 fp = ((unsigned long*)sp)[6];
498 if (fp > sp && fp < base + 16*1024)
499 return *(unsigned long *)fp;
500 }
501
502 return 0;
503}
504
505unsigned long
506get_wchan(struct task_struct *p)
507{
508 unsigned long schedule_frame;
509 unsigned long pc;
510 if (!p || p == current || p->state == TASK_RUNNING)
511 return 0;
512 /*
513 * This one depends on the frame size of schedule(). Do a
514 * "disass schedule" in gdb to find the frame size. Also, the
515 * code assumes that sleep_on() follows immediately after
516 * interruptible_sleep_on() and that add_timer() follows
517 * immediately after interruptible_sleep(). Ugly, isn't it?
518 * Maybe adding a wchan field to task_struct would be better,
519 * after all...
520 */
521
522 pc = thread_saved_pc(p);
523 if (in_sched_functions(pc)) {
524 schedule_frame = ((unsigned long *)p->thread_info->pcb.ksp)[6];
525 return ((unsigned long *)schedule_frame)[12];
526 }
527 return pc;
528}
diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h
new file mode 100644
index 000000000000..e1560fb15610
--- /dev/null
+++ b/arch/alpha/kernel/proto.h
@@ -0,0 +1,210 @@
1#include <linux/config.h>
2#include <linux/interrupt.h>
3
4
5/* Prototypes of functions used across modules here in this directory. */
6
7#define vucp volatile unsigned char *
8#define vusp volatile unsigned short *
9#define vip volatile int *
10#define vuip volatile unsigned int *
11#define vulp volatile unsigned long *
12
13struct pt_regs;
14struct task_struct;
15struct pci_dev;
16struct pci_controller;
17
18/* core_apecs.c */
19extern struct pci_ops apecs_pci_ops;
20extern void apecs_init_arch(void);
21extern void apecs_pci_clr_err(void);
22extern void apecs_machine_check(u64, u64, struct pt_regs *);
23extern void apecs_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
24
25/* core_cia.c */
26extern struct pci_ops cia_pci_ops;
27extern void cia_init_pci(void);
28extern void cia_init_arch(void);
29extern void pyxis_init_arch(void);
30extern void cia_kill_arch(int);
31extern void cia_machine_check(u64, u64, struct pt_regs *);
32extern void cia_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
33
34/* core_irongate.c */
35extern struct pci_ops irongate_pci_ops;
36extern int irongate_pci_clr_err(void);
37extern void irongate_init_arch(void);
38extern void irongate_machine_check(u64, u64, struct pt_regs *);
39#define irongate_pci_tbi ((void *)0)
40
41/* core_lca.c */
42extern struct pci_ops lca_pci_ops;
43extern void lca_init_arch(void);
44extern void lca_machine_check(u64, u64, struct pt_regs *);
45extern void lca_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
46
47/* core_marvel.c */
48extern struct pci_ops marvel_pci_ops;
49extern void marvel_init_arch(void);
50extern void marvel_kill_arch(int);
51extern void marvel_machine_check(u64, u64, struct pt_regs *);
52extern void marvel_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
53extern int marvel_pa_to_nid(unsigned long);
54extern int marvel_cpuid_to_nid(int);
55extern unsigned long marvel_node_mem_start(int);
56extern unsigned long marvel_node_mem_size(int);
57extern struct _alpha_agp_info *marvel_agp_info(void);
58struct io7 *marvel_find_io7(int pe);
59struct io7 *marvel_next_io7(struct io7 *prev);
60void io7_clear_errors(struct io7 *io7);
61
62/* core_mcpcia.c */
63extern struct pci_ops mcpcia_pci_ops;
64extern void mcpcia_init_arch(void);
65extern void mcpcia_init_hoses(void);
66extern void mcpcia_machine_check(u64, u64, struct pt_regs *);
67extern void mcpcia_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
68
69/* core_polaris.c */
70extern struct pci_ops polaris_pci_ops;
71extern int polaris_read_config_dword(struct pci_dev *, int, u32 *);
72extern int polaris_write_config_dword(struct pci_dev *, int, u32);
73extern void polaris_init_arch(void);
74extern void polaris_machine_check(u64, u64, struct pt_regs *);
75#define polaris_pci_tbi ((void *)0)
76
77/* core_t2.c */
78extern struct pci_ops t2_pci_ops;
79extern void t2_init_arch(void);
80extern void t2_kill_arch(int);
81extern void t2_machine_check(u64, u64, struct pt_regs *);
82extern void t2_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
83
84/* core_titan.c */
85extern struct pci_ops titan_pci_ops;
86extern void titan_init_arch(void);
87extern void titan_kill_arch(int);
88extern void titan_machine_check(u64, u64, struct pt_regs *);
89extern void titan_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
90extern struct _alpha_agp_info *titan_agp_info(void);
91
92/* core_tsunami.c */
93extern struct pci_ops tsunami_pci_ops;
94extern void tsunami_init_arch(void);
95extern void tsunami_kill_arch(int);
96extern void tsunami_machine_check(u64, u64, struct pt_regs *);
97extern void tsunami_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
98
99/* core_wildfire.c */
100extern struct pci_ops wildfire_pci_ops;
101extern void wildfire_init_arch(void);
102extern void wildfire_kill_arch(int);
103extern void wildfire_machine_check(u64, u64, struct pt_regs *);
104extern void wildfire_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
105extern int wildfire_pa_to_nid(unsigned long);
106extern int wildfire_cpuid_to_nid(int);
107extern unsigned long wildfire_node_mem_start(int);
108extern unsigned long wildfire_node_mem_size(int);
109
110/* setup.c */
111extern unsigned long srm_hae;
112extern int boot_cpuid;
113#ifdef CONFIG_VERBOSE_MCHECK
114extern unsigned long alpha_verbose_mcheck;
115#endif
116
117/* srmcons.c */
118#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM)
119extern void register_srm_console(void);
120extern void unregister_srm_console(void);
121#else
122#define register_srm_console()
123#define unregister_srm_console()
124#endif
125
126/* smp.c */
127extern void setup_smp(void);
128extern void handle_ipi(struct pt_regs *);
129extern void smp_percpu_timer_interrupt(struct pt_regs *);
130
131/* bios32.c */
132/* extern void reset_for_srm(void); */
133
134/* time.c */
135extern irqreturn_t timer_interrupt(int irq, void *dev, struct pt_regs * regs);
136extern void common_init_rtc(void);
137extern unsigned long est_cycle_freq;
138
139/* smc37c93x.c */
140extern void SMC93x_Init(void);
141
142/* smc37c669.c */
143extern void SMC669_Init(int);
144
145/* es1888.c */
146extern void es1888_init(void);
147
148/* ns87312.c */
149extern void ns87312_enable_ide(long ide_base);
150
151/* ../lib/fpreg.c */
152extern void alpha_write_fp_reg (unsigned long reg, unsigned long val);
153extern unsigned long alpha_read_fp_reg (unsigned long reg);
154
155/* head.S */
156extern void wrmces(unsigned long mces);
157extern void cserve_ena(unsigned long);
158extern void cserve_dis(unsigned long);
159extern void __smp_callin(unsigned long);
160
161/* entry.S */
162extern void entArith(void);
163extern void entIF(void);
164extern void entInt(void);
165extern void entMM(void);
166extern void entSys(void);
167extern void entUna(void);
168extern void entDbg(void);
169
170/* ptrace.c */
171extern int ptrace_set_bpt (struct task_struct *child);
172extern int ptrace_cancel_bpt (struct task_struct *child);
173
174/* traps.c */
175extern void dik_show_regs(struct pt_regs *regs, unsigned long *r9_15);
176extern void die_if_kernel(char *, struct pt_regs *, long, unsigned long *);
177
178/* sys_titan.c */
179extern void titan_dispatch_irqs(u64, struct pt_regs *);
180
181/* ../mm/init.c */
182extern void switch_to_system_map(void);
183extern void srm_paging_stop(void);
184
185/* ../mm/remap.c */
186extern int __alpha_remap_area_pages(unsigned long, unsigned long,
187 unsigned long, unsigned long);
188
189/* irq.c */
190
191#ifdef CONFIG_SMP
192#define mcheck_expected(cpu) (cpu_data[cpu].mcheck_expected)
193#define mcheck_taken(cpu) (cpu_data[cpu].mcheck_taken)
194#define mcheck_extra(cpu) (cpu_data[cpu].mcheck_extra)
195#else
196extern struct mcheck_info
197{
198 unsigned char expected __attribute__((aligned(8)));
199 unsigned char taken;
200 unsigned char extra;
201} __mcheck_info;
202
203#define mcheck_expected(cpu) (*((void)(cpu), &__mcheck_info.expected))
204#define mcheck_taken(cpu) (*((void)(cpu), &__mcheck_info.taken))
205#define mcheck_extra(cpu) (*((void)(cpu), &__mcheck_info.extra))
206#endif
207
208extern void process_mcheck_info(unsigned long vector, unsigned long la_ptr,
209 struct pt_regs *regs, const char *machine,
210 int expected);
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
new file mode 100644
index 000000000000..d00583161574
--- /dev/null
+++ b/arch/alpha/kernel/ptrace.c
@@ -0,0 +1,415 @@
1/* ptrace.c */
2/* By Ross Biro 1/23/92 */
3/* edited by Linus Torvalds */
4/* mangled further by Bob Manson (manson@santafe.edu) */
5/* more mutilation by David Mosberger (davidm@azstarnet.com) */
6
7#include <linux/kernel.h>
8#include <linux/sched.h>
9#include <linux/mm.h>
10#include <linux/smp.h>
11#include <linux/smp_lock.h>
12#include <linux/errno.h>
13#include <linux/ptrace.h>
14#include <linux/user.h>
15#include <linux/slab.h>
16#include <linux/security.h>
17
18#include <asm/uaccess.h>
19#include <asm/pgtable.h>
20#include <asm/system.h>
21#include <asm/fpu.h>
22
23#include "proto.h"
24
25#define DEBUG DBG_MEM
26#undef DEBUG
27
28#ifdef DEBUG
29enum {
30 DBG_MEM = (1<<0),
31 DBG_BPT = (1<<1),
32 DBG_MEM_ALL = (1<<2)
33};
34#define DBG(fac,args) {if ((fac) & DEBUG) printk args;}
35#else
36#define DBG(fac,args)
37#endif
38
39#define BREAKINST 0x00000080 /* call_pal bpt */
40
41/*
42 * does not yet catch signals sent when the child dies.
43 * in exit.c or in signal.c.
44 */
45
46/*
47 * Processes always block with the following stack-layout:
48 *
49 * +================================+ <---- task + 2*PAGE_SIZE
50 * | PALcode saved frame (ps, pc, | ^
51 * | gp, a0, a1, a2) | |
52 * +================================+ | struct pt_regs
53 * | | |
54 * | frame generated by SAVE_ALL | |
55 * | | v
56 * +================================+
57 * | | ^
58 * | frame saved by do_switch_stack | | struct switch_stack
59 * | | v
60 * +================================+
61 */
62
63/*
64 * The following table maps a register index into the stack offset at
65 * which the register is saved. Register indices are 0-31 for integer
66 * regs, 32-63 for fp regs, and 64 for the pc. Notice that sp and
67 * zero have no stack-slot and need to be treated specially (see
68 * get_reg/put_reg below).
69 */
70enum {
71 REG_R0 = 0, REG_F0 = 32, REG_FPCR = 63, REG_PC = 64
72};
73
74static int regoff[] = {
75 PT_REG( r0), PT_REG( r1), PT_REG( r2), PT_REG( r3),
76 PT_REG( r4), PT_REG( r5), PT_REG( r6), PT_REG( r7),
77 PT_REG( r8), SW_REG( r9), SW_REG( r10), SW_REG( r11),
78 SW_REG( r12), SW_REG( r13), SW_REG( r14), SW_REG( r15),
79 PT_REG( r16), PT_REG( r17), PT_REG( r18), PT_REG( r19),
80 PT_REG( r20), PT_REG( r21), PT_REG( r22), PT_REG( r23),
81 PT_REG( r24), PT_REG( r25), PT_REG( r26), PT_REG( r27),
82 PT_REG( r28), PT_REG( gp), -1, -1,
83 SW_REG(fp[ 0]), SW_REG(fp[ 1]), SW_REG(fp[ 2]), SW_REG(fp[ 3]),
84 SW_REG(fp[ 4]), SW_REG(fp[ 5]), SW_REG(fp[ 6]), SW_REG(fp[ 7]),
85 SW_REG(fp[ 8]), SW_REG(fp[ 9]), SW_REG(fp[10]), SW_REG(fp[11]),
86 SW_REG(fp[12]), SW_REG(fp[13]), SW_REG(fp[14]), SW_REG(fp[15]),
87 SW_REG(fp[16]), SW_REG(fp[17]), SW_REG(fp[18]), SW_REG(fp[19]),
88 SW_REG(fp[20]), SW_REG(fp[21]), SW_REG(fp[22]), SW_REG(fp[23]),
89 SW_REG(fp[24]), SW_REG(fp[25]), SW_REG(fp[26]), SW_REG(fp[27]),
90 SW_REG(fp[28]), SW_REG(fp[29]), SW_REG(fp[30]), SW_REG(fp[31]),
91 PT_REG( pc)
92};
93
94static unsigned long zero;
95
96/*
97 * Get address of register REGNO in task TASK.
98 */
99static unsigned long *
100get_reg_addr(struct task_struct * task, unsigned long regno)
101{
102 unsigned long *addr;
103
104 if (regno == 30) {
105 addr = &task->thread_info->pcb.usp;
106 } else if (regno == 65) {
107 addr = &task->thread_info->pcb.unique;
108 } else if (regno == 31 || regno > 65) {
109 zero = 0;
110 addr = &zero;
111 } else {
112 addr = (void *)task->thread_info + regoff[regno];
113 }
114 return addr;
115}
116
117/*
118 * Get contents of register REGNO in task TASK.
119 */
120static unsigned long
121get_reg(struct task_struct * task, unsigned long regno)
122{
123 /* Special hack for fpcr -- combine hardware and software bits. */
124 if (regno == 63) {
125 unsigned long fpcr = *get_reg_addr(task, regno);
126 unsigned long swcr
127 = task->thread_info->ieee_state & IEEE_SW_MASK;
128 swcr = swcr_update_status(swcr, fpcr);
129 return fpcr | swcr;
130 }
131 return *get_reg_addr(task, regno);
132}
133
134/*
135 * Write contents of register REGNO in task TASK.
136 */
137static int
138put_reg(struct task_struct *task, unsigned long regno, unsigned long data)
139{
140 if (regno == 63) {
141 task->thread_info->ieee_state
142 = ((task->thread_info->ieee_state & ~IEEE_SW_MASK)
143 | (data & IEEE_SW_MASK));
144 data = (data & FPCR_DYN_MASK) | ieee_swcr_to_fpcr(data);
145 }
146 *get_reg_addr(task, regno) = data;
147 return 0;
148}
149
150static inline int
151read_int(struct task_struct *task, unsigned long addr, int * data)
152{
153 int copied = access_process_vm(task, addr, data, sizeof(int), 0);
154 return (copied == sizeof(int)) ? 0 : -EIO;
155}
156
157static inline int
158write_int(struct task_struct *task, unsigned long addr, int data)
159{
160 int copied = access_process_vm(task, addr, &data, sizeof(int), 1);
161 return (copied == sizeof(int)) ? 0 : -EIO;
162}
163
164/*
165 * Set breakpoint.
166 */
167int
168ptrace_set_bpt(struct task_struct * child)
169{
170 int displ, i, res, reg_b, nsaved = 0;
171 unsigned int insn, op_code;
172 unsigned long pc;
173
174 pc = get_reg(child, REG_PC);
175 res = read_int(child, pc, (int *) &insn);
176 if (res < 0)
177 return res;
178
179 op_code = insn >> 26;
180 if (op_code >= 0x30) {
181 /*
182 * It's a branch: instead of trying to figure out
183 * whether the branch will be taken or not, we'll put
184 * a breakpoint at either location. This is simpler,
185 * more reliable, and probably not a whole lot slower
186 * than the alternative approach of emulating the
187 * branch (emulation can be tricky for fp branches).
188 */
189 displ = ((s32)(insn << 11)) >> 9;
190 child->thread_info->bpt_addr[nsaved++] = pc + 4;
191 if (displ) /* guard against unoptimized code */
192 child->thread_info->bpt_addr[nsaved++]
193 = pc + 4 + displ;
194 DBG(DBG_BPT, ("execing branch\n"));
195 } else if (op_code == 0x1a) {
196 reg_b = (insn >> 16) & 0x1f;
197 child->thread_info->bpt_addr[nsaved++] = get_reg(child, reg_b);
198 DBG(DBG_BPT, ("execing jump\n"));
199 } else {
200 child->thread_info->bpt_addr[nsaved++] = pc + 4;
201 DBG(DBG_BPT, ("execing normal insn\n"));
202 }
203
204 /* install breakpoints: */
205 for (i = 0; i < nsaved; ++i) {
206 res = read_int(child, child->thread_info->bpt_addr[i],
207 (int *) &insn);
208 if (res < 0)
209 return res;
210 child->thread_info->bpt_insn[i] = insn;
211 DBG(DBG_BPT, (" -> next_pc=%lx\n",
212 child->thread_info->bpt_addr[i]));
213 res = write_int(child, child->thread_info->bpt_addr[i],
214 BREAKINST);
215 if (res < 0)
216 return res;
217 }
218 child->thread_info->bpt_nsaved = nsaved;
219 return 0;
220}
221
222/*
223 * Ensure no single-step breakpoint is pending. Returns non-zero
224 * value if child was being single-stepped.
225 */
226int
227ptrace_cancel_bpt(struct task_struct * child)
228{
229 int i, nsaved = child->thread_info->bpt_nsaved;
230
231 child->thread_info->bpt_nsaved = 0;
232
233 if (nsaved > 2) {
234 printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
235 nsaved = 2;
236 }
237
238 for (i = 0; i < nsaved; ++i) {
239 write_int(child, child->thread_info->bpt_addr[i],
240 child->thread_info->bpt_insn[i]);
241 }
242 return (nsaved != 0);
243}
244
245/*
246 * Called by kernel/ptrace.c when detaching..
247 *
248 * Make sure the single step bit is not set.
249 */
250void ptrace_disable(struct task_struct *child)
251{
252 ptrace_cancel_bpt(child);
253}
254
255asmlinkage long
256do_sys_ptrace(long request, long pid, long addr, long data,
257 struct pt_regs *regs)
258{
259 struct task_struct *child;
260 unsigned long tmp;
261 size_t copied;
262 long ret;
263
264 lock_kernel();
265 DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n",
266 request, pid, addr, data));
267 ret = -EPERM;
268 if (request == PTRACE_TRACEME) {
269 /* are we already being traced? */
270 if (current->ptrace & PT_PTRACED)
271 goto out_notsk;
272 ret = security_ptrace(current->parent, current);
273 if (ret)
274 goto out_notsk;
275 /* set the ptrace bit in the process ptrace flags. */
276 current->ptrace |= PT_PTRACED;
277 ret = 0;
278 goto out_notsk;
279 }
280 if (pid == 1) /* you may not mess with init */
281 goto out_notsk;
282
283 ret = -ESRCH;
284 read_lock(&tasklist_lock);
285 child = find_task_by_pid(pid);
286 if (child)
287 get_task_struct(child);
288 read_unlock(&tasklist_lock);
289 if (!child)
290 goto out_notsk;
291
292 if (request == PTRACE_ATTACH) {
293 ret = ptrace_attach(child);
294 goto out;
295 }
296
297 ret = ptrace_check_attach(child, request == PTRACE_KILL);
298 if (ret < 0)
299 goto out;
300
301 switch (request) {
302 /* When I and D space are separate, these will need to be fixed. */
303 case PTRACE_PEEKTEXT: /* read word at location addr. */
304 case PTRACE_PEEKDATA:
305 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
306 ret = -EIO;
307 if (copied != sizeof(tmp))
308 break;
309
310 regs->r0 = 0; /* special return: no errors */
311 ret = tmp;
312 break;
313
314 /* Read register number ADDR. */
315 case PTRACE_PEEKUSR:
316 regs->r0 = 0; /* special return: no errors */
317 ret = get_reg(child, addr);
318 DBG(DBG_MEM, ("peek $%ld->%#lx\n", addr, ret));
319 break;
320
321 /* When I and D space are separate, this will have to be fixed. */
322 case PTRACE_POKETEXT: /* write the word at location addr. */
323 case PTRACE_POKEDATA:
324 tmp = data;
325 copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 1);
326 ret = (copied == sizeof(tmp)) ? 0 : -EIO;
327 break;
328
329 case PTRACE_POKEUSR: /* write the specified register */
330 DBG(DBG_MEM, ("poke $%ld<-%#lx\n", addr, data));
331 ret = put_reg(child, addr, data);
332 break;
333
334 case PTRACE_SYSCALL:
335 /* continue and stop at next (return from) syscall */
336 case PTRACE_CONT: /* restart after signal. */
337 ret = -EIO;
338 if ((unsigned long) data > _NSIG)
339 break;
340 if (request == PTRACE_SYSCALL)
341 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
342 else
343 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
344 child->exit_code = data;
345 /* make sure single-step breakpoint is gone. */
346 ptrace_cancel_bpt(child);
347 wake_up_process(child);
348 ret = 0;
349 break;
350
351 /*
352 * Make the child exit. Best I can do is send it a sigkill.
353 * perhaps it should be put in the status that it wants to
354 * exit.
355 */
356 case PTRACE_KILL:
357 ret = 0;
358 if (child->exit_state == EXIT_ZOMBIE)
359 break;
360 child->exit_code = SIGKILL;
361 /* make sure single-step breakpoint is gone. */
362 ptrace_cancel_bpt(child);
363 wake_up_process(child);
364 goto out;
365
366 case PTRACE_SINGLESTEP: /* execute single instruction. */
367 ret = -EIO;
368 if ((unsigned long) data > _NSIG)
369 break;
370 /* Mark single stepping. */
371 child->thread_info->bpt_nsaved = -1;
372 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
373 child->exit_code = data;
374 wake_up_process(child);
375 /* give it a chance to run. */
376 ret = 0;
377 goto out;
378
379 case PTRACE_DETACH: /* detach a process that was attached. */
380 ret = ptrace_detach(child, data);
381 goto out;
382
383 default:
384 ret = ptrace_request(child, request, addr, data);
385 goto out;
386 }
387 out:
388 put_task_struct(child);
389 out_notsk:
390 unlock_kernel();
391 return ret;
392}
393
394asmlinkage void
395syscall_trace(void)
396{
397 if (!test_thread_flag(TIF_SYSCALL_TRACE))
398 return;
399 if (!(current->ptrace & PT_PTRACED))
400 return;
401 /* The 0x80 provides a way for the tracing parent to distinguish
402 between a syscall stop and SIGTRAP delivery */
403 ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
404 ? 0x80 : 0));
405
406 /*
407 * This isn't the same as continuing with a signal, but it will do
408 * for normal use. strace only continues with a signal if the
409 * stopping signal is not SIGTRAP. -brl
410 */
411 if (current->exit_code) {
412 send_sig(current->exit_code, current, 1);
413 current->exit_code = 0;
414 }
415}
diff --git a/arch/alpha/kernel/semaphore.c b/arch/alpha/kernel/semaphore.c
new file mode 100644
index 000000000000..8c8aaa205eae
--- /dev/null
+++ b/arch/alpha/kernel/semaphore.c
@@ -0,0 +1,224 @@
1/*
2 * Alpha semaphore implementation.
3 *
4 * (C) Copyright 1996 Linus Torvalds
5 * (C) Copyright 1999, 2000 Richard Henderson
6 */
7
8#include <linux/errno.h>
9#include <linux/sched.h>
10#include <linux/init.h>
11
12/*
13 * This is basically the PPC semaphore scheme ported to use
14 * the Alpha ll/sc sequences, so see the PPC code for
15 * credits.
16 */
17
18/*
19 * Atomically update sem->count.
20 * This does the equivalent of the following:
21 *
22 * old_count = sem->count;
23 * tmp = MAX(old_count, 0) + incr;
24 * sem->count = tmp;
25 * return old_count;
26 */
27static inline int __sem_update_count(struct semaphore *sem, int incr)
28{
29 long old_count, tmp = 0;
30
31 __asm__ __volatile__(
32 "1: ldl_l %0,%2\n"
33 " cmovgt %0,%0,%1\n"
34 " addl %1,%3,%1\n"
35 " stl_c %1,%2\n"
36 " beq %1,2f\n"
37 " mb\n"
38 ".subsection 2\n"
39 "2: br 1b\n"
40 ".previous"
41 : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
42 : "Ir" (incr), "1" (tmp), "m" (sem->count));
43
44 return old_count;
45}
46
47/*
48 * Perform the "down" function. Return zero for semaphore acquired,
49 * return negative for signalled out of the function.
50 *
51 * If called from down, the return is ignored and the wait loop is
52 * not interruptible. This means that a task waiting on a semaphore
53 * using "down()" cannot be killed until someone does an "up()" on
54 * the semaphore.
55 *
56 * If called from down_interruptible, the return value gets checked
57 * upon return. If the return value is negative then the task continues
58 * with the negative value in the return register (it can be tested by
59 * the caller).
60 *
61 * Either form may be used in conjunction with "up()".
62 */
63
64void __sched
65__down_failed(struct semaphore *sem)
66{
67 struct task_struct *tsk = current;
68 DECLARE_WAITQUEUE(wait, tsk);
69
70#ifdef CONFIG_DEBUG_SEMAPHORE
71 printk("%s(%d): down failed(%p)\n",
72 tsk->comm, tsk->pid, sem);
73#endif
74
75 tsk->state = TASK_UNINTERRUPTIBLE;
76 wmb();
77 add_wait_queue_exclusive(&sem->wait, &wait);
78
79 /*
80 * Try to get the semaphore. If the count is > 0, then we've
81 * got the semaphore; we decrement count and exit the loop.
82 * If the count is 0 or negative, we set it to -1, indicating
83 * that we are asleep, and then sleep.
84 */
85 while (__sem_update_count(sem, -1) <= 0) {
86 schedule();
87 set_task_state(tsk, TASK_UNINTERRUPTIBLE);
88 }
89 remove_wait_queue(&sem->wait, &wait);
90 tsk->state = TASK_RUNNING;
91
92 /*
93 * If there are any more sleepers, wake one of them up so
94 * that it can either get the semaphore, or set count to -1
95 * indicating that there are still processes sleeping.
96 */
97 wake_up(&sem->wait);
98
99#ifdef CONFIG_DEBUG_SEMAPHORE
100 printk("%s(%d): down acquired(%p)\n",
101 tsk->comm, tsk->pid, sem);
102#endif
103}
104
105int __sched
106__down_failed_interruptible(struct semaphore *sem)
107{
108 struct task_struct *tsk = current;
109 DECLARE_WAITQUEUE(wait, tsk);
110 long ret = 0;
111
112#ifdef CONFIG_DEBUG_SEMAPHORE
113 printk("%s(%d): down failed(%p)\n",
114 tsk->comm, tsk->pid, sem);
115#endif
116
117 tsk->state = TASK_INTERRUPTIBLE;
118 wmb();
119 add_wait_queue_exclusive(&sem->wait, &wait);
120
121 while (__sem_update_count(sem, -1) <= 0) {
122 if (signal_pending(current)) {
123 /*
124 * A signal is pending - give up trying.
125 * Set sem->count to 0 if it is negative,
126 * since we are no longer sleeping.
127 */
128 __sem_update_count(sem, 0);
129 ret = -EINTR;
130 break;
131 }
132 schedule();
133 set_task_state(tsk, TASK_INTERRUPTIBLE);
134 }
135
136 remove_wait_queue(&sem->wait, &wait);
137 tsk->state = TASK_RUNNING;
138 wake_up(&sem->wait);
139
140#ifdef CONFIG_DEBUG_SEMAPHORE
141 printk("%s(%d): down %s(%p)\n",
142 current->comm, current->pid,
143 (ret < 0 ? "interrupted" : "acquired"), sem);
144#endif
145 return ret;
146}
147
148void
149__up_wakeup(struct semaphore *sem)
150{
151 /*
152 * Note that we incremented count in up() before we came here,
153 * but that was ineffective since the result was <= 0, and
154 * any negative value of count is equivalent to 0.
155 * This ends up setting count to 1, unless count is now > 0
156 * (i.e. because some other cpu has called up() in the meantime),
157 * in which case we just increment count.
158 */
159 __sem_update_count(sem, 1);
160 wake_up(&sem->wait);
161}
162
163void __sched
164down(struct semaphore *sem)
165{
166#ifdef WAITQUEUE_DEBUG
167 CHECK_MAGIC(sem->__magic);
168#endif
169#ifdef CONFIG_DEBUG_SEMAPHORE
170 printk("%s(%d): down(%p) <count=%d> from %p\n",
171 current->comm, current->pid, sem,
172 atomic_read(&sem->count), __builtin_return_address(0));
173#endif
174 __down(sem);
175}
176
177int __sched
178down_interruptible(struct semaphore *sem)
179{
180#ifdef WAITQUEUE_DEBUG
181 CHECK_MAGIC(sem->__magic);
182#endif
183#ifdef CONFIG_DEBUG_SEMAPHORE
184 printk("%s(%d): down(%p) <count=%d> from %p\n",
185 current->comm, current->pid, sem,
186 atomic_read(&sem->count), __builtin_return_address(0));
187#endif
188 return __down_interruptible(sem);
189}
190
191int
192down_trylock(struct semaphore *sem)
193{
194 int ret;
195
196#ifdef WAITQUEUE_DEBUG
197 CHECK_MAGIC(sem->__magic);
198#endif
199
200 ret = __down_trylock(sem);
201
202#ifdef CONFIG_DEBUG_SEMAPHORE
203 printk("%s(%d): down_trylock %s from %p\n",
204 current->comm, current->pid,
205 ret ? "failed" : "acquired",
206 __builtin_return_address(0));
207#endif
208
209 return ret;
210}
211
212void
213up(struct semaphore *sem)
214{
215#ifdef WAITQUEUE_DEBUG
216 CHECK_MAGIC(sem->__magic);
217#endif
218#ifdef CONFIG_DEBUG_SEMAPHORE
219 printk("%s(%d): up(%p) <count=%d> from %p\n",
220 current->comm, current->pid, sem,
221 atomic_read(&sem->count), __builtin_return_address(0));
222#endif
223 __up(sem);
224}
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
new file mode 100644
index 000000000000..b4e5f8ff2b25
--- /dev/null
+++ b/arch/alpha/kernel/setup.c
@@ -0,0 +1,1486 @@
1/*
2 * linux/arch/alpha/kernel/setup.c
3 *
4 * Copyright (C) 1995 Linus Torvalds
5 */
6
7/* 2.3.x bootmem, 1999 Andrea Arcangeli <andrea@suse.de> */
8
9/*
10 * Bootup setup stuff.
11 */
12
13#include <linux/sched.h>
14#include <linux/kernel.h>
15#include <linux/mm.h>
16#include <linux/stddef.h>
17#include <linux/unistd.h>
18#include <linux/ptrace.h>
19#include <linux/slab.h>
20#include <linux/user.h>
21#include <linux/a.out.h>
22#include <linux/tty.h>
23#include <linux/delay.h>
24#include <linux/config.h> /* CONFIG_ALPHA_LCA etc */
25#include <linux/mc146818rtc.h>
26#include <linux/console.h>
27#include <linux/errno.h>
28#include <linux/init.h>
29#include <linux/string.h>
30#include <linux/ioport.h>
31#include <linux/bootmem.h>
32#include <linux/pci.h>
33#include <linux/seq_file.h>
34#include <linux/root_dev.h>
35#include <linux/initrd.h>
36#include <linux/eisa.h>
37#ifdef CONFIG_MAGIC_SYSRQ
38#include <linux/sysrq.h>
39#include <linux/reboot.h>
40#endif
41#include <linux/notifier.h>
42#include <asm/setup.h>
43#include <asm/io.h>
44
45extern struct notifier_block *panic_notifier_list;
46static int alpha_panic_event(struct notifier_block *, unsigned long, void *);
47static struct notifier_block alpha_panic_block = {
48 alpha_panic_event,
49 NULL,
50 INT_MAX /* try to do it first */
51};
52
53#include <asm/uaccess.h>
54#include <asm/pgtable.h>
55#include <asm/system.h>
56#include <asm/hwrpb.h>
57#include <asm/dma.h>
58#include <asm/io.h>
59#include <asm/mmu_context.h>
60#include <asm/console.h>
61
62#include "proto.h"
63#include "pci_impl.h"
64
65
66struct hwrpb_struct *hwrpb;
67unsigned long srm_hae;
68
69int alpha_l1i_cacheshape;
70int alpha_l1d_cacheshape;
71int alpha_l2_cacheshape;
72int alpha_l3_cacheshape;
73
74#ifdef CONFIG_VERBOSE_MCHECK
75/* 0=minimum, 1=verbose, 2=all */
76/* These can be overridden via the command line, ie "verbose_mcheck=2") */
77unsigned long alpha_verbose_mcheck = CONFIG_VERBOSE_MCHECK_ON;
78#endif
79
80/* Which processor we booted from. */
81int boot_cpuid;
82
83/*
84 * Using SRM callbacks for initial console output. This works from
85 * setup_arch() time through the end of time_init(), as those places
86 * are under our (Alpha) control.
87
88 * "srmcons" specified in the boot command arguments allows us to
89 * see kernel messages during the period of time before the true
90 * console device is "registered" during console_init().
91 * As of this version (2.5.59), console_init() will call
92 * disable_early_printk() as the last action before initializing
93 * the console drivers. That's the last possible time srmcons can be
94 * unregistered without interfering with console behavior.
95 *
96 * By default, OFF; set it with a bootcommand arg of "srmcons" or
97 * "console=srm". The meaning of these two args is:
98 * "srmcons" - early callback prints
99 * "console=srm" - full callback based console, including early prints
100 */
101int srmcons_output = 0;
102
103/* Enforce a memory size limit; useful for testing. By default, none. */
104unsigned long mem_size_limit = 0;
105
106/* Set AGP GART window size (0 means disabled). */
107unsigned long alpha_agpgart_size = DEFAULT_AGP_APER_SIZE;
108
109#ifdef CONFIG_ALPHA_GENERIC
110struct alpha_machine_vector alpha_mv;
111int alpha_using_srm;
112#endif
113
114#define N(a) (sizeof(a)/sizeof(a[0]))
115
116static struct alpha_machine_vector *get_sysvec(unsigned long, unsigned long,
117 unsigned long);
118static struct alpha_machine_vector *get_sysvec_byname(const char *);
119static void get_sysnames(unsigned long, unsigned long, unsigned long,
120 char **, char **);
121static void determine_cpu_caches (unsigned int);
122
123static char command_line[COMMAND_LINE_SIZE];
124
125/*
126 * The format of "screen_info" is strange, and due to early
127 * i386-setup code. This is just enough to make the console
128 * code think we're on a VGA color display.
129 */
130
131struct screen_info screen_info = {
132 .orig_x = 0,
133 .orig_y = 25,
134 .orig_video_cols = 80,
135 .orig_video_lines = 25,
136 .orig_video_isVGA = 1,
137 .orig_video_points = 16
138};
139
140/*
141 * The direct map I/O window, if any. This should be the same
142 * for all busses, since it's used by virt_to_bus.
143 */
144
145unsigned long __direct_map_base;
146unsigned long __direct_map_size;
147
148/*
149 * Declare all of the machine vectors.
150 */
151
152/* GCC 2.7.2 (on alpha at least) is lame. It does not support either
153 __attribute__((weak)) or #pragma weak. Bypass it and talk directly
154 to the assembler. */
155
156#define WEAK(X) \
157 extern struct alpha_machine_vector X; \
158 asm(".weak "#X)
159
160WEAK(alcor_mv);
161WEAK(alphabook1_mv);
162WEAK(avanti_mv);
163WEAK(cabriolet_mv);
164WEAK(clipper_mv);
165WEAK(dp264_mv);
166WEAK(eb164_mv);
167WEAK(eb64p_mv);
168WEAK(eb66_mv);
169WEAK(eb66p_mv);
170WEAK(eiger_mv);
171WEAK(jensen_mv);
172WEAK(lx164_mv);
173WEAK(lynx_mv);
174WEAK(marvel_ev7_mv);
175WEAK(miata_mv);
176WEAK(mikasa_mv);
177WEAK(mikasa_primo_mv);
178WEAK(monet_mv);
179WEAK(nautilus_mv);
180WEAK(noname_mv);
181WEAK(noritake_mv);
182WEAK(noritake_primo_mv);
183WEAK(p2k_mv);
184WEAK(pc164_mv);
185WEAK(privateer_mv);
186WEAK(rawhide_mv);
187WEAK(ruffian_mv);
188WEAK(rx164_mv);
189WEAK(sable_mv);
190WEAK(sable_gamma_mv);
191WEAK(shark_mv);
192WEAK(sx164_mv);
193WEAK(takara_mv);
194WEAK(titan_mv);
195WEAK(webbrick_mv);
196WEAK(wildfire_mv);
197WEAK(xl_mv);
198WEAK(xlt_mv);
199
200#undef WEAK
201
202/*
203 * I/O resources inherited from PeeCees. Except for perhaps the
204 * turbochannel alphas, everyone has these on some sort of SuperIO chip.
205 *
206 * ??? If this becomes less standard, move the struct out into the
207 * machine vector.
208 */
209
210static void __init
211reserve_std_resources(void)
212{
213 static struct resource standard_io_resources[] = {
214 { .name = "rtc", .start = -1, .end = -1 },
215 { .name = "dma1", .start = 0x00, .end = 0x1f },
216 { .name = "pic1", .start = 0x20, .end = 0x3f },
217 { .name = "timer", .start = 0x40, .end = 0x5f },
218 { .name = "keyboard", .start = 0x60, .end = 0x6f },
219 { .name = "dma page reg", .start = 0x80, .end = 0x8f },
220 { .name = "pic2", .start = 0xa0, .end = 0xbf },
221 { .name = "dma2", .start = 0xc0, .end = 0xdf },
222 };
223
224 struct resource *io = &ioport_resource;
225 size_t i;
226
227 if (hose_head) {
228 struct pci_controller *hose;
229 for (hose = hose_head; hose; hose = hose->next)
230 if (hose->index == 0) {
231 io = hose->io_space;
232 break;
233 }
234 }
235
236 /* Fix up for the Jensen's queer RTC placement. */
237 standard_io_resources[0].start = RTC_PORT(0);
238 standard_io_resources[0].end = RTC_PORT(0) + 0x10;
239
240 for (i = 0; i < N(standard_io_resources); ++i)
241 request_resource(io, standard_io_resources+i);
242}
243
244#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
245#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
246#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
247#define PFN_MAX PFN_DOWN(0x80000000)
248#define for_each_mem_cluster(memdesc, cluster, i) \
249 for ((cluster) = (memdesc)->cluster, (i) = 0; \
250 (i) < (memdesc)->numclusters; (i)++, (cluster)++)
251
252static unsigned long __init
253get_mem_size_limit(char *s)
254{
255 unsigned long end = 0;
256 char *from = s;
257
258 end = simple_strtoul(from, &from, 0);
259 if ( *from == 'K' || *from == 'k' ) {
260 end = end << 10;
261 from++;
262 } else if ( *from == 'M' || *from == 'm' ) {
263 end = end << 20;
264 from++;
265 } else if ( *from == 'G' || *from == 'g' ) {
266 end = end << 30;
267 from++;
268 }
269 return end >> PAGE_SHIFT; /* Return the PFN of the limit. */
270}
271
272#ifdef CONFIG_BLK_DEV_INITRD
273void * __init
274move_initrd(unsigned long mem_limit)
275{
276 void *start;
277 unsigned long size;
278
279 size = initrd_end - initrd_start;
280 start = __alloc_bootmem(PAGE_ALIGN(size), PAGE_SIZE, 0);
281 if (!start || __pa(start) + size > mem_limit) {
282 initrd_start = initrd_end = 0;
283 return NULL;
284 }
285 memmove(start, (void *)initrd_start, size);
286 initrd_start = (unsigned long)start;
287 initrd_end = initrd_start + size;
288 printk("initrd moved to %p\n", start);
289 return start;
290}
291#endif
292
293#ifndef CONFIG_DISCONTIGMEM
294static void __init
295setup_memory(void *kernel_end)
296{
297 struct memclust_struct * cluster;
298 struct memdesc_struct * memdesc;
299 unsigned long start_kernel_pfn, end_kernel_pfn;
300 unsigned long bootmap_size, bootmap_pages, bootmap_start;
301 unsigned long start, end;
302 unsigned long i;
303
304 /* Find free clusters, and init and free the bootmem accordingly. */
305 memdesc = (struct memdesc_struct *)
306 (hwrpb->mddt_offset + (unsigned long) hwrpb);
307
308 for_each_mem_cluster(memdesc, cluster, i) {
309 printk("memcluster %lu, usage %01lx, start %8lu, end %8lu\n",
310 i, cluster->usage, cluster->start_pfn,
311 cluster->start_pfn + cluster->numpages);
312
313 /* Bit 0 is console/PALcode reserved. Bit 1 is
314 non-volatile memory -- we might want to mark
315 this for later. */
316 if (cluster->usage & 3)
317 continue;
318
319 end = cluster->start_pfn + cluster->numpages;
320 if (end > max_low_pfn)
321 max_low_pfn = end;
322 }
323
324 /*
325 * Except for the NUMA systems (wildfire, marvel) all of the
326 * Alpha systems we run on support 32GB of memory or less.
327 * Since the NUMA systems introduce large holes in memory addressing,
328 * we can get into a situation where there is not enough contiguous
329 * memory for the memory map.
330 *
331 * Limit memory to the first 32GB to limit the NUMA systems to
332 * memory on their first node (wildfire) or 2 (marvel) to avoid
333 * not being able to produce the memory map. In order to access
334 * all of the memory on the NUMA systems, build with discontiguous
335 * memory support.
336 *
337 * If the user specified a memory limit, let that memory limit stand.
338 */
339 if (!mem_size_limit)
340 mem_size_limit = (32ul * 1024 * 1024 * 1024) >> PAGE_SHIFT;
341
342 if (mem_size_limit && max_low_pfn >= mem_size_limit)
343 {
344 printk("setup: forcing memory size to %ldK (from %ldK).\n",
345 mem_size_limit << (PAGE_SHIFT - 10),
346 max_low_pfn << (PAGE_SHIFT - 10));
347 max_low_pfn = mem_size_limit;
348 }
349
350 /* Find the bounds of kernel memory. */
351 start_kernel_pfn = PFN_DOWN(KERNEL_START_PHYS);
352 end_kernel_pfn = PFN_UP(virt_to_phys(kernel_end));
353 bootmap_start = -1;
354
355 try_again:
356 if (max_low_pfn <= end_kernel_pfn)
357 panic("not enough memory to boot");
358
359 /* We need to know how many physically contiguous pages
360 we'll need for the bootmap. */
361 bootmap_pages = bootmem_bootmap_pages(max_low_pfn);
362
363 /* Now find a good region where to allocate the bootmap. */
364 for_each_mem_cluster(memdesc, cluster, i) {
365 if (cluster->usage & 3)
366 continue;
367
368 start = cluster->start_pfn;
369 end = start + cluster->numpages;
370 if (start >= max_low_pfn)
371 continue;
372 if (end > max_low_pfn)
373 end = max_low_pfn;
374 if (start < start_kernel_pfn) {
375 if (end > end_kernel_pfn
376 && end - end_kernel_pfn >= bootmap_pages) {
377 bootmap_start = end_kernel_pfn;
378 break;
379 } else if (end > start_kernel_pfn)
380 end = start_kernel_pfn;
381 } else if (start < end_kernel_pfn)
382 start = end_kernel_pfn;
383 if (end - start >= bootmap_pages) {
384 bootmap_start = start;
385 break;
386 }
387 }
388
389 if (bootmap_start == ~0UL) {
390 max_low_pfn >>= 1;
391 goto try_again;
392 }
393
394 /* Allocate the bootmap and mark the whole MM as reserved. */
395 bootmap_size = init_bootmem(bootmap_start, max_low_pfn);
396
397 /* Mark the free regions. */
398 for_each_mem_cluster(memdesc, cluster, i) {
399 if (cluster->usage & 3)
400 continue;
401
402 start = cluster->start_pfn;
403 end = cluster->start_pfn + cluster->numpages;
404 if (start >= max_low_pfn)
405 continue;
406 if (end > max_low_pfn)
407 end = max_low_pfn;
408 if (start < start_kernel_pfn) {
409 if (end > end_kernel_pfn) {
410 free_bootmem(PFN_PHYS(start),
411 (PFN_PHYS(start_kernel_pfn)
412 - PFN_PHYS(start)));
413 printk("freeing pages %ld:%ld\n",
414 start, start_kernel_pfn);
415 start = end_kernel_pfn;
416 } else if (end > start_kernel_pfn)
417 end = start_kernel_pfn;
418 } else if (start < end_kernel_pfn)
419 start = end_kernel_pfn;
420 if (start >= end)
421 continue;
422
423 free_bootmem(PFN_PHYS(start), PFN_PHYS(end) - PFN_PHYS(start));
424 printk("freeing pages %ld:%ld\n", start, end);
425 }
426
427 /* Reserve the bootmap memory. */
428 reserve_bootmem(PFN_PHYS(bootmap_start), bootmap_size);
429 printk("reserving pages %ld:%ld\n", bootmap_start, bootmap_start+PFN_UP(bootmap_size));
430
431#ifdef CONFIG_BLK_DEV_INITRD
432 initrd_start = INITRD_START;
433 if (initrd_start) {
434 initrd_end = initrd_start+INITRD_SIZE;
435 printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
436 (void *) initrd_start, INITRD_SIZE);
437
438 if ((void *)initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) {
439 if (!move_initrd(PFN_PHYS(max_low_pfn)))
440 printk("initrd extends beyond end of memory "
441 "(0x%08lx > 0x%p)\ndisabling initrd\n",
442 initrd_end,
443 phys_to_virt(PFN_PHYS(max_low_pfn)));
444 } else {
445 reserve_bootmem(virt_to_phys((void *)initrd_start),
446 INITRD_SIZE);
447 }
448 }
449#endif /* CONFIG_BLK_DEV_INITRD */
450}
451#else
452extern void setup_memory(void *);
453#endif /* !CONFIG_DISCONTIGMEM */
454
455int __init
456page_is_ram(unsigned long pfn)
457{
458 struct memclust_struct * cluster;
459 struct memdesc_struct * memdesc;
460 unsigned long i;
461
462 memdesc = (struct memdesc_struct *)
463 (hwrpb->mddt_offset + (unsigned long) hwrpb);
464 for_each_mem_cluster(memdesc, cluster, i)
465 {
466 if (pfn >= cluster->start_pfn &&
467 pfn < cluster->start_pfn + cluster->numpages) {
468 return (cluster->usage & 3) ? 0 : 1;
469 }
470 }
471
472 return 0;
473}
474
475#undef PFN_UP
476#undef PFN_DOWN
477#undef PFN_PHYS
478#undef PFN_MAX
479
480void __init
481setup_arch(char **cmdline_p)
482{
483 extern char _end[];
484
485 struct alpha_machine_vector *vec = NULL;
486 struct percpu_struct *cpu;
487 char *type_name, *var_name, *p;
488 void *kernel_end = _end; /* end of kernel */
489 char *args = command_line;
490
491 hwrpb = (struct hwrpb_struct*) __va(INIT_HWRPB->phys_addr);
492 boot_cpuid = hard_smp_processor_id();
493
494 /*
495 * Pre-process the system type to make sure it will be valid.
496 *
497 * This may restore real CABRIO and EB66+ family names, ie
498 * EB64+ and EB66.
499 *
500 * Oh, and "white box" AS800 (aka DIGITAL Server 3000 series)
501 * and AS1200 (DIGITAL Server 5000 series) have the type as
502 * the negative of the real one.
503 */
504 if ((long)hwrpb->sys_type < 0) {
505 hwrpb->sys_type = -((long)hwrpb->sys_type);
506 hwrpb_update_checksum(hwrpb);
507 }
508
509 /* Register a call for panic conditions. */
510 notifier_chain_register(&panic_notifier_list, &alpha_panic_block);
511
512#ifdef CONFIG_ALPHA_GENERIC
513 /* Assume that we've booted from SRM if we haven't booted from MILO.
514 Detect the later by looking for "MILO" in the system serial nr. */
515 alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0;
516#endif
517
518 /* If we are using SRM, we want to allow callbacks
519 as early as possible, so do this NOW, and then
520 they should work immediately thereafter.
521 */
522 kernel_end = callback_init(kernel_end);
523
524 /*
525 * Locate the command line.
526 */
527 /* Hack for Jensen... since we're restricted to 8 or 16 chars for
528 boot flags depending on the boot mode, we need some shorthand.
529 This should do for installation. */
530 if (strcmp(COMMAND_LINE, "INSTALL") == 0) {
531 strlcpy(command_line, "root=/dev/fd0 load_ramdisk=1", sizeof command_line);
532 } else {
533 strlcpy(command_line, COMMAND_LINE, sizeof command_line);
534 }
535 strcpy(saved_command_line, command_line);
536 *cmdline_p = command_line;
537
538 /*
539 * Process command-line arguments.
540 */
541 while ((p = strsep(&args, " \t")) != NULL) {
542 if (!*p) continue;
543 if (strncmp(p, "alpha_mv=", 9) == 0) {
544 vec = get_sysvec_byname(p+9);
545 continue;
546 }
547 if (strncmp(p, "cycle=", 6) == 0) {
548 est_cycle_freq = simple_strtol(p+6, NULL, 0);
549 continue;
550 }
551 if (strncmp(p, "mem=", 4) == 0) {
552 mem_size_limit = get_mem_size_limit(p+4);
553 continue;
554 }
555 if (strncmp(p, "srmcons", 7) == 0) {
556 srmcons_output |= 1;
557 continue;
558 }
559 if (strncmp(p, "console=srm", 11) == 0) {
560 srmcons_output |= 2;
561 continue;
562 }
563 if (strncmp(p, "gartsize=", 9) == 0) {
564 alpha_agpgart_size =
565 get_mem_size_limit(p+9) << PAGE_SHIFT;
566 continue;
567 }
568#ifdef CONFIG_VERBOSE_MCHECK
569 if (strncmp(p, "verbose_mcheck=", 15) == 0) {
570 alpha_verbose_mcheck = simple_strtol(p+15, NULL, 0);
571 continue;
572 }
573#endif
574 }
575
576 /* Replace the command line, now that we've killed it with strsep. */
577 strcpy(command_line, saved_command_line);
578
579 /* If we want SRM console printk echoing early, do it now. */
580 if (alpha_using_srm && srmcons_output) {
581 register_srm_console();
582
583 /*
584 * If "console=srm" was specified, clear the srmcons_output
585 * flag now so that time.c won't unregister_srm_console
586 */
587 if (srmcons_output & 2)
588 srmcons_output = 0;
589 }
590
591#ifdef CONFIG_MAGIC_SYSRQ
592 /* If we're using SRM, make sysrq-b halt back to the prom,
593 not auto-reboot. */
594 if (alpha_using_srm) {
595 struct sysrq_key_op *op = __sysrq_get_key_op('b');
596 op->handler = (void *) machine_halt;
597 }
598#endif
599
600 /*
601 * Identify and reconfigure for the current system.
602 */
603 cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset);
604
605 get_sysnames(hwrpb->sys_type, hwrpb->sys_variation,
606 cpu->type, &type_name, &var_name);
607 if (*var_name == '0')
608 var_name = "";
609
610 if (!vec) {
611 vec = get_sysvec(hwrpb->sys_type, hwrpb->sys_variation,
612 cpu->type);
613 }
614
615 if (!vec) {
616 panic("Unsupported system type: %s%s%s (%ld %ld)\n",
617 type_name, (*var_name ? " variation " : ""), var_name,
618 hwrpb->sys_type, hwrpb->sys_variation);
619 }
620 if (vec != &alpha_mv) {
621 alpha_mv = *vec;
622 }
623
624 printk("Booting "
625#ifdef CONFIG_ALPHA_GENERIC
626 "GENERIC "
627#endif
628 "on %s%s%s using machine vector %s from %s\n",
629 type_name, (*var_name ? " variation " : ""),
630 var_name, alpha_mv.vector_name,
631 (alpha_using_srm ? "SRM" : "MILO"));
632
633 printk("Major Options: "
634#ifdef CONFIG_SMP
635 "SMP "
636#endif
637#ifdef CONFIG_ALPHA_EV56
638 "EV56 "
639#endif
640#ifdef CONFIG_ALPHA_EV67
641 "EV67 "
642#endif
643#ifdef CONFIG_ALPHA_LEGACY_START_ADDRESS
644 "LEGACY_START "
645#endif
646#ifdef CONFIG_VERBOSE_MCHECK
647 "VERBOSE_MCHECK "
648#endif
649
650#ifdef CONFIG_DISCONTIGMEM
651 "DISCONTIGMEM "
652#ifdef CONFIG_NUMA
653 "NUMA "
654#endif
655#endif
656
657#ifdef CONFIG_DEBUG_SPINLOCK
658 "DEBUG_SPINLOCK "
659#endif
660#ifdef CONFIG_MAGIC_SYSRQ
661 "MAGIC_SYSRQ "
662#endif
663 "\n");
664
665 printk("Command line: %s\n", command_line);
666
667 /*
668 * Sync up the HAE.
669 * Save the SRM's current value for restoration.
670 */
671 srm_hae = *alpha_mv.hae_register;
672 __set_hae(alpha_mv.hae_cache);
673
674 /* Reset enable correctable error reports. */
675 wrmces(0x7);
676
677 /* Find our memory. */
678 setup_memory(kernel_end);
679
680 /* First guess at cpu cache sizes. Do this before init_arch. */
681 determine_cpu_caches(cpu->type);
682
683 /* Initialize the machine. Usually has to do with setting up
684 DMA windows and the like. */
685 if (alpha_mv.init_arch)
686 alpha_mv.init_arch();
687
688 /* Reserve standard resources. */
689 reserve_std_resources();
690
691 /*
692 * Give us a default console. TGA users will see nothing until
693 * chr_dev_init is called, rather late in the boot sequence.
694 */
695
696#ifdef CONFIG_VT
697#if defined(CONFIG_VGA_CONSOLE)
698 conswitchp = &vga_con;
699#elif defined(CONFIG_DUMMY_CONSOLE)
700 conswitchp = &dummy_con;
701#endif
702#endif
703
704 /* Default root filesystem to sda2. */
705 ROOT_DEV = Root_SDA2;
706
707#ifdef CONFIG_EISA
708 /* FIXME: only set this when we actually have EISA in this box? */
709 EISA_bus = 1;
710#endif
711
712 /*
713 * Check ASN in HWRPB for validity, report if bad.
714 * FIXME: how was this failing? Should we trust it instead,
715 * and copy the value into alpha_mv.max_asn?
716 */
717
718 if (hwrpb->max_asn != MAX_ASN) {
719 printk("Max ASN from HWRPB is bad (0x%lx)\n", hwrpb->max_asn);
720 }
721
722 /*
723 * Identify the flock of penguins.
724 */
725
726#ifdef CONFIG_SMP
727 setup_smp();
728#endif
729 paging_init();
730}
731
732void __init
733disable_early_printk(void)
734{
735 if (alpha_using_srm && srmcons_output) {
736 unregister_srm_console();
737 srmcons_output = 0;
738 }
739}
740
741static char sys_unknown[] = "Unknown";
742static char systype_names[][16] = {
743 "0",
744 "ADU", "Cobra", "Ruby", "Flamingo", "Mannequin", "Jensen",
745 "Pelican", "Morgan", "Sable", "Medulla", "Noname",
746 "Turbolaser", "Avanti", "Mustang", "Alcor", "Tradewind",
747 "Mikasa", "EB64", "EB66", "EB64+", "AlphaBook1",
748 "Rawhide", "K2", "Lynx", "XL", "EB164", "Noritake",
749 "Cortex", "29", "Miata", "XXM", "Takara", "Yukon",
750 "Tsunami", "Wildfire", "CUSCO", "Eiger", "Titan", "Marvel"
751};
752
753static char unofficial_names[][8] = {"100", "Ruffian"};
754
755static char api_names[][16] = {"200", "Nautilus"};
756
757static char eb164_names[][8] = {"EB164", "PC164", "LX164", "SX164", "RX164"};
758static int eb164_indices[] = {0,0,0,1,1,1,1,1,2,2,2,2,3,3,3,3,4};
759
760static char alcor_names[][16] = {"Alcor", "Maverick", "Bret"};
761static int alcor_indices[] = {0,0,0,1,1,1,0,0,0,0,0,0,2,2,2,2,2,2};
762
763static char eb64p_names[][16] = {"EB64+", "Cabriolet", "AlphaPCI64"};
764static int eb64p_indices[] = {0,0,1,2};
765
766static char eb66_names[][8] = {"EB66", "EB66+"};
767static int eb66_indices[] = {0,0,1};
768
769static char marvel_names[][16] = {
770 "Marvel/EV7"
771};
772static int marvel_indices[] = { 0 };
773
774static char rawhide_names[][16] = {
775 "Dodge", "Wrangler", "Durango", "Tincup", "DaVinci"
776};
777static int rawhide_indices[] = {0,0,0,1,1,2,2,3,3,4,4};
778
779static char titan_names[][16] = {
780 "DEFAULT", "Privateer", "Falcon", "Granite"
781};
782static int titan_indices[] = {0,1,2,2,3};
783
784static char tsunami_names[][16] = {
785 "0", "DP264", "Warhol", "Windjammer", "Monet", "Clipper",
786 "Goldrush", "Webbrick", "Catamaran", "Brisbane", "Melbourne",
787 "Flying Clipper", "Shark"
788};
789static int tsunami_indices[] = {0,1,2,3,4,5,6,7,8,9,10,11,12};
790
791static struct alpha_machine_vector * __init
792get_sysvec(unsigned long type, unsigned long variation, unsigned long cpu)
793{
794 static struct alpha_machine_vector *systype_vecs[] __initdata =
795 {
796 NULL, /* 0 */
797 NULL, /* ADU */
798 NULL, /* Cobra */
799 NULL, /* Ruby */
800 NULL, /* Flamingo */
801 NULL, /* Mannequin */
802 &jensen_mv,
803 NULL, /* Pelican */
804 NULL, /* Morgan */
805 NULL, /* Sable -- see below. */
806 NULL, /* Medulla */
807 &noname_mv,
808 NULL, /* Turbolaser */
809 &avanti_mv,
810 NULL, /* Mustang */
811 NULL, /* Alcor, Bret, Maverick. HWRPB inaccurate? */
812 NULL, /* Tradewind */
813 NULL, /* Mikasa -- see below. */
814 NULL, /* EB64 */
815 NULL, /* EB66 -- see variation. */
816 NULL, /* EB64+ -- see variation. */
817 &alphabook1_mv,
818 &rawhide_mv,
819 NULL, /* K2 */
820 &lynx_mv, /* Lynx */
821 &xl_mv,
822 NULL, /* EB164 -- see variation. */
823 NULL, /* Noritake -- see below. */
824 NULL, /* Cortex */
825 NULL, /* 29 */
826 &miata_mv,
827 NULL, /* XXM */
828 &takara_mv,
829 NULL, /* Yukon */
830 NULL, /* Tsunami -- see variation. */
831 &wildfire_mv, /* Wildfire */
832 NULL, /* CUSCO */
833 &eiger_mv, /* Eiger */
834 NULL, /* Titan */
835 NULL, /* Marvel */
836 };
837
838 static struct alpha_machine_vector *unofficial_vecs[] __initdata =
839 {
840 NULL, /* 100 */
841 &ruffian_mv,
842 };
843
844 static struct alpha_machine_vector *api_vecs[] __initdata =
845 {
846 NULL, /* 200 */
847 &nautilus_mv,
848 };
849
850 static struct alpha_machine_vector *alcor_vecs[] __initdata =
851 {
852 &alcor_mv, &xlt_mv, &xlt_mv
853 };
854
855 static struct alpha_machine_vector *eb164_vecs[] __initdata =
856 {
857 &eb164_mv, &pc164_mv, &lx164_mv, &sx164_mv, &rx164_mv
858 };
859
860 static struct alpha_machine_vector *eb64p_vecs[] __initdata =
861 {
862 &eb64p_mv,
863 &cabriolet_mv,
864 &cabriolet_mv /* AlphaPCI64 */
865 };
866
867 static struct alpha_machine_vector *eb66_vecs[] __initdata =
868 {
869 &eb66_mv,
870 &eb66p_mv
871 };
872
873 static struct alpha_machine_vector *marvel_vecs[] __initdata =
874 {
875 &marvel_ev7_mv,
876 };
877
878 static struct alpha_machine_vector *titan_vecs[] __initdata =
879 {
880 &titan_mv, /* default */
881 &privateer_mv, /* privateer */
882 &titan_mv, /* falcon */
883 &privateer_mv, /* granite */
884 };
885
886 static struct alpha_machine_vector *tsunami_vecs[] __initdata =
887 {
888 NULL,
889 &dp264_mv, /* dp264 */
890 &dp264_mv, /* warhol */
891 &dp264_mv, /* windjammer */
892 &monet_mv, /* monet */
893 &clipper_mv, /* clipper */
894 &dp264_mv, /* goldrush */
895 &webbrick_mv, /* webbrick */
896 &dp264_mv, /* catamaran */
897 NULL, /* brisbane? */
898 NULL, /* melbourne? */
899 NULL, /* flying clipper? */
900 &shark_mv, /* shark */
901 };
902
903 /* ??? Do we need to distinguish between Rawhides? */
904
905 struct alpha_machine_vector *vec;
906
907 /* Search the system tables first... */
908 vec = NULL;
909 if (type < N(systype_vecs)) {
910 vec = systype_vecs[type];
911 } else if ((type > ST_API_BIAS) &&
912 (type - ST_API_BIAS) < N(api_vecs)) {
913 vec = api_vecs[type - ST_API_BIAS];
914 } else if ((type > ST_UNOFFICIAL_BIAS) &&
915 (type - ST_UNOFFICIAL_BIAS) < N(unofficial_vecs)) {
916 vec = unofficial_vecs[type - ST_UNOFFICIAL_BIAS];
917 }
918
919 /* If we've not found one, try for a variation. */
920
921 if (!vec) {
922 /* Member ID is a bit-field. */
923 unsigned long member = (variation >> 10) & 0x3f;
924
925 cpu &= 0xffffffff; /* make it usable */
926
927 switch (type) {
928 case ST_DEC_ALCOR:
929 if (member < N(alcor_indices))
930 vec = alcor_vecs[alcor_indices[member]];
931 break;
932 case ST_DEC_EB164:
933 if (member < N(eb164_indices))
934 vec = eb164_vecs[eb164_indices[member]];
935 /* PC164 may show as EB164 variation with EV56 CPU,
936 but, since no true EB164 had anything but EV5... */
937 if (vec == &eb164_mv && cpu == EV56_CPU)
938 vec = &pc164_mv;
939 break;
940 case ST_DEC_EB64P:
941 if (member < N(eb64p_indices))
942 vec = eb64p_vecs[eb64p_indices[member]];
943 break;
944 case ST_DEC_EB66:
945 if (member < N(eb66_indices))
946 vec = eb66_vecs[eb66_indices[member]];
947 break;
948 case ST_DEC_MARVEL:
949 if (member < N(marvel_indices))
950 vec = marvel_vecs[marvel_indices[member]];
951 break;
952 case ST_DEC_TITAN:
953 vec = titan_vecs[0]; /* default */
954 if (member < N(titan_indices))
955 vec = titan_vecs[titan_indices[member]];
956 break;
957 case ST_DEC_TSUNAMI:
958 if (member < N(tsunami_indices))
959 vec = tsunami_vecs[tsunami_indices[member]];
960 break;
961 case ST_DEC_1000:
962 if (cpu == EV5_CPU || cpu == EV56_CPU)
963 vec = &mikasa_primo_mv;
964 else
965 vec = &mikasa_mv;
966 break;
967 case ST_DEC_NORITAKE:
968 if (cpu == EV5_CPU || cpu == EV56_CPU)
969 vec = &noritake_primo_mv;
970 else
971 vec = &noritake_mv;
972 break;
973 case ST_DEC_2100_A500:
974 if (cpu == EV5_CPU || cpu == EV56_CPU)
975 vec = &sable_gamma_mv;
976 else
977 vec = &sable_mv;
978 break;
979 }
980 }
981 return vec;
982}
983
984static struct alpha_machine_vector * __init
985get_sysvec_byname(const char *name)
986{
987 static struct alpha_machine_vector *all_vecs[] __initdata =
988 {
989 &alcor_mv,
990 &alphabook1_mv,
991 &avanti_mv,
992 &cabriolet_mv,
993 &clipper_mv,
994 &dp264_mv,
995 &eb164_mv,
996 &eb64p_mv,
997 &eb66_mv,
998 &eb66p_mv,
999 &eiger_mv,
1000 &jensen_mv,
1001 &lx164_mv,
1002 &lynx_mv,
1003 &miata_mv,
1004 &mikasa_mv,
1005 &mikasa_primo_mv,
1006 &monet_mv,
1007 &nautilus_mv,
1008 &noname_mv,
1009 &noritake_mv,
1010 &noritake_primo_mv,
1011 &p2k_mv,
1012 &pc164_mv,
1013 &privateer_mv,
1014 &rawhide_mv,
1015 &ruffian_mv,
1016 &rx164_mv,
1017 &sable_mv,
1018 &sable_gamma_mv,
1019 &shark_mv,
1020 &sx164_mv,
1021 &takara_mv,
1022 &webbrick_mv,
1023 &wildfire_mv,
1024 &xl_mv,
1025 &xlt_mv
1026 };
1027
1028 size_t i;
1029
1030 for (i = 0; i < N(all_vecs); ++i) {
1031 struct alpha_machine_vector *mv = all_vecs[i];
1032 if (strcasecmp(mv->vector_name, name) == 0)
1033 return mv;
1034 }
1035 return NULL;
1036}
1037
1038static void
1039get_sysnames(unsigned long type, unsigned long variation, unsigned long cpu,
1040 char **type_name, char **variation_name)
1041{
1042 unsigned long member;
1043
1044 /* If not in the tables, make it UNKNOWN,
1045 else set type name to family */
1046 if (type < N(systype_names)) {
1047 *type_name = systype_names[type];
1048 } else if ((type > ST_API_BIAS) &&
1049 (type - ST_API_BIAS) < N(api_names)) {
1050 *type_name = api_names[type - ST_API_BIAS];
1051 } else if ((type > ST_UNOFFICIAL_BIAS) &&
1052 (type - ST_UNOFFICIAL_BIAS) < N(unofficial_names)) {
1053 *type_name = unofficial_names[type - ST_UNOFFICIAL_BIAS];
1054 } else {
1055 *type_name = sys_unknown;
1056 *variation_name = sys_unknown;
1057 return;
1058 }
1059
1060 /* Set variation to "0"; if variation is zero, done. */
1061 *variation_name = systype_names[0];
1062 if (variation == 0) {
1063 return;
1064 }
1065
1066 member = (variation >> 10) & 0x3f; /* member ID is a bit-field */
1067
1068 cpu &= 0xffffffff; /* make it usable */
1069
1070 switch (type) { /* select by family */
1071 default: /* default to variation "0" for now */
1072 break;
1073 case ST_DEC_EB164:
1074 if (member < N(eb164_indices))
1075 *variation_name = eb164_names[eb164_indices[member]];
1076 /* PC164 may show as EB164 variation, but with EV56 CPU,
1077 so, since no true EB164 had anything but EV5... */
1078 if (eb164_indices[member] == 0 && cpu == EV56_CPU)
1079 *variation_name = eb164_names[1]; /* make it PC164 */
1080 break;
1081 case ST_DEC_ALCOR:
1082 if (member < N(alcor_indices))
1083 *variation_name = alcor_names[alcor_indices[member]];
1084 break;
1085 case ST_DEC_EB64P:
1086 if (member < N(eb64p_indices))
1087 *variation_name = eb64p_names[eb64p_indices[member]];
1088 break;
1089 case ST_DEC_EB66:
1090 if (member < N(eb66_indices))
1091 *variation_name = eb66_names[eb66_indices[member]];
1092 break;
1093 case ST_DEC_MARVEL:
1094 if (member < N(marvel_indices))
1095 *variation_name = marvel_names[marvel_indices[member]];
1096 break;
1097 case ST_DEC_RAWHIDE:
1098 if (member < N(rawhide_indices))
1099 *variation_name = rawhide_names[rawhide_indices[member]];
1100 break;
1101 case ST_DEC_TITAN:
1102 *variation_name = titan_names[0]; /* default */
1103 if (member < N(titan_indices))
1104 *variation_name = titan_names[titan_indices[member]];
1105 break;
1106 case ST_DEC_TSUNAMI:
1107 if (member < N(tsunami_indices))
1108 *variation_name = tsunami_names[tsunami_indices[member]];
1109 break;
1110 }
1111}
1112
1113/*
1114 * A change was made to the HWRPB via an ECO and the following code
1115 * tracks a part of the ECO. In HWRPB versions less than 5, the ECO
1116 * was not implemented in the console firmware. If it's revision 5 or
1117 * greater we can get the name of the platform as an ASCII string from
1118 * the HWRPB. That's what this function does. It checks the revision
1119 * level and if the string is in the HWRPB it returns the address of
1120 * the string--a pointer to the name of the platform.
1121 *
1122 * Returns:
1123 * - Pointer to a ASCII string if it's in the HWRPB
1124 * - Pointer to a blank string if the data is not in the HWRPB.
1125 */
1126
1127static char *
1128platform_string(void)
1129{
1130 struct dsr_struct *dsr;
1131 static char unk_system_string[] = "N/A";
1132
1133 /* Go to the console for the string pointer.
1134 * If the rpb_vers is not 5 or greater the rpb
1135 * is old and does not have this data in it.
1136 */
1137 if (hwrpb->revision < 5)
1138 return (unk_system_string);
1139 else {
1140 /* The Dynamic System Recognition struct
1141 * has the system platform name starting
1142 * after the character count of the string.
1143 */
1144 dsr = ((struct dsr_struct *)
1145 ((char *)hwrpb + hwrpb->dsr_offset));
1146 return ((char *)dsr + (dsr->sysname_off +
1147 sizeof(long)));
1148 }
1149}
1150
1151static int
1152get_nr_processors(struct percpu_struct *cpubase, unsigned long num)
1153{
1154 struct percpu_struct *cpu;
1155 unsigned long i;
1156 int count = 0;
1157
1158 for (i = 0; i < num; i++) {
1159 cpu = (struct percpu_struct *)
1160 ((char *)cpubase + i*hwrpb->processor_size);
1161 if ((cpu->flags & 0x1cc) == 0x1cc)
1162 count++;
1163 }
1164 return count;
1165}
1166
1167static void
1168show_cache_size (struct seq_file *f, const char *which, int shape)
1169{
1170 if (shape == -1)
1171 seq_printf (f, "%s\t\t: n/a\n", which);
1172 else if (shape == 0)
1173 seq_printf (f, "%s\t\t: unknown\n", which);
1174 else
1175 seq_printf (f, "%s\t\t: %dK, %d-way, %db line\n",
1176 which, shape >> 10, shape & 15,
1177 1 << ((shape >> 4) & 15));
1178}
1179
1180static int
1181show_cpuinfo(struct seq_file *f, void *slot)
1182{
1183 extern struct unaligned_stat {
1184 unsigned long count, va, pc;
1185 } unaligned[2];
1186
1187 static char cpu_names[][8] = {
1188 "EV3", "EV4", "Simulate", "LCA4", "EV5", "EV45", "EV56",
1189 "EV6", "PCA56", "PCA57", "EV67", "EV68CB", "EV68AL",
1190 "EV68CX", "EV7", "EV79", "EV69"
1191 };
1192
1193 struct percpu_struct *cpu = slot;
1194 unsigned int cpu_index;
1195 char *cpu_name;
1196 char *systype_name;
1197 char *sysvariation_name;
1198 int nr_processors;
1199
1200 cpu_index = (unsigned) (cpu->type - 1);
1201 cpu_name = "Unknown";
1202 if (cpu_index < N(cpu_names))
1203 cpu_name = cpu_names[cpu_index];
1204
1205 get_sysnames(hwrpb->sys_type, hwrpb->sys_variation,
1206 cpu->type, &systype_name, &sysvariation_name);
1207
1208 nr_processors = get_nr_processors(cpu, hwrpb->nr_processors);
1209
1210 seq_printf(f, "cpu\t\t\t: Alpha\n"
1211 "cpu model\t\t: %s\n"
1212 "cpu variation\t\t: %ld\n"
1213 "cpu revision\t\t: %ld\n"
1214 "cpu serial number\t: %s\n"
1215 "system type\t\t: %s\n"
1216 "system variation\t: %s\n"
1217 "system revision\t\t: %ld\n"
1218 "system serial number\t: %s\n"
1219 "cycle frequency [Hz]\t: %lu %s\n"
1220 "timer frequency [Hz]\t: %lu.%02lu\n"
1221 "page size [bytes]\t: %ld\n"
1222 "phys. address bits\t: %ld\n"
1223 "max. addr. space #\t: %ld\n"
1224 "BogoMIPS\t\t: %lu.%02lu\n"
1225 "kernel unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
1226 "user unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
1227 "platform string\t\t: %s\n"
1228 "cpus detected\t\t: %d\n",
1229 cpu_name, cpu->variation, cpu->revision,
1230 (char*)cpu->serial_no,
1231 systype_name, sysvariation_name, hwrpb->sys_revision,
1232 (char*)hwrpb->ssn,
1233 est_cycle_freq ? : hwrpb->cycle_freq,
1234 est_cycle_freq ? "est." : "",
1235 hwrpb->intr_freq / 4096,
1236 (100 * hwrpb->intr_freq / 4096) % 100,
1237 hwrpb->pagesize,
1238 hwrpb->pa_bits,
1239 hwrpb->max_asn,
1240 loops_per_jiffy / (500000/HZ),
1241 (loops_per_jiffy / (5000/HZ)) % 100,
1242 unaligned[0].count, unaligned[0].pc, unaligned[0].va,
1243 unaligned[1].count, unaligned[1].pc, unaligned[1].va,
1244 platform_string(), nr_processors);
1245
1246#ifdef CONFIG_SMP
1247 seq_printf(f, "cpus active\t\t: %d\n"
1248 "cpu active mask\t\t: %016lx\n",
1249 num_online_cpus(), cpus_addr(cpu_possible_map)[0]);
1250#endif
1251
1252 show_cache_size (f, "L1 Icache", alpha_l1i_cacheshape);
1253 show_cache_size (f, "L1 Dcache", alpha_l1d_cacheshape);
1254 show_cache_size (f, "L2 cache", alpha_l2_cacheshape);
1255 show_cache_size (f, "L3 cache", alpha_l3_cacheshape);
1256
1257 return 0;
1258}
1259
1260static int __init
1261read_mem_block(int *addr, int stride, int size)
1262{
1263 long nloads = size / stride, cnt, tmp;
1264
1265 __asm__ __volatile__(
1266 " rpcc %0\n"
1267 "1: ldl %3,0(%2)\n"
1268 " subq %1,1,%1\n"
1269 /* Next two XORs introduce an explicit data dependency between
1270 consecutive loads in the loop, which will give us true load
1271 latency. */
1272 " xor %3,%2,%2\n"
1273 " xor %3,%2,%2\n"
1274 " addq %2,%4,%2\n"
1275 " bne %1,1b\n"
1276 " rpcc %3\n"
1277 " subl %3,%0,%0\n"
1278 : "=&r" (cnt), "=&r" (nloads), "=&r" (addr), "=&r" (tmp)
1279 : "r" (stride), "1" (nloads), "2" (addr));
1280
1281 return cnt / (size / stride);
1282}
1283
1284#define CSHAPE(totalsize, linesize, assoc) \
1285 ((totalsize & ~0xff) | (linesize << 4) | assoc)
1286
1287/* ??? EV5 supports up to 64M, but did the systems with more than
1288 16M of BCACHE ever exist? */
1289#define MAX_BCACHE_SIZE 16*1024*1024
1290
1291/* Note that the offchip caches are direct mapped on all Alphas. */
1292static int __init
1293external_cache_probe(int minsize, int width)
1294{
1295 int cycles, prev_cycles = 1000000;
1296 int stride = 1 << width;
1297 long size = minsize, maxsize = MAX_BCACHE_SIZE * 2;
1298
1299 if (maxsize > (max_low_pfn + 1) << PAGE_SHIFT)
1300 maxsize = 1 << (floor_log2(max_low_pfn + 1) + PAGE_SHIFT);
1301
1302 /* Get the first block cached. */
1303 read_mem_block(__va(0), stride, size);
1304
1305 while (size < maxsize) {
1306 /* Get an average load latency in cycles. */
1307 cycles = read_mem_block(__va(0), stride, size);
1308 if (cycles > prev_cycles * 2) {
1309 /* Fine, we exceed the cache. */
1310 printk("%ldK Bcache detected; load hit latency %d "
1311 "cycles, load miss latency %d cycles\n",
1312 size >> 11, prev_cycles, cycles);
1313 return CSHAPE(size >> 1, width, 1);
1314 }
1315 /* Try to get the next block cached. */
1316 read_mem_block(__va(size), stride, size);
1317 prev_cycles = cycles;
1318 size <<= 1;
1319 }
1320 return -1; /* No BCACHE found. */
1321}
1322
1323static void __init
1324determine_cpu_caches (unsigned int cpu_type)
1325{
1326 int L1I, L1D, L2, L3;
1327
1328 switch (cpu_type) {
1329 case EV4_CPU:
1330 case EV45_CPU:
1331 {
1332 if (cpu_type == EV4_CPU)
1333 L1I = CSHAPE(8*1024, 5, 1);
1334 else
1335 L1I = CSHAPE(16*1024, 5, 1);
1336 L1D = L1I;
1337 L3 = -1;
1338
1339 /* BIU_CTL is a write-only Abox register. PALcode has a
1340 shadow copy, and may be available from some versions
1341 of the CSERVE PALcall. If we can get it, then
1342
1343 unsigned long biu_ctl, size;
1344 size = 128*1024 * (1 << ((biu_ctl >> 28) & 7));
1345 L2 = CSHAPE (size, 5, 1);
1346
1347 Unfortunately, we can't rely on that.
1348 */
1349 L2 = external_cache_probe(128*1024, 5);
1350 break;
1351 }
1352
1353 case LCA4_CPU:
1354 {
1355 unsigned long car, size;
1356
1357 L1I = L1D = CSHAPE(8*1024, 5, 1);
1358 L3 = -1;
1359
1360 car = *(vuip) phys_to_virt (0x120000078UL);
1361 size = 64*1024 * (1 << ((car >> 5) & 7));
1362 /* No typo -- 8 byte cacheline size. Whodathunk. */
1363 L2 = (car & 1 ? CSHAPE (size, 3, 1) : -1);
1364 break;
1365 }
1366
1367 case EV5_CPU:
1368 case EV56_CPU:
1369 {
1370 unsigned long sc_ctl, width;
1371
1372 L1I = L1D = CSHAPE(8*1024, 5, 1);
1373
1374 /* Check the line size of the Scache. */
1375 sc_ctl = *(vulp) phys_to_virt (0xfffff000a8UL);
1376 width = sc_ctl & 0x1000 ? 6 : 5;
1377 L2 = CSHAPE (96*1024, width, 3);
1378
1379 /* BC_CONTROL and BC_CONFIG are write-only IPRs. PALcode
1380 has a shadow copy, and may be available from some versions
1381 of the CSERVE PALcall. If we can get it, then
1382
1383 unsigned long bc_control, bc_config, size;
1384 size = 1024*1024 * (1 << ((bc_config & 7) - 1));
1385 L3 = (bc_control & 1 ? CSHAPE (size, width, 1) : -1);
1386
1387 Unfortunately, we can't rely on that.
1388 */
1389 L3 = external_cache_probe(1024*1024, width);
1390 break;
1391 }
1392
1393 case PCA56_CPU:
1394 case PCA57_CPU:
1395 {
1396 unsigned long cbox_config, size;
1397
1398 if (cpu_type == PCA56_CPU) {
1399 L1I = CSHAPE(16*1024, 6, 1);
1400 L1D = CSHAPE(8*1024, 5, 1);
1401 } else {
1402 L1I = CSHAPE(32*1024, 6, 2);
1403 L1D = CSHAPE(16*1024, 5, 1);
1404 }
1405 L3 = -1;
1406
1407 cbox_config = *(vulp) phys_to_virt (0xfffff00008UL);
1408 size = 512*1024 * (1 << ((cbox_config >> 12) & 3));
1409
1410#if 0
1411 L2 = ((cbox_config >> 31) & 1 ? CSHAPE (size, 6, 1) : -1);
1412#else
1413 L2 = external_cache_probe(512*1024, 6);
1414#endif
1415 break;
1416 }
1417
1418 case EV6_CPU:
1419 case EV67_CPU:
1420 case EV68CB_CPU:
1421 case EV68AL_CPU:
1422 case EV68CX_CPU:
1423 case EV69_CPU:
1424 L1I = L1D = CSHAPE(64*1024, 6, 2);
1425 L2 = external_cache_probe(1024*1024, 6);
1426 L3 = -1;
1427 break;
1428
1429 case EV7_CPU:
1430 case EV79_CPU:
1431 L1I = L1D = CSHAPE(64*1024, 6, 2);
1432 L2 = CSHAPE(7*1024*1024/4, 6, 7);
1433 L3 = -1;
1434 break;
1435
1436 default:
1437 /* Nothing known about this cpu type. */
1438 L1I = L1D = L2 = L3 = 0;
1439 break;
1440 }
1441
1442 alpha_l1i_cacheshape = L1I;
1443 alpha_l1d_cacheshape = L1D;
1444 alpha_l2_cacheshape = L2;
1445 alpha_l3_cacheshape = L3;
1446}
1447
1448/*
1449 * We show only CPU #0 info.
1450 */
1451static void *
1452c_start(struct seq_file *f, loff_t *pos)
1453{
1454 return *pos ? NULL : (char *)hwrpb + hwrpb->processor_offset;
1455}
1456
1457static void *
1458c_next(struct seq_file *f, void *v, loff_t *pos)
1459{
1460 return NULL;
1461}
1462
1463static void
1464c_stop(struct seq_file *f, void *v)
1465{
1466}
1467
1468struct seq_operations cpuinfo_op = {
1469 .start = c_start,
1470 .next = c_next,
1471 .stop = c_stop,
1472 .show = show_cpuinfo,
1473};
1474
1475
1476static int
1477alpha_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
1478{
1479#if 1
1480 /* FIXME FIXME FIXME */
1481 /* If we are using SRM and serial console, just hard halt here. */
1482 if (alpha_using_srm && srmcons_output)
1483 __halt();
1484#endif
1485 return NOTIFY_DONE;
1486}
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
new file mode 100644
index 000000000000..08fe8071a7f8
--- /dev/null
+++ b/arch/alpha/kernel/signal.c
@@ -0,0 +1,672 @@
1/*
2 * linux/arch/alpha/kernel/signal.c
3 *
4 * Copyright (C) 1995 Linus Torvalds
5 *
6 * 1997-11-02 Modified for POSIX.1b signals by Richard Henderson
7 */
8
9#include <linux/sched.h>
10#include <linux/kernel.h>
11#include <linux/signal.h>
12#include <linux/errno.h>
13#include <linux/wait.h>
14#include <linux/ptrace.h>
15#include <linux/unistd.h>
16#include <linux/mm.h>
17#include <linux/smp.h>
18#include <linux/smp_lock.h>
19#include <linux/stddef.h>
20#include <linux/tty.h>
21#include <linux/binfmts.h>
22#include <linux/bitops.h>
23
24#include <asm/uaccess.h>
25#include <asm/sigcontext.h>
26#include <asm/ucontext.h>
27
28#include "proto.h"
29
30
31#define DEBUG_SIG 0
32
33#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
34
35asmlinkage void ret_from_sys_call(void);
36static int do_signal(sigset_t *, struct pt_regs *, struct switch_stack *,
37 unsigned long, unsigned long);
38
39
40/*
41 * The OSF/1 sigprocmask calling sequence is different from the
42 * C sigprocmask() sequence..
43 *
44 * how:
45 * 1 - SIG_BLOCK
46 * 2 - SIG_UNBLOCK
47 * 3 - SIG_SETMASK
48 *
49 * We change the range to -1 .. 1 in order to let gcc easily
50 * use the conditional move instructions.
51 *
52 * Note that we don't need to acquire the kernel lock for SMP
53 * operation, as all of this is local to this thread.
54 */
55asmlinkage unsigned long
56do_osf_sigprocmask(int how, unsigned long newmask, struct pt_regs *regs)
57{
58 unsigned long oldmask = -EINVAL;
59
60 if ((unsigned long)how-1 <= 2) {
61 long sign = how-2; /* -1 .. 1 */
62 unsigned long block, unblock;
63
64 newmask &= _BLOCKABLE;
65 spin_lock_irq(&current->sighand->siglock);
66 oldmask = current->blocked.sig[0];
67
68 unblock = oldmask & ~newmask;
69 block = oldmask | newmask;
70 if (!sign)
71 block = unblock;
72 if (sign <= 0)
73 newmask = block;
74 if (_NSIG_WORDS > 1 && sign > 0)
75 sigemptyset(&current->blocked);
76 current->blocked.sig[0] = newmask;
77 recalc_sigpending();
78 spin_unlock_irq(&current->sighand->siglock);
79
80 regs->r0 = 0; /* special no error return */
81 }
82 return oldmask;
83}
84
85asmlinkage int
86osf_sigaction(int sig, const struct osf_sigaction __user *act,
87 struct osf_sigaction __user *oact)
88{
89 struct k_sigaction new_ka, old_ka;
90 int ret;
91
92 if (act) {
93 old_sigset_t mask;
94 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
95 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
96 __get_user(new_ka.sa.sa_flags, &act->sa_flags))
97 return -EFAULT;
98 __get_user(mask, &act->sa_mask);
99 siginitset(&new_ka.sa.sa_mask, mask);
100 new_ka.ka_restorer = NULL;
101 }
102
103 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
104
105 if (!ret && oact) {
106 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
107 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
108 __put_user(old_ka.sa.sa_flags, &oact->sa_flags))
109 return -EFAULT;
110 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
111 }
112
113 return ret;
114}
115
116asmlinkage long
117sys_rt_sigaction(int sig, const struct sigaction __user *act,
118 struct sigaction __user *oact,
119 size_t sigsetsize, void __user *restorer)
120{
121 struct k_sigaction new_ka, old_ka;
122 int ret;
123
124 /* XXX: Don't preclude handling different sized sigset_t's. */
125 if (sigsetsize != sizeof(sigset_t))
126 return -EINVAL;
127
128 if (act) {
129 new_ka.ka_restorer = restorer;
130 if (copy_from_user(&new_ka.sa, act, sizeof(*act)))
131 return -EFAULT;
132 }
133
134 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
135
136 if (!ret && oact) {
137 if (copy_to_user(oact, &old_ka.sa, sizeof(*oact)))
138 return -EFAULT;
139 }
140
141 return ret;
142}
143
144/*
145 * Atomically swap in the new signal mask, and wait for a signal.
146 */
147asmlinkage int
148do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw)
149{
150 sigset_t oldset;
151
152 mask &= _BLOCKABLE;
153 spin_lock_irq(&current->sighand->siglock);
154 oldset = current->blocked;
155 siginitset(&current->blocked, mask);
156 recalc_sigpending();
157 spin_unlock_irq(&current->sighand->siglock);
158
159 /* Indicate EINTR on return from any possible signal handler,
160 which will not come back through here, but via sigreturn. */
161 regs->r0 = EINTR;
162 regs->r19 = 1;
163
164 while (1) {
165 current->state = TASK_INTERRUPTIBLE;
166 schedule();
167 if (do_signal(&oldset, regs, sw, 0, 0))
168 return -EINTR;
169 }
170}
171
172asmlinkage int
173do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize,
174 struct pt_regs *regs, struct switch_stack *sw)
175{
176 sigset_t oldset, set;
177
178 /* XXX: Don't preclude handling different sized sigset_t's. */
179 if (sigsetsize != sizeof(sigset_t))
180 return -EINVAL;
181 if (copy_from_user(&set, uset, sizeof(set)))
182 return -EFAULT;
183
184 sigdelsetmask(&set, ~_BLOCKABLE);
185 spin_lock_irq(&current->sighand->siglock);
186 oldset = current->blocked;
187 current->blocked = set;
188 recalc_sigpending();
189 spin_unlock_irq(&current->sighand->siglock);
190
191 /* Indicate EINTR on return from any possible signal handler,
192 which will not come back through here, but via sigreturn. */
193 regs->r0 = EINTR;
194 regs->r19 = 1;
195
196 while (1) {
197 current->state = TASK_INTERRUPTIBLE;
198 schedule();
199 if (do_signal(&oldset, regs, sw, 0, 0))
200 return -EINTR;
201 }
202}
203
204asmlinkage int
205sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
206{
207 return do_sigaltstack(uss, uoss, rdusp());
208}
209
210/*
211 * Do a signal return; undo the signal stack.
212 */
213
214#if _NSIG_WORDS > 1
215# error "Non SA_SIGINFO frame needs rearranging"
216#endif
217
218struct sigframe
219{
220 struct sigcontext sc;
221 unsigned int retcode[3];
222};
223
224struct rt_sigframe
225{
226 struct siginfo info;
227 struct ucontext uc;
228 unsigned int retcode[3];
229};
230
231/* If this changes, userland unwinders that Know Things about our signal
232 frame will break. Do not undertake lightly. It also implies an ABI
233 change wrt the size of siginfo_t, which may cause some pain. */
234extern char compile_time_assert
235 [offsetof(struct rt_sigframe, uc.uc_mcontext) == 176 ? 1 : -1];
236
237#define INSN_MOV_R30_R16 0x47fe0410
238#define INSN_LDI_R0 0x201f0000
239#define INSN_CALLSYS 0x00000083
240
241static long
242restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
243 struct switch_stack *sw)
244{
245 unsigned long usp;
246 long i, err = __get_user(regs->pc, &sc->sc_pc);
247
248 sw->r26 = (unsigned long) ret_from_sys_call;
249
250 err |= __get_user(regs->r0, sc->sc_regs+0);
251 err |= __get_user(regs->r1, sc->sc_regs+1);
252 err |= __get_user(regs->r2, sc->sc_regs+2);
253 err |= __get_user(regs->r3, sc->sc_regs+3);
254 err |= __get_user(regs->r4, sc->sc_regs+4);
255 err |= __get_user(regs->r5, sc->sc_regs+5);
256 err |= __get_user(regs->r6, sc->sc_regs+6);
257 err |= __get_user(regs->r7, sc->sc_regs+7);
258 err |= __get_user(regs->r8, sc->sc_regs+8);
259 err |= __get_user(sw->r9, sc->sc_regs+9);
260 err |= __get_user(sw->r10, sc->sc_regs+10);
261 err |= __get_user(sw->r11, sc->sc_regs+11);
262 err |= __get_user(sw->r12, sc->sc_regs+12);
263 err |= __get_user(sw->r13, sc->sc_regs+13);
264 err |= __get_user(sw->r14, sc->sc_regs+14);
265 err |= __get_user(sw->r15, sc->sc_regs+15);
266 err |= __get_user(regs->r16, sc->sc_regs+16);
267 err |= __get_user(regs->r17, sc->sc_regs+17);
268 err |= __get_user(regs->r18, sc->sc_regs+18);
269 err |= __get_user(regs->r19, sc->sc_regs+19);
270 err |= __get_user(regs->r20, sc->sc_regs+20);
271 err |= __get_user(regs->r21, sc->sc_regs+21);
272 err |= __get_user(regs->r22, sc->sc_regs+22);
273 err |= __get_user(regs->r23, sc->sc_regs+23);
274 err |= __get_user(regs->r24, sc->sc_regs+24);
275 err |= __get_user(regs->r25, sc->sc_regs+25);
276 err |= __get_user(regs->r26, sc->sc_regs+26);
277 err |= __get_user(regs->r27, sc->sc_regs+27);
278 err |= __get_user(regs->r28, sc->sc_regs+28);
279 err |= __get_user(regs->gp, sc->sc_regs+29);
280 err |= __get_user(usp, sc->sc_regs+30);
281 wrusp(usp);
282
283 for (i = 0; i < 31; i++)
284 err |= __get_user(sw->fp[i], sc->sc_fpregs+i);
285 err |= __get_user(sw->fp[31], &sc->sc_fpcr);
286
287 return err;
288}
289
290/* Note that this syscall is also used by setcontext(3) to install
291 a given sigcontext. This because it's impossible to set *all*
292 registers and transfer control from userland. */
293
294asmlinkage void
295do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs,
296 struct switch_stack *sw)
297{
298 sigset_t set;
299
300 /* Verify that it's a good sigcontext before using it */
301 if (!access_ok(VERIFY_READ, sc, sizeof(*sc)))
302 goto give_sigsegv;
303 if (__get_user(set.sig[0], &sc->sc_mask))
304 goto give_sigsegv;
305
306 sigdelsetmask(&set, ~_BLOCKABLE);
307 spin_lock_irq(&current->sighand->siglock);
308 current->blocked = set;
309 recalc_sigpending();
310 spin_unlock_irq(&current->sighand->siglock);
311
312 if (restore_sigcontext(sc, regs, sw))
313 goto give_sigsegv;
314
315 /* Send SIGTRAP if we're single-stepping: */
316 if (ptrace_cancel_bpt (current)) {
317 siginfo_t info;
318
319 info.si_signo = SIGTRAP;
320 info.si_errno = 0;
321 info.si_code = TRAP_BRKPT;
322 info.si_addr = (void __user *) regs->pc;
323 info.si_trapno = 0;
324 send_sig_info(SIGTRAP, &info, current);
325 }
326 return;
327
328give_sigsegv:
329 force_sig(SIGSEGV, current);
330}
331
332asmlinkage void
333do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs,
334 struct switch_stack *sw)
335{
336 sigset_t set;
337
338 /* Verify that it's a good ucontext_t before using it */
339 if (!access_ok(VERIFY_READ, &frame->uc, sizeof(frame->uc)))
340 goto give_sigsegv;
341 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
342 goto give_sigsegv;
343
344 sigdelsetmask(&set, ~_BLOCKABLE);
345 spin_lock_irq(&current->sighand->siglock);
346 current->blocked = set;
347 recalc_sigpending();
348 spin_unlock_irq(&current->sighand->siglock);
349
350 if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw))
351 goto give_sigsegv;
352
353 /* Send SIGTRAP if we're single-stepping: */
354 if (ptrace_cancel_bpt (current)) {
355 siginfo_t info;
356
357 info.si_signo = SIGTRAP;
358 info.si_errno = 0;
359 info.si_code = TRAP_BRKPT;
360 info.si_addr = (void __user *) regs->pc;
361 info.si_trapno = 0;
362 send_sig_info(SIGTRAP, &info, current);
363 }
364 return;
365
366give_sigsegv:
367 force_sig(SIGSEGV, current);
368}
369
370
371/*
372 * Set up a signal frame.
373 */
374
375static inline void __user *
376get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
377{
378 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
379 sp = current->sas_ss_sp + current->sas_ss_size;
380
381 return (void __user *)((sp - frame_size) & -32ul);
382}
383
384static long
385setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
386 struct switch_stack *sw, unsigned long mask, unsigned long sp)
387{
388 long i, err = 0;
389
390 err |= __put_user(on_sig_stack((unsigned long)sc), &sc->sc_onstack);
391 err |= __put_user(mask, &sc->sc_mask);
392 err |= __put_user(regs->pc, &sc->sc_pc);
393 err |= __put_user(8, &sc->sc_ps);
394
395 err |= __put_user(regs->r0 , sc->sc_regs+0);
396 err |= __put_user(regs->r1 , sc->sc_regs+1);
397 err |= __put_user(regs->r2 , sc->sc_regs+2);
398 err |= __put_user(regs->r3 , sc->sc_regs+3);
399 err |= __put_user(regs->r4 , sc->sc_regs+4);
400 err |= __put_user(regs->r5 , sc->sc_regs+5);
401 err |= __put_user(regs->r6 , sc->sc_regs+6);
402 err |= __put_user(regs->r7 , sc->sc_regs+7);
403 err |= __put_user(regs->r8 , sc->sc_regs+8);
404 err |= __put_user(sw->r9 , sc->sc_regs+9);
405 err |= __put_user(sw->r10 , sc->sc_regs+10);
406 err |= __put_user(sw->r11 , sc->sc_regs+11);
407 err |= __put_user(sw->r12 , sc->sc_regs+12);
408 err |= __put_user(sw->r13 , sc->sc_regs+13);
409 err |= __put_user(sw->r14 , sc->sc_regs+14);
410 err |= __put_user(sw->r15 , sc->sc_regs+15);
411 err |= __put_user(regs->r16, sc->sc_regs+16);
412 err |= __put_user(regs->r17, sc->sc_regs+17);
413 err |= __put_user(regs->r18, sc->sc_regs+18);
414 err |= __put_user(regs->r19, sc->sc_regs+19);
415 err |= __put_user(regs->r20, sc->sc_regs+20);
416 err |= __put_user(regs->r21, sc->sc_regs+21);
417 err |= __put_user(regs->r22, sc->sc_regs+22);
418 err |= __put_user(regs->r23, sc->sc_regs+23);
419 err |= __put_user(regs->r24, sc->sc_regs+24);
420 err |= __put_user(regs->r25, sc->sc_regs+25);
421 err |= __put_user(regs->r26, sc->sc_regs+26);
422 err |= __put_user(regs->r27, sc->sc_regs+27);
423 err |= __put_user(regs->r28, sc->sc_regs+28);
424 err |= __put_user(regs->gp , sc->sc_regs+29);
425 err |= __put_user(sp, sc->sc_regs+30);
426 err |= __put_user(0, sc->sc_regs+31);
427
428 for (i = 0; i < 31; i++)
429 err |= __put_user(sw->fp[i], sc->sc_fpregs+i);
430 err |= __put_user(0, sc->sc_fpregs+31);
431 err |= __put_user(sw->fp[31], &sc->sc_fpcr);
432
433 err |= __put_user(regs->trap_a0, &sc->sc_traparg_a0);
434 err |= __put_user(regs->trap_a1, &sc->sc_traparg_a1);
435 err |= __put_user(regs->trap_a2, &sc->sc_traparg_a2);
436
437 return err;
438}
439
440static void
441setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
442 struct pt_regs *regs, struct switch_stack * sw)
443{
444 unsigned long oldsp, r26, err = 0;
445 struct sigframe __user *frame;
446
447 oldsp = rdusp();
448 frame = get_sigframe(ka, oldsp, sizeof(*frame));
449 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
450 goto give_sigsegv;
451
452 err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp);
453 if (err)
454 goto give_sigsegv;
455
456 /* Set up to return from userspace. If provided, use a stub
457 already in userspace. */
458 if (ka->ka_restorer) {
459 r26 = (unsigned long) ka->ka_restorer;
460 } else {
461 err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
462 err |= __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1);
463 err |= __put_user(INSN_CALLSYS, frame->retcode+2);
464 imb();
465 r26 = (unsigned long) frame->retcode;
466 }
467
468 /* Check that everything was written properly. */
469 if (err)
470 goto give_sigsegv;
471
472 /* "Return" to the handler */
473 regs->r26 = r26;
474 regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler;
475 regs->r16 = sig; /* a0: signal number */
476 regs->r17 = 0; /* a1: exception code */
477 regs->r18 = (unsigned long) &frame->sc; /* a2: sigcontext pointer */
478 wrusp((unsigned long) frame);
479
480#if DEBUG_SIG
481 printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
482 current->comm, current->pid, frame, regs->pc, regs->r26);
483#endif
484
485 return;
486
487give_sigsegv:
488 force_sigsegv(sig, current);
489}
490
491static void
492setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
493 sigset_t *set, struct pt_regs *regs, struct switch_stack * sw)
494{
495 unsigned long oldsp, r26, err = 0;
496 struct rt_sigframe __user *frame;
497
498 oldsp = rdusp();
499 frame = get_sigframe(ka, oldsp, sizeof(*frame));
500 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
501 goto give_sigsegv;
502
503 err |= copy_siginfo_to_user(&frame->info, info);
504
505 /* Create the ucontext. */
506 err |= __put_user(0, &frame->uc.uc_flags);
507 err |= __put_user(0, &frame->uc.uc_link);
508 err |= __put_user(set->sig[0], &frame->uc.uc_osf_sigmask);
509 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
510 err |= __put_user(sas_ss_flags(oldsp), &frame->uc.uc_stack.ss_flags);
511 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
512 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, sw,
513 set->sig[0], oldsp);
514 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
515 if (err)
516 goto give_sigsegv;
517
518 /* Set up to return from userspace. If provided, use a stub
519 already in userspace. */
520 if (ka->ka_restorer) {
521 r26 = (unsigned long) ka->ka_restorer;
522 } else {
523 err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
524 err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn,
525 frame->retcode+1);
526 err |= __put_user(INSN_CALLSYS, frame->retcode+2);
527 imb();
528 r26 = (unsigned long) frame->retcode;
529 }
530
531 if (err)
532 goto give_sigsegv;
533
534 /* "Return" to the handler */
535 regs->r26 = r26;
536 regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler;
537 regs->r16 = sig; /* a0: signal number */
538 regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */
539 regs->r18 = (unsigned long) &frame->uc; /* a2: ucontext pointer */
540 wrusp((unsigned long) frame);
541
542#if DEBUG_SIG
543 printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
544 current->comm, current->pid, frame, regs->pc, regs->r26);
545#endif
546
547 return;
548
549give_sigsegv:
550 force_sigsegv(sig, current);
551}
552
553
554/*
555 * OK, we're invoking a handler.
556 */
557static inline void
558handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
559 sigset_t *oldset, struct pt_regs * regs, struct switch_stack *sw)
560{
561 if (ka->sa.sa_flags & SA_SIGINFO)
562 setup_rt_frame(sig, ka, info, oldset, regs, sw);
563 else
564 setup_frame(sig, ka, oldset, regs, sw);
565
566 if (ka->sa.sa_flags & SA_RESETHAND)
567 ka->sa.sa_handler = SIG_DFL;
568
569 if (!(ka->sa.sa_flags & SA_NODEFER)) {
570 spin_lock_irq(&current->sighand->siglock);
571 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
572 sigaddset(&current->blocked,sig);
573 recalc_sigpending();
574 spin_unlock_irq(&current->sighand->siglock);
575 }
576}
577
578static inline void
579syscall_restart(unsigned long r0, unsigned long r19,
580 struct pt_regs *regs, struct k_sigaction *ka)
581{
582 switch (regs->r0) {
583 case ERESTARTSYS:
584 if (!(ka->sa.sa_flags & SA_RESTART)) {
585 case ERESTARTNOHAND:
586 regs->r0 = EINTR;
587 break;
588 }
589 /* fallthrough */
590 case ERESTARTNOINTR:
591 regs->r0 = r0; /* reset v0 and a3 and replay syscall */
592 regs->r19 = r19;
593 regs->pc -= 4;
594 break;
595 case ERESTART_RESTARTBLOCK:
596 current_thread_info()->restart_block.fn = do_no_restart_syscall;
597 regs->r0 = EINTR;
598 break;
599 }
600}
601
602
603/*
604 * Note that 'init' is a special process: it doesn't get signals it doesn't
605 * want to handle. Thus you cannot kill init even with a SIGKILL even by
606 * mistake.
607 *
608 * Note that we go through the signals twice: once to check the signals that
609 * the kernel can handle, and then we build all the user-level signal handling
610 * stack-frames in one go after that.
611 *
612 * "r0" and "r19" are the registers we need to restore for system call
613 * restart. "r0" is also used as an indicator whether we can restart at
614 * all (if we get here from anything but a syscall return, it will be 0)
615 */
616static int
617do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw,
618 unsigned long r0, unsigned long r19)
619{
620 siginfo_t info;
621 int signr;
622 unsigned long single_stepping = ptrace_cancel_bpt(current);
623 struct k_sigaction ka;
624
625 if (!oldset)
626 oldset = &current->blocked;
627
628 /* This lets the debugger run, ... */
629 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
630 /* ... so re-check the single stepping. */
631 single_stepping |= ptrace_cancel_bpt(current);
632
633 if (signr > 0) {
634 /* Whee! Actually deliver the signal. */
635 if (r0) syscall_restart(r0, r19, regs, &ka);
636 handle_signal(signr, &ka, &info, oldset, regs, sw);
637 if (single_stepping)
638 ptrace_set_bpt(current); /* re-set bpt */
639 return 1;
640 }
641
642 if (r0) {
643 switch (regs->r0) {
644 case ERESTARTNOHAND:
645 case ERESTARTSYS:
646 case ERESTARTNOINTR:
647 /* Reset v0 and a3 and replay syscall. */
648 regs->r0 = r0;
649 regs->r19 = r19;
650 regs->pc -= 4;
651 break;
652 case ERESTART_RESTARTBLOCK:
653 /* Force v0 to the restart syscall and reply. */
654 regs->r0 = __NR_restart_syscall;
655 regs->pc -= 4;
656 break;
657 }
658 }
659 if (single_stepping)
660 ptrace_set_bpt(current); /* re-set breakpoint */
661
662 return 0;
663}
664
665void
666do_notify_resume(sigset_t *oldset, struct pt_regs *regs,
667 struct switch_stack *sw, unsigned long r0,
668 unsigned long r19, unsigned long thread_info_flags)
669{
670 if (thread_info_flags & _TIF_SIGPENDING)
671 do_signal(oldset, regs, sw, r0, r19);
672}
diff --git a/arch/alpha/kernel/smc37c669.c b/arch/alpha/kernel/smc37c669.c
new file mode 100644
index 000000000000..fd467b207f0f
--- /dev/null
+++ b/arch/alpha/kernel/smc37c669.c
@@ -0,0 +1,2554 @@
1/*
2 * SMC 37C669 initialization code
3 */
4#include <linux/kernel.h>
5
6#include <linux/slab.h>
7#include <linux/mm.h>
8#include <linux/init.h>
9#include <linux/delay.h>
10#include <linux/spinlock.h>
11
12#include <asm/hwrpb.h>
13#include <asm/io.h>
14#include <asm/segment.h>
15
16#if 0
17# define DBG_DEVS(args) printk args
18#else
19# define DBG_DEVS(args)
20#endif
21
22#define KB 1024
23#define MB (1024*KB)
24#define GB (1024*MB)
25
26#define SMC_DEBUG 0
27
28/* File: smcc669_def.h
29 *
30 * Copyright (C) 1997 by
31 * Digital Equipment Corporation, Maynard, Massachusetts.
32 * All rights reserved.
33 *
34 * This software is furnished under a license and may be used and copied
35 * only in accordance of the terms of such license and with the
36 * inclusion of the above copyright notice. This software or any other
37 * copies thereof may not be provided or otherwise made available to any
38 * other person. No title to and ownership of the software is hereby
39 * transferred.
40 *
41 * The information in this software is subject to change without notice
42 * and should not be construed as a commitment by Digital Equipment
43 * Corporation.
44 *
45 * Digital assumes no responsibility for the use or reliability of its
46 * software on equipment which is not supplied by Digital.
47 *
48 *
49 * Abstract:
50 *
51 * This file contains header definitions for the SMC37c669
52 * Super I/O controller.
53 *
54 * Author:
55 *
56 * Eric Rasmussen
57 *
58 * Modification History:
59 *
60 * er 28-Jan-1997 Initial Entry
61 */
62
63#ifndef __SMC37c669_H
64#define __SMC37c669_H
65
66/*
67** Macros for handling device IRQs
68**
69** The mask acts as a flag used in mapping actual ISA IRQs (0 - 15)
70** to device IRQs (A - H).
71*/
72#define SMC37c669_DEVICE_IRQ_MASK 0x80000000
73#define SMC37c669_DEVICE_IRQ( __i ) \
74 ((SMC37c669_DEVICE_IRQ_MASK) | (__i))
75#define SMC37c669_IS_DEVICE_IRQ(__i) \
76 (((__i) & (SMC37c669_DEVICE_IRQ_MASK)) == (SMC37c669_DEVICE_IRQ_MASK))
77#define SMC37c669_RAW_DEVICE_IRQ(__i) \
78 ((__i) & ~(SMC37c669_DEVICE_IRQ_MASK))
79
80/*
81** Macros for handling device DRQs
82**
83** The mask acts as a flag used in mapping actual ISA DMA
84** channels to device DMA channels (A - C).
85*/
86#define SMC37c669_DEVICE_DRQ_MASK 0x80000000
87#define SMC37c669_DEVICE_DRQ(__d) \
88 ((SMC37c669_DEVICE_DRQ_MASK) | (__d))
89#define SMC37c669_IS_DEVICE_DRQ(__d) \
90 (((__d) & (SMC37c669_DEVICE_DRQ_MASK)) == (SMC37c669_DEVICE_DRQ_MASK))
91#define SMC37c669_RAW_DEVICE_DRQ(__d) \
92 ((__d) & ~(SMC37c669_DEVICE_DRQ_MASK))
93
94#define SMC37c669_DEVICE_ID 0x3
95
96/*
97** SMC37c669 Device Function Definitions
98*/
99#define SERIAL_0 0
100#define SERIAL_1 1
101#define PARALLEL_0 2
102#define FLOPPY_0 3
103#define IDE_0 4
104#define NUM_FUNCS 5
105
106/*
107** Default Device Function Mappings
108*/
109#define COM1_BASE 0x3F8
110#define COM1_IRQ 4
111#define COM2_BASE 0x2F8
112#define COM2_IRQ 3
113#define PARP_BASE 0x3BC
114#define PARP_IRQ 7
115#define PARP_DRQ 3
116#define FDC_BASE 0x3F0
117#define FDC_IRQ 6
118#define FDC_DRQ 2
119
120/*
121** Configuration On/Off Key Definitions
122*/
123#define SMC37c669_CONFIG_ON_KEY 0x55
124#define SMC37c669_CONFIG_OFF_KEY 0xAA
125
126/*
127** SMC 37c669 Device IRQs
128*/
129#define SMC37c669_DEVICE_IRQ_A ( SMC37c669_DEVICE_IRQ( 0x01 ) )
130#define SMC37c669_DEVICE_IRQ_B ( SMC37c669_DEVICE_IRQ( 0x02 ) )
131#define SMC37c669_DEVICE_IRQ_C ( SMC37c669_DEVICE_IRQ( 0x03 ) )
132#define SMC37c669_DEVICE_IRQ_D ( SMC37c669_DEVICE_IRQ( 0x04 ) )
133#define SMC37c669_DEVICE_IRQ_E ( SMC37c669_DEVICE_IRQ( 0x05 ) )
134#define SMC37c669_DEVICE_IRQ_F ( SMC37c669_DEVICE_IRQ( 0x06 ) )
135/* SMC37c669_DEVICE_IRQ_G *** RESERVED ***/
136#define SMC37c669_DEVICE_IRQ_H ( SMC37c669_DEVICE_IRQ( 0x08 ) )
137
138/*
139** SMC 37c669 Device DMA Channel Definitions
140*/
141#define SMC37c669_DEVICE_DRQ_A ( SMC37c669_DEVICE_DRQ( 0x01 ) )
142#define SMC37c669_DEVICE_DRQ_B ( SMC37c669_DEVICE_DRQ( 0x02 ) )
143#define SMC37c669_DEVICE_DRQ_C ( SMC37c669_DEVICE_DRQ( 0x03 ) )
144
145/*
146** Configuration Register Index Definitions
147*/
148#define SMC37c669_CR00_INDEX 0x00
149#define SMC37c669_CR01_INDEX 0x01
150#define SMC37c669_CR02_INDEX 0x02
151#define SMC37c669_CR03_INDEX 0x03
152#define SMC37c669_CR04_INDEX 0x04
153#define SMC37c669_CR05_INDEX 0x05
154#define SMC37c669_CR06_INDEX 0x06
155#define SMC37c669_CR07_INDEX 0x07
156#define SMC37c669_CR08_INDEX 0x08
157#define SMC37c669_CR09_INDEX 0x09
158#define SMC37c669_CR0A_INDEX 0x0A
159#define SMC37c669_CR0B_INDEX 0x0B
160#define SMC37c669_CR0C_INDEX 0x0C
161#define SMC37c669_CR0D_INDEX 0x0D
162#define SMC37c669_CR0E_INDEX 0x0E
163#define SMC37c669_CR0F_INDEX 0x0F
164#define SMC37c669_CR10_INDEX 0x10
165#define SMC37c669_CR11_INDEX 0x11
166#define SMC37c669_CR12_INDEX 0x12
167#define SMC37c669_CR13_INDEX 0x13
168#define SMC37c669_CR14_INDEX 0x14
169#define SMC37c669_CR15_INDEX 0x15
170#define SMC37c669_CR16_INDEX 0x16
171#define SMC37c669_CR17_INDEX 0x17
172#define SMC37c669_CR18_INDEX 0x18
173#define SMC37c669_CR19_INDEX 0x19
174#define SMC37c669_CR1A_INDEX 0x1A
175#define SMC37c669_CR1B_INDEX 0x1B
176#define SMC37c669_CR1C_INDEX 0x1C
177#define SMC37c669_CR1D_INDEX 0x1D
178#define SMC37c669_CR1E_INDEX 0x1E
179#define SMC37c669_CR1F_INDEX 0x1F
180#define SMC37c669_CR20_INDEX 0x20
181#define SMC37c669_CR21_INDEX 0x21
182#define SMC37c669_CR22_INDEX 0x22
183#define SMC37c669_CR23_INDEX 0x23
184#define SMC37c669_CR24_INDEX 0x24
185#define SMC37c669_CR25_INDEX 0x25
186#define SMC37c669_CR26_INDEX 0x26
187#define SMC37c669_CR27_INDEX 0x27
188#define SMC37c669_CR28_INDEX 0x28
189#define SMC37c669_CR29_INDEX 0x29
190
191/*
192** Configuration Register Alias Definitions
193*/
194#define SMC37c669_DEVICE_ID_INDEX SMC37c669_CR0D_INDEX
195#define SMC37c669_DEVICE_REVISION_INDEX SMC37c669_CR0E_INDEX
196#define SMC37c669_FDC_BASE_ADDRESS_INDEX SMC37c669_CR20_INDEX
197#define SMC37c669_IDE_BASE_ADDRESS_INDEX SMC37c669_CR21_INDEX
198#define SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX SMC37c669_CR22_INDEX
199#define SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX SMC37c669_CR23_INDEX
200#define SMC37c669_SERIAL0_BASE_ADDRESS_INDEX SMC37c669_CR24_INDEX
201#define SMC37c669_SERIAL1_BASE_ADDRESS_INDEX SMC37c669_CR25_INDEX
202#define SMC37c669_PARALLEL_FDC_DRQ_INDEX SMC37c669_CR26_INDEX
203#define SMC37c669_PARALLEL_FDC_IRQ_INDEX SMC37c669_CR27_INDEX
204#define SMC37c669_SERIAL_IRQ_INDEX SMC37c669_CR28_INDEX
205
206/*
207** Configuration Register Definitions
208**
209** The INDEX (write only) and DATA (read/write) ports are effective
210** only when the chip is in the Configuration State.
211*/
212typedef struct _SMC37c669_CONFIG_REGS {
213 unsigned char index_port;
214 unsigned char data_port;
215} SMC37c669_CONFIG_REGS;
216
217/*
218** CR00 - default value 0x28
219**
220** IDE_EN (CR00<1:0>):
221** 0x - 30ua pull-ups on nIDEEN, nHDCS0, NHDCS1
222** 11 - IRQ_H available as IRQ output,
223** IRRX2, IRTX2 available as alternate IR pins
224** 10 - nIDEEN, nHDCS0, nHDCS1 used to control IDE
225**
226** VALID (CR00<7>):
227** A high level on this software controlled bit can
228** be used to indicate that a valid configuration
229** cycle has occurred. The control software must
230** take care to set this bit at the appropriate times.
231** Set to zero after power up. This bit has no
232** effect on any other hardware in the chip.
233**
234*/
235typedef union _SMC37c669_CR00 {
236 unsigned char as_uchar;
237 struct {
238 unsigned ide_en : 2; /* See note above */
239 unsigned reserved1 : 1; /* RAZ */
240 unsigned fdc_pwr : 1; /* 1 = supply power to FDC */
241 unsigned reserved2 : 3; /* Read as 010b */
242 unsigned valid : 1; /* See note above */
243 } by_field;
244} SMC37c669_CR00;
245
246/*
247** CR01 - default value 0x9C
248*/
249typedef union _SMC37c669_CR01 {
250 unsigned char as_uchar;
251 struct {
252 unsigned reserved1 : 2; /* RAZ */
253 unsigned ppt_pwr : 1; /* 1 = supply power to PPT */
254 unsigned ppt_mode : 1; /* 1 = Printer mode, 0 = EPP */
255 unsigned reserved2 : 1; /* Read as 1 */
256 unsigned reserved3 : 2; /* RAZ */
257 unsigned lock_crx: 1; /* Lock CR00 - CR18 */
258 } by_field;
259} SMC37c669_CR01;
260
261/*
262** CR02 - default value 0x88
263*/
264typedef union _SMC37c669_CR02 {
265 unsigned char as_uchar;
266 struct {
267 unsigned reserved1 : 3; /* RAZ */
268 unsigned uart1_pwr : 1; /* 1 = supply power to UART1 */
269 unsigned reserved2 : 3; /* RAZ */
270 unsigned uart2_pwr : 1; /* 1 = supply power to UART2 */
271 } by_field;
272} SMC37c669_CR02;
273
274/*
275** CR03 - default value 0x78
276**
277** CR03<7> CR03<2> Pin 94
278** ------- ------- ------
279** 0 X DRV2 (input)
280** 1 0 ADRX
281** 1 1 IRQ_B
282**
283** CR03<6> CR03<5> Op Mode
284** ------- ------- -------
285** 0 0 Model 30
286** 0 1 PS/2
287** 1 0 Reserved
288** 1 1 AT Mode
289*/
290typedef union _SMC37c669_CR03 {
291 unsigned char as_uchar;
292 struct {
293 unsigned pwrgd_gamecs : 1; /* 1 = PWRGD, 0 = GAMECS */
294 unsigned fdc_mode2 : 1; /* 1 = Enhanced Mode 2 */
295 unsigned pin94_0 : 1; /* See note above */
296 unsigned reserved1 : 1; /* RAZ */
297 unsigned drvden : 1; /* 1 = high, 0 - output */
298 unsigned op_mode : 2; /* See note above */
299 unsigned pin94_1 : 1; /* See note above */
300 } by_field;
301} SMC37c669_CR03;
302
303/*
304** CR04 - default value 0x00
305**
306** PP_EXT_MODE:
307** If CR01<PP_MODE> = 0 and PP_EXT_MODE =
308** 00 - Standard and Bidirectional
309** 01 - EPP mode and SPP
310** 10 - ECP mode
311** In this mode, 2 drives can be supported
312** directly, 3 or 4 drives must use external
313** 4 drive support. SPP can be selected
314** through the ECR register of ECP as mode 000.
315** 11 - ECP mode and EPP mode
316** In this mode, 2 drives can be supported
317** directly, 3 or 4 drives must use external
318** 4 drive support. SPP can be selected
319** through the ECR register of ECP as mode 000.
320** In this mode, EPP can be selected through
321** the ECR register of ECP as mode 100.
322**
323** PP_FDC:
324** 00 - Normal
325** 01 - PPFD1
326** 10 - PPFD2
327** 11 - Reserved
328**
329** MIDI1:
330** Serial Clock Select:
331** A low level on this bit disables MIDI support,
332** clock = divide by 13. A high level on this
333** bit enables MIDI support, clock = divide by 12.
334**
335** MIDI operates at 31.25 Kbps which can be derived
336** from 125 KHz (24 MHz / 12 = 2 MHz, 2 MHz / 16 = 125 KHz)
337**
338** ALT_IO:
339** 0 - Use pins IRRX, IRTX
340** 1 - Use pins IRRX2, IRTX2
341**
342** If this bit is set, the IR receive and transmit
343** functions will not be available on pins 25 and 26
344** unless CR00<IDE_EN> = 11.
345*/
346typedef union _SMC37c669_CR04 {
347 unsigned char as_uchar;
348 struct {
349 unsigned ppt_ext_mode : 2; /* See note above */
350 unsigned ppt_fdc : 2; /* See note above */
351 unsigned midi1 : 1; /* See note above */
352 unsigned midi2 : 1; /* See note above */
353 unsigned epp_type : 1; /* 0 = EPP 1.9, 1 = EPP 1.7 */
354 unsigned alt_io : 1; /* See note above */
355 } by_field;
356} SMC37c669_CR04;
357
358/*
359** CR05 - default value 0x00
360**
361** DEN_SEL:
362** 00 - Densel output normal
363** 01 - Reserved
364** 10 - Densel output 1
365** 11 - Densel output 0
366**
367*/
368typedef union _SMC37c669_CR05 {
369 unsigned char as_uchar;
370 struct {
371 unsigned reserved1 : 2; /* RAZ */
372 unsigned fdc_dma_mode : 1; /* 0 = burst, 1 = non-burst */
373 unsigned den_sel : 2; /* See note above */
374 unsigned swap_drv : 1; /* Swap the FDC motor selects */
375 unsigned extx4 : 1; /* 0 = 2 drive, 1 = external 4 drive decode */
376 unsigned reserved2 : 1; /* RAZ */
377 } by_field;
378} SMC37c669_CR05;
379
380/*
381** CR06 - default value 0xFF
382*/
383typedef union _SMC37c669_CR06 {
384 unsigned char as_uchar;
385 struct {
386 unsigned floppy_a : 2; /* Type of floppy drive A */
387 unsigned floppy_b : 2; /* Type of floppy drive B */
388 unsigned floppy_c : 2; /* Type of floppy drive C */
389 unsigned floppy_d : 2; /* Type of floppy drive D */
390 } by_field;
391} SMC37c669_CR06;
392
393/*
394** CR07 - default value 0x00
395**
396** Auto Power Management CR07<7:4>:
397** 0 - Auto Powerdown disabled (default)
398** 1 - Auto Powerdown enabled
399**
400** This bit is reset to the default state by POR or
401** a hardware reset.
402**
403*/
404typedef union _SMC37c669_CR07 {
405 unsigned char as_uchar;
406 struct {
407 unsigned floppy_boot : 2; /* 0 = A:, 1 = B: */
408 unsigned reserved1 : 2; /* RAZ */
409 unsigned ppt_en : 1; /* See note above */
410 unsigned uart1_en : 1; /* See note above */
411 unsigned uart2_en : 1; /* See note above */
412 unsigned fdc_en : 1; /* See note above */
413 } by_field;
414} SMC37c669_CR07;
415
416/*
417** CR08 - default value 0x00
418*/
419typedef union _SMC37c669_CR08 {
420 unsigned char as_uchar;
421 struct {
422 unsigned zero : 4; /* 0 */
423 unsigned addrx7_4 : 4; /* ADR<7:3> for ADRx decode */
424 } by_field;
425} SMC37c669_CR08;
426
427/*
428** CR09 - default value 0x00
429**
430** ADRx_CONFIG:
431** 00 - ADRx disabled
432** 01 - 1 byte decode A<3:0> = 0000b
433** 10 - 8 byte block decode A<3:0> = 0XXXb
434** 11 - 16 byte block decode A<3:0> = XXXXb
435**
436*/
437typedef union _SMC37c669_CR09 {
438 unsigned char as_uchar;
439 struct {
440 unsigned adra8 : 3; /* ADR<10:8> for ADRx decode */
441 unsigned reserved1 : 3;
442 unsigned adrx_config : 2; /* See note above */
443 } by_field;
444} SMC37c669_CR09;
445
446/*
447** CR0A - default value 0x00
448*/
449typedef union _SMC37c669_CR0A {
450 unsigned char as_uchar;
451 struct {
452 unsigned ecp_fifo_threshold : 4;
453 unsigned reserved1 : 4;
454 } by_field;
455} SMC37c669_CR0A;
456
457/*
458** CR0B - default value 0x00
459*/
460typedef union _SMC37c669_CR0B {
461 unsigned char as_uchar;
462 struct {
463 unsigned fdd0_drtx : 2; /* FDD0 Data Rate Table */
464 unsigned fdd1_drtx : 2; /* FDD1 Data Rate Table */
465 unsigned fdd2_drtx : 2; /* FDD2 Data Rate Table */
466 unsigned fdd3_drtx : 2; /* FDD3 Data Rate Table */
467 } by_field;
468} SMC37c669_CR0B;
469
470/*
471** CR0C - default value 0x00
472**
473** UART2_MODE:
474** 000 - Standard (default)
475** 001 - IrDA (HPSIR)
476** 010 - Amplitude Shift Keyed IR @500 KHz
477** 011 - Reserved
478** 1xx - Reserved
479**
480*/
481typedef union _SMC37c669_CR0C {
482 unsigned char as_uchar;
483 struct {
484 unsigned uart2_rcv_polarity : 1; /* 1 = invert RX */
485 unsigned uart2_xmit_polarity : 1; /* 1 = invert TX */
486 unsigned uart2_duplex : 1; /* 1 = full, 0 = half */
487 unsigned uart2_mode : 3; /* See note above */
488 unsigned uart1_speed : 1; /* 1 = high speed enabled */
489 unsigned uart2_speed : 1; /* 1 = high speed enabled */
490 } by_field;
491} SMC37c669_CR0C;
492
493/*
494** CR0D - default value 0x03
495**
496** Device ID Register - read only
497*/
498typedef union _SMC37c669_CR0D {
499 unsigned char as_uchar;
500 struct {
501 unsigned device_id : 8; /* Returns 0x3 in this field */
502 } by_field;
503} SMC37c669_CR0D;
504
505/*
506** CR0E - default value 0x02
507**
508** Device Revision Register - read only
509*/
510typedef union _SMC37c669_CR0E {
511 unsigned char as_uchar;
512 struct {
513 unsigned device_rev : 8; /* Returns 0x2 in this field */
514 } by_field;
515} SMC37c669_CR0E;
516
517/*
518** CR0F - default value 0x00
519*/
520typedef union _SMC37c669_CR0F {
521 unsigned char as_uchar;
522 struct {
523 unsigned test0 : 1; /* Reserved - set to 0 */
524 unsigned test1 : 1; /* Reserved - set to 0 */
525 unsigned test2 : 1; /* Reserved - set to 0 */
526 unsigned test3 : 1; /* Reserved - set t0 0 */
527 unsigned test4 : 1; /* Reserved - set to 0 */
528 unsigned test5 : 1; /* Reserved - set t0 0 */
529 unsigned test6 : 1; /* Reserved - set t0 0 */
530 unsigned test7 : 1; /* Reserved - set to 0 */
531 } by_field;
532} SMC37c669_CR0F;
533
534/*
535** CR10 - default value 0x00
536*/
537typedef union _SMC37c669_CR10 {
538 unsigned char as_uchar;
539 struct {
540 unsigned reserved1 : 3; /* RAZ */
541 unsigned pll_gain : 1; /* 1 = 3V, 2 = 5V operation */
542 unsigned pll_stop : 1; /* 1 = stop PLLs */
543 unsigned ace_stop : 1; /* 1 = stop UART clocks */
544 unsigned pll_clock_ctrl : 1; /* 0 = 14.318 MHz, 1 = 24 MHz */
545 unsigned ir_test : 1; /* Enable IR test mode */
546 } by_field;
547} SMC37c669_CR10;
548
549/*
550** CR11 - default value 0x00
551*/
552typedef union _SMC37c669_CR11 {
553 unsigned char as_uchar;
554 struct {
555 unsigned ir_loopback : 1; /* Internal IR loop back */
556 unsigned test_10ms : 1; /* Test 10ms autopowerdown FDC timeout */
557 unsigned reserved1 : 6; /* RAZ */
558 } by_field;
559} SMC37c669_CR11;
560
561/*
562** CR12 - CR1D are reserved registers
563*/
564
565/*
566** CR1E - default value 0x80
567**
568** GAMECS:
569** 00 - GAMECS disabled
570** 01 - 1 byte decode ADR<3:0> = 0001b
571** 10 - 8 byte block decode ADR<3:0> = 0XXXb
572** 11 - 16 byte block decode ADR<3:0> = XXXXb
573**
574*/
575typedef union _SMC37c66_CR1E {
576 unsigned char as_uchar;
577 struct {
578 unsigned gamecs_config: 2; /* See note above */
579 unsigned gamecs_addr9_4 : 6; /* GAMECS Addr<9:4> */
580 } by_field;
581} SMC37c669_CR1E;
582
583/*
584** CR1F - default value 0x00
585**
586** DT0 DT1 DRVDEN0 DRVDEN1 Drive Type
587** --- --- ------- ------- ----------
588** 0 0 DENSEL DRATE0 4/2/1 MB 3.5"
589** 2/1 MB 5.25"
590** 2/1.6/1 MB 3.5" (3-mode)
591** 0 1 DRATE1 DRATE0
592** 1 0 nDENSEL DRATE0 PS/2
593** 1 1 DRATE0 DRATE1
594**
595** Note: DENSEL, DRATE1, and DRATE0 map onto two output
596** pins - DRVDEN0 and DRVDEN1.
597**
598*/
599typedef union _SMC37c669_CR1F {
600 unsigned char as_uchar;
601 struct {
602 unsigned fdd0_drive_type : 2; /* FDD0 drive type */
603 unsigned fdd1_drive_type : 2; /* FDD1 drive type */
604 unsigned fdd2_drive_type : 2; /* FDD2 drive type */
605 unsigned fdd3_drive_type : 2; /* FDD3 drive type */
606 } by_field;
607} SMC37c669_CR1F;
608
609/*
610** CR20 - default value 0x3C
611**
612** FDC Base Address Register
613** - To disable this decode set Addr<9:8> = 0
614** - A<10> = 0, A<3:0> = 0XXXb to access.
615**
616*/
617typedef union _SMC37c669_CR20 {
618 unsigned char as_uchar;
619 struct {
620 unsigned zero : 2; /* 0 */
621 unsigned addr9_4 : 6; /* FDC Addr<9:4> */
622 } by_field;
623} SMC37c669_CR20;
624
625/*
626** CR21 - default value 0x3C
627**
628** IDE Base Address Register
629** - To disable this decode set Addr<9:8> = 0
630** - A<10> = 0, A<3:0> = 0XXXb to access.
631**
632*/
633typedef union _SMC37c669_CR21 {
634 unsigned char as_uchar;
635 struct {
636 unsigned zero : 2; /* 0 */
637 unsigned addr9_4 : 6; /* IDE Addr<9:4> */
638 } by_field;
639} SMC37c669_CR21;
640
641/*
642** CR22 - default value 0x3D
643**
644** IDE Alternate Status Base Address Register
645** - To disable this decode set Addr<9:8> = 0
646** - A<10> = 0, A<3:0> = 0110b to access.
647**
648*/
649typedef union _SMC37c669_CR22 {
650 unsigned char as_uchar;
651 struct {
652 unsigned zero : 2; /* 0 */
653 unsigned addr9_4 : 6; /* IDE Alt Status Addr<9:4> */
654 } by_field;
655} SMC37c669_CR22;
656
657/*
658** CR23 - default value 0x00
659**
660** Parallel Port Base Address Register
661** - To disable this decode set Addr<9:8> = 0
662** - A<10> = 0 to access.
663** - If EPP is enabled, A<2:0> = XXXb to access.
664** If EPP is NOT enabled, A<1:0> = XXb to access
665**
666*/
667typedef union _SMC37c669_CR23 {
668 unsigned char as_uchar;
669 struct {
670 unsigned addr9_2 : 8; /* Parallel Port Addr<9:2> */
671 } by_field;
672} SMC37c669_CR23;
673
674/*
675** CR24 - default value 0x00
676**
677** UART1 Base Address Register
678** - To disable this decode set Addr<9:8> = 0
679** - A<10> = 0, A<2:0> = XXXb to access.
680**
681*/
682typedef union _SMC37c669_CR24 {
683 unsigned char as_uchar;
684 struct {
685 unsigned zero : 1; /* 0 */
686 unsigned addr9_3 : 7; /* UART1 Addr<9:3> */
687 } by_field;
688} SMC37c669_CR24;
689
690/*
691** CR25 - default value 0x00
692**
693** UART2 Base Address Register
694** - To disable this decode set Addr<9:8> = 0
695** - A<10> = 0, A<2:0> = XXXb to access.
696**
697*/
698typedef union _SMC37c669_CR25 {
699 unsigned char as_uchar;
700 struct {
701 unsigned zero : 1; /* 0 */
702 unsigned addr9_3 : 7; /* UART2 Addr<9:3> */
703 } by_field;
704} SMC37c669_CR25;
705
706/*
707** CR26 - default value 0x00
708**
709** Parallel Port / FDC DMA Select Register
710**
711** D3 - D0 DMA
712** D7 - D4 Selected
713** ------- --------
714** 0000 None
715** 0001 DMA_A
716** 0010 DMA_B
717** 0011 DMA_C
718**
719*/
720typedef union _SMC37c669_CR26 {
721 unsigned char as_uchar;
722 struct {
723 unsigned ppt_drq : 4; /* See note above */
724 unsigned fdc_drq : 4; /* See note above */
725 } by_field;
726} SMC37c669_CR26;
727
728/*
729** CR27 - default value 0x00
730**
731** Parallel Port / FDC IRQ Select Register
732**
733** D3 - D0 IRQ
734** D7 - D4 Selected
735** ------- --------
736** 0000 None
737** 0001 IRQ_A
738** 0010 IRQ_B
739** 0011 IRQ_C
740** 0100 IRQ_D
741** 0101 IRQ_E
742** 0110 IRQ_F
743** 0111 Reserved
744** 1000 IRQ_H
745**
746** Any unselected IRQ REQ is in tristate
747**
748*/
749typedef union _SMC37c669_CR27 {
750 unsigned char as_uchar;
751 struct {
752 unsigned ppt_irq : 4; /* See note above */
753 unsigned fdc_irq : 4; /* See note above */
754 } by_field;
755} SMC37c669_CR27;
756
757/*
758** CR28 - default value 0x00
759**
760** UART IRQ Select Register
761**
762** D3 - D0 IRQ
763** D7 - D4 Selected
764** ------- --------
765** 0000 None
766** 0001 IRQ_A
767** 0010 IRQ_B
768** 0011 IRQ_C
769** 0100 IRQ_D
770** 0101 IRQ_E
771** 0110 IRQ_F
772** 0111 Reserved
773** 1000 IRQ_H
774** 1111 share with UART1 (only for UART2)
775**
776** Any unselected IRQ REQ is in tristate
777**
778** To share an IRQ between UART1 and UART2, set
779** UART1 to use the desired IRQ and set UART2 to
780** 0xF to enable sharing mechanism.
781**
782*/
783typedef union _SMC37c669_CR28 {
784 unsigned char as_uchar;
785 struct {
786 unsigned uart2_irq : 4; /* See note above */
787 unsigned uart1_irq : 4; /* See note above */
788 } by_field;
789} SMC37c669_CR28;
790
791/*
792** CR29 - default value 0x00
793**
794** IRQIN IRQ Select Register
795**
796** D3 - D0 IRQ
797** D7 - D4 Selected
798** ------- --------
799** 0000 None
800** 0001 IRQ_A
801** 0010 IRQ_B
802** 0011 IRQ_C
803** 0100 IRQ_D
804** 0101 IRQ_E
805** 0110 IRQ_F
806** 0111 Reserved
807** 1000 IRQ_H
808**
809** Any unselected IRQ REQ is in tristate
810**
811*/
812typedef union _SMC37c669_CR29 {
813 unsigned char as_uchar;
814 struct {
815 unsigned irqin_irq : 4; /* See note above */
816 unsigned reserved1 : 4; /* RAZ */
817 } by_field;
818} SMC37c669_CR29;
819
820/*
821** Aliases of Configuration Register formats (should match
822** the set of index aliases).
823**
824** Note that CR24 and CR25 have the same format and are the
825** base address registers for UART1 and UART2. Because of
826** this we only define 1 alias here - for CR24 - as the serial
827** base address register.
828**
829** Note that CR21 and CR22 have the same format and are the
830** base address and alternate status address registers for
831** the IDE controller. Because of this we only define 1 alias
832** here - for CR21 - as the IDE address register.
833**
834*/
835typedef SMC37c669_CR0D SMC37c669_DEVICE_ID_REGISTER;
836typedef SMC37c669_CR0E SMC37c669_DEVICE_REVISION_REGISTER;
837typedef SMC37c669_CR20 SMC37c669_FDC_BASE_ADDRESS_REGISTER;
838typedef SMC37c669_CR21 SMC37c669_IDE_ADDRESS_REGISTER;
839typedef SMC37c669_CR23 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER;
840typedef SMC37c669_CR24 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER;
841typedef SMC37c669_CR26 SMC37c669_PARALLEL_FDC_DRQ_REGISTER;
842typedef SMC37c669_CR27 SMC37c669_PARALLEL_FDC_IRQ_REGISTER;
843typedef SMC37c669_CR28 SMC37c669_SERIAL_IRQ_REGISTER;
844
845/*
846** ISA/Device IRQ Translation Table Entry Definition
847*/
848typedef struct _SMC37c669_IRQ_TRANSLATION_ENTRY {
849 int device_irq;
850 int isa_irq;
851} SMC37c669_IRQ_TRANSLATION_ENTRY;
852
853/*
854** ISA/Device DMA Translation Table Entry Definition
855*/
856typedef struct _SMC37c669_DRQ_TRANSLATION_ENTRY {
857 int device_drq;
858 int isa_drq;
859} SMC37c669_DRQ_TRANSLATION_ENTRY;
860
861/*
862** External Interface Function Prototype Declarations
863*/
864
865SMC37c669_CONFIG_REGS *SMC37c669_detect(
866 int
867);
868
869unsigned int SMC37c669_enable_device(
870 unsigned int func
871);
872
873unsigned int SMC37c669_disable_device(
874 unsigned int func
875);
876
877unsigned int SMC37c669_configure_device(
878 unsigned int func,
879 int port,
880 int irq,
881 int drq
882);
883
884void SMC37c669_display_device_info(
885 void
886);
887
888#endif /* __SMC37c669_H */
889
890/* file: smcc669.c
891 *
892 * Copyright (C) 1997 by
893 * Digital Equipment Corporation, Maynard, Massachusetts.
894 * All rights reserved.
895 *
896 * This software is furnished under a license and may be used and copied
897 * only in accordance of the terms of such license and with the
898 * inclusion of the above copyright notice. This software or any other
899 * copies thereof may not be provided or otherwise made available to any
900 * other person. No title to and ownership of the software is hereby
901 * transferred.
902 *
903 * The information in this software is subject to change without notice
904 * and should not be construed as a commitment by digital equipment
905 * corporation.
906 *
907 * Digital assumes no responsibility for the use or reliability of its
908 * software on equipment which is not supplied by digital.
909 */
910
911/*
912 *++
913 * FACILITY:
914 *
915 * Alpha SRM Console Firmware
916 *
917 * MODULE DESCRIPTION:
918 *
919 * SMC37c669 Super I/O controller configuration routines.
920 *
921 * AUTHORS:
922 *
923 * Eric Rasmussen
924 *
925 * CREATION DATE:
926 *
927 * 28-Jan-1997
928 *
929 * MODIFICATION HISTORY:
930 *
931 * er 01-May-1997 Fixed pointer conversion errors in
932 * SMC37c669_get_device_config().
933 * er 28-Jan-1997 Initial version.
934 *
935 *--
936 */
937#if 0
938/* $INCLUDE_OPTIONS$ */
939#include "cp$inc:platform_io.h"
940/* $INCLUDE_OPTIONS_END$ */
941#include "cp$src:common.h"
942#include "cp$inc:prototypes.h"
943#include "cp$src:kernel_def.h"
944#include "cp$src:msg_def.h"
945#include "cp$src:smcc669_def.h"
946/* Platform-specific includes */
947#include "cp$src:platform.h"
948#endif
949
950#ifndef TRUE
951#define TRUE 1
952#endif
953#ifndef FALSE
954#define FALSE 0
955#endif
956
957#define wb( _x_, _y_ ) outb( _y_, (unsigned int)((unsigned long)_x_) )
958#define rb( _x_ ) inb( (unsigned int)((unsigned long)_x_) )
959
960/*
961** Local storage for device configuration information.
962**
963** Since the SMC37c669 does not provide an explicit
964** mechanism for enabling/disabling individual device
965** functions, other than unmapping the device, local
966** storage for device configuration information is
967** allocated here for use in implementing our own
968** function enable/disable scheme.
969*/
970static struct DEVICE_CONFIG {
971 unsigned int port1;
972 unsigned int port2;
973 int irq;
974 int drq;
975} local_config [NUM_FUNCS];
976
977/*
978** List of all possible addresses for the Super I/O chip
979*/
980static unsigned long SMC37c669_Addresses[] __initdata =
981 {
982 0x3F0UL, /* Primary address */
983 0x370UL, /* Secondary address */
984 0UL /* End of list */
985 };
986
987/*
988** Global Pointer to the Super I/O device
989*/
990static SMC37c669_CONFIG_REGS *SMC37c669 __initdata = NULL;
991
992/*
993** IRQ Translation Table
994**
995** The IRQ translation table is a list of SMC37c669 device
996** and standard ISA IRQs.
997**
998*/
999static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_table __initdata;
1000
1001/*
1002** The following definition is for the default IRQ
1003** translation table.
1004*/
1005static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_default_irq_table[]
1006__initdata =
1007 {
1008 { SMC37c669_DEVICE_IRQ_A, -1 },
1009 { SMC37c669_DEVICE_IRQ_B, -1 },
1010 { SMC37c669_DEVICE_IRQ_C, 7 },
1011 { SMC37c669_DEVICE_IRQ_D, 6 },
1012 { SMC37c669_DEVICE_IRQ_E, 4 },
1013 { SMC37c669_DEVICE_IRQ_F, 3 },
1014 { SMC37c669_DEVICE_IRQ_H, -1 },
1015 { -1, -1 } /* End of table */
1016 };
1017
1018/*
1019** The following definition is for the MONET (XP1000) IRQ
1020** translation table.
1021*/
1022static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_monet_irq_table[]
1023__initdata =
1024 {
1025 { SMC37c669_DEVICE_IRQ_A, -1 },
1026 { SMC37c669_DEVICE_IRQ_B, -1 },
1027 { SMC37c669_DEVICE_IRQ_C, 6 },
1028 { SMC37c669_DEVICE_IRQ_D, 7 },
1029 { SMC37c669_DEVICE_IRQ_E, 4 },
1030 { SMC37c669_DEVICE_IRQ_F, 3 },
1031 { SMC37c669_DEVICE_IRQ_H, -1 },
1032 { -1, -1 } /* End of table */
1033 };
1034
1035static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_tables[] __initdata =
1036 {
1037 SMC37c669_default_irq_table,
1038 SMC37c669_monet_irq_table
1039 };
1040
1041/*
1042** DRQ Translation Table
1043**
1044** The DRQ translation table is a list of SMC37c669 device and
1045** ISA DMA channels.
1046**
1047*/
1048static SMC37c669_DRQ_TRANSLATION_ENTRY *SMC37c669_drq_table __initdata;
1049
1050/*
1051** The following definition is the default DRQ
1052** translation table.
1053*/
1054static SMC37c669_DRQ_TRANSLATION_ENTRY SMC37c669_default_drq_table[]
1055__initdata =
1056 {
1057 { SMC37c669_DEVICE_DRQ_A, 2 },
1058 { SMC37c669_DEVICE_DRQ_B, 3 },
1059 { SMC37c669_DEVICE_DRQ_C, -1 },
1060 { -1, -1 } /* End of table */
1061 };
1062
1063/*
1064** Local Function Prototype Declarations
1065*/
1066
1067static unsigned int SMC37c669_is_device_enabled(
1068 unsigned int func
1069);
1070
1071#if 0
1072static unsigned int SMC37c669_get_device_config(
1073 unsigned int func,
1074 int *port,
1075 int *irq,
1076 int *drq
1077);
1078#endif
1079
1080static void SMC37c669_config_mode(
1081 unsigned int enable
1082);
1083
1084static unsigned char SMC37c669_read_config(
1085 unsigned char index
1086);
1087
1088static void SMC37c669_write_config(
1089 unsigned char index,
1090 unsigned char data
1091);
1092
1093static void SMC37c669_init_local_config( void );
1094
1095static struct DEVICE_CONFIG *SMC37c669_get_config(
1096 unsigned int func
1097);
1098
1099static int SMC37c669_xlate_irq(
1100 int irq
1101);
1102
1103static int SMC37c669_xlate_drq(
1104 int drq
1105);
1106
1107static __cacheline_aligned DEFINE_SPINLOCK(smc_lock);
1108
1109/*
1110**++
1111** FUNCTIONAL DESCRIPTION:
1112**
1113** This function detects the presence of an SMC37c669 Super I/O
1114** controller.
1115**
1116** FORMAL PARAMETERS:
1117**
1118** None
1119**
1120** RETURN VALUE:
1121**
1122** Returns a pointer to the device if found, otherwise,
1123** the NULL pointer is returned.
1124**
1125** SIDE EFFECTS:
1126**
1127** None
1128**
1129**--
1130*/
1131SMC37c669_CONFIG_REGS * __init SMC37c669_detect( int index )
1132{
1133 int i;
1134 SMC37c669_DEVICE_ID_REGISTER id;
1135
1136 for ( i = 0; SMC37c669_Addresses[i] != 0; i++ ) {
1137/*
1138** Initialize the device pointer even though we don't yet know if
1139** the controller is at this address. The support functions access
1140** the controller through this device pointer so we need to set it
1141** even when we are looking ...
1142*/
1143 SMC37c669 = ( SMC37c669_CONFIG_REGS * )SMC37c669_Addresses[i];
1144/*
1145** Enter configuration mode
1146*/
1147 SMC37c669_config_mode( TRUE );
1148/*
1149** Read the device id
1150*/
1151 id.as_uchar = SMC37c669_read_config( SMC37c669_DEVICE_ID_INDEX );
1152/*
1153** Exit configuration mode
1154*/
1155 SMC37c669_config_mode( FALSE );
1156/*
1157** Does the device id match? If so, assume we have found an
1158** SMC37c669 controller at this address.
1159*/
1160 if ( id.by_field.device_id == SMC37c669_DEVICE_ID ) {
1161/*
1162** Initialize the IRQ and DRQ translation tables.
1163*/
1164 SMC37c669_irq_table = SMC37c669_irq_tables[ index ];
1165 SMC37c669_drq_table = SMC37c669_default_drq_table;
1166/*
1167** erfix
1168**
1169** If the platform can't use the IRQ and DRQ defaults set up in this
1170** file, it should call a platform-specific external routine at this
1171** point to reset the IRQ and DRQ translation table pointers to point
1172** at the appropriate tables for the platform. If the defaults are
1173** acceptable, then the external routine should do nothing.
1174*/
1175
1176/*
1177** Put the chip back into configuration mode
1178*/
1179 SMC37c669_config_mode( TRUE );
1180/*
1181** Initialize local storage for configuration information
1182*/
1183 SMC37c669_init_local_config( );
1184/*
1185** Exit configuration mode
1186*/
1187 SMC37c669_config_mode( FALSE );
1188/*
1189** SMC37c669 controller found, break out of search loop
1190*/
1191 break;
1192 }
1193 else {
1194/*
1195** Otherwise, we did not find an SMC37c669 controller at this
1196** address so set the device pointer to NULL.
1197*/
1198 SMC37c669 = NULL;
1199 }
1200 }
1201 return SMC37c669;
1202}
1203
1204
1205/*
1206**++
1207** FUNCTIONAL DESCRIPTION:
1208**
1209** This function enables an SMC37c669 device function.
1210**
1211** FORMAL PARAMETERS:
1212**
1213** func:
1214** Which device function to enable
1215**
1216** RETURN VALUE:
1217**
1218** Returns TRUE is the device function was enabled, otherwise, FALSE
1219**
1220** SIDE EFFECTS:
1221**
1222** {@description or none@}
1223**
1224** DESIGN:
1225**
1226** Enabling a device function in the SMC37c669 controller involves
1227** setting all of its mappings (port, irq, drq ...). A local
1228** "shadow" copy of the device configuration is kept so we can
1229** just set each mapping to what the local copy says.
1230**
1231** This function ALWAYS updates the local shadow configuration of
1232** the device function being enabled, even if the device is always
1233** enabled. To avoid replication of code, functions such as
1234** configure_device set up the local copy and then call this
1235** function to the update the real device.
1236**
1237**--
1238*/
1239unsigned int __init SMC37c669_enable_device ( unsigned int func )
1240{
1241 unsigned int ret_val = FALSE;
1242/*
1243** Put the device into configuration mode
1244*/
1245 SMC37c669_config_mode( TRUE );
1246 switch ( func ) {
1247 case SERIAL_0:
1248 {
1249 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
1250 SMC37c669_SERIAL_IRQ_REGISTER irq;
1251/*
1252** Enable the serial 1 IRQ mapping
1253*/
1254 irq.as_uchar =
1255 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
1256
1257 irq.by_field.uart1_irq =
1258 SMC37c669_RAW_DEVICE_IRQ(
1259 SMC37c669_xlate_irq( local_config[ func ].irq )
1260 );
1261
1262 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
1263/*
1264** Enable the serial 1 port base address mapping
1265*/
1266 base_addr.as_uchar = 0;
1267 base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3;
1268
1269 SMC37c669_write_config(
1270 SMC37c669_SERIAL0_BASE_ADDRESS_INDEX,
1271 base_addr.as_uchar
1272 );
1273 ret_val = TRUE;
1274 break;
1275 }
1276 case SERIAL_1:
1277 {
1278 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
1279 SMC37c669_SERIAL_IRQ_REGISTER irq;
1280/*
1281** Enable the serial 2 IRQ mapping
1282*/
1283 irq.as_uchar =
1284 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
1285
1286 irq.by_field.uart2_irq =
1287 SMC37c669_RAW_DEVICE_IRQ(
1288 SMC37c669_xlate_irq( local_config[ func ].irq )
1289 );
1290
1291 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
1292/*
1293** Enable the serial 2 port base address mapping
1294*/
1295 base_addr.as_uchar = 0;
1296 base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3;
1297
1298 SMC37c669_write_config(
1299 SMC37c669_SERIAL1_BASE_ADDRESS_INDEX,
1300 base_addr.as_uchar
1301 );
1302 ret_val = TRUE;
1303 break;
1304 }
1305 case PARALLEL_0:
1306 {
1307 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr;
1308 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
1309 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
1310/*
1311** Enable the parallel port DMA channel mapping
1312*/
1313 drq.as_uchar =
1314 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
1315
1316 drq.by_field.ppt_drq =
1317 SMC37c669_RAW_DEVICE_DRQ(
1318 SMC37c669_xlate_drq( local_config[ func ].drq )
1319 );
1320
1321 SMC37c669_write_config(
1322 SMC37c669_PARALLEL_FDC_DRQ_INDEX,
1323 drq.as_uchar
1324 );
1325/*
1326** Enable the parallel port IRQ mapping
1327*/
1328 irq.as_uchar =
1329 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
1330
1331 irq.by_field.ppt_irq =
1332 SMC37c669_RAW_DEVICE_IRQ(
1333 SMC37c669_xlate_irq( local_config[ func ].irq )
1334 );
1335
1336 SMC37c669_write_config(
1337 SMC37c669_PARALLEL_FDC_IRQ_INDEX,
1338 irq.as_uchar
1339 );
1340/*
1341** Enable the parallel port base address mapping
1342*/
1343 base_addr.as_uchar = 0;
1344 base_addr.by_field.addr9_2 = local_config[ func ].port1 >> 2;
1345
1346 SMC37c669_write_config(
1347 SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX,
1348 base_addr.as_uchar
1349 );
1350 ret_val = TRUE;
1351 break;
1352 }
1353 case FLOPPY_0:
1354 {
1355 SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr;
1356 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
1357 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
1358/*
1359** Enable the floppy controller DMA channel mapping
1360*/
1361 drq.as_uchar =
1362 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
1363
1364 drq.by_field.fdc_drq =
1365 SMC37c669_RAW_DEVICE_DRQ(
1366 SMC37c669_xlate_drq( local_config[ func ].drq )
1367 );
1368
1369 SMC37c669_write_config(
1370 SMC37c669_PARALLEL_FDC_DRQ_INDEX,
1371 drq.as_uchar
1372 );
1373/*
1374** Enable the floppy controller IRQ mapping
1375*/
1376 irq.as_uchar =
1377 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
1378
1379 irq.by_field.fdc_irq =
1380 SMC37c669_RAW_DEVICE_IRQ(
1381 SMC37c669_xlate_irq( local_config[ func ].irq )
1382 );
1383
1384 SMC37c669_write_config(
1385 SMC37c669_PARALLEL_FDC_IRQ_INDEX,
1386 irq.as_uchar
1387 );
1388/*
1389** Enable the floppy controller base address mapping
1390*/
1391 base_addr.as_uchar = 0;
1392 base_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4;
1393
1394 SMC37c669_write_config(
1395 SMC37c669_FDC_BASE_ADDRESS_INDEX,
1396 base_addr.as_uchar
1397 );
1398 ret_val = TRUE;
1399 break;
1400 }
1401 case IDE_0:
1402 {
1403 SMC37c669_IDE_ADDRESS_REGISTER ide_addr;
1404/*
1405** Enable the IDE alternate status base address mapping
1406*/
1407 ide_addr.as_uchar = 0;
1408 ide_addr.by_field.addr9_4 = local_config[ func ].port2 >> 4;
1409
1410 SMC37c669_write_config(
1411 SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX,
1412 ide_addr.as_uchar
1413 );
1414/*
1415** Enable the IDE controller base address mapping
1416*/
1417 ide_addr.as_uchar = 0;
1418 ide_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4;
1419
1420 SMC37c669_write_config(
1421 SMC37c669_IDE_BASE_ADDRESS_INDEX,
1422 ide_addr.as_uchar
1423 );
1424 ret_val = TRUE;
1425 break;
1426 }
1427 }
1428/*
1429** Exit configuration mode and return
1430*/
1431 SMC37c669_config_mode( FALSE );
1432
1433 return ret_val;
1434}
1435
1436
1437/*
1438**++
1439** FUNCTIONAL DESCRIPTION:
1440**
1441** This function disables a device function within the
1442** SMC37c669 Super I/O controller.
1443**
1444** FORMAL PARAMETERS:
1445**
1446** func:
1447** Which function to disable
1448**
1449** RETURN VALUE:
1450**
1451** Return TRUE if the device function was disabled, otherwise, FALSE
1452**
1453** SIDE EFFECTS:
1454**
1455** {@description or none@}
1456**
1457** DESIGN:
1458**
1459** Disabling a function in the SMC37c669 device involves
1460** disabling all the function's mappings (port, irq, drq ...).
1461** A shadow copy of the device configuration is maintained
1462** in local storage so we won't worry aboving saving the
1463** current configuration information.
1464**
1465**--
1466*/
1467unsigned int __init SMC37c669_disable_device ( unsigned int func )
1468{
1469 unsigned int ret_val = FALSE;
1470
1471/*
1472** Put the device into configuration mode
1473*/
1474 SMC37c669_config_mode( TRUE );
1475 switch ( func ) {
1476 case SERIAL_0:
1477 {
1478 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
1479 SMC37c669_SERIAL_IRQ_REGISTER irq;
1480/*
1481** Disable the serial 1 IRQ mapping
1482*/
1483 irq.as_uchar =
1484 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
1485
1486 irq.by_field.uart1_irq = 0;
1487
1488 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
1489/*
1490** Disable the serial 1 port base address mapping
1491*/
1492 base_addr.as_uchar = 0;
1493 SMC37c669_write_config(
1494 SMC37c669_SERIAL0_BASE_ADDRESS_INDEX,
1495 base_addr.as_uchar
1496 );
1497 ret_val = TRUE;
1498 break;
1499 }
1500 case SERIAL_1:
1501 {
1502 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr;
1503 SMC37c669_SERIAL_IRQ_REGISTER irq;
1504/*
1505** Disable the serial 2 IRQ mapping
1506*/
1507 irq.as_uchar =
1508 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
1509
1510 irq.by_field.uart2_irq = 0;
1511
1512 SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar );
1513/*
1514** Disable the serial 2 port base address mapping
1515*/
1516 base_addr.as_uchar = 0;
1517
1518 SMC37c669_write_config(
1519 SMC37c669_SERIAL1_BASE_ADDRESS_INDEX,
1520 base_addr.as_uchar
1521 );
1522 ret_val = TRUE;
1523 break;
1524 }
1525 case PARALLEL_0:
1526 {
1527 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr;
1528 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
1529 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
1530/*
1531** Disable the parallel port DMA channel mapping
1532*/
1533 drq.as_uchar =
1534 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
1535
1536 drq.by_field.ppt_drq = 0;
1537
1538 SMC37c669_write_config(
1539 SMC37c669_PARALLEL_FDC_DRQ_INDEX,
1540 drq.as_uchar
1541 );
1542/*
1543** Disable the parallel port IRQ mapping
1544*/
1545 irq.as_uchar =
1546 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
1547
1548 irq.by_field.ppt_irq = 0;
1549
1550 SMC37c669_write_config(
1551 SMC37c669_PARALLEL_FDC_IRQ_INDEX,
1552 irq.as_uchar
1553 );
1554/*
1555** Disable the parallel port base address mapping
1556*/
1557 base_addr.as_uchar = 0;
1558
1559 SMC37c669_write_config(
1560 SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX,
1561 base_addr.as_uchar
1562 );
1563 ret_val = TRUE;
1564 break;
1565 }
1566 case FLOPPY_0:
1567 {
1568 SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr;
1569 SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq;
1570 SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq;
1571/*
1572** Disable the floppy controller DMA channel mapping
1573*/
1574 drq.as_uchar =
1575 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
1576
1577 drq.by_field.fdc_drq = 0;
1578
1579 SMC37c669_write_config(
1580 SMC37c669_PARALLEL_FDC_DRQ_INDEX,
1581 drq.as_uchar
1582 );
1583/*
1584** Disable the floppy controller IRQ mapping
1585*/
1586 irq.as_uchar =
1587 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
1588
1589 irq.by_field.fdc_irq = 0;
1590
1591 SMC37c669_write_config(
1592 SMC37c669_PARALLEL_FDC_IRQ_INDEX,
1593 irq.as_uchar
1594 );
1595/*
1596** Disable the floppy controller base address mapping
1597*/
1598 base_addr.as_uchar = 0;
1599
1600 SMC37c669_write_config(
1601 SMC37c669_FDC_BASE_ADDRESS_INDEX,
1602 base_addr.as_uchar
1603 );
1604 ret_val = TRUE;
1605 break;
1606 }
1607 case IDE_0:
1608 {
1609 SMC37c669_IDE_ADDRESS_REGISTER ide_addr;
1610/*
1611** Disable the IDE alternate status base address mapping
1612*/
1613 ide_addr.as_uchar = 0;
1614
1615 SMC37c669_write_config(
1616 SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX,
1617 ide_addr.as_uchar
1618 );
1619/*
1620** Disable the IDE controller base address mapping
1621*/
1622 ide_addr.as_uchar = 0;
1623
1624 SMC37c669_write_config(
1625 SMC37c669_IDE_BASE_ADDRESS_INDEX,
1626 ide_addr.as_uchar
1627 );
1628 ret_val = TRUE;
1629 break;
1630 }
1631 }
1632/*
1633** Exit configuration mode and return
1634*/
1635 SMC37c669_config_mode( FALSE );
1636
1637 return ret_val;
1638}
1639
1640
1641/*
1642**++
1643** FUNCTIONAL DESCRIPTION:
1644**
1645** This function configures a device function within the
1646** SMC37c669 Super I/O controller.
1647**
1648** FORMAL PARAMETERS:
1649**
1650** func:
1651** Which device function
1652**
1653** port:
1654** I/O port for the function to use
1655**
1656** irq:
1657** IRQ for the device function to use
1658**
1659** drq:
1660** DMA channel for the device function to use
1661**
1662** RETURN VALUE:
1663**
1664** Returns TRUE if the device function was configured,
1665** otherwise, FALSE.
1666**
1667** SIDE EFFECTS:
1668**
1669** {@description or none@}
1670**
1671** DESIGN:
1672**
1673** If this function returns TRUE, the local shadow copy of
1674** the configuration is also updated. If the device function
1675** is currently disabled, only the local shadow copy is
1676** updated and the actual device function will be updated
1677** if/when it is enabled.
1678**
1679**--
1680*/
1681unsigned int __init SMC37c669_configure_device (
1682 unsigned int func,
1683 int port,
1684 int irq,
1685 int drq )
1686{
1687 struct DEVICE_CONFIG *cp;
1688
1689/*
1690** Check for a valid configuration
1691*/
1692 if ( ( cp = SMC37c669_get_config ( func ) ) != NULL ) {
1693/*
1694** Configuration is valid, update the local shadow copy
1695*/
1696 if ( ( drq & ~0xFF ) == 0 ) {
1697 cp->drq = drq;
1698 }
1699 if ( ( irq & ~0xFF ) == 0 ) {
1700 cp->irq = irq;
1701 }
1702 if ( ( port & ~0xFFFF ) == 0 ) {
1703 cp->port1 = port;
1704 }
1705/*
1706** If the device function is enabled, update the actual
1707** device configuration.
1708*/
1709 if ( SMC37c669_is_device_enabled( func ) ) {
1710 SMC37c669_enable_device( func );
1711 }
1712 return TRUE;
1713 }
1714 return FALSE;
1715}
1716
1717
1718/*
1719**++
1720** FUNCTIONAL DESCRIPTION:
1721**
1722** This function determines whether a device function
1723** within the SMC37c669 controller is enabled.
1724**
1725** FORMAL PARAMETERS:
1726**
1727** func:
1728** Which device function
1729**
1730** RETURN VALUE:
1731**
1732** Returns TRUE if the device function is enabled, otherwise, FALSE
1733**
1734** SIDE EFFECTS:
1735**
1736** {@description or none@}
1737**
1738** DESIGN:
1739**
1740** To check whether a device is enabled we will only look at
1741** the port base address mapping. According to the SMC37c669
1742** specification, all of the port base address mappings are
1743** disabled if the addr<9:8> (bits <7:6> of the register) are
1744** zero.
1745**
1746**--
1747*/
1748static unsigned int __init SMC37c669_is_device_enabled ( unsigned int func )
1749{
1750 unsigned char base_addr = 0;
1751 unsigned int dev_ok = FALSE;
1752 unsigned int ret_val = FALSE;
1753/*
1754** Enter configuration mode
1755*/
1756 SMC37c669_config_mode( TRUE );
1757
1758 switch ( func ) {
1759 case SERIAL_0:
1760 base_addr =
1761 SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX );
1762 dev_ok = TRUE;
1763 break;
1764 case SERIAL_1:
1765 base_addr =
1766 SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX );
1767 dev_ok = TRUE;
1768 break;
1769 case PARALLEL_0:
1770 base_addr =
1771 SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX );
1772 dev_ok = TRUE;
1773 break;
1774 case FLOPPY_0:
1775 base_addr =
1776 SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX );
1777 dev_ok = TRUE;
1778 break;
1779 case IDE_0:
1780 base_addr =
1781 SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX );
1782 dev_ok = TRUE;
1783 break;
1784 }
1785/*
1786** If we have a valid device, check base_addr<7:6> to see if the
1787** device is enabled (mapped).
1788*/
1789 if ( ( dev_ok ) && ( ( base_addr & 0xC0 ) != 0 ) ) {
1790/*
1791** The mapping is not disabled, so assume that the function is
1792** enabled.
1793*/
1794 ret_val = TRUE;
1795 }
1796/*
1797** Exit configuration mode
1798*/
1799 SMC37c669_config_mode( FALSE );
1800
1801 return ret_val;
1802}
1803
1804
1805#if 0
1806/*
1807**++
1808** FUNCTIONAL DESCRIPTION:
1809**
1810** This function retrieves the configuration information of a
1811** device function within the SMC37c699 Super I/O controller.
1812**
1813** FORMAL PARAMETERS:
1814**
1815** func:
1816** Which device function
1817**
1818** port:
1819** I/O port returned
1820**
1821** irq:
1822** IRQ returned
1823**
1824** drq:
1825** DMA channel returned
1826**
1827** RETURN VALUE:
1828**
1829** Returns TRUE if the device configuration was successfully
1830** retrieved, otherwise, FALSE.
1831**
1832** SIDE EFFECTS:
1833**
1834** The data pointed to by the port, irq, and drq parameters
1835** my be modified even if the configuration is not successfully
1836** retrieved.
1837**
1838** DESIGN:
1839**
1840** The device configuration is fetched from the local shadow
1841** copy. Any unused parameters will be set to -1. Any
1842** parameter which is not desired can specify the NULL
1843** pointer.
1844**
1845**--
1846*/
1847static unsigned int __init SMC37c669_get_device_config (
1848 unsigned int func,
1849 int *port,
1850 int *irq,
1851 int *drq )
1852{
1853 struct DEVICE_CONFIG *cp;
1854 unsigned int ret_val = FALSE;
1855/*
1856** Check for a valid device configuration
1857*/
1858 if ( ( cp = SMC37c669_get_config( func ) ) != NULL ) {
1859 if ( drq != NULL ) {
1860 *drq = cp->drq;
1861 ret_val = TRUE;
1862 }
1863 if ( irq != NULL ) {
1864 *irq = cp->irq;
1865 ret_val = TRUE;
1866 }
1867 if ( port != NULL ) {
1868 *port = cp->port1;
1869 ret_val = TRUE;
1870 }
1871 }
1872 return ret_val;
1873}
1874#endif
1875
1876
1877/*
1878**++
1879** FUNCTIONAL DESCRIPTION:
1880**
1881** This function displays the current state of the SMC37c699
1882** Super I/O controller's device functions.
1883**
1884** FORMAL PARAMETERS:
1885**
1886** None
1887**
1888** RETURN VALUE:
1889**
1890** None
1891**
1892** SIDE EFFECTS:
1893**
1894** None
1895**
1896**--
1897*/
1898void __init SMC37c669_display_device_info ( void )
1899{
1900 if ( SMC37c669_is_device_enabled( SERIAL_0 ) ) {
1901 printk( " Serial 0: Enabled [ Port 0x%x, IRQ %d ]\n",
1902 local_config[ SERIAL_0 ].port1,
1903 local_config[ SERIAL_0 ].irq
1904 );
1905 }
1906 else {
1907 printk( " Serial 0: Disabled\n" );
1908 }
1909
1910 if ( SMC37c669_is_device_enabled( SERIAL_1 ) ) {
1911 printk( " Serial 1: Enabled [ Port 0x%x, IRQ %d ]\n",
1912 local_config[ SERIAL_1 ].port1,
1913 local_config[ SERIAL_1 ].irq
1914 );
1915 }
1916 else {
1917 printk( " Serial 1: Disabled\n" );
1918 }
1919
1920 if ( SMC37c669_is_device_enabled( PARALLEL_0 ) ) {
1921 printk( " Parallel: Enabled [ Port 0x%x, IRQ %d/%d ]\n",
1922 local_config[ PARALLEL_0 ].port1,
1923 local_config[ PARALLEL_0 ].irq,
1924 local_config[ PARALLEL_0 ].drq
1925 );
1926 }
1927 else {
1928 printk( " Parallel: Disabled\n" );
1929 }
1930
1931 if ( SMC37c669_is_device_enabled( FLOPPY_0 ) ) {
1932 printk( " Floppy Ctrl: Enabled [ Port 0x%x, IRQ %d/%d ]\n",
1933 local_config[ FLOPPY_0 ].port1,
1934 local_config[ FLOPPY_0 ].irq,
1935 local_config[ FLOPPY_0 ].drq
1936 );
1937 }
1938 else {
1939 printk( " Floppy Ctrl: Disabled\n" );
1940 }
1941
1942 if ( SMC37c669_is_device_enabled( IDE_0 ) ) {
1943 printk( " IDE 0: Enabled [ Port 0x%x, IRQ %d ]\n",
1944 local_config[ IDE_0 ].port1,
1945 local_config[ IDE_0 ].irq
1946 );
1947 }
1948 else {
1949 printk( " IDE 0: Disabled\n" );
1950 }
1951}
1952
1953
1954/*
1955**++
1956** FUNCTIONAL DESCRIPTION:
1957**
1958** This function puts the SMC37c669 Super I/O controller into,
1959** and takes it out of, configuration mode.
1960**
1961** FORMAL PARAMETERS:
1962**
1963** enable:
1964** TRUE to enter configuration mode, FALSE to exit.
1965**
1966** RETURN VALUE:
1967**
1968** None
1969**
1970** SIDE EFFECTS:
1971**
1972** The SMC37c669 controller may be left in configuration mode.
1973**
1974**--
1975*/
1976static void __init SMC37c669_config_mode(
1977 unsigned int enable )
1978{
1979 if ( enable ) {
1980/*
1981** To enter configuration mode, two writes in succession to the index
1982** port are required. If a write to another address or port occurs
1983** between these two writes, the chip does not enter configuration
1984** mode. Therefore, a spinlock is placed around the two writes to
1985** guarantee that they complete uninterrupted.
1986*/
1987 spin_lock(&smc_lock);
1988 wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY );
1989 wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY );
1990 spin_unlock(&smc_lock);
1991 }
1992 else {
1993 wb( &SMC37c669->index_port, SMC37c669_CONFIG_OFF_KEY );
1994 }
1995}
1996
1997/*
1998**++
1999** FUNCTIONAL DESCRIPTION:
2000**
2001** This function reads an SMC37c669 Super I/O controller
2002** configuration register. This function assumes that the
2003** device is already in configuration mode.
2004**
2005** FORMAL PARAMETERS:
2006**
2007** index:
2008** Index value of configuration register to read
2009**
2010** RETURN VALUE:
2011**
2012** Data read from configuration register
2013**
2014** SIDE EFFECTS:
2015**
2016** None
2017**
2018**--
2019*/
2020static unsigned char __init SMC37c669_read_config(
2021 unsigned char index )
2022{
2023 unsigned char data;
2024
2025 wb( &SMC37c669->index_port, index );
2026 data = rb( &SMC37c669->data_port );
2027 return data;
2028}
2029
2030/*
2031**++
2032** FUNCTIONAL DESCRIPTION:
2033**
2034** This function writes an SMC37c669 Super I/O controller
2035** configuration register. This function assumes that the
2036** device is already in configuration mode.
2037**
2038** FORMAL PARAMETERS:
2039**
2040** index:
2041** Index of configuration register to write
2042**
2043** data:
2044** Data to be written
2045**
2046** RETURN VALUE:
2047**
2048** None
2049**
2050** SIDE EFFECTS:
2051**
2052** None
2053**
2054**--
2055*/
2056static void __init SMC37c669_write_config(
2057 unsigned char index,
2058 unsigned char data )
2059{
2060 wb( &SMC37c669->index_port, index );
2061 wb( &SMC37c669->data_port, data );
2062}
2063
2064
2065/*
2066**++
2067** FUNCTIONAL DESCRIPTION:
2068**
2069** This function initializes the local device
2070** configuration storage. This function assumes
2071** that the device is already in configuration
2072** mode.
2073**
2074** FORMAL PARAMETERS:
2075**
2076** None
2077**
2078** RETURN VALUE:
2079**
2080** None
2081**
2082** SIDE EFFECTS:
2083**
2084** Local storage for device configuration information
2085** is initialized.
2086**
2087**--
2088*/
2089static void __init SMC37c669_init_local_config ( void )
2090{
2091 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER uart_base;
2092 SMC37c669_SERIAL_IRQ_REGISTER uart_irqs;
2093 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER ppt_base;
2094 SMC37c669_PARALLEL_FDC_IRQ_REGISTER ppt_fdc_irqs;
2095 SMC37c669_PARALLEL_FDC_DRQ_REGISTER ppt_fdc_drqs;
2096 SMC37c669_FDC_BASE_ADDRESS_REGISTER fdc_base;
2097 SMC37c669_IDE_ADDRESS_REGISTER ide_base;
2098 SMC37c669_IDE_ADDRESS_REGISTER ide_alt;
2099
2100/*
2101** Get serial port 1 base address
2102*/
2103 uart_base.as_uchar =
2104 SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX );
2105/*
2106** Get IRQs for serial ports 1 & 2
2107*/
2108 uart_irqs.as_uchar =
2109 SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX );
2110/*
2111** Store local configuration information for serial port 1
2112*/
2113 local_config[SERIAL_0].port1 = uart_base.by_field.addr9_3 << 3;
2114 local_config[SERIAL_0].irq =
2115 SMC37c669_xlate_irq(
2116 SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart1_irq )
2117 );
2118/*
2119** Get serial port 2 base address
2120*/
2121 uart_base.as_uchar =
2122 SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX );
2123/*
2124** Store local configuration information for serial port 2
2125*/
2126 local_config[SERIAL_1].port1 = uart_base.by_field.addr9_3 << 3;
2127 local_config[SERIAL_1].irq =
2128 SMC37c669_xlate_irq(
2129 SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart2_irq )
2130 );
2131/*
2132** Get parallel port base address
2133*/
2134 ppt_base.as_uchar =
2135 SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX );
2136/*
2137** Get IRQs for parallel port and floppy controller
2138*/
2139 ppt_fdc_irqs.as_uchar =
2140 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX );
2141/*
2142** Get DRQs for parallel port and floppy controller
2143*/
2144 ppt_fdc_drqs.as_uchar =
2145 SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX );
2146/*
2147** Store local configuration information for parallel port
2148*/
2149 local_config[PARALLEL_0].port1 = ppt_base.by_field.addr9_2 << 2;
2150 local_config[PARALLEL_0].irq =
2151 SMC37c669_xlate_irq(
2152 SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.ppt_irq )
2153 );
2154 local_config[PARALLEL_0].drq =
2155 SMC37c669_xlate_drq(
2156 SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.ppt_drq )
2157 );
2158/*
2159** Get floppy controller base address
2160*/
2161 fdc_base.as_uchar =
2162 SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX );
2163/*
2164** Store local configuration information for floppy controller
2165*/
2166 local_config[FLOPPY_0].port1 = fdc_base.by_field.addr9_4 << 4;
2167 local_config[FLOPPY_0].irq =
2168 SMC37c669_xlate_irq(
2169 SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.fdc_irq )
2170 );
2171 local_config[FLOPPY_0].drq =
2172 SMC37c669_xlate_drq(
2173 SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.fdc_drq )
2174 );
2175/*
2176** Get IDE controller base address
2177*/
2178 ide_base.as_uchar =
2179 SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX );
2180/*
2181** Get IDE alternate status base address
2182*/
2183 ide_alt.as_uchar =
2184 SMC37c669_read_config( SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX );
2185/*
2186** Store local configuration information for IDE controller
2187*/
2188 local_config[IDE_0].port1 = ide_base.by_field.addr9_4 << 4;
2189 local_config[IDE_0].port2 = ide_alt.by_field.addr9_4 << 4;
2190 local_config[IDE_0].irq = 14;
2191}
2192
2193
2194/*
2195**++
2196** FUNCTIONAL DESCRIPTION:
2197**
2198** This function returns a pointer to the local shadow
2199** configuration of the requested device function.
2200**
2201** FORMAL PARAMETERS:
2202**
2203** func:
2204** Which device function
2205**
2206** RETURN VALUE:
2207**
2208** Returns a pointer to the DEVICE_CONFIG structure for the
2209** requested function, otherwise, NULL.
2210**
2211** SIDE EFFECTS:
2212**
2213** {@description or none@}
2214**
2215**--
2216*/
2217static struct DEVICE_CONFIG * __init SMC37c669_get_config( unsigned int func )
2218{
2219 struct DEVICE_CONFIG *cp = NULL;
2220
2221 switch ( func ) {
2222 case SERIAL_0:
2223 cp = &local_config[ SERIAL_0 ];
2224 break;
2225 case SERIAL_1:
2226 cp = &local_config[ SERIAL_1 ];
2227 break;
2228 case PARALLEL_0:
2229 cp = &local_config[ PARALLEL_0 ];
2230 break;
2231 case FLOPPY_0:
2232 cp = &local_config[ FLOPPY_0 ];
2233 break;
2234 case IDE_0:
2235 cp = &local_config[ IDE_0 ];
2236 break;
2237 }
2238 return cp;
2239}
2240
2241/*
2242**++
2243** FUNCTIONAL DESCRIPTION:
2244**
2245** This function translates IRQs back and forth between ISA
2246** IRQs and SMC37c669 device IRQs.
2247**
2248** FORMAL PARAMETERS:
2249**
2250** irq:
2251** The IRQ to translate
2252**
2253** RETURN VALUE:
2254**
2255** Returns the translated IRQ, otherwise, returns -1.
2256**
2257** SIDE EFFECTS:
2258**
2259** {@description or none@}
2260**
2261**--
2262*/
2263static int __init SMC37c669_xlate_irq ( int irq )
2264{
2265 int i, translated_irq = -1;
2266
2267 if ( SMC37c669_IS_DEVICE_IRQ( irq ) ) {
2268/*
2269** We are translating a device IRQ to an ISA IRQ
2270*/
2271 for ( i = 0; ( SMC37c669_irq_table[i].device_irq != -1 ) || ( SMC37c669_irq_table[i].isa_irq != -1 ); i++ ) {
2272 if ( irq == SMC37c669_irq_table[i].device_irq ) {
2273 translated_irq = SMC37c669_irq_table[i].isa_irq;
2274 break;
2275 }
2276 }
2277 }
2278 else {
2279/*
2280** We are translating an ISA IRQ to a device IRQ
2281*/
2282 for ( i = 0; ( SMC37c669_irq_table[i].isa_irq != -1 ) || ( SMC37c669_irq_table[i].device_irq != -1 ); i++ ) {
2283 if ( irq == SMC37c669_irq_table[i].isa_irq ) {
2284 translated_irq = SMC37c669_irq_table[i].device_irq;
2285 break;
2286 }
2287 }
2288 }
2289 return translated_irq;
2290}
2291
2292
2293/*
2294**++
2295** FUNCTIONAL DESCRIPTION:
2296**
2297** This function translates DMA channels back and forth between
2298** ISA DMA channels and SMC37c669 device DMA channels.
2299**
2300** FORMAL PARAMETERS:
2301**
2302** drq:
2303** The DMA channel to translate
2304**
2305** RETURN VALUE:
2306**
2307** Returns the translated DMA channel, otherwise, returns -1
2308**
2309** SIDE EFFECTS:
2310**
2311** {@description or none@}
2312**
2313**--
2314*/
2315static int __init SMC37c669_xlate_drq ( int drq )
2316{
2317 int i, translated_drq = -1;
2318
2319 if ( SMC37c669_IS_DEVICE_DRQ( drq ) ) {
2320/*
2321** We are translating a device DMA channel to an ISA DMA channel
2322*/
2323 for ( i = 0; ( SMC37c669_drq_table[i].device_drq != -1 ) || ( SMC37c669_drq_table[i].isa_drq != -1 ); i++ ) {
2324 if ( drq == SMC37c669_drq_table[i].device_drq ) {
2325 translated_drq = SMC37c669_drq_table[i].isa_drq;
2326 break;
2327 }
2328 }
2329 }
2330 else {
2331/*
2332** We are translating an ISA DMA channel to a device DMA channel
2333*/
2334 for ( i = 0; ( SMC37c669_drq_table[i].isa_drq != -1 ) || ( SMC37c669_drq_table[i].device_drq != -1 ); i++ ) {
2335 if ( drq == SMC37c669_drq_table[i].isa_drq ) {
2336 translated_drq = SMC37c669_drq_table[i].device_drq;
2337 break;
2338 }
2339 }
2340 }
2341 return translated_drq;
2342}
2343
2344#if 0
2345int __init smcc669_init ( void )
2346{
2347 struct INODE *ip;
2348
2349 allocinode( smc_ddb.name, 1, &ip );
2350 ip->dva = &smc_ddb;
2351 ip->attr = ATTR$M_WRITE | ATTR$M_READ;
2352 ip->len[0] = 0x30;
2353 ip->misc = 0;
2354 INODE_UNLOCK( ip );
2355
2356 return msg_success;
2357}
2358
2359int __init smcc669_open( struct FILE *fp, char *info, char *next, char *mode )
2360{
2361 struct INODE *ip;
2362/*
2363** Allow multiple readers but only one writer. ip->misc keeps track
2364** of the number of writers
2365*/
2366 ip = fp->ip;
2367 INODE_LOCK( ip );
2368 if ( fp->mode & ATTR$M_WRITE ) {
2369 if ( ip->misc ) {
2370 INODE_UNLOCK( ip );
2371 return msg_failure; /* too many writers */
2372 }
2373 ip->misc++;
2374 }
2375/*
2376** Treat the information field as a byte offset
2377*/
2378 *fp->offset = xtoi( info );
2379 INODE_UNLOCK( ip );
2380
2381 return msg_success;
2382}
2383
2384int __init smcc669_close( struct FILE *fp )
2385{
2386 struct INODE *ip;
2387
2388 ip = fp->ip;
2389 if ( fp->mode & ATTR$M_WRITE ) {
2390 INODE_LOCK( ip );
2391 ip->misc--;
2392 INODE_UNLOCK( ip );
2393 }
2394 return msg_success;
2395}
2396
2397int __init smcc669_read( struct FILE *fp, int size, int number, unsigned char *buf )
2398{
2399 int i;
2400 int length;
2401 int nbytes;
2402 struct INODE *ip;
2403
2404/*
2405** Always access a byte at a time
2406*/
2407 ip = fp->ip;
2408 length = size * number;
2409 nbytes = 0;
2410
2411 SMC37c669_config_mode( TRUE );
2412 for ( i = 0; i < length; i++ ) {
2413 if ( !inrange( *fp->offset, 0, ip->len[0] ) )
2414 break;
2415 *buf++ = SMC37c669_read_config( *fp->offset );
2416 *fp->offset += 1;
2417 nbytes++;
2418 }
2419 SMC37c669_config_mode( FALSE );
2420 return nbytes;
2421}
2422
2423int __init smcc669_write( struct FILE *fp, int size, int number, unsigned char *buf )
2424{
2425 int i;
2426 int length;
2427 int nbytes;
2428 struct INODE *ip;
2429/*
2430** Always access a byte at a time
2431*/
2432 ip = fp->ip;
2433 length = size * number;
2434 nbytes = 0;
2435
2436 SMC37c669_config_mode( TRUE );
2437 for ( i = 0; i < length; i++ ) {
2438 if ( !inrange( *fp->offset, 0, ip->len[0] ) )
2439 break;
2440 SMC37c669_write_config( *fp->offset, *buf );
2441 *fp->offset += 1;
2442 buf++;
2443 nbytes++;
2444 }
2445 SMC37c669_config_mode( FALSE );
2446 return nbytes;
2447}
2448#endif
2449
2450void __init
2451SMC37c669_dump_registers(void)
2452{
2453 int i;
2454 for (i = 0; i <= 0x29; i++)
2455 printk("-- CR%02x : %02x\n", i, SMC37c669_read_config(i));
2456}
2457/*+
2458 * ============================================================================
2459 * = SMC_init - SMC37c669 Super I/O controller initialization =
2460 * ============================================================================
2461 *
2462 * OVERVIEW:
2463 *
2464 * This routine configures and enables device functions on the
2465 * SMC37c669 Super I/O controller.
2466 *
2467 * FORM OF CALL:
2468 *
2469 * SMC_init( );
2470 *
2471 * RETURNS:
2472 *
2473 * Nothing
2474 *
2475 * ARGUMENTS:
2476 *
2477 * None
2478 *
2479 * SIDE EFFECTS:
2480 *
2481 * None
2482 *
2483 */
2484void __init SMC669_Init ( int index )
2485{
2486 SMC37c669_CONFIG_REGS *SMC_base;
2487 unsigned long flags;
2488
2489 local_irq_save(flags);
2490 if ( ( SMC_base = SMC37c669_detect( index ) ) != NULL ) {
2491#if SMC_DEBUG
2492 SMC37c669_config_mode( TRUE );
2493 SMC37c669_dump_registers( );
2494 SMC37c669_config_mode( FALSE );
2495 SMC37c669_display_device_info( );
2496#endif
2497 SMC37c669_disable_device( SERIAL_0 );
2498 SMC37c669_configure_device(
2499 SERIAL_0,
2500 COM1_BASE,
2501 COM1_IRQ,
2502 -1
2503 );
2504 SMC37c669_enable_device( SERIAL_0 );
2505
2506 SMC37c669_disable_device( SERIAL_1 );
2507 SMC37c669_configure_device(
2508 SERIAL_1,
2509 COM2_BASE,
2510 COM2_IRQ,
2511 -1
2512 );
2513 SMC37c669_enable_device( SERIAL_1 );
2514
2515 SMC37c669_disable_device( PARALLEL_0 );
2516 SMC37c669_configure_device(
2517 PARALLEL_0,
2518 PARP_BASE,
2519 PARP_IRQ,
2520 PARP_DRQ
2521 );
2522 SMC37c669_enable_device( PARALLEL_0 );
2523
2524 SMC37c669_disable_device( FLOPPY_0 );
2525 SMC37c669_configure_device(
2526 FLOPPY_0,
2527 FDC_BASE,
2528 FDC_IRQ,
2529 FDC_DRQ
2530 );
2531 SMC37c669_enable_device( FLOPPY_0 );
2532
2533 /* Wake up sometimes forgotten floppy, especially on DP264. */
2534 outb(0xc, 0x3f2);
2535
2536 SMC37c669_disable_device( IDE_0 );
2537
2538#if SMC_DEBUG
2539 SMC37c669_config_mode( TRUE );
2540 SMC37c669_dump_registers( );
2541 SMC37c669_config_mode( FALSE );
2542 SMC37c669_display_device_info( );
2543#endif
2544 local_irq_restore(flags);
2545 printk( "SMC37c669 Super I/O Controller found @ 0x%lx\n",
2546 (unsigned long) SMC_base );
2547 }
2548 else {
2549 local_irq_restore(flags);
2550#if SMC_DEBUG
2551 printk( "No SMC37c669 Super I/O Controller found\n" );
2552#endif
2553 }
2554}
diff --git a/arch/alpha/kernel/smc37c93x.c b/arch/alpha/kernel/smc37c93x.c
new file mode 100644
index 000000000000..421e51ea6bb7
--- /dev/null
+++ b/arch/alpha/kernel/smc37c93x.c
@@ -0,0 +1,277 @@
1/*
2 * SMC 37C93X initialization code
3 */
4
5#include <linux/config.h>
6#include <linux/kernel.h>
7
8#include <linux/slab.h>
9#include <linux/mm.h>
10#include <linux/init.h>
11#include <linux/delay.h>
12
13#include <asm/hwrpb.h>
14#include <asm/io.h>
15#include <asm/segment.h>
16
17#define SMC_DEBUG 0
18
19#if SMC_DEBUG
20# define DBG_DEVS(args) printk args
21#else
22# define DBG_DEVS(args)
23#endif
24
25#define KB 1024
26#define MB (1024*KB)
27#define GB (1024*MB)
28
29/* device "activate" register contents */
30#define DEVICE_ON 1
31#define DEVICE_OFF 0
32
33/* configuration on/off keys */
34#define CONFIG_ON_KEY 0x55
35#define CONFIG_OFF_KEY 0xaa
36
37/* configuration space device definitions */
38#define FDC 0
39#define IDE1 1
40#define IDE2 2
41#define PARP 3
42#define SER1 4
43#define SER2 5
44#define RTCL 6
45#define KYBD 7
46#define AUXIO 8
47
48/* Chip register offsets from base */
49#define CONFIG_CONTROL 0x02
50#define INDEX_ADDRESS 0x03
51#define LOGICAL_DEVICE_NUMBER 0x07
52#define DEVICE_ID 0x20
53#define DEVICE_REV 0x21
54#define POWER_CONTROL 0x22
55#define POWER_MGMT 0x23
56#define OSC 0x24
57
58#define ACTIVATE 0x30
59#define ADDR_HI 0x60
60#define ADDR_LO 0x61
61#define INTERRUPT_SEL 0x70
62#define INTERRUPT_SEL_2 0x72 /* KYBD/MOUS only */
63#define DMA_CHANNEL_SEL 0x74 /* FDC/PARP only */
64
65#define FDD_MODE_REGISTER 0x90
66#define FDD_OPTION_REGISTER 0x91
67
68/* values that we read back that are expected ... */
69#define VALID_DEVICE_ID 2
70
71/* default device addresses */
72#define KYBD_INTERRUPT 1
73#define MOUS_INTERRUPT 12
74#define COM2_BASE 0x2f8
75#define COM2_INTERRUPT 3
76#define COM1_BASE 0x3f8
77#define COM1_INTERRUPT 4
78#define PARP_BASE 0x3bc
79#define PARP_INTERRUPT 7
80
81static unsigned long __init SMCConfigState(unsigned long baseAddr)
82{
83 unsigned char devId;
84 unsigned char devRev;
85
86 unsigned long configPort;
87 unsigned long indexPort;
88 unsigned long dataPort;
89
90 int i;
91
92 configPort = indexPort = baseAddr;
93 dataPort = configPort + 1;
94
95#define NUM_RETRIES 5
96
97 for (i = 0; i < NUM_RETRIES; i++)
98 {
99 outb(CONFIG_ON_KEY, configPort);
100 outb(CONFIG_ON_KEY, configPort);
101 outb(DEVICE_ID, indexPort);
102 devId = inb(dataPort);
103 if (devId == VALID_DEVICE_ID) {
104 outb(DEVICE_REV, indexPort);
105 devRev = inb(dataPort);
106 break;
107 }
108 else
109 udelay(100);
110 }
111 return (i != NUM_RETRIES) ? baseAddr : 0L;
112}
113
114static void __init SMCRunState(unsigned long baseAddr)
115{
116 outb(CONFIG_OFF_KEY, baseAddr);
117}
118
119static unsigned long __init SMCDetectUltraIO(void)
120{
121 unsigned long baseAddr;
122
123 baseAddr = 0x3F0;
124 if ( ( baseAddr = SMCConfigState( baseAddr ) ) == 0x3F0 ) {
125 return( baseAddr );
126 }
127 baseAddr = 0x370;
128 if ( ( baseAddr = SMCConfigState( baseAddr ) ) == 0x370 ) {
129 return( baseAddr );
130 }
131 return( ( unsigned long )0 );
132}
133
134static void __init SMCEnableDevice(unsigned long baseAddr,
135 unsigned long device,
136 unsigned long portaddr,
137 unsigned long interrupt)
138{
139 unsigned long indexPort;
140 unsigned long dataPort;
141
142 indexPort = baseAddr;
143 dataPort = baseAddr + 1;
144
145 outb(LOGICAL_DEVICE_NUMBER, indexPort);
146 outb(device, dataPort);
147
148 outb(ADDR_LO, indexPort);
149 outb(( portaddr & 0xFF ), dataPort);
150
151 outb(ADDR_HI, indexPort);
152 outb((portaddr >> 8) & 0xFF, dataPort);
153
154 outb(INTERRUPT_SEL, indexPort);
155 outb(interrupt, dataPort);
156
157 outb(ACTIVATE, indexPort);
158 outb(DEVICE_ON, dataPort);
159}
160
161static void __init SMCEnableKYBD(unsigned long baseAddr)
162{
163 unsigned long indexPort;
164 unsigned long dataPort;
165
166 indexPort = baseAddr;
167 dataPort = baseAddr + 1;
168
169 outb(LOGICAL_DEVICE_NUMBER, indexPort);
170 outb(KYBD, dataPort);
171
172 outb(INTERRUPT_SEL, indexPort); /* Primary interrupt select */
173 outb(KYBD_INTERRUPT, dataPort);
174
175 outb(INTERRUPT_SEL_2, indexPort); /* Secondary interrupt select */
176 outb(MOUS_INTERRUPT, dataPort);
177
178 outb(ACTIVATE, indexPort);
179 outb(DEVICE_ON, dataPort);
180}
181
182static void __init SMCEnableFDC(unsigned long baseAddr)
183{
184 unsigned long indexPort;
185 unsigned long dataPort;
186
187 unsigned char oldValue;
188
189 indexPort = baseAddr;
190 dataPort = baseAddr + 1;
191
192 outb(LOGICAL_DEVICE_NUMBER, indexPort);
193 outb(FDC, dataPort);
194
195 outb(FDD_MODE_REGISTER, indexPort);
196 oldValue = inb(dataPort);
197
198 oldValue |= 0x0E; /* Enable burst mode */
199 outb(oldValue, dataPort);
200
201 outb(INTERRUPT_SEL, indexPort); /* Primary interrupt select */
202 outb(0x06, dataPort );
203
204 outb(DMA_CHANNEL_SEL, indexPort); /* DMA channel select */
205 outb(0x02, dataPort);
206
207 outb(ACTIVATE, indexPort);
208 outb(DEVICE_ON, dataPort);
209}
210
211#if SMC_DEBUG
212static void __init SMCReportDeviceStatus(unsigned long baseAddr)
213{
214 unsigned long indexPort;
215 unsigned long dataPort;
216 unsigned char currentControl;
217
218 indexPort = baseAddr;
219 dataPort = baseAddr + 1;
220
221 outb(POWER_CONTROL, indexPort);
222 currentControl = inb(dataPort);
223
224 printk(currentControl & (1 << FDC)
225 ? "\t+FDC Enabled\n" : "\t-FDC Disabled\n");
226 printk(currentControl & (1 << IDE1)
227 ? "\t+IDE1 Enabled\n" : "\t-IDE1 Disabled\n");
228 printk(currentControl & (1 << IDE2)
229 ? "\t+IDE2 Enabled\n" : "\t-IDE2 Disabled\n");
230 printk(currentControl & (1 << PARP)
231 ? "\t+PARP Enabled\n" : "\t-PARP Disabled\n");
232 printk(currentControl & (1 << SER1)
233 ? "\t+SER1 Enabled\n" : "\t-SER1 Disabled\n");
234 printk(currentControl & (1 << SER2)
235 ? "\t+SER2 Enabled\n" : "\t-SER2 Disabled\n");
236
237 printk( "\n" );
238}
239#endif
240
241int __init SMC93x_Init(void)
242{
243 unsigned long SMCUltraBase;
244 unsigned long flags;
245
246 local_irq_save(flags);
247 if ((SMCUltraBase = SMCDetectUltraIO()) != 0UL) {
248#if SMC_DEBUG
249 SMCReportDeviceStatus(SMCUltraBase);
250#endif
251 SMCEnableDevice(SMCUltraBase, SER1, COM1_BASE, COM1_INTERRUPT);
252 DBG_DEVS(("SMC FDC37C93X: SER1 done\n"));
253 SMCEnableDevice(SMCUltraBase, SER2, COM2_BASE, COM2_INTERRUPT);
254 DBG_DEVS(("SMC FDC37C93X: SER2 done\n"));
255 SMCEnableDevice(SMCUltraBase, PARP, PARP_BASE, PARP_INTERRUPT);
256 DBG_DEVS(("SMC FDC37C93X: PARP done\n"));
257 /* On PC164, IDE on the SMC is not enabled;
258 CMD646 (PCI) on MB */
259 SMCEnableKYBD(SMCUltraBase);
260 DBG_DEVS(("SMC FDC37C93X: KYB done\n"));
261 SMCEnableFDC(SMCUltraBase);
262 DBG_DEVS(("SMC FDC37C93X: FDC done\n"));
263#if SMC_DEBUG
264 SMCReportDeviceStatus(SMCUltraBase);
265#endif
266 SMCRunState(SMCUltraBase);
267 local_irq_restore(flags);
268 printk("SMC FDC37C93X Ultra I/O Controller found @ 0x%lx\n",
269 SMCUltraBase);
270 return 1;
271 }
272 else {
273 local_irq_restore(flags);
274 DBG_DEVS(("No SMC FDC37C93X Ultra I/O Controller found\n"));
275 return 0;
276 }
277}
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
new file mode 100644
index 000000000000..8f1e78551b1e
--- /dev/null
+++ b/arch/alpha/kernel/smp.c
@@ -0,0 +1,1163 @@
1/*
2 * linux/arch/alpha/kernel/smp.c
3 *
4 * 2001-07-09 Phil Ezolt (Phillip.Ezolt@compaq.com)
5 * Renamed modified smp_call_function to smp_call_function_on_cpu()
6 * Created an function that conforms to the old calling convention
7 * of smp_call_function().
8 *
9 * This is helpful for DCPI.
10 *
11 */
12
13#include <linux/errno.h>
14#include <linux/kernel.h>
15#include <linux/kernel_stat.h>
16#include <linux/module.h>
17#include <linux/sched.h>
18#include <linux/mm.h>
19#include <linux/threads.h>
20#include <linux/smp.h>
21#include <linux/smp_lock.h>
22#include <linux/interrupt.h>
23#include <linux/init.h>
24#include <linux/delay.h>
25#include <linux/spinlock.h>
26#include <linux/irq.h>
27#include <linux/cache.h>
28#include <linux/profile.h>
29#include <linux/bitops.h>
30
31#include <asm/hwrpb.h>
32#include <asm/ptrace.h>
33#include <asm/atomic.h>
34
35#include <asm/io.h>
36#include <asm/irq.h>
37#include <asm/pgtable.h>
38#include <asm/pgalloc.h>
39#include <asm/mmu_context.h>
40#include <asm/tlbflush.h>
41
42#include "proto.h"
43#include "irq_impl.h"
44
45
46#define DEBUG_SMP 0
47#if DEBUG_SMP
48#define DBGS(args) printk args
49#else
50#define DBGS(args)
51#endif
52
53/* A collection of per-processor data. */
54struct cpuinfo_alpha cpu_data[NR_CPUS];
55
56/* A collection of single bit ipi messages. */
57static struct {
58 unsigned long bits ____cacheline_aligned;
59} ipi_data[NR_CPUS] __cacheline_aligned;
60
61enum ipi_message_type {
62 IPI_RESCHEDULE,
63 IPI_CALL_FUNC,
64 IPI_CPU_STOP,
65};
66
67/* Set to a secondary's cpuid when it comes online. */
68static int smp_secondary_alive __initdata = 0;
69
70/* Which cpus ids came online. */
71cpumask_t cpu_present_mask;
72cpumask_t cpu_online_map;
73
74EXPORT_SYMBOL(cpu_online_map);
75
76/* cpus reported in the hwrpb */
77static unsigned long hwrpb_cpu_present_mask __initdata = 0;
78
79int smp_num_probed; /* Internal processor count */
80int smp_num_cpus = 1; /* Number that came online. */
81
82extern void calibrate_delay(void);
83
84
85
86/*
87 * Called by both boot and secondaries to move global data into
88 * per-processor storage.
89 */
90static inline void __init
91smp_store_cpu_info(int cpuid)
92{
93 cpu_data[cpuid].loops_per_jiffy = loops_per_jiffy;
94 cpu_data[cpuid].last_asn = ASN_FIRST_VERSION;
95 cpu_data[cpuid].need_new_asn = 0;
96 cpu_data[cpuid].asn_lock = 0;
97}
98
99/*
100 * Ideally sets up per-cpu profiling hooks. Doesn't do much now...
101 */
102static inline void __init
103smp_setup_percpu_timer(int cpuid)
104{
105 cpu_data[cpuid].prof_counter = 1;
106 cpu_data[cpuid].prof_multiplier = 1;
107}
108
109static void __init
110wait_boot_cpu_to_stop(int cpuid)
111{
112 unsigned long stop = jiffies + 10*HZ;
113
114 while (time_before(jiffies, stop)) {
115 if (!smp_secondary_alive)
116 return;
117 barrier();
118 }
119
120 printk("wait_boot_cpu_to_stop: FAILED on CPU %d, hanging now\n", cpuid);
121 for (;;)
122 barrier();
123}
124
125/*
126 * Where secondaries begin a life of C.
127 */
128void __init
129smp_callin(void)
130{
131 int cpuid = hard_smp_processor_id();
132
133 if (cpu_test_and_set(cpuid, cpu_online_map)) {
134 printk("??, cpu 0x%x already present??\n", cpuid);
135 BUG();
136 }
137
138 /* Turn on machine checks. */
139 wrmces(7);
140
141 /* Set trap vectors. */
142 trap_init();
143
144 /* Set interrupt vector. */
145 wrent(entInt, 0);
146
147 /* Get our local ticker going. */
148 smp_setup_percpu_timer(cpuid);
149
150 /* Call platform-specific callin, if specified */
151 if (alpha_mv.smp_callin) alpha_mv.smp_callin();
152
153 /* All kernel threads share the same mm context. */
154 atomic_inc(&init_mm.mm_count);
155 current->active_mm = &init_mm;
156
157 /* Must have completely accurate bogos. */
158 local_irq_enable();
159
160 /* Wait boot CPU to stop with irq enabled before running
161 calibrate_delay. */
162 wait_boot_cpu_to_stop(cpuid);
163 mb();
164 calibrate_delay();
165
166 smp_store_cpu_info(cpuid);
167 /* Allow master to continue only after we written loops_per_jiffy. */
168 wmb();
169 smp_secondary_alive = 1;
170
171 DBGS(("smp_callin: commencing CPU %d current %p active_mm %p\n",
172 cpuid, current, current->active_mm));
173
174 /* Do nothing. */
175 cpu_idle();
176}
177
178/* Wait until hwrpb->txrdy is clear for cpu. Return -1 on timeout. */
179static int __init
180wait_for_txrdy (unsigned long cpumask)
181{
182 unsigned long timeout;
183
184 if (!(hwrpb->txrdy & cpumask))
185 return 0;
186
187 timeout = jiffies + 10*HZ;
188 while (time_before(jiffies, timeout)) {
189 if (!(hwrpb->txrdy & cpumask))
190 return 0;
191 udelay(10);
192 barrier();
193 }
194
195 return -1;
196}
197
198/*
199 * Send a message to a secondary's console. "START" is one such
200 * interesting message. ;-)
201 */
202static void __init
203send_secondary_console_msg(char *str, int cpuid)
204{
205 struct percpu_struct *cpu;
206 register char *cp1, *cp2;
207 unsigned long cpumask;
208 size_t len;
209
210 cpu = (struct percpu_struct *)
211 ((char*)hwrpb
212 + hwrpb->processor_offset
213 + cpuid * hwrpb->processor_size);
214
215 cpumask = (1UL << cpuid);
216 if (wait_for_txrdy(cpumask))
217 goto timeout;
218
219 cp2 = str;
220 len = strlen(cp2);
221 *(unsigned int *)&cpu->ipc_buffer[0] = len;
222 cp1 = (char *) &cpu->ipc_buffer[1];
223 memcpy(cp1, cp2, len);
224
225 /* atomic test and set */
226 wmb();
227 set_bit(cpuid, &hwrpb->rxrdy);
228
229 if (wait_for_txrdy(cpumask))
230 goto timeout;
231 return;
232
233 timeout:
234 printk("Processor %x not ready\n", cpuid);
235}
236
237/*
238 * A secondary console wants to send a message. Receive it.
239 */
240static void
241recv_secondary_console_msg(void)
242{
243 int mycpu, i, cnt;
244 unsigned long txrdy = hwrpb->txrdy;
245 char *cp1, *cp2, buf[80];
246 struct percpu_struct *cpu;
247
248 DBGS(("recv_secondary_console_msg: TXRDY 0x%lx.\n", txrdy));
249
250 mycpu = hard_smp_processor_id();
251
252 for (i = 0; i < NR_CPUS; i++) {
253 if (!(txrdy & (1UL << i)))
254 continue;
255
256 DBGS(("recv_secondary_console_msg: "
257 "TXRDY contains CPU %d.\n", i));
258
259 cpu = (struct percpu_struct *)
260 ((char*)hwrpb
261 + hwrpb->processor_offset
262 + i * hwrpb->processor_size);
263
264 DBGS(("recv_secondary_console_msg: on %d from %d"
265 " HALT_REASON 0x%lx FLAGS 0x%lx\n",
266 mycpu, i, cpu->halt_reason, cpu->flags));
267
268 cnt = cpu->ipc_buffer[0] >> 32;
269 if (cnt <= 0 || cnt >= 80)
270 strcpy(buf, "<<< BOGUS MSG >>>");
271 else {
272 cp1 = (char *) &cpu->ipc_buffer[11];
273 cp2 = buf;
274 strcpy(cp2, cp1);
275
276 while ((cp2 = strchr(cp2, '\r')) != 0) {
277 *cp2 = ' ';
278 if (cp2[1] == '\n')
279 cp2[1] = ' ';
280 }
281 }
282
283 DBGS((KERN_INFO "recv_secondary_console_msg: on %d "
284 "message is '%s'\n", mycpu, buf));
285 }
286
287 hwrpb->txrdy = 0;
288}
289
290/*
291 * Convince the console to have a secondary cpu begin execution.
292 */
293static int __init
294secondary_cpu_start(int cpuid, struct task_struct *idle)
295{
296 struct percpu_struct *cpu;
297 struct pcb_struct *hwpcb, *ipcb;
298 unsigned long timeout;
299
300 cpu = (struct percpu_struct *)
301 ((char*)hwrpb
302 + hwrpb->processor_offset
303 + cpuid * hwrpb->processor_size);
304 hwpcb = (struct pcb_struct *) cpu->hwpcb;
305 ipcb = &idle->thread_info->pcb;
306
307 /* Initialize the CPU's HWPCB to something just good enough for
308 us to get started. Immediately after starting, we'll swpctx
309 to the target idle task's pcb. Reuse the stack in the mean
310 time. Precalculate the target PCBB. */
311 hwpcb->ksp = (unsigned long)ipcb + sizeof(union thread_union) - 16;
312 hwpcb->usp = 0;
313 hwpcb->ptbr = ipcb->ptbr;
314 hwpcb->pcc = 0;
315 hwpcb->asn = 0;
316 hwpcb->unique = virt_to_phys(ipcb);
317 hwpcb->flags = ipcb->flags;
318 hwpcb->res1 = hwpcb->res2 = 0;
319
320#if 0
321 DBGS(("KSP 0x%lx PTBR 0x%lx VPTBR 0x%lx UNIQUE 0x%lx\n",
322 hwpcb->ksp, hwpcb->ptbr, hwrpb->vptb, hwpcb->unique));
323#endif
324 DBGS(("Starting secondary cpu %d: state 0x%lx pal_flags 0x%lx\n",
325 cpuid, idle->state, ipcb->flags));
326
327 /* Setup HWRPB fields that SRM uses to activate secondary CPU */
328 hwrpb->CPU_restart = __smp_callin;
329 hwrpb->CPU_restart_data = (unsigned long) __smp_callin;
330
331 /* Recalculate and update the HWRPB checksum */
332 hwrpb_update_checksum(hwrpb);
333
334 /*
335 * Send a "start" command to the specified processor.
336 */
337
338 /* SRM III 3.4.1.3 */
339 cpu->flags |= 0x22; /* turn on Context Valid and Restart Capable */
340 cpu->flags &= ~1; /* turn off Bootstrap In Progress */
341 wmb();
342
343 send_secondary_console_msg("START\r\n", cpuid);
344
345 /* Wait 10 seconds for an ACK from the console. */
346 timeout = jiffies + 10*HZ;
347 while (time_before(jiffies, timeout)) {
348 if (cpu->flags & 1)
349 goto started;
350 udelay(10);
351 barrier();
352 }
353 printk(KERN_ERR "SMP: Processor %d failed to start.\n", cpuid);
354 return -1;
355
356 started:
357 DBGS(("secondary_cpu_start: SUCCESS for CPU %d!!!\n", cpuid));
358 return 0;
359}
360
361/*
362 * Bring one cpu online.
363 */
364static int __init
365smp_boot_one_cpu(int cpuid)
366{
367 struct task_struct *idle;
368 unsigned long timeout;
369
370 /* Cook up an idler for this guy. Note that the address we
371 give to kernel_thread is irrelevant -- it's going to start
372 where HWRPB.CPU_restart says to start. But this gets all
373 the other task-y sort of data structures set up like we
374 wish. We can't use kernel_thread since we must avoid
375 rescheduling the child. */
376 idle = fork_idle(cpuid);
377 if (IS_ERR(idle))
378 panic("failed fork for CPU %d", cpuid);
379
380 DBGS(("smp_boot_one_cpu: CPU %d state 0x%lx flags 0x%lx\n",
381 cpuid, idle->state, idle->flags));
382
383 /* Signal the secondary to wait a moment. */
384 smp_secondary_alive = -1;
385
386 /* Whirrr, whirrr, whirrrrrrrrr... */
387 if (secondary_cpu_start(cpuid, idle))
388 return -1;
389
390 /* Notify the secondary CPU it can run calibrate_delay. */
391 mb();
392 smp_secondary_alive = 0;
393
394 /* We've been acked by the console; wait one second for
395 the task to start up for real. */
396 timeout = jiffies + 1*HZ;
397 while (time_before(jiffies, timeout)) {
398 if (smp_secondary_alive == 1)
399 goto alive;
400 udelay(10);
401 barrier();
402 }
403
404 /* We failed to boot the CPU. */
405
406 printk(KERN_ERR "SMP: Processor %d is stuck.\n", cpuid);
407 return -1;
408
409 alive:
410 /* Another "Red Snapper". */
411 return 0;
412}
413
414/*
415 * Called from setup_arch. Detect an SMP system and which processors
416 * are present.
417 */
418void __init
419setup_smp(void)
420{
421 struct percpu_struct *cpubase, *cpu;
422 unsigned long i;
423
424 if (boot_cpuid != 0) {
425 printk(KERN_WARNING "SMP: Booting off cpu %d instead of 0?\n",
426 boot_cpuid);
427 }
428
429 if (hwrpb->nr_processors > 1) {
430 int boot_cpu_palrev;
431
432 DBGS(("setup_smp: nr_processors %ld\n",
433 hwrpb->nr_processors));
434
435 cpubase = (struct percpu_struct *)
436 ((char*)hwrpb + hwrpb->processor_offset);
437 boot_cpu_palrev = cpubase->pal_revision;
438
439 for (i = 0; i < hwrpb->nr_processors; i++) {
440 cpu = (struct percpu_struct *)
441 ((char *)cpubase + i*hwrpb->processor_size);
442 if ((cpu->flags & 0x1cc) == 0x1cc) {
443 smp_num_probed++;
444 /* Assume here that "whami" == index */
445 hwrpb_cpu_present_mask |= (1UL << i);
446 cpu->pal_revision = boot_cpu_palrev;
447 }
448
449 DBGS(("setup_smp: CPU %d: flags 0x%lx type 0x%lx\n",
450 i, cpu->flags, cpu->type));
451 DBGS(("setup_smp: CPU %d: PAL rev 0x%lx\n",
452 i, cpu->pal_revision));
453 }
454 } else {
455 smp_num_probed = 1;
456 hwrpb_cpu_present_mask = (1UL << boot_cpuid);
457 }
458 cpu_present_mask = cpumask_of_cpu(boot_cpuid);
459
460 printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_mask = %lx\n",
461 smp_num_probed, hwrpb_cpu_present_mask);
462}
463
464/*
465 * Called by smp_init prepare the secondaries
466 */
467void __init
468smp_prepare_cpus(unsigned int max_cpus)
469{
470 int cpu_count, i;
471
472 /* Take care of some initial bookkeeping. */
473 memset(ipi_data, 0, sizeof(ipi_data));
474
475 current_thread_info()->cpu = boot_cpuid;
476
477 smp_store_cpu_info(boot_cpuid);
478 smp_setup_percpu_timer(boot_cpuid);
479
480 /* Nothing to do on a UP box, or when told not to. */
481 if (smp_num_probed == 1 || max_cpus == 0) {
482 cpu_present_mask = cpumask_of_cpu(boot_cpuid);
483 printk(KERN_INFO "SMP mode deactivated.\n");
484 return;
485 }
486
487 printk(KERN_INFO "SMP starting up secondaries.\n");
488
489 cpu_count = 1;
490 for (i = 0; (i < NR_CPUS) && (cpu_count < max_cpus); i++) {
491 if (i == boot_cpuid)
492 continue;
493
494 if (((hwrpb_cpu_present_mask >> i) & 1) == 0)
495 continue;
496
497 cpu_set(i, cpu_possible_map);
498 cpu_count++;
499 }
500
501 smp_num_cpus = cpu_count;
502}
503
504void __devinit
505smp_prepare_boot_cpu(void)
506{
507 /*
508 * Mark the boot cpu (current cpu) as both present and online
509 */
510 cpu_set(smp_processor_id(), cpu_present_mask);
511 cpu_set(smp_processor_id(), cpu_online_map);
512}
513
514int __devinit
515__cpu_up(unsigned int cpu)
516{
517 smp_boot_one_cpu(cpu);
518
519 return cpu_online(cpu) ? 0 : -ENOSYS;
520}
521
522void __init
523smp_cpus_done(unsigned int max_cpus)
524{
525 int cpu;
526 unsigned long bogosum = 0;
527
528 for(cpu = 0; cpu < NR_CPUS; cpu++)
529 if (cpu_online(cpu))
530 bogosum += cpu_data[cpu].loops_per_jiffy;
531
532 printk(KERN_INFO "SMP: Total of %d processors activated "
533 "(%lu.%02lu BogoMIPS).\n",
534 num_online_cpus(),
535 (bogosum + 2500) / (500000/HZ),
536 ((bogosum + 2500) / (5000/HZ)) % 100);
537}
538
539
540void
541smp_percpu_timer_interrupt(struct pt_regs *regs)
542{
543 int cpu = smp_processor_id();
544 unsigned long user = user_mode(regs);
545 struct cpuinfo_alpha *data = &cpu_data[cpu];
546
547 /* Record kernel PC. */
548 profile_tick(CPU_PROFILING, regs);
549
550 if (!--data->prof_counter) {
551 /* We need to make like a normal interrupt -- otherwise
552 timer interrupts ignore the global interrupt lock,
553 which would be a Bad Thing. */
554 irq_enter();
555
556 update_process_times(user);
557
558 data->prof_counter = data->prof_multiplier;
559
560 irq_exit();
561 }
562}
563
564int __init
565setup_profiling_timer(unsigned int multiplier)
566{
567 return -EINVAL;
568}
569
570
571static void
572send_ipi_message(cpumask_t to_whom, enum ipi_message_type operation)
573{
574 int i;
575
576 mb();
577 for_each_cpu_mask(i, to_whom)
578 set_bit(operation, &ipi_data[i].bits);
579
580 mb();
581 for_each_cpu_mask(i, to_whom)
582 wripir(i);
583}
584
585/* Structure and data for smp_call_function. This is designed to
586 minimize static memory requirements. Plus it looks cleaner. */
587
588struct smp_call_struct {
589 void (*func) (void *info);
590 void *info;
591 long wait;
592 atomic_t unstarted_count;
593 atomic_t unfinished_count;
594};
595
596static struct smp_call_struct *smp_call_function_data;
597
598/* Atomicly drop data into a shared pointer. The pointer is free if
599 it is initially locked. If retry, spin until free. */
600
601static int
602pointer_lock (void *lock, void *data, int retry)
603{
604 void *old, *tmp;
605
606 mb();
607 again:
608 /* Compare and swap with zero. */
609 asm volatile (
610 "1: ldq_l %0,%1\n"
611 " mov %3,%2\n"
612 " bne %0,2f\n"
613 " stq_c %2,%1\n"
614 " beq %2,1b\n"
615 "2:"
616 : "=&r"(old), "=m"(*(void **)lock), "=&r"(tmp)
617 : "r"(data)
618 : "memory");
619
620 if (old == 0)
621 return 0;
622 if (! retry)
623 return -EBUSY;
624
625 while (*(void **)lock)
626 barrier();
627 goto again;
628}
629
630void
631handle_ipi(struct pt_regs *regs)
632{
633 int this_cpu = smp_processor_id();
634 unsigned long *pending_ipis = &ipi_data[this_cpu].bits;
635 unsigned long ops;
636
637#if 0
638 DBGS(("handle_ipi: on CPU %d ops 0x%lx PC 0x%lx\n",
639 this_cpu, *pending_ipis, regs->pc));
640#endif
641
642 mb(); /* Order interrupt and bit testing. */
643 while ((ops = xchg(pending_ipis, 0)) != 0) {
644 mb(); /* Order bit clearing and data access. */
645 do {
646 unsigned long which;
647
648 which = ops & -ops;
649 ops &= ~which;
650 which = __ffs(which);
651
652 switch (which) {
653 case IPI_RESCHEDULE:
654 /* Reschedule callback. Everything to be done
655 is done by the interrupt return path. */
656 break;
657
658 case IPI_CALL_FUNC:
659 {
660 struct smp_call_struct *data;
661 void (*func)(void *info);
662 void *info;
663 int wait;
664
665 data = smp_call_function_data;
666 func = data->func;
667 info = data->info;
668 wait = data->wait;
669
670 /* Notify the sending CPU that the data has been
671 received, and execution is about to begin. */
672 mb();
673 atomic_dec (&data->unstarted_count);
674
675 /* At this point the structure may be gone unless
676 wait is true. */
677 (*func)(info);
678
679 /* Notify the sending CPU that the task is done. */
680 mb();
681 if (wait) atomic_dec (&data->unfinished_count);
682 break;
683 }
684
685 case IPI_CPU_STOP:
686 halt();
687
688 default:
689 printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n",
690 this_cpu, which);
691 break;
692 }
693 } while (ops);
694
695 mb(); /* Order data access and bit testing. */
696 }
697
698 cpu_data[this_cpu].ipi_count++;
699
700 if (hwrpb->txrdy)
701 recv_secondary_console_msg();
702}
703
704void
705smp_send_reschedule(int cpu)
706{
707#ifdef DEBUG_IPI_MSG
708 if (cpu == hard_smp_processor_id())
709 printk(KERN_WARNING
710 "smp_send_reschedule: Sending IPI to self.\n");
711#endif
712 send_ipi_message(cpumask_of_cpu(cpu), IPI_RESCHEDULE);
713}
714
715void
716smp_send_stop(void)
717{
718 cpumask_t to_whom = cpu_possible_map;
719 cpu_clear(smp_processor_id(), to_whom);
720#ifdef DEBUG_IPI_MSG
721 if (hard_smp_processor_id() != boot_cpu_id)
722 printk(KERN_WARNING "smp_send_stop: Not on boot cpu.\n");
723#endif
724 send_ipi_message(to_whom, IPI_CPU_STOP);
725}
726
727/*
728 * Run a function on all other CPUs.
729 * <func> The function to run. This must be fast and non-blocking.
730 * <info> An arbitrary pointer to pass to the function.
731 * <retry> If true, keep retrying until ready.
732 * <wait> If true, wait until function has completed on other CPUs.
733 * [RETURNS] 0 on success, else a negative status code.
734 *
735 * Does not return until remote CPUs are nearly ready to execute <func>
736 * or are or have executed.
737 * You must not call this function with disabled interrupts or from a
738 * hardware interrupt handler or from a bottom half handler.
739 */
740
741int
742smp_call_function_on_cpu (void (*func) (void *info), void *info, int retry,
743 int wait, cpumask_t to_whom)
744{
745 struct smp_call_struct data;
746 unsigned long timeout;
747 int num_cpus_to_call;
748
749 /* Can deadlock when called with interrupts disabled */
750 WARN_ON(irqs_disabled());
751
752 data.func = func;
753 data.info = info;
754 data.wait = wait;
755
756 cpu_clear(smp_processor_id(), to_whom);
757 num_cpus_to_call = cpus_weight(to_whom);
758
759 atomic_set(&data.unstarted_count, num_cpus_to_call);
760 atomic_set(&data.unfinished_count, num_cpus_to_call);
761
762 /* Acquire the smp_call_function_data mutex. */
763 if (pointer_lock(&smp_call_function_data, &data, retry))
764 return -EBUSY;
765
766 /* Send a message to the requested CPUs. */
767 send_ipi_message(to_whom, IPI_CALL_FUNC);
768
769 /* Wait for a minimal response. */
770 timeout = jiffies + HZ;
771 while (atomic_read (&data.unstarted_count) > 0
772 && time_before (jiffies, timeout))
773 barrier();
774
775 /* If there's no response yet, log a message but allow a longer
776 * timeout period -- if we get a response this time, log
777 * a message saying when we got it..
778 */
779 if (atomic_read(&data.unstarted_count) > 0) {
780 long start_time = jiffies;
781 printk(KERN_ERR "%s: initial timeout -- trying long wait\n",
782 __FUNCTION__);
783 timeout = jiffies + 30 * HZ;
784 while (atomic_read(&data.unstarted_count) > 0
785 && time_before(jiffies, timeout))
786 barrier();
787 if (atomic_read(&data.unstarted_count) <= 0) {
788 long delta = jiffies - start_time;
789 printk(KERN_ERR
790 "%s: response %ld.%ld seconds into long wait\n",
791 __FUNCTION__, delta / HZ,
792 (100 * (delta - ((delta / HZ) * HZ))) / HZ);
793 }
794 }
795
796 /* We either got one or timed out -- clear the lock. */
797 mb();
798 smp_call_function_data = NULL;
799
800 /*
801 * If after both the initial and long timeout periods we still don't
802 * have a response, something is very wrong...
803 */
804 BUG_ON(atomic_read (&data.unstarted_count) > 0);
805
806 /* Wait for a complete response, if needed. */
807 if (wait) {
808 while (atomic_read (&data.unfinished_count) > 0)
809 barrier();
810 }
811
812 return 0;
813}
814
815int
816smp_call_function (void (*func) (void *info), void *info, int retry, int wait)
817{
818 return smp_call_function_on_cpu (func, info, retry, wait,
819 cpu_online_map);
820}
821
822static void
823ipi_imb(void *ignored)
824{
825 imb();
826}
827
828void
829smp_imb(void)
830{
831 /* Must wait other processors to flush their icache before continue. */
832 if (on_each_cpu(ipi_imb, NULL, 1, 1))
833 printk(KERN_CRIT "smp_imb: timed out\n");
834}
835
836static void
837ipi_flush_tlb_all(void *ignored)
838{
839 tbia();
840}
841
842void
843flush_tlb_all(void)
844{
845 /* Although we don't have any data to pass, we do want to
846 synchronize with the other processors. */
847 if (on_each_cpu(ipi_flush_tlb_all, NULL, 1, 1)) {
848 printk(KERN_CRIT "flush_tlb_all: timed out\n");
849 }
850}
851
852#define asn_locked() (cpu_data[smp_processor_id()].asn_lock)
853
854static void
855ipi_flush_tlb_mm(void *x)
856{
857 struct mm_struct *mm = (struct mm_struct *) x;
858 if (mm == current->active_mm && !asn_locked())
859 flush_tlb_current(mm);
860 else
861 flush_tlb_other(mm);
862}
863
864void
865flush_tlb_mm(struct mm_struct *mm)
866{
867 preempt_disable();
868
869 if (mm == current->active_mm) {
870 flush_tlb_current(mm);
871 if (atomic_read(&mm->mm_users) <= 1) {
872 int cpu, this_cpu = smp_processor_id();
873 for (cpu = 0; cpu < NR_CPUS; cpu++) {
874 if (!cpu_online(cpu) || cpu == this_cpu)
875 continue;
876 if (mm->context[cpu])
877 mm->context[cpu] = 0;
878 }
879 preempt_enable();
880 return;
881 }
882 }
883
884 if (smp_call_function(ipi_flush_tlb_mm, mm, 1, 1)) {
885 printk(KERN_CRIT "flush_tlb_mm: timed out\n");
886 }
887
888 preempt_enable();
889}
890
891struct flush_tlb_page_struct {
892 struct vm_area_struct *vma;
893 struct mm_struct *mm;
894 unsigned long addr;
895};
896
897static void
898ipi_flush_tlb_page(void *x)
899{
900 struct flush_tlb_page_struct *data = (struct flush_tlb_page_struct *)x;
901 struct mm_struct * mm = data->mm;
902
903 if (mm == current->active_mm && !asn_locked())
904 flush_tlb_current_page(mm, data->vma, data->addr);
905 else
906 flush_tlb_other(mm);
907}
908
909void
910flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
911{
912 struct flush_tlb_page_struct data;
913 struct mm_struct *mm = vma->vm_mm;
914
915 preempt_disable();
916
917 if (mm == current->active_mm) {
918 flush_tlb_current_page(mm, vma, addr);
919 if (atomic_read(&mm->mm_users) <= 1) {
920 int cpu, this_cpu = smp_processor_id();
921 for (cpu = 0; cpu < NR_CPUS; cpu++) {
922 if (!cpu_online(cpu) || cpu == this_cpu)
923 continue;
924 if (mm->context[cpu])
925 mm->context[cpu] = 0;
926 }
927 preempt_enable();
928 return;
929 }
930 }
931
932 data.vma = vma;
933 data.mm = mm;
934 data.addr = addr;
935
936 if (smp_call_function(ipi_flush_tlb_page, &data, 1, 1)) {
937 printk(KERN_CRIT "flush_tlb_page: timed out\n");
938 }
939
940 preempt_enable();
941}
942
943void
944flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
945{
946 /* On the Alpha we always flush the whole user tlb. */
947 flush_tlb_mm(vma->vm_mm);
948}
949
950static void
951ipi_flush_icache_page(void *x)
952{
953 struct mm_struct *mm = (struct mm_struct *) x;
954 if (mm == current->active_mm && !asn_locked())
955 __load_new_mm_context(mm);
956 else
957 flush_tlb_other(mm);
958}
959
960void
961flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
962 unsigned long addr, int len)
963{
964 struct mm_struct *mm = vma->vm_mm;
965
966 if ((vma->vm_flags & VM_EXEC) == 0)
967 return;
968
969 preempt_disable();
970
971 if (mm == current->active_mm) {
972 __load_new_mm_context(mm);
973 if (atomic_read(&mm->mm_users) <= 1) {
974 int cpu, this_cpu = smp_processor_id();
975 for (cpu = 0; cpu < NR_CPUS; cpu++) {
976 if (!cpu_online(cpu) || cpu == this_cpu)
977 continue;
978 if (mm->context[cpu])
979 mm->context[cpu] = 0;
980 }
981 preempt_enable();
982 return;
983 }
984 }
985
986 if (smp_call_function(ipi_flush_icache_page, mm, 1, 1)) {
987 printk(KERN_CRIT "flush_icache_page: timed out\n");
988 }
989
990 preempt_enable();
991}
992
993#ifdef CONFIG_DEBUG_SPINLOCK
994void
995_raw_spin_unlock(spinlock_t * lock)
996{
997 mb();
998 lock->lock = 0;
999
1000 lock->on_cpu = -1;
1001 lock->previous = NULL;
1002 lock->task = NULL;
1003 lock->base_file = "none";
1004 lock->line_no = 0;
1005}
1006
1007void
1008debug_spin_lock(spinlock_t * lock, const char *base_file, int line_no)
1009{
1010 long tmp;
1011 long stuck;
1012 void *inline_pc = __builtin_return_address(0);
1013 unsigned long started = jiffies;
1014 int printed = 0;
1015 int cpu = smp_processor_id();
1016
1017 stuck = 1L << 30;
1018 try_again:
1019
1020 /* Use sub-sections to put the actual loop at the end
1021 of this object file's text section so as to perfect
1022 branch prediction. */
1023 __asm__ __volatile__(
1024 "1: ldl_l %0,%1\n"
1025 " subq %2,1,%2\n"
1026 " blbs %0,2f\n"
1027 " or %0,1,%0\n"
1028 " stl_c %0,%1\n"
1029 " beq %0,3f\n"
1030 "4: mb\n"
1031 ".subsection 2\n"
1032 "2: ldl %0,%1\n"
1033 " subq %2,1,%2\n"
1034 "3: blt %2,4b\n"
1035 " blbs %0,2b\n"
1036 " br 1b\n"
1037 ".previous"
1038 : "=r" (tmp), "=m" (lock->lock), "=r" (stuck)
1039 : "1" (lock->lock), "2" (stuck) : "memory");
1040
1041 if (stuck < 0) {
1042 printk(KERN_WARNING
1043 "%s:%d spinlock stuck in %s at %p(%d)"
1044 " owner %s at %p(%d) %s:%d\n",
1045 base_file, line_no,
1046 current->comm, inline_pc, cpu,
1047 lock->task->comm, lock->previous,
1048 lock->on_cpu, lock->base_file, lock->line_no);
1049 stuck = 1L << 36;
1050 printed = 1;
1051 goto try_again;
1052 }
1053
1054 /* Exiting. Got the lock. */
1055 lock->on_cpu = cpu;
1056 lock->previous = inline_pc;
1057 lock->task = current;
1058 lock->base_file = base_file;
1059 lock->line_no = line_no;
1060
1061 if (printed) {
1062 printk(KERN_WARNING
1063 "%s:%d spinlock grabbed in %s at %p(%d) %ld ticks\n",
1064 base_file, line_no, current->comm, inline_pc,
1065 cpu, jiffies - started);
1066 }
1067}
1068
1069int
1070debug_spin_trylock(spinlock_t * lock, const char *base_file, int line_no)
1071{
1072 int ret;
1073 if ((ret = !test_and_set_bit(0, lock))) {
1074 lock->on_cpu = smp_processor_id();
1075 lock->previous = __builtin_return_address(0);
1076 lock->task = current;
1077 } else {
1078 lock->base_file = base_file;
1079 lock->line_no = line_no;
1080 }
1081 return ret;
1082}
1083#endif /* CONFIG_DEBUG_SPINLOCK */
1084
1085#ifdef CONFIG_DEBUG_RWLOCK
1086void _raw_write_lock(rwlock_t * lock)
1087{
1088 long regx, regy;
1089 int stuck_lock, stuck_reader;
1090 void *inline_pc = __builtin_return_address(0);
1091
1092 try_again:
1093
1094 stuck_lock = 1<<30;
1095 stuck_reader = 1<<30;
1096
1097 __asm__ __volatile__(
1098 "1: ldl_l %1,%0\n"
1099 " blbs %1,6f\n"
1100 " blt %1,8f\n"
1101 " mov 1,%1\n"
1102 " stl_c %1,%0\n"
1103 " beq %1,6f\n"
1104 "4: mb\n"
1105 ".subsection 2\n"
1106 "6: blt %3,4b # debug\n"
1107 " subl %3,1,%3 # debug\n"
1108 " ldl %1,%0\n"
1109 " blbs %1,6b\n"
1110 "8: blt %4,4b # debug\n"
1111 " subl %4,1,%4 # debug\n"
1112 " ldl %1,%0\n"
1113 " blt %1,8b\n"
1114 " br 1b\n"
1115 ".previous"
1116 : "=m" (*(volatile int *)lock), "=&r" (regx), "=&r" (regy),
1117 "=&r" (stuck_lock), "=&r" (stuck_reader)
1118 : "0" (*(volatile int *)lock), "3" (stuck_lock), "4" (stuck_reader) : "memory");
1119
1120 if (stuck_lock < 0) {
1121 printk(KERN_WARNING "write_lock stuck at %p\n", inline_pc);
1122 goto try_again;
1123 }
1124 if (stuck_reader < 0) {
1125 printk(KERN_WARNING "write_lock stuck on readers at %p\n",
1126 inline_pc);
1127 goto try_again;
1128 }
1129}
1130
1131void _raw_read_lock(rwlock_t * lock)
1132{
1133 long regx;
1134 int stuck_lock;
1135 void *inline_pc = __builtin_return_address(0);
1136
1137 try_again:
1138
1139 stuck_lock = 1<<30;
1140
1141 __asm__ __volatile__(
1142 "1: ldl_l %1,%0;"
1143 " blbs %1,6f;"
1144 " subl %1,2,%1;"
1145 " stl_c %1,%0;"
1146 " beq %1,6f;"
1147 "4: mb\n"
1148 ".subsection 2\n"
1149 "6: ldl %1,%0;"
1150 " blt %2,4b # debug\n"
1151 " subl %2,1,%2 # debug\n"
1152 " blbs %1,6b;"
1153 " br 1b\n"
1154 ".previous"
1155 : "=m" (*(volatile int *)lock), "=&r" (regx), "=&r" (stuck_lock)
1156 : "0" (*(volatile int *)lock), "2" (stuck_lock) : "memory");
1157
1158 if (stuck_lock < 0) {
1159 printk(KERN_WARNING "read_lock stuck at %p\n", inline_pc);
1160 goto try_again;
1161 }
1162}
1163#endif /* CONFIG_DEBUG_RWLOCK */
diff --git a/arch/alpha/kernel/srm_env.c b/arch/alpha/kernel/srm_env.c
new file mode 100644
index 000000000000..5c98fc83e238
--- /dev/null
+++ b/arch/alpha/kernel/srm_env.c
@@ -0,0 +1,335 @@
1/*
2 * srm_env.c - Access to SRM environment
3 * variables through linux' procfs
4 *
5 * Copyright (C) 2001-2002 Jan-Benedict Glaw <jbglaw@lug-owl.de>
6 *
7 * This driver is at all a modified version of Erik Mouw's
8 * Documentation/DocBook/procfs_example.c, so: thank
9 * you, Erik! He can be reached via email at
10 * <J.A.K.Mouw@its.tudelft.nl>. It is based on an idea
11 * provided by DEC^WCompaq^WIntel's "Jumpstart" CD. They
12 * included a patch like this as well. Thanks for idea!
13 *
14 * This program is free software; you can redistribute
15 * it and/or modify it under the terms of the GNU General
16 * Public License version 2 as published by the Free Software
17 * Foundation.
18 *
19 * This program is distributed in the hope that it will be
20 * useful, but WITHOUT ANY WARRANTY; without even the implied
21 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
22 * PURPOSE. See the GNU General Public License for more
23 * details.
24 *
25 * You should have received a copy of the GNU General Public
26 * License along with this program; if not, write to the
27 * Free Software Foundation, Inc., 59 Temple Place,
28 * Suite 330, Boston, MA 02111-1307 USA
29 *
30 */
31
32/*
33 * Changelog
34 * ~~~~~~~~~
35 *
36 * Thu, 22 Aug 2002 15:10:43 +0200
37 * - Update Config.help entry. I got a number of emails asking
38 * me to tell their senders if they could make use of this
39 * piece of code... So: "SRM is something like BIOS for your
40 * Alpha"
41 * - Update code formatting a bit to better conform CodingStyle
42 * rules.
43 * - So this is v0.0.5, with no changes (except formatting)
44 *
45 * Wed, 22 May 2002 00:11:21 +0200
46 * - Fix typo on comment (SRC -> SRM)
47 * - Call this "Version 0.0.4"
48 *
49 * Tue, 9 Apr 2002 18:44:40 +0200
50 * - Implement access by variable name and additionally
51 * by number. This is done by creating two subdirectories
52 * where one holds all names (like the old directory
53 * did) and the other holding 256 files named like "0",
54 * "1" and so on.
55 * - Call this "Version 0.0.3"
56 *
57 */
58
59#include <linux/kernel.h>
60#include <linux/config.h>
61#include <linux/module.h>
62#include <linux/init.h>
63#include <linux/proc_fs.h>
64#include <asm/console.h>
65#include <asm/uaccess.h>
66#include <asm/machvec.h>
67
68#define BASE_DIR "srm_environment" /* Subdir in /proc/ */
69#define NAMED_DIR "named_variables" /* Subdir for known variables */
70#define NUMBERED_DIR "numbered_variables" /* Subdir for all variables */
71#define VERSION "0.0.5" /* Module version */
72#define NAME "srm_env" /* Module name */
73
74MODULE_AUTHOR("Jan-Benedict Glaw <jbglaw@lug-owl.de>");
75MODULE_DESCRIPTION("Accessing Alpha SRM environment through procfs interface");
76MODULE_LICENSE("GPL");
77
78typedef struct _srm_env {
79 char *name;
80 unsigned long id;
81 struct proc_dir_entry *proc_entry;
82} srm_env_t;
83
84static struct proc_dir_entry *base_dir;
85static struct proc_dir_entry *named_dir;
86static struct proc_dir_entry *numbered_dir;
87static char number[256][4];
88
89static srm_env_t srm_named_entries[] = {
90 { "auto_action", ENV_AUTO_ACTION },
91 { "boot_dev", ENV_BOOT_DEV },
92 { "bootdef_dev", ENV_BOOTDEF_DEV },
93 { "booted_dev", ENV_BOOTED_DEV },
94 { "boot_file", ENV_BOOT_FILE },
95 { "booted_file", ENV_BOOTED_FILE },
96 { "boot_osflags", ENV_BOOT_OSFLAGS },
97 { "booted_osflags", ENV_BOOTED_OSFLAGS },
98 { "boot_reset", ENV_BOOT_RESET },
99 { "dump_dev", ENV_DUMP_DEV },
100 { "enable_audit", ENV_ENABLE_AUDIT },
101 { "license", ENV_LICENSE },
102 { "char_set", ENV_CHAR_SET },
103 { "language", ENV_LANGUAGE },
104 { "tty_dev", ENV_TTY_DEV },
105 { NULL, 0 },
106};
107static srm_env_t srm_numbered_entries[256];
108
109
110
111static int
112srm_env_read(char *page, char **start, off_t off, int count, int *eof,
113 void *data)
114{
115 int nbytes;
116 unsigned long ret;
117 srm_env_t *entry;
118
119 if(off != 0)
120 return -EFAULT;
121
122 entry = (srm_env_t *) data;
123 ret = callback_getenv(entry->id, page, count);
124
125 if((ret >> 61) == 0)
126 nbytes = (int) ret;
127 else
128 nbytes = -EFAULT;
129
130 return nbytes;
131}
132
133
134static int
135srm_env_write(struct file *file, const char __user *buffer, unsigned long count,
136 void *data)
137{
138 int res;
139 srm_env_t *entry;
140 char *buf = (char *) __get_free_page(GFP_USER);
141 unsigned long ret1, ret2;
142
143 entry = (srm_env_t *) data;
144
145 if (!buf)
146 return -ENOMEM;
147
148 res = -EINVAL;
149 if (count >= PAGE_SIZE)
150 goto out;
151
152 res = -EFAULT;
153 if (copy_from_user(buf, buffer, count))
154 goto out;
155 buf[count] = '\0';
156
157 ret1 = callback_setenv(entry->id, buf, count);
158 if ((ret1 >> 61) == 0) {
159 do
160 ret2 = callback_save_env();
161 while((ret2 >> 61) == 1);
162 res = (int) ret1;
163 }
164
165 out:
166 free_page((unsigned long)buf);
167 return res;
168}
169
170static void
171srm_env_cleanup(void)
172{
173 srm_env_t *entry;
174 unsigned long var_num;
175
176 if(base_dir) {
177 /*
178 * Remove named entries
179 */
180 if(named_dir) {
181 entry = srm_named_entries;
182 while(entry->name != NULL && entry->id != 0) {
183 if(entry->proc_entry) {
184 remove_proc_entry(entry->name,
185 named_dir);
186 entry->proc_entry = NULL;
187 }
188 entry++;
189 }
190 remove_proc_entry(NAMED_DIR, base_dir);
191 }
192
193 /*
194 * Remove numbered entries
195 */
196 if(numbered_dir) {
197 for(var_num = 0; var_num <= 255; var_num++) {
198 entry = &srm_numbered_entries[var_num];
199
200 if(entry->proc_entry) {
201 remove_proc_entry(entry->name,
202 numbered_dir);
203 entry->proc_entry = NULL;
204 entry->name = NULL;
205 }
206 }
207 remove_proc_entry(NUMBERED_DIR, base_dir);
208 }
209
210 remove_proc_entry(BASE_DIR, NULL);
211 }
212
213 return;
214}
215
216
217static int __init
218srm_env_init(void)
219{
220 srm_env_t *entry;
221 unsigned long var_num;
222
223 /*
224 * Check system
225 */
226 if(!alpha_using_srm) {
227 printk(KERN_INFO "%s: This Alpha system doesn't "
228 "know about SRM (or you've booted "
229 "SRM->MILO->Linux, which gets "
230 "misdetected)...\n", __FUNCTION__);
231 return -ENODEV;
232 }
233
234 /*
235 * Init numbers
236 */
237 for(var_num = 0; var_num <= 255; var_num++)
238 sprintf(number[var_num], "%ld", var_num);
239
240 /*
241 * Create base directory
242 */
243 base_dir = proc_mkdir(BASE_DIR, NULL);
244 if(base_dir == NULL) {
245 printk(KERN_ERR "Couldn't create base dir /proc/%s\n",
246 BASE_DIR);
247 goto cleanup;
248 }
249 base_dir->owner = THIS_MODULE;
250
251 /*
252 * Create per-name subdirectory
253 */
254 named_dir = proc_mkdir(NAMED_DIR, base_dir);
255 if(named_dir == NULL) {
256 printk(KERN_ERR "Couldn't create dir /proc/%s/%s\n",
257 BASE_DIR, NAMED_DIR);
258 goto cleanup;
259 }
260 named_dir->owner = THIS_MODULE;
261
262 /*
263 * Create per-number subdirectory
264 */
265 numbered_dir = proc_mkdir(NUMBERED_DIR, base_dir);
266 if(numbered_dir == NULL) {
267 printk(KERN_ERR "Couldn't create dir /proc/%s/%s\n",
268 BASE_DIR, NUMBERED_DIR);
269 goto cleanup;
270
271 }
272 numbered_dir->owner = THIS_MODULE;
273
274 /*
275 * Create all named nodes
276 */
277 entry = srm_named_entries;
278 while(entry->name != NULL && entry->id != 0) {
279 entry->proc_entry = create_proc_entry(entry->name,
280 0644, named_dir);
281 if(entry->proc_entry == NULL)
282 goto cleanup;
283
284 entry->proc_entry->data = (void *) entry;
285 entry->proc_entry->owner = THIS_MODULE;
286 entry->proc_entry->read_proc = srm_env_read;
287 entry->proc_entry->write_proc = srm_env_write;
288
289 entry++;
290 }
291
292 /*
293 * Create all numbered nodes
294 */
295 for(var_num = 0; var_num <= 255; var_num++) {
296 entry = &srm_numbered_entries[var_num];
297 entry->name = number[var_num];
298
299 entry->proc_entry = create_proc_entry(entry->name,
300 0644, numbered_dir);
301 if(entry->proc_entry == NULL)
302 goto cleanup;
303
304 entry->id = var_num;
305 entry->proc_entry->data = (void *) entry;
306 entry->proc_entry->owner = THIS_MODULE;
307 entry->proc_entry->read_proc = srm_env_read;
308 entry->proc_entry->write_proc = srm_env_write;
309 }
310
311 printk(KERN_INFO "%s: version %s loaded successfully\n", NAME,
312 VERSION);
313
314 return 0;
315
316cleanup:
317 srm_env_cleanup();
318
319 return -ENOMEM;
320}
321
322
323static void __exit
324srm_env_exit(void)
325{
326 srm_env_cleanup();
327 printk(KERN_INFO "%s: unloaded successfully\n", NAME);
328
329 return;
330}
331
332
333module_init(srm_env_init);
334module_exit(srm_env_exit);
335
diff --git a/arch/alpha/kernel/srmcons.c b/arch/alpha/kernel/srmcons.c
new file mode 100644
index 000000000000..3b30d4f1fc42
--- /dev/null
+++ b/arch/alpha/kernel/srmcons.c
@@ -0,0 +1,326 @@
1/*
2 * linux/arch/alpha/kernel/srmcons.c
3 *
4 * Callback based driver for SRM Console console device.
5 * (TTY driver and console driver)
6 */
7
8#include <linux/config.h>
9#include <linux/kernel.h>
10#include <linux/init.h>
11#include <linux/console.h>
12#include <linux/delay.h>
13#include <linux/mm.h>
14#include <linux/slab.h>
15#include <linux/spinlock.h>
16#include <linux/timer.h>
17#include <linux/tty.h>
18#include <linux/tty_driver.h>
19#include <linux/tty_flip.h>
20
21#include <asm/console.h>
22#include <asm/uaccess.h>
23
24
25static DEFINE_SPINLOCK(srmcons_callback_lock);
26static int srm_is_registered_console = 0;
27
28/*
29 * The TTY driver
30 */
31#define MAX_SRM_CONSOLE_DEVICES 1 /* only support 1 console device */
32
33struct srmcons_private {
34 struct tty_struct *tty;
35 struct timer_list timer;
36 spinlock_t lock;
37};
38
39typedef union _srmcons_result {
40 struct {
41 unsigned long c :61;
42 unsigned long status :3;
43 } bits;
44 long as_long;
45} srmcons_result;
46
47/* called with callback_lock held */
48static int
49srmcons_do_receive_chars(struct tty_struct *tty)
50{
51 srmcons_result result;
52 int count = 0, loops = 0;
53
54 do {
55 result.as_long = callback_getc(0);
56 if (result.bits.status < 2) {
57 tty_insert_flip_char(tty, (char)result.bits.c, 0);
58 count++;
59 }
60 } while((result.bits.status & 1) && (++loops < 10));
61
62 if (count)
63 tty_schedule_flip(tty);
64
65 return count;
66}
67
68static void
69srmcons_receive_chars(unsigned long data)
70{
71 struct srmcons_private *srmconsp = (struct srmcons_private *)data;
72 unsigned long flags;
73 int incr = 10;
74
75 local_irq_save(flags);
76 if (spin_trylock(&srmcons_callback_lock)) {
77 if (!srmcons_do_receive_chars(srmconsp->tty))
78 incr = 100;
79 spin_unlock(&srmcons_callback_lock);
80 }
81
82 spin_lock(&srmconsp->lock);
83 if (srmconsp->tty) {
84 srmconsp->timer.expires = jiffies + incr;
85 add_timer(&srmconsp->timer);
86 }
87 spin_unlock(&srmconsp->lock);
88
89 local_irq_restore(flags);
90}
91
92/* called with callback_lock held */
93static int
94srmcons_do_write(struct tty_struct *tty, const char *buf, int count)
95{
96 static char str_cr[1] = "\r";
97 long c, remaining = count;
98 srmcons_result result;
99 char *cur;
100 int need_cr;
101
102 for (cur = (char *)buf; remaining > 0; ) {
103 need_cr = 0;
104 /*
105 * Break it up into reasonable size chunks to allow a chance
106 * for input to get in
107 */
108 for (c = 0; c < min_t(long, 128L, remaining) && !need_cr; c++)
109 if (cur[c] == '\n')
110 need_cr = 1;
111
112 while (c > 0) {
113 result.as_long = callback_puts(0, cur, c);
114 c -= result.bits.c;
115 remaining -= result.bits.c;
116 cur += result.bits.c;
117
118 /*
119 * Check for pending input iff a tty was provided
120 */
121 if (tty)
122 srmcons_do_receive_chars(tty);
123 }
124
125 while (need_cr) {
126 result.as_long = callback_puts(0, str_cr, 1);
127 if (result.bits.c > 0)
128 need_cr = 0;
129 }
130 }
131 return count;
132}
133
134static int
135srmcons_write(struct tty_struct *tty,
136 const unsigned char *buf, int count)
137{
138 unsigned long flags;
139
140 spin_lock_irqsave(&srmcons_callback_lock, flags);
141 srmcons_do_write(tty, (const char *) buf, count);
142 spin_unlock_irqrestore(&srmcons_callback_lock, flags);
143
144 return count;
145}
146
147static int
148srmcons_write_room(struct tty_struct *tty)
149{
150 return 512;
151}
152
153static int
154srmcons_chars_in_buffer(struct tty_struct *tty)
155{
156 return 0;
157}
158
159static int
160srmcons_get_private_struct(struct srmcons_private **ps)
161{
162 static struct srmcons_private *srmconsp = NULL;
163 static DEFINE_SPINLOCK(srmconsp_lock);
164 unsigned long flags;
165 int retval = 0;
166
167 if (srmconsp == NULL) {
168 spin_lock_irqsave(&srmconsp_lock, flags);
169
170 srmconsp = kmalloc(sizeof(*srmconsp), GFP_KERNEL);
171 if (srmconsp == NULL)
172 retval = -ENOMEM;
173 else {
174 srmconsp->tty = NULL;
175 spin_lock_init(&srmconsp->lock);
176 init_timer(&srmconsp->timer);
177 }
178
179 spin_unlock_irqrestore(&srmconsp_lock, flags);
180 }
181
182 *ps = srmconsp;
183 return retval;
184}
185
186static int
187srmcons_open(struct tty_struct *tty, struct file *filp)
188{
189 struct srmcons_private *srmconsp;
190 unsigned long flags;
191 int retval;
192
193 retval = srmcons_get_private_struct(&srmconsp);
194 if (retval)
195 return retval;
196
197 spin_lock_irqsave(&srmconsp->lock, flags);
198
199 if (!srmconsp->tty) {
200 tty->driver_data = srmconsp;
201
202 srmconsp->tty = tty;
203 srmconsp->timer.function = srmcons_receive_chars;
204 srmconsp->timer.data = (unsigned long)srmconsp;
205 srmconsp->timer.expires = jiffies + 10;
206 add_timer(&srmconsp->timer);
207 }
208
209 spin_unlock_irqrestore(&srmconsp->lock, flags);
210
211 return 0;
212}
213
214static void
215srmcons_close(struct tty_struct *tty, struct file *filp)
216{
217 struct srmcons_private *srmconsp = tty->driver_data;
218 unsigned long flags;
219
220 spin_lock_irqsave(&srmconsp->lock, flags);
221
222 if (tty->count == 1) {
223 srmconsp->tty = NULL;
224 del_timer(&srmconsp->timer);
225 }
226
227 spin_unlock_irqrestore(&srmconsp->lock, flags);
228}
229
230
231static struct tty_driver *srmcons_driver;
232
233static struct tty_operations srmcons_ops = {
234 .open = srmcons_open,
235 .close = srmcons_close,
236 .write = srmcons_write,
237 .write_room = srmcons_write_room,
238 .chars_in_buffer= srmcons_chars_in_buffer,
239};
240
241static int __init
242srmcons_init(void)
243{
244 if (srm_is_registered_console) {
245 struct tty_driver *driver;
246 int err;
247
248 driver = alloc_tty_driver(MAX_SRM_CONSOLE_DEVICES);
249 if (!driver)
250 return -ENOMEM;
251 driver->driver_name = "srm";
252 driver->name = "srm";
253 driver->major = 0; /* dynamic */
254 driver->minor_start = 0;
255 driver->type = TTY_DRIVER_TYPE_SYSTEM;
256 driver->subtype = SYSTEM_TYPE_SYSCONS;
257 driver->init_termios = tty_std_termios;
258 tty_set_operations(driver, &srmcons_ops);
259 err = tty_register_driver(driver);
260 if (err) {
261 put_tty_driver(driver);
262 return err;
263 }
264 srmcons_driver = driver;
265 }
266
267 return -ENODEV;
268}
269
270module_init(srmcons_init);
271
272
273/*
274 * The console driver
275 */
276static void
277srm_console_write(struct console *co, const char *s, unsigned count)
278{
279 unsigned long flags;
280
281 spin_lock_irqsave(&srmcons_callback_lock, flags);
282 srmcons_do_write(NULL, s, count);
283 spin_unlock_irqrestore(&srmcons_callback_lock, flags);
284}
285
286static struct tty_driver *
287srm_console_device(struct console *co, int *index)
288{
289 *index = co->index;
290 return srmcons_driver;
291}
292
293static int __init
294srm_console_setup(struct console *co, char *options)
295{
296 return 0;
297}
298
299static struct console srmcons = {
300 .name = "srm",
301 .write = srm_console_write,
302 .device = srm_console_device,
303 .setup = srm_console_setup,
304 .flags = CON_PRINTBUFFER,
305 .index = -1,
306};
307
308void __init
309register_srm_console(void)
310{
311 if (!srm_is_registered_console) {
312 callback_open_console();
313 register_console(&srmcons);
314 srm_is_registered_console = 1;
315 }
316}
317
318void __init
319unregister_srm_console(void)
320{
321 if (srm_is_registered_console) {
322 callback_close_console();
323 unregister_console(&srmcons);
324 srm_is_registered_console = 0;
325 }
326}
diff --git a/arch/alpha/kernel/sys_alcor.c b/arch/alpha/kernel/sys_alcor.c
new file mode 100644
index 000000000000..145dcde143ae
--- /dev/null
+++ b/arch/alpha/kernel/sys_alcor.c
@@ -0,0 +1,326 @@
1/*
2 * linux/arch/alpha/kernel/sys_alcor.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996 Jay A Estabrook
6 * Copyright (C) 1998, 1999 Richard Henderson
7 *
8 * Code supporting the ALCOR and XLT (XL-300/366/433).
9 */
10
11#include <linux/config.h>
12#include <linux/kernel.h>
13#include <linux/types.h>
14#include <linux/mm.h>
15#include <linux/sched.h>
16#include <linux/pci.h>
17#include <linux/init.h>
18#include <linux/reboot.h>
19#include <linux/bitops.h>
20
21#include <asm/ptrace.h>
22#include <asm/system.h>
23#include <asm/io.h>
24#include <asm/dma.h>
25#include <asm/mmu_context.h>
26#include <asm/irq.h>
27#include <asm/pgtable.h>
28#include <asm/core_cia.h>
29#include <asm/tlbflush.h>
30
31#include "proto.h"
32#include "irq_impl.h"
33#include "pci_impl.h"
34#include "machvec_impl.h"
35
36
37/* Note mask bit is true for ENABLED irqs. */
38static unsigned long cached_irq_mask;
39
40static inline void
41alcor_update_irq_hw(unsigned long mask)
42{
43 *(vuip)GRU_INT_MASK = mask;
44 mb();
45}
46
47static inline void
48alcor_enable_irq(unsigned int irq)
49{
50 alcor_update_irq_hw(cached_irq_mask |= 1UL << (irq - 16));
51}
52
53static void
54alcor_disable_irq(unsigned int irq)
55{
56 alcor_update_irq_hw(cached_irq_mask &= ~(1UL << (irq - 16)));
57}
58
59static void
60alcor_mask_and_ack_irq(unsigned int irq)
61{
62 alcor_disable_irq(irq);
63
64 /* On ALCOR/XLT, need to dismiss interrupt via GRU. */
65 *(vuip)GRU_INT_CLEAR = 1 << (irq - 16); mb();
66 *(vuip)GRU_INT_CLEAR = 0; mb();
67}
68
69static unsigned int
70alcor_startup_irq(unsigned int irq)
71{
72 alcor_enable_irq(irq);
73 return 0;
74}
75
76static void
77alcor_isa_mask_and_ack_irq(unsigned int irq)
78{
79 i8259a_mask_and_ack_irq(irq);
80
81 /* On ALCOR/XLT, need to dismiss interrupt via GRU. */
82 *(vuip)GRU_INT_CLEAR = 0x80000000; mb();
83 *(vuip)GRU_INT_CLEAR = 0; mb();
84}
85
86static void
87alcor_end_irq(unsigned int irq)
88{
89 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
90 alcor_enable_irq(irq);
91}
92
93static struct hw_interrupt_type alcor_irq_type = {
94 .typename = "ALCOR",
95 .startup = alcor_startup_irq,
96 .shutdown = alcor_disable_irq,
97 .enable = alcor_enable_irq,
98 .disable = alcor_disable_irq,
99 .ack = alcor_mask_and_ack_irq,
100 .end = alcor_end_irq,
101};
102
103static void
104alcor_device_interrupt(unsigned long vector, struct pt_regs *regs)
105{
106 unsigned long pld;
107 unsigned int i;
108
109 /* Read the interrupt summary register of the GRU */
110 pld = (*(vuip)GRU_INT_REQ) & GRU_INT_REQ_BITS;
111
112 /*
113 * Now for every possible bit set, work through them and call
114 * the appropriate interrupt handler.
115 */
116 while (pld) {
117 i = ffz(~pld);
118 pld &= pld - 1; /* clear least bit set */
119 if (i == 31) {
120 isa_device_interrupt(vector, regs);
121 } else {
122 handle_irq(16 + i, regs);
123 }
124 }
125}
126
127static void __init
128alcor_init_irq(void)
129{
130 long i;
131
132 if (alpha_using_srm)
133 alpha_mv.device_interrupt = srm_device_interrupt;
134
135 *(vuip)GRU_INT_MASK = 0; mb(); /* all disabled */
136 *(vuip)GRU_INT_EDGE = 0; mb(); /* all are level */
137 *(vuip)GRU_INT_HILO = 0x80000000U; mb(); /* ISA only HI */
138 *(vuip)GRU_INT_CLEAR = 0; mb(); /* all clear */
139
140 for (i = 16; i < 48; ++i) {
141 /* On Alcor, at least, lines 20..30 are not connected
142 and can generate spurrious interrupts if we turn them
143 on while IRQ probing. */
144 if (i >= 16+20 && i <= 16+30)
145 continue;
146 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
147 irq_desc[i].handler = &alcor_irq_type;
148 }
149 i8259a_irq_type.ack = alcor_isa_mask_and_ack_irq;
150
151 init_i8259a_irqs();
152 common_init_isa_dma();
153
154 setup_irq(16+31, &isa_cascade_irqaction);
155}
156
157
158/*
159 * PCI Fixup configuration.
160 *
161 * Summary @ GRU_INT_REQ:
162 * Bit Meaning
163 * 0 Interrupt Line A from slot 2
164 * 1 Interrupt Line B from slot 2
165 * 2 Interrupt Line C from slot 2
166 * 3 Interrupt Line D from slot 2
167 * 4 Interrupt Line A from slot 1
168 * 5 Interrupt line B from slot 1
169 * 6 Interrupt Line C from slot 1
170 * 7 Interrupt Line D from slot 1
171 * 8 Interrupt Line A from slot 0
172 * 9 Interrupt Line B from slot 0
173 *10 Interrupt Line C from slot 0
174 *11 Interrupt Line D from slot 0
175 *12 Interrupt Line A from slot 4
176 *13 Interrupt Line B from slot 4
177 *14 Interrupt Line C from slot 4
178 *15 Interrupt Line D from slot 4
179 *16 Interrupt Line D from slot 3
180 *17 Interrupt Line D from slot 3
181 *18 Interrupt Line D from slot 3
182 *19 Interrupt Line D from slot 3
183 *20-30 Reserved
184 *31 EISA interrupt
185 *
186 * The device to slot mapping looks like:
187 *
188 * Slot Device
189 * 6 built-in TULIP (XLT only)
190 * 7 PCI on board slot 0
191 * 8 PCI on board slot 3
192 * 9 PCI on board slot 4
193 * 10 PCEB (PCI-EISA bridge)
194 * 11 PCI on board slot 2
195 * 12 PCI on board slot 1
196 *
197 *
198 * This two layered interrupt approach means that we allocate IRQ 16 and
199 * above for PCI interrupts. The IRQ relates to which bit the interrupt
200 * comes in on. This makes interrupt processing much easier.
201 */
202
203static int __init
204alcor_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
205{
206 static char irq_tab[7][5] __initdata = {
207 /*INT INTA INTB INTC INTD */
208 /* note: IDSEL 17 is XLT only */
209 {16+13, 16+13, 16+13, 16+13, 16+13}, /* IdSel 17, TULIP */
210 { 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 18, slot 0 */
211 {16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 19, slot 3 */
212 {16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 20, slot 4 */
213 { -1, -1, -1, -1, -1}, /* IdSel 21, PCEB */
214 { 16+0, 16+0, 16+1, 16+2, 16+3}, /* IdSel 22, slot 2 */
215 { 16+4, 16+4, 16+5, 16+6, 16+7}, /* IdSel 23, slot 1 */
216 };
217 const long min_idsel = 6, max_idsel = 12, irqs_per_slot = 5;
218 return COMMON_TABLE_LOOKUP;
219}
220
221static void
222alcor_kill_arch(int mode)
223{
224 cia_kill_arch(mode);
225
226#ifndef ALPHA_RESTORE_SRM_SETUP
227 switch(mode) {
228 case LINUX_REBOOT_CMD_RESTART:
229 /* Who said DEC engineer's have no sense of humor? ;-) */
230 if (alpha_using_srm) {
231 *(vuip) GRU_RESET = 0x0000dead;
232 mb();
233 }
234 break;
235 case LINUX_REBOOT_CMD_HALT:
236 break;
237 case LINUX_REBOOT_CMD_POWER_OFF:
238 break;
239 }
240
241 halt();
242#endif
243}
244
245static void __init
246alcor_init_pci(void)
247{
248 struct pci_dev *dev;
249
250 cia_init_pci();
251
252 /*
253 * Now we can look to see if we are really running on an XLT-type
254 * motherboard, by looking for a 21040 TULIP in slot 6, which is
255 * built into XLT and BRET/MAVERICK, but not available on ALCOR.
256 */
257 dev = pci_find_device(PCI_VENDOR_ID_DEC,
258 PCI_DEVICE_ID_DEC_TULIP,
259 NULL);
260 if (dev && dev->devfn == PCI_DEVFN(6,0)) {
261 alpha_mv.sys.cia.gru_int_req_bits = XLT_GRU_INT_REQ_BITS;
262 printk(KERN_INFO "%s: Detected AS500 or XLT motherboard.\n",
263 __FUNCTION__);
264 }
265}
266
267
268/*
269 * The System Vectors
270 */
271
272struct alpha_machine_vector alcor_mv __initmv = {
273 .vector_name = "Alcor",
274 DO_EV5_MMU,
275 DO_DEFAULT_RTC,
276 DO_CIA_IO,
277 .machine_check = cia_machine_check,
278 .max_isa_dma_address = ALPHA_ALCOR_MAX_ISA_DMA_ADDRESS,
279 .min_io_address = EISA_DEFAULT_IO_BASE,
280 .min_mem_address = CIA_DEFAULT_MEM_BASE,
281
282 .nr_irqs = 48,
283 .device_interrupt = alcor_device_interrupt,
284
285 .init_arch = cia_init_arch,
286 .init_irq = alcor_init_irq,
287 .init_rtc = common_init_rtc,
288 .init_pci = alcor_init_pci,
289 .kill_arch = alcor_kill_arch,
290 .pci_map_irq = alcor_map_irq,
291 .pci_swizzle = common_swizzle,
292
293 .sys = { .cia = {
294 .gru_int_req_bits = ALCOR_GRU_INT_REQ_BITS
295 }}
296};
297ALIAS_MV(alcor)
298
299struct alpha_machine_vector xlt_mv __initmv = {
300 .vector_name = "XLT",
301 DO_EV5_MMU,
302 DO_DEFAULT_RTC,
303 DO_CIA_IO,
304 .machine_check = cia_machine_check,
305 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
306 .min_io_address = EISA_DEFAULT_IO_BASE,
307 .min_mem_address = CIA_DEFAULT_MEM_BASE,
308
309 .nr_irqs = 48,
310 .device_interrupt = alcor_device_interrupt,
311
312 .init_arch = cia_init_arch,
313 .init_irq = alcor_init_irq,
314 .init_rtc = common_init_rtc,
315 .init_pci = alcor_init_pci,
316 .kill_arch = alcor_kill_arch,
317 .pci_map_irq = alcor_map_irq,
318 .pci_swizzle = common_swizzle,
319
320 .sys = { .cia = {
321 .gru_int_req_bits = XLT_GRU_INT_REQ_BITS
322 }}
323};
324
325/* No alpha_mv alias for XLT, since we compile it in unconditionally
326 with ALCOR; setup_arch knows how to cope. */
diff --git a/arch/alpha/kernel/sys_cabriolet.c b/arch/alpha/kernel/sys_cabriolet.c
new file mode 100644
index 000000000000..8e3374d34c95
--- /dev/null
+++ b/arch/alpha/kernel/sys_cabriolet.c
@@ -0,0 +1,448 @@
1/*
2 * linux/arch/alpha/kernel/sys_cabriolet.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996 Jay A Estabrook
6 * Copyright (C) 1998, 1999, 2000 Richard Henderson
7 *
8 * Code supporting the Cabriolet (AlphaPC64), EB66+, and EB164,
9 * PC164 and LX164.
10 */
11
12#include <linux/config.h>
13#include <linux/kernel.h>
14#include <linux/types.h>
15#include <linux/mm.h>
16#include <linux/sched.h>
17#include <linux/pci.h>
18#include <linux/init.h>
19#include <linux/bitops.h>
20
21#include <asm/ptrace.h>
22#include <asm/system.h>
23#include <asm/dma.h>
24#include <asm/irq.h>
25#include <asm/mmu_context.h>
26#include <asm/io.h>
27#include <asm/pgtable.h>
28#include <asm/core_apecs.h>
29#include <asm/core_cia.h>
30#include <asm/core_lca.h>
31#include <asm/tlbflush.h>
32
33#include "proto.h"
34#include "irq_impl.h"
35#include "pci_impl.h"
36#include "machvec_impl.h"
37
38
39/* Note mask bit is true for DISABLED irqs. */
40static unsigned long cached_irq_mask = ~0UL;
41
42static inline void
43cabriolet_update_irq_hw(unsigned int irq, unsigned long mask)
44{
45 int ofs = (irq - 16) / 8;
46 outb(mask >> (16 + ofs * 8), 0x804 + ofs);
47}
48
49static inline void
50cabriolet_enable_irq(unsigned int irq)
51{
52 cabriolet_update_irq_hw(irq, cached_irq_mask &= ~(1UL << irq));
53}
54
55static void
56cabriolet_disable_irq(unsigned int irq)
57{
58 cabriolet_update_irq_hw(irq, cached_irq_mask |= 1UL << irq);
59}
60
61static unsigned int
62cabriolet_startup_irq(unsigned int irq)
63{
64 cabriolet_enable_irq(irq);
65 return 0; /* never anything pending */
66}
67
68static void
69cabriolet_end_irq(unsigned int irq)
70{
71 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
72 cabriolet_enable_irq(irq);
73}
74
75static struct hw_interrupt_type cabriolet_irq_type = {
76 .typename = "CABRIOLET",
77 .startup = cabriolet_startup_irq,
78 .shutdown = cabriolet_disable_irq,
79 .enable = cabriolet_enable_irq,
80 .disable = cabriolet_disable_irq,
81 .ack = cabriolet_disable_irq,
82 .end = cabriolet_end_irq,
83};
84
85static void
86cabriolet_device_interrupt(unsigned long v, struct pt_regs *r)
87{
88 unsigned long pld;
89 unsigned int i;
90
91 /* Read the interrupt summary registers */
92 pld = inb(0x804) | (inb(0x805) << 8) | (inb(0x806) << 16);
93
94 /*
95 * Now for every possible bit set, work through them and call
96 * the appropriate interrupt handler.
97 */
98 while (pld) {
99 i = ffz(~pld);
100 pld &= pld - 1; /* clear least bit set */
101 if (i == 4) {
102 isa_device_interrupt(v, r);
103 } else {
104 handle_irq(16 + i, r);
105 }
106 }
107}
108
109static void __init
110common_init_irq(void (*srm_dev_int)(unsigned long v, struct pt_regs *r))
111{
112 init_i8259a_irqs();
113
114 if (alpha_using_srm) {
115 alpha_mv.device_interrupt = srm_dev_int;
116 init_srm_irqs(35, 0);
117 }
118 else {
119 long i;
120
121 outb(0xff, 0x804);
122 outb(0xff, 0x805);
123 outb(0xff, 0x806);
124
125 for (i = 16; i < 35; ++i) {
126 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
127 irq_desc[i].handler = &cabriolet_irq_type;
128 }
129 }
130
131 common_init_isa_dma();
132 setup_irq(16+4, &isa_cascade_irqaction);
133}
134
135#ifndef CONFIG_ALPHA_PC164
136static void __init
137cabriolet_init_irq(void)
138{
139 common_init_irq(srm_device_interrupt);
140}
141#endif
142
143#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PC164)
144/* In theory, the PC164 has the same interrupt hardware as the other
145 Cabriolet based systems. However, something got screwed up late
146 in the development cycle which broke the interrupt masking hardware.
147 Repeat, it is not possible to mask and ack interrupts. At all.
148
149 In an attempt to work around this, while processing interrupts,
150 we do not allow the IPL to drop below what it is currently. This
151 prevents the possibility of recursion.
152
153 ??? Another option might be to force all PCI devices to use edge
154 triggered rather than level triggered interrupts. That might be
155 too invasive though. */
156
157static void
158pc164_srm_device_interrupt(unsigned long v, struct pt_regs *r)
159{
160 __min_ipl = getipl();
161 srm_device_interrupt(v, r);
162 __min_ipl = 0;
163}
164
165static void
166pc164_device_interrupt(unsigned long v, struct pt_regs *r)
167{
168 __min_ipl = getipl();
169 cabriolet_device_interrupt(v, r);
170 __min_ipl = 0;
171}
172
173static void __init
174pc164_init_irq(void)
175{
176 common_init_irq(pc164_srm_device_interrupt);
177}
178#endif
179
180/*
181 * The EB66+ is very similar to the EB66 except that it does not have
182 * the on-board NCR and Tulip chips. In the code below, I have used
183 * slot number to refer to the id select line and *not* the slot
184 * number used in the EB66+ documentation. However, in the table,
185 * I've given the slot number, the id select line and the Jxx number
186 * that's printed on the board. The interrupt pins from the PCI slots
187 * are wired into 3 interrupt summary registers at 0x804, 0x805 and
188 * 0x806 ISA.
189 *
190 * In the table, -1 means don't assign an IRQ number. This is usually
191 * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
192 */
193
194static inline int __init
195eb66p_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
196{
197 static char irq_tab[5][5] __initdata = {
198 /*INT INTA INTB INTC INTD */
199 {16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J25 */
200 {16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J26 */
201 { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
202 {16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 9, slot 2, J27 */
203 {16+3, 16+3, 16+8, 16+12, 16+6} /* IdSel 10, slot 3, J28 */
204 };
205 const long min_idsel = 6, max_idsel = 10, irqs_per_slot = 5;
206 return COMMON_TABLE_LOOKUP;
207}
208
209
210/*
211 * The AlphaPC64 is very similar to the EB66+ except that its slots
212 * are numbered differently. In the code below, I have used slot
213 * number to refer to the id select line and *not* the slot number
214 * used in the AlphaPC64 documentation. However, in the table, I've
215 * given the slot number, the id select line and the Jxx number that's
216 * printed on the board. The interrupt pins from the PCI slots are
217 * wired into 3 interrupt summary registers at 0x804, 0x805 and 0x806
218 * ISA.
219 *
220 * In the table, -1 means don't assign an IRQ number. This is usually
221 * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
222 */
223
224static inline int __init
225cabriolet_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
226{
227 static char irq_tab[5][5] __initdata = {
228 /*INT INTA INTB INTC INTD */
229 { 16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 5, slot 2, J21 */
230 { 16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J19 */
231 { 16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J20 */
232 { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
233 { 16+3, 16+3, 16+8, 16+12, 16+16} /* IdSel 9, slot 3, J22 */
234 };
235 const long min_idsel = 5, max_idsel = 9, irqs_per_slot = 5;
236 return COMMON_TABLE_LOOKUP;
237}
238
239static inline void __init
240cabriolet_init_pci(void)
241{
242 common_init_pci();
243 ns87312_enable_ide(0x398);
244}
245
246static inline void __init
247cia_cab_init_pci(void)
248{
249 cia_init_pci();
250 ns87312_enable_ide(0x398);
251}
252
253/*
254 * The PC164 and LX164 have 19 PCI interrupts, four from each of the four
255 * PCI slots, the SIO, PCI/IDE, and USB.
256 *
257 * Each of the interrupts can be individually masked. This is
258 * accomplished by setting the appropriate bit in the mask register.
259 * A bit is set by writing a "1" to the desired position in the mask
260 * register and cleared by writing a "0". There are 3 mask registers
261 * located at ISA address 804h, 805h and 806h.
262 *
263 * An I/O read at ISA address 804h, 805h, 806h will return the
264 * state of the 11 PCI interrupts and not the state of the MASKED
265 * interrupts.
266 *
267 * Note: A write to I/O 804h, 805h, and 806h the mask register will be
268 * updated.
269 *
270 *
271 * ISA DATA<7:0>
272 * ISA +--------------------------------------------------------------+
273 * ADDRESS | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
274 * +==============================================================+
275 * 0x804 | INTB0 | USB | IDE | SIO | INTA3 |INTA2 | INTA1 | INTA0 |
276 * +--------------------------------------------------------------+
277 * 0x805 | INTD0 | INTC3 | INTC2 | INTC1 | INTC0 |INTB3 | INTB2 | INTB1 |
278 * +--------------------------------------------------------------+
279 * 0x806 | Rsrv | Rsrv | Rsrv | Rsrv | Rsrv |INTD3 | INTD2 | INTD1 |
280 * +--------------------------------------------------------------+
281 * * Rsrv = reserved bits
282 * Note: The mask register is write-only.
283 *
284 * IdSel
285 * 5 32 bit PCI option slot 2
286 * 6 64 bit PCI option slot 0
287 * 7 64 bit PCI option slot 1
288 * 8 Saturn I/O
289 * 9 32 bit PCI option slot 3
290 * 10 USB
291 * 11 IDE
292 *
293 */
294
295static inline int __init
296alphapc164_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
297{
298 static char irq_tab[7][5] __initdata = {
299 /*INT INTA INTB INTC INTD */
300 { 16+2, 16+2, 16+9, 16+13, 16+17}, /* IdSel 5, slot 2, J20 */
301 { 16+0, 16+0, 16+7, 16+11, 16+15}, /* IdSel 6, slot 0, J29 */
302 { 16+1, 16+1, 16+8, 16+12, 16+16}, /* IdSel 7, slot 1, J26 */
303 { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
304 { 16+3, 16+3, 16+10, 16+14, 16+18}, /* IdSel 9, slot 3, J19 */
305 { 16+6, 16+6, 16+6, 16+6, 16+6}, /* IdSel 10, USB */
306 { 16+5, 16+5, 16+5, 16+5, 16+5} /* IdSel 11, IDE */
307 };
308 const long min_idsel = 5, max_idsel = 11, irqs_per_slot = 5;
309 return COMMON_TABLE_LOOKUP;
310}
311
312static inline void __init
313alphapc164_init_pci(void)
314{
315 cia_init_pci();
316 SMC93x_Init();
317}
318
319
320/*
321 * The System Vector
322 */
323
324#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_CABRIOLET)
325struct alpha_machine_vector cabriolet_mv __initmv = {
326 .vector_name = "Cabriolet",
327 DO_EV4_MMU,
328 DO_DEFAULT_RTC,
329 DO_APECS_IO,
330 .machine_check = apecs_machine_check,
331 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
332 .min_io_address = DEFAULT_IO_BASE,
333 .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE,
334
335 .nr_irqs = 35,
336 .device_interrupt = cabriolet_device_interrupt,
337
338 .init_arch = apecs_init_arch,
339 .init_irq = cabriolet_init_irq,
340 .init_rtc = common_init_rtc,
341 .init_pci = cabriolet_init_pci,
342 .pci_map_irq = cabriolet_map_irq,
343 .pci_swizzle = common_swizzle,
344};
345#ifndef CONFIG_ALPHA_EB64P
346ALIAS_MV(cabriolet)
347#endif
348#endif
349
350#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB164)
351struct alpha_machine_vector eb164_mv __initmv = {
352 .vector_name = "EB164",
353 DO_EV5_MMU,
354 DO_DEFAULT_RTC,
355 DO_CIA_IO,
356 .machine_check = cia_machine_check,
357 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
358 .min_io_address = DEFAULT_IO_BASE,
359 .min_mem_address = CIA_DEFAULT_MEM_BASE,
360
361 .nr_irqs = 35,
362 .device_interrupt = cabriolet_device_interrupt,
363
364 .init_arch = cia_init_arch,
365 .init_irq = cabriolet_init_irq,
366 .init_rtc = common_init_rtc,
367 .init_pci = cia_cab_init_pci,
368 .kill_arch = cia_kill_arch,
369 .pci_map_irq = cabriolet_map_irq,
370 .pci_swizzle = common_swizzle,
371};
372ALIAS_MV(eb164)
373#endif
374
375#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB66P)
376struct alpha_machine_vector eb66p_mv __initmv = {
377 .vector_name = "EB66+",
378 DO_EV4_MMU,
379 DO_DEFAULT_RTC,
380 DO_LCA_IO,
381 .machine_check = lca_machine_check,
382 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
383 .min_io_address = DEFAULT_IO_BASE,
384 .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE,
385
386 .nr_irqs = 35,
387 .device_interrupt = cabriolet_device_interrupt,
388
389 .init_arch = lca_init_arch,
390 .init_irq = cabriolet_init_irq,
391 .init_rtc = common_init_rtc,
392 .init_pci = cabriolet_init_pci,
393 .pci_map_irq = eb66p_map_irq,
394 .pci_swizzle = common_swizzle,
395};
396ALIAS_MV(eb66p)
397#endif
398
399#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LX164)
400struct alpha_machine_vector lx164_mv __initmv = {
401 .vector_name = "LX164",
402 DO_EV5_MMU,
403 DO_DEFAULT_RTC,
404 DO_PYXIS_IO,
405 .machine_check = cia_machine_check,
406 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
407 .min_io_address = DEFAULT_IO_BASE,
408 .min_mem_address = DEFAULT_MEM_BASE,
409 .pci_dac_offset = PYXIS_DAC_OFFSET,
410
411 .nr_irqs = 35,
412 .device_interrupt = cabriolet_device_interrupt,
413
414 .init_arch = pyxis_init_arch,
415 .init_irq = cabriolet_init_irq,
416 .init_rtc = common_init_rtc,
417 .init_pci = alphapc164_init_pci,
418 .kill_arch = cia_kill_arch,
419 .pci_map_irq = alphapc164_map_irq,
420 .pci_swizzle = common_swizzle,
421};
422ALIAS_MV(lx164)
423#endif
424
425#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PC164)
426struct alpha_machine_vector pc164_mv __initmv = {
427 .vector_name = "PC164",
428 DO_EV5_MMU,
429 DO_DEFAULT_RTC,
430 DO_CIA_IO,
431 .machine_check = cia_machine_check,
432 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
433 .min_io_address = DEFAULT_IO_BASE,
434 .min_mem_address = CIA_DEFAULT_MEM_BASE,
435
436 .nr_irqs = 35,
437 .device_interrupt = pc164_device_interrupt,
438
439 .init_arch = cia_init_arch,
440 .init_irq = pc164_init_irq,
441 .init_rtc = common_init_rtc,
442 .init_pci = alphapc164_init_pci,
443 .kill_arch = cia_kill_arch,
444 .pci_map_irq = alphapc164_map_irq,
445 .pci_swizzle = common_swizzle,
446};
447ALIAS_MV(pc164)
448#endif
diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c
new file mode 100644
index 000000000000..9e36b07fa940
--- /dev/null
+++ b/arch/alpha/kernel/sys_dp264.c
@@ -0,0 +1,689 @@
1/*
2 * linux/arch/alpha/kernel/sys_dp264.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996, 1999 Jay A Estabrook
6 * Copyright (C) 1998, 1999 Richard Henderson
7 *
8 * Modified by Christopher C. Chimelis, 2001 to
9 * add support for the addition of Shark to the
10 * Tsunami family.
11 *
12 * Code supporting the DP264 (EV6+TSUNAMI).
13 */
14
15#include <linux/config.h>
16#include <linux/kernel.h>
17#include <linux/types.h>
18#include <linux/mm.h>
19#include <linux/sched.h>
20#include <linux/pci.h>
21#include <linux/init.h>
22#include <linux/bitops.h>
23
24#include <asm/ptrace.h>
25#include <asm/system.h>
26#include <asm/dma.h>
27#include <asm/irq.h>
28#include <asm/mmu_context.h>
29#include <asm/io.h>
30#include <asm/pgtable.h>
31#include <asm/core_tsunami.h>
32#include <asm/hwrpb.h>
33#include <asm/tlbflush.h>
34
35#include "proto.h"
36#include "irq_impl.h"
37#include "pci_impl.h"
38#include "machvec_impl.h"
39
40
41/* Note mask bit is true for ENABLED irqs. */
42static unsigned long cached_irq_mask;
43/* dp264 boards handle at max four CPUs */
44static unsigned long cpu_irq_affinity[4] = { 0UL, 0UL, 0UL, 0UL };
45
46DEFINE_SPINLOCK(dp264_irq_lock);
47
48static void
49tsunami_update_irq_hw(unsigned long mask)
50{
51 register tsunami_cchip *cchip = TSUNAMI_cchip;
52 unsigned long isa_enable = 1UL << 55;
53 register int bcpu = boot_cpuid;
54
55#ifdef CONFIG_SMP
56 volatile unsigned long *dim0, *dim1, *dim2, *dim3;
57 unsigned long mask0, mask1, mask2, mask3, dummy;
58
59 mask &= ~isa_enable;
60 mask0 = mask & cpu_irq_affinity[0];
61 mask1 = mask & cpu_irq_affinity[1];
62 mask2 = mask & cpu_irq_affinity[2];
63 mask3 = mask & cpu_irq_affinity[3];
64
65 if (bcpu == 0) mask0 |= isa_enable;
66 else if (bcpu == 1) mask1 |= isa_enable;
67 else if (bcpu == 2) mask2 |= isa_enable;
68 else mask3 |= isa_enable;
69
70 dim0 = &cchip->dim0.csr;
71 dim1 = &cchip->dim1.csr;
72 dim2 = &cchip->dim2.csr;
73 dim3 = &cchip->dim3.csr;
74 if (!cpu_possible(0)) dim0 = &dummy;
75 if (!cpu_possible(1)) dim1 = &dummy;
76 if (!cpu_possible(2)) dim2 = &dummy;
77 if (!cpu_possible(3)) dim3 = &dummy;
78
79 *dim0 = mask0;
80 *dim1 = mask1;
81 *dim2 = mask2;
82 *dim3 = mask3;
83 mb();
84 *dim0;
85 *dim1;
86 *dim2;
87 *dim3;
88#else
89 volatile unsigned long *dimB;
90 if (bcpu == 0) dimB = &cchip->dim0.csr;
91 else if (bcpu == 1) dimB = &cchip->dim1.csr;
92 else if (bcpu == 2) dimB = &cchip->dim2.csr;
93 else dimB = &cchip->dim3.csr;
94
95 *dimB = mask | isa_enable;
96 mb();
97 *dimB;
98#endif
99}
100
101static void
102dp264_enable_irq(unsigned int irq)
103{
104 spin_lock(&dp264_irq_lock);
105 cached_irq_mask |= 1UL << irq;
106 tsunami_update_irq_hw(cached_irq_mask);
107 spin_unlock(&dp264_irq_lock);
108}
109
110static void
111dp264_disable_irq(unsigned int irq)
112{
113 spin_lock(&dp264_irq_lock);
114 cached_irq_mask &= ~(1UL << irq);
115 tsunami_update_irq_hw(cached_irq_mask);
116 spin_unlock(&dp264_irq_lock);
117}
118
119static unsigned int
120dp264_startup_irq(unsigned int irq)
121{
122 dp264_enable_irq(irq);
123 return 0; /* never anything pending */
124}
125
126static void
127dp264_end_irq(unsigned int irq)
128{
129 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
130 dp264_enable_irq(irq);
131}
132
133static void
134clipper_enable_irq(unsigned int irq)
135{
136 spin_lock(&dp264_irq_lock);
137 cached_irq_mask |= 1UL << (irq - 16);
138 tsunami_update_irq_hw(cached_irq_mask);
139 spin_unlock(&dp264_irq_lock);
140}
141
142static void
143clipper_disable_irq(unsigned int irq)
144{
145 spin_lock(&dp264_irq_lock);
146 cached_irq_mask &= ~(1UL << (irq - 16));
147 tsunami_update_irq_hw(cached_irq_mask);
148 spin_unlock(&dp264_irq_lock);
149}
150
151static unsigned int
152clipper_startup_irq(unsigned int irq)
153{
154 clipper_enable_irq(irq);
155 return 0; /* never anything pending */
156}
157
158static void
159clipper_end_irq(unsigned int irq)
160{
161 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
162 clipper_enable_irq(irq);
163}
164
165static void
166cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity)
167{
168 int cpu;
169
170 for (cpu = 0; cpu < 4; cpu++) {
171 unsigned long aff = cpu_irq_affinity[cpu];
172 if (cpu_isset(cpu, affinity))
173 aff |= 1UL << irq;
174 else
175 aff &= ~(1UL << irq);
176 cpu_irq_affinity[cpu] = aff;
177 }
178}
179
180static void
181dp264_set_affinity(unsigned int irq, cpumask_t affinity)
182{
183 spin_lock(&dp264_irq_lock);
184 cpu_set_irq_affinity(irq, affinity);
185 tsunami_update_irq_hw(cached_irq_mask);
186 spin_unlock(&dp264_irq_lock);
187}
188
189static void
190clipper_set_affinity(unsigned int irq, cpumask_t affinity)
191{
192 spin_lock(&dp264_irq_lock);
193 cpu_set_irq_affinity(irq - 16, affinity);
194 tsunami_update_irq_hw(cached_irq_mask);
195 spin_unlock(&dp264_irq_lock);
196}
197
198static struct hw_interrupt_type dp264_irq_type = {
199 .typename = "DP264",
200 .startup = dp264_startup_irq,
201 .shutdown = dp264_disable_irq,
202 .enable = dp264_enable_irq,
203 .disable = dp264_disable_irq,
204 .ack = dp264_disable_irq,
205 .end = dp264_end_irq,
206 .set_affinity = dp264_set_affinity,
207};
208
209static struct hw_interrupt_type clipper_irq_type = {
210 .typename = "CLIPPER",
211 .startup = clipper_startup_irq,
212 .shutdown = clipper_disable_irq,
213 .enable = clipper_enable_irq,
214 .disable = clipper_disable_irq,
215 .ack = clipper_disable_irq,
216 .end = clipper_end_irq,
217 .set_affinity = clipper_set_affinity,
218};
219
220static void
221dp264_device_interrupt(unsigned long vector, struct pt_regs * regs)
222{
223#if 1
224 printk("dp264_device_interrupt: NOT IMPLEMENTED YET!! \n");
225#else
226 unsigned long pld;
227 unsigned int i;
228
229 /* Read the interrupt summary register of TSUNAMI */
230 pld = TSUNAMI_cchip->dir0.csr;
231
232 /*
233 * Now for every possible bit set, work through them and call
234 * the appropriate interrupt handler.
235 */
236 while (pld) {
237 i = ffz(~pld);
238 pld &= pld - 1; /* clear least bit set */
239 if (i == 55)
240 isa_device_interrupt(vector, regs);
241 else
242 handle_irq(16 + i, 16 + i, regs);
243#if 0
244 TSUNAMI_cchip->dir0.csr = 1UL << i; mb();
245 tmp = TSUNAMI_cchip->dir0.csr;
246#endif
247 }
248#endif
249}
250
251static void
252dp264_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
253{
254 int irq;
255
256 irq = (vector - 0x800) >> 4;
257
258 /*
259 * The SRM console reports PCI interrupts with a vector calculated by:
260 *
261 * 0x900 + (0x10 * DRIR-bit)
262 *
263 * So bit 16 shows up as IRQ 32, etc.
264 *
265 * On DP264/BRICK/MONET, we adjust it down by 16 because at least
266 * that many of the low order bits of the DRIR are not used, and
267 * so we don't count them.
268 */
269 if (irq >= 32)
270 irq -= 16;
271
272 handle_irq(irq, regs);
273}
274
275static void
276clipper_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
277{
278 int irq;
279
280 irq = (vector - 0x800) >> 4;
281
282/*
283 * The SRM console reports PCI interrupts with a vector calculated by:
284 *
285 * 0x900 + (0x10 * DRIR-bit)
286 *
287 * So bit 16 shows up as IRQ 32, etc.
288 *
289 * CLIPPER uses bits 8-47 for PCI interrupts, so we do not need
290 * to scale down the vector reported, we just use it.
291 *
292 * Eg IRQ 24 is DRIR bit 8, etc, etc
293 */
294 handle_irq(irq, regs);
295}
296
297static void __init
298init_tsunami_irqs(struct hw_interrupt_type * ops, int imin, int imax)
299{
300 long i;
301 for (i = imin; i <= imax; ++i) {
302 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
303 irq_desc[i].handler = ops;
304 }
305}
306
307static void __init
308dp264_init_irq(void)
309{
310 outb(0, DMA1_RESET_REG);
311 outb(0, DMA2_RESET_REG);
312 outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
313 outb(0, DMA2_MASK_REG);
314
315 if (alpha_using_srm)
316 alpha_mv.device_interrupt = dp264_srm_device_interrupt;
317
318 tsunami_update_irq_hw(0);
319
320 init_i8259a_irqs();
321 init_tsunami_irqs(&dp264_irq_type, 16, 47);
322}
323
324static void __init
325clipper_init_irq(void)
326{
327 outb(0, DMA1_RESET_REG);
328 outb(0, DMA2_RESET_REG);
329 outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
330 outb(0, DMA2_MASK_REG);
331
332 if (alpha_using_srm)
333 alpha_mv.device_interrupt = clipper_srm_device_interrupt;
334
335 tsunami_update_irq_hw(0);
336
337 init_i8259a_irqs();
338 init_tsunami_irqs(&clipper_irq_type, 24, 63);
339}
340
341
342/*
343 * PCI Fixup configuration.
344 *
345 * Summary @ TSUNAMI_CSR_DIM0:
346 * Bit Meaning
347 * 0-17 Unused
348 *18 Interrupt SCSI B (Adaptec 7895 builtin)
349 *19 Interrupt SCSI A (Adaptec 7895 builtin)
350 *20 Interrupt Line D from slot 2 PCI0
351 *21 Interrupt Line C from slot 2 PCI0
352 *22 Interrupt Line B from slot 2 PCI0
353 *23 Interrupt Line A from slot 2 PCI0
354 *24 Interrupt Line D from slot 1 PCI0
355 *25 Interrupt Line C from slot 1 PCI0
356 *26 Interrupt Line B from slot 1 PCI0
357 *27 Interrupt Line A from slot 1 PCI0
358 *28 Interrupt Line D from slot 0 PCI0
359 *29 Interrupt Line C from slot 0 PCI0
360 *30 Interrupt Line B from slot 0 PCI0
361 *31 Interrupt Line A from slot 0 PCI0
362 *
363 *32 Interrupt Line D from slot 3 PCI1
364 *33 Interrupt Line C from slot 3 PCI1
365 *34 Interrupt Line B from slot 3 PCI1
366 *35 Interrupt Line A from slot 3 PCI1
367 *36 Interrupt Line D from slot 2 PCI1
368 *37 Interrupt Line C from slot 2 PCI1
369 *38 Interrupt Line B from slot 2 PCI1
370 *39 Interrupt Line A from slot 2 PCI1
371 *40 Interrupt Line D from slot 1 PCI1
372 *41 Interrupt Line C from slot 1 PCI1
373 *42 Interrupt Line B from slot 1 PCI1
374 *43 Interrupt Line A from slot 1 PCI1
375 *44 Interrupt Line D from slot 0 PCI1
376 *45 Interrupt Line C from slot 0 PCI1
377 *46 Interrupt Line B from slot 0 PCI1
378 *47 Interrupt Line A from slot 0 PCI1
379 *48-52 Unused
380 *53 PCI0 NMI (from Cypress)
381 *54 PCI0 SMI INT (from Cypress)
382 *55 PCI0 ISA Interrupt (from Cypress)
383 *56-60 Unused
384 *61 PCI1 Bus Error
385 *62 PCI0 Bus Error
386 *63 Reserved
387 *
388 * IdSel
389 * 5 Cypress Bridge I/O
390 * 6 SCSI Adaptec builtin
391 * 7 64 bit PCI option slot 0 (all busses)
392 * 8 64 bit PCI option slot 1 (all busses)
393 * 9 64 bit PCI option slot 2 (all busses)
394 * 10 64 bit PCI option slot 3 (not bus 0)
395 */
396
397static int __init
398dp264_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
399{
400 static char irq_tab[6][5] __initdata = {
401 /*INT INTA INTB INTC INTD */
402 { -1, -1, -1, -1, -1}, /* IdSel 5 ISA Bridge */
403 { 16+ 3, 16+ 3, 16+ 2, 16+ 2, 16+ 2}, /* IdSel 6 SCSI builtin*/
404 { 16+15, 16+15, 16+14, 16+13, 16+12}, /* IdSel 7 slot 0 */
405 { 16+11, 16+11, 16+10, 16+ 9, 16+ 8}, /* IdSel 8 slot 1 */
406 { 16+ 7, 16+ 7, 16+ 6, 16+ 5, 16+ 4}, /* IdSel 9 slot 2 */
407 { 16+ 3, 16+ 3, 16+ 2, 16+ 1, 16+ 0} /* IdSel 10 slot 3 */
408 };
409 const long min_idsel = 5, max_idsel = 10, irqs_per_slot = 5;
410
411 struct pci_controller *hose = dev->sysdata;
412 int irq = COMMON_TABLE_LOOKUP;
413
414 if (irq > 0) {
415 irq += 16 * hose->index;
416 } else {
417 /* ??? The Contaq IDE controller on the ISA bridge uses
418 "legacy" interrupts 14 and 15. I don't know if anything
419 can wind up at the same slot+pin on hose1, so we'll
420 just have to trust whatever value the console might
421 have assigned. */
422
423 u8 irq8;
424 pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq8);
425 irq = irq8;
426 }
427
428 return irq;
429}
430
431static int __init
432monet_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
433{
434 static char irq_tab[13][5] __initdata = {
435 /*INT INTA INTB INTC INTD */
436 { 45, 45, 45, 45, 45}, /* IdSel 3 21143 PCI1 */
437 { -1, -1, -1, -1, -1}, /* IdSel 4 unused */
438 { -1, -1, -1, -1, -1}, /* IdSel 5 unused */
439 { 47, 47, 47, 47, 47}, /* IdSel 6 SCSI PCI1 */
440 { -1, -1, -1, -1, -1}, /* IdSel 7 ISA Bridge */
441 { -1, -1, -1, -1, -1}, /* IdSel 8 P2P PCI1 */
442#if 1
443 { 28, 28, 29, 30, 31}, /* IdSel 14 slot 4 PCI2*/
444 { 24, 24, 25, 26, 27}, /* IdSel 15 slot 5 PCI2*/
445#else
446 { -1, -1, -1, -1, -1}, /* IdSel 9 unused */
447 { -1, -1, -1, -1, -1}, /* IdSel 10 unused */
448#endif
449 { 40, 40, 41, 42, 43}, /* IdSel 11 slot 1 PCI0*/
450 { 36, 36, 37, 38, 39}, /* IdSel 12 slot 2 PCI0*/
451 { 32, 32, 33, 34, 35}, /* IdSel 13 slot 3 PCI0*/
452 { 28, 28, 29, 30, 31}, /* IdSel 14 slot 4 PCI2*/
453 { 24, 24, 25, 26, 27} /* IdSel 15 slot 5 PCI2*/
454 };
455 const long min_idsel = 3, max_idsel = 15, irqs_per_slot = 5;
456 return COMMON_TABLE_LOOKUP;
457}
458
459static u8 __init
460monet_swizzle(struct pci_dev *dev, u8 *pinp)
461{
462 struct pci_controller *hose = dev->sysdata;
463 int slot, pin = *pinp;
464
465 if (!dev->bus->parent) {
466 slot = PCI_SLOT(dev->devfn);
467 }
468 /* Check for the built-in bridge on hose 1. */
469 else if (hose->index == 1 && PCI_SLOT(dev->bus->self->devfn) == 8) {
470 slot = PCI_SLOT(dev->devfn);
471 } else {
472 /* Must be a card-based bridge. */
473 do {
474 /* Check for built-in bridge on hose 1. */
475 if (hose->index == 1 &&
476 PCI_SLOT(dev->bus->self->devfn) == 8) {
477 slot = PCI_SLOT(dev->devfn);
478 break;
479 }
480 pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)) ;
481
482 /* Move up the chain of bridges. */
483 dev = dev->bus->self;
484 /* Slot of the next bridge. */
485 slot = PCI_SLOT(dev->devfn);
486 } while (dev->bus->self);
487 }
488 *pinp = pin;
489 return slot;
490}
491
492static int __init
493webbrick_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
494{
495 static char irq_tab[13][5] __initdata = {
496 /*INT INTA INTB INTC INTD */
497 { -1, -1, -1, -1, -1}, /* IdSel 7 ISA Bridge */
498 { -1, -1, -1, -1, -1}, /* IdSel 8 unused */
499 { 29, 29, 29, 29, 29}, /* IdSel 9 21143 #1 */
500 { -1, -1, -1, -1, -1}, /* IdSel 10 unused */
501 { 30, 30, 30, 30, 30}, /* IdSel 11 21143 #2 */
502 { -1, -1, -1, -1, -1}, /* IdSel 12 unused */
503 { -1, -1, -1, -1, -1}, /* IdSel 13 unused */
504 { 35, 35, 34, 33, 32}, /* IdSel 14 slot 0 */
505 { 39, 39, 38, 37, 36}, /* IdSel 15 slot 1 */
506 { 43, 43, 42, 41, 40}, /* IdSel 16 slot 2 */
507 { 47, 47, 46, 45, 44}, /* IdSel 17 slot 3 */
508 };
509 const long min_idsel = 7, max_idsel = 17, irqs_per_slot = 5;
510 return COMMON_TABLE_LOOKUP;
511}
512
513static int __init
514clipper_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
515{
516 static char irq_tab[7][5] __initdata = {
517 /*INT INTA INTB INTC INTD */
518 { 16+ 8, 16+ 8, 16+ 9, 16+10, 16+11}, /* IdSel 1 slot 1 */
519 { 16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 2 slot 2 */
520 { 16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 3 slot 3 */
521 { 16+20, 16+20, 16+21, 16+22, 16+23}, /* IdSel 4 slot 4 */
522 { 16+24, 16+24, 16+25, 16+26, 16+27}, /* IdSel 5 slot 5 */
523 { 16+28, 16+28, 16+29, 16+30, 16+31}, /* IdSel 6 slot 6 */
524 { -1, -1, -1, -1, -1} /* IdSel 7 ISA Bridge */
525 };
526 const long min_idsel = 1, max_idsel = 7, irqs_per_slot = 5;
527
528 struct pci_controller *hose = dev->sysdata;
529 int irq = COMMON_TABLE_LOOKUP;
530
531 if (irq > 0)
532 irq += 16 * hose->index;
533
534 return irq;
535}
536
537static void __init
538dp264_init_pci(void)
539{
540 common_init_pci();
541 SMC669_Init(0);
542}
543
544static void __init
545monet_init_pci(void)
546{
547 common_init_pci();
548 SMC669_Init(1);
549 es1888_init();
550}
551
552static void __init
553webbrick_init_arch(void)
554{
555 tsunami_init_arch();
556
557 /* Tsunami caches 4 PTEs at a time; DS10 has only 1 hose. */
558 hose_head->sg_isa->align_entry = 4;
559 hose_head->sg_pci->align_entry = 4;
560}
561
562
563/*
564 * The System Vectors
565 */
566
567struct alpha_machine_vector dp264_mv __initmv = {
568 .vector_name = "DP264",
569 DO_EV6_MMU,
570 DO_DEFAULT_RTC,
571 DO_TSUNAMI_IO,
572 .machine_check = tsunami_machine_check,
573 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
574 .min_io_address = DEFAULT_IO_BASE,
575 .min_mem_address = DEFAULT_MEM_BASE,
576 .pci_dac_offset = TSUNAMI_DAC_OFFSET,
577
578 .nr_irqs = 64,
579 .device_interrupt = dp264_device_interrupt,
580
581 .init_arch = tsunami_init_arch,
582 .init_irq = dp264_init_irq,
583 .init_rtc = common_init_rtc,
584 .init_pci = dp264_init_pci,
585 .kill_arch = tsunami_kill_arch,
586 .pci_map_irq = dp264_map_irq,
587 .pci_swizzle = common_swizzle,
588};
589ALIAS_MV(dp264)
590
591struct alpha_machine_vector monet_mv __initmv = {
592 .vector_name = "Monet",
593 DO_EV6_MMU,
594 DO_DEFAULT_RTC,
595 DO_TSUNAMI_IO,
596 .machine_check = tsunami_machine_check,
597 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
598 .min_io_address = DEFAULT_IO_BASE,
599 .min_mem_address = DEFAULT_MEM_BASE,
600 .pci_dac_offset = TSUNAMI_DAC_OFFSET,
601
602 .nr_irqs = 64,
603 .device_interrupt = dp264_device_interrupt,
604
605 .init_arch = tsunami_init_arch,
606 .init_irq = dp264_init_irq,
607 .init_rtc = common_init_rtc,
608 .init_pci = monet_init_pci,
609 .kill_arch = tsunami_kill_arch,
610 .pci_map_irq = monet_map_irq,
611 .pci_swizzle = monet_swizzle,
612};
613
614struct alpha_machine_vector webbrick_mv __initmv = {
615 .vector_name = "Webbrick",
616 DO_EV6_MMU,
617 DO_DEFAULT_RTC,
618 DO_TSUNAMI_IO,
619 .machine_check = tsunami_machine_check,
620 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
621 .min_io_address = DEFAULT_IO_BASE,
622 .min_mem_address = DEFAULT_MEM_BASE,
623 .pci_dac_offset = TSUNAMI_DAC_OFFSET,
624
625 .nr_irqs = 64,
626 .device_interrupt = dp264_device_interrupt,
627
628 .init_arch = webbrick_init_arch,
629 .init_irq = dp264_init_irq,
630 .init_rtc = common_init_rtc,
631 .init_pci = common_init_pci,
632 .kill_arch = tsunami_kill_arch,
633 .pci_map_irq = webbrick_map_irq,
634 .pci_swizzle = common_swizzle,
635};
636
637struct alpha_machine_vector clipper_mv __initmv = {
638 .vector_name = "Clipper",
639 DO_EV6_MMU,
640 DO_DEFAULT_RTC,
641 DO_TSUNAMI_IO,
642 .machine_check = tsunami_machine_check,
643 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
644 .min_io_address = DEFAULT_IO_BASE,
645 .min_mem_address = DEFAULT_MEM_BASE,
646 .pci_dac_offset = TSUNAMI_DAC_OFFSET,
647
648 .nr_irqs = 64,
649 .device_interrupt = dp264_device_interrupt,
650
651 .init_arch = tsunami_init_arch,
652 .init_irq = clipper_init_irq,
653 .init_rtc = common_init_rtc,
654 .init_pci = common_init_pci,
655 .kill_arch = tsunami_kill_arch,
656 .pci_map_irq = clipper_map_irq,
657 .pci_swizzle = common_swizzle,
658};
659
660/* Sharks strongly resemble Clipper, at least as far
661 * as interrupt routing, etc, so we're using the
662 * same functions as Clipper does
663 */
664
665struct alpha_machine_vector shark_mv __initmv = {
666 .vector_name = "Shark",
667 DO_EV6_MMU,
668 DO_DEFAULT_RTC,
669 DO_TSUNAMI_IO,
670 .machine_check = tsunami_machine_check,
671 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
672 .min_io_address = DEFAULT_IO_BASE,
673 .min_mem_address = DEFAULT_MEM_BASE,
674 .pci_dac_offset = TSUNAMI_DAC_OFFSET,
675
676 .nr_irqs = 64,
677 .device_interrupt = dp264_device_interrupt,
678
679 .init_arch = tsunami_init_arch,
680 .init_irq = clipper_init_irq,
681 .init_rtc = common_init_rtc,
682 .init_pci = common_init_pci,
683 .kill_arch = tsunami_kill_arch,
684 .pci_map_irq = clipper_map_irq,
685 .pci_swizzle = common_swizzle,
686};
687
688/* No alpha_mv alias for webbrick/monet/clipper, since we compile them
689 in unconditionally with DP264; setup_arch knows how to cope. */
diff --git a/arch/alpha/kernel/sys_eb64p.c b/arch/alpha/kernel/sys_eb64p.c
new file mode 100644
index 000000000000..61a79c354f0b
--- /dev/null
+++ b/arch/alpha/kernel/sys_eb64p.c
@@ -0,0 +1,256 @@
1/*
2 * linux/arch/alpha/kernel/sys_eb64p.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996 Jay A Estabrook
6 * Copyright (C) 1998, 1999 Richard Henderson
7 *
8 * Code supporting the EB64+ and EB66.
9 */
10
11#include <linux/config.h>
12#include <linux/kernel.h>
13#include <linux/types.h>
14#include <linux/mm.h>
15#include <linux/sched.h>
16#include <linux/pci.h>
17#include <linux/init.h>
18#include <linux/bitops.h>
19
20#include <asm/ptrace.h>
21#include <asm/system.h>
22#include <asm/dma.h>
23#include <asm/irq.h>
24#include <asm/mmu_context.h>
25#include <asm/io.h>
26#include <asm/pgtable.h>
27#include <asm/core_apecs.h>
28#include <asm/core_lca.h>
29#include <asm/hwrpb.h>
30#include <asm/tlbflush.h>
31
32#include "proto.h"
33#include "irq_impl.h"
34#include "pci_impl.h"
35#include "machvec_impl.h"
36
37
38/* Note mask bit is true for DISABLED irqs. */
39static unsigned int cached_irq_mask = -1;
40
41static inline void
42eb64p_update_irq_hw(unsigned int irq, unsigned long mask)
43{
44 outb(mask >> (irq >= 24 ? 24 : 16), (irq >= 24 ? 0x27 : 0x26));
45}
46
47static inline void
48eb64p_enable_irq(unsigned int irq)
49{
50 eb64p_update_irq_hw(irq, cached_irq_mask &= ~(1 << irq));
51}
52
53static void
54eb64p_disable_irq(unsigned int irq)
55{
56 eb64p_update_irq_hw(irq, cached_irq_mask |= 1 << irq);
57}
58
59static unsigned int
60eb64p_startup_irq(unsigned int irq)
61{
62 eb64p_enable_irq(irq);
63 return 0; /* never anything pending */
64}
65
66static void
67eb64p_end_irq(unsigned int irq)
68{
69 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
70 eb64p_enable_irq(irq);
71}
72
73static struct hw_interrupt_type eb64p_irq_type = {
74 .typename = "EB64P",
75 .startup = eb64p_startup_irq,
76 .shutdown = eb64p_disable_irq,
77 .enable = eb64p_enable_irq,
78 .disable = eb64p_disable_irq,
79 .ack = eb64p_disable_irq,
80 .end = eb64p_end_irq,
81};
82
83static void
84eb64p_device_interrupt(unsigned long vector, struct pt_regs *regs)
85{
86 unsigned long pld;
87 unsigned int i;
88
89 /* Read the interrupt summary registers */
90 pld = inb(0x26) | (inb(0x27) << 8);
91
92 /*
93 * Now, for every possible bit set, work through
94 * them and call the appropriate interrupt handler.
95 */
96 while (pld) {
97 i = ffz(~pld);
98 pld &= pld - 1; /* clear least bit set */
99
100 if (i == 5) {
101 isa_device_interrupt(vector, regs);
102 } else {
103 handle_irq(16 + i, regs);
104 }
105 }
106}
107
108static void __init
109eb64p_init_irq(void)
110{
111 long i;
112
113#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_CABRIOLET)
114 /*
115 * CABRIO SRM may not set variation correctly, so here we test
116 * the high word of the interrupt summary register for the RAZ
117 * bits, and hope that a true EB64+ would read all ones...
118 */
119 if (inw(0x806) != 0xffff) {
120 extern struct alpha_machine_vector cabriolet_mv;
121
122 printk("Detected Cabriolet: correcting HWRPB.\n");
123
124 hwrpb->sys_variation |= 2L << 10;
125 hwrpb_update_checksum(hwrpb);
126
127 alpha_mv = cabriolet_mv;
128 alpha_mv.init_irq();
129 return;
130 }
131#endif /* GENERIC */
132
133 outb(0xff, 0x26);
134 outb(0xff, 0x27);
135
136 init_i8259a_irqs();
137
138 for (i = 16; i < 32; ++i) {
139 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
140 irq_desc[i].handler = &eb64p_irq_type;
141 }
142
143 common_init_isa_dma();
144 setup_irq(16+5, &isa_cascade_irqaction);
145}
146
147/*
148 * PCI Fixup configuration.
149 *
150 * There are two 8 bit external summary registers as follows:
151 *
152 * Summary @ 0x26:
153 * Bit Meaning
154 * 0 Interrupt Line A from slot 0
155 * 1 Interrupt Line A from slot 1
156 * 2 Interrupt Line B from slot 0
157 * 3 Interrupt Line B from slot 1
158 * 4 Interrupt Line C from slot 0
159 * 5 Interrupt line from the two ISA PICs
160 * 6 Tulip
161 * 7 NCR SCSI
162 *
163 * Summary @ 0x27
164 * Bit Meaning
165 * 0 Interrupt Line C from slot 1
166 * 1 Interrupt Line D from slot 0
167 * 2 Interrupt Line D from slot 1
168 * 3 RAZ
169 * 4 RAZ
170 * 5 RAZ
171 * 6 RAZ
172 * 7 RAZ
173 *
174 * The device to slot mapping looks like:
175 *
176 * Slot Device
177 * 5 NCR SCSI controller
178 * 6 PCI on board slot 0
179 * 7 PCI on board slot 1
180 * 8 Intel SIO PCI-ISA bridge chip
181 * 9 Tulip - DECchip 21040 Ethernet controller
182 *
183 *
184 * This two layered interrupt approach means that we allocate IRQ 16 and
185 * above for PCI interrupts. The IRQ relates to which bit the interrupt
186 * comes in on. This makes interrupt processing much easier.
187 */
188
189static int __init
190eb64p_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
191{
192 static char irq_tab[5][5] __initdata = {
193 /*INT INTA INTB INTC INTD */
194 {16+7, 16+7, 16+7, 16+7, 16+7}, /* IdSel 5, slot ?, ?? */
195 {16+0, 16+0, 16+2, 16+4, 16+9}, /* IdSel 6, slot ?, ?? */
196 {16+1, 16+1, 16+3, 16+8, 16+10}, /* IdSel 7, slot ?, ?? */
197 { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
198 {16+6, 16+6, 16+6, 16+6, 16+6}, /* IdSel 9, TULIP */
199 };
200 const long min_idsel = 5, max_idsel = 9, irqs_per_slot = 5;
201 return COMMON_TABLE_LOOKUP;
202}
203
204
205/*
206 * The System Vector
207 */
208
209#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB64P)
210struct alpha_machine_vector eb64p_mv __initmv = {
211 .vector_name = "EB64+",
212 DO_EV4_MMU,
213 DO_DEFAULT_RTC,
214 DO_APECS_IO,
215 .machine_check = apecs_machine_check,
216 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
217 .min_io_address = DEFAULT_IO_BASE,
218 .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE,
219
220 .nr_irqs = 32,
221 .device_interrupt = eb64p_device_interrupt,
222
223 .init_arch = apecs_init_arch,
224 .init_irq = eb64p_init_irq,
225 .init_rtc = common_init_rtc,
226 .init_pci = common_init_pci,
227 .kill_arch = NULL,
228 .pci_map_irq = eb64p_map_irq,
229 .pci_swizzle = common_swizzle,
230};
231ALIAS_MV(eb64p)
232#endif
233
234#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB66)
235struct alpha_machine_vector eb66_mv __initmv = {
236 .vector_name = "EB66",
237 DO_EV4_MMU,
238 DO_DEFAULT_RTC,
239 DO_LCA_IO,
240 .machine_check = lca_machine_check,
241 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
242 .min_io_address = DEFAULT_IO_BASE,
243 .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE,
244
245 .nr_irqs = 32,
246 .device_interrupt = eb64p_device_interrupt,
247
248 .init_arch = lca_init_arch,
249 .init_irq = eb64p_init_irq,
250 .init_rtc = common_init_rtc,
251 .init_pci = common_init_pci,
252 .pci_map_irq = eb64p_map_irq,
253 .pci_swizzle = common_swizzle,
254};
255ALIAS_MV(eb66)
256#endif
diff --git a/arch/alpha/kernel/sys_eiger.c b/arch/alpha/kernel/sys_eiger.c
new file mode 100644
index 000000000000..bd6e5f0e43c7
--- /dev/null
+++ b/arch/alpha/kernel/sys_eiger.c
@@ -0,0 +1,242 @@
1/*
2 * linux/arch/alpha/kernel/sys_eiger.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996, 1999 Jay A Estabrook
6 * Copyright (C) 1998, 1999 Richard Henderson
7 * Copyright (C) 1999 Iain Grant
8 *
9 * Code supporting the EIGER (EV6+TSUNAMI).
10 */
11
12#include <linux/kernel.h>
13#include <linux/types.h>
14#include <linux/mm.h>
15#include <linux/sched.h>
16#include <linux/pci.h>
17#include <linux/init.h>
18#include <linux/bitops.h>
19
20#include <asm/ptrace.h>
21#include <asm/system.h>
22#include <asm/dma.h>
23#include <asm/irq.h>
24#include <asm/mmu_context.h>
25#include <asm/io.h>
26#include <asm/pci.h>
27#include <asm/pgtable.h>
28#include <asm/core_tsunami.h>
29#include <asm/hwrpb.h>
30#include <asm/tlbflush.h>
31
32#include "proto.h"
33#include "irq_impl.h"
34#include "pci_impl.h"
35#include "machvec_impl.h"
36
37
38/* Note that this interrupt code is identical to TAKARA. */
39
40/* Note mask bit is true for DISABLED irqs. */
41static unsigned long cached_irq_mask[2] = { -1, -1 };
42
43static inline void
44eiger_update_irq_hw(unsigned long irq, unsigned long mask)
45{
46 int regaddr;
47
48 mask = (irq >= 64 ? mask << 16 : mask >> ((irq - 16) & 0x30));
49 regaddr = 0x510 + (((irq - 16) >> 2) & 0x0c);
50 outl(mask & 0xffff0000UL, regaddr);
51}
52
53static inline void
54eiger_enable_irq(unsigned int irq)
55{
56 unsigned long mask;
57 mask = (cached_irq_mask[irq >= 64] &= ~(1UL << (irq & 63)));
58 eiger_update_irq_hw(irq, mask);
59}
60
61static void
62eiger_disable_irq(unsigned int irq)
63{
64 unsigned long mask;
65 mask = (cached_irq_mask[irq >= 64] |= 1UL << (irq & 63));
66 eiger_update_irq_hw(irq, mask);
67}
68
69static unsigned int
70eiger_startup_irq(unsigned int irq)
71{
72 eiger_enable_irq(irq);
73 return 0; /* never anything pending */
74}
75
76static void
77eiger_end_irq(unsigned int irq)
78{
79 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
80 eiger_enable_irq(irq);
81}
82
83static struct hw_interrupt_type eiger_irq_type = {
84 .typename = "EIGER",
85 .startup = eiger_startup_irq,
86 .shutdown = eiger_disable_irq,
87 .enable = eiger_enable_irq,
88 .disable = eiger_disable_irq,
89 .ack = eiger_disable_irq,
90 .end = eiger_end_irq,
91};
92
93static void
94eiger_device_interrupt(unsigned long vector, struct pt_regs * regs)
95{
96 unsigned intstatus;
97
98 /*
99 * The PALcode will have passed us vectors 0x800 or 0x810,
100 * which are fairly arbitrary values and serve only to tell
101 * us whether an interrupt has come in on IRQ0 or IRQ1. If
102 * it's IRQ1 it's a PCI interrupt; if it's IRQ0, it's
103 * probably ISA, but PCI interrupts can come through IRQ0
104 * as well if the interrupt controller isn't in accelerated
105 * mode.
106 *
107 * OTOH, the accelerator thing doesn't seem to be working
108 * overly well, so what we'll do instead is try directly
109 * examining the Master Interrupt Register to see if it's a
110 * PCI interrupt, and if _not_ then we'll pass it on to the
111 * ISA handler.
112 */
113
114 intstatus = inw(0x500) & 15;
115 if (intstatus) {
116 /*
117 * This is a PCI interrupt. Check each bit and
118 * despatch an interrupt if it's set.
119 */
120
121 if (intstatus & 8) handle_irq(16+3, regs);
122 if (intstatus & 4) handle_irq(16+2, regs);
123 if (intstatus & 2) handle_irq(16+1, regs);
124 if (intstatus & 1) handle_irq(16+0, regs);
125 } else {
126 isa_device_interrupt(vector, regs);
127 }
128}
129
130static void
131eiger_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
132{
133 int irq = (vector - 0x800) >> 4;
134 handle_irq(irq, regs);
135}
136
137static void __init
138eiger_init_irq(void)
139{
140 long i;
141
142 outb(0, DMA1_RESET_REG);
143 outb(0, DMA2_RESET_REG);
144 outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
145 outb(0, DMA2_MASK_REG);
146
147 if (alpha_using_srm)
148 alpha_mv.device_interrupt = eiger_srm_device_interrupt;
149
150 for (i = 16; i < 128; i += 16)
151 eiger_update_irq_hw(i, -1);
152
153 init_i8259a_irqs();
154
155 for (i = 16; i < 128; ++i) {
156 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
157 irq_desc[i].handler = &eiger_irq_type;
158 }
159}
160
161static int __init
162eiger_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
163{
164 u8 irq_orig;
165
166 /* The SRM console has already calculated out the IRQ value's for
167 option cards. As this works lets just read in the value already
168 set and change it to a useable value by Linux.
169
170 All the IRQ values generated by the console are greater than 90,
171 so we subtract 80 because it is (90 - allocated ISA IRQ's). */
172
173 pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq_orig);
174
175 return irq_orig - 0x80;
176}
177
178static u8 __init
179eiger_swizzle(struct pci_dev *dev, u8 *pinp)
180{
181 struct pci_controller *hose = dev->sysdata;
182 int slot, pin = *pinp;
183 int bridge_count = 0;
184
185 /* Find the number of backplane bridges. */
186 int backplane = inw(0x502) & 0x0f;
187
188 switch (backplane)
189 {
190 case 0x00: bridge_count = 0; break; /* No bridges */
191 case 0x01: bridge_count = 1; break; /* 1 */
192 case 0x03: bridge_count = 2; break; /* 2 */
193 case 0x07: bridge_count = 3; break; /* 3 */
194 case 0x0f: bridge_count = 4; break; /* 4 */
195 };
196
197 slot = PCI_SLOT(dev->devfn);
198 while (dev->bus->self) {
199 /* Check for built-in bridges on hose 0. */
200 if (hose->index == 0
201 && (PCI_SLOT(dev->bus->self->devfn)
202 > 20 - bridge_count)) {
203 slot = PCI_SLOT(dev->devfn);
204 break;
205 }
206 /* Must be a card-based bridge. */
207 pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
208
209 /* Move up the chain of bridges. */
210 dev = dev->bus->self;
211 }
212 *pinp = pin;
213 return slot;
214}
215
216/*
217 * The System Vectors
218 */
219
220struct alpha_machine_vector eiger_mv __initmv = {
221 .vector_name = "Eiger",
222 DO_EV6_MMU,
223 DO_DEFAULT_RTC,
224 DO_TSUNAMI_IO,
225 .machine_check = tsunami_machine_check,
226 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
227 .min_io_address = DEFAULT_IO_BASE,
228 .min_mem_address = DEFAULT_MEM_BASE,
229 .pci_dac_offset = TSUNAMI_DAC_OFFSET,
230
231 .nr_irqs = 128,
232 .device_interrupt = eiger_device_interrupt,
233
234 .init_arch = tsunami_init_arch,
235 .init_irq = eiger_init_irq,
236 .init_rtc = common_init_rtc,
237 .init_pci = common_init_pci,
238 .kill_arch = tsunami_kill_arch,
239 .pci_map_irq = eiger_map_irq,
240 .pci_swizzle = eiger_swizzle,
241};
242ALIAS_MV(eiger)
diff --git a/arch/alpha/kernel/sys_jensen.c b/arch/alpha/kernel/sys_jensen.c
new file mode 100644
index 000000000000..fcabb7c96a16
--- /dev/null
+++ b/arch/alpha/kernel/sys_jensen.c
@@ -0,0 +1,274 @@
1/*
2 * linux/arch/alpha/kernel/sys_jensen.c
3 *
4 * Copyright (C) 1995 Linus Torvalds
5 * Copyright (C) 1998, 1999 Richard Henderson
6 *
7 * Code supporting the Jensen.
8 */
9
10#include <linux/kernel.h>
11#include <linux/types.h>
12#include <linux/mm.h>
13#include <linux/sched.h>
14#include <linux/pci.h>
15#include <linux/init.h>
16
17#include <asm/ptrace.h>
18#include <asm/system.h>
19
20#define __EXTERN_INLINE inline
21#include <asm/io.h>
22#include <asm/jensen.h>
23#undef __EXTERN_INLINE
24
25#include <asm/dma.h>
26#include <asm/irq.h>
27#include <asm/mmu_context.h>
28#include <asm/pgtable.h>
29#include <asm/tlbflush.h>
30
31#include "proto.h"
32#include "irq_impl.h"
33#include "pci_impl.h"
34#include "machvec_impl.h"
35
36
37/*
38 * Jensen is special: the vector is 0x8X0 for EISA interrupt X, and
39 * 0x9X0 for the local motherboard interrupts.
40 *
41 * Note especially that those local interrupts CANNOT be masked,
42 * which causes much of the pain below...
43 *
44 * 0x660 - NMI
45 *
46 * 0x800 - IRQ0 interval timer (not used, as we use the RTC timer)
47 * 0x810 - IRQ1 line printer (duh..)
48 * 0x860 - IRQ6 floppy disk
49 *
50 * 0x900 - COM1
51 * 0x920 - COM2
52 * 0x980 - keyboard
53 * 0x990 - mouse
54 *
55 * PCI-based systems are more sane: they don't have the local
56 * interrupts at all, and have only normal PCI interrupts from
57 * devices. Happily it's easy enough to do a sane mapping from the
58 * Jensen.
59 *
60 * Note that this means that we may have to do a hardware
61 * "local_op" to a different interrupt than we report to the rest of the
62 * world.
63 */
64
65static unsigned int
66jensen_local_startup(unsigned int irq)
67{
68 /* the parport is really hw IRQ 1, silly Jensen. */
69 if (irq == 7)
70 i8259a_startup_irq(1);
71 else
72 /*
73 * For all true local interrupts, set the flag that prevents
74 * the IPL from being dropped during handler processing.
75 */
76 if (irq_desc[irq].action)
77 irq_desc[irq].action->flags |= SA_INTERRUPT;
78 return 0;
79}
80
81static void
82jensen_local_shutdown(unsigned int irq)
83{
84 /* the parport is really hw IRQ 1, silly Jensen. */
85 if (irq == 7)
86 i8259a_disable_irq(1);
87}
88
89static void
90jensen_local_enable(unsigned int irq)
91{
92 /* the parport is really hw IRQ 1, silly Jensen. */
93 if (irq == 7)
94 i8259a_enable_irq(1);
95}
96
97static void
98jensen_local_disable(unsigned int irq)
99{
100 /* the parport is really hw IRQ 1, silly Jensen. */
101 if (irq == 7)
102 i8259a_disable_irq(1);
103}
104
105static void
106jensen_local_ack(unsigned int irq)
107{
108 /* the parport is really hw IRQ 1, silly Jensen. */
109 if (irq == 7)
110 i8259a_mask_and_ack_irq(1);
111}
112
113static void
114jensen_local_end(unsigned int irq)
115{
116 /* the parport is really hw IRQ 1, silly Jensen. */
117 if (irq == 7)
118 i8259a_end_irq(1);
119}
120
121static struct hw_interrupt_type jensen_local_irq_type = {
122 .typename = "LOCAL",
123 .startup = jensen_local_startup,
124 .shutdown = jensen_local_shutdown,
125 .enable = jensen_local_enable,
126 .disable = jensen_local_disable,
127 .ack = jensen_local_ack,
128 .end = jensen_local_end,
129};
130
131static void
132jensen_device_interrupt(unsigned long vector, struct pt_regs * regs)
133{
134 int irq;
135
136 switch (vector) {
137 case 0x660:
138 printk("Whee.. NMI received. Probable hardware error\n");
139 printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461));
140 return;
141
142 /* local device interrupts: */
143 case 0x900: irq = 4; break; /* com1 -> irq 4 */
144 case 0x920: irq = 3; break; /* com2 -> irq 3 */
145 case 0x980: irq = 1; break; /* kbd -> irq 1 */
146 case 0x990: irq = 9; break; /* mouse -> irq 9 */
147
148 default:
149 if (vector > 0x900) {
150 printk("Unknown local interrupt %lx\n", vector);
151 return;
152 }
153
154 irq = (vector - 0x800) >> 4;
155 if (irq == 1)
156 irq = 7;
157 break;
158 }
159
160 /* If there is no handler yet... */
161 if (irq_desc[irq].action == NULL) {
162 /* If it is a local interrupt that cannot be masked... */
163 if (vector >= 0x900)
164 {
165 /* Clear keyboard/mouse state */
166 inb(0x64);
167 inb(0x60);
168 /* Reset serial ports */
169 inb(0x3fa);
170 inb(0x2fa);
171 outb(0x0c, 0x3fc);
172 outb(0x0c, 0x2fc);
173 /* Clear NMI */
174 outb(0,0x61);
175 outb(0,0x461);
176 }
177 }
178
179#if 0
180 /* A useful bit of code to find out if an interrupt is going wild. */
181 {
182 static unsigned int last_msg = 0, last_cc = 0;
183 static int last_irq = -1, count = 0;
184 unsigned int cc;
185
186 __asm __volatile("rpcc %0" : "=r"(cc));
187 ++count;
188#define JENSEN_CYCLES_PER_SEC (150000000)
189 if (cc - last_msg > ((JENSEN_CYCLES_PER_SEC) * 3) ||
190 irq != last_irq) {
191 printk(KERN_CRIT " irq %d count %d cc %u @ %lx\n",
192 irq, count, cc-last_cc, regs->pc);
193 count = 0;
194 last_msg = cc;
195 last_irq = irq;
196 }
197 last_cc = cc;
198 }
199#endif
200
201 handle_irq(irq, regs);
202}
203
204static void __init
205jensen_init_irq(void)
206{
207 init_i8259a_irqs();
208
209 irq_desc[1].handler = &jensen_local_irq_type;
210 irq_desc[4].handler = &jensen_local_irq_type;
211 irq_desc[3].handler = &jensen_local_irq_type;
212 irq_desc[7].handler = &jensen_local_irq_type;
213 irq_desc[9].handler = &jensen_local_irq_type;
214
215 common_init_isa_dma();
216}
217
218static void __init
219jensen_init_arch(void)
220{
221 struct pci_controller *hose;
222#ifdef CONFIG_PCI
223 static struct pci_dev fake_isa_bridge = { .dma_mask = 0xffffffffUL, };
224
225 isa_bridge = &fake_isa_bridge;
226#endif
227
228 /* Create a hose so that we can report i/o base addresses to
229 userland. */
230
231 pci_isa_hose = hose = alloc_pci_controller();
232 hose->io_space = &ioport_resource;
233 hose->mem_space = &iomem_resource;
234 hose->index = 0;
235
236 hose->sparse_mem_base = EISA_MEM - IDENT_ADDR;
237 hose->dense_mem_base = 0;
238 hose->sparse_io_base = EISA_IO - IDENT_ADDR;
239 hose->dense_io_base = 0;
240
241 hose->sg_isa = hose->sg_pci = NULL;
242 __direct_map_base = 0;
243 __direct_map_size = 0xffffffff;
244}
245
246static void
247jensen_machine_check (u64 vector, u64 la, struct pt_regs *regs)
248{
249 printk(KERN_CRIT "Machine check\n");
250}
251
252
253/*
254 * The System Vector
255 */
256
257struct alpha_machine_vector jensen_mv __initmv = {
258 .vector_name = "Jensen",
259 DO_EV4_MMU,
260 IO_LITE(JENSEN,jensen),
261 .machine_check = jensen_machine_check,
262 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
263 .rtc_port = 0x170,
264
265 .nr_irqs = 16,
266 .device_interrupt = jensen_device_interrupt,
267
268 .init_arch = jensen_init_arch,
269 .init_irq = jensen_init_irq,
270 .init_rtc = common_init_rtc,
271 .init_pci = NULL,
272 .kill_arch = NULL,
273};
274ALIAS_MV(jensen)
diff --git a/arch/alpha/kernel/sys_marvel.c b/arch/alpha/kernel/sys_marvel.c
new file mode 100644
index 000000000000..804727853d25
--- /dev/null
+++ b/arch/alpha/kernel/sys_marvel.c
@@ -0,0 +1,499 @@
1/*
2 * linux/arch/alpha/kernel/sys_marvel.c
3 *
4 * Marvel / IO7 support
5 */
6
7#include <linux/kernel.h>
8#include <linux/types.h>
9#include <linux/mm.h>
10#include <linux/sched.h>
11#include <linux/pci.h>
12#include <linux/init.h>
13#include <linux/bitops.h>
14
15#include <asm/ptrace.h>
16#include <asm/system.h>
17#include <asm/dma.h>
18#include <asm/irq.h>
19#include <asm/mmu_context.h>
20#include <asm/io.h>
21#include <asm/pgtable.h>
22#include <asm/core_marvel.h>
23#include <asm/hwrpb.h>
24#include <asm/tlbflush.h>
25
26#include "proto.h"
27#include "err_impl.h"
28#include "irq_impl.h"
29#include "pci_impl.h"
30#include "machvec_impl.h"
31
32#if NR_IRQS < MARVEL_NR_IRQS
33# error NR_IRQS < MARVEL_NR_IRQS !!!
34#endif
35
36
37/*
38 * Interrupt handling.
39 */
40static void
41io7_device_interrupt(unsigned long vector, struct pt_regs * regs)
42{
43 unsigned int pid;
44 unsigned int irq;
45
46 /*
47 * Vector is 0x800 + (interrupt)
48 *
49 * where (interrupt) is:
50 *
51 * ...16|15 14|13 4|3 0
52 * -----+-----+--------+---
53 * PE | 0 | irq | 0
54 *
55 * where (irq) is
56 *
57 * 0x0800 - 0x0ff0 - 0x0800 + (LSI id << 4)
58 * 0x1000 - 0x2ff0 - 0x1000 + (MSI_DAT<8:0> << 4)
59 */
60 pid = vector >> 16;
61 irq = ((vector & 0xffff) - 0x800) >> 4;
62
63 irq += 16; /* offset for legacy */
64 irq &= MARVEL_IRQ_VEC_IRQ_MASK; /* not too many bits */
65 irq |= pid << MARVEL_IRQ_VEC_PE_SHIFT; /* merge the pid */
66
67 handle_irq(irq, regs);
68}
69
70static volatile unsigned long *
71io7_get_irq_ctl(unsigned int irq, struct io7 **pio7)
72{
73 volatile unsigned long *ctl;
74 unsigned int pid;
75 struct io7 *io7;
76
77 pid = irq >> MARVEL_IRQ_VEC_PE_SHIFT;
78
79 if (!(io7 = marvel_find_io7(pid))) {
80 printk(KERN_ERR
81 "%s for nonexistent io7 -- vec %x, pid %d\n",
82 __FUNCTION__, irq, pid);
83 return NULL;
84 }
85
86 irq &= MARVEL_IRQ_VEC_IRQ_MASK; /* isolate the vector */
87 irq -= 16; /* subtract legacy bias */
88
89 if (irq >= 0x180) {
90 printk(KERN_ERR
91 "%s for invalid irq -- pid %d adjusted irq %x\n",
92 __FUNCTION__, pid, irq);
93 return NULL;
94 }
95
96 ctl = &io7->csrs->PO7_LSI_CTL[irq & 0xff].csr; /* assume LSI */
97 if (irq >= 0x80) /* MSI */
98 ctl = &io7->csrs->PO7_MSI_CTL[((irq - 0x80) >> 5) & 0x0f].csr;
99
100 if (pio7) *pio7 = io7;
101 return ctl;
102}
103
104static void
105io7_enable_irq(unsigned int irq)
106{
107 volatile unsigned long *ctl;
108 struct io7 *io7;
109
110 ctl = io7_get_irq_ctl(irq, &io7);
111 if (!ctl || !io7) {
112 printk(KERN_ERR "%s: get_ctl failed for irq %x\n",
113 __FUNCTION__, irq);
114 return;
115 }
116
117 spin_lock(&io7->irq_lock);
118 *ctl |= 1UL << 24;
119 mb();
120 *ctl;
121 spin_unlock(&io7->irq_lock);
122}
123
124static void
125io7_disable_irq(unsigned int irq)
126{
127 volatile unsigned long *ctl;
128 struct io7 *io7;
129
130 ctl = io7_get_irq_ctl(irq, &io7);
131 if (!ctl || !io7) {
132 printk(KERN_ERR "%s: get_ctl failed for irq %x\n",
133 __FUNCTION__, irq);
134 return;
135 }
136
137 spin_lock(&io7->irq_lock);
138 *ctl &= ~(1UL << 24);
139 mb();
140 *ctl;
141 spin_unlock(&io7->irq_lock);
142}
143
144static unsigned int
145io7_startup_irq(unsigned int irq)
146{
147 io7_enable_irq(irq);
148 return 0; /* never anything pending */
149}
150
151static void
152io7_end_irq(unsigned int irq)
153{
154 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
155 io7_enable_irq(irq);
156}
157
158static void
159marvel_irq_noop(unsigned int irq)
160{
161 return;
162}
163
164static unsigned int
165marvel_irq_noop_return(unsigned int irq)
166{
167 return 0;
168}
169
170static struct hw_interrupt_type marvel_legacy_irq_type = {
171 .typename = "LEGACY",
172 .startup = marvel_irq_noop_return,
173 .shutdown = marvel_irq_noop,
174 .enable = marvel_irq_noop,
175 .disable = marvel_irq_noop,
176 .ack = marvel_irq_noop,
177 .end = marvel_irq_noop,
178};
179
180static struct hw_interrupt_type io7_lsi_irq_type = {
181 .typename = "LSI",
182 .startup = io7_startup_irq,
183 .shutdown = io7_disable_irq,
184 .enable = io7_enable_irq,
185 .disable = io7_disable_irq,
186 .ack = io7_disable_irq,
187 .end = io7_end_irq,
188};
189
190static struct hw_interrupt_type io7_msi_irq_type = {
191 .typename = "MSI",
192 .startup = io7_startup_irq,
193 .shutdown = io7_disable_irq,
194 .enable = io7_enable_irq,
195 .disable = io7_disable_irq,
196 .ack = marvel_irq_noop,
197 .end = io7_end_irq,
198};
199
200static void
201io7_redirect_irq(struct io7 *io7,
202 volatile unsigned long *csr,
203 unsigned int where)
204{
205 unsigned long val;
206
207 val = *csr;
208 val &= ~(0x1ffUL << 24); /* clear the target pid */
209 val |= ((unsigned long)where << 24); /* set the new target pid */
210
211 *csr = val;
212 mb();
213 *csr;
214}
215
216static void
217io7_redirect_one_lsi(struct io7 *io7, unsigned int which, unsigned int where)
218{
219 unsigned long val;
220
221 /*
222 * LSI_CTL has target PID @ 14
223 */
224 val = io7->csrs->PO7_LSI_CTL[which].csr;
225 val &= ~(0x1ffUL << 14); /* clear the target pid */
226 val |= ((unsigned long)where << 14); /* set the new target pid */
227
228 io7->csrs->PO7_LSI_CTL[which].csr = val;
229 mb();
230 io7->csrs->PO7_LSI_CTL[which].csr;
231}
232
233static void
234io7_redirect_one_msi(struct io7 *io7, unsigned int which, unsigned int where)
235{
236 unsigned long val;
237
238 /*
239 * MSI_CTL has target PID @ 14
240 */
241 val = io7->csrs->PO7_MSI_CTL[which].csr;
242 val &= ~(0x1ffUL << 14); /* clear the target pid */
243 val |= ((unsigned long)where << 14); /* set the new target pid */
244
245 io7->csrs->PO7_MSI_CTL[which].csr = val;
246 mb();
247 io7->csrs->PO7_MSI_CTL[which].csr;
248}
249
250static void __init
251init_one_io7_lsi(struct io7 *io7, unsigned int which, unsigned int where)
252{
253 /*
254 * LSI_CTL has target PID @ 14
255 */
256 io7->csrs->PO7_LSI_CTL[which].csr = ((unsigned long)where << 14);
257 mb();
258 io7->csrs->PO7_LSI_CTL[which].csr;
259}
260
261static void __init
262init_one_io7_msi(struct io7 *io7, unsigned int which, unsigned int where)
263{
264 /*
265 * MSI_CTL has target PID @ 14
266 */
267 io7->csrs->PO7_MSI_CTL[which].csr = ((unsigned long)where << 14);
268 mb();
269 io7->csrs->PO7_MSI_CTL[which].csr;
270}
271
272static void __init
273init_io7_irqs(struct io7 *io7,
274 struct hw_interrupt_type *lsi_ops,
275 struct hw_interrupt_type *msi_ops)
276{
277 long base = (io7->pe << MARVEL_IRQ_VEC_PE_SHIFT) + 16;
278 long i;
279
280 printk("Initializing interrupts for IO7 at PE %u - base %lx\n",
281 io7->pe, base);
282
283 /*
284 * Where should interrupts from this IO7 go?
285 *
286 * They really should be sent to the local CPU to avoid having to
287 * traverse the mesh, but if it's not an SMP kernel, they have to
288 * go to the boot CPU. Send them all to the boot CPU for now,
289 * as each secondary starts, it can redirect it's local device
290 * interrupts.
291 */
292 printk(" Interrupts reported to CPU at PE %u\n", boot_cpuid);
293
294 spin_lock(&io7->irq_lock);
295
296 /* set up the error irqs */
297 io7_redirect_irq(io7, &io7->csrs->HLT_CTL.csr, boot_cpuid);
298 io7_redirect_irq(io7, &io7->csrs->HPI_CTL.csr, boot_cpuid);
299 io7_redirect_irq(io7, &io7->csrs->CRD_CTL.csr, boot_cpuid);
300 io7_redirect_irq(io7, &io7->csrs->STV_CTL.csr, boot_cpuid);
301 io7_redirect_irq(io7, &io7->csrs->HEI_CTL.csr, boot_cpuid);
302
303 /* Set up the lsi irqs. */
304 for (i = 0; i < 128; ++i) {
305 irq_desc[base + i].status = IRQ_DISABLED | IRQ_LEVEL;
306 irq_desc[base + i].handler = lsi_ops;
307 }
308
309 /* Disable the implemented irqs in hardware. */
310 for (i = 0; i < 0x60; ++i)
311 init_one_io7_lsi(io7, i, boot_cpuid);
312
313 init_one_io7_lsi(io7, 0x74, boot_cpuid);
314 init_one_io7_lsi(io7, 0x75, boot_cpuid);
315
316
317 /* Set up the msi irqs. */
318 for (i = 128; i < (128 + 512); ++i) {
319 irq_desc[base + i].status = IRQ_DISABLED | IRQ_LEVEL;
320 irq_desc[base + i].handler = msi_ops;
321 }
322
323 for (i = 0; i < 16; ++i)
324 init_one_io7_msi(io7, i, boot_cpuid);
325
326 spin_unlock(&io7->irq_lock);
327}
328
329static void __init
330marvel_init_irq(void)
331{
332 int i;
333 struct io7 *io7 = NULL;
334
335 /* Reserve the legacy irqs. */
336 for (i = 0; i < 16; ++i) {
337 irq_desc[i].status = IRQ_DISABLED;
338 irq_desc[i].handler = &marvel_legacy_irq_type;
339 }
340
341 /* Init the io7 irqs. */
342 for (io7 = NULL; (io7 = marvel_next_io7(io7)) != NULL; )
343 init_io7_irqs(io7, &io7_lsi_irq_type, &io7_msi_irq_type);
344}
345
346static int
347marvel_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
348{
349 struct pci_controller *hose = dev->sysdata;
350 struct io7_port *io7_port = hose->sysdata;
351 struct io7 *io7 = io7_port->io7;
352 int msi_loc, msi_data_off;
353 u16 msg_ctl;
354 u16 msg_dat;
355 u8 intline;
356 int irq;
357
358 pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &intline);
359 irq = intline;
360
361 msi_loc = pci_find_capability(dev, PCI_CAP_ID_MSI);
362 msg_ctl = 0;
363 if (msi_loc)
364 pci_read_config_word(dev, msi_loc + PCI_MSI_FLAGS, &msg_ctl);
365
366 if (msg_ctl & PCI_MSI_FLAGS_ENABLE) {
367 msi_data_off = PCI_MSI_DATA_32;
368 if (msg_ctl & PCI_MSI_FLAGS_64BIT)
369 msi_data_off = PCI_MSI_DATA_64;
370 pci_read_config_word(dev, msi_loc + msi_data_off, &msg_dat);
371
372 irq = msg_dat & 0x1ff; /* we use msg_data<8:0> */
373 irq += 0x80; /* offset for lsi */
374
375#if 1
376 printk("PCI:%d:%d:%d (hose %d) [%s] is using MSI\n",
377 dev->bus->number,
378 PCI_SLOT(dev->devfn),
379 PCI_FUNC(dev->devfn),
380 hose->index,
381 pci_pretty_name (dev));
382 printk(" %d message(s) from 0x%04x\n",
383 1 << ((msg_ctl & PCI_MSI_FLAGS_QSIZE) >> 4),
384 msg_dat);
385 printk(" reporting on %d IRQ(s) from %d (0x%x)\n",
386 1 << ((msg_ctl & PCI_MSI_FLAGS_QSIZE) >> 4),
387 (irq + 16) | (io7->pe << MARVEL_IRQ_VEC_PE_SHIFT),
388 (irq + 16) | (io7->pe << MARVEL_IRQ_VEC_PE_SHIFT));
389#endif
390
391#if 0
392 pci_write_config_word(dev, msi_loc + PCI_MSI_FLAGS,
393 msg_ctl & ~PCI_MSI_FLAGS_ENABLE);
394 pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &intline);
395 irq = intline;
396
397 printk(" forcing LSI interrupt on irq %d [0x%x]\n", irq, irq);
398#endif
399 }
400
401 irq += 16; /* offset for legacy */
402 irq |= io7->pe << MARVEL_IRQ_VEC_PE_SHIFT; /* merge the pid */
403
404 return irq;
405}
406
407static void __init
408marvel_init_pci(void)
409{
410 struct io7 *io7;
411
412 marvel_register_error_handlers();
413
414 pci_probe_only = 1;
415 common_init_pci();
416
417#ifdef CONFIG_VGA_HOSE
418 locate_and_init_vga(NULL);
419#endif
420
421 /* Clear any io7 errors. */
422 for (io7 = NULL; (io7 = marvel_next_io7(io7)) != NULL; )
423 io7_clear_errors(io7);
424}
425
426static void
427marvel_init_rtc(void)
428{
429 init_rtc_irq();
430}
431
432static void
433marvel_smp_callin(void)
434{
435 int cpuid = hard_smp_processor_id();
436 struct io7 *io7 = marvel_find_io7(cpuid);
437 unsigned int i;
438
439 if (!io7)
440 return;
441
442 /*
443 * There is a local IO7 - redirect all of its interrupts here.
444 */
445 printk("Redirecting IO7 interrupts to local CPU at PE %u\n", cpuid);
446
447 /* Redirect the error IRQS here. */
448 io7_redirect_irq(io7, &io7->csrs->HLT_CTL.csr, cpuid);
449 io7_redirect_irq(io7, &io7->csrs->HPI_CTL.csr, cpuid);
450 io7_redirect_irq(io7, &io7->csrs->CRD_CTL.csr, cpuid);
451 io7_redirect_irq(io7, &io7->csrs->STV_CTL.csr, cpuid);
452 io7_redirect_irq(io7, &io7->csrs->HEI_CTL.csr, cpuid);
453
454 /* Redirect the implemented LSIs here. */
455 for (i = 0; i < 0x60; ++i)
456 io7_redirect_one_lsi(io7, i, cpuid);
457
458 io7_redirect_one_lsi(io7, 0x74, cpuid);
459 io7_redirect_one_lsi(io7, 0x75, cpuid);
460
461 /* Redirect the MSIs here. */
462 for (i = 0; i < 16; ++i)
463 io7_redirect_one_msi(io7, i, cpuid);
464}
465
466/*
467 * System Vectors
468 */
469struct alpha_machine_vector marvel_ev7_mv __initmv = {
470 .vector_name = "MARVEL/EV7",
471 DO_EV7_MMU,
472 DO_DEFAULT_RTC,
473 DO_MARVEL_IO,
474 .machine_check = marvel_machine_check,
475 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
476 .min_io_address = DEFAULT_IO_BASE,
477 .min_mem_address = DEFAULT_MEM_BASE,
478 .pci_dac_offset = IO7_DAC_OFFSET,
479
480 .nr_irqs = MARVEL_NR_IRQS,
481 .device_interrupt = io7_device_interrupt,
482
483 .agp_info = marvel_agp_info,
484
485 .smp_callin = marvel_smp_callin,
486 .init_arch = marvel_init_arch,
487 .init_irq = marvel_init_irq,
488 .init_rtc = marvel_init_rtc,
489 .init_pci = marvel_init_pci,
490 .kill_arch = marvel_kill_arch,
491 .pci_map_irq = marvel_map_irq,
492 .pci_swizzle = common_swizzle,
493
494 .pa_to_nid = marvel_pa_to_nid,
495 .cpuid_to_nid = marvel_cpuid_to_nid,
496 .node_mem_start = marvel_node_mem_start,
497 .node_mem_size = marvel_node_mem_size,
498};
499ALIAS_MV(marvel_ev7)
diff --git a/arch/alpha/kernel/sys_miata.c b/arch/alpha/kernel/sys_miata.c
new file mode 100644
index 000000000000..61ac56f8eeea
--- /dev/null
+++ b/arch/alpha/kernel/sys_miata.c
@@ -0,0 +1,289 @@
1/*
2 * linux/arch/alpha/kernel/sys_miata.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996 Jay A Estabrook
6 * Copyright (C) 1998, 1999, 2000 Richard Henderson
7 *
8 * Code supporting the MIATA (EV56+PYXIS).
9 */
10
11#include <linux/kernel.h>
12#include <linux/types.h>
13#include <linux/mm.h>
14#include <linux/sched.h>
15#include <linux/pci.h>
16#include <linux/init.h>
17#include <linux/reboot.h>
18
19#include <asm/ptrace.h>
20#include <asm/system.h>
21#include <asm/dma.h>
22#include <asm/irq.h>
23#include <asm/mmu_context.h>
24#include <asm/io.h>
25#include <asm/pgtable.h>
26#include <asm/core_cia.h>
27#include <asm/tlbflush.h>
28
29#include "proto.h"
30#include "irq_impl.h"
31#include "pci_impl.h"
32#include "machvec_impl.h"
33
34
35static void
36miata_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
37{
38 int irq;
39
40 irq = (vector - 0x800) >> 4;
41
42 /*
43 * I really hate to do this, but the MIATA SRM console ignores the
44 * low 8 bits in the interrupt summary register, and reports the
45 * vector 0x80 *lower* than I expected from the bit numbering in
46 * the documentation.
47 * This was done because the low 8 summary bits really aren't used
48 * for reporting any interrupts (the PCI-ISA bridge, bit 7, isn't
49 * used for this purpose, as PIC interrupts are delivered as the
50 * vectors 0x800-0x8f0).
51 * But I really don't want to change the fixup code for allocation
52 * of IRQs, nor the alpha_irq_mask maintenance stuff, both of which
53 * look nice and clean now.
54 * So, here's this grotty hack... :-(
55 */
56 if (irq >= 16)
57 irq = irq + 8;
58
59 handle_irq(irq, regs);
60}
61
62static void __init
63miata_init_irq(void)
64{
65 if (alpha_using_srm)
66 alpha_mv.device_interrupt = miata_srm_device_interrupt;
67
68#if 0
69 /* These break on MiataGL so we'll try not to do it at all. */
70 *(vulp)PYXIS_INT_HILO = 0x000000B2UL; mb(); /* ISA/NMI HI */
71 *(vulp)PYXIS_RT_COUNT = 0UL; mb(); /* clear count */
72#endif
73
74 init_i8259a_irqs();
75
76 /* Not interested in the bogus interrupts (3,10), Fan Fault (0),
77 NMI (1), or EIDE (9).
78
79 We also disable the risers (4,5), since we don't know how to
80 route the interrupts behind the bridge. */
81 init_pyxis_irqs(0x63b0000);
82
83 common_init_isa_dma();
84 setup_irq(16+2, &halt_switch_irqaction); /* SRM only? */
85 setup_irq(16+6, &timer_cascade_irqaction);
86}
87
88
89/*
90 * PCI Fixup configuration.
91 *
92 * Summary @ PYXIS_INT_REQ:
93 * Bit Meaning
94 * 0 Fan Fault
95 * 1 NMI
96 * 2 Halt/Reset switch
97 * 3 none
98 * 4 CID0 (Riser ID)
99 * 5 CID1 (Riser ID)
100 * 6 Interval timer
101 * 7 PCI-ISA Bridge
102 * 8 Ethernet
103 * 9 EIDE (deprecated, ISA 14/15 used)
104 *10 none
105 *11 USB
106 *12 Interrupt Line A from slot 4
107 *13 Interrupt Line B from slot 4
108 *14 Interrupt Line C from slot 4
109 *15 Interrupt Line D from slot 4
110 *16 Interrupt Line A from slot 5
111 *17 Interrupt line B from slot 5
112 *18 Interrupt Line C from slot 5
113 *19 Interrupt Line D from slot 5
114 *20 Interrupt Line A from slot 1
115 *21 Interrupt Line B from slot 1
116 *22 Interrupt Line C from slot 1
117 *23 Interrupt Line D from slot 1
118 *24 Interrupt Line A from slot 2
119 *25 Interrupt Line B from slot 2
120 *26 Interrupt Line C from slot 2
121 *27 Interrupt Line D from slot 2
122 *27 Interrupt Line A from slot 3
123 *29 Interrupt Line B from slot 3
124 *30 Interrupt Line C from slot 3
125 *31 Interrupt Line D from slot 3
126 *
127 * The device to slot mapping looks like:
128 *
129 * Slot Device
130 * 3 DC21142 Ethernet
131 * 4 EIDE CMD646
132 * 5 none
133 * 6 USB
134 * 7 PCI-ISA bridge
135 * 8 PCI-PCI Bridge (SBU Riser)
136 * 9 none
137 * 10 none
138 * 11 PCI on board slot 4 (SBU Riser)
139 * 12 PCI on board slot 5 (SBU Riser)
140 *
141 * These are behind the bridge, so I'm not sure what to do...
142 *
143 * 13 PCI on board slot 1 (SBU Riser)
144 * 14 PCI on board slot 2 (SBU Riser)
145 * 15 PCI on board slot 3 (SBU Riser)
146 *
147 *
148 * This two layered interrupt approach means that we allocate IRQ 16 and
149 * above for PCI interrupts. The IRQ relates to which bit the interrupt
150 * comes in on. This makes interrupt processing much easier.
151 */
152
153static int __init
154miata_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
155{
156 static char irq_tab[18][5] __initdata = {
157 /*INT INTA INTB INTC INTD */
158 {16+ 8, 16+ 8, 16+ 8, 16+ 8, 16+ 8}, /* IdSel 14, DC21142 */
159 { -1, -1, -1, -1, -1}, /* IdSel 15, EIDE */
160 { -1, -1, -1, -1, -1}, /* IdSel 16, none */
161 { -1, -1, -1, -1, -1}, /* IdSel 17, none */
162 { -1, -1, -1, -1, -1}, /* IdSel 18, PCI-ISA */
163 { -1, -1, -1, -1, -1}, /* IdSel 19, PCI-PCI */
164 { -1, -1, -1, -1, -1}, /* IdSel 20, none */
165 { -1, -1, -1, -1, -1}, /* IdSel 21, none */
166 {16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 22, slot 4 */
167 {16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 23, slot 5 */
168 /* the next 7 are actually on PCI bus 1, across the bridge */
169 {16+11, 16+11, 16+11, 16+11, 16+11}, /* IdSel 24, QLISP/GL*/
170 { -1, -1, -1, -1, -1}, /* IdSel 25, none */
171 { -1, -1, -1, -1, -1}, /* IdSel 26, none */
172 { -1, -1, -1, -1, -1}, /* IdSel 27, none */
173 {16+20, 16+20, 16+21, 16+22, 16+23}, /* IdSel 28, slot 1 */
174 {16+24, 16+24, 16+25, 16+26, 16+27}, /* IdSel 29, slot 2 */
175 {16+28, 16+28, 16+29, 16+30, 16+31}, /* IdSel 30, slot 3 */
176 /* This bridge is on the main bus of the later orig MIATA */
177 { -1, -1, -1, -1, -1}, /* IdSel 31, PCI-PCI */
178 };
179 const long min_idsel = 3, max_idsel = 20, irqs_per_slot = 5;
180
181 /* the USB function of the 82c693 has it's interrupt connected to
182 the 2nd 8259 controller. So we have to check for it first. */
183
184 if((slot == 7) && (PCI_FUNC(dev->devfn) == 3)) {
185 u8 irq=0;
186
187 if(pci_read_config_byte(pci_find_slot(dev->bus->number, dev->devfn & ~(7)), 0x40,&irq)!=PCIBIOS_SUCCESSFUL)
188 return -1;
189 else
190 return irq;
191 }
192
193 return COMMON_TABLE_LOOKUP;
194}
195
196static u8 __init
197miata_swizzle(struct pci_dev *dev, u8 *pinp)
198{
199 int slot, pin = *pinp;
200
201 if (dev->bus->number == 0) {
202 slot = PCI_SLOT(dev->devfn);
203 }
204 /* Check for the built-in bridge. */
205 else if ((PCI_SLOT(dev->bus->self->devfn) == 8) ||
206 (PCI_SLOT(dev->bus->self->devfn) == 20)) {
207 slot = PCI_SLOT(dev->devfn) + 9;
208 }
209 else
210 {
211 /* Must be a card-based bridge. */
212 do {
213 if ((PCI_SLOT(dev->bus->self->devfn) == 8) ||
214 (PCI_SLOT(dev->bus->self->devfn) == 20)) {
215 slot = PCI_SLOT(dev->devfn) + 9;
216 break;
217 }
218 pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
219
220 /* Move up the chain of bridges. */
221 dev = dev->bus->self;
222 /* Slot of the next bridge. */
223 slot = PCI_SLOT(dev->devfn);
224 } while (dev->bus->self);
225 }
226 *pinp = pin;
227 return slot;
228}
229
230static void __init
231miata_init_pci(void)
232{
233 cia_init_pci();
234 SMC669_Init(0); /* it might be a GL (fails harmlessly if not) */
235 es1888_init();
236}
237
238static void
239miata_kill_arch(int mode)
240{
241 cia_kill_arch(mode);
242
243#ifndef ALPHA_RESTORE_SRM_SETUP
244 switch(mode) {
245 case LINUX_REBOOT_CMD_RESTART:
246 /* Who said DEC engineers have no sense of humor? ;-) */
247 if (alpha_using_srm) {
248 *(vuip) PYXIS_RESET = 0x0000dead;
249 mb();
250 }
251 break;
252 case LINUX_REBOOT_CMD_HALT:
253 break;
254 case LINUX_REBOOT_CMD_POWER_OFF:
255 break;
256 }
257
258 halt();
259#endif
260}
261
262
263/*
264 * The System Vector
265 */
266
267struct alpha_machine_vector miata_mv __initmv = {
268 .vector_name = "Miata",
269 DO_EV5_MMU,
270 DO_DEFAULT_RTC,
271 DO_PYXIS_IO,
272 .machine_check = cia_machine_check,
273 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
274 .min_io_address = DEFAULT_IO_BASE,
275 .min_mem_address = DEFAULT_MEM_BASE,
276 .pci_dac_offset = PYXIS_DAC_OFFSET,
277
278 .nr_irqs = 48,
279 .device_interrupt = pyxis_device_interrupt,
280
281 .init_arch = pyxis_init_arch,
282 .init_irq = miata_init_irq,
283 .init_rtc = common_init_rtc,
284 .init_pci = miata_init_pci,
285 .kill_arch = miata_kill_arch,
286 .pci_map_irq = miata_map_irq,
287 .pci_swizzle = miata_swizzle,
288};
289ALIAS_MV(miata)
diff --git a/arch/alpha/kernel/sys_mikasa.c b/arch/alpha/kernel/sys_mikasa.c
new file mode 100644
index 000000000000..d78a0daa6168
--- /dev/null
+++ b/arch/alpha/kernel/sys_mikasa.c
@@ -0,0 +1,265 @@
1/*
2 * linux/arch/alpha/kernel/sys_mikasa.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996 Jay A Estabrook
6 * Copyright (C) 1998, 1999 Richard Henderson
7 *
8 * Code supporting the MIKASA (AlphaServer 1000).
9 */
10
11#include <linux/config.h>
12#include <linux/kernel.h>
13#include <linux/types.h>
14#include <linux/mm.h>
15#include <linux/sched.h>
16#include <linux/pci.h>
17#include <linux/init.h>
18#include <linux/bitops.h>
19
20#include <asm/ptrace.h>
21#include <asm/system.h>
22#include <asm/dma.h>
23#include <asm/irq.h>
24#include <asm/mmu_context.h>
25#include <asm/io.h>
26#include <asm/pgtable.h>
27#include <asm/core_apecs.h>
28#include <asm/core_cia.h>
29#include <asm/tlbflush.h>
30
31#include "proto.h"
32#include "irq_impl.h"
33#include "pci_impl.h"
34#include "machvec_impl.h"
35
36
37/* Note mask bit is true for ENABLED irqs. */
38static int cached_irq_mask;
39
40static inline void
41mikasa_update_irq_hw(int mask)
42{
43 outw(mask, 0x536);
44}
45
46static inline void
47mikasa_enable_irq(unsigned int irq)
48{
49 mikasa_update_irq_hw(cached_irq_mask |= 1 << (irq - 16));
50}
51
52static void
53mikasa_disable_irq(unsigned int irq)
54{
55 mikasa_update_irq_hw(cached_irq_mask &= ~(1 << (irq - 16)));
56}
57
58static unsigned int
59mikasa_startup_irq(unsigned int irq)
60{
61 mikasa_enable_irq(irq);
62 return 0;
63}
64
65static void
66mikasa_end_irq(unsigned int irq)
67{
68 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
69 mikasa_enable_irq(irq);
70}
71
72static struct hw_interrupt_type mikasa_irq_type = {
73 .typename = "MIKASA",
74 .startup = mikasa_startup_irq,
75 .shutdown = mikasa_disable_irq,
76 .enable = mikasa_enable_irq,
77 .disable = mikasa_disable_irq,
78 .ack = mikasa_disable_irq,
79 .end = mikasa_end_irq,
80};
81
82static void
83mikasa_device_interrupt(unsigned long vector, struct pt_regs *regs)
84{
85 unsigned long pld;
86 unsigned int i;
87
88 /* Read the interrupt summary registers */
89 pld = (((~inw(0x534) & 0x0000ffffUL) << 16)
90 | (((unsigned long) inb(0xa0)) << 8)
91 | inb(0x20));
92
93 /*
94 * Now for every possible bit set, work through them and call
95 * the appropriate interrupt handler.
96 */
97 while (pld) {
98 i = ffz(~pld);
99 pld &= pld - 1; /* clear least bit set */
100 if (i < 16) {
101 isa_device_interrupt(vector, regs);
102 } else {
103 handle_irq(i, regs);
104 }
105 }
106}
107
108static void __init
109mikasa_init_irq(void)
110{
111 long i;
112
113 if (alpha_using_srm)
114 alpha_mv.device_interrupt = srm_device_interrupt;
115
116 mikasa_update_irq_hw(0);
117
118 for (i = 16; i < 32; ++i) {
119 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
120 irq_desc[i].handler = &mikasa_irq_type;
121 }
122
123 init_i8259a_irqs();
124 common_init_isa_dma();
125}
126
127
128/*
129 * PCI Fixup configuration.
130 *
131 * Summary @ 0x536:
132 * Bit Meaning
133 * 0 Interrupt Line A from slot 0
134 * 1 Interrupt Line B from slot 0
135 * 2 Interrupt Line C from slot 0
136 * 3 Interrupt Line D from slot 0
137 * 4 Interrupt Line A from slot 1
138 * 5 Interrupt line B from slot 1
139 * 6 Interrupt Line C from slot 1
140 * 7 Interrupt Line D from slot 1
141 * 8 Interrupt Line A from slot 2
142 * 9 Interrupt Line B from slot 2
143 *10 Interrupt Line C from slot 2
144 *11 Interrupt Line D from slot 2
145 *12 NCR 810 SCSI
146 *13 Power Supply Fail
147 *14 Temperature Warn
148 *15 Reserved
149 *
150 * The device to slot mapping looks like:
151 *
152 * Slot Device
153 * 6 NCR SCSI controller
154 * 7 Intel PCI-EISA bridge chip
155 * 11 PCI on board slot 0
156 * 12 PCI on board slot 1
157 * 13 PCI on board slot 2
158 *
159 *
160 * This two layered interrupt approach means that we allocate IRQ 16 and
161 * above for PCI interrupts. The IRQ relates to which bit the interrupt
162 * comes in on. This makes interrupt processing much easier.
163 */
164
165static int __init
166mikasa_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
167{
168 static char irq_tab[8][5] __initdata = {
169 /*INT INTA INTB INTC INTD */
170 {16+12, 16+12, 16+12, 16+12, 16+12}, /* IdSel 17, SCSI */
171 { -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */
172 { -1, -1, -1, -1, -1}, /* IdSel 19, ???? */
173 { -1, -1, -1, -1, -1}, /* IdSel 20, ???? */
174 { -1, -1, -1, -1, -1}, /* IdSel 21, ???? */
175 { 16+0, 16+0, 16+1, 16+2, 16+3}, /* IdSel 22, slot 0 */
176 { 16+4, 16+4, 16+5, 16+6, 16+7}, /* IdSel 23, slot 1 */
177 { 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 24, slot 2 */
178 };
179 const long min_idsel = 6, max_idsel = 13, irqs_per_slot = 5;
180 return COMMON_TABLE_LOOKUP;
181}
182
183
184#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
185static void
186mikasa_apecs_machine_check(unsigned long vector, unsigned long la_ptr,
187 struct pt_regs * regs)
188{
189#define MCHK_NO_DEVSEL 0x205U
190#define MCHK_NO_TABT 0x204U
191
192 struct el_common *mchk_header;
193 unsigned int code;
194
195 mchk_header = (struct el_common *)la_ptr;
196
197 /* Clear the error before any reporting. */
198 mb();
199 mb(); /* magic */
200 draina();
201 apecs_pci_clr_err();
202 wrmces(0x7);
203 mb();
204
205 code = mchk_header->code;
206 process_mcheck_info(vector, la_ptr, regs, "MIKASA APECS",
207 (mcheck_expected(0)
208 && (code == MCHK_NO_DEVSEL
209 || code == MCHK_NO_TABT)));
210}
211#endif
212
213
214/*
215 * The System Vector
216 */
217
218#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
219struct alpha_machine_vector mikasa_mv __initmv = {
220 .vector_name = "Mikasa",
221 DO_EV4_MMU,
222 DO_DEFAULT_RTC,
223 DO_APECS_IO,
224 .machine_check = mikasa_apecs_machine_check,
225 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
226 .min_io_address = DEFAULT_IO_BASE,
227 .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE,
228
229 .nr_irqs = 32,
230 .device_interrupt = mikasa_device_interrupt,
231
232 .init_arch = apecs_init_arch,
233 .init_irq = mikasa_init_irq,
234 .init_rtc = common_init_rtc,
235 .init_pci = common_init_pci,
236 .pci_map_irq = mikasa_map_irq,
237 .pci_swizzle = common_swizzle,
238};
239ALIAS_MV(mikasa)
240#endif
241
242#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PRIMO)
243struct alpha_machine_vector mikasa_primo_mv __initmv = {
244 .vector_name = "Mikasa-Primo",
245 DO_EV5_MMU,
246 DO_DEFAULT_RTC,
247 DO_CIA_IO,
248 .machine_check = cia_machine_check,
249 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
250 .min_io_address = DEFAULT_IO_BASE,
251 .min_mem_address = CIA_DEFAULT_MEM_BASE,
252
253 .nr_irqs = 32,
254 .device_interrupt = mikasa_device_interrupt,
255
256 .init_arch = cia_init_arch,
257 .init_irq = mikasa_init_irq,
258 .init_rtc = common_init_rtc,
259 .init_pci = cia_init_pci,
260 .kill_arch = cia_kill_arch,
261 .pci_map_irq = mikasa_map_irq,
262 .pci_swizzle = common_swizzle,
263};
264ALIAS_MV(mikasa_primo)
265#endif
diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
new file mode 100644
index 000000000000..c0d696efec5b
--- /dev/null
+++ b/arch/alpha/kernel/sys_nautilus.c
@@ -0,0 +1,269 @@
1/*
2 * linux/arch/alpha/kernel/sys_nautilus.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1998 Richard Henderson
6 * Copyright (C) 1999 Alpha Processor, Inc.,
7 * (David Daniel, Stig Telfer, Soohoon Lee)
8 *
9 * Code supporting NAUTILUS systems.
10 *
11 *
12 * NAUTILUS has the following I/O features:
13 *
14 * a) Driven by AMD 751 aka IRONGATE (northbridge):
15 * 4 PCI slots
16 * 1 AGP slot
17 *
18 * b) Driven by ALI M1543C (southbridge)
19 * 2 ISA slots
20 * 2 IDE connectors
21 * 1 dual drive capable FDD controller
22 * 2 serial ports
23 * 1 ECP/EPP/SP parallel port
24 * 2 USB ports
25 */
26
27#include <linux/kernel.h>
28#include <linux/types.h>
29#include <linux/mm.h>
30#include <linux/sched.h>
31#include <linux/pci.h>
32#include <linux/init.h>
33#include <linux/reboot.h>
34#include <linux/bootmem.h>
35#include <linux/bitops.h>
36
37#include <asm/ptrace.h>
38#include <asm/system.h>
39#include <asm/dma.h>
40#include <asm/irq.h>
41#include <asm/mmu_context.h>
42#include <asm/io.h>
43#include <asm/pci.h>
44#include <asm/pgtable.h>
45#include <asm/core_irongate.h>
46#include <asm/hwrpb.h>
47#include <asm/tlbflush.h>
48
49#include "proto.h"
50#include "err_impl.h"
51#include "irq_impl.h"
52#include "pci_impl.h"
53#include "machvec_impl.h"
54
55
56static void __init
57nautilus_init_irq(void)
58{
59 if (alpha_using_srm) {
60 alpha_mv.device_interrupt = srm_device_interrupt;
61 }
62
63 init_i8259a_irqs();
64 common_init_isa_dma();
65}
66
67static int __init
68nautilus_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
69{
70 /* Preserve the IRQ set up by the console. */
71
72 u8 irq;
73 pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
74 return irq;
75}
76
77void
78nautilus_kill_arch(int mode)
79{
80 struct pci_bus *bus = pci_isa_hose->bus;
81 u32 pmuport;
82 int off;
83
84 switch (mode) {
85 case LINUX_REBOOT_CMD_RESTART:
86 if (! alpha_using_srm) {
87 u8 t8;
88 pci_bus_read_config_byte(bus, 0x38, 0x43, &t8);
89 pci_bus_write_config_byte(bus, 0x38, 0x43, t8 | 0x80);
90 outb(1, 0x92);
91 outb(0, 0x92);
92 /* NOTREACHED */
93 }
94 break;
95
96 case LINUX_REBOOT_CMD_POWER_OFF:
97 /* Assume M1543C */
98 off = 0x2000; /* SLP_TYPE = 0, SLP_EN = 1 */
99 pci_bus_read_config_dword(bus, 0x88, 0x10, &pmuport);
100 if (!pmuport) {
101 /* M1535D/D+ */
102 off = 0x3400; /* SLP_TYPE = 5, SLP_EN = 1 */
103 pci_bus_read_config_dword(bus, 0x88, 0xe0, &pmuport);
104 }
105 pmuport &= 0xfffe;
106 outw(0xffff, pmuport); /* Clear pending events. */
107 outw(off, pmuport + 4);
108 /* NOTREACHED */
109 break;
110 }
111}
112
113/* Perform analysis of a machine check that arrived from the system (NMI) */
114
115static void
116naut_sys_machine_check(unsigned long vector, unsigned long la_ptr,
117 struct pt_regs *regs)
118{
119 printk("PC %lx RA %lx\n", regs->pc, regs->r26);
120 irongate_pci_clr_err();
121}
122
123/* Machine checks can come from two sources - those on the CPU and those
124 in the system. They are analysed separately but all starts here. */
125
126void
127nautilus_machine_check(unsigned long vector, unsigned long la_ptr,
128 struct pt_regs *regs)
129{
130 char *mchk_class;
131
132 /* Now for some analysis. Machine checks fall into two classes --
133 those picked up by the system, and those picked up by the CPU.
134 Add to that the two levels of severity - correctable or not. */
135
136 if (vector == SCB_Q_SYSMCHK
137 && ((IRONGATE0->dramms & 0x300) == 0x300)) {
138 unsigned long nmi_ctl;
139
140 /* Clear ALI NMI */
141 nmi_ctl = inb(0x61);
142 nmi_ctl |= 0x0c;
143 outb(nmi_ctl, 0x61);
144 nmi_ctl &= ~0x0c;
145 outb(nmi_ctl, 0x61);
146
147 /* Write again clears error bits. */
148 IRONGATE0->stat_cmd = IRONGATE0->stat_cmd & ~0x100;
149 mb();
150 IRONGATE0->stat_cmd;
151
152 /* Write again clears error bits. */
153 IRONGATE0->dramms = IRONGATE0->dramms;
154 mb();
155 IRONGATE0->dramms;
156
157 draina();
158 wrmces(0x7);
159 mb();
160 return;
161 }
162
163 if (vector == SCB_Q_SYSERR)
164 mchk_class = "Correctable";
165 else if (vector == SCB_Q_SYSMCHK)
166 mchk_class = "Fatal";
167 else {
168 ev6_machine_check(vector, la_ptr, regs);
169 return;
170 }
171
172 printk(KERN_CRIT "NAUTILUS Machine check 0x%lx "
173 "[%s System Machine Check (NMI)]\n",
174 vector, mchk_class);
175
176 naut_sys_machine_check(vector, la_ptr, regs);
177
178 /* Tell the PALcode to clear the machine check */
179 draina();
180 wrmces(0x7);
181 mb();
182}
183
184extern void free_reserved_mem(void *, void *);
185
186static struct resource irongate_mem = {
187 .name = "Irongate PCI MEM",
188 .flags = IORESOURCE_MEM,
189};
190
191void __init
192nautilus_init_pci(void)
193{
194 struct pci_controller *hose = hose_head;
195 struct pci_bus *bus;
196 struct pci_dev *irongate;
197 unsigned long bus_align, bus_size, pci_mem;
198 unsigned long memtop = max_low_pfn << PAGE_SHIFT;
199
200 /* Scan our single hose. */
201 bus = pci_scan_bus(0, alpha_mv.pci_ops, hose);
202 hose->bus = bus;
203
204 irongate = pci_find_slot(0, 0);
205 bus->self = irongate;
206 bus->resource[1] = &irongate_mem;
207
208 pci_bus_size_bridges(bus);
209
210 /* IO port range. */
211 bus->resource[0]->start = 0;
212 bus->resource[0]->end = 0xffff;
213
214 /* Set up PCI memory range - limit is hardwired to 0xffffffff,
215 base must be at aligned to 16Mb. */
216 bus_align = bus->resource[1]->start;
217 bus_size = bus->resource[1]->end + 1 - bus_align;
218 if (bus_align < 0x1000000UL)
219 bus_align = 0x1000000UL;
220
221 pci_mem = (0x100000000UL - bus_size) & -bus_align;
222
223 bus->resource[1]->start = pci_mem;
224 bus->resource[1]->end = 0xffffffffUL;
225 if (request_resource(&iomem_resource, bus->resource[1]) < 0)
226 printk(KERN_ERR "Failed to request MEM on hose 0\n");
227
228 if (pci_mem < memtop)
229 memtop = pci_mem;
230 if (memtop > alpha_mv.min_mem_address) {
231 free_reserved_mem(__va(alpha_mv.min_mem_address),
232 __va(memtop));
233 printk("nautilus_init_pci: %ldk freed\n",
234 (memtop - alpha_mv.min_mem_address) >> 10);
235 }
236
237 if ((IRONGATE0->dev_vendor >> 16) > 0x7006) /* Albacore? */
238 IRONGATE0->pci_mem = pci_mem;
239
240 pci_bus_assign_resources(bus);
241 pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
242}
243
244/*
245 * The System Vectors
246 */
247
248struct alpha_machine_vector nautilus_mv __initmv = {
249 .vector_name = "Nautilus",
250 DO_EV6_MMU,
251 DO_DEFAULT_RTC,
252 DO_IRONGATE_IO,
253 .machine_check = nautilus_machine_check,
254 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
255 .min_io_address = DEFAULT_IO_BASE,
256 .min_mem_address = IRONGATE_DEFAULT_MEM_BASE,
257
258 .nr_irqs = 16,
259 .device_interrupt = isa_device_interrupt,
260
261 .init_arch = irongate_init_arch,
262 .init_irq = nautilus_init_irq,
263 .init_rtc = common_init_rtc,
264 .init_pci = nautilus_init_pci,
265 .kill_arch = nautilus_kill_arch,
266 .pci_map_irq = nautilus_map_irq,
267 .pci_swizzle = common_swizzle,
268};
269ALIAS_MV(nautilus)
diff --git a/arch/alpha/kernel/sys_noritake.c b/arch/alpha/kernel/sys_noritake.c
new file mode 100644
index 000000000000..65061f5d7410
--- /dev/null
+++ b/arch/alpha/kernel/sys_noritake.c
@@ -0,0 +1,347 @@
1/*
2 * linux/arch/alpha/kernel/sys_noritake.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996 Jay A Estabrook
6 * Copyright (C) 1998, 1999 Richard Henderson
7 *
8 * Code supporting the NORITAKE (AlphaServer 1000A),
9 * CORELLE (AlphaServer 800), and ALCOR Primo (AlphaStation 600A).
10 */
11
12#include <linux/config.h>
13#include <linux/kernel.h>
14#include <linux/types.h>
15#include <linux/mm.h>
16#include <linux/sched.h>
17#include <linux/pci.h>
18#include <linux/init.h>
19#include <linux/bitops.h>
20
21#include <asm/ptrace.h>
22#include <asm/system.h>
23#include <asm/dma.h>
24#include <asm/irq.h>
25#include <asm/mmu_context.h>
26#include <asm/io.h>
27#include <asm/pgtable.h>
28#include <asm/core_apecs.h>
29#include <asm/core_cia.h>
30#include <asm/tlbflush.h>
31
32#include "proto.h"
33#include "irq_impl.h"
34#include "pci_impl.h"
35#include "machvec_impl.h"
36
37/* Note mask bit is true for ENABLED irqs. */
38static int cached_irq_mask;
39
40static inline void
41noritake_update_irq_hw(int irq, int mask)
42{
43 int port = 0x54a;
44 if (irq >= 32) {
45 mask >>= 16;
46 port = 0x54c;
47 }
48 outw(mask, port);
49}
50
51static void
52noritake_enable_irq(unsigned int irq)
53{
54 noritake_update_irq_hw(irq, cached_irq_mask |= 1 << (irq - 16));
55}
56
57static void
58noritake_disable_irq(unsigned int irq)
59{
60 noritake_update_irq_hw(irq, cached_irq_mask &= ~(1 << (irq - 16)));
61}
62
63static unsigned int
64noritake_startup_irq(unsigned int irq)
65{
66 noritake_enable_irq(irq);
67 return 0;
68}
69
70static struct hw_interrupt_type noritake_irq_type = {
71 .typename = "NORITAKE",
72 .startup = noritake_startup_irq,
73 .shutdown = noritake_disable_irq,
74 .enable = noritake_enable_irq,
75 .disable = noritake_disable_irq,
76 .ack = noritake_disable_irq,
77 .end = noritake_enable_irq,
78};
79
80static void
81noritake_device_interrupt(unsigned long vector, struct pt_regs *regs)
82{
83 unsigned long pld;
84 unsigned int i;
85
86 /* Read the interrupt summary registers of NORITAKE */
87 pld = (((unsigned long) inw(0x54c) << 32)
88 | ((unsigned long) inw(0x54a) << 16)
89 | ((unsigned long) inb(0xa0) << 8)
90 | inb(0x20));
91
92 /*
93 * Now for every possible bit set, work through them and call
94 * the appropriate interrupt handler.
95 */
96 while (pld) {
97 i = ffz(~pld);
98 pld &= pld - 1; /* clear least bit set */
99 if (i < 16) {
100 isa_device_interrupt(vector, regs);
101 } else {
102 handle_irq(i, regs);
103 }
104 }
105}
106
107static void
108noritake_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
109{
110 int irq;
111
112 irq = (vector - 0x800) >> 4;
113
114 /*
115 * I really hate to do this, too, but the NORITAKE SRM console also
116 * reports PCI vectors *lower* than I expected from the bit numbers
117 * in the documentation.
118 * But I really don't want to change the fixup code for allocation
119 * of IRQs, nor the alpha_irq_mask maintenance stuff, both of which
120 * look nice and clean now.
121 * So, here's this additional grotty hack... :-(
122 */
123 if (irq >= 16)
124 irq = irq + 1;
125
126 handle_irq(irq, regs);
127}
128
129static void __init
130noritake_init_irq(void)
131{
132 long i;
133
134 if (alpha_using_srm)
135 alpha_mv.device_interrupt = noritake_srm_device_interrupt;
136
137 outw(0, 0x54a);
138 outw(0, 0x54c);
139
140 for (i = 16; i < 48; ++i) {
141 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
142 irq_desc[i].handler = &noritake_irq_type;
143 }
144
145 init_i8259a_irqs();
146 common_init_isa_dma();
147}
148
149
150/*
151 * PCI Fixup configuration.
152 *
153 * Summary @ 0x542, summary register #1:
154 * Bit Meaning
155 * 0 All valid ints from summary regs 2 & 3
156 * 1 QLOGIC ISP1020A SCSI
157 * 2 Interrupt Line A from slot 0
158 * 3 Interrupt Line B from slot 0
159 * 4 Interrupt Line A from slot 1
160 * 5 Interrupt line B from slot 1
161 * 6 Interrupt Line A from slot 2
162 * 7 Interrupt Line B from slot 2
163 * 8 Interrupt Line A from slot 3
164 * 9 Interrupt Line B from slot 3
165 *10 Interrupt Line A from slot 4
166 *11 Interrupt Line B from slot 4
167 *12 Interrupt Line A from slot 5
168 *13 Interrupt Line B from slot 5
169 *14 Interrupt Line A from slot 6
170 *15 Interrupt Line B from slot 6
171 *
172 * Summary @ 0x544, summary register #2:
173 * Bit Meaning
174 * 0 OR of all unmasked ints in SR #2
175 * 1 OR of secondary bus ints
176 * 2 Interrupt Line C from slot 0
177 * 3 Interrupt Line D from slot 0
178 * 4 Interrupt Line C from slot 1
179 * 5 Interrupt line D from slot 1
180 * 6 Interrupt Line C from slot 2
181 * 7 Interrupt Line D from slot 2
182 * 8 Interrupt Line C from slot 3
183 * 9 Interrupt Line D from slot 3
184 *10 Interrupt Line C from slot 4
185 *11 Interrupt Line D from slot 4
186 *12 Interrupt Line C from slot 5
187 *13 Interrupt Line D from slot 5
188 *14 Interrupt Line C from slot 6
189 *15 Interrupt Line D from slot 6
190 *
191 * The device to slot mapping looks like:
192 *
193 * Slot Device
194 * 7 Intel PCI-EISA bridge chip
195 * 8 DEC PCI-PCI bridge chip
196 * 11 PCI on board slot 0
197 * 12 PCI on board slot 1
198 * 13 PCI on board slot 2
199 *
200 *
201 * This two layered interrupt approach means that we allocate IRQ 16 and
202 * above for PCI interrupts. The IRQ relates to which bit the interrupt
203 * comes in on. This makes interrupt processing much easier.
204 */
205
206static int __init
207noritake_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
208{
209 static char irq_tab[15][5] __initdata = {
210 /*INT INTA INTB INTC INTD */
211 /* note: IDSELs 16, 17, and 25 are CORELLE only */
212 { 16+1, 16+1, 16+1, 16+1, 16+1}, /* IdSel 16, QLOGIC */
213 { -1, -1, -1, -1, -1}, /* IdSel 17, S3 Trio64 */
214 { -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */
215 { -1, -1, -1, -1, -1}, /* IdSel 19, PPB */
216 { -1, -1, -1, -1, -1}, /* IdSel 20, ???? */
217 { -1, -1, -1, -1, -1}, /* IdSel 21, ???? */
218 { 16+2, 16+2, 16+3, 32+2, 32+3}, /* IdSel 22, slot 0 */
219 { 16+4, 16+4, 16+5, 32+4, 32+5}, /* IdSel 23, slot 1 */
220 { 16+6, 16+6, 16+7, 32+6, 32+7}, /* IdSel 24, slot 2 */
221 { 16+8, 16+8, 16+9, 32+8, 32+9}, /* IdSel 25, slot 3 */
222 /* The following 5 are actually on PCI bus 1, which is
223 across the built-in bridge of the NORITAKE only. */
224 { 16+1, 16+1, 16+1, 16+1, 16+1}, /* IdSel 16, QLOGIC */
225 { 16+8, 16+8, 16+9, 32+8, 32+9}, /* IdSel 17, slot 3 */
226 {16+10, 16+10, 16+11, 32+10, 32+11}, /* IdSel 18, slot 4 */
227 {16+12, 16+12, 16+13, 32+12, 32+13}, /* IdSel 19, slot 5 */
228 {16+14, 16+14, 16+15, 32+14, 32+15}, /* IdSel 20, slot 6 */
229 };
230 const long min_idsel = 5, max_idsel = 19, irqs_per_slot = 5;
231 return COMMON_TABLE_LOOKUP;
232}
233
234static u8 __init
235noritake_swizzle(struct pci_dev *dev, u8 *pinp)
236{
237 int slot, pin = *pinp;
238
239 if (dev->bus->number == 0) {
240 slot = PCI_SLOT(dev->devfn);
241 }
242 /* Check for the built-in bridge */
243 else if (PCI_SLOT(dev->bus->self->devfn) == 8) {
244 slot = PCI_SLOT(dev->devfn) + 15; /* WAG! */
245 }
246 else
247 {
248 /* Must be a card-based bridge. */
249 do {
250 if (PCI_SLOT(dev->bus->self->devfn) == 8) {
251 slot = PCI_SLOT(dev->devfn) + 15;
252 break;
253 }
254 pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)) ;
255
256 /* Move up the chain of bridges. */
257 dev = dev->bus->self;
258 /* Slot of the next bridge. */
259 slot = PCI_SLOT(dev->devfn);
260 } while (dev->bus->self);
261 }
262 *pinp = pin;
263 return slot;
264}
265
266#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
267static void
268noritake_apecs_machine_check(unsigned long vector, unsigned long la_ptr,
269 struct pt_regs * regs)
270{
271#define MCHK_NO_DEVSEL 0x205U
272#define MCHK_NO_TABT 0x204U
273
274 struct el_common *mchk_header;
275 unsigned int code;
276
277 mchk_header = (struct el_common *)la_ptr;
278
279 /* Clear the error before any reporting. */
280 mb();
281 mb(); /* magic */
282 draina();
283 apecs_pci_clr_err();
284 wrmces(0x7);
285 mb();
286
287 code = mchk_header->code;
288 process_mcheck_info(vector, la_ptr, regs, "NORITAKE APECS",
289 (mcheck_expected(0)
290 && (code == MCHK_NO_DEVSEL
291 || code == MCHK_NO_TABT)));
292}
293#endif
294
295
296/*
297 * The System Vectors
298 */
299
300#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
301struct alpha_machine_vector noritake_mv __initmv = {
302 .vector_name = "Noritake",
303 DO_EV4_MMU,
304 DO_DEFAULT_RTC,
305 DO_APECS_IO,
306 .machine_check = noritake_apecs_machine_check,
307 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
308 .min_io_address = EISA_DEFAULT_IO_BASE,
309 .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE,
310
311 .nr_irqs = 48,
312 .device_interrupt = noritake_device_interrupt,
313
314 .init_arch = apecs_init_arch,
315 .init_irq = noritake_init_irq,
316 .init_rtc = common_init_rtc,
317 .init_pci = common_init_pci,
318 .pci_map_irq = noritake_map_irq,
319 .pci_swizzle = noritake_swizzle,
320};
321ALIAS_MV(noritake)
322#endif
323
324#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PRIMO)
325struct alpha_machine_vector noritake_primo_mv __initmv = {
326 .vector_name = "Noritake-Primo",
327 DO_EV5_MMU,
328 DO_DEFAULT_RTC,
329 DO_CIA_IO,
330 .machine_check = cia_machine_check,
331 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
332 .min_io_address = EISA_DEFAULT_IO_BASE,
333 .min_mem_address = CIA_DEFAULT_MEM_BASE,
334
335 .nr_irqs = 48,
336 .device_interrupt = noritake_device_interrupt,
337
338 .init_arch = cia_init_arch,
339 .init_irq = noritake_init_irq,
340 .init_rtc = common_init_rtc,
341 .init_pci = cia_init_pci,
342 .kill_arch = cia_kill_arch,
343 .pci_map_irq = noritake_map_irq,
344 .pci_swizzle = noritake_swizzle,
345};
346ALIAS_MV(noritake_primo)
347#endif
diff --git a/arch/alpha/kernel/sys_rawhide.c b/arch/alpha/kernel/sys_rawhide.c
new file mode 100644
index 000000000000..05888a02a604
--- /dev/null
+++ b/arch/alpha/kernel/sys_rawhide.c
@@ -0,0 +1,270 @@
1/*
2 * linux/arch/alpha/kernel/sys_rawhide.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996 Jay A Estabrook
6 * Copyright (C) 1998, 1999 Richard Henderson
7 *
8 * Code supporting the RAWHIDE.
9 */
10
11#include <linux/kernel.h>
12#include <linux/types.h>
13#include <linux/mm.h>
14#include <linux/sched.h>
15#include <linux/pci.h>
16#include <linux/init.h>
17
18#include <asm/ptrace.h>
19#include <asm/system.h>
20#include <asm/dma.h>
21#include <asm/irq.h>
22#include <asm/mmu_context.h>
23#include <asm/io.h>
24#include <asm/pgtable.h>
25#include <asm/core_mcpcia.h>
26#include <asm/tlbflush.h>
27
28#include "proto.h"
29#include "irq_impl.h"
30#include "pci_impl.h"
31#include "machvec_impl.h"
32
33
34/*
35 * HACK ALERT! only the boot cpu is used for interrupts.
36 */
37
38
39/* Note mask bit is true for ENABLED irqs. */
40
41static unsigned int hose_irq_masks[4] = {
42 0xff0000, 0xfe0000, 0xff0000, 0xff0000
43};
44static unsigned int cached_irq_masks[4];
45DEFINE_SPINLOCK(rawhide_irq_lock);
46
47static inline void
48rawhide_update_irq_hw(int hose, int mask)
49{
50 *(vuip)MCPCIA_INT_MASK0(MCPCIA_HOSE2MID(hose)) = mask;
51 mb();
52 *(vuip)MCPCIA_INT_MASK0(MCPCIA_HOSE2MID(hose));
53}
54
55static inline void
56rawhide_enable_irq(unsigned int irq)
57{
58 unsigned int mask, hose;
59
60 irq -= 16;
61 hose = irq / 24;
62 irq -= hose * 24;
63 mask = 1 << irq;
64
65 spin_lock(&rawhide_irq_lock);
66 mask |= cached_irq_masks[hose];
67 cached_irq_masks[hose] = mask;
68 rawhide_update_irq_hw(hose, mask);
69 spin_unlock(&rawhide_irq_lock);
70}
71
72static void
73rawhide_disable_irq(unsigned int irq)
74{
75 unsigned int mask, hose;
76
77 irq -= 16;
78 hose = irq / 24;
79 irq -= hose * 24;
80 mask = ~(1 << irq) | hose_irq_masks[hose];
81
82 spin_lock(&rawhide_irq_lock);
83 mask &= cached_irq_masks[hose];
84 cached_irq_masks[hose] = mask;
85 rawhide_update_irq_hw(hose, mask);
86 spin_unlock(&rawhide_irq_lock);
87}
88
89static void
90rawhide_mask_and_ack_irq(unsigned int irq)
91{
92 unsigned int mask, mask1, hose;
93
94 irq -= 16;
95 hose = irq / 24;
96 irq -= hose * 24;
97 mask1 = 1 << irq;
98 mask = ~mask1 | hose_irq_masks[hose];
99
100 spin_lock(&rawhide_irq_lock);
101
102 mask &= cached_irq_masks[hose];
103 cached_irq_masks[hose] = mask;
104 rawhide_update_irq_hw(hose, mask);
105
106 /* Clear the interrupt. */
107 *(vuip)MCPCIA_INT_REQ(MCPCIA_HOSE2MID(hose)) = mask1;
108
109 spin_unlock(&rawhide_irq_lock);
110}
111
112static unsigned int
113rawhide_startup_irq(unsigned int irq)
114{
115 rawhide_enable_irq(irq);
116 return 0;
117}
118
119static void
120rawhide_end_irq(unsigned int irq)
121{
122 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
123 rawhide_enable_irq(irq);
124}
125
126static struct hw_interrupt_type rawhide_irq_type = {
127 .typename = "RAWHIDE",
128 .startup = rawhide_startup_irq,
129 .shutdown = rawhide_disable_irq,
130 .enable = rawhide_enable_irq,
131 .disable = rawhide_disable_irq,
132 .ack = rawhide_mask_and_ack_irq,
133 .end = rawhide_end_irq,
134};
135
136static void
137rawhide_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
138{
139 int irq;
140
141 irq = (vector - 0x800) >> 4;
142
143 /*
144 * The RAWHIDE SRM console reports PCI interrupts with a vector
145 * 0x80 *higher* than one might expect, as PCI IRQ 0 (ie bit 0)
146 * shows up as IRQ 24, etc, etc. We adjust it down by 8 to have
147 * it line up with the actual bit numbers from the REQ registers,
148 * which is how we manage the interrupts/mask. Sigh...
149 *
150 * Also, PCI #1 interrupts are offset some more... :-(
151 */
152
153 if (irq == 52) {
154 /* SCSI on PCI1 is special. */
155 irq = 72;
156 }
157
158 /* Adjust by which hose it is from. */
159 irq -= ((irq + 16) >> 2) & 0x38;
160
161 handle_irq(irq, regs);
162}
163
164static void __init
165rawhide_init_irq(void)
166{
167 struct pci_controller *hose;
168 long i;
169
170 mcpcia_init_hoses();
171
172 for (hose = hose_head; hose; hose = hose->next) {
173 unsigned int h = hose->index;
174 unsigned int mask = hose_irq_masks[h];
175
176 cached_irq_masks[h] = mask;
177 *(vuip)MCPCIA_INT_MASK0(MCPCIA_HOSE2MID(h)) = mask;
178 *(vuip)MCPCIA_INT_MASK1(MCPCIA_HOSE2MID(h)) = 0;
179 }
180
181 for (i = 16; i < 128; ++i) {
182 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
183 irq_desc[i].handler = &rawhide_irq_type;
184 }
185
186 init_i8259a_irqs();
187 common_init_isa_dma();
188}
189
190/*
191 * PCI Fixup configuration.
192 *
193 * Summary @ MCPCIA_PCI0_INT_REQ:
194 * Bit Meaning
195 * 0 Interrupt Line A from slot 2 PCI0
196 * 1 Interrupt Line B from slot 2 PCI0
197 * 2 Interrupt Line C from slot 2 PCI0
198 * 3 Interrupt Line D from slot 2 PCI0
199 * 4 Interrupt Line A from slot 3 PCI0
200 * 5 Interrupt Line B from slot 3 PCI0
201 * 6 Interrupt Line C from slot 3 PCI0
202 * 7 Interrupt Line D from slot 3 PCI0
203 * 8 Interrupt Line A from slot 4 PCI0
204 * 9 Interrupt Line B from slot 4 PCI0
205 * 10 Interrupt Line C from slot 4 PCI0
206 * 11 Interrupt Line D from slot 4 PCI0
207 * 12 Interrupt Line A from slot 5 PCI0
208 * 13 Interrupt Line B from slot 5 PCI0
209 * 14 Interrupt Line C from slot 5 PCI0
210 * 15 Interrupt Line D from slot 5 PCI0
211 * 16 EISA interrupt (PCI 0) or SCSI interrupt (PCI 1)
212 * 17-23 NA
213 *
214 * IdSel
215 * 1 EISA bridge (PCI bus 0 only)
216 * 2 PCI option slot 2
217 * 3 PCI option slot 3
218 * 4 PCI option slot 4
219 * 5 PCI option slot 5
220 *
221 */
222
223static int __init
224rawhide_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
225{
226 static char irq_tab[5][5] __initdata = {
227 /*INT INTA INTB INTC INTD */
228 { 16+16, 16+16, 16+16, 16+16, 16+16}, /* IdSel 1 SCSI PCI 1 */
229 { 16+ 0, 16+ 0, 16+ 1, 16+ 2, 16+ 3}, /* IdSel 2 slot 2 */
230 { 16+ 4, 16+ 4, 16+ 5, 16+ 6, 16+ 7}, /* IdSel 3 slot 3 */
231 { 16+ 8, 16+ 8, 16+ 9, 16+10, 16+11}, /* IdSel 4 slot 4 */
232 { 16+12, 16+12, 16+13, 16+14, 16+15} /* IdSel 5 slot 5 */
233 };
234 const long min_idsel = 1, max_idsel = 5, irqs_per_slot = 5;
235
236 struct pci_controller *hose = dev->sysdata;
237 int irq = COMMON_TABLE_LOOKUP;
238 if (irq >= 0)
239 irq += 24 * hose->index;
240 return irq;
241}
242
243
244/*
245 * The System Vector
246 */
247
248struct alpha_machine_vector rawhide_mv __initmv = {
249 .vector_name = "Rawhide",
250 DO_EV5_MMU,
251 DO_DEFAULT_RTC,
252 DO_MCPCIA_IO,
253 .machine_check = mcpcia_machine_check,
254 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
255 .min_io_address = DEFAULT_IO_BASE,
256 .min_mem_address = MCPCIA_DEFAULT_MEM_BASE,
257 .pci_dac_offset = MCPCIA_DAC_OFFSET,
258
259 .nr_irqs = 128,
260 .device_interrupt = rawhide_srm_device_interrupt,
261
262 .init_arch = mcpcia_init_arch,
263 .init_irq = rawhide_init_irq,
264 .init_rtc = common_init_rtc,
265 .init_pci = common_init_pci,
266 .kill_arch = NULL,
267 .pci_map_irq = rawhide_map_irq,
268 .pci_swizzle = common_swizzle,
269};
270ALIAS_MV(rawhide)
diff --git a/arch/alpha/kernel/sys_ruffian.c b/arch/alpha/kernel/sys_ruffian.c
new file mode 100644
index 000000000000..78c30decf3ff
--- /dev/null
+++ b/arch/alpha/kernel/sys_ruffian.c
@@ -0,0 +1,240 @@
1/*
2 * linux/arch/alpha/kernel/sys_ruffian.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996 Jay A Estabrook
6 * Copyright (C) 1998, 1999, 2000 Richard Henderson
7 *
8 * Code supporting the RUFFIAN.
9 */
10
11#include <linux/kernel.h>
12#include <linux/types.h>
13#include <linux/mm.h>
14#include <linux/sched.h>
15#include <linux/pci.h>
16#include <linux/ioport.h>
17#include <linux/init.h>
18
19#include <asm/ptrace.h>
20#include <asm/system.h>
21#include <asm/dma.h>
22#include <asm/irq.h>
23#include <asm/mmu_context.h>
24#include <asm/io.h>
25#include <asm/pgtable.h>
26#include <asm/core_cia.h>
27#include <asm/tlbflush.h>
28#include <asm/8253pit.h>
29
30#include "proto.h"
31#include "irq_impl.h"
32#include "pci_impl.h"
33#include "machvec_impl.h"
34
35
36static void __init
37ruffian_init_irq(void)
38{
39 /* Invert 6&7 for i82371 */
40 *(vulp)PYXIS_INT_HILO = 0x000000c0UL; mb();
41 *(vulp)PYXIS_INT_CNFG = 0x00002064UL; mb(); /* all clear */
42
43 outb(0x11,0xA0);
44 outb(0x08,0xA1);
45 outb(0x02,0xA1);
46 outb(0x01,0xA1);
47 outb(0xFF,0xA1);
48
49 outb(0x11,0x20);
50 outb(0x00,0x21);
51 outb(0x04,0x21);
52 outb(0x01,0x21);
53 outb(0xFF,0x21);
54
55 /* Finish writing the 82C59A PIC Operation Control Words */
56 outb(0x20,0xA0);
57 outb(0x20,0x20);
58
59 init_i8259a_irqs();
60
61 /* Not interested in the bogus interrupts (0,3,6),
62 NMI (1), HALT (2), flash (5), or 21142 (8). */
63 init_pyxis_irqs(0x16f0000);
64
65 common_init_isa_dma();
66}
67
68#define RUFFIAN_LATCH ((PIT_TICK_RATE + HZ / 2) / HZ)
69
70static void __init
71ruffian_init_rtc(void)
72{
73 /* Ruffian does not have the RTC connected to the CPU timer
74 interrupt. Instead, it uses the PIT connected to IRQ 0. */
75
76 /* Setup interval timer. */
77 outb(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */
78 outb(RUFFIAN_LATCH & 0xff, 0x40); /* LSB */
79 outb(RUFFIAN_LATCH >> 8, 0x40); /* MSB */
80
81 outb(0xb6, 0x43); /* pit counter 2: speaker */
82 outb(0x31, 0x42);
83 outb(0x13, 0x42);
84
85 setup_irq(0, &timer_irqaction);
86}
87
88static void
89ruffian_kill_arch (int mode)
90{
91 cia_kill_arch(mode);
92#if 0
93 /* This only causes re-entry to ARCSBIOS */
94 /* Perhaps this works for other PYXIS as well? */
95 *(vuip) PYXIS_RESET = 0x0000dead;
96 mb();
97#endif
98}
99
100/*
101 * Interrupt routing:
102 *
103 * Primary bus
104 * IdSel INTA INTB INTC INTD
105 * 21052 13 - - - -
106 * SIO 14 23 - - -
107 * 21143 15 44 - - -
108 * Slot 0 17 43 42 41 40
109 *
110 * Secondary bus
111 * IdSel INTA INTB INTC INTD
112 * Slot 0 8 (18) 19 18 17 16
113 * Slot 1 9 (19) 31 30 29 28
114 * Slot 2 10 (20) 27 26 25 24
115 * Slot 3 11 (21) 39 38 37 36
116 * Slot 4 12 (22) 35 34 33 32
117 * 53c875 13 (23) 20 - - -
118 *
119 */
120
121static int __init
122ruffian_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
123{
124 static char irq_tab[11][5] __initdata = {
125 /*INT INTA INTB INTC INTD */
126 {-1, -1, -1, -1, -1}, /* IdSel 13, 21052 */
127 {-1, -1, -1, -1, -1}, /* IdSel 14, SIO */
128 {44, 44, 44, 44, 44}, /* IdSel 15, 21143 */
129 {-1, -1, -1, -1, -1}, /* IdSel 16, none */
130 {43, 43, 42, 41, 40}, /* IdSel 17, 64-bit slot */
131 /* the next 6 are actually on PCI bus 1, across the bridge */
132 {19, 19, 18, 17, 16}, /* IdSel 8, slot 0 */
133 {31, 31, 30, 29, 28}, /* IdSel 9, slot 1 */
134 {27, 27, 26, 25, 24}, /* IdSel 10, slot 2 */
135 {39, 39, 38, 37, 36}, /* IdSel 11, slot 3 */
136 {35, 35, 34, 33, 32}, /* IdSel 12, slot 4 */
137 {20, 20, 20, 20, 20}, /* IdSel 13, 53c875 */
138 };
139 const long min_idsel = 13, max_idsel = 23, irqs_per_slot = 5;
140 return COMMON_TABLE_LOOKUP;
141}
142
143static u8 __init
144ruffian_swizzle(struct pci_dev *dev, u8 *pinp)
145{
146 int slot, pin = *pinp;
147
148 if (dev->bus->number == 0) {
149 slot = PCI_SLOT(dev->devfn);
150 }
151 /* Check for the built-in bridge. */
152 else if (PCI_SLOT(dev->bus->self->devfn) == 13) {
153 slot = PCI_SLOT(dev->devfn) + 10;
154 }
155 else
156 {
157 /* Must be a card-based bridge. */
158 do {
159 if (PCI_SLOT(dev->bus->self->devfn) == 13) {
160 slot = PCI_SLOT(dev->devfn) + 10;
161 break;
162 }
163 pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
164
165 /* Move up the chain of bridges. */
166 dev = dev->bus->self;
167 /* Slot of the next bridge. */
168 slot = PCI_SLOT(dev->devfn);
169 } while (dev->bus->self);
170 }
171 *pinp = pin;
172 return slot;
173}
174
175#ifdef BUILDING_FOR_MILO
176/*
177 * The DeskStation Ruffian motherboard firmware does not place
178 * the memory size in the PALimpure area. Therefore, we use
179 * the Bank Configuration Registers in PYXIS to obtain the size.
180 */
181static unsigned long __init
182ruffian_get_bank_size(unsigned long offset)
183{
184 unsigned long bank_addr, bank, ret = 0;
185
186 /* Valid offsets are: 0x800, 0x840 and 0x880
187 since Ruffian only uses three banks. */
188 bank_addr = (unsigned long)PYXIS_MCR + offset;
189 bank = *(vulp)bank_addr;
190
191 /* Check BANK_ENABLE */
192 if (bank & 0x01) {
193 static unsigned long size[] __initdata = {
194 0x40000000UL, /* 0x00, 1G */
195 0x20000000UL, /* 0x02, 512M */
196 0x10000000UL, /* 0x04, 256M */
197 0x08000000UL, /* 0x06, 128M */
198 0x04000000UL, /* 0x08, 64M */
199 0x02000000UL, /* 0x0a, 32M */
200 0x01000000UL, /* 0x0c, 16M */
201 0x00800000UL, /* 0x0e, 8M */
202 0x80000000UL, /* 0x10, 2G */
203 };
204
205 bank = (bank & 0x1e) >> 1;
206 if (bank < sizeof(size)/sizeof(*size))
207 ret = size[bank];
208 }
209
210 return ret;
211}
212#endif /* BUILDING_FOR_MILO */
213
214/*
215 * The System Vector
216 */
217
218struct alpha_machine_vector ruffian_mv __initmv = {
219 .vector_name = "Ruffian",
220 DO_EV5_MMU,
221 DO_DEFAULT_RTC,
222 DO_PYXIS_IO,
223 .machine_check = cia_machine_check,
224 .max_isa_dma_address = ALPHA_RUFFIAN_MAX_ISA_DMA_ADDRESS,
225 .min_io_address = DEFAULT_IO_BASE,
226 .min_mem_address = DEFAULT_MEM_BASE,
227 .pci_dac_offset = PYXIS_DAC_OFFSET,
228
229 .nr_irqs = 48,
230 .device_interrupt = pyxis_device_interrupt,
231
232 .init_arch = pyxis_init_arch,
233 .init_irq = ruffian_init_irq,
234 .init_rtc = ruffian_init_rtc,
235 .init_pci = cia_init_pci,
236 .kill_arch = ruffian_kill_arch,
237 .pci_map_irq = ruffian_map_irq,
238 .pci_swizzle = ruffian_swizzle,
239};
240ALIAS_MV(ruffian)
diff --git a/arch/alpha/kernel/sys_rx164.c b/arch/alpha/kernel/sys_rx164.c
new file mode 100644
index 000000000000..58404243057b
--- /dev/null
+++ b/arch/alpha/kernel/sys_rx164.c
@@ -0,0 +1,220 @@
1/*
2 * linux/arch/alpha/kernel/sys_rx164.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996 Jay A Estabrook
6 * Copyright (C) 1998, 1999 Richard Henderson
7 *
8 * Code supporting the RX164 (PCA56+POLARIS).
9 */
10
11#include <linux/kernel.h>
12#include <linux/types.h>
13#include <linux/mm.h>
14#include <linux/sched.h>
15#include <linux/pci.h>
16#include <linux/init.h>
17#include <linux/bitops.h>
18
19#include <asm/ptrace.h>
20#include <asm/system.h>
21#include <asm/dma.h>
22#include <asm/irq.h>
23#include <asm/mmu_context.h>
24#include <asm/io.h>
25#include <asm/pgtable.h>
26#include <asm/core_polaris.h>
27#include <asm/tlbflush.h>
28
29#include "proto.h"
30#include "irq_impl.h"
31#include "pci_impl.h"
32#include "machvec_impl.h"
33
34
35/* Note mask bit is true for ENABLED irqs. */
36static unsigned long cached_irq_mask;
37
38static inline void
39rx164_update_irq_hw(unsigned long mask)
40{
41 volatile unsigned int *irq_mask;
42
43 irq_mask = (void *)(POLARIS_DENSE_CONFIG_BASE + 0x74);
44 *irq_mask = mask;
45 mb();
46 *irq_mask;
47}
48
49static inline void
50rx164_enable_irq(unsigned int irq)
51{
52 rx164_update_irq_hw(cached_irq_mask |= 1UL << (irq - 16));
53}
54
55static void
56rx164_disable_irq(unsigned int irq)
57{
58 rx164_update_irq_hw(cached_irq_mask &= ~(1UL << (irq - 16)));
59}
60
61static unsigned int
62rx164_startup_irq(unsigned int irq)
63{
64 rx164_enable_irq(irq);
65 return 0;
66}
67
68static void
69rx164_end_irq(unsigned int irq)
70{
71 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
72 rx164_enable_irq(irq);
73}
74
75static struct hw_interrupt_type rx164_irq_type = {
76 .typename = "RX164",
77 .startup = rx164_startup_irq,
78 .shutdown = rx164_disable_irq,
79 .enable = rx164_enable_irq,
80 .disable = rx164_disable_irq,
81 .ack = rx164_disable_irq,
82 .end = rx164_end_irq,
83};
84
85static void
86rx164_device_interrupt(unsigned long vector, struct pt_regs *regs)
87{
88 unsigned long pld;
89 volatile unsigned int *dirr;
90 long i;
91
92 /* Read the interrupt summary register. On Polaris, this is
93 the DIRR register in PCI config space (offset 0x84). */
94 dirr = (void *)(POLARIS_DENSE_CONFIG_BASE + 0x84);
95 pld = *dirr;
96
97 /*
98 * Now for every possible bit set, work through them and call
99 * the appropriate interrupt handler.
100 */
101 while (pld) {
102 i = ffz(~pld);
103 pld &= pld - 1; /* clear least bit set */
104 if (i == 20) {
105 isa_no_iack_sc_device_interrupt(vector, regs);
106 } else {
107 handle_irq(16+i, regs);
108 }
109 }
110}
111
112static void __init
113rx164_init_irq(void)
114{
115 long i;
116
117 rx164_update_irq_hw(0);
118 for (i = 16; i < 40; ++i) {
119 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
120 irq_desc[i].handler = &rx164_irq_type;
121 }
122
123 init_i8259a_irqs();
124 common_init_isa_dma();
125
126 setup_irq(16+20, &isa_cascade_irqaction);
127}
128
129
130/*
131 * The RX164 changed its interrupt routing between pass1 and pass2...
132 *
133 * PASS1:
134 *
135 * Slot IDSEL INTA INTB INTC INTD
136 * 0 6 5 10 15 20
137 * 1 7 4 9 14 19
138 * 2 5 3 8 13 18
139 * 3 9 2 7 12 17
140 * 4 10 1 6 11 16
141 *
142 * PASS2:
143 * Slot IDSEL INTA INTB INTC INTD
144 * 0 5 1 7 12 17
145 * 1 6 2 8 13 18
146 * 2 8 3 9 14 19
147 * 3 9 4 10 15 20
148 * 4 10 5 11 16 6
149 *
150 */
151
152/*
153 * IdSel
154 * 5 32 bit PCI option slot 0
155 * 6 64 bit PCI option slot 1
156 * 7 PCI-ISA bridge
157 * 7 64 bit PCI option slot 2
158 * 9 32 bit PCI option slot 3
159 * 10 PCI-PCI bridge
160 *
161 */
162
163static int __init
164rx164_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
165{
166#if 0
167 static char irq_tab_pass1[6][5] __initdata = {
168 /*INT INTA INTB INTC INTD */
169 { 16+3, 16+3, 16+8, 16+13, 16+18}, /* IdSel 5, slot 2 */
170 { 16+5, 16+5, 16+10, 16+15, 16+20}, /* IdSel 6, slot 0 */
171 { 16+4, 16+4, 16+9, 16+14, 16+19}, /* IdSel 7, slot 1 */
172 { -1, -1, -1, -1, -1}, /* IdSel 8, PCI/ISA bridge */
173 { 16+2, 16+2, 16+7, 16+12, 16+17}, /* IdSel 9, slot 3 */
174 { 16+1, 16+1, 16+6, 16+11, 16+16}, /* IdSel 10, slot 4 */
175 };
176#else
177 static char irq_tab[6][5] __initdata = {
178 /*INT INTA INTB INTC INTD */
179 { 16+0, 16+0, 16+6, 16+11, 16+16}, /* IdSel 5, slot 0 */
180 { 16+1, 16+1, 16+7, 16+12, 16+17}, /* IdSel 6, slot 1 */
181 { -1, -1, -1, -1, -1}, /* IdSel 7, PCI/ISA bridge */
182 { 16+2, 16+2, 16+8, 16+13, 16+18}, /* IdSel 8, slot 2 */
183 { 16+3, 16+3, 16+9, 16+14, 16+19}, /* IdSel 9, slot 3 */
184 { 16+4, 16+4, 16+10, 16+15, 16+5}, /* IdSel 10, PCI-PCI */
185 };
186#endif
187 const long min_idsel = 5, max_idsel = 10, irqs_per_slot = 5;
188
189 /* JRP - Need to figure out how to distinguish pass1 from pass2,
190 and use the correct table. */
191 return COMMON_TABLE_LOOKUP;
192}
193
194
195/*
196 * The System Vector
197 */
198
199struct alpha_machine_vector rx164_mv __initmv = {
200 .vector_name = "RX164",
201 DO_EV5_MMU,
202 DO_DEFAULT_RTC,
203 DO_POLARIS_IO,
204 .machine_check = polaris_machine_check,
205 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
206 .min_io_address = DEFAULT_IO_BASE,
207 .min_mem_address = DEFAULT_MEM_BASE,
208
209 .nr_irqs = 40,
210 .device_interrupt = rx164_device_interrupt,
211
212 .init_arch = polaris_init_arch,
213 .init_irq = rx164_init_irq,
214 .init_rtc = common_init_rtc,
215 .init_pci = common_init_pci,
216 .kill_arch = NULL,
217 .pci_map_irq = rx164_map_irq,
218 .pci_swizzle = common_swizzle,
219};
220ALIAS_MV(rx164)
diff --git a/arch/alpha/kernel/sys_sable.c b/arch/alpha/kernel/sys_sable.c
new file mode 100644
index 000000000000..a7ff84474ace
--- /dev/null
+++ b/arch/alpha/kernel/sys_sable.c
@@ -0,0 +1,653 @@
1/*
2 * linux/arch/alpha/kernel/sys_sable.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996 Jay A Estabrook
6 * Copyright (C) 1998, 1999 Richard Henderson
7 *
8 * Code supporting the Sable, Sable-Gamma, and Lynx systems.
9 */
10
11#include <linux/config.h>
12#include <linux/kernel.h>
13#include <linux/types.h>
14#include <linux/mm.h>
15#include <linux/sched.h>
16#include <linux/pci.h>
17#include <linux/init.h>
18
19#include <asm/ptrace.h>
20#include <asm/system.h>
21#include <asm/dma.h>
22#include <asm/irq.h>
23#include <asm/mmu_context.h>
24#include <asm/io.h>
25#include <asm/pgtable.h>
26#include <asm/core_t2.h>
27#include <asm/tlbflush.h>
28
29#include "proto.h"
30#include "irq_impl.h"
31#include "pci_impl.h"
32#include "machvec_impl.h"
33
34DEFINE_SPINLOCK(sable_lynx_irq_lock);
35
36typedef struct irq_swizzle_struct
37{
38 char irq_to_mask[64];
39 char mask_to_irq[64];
40
41 /* Note mask bit is true for DISABLED irqs. */
42 unsigned long shadow_mask;
43
44 void (*update_irq_hw)(unsigned long bit, unsigned long mask);
45 void (*ack_irq_hw)(unsigned long bit);
46
47} irq_swizzle_t;
48
49static irq_swizzle_t *sable_lynx_irq_swizzle;
50
51static void sable_lynx_init_irq(int nr_irqs);
52
53#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SABLE)
54
55/***********************************************************************/
56/*
57 * For SABLE, which is really baroque, we manage 40 IRQ's, but the
58 * hardware really only supports 24, not via normal ISA PIC,
59 * but cascaded custom 8259's, etc.
60 * 0-7 (char at 536)
61 * 8-15 (char at 53a)
62 * 16-23 (char at 53c)
63 *
64 * Summary Registers (536/53a/53c):
65 *
66 * Bit Meaning Kernel IRQ
67 *------------------------------------------
68 * 0 PCI slot 0 34
69 * 1 NCR810 (builtin) 33
70 * 2 TULIP (builtin) 32
71 * 3 mouse 12
72 * 4 PCI slot 1 35
73 * 5 PCI slot 2 36
74 * 6 keyboard 1
75 * 7 floppy 6
76 * 8 COM2 3
77 * 9 parallel port 7
78 *10 EISA irq 3 -
79 *11 EISA irq 4 -
80 *12 EISA irq 5 5
81 *13 EISA irq 6 -
82 *14 EISA irq 7 -
83 *15 COM1 4
84 *16 EISA irq 9 9
85 *17 EISA irq 10 10
86 *18 EISA irq 11 11
87 *19 EISA irq 12 -
88 *20 EISA irq 13 -
89 *21 EISA irq 14 14
90 *22 NC 15
91 *23 IIC -
92 */
93
94static void
95sable_update_irq_hw(unsigned long bit, unsigned long mask)
96{
97 int port = 0x537;
98
99 if (bit >= 16) {
100 port = 0x53d;
101 mask >>= 16;
102 } else if (bit >= 8) {
103 port = 0x53b;
104 mask >>= 8;
105 }
106
107 outb(mask, port);
108}
109
110static void
111sable_ack_irq_hw(unsigned long bit)
112{
113 int port, val1, val2;
114
115 if (bit >= 16) {
116 port = 0x53c;
117 val1 = 0xE0 | (bit - 16);
118 val2 = 0xE0 | 4;
119 } else if (bit >= 8) {
120 port = 0x53a;
121 val1 = 0xE0 | (bit - 8);
122 val2 = 0xE0 | 3;
123 } else {
124 port = 0x536;
125 val1 = 0xE0 | (bit - 0);
126 val2 = 0xE0 | 1;
127 }
128
129 outb(val1, port); /* ack the slave */
130 outb(val2, 0x534); /* ack the master */
131}
132
133static irq_swizzle_t sable_irq_swizzle = {
134 {
135 -1, 6, -1, 8, 15, 12, 7, 9, /* pseudo PIC 0-7 */
136 -1, 16, 17, 18, 3, -1, 21, 22, /* pseudo PIC 8-15 */
137 -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 0-7 */
138 -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 8-15 */
139 2, 1, 0, 4, 5, -1, -1, -1, /* pseudo PCI */
140 -1, -1, -1, -1, -1, -1, -1, -1, /* */
141 -1, -1, -1, -1, -1, -1, -1, -1, /* */
142 -1, -1, -1, -1, -1, -1, -1, -1 /* */
143 },
144 {
145 34, 33, 32, 12, 35, 36, 1, 6, /* mask 0-7 */
146 3, 7, -1, -1, 5, -1, -1, 4, /* mask 8-15 */
147 9, 10, 11, -1, -1, 14, 15, -1, /* mask 16-23 */
148 -1, -1, -1, -1, -1, -1, -1, -1, /* */
149 -1, -1, -1, -1, -1, -1, -1, -1, /* */
150 -1, -1, -1, -1, -1, -1, -1, -1, /* */
151 -1, -1, -1, -1, -1, -1, -1, -1, /* */
152 -1, -1, -1, -1, -1, -1, -1, -1 /* */
153 },
154 -1,
155 sable_update_irq_hw,
156 sable_ack_irq_hw
157};
158
159static void __init
160sable_init_irq(void)
161{
162 outb(-1, 0x537); /* slave 0 */
163 outb(-1, 0x53b); /* slave 1 */
164 outb(-1, 0x53d); /* slave 2 */
165 outb(0x44, 0x535); /* enable cascades in master */
166
167 sable_lynx_irq_swizzle = &sable_irq_swizzle;
168 sable_lynx_init_irq(40);
169}
170
171/*
172 * PCI Fixup configuration for ALPHA SABLE (2100).
173 *
174 * The device to slot mapping looks like:
175 *
176 * Slot Device
177 * 0 TULIP
178 * 1 SCSI
179 * 2 PCI-EISA bridge
180 * 3 none
181 * 4 none
182 * 5 none
183 * 6 PCI on board slot 0
184 * 7 PCI on board slot 1
185 * 8 PCI on board slot 2
186 *
187 *
188 * This two layered interrupt approach means that we allocate IRQ 16 and
189 * above for PCI interrupts. The IRQ relates to which bit the interrupt
190 * comes in on. This makes interrupt processing much easier.
191 */
192/*
193 * NOTE: the IRQ assignments below are arbitrary, but need to be consistent
194 * with the values in the irq swizzling tables above.
195 */
196
197static int __init
198sable_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
199{
200 static char irq_tab[9][5] __initdata = {
201 /*INT INTA INTB INTC INTD */
202 { 32+0, 32+0, 32+0, 32+0, 32+0}, /* IdSel 0, TULIP */
203 { 32+1, 32+1, 32+1, 32+1, 32+1}, /* IdSel 1, SCSI */
204 { -1, -1, -1, -1, -1}, /* IdSel 2, SIO */
205 { -1, -1, -1, -1, -1}, /* IdSel 3, none */
206 { -1, -1, -1, -1, -1}, /* IdSel 4, none */
207 { -1, -1, -1, -1, -1}, /* IdSel 5, none */
208 { 32+2, 32+2, 32+2, 32+2, 32+2}, /* IdSel 6, slot 0 */
209 { 32+3, 32+3, 32+3, 32+3, 32+3}, /* IdSel 7, slot 1 */
210 { 32+4, 32+4, 32+4, 32+4, 32+4} /* IdSel 8, slot 2 */
211 };
212 long min_idsel = 0, max_idsel = 8, irqs_per_slot = 5;
213 return COMMON_TABLE_LOOKUP;
214}
215#endif /* defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SABLE) */
216
217#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LYNX)
218
219/***********************************************************************/
220/* LYNX hardware specifics
221 */
222/*
223 * For LYNX, which is also baroque, we manage 64 IRQs, via a custom IC.
224 *
225 * Bit Meaning Kernel IRQ
226 *------------------------------------------
227 * 0
228 * 1
229 * 2
230 * 3 mouse 12
231 * 4
232 * 5
233 * 6 keyboard 1
234 * 7 floppy 6
235 * 8 COM2 3
236 * 9 parallel port 7
237 *10 EISA irq 3 -
238 *11 EISA irq 4 -
239 *12 EISA irq 5 5
240 *13 EISA irq 6 -
241 *14 EISA irq 7 -
242 *15 COM1 4
243 *16 EISA irq 9 9
244 *17 EISA irq 10 10
245 *18 EISA irq 11 11
246 *19 EISA irq 12 -
247 *20
248 *21 EISA irq 14 14
249 *22 EISA irq 15 15
250 *23 IIC -
251 *24 VGA (builtin) -
252 *25
253 *26
254 *27
255 *28 NCR810 (builtin) 28
256 *29
257 *30
258 *31
259 *32 PCI 0 slot 4 A primary bus 32
260 *33 PCI 0 slot 4 B primary bus 33
261 *34 PCI 0 slot 4 C primary bus 34
262 *35 PCI 0 slot 4 D primary bus
263 *36 PCI 0 slot 5 A primary bus
264 *37 PCI 0 slot 5 B primary bus
265 *38 PCI 0 slot 5 C primary bus
266 *39 PCI 0 slot 5 D primary bus
267 *40 PCI 0 slot 6 A primary bus
268 *41 PCI 0 slot 6 B primary bus
269 *42 PCI 0 slot 6 C primary bus
270 *43 PCI 0 slot 6 D primary bus
271 *44 PCI 0 slot 7 A primary bus
272 *45 PCI 0 slot 7 B primary bus
273 *46 PCI 0 slot 7 C primary bus
274 *47 PCI 0 slot 7 D primary bus
275 *48 PCI 0 slot 0 A secondary bus
276 *49 PCI 0 slot 0 B secondary bus
277 *50 PCI 0 slot 0 C secondary bus
278 *51 PCI 0 slot 0 D secondary bus
279 *52 PCI 0 slot 1 A secondary bus
280 *53 PCI 0 slot 1 B secondary bus
281 *54 PCI 0 slot 1 C secondary bus
282 *55 PCI 0 slot 1 D secondary bus
283 *56 PCI 0 slot 2 A secondary bus
284 *57 PCI 0 slot 2 B secondary bus
285 *58 PCI 0 slot 2 C secondary bus
286 *59 PCI 0 slot 2 D secondary bus
287 *60 PCI 0 slot 3 A secondary bus
288 *61 PCI 0 slot 3 B secondary bus
289 *62 PCI 0 slot 3 C secondary bus
290 *63 PCI 0 slot 3 D secondary bus
291 */
292
293static void
294lynx_update_irq_hw(unsigned long bit, unsigned long mask)
295{
296 /*
297 * Write the AIR register on the T3/T4 with the
298 * address of the IC mask register (offset 0x40)
299 */
300 *(vulp)T2_AIR = 0x40;
301 mb();
302 *(vulp)T2_AIR; /* re-read to force write */
303 mb();
304 *(vulp)T2_DIR = mask;
305 mb();
306 mb();
307}
308
309static void
310lynx_ack_irq_hw(unsigned long bit)
311{
312 *(vulp)T2_VAR = (u_long) bit;
313 mb();
314 mb();
315}
316
317static irq_swizzle_t lynx_irq_swizzle = {
318 { /* irq_to_mask */
319 -1, 6, -1, 8, 15, 12, 7, 9, /* pseudo PIC 0-7 */
320 -1, 16, 17, 18, 3, -1, 21, 22, /* pseudo PIC 8-15 */
321 -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo */
322 -1, -1, -1, -1, 28, -1, -1, -1, /* pseudo */
323 32, 33, 34, 35, 36, 37, 38, 39, /* mask 32-39 */
324 40, 41, 42, 43, 44, 45, 46, 47, /* mask 40-47 */
325 48, 49, 50, 51, 52, 53, 54, 55, /* mask 48-55 */
326 56, 57, 58, 59, 60, 61, 62, 63 /* mask 56-63 */
327 },
328 { /* mask_to_irq */
329 -1, -1, -1, 12, -1, -1, 1, 6, /* mask 0-7 */
330 3, 7, -1, -1, 5, -1, -1, 4, /* mask 8-15 */
331 9, 10, 11, -1, -1, 14, 15, -1, /* mask 16-23 */
332 -1, -1, -1, -1, 28, -1, -1, -1, /* mask 24-31 */
333 32, 33, 34, 35, 36, 37, 38, 39, /* mask 32-39 */
334 40, 41, 42, 43, 44, 45, 46, 47, /* mask 40-47 */
335 48, 49, 50, 51, 52, 53, 54, 55, /* mask 48-55 */
336 56, 57, 58, 59, 60, 61, 62, 63 /* mask 56-63 */
337 },
338 -1,
339 lynx_update_irq_hw,
340 lynx_ack_irq_hw
341};
342
343static void __init
344lynx_init_irq(void)
345{
346 sable_lynx_irq_swizzle = &lynx_irq_swizzle;
347 sable_lynx_init_irq(64);
348}
349
350/*
351 * PCI Fixup configuration for ALPHA LYNX (2100A)
352 *
353 * The device to slot mapping looks like:
354 *
355 * Slot Device
356 * 0 none
357 * 1 none
358 * 2 PCI-EISA bridge
359 * 3 PCI-PCI bridge
360 * 4 NCR 810 (Demi-Lynx only)
361 * 5 none
362 * 6 PCI on board slot 4
363 * 7 PCI on board slot 5
364 * 8 PCI on board slot 6
365 * 9 PCI on board slot 7
366 *
367 * And behind the PPB we have:
368 *
369 * 11 PCI on board slot 0
370 * 12 PCI on board slot 1
371 * 13 PCI on board slot 2
372 * 14 PCI on board slot 3
373 */
374/*
375 * NOTE: the IRQ assignments below are arbitrary, but need to be consistent
376 * with the values in the irq swizzling tables above.
377 */
378
379static int __init
380lynx_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
381{
382 static char irq_tab[19][5] __initdata = {
383 /*INT INTA INTB INTC INTD */
384 { -1, -1, -1, -1, -1}, /* IdSel 13, PCEB */
385 { -1, -1, -1, -1, -1}, /* IdSel 14, PPB */
386 { 28, 28, 28, 28, 28}, /* IdSel 15, NCR demi */
387 { -1, -1, -1, -1, -1}, /* IdSel 16, none */
388 { 32, 32, 33, 34, 35}, /* IdSel 17, slot 4 */
389 { 36, 36, 37, 38, 39}, /* IdSel 18, slot 5 */
390 { 40, 40, 41, 42, 43}, /* IdSel 19, slot 6 */
391 { 44, 44, 45, 46, 47}, /* IdSel 20, slot 7 */
392 { -1, -1, -1, -1, -1}, /* IdSel 22, none */
393 /* The following are actually behind the PPB. */
394 { -1, -1, -1, -1, -1}, /* IdSel 16 none */
395 { 28, 28, 28, 28, 28}, /* IdSel 17 NCR lynx */
396 { -1, -1, -1, -1, -1}, /* IdSel 18 none */
397 { -1, -1, -1, -1, -1}, /* IdSel 19 none */
398 { -1, -1, -1, -1, -1}, /* IdSel 20 none */
399 { -1, -1, -1, -1, -1}, /* IdSel 21 none */
400 { 48, 48, 49, 50, 51}, /* IdSel 22 slot 0 */
401 { 52, 52, 53, 54, 55}, /* IdSel 23 slot 1 */
402 { 56, 56, 57, 58, 59}, /* IdSel 24 slot 2 */
403 { 60, 60, 61, 62, 63} /* IdSel 25 slot 3 */
404 };
405 const long min_idsel = 2, max_idsel = 20, irqs_per_slot = 5;
406 return COMMON_TABLE_LOOKUP;
407}
408
409static u8 __init
410lynx_swizzle(struct pci_dev *dev, u8 *pinp)
411{
412 int slot, pin = *pinp;
413
414 if (dev->bus->number == 0) {
415 slot = PCI_SLOT(dev->devfn);
416 }
417 /* Check for the built-in bridge */
418 else if (PCI_SLOT(dev->bus->self->devfn) == 3) {
419 slot = PCI_SLOT(dev->devfn) + 11;
420 }
421 else
422 {
423 /* Must be a card-based bridge. */
424 do {
425 if (PCI_SLOT(dev->bus->self->devfn) == 3) {
426 slot = PCI_SLOT(dev->devfn) + 11;
427 break;
428 }
429 pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)) ;
430
431 /* Move up the chain of bridges. */
432 dev = dev->bus->self;
433 /* Slot of the next bridge. */
434 slot = PCI_SLOT(dev->devfn);
435 } while (dev->bus->self);
436 }
437 *pinp = pin;
438 return slot;
439}
440
441#endif /* defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LYNX) */
442
443/***********************************************************************/
444/* GENERIC irq routines */
445
446static inline void
447sable_lynx_enable_irq(unsigned int irq)
448{
449 unsigned long bit, mask;
450
451 bit = sable_lynx_irq_swizzle->irq_to_mask[irq];
452 spin_lock(&sable_lynx_irq_lock);
453 mask = sable_lynx_irq_swizzle->shadow_mask &= ~(1UL << bit);
454 sable_lynx_irq_swizzle->update_irq_hw(bit, mask);
455 spin_unlock(&sable_lynx_irq_lock);
456#if 0
457 printk("%s: mask 0x%lx bit 0x%x irq 0x%x\n",
458 __FUNCTION__, mask, bit, irq);
459#endif
460}
461
462static void
463sable_lynx_disable_irq(unsigned int irq)
464{
465 unsigned long bit, mask;
466
467 bit = sable_lynx_irq_swizzle->irq_to_mask[irq];
468 spin_lock(&sable_lynx_irq_lock);
469 mask = sable_lynx_irq_swizzle->shadow_mask |= 1UL << bit;
470 sable_lynx_irq_swizzle->update_irq_hw(bit, mask);
471 spin_unlock(&sable_lynx_irq_lock);
472#if 0
473 printk("%s: mask 0x%lx bit 0x%x irq 0x%x\n",
474 __FUNCTION__, mask, bit, irq);
475#endif
476}
477
478static unsigned int
479sable_lynx_startup_irq(unsigned int irq)
480{
481 sable_lynx_enable_irq(irq);
482 return 0;
483}
484
485static void
486sable_lynx_end_irq(unsigned int irq)
487{
488 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
489 sable_lynx_enable_irq(irq);
490}
491
492static void
493sable_lynx_mask_and_ack_irq(unsigned int irq)
494{
495 unsigned long bit, mask;
496
497 bit = sable_lynx_irq_swizzle->irq_to_mask[irq];
498 spin_lock(&sable_lynx_irq_lock);
499 mask = sable_lynx_irq_swizzle->shadow_mask |= 1UL << bit;
500 sable_lynx_irq_swizzle->update_irq_hw(bit, mask);
501 sable_lynx_irq_swizzle->ack_irq_hw(bit);
502 spin_unlock(&sable_lynx_irq_lock);
503}
504
505static struct hw_interrupt_type sable_lynx_irq_type = {
506 .typename = "SABLE/LYNX",
507 .startup = sable_lynx_startup_irq,
508 .shutdown = sable_lynx_disable_irq,
509 .enable = sable_lynx_enable_irq,
510 .disable = sable_lynx_disable_irq,
511 .ack = sable_lynx_mask_and_ack_irq,
512 .end = sable_lynx_end_irq,
513};
514
515static void
516sable_lynx_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
517{
518 /* Note that the vector reported by the SRM PALcode corresponds
519 to the interrupt mask bits, but we have to manage via the
520 so-called legacy IRQs for many common devices. */
521
522 int bit, irq;
523
524 bit = (vector - 0x800) >> 4;
525 irq = sable_lynx_irq_swizzle->mask_to_irq[bit];
526#if 0
527 printk("%s: vector 0x%lx bit 0x%x irq 0x%x\n",
528 __FUNCTION__, vector, bit, irq);
529#endif
530 handle_irq(irq, regs);
531}
532
533static void __init
534sable_lynx_init_irq(int nr_irqs)
535{
536 long i;
537
538 for (i = 0; i < nr_irqs; ++i) {
539 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
540 irq_desc[i].handler = &sable_lynx_irq_type;
541 }
542
543 common_init_isa_dma();
544}
545
546static void __init
547sable_lynx_init_pci(void)
548{
549 common_init_pci();
550}
551
552/*****************************************************************/
553/*
554 * The System Vectors
555 *
556 * In order that T2_HAE_ADDRESS should be a constant, we play
557 * these games with GAMMA_BIAS.
558 */
559
560#if defined(CONFIG_ALPHA_GENERIC) || \
561 (defined(CONFIG_ALPHA_SABLE) && !defined(CONFIG_ALPHA_GAMMA))
562#undef GAMMA_BIAS
563#define GAMMA_BIAS 0
564struct alpha_machine_vector sable_mv __initmv = {
565 .vector_name = "Sable",
566 DO_EV4_MMU,
567 DO_DEFAULT_RTC,
568 DO_T2_IO,
569 .machine_check = t2_machine_check,
570 .max_isa_dma_address = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
571 .min_io_address = EISA_DEFAULT_IO_BASE,
572 .min_mem_address = T2_DEFAULT_MEM_BASE,
573
574 .nr_irqs = 40,
575 .device_interrupt = sable_lynx_srm_device_interrupt,
576
577 .init_arch = t2_init_arch,
578 .init_irq = sable_init_irq,
579 .init_rtc = common_init_rtc,
580 .init_pci = sable_lynx_init_pci,
581 .kill_arch = t2_kill_arch,
582 .pci_map_irq = sable_map_irq,
583 .pci_swizzle = common_swizzle,
584
585 .sys = { .t2 = {
586 .gamma_bias = 0
587 } }
588};
589ALIAS_MV(sable)
590#endif /* GENERIC || (SABLE && !GAMMA) */
591
592#if defined(CONFIG_ALPHA_GENERIC) || \
593 (defined(CONFIG_ALPHA_SABLE) && defined(CONFIG_ALPHA_GAMMA))
594#undef GAMMA_BIAS
595#define GAMMA_BIAS _GAMMA_BIAS
596struct alpha_machine_vector sable_gamma_mv __initmv = {
597 .vector_name = "Sable-Gamma",
598 DO_EV5_MMU,
599 DO_DEFAULT_RTC,
600 DO_T2_IO,
601 .machine_check = t2_machine_check,
602 .max_isa_dma_address = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
603 .min_io_address = EISA_DEFAULT_IO_BASE,
604 .min_mem_address = T2_DEFAULT_MEM_BASE,
605
606 .nr_irqs = 40,
607 .device_interrupt = sable_lynx_srm_device_interrupt,
608
609 .init_arch = t2_init_arch,
610 .init_irq = sable_init_irq,
611 .init_rtc = common_init_rtc,
612 .init_pci = sable_lynx_init_pci,
613 .kill_arch = t2_kill_arch,
614 .pci_map_irq = sable_map_irq,
615 .pci_swizzle = common_swizzle,
616
617 .sys = { .t2 = {
618 .gamma_bias = _GAMMA_BIAS
619 } }
620};
621ALIAS_MV(sable_gamma)
622#endif /* GENERIC || (SABLE && GAMMA) */
623
624#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LYNX)
625#undef GAMMA_BIAS
626#define GAMMA_BIAS _GAMMA_BIAS
627struct alpha_machine_vector lynx_mv __initmv = {
628 .vector_name = "Lynx",
629 DO_EV4_MMU,
630 DO_DEFAULT_RTC,
631 DO_T2_IO,
632 .machine_check = t2_machine_check,
633 .max_isa_dma_address = ALPHA_SABLE_MAX_ISA_DMA_ADDRESS,
634 .min_io_address = EISA_DEFAULT_IO_BASE,
635 .min_mem_address = T2_DEFAULT_MEM_BASE,
636
637 .nr_irqs = 64,
638 .device_interrupt = sable_lynx_srm_device_interrupt,
639
640 .init_arch = t2_init_arch,
641 .init_irq = lynx_init_irq,
642 .init_rtc = common_init_rtc,
643 .init_pci = sable_lynx_init_pci,
644 .kill_arch = t2_kill_arch,
645 .pci_map_irq = lynx_map_irq,
646 .pci_swizzle = lynx_swizzle,
647
648 .sys = { .t2 = {
649 .gamma_bias = _GAMMA_BIAS
650 } }
651};
652ALIAS_MV(lynx)
653#endif /* GENERIC || LYNX */
diff --git a/arch/alpha/kernel/sys_sio.c b/arch/alpha/kernel/sys_sio.c
new file mode 100644
index 000000000000..47df48a6ddb7
--- /dev/null
+++ b/arch/alpha/kernel/sys_sio.c
@@ -0,0 +1,438 @@
1/*
2 * linux/arch/alpha/kernel/sys_sio.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996 Jay A Estabrook
6 * Copyright (C) 1998, 1999 Richard Henderson
7 *
8 * Code for all boards that route the PCI interrupts through the SIO
9 * PCI/ISA bridge. This includes Noname (AXPpci33), Multia (UDB),
10 * Kenetics's Platform 2000, Avanti (AlphaStation), XL, and AlphaBook1.
11 */
12
13#include <linux/config.h>
14#include <linux/kernel.h>
15#include <linux/types.h>
16#include <linux/mm.h>
17#include <linux/sched.h>
18#include <linux/pci.h>
19#include <linux/init.h>
20#include <linux/tty.h>
21
22#include <asm/compiler.h>
23#include <asm/ptrace.h>
24#include <asm/system.h>
25#include <asm/dma.h>
26#include <asm/irq.h>
27#include <asm/mmu_context.h>
28#include <asm/io.h>
29#include <asm/pgtable.h>
30#include <asm/core_apecs.h>
31#include <asm/core_lca.h>
32#include <asm/tlbflush.h>
33
34#include "proto.h"
35#include "irq_impl.h"
36#include "pci_impl.h"
37#include "machvec_impl.h"
38
39#if defined(ALPHA_RESTORE_SRM_SETUP)
40/* Save LCA configuration data as the console had it set up. */
41struct
42{
43 unsigned int orig_route_tab; /* for SAVE/RESTORE */
44} saved_config __attribute((common));
45#endif
46
47
48static void __init
49sio_init_irq(void)
50{
51 if (alpha_using_srm)
52 alpha_mv.device_interrupt = srm_device_interrupt;
53
54 init_i8259a_irqs();
55 common_init_isa_dma();
56}
57
58static inline void __init
59alphabook1_init_arch(void)
60{
61 /* The AlphaBook1 has LCD video fixed at 800x600,
62 37 rows and 100 cols. */
63 screen_info.orig_y = 37;
64 screen_info.orig_video_cols = 100;
65 screen_info.orig_video_lines = 37;
66
67 lca_init_arch();
68}
69
70
71/*
72 * sio_route_tab selects irq routing in PCI/ISA bridge so that:
73 * PIRQ0 -> irq 15
74 * PIRQ1 -> irq 9
75 * PIRQ2 -> irq 10
76 * PIRQ3 -> irq 11
77 *
78 * This probably ought to be configurable via MILO. For
79 * example, sound boards seem to like using IRQ 9.
80 *
81 * This is NOT how we should do it. PIRQ0-X should have
82 * their own IRQ's, the way intel uses the IO-APIC irq's.
83 */
84
85static void __init
86sio_pci_route(void)
87{
88#if defined(ALPHA_RESTORE_SRM_SETUP)
89 /* First, read and save the original setting. */
90 pci_bus_read_config_dword(pci_isa_hose->bus, PCI_DEVFN(7, 0), 0x60,
91 &saved_config.orig_route_tab);
92 printk("%s: PIRQ original 0x%x new 0x%x\n", __FUNCTION__,
93 saved_config.orig_route_tab, alpha_mv.sys.sio.route_tab);
94#endif
95
96 /* Now override with desired setting. */
97 pci_bus_write_config_dword(pci_isa_hose->bus, PCI_DEVFN(7, 0), 0x60,
98 alpha_mv.sys.sio.route_tab);
99}
100
101static unsigned int __init
102sio_collect_irq_levels(void)
103{
104 unsigned int level_bits = 0;
105 struct pci_dev *dev = NULL;
106
107 /* Iterate through the devices, collecting IRQ levels. */
108 while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
109 if ((dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) &&
110 (dev->class >> 8 != PCI_CLASS_BRIDGE_PCMCIA))
111 continue;
112
113 if (dev->irq)
114 level_bits |= (1 << dev->irq);
115 }
116 return level_bits;
117}
118
119static void __init
120sio_fixup_irq_levels(unsigned int level_bits)
121{
122 unsigned int old_level_bits;
123
124 /*
125 * Now, make all PCI interrupts level sensitive. Notice:
126 * these registers must be accessed byte-wise. inw()/outw()
127 * don't work.
128 *
129 * Make sure to turn off any level bits set for IRQs 9,10,11,15,
130 * so that the only bits getting set are for devices actually found.
131 * Note that we do preserve the remainder of the bits, which we hope
132 * will be set correctly by ARC/SRM.
133 *
134 * Note: we at least preserve any level-set bits on AlphaBook1
135 */
136 old_level_bits = inb(0x4d0) | (inb(0x4d1) << 8);
137
138 level_bits |= (old_level_bits & 0x71ff);
139
140 outb((level_bits >> 0) & 0xff, 0x4d0);
141 outb((level_bits >> 8) & 0xff, 0x4d1);
142}
143
144static inline int __init
145noname_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
146{
147 /*
148 * The Noname board has 5 PCI slots with each of the 4
149 * interrupt pins routed to different pins on the PCI/ISA
150 * bridge (PIRQ0-PIRQ3). The table below is based on
151 * information available at:
152 *
153 * http://ftp.digital.com/pub/DEC/axppci/ref_interrupts.txt
154 *
155 * I have no information on the Avanti interrupt routing, but
156 * the routing seems to be identical to the Noname except
157 * that the Avanti has an additional slot whose routing I'm
158 * unsure of.
159 *
160 * pirq_tab[0] is a fake entry to deal with old PCI boards
161 * that have the interrupt pin number hardwired to 0 (meaning
162 * that they use the default INTA line, if they are interrupt
163 * driven at all).
164 */
165 static char irq_tab[][5] __initdata = {
166 /*INT A B C D */
167 { 3, 3, 3, 3, 3}, /* idsel 6 (53c810) */
168 {-1, -1, -1, -1, -1}, /* idsel 7 (SIO: PCI/ISA bridge) */
169 { 2, 2, -1, -1, -1}, /* idsel 8 (Hack: slot closest ISA) */
170 {-1, -1, -1, -1, -1}, /* idsel 9 (unused) */
171 {-1, -1, -1, -1, -1}, /* idsel 10 (unused) */
172 { 0, 0, 2, 1, 0}, /* idsel 11 KN25_PCI_SLOT0 */
173 { 1, 1, 0, 2, 1}, /* idsel 12 KN25_PCI_SLOT1 */
174 { 2, 2, 1, 0, 2}, /* idsel 13 KN25_PCI_SLOT2 */
175 { 0, 0, 0, 0, 0}, /* idsel 14 AS255 TULIP */
176 };
177 const long min_idsel = 6, max_idsel = 14, irqs_per_slot = 5;
178 int irq = COMMON_TABLE_LOOKUP, tmp;
179 tmp = __kernel_extbl(alpha_mv.sys.sio.route_tab, irq);
180 return irq >= 0 ? tmp : -1;
181}
182
183static inline int __init
184p2k_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
185{
186 static char irq_tab[][5] __initdata = {
187 /*INT A B C D */
188 { 0, 0, -1, -1, -1}, /* idsel 6 (53c810) */
189 {-1, -1, -1, -1, -1}, /* idsel 7 (SIO: PCI/ISA bridge) */
190 { 1, 1, 2, 3, 0}, /* idsel 8 (slot A) */
191 { 2, 2, 3, 0, 1}, /* idsel 9 (slot B) */
192 {-1, -1, -1, -1, -1}, /* idsel 10 (unused) */
193 {-1, -1, -1, -1, -1}, /* idsel 11 (unused) */
194 { 3, 3, -1, -1, -1}, /* idsel 12 (CMD0646) */
195 };
196 const long min_idsel = 6, max_idsel = 12, irqs_per_slot = 5;
197 int irq = COMMON_TABLE_LOOKUP, tmp;
198 tmp = __kernel_extbl(alpha_mv.sys.sio.route_tab, irq);
199 return irq >= 0 ? tmp : -1;
200}
201
202static inline void __init
203noname_init_pci(void)
204{
205 common_init_pci();
206 sio_pci_route();
207 sio_fixup_irq_levels(sio_collect_irq_levels());
208 ns87312_enable_ide(0x26e);
209}
210
211static inline void __init
212alphabook1_init_pci(void)
213{
214 struct pci_dev *dev;
215 unsigned char orig, config;
216
217 common_init_pci();
218 sio_pci_route();
219
220 /*
221 * On the AlphaBook1, the PCMCIA chip (Cirrus 6729)
222 * is sensitive to PCI bus bursts, so we must DISABLE
223 * burst mode for the NCR 8xx SCSI... :-(
224 *
225 * Note that the NCR810 SCSI driver must preserve the
226 * setting of the bit in order for this to work. At the
227 * moment (2.0.29), ncr53c8xx.c does NOT do this, but
228 * 53c7,8xx.c DOES.
229 */
230
231 dev = NULL;
232 while ((dev = pci_find_device(PCI_VENDOR_ID_NCR, PCI_ANY_ID, dev))) {
233 if (dev->device == PCI_DEVICE_ID_NCR_53C810
234 || dev->device == PCI_DEVICE_ID_NCR_53C815
235 || dev->device == PCI_DEVICE_ID_NCR_53C820
236 || dev->device == PCI_DEVICE_ID_NCR_53C825) {
237 unsigned long io_port;
238 unsigned char ctest4;
239
240 io_port = dev->resource[0].start;
241 ctest4 = inb(io_port+0x21);
242 if (!(ctest4 & 0x80)) {
243 printk("AlphaBook1 NCR init: setting"
244 " burst disable\n");
245 outb(ctest4 | 0x80, io_port+0x21);
246 }
247 }
248 }
249
250 /* Do not set *ANY* level triggers for AlphaBook1. */
251 sio_fixup_irq_levels(0);
252
253 /* Make sure that register PR1 indicates 1Mb mem */
254 outb(0x0f, 0x3ce); orig = inb(0x3cf); /* read PR5 */
255 outb(0x0f, 0x3ce); outb(0x05, 0x3cf); /* unlock PR0-4 */
256 outb(0x0b, 0x3ce); config = inb(0x3cf); /* read PR1 */
257 if ((config & 0xc0) != 0xc0) {
258 printk("AlphaBook1 VGA init: setting 1Mb memory\n");
259 config |= 0xc0;
260 outb(0x0b, 0x3ce); outb(config, 0x3cf); /* write PR1 */
261 }
262 outb(0x0f, 0x3ce); outb(orig, 0x3cf); /* (re)lock PR0-4 */
263}
264
265void
266sio_kill_arch(int mode)
267{
268#if defined(ALPHA_RESTORE_SRM_SETUP)
269 /* Since we cannot read the PCI DMA Window CSRs, we
270 * cannot restore them here.
271 *
272 * However, we CAN read the PIRQ route register, so restore it
273 * now...
274 */
275 pci_bus_write_config_dword(pci_isa_hose->bus, PCI_DEVFN(7, 0), 0x60,
276 saved_config.orig_route_tab);
277#endif
278}
279
280
281/*
282 * The System Vectors
283 */
284
285#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_BOOK1)
286struct alpha_machine_vector alphabook1_mv __initmv = {
287 .vector_name = "AlphaBook1",
288 DO_EV4_MMU,
289 DO_DEFAULT_RTC,
290 DO_LCA_IO,
291 .machine_check = lca_machine_check,
292 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
293 .min_io_address = DEFAULT_IO_BASE,
294 .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE,
295
296 .nr_irqs = 16,
297 .device_interrupt = isa_device_interrupt,
298
299 .init_arch = alphabook1_init_arch,
300 .init_irq = sio_init_irq,
301 .init_rtc = common_init_rtc,
302 .init_pci = alphabook1_init_pci,
303 .kill_arch = sio_kill_arch,
304 .pci_map_irq = noname_map_irq,
305 .pci_swizzle = common_swizzle,
306
307 .sys = { .sio = {
308 /* NCR810 SCSI is 14, PCMCIA controller is 15. */
309 .route_tab = 0x0e0f0a0a,
310 }}
311};
312ALIAS_MV(alphabook1)
313#endif
314
315#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_AVANTI)
316struct alpha_machine_vector avanti_mv __initmv = {
317 .vector_name = "Avanti",
318 DO_EV4_MMU,
319 DO_DEFAULT_RTC,
320 DO_APECS_IO,
321 .machine_check = apecs_machine_check,
322 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
323 .min_io_address = DEFAULT_IO_BASE,
324 .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE,
325
326 .nr_irqs = 16,
327 .device_interrupt = isa_device_interrupt,
328
329 .init_arch = apecs_init_arch,
330 .init_irq = sio_init_irq,
331 .init_rtc = common_init_rtc,
332 .init_pci = noname_init_pci,
333 .kill_arch = sio_kill_arch,
334 .pci_map_irq = noname_map_irq,
335 .pci_swizzle = common_swizzle,
336
337 .sys = { .sio = {
338 .route_tab = 0x0b0a0e0f,
339 }}
340};
341ALIAS_MV(avanti)
342#endif
343
344#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_NONAME)
345struct alpha_machine_vector noname_mv __initmv = {
346 .vector_name = "Noname",
347 DO_EV4_MMU,
348 DO_DEFAULT_RTC,
349 DO_LCA_IO,
350 .machine_check = lca_machine_check,
351 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
352 .min_io_address = DEFAULT_IO_BASE,
353 .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE,
354
355 .nr_irqs = 16,
356 .device_interrupt = srm_device_interrupt,
357
358 .init_arch = lca_init_arch,
359 .init_irq = sio_init_irq,
360 .init_rtc = common_init_rtc,
361 .init_pci = noname_init_pci,
362 .kill_arch = sio_kill_arch,
363 .pci_map_irq = noname_map_irq,
364 .pci_swizzle = common_swizzle,
365
366 .sys = { .sio = {
367 /* For UDB, the only available PCI slot must not map to IRQ 9,
368 since that's the builtin MSS sound chip. That PCI slot
369 will map to PIRQ1 (for INTA at least), so we give it IRQ 15
370 instead.
371
372 Unfortunately we have to do this for NONAME as well, since
373 they are co-indicated when the platform type "Noname" is
374 selected... :-( */
375
376 .route_tab = 0x0b0a0f0d,
377 }}
378};
379ALIAS_MV(noname)
380#endif
381
382#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_P2K)
383struct alpha_machine_vector p2k_mv __initmv = {
384 .vector_name = "Platform2000",
385 DO_EV4_MMU,
386 DO_DEFAULT_RTC,
387 DO_LCA_IO,
388 .machine_check = lca_machine_check,
389 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
390 .min_io_address = DEFAULT_IO_BASE,
391 .min_mem_address = APECS_AND_LCA_DEFAULT_MEM_BASE,
392
393 .nr_irqs = 16,
394 .device_interrupt = srm_device_interrupt,
395
396 .init_arch = lca_init_arch,
397 .init_irq = sio_init_irq,
398 .init_rtc = common_init_rtc,
399 .init_pci = noname_init_pci,
400 .kill_arch = sio_kill_arch,
401 .pci_map_irq = p2k_map_irq,
402 .pci_swizzle = common_swizzle,
403
404 .sys = { .sio = {
405 .route_tab = 0x0b0a090f,
406 }}
407};
408ALIAS_MV(p2k)
409#endif
410
411#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_XL)
412struct alpha_machine_vector xl_mv __initmv = {
413 .vector_name = "XL",
414 DO_EV4_MMU,
415 DO_DEFAULT_RTC,
416 DO_APECS_IO,
417 .machine_check = apecs_machine_check,
418 .max_isa_dma_address = ALPHA_XL_MAX_ISA_DMA_ADDRESS,
419 .min_io_address = DEFAULT_IO_BASE,
420 .min_mem_address = XL_DEFAULT_MEM_BASE,
421
422 .nr_irqs = 16,
423 .device_interrupt = isa_device_interrupt,
424
425 .init_arch = apecs_init_arch,
426 .init_irq = sio_init_irq,
427 .init_rtc = common_init_rtc,
428 .init_pci = noname_init_pci,
429 .kill_arch = sio_kill_arch,
430 .pci_map_irq = noname_map_irq,
431 .pci_swizzle = common_swizzle,
432
433 .sys = { .sio = {
434 .route_tab = 0x0b0a090f,
435 }}
436};
437ALIAS_MV(xl)
438#endif
diff --git a/arch/alpha/kernel/sys_sx164.c b/arch/alpha/kernel/sys_sx164.c
new file mode 100644
index 000000000000..94ad68b7c0ae
--- /dev/null
+++ b/arch/alpha/kernel/sys_sx164.c
@@ -0,0 +1,178 @@
1/*
2 * linux/arch/alpha/kernel/sys_sx164.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996 Jay A Estabrook
6 * Copyright (C) 1998, 1999, 2000 Richard Henderson
7 *
8 * Code supporting the SX164 (PCA56+PYXIS).
9 */
10
11#include <linux/kernel.h>
12#include <linux/types.h>
13#include <linux/mm.h>
14#include <linux/sched.h>
15#include <linux/pci.h>
16#include <linux/init.h>
17#include <linux/bitops.h>
18
19#include <asm/ptrace.h>
20#include <asm/system.h>
21#include <asm/dma.h>
22#include <asm/irq.h>
23#include <asm/mmu_context.h>
24#include <asm/io.h>
25#include <asm/pgtable.h>
26#include <asm/core_cia.h>
27#include <asm/hwrpb.h>
28#include <asm/tlbflush.h>
29
30#include "proto.h"
31#include "irq_impl.h"
32#include "pci_impl.h"
33#include "machvec_impl.h"
34
35
36static void __init
37sx164_init_irq(void)
38{
39 outb(0, DMA1_RESET_REG);
40 outb(0, DMA2_RESET_REG);
41 outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
42 outb(0, DMA2_MASK_REG);
43
44 if (alpha_using_srm)
45 alpha_mv.device_interrupt = srm_device_interrupt;
46
47 init_i8259a_irqs();
48
49 /* Not interested in the bogus interrupts (0,3,4,5,40-47),
50 NMI (1), or HALT (2). */
51 if (alpha_using_srm)
52 init_srm_irqs(40, 0x3f0000);
53 else
54 init_pyxis_irqs(0xff00003f0000UL);
55
56 setup_irq(16+6, &timer_cascade_irqaction);
57}
58
59/*
60 * PCI Fixup configuration.
61 *
62 * Summary @ PYXIS_INT_REQ:
63 * Bit Meaning
64 * 0 RSVD
65 * 1 NMI
66 * 2 Halt/Reset switch
67 * 3 MBZ
68 * 4 RAZ
69 * 5 RAZ
70 * 6 Interval timer (RTC)
71 * 7 PCI-ISA Bridge
72 * 8 Interrupt Line A from slot 3
73 * 9 Interrupt Line A from slot 2
74 *10 Interrupt Line A from slot 1
75 *11 Interrupt Line A from slot 0
76 *12 Interrupt Line B from slot 3
77 *13 Interrupt Line B from slot 2
78 *14 Interrupt Line B from slot 1
79 *15 Interrupt line B from slot 0
80 *16 Interrupt Line C from slot 3
81 *17 Interrupt Line C from slot 2
82 *18 Interrupt Line C from slot 1
83 *19 Interrupt Line C from slot 0
84 *20 Interrupt Line D from slot 3
85 *21 Interrupt Line D from slot 2
86 *22 Interrupt Line D from slot 1
87 *23 Interrupt Line D from slot 0
88 *
89 * IdSel
90 * 5 32 bit PCI option slot 2
91 * 6 64 bit PCI option slot 0
92 * 7 64 bit PCI option slot 1
93 * 8 Cypress I/O
94 * 9 32 bit PCI option slot 3
95 */
96
97static int __init
98sx164_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
99{
100 static char irq_tab[5][5] __initdata = {
101 /*INT INTA INTB INTC INTD */
102 { 16+ 9, 16+ 9, 16+13, 16+17, 16+21}, /* IdSel 5 slot 2 J17 */
103 { 16+11, 16+11, 16+15, 16+19, 16+23}, /* IdSel 6 slot 0 J19 */
104 { 16+10, 16+10, 16+14, 16+18, 16+22}, /* IdSel 7 slot 1 J18 */
105 { -1, -1, -1, -1, -1}, /* IdSel 8 SIO */
106 { 16+ 8, 16+ 8, 16+12, 16+16, 16+20} /* IdSel 9 slot 3 J15 */
107 };
108 const long min_idsel = 5, max_idsel = 9, irqs_per_slot = 5;
109 return COMMON_TABLE_LOOKUP;
110}
111
112static void __init
113sx164_init_pci(void)
114{
115 cia_init_pci();
116 SMC669_Init(0);
117}
118
119static void __init
120sx164_init_arch(void)
121{
122 /*
123 * OSF palcode v1.23 forgets to enable PCA56 Motion Video
124 * Instructions. Let's enable it.
125 * We have to check palcode revision because CSERVE interface
126 * is subject to change without notice. For example, it
127 * has been changed completely since v1.16 (found in MILO
128 * distribution). -ink
129 */
130 struct percpu_struct *cpu = (struct percpu_struct*)
131 ((char*)hwrpb + hwrpb->processor_offset);
132
133 if (amask(AMASK_MAX) != 0
134 && alpha_using_srm
135 && (cpu->pal_revision & 0xffff) == 0x117) {
136 __asm__ __volatile__(
137 "lda $16,8($31)\n"
138 "call_pal 9\n" /* Allow PALRES insns in kernel mode */
139 ".long 0x64000118\n\n" /* hw_mfpr $0,icsr */
140 "ldah $16,(1<<(19-16))($31)\n"
141 "or $0,$16,$0\n" /* set MVE bit */
142 ".long 0x74000118\n" /* hw_mtpr $0,icsr */
143 "lda $16,9($31)\n"
144 "call_pal 9" /* Disable PALRES insns */
145 : : : "$0", "$16");
146 printk("PCA56 MVI set enabled\n");
147 }
148
149 pyxis_init_arch();
150}
151
152/*
153 * The System Vector
154 */
155
156struct alpha_machine_vector sx164_mv __initmv = {
157 .vector_name = "SX164",
158 DO_EV5_MMU,
159 DO_DEFAULT_RTC,
160 DO_PYXIS_IO,
161 .machine_check = cia_machine_check,
162 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
163 .min_io_address = DEFAULT_IO_BASE,
164 .min_mem_address = DEFAULT_MEM_BASE,
165 .pci_dac_offset = PYXIS_DAC_OFFSET,
166
167 .nr_irqs = 48,
168 .device_interrupt = pyxis_device_interrupt,
169
170 .init_arch = sx164_init_arch,
171 .init_irq = sx164_init_irq,
172 .init_rtc = common_init_rtc,
173 .init_pci = sx164_init_pci,
174 .kill_arch = cia_kill_arch,
175 .pci_map_irq = sx164_map_irq,
176 .pci_swizzle = common_swizzle,
177};
178ALIAS_MV(sx164)
diff --git a/arch/alpha/kernel/sys_takara.c b/arch/alpha/kernel/sys_takara.c
new file mode 100644
index 000000000000..7955bdfc2db0
--- /dev/null
+++ b/arch/alpha/kernel/sys_takara.c
@@ -0,0 +1,296 @@
1/*
2 * linux/arch/alpha/kernel/sys_takara.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996 Jay A Estabrook
6 * Copyright (C) 1998, 1999 Richard Henderson
7 *
8 * Code supporting the TAKARA.
9 */
10
11#include <linux/kernel.h>
12#include <linux/types.h>
13#include <linux/mm.h>
14#include <linux/sched.h>
15#include <linux/pci.h>
16#include <linux/init.h>
17
18#include <asm/ptrace.h>
19#include <asm/system.h>
20#include <asm/dma.h>
21#include <asm/irq.h>
22#include <asm/mmu_context.h>
23#include <asm/io.h>
24#include <asm/pgtable.h>
25#include <asm/core_cia.h>
26#include <asm/tlbflush.h>
27
28#include "proto.h"
29#include "irq_impl.h"
30#include "pci_impl.h"
31#include "machvec_impl.h"
32
33
34/* Note mask bit is true for DISABLED irqs. */
35static unsigned long cached_irq_mask[2] = { -1, -1 };
36
37static inline void
38takara_update_irq_hw(unsigned long irq, unsigned long mask)
39{
40 int regaddr;
41
42 mask = (irq >= 64 ? mask << 16 : mask >> ((irq - 16) & 0x30));
43 regaddr = 0x510 + (((irq - 16) >> 2) & 0x0c);
44 outl(mask & 0xffff0000UL, regaddr);
45}
46
47static inline void
48takara_enable_irq(unsigned int irq)
49{
50 unsigned long mask;
51 mask = (cached_irq_mask[irq >= 64] &= ~(1UL << (irq & 63)));
52 takara_update_irq_hw(irq, mask);
53}
54
55static void
56takara_disable_irq(unsigned int irq)
57{
58 unsigned long mask;
59 mask = (cached_irq_mask[irq >= 64] |= 1UL << (irq & 63));
60 takara_update_irq_hw(irq, mask);
61}
62
63static unsigned int
64takara_startup_irq(unsigned int irq)
65{
66 takara_enable_irq(irq);
67 return 0; /* never anything pending */
68}
69
70static void
71takara_end_irq(unsigned int irq)
72{
73 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
74 takara_enable_irq(irq);
75}
76
77static struct hw_interrupt_type takara_irq_type = {
78 .typename = "TAKARA",
79 .startup = takara_startup_irq,
80 .shutdown = takara_disable_irq,
81 .enable = takara_enable_irq,
82 .disable = takara_disable_irq,
83 .ack = takara_disable_irq,
84 .end = takara_end_irq,
85};
86
87static void
88takara_device_interrupt(unsigned long vector, struct pt_regs *regs)
89{
90 unsigned intstatus;
91
92 /*
93 * The PALcode will have passed us vectors 0x800 or 0x810,
94 * which are fairly arbitrary values and serve only to tell
95 * us whether an interrupt has come in on IRQ0 or IRQ1. If
96 * it's IRQ1 it's a PCI interrupt; if it's IRQ0, it's
97 * probably ISA, but PCI interrupts can come through IRQ0
98 * as well if the interrupt controller isn't in accelerated
99 * mode.
100 *
101 * OTOH, the accelerator thing doesn't seem to be working
102 * overly well, so what we'll do instead is try directly
103 * examining the Master Interrupt Register to see if it's a
104 * PCI interrupt, and if _not_ then we'll pass it on to the
105 * ISA handler.
106 */
107
108 intstatus = inw(0x500) & 15;
109 if (intstatus) {
110 /*
111 * This is a PCI interrupt. Check each bit and
112 * despatch an interrupt if it's set.
113 */
114
115 if (intstatus & 8) handle_irq(16+3, regs);
116 if (intstatus & 4) handle_irq(16+2, regs);
117 if (intstatus & 2) handle_irq(16+1, regs);
118 if (intstatus & 1) handle_irq(16+0, regs);
119 } else {
120 isa_device_interrupt (vector, regs);
121 }
122}
123
124static void
125takara_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
126{
127 int irq = (vector - 0x800) >> 4;
128 handle_irq(irq, regs);
129}
130
131static void __init
132takara_init_irq(void)
133{
134 long i;
135
136 init_i8259a_irqs();
137
138 if (alpha_using_srm) {
139 alpha_mv.device_interrupt = takara_srm_device_interrupt;
140 } else {
141 unsigned int ctlreg = inl(0x500);
142
143 /* Return to non-accelerated mode. */
144 ctlreg &= ~0x8000;
145 outl(ctlreg, 0x500);
146
147 /* Enable the PCI interrupt register. */
148 ctlreg = 0x05107c00;
149 outl(ctlreg, 0x500);
150 }
151
152 for (i = 16; i < 128; i += 16)
153 takara_update_irq_hw(i, -1);
154
155 for (i = 16; i < 128; ++i) {
156 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
157 irq_desc[i].handler = &takara_irq_type;
158 }
159
160 common_init_isa_dma();
161}
162
163
164/*
165 * The Takara has PCI devices 1, 2, and 3 configured to slots 20,
166 * 19, and 18 respectively, in the default configuration. They can
167 * also be jumpered to slots 8, 7, and 6 respectively, which is fun
168 * because the SIO ISA bridge can also be slot 7. However, the SIO
169 * doesn't explicitly generate PCI-type interrupts, so we can
170 * assign it whatever the hell IRQ we like and it doesn't matter.
171 */
172
173static int __init
174takara_map_irq_srm(struct pci_dev *dev, u8 slot, u8 pin)
175{
176 static char irq_tab[15][5] __initdata = {
177 { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 6 == device 3 */
178 { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 7 == device 2 */
179 { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 8 == device 1 */
180 { -1, -1, -1, -1, -1}, /* slot 9 == nothing */
181 { -1, -1, -1, -1, -1}, /* slot 10 == nothing */
182 { -1, -1, -1, -1, -1}, /* slot 11 == nothing */
183 /* These are behind the bridges. */
184 { 12, 12, 13, 14, 15}, /* slot 12 == nothing */
185 { 8, 8, 9, 19, 11}, /* slot 13 == nothing */
186 { 4, 4, 5, 6, 7}, /* slot 14 == nothing */
187 { 0, 0, 1, 2, 3}, /* slot 15 == nothing */
188 { -1, -1, -1, -1, -1}, /* slot 16 == nothing */
189 {64+ 0, 64+0, 64+1, 64+2, 64+3}, /* slot 17= device 4 */
190 {48+ 0, 48+0, 48+1, 48+2, 48+3}, /* slot 18= device 3 */
191 {32+ 0, 32+0, 32+1, 32+2, 32+3}, /* slot 19= device 2 */
192 {16+ 0, 16+0, 16+1, 16+2, 16+3}, /* slot 20= device 1 */
193 };
194 const long min_idsel = 6, max_idsel = 20, irqs_per_slot = 5;
195 int irq = COMMON_TABLE_LOOKUP;
196 if (irq >= 0 && irq < 16) {
197 /* Guess that we are behind a bridge. */
198 unsigned int busslot = PCI_SLOT(dev->bus->self->devfn);
199 irq += irq_tab[busslot-min_idsel][0];
200 }
201 return irq;
202}
203
204static int __init
205takara_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
206{
207 static char irq_tab[15][5] __initdata = {
208 { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 6 == device 3 */
209 { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 7 == device 2 */
210 { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 8 == device 1 */
211 { -1, -1, -1, -1, -1}, /* slot 9 == nothing */
212 { -1, -1, -1, -1, -1}, /* slot 10 == nothing */
213 { -1, -1, -1, -1, -1}, /* slot 11 == nothing */
214 { -1, -1, -1, -1, -1}, /* slot 12 == nothing */
215 { -1, -1, -1, -1, -1}, /* slot 13 == nothing */
216 { -1, -1, -1, -1, -1}, /* slot 14 == nothing */
217 { -1, -1, -1, -1, -1}, /* slot 15 == nothing */
218 { -1, -1, -1, -1, -1}, /* slot 16 == nothing */
219 { -1, -1, -1, -1, -1}, /* slot 17 == nothing */
220 { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 18 == device 3 */
221 { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 19 == device 2 */
222 { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 20 == device 1 */
223 };
224 const long min_idsel = 6, max_idsel = 20, irqs_per_slot = 5;
225 return COMMON_TABLE_LOOKUP;
226}
227
228static u8 __init
229takara_swizzle(struct pci_dev *dev, u8 *pinp)
230{
231 int slot = PCI_SLOT(dev->devfn);
232 int pin = *pinp;
233 unsigned int ctlreg = inl(0x500);
234 unsigned int busslot;
235
236 if (!dev->bus->self)
237 return slot;
238
239 busslot = PCI_SLOT(dev->bus->self->devfn);
240 /* Check for built-in bridges. */
241 if (dev->bus->number != 0
242 && busslot > 16
243 && ((1<<(36-busslot)) & ctlreg)) {
244 if (pin == 1)
245 pin += (20 - busslot);
246 else {
247 printk(KERN_WARNING "takara_swizzle: can only "
248 "handle cards with INTA IRQ pin.\n");
249 }
250 } else {
251 /* Must be a card-based bridge. */
252 printk(KERN_WARNING "takara_swizzle: cannot handle "
253 "card-bridge behind builtin bridge yet.\n");
254 }
255
256 *pinp = pin;
257 return slot;
258}
259
260static void __init
261takara_init_pci(void)
262{
263 if (alpha_using_srm)
264 alpha_mv.pci_map_irq = takara_map_irq_srm;
265
266 cia_init_pci();
267 ns87312_enable_ide(0x26e);
268}
269
270
271/*
272 * The System Vector
273 */
274
275struct alpha_machine_vector takara_mv __initmv = {
276 .vector_name = "Takara",
277 DO_EV5_MMU,
278 DO_DEFAULT_RTC,
279 DO_CIA_IO,
280 .machine_check = cia_machine_check,
281 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
282 .min_io_address = DEFAULT_IO_BASE,
283 .min_mem_address = CIA_DEFAULT_MEM_BASE,
284
285 .nr_irqs = 128,
286 .device_interrupt = takara_device_interrupt,
287
288 .init_arch = cia_init_arch,
289 .init_irq = takara_init_irq,
290 .init_rtc = common_init_rtc,
291 .init_pci = takara_init_pci,
292 .kill_arch = cia_kill_arch,
293 .pci_map_irq = takara_map_irq,
294 .pci_swizzle = takara_swizzle,
295};
296ALIAS_MV(takara)
diff --git a/arch/alpha/kernel/sys_titan.c b/arch/alpha/kernel/sys_titan.c
new file mode 100644
index 000000000000..5f84417eeb7b
--- /dev/null
+++ b/arch/alpha/kernel/sys_titan.c
@@ -0,0 +1,420 @@
1/*
2 * linux/arch/alpha/kernel/sys_titan.c
3 *
4 * Copyright (C) 1995 David A Rusling
5 * Copyright (C) 1996, 1999 Jay A Estabrook
6 * Copyright (C) 1998, 1999 Richard Henderson
7 * Copyright (C) 1999, 2000 Jeff Wiedemeier
8 *
9 * Code supporting TITAN systems (EV6+TITAN), currently:
10 * Privateer
11 * Falcon
12 * Granite
13 */
14
15#include <linux/config.h>
16#include <linux/kernel.h>
17#include <linux/types.h>
18#include <linux/mm.h>
19#include <linux/sched.h>
20#include <linux/pci.h>
21#include <linux/init.h>
22#include <linux/bitops.h>
23
24#include <asm/ptrace.h>
25#include <asm/system.h>
26#include <asm/dma.h>
27#include <asm/irq.h>
28#include <asm/mmu_context.h>
29#include <asm/io.h>
30#include <asm/pgtable.h>
31#include <asm/core_titan.h>
32#include <asm/hwrpb.h>
33#include <asm/tlbflush.h>
34
35#include "proto.h"
36#include "irq_impl.h"
37#include "pci_impl.h"
38#include "machvec_impl.h"
39#include "err_impl.h"
40
41
42/*
43 * Titan generic
44 */
45
46/*
47 * Titan supports up to 4 CPUs
48 */
49static unsigned long titan_cpu_irq_affinity[4] = { ~0UL, ~0UL, ~0UL, ~0UL };
50
51/*
52 * Mask is set (1) if enabled
53 */
54static unsigned long titan_cached_irq_mask;
55
56/*
57 * Need SMP-safe access to interrupt CSRs
58 */
59DEFINE_SPINLOCK(titan_irq_lock);
60
61static void
62titan_update_irq_hw(unsigned long mask)
63{
64 register titan_cchip *cchip = TITAN_cchip;
65 unsigned long isa_enable = 1UL << 55;
66 register int bcpu = boot_cpuid;
67
68#ifdef CONFIG_SMP
69 cpumask_t cpm = cpu_present_mask;
70 volatile unsigned long *dim0, *dim1, *dim2, *dim3;
71 unsigned long mask0, mask1, mask2, mask3, dummy;
72
73 mask &= ~isa_enable;
74 mask0 = mask & titan_cpu_irq_affinity[0];
75 mask1 = mask & titan_cpu_irq_affinity[1];
76 mask2 = mask & titan_cpu_irq_affinity[2];
77 mask3 = mask & titan_cpu_irq_affinity[3];
78
79 if (bcpu == 0) mask0 |= isa_enable;
80 else if (bcpu == 1) mask1 |= isa_enable;
81 else if (bcpu == 2) mask2 |= isa_enable;
82 else mask3 |= isa_enable;
83
84 dim0 = &cchip->dim0.csr;
85 dim1 = &cchip->dim1.csr;
86 dim2 = &cchip->dim2.csr;
87 dim3 = &cchip->dim3.csr;
88 if (!cpu_isset(0, cpm)) dim0 = &dummy;
89 if (!cpu_isset(1, cpm)) dim1 = &dummy;
90 if (!cpu_isset(2, cpm)) dim2 = &dummy;
91 if (!cpu_isset(3, cpm)) dim3 = &dummy;
92
93 *dim0 = mask0;
94 *dim1 = mask1;
95 *dim2 = mask2;
96 *dim3 = mask3;
97 mb();
98 *dim0;
99 *dim1;
100 *dim2;
101 *dim3;
102#else
103 volatile unsigned long *dimB;
104 dimB = &cchip->dim0.csr;
105 if (bcpu == 1) dimB = &cchip->dim1.csr;
106 else if (bcpu == 2) dimB = &cchip->dim2.csr;
107 else if (bcpu == 3) dimB = &cchip->dim3.csr;
108
109 *dimB = mask | isa_enable;
110 mb();
111 *dimB;
112#endif
113}
114
115static inline void
116titan_enable_irq(unsigned int irq)
117{
118 spin_lock(&titan_irq_lock);
119 titan_cached_irq_mask |= 1UL << (irq - 16);
120 titan_update_irq_hw(titan_cached_irq_mask);
121 spin_unlock(&titan_irq_lock);
122}
123
124static inline void
125titan_disable_irq(unsigned int irq)
126{
127 spin_lock(&titan_irq_lock);
128 titan_cached_irq_mask &= ~(1UL << (irq - 16));
129 titan_update_irq_hw(titan_cached_irq_mask);
130 spin_unlock(&titan_irq_lock);
131}
132
133static unsigned int
134titan_startup_irq(unsigned int irq)
135{
136 titan_enable_irq(irq);
137 return 0; /* never anything pending */
138}
139
140static void
141titan_end_irq(unsigned int irq)
142{
143 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
144 titan_enable_irq(irq);
145}
146
147static void
148titan_cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity)
149{
150 int cpu;
151
152 for (cpu = 0; cpu < 4; cpu++) {
153 if (cpu_isset(cpu, affinity))
154 titan_cpu_irq_affinity[cpu] |= 1UL << irq;
155 else
156 titan_cpu_irq_affinity[cpu] &= ~(1UL << irq);
157 }
158
159}
160
161static void
162titan_set_irq_affinity(unsigned int irq, cpumask_t affinity)
163{
164 spin_lock(&titan_irq_lock);
165 titan_cpu_set_irq_affinity(irq - 16, affinity);
166 titan_update_irq_hw(titan_cached_irq_mask);
167 spin_unlock(&titan_irq_lock);
168}
169
170static void
171titan_device_interrupt(unsigned long vector, struct pt_regs * regs)
172{
173 printk("titan_device_interrupt: NOT IMPLEMENTED YET!! \n");
174}
175
176static void
177titan_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
178{
179 int irq;
180
181 irq = (vector - 0x800) >> 4;
182 handle_irq(irq, regs);
183}
184
185
186static void __init
187init_titan_irqs(struct hw_interrupt_type * ops, int imin, int imax)
188{
189 long i;
190 for (i = imin; i <= imax; ++i) {
191 irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
192 irq_desc[i].handler = ops;
193 }
194}
195
196static struct hw_interrupt_type titan_irq_type = {
197 .typename = "TITAN",
198 .startup = titan_startup_irq,
199 .shutdown = titan_disable_irq,
200 .enable = titan_enable_irq,
201 .disable = titan_disable_irq,
202 .ack = titan_disable_irq,
203 .end = titan_end_irq,
204 .set_affinity = titan_set_irq_affinity,
205};
206
207static irqreturn_t
208titan_intr_nop(int irq, void *dev_id, struct pt_regs *regs)
209{
210 /*
211 * This is a NOP interrupt handler for the purposes of
212 * event counting -- just return.
213 */
214 return IRQ_HANDLED;
215}
216
217static void __init
218titan_init_irq(void)
219{
220 if (alpha_using_srm && !alpha_mv.device_interrupt)
221 alpha_mv.device_interrupt = titan_srm_device_interrupt;
222 if (!alpha_mv.device_interrupt)
223 alpha_mv.device_interrupt = titan_device_interrupt;
224
225 titan_update_irq_hw(0);
226
227 init_titan_irqs(&titan_irq_type, 16, 63 + 16);
228}
229
230static void __init
231titan_legacy_init_irq(void)
232{
233 /* init the legacy dma controller */
234 outb(0, DMA1_RESET_REG);
235 outb(0, DMA2_RESET_REG);
236 outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
237 outb(0, DMA2_MASK_REG);
238
239 /* init the legacy irq controller */
240 init_i8259a_irqs();
241
242 /* init the titan irqs */
243 titan_init_irq();
244}
245
246void
247titan_dispatch_irqs(u64 mask, struct pt_regs *regs)
248{
249 unsigned long vector;
250
251 /*
252 * Mask down to those interrupts which are enable on this processor
253 */
254 mask &= titan_cpu_irq_affinity[smp_processor_id()];
255
256 /*
257 * Dispatch all requested interrupts
258 */
259 while (mask) {
260 /* convert to SRM vector... priority is <63> -> <0> */
261 __asm__("ctlz %1, %0" : "=r"(vector) : "r"(mask));
262 vector = 63 - vector;
263 mask &= ~(1UL << vector); /* clear it out */
264 vector = 0x900 + (vector << 4); /* convert to SRM vector */
265
266 /* dispatch it */
267 alpha_mv.device_interrupt(vector, regs);
268 }
269}
270
271
272/*
273 * Titan Family
274 */
275static void __init
276titan_late_init(void)
277{
278 /*
279 * Enable the system error interrupts. These interrupts are
280 * all reported to the kernel as machine checks, so the handler
281 * is a nop so it can be called to count the individual events.
282 */
283 request_irq(63+16, titan_intr_nop, SA_INTERRUPT,
284 "CChip Error", NULL);
285 request_irq(62+16, titan_intr_nop, SA_INTERRUPT,
286 "PChip 0 H_Error", NULL);
287 request_irq(61+16, titan_intr_nop, SA_INTERRUPT,
288 "PChip 1 H_Error", NULL);
289 request_irq(60+16, titan_intr_nop, SA_INTERRUPT,
290 "PChip 0 C_Error", NULL);
291 request_irq(59+16, titan_intr_nop, SA_INTERRUPT,
292 "PChip 1 C_Error", NULL);
293
294 /*
295 * Register our error handlers.
296 */
297 titan_register_error_handlers();
298
299 /*
300 * Check if the console left us any error logs.
301 */
302 cdl_check_console_data_log();
303
304}
305
306static int __devinit
307titan_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
308{
309 u8 intline;
310 int irq;
311
312 /* Get the current intline. */
313 pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &intline);
314 irq = intline;
315
316 /* Is it explicitly routed through ISA? */
317 if ((irq & 0xF0) == 0xE0)
318 return irq;
319
320 /* Offset by 16 to make room for ISA interrupts 0 - 15. */
321 return irq + 16;
322}
323
324static void __init
325titan_init_pci(void)
326{
327 /*
328 * This isn't really the right place, but there's some init
329 * that needs to be done after everything is basically up.
330 */
331 titan_late_init();
332
333 pci_probe_only = 1;
334 common_init_pci();
335 SMC669_Init(0);
336#ifdef CONFIG_VGA_HOSE
337 locate_and_init_vga(NULL);
338#endif
339}
340
341
342/*
343 * Privateer
344 */
345static void __init
346privateer_init_pci(void)
347{
348 /*
349 * Hook a couple of extra err interrupts that the
350 * common titan code won't.
351 */
352 request_irq(53+16, titan_intr_nop, SA_INTERRUPT,
353 "NMI", NULL);
354 request_irq(50+16, titan_intr_nop, SA_INTERRUPT,
355 "Temperature Warning", NULL);
356
357 /*
358 * Finish with the common version.
359 */
360 return titan_init_pci();
361}
362
363
364/*
365 * The System Vectors.
366 */
367struct alpha_machine_vector titan_mv __initmv = {
368 .vector_name = "TITAN",
369 DO_EV6_MMU,
370 DO_DEFAULT_RTC,
371 DO_TITAN_IO,
372 .machine_check = titan_machine_check,
373 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
374 .min_io_address = DEFAULT_IO_BASE,
375 .min_mem_address = DEFAULT_MEM_BASE,
376 .pci_dac_offset = TITAN_DAC_OFFSET,
377
378 .nr_irqs = 80, /* 64 + 16 */
379 /* device_interrupt will be filled in by titan_init_irq */
380
381 .agp_info = titan_agp_info,
382
383 .init_arch = titan_init_arch,
384 .init_irq = titan_legacy_init_irq,
385 .init_rtc = common_init_rtc,
386 .init_pci = titan_init_pci,
387
388 .kill_arch = titan_kill_arch,
389 .pci_map_irq = titan_map_irq,
390 .pci_swizzle = common_swizzle,
391};
392ALIAS_MV(titan)
393
394struct alpha_machine_vector privateer_mv __initmv = {
395 .vector_name = "PRIVATEER",
396 DO_EV6_MMU,
397 DO_DEFAULT_RTC,
398 DO_TITAN_IO,
399 .machine_check = privateer_machine_check,
400 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
401 .min_io_address = DEFAULT_IO_BASE,
402 .min_mem_address = DEFAULT_MEM_BASE,
403 .pci_dac_offset = TITAN_DAC_OFFSET,
404
405 .nr_irqs = 80, /* 64 + 16 */
406 /* device_interrupt will be filled in by titan_init_irq */
407
408 .agp_info = titan_agp_info,
409
410 .init_arch = titan_init_arch,
411 .init_irq = titan_legacy_init_irq,
412 .init_rtc = common_init_rtc,
413 .init_pci = privateer_init_pci,
414
415 .kill_arch = titan_kill_arch,
416 .pci_map_irq = titan_map_irq,
417 .pci_swizzle = common_swizzle,
418};
419/* No alpha_mv alias for privateer since we compile it
420 in unconditionally with titan; setup_arch knows how to cope. */
diff --git a/arch/alpha/kernel/sys_wildfire.c b/arch/alpha/kernel/sys_wildfire.c
new file mode 100644
index 000000000000..1553f470246e
--- /dev/null
+++ b/arch/alpha/kernel/sys_wildfire.c
@@ -0,0 +1,361 @@
1/*
2 * linux/arch/alpha/kernel/sys_wildfire.c
3 *
4 * Wildfire support.
5 *
6 * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
7 */
8
9#include <linux/kernel.h>
10#include <linux/types.h>
11#include <linux/mm.h>
12#include <linux/sched.h>
13#include <linux/pci.h>
14#include <linux/init.h>
15#include <linux/bitops.h>
16
17#include <asm/ptrace.h>
18#include <asm/system.h>
19#include <asm/dma.h>
20#include <asm/irq.h>
21#include <asm/mmu_context.h>
22#include <asm/io.h>
23#include <asm/pgtable.h>
24#include <asm/core_wildfire.h>
25#include <asm/hwrpb.h>
26#include <asm/tlbflush.h>
27
28#include "proto.h"
29#include "irq_impl.h"
30#include "pci_impl.h"
31#include "machvec_impl.h"
32
33static unsigned long cached_irq_mask[WILDFIRE_NR_IRQS/(sizeof(long)*8)];
34
35DEFINE_SPINLOCK(wildfire_irq_lock);
36
37static int doing_init_irq_hw = 0;
38
39static void
40wildfire_update_irq_hw(unsigned int irq)
41{
42 int qbbno = (irq >> 8) & (WILDFIRE_MAX_QBB - 1);
43 int pcano = (irq >> 6) & (WILDFIRE_PCA_PER_QBB - 1);
44 wildfire_pca *pca;
45 volatile unsigned long * enable0;
46
47 if (!WILDFIRE_PCA_EXISTS(qbbno, pcano)) {
48 if (!doing_init_irq_hw) {
49 printk(KERN_ERR "wildfire_update_irq_hw:"
50 " got irq %d for non-existent PCA %d"
51 " on QBB %d.\n",
52 irq, pcano, qbbno);
53 }
54 return;
55 }
56
57 pca = WILDFIRE_pca(qbbno, pcano);
58 enable0 = (unsigned long *) &pca->pca_int[0].enable; /* ??? */
59
60 *enable0 = cached_irq_mask[qbbno * WILDFIRE_PCA_PER_QBB + pcano];
61 mb();
62 *enable0;
63}
64
65static void __init
66wildfire_init_irq_hw(void)
67{
68#if 0
69 register wildfire_pca * pca = WILDFIRE_pca(0, 0);
70 volatile unsigned long * enable0, * enable1, * enable2, *enable3;
71 volatile unsigned long * target0, * target1, * target2, *target3;
72
73 enable0 = (unsigned long *) &pca->pca_int[0].enable;
74 enable1 = (unsigned long *) &pca->pca_int[1].enable;
75 enable2 = (unsigned long *) &pca->pca_int[2].enable;
76 enable3 = (unsigned long *) &pca->pca_int[3].enable;
77
78 target0 = (unsigned long *) &pca->pca_int[0].target;
79 target1 = (unsigned long *) &pca->pca_int[1].target;
80 target2 = (unsigned long *) &pca->pca_int[2].target;
81 target3 = (unsigned long *) &pca->pca_int[3].target;
82
83 *enable0 = *enable1 = *enable2 = *enable3 = 0;
84
85 *target0 = (1UL<<8) | WILDFIRE_QBB(0);
86 *target1 = *target2 = *target3 = 0;
87
88 mb();
89
90 *enable0; *enable1; *enable2; *enable3;
91 *target0; *target1; *target2; *target3;
92
93#else
94 int i;
95
96 doing_init_irq_hw = 1;
97
98 /* Need to update only once for every possible PCA. */
99 for (i = 0; i < WILDFIRE_NR_IRQS; i+=WILDFIRE_IRQ_PER_PCA)
100 wildfire_update_irq_hw(i);
101
102 doing_init_irq_hw = 0;
103#endif
104}
105
106static void
107wildfire_enable_irq(unsigned int irq)
108{
109 if (irq < 16)
110 i8259a_enable_irq(irq);
111
112 spin_lock(&wildfire_irq_lock);
113 set_bit(irq, &cached_irq_mask);
114 wildfire_update_irq_hw(irq);
115 spin_unlock(&wildfire_irq_lock);
116}
117
118static void
119wildfire_disable_irq(unsigned int irq)
120{
121 if (irq < 16)
122 i8259a_disable_irq(irq);
123
124 spin_lock(&wildfire_irq_lock);
125 clear_bit(irq, &cached_irq_mask);
126 wildfire_update_irq_hw(irq);
127 spin_unlock(&wildfire_irq_lock);
128}
129
130static void
131wildfire_mask_and_ack_irq(unsigned int irq)
132{
133 if (irq < 16)
134 i8259a_mask_and_ack_irq(irq);
135
136 spin_lock(&wildfire_irq_lock);
137 clear_bit(irq, &cached_irq_mask);
138 wildfire_update_irq_hw(irq);
139 spin_unlock(&wildfire_irq_lock);
140}
141
142static unsigned int
143wildfire_startup_irq(unsigned int irq)
144{
145 wildfire_enable_irq(irq);
146 return 0; /* never anything pending */
147}
148
149static void
150wildfire_end_irq(unsigned int irq)
151{
152#if 0
153 if (!irq_desc[irq].action)
154 printk("got irq %d\n", irq);
155#endif
156 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
157 wildfire_enable_irq(irq);
158}
159
160static struct hw_interrupt_type wildfire_irq_type = {
161 .typename = "WILDFIRE",
162 .startup = wildfire_startup_irq,
163 .shutdown = wildfire_disable_irq,
164 .enable = wildfire_enable_irq,
165 .disable = wildfire_disable_irq,
166 .ack = wildfire_mask_and_ack_irq,
167 .end = wildfire_end_irq,
168};
169
170static void __init
171wildfire_init_irq_per_pca(int qbbno, int pcano)
172{
173 int i, irq_bias;
174 unsigned long io_bias;
175 static struct irqaction isa_enable = {
176 .handler = no_action,
177 .name = "isa_enable",
178 };
179
180 irq_bias = qbbno * (WILDFIRE_PCA_PER_QBB * WILDFIRE_IRQ_PER_PCA)
181 + pcano * WILDFIRE_IRQ_PER_PCA;
182
183 /* Only need the following for first PCI bus per PCA. */
184 io_bias = WILDFIRE_IO(qbbno, pcano<<1) - WILDFIRE_IO_BIAS;
185
186#if 0
187 outb(0, DMA1_RESET_REG + io_bias);
188 outb(0, DMA2_RESET_REG + io_bias);
189 outb(DMA_MODE_CASCADE, DMA2_MODE_REG + io_bias);
190 outb(0, DMA2_MASK_REG + io_bias);
191#endif
192
193#if 0
194 /* ??? Not sure how to do this, yet... */
195 init_i8259a_irqs(); /* ??? */
196#endif
197
198 for (i = 0; i < 16; ++i) {
199 if (i == 2)
200 continue;
201 irq_desc[i+irq_bias].status = IRQ_DISABLED | IRQ_LEVEL;
202 irq_desc[i+irq_bias].handler = &wildfire_irq_type;
203 }
204
205 irq_desc[36+irq_bias].status = IRQ_DISABLED | IRQ_LEVEL;
206 irq_desc[36+irq_bias].handler = &wildfire_irq_type;
207 for (i = 40; i < 64; ++i) {
208 irq_desc[i+irq_bias].status = IRQ_DISABLED | IRQ_LEVEL;
209 irq_desc[i+irq_bias].handler = &wildfire_irq_type;
210 }
211
212 setup_irq(32+irq_bias, &isa_enable);
213}
214
215static void __init
216wildfire_init_irq(void)
217{
218 int qbbno, pcano;
219
220#if 1
221 wildfire_init_irq_hw();
222 init_i8259a_irqs();
223#endif
224
225 for (qbbno = 0; qbbno < WILDFIRE_MAX_QBB; qbbno++) {
226 if (WILDFIRE_QBB_EXISTS(qbbno)) {
227 for (pcano = 0; pcano < WILDFIRE_PCA_PER_QBB; pcano++) {
228 if (WILDFIRE_PCA_EXISTS(qbbno, pcano)) {
229 wildfire_init_irq_per_pca(qbbno, pcano);
230 }
231 }
232 }
233 }
234}
235
236static void
237wildfire_device_interrupt(unsigned long vector, struct pt_regs * regs)
238{
239 int irq;
240
241 irq = (vector - 0x800) >> 4;
242
243 /*
244 * bits 10-8: source QBB ID
245 * bits 7-6: PCA
246 * bits 5-0: irq in PCA
247 */
248
249 handle_irq(irq, regs);
250 return;
251}
252
253/*
254 * PCI Fixup configuration.
255 *
256 * Summary per PCA (2 PCI or HIPPI buses):
257 *
258 * Bit Meaning
259 * 0-15 ISA
260 *
261 *32 ISA summary
262 *33 SMI
263 *34 NMI
264 *36 builtin QLogic SCSI (or slot 0 if no IO module)
265 *40 Interrupt Line A from slot 2 PCI0
266 *41 Interrupt Line B from slot 2 PCI0
267 *42 Interrupt Line C from slot 2 PCI0
268 *43 Interrupt Line D from slot 2 PCI0
269 *44 Interrupt Line A from slot 3 PCI0
270 *45 Interrupt Line B from slot 3 PCI0
271 *46 Interrupt Line C from slot 3 PCI0
272 *47 Interrupt Line D from slot 3 PCI0
273 *
274 *48 Interrupt Line A from slot 4 PCI1
275 *49 Interrupt Line B from slot 4 PCI1
276 *50 Interrupt Line C from slot 4 PCI1
277 *51 Interrupt Line D from slot 4 PCI1
278 *52 Interrupt Line A from slot 5 PCI1
279 *53 Interrupt Line B from slot 5 PCI1
280 *54 Interrupt Line C from slot 5 PCI1
281 *55 Interrupt Line D from slot 5 PCI1
282 *56 Interrupt Line A from slot 6 PCI1
283 *57 Interrupt Line B from slot 6 PCI1
284 *58 Interrupt Line C from slot 6 PCI1
285 *50 Interrupt Line D from slot 6 PCI1
286 *60 Interrupt Line A from slot 7 PCI1
287 *61 Interrupt Line B from slot 7 PCI1
288 *62 Interrupt Line C from slot 7 PCI1
289 *63 Interrupt Line D from slot 7 PCI1
290 *
291 *
292 * IdSel
293 * 0 Cypress Bridge I/O (ISA summary interrupt)
294 * 1 64 bit PCI 0 option slot 1 (SCSI QLogic builtin)
295 * 2 64 bit PCI 0 option slot 2
296 * 3 64 bit PCI 0 option slot 3
297 * 4 64 bit PCI 1 option slot 4
298 * 5 64 bit PCI 1 option slot 5
299 * 6 64 bit PCI 1 option slot 6
300 * 7 64 bit PCI 1 option slot 7
301 */
302
303static int __init
304wildfire_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
305{
306 static char irq_tab[8][5] __initdata = {
307 /*INT INTA INTB INTC INTD */
308 { -1, -1, -1, -1, -1}, /* IdSel 0 ISA Bridge */
309 { 36, 36, 36+1, 36+2, 36+3}, /* IdSel 1 SCSI builtin */
310 { 40, 40, 40+1, 40+2, 40+3}, /* IdSel 2 PCI 0 slot 2 */
311 { 44, 44, 44+1, 44+2, 44+3}, /* IdSel 3 PCI 0 slot 3 */
312 { 48, 48, 48+1, 48+2, 48+3}, /* IdSel 4 PCI 1 slot 4 */
313 { 52, 52, 52+1, 52+2, 52+3}, /* IdSel 5 PCI 1 slot 5 */
314 { 56, 56, 56+1, 56+2, 56+3}, /* IdSel 6 PCI 1 slot 6 */
315 { 60, 60, 60+1, 60+2, 60+3}, /* IdSel 7 PCI 1 slot 7 */
316 };
317 long min_idsel = 0, max_idsel = 7, irqs_per_slot = 5;
318
319 struct pci_controller *hose = dev->sysdata;
320 int irq = COMMON_TABLE_LOOKUP;
321
322 if (irq > 0) {
323 int qbbno = hose->index >> 3;
324 int pcano = (hose->index >> 1) & 3;
325 irq += (qbbno << 8) + (pcano << 6);
326 }
327 return irq;
328}
329
330
331/*
332 * The System Vectors
333 */
334
335struct alpha_machine_vector wildfire_mv __initmv = {
336 .vector_name = "WILDFIRE",
337 DO_EV6_MMU,
338 DO_DEFAULT_RTC,
339 DO_WILDFIRE_IO,
340 .machine_check = wildfire_machine_check,
341 .max_isa_dma_address = ALPHA_MAX_ISA_DMA_ADDRESS,
342 .min_io_address = DEFAULT_IO_BASE,
343 .min_mem_address = DEFAULT_MEM_BASE,
344
345 .nr_irqs = WILDFIRE_NR_IRQS,
346 .device_interrupt = wildfire_device_interrupt,
347
348 .init_arch = wildfire_init_arch,
349 .init_irq = wildfire_init_irq,
350 .init_rtc = common_init_rtc,
351 .init_pci = common_init_pci,
352 .kill_arch = wildfire_kill_arch,
353 .pci_map_irq = wildfire_map_irq,
354 .pci_swizzle = common_swizzle,
355
356 .pa_to_nid = wildfire_pa_to_nid,
357 .cpuid_to_nid = wildfire_cpuid_to_nid,
358 .node_mem_start = wildfire_node_mem_start,
359 .node_mem_size = wildfire_node_mem_size,
360};
361ALIAS_MV(wildfire)
diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S
new file mode 100644
index 000000000000..faab8c2a03eb
--- /dev/null
+++ b/arch/alpha/kernel/systbls.S
@@ -0,0 +1,468 @@
1/*
2 * arch/alpha/kernel/systbls.S
3 *
4 * The system call table.
5 */
6
7#include <linux/config.h> /* CONFIG_OSF4_COMPAT */
8#include <asm/unistd.h>
9
10 .data
11 .align 3
12 .globl sys_call_table
13sys_call_table:
14 .quad alpha_ni_syscall /* 0 */
15 .quad sys_exit
16 .quad sys_fork
17 .quad sys_read
18 .quad sys_write
19 .quad alpha_ni_syscall /* 5 */
20 .quad sys_close
21 .quad osf_wait4
22 .quad alpha_ni_syscall
23 .quad sys_link
24 .quad sys_unlink /* 10 */
25 .quad alpha_ni_syscall
26 .quad sys_chdir
27 .quad sys_fchdir
28 .quad sys_mknod
29 .quad sys_chmod /* 15 */
30 .quad sys_chown
31 .quad osf_brk
32 .quad alpha_ni_syscall
33 .quad sys_lseek
34 .quad sys_getxpid /* 20 */
35 .quad osf_mount
36 .quad sys_umount
37 .quad sys_setuid
38 .quad sys_getxuid
39 .quad alpha_ni_syscall /* 25 */
40 .quad sys_ptrace
41 .quad alpha_ni_syscall
42 .quad alpha_ni_syscall
43 .quad alpha_ni_syscall
44 .quad alpha_ni_syscall /* 30 */
45 .quad alpha_ni_syscall
46 .quad alpha_ni_syscall
47 .quad sys_access
48 .quad alpha_ni_syscall
49 .quad alpha_ni_syscall /* 35 */
50 .quad sys_sync
51 .quad sys_kill
52 .quad alpha_ni_syscall
53 .quad sys_setpgid
54 .quad alpha_ni_syscall /* 40 */
55 .quad sys_dup
56 .quad sys_pipe
57 .quad osf_set_program_attributes
58 .quad alpha_ni_syscall
59 .quad sys_open /* 45 */
60 .quad alpha_ni_syscall
61 .quad sys_getxgid
62 .quad osf_sigprocmask
63 .quad alpha_ni_syscall
64 .quad alpha_ni_syscall /* 50 */
65 .quad sys_acct
66 .quad sys_sigpending
67 .quad alpha_ni_syscall
68 .quad sys_ioctl
69 .quad alpha_ni_syscall /* 55 */
70 .quad alpha_ni_syscall
71 .quad sys_symlink
72 .quad sys_readlink
73 .quad sys_execve
74 .quad sys_umask /* 60 */
75 .quad sys_chroot
76 .quad alpha_ni_syscall
77 .quad sys_getpgrp
78 .quad sys_getpagesize
79 .quad alpha_ni_syscall /* 65 */
80 .quad sys_vfork
81 .quad sys_newstat
82 .quad sys_newlstat
83 .quad alpha_ni_syscall
84 .quad alpha_ni_syscall /* 70 */
85 .quad osf_mmap
86 .quad alpha_ni_syscall
87 .quad sys_munmap
88 .quad sys_mprotect
89 .quad sys_madvise /* 75 */
90 .quad sys_vhangup
91 .quad alpha_ni_syscall
92 .quad alpha_ni_syscall
93 .quad sys_getgroups
94 /* map BSD's setpgrp to sys_setpgid for binary compatibility: */
95 .quad sys_setgroups /* 80 */
96 .quad alpha_ni_syscall
97 .quad sys_setpgid
98 .quad osf_setitimer
99 .quad alpha_ni_syscall
100 .quad alpha_ni_syscall /* 85 */
101 .quad osf_getitimer
102 .quad sys_gethostname
103 .quad sys_sethostname
104 .quad sys_getdtablesize
105 .quad sys_dup2 /* 90 */
106 .quad sys_newfstat
107 .quad sys_fcntl
108 .quad osf_select
109 .quad sys_poll
110 .quad sys_fsync /* 95 */
111 .quad sys_setpriority
112 .quad sys_socket
113 .quad sys_connect
114 .quad sys_accept
115 .quad osf_getpriority /* 100 */
116 .quad sys_send
117 .quad sys_recv
118 .quad sys_sigreturn
119 .quad sys_bind
120 .quad sys_setsockopt /* 105 */
121 .quad sys_listen
122 .quad alpha_ni_syscall
123 .quad alpha_ni_syscall
124 .quad alpha_ni_syscall
125 .quad alpha_ni_syscall /* 110 */
126 .quad sys_sigsuspend
127 .quad osf_sigstack
128 .quad sys_recvmsg
129 .quad sys_sendmsg
130 .quad alpha_ni_syscall /* 115 */
131 .quad osf_gettimeofday
132 .quad osf_getrusage
133 .quad sys_getsockopt
134 .quad alpha_ni_syscall
135#ifdef CONFIG_OSF4_COMPAT
136 .quad osf_readv /* 120 */
137 .quad osf_writev
138#else
139 .quad sys_readv /* 120 */
140 .quad sys_writev
141#endif
142 .quad osf_settimeofday
143 .quad sys_fchown
144 .quad sys_fchmod
145 .quad sys_recvfrom /* 125 */
146 .quad sys_setreuid
147 .quad sys_setregid
148 .quad sys_rename
149 .quad sys_truncate
150 .quad sys_ftruncate /* 130 */
151 .quad sys_flock
152 .quad sys_setgid
153 .quad sys_sendto
154 .quad sys_shutdown
155 .quad sys_socketpair /* 135 */
156 .quad sys_mkdir
157 .quad sys_rmdir
158 .quad osf_utimes
159 .quad alpha_ni_syscall
160 .quad alpha_ni_syscall /* 140 */
161 .quad sys_getpeername
162 .quad alpha_ni_syscall
163 .quad alpha_ni_syscall
164 .quad sys_getrlimit
165 .quad sys_setrlimit /* 145 */
166 .quad alpha_ni_syscall
167 .quad sys_setsid
168 .quad sys_quotactl
169 .quad alpha_ni_syscall
170 .quad sys_getsockname /* 150 */
171 .quad alpha_ni_syscall
172 .quad alpha_ni_syscall
173 .quad alpha_ni_syscall
174 .quad alpha_ni_syscall
175 .quad alpha_ni_syscall /* 155 */
176 .quad osf_sigaction
177 .quad alpha_ni_syscall
178 .quad alpha_ni_syscall
179 .quad osf_getdirentries
180 .quad osf_statfs /* 160 */
181 .quad osf_fstatfs
182 .quad alpha_ni_syscall
183 .quad alpha_ni_syscall
184 .quad alpha_ni_syscall
185 .quad osf_getdomainname /* 165 */
186 .quad sys_setdomainname
187 .quad alpha_ni_syscall
188 .quad alpha_ni_syscall
189 .quad alpha_ni_syscall
190 .quad alpha_ni_syscall /* 170 */
191 .quad alpha_ni_syscall
192 .quad alpha_ni_syscall
193 .quad alpha_ni_syscall
194 .quad alpha_ni_syscall
195 .quad alpha_ni_syscall /* 175 */
196 .quad alpha_ni_syscall
197 .quad alpha_ni_syscall
198 .quad alpha_ni_syscall
199 .quad alpha_ni_syscall
200 .quad alpha_ni_syscall /* 180 */
201 .quad alpha_ni_syscall
202 .quad alpha_ni_syscall
203 .quad alpha_ni_syscall
204 .quad alpha_ni_syscall
205 .quad alpha_ni_syscall /* 185 */
206 .quad alpha_ni_syscall
207 .quad alpha_ni_syscall
208 .quad alpha_ni_syscall
209 .quad alpha_ni_syscall
210 .quad alpha_ni_syscall /* 190 */
211 .quad alpha_ni_syscall
212 .quad alpha_ni_syscall
213 .quad alpha_ni_syscall
214 .quad alpha_ni_syscall
215 .quad alpha_ni_syscall /* 195 */
216 .quad alpha_ni_syscall
217 .quad alpha_ni_syscall
218 .quad alpha_ni_syscall
219 /* The OSF swapon has two extra arguments, but we ignore them. */
220 .quad sys_swapon
221 .quad sys_msgctl /* 200 */
222 .quad sys_msgget
223 .quad sys_msgrcv
224 .quad sys_msgsnd
225 .quad sys_semctl
226 .quad sys_semget /* 205 */
227 .quad sys_semop
228 .quad osf_utsname
229 .quad sys_lchown
230 .quad osf_shmat
231 .quad sys_shmctl /* 210 */
232 .quad sys_shmdt
233 .quad sys_shmget
234 .quad alpha_ni_syscall
235 .quad alpha_ni_syscall
236 .quad alpha_ni_syscall /* 215 */
237 .quad alpha_ni_syscall
238 .quad sys_msync
239 .quad alpha_ni_syscall
240 .quad alpha_ni_syscall
241 .quad alpha_ni_syscall /* 220 */
242 .quad alpha_ni_syscall
243 .quad alpha_ni_syscall
244 .quad alpha_ni_syscall
245 .quad alpha_ni_syscall
246 .quad alpha_ni_syscall /* 225 */
247 .quad alpha_ni_syscall
248 .quad alpha_ni_syscall
249 .quad alpha_ni_syscall
250 .quad alpha_ni_syscall
251 .quad alpha_ni_syscall /* 230 */
252 .quad alpha_ni_syscall
253 .quad alpha_ni_syscall
254 .quad sys_getpgid
255 .quad sys_getsid
256 .quad sys_sigaltstack /* 235 */
257 .quad alpha_ni_syscall
258 .quad alpha_ni_syscall
259 .quad alpha_ni_syscall
260 .quad alpha_ni_syscall
261 .quad alpha_ni_syscall /* 240 */
262 .quad osf_sysinfo
263 .quad alpha_ni_syscall
264 .quad alpha_ni_syscall
265 .quad osf_proplist_syscall
266 .quad alpha_ni_syscall /* 245 */
267 .quad alpha_ni_syscall
268 .quad alpha_ni_syscall
269 .quad alpha_ni_syscall
270 .quad alpha_ni_syscall
271 .quad alpha_ni_syscall /* 250 */
272 .quad osf_usleep_thread
273 .quad alpha_ni_syscall
274 .quad alpha_ni_syscall
275 .quad sys_sysfs
276 .quad alpha_ni_syscall /* 255 */
277 .quad osf_getsysinfo
278 .quad osf_setsysinfo
279 .quad alpha_ni_syscall
280 .quad alpha_ni_syscall
281 .quad alpha_ni_syscall /* 260 */
282 .quad alpha_ni_syscall
283 .quad alpha_ni_syscall
284 .quad alpha_ni_syscall
285 .quad alpha_ni_syscall
286 .quad alpha_ni_syscall /* 265 */
287 .quad alpha_ni_syscall
288 .quad alpha_ni_syscall
289 .quad alpha_ni_syscall
290 .quad alpha_ni_syscall
291 .quad alpha_ni_syscall /* 270 */
292 .quad alpha_ni_syscall
293 .quad alpha_ni_syscall
294 .quad alpha_ni_syscall
295 .quad alpha_ni_syscall
296 .quad alpha_ni_syscall /* 275 */
297 .quad alpha_ni_syscall
298 .quad alpha_ni_syscall
299 .quad alpha_ni_syscall
300 .quad alpha_ni_syscall
301 .quad alpha_ni_syscall /* 280 */
302 .quad alpha_ni_syscall
303 .quad alpha_ni_syscall
304 .quad alpha_ni_syscall
305 .quad alpha_ni_syscall
306 .quad alpha_ni_syscall /* 285 */
307 .quad alpha_ni_syscall
308 .quad alpha_ni_syscall
309 .quad alpha_ni_syscall
310 .quad alpha_ni_syscall
311 .quad alpha_ni_syscall /* 290 */
312 .quad alpha_ni_syscall
313 .quad alpha_ni_syscall
314 .quad alpha_ni_syscall
315 .quad alpha_ni_syscall
316 .quad alpha_ni_syscall /* 295 */
317 .quad alpha_ni_syscall
318 .quad alpha_ni_syscall
319 .quad alpha_ni_syscall
320 .quad alpha_ni_syscall
321/* linux-specific system calls start at 300 */
322 .quad sys_bdflush /* 300 */
323 .quad sys_sethae
324 .quad sys_mount
325 .quad sys_old_adjtimex
326 .quad sys_swapoff
327 .quad sys_getdents /* 305 */
328 .quad sys_ni_syscall /* 306: old create_module */
329 .quad sys_init_module
330 .quad sys_delete_module
331 .quad sys_ni_syscall /* 309: old get_kernel_syms */
332 .quad sys_syslog /* 310 */
333 .quad sys_reboot
334 .quad sys_clone
335 .quad sys_uselib
336 .quad sys_mlock
337 .quad sys_munlock /* 315 */
338 .quad sys_mlockall
339 .quad sys_munlockall
340 .quad sys_sysinfo
341 .quad sys_sysctl
342 .quad sys_ni_syscall /* 320 */
343 .quad sys_oldumount
344 .quad sys_swapon
345 .quad sys_times
346 .quad sys_personality
347 .quad sys_setfsuid /* 325 */
348 .quad sys_setfsgid
349 .quad sys_ustat
350 .quad sys_statfs
351 .quad sys_fstatfs
352 .quad sys_sched_setparam /* 330 */
353 .quad sys_sched_getparam
354 .quad sys_sched_setscheduler
355 .quad sys_sched_getscheduler
356 .quad sys_sched_yield
357 .quad sys_sched_get_priority_max /* 335 */
358 .quad sys_sched_get_priority_min
359 .quad sys_sched_rr_get_interval
360 .quad sys_ni_syscall /* sys_afs_syscall */
361 .quad sys_newuname
362 .quad sys_nanosleep /* 340 */
363 .quad sys_mremap
364 .quad sys_nfsservctl
365 .quad sys_setresuid
366 .quad sys_getresuid
367 .quad sys_pciconfig_read /* 345 */
368 .quad sys_pciconfig_write
369 .quad sys_ni_syscall /* 347: old query_module */
370 .quad sys_prctl
371 .quad sys_pread64
372 .quad sys_pwrite64 /* 350 */
373 .quad sys_rt_sigreturn
374 .quad sys_rt_sigaction
375 .quad sys_rt_sigprocmask
376 .quad sys_rt_sigpending
377 .quad sys_rt_sigtimedwait /* 355 */
378 .quad sys_rt_sigqueueinfo
379 .quad sys_rt_sigsuspend
380 .quad sys_select
381 .quad sys_gettimeofday
382 .quad sys_settimeofday /* 360 */
383 .quad sys_getitimer
384 .quad sys_setitimer
385 .quad sys_utimes
386 .quad sys_getrusage
387 .quad sys_wait4 /* 365 */
388 .quad sys_adjtimex
389 .quad sys_getcwd
390 .quad sys_capget
391 .quad sys_capset
392 .quad sys_sendfile64 /* 370 */
393 .quad sys_setresgid
394 .quad sys_getresgid
395 .quad sys_ni_syscall /* sys_dipc */
396 .quad sys_pivot_root
397 .quad sys_mincore /* 375 */
398 .quad sys_pciconfig_iobase
399 .quad sys_getdents64
400 .quad sys_gettid
401 .quad sys_readahead
402 .quad sys_ni_syscall /* 380 */
403 .quad sys_tkill
404 .quad sys_setxattr
405 .quad sys_lsetxattr
406 .quad sys_fsetxattr
407 .quad sys_getxattr /* 385 */
408 .quad sys_lgetxattr
409 .quad sys_fgetxattr
410 .quad sys_listxattr
411 .quad sys_llistxattr
412 .quad sys_flistxattr /* 390 */
413 .quad sys_removexattr
414 .quad sys_lremovexattr
415 .quad sys_fremovexattr
416 .quad sys_futex
417 .quad sys_sched_setaffinity /* 395 */
418 .quad sys_sched_getaffinity
419 .quad sys_ni_syscall /* 397, tux */
420 .quad sys_io_setup
421 .quad sys_io_destroy
422 .quad sys_io_getevents /* 400 */
423 .quad sys_io_submit
424 .quad sys_io_cancel
425 .quad sys_ni_syscall /* 403, sys_alloc_hugepages */
426 .quad sys_ni_syscall /* 404, sys_free_hugepages */
427 .quad sys_exit_group /* 405 */
428 .quad sys_lookup_dcookie
429 .quad sys_epoll_create
430 .quad sys_epoll_ctl
431 .quad sys_epoll_wait
432 .quad sys_remap_file_pages /* 410 */
433 .quad sys_set_tid_address
434 .quad sys_restart_syscall
435 .quad sys_fadvise64
436 .quad sys_timer_create
437 .quad sys_timer_settime /* 415 */
438 .quad sys_timer_gettime
439 .quad sys_timer_getoverrun
440 .quad sys_timer_delete
441 .quad sys_clock_settime
442 .quad sys_clock_gettime /* 420 */
443 .quad sys_clock_getres
444 .quad sys_clock_nanosleep
445 .quad sys_semtimedop
446 .quad sys_tgkill
447 .quad sys_stat64 /* 425 */
448 .quad sys_lstat64
449 .quad sys_fstat64
450 .quad sys_ni_syscall /* sys_vserver */
451 .quad sys_ni_syscall /* sys_mbind */
452 .quad sys_ni_syscall /* sys_get_mempolicy */
453 .quad sys_ni_syscall /* sys_set_mempolicy */
454 .quad sys_mq_open
455 .quad sys_mq_unlink
456 .quad sys_mq_timedsend
457 .quad sys_mq_timedreceive /* 435 */
458 .quad sys_mq_notify
459 .quad sys_mq_getsetattr
460 .quad sys_waitid
461
462 .size sys_call_table, . - sys_call_table
463 .type sys_call_table, @object
464
465/* Remember to update everything, kids. */
466.ifne (. - sys_call_table) - (NR_SYSCALLS * 8)
467.err
468.endif
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
new file mode 100644
index 000000000000..8226c5cd788c
--- /dev/null
+++ b/arch/alpha/kernel/time.c
@@ -0,0 +1,591 @@
1/*
2 * linux/arch/alpha/kernel/time.c
3 *
4 * Copyright (C) 1991, 1992, 1995, 1999, 2000 Linus Torvalds
5 *
6 * This file contains the PC-specific time handling details:
7 * reading the RTC at bootup, etc..
8 * 1994-07-02 Alan Modra
9 * fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
10 * 1995-03-26 Markus Kuhn
11 * fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887
12 * precision CMOS clock update
13 * 1997-09-10 Updated NTP code according to technical memorandum Jan '96
14 * "A Kernel Model for Precision Timekeeping" by Dave Mills
15 * 1997-01-09 Adrian Sun
16 * use interval timer if CONFIG_RTC=y
17 * 1997-10-29 John Bowman (bowman@math.ualberta.ca)
18 * fixed tick loss calculation in timer_interrupt
19 * (round system clock to nearest tick instead of truncating)
20 * fixed algorithm in time_init for getting time from CMOS clock
21 * 1999-04-16 Thorsten Kranzkowski (dl8bcu@gmx.net)
22 * fixed algorithm in do_gettimeofday() for calculating the precise time
23 * from processor cycle counter (now taking lost_ticks into account)
24 * 2000-08-13 Jan-Benedict Glaw <jbglaw@lug-owl.de>
25 * Fixed time_init to be aware of epoches != 1900. This prevents
26 * booting up in 2048 for me;) Code is stolen from rtc.c.
27 * 2003-06-03 R. Scott Bailey <scott.bailey@eds.com>
28 * Tighten sanity in time_init from 1% (10,000 PPM) to 250 PPM
29 */
30#include <linux/config.h>
31#include <linux/errno.h>
32#include <linux/module.h>
33#include <linux/sched.h>
34#include <linux/kernel.h>
35#include <linux/param.h>
36#include <linux/string.h>
37#include <linux/mm.h>
38#include <linux/delay.h>
39#include <linux/ioport.h>
40#include <linux/irq.h>
41#include <linux/interrupt.h>
42#include <linux/init.h>
43#include <linux/bcd.h>
44#include <linux/profile.h>
45
46#include <asm/uaccess.h>
47#include <asm/io.h>
48#include <asm/hwrpb.h>
49#include <asm/8253pit.h>
50
51#include <linux/mc146818rtc.h>
52#include <linux/time.h>
53#include <linux/timex.h>
54
55#include "proto.h"
56#include "irq_impl.h"
57
58u64 jiffies_64 = INITIAL_JIFFIES;
59
60EXPORT_SYMBOL(jiffies_64);
61
62extern unsigned long wall_jiffies; /* kernel/timer.c */
63
64static int set_rtc_mmss(unsigned long);
65
66DEFINE_SPINLOCK(rtc_lock);
67
68#define TICK_SIZE (tick_nsec / 1000)
69
70/*
71 * Shift amount by which scaled_ticks_per_cycle is scaled. Shifting
72 * by 48 gives us 16 bits for HZ while keeping the accuracy good even
73 * for large CPU clock rates.
74 */
75#define FIX_SHIFT 48
76
77/* lump static variables together for more efficient access: */
78static struct {
79 /* cycle counter last time it got invoked */
80 __u32 last_time;
81 /* ticks/cycle * 2^48 */
82 unsigned long scaled_ticks_per_cycle;
83 /* last time the CMOS clock got updated */
84 time_t last_rtc_update;
85 /* partial unused tick */
86 unsigned long partial_tick;
87} state;
88
89unsigned long est_cycle_freq;
90
91
92static inline __u32 rpcc(void)
93{
94 __u32 result;
95 asm volatile ("rpcc %0" : "=r"(result));
96 return result;
97}
98
99/*
100 * Scheduler clock - returns current time in nanosec units.
101 *
102 * Copied from ARM code for expediency... ;-}
103 */
104unsigned long long sched_clock(void)
105{
106 return (unsigned long long)jiffies * (1000000000 / HZ);
107}
108
109
110/*
111 * timer_interrupt() needs to keep up the real-time clock,
112 * as well as call the "do_timer()" routine every clocktick
113 */
114irqreturn_t timer_interrupt(int irq, void *dev, struct pt_regs * regs)
115{
116 unsigned long delta;
117 __u32 now;
118 long nticks;
119
120#ifndef CONFIG_SMP
121 /* Not SMP, do kernel PC profiling here. */
122 profile_tick(CPU_PROFILING, regs);
123#endif
124
125 write_seqlock(&xtime_lock);
126
127 /*
128 * Calculate how many ticks have passed since the last update,
129 * including any previous partial leftover. Save any resulting
130 * fraction for the next pass.
131 */
132 now = rpcc();
133 delta = now - state.last_time;
134 state.last_time = now;
135 delta = delta * state.scaled_ticks_per_cycle + state.partial_tick;
136 state.partial_tick = delta & ((1UL << FIX_SHIFT) - 1);
137 nticks = delta >> FIX_SHIFT;
138
139 while (nticks > 0) {
140 do_timer(regs);
141#ifndef CONFIG_SMP
142 update_process_times(user_mode(regs));
143#endif
144 nticks--;
145 }
146
147 /*
148 * If we have an externally synchronized Linux clock, then update
149 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
150 * called as close as possible to 500 ms before the new second starts.
151 */
152 if ((time_status & STA_UNSYNC) == 0
153 && xtime.tv_sec > state.last_rtc_update + 660
154 && xtime.tv_nsec >= 500000 - ((unsigned) TICK_SIZE) / 2
155 && xtime.tv_nsec <= 500000 + ((unsigned) TICK_SIZE) / 2) {
156 int tmp = set_rtc_mmss(xtime.tv_sec);
157 state.last_rtc_update = xtime.tv_sec - (tmp ? 600 : 0);
158 }
159
160 write_sequnlock(&xtime_lock);
161 return IRQ_HANDLED;
162}
163
164void
165common_init_rtc(void)
166{
167 unsigned char x;
168
169 /* Reset periodic interrupt frequency. */
170 x = CMOS_READ(RTC_FREQ_SELECT) & 0x3f;
171 /* Test includes known working values on various platforms
172 where 0x26 is wrong; we refuse to change those. */
173 if (x != 0x26 && x != 0x25 && x != 0x19 && x != 0x06) {
174 printk("Setting RTC_FREQ to 1024 Hz (%x)\n", x);
175 CMOS_WRITE(0x26, RTC_FREQ_SELECT);
176 }
177
178 /* Turn on periodic interrupts. */
179 x = CMOS_READ(RTC_CONTROL);
180 if (!(x & RTC_PIE)) {
181 printk("Turning on RTC interrupts.\n");
182 x |= RTC_PIE;
183 x &= ~(RTC_AIE | RTC_UIE);
184 CMOS_WRITE(x, RTC_CONTROL);
185 }
186 (void) CMOS_READ(RTC_INTR_FLAGS);
187
188 outb(0x36, 0x43); /* pit counter 0: system timer */
189 outb(0x00, 0x40);
190 outb(0x00, 0x40);
191
192 outb(0xb6, 0x43); /* pit counter 2: speaker */
193 outb(0x31, 0x42);
194 outb(0x13, 0x42);
195
196 init_rtc_irq();
197}
198
199
200/* Validate a computed cycle counter result against the known bounds for
201 the given processor core. There's too much brokenness in the way of
202 timing hardware for any one method to work everywhere. :-(
203
204 Return 0 if the result cannot be trusted, otherwise return the argument. */
205
206static unsigned long __init
207validate_cc_value(unsigned long cc)
208{
209 static struct bounds {
210 unsigned int min, max;
211 } cpu_hz[] __initdata = {
212 [EV3_CPU] = { 50000000, 200000000 }, /* guess */
213 [EV4_CPU] = { 100000000, 300000000 },
214 [LCA4_CPU] = { 100000000, 300000000 }, /* guess */
215 [EV45_CPU] = { 200000000, 300000000 },
216 [EV5_CPU] = { 250000000, 433000000 },
217 [EV56_CPU] = { 333000000, 667000000 },
218 [PCA56_CPU] = { 400000000, 600000000 }, /* guess */
219 [PCA57_CPU] = { 500000000, 600000000 }, /* guess */
220 [EV6_CPU] = { 466000000, 600000000 },
221 [EV67_CPU] = { 600000000, 750000000 },
222 [EV68AL_CPU] = { 750000000, 940000000 },
223 [EV68CB_CPU] = { 1000000000, 1333333333 },
224 /* None of the following are shipping as of 2001-11-01. */
225 [EV68CX_CPU] = { 1000000000, 1700000000 }, /* guess */
226 [EV69_CPU] = { 1000000000, 1700000000 }, /* guess */
227 [EV7_CPU] = { 800000000, 1400000000 }, /* guess */
228 [EV79_CPU] = { 1000000000, 2000000000 }, /* guess */
229 };
230
231 /* Allow for some drift in the crystal. 10MHz is more than enough. */
232 const unsigned int deviation = 10000000;
233
234 struct percpu_struct *cpu;
235 unsigned int index;
236
237 cpu = (struct percpu_struct *)((char*)hwrpb + hwrpb->processor_offset);
238 index = cpu->type & 0xffffffff;
239
240 /* If index out of bounds, no way to validate. */
241 if (index >= sizeof(cpu_hz)/sizeof(cpu_hz[0]))
242 return cc;
243
244 /* If index contains no data, no way to validate. */
245 if (cpu_hz[index].max == 0)
246 return cc;
247
248 if (cc < cpu_hz[index].min - deviation
249 || cc > cpu_hz[index].max + deviation)
250 return 0;
251
252 return cc;
253}
254
255
256/*
257 * Calibrate CPU clock using legacy 8254 timer/counter. Stolen from
258 * arch/i386/time.c.
259 */
260
261#define CALIBRATE_LATCH 0xffff
262#define TIMEOUT_COUNT 0x100000
263
264static unsigned long __init
265calibrate_cc_with_pit(void)
266{
267 int cc, count = 0;
268
269 /* Set the Gate high, disable speaker */
270 outb((inb(0x61) & ~0x02) | 0x01, 0x61);
271
272 /*
273 * Now let's take care of CTC channel 2
274 *
275 * Set the Gate high, program CTC channel 2 for mode 0,
276 * (interrupt on terminal count mode), binary count,
277 * load 5 * LATCH count, (LSB and MSB) to begin countdown.
278 */
279 outb(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */
280 outb(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */
281 outb(CALIBRATE_LATCH >> 8, 0x42); /* MSB of count */
282
283 cc = rpcc();
284 do {
285 count++;
286 } while ((inb(0x61) & 0x20) == 0 && count < TIMEOUT_COUNT);
287 cc = rpcc() - cc;
288
289 /* Error: ECTCNEVERSET or ECPUTOOFAST. */
290 if (count <= 1 || count == TIMEOUT_COUNT)
291 return 0;
292
293 return ((long)cc * PIT_TICK_RATE) / (CALIBRATE_LATCH + 1);
294}
295
296/* The Linux interpretation of the CMOS clock register contents:
297 When the Update-In-Progress (UIP) flag goes from 1 to 0, the
298 RTC registers show the second which has precisely just started.
299 Let's hope other operating systems interpret the RTC the same way. */
300
301static unsigned long __init
302rpcc_after_update_in_progress(void)
303{
304 do { } while (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP));
305 do { } while (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
306
307 return rpcc();
308}
309
310void __init
311time_init(void)
312{
313 unsigned int year, mon, day, hour, min, sec, cc1, cc2, epoch;
314 unsigned long cycle_freq, tolerance;
315 long diff;
316
317 /* Calibrate CPU clock -- attempt #1. */
318 if (!est_cycle_freq)
319 est_cycle_freq = validate_cc_value(calibrate_cc_with_pit());
320
321 cc1 = rpcc_after_update_in_progress();
322
323 /* Calibrate CPU clock -- attempt #2. */
324 if (!est_cycle_freq) {
325 cc2 = rpcc_after_update_in_progress();
326 est_cycle_freq = validate_cc_value(cc2 - cc1);
327 cc1 = cc2;
328 }
329
330 cycle_freq = hwrpb->cycle_freq;
331 if (est_cycle_freq) {
332 /* If the given value is within 250 PPM of what we calculated,
333 accept it. Otherwise, use what we found. */
334 tolerance = cycle_freq / 4000;
335 diff = cycle_freq - est_cycle_freq;
336 if (diff < 0)
337 diff = -diff;
338 if ((unsigned long)diff > tolerance) {
339 cycle_freq = est_cycle_freq;
340 printk("HWRPB cycle frequency bogus. "
341 "Estimated %lu Hz\n", cycle_freq);
342 } else {
343 est_cycle_freq = 0;
344 }
345 } else if (! validate_cc_value (cycle_freq)) {
346 printk("HWRPB cycle frequency bogus, "
347 "and unable to estimate a proper value!\n");
348 }
349
350 /* From John Bowman <bowman@math.ualberta.ca>: allow the values
351 to settle, as the Update-In-Progress bit going low isn't good
352 enough on some hardware. 2ms is our guess; we haven't found
353 bogomips yet, but this is close on a 500Mhz box. */
354 __delay(1000000);
355
356 sec = CMOS_READ(RTC_SECONDS);
357 min = CMOS_READ(RTC_MINUTES);
358 hour = CMOS_READ(RTC_HOURS);
359 day = CMOS_READ(RTC_DAY_OF_MONTH);
360 mon = CMOS_READ(RTC_MONTH);
361 year = CMOS_READ(RTC_YEAR);
362
363 if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
364 BCD_TO_BIN(sec);
365 BCD_TO_BIN(min);
366 BCD_TO_BIN(hour);
367 BCD_TO_BIN(day);
368 BCD_TO_BIN(mon);
369 BCD_TO_BIN(year);
370 }
371
372 /* PC-like is standard; used for year >= 70 */
373 epoch = 1900;
374 if (year < 20)
375 epoch = 2000;
376 else if (year >= 20 && year < 48)
377 /* NT epoch */
378 epoch = 1980;
379 else if (year >= 48 && year < 70)
380 /* Digital UNIX epoch */
381 epoch = 1952;
382
383 printk(KERN_INFO "Using epoch = %d\n", epoch);
384
385 if ((year += epoch) < 1970)
386 year += 100;
387
388 xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
389 xtime.tv_nsec = 0;
390
391 wall_to_monotonic.tv_sec -= xtime.tv_sec;
392 wall_to_monotonic.tv_nsec = 0;
393
394 if (HZ > (1<<16)) {
395 extern void __you_loose (void);
396 __you_loose();
397 }
398
399 state.last_time = cc1;
400 state.scaled_ticks_per_cycle
401 = ((unsigned long) HZ << FIX_SHIFT) / cycle_freq;
402 state.last_rtc_update = 0;
403 state.partial_tick = 0L;
404
405 /* Startup the timer source. */
406 alpha_mv.init_rtc();
407}
408
409/*
410 * Use the cycle counter to estimate an displacement from the last time
411 * tick. Unfortunately the Alpha designers made only the low 32-bits of
412 * the cycle counter active, so we overflow on 8.2 seconds on a 500MHz
413 * part. So we can't do the "find absolute time in terms of cycles" thing
414 * that the other ports do.
415 */
416void
417do_gettimeofday(struct timeval *tv)
418{
419 unsigned long flags;
420 unsigned long sec, usec, lost, seq;
421 unsigned long delta_cycles, delta_usec, partial_tick;
422
423 do {
424 seq = read_seqbegin_irqsave(&xtime_lock, flags);
425
426 delta_cycles = rpcc() - state.last_time;
427 sec = xtime.tv_sec;
428 usec = (xtime.tv_nsec / 1000);
429 partial_tick = state.partial_tick;
430 lost = jiffies - wall_jiffies;
431
432 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
433
434#ifdef CONFIG_SMP
435 /* Until and unless we figure out how to get cpu cycle counters
436 in sync and keep them there, we can't use the rpcc tricks. */
437 delta_usec = lost * (1000000 / HZ);
438#else
439 /*
440 * usec = cycles * ticks_per_cycle * 2**48 * 1e6 / (2**48 * ticks)
441 * = cycles * (s_t_p_c) * 1e6 / (2**48 * ticks)
442 * = cycles * (s_t_p_c) * 15625 / (2**42 * ticks)
443 *
444 * which, given a 600MHz cycle and a 1024Hz tick, has a
445 * dynamic range of about 1.7e17, which is less than the
446 * 1.8e19 in an unsigned long, so we are safe from overflow.
447 *
448 * Round, but with .5 up always, since .5 to even is harder
449 * with no clear gain.
450 */
451
452 delta_usec = (delta_cycles * state.scaled_ticks_per_cycle
453 + partial_tick
454 + (lost << FIX_SHIFT)) * 15625;
455 delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2;
456#endif
457
458 usec += delta_usec;
459 if (usec >= 1000000) {
460 sec += 1;
461 usec -= 1000000;
462 }
463
464 tv->tv_sec = sec;
465 tv->tv_usec = usec;
466}
467
468EXPORT_SYMBOL(do_gettimeofday);
469
470int
471do_settimeofday(struct timespec *tv)
472{
473 time_t wtm_sec, sec = tv->tv_sec;
474 long wtm_nsec, nsec = tv->tv_nsec;
475 unsigned long delta_nsec;
476
477 if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
478 return -EINVAL;
479
480 write_seqlock_irq(&xtime_lock);
481
482 /* The offset that is added into time in do_gettimeofday above
483 must be subtracted out here to keep a coherent view of the
484 time. Without this, a full-tick error is possible. */
485
486#ifdef CONFIG_SMP
487 delta_nsec = (jiffies - wall_jiffies) * (NSEC_PER_SEC / HZ);
488#else
489 delta_nsec = rpcc() - state.last_time;
490 delta_nsec = (delta_nsec * state.scaled_ticks_per_cycle
491 + state.partial_tick
492 + ((jiffies - wall_jiffies) << FIX_SHIFT)) * 15625;
493 delta_nsec = ((delta_nsec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2;
494 delta_nsec *= 1000;
495#endif
496
497 nsec -= delta_nsec;
498
499 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
500 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
501
502 set_normalized_timespec(&xtime, sec, nsec);
503 set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
504
505 time_adjust = 0; /* stop active adjtime() */
506 time_status |= STA_UNSYNC;
507 time_maxerror = NTP_PHASE_LIMIT;
508 time_esterror = NTP_PHASE_LIMIT;
509
510 write_sequnlock_irq(&xtime_lock);
511 clock_was_set();
512 return 0;
513}
514
515EXPORT_SYMBOL(do_settimeofday);
516
517
518/*
519 * In order to set the CMOS clock precisely, set_rtc_mmss has to be
520 * called 500 ms after the second nowtime has started, because when
521 * nowtime is written into the registers of the CMOS clock, it will
522 * jump to the next second precisely 500 ms later. Check the Motorola
523 * MC146818A or Dallas DS12887 data sheet for details.
524 *
525 * BUG: This routine does not handle hour overflow properly; it just
526 * sets the minutes. Usually you won't notice until after reboot!
527 */
528
529
530static int
531set_rtc_mmss(unsigned long nowtime)
532{
533 int retval = 0;
534 int real_seconds, real_minutes, cmos_minutes;
535 unsigned char save_control, save_freq_select;
536
537 /* irq are locally disabled here */
538 spin_lock(&rtc_lock);
539 /* Tell the clock it's being set */
540 save_control = CMOS_READ(RTC_CONTROL);
541 CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
542
543 /* Stop and reset prescaler */
544 save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
545 CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
546
547 cmos_minutes = CMOS_READ(RTC_MINUTES);
548 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
549 BCD_TO_BIN(cmos_minutes);
550
551 /*
552 * since we're only adjusting minutes and seconds,
553 * don't interfere with hour overflow. This avoids
554 * messing with unknown time zones but requires your
555 * RTC not to be off by more than 15 minutes
556 */
557 real_seconds = nowtime % 60;
558 real_minutes = nowtime / 60;
559 if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) {
560 /* correct for half hour time zone */
561 real_minutes += 30;
562 }
563 real_minutes %= 60;
564
565 if (abs(real_minutes - cmos_minutes) < 30) {
566 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
567 BIN_TO_BCD(real_seconds);
568 BIN_TO_BCD(real_minutes);
569 }
570 CMOS_WRITE(real_seconds,RTC_SECONDS);
571 CMOS_WRITE(real_minutes,RTC_MINUTES);
572 } else {
573 printk(KERN_WARNING
574 "set_rtc_mmss: can't update from %d to %d\n",
575 cmos_minutes, real_minutes);
576 retval = -1;
577 }
578
579 /* The following flags have to be released exactly in this order,
580 * otherwise the DS12887 (popular MC146818A clone with integrated
581 * battery and quartz) will not reset the oscillator and will not
582 * update precisely 500 ms later. You won't find this mentioned in
583 * the Dallas Semiconductor data sheets, but who believes data
584 * sheets anyway ... -- Markus Kuhn
585 */
586 CMOS_WRITE(save_control, RTC_CONTROL);
587 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
588 spin_unlock(&rtc_lock);
589
590 return retval;
591}
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
new file mode 100644
index 000000000000..fd7bd17cc960
--- /dev/null
+++ b/arch/alpha/kernel/traps.c
@@ -0,0 +1,1092 @@
1/*
2 * arch/alpha/kernel/traps.c
3 *
4 * (C) Copyright 1994 Linus Torvalds
5 */
6
7/*
8 * This file initializes the trap entry points
9 */
10
11#include <linux/config.h>
12#include <linux/mm.h>
13#include <linux/sched.h>
14#include <linux/tty.h>
15#include <linux/delay.h>
16#include <linux/smp_lock.h>
17#include <linux/module.h>
18#include <linux/init.h>
19#include <linux/kallsyms.h>
20
21#include <asm/gentrap.h>
22#include <asm/uaccess.h>
23#include <asm/unaligned.h>
24#include <asm/sysinfo.h>
25#include <asm/hwrpb.h>
26#include <asm/mmu_context.h>
27
28#include "proto.h"
29
30/* Work-around for some SRMs which mishandle opDEC faults. */
31
32static int opDEC_fix;
33
34static void __init
35opDEC_check(void)
36{
37 __asm__ __volatile__ (
38 /* Load the address of... */
39 " br $16, 1f\n"
40 /* A stub instruction fault handler. Just add 4 to the
41 pc and continue. */
42 " ldq $16, 8($sp)\n"
43 " addq $16, 4, $16\n"
44 " stq $16, 8($sp)\n"
45 " call_pal %[rti]\n"
46 /* Install the instruction fault handler. */
47 "1: lda $17, 3\n"
48 " call_pal %[wrent]\n"
49 /* With that in place, the fault from the round-to-minf fp
50 insn will arrive either at the "lda 4" insn (bad) or one
51 past that (good). This places the correct fixup in %0. */
52 " lda %[fix], 0\n"
53 " cvttq/svm $f31,$f31\n"
54 " lda %[fix], 4"
55 : [fix] "=r" (opDEC_fix)
56 : [rti] "n" (PAL_rti), [wrent] "n" (PAL_wrent)
57 : "$0", "$1", "$16", "$17", "$22", "$23", "$24", "$25");
58
59 if (opDEC_fix)
60 printk("opDEC fixup enabled.\n");
61}
62
63void
64dik_show_regs(struct pt_regs *regs, unsigned long *r9_15)
65{
66 printk("pc = [<%016lx>] ra = [<%016lx>] ps = %04lx %s\n",
67 regs->pc, regs->r26, regs->ps, print_tainted());
68 print_symbol("pc is at %s\n", regs->pc);
69 print_symbol("ra is at %s\n", regs->r26 );
70 printk("v0 = %016lx t0 = %016lx t1 = %016lx\n",
71 regs->r0, regs->r1, regs->r2);
72 printk("t2 = %016lx t3 = %016lx t4 = %016lx\n",
73 regs->r3, regs->r4, regs->r5);
74 printk("t5 = %016lx t6 = %016lx t7 = %016lx\n",
75 regs->r6, regs->r7, regs->r8);
76
77 if (r9_15) {
78 printk("s0 = %016lx s1 = %016lx s2 = %016lx\n",
79 r9_15[9], r9_15[10], r9_15[11]);
80 printk("s3 = %016lx s4 = %016lx s5 = %016lx\n",
81 r9_15[12], r9_15[13], r9_15[14]);
82 printk("s6 = %016lx\n", r9_15[15]);
83 }
84
85 printk("a0 = %016lx a1 = %016lx a2 = %016lx\n",
86 regs->r16, regs->r17, regs->r18);
87 printk("a3 = %016lx a4 = %016lx a5 = %016lx\n",
88 regs->r19, regs->r20, regs->r21);
89 printk("t8 = %016lx t9 = %016lx t10= %016lx\n",
90 regs->r22, regs->r23, regs->r24);
91 printk("t11= %016lx pv = %016lx at = %016lx\n",
92 regs->r25, regs->r27, regs->r28);
93 printk("gp = %016lx sp = %p\n", regs->gp, regs+1);
94#if 0
95__halt();
96#endif
97}
98
99#if 0
100static char * ireg_name[] = {"v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6",
101 "t7", "s0", "s1", "s2", "s3", "s4", "s5", "s6",
102 "a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9",
103 "t10", "t11", "ra", "pv", "at", "gp", "sp", "zero"};
104#endif
105
106static void
107dik_show_code(unsigned int *pc)
108{
109 long i;
110
111 printk("Code:");
112 for (i = -6; i < 2; i++) {
113 unsigned int insn;
114 if (__get_user(insn, (unsigned int __user *)pc + i))
115 break;
116 printk("%c%08x%c", i ? ' ' : '<', insn, i ? ' ' : '>');
117 }
118 printk("\n");
119}
120
121static void
122dik_show_trace(unsigned long *sp)
123{
124 long i = 0;
125 printk("Trace:\n");
126 while (0x1ff8 & (unsigned long) sp) {
127 extern char _stext[], _etext[];
128 unsigned long tmp = *sp;
129 sp++;
130 if (tmp < (unsigned long) &_stext)
131 continue;
132 if (tmp >= (unsigned long) &_etext)
133 continue;
134 printk("[<%lx>]", tmp);
135 print_symbol(" %s", tmp);
136 printk("\n");
137 if (i > 40) {
138 printk(" ...");
139 break;
140 }
141 }
142 printk("\n");
143}
144
145static int kstack_depth_to_print = 24;
146
147void show_stack(struct task_struct *task, unsigned long *sp)
148{
149 unsigned long *stack;
150 int i;
151
152 /*
153 * debugging aid: "show_stack(NULL);" prints the
154 * back trace for this cpu.
155 */
156 if(sp==NULL)
157 sp=(unsigned long*)&sp;
158
159 stack = sp;
160 for(i=0; i < kstack_depth_to_print; i++) {
161 if (((long) stack & (THREAD_SIZE-1)) == 0)
162 break;
163 if (i && ((i % 4) == 0))
164 printk("\n ");
165 printk("%016lx ", *stack++);
166 }
167 printk("\n");
168 dik_show_trace(sp);
169}
170
171void dump_stack(void)
172{
173 show_stack(NULL, NULL);
174}
175
176EXPORT_SYMBOL(dump_stack);
177
178void
179die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15)
180{
181 if (regs->ps & 8)
182 return;
183#ifdef CONFIG_SMP
184 printk("CPU %d ", hard_smp_processor_id());
185#endif
186 printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err);
187 dik_show_regs(regs, r9_15);
188 dik_show_trace((unsigned long *)(regs+1));
189 dik_show_code((unsigned int *)regs->pc);
190
191 if (test_and_set_thread_flag (TIF_DIE_IF_KERNEL)) {
192 printk("die_if_kernel recursion detected.\n");
193 local_irq_enable();
194 while (1);
195 }
196 do_exit(SIGSEGV);
197}
198
199#ifndef CONFIG_MATHEMU
200static long dummy_emul(void) { return 0; }
201long (*alpha_fp_emul_imprecise)(struct pt_regs *regs, unsigned long writemask)
202 = (void *)dummy_emul;
203long (*alpha_fp_emul) (unsigned long pc)
204 = (void *)dummy_emul;
205#else
206long alpha_fp_emul_imprecise(struct pt_regs *regs, unsigned long writemask);
207long alpha_fp_emul (unsigned long pc);
208#endif
209
210asmlinkage void
211do_entArith(unsigned long summary, unsigned long write_mask,
212 struct pt_regs *regs)
213{
214 long si_code = FPE_FLTINV;
215 siginfo_t info;
216
217 if (summary & 1) {
218 /* Software-completion summary bit is set, so try to
219 emulate the instruction. If the processor supports
220 precise exceptions, we don't have to search. */
221 if (!amask(AMASK_PRECISE_TRAP))
222 si_code = alpha_fp_emul(regs->pc - 4);
223 else
224 si_code = alpha_fp_emul_imprecise(regs, write_mask);
225 if (si_code == 0)
226 return;
227 }
228 die_if_kernel("Arithmetic fault", regs, 0, NULL);
229
230 info.si_signo = SIGFPE;
231 info.si_errno = 0;
232 info.si_code = si_code;
233 info.si_addr = (void __user *) regs->pc;
234 send_sig_info(SIGFPE, &info, current);
235}
236
237asmlinkage void
238do_entIF(unsigned long type, struct pt_regs *regs)
239{
240 siginfo_t info;
241 int signo, code;
242
243 if (regs->ps == 0) {
244 if (type == 1) {
245 const unsigned int *data
246 = (const unsigned int *) regs->pc;
247 printk("Kernel bug at %s:%d\n",
248 (const char *)(data[1] | (long)data[2] << 32),
249 data[0]);
250 }
251 die_if_kernel((type == 1 ? "Kernel Bug" : "Instruction fault"),
252 regs, type, NULL);
253 }
254
255 switch (type) {
256 case 0: /* breakpoint */
257 info.si_signo = SIGTRAP;
258 info.si_errno = 0;
259 info.si_code = TRAP_BRKPT;
260 info.si_trapno = 0;
261 info.si_addr = (void __user *) regs->pc;
262
263 if (ptrace_cancel_bpt(current)) {
264 regs->pc -= 4; /* make pc point to former bpt */
265 }
266
267 send_sig_info(SIGTRAP, &info, current);
268 return;
269
270 case 1: /* bugcheck */
271 info.si_signo = SIGTRAP;
272 info.si_errno = 0;
273 info.si_code = __SI_FAULT;
274 info.si_addr = (void __user *) regs->pc;
275 info.si_trapno = 0;
276 send_sig_info(SIGTRAP, &info, current);
277 return;
278
279 case 2: /* gentrap */
280 info.si_addr = (void __user *) regs->pc;
281 info.si_trapno = regs->r16;
282 switch ((long) regs->r16) {
283 case GEN_INTOVF:
284 signo = SIGFPE;
285 code = FPE_INTOVF;
286 break;
287 case GEN_INTDIV:
288 signo = SIGFPE;
289 code = FPE_INTDIV;
290 break;
291 case GEN_FLTOVF:
292 signo = SIGFPE;
293 code = FPE_FLTOVF;
294 break;
295 case GEN_FLTDIV:
296 signo = SIGFPE;
297 code = FPE_FLTDIV;
298 break;
299 case GEN_FLTUND:
300 signo = SIGFPE;
301 code = FPE_FLTUND;
302 break;
303 case GEN_FLTINV:
304 signo = SIGFPE;
305 code = FPE_FLTINV;
306 break;
307 case GEN_FLTINE:
308 signo = SIGFPE;
309 code = FPE_FLTRES;
310 break;
311 case GEN_ROPRAND:
312 signo = SIGFPE;
313 code = __SI_FAULT;
314 break;
315
316 case GEN_DECOVF:
317 case GEN_DECDIV:
318 case GEN_DECINV:
319 case GEN_ASSERTERR:
320 case GEN_NULPTRERR:
321 case GEN_STKOVF:
322 case GEN_STRLENERR:
323 case GEN_SUBSTRERR:
324 case GEN_RANGERR:
325 case GEN_SUBRNG:
326 case GEN_SUBRNG1:
327 case GEN_SUBRNG2:
328 case GEN_SUBRNG3:
329 case GEN_SUBRNG4:
330 case GEN_SUBRNG5:
331 case GEN_SUBRNG6:
332 case GEN_SUBRNG7:
333 default:
334 signo = SIGTRAP;
335 code = __SI_FAULT;
336 break;
337 }
338
339 info.si_signo = signo;
340 info.si_errno = 0;
341 info.si_code = code;
342 info.si_addr = (void __user *) regs->pc;
343 send_sig_info(signo, &info, current);
344 return;
345
346 case 4: /* opDEC */
347 if (implver() == IMPLVER_EV4) {
348 long si_code;
349
350 /* The some versions of SRM do not handle
351 the opDEC properly - they return the PC of the
352 opDEC fault, not the instruction after as the
353 Alpha architecture requires. Here we fix it up.
354 We do this by intentionally causing an opDEC
355 fault during the boot sequence and testing if
356 we get the correct PC. If not, we set a flag
357 to correct it every time through. */
358 regs->pc += opDEC_fix;
359
360 /* EV4 does not implement anything except normal
361 rounding. Everything else will come here as
362 an illegal instruction. Emulate them. */
363 si_code = alpha_fp_emul(regs->pc - 4);
364 if (si_code == 0)
365 return;
366 if (si_code > 0) {
367 info.si_signo = SIGFPE;
368 info.si_errno = 0;
369 info.si_code = si_code;
370 info.si_addr = (void __user *) regs->pc;
371 send_sig_info(SIGFPE, &info, current);
372 return;
373 }
374 }
375 break;
376
377 case 3: /* FEN fault */
378 /* Irritating users can call PAL_clrfen to disable the
379 FPU for the process. The kernel will then trap in
380 do_switch_stack and undo_switch_stack when we try
381 to save and restore the FP registers.
382
383 Given that GCC by default generates code that uses the
384 FP registers, PAL_clrfen is not useful except for DoS
385 attacks. So turn the bleeding FPU back on and be done
386 with it. */
387 current_thread_info()->pcb.flags |= 1;
388 __reload_thread(&current_thread_info()->pcb);
389 return;
390
391 case 5: /* illoc */
392 default: /* unexpected instruction-fault type */
393 ;
394 }
395
396 info.si_signo = SIGILL;
397 info.si_errno = 0;
398 info.si_code = ILL_ILLOPC;
399 info.si_addr = (void __user *) regs->pc;
400 send_sig_info(SIGILL, &info, current);
401}
402
403/* There is an ifdef in the PALcode in MILO that enables a
404 "kernel debugging entry point" as an unprivileged call_pal.
405
406 We don't want to have anything to do with it, but unfortunately
407 several versions of MILO included in distributions have it enabled,
408 and if we don't put something on the entry point we'll oops. */
409
410asmlinkage void
411do_entDbg(struct pt_regs *regs)
412{
413 siginfo_t info;
414
415 die_if_kernel("Instruction fault", regs, 0, NULL);
416
417 info.si_signo = SIGILL;
418 info.si_errno = 0;
419 info.si_code = ILL_ILLOPC;
420 info.si_addr = (void __user *) regs->pc;
421 force_sig_info(SIGILL, &info, current);
422}
423
424
425/*
426 * entUna has a different register layout to be reasonably simple. It
427 * needs access to all the integer registers (the kernel doesn't use
428 * fp-regs), and it needs to have them in order for simpler access.
429 *
430 * Due to the non-standard register layout (and because we don't want
431 * to handle floating-point regs), user-mode unaligned accesses are
432 * handled separately by do_entUnaUser below.
433 *
434 * Oh, btw, we don't handle the "gp" register correctly, but if we fault
435 * on a gp-register unaligned load/store, something is _very_ wrong
436 * in the kernel anyway..
437 */
438struct allregs {
439 unsigned long regs[32];
440 unsigned long ps, pc, gp, a0, a1, a2;
441};
442
443struct unaligned_stat {
444 unsigned long count, va, pc;
445} unaligned[2];
446
447
448/* Macro for exception fixup code to access integer registers. */
449#define una_reg(r) (regs.regs[(r) >= 16 && (r) <= 18 ? (r)+19 : (r)])
450
451
452asmlinkage void
453do_entUna(void * va, unsigned long opcode, unsigned long reg,
454 unsigned long a3, unsigned long a4, unsigned long a5,
455 struct allregs regs)
456{
457 long error, tmp1, tmp2, tmp3, tmp4;
458 unsigned long pc = regs.pc - 4;
459 const struct exception_table_entry *fixup;
460
461 unaligned[0].count++;
462 unaligned[0].va = (unsigned long) va;
463 unaligned[0].pc = pc;
464
465 /* We don't want to use the generic get/put unaligned macros as
466 we want to trap exceptions. Only if we actually get an
467 exception will we decide whether we should have caught it. */
468
469 switch (opcode) {
470 case 0x0c: /* ldwu */
471 __asm__ __volatile__(
472 "1: ldq_u %1,0(%3)\n"
473 "2: ldq_u %2,1(%3)\n"
474 " extwl %1,%3,%1\n"
475 " extwh %2,%3,%2\n"
476 "3:\n"
477 ".section __ex_table,\"a\"\n"
478 " .long 1b - .\n"
479 " lda %1,3b-1b(%0)\n"
480 " .long 2b - .\n"
481 " lda %2,3b-2b(%0)\n"
482 ".previous"
483 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
484 : "r"(va), "0"(0));
485 if (error)
486 goto got_exception;
487 una_reg(reg) = tmp1|tmp2;
488 return;
489
490 case 0x28: /* ldl */
491 __asm__ __volatile__(
492 "1: ldq_u %1,0(%3)\n"
493 "2: ldq_u %2,3(%3)\n"
494 " extll %1,%3,%1\n"
495 " extlh %2,%3,%2\n"
496 "3:\n"
497 ".section __ex_table,\"a\"\n"
498 " .long 1b - .\n"
499 " lda %1,3b-1b(%0)\n"
500 " .long 2b - .\n"
501 " lda %2,3b-2b(%0)\n"
502 ".previous"
503 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
504 : "r"(va), "0"(0));
505 if (error)
506 goto got_exception;
507 una_reg(reg) = (int)(tmp1|tmp2);
508 return;
509
510 case 0x29: /* ldq */
511 __asm__ __volatile__(
512 "1: ldq_u %1,0(%3)\n"
513 "2: ldq_u %2,7(%3)\n"
514 " extql %1,%3,%1\n"
515 " extqh %2,%3,%2\n"
516 "3:\n"
517 ".section __ex_table,\"a\"\n"
518 " .long 1b - .\n"
519 " lda %1,3b-1b(%0)\n"
520 " .long 2b - .\n"
521 " lda %2,3b-2b(%0)\n"
522 ".previous"
523 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
524 : "r"(va), "0"(0));
525 if (error)
526 goto got_exception;
527 una_reg(reg) = tmp1|tmp2;
528 return;
529
530 /* Note that the store sequences do not indicate that they change
531 memory because it _should_ be affecting nothing in this context.
532 (Otherwise we have other, much larger, problems.) */
533 case 0x0d: /* stw */
534 __asm__ __volatile__(
535 "1: ldq_u %2,1(%5)\n"
536 "2: ldq_u %1,0(%5)\n"
537 " inswh %6,%5,%4\n"
538 " inswl %6,%5,%3\n"
539 " mskwh %2,%5,%2\n"
540 " mskwl %1,%5,%1\n"
541 " or %2,%4,%2\n"
542 " or %1,%3,%1\n"
543 "3: stq_u %2,1(%5)\n"
544 "4: stq_u %1,0(%5)\n"
545 "5:\n"
546 ".section __ex_table,\"a\"\n"
547 " .long 1b - .\n"
548 " lda %2,5b-1b(%0)\n"
549 " .long 2b - .\n"
550 " lda %1,5b-2b(%0)\n"
551 " .long 3b - .\n"
552 " lda $31,5b-3b(%0)\n"
553 " .long 4b - .\n"
554 " lda $31,5b-4b(%0)\n"
555 ".previous"
556 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
557 "=&r"(tmp3), "=&r"(tmp4)
558 : "r"(va), "r"(una_reg(reg)), "0"(0));
559 if (error)
560 goto got_exception;
561 return;
562
563 case 0x2c: /* stl */
564 __asm__ __volatile__(
565 "1: ldq_u %2,3(%5)\n"
566 "2: ldq_u %1,0(%5)\n"
567 " inslh %6,%5,%4\n"
568 " insll %6,%5,%3\n"
569 " msklh %2,%5,%2\n"
570 " mskll %1,%5,%1\n"
571 " or %2,%4,%2\n"
572 " or %1,%3,%1\n"
573 "3: stq_u %2,3(%5)\n"
574 "4: stq_u %1,0(%5)\n"
575 "5:\n"
576 ".section __ex_table,\"a\"\n"
577 " .long 1b - .\n"
578 " lda %2,5b-1b(%0)\n"
579 " .long 2b - .\n"
580 " lda %1,5b-2b(%0)\n"
581 " .long 3b - .\n"
582 " lda $31,5b-3b(%0)\n"
583 " .long 4b - .\n"
584 " lda $31,5b-4b(%0)\n"
585 ".previous"
586 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
587 "=&r"(tmp3), "=&r"(tmp4)
588 : "r"(va), "r"(una_reg(reg)), "0"(0));
589 if (error)
590 goto got_exception;
591 return;
592
593 case 0x2d: /* stq */
594 __asm__ __volatile__(
595 "1: ldq_u %2,7(%5)\n"
596 "2: ldq_u %1,0(%5)\n"
597 " insqh %6,%5,%4\n"
598 " insql %6,%5,%3\n"
599 " mskqh %2,%5,%2\n"
600 " mskql %1,%5,%1\n"
601 " or %2,%4,%2\n"
602 " or %1,%3,%1\n"
603 "3: stq_u %2,7(%5)\n"
604 "4: stq_u %1,0(%5)\n"
605 "5:\n"
606 ".section __ex_table,\"a\"\n\t"
607 " .long 1b - .\n"
608 " lda %2,5b-1b(%0)\n"
609 " .long 2b - .\n"
610 " lda %1,5b-2b(%0)\n"
611 " .long 3b - .\n"
612 " lda $31,5b-3b(%0)\n"
613 " .long 4b - .\n"
614 " lda $31,5b-4b(%0)\n"
615 ".previous"
616 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
617 "=&r"(tmp3), "=&r"(tmp4)
618 : "r"(va), "r"(una_reg(reg)), "0"(0));
619 if (error)
620 goto got_exception;
621 return;
622 }
623
624 lock_kernel();
625 printk("Bad unaligned kernel access at %016lx: %p %lx %ld\n",
626 pc, va, opcode, reg);
627 do_exit(SIGSEGV);
628
629got_exception:
630 /* Ok, we caught the exception, but we don't want it. Is there
631 someone to pass it along to? */
632 if ((fixup = search_exception_tables(pc)) != 0) {
633 unsigned long newpc;
634 newpc = fixup_exception(una_reg, fixup, pc);
635
636 printk("Forwarding unaligned exception at %lx (%lx)\n",
637 pc, newpc);
638
639 (&regs)->pc = newpc;
640 return;
641 }
642
643 /*
644 * Yikes! No one to forward the exception to.
645 * Since the registers are in a weird format, dump them ourselves.
646 */
647 lock_kernel();
648
649 printk("%s(%d): unhandled unaligned exception\n",
650 current->comm, current->pid);
651
652 printk("pc = [<%016lx>] ra = [<%016lx>] ps = %04lx\n",
653 pc, una_reg(26), regs.ps);
654 printk("r0 = %016lx r1 = %016lx r2 = %016lx\n",
655 una_reg(0), una_reg(1), una_reg(2));
656 printk("r3 = %016lx r4 = %016lx r5 = %016lx\n",
657 una_reg(3), una_reg(4), una_reg(5));
658 printk("r6 = %016lx r7 = %016lx r8 = %016lx\n",
659 una_reg(6), una_reg(7), una_reg(8));
660 printk("r9 = %016lx r10= %016lx r11= %016lx\n",
661 una_reg(9), una_reg(10), una_reg(11));
662 printk("r12= %016lx r13= %016lx r14= %016lx\n",
663 una_reg(12), una_reg(13), una_reg(14));
664 printk("r15= %016lx\n", una_reg(15));
665 printk("r16= %016lx r17= %016lx r18= %016lx\n",
666 una_reg(16), una_reg(17), una_reg(18));
667 printk("r19= %016lx r20= %016lx r21= %016lx\n",
668 una_reg(19), una_reg(20), una_reg(21));
669 printk("r22= %016lx r23= %016lx r24= %016lx\n",
670 una_reg(22), una_reg(23), una_reg(24));
671 printk("r25= %016lx r27= %016lx r28= %016lx\n",
672 una_reg(25), una_reg(27), una_reg(28));
673 printk("gp = %016lx sp = %p\n", regs.gp, &regs+1);
674
675 dik_show_code((unsigned int *)pc);
676 dik_show_trace((unsigned long *)(&regs+1));
677
678 if (test_and_set_thread_flag (TIF_DIE_IF_KERNEL)) {
679 printk("die_if_kernel recursion detected.\n");
680 local_irq_enable();
681 while (1);
682 }
683 do_exit(SIGSEGV);
684}
685
686/*
687 * Convert an s-floating point value in memory format to the
688 * corresponding value in register format. The exponent
689 * needs to be remapped to preserve non-finite values
690 * (infinities, not-a-numbers, denormals).
691 */
692static inline unsigned long
693s_mem_to_reg (unsigned long s_mem)
694{
695 unsigned long frac = (s_mem >> 0) & 0x7fffff;
696 unsigned long sign = (s_mem >> 31) & 0x1;
697 unsigned long exp_msb = (s_mem >> 30) & 0x1;
698 unsigned long exp_low = (s_mem >> 23) & 0x7f;
699 unsigned long exp;
700
701 exp = (exp_msb << 10) | exp_low; /* common case */
702 if (exp_msb) {
703 if (exp_low == 0x7f) {
704 exp = 0x7ff;
705 }
706 } else {
707 if (exp_low == 0x00) {
708 exp = 0x000;
709 } else {
710 exp |= (0x7 << 7);
711 }
712 }
713 return (sign << 63) | (exp << 52) | (frac << 29);
714}
715
716/*
717 * Convert an s-floating point value in register format to the
718 * corresponding value in memory format.
719 */
720static inline unsigned long
721s_reg_to_mem (unsigned long s_reg)
722{
723 return ((s_reg >> 62) << 30) | ((s_reg << 5) >> 34);
724}
725
726/*
727 * Handle user-level unaligned fault. Handling user-level unaligned
728 * faults is *extremely* slow and produces nasty messages. A user
729 * program *should* fix unaligned faults ASAP.
730 *
731 * Notice that we have (almost) the regular kernel stack layout here,
732 * so finding the appropriate registers is a little more difficult
733 * than in the kernel case.
734 *
735 * Finally, we handle regular integer load/stores only. In
736 * particular, load-linked/store-conditionally and floating point
737 * load/stores are not supported. The former make no sense with
738 * unaligned faults (they are guaranteed to fail) and I don't think
739 * the latter will occur in any decent program.
740 *
741 * Sigh. We *do* have to handle some FP operations, because GCC will
742 * uses them as temporary storage for integer memory to memory copies.
743 * However, we need to deal with stt/ldt and sts/lds only.
744 */
745
746#define OP_INT_MASK ( 1L << 0x28 | 1L << 0x2c /* ldl stl */ \
747 | 1L << 0x29 | 1L << 0x2d /* ldq stq */ \
748 | 1L << 0x0c | 1L << 0x0d /* ldwu stw */ \
749 | 1L << 0x0a | 1L << 0x0e ) /* ldbu stb */
750
751#define OP_WRITE_MASK ( 1L << 0x26 | 1L << 0x27 /* sts stt */ \
752 | 1L << 0x2c | 1L << 0x2d /* stl stq */ \
753 | 1L << 0x0d | 1L << 0x0e ) /* stw stb */
754
755#define R(x) ((size_t) &((struct pt_regs *)0)->x)
756
757static int unauser_reg_offsets[32] = {
758 R(r0), R(r1), R(r2), R(r3), R(r4), R(r5), R(r6), R(r7), R(r8),
759 /* r9 ... r15 are stored in front of regs. */
760 -56, -48, -40, -32, -24, -16, -8,
761 R(r16), R(r17), R(r18),
762 R(r19), R(r20), R(r21), R(r22), R(r23), R(r24), R(r25), R(r26),
763 R(r27), R(r28), R(gp),
764 0, 0
765};
766
767#undef R
768
769asmlinkage void
770do_entUnaUser(void __user * va, unsigned long opcode,
771 unsigned long reg, struct pt_regs *regs)
772{
773 static int cnt = 0;
774 static long last_time = 0;
775
776 unsigned long tmp1, tmp2, tmp3, tmp4;
777 unsigned long fake_reg, *reg_addr = &fake_reg;
778 siginfo_t info;
779 long error;
780
781 /* Check the UAC bits to decide what the user wants us to do
782 with the unaliged access. */
783
784 if (!test_thread_flag (TIF_UAC_NOPRINT)) {
785 if (cnt >= 5 && jiffies - last_time > 5*HZ) {
786 cnt = 0;
787 }
788 if (++cnt < 5) {
789 printk("%s(%d): unaligned trap at %016lx: %p %lx %ld\n",
790 current->comm, current->pid,
791 regs->pc - 4, va, opcode, reg);
792 }
793 last_time = jiffies;
794 }
795 if (test_thread_flag (TIF_UAC_SIGBUS))
796 goto give_sigbus;
797 /* Not sure why you'd want to use this, but... */
798 if (test_thread_flag (TIF_UAC_NOFIX))
799 return;
800
801 /* Don't bother reading ds in the access check since we already
802 know that this came from the user. Also rely on the fact that
803 the page at TASK_SIZE is unmapped and so can't be touched anyway. */
804 if (!__access_ok((unsigned long)va, 0, USER_DS))
805 goto give_sigsegv;
806
807 ++unaligned[1].count;
808 unaligned[1].va = (unsigned long)va;
809 unaligned[1].pc = regs->pc - 4;
810
811 if ((1L << opcode) & OP_INT_MASK) {
812 /* it's an integer load/store */
813 if (reg < 30) {
814 reg_addr = (unsigned long *)
815 ((char *)regs + unauser_reg_offsets[reg]);
816 } else if (reg == 30) {
817 /* usp in PAL regs */
818 fake_reg = rdusp();
819 } else {
820 /* zero "register" */
821 fake_reg = 0;
822 }
823 }
824
825 /* We don't want to use the generic get/put unaligned macros as
826 we want to trap exceptions. Only if we actually get an
827 exception will we decide whether we should have caught it. */
828
829 switch (opcode) {
830 case 0x0c: /* ldwu */
831 __asm__ __volatile__(
832 "1: ldq_u %1,0(%3)\n"
833 "2: ldq_u %2,1(%3)\n"
834 " extwl %1,%3,%1\n"
835 " extwh %2,%3,%2\n"
836 "3:\n"
837 ".section __ex_table,\"a\"\n"
838 " .long 1b - .\n"
839 " lda %1,3b-1b(%0)\n"
840 " .long 2b - .\n"
841 " lda %2,3b-2b(%0)\n"
842 ".previous"
843 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
844 : "r"(va), "0"(0));
845 if (error)
846 goto give_sigsegv;
847 *reg_addr = tmp1|tmp2;
848 break;
849
850 case 0x22: /* lds */
851 __asm__ __volatile__(
852 "1: ldq_u %1,0(%3)\n"
853 "2: ldq_u %2,3(%3)\n"
854 " extll %1,%3,%1\n"
855 " extlh %2,%3,%2\n"
856 "3:\n"
857 ".section __ex_table,\"a\"\n"
858 " .long 1b - .\n"
859 " lda %1,3b-1b(%0)\n"
860 " .long 2b - .\n"
861 " lda %2,3b-2b(%0)\n"
862 ".previous"
863 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
864 : "r"(va), "0"(0));
865 if (error)
866 goto give_sigsegv;
867 alpha_write_fp_reg(reg, s_mem_to_reg((int)(tmp1|tmp2)));
868 return;
869
870 case 0x23: /* ldt */
871 __asm__ __volatile__(
872 "1: ldq_u %1,0(%3)\n"
873 "2: ldq_u %2,7(%3)\n"
874 " extql %1,%3,%1\n"
875 " extqh %2,%3,%2\n"
876 "3:\n"
877 ".section __ex_table,\"a\"\n"
878 " .long 1b - .\n"
879 " lda %1,3b-1b(%0)\n"
880 " .long 2b - .\n"
881 " lda %2,3b-2b(%0)\n"
882 ".previous"
883 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
884 : "r"(va), "0"(0));
885 if (error)
886 goto give_sigsegv;
887 alpha_write_fp_reg(reg, tmp1|tmp2);
888 return;
889
890 case 0x28: /* ldl */
891 __asm__ __volatile__(
892 "1: ldq_u %1,0(%3)\n"
893 "2: ldq_u %2,3(%3)\n"
894 " extll %1,%3,%1\n"
895 " extlh %2,%3,%2\n"
896 "3:\n"
897 ".section __ex_table,\"a\"\n"
898 " .long 1b - .\n"
899 " lda %1,3b-1b(%0)\n"
900 " .long 2b - .\n"
901 " lda %2,3b-2b(%0)\n"
902 ".previous"
903 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
904 : "r"(va), "0"(0));
905 if (error)
906 goto give_sigsegv;
907 *reg_addr = (int)(tmp1|tmp2);
908 break;
909
910 case 0x29: /* ldq */
911 __asm__ __volatile__(
912 "1: ldq_u %1,0(%3)\n"
913 "2: ldq_u %2,7(%3)\n"
914 " extql %1,%3,%1\n"
915 " extqh %2,%3,%2\n"
916 "3:\n"
917 ".section __ex_table,\"a\"\n"
918 " .long 1b - .\n"
919 " lda %1,3b-1b(%0)\n"
920 " .long 2b - .\n"
921 " lda %2,3b-2b(%0)\n"
922 ".previous"
923 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
924 : "r"(va), "0"(0));
925 if (error)
926 goto give_sigsegv;
927 *reg_addr = tmp1|tmp2;
928 break;
929
930 /* Note that the store sequences do not indicate that they change
931 memory because it _should_ be affecting nothing in this context.
932 (Otherwise we have other, much larger, problems.) */
933 case 0x0d: /* stw */
934 __asm__ __volatile__(
935 "1: ldq_u %2,1(%5)\n"
936 "2: ldq_u %1,0(%5)\n"
937 " inswh %6,%5,%4\n"
938 " inswl %6,%5,%3\n"
939 " mskwh %2,%5,%2\n"
940 " mskwl %1,%5,%1\n"
941 " or %2,%4,%2\n"
942 " or %1,%3,%1\n"
943 "3: stq_u %2,1(%5)\n"
944 "4: stq_u %1,0(%5)\n"
945 "5:\n"
946 ".section __ex_table,\"a\"\n"
947 " .long 1b - .\n"
948 " lda %2,5b-1b(%0)\n"
949 " .long 2b - .\n"
950 " lda %1,5b-2b(%0)\n"
951 " .long 3b - .\n"
952 " lda $31,5b-3b(%0)\n"
953 " .long 4b - .\n"
954 " lda $31,5b-4b(%0)\n"
955 ".previous"
956 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
957 "=&r"(tmp3), "=&r"(tmp4)
958 : "r"(va), "r"(*reg_addr), "0"(0));
959 if (error)
960 goto give_sigsegv;
961 return;
962
963 case 0x26: /* sts */
964 fake_reg = s_reg_to_mem(alpha_read_fp_reg(reg));
965 /* FALLTHRU */
966
967 case 0x2c: /* stl */
968 __asm__ __volatile__(
969 "1: ldq_u %2,3(%5)\n"
970 "2: ldq_u %1,0(%5)\n"
971 " inslh %6,%5,%4\n"
972 " insll %6,%5,%3\n"
973 " msklh %2,%5,%2\n"
974 " mskll %1,%5,%1\n"
975 " or %2,%4,%2\n"
976 " or %1,%3,%1\n"
977 "3: stq_u %2,3(%5)\n"
978 "4: stq_u %1,0(%5)\n"
979 "5:\n"
980 ".section __ex_table,\"a\"\n"
981 " .long 1b - .\n"
982 " lda %2,5b-1b(%0)\n"
983 " .long 2b - .\n"
984 " lda %1,5b-2b(%0)\n"
985 " .long 3b - .\n"
986 " lda $31,5b-3b(%0)\n"
987 " .long 4b - .\n"
988 " lda $31,5b-4b(%0)\n"
989 ".previous"
990 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
991 "=&r"(tmp3), "=&r"(tmp4)
992 : "r"(va), "r"(*reg_addr), "0"(0));
993 if (error)
994 goto give_sigsegv;
995 return;
996
997 case 0x27: /* stt */
998 fake_reg = alpha_read_fp_reg(reg);
999 /* FALLTHRU */
1000
1001 case 0x2d: /* stq */
1002 __asm__ __volatile__(
1003 "1: ldq_u %2,7(%5)\n"
1004 "2: ldq_u %1,0(%5)\n"
1005 " insqh %6,%5,%4\n"
1006 " insql %6,%5,%3\n"
1007 " mskqh %2,%5,%2\n"
1008 " mskql %1,%5,%1\n"
1009 " or %2,%4,%2\n"
1010 " or %1,%3,%1\n"
1011 "3: stq_u %2,7(%5)\n"
1012 "4: stq_u %1,0(%5)\n"
1013 "5:\n"
1014 ".section __ex_table,\"a\"\n\t"
1015 " .long 1b - .\n"
1016 " lda %2,5b-1b(%0)\n"
1017 " .long 2b - .\n"
1018 " lda %1,5b-2b(%0)\n"
1019 " .long 3b - .\n"
1020 " lda $31,5b-3b(%0)\n"
1021 " .long 4b - .\n"
1022 " lda $31,5b-4b(%0)\n"
1023 ".previous"
1024 : "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
1025 "=&r"(tmp3), "=&r"(tmp4)
1026 : "r"(va), "r"(*reg_addr), "0"(0));
1027 if (error)
1028 goto give_sigsegv;
1029 return;
1030
1031 default:
1032 /* What instruction were you trying to use, exactly? */
1033 goto give_sigbus;
1034 }
1035
1036 /* Only integer loads should get here; everyone else returns early. */
1037 if (reg == 30)
1038 wrusp(fake_reg);
1039 return;
1040
1041give_sigsegv:
1042 regs->pc -= 4; /* make pc point to faulting insn */
1043 info.si_signo = SIGSEGV;
1044 info.si_errno = 0;
1045
1046 /* We need to replicate some of the logic in mm/fault.c,
1047 since we don't have access to the fault code in the
1048 exception handling return path. */
1049 if (!__access_ok((unsigned long)va, 0, USER_DS))
1050 info.si_code = SEGV_ACCERR;
1051 else {
1052 struct mm_struct *mm = current->mm;
1053 down_read(&mm->mmap_sem);
1054 if (find_vma(mm, (unsigned long)va))
1055 info.si_code = SEGV_ACCERR;
1056 else
1057 info.si_code = SEGV_MAPERR;
1058 up_read(&mm->mmap_sem);
1059 }
1060 info.si_addr = va;
1061 send_sig_info(SIGSEGV, &info, current);
1062 return;
1063
1064give_sigbus:
1065 regs->pc -= 4;
1066 info.si_signo = SIGBUS;
1067 info.si_errno = 0;
1068 info.si_code = BUS_ADRALN;
1069 info.si_addr = va;
1070 send_sig_info(SIGBUS, &info, current);
1071 return;
1072}
1073
1074void __init
1075trap_init(void)
1076{
1077 /* Tell PAL-code what global pointer we want in the kernel. */
1078 register unsigned long gptr __asm__("$29");
1079 wrkgp(gptr);
1080
1081 /* Hack for Multia (UDB) and JENSEN: some of their SRMs have
1082 a bug in the handling of the opDEC fault. Fix it up if so. */
1083 if (implver() == IMPLVER_EV4)
1084 opDEC_check();
1085
1086 wrent(entArith, 1);
1087 wrent(entMM, 2);
1088 wrent(entIF, 3);
1089 wrent(entUna, 4);
1090 wrent(entSys, 5);
1091 wrent(entDbg, 6);
1092}
diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..0922e0785ddb
--- /dev/null
+++ b/arch/alpha/kernel/vmlinux.lds.S
@@ -0,0 +1,149 @@
1#include <linux/config.h>
2#include <asm-generic/vmlinux.lds.h>
3
4OUTPUT_FORMAT("elf64-alpha")
5OUTPUT_ARCH(alpha)
6ENTRY(__start)
7PHDRS { kernel PT_LOAD ; }
8jiffies = jiffies_64;
9SECTIONS
10{
11#ifdef CONFIG_ALPHA_LEGACY_START_ADDRESS
12 . = 0xfffffc0000310000;
13#else
14 . = 0xfffffc0001010000;
15#endif
16
17 _text = .; /* Text and read-only data */
18 .text : {
19 *(.text)
20 SCHED_TEXT
21 LOCK_TEXT
22 *(.fixup)
23 *(.gnu.warning)
24 } :kernel
25 _etext = .; /* End of text section */
26
27 . = ALIGN(16);
28 __start___ex_table = .; /* Exception table */
29 __ex_table : { *(__ex_table) }
30 __stop___ex_table = .;
31
32 RODATA
33
34 /* Will be freed after init */
35 . = ALIGN(8192); /* Init code and data */
36 __init_begin = .;
37 .init.text : {
38 _sinittext = .;
39 *(.init.text)
40 _einittext = .;
41 }
42 .init.data : { *(.init.data) }
43
44 . = ALIGN(16);
45 __setup_start = .;
46 .init.setup : { *(.init.setup) }
47 __setup_end = .;
48
49 . = ALIGN(8);
50 __initcall_start = .;
51 .initcall.init : {
52 *(.initcall1.init)
53 *(.initcall2.init)
54 *(.initcall3.init)
55 *(.initcall4.init)
56 *(.initcall5.init)
57 *(.initcall6.init)
58 *(.initcall7.init)
59 }
60 __initcall_end = .;
61
62 . = ALIGN(8192);
63 __initramfs_start = .;
64 .init.ramfs : { *(.init.ramfs) }
65 __initramfs_end = .;
66
67 . = ALIGN(8);
68 .con_initcall.init : {
69 __con_initcall_start = .;
70 *(.con_initcall.init)
71 __con_initcall_end = .;
72 }
73
74 . = ALIGN(8);
75 SECURITY_INIT
76
77 . = ALIGN(64);
78 __per_cpu_start = .;
79 .data.percpu : { *(.data.percpu) }
80 __per_cpu_end = .;
81
82 . = ALIGN(2*8192);
83 __init_end = .;
84 /* Freed after init ends here */
85
86 /* Note 2 page alignment above. */
87 .data.init_thread : { *(.data.init_thread) }
88
89 . = ALIGN(8192);
90 .data.page_aligned : { *(.data.page_aligned) }
91
92 . = ALIGN(64);
93 .data.cacheline_aligned : { *(.data.cacheline_aligned) }
94
95 _data = .;
96 .data : { /* Data */
97 *(.data)
98 CONSTRUCTORS
99 }
100
101 .got : { *(.got) }
102 .sdata : { *(.sdata) }
103
104 _edata = .; /* End of data section */
105
106 __bss_start = .;
107 .sbss : { *(.sbss) *(.scommon) }
108 .bss : { *(.bss) *(COMMON) }
109 __bss_stop = .;
110
111 _end = .;
112
113 /* Sections to be discarded */
114 /DISCARD/ : { *(.exit.text) *(.exit.data) *(.exitcall.exit) }
115
116 .mdebug 0 : { *(.mdebug) }
117 .note 0 : { *(.note) }
118 .comment 0 : { *(.comment) }
119
120 /* Stabs debugging sections */
121 .stab 0 : { *(.stab) }
122 .stabstr 0 : { *(.stabstr) }
123 .stab.excl 0 : { *(.stab.excl) }
124 .stab.exclstr 0 : { *(.stab.exclstr) }
125 .stab.index 0 : { *(.stab.index) }
126 .stab.indexstr 0 : { *(.stab.indexstr) }
127 /* DWARF 1 */
128 .debug 0 : { *(.debug) }
129 .line 0 : { *(.line) }
130 /* GNU DWARF 1 extensions */
131 .debug_srcinfo 0 : { *(.debug_srcinfo) }
132 .debug_sfnames 0 : { *(.debug_sfnames) }
133 /* DWARF 1.1 and DWARF 2 */
134 .debug_aranges 0 : { *(.debug_aranges) }
135 .debug_pubnames 0 : { *(.debug_pubnames) }
136 /* DWARF 2 */
137 .debug_info 0 : { *(.debug_info) }
138 .debug_abbrev 0 : { *(.debug_abbrev) }
139 .debug_line 0 : { *(.debug_line) }
140 .debug_frame 0 : { *(.debug_frame) }
141 .debug_str 0 : { *(.debug_str) }
142 .debug_loc 0 : { *(.debug_loc) }
143 .debug_macinfo 0 : { *(.debug_macinfo) }
144 /* SGI/MIPS DWARF 2 extensions */
145 .debug_weaknames 0 : { *(.debug_weaknames) }
146 .debug_funcnames 0 : { *(.debug_funcnames) }
147 .debug_typenames 0 : { *(.debug_typenames) }
148 .debug_varnames 0 : { *(.debug_varnames) }
149}
diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile
new file mode 100644
index 000000000000..21cf624d7329
--- /dev/null
+++ b/arch/alpha/lib/Makefile
@@ -0,0 +1,58 @@
1#
2# Makefile for alpha-specific library files..
3#
4
5EXTRA_AFLAGS := $(CFLAGS)
6EXTRA_CFLAGS := -Werror
7
8# Many of these routines have implementations tuned for ev6.
9# Choose them iff we're targeting ev6 specifically.
10ev6-$(CONFIG_ALPHA_EV6) := ev6-
11
12# Several make use of the cttz instruction introduced in ev67.
13ev67-$(CONFIG_ALPHA_EV67) := ev67-
14
15lib-y = __divqu.o __remqu.o __divlu.o __remlu.o \
16 udelay.o \
17 $(ev6-y)memset.o \
18 $(ev6-y)memcpy.o \
19 memmove.o \
20 checksum.o \
21 csum_partial_copy.o \
22 $(ev67-y)strlen.o \
23 $(ev67-y)strcat.o \
24 strcpy.o \
25 $(ev67-y)strncat.o \
26 strncpy.o \
27 $(ev6-y)stxcpy.o \
28 $(ev6-y)stxncpy.o \
29 $(ev67-y)strchr.o \
30 $(ev67-y)strrchr.o \
31 $(ev6-y)memchr.o \
32 $(ev6-y)copy_user.o \
33 $(ev6-y)clear_user.o \
34 $(ev6-y)strncpy_from_user.o \
35 $(ev67-y)strlen_user.o \
36 $(ev6-y)csum_ipv6_magic.o \
37 $(ev6-y)clear_page.o \
38 $(ev6-y)copy_page.o \
39 strcasecmp.o \
40 fpreg.o \
41 callback_srm.o srm_puts.o srm_printk.o
42
43lib-$(CONFIG_SMP) += dec_and_lock.o
44
45# The division routines are built from single source, with different defines.
46AFLAGS___divqu.o = -DDIV
47AFLAGS___remqu.o = -DREM
48AFLAGS___divlu.o = -DDIV -DINTSIZE
49AFLAGS___remlu.o = -DREM -DINTSIZE
50
51$(obj)/__divqu.o: $(obj)/$(ev6-y)divide.S
52 $(cmd_as_o_S)
53$(obj)/__remqu.o: $(obj)/$(ev6-y)divide.S
54 $(cmd_as_o_S)
55$(obj)/__divlu.o: $(obj)/$(ev6-y)divide.S
56 $(cmd_as_o_S)
57$(obj)/__remlu.o: $(obj)/$(ev6-y)divide.S
58 $(cmd_as_o_S)
diff --git a/arch/alpha/lib/callback_srm.S b/arch/alpha/lib/callback_srm.S
new file mode 100644
index 000000000000..0528acd0d9ad
--- /dev/null
+++ b/arch/alpha/lib/callback_srm.S
@@ -0,0 +1,104 @@
1/*
2 * arch/alpha/lib/callback_srm.S
3 */
4
5#include <linux/config.h>
6#include <asm/console.h>
7
8.text
9#define HWRPB_CRB_OFFSET 0xc0
10
11#if defined(CONFIG_ALPHA_SRM) || defined(CONFIG_ALPHA_GENERIC)
12.align 4
13srm_dispatch:
14#if defined(CONFIG_ALPHA_GENERIC)
15 ldl $4,alpha_using_srm
16 beq $4,nosrm
17#endif
18 ldq $0,hwrpb # gp is set up by CALLBACK macro.
19 ldl $25,0($25) # Pick up the wrapper data.
20 mov $20,$21 # Shift arguments right.
21 mov $19,$20
22 ldq $1,HWRPB_CRB_OFFSET($0)
23 mov $18,$19
24 mov $17,$18
25 mov $16,$17
26 addq $0,$1,$2 # CRB address
27 ldq $27,0($2) # DISPATCH procedure descriptor (VMS call std)
28 extwl $25,0,$16 # SRM callback function code
29 ldq $3,8($27) # call address
30 extwl $25,2,$25 # argument information (VMS calling std)
31 jmp ($3) # Return directly to caller of wrapper.
32
33.align 4
34.globl srm_fixup
35.ent srm_fixup
36srm_fixup:
37 ldgp $29,0($27)
38#if defined(CONFIG_ALPHA_GENERIC)
39 ldl $4,alpha_using_srm
40 beq $4,nosrm
41#endif
42 ldq $0,hwrpb
43 ldq $1,HWRPB_CRB_OFFSET($0)
44 addq $0,$1,$2 # CRB address
45 ldq $27,16($2) # VA of FIXUP procedure descriptor
46 ldq $3,8($27) # call address
47 lda $25,2($31) # two integer arguments
48 jmp ($3) # Return directly to caller of srm_fixup.
49.end srm_fixup
50
51#if defined(CONFIG_ALPHA_GENERIC)
52.align 3
53nosrm:
54 lda $0,-1($31)
55 ret
56#endif
57
58#define CALLBACK(NAME, CODE, ARG_CNT) \
59.align 4; .globl callback_##NAME; .ent callback_##NAME; callback_##NAME##: \
60ldgp $29,0($27); br $25,srm_dispatch; .word CODE, ARG_CNT; .end callback_##NAME
61
62#else /* defined(CONFIG_ALPHA_SRM) || defined(CONFIG_ALPHA_GENERIC) */
63
64#define CALLBACK(NAME, CODE, ARG_CNT) \
65.align 3; .globl callback_##NAME; .ent callback_##NAME; callback_##NAME##: \
66lda $0,-1($31); ret; .end callback_##NAME
67
68.align 3
69.globl srm_fixup
70.ent srm_fixup
71srm_fixup:
72 lda $0,-1($31)
73 ret
74.end srm_fixup
75#endif /* defined(CONFIG_ALPHA_SRM) || defined(CONFIG_ALPHA_GENERIC) */
76
77CALLBACK(puts, CCB_PUTS, 4)
78CALLBACK(open, CCB_OPEN, 3)
79CALLBACK(close, CCB_CLOSE, 2)
80CALLBACK(read, CCB_READ, 5)
81CALLBACK(open_console, CCB_OPEN_CONSOLE, 1)
82CALLBACK(close_console, CCB_CLOSE_CONSOLE, 1)
83CALLBACK(getenv, CCB_GET_ENV, 4)
84CALLBACK(setenv, CCB_SET_ENV, 4)
85CALLBACK(getc, CCB_GETC, 2)
86CALLBACK(reset_term, CCB_RESET_TERM, 2)
87CALLBACK(term_int, CCB_SET_TERM_INT, 3)
88CALLBACK(term_ctl, CCB_SET_TERM_CTL, 3)
89CALLBACK(process_keycode, CCB_PROCESS_KEYCODE, 3)
90CALLBACK(ioctl, CCB_IOCTL, 6)
91CALLBACK(write, CCB_WRITE, 5)
92CALLBACK(reset_env, CCB_RESET_ENV, 4)
93CALLBACK(save_env, CCB_SAVE_ENV, 1)
94CALLBACK(pswitch, CCB_PSWITCH, 3)
95CALLBACK(bios_emul, CCB_BIOS_EMUL, 5)
96
97.data
98__alpha_using_srm: # For use by bootpheader
99 .long 7 # value is not 1 for link debugging
100 .weak alpha_using_srm; alpha_using_srm = __alpha_using_srm
101__callback_init_done: # For use by bootpheader
102 .long 7 # value is not 1 for link debugging
103 .weak callback_init_done; callback_init_done = __callback_init_done
104
diff --git a/arch/alpha/lib/checksum.c b/arch/alpha/lib/checksum.c
new file mode 100644
index 000000000000..89044e6385fe
--- /dev/null
+++ b/arch/alpha/lib/checksum.c
@@ -0,0 +1,186 @@
1/*
2 * arch/alpha/lib/checksum.c
3 *
4 * This file contains network checksum routines that are better done
5 * in an architecture-specific manner due to speed..
6 * Comments in other versions indicate that the algorithms are from RFC1071
7 *
8 * accellerated versions (and 21264 assembly versions ) contributed by
9 * Rick Gorton <rick.gorton@alpha-processor.com>
10 */
11
12#include <linux/module.h>
13#include <linux/string.h>
14
15#include <asm/byteorder.h>
16
17static inline unsigned short from64to16(unsigned long x)
18{
19 /* Using extract instructions is a bit more efficient
20 than the original shift/bitmask version. */
21
22 union {
23 unsigned long ul;
24 unsigned int ui[2];
25 unsigned short us[4];
26 } in_v, tmp_v, out_v;
27
28 in_v.ul = x;
29 tmp_v.ul = (unsigned long) in_v.ui[0] + (unsigned long) in_v.ui[1];
30
31 /* Since the bits of tmp_v.sh[3] are going to always be zero,
32 we don't have to bother to add that in. */
33 out_v.ul = (unsigned long) tmp_v.us[0] + (unsigned long) tmp_v.us[1]
34 + (unsigned long) tmp_v.us[2];
35
36 /* Similarly, out_v.us[2] is always zero for the final add. */
37 return out_v.us[0] + out_v.us[1];
38}
39
40/*
41 * computes the checksum of the TCP/UDP pseudo-header
42 * returns a 16-bit checksum, already complemented.
43 */
44unsigned short int csum_tcpudp_magic(unsigned long saddr,
45 unsigned long daddr,
46 unsigned short len,
47 unsigned short proto,
48 unsigned int sum)
49{
50 return ~from64to16(saddr + daddr + sum +
51 ((unsigned long) ntohs(len) << 16) +
52 ((unsigned long) proto << 8));
53}
54
55unsigned int csum_tcpudp_nofold(unsigned long saddr,
56 unsigned long daddr,
57 unsigned short len,
58 unsigned short proto,
59 unsigned int sum)
60{
61 unsigned long result;
62
63 result = (saddr + daddr + sum +
64 ((unsigned long) ntohs(len) << 16) +
65 ((unsigned long) proto << 8));
66
67 /* Fold down to 32-bits so we don't lose in the typedef-less
68 network stack. */
69 /* 64 to 33 */
70 result = (result & 0xffffffff) + (result >> 32);
71 /* 33 to 32 */
72 result = (result & 0xffffffff) + (result >> 32);
73 return result;
74}
75
76/*
77 * Do a 64-bit checksum on an arbitrary memory area..
78 *
79 * This isn't a great routine, but it's not _horrible_ either. The
80 * inner loop could be unrolled a bit further, and there are better
81 * ways to do the carry, but this is reasonable.
82 */
83static inline unsigned long do_csum(const unsigned char * buff, int len)
84{
85 int odd, count;
86 unsigned long result = 0;
87
88 if (len <= 0)
89 goto out;
90 odd = 1 & (unsigned long) buff;
91 if (odd) {
92 result = *buff << 8;
93 len--;
94 buff++;
95 }
96 count = len >> 1; /* nr of 16-bit words.. */
97 if (count) {
98 if (2 & (unsigned long) buff) {
99 result += *(unsigned short *) buff;
100 count--;
101 len -= 2;
102 buff += 2;
103 }
104 count >>= 1; /* nr of 32-bit words.. */
105 if (count) {
106 if (4 & (unsigned long) buff) {
107 result += *(unsigned int *) buff;
108 count--;
109 len -= 4;
110 buff += 4;
111 }
112 count >>= 1; /* nr of 64-bit words.. */
113 if (count) {
114 unsigned long carry = 0;
115 do {
116 unsigned long w = *(unsigned long *) buff;
117 count--;
118 buff += 8;
119 result += carry;
120 result += w;
121 carry = (w > result);
122 } while (count);
123 result += carry;
124 result = (result & 0xffffffff) + (result >> 32);
125 }
126 if (len & 4) {
127 result += *(unsigned int *) buff;
128 buff += 4;
129 }
130 }
131 if (len & 2) {
132 result += *(unsigned short *) buff;
133 buff += 2;
134 }
135 }
136 if (len & 1)
137 result += *buff;
138 result = from64to16(result);
139 if (odd)
140 result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
141out:
142 return result;
143}
144
145/*
146 * This is a version of ip_compute_csum() optimized for IP headers,
147 * which always checksum on 4 octet boundaries.
148 */
149unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
150{
151 return ~do_csum(iph,ihl*4);
152}
153
154/*
155 * computes the checksum of a memory block at buff, length len,
156 * and adds in "sum" (32-bit)
157 *
158 * returns a 32-bit number suitable for feeding into itself
159 * or csum_tcpudp_magic
160 *
161 * this function must be called with even lengths, except
162 * for the last fragment, which may be odd
163 *
164 * it's best to have buff aligned on a 32-bit boundary
165 */
166unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
167{
168 unsigned long result = do_csum(buff, len);
169
170 /* add in old sum, and carry.. */
171 result += sum;
172 /* 32+c bits -> 32 bits */
173 result = (result & 0xffffffff) + (result >> 32);
174 return result;
175}
176
177EXPORT_SYMBOL(csum_partial);
178
179/*
180 * this routine is used for miscellaneous IP-like checksums, mainly
181 * in icmp.c
182 */
183unsigned short ip_compute_csum(unsigned char * buff, int len)
184{
185 return ~from64to16(do_csum(buff,len));
186}
diff --git a/arch/alpha/lib/clear_page.S b/arch/alpha/lib/clear_page.S
new file mode 100644
index 000000000000..a221ae266e29
--- /dev/null
+++ b/arch/alpha/lib/clear_page.S
@@ -0,0 +1,39 @@
1/*
2 * arch/alpha/lib/clear_page.S
3 *
4 * Zero an entire page.
5 */
6
7 .text
8 .align 4
9 .global clear_page
10 .ent clear_page
11clear_page:
12 .prologue 0
13
14 lda $0,128
15 nop
16 unop
17 nop
18
191: stq $31,0($16)
20 stq $31,8($16)
21 stq $31,16($16)
22 stq $31,24($16)
23
24 stq $31,32($16)
25 stq $31,40($16)
26 stq $31,48($16)
27 subq $0,1,$0
28
29 stq $31,56($16)
30 addq $16,64,$16
31 unop
32 bne $0,1b
33
34 ret
35 nop
36 unop
37 nop
38
39 .end clear_page
diff --git a/arch/alpha/lib/clear_user.S b/arch/alpha/lib/clear_user.S
new file mode 100644
index 000000000000..8860316c1957
--- /dev/null
+++ b/arch/alpha/lib/clear_user.S
@@ -0,0 +1,113 @@
1/*
2 * arch/alpha/lib/clear_user.S
3 * Contributed by Richard Henderson <rth@tamu.edu>
4 *
5 * Zero user space, handling exceptions as we go.
6 *
7 * We have to make sure that $0 is always up-to-date and contains the
8 * right "bytes left to zero" value (and that it is updated only _after_
9 * a successful copy). There is also some rather minor exception setup
10 * stuff.
11 *
12 * NOTE! This is not directly C-callable, because the calling semantics
13 * are different:
14 *
15 * Inputs:
16 * length in $0
17 * destination address in $6
18 * exception pointer in $7
19 * return address in $28 (exceptions expect it there)
20 *
21 * Outputs:
22 * bytes left to copy in $0
23 *
24 * Clobbers:
25 * $1,$2,$3,$4,$5,$6
26 */
27
28/* Allow an exception for an insn; exit if we get one. */
29#define EX(x,y...) \
30 99: x,##y; \
31 .section __ex_table,"a"; \
32 .long 99b - .; \
33 lda $31, $exception-99b($31); \
34 .previous
35
36 .set noat
37 .set noreorder
38 .align 4
39
40 .globl __do_clear_user
41 .ent __do_clear_user
42 .frame $30, 0, $28
43 .prologue 0
44
45$loop:
46 and $1, 3, $4 # e0 :
47 beq $4, 1f # .. e1 :
48
490: EX( stq_u $31, 0($6) ) # e0 : zero one word
50 subq $0, 8, $0 # .. e1 :
51 subq $4, 1, $4 # e0 :
52 addq $6, 8, $6 # .. e1 :
53 bne $4, 0b # e1 :
54 unop # :
55
561: bic $1, 3, $1 # e0 :
57 beq $1, $tail # .. e1 :
58
592: EX( stq_u $31, 0($6) ) # e0 : zero four words
60 subq $0, 8, $0 # .. e1 :
61 EX( stq_u $31, 8($6) ) # e0 :
62 subq $0, 8, $0 # .. e1 :
63 EX( stq_u $31, 16($6) ) # e0 :
64 subq $0, 8, $0 # .. e1 :
65 EX( stq_u $31, 24($6) ) # e0 :
66 subq $0, 8, $0 # .. e1 :
67 subq $1, 4, $1 # e0 :
68 addq $6, 32, $6 # .. e1 :
69 bne $1, 2b # e1 :
70
71$tail:
72 bne $2, 1f # e1 : is there a tail to do?
73 ret $31, ($28), 1 # .. e1 :
74
751: EX( ldq_u $5, 0($6) ) # e0 :
76 clr $0 # .. e1 :
77 nop # e1 :
78 mskqh $5, $0, $5 # e0 :
79 EX( stq_u $5, 0($6) ) # e0 :
80 ret $31, ($28), 1 # .. e1 :
81
82__do_clear_user:
83 and $6, 7, $4 # e0 : find dest misalignment
84 beq $0, $zerolength # .. e1 :
85 addq $0, $4, $1 # e0 : bias counter
86 and $1, 7, $2 # e1 : number of bytes in tail
87 srl $1, 3, $1 # e0 :
88 beq $4, $loop # .. e1 :
89
90 EX( ldq_u $5, 0($6) ) # e0 : load dst word to mask back in
91 beq $1, $oneword # .. e1 : sub-word store?
92
93 mskql $5, $6, $5 # e0 : take care of misaligned head
94 addq $6, 8, $6 # .. e1 :
95 EX( stq_u $5, -8($6) ) # e0 :
96 addq $0, $4, $0 # .. e1 : bytes left -= 8 - misalignment
97 subq $1, 1, $1 # e0 :
98 subq $0, 8, $0 # .. e1 :
99 br $loop # e1 :
100 unop # :
101
102$oneword:
103 mskql $5, $6, $4 # e0 :
104 mskqh $5, $2, $5 # e0 :
105 or $5, $4, $5 # e1 :
106 EX( stq_u $5, 0($6) ) # e0 :
107 clr $0 # .. e1 :
108
109$zerolength:
110$exception:
111 ret $31, ($28), 1 # .. e1 :
112
113 .end __do_clear_user
diff --git a/arch/alpha/lib/copy_page.S b/arch/alpha/lib/copy_page.S
new file mode 100644
index 000000000000..9f3b97459cc6
--- /dev/null
+++ b/arch/alpha/lib/copy_page.S
@@ -0,0 +1,49 @@
1/*
2 * arch/alpha/lib/copy_page.S
3 *
4 * Copy an entire page.
5 */
6
7 .text
8 .align 4
9 .global copy_page
10 .ent copy_page
11copy_page:
12 .prologue 0
13
14 lda $18,128
15 nop
16 unop
17 nop
18
191: ldq $0,0($17)
20 ldq $1,8($17)
21 ldq $2,16($17)
22 ldq $3,24($17)
23
24 ldq $4,32($17)
25 ldq $5,40($17)
26 ldq $6,48($17)
27 ldq $7,56($17)
28
29 stq $0,0($16)
30 subq $18,1,$18
31 stq $1,8($16)
32 addq $17,64,$17
33
34 stq $2,16($16)
35 stq $3,24($16)
36 stq $4,32($16)
37 stq $5,40($16)
38
39 stq $6,48($16)
40 stq $7,56($16)
41 addq $16,64,$16
42 bne $18, 1b
43
44 ret
45 nop
46 unop
47 nop
48
49 .end copy_page
diff --git a/arch/alpha/lib/copy_user.S b/arch/alpha/lib/copy_user.S
new file mode 100644
index 000000000000..6f3fab9eb434
--- /dev/null
+++ b/arch/alpha/lib/copy_user.S
@@ -0,0 +1,145 @@
1/*
2 * arch/alpha/lib/copy_user.S
3 *
4 * Copy to/from user space, handling exceptions as we go.. This
5 * isn't exactly pretty.
6 *
7 * This is essentially the same as "memcpy()", but with a few twists.
8 * Notably, we have to make sure that $0 is always up-to-date and
9 * contains the right "bytes left to copy" value (and that it is updated
10 * only _after_ a successful copy). There is also some rather minor
11 * exception setup stuff..
12 *
13 * NOTE! This is not directly C-callable, because the calling semantics are
14 * different:
15 *
16 * Inputs:
17 * length in $0
18 * destination address in $6
19 * source address in $7
20 * return address in $28
21 *
22 * Outputs:
23 * bytes left to copy in $0
24 *
25 * Clobbers:
26 * $1,$2,$3,$4,$5,$6,$7
27 */
28
29/* Allow an exception for an insn; exit if we get one. */
30#define EXI(x,y...) \
31 99: x,##y; \
32 .section __ex_table,"a"; \
33 .long 99b - .; \
34 lda $31, $exitin-99b($31); \
35 .previous
36
37#define EXO(x,y...) \
38 99: x,##y; \
39 .section __ex_table,"a"; \
40 .long 99b - .; \
41 lda $31, $exitout-99b($31); \
42 .previous
43
44 .set noat
45 .align 4
46 .globl __copy_user
47 .ent __copy_user
48__copy_user:
49 .prologue 0
50 and $6,7,$3
51 beq $0,$35
52 beq $3,$36
53 subq $3,8,$3
54 .align 4
55$37:
56 EXI( ldq_u $1,0($7) )
57 EXO( ldq_u $2,0($6) )
58 extbl $1,$7,$1
59 mskbl $2,$6,$2
60 insbl $1,$6,$1
61 addq $3,1,$3
62 bis $1,$2,$1
63 EXO( stq_u $1,0($6) )
64 subq $0,1,$0
65 addq $6,1,$6
66 addq $7,1,$7
67 beq $0,$41
68 bne $3,$37
69$36:
70 and $7,7,$1
71 bic $0,7,$4
72 beq $1,$43
73 beq $4,$48
74 EXI( ldq_u $3,0($7) )
75 .align 4
76$50:
77 EXI( ldq_u $2,8($7) )
78 subq $4,8,$4
79 extql $3,$7,$3
80 extqh $2,$7,$1
81 bis $3,$1,$1
82 EXO( stq $1,0($6) )
83 addq $7,8,$7
84 subq $0,8,$0
85 addq $6,8,$6
86 bis $2,$2,$3
87 bne $4,$50
88$48:
89 beq $0,$41
90 .align 4
91$57:
92 EXI( ldq_u $1,0($7) )
93 EXO( ldq_u $2,0($6) )
94 extbl $1,$7,$1
95 mskbl $2,$6,$2
96 insbl $1,$6,$1
97 bis $1,$2,$1
98 EXO( stq_u $1,0($6) )
99 subq $0,1,$0
100 addq $6,1,$6
101 addq $7,1,$7
102 bne $0,$57
103 br $31,$41
104 .align 4
105$43:
106 beq $4,$65
107 .align 4
108$66:
109 EXI( ldq $1,0($7) )
110 subq $4,8,$4
111 EXO( stq $1,0($6) )
112 addq $7,8,$7
113 subq $0,8,$0
114 addq $6,8,$6
115 bne $4,$66
116$65:
117 beq $0,$41
118 EXI( ldq $2,0($7) )
119 EXO( ldq $1,0($6) )
120 mskql $2,$0,$2
121 mskqh $1,$0,$1
122 bis $2,$1,$2
123 EXO( stq $2,0($6) )
124 bis $31,$31,$0
125$41:
126$35:
127$exitout:
128 ret $31,($28),1
129
130$exitin:
131 /* A stupid byte-by-byte zeroing of the rest of the output
132 buffer. This cures security holes by never leaving
133 random kernel data around to be copied elsewhere. */
134
135 mov $0,$1
136$101:
137 EXO ( ldq_u $2,0($6) )
138 subq $1,1,$1
139 mskbl $2,$6,$2
140 EXO ( stq_u $2,0($6) )
141 addq $6,1,$6
142 bgt $1,$101
143 ret $31,($28),1
144
145 .end __copy_user
diff --git a/arch/alpha/lib/csum_ipv6_magic.S b/arch/alpha/lib/csum_ipv6_magic.S
new file mode 100644
index 000000000000..e09748dbf2ed
--- /dev/null
+++ b/arch/alpha/lib/csum_ipv6_magic.S
@@ -0,0 +1,92 @@
1/*
2 * arch/alpha/lib/csum_ipv6_magic.S
3 * Contributed by Richard Henderson <rth@tamu.edu>
4 *
5 * unsigned short csum_ipv6_magic(struct in6_addr *saddr,
6 * struct in6_addr *daddr,
7 * __u32 len,
8 * unsigned short proto,
9 * unsigned int csum);
10 */
11
12 .globl csum_ipv6_magic
13 .align 4
14 .ent csum_ipv6_magic
15 .frame $30,0,$26,0
16csum_ipv6_magic:
17 .prologue 0
18
19 ldq $0,0($16) # e0 : load src & dst addr words
20 zapnot $20,15,$20 # .. e1 : zero extend incoming csum
21 extqh $18,1,$4 # e0 : byte swap len & proto while we wait
22 ldq $1,8($16) # .. e1 :
23
24 extbl $18,1,$5 # e0 :
25 ldq $2,0($17) # .. e1 :
26 extbl $18,2,$6 # e0 :
27 ldq $3,8($17) # .. e1 :
28
29 extbl $18,3,$18 # e0 :
30 sra $4,32,$4 # e0 :
31 sll $5,16,$5 # e0 :
32 addq $20,$0,$20 # .. e1 : begin summing the words
33
34 sll $6,8,$6 # e0 :
35 cmpult $20,$0,$0 # .. e1 :
36 extwh $19,7,$7 # e0 :
37 or $4,$18,$18 # .. e1 :
38
39 extbl $19,1,$19 # e0 :
40 or $5,$6,$5 # .. e1 :
41 or $18,$5,$18 # e0 : len complete
42 or $19,$7,$19 # .. e1 :
43
44 sll $19,48,$19 # e0 :
45 addq $20,$1,$20 # .. e1 :
46 sra $19,32,$19 # e0 : proto complete
47 cmpult $20,$1,$1 # .. e1 :
48
49 nop # e0 :
50 addq $20,$2,$20 # .. e1 :
51 cmpult $20,$2,$2 # e0 :
52 addq $20,$3,$20 # .. e1 :
53
54 cmpult $20,$3,$3 # e0 :
55 addq $20,$18,$20 # .. e1 :
56 cmpult $20,$18,$18 # e0 :
57 addq $20,$19,$20 # .. e1 :
58
59 cmpult $20,$19,$19 # e0 :
60 addq $0,$1,$0 # .. e1 : merge the carries back into the csum
61 addq $2,$3,$2 # e0 :
62 addq $18,$19,$18 # .. e1 :
63
64 addq $0,$2,$0 # e0 :
65 addq $20,$18,$20 # .. e1 :
66 addq $0,$20,$0 # e0 :
67 unop # :
68
69 extwl $0,2,$2 # e0 : begin folding the 64-bit value
70 zapnot $0,3,$3 # .. e1 :
71 extwl $0,4,$1 # e0 :
72 addq $2,$3,$3 # .. e1 :
73
74 extwl $0,6,$0 # e0 :
75 addq $3,$1,$3 # .. e1 :
76 addq $0,$3,$0 # e0 :
77 unop # :
78
79 extwl $0,2,$1 # e0 : fold 18-bit value
80 zapnot $0,3,$0 # .. e1 :
81 addq $0,$1,$0 # e0 :
82 unop # :
83
84 extwl $0,2,$1 # e0 : fold 17-bit value
85 zapnot $0,3,$0 # .. e1 :
86 addq $0,$1,$0 # e0 :
87 not $0,$0 # e1 : and complement.
88
89 zapnot $0,3,$0 # e0 :
90 ret # .. e1 :
91
92 .end csum_ipv6_magic
diff --git a/arch/alpha/lib/csum_partial_copy.c b/arch/alpha/lib/csum_partial_copy.c
new file mode 100644
index 000000000000..a37948f3037a
--- /dev/null
+++ b/arch/alpha/lib/csum_partial_copy.c
@@ -0,0 +1,391 @@
1/*
2 * csum_partial_copy - do IP checksumming and copy
3 *
4 * (C) Copyright 1996 Linus Torvalds
5 * accellerated versions (and 21264 assembly versions ) contributed by
6 * Rick Gorton <rick.gorton@alpha-processor.com>
7 *
8 * Don't look at this too closely - you'll go mad. The things
9 * we do for performance..
10 */
11
12#include <linux/types.h>
13#include <linux/string.h>
14#include <asm/uaccess.h>
15
16
17#define ldq_u(x,y) \
18__asm__ __volatile__("ldq_u %0,%1":"=r" (x):"m" (*(const unsigned long *)(y)))
19
20#define stq_u(x,y) \
21__asm__ __volatile__("stq_u %1,%0":"=m" (*(unsigned long *)(y)):"r" (x))
22
23#define extql(x,y,z) \
24__asm__ __volatile__("extql %1,%2,%0":"=r" (z):"r" (x),"r" (y))
25
26#define extqh(x,y,z) \
27__asm__ __volatile__("extqh %1,%2,%0":"=r" (z):"r" (x),"r" (y))
28
29#define mskql(x,y,z) \
30__asm__ __volatile__("mskql %1,%2,%0":"=r" (z):"r" (x),"r" (y))
31
32#define mskqh(x,y,z) \
33__asm__ __volatile__("mskqh %1,%2,%0":"=r" (z):"r" (x),"r" (y))
34
35#define insql(x,y,z) \
36__asm__ __volatile__("insql %1,%2,%0":"=r" (z):"r" (x),"r" (y))
37
38#define insqh(x,y,z) \
39__asm__ __volatile__("insqh %1,%2,%0":"=r" (z):"r" (x),"r" (y))
40
41
42#define __get_user_u(x,ptr) \
43({ \
44 long __guu_err; \
45 __asm__ __volatile__( \
46 "1: ldq_u %0,%2\n" \
47 "2:\n" \
48 ".section __ex_table,\"a\"\n" \
49 " .long 1b - .\n" \
50 " lda %0,2b-1b(%1)\n" \
51 ".previous" \
52 : "=r"(x), "=r"(__guu_err) \
53 : "m"(__m(ptr)), "1"(0)); \
54 __guu_err; \
55})
56
57#define __put_user_u(x,ptr) \
58({ \
59 long __puu_err; \
60 __asm__ __volatile__( \
61 "1: stq_u %2,%1\n" \
62 "2:\n" \
63 ".section __ex_table,\"a\"\n" \
64 " .long 1b - ." \
65 " lda $31,2b-1b(%0)\n" \
66 ".previous" \
67 : "=r"(__puu_err) \
68 : "m"(__m(addr)), "rJ"(x), "0"(0)); \
69 __puu_err; \
70})
71
72
73static inline unsigned short from64to16(unsigned long x)
74{
75 /* Using extract instructions is a bit more efficient
76 than the original shift/bitmask version. */
77
78 union {
79 unsigned long ul;
80 unsigned int ui[2];
81 unsigned short us[4];
82 } in_v, tmp_v, out_v;
83
84 in_v.ul = x;
85 tmp_v.ul = (unsigned long) in_v.ui[0] + (unsigned long) in_v.ui[1];
86
87 /* Since the bits of tmp_v.sh[3] are going to always be zero,
88 we don't have to bother to add that in. */
89 out_v.ul = (unsigned long) tmp_v.us[0] + (unsigned long) tmp_v.us[1]
90 + (unsigned long) tmp_v.us[2];
91
92 /* Similarly, out_v.us[2] is always zero for the final add. */
93 return out_v.us[0] + out_v.us[1];
94}
95
96
97
98/*
99 * Ok. This isn't fun, but this is the EASY case.
100 */
101static inline unsigned long
102csum_partial_cfu_aligned(const unsigned long __user *src, unsigned long *dst,
103 long len, unsigned long checksum,
104 int *errp)
105{
106 unsigned long carry = 0;
107 int err = 0;
108
109 while (len >= 0) {
110 unsigned long word;
111 err |= __get_user(word, src);
112 checksum += carry;
113 src++;
114 checksum += word;
115 len -= 8;
116 carry = checksum < word;
117 *dst = word;
118 dst++;
119 }
120 len += 8;
121 checksum += carry;
122 if (len) {
123 unsigned long word, tmp;
124 err |= __get_user(word, src);
125 tmp = *dst;
126 mskql(word, len, word);
127 checksum += word;
128 mskqh(tmp, len, tmp);
129 carry = checksum < word;
130 *dst = word | tmp;
131 checksum += carry;
132 }
133 if (err) *errp = err;
134 return checksum;
135}
136
137/*
138 * This is even less fun, but this is still reasonably
139 * easy.
140 */
141static inline unsigned long
142csum_partial_cfu_dest_aligned(const unsigned long __user *src,
143 unsigned long *dst,
144 unsigned long soff,
145 long len, unsigned long checksum,
146 int *errp)
147{
148 unsigned long first;
149 unsigned long word, carry;
150 unsigned long lastsrc = 7+len+(unsigned long)src;
151 int err = 0;
152
153 err |= __get_user_u(first,src);
154 carry = 0;
155 while (len >= 0) {
156 unsigned long second;
157
158 err |= __get_user_u(second, src+1);
159 extql(first, soff, word);
160 len -= 8;
161 src++;
162 extqh(second, soff, first);
163 checksum += carry;
164 word |= first;
165 first = second;
166 checksum += word;
167 *dst = word;
168 dst++;
169 carry = checksum < word;
170 }
171 len += 8;
172 checksum += carry;
173 if (len) {
174 unsigned long tmp;
175 unsigned long second;
176 err |= __get_user_u(second, lastsrc);
177 tmp = *dst;
178 extql(first, soff, word);
179 extqh(second, soff, first);
180 word |= first;
181 mskql(word, len, word);
182 checksum += word;
183 mskqh(tmp, len, tmp);
184 carry = checksum < word;
185 *dst = word | tmp;
186 checksum += carry;
187 }
188 if (err) *errp = err;
189 return checksum;
190}
191
192/*
193 * This is slightly less fun than the above..
194 */
195static inline unsigned long
196csum_partial_cfu_src_aligned(const unsigned long __user *src,
197 unsigned long *dst,
198 unsigned long doff,
199 long len, unsigned long checksum,
200 unsigned long partial_dest,
201 int *errp)
202{
203 unsigned long carry = 0;
204 unsigned long word;
205 unsigned long second_dest;
206 int err = 0;
207
208 mskql(partial_dest, doff, partial_dest);
209 while (len >= 0) {
210 err |= __get_user(word, src);
211 len -= 8;
212 insql(word, doff, second_dest);
213 checksum += carry;
214 stq_u(partial_dest | second_dest, dst);
215 src++;
216 checksum += word;
217 insqh(word, doff, partial_dest);
218 carry = checksum < word;
219 dst++;
220 }
221 len += 8;
222 if (len) {
223 checksum += carry;
224 err |= __get_user(word, src);
225 mskql(word, len, word);
226 len -= 8;
227 checksum += word;
228 insql(word, doff, second_dest);
229 len += doff;
230 carry = checksum < word;
231 partial_dest |= second_dest;
232 if (len >= 0) {
233 stq_u(partial_dest, dst);
234 if (!len) goto out;
235 dst++;
236 insqh(word, doff, partial_dest);
237 }
238 doff = len;
239 }
240 ldq_u(second_dest, dst);
241 mskqh(second_dest, doff, second_dest);
242 stq_u(partial_dest | second_dest, dst);
243out:
244 checksum += carry;
245 if (err) *errp = err;
246 return checksum;
247}
248
249/*
250 * This is so totally un-fun that it's frightening. Don't
251 * look at this too closely, you'll go blind.
252 */
253static inline unsigned long
254csum_partial_cfu_unaligned(const unsigned long __user * src,
255 unsigned long * dst,
256 unsigned long soff, unsigned long doff,
257 long len, unsigned long checksum,
258 unsigned long partial_dest,
259 int *errp)
260{
261 unsigned long carry = 0;
262 unsigned long first;
263 unsigned long lastsrc;
264 int err = 0;
265
266 err |= __get_user_u(first, src);
267 lastsrc = 7+len+(unsigned long)src;
268 mskql(partial_dest, doff, partial_dest);
269 while (len >= 0) {
270 unsigned long second, word;
271 unsigned long second_dest;
272
273 err |= __get_user_u(second, src+1);
274 extql(first, soff, word);
275 checksum += carry;
276 len -= 8;
277 extqh(second, soff, first);
278 src++;
279 word |= first;
280 first = second;
281 insql(word, doff, second_dest);
282 checksum += word;
283 stq_u(partial_dest | second_dest, dst);
284 carry = checksum < word;
285 insqh(word, doff, partial_dest);
286 dst++;
287 }
288 len += doff;
289 checksum += carry;
290 if (len >= 0) {
291 unsigned long second, word;
292 unsigned long second_dest;
293
294 err |= __get_user_u(second, lastsrc);
295 extql(first, soff, word);
296 extqh(second, soff, first);
297 word |= first;
298 first = second;
299 mskql(word, len-doff, word);
300 checksum += word;
301 insql(word, doff, second_dest);
302 carry = checksum < word;
303 stq_u(partial_dest | second_dest, dst);
304 if (len) {
305 ldq_u(second_dest, dst+1);
306 insqh(word, doff, partial_dest);
307 mskqh(second_dest, len, second_dest);
308 stq_u(partial_dest | second_dest, dst+1);
309 }
310 checksum += carry;
311 } else {
312 unsigned long second, word;
313 unsigned long second_dest;
314
315 err |= __get_user_u(second, lastsrc);
316 extql(first, soff, word);
317 extqh(second, soff, first);
318 word |= first;
319 ldq_u(second_dest, dst);
320 mskql(word, len-doff, word);
321 checksum += word;
322 mskqh(second_dest, len, second_dest);
323 carry = checksum < word;
324 insql(word, doff, word);
325 stq_u(partial_dest | word | second_dest, dst);
326 checksum += carry;
327 }
328 if (err) *errp = err;
329 return checksum;
330}
331
332static unsigned int
333do_csum_partial_copy_from_user(const char __user *src, char *dst, int len,
334 unsigned int sum, int *errp)
335{
336 unsigned long checksum = (unsigned) sum;
337 unsigned long soff = 7 & (unsigned long) src;
338 unsigned long doff = 7 & (unsigned long) dst;
339
340 if (len) {
341 if (!doff) {
342 if (!soff)
343 checksum = csum_partial_cfu_aligned(
344 (const unsigned long __user *) src,
345 (unsigned long *) dst,
346 len-8, checksum, errp);
347 else
348 checksum = csum_partial_cfu_dest_aligned(
349 (const unsigned long __user *) src,
350 (unsigned long *) dst,
351 soff, len-8, checksum, errp);
352 } else {
353 unsigned long partial_dest;
354 ldq_u(partial_dest, dst);
355 if (!soff)
356 checksum = csum_partial_cfu_src_aligned(
357 (const unsigned long __user *) src,
358 (unsigned long *) dst,
359 doff, len-8, checksum,
360 partial_dest, errp);
361 else
362 checksum = csum_partial_cfu_unaligned(
363 (const unsigned long __user *) src,
364 (unsigned long *) dst,
365 soff, doff, len-8, checksum,
366 partial_dest, errp);
367 }
368 checksum = from64to16 (checksum);
369 }
370 return checksum;
371}
372
373unsigned int
374csum_partial_copy_from_user(const char __user *src, char *dst, int len,
375 unsigned int sum, int *errp)
376{
377 if (!access_ok(VERIFY_READ, src, len)) {
378 *errp = -EFAULT;
379 memset(dst, 0, len);
380 return sum;
381 }
382
383 return do_csum_partial_copy_from_user(src, dst, len, sum, errp);
384}
385
386unsigned int
387csum_partial_copy_nocheck(const char __user *src, char *dst, int len,
388 unsigned int sum)
389{
390 return do_csum_partial_copy_from_user(src, dst, len, sum, NULL);
391}
diff --git a/arch/alpha/lib/dbg_current.S b/arch/alpha/lib/dbg_current.S
new file mode 100644
index 000000000000..e6d071015f9b
--- /dev/null
+++ b/arch/alpha/lib/dbg_current.S
@@ -0,0 +1,29 @@
1/*
2 * arch/alpha/lib/dbg_current.S
3 * Contributed by Richard Henderson (rth@cygnus.com)
4 *
5 * Trap if we find current not correct.
6 */
7
8#include <asm/pal.h>
9
10 .text
11 .set noat
12
13 .globl _mcount
14 .ent _mcount
15_mcount:
16 .frame $30, 0, $28, 0
17 .prologue 0
18
19 lda $0, -0x4000($30)
20 cmpult $8, $30, $1
21 cmpule $0, $30, $2
22 and $1, $2, $3
23 bne $3, 1f
24
25 call_pal PAL_bugchk
26
271: ret $31, ($28), 1
28
29 .end _mcount
diff --git a/arch/alpha/lib/dbg_stackcheck.S b/arch/alpha/lib/dbg_stackcheck.S
new file mode 100644
index 000000000000..cc5ce3a5fcad
--- /dev/null
+++ b/arch/alpha/lib/dbg_stackcheck.S
@@ -0,0 +1,27 @@
1/*
2 * arch/alpha/lib/stackcheck.S
3 * Contributed by Richard Henderson (rth@tamu.edu)
4 *
5 * Verify that we have not overflowed the stack. Oops if we have.
6 */
7
8#include <asm/asm_offsets.h>
9
10 .text
11 .set noat
12
13 .align 3
14 .globl _mcount
15 .ent _mcount
16_mcount:
17 .frame $30, 0, $28, 0
18 .prologue 0
19
20 lda $0, TASK_SIZE($8)
21 cmpult $30, $0, $0
22 bne $0, 1f
23 ret ($28)
241: stq $31, -8($31) # oops me, damn it.
25 br 1b
26
27 .end _mcount
diff --git a/arch/alpha/lib/dbg_stackkill.S b/arch/alpha/lib/dbg_stackkill.S
new file mode 100644
index 000000000000..e09f2ae1e09e
--- /dev/null
+++ b/arch/alpha/lib/dbg_stackkill.S
@@ -0,0 +1,35 @@
1/*
2 * arch/alpha/lib/killstack.S
3 * Contributed by Richard Henderson (rth@cygnus.com)
4 *
5 * Clobber the balance of the kernel stack, hoping to catch
6 * uninitialized local variables in the act.
7 */
8
9#include <asm/asm_offsets.h>
10
11 .text
12 .set noat
13
14 .align 5
15 .globl _mcount
16 .ent _mcount
17_mcount:
18 .frame $30, 0, $28, 0
19 .prologue 0
20
21 ldi $0, 0xdeadbeef
22 lda $2, -STACK_SIZE
23 sll $0, 32, $1
24 and $30, $2, $2
25 or $0, $1, $0
26 lda $2, TASK_SIZE($2)
27 cmpult $2, $30, $1
28 beq $1, 2f
291: stq $0, 0($2)
30 addq $2, 8, $2
31 cmpult $2, $30, $1
32 bne $1, 1b
332: ret ($28)
34
35 .end _mcount
diff --git a/arch/alpha/lib/dec_and_lock.c b/arch/alpha/lib/dec_and_lock.c
new file mode 100644
index 000000000000..6ae2500a9d9e
--- /dev/null
+++ b/arch/alpha/lib/dec_and_lock.c
@@ -0,0 +1,42 @@
1/*
2 * arch/alpha/lib/dec_and_lock.c
3 *
4 * ll/sc version of atomic_dec_and_lock()
5 *
6 */
7
8#include <linux/spinlock.h>
9#include <asm/atomic.h>
10
11 asm (".text \n\
12 .global _atomic_dec_and_lock \n\
13 .ent _atomic_dec_and_lock \n\
14 .align 4 \n\
15_atomic_dec_and_lock: \n\
16 .prologue 0 \n\
171: ldl_l $1, 0($16) \n\
18 subl $1, 1, $1 \n\
19 beq $1, 2f \n\
20 stl_c $1, 0($16) \n\
21 beq $1, 4f \n\
22 mb \n\
23 clr $0 \n\
24 ret \n\
252: br $29, 3f \n\
263: ldgp $29, 0($29) \n\
27 br $atomic_dec_and_lock_1..ng \n\
28 .subsection 2 \n\
294: br 1b \n\
30 .previous \n\
31 .end _atomic_dec_and_lock");
32
33static int __attribute_used__
34atomic_dec_and_lock_1(atomic_t *atomic, spinlock_t *lock)
35{
36 /* Slow path */
37 spin_lock(lock);
38 if (atomic_dec_and_test(atomic))
39 return 1;
40 spin_unlock(lock);
41 return 0;
42}
diff --git a/arch/alpha/lib/divide.S b/arch/alpha/lib/divide.S
new file mode 100644
index 000000000000..2d1a0484a99e
--- /dev/null
+++ b/arch/alpha/lib/divide.S
@@ -0,0 +1,195 @@
1/*
2 * arch/alpha/lib/divide.S
3 *
4 * (C) 1995 Linus Torvalds
5 *
6 * Alpha division..
7 */
8
9/*
10 * The alpha chip doesn't provide hardware division, so we have to do it
11 * by hand. The compiler expects the functions
12 *
13 * __divqu: 64-bit unsigned long divide
14 * __remqu: 64-bit unsigned long remainder
15 * __divqs/__remqs: signed 64-bit
16 * __divlu/__remlu: unsigned 32-bit
17 * __divls/__remls: signed 32-bit
18 *
19 * These are not normal C functions: instead of the normal
20 * calling sequence, these expect their arguments in registers
21 * $24 and $25, and return the result in $27. Register $28 may
22 * be clobbered (assembly temporary), anything else must be saved.
23 *
24 * In short: painful.
25 *
26 * This is a rather simple bit-at-a-time algorithm: it's very good
27 * at dividing random 64-bit numbers, but the more usual case where
28 * the divisor is small is handled better by the DEC algorithm
29 * using lookup tables. This uses much less memory, though, and is
30 * nicer on the cache.. Besides, I don't know the copyright status
31 * of the DEC code.
32 */
33
34/*
35 * My temporaries:
36 * $0 - current bit
37 * $1 - shifted divisor
38 * $2 - modulus/quotient
39 *
40 * $23 - return address
41 * $24 - dividend
42 * $25 - divisor
43 *
44 * $27 - quotient/modulus
45 * $28 - compare status
46 */
47
48#define halt .long 0
49
50/*
51 * Select function type and registers
52 */
53#define mask $0
54#define divisor $1
55#define compare $28
56#define tmp1 $3
57#define tmp2 $4
58
59#ifdef DIV
60#define DIV_ONLY(x,y...) x,##y
61#define MOD_ONLY(x,y...)
62#define func(x) __div##x
63#define modulus $2
64#define quotient $27
65#define GETSIGN(x) xor $24,$25,x
66#define STACK 48
67#else
68#define DIV_ONLY(x,y...)
69#define MOD_ONLY(x,y...) x,##y
70#define func(x) __rem##x
71#define modulus $27
72#define quotient $2
73#define GETSIGN(x) bis $24,$24,x
74#define STACK 32
75#endif
76
77/*
78 * For 32-bit operations, we need to extend to 64-bit
79 */
80#ifdef INTSIZE
81#define ufunction func(lu)
82#define sfunction func(l)
83#define LONGIFY(x) zapnot x,15,x
84#define SLONGIFY(x) addl x,0,x
85#else
86#define ufunction func(qu)
87#define sfunction func(q)
88#define LONGIFY(x)
89#define SLONGIFY(x)
90#endif
91
92.set noat
93.align 3
94.globl ufunction
95.ent ufunction
96ufunction:
97 subq $30,STACK,$30
98 .frame $30,STACK,$23
99 .prologue 0
100
1017: stq $1, 0($30)
102 bis $25,$25,divisor
103 stq $2, 8($30)
104 bis $24,$24,modulus
105 stq $0,16($30)
106 bis $31,$31,quotient
107 LONGIFY(divisor)
108 stq tmp1,24($30)
109 LONGIFY(modulus)
110 bis $31,1,mask
111 DIV_ONLY(stq tmp2,32($30))
112 beq divisor, 9f /* div by zero */
113
114#ifdef INTSIZE
115 /*
116 * shift divisor left, using 3-bit shifts for
117 * 32-bit divides as we can't overflow. Three-bit
118 * shifts will result in looping three times less
119 * here, but can result in two loops more later.
120 * Thus using a large shift isn't worth it (and
121 * s8add pairs better than a sll..)
122 */
1231: cmpult divisor,modulus,compare
124 s8addq divisor,$31,divisor
125 s8addq mask,$31,mask
126 bne compare,1b
127#else
1281: cmpult divisor,modulus,compare
129 blt divisor, 2f
130 addq divisor,divisor,divisor
131 addq mask,mask,mask
132 bne compare,1b
133 unop
134#endif
135
136 /* ok, start to go right again.. */
1372: DIV_ONLY(addq quotient,mask,tmp2)
138 srl mask,1,mask
139 cmpule divisor,modulus,compare
140 subq modulus,divisor,tmp1
141 DIV_ONLY(cmovne compare,tmp2,quotient)
142 srl divisor,1,divisor
143 cmovne compare,tmp1,modulus
144 bne mask,2b
145
1469: ldq $1, 0($30)
147 ldq $2, 8($30)
148 ldq $0,16($30)
149 ldq tmp1,24($30)
150 DIV_ONLY(ldq tmp2,32($30))
151 addq $30,STACK,$30
152 ret $31,($23),1
153 .end ufunction
154
155/*
156 * Uhh.. Ugly signed division. I'd rather not have it at all, but
157 * it's needed in some circumstances. There are different ways to
158 * handle this, really. This does:
159 * -a / b = a / -b = -(a / b)
160 * -a % b = -(a % b)
161 * a % -b = a % b
162 * which is probably not the best solution, but at least should
163 * have the property that (x/y)*y + (x%y) = x.
164 */
165.align 3
166.globl sfunction
167.ent sfunction
168sfunction:
169 subq $30,STACK,$30
170 .frame $30,STACK,$23
171 .prologue 0
172 bis $24,$25,$28
173 SLONGIFY($28)
174 bge $28,7b
175 stq $24,0($30)
176 subq $31,$24,$28
177 stq $25,8($30)
178 cmovlt $24,$28,$24 /* abs($24) */
179 stq $23,16($30)
180 subq $31,$25,$28
181 stq tmp1,24($30)
182 cmovlt $25,$28,$25 /* abs($25) */
183 unop
184 bsr $23,ufunction
185 ldq $24,0($30)
186 ldq $25,8($30)
187 GETSIGN($28)
188 subq $31,$27,tmp1
189 SLONGIFY($28)
190 ldq $23,16($30)
191 cmovlt $28,tmp1,$27
192 ldq tmp1,24($30)
193 addq $30,STACK,$30
194 ret $31,($23),1
195 .end sfunction
diff --git a/arch/alpha/lib/ev6-clear_page.S b/arch/alpha/lib/ev6-clear_page.S
new file mode 100644
index 000000000000..adf4f7be0e2b
--- /dev/null
+++ b/arch/alpha/lib/ev6-clear_page.S
@@ -0,0 +1,54 @@
1/*
2 * arch/alpha/lib/ev6-clear_page.S
3 *
4 * Zero an entire page.
5 */
6
7 .text
8 .align 4
9 .global clear_page
10 .ent clear_page
11clear_page:
12 .prologue 0
13
14 lda $0,128
15 lda $1,125
16 addq $16,64,$2
17 addq $16,128,$3
18
19 addq $16,192,$17
20 wh64 ($16)
21 wh64 ($2)
22 wh64 ($3)
23
241: wh64 ($17)
25 stq $31,0($16)
26 subq $0,1,$0
27 subq $1,1,$1
28
29 stq $31,8($16)
30 stq $31,16($16)
31 addq $17,64,$2
32 nop
33
34 stq $31,24($16)
35 stq $31,32($16)
36 cmovgt $1,$2,$17
37 nop
38
39 stq $31,40($16)
40 stq $31,48($16)
41 nop
42 nop
43
44 stq $31,56($16)
45 addq $16,64,$16
46 nop
47 bne $0,1b
48
49 ret
50 nop
51 nop
52 nop
53
54 .end clear_page
diff --git a/arch/alpha/lib/ev6-clear_user.S b/arch/alpha/lib/ev6-clear_user.S
new file mode 100644
index 000000000000..4f42a16b7f53
--- /dev/null
+++ b/arch/alpha/lib/ev6-clear_user.S
@@ -0,0 +1,225 @@
1/*
2 * arch/alpha/lib/ev6-clear_user.S
3 * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
4 *
5 * Zero user space, handling exceptions as we go.
6 *
7 * We have to make sure that $0 is always up-to-date and contains the
8 * right "bytes left to zero" value (and that it is updated only _after_
9 * a successful copy). There is also some rather minor exception setup
10 * stuff.
11 *
12 * NOTE! This is not directly C-callable, because the calling semantics
13 * are different:
14 *
15 * Inputs:
16 * length in $0
17 * destination address in $6
18 * exception pointer in $7
19 * return address in $28 (exceptions expect it there)
20 *
21 * Outputs:
22 * bytes left to copy in $0
23 *
24 * Clobbers:
25 * $1,$2,$3,$4,$5,$6
26 *
27 * Much of the information about 21264 scheduling/coding comes from:
28 * Compiler Writer's Guide for the Alpha 21264
29 * abbreviated as 'CWG' in other comments here
30 * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
31 * Scheduling notation:
32 * E - either cluster
33 * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
34 * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
35 * Try not to change the actual algorithm if possible for consistency.
36 * Determining actual stalls (other than slotting) doesn't appear to be easy to do.
37 * From perusing the source code context where this routine is called, it is
38 * a fair assumption that significant fractions of entire pages are zeroed, so
39 * it's going to be worth the effort to hand-unroll a big loop, and use wh64.
40 * ASSUMPTION:
41 * The believed purpose of only updating $0 after a store is that a signal
42 * may come along during the execution of this chunk of code, and we don't
43 * want to leave a hole (and we also want to avoid repeating lots of work)
44 */
45
46/* Allow an exception for an insn; exit if we get one. */
47#define EX(x,y...) \
48 99: x,##y; \
49 .section __ex_table,"a"; \
50 .long 99b - .; \
51 lda $31, $exception-99b($31); \
52 .previous
53
54 .set noat
55 .set noreorder
56 .align 4
57
58 .globl __do_clear_user
59 .ent __do_clear_user
60 .frame $30, 0, $28
61 .prologue 0
62
63 # Pipeline info : Slotting & Comments
64__do_clear_user:
65 and $6, 7, $4 # .. E .. .. : find dest head misalignment
66 beq $0, $zerolength # U .. .. .. : U L U L
67
68 addq $0, $4, $1 # .. .. .. E : bias counter
69 and $1, 7, $2 # .. .. E .. : number of misaligned bytes in tail
70# Note - we never actually use $2, so this is a moot computation
71# and we can rewrite this later...
72 srl $1, 3, $1 # .. E .. .. : number of quadwords to clear
73 beq $4, $headalign # U .. .. .. : U L U L
74
75/*
76 * Head is not aligned. Write (8 - $4) bytes to head of destination
77 * This means $6 is known to be misaligned
78 */
79 EX( ldq_u $5, 0($6) ) # .. .. .. L : load dst word to mask back in
80 beq $1, $onebyte # .. .. U .. : sub-word store?
81 mskql $5, $6, $5 # .. U .. .. : take care of misaligned head
82 addq $6, 8, $6 # E .. .. .. : L U U L
83
84 EX( stq_u $5, -8($6) ) # .. .. .. L :
85 subq $1, 1, $1 # .. .. E .. :
86 addq $0, $4, $0 # .. E .. .. : bytes left -= 8 - misalignment
87 subq $0, 8, $0 # E .. .. .. : U L U L
88
89 .align 4
90/*
91 * (The .align directive ought to be a moot point)
92 * values upon initial entry to the loop
93 * $1 is number of quadwords to clear (zero is a valid value)
94 * $2 is number of trailing bytes (0..7) ($2 never used...)
95 * $6 is known to be aligned 0mod8
96 */
97$headalign:
98 subq $1, 16, $4 # .. .. .. E : If < 16, we can not use the huge loop
99 and $6, 0x3f, $2 # .. .. E .. : Forward work for huge loop
100 subq $2, 0x40, $3 # .. E .. .. : bias counter (huge loop)
101 blt $4, $trailquad # U .. .. .. : U L U L
102
103/*
104 * We know that we're going to do at least 16 quads, which means we are
105 * going to be able to use the large block clear loop at least once.
106 * Figure out how many quads we need to clear before we are 0mod64 aligned
107 * so we can use the wh64 instruction.
108 */
109
110 nop # .. .. .. E
111 nop # .. .. E ..
112 nop # .. E .. ..
113 beq $3, $bigalign # U .. .. .. : U L U L : Aligned 0mod64
114
115$alignmod64:
116 EX( stq_u $31, 0($6) ) # .. .. .. L
117 addq $3, 8, $3 # .. .. E ..
118 subq $0, 8, $0 # .. E .. ..
119 nop # E .. .. .. : U L U L
120
121 nop # .. .. .. E
122 subq $1, 1, $1 # .. .. E ..
123 addq $6, 8, $6 # .. E .. ..
124 blt $3, $alignmod64 # U .. .. .. : U L U L
125
126$bigalign:
127/*
128 * $0 is the number of bytes left
129 * $1 is the number of quads left
130 * $6 is aligned 0mod64
131 * we know that we'll be taking a minimum of one trip through
132 * CWG Section 3.7.6: do not expect a sustained store rate of > 1/cycle
133 * We are _not_ going to update $0 after every single store. That
134 * would be silly, because there will be cross-cluster dependencies
135 * no matter how the code is scheduled. By doing it in slightly
136 * staggered fashion, we can still do this loop in 5 fetches
137 * The worse case will be doing two extra quads in some future execution,
138 * in the event of an interrupted clear.
139 * Assumes the wh64 needs to be for 2 trips through the loop in the future
140 * The wh64 is issued on for the starting destination address for trip +2
141 * through the loop, and if there are less than two trips left, the target
142 * address will be for the current trip.
143 */
144 nop # E :
145 nop # E :
146 nop # E :
147 bis $6,$6,$3 # E : U L U L : Initial wh64 address is dest
148 /* This might actually help for the current trip... */
149
150$do_wh64:
151 wh64 ($3) # .. .. .. L1 : memory subsystem hint
152 subq $1, 16, $4 # .. .. E .. : Forward calculation - repeat the loop?
153 EX( stq_u $31, 0($6) ) # .. L .. ..
154 subq $0, 8, $0 # E .. .. .. : U L U L
155
156 addq $6, 128, $3 # E : Target address of wh64
157 EX( stq_u $31, 8($6) ) # L :
158 EX( stq_u $31, 16($6) ) # L :
159 subq $0, 16, $0 # E : U L L U
160
161 nop # E :
162 EX( stq_u $31, 24($6) ) # L :
163 EX( stq_u $31, 32($6) ) # L :
164 subq $0, 168, $5 # E : U L L U : two trips through the loop left?
165 /* 168 = 192 - 24, since we've already completed some stores */
166
167 subq $0, 16, $0 # E :
168 EX( stq_u $31, 40($6) ) # L :
169 EX( stq_u $31, 48($6) ) # L :
170 cmovlt $5, $6, $3 # E : U L L U : Latency 2, extra mapping cycle
171
172 subq $1, 8, $1 # E :
173 subq $0, 16, $0 # E :
174 EX( stq_u $31, 56($6) ) # L :
175 nop # E : U L U L
176
177 nop # E :
178 subq $0, 8, $0 # E :
179 addq $6, 64, $6 # E :
180 bge $4, $do_wh64 # U : U L U L
181
182$trailquad:
183 # zero to 16 quadwords left to store, plus any trailing bytes
184 # $1 is the number of quadwords left to go.
185 #
186 nop # .. .. .. E
187 nop # .. .. E ..
188 nop # .. E .. ..
189 beq $1, $trailbytes # U .. .. .. : U L U L : Only 0..7 bytes to go
190
191$onequad:
192 EX( stq_u $31, 0($6) ) # .. .. .. L
193 subq $1, 1, $1 # .. .. E ..
194 subq $0, 8, $0 # .. E .. ..
195 nop # E .. .. .. : U L U L
196
197 nop # .. .. .. E
198 nop # .. .. E ..
199 addq $6, 8, $6 # .. E .. ..
200 bgt $1, $onequad # U .. .. .. : U L U L
201
202 # We have an unknown number of bytes left to go.
203$trailbytes:
204 nop # .. .. .. E
205 nop # .. .. E ..
206 nop # .. E .. ..
207 beq $0, $zerolength # U .. .. .. : U L U L
208
209 # $0 contains the number of bytes left to copy (0..31)
210 # so we will use $0 as the loop counter
211 # We know for a fact that $0 > 0 zero due to previous context
212$onebyte:
213 EX( stb $31, 0($6) ) # .. .. .. L
214 subq $0, 1, $0 # .. .. E .. :
215 addq $6, 1, $6 # .. E .. .. :
216 bgt $0, $onebyte # U .. .. .. : U L U L
217
218$zerolength:
219$exception: # Destination for exception recovery(?)
220 nop # .. .. .. E :
221 nop # .. .. E .. :
222 nop # .. E .. .. :
223 ret $31, ($28), 1 # L0 .. .. .. : L U L U
224 .end __do_clear_user
225
diff --git a/arch/alpha/lib/ev6-copy_page.S b/arch/alpha/lib/ev6-copy_page.S
new file mode 100644
index 000000000000..b789db192754
--- /dev/null
+++ b/arch/alpha/lib/ev6-copy_page.S
@@ -0,0 +1,203 @@
1/*
2 * arch/alpha/lib/ev6-copy_page.S
3 *
4 * Copy an entire page.
5 */
6
7/* The following comparison of this routine vs the normal copy_page.S
8 was written by an unnamed ev6 hardware designer and forwarded to me
9 via Steven Hobbs <hobbs@steven.zko.dec.com>.
10
11 First Problem: STQ overflows.
12 -----------------------------
13
14 It would be nice if EV6 handled every resource overflow efficiently,
15 but for some it doesn't. Including store queue overflows. It causes
16 a trap and a restart of the pipe.
17
18 To get around this we sometimes use (to borrow a term from a VSSAD
19 researcher) "aeration". The idea is to slow the rate at which the
20 processor receives valid instructions by inserting nops in the fetch
21 path. In doing so, you can prevent the overflow and actually make
22 the code run faster. You can, of course, take advantage of the fact
23 that the processor can fetch at most 4 aligned instructions per cycle.
24
25 I inserted enough nops to force it to take 10 cycles to fetch the
26 loop code. In theory, EV6 should be able to execute this loop in
27 9 cycles but I was not able to get it to run that fast -- the initial
28 conditions were such that I could not reach this optimum rate on
29 (chaotic) EV6. I wrote the code such that everything would issue
30 in order.
31
32 Second Problem: Dcache index matches.
33 -------------------------------------
34
35 If you are going to use this routine on random aligned pages, there
36 is a 25% chance that the pages will be at the same dcache indices.
37 This results in many nasty memory traps without care.
38
39 The solution is to schedule the prefetches to avoid the memory
40 conflicts. I schedule the wh64 prefetches farther ahead of the
41 read prefetches to avoid this problem.
42
43 Third Problem: Needs more prefetching.
44 --------------------------------------
45
46 In order to improve the code I added deeper prefetching to take the
47 most advantage of EV6's bandwidth.
48
49 I also prefetched the read stream. Note that adding the read prefetch
50 forced me to add another cycle to the inner-most kernel - up to 11
51 from the original 8 cycles per iteration. We could improve performance
52 further by unrolling the loop and doing multiple prefetches per cycle.
53
54 I think that the code below will be very robust and fast code for the
55 purposes of copying aligned pages. It is slower when both source and
56 destination pages are in the dcache, but it is my guess that this is
57 less important than the dcache miss case. */
58
59
60 .text
61 .align 4
62 .global copy_page
63 .ent copy_page
64copy_page:
65 .prologue 0
66
67 /* Prefetch 5 read cachelines; write-hint 10 cache lines. */
68 wh64 ($16)
69 ldl $31,0($17)
70 ldl $31,64($17)
71 lda $1,1*64($16)
72
73 wh64 ($1)
74 ldl $31,128($17)
75 ldl $31,192($17)
76 lda $1,2*64($16)
77
78 wh64 ($1)
79 ldl $31,256($17)
80 lda $18,118
81 lda $1,3*64($16)
82
83 wh64 ($1)
84 nop
85 lda $1,4*64($16)
86 lda $2,5*64($16)
87
88 wh64 ($1)
89 wh64 ($2)
90 lda $1,6*64($16)
91 lda $2,7*64($16)
92
93 wh64 ($1)
94 wh64 ($2)
95 lda $1,8*64($16)
96 lda $2,9*64($16)
97
98 wh64 ($1)
99 wh64 ($2)
100 lda $19,10*64($16)
101 nop
102
103 /* Main prefetching/write-hinting loop. */
1041: ldq $0,0($17)
105 ldq $1,8($17)
106 unop
107 unop
108
109 unop
110 unop
111 ldq $2,16($17)
112 ldq $3,24($17)
113
114 ldq $4,32($17)
115 ldq $5,40($17)
116 unop
117 unop
118
119 unop
120 unop
121 ldq $6,48($17)
122 ldq $7,56($17)
123
124 ldl $31,320($17)
125 unop
126 unop
127 unop
128
129 /* This gives the extra cycle of aeration above the minimum. */
130 unop
131 unop
132 unop
133 unop
134
135 wh64 ($19)
136 unop
137 unop
138 unop
139
140 stq $0,0($16)
141 subq $18,1,$18
142 stq $1,8($16)
143 unop
144
145 unop
146 stq $2,16($16)
147 addq $17,64,$17
148 stq $3,24($16)
149
150 stq $4,32($16)
151 stq $5,40($16)
152 addq $19,64,$19
153 unop
154
155 stq $6,48($16)
156 stq $7,56($16)
157 addq $16,64,$16
158 bne $18, 1b
159
160 /* Prefetch the final 5 cache lines of the read stream. */
161 lda $18,10
162 ldl $31,320($17)
163 ldl $31,384($17)
164 ldl $31,448($17)
165
166 ldl $31,512($17)
167 ldl $31,576($17)
168 nop
169 nop
170
171 /* Non-prefetching, non-write-hinting cleanup loop for the
172 final 10 cache lines. */
1732: ldq $0,0($17)
174 ldq $1,8($17)
175 ldq $2,16($17)
176 ldq $3,24($17)
177
178 ldq $4,32($17)
179 ldq $5,40($17)
180 ldq $6,48($17)
181 ldq $7,56($17)
182
183 stq $0,0($16)
184 subq $18,1,$18
185 stq $1,8($16)
186 addq $17,64,$17
187
188 stq $2,16($16)
189 stq $3,24($16)
190 stq $4,32($16)
191 stq $5,40($16)
192
193 stq $6,48($16)
194 stq $7,56($16)
195 addq $16,64,$16
196 bne $18, 2b
197
198 ret
199 nop
200 unop
201 nop
202
203 .end copy_page
diff --git a/arch/alpha/lib/ev6-copy_user.S b/arch/alpha/lib/ev6-copy_user.S
new file mode 100644
index 000000000000..db42ffe9c350
--- /dev/null
+++ b/arch/alpha/lib/ev6-copy_user.S
@@ -0,0 +1,259 @@
1/*
2 * arch/alpha/lib/ev6-copy_user.S
3 *
4 * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
5 *
6 * Copy to/from user space, handling exceptions as we go.. This
7 * isn't exactly pretty.
8 *
9 * This is essentially the same as "memcpy()", but with a few twists.
10 * Notably, we have to make sure that $0 is always up-to-date and
11 * contains the right "bytes left to copy" value (and that it is updated
12 * only _after_ a successful copy). There is also some rather minor
13 * exception setup stuff..
14 *
15 * NOTE! This is not directly C-callable, because the calling semantics are
16 * different:
17 *
18 * Inputs:
19 * length in $0
20 * destination address in $6
21 * source address in $7
22 * return address in $28
23 *
24 * Outputs:
25 * bytes left to copy in $0
26 *
27 * Clobbers:
28 * $1,$2,$3,$4,$5,$6,$7
29 *
30 * Much of the information about 21264 scheduling/coding comes from:
31 * Compiler Writer's Guide for the Alpha 21264
32 * abbreviated as 'CWG' in other comments here
33 * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
34 * Scheduling notation:
35 * E - either cluster
36 * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
37 * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
38 */
39
40/* Allow an exception for an insn; exit if we get one. */
41#define EXI(x,y...) \
42 99: x,##y; \
43 .section __ex_table,"a"; \
44 .long 99b - .; \
45 lda $31, $exitin-99b($31); \
46 .previous
47
48#define EXO(x,y...) \
49 99: x,##y; \
50 .section __ex_table,"a"; \
51 .long 99b - .; \
52 lda $31, $exitout-99b($31); \
53 .previous
54
55 .set noat
56 .align 4
57 .globl __copy_user
58 .ent __copy_user
59 # Pipeline info: Slotting & Comments
60__copy_user:
61 .prologue 0
62 subq $0, 32, $1 # .. E .. .. : Is this going to be a small copy?
63 beq $0, $zerolength # U .. .. .. : U L U L
64
65 and $6,7,$3 # .. .. .. E : is leading dest misalignment
66 ble $1, $onebyteloop # .. .. U .. : 1st branch : small amount of data
67 beq $3, $destaligned # .. U .. .. : 2nd (one cycle fetcher stall)
68 subq $3, 8, $3 # E .. .. .. : L U U L : trip counter
69/*
70 * The fetcher stall also hides the 1 cycle cross-cluster stall for $3 (L --> U)
71 * This loop aligns the destination a byte at a time
72 * We know we have at least one trip through this loop
73 */
74$aligndest:
75 EXI( ldbu $1,0($7) ) # .. .. .. L : Keep loads separate from stores
76 addq $6,1,$6 # .. .. E .. : Section 3.8 in the CWG
77 addq $3,1,$3 # .. E .. .. :
78 nop # E .. .. .. : U L U L
79
80/*
81 * the -1 is to compensate for the inc($6) done in a previous quadpack
82 * which allows us zero dependencies within either quadpack in the loop
83 */
84 EXO( stb $1,-1($6) ) # .. .. .. L :
85 addq $7,1,$7 # .. .. E .. : Section 3.8 in the CWG
86 subq $0,1,$0 # .. E .. .. :
87 bne $3, $aligndest # U .. .. .. : U L U L
88
89/*
90 * If we fell through into here, we have a minimum of 33 - 7 bytes
91 * If we arrived via branch, we have a minimum of 32 bytes
92 */
93$destaligned:
94 and $7,7,$1 # .. .. .. E : Check _current_ source alignment
95 bic $0,7,$4 # .. .. E .. : number bytes as a quadword loop
96 EXI( ldq_u $3,0($7) ) # .. L .. .. : Forward fetch for fallthrough code
97 beq $1,$quadaligned # U .. .. .. : U L U L
98
99/*
100 * In the worst case, we've just executed an ldq_u here from 0($7)
101 * and we'll repeat it once if we take the branch
102 */
103
104/* Misaligned quadword loop - not unrolled. Leave it that way. */
105$misquad:
106 EXI( ldq_u $2,8($7) ) # .. .. .. L :
107 subq $4,8,$4 # .. .. E .. :
108 extql $3,$7,$3 # .. U .. .. :
109 extqh $2,$7,$1 # U .. .. .. : U U L L
110
111 bis $3,$1,$1 # .. .. .. E :
112 EXO( stq $1,0($6) ) # .. .. L .. :
113 addq $7,8,$7 # .. E .. .. :
114 subq $0,8,$0 # E .. .. .. : U L L U
115
116 addq $6,8,$6 # .. .. .. E :
117 bis $2,$2,$3 # .. .. E .. :
118 nop # .. E .. .. :
119 bne $4,$misquad # U .. .. .. : U L U L
120
121 nop # .. .. .. E
122 nop # .. .. E ..
123 nop # .. E .. ..
124 beq $0,$zerolength # U .. .. .. : U L U L
125
126/* We know we have at least one trip through the byte loop */
127 EXI ( ldbu $2,0($7) ) # .. .. .. L : No loads in the same quad
128 addq $6,1,$6 # .. .. E .. : as the store (Section 3.8 in CWG)
129 nop # .. E .. .. :
130 br $31, $dirtyentry # L0 .. .. .. : L U U L
131/* Do the trailing byte loop load, then hop into the store part of the loop */
132
133/*
134 * A minimum of (33 - 7) bytes to do a quad at a time.
135 * Based upon the usage context, it's worth the effort to unroll this loop
136 * $0 - number of bytes to be moved
137 * $4 - number of bytes to move as quadwords
138 * $6 is current destination address
139 * $7 is current source address
140 */
141$quadaligned:
142 subq $4, 32, $2 # .. .. .. E : do not unroll for small stuff
143 nop # .. .. E ..
144 nop # .. E .. ..
145 blt $2, $onequad # U .. .. .. : U L U L
146
147/*
148 * There is a significant assumption here that the source and destination
149 * addresses differ by more than 32 bytes. In this particular case, a
150 * sparsity of registers further bounds this to be a minimum of 8 bytes.
151 * But if this isn't met, then the output result will be incorrect.
152 * Furthermore, due to a lack of available registers, we really can't
153 * unroll this to be an 8x loop (which would enable us to use the wh64
154 * instruction memory hint instruction).
155 */
156$unroll4:
157 EXI( ldq $1,0($7) ) # .. .. .. L
158 EXI( ldq $2,8($7) ) # .. .. L ..
159 subq $4,32,$4 # .. E .. ..
160 nop # E .. .. .. : U U L L
161
162 addq $7,16,$7 # .. .. .. E
163 EXO( stq $1,0($6) ) # .. .. L ..
164 EXO( stq $2,8($6) ) # .. L .. ..
165 subq $0,16,$0 # E .. .. .. : U L L U
166
167 addq $6,16,$6 # .. .. .. E
168 EXI( ldq $1,0($7) ) # .. .. L ..
169 EXI( ldq $2,8($7) ) # .. L .. ..
170 subq $4, 32, $3 # E .. .. .. : U U L L : is there enough for another trip?
171
172 EXO( stq $1,0($6) ) # .. .. .. L
173 EXO( stq $2,8($6) ) # .. .. L ..
174 subq $0,16,$0 # .. E .. ..
175 addq $7,16,$7 # E .. .. .. : U L L U
176
177 nop # .. .. .. E
178 nop # .. .. E ..
179 addq $6,16,$6 # .. E .. ..
180 bgt $3,$unroll4 # U .. .. .. : U L U L
181
182 nop
183 nop
184 nop
185 beq $4, $noquads
186
187$onequad:
188 EXI( ldq $1,0($7) )
189 subq $4,8,$4
190 addq $7,8,$7
191 nop
192
193 EXO( stq $1,0($6) )
194 subq $0,8,$0
195 addq $6,8,$6
196 bne $4,$onequad
197
198$noquads:
199 nop
200 nop
201 nop
202 beq $0,$zerolength
203
204/*
205 * For small copies (or the tail of a larger copy), do a very simple byte loop.
206 * There's no point in doing a lot of complex alignment calculations to try to
207 * to quadword stuff for a small amount of data.
208 * $0 - remaining number of bytes left to copy
209 * $6 - current dest addr
210 * $7 - current source addr
211 */
212
213$onebyteloop:
214 EXI ( ldbu $2,0($7) ) # .. .. .. L : No loads in the same quad
215 addq $6,1,$6 # .. .. E .. : as the store (Section 3.8 in CWG)
216 nop # .. E .. .. :
217 nop # E .. .. .. : U L U L
218
219$dirtyentry:
220/*
221 * the -1 is to compensate for the inc($6) done in a previous quadpack
222 * which allows us zero dependencies within either quadpack in the loop
223 */
224 EXO ( stb $2,-1($6) ) # .. .. .. L :
225 addq $7,1,$7 # .. .. E .. : quadpack as the load
226 subq $0,1,$0 # .. E .. .. : change count _after_ copy
227 bgt $0,$onebyteloop # U .. .. .. : U L U L
228
229$zerolength:
230$exitout: # Destination for exception recovery(?)
231 nop # .. .. .. E
232 nop # .. .. E ..
233 nop # .. E .. ..
234 ret $31,($28),1 # L0 .. .. .. : L U L U
235
236$exitin:
237
238 /* A stupid byte-by-byte zeroing of the rest of the output
239 buffer. This cures security holes by never leaving
240 random kernel data around to be copied elsewhere. */
241
242 nop
243 nop
244 nop
245 mov $0,$1
246
247$101:
248 EXO ( stb $31,0($6) ) # L
249 subq $1,1,$1 # E
250 addq $6,1,$6 # E
251 bgt $1,$101 # U
252
253 nop
254 nop
255 nop
256 ret $31,($28),1 # L0
257
258 .end __copy_user
259
diff --git a/arch/alpha/lib/ev6-csum_ipv6_magic.S b/arch/alpha/lib/ev6-csum_ipv6_magic.S
new file mode 100644
index 000000000000..de1948a69118
--- /dev/null
+++ b/arch/alpha/lib/ev6-csum_ipv6_magic.S
@@ -0,0 +1,126 @@
1/*
2 * arch/alpha/lib/ev6-csum_ipv6_magic.S
3 * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
4 *
5 * unsigned short csum_ipv6_magic(struct in6_addr *saddr,
6 * struct in6_addr *daddr,
7 * __u32 len,
8 * unsigned short proto,
9 * unsigned int csum);
10 *
11 * Much of the information about 21264 scheduling/coding comes from:
12 * Compiler Writer's Guide for the Alpha 21264
13 * abbreviated as 'CWG' in other comments here
14 * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
15 * Scheduling notation:
16 * E - either cluster
17 * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
18 * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
19 * Try not to change the actual algorithm if possible for consistency.
20 * Determining actual stalls (other than slotting) doesn't appear to be easy to do.
21 *
22 * unsigned short csum_ipv6_magic(struct in6_addr *saddr,
23 * struct in6_addr *daddr,
24 * __u32 len,
25 * unsigned short proto,
26 * unsigned int csum);
27 *
28 * Swap <proto> (takes form 0xaabb)
29 * Then shift it left by 48, so result is:
30 * 0xbbaa0000 00000000
31 * Then turn it back into a sign extended 32-bit item
32 * 0xbbaa0000
33 *
34 * Swap <len> (an unsigned int) using Mike Burrows' 7-instruction sequence
35 * (we can't hide the 3-cycle latency of the unpkbw in the 6-instruction sequence)
36 * Assume input takes form 0xAABBCCDD
37 *
38 * Finally, original 'folding' approach is to split the long into 4 unsigned shorts
39 * add 4 ushorts, resulting in ushort/carry
40 * add carry bits + ushort --> ushort
41 * add carry bits + ushort --> ushort (in case the carry results in an overflow)
42 * Truncate to a ushort. (took 13 instructions)
43 * From doing some testing, using the approach in checksum.c:from64to16()
44 * results in the same outcome:
45 * split into 2 uints, add those, generating a ulong
46 * add the 3 low ushorts together, generating a uint
47 * a final add of the 2 lower ushorts
48 * truncating the result.
49 */
50
51 .globl csum_ipv6_magic
52 .align 4
53 .ent csum_ipv6_magic
54 .frame $30,0,$26,0
55csum_ipv6_magic:
56 .prologue 0
57
58 ldq $0,0($16) # L : Latency: 3
59 inslh $18,7,$4 # U : 0000000000AABBCC
60 ldq $1,8($16) # L : Latency: 3
61 sll $19,8,$7 # U : U L U L : 0x00000000 00aabb00
62
63 zapnot $20,15,$20 # U : zero extend incoming csum
64 ldq $2,0($17) # L : Latency: 3
65 sll $19,24,$19 # U : U L L U : 0x000000aa bb000000
66 inswl $18,3,$18 # U : 000000CCDD000000
67
68 ldq $3,8($17) # L : Latency: 3
69 bis $18,$4,$18 # E : 000000CCDDAABBCC
70 addl $19,$7,$19 # E : <sign bits>bbaabb00
71 nop # E : U L U L
72
73 addq $20,$0,$20 # E : begin summing the words
74 srl $18,16,$4 # U : 0000000000CCDDAA
75 zap $19,0x3,$19 # U : <sign bits>bbaa0000
76 nop # E : L U U L
77
78 cmpult $20,$0,$0 # E :
79 addq $20,$1,$20 # E :
80 zapnot $18,0xa,$18 # U : 00000000DD00BB00
81 zap $4,0xa,$4 # U : U U L L : 0000000000CC00AA
82
83 or $18,$4,$18 # E : 00000000DDCCBBAA
84 nop # E :
85 cmpult $20,$1,$1 # E :
86 addq $20,$2,$20 # E : U L U L
87
88 cmpult $20,$2,$2 # E :
89 addq $20,$3,$20 # E :
90 cmpult $20,$3,$3 # E : (1 cycle stall on $20)
91 addq $20,$18,$20 # E : U L U L (1 cycle stall on $20)
92
93 cmpult $20,$18,$18 # E :
94 addq $20,$19,$20 # E : (1 cycle stall on $20)
95 addq $0,$1,$0 # E : merge the carries back into the csum
96 addq $2,$3,$2 # E :
97
98 cmpult $20,$19,$19 # E :
99 addq $18,$19,$18 # E : (1 cycle stall on $19)
100 addq $0,$2,$0 # E :
101 addq $20,$18,$20 # E : U L U L :
102 /* (1 cycle stall on $18, 2 cycles on $20) */
103
104 addq $0,$20,$0 # E :
105 zapnot $0,15,$1 # U : Start folding output (1 cycle stall on $0)
106 nop # E :
107 srl $0,32,$0 # U : U L U L : (1 cycle stall on $0)
108
109 addq $1,$0,$1 # E : Finished generating ulong
110 extwl $1,2,$2 # U : ushort[1] (1 cycle stall on $1)
111 zapnot $1,3,$0 # U : ushort[0] (1 cycle stall on $1)
112 extwl $1,4,$1 # U : ushort[2] (1 cycle stall on $1)
113
114 addq $0,$2,$0 # E
115 addq $0,$1,$3 # E : Finished generating uint
116 /* (1 cycle stall on $0) */
117 extwl $3,2,$1 # U : ushort[1] (1 cycle stall on $3)
118 nop # E : L U L U
119
120 addq $1,$3,$0 # E : Final carry
121 not $0,$4 # E : complement (1 cycle stall on $0)
122 zapnot $4,3,$0 # U : clear upper garbage bits
123 /* (1 cycle stall on $4) */
124 ret # L0 : L U L U
125
126 .end csum_ipv6_magic
diff --git a/arch/alpha/lib/ev6-divide.S b/arch/alpha/lib/ev6-divide.S
new file mode 100644
index 000000000000..2a82b9be93fa
--- /dev/null
+++ b/arch/alpha/lib/ev6-divide.S
@@ -0,0 +1,259 @@
1/*
2 * arch/alpha/lib/ev6-divide.S
3 *
4 * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
5 *
6 * Alpha division..
7 */
8
9/*
10 * The alpha chip doesn't provide hardware division, so we have to do it
11 * by hand. The compiler expects the functions
12 *
13 * __divqu: 64-bit unsigned long divide
14 * __remqu: 64-bit unsigned long remainder
15 * __divqs/__remqs: signed 64-bit
16 * __divlu/__remlu: unsigned 32-bit
17 * __divls/__remls: signed 32-bit
18 *
19 * These are not normal C functions: instead of the normal
20 * calling sequence, these expect their arguments in registers
21 * $24 and $25, and return the result in $27. Register $28 may
22 * be clobbered (assembly temporary), anything else must be saved.
23 *
24 * In short: painful.
25 *
26 * This is a rather simple bit-at-a-time algorithm: it's very good
27 * at dividing random 64-bit numbers, but the more usual case where
28 * the divisor is small is handled better by the DEC algorithm
29 * using lookup tables. This uses much less memory, though, and is
30 * nicer on the cache.. Besides, I don't know the copyright status
31 * of the DEC code.
32 */
33
34/*
35 * My temporaries:
36 * $0 - current bit
37 * $1 - shifted divisor
38 * $2 - modulus/quotient
39 *
40 * $23 - return address
41 * $24 - dividend
42 * $25 - divisor
43 *
44 * $27 - quotient/modulus
45 * $28 - compare status
46 *
47 * Much of the information about 21264 scheduling/coding comes from:
48 * Compiler Writer's Guide for the Alpha 21264
49 * abbreviated as 'CWG' in other comments here
50 * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
51 * Scheduling notation:
52 * E - either cluster
53 * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
54 * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
55 * Try not to change the actual algorithm if possible for consistency.
56 */
57
58#define halt .long 0
59
60/*
61 * Select function type and registers
62 */
63#define mask $0
64#define divisor $1
65#define compare $28
66#define tmp1 $3
67#define tmp2 $4
68
69#ifdef DIV
70#define DIV_ONLY(x,y...) x,##y
71#define MOD_ONLY(x,y...)
72#define func(x) __div##x
73#define modulus $2
74#define quotient $27
75#define GETSIGN(x) xor $24,$25,x
76#define STACK 48
77#else
78#define DIV_ONLY(x,y...)
79#define MOD_ONLY(x,y...) x,##y
80#define func(x) __rem##x
81#define modulus $27
82#define quotient $2
83#define GETSIGN(x) bis $24,$24,x
84#define STACK 32
85#endif
86
87/*
88 * For 32-bit operations, we need to extend to 64-bit
89 */
90#ifdef INTSIZE
91#define ufunction func(lu)
92#define sfunction func(l)
93#define LONGIFY(x) zapnot x,15,x
94#define SLONGIFY(x) addl x,0,x
95#else
96#define ufunction func(qu)
97#define sfunction func(q)
98#define LONGIFY(x)
99#define SLONGIFY(x)
100#endif
101
102.set noat
103.align 4
104.globl ufunction
105.ent ufunction
106ufunction:
107 subq $30,STACK,$30 # E :
108 .frame $30,STACK,$23
109 .prologue 0
110
1117: stq $1, 0($30) # L :
112 bis $25,$25,divisor # E :
113 stq $2, 8($30) # L : L U L U
114
115 bis $24,$24,modulus # E :
116 stq $0,16($30) # L :
117 bis $31,$31,quotient # E :
118 LONGIFY(divisor) # E : U L L U
119
120 stq tmp1,24($30) # L :
121 LONGIFY(modulus) # E :
122 bis $31,1,mask # E :
123 DIV_ONLY(stq tmp2,32($30)) # L : L U U L
124
125 beq divisor, 9f /* div by zero */
126 /*
127 * In spite of the DIV_ONLY being either a non-instruction
128 * or an actual stq, the addition of the .align directive
129 * below ensures that label 1 is going to be nicely aligned
130 */
131
132 .align 4
133#ifdef INTSIZE
134 /*
135 * shift divisor left, using 3-bit shifts for
136 * 32-bit divides as we can't overflow. Three-bit
137 * shifts will result in looping three times less
138 * here, but can result in two loops more later.
139 * Thus using a large shift isn't worth it (and
140 * s8add pairs better than a sll..)
141 */
1421: cmpult divisor,modulus,compare # E :
143 s8addq divisor,$31,divisor # E :
144 s8addq mask,$31,mask # E :
145 bne compare,1b # U : U L U L
146#else
1471: cmpult divisor,modulus,compare # E :
148 nop # E :
149 nop # E :
150 blt divisor, 2f # U : U L U L
151
152 addq divisor,divisor,divisor # E :
153 addq mask,mask,mask # E :
154 unop # E :
155 bne compare,1b # U : U L U L
156#endif
157
158 /* ok, start to go right again.. */
1592:
160 /*
161 * Keep things nicely bundled... use a nop instead of not
162 * having an instruction for DIV_ONLY
163 */
164#ifdef DIV
165 DIV_ONLY(addq quotient,mask,tmp2) # E :
166#else
167 nop # E :
168#endif
169 srl mask,1,mask # U :
170 cmpule divisor,modulus,compare # E :
171 subq modulus,divisor,tmp1 # E :
172
173#ifdef DIV
174 DIV_ONLY(cmovne compare,tmp2,quotient) # E : Latency 2, extra map slot
175 nop # E : as part of the cmovne
176 srl divisor,1,divisor # U :
177 nop # E : L U L U
178
179 nop # E :
180 cmovne compare,tmp1,modulus # E : Latency 2, extra map slot
181 nop # E : as part of the cmovne
182 bne mask,2b # U : U L U L
183#else
184 srl divisor,1,divisor # U :
185 cmovne compare,tmp1,modulus # E : Latency 2, extra map slot
186 nop # E : as part of the cmovne
187 bne mask,2b # U : U L L U
188#endif
189
1909: ldq $1, 0($30) # L :
191 ldq $2, 8($30) # L :
192 nop # E :
193 nop # E : U U L L
194
195 ldq $0,16($30) # L :
196 ldq tmp1,24($30) # L :
197 nop # E :
198 nop # E :
199
200#ifdef DIV
201 DIV_ONLY(ldq tmp2,32($30)) # L :
202#else
203 nop # E :
204#endif
205 addq $30,STACK,$30 # E :
206 ret $31,($23),1 # L0 : L U U L
207 .end ufunction
208
209/*
210 * Uhh.. Ugly signed division. I'd rather not have it at all, but
211 * it's needed in some circumstances. There are different ways to
212 * handle this, really. This does:
213 * -a / b = a / -b = -(a / b)
214 * -a % b = -(a % b)
215 * a % -b = a % b
216 * which is probably not the best solution, but at least should
217 * have the property that (x/y)*y + (x%y) = x.
218 */
219.align 4
220.globl sfunction
221.ent sfunction
222sfunction:
223 subq $30,STACK,$30 # E :
224 .frame $30,STACK,$23
225 .prologue 0
226 bis $24,$25,$28 # E :
227 SLONGIFY($28) # E :
228 bge $28,7b # U :
229
230 stq $24,0($30) # L :
231 subq $31,$24,$28 # E :
232 stq $25,8($30) # L :
233 nop # E : U L U L
234
235 cmovlt $24,$28,$24 /* abs($24) */ # E : Latency 2, extra map slot
236 nop # E : as part of the cmov
237 stq $23,16($30) # L :
238 subq $31,$25,$28 # E : U L U L
239
240 stq tmp1,24($30) # L :
241 cmovlt $25,$28,$25 /* abs($25) */ # E : Latency 2, extra map slot
242 nop # E :
243 bsr $23,ufunction # L0: L U L U
244
245 ldq $24,0($30) # L :
246 ldq $25,8($30) # L :
247 GETSIGN($28) # E :
248 subq $31,$27,tmp1 # E : U U L L
249
250 SLONGIFY($28) # E :
251 ldq $23,16($30) # L :
252 cmovlt $28,tmp1,$27 # E : Latency 2, extra map slot
253 nop # E : U L L U : as part of the cmov
254
255 ldq tmp1,24($30) # L :
256 nop # E : as part of the cmov
257 addq $30,STACK,$30 # E :
258 ret $31,($23),1 # L0 : L U U L
259 .end sfunction
diff --git a/arch/alpha/lib/ev6-memchr.S b/arch/alpha/lib/ev6-memchr.S
new file mode 100644
index 000000000000..a8e843dbcc23
--- /dev/null
+++ b/arch/alpha/lib/ev6-memchr.S
@@ -0,0 +1,191 @@
1/*
2 * arch/alpha/lib/ev6-memchr.S
3 *
4 * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
5 *
6 * Finds characters in a memory area. Optimized for the Alpha:
7 *
8 * - memory accessed as aligned quadwords only
9 * - uses cmpbge to compare 8 bytes in parallel
10 * - does binary search to find 0 byte in last
11 * quadword (HAKMEM needed 12 instructions to
12 * do this instead of the 9 instructions that
13 * binary search needs).
14 *
15 * For correctness consider that:
16 *
17 * - only minimum number of quadwords may be accessed
18 * - the third argument is an unsigned long
19 *
20 * Much of the information about 21264 scheduling/coding comes from:
21 * Compiler Writer's Guide for the Alpha 21264
22 * abbreviated as 'CWG' in other comments here
23 * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
24 * Scheduling notation:
25 * E - either cluster
26 * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
27 * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
28 * Try not to change the actual algorithm if possible for consistency.
29 */
30
31 .set noreorder
32 .set noat
33
34 .align 4
35 .globl memchr
36 .ent memchr
37memchr:
38 .frame $30,0,$26,0
39 .prologue 0
40
41 # Hack -- if someone passes in (size_t)-1, hoping to just
42 # search til the end of the address space, we will overflow
43 # below when we find the address of the last byte. Given
44 # that we will never have a 56-bit address space, cropping
45 # the length is the easiest way to avoid trouble.
46 zap $18, 0x80, $5 # U : Bound length
47 beq $18, $not_found # U :
48 ldq_u $1, 0($16) # L : load first quadword Latency=3
49 and $17, 0xff, $17 # E : L L U U : 00000000000000ch
50
51 insbl $17, 1, $2 # U : 000000000000ch00
52 cmpult $18, 9, $4 # E : small (< 1 quad) string?
53 or $2, $17, $17 # E : 000000000000chch
54 lda $3, -1($31) # E : U L L U
55
56 sll $17, 16, $2 # U : 00000000chch0000
57 addq $16, $5, $5 # E : Max search address
58 or $2, $17, $17 # E : 00000000chchchch
59 sll $17, 32, $2 # U : U L L U : chchchch00000000
60
61 or $2, $17, $17 # E : chchchchchchchch
62 extql $1, $16, $7 # U : $7 is upper bits
63 beq $4, $first_quad # U :
64 ldq_u $6, -1($5) # L : L U U L : eight or less bytes to search Latency=3
65
66 extqh $6, $16, $6 # U : 2 cycle stall for $6
67 mov $16, $0 # E :
68 nop # E :
69 or $7, $6, $1 # E : L U L U $1 = quadword starting at $16
70
71 # Deal with the case where at most 8 bytes remain to be searched
72 # in $1. E.g.:
73 # $18 = 6
74 # $1 = ????c6c5c4c3c2c1
75$last_quad:
76 negq $18, $6 # E :
77 xor $17, $1, $1 # E :
78 srl $3, $6, $6 # U : $6 = mask of $18 bits set
79 cmpbge $31, $1, $2 # E : L U L U
80
81 nop
82 nop
83 and $2, $6, $2 # E :
84 beq $2, $not_found # U : U L U L
85
86$found_it:
87#if defined(__alpha_fix__) && defined(__alpha_cix__)
88 /*
89 * Since we are guaranteed to have set one of the bits, we don't
90 * have to worry about coming back with a 0x40 out of cttz...
91 */
92 cttz $2, $3 # U0 :
93 addq $0, $3, $0 # E : All done
94 nop # E :
95 ret # L0 : L U L U
96#else
97 /*
98 * Slow and clunky. It can probably be improved.
99 * An exercise left for others.
100 */
101 negq $2, $3 # E :
102 and $2, $3, $2 # E :
103 and $2, 0x0f, $1 # E :
104 addq $0, 4, $3 # E :
105
106 cmoveq $1, $3, $0 # E : Latency 2, extra map cycle
107 nop # E : keep with cmov
108 and $2, 0x33, $1 # E :
109 addq $0, 2, $3 # E : U L U L : 2 cycle stall on $0
110
111 cmoveq $1, $3, $0 # E : Latency 2, extra map cycle
112 nop # E : keep with cmov
113 and $2, 0x55, $1 # E :
114 addq $0, 1, $3 # E : U L U L : 2 cycle stall on $0
115
116 cmoveq $1, $3, $0 # E : Latency 2, extra map cycle
117 nop
118 nop
119 ret # L0 : L U L U
120#endif
121
122 # Deal with the case where $18 > 8 bytes remain to be
123 # searched. $16 may not be aligned.
124 .align 4
125$first_quad:
126 andnot $16, 0x7, $0 # E :
127 insqh $3, $16, $2 # U : $2 = 0000ffffffffffff ($16<0:2> ff)
128 xor $1, $17, $1 # E :
129 or $1, $2, $1 # E : U L U L $1 = ====ffffffffffff
130
131 cmpbge $31, $1, $2 # E :
132 bne $2, $found_it # U :
133 # At least one byte left to process.
134 ldq $1, 8($0) # L :
135 subq $5, 1, $18 # E : U L U L
136
137 addq $0, 8, $0 # E :
138 # Make $18 point to last quad to be accessed (the
139 # last quad may or may not be partial).
140 andnot $18, 0x7, $18 # E :
141 cmpult $0, $18, $2 # E :
142 beq $2, $final # U : U L U L
143
144 # At least two quads remain to be accessed.
145
146 subq $18, $0, $4 # E : $4 <- nr quads to be processed
147 and $4, 8, $4 # E : odd number of quads?
148 bne $4, $odd_quad_count # U :
149 # At least three quads remain to be accessed
150 mov $1, $4 # E : L U L U : move prefetched value to correct reg
151
152 .align 4
153$unrolled_loop:
154 ldq $1, 8($0) # L : prefetch $1
155 xor $17, $4, $2 # E :
156 cmpbge $31, $2, $2 # E :
157 bne $2, $found_it # U : U L U L
158
159 addq $0, 8, $0 # E :
160 nop # E :
161 nop # E :
162 nop # E :
163
164$odd_quad_count:
165 xor $17, $1, $2 # E :
166 ldq $4, 8($0) # L : prefetch $4
167 cmpbge $31, $2, $2 # E :
168 addq $0, 8, $6 # E :
169
170 bne $2, $found_it # U :
171 cmpult $6, $18, $6 # E :
172 addq $0, 8, $0 # E :
173 nop # E :
174
175 bne $6, $unrolled_loop # U :
176 mov $4, $1 # E : move prefetched value into $1
177 nop # E :
178 nop # E :
179
180$final: subq $5, $0, $18 # E : $18 <- number of bytes left to do
181 nop # E :
182 nop # E :
183 bne $18, $last_quad # U :
184
185$not_found:
186 mov $31, $0 # E :
187 nop # E :
188 nop # E :
189 ret # L0 :
190
191 .end memchr
diff --git a/arch/alpha/lib/ev6-memcpy.S b/arch/alpha/lib/ev6-memcpy.S
new file mode 100644
index 000000000000..52b37b0f2af5
--- /dev/null
+++ b/arch/alpha/lib/ev6-memcpy.S
@@ -0,0 +1,248 @@
1/*
2 * arch/alpha/lib/ev6-memcpy.S
3 * 21264 version by Rick Gorton <rick.gorton@alpha-processor.com>
4 *
5 * Reasonably optimized memcpy() routine for the Alpha 21264
6 *
7 * - memory accessed as aligned quadwords only
8 * - uses bcmpge to compare 8 bytes in parallel
9 *
10 * Much of the information about 21264 scheduling/coding comes from:
11 * Compiler Writer's Guide for the Alpha 21264
12 * abbreviated as 'CWG' in other comments here
13 * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
14 * Scheduling notation:
15 * E - either cluster
16 * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
17 * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
18 *
19 * Temp usage notes:
20 * $1,$2, - scratch
21 */
22
23 .set noreorder
24 .set noat
25
26 .align 4
27 .globl memcpy
28 .ent memcpy
29memcpy:
30 .frame $30,0,$26,0
31 .prologue 0
32
33 mov $16, $0 # E : copy dest to return
34 ble $18, $nomoredata # U : done with the copy?
35 xor $16, $17, $1 # E : are source and dest alignments the same?
36 and $1, 7, $1 # E : are they the same mod 8?
37
38 bne $1, $misaligned # U : Nope - gotta do this the slow way
39 /* source and dest are same mod 8 address */
40 and $16, 7, $1 # E : Are both 0mod8?
41 beq $1, $both_0mod8 # U : Yes
42 nop # E :
43
44 /*
45 * source and dest are same misalignment. move a byte at a time
46 * until a 0mod8 alignment for both is reached.
47 * At least one byte more to move
48 */
49
50$head_align:
51 ldbu $1, 0($17) # L : grab a byte
52 subq $18, 1, $18 # E : count--
53 addq $17, 1, $17 # E : src++
54 stb $1, 0($16) # L :
55 addq $16, 1, $16 # E : dest++
56 and $16, 7, $1 # E : Are we at 0mod8 yet?
57 ble $18, $nomoredata # U : done with the copy?
58 bne $1, $head_align # U :
59
60$both_0mod8:
61 cmple $18, 127, $1 # E : Can we unroll the loop?
62 bne $1, $no_unroll # U :
63 and $16, 63, $1 # E : get mod64 alignment
64 beq $1, $do_unroll # U : no single quads to fiddle
65
66$single_head_quad:
67 ldq $1, 0($17) # L : get 8 bytes
68 subq $18, 8, $18 # E : count -= 8
69 addq $17, 8, $17 # E : src += 8
70 nop # E :
71
72 stq $1, 0($16) # L : store
73 addq $16, 8, $16 # E : dest += 8
74 and $16, 63, $1 # E : get mod64 alignment
75 bne $1, $single_head_quad # U : still not fully aligned
76
77$do_unroll:
78 addq $16, 64, $7 # E : Initial (+1 trip) wh64 address
79 cmple $18, 127, $1 # E : Can we go through the unrolled loop?
80 bne $1, $tail_quads # U : Nope
81 nop # E :
82
83$unroll_body:
84 wh64 ($7) # L1 : memory subsystem hint: 64 bytes at
85 # ($7) are about to be over-written
86 ldq $6, 0($17) # L0 : bytes 0..7
87 nop # E :
88 nop # E :
89
90 ldq $4, 8($17) # L : bytes 8..15
91 ldq $5, 16($17) # L : bytes 16..23
92 addq $7, 64, $7 # E : Update next wh64 address
93 nop # E :
94
95 ldq $3, 24($17) # L : bytes 24..31
96 addq $16, 64, $1 # E : fallback value for wh64
97 nop # E :
98 nop # E :
99
100 addq $17, 32, $17 # E : src += 32 bytes
101 stq $6, 0($16) # L : bytes 0..7
102 nop # E :
103 nop # E :
104
105 stq $4, 8($16) # L : bytes 8..15
106 stq $5, 16($16) # L : bytes 16..23
107 subq $18, 192, $2 # E : At least two more trips to go?
108 nop # E :
109
110 stq $3, 24($16) # L : bytes 24..31
111 addq $16, 32, $16 # E : dest += 32 bytes
112 nop # E :
113 nop # E :
114
115 ldq $6, 0($17) # L : bytes 0..7
116 ldq $4, 8($17) # L : bytes 8..15
117 cmovlt $2, $1, $7 # E : Latency 2, extra map slot - Use
118 # fallback wh64 address if < 2 more trips
119 nop # E :
120
121 ldq $5, 16($17) # L : bytes 16..23
122 ldq $3, 24($17) # L : bytes 24..31
123 addq $16, 32, $16 # E : dest += 32
124 subq $18, 64, $18 # E : count -= 64
125
126 addq $17, 32, $17 # E : src += 32
127 stq $6, -32($16) # L : bytes 0..7
128 stq $4, -24($16) # L : bytes 8..15
129 cmple $18, 63, $1 # E : At least one more trip?
130
131 stq $5, -16($16) # L : bytes 16..23
132 stq $3, -8($16) # L : bytes 24..31
133 nop # E :
134 beq $1, $unroll_body
135
136$tail_quads:
137$no_unroll:
138 .align 4
139 subq $18, 8, $18 # E : At least a quad left?
140 blt $18, $less_than_8 # U : Nope
141 nop # E :
142 nop # E :
143
144$move_a_quad:
145 ldq $1, 0($17) # L : fetch 8
146 subq $18, 8, $18 # E : count -= 8
147 addq $17, 8, $17 # E : src += 8
148 nop # E :
149
150 stq $1, 0($16) # L : store 8
151 addq $16, 8, $16 # E : dest += 8
152 bge $18, $move_a_quad # U :
153 nop # E :
154
155$less_than_8:
156 .align 4
157 addq $18, 8, $18 # E : add back for trailing bytes
158 ble $18, $nomoredata # U : All-done
159 nop # E :
160 nop # E :
161
162 /* Trailing bytes */
163$tail_bytes:
164 subq $18, 1, $18 # E : count--
165 ldbu $1, 0($17) # L : fetch a byte
166 addq $17, 1, $17 # E : src++
167 nop # E :
168
169 stb $1, 0($16) # L : store a byte
170 addq $16, 1, $16 # E : dest++
171 bgt $18, $tail_bytes # U : more to be done?
172 nop # E :
173
174 /* branching to exit takes 3 extra cycles, so replicate exit here */
175 ret $31, ($26), 1 # L0 :
176 nop # E :
177 nop # E :
178 nop # E :
179
180$misaligned:
181 mov $0, $4 # E : dest temp
182 and $0, 7, $1 # E : dest alignment mod8
183 beq $1, $dest_0mod8 # U : life doesnt totally suck
184 nop
185
186$aligndest:
187 ble $18, $nomoredata # U :
188 ldbu $1, 0($17) # L : fetch a byte
189 subq $18, 1, $18 # E : count--
190 addq $17, 1, $17 # E : src++
191
192 stb $1, 0($4) # L : store it
193 addq $4, 1, $4 # E : dest++
194 and $4, 7, $1 # E : dest 0mod8 yet?
195 bne $1, $aligndest # U : go until we are aligned.
196
197 /* Source has unknown alignment, but dest is known to be 0mod8 */
198$dest_0mod8:
199 subq $18, 8, $18 # E : At least a quad left?
200 blt $18, $misalign_tail # U : Nope
201 ldq_u $3, 0($17) # L : seed (rotating load) of 8 bytes
202 nop # E :
203
204$mis_quad:
205 ldq_u $16, 8($17) # L : Fetch next 8
206 extql $3, $17, $3 # U : masking
207 extqh $16, $17, $1 # U : masking
208 bis $3, $1, $1 # E : merged bytes to store
209
210 subq $18, 8, $18 # E : count -= 8
211 addq $17, 8, $17 # E : src += 8
212 stq $1, 0($4) # L : store 8 (aligned)
213 mov $16, $3 # E : "rotate" source data
214
215 addq $4, 8, $4 # E : dest += 8
216 bge $18, $mis_quad # U : More quads to move
217 nop
218 nop
219
220$misalign_tail:
221 addq $18, 8, $18 # E : account for tail stuff
222 ble $18, $nomoredata # U :
223 nop
224 nop
225
226$misalign_byte:
227 ldbu $1, 0($17) # L : fetch 1
228 subq $18, 1, $18 # E : count--
229 addq $17, 1, $17 # E : src++
230 nop # E :
231
232 stb $1, 0($4) # L : store
233 addq $4, 1, $4 # E : dest++
234 bgt $18, $misalign_byte # U : more to go?
235 nop
236
237
238$nomoredata:
239 ret $31, ($26), 1 # L0 :
240 nop # E :
241 nop # E :
242 nop # E :
243
244 .end memcpy
245
246/* For backwards module compatibility. */
247__memcpy = memcpy
248.globl __memcpy
diff --git a/arch/alpha/lib/ev6-memset.S b/arch/alpha/lib/ev6-memset.S
new file mode 100644
index 000000000000..d8b94e1c7fca
--- /dev/null
+++ b/arch/alpha/lib/ev6-memset.S
@@ -0,0 +1,597 @@
1/*
2 * arch/alpha/lib/ev6-memset.S
3 *
4 * This is an efficient (and relatively small) implementation of the C library
5 * "memset()" function for the 21264 implementation of Alpha.
6 *
7 * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
8 *
9 * Much of the information about 21264 scheduling/coding comes from:
10 * Compiler Writer's Guide for the Alpha 21264
11 * abbreviated as 'CWG' in other comments here
12 * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
13 * Scheduling notation:
14 * E - either cluster
15 * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
16 * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
17 * The algorithm for the leading and trailing quadwords remains the same,
18 * however the loop has been unrolled to enable better memory throughput,
19 * and the code has been replicated for each of the entry points: __memset
20 * and __memsetw to permit better scheduling to eliminate the stalling
21 * encountered during the mask replication.
22 * A future enhancement might be to put in a byte store loop for really
23 * small (say < 32 bytes) memset()s. Whether or not that change would be
24 * a win in the kernel would depend upon the contextual usage.
25 * WARNING: Maintaining this is going to be more work than the above version,
26 * as fixes will need to be made in multiple places. The performance gain
27 * is worth it.
28 */
29
30 .set noat
31 .set noreorder
32.text
33 .globl __memset
34 .globl __memsetw
35 .globl __constant_c_memset
36 .globl memset
37
38 .ent __memset
39.align 5
40__memset:
41 .frame $30,0,$26,0
42 .prologue 0
43
44 /*
45 * Serious stalling happens. The only way to mitigate this is to
46 * undertake a major re-write to interleave the constant materialization
47 * with other parts of the fall-through code. This is important, even
48 * though it makes maintenance tougher.
49 * Do this later.
50 */
51 and $17,255,$1 # E : 00000000000000ch
52 insbl $17,1,$2 # U : 000000000000ch00
53 bis $16,$16,$0 # E : return value
54 ble $18,end_b # U : zero length requested?
55
56 addq $18,$16,$6 # E : max address to write to
57 bis $1,$2,$17 # E : 000000000000chch
58 insbl $1,2,$3 # U : 0000000000ch0000
59 insbl $1,3,$4 # U : 00000000ch000000
60
61 or $3,$4,$3 # E : 00000000chch0000
62 inswl $17,4,$5 # U : 0000chch00000000
63 xor $16,$6,$1 # E : will complete write be within one quadword?
64 inswl $17,6,$2 # U : chch000000000000
65
66 or $17,$3,$17 # E : 00000000chchchch
67 or $2,$5,$2 # E : chchchch00000000
68 bic $1,7,$1 # E : fit within a single quadword?
69 and $16,7,$3 # E : Target addr misalignment
70
71 or $17,$2,$17 # E : chchchchchchchch
72 beq $1,within_quad_b # U :
73 nop # E :
74 beq $3,aligned_b # U : target is 0mod8
75
76 /*
77 * Target address is misaligned, and won't fit within a quadword
78 */
79 ldq_u $4,0($16) # L : Fetch first partial
80 bis $16,$16,$5 # E : Save the address
81 insql $17,$16,$2 # U : Insert new bytes
82 subq $3,8,$3 # E : Invert (for addressing uses)
83
84 addq $18,$3,$18 # E : $18 is new count ($3 is negative)
85 mskql $4,$16,$4 # U : clear relevant parts of the quad
86 subq $16,$3,$16 # E : $16 is new aligned destination
87 bis $2,$4,$1 # E : Final bytes
88
89 nop
90 stq_u $1,0($5) # L : Store result
91 nop
92 nop
93
94.align 4
95aligned_b:
96 /*
97 * We are now guaranteed to be quad aligned, with at least
98 * one partial quad to write.
99 */
100
101 sra $18,3,$3 # U : Number of remaining quads to write
102 and $18,7,$18 # E : Number of trailing bytes to write
103 bis $16,$16,$5 # E : Save dest address
104 beq $3,no_quad_b # U : tail stuff only
105
106 /*
107 * it's worth the effort to unroll this and use wh64 if possible
108 * Lifted a bunch of code from clear_user.S
109 * At this point, entry values are:
110 * $16 Current destination address
111 * $5 A copy of $16
112 * $6 The max quadword address to write to
113 * $18 Number trailer bytes
114 * $3 Number quads to write
115 */
116
117 and $16, 0x3f, $2 # E : Forward work (only useful for unrolled loop)
118 subq $3, 16, $4 # E : Only try to unroll if > 128 bytes
119 subq $2, 0x40, $1 # E : bias counter (aligning stuff 0mod64)
120 blt $4, loop_b # U :
121
122 /*
123 * We know we've got at least 16 quads, minimum of one trip
124 * through unrolled loop. Do a quad at a time to get us 0mod64
125 * aligned.
126 */
127
128 nop # E :
129 nop # E :
130 nop # E :
131 beq $1, $bigalign_b # U :
132
133$alignmod64_b:
134 stq $17, 0($5) # L :
135 subq $3, 1, $3 # E : For consistency later
136 addq $1, 8, $1 # E : Increment towards zero for alignment
137 addq $5, 8, $4 # E : Initial wh64 address (filler instruction)
138
139 nop
140 nop
141 addq $5, 8, $5 # E : Inc address
142 blt $1, $alignmod64_b # U :
143
144$bigalign_b:
145 /*
146 * $3 - number quads left to go
147 * $5 - target address (aligned 0mod64)
148 * $17 - mask of stuff to store
149 * Scratch registers available: $7, $2, $4, $1
150 * we know that we'll be taking a minimum of one trip through
151 * CWG Section 3.7.6: do not expect a sustained store rate of > 1/cycle
152 * Assumes the wh64 needs to be for 2 trips through the loop in the future
153 * The wh64 is issued on for the starting destination address for trip +2
154 * through the loop, and if there are less than two trips left, the target
155 * address will be for the current trip.
156 */
157
158$do_wh64_b:
159 wh64 ($4) # L1 : memory subsystem write hint
160 subq $3, 24, $2 # E : For determining future wh64 addresses
161 stq $17, 0($5) # L :
162 nop # E :
163
164 addq $5, 128, $4 # E : speculative target of next wh64
165 stq $17, 8($5) # L :
166 stq $17, 16($5) # L :
167 addq $5, 64, $7 # E : Fallback address for wh64 (== next trip addr)
168
169 stq $17, 24($5) # L :
170 stq $17, 32($5) # L :
171 cmovlt $2, $7, $4 # E : Latency 2, extra mapping cycle
172 nop
173
174 stq $17, 40($5) # L :
175 stq $17, 48($5) # L :
176 subq $3, 16, $2 # E : Repeat the loop at least once more?
177 nop
178
179 stq $17, 56($5) # L :
180 addq $5, 64, $5 # E :
181 subq $3, 8, $3 # E :
182 bge $2, $do_wh64_b # U :
183
184 nop
185 nop
186 nop
187 beq $3, no_quad_b # U : Might have finished already
188
189.align 4
190 /*
191 * Simple loop for trailing quadwords, or for small amounts
192 * of data (where we can't use an unrolled loop and wh64)
193 */
194loop_b:
195 stq $17,0($5) # L :
196 subq $3,1,$3 # E : Decrement number quads left
197 addq $5,8,$5 # E : Inc address
198 bne $3,loop_b # U : more?
199
200no_quad_b:
201 /*
202 * Write 0..7 trailing bytes.
203 */
204 nop # E :
205 beq $18,end_b # U : All done?
206 ldq $7,0($5) # L :
207 mskqh $7,$6,$2 # U : Mask final quad
208
209 insqh $17,$6,$4 # U : New bits
210 bis $2,$4,$1 # E : Put it all together
211 stq $1,0($5) # L : And back to memory
212 ret $31,($26),1 # L0 :
213
214within_quad_b:
215 ldq_u $1,0($16) # L :
216 insql $17,$16,$2 # U : New bits
217 mskql $1,$16,$4 # U : Clear old
218 bis $2,$4,$2 # E : New result
219
220 mskql $2,$6,$4 # U :
221 mskqh $1,$6,$2 # U :
222 bis $2,$4,$1 # E :
223 stq_u $1,0($16) # L :
224
225end_b:
226 nop
227 nop
228 nop
229 ret $31,($26),1 # L0 :
230 .end __memset
231
232 /*
233 * This is the original body of code, prior to replication and
234 * rescheduling. Leave it here, as there may be calls to this
235 * entry point.
236 */
237.align 4
238 .ent __constant_c_memset
239__constant_c_memset:
240 .frame $30,0,$26,0
241 .prologue 0
242
243 addq $18,$16,$6 # E : max address to write to
244 bis $16,$16,$0 # E : return value
245 xor $16,$6,$1 # E : will complete write be within one quadword?
246 ble $18,end # U : zero length requested?
247
248 bic $1,7,$1 # E : fit within a single quadword
249 beq $1,within_one_quad # U :
250 and $16,7,$3 # E : Target addr misalignment
251 beq $3,aligned # U : target is 0mod8
252
253 /*
254 * Target address is misaligned, and won't fit within a quadword
255 */
256 ldq_u $4,0($16) # L : Fetch first partial
257 bis $16,$16,$5 # E : Save the address
258 insql $17,$16,$2 # U : Insert new bytes
259 subq $3,8,$3 # E : Invert (for addressing uses)
260
261 addq $18,$3,$18 # E : $18 is new count ($3 is negative)
262 mskql $4,$16,$4 # U : clear relevant parts of the quad
263 subq $16,$3,$16 # E : $16 is new aligned destination
264 bis $2,$4,$1 # E : Final bytes
265
266 nop
267 stq_u $1,0($5) # L : Store result
268 nop
269 nop
270
271.align 4
272aligned:
273 /*
274 * We are now guaranteed to be quad aligned, with at least
275 * one partial quad to write.
276 */
277
278 sra $18,3,$3 # U : Number of remaining quads to write
279 and $18,7,$18 # E : Number of trailing bytes to write
280 bis $16,$16,$5 # E : Save dest address
281 beq $3,no_quad # U : tail stuff only
282
283 /*
284 * it's worth the effort to unroll this and use wh64 if possible
285 * Lifted a bunch of code from clear_user.S
286 * At this point, entry values are:
287 * $16 Current destination address
288 * $5 A copy of $16
289 * $6 The max quadword address to write to
290 * $18 Number trailer bytes
291 * $3 Number quads to write
292 */
293
294 and $16, 0x3f, $2 # E : Forward work (only useful for unrolled loop)
295 subq $3, 16, $4 # E : Only try to unroll if > 128 bytes
296 subq $2, 0x40, $1 # E : bias counter (aligning stuff 0mod64)
297 blt $4, loop # U :
298
299 /*
300 * We know we've got at least 16 quads, minimum of one trip
301 * through unrolled loop. Do a quad at a time to get us 0mod64
302 * aligned.
303 */
304
305 nop # E :
306 nop # E :
307 nop # E :
308 beq $1, $bigalign # U :
309
310$alignmod64:
311 stq $17, 0($5) # L :
312 subq $3, 1, $3 # E : For consistency later
313 addq $1, 8, $1 # E : Increment towards zero for alignment
314 addq $5, 8, $4 # E : Initial wh64 address (filler instruction)
315
316 nop
317 nop
318 addq $5, 8, $5 # E : Inc address
319 blt $1, $alignmod64 # U :
320
321$bigalign:
322 /*
323 * $3 - number quads left to go
324 * $5 - target address (aligned 0mod64)
325 * $17 - mask of stuff to store
326 * Scratch registers available: $7, $2, $4, $1
327 * we know that we'll be taking a minimum of one trip through
328 * CWG Section 3.7.6: do not expect a sustained store rate of > 1/cycle
329 * Assumes the wh64 needs to be for 2 trips through the loop in the future
330 * The wh64 is issued on for the starting destination address for trip +2
331 * through the loop, and if there are less than two trips left, the target
332 * address will be for the current trip.
333 */
334
335$do_wh64:
336 wh64 ($4) # L1 : memory subsystem write hint
337 subq $3, 24, $2 # E : For determining future wh64 addresses
338 stq $17, 0($5) # L :
339 nop # E :
340
341 addq $5, 128, $4 # E : speculative target of next wh64
342 stq $17, 8($5) # L :
343 stq $17, 16($5) # L :
344 addq $5, 64, $7 # E : Fallback address for wh64 (== next trip addr)
345
346 stq $17, 24($5) # L :
347 stq $17, 32($5) # L :
348 cmovlt $2, $7, $4 # E : Latency 2, extra mapping cycle
349 nop
350
351 stq $17, 40($5) # L :
352 stq $17, 48($5) # L :
353 subq $3, 16, $2 # E : Repeat the loop at least once more?
354 nop
355
356 stq $17, 56($5) # L :
357 addq $5, 64, $5 # E :
358 subq $3, 8, $3 # E :
359 bge $2, $do_wh64 # U :
360
361 nop
362 nop
363 nop
364 beq $3, no_quad # U : Might have finished already
365
366.align 4
367 /*
368 * Simple loop for trailing quadwords, or for small amounts
369 * of data (where we can't use an unrolled loop and wh64)
370 */
371loop:
372 stq $17,0($5) # L :
373 subq $3,1,$3 # E : Decrement number quads left
374 addq $5,8,$5 # E : Inc address
375 bne $3,loop # U : more?
376
377no_quad:
378 /*
379 * Write 0..7 trailing bytes.
380 */
381 nop # E :
382 beq $18,end # U : All done?
383 ldq $7,0($5) # L :
384 mskqh $7,$6,$2 # U : Mask final quad
385
386 insqh $17,$6,$4 # U : New bits
387 bis $2,$4,$1 # E : Put it all together
388 stq $1,0($5) # L : And back to memory
389 ret $31,($26),1 # L0 :
390
391within_one_quad:
392 ldq_u $1,0($16) # L :
393 insql $17,$16,$2 # U : New bits
394 mskql $1,$16,$4 # U : Clear old
395 bis $2,$4,$2 # E : New result
396
397 mskql $2,$6,$4 # U :
398 mskqh $1,$6,$2 # U :
399 bis $2,$4,$1 # E :
400 stq_u $1,0($16) # L :
401
402end:
403 nop
404 nop
405 nop
406 ret $31,($26),1 # L0 :
407 .end __constant_c_memset
408
409 /*
410 * This is a replicant of the __constant_c_memset code, rescheduled
411 * to mask stalls. Note that entry point names also had to change
412 */
413 .align 5
414 .ent __memsetw
415
416__memsetw:
417 .frame $30,0,$26,0
418 .prologue 0
419
420 inswl $17,0,$5 # U : 000000000000c1c2
421 inswl $17,2,$2 # U : 00000000c1c20000
422 bis $16,$16,$0 # E : return value
423 addq $18,$16,$6 # E : max address to write to
424
425 ble $18, end_w # U : zero length requested?
426 inswl $17,4,$3 # U : 0000c1c200000000
427 inswl $17,6,$4 # U : c1c2000000000000
428 xor $16,$6,$1 # E : will complete write be within one quadword?
429
430 or $2,$5,$2 # E : 00000000c1c2c1c2
431 or $3,$4,$17 # E : c1c2c1c200000000
432 bic $1,7,$1 # E : fit within a single quadword
433 and $16,7,$3 # E : Target addr misalignment
434
435 or $17,$2,$17 # E : c1c2c1c2c1c2c1c2
436 beq $1,within_quad_w # U :
437 nop
438 beq $3,aligned_w # U : target is 0mod8
439
440 /*
441 * Target address is misaligned, and won't fit within a quadword
442 */
443 ldq_u $4,0($16) # L : Fetch first partial
444 bis $16,$16,$5 # E : Save the address
445 insql $17,$16,$2 # U : Insert new bytes
446 subq $3,8,$3 # E : Invert (for addressing uses)
447
448 addq $18,$3,$18 # E : $18 is new count ($3 is negative)
449 mskql $4,$16,$4 # U : clear relevant parts of the quad
450 subq $16,$3,$16 # E : $16 is new aligned destination
451 bis $2,$4,$1 # E : Final bytes
452
453 nop
454 stq_u $1,0($5) # L : Store result
455 nop
456 nop
457
458.align 4
459aligned_w:
460 /*
461 * We are now guaranteed to be quad aligned, with at least
462 * one partial quad to write.
463 */
464
465 sra $18,3,$3 # U : Number of remaining quads to write
466 and $18,7,$18 # E : Number of trailing bytes to write
467 bis $16,$16,$5 # E : Save dest address
468 beq $3,no_quad_w # U : tail stuff only
469
470 /*
471 * it's worth the effort to unroll this and use wh64 if possible
472 * Lifted a bunch of code from clear_user.S
473 * At this point, entry values are:
474 * $16 Current destination address
475 * $5 A copy of $16
476 * $6 The max quadword address to write to
477 * $18 Number trailer bytes
478 * $3 Number quads to write
479 */
480
481 and $16, 0x3f, $2 # E : Forward work (only useful for unrolled loop)
482 subq $3, 16, $4 # E : Only try to unroll if > 128 bytes
483 subq $2, 0x40, $1 # E : bias counter (aligning stuff 0mod64)
484 blt $4, loop_w # U :
485
486 /*
487 * We know we've got at least 16 quads, minimum of one trip
488 * through unrolled loop. Do a quad at a time to get us 0mod64
489 * aligned.
490 */
491
492 nop # E :
493 nop # E :
494 nop # E :
495 beq $1, $bigalign_w # U :
496
497$alignmod64_w:
498 stq $17, 0($5) # L :
499 subq $3, 1, $3 # E : For consistency later
500 addq $1, 8, $1 # E : Increment towards zero for alignment
501 addq $5, 8, $4 # E : Initial wh64 address (filler instruction)
502
503 nop
504 nop
505 addq $5, 8, $5 # E : Inc address
506 blt $1, $alignmod64_w # U :
507
508$bigalign_w:
509 /*
510 * $3 - number quads left to go
511 * $5 - target address (aligned 0mod64)
512 * $17 - mask of stuff to store
513 * Scratch registers available: $7, $2, $4, $1
514 * we know that we'll be taking a minimum of one trip through
515 * CWG Section 3.7.6: do not expect a sustained store rate of > 1/cycle
516 * Assumes the wh64 needs to be for 2 trips through the loop in the future
517 * The wh64 is issued on for the starting destination address for trip +2
518 * through the loop, and if there are less than two trips left, the target
519 * address will be for the current trip.
520 */
521
522$do_wh64_w:
523 wh64 ($4) # L1 : memory subsystem write hint
524 subq $3, 24, $2 # E : For determining future wh64 addresses
525 stq $17, 0($5) # L :
526 nop # E :
527
528 addq $5, 128, $4 # E : speculative target of next wh64
529 stq $17, 8($5) # L :
530 stq $17, 16($5) # L :
531 addq $5, 64, $7 # E : Fallback address for wh64 (== next trip addr)
532
533 stq $17, 24($5) # L :
534 stq $17, 32($5) # L :
535 cmovlt $2, $7, $4 # E : Latency 2, extra mapping cycle
536 nop
537
538 stq $17, 40($5) # L :
539 stq $17, 48($5) # L :
540 subq $3, 16, $2 # E : Repeat the loop at least once more?
541 nop
542
543 stq $17, 56($5) # L :
544 addq $5, 64, $5 # E :
545 subq $3, 8, $3 # E :
546 bge $2, $do_wh64_w # U :
547
548 nop
549 nop
550 nop
551 beq $3, no_quad_w # U : Might have finished already
552
553.align 4
554 /*
555 * Simple loop for trailing quadwords, or for small amounts
556 * of data (where we can't use an unrolled loop and wh64)
557 */
558loop_w:
559 stq $17,0($5) # L :
560 subq $3,1,$3 # E : Decrement number quads left
561 addq $5,8,$5 # E : Inc address
562 bne $3,loop_w # U : more?
563
564no_quad_w:
565 /*
566 * Write 0..7 trailing bytes.
567 */
568 nop # E :
569 beq $18,end_w # U : All done?
570 ldq $7,0($5) # L :
571 mskqh $7,$6,$2 # U : Mask final quad
572
573 insqh $17,$6,$4 # U : New bits
574 bis $2,$4,$1 # E : Put it all together
575 stq $1,0($5) # L : And back to memory
576 ret $31,($26),1 # L0 :
577
578within_quad_w:
579 ldq_u $1,0($16) # L :
580 insql $17,$16,$2 # U : New bits
581 mskql $1,$16,$4 # U : Clear old
582 bis $2,$4,$2 # E : New result
583
584 mskql $2,$6,$4 # U :
585 mskqh $1,$6,$2 # U :
586 bis $2,$4,$1 # E :
587 stq_u $1,0($16) # L :
588
589end_w:
590 nop
591 nop
592 nop
593 ret $31,($26),1 # L0 :
594
595 .end __memsetw
596
597memset = __memset
diff --git a/arch/alpha/lib/ev6-strncpy_from_user.S b/arch/alpha/lib/ev6-strncpy_from_user.S
new file mode 100644
index 000000000000..d2e28178cacc
--- /dev/null
+++ b/arch/alpha/lib/ev6-strncpy_from_user.S
@@ -0,0 +1,424 @@
1/*
2 * arch/alpha/lib/ev6-strncpy_from_user.S
3 * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
4 *
5 * Just like strncpy except in the return value:
6 *
7 * -EFAULT if an exception occurs before the terminator is copied.
8 * N if the buffer filled.
9 *
10 * Otherwise the length of the string is returned.
11 *
12 * Much of the information about 21264 scheduling/coding comes from:
13 * Compiler Writer's Guide for the Alpha 21264
14 * abbreviated as 'CWG' in other comments here
15 * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
16 * Scheduling notation:
17 * E - either cluster
18 * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
19 * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
20 * A bunch of instructions got moved and temp registers were changed
21 * to aid in scheduling. Control flow was also re-arranged to eliminate
22 * branches, and to provide longer code sequences to enable better scheduling.
23 * A total rewrite (using byte load/stores for start & tail sequences)
24 * is desirable, but very difficult to do without a from-scratch rewrite.
25 * Save that for the future.
26 */
27
28
29#include <asm/errno.h>
30#include <asm/regdef.h>
31
32
33/* Allow an exception for an insn; exit if we get one. */
34#define EX(x,y...) \
35 99: x,##y; \
36 .section __ex_table,"a"; \
37 .long 99b - .; \
38 lda $31, $exception-99b($0); \
39 .previous
40
41
42 .set noat
43 .set noreorder
44 .text
45
46 .globl __strncpy_from_user
47 .ent __strncpy_from_user
48 .frame $30, 0, $26
49 .prologue 0
50
51 .align 4
52__strncpy_from_user:
53 and a0, 7, t3 # E : find dest misalignment
54 beq a2, $zerolength # U :
55
56 /* Are source and destination co-aligned? */
57 mov a0, v0 # E : save the string start
58 xor a0, a1, t4 # E :
59 EX( ldq_u t1, 0(a1) ) # L : Latency=3 load first quadword
60 ldq_u t0, 0(a0) # L : load first (partial) aligned dest quadword
61
62 addq a2, t3, a2 # E : bias count by dest misalignment
63 subq a2, 1, a3 # E :
64 addq zero, 1, t10 # E :
65 and t4, 7, t4 # E : misalignment between the two
66
67 and a3, 7, t6 # E : number of tail bytes
68 sll t10, t6, t10 # E : t10 = bitmask of last count byte
69 bne t4, $unaligned # U :
70 lda t2, -1 # E : build a mask against false zero
71
72 /*
73 * We are co-aligned; take care of a partial first word.
74 * On entry to this basic block:
75 * t0 == the first destination word for masking back in
76 * t1 == the first source word.
77 */
78
79 srl a3, 3, a2 # E : a2 = loop counter = (count - 1)/8
80 addq a1, 8, a1 # E :
81 mskqh t2, a1, t2 # U : detection in the src word
82 nop
83
84 /* Create the 1st output word and detect 0's in the 1st input word. */
85 mskqh t1, a1, t3 # U :
86 mskql t0, a1, t0 # U : assemble the first output word
87 ornot t1, t2, t2 # E :
88 nop
89
90 cmpbge zero, t2, t8 # E : bits set iff null found
91 or t0, t3, t0 # E :
92 beq a2, $a_eoc # U :
93 bne t8, $a_eos # U : 2nd branch in a quad. Bad.
94
95 /* On entry to this basic block:
96 * t0 == a source quad not containing a null.
97 * a0 - current aligned destination address
98 * a1 - current aligned source address
99 * a2 - count of quadwords to move.
100 * NOTE: Loop improvement - unrolling this is going to be
101 * a huge win, since we're going to stall otherwise.
102 * Fix this later. For _really_ large copies, look
103 * at using wh64 on a look-ahead basis. See the code
104 * in clear_user.S and copy_user.S.
105 * Presumably, since (a0) and (a1) do not overlap (by C definition)
106 * Lots of nops here:
107 * - Separate loads from stores
108 * - Keep it to 1 branch/quadpack so the branch predictor
109 * can train.
110 */
111$a_loop:
112 stq_u t0, 0(a0) # L :
113 addq a0, 8, a0 # E :
114 nop
115 subq a2, 1, a2 # E :
116
117 EX( ldq_u t0, 0(a1) ) # L :
118 addq a1, 8, a1 # E :
119 cmpbge zero, t0, t8 # E : Stall 2 cycles on t0
120 beq a2, $a_eoc # U :
121
122 beq t8, $a_loop # U :
123 nop
124 nop
125 nop
126
127 /* Take care of the final (partial) word store. At this point
128 * the end-of-count bit is set in t8 iff it applies.
129 *
130 * On entry to this basic block we have:
131 * t0 == the source word containing the null
132 * t8 == the cmpbge mask that found it.
133 */
134$a_eos:
135 negq t8, t12 # E : find low bit set
136 and t8, t12, t12 # E :
137
138 /* We're doing a partial word store and so need to combine
139 our source and original destination words. */
140 ldq_u t1, 0(a0) # L :
141 subq t12, 1, t6 # E :
142
143 or t12, t6, t8 # E :
144 zapnot t0, t8, t0 # U : clear src bytes > null
145 zap t1, t8, t1 # U : clear dst bytes <= null
146 or t0, t1, t0 # E :
147
148 stq_u t0, 0(a0) # L :
149 br $finish_up # L0 :
150 nop
151 nop
152
153 /* Add the end-of-count bit to the eos detection bitmask. */
154 .align 4
155$a_eoc:
156 or t10, t8, t8
157 br $a_eos
158 nop
159 nop
160
161
162/* The source and destination are not co-aligned. Align the destination
163 and cope. We have to be very careful about not reading too much and
164 causing a SEGV. */
165
166 .align 4
167$u_head:
168 /* We know just enough now to be able to assemble the first
169 full source word. We can still find a zero at the end of it
170 that prevents us from outputting the whole thing.
171
172 On entry to this basic block:
173 t0 == the first dest word, unmasked
174 t1 == the shifted low bits of the first source word
175 t6 == bytemask that is -1 in dest word bytes */
176
177 EX( ldq_u t2, 8(a1) ) # L : load second src word
178 addq a1, 8, a1 # E :
179 mskql t0, a0, t0 # U : mask trailing garbage in dst
180 extqh t2, a1, t4 # U :
181
182 or t1, t4, t1 # E : first aligned src word complete
183 mskqh t1, a0, t1 # U : mask leading garbage in src
184 or t0, t1, t0 # E : first output word complete
185 or t0, t6, t6 # E : mask original data for zero test
186
187 cmpbge zero, t6, t8 # E :
188 beq a2, $u_eocfin # U :
189 bne t8, $u_final # U : bad news - 2nd branch in a quad
190 lda t6, -1 # E : mask out the bits we have
191
192 mskql t6, a1, t6 # U : already seen
193 stq_u t0, 0(a0) # L : store first output word
194 or t6, t2, t2 # E :
195 cmpbge zero, t2, t8 # E : find nulls in second partial
196
197 addq a0, 8, a0 # E :
198 subq a2, 1, a2 # E :
199 bne t8, $u_late_head_exit # U :
200 nop
201
202 /* Finally, we've got all the stupid leading edge cases taken care
203 of and we can set up to enter the main loop. */
204
205 extql t2, a1, t1 # U : position hi-bits of lo word
206 EX( ldq_u t2, 8(a1) ) # L : read next high-order source word
207 addq a1, 8, a1 # E :
208 cmpbge zero, t2, t8 # E :
209
210 beq a2, $u_eoc # U :
211 bne t8, $u_eos # U :
212 nop
213 nop
214
215 /* Unaligned copy main loop. In order to avoid reading too much,
216 the loop is structured to detect zeros in aligned source words.
217 This has, unfortunately, effectively pulled half of a loop
218 iteration out into the head and half into the tail, but it does
219 prevent nastiness from accumulating in the very thing we want
220 to run as fast as possible.
221
222 On entry to this basic block:
223 t1 == the shifted high-order bits from the previous source word
224 t2 == the unshifted current source word
225
226 We further know that t2 does not contain a null terminator. */
227
228 /*
229 * Extra nops here:
230 * separate load quads from store quads
231 * only one branch/quad to permit predictor training
232 */
233
234 .align 4
235$u_loop:
236 extqh t2, a1, t0 # U : extract high bits for current word
237 addq a1, 8, a1 # E :
238 extql t2, a1, t3 # U : extract low bits for next time
239 addq a0, 8, a0 # E :
240
241 or t0, t1, t0 # E : current dst word now complete
242 EX( ldq_u t2, 0(a1) ) # L : load high word for next time
243 subq a2, 1, a2 # E :
244 nop
245
246 stq_u t0, -8(a0) # L : save the current word
247 mov t3, t1 # E :
248 cmpbge zero, t2, t8 # E : test new word for eos
249 beq a2, $u_eoc # U :
250
251 beq t8, $u_loop # U :
252 nop
253 nop
254 nop
255
256 /* We've found a zero somewhere in the source word we just read.
257 If it resides in the lower half, we have one (probably partial)
258 word to write out, and if it resides in the upper half, we
259 have one full and one partial word left to write out.
260
261 On entry to this basic block:
262 t1 == the shifted high-order bits from the previous source word
263 t2 == the unshifted current source word. */
264 .align 4
265$u_eos:
266 extqh t2, a1, t0 # U :
267 or t0, t1, t0 # E : first (partial) source word complete
268 cmpbge zero, t0, t8 # E : is the null in this first bit?
269 nop
270
271 bne t8, $u_final # U :
272 stq_u t0, 0(a0) # L : the null was in the high-order bits
273 addq a0, 8, a0 # E :
274 subq a2, 1, a2 # E :
275
276 .align 4
277$u_late_head_exit:
278 extql t2, a1, t0 # U :
279 cmpbge zero, t0, t8 # E :
280 or t8, t10, t6 # E :
281 cmoveq a2, t6, t8 # E :
282
283 /* Take care of a final (probably partial) result word.
284 On entry to this basic block:
285 t0 == assembled source word
286 t8 == cmpbge mask that found the null. */
287 .align 4
288$u_final:
289 negq t8, t6 # E : isolate low bit set
290 and t6, t8, t12 # E :
291 ldq_u t1, 0(a0) # L :
292 subq t12, 1, t6 # E :
293
294 or t6, t12, t8 # E :
295 zapnot t0, t8, t0 # U : kill source bytes > null
296 zap t1, t8, t1 # U : kill dest bytes <= null
297 or t0, t1, t0 # E :
298
299 stq_u t0, 0(a0) # E :
300 br $finish_up # U :
301 nop
302 nop
303
304 .align 4
305$u_eoc: # end-of-count
306 extqh t2, a1, t0 # U :
307 or t0, t1, t0 # E :
308 cmpbge zero, t0, t8 # E :
309 nop
310
311 .align 4
312$u_eocfin: # end-of-count, final word
313 or t10, t8, t8 # E :
314 br $u_final # U :
315 nop
316 nop
317
318 /* Unaligned copy entry point. */
319 .align 4
320$unaligned:
321
322 srl a3, 3, a2 # U : a2 = loop counter = (count - 1)/8
323 and a0, 7, t4 # E : find dest misalignment
324 and a1, 7, t5 # E : find src misalignment
325 mov zero, t0 # E :
326
327 /* Conditionally load the first destination word and a bytemask
328 with 0xff indicating that the destination byte is sacrosanct. */
329
330 mov zero, t6 # E :
331 beq t4, 1f # U :
332 ldq_u t0, 0(a0) # L :
333 lda t6, -1 # E :
334
335 mskql t6, a0, t6 # E :
336 nop
337 nop
338 nop
339
340 .align 4
3411:
342 subq a1, t4, a1 # E : sub dest misalignment from src addr
343 /* If source misalignment is larger than dest misalignment, we need
344 extra startup checks to avoid SEGV. */
345 cmplt t4, t5, t12 # E :
346 extql t1, a1, t1 # U : shift src into place
347 lda t2, -1 # E : for creating masks later
348
349 beq t12, $u_head # U :
350 mskqh t2, t5, t2 # U : begin src byte validity mask
351 cmpbge zero, t1, t8 # E : is there a zero?
352 nop
353
354 extql t2, a1, t2 # U :
355 or t8, t10, t5 # E : test for end-of-count too
356 cmpbge zero, t2, t3 # E :
357 cmoveq a2, t5, t8 # E : Latency=2, extra map slot
358
359 nop # E : goes with cmov
360 andnot t8, t3, t8 # E :
361 beq t8, $u_head # U :
362 nop
363
364 /* At this point we've found a zero in the first partial word of
365 the source. We need to isolate the valid source data and mask
366 it into the original destination data. (Incidentally, we know
367 that we'll need at least one byte of that original dest word.) */
368
369 ldq_u t0, 0(a0) # L :
370 negq t8, t6 # E : build bitmask of bytes <= zero
371 mskqh t1, t4, t1 # U :
372 and t6, t8, t12 # E :
373
374 subq t12, 1, t6 # E :
375 or t6, t12, t8 # E :
376 zapnot t2, t8, t2 # U : prepare source word; mirror changes
377 zapnot t1, t8, t1 # U : to source validity mask
378
379 andnot t0, t2, t0 # E : zero place for source to reside
380 or t0, t1, t0 # E : and put it there
381 stq_u t0, 0(a0) # L :
382 nop
383
384 .align 4
385$finish_up:
386 zapnot t0, t12, t4 # U : was last byte written null?
387 and t12, 0xf0, t3 # E : binary search for the address of the
388 cmovne t4, 1, t4 # E : Latency=2, extra map slot
389 nop # E : with cmovne
390
391 and t12, 0xcc, t2 # E : last byte written
392 and t12, 0xaa, t1 # E :
393 cmovne t3, 4, t3 # E : Latency=2, extra map slot
394 nop # E : with cmovne
395
396 bic a0, 7, t0
397 cmovne t2, 2, t2 # E : Latency=2, extra map slot
398 nop # E : with cmovne
399 nop
400
401 cmovne t1, 1, t1 # E : Latency=2, extra map slot
402 nop # E : with cmovne
403 addq t0, t3, t0 # E :
404 addq t1, t2, t1 # E :
405
406 addq t0, t1, t0 # E :
407 addq t0, t4, t0 # add one if we filled the buffer
408 subq t0, v0, v0 # find string length
409 ret # L0 :
410
411 .align 4
412$zerolength:
413 nop
414 nop
415 nop
416 clr v0
417
418$exception:
419 nop
420 nop
421 nop
422 ret
423
424 .end __strncpy_from_user
diff --git a/arch/alpha/lib/ev6-stxcpy.S b/arch/alpha/lib/ev6-stxcpy.S
new file mode 100644
index 000000000000..4643ff2ffc8d
--- /dev/null
+++ b/arch/alpha/lib/ev6-stxcpy.S
@@ -0,0 +1,321 @@
1/*
2 * arch/alpha/lib/ev6-stxcpy.S
3 * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
4 *
5 * Copy a null-terminated string from SRC to DST.
6 *
7 * This is an internal routine used by strcpy, stpcpy, and strcat.
8 * As such, it uses special linkage conventions to make implementation
9 * of these public functions more efficient.
10 *
11 * On input:
12 * t9 = return address
13 * a0 = DST
14 * a1 = SRC
15 *
16 * On output:
17 * t12 = bitmask (with one bit set) indicating the last byte written
18 * a0 = unaligned address of the last *word* written
19 *
20 * Furthermore, v0, a3-a5, t11, and t12 are untouched.
21 *
22 * Much of the information about 21264 scheduling/coding comes from:
23 * Compiler Writer's Guide for the Alpha 21264
24 * abbreviated as 'CWG' in other comments here
25 * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
26 * Scheduling notation:
27 * E - either cluster
28 * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
29 * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
30 * Try not to change the actual algorithm if possible for consistency.
31 */
32
33#include <asm/regdef.h>
34
35 .set noat
36 .set noreorder
37
38 .text
39
40/* There is a problem with either gdb (as of 4.16) or gas (as of 2.7) that
41 doesn't like putting the entry point for a procedure somewhere in the
42 middle of the procedure descriptor. Work around this by putting the
43 aligned copy in its own procedure descriptor */
44
45
46 .ent stxcpy_aligned
47 .align 4
48stxcpy_aligned:
49 .frame sp, 0, t9
50 .prologue 0
51
52 /* On entry to this basic block:
53 t0 == the first destination word for masking back in
54 t1 == the first source word. */
55
56 /* Create the 1st output word and detect 0's in the 1st input word. */
57 lda t2, -1 # E : build a mask against false zero
58 mskqh t2, a1, t2 # U : detection in the src word (stall)
59 mskqh t1, a1, t3 # U :
60 ornot t1, t2, t2 # E : (stall)
61
62 mskql t0, a1, t0 # U : assemble the first output word
63 cmpbge zero, t2, t8 # E : bits set iff null found
64 or t0, t3, t1 # E : (stall)
65 bne t8, $a_eos # U : (stall)
66
67 /* On entry to this basic block:
68 t0 == the first destination word for masking back in
69 t1 == a source word not containing a null. */
70 /* Nops here to separate store quads from load quads */
71
72$a_loop:
73 stq_u t1, 0(a0) # L :
74 addq a0, 8, a0 # E :
75 nop
76 nop
77
78 ldq_u t1, 0(a1) # L : Latency=3
79 addq a1, 8, a1 # E :
80 cmpbge zero, t1, t8 # E : (3 cycle stall)
81 beq t8, $a_loop # U : (stall for t8)
82
83 /* Take care of the final (partial) word store.
84 On entry to this basic block we have:
85 t1 == the source word containing the null
86 t8 == the cmpbge mask that found it. */
87$a_eos:
88 negq t8, t6 # E : find low bit set
89 and t8, t6, t12 # E : (stall)
90 /* For the sake of the cache, don't read a destination word
91 if we're not going to need it. */
92 and t12, 0x80, t6 # E : (stall)
93 bne t6, 1f # U : (stall)
94
95 /* We're doing a partial word store and so need to combine
96 our source and original destination words. */
97 ldq_u t0, 0(a0) # L : Latency=3
98 subq t12, 1, t6 # E :
99 zapnot t1, t6, t1 # U : clear src bytes >= null (stall)
100 or t12, t6, t8 # E : (stall)
101
102 zap t0, t8, t0 # E : clear dst bytes <= null
103 or t0, t1, t1 # E : (stall)
104 nop
105 nop
106
1071: stq_u t1, 0(a0) # L :
108 ret (t9) # L0 : Latency=3
109 nop
110 nop
111
112 .end stxcpy_aligned
113
114 .align 4
115 .ent __stxcpy
116 .globl __stxcpy
117__stxcpy:
118 .frame sp, 0, t9
119 .prologue 0
120
121 /* Are source and destination co-aligned? */
122 xor a0, a1, t0 # E :
123 unop # E :
124 and t0, 7, t0 # E : (stall)
125 bne t0, $unaligned # U : (stall)
126
127 /* We are co-aligned; take care of a partial first word. */
128 ldq_u t1, 0(a1) # L : load first src word
129 and a0, 7, t0 # E : take care not to load a word ...
130 addq a1, 8, a1 # E :
131 beq t0, stxcpy_aligned # U : ... if we wont need it (stall)
132
133 ldq_u t0, 0(a0) # L :
134 br stxcpy_aligned # L0 : Latency=3
135 nop
136 nop
137
138
139/* The source and destination are not co-aligned. Align the destination
140 and cope. We have to be very careful about not reading too much and
141 causing a SEGV. */
142
143 .align 4
144$u_head:
145 /* We know just enough now to be able to assemble the first
146 full source word. We can still find a zero at the end of it
147 that prevents us from outputting the whole thing.
148
149 On entry to this basic block:
150 t0 == the first dest word, for masking back in, if needed else 0
151 t1 == the low bits of the first source word
152 t6 == bytemask that is -1 in dest word bytes */
153
154 ldq_u t2, 8(a1) # L :
155 addq a1, 8, a1 # E :
156 extql t1, a1, t1 # U : (stall on a1)
157 extqh t2, a1, t4 # U : (stall on a1)
158
159 mskql t0, a0, t0 # U :
160 or t1, t4, t1 # E :
161 mskqh t1, a0, t1 # U : (stall on t1)
162 or t0, t1, t1 # E : (stall on t1)
163
164 or t1, t6, t6 # E :
165 cmpbge zero, t6, t8 # E : (stall)
166 lda t6, -1 # E : for masking just below
167 bne t8, $u_final # U : (stall)
168
169 mskql t6, a1, t6 # U : mask out the bits we have
170 or t6, t2, t2 # E : already extracted before (stall)
171 cmpbge zero, t2, t8 # E : testing eos (stall)
172 bne t8, $u_late_head_exit # U : (stall)
173
174 /* Finally, we've got all the stupid leading edge cases taken care
175 of and we can set up to enter the main loop. */
176
177 stq_u t1, 0(a0) # L : store first output word
178 addq a0, 8, a0 # E :
179 extql t2, a1, t0 # U : position ho-bits of lo word
180 ldq_u t2, 8(a1) # U : read next high-order source word
181
182 addq a1, 8, a1 # E :
183 cmpbge zero, t2, t8 # E : (stall for t2)
184 nop # E :
185 bne t8, $u_eos # U : (stall)
186
187 /* Unaligned copy main loop. In order to avoid reading too much,
188 the loop is structured to detect zeros in aligned source words.
189 This has, unfortunately, effectively pulled half of a loop
190 iteration out into the head and half into the tail, but it does
191 prevent nastiness from accumulating in the very thing we want
192 to run as fast as possible.
193
194 On entry to this basic block:
195 t0 == the shifted high-order bits from the previous source word
196 t2 == the unshifted current source word
197
198 We further know that t2 does not contain a null terminator. */
199
200 .align 3
201$u_loop:
202 extqh t2, a1, t1 # U : extract high bits for current word
203 addq a1, 8, a1 # E : (stall)
204 extql t2, a1, t3 # U : extract low bits for next time (stall)
205 addq a0, 8, a0 # E :
206
207 or t0, t1, t1 # E : current dst word now complete
208 ldq_u t2, 0(a1) # L : Latency=3 load high word for next time
209 stq_u t1, -8(a0) # L : save the current word (stall)
210 mov t3, t0 # E :
211
212 cmpbge zero, t2, t8 # E : test new word for eos
213 beq t8, $u_loop # U : (stall)
214 nop
215 nop
216
217 /* We've found a zero somewhere in the source word we just read.
218 If it resides in the lower half, we have one (probably partial)
219 word to write out, and if it resides in the upper half, we
220 have one full and one partial word left to write out.
221
222 On entry to this basic block:
223 t0 == the shifted high-order bits from the previous source word
224 t2 == the unshifted current source word. */
225$u_eos:
226 extqh t2, a1, t1 # U :
227 or t0, t1, t1 # E : first (partial) source word complete (stall)
228 cmpbge zero, t1, t8 # E : is the null in this first bit? (stall)
229 bne t8, $u_final # U : (stall)
230
231$u_late_head_exit:
232 stq_u t1, 0(a0) # L : the null was in the high-order bits
233 addq a0, 8, a0 # E :
234 extql t2, a1, t1 # U :
235 cmpbge zero, t1, t8 # E : (stall)
236
237 /* Take care of a final (probably partial) result word.
238 On entry to this basic block:
239 t1 == assembled source word
240 t8 == cmpbge mask that found the null. */
241$u_final:
242 negq t8, t6 # E : isolate low bit set
243 and t6, t8, t12 # E : (stall)
244 and t12, 0x80, t6 # E : avoid dest word load if we can (stall)
245 bne t6, 1f # U : (stall)
246
247 ldq_u t0, 0(a0) # E :
248 subq t12, 1, t6 # E :
249 or t6, t12, t8 # E : (stall)
250 zapnot t1, t6, t1 # U : kill source bytes >= null (stall)
251
252 zap t0, t8, t0 # U : kill dest bytes <= null (2 cycle data stall)
253 or t0, t1, t1 # E : (stall)
254 nop
255 nop
256
2571: stq_u t1, 0(a0) # L :
258 ret (t9) # L0 : Latency=3
259 nop
260 nop
261
262 /* Unaligned copy entry point. */
263 .align 4
264$unaligned:
265
266 ldq_u t1, 0(a1) # L : load first source word
267 and a0, 7, t4 # E : find dest misalignment
268 and a1, 7, t5 # E : find src misalignment
269 /* Conditionally load the first destination word and a bytemask
270 with 0xff indicating that the destination byte is sacrosanct. */
271 mov zero, t0 # E :
272
273 mov zero, t6 # E :
274 beq t4, 1f # U :
275 ldq_u t0, 0(a0) # L :
276 lda t6, -1 # E :
277
278 mskql t6, a0, t6 # U :
279 nop
280 nop
281 nop
2821:
283 subq a1, t4, a1 # E : sub dest misalignment from src addr
284 /* If source misalignment is larger than dest misalignment, we need
285 extra startup checks to avoid SEGV. */
286 cmplt t4, t5, t12 # E :
287 beq t12, $u_head # U :
288 lda t2, -1 # E : mask out leading garbage in source
289
290 mskqh t2, t5, t2 # U :
291 ornot t1, t2, t3 # E : (stall)
292 cmpbge zero, t3, t8 # E : is there a zero? (stall)
293 beq t8, $u_head # U : (stall)
294
295 /* At this point we've found a zero in the first partial word of
296 the source. We need to isolate the valid source data and mask
297 it into the original destination data. (Incidentally, we know
298 that we'll need at least one byte of that original dest word.) */
299
300 ldq_u t0, 0(a0) # L :
301 negq t8, t6 # E : build bitmask of bytes <= zero
302 and t6, t8, t12 # E : (stall)
303 and a1, 7, t5 # E :
304
305 subq t12, 1, t6 # E :
306 or t6, t12, t8 # E : (stall)
307 srl t12, t5, t12 # U : adjust final null return value
308 zapnot t2, t8, t2 # U : prepare source word; mirror changes (stall)
309
310 and t1, t2, t1 # E : to source validity mask
311 extql t2, a1, t2 # U :
312 extql t1, a1, t1 # U : (stall)
313 andnot t0, t2, t0 # .. e1 : zero place for source to reside (stall)
314
315 or t0, t1, t1 # e1 : and put it there
316 stq_u t1, 0(a0) # .. e0 : (stall)
317 ret (t9) # e1 :
318 nop
319
320 .end __stxcpy
321
diff --git a/arch/alpha/lib/ev6-stxncpy.S b/arch/alpha/lib/ev6-stxncpy.S
new file mode 100644
index 000000000000..b581a7af2456
--- /dev/null
+++ b/arch/alpha/lib/ev6-stxncpy.S
@@ -0,0 +1,397 @@
1/*
2 * arch/alpha/lib/ev6-stxncpy.S
3 * 21264 version contributed by Rick Gorton <rick.gorton@api-networks.com>
4 *
5 * Copy no more than COUNT bytes of the null-terminated string from
6 * SRC to DST.
7 *
8 * This is an internal routine used by strncpy, stpncpy, and strncat.
9 * As such, it uses special linkage conventions to make implementation
10 * of these public functions more efficient.
11 *
12 * On input:
13 * t9 = return address
14 * a0 = DST
15 * a1 = SRC
16 * a2 = COUNT
17 *
18 * Furthermore, COUNT may not be zero.
19 *
20 * On output:
21 * t0 = last word written
22 * t10 = bitmask (with one bit set) indicating the byte position of
23 * the end of the range specified by COUNT
24 * t12 = bitmask (with one bit set) indicating the last byte written
25 * a0 = unaligned address of the last *word* written
26 * a2 = the number of full words left in COUNT
27 *
28 * Furthermore, v0, a3-a5, t11, and $at are untouched.
29 *
30 * Much of the information about 21264 scheduling/coding comes from:
31 * Compiler Writer's Guide for the Alpha 21264
32 * abbreviated as 'CWG' in other comments here
33 * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
34 * Scheduling notation:
35 * E - either cluster
36 * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
37 * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
38 * Try not to change the actual algorithm if possible for consistency.
39 */
40
41#include <asm/regdef.h>
42
43 .set noat
44 .set noreorder
45
46 .text
47
48/* There is a problem with either gdb (as of 4.16) or gas (as of 2.7) that
49 doesn't like putting the entry point for a procedure somewhere in the
50 middle of the procedure descriptor. Work around this by putting the
51 aligned copy in its own procedure descriptor */
52
53
54 .ent stxncpy_aligned
55 .align 4
56stxncpy_aligned:
57 .frame sp, 0, t9, 0
58 .prologue 0
59
60 /* On entry to this basic block:
61 t0 == the first destination word for masking back in
62 t1 == the first source word. */
63
64 /* Create the 1st output word and detect 0's in the 1st input word. */
65 lda t2, -1 # E : build a mask against false zero
66 mskqh t2, a1, t2 # U : detection in the src word (stall)
67 mskqh t1, a1, t3 # U :
68 ornot t1, t2, t2 # E : (stall)
69
70 mskql t0, a1, t0 # U : assemble the first output word
71 cmpbge zero, t2, t8 # E : bits set iff null found
72 or t0, t3, t0 # E : (stall)
73 beq a2, $a_eoc # U :
74
75 bne t8, $a_eos # U :
76 nop
77 nop
78 nop
79
80 /* On entry to this basic block:
81 t0 == a source word not containing a null. */
82
83 /*
84 * nops here to:
85 * separate store quads from load quads
86 * limit of 1 bcond/quad to permit training
87 */
88$a_loop:
89 stq_u t0, 0(a0) # L :
90 addq a0, 8, a0 # E :
91 subq a2, 1, a2 # E :
92 nop
93
94 ldq_u t0, 0(a1) # L :
95 addq a1, 8, a1 # E :
96 cmpbge zero, t0, t8 # E :
97 beq a2, $a_eoc # U :
98
99 beq t8, $a_loop # U :
100 nop
101 nop
102 nop
103
104 /* Take care of the final (partial) word store. At this point
105 the end-of-count bit is set in t8 iff it applies.
106
107 On entry to this basic block we have:
108 t0 == the source word containing the null
109 t8 == the cmpbge mask that found it. */
110
111$a_eos:
112 negq t8, t12 # E : find low bit set
113 and t8, t12, t12 # E : (stall)
114 /* For the sake of the cache, don't read a destination word
115 if we're not going to need it. */
116 and t12, 0x80, t6 # E : (stall)
117 bne t6, 1f # U : (stall)
118
119 /* We're doing a partial word store and so need to combine
120 our source and original destination words. */
121 ldq_u t1, 0(a0) # L :
122 subq t12, 1, t6 # E :
123 or t12, t6, t8 # E : (stall)
124 zapnot t0, t8, t0 # U : clear src bytes > null (stall)
125
126 zap t1, t8, t1 # .. e1 : clear dst bytes <= null
127 or t0, t1, t0 # e1 : (stall)
128 nop
129 nop
130
1311: stq_u t0, 0(a0) # L :
132 ret (t9) # L0 : Latency=3
133 nop
134 nop
135
136 /* Add the end-of-count bit to the eos detection bitmask. */
137$a_eoc:
138 or t10, t8, t8 # E :
139 br $a_eos # L0 : Latency=3
140 nop
141 nop
142
143 .end stxncpy_aligned
144
145 .align 4
146 .ent __stxncpy
147 .globl __stxncpy
148__stxncpy:
149 .frame sp, 0, t9, 0
150 .prologue 0
151
152 /* Are source and destination co-aligned? */
153 xor a0, a1, t1 # E :
154 and a0, 7, t0 # E : find dest misalignment
155 and t1, 7, t1 # E : (stall)
156 addq a2, t0, a2 # E : bias count by dest misalignment (stall)
157
158 subq a2, 1, a2 # E :
159 and a2, 7, t2 # E : (stall)
160 srl a2, 3, a2 # U : a2 = loop counter = (count - 1)/8 (stall)
161 addq zero, 1, t10 # E :
162
163 sll t10, t2, t10 # U : t10 = bitmask of last count byte
164 bne t1, $unaligned # U :
165 /* We are co-aligned; take care of a partial first word. */
166 ldq_u t1, 0(a1) # L : load first src word
167 addq a1, 8, a1 # E :
168
169 beq t0, stxncpy_aligned # U : avoid loading dest word if not needed
170 ldq_u t0, 0(a0) # L :
171 nop
172 nop
173
174 br stxncpy_aligned # .. e1 :
175 nop
176 nop
177 nop
178
179
180
181/* The source and destination are not co-aligned. Align the destination
182 and cope. We have to be very careful about not reading too much and
183 causing a SEGV. */
184
185 .align 4
186$u_head:
187 /* We know just enough now to be able to assemble the first
188 full source word. We can still find a zero at the end of it
189 that prevents us from outputting the whole thing.
190
191 On entry to this basic block:
192 t0 == the first dest word, unmasked
193 t1 == the shifted low bits of the first source word
194 t6 == bytemask that is -1 in dest word bytes */
195
196 ldq_u t2, 8(a1) # L : Latency=3 load second src word
197 addq a1, 8, a1 # E :
198 mskql t0, a0, t0 # U : mask trailing garbage in dst
199 extqh t2, a1, t4 # U : (3 cycle stall on t2)
200
201 or t1, t4, t1 # E : first aligned src word complete (stall)
202 mskqh t1, a0, t1 # U : mask leading garbage in src (stall)
203 or t0, t1, t0 # E : first output word complete (stall)
204 or t0, t6, t6 # E : mask original data for zero test (stall)
205
206 cmpbge zero, t6, t8 # E :
207 beq a2, $u_eocfin # U :
208 lda t6, -1 # E :
209 nop
210
211 bne t8, $u_final # U :
212 mskql t6, a1, t6 # U : mask out bits already seen
213 stq_u t0, 0(a0) # L : store first output word
214 or t6, t2, t2 # E : (stall)
215
216 cmpbge zero, t2, t8 # E : find nulls in second partial
217 addq a0, 8, a0 # E :
218 subq a2, 1, a2 # E :
219 bne t8, $u_late_head_exit # U :
220
221 /* Finally, we've got all the stupid leading edge cases taken care
222 of and we can set up to enter the main loop. */
223 extql t2, a1, t1 # U : position hi-bits of lo word
224 beq a2, $u_eoc # U :
225 ldq_u t2, 8(a1) # L : read next high-order source word
226 addq a1, 8, a1 # E :
227
228 extqh t2, a1, t0 # U : position lo-bits of hi word (stall)
229 cmpbge zero, t2, t8 # E :
230 nop
231 bne t8, $u_eos # U :
232
233 /* Unaligned copy main loop. In order to avoid reading too much,
234 the loop is structured to detect zeros in aligned source words.
235 This has, unfortunately, effectively pulled half of a loop
236 iteration out into the head and half into the tail, but it does
237 prevent nastiness from accumulating in the very thing we want
238 to run as fast as possible.
239
240 On entry to this basic block:
241 t0 == the shifted low-order bits from the current source word
242 t1 == the shifted high-order bits from the previous source word
243 t2 == the unshifted current source word
244
245 We further know that t2 does not contain a null terminator. */
246
247 .align 4
248$u_loop:
249 or t0, t1, t0 # E : current dst word now complete
250 subq a2, 1, a2 # E : decrement word count
251 extql t2, a1, t1 # U : extract low bits for next time
252 addq a0, 8, a0 # E :
253
254 stq_u t0, -8(a0) # U : save the current word
255 beq a2, $u_eoc # U :
256 ldq_u t2, 8(a1) # U : Latency=3 load high word for next time
257 addq a1, 8, a1 # E :
258
259 extqh t2, a1, t0 # U : extract low bits (2 cycle stall)
260 cmpbge zero, t2, t8 # E : test new word for eos
261 nop
262 beq t8, $u_loop # U :
263
264 /* We've found a zero somewhere in the source word we just read.
265 If it resides in the lower half, we have one (probably partial)
266 word to write out, and if it resides in the upper half, we
267 have one full and one partial word left to write out.
268
269 On entry to this basic block:
270 t0 == the shifted low-order bits from the current source word
271 t1 == the shifted high-order bits from the previous source word
272 t2 == the unshifted current source word. */
273$u_eos:
274 or t0, t1, t0 # E : first (partial) source word complete
275 nop
276 cmpbge zero, t0, t8 # E : is the null in this first bit? (stall)
277 bne t8, $u_final # U : (stall)
278
279 stq_u t0, 0(a0) # L : the null was in the high-order bits
280 addq a0, 8, a0 # E :
281 subq a2, 1, a2 # E :
282 nop
283
284$u_late_head_exit:
285 extql t2, a1, t0 # U :
286 cmpbge zero, t0, t8 # E :
287 or t8, t10, t6 # E : (stall)
288 cmoveq a2, t6, t8 # E : Latency=2, extra map slot (stall)
289
290 /* Take care of a final (probably partial) result word.
291 On entry to this basic block:
292 t0 == assembled source word
293 t8 == cmpbge mask that found the null. */
294$u_final:
295 negq t8, t6 # E : isolate low bit set
296 and t6, t8, t12 # E : (stall)
297 and t12, 0x80, t6 # E : avoid dest word load if we can (stall)
298 bne t6, 1f # U : (stall)
299
300 ldq_u t1, 0(a0) # L :
301 subq t12, 1, t6 # E :
302 or t6, t12, t8 # E : (stall)
303 zapnot t0, t8, t0 # U : kill source bytes > null
304
305 zap t1, t8, t1 # U : kill dest bytes <= null
306 or t0, t1, t0 # E : (stall)
307 nop
308 nop
309
3101: stq_u t0, 0(a0) # L :
311 ret (t9) # L0 : Latency=3
312
313 /* Got to end-of-count before end of string.
314 On entry to this basic block:
315 t1 == the shifted high-order bits from the previous source word */
316$u_eoc:
317 and a1, 7, t6 # E : avoid final load if possible
318 sll t10, t6, t6 # U : (stall)
319 and t6, 0xff, t6 # E : (stall)
320 bne t6, 1f # U : (stall)
321
322 ldq_u t2, 8(a1) # L : load final src word
323 nop
324 extqh t2, a1, t0 # U : extract low bits for last word (stall)
325 or t1, t0, t1 # E : (stall)
326
3271: cmpbge zero, t1, t8 # E :
328 mov t1, t0 # E :
329
330$u_eocfin: # end-of-count, final word
331 or t10, t8, t8 # E :
332 br $u_final # L0 : Latency=3
333
334 /* Unaligned copy entry point. */
335 .align 4
336$unaligned:
337
338 ldq_u t1, 0(a1) # L : load first source word
339 and a0, 7, t4 # E : find dest misalignment
340 and a1, 7, t5 # E : find src misalignment
341 /* Conditionally load the first destination word and a bytemask
342 with 0xff indicating that the destination byte is sacrosanct. */
343 mov zero, t0 # E :
344
345 mov zero, t6 # E :
346 beq t4, 1f # U :
347 ldq_u t0, 0(a0) # L :
348 lda t6, -1 # E :
349
350 mskql t6, a0, t6 # U :
351 nop
352 nop
353 subq a1, t4, a1 # E : sub dest misalignment from src addr
354
355 /* If source misalignment is larger than dest misalignment, we need
356 extra startup checks to avoid SEGV. */
357
3581: cmplt t4, t5, t12 # E :
359 extql t1, a1, t1 # U : shift src into place
360 lda t2, -1 # E : for creating masks later
361 beq t12, $u_head # U : (stall)
362
363 extql t2, a1, t2 # U :
364 cmpbge zero, t1, t8 # E : is there a zero?
365 andnot t2, t6, t12 # E : dest mask for a single word copy
366 or t8, t10, t5 # E : test for end-of-count too
367
368 cmpbge zero, t12, t3 # E :
369 cmoveq a2, t5, t8 # E : Latency=2, extra map slot
370 nop # E : keep with cmoveq
371 andnot t8, t3, t8 # E : (stall)
372
373 beq t8, $u_head # U :
374 /* At this point we've found a zero in the first partial word of
375 the source. We need to isolate the valid source data and mask
376 it into the original destination data. (Incidentally, we know
377 that we'll need at least one byte of that original dest word.) */
378 ldq_u t0, 0(a0) # L :
379 negq t8, t6 # E : build bitmask of bytes <= zero
380 mskqh t1, t4, t1 # U :
381
382 and t6, t8, t2 # E :
383 subq t2, 1, t6 # E : (stall)
384 or t6, t2, t8 # E : (stall)
385 zapnot t12, t8, t12 # U : prepare source word; mirror changes (stall)
386
387 zapnot t1, t8, t1 # U : to source validity mask
388 andnot t0, t12, t0 # E : zero place for source to reside
389 or t0, t1, t0 # E : and put it there (stall both t0, t1)
390 stq_u t0, 0(a0) # L : (stall)
391
392 ret (t9) # L0 : Latency=3
393 nop
394 nop
395 nop
396
397 .end __stxncpy
diff --git a/arch/alpha/lib/ev67-strcat.S b/arch/alpha/lib/ev67-strcat.S
new file mode 100644
index 000000000000..c426fe3ed72f
--- /dev/null
+++ b/arch/alpha/lib/ev67-strcat.S
@@ -0,0 +1,54 @@
1/*
2 * arch/alpha/lib/ev67-strcat.S
3 * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
4 *
5 * Append a null-terminated string from SRC to DST.
6 *
7 * Much of the information about 21264 scheduling/coding comes from:
8 * Compiler Writer's Guide for the Alpha 21264
9 * abbreviated as 'CWG' in other comments here
10 * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
11 * Scheduling notation:
12 * E - either cluster
13 * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
14 * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
15 * Try not to change the actual algorithm if possible for consistency.
16 * Commentary: It seems bogus to walk the input string twice - once
17 * to determine the length, and then again while doing the copy.
18 * A significant (future) enhancement would be to only read the input
19 * string once.
20 */
21
22
23 .text
24
25 .align 4
26 .globl strcat
27 .ent strcat
28strcat:
29 .frame $30, 0, $26
30 .prologue 0
31
32 mov $16, $0 # E : set up return value
33 /* Find the end of the string. */
34 ldq_u $1, 0($16) # L : load first quadword (a0 may be misaligned)
35 lda $2, -1 # E :
36 insqh $2, $16, $2 # U :
37
38 andnot $16, 7, $16 # E :
39 or $2, $1, $1 # E :
40 cmpbge $31, $1, $2 # E : bits set iff byte == 0
41 bne $2, $found # U :
42
43$loop: ldq $1, 8($16) # L :
44 addq $16, 8, $16 # E :
45 cmpbge $31, $1, $2 # E :
46 beq $2, $loop # U :
47
48$found: cttz $2, $3 # U0 :
49 addq $16, $3, $16 # E :
50 /* Now do the append. */
51 mov $26, $23 # E :
52 br __stxcpy # L0 :
53
54 .end strcat
diff --git a/arch/alpha/lib/ev67-strchr.S b/arch/alpha/lib/ev67-strchr.S
new file mode 100644
index 000000000000..fbb7b4ffade9
--- /dev/null
+++ b/arch/alpha/lib/ev67-strchr.S
@@ -0,0 +1,88 @@
1/*
2 * arch/alpha/lib/ev67-strchr.S
3 * 21264 version contributed by Rick Gorton <rick.gorton@alpha-processor.com>
4 *
5 * Return the address of a given character within a null-terminated
6 * string, or null if it is not found.
7 *
8 * Much of the information about 21264 scheduling/coding comes from:
9 * Compiler Writer's Guide for the Alpha 21264
10 * abbreviated as 'CWG' in other comments here
11 * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
12 * Scheduling notation:
13 * E - either cluster
14 * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
15 * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
16 * Try not to change the actual algorithm if possible for consistency.
17 */
18
19#include <asm/regdef.h>
20
21 .set noreorder
22 .set noat
23
24 .align 4
25 .globl strchr
26 .ent strchr
27strchr:
28 .frame sp, 0, ra
29 .prologue 0
30
31 ldq_u t0, 0(a0) # L : load first quadword Latency=3
32 and a1, 0xff, t3 # E : 00000000000000ch
33 insbl a1, 1, t5 # U : 000000000000ch00
34 insbl a1, 7, a2 # U : ch00000000000000
35
36 insbl t3, 6, a3 # U : 00ch000000000000
37 or t5, t3, a1 # E : 000000000000chch
38 andnot a0, 7, v0 # E : align our loop pointer
39 lda t4, -1 # E : build garbage mask
40
41 mskqh t4, a0, t4 # U : only want relevant part of first quad
42 or a2, a3, a2 # E : chch000000000000
43 inswl a1, 2, t5 # E : 00000000chch0000
44 inswl a1, 4, a3 # E : 0000chch00000000
45
46 or a1, a2, a1 # E : chch00000000chch
47 or a3, t5, t5 # E : 0000chchchch0000
48 cmpbge zero, t0, t2 # E : bits set iff byte == zero
49 cmpbge zero, t4, t4 # E : bits set iff byte is garbage
50
51 /* This quad is _very_ serialized. Lots of stalling happens */
52 or t5, a1, a1 # E : chchchchchchchch
53 xor t0, a1, t1 # E : make bytes == c zero
54 cmpbge zero, t1, t3 # E : bits set iff byte == c
55 or t2, t3, t0 # E : bits set iff char match or zero match
56
57 andnot t0, t4, t0 # E : clear garbage bits
58 cttz t0, a2 # U0 : speculative (in case we get a match)
59 nop # E :
60 bne t0, $found # U :
61
62 /*
63 * Yuk. This loop is going to stall like crazy waiting for the
64 * data to be loaded. Not much can be done about it unless it's
65 * unrolled multiple times - is that safe to do in kernel space?
66 * Or would exception handling recovery code do the trick here?
67 */
68$loop: ldq t0, 8(v0) # L : Latency=3
69 addq v0, 8, v0 # E :
70 xor t0, a1, t1 # E :
71 cmpbge zero, t0, t2 # E : bits set iff byte == 0
72
73 cmpbge zero, t1, t3 # E : bits set iff byte == c
74 or t2, t3, t0 # E :
75 cttz t3, a2 # U0 : speculative (in case we get a match)
76 beq t0, $loop # U :
77
78$found: negq t0, t1 # E : clear all but least set bit
79 and t0, t1, t0 # E :
80 and t0, t3, t1 # E : bit set iff byte was the char
81 addq v0, a2, v0 # E : Add in the bit number from above
82
83 cmoveq t1, $31, v0 # E : Two mapping slots, latency = 2
84 nop
85 nop
86 ret # L0 :
87
88 .end strchr
diff --git a/arch/alpha/lib/ev67-strlen.S b/arch/alpha/lib/ev67-strlen.S
new file mode 100644
index 000000000000..503928072523
--- /dev/null
+++ b/arch/alpha/lib/ev67-strlen.S
@@ -0,0 +1,49 @@
1/*
2 * arch/alpha/lib/ev67-strlen.S
3 * 21264 version by Rick Gorton <rick.gorton@alpha-processor.com>
4 *
5 * Finds length of a 0-terminated string. Optimized for the
6 * Alpha architecture:
7 *
8 * - memory accessed as aligned quadwords only
9 * - uses bcmpge to compare 8 bytes in parallel
10 *
11 * Much of the information about 21264 scheduling/coding comes from:
12 * Compiler Writer's Guide for the Alpha 21264
13 * abbreviated as 'CWG' in other comments here
14 * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
15 * Scheduling notation:
16 * E - either cluster
17 * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
18 * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
19 */
20
21 .set noreorder
22 .set noat
23
24 .globl strlen
25 .ent strlen
26 .align 4
27strlen:
28 ldq_u $1, 0($16) # L : load first quadword ($16 may be misaligned)
29 lda $2, -1($31) # E :
30 insqh $2, $16, $2 # U :
31 andnot $16, 7, $0 # E :
32
33 or $2, $1, $1 # E :
34 cmpbge $31, $1, $2 # E : $2 <- bitmask: bit i == 1 <==> i-th byte == 0
35 nop # E :
36 bne $2, $found # U :
37
38$loop: ldq $1, 8($0) # L :
39 addq $0, 8, $0 # E : addr += 8
40 cmpbge $31, $1, $2 # E :
41 beq $2, $loop # U :
42
43$found:
44 cttz $2, $3 # U0 :
45 addq $0, $3, $0 # E :
46 subq $0, $16, $0 # E :
47 ret $31, ($26) # L0 :
48
49 .end strlen
diff --git a/arch/alpha/lib/ev67-strlen_user.S b/arch/alpha/lib/ev67-strlen_user.S
new file mode 100644
index 000000000000..57e0d77b81a6
--- /dev/null
+++ b/arch/alpha/lib/ev67-strlen_user.S
@@ -0,0 +1,107 @@
1/*
2 * arch/alpha/lib/ev67-strlen_user.S
3 * 21264 version contributed by Rick Gorton <rick.gorton@api-networks.com>
4 *
5 * Return the length of the string including the NULL terminator
6 * (strlen+1) or zero if an error occurred.
7 *
8 * In places where it is critical to limit the processing time,
9 * and the data is not trusted, strnlen_user() should be used.
10 * It will return a value greater than its second argument if
11 * that limit would be exceeded. This implementation is allowed
12 * to access memory beyond the limit, but will not cross a page
13 * boundary when doing so.
14 *
15 * Much of the information about 21264 scheduling/coding comes from:
16 * Compiler Writer's Guide for the Alpha 21264
17 * abbreviated as 'CWG' in other comments here
18 * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
19 * Scheduling notation:
20 * E - either cluster
21 * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
22 * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
23 * Try not to change the actual algorithm if possible for consistency.
24 */
25
26#include <asm/regdef.h>
27
28
29/* Allow an exception for an insn; exit if we get one. */
30#define EX(x,y...) \
31 99: x,##y; \
32 .section __ex_table,"a"; \
33 .long 99b - .; \
34 lda v0, $exception-99b(zero); \
35 .previous
36
37
38 .set noreorder
39 .set noat
40 .text
41
42 .globl __strlen_user
43 .ent __strlen_user
44 .frame sp, 0, ra
45
46 .align 4
47__strlen_user:
48 ldah a1, 32767(zero) # do not use plain strlen_user() for strings
49 # that might be almost 2 GB long; you should
50 # be using strnlen_user() instead
51 nop
52 nop
53 nop
54
55 .globl __strnlen_user
56
57 .align 4
58__strnlen_user:
59 .prologue 0
60 EX( ldq_u t0, 0(a0) ) # L : load first quadword (a0 may be misaligned)
61 lda t1, -1(zero) # E :
62
63 insqh t1, a0, t1 # U :
64 andnot a0, 7, v0 # E :
65 or t1, t0, t0 # E :
66 subq a0, 1, a0 # E : get our +1 for the return
67
68 cmpbge zero, t0, t1 # E : t1 <- bitmask: bit i == 1 <==> i-th byte == 0
69 subq a1, 7, t2 # E :
70 subq a0, v0, t0 # E :
71 bne t1, $found # U :
72
73 addq t2, t0, t2 # E :
74 addq a1, 1, a1 # E :
75 nop # E :
76 nop # E :
77
78 .align 4
79$loop: ble t2, $limit # U :
80 EX( ldq t0, 8(v0) ) # L :
81 nop # E :
82 nop # E :
83
84 cmpbge zero, t0, t1 # E :
85 subq t2, 8, t2 # E :
86 addq v0, 8, v0 # E : addr += 8
87 beq t1, $loop # U :
88
89$found: cttz t1, t2 # U0 :
90 addq v0, t2, v0 # E :
91 subq v0, a0, v0 # E :
92 ret # L0 :
93
94$exception:
95 nop
96 nop
97 nop
98 ret
99
100 .align 4 # currently redundant
101$limit:
102 nop
103 nop
104 subq a1, t2, v0
105 ret
106
107 .end __strlen_user
diff --git a/arch/alpha/lib/ev67-strncat.S b/arch/alpha/lib/ev67-strncat.S
new file mode 100644
index 000000000000..4ae716cd2bfb
--- /dev/null
+++ b/arch/alpha/lib/ev67-strncat.S
@@ -0,0 +1,94 @@
1/*
2 * arch/alpha/lib/ev67-strncat.S
3 * 21264 version contributed by Rick Gorton <rick.gorton@api-networks.com>
4 *
5 * Append no more than COUNT characters from the null-terminated string SRC
6 * to the null-terminated string DST. Always null-terminate the new DST.
7 *
8 * This differs slightly from the semantics in libc in that we never write
9 * past count, whereas libc may write to count+1. This follows the generic
10 * implementation in lib/string.c and is, IMHO, more sensible.
11 *
12 * Much of the information about 21264 scheduling/coding comes from:
13 * Compiler Writer's Guide for the Alpha 21264
14 * abbreviated as 'CWG' in other comments here
15 * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
16 * Scheduling notation:
17 * E - either cluster
18 * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
19 * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
20 * Try not to change the actual algorithm if possible for consistency.
21 */
22
23
24 .text
25
26 .align 4
27 .globl strncat
28 .ent strncat
29strncat:
30 .frame $30, 0, $26
31 .prologue 0
32
33 mov $16, $0 # set up return value
34 beq $18, $zerocount # U :
35 /* Find the end of the string. */
36 ldq_u $1, 0($16) # L : load first quadword ($16 may be misaligned)
37 lda $2, -1($31) # E :
38
39 insqh $2, $0, $2 # U :
40 andnot $16, 7, $16 # E :
41 nop # E :
42 or $2, $1, $1 # E :
43
44 nop # E :
45 nop # E :
46 cmpbge $31, $1, $2 # E : bits set iff byte == 0
47 bne $2, $found # U :
48
49$loop: ldq $1, 8($16) # L :
50 addq $16, 8, $16 # E :
51 cmpbge $31, $1, $2 # E :
52 beq $2, $loop # U :
53
54$found: cttz $2, $3 # U0 :
55 addq $16, $3, $16 # E :
56 nop # E :
57 bsr $23, __stxncpy # L0 :/* Now do the append. */
58
59 /* Worry about the null termination. */
60
61 zapnot $1, $27, $2 # U : was last byte a null?
62 cmplt $27, $24, $5 # E : did we fill the buffer completely?
63 bne $2, 0f # U :
64 ret # L0 :
65
660: or $5, $18, $2 # E :
67 nop
68 bne $2, 2f # U :
69 and $24, 0x80, $3 # E : no zero next byte
70
71 nop # E :
72 bne $3, 1f # U :
73 /* Here there are bytes left in the current word. Clear one. */
74 addq $24, $24, $24 # E : end-of-count bit <<= 1
75 nop # E :
76
772: zap $1, $24, $1 # U :
78 nop # E :
79 stq_u $1, 0($16) # L :
80 ret # L0 :
81
821: /* Here we must clear the first byte of the next DST word */
83 stb $31, 8($16) # L :
84 nop # E :
85 nop # E :
86 ret # L0 :
87
88$zerocount:
89 nop # E :
90 nop # E :
91 nop # E :
92 ret # L0 :
93
94 .end strncat
diff --git a/arch/alpha/lib/ev67-strrchr.S b/arch/alpha/lib/ev67-strrchr.S
new file mode 100644
index 000000000000..3fd8bf414c7b
--- /dev/null
+++ b/arch/alpha/lib/ev67-strrchr.S
@@ -0,0 +1,109 @@
1/*
2 * arch/alpha/lib/ev67-strrchr.S
3 * 21264 version by Rick Gorton <rick.gorton@alpha-processor.com>
4 *
5 * Finds length of a 0-terminated string. Optimized for the
6 * Alpha architecture:
7 *
8 * - memory accessed as aligned quadwords only
9 * - uses bcmpge to compare 8 bytes in parallel
10 *
11 * Much of the information about 21264 scheduling/coding comes from:
12 * Compiler Writer's Guide for the Alpha 21264
13 * abbreviated as 'CWG' in other comments here
14 * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html
15 * Scheduling notation:
16 * E - either cluster
17 * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1
18 * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1
19 */
20
21
22#include <asm/regdef.h>
23
24 .set noreorder
25 .set noat
26
27 .align 4
28 .ent strrchr
29 .globl strrchr
30strrchr:
31 .frame sp, 0, ra
32 .prologue 0
33
34 and a1, 0xff, t2 # E : 00000000000000ch
35 insbl a1, 1, t4 # U : 000000000000ch00
36 insbl a1, 2, t5 # U : 0000000000ch0000
37 ldq_u t0, 0(a0) # L : load first quadword Latency=3
38
39 mov zero, t6 # E : t6 is last match aligned addr
40 or t2, t4, a1 # E : 000000000000chch
41 sll t5, 8, t3 # U : 00000000ch000000
42 mov zero, t8 # E : t8 is last match byte compare mask
43
44 andnot a0, 7, v0 # E : align source addr
45 or t5, t3, t3 # E : 00000000chch0000
46 sll a1, 32, t2 # U : 0000chch00000000
47 sll a1, 48, t4 # U : chch000000000000
48
49 or t4, a1, a1 # E : chch00000000chch
50 or t2, t3, t2 # E : 0000chchchch0000
51 or a1, t2, a1 # E : chchchchchchchch
52 lda t5, -1 # E : build garbage mask
53
54 cmpbge zero, t0, t1 # E : bits set iff byte == zero
55 mskqh t5, a0, t4 # E : Complete garbage mask
56 xor t0, a1, t2 # E : make bytes == c zero
57 cmpbge zero, t4, t4 # E : bits set iff byte is garbage
58
59 cmpbge zero, t2, t3 # E : bits set iff byte == c
60 andnot t1, t4, t1 # E : clear garbage from null test
61 andnot t3, t4, t3 # E : clear garbage from char test
62 bne t1, $eos # U : did we already hit the terminator?
63
64 /* Character search main loop */
65$loop:
66 ldq t0, 8(v0) # L : load next quadword
67 cmovne t3, v0, t6 # E : save previous comparisons match
68 nop # : Latency=2, extra map slot (keep nop with cmov)
69 nop
70
71 cmovne t3, t3, t8 # E : Latency=2, extra map slot
72 nop # : keep with cmovne
73 addq v0, 8, v0 # E :
74 xor t0, a1, t2 # E :
75
76 cmpbge zero, t0, t1 # E : bits set iff byte == zero
77 cmpbge zero, t2, t3 # E : bits set iff byte == c
78 beq t1, $loop # U : if we havnt seen a null, loop
79 nop
80
81 /* Mask out character matches after terminator */
82$eos:
83 negq t1, t4 # E : isolate first null byte match
84 and t1, t4, t4 # E :
85 subq t4, 1, t5 # E : build a mask of the bytes upto...
86 or t4, t5, t4 # E : ... and including the null
87
88 and t3, t4, t3 # E : mask out char matches after null
89 cmovne t3, t3, t8 # E : save it, if match found Latency=2, extra map slot
90 nop # : Keep with cmovne
91 nop
92
93 cmovne t3, v0, t6 # E :
94 nop # : Keep with cmovne
95 /* Locate the address of the last matched character */
96 ctlz t8, t2 # U0 : Latency=3 (0x40 for t8=0)
97 nop
98
99 cmoveq t8, 0x3f, t2 # E : Compensate for case when no match is seen
100 nop # E : hide the cmov latency (2) behind ctlz latency
101 lda t5, 0x3f($31) # E :
102 subq t5, t2, t5 # E : Normalize leading zero count
103
104 addq t6, t5, v0 # E : and add to quadword address
105 ret # L0 : Latency=3
106 nop
107 nop
108
109 .end strrchr
diff --git a/arch/alpha/lib/fpreg.c b/arch/alpha/lib/fpreg.c
new file mode 100644
index 000000000000..97c4d9d7a4d5
--- /dev/null
+++ b/arch/alpha/lib/fpreg.c
@@ -0,0 +1,193 @@
1/*
2 * arch/alpha/lib/fpreg.c
3 *
4 * (C) Copyright 1998 Linus Torvalds
5 */
6
7#if defined(__alpha_cix__) || defined(__alpha_fix__)
8#define STT(reg,val) asm volatile ("ftoit $f"#reg",%0" : "=r"(val));
9#else
10#define STT(reg,val) asm volatile ("stt $f"#reg",%0" : "=m"(val));
11#endif
12
13unsigned long
14alpha_read_fp_reg (unsigned long reg)
15{
16 unsigned long val;
17
18 switch (reg) {
19 case 0: STT( 0, val); break;
20 case 1: STT( 1, val); break;
21 case 2: STT( 2, val); break;
22 case 3: STT( 3, val); break;
23 case 4: STT( 4, val); break;
24 case 5: STT( 5, val); break;
25 case 6: STT( 6, val); break;
26 case 7: STT( 7, val); break;
27 case 8: STT( 8, val); break;
28 case 9: STT( 9, val); break;
29 case 10: STT(10, val); break;
30 case 11: STT(11, val); break;
31 case 12: STT(12, val); break;
32 case 13: STT(13, val); break;
33 case 14: STT(14, val); break;
34 case 15: STT(15, val); break;
35 case 16: STT(16, val); break;
36 case 17: STT(17, val); break;
37 case 18: STT(18, val); break;
38 case 19: STT(19, val); break;
39 case 20: STT(20, val); break;
40 case 21: STT(21, val); break;
41 case 22: STT(22, val); break;
42 case 23: STT(23, val); break;
43 case 24: STT(24, val); break;
44 case 25: STT(25, val); break;
45 case 26: STT(26, val); break;
46 case 27: STT(27, val); break;
47 case 28: STT(28, val); break;
48 case 29: STT(29, val); break;
49 case 30: STT(30, val); break;
50 case 31: STT(31, val); break;
51 default: return 0;
52 }
53 return val;
54}
55
56#if defined(__alpha_cix__) || defined(__alpha_fix__)
57#define LDT(reg,val) asm volatile ("itoft %0,$f"#reg : : "r"(val));
58#else
59#define LDT(reg,val) asm volatile ("ldt $f"#reg",%0" : : "m"(val));
60#endif
61
62void
63alpha_write_fp_reg (unsigned long reg, unsigned long val)
64{
65 switch (reg) {
66 case 0: LDT( 0, val); break;
67 case 1: LDT( 1, val); break;
68 case 2: LDT( 2, val); break;
69 case 3: LDT( 3, val); break;
70 case 4: LDT( 4, val); break;
71 case 5: LDT( 5, val); break;
72 case 6: LDT( 6, val); break;
73 case 7: LDT( 7, val); break;
74 case 8: LDT( 8, val); break;
75 case 9: LDT( 9, val); break;
76 case 10: LDT(10, val); break;
77 case 11: LDT(11, val); break;
78 case 12: LDT(12, val); break;
79 case 13: LDT(13, val); break;
80 case 14: LDT(14, val); break;
81 case 15: LDT(15, val); break;
82 case 16: LDT(16, val); break;
83 case 17: LDT(17, val); break;
84 case 18: LDT(18, val); break;
85 case 19: LDT(19, val); break;
86 case 20: LDT(20, val); break;
87 case 21: LDT(21, val); break;
88 case 22: LDT(22, val); break;
89 case 23: LDT(23, val); break;
90 case 24: LDT(24, val); break;
91 case 25: LDT(25, val); break;
92 case 26: LDT(26, val); break;
93 case 27: LDT(27, val); break;
94 case 28: LDT(28, val); break;
95 case 29: LDT(29, val); break;
96 case 30: LDT(30, val); break;
97 case 31: LDT(31, val); break;
98 }
99}
100
101#if defined(__alpha_cix__) || defined(__alpha_fix__)
102#define STS(reg,val) asm volatile ("ftois $f"#reg",%0" : "=r"(val));
103#else
104#define STS(reg,val) asm volatile ("sts $f"#reg",%0" : "=m"(val));
105#endif
106
107unsigned long
108alpha_read_fp_reg_s (unsigned long reg)
109{
110 unsigned long val;
111
112 switch (reg) {
113 case 0: STS( 0, val); break;
114 case 1: STS( 1, val); break;
115 case 2: STS( 2, val); break;
116 case 3: STS( 3, val); break;
117 case 4: STS( 4, val); break;
118 case 5: STS( 5, val); break;
119 case 6: STS( 6, val); break;
120 case 7: STS( 7, val); break;
121 case 8: STS( 8, val); break;
122 case 9: STS( 9, val); break;
123 case 10: STS(10, val); break;
124 case 11: STS(11, val); break;
125 case 12: STS(12, val); break;
126 case 13: STS(13, val); break;
127 case 14: STS(14, val); break;
128 case 15: STS(15, val); break;
129 case 16: STS(16, val); break;
130 case 17: STS(17, val); break;
131 case 18: STS(18, val); break;
132 case 19: STS(19, val); break;
133 case 20: STS(20, val); break;
134 case 21: STS(21, val); break;
135 case 22: STS(22, val); break;
136 case 23: STS(23, val); break;
137 case 24: STS(24, val); break;
138 case 25: STS(25, val); break;
139 case 26: STS(26, val); break;
140 case 27: STS(27, val); break;
141 case 28: STS(28, val); break;
142 case 29: STS(29, val); break;
143 case 30: STS(30, val); break;
144 case 31: STS(31, val); break;
145 default: return 0;
146 }
147 return val;
148}
149
150#if defined(__alpha_cix__) || defined(__alpha_fix__)
151#define LDS(reg,val) asm volatile ("itofs %0,$f"#reg : : "r"(val));
152#else
153#define LDS(reg,val) asm volatile ("lds $f"#reg",%0" : : "m"(val));
154#endif
155
156void
157alpha_write_fp_reg_s (unsigned long reg, unsigned long val)
158{
159 switch (reg) {
160 case 0: LDS( 0, val); break;
161 case 1: LDS( 1, val); break;
162 case 2: LDS( 2, val); break;
163 case 3: LDS( 3, val); break;
164 case 4: LDS( 4, val); break;
165 case 5: LDS( 5, val); break;
166 case 6: LDS( 6, val); break;
167 case 7: LDS( 7, val); break;
168 case 8: LDS( 8, val); break;
169 case 9: LDS( 9, val); break;
170 case 10: LDS(10, val); break;
171 case 11: LDS(11, val); break;
172 case 12: LDS(12, val); break;
173 case 13: LDS(13, val); break;
174 case 14: LDS(14, val); break;
175 case 15: LDS(15, val); break;
176 case 16: LDS(16, val); break;
177 case 17: LDS(17, val); break;
178 case 18: LDS(18, val); break;
179 case 19: LDS(19, val); break;
180 case 20: LDS(20, val); break;
181 case 21: LDS(21, val); break;
182 case 22: LDS(22, val); break;
183 case 23: LDS(23, val); break;
184 case 24: LDS(24, val); break;
185 case 25: LDS(25, val); break;
186 case 26: LDS(26, val); break;
187 case 27: LDS(27, val); break;
188 case 28: LDS(28, val); break;
189 case 29: LDS(29, val); break;
190 case 30: LDS(30, val); break;
191 case 31: LDS(31, val); break;
192 }
193}
diff --git a/arch/alpha/lib/memchr.S b/arch/alpha/lib/memchr.S
new file mode 100644
index 000000000000..14427eeb555e
--- /dev/null
+++ b/arch/alpha/lib/memchr.S
@@ -0,0 +1,164 @@
1/* Copyright (C) 1996 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by David Mosberger (davidm@cs.arizona.edu).
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
19
20/* Finds characters in a memory area. Optimized for the Alpha:
21
22 - memory accessed as aligned quadwords only
23 - uses cmpbge to compare 8 bytes in parallel
24 - does binary search to find 0 byte in last
25 quadword (HAKMEM needed 12 instructions to
26 do this instead of the 9 instructions that
27 binary search needs).
28
29For correctness consider that:
30
31 - only minimum number of quadwords may be accessed
32 - the third argument is an unsigned long
33*/
34
35 .set noreorder
36 .set noat
37
38 .globl memchr
39 .ent memchr
40memchr:
41 .frame $30,0,$26,0
42 .prologue 0
43
44 # Hack -- if someone passes in (size_t)-1, hoping to just
45 # search til the end of the address space, we will overflow
46 # below when we find the address of the last byte. Given
47 # that we will never have a 56-bit address space, cropping
48 # the length is the easiest way to avoid trouble.
49 zap $18, 0x80, $5 #-e0 :
50
51 beq $18, $not_found # .. e1 :
52 ldq_u $1, 0($16) # e1 : load first quadword
53 insbl $17, 1, $2 # .. e0 : $2 = 000000000000ch00
54 and $17, 0xff, $17 #-e0 : $17 = 00000000000000ch
55 cmpult $18, 9, $4 # .. e1 :
56 or $2, $17, $17 # e0 : $17 = 000000000000chch
57 lda $3, -1($31) # .. e1 :
58 sll $17, 16, $2 #-e0 : $2 = 00000000chch0000
59 addq $16, $5, $5 # .. e1 :
60 or $2, $17, $17 # e1 : $17 = 00000000chchchch
61 unop # :
62 sll $17, 32, $2 #-e0 : $2 = chchchch00000000
63 or $2, $17, $17 # e1 : $17 = chchchchchchchch
64 extql $1, $16, $7 # e0 :
65 beq $4, $first_quad # .. e1 :
66
67 ldq_u $6, -1($5) #-e1 : eight or less bytes to search
68 extqh $6, $16, $6 # .. e0 :
69 mov $16, $0 # e0 :
70 or $7, $6, $1 # .. e1 : $1 = quadword starting at $16
71
72 # Deal with the case where at most 8 bytes remain to be searched
73 # in $1. E.g.:
74 # $18 = 6
75 # $1 = ????c6c5c4c3c2c1
76$last_quad:
77 negq $18, $6 #-e0 :
78 xor $17, $1, $1 # .. e1 :
79 srl $3, $6, $6 # e0 : $6 = mask of $18 bits set
80 cmpbge $31, $1, $2 # .. e1 :
81 and $2, $6, $2 #-e0 :
82 beq $2, $not_found # .. e1 :
83
84$found_it:
85 # Now, determine which byte matched:
86 negq $2, $3 # e0 :
87 and $2, $3, $2 # e1 :
88
89 and $2, 0x0f, $1 #-e0 :
90 addq $0, 4, $3 # .. e1 :
91 cmoveq $1, $3, $0 # e0 :
92
93 addq $0, 2, $3 # .. e1 :
94 and $2, 0x33, $1 #-e0 :
95 cmoveq $1, $3, $0 # .. e1 :
96
97 and $2, 0x55, $1 # e0 :
98 addq $0, 1, $3 # .. e1 :
99 cmoveq $1, $3, $0 #-e0 :
100
101$done: ret # .. e1 :
102
103 # Deal with the case where $18 > 8 bytes remain to be
104 # searched. $16 may not be aligned.
105 .align 4
106$first_quad:
107 andnot $16, 0x7, $0 #-e1 :
108 insqh $3, $16, $2 # .. e0 : $2 = 0000ffffffffffff ($16<0:2> ff)
109 xor $1, $17, $1 # e0 :
110 or $1, $2, $1 # e1 : $1 = ====ffffffffffff
111 cmpbge $31, $1, $2 #-e0 :
112 bne $2, $found_it # .. e1 :
113
114 # At least one byte left to process.
115
116 ldq $1, 8($0) # e0 :
117 subq $5, 1, $18 # .. e1 :
118 addq $0, 8, $0 #-e0 :
119
120 # Make $18 point to last quad to be accessed (the
121 # last quad may or may not be partial).
122
123 andnot $18, 0x7, $18 # .. e1 :
124 cmpult $0, $18, $2 # e0 :
125 beq $2, $final # .. e1 :
126
127 # At least two quads remain to be accessed.
128
129 subq $18, $0, $4 #-e0 : $4 <- nr quads to be processed
130 and $4, 8, $4 # e1 : odd number of quads?
131 bne $4, $odd_quad_count # e1 :
132
133 # At least three quads remain to be accessed
134
135 mov $1, $4 # e0 : move prefetched value to correct reg
136
137 .align 4
138$unrolled_loop:
139 ldq $1, 8($0) #-e0 : prefetch $1
140 xor $17, $4, $2 # .. e1 :
141 cmpbge $31, $2, $2 # e0 :
142 bne $2, $found_it # .. e1 :
143
144 addq $0, 8, $0 #-e0 :
145$odd_quad_count:
146 xor $17, $1, $2 # .. e1 :
147 ldq $4, 8($0) # e0 : prefetch $4
148 cmpbge $31, $2, $2 # .. e1 :
149 addq $0, 8, $6 #-e0 :
150 bne $2, $found_it # .. e1 :
151
152 cmpult $6, $18, $6 # e0 :
153 addq $0, 8, $0 # .. e1 :
154 bne $6, $unrolled_loop #-e1 :
155
156 mov $4, $1 # e0 : move prefetched value into $1
157$final: subq $5, $0, $18 # .. e1 : $18 <- number of bytes left to do
158 bne $18, $last_quad # e1 :
159
160$not_found:
161 mov $31, $0 #-e0 :
162 ret # .. e1 :
163
164 .end memchr
diff --git a/arch/alpha/lib/memcpy.c b/arch/alpha/lib/memcpy.c
new file mode 100644
index 000000000000..64083fc73238
--- /dev/null
+++ b/arch/alpha/lib/memcpy.c
@@ -0,0 +1,163 @@
1/*
2 * linux/arch/alpha/lib/memcpy.c
3 *
4 * Copyright (C) 1995 Linus Torvalds
5 */
6
7/*
8 * This is a reasonably optimized memcpy() routine.
9 */
10
11/*
12 * Note that the C code is written to be optimized into good assembly. However,
13 * at this point gcc is unable to sanely compile "if (n >= 0)", resulting in a
14 * explicit compare against 0 (instead of just using the proper "blt reg, xx" or
15 * "bge reg, xx"). I hope alpha-gcc will be fixed to notice this eventually..
16 */
17
18#include <linux/types.h>
19
20/*
21 * This should be done in one go with ldq_u*2/mask/stq_u. Do it
22 * with a macro so that we can fix it up later..
23 */
24#define ALIGN_DEST_TO8_UP(d,s,n) \
25 while (d & 7) { \
26 if (n <= 0) return; \
27 n--; \
28 *(char *) d = *(char *) s; \
29 d++; s++; \
30 }
31#define ALIGN_DEST_TO8_DN(d,s,n) \
32 while (d & 7) { \
33 if (n <= 0) return; \
34 n--; \
35 d--; s--; \
36 *(char *) d = *(char *) s; \
37 }
38
39/*
40 * This should similarly be done with ldq_u*2/mask/stq. The destination
41 * is aligned, but we don't fill in a full quad-word
42 */
43#define DO_REST_UP(d,s,n) \
44 while (n > 0) { \
45 n--; \
46 *(char *) d = *(char *) s; \
47 d++; s++; \
48 }
49#define DO_REST_DN(d,s,n) \
50 while (n > 0) { \
51 n--; \
52 d--; s--; \
53 *(char *) d = *(char *) s; \
54 }
55
56/*
57 * This should be done with ldq/mask/stq. The source and destination are
58 * aligned, but we don't fill in a full quad-word
59 */
60#define DO_REST_ALIGNED_UP(d,s,n) DO_REST_UP(d,s,n)
61#define DO_REST_ALIGNED_DN(d,s,n) DO_REST_DN(d,s,n)
62
63/*
64 * This does unaligned memory copies. We want to avoid storing to
65 * an unaligned address, as that would do a read-modify-write cycle.
66 * We also want to avoid double-reading the unaligned reads.
67 *
68 * Note the ordering to try to avoid load (and address generation) latencies.
69 */
70static inline void __memcpy_unaligned_up (unsigned long d, unsigned long s,
71 long n)
72{
73 ALIGN_DEST_TO8_UP(d,s,n);
74 n -= 8; /* to avoid compare against 8 in the loop */
75 if (n >= 0) {
76 unsigned long low_word, high_word;
77 __asm__("ldq_u %0,%1":"=r" (low_word):"m" (*(unsigned long *) s));
78 do {
79 unsigned long tmp;
80 __asm__("ldq_u %0,%1":"=r" (high_word):"m" (*(unsigned long *)(s+8)));
81 n -= 8;
82 __asm__("extql %1,%2,%0"
83 :"=r" (low_word)
84 :"r" (low_word), "r" (s));
85 __asm__("extqh %1,%2,%0"
86 :"=r" (tmp)
87 :"r" (high_word), "r" (s));
88 s += 8;
89 *(unsigned long *) d = low_word | tmp;
90 d += 8;
91 low_word = high_word;
92 } while (n >= 0);
93 }
94 n += 8;
95 DO_REST_UP(d,s,n);
96}
97
98static inline void __memcpy_unaligned_dn (unsigned long d, unsigned long s,
99 long n)
100{
101 /* I don't understand AXP assembler well enough for this. -Tim */
102 s += n;
103 d += n;
104 while (n--)
105 * (char *) --d = * (char *) --s;
106}
107
108/*
109 * Hmm.. Strange. The __asm__ here is there to make gcc use an integer register
110 * for the load-store. I don't know why, but it would seem that using a floating
111 * point register for the move seems to slow things down (very small difference,
112 * though).
113 *
114 * Note the ordering to try to avoid load (and address generation) latencies.
115 */
116static inline void __memcpy_aligned_up (unsigned long d, unsigned long s,
117 long n)
118{
119 ALIGN_DEST_TO8_UP(d,s,n);
120 n -= 8;
121 while (n >= 0) {
122 unsigned long tmp;
123 __asm__("ldq %0,%1":"=r" (tmp):"m" (*(unsigned long *) s));
124 n -= 8;
125 s += 8;
126 *(unsigned long *) d = tmp;
127 d += 8;
128 }
129 n += 8;
130 DO_REST_ALIGNED_UP(d,s,n);
131}
132static inline void __memcpy_aligned_dn (unsigned long d, unsigned long s,
133 long n)
134{
135 s += n;
136 d += n;
137 ALIGN_DEST_TO8_DN(d,s,n);
138 n -= 8;
139 while (n >= 0) {
140 unsigned long tmp;
141 s -= 8;
142 __asm__("ldq %0,%1":"=r" (tmp):"m" (*(unsigned long *) s));
143 n -= 8;
144 d -= 8;
145 *(unsigned long *) d = tmp;
146 }
147 n += 8;
148 DO_REST_ALIGNED_DN(d,s,n);
149}
150
151void * memcpy(void * dest, const void *src, size_t n)
152{
153 if (!(((unsigned long) dest ^ (unsigned long) src) & 7)) {
154 __memcpy_aligned_up ((unsigned long) dest, (unsigned long) src,
155 n);
156 return dest;
157 }
158 __memcpy_unaligned_up ((unsigned long) dest, (unsigned long) src, n);
159 return dest;
160}
161
162/* For backward modules compatibility, define __memcpy. */
163asm("__memcpy = memcpy; .globl __memcpy");
diff --git a/arch/alpha/lib/memmove.S b/arch/alpha/lib/memmove.S
new file mode 100644
index 000000000000..eb3b6e02242f
--- /dev/null
+++ b/arch/alpha/lib/memmove.S
@@ -0,0 +1,181 @@
1/*
2 * arch/alpha/lib/memmove.S
3 *
4 * Barely optimized memmove routine for Alpha EV5.
5 *
6 * This is hand-massaged output from the original memcpy.c. We defer to
7 * memcpy whenever possible; the backwards copy loops are not unrolled.
8 */
9
10 .set noat
11 .set noreorder
12 .text
13
14 .align 4
15 .globl memmove
16 .ent memmove
17memmove:
18 ldgp $29, 0($27)
19 unop
20 nop
21 .prologue 1
22
23 addq $16,$18,$4
24 addq $17,$18,$5
25 cmpule $4,$17,$1 /* dest + n <= src */
26 cmpule $5,$16,$2 /* dest >= src + n */
27
28 bis $1,$2,$1
29 mov $16,$0
30 xor $16,$17,$2
31 bne $1,memcpy !samegp
32
33 and $2,7,$2 /* Test for src/dest co-alignment. */
34 and $16,7,$1
35 cmpule $16,$17,$3
36 bne $3,$memmove_up /* dest < src */
37
38 and $4,7,$1
39 bne $2,$misaligned_dn
40 unop
41 beq $1,$skip_aligned_byte_loop_head_dn
42
43$aligned_byte_loop_head_dn:
44 lda $4,-1($4)
45 lda $5,-1($5)
46 unop
47 ble $18,$egress
48
49 ldq_u $3,0($5)
50 ldq_u $2,0($4)
51 lda $18,-1($18)
52 extbl $3,$5,$1
53
54 insbl $1,$4,$1
55 mskbl $2,$4,$2
56 bis $1,$2,$1
57 and $4,7,$6
58
59 stq_u $1,0($4)
60 bne $6,$aligned_byte_loop_head_dn
61
62$skip_aligned_byte_loop_head_dn:
63 lda $18,-8($18)
64 blt $18,$skip_aligned_word_loop_dn
65
66$aligned_word_loop_dn:
67 ldq $1,-8($5)
68 nop
69 lda $5,-8($5)
70 lda $18,-8($18)
71
72 stq $1,-8($4)
73 nop
74 lda $4,-8($4)
75 bge $18,$aligned_word_loop_dn
76
77$skip_aligned_word_loop_dn:
78 lda $18,8($18)
79 bgt $18,$byte_loop_tail_dn
80 unop
81 ret $31,($26),1
82
83 .align 4
84$misaligned_dn:
85 nop
86 fnop
87 unop
88 beq $18,$egress
89
90$byte_loop_tail_dn:
91 ldq_u $3,-1($5)
92 ldq_u $2,-1($4)
93 lda $5,-1($5)
94 lda $4,-1($4)
95
96 lda $18,-1($18)
97 extbl $3,$5,$1
98 insbl $1,$4,$1
99 mskbl $2,$4,$2
100
101 bis $1,$2,$1
102 stq_u $1,0($4)
103 bgt $18,$byte_loop_tail_dn
104 br $egress
105
106$memmove_up:
107 mov $16,$4
108 mov $17,$5
109 bne $2,$misaligned_up
110 beq $1,$skip_aligned_byte_loop_head_up
111
112$aligned_byte_loop_head_up:
113 unop
114 ble $18,$egress
115 ldq_u $3,0($5)
116 ldq_u $2,0($4)
117
118 lda $18,-1($18)
119 extbl $3,$5,$1
120 insbl $1,$4,$1
121 mskbl $2,$4,$2
122
123 bis $1,$2,$1
124 lda $5,1($5)
125 stq_u $1,0($4)
126 lda $4,1($4)
127
128 and $4,7,$6
129 bne $6,$aligned_byte_loop_head_up
130
131$skip_aligned_byte_loop_head_up:
132 lda $18,-8($18)
133 blt $18,$skip_aligned_word_loop_up
134
135$aligned_word_loop_up:
136 ldq $1,0($5)
137 nop
138 lda $5,8($5)
139 lda $18,-8($18)
140
141 stq $1,0($4)
142 nop
143 lda $4,8($4)
144 bge $18,$aligned_word_loop_up
145
146$skip_aligned_word_loop_up:
147 lda $18,8($18)
148 bgt $18,$byte_loop_tail_up
149 unop
150 ret $31,($26),1
151
152 .align 4
153$misaligned_up:
154 nop
155 fnop
156 unop
157 beq $18,$egress
158
159$byte_loop_tail_up:
160 ldq_u $3,0($5)
161 ldq_u $2,0($4)
162 lda $18,-1($18)
163 extbl $3,$5,$1
164
165 insbl $1,$4,$1
166 mskbl $2,$4,$2
167 bis $1,$2,$1
168 stq_u $1,0($4)
169
170 lda $5,1($5)
171 lda $4,1($4)
172 nop
173 bgt $18,$byte_loop_tail_up
174
175$egress:
176 ret $31,($26),1
177 nop
178 nop
179 nop
180
181 .end memmove
diff --git a/arch/alpha/lib/memset.S b/arch/alpha/lib/memset.S
new file mode 100644
index 000000000000..8ff6e7e1773e
--- /dev/null
+++ b/arch/alpha/lib/memset.S
@@ -0,0 +1,124 @@
1/*
2 * linux/arch/alpha/memset.S
3 *
4 * This is an efficient (and small) implementation of the C library "memset()"
5 * function for the alpha.
6 *
7 * (C) Copyright 1996 Linus Torvalds
8 *
9 * This routine is "moral-ware": you are free to use it any way you wish, and
10 * the only obligation I put on you is a moral one: if you make any improvements
11 * to the routine, please send me your improvements for me to use similarly.
12 *
13 * The scheduling comments are according to the EV5 documentation (and done by
14 * hand, so they might well be incorrect, please do tell me about it..)
15 */
16
17 .set noat
18 .set noreorder
19.text
20 .globl memset
21 .globl __memset
22 .globl __memsetw
23 .globl __constant_c_memset
24 .ent __memset
25.align 5
26__memset:
27 .frame $30,0,$26,0
28 .prologue 0
29
30 and $17,255,$1 /* E1 */
31 insbl $17,1,$17 /* .. E0 */
32 bis $17,$1,$17 /* E0 (p-c latency, next cycle) */
33 sll $17,16,$1 /* E1 (p-c latency, next cycle) */
34
35 bis $17,$1,$17 /* E0 (p-c latency, next cycle) */
36 sll $17,32,$1 /* E1 (p-c latency, next cycle) */
37 bis $17,$1,$17 /* E0 (p-c latency, next cycle) */
38 ldq_u $31,0($30) /* .. E1 */
39
40.align 5
41__constant_c_memset:
42 addq $18,$16,$6 /* E0 */
43 bis $16,$16,$0 /* .. E1 */
44 xor $16,$6,$1 /* E0 */
45 ble $18,end /* .. E1 */
46
47 bic $1,7,$1 /* E0 */
48 beq $1,within_one_quad /* .. E1 (note EV5 zero-latency forwarding) */
49 and $16,7,$3 /* E0 */
50 beq $3,aligned /* .. E1 (note EV5 zero-latency forwarding) */
51
52 ldq_u $4,0($16) /* E0 */
53 bis $16,$16,$5 /* .. E1 */
54 insql $17,$16,$2 /* E0 */
55 subq $3,8,$3 /* .. E1 */
56
57 addq $18,$3,$18 /* E0 $18 is new count ($3 is negative) */
58 mskql $4,$16,$4 /* .. E1 (and possible load stall) */
59 subq $16,$3,$16 /* E0 $16 is new aligned destination */
60 bis $2,$4,$1 /* .. E1 */
61
62 bis $31,$31,$31 /* E0 */
63 ldq_u $31,0($30) /* .. E1 */
64 stq_u $1,0($5) /* E0 */
65 bis $31,$31,$31 /* .. E1 */
66
67.align 4
68aligned:
69 sra $18,3,$3 /* E0 */
70 and $18,7,$18 /* .. E1 */
71 bis $16,$16,$5 /* E0 */
72 beq $3,no_quad /* .. E1 */
73
74.align 3
75loop:
76 stq $17,0($5) /* E0 */
77 subq $3,1,$3 /* .. E1 */
78 addq $5,8,$5 /* E0 */
79 bne $3,loop /* .. E1 */
80
81no_quad:
82 bis $31,$31,$31 /* E0 */
83 beq $18,end /* .. E1 */
84 ldq $7,0($5) /* E0 */
85 mskqh $7,$6,$2 /* .. E1 (and load stall) */
86
87 insqh $17,$6,$4 /* E0 */
88 bis $2,$4,$1 /* .. E1 */
89 stq $1,0($5) /* E0 */
90 ret $31,($26),1 /* .. E1 */
91
92.align 3
93within_one_quad:
94 ldq_u $1,0($16) /* E0 */
95 insql $17,$16,$2 /* E1 */
96 mskql $1,$16,$4 /* E0 (after load stall) */
97 bis $2,$4,$2 /* E0 */
98
99 mskql $2,$6,$4 /* E0 */
100 mskqh $1,$6,$2 /* .. E1 */
101 bis $2,$4,$1 /* E0 */
102 stq_u $1,0($16) /* E0 */
103
104end:
105 ret $31,($26),1 /* E1 */
106 .end __memset
107
108 .align 5
109 .ent __memsetw
110__memsetw:
111 .prologue 0
112
113 inswl $17,0,$1 /* E0 */
114 inswl $17,2,$2 /* E0 */
115 inswl $17,4,$3 /* E0 */
116 or $1,$2,$1 /* .. E1 */
117 inswl $17,6,$4 /* E0 */
118 or $1,$3,$1 /* .. E1 */
119 or $1,$4,$17 /* E0 */
120 br __constant_c_memset /* .. E1 */
121
122 .end __memsetw
123
124memset = __memset
diff --git a/arch/alpha/lib/srm_printk.c b/arch/alpha/lib/srm_printk.c
new file mode 100644
index 000000000000..31b53c49435e
--- /dev/null
+++ b/arch/alpha/lib/srm_printk.c
@@ -0,0 +1,41 @@
1/*
2 * arch/alpha/lib/srm_printk.c
3 */
4
5#include <linux/kernel.h>
6#include <asm/console.h>
7
8long
9srm_printk(const char *fmt, ...)
10{
11 static char buf[1024];
12 va_list args;
13 long len, num_lf;
14 char *src, *dst;
15
16 va_start(args, fmt);
17 len = vsprintf(buf, fmt, args);
18 va_end(args);
19
20 /* count number of linefeeds in string: */
21
22 num_lf = 0;
23 for (src = buf; *src; ++src) {
24 if (*src == '\n') {
25 ++num_lf;
26 }
27 }
28
29 if (num_lf) {
30 /* expand each linefeed into carriage-return/linefeed: */
31 for (dst = src + num_lf; src >= buf; ) {
32 if (*src == '\n') {
33 *dst-- = '\r';
34 }
35 *dst-- = *src--;
36 }
37 }
38
39 srm_puts(buf, num_lf+len);
40 return len;
41}
diff --git a/arch/alpha/lib/srm_puts.c b/arch/alpha/lib/srm_puts.c
new file mode 100644
index 000000000000..7b60a6f75a78
--- /dev/null
+++ b/arch/alpha/lib/srm_puts.c
@@ -0,0 +1,23 @@
1/*
2 * arch/alpha/lib/srm_puts.c
3 */
4
5#include <linux/string.h>
6#include <asm/console.h>
7
8long
9srm_puts(const char *str, long len)
10{
11 long remaining, written;
12
13 if (!callback_init_done)
14 return len;
15
16 for (remaining = len; remaining > 0; remaining -= written)
17 {
18 written = callback_puts(0, str, remaining);
19 written &= 0xffffffff;
20 str += written;
21 }
22 return len;
23}
diff --git a/arch/alpha/lib/stacktrace.c b/arch/alpha/lib/stacktrace.c
new file mode 100644
index 000000000000..6d432e42aedc
--- /dev/null
+++ b/arch/alpha/lib/stacktrace.c
@@ -0,0 +1,103 @@
1#include <linux/kernel.h>
2#include <asm/system.h>
3
4typedef unsigned int instr;
5
6#define MAJOR_OP 0xfc000000
7#define LDA_OP 0x20000000
8#define STQ_OP 0xb4000000
9#define BR_OP 0xc0000000
10
11#define STK_ALLOC_1 0x23de8000 /* lda $30,-X($30) */
12#define STK_ALLOC_1M 0xffff8000
13#define STK_ALLOC_2 0x43c0153e /* subq $30,X,$30 */
14#define STK_ALLOC_2M 0xffe01fff
15
16#define MEM_REG 0x03e00000
17#define MEM_BASE 0x001f0000
18#define MEM_OFF 0x0000ffff
19#define MEM_OFF_SIGN 0x00008000
20#define BASE_SP 0x001e0000
21
22#define STK_ALLOC_MATCH(INSTR) \
23 (((INSTR) & STK_ALLOC_1M) == STK_ALLOC_1 \
24 || ((INSTR) & STK_ALLOC_2M) == STK_ALLOC_2)
25#define STK_PUSH_MATCH(INSTR) \
26 (((INSTR) & (MAJOR_OP | MEM_BASE | MEM_OFF_SIGN)) == (STQ_OP | BASE_SP))
27#define MEM_OP_OFFSET(INSTR) \
28 (((long)((INSTR) & MEM_OFF) << 48) >> 48)
29#define MEM_OP_REG(INSTR) \
30 (((INSTR) & MEM_REG) >> 22)
31
32/* Branches, jumps, PAL calls, and illegal opcodes end a basic block. */
33#define BB_END(INSTR) \
34 (((instr)(INSTR) >= BR_OP) | ((instr)(INSTR) < LDA_OP) | \
35 ((((instr)(INSTR) ^ 0x60000000) < 0x20000000) & \
36 (((instr)(INSTR) & 0x0c000000) != 0)))
37
38#define IS_KERNEL_TEXT(PC) ((unsigned long)(PC) > START_ADDR)
39
40static char reg_name[][4] = {
41 "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ", "t7 ",
42 "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "s6 ", "a0 ", "a1 ",
43 "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ", "t10", "t11", "ra ",
44 "pv ", "at ", "gp ", "sp ", "0"
45};
46
47
48static instr *
49display_stored_regs(instr * pro_pc, unsigned char * sp)
50{
51 instr * ret_pc = 0;
52 int reg;
53 unsigned long value;
54
55 printk("Prologue [<%p>], Frame %p:\n", pro_pc, sp);
56 while (!BB_END(*pro_pc))
57 if (STK_PUSH_MATCH(*pro_pc)) {
58 reg = (*pro_pc & MEM_REG) >> 21;
59 value = *(unsigned long *)(sp + (*pro_pc & MEM_OFF));
60 if (reg == 26)
61 ret_pc = (instr *)value;
62 printk("\t\t%s / 0x%016lx\n", reg_name[reg], value);
63 }
64 return ret_pc;
65}
66
67static instr *
68seek_prologue(instr * pc)
69{
70 while (!STK_ALLOC_MATCH(*pc))
71 --pc;
72 while (!BB_END(*(pc - 1)))
73 --pc;
74 return pc;
75}
76
77static long
78stack_increment(instr * prologue_pc)
79{
80 while (!STK_ALLOC_MATCH(*prologue_pc))
81 ++prologue_pc;
82
83 /* Count the bytes allocated. */
84 if ((*prologue_pc & STK_ALLOC_1M) == STK_ALLOC_1M)
85 return -(((long)(*prologue_pc) << 48) >> 48);
86 else
87 return (*prologue_pc >> 13) & 0xff;
88}
89
90void
91stacktrace(void)
92{
93 instr * ret_pc;
94 instr * prologue = (instr *)stacktrace;
95 register unsigned char * sp __asm__ ("$30");
96
97 printk("\tstack trace:\n");
98 do {
99 ret_pc = display_stored_regs(prologue, sp);
100 sp += stack_increment(prologue);
101 prologue = seek_prologue(ret_pc);
102 } while (IS_KERNEL_TEXT(ret_pc));
103}
diff --git a/arch/alpha/lib/strcasecmp.c b/arch/alpha/lib/strcasecmp.c
new file mode 100644
index 000000000000..4e57a216feaf
--- /dev/null
+++ b/arch/alpha/lib/strcasecmp.c
@@ -0,0 +1,26 @@
1/*
2 * linux/arch/alpha/lib/strcasecmp.c
3 */
4
5#include <linux/string.h>
6
7
8/* We handle nothing here except the C locale. Since this is used in
9 only one place, on strings known to contain only 7 bit ASCII, this
10 is ok. */
11
12int strcasecmp(const char *a, const char *b)
13{
14 int ca, cb;
15
16 do {
17 ca = *a++ & 0xff;
18 cb = *b++ & 0xff;
19 if (ca >= 'A' && ca <= 'Z')
20 ca += 'a' - 'A';
21 if (cb >= 'A' && cb <= 'Z')
22 cb += 'a' - 'A';
23 } while (ca == cb && ca != '\0');
24
25 return ca - cb;
26}
diff --git a/arch/alpha/lib/strcat.S b/arch/alpha/lib/strcat.S
new file mode 100644
index 000000000000..393f50384878
--- /dev/null
+++ b/arch/alpha/lib/strcat.S
@@ -0,0 +1,52 @@
1/*
2 * arch/alpha/lib/strcat.S
3 * Contributed by Richard Henderson (rth@tamu.edu)
4 *
5 * Append a null-terminated string from SRC to DST.
6 */
7
8 .text
9
10 .align 3
11 .globl strcat
12 .ent strcat
13strcat:
14 .frame $30, 0, $26
15 .prologue 0
16
17 mov $16, $0 # set up return value
18
19 /* Find the end of the string. */
20
21 ldq_u $1, 0($16) # load first quadword (a0 may be misaligned)
22 lda $2, -1
23 insqh $2, $16, $2
24 andnot $16, 7, $16
25 or $2, $1, $1
26 cmpbge $31, $1, $2 # bits set iff byte == 0
27 bne $2, $found
28
29$loop: ldq $1, 8($16)
30 addq $16, 8, $16
31 cmpbge $31, $1, $2
32 beq $2, $loop
33
34$found: negq $2, $3 # clear all but least set bit
35 and $2, $3, $2
36
37 and $2, 0xf0, $3 # binary search for that set bit
38 and $2, 0xcc, $4
39 and $2, 0xaa, $5
40 cmovne $3, 4, $3
41 cmovne $4, 2, $4
42 cmovne $5, 1, $5
43 addq $3, $4, $3
44 addq $16, $5, $16
45 addq $16, $3, $16
46
47 /* Now do the append. */
48
49 mov $26, $23
50 br __stxcpy
51
52 .end strcat
diff --git a/arch/alpha/lib/strchr.S b/arch/alpha/lib/strchr.S
new file mode 100644
index 000000000000..011a175e8329
--- /dev/null
+++ b/arch/alpha/lib/strchr.S
@@ -0,0 +1,70 @@
1/*
2 * arch/alpha/lib/strchr.S
3 * Contributed by Richard Henderson (rth@tamu.edu)
4 *
5 * Return the address of a given character within a null-terminated
6 * string, or null if it is not found.
7 */
8
9#include <asm/regdef.h>
10
11 .set noreorder
12 .set noat
13
14 .align 3
15 .globl strchr
16 .ent strchr
17strchr:
18 .frame sp, 0, ra
19 .prologue 0
20
21 zapnot a1, 1, a1 # e0 : zero extend the search character
22 ldq_u t0, 0(a0) # .. e1 : load first quadword
23 sll a1, 8, t5 # e0 : replicate the search character
24 andnot a0, 7, v0 # .. e1 : align our loop pointer
25 or t5, a1, a1 # e0 :
26 lda t4, -1 # .. e1 : build garbage mask
27 sll a1, 16, t5 # e0 :
28 cmpbge zero, t0, t2 # .. e1 : bits set iff byte == zero
29 mskqh t4, a0, t4 # e0 :
30 or t5, a1, a1 # .. e1 :
31 sll a1, 32, t5 # e0 :
32 cmpbge zero, t4, t4 # .. e1 : bits set iff byte is garbage
33 or t5, a1, a1 # e0 :
34 xor t0, a1, t1 # .. e1 : make bytes == c zero
35 cmpbge zero, t1, t3 # e0 : bits set iff byte == c
36 or t2, t3, t0 # e1 : bits set iff char match or zero match
37 andnot t0, t4, t0 # e0 : clear garbage bits
38 bne t0, $found # .. e1 (zdb)
39
40$loop: ldq t0, 8(v0) # e0 :
41 addq v0, 8, v0 # .. e1 :
42 nop # e0 :
43 xor t0, a1, t1 # .. e1 (ev5 data stall)
44 cmpbge zero, t0, t2 # e0 : bits set iff byte == 0
45 cmpbge zero, t1, t3 # .. e1 : bits set iff byte == c
46 or t2, t3, t0 # e0 :
47 beq t0, $loop # .. e1 (zdb)
48
49$found: negq t0, t1 # e0 : clear all but least set bit
50 and t0, t1, t0 # e1 (stall)
51
52 and t0, t3, t1 # e0 : bit set iff byte was the char
53 beq t1, $retnull # .. e1 (zdb)
54
55 and t0, 0xf0, t2 # e0 : binary search for that set bit
56 and t0, 0xcc, t3 # .. e1 :
57 and t0, 0xaa, t4 # e0 :
58 cmovne t2, 4, t2 # .. e1 :
59 cmovne t3, 2, t3 # e0 :
60 cmovne t4, 1, t4 # .. e1 :
61 addq t2, t3, t2 # e0 :
62 addq v0, t4, v0 # .. e1 :
63 addq v0, t2, v0 # e0 :
64 ret # .. e1 :
65
66$retnull:
67 mov zero, v0 # e0 :
68 ret # .. e1 :
69
70 .end strchr
diff --git a/arch/alpha/lib/strcpy.S b/arch/alpha/lib/strcpy.S
new file mode 100644
index 000000000000..e0728e4ad21f
--- /dev/null
+++ b/arch/alpha/lib/strcpy.S
@@ -0,0 +1,23 @@
1/*
2 * arch/alpha/lib/strcpy.S
3 * Contributed by Richard Henderson (rth@tamu.edu)
4 *
5 * Copy a null-terminated string from SRC to DST. Return a pointer
6 * to the null-terminator in the source.
7 */
8
9 .text
10
11 .align 3
12 .globl strcpy
13 .ent strcpy
14strcpy:
15 .frame $30, 0, $26
16 .prologue 0
17
18 mov $16, $0 # set up return value
19 mov $26, $23 # set up return address
20 unop
21 br __stxcpy # do the copy
22
23 .end strcpy
diff --git a/arch/alpha/lib/strlen.S b/arch/alpha/lib/strlen.S
new file mode 100644
index 000000000000..fe63353de152
--- /dev/null
+++ b/arch/alpha/lib/strlen.S
@@ -0,0 +1,57 @@
1/*
2 * strlen.S (c) 1995 David Mosberger (davidm@cs.arizona.edu)
3 *
4 * Finds length of a 0-terminated string. Optimized for the
5 * Alpha architecture:
6 *
7 * - memory accessed as aligned quadwords only
8 * - uses bcmpge to compare 8 bytes in parallel
9 * - does binary search to find 0 byte in last
10 * quadword (HAKMEM needed 12 instructions to
11 * do this instead of the 9 instructions that
12 * binary search needs).
13 */
14
15 .set noreorder
16 .set noat
17
18 .align 3
19
20 .globl strlen
21 .ent strlen
22
23strlen:
24 ldq_u $1, 0($16) # load first quadword ($16 may be misaligned)
25 lda $2, -1($31)
26 insqh $2, $16, $2
27 andnot $16, 7, $0
28 or $2, $1, $1
29 cmpbge $31, $1, $2 # $2 <- bitmask: bit i == 1 <==> i-th byte == 0
30 bne $2, found
31
32loop: ldq $1, 8($0)
33 addq $0, 8, $0 # addr += 8
34 nop # helps dual issue last two insns
35 cmpbge $31, $1, $2
36 beq $2, loop
37
38found: blbs $2, done # make aligned case fast
39 negq $2, $3
40 and $2, $3, $2
41
42 and $2, 0x0f, $1
43 addq $0, 4, $3
44 cmoveq $1, $3, $0
45
46 and $2, 0x33, $1
47 addq $0, 2, $3
48 cmoveq $1, $3, $0
49
50 and $2, 0x55, $1
51 addq $0, 1, $3
52 cmoveq $1, $3, $0
53
54done: subq $0, $16, $0
55 ret $31, ($26)
56
57 .end strlen
diff --git a/arch/alpha/lib/strlen_user.S b/arch/alpha/lib/strlen_user.S
new file mode 100644
index 000000000000..508a18e96479
--- /dev/null
+++ b/arch/alpha/lib/strlen_user.S
@@ -0,0 +1,91 @@
1/*
2 * arch/alpha/lib/strlen_user.S
3 *
4 * Return the length of the string including the NUL terminator
5 * (strlen+1) or zero if an error occurred.
6 *
7 * In places where it is critical to limit the processing time,
8 * and the data is not trusted, strnlen_user() should be used.
9 * It will return a value greater than its second argument if
10 * that limit would be exceeded. This implementation is allowed
11 * to access memory beyond the limit, but will not cross a page
12 * boundary when doing so.
13 */
14
15#include <asm/regdef.h>
16
17
18/* Allow an exception for an insn; exit if we get one. */
19#define EX(x,y...) \
20 99: x,##y; \
21 .section __ex_table,"a"; \
22 .long 99b - .; \
23 lda v0, $exception-99b(zero); \
24 .previous
25
26
27 .set noreorder
28 .set noat
29 .text
30
31 .globl __strlen_user
32 .ent __strlen_user
33 .frame sp, 0, ra
34
35 .align 3
36__strlen_user:
37 ldah a1, 32767(zero) # do not use plain strlen_user() for strings
38 # that might be almost 2 GB long; you should
39 # be using strnlen_user() instead
40
41 .globl __strnlen_user
42
43 .align 3
44__strnlen_user:
45 .prologue 0
46
47 EX( ldq_u t0, 0(a0) ) # load first quadword (a0 may be misaligned)
48 lda t1, -1(zero)
49 insqh t1, a0, t1
50 andnot a0, 7, v0
51 or t1, t0, t0
52 subq a0, 1, a0 # get our +1 for the return
53 cmpbge zero, t0, t1 # t1 <- bitmask: bit i == 1 <==> i-th byte == 0
54 subq a1, 7, t2
55 subq a0, v0, t0
56 bne t1, $found
57
58 addq t2, t0, t2
59 addq a1, 1, a1
60
61 .align 3
62$loop: ble t2, $limit
63 EX( ldq t0, 8(v0) )
64 subq t2, 8, t2
65 addq v0, 8, v0 # addr += 8
66 cmpbge zero, t0, t1
67 beq t1, $loop
68
69$found: negq t1, t2 # clear all but least set bit
70 and t1, t2, t1
71
72 and t1, 0xf0, t2 # binary search for that set bit
73 and t1, 0xcc, t3
74 and t1, 0xaa, t4
75 cmovne t2, 4, t2
76 cmovne t3, 2, t3
77 cmovne t4, 1, t4
78 addq t2, t3, t2
79 addq v0, t4, v0
80 addq v0, t2, v0
81 nop # dual issue next two on ev4 and ev5
82 subq v0, a0, v0
83$exception:
84 ret
85
86 .align 3 # currently redundant
87$limit:
88 subq a1, t2, v0
89 ret
90
91 .end __strlen_user
diff --git a/arch/alpha/lib/strncat.S b/arch/alpha/lib/strncat.S
new file mode 100644
index 000000000000..a8278163c972
--- /dev/null
+++ b/arch/alpha/lib/strncat.S
@@ -0,0 +1,84 @@
1/*
2 * arch/alpha/lib/strncat.S
3 * Contributed by Richard Henderson (rth@tamu.edu)
4 *
5 * Append no more than COUNT characters from the null-terminated string SRC
6 * to the null-terminated string DST. Always null-terminate the new DST.
7 *
8 * This differs slightly from the semantics in libc in that we never write
9 * past count, whereas libc may write to count+1. This follows the generic
10 * implementation in lib/string.c and is, IMHO, more sensible.
11 */
12
13 .text
14
15 .align 3
16 .globl strncat
17 .ent strncat
18strncat:
19 .frame $30, 0, $26
20 .prologue 0
21
22 mov $16, $0 # set up return value
23 beq $18, $zerocount
24
25 /* Find the end of the string. */
26
27 ldq_u $1, 0($16) # load first quadword ($16 may be misaligned)
28 lda $2, -1($31)
29 insqh $2, $16, $2
30 andnot $16, 7, $16
31 or $2, $1, $1
32 cmpbge $31, $1, $2 # bits set iff byte == 0
33 bne $2, $found
34
35$loop: ldq $1, 8($16)
36 addq $16, 8, $16
37 cmpbge $31, $1, $2
38 beq $2, $loop
39
40$found: negq $2, $3 # clear all but least set bit
41 and $2, $3, $2
42
43 and $2, 0xf0, $3 # binary search for that set bit
44 and $2, 0xcc, $4
45 and $2, 0xaa, $5
46 cmovne $3, 4, $3
47 cmovne $4, 2, $4
48 cmovne $5, 1, $5
49 addq $3, $4, $3
50 addq $16, $5, $16
51 addq $16, $3, $16
52
53 /* Now do the append. */
54
55 bsr $23, __stxncpy
56
57 /* Worry about the null termination. */
58
59 zapnot $1, $27, $2 # was last byte a null?
60 bne $2, 0f
61 ret
62
630: cmplt $27, $24, $2 # did we fill the buffer completely?
64 or $2, $18, $2
65 bne $2, 2f
66
67 and $24, 0x80, $2 # no zero next byte
68 bne $2, 1f
69
70 /* Here there are bytes left in the current word. Clear one. */
71 addq $24, $24, $24 # end-of-count bit <<= 1
722: zap $1, $24, $1
73 stq_u $1, 0($16)
74 ret
75
761: /* Here we must read the next DST word and clear the first byte. */
77 ldq_u $1, 8($16)
78 zap $1, 1, $1
79 stq_u $1, 8($16)
80
81$zerocount:
82 ret
83
84 .end strncat
diff --git a/arch/alpha/lib/strncpy.S b/arch/alpha/lib/strncpy.S
new file mode 100644
index 000000000000..338551c7113c
--- /dev/null
+++ b/arch/alpha/lib/strncpy.S
@@ -0,0 +1,81 @@
1/*
2 * arch/alpha/lib/strncpy.S
3 * Contributed by Richard Henderson (rth@tamu.edu)
4 *
5 * Copy no more than COUNT bytes of the null-terminated string from
6 * SRC to DST. If SRC does not cover all of COUNT, the balance is
7 * zeroed.
8 *
9 * Or, rather, if the kernel cared about that weird ANSI quirk. This
10 * version has cropped that bit o' nastiness as well as assuming that
11 * __stxncpy is in range of a branch.
12 */
13
14 .set noat
15 .set noreorder
16
17 .text
18
19 .align 4
20 .globl strncpy
21 .ent strncpy
22strncpy:
23 .frame $30, 0, $26
24 .prologue 0
25
26 mov $16, $0 # set return value now
27 beq $18, $zerolen
28 unop
29 bsr $23, __stxncpy # do the work of the copy
30
31 unop
32 bne $18, $multiword # do we have full words left?
33 subq $24, 1, $3 # nope
34 subq $27, 1, $4
35
36 or $3, $24, $3 # clear the bits between the last
37 or $4, $27, $4 # written byte and the last byte in COUNT
38 andnot $4, $3, $4
39 zap $1, $4, $1
40
41 stq_u $1, 0($16)
42 ret
43
44 .align 4
45$multiword:
46 subq $24, 1, $2 # clear the final bits in the prev word
47 or $2, $24, $2
48 zapnot $1, $2, $1
49 subq $18, 1, $18
50
51 stq_u $1, 0($16)
52 addq $16, 8, $16
53 unop
54 beq $18, 1f
55
56 nop
57 unop
58 nop
59 blbc $18, 0f
60
61 stq_u $31, 0($16) # zero one word
62 subq $18, 1, $18
63 addq $16, 8, $16
64 beq $18, 1f
65
660: stq_u $31, 0($16) # zero two words
67 subq $18, 2, $18
68 stq_u $31, 8($16)
69 addq $16, 16, $16
70 bne $18, 0b
71
721: ldq_u $1, 0($16) # clear the leading bits in the final word
73 subq $27, 1, $2
74 or $2, $27, $2
75
76 zap $1, $2, $1
77 stq_u $1, 0($16)
78$zerolen:
79 ret
80
81 .end strncpy
diff --git a/arch/alpha/lib/strncpy_from_user.S b/arch/alpha/lib/strncpy_from_user.S
new file mode 100644
index 000000000000..73ee21160ff7
--- /dev/null
+++ b/arch/alpha/lib/strncpy_from_user.S
@@ -0,0 +1,339 @@
1/*
2 * arch/alpha/lib/strncpy_from_user.S
3 * Contributed by Richard Henderson (rth@tamu.edu)
4 *
5 * Just like strncpy except in the return value:
6 *
7 * -EFAULT if an exception occurs before the terminator is copied.
8 * N if the buffer filled.
9 *
10 * Otherwise the length of the string is returned.
11 */
12
13
14#include <asm/errno.h>
15#include <asm/regdef.h>
16
17
18/* Allow an exception for an insn; exit if we get one. */
19#define EX(x,y...) \
20 99: x,##y; \
21 .section __ex_table,"a"; \
22 .long 99b - .; \
23 lda $31, $exception-99b($0); \
24 .previous
25
26
27 .set noat
28 .set noreorder
29 .text
30
31 .globl __strncpy_from_user
32 .ent __strncpy_from_user
33 .frame $30, 0, $26
34 .prologue 0
35
36 .align 3
37$aligned:
38 /* On entry to this basic block:
39 t0 == the first destination word for masking back in
40 t1 == the first source word. */
41
42 /* Create the 1st output word and detect 0's in the 1st input word. */
43 lda t2, -1 # e1 : build a mask against false zero
44 mskqh t2, a1, t2 # e0 : detection in the src word
45 mskqh t1, a1, t3 # e0 :
46 ornot t1, t2, t2 # .. e1 :
47 mskql t0, a1, t0 # e0 : assemble the first output word
48 cmpbge zero, t2, t8 # .. e1 : bits set iff null found
49 or t0, t3, t0 # e0 :
50 beq a2, $a_eoc # .. e1 :
51 bne t8, $a_eos # .. e1 :
52
53 /* On entry to this basic block:
54 t0 == a source word not containing a null. */
55
56$a_loop:
57 stq_u t0, 0(a0) # e0 :
58 addq a0, 8, a0 # .. e1 :
59 EX( ldq_u t0, 0(a1) ) # e0 :
60 addq a1, 8, a1 # .. e1 :
61 subq a2, 1, a2 # e0 :
62 cmpbge zero, t0, t8 # .. e1 (stall)
63 beq a2, $a_eoc # e1 :
64 beq t8, $a_loop # e1 :
65
66 /* Take care of the final (partial) word store. At this point
67 the end-of-count bit is set in t8 iff it applies.
68
69 On entry to this basic block we have:
70 t0 == the source word containing the null
71 t8 == the cmpbge mask that found it. */
72
73$a_eos:
74 negq t8, t12 # e0 : find low bit set
75 and t8, t12, t12 # e1 (stall)
76
77 /* For the sake of the cache, don't read a destination word
78 if we're not going to need it. */
79 and t12, 0x80, t6 # e0 :
80 bne t6, 1f # .. e1 (zdb)
81
82 /* We're doing a partial word store and so need to combine
83 our source and original destination words. */
84 ldq_u t1, 0(a0) # e0 :
85 subq t12, 1, t6 # .. e1 :
86 or t12, t6, t8 # e0 :
87 unop #
88 zapnot t0, t8, t0 # e0 : clear src bytes > null
89 zap t1, t8, t1 # .. e1 : clear dst bytes <= null
90 or t0, t1, t0 # e1 :
91
921: stq_u t0, 0(a0)
93 br $finish_up
94
95 /* Add the end-of-count bit to the eos detection bitmask. */
96$a_eoc:
97 or t10, t8, t8
98 br $a_eos
99
100 /*** The Function Entry Point ***/
101 .align 3
102__strncpy_from_user:
103 mov a0, v0 # save the string start
104 beq a2, $zerolength
105
106 /* Are source and destination co-aligned? */
107 xor a0, a1, t1 # e0 :
108 and a0, 7, t0 # .. e1 : find dest misalignment
109 and t1, 7, t1 # e0 :
110 addq a2, t0, a2 # .. e1 : bias count by dest misalignment
111 subq a2, 1, a2 # e0 :
112 and a2, 7, t2 # e1 :
113 srl a2, 3, a2 # e0 : a2 = loop counter = (count - 1)/8
114 addq zero, 1, t10 # .. e1 :
115 sll t10, t2, t10 # e0 : t10 = bitmask of last count byte
116 bne t1, $unaligned # .. e1 :
117
118 /* We are co-aligned; take care of a partial first word. */
119
120 EX( ldq_u t1, 0(a1) ) # e0 : load first src word
121 addq a1, 8, a1 # .. e1 :
122
123 beq t0, $aligned # avoid loading dest word if not needed
124 ldq_u t0, 0(a0) # e0 :
125 br $aligned # .. e1 :
126
127
128/* The source and destination are not co-aligned. Align the destination
129 and cope. We have to be very careful about not reading too much and
130 causing a SEGV. */
131
132 .align 3
133$u_head:
134 /* We know just enough now to be able to assemble the first
135 full source word. We can still find a zero at the end of it
136 that prevents us from outputting the whole thing.
137
138 On entry to this basic block:
139 t0 == the first dest word, unmasked
140 t1 == the shifted low bits of the first source word
141 t6 == bytemask that is -1 in dest word bytes */
142
143 EX( ldq_u t2, 8(a1) ) # e0 : load second src word
144 addq a1, 8, a1 # .. e1 :
145 mskql t0, a0, t0 # e0 : mask trailing garbage in dst
146 extqh t2, a1, t4 # e0 :
147 or t1, t4, t1 # e1 : first aligned src word complete
148 mskqh t1, a0, t1 # e0 : mask leading garbage in src
149 or t0, t1, t0 # e0 : first output word complete
150 or t0, t6, t6 # e1 : mask original data for zero test
151 cmpbge zero, t6, t8 # e0 :
152 beq a2, $u_eocfin # .. e1 :
153 bne t8, $u_final # e1 :
154
155 lda t6, -1 # e1 : mask out the bits we have
156 mskql t6, a1, t6 # e0 : already seen
157 stq_u t0, 0(a0) # e0 : store first output word
158 or t6, t2, t2 # .. e1 :
159 cmpbge zero, t2, t8 # e0 : find nulls in second partial
160 addq a0, 8, a0 # .. e1 :
161 subq a2, 1, a2 # e0 :
162 bne t8, $u_late_head_exit # .. e1 :
163
164 /* Finally, we've got all the stupid leading edge cases taken care
165 of and we can set up to enter the main loop. */
166
167 extql t2, a1, t1 # e0 : position hi-bits of lo word
168 EX( ldq_u t2, 8(a1) ) # .. e1 : read next high-order source word
169 addq a1, 8, a1 # e0 :
170 cmpbge zero, t2, t8 # e1 (stall)
171 beq a2, $u_eoc # e1 :
172 bne t8, $u_eos # e1 :
173
174 /* Unaligned copy main loop. In order to avoid reading too much,
175 the loop is structured to detect zeros in aligned source words.
176 This has, unfortunately, effectively pulled half of a loop
177 iteration out into the head and half into the tail, but it does
178 prevent nastiness from accumulating in the very thing we want
179 to run as fast as possible.
180
181 On entry to this basic block:
182 t1 == the shifted high-order bits from the previous source word
183 t2 == the unshifted current source word
184
185 We further know that t2 does not contain a null terminator. */
186
187 .align 3
188$u_loop:
189 extqh t2, a1, t0 # e0 : extract high bits for current word
190 addq a1, 8, a1 # .. e1 :
191 extql t2, a1, t3 # e0 : extract low bits for next time
192 addq a0, 8, a0 # .. e1 :
193 or t0, t1, t0 # e0 : current dst word now complete
194 EX( ldq_u t2, 0(a1) ) # .. e1 : load high word for next time
195 stq_u t0, -8(a0) # e0 : save the current word
196 mov t3, t1 # .. e1 :
197 subq a2, 1, a2 # e0 :
198 cmpbge zero, t2, t8 # .. e1 : test new word for eos
199 beq a2, $u_eoc # e1 :
200 beq t8, $u_loop # e1 :
201
202 /* We've found a zero somewhere in the source word we just read.
203 If it resides in the lower half, we have one (probably partial)
204 word to write out, and if it resides in the upper half, we
205 have one full and one partial word left to write out.
206
207 On entry to this basic block:
208 t1 == the shifted high-order bits from the previous source word
209 t2 == the unshifted current source word. */
210$u_eos:
211 extqh t2, a1, t0 # e0 :
212 or t0, t1, t0 # e1 : first (partial) source word complete
213
214 cmpbge zero, t0, t8 # e0 : is the null in this first bit?
215 bne t8, $u_final # .. e1 (zdb)
216
217 stq_u t0, 0(a0) # e0 : the null was in the high-order bits
218 addq a0, 8, a0 # .. e1 :
219 subq a2, 1, a2 # e1 :
220
221$u_late_head_exit:
222 extql t2, a1, t0 # .. e0 :
223 cmpbge zero, t0, t8 # e0 :
224 or t8, t10, t6 # e1 :
225 cmoveq a2, t6, t8 # e0 :
226 nop # .. e1 :
227
228 /* Take care of a final (probably partial) result word.
229 On entry to this basic block:
230 t0 == assembled source word
231 t8 == cmpbge mask that found the null. */
232$u_final:
233 negq t8, t6 # e0 : isolate low bit set
234 and t6, t8, t12 # e1 :
235
236 and t12, 0x80, t6 # e0 : avoid dest word load if we can
237 bne t6, 1f # .. e1 (zdb)
238
239 ldq_u t1, 0(a0) # e0 :
240 subq t12, 1, t6 # .. e1 :
241 or t6, t12, t8 # e0 :
242 zapnot t0, t8, t0 # .. e1 : kill source bytes > null
243 zap t1, t8, t1 # e0 : kill dest bytes <= null
244 or t0, t1, t0 # e1 :
245
2461: stq_u t0, 0(a0) # e0 :
247 br $finish_up
248
249$u_eoc: # end-of-count
250 extqh t2, a1, t0
251 or t0, t1, t0
252 cmpbge zero, t0, t8
253
254$u_eocfin: # end-of-count, final word
255 or t10, t8, t8
256 br $u_final
257
258 /* Unaligned copy entry point. */
259 .align 3
260$unaligned:
261
262 EX( ldq_u t1, 0(a1) ) # e0 : load first source word
263
264 and a0, 7, t4 # .. e1 : find dest misalignment
265 and a1, 7, t5 # e0 : find src misalignment
266
267 /* Conditionally load the first destination word and a bytemask
268 with 0xff indicating that the destination byte is sacrosanct. */
269
270 mov zero, t0 # .. e1 :
271 mov zero, t6 # e0 :
272 beq t4, 1f # .. e1 :
273 ldq_u t0, 0(a0) # e0 :
274 lda t6, -1 # .. e1 :
275 mskql t6, a0, t6 # e0 :
2761:
277 subq a1, t4, a1 # .. e1 : sub dest misalignment from src addr
278
279 /* If source misalignment is larger than dest misalignment, we need
280 extra startup checks to avoid SEGV. */
281
282 cmplt t4, t5, t12 # e1 :
283 extql t1, a1, t1 # .. e0 : shift src into place
284 lda t2, -1 # e0 : for creating masks later
285 beq t12, $u_head # e1 :
286
287 mskqh t2, t5, t2 # e0 : begin src byte validity mask
288 cmpbge zero, t1, t8 # .. e1 : is there a zero?
289 extql t2, a1, t2 # e0 :
290 or t8, t10, t5 # .. e1 : test for end-of-count too
291 cmpbge zero, t2, t3 # e0 :
292 cmoveq a2, t5, t8 # .. e1 :
293 andnot t8, t3, t8 # e0 :
294 beq t8, $u_head # .. e1 (zdb)
295
296 /* At this point we've found a zero in the first partial word of
297 the source. We need to isolate the valid source data and mask
298 it into the original destination data. (Incidentally, we know
299 that we'll need at least one byte of that original dest word.) */
300
301 ldq_u t0, 0(a0) # e0 :
302 negq t8, t6 # .. e1 : build bitmask of bytes <= zero
303 mskqh t1, t4, t1 # e0 :
304 and t6, t8, t12 # .. e1 :
305 subq t12, 1, t6 # e0 :
306 or t6, t12, t8 # e1 :
307
308 zapnot t2, t8, t2 # e0 : prepare source word; mirror changes
309 zapnot t1, t8, t1 # .. e1 : to source validity mask
310
311 andnot t0, t2, t0 # e0 : zero place for source to reside
312 or t0, t1, t0 # e1 : and put it there
313 stq_u t0, 0(a0) # e0 :
314
315$finish_up:
316 zapnot t0, t12, t4 # was last byte written null?
317 cmovne t4, 1, t4
318
319 and t12, 0xf0, t3 # binary search for the address of the
320 and t12, 0xcc, t2 # last byte written
321 and t12, 0xaa, t1
322 bic a0, 7, t0
323 cmovne t3, 4, t3
324 cmovne t2, 2, t2
325 cmovne t1, 1, t1
326 addq t0, t3, t0
327 addq t1, t2, t1
328 addq t0, t1, t0
329 addq t0, t4, t0 # add one if we filled the buffer
330
331 subq t0, v0, v0 # find string length
332 ret
333
334$zerolength:
335 clr v0
336$exception:
337 ret
338
339 .end __strncpy_from_user
diff --git a/arch/alpha/lib/strrchr.S b/arch/alpha/lib/strrchr.S
new file mode 100644
index 000000000000..82cfd0ac907b
--- /dev/null
+++ b/arch/alpha/lib/strrchr.S
@@ -0,0 +1,87 @@
1/*
2 * arch/alpha/lib/strrchr.S
3 * Contributed by Richard Henderson (rth@tamu.edu)
4 *
5 * Return the address of the last occurrence of a given character
6 * within a null-terminated string, or null if it is not found.
7 */
8
9#include <asm/regdef.h>
10
11 .set noreorder
12 .set noat
13
14 .align 3
15 .ent strrchr
16 .globl strrchr
17strrchr:
18 .frame sp, 0, ra
19 .prologue 0
20
21 zapnot a1, 1, a1 # e0 : zero extend our test character
22 mov zero, t6 # .. e1 : t6 is last match aligned addr
23 sll a1, 8, t5 # e0 : replicate our test character
24 mov zero, t8 # .. e1 : t8 is last match byte compare mask
25 or t5, a1, a1 # e0 :
26 ldq_u t0, 0(a0) # .. e1 : load first quadword
27 sll a1, 16, t5 # e0 :
28 andnot a0, 7, v0 # .. e1 : align source addr
29 or t5, a1, a1 # e0 :
30 lda t4, -1 # .. e1 : build garbage mask
31 sll a1, 32, t5 # e0 :
32 cmpbge zero, t0, t1 # .. e1 : bits set iff byte == zero
33 mskqh t4, a0, t4 # e0 :
34 or t5, a1, a1 # .. e1 : character replication complete
35 xor t0, a1, t2 # e0 : make bytes == c zero
36 cmpbge zero, t4, t4 # .. e1 : bits set iff byte is garbage
37 cmpbge zero, t2, t3 # e0 : bits set iff byte == c
38 andnot t1, t4, t1 # .. e1 : clear garbage from null test
39 andnot t3, t4, t3 # e0 : clear garbage from char test
40 bne t1, $eos # .. e1 : did we already hit the terminator?
41
42 /* Character search main loop */
43$loop:
44 ldq t0, 8(v0) # e0 : load next quadword
45 cmovne t3, v0, t6 # .. e1 : save previous comparisons match
46 cmovne t3, t3, t8 # e0 :
47 addq v0, 8, v0 # .. e1 :
48 xor t0, a1, t2 # e0 :
49 cmpbge zero, t0, t1 # .. e1 : bits set iff byte == zero
50 cmpbge zero, t2, t3 # e0 : bits set iff byte == c
51 beq t1, $loop # .. e1 : if we havnt seen a null, loop
52
53 /* Mask out character matches after terminator */
54$eos:
55 negq t1, t4 # e0 : isolate first null byte match
56 and t1, t4, t4 # e1 :
57 subq t4, 1, t5 # e0 : build a mask of the bytes upto...
58 or t4, t5, t4 # e1 : ... and including the null
59
60 and t3, t4, t3 # e0 : mask out char matches after null
61 cmovne t3, t3, t8 # .. e1 : save it, if match found
62 cmovne t3, v0, t6 # e0 :
63
64 /* Locate the address of the last matched character */
65
66 /* Retain the early exit for the ev4 -- the ev5 mispredict penalty
67 is 5 cycles -- the same as just falling through. */
68 beq t8, $retnull # .. e1 :
69
70 and t8, 0xf0, t2 # e0 : binary search for the high bit set
71 cmovne t2, t2, t8 # .. e1 (zdb)
72 cmovne t2, 4, t2 # e0 :
73 and t8, 0xcc, t1 # .. e1 :
74 cmovne t1, t1, t8 # e0 :
75 cmovne t1, 2, t1 # .. e1 :
76 and t8, 0xaa, t0 # e0 :
77 cmovne t0, 1, t0 # .. e1 (zdb)
78 addq t2, t1, t1 # e0 :
79 addq t6, t0, v0 # .. e1 : add our aligned base ptr to the mix
80 addq v0, t1, v0 # e0 :
81 ret # .. e1 :
82
83$retnull:
84 mov zero, v0 # e0 :
85 ret # .. e1 :
86
87 .end strrchr
diff --git a/arch/alpha/lib/stxcpy.S b/arch/alpha/lib/stxcpy.S
new file mode 100644
index 000000000000..2a8d51bfc05d
--- /dev/null
+++ b/arch/alpha/lib/stxcpy.S
@@ -0,0 +1,289 @@
1/*
2 * arch/alpha/lib/stxcpy.S
3 * Contributed by Richard Henderson (rth@tamu.edu)
4 *
5 * Copy a null-terminated string from SRC to DST.
6 *
7 * This is an internal routine used by strcpy, stpcpy, and strcat.
8 * As such, it uses special linkage conventions to make implementation
9 * of these public functions more efficient.
10 *
11 * On input:
12 * t9 = return address
13 * a0 = DST
14 * a1 = SRC
15 *
16 * On output:
17 * t12 = bitmask (with one bit set) indicating the last byte written
18 * a0 = unaligned address of the last *word* written
19 *
20 * Furthermore, v0, a3-a5, t11, and t12 are untouched.
21 */
22
23#include <asm/regdef.h>
24
25 .set noat
26 .set noreorder
27
28 .text
29
30/* There is a problem with either gdb (as of 4.16) or gas (as of 2.7) that
31 doesn't like putting the entry point for a procedure somewhere in the
32 middle of the procedure descriptor. Work around this by putting the
33 aligned copy in its own procedure descriptor */
34
35 .ent stxcpy_aligned
36 .align 3
37stxcpy_aligned:
38 .frame sp, 0, t9
39 .prologue 0
40
41 /* On entry to this basic block:
42 t0 == the first destination word for masking back in
43 t1 == the first source word. */
44
45 /* Create the 1st output word and detect 0's in the 1st input word. */
46 lda t2, -1 # e1 : build a mask against false zero
47 mskqh t2, a1, t2 # e0 : detection in the src word
48 mskqh t1, a1, t3 # e0 :
49 ornot t1, t2, t2 # .. e1 :
50 mskql t0, a1, t0 # e0 : assemble the first output word
51 cmpbge zero, t2, t8 # .. e1 : bits set iff null found
52 or t0, t3, t1 # e0 :
53 bne t8, $a_eos # .. e1 :
54
55 /* On entry to this basic block:
56 t0 == the first destination word for masking back in
57 t1 == a source word not containing a null. */
58
59$a_loop:
60 stq_u t1, 0(a0) # e0 :
61 addq a0, 8, a0 # .. e1 :
62 ldq_u t1, 0(a1) # e0 :
63 addq a1, 8, a1 # .. e1 :
64 cmpbge zero, t1, t8 # e0 (stall)
65 beq t8, $a_loop # .. e1 (zdb)
66
67 /* Take care of the final (partial) word store.
68 On entry to this basic block we have:
69 t1 == the source word containing the null
70 t8 == the cmpbge mask that found it. */
71$a_eos:
72 negq t8, t6 # e0 : find low bit set
73 and t8, t6, t12 # e1 (stall)
74
75 /* For the sake of the cache, don't read a destination word
76 if we're not going to need it. */
77 and t12, 0x80, t6 # e0 :
78 bne t6, 1f # .. e1 (zdb)
79
80 /* We're doing a partial word store and so need to combine
81 our source and original destination words. */
82 ldq_u t0, 0(a0) # e0 :
83 subq t12, 1, t6 # .. e1 :
84 zapnot t1, t6, t1 # e0 : clear src bytes >= null
85 or t12, t6, t8 # .. e1 :
86 zap t0, t8, t0 # e0 : clear dst bytes <= null
87 or t0, t1, t1 # e1 :
88
891: stq_u t1, 0(a0) # e0 :
90 ret (t9) # .. e1 :
91
92 .end stxcpy_aligned
93
94 .align 3
95 .ent __stxcpy
96 .globl __stxcpy
97__stxcpy:
98 .frame sp, 0, t9
99 .prologue 0
100
101 /* Are source and destination co-aligned? */
102 xor a0, a1, t0 # e0 :
103 unop # :
104 and t0, 7, t0 # e0 :
105 bne t0, $unaligned # .. e1 :
106
107 /* We are co-aligned; take care of a partial first word. */
108 ldq_u t1, 0(a1) # e0 : load first src word
109 and a0, 7, t0 # .. e1 : take care not to load a word ...
110 addq a1, 8, a1 # e0 :
111 beq t0, stxcpy_aligned # .. e1 : ... if we wont need it
112 ldq_u t0, 0(a0) # e0 :
113 br stxcpy_aligned # .. e1 :
114
115
116/* The source and destination are not co-aligned. Align the destination
117 and cope. We have to be very careful about not reading too much and
118 causing a SEGV. */
119
120 .align 3
121$u_head:
122 /* We know just enough now to be able to assemble the first
123 full source word. We can still find a zero at the end of it
124 that prevents us from outputting the whole thing.
125
126 On entry to this basic block:
127 t0 == the first dest word, for masking back in, if needed else 0
128 t1 == the low bits of the first source word
129 t6 == bytemask that is -1 in dest word bytes */
130
131 ldq_u t2, 8(a1) # e0 :
132 addq a1, 8, a1 # .. e1 :
133
134 extql t1, a1, t1 # e0 :
135 extqh t2, a1, t4 # e0 :
136 mskql t0, a0, t0 # e0 :
137 or t1, t4, t1 # .. e1 :
138 mskqh t1, a0, t1 # e0 :
139 or t0, t1, t1 # e1 :
140
141 or t1, t6, t6 # e0 :
142 cmpbge zero, t6, t8 # .. e1 :
143 lda t6, -1 # e0 : for masking just below
144 bne t8, $u_final # .. e1 :
145
146 mskql t6, a1, t6 # e0 : mask out the bits we have
147 or t6, t2, t2 # e1 : already extracted before
148 cmpbge zero, t2, t8 # e0 : testing eos
149 bne t8, $u_late_head_exit # .. e1 (zdb)
150
151 /* Finally, we've got all the stupid leading edge cases taken care
152 of and we can set up to enter the main loop. */
153
154 stq_u t1, 0(a0) # e0 : store first output word
155 addq a0, 8, a0 # .. e1 :
156 extql t2, a1, t0 # e0 : position ho-bits of lo word
157 ldq_u t2, 8(a1) # .. e1 : read next high-order source word
158 addq a1, 8, a1 # e0 :
159 cmpbge zero, t2, t8 # .. e1 :
160 nop # e0 :
161 bne t8, $u_eos # .. e1 :
162
163 /* Unaligned copy main loop. In order to avoid reading too much,
164 the loop is structured to detect zeros in aligned source words.
165 This has, unfortunately, effectively pulled half of a loop
166 iteration out into the head and half into the tail, but it does
167 prevent nastiness from accumulating in the very thing we want
168 to run as fast as possible.
169
170 On entry to this basic block:
171 t0 == the shifted high-order bits from the previous source word
172 t2 == the unshifted current source word
173
174 We further know that t2 does not contain a null terminator. */
175
176 .align 3
177$u_loop:
178 extqh t2, a1, t1 # e0 : extract high bits for current word
179 addq a1, 8, a1 # .. e1 :
180 extql t2, a1, t3 # e0 : extract low bits for next time
181 addq a0, 8, a0 # .. e1 :
182 or t0, t1, t1 # e0 : current dst word now complete
183 ldq_u t2, 0(a1) # .. e1 : load high word for next time
184 stq_u t1, -8(a0) # e0 : save the current word
185 mov t3, t0 # .. e1 :
186 cmpbge zero, t2, t8 # e0 : test new word for eos
187 beq t8, $u_loop # .. e1 :
188
189 /* We've found a zero somewhere in the source word we just read.
190 If it resides in the lower half, we have one (probably partial)
191 word to write out, and if it resides in the upper half, we
192 have one full and one partial word left to write out.
193
194 On entry to this basic block:
195 t0 == the shifted high-order bits from the previous source word
196 t2 == the unshifted current source word. */
197$u_eos:
198 extqh t2, a1, t1 # e0 :
199 or t0, t1, t1 # e1 : first (partial) source word complete
200
201 cmpbge zero, t1, t8 # e0 : is the null in this first bit?
202 bne t8, $u_final # .. e1 (zdb)
203
204$u_late_head_exit:
205 stq_u t1, 0(a0) # e0 : the null was in the high-order bits
206 addq a0, 8, a0 # .. e1 :
207 extql t2, a1, t1 # e0 :
208 cmpbge zero, t1, t8 # .. e1 :
209
210 /* Take care of a final (probably partial) result word.
211 On entry to this basic block:
212 t1 == assembled source word
213 t8 == cmpbge mask that found the null. */
214$u_final:
215 negq t8, t6 # e0 : isolate low bit set
216 and t6, t8, t12 # e1 :
217
218 and t12, 0x80, t6 # e0 : avoid dest word load if we can
219 bne t6, 1f # .. e1 (zdb)
220
221 ldq_u t0, 0(a0) # e0 :
222 subq t12, 1, t6 # .. e1 :
223 or t6, t12, t8 # e0 :
224 zapnot t1, t6, t1 # .. e1 : kill source bytes >= null
225 zap t0, t8, t0 # e0 : kill dest bytes <= null
226 or t0, t1, t1 # e1 :
227
2281: stq_u t1, 0(a0) # e0 :
229 ret (t9) # .. e1 :
230
231 /* Unaligned copy entry point. */
232 .align 3
233$unaligned:
234
235 ldq_u t1, 0(a1) # e0 : load first source word
236
237 and a0, 7, t4 # .. e1 : find dest misalignment
238 and a1, 7, t5 # e0 : find src misalignment
239
240 /* Conditionally load the first destination word and a bytemask
241 with 0xff indicating that the destination byte is sacrosanct. */
242
243 mov zero, t0 # .. e1 :
244 mov zero, t6 # e0 :
245 beq t4, 1f # .. e1 :
246 ldq_u t0, 0(a0) # e0 :
247 lda t6, -1 # .. e1 :
248 mskql t6, a0, t6 # e0 :
2491:
250 subq a1, t4, a1 # .. e1 : sub dest misalignment from src addr
251
252 /* If source misalignment is larger than dest misalignment, we need
253 extra startup checks to avoid SEGV. */
254
255 cmplt t4, t5, t12 # e0 :
256 beq t12, $u_head # .. e1 (zdb)
257
258 lda t2, -1 # e1 : mask out leading garbage in source
259 mskqh t2, t5, t2 # e0 :
260 nop # e0 :
261 ornot t1, t2, t3 # .. e1 :
262 cmpbge zero, t3, t8 # e0 : is there a zero?
263 beq t8, $u_head # .. e1 (zdb)
264
265 /* At this point we've found a zero in the first partial word of
266 the source. We need to isolate the valid source data and mask
267 it into the original destination data. (Incidentally, we know
268 that we'll need at least one byte of that original dest word.) */
269
270 ldq_u t0, 0(a0) # e0 :
271
272 negq t8, t6 # .. e1 : build bitmask of bytes <= zero
273 and t6, t8, t12 # e0 :
274 and a1, 7, t5 # .. e1 :
275 subq t12, 1, t6 # e0 :
276 or t6, t12, t8 # e1 :
277 srl t12, t5, t12 # e0 : adjust final null return value
278
279 zapnot t2, t8, t2 # .. e1 : prepare source word; mirror changes
280 and t1, t2, t1 # e1 : to source validity mask
281 extql t2, a1, t2 # .. e0 :
282 extql t1, a1, t1 # e0 :
283
284 andnot t0, t2, t0 # .. e1 : zero place for source to reside
285 or t0, t1, t1 # e1 : and put it there
286 stq_u t1, 0(a0) # .. e0 :
287 ret (t9) # e1 :
288
289 .end __stxcpy
diff --git a/arch/alpha/lib/stxncpy.S b/arch/alpha/lib/stxncpy.S
new file mode 100644
index 000000000000..da1a72740d29
--- /dev/null
+++ b/arch/alpha/lib/stxncpy.S
@@ -0,0 +1,345 @@
1/*
2 * arch/alpha/lib/stxncpy.S
3 * Contributed by Richard Henderson (rth@tamu.edu)
4 *
5 * Copy no more than COUNT bytes of the null-terminated string from
6 * SRC to DST.
7 *
8 * This is an internal routine used by strncpy, stpncpy, and strncat.
9 * As such, it uses special linkage conventions to make implementation
10 * of these public functions more efficient.
11 *
12 * On input:
13 * t9 = return address
14 * a0 = DST
15 * a1 = SRC
16 * a2 = COUNT
17 *
18 * Furthermore, COUNT may not be zero.
19 *
20 * On output:
21 * t0 = last word written
22 * t10 = bitmask (with one bit set) indicating the byte position of
23 * the end of the range specified by COUNT
24 * t12 = bitmask (with one bit set) indicating the last byte written
25 * a0 = unaligned address of the last *word* written
26 * a2 = the number of full words left in COUNT
27 *
28 * Furthermore, v0, a3-a5, t11, and $at are untouched.
29 */
30
31#include <asm/regdef.h>
32
33 .set noat
34 .set noreorder
35
36 .text
37
38/* There is a problem with either gdb (as of 4.16) or gas (as of 2.7) that
39 doesn't like putting the entry point for a procedure somewhere in the
40 middle of the procedure descriptor. Work around this by putting the
41 aligned copy in its own procedure descriptor */
42
43 .ent stxncpy_aligned
44 .align 3
45stxncpy_aligned:
46 .frame sp, 0, t9, 0
47 .prologue 0
48
49 /* On entry to this basic block:
50 t0 == the first destination word for masking back in
51 t1 == the first source word. */
52
53 /* Create the 1st output word and detect 0's in the 1st input word. */
54 lda t2, -1 # e1 : build a mask against false zero
55 mskqh t2, a1, t2 # e0 : detection in the src word
56 mskqh t1, a1, t3 # e0 :
57 ornot t1, t2, t2 # .. e1 :
58 mskql t0, a1, t0 # e0 : assemble the first output word
59 cmpbge zero, t2, t8 # .. e1 : bits set iff null found
60 or t0, t3, t0 # e0 :
61 beq a2, $a_eoc # .. e1 :
62 bne t8, $a_eos # .. e1 :
63
64 /* On entry to this basic block:
65 t0 == a source word not containing a null. */
66
67$a_loop:
68 stq_u t0, 0(a0) # e0 :
69 addq a0, 8, a0 # .. e1 :
70 ldq_u t0, 0(a1) # e0 :
71 addq a1, 8, a1 # .. e1 :
72 subq a2, 1, a2 # e0 :
73 cmpbge zero, t0, t8 # .. e1 (stall)
74 beq a2, $a_eoc # e1 :
75 beq t8, $a_loop # e1 :
76
77 /* Take care of the final (partial) word store. At this point
78 the end-of-count bit is set in t8 iff it applies.
79
80 On entry to this basic block we have:
81 t0 == the source word containing the null
82 t8 == the cmpbge mask that found it. */
83
84$a_eos:
85 negq t8, t12 # e0 : find low bit set
86 and t8, t12, t12 # e1 (stall)
87
88 /* For the sake of the cache, don't read a destination word
89 if we're not going to need it. */
90 and t12, 0x80, t6 # e0 :
91 bne t6, 1f # .. e1 (zdb)
92
93 /* We're doing a partial word store and so need to combine
94 our source and original destination words. */
95 ldq_u t1, 0(a0) # e0 :
96 subq t12, 1, t6 # .. e1 :
97 or t12, t6, t8 # e0 :
98 unop #
99 zapnot t0, t8, t0 # e0 : clear src bytes > null
100 zap t1, t8, t1 # .. e1 : clear dst bytes <= null
101 or t0, t1, t0 # e1 :
102
1031: stq_u t0, 0(a0) # e0 :
104 ret (t9) # e1 :
105
106 /* Add the end-of-count bit to the eos detection bitmask. */
107$a_eoc:
108 or t10, t8, t8
109 br $a_eos
110
111 .end stxncpy_aligned
112
113 .align 3
114 .ent __stxncpy
115 .globl __stxncpy
116__stxncpy:
117 .frame sp, 0, t9, 0
118 .prologue 0
119
120 /* Are source and destination co-aligned? */
121 xor a0, a1, t1 # e0 :
122 and a0, 7, t0 # .. e1 : find dest misalignment
123 and t1, 7, t1 # e0 :
124 addq a2, t0, a2 # .. e1 : bias count by dest misalignment
125 subq a2, 1, a2 # e0 :
126 and a2, 7, t2 # e1 :
127 srl a2, 3, a2 # e0 : a2 = loop counter = (count - 1)/8
128 addq zero, 1, t10 # .. e1 :
129 sll t10, t2, t10 # e0 : t10 = bitmask of last count byte
130 bne t1, $unaligned # .. e1 :
131
132 /* We are co-aligned; take care of a partial first word. */
133
134 ldq_u t1, 0(a1) # e0 : load first src word
135 addq a1, 8, a1 # .. e1 :
136
137 beq t0, stxncpy_aligned # avoid loading dest word if not needed
138 ldq_u t0, 0(a0) # e0 :
139 br stxncpy_aligned # .. e1 :
140
141
142/* The source and destination are not co-aligned. Align the destination
143 and cope. We have to be very careful about not reading too much and
144 causing a SEGV. */
145
146 .align 3
147$u_head:
148 /* We know just enough now to be able to assemble the first
149 full source word. We can still find a zero at the end of it
150 that prevents us from outputting the whole thing.
151
152 On entry to this basic block:
153 t0 == the first dest word, unmasked
154 t1 == the shifted low bits of the first source word
155 t6 == bytemask that is -1 in dest word bytes */
156
157 ldq_u t2, 8(a1) # e0 : load second src word
158 addq a1, 8, a1 # .. e1 :
159 mskql t0, a0, t0 # e0 : mask trailing garbage in dst
160 extqh t2, a1, t4 # e0 :
161 or t1, t4, t1 # e1 : first aligned src word complete
162 mskqh t1, a0, t1 # e0 : mask leading garbage in src
163 or t0, t1, t0 # e0 : first output word complete
164 or t0, t6, t6 # e1 : mask original data for zero test
165 cmpbge zero, t6, t8 # e0 :
166 beq a2, $u_eocfin # .. e1 :
167 lda t6, -1 # e0 :
168 bne t8, $u_final # .. e1 :
169
170 mskql t6, a1, t6 # e0 : mask out bits already seen
171 nop # .. e1 :
172 stq_u t0, 0(a0) # e0 : store first output word
173 or t6, t2, t2 # .. e1 :
174 cmpbge zero, t2, t8 # e0 : find nulls in second partial
175 addq a0, 8, a0 # .. e1 :
176 subq a2, 1, a2 # e0 :
177 bne t8, $u_late_head_exit # .. e1 :
178
179 /* Finally, we've got all the stupid leading edge cases taken care
180 of and we can set up to enter the main loop. */
181
182 extql t2, a1, t1 # e0 : position hi-bits of lo word
183 beq a2, $u_eoc # .. e1 :
184 ldq_u t2, 8(a1) # e0 : read next high-order source word
185 addq a1, 8, a1 # .. e1 :
186 extqh t2, a1, t0 # e0 : position lo-bits of hi word (stall)
187 cmpbge zero, t2, t8 # .. e1 :
188 nop # e0 :
189 bne t8, $u_eos # .. e1 :
190
191 /* Unaligned copy main loop. In order to avoid reading too much,
192 the loop is structured to detect zeros in aligned source words.
193 This has, unfortunately, effectively pulled half of a loop
194 iteration out into the head and half into the tail, but it does
195 prevent nastiness from accumulating in the very thing we want
196 to run as fast as possible.
197
198 On entry to this basic block:
199 t0 == the shifted low-order bits from the current source word
200 t1 == the shifted high-order bits from the previous source word
201 t2 == the unshifted current source word
202
203 We further know that t2 does not contain a null terminator. */
204
205 .align 3
206$u_loop:
207 or t0, t1, t0 # e0 : current dst word now complete
208 subq a2, 1, a2 # .. e1 : decrement word count
209 stq_u t0, 0(a0) # e0 : save the current word
210 addq a0, 8, a0 # .. e1 :
211 extql t2, a1, t1 # e0 : extract high bits for next time
212 beq a2, $u_eoc # .. e1 :
213 ldq_u t2, 8(a1) # e0 : load high word for next time
214 addq a1, 8, a1 # .. e1 :
215 nop # e0 :
216 cmpbge zero, t2, t8 # e1 : test new word for eos (stall)
217 extqh t2, a1, t0 # e0 : extract low bits for current word
218 beq t8, $u_loop # .. e1 :
219
220 /* We've found a zero somewhere in the source word we just read.
221 If it resides in the lower half, we have one (probably partial)
222 word to write out, and if it resides in the upper half, we
223 have one full and one partial word left to write out.
224
225 On entry to this basic block:
226 t0 == the shifted low-order bits from the current source word
227 t1 == the shifted high-order bits from the previous source word
228 t2 == the unshifted current source word. */
229$u_eos:
230 or t0, t1, t0 # e0 : first (partial) source word complete
231 nop # .. e1 :
232 cmpbge zero, t0, t8 # e0 : is the null in this first bit?
233 bne t8, $u_final # .. e1 (zdb)
234
235 stq_u t0, 0(a0) # e0 : the null was in the high-order bits
236 addq a0, 8, a0 # .. e1 :
237 subq a2, 1, a2 # e1 :
238
239$u_late_head_exit:
240 extql t2, a1, t0 # .. e0 :
241 cmpbge zero, t0, t8 # e0 :
242 or t8, t10, t6 # e1 :
243 cmoveq a2, t6, t8 # e0 :
244 nop # .. e1 :
245
246 /* Take care of a final (probably partial) result word.
247 On entry to this basic block:
248 t0 == assembled source word
249 t8 == cmpbge mask that found the null. */
250$u_final:
251 negq t8, t6 # e0 : isolate low bit set
252 and t6, t8, t12 # e1 :
253
254 and t12, 0x80, t6 # e0 : avoid dest word load if we can
255 bne t6, 1f # .. e1 (zdb)
256
257 ldq_u t1, 0(a0) # e0 :
258 subq t12, 1, t6 # .. e1 :
259 or t6, t12, t8 # e0 :
260 zapnot t0, t8, t0 # .. e1 : kill source bytes > null
261 zap t1, t8, t1 # e0 : kill dest bytes <= null
262 or t0, t1, t0 # e1 :
263
2641: stq_u t0, 0(a0) # e0 :
265 ret (t9) # .. e1 :
266
267 /* Got to end-of-count before end of string.
268 On entry to this basic block:
269 t1 == the shifted high-order bits from the previous source word */
270$u_eoc:
271 and a1, 7, t6 # e1 :
272 sll t10, t6, t6 # e0 :
273 and t6, 0xff, t6 # e0 :
274 bne t6, 1f # .. e1 :
275
276 ldq_u t2, 8(a1) # e0 : load final src word
277 nop # .. e1 :
278 extqh t2, a1, t0 # e0 : extract low bits for last word
279 or t1, t0, t1 # e1 :
280
2811: cmpbge zero, t1, t8
282 mov t1, t0
283
284$u_eocfin: # end-of-count, final word
285 or t10, t8, t8
286 br $u_final
287
288 /* Unaligned copy entry point. */
289 .align 3
290$unaligned:
291
292 ldq_u t1, 0(a1) # e0 : load first source word
293
294 and a0, 7, t4 # .. e1 : find dest misalignment
295 and a1, 7, t5 # e0 : find src misalignment
296
297 /* Conditionally load the first destination word and a bytemask
298 with 0xff indicating that the destination byte is sacrosanct. */
299
300 mov zero, t0 # .. e1 :
301 mov zero, t6 # e0 :
302 beq t4, 1f # .. e1 :
303 ldq_u t0, 0(a0) # e0 :
304 lda t6, -1 # .. e1 :
305 mskql t6, a0, t6 # e0 :
306 subq a1, t4, a1 # .. e1 : sub dest misalignment from src addr
307
308 /* If source misalignment is larger than dest misalignment, we need
309 extra startup checks to avoid SEGV. */
310
3111: cmplt t4, t5, t12 # e1 :
312 extql t1, a1, t1 # .. e0 : shift src into place
313 lda t2, -1 # e0 : for creating masks later
314 beq t12, $u_head # .. e1 :
315
316 extql t2, a1, t2 # e0 :
317 cmpbge zero, t1, t8 # .. e1 : is there a zero?
318 andnot t2, t6, t12 # e0 : dest mask for a single word copy
319 or t8, t10, t5 # .. e1 : test for end-of-count too
320 cmpbge zero, t12, t3 # e0 :
321 cmoveq a2, t5, t8 # .. e1 :
322 andnot t8, t3, t8 # e0 :
323 beq t8, $u_head # .. e1 (zdb)
324
325 /* At this point we've found a zero in the first partial word of
326 the source. We need to isolate the valid source data and mask
327 it into the original destination data. (Incidentally, we know
328 that we'll need at least one byte of that original dest word.) */
329
330 ldq_u t0, 0(a0) # e0 :
331 negq t8, t6 # .. e1 : build bitmask of bytes <= zero
332 mskqh t1, t4, t1 # e0 :
333 and t6, t8, t2 # .. e1 :
334 subq t2, 1, t6 # e0 :
335 or t6, t2, t8 # e1 :
336
337 zapnot t12, t8, t12 # e0 : prepare source word; mirror changes
338 zapnot t1, t8, t1 # .. e1 : to source validity mask
339
340 andnot t0, t12, t0 # e0 : zero place for source to reside
341 or t0, t1, t0 # e1 : and put it there
342 stq_u t0, 0(a0) # e0 :
343 ret (t9) # .. e1 :
344
345 .end __stxncpy
diff --git a/arch/alpha/lib/udelay.c b/arch/alpha/lib/udelay.c
new file mode 100644
index 000000000000..1c879bbce419
--- /dev/null
+++ b/arch/alpha/lib/udelay.c
@@ -0,0 +1,55 @@
1/*
2 * Copyright (C) 1993, 2000 Linus Torvalds
3 *
4 * Delay routines, using a pre-computed "loops_per_jiffy" value.
5 */
6
7#include <linux/config.h>
8#include <linux/module.h>
9#include <linux/sched.h> /* for udelay's use of smp_processor_id */
10#include <asm/param.h>
11#include <asm/smp.h>
12#include <linux/delay.h>
13
14/*
15 * Use only for very small delays (< 1 msec).
16 *
17 * The active part of our cycle counter is only 32-bits wide, and
18 * we're treating the difference between two marks as signed. On
19 * a 1GHz box, that's about 2 seconds.
20 */
21
22void
23__delay(int loops)
24{
25 int tmp;
26 __asm__ __volatile__(
27 " rpcc %0\n"
28 " addl %1,%0,%1\n"
29 "1: rpcc %0\n"
30 " subl %1,%0,%0\n"
31 " bgt %0,1b"
32 : "=&r" (tmp), "=r" (loops) : "1"(loops));
33}
34
35#ifdef CONFIG_SMP
36#define LPJ cpu_data[smp_processor_id()].loops_per_jiffy
37#else
38#define LPJ loops_per_jiffy
39#endif
40
41void
42udelay(unsigned long usecs)
43{
44 usecs *= (((unsigned long)HZ << 32) / 1000000) * LPJ;
45 __delay((long)usecs >> 32);
46}
47EXPORT_SYMBOL(udelay);
48
49void
50ndelay(unsigned long nsecs)
51{
52 nsecs *= (((unsigned long)HZ << 32) / 1000000000) * LPJ;
53 __delay((long)nsecs >> 32);
54}
55EXPORT_SYMBOL(ndelay);
diff --git a/arch/alpha/math-emu/Makefile b/arch/alpha/math-emu/Makefile
new file mode 100644
index 000000000000..359ef087e69e
--- /dev/null
+++ b/arch/alpha/math-emu/Makefile
@@ -0,0 +1,9 @@
1#
2# Makefile for the FPU instruction emulation.
3#
4
5EXTRA_CFLAGS := -w
6
7obj-$(CONFIG_MATHEMU) += math-emu.o
8
9math-emu-objs := math.o qrnnd.o
diff --git a/arch/alpha/math-emu/math.c b/arch/alpha/math-emu/math.c
new file mode 100644
index 000000000000..ae79dd970b02
--- /dev/null
+++ b/arch/alpha/math-emu/math.c
@@ -0,0 +1,400 @@
1#include <linux/module.h>
2#include <linux/types.h>
3#include <linux/kernel.h>
4#include <linux/sched.h>
5
6#include <asm/uaccess.h>
7
8#include "sfp-util.h"
9#include <math-emu/soft-fp.h>
10#include <math-emu/single.h>
11#include <math-emu/double.h>
12
13#define OPC_PAL 0x00
14#define OPC_INTA 0x10
15#define OPC_INTL 0x11
16#define OPC_INTS 0x12
17#define OPC_INTM 0x13
18#define OPC_FLTC 0x14
19#define OPC_FLTV 0x15
20#define OPC_FLTI 0x16
21#define OPC_FLTL 0x17
22#define OPC_MISC 0x18
23#define OPC_JSR 0x1a
24
25#define FOP_SRC_S 0
26#define FOP_SRC_T 2
27#define FOP_SRC_Q 3
28
29#define FOP_FNC_ADDx 0
30#define FOP_FNC_CVTQL 0
31#define FOP_FNC_SUBx 1
32#define FOP_FNC_MULx 2
33#define FOP_FNC_DIVx 3
34#define FOP_FNC_CMPxUN 4
35#define FOP_FNC_CMPxEQ 5
36#define FOP_FNC_CMPxLT 6
37#define FOP_FNC_CMPxLE 7
38#define FOP_FNC_SQRTx 11
39#define FOP_FNC_CVTxS 12
40#define FOP_FNC_CVTxT 14
41#define FOP_FNC_CVTxQ 15
42
43#define MISC_TRAPB 0x0000
44#define MISC_EXCB 0x0400
45
46extern unsigned long alpha_read_fp_reg (unsigned long reg);
47extern void alpha_write_fp_reg (unsigned long reg, unsigned long val);
48extern unsigned long alpha_read_fp_reg_s (unsigned long reg);
49extern void alpha_write_fp_reg_s (unsigned long reg, unsigned long val);
50
51
52#ifdef MODULE
53
54MODULE_DESCRIPTION("FP Software completion module");
55
56extern long (*alpha_fp_emul_imprecise)(struct pt_regs *, unsigned long);
57extern long (*alpha_fp_emul) (unsigned long pc);
58
59static long (*save_emul_imprecise)(struct pt_regs *, unsigned long);
60static long (*save_emul) (unsigned long pc);
61
62long do_alpha_fp_emul_imprecise(struct pt_regs *, unsigned long);
63long do_alpha_fp_emul(unsigned long);
64
65int init_module(void)
66{
67 save_emul_imprecise = alpha_fp_emul_imprecise;
68 save_emul = alpha_fp_emul;
69 alpha_fp_emul_imprecise = do_alpha_fp_emul_imprecise;
70 alpha_fp_emul = do_alpha_fp_emul;
71 return 0;
72}
73
74void cleanup_module(void)
75{
76 alpha_fp_emul_imprecise = save_emul_imprecise;
77 alpha_fp_emul = save_emul;
78}
79
80#undef alpha_fp_emul_imprecise
81#define alpha_fp_emul_imprecise do_alpha_fp_emul_imprecise
82#undef alpha_fp_emul
83#define alpha_fp_emul do_alpha_fp_emul
84
85#endif /* MODULE */
86
87
88/*
89 * Emulate the floating point instruction at address PC. Returns -1 if the
90 * instruction to be emulated is illegal (such as with the opDEC trap), else
91 * the SI_CODE for a SIGFPE signal, else 0 if everything's ok.
92 *
93 * Notice that the kernel does not and cannot use FP regs. This is good
94 * because it means that instead of saving/restoring all fp regs, we simply
95 * stick the result of the operation into the appropriate register.
96 */
97long
98alpha_fp_emul (unsigned long pc)
99{
100 FP_DECL_EX;
101 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR);
102 FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR);
103
104 unsigned long fa, fb, fc, func, mode, src;
105 unsigned long res, va, vb, vc, swcr, fpcr;
106 __u32 insn;
107 long si_code;
108
109 get_user(insn, (__u32 __user *)pc);
110 fc = (insn >> 0) & 0x1f; /* destination register */
111 fb = (insn >> 16) & 0x1f;
112 fa = (insn >> 21) & 0x1f;
113 func = (insn >> 5) & 0xf;
114 src = (insn >> 9) & 0x3;
115 mode = (insn >> 11) & 0x3;
116
117 fpcr = rdfpcr();
118 swcr = swcr_update_status(current_thread_info()->ieee_state, fpcr);
119
120 if (mode == 3) {
121 /* Dynamic -- get rounding mode from fpcr. */
122 mode = (fpcr >> FPCR_DYN_SHIFT) & 3;
123 }
124
125 switch (src) {
126 case FOP_SRC_S:
127 va = alpha_read_fp_reg_s(fa);
128 vb = alpha_read_fp_reg_s(fb);
129
130 FP_UNPACK_SP(SA, &va);
131 FP_UNPACK_SP(SB, &vb);
132
133 switch (func) {
134 case FOP_FNC_SUBx:
135 FP_SUB_S(SR, SA, SB);
136 goto pack_s;
137
138 case FOP_FNC_ADDx:
139 FP_ADD_S(SR, SA, SB);
140 goto pack_s;
141
142 case FOP_FNC_MULx:
143 FP_MUL_S(SR, SA, SB);
144 goto pack_s;
145
146 case FOP_FNC_DIVx:
147 FP_DIV_S(SR, SA, SB);
148 goto pack_s;
149
150 case FOP_FNC_SQRTx:
151 FP_SQRT_S(SR, SB);
152 goto pack_s;
153 }
154 goto bad_insn;
155
156 case FOP_SRC_T:
157 va = alpha_read_fp_reg(fa);
158 vb = alpha_read_fp_reg(fb);
159
160 if ((func & ~3) == FOP_FNC_CMPxUN) {
161 FP_UNPACK_RAW_DP(DA, &va);
162 FP_UNPACK_RAW_DP(DB, &vb);
163 if (!DA_e && !_FP_FRAC_ZEROP_1(DA)) {
164 FP_SET_EXCEPTION(FP_EX_DENORM);
165 if (FP_DENORM_ZERO)
166 _FP_FRAC_SET_1(DA, _FP_ZEROFRAC_1);
167 }
168 if (!DB_e && !_FP_FRAC_ZEROP_1(DB)) {
169 FP_SET_EXCEPTION(FP_EX_DENORM);
170 if (FP_DENORM_ZERO)
171 _FP_FRAC_SET_1(DB, _FP_ZEROFRAC_1);
172 }
173 FP_CMP_D(res, DA, DB, 3);
174 vc = 0x4000000000000000UL;
175 /* CMPTEQ, CMPTUN don't trap on QNaN,
176 while CMPTLT and CMPTLE do */
177 if (res == 3
178 && ((func & 3) >= 2
179 || FP_ISSIGNAN_D(DA)
180 || FP_ISSIGNAN_D(DB))) {
181 FP_SET_EXCEPTION(FP_EX_INVALID);
182 }
183 switch (func) {
184 case FOP_FNC_CMPxUN: if (res != 3) vc = 0; break;
185 case FOP_FNC_CMPxEQ: if (res) vc = 0; break;
186 case FOP_FNC_CMPxLT: if (res != -1) vc = 0; break;
187 case FOP_FNC_CMPxLE: if ((long)res > 0) vc = 0; break;
188 }
189 goto done_d;
190 }
191
192 FP_UNPACK_DP(DA, &va);
193 FP_UNPACK_DP(DB, &vb);
194
195 switch (func) {
196 case FOP_FNC_SUBx:
197 FP_SUB_D(DR, DA, DB);
198 goto pack_d;
199
200 case FOP_FNC_ADDx:
201 FP_ADD_D(DR, DA, DB);
202 goto pack_d;
203
204 case FOP_FNC_MULx:
205 FP_MUL_D(DR, DA, DB);
206 goto pack_d;
207
208 case FOP_FNC_DIVx:
209 FP_DIV_D(DR, DA, DB);
210 goto pack_d;
211
212 case FOP_FNC_SQRTx:
213 FP_SQRT_D(DR, DB);
214 goto pack_d;
215
216 case FOP_FNC_CVTxS:
217 /* It is irritating that DEC encoded CVTST with
218 SRC == T_floating. It is also interesting that
219 the bit used to tell the two apart is /U... */
220 if (insn & 0x2000) {
221 FP_CONV(S,D,1,1,SR,DB);
222 goto pack_s;
223 } else {
224 vb = alpha_read_fp_reg_s(fb);
225 FP_UNPACK_SP(SB, &vb);
226 DR_c = DB_c;
227 DR_s = DB_s;
228 DR_e = DB_e;
229 DR_f = SB_f << (52 - 23);
230 goto pack_d;
231 }
232
233 case FOP_FNC_CVTxQ:
234 if (DB_c == FP_CLS_NAN
235 && (_FP_FRAC_HIGH_RAW_D(DB) & _FP_QNANBIT_D)) {
236 /* AAHB Table B-2 says QNaN should not trigger INV */
237 vc = 0;
238 } else
239 FP_TO_INT_ROUND_D(vc, DB, 64, 2);
240 goto done_d;
241 }
242 goto bad_insn;
243
244 case FOP_SRC_Q:
245 vb = alpha_read_fp_reg(fb);
246
247 switch (func) {
248 case FOP_FNC_CVTQL:
249 /* Notice: We can get here only due to an integer
250 overflow. Such overflows are reported as invalid
251 ops. We return the result the hw would have
252 computed. */
253 vc = ((vb & 0xc0000000) << 32 | /* sign and msb */
254 (vb & 0x3fffffff) << 29); /* rest of the int */
255 FP_SET_EXCEPTION (FP_EX_INVALID);
256 goto done_d;
257
258 case FOP_FNC_CVTxS:
259 FP_FROM_INT_S(SR, ((long)vb), 64, long);
260 goto pack_s;
261
262 case FOP_FNC_CVTxT:
263 FP_FROM_INT_D(DR, ((long)vb), 64, long);
264 goto pack_d;
265 }
266 goto bad_insn;
267 }
268 goto bad_insn;
269
270pack_s:
271 FP_PACK_SP(&vc, SR);
272 if ((_fex & FP_EX_UNDERFLOW) && (swcr & IEEE_MAP_UMZ))
273 vc = 0;
274 alpha_write_fp_reg_s(fc, vc);
275 goto done;
276
277pack_d:
278 FP_PACK_DP(&vc, DR);
279 if ((_fex & FP_EX_UNDERFLOW) && (swcr & IEEE_MAP_UMZ))
280 vc = 0;
281done_d:
282 alpha_write_fp_reg(fc, vc);
283 goto done;
284
285 /*
286 * Take the appropriate action for each possible
287 * floating-point result:
288 *
289 * - Set the appropriate bits in the FPCR
290 * - If the specified exception is enabled in the FPCR,
291 * return. The caller (entArith) will dispatch
292 * the appropriate signal to the translated program.
293 *
294 * In addition, properly track the exception state in software
295 * as described in the Alpha Architecture Handbook section 4.7.7.3.
296 */
297done:
298 if (_fex) {
299 /* Record exceptions in software control word. */
300 swcr |= (_fex << IEEE_STATUS_TO_EXCSUM_SHIFT);
301 current_thread_info()->ieee_state
302 |= (_fex << IEEE_STATUS_TO_EXCSUM_SHIFT);
303
304 /* Update hardware control register. */
305 fpcr &= (~FPCR_MASK | FPCR_DYN_MASK);
306 fpcr |= ieee_swcr_to_fpcr(swcr);
307 wrfpcr(fpcr);
308
309 /* Do we generate a signal? */
310 _fex = _fex & swcr & IEEE_TRAP_ENABLE_MASK;
311 si_code = 0;
312 if (_fex) {
313 if (_fex & IEEE_TRAP_ENABLE_DNO) si_code = FPE_FLTUND;
314 if (_fex & IEEE_TRAP_ENABLE_INE) si_code = FPE_FLTRES;
315 if (_fex & IEEE_TRAP_ENABLE_UNF) si_code = FPE_FLTUND;
316 if (_fex & IEEE_TRAP_ENABLE_OVF) si_code = FPE_FLTOVF;
317 if (_fex & IEEE_TRAP_ENABLE_DZE) si_code = FPE_FLTDIV;
318 if (_fex & IEEE_TRAP_ENABLE_INV) si_code = FPE_FLTINV;
319 }
320
321 return si_code;
322 }
323
324 /* We used to write the destination register here, but DEC FORTRAN
325 requires that the result *always* be written... so we do the write
326 immediately after the operations above. */
327
328 return 0;
329
330bad_insn:
331 printk(KERN_ERR "alpha_fp_emul: Invalid FP insn %#x at %#lx\n",
332 insn, pc);
333 return -1;
334}
335
336long
337alpha_fp_emul_imprecise (struct pt_regs *regs, unsigned long write_mask)
338{
339 unsigned long trigger_pc = regs->pc - 4;
340 unsigned long insn, opcode, rc, si_code = 0;
341
342 /*
343 * Turn off the bits corresponding to registers that are the
344 * target of instructions that set bits in the exception
345 * summary register. We have some slack doing this because a
346 * register that is the target of a trapping instruction can
347 * be written at most once in the trap shadow.
348 *
349 * Branches, jumps, TRAPBs, EXCBs and calls to PALcode all
350 * bound the trap shadow, so we need not look any further than
351 * up to the first occurrence of such an instruction.
352 */
353 while (write_mask) {
354 get_user(insn, (__u32 __user *)(trigger_pc));
355 opcode = insn >> 26;
356 rc = insn & 0x1f;
357
358 switch (opcode) {
359 case OPC_PAL:
360 case OPC_JSR:
361 case 0x30 ... 0x3f: /* branches */
362 goto egress;
363
364 case OPC_MISC:
365 switch (insn & 0xffff) {
366 case MISC_TRAPB:
367 case MISC_EXCB:
368 goto egress;
369
370 default:
371 break;
372 }
373 break;
374
375 case OPC_INTA:
376 case OPC_INTL:
377 case OPC_INTS:
378 case OPC_INTM:
379 write_mask &= ~(1UL << rc);
380 break;
381
382 case OPC_FLTC:
383 case OPC_FLTV:
384 case OPC_FLTI:
385 case OPC_FLTL:
386 write_mask &= ~(1UL << (rc + 32));
387 break;
388 }
389 if (!write_mask) {
390 /* Re-execute insns in the trap-shadow. */
391 regs->pc = trigger_pc + 4;
392 si_code = alpha_fp_emul(trigger_pc);
393 goto egress;
394 }
395 trigger_pc -= 4;
396 }
397
398egress:
399 return si_code;
400}
diff --git a/arch/alpha/math-emu/qrnnd.S b/arch/alpha/math-emu/qrnnd.S
new file mode 100644
index 000000000000..d6373ec1bff9
--- /dev/null
+++ b/arch/alpha/math-emu/qrnnd.S
@@ -0,0 +1,163 @@
1 # Alpha 21064 __udiv_qrnnd
2 # Copyright (C) 1992, 1994, 1995, 2000 Free Software Foundation, Inc.
3
4 # This file is part of GCC.
5
6 # The GNU MP Library is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or (at your
9 # option) any later version.
10
11 # In addition to the permissions in the GNU General Public License, the
12 # Free Software Foundation gives you unlimited permission to link the
13 # compiled version of this file with other programs, and to distribute
14 # those programs without any restriction coming from the use of this
15 # file. (The General Public License restrictions do apply in other
16 # respects; for example, they cover modification of the file, and
17 # distribution when not linked into another program.)
18
19 # This file is distributed in the hope that it will be useful, but
20 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
22 # License for more details.
23
24 # You should have received a copy of the GNU General Public License
25 # along with GCC; see the file COPYING. If not, write to the
26 # Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27 # MA 02111-1307, USA.
28
29 .set noreorder
30 .set noat
31
32 .text
33
34 .globl __udiv_qrnnd
35 .ent __udiv_qrnnd
36__udiv_qrnnd:
37 .frame $30,0,$26,0
38 .prologue 0
39
40#define cnt $2
41#define tmp $3
42#define rem_ptr $16
43#define n1 $17
44#define n0 $18
45#define d $19
46#define qb $20
47#define AT $at
48
49 ldiq cnt,16
50 blt d,$largedivisor
51
52$loop1: cmplt n0,0,tmp
53 addq n1,n1,n1
54 bis n1,tmp,n1
55 addq n0,n0,n0
56 cmpule d,n1,qb
57 subq n1,d,tmp
58 cmovne qb,tmp,n1
59 bis n0,qb,n0
60 cmplt n0,0,tmp
61 addq n1,n1,n1
62 bis n1,tmp,n1
63 addq n0,n0,n0
64 cmpule d,n1,qb
65 subq n1,d,tmp
66 cmovne qb,tmp,n1
67 bis n0,qb,n0
68 cmplt n0,0,tmp
69 addq n1,n1,n1
70 bis n1,tmp,n1
71 addq n0,n0,n0
72 cmpule d,n1,qb
73 subq n1,d,tmp
74 cmovne qb,tmp,n1
75 bis n0,qb,n0
76 cmplt n0,0,tmp
77 addq n1,n1,n1
78 bis n1,tmp,n1
79 addq n0,n0,n0
80 cmpule d,n1,qb
81 subq n1,d,tmp
82 cmovne qb,tmp,n1
83 bis n0,qb,n0
84 subq cnt,1,cnt
85 bgt cnt,$loop1
86 stq n1,0(rem_ptr)
87 bis $31,n0,$0
88 ret $31,($26),1
89
90$largedivisor:
91 and n0,1,$4
92
93 srl n0,1,n0
94 sll n1,63,tmp
95 or tmp,n0,n0
96 srl n1,1,n1
97
98 and d,1,$6
99 srl d,1,$5
100 addq $5,$6,$5
101
102$loop2: cmplt n0,0,tmp
103 addq n1,n1,n1
104 bis n1,tmp,n1
105 addq n0,n0,n0
106 cmpule $5,n1,qb
107 subq n1,$5,tmp
108 cmovne qb,tmp,n1
109 bis n0,qb,n0
110 cmplt n0,0,tmp
111 addq n1,n1,n1
112 bis n1,tmp,n1
113 addq n0,n0,n0
114 cmpule $5,n1,qb
115 subq n1,$5,tmp
116 cmovne qb,tmp,n1
117 bis n0,qb,n0
118 cmplt n0,0,tmp
119 addq n1,n1,n1
120 bis n1,tmp,n1
121 addq n0,n0,n0
122 cmpule $5,n1,qb
123 subq n1,$5,tmp
124 cmovne qb,tmp,n1
125 bis n0,qb,n0
126 cmplt n0,0,tmp
127 addq n1,n1,n1
128 bis n1,tmp,n1
129 addq n0,n0,n0
130 cmpule $5,n1,qb
131 subq n1,$5,tmp
132 cmovne qb,tmp,n1
133 bis n0,qb,n0
134 subq cnt,1,cnt
135 bgt cnt,$loop2
136
137 addq n1,n1,n1
138 addq $4,n1,n1
139 bne $6,$Odd
140 stq n1,0(rem_ptr)
141 bis $31,n0,$0
142 ret $31,($26),1
143
144$Odd:
145 /* q' in n0. r' in n1 */
146 addq n1,n0,n1
147
148 cmpult n1,n0,tmp # tmp := carry from addq
149 subq n1,d,AT
150 addq n0,tmp,n0
151 cmovne tmp,AT,n1
152
153 cmpult n1,d,tmp
154 addq n0,1,AT
155 cmoveq tmp,AT,n0
156 subq n1,d,AT
157 cmoveq tmp,AT,n1
158
159 stq n1,0(rem_ptr)
160 bis $31,n0,$0
161 ret $31,($26),1
162
163 .end __udiv_qrnnd
diff --git a/arch/alpha/math-emu/sfp-util.h b/arch/alpha/math-emu/sfp-util.h
new file mode 100644
index 000000000000..f53707f77455
--- /dev/null
+++ b/arch/alpha/math-emu/sfp-util.h
@@ -0,0 +1,35 @@
1#include <linux/kernel.h>
2#include <linux/sched.h>
3#include <linux/types.h>
4#include <asm/byteorder.h>
5#include <asm/fpu.h>
6
7#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
8 ((sl) = (al) + (bl), (sh) = (ah) + (bh) + ((sl) < (al)))
9
10#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
11 ((sl) = (al) - (bl), (sh) = (ah) - (bh) - ((al) < (bl)))
12
13#define umul_ppmm(wh, wl, u, v) \
14 __asm__ ("mulq %2,%3,%1; umulh %2,%3,%0" \
15 : "=r" ((UDItype)(wh)), \
16 "=&r" ((UDItype)(wl)) \
17 : "r" ((UDItype)(u)), \
18 "r" ((UDItype)(v)))
19
20#define udiv_qrnnd(q, r, n1, n0, d) \
21 do { unsigned long __r; \
22 (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \
23 (r) = __r; \
24 } while (0)
25extern unsigned long __udiv_qrnnd (unsigned long *, unsigned long,
26 unsigned long , unsigned long);
27
28#define UDIV_NEEDS_NORMALIZATION 1
29
30#define abort() goto bad_insn
31
32#ifndef __LITTLE_ENDIAN
33#define __LITTLE_ENDIAN -1
34#endif
35#define __BYTE_ORDER __LITTLE_ENDIAN
diff --git a/arch/alpha/mm/Makefile b/arch/alpha/mm/Makefile
new file mode 100644
index 000000000000..6edd9a09ea4f
--- /dev/null
+++ b/arch/alpha/mm/Makefile
@@ -0,0 +1,9 @@
1#
2# Makefile for the linux alpha-specific parts of the memory manager.
3#
4
5EXTRA_CFLAGS := -Werror
6
7obj-y := init.o fault.o extable.o remap.o
8
9obj-$(CONFIG_DISCONTIGMEM) += numa.o
diff --git a/arch/alpha/mm/extable.c b/arch/alpha/mm/extable.c
new file mode 100644
index 000000000000..c3849baebd57
--- /dev/null
+++ b/arch/alpha/mm/extable.c
@@ -0,0 +1,34 @@
1/*
2 * linux/arch/alpha/mm/extable.c
3 */
4
5#include <linux/config.h>
6#include <linux/module.h>
7#include <asm/uaccess.h>
8
9void sort_extable(struct exception_table_entry *start,
10 struct exception_table_entry *finish)
11{
12}
13
14const struct exception_table_entry *
15search_extable(const struct exception_table_entry *first,
16 const struct exception_table_entry *last,
17 unsigned long value)
18{
19 while (first <= last) {
20 const struct exception_table_entry *mid;
21 unsigned long mid_value;
22
23 mid = (last - first) / 2 + first;
24 mid_value = (unsigned long)&mid->insn + mid->insn;
25 if (mid_value == value)
26 return mid;
27 else if (mid_value < value)
28 first = mid+1;
29 else
30 last = mid-1;
31 }
32
33 return NULL;
34}
diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
new file mode 100644
index 000000000000..64ace5a9cd3d
--- /dev/null
+++ b/arch/alpha/mm/fault.c
@@ -0,0 +1,247 @@
1/*
2 * linux/arch/alpha/mm/fault.c
3 *
4 * Copyright (C) 1995 Linus Torvalds
5 */
6
7#include <linux/config.h>
8#include <linux/sched.h>
9#include <linux/kernel.h>
10#include <linux/mm.h>
11#include <asm/io.h>
12
13#define __EXTERN_INLINE inline
14#include <asm/mmu_context.h>
15#include <asm/tlbflush.h>
16#undef __EXTERN_INLINE
17
18#include <linux/signal.h>
19#include <linux/errno.h>
20#include <linux/string.h>
21#include <linux/types.h>
22#include <linux/ptrace.h>
23#include <linux/mman.h>
24#include <linux/smp.h>
25#include <linux/smp_lock.h>
26#include <linux/interrupt.h>
27#include <linux/module.h>
28
29#include <asm/system.h>
30#include <asm/uaccess.h>
31
32extern void die_if_kernel(char *,struct pt_regs *,long, unsigned long *);
33
34
35/*
36 * Force a new ASN for a task.
37 */
38
39#ifndef CONFIG_SMP
40unsigned long last_asn = ASN_FIRST_VERSION;
41#endif
42
43void
44__load_new_mm_context(struct mm_struct *next_mm)
45{
46 unsigned long mmc;
47 struct pcb_struct *pcb;
48
49 mmc = __get_new_mm_context(next_mm, smp_processor_id());
50 next_mm->context[smp_processor_id()] = mmc;
51
52 pcb = &current_thread_info()->pcb;
53 pcb->asn = mmc & HARDWARE_ASN_MASK;
54 pcb->ptbr = ((unsigned long) next_mm->pgd - IDENT_ADDR) >> PAGE_SHIFT;
55
56 __reload_thread(pcb);
57}
58
59
60/*
61 * This routine handles page faults. It determines the address,
62 * and the problem, and then passes it off to handle_mm_fault().
63 *
64 * mmcsr:
65 * 0 = translation not valid
66 * 1 = access violation
67 * 2 = fault-on-read
68 * 3 = fault-on-execute
69 * 4 = fault-on-write
70 *
71 * cause:
72 * -1 = instruction fetch
73 * 0 = load
74 * 1 = store
75 *
76 * Registers $9 through $15 are saved in a block just prior to `regs' and
77 * are saved and restored around the call to allow exception code to
78 * modify them.
79 */
80
81/* Macro for exception fixup code to access integer registers. */
82#define dpf_reg(r) \
83 (((unsigned long *)regs)[(r) <= 8 ? (r) : (r) <= 15 ? (r)-16 : \
84 (r) <= 18 ? (r)+8 : (r)-10])
85
86asmlinkage void
87do_page_fault(unsigned long address, unsigned long mmcsr,
88 long cause, struct pt_regs *regs)
89{
90 struct vm_area_struct * vma;
91 struct mm_struct *mm = current->mm;
92 const struct exception_table_entry *fixup;
93 int fault, si_code = SEGV_MAPERR;
94 siginfo_t info;
95
96 /* As of EV6, a load into $31/$f31 is a prefetch, and never faults
97 (or is suppressed by the PALcode). Support that for older CPUs
98 by ignoring such an instruction. */
99 if (cause == 0) {
100 unsigned int insn;
101 __get_user(insn, (unsigned int __user *)regs->pc);
102 if ((insn >> 21 & 0x1f) == 0x1f &&
103 /* ldq ldl ldt lds ldg ldf ldwu ldbu */
104 (1ul << (insn >> 26) & 0x30f00001400ul)) {
105 regs->pc += 4;
106 return;
107 }
108 }
109
110 /* If we're in an interrupt context, or have no user context,
111 we must not take the fault. */
112 if (!mm || in_interrupt())
113 goto no_context;
114
115#ifdef CONFIG_ALPHA_LARGE_VMALLOC
116 if (address >= TASK_SIZE)
117 goto vmalloc_fault;
118#endif
119
120 down_read(&mm->mmap_sem);
121 vma = find_vma(mm, address);
122 if (!vma)
123 goto bad_area;
124 if (vma->vm_start <= address)
125 goto good_area;
126 if (!(vma->vm_flags & VM_GROWSDOWN))
127 goto bad_area;
128 if (expand_stack(vma, address))
129 goto bad_area;
130
131 /* Ok, we have a good vm_area for this memory access, so
132 we can handle it. */
133 good_area:
134 si_code = SEGV_ACCERR;
135 if (cause < 0) {
136 if (!(vma->vm_flags & VM_EXEC))
137 goto bad_area;
138 } else if (!cause) {
139 /* Allow reads even for write-only mappings */
140 if (!(vma->vm_flags & (VM_READ | VM_WRITE)))
141 goto bad_area;
142 } else {
143 if (!(vma->vm_flags & VM_WRITE))
144 goto bad_area;
145 }
146
147 survive:
148 /* If for any reason at all we couldn't handle the fault,
149 make sure we exit gracefully rather than endlessly redo
150 the fault. */
151 fault = handle_mm_fault(mm, vma, address, cause > 0);
152 up_read(&mm->mmap_sem);
153
154 switch (fault) {
155 case VM_FAULT_MINOR:
156 current->min_flt++;
157 break;
158 case VM_FAULT_MAJOR:
159 current->maj_flt++;
160 break;
161 case VM_FAULT_SIGBUS:
162 goto do_sigbus;
163 case VM_FAULT_OOM:
164 goto out_of_memory;
165 default:
166 BUG();
167 }
168 return;
169
170 /* Something tried to access memory that isn't in our memory map.
171 Fix it, but check if it's kernel or user first. */
172 bad_area:
173 up_read(&mm->mmap_sem);
174
175 if (user_mode(regs))
176 goto do_sigsegv;
177
178 no_context:
179 /* Are we prepared to handle this fault as an exception? */
180 if ((fixup = search_exception_tables(regs->pc)) != 0) {
181 unsigned long newpc;
182 newpc = fixup_exception(dpf_reg, fixup, regs->pc);
183 regs->pc = newpc;
184 return;
185 }
186
187 /* Oops. The kernel tried to access some bad page. We'll have to
188 terminate things with extreme prejudice. */
189 printk(KERN_ALERT "Unable to handle kernel paging request at "
190 "virtual address %016lx\n", address);
191 die_if_kernel("Oops", regs, cause, (unsigned long*)regs - 16);
192 do_exit(SIGKILL);
193
194 /* We ran out of memory, or some other thing happened to us that
195 made us unable to handle the page fault gracefully. */
196 out_of_memory:
197 if (current->pid == 1) {
198 yield();
199 down_read(&mm->mmap_sem);
200 goto survive;
201 }
202 printk(KERN_ALERT "VM: killing process %s(%d)\n",
203 current->comm, current->pid);
204 if (!user_mode(regs))
205 goto no_context;
206 do_exit(SIGKILL);
207
208 do_sigbus:
209 /* Send a sigbus, regardless of whether we were in kernel
210 or user mode. */
211 info.si_signo = SIGBUS;
212 info.si_errno = 0;
213 info.si_code = BUS_ADRERR;
214 info.si_addr = (void __user *) address;
215 force_sig_info(SIGBUS, &info, current);
216 if (!user_mode(regs))
217 goto no_context;
218 return;
219
220 do_sigsegv:
221 info.si_signo = SIGSEGV;
222 info.si_errno = 0;
223 info.si_code = si_code;
224 info.si_addr = (void __user *) address;
225 force_sig_info(SIGSEGV, &info, current);
226 return;
227
228#ifdef CONFIG_ALPHA_LARGE_VMALLOC
229 vmalloc_fault:
230 if (user_mode(regs))
231 goto do_sigsegv;
232 else {
233 /* Synchronize this task's top level page-table
234 with the "reference" page table from init. */
235 long index = pgd_index(address);
236 pgd_t *pgd, *pgd_k;
237
238 pgd = current->active_mm->pgd + index;
239 pgd_k = swapper_pg_dir + index;
240 if (!pgd_present(*pgd) && pgd_present(*pgd_k)) {
241 pgd_val(*pgd) = pgd_val(*pgd_k);
242 return;
243 }
244 goto no_context;
245 }
246#endif
247}
diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c
new file mode 100644
index 000000000000..90752f6d8867
--- /dev/null
+++ b/arch/alpha/mm/init.c
@@ -0,0 +1,382 @@
1/*
2 * linux/arch/alpha/mm/init.c
3 *
4 * Copyright (C) 1995 Linus Torvalds
5 */
6
7/* 2.3.x zone allocator, 1999 Andrea Arcangeli <andrea@suse.de> */
8
9#include <linux/config.h>
10#include <linux/signal.h>
11#include <linux/sched.h>
12#include <linux/kernel.h>
13#include <linux/errno.h>
14#include <linux/string.h>
15#include <linux/types.h>
16#include <linux/ptrace.h>
17#include <linux/mman.h>
18#include <linux/mm.h>
19#include <linux/swap.h>
20#include <linux/init.h>
21#include <linux/bootmem.h> /* max_low_pfn */
22#include <linux/vmalloc.h>
23
24#include <asm/system.h>
25#include <asm/uaccess.h>
26#include <asm/pgtable.h>
27#include <asm/pgalloc.h>
28#include <asm/hwrpb.h>
29#include <asm/dma.h>
30#include <asm/mmu_context.h>
31#include <asm/console.h>
32#include <asm/tlb.h>
33
34DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
35
36extern void die_if_kernel(char *,struct pt_regs *,long);
37
38static struct pcb_struct original_pcb;
39
40pgd_t *
41pgd_alloc(struct mm_struct *mm)
42{
43 pgd_t *ret, *init;
44
45 ret = (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
46 init = pgd_offset(&init_mm, 0UL);
47 if (ret) {
48#ifdef CONFIG_ALPHA_LARGE_VMALLOC
49 memcpy (ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
50 (PTRS_PER_PGD - USER_PTRS_PER_PGD - 1)*sizeof(pgd_t));
51#else
52 pgd_val(ret[PTRS_PER_PGD-2]) = pgd_val(init[PTRS_PER_PGD-2]);
53#endif
54
55 /* The last PGD entry is the VPTB self-map. */
56 pgd_val(ret[PTRS_PER_PGD-1])
57 = pte_val(mk_pte(virt_to_page(ret), PAGE_KERNEL));
58 }
59 return ret;
60}
61
62pte_t *
63pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
64{
65 pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
66 return pte;
67}
68
69
70/*
71 * BAD_PAGE is the page that is used for page faults when linux
72 * is out-of-memory. Older versions of linux just did a
73 * do_exit(), but using this instead means there is less risk
74 * for a process dying in kernel mode, possibly leaving an inode
75 * unused etc..
76 *
77 * BAD_PAGETABLE is the accompanying page-table: it is initialized
78 * to point to BAD_PAGE entries.
79 *
80 * ZERO_PAGE is a special page that is used for zero-initialized
81 * data and COW.
82 */
83pmd_t *
84__bad_pagetable(void)
85{
86 memset((void *) EMPTY_PGT, 0, PAGE_SIZE);
87 return (pmd_t *) EMPTY_PGT;
88}
89
90pte_t
91__bad_page(void)
92{
93 memset((void *) EMPTY_PGE, 0, PAGE_SIZE);
94 return pte_mkdirty(mk_pte(virt_to_page(EMPTY_PGE), PAGE_SHARED));
95}
96
97#ifndef CONFIG_DISCONTIGMEM
98void
99show_mem(void)
100{
101 long i,free = 0,total = 0,reserved = 0;
102 long shared = 0, cached = 0;
103
104 printk("\nMem-info:\n");
105 show_free_areas();
106 printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
107 i = max_mapnr;
108 while (i-- > 0) {
109 total++;
110 if (PageReserved(mem_map+i))
111 reserved++;
112 else if (PageSwapCache(mem_map+i))
113 cached++;
114 else if (!page_count(mem_map+i))
115 free++;
116 else
117 shared += page_count(mem_map + i) - 1;
118 }
119 printk("%ld pages of RAM\n",total);
120 printk("%ld free pages\n",free);
121 printk("%ld reserved pages\n",reserved);
122 printk("%ld pages shared\n",shared);
123 printk("%ld pages swap cached\n",cached);
124}
125#endif
126
127static inline unsigned long
128load_PCB(struct pcb_struct *pcb)
129{
130 register unsigned long sp __asm__("$30");
131 pcb->ksp = sp;
132 return __reload_thread(pcb);
133}
134
135/* Set up initial PCB, VPTB, and other such nicities. */
136
137static inline void
138switch_to_system_map(void)
139{
140 unsigned long newptbr;
141 unsigned long original_pcb_ptr;
142
143 /* Initialize the kernel's page tables. Linux puts the vptb in
144 the last slot of the L1 page table. */
145 memset(swapper_pg_dir, 0, PAGE_SIZE);
146 newptbr = ((unsigned long) swapper_pg_dir - PAGE_OFFSET) >> PAGE_SHIFT;
147 pgd_val(swapper_pg_dir[1023]) =
148 (newptbr << 32) | pgprot_val(PAGE_KERNEL);
149
150 /* Set the vptb. This is often done by the bootloader, but
151 shouldn't be required. */
152 if (hwrpb->vptb != 0xfffffffe00000000UL) {
153 wrvptptr(0xfffffffe00000000UL);
154 hwrpb->vptb = 0xfffffffe00000000UL;
155 hwrpb_update_checksum(hwrpb);
156 }
157
158 /* Also set up the real kernel PCB while we're at it. */
159 init_thread_info.pcb.ptbr = newptbr;
160 init_thread_info.pcb.flags = 1; /* set FEN, clear everything else */
161 original_pcb_ptr = load_PCB(&init_thread_info.pcb);
162 tbia();
163
164 /* Save off the contents of the original PCB so that we can
165 restore the original console's page tables for a clean reboot.
166
167 Note that the PCB is supposed to be a physical address, but
168 since KSEG values also happen to work, folks get confused.
169 Check this here. */
170
171 if (original_pcb_ptr < PAGE_OFFSET) {
172 original_pcb_ptr = (unsigned long)
173 phys_to_virt(original_pcb_ptr);
174 }
175 original_pcb = *(struct pcb_struct *) original_pcb_ptr;
176}
177
178int callback_init_done;
179
180void * __init
181callback_init(void * kernel_end)
182{
183 struct crb_struct * crb;
184 pgd_t *pgd;
185 pmd_t *pmd;
186 void *two_pages;
187
188 /* Starting at the HWRPB, locate the CRB. */
189 crb = (struct crb_struct *)((char *)hwrpb + hwrpb->crb_offset);
190
191 if (alpha_using_srm) {
192 /* Tell the console whither it is to be remapped. */
193 if (srm_fixup(VMALLOC_START, (unsigned long)hwrpb))
194 __halt(); /* "We're boned." --Bender */
195
196 /* Edit the procedure descriptors for DISPATCH and FIXUP. */
197 crb->dispatch_va = (struct procdesc_struct *)
198 (VMALLOC_START + (unsigned long)crb->dispatch_va
199 - crb->map[0].va);
200 crb->fixup_va = (struct procdesc_struct *)
201 (VMALLOC_START + (unsigned long)crb->fixup_va
202 - crb->map[0].va);
203 }
204
205 switch_to_system_map();
206
207 /* Allocate one PGD and one PMD. In the case of SRM, we'll need
208 these to actually remap the console. There is an assumption
209 here that only one of each is needed, and this allows for 8MB.
210 On systems with larger consoles, additional pages will be
211 allocated as needed during the mapping process.
212
213 In the case of not SRM, but not CONFIG_ALPHA_LARGE_VMALLOC,
214 we need to allocate the PGD we use for vmalloc before we start
215 forking other tasks. */
216
217 two_pages = (void *)
218 (((unsigned long)kernel_end + ~PAGE_MASK) & PAGE_MASK);
219 kernel_end = two_pages + 2*PAGE_SIZE;
220 memset(two_pages, 0, 2*PAGE_SIZE);
221
222 pgd = pgd_offset_k(VMALLOC_START);
223 pgd_set(pgd, (pmd_t *)two_pages);
224 pmd = pmd_offset(pgd, VMALLOC_START);
225 pmd_set(pmd, (pte_t *)(two_pages + PAGE_SIZE));
226
227 if (alpha_using_srm) {
228 static struct vm_struct console_remap_vm;
229 unsigned long vaddr = VMALLOC_START;
230 unsigned long i, j;
231
232 /* Set up the third level PTEs and update the virtual
233 addresses of the CRB entries. */
234 for (i = 0; i < crb->map_entries; ++i) {
235 unsigned long pfn = crb->map[i].pa >> PAGE_SHIFT;
236 crb->map[i].va = vaddr;
237 for (j = 0; j < crb->map[i].count; ++j) {
238 /* Newer console's (especially on larger
239 systems) may require more pages of
240 PTEs. Grab additional pages as needed. */
241 if (pmd != pmd_offset(pgd, vaddr)) {
242 memset(kernel_end, 0, PAGE_SIZE);
243 pmd = pmd_offset(pgd, vaddr);
244 pmd_set(pmd, (pte_t *)kernel_end);
245 kernel_end += PAGE_SIZE;
246 }
247 set_pte(pte_offset_kernel(pmd, vaddr),
248 pfn_pte(pfn, PAGE_KERNEL));
249 pfn++;
250 vaddr += PAGE_SIZE;
251 }
252 }
253
254 /* Let vmalloc know that we've allocated some space. */
255 console_remap_vm.flags = VM_ALLOC;
256 console_remap_vm.addr = (void *) VMALLOC_START;
257 console_remap_vm.size = vaddr - VMALLOC_START;
258 vmlist = &console_remap_vm;
259 }
260
261 callback_init_done = 1;
262 return kernel_end;
263}
264
265
266#ifndef CONFIG_DISCONTIGMEM
267/*
268 * paging_init() sets up the memory map.
269 */
270void
271paging_init(void)
272{
273 unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
274 unsigned long dma_pfn, high_pfn;
275
276 dma_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
277 high_pfn = max_pfn = max_low_pfn;
278
279 if (dma_pfn >= high_pfn)
280 zones_size[ZONE_DMA] = high_pfn;
281 else {
282 zones_size[ZONE_DMA] = dma_pfn;
283 zones_size[ZONE_NORMAL] = high_pfn - dma_pfn;
284 }
285
286 /* Initialize mem_map[]. */
287 free_area_init(zones_size);
288
289 /* Initialize the kernel's ZERO_PGE. */
290 memset((void *)ZERO_PGE, 0, PAGE_SIZE);
291}
292#endif /* CONFIG_DISCONTIGMEM */
293
294#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM)
295void
296srm_paging_stop (void)
297{
298 /* Move the vptb back to where the SRM console expects it. */
299 swapper_pg_dir[1] = swapper_pg_dir[1023];
300 tbia();
301 wrvptptr(0x200000000UL);
302 hwrpb->vptb = 0x200000000UL;
303 hwrpb_update_checksum(hwrpb);
304
305 /* Reload the page tables that the console had in use. */
306 load_PCB(&original_pcb);
307 tbia();
308}
309#endif
310
311#ifndef CONFIG_DISCONTIGMEM
312static void __init
313printk_memory_info(void)
314{
315 unsigned long codesize, reservedpages, datasize, initsize, tmp;
316 extern int page_is_ram(unsigned long) __init;
317 extern char _text, _etext, _data, _edata;
318 extern char __init_begin, __init_end;
319
320 /* printk all informations */
321 reservedpages = 0;
322 for (tmp = 0; tmp < max_low_pfn; tmp++)
323 /*
324 * Only count reserved RAM pages
325 */
326 if (page_is_ram(tmp) && PageReserved(mem_map+tmp))
327 reservedpages++;
328
329 codesize = (unsigned long) &_etext - (unsigned long) &_text;
330 datasize = (unsigned long) &_edata - (unsigned long) &_data;
331 initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
332
333 printk("Memory: %luk/%luk available (%luk kernel code, %luk reserved, %luk data, %luk init)\n",
334 (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
335 max_mapnr << (PAGE_SHIFT-10),
336 codesize >> 10,
337 reservedpages << (PAGE_SHIFT-10),
338 datasize >> 10,
339 initsize >> 10);
340}
341
342void __init
343mem_init(void)
344{
345 max_mapnr = num_physpages = max_low_pfn;
346 totalram_pages += free_all_bootmem();
347 high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
348
349 printk_memory_info();
350}
351#endif /* CONFIG_DISCONTIGMEM */
352
353void
354free_reserved_mem(void *start, void *end)
355{
356 void *__start = start;
357 for (; __start < end; __start += PAGE_SIZE) {
358 ClearPageReserved(virt_to_page(__start));
359 set_page_count(virt_to_page(__start), 1);
360 free_page((long)__start);
361 totalram_pages++;
362 }
363}
364
365void
366free_initmem(void)
367{
368 extern char __init_begin, __init_end;
369
370 free_reserved_mem(&__init_begin, &__init_end);
371 printk ("Freeing unused kernel memory: %ldk freed\n",
372 (&__init_end - &__init_begin) >> 10);
373}
374
375#ifdef CONFIG_BLK_DEV_INITRD
376void
377free_initrd_mem(unsigned long start, unsigned long end)
378{
379 free_reserved_mem((void *)start, (void *)end);
380 printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
381}
382#endif
diff --git a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c
new file mode 100644
index 000000000000..ba81c4422aaf
--- /dev/null
+++ b/arch/alpha/mm/numa.c
@@ -0,0 +1,395 @@
1/*
2 * linux/arch/alpha/mm/numa.c
3 *
4 * DISCONTIGMEM NUMA alpha support.
5 *
6 * Copyright (C) 2001 Andrea Arcangeli <andrea@suse.de> SuSE
7 */
8
9#include <linux/config.h>
10#include <linux/types.h>
11#include <linux/kernel.h>
12#include <linux/mm.h>
13#include <linux/bootmem.h>
14#include <linux/swap.h>
15#include <linux/initrd.h>
16
17#include <asm/hwrpb.h>
18#include <asm/pgalloc.h>
19
20pg_data_t node_data[MAX_NUMNODES];
21bootmem_data_t node_bdata[MAX_NUMNODES];
22
23#undef DEBUG_DISCONTIG
24#ifdef DEBUG_DISCONTIG
25#define DBGDCONT(args...) printk(args)
26#else
27#define DBGDCONT(args...)
28#endif
29
30#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
31#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
32#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
33#define for_each_mem_cluster(memdesc, cluster, i) \
34 for ((cluster) = (memdesc)->cluster, (i) = 0; \
35 (i) < (memdesc)->numclusters; (i)++, (cluster)++)
36
37static void __init show_mem_layout(void)
38{
39 struct memclust_struct * cluster;
40 struct memdesc_struct * memdesc;
41 int i;
42
43 /* Find free clusters, and init and free the bootmem accordingly. */
44 memdesc = (struct memdesc_struct *)
45 (hwrpb->mddt_offset + (unsigned long) hwrpb);
46
47 printk("Raw memory layout:\n");
48 for_each_mem_cluster(memdesc, cluster, i) {
49 printk(" memcluster %2d, usage %1lx, start %8lu, end %8lu\n",
50 i, cluster->usage, cluster->start_pfn,
51 cluster->start_pfn + cluster->numpages);
52 }
53}
54
55static void __init
56setup_memory_node(int nid, void *kernel_end)
57{
58 extern unsigned long mem_size_limit;
59 struct memclust_struct * cluster;
60 struct memdesc_struct * memdesc;
61 unsigned long start_kernel_pfn, end_kernel_pfn;
62 unsigned long bootmap_size, bootmap_pages, bootmap_start;
63 unsigned long start, end;
64 unsigned long node_pfn_start, node_pfn_end;
65 unsigned long node_min_pfn, node_max_pfn;
66 int i;
67 unsigned long node_datasz = PFN_UP(sizeof(pg_data_t));
68 int show_init = 0;
69
70 /* Find the bounds of current node */
71 node_pfn_start = (node_mem_start(nid)) >> PAGE_SHIFT;
72 node_pfn_end = node_pfn_start + (node_mem_size(nid) >> PAGE_SHIFT);
73
74 /* Find free clusters, and init and free the bootmem accordingly. */
75 memdesc = (struct memdesc_struct *)
76 (hwrpb->mddt_offset + (unsigned long) hwrpb);
77
78 /* find the bounds of this node (node_min_pfn/node_max_pfn) */
79 node_min_pfn = ~0UL;
80 node_max_pfn = 0UL;
81 for_each_mem_cluster(memdesc, cluster, i) {
82 /* Bit 0 is console/PALcode reserved. Bit 1 is
83 non-volatile memory -- we might want to mark
84 this for later. */
85 if (cluster->usage & 3)
86 continue;
87
88 start = cluster->start_pfn;
89 end = start + cluster->numpages;
90
91 if (start >= node_pfn_end || end <= node_pfn_start)
92 continue;
93
94 if (!show_init) {
95 show_init = 1;
96 printk("Initializing bootmem allocator on Node ID %d\n", nid);
97 }
98 printk(" memcluster %2d, usage %1lx, start %8lu, end %8lu\n",
99 i, cluster->usage, cluster->start_pfn,
100 cluster->start_pfn + cluster->numpages);
101
102 if (start < node_pfn_start)
103 start = node_pfn_start;
104 if (end > node_pfn_end)
105 end = node_pfn_end;
106
107 if (start < node_min_pfn)
108 node_min_pfn = start;
109 if (end > node_max_pfn)
110 node_max_pfn = end;
111 }
112
113 if (mem_size_limit && node_max_pfn > mem_size_limit) {
114 static int msg_shown = 0;
115 if (!msg_shown) {
116 msg_shown = 1;
117 printk("setup: forcing memory size to %ldK (from %ldK).\n",
118 mem_size_limit << (PAGE_SHIFT - 10),
119 node_max_pfn << (PAGE_SHIFT - 10));
120 }
121 node_max_pfn = mem_size_limit;
122 }
123
124 if (node_min_pfn >= node_max_pfn)
125 return;
126
127 /* Update global {min,max}_low_pfn from node information. */
128 if (node_min_pfn < min_low_pfn)
129 min_low_pfn = node_min_pfn;
130 if (node_max_pfn > max_low_pfn)
131 max_pfn = max_low_pfn = node_max_pfn;
132
133 num_physpages += node_max_pfn - node_min_pfn;
134
135#if 0 /* we'll try this one again in a little while */
136 /* Cute trick to make sure our local node data is on local memory */
137 node_data[nid] = (pg_data_t *)(__va(node_min_pfn << PAGE_SHIFT));
138#endif
139 /* Quasi-mark the pg_data_t as in-use */
140 node_min_pfn += node_datasz;
141 if (node_min_pfn >= node_max_pfn) {
142 printk(" not enough mem to reserve NODE_DATA");
143 return;
144 }
145 NODE_DATA(nid)->bdata = &node_bdata[nid];
146
147 printk(" Detected node memory: start %8lu, end %8lu\n",
148 node_min_pfn, node_max_pfn);
149
150 DBGDCONT(" DISCONTIG: node_data[%d] is at 0x%p\n", nid, NODE_DATA(nid));
151 DBGDCONT(" DISCONTIG: NODE_DATA(%d)->bdata is at 0x%p\n", nid, NODE_DATA(nid)->bdata);
152
153 /* Find the bounds of kernel memory. */
154 start_kernel_pfn = PFN_DOWN(KERNEL_START_PHYS);
155 end_kernel_pfn = PFN_UP(virt_to_phys(kernel_end));
156 bootmap_start = -1;
157
158 if (!nid && (node_max_pfn < end_kernel_pfn || node_min_pfn > start_kernel_pfn))
159 panic("kernel loaded out of ram");
160
161 /* Zone start phys-addr must be 2^(MAX_ORDER-1) aligned.
162 Note that we round this down, not up - node memory
163 has much larger alignment than 8Mb, so it's safe. */
164 node_min_pfn &= ~((1UL << (MAX_ORDER-1))-1);
165
166 /* We need to know how many physically contiguous pages
167 we'll need for the bootmap. */
168 bootmap_pages = bootmem_bootmap_pages(node_max_pfn-node_min_pfn);
169
170 /* Now find a good region where to allocate the bootmap. */
171 for_each_mem_cluster(memdesc, cluster, i) {
172 if (cluster->usage & 3)
173 continue;
174
175 start = cluster->start_pfn;
176 end = start + cluster->numpages;
177
178 if (start >= node_max_pfn || end <= node_min_pfn)
179 continue;
180
181 if (end > node_max_pfn)
182 end = node_max_pfn;
183 if (start < node_min_pfn)
184 start = node_min_pfn;
185
186 if (start < start_kernel_pfn) {
187 if (end > end_kernel_pfn
188 && end - end_kernel_pfn >= bootmap_pages) {
189 bootmap_start = end_kernel_pfn;
190 break;
191 } else if (end > start_kernel_pfn)
192 end = start_kernel_pfn;
193 } else if (start < end_kernel_pfn)
194 start = end_kernel_pfn;
195 if (end - start >= bootmap_pages) {
196 bootmap_start = start;
197 break;
198 }
199 }
200
201 if (bootmap_start == -1)
202 panic("couldn't find a contigous place for the bootmap");
203
204 /* Allocate the bootmap and mark the whole MM as reserved. */
205 bootmap_size = init_bootmem_node(NODE_DATA(nid), bootmap_start,
206 node_min_pfn, node_max_pfn);
207 DBGDCONT(" bootmap_start %lu, bootmap_size %lu, bootmap_pages %lu\n",
208 bootmap_start, bootmap_size, bootmap_pages);
209
210 /* Mark the free regions. */
211 for_each_mem_cluster(memdesc, cluster, i) {
212 if (cluster->usage & 3)
213 continue;
214
215 start = cluster->start_pfn;
216 end = cluster->start_pfn + cluster->numpages;
217
218 if (start >= node_max_pfn || end <= node_min_pfn)
219 continue;
220
221 if (end > node_max_pfn)
222 end = node_max_pfn;
223 if (start < node_min_pfn)
224 start = node_min_pfn;
225
226 if (start < start_kernel_pfn) {
227 if (end > end_kernel_pfn) {
228 free_bootmem_node(NODE_DATA(nid), PFN_PHYS(start),
229 (PFN_PHYS(start_kernel_pfn)
230 - PFN_PHYS(start)));
231 printk(" freeing pages %ld:%ld\n",
232 start, start_kernel_pfn);
233 start = end_kernel_pfn;
234 } else if (end > start_kernel_pfn)
235 end = start_kernel_pfn;
236 } else if (start < end_kernel_pfn)
237 start = end_kernel_pfn;
238 if (start >= end)
239 continue;
240
241 free_bootmem_node(NODE_DATA(nid), PFN_PHYS(start), PFN_PHYS(end) - PFN_PHYS(start));
242 printk(" freeing pages %ld:%ld\n", start, end);
243 }
244
245 /* Reserve the bootmap memory. */
246 reserve_bootmem_node(NODE_DATA(nid), PFN_PHYS(bootmap_start), bootmap_size);
247 printk(" reserving pages %ld:%ld\n", bootmap_start, bootmap_start+PFN_UP(bootmap_size));
248
249 node_set_online(nid);
250}
251
252void __init
253setup_memory(void *kernel_end)
254{
255 int nid;
256
257 show_mem_layout();
258
259 nodes_clear(node_online_map);
260
261 min_low_pfn = ~0UL;
262 max_low_pfn = 0UL;
263 for (nid = 0; nid < MAX_NUMNODES; nid++)
264 setup_memory_node(nid, kernel_end);
265
266#ifdef CONFIG_BLK_DEV_INITRD
267 initrd_start = INITRD_START;
268 if (initrd_start) {
269 extern void *move_initrd(unsigned long);
270
271 initrd_end = initrd_start+INITRD_SIZE;
272 printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
273 (void *) initrd_start, INITRD_SIZE);
274
275 if ((void *)initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) {
276 if (!move_initrd(PFN_PHYS(max_low_pfn)))
277 printk("initrd extends beyond end of memory "
278 "(0x%08lx > 0x%p)\ndisabling initrd\n",
279 initrd_end,
280 phys_to_virt(PFN_PHYS(max_low_pfn)));
281 } else {
282 nid = kvaddr_to_nid(initrd_start);
283 reserve_bootmem_node(NODE_DATA(nid),
284 virt_to_phys((void *)initrd_start),
285 INITRD_SIZE);
286 }
287 }
288#endif /* CONFIG_BLK_DEV_INITRD */
289}
290
291void __init paging_init(void)
292{
293 unsigned int nid;
294 unsigned long zones_size[MAX_NR_ZONES] = {0, };
295 unsigned long dma_local_pfn;
296
297 /*
298 * The old global MAX_DMA_ADDRESS per-arch API doesn't fit
299 * in the NUMA model, for now we convert it to a pfn and
300 * we interpret this pfn as a local per-node information.
301 * This issue isn't very important since none of these machines
302 * have legacy ISA slots anyways.
303 */
304 dma_local_pfn = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
305
306 for_each_online_node(nid) {
307 unsigned long start_pfn = node_bdata[nid].node_boot_start >> PAGE_SHIFT;
308 unsigned long end_pfn = node_bdata[nid].node_low_pfn;
309
310 if (dma_local_pfn >= end_pfn - start_pfn)
311 zones_size[ZONE_DMA] = end_pfn - start_pfn;
312 else {
313 zones_size[ZONE_DMA] = dma_local_pfn;
314 zones_size[ZONE_NORMAL] = (end_pfn - start_pfn) - dma_local_pfn;
315 }
316 free_area_init_node(nid, NODE_DATA(nid), zones_size, start_pfn, NULL);
317 }
318
319 /* Initialize the kernel's ZERO_PGE. */
320 memset((void *)ZERO_PGE, 0, PAGE_SIZE);
321}
322
323void __init mem_init(void)
324{
325 unsigned long codesize, reservedpages, datasize, initsize, pfn;
326 extern int page_is_ram(unsigned long) __init;
327 extern char _text, _etext, _data, _edata;
328 extern char __init_begin, __init_end;
329 unsigned long nid, i;
330 struct page * lmem_map;
331
332 high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
333
334 reservedpages = 0;
335 for_each_online_node(nid) {
336 /*
337 * This will free up the bootmem, ie, slot 0 memory
338 */
339 totalram_pages += free_all_bootmem_node(NODE_DATA(nid));
340
341 lmem_map = node_mem_map(nid);
342 pfn = NODE_DATA(nid)->node_start_pfn;
343 for (i = 0; i < node_spanned_pages(nid); i++, pfn++)
344 if (page_is_ram(pfn) && PageReserved(lmem_map+i))
345 reservedpages++;
346 }
347
348 codesize = (unsigned long) &_etext - (unsigned long) &_text;
349 datasize = (unsigned long) &_edata - (unsigned long) &_data;
350 initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
351
352 printk("Memory: %luk/%luk available (%luk kernel code, %luk reserved, "
353 "%luk data, %luk init)\n",
354 (unsigned long)nr_free_pages() << (PAGE_SHIFT-10),
355 num_physpages << (PAGE_SHIFT-10),
356 codesize >> 10,
357 reservedpages << (PAGE_SHIFT-10),
358 datasize >> 10,
359 initsize >> 10);
360#if 0
361 mem_stress();
362#endif
363}
364
365void
366show_mem(void)
367{
368 long i,free = 0,total = 0,reserved = 0;
369 long shared = 0, cached = 0;
370 int nid;
371
372 printk("\nMem-info:\n");
373 show_free_areas();
374 printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
375 for_each_online_node(nid) {
376 struct page * lmem_map = node_mem_map(nid);
377 i = node_spanned_pages(nid);
378 while (i-- > 0) {
379 total++;
380 if (PageReserved(lmem_map+i))
381 reserved++;
382 else if (PageSwapCache(lmem_map+i))
383 cached++;
384 else if (!page_count(lmem_map+i))
385 free++;
386 else
387 shared += page_count(lmem_map + i) - 1;
388 }
389 }
390 printk("%ld pages of RAM\n",total);
391 printk("%ld free pages\n",free);
392 printk("%ld reserved pages\n",reserved);
393 printk("%ld pages shared\n",shared);
394 printk("%ld pages swap cached\n",cached);
395}
diff --git a/arch/alpha/mm/remap.c b/arch/alpha/mm/remap.c
new file mode 100644
index 000000000000..19817ad3d89b
--- /dev/null
+++ b/arch/alpha/mm/remap.c
@@ -0,0 +1,90 @@
1#include <linux/vmalloc.h>
2#include <asm/pgalloc.h>
3#include <asm/cacheflush.h>
4
5/* called with the page_table_lock held */
6static inline void
7remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
8 unsigned long phys_addr, unsigned long flags)
9{
10 unsigned long end;
11 unsigned long pfn;
12
13 address &= ~PMD_MASK;
14 end = address + size;
15 if (end > PMD_SIZE)
16 end = PMD_SIZE;
17 if (address >= end)
18 BUG();
19 pfn = phys_addr >> PAGE_SHIFT;
20 do {
21 if (!pte_none(*pte)) {
22 printk("remap_area_pte: page already exists\n");
23 BUG();
24 }
25 set_pte(pte, pfn_pte(pfn,
26 __pgprot(_PAGE_VALID | _PAGE_ASM |
27 _PAGE_KRE | _PAGE_KWE | flags)));
28 address += PAGE_SIZE;
29 pfn++;
30 pte++;
31 } while (address && (address < end));
32}
33
34/* called with the page_table_lock held */
35static inline int
36remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
37 unsigned long phys_addr, unsigned long flags)
38{
39 unsigned long end;
40
41 address &= ~PGDIR_MASK;
42 end = address + size;
43 if (end > PGDIR_SIZE)
44 end = PGDIR_SIZE;
45 phys_addr -= address;
46 if (address >= end)
47 BUG();
48 do {
49 pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
50 if (!pte)
51 return -ENOMEM;
52 remap_area_pte(pte, address, end - address,
53 address + phys_addr, flags);
54 address = (address + PMD_SIZE) & PMD_MASK;
55 pmd++;
56 } while (address && (address < end));
57 return 0;
58}
59
60int
61__alpha_remap_area_pages(unsigned long address, unsigned long phys_addr,
62 unsigned long size, unsigned long flags)
63{
64 pgd_t * dir;
65 int error = 0;
66 unsigned long end = address + size;
67
68 phys_addr -= address;
69 dir = pgd_offset(&init_mm, address);
70 flush_cache_all();
71 if (address >= end)
72 BUG();
73 spin_lock(&init_mm.page_table_lock);
74 do {
75 pmd_t *pmd;
76 pmd = pmd_alloc(&init_mm, dir, address);
77 error = -ENOMEM;
78 if (!pmd)
79 break;
80 if (remap_area_pmd(pmd, address, end - address,
81 phys_addr + address, flags))
82 break;
83 error = 0;
84 address = (address + PGDIR_SIZE) & PGDIR_MASK;
85 dir++;
86 } while (address && (address < end));
87 spin_unlock(&init_mm.page_table_lock);
88 return error;
89}
90
diff --git a/arch/alpha/oprofile/Kconfig b/arch/alpha/oprofile/Kconfig
new file mode 100644
index 000000000000..5ade19801b97
--- /dev/null
+++ b/arch/alpha/oprofile/Kconfig
@@ -0,0 +1,23 @@
1
2menu "Profiling support"
3 depends on EXPERIMENTAL
4
5config PROFILING
6 bool "Profiling support (EXPERIMENTAL)"
7 help
8 Say Y here to enable the extended profiling support mechanisms used
9 by profilers such as OProfile.
10
11
12config OPROFILE
13 tristate "OProfile system profiling (EXPERIMENTAL)"
14 depends on PROFILING
15 help
16 OProfile is a profiling system capable of profiling the
17 whole system, include the kernel, kernel modules, libraries,
18 and applications.
19
20 If unsure, say N.
21
22endmenu
23
diff --git a/arch/alpha/oprofile/Makefile b/arch/alpha/oprofile/Makefile
new file mode 100644
index 000000000000..4aa56247bdc6
--- /dev/null
+++ b/arch/alpha/oprofile/Makefile
@@ -0,0 +1,19 @@
1EXTRA_CFLAGS := -Werror -Wno-sign-compare
2
3obj-$(CONFIG_OPROFILE) += oprofile.o
4
5DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
6 oprof.o cpu_buffer.o buffer_sync.o \
7 event_buffer.o oprofile_files.o \
8 oprofilefs.o oprofile_stats.o \
9 timer_int.o )
10
11oprofile-y := $(DRIVER_OBJS) common.o
12oprofile-$(CONFIG_ALPHA_GENERIC) += op_model_ev4.o \
13 op_model_ev5.o \
14 op_model_ev6.o \
15 op_model_ev67.o
16oprofile-$(CONFIG_ALPHA_EV4) += op_model_ev4.o
17oprofile-$(CONFIG_ALPHA_EV5) += op_model_ev5.o
18oprofile-$(CONFIG_ALPHA_EV6) += op_model_ev6.o \
19 op_model_ev67.o
diff --git a/arch/alpha/oprofile/common.c b/arch/alpha/oprofile/common.c
new file mode 100644
index 000000000000..908eb4af8dec
--- /dev/null
+++ b/arch/alpha/oprofile/common.c
@@ -0,0 +1,189 @@
1/**
2 * @file arch/alpha/oprofile/common.c
3 *
4 * @remark Copyright 2002 OProfile authors
5 * @remark Read the file COPYING
6 *
7 * @author Richard Henderson <rth@twiddle.net>
8 */
9
10#include <linux/oprofile.h>
11#include <linux/init.h>
12#include <linux/smp.h>
13#include <linux/errno.h>
14#include <asm/ptrace.h>
15#include <asm/system.h>
16
17#include "op_impl.h"
18
19extern struct op_axp_model op_model_ev4 __attribute__((weak));
20extern struct op_axp_model op_model_ev5 __attribute__((weak));
21extern struct op_axp_model op_model_pca56 __attribute__((weak));
22extern struct op_axp_model op_model_ev6 __attribute__((weak));
23extern struct op_axp_model op_model_ev67 __attribute__((weak));
24
25static struct op_axp_model *model;
26
27extern void (*perf_irq)(unsigned long, struct pt_regs *);
28static void (*save_perf_irq)(unsigned long, struct pt_regs *);
29
30static struct op_counter_config ctr[20];
31static struct op_system_config sys;
32static struct op_register_config reg;
33
34/* Called from do_entInt to handle the performance monitor interrupt. */
35
36static void
37op_handle_interrupt(unsigned long which, struct pt_regs *regs)
38{
39 model->handle_interrupt(which, regs, ctr);
40
41 /* If the user has selected an interrupt frequency that is
42 not exactly the width of the counter, write a new value
43 into the counter such that it'll overflow after N more
44 events. */
45 if ((reg.need_reset >> which) & 1)
46 model->reset_ctr(&reg, which);
47}
48
49static int
50op_axp_setup(void)
51{
52 unsigned long i, e;
53
54 /* Install our interrupt handler into the existing hook. */
55 save_perf_irq = perf_irq;
56 perf_irq = op_handle_interrupt;
57
58 /* Compute the mask of enabled counters. */
59 for (i = e = 0; i < model->num_counters; ++i)
60 if (ctr[i].enabled)
61 e |= 1 << i;
62 reg.enable = e;
63
64 /* Pre-compute the values to stuff in the hardware registers. */
65 model->reg_setup(&reg, ctr, &sys);
66
67 /* Configure the registers on all cpus. */
68 smp_call_function(model->cpu_setup, &reg, 0, 1);
69 model->cpu_setup(&reg);
70 return 0;
71}
72
73static void
74op_axp_shutdown(void)
75{
76 /* Remove our interrupt handler. We may be removing this module. */
77 perf_irq = save_perf_irq;
78}
79
80static void
81op_axp_cpu_start(void *dummy)
82{
83 wrperfmon(1, reg.enable);
84}
85
86static int
87op_axp_start(void)
88{
89 smp_call_function(op_axp_cpu_start, NULL, 0, 1);
90 op_axp_cpu_start(NULL);
91 return 0;
92}
93
94static inline void
95op_axp_cpu_stop(void *dummy)
96{
97 /* Disable performance monitoring for all counters. */
98 wrperfmon(0, -1);
99}
100
101static void
102op_axp_stop(void)
103{
104 smp_call_function(op_axp_cpu_stop, NULL, 0, 1);
105 op_axp_cpu_stop(NULL);
106}
107
108static int
109op_axp_create_files(struct super_block * sb, struct dentry * root)
110{
111 int i;
112
113 for (i = 0; i < model->num_counters; ++i) {
114 struct dentry *dir;
115 char buf[3];
116
117 snprintf(buf, sizeof buf, "%d", i);
118 dir = oprofilefs_mkdir(sb, root, buf);
119
120 oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled);
121 oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event);
122 oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count);
123 /* Dummies. */
124 oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel);
125 oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user);
126 oprofilefs_create_ulong(sb, dir, "unit_mask", &ctr[i].unit_mask);
127 }
128
129 if (model->can_set_proc_mode) {
130 oprofilefs_create_ulong(sb, root, "enable_pal",
131 &sys.enable_pal);
132 oprofilefs_create_ulong(sb, root, "enable_kernel",
133 &sys.enable_kernel);
134 oprofilefs_create_ulong(sb, root, "enable_user",
135 &sys.enable_user);
136 }
137
138 return 0;
139}
140
141int __init
142oprofile_arch_init(struct oprofile_operations *ops)
143{
144 struct op_axp_model *lmodel = NULL;
145
146 switch (implver()) {
147 case IMPLVER_EV4:
148 lmodel = &op_model_ev4;
149 break;
150 case IMPLVER_EV5:
151 /* 21164PC has a slightly different set of events.
152 Recognize the chip by the presence of the MAX insns. */
153 if (!amask(AMASK_MAX))
154 lmodel = &op_model_pca56;
155 else
156 lmodel = &op_model_ev5;
157 break;
158 case IMPLVER_EV6:
159 /* 21264A supports ProfileMe.
160 Recognize the chip by the presence of the CIX insns. */
161 if (!amask(AMASK_CIX))
162 lmodel = &op_model_ev67;
163 else
164 lmodel = &op_model_ev6;
165 break;
166 }
167
168 if (!lmodel)
169 return -ENODEV;
170 model = lmodel;
171
172 ops->create_files = op_axp_create_files;
173 ops->setup = op_axp_setup;
174 ops->shutdown = op_axp_shutdown;
175 ops->start = op_axp_start;
176 ops->stop = op_axp_stop;
177 ops->cpu_type = lmodel->cpu_type;
178
179 printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
180 lmodel->cpu_type);
181
182 return 0;
183}
184
185
186void
187oprofile_arch_exit(void)
188{
189}
diff --git a/arch/alpha/oprofile/op_impl.h b/arch/alpha/oprofile/op_impl.h
new file mode 100644
index 000000000000..6b97893c1a80
--- /dev/null
+++ b/arch/alpha/oprofile/op_impl.h
@@ -0,0 +1,55 @@
1/**
2 * @file arch/alpha/oprofile/op_impl.h
3 *
4 * @remark Copyright 2002 OProfile authors
5 * @remark Read the file COPYING
6 *
7 * @author Richard Henderson <rth@twiddle.net>
8 */
9
10#ifndef OP_IMPL_H
11#define OP_IMPL_H 1
12
13/* Per-counter configuration as set via oprofilefs. */
14struct op_counter_config {
15 unsigned long enabled;
16 unsigned long event;
17 unsigned long count;
18 /* Dummies because I am too lazy to hack the userspace tools. */
19 unsigned long kernel;
20 unsigned long user;
21 unsigned long unit_mask;
22};
23
24/* System-wide configuration as set via oprofilefs. */
25struct op_system_config {
26 unsigned long enable_pal;
27 unsigned long enable_kernel;
28 unsigned long enable_user;
29};
30
31/* Cached values for the various performance monitoring registers. */
32struct op_register_config {
33 unsigned long enable;
34 unsigned long mux_select;
35 unsigned long proc_mode;
36 unsigned long freq;
37 unsigned long reset_values;
38 unsigned long need_reset;
39};
40
41/* Per-architecture configury and hooks. */
42struct op_axp_model {
43 void (*reg_setup) (struct op_register_config *,
44 struct op_counter_config *,
45 struct op_system_config *);
46 void (*cpu_setup) (void *);
47 void (*reset_ctr) (struct op_register_config *, unsigned long);
48 void (*handle_interrupt) (unsigned long, struct pt_regs *,
49 struct op_counter_config *);
50 char *cpu_type;
51 unsigned char num_counters;
52 unsigned char can_set_proc_mode;
53};
54
55#endif
diff --git a/arch/alpha/oprofile/op_model_ev4.c b/arch/alpha/oprofile/op_model_ev4.c
new file mode 100644
index 000000000000..80d764dbf22f
--- /dev/null
+++ b/arch/alpha/oprofile/op_model_ev4.c
@@ -0,0 +1,116 @@
1/**
2 * @file arch/alpha/oprofile/op_model_ev4.c
3 *
4 * @remark Copyright 2002 OProfile authors
5 * @remark Read the file COPYING
6 *
7 * @author Richard Henderson <rth@twiddle.net>
8 */
9
10#include <linux/oprofile.h>
11#include <linux/init.h>
12#include <linux/smp.h>
13#include <asm/ptrace.h>
14#include <asm/system.h>
15
16#include "op_impl.h"
17
18
19/* Compute all of the registers in preparation for enabling profiling. */
20
21static void
22ev4_reg_setup(struct op_register_config *reg,
23 struct op_counter_config *ctr,
24 struct op_system_config *sys)
25{
26 unsigned long ctl = 0, count, hilo;
27
28 /* Select desired events. We've mapped the event numbers
29 such that they fit directly into the event selection fields.
30
31 Note that there is no "off" setting. In both cases we select
32 the EXTERNAL event source, hoping that it'll be the lowest
33 frequency, and set the frequency counter to LOW. The interrupts
34 for these "disabled" counter overflows are ignored by the
35 interrupt handler.
36
37 This is most irritating, because the hardware *can* enable and
38 disable the interrupts for these counters independently, but the
39 wrperfmon interface doesn't allow it. */
40
41 ctl |= (ctr[0].enabled ? ctr[0].event << 8 : 14 << 8);
42 ctl |= (ctr[1].enabled ? (ctr[1].event - 16) << 32 : 7ul << 32);
43
44 /* EV4 can not read or write its counter registers. The only
45 thing one can do at all is see if you overflow and get an
46 interrupt. We can set the width of the counters, to some
47 extent. Take the interrupt count selected by the user,
48 map it onto one of the possible values, and write it back. */
49
50 count = ctr[0].count;
51 if (count <= 4096)
52 count = 4096, hilo = 1;
53 else
54 count = 65536, hilo = 0;
55 ctr[0].count = count;
56 ctl |= (ctr[0].enabled && hilo) << 3;
57
58 count = ctr[1].count;
59 if (count <= 256)
60 count = 256, hilo = 1;
61 else
62 count = 4096, hilo = 0;
63 ctr[1].count = count;
64 ctl |= (ctr[1].enabled && hilo);
65
66 reg->mux_select = ctl;
67
68 /* Select performance monitoring options. */
69 /* ??? Need to come up with some mechanism to trace only
70 selected processes. EV4 does not have a mechanism to
71 select kernel or user mode only. For now, enable always. */
72 reg->proc_mode = 0;
73
74 /* Frequency is folded into mux_select for EV4. */
75 reg->freq = 0;
76
77 /* See above regarding no writes. */
78 reg->reset_values = 0;
79 reg->need_reset = 0;
80
81}
82
83/* Program all of the registers in preparation for enabling profiling. */
84
85static void
86ev4_cpu_setup(void *x)
87{
88 struct op_register_config *reg = x;
89
90 wrperfmon(2, reg->mux_select);
91 wrperfmon(3, reg->proc_mode);
92}
93
94static void
95ev4_handle_interrupt(unsigned long which, struct pt_regs *regs,
96 struct op_counter_config *ctr)
97{
98 /* EV4 can't properly disable counters individually.
99 Discard "disabled" events now. */
100 if (!ctr[which].enabled)
101 return;
102
103 /* Record the sample. */
104 oprofile_add_sample(regs, which);
105}
106
107
108struct op_axp_model op_model_ev4 = {
109 .reg_setup = ev4_reg_setup,
110 .cpu_setup = ev4_cpu_setup,
111 .reset_ctr = NULL,
112 .handle_interrupt = ev4_handle_interrupt,
113 .cpu_type = "alpha/ev4",
114 .num_counters = 2,
115 .can_set_proc_mode = 0,
116};
diff --git a/arch/alpha/oprofile/op_model_ev5.c b/arch/alpha/oprofile/op_model_ev5.c
new file mode 100644
index 000000000000..ceea6e1ad79a
--- /dev/null
+++ b/arch/alpha/oprofile/op_model_ev5.c
@@ -0,0 +1,211 @@
1/**
2 * @file arch/alpha/oprofile/op_model_ev5.c
3 *
4 * @remark Copyright 2002 OProfile authors
5 * @remark Read the file COPYING
6 *
7 * @author Richard Henderson <rth@twiddle.net>
8 */
9
10#include <linux/oprofile.h>
11#include <linux/init.h>
12#include <linux/smp.h>
13#include <asm/ptrace.h>
14#include <asm/system.h>
15
16#include "op_impl.h"
17
18
19/* Compute all of the registers in preparation for enabling profiling.
20
21 The 21164 (EV5) and 21164PC (PCA65) vary in the bit placement and
22 meaning of the "CBOX" events. Given that we don't care about meaning
23 at this point, arrange for the difference in bit placement to be
24 handled by common code. */
25
26static void
27common_reg_setup(struct op_register_config *reg,
28 struct op_counter_config *ctr,
29 struct op_system_config *sys,
30 int cbox1_ofs, int cbox2_ofs)
31{
32 int i, ctl, reset, need_reset;
33
34 /* Select desired events. The event numbers are selected such
35 that they map directly into the event selection fields:
36
37 PCSEL0: 0, 1
38 PCSEL1: 24-39
39 CBOX1: 40-47
40 PCSEL2: 48-63
41 CBOX2: 64-71
42
43 There are two special cases, in that CYCLES can be measured
44 on PCSEL[02], and SCACHE_WRITE can be measured on CBOX[12].
45 These event numbers are canonicalizes to their first appearance. */
46
47 ctl = 0;
48 for (i = 0; i < 3; ++i) {
49 unsigned long event = ctr[i].event;
50 if (!ctr[i].enabled)
51 continue;
52
53 /* Remap the duplicate events, as described above. */
54 if (i == 2) {
55 if (event == 0)
56 event = 12+48;
57 else if (event == 2+41)
58 event = 4+65;
59 }
60
61 /* Convert the event numbers onto mux_select bit mask. */
62 if (event < 2)
63 ctl |= event << 31;
64 else if (event < 24)
65 /* error */;
66 else if (event < 40)
67 ctl |= (event - 24) << 4;
68 else if (event < 48)
69 ctl |= (event - 40) << cbox1_ofs | 15 << 4;
70 else if (event < 64)
71 ctl |= event - 48;
72 else if (event < 72)
73 ctl |= (event - 64) << cbox2_ofs | 15;
74 }
75 reg->mux_select = ctl;
76
77 /* Select processor mode. */
78 /* ??? Need to come up with some mechanism to trace only selected
79 processes. For now select from pal, kernel and user mode. */
80 ctl = 0;
81 ctl |= !sys->enable_pal << 9;
82 ctl |= !sys->enable_kernel << 8;
83 ctl |= !sys->enable_user << 30;
84 reg->proc_mode = ctl;
85
86 /* Select interrupt frequencies. Take the interrupt count selected
87 by the user, and map it onto one of the possible counter widths.
88 If the user value is in between, compute a value to which the
89 counter is reset at each interrupt. */
90
91 ctl = reset = need_reset = 0;
92 for (i = 0; i < 3; ++i) {
93 unsigned long max, hilo, count = ctr[i].count;
94 if (!ctr[i].enabled)
95 continue;
96
97 if (count <= 256)
98 count = 256, hilo = 3, max = 256;
99 else {
100 max = (i == 2 ? 16384 : 65536);
101 hilo = 2;
102 if (count > max)
103 count = max;
104 }
105 ctr[i].count = count;
106
107 ctl |= hilo << (8 - i*2);
108 reset |= (max - count) << (48 - 16*i);
109 if (count != max)
110 need_reset |= 1 << i;
111 }
112 reg->freq = ctl;
113 reg->reset_values = reset;
114 reg->need_reset = need_reset;
115}
116
117static void
118ev5_reg_setup(struct op_register_config *reg,
119 struct op_counter_config *ctr,
120 struct op_system_config *sys)
121{
122 common_reg_setup(reg, ctr, sys, 19, 22);
123}
124
125static void
126pca56_reg_setup(struct op_register_config *reg,
127 struct op_counter_config *ctr,
128 struct op_system_config *sys)
129{
130 common_reg_setup(reg, ctr, sys, 8, 11);
131}
132
133/* Program all of the registers in preparation for enabling profiling. */
134
135static void
136ev5_cpu_setup (void *x)
137{
138 struct op_register_config *reg = x;
139
140 wrperfmon(2, reg->mux_select);
141 wrperfmon(3, reg->proc_mode);
142 wrperfmon(4, reg->freq);
143 wrperfmon(6, reg->reset_values);
144}
145
146/* CTR is a counter for which the user has requested an interrupt count
147 in between one of the widths selectable in hardware. Reset the count
148 for CTR to the value stored in REG->RESET_VALUES.
149
150 For EV5, this means disabling profiling, reading the current values,
151 masking in the value for the desired register, writing, then turning
152 profiling back on.
153
154 This can be streamlined if profiling is only enabled for user mode.
155 In that case we know that the counters are not currently incrementing
156 (due to being in kernel mode). */
157
158static void
159ev5_reset_ctr(struct op_register_config *reg, unsigned long ctr)
160{
161 unsigned long values, mask, not_pk, reset_values;
162
163 mask = (ctr == 0 ? 0xfffful << 48
164 : ctr == 1 ? 0xfffful << 32
165 : 0x3fff << 16);
166
167 not_pk = 1 << 9 | 1 << 8;
168
169 reset_values = reg->reset_values;
170
171 if ((reg->proc_mode & not_pk) == not_pk) {
172 values = wrperfmon(5, 0);
173 values = (reset_values & mask) | (values & ~mask & -2);
174 wrperfmon(6, values);
175 } else {
176 wrperfmon(0, -1);
177 values = wrperfmon(5, 0);
178 values = (reset_values & mask) | (values & ~mask & -2);
179 wrperfmon(6, values);
180 wrperfmon(1, reg->enable);
181 }
182}
183
184static void
185ev5_handle_interrupt(unsigned long which, struct pt_regs *regs,
186 struct op_counter_config *ctr)
187{
188 /* Record the sample. */
189 oprofile_add_sample(regs, which);
190}
191
192
193struct op_axp_model op_model_ev5 = {
194 .reg_setup = ev5_reg_setup,
195 .cpu_setup = ev5_cpu_setup,
196 .reset_ctr = ev5_reset_ctr,
197 .handle_interrupt = ev5_handle_interrupt,
198 .cpu_type = "alpha/ev5",
199 .num_counters = 3,
200 .can_set_proc_mode = 1,
201};
202
203struct op_axp_model op_model_pca56 = {
204 .reg_setup = pca56_reg_setup,
205 .cpu_setup = ev5_cpu_setup,
206 .reset_ctr = ev5_reset_ctr,
207 .handle_interrupt = ev5_handle_interrupt,
208 .cpu_type = "alpha/pca56",
209 .num_counters = 3,
210 .can_set_proc_mode = 1,
211};
diff --git a/arch/alpha/oprofile/op_model_ev6.c b/arch/alpha/oprofile/op_model_ev6.c
new file mode 100644
index 000000000000..0869f85f5748
--- /dev/null
+++ b/arch/alpha/oprofile/op_model_ev6.c
@@ -0,0 +1,103 @@
1/**
2 * @file arch/alpha/oprofile/op_model_ev6.c
3 *
4 * @remark Copyright 2002 OProfile authors
5 * @remark Read the file COPYING
6 *
7 * @author Richard Henderson <rth@twiddle.net>
8 */
9
10#include <linux/oprofile.h>
11#include <linux/init.h>
12#include <linux/smp.h>
13#include <asm/ptrace.h>
14#include <asm/system.h>
15
16#include "op_impl.h"
17
18
19/* Compute all of the registers in preparation for enabling profiling. */
20
21static void
22ev6_reg_setup(struct op_register_config *reg,
23 struct op_counter_config *ctr,
24 struct op_system_config *sys)
25{
26 unsigned long ctl, reset, need_reset, i;
27
28 /* Select desired events. We've mapped the event numbers
29 such that they fit directly into the event selection fields. */
30 ctl = 0;
31 if (ctr[0].enabled && ctr[0].event)
32 ctl |= (ctr[0].event & 1) << 4;
33 if (ctr[1].enabled)
34 ctl |= (ctr[1].event - 2) & 15;
35 reg->mux_select = ctl;
36
37 /* Select logging options. */
38 /* ??? Need to come up with some mechanism to trace only
39 selected processes. EV6 does not have a mechanism to
40 select kernel or user mode only. For now, enable always. */
41 reg->proc_mode = 0;
42
43 /* EV6 cannot change the width of the counters as with the
44 other implementations. But fortunately, we can write to
45 the counters and set the value such that it will overflow
46 at the right time. */
47 reset = need_reset = 0;
48 for (i = 0; i < 2; ++i) {
49 unsigned long count = ctr[i].count;
50 if (!ctr[i].enabled)
51 continue;
52
53 if (count > 0x100000)
54 count = 0x100000;
55 ctr[i].count = count;
56 reset |= (0x100000 - count) << (i ? 6 : 28);
57 if (count != 0x100000)
58 need_reset |= 1 << i;
59 }
60 reg->reset_values = reset;
61 reg->need_reset = need_reset;
62}
63
64/* Program all of the registers in preparation for enabling profiling. */
65
66static void
67ev6_cpu_setup (void *x)
68{
69 struct op_register_config *reg = x;
70
71 wrperfmon(2, reg->mux_select);
72 wrperfmon(3, reg->proc_mode);
73 wrperfmon(6, reg->reset_values | 3);
74}
75
76/* CTR is a counter for which the user has requested an interrupt count
77 in between one of the widths selectable in hardware. Reset the count
78 for CTR to the value stored in REG->RESET_VALUES. */
79
80static void
81ev6_reset_ctr(struct op_register_config *reg, unsigned long ctr)
82{
83 wrperfmon(6, reg->reset_values | (1 << ctr));
84}
85
86static void
87ev6_handle_interrupt(unsigned long which, struct pt_regs *regs,
88 struct op_counter_config *ctr)
89{
90 /* Record the sample. */
91 oprofile_add_sample(regs, which);
92}
93
94
95struct op_axp_model op_model_ev6 = {
96 .reg_setup = ev6_reg_setup,
97 .cpu_setup = ev6_cpu_setup,
98 .reset_ctr = ev6_reset_ctr,
99 .handle_interrupt = ev6_handle_interrupt,
100 .cpu_type = "alpha/ev6",
101 .num_counters = 2,
102 .can_set_proc_mode = 0,
103};
diff --git a/arch/alpha/oprofile/op_model_ev67.c b/arch/alpha/oprofile/op_model_ev67.c
new file mode 100644
index 000000000000..70302086283c
--- /dev/null
+++ b/arch/alpha/oprofile/op_model_ev67.c
@@ -0,0 +1,263 @@
1/**
2 * @file arch/alpha/oprofile/op_model_ev67.c
3 *
4 * @remark Copyright 2002 OProfile authors
5 * @remark Read the file COPYING
6 *
7 * @author Richard Henderson <rth@twiddle.net>
8 * @author Falk Hueffner <falk@debian.org>
9 */
10
11#include <linux/oprofile.h>
12#include <linux/init.h>
13#include <linux/smp.h>
14#include <asm/ptrace.h>
15#include <asm/system.h>
16
17#include "op_impl.h"
18
19
20/* Compute all of the registers in preparation for enabling profiling. */
21
22static void
23ev67_reg_setup(struct op_register_config *reg,
24 struct op_counter_config *ctr,
25 struct op_system_config *sys)
26{
27 unsigned long ctl, reset, need_reset, i;
28
29 /* Select desired events. */
30 ctl = 1UL << 4; /* Enable ProfileMe mode. */
31
32 /* The event numbers are chosen so we can use them directly if
33 PCTR1 is enabled. */
34 if (ctr[1].enabled) {
35 ctl |= (ctr[1].event & 3) << 2;
36 } else {
37 if (ctr[0].event == 0) /* cycles */
38 ctl |= 1UL << 2;
39 }
40 reg->mux_select = ctl;
41
42 /* Select logging options. */
43 /* ??? Need to come up with some mechanism to trace only
44 selected processes. EV67 does not have a mechanism to
45 select kernel or user mode only. For now, enable always. */
46 reg->proc_mode = 0;
47
48 /* EV67 cannot change the width of the counters as with the
49 other implementations. But fortunately, we can write to
50 the counters and set the value such that it will overflow
51 at the right time. */
52 reset = need_reset = 0;
53 for (i = 0; i < 2; ++i) {
54 unsigned long count = ctr[i].count;
55 if (!ctr[i].enabled)
56 continue;
57
58 if (count > 0x100000)
59 count = 0x100000;
60 ctr[i].count = count;
61 reset |= (0x100000 - count) << (i ? 6 : 28);
62 if (count != 0x100000)
63 need_reset |= 1 << i;
64 }
65 reg->reset_values = reset;
66 reg->need_reset = need_reset;
67}
68
69/* Program all of the registers in preparation for enabling profiling. */
70
71static void
72ev67_cpu_setup (void *x)
73{
74 struct op_register_config *reg = x;
75
76 wrperfmon(2, reg->mux_select);
77 wrperfmon(3, reg->proc_mode);
78 wrperfmon(6, reg->reset_values | 3);
79}
80
81/* CTR is a counter for which the user has requested an interrupt count
82 in between one of the widths selectable in hardware. Reset the count
83 for CTR to the value stored in REG->RESET_VALUES. */
84
85static void
86ev67_reset_ctr(struct op_register_config *reg, unsigned long ctr)
87{
88 wrperfmon(6, reg->reset_values | (1 << ctr));
89}
90
91/* ProfileMe conditions which will show up as counters. We can also
92 detect the following, but it seems unlikely that anybody is
93 interested in counting them:
94 * Reset
95 * MT_FPCR (write to floating point control register)
96 * Arithmetic trap
97 * Dstream Fault
98 * Machine Check (ECC fault, etc.)
99 * OPCDEC (illegal opcode)
100 * Floating point disabled
101 * Differentiate between DTB single/double misses and 3 or 4 level
102 page tables
103 * Istream access violation
104 * Interrupt
105 * Icache Parity Error.
106 * Instruction killed (nop, trapb)
107
108 Unfortunately, there seems to be no way to detect Dcache and Bcache
109 misses; the latter could be approximated by making the counter
110 count Bcache misses, but that is not precise.
111
112 We model this as 20 counters:
113 * PCTR0
114 * PCTR1
115 * 9 ProfileMe events, induced by PCTR0
116 * 9 ProfileMe events, induced by PCTR1
117*/
118
119enum profileme_counters {
120 PM_STALLED, /* Stalled for at least one cycle
121 between the fetch and map stages */
122 PM_TAKEN, /* Conditional branch taken */
123 PM_MISPREDICT, /* Branch caused mispredict trap */
124 PM_ITB_MISS, /* ITB miss */
125 PM_DTB_MISS, /* DTB miss */
126 PM_REPLAY, /* Replay trap */
127 PM_LOAD_STORE, /* Load-store order trap */
128 PM_ICACHE_MISS, /* Icache miss */
129 PM_UNALIGNED, /* Unaligned Load/Store */
130 PM_NUM_COUNTERS
131};
132
133static inline void
134op_add_pm(unsigned long pc, int kern, unsigned long counter,
135 struct op_counter_config *ctr, unsigned long event)
136{
137 unsigned long fake_counter = 2 + event;
138 if (counter == 1)
139 fake_counter += PM_NUM_COUNTERS;
140 if (ctr[fake_counter].enabled)
141 oprofile_add_pc(pc, kern, fake_counter);
142}
143
144static void
145ev67_handle_interrupt(unsigned long which, struct pt_regs *regs,
146 struct op_counter_config *ctr)
147{
148 unsigned long pmpc, pctr_ctl;
149 int kern = !user_mode(regs);
150 int mispredict = 0;
151 union {
152 unsigned long v;
153 struct {
154 unsigned reserved: 30; /* 0-29 */
155 unsigned overcount: 3; /* 30-32 */
156 unsigned icache_miss: 1; /* 33 */
157 unsigned trap_type: 4; /* 34-37 */
158 unsigned load_store: 1; /* 38 */
159 unsigned trap: 1; /* 39 */
160 unsigned mispredict: 1; /* 40 */
161 } fields;
162 } i_stat;
163
164 enum trap_types {
165 TRAP_REPLAY,
166 TRAP_INVALID0,
167 TRAP_DTB_DOUBLE_MISS_3,
168 TRAP_DTB_DOUBLE_MISS_4,
169 TRAP_FP_DISABLED,
170 TRAP_UNALIGNED,
171 TRAP_DTB_SINGLE_MISS,
172 TRAP_DSTREAM_FAULT,
173 TRAP_OPCDEC,
174 TRAP_INVALID1,
175 TRAP_MACHINE_CHECK,
176 TRAP_INVALID2,
177 TRAP_ARITHMETIC,
178 TRAP_INVALID3,
179 TRAP_MT_FPCR,
180 TRAP_RESET
181 };
182
183 pmpc = wrperfmon(9, 0);
184 /* ??? Don't know how to handle physical-mode PALcode address. */
185 if (pmpc & 1)
186 return;
187 pmpc &= ~2; /* clear reserved bit */
188
189 i_stat.v = wrperfmon(8, 0);
190 if (i_stat.fields.trap) {
191 switch (i_stat.fields.trap_type) {
192 case TRAP_INVALID1:
193 case TRAP_INVALID2:
194 case TRAP_INVALID3:
195 /* Pipeline redirection ocurred. PMPC points
196 to PALcode. Recognize ITB miss by PALcode
197 offset address, and get actual PC from
198 EXC_ADDR. */
199 oprofile_add_pc(regs->pc, kern, which);
200 if ((pmpc & ((1 << 15) - 1)) == 581)
201 op_add_pm(regs->pc, kern, which,
202 ctr, PM_ITB_MISS);
203 /* Most other bit and counter values will be
204 those for the first instruction in the
205 fault handler, so we're done. */
206 return;
207 case TRAP_REPLAY:
208 op_add_pm(pmpc, kern, which, ctr,
209 (i_stat.fields.load_store
210 ? PM_LOAD_STORE : PM_REPLAY));
211 break;
212 case TRAP_DTB_DOUBLE_MISS_3:
213 case TRAP_DTB_DOUBLE_MISS_4:
214 case TRAP_DTB_SINGLE_MISS:
215 op_add_pm(pmpc, kern, which, ctr, PM_DTB_MISS);
216 break;
217 case TRAP_UNALIGNED:
218 op_add_pm(pmpc, kern, which, ctr, PM_UNALIGNED);
219 break;
220 case TRAP_INVALID0:
221 case TRAP_FP_DISABLED:
222 case TRAP_DSTREAM_FAULT:
223 case TRAP_OPCDEC:
224 case TRAP_MACHINE_CHECK:
225 case TRAP_ARITHMETIC:
226 case TRAP_MT_FPCR:
227 case TRAP_RESET:
228 break;
229 }
230
231 /* ??? JSR/JMP/RET/COR or HW_JSR/HW_JMP/HW_RET/HW_COR
232 mispredicts do not set this bit but can be
233 recognized by the presence of one of these
234 instructions at the PMPC location with bit 39
235 set. */
236 if (i_stat.fields.mispredict) {
237 mispredict = 1;
238 op_add_pm(pmpc, kern, which, ctr, PM_MISPREDICT);
239 }
240 }
241
242 oprofile_add_pc(pmpc, kern, which);
243
244 pctr_ctl = wrperfmon(5, 0);
245 if (pctr_ctl & (1UL << 27))
246 op_add_pm(pmpc, kern, which, ctr, PM_STALLED);
247
248 /* Unfortunately, TAK is undefined on mispredicted branches.
249 ??? It is also undefined for non-cbranch insns, should
250 check that. */
251 if (!mispredict && pctr_ctl & (1UL << 0))
252 op_add_pm(pmpc, kern, which, ctr, PM_TAKEN);
253}
254
255struct op_axp_model op_model_ev67 = {
256 .reg_setup = ev67_reg_setup,
257 .cpu_setup = ev67_cpu_setup,
258 .reset_ctr = ev67_reset_ctr,
259 .handle_interrupt = ev67_handle_interrupt,
260 .cpu_type = "alpha/ev67",
261 .num_counters = 20,
262 .can_set_proc_mode = 0,
263};