summaryrefslogtreecommitdiffstats
path: root/include/asm-ia64/sn/pci/pcibr_private.h
blob: f7f03398996e235f9ee64745b3b24c647d30d83d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
/* $Id$
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc.
 * Copyright (C) 2000 by Colin Ngam
 */
#ifndef _ASM_SN_PCI_PCIBR_PRIVATE_H
#define _ASM_SN_PCI_PCIBR_PRIVATE_H

/*
 * pcibr_private.h -- private definitions for pcibr
 * only the pcibr driver (and its closest friends)
 * should ever peek into this file.
 */

#include <asm/sn/pci/pciio_private.h>

/*
 * convenience typedefs
 */

typedef uint64_t pcibr_DMattr_t;
typedef uint32_t pcibr_ATEattr_t;

typedef struct pcibr_info_s *pcibr_info_t, **pcibr_info_h;
typedef struct pcibr_soft_s *pcibr_soft_t;
typedef struct pcibr_soft_slot_s *pcibr_soft_slot_t;
typedef struct pcibr_hints_s *pcibr_hints_t;
typedef struct pcibr_intr_list_s *pcibr_intr_list_t;
typedef struct pcibr_intr_wrap_s *pcibr_intr_wrap_t;

/*
 * Bridge sets up PIO using this information.
 */
struct pcibr_piomap_s {
    struct pciio_piomap_s   bp_pp;	/* generic stuff */

#define	bp_flags	bp_pp.pp_flags	/* PCIBR_PIOMAP flags */
#define	bp_dev		bp_pp.pp_dev	/* associated pci card */
#define	bp_slot		bp_pp.pp_slot	/* which slot the card is in */
#define	bp_space	bp_pp.pp_space	/* which address space */
#define	bp_pciaddr	bp_pp.pp_pciaddr	/* starting offset of mapping */
#define	bp_mapsz	bp_pp.pp_mapsz	/* size of this mapping */
#define	bp_kvaddr	bp_pp.pp_kvaddr	/* kernel virtual address to use */

    iopaddr_t               bp_xtalk_addr;	/* corresponding xtalk address */
    xtalk_piomap_t          bp_xtalk_pio;	/* corresponding xtalk resource */
    pcibr_piomap_t	    bp_next;	/* Next piomap on the list */
    pcibr_soft_t	    bp_soft;	/* backpointer to bridge soft data */
    int			    bp_toc[1];	/* PCI timeout counter */

};

/*
 * Bridge sets up DMA using this information.
 */
struct pcibr_dmamap_s {
    struct pciio_dmamap_s   bd_pd;
#define	bd_flags	bd_pd.pd_flags	/* PCIBR_DMAMAP flags */
#define	bd_dev		bd_pd.pd_dev	/* associated pci card */
#define	bd_slot		bd_pd.pd_slot	/* which slot the card is in */
    struct pcibr_soft_s    *bd_soft;	/* pcibr soft state backptr */
    xtalk_dmamap_t          bd_xtalk;	/* associated xtalk resources */

    size_t                  bd_max_size;	/* maximum size of mapping */
    xwidgetnum_t            bd_xio_port;	/* target XIO port */
    iopaddr_t               bd_xio_addr;	/* target XIO address */
    iopaddr_t               bd_pci_addr;	/* via PCI address */

    int                     bd_ate_index;	/* Address Translation Entry Index */
    int                     bd_ate_count;	/* number of ATE's allocated */
    bridge_ate_p            bd_ate_ptr;		/* where to write first ATE */
    bridge_ate_t            bd_ate_proto;	/* prototype ATE (for xioaddr=0) */
    bridge_ate_t            bd_ate_prime;	/* value of 1st ATE written */
};

/*
 * Bridge sets up interrupts using this information.
 */

struct pcibr_intr_s {
    struct pciio_intr_s     bi_pi;
#define	bi_flags	bi_pi.pi_flags	/* PCIBR_INTR flags */
#define	bi_dev		bi_pi.pi_dev	/* associated pci card */
#define	bi_lines	bi_pi.pi_lines	/* which PCI interrupt line(s) */
#define	bi_func		bi_pi.pi_func	/* handler function (when connected) */
#define	bi_arg		bi_pi.pi_arg	/* handler parameter (when connected) */
#define bi_tinfo	bi_pi.pi_tinfo	/* Thread info (when connected) */
#define bi_mustruncpu	bi_pi.pi_mustruncpu /* Where we must run. */
#define bi_irq		bi_pi.pi_irq	/* IRQ assigned. */
#define bi_cpu		bi_pi.pi_cpu	/* cpu assigned. */
    unsigned                bi_ibits;	/* which Bridge interrupt bit(s) */
    pcibr_soft_t            bi_soft;	/* shortcut to soft info */
};

