r600_cs.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  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;
  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 SQ_ESGS_RING_BASE:
  446. case SQ_GSVS_RING_BASE:
  447. case SQ_ESTMP_RING_BASE:
  448. case SQ_GSTMP_RING_BASE:
  449. case SQ_VSTMP_RING_BASE:
  450. case SQ_PSTMP_RING_BASE:
  451. case SQ_FBUF_RING_BASE:
  452. case SQ_REDUC_RING_BASE:
  453. case SX_MEMORY_EXPORT_BASE:
  454. r = r600_cs_packet_next_reloc(p, &reloc);
  455. if (r) {
  456. DRM_ERROR("bad SET_CONFIG_REG "
  457. "0x%04X\n", reg);
  458. return -EINVAL;
  459. }
  460. ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
  461. break;
  462. case CP_COHER_BASE:
  463. /* use PACKET3_SURFACE_SYNC */
  464. return -EINVAL;
  465. default:
  466. break;
  467. }
  468. }
  469. break;
  470. case PACKET3_SET_CONTEXT_REG:
  471. start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_OFFSET;
  472. end_reg = 4 * pkt->count + start_reg - 4;
  473. if ((start_reg < PACKET3_SET_CONTEXT_REG_OFFSET) ||
  474. (start_reg >= PACKET3_SET_CONTEXT_REG_END) ||
  475. (end_reg >= PACKET3_SET_CONTEXT_REG_END)) {
  476. DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n");
  477. return -EINVAL;
  478. }
  479. for (i = 0; i < pkt->count; i++) {
  480. reg = start_reg + (4 * i);
  481. switch (reg) {
  482. case DB_DEPTH_BASE:
  483. case DB_HTILE_DATA_BASE:
  484. case CB_COLOR0_BASE:
  485. case CB_COLOR1_BASE:
  486. case CB_COLOR2_BASE:
  487. case CB_COLOR3_BASE:
  488. case CB_COLOR4_BASE:
  489. case CB_COLOR5_BASE:
  490. case CB_COLOR6_BASE:
  491. case CB_COLOR7_BASE:
  492. case SQ_PGM_START_FS:
  493. case SQ_PGM_START_ES:
  494. case SQ_PGM_START_VS:
  495. case SQ_PGM_START_GS:
  496. case SQ_PGM_START_PS:
  497. r = r600_cs_packet_next_reloc(p, &reloc);
  498. if (r) {
  499. DRM_ERROR("bad SET_CONTEXT_REG "
  500. "0x%04X\n", reg);
  501. return -EINVAL;
  502. }
  503. ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
  504. break;
  505. case VGT_DMA_BASE:
  506. case VGT_DMA_BASE_HI:
  507. /* These should be handled by DRAW_INDEX packet 3 */
  508. case VGT_STRMOUT_BASE_OFFSET_0:
  509. case VGT_STRMOUT_BASE_OFFSET_1:
  510. case VGT_STRMOUT_BASE_OFFSET_2:
  511. case VGT_STRMOUT_BASE_OFFSET_3:
  512. case VGT_STRMOUT_BASE_OFFSET_HI_0:
  513. case VGT_STRMOUT_BASE_OFFSET_HI_1:
  514. case VGT_STRMOUT_BASE_OFFSET_HI_2:
  515. case VGT_STRMOUT_BASE_OFFSET_HI_3:
  516. case VGT_STRMOUT_BUFFER_BASE_0:
  517. case VGT_STRMOUT_BUFFER_BASE_1:
  518. case VGT_STRMOUT_BUFFER_BASE_2:
  519. case VGT_STRMOUT_BUFFER_BASE_3:
  520. case VGT_STRMOUT_BUFFER_OFFSET_0:
  521. case VGT_STRMOUT_BUFFER_OFFSET_1:
  522. case VGT_STRMOUT_BUFFER_OFFSET_2:
  523. case VGT_STRMOUT_BUFFER_OFFSET_3:
  524. /* These should be handled by STRMOUT_BUFFER packet 3 */
  525. DRM_ERROR("bad context reg: 0x%08x\n", reg);
  526. return -EINVAL;
  527. default:
  528. break;
  529. }
  530. }
  531. break;
  532. case PACKET3_SET_RESOURCE:
  533. if (pkt->count % 7) {
  534. DRM_ERROR("bad SET_RESOURCE\n");
  535. return -EINVAL;
  536. }
  537. start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_OFFSET;
  538. end_reg = 4 * pkt->count + start_reg - 4;
  539. if ((start_reg < PACKET3_SET_RESOURCE_OFFSET) ||
  540. (start_reg >= PACKET3_SET_RESOURCE_END) ||
  541. (end_reg >= PACKET3_SET_RESOURCE_END)) {
  542. DRM_ERROR("bad SET_RESOURCE\n");
  543. return -EINVAL;
  544. }
  545. for (i = 0; i < (pkt->count / 7); i++) {
  546. switch (G__SQ_VTX_CONSTANT_TYPE(radeon_get_ib_value(p, idx+(i*7)+6+1))) {
  547. case SQ_TEX_VTX_VALID_TEXTURE:
  548. /* tex base */
  549. r = r600_cs_packet_next_reloc(p, &reloc);
  550. if (r) {
  551. DRM_ERROR("bad SET_RESOURCE\n");
  552. return -EINVAL;
  553. }
  554. ib[idx+1+(i*7)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
  555. /* tex mip base */
  556. r = r600_cs_packet_next_reloc(p, &reloc);
  557. if (r) {
  558. DRM_ERROR("bad SET_RESOURCE\n");
  559. return -EINVAL;
  560. }
  561. ib[idx+1+(i*7)+3] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
  562. break;
  563. case SQ_TEX_VTX_VALID_BUFFER:
  564. /* vtx base */
  565. r = r600_cs_packet_next_reloc(p, &reloc);
  566. if (r) {
  567. DRM_ERROR("bad SET_RESOURCE\n");
  568. return -EINVAL;
  569. }
  570. ib[idx+1+(i*7)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff);
  571. ib[idx+1+(i*7)+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff;
  572. break;
  573. case SQ_TEX_VTX_INVALID_TEXTURE:
  574. case SQ_TEX_VTX_INVALID_BUFFER:
  575. default:
  576. DRM_ERROR("bad SET_RESOURCE\n");
  577. return -EINVAL;
  578. }
  579. }
  580. break;
  581. case PACKET3_SET_ALU_CONST:
  582. start_reg = (idx_value << 2) + PACKET3_SET_ALU_CONST_OFFSET;
  583. end_reg = 4 * pkt->count + start_reg - 4;
  584. if ((start_reg < PACKET3_SET_ALU_CONST_OFFSET) ||
  585. (start_reg >= PACKET3_SET_ALU_CONST_END) ||
  586. (end_reg >= PACKET3_SET_ALU_CONST_END)) {
  587. DRM_ERROR("bad SET_ALU_CONST\n");
  588. return -EINVAL;
  589. }
  590. break;
  591. case PACKET3_SET_BOOL_CONST:
  592. start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_OFFSET;
  593. end_reg = 4 * pkt->count + start_reg - 4;
  594. if ((start_reg < PACKET3_SET_BOOL_CONST_OFFSET) ||
  595. (start_reg >= PACKET3_SET_BOOL_CONST_END) ||
  596. (end_reg >= PACKET3_SET_BOOL_CONST_END)) {
  597. DRM_ERROR("bad SET_BOOL_CONST\n");
  598. return -EINVAL;
  599. }
  600. break;
  601. case PACKET3_SET_LOOP_CONST:
  602. start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_OFFSET;
  603. end_reg = 4 * pkt->count + start_reg - 4;
  604. if ((start_reg < PACKET3_SET_LOOP_CONST_OFFSET) ||
  605. (start_reg >= PACKET3_SET_LOOP_CONST_END) ||
  606. (end_reg >= PACKET3_SET_LOOP_CONST_END)) {
  607. DRM_ERROR("bad SET_LOOP_CONST\n");
  608. return -EINVAL;
  609. }
  610. break;
  611. case PACKET3_SET_CTL_CONST:
  612. start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_OFFSET;
  613. end_reg = 4 * pkt->count + start_reg - 4;
  614. if ((start_reg < PACKET3_SET_CTL_CONST_OFFSET) ||
  615. (start_reg >= PACKET3_SET_CTL_CONST_END) ||
  616. (end_reg >= PACKET3_SET_CTL_CONST_END)) {
  617. DRM_ERROR("bad SET_CTL_CONST\n");
  618. return -EINVAL;
  619. }
  620. break;
  621. case PACKET3_SET_SAMPLER:
  622. if (pkt->count % 3) {
  623. DRM_ERROR("bad SET_SAMPLER\n");
  624. return -EINVAL;
  625. }
  626. start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_OFFSET;
  627. end_reg = 4 * pkt->count + start_reg - 4;
  628. if ((start_reg < PACKET3_SET_SAMPLER_OFFSET) ||
  629. (start_reg >= PACKET3_SET_SAMPLER_END) ||
  630. (end_reg >= PACKET3_SET_SAMPLER_END)) {
  631. DRM_ERROR("bad SET_SAMPLER\n");
  632. return -EINVAL;
  633. }
  634. break;
  635. case PACKET3_SURFACE_BASE_UPDATE:
  636. if (p->family >= CHIP_RV770 || p->family == CHIP_R600) {
  637. DRM_ERROR("bad SURFACE_BASE_UPDATE\n");
  638. return -EINVAL;
  639. }
  640. if (pkt->count) {
  641. DRM_ERROR("bad SURFACE_BASE_UPDATE\n");
  642. return -EINVAL;
  643. }
  644. break;
  645. case PACKET3_NOP:
  646. break;
  647. default:
  648. DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode);
  649. return -EINVAL;
  650. }
  651. return 0;
  652. }
  653. int r600_cs_parse(struct radeon_cs_parser *p)
  654. {
  655. struct radeon_cs_packet pkt;
  656. int r;
  657. do {
  658. r = r600_cs_packet_parse(p, &pkt, p->idx);
  659. if (r) {
  660. return r;
  661. }
  662. p->idx += pkt.count + 2;
  663. switch (pkt.type) {
  664. case PACKET_TYPE0:
  665. r = r600_cs_parse_packet0(p, &pkt);
  666. break;
  667. case PACKET_TYPE2:
  668. break;
  669. case PACKET_TYPE3:
  670. r = r600_packet3_check(p, &pkt);
  671. break;
  672. default:
  673. DRM_ERROR("Unknown packet type %d !\n", pkt.type);
  674. return -EINVAL;
  675. }
  676. if (r) {
  677. return r;
  678. }
  679. } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
  680. #if 0
  681. for (r = 0; r < p->ib->length_dw; r++) {
  682. printk(KERN_INFO "%05d 0x%08X\n", r, p->ib->ptr[r]);
  683. mdelay(1);
  684. }
  685. #endif
  686. return 0;
  687. }
  688. static int r600_cs_parser_relocs_legacy(struct radeon_cs_parser *p)
  689. {
  690. if (p->chunk_relocs_idx == -1) {
  691. return 0;
  692. }
  693. p->relocs = kzalloc(sizeof(struct radeon_cs_reloc), GFP_KERNEL);
  694. if (p->relocs == NULL) {
  695. return -ENOMEM;
  696. }
  697. return 0;
  698. }
  699. /**
  700. * cs_parser_fini() - clean parser states
  701. * @parser: parser structure holding parsing context.
  702. * @error: error number
  703. *
  704. * If error is set than unvalidate buffer, otherwise just free memory
  705. * used by parsing context.
  706. **/
  707. static void r600_cs_parser_fini(struct radeon_cs_parser *parser, int error)
  708. {
  709. unsigned i;
  710. kfree(parser->relocs);
  711. for (i = 0; i < parser->nchunks; i++) {
  712. kfree(parser->chunks[i].kdata);
  713. kfree(parser->chunks[i].kpage[0]);
  714. kfree(parser->chunks[i].kpage[1]);
  715. }
  716. kfree(parser->chunks);
  717. kfree(parser->chunks_array);
  718. }
  719. int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp,
  720. unsigned family, u32 *ib, int *l)
  721. {
  722. struct radeon_cs_parser parser;
  723. struct radeon_cs_chunk *ib_chunk;
  724. struct radeon_ib fake_ib;
  725. int r;
  726. /* initialize parser */
  727. memset(&parser, 0, sizeof(struct radeon_cs_parser));
  728. parser.filp = filp;
  729. parser.rdev = NULL;
  730. parser.family = family;
  731. parser.ib = &fake_ib;
  732. fake_ib.ptr = ib;
  733. r = radeon_cs_parser_init(&parser, data);
  734. if (r) {
  735. DRM_ERROR("Failed to initialize parser !\n");
  736. r600_cs_parser_fini(&parser, r);
  737. return r;
  738. }
  739. r = r600_cs_parser_relocs_legacy(&parser);
  740. if (r) {
  741. DRM_ERROR("Failed to parse relocation !\n");
  742. r600_cs_parser_fini(&parser, r);
  743. return r;
  744. }
  745. /* Copy the packet into the IB, the parser will read from the
  746. * input memory (cached) and write to the IB (which can be
  747. * uncached). */
  748. ib_chunk = &parser.chunks[parser.chunk_ib_idx];
  749. parser.ib->length_dw = ib_chunk->length_dw;
  750. *l = parser.ib->length_dw;
  751. r = r600_cs_parse(&parser);
  752. if (r) {
  753. DRM_ERROR("Invalid command stream !\n");
  754. r600_cs_parser_fini(&parser, r);
  755. return r;
  756. }
  757. r = radeon_cs_finish_pages(&parser);
  758. if (r) {
  759. DRM_ERROR("Invalid command stream !\n");
  760. r600_cs_parser_fini(&parser, r);
  761. return r;
  762. }
  763. r600_cs_parser_fini(&parser, r);
  764. return r;
  765. }
  766. void r600_cs_legacy_init(void)
  767. {
  768. r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_nomm;
  769. }