Exemplo n.º 1
0
/**
 * del_node
 *
 * @param phandle
 */
static void
del_node(unsigned int phandle)
{
    char *name = find_phandle(phandle);
    char delcmd[128] = "remove_node ";

    if (name == NULL)
        say(DEBUG, "Delete node error: Invalid phandle %8.8x", phandle);
    else {
        strcat(delcmd,name);
        do_update(delcmd, strlen(delcmd));
    }
}
Exemplo n.º 2
0
/**
 * add_new_node
 *
 * @param phandle
 * @param drcindex
 */
static void
add_new_node(unsigned int phandle, unsigned int drcindex)
{
    char *path;
    int rtas_rc;
    struct of_node *new_nodes;/* nodes returned from configure_connector */

    new_nodes = configure_connector(drcindex);

    path = find_phandle(phandle);
    if (path == NULL) {
        say(DEBUG, "Cannot find pnahdle %x\n", phandle);
        return;
    }

    rtas_rc = add_device_tree_nodes(path, new_nodes);
    if (rtas_rc)
        say(DEBUG, "add_device_tree_nodes failed at %s\n", path);
}
Exemplo n.º 3
0
/*
 * Find the interrupt parent of a node.
 */
static struct device_node * __init
intr_parent(struct device_node *p)
{
	phandle *parp;

	parp = (phandle *) get_property(p, "interrupt-parent", NULL);
	if (parp == NULL)
		return p->parent;
	p = find_phandle(*parp);
	if (p != NULL)
		return p;
	/*
	 * On a powermac booted with BootX, we don't get to know the
	 * phandles for any nodes, so find_phandle will return NULL.
	 * Fortunately these machines only have one interrupt controller
	 * so there isn't in fact any ambiguity.  -- paulus
	 */
	if (num_interrupt_controllers == 1)
		p = dflt_interrupt_controller;
	return p;
}
Exemplo n.º 4
0
/**
 * update_properties
 *
 * @param phandle
 * @returns 0 on success, !0 otherwise
 */
static int
update_properties(unsigned int phandle)
{
    int rc;
    char cmd[DR_PATH_MAX];
    char *longcmd = NULL;
    char *newcmd;
    int cmdlen = 0;
    int proplen = 0;
    unsigned int wa[1024];
    unsigned int *op;
    unsigned int nprop;
    unsigned int vd;
    int lenpos = 0;
    char *pname;
    unsigned int i;
    int more = 0;
    char *name = find_phandle(phandle);
    int initial = 1;

    memset(wa, 0x00, 16);
    wa[0] = phandle;

    do {
        say(DEBUG, "about to call rtas_update_properties.  work area:\n"
            "phandle %8.8x, node %s\n"
            " %8.8x %8.8x %8.8x %8.8x\n",
            phandle, name ? name : "NULL", wa[0], wa[1], wa[2], wa[3]);

        rc = rtas_update_properties((char *)wa, 1);
        if (rc && rc != 1) {
            say(DEBUG, "Error %d from rtas_update_properties()\n",
                rc);
            return 1;
        }

        say(DEBUG, "successful rtas_update_properties (more %d)\n", rc);

        op = wa+4;
        nprop = *op++;

        /* After the initial call to rtas_update_properties the first
         * property value descriptor in the buffer is the path of the
         * node being updated. Format is as follows:
         *
         * property name - 1 byte set to NULL 0x00
         * value descriptor - 4 bytes containing length of value string
         * value string - fully qualified path name of updated node
         * */
        if (initial) {
            say(DEBUG, "Null byte = %2.2x, ", *((char *)op));
            op = (unsigned int *)(((char *)op) + 1);
            vd = *op++;
            say(DEBUG, "string length = %u, path = %s\n", vd, ((char *)op));
            op = (unsigned int *)(((char *)op) + vd);
            initial = 0;

            /* The path we are skipping is inclusive in the
             * property count.
             */
            nprop--;
        }

        for (i = 0; i < nprop; i++) {
            pname = (char *)op;
            op = (unsigned int *)(pname + strlen(pname) + 1);
            vd = *op++;

            switch (vd) {
            case 0x00000000:
                say(DEBUG, "%s - name only property %s\n",
                    name, pname);
                break;

            case 0x80000000:
                say(DEBUG, "%s - delete property %s\n", name,
                    pname);
                sprintf(cmd,"remove_property %u %s",
                        phandle, pname);
                do_update(cmd, strlen(cmd) + 1);
                break;

            default:
                if (vd & 0x80000000) {
                    say(DEBUG, "partial property!\n");
                    /* twos compliment of length */
                    vd = ~vd + 1;
                    more = 1;
                }
                else {
                    more = 0;
                }

                say(DEBUG, "%s - updating property %s length "
                    "%d\n", name, pname, vd);

                /* See if we have a partially completed
                 * command
                 */
                if (longcmd) {
                    newcmd = zalloc(cmdlen + vd);
                    memcpy(newcmd, longcmd, cmdlen);
                    free(longcmd);
                    longcmd = newcmd;
                }
                else {
                    longcmd = zalloc(vd+128);
                    /* Build the command with a length
                     * of six zeros
                     */
                    lenpos = sprintf(longcmd,
                                     "update_property %u "
                                     "%s ", phandle,
                                     pname);
                    strcat(longcmd, "000000 ");
                    cmdlen = strlen(longcmd);
                }

                memcpy(longcmd + cmdlen, op, vd);
                cmdlen += vd;
                proplen += vd;

                if (! more) {
                    /* Now update the length to its actual
                    * value  and do a hideous fixup of
                     * the new trailing null
                     */
                    sprintf(longcmd+lenpos,"%06d",proplen);
                    longcmd[lenpos+6] = ' ';

                    do_update(longcmd, cmdlen);
                    free(longcmd);
                    longcmd = NULL;
                    cmdlen = 0;
                    proplen = 0;
                }

                op = (unsigned int *)(((char *)op) + vd);
            }
        }
    } while (rc == 1);

    return 0;
}
Exemplo n.º 5
0
/*
 * Map an interrupt from a device up to the platform interrupt
 * descriptor.
 */
