Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

954 lines
30 KiB

  1. /******************************Module*Header*******************************\
  2. *
  3. * Module Name: displist.c
  4. * Author: Goran Devic, Mark Einkauf
  5. * Purpose: General output to Laguna3D
  6. *
  7. * Copyright (c) 1997 Cirrus Logic, Inc.
  8. *
  9. \**************************************************************************/
  10. #define OPENGL_MCD
  11. #include "precomp.h"
  12. #include "mcdhw.h"
  13. #include "mcdutil.h"
  14. /*********************************************************************
  15. * Defines
  16. **********************************************************************/
  17. #define DL_MIN_SIZE (8 * KB) // Minimum size of the d-list
  18. #define DL_MAX_SIZE (4096 * KB) // Maximum size of the d-list
  19. #define DL_SAFETY_MARGIN (1 * KB) // Margin when building d-list (b)
  20. //WARNING!!! Any change to DL_START_OFFSET must be made in polys.c also!!!
  21. #define DL_START_OFFSET 20 // 5 dwords offset for dlist
  22. //WARNING!!! Any change to DL_START_OFFSET must be made in polys.c also!!!
  23. /*********************************************************************
  24. * Include Files
  25. **********************************************************************/
  26. /*********************************************************************
  27. * Local Functions
  28. **********************************************************************/
  29. /*********************************************************************
  30. *
  31. * DWORD _InitDisplayList( LL_DeviceState * DC )
  32. *
  33. * Allocates memory and initializes display list structure.
  34. * Two display lists are created.
  35. *
  36. * Where:
  37. *
  38. * DC is the device context structure to be initialized
  39. * DC->dwDisplayListLen is the size of the display list
  40. * to be allocated (in bytes).
  41. *
  42. * Returns:
  43. *
  44. * LL_OK (0) if initialization succeeds
  45. * error_code if initialization fails
  46. *
  47. **********************************************************************/
  48. DWORD _InitDisplayList( PDEV *ppdev, DWORD dwListLen )
  49. {
  50. int i;
  51. #if 0
  52. // The user requested DC->dwDisplayListLen bytes of system memory
  53. // to be used for device display list. That memory will be
  54. // allocated and stay locked. But first, we subdivide it at
  55. // several chunks for display list multibuffering.
  56. //
  57. // Sanity check
  58. //
  59. if( dwListLen < DL_MIN_SIZE || dwListLen > DL_MAX_SIZE )
  60. return( LLE_INI_DL_LEN );
  61. // Subdivide display list and allocate each chunk
  62. //
  63. chunk_size = (dwListLen / NUM_DL) & ~3;
  64. for( i=0; i<NUM_DL; i++ )
  65. {
  66. // Allocate memory for a display list
  67. //
  68. if( (LL_State.DL[i].hMem = AllocSystemMemory( chunk_size )) == 0 )
  69. return( LLE_INI_ALLOC_DL );
  70. // Get the linear and physical address of a display list
  71. //
  72. LL_State.DL[i].pdwLinPtr = (DWORD *) GetLinearAddress( LL_State.DL[i].hMem );
  73. LL_State.DL[i].dwPhyPtr = GetPhysicalAddress( LL_State.DL[i].hMem );
  74. // Set the length and the parametarization pointer to point to the
  75. // offset of 20: 16 bytes are reserved for jump table, additional 4 bytes
  76. // for a semaphore.
  77. //
  78. LL_State.DL[i].dwLen = chunk_size;
  79. LL_State.DL[i].pdwNext = LL_State.DL[i].pdwLinPtr + DL_START_OFFSET/4;
  80. LL_State.DL[i].pdwStartOutPtr = LL_State.DL[i].pdwNext;//only used in coproc mode
  81. // Clear the jump table and a semaphore
  82. //
  83. LL_State.DL[i].pdwNext[0] = IDLE;
  84. LL_State.DL[i].pdwNext[1] = IDLE;
  85. LL_State.DL[i].pdwNext[2] = IDLE;
  86. LL_State.DL[i].pdwNext[3] = IDLE;
  87. LL_State.DL[i].pdwNext[4] = 0;
  88. // Set the safety margin for the parametarization routines
  89. //
  90. LL_State.DL[i].dwMargin = (DWORD)LL_State.DL[i].pdwLinPtr + chunk_size - DL_SAFETY_MARGIN;
  91. // Temporary fix for non-flushing TLB
  92. *(DWORD *)((DWORD)LL_State.DL[i].pdwLinPtr + chunk_size - 16) = BRANCH + DL_START_OFFSET;
  93. DEB2("Display list: %d\n", i );
  94. DEB2("\tLength = %d b\n", LL_State.DL[i].dwLen );
  95. DEB2("\tMemory handle = %08Xh\n", LL_State.DL[i].hMem );
  96. DEB2("\tLinear memory = %08Xh\n", LL_State.DL[i].pdwLinPtr );
  97. DEB2("\tPhysical memory = %08Xh\n", LL_State.DL[i].dwPhyPtr );
  98. DEB2("\tSafety margin = %08Xh\n", LL_State.DL[i].dwMargin );
  99. }
  100. // Set the current display list to the first one. This one will be
  101. // used with parametarizations
  102. //
  103. LL_State.dwCdl = 0;
  104. LL_State.pDL = &LL_State.DL[0];
  105. *(LL_State.pRegs + PF_BASE_ADDR_3D) = LL_State.DL[0].dwPhyPtr;
  106. #else
  107. // MCD_TEMP - reduced InitDisplayList function to get running quickly - 1 DList only
  108. ppdev->LL_State.DL[0].pdwLinPtr = ppdev->temp_DL_chunk;
  109. // Set the length and the parametarization pointer to point to the
  110. // offset of 20: 16 bytes are reserved for jump table, additional 4 bytes
  111. // for a semaphore.
  112. //
  113. ppdev->LL_State.DL[0].dwLen = dwListLen;
  114. ppdev->LL_State.DL[0].pdwNext = ppdev->LL_State.DL[0].pdwLinPtr + DL_START_OFFSET/4;
  115. ppdev->LL_State.DL[0].pdwStartOutPtr = ppdev->LL_State.DL[0].pdwNext;//only used in coproc mode
  116. ppdev->LL_State.pDL = &ppdev->LL_State.DL[ 0 ];
  117. ppdev->LL_State.pDL->pdwNext = ppdev->LL_State.pDL->pdwLinPtr + DL_START_OFFSET/4;
  118. ppdev->LL_State.pDL->pdwStartOutPtr = ppdev->LL_State.pDL->pdwNext;//only used in coproc mode
  119. #endif
  120. return( LL_OK );
  121. }
  122. #ifndef OPENGL_MCD
  123. /*********************************************************************
  124. *
  125. * void _CloseDisplayList()
  126. *
  127. * Cleans up the memory allocations for display list(s).
  128. * This function is to be called at closing the library.
  129. *
  130. **********************************************************************/
  131. void _CloseDisplayList()
  132. {
  133. int i;
  134. // Loop through and free each chunk of the display list
  135. //
  136. for( i=0; i<NUM_DL; i++ )
  137. {
  138. // Free memory and reset pointers just to be safe
  139. //
  140. FreeSystemMemory( LL_State.DL[i].hMem );
  141. memset( &LL_State.DL[i], 0, sizeof(TDisplayList) );
  142. }
  143. LL_State.pDL = NULL;
  144. }
  145. /*********************************************************************
  146. *
  147. * Batch cell instruction: LL_IDLE
  148. *
  149. * Stores IDLE Laguna 3D microinstruction.
  150. *
  151. * Every batch array that is sent to the LL_Execute() must have this
  152. * operation terminating it.
  153. *
  154. * Example:
  155. *
  156. * pBatch->bOp = LL_IDLE;
  157. *
  158. **********************************************************************/
  159. DWORD * fnIdle( DWORD * pdwNext, LL_Batch * pBatch )
  160. {
  161. if( !LL_State.fIndirectMode )
  162. *pdwNext++ = IDLE;
  163. return( pdwNext );
  164. }
  165. /*********************************************************************
  166. *
  167. * Batch cell instruction: LL_NOP
  168. *
  169. * Does nothing.
  170. *
  171. **********************************************************************/
  172. DWORD * fnNop( DWORD * pdwNext, LL_Batch * pBatch )
  173. {
  174. return( pdwNext );
  175. }
  176. /*********************************************************************
  177. *
  178. * Batch cell instruction: LL_RAW_DATA
  179. *
  180. * Copies raw data to the display list. The pointer to data (DWORD *)
  181. * is pVert, number of dwords to be copied is in wCount.
  182. *
  183. * Note: All the data must fit into a display list. No explicit checking
  184. * is done. Keep your data stream short!
  185. *
  186. * Example:
  187. *
  188. * pBatch->wCount = 2; // 2 integers of data
  189. * pBatch->pVert = (DWORD *) &MyData[0]; // Starting data address
  190. *
  191. **********************************************************************/
  192. DWORD * fnRawData( DWORD * pdwNext, LL_Batch * pBatch )
  193. {
  194. register int count;
  195. register DWORD * dwPtr;
  196. dwPtr = (DWORD *)pBatch->pVert;
  197. for( count = pBatch->wCount; count>0; count-- )
  198. {
  199. *pdwNext++ = *dwPtr++;
  200. }
  201. return( pdwNext );
  202. }
  203. #endif // ndef OPENGL_MCD
  204. /*********************************************************************
  205. *
  206. * DWORD * _RunLaguna( DWORD *pdwNext )
  207. *
  208. * Spins off Laguna 3D and resets the parametarization pointers
  209. * to the next available d-list
  210. *
  211. * The function will take into account the rendering mode that
  212. * was set to either processor or coprocessor indirect.
  213. * In the later case it will sense the instructions that can
  214. * not be executed in that mode and it will do them directly.
  215. *
  216. * Where:
  217. *
  218. * pdwNext is the pointer to a current display list to the next
  219. * available space.
  220. *
  221. * Returns:
  222. *
  223. * Offset in the new d-list to start building
  224. *
  225. **********************************************************************/
  226. void _RunLaguna( PDEV *ppdev, DWORD *pdwNext )
  227. {
  228. DWORD instr;
  229. int len;
  230. int address, offset, update_offset;
  231. int event;
  232. volatile int status;
  233. // Two rendering modes are supported: processor direct mode and
  234. // coprocessor indirect mode.
  235. //
  236. // MCD_TEMP - RunLaguna only supporting coprocessor mode now
  237. //if( ppdev->LL_State.fIndirectMode )
  238. {
  239. DWORD *pSrc, *pDest;
  240. // Co-processor indirect mode: use host data port to program
  241. // the hardware
  242. //
  243. pSrc = ppdev->LL_State.pDL->pdwStartOutPtr;
  244. pDest = ppdev->LL_State.pRegs + HOST_3D_DATA_PORT;
  245. // Assumption: On the entry of this loop pSrc points to the valid
  246. // instruction.
  247. //
  248. while( pdwNext != pSrc )
  249. {
  250. // The display list is examined for the instructions that
  251. // can not be executed in coprocessor mode. That involves
  252. // partially disassembling each instruction and tracing the
  253. // number of parameters.
  254. //
  255. // All this work is done so that WRITE_DEV_REGS and READ_DEV_REGS
  256. // may be detected and simulated. Other instructions such as
  257. // branches, idle, return, waits and interrupts are ignored.
  258. //
  259. /* Get the next instruction */
  260. instr = *pSrc;
  261. update_offset = 0;
  262. /* Switch on the instruction opcode */
  263. #if 1 // 1 here for good RM sound
  264. {
  265. int i;
  266. status = *(volatile *)(ppdev->LL_State.pRegs + PF_STATUS_3D);
  267. while (status & 0x200)
  268. {
  269. //i=10;
  270. //while (i--) { /* don't read in tight loop*/ }
  271. status = *(volatile *)(ppdev->LL_State.pRegs + PF_STATUS_3D);
  272. }
  273. }
  274. #endif
  275. USB_TIMEOUT_FIX(ppdev)
  276. switch( instr >> 27 )
  277. {
  278. case 0x00: /* Draw point opcode */
  279. case 0x01: /* Draw line opcode */
  280. case 0x02: /* Draw poly opcode */
  281. case 0x03: /* Write register opcode */
  282. /* Get the amount of data for this opcode */
  283. len = (instr & 0x3F) + 1;
  284. /* Send data to the host data area */
  285. while( len-- )
  286. *pDest = *pSrc++;
  287. break;
  288. case 0x05: /* Write device opcode (Simulated) */
  289. /* Step past the instruction opcode */
  290. pSrc++;
  291. /* Get the amount of data for this opcode */
  292. len = instr & 0x3F;
  293. /* Switch on the module selected */
  294. switch( (instr >> 21) & 0x1F )
  295. {
  296. case 0x00: /* VGA register set */
  297. /* Setup the device address and offset */
  298. address = (int) (((BYTE *) ppdev->LL_State.pRegs) + 0x0000);
  299. offset = (instr >> 6) & 0x0FF;
  300. break;
  301. case 0x01: /* VGA frame buffer */
  302. /* Setup the device address and offset */
  303. address = 0xA0000;
  304. offset = (instr >> 6) & 0x7FF;
  305. break;
  306. case 0x02: /* Video port */
  307. /* Setup the device address and offset */
  308. address = (int) (((BYTE *) ppdev->LL_State.pRegs) + 0x0100);
  309. offset = (instr >> 6) & 0x07F;
  310. break;
  311. case 0x03: /* Local peripheral bus */
  312. /* Setup the device address and offset */
  313. address = (int) (((BYTE *) ppdev->LL_State.pRegs) + 0x0180);
  314. offset = (instr >> 6) & 0x07F;
  315. break;
  316. case 0x04: /* Miscellaneous */
  317. /* Setup the device address and offset */
  318. address = (int) (((BYTE *) ppdev->LL_State.pRegs) + 0x0200);
  319. offset = (instr >> 6) & 0x0FF;
  320. break;
  321. case 0x05: /* 2D engine registers */
  322. /* Setup the device address and offset */
  323. address = (int) (((BYTE *) ppdev->LL_State.pRegs) + 0x0400);
  324. offset = (instr >> 6) & 0x3FF;
  325. break;
  326. case 0x06: /* 2D host data */
  327. /* Setup the device address and offset */
  328. address = (int) (((BYTE *) ppdev->LL_State.pRegs) + 0x0800);
  329. offset = (instr >> 6) & 0x7FF;
  330. break;
  331. case 0x07: /* Frame buffer */
  332. /* Setup the device address and offset */
  333. address = (int) ppdev->LL_State.pFrame;
  334. offset = (instr >> 6) & 0x7FF;
  335. break;
  336. case 0x08: /* ROM memory */
  337. /* Setup the device address and offset */
  338. address = 0xC0000;
  339. offset = (instr >> 6) & 0x7FF;
  340. break;
  341. case 0x09: /* 3D engine registers */
  342. /* Setup the device address and offset */
  343. address = (int) (((BYTE *) ppdev->LL_State.pRegs) + 0x4000);
  344. offset = (instr >> 6) & 0x1FF;
  345. break;
  346. case 0x0A: /* 3D host XY registers */
  347. /* Setup the device address and offset */
  348. address = (int) (((BYTE *) ppdev->LL_State.pRegs) + 0x4200);
  349. offset = (instr >> 6) & 0x0FF;
  350. update_offset = 4;
  351. break;
  352. case 0x0B: /* 3D host data */
  353. /* Setup the device address and offset */
  354. address = (int) (((BYTE *) ppdev->LL_State.pRegs) + 0x4800);
  355. offset = (instr >> 6) & 0x3FF;
  356. break;
  357. default: /* Unknown module */
  358. /* Setup the device address and offset */
  359. //printf("RL:WriteDev, unknown mod instr=%x\n",instr);
  360. address = (int)NULL;
  361. offset = (int)NULL;
  362. break;
  363. }
  364. /* If this device supported, send the data */
  365. if ( address )
  366. {
  367. /* Send data to the device */
  368. while( len-- )
  369. {
  370. *(DWORD *)( address + offset ) = *pSrc++;
  371. offset += update_offset;
  372. }
  373. }
  374. else
  375. pSrc += len;
  376. break;
  377. case 0x0D: /* Control opcode */
  378. /* Step past the instruction opcode */
  379. pSrc++;
  380. /* Switch on the sub-opcode value */
  381. switch( (instr >> 22) & 0x0F )
  382. {
  383. case 0: /* Idle sub-opcode */
  384. /* Force exit from display list */
  385. pSrc = pdwNext;
  386. break;
  387. case 5: /* Clear sub-opcode */
  388. *pDest = instr;
  389. break;
  390. }
  391. break;
  392. case 0x0E: /* Wait opcode */
  393. {
  394. int wait_time_out;
  395. /* Step past the instruction opcode */
  396. pSrc++;
  397. /* Get the wait event mask */
  398. event = instr & 0x3FF;
  399. if (event == EV_BUFFER_SWITCH)
  400. wait_time_out=100000;
  401. else
  402. wait_time_out=5000000;
  403. /* Switch on the wait opcode sub-type (AND/OR/NAND/NOR) */
  404. switch( (instr >> 24) & 0x03 )
  405. {
  406. case 0: /* Wait OR sub-opcode */
  407. /* Wait for requested event to happen */
  408. do
  409. {
  410. status = (*(volatile *)(ppdev->LL_State.pRegs + PF_STATUS_3D) & 0x3FF) ^ 0x3E0;
  411. } while((!(status & event)) && wait_time_out--);
  412. break;
  413. case 1: /* Wait NOR sub-code */
  414. /* Wait for requested event to happen */
  415. do
  416. {
  417. status = (*(volatile *)(ppdev->LL_State.pRegs + PF_STATUS_3D) & 0x3FF) ^ 0x01F;
  418. } while((!(status & event)) && wait_time_out--);
  419. break;
  420. case 2: /* Wait AND sub-opcode */
  421. /* Wait for requested events to happen */
  422. do
  423. {
  424. status = (*(volatile *)(ppdev->LL_State.pRegs + PF_STATUS_3D) & 0x3FF) ^ 0x3E0;
  425. } while(((status & event) != event) && wait_time_out--);
  426. break;
  427. case 3: /* Wait NAND sub-opcode */
  428. /* Wait for requested events to happen */
  429. do
  430. {
  431. status = (*(volatile *)(ppdev->LL_State.pRegs + PF_STATUS_3D) & 0x3FF) ^ 0x01F;
  432. } while(((status & event) != event) && wait_time_out--);
  433. break;
  434. }
  435. //if (wait_time_out <= 0) printf("WAIT TIMED OUT, instr = %x, ev=%x stat=%x\n",instr,event,status);
  436. }
  437. break;
  438. default: /* Unknown/unhandled opcode (Skip) */
  439. //printf("RL:WriteDev, unknown opcode, instr=%x\n",instr);
  440. /* Step past the instruction opcode */
  441. pSrc++;
  442. break;
  443. }
  444. }
  445. }
  446. #if 0 // MCD_TEMP - no processor mode support yet
  447. else
  448. {
  449. // Check for valid address to put IDLE
  450. //
  451. if( ((int)pdwNext < (int)ppdev->LL_State.pDL->pdwLinPtr) ||
  452. ((int)pdwNext - (int)ppdev->LL_State.pDL->pdwLinPtr >= chunk_size - 16) )
  453. {
  454. //printf("DISPLAY LIST OVERRUN\n");
  455. goto proceed;
  456. }
  457. // Stuff IDLE since this must be the end of current display list
  458. //
  459. *pdwNext = IDLE;
  460. // If Laguna is still busy with the previous d-list, poll
  461. // it until it is idle.
  462. //
  463. DEB("Entering 3D Engine Busy wait state...\n");
  464. LL_Wait();
  465. // We have to set the base address of the display list
  466. // This address is used as a base address when
  467. // fetching display list instructions
  468. //
  469. *(ppdev->LL_State.pRegs + PF_BASE_ADDR_3D) = ppdev->LL_State.pDL->dwPhyPtr;
  470. inp(0x80);
  471. inp(0x80);
  472. DEB2("New base: PF_BASE_ADDR_3D: %08X\n", *(ppdev->LL_State.pRegs + PF_BASE_ADDR_3D) );
  473. // Start the execution of the display list from the offset 0
  474. //
  475. // *(ppdev->LL_State.pRegs + PF_INST_3D) = BRANCH + DL_START_OFFSET;
  476. // No! Temporary fix the prefetch bug and jump to the
  477. // top of the display list where the real branch(0)
  478. // instruction was stored during the display list initialization
  479. //
  480. DEB4("Issuing BRANCH %08X (->%08X ->%08X)\n", BRANCH + chunk_size - 16,
  481. *(DWORD *)((int)ppdev->LL_State.pDL->pdwLinPtr + chunk_size - 16),
  482. *(ppdev->LL_State.pDL->pdwLinPtr + 5) );
  483. if( *(DWORD *)((int)ppdev->LL_State.pDL->pdwLinPtr + chunk_size - 16) != BRANCH + DL_START_OFFSET )
  484. {
  485. //printf("BRANCH LOCATION CONTAINS INVALID DATA!\n");
  486. goto proceed;
  487. }
  488. *(ppdev->LL_State.pRegs + PF_INST_3D) = BRANCH + chunk_size - 16;
  489. inp(0x80);
  490. inp(0x80);
  491. }
  492. proceed:
  493. #endif // 0 - no processor mode support yet
  494. #if 0
  495. // Set the active display list index to the next in an array
  496. //
  497. if( ++ppdev->LL_State.dwCdl >= NUM_DL )
  498. ppdev->LL_State.dwCdl = 0;
  499. // Reset the parametarization pointer to the beginning
  500. // of the next display list
  501. //
  502. ppdev->LL_State.pDL = &ppdev->LL_State.DL[ ppdev->LL_State.dwCdl ];
  503. ppdev->LL_State.pDL->pdwNext = ppdev->LL_State.pDL->pdwLinPtr + DL_START_OFFSET/4;
  504. ppdev->LL_State.pDL->pdwStartOutPtr = ppdev->LL_State.pDL->pdwNext;//only used in coproc mode
  505. return( ppdev->LL_State.pDL->pdwNext );
  506. #else // 0
  507. // MCD_TEMP - ppdev->LL_State.pDL remains same always since only 1 DList
  508. ppdev->LL_State.pDL->pdwNext = ppdev->LL_State.pDL->pdwLinPtr + DL_START_OFFSET/4;
  509. ppdev->LL_State.pDL->pdwStartOutPtr = ppdev->LL_State.pDL->pdwNext;//only used in coproc mode
  510. #endif // 0
  511. }
  512. #ifndef OPENGL_MCD
  513. /*********************************************************************
  514. *
  515. * void LL_Execute( LL_Batch * pBatch )
  516. *
  517. * Builds the display list from the batch array and executes it.
  518. * This function is the main executing function. If the batch
  519. * array cannot be completely fit into the available display
  520. * list, it will be processed in multiple pieces.
  521. *
  522. **********************************************************************/
  523. void LL_Execute( LL_Batch * pBatch )
  524. {
  525. register DWORD *pdwNext;
  526. // First we build the current display list
  527. //
  528. pdwNext = LL_State.pDL->pdwNext;
  529. do
  530. {
  531. // Build the current display list until IDLE instruction
  532. //
  533. //printf("bOp=%x\n",pBatch->bOp);
  534. pdwNext = (fnList[ pBatch->bOp ])( pdwNext, pBatch );
  535. } while( (pBatch++)->bOp != LL_IDLE );
  536. // Spin off the d-list that was just built and prepare to render
  537. // to the next available d-list
  538. //
  539. (void)_RunLaguna( pdwNext );
  540. }
  541. /*********************************************************************
  542. *
  543. * void LL_QueueOp( LL_Batch *pBatch )
  544. *
  545. * Queues the operation. This function supports programming the
  546. * l3d without using the arrays of batch cells and vertex cells.
  547. * Instead of building a batch command, all the parameters that
  548. * are to be set in a batch are passed in this function.
  549. *
  550. * Where:
  551. *
  552. * pBatch->bOp is the operation (eg. LL_LINE)
  553. * pBatch->wCount is the generic count
  554. * pBatch->dwFlags are the operation flags
  555. * pBatch->wBuf is the buffer/texture designator
  556. * pBatch->pVert is the pointer to a vertex array defining the operation
  557. *
  558. **********************************************************************/
  559. void LL_QueueOp( LL_Batch *pBatch )
  560. {
  561. // We continue building the current display list
  562. // If instruction was IDLE, spin-off the current d-list
  563. //
  564. if( pBatch->bOp == LL_IDLE )
  565. (void)_RunLaguna( LL_State.pDL->pdwNext );
  566. else
  567. LL_State.pDL->pdwNext = (fnList[ pBatch->bOp ])( LL_State.pDL->pdwNext, pBatch );
  568. }
  569. /*********************************************************************
  570. *
  571. * void LL_SetRenderingMode( DWORD dwMode )
  572. *
  573. * Sets the rendering mode: coprocessor indirect or processor
  574. * mode. By default, library will use processor mode and build
  575. * display list to execute it.
  576. *
  577. * Where:
  578. *
  579. * dwMode is one of LL_PROCESSOR_MODE
  580. * LL_COPROCESSOR_MODE
  581. *
  582. *
  583. **********************************************************************/
  584. void LL_SetRenderingMode( DWORD dwMode )
  585. {
  586. LL_State.fIndirectMode = dwMode;
  587. DEB2("Rendering mode set to: %sPROCESSOR\n", dwMode?"CO":"" );
  588. LL_Wait();
  589. }
  590. /*********************************************************************
  591. *
  592. * void DumpDisplayList( DWORD *pPtr, DWORD dwLen )
  593. *
  594. * Dumps the content of the display list to the file. This function
  595. * can be used by a software developer for debugging.
  596. *
  597. * The display list disassembler (sldis.exe) may be used to
  598. * disassemble the display list:
  599. *
  600. * sldis -i9 < list00.pci > list00.out
  601. *
  602. * Where:
  603. *
  604. * pPtr is the starting address to dump
  605. * dwLen is the number of dwords to dump
  606. *
  607. **********************************************************************/
  608. void DumpDisplayList( DWORD *pPtr, DWORD dwLen )
  609. {
  610. static int count = 0;
  611. static char *sName = "List00.pci";
  612. FILE *fp;
  613. DWORD i;
  614. #ifndef CGL
  615. // if( count == 5 )
  616. // count = 4;
  617. sprintf(&sName[4], "%02X.pci", count++ );
  618. printf("Temp Name: %s\nSize:%d dwords", sName, dwLen );
  619. if( (fp=fopen(sName, "w" ))==NULL )
  620. return;
  621. for( i=0; i<dwLen; i++ )
  622. {
  623. fprintf(fp, "%08X %08X\n", pPtr, *pPtr );
  624. pPtr++;
  625. }
  626. fclose(fp);
  627. fflush(NULL);
  628. #else // CGL's DLL - no file io allowed
  629. printf("Temp Name: %s\nSize:%d dwords\n", sName, dwLen );
  630. for( i=0; i<dwLen; i++ )
  631. {
  632. printf("%08X %08X\n", pPtr, *pPtr );flushall();
  633. pPtr++;
  634. }
  635. #endif
  636. }
  637. /*********************************************************************
  638. *
  639. * void LL_Wait()
  640. *
  641. * Waits for enging to become not busy. Use this call when
  642. * switching from display list mode to direct programming
  643. * mode to ensure that the engine is idle.
  644. *
  645. *
  646. **********************************************************************/
  647. void LL_Wait()
  648. {
  649. DWORD dwValue;
  650. int delay;
  651. volatile DWORD dwCount;
  652. #define MAX_COUNT 1000000
  653. #define DELAY_COUNT 100
  654. dwCount = 0;
  655. // Poll the 3D engine to finish rendering
  656. //
  657. do
  658. {
  659. dwValue = *(volatile *)(LL_State.pRegs + PF_STATUS_3D);
  660. DEB2("LL_Wait... PF_STATUS_3D: %08X\n", dwValue );
  661. DEB2("LL_Wait... PF_INST_3D: %08X\n", *(LL_State.pRegs + PF_INST_3D) );
  662. // wait before polling again to give PCI a breather, unless
  663. // the last read shows everything idle
  664. for( delay = 0;
  665. (delay<DELAY_COUNT) && (dwValue & LL_State.dwWaitMode);
  666. delay++ ) { /*inp(0x80);*/ }
  667. if( dwCount++ == MAX_COUNT )
  668. _ShutDown("Laguna does not respond (PF_STATUS is %08X)", dwValue );
  669. } while(dwValue & LL_State.dwWaitMode );
  670. }
  671. void LL_Wait2()
  672. {
  673. DWORD dwValue;
  674. int delay;
  675. volatile DWORD dwCount;
  676. dwCount = 0;
  677. // Poll the 3D engine to finish rendering
  678. //
  679. do
  680. {
  681. dwValue = *(volatile *)(LL_State.pRegs + PF_STATUS_3D);
  682. DEB2("LL_Wait... PF_STATUS_3D: %08X\n", dwValue );
  683. DEB2("LL_Wait... PF_INST_3D: %08X\n", *(LL_State.pRegs + PF_INST_3D) );
  684. // wait before polling again to give PCI a breather, unless
  685. // the last read shows everything idle
  686. for( delay = 0;
  687. (delay<DELAY_COUNT) && (dwValue & LL_State.dwWaitMode);
  688. delay++ ) inp(0x80);
  689. if( dwCount++ == MAX_COUNT )
  690. _ShutDown("Laguna does not respond (PF_STATUS is %08X)", dwValue );
  691. } while(dwValue & LL_State.dwWaitMode );
  692. }
  693. void LL_Wait3()
  694. {
  695. DWORD dwValue;
  696. int delay;
  697. volatile DWORD dwCount;
  698. dwCount = 0;
  699. // Poll the 3D engine to finish rendering
  700. //
  701. do
  702. {
  703. dwValue = *(volatile *)(LL_State.pRegs + PF_STATUS_3D);
  704. if (dwValue & LL_State.dwWaitMode) {printf("WARNING: 3rd wait busy, val=%08x\n",dwValue);}
  705. DEB2("LL_Wait... PF_STATUS_3D: %08X\n", dwValue );
  706. DEB2("LL_Wait... PF_INST_3D: %08X\n", *(LL_State.pRegs + PF_INST_3D) );
  707. // wait before polling again to give PCI a breather, unless
  708. // the last read shows everything idle
  709. for( delay = 0;
  710. (delay<DELAY_COUNT) && (dwValue & LL_State.dwWaitMode);
  711. delay++ ) inp(0x80);
  712. if( dwCount++ == MAX_COUNT )
  713. _ShutDown("Laguna does not respond (PF_STATUS is %08X)", dwValue );
  714. } while(dwValue & LL_State.dwWaitMode );
  715. }
  716. #endif // ndef OPENGL_MCD