1*1772Sjl139090 /* 2*1772Sjl139090 * CDDL HEADER START 3*1772Sjl139090 * 4*1772Sjl139090 * The contents of this file are subject to the terms of the 5*1772Sjl139090 * Common Development and Distribution License (the "License"). 6*1772Sjl139090 * You may not use this file except in compliance with the License. 7*1772Sjl139090 * 8*1772Sjl139090 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*1772Sjl139090 * or http://www.opensolaris.org/os/licensing. 10*1772Sjl139090 * See the License for the specific language governing permissions 11*1772Sjl139090 * and limitations under the License. 12*1772Sjl139090 * 13*1772Sjl139090 * When distributing Covered Code, include this CDDL HEADER in each 14*1772Sjl139090 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*1772Sjl139090 * If applicable, add the following below this CDDL HEADER, with the 16*1772Sjl139090 * fields enclosed by brackets "[]" replaced with your own identifying 17*1772Sjl139090 * information: Portions Copyright [yyyy] [name of copyright owner] 18*1772Sjl139090 * 19*1772Sjl139090 * CDDL HEADER END 20*1772Sjl139090 */ 21*1772Sjl139090 /* 22*1772Sjl139090 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23*1772Sjl139090 * Use is subject to license terms. 24*1772Sjl139090 */ 25*1772Sjl139090 26*1772Sjl139090 #pragma ident "%Z%%M% %I% %E% SMI" 27*1772Sjl139090 28*1772Sjl139090 #include <stdio.h> 29*1772Sjl139090 #include <stdlib.h> 30*1772Sjl139090 #include <strings.h> 31*1772Sjl139090 32*1772Sjl139090 #include <fcode/private.h> 33*1772Sjl139090 #include <fcode/log.h> 34*1772Sjl139090 35*1772Sjl139090 #include <fcdriver/fcdriver.h> 36*1772Sjl139090 37*1772Sjl139090 #include <sys/opl_cfg.h> 38*1772Sjl139090 39*1772Sjl139090 /* VA for HardWare Descriptor */ 40*1772Sjl139090 static hwd_cmu_chan_t hwd_va_cmu; 41*1772Sjl139090 static hwd_leaf_t hwd_va_pci; 42*1772Sjl139090 43*1772Sjl139090 /* Macro to get I/O portid */ 44*1772Sjl139090 #define DO_GET_IO_PORTID(env, lo, hi, portid) \ 45*1772Sjl139090 PUSH(DS, lo); \ 46*1772Sjl139090 PUSH(DS, hi); \ 47*1772Sjl139090 do_get_io_portid(env); \ 48*1772Sjl139090 portid = (uint32_t)POP(DS) 49*1772Sjl139090 50*1772Sjl139090 fstack_t 51*1772Sjl139090 mem_map_in(fcode_env_t *env, fstack_t hi, fstack_t lo, fstack_t len) 52*1772Sjl139090 { 53*1772Sjl139090 private_data_t *pdp = DEVICE_PRIVATE(env); 54*1772Sjl139090 fc_cell_t virt; 55*1772Sjl139090 fstack_t mcookie = NULL; 56*1772Sjl139090 char *service = "map-in"; 57*1772Sjl139090 int error; 58*1772Sjl139090 int offset = 0; 59*1772Sjl139090 60*1772Sjl139090 /* 61*1772Sjl139090 * The calculation of the offset, lo and len are left here 62*1772Sjl139090 * due to historical precedence. 63*1772Sjl139090 */ 64*1772Sjl139090 65*1772Sjl139090 offset = lo & PAGEOFFSET; 66*1772Sjl139090 lo &= PAGEMASK; 67*1772Sjl139090 len = (len + offset + PAGEOFFSET) & PAGEMASK; 68*1772Sjl139090 69*1772Sjl139090 error = fc_run_priv(pdp->common, service, 3, 1, fc_size2cell(len), 70*1772Sjl139090 fc_uint32_t2cell(hi), fc_uint32_t2cell(lo), &virt); 71*1772Sjl139090 72*1772Sjl139090 if (error) 73*1772Sjl139090 throw_from_fclib(env, 1, "jupiter:%s: failed\n", service); 74*1772Sjl139090 75*1772Sjl139090 mcookie = mapping_to_mcookie(virt, len, NULL, NULL); 76*1772Sjl139090 77*1772Sjl139090 if (mcookie == NULL) 78*1772Sjl139090 throw_from_fclib(env, 1, 79*1772Sjl139090 "jupiter:%s: mapping_to_mcookie failed\n", service); 80*1772Sjl139090 81*1772Sjl139090 mcookie += offset; 82*1772Sjl139090 83*1772Sjl139090 debug_msg(DEBUG_REG_ACCESS, "jupiter:%s: %llx -> %x\n", service, 84*1772Sjl139090 (long long)virt, (uint32_t)mcookie); 85*1772Sjl139090 86*1772Sjl139090 return (mcookie); 87*1772Sjl139090 } 88*1772Sjl139090 89*1772Sjl139090 static void 90*1772Sjl139090 mem_map_out(fcode_env_t *env, fstack_t mcookie, fstack_t len) 91*1772Sjl139090 { 92*1772Sjl139090 private_data_t *pdp = DEVICE_PRIVATE(env); 93*1772Sjl139090 fc_cell_t virt; 94*1772Sjl139090 char *service = "map-out"; 95*1772Sjl139090 int error; 96*1772Sjl139090 int offset; 97*1772Sjl139090 98*1772Sjl139090 /* 99*1772Sjl139090 * The calculation of the offset, lo and len are left here 100*1772Sjl139090 * due to historical precedence. 101*1772Sjl139090 */ 102*1772Sjl139090 103*1772Sjl139090 offset = mcookie & PAGEOFFSET; 104*1772Sjl139090 mcookie &= PAGEMASK; 105*1772Sjl139090 len = (len + offset + PAGEOFFSET) & PAGEMASK; 106*1772Sjl139090 107*1772Sjl139090 if (!is_mcookie(mcookie)) { 108*1772Sjl139090 log_message(MSG_ERROR, "jupiter:%s: %x not an mcookie!\n", 109*1772Sjl139090 service, (int)mcookie); 110*1772Sjl139090 virt = mcookie; 111*1772Sjl139090 } else { 112*1772Sjl139090 virt = mcookie_to_addr(mcookie); 113*1772Sjl139090 debug_msg(DEBUG_REG_ACCESS, "jupiter:%s: %x -> %llx\n", 114*1772Sjl139090 service, (int)mcookie, (long long)virt); 115*1772Sjl139090 delete_mapping(mcookie); 116*1772Sjl139090 } 117*1772Sjl139090 118*1772Sjl139090 error = fc_run_priv(pdp->common, service, 2, 0, 119*1772Sjl139090 fc_size2cell(len), virt); 120*1772Sjl139090 if (error) 121*1772Sjl139090 log_message(MSG_ERROR, "jupiter:%s: failed\n", service); 122*1772Sjl139090 } 123*1772Sjl139090 124*1772Sjl139090 static void 125*1772Sjl139090 do_map_in(fcode_env_t *env) 126*1772Sjl139090 { 127*1772Sjl139090 fstack_t phi, plo, len, addr; 128*1772Sjl139090 129*1772Sjl139090 CHECK_DEPTH(env, 3, "jupiter:map-in"); 130*1772Sjl139090 len = POP(DS); 131*1772Sjl139090 phi = POP(DS); 132*1772Sjl139090 plo = POP(DS); 133*1772Sjl139090 addr = mem_map_in(env, phi, plo, len); 134*1772Sjl139090 PUSH(DS, addr); 135*1772Sjl139090 } 136*1772Sjl139090 137*1772Sjl139090 static void 138*1772Sjl139090 do_map_out(fcode_env_t *env) 139*1772Sjl139090 { 140*1772Sjl139090 fstack_t addr, len; 141*1772Sjl139090 142*1772Sjl139090 CHECK_DEPTH(env, 2, "jupiter:map-out"); 143*1772Sjl139090 len = POP(DS); 144*1772Sjl139090 addr = POP(DS); 145*1772Sjl139090 mem_map_out(env, addr, len); 146*1772Sjl139090 } 147*1772Sjl139090 148*1772Sjl139090 static void 149*1772Sjl139090 do_get_io_portid(fcode_env_t *env) 150*1772Sjl139090 { 151*1772Sjl139090 fstack_t phi, plo; 152*1772Sjl139090 unsigned int portid, lsb, ch, leaf; 153*1772Sjl139090 154*1772Sjl139090 CHECK_DEPTH(env, 2, "jupiter:get-portid"); 155*1772Sjl139090 156*1772Sjl139090 phi = POP(DS); 157*1772Sjl139090 plo = POP(DS); 158*1772Sjl139090 159*1772Sjl139090 lsb = OPL_ADDR_TO_LSB(phi); 160*1772Sjl139090 ch = OPL_ADDR_TO_CHANNEL(phi); 161*1772Sjl139090 leaf = OPL_ADDR_TO_LEAF(phi, plo); 162*1772Sjl139090 163*1772Sjl139090 portid = OPL_IO_PORTID(lsb, ch, leaf); 164*1772Sjl139090 165*1772Sjl139090 debug_msg(DEBUG_REG_ACCESS, "jupiter:get-portid ( %x %x ) -> %x\n", 166*1772Sjl139090 (int)phi, (int)plo, (int)portid); 167*1772Sjl139090 PUSH(DS, portid); 168*1772Sjl139090 } 169*1772Sjl139090 170*1772Sjl139090 static void 171*1772Sjl139090 do_encode_unit(fcode_env_t *env) 172*1772Sjl139090 { 173*1772Sjl139090 char enc_buf[64]; 174*1772Sjl139090 fstack_t hi, lo; 175*1772Sjl139090 uint32_t id; 176*1772Sjl139090 long long off; 177*1772Sjl139090 178*1772Sjl139090 CHECK_DEPTH(env, 2, "jupiter:encode-unit"); 179*1772Sjl139090 180*1772Sjl139090 hi = POP(DS); 181*1772Sjl139090 lo = POP(DS); 182*1772Sjl139090 off = (long long)(((hi & 0x1F) << 32) | lo); 183*1772Sjl139090 184*1772Sjl139090 /* Convert physical address to portid */ 185*1772Sjl139090 DO_GET_IO_PORTID(env, lo, hi, id); 186*1772Sjl139090 187*1772Sjl139090 if (off) { 188*1772Sjl139090 (void) sprintf(enc_buf, "%x,%llx", id, off); 189*1772Sjl139090 } else { 190*1772Sjl139090 (void) sprintf(enc_buf, "%x", id); 191*1772Sjl139090 } 192*1772Sjl139090 193*1772Sjl139090 debug_msg(DEBUG_REG_ACCESS, "jupiter:encode_unit ( %x %x ) -> '%s'\n", 194*1772Sjl139090 (uint32_t)hi, (uint32_t)lo, enc_buf); 195*1772Sjl139090 196*1772Sjl139090 push_a_string(env, STRDUP(enc_buf)); 197*1772Sjl139090 } 198*1772Sjl139090 199*1772Sjl139090 static void 200*1772Sjl139090 do_decode_unit(fcode_env_t *env) 201*1772Sjl139090 { 202*1772Sjl139090 uint32_t hi; 203*1772Sjl139090 long long lo; 204*1772Sjl139090 unsigned int portid, lsb, ch; 205*1772Sjl139090 char *buf; 206*1772Sjl139090 207*1772Sjl139090 CHECK_DEPTH(env, 2, "jupiter:decode-unit"); 208*1772Sjl139090 209*1772Sjl139090 buf = pop_a_string(env, NULL); 210*1772Sjl139090 if (sscanf(buf, "%x,%llx", &portid, &lo) != 2) { 211*1772Sjl139090 if (sscanf(buf, "%x", &portid) != 1) { 212*1772Sjl139090 throw_from_fclib(env, 1, "jupiter:decode_unit:%s", 213*1772Sjl139090 buf); 214*1772Sjl139090 } 215*1772Sjl139090 lo = 0; 216*1772Sjl139090 } 217*1772Sjl139090 218*1772Sjl139090 lsb = OPL_IO_PORTID_TO_LSB(portid); 219*1772Sjl139090 ch = OPL_PORTID_TO_CHANNEL(portid); 220*1772Sjl139090 hi = OPL_ADDR_HI(lsb, ch); 221*1772Sjl139090 222*1772Sjl139090 debug_msg(DEBUG_REG_ACCESS, 223*1772Sjl139090 "jupiter:decode_unit ( '%s' ) -> %x %llx\n", buf, hi, lo); 224*1772Sjl139090 225*1772Sjl139090 PUSH(DS, (fstack_t)lo); 226*1772Sjl139090 PUSH(DS, (fstack_t)hi); 227*1772Sjl139090 } 228*1772Sjl139090 229*1772Sjl139090 static void 230*1772Sjl139090 do_device_id(fcode_env_t *env) 231*1772Sjl139090 { 232*1772Sjl139090 common_data_t *cdp = COMMON_PRIVATE(env); 233*1772Sjl139090 char *buf = NULL; 234*1772Sjl139090 uint32_t hi; 235*1772Sjl139090 long long lo; 236*1772Sjl139090 uint32_t portid, ch, leaf; 237*1772Sjl139090 238*1772Sjl139090 CHECK_DEPTH(env, 2, "jupiter:device-id"); 239*1772Sjl139090 240*1772Sjl139090 hi = POP(DS); 241*1772Sjl139090 lo = POP(DS); 242*1772Sjl139090 243*1772Sjl139090 portid = 0; 244*1772Sjl139090 if (cdp && cdp->fc.unit_address && 245*1772Sjl139090 ((buf = strdup(cdp->fc.unit_address)) != NULL)) { 246*1772Sjl139090 /* 247*1772Sjl139090 * Get portid number from unit_address 248*1772Sjl139090 * Because of no leaf information in physical address 249*1772Sjl139090 */ 250*1772Sjl139090 if (sscanf(buf, "%x,%llx", &portid, &lo) != 2) { 251*1772Sjl139090 if (sscanf(buf, "%x", &portid) != 1) { 252*1772Sjl139090 throw_from_fclib(env, 1, 253*1772Sjl139090 "jupiter:do_device_id: invalid %s", buf); 254*1772Sjl139090 } 255*1772Sjl139090 } 256*1772Sjl139090 } else { 257*1772Sjl139090 /* 258*1772Sjl139090 * Non existence unit_address case. 259*1772Sjl139090 * Convert physical address to portid. 260*1772Sjl139090 */ 261*1772Sjl139090 throw_from_fclib(env, 1, 262*1772Sjl139090 "jupiter:do_device_id: failed unit address"); 263*1772Sjl139090 DO_GET_IO_PORTID(env, lo, hi, portid); 264*1772Sjl139090 } 265*1772Sjl139090 266*1772Sjl139090 debug_msg(DEBUG_FIND_FCODE, 267*1772Sjl139090 "jupiter:do_device_id:(%x,%llx)\n", portid, lo); 268*1772Sjl139090 269*1772Sjl139090 /* Pick up each ID from portid */ 270*1772Sjl139090 ch = OPL_PORTID_TO_CHANNEL(portid); 271*1772Sjl139090 leaf = OPL_PORTID_TO_LEAF(portid); 272*1772Sjl139090 273*1772Sjl139090 if (ch == OPL_CMU_CHANNEL) { 274*1772Sjl139090 /* 275*1772Sjl139090 * CMU-CH: PCICMU CHANNEL 276*1772Sjl139090 */ 277*1772Sjl139090 debug_msg(DEBUG_FIND_FCODE, 278*1772Sjl139090 "jupiter:do_device_id:cmu-ch\n"); 279*1772Sjl139090 push_a_string(env, "cmu-ch"); 280*1772Sjl139090 } else if (OPL_OBERON_CHANNEL(ch) && OPL_VALID_LEAF(leaf)) { 281*1772Sjl139090 /* 282*1772Sjl139090 * PCI-CH: Oberon Leaves CHANNEL 283*1772Sjl139090 */ 284*1772Sjl139090 if (leaf) { 285*1772Sjl139090 /* Leaf B */ 286*1772Sjl139090 debug_msg(DEBUG_FIND_FCODE, 287*1772Sjl139090 "jupiter:do_device_id:jup-oberon-pci1\n"); 288*1772Sjl139090 push_a_string(env, "jup-oberon-pci1"); 289*1772Sjl139090 } else { 290*1772Sjl139090 /* Leaf A */ 291*1772Sjl139090 debug_msg(DEBUG_FIND_FCODE, 292*1772Sjl139090 "jupiter:do_device_id:jup-oberon-pci0\n"); 293*1772Sjl139090 push_a_string(env, "jup-oberon-pci0"); 294*1772Sjl139090 } 295*1772Sjl139090 } else { 296*1772Sjl139090 /* Not matched to any channels */ 297*1772Sjl139090 throw_from_fclib(env, 1, 298*1772Sjl139090 "jupiter:do_device_id: invalid portid %x", portid); 299*1772Sjl139090 push_a_string(env, ""); 300*1772Sjl139090 } 301*1772Sjl139090 302*1772Sjl139090 /* Free the duplicated buf */ 303*1772Sjl139090 if (buf != NULL) 304*1772Sjl139090 free(buf); 305*1772Sjl139090 } 306*1772Sjl139090 307*1772Sjl139090 static void 308*1772Sjl139090 do_get_hwd_va(fcode_env_t *env) 309*1772Sjl139090 { 310*1772Sjl139090 private_data_t *pdp = DEVICE_PRIVATE(env); 311*1772Sjl139090 char *service = "get-hwd-va"; 312*1772Sjl139090 char *buf; 313*1772Sjl139090 uint32_t portid = 0; 314*1772Sjl139090 int ch; 315*1772Sjl139090 int error; 316*1772Sjl139090 fc_cell_t status; 317*1772Sjl139090 void *hwd_va; 318*1772Sjl139090 319*1772Sjl139090 CHECK_DEPTH(env, 2, "jupiter:get-hwd-va"); 320*1772Sjl139090 321*1772Sjl139090 /* Get a portid with string format */ 322*1772Sjl139090 buf = pop_a_string(env, NULL); 323*1772Sjl139090 324*1772Sjl139090 /* Convert to the integer from the string */ 325*1772Sjl139090 if (sscanf(buf, "%x", &portid) != 1) { 326*1772Sjl139090 throw_from_fclib(env, 1, "jupiter:%s: invalid portid", 327*1772Sjl139090 service); 328*1772Sjl139090 } 329*1772Sjl139090 330*1772Sjl139090 ch = OPL_PORTID_TO_CHANNEL(portid); 331*1772Sjl139090 if (!OPL_VALID_CHANNEL(ch)) { 332*1772Sjl139090 throw_from_fclib(env, 1, "jupiter:%s: invalid poritd", 333*1772Sjl139090 service); 334*1772Sjl139090 hwd_va = 0; 335*1772Sjl139090 goto out; 336*1772Sjl139090 } 337*1772Sjl139090 338*1772Sjl139090 if (ch == OPL_CMU_CHANNEL) { 339*1772Sjl139090 hwd_va = (void *)&hwd_va_cmu; 340*1772Sjl139090 } else { 341*1772Sjl139090 hwd_va = (void *)&hwd_va_pci; 342*1772Sjl139090 } 343*1772Sjl139090 344*1772Sjl139090 /* 345*1772Sjl139090 * Get the virtual address of hwd specified with portid. 346*1772Sjl139090 */ 347*1772Sjl139090 error = fc_run_priv(pdp->common, service, 2, 1, 348*1772Sjl139090 fc_uint32_t2cell(portid), fc_ptr2cell(hwd_va), &status); 349*1772Sjl139090 350*1772Sjl139090 if (error || !status) 351*1772Sjl139090 throw_from_fclib(env, 1, "jupiter:%s: failed\n", service); 352*1772Sjl139090 353*1772Sjl139090 out: 354*1772Sjl139090 PUSH(DS, (fstack_t)hwd_va); 355*1772Sjl139090 } 356*1772Sjl139090 357*1772Sjl139090 static void 358*1772Sjl139090 do_get_intrp_name(fcode_env_t *env) 359*1772Sjl139090 { 360*1772Sjl139090 /* 361*1772Sjl139090 * Just pass the "eFCode" string. 362*1772Sjl139090 */ 363*1772Sjl139090 364*1772Sjl139090 debug_msg(DEBUG_FIND_FCODE, 365*1772Sjl139090 "jupiter: do_get_intrp_name: eFCode\n"); 366*1772Sjl139090 367*1772Sjl139090 push_a_string(env, "eFCode"); 368*1772Sjl139090 } 369*1772Sjl139090 370*1772Sjl139090 static void 371*1772Sjl139090 do_master_interrupt(fcode_env_t *env) 372*1772Sjl139090 { 373*1772Sjl139090 int portid; 374*1772Sjl139090 token_t xt; 375*1772Sjl139090 376*1772Sjl139090 CHECK_DEPTH(env, 2, "jupiter:master-interrput"); 377*1772Sjl139090 portid = POP(DS); 378*1772Sjl139090 xt = POP(DS); 379*1772Sjl139090 380*1772Sjl139090 PUSH(DS, FALSE); 381*1772Sjl139090 debug_msg(DEBUG_REG_ACCESS, 382*1772Sjl139090 "jupiter:master-interrupt ( %x %x ) -> %x\n", 383*1772Sjl139090 portid, xt, (int)FALSE); 384*1772Sjl139090 } 385*1772Sjl139090 386*1772Sjl139090 static void 387*1772Sjl139090 do_register_vector_entry(fcode_env_t *env) 388*1772Sjl139090 { 389*1772Sjl139090 int ign, ino, level; 390*1772Sjl139090 391*1772Sjl139090 CHECK_DEPTH(env, 3, "jupiter:register-vector-entry"); 392*1772Sjl139090 ign = POP(DS); 393*1772Sjl139090 ino = POP(DS); 394*1772Sjl139090 level = POP(DS); 395*1772Sjl139090 396*1772Sjl139090 PUSH(DS, FALSE); 397*1772Sjl139090 debug_msg(DEBUG_REG_ACCESS, 398*1772Sjl139090 "jupiter:register-vector-entry ( %x %x %x ) -> %x\n", 399*1772Sjl139090 ign, ino, level, (int)FALSE); 400*1772Sjl139090 } 401*1772Sjl139090 402*1772Sjl139090 static void 403*1772Sjl139090 do_get_interrupt_target(fcode_env_t *env) 404*1772Sjl139090 { 405*1772Sjl139090 int mid = -1; 406*1772Sjl139090 407*1772Sjl139090 PUSH(DS, mid); 408*1772Sjl139090 debug_msg(DEBUG_REG_ACCESS, 409*1772Sjl139090 "jupiter:get-interrupt-target ( ) -> %x\n", mid); 410*1772Sjl139090 } 411*1772Sjl139090 412*1772Sjl139090 413*1772Sjl139090 #pragma init(_init) 414*1772Sjl139090 415*1772Sjl139090 static void 416*1772Sjl139090 _init(void) 417*1772Sjl139090 { 418*1772Sjl139090 fcode_env_t *env = initial_env; 419*1772Sjl139090 420*1772Sjl139090 ASSERT(env); 421*1772Sjl139090 ASSERT(env->current_device); 422*1772Sjl139090 NOTICE; 423*1772Sjl139090 424*1772Sjl139090 create_int_prop(env, "#address-cells", 2); 425*1772Sjl139090 426*1772Sjl139090 FORTH(0, "map-in", do_map_in); 427*1772Sjl139090 FORTH(0, "map-out", do_map_out); 428*1772Sjl139090 FORTH(0, "get-portid", do_get_io_portid); 429*1772Sjl139090 FORTH(0, "decode-unit", do_decode_unit); 430*1772Sjl139090 FORTH(0, "encode-unit", do_encode_unit); 431*1772Sjl139090 FORTH(0, "device-id", do_device_id); 432*1772Sjl139090 FORTH(0, "get-hwd-va", do_get_hwd_va); 433*1772Sjl139090 FORTH(0, "get-fcinterp-name", do_get_intrp_name); 434*1772Sjl139090 FORTH(0, "master-interrupt", do_master_interrupt); 435*1772Sjl139090 FORTH(0, "register-vector-entry", do_register_vector_entry); 436*1772Sjl139090 FORTH(0, "get-interrupt-target", do_get_interrupt_target); 437*1772Sjl139090 } 438