/*
 * per-connect point pcibr data, including
 * standard pciio data in-line:
 */
struct pcibr_info_s {
    struct pciio_info_s	    f_c;	/* MUST BE FIRST. */
#define	f_vertex	f_c.c_vertex	/* back pointer to vertex */
#define	f_bus		f_c.c_bus	/* which bus the card is in */
#define	f_slot		f_c.c_slot	/* which slot the card is in */
#define	f_func		f_c.c_func	/* which func (on multi-func cards) */
#define	f_vendor	f_c.c_vendor	/* PCI card "vendor" code */
#define	f_device	f_c.c_device	/* PCI card "device" code */
#define	f_master	f_c.c_master	/* PCI bus provider */
#define	f_mfast		f_c.c_mfast	/* cached fastinfo from c_master */
#define	f_pops		f_c.c_pops	/* cached provider from c_master */
#define	f_efunc		f_c.c_efunc	/* error handling function */
#define	f_einfo		f_c.c_einfo	/* first parameter for efunc */
#define	f_window	f_c.c_window	/* state of BASE regs */
#define	f_rbase		f_c.c_rbase	/* expansion rom base */
#define	f_rsize		f_c.c_rsize	/* expansion rom size */
#define	f_piospace	f_c.c_piospace	/* additional I/O spaces allocated */

    /* pcibr-specific connection state */
    int			    f_ibit[4];	/* Bridge bit for each INTx */
    pcibr_piomap_t	    f_piomap;
};

/* =====================================================================
 *          Shared Interrupt Information
 */

struct pcibr_intr_list_s {
    pcibr_intr_list_t       il_next;
    pcibr_intr_t            il_intr;
    volatile bridgereg_t   *il_wrbf;	/* ptr to b_wr_req_buf[] */
};

/* =====================================================================
 *          Interrupt Wrapper Data
 */
struct pcibr_intr_wrap_s {
    pcibr_soft_t            iw_soft;	/* which bridge */
    volatile bridgereg_t   *iw_stat;	/* ptr to b_int_status */
    bridgereg_t             iw_intr;	/* bits in b_int_status */
    pcibr_intr_list_t       iw_list;	/* ghostbusters! */
};

#define	PCIBR_ISR_ERR_START	8
#define PCIBR_ISR_MAX_ERRS 	32

/* =====================================================================
 *            Bridge Device State structure
 *
 *      one instance of this structure is kept for each
 *      Bridge ASIC in the system.
 */

struct pcibr_soft_s {
    devfs_handle_t            bs_conn;	/* xtalk connection point */
    devfs_handle_t            bs_vhdl;	/* vertex owned by pcibr */
    int                     bs_int_enable;	/* Mask of enabled intrs */
    bridge_t               *bs_base;	/* PIO pointer to Bridge chip */
    char                   *bs_name;	/* hw graph name */
    xwidgetnum_t            bs_xid;	/* Bridge's xtalk ID number */
    devfs_handle_t            bs_master;	/* xtalk master vertex */
    xwidgetnum_t            bs_mxid;	/* master's xtalk ID number */

    iopaddr_t               bs_dir_xbase;	/* xtalk address for 32-bit PCI direct map */
    xwidgetnum_t	    bs_dir_xport;	/* xtalk port for 32-bit PCI direct map */

    struct map             *bs_int_ate_map;	/* rmalloc map for internal ATEs */
    struct map             *bs_ext_ate_map;	/* rmalloc map for external ATEs */
    short		    bs_int_ate_size;	/* number of internal ates */
    short		    bs_xbridge;		/* if 1 then xbridge */

    int                     bs_rev_num;	/* revision number of Bridge */

    unsigned                bs_dma_flags;	/* revision-implied DMA flags */

    /*
     * Lock used primarily to get mutual exclusion while managing any
     * bridge resources..
     */
    lock_t                  bs_lock;
    
