rdma/siw: network and RDMA core interface
[linux-2.6-block.git] / drivers / sn / ioc3.c
CommitLineData
09c434b8 1// SPDX-License-Identifier: GPL-2.0-only
2d0cfb52
PG
2/*
3 * SGI IOC3 master driver and IRQ demuxer
4 *
5 * Copyright (c) 2005 Stanislaw Skowronek <skylark@linux-mips.org>
6 * Heavily based on similar work by:
7 * Brent Casavant <bcasavan@sgi.com> - IOC4 master driver
8 * Pat Gefre <pfg@sgi.com> - IOC3 serial port IRQ demuxer
9 */
10
2d0cfb52
PG
11#include <linux/errno.h>
12#include <linux/module.h>
13#include <linux/pci.h>
56b146d3 14#include <linux/dma-mapping.h>
2d0cfb52
PG
15#include <linux/interrupt.h>
16#include <linux/spinlock.h>
17#include <linux/delay.h>
18#include <linux/ioc3.h>
19#include <linux/rwsem.h>
5a0e3ad6 20#include <linux/slab.h>
2d0cfb52
PG
21
22#define IOC3_PCI_SIZE 0x100000
23
24static LIST_HEAD(ioc3_devices);
25static int ioc3_counter;
26static DECLARE_RWSEM(ioc3_devices_rwsem);
27
28static struct ioc3_submodule *ioc3_submodules[IOC3_MAX_SUBMODULES];
29static struct ioc3_submodule *ioc3_ethernet;
34af946a 30static DEFINE_RWLOCK(ioc3_submodules_lock);
2d0cfb52
PG
31
32/* NIC probing code */
33
34#define GPCR_MLAN_EN 0x00200000 /* enable MCR to pin 8 */
35
36static inline unsigned mcr_pack(unsigned pulse, unsigned sample)
37{
38 return (pulse << 10) | (sample << 2);
39}
40
41static int nic_wait(struct ioc3_driver_data *idd)
42{
d6561010 43 unsigned mcr;
2d0cfb52
PG
44
45 do {
d6561010 46 mcr = readl(&idd->vma->mcr);
2d0cfb52
PG
47 } while (!(mcr & 2));
48
49 return mcr & 1;
50}
51
52static int nic_reset(struct ioc3_driver_data *idd)
53{
54 int presence;
55 unsigned long flags;
56
57 local_irq_save(flags);
d6561010 58 writel(mcr_pack(500, 65), &idd->vma->mcr);
2d0cfb52
PG
59 presence = nic_wait(idd);
60 local_irq_restore(flags);
61
62 udelay(500);
63
64 return presence;
65}
66
15b370c9 67static int nic_read_bit(struct ioc3_driver_data *idd)
2d0cfb52
PG
68{
69 int result;
70 unsigned long flags;
71
72 local_irq_save(flags);
d6561010 73 writel(mcr_pack(6, 13), &idd->vma->mcr);
2d0cfb52
PG
74 result = nic_wait(idd);
75 local_irq_restore(flags);
76
77 udelay(500);
78
79 return result;
80}
81
15b370c9 82static void nic_write_bit(struct ioc3_driver_data *idd, int bit)
2d0cfb52
PG
83{
84 if (bit)
d6561010 85 writel(mcr_pack(6, 110), &idd->vma->mcr);
2d0cfb52 86 else
d6561010 87 writel(mcr_pack(80, 30), &idd->vma->mcr);
2d0cfb52
PG
88
89 nic_wait(idd);
90}
91
92static unsigned nic_read_byte(struct ioc3_driver_data *idd)
93{
94 unsigned result = 0;
95 int i;
96
97 for (i = 0; i < 8; i++)
98 result = (result >> 1) | (nic_read_bit(idd) << 7);
99
100 return result;
101}
102
103static void nic_write_byte(struct ioc3_driver_data *idd, int byte)
104{
105 int i, bit;
106
107 for (i = 8; i; i--) {
108 bit = byte & 1;
109 byte >>= 1;
110
111 nic_write_bit(idd, bit);
112 }
113}
114
115static unsigned long
116nic_find(struct ioc3_driver_data *idd, int *last, unsigned long addr)
117{
118 int a, b, index, disc;
119
120 nic_reset(idd);
121
122 /* Search ROM. */
123 nic_write_byte(idd, 0xF0);
124
125 /* Algorithm from ``Book of iButton Standards''. */
126 for (index = 0, disc = 0; index < 64; index++) {
127 a = nic_read_bit(idd);
128 b = nic_read_bit(idd);
129
130 if (a && b) {
131 printk(KERN_WARNING "IOC3 NIC search failed.\n");
132 *last = 0;
133 return 0;
134 }
135
136 if (!a && !b) {
137 if (index == *last) {
138 addr |= 1UL << index;
139 } else if (index > *last) {
140 addr &= ~(1UL << index);
141 disc = index;
142 } else if ((addr & (1UL << index)) == 0)
143 disc = index;
144 nic_write_bit(idd, (addr>>index)&1);
145 continue;
146 } else {
147 if (a)
148 addr |= 1UL << index;
149 else
150 addr &= ~(1UL << index);
151 nic_write_bit(idd, a);
152 continue;
153 }
154 }
155 *last = disc;
156 return addr;
157}
158
159static void nic_addr(struct ioc3_driver_data *idd, unsigned long addr)
160{
161 int index;
162
163 nic_reset(idd);
164 nic_write_byte(idd, 0xF0);
165 for (index = 0; index < 64; index++) {
166 nic_read_bit(idd);
167 nic_read_bit(idd);
168 nic_write_bit(idd, (addr>>index)&1);
169 }
170}
171
172static void crc16_byte(unsigned int *crc, unsigned char db)
173{
174 int i;
175
176 for(i=0;i<8;i++) {
177 *crc <<= 1;
178 if((db^(*crc>>16)) & 1)
179 *crc ^= 0x8005;
180 db >>= 1;
181 }
182 *crc &= 0xFFFF;
183}
184
185static unsigned int crc16_area(unsigned char *dbs, int size, unsigned int crc)
186{
187 while(size--)
188 crc16_byte(&crc, *(dbs++));
189 return crc;
190}
191
192static void crc8_byte(unsigned int *crc, unsigned char db)
193{
194 int i,f;
195
196 for(i=0;i<8;i++) {
197 f = (*crc ^ db) & 1;
198 *crc >>= 1;
199 db >>= 1;
200 if(f)
201 *crc ^= 0x8c;
202 }
203 *crc &= 0xff;
204}
205
206static unsigned int crc8_addr(unsigned long addr)
207{
208 int i;
209 unsigned int crc = 0x00;
210
211 for(i=0;i<8;i++)
212 crc8_byte(&crc, addr>>(i<<3));
213 return crc;
214}
215
216static void
217read_redir_page(struct ioc3_driver_data *idd, unsigned long addr, int page,
218 unsigned char *redir, unsigned char *data)
219{
220 int loops = 16, i;
221
222 while(redir[page] != 0xFF) {
223 page = redir[page]^0xFF;
224 loops--;
225 if(loops<0) {
226 printk(KERN_ERR "IOC3: NIC circular redirection\n");
227 return;
228 }
229 }
230 loops = 3;
231 while(loops>0) {
232 nic_addr(idd, addr);
233 nic_write_byte(idd, 0xF0);
234 nic_write_byte(idd, (page << 5) & 0xE0);
235 nic_write_byte(idd, (page >> 3) & 0x1F);
236 for(i=0;i<0x20;i++)
237 data[i] = nic_read_byte(idd);
238 if(crc16_area(data, 0x20, 0x0000) == 0x800d)
239 return;
240 loops--;
241 }
242 printk(KERN_ERR "IOC3: CRC error in data page\n");
243 for(i=0;i<0x20;i++)
244 data[i] = 0x00;
245}
246
247static void
248read_redir_map(struct ioc3_driver_data *idd, unsigned long addr,
249 unsigned char *redir)
250{
251 int i,j,loops = 3,crc_ok;
252 unsigned int crc;
253
254 while(loops>0) {
255 crc_ok = 1;
256 nic_addr(idd, addr);
257 nic_write_byte(idd, 0xAA);
258 nic_write_byte(idd, 0x00);
259 nic_write_byte(idd, 0x01);
260 for(i=0;i<64;i+=8) {
261 for(j=0;j<8;j++)
262 redir[i+j] = nic_read_byte(idd);
263 crc = crc16_area(redir+i, 8, (i==0)?0x8707:0x0000);
264 crc16_byte(&crc, nic_read_byte(idd));
265 crc16_byte(&crc, nic_read_byte(idd));
266 if(crc != 0x800d)
267 crc_ok = 0;
268 }
269 if(crc_ok)
270 return;
271 loops--;
272 }
273 printk(KERN_ERR "IOC3: CRC error in redirection page\n");
274 for(i=0;i<64;i++)
275 redir[i] = 0xFF;
276}
277
278static void read_nic(struct ioc3_driver_data *idd, unsigned long addr)
279{
280 unsigned char redir[64];
281 unsigned char data[64],part[32];
282 int i,j;
283
284 /* read redirections */
285 read_redir_map(idd, addr, redir);
286 /* read data pages */
287 read_redir_page(idd, addr, 0, redir, data);
288 read_redir_page(idd, addr, 1, redir, data+32);
289 /* assemble the part # */
290 j=0;
291 for(i=0;i<19;i++)
292 if(data[i+11] != ' ')
293 part[j++] = data[i+11];
294 for(i=0;i<6;i++)
295 if(data[i+32] != ' ')
296 part[j++] = data[i+32];
297 part[j] = 0;
298 /* skip Octane power supplies */
299 if(!strncmp(part, "060-0035-", 9))
300 return;
301 if(!strncmp(part, "060-0038-", 9))
302 return;
303 strcpy(idd->nic_part, part);
304 /* assemble the serial # */
305 j=0;
306 for(i=0;i<10;i++)
307 if(data[i+1] != ' ')
308 idd->nic_serial[j++] = data[i+1];
309 idd->nic_serial[j] = 0;
310}
311
312static void read_mac(struct ioc3_driver_data *idd, unsigned long addr)
313{
314 int i, loops = 3;
315 unsigned char data[13];
316
317 while(loops>0) {
318 nic_addr(idd, addr);
319 nic_write_byte(idd, 0xF0);
320 nic_write_byte(idd, 0x00);
321 nic_write_byte(idd, 0x00);
322 nic_read_byte(idd);
323 for(i=0;i<13;i++)
324 data[i] = nic_read_byte(idd);
325 if(crc16_area(data, 13, 0x0000) == 0x800d) {
326 for(i=10;i>4;i--)
327 idd->nic_mac[10-i] = data[i];
328 return;
329 }
330 loops--;
331 }
332 printk(KERN_ERR "IOC3: CRC error in MAC address\n");
333 for(i=0;i<6;i++)
334 idd->nic_mac[i] = 0x00;
335}
336
337static void probe_nic(struct ioc3_driver_data *idd)
338{
339 int save = 0, loops = 3;
340 unsigned long first, addr;
341
d6561010 342 writel(GPCR_MLAN_EN, &idd->vma->gpcr_s);
2d0cfb52
PG
343
344 while(loops>0) {
345 idd->nic_part[0] = 0;
346 idd->nic_serial[0] = 0;
347 addr = first = nic_find(idd, &save, 0);
348 if(!first)
349 return;
350 while(1) {
351 if(crc8_addr(addr))
352 break;
353 else {
354 switch(addr & 0xFF) {
355 case 0x0B:
356 read_nic(idd, addr);
357 break;
358 case 0x09:
359 case 0x89:
360 case 0x91:
361 read_mac(idd, addr);
362 break;
363 }
364 }
365 addr = nic_find(idd, &save, addr);
366 if(addr == first)
367 return;
368 }
369 loops--;
370 }
371 printk(KERN_ERR "IOC3: CRC error in NIC address\n");
372}
373
374/* Interrupts */
375
15b370c9 376static void write_ireg(struct ioc3_driver_data *idd, uint32_t val, int which)
2d0cfb52
PG
377{
378 unsigned long flags;
379
380 spin_lock_irqsave(&idd->ir_lock, flags);
381 switch (which) {
382 case IOC3_W_IES:
383 writel(val, &idd->vma->sio_ies);
384 break;
385 case IOC3_W_IEC:
386 writel(val, &idd->vma->sio_iec);
387 break;
388 }
389 spin_unlock_irqrestore(&idd->ir_lock, flags);
390}
391static inline uint32_t get_pending_intrs(struct ioc3_driver_data *idd)
392{
393 unsigned long flag;
394 uint32_t intrs = 0;
395
396 spin_lock_irqsave(&idd->ir_lock, flag);
397 intrs = readl(&idd->vma->sio_ir);
398 intrs &= readl(&idd->vma->sio_ies);
399 spin_unlock_irqrestore(&idd->ir_lock, flag);
400 return intrs;
401}
402
7d12e780 403static irqreturn_t ioc3_intr_io(int irq, void *arg)
2d0cfb52
PG
404{
405 unsigned long flags;
c7bec5ab 406 struct ioc3_driver_data *idd = arg;
2d0cfb52
PG
407 int handled = 1, id;
408 unsigned int pending;
409
410 read_lock_irqsave(&ioc3_submodules_lock, flags);
411
d6561010 412 if(idd->dual_irq && readb(&idd->vma->eisr)) {
2d0cfb52
PG
413 /* send Ethernet IRQ to the driver */
414 if(ioc3_ethernet && idd->active[ioc3_ethernet->id] &&
415 ioc3_ethernet->intr) {
416 handled = handled && !ioc3_ethernet->intr(ioc3_ethernet,
7d12e780 417 idd, 0);
2d0cfb52
PG
418 }
419 }
420 pending = get_pending_intrs(idd); /* look at the IO IRQs */
421
422 for(id=0;id<IOC3_MAX_SUBMODULES;id++) {
423 if(idd->active[id] && ioc3_submodules[id]
424 && (pending & ioc3_submodules[id]->irq_mask)
425 && ioc3_submodules[id]->intr) {
426 write_ireg(idd, ioc3_submodules[id]->irq_mask,
427 IOC3_W_IEC);
428 if(!ioc3_submodules[id]->intr(ioc3_submodules[id],
7d12e780 429 idd, pending & ioc3_submodules[id]->irq_mask))
2d0cfb52
PG
430 pending &= ~ioc3_submodules[id]->irq_mask;
431 if (ioc3_submodules[id]->reset_mask)
432 write_ireg(idd, ioc3_submodules[id]->irq_mask,
433 IOC3_W_IES);
434 }
435 }
436 read_unlock_irqrestore(&ioc3_submodules_lock, flags);
437 if(pending) {
438 printk(KERN_WARNING
439 "IOC3: Pending IRQs 0x%08x discarded and disabled\n",pending);
440 write_ireg(idd, pending, IOC3_W_IEC);
441 handled = 1;
442 }
443 return handled?IRQ_HANDLED:IRQ_NONE;
444}
445
7d12e780 446static irqreturn_t ioc3_intr_eth(int irq, void *arg)
2d0cfb52
PG
447{
448 unsigned long flags;
449 struct ioc3_driver_data *idd = (struct ioc3_driver_data *)arg;
450 int handled = 1;
451
452 if(!idd->dual_irq)
453 return IRQ_NONE;
454 read_lock_irqsave(&ioc3_submodules_lock, flags);
455 if(ioc3_ethernet && idd->active[ioc3_ethernet->id]
456 && ioc3_ethernet->intr)
7d12e780 457 handled = handled && !ioc3_ethernet->intr(ioc3_ethernet, idd, 0);
2d0cfb52
PG
458 read_unlock_irqrestore(&ioc3_submodules_lock, flags);
459 return handled?IRQ_HANDLED:IRQ_NONE;
460}
461
462void ioc3_enable(struct ioc3_submodule *is,
463 struct ioc3_driver_data *idd, unsigned int irqs)
464{
465 write_ireg(idd, irqs & is->irq_mask, IOC3_W_IES);
466}
467
468void ioc3_ack(struct ioc3_submodule *is, struct ioc3_driver_data *idd,
469 unsigned int irqs)
470{
471 writel(irqs & is->irq_mask, &idd->vma->sio_ir);
472}
473
474void ioc3_disable(struct ioc3_submodule *is,
475 struct ioc3_driver_data *idd, unsigned int irqs)
476{
477 write_ireg(idd, irqs & is->irq_mask, IOC3_W_IEC);
478}
479
480void ioc3_gpcr_set(struct ioc3_driver_data *idd, unsigned int val)
481{
482 unsigned long flags;
483 spin_lock_irqsave(&idd->gpio_lock, flags);
484 writel(val, &idd->vma->gpcr_s);
485 spin_unlock_irqrestore(&idd->gpio_lock, flags);
486}
487
488/* Keep it simple, stupid! */
489static int find_slot(void **tab, int max)
490{
491 int i;
492 for(i=0;i<max;i++)
493 if(!(tab[i]))
494 return i;
495 return -1;
496}
497
498/* Register an IOC3 submodule */
499int ioc3_register_submodule(struct ioc3_submodule *is)
500{
501 struct ioc3_driver_data *idd;
502 int alloc_id;
503 unsigned long flags;
504
505 write_lock_irqsave(&ioc3_submodules_lock, flags);
506 alloc_id = find_slot((void **)ioc3_submodules, IOC3_MAX_SUBMODULES);
507 if(alloc_id != -1) {
508 ioc3_submodules[alloc_id] = is;
509 if(is->ethernet) {
510 if(ioc3_ethernet==NULL)
511 ioc3_ethernet=is;
512 else
513 printk(KERN_WARNING
514 "IOC3 Ethernet module already registered!\n");
515 }
516 }
517 write_unlock_irqrestore(&ioc3_submodules_lock, flags);
518
519 if(alloc_id == -1) {
520 printk(KERN_WARNING "Increase IOC3_MAX_SUBMODULES!\n");
521 return -ENOMEM;
522 }
523
524 is->id=alloc_id;
525
526 /* Initialize submodule for each IOC3 */
527 if (!is->probe)
528 return 0;
529
530 down_read(&ioc3_devices_rwsem);
531 list_for_each_entry(idd, &ioc3_devices, list) {
532 /* set to 1 for IRQs in probe */
533 idd->active[alloc_id] = 1;
534 idd->active[alloc_id] = !is->probe(is, idd);
535 }
536 up_read(&ioc3_devices_rwsem);
537
538 return 0;
539}
540
541/* Unregister an IOC3 submodule */
542void ioc3_unregister_submodule(struct ioc3_submodule *is)
543{
544 struct ioc3_driver_data *idd;
545 unsigned long flags;
546
547 write_lock_irqsave(&ioc3_submodules_lock, flags);
548 if(ioc3_submodules[is->id]==is)
549 ioc3_submodules[is->id]=NULL;
550 else
551 printk(KERN_WARNING
552 "IOC3 submodule %s has wrong ID.\n",is->name);
553 if(ioc3_ethernet==is)
554 ioc3_ethernet = NULL;
555 write_unlock_irqrestore(&ioc3_submodules_lock, flags);
556
557 /* Remove submodule for each IOC3 */
558 down_read(&ioc3_devices_rwsem);
559 list_for_each_entry(idd, &ioc3_devices, list)
560 if(idd->active[is->id]) {
561 if(is->remove)
562 if(is->remove(is, idd))
563 printk(KERN_WARNING
564 "%s: IOC3 submodule %s remove failed "
565 "for pci_dev %s.\n",
9150c979 566 __func__, module_name(is->owner),
2d0cfb52
PG
567 pci_name(idd->pdev));
568 idd->active[is->id] = 0;
569 if(is->irq_mask)
570 write_ireg(idd, is->irq_mask, IOC3_W_IEC);
571 }
572 up_read(&ioc3_devices_rwsem);
573}
574
575/*********************
576 * Device management *
577 *********************/
578
0fe763c5
GKH
579static char *ioc3_class_names[] = { "unknown", "IP27 BaseIO", "IP30 system",
580 "MENET 1/2/3", "MENET 4", "CADduo", "Altix Serial" };
2d0cfb52 581
0fe763c5 582static int ioc3_class(struct ioc3_driver_data *idd)
2d0cfb52
PG
583{
584 int res = IOC3_CLASS_NONE;
585 /* NIC-based logic */
586 if(!strncmp(idd->nic_part, "030-0891-", 9))
587 res = IOC3_CLASS_BASE_IP30;
588 if(!strncmp(idd->nic_part, "030-1155-", 9))
589 res = IOC3_CLASS_CADDUO;
590 if(!strncmp(idd->nic_part, "030-1657-", 9))
591 res = IOC3_CLASS_SERIAL;
592 if(!strncmp(idd->nic_part, "030-1664-", 9))
593 res = IOC3_CLASS_SERIAL;
594 /* total random heuristics */
595#ifdef CONFIG_SGI_IP27
596 if(!idd->nic_part[0])
597 res = IOC3_CLASS_BASE_IP27;
598#endif
599 /* print educational message */
600 printk(KERN_INFO "IOC3 part: [%s], serial: [%s] => class %s\n",
601 idd->nic_part, idd->nic_serial, ioc3_class_names[res]);
602 return res;
603}
604/* Adds a new instance of an IOC3 card */
0fe763c5 605static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
2d0cfb52
PG
606{
607 struct ioc3_driver_data *idd;
608 uint32_t pcmd;
609 int ret, id;
610
611 /* Enable IOC3 and take ownership of it */
612 if ((ret = pci_enable_device(pdev))) {
613 printk(KERN_WARNING
614 "%s: Failed to enable IOC3 device for pci_dev %s.\n",
9150c979 615 __func__, pci_name(pdev));
2d0cfb52
PG
616 goto out;
617 }
618 pci_set_master(pdev);
619
620#ifdef USE_64BIT_DMA
6a35528a 621 ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
2d0cfb52 622 if (!ret) {
6a35528a 623 ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
2d0cfb52
PG
624 if (ret < 0) {
625 printk(KERN_WARNING "%s: Unable to obtain 64 bit DMA "
626 "for consistent allocations\n",
9150c979 627 __func__);
2d0cfb52
PG
628 }
629 }
630#endif
631
632 /* Set up per-IOC3 data */
dd00cc48 633 idd = kzalloc(sizeof(struct ioc3_driver_data), GFP_KERNEL);
2d0cfb52
PG
634 if (!idd) {
635 printk(KERN_WARNING
636 "%s: Failed to allocate IOC3 data for pci_dev %s.\n",
9150c979 637 __func__, pci_name(pdev));
2d0cfb52
PG
638 ret = -ENODEV;
639 goto out_idd;
640 }
2d0cfb52
PG
641 spin_lock_init(&idd->ir_lock);
642 spin_lock_init(&idd->gpio_lock);
643 idd->pdev = pdev;
644
645 /* Map all IOC3 registers. These are shared between subdevices
646 * so the main IOC3 module manages them.
647 */
648 idd->pma = pci_resource_start(pdev, 0);
649 if (!idd->pma) {
650 printk(KERN_WARNING
651 "%s: Unable to find IOC3 resource "
652 "for pci_dev %s.\n",
9150c979 653 __func__, pci_name(pdev));
2d0cfb52
PG
654 ret = -ENODEV;
655 goto out_pci;
656 }
52c9ae0a 657 if (!request_mem_region(idd->pma, IOC3_PCI_SIZE, "ioc3")) {
2d0cfb52
PG
658 printk(KERN_WARNING
659 "%s: Unable to request IOC3 region "
660 "for pci_dev %s.\n",
9150c979 661 __func__, pci_name(pdev));
2d0cfb52
PG
662 ret = -ENODEV;
663 goto out_pci;
664 }
665 idd->vma = ioremap(idd->pma, IOC3_PCI_SIZE);
666 if (!idd->vma) {
667 printk(KERN_WARNING
668 "%s: Unable to remap IOC3 region "
669 "for pci_dev %s.\n",
9150c979 670 __func__, pci_name(pdev));
2d0cfb52
PG
671 ret = -ENODEV;
672 goto out_misc_region;
673 }
674
675 /* Track PCI-device specific data */
676 pci_set_drvdata(pdev, idd);
677 down_write(&ioc3_devices_rwsem);
2c43630f 678 list_add_tail(&idd->list, &ioc3_devices);
2d0cfb52
PG
679 idd->id = ioc3_counter++;
680 up_write(&ioc3_devices_rwsem);
681
d6561010 682 idd->gpdr_shadow = readl(&idd->vma->gpdr);
2d0cfb52
PG
683
684 /* Read IOC3 NIC contents */
685 probe_nic(idd);
686
687 /* Detect IOC3 class */
688 idd->class = ioc3_class(idd);
689
690 /* Initialize IOC3 */
691 pci_read_config_dword(pdev, PCI_COMMAND, &pcmd);
692 pci_write_config_dword(pdev, PCI_COMMAND,
693 pcmd | PCI_COMMAND_MEMORY |
694 PCI_COMMAND_PARITY | PCI_COMMAND_SERR |
695 PCI_SCR_DROP_MODE_EN);
696
697 write_ireg(idd, ~0, IOC3_W_IEC);
698 writel(~0, &idd->vma->sio_ir);
699
700 /* Set up IRQs */
701 if(idd->class == IOC3_CLASS_BASE_IP30
702 || idd->class == IOC3_CLASS_BASE_IP27) {
703 writel(0, &idd->vma->eier);
704 writel(~0, &idd->vma->eisr);
705
706 idd->dual_irq = 1;
dace1453 707 if (!request_irq(pdev->irq, ioc3_intr_eth, IRQF_SHARED,
2d0cfb52
PG
708 "ioc3-eth", (void *)idd)) {
709 idd->irq_eth = pdev->irq;
710 } else {
711 printk(KERN_WARNING
712 "%s : request_irq fails for IRQ 0x%x\n ",
9150c979 713 __func__, pdev->irq);
2d0cfb52 714 }
dace1453 715 if (!request_irq(pdev->irq+2, ioc3_intr_io, IRQF_SHARED,
2d0cfb52
PG
716 "ioc3-io", (void *)idd)) {
717 idd->irq_io = pdev->irq+2;
718 } else {
719 printk(KERN_WARNING
720 "%s : request_irq fails for IRQ 0x%x\n ",
9150c979 721 __func__, pdev->irq+2);
2d0cfb52
PG
722 }
723 } else {
dace1453 724 if (!request_irq(pdev->irq, ioc3_intr_io, IRQF_SHARED,
2d0cfb52
PG
725 "ioc3", (void *)idd)) {
726 idd->irq_io = pdev->irq;
727 } else {
728 printk(KERN_WARNING
729 "%s : request_irq fails for IRQ 0x%x\n ",
9150c979 730 __func__, pdev->irq);
2d0cfb52
PG
731 }
732 }
733
734 /* Add this IOC3 to all submodules */
2d0cfb52
PG
735 for(id=0;id<IOC3_MAX_SUBMODULES;id++)
736 if(ioc3_submodules[id] && ioc3_submodules[id]->probe) {
737 idd->active[id] = 1;
738 idd->active[id] = !ioc3_submodules[id]->probe
739 (ioc3_submodules[id], idd);
740 }
2d0cfb52
PG
741
742 printk(KERN_INFO "IOC3 Master Driver loaded for %s\n", pci_name(pdev));
743
744 return 0;
745
746out_misc_region:
52c9ae0a 747 release_mem_region(idd->pma, IOC3_PCI_SIZE);
2d0cfb52
PG
748out_pci:
749 kfree(idd);
750out_idd:
751 pci_disable_device(pdev);
752out:
753 return ret;
754}
755
756/* Removes a particular instance of an IOC3 card. */
0fe763c5 757static void ioc3_remove(struct pci_dev *pdev)
2d0cfb52
PG
758{
759 int id;
760 struct ioc3_driver_data *idd;
761
762 idd = pci_get_drvdata(pdev);
763
764 /* Remove this IOC3 from all submodules */
2d0cfb52
PG
765 for(id=0;id<IOC3_MAX_SUBMODULES;id++)
766 if(idd->active[id]) {
767 if(ioc3_submodules[id] && ioc3_submodules[id]->remove)
768 if(ioc3_submodules[id]->remove(ioc3_submodules[id],
769 idd))
770 printk(KERN_WARNING
771 "%s: IOC3 submodule 0x%s remove failed "
772 "for pci_dev %s.\n",
9150c979 773 __func__,
2d0cfb52
PG
774 module_name(ioc3_submodules[id]->owner),
775 pci_name(pdev));
776 idd->active[id] = 0;
777 }
2d0cfb52
PG
778
779 /* Clear and disable all IRQs */
780 write_ireg(idd, ~0, IOC3_W_IEC);
781 writel(~0, &idd->vma->sio_ir);
782
783 /* Release resources */
784 free_irq(idd->irq_io, (void *)idd);
785 if(idd->dual_irq)
786 free_irq(idd->irq_eth, (void *)idd);
787 iounmap(idd->vma);
52c9ae0a 788 release_mem_region(idd->pma, IOC3_PCI_SIZE);
2d0cfb52
PG
789
790 /* Disable IOC3 and relinquish */
791 pci_disable_device(pdev);
792
793 /* Remove and free driver data */
794 down_write(&ioc3_devices_rwsem);
795 list_del(&idd->list);
796 up_write(&ioc3_devices_rwsem);
797 kfree(idd);
798}
799
800static struct pci_device_id ioc3_id_table[] = {
801 {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, PCI_ANY_ID, PCI_ANY_ID},
802 {0}
803};
804
805static struct pci_driver ioc3_driver = {
806 .name = "IOC3",
807 .id_table = ioc3_id_table,
808 .probe = ioc3_probe,
0fe763c5 809 .remove = ioc3_remove,
2d0cfb52
PG
810};
811
812MODULE_DEVICE_TABLE(pci, ioc3_id_table);
813
814/*********************
815 * Module management *
816 *********************/
817
818/* Module load */
2ea5d35a 819static int __init ioc3_init(void)
2d0cfb52
PG
820{
821 if (ia64_platform_is("sn2"))
822 return pci_register_driver(&ioc3_driver);
9385565e 823 return -ENODEV;
2d0cfb52
PG
824}
825
826/* Module unload */
2ea5d35a 827static void __exit ioc3_exit(void)
2d0cfb52
PG
828{
829 pci_unregister_driver(&ioc3_driver);
830}
831
832module_init(ioc3_init);
833module_exit(ioc3_exit);
834
835MODULE_AUTHOR("Stanislaw Skowronek <skylark@linux-mips.org>");
836MODULE_DESCRIPTION("PCI driver for SGI IOC3");
837MODULE_LICENSE("GPL");
838
53d8be5c
PG
839EXPORT_SYMBOL_GPL(ioc3_register_submodule);
840EXPORT_SYMBOL_GPL(ioc3_unregister_submodule);
841EXPORT_SYMBOL_GPL(ioc3_ack);
842EXPORT_SYMBOL_GPL(ioc3_gpcr_set);
843EXPORT_SYMBOL_GPL(ioc3_disable);
844EXPORT_SYMBOL_GPL(ioc3_enable);