mgx.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795
  1. /* $OpenBSD: mgx.c,v 1.13 2013/10/20 20:07:31 miod Exp $ */
  2. /*
  3. * Copyright (c) 2003, Miodrag Vallat.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  16. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  17. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  19. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  20. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  23. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  24. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  25. * POSSIBILITY OF SUCH DAMAGE.
  26. *
  27. */
  28. /*
  29. * Driver for the Southland Media Systems (now Quantum 3D) MGX and MGXPlus
  30. * frame buffers.
  31. *
  32. * This board is built of an Alliance Promotion AT24 chip, and a simple
  33. * SBus-PCI glue logic. It also sports an EEPROM to store configuration
  34. * parameters, which can be controlled from SunOS or Solaris with the
  35. * mgxconfig utility.
  36. *
  37. * We currently don't reprogram the video mode at all, so only the resolution
  38. * and depth set by the PROM (or mgxconfig) will be used.
  39. *
  40. * Also, interrupts are not handled.
  41. */
  42. #include <sys/param.h>
  43. #include <sys/systm.h>
  44. #include <sys/buf.h>
  45. #include <sys/device.h>
  46. #include <sys/ioctl.h>
  47. #include <sys/malloc.h>
  48. #include <sys/mman.h>
  49. #include <sys/tty.h>
  50. #include <sys/conf.h>
  51. #include <uvm/uvm_extern.h>
  52. #include <machine/autoconf.h>
  53. #include <machine/pmap.h>
  54. #include <machine/cpu.h>
  55. #include <machine/conf.h>
  56. #include <dev/wscons/wsconsio.h>
  57. #include <dev/wscons/wsdisplayvar.h>
  58. #include <dev/rasops/rasops.h>
  59. #include <machine/fbvar.h>
  60. #include <dev/ic/vgareg.h>
  61. #include <dev/ic/atxxreg.h>
  62. #include <dev/sbus/sbusvar.h>
  63. /*
  64. * MGX PROM register layout
  65. *
  66. * The cards FCode registers 9 regions:
  67. *
  68. * region offset size description
  69. * 0 00000000 00010000 FCode (32KB only)
  70. * 1 00100000 00010000 FCode, repeated
  71. * 2 00200000 00001000 unknown, repeats every 0x100
  72. * with little differences, could be the EEPROM image
  73. * 3 00400000 00001000 PCI configuration space
  74. * 4 00500000 00001000 CRTC
  75. * 5 00600000 00001000 AT24 registers (offset 0xb0000)
  76. * 6 00700000 00010000 unknown
  77. * 7 00800000 00800000 unknown
  78. * 8 01000000 00400000 video memory
  79. */
  80. #define MGX_NREG 9
  81. #define MGX_REG_CRTC 4 /* video control and ramdac */
  82. #define MGX_REG_ATREG 5 /* AT24 registers */
  83. #define MGX_REG_ATREG_OFFSET 0x000b0000
  84. #define MGX_REG_ATREG_SIZE 0x00000400
  85. #define MGX_REG_VRAM8 8 /* 8-bit memory space */
  86. /*
  87. * MGX CRTC access
  88. *
  89. * The CRTC only answers to the following ``port'' locations:
  90. * - a subset of the VGA registers:
  91. * 3c0, 3c1 (ATC)
  92. * 3c4, 3c5 (TS sequencer)
  93. * 3c6-3c9 (DAC)
  94. * 3c2, 3cc (Misc)
  95. * 3ce, 3cf (GDC)
  96. *
  97. * - the CRTC (6845-style) registers:
  98. * 3d4 index register
  99. * 3d5 data register
  100. */
  101. #define VGA_BASE 0x03c0
  102. #define TS_INDEX (VGA_BASE + VGA_TS_INDEX)
  103. #define TS_DATA (VGA_BASE + VGA_TS_DATA)
  104. #define CD_DISABLEVIDEO 0x0020
  105. #define CMAP_WRITE_INDEX (VGA_BASE + 0x08)
  106. #define CMAP_DATA (VGA_BASE + 0x09)
  107. /* per-display variables */
  108. struct mgx_softc {
  109. struct sunfb sc_sunfb; /* common base device */
  110. bus_space_tag_t sc_bustag;
  111. bus_addr_t sc_paddr; /* for mmap() */
  112. u_int8_t sc_cmap[256 * 3]; /* shadow colormap */
  113. vaddr_t sc_vidc; /* ramdac registers */
  114. vaddr_t sc_xreg; /* AT24 registers */
  115. uint32_t sc_dec; /* dec register template */
  116. int sc_nscreens;
  117. };
  118. void mgx_burner(void *, u_int ,u_int);
  119. int mgx_ioctl(void *, u_long, caddr_t, int, struct proc *);
  120. paddr_t mgx_mmap(void *, off_t, int);
  121. struct wsdisplay_accessops mgx_accessops = {
  122. .ioctl = mgx_ioctl,
  123. .mmap = mgx_mmap,
  124. .burn_screen = mgx_burner
  125. };
  126. int mgx_getcmap(u_int8_t *, struct wsdisplay_cmap *);
  127. void mgx_loadcmap(struct mgx_softc *, int, int);
  128. int mgx_putcmap(u_int8_t *, struct wsdisplay_cmap *);
  129. void mgx_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
  130. int mgx_ras_copycols(void *, int, int, int, int);
  131. int mgx_ras_copyrows(void *, int, int, int);
  132. int mgx_ras_do_cursor(struct rasops_info *);
  133. int mgx_ras_erasecols(void *, int, int, int, long int);
  134. int mgx_ras_eraserows(void *, int, int, long int);
  135. void mgx_ras_init(struct mgx_softc *, uint);
  136. uint8_t mgx_read_1(vaddr_t, uint);
  137. uint16_t mgx_read_2(vaddr_t, uint);
  138. void mgx_write_1(vaddr_t, uint, uint8_t);
  139. void mgx_write_4(vaddr_t, uint, uint32_t);
  140. int mgx_wait_engine(struct mgx_softc *);
  141. int mgx_wait_fifo(struct mgx_softc *, uint);
  142. /*
  143. * Attachment Glue
  144. */
  145. int mgxmatch(struct device *, void *, void *);
  146. void mgxattach(struct device *, struct device *, void *);
  147. struct cfattach mgx_ca = {
  148. sizeof(struct mgx_softc), mgxmatch, mgxattach
  149. };
  150. struct cfdriver mgx_cd = {
  151. NULL, "mgx", DV_DULL
  152. };
  153. /*
  154. * Match an MGX or MGX+ card.
  155. */
  156. int
  157. mgxmatch(struct device *parent, void *vcf, void *aux)
  158. {
  159. struct sbus_attach_args *sa = aux;
  160. if (strcmp(sa->sa_name, "SMSI,mgx") != 0 &&
  161. strcmp(sa->sa_name, "mgx") != 0)
  162. return (0);
  163. return (1);
  164. }
  165. /*
  166. * Attach an MGX frame buffer.
  167. * This will keep the frame buffer in the actual PROM mode, and attach
  168. * a wsdisplay child device to itself.
  169. */
  170. void
  171. mgxattach(struct device *parent, struct device *self, void *args)
  172. {
  173. struct mgx_softc *sc = (struct mgx_softc *)self;
  174. struct sbus_attach_args *sa = args;
  175. bus_space_tag_t bt;
  176. bus_space_handle_t bh;
  177. int node, fbsize;
  178. int isconsole;
  179. uint16_t chipid;
  180. bt = sa->sa_bustag;
  181. node = sa->sa_node;
  182. printf(": %s", getpropstring(node, "model"));
  183. isconsole = node == fbnode;
  184. /* Check registers */
  185. if (sa->sa_nreg < MGX_NREG) {
  186. printf("\n%s: expected %d registers, got %d\n",
  187. self->dv_xname, MGX_NREG, sa->sa_nreg);
  188. return;
  189. }
  190. sc->sc_bustag = bt;
  191. if (sbus_bus_map(bt, sa->sa_reg[MGX_REG_CRTC].sbr_slot,
  192. sa->sa_reg[MGX_REG_CRTC].sbr_offset, PAGE_SIZE,
  193. BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
  194. printf("\n%s: couldn't map crtc registers\n", self->dv_xname);
  195. return;
  196. }
  197. sc->sc_vidc = (vaddr_t)bus_space_vaddr(bt, bh);
  198. sc->sc_bustag = bt;
  199. if (sbus_bus_map(bt, sa->sa_reg[MGX_REG_ATREG].sbr_slot,
  200. sa->sa_reg[MGX_REG_ATREG].sbr_offset + MGX_REG_ATREG_OFFSET,
  201. MGX_REG_ATREG_SIZE, BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
  202. printf("\n%s: couldn't map crtc registers\n", self->dv_xname);
  203. /* XXX unmap vidc */
  204. return;
  205. }
  206. sc->sc_xreg = (vaddr_t)bus_space_vaddr(bt, bh);
  207. /*
  208. * Check the chip ID. If it's not an AT24, prefer not to access
  209. * the extended registers at all.
  210. */
  211. chipid = mgx_read_2(sc->sc_xreg, ATR_ID);
  212. if (chipid != ID_AT24) {
  213. sc->sc_xreg = (vaddr_t)0;
  214. }
  215. /* enable video */
  216. mgx_burner(sc, 1, 0);
  217. fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, 0);
  218. /* Sanity check frame buffer memory */
  219. fbsize = getpropint(node, "fb_size", 0);
  220. if (fbsize != 0 && sc->sc_sunfb.sf_fbsize > fbsize) {
  221. printf("\n%s: expected at least %d bytes of vram, but card "
  222. "only provides %d\n",
  223. self->dv_xname, sc->sc_sunfb.sf_fbsize, fbsize);
  224. return;
  225. }
  226. /* Map the frame buffer memory area we're interested in */
  227. sc->sc_paddr = sbus_bus_addr(bt, sa->sa_reg[MGX_REG_VRAM8].sbr_slot,
  228. sa->sa_reg[MGX_REG_VRAM8].sbr_offset);
  229. if (sbus_bus_map(bt, sa->sa_reg[MGX_REG_VRAM8].sbr_slot,
  230. sa->sa_reg[MGX_REG_VRAM8].sbr_offset,
  231. round_page(sc->sc_sunfb.sf_fbsize),
  232. BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
  233. printf("\n%s: couldn't map video memory\n", self->dv_xname);
  234. /* XXX unmap vidc and xreg */
  235. return;
  236. }
  237. sc->sc_sunfb.sf_ro.ri_bits = bus_space_vaddr(bt, bh);
  238. sc->sc_sunfb.sf_ro.ri_hw = sc;
  239. printf(", %dx%d\n",
  240. sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
  241. fbwscons_init(&sc->sc_sunfb, 0, isconsole);
  242. bzero(sc->sc_cmap, sizeof(sc->sc_cmap));
  243. fbwscons_setcolormap(&sc->sc_sunfb, mgx_setcolor);
  244. if (chipid != ID_AT24) {
  245. printf("%s: unexpected engine id %04x\n",
  246. self->dv_xname, chipid);
  247. }
  248. mgx_ras_init(sc, chipid);
  249. if (isconsole)
  250. fbwscons_console_init(&sc->sc_sunfb, -1);
  251. fbwscons_attach(&sc->sc_sunfb, &mgx_accessops, isconsole);
  252. }
  253. /*
  254. * Register Access
  255. *
  256. * On big-endian systems such as the sparc, it is necessary to flip
  257. * the low-order bits of the addresses to reach the right register.
  258. */
  259. uint8_t
  260. mgx_read_1(vaddr_t regs, uint offs)
  261. {
  262. #if _BYTE_ORDER == _LITTLE_ENDIAN
  263. return *(volatile uint8_t *)(regs + offs);
  264. #else
  265. return *(volatile uint8_t *)(regs + (offs ^ 3));
  266. #endif
  267. }
  268. uint16_t
  269. mgx_read_2(vaddr_t regs, uint offs)
  270. {
  271. #if _BYTE_ORDER == _LITTLE_ENDIAN
  272. return *(volatile uint16_t *)(regs + offs);
  273. #else
  274. return *(volatile uint16_t *)(regs + (offs ^ 2));
  275. #endif
  276. }
  277. void
  278. mgx_write_1(vaddr_t regs, uint offs, uint8_t val)
  279. {
  280. #if _BYTE_ORDER == _LITTLE_ENDIAN
  281. *(volatile uint8_t *)(regs + offs) = val;
  282. #else
  283. *(volatile uint8_t *)(regs + (offs ^ 3)) = val;
  284. #endif
  285. }
  286. void
  287. mgx_write_4(vaddr_t regs, uint offs, uint32_t val)
  288. {
  289. *(volatile uint32_t *)(regs + offs) = val;
  290. }
  291. /*
  292. * Wsdisplay Operations
  293. */
  294. int
  295. mgx_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p)
  296. {
  297. struct mgx_softc *sc = dev;
  298. struct wsdisplay_cmap *cm;
  299. struct wsdisplay_fbinfo *wdf;
  300. int error;
  301. switch (cmd) {
  302. case WSDISPLAYIO_GTYPE:
  303. *(u_int *)data = WSDISPLAY_TYPE_MGX;
  304. break;
  305. case WSDISPLAYIO_GINFO:
  306. wdf = (struct wsdisplay_fbinfo *)data;
  307. wdf->height = sc->sc_sunfb.sf_height;
  308. wdf->width = sc->sc_sunfb.sf_width;
  309. wdf->depth = sc->sc_sunfb.sf_depth;
  310. wdf->cmsize = 256;
  311. break;
  312. case WSDISPLAYIO_LINEBYTES:
  313. *(u_int *)data = sc->sc_sunfb.sf_linebytes;
  314. break;
  315. case WSDISPLAYIO_GETCMAP:
  316. cm = (struct wsdisplay_cmap *)data;
  317. error = mgx_getcmap(sc->sc_cmap, cm);
  318. if (error != 0)
  319. return (error);
  320. break;
  321. case WSDISPLAYIO_PUTCMAP:
  322. cm = (struct wsdisplay_cmap *)data;
  323. error = mgx_putcmap(sc->sc_cmap, cm);
  324. if (error != 0)
  325. return (error);
  326. mgx_loadcmap(sc, cm->index, cm->count);
  327. break;
  328. case WSDISPLAYIO_SVIDEO:
  329. case WSDISPLAYIO_GVIDEO:
  330. break;
  331. default:
  332. return (-1);
  333. }
  334. return (0);
  335. }
  336. paddr_t
  337. mgx_mmap(void *v, off_t offset, int prot)
  338. {
  339. struct mgx_softc *sc = v;
  340. if (offset & PGOFSET)
  341. return (-1);
  342. /* Allow mapping as a dumb framebuffer from offset 0 */
  343. if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) {
  344. return (bus_space_mmap(sc->sc_bustag, sc->sc_paddr,
  345. offset, prot, BUS_SPACE_MAP_LINEAR));
  346. }
  347. return (-1);
  348. }
  349. void
  350. mgx_burner(void *v, u_int on, u_int flags)
  351. {
  352. struct mgx_softc *sc = v;
  353. uint mode;
  354. #ifdef notyet
  355. if (sc->sc_xreg != 0) {
  356. mode = mgx_read_1(sc->sc_xreg, ATR_DPMS);
  357. if (on)
  358. CLR(mode, DPMS_HSYNC_DISABLE | DPMS_VSYNC_DISABLE);
  359. else {
  360. SET(mode, DPMS_HSYNC_DISABLE);
  361. #if 0 /* needs ramdac reprogramming on resume */
  362. if (flags & WSDISPLAY_BURN_VBLANK)
  363. SET(mode, DPMS_VSYNC_DISABLE);
  364. #endif
  365. }
  366. mgx_write_1(sc->sc_xreg, ATR_DPMS, mode);
  367. return;
  368. }
  369. #endif
  370. mgx_write_1(sc->sc_vidc, TS_INDEX, 1); /* TS mode register */
  371. mode = mgx_read_1(sc->sc_vidc, TS_DATA);
  372. if (on)
  373. mode &= ~CD_DISABLEVIDEO;
  374. else
  375. mode |= CD_DISABLEVIDEO;
  376. mgx_write_1(sc->sc_vidc, TS_DATA, mode);
  377. }
  378. /*
  379. * Colormap Handling Routines
  380. */
  381. void
  382. mgx_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
  383. {
  384. struct mgx_softc *sc = v;
  385. u_int i = index * 3;
  386. sc->sc_cmap[i++] = r;
  387. sc->sc_cmap[i++] = g;
  388. sc->sc_cmap[i] = b;
  389. mgx_loadcmap(sc, index, 1);
  390. }
  391. void
  392. mgx_loadcmap(struct mgx_softc *sc, int start, int ncolors)
  393. {
  394. u_int8_t *color;
  395. int i;
  396. mgx_write_1(sc->sc_vidc, CMAP_WRITE_INDEX, start);
  397. color = sc->sc_cmap + start * 3;
  398. for (i = ncolors * 3; i != 0; i--)
  399. mgx_write_1(sc->sc_vidc, CMAP_DATA, *color++);
  400. }
  401. int
  402. mgx_getcmap(u_int8_t *cm, struct wsdisplay_cmap *rcm)
  403. {
  404. u_int index = rcm->index, count = rcm->count, i;
  405. int error;
  406. if (index >= 256 || count > 256 - index)
  407. return (EINVAL);
  408. index *= 3;
  409. for (i = 0; i < count; i++) {
  410. if ((error =
  411. copyout(cm + index++, &rcm->red[i], 1)) != 0)
  412. return (error);
  413. if ((error =
  414. copyout(cm + index++, &rcm->green[i], 1)) != 0)
  415. return (error);
  416. if ((error =
  417. copyout(cm + index++, &rcm->blue[i], 1)) != 0)
  418. return (error);
  419. }
  420. return (0);
  421. }
  422. int
  423. mgx_putcmap(u_int8_t *cm, struct wsdisplay_cmap *rcm)
  424. {
  425. u_int index = rcm->index, count = rcm->count, i;
  426. int error;
  427. if (index >= 256 || count > 256 - index)
  428. return (EINVAL);
  429. index *= 3;
  430. for (i = 0; i < count; i++) {
  431. if ((error =
  432. copyin(&rcm->red[i], cm + index++, 1)) != 0)
  433. return (error);
  434. if ((error =
  435. copyin(&rcm->green[i], cm + index++, 1)) != 0)
  436. return (error);
  437. if ((error =
  438. copyin(&rcm->blue[i], cm + index++, 1)) != 0)
  439. return (error);
  440. }
  441. return (0);
  442. }
  443. /*
  444. * Accelerated Text Console Code
  445. *
  446. * The X driver makes sure there are at least as many FIFOs available as
  447. * registers to write. They can thus be considered as write slots.
  448. *
  449. * The code below expects to run on at least an AT24 chip, and does not
  450. * care for the AP6422 which has fewer FIFOs; some operations would need
  451. * to be done in two steps to support this chip.
  452. */
  453. int
  454. mgx_wait_engine(struct mgx_softc *sc)
  455. {
  456. uint i;
  457. uint stat;
  458. for (i = 10000; i != 0; i--) {
  459. stat = mgx_read_1(sc->sc_xreg, ATR_BLT_STATUS);
  460. if (!ISSET(stat, BLT_HOST_BUSY | BLT_ENGINE_BUSY))
  461. break;
  462. }
  463. return i;
  464. }
  465. int
  466. mgx_wait_fifo(struct mgx_softc *sc, uint nfifo)
  467. {
  468. uint i;
  469. uint stat;
  470. for (i = 10000; i != 0; i--) {
  471. stat = (mgx_read_1(sc->sc_xreg, ATR_FIFO_STATUS) & FIFO_MASK) >>
  472. FIFO_SHIFT;
  473. if (stat >= nfifo)
  474. break;
  475. mgx_write_1(sc->sc_xreg, ATR_FIFO_STATUS, 0);
  476. }
  477. return i;
  478. }
  479. void
  480. mgx_ras_init(struct mgx_softc *sc, uint chipid)
  481. {
  482. /*
  483. * Check the chip ID. If it's not a 6424, do not plug the
  484. * accelerated routines.
  485. */
  486. if (chipid != ID_AT24)
  487. return;
  488. /*
  489. * Wait until the chip is completely idle.
  490. */
  491. if (mgx_wait_engine(sc) == 0)
  492. return;
  493. if (mgx_wait_fifo(sc, FIFO_AT24) == 0)
  494. return;
  495. /*
  496. * Compute the invariant bits of the DEC register.
  497. */
  498. switch (sc->sc_sunfb.sf_depth) {
  499. case 8:
  500. sc->sc_dec = DEC_DEPTH_8 << DEC_DEPTH_SHIFT;
  501. break;
  502. case 15:
  503. case 16:
  504. sc->sc_dec = DEC_DEPTH_16 << DEC_DEPTH_SHIFT;
  505. break;
  506. case 32:
  507. sc->sc_dec = DEC_DEPTH_32 << DEC_DEPTH_SHIFT;
  508. break;
  509. default:
  510. return; /* not supported */
  511. }
  512. switch (sc->sc_sunfb.sf_width) {
  513. case 640:
  514. sc->sc_dec |= DEC_WIDTH_640 << DEC_WIDTH_SHIFT;
  515. break;
  516. case 800:
  517. sc->sc_dec |= DEC_WIDTH_800 << DEC_WIDTH_SHIFT;
  518. break;
  519. case 1024:
  520. sc->sc_dec |= DEC_WIDTH_1024 << DEC_WIDTH_SHIFT;
  521. break;
  522. case 1152:
  523. sc->sc_dec |= DEC_WIDTH_1152 << DEC_WIDTH_SHIFT;
  524. break;
  525. case 1280:
  526. sc->sc_dec |= DEC_WIDTH_1280 << DEC_WIDTH_SHIFT;
  527. break;
  528. case 1600:
  529. sc->sc_dec |= DEC_WIDTH_1600 << DEC_WIDTH_SHIFT;
  530. break;
  531. default:
  532. return; /* not supported */
  533. }
  534. sc->sc_sunfb.sf_ro.ri_ops.copycols = mgx_ras_copycols;
  535. sc->sc_sunfb.sf_ro.ri_ops.copyrows = mgx_ras_copyrows;
  536. sc->sc_sunfb.sf_ro.ri_ops.erasecols = mgx_ras_erasecols;
  537. sc->sc_sunfb.sf_ro.ri_ops.eraserows = mgx_ras_eraserows;
  538. sc->sc_sunfb.sf_ro.ri_do_cursor = mgx_ras_do_cursor;
  539. #ifdef notneeded
  540. mgx_write_1(sc->sc_xreg, ATR_CLIP_CONTROL, 1);
  541. mgx_write_4(sc->sc_xreg, ATR_CLIP_LEFTTOP, ATR_DUAL(0, 0));
  542. mgx_write_4(sc->sc_xreg, ATR_CLIP_RIGHTBOTTOM,
  543. ATR_DUAL(sc->sc_sunfb.sf_width - 1, sc->sc_sunfb.sf_depth - 1));
  544. #else
  545. mgx_write_1(sc->sc_xreg, ATR_CLIP_CONTROL, 0);
  546. #endif
  547. mgx_write_1(sc->sc_xreg, ATR_BYTEMASK, 0xff);
  548. }
  549. int
  550. mgx_ras_copycols(void *v, int row, int src, int dst, int n)
  551. {
  552. struct rasops_info *ri = v;
  553. struct mgx_softc *sc = ri->ri_hw;
  554. uint dec = sc->sc_dec;
  555. n *= ri->ri_font->fontwidth;
  556. src *= ri->ri_font->fontwidth;
  557. src += ri->ri_xorigin;
  558. dst *= ri->ri_font->fontwidth;
  559. dst += ri->ri_xorigin;
  560. row *= ri->ri_font->fontheight;
  561. row += ri->ri_yorigin;
  562. dec |= (DEC_COMMAND_BLT << DEC_COMMAND_SHIFT) |
  563. (DEC_START_DIMX << DEC_START_SHIFT);
  564. if (src < dst) {
  565. src += n - 1;
  566. dst += n - 1;
  567. dec |= DEC_DIR_X_REVERSE;
  568. }
  569. mgx_wait_fifo(sc, 5);
  570. mgx_write_1(sc->sc_xreg, ATR_ROP, ROP_SRC);
  571. mgx_write_4(sc->sc_xreg, ATR_DEC, dec);
  572. mgx_write_4(sc->sc_xreg, ATR_SRC_XY, ATR_DUAL(row, src));
  573. mgx_write_4(sc->sc_xreg, ATR_DST_XY, ATR_DUAL(row, dst));
  574. mgx_write_4(sc->sc_xreg, ATR_WH, ATR_DUAL(ri->ri_font->fontheight, n));
  575. mgx_wait_engine(sc);
  576. return 0;
  577. }
  578. int
  579. mgx_ras_copyrows(void *v, int src, int dst, int n)
  580. {
  581. struct rasops_info *ri = v;
  582. struct mgx_softc *sc = ri->ri_hw;
  583. uint dec = sc->sc_dec;
  584. n *= ri->ri_font->fontheight;
  585. src *= ri->ri_font->fontheight;
  586. src += ri->ri_yorigin;
  587. dst *= ri->ri_font->fontheight;
  588. dst += ri->ri_yorigin;
  589. dec |= (DEC_COMMAND_BLT << DEC_COMMAND_SHIFT) |
  590. (DEC_START_DIMX << DEC_START_SHIFT);
  591. if (src < dst) {
  592. src += n - 1;
  593. dst += n - 1;
  594. dec |= DEC_DIR_Y_REVERSE;
  595. }
  596. mgx_wait_fifo(sc, 5);
  597. mgx_write_1(sc->sc_xreg, ATR_ROP, ROP_SRC);
  598. mgx_write_4(sc->sc_xreg, ATR_DEC, dec);
  599. mgx_write_4(sc->sc_xreg, ATR_SRC_XY, ATR_DUAL(src, ri->ri_xorigin));
  600. mgx_write_4(sc->sc_xreg, ATR_DST_XY, ATR_DUAL(dst, ri->ri_xorigin));
  601. mgx_write_4(sc->sc_xreg, ATR_WH, ATR_DUAL(n, ri->ri_emuwidth));
  602. mgx_wait_engine(sc);
  603. return 0;
  604. }
  605. int
  606. mgx_ras_erasecols(void *v, int row, int col, int n, long int attr)
  607. {
  608. struct rasops_info *ri = v;
  609. struct mgx_softc *sc = ri->ri_hw;
  610. int fg, bg;
  611. uint dec = sc->sc_dec;
  612. ri->ri_ops.unpack_attr(v, attr, &fg, &bg, NULL);
  613. bg = ri->ri_devcmap[bg];
  614. n *= ri->ri_font->fontwidth;
  615. col *= ri->ri_font->fontwidth;
  616. col += ri->ri_xorigin;
  617. row *= ri->ri_font->fontheight;
  618. row += ri->ri_yorigin;
  619. dec |= (DEC_COMMAND_RECT << DEC_COMMAND_SHIFT) |
  620. (DEC_START_DIMX << DEC_START_SHIFT);
  621. mgx_wait_fifo(sc, 5);
  622. mgx_write_1(sc->sc_xreg, ATR_ROP, ROP_SRC);
  623. mgx_write_4(sc->sc_xreg, ATR_FG, bg);
  624. mgx_write_4(sc->sc_xreg, ATR_DEC, dec);
  625. mgx_write_4(sc->sc_xreg, ATR_DST_XY, ATR_DUAL(row, col));
  626. mgx_write_4(sc->sc_xreg, ATR_WH, ATR_DUAL(ri->ri_font->fontheight, n));
  627. mgx_wait_engine(sc);
  628. return 0;
  629. }
  630. int
  631. mgx_ras_eraserows(void *v, int row, int n, long int attr)
  632. {
  633. struct rasops_info *ri = v;
  634. struct mgx_softc *sc = ri->ri_hw;
  635. int fg, bg;
  636. uint dec = sc->sc_dec;
  637. ri->ri_ops.unpack_attr(v, attr, &fg, &bg, NULL);
  638. bg = ri->ri_devcmap[bg];
  639. dec |= (DEC_COMMAND_RECT << DEC_COMMAND_SHIFT) |
  640. (DEC_START_DIMX << DEC_START_SHIFT);
  641. mgx_wait_fifo(sc, 5);
  642. mgx_write_1(sc->sc_xreg, ATR_ROP, ROP_SRC);
  643. mgx_write_4(sc->sc_xreg, ATR_FG, bg);
  644. mgx_write_4(sc->sc_xreg, ATR_DEC, dec);
  645. if (n == ri->ri_rows && ISSET(ri->ri_flg, RI_FULLCLEAR)) {
  646. mgx_write_4(sc->sc_xreg, ATR_DST_XY, ATR_DUAL(0, 0));
  647. mgx_write_4(sc->sc_xreg, ATR_WH,
  648. ATR_DUAL(ri->ri_height, ri->ri_width));
  649. } else {
  650. n *= ri->ri_font->fontheight;
  651. row *= ri->ri_font->fontheight;
  652. row += ri->ri_yorigin;
  653. mgx_write_4(sc->sc_xreg, ATR_DST_XY,
  654. ATR_DUAL(row, ri->ri_xorigin));
  655. mgx_write_4(sc->sc_xreg, ATR_WH, ATR_DUAL(n, ri->ri_emuwidth));
  656. }
  657. mgx_wait_engine(sc);
  658. return 0;
  659. }
  660. int
  661. mgx_ras_do_cursor(struct rasops_info *ri)
  662. {
  663. struct mgx_softc *sc = ri->ri_hw;
  664. int row, col;
  665. uint dec = sc->sc_dec;
  666. row = ri->ri_crow * ri->ri_font->fontheight + ri->ri_yorigin;
  667. col = ri->ri_ccol * ri->ri_font->fontwidth + ri->ri_xorigin;
  668. dec |= (DEC_COMMAND_BLT << DEC_COMMAND_SHIFT) |
  669. (DEC_START_DIMX << DEC_START_SHIFT);
  670. mgx_wait_fifo(sc, 5);
  671. mgx_write_1(sc->sc_xreg, ATR_ROP, (uint8_t)~ROP_SRC);
  672. mgx_write_4(sc->sc_xreg, ATR_DEC, dec);
  673. mgx_write_4(sc->sc_xreg, ATR_SRC_XY, ATR_DUAL(row, col));
  674. mgx_write_4(sc->sc_xreg, ATR_DST_XY, ATR_DUAL(row, col));
  675. mgx_write_4(sc->sc_xreg, ATR_WH,
  676. ATR_DUAL(ri->ri_font->fontheight, ri->ri_font->fontwidth));
  677. mgx_wait_engine(sc);
  678. return 0;
  679. }