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) 2003 Silicon Graphics, Inc. All rights reserved.
8  */
9 
10 #include <linux/init.h>
11 #include <linux/types.h>
12 #include <linux/pci.h>
13 #include <linux/pci_ids.h>
14 #include <linux/sched.h>
15 #include <linux/ioport.h>
16 #include <linux/slab.h>
17 #include <asm/sn/sgi.h>
18 #include <asm/sn/xtalk/xbow.h>	/* Must be before iograph.h to get MAX_PORT_NUM */
19 #include <asm/sn/iograph.h>
20 #include <asm/sn/invent.h>
21 #include <asm/sn/hcl.h>
22 #include <asm/sn/hcl_util.h>
23 #include <asm/sn/labelcl.h>
24 #include <asm/sn/pci/bridge.h>
25 #include <asm/sn/ioerror_handling.h>
26 #include <asm/sn/pci/pciio.h>
27 #include <asm/sn/pci/pciio_private.h>
28 #include <asm/sn/sn_sal.h>
29 #include <asm/sn/io.h>
30 #include <asm/sn/pci/pci_bus_cvlink.h>
31 #include <asm/sn/simulator.h>
32 
33 #if !defined(DEV_FUNC)
34 extern pciio_provider_t *pciio_to_provider_fns(vertex_hdl_t dev);
35 #define DEV_FUNC(dev,func)	pciio_to_provider_fns(dev)->func
36 #define CAST_PIOMAP(x)		((pciio_piomap_t)(x))
37 #define CAST_DMAMAP(x)		((pciio_dmamap_t)(x))
38 #define CAST_INTR(x)		((pciio_intr_t)(x))
39 #endif
40 
41 /*
42  * Many functions are not passed their vertex
43  * information directly; rather, they must
44  * dive through a resource map. These macros
45  * are available to coordinate this detail.
46  */
47 #define PIOMAP_FUNC(map,func)		DEV_FUNC((map)->pp_dev,func)
48 #define DMAMAP_FUNC(map,func)		DEV_FUNC((map)->pd_dev,func)
49 #define INTR_FUNC(intr_hdl,func)	DEV_FUNC((intr_hdl)->pi_dev,func)
50 
51 int
snia_badaddr_val(volatile void * addr,int len,volatile void * ptr)52 snia_badaddr_val(volatile void *addr, int len, volatile void *ptr)
53 {
54 	int ret = 0;
55 	volatile void *new_addr;
56 
57 	switch (len) {
58 		case 4:
59 			new_addr = (void *) addr;
60 			ret = ia64_sn_probe_io_slot((long)new_addr, len, (void *)ptr);
61 			break;
62 		default:
63 			printk(KERN_WARNING "badaddr_val given len %x but supports len of 4 only\n", len);
64 	}
65 
66 	if (ret < 0)
67 		panic("badaddr_val: unexpected status (%d) in probing", ret);
68 	return(ret);
69 
70 }
71 
72 
73 nasid_t
snia_get_console_nasid(void)74 snia_get_console_nasid(void)
75 {
76 	extern nasid_t console_nasid;
77 	extern nasid_t master_baseio_nasid;
78 
79 	if (console_nasid < 0) {
80 		console_nasid = ia64_sn_get_console_nasid();
81 		if (console_nasid < 0) {
82 // ZZZ What do we do if we don't get a console nasid on the hardware????
83 			if (IS_RUNNING_ON_SIMULATOR() )
84 				console_nasid = master_baseio_nasid;
85 		}
86 	}
87 	return console_nasid;
88 }
89 
90 nasid_t
snia_get_master_baseio_nasid(void)91 snia_get_master_baseio_nasid(void)
92 {
93 	extern nasid_t master_baseio_nasid;
94 	extern char master_baseio_wid;
95 
96 	if (master_baseio_nasid < 0) {
97 		master_baseio_nasid = ia64_sn_get_master_baseio_nasid();
98 
99 		if ( master_baseio_nasid >= 0 ) {
100         		master_baseio_wid = WIDGETID_GET(KL_CONFIG_CH_CONS_INFO(master_baseio_nasid)->memory_base);
101 		}
102 	}
103 	return master_baseio_nasid;
104 }
105 
106 
107 void
snia_ioerror_dump(char * name,int error_code,int error_mode,ioerror_t * ioerror)108 snia_ioerror_dump(char *name, int error_code, int error_mode, ioerror_t *ioerror)
109 {
110 #ifdef	LATER
111 	/* This needs to be tested */
112 
113 	static char *error_mode_string[] =
114 		{ "probe", "kernel", "user", "reenable" };
115 
116 	printk("%s%s%s%s%s error in %s mode\n",
117                name,
118                (error_code & IOECODE_PIO) ? " PIO" : "",
119                (error_code & IOECODE_DMA) ? " DMA" : "",
120                (error_code & IOECODE_READ) ? " Read" : "",
121                (error_code & IOECODE_WRITE) ? " Write" : "",
122                error_mode_string[error_mode]);
123 
124 #define PRFIELD(f)                                  \
125         if (IOERROR_FIELDVALID(ioerror,f)) {        \
126 		int tmp;                            \
127 		IOERROR_GETVALUE(tmp, ioerror, f);  \
128                 printk("\t%20s: 0x%x\n", #f, tmp);  \
129 	}
130 
131         PRFIELD(errortype);             /* error type: extra info about error */
132         PRFIELD(widgetnum);             /* Widget number that's in error */
133         PRFIELD(widgetdev);             /* Device within widget in error */
134         PRFIELD(srccpu);                /* CPU on srcnode generating error */
135         PRFIELD(srcnode);               /* Node which caused the error   */
136         PRFIELD(errnode);               /* Node where error was noticed  */
137         PRFIELD(sysioaddr);             /* Sys specific IO address       */
138         PRFIELD(xtalkaddr);             /* Xtalk (48bit) addr of Error   */
139         PRFIELD(busspace);              /* Bus specific address space    */
140         PRFIELD(busaddr);               /* Bus specific address          */
141         PRFIELD(vaddr);                 /* Virtual address of error      */
142         PRFIELD(memaddr);               /* Physical memory address       */
143         PRFIELD(epc);                   /* pc when error reported        */
144         PRFIELD(ef);                    /* eframe when error reported    */
145 
146 #undef  PRFIELD
147 
148         {
149                 /* Print a more descriptive CPU string */
150                 cpuid_t srccpu;
151 		IOERROR_GETVALUE(srccpu, ioerror, srccpu);
152 		// smp_processor_id()
153                 printk("(NOTE: CPU %d)\n", srccpu);
154                 printk("\n");
155         }
156 #endif	/* LATER */
157 }
158 
159 
160 int
snia_pcibr_rrb_alloc(struct pci_dev * pci_dev,int * count_vchan0,int * count_vchan1)161 snia_pcibr_rrb_alloc(struct pci_dev *pci_dev,
162 	int *count_vchan0,
163 	int *count_vchan1)
164 {
165 	vertex_hdl_t dev = PCIDEV_VERTEX(pci_dev);
166 
167 	return pcibr_rrb_alloc(dev, count_vchan0, count_vchan1);
168 }
169 
170 pciio_endian_t
snia_pciio_endian_set(struct pci_dev * pci_dev,pciio_endian_t device_end,pciio_endian_t desired_end)171 snia_pciio_endian_set(struct pci_dev *pci_dev,
172 	pciio_endian_t device_end,
173 	pciio_endian_t desired_end)
174 {
175 	vertex_hdl_t dev = PCIDEV_VERTEX(pci_dev);
176 
177 	return DEV_FUNC(dev, endian_set)
178 		(dev, device_end, desired_end);
179 }
180 
181 iopaddr_t
snia_pciio_dmatrans_addr(struct pci_dev * pci_dev,device_desc_t dev_desc,paddr_t paddr,size_t byte_count,unsigned flags)182 snia_pciio_dmatrans_addr(struct pci_dev *pci_dev, /* translate for this device */
183                     device_desc_t dev_desc,     /* device descriptor */
184                     paddr_t paddr,      /* system physical address */
185                     size_t byte_count,  /* length */
186                     unsigned flags)
187 {                                       /* defined in dma.h */
188 
189     vertex_hdl_t dev = PCIDEV_VERTEX(pci_dev);
190 
191     /*
192      * If the device is not a PIC, we always want the PCIIO_BYTE_STREAM to be
193      * set.  Otherwise, it must not be set.  This applies to SN1 and SN2.
194      */
195     return DEV_FUNC(dev, dmatrans_addr)
196         (dev, dev_desc, paddr, byte_count, flags & ~PCIIO_BYTE_STREAM);
197 }
198 
199 pciio_dmamap_t
snia_pciio_dmamap_alloc(struct pci_dev * pci_dev,device_desc_t dev_desc,size_t byte_count_max,unsigned flags)200 snia_pciio_dmamap_alloc(struct pci_dev *pci_dev,  /* set up mappings for this device */
201                    device_desc_t dev_desc,      /* device descriptor */
202                    size_t byte_count_max,       /* max size of a mapping */
203                    unsigned flags)
204 {                                       /* defined in dma.h */
205 
206     vertex_hdl_t dev = PCIDEV_VERTEX(pci_dev);
207 
208     /*
209      * If the device is not a PIC, we always want the PCIIO_BYTE_STREAM to be
210      * set.  Otherwise, it must not be set.  This applies to SN1 and SN2.
211      */
212     return (pciio_dmamap_t) DEV_FUNC(dev, dmamap_alloc)
213         (dev, dev_desc, byte_count_max, flags & ~PCIIO_BYTE_STREAM);
214 }
215 
216 void
snia_pciio_dmamap_free(pciio_dmamap_t pciio_dmamap)217 snia_pciio_dmamap_free(pciio_dmamap_t pciio_dmamap)
218 {
219     DMAMAP_FUNC(pciio_dmamap, dmamap_free)
220         (CAST_DMAMAP(pciio_dmamap));
221 }
222 
223 iopaddr_t
snia_pciio_dmamap_addr(pciio_dmamap_t pciio_dmamap,paddr_t paddr,size_t byte_count)224 snia_pciio_dmamap_addr(pciio_dmamap_t pciio_dmamap,  /* use these mapping resources */
225                   paddr_t paddr,        /* map for this address */
226                   size_t byte_count)
227 {                                       /* map this many bytes */
228     return DMAMAP_FUNC(pciio_dmamap, dmamap_addr)
229         (CAST_DMAMAP(pciio_dmamap), paddr, byte_count);
230 }
231 
232 void
snia_pciio_dmamap_done(pciio_dmamap_t pciio_dmamap)233 snia_pciio_dmamap_done(pciio_dmamap_t pciio_dmamap)
234 {
235     DMAMAP_FUNC(pciio_dmamap, dmamap_done)
236         (CAST_DMAMAP(pciio_dmamap));
237 }
238 
239 #include <linux/module.h>
240 EXPORT_SYMBOL(snia_pciio_dmatrans_addr);
241 EXPORT_SYMBOL(snia_pciio_dmamap_alloc);
242 EXPORT_SYMBOL(snia_pciio_dmamap_free);
243 EXPORT_SYMBOL(snia_pciio_dmamap_addr);
244 EXPORT_SYMBOL(snia_pciio_dmamap_done);
245 EXPORT_SYMBOL(snia_pciio_endian_set);
246 EXPORT_SYMBOL(snia_pcibr_rrb_alloc);
247