4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
33 #include <fcode/private.h>
34 #include <fcode/log.h>
36 #include <fcdriver/fcdriver.h>
39 fc_reg_read(fcode_env_t
*env
, char *service
, fstack_t virt
, int *errp
)
41 fc_cell_t virtaddr
, data
;
44 if (!is_mcookie(virt
))
45 forth_abort(env
, "fc_reg_read: bad mcookie: 0x%x\n", virt
);
47 virtaddr
= mcookie_to_addr(virt
);
49 /* Supress fc_run_priv error msgs on peeks */
50 nin
= ((errp
== NULL
) ? 1 : (1 | FCRP_NOERROR
));
52 error
= fc_run_priv(env
->private, service
, nin
, 1, virtaddr
, &data
);
54 /* Don't report error on peeks */
57 forth_abort(env
, "fc_read_reg: ERROR: cookie: %llx"
58 " virt: %llx\n", (uint64_t)virt
, (uint64_t)virtaddr
);
64 fc_reg_write(fcode_env_t
*env
, char *service
, fstack_t virt
, fc_cell_t data
,
70 if (!is_mcookie(virt
))
71 forth_abort(env
, "fc_reg_write: bad mcookie: 0x%x\n", virt
);
73 virtaddr
= mcookie_to_addr(virt
);
75 /* Supress fc_run_priv error msgs on pokes */
76 nin
= ((errp
== NULL
) ? 2 : (2 | FCRP_NOERROR
));
78 error
= fc_run_priv(env
->private, service
, nin
, 0, virtaddr
, data
);
80 /* Don't report error on pokes */
83 forth_abort(env
, "fc_write_reg: ERROR: cookie: %llx"
84 " virt: %llx\n", (uint64_t)virt
, (uint64_t)virtaddr
);
89 check_address_abuse(fcode_env_t
*env
, fstack_t addr
, char *type
,
90 int want_mcookie
, void (*alt
)(fcode_env_t
*))
92 if (is_mcookie(addr
) != want_mcookie
) {
93 debug_msg(DEBUG_ADDR_ABUSE
, "Warning: %s to %s address: %llx\n",
94 type
, want_mcookie
? "unmapped" : "mapped",
103 rlfetch(fcode_env_t
*env
)
107 CHECK_DEPTH(env
, 1, "rl@");
109 if (!check_address_abuse(env
, p
, "rl@", 1, lfetch
))
110 TOS
= (lforth_t
)fc_reg_read(env
, "rl@", p
, NULL
);
114 rlstore(fcode_env_t
*env
)
118 CHECK_DEPTH(env
, 2, "rl!");
120 if (!check_address_abuse(env
, p
, "rl!", 1, lstore
)) {
123 fc_reg_write(env
, "rl!", p
, d
, NULL
);
128 rwfetch(fcode_env_t
*env
)
132 CHECK_DEPTH(env
, 1, "rw@");
134 if (!check_address_abuse(env
, p
, "rw@", 1, wfetch
))
135 TOS
= (wforth_t
)fc_reg_read(env
, "rw@", p
, NULL
);
139 rwstore(fcode_env_t
*env
)
143 CHECK_DEPTH(env
, 2, "rw!");
145 if (!check_address_abuse(env
, p
, "rw!", 1, wstore
)) {
148 fc_reg_write(env
, "rw!", p
, d
, NULL
);
153 rbfetch(fcode_env_t
*env
)
157 CHECK_DEPTH(env
, 1, "rb@");
159 if (!check_address_abuse(env
, p
, "rb@", 1, cfetch
)) {
160 TOS
= (uchar_t
)fc_reg_read(env
, "rb@", p
, NULL
);
165 rbstore(fcode_env_t
*env
)
169 CHECK_DEPTH(env
, 2, "rb!");
171 if (!check_address_abuse(env
, p
, "rb!", 1, cstore
)) {
174 fc_reg_write(env
, "rb!", p
, d
, NULL
);
182 rxfetch(fcode_env_t
*env
)
187 CHECK_DEPTH(env
, 1, "rx@");
189 if (!check_address_abuse(env
, p
, "rx@", 1, xfetch
)) {
191 push_xforth(env
, (xforth_t
)fc_reg_read(env
, "rx@", p
, NULL
));
199 rxstore(fcode_env_t
*env
)
204 CHECK_DEPTH(env
, 2, "rx!");
206 if (!check_address_abuse(env
, p
, "rx!", 1, xstore
)) {
209 fc_reg_write(env
, "rx!", p
, d
, NULL
);
214 lpeek(fcode_env_t
*env
)
220 CHECK_DEPTH(env
, 1, "lpeek");
222 r
= (lforth_t
)fc_reg_read(env
, "rl@", p
, &error
);
232 lpoke(fcode_env_t
*env
)
237 CHECK_DEPTH(env
, 2, "lpoke");
240 fc_reg_write(env
, "rl!", p
, d
, &error
);
241 PUSH(DS
, error
? FALSE
: TRUE
);
245 wpeek(fcode_env_t
*env
)
251 CHECK_DEPTH(env
, 1, "wpeek");
253 r
= (wforth_t
)fc_reg_read(env
, "rw@", p
, &error
);
263 wpoke(fcode_env_t
*env
)
268 CHECK_DEPTH(env
, 2, "wpoke");
271 fc_reg_write(env
, "rw!", p
, d
, &error
);
272 PUSH(DS
, error
? FALSE
: TRUE
);
276 cpeek(fcode_env_t
*env
)
282 CHECK_DEPTH(env
, 1, "cpeek");
284 r
= (uchar_t
)fc_reg_read(env
, "rb@", p
, &error
);
294 cpoke(fcode_env_t
*env
)
299 CHECK_DEPTH(env
, 2, "cpoke");
302 fc_reg_write(env
, "rb!", p
, d
, &error
);
303 PUSH(DS
, error
? FALSE
: TRUE
);
307 * fcdriver version of cfetch, replaces base 'c@'
310 fcd_cfetch(fcode_env_t
*env
)
314 CHECK_DEPTH(env
, 1, "c@");
315 if (!check_address_abuse(env
, addr
, "c@", 0, rbfetch
))
320 * fcdriver version of cstore, replaces base 'c!'
323 fcd_cstore(fcode_env_t
*env
)
327 CHECK_DEPTH(env
, 2, "c!");
328 if (!check_address_abuse(env
, addr
, "c!", 0, rbstore
))
333 * fcdriver version of wfetch, replaces base 'w@'
336 fcd_wfetch(fcode_env_t
*env
)
340 CHECK_DEPTH(env
, 1, "w@");
341 if (!check_address_abuse(env
, addr
, "w@", 0, rwfetch
))
346 * fcdriver version of wstore, replaces base 'w!'
349 fcd_wstore(fcode_env_t
*env
)
353 CHECK_DEPTH(env
, 2, "w!");
354 if (!check_address_abuse(env
, addr
, "w!", 0, rwstore
))
359 * fcdriver version of lfetch, replaces base 'l@'
362 fcd_lfetch(fcode_env_t
*env
)
366 CHECK_DEPTH(env
, 1, "l@");
367 if (!check_address_abuse(env
, addr
, "l@", 0, rlfetch
))
372 * fcdriver version of lstore, replaces base 'l!'
375 fcd_lstore(fcode_env_t
*env
)
379 CHECK_DEPTH(env
, 2, "l!");
380 if (!check_address_abuse(env
, addr
, "l!", 0, rlstore
))
385 * fcdriver version of xfetch, replaces base 'x@'
388 fcd_xfetch(fcode_env_t
*env
)
392 CHECK_DEPTH(env
, 1, "x@");
393 if (!check_address_abuse(env
, addr
, "x@", 0, rxfetch
))
398 * fcdriver version of xstore, replaces base 'x!'
401 fcd_xstore(fcode_env_t
*env
)
405 CHECK_DEPTH(env
, 2, "x!");
406 if (!check_address_abuse(env
, addr
, "x!", 0, rxstore
))
411 * fcdriver version of move, replaces base 'move'
414 fcd_move(fcode_env_t
*env
)
417 uchar_t
*destaddr
, *srcaddr
;
419 CHECK_DEPTH(env
, 3, "move");
421 destaddr
= ((uchar_t
*)POP(DS
));
422 srcaddr
= ((uchar_t
*)POP(DS
));
423 for (; len
> 0; len
--, srcaddr
++, destaddr
++) {
424 PUSH(DS
, (fstack_t
)srcaddr
);
426 PUSH(DS
, (fstack_t
)destaddr
);
432 fcd_comp(fcode_env_t
*env
)
434 char *str1
, *str2
, byte1
, byte2
;
437 CHECK_DEPTH(env
, 3, "comp");
438 len
= (size_t)POP(DS
);
439 str1
= (char *)POP(DS
);
440 str2
= (char *)POP(DS
);
441 for (; len
> 0; len
--, str1
++, str2
++) {
442 PUSH(DS
, (fstack_t
)str1
);
445 PUSH(DS
, (fstack_t
)str2
);
461 get_eeprom_value(fcode_env_t
*env
, char *name
)
466 sprintf(buf
, "eeprom '%s'", name
);
467 if ((fd
= popen(buf
, "r")) == NULL
)
469 fgets(buf
, sizeof (buf
), fd
);
471 if ((p
= strchr(buf
, '\n')) != NULL
)
473 if ((p
= strchr(buf
, '=')) != NULL
)
479 local_mac_address(fcode_env_t
*env
)
484 mac_str
= get_eeprom_value(env
, "local-mac-address?");
485 if (mac_str
!= NULL
&& strcmp(mac_str
, "true") == 0)
493 * Allow for programmatic over-ride of 'mac-address'
495 #define MAC_ADDR_SIZE 6
496 static char *mac_addr
;
497 static int mac_addr_is_valid
;
500 set_mac_address(char *macaddr
)
502 mac_addr_is_valid
= 1;
503 memcpy(mac_addr
, macaddr
, MAC_ADDR_SIZE
);
507 push_mac_address(fcode_env_t
*env
)
509 PUSH(DS
, (fstack_t
)mac_addr
);
510 PUSH(DS
, MAC_ADDR_SIZE
);
514 * Does driver call to get this.
517 local_ether_addr(fcode_env_t
*env
)
519 static fc_cell_t
*mac_add
;
522 mac_add
= MALLOC(sizeof (fc_cell_t
) * 2);
523 error
= fc_run_priv(env
->private, "local-ether-addr", 0, 2, &mac_add
[0],
526 bzero(mac_add
, sizeof (mac_add
));
529 PUSH(DS
, (fstack_t
)&mac_add
[0]);
534 * 'mac-address' - complicated by 'local-mac-address' stuff.
537 mac_address(fcode_env_t
*env
)
541 if (mac_addr_is_valid
) {
542 push_mac_address(env
);
547 * From here, we essentially re-implement OBP's 'mac-address' word.
548 * on some platforms, this may need to be re-implemented.
550 local_mac_address(env
);
553 push_a_string(env
, "local-mac-address");
554 get_inherited_prop(env
);
556 if (d
== FALSE
&& TOS
== 6)
560 local_ether_addr(env
);
564 * Allow for the programmatic setting of diagnostic-mode?
566 static int diag_mode_is_valid
= 0;
567 static int diag_mode
= 0;
570 set_diagnostic_mode(fcode_env_t
*env
)
572 fstack_t d
= POP(DS
);
575 diag_mode_is_valid
= 1;
579 push_diagnostic_mode(fcode_env_t
*env
)
581 PUSH(DS
, (fstack_t
)diag_mode
);
585 * 'diagnostic-mode?' - diagnostic-mode? is equivalent to NVRAM 'diag-switch?'
588 diagnostic_mode(fcode_env_t
*env
)
593 if (!diag_mode_is_valid
) {
594 diag_str
= get_eeprom_value(env
, "diag-switch?");
595 if (diag_str
!= NULL
&& strcmp(diag_str
, "false") == 0)
599 PUSH(DS
, diag_value
);
600 set_diagnostic_mode(env
);
603 push_diagnostic_mode(env
);
607 * May need to implement other memory-access Fcodes here (depending upon
608 * abuse), like fill, comp, +!, etc., etc.
616 fcode_env_t
*env
= initial_env
;
618 mac_addr
= MALLOC(MAC_ADDR_SIZE
);
623 ANSI(0x06e, 0, "l@", fcd_lfetch
);
624 ANSI(0x06f, 0, "w@", fcd_wfetch
);
625 ANSI(0x071, 0, "c@", fcd_cfetch
);
626 ANSI(0x073, 0, "l!", fcd_lstore
);
627 ANSI(0x074, 0, "w!", fcd_wstore
);
628 ANSI(0x075, 0, "c!", fcd_cstore
);
629 ANSI(0x078, 0, "move", fcd_move
);
630 ANSI(0x07a, 0, "comp", fcd_comp
);
632 ANSI(0x120, 0, "diagnostic-mode?", diagnostic_mode
);
634 ANSI(0x1a4, 0, "mac-address", mac_address
);
636 P1275(0x220, 0, "cpeek", cpeek
);
637 P1275(0x221, 0, "wpeek", wpeek
);
638 P1275(0x222, 0, "lpeek", lpeek
);
639 P1275(0x223, 0, "cpoke", cpoke
);
640 P1275(0x224, 0, "wpoke", wpoke
);
641 P1275(0x225, 0, "lpoke", lpoke
);
643 P1275(0x230, 0, "rb@", rbfetch
);
644 P1275(0x231, 0, "rb!", rbstore
);
645 P1275(0x232, 0, "rw@", rwfetch
);
646 P1275(0x233, 0, "rw!", rwstore
);
647 P1275(0x234, 0, "rl@", rlfetch
);
648 P1275(0x235, 0, "rl!", rlstore
);
650 P1275(0x246, 0, "x@", fcd_xfetch
);
651 P1275(0x247, 0, "x!", fcd_xstore
);
653 P1275(0x22e, 0, "rx@", rxfetch
);
654 P1275(0x22f, 0, "rx!", rxstore
);
655 FORTH(0, "set-diagnostic-mode", set_diagnostic_mode
);
656 FORTH(0, "local-mac-address?", local_mac_address
);
657 FORTH(0, "local-ether-addr", local_ether_addr
);