1 /*
2 * Find I2O capable controllers on the PCI bus, and register/install
3 * them with the I2O layer
4 *
5 * (C) Copyright 1999 Red Hat Software
6 *
7 * Written by Alan Cox, Building Number Three Ltd
8 * Modified by Deepak Saxena <deepak@plexity.net>
9 * Modified by Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version
14 * 2 of the License, or (at your option) any later version.
15 *
16 * TODO:
17 * Support polled I2O PCI controllers.
18 */
19
20 #include <linux/config.h>
21 #include <linux/module.h>
22 #include <linux/kernel.h>
23 #include <linux/pci.h>
24 #include <linux/i2o.h>
25 #include <linux/errno.h>
26 #include <linux/init.h>
27 #include <linux/malloc.h>
28 #include <asm/io.h>
29
30 #ifdef CONFIG_MTRR
31 #include <asm/mtrr.h>
32 #endif // CONFIG_MTRR
33
34 #ifdef MODULE
35 /*
36 * Core function table
37 * See <include/linux/i2o.h> for an explanation
38 */
39 static struct i2o_core_func_table *core;
40
41 /* Core attach function */
42 extern int i2o_pci_core_attach(struct i2o_core_func_table *);
43 extern void i2o_pci_core_detach(void);
44 #endif /* MODULE */
45
46 /*
47 * Free bus specific resources
48 */
49 static void i2o_pci_dispose(struct i2o_controller *c)
50 {
51 I2O_IRQ_WRITE32(c,0xFFFFFFFF);
52 if(c->bus.pci.irq > 0)
53 free_irq(c->bus.pci.irq, c);
54 iounmap(((u8 *)c->post_port)-0x40);
55
56 #ifdef CONFIG_MTRR
57 if(c->bus.pci.mtrr_reg0 > 0)
58 mtrr_del(c->bus.pci.mtrr_reg0, 0, 0);
59 if(c->bus.pci.mtrr_reg1 > 0)
60 mtrr_del(c->bus.pci.mtrr_reg1, 0, 0);
61 #endif
62 }
63
64 /*
65 * No real bus specific handling yet (note that later we will
66 * need to 'steal' PCI devices on i960 mainboards)
67 */
68
69 static int i2o_pci_bind(struct i2o_controller *c, struct i2o_device *dev)
70 {
71 MOD_INC_USE_COUNT;
72 return 0;
73 }
74
75 static int i2o_pci_unbind(struct i2o_controller *c, struct i2o_device *dev)
76 {
77 MOD_DEC_USE_COUNT;
78 return 0;
79 }
80
81 /*
82 * Bus specific enable/disable functions
83 */
84 static void i2o_pci_enable(struct i2o_controller *c)
85 {
86 I2O_IRQ_WRITE32(c, 0);
87 c->enabled = 1;
88 }
89
90 static void i2o_pci_disable(struct i2o_controller *c)
91 {
92 I2O_IRQ_WRITE32(c, 0xFFFFFFFF);
93 c->enabled = 0;
94 }
95
96 /*
97 * Bus specific interrupt handler
98 */
99
100 static void i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r)
101 {
102 struct i2o_controller *c = dev_id;
103 #ifdef MODULE
104 core->run_queue(c);
105 #else
106 i2o_run_queue(c);
107 #endif /* MODULE */
108 }
109
110 /*
111 * Install a PCI (or in theory AGP) i2o controller
112 *
113 * TODO: Add support for polled controllers
114 */
115 int __init i2o_pci_install(struct pci_dev *dev)
116 {
117 struct i2o_controller *c=kmalloc(sizeof(struct i2o_controller),
118 GFP_KERNEL);
119 u8 *mem;
120 u32 memptr = 0;
121 u32 size;
122
123 int i;
124
125 if(c==NULL)
126 {
127 printk(KERN_ERR "i2o: Insufficient memory to add controller.\n");
128 return -ENOMEM;
129 }
130 memset(c, 0, sizeof(*c));
131
132 for(i=0; i<6; i++)
133 {
134 /* Skip I/O spaces */
135 if(!(pci_resource_flags(dev, i) & IORESOURCE_IO))
136 {
137 memptr = pci_resource_start(dev, i);
138 break;
139 }
140 }
141
142 if(i==6)
143 {
144 printk(KERN_ERR "i2o: I2O controller has no memory regions defined.\n");
145 kfree(c);
146 return -EINVAL;
147 }
148
149 size = dev->resource[i].end-dev->resource[i].start+1;
150 /* Map the I2O controller */
151
152 printk(KERN_INFO "i2o: PCI I2O controller at 0x%08X size=%d\n", memptr, size);
153 mem = ioremap(memptr, size);
154 if(mem==NULL)
155 {
156 printk(KERN_ERR "i2o: Unable to map controller.\n");
157 kfree(c);
158 return -EINVAL;
159 }
160
161 c->bus.pci.irq = -1;
162
163 c->irq_mask = (volatile u32 *)(mem+0x34);
164 c->post_port = (volatile u32 *)(mem+0x40);
165 c->reply_port = (volatile u32 *)(mem+0x44);
166
167 c->mem_phys = memptr;
168 c->mem_offset = (u32)mem;
169 c->destructor = i2o_pci_dispose;
170
171 c->bind = i2o_pci_bind;
172 c->unbind = i2o_pci_unbind;
173 c->bus_enable = i2o_pci_enable;
174 c->bus_disable = i2o_pci_disable;
175
176 c->type = I2O_TYPE_PCI;
177
178 /*
179 * Enable Write Combining MTRR for IOP's memory region
180 */
181 #ifdef CONFIG_MTRR
182 c->bus.pci.mtrr_reg0 =
183 mtrr_add(c->mem_phys, size, MTRR_TYPE_WRCOMB, 1);
184 /*
185 * If it is an INTEL i960 I/O processor then set the first 64K to Uncacheable
186 * since the region contains the Messaging unit which shouldn't be cached.
187 */
188 c->bus.pci.mtrr_reg1 = -1;
189 if(dev->vendor == PCI_VENDOR_ID_INTEL)
190 {
191 printk(KERN_INFO "I2O: MTRR workaround for Intel i960 processor\n");
192 c->bus.pci.mtrr_reg1 =
193 mtrr_add(c->mem_phys, 65536, MTRR_TYPE_UNCACHABLE, 1);
194 if(c->bus.pci.mtrr_reg1< 0)
195 printk(KERN_INFO "i2o_pci: Error in setting MTRR_TYPE_UNCACHABLE\n");
196 }
197
198 #endif
199
200 I2O_IRQ_WRITE32(c,0xFFFFFFFF);
201
202 #ifdef MODULE
203 i = core->install(c);
204 #else
205 i = i2o_install_controller(c);
206 #endif /* MODULE */
207
208 if(i<0)
209 {
210 printk(KERN_ERR "i2o: Unable to install controller.\n");
211 kfree(c);
212 iounmap(mem);
213 return i;
214 }
215
216 c->bus.pci.irq = dev->irq;
217 if(c->bus.pci.irq)
218 {
219 i=request_irq(dev->irq, i2o_pci_interrupt, SA_SHIRQ,
220 c->name, c);
221 if(i<0)
222 {
223 printk(KERN_ERR "%s: unable to allocate interrupt %d.\n",
224 c->name, dev->irq);
225 c->bus.pci.irq = -1;
226 #ifdef MODULE
227 core->delete(c);
228 #else
229 i2o_delete_controller(c);
230 #endif /* MODULE */
231 kfree(c);
232 iounmap(mem);
233 return -EBUSY;
234 }
235 }
236
237 printk(KERN_INFO "%s: Installed at IRQ%d\n", c->name, dev->irq);
238 I2O_IRQ_WRITE32(c,0x0);
239 c->enabled = 1;
240 return 0;
241 }
242
243 int __init i2o_pci_scan(void)
244 {
245 struct pci_dev *dev;
246 int count=0;
247
248 printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n");
249
250 pci_for_each_dev(dev)
251 {
252 if((dev->class>>8)!=PCI_CLASS_INTELLIGENT_I2O)
253 continue;
254 if((dev->class&0xFF)>1)
255 {
256 printk(KERN_INFO "i2o: I2O Controller found but does not support I2O 1.5 (skipping).\n");
257 continue;
258 }
259 if (pci_enable_device(dev))
260 continue;
261 printk(KERN_INFO "i2o: I2O controller on bus %d at %d.\n",
262 dev->bus->number, dev->devfn);
263 pci_set_master(dev);
264 if(i2o_pci_install(dev)==0)
265 count++;
266 }
267 if(count)
268 printk(KERN_INFO "i2o: %d I2O controller%s found and installed.\n", count,
269 count==1?"":"s");
270 return count?count:-ENODEV;
271 }
272
273 #ifdef I2O_HOTPLUG_SUPPORT
274 /*
275 * Activate a newly found PCI I2O controller
276 * Not used now, but will be needed in future for
277 * hot plug PCI support
278 */
279 static void i2o_pci_activate(i2o_controller * c)
280 {
281 int i=0;
282 struct i2o_controller *c;
283
284 if(c->type == I2O_TYPE_PCI)
285 {
286 I2O_IRQ_WRITE32(c,0);
287 #ifdef MODULE
288 if(core->activate(c))
289 #else
290 if(i2o_activate_controller(c))
291 #endif /* MODULE */
292 {
293 printk("%s: Failed to initialize.\n", c->name);
294 #ifdef MODULE
295 core->unlock(c);
296 core->delete(c);
297 #else
298 i2o_unlock_controller(c);
299 i2o_delete_controller(c);
300 #endif
301 continue;
302 }
303 }
304 }
305 #endif // I2O_HOTPLUG_SUPPORT
306
307 #ifdef MODULE
308
309 int i2o_pci_core_attach(struct i2o_core_func_table *table)
310 {
311 MOD_INC_USE_COUNT;
312
313 core = table;
314
315 return i2o_pci_scan();
316 }
317
318 void i2o_pci_core_detach(void)
319 {
320 core = NULL;
321
322 MOD_DEC_USE_COUNT;
323 }
324
325 int init_module(void)
326 {
327 printk(KERN_INFO "Linux I2O PCI support (c) 1999 Red Hat Software.\n");
328
329 core = NULL;
330
331 return 0;
332
333 }
334
335 void cleanup_module(void)
336 {
337 }
338
339 EXPORT_SYMBOL(i2o_pci_core_attach);
340 EXPORT_SYMBOL(i2o_pci_core_detach);
341
342 MODULE_AUTHOR("Red Hat Software");
343 MODULE_DESCRIPTION("I2O PCI Interface");
344
345 #else
346 void __init i2o_pci_init(void)
347 {
348 printk(KERN_INFO "Linux I2O PCI support (c) 1999 Red Hat Software.\n");
349 i2o_pci_scan();
350 }
351 #endif
352
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.