!C99Shell v. 1.0 pre-release build #13!

Software: Apache/2.0.54 (Unix) mod_perl/1.99_09 Perl/v5.8.0 mod_ssl/2.0.54 OpenSSL/0.9.7l DAV/2 FrontPage/5.0.2.2635 PHP/4.4.0 mod_gzip/2.0.26.1a 

uname -a: Linux snow.he.net 4.4.276-v2-mono-1 #1 SMP Wed Jul 21 11:21:17 PDT 2021 i686 

uid=99(nobody) gid=98(nobody) groups=98(nobody) 

Safe-mode: OFF (not secure)

/usr/src/linux-2.4.18-xfs-1.1/arch/sparc64/kernel/   drwxr-xr-x
Free 318.33 GB of 458.09 GB (69.49%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     chmc.c (10.29 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/* $Id: chmc.c,v 1.3 2001/04/03 12:49:47 davem Exp $
 * memctrlr.c: Driver for UltraSPARC-III memory controller.
 *
 * Copyright (C) 2001 David S. Miller (davem@redhat.com)
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/init.h>
#include <asm/spitfire.h>
#include <asm/chmctrl.h>
#include <asm/oplib.h>
#include <asm/io.h>

#define CHMCTRL_NDGRPS    2
#define CHMCTRL_NDIMMS    4

#define DIMMS_PER_MC    (CHMCTRL_NDGRPS * CHMCTRL_NDIMMS)

/* OBP memory-layout property format. */
struct obp_map {
    unsigned char    dimm_map[144];
    unsigned char    pin_map[576];
};

#define DIMM_LABEL_SZ    8

struct obp_mem_layout {
    /* One max 8-byte string label per DIMM.  Usually
     * this matches the label on the motherboard where
     * that DIMM resides.
     */
    char        dimm_labels[DIMMS_PER_MC][DIMM_LABEL_SZ];

    /* If symmetric use map[0], else it is
     * asymmetric and map[1] should be used.
     */
    char        symmetric;

    struct obp_map    map[2];
};

#define CHMCTRL_NBANKS    4

struct bank_info {
    struct mctrl_info    *mp;
    int            bank_id;

    u64            raw_reg;
    int            valid;
    int            uk;
    int            um;
    int            lk;
    int            lm;
    int            interleave;
    unsigned long        base;
    unsigned long        size;
};

struct mctrl_info {
    struct list_head    list;
    int            portid;
    int            index;

    struct obp_mem_layout    layout_prop;
    int            layout_size;

    void            *regs;

    u64            timing_control1;
    u64            timing_control2;
    u64            timing_control3;
    u64            timing_control4;
    u64            memaddr_control;

    struct bank_info    logical_banks[CHMCTRL_NBANKS];
};

static LIST_HEAD(mctrl_list);

/* Does BANK decode PHYS_ADDR? */
static int bank_match(struct bank_info *bp, unsigned long phys_addr)
{
    unsigned long upper_bits = (phys_addr & PA_UPPER_BITS) >> PA_UPPER_BITS_SHIFT;
    unsigned long lower_bits = (phys_addr & PA_LOWER_BITS) >> PA_LOWER_BITS_SHIFT;

    /* Bank must be enabled to match. */
    if (bp->valid == 0)
        return 0;

    /* Would BANK match upper bits? */
    upper_bits ^= bp->um;        /* What bits are different? */
    upper_bits  = ~upper_bits;    /* Invert. */
    upper_bits |= bp->uk;        /* What bits don't matter for matching? */
    upper_bits  = ~upper_bits;    /* Invert. */

    if (upper_bits)
        return 0;

    /* Would BANK match lower bits? */
    lower_bits ^= bp->lm;        /* What bits are different? */
    lower_bits  = ~lower_bits;    /* Invert. */
    lower_bits |= bp->lk;        /* What bits don't matter for matching? */
    lower_bits  = ~lower_bits;    /* Invert. */

    if (lower_bits)
        return 0;

    /* I always knew you'd be the one. */
    return 1;
}

/* Given PHYS_ADDR, search memory controller banks for a match. */
static struct bank_info *find_bank(unsigned long phys_addr)
{
    struct list_head *mctrl_head = &mctrl_list;
    struct list_head *mctrl_entry = mctrl_head->next;

    for (;;) {
        struct mctrl_info *mp =
            list_entry(mctrl_entry, struct mctrl_info, list);
        int bank_no;

        if (mctrl_entry == mctrl_head)
            break;
        mctrl_entry = mctrl_entry->next;

        for (bank_no = 0; bank_no < CHMCTRL_NBANKS; bank_no++) {
            struct bank_info *bp;

            bp = &mp->logical_banks[bank_no];
            if (bank_match(bp, phys_addr))
                return bp;
        }
    }

    return NULL;
}

/* This is the main purpose of this driver. */
#define SYNDROME_MIN    -1
#define SYNDROME_MAX    144
int chmc_getunumber(int syndrome_code,
            unsigned long phys_addr,
            char *buf, int buflen)
{
    struct bank_info *bp;
    struct obp_mem_layout *prop;
    int bank_in_controller, first_dimm;

    bp = find_bank(phys_addr);
    if (bp == NULL ||
        syndrome_code < SYNDROME_MIN ||
        syndrome_code > SYNDROME_MAX) {
        buf[0] = '?';
        buf[1] = '?';
        buf[2] = '?';
        buf[3] = '\0';
        return 0;
    }

    prop = &bp->mp->layout_prop;
    bank_in_controller = bp->bank_id & (CHMCTRL_NBANKS - 1);
    first_dimm  = (bank_in_controller & (CHMCTRL_NDGRPS - 1));
    first_dimm *= CHMCTRL_NDIMMS;

    if (syndrome_code != SYNDROME_MIN) {
        struct obp_map *map;
        int qword, where_in_line, where, map_index, map_offset;
        unsigned int map_val;

        /* Yaay, single bit error so we can figure out
         * the exact dimm.
         */
        if (prop->symmetric)
            map = &prop->map[0];
        else
            map = &prop->map[1];

        /* Covert syndrome code into the way the bits are
         * positioned on the bus.
         */
        if (syndrome_code < 144 - 16)
            syndrome_code += 16;
        else if (syndrome_code < 144)
            syndrome_code -= (144 - 7);
        else if (syndrome_code < (144 + 3))
            syndrome_code -= (144 + 3 - 4);
        else
            syndrome_code -= 144 + 3;

        /* All this magic has to do with how a cache line
         * comes over the wire on Safari.  A 64-bit line
         * comes over in 4 quadword cycles, each of which
         * transmit ECC/MTAG info as well as the actual
         * data.  144 bits per quadword, 576 total.
         */
#define LINE_SIZE    64
#define LINE_ADDR_MSK    (LINE_SIZE - 1)
#define QW_PER_LINE    4
#define QW_BYTES    (LINE_SIZE / QW_PER_LINE)
#define QW_BITS        144
#define LAST_BIT    (576 - 1)

        qword = (phys_addr & LINE_ADDR_MSK) / QW_BYTES;
        where_in_line = ((3 - qword) * QW_BITS) + syndrome_code;
        where = (LAST_BIT - where_in_line);
        map_index = where >> 2;
        map_offset = where & 0x3;
        map_val = map->dimm_map[map_index];
        map_val = ((map_val >> ((3 - map_offset) << 1)) & (2 - 1));

        sprintf(buf, "%s, pin %3d",
            prop->dimm_labels[first_dimm + map_val],
            map->pin_map[where_in_line]);
    } else {
        int dimm;

        /* Multi-bit error, we just dump out all the
         * dimm labels assosciated with this bank.
         */
        for (dimm = 0; dimm < CHMCTRL_NDIMMS; dimm++) {
            sprintf(buf, "%s ",
                prop->dimm_labels[first_dimm + dimm]);
            buf += strlen(buf);
        }
    }
    return 0;
}

/* Accessing the registers is slightly complicated.  If you want
 * to get at the memory controller which is on the same processor
 * the code is executing, you must use special ASI load/store else
 * you go through the global mapping.
 */
static u64 read_mcreg(struct mctrl_info *mp, unsigned long offset)
{
    unsigned long ret;

    if (mp->portid == smp_processor_id()) {
        __asm__ __volatile__("ldxa    [%1] %2, %0"
                     : "=r" (ret)
                     : "r" (offset), "i" (ASI_MCU_CTRL_REG));
    } else {
        __asm__ __volatile__("ldxa    [%1] %2, %0"
                     : "=r" (ret)
                     : "r" (mp->regs + offset),
                       "i" (ASI_PHYS_BYPASS_EC_E));
    }
    return ret;
}

#if 0 /* currently unused */
static void write_mcreg(struct mctrl_info *mp, unsigned long offset, u64 val)
{
    if (mp->portid == smp_processor_id()) {
        __asm__ __volatile__("stxa    %0, [%1] %2"
                     : : "r" (val),
                         "r" (offset), "i" (ASI_MCU_CTRL_REG));
    } else {
        __asm__ __volatile__("ldxa    %0, [%1] %2"
                     : : "r" (val),
                         "r" (mp->regs + offset),
                         "i" (ASI_PHYS_BYPASS_EC_E));
    }
}
#endif

static void interpret_one_decode_reg(struct mctrl_info *mp, int which_bank, u64 val)
{
    struct bank_info *p = &mp->logical_banks[which_bank];

    p->mp = mp;
    p->bank_id = (CHMCTRL_NBANKS * mp->portid) + which_bank;
    p->raw_reg = val;
    p->valid = (val & MEM_DECODE_VALID) >> MEM_DECODE_VALID_SHIFT;
    p->uk = (val & MEM_DECODE_UK) >> MEM_DECODE_UK_SHIFT;
    p->um = (val & MEM_DECODE_UM) >> MEM_DECODE_UM_SHIFT;
    p->lk = (val & MEM_DECODE_LK) >> MEM_DECODE_LK_SHIFT;
    p->lm = (val & MEM_DECODE_LM) >> MEM_DECODE_LM_SHIFT;

    p->base  =  (p->um);
    p->base &= ~(p->uk);
    p->base <<= PA_UPPER_BITS_SHIFT;

    switch(p->lk) {
    case 0xf:
    default:
        p->interleave = 1;
        break;

    case 0xe:
        p->interleave = 2;
        break;

    case 0xc:
        p->interleave = 4;
        break;

    case 0x8:
        p->interleave = 8;
        break;

    case 0x0:
        p->interleave = 16;
        break;
    };

    /* UK[10] is reserved, and UK[11] is not set for the SDRAM
     * bank size definition.
     */
    p->size = (((unsigned long)p->uk &
            ((1UL << 10UL) - 1UL)) + 1UL) << PA_UPPER_BITS_SHIFT;
    p->size /= p->interleave;
}

static void fetch_decode_regs(struct mctrl_info *mp)
{
    if (mp->layout_size == 0)
        return;

    interpret_one_decode_reg(mp, 0,
                 read_mcreg(mp, CHMCTRL_DECODE1));
    interpret_one_decode_reg(mp, 1,
                 read_mcreg(mp, CHMCTRL_DECODE2));
    interpret_one_decode_reg(mp, 2,
                 read_mcreg(mp, CHMCTRL_DECODE3));
    interpret_one_decode_reg(mp, 3,
                 read_mcreg(mp, CHMCTRL_DECODE4));
}

static int init_one_mctrl(int node, int index)
{
    struct mctrl_info *mp = kmalloc(sizeof(*mp), GFP_KERNEL);
    int portid = prom_getintdefault(node, "portid", -1);
    struct linux_prom64_registers p_reg_prop;
    int t;

    if (!mp)
        return -1;
    memset(mp, 0, sizeof(*mp));
    if (portid == -1)
        goto fail;

    mp->portid = portid;
    mp->layout_size = prom_getproplen(node, "memory-layout");
    if (mp->layout_size < 0)
        mp->layout_size = 0;
    if (mp->layout_size > sizeof(mp->layout_prop))
        goto fail;

    if (mp->layout_size > 0)
        prom_getproperty(node, "memory-layout",
                 (char *) &mp->layout_prop,
                 mp->layout_size);

    t = prom_getproperty(node, "reg",
                 (char *) &p_reg_prop,
                 sizeof(p_reg_prop));
    if (t < 0 || p_reg_prop.reg_size != 0x48)
        goto fail;

    mp->regs = ioremap(p_reg_prop.phys_addr, p_reg_prop.reg_size);
    if (mp->regs == NULL)
        goto fail;

    if (mp->layout_size != 0UL) {
        mp->timing_control1 = read_mcreg(mp, CHMCTRL_TCTRL1);
        mp->timing_control2 = read_mcreg(mp, CHMCTRL_TCTRL2);
        mp->timing_control3 = read_mcreg(mp, CHMCTRL_TCTRL3);
        mp->timing_control4 = read_mcreg(mp, CHMCTRL_TCTRL4);
        mp->memaddr_control = read_mcreg(mp, CHMCTRL_MACTRL);
    }

    fetch_decode_regs(mp);

    mp->index = index;

    list_add(&mp->list, &mctrl_list);

    /* Report the device. */
    printk(KERN_INFO "chmc%d: US3 memory controller at %p [%s]\n",
           mp->index,
           mp->regs, (mp->layout_size ? "ACTIVE" : "INACTIVE"));

    return 0;

fail:
    if (mp) {
        if (mp->regs != NULL)
            iounmap(mp->regs);
        kfree(mp);
    }
    return -1;
}

static int __init probe_for_string(char *name, int index)
{
    int node = prom_getchild(prom_root_node);

    while ((node = prom_searchsiblings(node, name)) != 0) {
        int ret = init_one_mctrl(node, index);

        if (!ret)
            index++;

        node = prom_getsibling(node);
        if (!node)
            break;
    }

    return index;
}

static int __init chmc_init(void)
{
    int index;

    /* This driver is only for cheetah platforms. */
    if (tlb_type != cheetah)
        return -ENODEV;

    index = probe_for_string("memory-controller", 0);
    index = probe_for_string("mc-us3", index);

    return 0;
}

static void __exit chmc_cleanup(void)
{
    struct list_head *head = &mctrl_list;
    struct list_head *tmp = head->next;

    for (;;) {
        struct mctrl_info *p =
            list_entry(tmp, struct mctrl_info, list);
        if (tmp == head)
            break;
        tmp = tmp->next;

        list_del(&p->list);
        iounmap(p->regs);
        kfree(p);
    }
}

module_init(chmc_init);
module_exit(chmc_cleanup);

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 1.0 pre-release build #13 powered by Captain Crunch Security Team | http://ccteam.ru | Generation time: 0.0047 ]--