r600_cs.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  1. /*
  2. * Copyright 2008 Advanced Micro Devices, Inc.
  3. * Copyright 2008 Red Hat Inc.
  4. * Copyright 2009 Jerome Glisse.
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a
  7. * copy of this software and associated documentation files (the "Software"),
  8. * to deal in the Software without restriction, including without limitation
  9. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10. * and/or sell copies of the Software, and to permit persons to whom the
  11. * Software is furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  20. * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  21. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  22. * OTHER DEALINGS IN THE SOFTWARE.
  23. *
  24. * Authors: Dave Airlie
  25. * Alex Deucher
  26. * Jerome Glisse
  27. */
  28. #include "drmP.h"
  29. #include "radeon.h"
  30. #include "r600d.h"
  31. static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
  32. struct radeon_cs_reloc **cs_reloc);
  33. static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
  34. struct radeon_cs_reloc **cs_reloc);
  35. typedef int (*next_reloc_t)(struct radeon_cs_parser*, struct radeon_cs_reloc**);
  36. static next_reloc_t r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_mm;
  37. /**
  38. * r600_cs_packet_parse() - parse cp packet and point ib index to next packet
  39. * @parser: parser structure holding parsing context.
  40. * @pkt: where to store packet informations
  41. *
  42. * Assume that chunk_ib_index is properly set. Will return -EINVAL
  43. * if packet is bigger than remaining ib size. or if packets is unknown.
  44. **/
  45. int r600_cs_packet_parse(struct radeon_cs_parser *p,
  46. struct radeon_cs_packet *pkt,
  47. unsigned idx)
  48. {
  49. struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
  50. uint32_t header;
  51. if (idx >= ib_chunk->length_dw) {
  52. DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
  53. idx, ib_chunk->length_dw);
  54. return -EINVAL;
  55. }
  56. header = radeon_get_ib_value(p, idx);
  57. pkt->idx = idx;
  58. pkt->type = CP_PACKET_GET_TYPE(header);
  59. pkt->count = CP_PACKET_GET_COUNT(header);
  60. pkt->one_reg_wr = 0;
  61. switch (pkt->type) {
  62. case PACKET_TYPE0:
  63. pkt->reg = CP_PACKET0_GET_REG(header);
  64. break;
  65. case PACKET_TYPE3:
  66. pkt->opcode = CP_PACKET3_GET_OPCODE(header);
  67. break;
  68. case PACKET_TYPE2:
  69. pkt->count = -1;
  70. break;
  71. default:
  72. DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx);
  73. return -EINVAL;
  74. }
  75. if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) {
  76. DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n",
  77. pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
  78. return -EINVAL;
  79. }
  80. return 0;
  81. }
  82. /**
  83. * r600_cs_packet_next_reloc_mm() - parse next packet which should be reloc packet3
  84. * @parser: parser structure holding parsing context.
  85. * @data: pointer to relocation data
  86. * @offset_start: starting offset
  87. * @offset_mask: offset mask (to align start offset on)
  88. * @reloc: reloc informations
  89. *
  90. * Check next packet is relocation packet3, do bo validation and compute
  91. * GPU offset using the provided start.
  92. **/
  93. static int r600_cs_packet_next_reloc_mm(struct radeon_cs_parser *p,
  94. struct radeon_cs_reloc **cs_reloc)
  95. {
  96. struct radeon_cs_chunk *relocs_chunk;
  97. struct radeon_cs_packet p3reloc;
  98. unsigned idx;
  99. int r;
  100. if (p->chunk_relocs_idx == -1) {
  101. DRM_ERROR("No relocation chunk !\n");
  102. return -EINVAL;
  103. }
  104. *cs_reloc = NULL;
  105. relocs_chunk = &p->chunks[p->chunk_relocs_idx];
  106. r = r600_cs_packet_parse(p, &p3reloc, p->idx);
  107. if (r) {
  108. return r;
  109. }
  110. p->idx += p3reloc.count + 2;
  111. if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
  112. DRM_ERROR("No packet3 for relocation for packet at %d.\n",
  113. p3reloc.idx);
  114. return -EINVAL;
  115. }
  116. idx = radeon_get_ib_value(p, p3reloc.idx + 1);
  117. if (idx >= relocs_chunk->length_dw) {
  118. DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
  119. idx, relocs_chunk->length_dw);
  120. return -EINVAL;
  121. }
  122. /* FIXME: we assume reloc size is 4 dwords */
  123. *cs_reloc = p->relocs_ptr[(idx / 4)];
  124. return 0;
  125. }
  126. /**
  127. * r600_cs_packet_next_reloc_nomm() - parse next packet which should be reloc packet3
  128. * @parser: parser structure holding parsing context.
  129. * @data: pointer to relocation data
  130. * @offset_start: starting offset
  131. * @offset_mask: offset mask (to align start offset on)
  132. * @reloc: reloc informations
  133. *
  134. * Check next packet is relocation packet3, do bo validation and compute
  135. * GPU offset using the provided start.
  136. **/
  137. static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p,
  138. struct radeon_cs_reloc **cs_reloc)
  139. {
  140. struct radeon_cs_chunk *relocs_chunk;
  141. struct radeon_cs_packet p3reloc;
  142. unsigned idx;
  143. int r;
  144. if (p->chunk_relocs_idx == -1) {
  145. DRM_ERROR("No relocation chunk !\n");
  146. return -EINVAL;
  147. }
  148. *cs_reloc = NULL;
  149. relocs_chunk = &p->chunks[p->chunk_relocs_idx];
  150. r = r600_cs_packet_parse(p, &p3reloc, p->idx);
  151. if (r) {
  152. return r;
  153. }
  154. p->idx += p3reloc.count + 2;
  155. if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) {
  156. DRM_ERROR("No packet3 for relocation for packet at %d.\n",
  157. p3reloc.idx);
  158. return -EINVAL;
  159. }
  160. idx = radeon_get_ib_value(p, p3reloc.idx + 1);
  161. if (idx >= relocs_chunk->length_dw) {
  162. DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
  163. idx, relocs_chunk->length_dw);
  164. return -EINVAL;
  165. }
  166. *cs_reloc = &p->relocs[0];
  167. (*cs_reloc)->lobj.gpu_offset = (u64)relocs_chunk->kdata[idx + 3] << 32;
  168. (*cs_reloc)->lobj.gpu_offset |= relocs_chunk->kdata[idx + 0];
  169. return 0;
  170. }
  171. /**
  172. * r600_cs_packet_next_vline() - parse userspace VLINE packet
  173. * @parser: parser structure holding parsing context.
  174. *
  175. * Userspace sends a special sequence for VLINE waits.
  176. * PACKET0 - VLINE_START_END + value
  177. * PACKET3 - WAIT_REG_MEM poll vline status reg
  178. * RELOC (P3) - crtc_id in reloc.
  179. *
  180. * This function parses this and relocates the VLINE START END
  181. * and WAIT_REG_MEM packets to the correct crtc.
  182. * It also detects a switched off crtc and nulls out the
  183. * wait in that case.
  184. */
  185. static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
  186. {
  187. struct drm_mode_object *obj;
  188. struct drm_crtc *crtc;
  189. struct radeon_crtc *radeon_crtc;
  190. struct radeon_cs_packet p3reloc, wait_reg_mem;
  191. int crtc_id;
  192. int r;
  193. uint32_t header, h_idx, reg, wait_reg_mem_info;
  194. volatile uint32_t *ib;
  195. ib = p->ib->ptr;
  196. /* parse the WAIT_REG_MEM */
  197. r = r600_cs_packet_parse(p, &wait_reg_mem, p->idx);
  198. if (r)
  199. return r;
  200. /* check its a WAIT_REG_MEM */
  201. if (wait_reg_mem.type != PACKET_TYPE3 ||
  202. wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
  203. DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
  204. r = -EINVAL;
  205. return r;
  206. }
  207. wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
  208. /* bit 4 is reg (0) or mem (1) */
  209. if (wait_reg_mem_info & 0x10) {
  210. DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
  211. r = -EINVAL;
  212. return r;
  213. }
  214. /* waiting for value to be equal */
  215. if ((wait_reg_mem_info & 0x7) != 0x3) {
  216. DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
  217. r = -EINVAL;
  218. return r;
  219. }
  220. if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != AVIVO_D1MODE_VLINE_STATUS) {
  221. DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
  222. r = -EINVAL;
  223. return r;
  224. }
  225. if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != AVIVO_D1MODE_VLINE_STAT) {
  226. DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
  227. r = -EINVAL;
  228. return r;
  229. }
  230. /* jump over the NOP */
  231. r = r600_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);
  232. if (r)
  233. return r;
  234. h_idx = p->idx - 2;
  235. p->idx += wait_reg_mem.count + 2;
  236. p->idx += p3reloc.count + 2;
  237. header = radeon_get_ib_value(p, h_idx);
  238. crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
  239. reg = CP_PACKET0_GET_REG(header);
  240. mutex_lock(&p->rdev->ddev->mode_config.mutex);
  241. obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
  242. if (!obj) {
  243. DRM_ERROR("cannot find crtc %d\n", crtc_id);
  244. r = -EINVAL;
  245. goto out;
  246. }
  247. crtc = obj_to_crtc(obj);
  248. radeon_crtc = to_radeon_crtc(crtc);
  249. crtc_id = radeon_crtc->crtc_id;
  250. if (!crtc->enabled) {
  251. /* if the CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
  252. ib[h_idx + 2] = PACKET2(0);
  253. ib[h_idx + 3] = PACKET2(0);
  254. ib[h_idx + 4] = PACKET2(0);
  255. ib[h_idx + 5] = PACKET2(0);
  256. ib[h_idx + 6] = PACKET2(0);
  257. ib[h_idx + 7] = PACKET2(0);
  258. ib[h_idx + 8] = PACKET2(0);
  259. } else if (crtc_id == 1) {
  260. switch (reg) {
  261. case AVIVO_D1MODE_VLINE_START_END:
  262. header &= ~R600_CP_PACKET0_REG_MASK;
  263. header |= AVIVO_D2MODE_VLINE_START_END >> 2;
  264. break;
  265. default:
  266. DRM_ERROR("unknown crtc reloc\n");
  267. r = -EINVAL;
  268. goto out;
  269. }
  270. ib[h_idx] = header;
  271. ib[h_idx + 4] = AVIVO_D2MODE_VLINE_STATUS >> 2;
  272. }
  273. out:
  274. mutex_unlock(&p->rdev->ddev->mode_config.mutex);
  275. return r;
  276. }
  277. static int r600_packet0_check(struct radeon_cs_parser *p,
  278. struct radeon_cs_packet *pkt,
  279. unsigned idx, unsigned reg)
  280. {
  281. int r;
  282. switch (reg) {
  283. case AVIVO_D1MODE_VLINE_START_END:
  284. r = r600_cs_packet_parse_vline(p);
  285. if (r) {
  286. DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
  287. idx, reg);
  288. return r;
  289. }
  290. break;
  291. default:
  292. printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
  293. reg, idx);
  294. return -EINVAL;
  295. }
  296. return 0;
  297. }
  298. static int r600_cs_parse_packet0(struct radeon_cs_parser *p,
  299. struct radeon_cs_packet *pkt)
  300. {
  301. unsigned reg, i;
  302. unsigned idx;
  303. int r;
  304. idx = pkt->idx + 1;
  305. reg = pkt->reg;
  306. for (i = 0; i <= pkt->count; i++, idx++, reg += 4) {
  307. r = r600_packet0_check(p, pkt, idx, reg);
  308. if (r) {
  309. return r;
  310. }
  311. }
  312. return 0;
  313. }
  314. static int r600_packet3_check(struct radeon_cs_parser *p,
  315. struct radeon_cs_packet *pkt)
  316. {
  317. struct radeon_cs_reloc *reloc;
  318. volatile u32 *ib;
  319. unsigned idx;
  320. unsigned i;
  321. unsigned start_reg, end_reg, reg;
  322. int r;
  323. u32 idx_value;
  324. ib = p->ib->ptr;
  325. idx = pkt->idx + 1;
  326. idx_value = radeon_get_ib_value(p, idx);
  327. switch (pkt->opcode) {
  328. case PACKET3_START_3D_CMDBUF:
  329. if (p->family >= CHIP_RV770 || pkt->count) {
  330. DRM_ERROR("bad START_3D\n");
  331. return -EINVAL;
  332. }
  333. break;
  334. case PACKET3_CONTEXT_CONTROL:
  335. if (pkt->count != 1) {
  336. DRM_ERROR("bad CONTEXT_CONTROL\n");
  337. return -EINVAL;
  338. }
  339. break;
  340. case PACKET3_INDEX_TYPE:
  341. case PACKET3_NUM_INSTANCES:
  342. if (pkt->count) {
  343. DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES\n");
  344. return -EINVAL;
  345. }
  346. break;
  347. case PACKET3_DRAW_INDEX:
  348. if (pkt->count != 3) {
  349. DRM_ERROR("bad DRAW_INDEX\n");
  350. return -EINVAL;
  351. }
  352. r = r600_cs_packet_next_reloc(p, &reloc);
  353. if (r) {
  354. DRM_ERROR("bad DRAW_INDEX\n");
  355. return -EINVAL;
  356. }
  357. ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
  358. ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
  359. break;
  360. case PACKET3_DRAW_INDEX_AUTO:
  361. if (pkt->count != 1) {
  362. DRM_ERROR("bad DRAW_INDEX_AUTO\n");
  363. return -EINVAL;
  364. }
  365. break;
  366. case PACKET3_DRAW_INDEX_IMMD_BE:
  367. case PACKET3_DRAW_INDEX_IMMD:
  368. if (pkt->count < 2) {
  369. DRM_ERROR("bad DRAW_INDEX_IMMD\n");
  370. return -EINVAL;
  371. }
  372. break;
  373. case PACKET3_WAIT_REG_MEM:
  374. if (pkt->count != 5) {
  375. DRM_ERROR("bad WAIT_REG_MEM\n");
  376. return -EINVAL;
  377. }
  378. /* bit 4 is reg (0) or mem (1) */
  379. if (idx_value & 0x10) {
  380. r = r600_cs_packet_next_reloc(p, &reloc);
  381. if (r) {
  382. DRM_ERROR("bad WAIT_REG_MEM\n");
  383. return -EINVAL;
  384. }
  385. ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
  386. ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
  387. }
  388. break;
  389. case PACKET3_SURFACE_SYNC:
  390. if (pkt->count != 3) {
  391. DRM_ERROR("bad SURFACE_SYNC\n");
  392. return -EINVAL;
  393. }
  394. /* 0xffffffff/0x0 is flush all cache flag */
  395. if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||
  396. radeon_get_ib_value(p, idx + 2) != 0) {
  397. r = r600_cs_packet_next_reloc(p, &reloc);
  398. if (r) {
  399. DRM_ERROR("bad SURFACE_SYNC\n");
  400. return -EINVAL;
  401. }
  402. ib[idx+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
  403. }
  404. break;
  405. case PACKET3_EVENT_WRITE:
  406. if (pkt->count != 2 && pkt->count != 0) {
  407. DRM_ERROR("bad EVENT_WRITE\n");
  408. return -EINVAL;
  409. }
  410. if (pkt->count) {
  411. r = r600_cs_packet_next_reloc(p, &reloc);
  412. if (r) {
  413. DRM_ERROR("bad EVENT_WRITE\n");
  414. return -EINVAL;
  415. }
  416. ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
  417. ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
  418. }
  419. break;
  420. case PACKET3_EVENT_WRITE_EOP:
  421. if (pkt->count != 4) {
  422. DRM_ERROR("bad EVENT_WRITE_EOP\n");
  423. return -EINVAL;
  424. }
  425. r = r600_cs_packet_next_reloc(p, &reloc);
  426. if (r) {
  427. DRM_ERROR("bad EVENT_WRITE\n");
  428. return -EINVAL;
  429. }
  430. ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff);
  431. ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
  432. break;
  433. case PACKET3_SET_CONFIG_REG:
  434. start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_OFFSET;
  435. end_reg = 4 * pkt->count + start_reg - 4;
  436. if ((start_reg < PACKET3_SET_CONFIG_REG_OFFSET) ||
  437. (start_reg >= PACKET3_SET_CONFIG_REG_END) ||
  438. (end_reg >= PACKET3_SET_CONFIG_REG_END)) {
  439. DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");
  440. return -EINVAL;
  441. }
  442. for (i = 0; i < pkt->count; i++) {
  443. reg = start_reg + (4 * i);
  444. switch (reg) {
  445. case CP_COHER_BASE:
  446. /* use PACKET3_SURFACE_SYNC */
  447. return -EINVAL;
  448. default:
  449. break;
  450. }
  451. }
  452. break;
  453. case PACKET3_SET_CONTEXT_REG:
  454. start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_OFFSET;
  455. end_reg = 4 * pkt->count + start_reg - 4;
  456. if ((start_reg < PACKET3_SET_CONTEXT_REG_OFFSET) ||
  457. (start_reg >= PACKET3_SET_CONTEXT_REG_END) ||
  458. (end_reg >= PACKET3_SET_CONTEXT_REG_END)) {
  459. DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n");
  460. return -EINVAL;
  461. }
  462. for (i = 0; i < pkt->count; i++) {
  463. reg = start_reg + (4 * i);
  464. switch (reg) {
  465. case DB_DEPTH_BASE:
  466. case CB_COLOR0_BASE:
  467. case CB_COLOR1_BASE:
  468. case CB_COLOR2_BASE:
  469. case CB_COLOR3_BASE:
  470. case CB_COLOR4_BASE:
  471. case CB_COLOR5_BASE:
  472. case CB_COLOR6_BASE:
  473. case CB_COLOR7_BASE:
  474. case SQ_PGM_START_FS:
  475. case SQ_PGM_START_ES:
  476. case SQ_PGM_START_VS:
  477. case SQ_PGM_START_GS:
  478. case SQ_PGM_START_PS:
  479. r = r600_cs_packet_next_reloc(p, &reloc);
  480. if (r) {
  481. DRM_ERROR("bad SET_CONTEXT_REG "
  482. "0x%04X\n", reg);
  483. return -EINVAL;
  484. }
  485. ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
  486. break;
  487. case VGT_DMA_BASE:
  488. case VGT_DMA_BASE_HI:
  489. /* These should be handled by DRAW_INDEX packet 3 */
  490. case VGT_STRMOUT_BASE_OFFSET_0:
  491. case VGT_STRMOUT_BASE_OFFSET_1:
  492. case VGT_STRMOUT_BASE_OFFSET_2:
  493. case VGT_STRMOUT_BASE_OFFSET_3:
  494. case VGT_STRMOUT_BASE_OFFSET_HI_0:
  495. case VGT_STRMOUT_BASE_OFFSET_HI_1:
  496. case VGT_STRMOUT_BASE_OFFSET_HI_2:
  497. case VGT_STRMOUT_BASE_OFFSET_HI_3:
  498. case VGT_STRMOUT_BUFFER_BASE_0:
  499. case VGT_STRMOUT_BUFFER_BASE_1:
  500. case VGT_STRMOUT_BUFFER_BASE_2:
  501. case VGT_STRMOUT_BUFFER_BASE_3:
  502. case VGT_STRMOUT_BUFFER_OFFSET_0:
  503. case VGT_STRMOUT_BUFFER_OFFSET_1:
  504. case VGT_STRMOUT_BUFFER_OFFSET_2:
  505. case VGT_STRMOUT_BUFFER_OFFSET_3:
  506. /* These should be handled by STRMOUT_BUFFER packet 3 */
  507. DRM_ERROR("bad context reg: 0x%08x\n", reg);
  508. return -EINVAL;
  509. default:
  510. break;
  511. }
  512. }
  513. break;
  514. case PACKET3_SET_RESOURCE:
  515. if (pkt->count % 7) {
  516. DRM_ERROR("bad SET_RESOURCE\n");
  517. return -EINVAL;
  518. }
  519. start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_OFFSET;
  520. end_reg = 4 * pkt->count + start_reg - 4;
  521. if ((start_reg < PACKET3_SET_RESOURCE_OFFSET) ||
  522. (start_reg >= PACKET3_SET_RESOURCE_END) ||
  523. (end_reg >= PACKET3_SET_RESOURCE_END)) {
  524. DRM_ERROR("bad SET_RESOURCE\n");
  525. return -EINVAL;
  526. }
  527. for (i = 0; i < (pkt->count / 7); i++) {
  528. switch (G__SQ_VTX_CONSTANT_TYPE(radeon_get_ib_value(p, idx+(i*7)+6+1))) {
  529. case SQ_TEX_VTX_VALID_TEXTURE:
  530. /* tex base */
  531. r = r600_cs_packet_next_reloc(p, &reloc);
  532. if (r) {
  533. DRM_ERROR("bad SET_RESOURCE\n");
  534. return -EINVAL;
  535. }
  536. ib[idx+1+(i*7)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
  537. /* tex mip base */
  538. r = r600_cs_packet_next_reloc(p, &reloc);
  539. if (r) {
  540. DRM_ERROR("bad SET_RESOURCE\n");
  541. return -EINVAL;
  542. }
  543. ib[idx+1+(i*7)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
  544. break;
  545. case SQ_TEX_VTX_VALID_BUFFER:
  546. /* vtx base */
  547. r = r600_cs_packet_next_reloc(p, &reloc);
  548. if (r) {
  549. DRM_ERROR("bad SET_RESOURCE\n");
  550. return -EINVAL;
  551. }
  552. ib[idx+1+(i*7)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff);
  553. ib[idx+1+(i*7)+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
  554. break;
  555. case SQ_TEX_VTX_INVALID_TEXTURE:
  556. case SQ_TEX_VTX_INVALID_BUFFER:
  557. default:
  558. DRM_ERROR("bad SET_RESOURCE\n");
  559. return -EINVAL;
  560. }
  561. }
  562. break;
  563. case PACKET3_SET_ALU_CONST:
  564. start_reg = (idx_value << 2) + PACKET3_SET_ALU_CONST_OFFSET;
  565. end_reg = 4 * pkt->count + start_reg - 4;
  566. if ((start_reg < PACKET3_SET_ALU_CONST_OFFSET) ||
  567. (start_reg >= PACKET3_SET_ALU_CONST_END) ||
  568. (end_reg >= PACKET3_SET_ALU_CONST_END)) {
  569. DRM_ERROR("bad SET_ALU_CONST\n");
  570. return -EINVAL;
  571. }
  572. break;
  573. case PACKET3_SET_BOOL_CONST:
  574. start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_OFFSET;
  575. end_reg = 4 * pkt->count + start_reg - 4;
  576. if ((start_reg < PACKET3_SET_BOOL_CONST_OFFSET) ||
  577. (start_reg >= PACKET3_SET_BOOL_CONST_END) ||
  578. (end_reg >= PACKET3_SET_BOOL_CONST_END)) {
  579. DRM_ERROR("bad SET_BOOL_CONST\n");
  580. return -EINVAL;
  581. }
  582. break;
  583. case PACKET3_SET_LOOP_CONST:
  584. start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_OFFSET;
  585. end_reg = 4 * pkt->count + start_reg - 4;
  586. if ((start_reg < PACKET3_SET_LOOP_CONST_OFFSET) ||
  587. (start_reg >= PACKET3_SET_LOOP_CONST_END) ||
  588. (end_reg >= PACKET3_SET_LOOP_CONST_END)) {
  589. DRM_ERROR("bad SET_LOOP_CONST\n");
  590. return -EINVAL;
  591. }
  592. break;
  593. case PACKET3_SET_CTL_CONST:
  594. start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_OFFSET;
  595. end_reg = 4 * pkt->count + start_reg - 4;
  596. if ((start_reg < PACKET3_SET_CTL_CONST_OFFSET) ||
  597. (start_reg >= PACKET3_SET_CTL_CONST_END) ||
  598. (end_reg >= PACKET3_SET_CTL_CONST_END)) {
  599. DRM_ERROR("bad SET_CTL_CONST\n");
  600. return -EINVAL;
  601. }
  602. break;
  603. case PACKET3_SET_SAMPLER:
  604. if (pkt->count % 3) {
  605. DRM_ERROR("bad SET_SAMPLER\n");
  606. return -EINVAL;
  607. }
  608. start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_OFFSET;
  609. end_reg = 4 * pkt->count + start_reg - 4;
  610. if ((start_reg < PACKET3_SET_SAMPLER_OFFSET) ||
  611. (start_reg >= PACKET3_SET_SAMPLER_END) ||
  612. (end_reg >= PACKET3_SET_SAMPLER_END)) {
  613. DRM_ERROR("bad SET_SAMPLER\n");
  614. return -EINVAL;
  615. }
  616. break;
  617. case PACKET3_SURFACE_BASE_UPDATE:
  618. if (p->family >= CHIP_RV770 || p->family == CHIP_R600) {
  619. DRM_ERROR("bad SURFACE_BASE_UPDATE\n");
  620. return -EINVAL;
  621. }
  622. if (pkt->count) {
  623. DRM_ERROR("bad SURFACE_BASE_UPDATE\n");
  624. return -EINVAL;
  625. }
  626. break;
  627. case PACKET3_NOP:
  628. break;
  629. default:
  630. DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode);
  631. return -EINVAL;
  632. }
  633. return 0;
  634. }
  635. int r600_cs_parse(struct radeon_cs_parser *p)
  636. {
  637. struct radeon_cs_packet pkt;
  638. int r;
  639. do {
  640. r = r600_cs_packet_parse(p, &pkt, p->idx);
  641. if (r) {
  642. return r;
  643. }
  644. p->idx += pkt.count + 2;
  645. switch (pkt.type) {
  646. case PACKET_TYPE0:
  647. r = r600_cs_parse_packet0(p, &pkt);
  648. break;
  649. case PACKET_TYPE2:
  650. break;
  651. case PACKET_TYPE3:
  652. r = r600_packet3_check(p, &pkt);
  653. break;
  654. default:
  655. DRM_ERROR("Unknown packet type %d !\n", pkt.type);
  656. return -EINVAL;
  657. }
  658. if (r) {
  659. return r;
  660. }
  661. } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
  662. #if 0
  663. for (r = 0; r < p->ib->length_dw; r++) {
  664. printk(KERN_INFO "%05d 0x%08X\n", r, p->ib->ptr[r]);
  665. mdelay(1);
  666. }
  667. #endif
  668. return 0;
  669. }
  670. static int r600_cs_parser_relocs_legacy(struct radeon_cs_parser *p)
  671. {
  672. if (p->chunk_relocs_idx == -1) {
  673. return 0;
  674. }
  675. p->relocs = kcalloc(1, sizeof(struct radeon_cs_reloc), GFP_KERNEL);
  676. if (p->relocs == NULL) {
  677. return -ENOMEM;
  678. }
  679. return 0;
  680. }
  681. /**
  682. * cs_parser_fini() - clean parser states
  683. * @parser: parser structure holding parsing context.
  684. * @error: error number
  685. *
  686. * If error is set than unvalidate buffer, otherwise just free memory
  687. * used by parsing context.
  688. **/
  689. static void r600_cs_parser_fini(struct radeon_cs_parser *parser, int error)
  690. {
  691. unsigned i;
  692. kfree(parser->relocs);
  693. for (i = 0; i < parser->nchunks; i++) {
  694. kfree(parser->chunks[i].kdata);
  695. kfree(parser->chunks[i].kpage[0]);
  696. kfree(parser->chunks[i].kpage[1]);
  697. }
  698. kfree(parser->chunks);
  699. kfree(parser->chunks_array);
  700. }
  701. int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
  702. unsigned family, u32 *ib, int *l)
  703. {
  704. struct radeon_cs_parser parser;
  705. struct radeon_cs_chunk *ib_chunk;
  706. struct radeon_ib fake_ib;
  707. int r;
  708. /* initialize parser */
  709. memset(&parser, 0, sizeof(struct radeon_cs_parser));
  710. parser.filp = filp;
  711. parser.rdev = NULL;
  712. parser.family = family;
  713. parser.ib = &fake_ib;
  714. fake_ib.ptr = ib;
  715. r = radeon_cs_parser_init(&parser, data);
  716. if (r) {
  717. DRM_ERROR("Failed to initialize parser !\n");
  718. r600_cs_parser_fini(&parser, r);
  719. return r;
  720. }
  721. r = r600_cs_parser_relocs_legacy(&parser);
  722. if (r) {
  723. DRM_ERROR("Failed to parse relocation !\n");
  724. r600_cs_parser_fini(&parser, r);
  725. return r;
  726. }
  727. /* Copy the packet into the IB, the parser will read from the
  728. * input memory (cached) and write to the IB (which can be
  729. * uncached). */
  730. ib_chunk = &parser.chunks[parser.chunk_ib_idx];
  731. parser.ib->length_dw = ib_chunk->length_dw;
  732. *l = parser.ib->length_dw;
  733. r = r600_cs_parse(&parser);
  734. if (r) {
  735. DRM_ERROR("Invalid command stream !\n");
  736. r600_cs_parser_fini(&parser, r);
  737. return r;
  738. }
  739. r = radeon_cs_finish_pages(&parser);
  740. if (r) {
  741. DRM_ERROR("Invalid command stream !\n");
  742. r600_cs_parser_fini(&parser, r);
  743. return r;
  744. }
  745. r600_cs_parser_fini(&parser, r);
  746. return r;
  747. }
  748. void r600_cs_legacy_init(void)
  749. {
  750. r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_nomm;
  751. }