1 /* 2 * CDDL HEADER START 3 * 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 7 * with the License. 8 * 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. 13 * 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] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <strings.h> 32 33 #include <fcode/private.h> 34 #include <fcode/log.h> 35 36 #include <fcdriver/fcdriver.h> 37 38 fstack_t 39 mem_map_in(fcode_env_t *env, fstack_t hi, fstack_t lo, fstack_t len) 40 { 41 private_data_t *pdp = DEVICE_PRIVATE(env); 42 fc_cell_t virt; 43 fstack_t mcookie = NULL; 44 char *service = "map-in"; 45 int error; 46 int offset = 0; 47 48 /* 49 * The calculation of the offset, lo and len are left here 50 * due to historical precedence. 51 */ 52 53 offset = lo & PAGEOFFSET; 54 lo &= PAGEMASK; 55 len = (len + offset + PAGEOFFSET) & PAGEMASK; 56 57 error = fc_run_priv(pdp->common, service, 3, 1, fc_size2cell(len), 58 fc_uint32_t2cell(hi), fc_uint32_t2cell(lo), &virt); 59 60 if (error) 61 throw_from_fclib(env, 1, "gp2:%s: failed\n", service); 62 63 mcookie = mapping_to_mcookie(virt, len, NULL, NULL); 64 65 if (mcookie == NULL) 66 throw_from_fclib(env, 1, "gp2:%s: mapping_to_mcookie failed\n", 67 service); 68 69 mcookie += offset; 70 71 debug_msg(DEBUG_REG_ACCESS, "gp2:%s: %llx -> %x\n", service, 72 (uint64_t)virt, (uint32_t)mcookie); 73 74 return (mcookie); 75 } 76 77 static void 78 mem_map_out(fcode_env_t *env, fstack_t mcookie, fstack_t len) 79 { 80 private_data_t *pdp = DEVICE_PRIVATE(env); 81 fc_cell_t virt; 82 char *service = "map-out"; 83 int error; 84 int offset; 85 86 /* 87 * The calculation of the offset, lo and len are left here 88 * due to historical precedence. 89 */ 90 91 offset = mcookie & PAGEOFFSET; 92 mcookie &= PAGEMASK; 93 len = (len + offset + PAGEOFFSET) & PAGEMASK; 94 95 if (!is_mcookie(mcookie)) { 96 log_message(MSG_ERROR, "gp2:%s: %x not an mcookie!\n", 97 service, (int)mcookie); 98 virt = mcookie; 99 } else { 100 virt = mcookie_to_addr(mcookie); 101 debug_msg(DEBUG_REG_ACCESS, "gp2:%s: %x -> %llx\n", service, 102 (int)mcookie, (uint64_t)virt); 103 delete_mapping(mcookie); 104 } 105 106 error = fc_run_priv(pdp->common, service, 2, 0, fc_size2cell(len), 107 virt); 108 if (error) 109 log_message(MSG_ERROR, "gp2:%s: failed\n", service); 110 } 111 112 static void 113 do_get_portid(fcode_env_t *env) 114 { 115 fstack_t phi, plo, portid; 116 private_data_t *pdp = DEVICE_PRIVATE(env); 117 118 CHECK_DEPTH(env, 2, "gp2:get-portid"); 119 phi = POP(DS); 120 plo = POP(DS); 121 122 portid = ((plo & 0xff800000) >> 23) | ((phi & 1) << 9); 123 debug_msg(DEBUG_REG_ACCESS, "gp2:get-portid ( %x %x ) -> %x\n", 124 (int)phi, (int)plo, (int)portid); 125 PUSH(DS, portid); 126 } 127 128 static void 129 do_map_in(fcode_env_t *env) 130 { 131 fstack_t phi, pmid, plo, len, addr; 132 133 CHECK_DEPTH(env, 3, "gp2:map-in"); 134 len = POP(DS); 135 phi = POP(DS); 136 plo = POP(DS); 137 addr = mem_map_in(env, phi, plo, len); 138 PUSH(DS, addr); 139 } 140 141 static void 142 do_map_out(fcode_env_t *env) 143 { 144 fstack_t addr, len; 145 146 CHECK_DEPTH(env, 2, "gp2:map-out"); 147 len = POP(DS); 148 addr = POP(DS); 149 mem_map_out(env, addr, len); 150 } 151 152 static void 153 do_encode_unit(fcode_env_t *env) 154 { 155 char enc_buf[64]; 156 fstack_t hi, mid, lo; 157 int id, off; 158 159 CHECK_DEPTH(env, 2, "gp2:encode-unit"); 160 hi = POP(DS); 161 lo = POP(DS); 162 163 hi = (hi & 0x00000001); /* get high order agent id bit */ 164 id = (hi << 9) | (lo >> 23); /* build extended agent id */ 165 off = lo & 0x7fffff; /* build config offset */ 166 167 if (off) { 168 sprintf(enc_buf, "%x,%x", id, off); 169 } else { 170 sprintf(enc_buf, "%x", id); 171 } 172 debug_msg(DEBUG_REG_ACCESS, "gp2:encode_unit ( %x %x ) -> '%s'\n", 173 (int)hi, (int)lo, enc_buf); 174 push_a_string(env, STRDUP(enc_buf)); 175 } 176 177 static void 178 do_decode_unit(fcode_env_t *env) 179 { 180 uint32_t lo, hi; 181 int agent, offset; 182 char *buf; 183 184 CHECK_DEPTH(env, 2, "gp2:decode-unit"); 185 buf = pop_a_string(env, NULL); 186 if (sscanf(buf, "%x,%x", &agent, &offset) != 2) { 187 if (sscanf(buf, "%x", &agent) != 1) { 188 throw_from_fclib(env, 1, "gp2:decode_unit:%s", buf); 189 } 190 offset = 0; 191 } 192 lo = offset | (agent << 23); 193 hi = (agent >> 9) | 0x400; 194 debug_msg(DEBUG_REG_ACCESS, "gp2:decode_unit ( '%s' ) -> %x %x\n", buf, 195 hi, lo); 196 PUSH(DS, lo); 197 PUSH(DS, hi); 198 } 199 200 static void 201 do_claim_addr(fcode_env_t *env) 202 { 203 fstack_t portid, bar, align, type, size_hi, size_lo; 204 fc_cell_t lo, hi; 205 private_data_t *pdp = DEVICE_PRIVATE(env); 206 char *service = "claim-address"; 207 int error; 208 209 CHECK_DEPTH(env, 6, "gp2:claim-address"); 210 portid = POP(DS); 211 bar = POP(DS); 212 align = POP(DS); 213 type = POP(DS); 214 size_hi = POP(DS); 215 size_lo = POP(DS); 216 217 error = fc_run_priv(pdp->common, service, 6, 2, 218 fc_int2cell(portid), fc_int2cell(bar), fc_int2cell(align), 219 fc_int2cell(type), fc_int2cell(size_hi), fc_int2cell(size_lo), 220 &lo, &hi); 221 222 if (error) 223 throw_from_fclib(env, 1, "gp2:%s: failed\n", service); 224 225 debug_msg(DEBUG_REG_ACCESS, 226 "gp2:%s ( %x %x %x %x %x %x ) -> %x %x\n", service, (int)portid, 227 (int)bar, (int)align, (int)type, (int)size_hi, (int)size_lo, 228 (uint32_t)hi, (uint32_t)lo); 229 230 PUSH(DS, (uint32_t)lo); 231 PUSH(DS, (uint32_t)hi); 232 } 233 234 static void 235 do_master_interrupt(fcode_env_t *env) 236 { 237 int portid; 238 token_t xt; 239 240 CHECK_DEPTH(env, 2, "gp2:master-interrput"); 241 portid = POP(DS); 242 xt = POP(DS); 243 PUSH(DS, FALSE); 244 debug_msg(DEBUG_REG_ACCESS, "gp2:master-interrupt ( %x %x ) -> %x\n", 245 portid, xt, (int)FALSE); 246 } 247 248 static void 249 do_register_vectory_entry(fcode_env_t *env) 250 { 251 int ign, ino, level; 252 253 CHECK_DEPTH(env, 3, "gp2:register-vector-entry"); 254 ign = POP(DS); 255 ino = POP(DS); 256 level = POP(DS); 257 PUSH(DS, FALSE); 258 debug_msg(DEBUG_REG_ACCESS, "gp2:register-vector-entry ( %x %x %x ) ->" 259 " %x\n", ign, ino, level, (int)FALSE); 260 } 261 262 static void 263 do_get_interrupt_target(fcode_env_t *env) 264 { 265 int mid = 0; 266 267 PUSH(DS, mid); 268 debug_msg(DEBUG_REG_ACCESS, "gp2:get-interrupt-target ( ) -> %x\n", 269 mid); 270 } 271 272 static void 273 do_device_id(fcode_env_t *env) 274 { 275 fstack_t phi, plo, addr; 276 fc_cell_t virtaddr; 277 private_data_t *pdp = DEVICE_PRIVATE(env); 278 uint64_t wci_id_reg; 279 int rc, parid; 280 281 CHECK_DEPTH(env, 2, "gp2:device-id"); 282 phi = POP(DS); 283 plo = POP(DS); 284 285 PUSH(DS, plo); 286 PUSH(DS, phi); 287 PUSH(DS, 0x100); 288 289 do_map_in(env); 290 291 addr = POP(DS); 292 293 virtaddr = mcookie_to_addr(addr); 294 295 /* Try to read the wci_id register */ 296 rc = fc_run_priv(pdp->common, "rx@", 1, 1, virtaddr + 0xe0, 297 &wci_id_reg); 298 299 mem_map_out(env, addr, 0x100); 300 301 /* 302 * Get the part id from the jtag ID register 303 */ 304 parid = ((wci_id_reg >> 12) & 0xffff); 305 306 if (!rc && parid == 0x4478) { 307 debug_msg(DEBUG_FIND_FCODE, "gp2: do_device_id: gp2-wci\n"); 308 push_a_string(env, "SUNW,wci"); 309 } else { 310 debug_msg(DEBUG_FIND_FCODE, "gp2: do_device_id: gp2-pci\n"); 311 push_a_string(env, "gp2-pci"); 312 } 313 } 314 315 #pragma init(_init) 316 317 static void 318 _init(void) 319 { 320 fcode_env_t *env = initial_env; 321 322 ASSERT(env); 323 ASSERT(env->current_device); 324 NOTICE; 325 326 create_int_prop(env, "#address-cells", 2); 327 328 FORTH(0, "map-in", do_map_in); 329 FORTH(0, "get-portid", do_get_portid); 330 FORTH(0, "map-out", do_map_out); 331 FORTH(0, "decode-unit", do_decode_unit); 332 FORTH(0, "encode-unit", do_encode_unit); 333 FORTH(0, "claim-address", do_claim_addr); 334 FORTH(0, "master-interrupt", do_master_interrupt); 335 FORTH(0, "register-vector-entry", do_register_vectory_entry); 336 FORTH(0, "get-interrupt-target", do_get_interrupt_target); 337 FORTH(0, "device-id", do_device_id); 338 339 install_dma_methods(env); 340 341 } 342