zx.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786
  1. /* $OpenBSD: zx.c,v 1.19 2013/10/20 20:07:31 miod Exp $ */
  2. /* $NetBSD: zx.c,v 1.5 2002/10/02 16:52:46 thorpej Exp $ */
  3. /*
  4. * Copyright (c) 2003, Miodrag Vallat.
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  17. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  20. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  22. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  23. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  24. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  25. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  26. * POSSIBILITY OF SUCH DAMAGE.
  27. *
  28. * Derived from NetBSD syssrc/sys/dev/sbus/zx.c under the following licence
  29. * terms:
  30. *
  31. * Copyright (c) 2002 The NetBSD Foundation, Inc.
  32. * All rights reserved.
  33. *
  34. * This code is derived from software contributed to The NetBSD Foundation
  35. * by Andrew Doran.
  36. *
  37. * Redistribution and use in source and binary forms, with or without
  38. * modification, are permitted provided that the following conditions
  39. * are met:
  40. * 1. Redistributions of source code must retain the above copyright
  41. * notice, this list of conditions and the following disclaimer.
  42. * 2. Redistributions in binary form must reproduce the above copyright
  43. * notice, this list of conditions and the following disclaimer in the
  44. * documentation and/or other materials provided with the distribution.
  45. *
  46. * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  47. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  48. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  49. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
  50. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  51. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  52. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  53. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  54. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  55. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  56. * POSSIBILITY OF SUCH DAMAGE.
  57. */
  58. /*
  59. * Driver for the Sun ZX display adapter. This would be called 'leo', but
  60. * NetBSD/amiga already has a driver by that name. The XFree86 and Linux
  61. * drivers were used as "living documentation" when writing this; thanks
  62. * to the authors.
  63. */
  64. #include <sys/param.h>
  65. #include <sys/systm.h>
  66. #include <sys/device.h>
  67. #include <sys/ioctl.h>
  68. #include <sys/malloc.h>
  69. #include <sys/mman.h>
  70. #include <sys/tty.h>
  71. #include <sys/conf.h>
  72. #include <uvm/uvm_extern.h>
  73. #include <machine/autoconf.h>
  74. #include <machine/bus.h>
  75. #include <machine/cpu.h>
  76. #include <machine/conf.h>
  77. #include <dev/wscons/wsconsio.h>
  78. #include <dev/wscons/wsdisplayvar.h>
  79. #include <dev/rasops/rasops.h>
  80. #include <machine/fbvar.h>
  81. #include <dev/sbus/zxreg.h>
  82. #include <dev/sbus/sbusvar.h>
  83. #define ZX_WID_SHARED_8 0
  84. #define ZX_WID_SHARED_24 1
  85. #define ZX_WID_DBL_8 2
  86. #define ZX_WID_DBL_24 3
  87. /*
  88. * Per-instance data.
  89. */
  90. struct zx_cmap {
  91. u_int8_t cm_red[256];
  92. u_int8_t cm_green[256];
  93. u_int8_t cm_blue[256];
  94. };
  95. struct zx_softc {
  96. struct sunfb sc_sunfb;
  97. bus_space_tag_t sc_bustag;
  98. bus_addr_t sc_paddr;
  99. struct zx_cmap sc_cmap; /* shadow color map for overlay plane */
  100. volatile struct zx_command *sc_zc;
  101. volatile struct zx_cross *sc_zx;
  102. volatile struct zx_draw *sc_zd_ss0;
  103. volatile struct zx_draw_ss1 *sc_zd_ss1;
  104. volatile struct zx_cursor *sc_zcu;
  105. int sc_nscreens;
  106. };
  107. int zx_ioctl(void *, u_long, caddr_t, int, struct proc *);
  108. paddr_t zx_mmap(void *, off_t, int);
  109. void zx_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t);
  110. void zx_reset(struct zx_softc *, u_int);
  111. void zx_burner(void *, u_int, u_int);
  112. struct wsdisplay_accessops zx_accessops = {
  113. .ioctl = zx_ioctl,
  114. .mmap = zx_mmap,
  115. .burn_screen = zx_burner
  116. };
  117. /* Force 32-bit writes. */
  118. #define SETREG(r, v) (*((volatile u_int32_t *)&r) = (v))
  119. #define ZX_STD_ROP (ZX_ROP_NEW | ZX_ATTR_WE_ENABLE | \
  120. ZX_ATTR_OE_ENABLE | ZX_ATTR_FORCE_WID)
  121. #define ZX_BWIDTH 13
  122. #define ZX_WWIDTH 11 /* word width */
  123. #define ZX_COORDS(x, y) ((x) | ((y) << ZX_WWIDTH))
  124. void zx_attach(struct device *, struct device *, void *);
  125. int zx_match(struct device *, void *, void *);
  126. int zx_putcmap(struct zx_softc *);
  127. void zx_copyrect(struct rasops_info *, int, int, int, int, int, int);
  128. int zx_cross_loadwid(struct zx_softc *, u_int, u_int, u_int);
  129. int zx_cross_wait(struct zx_softc *);
  130. void zx_fillrect(struct rasops_info *, int, int, int, int, long, int);
  131. int zx_intr(void *);
  132. void zx_prom(void *);
  133. int zx_putchar(void *, int, int, u_int, long);
  134. int zx_copycols(void *, int, int, int, int);
  135. int zx_erasecols(void *, int, int, int, long);
  136. int zx_copyrows(void *, int, int, int);
  137. int zx_eraserows(void *, int, int, long);
  138. int zx_do_cursor(struct rasops_info *);
  139. struct cfattach zx_ca = {
  140. sizeof(struct zx_softc), zx_match, zx_attach
  141. };
  142. struct cfdriver zx_cd = {
  143. NULL, "zx", DV_DULL
  144. };
  145. int
  146. zx_match(struct device *parent, void *vcf, void *aux)
  147. {
  148. struct sbus_attach_args *sa = aux;
  149. if (strcmp(sa->sa_name, "SUNW,leo") == 0)
  150. return (1);
  151. return (0);
  152. }
  153. void
  154. zx_attach(struct device *parent, struct device *self, void *args)
  155. {
  156. struct zx_softc *sc = (struct zx_softc *)self;
  157. struct sbus_attach_args *sa = args;
  158. struct rasops_info *ri;
  159. bus_space_tag_t bt;
  160. bus_space_handle_t bh;
  161. int node, isconsole = 0;
  162. const char *nam;
  163. bt = sa->sa_bustag;
  164. ri = &sc->sc_sunfb.sf_ro;
  165. node = sa->sa_node;
  166. /*
  167. * Map the various parts of the card.
  168. */
  169. sc->sc_bustag = bt;
  170. sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset);
  171. if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LC_SS0_USR,
  172. sizeof(struct zx_command), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
  173. printf(": couldn't map command registers\n");
  174. return;
  175. }
  176. sc->sc_zc = (struct zx_command *)bus_space_vaddr(bt, bh);
  177. if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS0,
  178. sizeof(struct zx_draw), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
  179. printf(": couldn't map ss0 drawing registers\n");
  180. return;
  181. }
  182. sc->sc_zd_ss0 = (struct zx_draw *)bus_space_vaddr(bt, bh);
  183. if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS1,
  184. sizeof(struct zx_draw_ss1), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
  185. printf(": couldn't map ss1 drawing registers\n");
  186. return;
  187. }
  188. sc->sc_zd_ss1 = (struct zx_draw_ss1 *)bus_space_vaddr(bt, bh);
  189. if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CROSS,
  190. sizeof(struct zx_cross), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
  191. printf(": couldn't map cross registers\n");
  192. return;
  193. }
  194. sc->sc_zx = (struct zx_cross *)bus_space_vaddr(bt, bh);
  195. if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CURSOR,
  196. sizeof(struct zx_cursor), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) {
  197. printf(": couldn't map cursor registers\n");
  198. return;
  199. }
  200. sc->sc_zcu = (struct zx_cursor *)bus_space_vaddr(bt, bh);
  201. nam = getpropstring(node, "model");
  202. if (*nam == '\0')
  203. nam = sa->sa_name;
  204. printf(": %s", nam);
  205. isconsole = node == fbnode;
  206. /*
  207. * The console is using the 8-bit overlay plane, while the prom
  208. * will correctly report 32 bit depth.
  209. * The following is an equivalent for
  210. * fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype);
  211. * forcing the depth value not to be overwritten.
  212. * Furthermore, the linebytes value is in fact 8192 bytes.
  213. */
  214. sc->sc_sunfb.sf_depth = 8;
  215. sc->sc_sunfb.sf_width = getpropint(node, "width", 1152);
  216. sc->sc_sunfb.sf_height = getpropint(node, "height", 900);
  217. sc->sc_sunfb.sf_linebytes = 1 << ZX_BWIDTH;
  218. sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_height << ZX_BWIDTH;
  219. printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
  220. if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_SS0,
  221. round_page(sc->sc_sunfb.sf_fbsize), BUS_SPACE_MAP_LINEAR,
  222. 0, &bh) != 0) {
  223. printf("%s: couldn't map video memory\n", self->dv_xname);
  224. return;
  225. }
  226. ri->ri_bits = bus_space_vaddr(bt, bh);
  227. ri->ri_hw = sc;
  228. fbwscons_init(&sc->sc_sunfb, 0, isconsole);
  229. /*
  230. * Watch out! rasops_init() invoked via fbwscons_init() did not
  231. * compute ri_bits correctly when centering the display, because
  232. * it has been tricked with the low depth value.
  233. * Recompute now.
  234. */
  235. ri->ri_emustride = ri->ri_emuwidth * 4;
  236. ri->ri_delta = ri->ri_stride - ri->ri_emustride;
  237. ri->ri_pelbytes = 4;
  238. ri->ri_xscale = ri->ri_font->fontwidth * 4;
  239. ri->ri_bits = ri->ri_origbits;
  240. ri->ri_bits += (((ri->ri_width * 4) - ri->ri_emustride) >> 1) & ~3;
  241. ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) *
  242. ri->ri_stride;
  243. ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits)
  244. / ri->ri_stride;
  245. ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits)
  246. % ri->ri_stride) / 4);
  247. ri->ri_ops.copyrows = zx_copyrows;
  248. ri->ri_ops.copycols = zx_copycols;
  249. ri->ri_ops.eraserows = zx_eraserows;
  250. ri->ri_ops.erasecols = zx_erasecols;
  251. ri->ri_ops.putchar = zx_putchar;
  252. ri->ri_do_cursor = zx_do_cursor;
  253. if (isconsole) {
  254. /* zx_reset() below will clear screen, so restart at 1st row */
  255. fbwscons_console_init(&sc->sc_sunfb, 0);
  256. }
  257. /* reset cursor & frame buffer controls */
  258. zx_reset(sc, WSDISPLAYIO_MODE_EMUL);
  259. /* enable video */
  260. zx_burner(sc, 1, 0);
  261. fbwscons_attach(&sc->sc_sunfb, &zx_accessops, isconsole);
  262. }
  263. int
  264. zx_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p)
  265. {
  266. struct zx_softc *sc = dev;
  267. struct wsdisplay_fbinfo *wdf;
  268. /*
  269. * Note that, although the emulation (text) mode is running in
  270. * a 8-bit plane, we advertize the frame buffer as the full-blown
  271. * 32-bit beast it is.
  272. */
  273. switch (cmd) {
  274. case WSDISPLAYIO_GTYPE:
  275. *(u_int *)data = WSDISPLAY_TYPE_SUNLEO;
  276. break;
  277. case WSDISPLAYIO_GINFO:
  278. wdf = (struct wsdisplay_fbinfo *)data;
  279. wdf->height = sc->sc_sunfb.sf_height;
  280. wdf->width = sc->sc_sunfb.sf_width;
  281. wdf->depth = 32;
  282. wdf->cmsize = 0;
  283. break;
  284. case WSDISPLAYIO_GETSUPPORTEDDEPTH:
  285. *(u_int *)data = WSDISPLAYIO_DEPTH_24_32;
  286. break;
  287. case WSDISPLAYIO_LINEBYTES:
  288. *(u_int *)data = sc->sc_sunfb.sf_linebytes;
  289. break;
  290. case WSDISPLAYIO_GETCMAP:
  291. case WSDISPLAYIO_PUTCMAP:
  292. break;
  293. case WSDISPLAYIO_SMODE:
  294. zx_reset(sc, *(u_int *)data);
  295. break;
  296. case WSDISPLAYIO_SVIDEO:
  297. case WSDISPLAYIO_GVIDEO:
  298. break;
  299. default:
  300. return (-1);
  301. }
  302. return (0);
  303. }
  304. /*
  305. * Return the address that would map the given device at the given
  306. * offset, allowing for the given protection, or return -1 for error.
  307. */
  308. paddr_t
  309. zx_mmap(void *v, off_t offset, int prot)
  310. {
  311. struct zx_softc *sc = v;
  312. if (offset & PGOFSET)
  313. return (-1);
  314. /* Allow mapping as a dumb framebuffer from offset 0 */
  315. if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) {
  316. return (bus_space_mmap(sc->sc_bustag, sc->sc_paddr,
  317. ZX_OFF_SS0 + offset, prot, BUS_SPACE_MAP_LINEAR));
  318. }
  319. return (-1);
  320. }
  321. void
  322. zx_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b)
  323. {
  324. struct zx_softc *sc = v;
  325. sc->sc_cmap.cm_red[index] = r;
  326. sc->sc_cmap.cm_green[index] = g;
  327. sc->sc_cmap.cm_blue[index] = b;
  328. }
  329. void
  330. zx_reset(struct zx_softc *sc, u_int mode)
  331. {
  332. volatile struct zx_draw *zd;
  333. volatile struct zx_command *zc;
  334. u_int32_t i;
  335. const u_char *color;
  336. u_int8_t *r, *g, *b;
  337. zd = sc->sc_zd_ss0;
  338. zc = sc->sc_zc;
  339. if (mode == WSDISPLAYIO_MODE_EMUL) {
  340. /* Back from X11 to emulation mode, or first reset */
  341. zx_cross_loadwid(sc, ZX_WID_DBL_8, 0, 0x2c0);
  342. zx_cross_loadwid(sc, ZX_WID_DBL_8, 1, 0x30);
  343. zx_cross_loadwid(sc, ZX_WID_DBL_8, 2, 0x20);
  344. zx_cross_loadwid(sc, ZX_WID_DBL_24, 1, 0x30);
  345. i = sc->sc_zd_ss1->zd_misc;
  346. i |= ZX_SS1_MISC_ENABLE;
  347. SETREG(sc->sc_zd_ss1->zd_misc, i);
  348. /*
  349. * XXX
  350. * If zc_fill is not set to that value, there will be black
  351. * bars left in the margins. But then with this value, the
  352. * screen gets cleared. Go figure.
  353. */
  354. SETREG(zd->zd_wid, 0xffffffff);
  355. SETREG(zd->zd_wmask, 0xffff);
  356. SETREG(zd->zd_vclipmin, 0);
  357. SETREG(zd->zd_vclipmax, (sc->sc_sunfb.sf_width - 1) |
  358. ((sc->sc_sunfb.sf_height - 1) << 16));
  359. SETREG(zd->zd_fg, 0);
  360. SETREG(zd->zd_planemask, 0xff000000);
  361. SETREG(zd->zd_rop, ZX_STD_ROP);
  362. SETREG(zd->zd_widclip, 0);
  363. SETREG(zc->zc_extent, ZX_COORDS(sc->sc_sunfb.sf_width - 1,
  364. sc->sc_sunfb.sf_height - 1));
  365. SETREG(zc->zc_addrspace, ZX_ADDRSPC_FONT_OBGR);
  366. SETREG(zc->zc_fill, ZX_COORDS(0, 0) | ZX_EXTENT_DIR_BACKWARDS);
  367. SETREG(zc->zc_fontt, 0);
  368. while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
  369. ;
  370. /*
  371. * Initialize the 8-bit colormap
  372. */
  373. r = sc->sc_cmap.cm_red;
  374. g = sc->sc_cmap.cm_green;
  375. b = sc->sc_cmap.cm_blue;
  376. color = rasops_cmap;
  377. for (i = 0; i < 256; i++) {
  378. *r++ = *color++;
  379. *g++ = *color++;
  380. *b++ = *color++;
  381. }
  382. fbwscons_setcolormap(&sc->sc_sunfb, zx_setcolor);
  383. zx_putcmap(sc);
  384. } else {
  385. /* Starting X11 - switch to 24bit WID */
  386. SETREG(zd->zd_wid, 1);
  387. SETREG(zd->zd_widclip, 0);
  388. SETREG(zd->zd_wmask, 0xffff);
  389. SETREG(zd->zd_planemask, 0x00ffffff);
  390. SETREG(zc->zc_extent, ZX_COORDS(sc->sc_sunfb.sf_width - 1,
  391. sc->sc_sunfb.sf_height - 1));
  392. SETREG(zc->zc_fill, 0);
  393. while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
  394. ;
  395. SETREG(zc->zc_addrspace, ZX_ADDRSPC_OBGR);
  396. SETREG(zd->zd_rop, ZX_ATTR_RGBE_ENABLE |
  397. ZX_ROP_NEW /* | ZX_ATTR_FORCE_WID */);
  398. }
  399. }
  400. int
  401. zx_cross_wait(struct zx_softc *sc)
  402. {
  403. volatile struct zx_cross *zx;
  404. int i;
  405. zx = sc->sc_zx;
  406. for (i = 300000; i != 0; i--) {
  407. if ((zx->zx_csr & ZX_CROSS_CSR_PROGRESS) == 0)
  408. break;
  409. DELAY(1);
  410. }
  411. if (i == 0)
  412. printf("%s: zx_cross_wait: timed out\n",
  413. sc->sc_sunfb.sf_dev.dv_xname);
  414. return (i);
  415. }
  416. int
  417. zx_cross_loadwid(struct zx_softc *sc, u_int type, u_int index, u_int value)
  418. {
  419. volatile struct zx_cross *zx;
  420. u_int tmp;
  421. zx = sc->sc_zx;
  422. SETREG(zx->zx_type, ZX_CROSS_TYPE_WID);
  423. if (!zx_cross_wait(sc))
  424. return (1);
  425. if (type == ZX_WID_DBL_8)
  426. tmp = (index & 0x0f) + 0x40;
  427. else /* ZX_WID_DBL_24 */
  428. tmp = index & 0x3f;
  429. SETREG(zx->zx_type, 0x5800 + tmp);
  430. SETREG(zx->zx_value, value);
  431. SETREG(zx->zx_type, ZX_CROSS_TYPE_WID);
  432. SETREG(zx->zx_csr, ZX_CROSS_CSR_UNK | ZX_CROSS_CSR_UNK2);
  433. return (0);
  434. }
  435. int
  436. zx_putcmap(struct zx_softc *sc)
  437. {
  438. volatile struct zx_cross *zx;
  439. u_int32_t i;
  440. u_int8_t *r, *g, *b;
  441. zx = sc->sc_zx;
  442. SETREG(zx->zx_type, ZX_CROSS_TYPE_CLUT0);
  443. if (!zx_cross_wait(sc))
  444. return (1);
  445. SETREG(zx->zx_type, ZX_CROSS_TYPE_CLUTDATA);
  446. r = sc->sc_cmap.cm_red;
  447. g = sc->sc_cmap.cm_green;
  448. b = sc->sc_cmap.cm_blue;
  449. for (i = 0; i < 256; i++) {
  450. SETREG(zx->zx_value, *r++ | (*g++ << 8) | (*b++ << 16));
  451. }
  452. SETREG(zx->zx_type, ZX_CROSS_TYPE_CLUT0);
  453. i = zx->zx_csr;
  454. i = i | ZX_CROSS_CSR_UNK | ZX_CROSS_CSR_UNK2;
  455. SETREG(zx->zx_csr, i);
  456. return (0);
  457. }
  458. void
  459. zx_burner(void *v, u_int on, u_int flags)
  460. {
  461. struct zx_softc *sc = v;
  462. volatile struct zx_cross *zx;
  463. u_int32_t i;
  464. zx = sc->sc_zx;
  465. SETREG(zx->zx_type, ZX_CROSS_TYPE_VIDEO);
  466. i = zx->zx_csr;
  467. if (on) {
  468. i |= ZX_CROSS_CSR_ENABLE;
  469. } else {
  470. i &= ~ZX_CROSS_CSR_ENABLE;
  471. }
  472. SETREG(zx->zx_csr, i);
  473. }
  474. void
  475. zx_fillrect(struct rasops_info *ri, int x, int y, int w, int h, long attr,
  476. int rop)
  477. {
  478. struct zx_softc *sc;
  479. volatile struct zx_command *zc;
  480. volatile struct zx_draw *zd;
  481. int fg, bg;
  482. sc = ri->ri_hw;
  483. zc = sc->sc_zc;
  484. zd = sc->sc_zd_ss0;
  485. ri->ri_ops.unpack_attr(ri, attr, &fg, &bg, NULL);
  486. x = x * ri->ri_font->fontwidth + ri->ri_xorigin;
  487. y = y * ri->ri_font->fontheight + ri->ri_yorigin;
  488. w = ri->ri_font->fontwidth * w - 1;
  489. h = ri->ri_font->fontheight * h - 1;
  490. while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
  491. ;
  492. SETREG(zd->zd_rop, rop);
  493. SETREG(zd->zd_fg, ri->ri_devcmap[bg] << 24);
  494. SETREG(zc->zc_extent, ZX_COORDS(w, h));
  495. SETREG(zc->zc_fill, ZX_COORDS(x, y) | ZX_EXTENT_DIR_BACKWARDS);
  496. }
  497. void
  498. zx_copyrect(struct rasops_info *ri, int sx, int sy, int dx, int dy, int w,
  499. int h)
  500. {
  501. struct zx_softc *sc;
  502. volatile struct zx_command *zc;
  503. volatile struct zx_draw *zd;
  504. int dir;
  505. sc = ri->ri_hw;
  506. zc = sc->sc_zc;
  507. zd = sc->sc_zd_ss0;
  508. sx = sx * ri->ri_font->fontwidth + ri->ri_xorigin;
  509. sy = sy * ri->ri_font->fontheight + ri->ri_yorigin;
  510. dx = dx * ri->ri_font->fontwidth + ri->ri_xorigin;
  511. dy = dy * ri->ri_font->fontheight + ri->ri_yorigin;
  512. w = w * ri->ri_font->fontwidth - 1;
  513. h = h * ri->ri_font->fontheight - 1;
  514. if (sy < dy || sx < dx) {
  515. dir = ZX_EXTENT_DIR_BACKWARDS;
  516. sx += w;
  517. sy += h;
  518. dx += w;
  519. dy += h;
  520. } else
  521. dir = ZX_EXTENT_DIR_FORWARDS;
  522. while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
  523. ;
  524. SETREG(zd->zd_rop, ZX_STD_ROP);
  525. SETREG(zc->zc_extent, ZX_COORDS(w, h) | dir);
  526. SETREG(zc->zc_src, ZX_COORDS(sx, sy));
  527. SETREG(zc->zc_copy, ZX_COORDS(dx, dy));
  528. }
  529. int
  530. zx_do_cursor(struct rasops_info *ri)
  531. {
  532. zx_fillrect(ri, ri->ri_ccol, ri->ri_crow, 1, 1, WSCOL_BLACK << 16,
  533. ZX_ROP_NEW_XOR_OLD | ZX_ATTR_WE_ENABLE | ZX_ATTR_OE_ENABLE |
  534. ZX_ATTR_FORCE_WID);
  535. return 0;
  536. }
  537. int
  538. zx_erasecols(void *cookie, int row, int col, int num, long attr)
  539. {
  540. struct rasops_info *ri;
  541. ri = (struct rasops_info *)cookie;
  542. zx_fillrect(ri, col, row, num, 1, attr, ZX_STD_ROP);
  543. return 0;
  544. }
  545. int
  546. zx_eraserows(void *cookie, int row, int num, long attr)
  547. {
  548. struct rasops_info *ri;
  549. struct zx_softc *sc;
  550. volatile struct zx_command *zc;
  551. volatile struct zx_draw *zd;
  552. int fg, bg;
  553. ri = (struct rasops_info *)cookie;
  554. if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR)) {
  555. sc = ri->ri_hw;
  556. zc = sc->sc_zc;
  557. zd = sc->sc_zd_ss0;
  558. ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
  559. while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
  560. ;
  561. SETREG(zd->zd_rop, ZX_STD_ROP);
  562. SETREG(zd->zd_fg, ri->ri_devcmap[bg] << 24);
  563. SETREG(zc->zc_extent,
  564. ZX_COORDS(ri->ri_width - 1, ri->ri_height - 1));
  565. SETREG(zc->zc_fill, ZX_COORDS(0, 0) | ZX_EXTENT_DIR_BACKWARDS);
  566. } else
  567. zx_fillrect(ri, 0, row, ri->ri_cols, num, attr, ZX_STD_ROP);
  568. return 0;
  569. }
  570. int
  571. zx_copyrows(void *cookie, int src, int dst, int num)
  572. {
  573. struct rasops_info *ri;
  574. ri = (struct rasops_info *)cookie;
  575. zx_copyrect(ri, 0, src, 0, dst, ri->ri_cols, num);
  576. return 0;
  577. }
  578. int
  579. zx_copycols(void *cookie, int row, int src, int dst, int num)
  580. {
  581. struct rasops_info *ri;
  582. ri = (struct rasops_info *)cookie;
  583. zx_copyrect(ri, src, row, dst, row, num, 1);
  584. return 0;
  585. }
  586. int
  587. zx_putchar(void *cookie, int row, int col, u_int uc, long attr)
  588. {
  589. struct rasops_info *ri;
  590. struct zx_softc *sc;
  591. struct wsdisplay_font *font;
  592. volatile struct zx_command *zc;
  593. volatile struct zx_draw *zd;
  594. volatile u_int32_t *dp;
  595. u_int8_t *fb;
  596. int fs, i, fg, bg, ul;
  597. ri = (struct rasops_info *)cookie;
  598. font = ri->ri_font;
  599. ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, &ul);
  600. fg = ri->ri_devcmap[fg];
  601. bg = ri->ri_devcmap[bg];
  602. dp = (volatile u_int32_t *)ri->ri_bits +
  603. ZX_COORDS(col * font->fontwidth, row * font->fontheight);
  604. if (uc == ' ') {
  605. zx_fillrect(ri, col, row, 1, 1, attr, ZX_STD_ROP);
  606. if (ul == 0)
  607. return 0;
  608. dp += font->fontheight << ZX_WWIDTH;
  609. while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
  610. ;
  611. SETREG(zd->zd_rop, ZX_STD_ROP);
  612. SETREG(zd->zd_fg, fg << 24);
  613. SETREG(zd->zd_bg, bg << 24);
  614. SETREG(zc->zc_fontmsk, 0xffffffff << (32 - font->fontwidth));
  615. } else {
  616. sc = ri->ri_hw;
  617. zc = sc->sc_zc;
  618. zd = sc->sc_zd_ss0;
  619. fb = (u_int8_t *)font->data + (uc - font->firstchar) *
  620. ri->ri_fontscale;
  621. fs = font->stride;
  622. while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0)
  623. ;
  624. SETREG(zd->zd_rop, ZX_STD_ROP);
  625. SETREG(zd->zd_fg, fg << 24);
  626. SETREG(zd->zd_bg, bg << 24);
  627. SETREG(zc->zc_fontmsk, 0xffffffff << (32 - font->fontwidth));
  628. if (font->fontwidth <= 8) {
  629. for (i = font->fontheight; i != 0;
  630. i--, dp += 1 << ZX_WWIDTH) {
  631. *dp = *fb << 24;
  632. fb += fs;
  633. }
  634. } else {
  635. for (i = font->fontheight; i != 0;
  636. i--, dp += 1 << ZX_WWIDTH) {
  637. *dp = *((u_int16_t *)fb) << 16;
  638. fb += fs;
  639. }
  640. }
  641. }
  642. /* underline */
  643. if (ul) {
  644. dp -= 2 << ZX_WWIDTH;
  645. *dp = 0xffffffff;
  646. }
  647. return 0;
  648. }