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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* mga_dma.c -- DMA support for mga g200/g400 -*- linux-c -*-
  2.  * Created: Mon Dec 13 01:50:01 1999 by jhartmann@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.  *    Jeff Hartmann <jhartmann@valinux.com>
  30.  *    Keith Whitwell <keithw@valinux.com>
  31.  *
  32.  * Rewritten by:
  33.  *    Gareth Hughes <gareth@valinux.com>
  34.  */
  35. #define __NO_VERSION__
  36. #include "mga.h"
  37. #include "drmP.h"
  38. #include "mga_drv.h"
  39. #include <linux/interrupt.h> /* For task queue support */
  40. #include <linux/delay.h>
  41. #define MGA_DEFAULT_USEC_TIMEOUT 10000
  42. #define MGA_FREELIST_DEBUG 0
  43. /* ================================================================
  44.  * Engine control
  45.  */
  46. int mga_do_wait_for_idle( drm_mga_private_t *dev_priv )
  47. {
  48. u32 status = 0;
  49. int i;
  50. DRM_DEBUG( "%sn", __FUNCTION__ );
  51. for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
  52. status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
  53. if ( status == MGA_ENDPRDMASTS ) {
  54. MGA_WRITE8( MGA_CRTC_INDEX, 0 );
  55. return 0;
  56. }
  57. udelay( 1 );
  58. }
  59. #if MGA_DMA_DEBUG
  60. DRM_ERROR( "failed!n" );
  61. DRM_INFO( "   status=0x%08xn", status );
  62. #endif
  63. return -EBUSY;
  64. }
  65. int mga_do_dma_idle( drm_mga_private_t *dev_priv )
  66. {
  67. u32 status = 0;
  68. int i;
  69. DRM_DEBUG( "%sn", __FUNCTION__ );
  70. for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
  71. status = MGA_READ( MGA_STATUS ) & MGA_DMA_IDLE_MASK;
  72. if ( status == MGA_ENDPRDMASTS ) return 0;
  73. udelay( 1 );
  74. }
  75. #if MGA_DMA_DEBUG
  76. DRM_ERROR( "failed! status=0x%08xn", status );
  77. #endif
  78. return -EBUSY;
  79. }
  80. int mga_do_dma_reset( drm_mga_private_t *dev_priv )
  81. {
  82. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  83. drm_mga_primary_buffer_t *primary = &dev_priv->prim;
  84. DRM_DEBUG( "%sn", __FUNCTION__ );
  85. /* The primary DMA stream should look like new right about now.
  86.  */
  87. primary->tail = 0;
  88. primary->space = primary->size;
  89. primary->last_flush = 0;
  90. sarea_priv->last_wrap = 0;
  91. /* FIXME: Reset counters, buffer ages etc...
  92.  */
  93. /* FIXME: What else do we need to reinitialize?  WARP stuff?
  94.  */
  95. return 0;
  96. }
  97. int mga_do_engine_reset( drm_mga_private_t *dev_priv )
  98. {
  99. DRM_DEBUG( "%sn", __FUNCTION__ );
  100. /* Okay, so we've completely screwed up and locked the engine.
  101.  * How about we clean up after ourselves?
  102.  */
  103. MGA_WRITE( MGA_RST, MGA_SOFTRESET );
  104. udelay( 15 ); /* Wait at least 10 usecs */
  105. MGA_WRITE( MGA_RST, 0 );
  106. /* Initialize the registers that get clobbered by the soft
  107.  * reset.  Many of the core register values survive a reset,
  108.  * but the drawing registers are basically all gone.
  109.  *
  110.  * 3D clients should probably die after calling this.  The X
  111.  * server should reset the engine state to known values.
  112.  */
  113. #if 0
  114. MGA_WRITE( MGA_PRIMPTR,
  115.    virt_to_bus((void *)dev_priv->prim.status_page) |
  116.    MGA_PRIMPTREN0 |
  117.    MGA_PRIMPTREN1 );
  118. #endif
  119. MGA_WRITE( MGA_ICLEAR, MGA_SOFTRAPICLR );
  120. MGA_WRITE( MGA_IEN,    MGA_SOFTRAPIEN );
  121. /* The primary DMA stream should look like new right about now.
  122.  */
  123. mga_do_dma_reset( dev_priv );
  124. /* This bad boy will never fail.
  125.  */
  126. return 0;
  127. }
  128. /* ================================================================
  129.  * Primary DMA stream
  130.  */
  131. void mga_do_dma_flush( drm_mga_private_t *dev_priv )
  132. {
  133. drm_mga_primary_buffer_t *primary = &dev_priv->prim;
  134. u32 head, tail;
  135. DMA_LOCALS;
  136. DRM_DEBUG( "%s:n", __FUNCTION__ );
  137. if ( primary->tail == primary->last_flush ) {
  138. DRM_DEBUG( "   bailing out...n" );
  139. return;
  140. }
  141. tail = primary->tail + dev_priv->primary->offset;
  142. /* We need to pad the stream between flushes, as the card
  143.  * actually (partially?) reads the first of these commands.
  144.  * See page 4-16 in the G400 manual, middle of the page or so.
  145.  */
  146. BEGIN_DMA( 1 );
  147. DMA_BLOCK( MGA_DMAPAD,  0x00000000,
  148.    MGA_DMAPAD,  0x00000000,
  149.    MGA_DMAPAD,  0x00000000,
  150.    MGA_DMAPAD, 0x00000000 );
  151. ADVANCE_DMA();
  152. primary->last_flush = primary->tail;
  153. head = MGA_READ( MGA_PRIMADDRESS );
  154. if ( head <= tail ) {
  155. primary->space = primary->size - primary->tail;
  156. } else {
  157. primary->space = head - tail;
  158. }
  159. DRM_DEBUG( "   head = 0x%06lxn", head - dev_priv->primary->offset );
  160. DRM_DEBUG( "   tail = 0x%06lxn", tail - dev_priv->primary->offset );
  161. DRM_DEBUG( "  space = 0x%06xn", primary->space );
  162. mga_flush_write_combine();
  163. MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );
  164. DRM_DEBUG( "%s: done.n", __FUNCTION__ );
  165. }
  166. void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv )
  167. {
  168. drm_mga_primary_buffer_t *primary = &dev_priv->prim;
  169. u32 head, tail;
  170. DMA_LOCALS;
  171. DRM_DEBUG( "%s:n", __FUNCTION__ );
  172. BEGIN_DMA_WRAP();
  173. DMA_BLOCK( MGA_DMAPAD, 0x00000000,
  174.    MGA_DMAPAD, 0x00000000,
  175.    MGA_DMAPAD, 0x00000000,
  176.    MGA_DMAPAD, 0x00000000 );
  177. ADVANCE_DMA();
  178. tail = primary->tail + dev_priv->primary->offset;
  179. primary->tail = 0;
  180. primary->last_flush = 0;
  181. primary->last_wrap++;
  182. head = MGA_READ( MGA_PRIMADDRESS );
  183. if ( head == dev_priv->primary->offset ) {
  184. primary->space = primary->size;
  185. } else {
  186. primary->space = head - dev_priv->primary->offset;
  187. }
  188. DRM_DEBUG( "   head = 0x%06lxn",
  189.   head - dev_priv->primary->offset );
  190. DRM_DEBUG( "   tail = 0x%06xn", primary->tail );
  191. DRM_DEBUG( "   wrap = %dn", primary->last_wrap );
  192. DRM_DEBUG( "  space = 0x%06xn", primary->space );
  193. mga_flush_write_combine();
  194. MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );
  195. set_bit( 0, &primary->wrapped );
  196. DRM_DEBUG( "%s: done.n", __FUNCTION__ );
  197. }
  198. void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv )
  199. {
  200. drm_mga_primary_buffer_t *primary = &dev_priv->prim;
  201. drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
  202. u32 head = dev_priv->primary->offset;
  203. DRM_DEBUG( "%s:n", __FUNCTION__ );
  204. sarea_priv->last_wrap++;
  205. DRM_DEBUG( "   wrap = %dn", sarea_priv->last_wrap );
  206. mga_flush_write_combine();
  207. MGA_WRITE( MGA_PRIMADDRESS, head | MGA_DMA_GENERAL );
  208. clear_bit( 0, &primary->wrapped );
  209. DRM_DEBUG( "%s: done.n", __FUNCTION__ );
  210. }
  211. /* ================================================================
  212.  * Freelist management
  213.  */
  214. #define MGA_BUFFER_USED ~0
  215. #define MGA_BUFFER_FREE 0
  216. #if MGA_FREELIST_DEBUG
  217. static void mga_freelist_print( drm_device_t *dev )
  218. {
  219. drm_mga_private_t *dev_priv = dev->dev_private;
  220. drm_mga_freelist_t *entry;
  221. DRM_INFO( "n" );
  222. DRM_INFO( "current dispatch: last=0x%x done=0x%xn",
  223.   dev_priv->sarea_priv->last_dispatch,
  224.   (unsigned int)(MGA_READ( MGA_PRIMADDRESS ) -
  225.  dev_priv->primary->offset) );
  226. DRM_INFO( "current freelist:n" );
  227. for ( entry = dev_priv->head->next ; entry ; entry = entry->next ) {
  228. DRM_INFO( "   %p   idx=%2d  age=0x%x 0x%06lxn",
  229.   entry, entry->buf->idx, entry->age.head,
  230.   entry->age.head - dev_priv->primary->offset );
  231. }
  232. DRM_INFO( "n" );
  233. }
  234. #endif
  235. static int mga_freelist_init( drm_device_t *dev, drm_mga_private_t *dev_priv )
  236. {
  237. drm_device_dma_t *dma = dev->dma;
  238. drm_buf_t *buf;
  239. drm_mga_buf_priv_t *buf_priv;
  240. drm_mga_freelist_t *entry;
  241. int i;
  242. DRM_DEBUG( "%s: count=%dn",
  243.    __FUNCTION__, dma->buf_count );
  244. dev_priv->head = DRM(alloc)( sizeof(drm_mga_freelist_t),
  245.      DRM_MEM_DRIVER );
  246. if ( dev_priv->head == NULL )
  247. return -ENOMEM;
  248. memset( dev_priv->head, 0, sizeof(drm_mga_freelist_t) );
  249. SET_AGE( &dev_priv->head->age, MGA_BUFFER_USED, 0 );
  250. for ( i = 0 ; i < dma->buf_count ; i++ ) {
  251. buf = dma->buflist[i];
  252.         buf_priv = buf->dev_private;
  253. entry = DRM(alloc)( sizeof(drm_mga_freelist_t),
  254.     DRM_MEM_DRIVER );
  255. if ( entry == NULL )
  256. return -ENOMEM;
  257. memset( entry, 0, sizeof(drm_mga_freelist_t) );
  258. entry->next = dev_priv->head->next;
  259. entry->prev = dev_priv->head;
  260. SET_AGE( &entry->age, MGA_BUFFER_FREE, 0 );
  261. entry->buf = buf;
  262. if ( dev_priv->head->next != NULL )
  263. dev_priv->head->next->prev = entry;
  264. if ( entry->next == NULL )
  265. dev_priv->tail = entry;
  266. buf_priv->list_entry = entry;
  267. buf_priv->discard = 0;
  268. buf_priv->dispatched = 0;
  269. dev_priv->head->next = entry;
  270. }
  271. return 0;
  272. }
  273. static void mga_freelist_cleanup( drm_device_t *dev )
  274. {
  275. drm_mga_private_t *dev_priv = dev->dev_private;
  276. drm_mga_freelist_t *entry;
  277. drm_mga_freelist_t *next;
  278. DRM_DEBUG( "%sn", __FUNCTION__ );
  279. entry = dev_priv->head;
  280. while ( entry ) {
  281. next = entry->next;
  282. DRM(free)( entry, sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER );
  283. entry = next;
  284. }
  285. dev_priv->head = dev_priv->tail = NULL;
  286. }
  287. #if 0
  288. /* FIXME: Still needed?
  289.  */
  290. static void mga_freelist_reset( drm_device_t *dev )
  291. {
  292. drm_device_dma_t *dma = dev->dma;
  293. drm_buf_t *buf;
  294. drm_mga_buf_priv_t *buf_priv;
  295. int i;
  296. for ( i = 0 ; i < dma->buf_count ; i++ ) {
  297. buf = dma->buflist[i];
  298.         buf_priv = buf->dev_private;
  299. SET_AGE( &buf_priv->list_entry->age,
  300.  MGA_BUFFER_FREE, 0 );
  301. }
  302. }
  303. #endif
  304. static drm_buf_t *mga_freelist_get( drm_device_t *dev )
  305. {
  306. drm_mga_private_t *dev_priv = dev->dev_private;
  307. drm_mga_freelist_t *next;
  308. drm_mga_freelist_t *prev;
  309. drm_mga_freelist_t *tail = dev_priv->tail;
  310. u32 head, wrap;
  311. DRM_DEBUG( "%s:n", __FUNCTION__ );
  312. head = MGA_READ( MGA_PRIMADDRESS );
  313. wrap = dev_priv->sarea_priv->last_wrap;
  314. DRM_DEBUG( "   tail=0x%06lx %dn",
  315.    tail->age.head ?
  316.    tail->age.head - dev_priv->primary->offset : 0,
  317.    tail->age.wrap );
  318. DRM_DEBUG( "   head=0x%06lx %dn",
  319.    head - dev_priv->primary->offset, wrap );
  320. if ( TEST_AGE( &tail->age, head, wrap ) ) {
  321. prev = dev_priv->tail->prev;
  322. next = dev_priv->tail;
  323. prev->next = NULL;
  324. next->prev = next->next = NULL;
  325. dev_priv->tail = prev;
  326. SET_AGE( &next->age, MGA_BUFFER_USED, 0 );
  327. return next->buf;
  328. }
  329. DRM_DEBUG( "returning NULL!n" );
  330. return NULL;
  331. }
  332. int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf )
  333. {
  334. drm_mga_private_t *dev_priv = dev->dev_private;
  335. drm_mga_buf_priv_t *buf_priv = buf->dev_private;
  336. drm_mga_freelist_t *head, *entry, *prev;
  337. DRM_DEBUG( "%s: age=0x%06lx wrap=%dn",
  338.    __FUNCTION__,
  339.    buf_priv->list_entry->age.head -
  340.    dev_priv->primary->offset,
  341.    buf_priv->list_entry->age.wrap );
  342. entry = buf_priv->list_entry;
  343. head = dev_priv->head;
  344. if ( buf_priv->list_entry->age.head == MGA_BUFFER_USED ) {
  345. SET_AGE( &entry->age, MGA_BUFFER_FREE, 0 );
  346. prev = dev_priv->tail;
  347. prev->next = entry;
  348. entry->prev = prev;
  349. entry->next = NULL;
  350. } else {
  351. prev = head->next;
  352. head->next = entry;
  353. prev->prev = entry;
  354. entry->prev = head;
  355. entry->next = prev;
  356. }
  357. return 0;
  358. }
  359. /* ================================================================
  360.  * DMA initialization, cleanup
  361.  */
  362. static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
  363. {
  364. drm_mga_private_t *dev_priv;
  365. struct list_head *list;
  366. int ret;
  367. DRM_DEBUG( "%sn", __FUNCTION__ );
  368. dev_priv = DRM(alloc)( sizeof(drm_mga_private_t), DRM_MEM_DRIVER );
  369. if ( !dev_priv )
  370. return -ENOMEM;
  371. memset( dev_priv, 0, sizeof(drm_mga_private_t) );
  372. dev_priv->chipset = init->chipset;
  373. dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
  374. if ( init->sgram ) {
  375. dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK;
  376. } else {
  377. dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR;
  378. }
  379. dev_priv->maccess = init->maccess;
  380. dev_priv->fb_cpp = init->fb_cpp;
  381. dev_priv->front_offset = init->front_offset;
  382. dev_priv->front_pitch = init->front_pitch;
  383. dev_priv->back_offset = init->back_offset;
  384. dev_priv->back_pitch = init->back_pitch;
  385. dev_priv->depth_cpp = init->depth_cpp;
  386. dev_priv->depth_offset = init->depth_offset;
  387. dev_priv->depth_pitch = init->depth_pitch;
  388. /* FIXME: Need to support AGP textures...
  389.  */
  390. dev_priv->texture_offset = init->texture_offset[0];
  391. dev_priv->texture_size = init->texture_size[0];
  392. list_for_each( list, &dev->maplist->head ) {
  393. drm_map_list_t *entry = (drm_map_list_t *)list;
  394. if ( entry->map &&
  395.      entry->map->type == _DRM_SHM &&
  396.      (entry->map->flags & _DRM_CONTAINS_LOCK) ) {
  397. dev_priv->sarea = entry->map;
  398.   break;
  399.   }
  400.   }
  401. if(!dev_priv->sarea) {
  402. DRM_ERROR( "failed to find sarea!n" );
  403. /* Assign dev_private so we can do cleanup. */
  404. dev->dev_private = (void *)dev_priv;
  405. mga_do_cleanup_dma( dev );
  406. return -EINVAL;
  407. }
  408. DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
  409. if(!dev_priv->fb) {
  410. DRM_ERROR( "failed to find framebuffer!n" );
  411. /* Assign dev_private so we can do cleanup. */
  412. dev->dev_private = (void *)dev_priv;
  413. mga_do_cleanup_dma( dev );
  414. return -EINVAL;
  415. }
  416. DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
  417. if(!dev_priv->mmio) {
  418. DRM_ERROR( "failed to find mmio region!n" );
  419. /* Assign dev_private so we can do cleanup. */
  420. dev->dev_private = (void *)dev_priv;
  421. mga_do_cleanup_dma( dev );
  422. return -EINVAL;
  423. }
  424. DRM_FIND_MAP( dev_priv->status, init->status_offset );
  425. if(!dev_priv->status) {
  426. DRM_ERROR( "failed to find status page!n" );
  427. /* Assign dev_private so we can do cleanup. */
  428. dev->dev_private = (void *)dev_priv;
  429. mga_do_cleanup_dma( dev );
  430. return -EINVAL;
  431. }
  432. DRM_FIND_MAP( dev_priv->warp, init->warp_offset );
  433. if(!dev_priv->warp) {
  434. DRM_ERROR( "failed to find warp microcode region!n" );
  435. /* Assign dev_private so we can do cleanup. */
  436. dev->dev_private = (void *)dev_priv;
  437. mga_do_cleanup_dma( dev );
  438. return -EINVAL;
  439. }
  440. DRM_FIND_MAP( dev_priv->primary, init->primary_offset );
  441. if(!dev_priv->primary) {
  442. DRM_ERROR( "failed to find primary dma region!n" );
  443. /* Assign dev_private so we can do cleanup. */
  444. dev->dev_private = (void *)dev_priv;
  445. mga_do_cleanup_dma( dev );
  446. return -EINVAL;
  447. }
  448. DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
  449. if(!dev_priv->buffers) {
  450. DRM_ERROR( "failed to find dma buffer region!n" );
  451. /* Assign dev_private so we can do cleanup. */
  452. dev->dev_private = (void *)dev_priv;
  453. mga_do_cleanup_dma( dev );
  454. return -EINVAL;
  455. }
  456. dev_priv->sarea_priv =
  457. (drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle +
  458.     init->sarea_priv_offset);
  459. DRM_IOREMAP( dev_priv->warp );
  460. DRM_IOREMAP( dev_priv->primary );
  461. DRM_IOREMAP( dev_priv->buffers );
  462. if(!dev_priv->warp->handle ||
  463.    !dev_priv->primary->handle ||
  464.    !dev_priv->buffers->handle ) {
  465. DRM_ERROR( "failed to ioremap agp regions!n" );
  466. /* Assign dev_private so we can do cleanup. */
  467. dev->dev_private = (void *)dev_priv;
  468. mga_do_cleanup_dma( dev );
  469. return -ENOMEM;
  470. }
  471. ret = mga_warp_install_microcode( dev_priv );
  472. if ( ret < 0 ) {
  473. DRM_ERROR( "failed to install WARP ucode!n" );
  474. /* Assign dev_private so we can do cleanup. */
  475. dev->dev_private = (void *)dev_priv;
  476. mga_do_cleanup_dma( dev );
  477. return ret;
  478. }
  479. ret = mga_warp_init( dev_priv );
  480. if ( ret < 0 ) {
  481. DRM_ERROR( "failed to init WARP engine!n" );
  482. /* Assign dev_private so we can do cleanup. */
  483. dev->dev_private = (void *)dev_priv;
  484. mga_do_cleanup_dma( dev );
  485. return ret;
  486. }
  487. dev_priv->prim.status = (u32 *)dev_priv->status->handle;
  488. mga_do_wait_for_idle( dev_priv );
  489. /* Init the primary DMA registers.
  490.  */
  491. MGA_WRITE( MGA_PRIMADDRESS,
  492.    dev_priv->primary->offset | MGA_DMA_GENERAL );
  493. #if 0
  494. MGA_WRITE( MGA_PRIMPTR,
  495.    virt_to_bus((void *)dev_priv->prim.status) |
  496.    MGA_PRIMPTREN0 | /* Soft trap, SECEND, SETUPEND */
  497.    MGA_PRIMPTREN1 ); /* DWGSYNC */
  498. #endif
  499. dev_priv->prim.start = (u8 *)dev_priv->primary->handle;
  500. dev_priv->prim.end = ((u8 *)dev_priv->primary->handle
  501.       + dev_priv->primary->size);
  502. dev_priv->prim.size = dev_priv->primary->size;
  503. dev_priv->prim.tail = 0;
  504. dev_priv->prim.space = dev_priv->prim.size;
  505. dev_priv->prim.wrapped = 0;
  506. dev_priv->prim.last_flush = 0;
  507. dev_priv->prim.last_wrap = 0;
  508. dev_priv->prim.high_mark = 256 * DMA_BLOCK_SIZE;
  509. spin_lock_init( &dev_priv->prim.list_lock );
  510. dev_priv->prim.status[0] = dev_priv->primary->offset;
  511. dev_priv->prim.status[1] = 0;
  512. dev_priv->sarea_priv->last_wrap = 0;
  513. dev_priv->sarea_priv->last_frame.head = 0;
  514. dev_priv->sarea_priv->last_frame.wrap = 0;
  515. if ( mga_freelist_init( dev, dev_priv ) < 0 ) {
  516. DRM_ERROR( "could not initialize freelistn" );
  517. /* Assign dev_private so we can do cleanup. */
  518. dev->dev_private = (void *)dev_priv;
  519. mga_do_cleanup_dma( dev );
  520. return -ENOMEM;
  521. }
  522. /* Make dev_private visable to others. */
  523. dev->dev_private = (void *)dev_priv;
  524. return 0;
  525. }
  526. int mga_do_cleanup_dma( drm_device_t *dev )
  527. {
  528. DRM_DEBUG( "%sn", __FUNCTION__ );
  529. if ( dev->dev_private ) {
  530. drm_mga_private_t *dev_priv = dev->dev_private;
  531. DRM_IOREMAPFREE( dev_priv->warp );
  532. DRM_IOREMAPFREE( dev_priv->primary );
  533. DRM_IOREMAPFREE( dev_priv->buffers );
  534. if ( dev_priv->head != NULL ) {
  535. mga_freelist_cleanup( dev );
  536. }
  537. DRM(free)( dev->dev_private, sizeof(drm_mga_private_t),
  538.    DRM_MEM_DRIVER );
  539. dev->dev_private = NULL;
  540. }
  541. return 0;
  542. }
  543. int mga_dma_init( struct inode *inode, struct file *filp,
  544.   unsigned int cmd, unsigned long arg )
  545. {
  546. drm_file_t *priv = filp->private_data;
  547. drm_device_t *dev = priv->dev;
  548. drm_mga_init_t init;
  549. if ( copy_from_user( &init, (drm_mga_init_t *)arg, sizeof(init) ) )
  550. return -EFAULT;
  551. switch ( init.func ) {
  552. case MGA_INIT_DMA:
  553. return mga_do_init_dma( dev, &init );
  554. case MGA_CLEANUP_DMA:
  555. return mga_do_cleanup_dma( dev );
  556. }
  557. return -EINVAL;
  558. }
  559. /* ================================================================
  560.  * Primary DMA stream management
  561.  */
  562. int mga_dma_flush( struct inode *inode, struct file *filp,
  563.    unsigned int cmd, unsigned long arg )
  564. {
  565. drm_file_t *priv = filp->private_data;
  566. drm_device_t *dev = priv->dev;
  567. drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
  568. drm_lock_t lock;
  569. LOCK_TEST_WITH_RETURN( dev );
  570. if ( copy_from_user( &lock, (drm_lock_t *)arg, sizeof(lock) ) )
  571. return -EFAULT;
  572. DRM_DEBUG( "%s: %s%s%sn",
  573.    __FUNCTION__,
  574.    (lock.flags & _DRM_LOCK_FLUSH) ? "flush, " : "",
  575.    (lock.flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "",
  576.    (lock.flags & _DRM_LOCK_QUIESCENT) ? "idle, " : "" );
  577. WRAP_WAIT_WITH_RETURN( dev_priv );
  578. if ( lock.flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL) ) {
  579. mga_do_dma_flush( dev_priv );
  580. }
  581. if ( lock.flags & _DRM_LOCK_QUIESCENT ) {
  582. #if MGA_DMA_DEBUG
  583. int ret = mga_do_wait_for_idle( dev_priv );
  584. if ( ret < 0 )
  585. DRM_INFO( __FUNCTION__": -EBUSYn" );
  586. return ret;
  587. #else
  588. return mga_do_wait_for_idle( dev_priv );
  589. #endif
  590. } else {
  591. return 0;
  592. }
  593. }
  594. int mga_dma_reset( struct inode *inode, struct file *filp,
  595.    unsigned int cmd, unsigned long arg )
  596. {
  597. drm_file_t *priv = filp->private_data;
  598. drm_device_t *dev = priv->dev;
  599. drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
  600. LOCK_TEST_WITH_RETURN( dev );
  601. return mga_do_dma_reset( dev_priv );
  602. }
  603. /* ================================================================
  604.  * DMA buffer management
  605.  */
  606. static int mga_dma_get_buffers( drm_device_t *dev, drm_dma_t *d )
  607. {
  608. drm_buf_t *buf;
  609. int i;
  610. for ( i = d->granted_count ; i < d->request_count ; i++ ) {
  611. buf = mga_freelist_get( dev );
  612. if ( !buf ) return -EAGAIN;
  613. buf->pid = current->pid;
  614. if ( copy_to_user( &d->request_indices[i],
  615.    &buf->idx, sizeof(buf->idx) ) )
  616. return -EFAULT;
  617. if ( copy_to_user( &d->request_sizes[i],
  618.    &buf->total, sizeof(buf->total) ) )
  619. return -EFAULT;
  620. d->granted_count++;
  621. }
  622. return 0;
  623. }
  624. int mga_dma_buffers( struct inode *inode, struct file *filp,
  625.      unsigned int cmd, unsigned long arg )
  626. {
  627. drm_file_t *priv = filp->private_data;
  628. drm_device_t *dev = priv->dev;
  629. drm_device_dma_t *dma = dev->dma;
  630. drm_mga_private_t *dev_priv = (drm_mga_private_t *)dev->dev_private;
  631. drm_dma_t d;
  632. int ret = 0;
  633. LOCK_TEST_WITH_RETURN( dev );
  634. if ( copy_from_user( &d, (drm_dma_t *)arg, sizeof(d) ) )
  635. return -EFAULT;
  636. /* Please don't send us buffers.
  637.  */
  638. if ( d.send_count != 0 ) {
  639. DRM_ERROR( "Process %d trying to send %d buffers via drmDMAn",
  640.    current->pid, d.send_count );
  641. return -EINVAL;
  642. }
  643. /* We'll send you buffers.
  644.  */
  645. if ( d.request_count < 0 || d.request_count > dma->buf_count ) {
  646. DRM_ERROR( "Process %d trying to get %d buffers (of %d max)n",
  647.    current->pid, d.request_count, dma->buf_count );
  648. return -EINVAL;
  649. }
  650. WRAP_TEST_WITH_RETURN( dev_priv );
  651. d.granted_count = 0;
  652. if ( d.request_count ) {
  653. ret = mga_dma_get_buffers( dev, &d );
  654. }
  655. if ( copy_to_user( (drm_dma_t *)arg, &d, sizeof(d) ) )
  656. return -EFAULT;
  657. return ret;
  658. }