Subject: Re: (yet another) color X server available
To: None <kei_sun@ba2.so-net.or.jp>
From: Ken Nakata <kenn@physics.rutgers.edu>
List: port-mac68k
Date: 02/24/1998 01:40:44
----Next_Part(Tue_Feb_24_01:38:46_1998_595)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

On Tue, 24 Feb 1998 02:16:20 +0900,
SUNAGAWA Keiki <kei_sun@ba2.so-net.or.jp> writes:
> 
> I ftp'ed the server and the document and tried it.
> 
> machine: Mac IIci w/ Daystar PowerCache.
> video: MacII Portrait Video Card. I upgraded its VRAM, so
> it can display 16 grays (4 bit/pixel).
> 
> They're shown as below in the boot message.
> 
> macvid0 at nubus0 slot c: Mac II Portrait Video Card
> macvid0: 640 x 870, monochrome
> grf0 at macvid0
> ite0 at grf0 (minimal console)
> 
> My problem is that I couldn't get the grayscale to work.

Ouch.

> To enable grayscale mode, I set the monitor to 4 bits
> grayscale mode in MacOS, changed the Booter not to touch
> monitor configuration before booting NetBSD.

So far, so good.

> Booted NetBSD, I set the environment variable (I actually
> tried the command line argument too.)
> 
> % setenv XDEVICES /dev/grf0,2,g

Actually, as you don't have ROM driver support, this shouldn't be
necessary (shouldn't hurt, either).

> When I start the new X server, the display is split into 16
> (4x4) and everything is shown in the most upper 4 screens
> same as stock server.  It says that there is no ROM support
> in the video card, also.  If you need exact message, I'll
> post them later.

Hmm...  Probably the error message won't help much if at all.  I'd
like you to compile and run the attached program under 4-bpp mode, and
tell me what you see on the screen.  I expect a screen divided into 4
horizontal bands of 4 different gray levels.

Thanks,

ken

----Next_Part(Tue_Feb_24_01:38:46_1998_595)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

#include <unistd.h>
#include <stddef.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <machine/grfioctl.h>
#include <machine/endian.h>

struct grfmode mode;

int
main(int argc, char *argv[])
{
    int gfd, i;
    char buf[20];
    void fill_screen(int);

    if (argc == 1) {
	if ((gfd = open("/dev/grf0", O_RDWR)) == -1) {
	    perror("scrfill:");
	    exit(1);
	}
	fill_screen(gfd);
	while (read(0, buf, 20) <= 0) {
	    /* wait until return key is pressed */
	}
	close(gfd);
    } else {
	for (i = 1; i < argc; i++) {
	    if ((gfd = open(*argv, O_RDWR)) == -1) {
		perror("scrfill:");
		exit(1);
	    }
	    fill_screen(gfd);
	    while (read(0, buf, 20) <= 0) {
		/* wait until return key is pressed */
	    }
	    close(gfd);
	}
    }
    return 0;
}


void
fill_screen(int gfd)
{
    int height, width, depth, rowbytes;
    u_int32_t data;
    int i, j, k;
    void *p;
    caddr_t vaddr;
    void fill_line(void *, int, u_int32_t, int);

    if (ioctl(gfd, GRFIOCGMODE, (void *)&mode) == -1) {
	perror("scrfill: cannot obtain mode info:");
	return;
    }
    height = mode.height;
    width = mode.width;
    depth = mode.psize;
    rowbytes = mode.rowbytes;
    printf("screen: %d x %d x %d, rowbytes = %d\n", width, height, depth, rowbytes);

    /* map frame buffer into my virtual addr space */
    if ((vaddr = mmap(0, mode.fbsize, (PROT_READ|PROT_WRITE),
		      MAP_SHARED, gfd, mode.fboff)) == (caddr_t) -1) {
	perror("scrfill: cannot map screen:");
	return;
    }

    if (depth > 8) {
	data = 1;
	k = height / depth;
	p = (void *)vaddr;
	for (j = 0; j < depth; j++) {
	    for (i = 0; i < k; i++) {
		fill_line(p, width, data, depth);
		p += rowbytes;
	    }
	    data <<= 1;
	}
    } else {
	data = 0;
	k = height / (1 << depth);
	p = (void *)vaddr;
	for (j = 0; j < (1 << depth); j++) {
	    for (i = 0; i < k; i++) {
		fill_line(p, width, data, depth);
		p += rowbytes;
	    }
	    data++;
	}
    }
}

void
fill_line(void *dst, int n_data, u_int32_t data, int data_size)
{
    int i, shift;
    u_int32_t *p;
    u_int32_t pat, *pats;

    switch (data_size) {
    case 1:
    case 2:
    case 4:
    case 8:
    case 16:
    case 32:
	for (i = 32, pat = data, shift = data_size; i > data_size; i >>= 1) {
	    pat |= (pat << shift);
	    shift *= 2;
	}
	for (p = (u_int32_t *)dst, shift = 32 / data_size;
	     n_data > 0;
	     n_data -= shift) {
	    *p++ = pat;
	}
	break;
    case 24:
#if BYTE_ORDER == BIG_ENDIAN
	data <<= (32 - data_size);
#endif /* BYTE_ORDER */
	data_size /= 8;
	for (i = 0; i < n_data; i++) {
	    memcpy(dst, (void *)&data, data_size);
	    dst += data_size;
	}
	break;
    default:
	/* XXX too lazy to implement the general case */
	break;
    }
}

----Next_Part(Tue_Feb_24_01:38:46_1998_595)----