1*e3adcf8fSFrançois Tigeot /* 2*e3adcf8fSFrançois Tigeot * $FreeBSD: src/sys/dev/drm2/i915/intel_ringbuffer.h,v 1.1 2012/05/22 11:07:44 kib Exp $ 3*e3adcf8fSFrançois Tigeot */ 4*e3adcf8fSFrançois Tigeot 5*e3adcf8fSFrançois Tigeot #ifndef _INTEL_RINGBUFFER_H_ 6*e3adcf8fSFrançois Tigeot #define _INTEL_RINGBUFFER_H_ 7*e3adcf8fSFrançois Tigeot 8*e3adcf8fSFrançois Tigeot struct intel_hw_status_page { 9*e3adcf8fSFrançois Tigeot uint32_t *page_addr; 10*e3adcf8fSFrançois Tigeot unsigned int gfx_addr; 11*e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 12*e3adcf8fSFrançois Tigeot }; 13*e3adcf8fSFrançois Tigeot 14*e3adcf8fSFrançois Tigeot #define I915_READ_TAIL(ring) I915_READ(RING_TAIL((ring)->mmio_base)) 15*e3adcf8fSFrançois Tigeot #define I915_WRITE_TAIL(ring, val) I915_WRITE(RING_TAIL((ring)->mmio_base), val) 16*e3adcf8fSFrançois Tigeot 17*e3adcf8fSFrançois Tigeot #define I915_READ_START(ring) I915_READ(RING_START((ring)->mmio_base)) 18*e3adcf8fSFrançois Tigeot #define I915_WRITE_START(ring, val) I915_WRITE(RING_START((ring)->mmio_base), val) 19*e3adcf8fSFrançois Tigeot 20*e3adcf8fSFrançois Tigeot #define I915_READ_HEAD(ring) I915_READ(RING_HEAD((ring)->mmio_base)) 21*e3adcf8fSFrançois Tigeot #define I915_WRITE_HEAD(ring, val) I915_WRITE(RING_HEAD((ring)->mmio_base), val) 22*e3adcf8fSFrançois Tigeot 23*e3adcf8fSFrançois Tigeot #define I915_READ_CTL(ring) I915_READ(RING_CTL((ring)->mmio_base)) 24*e3adcf8fSFrançois Tigeot #define I915_WRITE_CTL(ring, val) I915_WRITE(RING_CTL((ring)->mmio_base), val) 25*e3adcf8fSFrançois Tigeot 26*e3adcf8fSFrançois Tigeot #define I915_READ_IMR(ring) I915_READ(RING_IMR((ring)->mmio_base)) 27*e3adcf8fSFrançois Tigeot #define I915_WRITE_IMR(ring, val) I915_WRITE(RING_IMR((ring)->mmio_base), val) 28*e3adcf8fSFrançois Tigeot 29*e3adcf8fSFrançois Tigeot #define I915_READ_NOPID(ring) I915_READ(RING_NOPID((ring)->mmio_base)) 30*e3adcf8fSFrançois Tigeot #define I915_READ_SYNC_0(ring) I915_READ(RING_SYNC_0((ring)->mmio_base)) 31*e3adcf8fSFrançois Tigeot #define I915_READ_SYNC_1(ring) I915_READ(RING_SYNC_1((ring)->mmio_base)) 32*e3adcf8fSFrançois Tigeot 33*e3adcf8fSFrançois Tigeot struct intel_ring_buffer { 34*e3adcf8fSFrançois Tigeot const char *name; 35*e3adcf8fSFrançois Tigeot enum intel_ring_id { 36*e3adcf8fSFrançois Tigeot RCS = 0x0, 37*e3adcf8fSFrançois Tigeot VCS, 38*e3adcf8fSFrançois Tigeot BCS, 39*e3adcf8fSFrançois Tigeot } id; 40*e3adcf8fSFrançois Tigeot #define I915_NUM_RINGS 3 41*e3adcf8fSFrançois Tigeot uint32_t mmio_base; 42*e3adcf8fSFrançois Tigeot void *virtual_start; 43*e3adcf8fSFrançois Tigeot struct drm_device *dev; 44*e3adcf8fSFrançois Tigeot struct drm_i915_gem_object *obj; 45*e3adcf8fSFrançois Tigeot 46*e3adcf8fSFrançois Tigeot uint32_t head; 47*e3adcf8fSFrançois Tigeot uint32_t tail; 48*e3adcf8fSFrançois Tigeot int space; 49*e3adcf8fSFrançois Tigeot int size; 50*e3adcf8fSFrançois Tigeot int effective_size; 51*e3adcf8fSFrançois Tigeot struct intel_hw_status_page status_page; 52*e3adcf8fSFrançois Tigeot 53*e3adcf8fSFrançois Tigeot /** We track the position of the requests in the ring buffer, and 54*e3adcf8fSFrançois Tigeot * when each is retired we increment last_retired_head as the GPU 55*e3adcf8fSFrançois Tigeot * must have finished processing the request and so we know we 56*e3adcf8fSFrançois Tigeot * can advance the ringbuffer up to that position. 57*e3adcf8fSFrançois Tigeot * 58*e3adcf8fSFrançois Tigeot * last_retired_head is set to -1 after the value is consumed so 59*e3adcf8fSFrançois Tigeot * we can detect new retirements. 60*e3adcf8fSFrançois Tigeot */ 61*e3adcf8fSFrançois Tigeot u32 last_retired_head; 62*e3adcf8fSFrançois Tigeot 63*e3adcf8fSFrançois Tigeot struct lock irq_lock; 64*e3adcf8fSFrançois Tigeot uint32_t irq_refcount; 65*e3adcf8fSFrançois Tigeot uint32_t irq_mask; 66*e3adcf8fSFrançois Tigeot uint32_t irq_seqno; /* last seq seem at irq time */ 67*e3adcf8fSFrançois Tigeot uint32_t trace_irq_seqno; 68*e3adcf8fSFrançois Tigeot uint32_t waiting_seqno; 69*e3adcf8fSFrançois Tigeot uint32_t sync_seqno[I915_NUM_RINGS-1]; 70*e3adcf8fSFrançois Tigeot bool (*irq_get)(struct intel_ring_buffer *ring); 71*e3adcf8fSFrançois Tigeot void (*irq_put)(struct intel_ring_buffer *ring); 72*e3adcf8fSFrançois Tigeot 73*e3adcf8fSFrançois Tigeot int (*init)(struct intel_ring_buffer *ring); 74*e3adcf8fSFrançois Tigeot 75*e3adcf8fSFrançois Tigeot void (*write_tail)(struct intel_ring_buffer *ring, 76*e3adcf8fSFrançois Tigeot uint32_t value); 77*e3adcf8fSFrançois Tigeot int (*flush)(struct intel_ring_buffer *ring, 78*e3adcf8fSFrançois Tigeot uint32_t invalidate_domains, 79*e3adcf8fSFrançois Tigeot uint32_t flush_domains); 80*e3adcf8fSFrançois Tigeot int (*add_request)(struct intel_ring_buffer *ring, 81*e3adcf8fSFrançois Tigeot uint32_t *seqno); 82*e3adcf8fSFrançois Tigeot uint32_t (*get_seqno)(struct intel_ring_buffer *ring); 83*e3adcf8fSFrançois Tigeot int (*dispatch_execbuffer)(struct intel_ring_buffer *ring, 84*e3adcf8fSFrançois Tigeot uint32_t offset, uint32_t length); 85*e3adcf8fSFrançois Tigeot void (*cleanup)(struct intel_ring_buffer *ring); 86*e3adcf8fSFrançois Tigeot int (*sync_to)(struct intel_ring_buffer *ring, 87*e3adcf8fSFrançois Tigeot struct intel_ring_buffer *to, 88*e3adcf8fSFrançois Tigeot u32 seqno); 89*e3adcf8fSFrançois Tigeot 90*e3adcf8fSFrançois Tigeot u32 semaphore_register[3]; /*our mbox written by others */ 91*e3adcf8fSFrançois Tigeot u32 signal_mbox[2]; /* mboxes this ring signals to */ 92*e3adcf8fSFrançois Tigeot 93*e3adcf8fSFrançois Tigeot /** 94*e3adcf8fSFrançois Tigeot * List of objects currently involved in rendering from the 95*e3adcf8fSFrançois Tigeot * ringbuffer. 96*e3adcf8fSFrançois Tigeot * 97*e3adcf8fSFrançois Tigeot * Includes buffers having the contents of their GPU caches 98*e3adcf8fSFrançois Tigeot * flushed, not necessarily primitives. last_rendering_seqno 99*e3adcf8fSFrançois Tigeot * represents when the rendering involved will be completed. 100*e3adcf8fSFrançois Tigeot * 101*e3adcf8fSFrançois Tigeot * A reference is held on the buffer while on this list. 102*e3adcf8fSFrançois Tigeot */ 103*e3adcf8fSFrançois Tigeot struct list_head active_list; 104*e3adcf8fSFrançois Tigeot 105*e3adcf8fSFrançois Tigeot /** 106*e3adcf8fSFrançois Tigeot * List of breadcrumbs associated with GPU requests currently 107*e3adcf8fSFrançois Tigeot * outstanding. 108*e3adcf8fSFrançois Tigeot */ 109*e3adcf8fSFrançois Tigeot struct list_head request_list; 110*e3adcf8fSFrançois Tigeot 111*e3adcf8fSFrançois Tigeot /** 112*e3adcf8fSFrançois Tigeot * List of objects currently pending a GPU write flush. 113*e3adcf8fSFrançois Tigeot * 114*e3adcf8fSFrançois Tigeot * All elements on this list will belong to either the 115*e3adcf8fSFrançois Tigeot * active_list or flushing_list, last_rendering_seqno can 116*e3adcf8fSFrançois Tigeot * be used to differentiate between the two elements. 117*e3adcf8fSFrançois Tigeot */ 118*e3adcf8fSFrançois Tigeot struct list_head gpu_write_list; 119*e3adcf8fSFrançois Tigeot 120*e3adcf8fSFrançois Tigeot /** 121*e3adcf8fSFrançois Tigeot * Do we have some not yet emitted requests outstanding? 122*e3adcf8fSFrançois Tigeot */ 123*e3adcf8fSFrançois Tigeot uint32_t outstanding_lazy_request; 124*e3adcf8fSFrançois Tigeot 125*e3adcf8fSFrançois Tigeot drm_local_map_t map; 126*e3adcf8fSFrançois Tigeot 127*e3adcf8fSFrançois Tigeot void *private; 128*e3adcf8fSFrançois Tigeot }; 129*e3adcf8fSFrançois Tigeot 130*e3adcf8fSFrançois Tigeot static inline unsigned 131*e3adcf8fSFrançois Tigeot intel_ring_flag(struct intel_ring_buffer *ring) 132*e3adcf8fSFrançois Tigeot { 133*e3adcf8fSFrançois Tigeot return 1 << ring->id; 134*e3adcf8fSFrançois Tigeot } 135*e3adcf8fSFrançois Tigeot 136*e3adcf8fSFrançois Tigeot static inline uint32_t 137*e3adcf8fSFrançois Tigeot intel_ring_sync_index(struct intel_ring_buffer *ring, 138*e3adcf8fSFrançois Tigeot struct intel_ring_buffer *other) 139*e3adcf8fSFrançois Tigeot { 140*e3adcf8fSFrançois Tigeot int idx; 141*e3adcf8fSFrançois Tigeot 142*e3adcf8fSFrançois Tigeot /* 143*e3adcf8fSFrançois Tigeot * cs -> 0 = vcs, 1 = bcs 144*e3adcf8fSFrançois Tigeot * vcs -> 0 = bcs, 1 = cs, 145*e3adcf8fSFrançois Tigeot * bcs -> 0 = cs, 1 = vcs. 146*e3adcf8fSFrançois Tigeot */ 147*e3adcf8fSFrançois Tigeot 148*e3adcf8fSFrançois Tigeot idx = (other - ring) - 1; 149*e3adcf8fSFrançois Tigeot if (idx < 0) 150*e3adcf8fSFrançois Tigeot idx += I915_NUM_RINGS; 151*e3adcf8fSFrançois Tigeot 152*e3adcf8fSFrançois Tigeot return idx; 153*e3adcf8fSFrançois Tigeot } 154*e3adcf8fSFrançois Tigeot 155*e3adcf8fSFrançois Tigeot static inline uint32_t 156*e3adcf8fSFrançois Tigeot intel_read_status_page(struct intel_ring_buffer *ring, int reg) 157*e3adcf8fSFrançois Tigeot { 158*e3adcf8fSFrançois Tigeot 159*e3adcf8fSFrançois Tigeot return (atomic_load_acq_32(ring->status_page.page_addr + reg)); 160*e3adcf8fSFrançois Tigeot } 161*e3adcf8fSFrançois Tigeot 162*e3adcf8fSFrançois Tigeot void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring); 163*e3adcf8fSFrançois Tigeot 164*e3adcf8fSFrançois Tigeot int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n); 165*e3adcf8fSFrançois Tigeot static inline int intel_wait_ring_idle(struct intel_ring_buffer *ring) 166*e3adcf8fSFrançois Tigeot { 167*e3adcf8fSFrançois Tigeot 168*e3adcf8fSFrançois Tigeot return (intel_wait_ring_buffer(ring, ring->size - 8)); 169*e3adcf8fSFrançois Tigeot } 170*e3adcf8fSFrançois Tigeot 171*e3adcf8fSFrançois Tigeot int intel_ring_begin(struct intel_ring_buffer *ring, int n); 172*e3adcf8fSFrançois Tigeot 173*e3adcf8fSFrançois Tigeot static inline void intel_ring_emit(struct intel_ring_buffer *ring, 174*e3adcf8fSFrançois Tigeot uint32_t data) 175*e3adcf8fSFrançois Tigeot { 176*e3adcf8fSFrançois Tigeot *(volatile uint32_t *)((char *)ring->virtual_start + 177*e3adcf8fSFrançois Tigeot ring->tail) = data; 178*e3adcf8fSFrançois Tigeot ring->tail += 4; 179*e3adcf8fSFrançois Tigeot } 180*e3adcf8fSFrançois Tigeot 181*e3adcf8fSFrançois Tigeot void intel_ring_advance(struct intel_ring_buffer *ring); 182*e3adcf8fSFrançois Tigeot 183*e3adcf8fSFrançois Tigeot uint32_t intel_ring_get_seqno(struct intel_ring_buffer *ring); 184*e3adcf8fSFrançois Tigeot 185*e3adcf8fSFrançois Tigeot int intel_init_render_ring_buffer(struct drm_device *dev); 186*e3adcf8fSFrançois Tigeot int intel_init_bsd_ring_buffer(struct drm_device *dev); 187*e3adcf8fSFrançois Tigeot int intel_init_blt_ring_buffer(struct drm_device *dev); 188*e3adcf8fSFrançois Tigeot 189*e3adcf8fSFrançois Tigeot u32 intel_ring_get_active_head(struct intel_ring_buffer *ring); 190*e3adcf8fSFrançois Tigeot void intel_ring_setup_status_page(struct intel_ring_buffer *ring); 191*e3adcf8fSFrançois Tigeot 192*e3adcf8fSFrançois Tigeot static inline u32 intel_ring_get_tail(struct intel_ring_buffer *ring) 193*e3adcf8fSFrançois Tigeot { 194*e3adcf8fSFrançois Tigeot return ring->tail; 195*e3adcf8fSFrançois Tigeot } 196*e3adcf8fSFrançois Tigeot 197*e3adcf8fSFrançois Tigeot void i915_trace_irq_get(struct intel_ring_buffer *ring, uint32_t seqno); 198*e3adcf8fSFrançois Tigeot 199*e3adcf8fSFrançois Tigeot /* DRI warts */ 200*e3adcf8fSFrançois Tigeot int intel_render_ring_init_dri(struct drm_device *dev, uint64_t start, 201*e3adcf8fSFrançois Tigeot uint32_t size); 202*e3adcf8fSFrançois Tigeot 203*e3adcf8fSFrançois Tigeot #endif /* _INTEL_RINGBUFFER_H_ */ 204