gamma_dma.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:21k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* gamma_dma.c -- DMA support for GMX 2000 -*- linux-c -*-
  2.  * Created: Fri Mar 19 14:30:16 1999 by faith@precisioninsight.com
  3.  *
  4.  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  5.  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  6.  * All Rights Reserved.
  7.  *
  8.  * Permission is hereby granted, free of charge, to any person obtaining a
  9.  * copy of this software and associated documentation files (the "Software"),
  10.  * to deal in the Software without restriction, including without limitation
  11.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  12.  * and/or sell copies of the Software, and to permit persons to whom the
  13.  * Software is furnished to do so, subject to the following conditions:
  14.  * 
  15.  * The above copyright notice and this permission notice (including the next
  16.  * paragraph) shall be included in all copies or substantial portions of the
  17.  * Software.
  18.  * 
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  23.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  24.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  25.  * DEALINGS IN THE SOFTWARE.
  26.  * 
  27.  * Authors:
  28.  *    Rickard E. (Rik) Faith <faith@valinux.com>
  29.  *
  30.  */
  31. #define __NO_VERSION__
  32. #include "drmP.h"
  33. #include "gamma_drv.h"
  34. #include <linux/interrupt.h> /* For task queue support */
  35. /* WARNING!!! MAGIC NUMBER!!!  The number of regions already added to the
  36.    kernel must be specified here.  Currently, the number is 2. This must
  37.    match the order the X server uses for instantiating register regions ,
  38.    or must be passed in a new ioctl. */
  39. #define GAMMA_REG(reg)    
  40. (2    
  41.  + ((reg < 0x1000)    
  42.     ? 0    
  43.     : ((reg < 0x10000) ? 1 : ((reg < 0x11000) ? 2 : 3))))
  44. #define GAMMA_OFF(reg)    
  45. ((reg < 0x1000)    
  46.  ? reg    
  47.  : ((reg < 0x10000)    
  48.     ? (reg - 0x1000)    
  49.     : ((reg < 0x11000)    
  50.        ? (reg - 0x10000)    
  51.        : (reg - 0x11000))))
  52. #define GAMMA_BASE(reg)  ((unsigned long)dev->maplist[GAMMA_REG(reg)]->handle)
  53. #define GAMMA_ADDR(reg)  (GAMMA_BASE(reg) + GAMMA_OFF(reg))
  54. #define GAMMA_DEREF(reg) *(__volatile__ int *)GAMMA_ADDR(reg)
  55. #define GAMMA_READ(reg)  GAMMA_DEREF(reg)
  56. #define GAMMA_WRITE(reg,val) do { GAMMA_DEREF(reg) = val; } while (0)
  57. #define GAMMA_BROADCASTMASK    0x9378
  58. #define GAMMA_COMMANDINTENABLE 0x0c48
  59. #define GAMMA_DMAADDRESS       0x0028
  60. #define GAMMA_DMACOUNT        0x0030
  61. #define GAMMA_FILTERMODE       0x8c00
  62. #define GAMMA_GCOMMANDINTFLAGS 0x0c50
  63. #define GAMMA_GCOMMANDMODE     0x0c40
  64. #define GAMMA_GCOMMANDSTATUS   0x0c60
  65. #define GAMMA_GDELAYTIMER      0x0c38
  66. #define GAMMA_GDMACONTROL      0x0060
  67. #define GAMMA_GINTENABLE       0x0808
  68. #define GAMMA_GINTFLAGS        0x0810
  69. #define GAMMA_INFIFOSPACE      0x0018
  70. #define GAMMA_OUTFIFOWORDS     0x0020
  71. #define GAMMA_OUTPUTFIFO       0x2000
  72. #define GAMMA_SYNC        0x8c40
  73. #define GAMMA_SYNC_TAG        0x0188
  74. static inline void gamma_dma_dispatch(drm_device_t *dev, unsigned long address,
  75.       unsigned long length)
  76. {
  77. GAMMA_WRITE(GAMMA_DMAADDRESS, virt_to_phys((void *)address));
  78. while (GAMMA_READ(GAMMA_GCOMMANDSTATUS) != 4)
  79. ;
  80. GAMMA_WRITE(GAMMA_DMACOUNT, length / 4);
  81. }
  82. static inline void gamma_dma_quiescent_single(drm_device_t *dev)
  83. {
  84. while (GAMMA_READ(GAMMA_DMACOUNT))
  85. ;
  86. while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
  87. ;
  88. GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10);
  89. GAMMA_WRITE(GAMMA_SYNC, 0);
  90. do {
  91. while (!GAMMA_READ(GAMMA_OUTFIFOWORDS))
  92. ;
  93. } while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG);
  94. }
  95. static inline void gamma_dma_quiescent_dual(drm_device_t *dev)
  96. {
  97. while (GAMMA_READ(GAMMA_DMACOUNT))
  98. ;
  99. while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3)
  100. ;
  101. GAMMA_WRITE(GAMMA_BROADCASTMASK, 3);
  102. GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10);
  103. GAMMA_WRITE(GAMMA_SYNC, 0);
  104. /* Read from first MX */
  105. do {
  106. while (!GAMMA_READ(GAMMA_OUTFIFOWORDS))
  107. ;
  108. } while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG);
  109. /* Read from second MX */
  110. do {
  111. while (!GAMMA_READ(GAMMA_OUTFIFOWORDS + 0x10000))
  112. ;
  113. } while (GAMMA_READ(GAMMA_OUTPUTFIFO + 0x10000) != GAMMA_SYNC_TAG);
  114. }
  115. static inline void gamma_dma_ready(drm_device_t *dev)
  116. {
  117. while (GAMMA_READ(GAMMA_DMACOUNT))
  118. ;
  119. }
  120. static inline int gamma_dma_is_ready(drm_device_t *dev)
  121. {
  122. return !GAMMA_READ(GAMMA_DMACOUNT);
  123. }
  124. static void gamma_dma_service(int irq, void *device, struct pt_regs *regs)
  125. {
  126. drm_device_t  *dev = (drm_device_t *)device;
  127. drm_device_dma_t *dma = dev->dma;
  128. atomic_inc(&dev->total_irq);
  129. GAMMA_WRITE(GAMMA_GDELAYTIMER, 0xc350/2); /* 0x05S */
  130. GAMMA_WRITE(GAMMA_GCOMMANDINTFLAGS, 8);
  131. GAMMA_WRITE(GAMMA_GINTFLAGS, 0x2001);
  132. if (gamma_dma_is_ready(dev)) {
  133. /* Free previous buffer */
  134. if (test_and_set_bit(0, &dev->dma_flag)) {
  135. atomic_inc(&dma->total_missed_free);
  136. return;
  137. }
  138. if (dma->this_buffer) {
  139. drm_free_buffer(dev, dma->this_buffer);
  140. dma->this_buffer = NULL;
  141. }
  142. clear_bit(0, &dev->dma_flag);
  143. /* Dispatch new buffer */
  144. queue_task(&dev->tq, &tq_immediate);
  145. mark_bh(IMMEDIATE_BH);
  146. }
  147. }
  148. /* Only called by gamma_dma_schedule. */
  149. static int gamma_do_dma(drm_device_t *dev, int locked)
  150. {
  151. unsigned long  address;
  152. unsigned long  length;
  153. drm_buf_t  *buf;
  154. int  retcode = 0;
  155. drm_device_dma_t *dma = dev->dma;
  156. #if DRM_DMA_HISTOGRAM
  157. cycles_t  dma_start, dma_stop;
  158. #endif
  159. if (test_and_set_bit(0, &dev->dma_flag)) {
  160. atomic_inc(&dma->total_missed_dma);
  161. return -EBUSY;
  162. }
  163. #if DRM_DMA_HISTOGRAM
  164. dma_start = get_cycles();
  165. #endif
  166. if (!dma->next_buffer) {
  167. DRM_ERROR("No next_buffern");
  168. clear_bit(0, &dev->dma_flag);
  169. return -EINVAL;
  170. }
  171. buf = dma->next_buffer;
  172. address = (unsigned long)buf->address;
  173. length = buf->used;
  174. DRM_DEBUG("context %d, buffer %d (%ld bytes)n",
  175.   buf->context, buf->idx, length);
  176. if (buf->list == DRM_LIST_RECLAIM) {
  177. drm_clear_next_buffer(dev);
  178. drm_free_buffer(dev, buf);
  179. clear_bit(0, &dev->dma_flag);
  180. return -EINVAL;
  181. }
  182. if (!length) {
  183. DRM_ERROR("0 length buffern");
  184. drm_clear_next_buffer(dev);
  185. drm_free_buffer(dev, buf);
  186. clear_bit(0, &dev->dma_flag);
  187. return 0;
  188. }
  189. if (!gamma_dma_is_ready(dev)) {
  190. clear_bit(0, &dev->dma_flag);
  191. return -EBUSY;
  192. }
  193. if (buf->while_locked) {
  194. if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) {
  195. DRM_ERROR("Dispatching buffer %d from pid %d"
  196.   " "while locked", but no lock heldn",
  197.   buf->idx, buf->pid);
  198. }
  199. } else {
  200. if (!locked && !drm_lock_take(&dev->lock.hw_lock->lock,
  201.       DRM_KERNEL_CONTEXT)) {
  202. atomic_inc(&dma->total_missed_lock);
  203. clear_bit(0, &dev->dma_flag);
  204. return -EBUSY;
  205. }
  206. }
  207. if (dev->last_context != buf->context
  208.     && !(dev->queuelist[buf->context]->flags
  209.  & _DRM_CONTEXT_PRESERVED)) {
  210. /* PRE: dev->last_context != buf->context */
  211. if (drm_context_switch(dev, dev->last_context, buf->context)) {
  212. drm_clear_next_buffer(dev);
  213. drm_free_buffer(dev, buf);
  214. }
  215. retcode = -EBUSY;
  216. goto cleanup;
  217. /* POST: we will wait for the context
  218.    switch and will dispatch on a later call
  219.    when dev->last_context == buf->context.
  220.    NOTE WE HOLD THE LOCK THROUGHOUT THIS
  221.    TIME! */
  222. }
  223. drm_clear_next_buffer(dev);
  224. buf->pending  = 1;
  225. buf->waiting  = 0;
  226. buf->list  = DRM_LIST_PEND;
  227. #if DRM_DMA_HISTOGRAM
  228. buf->time_dispatched = get_cycles();
  229. #endif
  230. gamma_dma_dispatch(dev, address, length);
  231. drm_free_buffer(dev, dma->this_buffer);
  232. dma->this_buffer = buf;
  233. atomic_add(length, &dma->total_bytes);
  234. atomic_inc(&dma->total_dmas);
  235. if (!buf->while_locked && !dev->context_flag && !locked) {
  236. if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
  237.   DRM_KERNEL_CONTEXT)) {
  238. DRM_ERROR("n");
  239. }
  240. }
  241. cleanup:
  242. clear_bit(0, &dev->dma_flag);
  243. #if DRM_DMA_HISTOGRAM
  244. dma_stop = get_cycles();
  245. atomic_inc(&dev->histo.dma[drm_histogram_slot(dma_stop - dma_start)]);
  246. #endif
  247. return retcode;
  248. }
  249. static void gamma_dma_schedule_timer_wrapper(unsigned long dev)
  250. {
  251. gamma_dma_schedule((drm_device_t *)dev, 0);
  252. }
  253. static void gamma_dma_schedule_tq_wrapper(void *dev)
  254. {
  255. gamma_dma_schedule(dev, 0);
  256. }
  257. int gamma_dma_schedule(drm_device_t *dev, int locked)
  258. {
  259. int  next;
  260. drm_queue_t  *q;
  261. drm_buf_t  *buf;
  262. int  retcode   = 0;
  263. int  processed = 0;
  264. int  missed;
  265. int  expire    = 20;
  266. drm_device_dma_t *dma    = dev->dma;
  267. #if DRM_DMA_HISTOGRAM
  268. cycles_t  schedule_start;
  269. #endif
  270. if (test_and_set_bit(0, &dev->interrupt_flag)) {
  271. /* Not reentrant */
  272. atomic_inc(&dma->total_missed_sched);
  273. return -EBUSY;
  274. }
  275. missed = atomic_read(&dma->total_missed_sched);
  276. #if DRM_DMA_HISTOGRAM
  277. schedule_start = get_cycles();
  278. #endif
  279. again:
  280. if (dev->context_flag) {
  281. clear_bit(0, &dev->interrupt_flag);
  282. return -EBUSY;
  283. }
  284. if (dma->next_buffer) {
  285. /* Unsent buffer that was previously
  286.    selected, but that couldn't be sent
  287.    because the lock could not be obtained
  288.    or the DMA engine wasn't ready.  Try
  289.    again. */
  290. atomic_inc(&dma->total_tried);
  291. if (!(retcode = gamma_do_dma(dev, locked))) {
  292. atomic_inc(&dma->total_hit);
  293. ++processed;
  294. }
  295. } else {
  296. do {
  297. next = drm_select_queue(dev,
  298.      gamma_dma_schedule_timer_wrapper);
  299. if (next >= 0) {
  300. q   = dev->queuelist[next];
  301. buf = drm_waitlist_get(&q->waitlist);
  302. dma->next_buffer = buf;
  303. dma->next_queue  = q;
  304. if (buf && buf->list == DRM_LIST_RECLAIM) {
  305. drm_clear_next_buffer(dev);
  306. drm_free_buffer(dev, buf);
  307. }
  308. }
  309. } while (next >= 0 && !dma->next_buffer);
  310. if (dma->next_buffer) {
  311. if (!(retcode = gamma_do_dma(dev, locked))) {
  312. ++processed;
  313. }
  314. }
  315. }
  316. if (--expire) {
  317. if (missed != atomic_read(&dma->total_missed_sched)) {
  318. atomic_inc(&dma->total_lost);
  319. if (gamma_dma_is_ready(dev)) goto again;
  320. }
  321. if (processed && gamma_dma_is_ready(dev)) {
  322. atomic_inc(&dma->total_lost);
  323. processed = 0;
  324. goto again;
  325. }
  326. }
  327. clear_bit(0, &dev->interrupt_flag);
  328. #if DRM_DMA_HISTOGRAM
  329. atomic_inc(&dev->histo.schedule[drm_histogram_slot(get_cycles()
  330.    - schedule_start)]);
  331. #endif
  332. return retcode;
  333. }
  334. static int gamma_dma_priority(drm_device_t *dev, drm_dma_t *d)
  335. {
  336. unsigned long   address;
  337. unsigned long   length;
  338. int   must_free = 0;
  339. int   retcode   = 0;
  340. int   i;
  341. int   idx;
  342. drm_buf_t   *buf;
  343. drm_buf_t   *last_buf = NULL;
  344. drm_device_dma_t  *dma     = dev->dma;
  345. DECLARE_WAITQUEUE(entry, current);
  346. /* Turn off interrupt handling */
  347. while (test_and_set_bit(0, &dev->interrupt_flag)) {
  348. schedule();
  349. if (signal_pending(current)) return -EINTR;
  350. }
  351. if (!(d->flags & _DRM_DMA_WHILE_LOCKED)) {
  352. while (!drm_lock_take(&dev->lock.hw_lock->lock,
  353.       DRM_KERNEL_CONTEXT)) {
  354. schedule();
  355. if (signal_pending(current)) {
  356. clear_bit(0, &dev->interrupt_flag);
  357. return -EINTR;
  358. }
  359. }
  360. ++must_free;
  361. }
  362. atomic_inc(&dma->total_prio);
  363. for (i = 0; i < d->send_count; i++) {
  364. idx = d->send_indices[i];
  365. if (idx < 0 || idx >= dma->buf_count) {
  366. DRM_ERROR("Index %d (of %d max)n",
  367.   d->send_indices[i], dma->buf_count - 1);
  368. continue;
  369. }
  370. buf = dma->buflist[ idx ];
  371. if (buf->pid != current->pid) {
  372. DRM_ERROR("Process %d using buffer owned by %dn",
  373.   current->pid, buf->pid);
  374. retcode = -EINVAL;
  375. goto cleanup;
  376. }
  377. if (buf->list != DRM_LIST_NONE) {
  378. DRM_ERROR("Process %d using %d's buffer on list %dn",
  379.   current->pid, buf->pid, buf->list);
  380. retcode = -EINVAL;
  381. goto cleanup;
  382. }
  383. /* This isn't a race condition on
  384.    buf->list, since our concern is the
  385.    buffer reclaim during the time the
  386.    process closes the /dev/drm? handle, so
  387.    it can't also be doing DMA. */
  388. buf->list   = DRM_LIST_PRIO;
  389. buf->used   = d->send_sizes[i];
  390. buf->context   = d->context;
  391. buf->while_locked = d->flags & _DRM_DMA_WHILE_LOCKED;
  392. address   = (unsigned long)buf->address;
  393. length   = buf->used;
  394. if (!length) {
  395. DRM_ERROR("0 length buffern");
  396. }
  397. if (buf->pending) {
  398. DRM_ERROR("Sending pending buffer:"
  399.   " buffer %d, offset %dn",
  400.   d->send_indices[i], i);
  401. retcode = -EINVAL;
  402. goto cleanup;
  403. }
  404. if (buf->waiting) {
  405. DRM_ERROR("Sending waiting buffer:"
  406.   " buffer %d, offset %dn",
  407.   d->send_indices[i], i);
  408. retcode = -EINVAL;
  409. goto cleanup;
  410. }
  411. buf->pending = 1;
  412. if (dev->last_context != buf->context
  413.     && !(dev->queuelist[buf->context]->flags
  414.  & _DRM_CONTEXT_PRESERVED)) {
  415. add_wait_queue(&dev->context_wait, &entry);
  416. current->state = TASK_INTERRUPTIBLE;
  417. /* PRE: dev->last_context != buf->context */
  418. drm_context_switch(dev, dev->last_context,
  419.    buf->context);
  420. /* POST: we will wait for the context
  421.    switch and will dispatch on a later call
  422.    when dev->last_context == buf->context.
  423.    NOTE WE HOLD THE LOCK THROUGHOUT THIS
  424.    TIME! */
  425. schedule();
  426. current->state = TASK_RUNNING;
  427. remove_wait_queue(&dev->context_wait, &entry);
  428. if (signal_pending(current)) {
  429. retcode = -EINTR;
  430. goto cleanup;
  431. }
  432. if (dev->last_context != buf->context) {
  433. DRM_ERROR("Context mismatch: %d %dn",
  434.   dev->last_context,
  435.   buf->context);
  436. }
  437. }
  438. #if DRM_DMA_HISTOGRAM
  439. buf->time_queued     = get_cycles();
  440. buf->time_dispatched = buf->time_queued;
  441. #endif
  442. gamma_dma_dispatch(dev, address, length);
  443. atomic_add(length, &dma->total_bytes);
  444. atomic_inc(&dma->total_dmas);
  445. if (last_buf) {
  446. drm_free_buffer(dev, last_buf);
  447. }
  448. last_buf = buf;
  449. }
  450. cleanup:
  451. if (last_buf) {
  452. gamma_dma_ready(dev);
  453. drm_free_buffer(dev, last_buf);
  454. }
  455. if (must_free && !dev->context_flag) {
  456. if (drm_lock_free(dev, &dev->lock.hw_lock->lock,
  457.   DRM_KERNEL_CONTEXT)) {
  458. DRM_ERROR("n");
  459. }
  460. }
  461. clear_bit(0, &dev->interrupt_flag);
  462. return retcode;
  463. }
  464. static int gamma_dma_send_buffers(drm_device_t *dev, drm_dma_t *d)
  465. {
  466. DECLARE_WAITQUEUE(entry, current);
  467. drm_buf_t   *last_buf = NULL;
  468. int   retcode   = 0;
  469. drm_device_dma_t  *dma     = dev->dma;
  470. if (d->flags & _DRM_DMA_BLOCK) {
  471. last_buf = dma->buflist[d->send_indices[d->send_count-1]];
  472. add_wait_queue(&last_buf->dma_wait, &entry);
  473. }
  474. if ((retcode = drm_dma_enqueue(dev, d))) {
  475. if (d->flags & _DRM_DMA_BLOCK)
  476. remove_wait_queue(&last_buf->dma_wait, &entry);
  477. return retcode;
  478. }
  479. gamma_dma_schedule(dev, 0);
  480. if (d->flags & _DRM_DMA_BLOCK) {
  481. DRM_DEBUG("%d waitingn", current->pid);
  482. for (;;) {
  483. current->state = TASK_INTERRUPTIBLE;
  484. if (!last_buf->waiting && !last_buf->pending)
  485. break; /* finished */
  486. schedule();
  487. if (signal_pending(current)) {
  488. retcode = -EINTR; /* Can't restart */
  489. break;
  490. }
  491. }
  492. current->state = TASK_RUNNING;
  493. DRM_DEBUG("%d runningn", current->pid);
  494. remove_wait_queue(&last_buf->dma_wait, &entry);
  495. if (!retcode
  496.     || (last_buf->list==DRM_LIST_PEND && !last_buf->pending)) {
  497. if (!waitqueue_active(&last_buf->dma_wait)) {
  498. drm_free_buffer(dev, last_buf);
  499. }
  500. }
  501. if (retcode) {
  502. DRM_ERROR("ctx%d w%d p%d c%d i%d l%d %d/%dn",
  503.   d->context,
  504.   last_buf->waiting,
  505.   last_buf->pending,
  506.   DRM_WAITCOUNT(dev, d->context),
  507.   last_buf->idx,
  508.   last_buf->list,
  509.   last_buf->pid,
  510.   current->pid);
  511. }
  512. }
  513. return retcode;
  514. }
  515. int gamma_dma(struct inode *inode, struct file *filp, unsigned int cmd,
  516.       unsigned long arg)
  517. {
  518. drm_file_t   *priv     = filp->private_data;
  519. drm_device_t   *dev     = priv->dev;
  520. drm_device_dma_t  *dma     = dev->dma;
  521. int   retcode   = 0;
  522. drm_dma_t   d;
  523. if (copy_from_user(&d, (drm_dma_t *)arg, sizeof(d)))
  524. return -EFAULT;
  525. DRM_DEBUG("%d %d: %d send, %d reqn",
  526.   current->pid, d.context, d.send_count, d.request_count);
  527. if (d.context == DRM_KERNEL_CONTEXT || d.context >= dev->queue_slots) {
  528. DRM_ERROR("Process %d using context %dn",
  529.   current->pid, d.context);
  530. return -EINVAL;
  531. }
  532. if (d.send_count < 0 || d.send_count > dma->buf_count) {
  533. DRM_ERROR("Process %d trying to send %d buffers (of %d max)n",
  534.   current->pid, d.send_count, dma->buf_count);
  535. return -EINVAL;
  536. }
  537. if (d.request_count < 0 || d.request_count > dma->buf_count) {
  538. DRM_ERROR("Process %d trying to get %d buffers (of %d max)n",
  539.   current->pid, d.request_count, dma->buf_count);
  540. return -EINVAL;
  541. }
  542. if (d.send_count) {
  543. if (d.flags & _DRM_DMA_PRIORITY)
  544. retcode = gamma_dma_priority(dev, &d);
  545. else 
  546. retcode = gamma_dma_send_buffers(dev, &d);
  547. }
  548. d.granted_count = 0;
  549. if (!retcode && d.request_count) {
  550. retcode = drm_dma_get_buffers(dev, &d);
  551. }
  552. DRM_DEBUG("%d returning, granted = %dn",
  553.   current->pid, d.granted_count);
  554. if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d)))
  555. return -EFAULT;
  556. return retcode;
  557. }
  558. int gamma_irq_install(drm_device_t *dev, int irq)
  559. {
  560. int retcode;
  561. if (!irq)     return -EINVAL;
  562. down(&dev->struct_sem);
  563. if (dev->irq) {
  564. up(&dev->struct_sem);
  565. return -EBUSY;
  566. }
  567. dev->irq = irq;
  568. up(&dev->struct_sem);
  569. DRM_DEBUG("%dn", irq);
  570. dev->context_flag     = 0;
  571. dev->interrupt_flag   = 0;
  572. dev->dma_flag       = 0;
  573. dev->dma->next_buffer = NULL;
  574. dev->dma->next_queue  = NULL;
  575. dev->dma->this_buffer = NULL;
  576. INIT_LIST_HEAD(&dev->tq.list);
  577. dev->tq.sync       = 0;
  578. dev->tq.routine       = gamma_dma_schedule_tq_wrapper;
  579. dev->tq.data       = dev;
  580. /* Before installing handler */
  581. GAMMA_WRITE(GAMMA_GCOMMANDMODE, 0);
  582. GAMMA_WRITE(GAMMA_GDMACONTROL, 0);
  583. /* Install handler */
  584. if ((retcode = request_irq(dev->irq,
  585.    gamma_dma_service,
  586.    0,
  587.    dev->devname,
  588.    dev))) {
  589. down(&dev->struct_sem);
  590. dev->irq = 0;
  591. up(&dev->struct_sem);
  592. return retcode;
  593. }
  594. /* After installing handler */
  595. GAMMA_WRITE(GAMMA_GINTENABLE,     0x2001);
  596. GAMMA_WRITE(GAMMA_COMMANDINTENABLE, 0x0008);
  597. GAMMA_WRITE(GAMMA_GDELAYTIMER,    0x39090);
  598. return 0;
  599. }
  600. int gamma_irq_uninstall(drm_device_t *dev)
  601. {
  602. int irq;
  603. down(&dev->struct_sem);
  604. irq  = dev->irq;
  605. dev->irq = 0;
  606. up(&dev->struct_sem);
  607. if (!irq) return -EINVAL;
  608. DRM_DEBUG("%dn", irq);
  609. GAMMA_WRITE(GAMMA_GDELAYTIMER,     0);
  610. GAMMA_WRITE(GAMMA_COMMANDINTENABLE, 0);
  611. GAMMA_WRITE(GAMMA_GINTENABLE,     0);
  612. free_irq(irq, dev);
  613. return 0;
  614. }
  615. int gamma_control(struct inode *inode, struct file *filp, unsigned int cmd,
  616.   unsigned long arg)
  617. {
  618. drm_file_t *priv = filp->private_data;
  619. drm_device_t *dev = priv->dev;
  620. drm_control_t ctl;
  621. int retcode;
  622. if (copy_from_user(&ctl, (drm_control_t *)arg, sizeof(ctl)))
  623. return -EFAULT;
  624. switch (ctl.func) {
  625. case DRM_INST_HANDLER:
  626. if ((retcode = gamma_irq_install(dev, ctl.irq)))
  627. return retcode;
  628. break;
  629. case DRM_UNINST_HANDLER:
  630. if ((retcode = gamma_irq_uninstall(dev)))
  631. return retcode;
  632. break;
  633. default:
  634. return -EINVAL;
  635. }
  636. return 0;
  637. }
  638. int gamma_lock(struct inode *inode, struct file *filp, unsigned int cmd,
  639.        unsigned long arg)
  640. {
  641. drm_file_t   *priv   = filp->private_data;
  642. drm_device_t   *dev   = priv->dev;
  643. DECLARE_WAITQUEUE(entry, current);
  644. int   ret = 0;
  645. drm_lock_t   lock;
  646. drm_queue_t   *q;
  647. #if DRM_DMA_HISTOGRAM
  648. cycles_t   start;
  649. dev->lck_start = start = get_cycles();
  650. #endif
  651. if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock)))
  652. return -EFAULT;
  653. if (lock.context == DRM_KERNEL_CONTEXT) {
  654. DRM_ERROR("Process %d using kernel context %dn",
  655.   current->pid, lock.context);
  656. return -EINVAL;
  657. }
  658. DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08xn",
  659.   lock.context, current->pid, dev->lock.hw_lock->lock,
  660.   lock.flags);
  661. if (lock.context < 0 || lock.context >= dev->queue_count)
  662. return -EINVAL;
  663. q = dev->queuelist[lock.context];
  664. ret = drm_flush_block_and_flush(dev, lock.context, lock.flags);
  665. if (!ret) {
  666. if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)
  667.     != lock.context) {
  668. long j = jiffies - dev->lock.lock_time;
  669. if (j > 0 && j <= DRM_LOCK_SLICE) {
  670. /* Can't take lock if we just had it and
  671.    there is contention. */
  672. current->state = TASK_INTERRUPTIBLE;
  673. schedule_timeout(j);
  674. }
  675. }
  676. add_wait_queue(&dev->lock.lock_queue, &entry);
  677. for (;;) {
  678. current->state = TASK_INTERRUPTIBLE;
  679. if (!dev->lock.hw_lock) {
  680. /* Device has been unregistered */
  681. ret = -EINTR;
  682. break;
  683. }
  684. if (drm_lock_take(&dev->lock.hw_lock->lock,
  685.   lock.context)) {
  686. dev->lock.pid     = current->pid;
  687. dev->lock.lock_time = jiffies;
  688. atomic_inc(&dev->total_locks);
  689. atomic_inc(&q->total_locks);
  690. break; /* Got lock */
  691. }
  692. /* Contention */
  693. atomic_inc(&dev->total_sleeps);
  694. schedule();
  695. if (signal_pending(current)) {
  696. ret = -ERESTARTSYS;
  697. break;
  698. }
  699. }
  700. current->state = TASK_RUNNING;
  701. remove_wait_queue(&dev->lock.lock_queue, &entry);
  702. }
  703. drm_flush_unblock(dev, lock.context, lock.flags); /* cleanup phase */
  704. if (!ret) {
  705. sigemptyset(&dev->sigmask);
  706. sigaddset(&dev->sigmask, SIGSTOP);
  707. sigaddset(&dev->sigmask, SIGTSTP);
  708. sigaddset(&dev->sigmask, SIGTTIN);
  709. sigaddset(&dev->sigmask, SIGTTOU);
  710. dev->sigdata.context = lock.context;
  711. dev->sigdata.lock    = dev->lock.hw_lock;
  712. block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask);
  713. if (lock.flags & _DRM_LOCK_READY)
  714. gamma_dma_ready(dev);
  715. if (lock.flags & _DRM_LOCK_QUIESCENT) {
  716. if (gamma_found() == 1) {
  717. gamma_dma_quiescent_single(dev);
  718. } else {
  719. gamma_dma_quiescent_dual(dev);
  720. }
  721. }
  722. }
  723. DRM_DEBUG("%d %sn", lock.context, ret ? "interrupted" : "has lock");
  724. #if DRM_DMA_HISTOGRAM
  725. atomic_inc(&dev->histo.lacq[drm_histogram_slot(get_cycles() - start)]);
  726. #endif
  727. return ret;
  728. }