aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ide/pci/sgiioc4.c30
-rw-r--r--drivers/serial/ioc4_serial.c311
-rw-r--r--drivers/sn/ioc4.c290
3 files changed, 416 insertions, 215 deletions
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index 4651a22bf12e..af526b671c4e 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -34,7 +34,7 @@
34#include <linux/mm.h> 34#include <linux/mm.h>
35#include <linux/ioport.h> 35#include <linux/ioport.h>
36#include <linux/blkdev.h> 36#include <linux/blkdev.h>
37#include <linux/ioc4_common.h> 37#include <linux/ioc4.h>
38#include <asm/io.h> 38#include <asm/io.h>
39 39
40#include <linux/ide.h> 40#include <linux/ide.h>
@@ -715,14 +715,34 @@ static ide_pci_device_t sgiioc4_chipsets[] __devinitdata = {
715}; 715};
716 716
717int 717int
718ioc4_ide_attach_one(struct pci_dev *dev, const struct pci_device_id *id) 718ioc4_ide_attach_one(struct ioc4_driver_data *idd)
719{ 719{
720 return pci_init_sgiioc4(dev, &sgiioc4_chipsets[id->driver_data]); 720 return pci_init_sgiioc4(idd->idd_pdev,
721 &sgiioc4_chipsets[idd->idd_pci_id->driver_data]);
721} 722}
722 723
724static struct ioc4_submodule ioc4_ide_submodule = {
725 .is_name = "IOC4_ide",
726 .is_owner = THIS_MODULE,
727 .is_probe = ioc4_ide_attach_one,
728/* .is_remove = ioc4_ide_remove_one, */
729};
730
731static int __devinit
732ioc4_ide_init(void)
733{
734 return ioc4_register_submodule(&ioc4_ide_submodule);
735}
736
737static void __devexit
738ioc4_ide_exit(void)
739{
740 ioc4_unregister_submodule(&ioc4_ide_submodule);
741}
742
743module_init(ioc4_ide_init);
744module_exit(ioc4_ide_exit);
723 745
724MODULE_AUTHOR("Aniket Malatpure - Silicon Graphics Inc. (SGI)"); 746MODULE_AUTHOR("Aniket Malatpure - Silicon Graphics Inc. (SGI)");
725MODULE_DESCRIPTION("IDE PCI driver module for SGI IOC4 Base-IO Card"); 747MODULE_DESCRIPTION("IDE PCI driver module for SGI IOC4 Base-IO Card");
726MODULE_LICENSE("GPL"); 748MODULE_LICENSE("GPL");
727
728EXPORT_SYMBOL(ioc4_ide_attach_one);
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
index ba4e13a22a50..da5f10eb4845 100644
--- a/drivers/serial/ioc4_serial.c
+++ b/drivers/serial/ioc4_serial.c
@@ -20,7 +20,7 @@
20#include <linux/serial_reg.h> 20#include <linux/serial_reg.h>
21#include <linux/module.h> 21#include <linux/module.h>
22#include <linux/pci.h> 22#include <linux/pci.h>
23#include <linux/ioc4_common.h> 23#include <linux/ioc4.h>
24#include <linux/serial_core.h> 24#include <linux/serial_core.h>
25 25
26/* 26/*
@@ -130,12 +130,19 @@
130 IOC4_SIO_IR_S3_TX_EXPLICIT) 130 IOC4_SIO_IR_S3_TX_EXPLICIT)
131 131
132/* Bitmasks for IOC4_OTHER_IR, IOC4_OTHER_IEC, and IOC4_OTHER_IES */ 132/* Bitmasks for IOC4_OTHER_IR, IOC4_OTHER_IEC, and IOC4_OTHER_IES */
133#define IOC4_OTHER_IR_ATA_INT 0x00000001 /* ATAPI intr pass-thru */ 133#define IOC4_OTHER_IR_ATA_INT 0x00000001 /* ATAPI intr pass-thru */
134#define IOC4_OTHER_IR_ATA_MEMERR 0x00000002 /* ATAPI DMA PCI error */ 134#define IOC4_OTHER_IR_ATA_MEMERR 0x00000002 /* ATAPI DMA PCI error */
135#define IOC4_OTHER_IR_S0_MEMERR 0x00000004 /* Port 0 PCI error */ 135#define IOC4_OTHER_IR_S0_MEMERR 0x00000004 /* Port 0 PCI error */
136#define IOC4_OTHER_IR_S1_MEMERR 0x00000008 /* Port 1 PCI error */ 136#define IOC4_OTHER_IR_S1_MEMERR 0x00000008 /* Port 1 PCI error */
137#define IOC4_OTHER_IR_S2_MEMERR 0x00000010 /* Port 2 PCI error */ 137#define IOC4_OTHER_IR_S2_MEMERR 0x00000010 /* Port 2 PCI error */
138#define IOC4_OTHER_IR_S3_MEMERR 0x00000020 /* Port 3 PCI error */ 138#define IOC4_OTHER_IR_S3_MEMERR 0x00000020 /* Port 3 PCI error */
139#define IOC4_OTHER_IR_KBD_INT 0x00000040 /* Keyboard/mouse */
140#define IOC4_OTHER_IR_RESERVED 0x007fff80 /* Reserved */
141#define IOC4_OTHER_IR_RT_INT 0x00800000 /* INT_OUT section output */
142#define IOC4_OTHER_IR_GEN_INT 0xff000000 /* Generic pins */
143
144#define IOC4_OTHER_IR_SER_MEMERR (IOC4_OTHER_IR_S0_MEMERR | IOC4_OTHER_IR_S1_MEMERR | \
145 IOC4_OTHER_IR_S2_MEMERR | IOC4_OTHER_IR_S3_MEMERR)
139 146
140/* Bitmasks for IOC4_SIO_CR */ 147/* Bitmasks for IOC4_SIO_CR */
141#define IOC4_SIO_CR_CMD_PULSE_SHIFT 0 /* byte bus strobe shift */ 148#define IOC4_SIO_CR_CMD_PULSE_SHIFT 0 /* byte bus strobe shift */
@@ -274,67 +281,22 @@ struct ioc4_uartregs {
274#define i4u_dlm u2.dlm 281#define i4u_dlm u2.dlm
275#define i4u_fcr u3.fcr 282#define i4u_fcr u3.fcr
276 283
277/* PCI memory space register map addressed using pci_bar0 */ 284/* Serial port registers used for DMA serial I/O */
278struct ioc4_memregs { 285struct ioc4_serial {
279 struct ioc4_mem { 286 uint32_t sbbr01_l;
280 /* Miscellaneous IOC4 registers */ 287 uint32_t sbbr01_h;
281 uint32_t pci_err_addr_l; 288 uint32_t sbbr23_l;
282 uint32_t pci_err_addr_h; 289 uint32_t sbbr23_h;
283 uint32_t sio_ir; 290
284 uint32_t other_ir; 291 struct ioc4_serialregs port_0;
285 292 struct ioc4_serialregs port_1;
286 /* These registers are read-only for general kernel code. */ 293 struct ioc4_serialregs port_2;
287 uint32_t sio_ies_ro; 294 struct ioc4_serialregs port_3;
288 uint32_t other_ies_ro; 295 struct ioc4_uartregs uart_0;
289 uint32_t sio_iec_ro; 296 struct ioc4_uartregs uart_1;
290 uint32_t other_iec_ro; 297 struct ioc4_uartregs uart_2;
291 uint32_t sio_cr; 298 struct ioc4_uartregs uart_3;
292 uint32_t misc_fill1; 299} ioc4_serial;
293 uint32_t int_out;
294 uint32_t misc_fill2;
295 uint32_t gpcr_s;
296 uint32_t gpcr_c;
297 uint32_t gpdr;
298 uint32_t misc_fill3;
299 uint32_t gppr_0;
300 uint32_t gppr_1;
301 uint32_t gppr_2;
302 uint32_t gppr_3;
303 uint32_t gppr_4;
304 uint32_t gppr_5;
305 uint32_t gppr_6;
306 uint32_t gppr_7;
307 } ioc4_mem;
308
309 char misc_fill4[0x100 - 0x5C - 4];
310
311 /* ATA/ATAP registers */
312 uint32_t ata_notused[9];
313 char ata_fill1[0x140 - 0x120 - 4];
314 uint32_t ata_notused1[8];
315 char ata_fill2[0x200 - 0x15C - 4];
316
317 /* Keyboard and mouse registers */
318 uint32_t km_notused[5];;
319 char km_fill1[0x300 - 0x210 - 4];
320
321 /* Serial port registers used for DMA serial I/O */
322 struct ioc4_serial {
323 uint32_t sbbr01_l;
324 uint32_t sbbr01_h;
325 uint32_t sbbr23_l;
326 uint32_t sbbr23_h;
327
328 struct ioc4_serialregs port_0;
329 struct ioc4_serialregs port_1;
330 struct ioc4_serialregs port_2;
331 struct ioc4_serialregs port_3;
332 struct ioc4_uartregs uart_0;
333 struct ioc4_uartregs uart_1;
334 struct ioc4_uartregs uart_2;
335 struct ioc4_uartregs uart_3;
336 } ioc4_serial;
337};
338 300
339/* UART clock speed */ 301/* UART clock speed */
340#define IOC4_SER_XIN_CLK IOC4_SER_XIN_CLK_66 302#define IOC4_SER_XIN_CLK IOC4_SER_XIN_CLK_66
@@ -412,8 +374,8 @@ enum sio_proto {
412 | UART_LCR_WLEN7 | UART_LCR_WLEN8) 374 | UART_LCR_WLEN7 | UART_LCR_WLEN8)
413#define LCR_MASK_STOP_BITS (UART_LCR_STOP) 375#define LCR_MASK_STOP_BITS (UART_LCR_STOP)
414 376
415#define PENDING(_p) (readl(&(_p)->ip_mem->sio_ir) & _p->ip_ienb) 377#define PENDING(_p) (readl(&(_p)->ip_mem->sio_ir.raw) & _p->ip_ienb)
416#define READ_SIO_IR(_p) readl(&(_p)->ip_mem->sio_ir) 378#define READ_SIO_IR(_p) readl(&(_p)->ip_mem->sio_ir.raw)
417 379
418/* Default to 4k buffers */ 380/* Default to 4k buffers */
419#ifdef IOC4_1K_BUFFERS 381#ifdef IOC4_1K_BUFFERS
@@ -447,7 +409,7 @@ struct ioc4_control {
447 */ 409 */
448#define MAX_IOC4_INTR_ENTS (8 * sizeof(uint32_t)) 410#define MAX_IOC4_INTR_ENTS (8 * sizeof(uint32_t))
449struct ioc4_soft { 411struct ioc4_soft {
450 struct ioc4_mem __iomem *is_ioc4_mem_addr; 412 struct ioc4_misc_regs __iomem *is_ioc4_misc_addr;
451 struct ioc4_serial __iomem *is_ioc4_serial_addr; 413 struct ioc4_serial __iomem *is_ioc4_serial_addr;
452 414
453 /* Each interrupt type has an entry in the array */ 415 /* Each interrupt type has an entry in the array */
@@ -486,7 +448,7 @@ struct ioc4_port {
486 struct ioc4_soft *ip_ioc4_soft; 448 struct ioc4_soft *ip_ioc4_soft;
487 449
488 /* pci mem addresses */ 450 /* pci mem addresses */
489 struct ioc4_mem __iomem *ip_mem; 451 struct ioc4_misc_regs __iomem *ip_mem;
490 struct ioc4_serial __iomem *ip_serial; 452 struct ioc4_serial __iomem *ip_serial;
491 struct ioc4_serialregs __iomem *ip_serial_regs; 453 struct ioc4_serialregs __iomem *ip_serial_regs;
492 struct ioc4_uartregs __iomem *ip_uart_regs; 454 struct ioc4_uartregs __iomem *ip_uart_regs;
@@ -553,7 +515,7 @@ struct hooks {
553 uint32_t intr_dma_error; 515 uint32_t intr_dma_error;
554 uint32_t intr_clear; 516 uint32_t intr_clear;
555 uint32_t intr_all; 517 uint32_t intr_all;
556 char rs422_select_pin; 518 int rs422_select_pin;
557}; 519};
558 520
559static struct hooks hooks_array[IOC4_NUM_SERIAL_PORTS] = { 521static struct hooks hooks_array[IOC4_NUM_SERIAL_PORTS] = {
@@ -669,7 +631,7 @@ static void handle_intr(void *arg, uint32_t sio_ir);
669static inline void 631static inline void
670write_ireg(struct ioc4_soft *ioc4_soft, uint32_t val, int which, int type) 632write_ireg(struct ioc4_soft *ioc4_soft, uint32_t val, int which, int type)
671{ 633{
672 struct ioc4_mem __iomem *mem = ioc4_soft->is_ioc4_mem_addr; 634 struct ioc4_misc_regs __iomem *mem = ioc4_soft->is_ioc4_misc_addr;
673 unsigned long flags; 635 unsigned long flags;
674 636
675 spin_lock_irqsave(&ioc4_soft->is_ir_lock, flags); 637 spin_lock_irqsave(&ioc4_soft->is_ir_lock, flags);
@@ -678,11 +640,11 @@ write_ireg(struct ioc4_soft *ioc4_soft, uint32_t val, int which, int type)
678 case IOC4_SIO_INTR_TYPE: 640 case IOC4_SIO_INTR_TYPE:
679 switch (which) { 641 switch (which) {
680 case IOC4_W_IES: 642 case IOC4_W_IES:
681 writel(val, &mem->sio_ies_ro); 643 writel(val, &mem->sio_ies.raw);
682 break; 644 break;
683 645
684 case IOC4_W_IEC: 646 case IOC4_W_IEC:
685 writel(val, &mem->sio_iec_ro); 647 writel(val, &mem->sio_iec.raw);
686 break; 648 break;
687 } 649 }
688 break; 650 break;
@@ -690,11 +652,11 @@ write_ireg(struct ioc4_soft *ioc4_soft, uint32_t val, int which, int type)
690 case IOC4_OTHER_INTR_TYPE: 652 case IOC4_OTHER_INTR_TYPE:
691 switch (which) { 653 switch (which) {
692 case IOC4_W_IES: 654 case IOC4_W_IES:
693 writel(val, &mem->other_ies_ro); 655 writel(val, &mem->other_ies.raw);
694 break; 656 break;
695 657
696 case IOC4_W_IEC: 658 case IOC4_W_IEC:
697 writel(val, &mem->other_iec_ro); 659 writel(val, &mem->other_iec.raw);
698 break; 660 break;
699 } 661 }
700 break; 662 break;
@@ -747,7 +709,8 @@ static int set_baud(struct ioc4_port *port, int baud)
747 */ 709 */
748static struct ioc4_port *get_ioc4_port(struct uart_port *the_port) 710static struct ioc4_port *get_ioc4_port(struct uart_port *the_port)
749{ 711{
750 struct ioc4_control *control = dev_get_drvdata(the_port->dev); 712 struct ioc4_driver_data *idd = dev_get_drvdata(the_port->dev);
713 struct ioc4_control *control = idd->idd_serial_data;
751 int ii; 714 int ii;
752 715
753 if (control) { 716 if (control) {
@@ -782,7 +745,7 @@ static struct ioc4_port *get_ioc4_port(struct uart_port *the_port)
782static inline uint32_t 745static inline uint32_t
783pending_intrs(struct ioc4_soft *soft, int type) 746pending_intrs(struct ioc4_soft *soft, int type)
784{ 747{
785 struct ioc4_mem __iomem *mem = soft->is_ioc4_mem_addr; 748 struct ioc4_misc_regs __iomem *mem = soft->is_ioc4_misc_addr;
786 unsigned long flag; 749 unsigned long flag;
787 uint32_t intrs = 0; 750 uint32_t intrs = 0;
788 751
@@ -793,11 +756,11 @@ pending_intrs(struct ioc4_soft *soft, int type)
793 756
794 switch (type) { 757 switch (type) {
795 case IOC4_SIO_INTR_TYPE: 758 case IOC4_SIO_INTR_TYPE:
796 intrs = readl(&mem->sio_ir) & readl(&mem->sio_ies_ro); 759 intrs = readl(&mem->sio_ir.raw) & readl(&mem->sio_ies.raw);
797 break; 760 break;
798 761
799 case IOC4_OTHER_INTR_TYPE: 762 case IOC4_OTHER_INTR_TYPE:
800 intrs = readl(&mem->other_ir) & readl(&mem->other_ies_ro); 763 intrs = readl(&mem->other_ir.raw) & readl(&mem->other_ies.raw);
801 764
802 /* Don't process any ATA interrupte */ 765 /* Don't process any ATA interrupte */
803 intrs &= ~(IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR); 766 intrs &= ~(IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR);
@@ -826,7 +789,7 @@ static int inline port_init(struct ioc4_port *port)
826 789
827 /* Wait until any pending bus activity for this port has ceased */ 790 /* Wait until any pending bus activity for this port has ceased */
828 do 791 do
829 sio_cr = readl(&port->ip_mem->sio_cr); 792 sio_cr = readl(&port->ip_mem->sio_cr.raw);
830 while (!(sio_cr & IOC4_SIO_CR_SIO_DIAG_IDLE)); 793 while (!(sio_cr & IOC4_SIO_CR_SIO_DIAG_IDLE));
831 794
832 /* Finish reset sequence */ 795 /* Finish reset sequence */
@@ -899,7 +862,7 @@ static int inline port_init(struct ioc4_port *port)
899 write_ireg(port->ip_ioc4_soft, hooks->intr_clear, 862 write_ireg(port->ip_ioc4_soft, hooks->intr_clear,
900 IOC4_W_IEC, IOC4_SIO_INTR_TYPE); 863 IOC4_W_IEC, IOC4_SIO_INTR_TYPE);
901 port->ip_ienb &= ~hooks->intr_clear; 864 port->ip_ienb &= ~hooks->intr_clear;
902 writel(hooks->intr_clear, &port->ip_mem->sio_ir); 865 writel(hooks->intr_clear, &port->ip_mem->sio_ir.raw);
903 return 0; 866 return 0;
904} 867}
905 868
@@ -918,23 +881,23 @@ static void handle_dma_error_intr(void *arg, uint32_t other_ir)
918 spin_lock_irqsave(&port->ip_lock, flags); 881 spin_lock_irqsave(&port->ip_lock, flags);
919 882
920 /* ACK the interrupt */ 883 /* ACK the interrupt */
921 writel(hooks->intr_dma_error, &port->ip_mem->other_ir); 884 writel(hooks->intr_dma_error, &port->ip_mem->other_ir.raw);
922 885
923 if (readl(&port->ip_mem->pci_err_addr_l) & IOC4_PCI_ERR_ADDR_VLD) { 886 if (readl(&port->ip_mem->pci_err_addr_l.raw) & IOC4_PCI_ERR_ADDR_VLD) {
924 printk(KERN_ERR 887 printk(KERN_ERR
925 "PCI error address is 0x%lx, " 888 "PCI error address is 0x%lx, "
926 "master is serial port %c %s\n", 889 "master is serial port %c %s\n",
927 (((uint64_t)readl(&port->ip_mem->pci_err_addr_h) 890 (((uint64_t)readl(&port->ip_mem->pci_err_addr_h)
928 << 32) 891 << 32)
929 | readl(&port->ip_mem->pci_err_addr_l)) 892 | readl(&port->ip_mem->pci_err_addr_l.raw))
930 & IOC4_PCI_ERR_ADDR_ADDR_MSK, '1' + 893 & IOC4_PCI_ERR_ADDR_ADDR_MSK, '1' +
931 ((char)(readl(&port->ip_mem-> pci_err_addr_l) & 894 ((char)(readl(&port->ip_mem->pci_err_addr_l.raw) &
932 IOC4_PCI_ERR_ADDR_MST_NUM_MSK) >> 1), 895 IOC4_PCI_ERR_ADDR_MST_NUM_MSK) >> 1),
933 (readl(&port->ip_mem->pci_err_addr_l) 896 (readl(&port->ip_mem->pci_err_addr_l.raw)
934 & IOC4_PCI_ERR_ADDR_MST_TYP_MSK) 897 & IOC4_PCI_ERR_ADDR_MST_TYP_MSK)
935 ? "RX" : "TX"); 898 ? "RX" : "TX");
936 899
937 if (readl(&port->ip_mem->pci_err_addr_l) 900 if (readl(&port->ip_mem->pci_err_addr_l.raw)
938 & IOC4_PCI_ERR_ADDR_MUL_ERR) { 901 & IOC4_PCI_ERR_ADDR_MUL_ERR) {
939 printk(KERN_ERR 902 printk(KERN_ERR
940 "Multiple errors occurred\n"); 903 "Multiple errors occurred\n");
@@ -1018,26 +981,26 @@ static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs)
1018 "other_ies = 0x%x\n", 981 "other_ies = 0x%x\n",
1019 (intr_type == IOC4_SIO_INTR_TYPE) ? "sio" : 982 (intr_type == IOC4_SIO_INTR_TYPE) ? "sio" :
1020 "other", this_ir, 983 "other", this_ir,
1021 readl(&soft->is_ioc4_mem_addr->sio_ir), 984 readl(&soft->is_ioc4_misc_addr->sio_ir.raw),
1022 readl(&soft->is_ioc4_mem_addr->sio_ies_ro), 985 readl(&soft->is_ioc4_misc_addr->sio_ies.raw),
1023 readl(&soft->is_ioc4_mem_addr->other_ir), 986 readl(&soft->is_ioc4_misc_addr->other_ir.raw),
1024 readl(&soft->is_ioc4_mem_addr->other_ies_ro)); 987 readl(&soft->is_ioc4_misc_addr->other_ies.raw));
1025 } 988 }
1026 } 989 }
1027#ifdef DEBUG_INTERRUPTS 990#ifdef DEBUG_INTERRUPTS
1028 { 991 {
1029 struct ioc4_mem __iomem *mem = soft->is_ioc4_mem_addr; 992 struct ioc4_misc_regs __iomem *mem = soft->is_ioc4_misc_addr;
1030 spinlock_t *lp = &soft->is_ir_lock; 993 spinlock_t *lp = &soft->is_ir_lock;
1031 unsigned long flag; 994 unsigned long flag;
1032 995
1033 spin_lock_irqsave(&soft->is_ir_lock, flag); 996 spin_lock_irqsave(&soft->is_ir_lock, flag);
1034 printk ("%s : %d : mem 0x%p sio_ir 0x%x sio_ies_ro 0x%x " 997 printk ("%s : %d : mem 0x%p sio_ir 0x%x sio_ies 0x%x "
1035 "other_ir 0x%x other_ies_ro 0x%x mask 0x%x\n", 998 "other_ir 0x%x other_ies 0x%x mask 0x%x\n",
1036 __FUNCTION__, __LINE__, 999 __FUNCTION__, __LINE__,
1037 (void *)mem, readl(&mem->sio_ir), 1000 (void *)mem, readl(&mem->sio_ir.raw),
1038 readl(&mem->sio_ies_ro), 1001 readl(&mem->sio_ies.raw),
1039 readl(&mem->other_ir), 1002 readl(&mem->other_ir.raw),
1040 readl(&mem->other_ies_ro), 1003 readl(&mem->other_ies.raw),
1041 IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR); 1004 IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR);
1042 spin_unlock_irqrestore(&soft->is_ir_lock, flag); 1005 spin_unlock_irqrestore(&soft->is_ir_lock, flag);
1043 } 1006 }
@@ -1056,7 +1019,7 @@ static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs)
1056 */ 1019 */
1057static int inline ioc4_attach_local(struct pci_dev *pdev, 1020static int inline ioc4_attach_local(struct pci_dev *pdev,
1058 struct ioc4_control *control, 1021 struct ioc4_control *control,
1059 struct ioc4_soft *soft, void __iomem *ioc4_mem, 1022 struct ioc4_soft *soft, void __iomem *ioc4_misc,
1060 void __iomem *ioc4_serial) 1023 void __iomem *ioc4_serial)
1061{ 1024{
1062 struct ioc4_port *port; 1025 struct ioc4_port *port;
@@ -1076,7 +1039,7 @@ static int inline ioc4_attach_local(struct pci_dev *pdev,
1076 ioc4_revid, ioc4_revid_min); 1039 ioc4_revid, ioc4_revid_min);
1077 return -EPERM; 1040 return -EPERM;
1078 } 1041 }
1079 BUG_ON(ioc4_mem == NULL); 1042 BUG_ON(ioc4_misc == NULL);
1080 BUG_ON(ioc4_serial == NULL); 1043 BUG_ON(ioc4_serial == NULL);
1081 1044
1082 /* Create port structures for each port */ 1045 /* Create port structures for each port */
@@ -1103,7 +1066,7 @@ static int inline ioc4_attach_local(struct pci_dev *pdev,
1103 port->ip_pci_bus_speed = IOC4_SER_XIN_CLK; 1066 port->ip_pci_bus_speed = IOC4_SER_XIN_CLK;
1104 port->ip_baud = 9600; 1067 port->ip_baud = 9600;
1105 port->ip_control = control; 1068 port->ip_control = control;
1106 port->ip_mem = ioc4_mem; 1069 port->ip_mem = ioc4_misc;
1107 port->ip_serial = ioc4_serial; 1070 port->ip_serial = ioc4_serial;
1108 1071
1109 /* point to the right hook */ 1072 /* point to the right hook */
@@ -1604,14 +1567,12 @@ static int ioc4_set_proto(struct ioc4_port *port, enum sio_proto proto)
1604 switch (proto) { 1567 switch (proto) {
1605 case PROTO_RS232: 1568 case PROTO_RS232:
1606 /* Clear the appropriate GIO pin */ 1569 /* Clear the appropriate GIO pin */
1607 writel(0, (&port->ip_mem->gppr_0 + 1570 writel(0, (&port->ip_mem->gppr[hooks->rs422_select_pin].raw));
1608 hooks->rs422_select_pin));
1609 break; 1571 break;
1610 1572
1611 case PROTO_RS422: 1573 case PROTO_RS422:
1612 /* Set the appropriate GIO pin */ 1574 /* Set the appropriate GIO pin */
1613 writel(1, (&port->ip_mem->gppr_0 + 1575 writel(1, (&port->ip_mem->gppr[hooks->rs422_select_pin].raw));
1614 hooks->rs422_select_pin));
1615 break; 1576 break;
1616 1577
1617 default: 1578 default:
@@ -1885,7 +1846,7 @@ static void handle_intr(void *arg, uint32_t sio_ir)
1885 if (sio_ir & hooks->intr_delta_dcd) { 1846 if (sio_ir & hooks->intr_delta_dcd) {
1886 /* ACK the interrupt */ 1847 /* ACK the interrupt */
1887 writel(hooks->intr_delta_dcd, 1848 writel(hooks->intr_delta_dcd,
1888 &port->ip_mem->sio_ir); 1849 &port->ip_mem->sio_ir.raw);
1889 1850
1890 shadow = readl(&port->ip_serial_regs->shadow); 1851 shadow = readl(&port->ip_serial_regs->shadow);
1891 1852
@@ -1907,7 +1868,7 @@ static void handle_intr(void *arg, uint32_t sio_ir)
1907 if (sio_ir & hooks->intr_delta_cts) { 1868 if (sio_ir & hooks->intr_delta_cts) {
1908 /* ACK the interrupt */ 1869 /* ACK the interrupt */
1909 writel(hooks->intr_delta_cts, 1870 writel(hooks->intr_delta_cts,
1910 &port->ip_mem->sio_ir); 1871 &port->ip_mem->sio_ir.raw);
1911 1872
1912 shadow = readl(&port->ip_serial_regs->shadow); 1873 shadow = readl(&port->ip_serial_regs->shadow);
1913 1874
@@ -1928,7 +1889,7 @@ static void handle_intr(void *arg, uint32_t sio_ir)
1928 if (sio_ir & hooks->intr_rx_timer) { 1889 if (sio_ir & hooks->intr_rx_timer) {
1929 /* ACK the interrupt */ 1890 /* ACK the interrupt */
1930 writel(hooks->intr_rx_timer, 1891 writel(hooks->intr_rx_timer,
1931 &port->ip_mem->sio_ir); 1892 &port->ip_mem->sio_ir.raw);
1932 1893
1933 if ((port->ip_notify & N_DATA_READY) 1894 if ((port->ip_notify & N_DATA_READY)
1934 && (port->ip_port)) { 1895 && (port->ip_port)) {
@@ -1974,7 +1935,7 @@ static void handle_intr(void *arg, uint32_t sio_ir)
1974 1935
1975 /* ACK the interrupt */ 1936 /* ACK the interrupt */
1976 writel(hooks->intr_tx_explicit, 1937 writel(hooks->intr_tx_explicit,
1977 &port->ip_mem->sio_ir); 1938 &port->ip_mem->sio_ir.raw);
1978 1939
1979 if (port->ip_notify & N_OUTPUT_LOWAT) 1940 if (port->ip_notify & N_OUTPUT_LOWAT)
1980 ioc4_cb_output_lowat(port); 1941 ioc4_cb_output_lowat(port);
@@ -2634,7 +2595,8 @@ ioc4_serial_core_attach(struct pci_dev *pdev)
2634{ 2595{
2635 struct ioc4_port *port; 2596 struct ioc4_port *port;
2636 struct uart_port *the_port; 2597 struct uart_port *the_port;
2637 struct ioc4_control *control = pci_get_drvdata(pdev); 2598 struct ioc4_driver_data *idd = pci_get_drvdata(pdev);
2599 struct ioc4_control *control = idd->idd_serial_data;
2638 int ii; 2600 int ii;
2639 2601
2640 DPRINT_CONFIG(("%s: attach pdev 0x%p - control 0x%p\n", 2602 DPRINT_CONFIG(("%s: attach pdev 0x%p - control 0x%p\n",
@@ -2680,55 +2642,29 @@ ioc4_serial_core_attach(struct pci_dev *pdev)
2680 2642
2681/** 2643/**
2682 * ioc4_serial_attach_one - register attach function 2644 * ioc4_serial_attach_one - register attach function
2683 * called per card found from ioc4_serial_detect as part 2645 * called per card found from IOC4 master module.
2684 * of module_init(). 2646 * @idd: Master module data for this IOC4
2685 * @pdev: handle for this card
2686 * @pci_id: pci id for this card
2687 */ 2647 */
2688int 2648int
2689ioc4_serial_attach_one(struct pci_dev *pdev, const struct pci_device_id *pci_id) 2649ioc4_serial_attach_one(struct ioc4_driver_data *idd)
2690{ 2650{
2691 struct ioc4_mem __iomem *mem; 2651 unsigned long tmp_addr1;
2692 unsigned long tmp_addr, tmp_addr1;
2693 struct ioc4_serial __iomem *serial; 2652 struct ioc4_serial __iomem *serial;
2694 struct ioc4_soft *soft; 2653 struct ioc4_soft *soft;
2695 struct ioc4_control *control; 2654 struct ioc4_control *control;
2696 int tmp, ret = 0; 2655 int ret = 0;
2697 2656
2698 2657
2699 DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, pdev, pci_id)); 2658 DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, idd->idd_pdev, idd->idd_pci_id));
2700
2701 /* Map in the ioc4 memory */
2702 tmp_addr = pci_resource_start(pdev, 0);
2703 if (!tmp_addr) {
2704 printk(KERN_WARNING
2705 "ioc4 (%p) : unable to get PIO mapping for "
2706 "MEM space\n", (void *)pdev);
2707 return -ENODEV;
2708 }
2709 if (!request_region(tmp_addr, sizeof(struct ioc4_mem), "sioc4_mem")) {
2710 printk(KERN_ALERT
2711 "ioc4 (%p): unable to get request region for "
2712 "MEM space\n", (void *)pdev);
2713 return -ENODEV;
2714 }
2715 mem = ioremap(tmp_addr, sizeof(struct ioc4_mem));
2716 if (!mem) {
2717 printk(KERN_WARNING
2718 "ioc4 (%p) : unable to remap ioc4 memory\n",
2719 (void *)pdev);
2720 ret = -ENODEV;
2721 goto out1;
2722 }
2723 2659
2724 /* request serial registers */ 2660 /* request serial registers */
2725 tmp_addr1 = pci_resource_start(pdev, 0) + IOC4_SERIAL_OFFSET; 2661 tmp_addr1 = idd->idd_bar0 + IOC4_SERIAL_OFFSET;
2726 2662
2727 if (!request_region(tmp_addr1, sizeof(struct ioc4_serial), 2663 if (!request_region(tmp_addr1, sizeof(struct ioc4_serial),
2728 "sioc4_uart")) { 2664 "sioc4_uart")) {
2729 printk(KERN_WARNING 2665 printk(KERN_WARNING
2730 "ioc4 (%p): unable to get request region for " 2666 "ioc4 (%p): unable to get request region for "
2731 "uart space\n", (void *)pdev); 2667 "uart space\n", (void *)idd->idd_pdev);
2732 ret = -ENODEV; 2668 ret = -ENODEV;
2733 goto out1; 2669 goto out1;
2734 } 2670 }
@@ -2736,12 +2672,12 @@ ioc4_serial_attach_one(struct pci_dev *pdev, const struct pci_device_id *pci_id)
2736 if (!serial) { 2672 if (!serial) {
2737 printk(KERN_WARNING 2673 printk(KERN_WARNING
2738 "ioc4 (%p) : unable to remap ioc4 serial register\n", 2674 "ioc4 (%p) : unable to remap ioc4 serial register\n",
2739 (void *)pdev); 2675 (void *)idd->idd_pdev);
2740 ret = -ENODEV; 2676 ret = -ENODEV;
2741 goto out2; 2677 goto out2;
2742 } 2678 }
2743 DPRINT_CONFIG(("%s : mem 0x%p, serial 0x%p\n", 2679 DPRINT_CONFIG(("%s : mem 0x%p, serial 0x%p\n",
2744 __FUNCTION__, (void *)mem, (void *)serial)); 2680 __FUNCTION__, (void *)idd->idd_misc_regs, (void *)serial));
2745 2681
2746 /* Get memory for the new card */ 2682 /* Get memory for the new card */
2747 control = kmalloc(sizeof(struct ioc4_control) * IOC4_NUM_SERIAL_PORTS, 2683 control = kmalloc(sizeof(struct ioc4_control) * IOC4_NUM_SERIAL_PORTS,
@@ -2754,59 +2690,57 @@ ioc4_serial_attach_one(struct pci_dev *pdev, const struct pci_device_id *pci_id)
2754 goto out2; 2690 goto out2;
2755 } 2691 }
2756 memset(control, 0, sizeof(struct ioc4_control)); 2692 memset(control, 0, sizeof(struct ioc4_control));
2757 pci_set_drvdata(pdev, control); 2693 idd->idd_serial_data = control;
2758 2694
2759 /* Allocate the soft structure */ 2695 /* Allocate the soft structure */
2760 soft = kmalloc(sizeof(struct ioc4_soft), GFP_KERNEL); 2696 soft = kmalloc(sizeof(struct ioc4_soft), GFP_KERNEL);
2761 if (!soft) { 2697 if (!soft) {
2762 printk(KERN_WARNING 2698 printk(KERN_WARNING
2763 "ioc4 (%p): unable to get memory for the soft struct\n", 2699 "ioc4 (%p): unable to get memory for the soft struct\n",
2764 (void *)pdev); 2700 (void *)idd->idd_pdev);
2765 ret = -ENOMEM; 2701 ret = -ENOMEM;
2766 goto out3; 2702 goto out3;
2767 } 2703 }
2768 memset(soft, 0, sizeof(struct ioc4_soft)); 2704 memset(soft, 0, sizeof(struct ioc4_soft));
2769 2705
2770 spin_lock_init(&soft->is_ir_lock); 2706 spin_lock_init(&soft->is_ir_lock);
2771 soft->is_ioc4_mem_addr = mem; 2707 soft->is_ioc4_misc_addr = idd->idd_misc_regs;
2772 soft->is_ioc4_serial_addr = serial; 2708 soft->is_ioc4_serial_addr = serial;
2773 2709
2774 /* Init the IOC4 */ 2710 /* Init the IOC4 */
2775 pci_read_config_dword(pdev, PCI_COMMAND, &tmp); 2711 writel(0xf << IOC4_SIO_CR_CMD_PULSE_SHIFT,
2776 pci_write_config_dword(pdev, PCI_COMMAND, 2712 &idd->idd_misc_regs->sio_cr.raw);
2777 tmp | PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
2778
2779 writel(0xf << IOC4_SIO_CR_CMD_PULSE_SHIFT, &mem->sio_cr);
2780 2713
2781 /* Enable serial port mode select generic PIO pins as outputs */ 2714 /* Enable serial port mode select generic PIO pins as outputs */
2782 writel(IOC4_GPCR_UART0_MODESEL | IOC4_GPCR_UART1_MODESEL 2715 writel(IOC4_GPCR_UART0_MODESEL | IOC4_GPCR_UART1_MODESEL
2783 | IOC4_GPCR_UART2_MODESEL | IOC4_GPCR_UART3_MODESEL, 2716 | IOC4_GPCR_UART2_MODESEL | IOC4_GPCR_UART3_MODESEL,
2784 &mem->gpcr_s); 2717 &idd->idd_misc_regs->gpcr_s.raw);
2785 2718
2786 /* Clear and disable all interrupts */ 2719 /* Clear and disable all serial interrupts */
2787 write_ireg(soft, ~0, IOC4_W_IEC, IOC4_SIO_INTR_TYPE); 2720 write_ireg(soft, ~0, IOC4_W_IEC, IOC4_SIO_INTR_TYPE);
2788 writel(~0, &mem->sio_ir); 2721 writel(~0, &idd->idd_misc_regs->sio_ir.raw);
2789 write_ireg(soft, ~(IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR), 2722 write_ireg(soft, IOC4_OTHER_IR_SER_MEMERR, IOC4_W_IEC,
2790 IOC4_W_IEC, IOC4_OTHER_INTR_TYPE); 2723 IOC4_OTHER_INTR_TYPE);
2791 writel(~(IOC4_OTHER_IR_ATA_MEMERR | IOC4_OTHER_IR_ATA_MEMERR), 2724 writel(IOC4_OTHER_IR_SER_MEMERR, &idd->idd_misc_regs->other_ir.raw);
2792 &mem->other_ir);
2793 control->ic_soft = soft; 2725 control->ic_soft = soft;
2794 if (!request_irq(pdev->irq, ioc4_intr, SA_SHIRQ, 2726
2727 /* Hook up interrupt handler */
2728 if (!request_irq(idd->idd_pdev->irq, ioc4_intr, SA_SHIRQ,
2795 "sgi-ioc4serial", (void *)soft)) { 2729 "sgi-ioc4serial", (void *)soft)) {
2796 control->ic_irq = pdev->irq; 2730 control->ic_irq = idd->idd_pdev->irq;
2797 } else { 2731 } else {
2798 printk(KERN_WARNING 2732 printk(KERN_WARNING
2799 "%s : request_irq fails for IRQ 0x%x\n ", 2733 "%s : request_irq fails for IRQ 0x%x\n ",
2800 __FUNCTION__, pdev->irq); 2734 __FUNCTION__, idd->idd_pdev->irq);
2801 } 2735 }
2802 if ((ret = ioc4_attach_local(pdev, control, soft, 2736 if ((ret = ioc4_attach_local(idd->idd_pdev, control, soft,
2803 soft->is_ioc4_mem_addr, 2737 soft->is_ioc4_misc_addr,
2804 soft->is_ioc4_serial_addr))) 2738 soft->is_ioc4_serial_addr)))
2805 goto out4; 2739 goto out4;
2806 2740
2807 /* register port with the serial core */ 2741 /* register port with the serial core */
2808 2742
2809 if ((ret = ioc4_serial_core_attach(pdev))) 2743 if ((ret = ioc4_serial_core_attach(idd->idd_pdev)))
2810 goto out4; 2744 goto out4;
2811 2745
2812 return ret; 2746 return ret;
@@ -2819,7 +2753,6 @@ out3:
2819out2: 2753out2:
2820 release_region(tmp_addr1, sizeof(struct ioc4_serial)); 2754 release_region(tmp_addr1, sizeof(struct ioc4_serial));
2821out1: 2755out1:
2822 release_region(tmp_addr, sizeof(struct ioc4_mem));
2823 2756
2824 return ret; 2757 return ret;
2825} 2758}
@@ -2828,11 +2761,10 @@ out1:
2828/** 2761/**
2829 * ioc4_serial_remove_one - detach function 2762 * ioc4_serial_remove_one - detach function
2830 * 2763 *
2831 * @pdev: handle for this card 2764 * @idd: IOC4 master module data for this IOC4
2832 */ 2765 */
2833 2766
2834#if 0 2767int ioc4_serial_remove_one(struct ioc4_driver_data *idd)
2835void ioc4_serial_remove_one(struct pci_dev *pdev)
2836{ 2768{
2837 int ii; 2769 int ii;
2838 struct ioc4_control *control; 2770 struct ioc4_control *control;
@@ -2840,7 +2772,7 @@ void ioc4_serial_remove_one(struct pci_dev *pdev)
2840 struct ioc4_port *port; 2772 struct ioc4_port *port;
2841 struct ioc4_soft *soft; 2773 struct ioc4_soft *soft;
2842 2774
2843 control = pci_get_drvdata(pdev); 2775 control = idd->idd_serial_data;
2844 2776
2845 for (ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++) { 2777 for (ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++) {
2846 the_port = &control->ic_port[ii].icp_uart_port; 2778 the_port = &control->ic_port[ii].icp_uart_port;
@@ -2867,10 +2799,17 @@ void ioc4_serial_remove_one(struct pci_dev *pdev)
2867 kfree(soft); 2799 kfree(soft);
2868 } 2800 }
2869 kfree(control); 2801 kfree(control);
2870 pci_set_drvdata(pdev, NULL); 2802 idd->idd_serial_data = NULL;
2871 uart_unregister_driver(&ioc4_uart); 2803
2804 return 0;
2872} 2805}
2873#endif 2806
2807static struct ioc4_submodule ioc4_serial_submodule = {
2808 .is_name = "IOC4_serial",
2809 .is_owner = THIS_MODULE,
2810 .is_probe = ioc4_serial_attach_one,
2811 .is_remove = ioc4_serial_remove_one,
2812};
2874 2813
2875/** 2814/**
2876 * ioc4_serial_init - module init 2815 * ioc4_serial_init - module init
@@ -2886,12 +2825,20 @@ int ioc4_serial_init(void)
2886 __FUNCTION__); 2825 __FUNCTION__);
2887 return ret; 2826 return ret;
2888 } 2827 }
2889 return 0; 2828
2829 /* register with IOC4 main module */
2830 return ioc4_register_submodule(&ioc4_serial_submodule);
2890} 2831}
2891 2832
2833static void __devexit ioc4_serial_exit(void)
2834{
2835 ioc4_unregister_submodule(&ioc4_serial_submodule);
2836 uart_unregister_driver(&ioc4_uart);
2837}
2838
2839module_init(ioc4_serial_init);
2840module_exit(ioc4_serial_exit);
2841
2892MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>"); 2842MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>");
2893MODULE_DESCRIPTION("Serial PCI driver module for SGI IOC4 Base-IO Card"); 2843MODULE_DESCRIPTION("Serial PCI driver module for SGI IOC4 Base-IO Card");
2894MODULE_LICENSE("GPL"); 2844MODULE_LICENSE("GPL");
2895
2896EXPORT_SYMBOL(ioc4_serial_init);
2897EXPORT_SYMBOL(ioc4_serial_attach_one);
diff --git a/drivers/sn/ioc4.c b/drivers/sn/ioc4.c
index d9e4ee280e5f..70862d72ea9d 100644
--- a/drivers/sn/ioc4.c
+++ b/drivers/sn/ioc4.c
@@ -6,60 +6,294 @@
6 * Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved. 6 * Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved.
7 */ 7 */
8 8
9/* 9/* This file contains the master driver module for use by SGI IOC4 subdrivers.
10 * This file contains a shim driver for the IOC4 IDE and serial drivers. 10 *
11 * It allocates any resources shared between multiple subdevices, and
12 * provides accessor functions (where needed) and the like for those
13 * resources. It also provides a mechanism for the subdevice modules
14 * to support loading and unloading.
15 *
16 * Non-shared resources (e.g. external interrupt A_INT_OUT register page
17 * alias, serial port and UART registers) are handled by the subdevice
18 * modules themselves.
19 *
20 * This is all necessary because IOC4 is not implemented as a multi-function
21 * PCI device, but an amalgamation of disparate registers for several
22 * types of device (ATA, serial, external interrupts). The normal
23 * resource management in the kernel doesn't have quite the right interfaces
24 * to handle this situation (e.g. multiple modules can't claim the same
25 * PCI ID), thus this IOC4 master module.
11 */ 26 */
12 27
13#include <linux/errno.h> 28#include <linux/errno.h>
14#include <linux/module.h> 29#include <linux/module.h>
15#include <linux/pci.h> 30#include <linux/pci.h>
16#include <linux/ioc4_common.h> 31#include <linux/ioc4.h>
17#include <linux/ide.h> 32#include <linux/rwsem.h>
18 33
34/************************
35 * Submodule management *
36 ************************/
19 37
20static int __devinit 38static LIST_HEAD(ioc4_devices);
21ioc4_probe_one(struct pci_dev *pdev, const struct pci_device_id *pci_id) 39static DECLARE_RWSEM(ioc4_devices_rwsem);
40
41static LIST_HEAD(ioc4_submodules);
42static DECLARE_RWSEM(ioc4_submodules_rwsem);
43
44/* Register an IOC4 submodule */
45int
46ioc4_register_submodule(struct ioc4_submodule *is)
47{
48 struct ioc4_driver_data *idd;
49
50 down_write(&ioc4_submodules_rwsem);
51 list_add(&is->is_list, &ioc4_submodules);
52 up_write(&ioc4_submodules_rwsem);
53
54 /* Initialize submodule for each IOC4 */
55 if (!is->is_probe)
56 return 0;
57
58 down_read(&ioc4_devices_rwsem);
59 list_for_each_entry(idd, &ioc4_devices, idd_list) {
60 if (is->is_probe(idd)) {
61 printk(KERN_WARNING
62 "%s: IOC4 submodule %s probe failed "
63 "for pci_dev %s",
64 __FUNCTION__, module_name(is->is_owner),
65 pci_name(idd->idd_pdev));
66 }
67 }
68 up_read(&ioc4_devices_rwsem);
69
70 return 0;
71}
72
73/* Unregister an IOC4 submodule */
74void
75ioc4_unregister_submodule(struct ioc4_submodule *is)
22{ 76{
77 struct ioc4_driver_data *idd;
78
79 down_write(&ioc4_submodules_rwsem);
80 list_del(&is->is_list);
81 up_write(&ioc4_submodules_rwsem);
82
83 /* Remove submodule for each IOC4 */
84 if (!is->is_remove)
85 return;
86
87 down_read(&ioc4_devices_rwsem);
88 list_for_each_entry(idd, &ioc4_devices, idd_list) {
89 if (is->is_remove(idd)) {
90 printk(KERN_WARNING
91 "%s: IOC4 submodule %s remove failed "
92 "for pci_dev %s.\n",
93 __FUNCTION__, module_name(is->is_owner),
94 pci_name(idd->idd_pdev));
95 }
96 }
97 up_read(&ioc4_devices_rwsem);
98}
99
100/*********************
101 * Device management *
102 *********************/
103
104/* Adds a new instance of an IOC4 card */
105static int
106ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
107{
108 struct ioc4_driver_data *idd;
109 struct ioc4_submodule *is;
110 uint32_t pcmd;
23 int ret; 111 int ret;
24 112
113 /* Enable IOC4 and take ownership of it */
25 if ((ret = pci_enable_device(pdev))) { 114 if ((ret = pci_enable_device(pdev))) {
26 printk(KERN_WARNING 115 printk(KERN_WARNING
27 "%s: Failed to enable device with " 116 "%s: Failed to enable IOC4 device for pci_dev %s.\n",
28 "pci_dev 0x%p... returning\n", 117 __FUNCTION__, pci_name(pdev));
29 __FUNCTION__, (void *)pdev); 118 goto out;
30 return ret;
31 } 119 }
32 pci_set_master(pdev); 120 pci_set_master(pdev);
33 121
34 /* attach each sub-device */ 122 /* Set up per-IOC4 data */
35 ret = ioc4_ide_attach_one(pdev, pci_id); 123 idd = kmalloc(sizeof(struct ioc4_driver_data), GFP_KERNEL);
36 if (ret) 124 if (!idd) {
37 return ret; 125 printk(KERN_WARNING
38 return ioc4_serial_attach_one(pdev, pci_id); 126 "%s: Failed to allocate IOC4 data for pci_dev %s.\n",
127 __FUNCTION__, pci_name(pdev));
128 ret = -ENODEV;
129 goto out_idd;
130 }
131 idd->idd_pdev = pdev;
132 idd->idd_pci_id = pci_id;
133
134 /* Map IOC4 misc registers. These are shared between subdevices
135 * so the main IOC4 module manages them.
136 */
137 idd->idd_bar0 = pci_resource_start(idd->idd_pdev, 0);
138 if (!idd->idd_bar0) {
139 printk(KERN_WARNING
140 "%s: Unable to find IOC4 misc resource "
141 "for pci_dev %s.\n",
142 __FUNCTION__, pci_name(idd->idd_pdev));
143 ret = -ENODEV;
144 goto out_pci;
145 }
146 if (!request_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs),
147 "ioc4_misc")) {
148 printk(KERN_WARNING
149 "%s: Unable to request IOC4 misc region "
150 "for pci_dev %s.\n",
151 __FUNCTION__, pci_name(idd->idd_pdev));
152 ret = -ENODEV;
153 goto out_pci;
154 }
155 idd->idd_misc_regs = ioremap(idd->idd_bar0,
156 sizeof(struct ioc4_misc_regs));
157 if (!idd->idd_misc_regs) {
158 printk(KERN_WARNING
159 "%s: Unable to remap IOC4 misc region "
160 "for pci_dev %s.\n",
161 __FUNCTION__, pci_name(idd->idd_pdev));
162 ret = -ENODEV;
163 goto out_misc_region;
164 }
165
166 /* Failsafe portion of per-IOC4 initialization */
167
168 /* Initialize IOC4 */
169 pci_read_config_dword(idd->idd_pdev, PCI_COMMAND, &pcmd);
170 pci_write_config_dword(idd->idd_pdev, PCI_COMMAND,
171 pcmd | PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
172
173 /* Disable/clear all interrupts. Need to do this here lest
174 * one submodule request the shared IOC4 IRQ, but interrupt
175 * is generated by a different subdevice.
176 */
177 /* Disable */
178 writel(~0, &idd->idd_misc_regs->other_iec.raw);
179 writel(~0, &idd->idd_misc_regs->sio_iec);
180 /* Clear (i.e. acknowledge) */
181 writel(~0, &idd->idd_misc_regs->other_ir.raw);
182 writel(~0, &idd->idd_misc_regs->sio_ir);
183
184 /* Track PCI-device specific data */
185 idd->idd_serial_data = NULL;
186 pci_set_drvdata(idd->idd_pdev, idd);
187 down_write(&ioc4_devices_rwsem);
188 list_add(&idd->idd_list, &ioc4_devices);
189 up_write(&ioc4_devices_rwsem);
190
191 /* Add this IOC4 to all submodules */
192 down_read(&ioc4_submodules_rwsem);
193 list_for_each_entry(is, &ioc4_submodules, is_list) {
194 if (is->is_probe && is->is_probe(idd)) {
195 printk(KERN_WARNING
196 "%s: IOC4 submodule 0x%s probe failed "
197 "for pci_dev %s.\n",
198 __FUNCTION__, module_name(is->is_owner),
199 pci_name(idd->idd_pdev));
200 }
201 }
202 up_read(&ioc4_submodules_rwsem);
203
204 return 0;
205
206out_misc_region:
207 release_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
208out_pci:
209 kfree(idd);
210out_idd:
211 pci_disable_device(pdev);
212out:
213 return ret;
39} 214}
40 215
41/* pci device struct */ 216/* Removes a particular instance of an IOC4 card. */
42static struct pci_device_id ioc4_s_id_table[] = { 217static void
218ioc4_remove(struct pci_dev *pdev)
219{
220 struct ioc4_submodule *is;
221 struct ioc4_driver_data *idd;
222
223 idd = pci_get_drvdata(pdev);
224
225 /* Remove this IOC4 from all submodules */
226 down_read(&ioc4_submodules_rwsem);
227 list_for_each_entry(is, &ioc4_submodules, is_list) {
228 if (is->is_remove && is->is_remove(idd)) {
229 printk(KERN_WARNING
230 "%s: IOC4 submodule 0x%s remove failed "
231 "for pci_dev %s.\n",
232 __FUNCTION__, module_name(is->is_owner),
233 pci_name(idd->idd_pdev));
234 }
235 }
236 up_read(&ioc4_submodules_rwsem);
237
238 /* Release resources */
239 iounmap(idd->idd_misc_regs);
240 if (!idd->idd_bar0) {
241 printk(KERN_WARNING
242 "%s: Unable to get IOC4 misc mapping for pci_dev %s. "
243 "Device removal may be incomplete.\n",
244 __FUNCTION__, pci_name(idd->idd_pdev));
245 }
246 release_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
247
248 /* Disable IOC4 and relinquish */
249 pci_disable_device(pdev);
250
251 /* Remove and free driver data */
252 down_write(&ioc4_devices_rwsem);
253 list_del(&idd->idd_list);
254 up_write(&ioc4_devices_rwsem);
255 kfree(idd);
256}
257
258static struct pci_device_id ioc4_id_table[] = {
43 {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC4, PCI_ANY_ID, 259 {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC4, PCI_ANY_ID,
44 PCI_ANY_ID, 0x0b4000, 0xFFFFFF}, 260 PCI_ANY_ID, 0x0b4000, 0xFFFFFF},
45 {0} 261 {0}
46}; 262};
47MODULE_DEVICE_TABLE(pci, ioc4_s_id_table);
48 263
49static struct pci_driver __devinitdata ioc4_s_driver = { 264static struct pci_driver __devinitdata ioc4_driver = {
50 .name = "IOC4", 265 .name = "IOC4",
51 .id_table = ioc4_s_id_table, 266 .id_table = ioc4_id_table,
52 .probe = ioc4_probe_one, 267 .probe = ioc4_probe,
268 .remove = ioc4_remove,
53}; 269};
54 270
55static int __devinit ioc4_detect(void) 271MODULE_DEVICE_TABLE(pci, ioc4_id_table);
272
273/*********************
274 * Module management *
275 *********************/
276
277/* Module load */
278static int __devinit
279ioc4_init(void)
56{ 280{
57 ioc4_serial_init(); 281 return pci_register_driver(&ioc4_driver);
282}
58 283
59 return pci_register_driver(&ioc4_s_driver); 284/* Module unload */
285static void __devexit
286ioc4_exit(void)
287{
288 pci_unregister_driver(&ioc4_driver);
60} 289}
61module_init(ioc4_detect);
62 290
63MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>"); 291module_init(ioc4_init);
64MODULE_DESCRIPTION("PCI driver module for SGI IOC4 Base-IO Card"); 292module_exit(ioc4_exit);
293
294MODULE_AUTHOR("Brent Casavant - Silicon Graphics, Inc. <bcasavan@sgi.com>");
295MODULE_DESCRIPTION("PCI driver master module for SGI IOC4 Base-IO Card");
65MODULE_LICENSE("GPL"); 296MODULE_LICENSE("GPL");
297
298EXPORT_SYMBOL(ioc4_register_submodule);
299EXPORT_SYMBOL(ioc4_unregister_submodule);