Update ia64 patch to 2.5.72-030619
[linux-flexiantxendom0-3.2.10.git] / arch / ia64 / sn / io / sgi_if.c
1 /* $Id$
2  *
3  * This file is subject to the terms and conditions of the GNU General Public
4  * License.  See the file "COPYING" in the main directory of this archive
5  * for more details.
6  *
7  * Copyright (C) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved.
8  */
9
10 #include <linux/types.h>
11 #include <linux/ctype.h>
12 #include <linux/mm.h>
13 #include <linux/slab.h>
14 #include <asm/sn/sgi.h>
15 #include <asm/sn/invent.h>
16 #include <asm/sn/hcl.h>
17 #include <asm/sn/labelcl.h>
18 #include <asm/sn/pci/bridge.h>
19 #include <asm/sn/ioerror_handling.h>
20 #include <asm/sn/pci/pciio.h>
21 #include <asm/sn/slotnum.h>
22
23 void *
24 snia_kmem_zalloc(size_t size, int flag)
25 {
26         void *ptr = kmalloc(size, GFP_KERNEL);
27         if ( ptr )
28                 BZERO(ptr, size);
29         return(ptr);
30 }
31
32 void
33 snia_kmem_free(void *ptr, size_t size)
34 {
35         kfree(ptr);
36 }
37
38 /*
39  * the alloc/free_node routines do a simple kmalloc for now ..
40  */
41 void *
42 snia_kmem_alloc_node(register size_t size, register int flags, cnodeid_t node)
43 {
44         /* someday will Allocate on node 'node' */
45         return(kmalloc(size, GFP_KERNEL));
46 }
47
48 void *
49 snia_kmem_zalloc_node(register size_t size, register int flags, cnodeid_t node)
50 {
51         void *ptr = kmalloc(size, GFP_KERNEL);
52         if ( ptr )
53                 BZERO(ptr, size);
54         return(ptr);
55 }
56
57
58 #define xtod(c)         ((c) <= '9' ? '0' - (c) : 'a' - (c) - 10)
59 long
60 atoi(register char *p)
61 {
62         register long n;
63         register int c, neg = 0;
64
65         if (p == NULL)
66                 return 0;
67
68         if (!isdigit(c = *p)) {
69                 while (isspace(c))
70                         c = *++p;
71                 switch (c) {
72                 case '-':
73                         neg++;
74                 case '+': /* fall-through */
75                         c = *++p;
76                 }
77                 if (!isdigit(c))
78                         return (0);
79         }
80         if (c == '0' && *(p + 1) == 'x') {
81                 p += 2;
82                 c = *p;
83                 n = xtod(c);
84                 while ((c = *++p) && isxdigit(c)) {
85                         n *= 16; /* two steps to avoid unnecessary overflow */
86                         n += xtod(c); /* accum neg to avoid surprises at MAX */
87                 }
88         } else {
89                 n = '0' - c;
90                 while ((c = *++p) && isdigit(c)) {
91                         n *= 10; /* two steps to avoid unnecessary overflow */
92                         n += '0' - c; /* accum neg to avoid surprises at MAX */
93                 }
94         }
95         return (neg ? n : -n);
96 }
97
98 /*
99  * print_register() allows formatted printing of bit fields.  individual
100  * bit fields are described by a struct reg_desc, multiple bit fields within
101  * a single word can be described by multiple reg_desc structures.
102  * %r outputs a string of the format "<bit field descriptions>"
103  * %R outputs a string of the format "0x%x<bit field descriptions>"
104  *
105  * The fields in a reg_desc are:
106  *      unsigned long long rd_mask; An appropriate mask to isolate the bit field
107  *                              within a word, and'ed with val
108  *
109  *      int rd_shift;           A shift amount to be done to the isolated
110  *                              bit field.  done before printing the isolate
111  *                              bit field with rd_format and before searching
112  *                              for symbolic value names in rd_values
113  *
114  *      char *rd_name;          If non-null, a bit field name to label any
115  *                              out from rd_format or searching rd_values.
116  *                              if neither rd_format or rd_values is non-null
117  *                              rd_name is printed only if the isolated
118  *                              bit field is non-null.
119  *
120  *      char *rd_format;        If non-null, the shifted bit field value
121  *                              is printed using this format.
122  *
123  *      struct reg_values *rd_values;   If non-null, a pointer to a table
124  *                              matching numeric values with symbolic names.
125  *                              rd_values are searched and the symbolic
126  *                              value is printed if a match is found, if no
127  *                              match is found "???" is printed.
128  *                              
129  */
130
131 void
132 print_register(unsigned long long reg, struct reg_desc *addr)
133 {
134         register struct reg_desc *rd;
135         register struct reg_values *rv;
136         unsigned long long field;
137         int any;
138
139         printk("<");
140         any = 0;
141         for (rd = addr; rd->rd_mask; rd++) {
142                 field = reg & rd->rd_mask;
143                 field = (rd->rd_shift > 0) ? field << rd->rd_shift : field >> -rd->rd_shift;
144                 if (any && (rd->rd_format || rd->rd_values || (rd->rd_name && field)))
145                         printk(",");
146                 if (rd->rd_name) {
147                         if (rd->rd_format || rd->rd_values || field) {
148                                 printk("%s", rd->rd_name);
149                                 any = 1;
150                         }
151                         if (rd->rd_format || rd->rd_values) {
152                                 printk("=");
153                                 any = 1;
154                         }
155                 }
156                 /* You can have any format so long as it is %x */
157                 if (rd->rd_format) {
158                         printk("%llx", field);
159                         any = 1;
160                         if (rd->rd_values)
161                                 printk(":");
162                 }
163                 if (rd->rd_values) {
164                         any = 1;
165                         for (rv = rd->rd_values; rv->rv_name; rv++) {
166                                 if (field == rv->rv_value) {
167                                         printk("%s", rv->rv_name);
168                                         break;
169                                 }
170                         }
171                         if (rv->rv_name == NULL)
172                                 printk("???");
173                 }
174         }
175         printk(">\n");
176 }