📄 voyager_cat.c
字号:
return 1; } outb(VOYAGER_CAT_HEADER, CAT_DATA); outb(value, CAT_DATA); if(inb(CAT_DATA) != VOYAGER_CAT_HEADER) { CDEBUG(("cat_senddata: failed to get correct header response to sent data\n")); return 1; } if(reg > VOYAGER_SUBADDRHI) { outb(VOYAGER_CAT_RUN, CAT_CMD); outb(VOYAGER_CAT_END, CAT_CMD); outb(VOYAGER_CAT_RUN, CAT_CMD); } return 0; } else { __u16 hbytes = asicp->ireg_length / BITS_PER_BYTE; __u16 dbytes = (modp->num_asics - 1 + asicp->ireg_length)/BITS_PER_BYTE; __u8 padbits, dseq[VOYAGER_MAX_SCAN_PATH], hseq[VOYAGER_MAX_REG_SIZE]; int i; if((padbits = (modp->num_asics - 1 + asicp->ireg_length) % BITS_PER_BYTE) != 0) { padbits = BITS_PER_BYTE - padbits; dbytes++; } if(asicp->ireg_length % BITS_PER_BYTE) hbytes++; cat_build_header(hseq, hbytes, 1, asicp->ireg_length); for(i = 0; i < dbytes + hbytes; i++) dseq[i] = 0xff; CDEBUG(("cat_senddata: dbytes=%d, hbytes=%d, padbits=%d\n", dbytes, hbytes, padbits)); cat_pack(dseq, modp->num_asics - 1 + asicp->ireg_length, hseq, hbytes * BITS_PER_BYTE); cat_pack(dseq, asicp->asic_location, &value, asicp->ireg_length);#ifdef VOYAGER_CAT_DEBUG printk("dseq "); for(i=0; i<hbytes+dbytes; i++) { printk("0x%x ", dseq[i]); } printk("\n");#endif return cat_shiftout(dseq, dbytes, hbytes, padbits); }}static intcat_write(voyager_module_t *modp, voyager_asic_t *asicp, __u8 reg, __u8 value){ if(cat_sendinst(modp, asicp, reg, VOYAGER_WRITE_CONFIG)) return 1; return cat_senddata(modp, asicp, reg, value);}static intcat_read(voyager_module_t *modp, voyager_asic_t *asicp, __u8 reg, __u8 *value){ if(cat_sendinst(modp, asicp, reg, VOYAGER_READ_CONFIG)) return 1; return cat_getdata(modp, asicp, reg, value);}static intcat_subaddrsetup(voyager_module_t *modp, voyager_asic_t *asicp, __u16 offset, __u16 len){ __u8 val; if(len > 1) { /* set auto increment */ __u8 newval; if(cat_read(modp, asicp, VOYAGER_AUTO_INC_REG, &val)) { CDEBUG(("cat_subaddrsetup: read of VOYAGER_AUTO_INC_REG failed\n")); return 1; } CDEBUG(("cat_subaddrsetup: VOYAGER_AUTO_INC_REG = 0x%x\n", val)); newval = val | VOYAGER_AUTO_INC; if(newval != val) { if(cat_write(modp, asicp, VOYAGER_AUTO_INC_REG, val)) { CDEBUG(("cat_subaddrsetup: write to VOYAGER_AUTO_INC_REG failed\n")); return 1; } } } if(cat_write(modp, asicp, VOYAGER_SUBADDRLO, (__u8)(offset &0xff))) { CDEBUG(("cat_subaddrsetup: write to SUBADDRLO failed\n")); return 1; } if(asicp->subaddr > VOYAGER_SUBADDR_LO) { if(cat_write(modp, asicp, VOYAGER_SUBADDRHI, (__u8)(offset >> 8))) { CDEBUG(("cat_subaddrsetup: write to SUBADDRHI failed\n")); return 1; } cat_read(modp, asicp, VOYAGER_SUBADDRHI, &val); CDEBUG(("cat_subaddrsetup: offset = %d, hi = %d\n", offset, val)); } cat_read(modp, asicp, VOYAGER_SUBADDRLO, &val); CDEBUG(("cat_subaddrsetup: offset = %d, lo = %d\n", offset, val)); return 0;} static intcat_subwrite(voyager_module_t *modp, voyager_asic_t *asicp, __u16 offset, __u16 len, void *buf){ int i, retval; /* FIXME: need special actions for VOYAGER_CAT_ID here */ if(asicp->asic_id == VOYAGER_CAT_ID) { CDEBUG(("cat_subwrite: ATTEMPT TO WRITE TO CAT ASIC\n")); /* FIXME -- This is supposed to be handled better * There is a problem writing to the cat asic in the * PSI. The 30us delay seems to work, though */ udelay(30); } if((retval = cat_subaddrsetup(modp, asicp, offset, len)) != 0) { printk("cat_subwrite: cat_subaddrsetup FAILED\n"); return retval; } if(cat_sendinst(modp, asicp, VOYAGER_SUBADDRDATA, VOYAGER_WRITE_CONFIG)) { printk("cat_subwrite: cat_sendinst FAILED\n"); return 1; } for(i = 0; i < len; i++) { if(cat_senddata(modp, asicp, 0xFF, ((__u8 *)buf)[i])) { printk("cat_subwrite: cat_sendata element at %d FAILED\n", i); return 1; } } return 0;}static intcat_subread(voyager_module_t *modp, voyager_asic_t *asicp, __u16 offset, __u16 len, void *buf){ int i, retval; if((retval = cat_subaddrsetup(modp, asicp, offset, len)) != 0) { CDEBUG(("cat_subread: cat_subaddrsetup FAILED\n")); return retval; } if(cat_sendinst(modp, asicp, VOYAGER_SUBADDRDATA, VOYAGER_READ_CONFIG)) { CDEBUG(("cat_subread: cat_sendinst failed\n")); return 1; } for(i = 0; i < len; i++) { if(cat_getdata(modp, asicp, 0xFF, &((__u8 *)buf)[i])) { CDEBUG(("cat_subread: cat_getdata element %d failed\n", i)); return 1; } } return 0;}/* buffer for storing EPROM data read in during initialisation */static __initdata __u8 eprom_buf[0xFFFF];static voyager_module_t *voyager_initial_module;/* Initialise the cat bus components. We assume this is called by the * boot cpu *after* all memory initialisation has been done (so we can * use kmalloc) but before smp initialisation, so we can probe the SMP * configuration and pick up necessary information. */void __initvoyager_cat_init(void){ voyager_module_t **modpp = &voyager_initial_module; voyager_asic_t **asicpp; voyager_asic_t *qabc_asic = NULL; int i, j; unsigned long qic_addr = 0; __u8 qabc_data[0x20]; __u8 num_submodules, val; voyager_eprom_hdr_t *eprom_hdr = (voyager_eprom_hdr_t *)&eprom_buf[0]; __u8 cmos[4]; unsigned long addr; /* initiallise the SUS mailbox */ for(i=0; i<sizeof(cmos); i++) cmos[i] = voyager_extended_cmos_read(VOYAGER_DUMP_LOCATION + i); addr = *(unsigned long *)cmos; if((addr & 0xff000000) != 0xff000000) { printk(KERN_ERR "Voyager failed to get SUS mailbox (addr = 0x%lx\n", addr); } else { static struct resource res; res.name = "voyager SUS"; res.start = addr; res.end = addr+0x3ff; request_resource(&iomem_resource, &res); voyager_SUS = (struct voyager_SUS *) ioremap(addr, 0x400); printk(KERN_NOTICE "Voyager SUS mailbox version 0x%x\n", voyager_SUS->SUS_version); voyager_SUS->kernel_version = VOYAGER_MAILBOX_VERSION; voyager_SUS->kernel_flags = VOYAGER_OS_HAS_SYSINT; } /* clear the processor counts */ voyager_extended_vic_processors = 0; voyager_quad_processors = 0; printk("VOYAGER: beginning CAT bus probe\n"); /* set up the SuperSet Port Block which tells us where the * CAT communication port is */ sspb = inb(VOYAGER_SSPB_RELOCATION_PORT) * 0x100; VDEBUG(("VOYAGER DEBUG: sspb = 0x%x\n", sspb)); /* now find out if were 8 slot or normal */ if((inb(VIC_PROC_WHO_AM_I) & EIGHT_SLOT_IDENTIFIER) == EIGHT_SLOT_IDENTIFIER) { voyager_8slot = 1; printk(KERN_NOTICE "Voyager: Eight slot 51xx configuration detected\n"); } for(i = VOYAGER_MIN_MODULE; i <= VOYAGER_MAX_MODULE; i++) { __u8 input; int asic; __u16 eprom_size; __u16 sp_offset; outb(VOYAGER_CAT_DESELECT, VOYAGER_CAT_CONFIG_PORT); outb(i, VOYAGER_CAT_CONFIG_PORT); /* check the presence of the module */ outb(VOYAGER_CAT_RUN, CAT_CMD); outb(VOYAGER_CAT_IRCYC, CAT_CMD); outb(VOYAGER_CAT_HEADER, CAT_DATA); /* stream series of alternating 1's and 0's to stimulate * response */ outb(0xAA, CAT_DATA); input = inb(CAT_DATA); outb(VOYAGER_CAT_END, CAT_CMD); if(input != VOYAGER_CAT_HEADER) { continue; } CDEBUG(("VOYAGER DEBUG: found module id 0x%x, %s\n", i, cat_module_name(i))); *modpp = kmalloc(sizeof(voyager_module_t), GFP_KERNEL); /*&voyager_module_storage[cat_count++];*/ if(*modpp == NULL) { printk("**WARNING** kmalloc failure in cat_init\n"); continue; } memset(*modpp, 0, sizeof(voyager_module_t)); /* need temporary asic for cat_subread. It will be * filled in correctly later */ (*modpp)->asic = kmalloc(sizeof(voyager_asic_t), GFP_KERNEL); /*&voyager_asic_storage[asic_count];*/ if((*modpp)->asic == NULL) { printk("**WARNING** kmalloc failure in cat_init\n"); continue; } memset((*modpp)->asic, 0, sizeof(voyager_asic_t)); (*modpp)->asic->asic_id = VOYAGER_CAT_ID; (*modpp)->asic->subaddr = VOYAGER_SUBADDR_HI; (*modpp)->module_addr = i; (*modpp)->scan_path_connected = 0; if(i == VOYAGER_PSI) { /* Exception leg for modules with no EEPROM */ printk("Module \"%s\"\n", cat_module_name(i)); continue; } CDEBUG(("cat_init: Reading eeprom for module 0x%x at offset %d\n", i, VOYAGER_XSUM_END_OFFSET)); outb(VOYAGER_CAT_RUN, CAT_CMD); cat_disconnect(*modpp, (*modpp)->asic); if(cat_subread(*modpp, (*modpp)->asic, VOYAGER_XSUM_END_OFFSET, sizeof(eprom_size), &eprom_size)) { printk("**WARNING**: Voyager couldn't read EPROM size for module 0x%x\n", i); outb(VOYAGER_CAT_END, CAT_CMD); continue; } if(eprom_size > sizeof(eprom_buf)) { printk("**WARNING**: Voyager insufficient size to read EPROM data, module 0x%x. Need %d\n", i, eprom_size); outb(VOYAGER_CAT_END, CAT_CMD); continue; } outb(VOYAGER_CAT_END, CAT_CMD); outb(VOYAGER_CAT_RUN, CAT_CMD); CDEBUG(("cat_init: module 0x%x, eeprom_size %d\n", i, eprom_size)); if(cat_subread(*modpp, (*modpp)->asic, 0, eprom_size, eprom_buf)) { outb(VOYAGER_CAT_END, CAT_CMD); continue; } outb(VOYAGER_CAT_END, CAT_CMD); printk("Module \"%s\", version 0x%x, tracer 0x%x, asics %d\n", cat_module_name(i), eprom_hdr->version_id, *((__u32 *)eprom_hdr->tracer), eprom_hdr->num_asics); (*modpp)->ee_size = eprom_hdr->ee_size; (*modpp)->num_asics = eprom_hdr->num_asics; asicpp = &((*modpp)->asic); sp_offset = eprom_hdr->scan_path_offset; /* All we really care about are the Quad cards. We * identify them because they are in a processor slot * and have only four asics */ if((i < 0x10 || (i>=0x14 && i < 0x1c) || i>0x1f)) { modpp = &((*modpp)->next); continue; } /* Now we know it's in a processor slot, does it have * a quad baseboard submodule */ outb(VOYAGER_CAT_RUN, CAT_CMD); cat_read(*modpp, (*modpp)->asic, VOYAGER_SUBMODPRESENT, &num_submodules); /* lowest two bits, active low */ num_submodules = ~(0xfc | num_submodules); CDEBUG(("VOYAGER CAT: %d submodules present\n", num_submodules)); if(num_submodules == 0) { /* fill in the dyadic extended processors */ __u8 cpu = i & 0x07; printk("Module \"%s\": Dyadic Processor Card\n", cat_module_name(i)); voyager_extended_vic_processors |= (1<<cpu); cpu += 4; voyager_extended_vic_processors |= (1<<cpu); outb(VOYAGER_CAT_END, CAT_CMD); continue; } /* now we want to read the asics on the first submodule, * which should be the quad base board */ cat_read(*modpp, (*modpp)->asic, VOYAGER_SUBMODSELECT, &val); CDEBUG(("cat_init: SUBMODSELECT value = 0x%x\n", val)); val = (val & 0x7c) | VOYAGER_QUAD_BASEBOARD; cat_write(*modpp, (*modpp)->asic, VOYAGER_SUBMODSELECT, val); outb(VOYAGER_CAT_END, CAT_CMD); CDEBUG(("cat_init: Reading eeprom for module 0x%x at offset %d\n", i, VOYAGER_XSUM_END_OFFSET)); outb(VOYAGER_CAT_RUN, CAT_CMD); cat_disconnect(*modpp, (*modpp)->asic); if(cat_subread(*modpp, (*modpp)->asic, VOYAGER_XSUM_END_OFFSET, sizeof(eprom_size), &eprom_size)) { printk("**WARNING**: Voyager couldn't read EPROM size for module 0x%x\n", i); outb(VOYAGER_CAT_END, CAT_CMD); continue; } if(eprom_size > sizeof(eprom_buf)) { printk("**WARNING**: Voyager insufficient size to read EPROM data, module 0x%x. Need %d\n", i, eprom_size); outb(VOYAGER_CAT_END, CAT_CMD); continue; } outb(VOYAGER_CAT_END, CAT_CMD); outb(VOYAGER_CAT_RUN, CAT_CMD); CDEBUG(("cat_init: module 0x%x, eeprom_size %d\n", i, eprom_size)); if(cat_subread(*modpp, (*modpp)->asic, 0, eprom_size, eprom_buf)) { outb(VOYAGER_CAT_END, CAT_CMD); continue; } outb(VOYAGER_CAT_END, CAT_CMD); /* Now do everything for the QBB submodule 1 */ (*modpp)->ee_size = eprom_hdr->ee_size; (*modpp)->num_asics = eprom_hdr->num_asics; asicpp = &((*modpp)->asic); sp_offset = eprom_hdr->scan_path_offset; /* get rid of the dummy CAT asic and read the real one */ kfree((*modpp)->asic); for(asic=0; asic < (*modpp)->num_asics; asic++) { int j; voyager_asic_t *asicp = *asicpp = kzalloc(sizeof(voyager_asic_t), GFP_KERNEL); /*&voyager_asic_storage[asic_count++];*/ voyager_sp_table_t *sp_table; voyager_at_t *asic_table; voyager_jtt_t *jtag_table; if(asicp == NULL) { printk("**WARNING** kmalloc failure in cat_init\n"); continue; } asicpp = &(asicp->next);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -