xref: /onnv-gate/usr/src/lib/efcode/fcdriver/misc.c (revision 762:bac9c2e4aa76)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
23*762Sdhain  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*762Sdhain  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #include <stdio.h>
300Sstevel@tonic-gate #include <stdlib.h>
310Sstevel@tonic-gate #include <strings.h>
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #include <fcode/private.h>
340Sstevel@tonic-gate #include <fcode/log.h>
350Sstevel@tonic-gate 
360Sstevel@tonic-gate #include <fcdriver/fcdriver.h>
370Sstevel@tonic-gate 
380Sstevel@tonic-gate static fc_cell_t
fc_reg_read(fcode_env_t * env,char * service,fstack_t virt,int * errp)390Sstevel@tonic-gate fc_reg_read(fcode_env_t *env, char *service, fstack_t virt, int *errp)
400Sstevel@tonic-gate {
410Sstevel@tonic-gate 	fc_cell_t virtaddr, data;
420Sstevel@tonic-gate 	int error, nin;
430Sstevel@tonic-gate 
440Sstevel@tonic-gate 	if (!is_mcookie(virt))
450Sstevel@tonic-gate 		forth_abort(env, "fc_reg_read: bad mcookie: 0x%x\n", virt);
460Sstevel@tonic-gate 
470Sstevel@tonic-gate 	virtaddr = mcookie_to_addr(virt);
480Sstevel@tonic-gate 
490Sstevel@tonic-gate 	/* Supress fc_run_priv error msgs on peeks */
500Sstevel@tonic-gate 	nin = ((errp == NULL) ? 1 : (1 | FCRP_NOERROR));
510Sstevel@tonic-gate 
520Sstevel@tonic-gate 	error = fc_run_priv(env->private, service, nin, 1, virtaddr, &data);
530Sstevel@tonic-gate 	if (errp)
540Sstevel@tonic-gate 		/* Don't report error on peeks */
550Sstevel@tonic-gate 		*errp = error;
560Sstevel@tonic-gate 	else if (error) {
57*762Sdhain 		forth_abort(env, "fc_read_reg: ERROR: cookie: %llx"
580Sstevel@tonic-gate 		    " virt: %llx\n", (uint64_t)virt, (uint64_t)virtaddr);
590Sstevel@tonic-gate 	}
600Sstevel@tonic-gate 	return (data);
610Sstevel@tonic-gate }
620Sstevel@tonic-gate 
630Sstevel@tonic-gate static void
fc_reg_write(fcode_env_t * env,char * service,fstack_t virt,fc_cell_t data,int * errp)640Sstevel@tonic-gate fc_reg_write(fcode_env_t *env, char *service, fstack_t virt, fc_cell_t data,
650Sstevel@tonic-gate     int *errp)
660Sstevel@tonic-gate {
670Sstevel@tonic-gate 	fc_cell_t virtaddr;
680Sstevel@tonic-gate 	int error, nin;
690Sstevel@tonic-gate 
700Sstevel@tonic-gate 	if (!is_mcookie(virt))
710Sstevel@tonic-gate 		forth_abort(env, "fc_reg_write: bad mcookie: 0x%x\n", virt);
720Sstevel@tonic-gate 
730Sstevel@tonic-gate 	virtaddr = mcookie_to_addr(virt);
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 	/* Supress fc_run_priv error msgs on pokes */
760Sstevel@tonic-gate 	nin = ((errp == NULL) ? 2 : (2 | FCRP_NOERROR));
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 	error = fc_run_priv(env->private, service, nin, 0, virtaddr, data);
790Sstevel@tonic-gate 	if (errp)
800Sstevel@tonic-gate 		/* Don't report error on pokes */
810Sstevel@tonic-gate 		*errp = error;
820Sstevel@tonic-gate 	else if (error) {
83*762Sdhain 		forth_abort(env, "fc_write_reg: ERROR: cookie: %llx"
840Sstevel@tonic-gate 		    " virt: %llx\n", (uint64_t)virt, (uint64_t)virtaddr);
850Sstevel@tonic-gate 	}
860Sstevel@tonic-gate }
870Sstevel@tonic-gate 
880Sstevel@tonic-gate static int
check_address_abuse(fcode_env_t * env,fstack_t addr,char * type,int want_mcookie,void (* alt)(fcode_env_t *))890Sstevel@tonic-gate check_address_abuse(fcode_env_t *env, fstack_t addr, char *type,
900Sstevel@tonic-gate     int want_mcookie, void (*alt)(fcode_env_t *))
910Sstevel@tonic-gate {
920Sstevel@tonic-gate 	if (is_mcookie(addr) != want_mcookie) {
930Sstevel@tonic-gate 		debug_msg(DEBUG_ADDR_ABUSE, "Warning: %s to %s address: %llx\n",
940Sstevel@tonic-gate 		    type, want_mcookie ? "unmapped" : "mapped",
950Sstevel@tonic-gate 		    (uint64_t)addr);
960Sstevel@tonic-gate 		(*alt)(env);
970Sstevel@tonic-gate 		return (1);
980Sstevel@tonic-gate 	}
990Sstevel@tonic-gate 	return (0);
1000Sstevel@tonic-gate }
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate static void
rlfetch(fcode_env_t * env)1030Sstevel@tonic-gate rlfetch(fcode_env_t *env)
1040Sstevel@tonic-gate {
1050Sstevel@tonic-gate 	fstack_t p;
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate 	CHECK_DEPTH(env, 1, "rl@");
1080Sstevel@tonic-gate 	p = TOS;
1090Sstevel@tonic-gate 	if (!check_address_abuse(env, p, "rl@", 1, lfetch))
1100Sstevel@tonic-gate 		TOS = (lforth_t)fc_reg_read(env, "rl@", p, NULL);
1110Sstevel@tonic-gate }
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate static void
rlstore(fcode_env_t * env)1140Sstevel@tonic-gate rlstore(fcode_env_t *env)
1150Sstevel@tonic-gate {
1160Sstevel@tonic-gate 	fstack_t p, d;
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "rl!");
1190Sstevel@tonic-gate 	p = TOS;
1200Sstevel@tonic-gate 	if (!check_address_abuse(env, p, "rl!", 1, lstore)) {
1210Sstevel@tonic-gate 		p = POP(DS);
1220Sstevel@tonic-gate 		d = POP(DS);
1230Sstevel@tonic-gate 		fc_reg_write(env, "rl!", p, d, NULL);
1240Sstevel@tonic-gate 	}
1250Sstevel@tonic-gate }
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate static void
rwfetch(fcode_env_t * env)1280Sstevel@tonic-gate rwfetch(fcode_env_t *env)
1290Sstevel@tonic-gate {
1300Sstevel@tonic-gate 	fstack_t p;
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 	CHECK_DEPTH(env, 1, "rw@");
1330Sstevel@tonic-gate 	p = TOS;
1340Sstevel@tonic-gate 	if (!check_address_abuse(env, p, "rw@", 1, wfetch))
1350Sstevel@tonic-gate 		TOS = (wforth_t)fc_reg_read(env, "rw@", p, NULL);
1360Sstevel@tonic-gate }
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate static void
rwstore(fcode_env_t * env)1390Sstevel@tonic-gate rwstore(fcode_env_t *env)
1400Sstevel@tonic-gate {
1410Sstevel@tonic-gate 	fstack_t p, d;
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "rw!");
1440Sstevel@tonic-gate 	p = TOS;
1450Sstevel@tonic-gate 	if (!check_address_abuse(env, p, "rw!", 1, wstore)) {
1460Sstevel@tonic-gate 		p = POP(DS);
1470Sstevel@tonic-gate 		d = POP(DS);
1480Sstevel@tonic-gate 		fc_reg_write(env, "rw!", p, d, NULL);
1490Sstevel@tonic-gate 	}
1500Sstevel@tonic-gate }
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate void
rbfetch(fcode_env_t * env)1530Sstevel@tonic-gate rbfetch(fcode_env_t *env)
1540Sstevel@tonic-gate {
1550Sstevel@tonic-gate 	fstack_t p;
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	CHECK_DEPTH(env, 1, "rb@");
1580Sstevel@tonic-gate 	p = TOS;
1590Sstevel@tonic-gate 	if (!check_address_abuse(env, p, "rb@", 1, cfetch)) {
1600Sstevel@tonic-gate 		TOS = (uchar_t)fc_reg_read(env, "rb@", p, NULL);
1610Sstevel@tonic-gate 	}
1620Sstevel@tonic-gate }
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate static void
rbstore(fcode_env_t * env)1650Sstevel@tonic-gate rbstore(fcode_env_t *env)
1660Sstevel@tonic-gate {
1670Sstevel@tonic-gate 	fstack_t	p, d;
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "rb!");
1700Sstevel@tonic-gate 	p = TOS;
1710Sstevel@tonic-gate 	if (!check_address_abuse(env, p, "rb!", 1, cstore)) {
1720Sstevel@tonic-gate 		p = POP(DS);
1730Sstevel@tonic-gate 		d = POP(DS);
1740Sstevel@tonic-gate 		fc_reg_write(env, "rb!", p, d, NULL);
1750Sstevel@tonic-gate 	}
1760Sstevel@tonic-gate }
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate /*
1790Sstevel@tonic-gate  * rx@        ( xa -- xv )
1800Sstevel@tonic-gate  */
1810Sstevel@tonic-gate static void
rxfetch(fcode_env_t * env)1820Sstevel@tonic-gate rxfetch(fcode_env_t *env)
1830Sstevel@tonic-gate {
1840Sstevel@tonic-gate 	fstack_t p;
1850Sstevel@tonic-gate 	xforth_t x;
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 	CHECK_DEPTH(env, 1, "rx@");
1880Sstevel@tonic-gate 	p = TOS;
1890Sstevel@tonic-gate 	if (!check_address_abuse(env, p, "rx@", 1, xfetch)) {
1900Sstevel@tonic-gate 		p = POP(DS);
1910Sstevel@tonic-gate 		push_xforth(env, (xforth_t)fc_reg_read(env, "rx@", p, NULL));
1920Sstevel@tonic-gate 	}
1930Sstevel@tonic-gate }
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate /*
1960Sstevel@tonic-gate  * rx!        ( xv xa -- )
1970Sstevel@tonic-gate  */
1980Sstevel@tonic-gate static void
rxstore(fcode_env_t * env)1990Sstevel@tonic-gate rxstore(fcode_env_t *env)
2000Sstevel@tonic-gate {
2010Sstevel@tonic-gate 	fstack_t p;
2020Sstevel@tonic-gate 	xforth_t d;
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "rx!");
2050Sstevel@tonic-gate 	p = TOS;
2060Sstevel@tonic-gate 	if (!check_address_abuse(env, p, "rx!", 1, xstore)) {
2070Sstevel@tonic-gate 		p = POP(DS);
2080Sstevel@tonic-gate 		d = pop_xforth(env);
2090Sstevel@tonic-gate 		fc_reg_write(env, "rx!", p, d, NULL);
2100Sstevel@tonic-gate 	}
2110Sstevel@tonic-gate }
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate static void
lpeek(fcode_env_t * env)2140Sstevel@tonic-gate lpeek(fcode_env_t *env)
2150Sstevel@tonic-gate {
2160Sstevel@tonic-gate 	fstack_t p;
2170Sstevel@tonic-gate 	lforth_t r;
2180Sstevel@tonic-gate 	int error;
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	CHECK_DEPTH(env, 1, "lpeek");
2210Sstevel@tonic-gate 	p = POP(DS);
2220Sstevel@tonic-gate 	r = (lforth_t)fc_reg_read(env, "rl@", p, &error);
2230Sstevel@tonic-gate 	if (error)
2240Sstevel@tonic-gate 		PUSH(DS, FALSE);
2250Sstevel@tonic-gate 	else {
2260Sstevel@tonic-gate 		PUSH(DS, r);
2270Sstevel@tonic-gate 		PUSH(DS, TRUE);
2280Sstevel@tonic-gate 	}
2290Sstevel@tonic-gate }
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate static void
lpoke(fcode_env_t * env)2320Sstevel@tonic-gate lpoke(fcode_env_t *env)
2330Sstevel@tonic-gate {
2340Sstevel@tonic-gate 	fstack_t p, d;
2350Sstevel@tonic-gate 	int error;
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "lpoke");
2380Sstevel@tonic-gate 	p = POP(DS);
2390Sstevel@tonic-gate 	d = POP(DS);
2400Sstevel@tonic-gate 	fc_reg_write(env, "rl!", p, d, &error);
2410Sstevel@tonic-gate 	PUSH(DS, error ? FALSE : TRUE);
2420Sstevel@tonic-gate }
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate static void
wpeek(fcode_env_t * env)2450Sstevel@tonic-gate wpeek(fcode_env_t *env)
2460Sstevel@tonic-gate {
2470Sstevel@tonic-gate 	fstack_t p;
2480Sstevel@tonic-gate 	int error;
2490Sstevel@tonic-gate 	wforth_t r;
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 	CHECK_DEPTH(env, 1, "wpeek");
2520Sstevel@tonic-gate 	p = POP(DS);
2530Sstevel@tonic-gate 	r = (wforth_t)fc_reg_read(env, "rw@", p, &error);
2540Sstevel@tonic-gate 	if (error)
2550Sstevel@tonic-gate 		PUSH(DS, FALSE);
2560Sstevel@tonic-gate 	else {
2570Sstevel@tonic-gate 		PUSH(DS, r);
2580Sstevel@tonic-gate 		PUSH(DS, TRUE);
2590Sstevel@tonic-gate 	}
2600Sstevel@tonic-gate }
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate static void
wpoke(fcode_env_t * env)2630Sstevel@tonic-gate wpoke(fcode_env_t *env)
2640Sstevel@tonic-gate {
2650Sstevel@tonic-gate 	fstack_t p, d;
2660Sstevel@tonic-gate 	int error;
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "wpoke");
2690Sstevel@tonic-gate 	p = POP(DS);
2700Sstevel@tonic-gate 	d = POP(DS);
2710Sstevel@tonic-gate 	fc_reg_write(env, "rw!", p, d, &error);
2720Sstevel@tonic-gate 	PUSH(DS, error ? FALSE : TRUE);
2730Sstevel@tonic-gate }
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate static void
cpeek(fcode_env_t * env)2760Sstevel@tonic-gate cpeek(fcode_env_t *env)
2770Sstevel@tonic-gate {
2780Sstevel@tonic-gate 	fstack_t	p;
2790Sstevel@tonic-gate 	uchar_t r;
2800Sstevel@tonic-gate 	int error;
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate 	CHECK_DEPTH(env, 1, "cpeek");
2830Sstevel@tonic-gate 	p = POP(DS);
2840Sstevel@tonic-gate 	r = (uchar_t)fc_reg_read(env, "rb@", p, &error);
2850Sstevel@tonic-gate 	if (error)
2860Sstevel@tonic-gate 		PUSH(DS, FALSE);
2870Sstevel@tonic-gate 	else {
2880Sstevel@tonic-gate 		PUSH(DS, r);
2890Sstevel@tonic-gate 		PUSH(DS, TRUE);
2900Sstevel@tonic-gate 	}
2910Sstevel@tonic-gate }
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate static void
cpoke(fcode_env_t * env)2940Sstevel@tonic-gate cpoke(fcode_env_t *env)
2950Sstevel@tonic-gate {
2960Sstevel@tonic-gate 	fstack_t	p, d;
2970Sstevel@tonic-gate 	int error;
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "cpoke");
3000Sstevel@tonic-gate 	p = POP(DS);
3010Sstevel@tonic-gate 	d = POP(DS);
3020Sstevel@tonic-gate 	fc_reg_write(env, "rb!", p, d, &error);
3030Sstevel@tonic-gate 	PUSH(DS, error ? FALSE : TRUE);
3040Sstevel@tonic-gate }
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate /*
3070Sstevel@tonic-gate  * fcdriver version of cfetch, replaces base 'c@'
3080Sstevel@tonic-gate  */
3090Sstevel@tonic-gate static void
fcd_cfetch(fcode_env_t * env)3100Sstevel@tonic-gate fcd_cfetch(fcode_env_t *env)
3110Sstevel@tonic-gate {
3120Sstevel@tonic-gate 	fstack_t addr = TOS;
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	CHECK_DEPTH(env, 1, "c@");
3150Sstevel@tonic-gate 	if (!check_address_abuse(env, addr, "c@", 0, rbfetch))
3160Sstevel@tonic-gate 		cfetch(env);
3170Sstevel@tonic-gate }
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate /*
3200Sstevel@tonic-gate  * fcdriver version of cstore, replaces base 'c!'
3210Sstevel@tonic-gate  */
3220Sstevel@tonic-gate static void
fcd_cstore(fcode_env_t * env)3230Sstevel@tonic-gate fcd_cstore(fcode_env_t *env)
3240Sstevel@tonic-gate {
3250Sstevel@tonic-gate 	fstack_t addr = TOS;
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "c!");
3280Sstevel@tonic-gate 	if (!check_address_abuse(env, addr, "c!", 0, rbstore))
3290Sstevel@tonic-gate 		cstore(env);
3300Sstevel@tonic-gate }
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate /*
3330Sstevel@tonic-gate  * fcdriver version of wfetch, replaces base 'w@'
3340Sstevel@tonic-gate  */
3350Sstevel@tonic-gate static void
fcd_wfetch(fcode_env_t * env)3360Sstevel@tonic-gate fcd_wfetch(fcode_env_t *env)
3370Sstevel@tonic-gate {
3380Sstevel@tonic-gate 	fstack_t addr = TOS;
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate 	CHECK_DEPTH(env, 1, "w@");
3410Sstevel@tonic-gate 	if (!check_address_abuse(env, addr, "w@", 0, rwfetch))
3420Sstevel@tonic-gate 		wfetch(env);
3430Sstevel@tonic-gate }
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate /*
3460Sstevel@tonic-gate  * fcdriver version of wstore, replaces base 'w!'
3470Sstevel@tonic-gate  */
3480Sstevel@tonic-gate static void
fcd_wstore(fcode_env_t * env)3490Sstevel@tonic-gate fcd_wstore(fcode_env_t *env)
3500Sstevel@tonic-gate {
3510Sstevel@tonic-gate 	fstack_t addr = TOS;
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "w!");
3540Sstevel@tonic-gate 	if (!check_address_abuse(env, addr, "w!", 0, rwstore))
3550Sstevel@tonic-gate 		wstore(env);
3560Sstevel@tonic-gate }
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate /*
3590Sstevel@tonic-gate  * fcdriver version of lfetch, replaces base 'l@'
3600Sstevel@tonic-gate  */
3610Sstevel@tonic-gate static void
fcd_lfetch(fcode_env_t * env)3620Sstevel@tonic-gate fcd_lfetch(fcode_env_t *env)
3630Sstevel@tonic-gate {
3640Sstevel@tonic-gate 	fstack_t addr = TOS;
3650Sstevel@tonic-gate 
3660Sstevel@tonic-gate 	CHECK_DEPTH(env, 1, "l@");
3670Sstevel@tonic-gate 	if (!check_address_abuse(env, addr, "l@", 0, rlfetch))
3680Sstevel@tonic-gate 		lfetch(env);
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate /*
3720Sstevel@tonic-gate  * fcdriver version of lstore, replaces base 'l!'
3730Sstevel@tonic-gate  */
3740Sstevel@tonic-gate static void
fcd_lstore(fcode_env_t * env)3750Sstevel@tonic-gate fcd_lstore(fcode_env_t *env)
3760Sstevel@tonic-gate {
3770Sstevel@tonic-gate 	fstack_t addr = TOS;
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "l!");
3800Sstevel@tonic-gate 	if (!check_address_abuse(env, addr, "l!", 0, rlstore))
3810Sstevel@tonic-gate 		lstore(env);
3820Sstevel@tonic-gate }
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate /*
3850Sstevel@tonic-gate  * fcdriver version of xfetch, replaces base 'x@'
3860Sstevel@tonic-gate  */
3870Sstevel@tonic-gate static void
fcd_xfetch(fcode_env_t * env)3880Sstevel@tonic-gate fcd_xfetch(fcode_env_t *env)
3890Sstevel@tonic-gate {
3900Sstevel@tonic-gate 	fstack_t addr = TOS;
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate 	CHECK_DEPTH(env, 1, "x@");
3930Sstevel@tonic-gate 	if (!check_address_abuse(env, addr, "x@", 0, rxfetch))
3940Sstevel@tonic-gate 		xfetch(env);
3950Sstevel@tonic-gate }
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate /*
3980Sstevel@tonic-gate  * fcdriver version of xstore, replaces base 'x!'
3990Sstevel@tonic-gate  */
4000Sstevel@tonic-gate static void
fcd_xstore(fcode_env_t * env)4010Sstevel@tonic-gate fcd_xstore(fcode_env_t *env)
4020Sstevel@tonic-gate {
4030Sstevel@tonic-gate 	fstack_t addr = TOS;
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "x!");
4060Sstevel@tonic-gate 	if (!check_address_abuse(env, addr, "x!", 0, rxstore))
4070Sstevel@tonic-gate 		xstore(env);
4080Sstevel@tonic-gate }
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate /*
4110Sstevel@tonic-gate  * fcdriver version of move, replaces base 'move'
4120Sstevel@tonic-gate  */
4130Sstevel@tonic-gate static void
fcd_move(fcode_env_t * env)4140Sstevel@tonic-gate fcd_move(fcode_env_t *env)
4150Sstevel@tonic-gate {
4160Sstevel@tonic-gate 	size_t len;
4170Sstevel@tonic-gate 	uchar_t *destaddr, *srcaddr;
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 	CHECK_DEPTH(env, 3, "move");
4200Sstevel@tonic-gate 	len = POP(DS);
4210Sstevel@tonic-gate 	destaddr = ((uchar_t *)POP(DS));
4220Sstevel@tonic-gate 	srcaddr = ((uchar_t *)POP(DS));
4230Sstevel@tonic-gate 	for (; len > 0; len--, srcaddr++, destaddr++) {
4240Sstevel@tonic-gate 		PUSH(DS, (fstack_t)srcaddr);
4250Sstevel@tonic-gate 		fcd_cfetch(env);
4260Sstevel@tonic-gate 		PUSH(DS, (fstack_t)destaddr);
4270Sstevel@tonic-gate 		fcd_cstore(env);
4280Sstevel@tonic-gate 	}
4290Sstevel@tonic-gate }
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate static void
fcd_comp(fcode_env_t * env)4320Sstevel@tonic-gate fcd_comp(fcode_env_t *env)
4330Sstevel@tonic-gate {
4340Sstevel@tonic-gate 	char *str1, *str2, byte1, byte2;
4350Sstevel@tonic-gate 	size_t len;
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate 	CHECK_DEPTH(env, 3, "comp");
4380Sstevel@tonic-gate 	len  = (size_t)POP(DS);
4390Sstevel@tonic-gate 	str1 = (char *)POP(DS);
4400Sstevel@tonic-gate 	str2 = (char *)POP(DS);
4410Sstevel@tonic-gate 	for (; len > 0; len--, str1++, str2++) {
4420Sstevel@tonic-gate 		PUSH(DS, (fstack_t)str1);
4430Sstevel@tonic-gate 		fcd_cfetch(env);
4440Sstevel@tonic-gate 		byte1 = POP(DS);
4450Sstevel@tonic-gate 		PUSH(DS, (fstack_t)str2);
4460Sstevel@tonic-gate 		fcd_cfetch(env);
4470Sstevel@tonic-gate 		byte2 = POP(DS);
4480Sstevel@tonic-gate 		if (byte1 > byte2) {
4490Sstevel@tonic-gate 			PUSH(DS, -1);
4500Sstevel@tonic-gate 			return;
4510Sstevel@tonic-gate 		}
4520Sstevel@tonic-gate 		if (byte1 < byte2) {
4530Sstevel@tonic-gate 			PUSH(DS, 1);
4540Sstevel@tonic-gate 			return;
4550Sstevel@tonic-gate 		}
4560Sstevel@tonic-gate 	}
4570Sstevel@tonic-gate 	PUSH(DS, 0);
4580Sstevel@tonic-gate }
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate char *
get_eeprom_value(fcode_env_t * env,char * name)4610Sstevel@tonic-gate get_eeprom_value(fcode_env_t *env, char *name)
4620Sstevel@tonic-gate {
4630Sstevel@tonic-gate 	FILE *fd;
4640Sstevel@tonic-gate 	char buf[80], *p;
4650Sstevel@tonic-gate 
4660Sstevel@tonic-gate 	sprintf(buf, "eeprom '%s'", name);
4670Sstevel@tonic-gate 	if ((fd = popen(buf, "r")) == NULL)
4680Sstevel@tonic-gate 		return (NULL);
4690Sstevel@tonic-gate 	fgets(buf, sizeof (buf), fd);
4700Sstevel@tonic-gate 	pclose(fd);
4710Sstevel@tonic-gate 	if ((p = strchr(buf, '\n')) != NULL)
4720Sstevel@tonic-gate 		*p = '\0';
4730Sstevel@tonic-gate 	if ((p = strchr(buf, '=')) != NULL)
4740Sstevel@tonic-gate 		return (p + 1);
4750Sstevel@tonic-gate 	return (NULL);
4760Sstevel@tonic-gate }
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate static void
local_mac_address(fcode_env_t * env)4790Sstevel@tonic-gate local_mac_address(fcode_env_t *env)
4800Sstevel@tonic-gate {
4810Sstevel@tonic-gate 	char *mac_str;
4820Sstevel@tonic-gate 	int mac_value;
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate 	mac_str = get_eeprom_value(env, "local-mac-address?");
4850Sstevel@tonic-gate 	if (mac_str != NULL && strcmp(mac_str, "true") == 0)
4860Sstevel@tonic-gate 		mac_value = TRUE;
4870Sstevel@tonic-gate 	else
4880Sstevel@tonic-gate 		mac_value = FALSE;
4890Sstevel@tonic-gate 	PUSH(DS, mac_value);
4900Sstevel@tonic-gate }
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate /*
4930Sstevel@tonic-gate  * Allow for programmatic over-ride of 'mac-address'
4940Sstevel@tonic-gate  */
4950Sstevel@tonic-gate #define	MAC_ADDR_SIZE	6
4960Sstevel@tonic-gate static char *mac_addr;
4970Sstevel@tonic-gate static int mac_addr_is_valid;
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate void
set_mac_address(char * macaddr)5000Sstevel@tonic-gate set_mac_address(char *macaddr)
5010Sstevel@tonic-gate {
5020Sstevel@tonic-gate 	mac_addr_is_valid = 1;
5030Sstevel@tonic-gate 	memcpy(mac_addr, macaddr, MAC_ADDR_SIZE);
5040Sstevel@tonic-gate }
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate void
push_mac_address(fcode_env_t * env)5070Sstevel@tonic-gate push_mac_address(fcode_env_t *env)
5080Sstevel@tonic-gate {
5090Sstevel@tonic-gate 	PUSH(DS, (fstack_t)mac_addr);
5100Sstevel@tonic-gate 	PUSH(DS, MAC_ADDR_SIZE);
5110Sstevel@tonic-gate }
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate /*
5140Sstevel@tonic-gate  * Does driver call to get this.
5150Sstevel@tonic-gate  */
5160Sstevel@tonic-gate static void
local_ether_addr(fcode_env_t * env)5170Sstevel@tonic-gate local_ether_addr(fcode_env_t *env)
5180Sstevel@tonic-gate {
5190Sstevel@tonic-gate 	static fc_cell_t *mac_add;
5200Sstevel@tonic-gate 	int error;
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate 	mac_add = MALLOC(sizeof (fc_cell_t) * 2);
5230Sstevel@tonic-gate 	error = fc_run_priv(env->private, "local-ether-addr", 0, 2, &mac_add[0],
5240Sstevel@tonic-gate 	    &mac_add[1]);
5250Sstevel@tonic-gate 	if (error) {
5260Sstevel@tonic-gate 		bzero(mac_add, sizeof (mac_add));
5270Sstevel@tonic-gate 	}
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate 	PUSH(DS, (fstack_t)&mac_add[0]);
5300Sstevel@tonic-gate 	PUSH(DS, 6);
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate /*
5340Sstevel@tonic-gate  * 'mac-address' - complicated by 'local-mac-address' stuff.
5350Sstevel@tonic-gate  */
5360Sstevel@tonic-gate static void
mac_address(fcode_env_t * env)5370Sstevel@tonic-gate mac_address(fcode_env_t *env)
5380Sstevel@tonic-gate {
5390Sstevel@tonic-gate 	fstack_t d;
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 	if (mac_addr_is_valid) {
5420Sstevel@tonic-gate 		push_mac_address(env);
5430Sstevel@tonic-gate 		return;
5440Sstevel@tonic-gate 	}
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate 	/*
5470Sstevel@tonic-gate 	 * From here, we essentially re-implement OBP's 'mac-address' word.
5480Sstevel@tonic-gate 	 * on some platforms, this may need to be re-implemented.
5490Sstevel@tonic-gate 	 */
5500Sstevel@tonic-gate 	local_mac_address(env);
5510Sstevel@tonic-gate 	d = POP(DS);
5520Sstevel@tonic-gate 	if (d) {
5530Sstevel@tonic-gate 		push_a_string(env, "local-mac-address");
5540Sstevel@tonic-gate 		get_inherited_prop(env);
5550Sstevel@tonic-gate 		d = POP(DS);
5560Sstevel@tonic-gate 		if (d == FALSE && TOS == 6)
5570Sstevel@tonic-gate 			return;
5580Sstevel@tonic-gate 		two_drop(env);
5590Sstevel@tonic-gate 	}
5600Sstevel@tonic-gate 	local_ether_addr(env);
5610Sstevel@tonic-gate }
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate /*
5640Sstevel@tonic-gate  * Allow for the programmatic setting of diagnostic-mode?
5650Sstevel@tonic-gate  */
5660Sstevel@tonic-gate static int diag_mode_is_valid = 0;
5670Sstevel@tonic-gate static int diag_mode = 0;
5680Sstevel@tonic-gate 
5690Sstevel@tonic-gate void
set_diagnostic_mode(fcode_env_t * env)5700Sstevel@tonic-gate set_diagnostic_mode(fcode_env_t *env)
5710Sstevel@tonic-gate {
5720Sstevel@tonic-gate 	fstack_t d = POP(DS);
5730Sstevel@tonic-gate 
5740Sstevel@tonic-gate 	diag_mode = d;
5750Sstevel@tonic-gate 	diag_mode_is_valid = 1;
5760Sstevel@tonic-gate }
5770Sstevel@tonic-gate 
5780Sstevel@tonic-gate void
push_diagnostic_mode(fcode_env_t * env)5790Sstevel@tonic-gate push_diagnostic_mode(fcode_env_t *env)
5800Sstevel@tonic-gate {
5810Sstevel@tonic-gate 	PUSH(DS, (fstack_t)diag_mode);
5820Sstevel@tonic-gate }
5830Sstevel@tonic-gate 
5840Sstevel@tonic-gate /*
5850Sstevel@tonic-gate  * 'diagnostic-mode?' - diagnostic-mode? is equivalent to NVRAM 'diag-switch?'
5860Sstevel@tonic-gate  */
5870Sstevel@tonic-gate static void
diagnostic_mode(fcode_env_t * env)5880Sstevel@tonic-gate diagnostic_mode(fcode_env_t *env)
5890Sstevel@tonic-gate {
5900Sstevel@tonic-gate 	char *diag_str;
5910Sstevel@tonic-gate 	int diag_value;
5920Sstevel@tonic-gate 
5930Sstevel@tonic-gate 	if (!diag_mode_is_valid) {
5940Sstevel@tonic-gate 		diag_str = get_eeprom_value(env, "diag-switch?");
5950Sstevel@tonic-gate 		if (diag_str != NULL && strcmp(diag_str, "false") == 0)
5960Sstevel@tonic-gate 			diag_value = FALSE;
5970Sstevel@tonic-gate 		else
5980Sstevel@tonic-gate 			diag_value = TRUE;
5990Sstevel@tonic-gate 		PUSH(DS, diag_value);
6000Sstevel@tonic-gate 		set_diagnostic_mode(env);
6010Sstevel@tonic-gate 	}
6020Sstevel@tonic-gate 
6030Sstevel@tonic-gate 	push_diagnostic_mode(env);
6040Sstevel@tonic-gate }
6050Sstevel@tonic-gate 
6060Sstevel@tonic-gate /*
6070Sstevel@tonic-gate  * May need to implement other memory-access Fcodes here (depending upon
6080Sstevel@tonic-gate  * abuse), like fill, comp, +!, etc., etc.
6090Sstevel@tonic-gate  */
6100Sstevel@tonic-gate 
6110Sstevel@tonic-gate #pragma init(_init)
6120Sstevel@tonic-gate 
6130Sstevel@tonic-gate static void
_init(void)6140Sstevel@tonic-gate _init(void)
6150Sstevel@tonic-gate {
6160Sstevel@tonic-gate 	fcode_env_t *env = initial_env;
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate 	mac_addr = MALLOC(MAC_ADDR_SIZE);
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate 	ASSERT(env);
6210Sstevel@tonic-gate 	NOTICE;
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate 	ANSI(0x06e, 0,		"l@",			fcd_lfetch);
6240Sstevel@tonic-gate 	ANSI(0x06f, 0,		"w@",			fcd_wfetch);
6250Sstevel@tonic-gate 	ANSI(0x071, 0,		"c@",			fcd_cfetch);
6260Sstevel@tonic-gate 	ANSI(0x073, 0,		"l!",			fcd_lstore);
6270Sstevel@tonic-gate 	ANSI(0x074, 0,		"w!",			fcd_wstore);
6280Sstevel@tonic-gate 	ANSI(0x075, 0,		"c!",			fcd_cstore);
6290Sstevel@tonic-gate 	ANSI(0x078, 0,		"move",			fcd_move);
6300Sstevel@tonic-gate 	ANSI(0x07a, 0,		"comp",			fcd_comp);
6310Sstevel@tonic-gate 
6320Sstevel@tonic-gate 	ANSI(0x120, 0,		"diagnostic-mode?",	diagnostic_mode);
6330Sstevel@tonic-gate 
6340Sstevel@tonic-gate 	ANSI(0x1a4, 0,		"mac-address",		mac_address);
6350Sstevel@tonic-gate 
6360Sstevel@tonic-gate 	P1275(0x220, 0,		"cpeek",		cpeek);
6370Sstevel@tonic-gate 	P1275(0x221, 0,		"wpeek",		wpeek);
6380Sstevel@tonic-gate 	P1275(0x222, 0,		"lpeek",		lpeek);
6390Sstevel@tonic-gate 	P1275(0x223, 0,		"cpoke",		cpoke);
6400Sstevel@tonic-gate 	P1275(0x224, 0,		"wpoke",		wpoke);
6410Sstevel@tonic-gate 	P1275(0x225, 0,		"lpoke",		lpoke);
6420Sstevel@tonic-gate 
6430Sstevel@tonic-gate 	P1275(0x230, 0,		"rb@",			rbfetch);
6440Sstevel@tonic-gate 	P1275(0x231, 0,		"rb!",			rbstore);
6450Sstevel@tonic-gate 	P1275(0x232, 0,		"rw@",			rwfetch);
6460Sstevel@tonic-gate 	P1275(0x233, 0,		"rw!",			rwstore);
6470Sstevel@tonic-gate 	P1275(0x234, 0,		"rl@",			rlfetch);
6480Sstevel@tonic-gate 	P1275(0x235, 0,		"rl!",			rlstore);
6490Sstevel@tonic-gate 
6500Sstevel@tonic-gate 	P1275(0x246,	0,	"x@",			fcd_xfetch);
6510Sstevel@tonic-gate 	P1275(0x247,	0,	"x!",			fcd_xstore);
6520Sstevel@tonic-gate 
6530Sstevel@tonic-gate 	P1275(0x22e,	0,	"rx@",			rxfetch);
6540Sstevel@tonic-gate 	P1275(0x22f,	0,	"rx!",			rxstore);
6550Sstevel@tonic-gate 	FORTH(0,		"set-diagnostic-mode",	set_diagnostic_mode);
6560Sstevel@tonic-gate 	FORTH(0,		"local-mac-address?",	local_mac_address);
6570Sstevel@tonic-gate 	FORTH(0,		"local-ether-addr",	local_ether_addr);
6580Sstevel@tonic-gate }
659