    devfs_handle_t	    bs_noslot_conn;	/* NO-SLOT connection point */
    pcibr_info_t	    bs_noslot_info;
    struct pcibr_soft_slot_s {
	/* information we keep about each CFG slot */

	/* some devices (ioc3 in non-slotted
	 * configurations, sometimes) make use
	 * of more than one REQ/GNT/INT* signal
	 * sets. The slot corresponding to the
	 * IDSEL that the device responds to is
	 * called the host slot; the slot
	 * numbers that the device is stealing
	 * REQ/GNT/INT bits from are known as
	 * the guest slots.
	 */
	int                     has_host;
	pciio_slot_t            host_slot;
	devfs_handle_t		slot_conn;
	/* Potentially several connection points
	 * for this slot. bss_ninfo is how many,
	 * and bss_infos is a pointer to
	 * an array pcibr_info_t values (which are
	 * pointers to pcibr_info structs, stored
	 * as device_info in connection ponts).
	 */
	int			bss_ninfo;
	pcibr_info_h	        bss_infos;

	/* Temporary Compatibility Macros, for
	 * stuff that has moved out of bs_slot
	 * and into the info structure. These
	 * will go away when their users have
	 * converted over to multifunction-
	 * friendly use of bss_{ninfo,infos}.
	 */
#define	bss_vendor_id	bss_infos[0]->f_vendor
#define	bss_device_id	bss_infos[0]->f_device
#define	bss_window	bss_infos[0]->f_window
#define	bssw_space	w_space
#define	bssw_base	w_base
#define	bssw_size	w_size

	/* Where is DevIO(x) pointing? */
	/* bssd_space is NONE if it is not assigned. */
	struct {
	    pciio_space_t           bssd_space;
	    iopaddr_t               bssd_base;
	} bss_devio;

	/* Shadow value for Device(x) register,
	 * so we don't have to go to the chip.
	 */
	bridgereg_t             bss_device;

	/* Number of sets on GBR/REALTIME bit outstanding
	 * Used by Priority I/O for tracking reservations
	 */
	int                     bss_pri_uctr;

	/* Number of "uses" of PMU, 32-bit direct,
	 * and 64-bit direct DMA (0:none, <0: trans,
	 * >0: how many dmamaps). Device(x) bits
	 * controlling attribute of each kind of
	 * channel can't be changed by dmamap_alloc
	 * or dmatrans if the controlling counter
	 * is nonzero. dmatrans is forever.
	 */
	int                     bss_pmu_uctr;
	int                     bss_d32_uctr;
	int                     bss_d64_uctr;

	/* When the contents of mapping configuration
	 * information is locked down by dmatrans,
	 * repeated checks of the same flags should
	 * be shortcircuited for efficiency.
	 */
	iopaddr_t		bss_d64_base;
	unsigned		bss_d64_flags;
	iopaddr_t		bss_d32_base;
	unsigned		bss_d32_flags;

	/* Shadow information used for implementing
	 * Bridge Hardware WAR #484930
	 */
	int			bss_ext_ates_active;
        volatile unsigned      *bss_cmd_pointer;
	unsigned		bss_cmd_shadow;

    } bs_slot[8];

    pcibr_intr_bits_f	       *bs_intr_bits;

    /* RRB MANAGEMENT
     * bs_rrb_fixed: bitmap of slots whose RRB
     *	allocations we should not "automatically" change
     * bs_rrb_avail: number of RRBs that have not
     *  been allocated or reserved for {even,odd} slots
     * bs_rrb_res: number of RRBs reserved for the
     *	use of the index slot number
     * bs_rrb_valid: number of RRBs marked valid
     *	for the indexed slot number; indexes 8-15
     *	are for the virtual channels for slots 0-7.
     */
    int                     bs_rrb_fixed;
    int			    bs_rrb_avail[2];
    int			    bs_rrb_res[8];
    int			    bs_rrb_valid[16];

    struct {
	/* Each Bridge interrupt bit has a single XIO
	 * interrupt channel allocated.
	 */
	xtalk_intr_t            bsi_xtalk_intr;
	/*
	 * We do not like sharing PCI interrrupt lines
	 * between devices, but the Origin 200 PCI
	 * layout forces us to do so.
	 */
	pcibr_intr_list_t       bsi_pcibr_intr_list;
	pcibr_intr_wrap_t       bsi_pcibr_intr_wrap;
	int                     bsi_pcibr_wrap_set;

    } bs_intr[8];