static int __init
map_interrupt(unsigned int **irq, struct device_node **ictrler,
	      struct device_node *np, unsigned int *ints, int nintrc)
{
	struct device_node *p, *ipar;
	unsigned int *imap, *imask, *ip;
	int i, imaplen, match;
	int newintrc, newaddrc;
	unsigned int *reg;
	int naddrc;

	reg = (unsigned int *) get_property(np, "reg", NULL);
	naddrc = prom_n_addr_cells(np);
	p = intr_parent(np);
	while (p != NULL) {
		if (get_property(p, "interrupt-controller", NULL) != NULL)
			/* this node is an interrupt controller, stop here */
			break;
		imap = (unsigned int *)
			get_property(p, "interrupt-map", &imaplen);
		if (imap == NULL) {
			p = intr_parent(p);
			continue;
		}
		imask = (unsigned int *)
			get_property(p, "interrupt-map-mask", NULL);
		if (imask == NULL) {
			printk("oops, %s has interrupt-map but no mask\n",
			       p->full_name);
			return 0;
		}
		imaplen /= sizeof(unsigned int);
		match = 0;
		ipar = NULL;
		while (imaplen > 0 && !match) {
			/* check the child-interrupt field */
			match = 1;
			for (i = 0; i < naddrc && match; ++i)
				match = ((reg[i] ^ imap[i]) & imask[i]) == 0;
			for (; i < naddrc + nintrc && match; ++i)
				match = ((ints[i-naddrc] ^ imap[i]) & imask[i]) == 0;
			imap += naddrc + nintrc;
			imaplen -= naddrc + nintrc;
			/* grab the interrupt parent */
			ipar = find_phandle((phandle) *imap++);
			--imaplen;
			if (ipar == NULL && num_interrupt_controllers == 1)
				/* cope with BootX not giving us phandles */
				ipar = dflt_interrupt_controller;
			if (ipar == NULL) {
				printk("oops, no int parent %x in map of %s\n",
				       imap[-1], p->full_name);
				return 0;
			}
			/* find the parent's # addr and intr cells */
			ip = (unsigned int *)
				get_property(ipar, "#interrupt-cells", NULL);
			if (ip == NULL) {
				printk("oops, no #interrupt-cells on %s\n",
				       ipar->full_name);
				return 0;
			}
			newintrc = *ip;
			ip = (unsigned int *)
				get_property(ipar, "#address-cells", NULL);
			newaddrc = (ip == NULL)? 0: *ip;
			imap += newaddrc + newintrc;
			imaplen -= newaddrc + newintrc;
		}
		if (imaplen < 0) {
			printk("oops, error decoding int-map on %s, len=%d\n",
			       p->full_name, imaplen);
			return 0;
		}
		if (!match) {
			printk("oops, no match in %s int-map for %s\n",
			       p->full_name, np->full_name);
			return 0;
		}
		p = ipar;
		naddrc = newaddrc;
		nintrc = newintrc;
		ints = imap - nintrc;
		reg = ints - naddrc;
	}
	if (p == NULL)
		printk("hmmm, int tree for %s doesn't have ctrler\n",
		       np->full_name);
	*irq = ints;
	*ictrler = p;
	return nintrc;
}