/* * load comet microcode patches */ #include <stdio.h> #include <sys/types.h> #include <sys/mtpr.h> typedef long preg_t; /* type of a processor register */ typedef long word_t; /* type of a `word' in pcs */ /* * format of the patch file, as distributed by DEC * first 1k bytes are patch bits: * each bit goes in a successive 32-bit word * remaining 10k bytes are the microcode proper * each 20 bits goes in a successive 32-bit word */ #define FPATLEN 1024 /* number of bytes of packed patch bit */ #define FMICLEN 10240 /* number of bytes of packed microcode */ #define NPAT1 (FPATLEN*8) /* number of patch bits */ #define NMIC20 ((FMICLEN*8)/20) /* number of 20-bit microcode lumps */ word_t pat[NPAT1]; word_t mic[NMIC20]; /* * PCS definitions */ #define PCSPAT 0xf00000 /* first patchbit loc */ #define PCSMIC 0xf08000 /* first microcode loc */ #define PCSENA 0xf0c000 /* patchbit enable addr */ #define ENABLE 0xfff00000 /* bits to enable pcs */ #define MINVER 0x5f /* minimum ucode version supporting pcs */ #define STYPE 0xff000000 /* processor type in SID */ #define SCOMET 0x02000000 /* VAX-11/750 */ int fmem, freg; int force = 0; int babble = 0; main(argc, argv) int argc; char **argv; { while (--argc > 0 && **++argv == '-') { if (strcmp(argv[0], "-f") == 0) force++; else if (strcmp(argv[0], "-v") == 0) babble++; else usage(); } if (argc != 1) usage(); openmem(); if (force == 0 && micver() < MINVER) { fprintf(stderr, "no pcs hardware"); exit(1); } getpcs(argv[0]); loadpcs(); if (babble) printf("ucode rev x%x\n", micver()); exit(0); } usage() { fprintf(stderr, "usage: ldpcs [ -f ] [ -v ] pcsfile\n"); exit(1); } openmem() { if ((fmem = open("/dev/mem", 2)) < 0) { perror("/dev/mem"); exit(1); } if ((freg = open("/dev/mtpr", 2)) < 0) { perror("/dev/mtpr"); exit(1); } } micver() { preg_t sid; preg_t mfpr(); sid = mfpr(SID); if (force == 0 && (sid & STYPE) != SCOMET) { fprintf(stderr, "not a VAX-11/750\n"); exit(1); } return ((sid >> 8) & 0xff); } /* * get the patch bits and microcode out of the file * leave them unpacked and ready to load in pat and mic */ getpcs(f) char *f; { int fd; char ppat[FPATLEN]; char pmic[FMICLEN]; char junk; if ((fd = open(f, 0)) < 0) { perror(f); exit(1); } if (read(fd, ppat, sizeof(ppat)) != sizeof(ppat)) { fprintf(stderr, "%s: can't read patch bits\n", f); close(fd); exit(1); } if (read(fd, pmic, sizeof(pmic)) != sizeof(pmic)) { fprintf(stderr, "%s: can't read microcode\n", f); close(fd); exit(1); } /* sanity check */ if (read(fd, &junk, 1) != 0) { fprintf(stderr, "%s: bad format\n", f); close(fd); exit(1); } close(fd); unpack(ppat, pat, NPAT1, 1); unpack(pmic, mic, NMIC20, 20); } /* * load the PCS: * for safety, turn off any ucode now running there * enable patching; write patch bits; disable patching * write microcode * enable the PCS, i.e. turn it on */ loadpcs() { long w; w = 0; mwrite(fmem, (off_t)PCSMIC, (char *)&w, sizeof(w)); /* disable pcs */ w = 1; mwrite(fmem, (off_t)PCSENA, (char *)&w, sizeof(w)); /* enable patching */ mwrite(fmem, (off_t)PCSPAT, (char *)pat, sizeof(pat)); /* write patch bits */ w = 0; mwrite(fmem, (off_t)PCSENA, (char *)&w, sizeof(w)); /* disable patching */ mwrite(fmem, (off_t)PCSMIC, (char *)mic, sizeof(mic)); /* write microcode */ w = mic[0] | ENABLE; mwrite(fmem, (off_t)PCSMIC, (char *)&w, sizeof(w)); /* enable pcs */ } mwrite(fd, addr, buf, size) int fd; off_t addr; char *buf; int size; { lseek(fd, addr, 0); if (write(fd, buf, size) != size) { perror("write"); exit(1); } } preg_t mfpr(rno) int rno; { long reg; lseek(freg, (off_t)rno * sizeof(reg), 0); if (read(freg, (char *)®, sizeof(reg)) != sizeof(reg)) { perror("mtpr"); exit(1); } return (reg); }