156885Sakito /*
256885Sakito * Copyright (c) 1992 OMRON Corporation.
3*63192Sbostic * Copyright (c) 1992, 1993
4*63192Sbostic * The Regents of the University of California. All rights reserved.
556885Sakito *
656885Sakito * This code is derived from software contributed to Berkeley by
756885Sakito * OMRON Corporation.
856885Sakito *
956885Sakito * %sccs.include.redist.c%
1056885Sakito *
11*63192Sbostic * @(#)bmd.c 8.1 (Berkeley) 06/10/93
1256885Sakito */
1357239Sakito
1456885Sakito /*
1556885Sakito
1656885Sakito * bmd.c --- Bitmap-Display raw-level driver routines
1756885Sakito *
1856885Sakito * by A.Fujita, SEP-09-1992
1956885Sakito */
2056885Sakito
2157353Sakito #undef BMD_PRINTF
2256885Sakito
2357108Sakito #include <sys/param.h>
2457108Sakito #include <sys/systm.h>
2556885Sakito
2656885Sakito extern u_short bmdfont[][20];
2756885Sakito
2856885Sakito #define isprint(c) ( c < 0x20 ? 0 : 1)
2956885Sakito
3056885Sakito /*
3156885Sakito * Width & Hight
3256885Sakito */
3356885Sakito
3456885Sakito #define PB_WIDTH 2048 /* Plane Width (Bit) */
3556885Sakito #define PB_HIGHT 1024 /* Plane Hight (Bit) */
3656885Sakito #define PL_WIDTH 64 /* Plane Width (long) */
3756885Sakito #define PS_WIDTH 128 /* Plane Width (long) */
3856885Sakito #define P_WIDTH 256 /* Plane Width (Byte) */
3956885Sakito
4056885Sakito #define SB_WIDTH 1280 /* Screen Width (Bit) */
4156885Sakito #define SB_HIGHT 1024 /* Screen Hight (Bit) */
4256885Sakito #define SL_WIDTH 40 /* Screen Width (Long) */
4356885Sakito #define S_WIDTH 160 /* Screen Width (Byte) */
4456885Sakito
4556885Sakito #define FB_WIDTH 12 /* Font Width (Bit) */
4656885Sakito #define FB_HIGHT 20 /* Font Hight (Bit) */
4756885Sakito
4856885Sakito
4956885Sakito #define NEXT_LINE(addr) ( addr + (PL_WIDTH * FB_HIGHT) )
5056885Sakito #define SKIP_NEXT_LINE(addr) ( addr += (PL_WIDTH - SL_WIDTH) )
5156885Sakito
5256885Sakito
5356885Sakito void bmd_add_new_line();
5456885Sakito
5556885Sakito void bmd_draw_char();
5656885Sakito void bmd_reverse_char();
5756885Sakito void bmd_erase_char();
5856885Sakito void bmd_erase_screen();
5956885Sakito void bmd_scroll_screen();
6056885Sakito
6157353Sakito void bmd_escape();
6256885Sakito
6357353Sakito
6456885Sakito struct bmd_linec {
6556885Sakito struct bmd_linec *bl_next;
6656885Sakito struct bmd_linec *bl_prev;
6756885Sakito int bl_col;
6856885Sakito int bl_end;
6956885Sakito u_char bl_line[128];
7056885Sakito };
7156885Sakito
7256885Sakito struct bmd_softc {
7356885Sakito int bc_stat;
7456885Sakito char *bc_raddr;
7556885Sakito char *bc_waddr;
7656885Sakito int bc_xmin;
7756885Sakito int bc_xmax;
7856885Sakito int bc_ymin;
7956885Sakito int bc_ymax;
8056885Sakito int bc_col;
8156885Sakito int bc_row;
8256885Sakito struct bmd_linec *bc_bl;
8356885Sakito char bc_escseq[8];
8456885Sakito char *bc_esc;
8556885Sakito void (*bc_escape)();
8656885Sakito };
8756885Sakito
8856885Sakito #define STAT_NORMAL 0x0000
8956885Sakito #define STAT_ESCAPE 0x0001
9057239Sakito #define STAT_STOP 0x0002
9156885Sakito
9256885Sakito struct bmd_softc bmd_softc;
9356885Sakito struct bmd_linec bmd_linec[52];
9456885Sakito
9557353Sakito int bmd_initflag = 0;
9656885Sakito
9756885Sakito /*
9856885Sakito * Escape-Sequence
9956885Sakito */
10056885Sakito
10157239Sakito #define push_ESC(p, c) *(p)->bc_esc++ = c; *(p)->bc_esc = '\0'
10257239Sakito
10356885Sakito void
bmd_escape(c)10456885Sakito bmd_escape(c)
10556885Sakito int c;
10656885Sakito {
10756885Sakito register struct bmd_softc *bp = &bmd_softc;
10856885Sakito
10956885Sakito bp->bc_stat &= ~STAT_ESCAPE;
11056885Sakito bp->bc_esc = &bp->bc_escseq[0];
11157239Sakito /* bp->bc_escape = bmd_escape; */
11256885Sakito }
11356885Sakito
11456885Sakito /*
11556885Sakito * Entry Routine
11656885Sakito */
11756885Sakito
bmdinit()11856885Sakito bmdinit()
11956885Sakito {
12056885Sakito register struct bmd_softc *bp = &bmd_softc;
12156885Sakito register struct bmd_linec *bq;
12256885Sakito register int i;
12356885Sakito
12457218Sakito bp->bc_raddr = (char *) 0xB10C0008; /* plane-0 hardware address */
12557218Sakito bp->bc_waddr = (char *) 0xB1080008; /* common bitmap hardware address */
12657218Sakito
12756885Sakito /*
12856885Sakito * adjust plane position
12956885Sakito */
13056885Sakito
13157218Sakito fb_adjust(7, -27);
13256885Sakito
13356885Sakito bp->bc_stat = STAT_NORMAL;
13456885Sakito
13556885Sakito bp->bc_xmin = 8;
13656885Sakito bp->bc_xmax = 96;
13756885Sakito bp->bc_ymin = 2;
13856885Sakito bp->bc_ymax = 48;
13956885Sakito
14056885Sakito bp->bc_row = bp->bc_ymin;
14156885Sakito
14256885Sakito for (i = bp->bc_ymin; i < bp->bc_ymax; i++) {
14356885Sakito bmd_linec[i].bl_next = &bmd_linec[i+1];
14456885Sakito bmd_linec[i].bl_prev = &bmd_linec[i-1];
14556885Sakito }
14656885Sakito bmd_linec[bp->bc_ymax-1].bl_next = &bmd_linec[bp->bc_ymin];
14756885Sakito bmd_linec[bp->bc_ymin].bl_prev = &bmd_linec[bp->bc_ymax-1];
14856885Sakito
14956885Sakito bq = bp->bc_bl = &bmd_linec[bp->bc_ymin];
15056885Sakito bq->bl_col = bq->bl_end = bp->bc_xmin;
15156885Sakito
15256885Sakito bp->bc_col = bp->bc_xmin;
15356885Sakito
15456885Sakito bp->bc_esc = &bp->bc_escseq[0];
15556885Sakito bp->bc_escape = bmd_escape;
15656885Sakito
15756885Sakito bmd_erase_screen((u_long *) bp->bc_waddr); /* clear screen */
15856885Sakito
15956885Sakito /* turn on cursole */
16056885Sakito bmd_reverse_char(bp->bc_raddr,
16156885Sakito bp->bc_waddr,
16256885Sakito bq->bl_col, bp->bc_row);
16357353Sakito
16457353Sakito bmd_initflag = 1;
16556885Sakito }
16656885Sakito
bmdputc(c)16756885Sakito bmdputc(c)
16856885Sakito register int c;
16956885Sakito {
17057353Sakito register struct bmd_softc *bp;
17157353Sakito register struct bmd_linec *bq;
17256885Sakito register int i;
17356885Sakito
17457353Sakito if (!bmd_initflag)
17557353Sakito bmdinit();
17657353Sakito
17757353Sakito bp = &bmd_softc;
17857353Sakito bq = bp->bc_bl;
17957353Sakito
18057239Sakito /* skip out, if STAT_STOP */
18157239Sakito if (bp->bc_stat & STAT_STOP)
18257239Sakito return(c);
18357239Sakito
18456885Sakito c &= 0x7F;
18556885Sakito /* turn off cursole */
18656885Sakito bmd_reverse_char(bp->bc_raddr,
18756885Sakito bp->bc_waddr,
18856885Sakito bq->bl_col, bp->bc_row);
18956885Sakito /* do escape-sequence */
19057239Sakito
19156885Sakito if (bp->bc_stat & STAT_ESCAPE) {
19256885Sakito *bp->bc_esc++ = c;
19356885Sakito (*bp->bc_escape)(c);
19456885Sakito goto done;
19556885Sakito }
19656885Sakito
19756885Sakito if (isprint(c)) {
19856885Sakito bmd_draw_char(bp->bc_raddr, bp->bc_waddr,
19956885Sakito bq->bl_col, bp->bc_row, c);
20056885Sakito bq->bl_col++;
20156885Sakito bq->bl_end++;
20256885Sakito if (bq->bl_col >= bp->bc_xmax) {
20356885Sakito bq->bl_col = bq->bl_end = bp->bc_xmin;
20456885Sakito bp->bc_row++;
20556885Sakito if (bp->bc_row >= bp->bc_ymax) {
20656885Sakito bmd_scroll_screen((u_long *) bp->bc_raddr,
20756885Sakito (u_long *) bp->bc_waddr,
20856885Sakito bp->bc_xmin, bp->bc_xmax,
20956885Sakito bp->bc_ymin, bp->bc_ymax);
21056885Sakito
21156885Sakito bp->bc_row = bp->bc_ymax - 1;
21256885Sakito }
21356885Sakito }
21456885Sakito } else {
21556885Sakito switch (c) {
21656885Sakito case 0x08: /* BS */
21756885Sakito if (bq->bl_col > bp->bc_xmin) {
21856885Sakito bq->bl_col--;
21956885Sakito }
22056885Sakito break;
22156885Sakito
22256885Sakito case 0x09: /* HT */
22356885Sakito case 0x0B: /* VT */
22456885Sakito i = ((bq->bl_col / 8) + 1) * 8;
22556885Sakito if (i < bp->bc_xmax) {
22656885Sakito bq->bl_col = bq->bl_end = i;
22756885Sakito }
22856885Sakito break;
22956885Sakito
23056885Sakito case 0x0A: /* NL */
23156885Sakito bp->bc_row++;
23256885Sakito if (bp->bc_row >= bp->bc_ymax) {
23356885Sakito bmd_scroll_screen((u_long *) bp->bc_raddr,
23456885Sakito (u_long *) bp->bc_waddr,
23556885Sakito bp->bc_xmin, bp->bc_xmax,
23656885Sakito bp->bc_ymin, bp->bc_ymax);
23756885Sakito
23856885Sakito bp->bc_row = bp->bc_ymax - 1;
23956885Sakito }
24056885Sakito break;
24156885Sakito
24256885Sakito case 0x0D: /* CR */
24356885Sakito bq->bl_col = bp->bc_xmin;
24456885Sakito break;
24556885Sakito
24656885Sakito case 0x1b: /* ESC */
24757239Sakito bmdputc('<');
24857239Sakito bmdputc('E');
24957239Sakito bmdputc('S');
25057239Sakito bmdputc('C');
25157239Sakito bmdputc('>');
25257239Sakito /*
25356885Sakito bp->bc_stat |= STAT_ESCAPE;
25456885Sakito *bp->bc_esc++ = 0x1b;
25557239Sakito */
25656885Sakito break;
25756885Sakito
25856885Sakito case 0x7F: /* DEL */
25956885Sakito if (bq->bl_col > bp->bc_xmin) {
26056885Sakito bq->bl_col--;
26156885Sakito bmd_erase_char(bp->bc_raddr,
26256885Sakito bp->bc_waddr,
26356885Sakito bq->bl_col, bp->bc_row);
26456885Sakito }
26556885Sakito break;
26656885Sakito
26756885Sakito default:
26856885Sakito break;
26956885Sakito }
27056885Sakito }
27156885Sakito
27256885Sakito done:
27356885Sakito /* turn on cursole */
27456885Sakito bmd_reverse_char(bp->bc_raddr,
27556885Sakito bp->bc_waddr,
27656885Sakito bq->bl_col, bp->bc_row);
27756885Sakito
27856885Sakito return(c);
27956885Sakito }
28056885Sakito
28157239Sakito /*
28257239Sakito *
28357239Sakito */
28457239Sakito
bmd_on()28557239Sakito bmd_on()
28656885Sakito {
28757239Sakito bmdinit();
28857239Sakito }
28957239Sakito
bmd_off()29057239Sakito bmd_off()
29157239Sakito {
29256885Sakito register struct bmd_softc *bp = &bmd_softc;
29357239Sakito
29457239Sakito bp->bc_stat |= STAT_STOP;
29557239Sakito bmd_erase_screen((u_long *) bp->bc_waddr); /* clear screen */
29657239Sakito }
29757239Sakito
bmd_clear()29857239Sakito bmd_clear()
29957239Sakito {
30057239Sakito register struct bmd_softc *bp = &bmd_softc;
30156885Sakito register struct bmd_linec *bq = bp->bc_bl;
30256885Sakito
30356885Sakito bmd_erase_screen((u_long *) bp->bc_waddr); /* clear screen */
30456885Sakito
30556885Sakito bmd_reverse_char(bp->bc_raddr,
30656885Sakito bp->bc_waddr,
30756885Sakito bq->bl_col, bp->bc_row); /* turn on cursole */
30856885Sakito }
30956885Sakito
bmd_home()31057239Sakito bmd_home()
31157239Sakito {
31257239Sakito register struct bmd_softc *bp = &bmd_softc;
31357239Sakito register struct bmd_linec *bq = bp->bc_bl;
31456885Sakito
31557239Sakito bmd_reverse_char(bp->bc_raddr,
31657239Sakito bp->bc_waddr,
31757239Sakito bq->bl_col, bp->bc_row); /* turn off cursole */
31856885Sakito
31957239Sakito bq->bl_col = bq->bl_end = bp->bc_xmin;
32057239Sakito bp->bc_row = bp->bc_ymin;
32157239Sakito
32257239Sakito bmd_reverse_char(bp->bc_raddr,
32357239Sakito bp->bc_waddr,
32457239Sakito bq->bl_col, bp->bc_row); /* turn on cursole */
32556885Sakito }
32656885Sakito
32756885Sakito /*
32856885Sakito * charactor operation routines
32956885Sakito */
33056885Sakito
33156885Sakito void
bmd_draw_char(raddr,waddr,col,row,c)33256885Sakito bmd_draw_char(raddr, waddr, col, row, c)
33356885Sakito char *raddr;
33456885Sakito char *waddr;
33556885Sakito int col;
33656885Sakito int row;
33756885Sakito int c;
33856885Sakito {
33956885Sakito volatile register u_short *p, *q, *fp;
34056885Sakito volatile register u_long *lp, *lq;
34156885Sakito register int i;
34256885Sakito
34356885Sakito fp = &bmdfont[c][0];
34456885Sakito
34556885Sakito switch (col % 4) {
34656885Sakito
34756885Sakito case 0:
34856885Sakito p = (u_short *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ));
34956885Sakito q = (u_short *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ));
35056885Sakito for (i = 0; i < FB_HIGHT; i++) {
35156885Sakito *q = (*p & 0x000F) | (*fp & 0xFFF0);
35256885Sakito p += 128;
35356885Sakito q += 128;
35456885Sakito fp++;
35556885Sakito }
35656885Sakito break;
35756885Sakito
35856885Sakito case 1:
35956885Sakito lp = (u_long *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ));
36056885Sakito lq = (u_long *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ));
36156885Sakito for (i = 0; i < FB_HIGHT; i++) {
36256885Sakito *lq = (*lp & 0xFFF000FF) | ((u_long)(*fp & 0xFFF0) << 4);
36356885Sakito lp += 64;
36456885Sakito lq += 64;
36556885Sakito fp++;
36656885Sakito }
36756885Sakito break;
36856885Sakito
36956885Sakito case 2:
37056885Sakito lp = (u_long *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 2 );
37156885Sakito lq = (u_long *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 2 );
37256885Sakito for (i = 0; i < FB_HIGHT; i++) {
37356885Sakito *lq = (*lp & 0xFF000FFF) | ((u_long)(*fp & 0xFFF0) << 8);
37456885Sakito lp += 64;
37556885Sakito lq += 64;
37656885Sakito fp++;
37756885Sakito }
37856885Sakito break;
37956885Sakito
38056885Sakito case 3:
38156885Sakito p = (u_short *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 4 );
38256885Sakito q = (u_short *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 4 );
38356885Sakito for (i = 0; i < FB_HIGHT; i++) {
38456885Sakito *q = (*p & 0xF000) | ((*fp & 0xFFF0) >> 4);
38556885Sakito p += 128;
38656885Sakito q += 128;
38756885Sakito fp++;
38856885Sakito }
38956885Sakito break;
39056885Sakito
39156885Sakito default:
39256885Sakito break;
39356885Sakito }
39456885Sakito }
39556885Sakito
39656885Sakito void
bmd_reverse_char(raddr,waddr,col,row)39756885Sakito bmd_reverse_char(raddr, waddr, col, row)
39856885Sakito char *raddr;
39956885Sakito char *waddr;
40056885Sakito int col;
40156885Sakito int row;
40256885Sakito {
40356885Sakito volatile register u_short *p, *q, us;
40456885Sakito volatile register u_long *lp, *lq, ul;
40556885Sakito register int i;
40656885Sakito
40756885Sakito switch (col%4) {
40856885Sakito
40956885Sakito case 0:
41056885Sakito p = (u_short *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ));
41156885Sakito q = (u_short *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ));
41256885Sakito for (i = 0; i < FB_HIGHT; i++) {
41356885Sakito *q = (*p & 0x000F) | (~(*p) & 0xFFF0);
41456885Sakito p += 128;
41556885Sakito q += 128;
41656885Sakito }
41756885Sakito break;
41856885Sakito
41956885Sakito case 1:
42056885Sakito lp = (u_long *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ));
42156885Sakito lq = (u_long *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ));
42256885Sakito for (i = 0; i < FB_HIGHT; i++) {
42356885Sakito *lq = (*lp & 0xFFF000FF) | (~(*lp) & 0x000FFF00);
42456885Sakito lp += 64;
42556885Sakito lq += 64;
42656885Sakito }
42756885Sakito break;
42856885Sakito
42956885Sakito case 2:
43056885Sakito lp = (u_long *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 2 );
43156885Sakito lq = (u_long *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 2 );
43256885Sakito for (i = 0; i < FB_HIGHT; i++) {
43356885Sakito *lq = (*lp & 0xFF000FFF) | (~(*lp) & 0x00FFF000);
43456885Sakito lp += 64;
43556885Sakito lq += 64;
43656885Sakito }
43756885Sakito break;
43856885Sakito
43956885Sakito case 3:
44056885Sakito p = (u_short *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 4 );
44156885Sakito q = (u_short *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 4 );
44256885Sakito for (i = 0; i < FB_HIGHT; i++) {
44356885Sakito *q = (*p & 0xF000) | (~(*p) & 0x0FFF);
44456885Sakito p += 128;
44556885Sakito q += 128;
44656885Sakito }
44756885Sakito break;
44856885Sakito
44956885Sakito default:
45056885Sakito break;
45156885Sakito }
45256885Sakito }
45356885Sakito
45456885Sakito void
bmd_erase_char(raddr,waddr,col,row)45556885Sakito bmd_erase_char(raddr, waddr, col, row)
45656885Sakito char *raddr;
45756885Sakito char *waddr;
45856885Sakito int col;
45956885Sakito int row;
46056885Sakito {
46156885Sakito bmd_draw_char(raddr, waddr, col, row, 0);
46256885Sakito
46356885Sakito return;
46456885Sakito }
46556885Sakito
46656885Sakito
46756885Sakito /*
46856885Sakito * screen operation routines
46956885Sakito */
47056885Sakito
47156885Sakito void
bmd_erase_screen(lp)47256885Sakito bmd_erase_screen(lp)
47356885Sakito volatile register u_long *lp;
47456885Sakito {
47556885Sakito register int i, j;
47656885Sakito
47756885Sakito for (i = 0; i < SB_HIGHT; i++) {
47856885Sakito for (j = 0; j < SL_WIDTH; j++)
47956885Sakito *lp++ = 0;
48056885Sakito SKIP_NEXT_LINE(lp);
48156885Sakito }
48256885Sakito
48356885Sakito return;
48456885Sakito }
48556885Sakito
48656885Sakito void
bmd_scroll_screen(lp,lq,xmin,xmax,ymin,ymax)48756885Sakito bmd_scroll_screen(lp, lq, xmin, xmax, ymin, ymax)
48856885Sakito volatile register u_long *lp;
48956885Sakito volatile register u_long *lq;
49056885Sakito int xmin, xmax, ymin, ymax;
49156885Sakito {
49256885Sakito register int i, j;
49356885Sakito
49456885Sakito lp += ((PL_WIDTH * FB_HIGHT) * (ymin + 1));
49556885Sakito lq += ((PL_WIDTH * FB_HIGHT) * ymin);
49656885Sakito
49756885Sakito for (i = 0; i < ((ymax - ymin -1) * FB_HIGHT); i++) {
49856885Sakito for (j = 0; j < SL_WIDTH; j++) {
49956885Sakito *lq++ = *lp++;
50056885Sakito }
50156885Sakito lp += (PL_WIDTH - SL_WIDTH);
50256885Sakito lq += (PL_WIDTH - SL_WIDTH);
50356885Sakito }
50456885Sakito
50556885Sakito for (i = 0; i < FB_HIGHT; i++) {
50656885Sakito for (j = 0; j < SL_WIDTH; j++) {
50756885Sakito *lq++ = 0;
50856885Sakito }
50956885Sakito lq += (PL_WIDTH - SL_WIDTH);
51056885Sakito }
51156885Sakito
51256885Sakito }
51357353Sakito
51457353Sakito
51557353Sakito #ifdef BMD_PRINTF
51657353Sakito
51757353Sakito #include <machine/stdarg.h>
51857353Sakito
51957353Sakito void bmd_kprintf();
52057353Sakito static char * bmd_sprintn();
52157353Sakito
52257353Sakito void
52357353Sakito #ifdef __STDC__
bmd_printf(const char * fmt,...)52457353Sakito bmd_printf(const char *fmt, ...)
52557353Sakito #else
52657353Sakito bmd_printf(fmt, va_alist)
52757353Sakito char *fmt;
52857353Sakito #endif
52957353Sakito {
53057353Sakito va_list ap;
53157353Sakito
53257353Sakito va_start(ap, fmt);
53357353Sakito bmd_kprintf(fmt, ap);
53457353Sakito va_end(ap);
53557353Sakito }
53657353Sakito
53757353Sakito /*
53857353Sakito * Scaled down version of printf(3).
53957353Sakito *
54057353Sakito * Two additional formats:
54157353Sakito *
54257353Sakito * The format %b is supported to decode error registers.
54357353Sakito * Its usage is:
54457353Sakito *
54557353Sakito * printf("reg=%b\n", regval, "<base><arg>*");
54657353Sakito *
54757353Sakito * where <base> is the output base expressed as a control character, e.g.
54857353Sakito * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
54957353Sakito * the first of which gives the bit number to be inspected (origin 1), and
55057353Sakito * the next characters (up to a control character, i.e. a character <= 32),
55157353Sakito * give the name of the register. Thus:
55257353Sakito *
55357353Sakito * kprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
55457353Sakito *
55557353Sakito * would produce output:
55657353Sakito *
55757353Sakito * reg=3<BITTWO,BITONE>
55857353Sakito *
55957353Sakito * The format %r passes an additional format string and argument list
56057353Sakito * recursively. Its usage is:
56157353Sakito *
56257353Sakito * fn(char *fmt, ...)
56357353Sakito * {
56457353Sakito * va_list ap;
56557353Sakito * va_start(ap, fmt);
56657353Sakito * printf("prefix: %r: suffix\n", fmt, ap);
56757353Sakito * va_end(ap);
56857353Sakito * }
56957353Sakito *
57057353Sakito * Space or zero padding and a field width are supported for the numeric
57157353Sakito * formats only.
57257353Sakito */
57357353Sakito void
bmd_kprintf(fmt,ap)57457353Sakito bmd_kprintf(fmt, ap)
57557353Sakito register const char *fmt;
57657353Sakito va_list ap;
57757353Sakito {
57857353Sakito register char *p, *q;
57957353Sakito register int ch, n;
58057353Sakito u_long ul;
58157353Sakito int base, lflag, tmp, width;
58257353Sakito char padc;
58357353Sakito
58457353Sakito for (;;) {
58557353Sakito padc = ' ';
58657353Sakito width = 0;
58757353Sakito while ((ch = *(u_char *)fmt++) != '%') {
58857353Sakito if (ch == '\0')
58957353Sakito return;
59057353Sakito if (ch == '\n')
59157353Sakito bmdputc('\r');
59257353Sakito bmdputc(ch);
59357353Sakito }
59457353Sakito lflag = 0;
59557353Sakito reswitch: switch (ch = *(u_char *)fmt++) {
59657353Sakito case '0':
59757353Sakito padc = '0';
59857353Sakito goto reswitch;
59957353Sakito case '1': case '2': case '3': case '4':
60057353Sakito case '5': case '6': case '7': case '8': case '9':
60157353Sakito for (width = 0;; ++fmt) {
60257353Sakito width = width * 10 + ch - '0';
60357353Sakito ch = *fmt;
60457353Sakito if (ch < '0' || ch > '9')
60557353Sakito break;
60657353Sakito }
60757353Sakito goto reswitch;
60857353Sakito case 'l':
60957353Sakito lflag = 1;
61057353Sakito goto reswitch;
61157353Sakito case 'b':
61257353Sakito ul = va_arg(ap, int);
61357353Sakito p = va_arg(ap, char *);
61457353Sakito for (q = bmd_sprintn(ul, *p++, NULL); ch = *q--;)
61557353Sakito bmdputc(ch);
61657353Sakito
61757353Sakito if (!ul)
61857353Sakito break;
61957353Sakito
62057353Sakito for (tmp = 0; n = *p++;) {
62157353Sakito if (ul & (1 << (n - 1))) {
62257353Sakito bmdputc(tmp ? ',' : '<');
62357353Sakito for (; (n = *p) > ' '; ++p)
62457353Sakito bmdputc(n);
62557353Sakito tmp = 1;
62657353Sakito } else
62757353Sakito for (; *p > ' '; ++p)
62857353Sakito continue;
62957353Sakito }
63057353Sakito if (tmp)
63157353Sakito bmdputc('>');
63257353Sakito break;
63357353Sakito case 'c':
63457353Sakito bmdputc(va_arg(ap, int));
63557353Sakito break;
63657353Sakito case 'r':
63757353Sakito p = va_arg(ap, char *);
63857353Sakito bmd_kprintf(p, va_arg(ap, va_list));
63957353Sakito break;
64057353Sakito case 's':
64157353Sakito p = va_arg(ap, char *);
64257353Sakito while (ch = *p++)
64357353Sakito bmdputc(ch);
64457353Sakito break;
64557353Sakito case 'd':
64657353Sakito ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
64757353Sakito if ((long)ul < 0) {
64857353Sakito bmdputc('-');
64957353Sakito ul = -(long)ul;
65057353Sakito }
65157353Sakito base = 10;
65257353Sakito goto number;
65357353Sakito case 'o':
65457353Sakito ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
65557353Sakito base = 8;
65657353Sakito goto number;
65757353Sakito case 'u':
65857353Sakito ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
65957353Sakito base = 10;
66057353Sakito goto number;
66157353Sakito case 'x':
66257353Sakito ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
66357353Sakito base = 16;
66457353Sakito number: p = bmd_sprintn(ul, base, &tmp);
66557353Sakito if (width && (width -= tmp) > 0)
66657353Sakito while (width--)
66757353Sakito bmdputc(padc);
66857353Sakito while (ch = *p--)
66957353Sakito bmdputc(ch);
67057353Sakito break;
67157353Sakito default:
67257353Sakito bmdputc('%');
67357353Sakito if (lflag)
67457353Sakito bmdputc('l');
67557353Sakito /* FALLTHROUGH */
67657353Sakito case '%':
67757353Sakito bmdputc(ch);
67857353Sakito }
67957353Sakito }
68057353Sakito }
68157353Sakito
68257353Sakito /*
68357353Sakito * Put a number (base <= 16) in a buffer in reverse order; return an
68457353Sakito * optional length and a pointer to the NULL terminated (preceded?)
68557353Sakito * buffer.
68657353Sakito */
68757353Sakito static char *
bmd_sprintn(ul,base,lenp)68857353Sakito bmd_sprintn(ul, base, lenp)
68957353Sakito register u_long ul;
69057353Sakito register int base, *lenp;
69157353Sakito { /* A long in base 8, plus NULL. */
69257353Sakito static char buf[sizeof(long) * NBBY / 3 + 2];
69357353Sakito register char *p;
69457353Sakito
69557353Sakito p = buf;
69657353Sakito do {
69757353Sakito *++p = "0123456789abcdef"[ul % base];
69857353Sakito } while (ul /= base);
69957353Sakito if (lenp)
70057353Sakito *lenp = p - buf;
70157353Sakito return (p);
70257353Sakito }
70357353Sakito #endif
704