/* * code to take a crash dump * on a disk attached to a KDB50 on some VAXBI machine * assume buses are, in general, already initialized */ #include "sys/param.h" #include "sys/mscp.h" #include "sys/biic.h" /* * pieces of unit number */ #define UNIT(d) ((d)&0xff) #define NODE(d) (((d)>>8)&0xf) #define BI(d) (((d)>>12)&0xf) /* * hardware parameters */ #define PHYS(x) ((long)(x)&~KSTART) struct device { short bdxx; /* unused */ short bdip; short bdsar; short bdsaw; }; /* * bits in bdsa */ #define ERR 0100000 #define STEP4 040000 #define STEP3 020000 #define STEP2 010000 #define STEP1 04000 #define GO 01 /* step4 ok */ /* * bits in ring pointers */ #define DPOWN 0x80000000 /* port owns descriptor */ #define BDACSIZE 50 /* size of a command packet, says KDB50 */ struct bdcmd { short uc_len; /* length of message */ char uc_tc; /* type, credits */ char uc_cid; /* connection id */ struct mscmd uc_p; char junk[BDACSIZE-sizeof(struct mscmd)]; }; struct bdrsp { short ur_len; /* length of message */ char ur_tc; /* type, credits */ char ur_cid; /* connection id */ struct msend ur_p; }; static struct bdx { short ud__r0; /* reserved (ugh) */ char ud__r1; char ud_bdp; /* path to purge */ short ud_cmdint; /* flag for command interrupt */ short ud_rspint; /* flag for response interrupt */ long ud_rsp; /* response pointer ring */ long ud_cmd; /* command pointer ring */ struct bdcmd ud_cp; /* the only command packet */ struct bdrsp ud_rp; /* the only response packet */ } bdx; #define CHUNK 20 /* number of blocks to write at once */ static struct biic *bdxaddr(); static bdxinit(), bdxsend(); bddump(unit, low, size) int unit; daddr_t low, size; { register struct bdx *up; extern int physmem; struct biic *addr; if (size > physmem) size = physmem; addr = bdxaddr(BI(unit), NODE(unit)); if (bdxinit(addr)) return (1); unit = UNIT(unit); up = (struct bdx *)PHYS(&bdx); up->ud_cp.uc_p.m_unit = unit; up->ud_cp.uc_p.m_opcd = OPONL; if (bdxsend(addr)) return (1); printf("onl ok\n"); up->ud_cp.uc_p.m_opcd = OPWR; up->ud_cp.uc_p.m_bcnt = size * NBPG; *(long *)&up->ud_cp.uc_p.m_buff = 0; up->ud_cp.uc_p.m_lbn = low; return (bdxsend(addr)); } static struct biic * bdxaddr(bi, node) { return ((struct biic *)(0x20000000 + (bi * 0x2000000) + (node * 0x2000))); } static bdxinit(bp) register struct biic *bp; { register struct bdx *up; register struct device *rp; up = (struct bdx *)PHYS(&bdx); up->ud_cmd = 0; up->ud_rsp = 0; bp->biintr = 0; /* no interrupts */ bp->bicsr |= BINRST; rp = (struct device *)&bp->bigpr0; while ((rp->bdsar & (ERR|STEP1)) == 0) ; if (rp->bdsar & ERR) return (1); rp->bdsaw = ERR; /* no vector, no IE, ring size 1, 1 */ while ((rp->bdsar & (ERR|STEP2)) == 0) ; if (rp->bdsar & ERR) return (1); rp->bdsaw = (short)&up->ud_rsp; /* low order part */ while ((rp->bdsar & (ERR|STEP3)) == 0) ; if (rp->bdsar & ERR) return (1); rp->bdsaw = ((long)&up->ud_rsp)>>16; /* high order part */ while ((rp->bdsar & (ERR|STEP4)) == 0) ; if (rp->bdsar & ERR) return (1); rp->bdsaw = GO; return (0); } static bdxsend(bp) struct biic *bp; { register struct bdx *up; register int x; struct device *rp; static int ref; rp = (struct device *)&bp->bigpr0; up = (struct bdx *)PHYS(&bdx); up->ud_cp.uc_p.m_crf = ++ref; up->ud_cp.uc_len = BDACSIZE; up->ud_rp.ur_len = sizeof(struct msend); up->ud_rsp = (long)&up->ud_rp.ur_p|DPOWN; up->ud_cmd = (long)&up->ud_cp.uc_p|DPOWN; x = rp->bdip; for (;;) { while (up->ud_rsp & DPOWN) ; if (up->ud_rp.ur_p.m_crf == ref) break; up->ud_rsp |= DPOWN; } if ((up->ud_rp.ur_p.m_sts & STMSK) != STSUC) { printf("bd err %o opc %o\n", up->ud_rp.ur_p.m_sts, up->ud_cp.uc_p.m_opcd); return (1); } return (0); }