    xtalk_intr_t		bsi_err_intr;

    /*
     * We stash away some information in this structure on getting
     * an error interrupt. This information is used during PIO read/
     * write error handling.
     *
     * As it stands now, we do not re-enable the error interrupt
     * till the error is resolved. Error resolution happens either at
     * bus error time for PIO Read errors (~100 microseconds), or at
     * the scheduled timeout time for PIO write errors (~milliseconds).
     * If this delay causes problems, we may need to move towards
     * a different scheme..
     *
     * Note that there is no locking while looking at this data structure.
     * There should not be any race between bus error code and
     * error interrupt code.. will look into this if needed.
     */
    struct br_errintr_info {
	int                     bserr_toutcnt;
#ifdef IRIX
	toid_t                  bserr_toutid;	/* Timeout started by errintr */
#endif
	iopaddr_t               bserr_addr;	/* Address where error occured */
	bridgereg_t             bserr_intstat;	/* interrupts active at error time */
    } bs_errinfo;

    /*
     * PCI Bus Space allocation data structure.
     * This info is used to satisfy the callers of pcibr_piospace_alloc
     * interface. Most of these users need "large" amounts of PIO
     * space (typically in Megabytes), and they generally tend to
     * take once and never release..
     * For Now use a simple algorithm to manage it. On allocation,
     * Update the _base field to reflect next free address.
     *
     * Freeing does nothing.. So, once allocated, it's gone for good.
     */
    struct br_pcisp_info {
	iopaddr_t               pci_io_base;
	iopaddr_t               pci_io_last;
	iopaddr_t               pci_swin_base;
	iopaddr_t               pci_swin_last;
	iopaddr_t               pci_mem_base;
	iopaddr_t               pci_mem_last;
    } bs_spinfo;

    struct bs_errintr_stat_s {
	uint32_t              bs_errcount_total;
	uint32_t              bs_lasterr_timestamp;
	uint32_t              bs_lasterr_snapshot;
    } bs_errintr_stat[PCIBR_ISR_MAX_ERRS];

    /*
     * Bridge-wide endianness control for
     * large-window PIO mappings
     *
     * These fields are set to PCIIO_BYTE_SWAP
     * or PCIIO_WORD_VALUES once the swapper
     * has been configured, one way or the other,
     * for the direct windows. If they are zero,
     * nobody has a PIO mapping through that window,
     * and the swapper can be set either way.
     */
    unsigned		bs_pio_end_io;
    unsigned		bs_pio_end_mem;
};

#define	PCIBR_ERRTIME_THRESHOLD		(100)
#define	PCIBR_ERRRATE_THRESHOLD		(100)

/*
 * pcibr will respond to hints dropped in its vertex
 * using the following structure.
 */
struct pcibr_hints_s {
    /* ph_host_slot is actually +1 so "0" means "no host" */
    pciio_slot_t            ph_host_slot[8];	/* REQ/GNT/INT in use by ... */
    unsigned                ph_rrb_fixed;	/* do not change RRB allocations */
    unsigned                ph_hands_off;	/* prevent further pcibr operations */
    rrb_alloc_funct_t       rrb_alloc_funct;	/* do dynamic rrb allocation */
    pcibr_intr_bits_f	   *ph_intr_bits;	/* map PCI INT[ABCD] to Bridge Int(n) */
};

extern int              pcibr_prefetch_enable_rev, pcibr_wg_enable_rev;

/*
 * Number of bridge non-fatal error interrupts we can see before
 * we decide to disable that interrupt.
 */
#define	PCIBR_ERRINTR_DISABLE_LEVEL	10000

/* =====================================================================
 *    Bridge (pcibr) state management functions
 *
 *      pcibr_soft_get is here because we do it in a lot
 *      of places and I want to make sure they all stay
 *      in step with each other.
 *
 *      pcibr_soft_set is here because I want it to be
 *      closely associated with pcibr_soft_get, even
 *      though it is only called in one place.
 */

#define pcibr_soft_get(v)       ((pcibr_soft_t)hwgraph_fastinfo_get((v)))
#define pcibr_soft_set(v,i)     (hwgraph_fastinfo_set((v), (arbitrary_info_t)(i)))

#endif				/* _ASM_SN_PCI_PCIBR_PRIVATE_H */