source: trunk/packages/xen-3.1/xen-3.1/xen/arch/x86/genapic/es7000plat.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 6.9 KB
Line 
1/*
2 * Written by: Garry Forsgren, Unisys Corporation
3 *             Natalie Protasevich, Unisys Corporation
4 * This file contains the code to configure and interface
5 * with Unisys ES7000 series hardware system manager.
6 *
7 * Copyright (c) 2003 Unisys Corporation.  All Rights Reserved.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of version 2 of the GNU General Public License as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it would be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write the Free Software Foundation, Inc., 59
19 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
20 *
21 * Contact information: Unisys Corporation, Township Line & Union Meeting
22 * Roads-A, Unisys Way, Blue Bell, Pennsylvania, 19424, or:
23 *
24 * http://www.unisys.com
25 */
26
27#include <xen/config.h>
28#include <xen/types.h>
29#include <xen/kernel.h>
30#include <xen/smp.h>
31#include <xen/string.h>
32#include <xen/spinlock.h>
33#include <xen/errno.h>
34#include <xen/init.h>
35#include <xen/acpi.h>
36#include <asm/io.h>
37#include <asm/smp.h>
38#include <asm/apicdef.h>
39#include "es7000.h"
40
41/*
42 * ES7000 Globals
43 */
44
45volatile unsigned long  *psai = NULL;
46struct mip_reg          *mip_reg;
47struct mip_reg          *host_reg;
48int                     mip_port;
49unsigned long           mip_addr, host_addr;
50
51#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI)
52
53/*
54 * GSI override for ES7000 platforms.
55 */
56
57static unsigned int base;
58
59static int
60es7000_rename_gsi(int ioapic, int gsi)
61{
62        if (es7000_plat == ES7000_ZORRO)
63                return gsi;
64
65        if (!base) {
66                int i;
67                for (i = 0; i < nr_ioapics; i++)
68                        base += nr_ioapic_registers[i];
69        }
70
71        if (!ioapic && (gsi < 16)) 
72                gsi += base;
73        return gsi;
74}
75
76#endif  /* (CONFIG_X86_IO_APIC) && (CONFIG_ACPI) */
77
78void __init
79setup_unisys(void)
80{
81        /*
82         * Determine the generation of the ES7000 currently running.
83         *
84         * es7000_plat = 1 if the machine is a 5xx ES7000 box
85         * es7000_plat = 2 if the machine is a x86_64 ES7000 box
86         *
87         */
88        if (!(boot_cpu_data.x86 <= 15 && boot_cpu_data.x86_model <= 2))
89                es7000_plat = ES7000_ZORRO;
90        else
91                es7000_plat = ES7000_CLASSIC;
92        ioapic_renumber_irq = es7000_rename_gsi;
93}
94
95/*
96 * Parse the OEM Table
97 */
98
99int __init
100parse_unisys_oem (char *oemptr)
101{
102        int                     i;
103        int                     success = 0;
104        unsigned char           type, size;
105        unsigned long           val;
106        char                    *tp = NULL;
107        struct psai             *psaip = NULL;
108        struct mip_reg_info     *mi;
109        struct mip_reg          *host, *mip;
110
111        tp = oemptr;
112
113        tp += 8;
114
115        for (i=0; i <= 6; i++) {
116                type = *tp++;
117                size = *tp++;
118                tp -= 2;
119                switch (type) {
120                case MIP_REG:
121                        mi = (struct mip_reg_info *)tp;
122                        val = MIP_RD_LO(mi->host_reg);
123                        host_addr = val;
124                        host = (struct mip_reg *)val;
125                        host_reg = __va(host);
126                        val = MIP_RD_LO(mi->mip_reg);
127                        mip_port = MIP_PORT(mi->mip_info);
128                        mip_addr = val;
129                        mip = (struct mip_reg *)val;
130                        mip_reg = __va(mip);
131                        Dprintk("es7000_mipcfg: host_reg = 0x%lx \n",
132                                (unsigned long)host_reg);
133                        Dprintk("es7000_mipcfg: mip_reg = 0x%lx \n",
134                                (unsigned long)mip_reg);
135                        success++;
136                        break;
137                case MIP_PSAI_REG:
138                        psaip = (struct psai *)tp;
139                        if (tp != NULL) {
140                                if (psaip->addr)
141                                        psai = __va(psaip->addr);
142                                else
143                                        psai = NULL;
144                                success++;
145                        }
146                        break;
147                default:
148                        break;
149                }
150                tp += size;
151        }
152
153        if (success < 2) {
154                es7000_plat = NON_UNISYS;
155        } else
156                setup_unisys();
157        return es7000_plat;
158}
159
160int __init
161find_unisys_acpi_oem_table(unsigned long *oem_addr)
162{
163        struct acpi_table_rsdp          *rsdp = NULL;
164        unsigned long                   rsdp_phys = 0;
165        struct acpi_table_header        *header = NULL;
166        int                             i;
167        struct acpi_table_sdt           sdt = { 0 }; /* initialise sdt.count */
168
169        rsdp_phys = acpi_find_rsdp();
170        rsdp = __va(rsdp_phys);
171        if (rsdp->rsdt_address) {
172                struct acpi_table_rsdt  *mapped_rsdt = NULL;
173                sdt.pa = rsdp->rsdt_address;
174
175                header = (struct acpi_table_header *)
176                        __acpi_map_table(sdt.pa, sizeof(struct acpi_table_header));
177                if (!header)
178                        return -ENODEV;
179
180                sdt.count = (header->length - sizeof(struct acpi_table_header)) >> 3;
181                mapped_rsdt = (struct acpi_table_rsdt *)
182                        __acpi_map_table(sdt.pa, header->length);
183                if (!mapped_rsdt)
184                        return -ENODEV;
185
186                header = &mapped_rsdt->header;
187
188                for (i = 0; i < sdt.count; i++)
189                        sdt.entry[i].pa = (unsigned long) mapped_rsdt->entry[i];
190        };
191        for (i = 0; i < sdt.count; i++) {
192
193                header = (struct acpi_table_header *)
194                        __acpi_map_table(sdt.entry[i].pa,
195                                sizeof(struct acpi_table_header));
196                if (!header)
197                        continue;
198                if (!strncmp((char *) &header->signature, "OEM1", 4)) {
199                        if (!strncmp((char *) &header->oem_id, "UNISYS", 6)) {
200                                void *addr;
201                                struct oem_table *t;
202                                acpi_table_print(header, sdt.entry[i].pa);
203                                t = (struct oem_table *) __acpi_map_table(sdt.entry[i].pa, header->length);
204                                addr = (void *) __acpi_map_table(t->OEMTableAddr, t->OEMTableSize);
205                                *oem_addr = (unsigned long) addr;
206                                return 0;
207                        }
208                }
209        }
210        return -1;
211}
212
213static void
214es7000_spin(int n)
215{
216        int i = 0;
217
218        while (i++ < n)
219                rep_nop();
220}
221
222static int __init
223es7000_mip_write(struct mip_reg *mip_reg)
224{
225        int                     status = 0;
226        int                     spin;
227
228        spin = MIP_SPIN;
229        while (((unsigned long long)host_reg->off_38 &
230                (unsigned long long)MIP_VALID) != 0) {
231                        if (--spin <= 0) {
232                                printk("es7000_mip_write: Timeout waiting for Host Valid Flag");
233                                return -1;
234                        }
235                es7000_spin(MIP_SPIN);
236        }
237
238        memcpy(host_reg, mip_reg, sizeof(struct mip_reg));
239        outb(1, mip_port);
240
241        spin = MIP_SPIN;
242
243        while (((unsigned long long)mip_reg->off_38 &
244                (unsigned long long)MIP_VALID) == 0) {
245                if (--spin <= 0) {
246                        printk("es7000_mip_write: Timeout waiting for MIP Valid Flag");
247                        return -1;
248                }
249                es7000_spin(MIP_SPIN);
250        }
251
252        status = ((unsigned long long)mip_reg->off_0 &
253                (unsigned long long)0xffff0000000000ULL) >> 48;
254        mip_reg->off_38 = ((unsigned long long)mip_reg->off_38 &
255                (unsigned long long)~MIP_VALID);
256        return status;
257}
258
259int
260es7000_start_cpu(int cpu, unsigned long eip)
261{
262        unsigned long vect = 0, psaival = 0;
263
264        if (psai == NULL)
265                return -1;
266
267        vect = ((unsigned long)__pa(eip)/0x1000) << 16;
268        psaival = (0x1000000 | vect | cpu);
269
270        while (*psai & 0x1000000)
271                ;
272
273        *psai = psaival;
274
275        return 0;
276
277}
278
279int
280es7000_stop_cpu(int cpu)
281{
282        int startup;
283
284        if (psai == NULL)
285                return -1;
286
287        startup= (0x1000000 | cpu);
288
289        while ((*psai & 0xff00ffff) != startup)
290                ;
291
292        startup = (*psai & 0xff0000) >> 16;
293        *psai &= 0xffffff;
294
295        return 0;
296
297}
298
299void __init
300es7000_sw_apic()
301{
302        if (es7000_plat) {
303                int mip_status;
304                struct mip_reg es7000_mip_reg;
305
306                printk("ES7000: Enabling APIC mode.\n");
307                memset(&es7000_mip_reg, 0, sizeof(struct mip_reg));
308                es7000_mip_reg.off_0 = MIP_SW_APIC;
309                es7000_mip_reg.off_38 = (MIP_VALID);
310                while ((mip_status = es7000_mip_write(&es7000_mip_reg)) != 0)
311                        printk("es7000_sw_apic: command failed, status = %x\n",
312                                mip_status);
313                return;
314        }
315}
Note: See TracBrowser for help on using the repository browser.