📄 uda.c
字号:
struct udadevice *udaddr; struct uda1 *ud_ubaddr; char *start; int num, blk, unit, maxsz, blkoff, reg; struct partition *pp; register struct uba_regs *uba; register struct uba_device *ui; register struct uda1 *ud; register struct pte *io; register int i; /* * Make sure the device is a reasonable place on which to dump. */ unit = udaunit(dev); if (unit >= NRA) return (ENXIO);#define phys(cast, addr) ((cast) ((int)addr & 0x7fffffff)) ui = phys(struct uba_device *, udadinfo[unit]); if (ui == NULL || ui->ui_alive == 0) return (ENXIO); /* * Find and initialise the UBA; get the physical address of the * device registers, and of communications area and command and * response packet. */ uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; ubainit(uba); udaddr = (struct udadevice *)ui->ui_physaddr; ud = phys(struct uda1 *, &uda1); /* * Map the ca+packets into Unibus I/O space so the UDA50 can get * at them. Use the registers at the end of the Unibus map (since * we will use the registers at the beginning to map the memory * we are dumping). */ num = btoc(sizeof(struct uda1)) + 1; reg = NUBMREG - num; io = &uba->uba_map[reg]; for (i = 0; i < num; i++) *(int *)io++ = UBAMR_MRV | (btop(ud) + i); ud_ubaddr = (struct uda1 *)(((int)ud & PGOFSET) | (reg << 9)); /* * Initialise the controller, with one command and one response * packet. */ udaddr->udaip = 0; if (udadumpwait(udaddr, UDA_STEP1)) return (EFAULT); udaddr->udasa = UDA_ERR; if (udadumpwait(udaddr, UDA_STEP2)) return (EFAULT); udaddr->udasa = (int)&ud_ubaddr->uda1_ca.ca_rspdsc; if (udadumpwait(udaddr, UDA_STEP3)) return (EFAULT); udaddr->udasa = ((int)&ud_ubaddr->uda1_ca.ca_rspdsc) >> 16; if (udadumpwait(udaddr, UDA_STEP4)) return (EFAULT); uda_softc[ui->ui_ctlr].sc_micro = udaddr->udasa & 0xff; udaddr->udasa = UDA_GO; /* * Set up the command and response descriptor, then set the * controller characteristics and bring the drive on line. * Note that all uninitialised locations in uda1_cmd are zero. */ ud->uda1_ca.ca_rspdsc = (long)&ud_ubaddr->uda1_rsp.mscp_cmdref; ud->uda1_ca.ca_cmddsc = (long)&ud_ubaddr->uda1_cmd.mscp_cmdref; /* ud->uda1_cmd.mscp_sccc.sccc_ctlrflags = 0; */ /* ud->uda1_cmd.mscp_sccc.sccc_version = 0; */ if (udadumpcmd(M_OP_SETCTLRC, ud, ui)) return (EFAULT); ud->uda1_cmd.mscp_unit = ui->ui_slave; if (udadumpcmd(M_OP_ONLINE, ud, ui)) return (EFAULT); pp = phys(struct partition *, &udalabel[unit].d_partitions[udapart(dev)]); maxsz = pp->p_size; blkoff = pp->p_offset; /* * Dump all of physical memory, or as much as will fit in the * space provided. */ start = 0; num = maxfree; if (dumplo + num >= maxsz) num = maxsz - dumplo; blkoff += dumplo; /* * Write out memory, DBSIZE pages at a time. * N.B.: this code depends on the fact that the sector * size == the page size. */ while (num > 0) { blk = num > DBSIZE ? DBSIZE : num; io = uba->uba_map; /* * Map in the pages to write, leaving an invalid entry * at the end to guard against wild Unibus transfers. * Then do the write. */ for (i = 0; i < blk; i++) *(int *)io++ = UBAMR_MRV | (btop(start) + i); *(int *)io = 0; ud->uda1_cmd.mscp_unit = ui->ui_slave; ud->uda1_cmd.mscp_seq.seq_lbn = btop(start) + blkoff; ud->uda1_cmd.mscp_seq.seq_bytecount = blk << PGSHIFT; if (udadumpcmd(M_OP_WRITE, ud, ui)) return (EIO); start += blk << PGSHIFT; num -= blk; } return (0); /* made it! */}/* * Wait for some of the bits in `bits' to come on. If the error bit * comes on, or ten seconds pass without response, return true (error). */udadumpwait(udaddr, bits) register struct udadevice *udaddr; register int bits;{ register int timo = todr() + 1000; while ((udaddr->udasa & bits) == 0) { if (udaddr->udasa & UDA_ERR) { printf("udasa=%b\ndump ", udaddr->udasa, udasr_bits); return (1); } if (todr() >= timo) { printf("timeout\ndump "); return (1); } } return (0);}/* * Feed a command to the UDA50, wait for its response, and return * true iff something went wrong. */udadumpcmd(op, ud, ui) int op; register struct uda1 *ud; struct uba_device *ui;{ register struct udadevice *udaddr; register int n;#define mp (&ud->uda1_rsp) udaddr = (struct udadevice *)ui->ui_physaddr; ud->uda1_cmd.mscp_opcode = op; ud->uda1_cmd.mscp_msglen = MSCP_MSGLEN; ud->uda1_rsp.mscp_msglen = MSCP_MSGLEN; ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT; ud->uda1_ca.ca_cmddsc |= MSCP_OWN | MSCP_INT; if (udaddr->udasa & UDA_ERR) { printf("udasa=%b\ndump ", udaddr->udasa, udasr_bits); return (1); } n = udaddr->udaip; n = todr() + 1000; for (;;) { if (todr() > n) { printf("timeout\ndump "); return (1); } if (ud->uda1_ca.ca_cmdint) ud->uda1_ca.ca_cmdint = 0; if (ud->uda1_ca.ca_rspint == 0) continue; ud->uda1_ca.ca_rspint = 0; if (mp->mscp_opcode == (op | M_OP_END)) break; printf("\n"); switch (MSCP_MSGTYPE(mp->mscp_msgtc)) { case MSCPT_SEQ: printf("sequential"); break; case MSCPT_DATAGRAM: mscp_decodeerror("uda", ui->ui_ctlr, mp); printf("datagram"); break; case MSCPT_CREDITS: printf("credits"); break; case MSCPT_MAINTENANCE: printf("maintenance"); break; default: printf("unknown (type 0x%x)", MSCP_MSGTYPE(mp->mscp_msgtc)); break; } printf(" ignored\ndump "); ud->uda1_ca.ca_rspdsc |= MSCP_OWN | MSCP_INT; } if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) { printf("error: op 0x%x => 0x%x status 0x%x\ndump ", op, mp->mscp_opcode, mp->mscp_status); return (1); } return (0);#undef mp}/* * Return the size of a partition, if known, or -1 if not. */udasize(dev) dev_t dev;{ register int unit = udaunit(dev); register struct uba_device *ui; if (unit >= NRA || (ui = udadinfo[unit]) == NULL || ui->ui_alive == 0 || (ui->ui_flags & UNIT_ONLINE) == 0 || ra_info[unit].ra_state != OPEN) return (-1); return ((int)udalabel[unit].d_partitions[udapart(dev)].p_size);}#ifdef COMPAT_42/* * Tables mapping unlabelled drives. */struct size { daddr_t nblocks; daddr_t blkoff;} ra60_sizes[8] = { 15884, 0, /* A=sectors 0 thru 15883 */ 33440, 15884, /* B=sectors 15884 thru 49323 */ 400176, 0, /* C=sectors 0 thru 400175 */ 82080, 49324, /* 4.2 G => D=sectors 49324 thru 131403 */ 268772, 131404, /* 4.2 H => E=sectors 131404 thru 400175 */ 350852, 49324, /* F=sectors 49324 thru 400175 */ 157570, 242606, /* UCB G => G=sectors 242606 thru 400175 */ 193282, 49324, /* UCB H => H=sectors 49324 thru 242605 */}, ra70_sizes[8] = { 15884, 0, /* A=blk 0 thru 15883 */ 33440, 15972, /* B=blk 15972 thru 49323 */ -1, 0, /* C=blk 0 thru end */ 15884, 341220, /* D=blk 341220 thru 357103 */ 55936, 357192, /* E=blk 357192 thru 413127 */ -1, 413457, /* F=blk 413457 thru end */ -1, 341220, /* G=blk 341220 thru end */ 291346, 49731, /* H=blk 49731 thru 341076 */}, ra80_sizes[8] = { 15884, 0, /* A=sectors 0 thru 15883 */ 33440, 15884, /* B=sectors 15884 thru 49323 */ 242606, 0, /* C=sectors 0 thru 242605 */ 0, 0, /* D=unused */ 193282, 49324, /* UCB H => E=sectors 49324 thru 242605 */ 82080, 49324, /* 4.2 G => F=sectors 49324 thru 131403 */ 192696, 49910, /* G=sectors 49910 thru 242605 */ 111202, 131404, /* 4.2 H => H=sectors 131404 thru 242605 */}, ra81_sizes[8] ={/* * These are the new standard partition sizes for ra81's. * An RA_COMPAT system is compiled with D, E, and F corresponding * to the 4.2 partitions for G, H, and F respectively. */#ifndef UCBRA 15884, 0, /* A=sectors 0 thru 15883 */ 66880, 16422, /* B=sectors 16422 thru 83301 */ 891072, 0, /* C=sectors 0 thru 891071 */#ifdef RA_COMPAT 82080, 49324, /* 4.2 G => D=sectors 49324 thru 131403 */ 759668, 131404, /* 4.2 H => E=sectors 131404 thru 891071 */ 478582, 412490, /* 4.2 F => F=sectors 412490 thru 891071 */#else 15884, 375564, /* D=sectors 375564 thru 391447 */ 307200, 391986, /* E=sectors 391986 thru 699185 */ 191352, 699720, /* F=sectors 699720 thru 891071 */#endif RA_COMPAT 515508, 375564, /* G=sectors 375564 thru 891071 */ 291346, 83538, /* H=sectors 83538 thru 374883 *//* * These partitions correspond to the sizes used by sites at Berkeley, * and by those sites that have received copies of the Berkeley driver * with deltas 6.2 or greater (11/15/83). */#else UCBRA 15884, 0, /* A=sectors 0 thru 15883 */ 33440, 15884, /* B=sectors 15884 thru 49323 */ 891072, 0, /* C=sectors 0 thru 891071 */ 15884, 242606, /* D=sectors 242606 thru 258489 */ 307200, 258490, /* E=sectors 258490 thru 565689 */ 325382, 565690, /* F=sectors 565690 thru 891071 */ 648466, 242606, /* G=sectors 242606 thru 891071 */ 193282, 49324, /* H=sectors 49324 thru 242605 */#endif UCBRA}, ra82_sizes[8] = { 15884, 0, /* A=blk 0 thru 15883 */ 66880, 16245, /* B=blk 16245 thru 83124 */ -1, 0, /* C=blk 0 thru end */ 15884, 375345, /* D=blk 375345 thru 391228 */ 307200, 391590, /* E=blk 391590 thru 698789 */ -1, 699390, /* F=blk 699390 thru end */ -1, 375345, /* G=blk 375345 thru end */ 291346, 83790, /* H=blk 83790 thru 375135 */}, rc25_sizes[8] = { 15884, 0, /* A=blk 0 thru 15883 */ 10032, 15884, /* B=blk 15884 thru 49323 */ -1, 0, /* C=blk 0 thru end */ 0, 0, /* D=blk 340670 thru 356553 */ 0, 0, /* E=blk 356554 thru 412489 */ 0, 0, /* F=blk 412490 thru end */ -1, 25916, /* G=blk 49324 thru 131403 */ 0, 0, /* H=blk 131404 thru end */}, rd52_sizes[8] = { 15884, 0, /* A=blk 0 thru 15883 */ 9766, 15884, /* B=blk 15884 thru 25649 */ -1, 0, /* C=blk 0 thru end */ 0, 0, /* D=unused */ 0, 0, /* E=unused */ 0, 0, /* F=unused */ -1, 25650, /* G=blk 25650 thru end */ 0, 0, /* H=unused */}, rd53_sizes[8] = { 15884, 0, /* A=blk 0 thru 15883 */ 33440, 15884, /* B=blk 15884 thru 49323 */ -1, 0, /* C=blk 0 thru end */ 0, 0, /* D=unused */ 33440, 0, /* E=blk 0 thru 33439 */ -1, 33440, /* F=blk 33440 thru end */ -1, 49324, /* G=blk 49324 thru end */ -1, 15884, /* H=blk 15884 thru end */}, rd54_sizes[8] = { 15884, 0, /* A=blk 0 thru 15883 */ 33440, 15884, /* B=blk 15884 thru 49323 */ -1, 0, /* C=blk 0 thru end */ 130938, 49324, /* D=blk 49324 thru 180261 */ 130938, 180262, /* E=blk 180262 thru 311199 (end) */ 0, 0, /* F=unused */ 261876, 49324, /* G=blk 49324 thru 311199 (end) */ 0, 0, /* H=unused */}, rx50_sizes[8] = { 800, 0, /* A=blk 0 thru 799 */ 0, 0, -1, 0, /* C=blk 0 thru end */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};/* * Media ID decoding table. */struct udatypes { u_long ut_id; /* media drive ID */ char *ut_name; /* drive type name */ struct size *ut_sizes; /* partition tables */ int ut_nsectors, ut_ntracks, ut_ncylinders;} udatypes[] = { { MSCP_MKDRIVE2('R', 'A', 60), "ra60", ra60_sizes, 42, 4, 2382 }, { MSCP_MKDRIVE2('R', 'A', 70), "ra70", ra70_sizes, 33, 11, 1507 }, { MSCP_MKDRIVE2('R', 'A', 80), "ra80", ra80_sizes, 31, 14, 559 }, { MSCP_MKDRIVE2('R', 'A', 81), "ra81", ra81_sizes, 51, 14, 1248 }, { MSCP_MKDRIVE2('R', 'A', 82), "ra82", ra82_sizes, 57, 15, 1423 }, { MSCP_MKDRIVE2('R', 'C', 25), "rc25-removable", rc25_sizes, 42, 4, 302 }, { MSCP_MKDRIVE3('R', 'C', 'F', 25), "rc25-fixed", rc25_sizes, 42, 4, 302 }, { MSCP_MKDRIVE2('R', 'D', 52), "rd52", rd52_sizes, 18, 7, 480 }, { MSCP_MKDRIVE2('R', 'D', 53), "rd53", rd53_sizes, 18, 8, 963 }, { MSCP_MKDRIVE2('R', 'D', 32), "rd54-from-rd32", rd54_sizes, 17, 15, 1220 }, { MSCP_MKDRIVE2('R', 'D', 54), "rd54", rd54_sizes, 17, 15, 1220 }, { MSCP_MKDRIVE2('R', 'X', 50), "rx50", rx50_sizes, 10, 1, 80 }, 0};#define NTYPES (sizeof(udatypes) / sizeof(*udatypes))udamaptype(unit, lp) int unit; register struct disklabel *lp;{ register struct udatypes *ut; register struct size *sz; register struct partition *pp; register char *p; register int i; register struct ra_info *ra = &ra_info[unit]; i = MSCP_MEDIA_DRIVE(ra->ra_mediaid); for (ut = udatypes; ut->ut_id; ut++) if (ut->ut_id == i && ut->ut_nsectors == ra->ra_geom.rg_nsectors && ut->ut_ntracks == ra->ra_geom.rg_ntracks && ut->ut_ncylinders == ra->ra_geom.rg_ncyl) goto found; /* not one we know; fake up a label for the whole drive */ uda_makefakelabel(ra, lp); i = ra->ra_mediaid; /* print the port type too */ addlog(": no partition table for %c%c %c%c%c%d, size %d;\n\using (s,t,c)=(%d,%d,%d)", MSCP_MID_CHAR(4, i), MSCP_MID_CHAR(3, i), MSCP_MID_CHAR(2, i), MSCP_MID_CHAR(1, i), MSCP_MID_CHAR(0, i), MSCP_MID_NUM(i), lp->d_secperunit, lp->d_nsectors, lp->d_ntracks, lp->d_ncylinders); if (!cold) addlog("\n"); return (0);found: p = ut->ut_name; for (i = 0; i < sizeof(lp->d_typename) - 1 && *p; i++) lp->d_typename[i] = *p++; lp->d_typename[i] = 0; sz = ut->ut_sizes; lp->d_nsectors = ut->ut_nsectors; lp->d_ntracks = ut->ut_ntracks; lp->d_ncylinders = ut->ut_ncylinders; lp->d_npartitions = 8; lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; for (pp = lp->d_partitions; pp < &lp->d_partitions[8]; pp++, sz++) { pp->p_offset = sz->blkoff; if ((pp->p_size = sz->nblocks) == (u_long)-1) pp->p_size = ra->ra_dsize - sz->blkoff; } return (1);}#endif /* COMPAT_42 *//* * Construct a label for a drive from geometry information * if we have no better information. */uda_makefakelabel(ra, lp) register struct ra_info *ra; register struct disklabel *lp;{ lp->d_nsectors = ra->ra_geom.rg_nsectors; lp->d_ntracks = ra->ra_geom.rg_ntracks; lp->d_ncylinders = ra->ra_geom.rg_ncyl; lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; bcopy("ra??", lp->d_typename, sizeof("ra??")); lp->d_npartitions = 1; lp->d_partitions[0].p_offset = 0; lp->d_partitions[0].p_size = lp->d_secperunit;}#endif /* NUDA > 0 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -