cfxga.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216
  1. /* $OpenBSD: cfxga.c,v 1.29 2014/12/13 21:05:33 doug Exp $ */
  2. /*
  3. * Copyright (c) 2005, 2006, Matthieu Herrb and Miodrag Vallat
  4. *
  5. * Permission to use, copy, modify, and distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
  10. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
  12. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. /*
  18. * Display driver for the Colorgraphic CompactFlash ``VoyagerVGA'' card.
  19. * based upon the Epson S1D13806 graphics chip.
  20. *
  21. * Our goals are:
  22. * - to provide a somewhat usable emulation mode for extra text display.
  23. * - to let an application (such as an X server) map the controller registers
  24. * in order to do its own display game.
  25. *
  26. * Driving this card is somewhat a challenge since:
  27. * - its video memory is not directly accessible.
  28. * - no operation can make use of DMA.
  29. */
  30. #include <sys/param.h>
  31. #include <sys/kernel.h>
  32. #include <sys/device.h>
  33. #include <sys/systm.h>
  34. #include <sys/malloc.h>
  35. #include <sys/conf.h>
  36. #include <dev/pcmcia/pcmciavar.h>
  37. #include <dev/pcmcia/pcmciareg.h>
  38. #include <dev/wscons/wsconsio.h>
  39. #include <dev/wscons/wsdisplayvar.h>
  40. #include <dev/rasops/rasops.h>
  41. #include <dev/pcmcia/cfxgareg.h>
  42. /*
  43. #define CFXGADEBUG
  44. #define ENABLE_8BIT_MODES
  45. */
  46. #ifdef CFXGADEBUG
  47. #define DPRINTF(arg) printf arg
  48. #else
  49. #define DPRINTF(arg)
  50. #endif
  51. struct cfxga_screen;
  52. #define CFXGA_MODE_640x480x16 0
  53. #define CFXGA_MODE_800x600x16 1
  54. #ifdef ENABLE_8BIT_MODES
  55. #define CFXGA_MODE_640x480x8 2
  56. #define CFXGA_MODE_800x600x8 3
  57. #define CFXGA_NMODES 4
  58. #else
  59. #define CFXGA_NMODES 2
  60. #endif
  61. struct cfxga_softc {
  62. struct device sc_dev;
  63. struct pcmcia_function *sc_pf;
  64. int sc_state;
  65. #define CS_MAPPED 0x0001
  66. #define CS_RESET 0x0002
  67. struct pcmcia_mem_handle sc_pmemh;
  68. int sc_memwin;
  69. bus_addr_t sc_offset;
  70. int sc_mode;
  71. int sc_nscreens;
  72. LIST_HEAD(, cfxga_screen) sc_scr;
  73. struct cfxga_screen *sc_active;
  74. /* wsdisplay glue */
  75. struct wsscreen_descr sc_wsd[CFXGA_NMODES];
  76. struct wsscreen_list sc_wsl;
  77. struct wsscreen_descr *sc_scrlist[CFXGA_NMODES];
  78. struct wsdisplay_emulops sc_ops;
  79. struct device *sc_wsdisplay;
  80. };
  81. int cfxga_match(struct device *, void *, void *);
  82. void cfxga_attach(struct device *, struct device *, void *);
  83. int cfxga_detach(struct device *, int);
  84. int cfxga_activate(struct device *, int);
  85. struct cfattach cfxga_ca = {
  86. sizeof(struct cfxga_softc), cfxga_match, cfxga_attach,
  87. cfxga_detach, cfxga_activate
  88. };
  89. struct cfdriver cfxga_cd = {
  90. NULL, "cfxga", DV_DULL
  91. };
  92. int cfxga_alloc_screen(void *, const struct wsscreen_descr *, void **,
  93. int *, int *, long *);
  94. void cfxga_burner(void *, u_int, u_int);
  95. void cfxga_free_screen(void *, void *);
  96. int cfxga_ioctl(void *, u_long, caddr_t, int, struct proc *);
  97. paddr_t cfxga_mmap(void *, off_t, int);
  98. int cfxga_load_font(void *, void *, struct wsdisplay_font *);
  99. int cfxga_list_font(void *, struct wsdisplay_font *);
  100. int cfxga_show_screen(void *, void *, int, void (*)(void *, int, int),
  101. void *);
  102. struct wsdisplay_accessops cfxga_accessops = {
  103. .ioctl = cfxga_ioctl,
  104. .mmap = cfxga_mmap,
  105. .alloc_screen = cfxga_alloc_screen,
  106. .free_screen = cfxga_free_screen,
  107. .show_screen = cfxga_show_screen,
  108. .load_font = cfxga_load_font,
  109. .list_font = cfxga_list_font,
  110. .burn_screen = cfxga_burner
  111. };
  112. /*
  113. * Per-screen structure
  114. */
  115. struct cfxga_screen {
  116. LIST_ENTRY(cfxga_screen) scr_link;
  117. struct cfxga_softc *scr_sc; /* parent reference */
  118. struct rasops_info scr_ri; /* raster op glue */
  119. struct wsdisplay_charcell *scr_mem; /* backing memory */
  120. };
  121. int cfxga_copycols(void *, int, int, int, int);
  122. int cfxga_copyrows(void *, int, int, int);
  123. int cfxga_do_cursor(struct rasops_info *);
  124. int cfxga_erasecols(void *, int, int, int, long);
  125. int cfxga_eraserows(void *, int, int, long);
  126. int cfxga_putchar(void *, int, int, u_int, long);
  127. int cfxga_install_function(struct pcmcia_function *);
  128. void cfxga_remove_function(struct pcmcia_function *);
  129. int cfxga_expand_char(struct cfxga_screen *, u_int, int, int, long);
  130. int cfxga_repaint_screen(struct cfxga_screen *);
  131. void cfxga_reset_video(struct cfxga_softc *);
  132. void cfxga_reset_and_repaint(struct cfxga_softc *);
  133. int cfxga_solid_fill(struct cfxga_screen *, int, int, int, int, int32_t);
  134. int cfxga_standalone_rop(struct cfxga_screen *, u_int,
  135. int, int, int, int, int, int);
  136. int cfxga_synchronize(struct cfxga_softc *);
  137. u_int cfxga_wait(struct cfxga_softc *, u_int, u_int);
  138. #define cfxga_clear_screen(scr) \
  139. cfxga_solid_fill(scr, 0, 0, scr->scr_ri.ri_width, \
  140. scr->scr_ri.ri_height, scr->scr_ri.ri_devcmap[WSCOL_BLACK])
  141. #define cfxga_read_1(sc, addr) \
  142. bus_space_read_1((sc)->sc_pmemh.memt, (sc)->sc_pmemh.memh, \
  143. (sc)->sc_offset + (addr))
  144. #define cfxga_read_2(sc, addr) \
  145. bus_space_read_2((sc)->sc_pmemh.memt, (sc)->sc_pmemh.memh, \
  146. (sc)->sc_offset + (addr))
  147. #define cfxga_write_1(sc, addr, val) \
  148. bus_space_write_1((sc)->sc_pmemh.memt, (sc)->sc_pmemh.memh, \
  149. (sc)->sc_offset + (addr), (val))
  150. #define cfxga_write_2(sc, addr, val) \
  151. bus_space_write_2((sc)->sc_pmemh.memt, (sc)->sc_pmemh.memh, \
  152. (sc)->sc_offset + (addr), (val))
  153. #define cfxga_stop_memory_blt(sc) \
  154. (void)cfxga_read_2(sc, CFREG_BITBLT_DATA)
  155. const char *cfxga_modenames[CFXGA_NMODES] = {
  156. "640x480x16",
  157. "800x600x16",
  158. #ifdef ENABLE_8BIT_MODES
  159. "640x480x8",
  160. "800x600x8"
  161. #endif
  162. };
  163. /*
  164. * This card is very poorly engineered, specificationwise. It does not
  165. * provide any CIS information, and has no vendor/product numbers as
  166. * well: as such, there is no easy way to differentiate it from any
  167. * other cheapo PCMCIA card.
  168. *
  169. * The best we can do is probe for a chip ID. This is not perfect but better
  170. * than matching blindly. Of course this requires us to play some nasty games
  171. * behind the PCMCIA framework to be able to do this probe, and correctly fail
  172. * if this is not the card we are looking for.
  173. *
  174. * In shorter words: some card designers ought to be shot, as a service
  175. * to the community.
  176. */
  177. /*
  178. * Create the necessary pcmcia function structures to alleviate the lack
  179. * of any CIS information on this device.
  180. * Actually, we hijack the fake function created by the pcmcia framework.
  181. */
  182. int
  183. cfxga_install_function(struct pcmcia_function *pf)
  184. {
  185. struct pcmcia_config_entry *cfe;
  186. /* Get real. */
  187. pf->pf_flags &= ~PFF_FAKE;
  188. /* Tell the pcmcia framework where the CCR is. */
  189. pf->ccr_base = 0x800;
  190. pf->ccr_mask = 0x67;
  191. /* Create a simple cfe. */
  192. cfe = (struct pcmcia_config_entry *)malloc(sizeof *cfe,
  193. M_DEVBUF, M_NOWAIT | M_ZERO);
  194. if (cfe == NULL) {
  195. DPRINTF(("%s: cfe allocation failed\n", __func__));
  196. return (ENOMEM);
  197. }
  198. cfe->number = 42; /* have to put some value... */
  199. cfe->flags = PCMCIA_CFE_IO16;
  200. cfe->iftype = PCMCIA_IFTYPE_MEMORY;
  201. SIMPLEQ_INSERT_TAIL(&pf->cfe_head, cfe, cfe_list);
  202. pcmcia_function_init(pf, cfe);
  203. return (0);
  204. }
  205. /*
  206. * Undo the changes done above.
  207. * Such a function is necessary since we need a full-blown pcmcia world
  208. * set up in order to do the device probe, but if we don't match the card,
  209. * leaving this state will cause trouble during other probes.
  210. */
  211. void
  212. cfxga_remove_function(struct pcmcia_function *pf)
  213. {
  214. struct pcmcia_config_entry *cfe;
  215. /* we are the first and only entry... */
  216. cfe = SIMPLEQ_FIRST(&pf->cfe_head);
  217. SIMPLEQ_REMOVE_HEAD(&pf->cfe_head, cfe_list);
  218. free(cfe, M_DEVBUF, 0);
  219. /* And we're a figment of the kernel's imagination again. */
  220. pf->pf_flags |= PFF_FAKE;
  221. }
  222. int
  223. cfxga_match(struct device *parent, void *match, void *aux)
  224. {
  225. struct pcmcia_attach_args *pa = aux;
  226. struct pcmcia_function *pf = pa->pf;
  227. struct pcmcia_mem_handle h;
  228. int rc;
  229. int win;
  230. bus_addr_t ptr;
  231. u_int8_t id = 0;
  232. if (pa->product != PCMCIA_PRODUCT_INVALID ||
  233. pa->manufacturer != PCMCIA_VENDOR_INVALID)
  234. return (0);
  235. /* Only a card with no CIS will have a fake function... */
  236. if ((pf->pf_flags & PFF_FAKE) == 0)
  237. return (0);
  238. if (cfxga_install_function(pf) != 0)
  239. return (0);
  240. if (pcmcia_function_enable(pf) != 0) {
  241. DPRINTF(("%s: function enable failed\n", __func__));
  242. return (0);
  243. }
  244. rc = pcmcia_mem_alloc(pf, CFXGA_MEM_RANGE, &h);
  245. if (rc != 0)
  246. goto out;
  247. rc = pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, 0, CFXGA_MEM_RANGE,
  248. &h, &ptr, &win);
  249. if (rc != 0)
  250. goto out2;
  251. id = (bus_space_read_1(h.memt, h.memh, ptr + CFREG_REV) &
  252. CR_PRODUCT_MASK) >> CR_PRODUCT_SHIFT;
  253. pcmcia_mem_unmap(pa->pf, win);
  254. out2:
  255. pcmcia_mem_free(pa->pf, &h);
  256. out:
  257. pcmcia_function_disable(pf);
  258. cfxga_remove_function(pf);
  259. /*
  260. * Be sure to return a value greater than com's if we match,
  261. * otherwise it can win due to the way config(8) will order devices...
  262. */
  263. return (id == PRODUCT_S1D13806 ? 10 : 0);
  264. }
  265. int
  266. cfxga_activate(struct device *dev, int act)
  267. {
  268. struct cfxga_softc *sc = (void *)dev;
  269. int rv = 0;
  270. switch (act) {
  271. case DVACT_DEACTIVATE:
  272. pcmcia_function_disable(sc->sc_pf);
  273. break;
  274. default:
  275. rv = config_activate_children(self, act);
  276. break;
  277. }
  278. return (rv);
  279. }
  280. void
  281. cfxga_attach(struct device *parent, struct device *self, void *aux)
  282. {
  283. struct cfxga_softc *sc = (void *)self;
  284. struct pcmcia_attach_args *pa = aux;
  285. struct pcmcia_function *pf = pa->pf;
  286. struct wsemuldisplaydev_attach_args waa;
  287. struct wsscreen_descr *wsd;
  288. u_int i;
  289. LIST_INIT(&sc->sc_scr);
  290. sc->sc_nscreens = 0;
  291. sc->sc_pf = pf;
  292. if (cfxga_install_function(pf) != 0) {
  293. printf(": pcmcia function setup failed\n");
  294. return;
  295. }
  296. if (pcmcia_function_enable(pf)) {
  297. printf(": function enable failed\n");
  298. return;
  299. }
  300. if (pcmcia_mem_alloc(pf, CFXGA_MEM_RANGE, &sc->sc_pmemh) != 0) {
  301. printf(": can't allocate memory space\n");
  302. return;
  303. }
  304. if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, 0, CFXGA_MEM_RANGE,
  305. &sc->sc_pmemh, &sc->sc_offset, &sc->sc_memwin) != 0) {
  306. printf(": can't map frame buffer registers\n");
  307. pcmcia_mem_free(pf, &sc->sc_pmemh);
  308. return;
  309. }
  310. SET(sc->sc_state, CS_MAPPED);
  311. printf("\n");
  312. sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
  313. /*
  314. * We actually defer real initialization to the creation of the
  315. * first wsdisplay screen, since we do not know which mode to pick
  316. * yet.
  317. */
  318. for (wsd = sc->sc_wsd, i = 0; i < CFXGA_NMODES; wsd++, i++) {
  319. strlcpy(wsd->name, cfxga_modenames[i], sizeof(wsd->name));
  320. wsd->textops = &sc->sc_ops;
  321. sc->sc_scrlist[i] = wsd;
  322. }
  323. sc->sc_wsl.nscreens = CFXGA_NMODES;
  324. sc->sc_wsl.screens = (const struct wsscreen_descr **)sc->sc_scrlist;
  325. waa.console = 0;
  326. waa.scrdata = &sc->sc_wsl;
  327. waa.accessops = &cfxga_accessops;
  328. waa.accesscookie = sc;
  329. waa.defaultscreens = 1;
  330. if ((sc->sc_wsdisplay =
  331. config_found(self, &waa, wsemuldisplaydevprint)) == NULL) {
  332. /* otherwise wscons will do this */
  333. if (sc->sc_active != NULL)
  334. cfxga_clear_screen(sc->sc_active);
  335. else
  336. cfxga_burner(sc, 0, 0);
  337. }
  338. }
  339. int
  340. cfxga_detach(struct device *dev, int flags)
  341. {
  342. struct cfxga_softc *sc = (void *)dev;
  343. /*
  344. * Detach all children, and hope wsdisplay detach code is correct...
  345. */
  346. if (sc->sc_wsdisplay != NULL) {
  347. config_detach(sc->sc_wsdisplay, DETACH_FORCE);
  348. /* sc->sc_wsdisplay = NULL; */
  349. }
  350. if (ISSET(sc->sc_state, CS_MAPPED)) {
  351. pcmcia_mem_unmap(sc->sc_pf, sc->sc_memwin);
  352. pcmcia_mem_free(sc->sc_pf, &sc->sc_pmemh);
  353. /* CLR(sc->sc_state, CS_MAPPED); */
  354. }
  355. return (0);
  356. }
  357. /*
  358. * Wscons operations
  359. */
  360. int
  361. cfxga_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
  362. int *curxp, int *curyp, long *attrp)
  363. {
  364. struct cfxga_softc *sc = v;
  365. struct cfxga_screen *scr;
  366. struct rasops_info *ri;
  367. u_int mode, width, height, depth, scrsize;
  368. scr = malloc(sizeof *scr, M_DEVBUF,
  369. (cold ? M_NOWAIT : M_WAITOK) | M_ZERO);
  370. if (scr == NULL)
  371. return (ENOMEM);
  372. mode = type - sc->sc_wsd;
  373. #ifdef DIAGNOSTIC
  374. if (mode >= CFXGA_NMODES)
  375. mode = CFXGA_MODE_640x480x16;
  376. #endif
  377. switch (mode) {
  378. default:
  379. case CFXGA_MODE_640x480x16:
  380. width = 640;
  381. height = 480;
  382. depth = 16;
  383. break;
  384. case CFXGA_MODE_800x600x16:
  385. width = 800;
  386. height = 600;
  387. depth = 16;
  388. break;
  389. #ifdef ENABLE_8BIT_MODES
  390. case CFXGA_MODE_640x480x8:
  391. width = 640;
  392. height = 480;
  393. depth = 8;
  394. break;
  395. case CFXGA_MODE_800x600x8:
  396. width = 800;
  397. height = 600;
  398. depth = 8;
  399. break;
  400. #endif
  401. }
  402. ri = &scr->scr_ri;
  403. ri->ri_hw = (void *)scr;
  404. ri->ri_bits = NULL;
  405. ri->ri_depth = depth;
  406. ri->ri_width = width;
  407. ri->ri_height = height;
  408. ri->ri_stride = width * depth / 8;
  409. ri->ri_flg = 0;
  410. /* swap B and R at 16 bpp */
  411. if (depth == 16) {
  412. ri->ri_rnum = 5;
  413. ri->ri_rpos = 11;
  414. ri->ri_gnum = 6;
  415. ri->ri_gpos = 5;
  416. ri->ri_bnum = 5;
  417. ri->ri_bpos = 0;
  418. }
  419. if (type->nrows == 0) /* first screen creation */
  420. rasops_init(ri, 100, 100);
  421. else
  422. rasops_init(ri, type->nrows, type->ncols);
  423. /*
  424. * Allocate backing store to remember non-visible screen contents in
  425. * emulation mode.
  426. */
  427. scr->scr_mem = mallocarray(ri->ri_rows,
  428. ri->ri_cols * sizeof(struct wsdisplay_charcell), M_DEVBUF,
  429. (cold ? M_NOWAIT : M_WAITOK) | M_ZERO);
  430. if (scr->scr_mem == NULL) {
  431. free(scr, M_DEVBUF, 0);
  432. return (ENOMEM);
  433. }
  434. scrsize = ri->ri_rows * ri->ri_cols * sizeof(struct wsdisplay_charcell);
  435. ri->ri_ops.copycols = cfxga_copycols;
  436. ri->ri_ops.copyrows = cfxga_copyrows;
  437. ri->ri_ops.erasecols = cfxga_erasecols;
  438. ri->ri_ops.eraserows = cfxga_eraserows;
  439. ri->ri_ops.putchar = cfxga_putchar;
  440. ri->ri_do_cursor = cfxga_do_cursor;
  441. /*
  442. * Finish initializing our screen descriptions, now that we know
  443. * the actual console emulation parameters.
  444. */
  445. if (type->nrows == 0) {
  446. struct wsscreen_descr *wsd = (struct wsscreen_descr *)type;
  447. wsd->nrows = ri->ri_rows;
  448. wsd->ncols = ri->ri_cols;
  449. bcopy(&ri->ri_ops, &sc->sc_ops, sizeof(sc->sc_ops));
  450. wsd->fontwidth = ri->ri_font->fontwidth;
  451. wsd->fontheight = ri->ri_font->fontheight;
  452. wsd->capabilities = ri->ri_caps;
  453. }
  454. scr->scr_sc = sc;
  455. LIST_INSERT_HEAD(&sc->sc_scr, scr, scr_link);
  456. sc->sc_nscreens++;
  457. ri->ri_ops.alloc_attr(ri, 0, 0, 0, attrp);
  458. *cookiep = ri;
  459. *curxp = *curyp = 0;
  460. return (0);
  461. }
  462. void
  463. cfxga_burner(void *v, u_int on, u_int flags)
  464. {
  465. struct cfxga_softc *sc = (void *)v;
  466. u_int8_t mode;
  467. mode = cfxga_read_1(sc, CFREG_MODE) & LCD_MODE_SWIVEL_BIT_0;
  468. if (on)
  469. cfxga_write_1(sc, CFREG_MODE, mode | MODE_CRT);
  470. else
  471. cfxga_write_1(sc, CFREG_MODE, mode | MODE_NO_DISPLAY);
  472. }
  473. void
  474. cfxga_free_screen(void *v, void *cookie)
  475. {
  476. struct cfxga_softc *sc = v;
  477. struct rasops_info *ri = cookie;
  478. struct cfxga_screen *scr = ri->ri_hw;
  479. LIST_REMOVE(scr, scr_link);
  480. sc->sc_nscreens--;
  481. if (scr == sc->sc_active) {
  482. sc->sc_active = NULL;
  483. cfxga_burner(sc, 0, 0);
  484. }
  485. free(scr->scr_mem, M_DEVBUF, 0);
  486. free(scr, M_DEVBUF, 0);
  487. }
  488. int
  489. cfxga_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
  490. {
  491. struct cfxga_softc *sc = v;
  492. struct cfxga_screen *scr;
  493. struct wsdisplay_fbinfo *wdf;
  494. int mode;
  495. switch (cmd) {
  496. case WSDISPLAYIO_GTYPE:
  497. *(u_int *)data = WSDISPLAY_TYPE_CFXGA;
  498. break;
  499. case WSDISPLAYIO_GINFO:
  500. wdf = (struct wsdisplay_fbinfo *)data;
  501. scr = sc->sc_active;
  502. if (scr == NULL) {
  503. /* try later...after running wsconscfg to add screens */
  504. wdf->height = wdf->width = wdf->depth = wdf->cmsize = 0;
  505. } else {
  506. wdf->height = scr->scr_ri.ri_height;
  507. wdf->width = scr->scr_ri.ri_width;
  508. wdf->depth = scr->scr_ri.ri_depth;
  509. wdf->cmsize = scr->scr_ri.ri_depth <= 8 ?
  510. (1 << scr->scr_ri.ri_depth) : 0;
  511. }
  512. break;
  513. case WSDISPLAYIO_SMODE:
  514. mode = *(u_int *)data;
  515. if (mode == sc->sc_mode)
  516. break;
  517. switch (mode) {
  518. case WSDISPLAYIO_MODE_EMUL:
  519. cfxga_reset_and_repaint(sc);
  520. break;
  521. case WSDISPLAYIO_MODE_MAPPED:
  522. break;
  523. default:
  524. return (EINVAL);
  525. }
  526. sc->sc_mode = mode;
  527. break;
  528. /* these operations are handled by the wscons code... */
  529. case WSDISPLAYIO_GVIDEO:
  530. case WSDISPLAYIO_SVIDEO:
  531. break;
  532. /* these operations are not supported... */
  533. case WSDISPLAYIO_GETCMAP:
  534. case WSDISPLAYIO_PUTCMAP:
  535. case WSDISPLAYIO_LINEBYTES:
  536. case WSDISPLAYIO_GCURPOS:
  537. case WSDISPLAYIO_SCURPOS:
  538. case WSDISPLAYIO_GCURMAX:
  539. case WSDISPLAYIO_GCURSOR:
  540. case WSDISPLAYIO_SCURSOR:
  541. default:
  542. return (-1);
  543. }
  544. return (0);
  545. }
  546. paddr_t
  547. cfxga_mmap(void *v, off_t off, int prot)
  548. {
  549. return (-1);
  550. }
  551. int
  552. cfxga_show_screen(void *v, void *cookie, int waitok,
  553. void (*cb)(void *, int, int), void *cbarg)
  554. {
  555. struct cfxga_softc *sc = v;
  556. struct rasops_info *ri = cookie;
  557. struct cfxga_screen *scr = ri->ri_hw, *old;
  558. old = sc->sc_active;
  559. if (old == scr)
  560. return (0);
  561. sc->sc_active = scr;
  562. cfxga_reset_and_repaint(sc); /* will turn video on if scr != NULL */
  563. return (0);
  564. }
  565. int
  566. cfxga_load_font(void *v, void *emulcookie, struct wsdisplay_font *font)
  567. {
  568. struct cfxga_softc *sc = v;
  569. struct cfxga_screen *scr = sc->sc_active;
  570. if (scr == NULL)
  571. return ENXIO;
  572. return rasops_load_font(&scr->scr_ri, emulcookie, font);
  573. }
  574. int
  575. cfxga_list_font(void *v, struct wsdisplay_font *font)
  576. {
  577. struct cfxga_softc *sc = v;
  578. struct cfxga_screen *scr = sc->sc_active;
  579. if (scr == NULL)
  580. return ENXIO;
  581. return rasops_list_font(&scr->scr_ri, font);
  582. }
  583. /*
  584. * Real frame buffer operations
  585. */
  586. void
  587. cfxga_reset_video(struct cfxga_softc *sc)
  588. {
  589. struct cfxga_screen *scr = sc->sc_active;
  590. struct rasops_info *ri;
  591. #ifdef ENABLE_8BIT_MODES
  592. const u_int8_t *cmap;
  593. u_int i;
  594. #endif
  595. /*
  596. * Reset controller
  597. */
  598. /* need to write to both REV and MISC at the same time */
  599. cfxga_write_2(sc, CFREG_REV, 0x80 | (CM_REGSEL << 8));
  600. delay(25000); /* maintain reset for a short while */
  601. /* need to write to both REV and MISC at the same time */
  602. cfxga_write_2(sc, CFREG_REV, 0 | (CM_MEMSEL << 8));
  603. delay(25000);
  604. /* stop any pending blt operation */
  605. cfxga_write_2(sc, CFREG_BITBLT_CONTROL, 0);
  606. cfxga_stop_memory_blt(sc);
  607. cfxga_write_1(sc, CFREG_MODE, 0); /* disable all displays */
  608. /*
  609. * Setup common video mode parameters.
  610. */
  611. cfxga_write_2(sc, CFREG_MEMCLK, MEMCLK_SRC_CLK3);
  612. #if 0
  613. cfxga_write_1(sc, CFREG_LCD_PCLK, LCD_PCLK_SRC_CLKI | LCD_PCLK_DIV_1);
  614. cfxga_write_1(sc, CFREG_MPLUG_CLK,
  615. MPLUG_PCLK_SRC_CLKI2 | MPLUG_PCLK_DIV_1);
  616. #endif
  617. cfxga_write_2(sc, CFREG_CRTTV_PCLK, CRT_PCLK_SRC_CLKI | CRT_PCLK_DIV_1);
  618. cfxga_write_2(sc, CFREG_WSTATE, WSTATE_MCLK);
  619. /* MEMCNF and DRAM_RFRSH need to be programmed at the same time */
  620. cfxga_write_2(sc, CFREG_MEMCNF,
  621. MEMCNF_SDRAM_INIT | (DRAM_RFRSH_50MHZ << 8));
  622. delay(250);
  623. cfxga_write_2(sc, CFREG_DRAM_TIMING, DRAM_TIMING_50MHZ);
  624. /*
  625. * Setup mode-dependent parameters.
  626. */
  627. if (scr == NULL)
  628. return;
  629. ri = &scr->scr_ri;
  630. switch (scr->scr_ri.ri_width) {
  631. default:
  632. case 640:
  633. cfxga_write_1(sc, CFREG_CRT_HWIDTH, (640 / 8) - 1);
  634. /* HNDISP and HSTART need to be programmed at the same time */
  635. cfxga_write_2(sc, CFREG_CRT_HNDISP, 23 | (2 << 8));
  636. cfxga_write_1(sc, CFREG_CRT_HPULSE, 4);
  637. cfxga_write_2(sc, CFREG_CRT_VHEIGHT, 480 - 1);
  638. /* VNDISP and VSTART need to be programmed at the same time */
  639. cfxga_write_2(sc, CFREG_CRT_VNDISP, 39 | (8 << 8));
  640. cfxga_write_1(sc, CFREG_CRT_VPULSE, 2);
  641. break;
  642. case 800:
  643. cfxga_write_1(sc, CFREG_CRT_HWIDTH, (800 / 8) - 1);
  644. /* HNDISP and HSTART need to be programmed at the same time */
  645. cfxga_write_2(sc, CFREG_CRT_HNDISP, 27 | (2 << 8));
  646. cfxga_write_1(sc, CFREG_CRT_HPULSE, 4);
  647. cfxga_write_2(sc, CFREG_CRT_VHEIGHT, 600 - 1);
  648. /* VNDISP and VSTART need to be programmed at the same time */
  649. cfxga_write_2(sc, CFREG_CRT_VNDISP, 25 | (8 << 8));
  650. cfxga_write_1(sc, CFREG_CRT_VPULSE, 2);
  651. break;
  652. }
  653. cfxga_write_1(sc, CFREG_CRT_MODE,
  654. ri->ri_depth == 16 ? CRT_MODE_16BPP : CRT_MODE_8BPP);
  655. cfxga_write_2(sc, CFREG_CRT_START_LOW, 0);
  656. cfxga_write_1(sc, CFREG_CRT_START_HIGH, 0);
  657. cfxga_write_2(sc, CFREG_CRT_MEMORY, ri->ri_width * ri->ri_depth / 16);
  658. cfxga_write_1(sc, CFREG_CRT_PANNING, 0);
  659. cfxga_write_1(sc, CFREG_CRT_FIFO_THRESHOLD_HIGH, 0);
  660. cfxga_write_1(sc, CFREG_CRT_FIFO_THRESHOLD_LOW, 0);
  661. cfxga_write_1(sc, CFREG_CRT_CURSOR_CONTROL, CURSOR_INACTIVE);
  662. #ifdef ENABLE_8BIT_MODES
  663. /*
  664. * On 8bpp video modes, program the LUT
  665. */
  666. if (ri->ri_depth == 8) {
  667. #if 0
  668. /* Wait for retrace */
  669. while ((cfxga_read_1(sc, CFREG_CRT_VNDISP) &
  670. CRT_VNDISP_STATUS) == 0)
  671. delay(1);
  672. #endif
  673. cfxga_write_1(sc, CFREG_LUT_MODE, LUT_CRT);
  674. cfxga_write_1(sc, CFREG_LUT_ADDRESS, 0); /* autoincrements */
  675. cmap = rasops_cmap;
  676. for (i = 256 * 3; i != 0; i--)
  677. cfxga_write_1(sc, CFREG_LUT_DATA, *cmap++ & 0xf0);
  678. }
  679. #endif
  680. cfxga_write_1(sc, CFREG_TV_CONTROL,
  681. TV_LUMINANCE_FILTER | TV_SVIDEO_OUTPUT | TV_NTSC_OUTPUT);
  682. cfxga_write_1(sc, CFREG_POWER_CONF, POWERSAVE_MBO);
  683. cfxga_write_1(sc, CFREG_WATCHDOG, 0);
  684. cfxga_write_1(sc, CFREG_MODE, MODE_CRT);
  685. delay(25000);
  686. }
  687. void
  688. cfxga_reset_and_repaint(struct cfxga_softc *sc)
  689. {
  690. cfxga_reset_video(sc);
  691. if (sc->sc_active != NULL)
  692. cfxga_repaint_screen(sc->sc_active);
  693. else
  694. cfxga_burner(sc, 0, 0);
  695. }
  696. /*
  697. * Wait for the blitter to be in a given state.
  698. */
  699. u_int
  700. cfxga_wait(struct cfxga_softc *sc, u_int mask, u_int result)
  701. {
  702. u_int tries;
  703. for (tries = 10000; tries != 0; tries--) {
  704. if ((cfxga_read_1(sc, CFREG_BITBLT_CONTROL) & mask) == result)
  705. break;
  706. delay(10);
  707. }
  708. return (tries);
  709. }
  710. /*
  711. * Wait for all pending blitter operations to be complete.
  712. * Returns non-zero if the blitter got stuck.
  713. */
  714. int
  715. cfxga_synchronize(struct cfxga_softc *sc)
  716. {
  717. /* Wait for previous operations to complete */
  718. if (cfxga_wait(sc, BITBLT_ACTIVE, 0) == 0) {
  719. DPRINTF(("%s: not ready\n", __func__));
  720. if (ISSET(sc->sc_state, CS_RESET))
  721. return (EAGAIN);
  722. else {
  723. DPRINTF(("%s: resetting...\n", sc->sc_dev.dv_xname));
  724. SET(sc->sc_state, CS_RESET);
  725. cfxga_reset_and_repaint(sc);
  726. CLR(sc->sc_state, CS_RESET);
  727. }
  728. }
  729. cfxga_stop_memory_blt(sc);
  730. return (0);
  731. }
  732. /*
  733. * Display a character.
  734. */
  735. int
  736. cfxga_expand_char(struct cfxga_screen *scr, u_int uc, int x, int y, long attr)
  737. {
  738. struct cfxga_softc *sc = scr->scr_sc;
  739. struct rasops_info *ri = &scr->scr_ri;
  740. struct wsdisplay_font *font = ri->ri_font;
  741. u_int pos, sts, fifo_avail, chunk;
  742. u_int8_t *fontbits;
  743. int bg, fg, ul;
  744. u_int i;
  745. int rc;
  746. pos = (y * ri->ri_width + x) * ri->ri_depth / 8;
  747. fontbits = (u_int8_t *)(font->data + (uc - font->firstchar) *
  748. ri->ri_fontscale);
  749. ri->ri_ops.unpack_attr(ri, attr, &fg, &bg, &ul);
  750. /* Wait for previous operations to complete */
  751. if ((rc = cfxga_synchronize(sc)) != 0)
  752. return (rc);
  753. cfxga_write_2(sc, CFREG_COLOR_EXPANSION,
  754. ((font->fontwidth - 1) & 7) | (OP_COLOR_EXPANSION << 8));
  755. cfxga_write_2(sc, CFREG_BITBLT_SRC_LOW, font->fontwidth <= 8 ? 0 : 1);
  756. cfxga_write_2(sc, CFREG_BITBLT_SRC_HIGH, 0);
  757. cfxga_write_2(sc, CFREG_BITBLT_DST_LOW, pos);
  758. cfxga_write_2(sc, CFREG_BITBLT_DST_HIGH, pos >> 16);
  759. cfxga_write_2(sc, CFREG_BITBLT_OFFSET,
  760. ri->ri_width * ri->ri_depth / 16);
  761. cfxga_write_2(sc, CFREG_BITBLT_WIDTH, font->fontwidth - 1);
  762. cfxga_write_2(sc, CFREG_BITBLT_HEIGHT, font->fontheight - 1);
  763. cfxga_write_2(sc, CFREG_BITBLT_FG, ri->ri_devcmap[fg]);
  764. cfxga_write_2(sc, CFREG_BITBLT_BG, ri->ri_devcmap[bg]);
  765. cfxga_write_2(sc, CFREG_BITBLT_CONTROL, BITBLT_ACTIVE |
  766. (ri->ri_depth > 8 ? BITBLT_COLOR_16 : BITBLT_COLOR_8));
  767. if (cfxga_wait(sc, BITBLT_ACTIVE, BITBLT_ACTIVE) == 0)
  768. goto fail; /* unlikely */
  769. fifo_avail = 0;
  770. for (i = font->fontheight; i != 0; i--) {
  771. /*
  772. * Find out how much words we can feed before
  773. * a FIFO check is needed.
  774. */
  775. if (fifo_avail == 0) {
  776. sts = cfxga_read_1(sc, CFREG_BITBLT_CONTROL);
  777. if ((sts & BITBLT_FIFO_NOT_EMPTY) == 0)
  778. fifo_avail = font->fontwidth <= 8 ? 2 : 1;
  779. else if ((sts & BITBLT_FIFO_HALF_FULL) == 0)
  780. fifo_avail = font->fontwidth <= 8 ? 1 : 0;
  781. else {
  782. /*
  783. * Let the cheap breathe for a short while.
  784. * If this is not enough to free some FIFO
  785. * entries, abort the operation.
  786. */
  787. if (cfxga_wait(sc, BITBLT_FIFO_FULL, 0) == 0)
  788. goto fail;
  789. }
  790. }
  791. if (font->fontwidth <= 8) {
  792. chunk = *fontbits;
  793. if (ul && i == 1)
  794. chunk = 0xff;
  795. } else {
  796. chunk = *(u_int16_t *)fontbits;
  797. if (ul && i == 1)
  798. chunk = 0xffff;
  799. }
  800. cfxga_write_2(sc, CFREG_BITBLT_DATA, chunk);
  801. fontbits += font->stride;
  802. fifo_avail--;
  803. }
  804. return (0);
  805. fail:
  806. DPRINTF(("%s: abort\n", __func__));
  807. cfxga_write_2(sc, CFREG_BITBLT_CONTROL, 0);
  808. cfxga_stop_memory_blt(sc);
  809. return (EINTR);
  810. }
  811. /*
  812. * Copy a memory bitmap to the frame buffer.
  813. *
  814. * This is slow - we only use this to repaint the whole frame buffer on
  815. * screen switches.
  816. */
  817. int
  818. cfxga_repaint_screen(struct cfxga_screen *scr)
  819. {
  820. struct wsdisplay_charcell *cell = scr->scr_mem;
  821. struct rasops_info *ri = &scr->scr_ri;
  822. int x, y, cx, cy, lx, ly;
  823. int fg, bg;
  824. int rc;
  825. cfxga_clear_screen(scr);
  826. cx = ri->ri_font->fontwidth;
  827. cy = ri->ri_font->fontheight;
  828. for (ly = 0, y = ri->ri_yorigin; ly < ri->ri_rows; ly++, y += cy) {
  829. for (lx = 0, x = ri->ri_xorigin; lx < ri->ri_cols;
  830. lx++, x += cx) {
  831. if (cell->uc == 0 || cell->uc == ' ') {
  832. ri->ri_ops.unpack_attr(ri, cell->attr,
  833. &fg, &bg, NULL);
  834. rc = cfxga_solid_fill(scr, x, y, cx, cy,
  835. ri->ri_devcmap[bg]);
  836. } else {
  837. rc = cfxga_expand_char(scr, cell->uc,
  838. x, y, cell->attr);
  839. }
  840. cell++;
  841. if (rc != 0)
  842. return (rc);
  843. }
  844. }
  845. return (0);
  846. }
  847. /*
  848. * Perform a solid fill operation.
  849. */
  850. int
  851. cfxga_solid_fill(struct cfxga_screen *scr, int x, int y, int cx, int cy,
  852. int32_t srccolor)
  853. {
  854. struct cfxga_softc *sc = scr->scr_sc;
  855. struct rasops_info *ri = &scr->scr_ri;
  856. u_int pos;
  857. int rc;
  858. pos = (y * ri->ri_width + x) * ri->ri_depth / 8;
  859. /* Wait for previous operations to complete */
  860. if ((rc = cfxga_synchronize(sc)) != 0)
  861. return (rc);
  862. cfxga_write_2(sc, CFREG_BITBLT_ROP, 0 | (OP_SOLID_FILL << 8));
  863. cfxga_write_2(sc, CFREG_BITBLT_SRC_LOW, pos);
  864. cfxga_write_2(sc, CFREG_BITBLT_SRC_HIGH, pos >> 16);
  865. cfxga_write_2(sc, CFREG_BITBLT_DST_LOW, pos);
  866. cfxga_write_2(sc, CFREG_BITBLT_DST_HIGH, pos >> 16);
  867. cfxga_write_2(sc, CFREG_BITBLT_OFFSET,
  868. ri->ri_width * ri->ri_depth / 16);
  869. cfxga_write_2(sc, CFREG_BITBLT_WIDTH, cx - 1);
  870. cfxga_write_2(sc, CFREG_BITBLT_HEIGHT, cy - 1);
  871. cfxga_write_2(sc, CFREG_BITBLT_FG, (u_int16_t)srccolor);
  872. cfxga_write_2(sc, CFREG_BITBLT_CONTROL, BITBLT_ACTIVE |
  873. (ri->ri_depth > 8 ? BITBLT_COLOR_16 : BITBLT_COLOR_8));
  874. return (0);
  875. }
  876. /*
  877. * Perform an internal frame buffer operation.
  878. */
  879. int
  880. cfxga_standalone_rop(struct cfxga_screen *scr, u_int rop, int sx, int sy,
  881. int dx, int dy, int cx, int cy)
  882. {
  883. struct cfxga_softc *sc = scr->scr_sc;
  884. struct rasops_info *ri = &scr->scr_ri;
  885. u_int srcpos, dstpos;
  886. u_int opcode;
  887. int rc;
  888. srcpos = (sy * ri->ri_width + sx) * ri->ri_depth / 8;
  889. dstpos = (dy * ri->ri_width + dx) * ri->ri_depth / 8;
  890. if (dstpos <= srcpos)
  891. opcode = (OP_MOVE_POSITIVE_ROP << 8) | rop;
  892. else
  893. opcode = (OP_MOVE_NEGATIVE_ROP << 8) | rop;
  894. /* Wait for previous operations to complete */
  895. if ((rc = cfxga_synchronize(sc)) != 0)
  896. return (rc);
  897. cfxga_write_2(sc, CFREG_BITBLT_ROP, opcode);
  898. cfxga_write_2(sc, CFREG_BITBLT_SRC_LOW, srcpos);
  899. cfxga_write_2(sc, CFREG_BITBLT_SRC_HIGH, srcpos >> 16);
  900. cfxga_write_2(sc, CFREG_BITBLT_DST_LOW, dstpos);
  901. cfxga_write_2(sc, CFREG_BITBLT_DST_HIGH, dstpos >> 16);
  902. cfxga_write_2(sc, CFREG_BITBLT_OFFSET,
  903. ri->ri_width * ri->ri_depth / 16);
  904. cfxga_write_2(sc, CFREG_BITBLT_WIDTH, cx - 1);
  905. cfxga_write_2(sc, CFREG_BITBLT_HEIGHT, cy - 1);
  906. cfxga_write_2(sc, CFREG_BITBLT_CONTROL, BITBLT_ACTIVE |
  907. (ri->ri_depth > 8 ? BITBLT_COLOR_16 : BITBLT_COLOR_8));
  908. return (0);
  909. }
  910. /*
  911. * Text console raster operations.
  912. *
  913. * We shadow all these operations on a memory copy of the frame buffer.
  914. * Since we are running in emulation mode only, this could be optimized
  915. * by only storing actual character cell values (a la mda).
  916. */
  917. int
  918. cfxga_copycols(void *cookie, int row, int src, int dst, int num)
  919. {
  920. struct rasops_info *ri = cookie;
  921. struct cfxga_screen *scr = ri->ri_hw;
  922. int sx, dx, y, cx, cy;
  923. /* Copy columns in backing store. */
  924. memmove(scr->scr_mem + row * ri->ri_cols + dst,
  925. scr->scr_mem + row * ri->ri_cols + src,
  926. num * sizeof(struct wsdisplay_charcell));
  927. if (scr != scr->scr_sc->sc_active)
  928. return 0;
  929. sx = src * ri->ri_font->fontwidth + ri->ri_xorigin;
  930. dx = dst * ri->ri_font->fontwidth + ri->ri_xorigin;
  931. y = row * ri->ri_font->fontheight + ri->ri_yorigin;
  932. cx = num * ri->ri_font->fontwidth;
  933. cy = ri->ri_font->fontheight;
  934. return cfxga_standalone_rop(scr, ROP_SRC, sx, y, dx, y, cx, cy);
  935. }
  936. int
  937. cfxga_copyrows(void *cookie, int src, int dst, int num)
  938. {
  939. struct rasops_info *ri = cookie;
  940. struct cfxga_screen *scr = ri->ri_hw;
  941. int x, sy, dy, cx, cy;
  942. /* Copy rows in backing store. */
  943. memmove(scr->scr_mem + dst * ri->ri_cols,
  944. scr->scr_mem + src * ri->ri_cols,
  945. num * ri->ri_cols * sizeof(struct wsdisplay_charcell));
  946. if (scr != scr->scr_sc->sc_active)
  947. return 0;
  948. x = ri->ri_xorigin;
  949. sy = src * ri->ri_font->fontheight + ri->ri_yorigin;
  950. dy = dst * ri->ri_font->fontheight + ri->ri_yorigin;
  951. cx = ri->ri_emuwidth;
  952. cy = num * ri->ri_font->fontheight;
  953. return cfxga_standalone_rop(scr, ROP_SRC, x, sy, x, dy, cx, cy);
  954. }
  955. int
  956. cfxga_do_cursor(struct rasops_info *ri)
  957. {
  958. struct cfxga_screen *scr = ri->ri_hw;
  959. int x, y, cx, cy;
  960. if (scr != scr->scr_sc->sc_active)
  961. return 0;
  962. x = ri->ri_ccol * ri->ri_font->fontwidth + ri->ri_xorigin;
  963. y = ri->ri_crow * ri->ri_font->fontheight + ri->ri_yorigin;
  964. cx = ri->ri_font->fontwidth;
  965. cy = ri->ri_font->fontheight;
  966. return cfxga_standalone_rop(scr, ROP_ONES ^ ROP_SRC /* i.e. not SRC */,
  967. x, y, x, y, cx, cy);
  968. }
  969. int
  970. cfxga_erasecols(void *cookie, int row, int col, int num, long attr)
  971. {
  972. struct rasops_info *ri = cookie;
  973. struct cfxga_screen *scr = ri->ri_hw;
  974. int fg, bg;
  975. int x, y, cx, cy;
  976. /* Erase columns in backing store. */
  977. for (x = col; x < col + num; x++) {
  978. scr->scr_mem[row * ri->ri_cols + x].uc = 0;
  979. scr->scr_mem[row * ri->ri_cols + x].attr = attr;
  980. }
  981. if (scr != scr->scr_sc->sc_active)
  982. return 0;
  983. ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
  984. x = col * ri->ri_font->fontwidth + ri->ri_xorigin;
  985. y = row * ri->ri_font->fontheight + ri->ri_yorigin;
  986. cx = num * ri->ri_font->fontwidth;
  987. cy = ri->ri_font->fontheight;
  988. return cfxga_solid_fill(scr, x, y, cx, cy, ri->ri_devcmap[bg]);
  989. }
  990. int
  991. cfxga_eraserows(void *cookie, int row, int num, long attr)
  992. {
  993. struct rasops_info *ri = cookie;
  994. struct cfxga_screen *scr = ri->ri_hw;
  995. int fg, bg;
  996. int x, y, cx, cy;
  997. /* Erase rows in backing store. */
  998. for (x = 0; x < ri->ri_cols; x++) {
  999. scr->scr_mem[row * ri->ri_cols + x].uc = 0;
  1000. scr->scr_mem[row * ri->ri_cols + x].attr = attr;
  1001. }
  1002. for (y = 1; y < num; y++)
  1003. memmove(scr->scr_mem + (row + y) * ri->ri_cols,
  1004. scr->scr_mem + row * ri->ri_cols,
  1005. ri->ri_cols * sizeof(struct wsdisplay_charcell));
  1006. if (scr != scr->scr_sc->sc_active)
  1007. return 0;
  1008. ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
  1009. x = ri->ri_xorigin;
  1010. y = row * ri->ri_font->fontheight + ri->ri_yorigin;
  1011. cx = ri->ri_emuwidth;
  1012. cy = num * ri->ri_font->fontheight;
  1013. return cfxga_solid_fill(scr, x, y, cx, cy, ri->ri_devcmap[bg]);
  1014. }
  1015. int
  1016. cfxga_putchar(void *cookie, int row, int col, u_int uc, long attr)
  1017. {
  1018. struct rasops_info *ri = cookie;
  1019. struct cfxga_screen *scr = ri->ri_hw;
  1020. int x, y;
  1021. scr->scr_mem[row * ri->ri_cols + col].uc = uc;
  1022. scr->scr_mem[row * ri->ri_cols + col].attr = attr;
  1023. if (scr != scr->scr_sc->sc_active)
  1024. return 0;
  1025. x = col * ri->ri_font->fontwidth + ri->ri_xorigin;
  1026. y = row * ri->ri_font->fontheight + ri->ri_yorigin;
  1027. if (uc == ' ') {
  1028. int cx, cy, fg, bg;
  1029. ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
  1030. cx = ri->ri_font->fontwidth;
  1031. cy = ri->ri_font->fontheight;
  1032. return cfxga_solid_fill(scr, x, y, cx, cy, ri->ri_devcmap[bg]);
  1033. } else {
  1034. return cfxga_expand_char(scr, uc, x, y, attr);
  1035. }
  1036. }