1 1.56 thorpej /* $NetBSD: grf_ul.c,v 1.56 2023/12/20 00:40:42 thorpej Exp $ */ 2 1.1 chopps 3 1.26 is /*- 4 1.27 is * Copyright (c) 1995 The NetBSD Foundation, Inc. 5 1.1 chopps * All rights reserved. 6 1.1 chopps * 7 1.26 is * This code is derived from software contributed to The NetBSD Foundation 8 1.26 is * by Ignatios Souvatzis. 9 1.26 is * 10 1.1 chopps * Redistribution and use in source and binary forms, with or without 11 1.1 chopps * modification, are permitted provided that the following conditions 12 1.1 chopps * are met: 13 1.1 chopps * 1. Redistributions of source code must retain the above copyright 14 1.1 chopps * notice, this list of conditions and the following disclaimer. 15 1.1 chopps * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 chopps * notice, this list of conditions and the following disclaimer in the 17 1.1 chopps * documentation and/or other materials provided with the distribution. 18 1.1 chopps * 19 1.26 is * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.26 is * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.26 is * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.26 is * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.26 is * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.26 is * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.26 is * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.26 is * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.26 is * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.26 is * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.26 is * POSSIBILITY OF SUCH DAMAGE. 30 1.1 chopps */ 31 1.26 is 32 1.28 is #include "opt_amigacons.h" 33 1.30 aymeric 34 1.30 aymeric #include <sys/cdefs.h> 35 1.56 thorpej __KERNEL_RCSID(0, "$NetBSD: grf_ul.c,v 1.56 2023/12/20 00:40:42 thorpej Exp $"); 36 1.30 aymeric 37 1.1 chopps #include "grful.h" 38 1.47 phx #include "ite.h" 39 1.1 chopps #if NGRFUL > 0 40 1.1 chopps 41 1.29 aymeric /* Graphics routines for the University of Lowell A2410 board, 42 1.1 chopps using the TMS34010 processor. */ 43 1.1 chopps 44 1.1 chopps #include <sys/param.h> 45 1.3 chopps #include <sys/systm.h> 46 1.1 chopps #include <sys/errno.h> 47 1.1 chopps #include <sys/ioctl.h> 48 1.1 chopps #include <sys/device.h> 49 1.54 riastrad #include <sys/device_impl.h> /* XXX autoconf abuse */ 50 1.1 chopps #include <sys/syslog.h> 51 1.1 chopps 52 1.1 chopps #include <machine/cpu.h> 53 1.1 chopps 54 1.1 chopps #include <amiga/amiga/device.h> 55 1.1 chopps #include <amiga/amiga/isr.h> 56 1.1 chopps #include <amiga/dev/zbusvar.h> 57 1.1 chopps #include <amiga/dev/grfioctl.h> 58 1.1 chopps #include <amiga/dev/grfvar.h> 59 1.1 chopps #include <amiga/dev/grf_ulreg.h> 60 1.6 chopps 61 1.8 jtc extern u_int16_t tmscode[]; 62 1.1 chopps 63 1.29 aymeric int ul_ioctl(struct grf_softc *, u_long, void *, dev_t); 64 1.29 aymeric int ul_getcmap(struct grf_softc *, struct grf_colormap *, dev_t); 65 1.29 aymeric int ul_putcmap(struct grf_softc *, struct grf_colormap *, dev_t); 66 1.29 aymeric int ul_bitblt(struct grf_softc *, struct grf_bitblt *, dev_t); 67 1.29 aymeric int ul_blank(struct grf_softc *, int *, dev_t); 68 1.29 aymeric 69 1.29 aymeric static int ulisr(void *); 70 1.29 aymeric int ulowell_alive(struct grfvideo_mode *); 71 1.29 aymeric static void ul_load_code(struct grf_softc *); 72 1.29 aymeric static int ul_load_mon(struct grf_softc *, struct grfvideo_mode *); 73 1.29 aymeric static int ul_getvmode(struct grf_softc *, struct grfvideo_mode *); 74 1.29 aymeric static int ul_setvmode(struct grf_softc *, unsigned); 75 1.39 perry static inline void ul_setfb(struct grf_softc *, u_long); 76 1.15 veego 77 1.1 chopps /* 78 1.29 aymeric * marked true early so that ulowell_cnprobe() can tell if we are alive. 79 1.1 chopps */ 80 1.1 chopps int ulowell_inited; 81 1.1 chopps 82 1.1 chopps /* standard-palette definition */ 83 1.1 chopps u_int8_t ul_std_palette[] = { 84 1.1 chopps 0,128, 0,128, 0,128, 0,128, 0,255, 0,255, 0,255, 0,255, 85 1.1 chopps 0, 0,128,128, 0, 0,128,128, 0, 0,255,255, 0, 0,255,255, 86 1.1 chopps 0, 0, 0, 0, 128,128,128,128, 0, 0, 0, 0, 255,255,255,255}; 87 1.1 chopps 88 1.1 chopps u_int8_t ul_ovl_palette[] = { 89 1.1 chopps 128, 0, 0, 0, 90 1.29 aymeric 128, 0, 0, 0, 91 1.1 chopps 128, 0, 0, 0}; 92 1.1 chopps 93 1.2 chopps struct grfvideo_mode ul_monitor_defs[] = { 94 1.1 chopps 95 1.1 chopps /* 96 1.24 veego * We give all these values in MI units, that is: 97 1.24 veego * horizontal timings in units of pixels 98 1.24 veego * vertical timings in units of lines 99 1.24 veego * point of reference is blanking end. 100 1.1 chopps * 101 1.24 veego * The ul_load_mon transforms these values right before loading 102 1.24 veego * them into the chip. 103 1.1 chopps * 104 1.24 veego * This leaves us with a single point where things are transformed, 105 1.24 veego * which should make life easier if we ever change things again. 106 1.1 chopps */ 107 1.1 chopps 108 1.1 chopps /* 1024x768, 60Hz */ 109 1.24 veego {1,"1024x768", 66667000, 1024,768,8, 1024,1088,1296,1392, 110 1.24 veego 768,771,774,798, 0}, 111 1.1 chopps /* 864x648, 70Hz */ 112 1.24 veego {2,"864x648", 50000000, 864,648,8, 864,928,992,1056, 113 1.24 veego 648,658,663,678, 0}, 114 1.1 chopps /* 800x600, 60Hz */ 115 1.24 veego {3, "800x600", 36000000, 800,600,8, 800,864,928,992, 116 1.24 veego 600,610,615,630, 0}, 117 1.1 chopps /* 640x400, 60 Hz, interlaced */ 118 1.24 veego {4, "640x400i", 14318000, 640,400,8, 640,768,832,912, 119 1.24 veego 200,223,203,240, 1}, 120 1.1 chopps /* 1024x768, 65Hz interlaced, s.th. is strange */ 121 1.24 veego {5, "1024x768?i", 44980000, 1024,768,8, 1024,1072,1136,1280, 122 1.24 veego 488,509,512,534, 1}, 123 1.1 chopps /* 1024x1024, 60Hz */ 124 1.24 veego {6, "1024x1024", 80000000, 1024,1024,8, 1024,1040,1120,1248, 125 1.24 veego 1024,1027,1030,1055, 0}, 126 1.1 chopps /* 736x480, 60 Hz */ 127 1.24 veego {7, "736x480", 28636300, 736,480,8, 736,784,848,928, 128 1.24 veego 480,491,495,515, 0}, 129 1.1 chopps }; 130 1.1 chopps 131 1.2 chopps int ulowell_mon_max = sizeof (ul_monitor_defs)/sizeof (ul_monitor_defs[0]); 132 1.1 chopps 133 1.1 chopps /* option settable */ 134 1.1 chopps #ifndef ULOWELL_OSC1 135 1.1 chopps #define ULOWELL_OSC1 36000000 136 1.1 chopps #endif 137 1.1 chopps 138 1.1 chopps #ifndef ULOWELL_OSC2 139 1.1 chopps #define ULOWELL_OSC2 66667000 140 1.1 chopps #endif 141 1.1 chopps 142 1.1 chopps #ifndef ULOWELL_DEFAULT_MON 143 1.1 chopps #define ULOWELL_DEFAULT_MON 1 144 1.1 chopps #endif 145 1.1 chopps 146 1.1 chopps /* patchable */ 147 1.1 chopps int ulowell_default_mon = ULOWELL_DEFAULT_MON; 148 1.1 chopps int ulowell_default_gfx = ULOWELL_DEFAULT_MON; 149 1.1 chopps 150 1.29 aymeric /* 151 1.1 chopps * yes, this should be per board. We don't pay service to multiple boards, 152 1.1 chopps * anyway. 153 1.1 chopps */ 154 1.1 chopps 155 1.4 chopps u_long ulowell_clock[2] = { ULOWELL_OSC2, ULOWELL_OSC1 }; 156 1.29 aymeric 157 1.1 chopps static struct grfvideo_mode *current_mon; 158 1.1 chopps 159 1.1 chopps /* 160 1.1 chopps * We dont use ints at the moment, but will need this later to avoid 161 1.1 chopps * busy_waiting in gsp_write, and we use it for spurious int warnings. 162 1.1 chopps */ 163 1.1 chopps 164 1.29 aymeric static int 165 1.43 dsl ulisr(void *arg) 166 1.1 chopps { 167 1.15 veego struct grf_softc *gp = arg; 168 1.41 he volatile struct gspregs *ba; 169 1.1 chopps u_int16_t thebits; 170 1.1 chopps 171 1.1 chopps if (gp == NULL) 172 1.1 chopps return 0; 173 1.1 chopps 174 1.41 he ba = (volatile struct gspregs *)gp->g_regkva; 175 1.1 chopps 176 1.1 chopps if (ba == NULL) 177 1.1 chopps return 0; 178 1.1 chopps 179 1.1 chopps thebits = ba->ctrl; 180 1.1 chopps if (thebits & INTOUT) { 181 1.1 chopps log(LOG_INFO, "grf4: got interrupt, ctrl=0x%4x\n", thebits); 182 1.1 chopps /* clear int */ 183 1.1 chopps ba->ctrl = thebits & ~INTOUT; 184 1.1 chopps return 1; 185 1.29 aymeric } 186 1.1 chopps return 0; 187 1.1 chopps } 188 1.1 chopps 189 1.1 chopps /* 190 1.1 chopps * used to query the ulowell board to see if its alive. 191 1.1 chopps * for the moment, a NOP. 192 1.1 chopps */ 193 1.1 chopps int 194 1.43 dsl ulowell_alive(struct grfvideo_mode *mdp) 195 1.1 chopps { 196 1.1 chopps return 1; 197 1.1 chopps } 198 1.1 chopps 199 1.1 chopps /* 200 1.1 chopps * Load the (mostly) ite support code and the default colormaps. 201 1.1 chopps */ 202 1.1 chopps static void 203 1.43 dsl ul_load_code(struct grf_softc *gp) 204 1.1 chopps { 205 1.1 chopps struct grf_ul_softc *gup; 206 1.41 he volatile struct gspregs *ba; 207 1.1 chopps struct grfinfo *gi; 208 1.15 veego int i,j; 209 1.15 veego #if 0 210 1.1 chopps struct grf_colormap gcm; 211 1.15 veego #endif 212 1.1 chopps 213 1.1 chopps gup = (struct grf_ul_softc *)gp; 214 1.41 he ba = (volatile struct gspregs *)gp->g_regkva; 215 1.1 chopps gi = &gp->g_display; 216 1.1 chopps 217 1.41 he gi->gd_regaddr = ztwopa((volatile void *)ba); 218 1.1 chopps gi->gd_regsize = sizeof(struct gspregs); 219 1.1 chopps gi->gd_fbaddr = NULL; 220 1.1 chopps gi->gd_fbsize = 0; 221 1.1 chopps gi->gd_fbwidth = 1024; 222 1.1 chopps gi->gd_fbheight = 1024; 223 1.1 chopps gi->gd_colors = 256; 224 1.1 chopps 225 1.15 veego ba->ctrl = (ba->ctrl & ~INCR) | (LBL | INCW); 226 1.1 chopps ba->hstadrh = 0xC000; 227 1.1 chopps ba->hstadrl = 0x0080; 228 1.1 chopps ba->data = 0x0; /* disable screen refresh and video output */ 229 1.1 chopps ba->data = 0xFFFC; /* screen refresh base address */ 230 1.1 chopps ba->data = 0xFFFF; /* no display int possible */ 231 1.1 chopps ba->data = 0x000C; /* CAS before RAS refresh each 64 local clks */ 232 1.1 chopps 233 1.5 chopps ba->ctrl = (ba->ctrl & ~INCW) | LBL; 234 1.1 chopps ba->hstadrh = 0xfe80; 235 1.1 chopps ba->hstadrl = 0; 236 1.1 chopps ba->data = 4; 237 1.1 chopps ba->hstadrl = 0x20; 238 1.1 chopps ba->data = 0xFF; /* all color planes visible */ 239 1.1 chopps 240 1.1 chopps ba->hstadrl = 0; 241 1.1 chopps ba->data = 5; 242 1.1 chopps ba->hstadrl = 0x20; 243 1.1 chopps ba->data = 0; /* no color planes blinking */ 244 1.1 chopps 245 1.1 chopps ba->hstadrl = 0; 246 1.1 chopps ba->data = 6; 247 1.1 chopps ba->hstadrl = 0x20; 248 1.1 chopps ba->data = gup->gus_ovslct = 0x43; 249 1.1 chopps /* overlay visible, no overlay blinking, overlay color 0 transparent */ 250 1.1 chopps 251 1.1 chopps ba->hstadrl = 0; 252 1.1 chopps ba->data = 7; 253 1.1 chopps ba->hstadrl = 0x20; 254 1.1 chopps ba->data = 0; /* voodoo */ 255 1.29 aymeric 256 1.1 chopps /* clear overlay planes */ 257 1.1 chopps ba->ctrl |= INCW; 258 1.1 chopps ba->hstadrh = 0xff80; 259 1.1 chopps ba->hstadrl = 0x0000; 260 1.1 chopps for (i=0xff80000; i< 0xffa0000; ++i) { 261 1.1 chopps ba->data = 0; 262 1.1 chopps } 263 1.1 chopps 264 1.1 chopps /* download tms code */ 265 1.1 chopps 266 1.1 chopps ba->ctrl = LBL | INCW | NMI | NMIM | HLT | CF; 267 1.1 chopps 268 1.22 christos printf("\ndownloading TMS code"); 269 1.5 chopps i=0; 270 1.5 chopps while ((j = tmscode[i++])) { 271 1.22 christos printf("."); 272 1.5 chopps ba->hstadrh = tmscode[i++]; 273 1.5 chopps ba->hstadrl = tmscode[i++]; 274 1.5 chopps while (j-- > 0) { 275 1.5 chopps ba->data = tmscode[i++]; 276 1.1 chopps } 277 1.1 chopps } 278 1.1 chopps 279 1.1 chopps /* font info was uploaded in ite_ul.c(ite_ulinit). */ 280 1.1 chopps 281 1.9 chopps #if 1 282 1.1 chopps /* XXX load image palette with some initial values, slightly hacky */ 283 1.1 chopps 284 1.1 chopps ba->hstadrh = 0xfe80; 285 1.1 chopps ba->hstadrl = 0x0000; 286 1.1 chopps ba->ctrl |= INCW; 287 1.1 chopps ba->data = 0; 288 1.1 chopps ba->ctrl &= ~INCW; 289 1.1 chopps 290 1.1 chopps for (i=0; i<16; ++i) { 291 1.1 chopps ba->data = gup->gus_imcmap[i+ 0] = ul_std_palette[i+ 0]; 292 1.1 chopps ba->data = gup->gus_imcmap[i+256] = ul_std_palette[i+16]; 293 1.1 chopps ba->data = gup->gus_imcmap[i+512] = ul_std_palette[i+32]; 294 1.1 chopps } 295 1.1 chopps 296 1.29 aymeric /* 297 1.29 aymeric * XXX load shadow overlay palette with what the TMS code will load 298 1.29 aymeric * into the real one some time after the TMS code is started below. 299 1.9 chopps * This might be considered a rude hack. 300 1.29 aymeric */ 301 1.46 cegger memcpy(gup->gus_ovcmap, ul_ovl_palette, 3*4); 302 1.9 chopps 303 1.29 aymeric /* 304 1.37 wiz * Unflush cache, unhalt CPU -> nmi starts to run. This MUST NOT BE 305 1.9 chopps * DONE before the image color map initialization above, to guarantee 306 1.12 is * the index register in the BT458 is not used by more than one CPU 307 1.9 chopps * at once. 308 1.9 chopps * 309 1.9 chopps * XXX For the same reason, we'll have to rething ul_putcmap(). For 310 1.9 chopps * details, look at comment there. 311 1.9 chopps */ 312 1.29 aymeric ba->ctrl &= ~(HLT|CF); 313 1.9 chopps 314 1.1 chopps #else 315 1.9 chopps /* 316 1.29 aymeric * XXX I wonder why this partially ever worked. 317 1.9 chopps * 318 1.9 chopps * This can't possibly work this way, as we are copyin()ing data in 319 1.9 chopps * ul_putcmap. 320 1.9 chopps * 321 1.29 aymeric * I guess this partially worked because SFC happened to point to 322 1.29 aymeric * to supervisor data space on 68030 machines coming from the old 323 1.9 chopps * boot loader. 324 1.9 chopps * 325 1.9 chopps * While this looks more correct than the hack in the other part of the 326 1.29 aymeric * loop, we would have to do our own version of the loop through 327 1.9 chopps * colormap entries, set up command buffer, and call gsp_write(), or 328 1.9 chopps * factor out some code. 329 1.9 chopps */ 330 1.9 chopps 331 1.9 chopps /* 332 1.29 aymeric * XXX This version will work for the overlay, if our queue codes 333 1.1 chopps * initial conditions are set at load time (not start time). 334 1.29 aymeric * It further assumes that ul_putcmap only uses the 335 1.1 chopps * GRFIMDEV/GRFOVDEV bits of the dev parameter. 336 1.1 chopps */ 337 1.1 chopps 338 1.9 chopps 339 1.37 wiz /* unflush cache, unhalt CPU first -> nmi starts to run */ 340 1.29 aymeric ba->ctrl &= ~(HLT|CF); 341 1.9 chopps 342 1.1 chopps gcm.index = 0; 343 1.1 chopps gcm.count = 16; 344 1.1 chopps gcm.red = ul_std_palette + 0; 345 1.1 chopps gcm.green = ul_std_palette + 16; 346 1.1 chopps gcm.blue = ul_std_palette + 32; 347 1.1 chopps ul_putcmap(gp, &gcm, GRFIMDEV); 348 1.1 chopps 349 1.1 chopps gcm.index = 0; 350 1.1 chopps gcm.count = 4; 351 1.1 chopps gcm.red = ul_ovl_palette + 0; 352 1.1 chopps gcm.green = ul_ovl_palette + 4; 353 1.1 chopps gcm.blue = ul_ovl_palette + 8; 354 1.1 chopps ul_putcmap(gp, &gcm, GRFOVDEV); 355 1.1 chopps #endif 356 1.1 chopps 357 1.1 chopps } 358 1.1 chopps 359 1.1 chopps static int 360 1.43 dsl ul_load_mon(struct grf_softc *gp, struct grfvideo_mode *md) 361 1.1 chopps { 362 1.1 chopps struct grfinfo *gi; 363 1.41 he volatile struct gspregs *ba; 364 1.1 chopps u_int16_t buf[8]; 365 1.1 chopps 366 1.1 chopps gi = &gp->g_display; 367 1.41 he ba = (volatile struct gspregs *)gp->g_regkva; 368 1.1 chopps 369 1.1 chopps gi->gd_dyn.gdi_fbx = 0; 370 1.1 chopps gi->gd_dyn.gdi_fby = 0; 371 1.1 chopps gi->gd_dyn.gdi_dwidth = md->disp_width; 372 1.1 chopps gi->gd_dyn.gdi_dheight = md->disp_height; 373 1.1 chopps gi->gd_dyn.gdi_dx = 0; 374 1.1 chopps gi->gd_dyn.gdi_dy = 0; 375 1.1 chopps 376 1.15 veego ba->ctrl = (ba->ctrl & ~INCR) | (LBL | INCW); /* XXX */ 377 1.1 chopps 378 1.1 chopps ba->hstadrh = 0xC000; 379 1.1 chopps ba->hstadrl = 0x0000; 380 1.24 veego 381 1.24 veego ba->data = (md->hsync_stop - md->hsync_start)/16; 382 1.24 veego ba->data = (md->htotal - md->hsync_start)/16 - 1; 383 1.24 veego ba->data = (md->hblank_start + md->htotal - md->hsync_start)/16 - 1; 384 1.24 veego ba->data = md->htotal/16 - 1; 385 1.24 veego 386 1.24 veego ba->data = md->vsync_stop - md->vsync_start; 387 1.24 veego ba->data = md->vtotal - md->vsync_start - 1; 388 1.24 veego ba->data = md->vblank_start + md->vtotal - md->vsync_start - 1; 389 1.24 veego ba->data = md->vtotal - 1; 390 1.1 chopps 391 1.1 chopps ba->ctrl &= ~INCW; 392 1.1 chopps ba->hstadrh = 0xFE90; 393 1.1 chopps ba->hstadrl = 0x0000; 394 1.1 chopps 395 1.1 chopps if (abs(md->pixel_clock - ulowell_clock[0]) > 396 1.1 chopps abs(md->pixel_clock - ulowell_clock[1])) { 397 1.1 chopps 398 1.5 chopps ba->data = (ba->data & 0xFC) | 2 | 1; 399 1.1 chopps md->pixel_clock = ulowell_clock[1]; 400 1.1 chopps 401 1.1 chopps } else { 402 1.5 chopps ba->data = (ba->data & 0xFC) | 2 | 0; 403 1.1 chopps md->pixel_clock = ulowell_clock[0]; 404 1.1 chopps } 405 1.1 chopps 406 1.15 veego ba->ctrl |= LBL | INCW; 407 1.1 chopps ba->hstadrh = 0xC000; 408 1.1 chopps ba->hstadrl = 0x0080; 409 1.24 veego ba->data = md->disp_flags & GRF_FLAGS_LACE ? 0xb020 : 0xf020; 410 1.1 chopps 411 1.1 chopps /* I guess this should be in the yet unimplemented mode select ioctl */ 412 1.1 chopps /* Hm.. maybe not. We always put the console on overlay plane no 0. */ 413 1.1 chopps /* Anyway, this _IS_ called in the mode select ioctl. */ 414 1.1 chopps 415 1.1 chopps /* ite support code parameters: */ 416 1.1 chopps buf[0] = GCMD_MCHG; 417 1.1 chopps buf[1] = md->disp_width; /* display width */ 418 1.1 chopps buf[2] = md->disp_height; /* display height */ 419 1.1 chopps buf[3] = 0; /* LSW of frame buffer origin */ 420 1.1 chopps buf[4] = 0xFF80; /* MSW of frame buffer origin */ 421 1.1 chopps buf[5] = gi->gd_fbwidth * 1; /* frame buffer pitch */ 422 1.1 chopps buf[6] = 1; /* frame buffer depth */ 423 1.1 chopps gsp_write(ba, buf, 7); 424 1.1 chopps 425 1.1 chopps return(1); 426 1.1 chopps } 427 1.1 chopps 428 1.29 aymeric int ul_mode(struct grf_softc *, u_long, void *, u_long, int); 429 1.29 aymeric 430 1.48 chs void grfulattach(device_t, device_t, void *); 431 1.29 aymeric int grfulprint(void *, const char *); 432 1.48 chs int grfulmatch(device_t, cfdata_t, void *); 433 1.1 chopps 434 1.48 chs CFATTACH_DECL_NEW(grful, sizeof(struct grf_ul_softc), 435 1.34 thorpej grfulmatch, grfulattach, NULL, NULL); 436 1.1 chopps 437 1.1 chopps /* 438 1.1 chopps * only used in console init 439 1.1 chopps */ 440 1.1 chopps static struct cfdata *cfdata; 441 1.1 chopps 442 1.1 chopps /* 443 1.1 chopps * we make sure to only init things once. this is somewhat 444 1.1 chopps * tricky regarding the console. 445 1.1 chopps */ 446 1.29 aymeric int 447 1.48 chs grfulmatch(device_t parent, cfdata_t cf, void *aux) 448 1.1 chopps { 449 1.16 veego #ifdef ULOWELLCONSOLE 450 1.1 chopps static int ulconunit = -1; 451 1.1 chopps #endif 452 1.1 chopps struct zbus_args *zap; 453 1.1 chopps 454 1.48 chs zap = aux; 455 1.1 chopps 456 1.1 chopps /* 457 1.1 chopps * allow only one ulowell console 458 1.1 chopps */ 459 1.1 chopps if (amiga_realconfig == 0) 460 1.1 chopps #ifdef ULOWELLCONSOLE 461 1.1 chopps if (ulconunit != -1) 462 1.1 chopps #endif 463 1.1 chopps return(0); 464 1.1 chopps 465 1.1 chopps if (zap->manid != 1030 || zap->prodid != 0) 466 1.1 chopps return(0); 467 1.1 chopps 468 1.1 chopps #ifdef ULOWELLCONSOLE 469 1.48 chs if (amiga_realconfig == 0 || ulconunit != cf->cf_unit) { 470 1.1 chopps #endif 471 1.11 chopps if ((unsigned)ulowell_default_mon > ulowell_mon_max) 472 1.1 chopps ulowell_default_mon = 1; 473 1.1 chopps 474 1.2 chopps current_mon = ul_monitor_defs + ulowell_default_mon - 1; 475 1.1 chopps if (ulowell_alive(current_mon) == 0) 476 1.1 chopps return(0); 477 1.29 aymeric #ifdef ULOWELLCONSOLE 478 1.1 chopps if (amiga_realconfig == 0) { 479 1.48 chs ulconunit = cf->cf_unit; 480 1.48 chs cfdata = cf; 481 1.29 aymeric } 482 1.1 chopps } 483 1.1 chopps #endif 484 1.1 chopps return(1); 485 1.1 chopps } 486 1.1 chopps 487 1.29 aymeric /* 488 1.1 chopps * attach to the grfbus (zbus) 489 1.1 chopps */ 490 1.1 chopps void 491 1.48 chs grfulattach(device_t parent, device_t self, void *aux) 492 1.1 chopps { 493 1.1 chopps static struct grf_ul_softc congrf; 494 1.48 chs struct device temp; 495 1.1 chopps struct zbus_args *zap; 496 1.1 chopps struct grf_softc *gp; 497 1.1 chopps struct grf_ul_softc *gup; 498 1.1 chopps 499 1.48 chs zap = aux; 500 1.29 aymeric 501 1.48 chs if (self == NULL) { 502 1.1 chopps gup = &congrf; 503 1.48 chs gp = &gup->gus_sc; 504 1.48 chs gp->g_device = &temp; 505 1.48 chs temp.dv_private = gp; 506 1.48 chs } else { 507 1.48 chs gup = device_private(self); 508 1.48 chs gp = &gup->gus_sc; 509 1.48 chs gp->g_device = self; 510 1.48 chs } 511 1.1 chopps 512 1.48 chs if (self != NULL && congrf.gus_sc.g_regkva != 0) { 513 1.1 chopps /* 514 1.1 chopps * inited earlier, just copy (not device struct) 515 1.1 chopps */ 516 1.46 cegger memcpy(&gp->g_display, &congrf.gus_sc.g_display, 517 1.1 chopps (char *)&gup->gus_isr - (char *)&gp->g_display); 518 1.1 chopps 519 1.1 chopps /* ...and transfer the isr */ 520 1.1 chopps gup->gus_isr.isr_ipl = 2; 521 1.1 chopps gup->gus_isr.isr_intr = ulisr; 522 1.1 chopps gup->gus_isr.isr_arg = (void *)gp; 523 1.29 aymeric /* 524 1.51 kamil * To make sure ints are always caught, first add new isr 525 1.1 chopps * then remove old: 526 1.1 chopps */ 527 1.1 chopps add_isr(&gup->gus_isr); 528 1.1 chopps remove_isr(&congrf.gus_isr); 529 1.1 chopps } else { 530 1.40 christos gp->g_regkva = (void *)zap->va; 531 1.1 chopps gp->g_fbkva = NULL; 532 1.1 chopps gp->g_unit = GRF_ULOWELL_UNIT; 533 1.1 chopps gp->g_flags = GF_ALIVE; 534 1.1 chopps gp->g_mode = ul_mode; 535 1.47 phx #if NITE > 0 536 1.1 chopps gp->g_conpri = grful_cnprobe(); 537 1.47 phx #endif 538 1.1 chopps gp->g_data = NULL; 539 1.1 chopps 540 1.1 chopps gup->gus_isr.isr_ipl = 2; 541 1.1 chopps gup->gus_isr.isr_intr = ulisr; 542 1.1 chopps gup->gus_isr.isr_arg = (void *)gp; 543 1.1 chopps add_isr(&gup->gus_isr); 544 1.1 chopps 545 1.1 chopps (void)ul_load_code(gp); 546 1.1 chopps (void)ul_load_mon(gp, current_mon); 547 1.47 phx #if NITE > 0 548 1.1 chopps grful_iteinit(gp); 549 1.47 phx #endif 550 1.1 chopps } 551 1.48 chs if (self != NULL) 552 1.22 christos printf("\n"); 553 1.1 chopps /* 554 1.1 chopps * attach grf 555 1.1 chopps */ 556 1.53 thorpej amiga_config_found(cfdata, gp->g_device, gp, grfulprint, CFARGS_NONE); 557 1.1 chopps } 558 1.1 chopps 559 1.1 chopps int 560 1.48 chs grfulprint(void *aux, const char *pnp) 561 1.1 chopps { 562 1.1 chopps if (pnp) 563 1.48 chs aprint_normal("grf%d at %s", ((struct grf_softc *)aux)->g_unit, 564 1.1 chopps pnp); 565 1.1 chopps return(UNCONF); 566 1.1 chopps } 567 1.1 chopps 568 1.29 aymeric static int 569 1.44 dsl ul_getvmode (struct grf_softc *gp, struct grfvideo_mode *vm) 570 1.1 chopps { 571 1.1 chopps struct grfvideo_mode *md; 572 1.1 chopps 573 1.1 chopps if (vm->mode_num && vm->mode_num > ulowell_mon_max) 574 1.1 chopps return EINVAL; 575 1.1 chopps 576 1.1 chopps if (! vm->mode_num) 577 1.2 chopps vm->mode_num = current_mon - ul_monitor_defs + 1; 578 1.1 chopps 579 1.2 chopps md = ul_monitor_defs + vm->mode_num - 1; 580 1.29 aymeric strncpy (vm->mode_descr, md->mode_descr, 581 1.1 chopps sizeof (vm->mode_descr)); 582 1.1 chopps 583 1.1 chopps /* XXX should tell TMS to measure it */ 584 1.1 chopps vm->pixel_clock = md->pixel_clock; 585 1.1 chopps vm->disp_width = md->disp_width; 586 1.1 chopps vm->disp_height = md->disp_height; 587 1.1 chopps vm->depth = md->depth; 588 1.1 chopps 589 1.24 veego vm->hblank_start = md->hblank_start; 590 1.24 veego vm->hsync_start = md->hsync_start; 591 1.24 veego vm->hsync_stop = md->hsync_stop; 592 1.24 veego vm->htotal = md->htotal; 593 1.24 veego 594 1.24 veego vm->vblank_start = md->vblank_start; 595 1.24 veego vm->vsync_start = md->vsync_start; 596 1.24 veego vm->vsync_stop = md->vsync_stop; 597 1.1 chopps vm->vtotal = md->vtotal; 598 1.1 chopps 599 1.24 veego vm->disp_flags = md->disp_flags; 600 1.1 chopps return 0; 601 1.1 chopps } 602 1.1 chopps 603 1.1 chopps 604 1.29 aymeric static int 605 1.44 dsl ul_setvmode (struct grf_softc *gp, unsigned mode) 606 1.1 chopps { 607 1.1 chopps int error; 608 1.1 chopps 609 1.1 chopps if (!mode || mode > ulowell_mon_max) 610 1.1 chopps return EINVAL; 611 1.1 chopps 612 1.2 chopps current_mon = ul_monitor_defs + mode - 1; 613 1.1 chopps 614 1.1 chopps error = ul_load_mon (gp, current_mon) ? 0 : EINVAL; 615 1.1 chopps 616 1.1 chopps return error; 617 1.1 chopps } 618 1.1 chopps 619 1.1 chopps /* 620 1.1 chopps * Set the frame buffer or overlay planes on or off. 621 1.1 chopps * Always succeeds. 622 1.1 chopps */ 623 1.1 chopps 624 1.39 perry static inline void 625 1.43 dsl ul_setfb(struct grf_softc *gp, u_long cmd) 626 1.1 chopps { 627 1.1 chopps struct grf_ul_softc *gup; 628 1.41 he volatile struct gspregs *ba; 629 1.1 chopps 630 1.1 chopps gup = (struct grf_ul_softc *)gp; 631 1.1 chopps 632 1.41 he ba = (volatile struct gspregs *)gp->g_regkva; 633 1.1 chopps ba->ctrl = LBL; 634 1.1 chopps ba->hstadrh = 0xfe80; 635 1.1 chopps ba->hstadrl = 0x0000; 636 1.1 chopps ba->data = 6; 637 1.1 chopps ba->hstadrl = 0x0020; 638 1.1 chopps 639 1.1 chopps switch (cmd) { 640 1.1 chopps case GM_GRFON: 641 1.1 chopps gup->gus_ovslct |= 0x40; 642 1.1 chopps break; 643 1.1 chopps case GM_GRFOFF: 644 1.1 chopps gup->gus_ovslct &= ~0x40; 645 1.1 chopps break; 646 1.1 chopps case GM_GRFOVON: 647 1.1 chopps gup->gus_ovslct |= 3; 648 1.1 chopps break; 649 1.1 chopps case GM_GRFOVOFF: 650 1.1 chopps gup->gus_ovslct &= ~3; 651 1.1 chopps break; 652 1.1 chopps } 653 1.1 chopps ba->data = gup->gus_ovslct; 654 1.1 chopps } 655 1.1 chopps 656 1.1 chopps /* 657 1.1 chopps * Change the mode of the display. 658 1.1 chopps * Return a UNIX error number or 0 for success. 659 1.1 chopps */ 660 1.1 chopps int 661 1.43 dsl ul_mode(struct grf_softc *gp, u_long cmd, void *arg, u_long a2, int a3) 662 1.1 chopps { 663 1.1 chopps int i; 664 1.1 chopps struct grfdyninfo *gd; 665 1.1 chopps 666 1.1 chopps switch (cmd) { 667 1.1 chopps case GM_GRFON: 668 1.1 chopps case GM_GRFOFF: 669 1.1 chopps case GM_GRFOVON: 670 1.1 chopps case GM_GRFOVOFF: 671 1.1 chopps ul_setfb (gp, cmd); 672 1.1 chopps return 0; 673 1.29 aymeric 674 1.1 chopps case GM_GRFCONFIG: 675 1.1 chopps gd = (struct grfdyninfo *)arg; 676 1.1 chopps for (i=0; i<ulowell_mon_max; ++i) { 677 1.2 chopps if (ul_monitor_defs[i].disp_width == gd->gdi_dwidth && 678 1.2 chopps ul_monitor_defs[i].disp_height == gd->gdi_dheight) 679 1.1 chopps return ul_setvmode(gp, i+1); 680 1.1 chopps } 681 1.1 chopps return EINVAL; 682 1.1 chopps 683 1.1 chopps case GM_GRFGETVMODE: 684 1.1 chopps return ul_getvmode (gp, (struct grfvideo_mode *) arg); 685 1.1 chopps 686 1.1 chopps case GM_GRFSETVMODE: 687 1.1 chopps return ul_setvmode (gp, *(unsigned *) arg); 688 1.1 chopps 689 1.1 chopps case GM_GRFGETNUMVM: 690 1.1 chopps *(int *)arg = ulowell_mon_max; 691 1.1 chopps return 0; 692 1.1 chopps 693 1.1 chopps case GM_GRFIOCTL: 694 1.15 veego return ul_ioctl (gp, a2, arg, (dev_t)a3); 695 1.1 chopps 696 1.1 chopps default: 697 1.1 chopps break; 698 1.1 chopps } 699 1.29 aymeric 700 1.31 atatat return EPASSTHROUGH; 701 1.1 chopps } 702 1.1 chopps 703 1.1 chopps int 704 1.44 dsl ul_ioctl (register struct grf_softc *gp, u_long cmd, void *data, dev_t dev) 705 1.1 chopps { 706 1.1 chopps switch (cmd) { 707 1.1 chopps #if 0 708 1.1 chopps /* 709 1.1 chopps * XXX we have no hardware sprites, but might implement them 710 1.1 chopps * later in TMS code. 711 1.1 chopps */ 712 1.1 chopps 713 1.1 chopps case GRFIOCGSPRITEPOS: 714 1.1 chopps return ul_getspritepos (gp, (struct grf_position *) data); 715 1.1 chopps 716 1.1 chopps case GRFIOCSSPRITEPOS: 717 1.1 chopps return ul_setspritepos (gp, (struct grf_position *) data); 718 1.1 chopps 719 1.1 chopps case GRFIOCSSPRITEINF: 720 1.1 chopps return ul_setspriteinfo (gp, (struct grf_spriteinfo *) data); 721 1.1 chopps 722 1.1 chopps case GRFIOCGSPRITEINF: 723 1.1 chopps return ul_getspriteinfo (gp, (struct grf_spriteinfo *) data); 724 1.1 chopps 725 1.1 chopps case GRFIOCGSPRITEMAX: 726 1.1 chopps return ul_getspritemax (gp, (struct grf_position *) data); 727 1.1 chopps 728 1.1 chopps #endif 729 1.1 chopps 730 1.1 chopps case GRFIOCGETCMAP: 731 1.1 chopps return ul_getcmap (gp, (struct grf_colormap *) data, dev); 732 1.1 chopps 733 1.1 chopps case GRFIOCPUTCMAP: 734 1.1 chopps return ul_putcmap (gp, (struct grf_colormap *) data, dev); 735 1.1 chopps 736 1.1 chopps case GRFIOCBITBLT: 737 1.1 chopps return ul_bitblt (gp, (struct grf_bitblt *) data, dev); 738 1.10 chopps 739 1.10 chopps case GRFIOCBLANK: 740 1.10 chopps return ul_blank (gp, (int *) data, dev); 741 1.1 chopps } 742 1.1 chopps 743 1.31 atatat return EPASSTHROUGH; 744 1.29 aymeric } 745 1.1 chopps 746 1.1 chopps int 747 1.44 dsl ul_getcmap (struct grf_softc *gp, struct grf_colormap *cmap, dev_t dev) 748 1.1 chopps { 749 1.1 chopps struct grf_ul_softc *gup; 750 1.1 chopps u_int8_t *mymap; 751 1.5 chopps int mxidx, error; 752 1.1 chopps 753 1.1 chopps gup = (struct grf_ul_softc *)gp; 754 1.1 chopps 755 1.1 chopps if (minor(dev) & GRFIMDEV) { 756 1.1 chopps mxidx = 256; 757 1.1 chopps mymap = gup->gus_imcmap; 758 1.1 chopps } else { 759 1.1 chopps mxidx = 4; 760 1.1 chopps mymap = gup->gus_ovcmap; 761 1.1 chopps } 762 1.29 aymeric 763 1.1 chopps if (cmap->count == 0 || cmap->index >= mxidx) 764 1.1 chopps return 0; 765 1.1 chopps 766 1.32 itojun if (cmap->count > mxidx - cmap->index) 767 1.1 chopps cmap->count = mxidx - cmap->index; 768 1.1 chopps 769 1.1 chopps /* just copyout from the shadow color map */ 770 1.1 chopps 771 1.1 chopps if ((error = copyout(mymap + cmap->index, cmap->red, cmap->count)) 772 1.1 chopps 773 1.29 aymeric || (error = copyout(mymap + mxidx + cmap->index, cmap->green, 774 1.1 chopps cmap->count)) 775 1.1 chopps 776 1.29 aymeric || (error = copyout(mymap + mxidx * 2 + cmap->index, cmap->blue, 777 1.1 chopps cmap->count))) 778 1.1 chopps 779 1.1 chopps return(error); 780 1.1 chopps 781 1.1 chopps return(0); 782 1.1 chopps } 783 1.1 chopps 784 1.1 chopps int 785 1.44 dsl ul_putcmap (struct grf_softc *gp, struct grf_colormap *cmap, dev_t dev) 786 1.1 chopps { 787 1.1 chopps struct grf_ul_softc *gup; 788 1.41 he volatile struct gspregs *ba; 789 1.1 chopps u_int16_t cmd[8]; 790 1.1 chopps int x, mxidx, error; 791 1.1 chopps u_int8_t *mymap; 792 1.1 chopps 793 1.1 chopps gup = (struct grf_ul_softc *)gp; 794 1.1 chopps 795 1.1 chopps if (minor(dev) & GRFIMDEV) { 796 1.1 chopps mxidx = 256; 797 1.1 chopps mymap = gup->gus_imcmap; 798 1.1 chopps } else { 799 1.1 chopps mxidx = 4; 800 1.1 chopps mymap = gup->gus_ovcmap; 801 1.1 chopps } 802 1.1 chopps 803 1.1 chopps if (cmap->count == 0 || cmap->index >= mxidx) 804 1.1 chopps return 0; 805 1.1 chopps 806 1.32 itojun if (cmap->count > mxidx - cmap->index) 807 1.1 chopps cmap->count = mxidx - cmap->index; 808 1.1 chopps 809 1.1 chopps /* first copyin to our shadow color map */ 810 1.1 chopps 811 1.1 chopps if ((error = copyin(cmap->red, mymap + cmap->index, cmap->count)) 812 1.1 chopps 813 1.1 chopps || (error = copyin(cmap->green, mymap + cmap->index + mxidx, 814 1.1 chopps cmap->count)) 815 1.1 chopps 816 1.1 chopps || (error = copyin(cmap->blue, mymap + cmap->index + mxidx*2, 817 1.1 chopps cmap->count))) 818 1.1 chopps 819 1.1 chopps return error; 820 1.29 aymeric 821 1.1 chopps 822 1.1 chopps /* then write from there to the hardware */ 823 1.41 he ba = (volatile struct gspregs *)gp->g_regkva; 824 1.9 chopps /* 825 1.9 chopps * XXX This is a bad thing to do. 826 1.29 aymeric * We should always use the gsp call, or have a means to arbitrate 827 1.29 aymeric * the usage of the BT458 index register. Else there might be a 828 1.9 chopps * race condition (when writing both colormaps at nearly the same 829 1.9 chopps * time), where one CPU changes the index register when the other 830 1.9 chopps * one has not finished using it. 831 1.9 chopps */ 832 1.1 chopps if (mxidx > 4) { 833 1.1 chopps /* image color map: we can write, with a hack, directly */ 834 1.1 chopps ba->ctrl = LBL; 835 1.1 chopps ba->hstadrh = 0xfe80; 836 1.1 chopps ba->hstadrl = 0x0000; 837 1.1 chopps ba->ctrl |= INCW; 838 1.1 chopps ba->data = cmap->index; 839 1.1 chopps ba->ctrl &= ~INCW; 840 1.1 chopps 841 1.1 chopps for (x=cmap->index; x < cmap->index + cmap->count; ++x) { 842 1.1 chopps ba->data = (u_int16_t) mymap[x]; 843 1.1 chopps ba->data = (u_int16_t) mymap[x + mxidx]; 844 1.1 chopps ba->data = (u_int16_t) mymap[x + mxidx * 2]; 845 1.1 chopps } 846 1.1 chopps } else { 847 1.1 chopps 848 1.1 chopps /* overlay planes color map: have to call tms to do it */ 849 1.1 chopps cmd[0] = GCMD_CMAP; 850 1.1 chopps cmd[1] = 1; 851 1.1 chopps for (x=cmap->index; x < cmap->index + cmap->count; ++x) { 852 1.1 chopps cmd[2] = x; 853 1.1 chopps cmd[3] = mymap[x]; 854 1.1 chopps cmd[4] = mymap[x + mxidx]; 855 1.1 chopps cmd[5] = mymap[x + mxidx * 2]; 856 1.1 chopps gsp_write(ba, cmd, 6); 857 1.1 chopps } 858 1.1 chopps } 859 1.1 chopps return 0; 860 1.1 chopps } 861 1.1 chopps 862 1.10 chopps int 863 1.43 dsl ul_blank(struct grf_softc *gp, int *onoff, dev_t dev) 864 1.10 chopps { 865 1.41 he volatile struct gspregs *gsp; 866 1.17 is 867 1.41 he gsp = (volatile struct gspregs *)gp->g_regkva; 868 1.15 veego gsp->ctrl = (gsp->ctrl & ~(INCR | INCW)) | LBL; 869 1.10 chopps gsp->hstadrh = 0xC000; 870 1.10 chopps gsp->hstadrl = 0x0080; 871 1.18 is if (*onoff > 0) 872 1.10 chopps gsp->data |= 0x9000; 873 1.10 chopps else 874 1.10 chopps gsp->data &= ~0x9000; 875 1.29 aymeric 876 1.10 chopps return 0; 877 1.10 chopps } 878 1.1 chopps /* 879 1.1 chopps * !!! THIS AREA UNDER CONSTRUCTION !!! 880 1.1 chopps */ 881 1.1 chopps int ul_BltOpMap[16] = { 882 1.29 aymeric 3, 1, 2, 0, 11, 9, 10, 8, 883 1.1 chopps 7, 5, 6, 4, 15, 13, 14, 12 884 1.1 chopps }; 885 1.1 chopps 886 1.1 chopps int 887 1.44 dsl ul_bitblt (struct grf_softc *gp, struct grf_bitblt *bb, dev_t dev) 888 1.1 chopps { 889 1.1 chopps /* XXX not yet implemented, but pretty trivial */ 890 1.31 atatat return EPASSTHROUGH; 891 1.1 chopps } 892 1.1 chopps 893 1.1 chopps void 894 1.43 dsl gsp_write(volatile struct gspregs *gsp, u_short *ptr, size_t size) 895 1.1 chopps { 896 1.1 chopps u_short put, new_put, next, oc; 897 1.1 chopps u_long put_hi, oa; 898 1.1 chopps size_t n; 899 1.1 chopps 900 1.1 chopps if (size == 0 || size > 8) 901 1.1 chopps return; 902 1.1 chopps 903 1.1 chopps n = size; 904 1.1 chopps 905 1.1 chopps oc = gsp->ctrl; 906 1.1 chopps oa = GSPGETHADRS(gsp); 907 1.1 chopps 908 1.5 chopps gsp->ctrl = (oc & ~INCR) | LBL | INCW; 909 1.5 chopps GSPSETHADRS(gsp, GSP_MODE_ADRS); 910 1.1 chopps gsp->data &= ~GMODE_FLUSH; 911 1.1 chopps 912 1.5 chopps GSPSETHADRS(gsp, PUT_HI_PTR_ADRS); 913 1.1 chopps put_hi = gsp->data << 16; 914 1.1 chopps 915 1.5 chopps GSPSETHADRS(gsp, PUT_PTR_ADRS); 916 1.1 chopps put = gsp->data; 917 1.1 chopps new_put = put + (8<<4); 918 1.1 chopps 919 1.5 chopps GSPSETHADRS(gsp, GET_PTR_ADRS); 920 1.1 chopps next = gsp->data; 921 1.29 aymeric 922 1.1 chopps while (next == new_put) { 923 1.1 chopps /* 924 1.1 chopps * we should use an intr. here. unfortunately, we already 925 1.36 wiz * are called from an interrupt and can't use tsleep. 926 1.1 chopps * so we do busy waiting, at least for the moment. 927 1.1 chopps */ 928 1.1 chopps 929 1.1 chopps GSPSETHADRS(gsp,GET_PTR_ADRS); 930 1.1 chopps next = gsp->data; 931 1.1 chopps } 932 1.1 chopps 933 1.1 chopps GSPSETHADRS(gsp,put|put_hi); 934 1.1 chopps gsp->data = *ptr++ | 8<<4; 935 1.1 chopps while ( --n > 0) { 936 1.1 chopps gsp->data = *ptr++; 937 1.1 chopps } 938 1.1 chopps 939 1.1 chopps GSPSETHADRS(gsp,PUT_PTR_ADRS); 940 1.1 chopps gsp->data = new_put; 941 1.1 chopps GSPSETHADRS(gsp,oa); 942 1.1 chopps gsp->ctrl = oc; 943 1.1 chopps 944 1.1 chopps return; 945 1.1 chopps } 946 1.1 chopps 947 1.1 chopps #endif /* NGRF */ 948