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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 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 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 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