123308Smckusick /* 223308Smckusick * Copyright (c) 1982 Regents of the University of California. 323308Smckusick * All rights reserved. The Berkeley software License Agreement 423308Smckusick * specifies the terms and conditions for redistribution. 523308Smckusick * 6*28987Skarels * @(#)hp.c 6.23 (Berkeley) 06/03/86 723308Smckusick */ 83706Sroot 93706Sroot #ifdef HPDEBUG 103289Swnj int hpdebug; 113706Sroot #endif 123706Sroot #ifdef HPBDEBUG 133706Sroot int hpbdebug; 143706Sroot #endif 1521Sbill 161939Swnj #include "hp.h" 171565Sbill #if NHP > 0 1821Sbill /* 195726Sroot * HP disk driver for RP0x+RMxx+ML11 202827Swnj * 212827Swnj * TODO: 223706Sroot * see if DCLR and/or RELEASE set attention status 2321Sbill */ 249786Ssam #include "../machine/pte.h" 2521Sbill 2617120Sbloom #include "param.h" 2717120Sbloom #include "systm.h" 2817120Sbloom #include "dk.h" 2917120Sbloom #include "buf.h" 3017120Sbloom #include "conf.h" 3117120Sbloom #include "dir.h" 3217120Sbloom #include "user.h" 3317120Sbloom #include "map.h" 348468Sroot #include "../vax/mtpr.h" 3517120Sbloom #include "vm.h" 3617120Sbloom #include "cmap.h" 3717120Sbloom #include "dkbad.h" 3817120Sbloom #include "ioctl.h" 3917120Sbloom #include "uio.h" 4018411Skarels #include "syslog.h" 4121Sbill 428988Sroot #include "../vax/dkio.h" 4317120Sbloom #include "mbareg.h" 4417120Sbloom #include "mbavar.h" 4517120Sbloom #include "hpreg.h" 4621Sbill 472383Swnj /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ 482383Swnj struct size { 4921Sbill daddr_t nblocks; 5021Sbill int cyloff; 5111212Ssam } rp06_sizes[8] = { 52886Sbill 15884, 0, /* A=cyl 0 thru 37 */ 53886Sbill 33440, 38, /* B=cyl 38 thru 117 */ 54886Sbill 340670, 0, /* C=cyl 0 thru 814 */ 5511212Ssam 15884, 118, /* D=cyl 118 thru 155 */ 5611212Ssam 55936, 156, /* E=cyl 156 thru 289 */ 5711212Ssam 219384, 290, /* F=cyl 290 thru 814 */ 5811212Ssam 291280, 118, /* G=cyl 118 thru 814 */ 5921Sbill 0, 0, 6011212Ssam }, rp05_sizes[8] = { 6111212Ssam 15884, 0, /* A=cyl 0 thru 37 */ 6211212Ssam 33440, 38, /* B=cyl 38 thru 117 */ 6311212Ssam 171798, 0, /* C=cyl 0 thru 410 */ 6411212Ssam 15884, 118, /* D=cyl 118 thru 155 */ 6511212Ssam 55936, 156, /* E=cyl 156 thru 289 */ 6611212Ssam 50512, 290, /* F=cyl 290 thru 410 */ 6711212Ssam 122408, 118, /* G=cyl 118 thru 410 */ 6821Sbill 0, 0, 6911212Ssam }, rm03_sizes[8] = { 70886Sbill 15884, 0, /* A=cyl 0 thru 99 */ 7111212Ssam 33440, 100, /* B=cyl 100 thru 308 */ 72886Sbill 131680, 0, /* C=cyl 0 thru 822 */ 7311212Ssam 15884, 309, /* D=cyl 309 thru 408 */ 7411212Ssam 55936, 409, /* E=cyl 409 thru 758 */ 7511212Ssam 10144, 759, /* F=cyl 759 thru 822 */ 7611212Ssam 82144, 309, /* G=cyl 309 thru 822 */ 7721Sbill 0, 0, 7811212Ssam }, rm05_sizes[8] = { 79886Sbill 15884, 0, /* A=cyl 0 thru 26 */ 80886Sbill 33440, 27, /* B=cyl 27 thru 81 */ 813271Swnj 500384, 0, /* C=cyl 0 thru 822 */ 82886Sbill 15884, 562, /* D=cyl 562 thru 588 */ 83886Sbill 55936, 589, /* E=cyl 589 thru 680 */ 843729Sroot 86240, 681, /* F=cyl 681 thru 822 */ 853729Sroot 158592, 562, /* G=cyl 562 thru 822 */ 86886Sbill 291346, 82, /* H=cyl 82 thru 561 */ 872383Swnj }, rm80_sizes[8] = { 882383Swnj 15884, 0, /* A=cyl 0 thru 36 */ 892383Swnj 33440, 37, /* B=cyl 37 thru 114 */ 902383Swnj 242606, 0, /* C=cyl 0 thru 558 */ 9111212Ssam 15884, 115, /* D=cyl 115 thru 151 */ 9211212Ssam 55936, 152, /* E=cyl 152 thru 280 */ 9311212Ssam 120559, 281, /* F=cyl 281 thru 558 */ 9411212Ssam 192603, 115, /* G=cyl 115 thru 558 */ 952383Swnj 0, 0, 9611212Ssam }, rp07_sizes[8] = { 976927Ssam 15884, 0, /* A=cyl 0 thru 9 */ 9811212Ssam 66880, 10, /* B=cyl 10 thru 51 */ 9911212Ssam 1008000, 0, /* C=cyl 0 thru 629 */ 10011212Ssam 15884, 235, /* D=cyl 235 thru 244 */ 10111212Ssam 307200, 245, /* E=cyl 245 thru 436 */ 10211212Ssam 308650, 437, /* F=cyl 437 thru 629 */ 10311212Ssam 631850, 235, /* G=cyl 235 thru 629 */ 10411212Ssam 291346, 52, /* H=cyl 52 thru 234 */ 10511212Ssam }, cdc9775_sizes[8] = { 10611212Ssam 15884, 0, /* A=cyl 0 thru 12 */ 10711212Ssam 66880, 13, /* B=cyl 13 thru 65 */ 10815101Skarels 1077760, 0, /* C=cyl 0 thru 841 */ 10911212Ssam 15884, 294, /* D=cyl 294 thru 306 */ 11011212Ssam 307200, 307, /* E=cyl 307 thru 546 */ 11115101Skarels 377440, 547, /* F=cyl 547 thru 841 */ 11215101Skarels 701280, 294, /* G=cyl 294 thru 841 */ 11311212Ssam 291346, 66, /* H=cyl 66 thru 293 */ 11411212Ssam }, cdc9730_sizes[8] = { 1156927Ssam 15884, 0, /* A=cyl 0 thru 49 */ 1166927Ssam 33440, 50, /* B=cyl 50 thru 154 */ 1176927Ssam 263360, 0, /* C=cyl 0 thru 822 */ 11811212Ssam 15884, 155, /* D=cyl 155 thru 204 */ 11911212Ssam 55936, 205, /* E=cyl 205 thru 379 */ 12011212Ssam 141664, 380, /* F=cyl 380 thru 822 */ 12111212Ssam 213664, 155, /* G=cyl 155 thru 822 */ 1226927Ssam 0, 0, 12311212Ssam }, capricorn_sizes[8] = { 1246927Ssam 15884, 0, /* A=cyl 0 thru 31 */ 1256927Ssam 33440, 32, /* B=cyl 32 thru 97 */ 1266927Ssam 524288, 0, /* C=cyl 0 thru 1023 */ 12711212Ssam 15884, 668, /* D=cyl 668 thru 699 */ 12811212Ssam 55936, 700, /* E=cyl 700 thru 809 */ 12911212Ssam 109472, 810, /* F=cyl 810 thru 1023 */ 13011212Ssam 182176, 668, /* G=cyl 668 thru 1023 */ 1316927Ssam 291346, 98, /* H=cyl 98 thru 667 */ 13211212Ssam }, eagle_sizes[8] = { 13310734Ssam 15884, 0, /* A=cyl 0 thru 16 */ 13411212Ssam 66880, 17, /* B=cyl 17 thru 86 */ 13511629Ssam 808320, 0, /* C=cyl 0 thru 841 */ 13611212Ssam 15884, 391, /* D=cyl 391 thru 407 */ 13711212Ssam 307200, 408, /* E=cyl 408 thru 727 */ 13811629Ssam 109296, 728, /* F=cyl 728 thru 841 */ 13911629Ssam 432816, 391, /* G=cyl 391 thru 841 */ 14011212Ssam 291346, 87, /* H=cyl 87 thru 390 */ 14113202Sroot }, ampex_sizes[8] = { 14211281Ssam 15884, 0, /* A=cyl 0 thru 26 */ 14311281Ssam 33440, 27, /* B=cyl 27 thru 81 */ 14413184Shelge 495520, 0, /* C=cyl 0 thru 814 */ 14511281Ssam 15884, 562, /* D=cyl 562 thru 588 */ 14611281Ssam 55936, 589, /* E=cyl 589 thru 680 */ 14713184Shelge 81312, 681, /* F=cyl 681 thru 814 */ 14813184Shelge 153664, 562, /* G=cyl 562 thru 814 */ 14911281Ssam 291346, 82, /* H=cyl 82 thru 561 */ 15028908Skarels }, fj2361_sizes[8] = { 15128908Skarels 15884, 0, /* A=cyl 0 thru 12 */ 15228908Skarels 66880, 13, /* B=cyl 13 thru 65 */ 15328908Skarels 1077760, 0, /* C=cyl 0 thru 841 */ 15428908Skarels 15884, 294, /* D=cyl 294 thru 306 */ 15528908Skarels 307200, 307, /* E=cyl 307 thru 546 */ 15628908Skarels 377408, 547, /* F=cyl 547 thru 841 */ 15728908Skarels 701248, 294, /* G=cyl 294 thru 841 */ 15828908Skarels 291346, 66, /* H=cyl 66 thru 293 */ 15921Sbill }; 1602383Swnj /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ 16121Sbill 1626927Ssam /* 1636927Ssam * Table for converting Massbus drive types into 1646927Ssam * indices into the partition tables. Slots are 16528908Skarels * left for those drives divined from other means 1666927Ssam * (e.g. SI, AMPEX, etc.). 1676927Ssam */ 1686927Ssam short hptypes[] = { 1696927Ssam #define HPDT_RM03 0 1706927Ssam MBDT_RM03, 1716927Ssam #define HPDT_RM05 1 1726927Ssam MBDT_RM05, 1736927Ssam #define HPDT_RP06 2 1746927Ssam MBDT_RP06, 1756927Ssam #define HPDT_RM80 3 1766927Ssam MBDT_RM80, 17713157Ssam #define HPDT_RP04 4 17813157Ssam MBDT_RP04, 17913157Ssam #define HPDT_RP05 5 1806927Ssam MBDT_RP05, 18113157Ssam #define HPDT_RP07 6 1826927Ssam MBDT_RP07, 18313157Ssam #define HPDT_ML11A 7 1846927Ssam MBDT_ML11A, 18513157Ssam #define HPDT_ML11B 8 1866927Ssam MBDT_ML11B, 18713157Ssam #define HPDT_9775 9 1886927Ssam -1, 18913157Ssam #define HPDT_9730 10 1906927Ssam -1, 19113157Ssam #define HPDT_CAPRICORN 11 1926927Ssam -1, 19313157Ssam #define HPDT_EAGLE 12 1949175Ssam -1, 19513157Ssam #define HPDT_9300 13 19611281Ssam -1, 19713157Ssam #define HPDT_RM02 14 19828908Skarels MBDT_RM02, /* beware, actually mapped */ 19928908Skarels #define HPDT_2361 15 20028908Skarels -1, 2016927Ssam 0 2026927Ssam }; 2032978Swnj struct mba_device *hpinfo[NHP]; 20414145Shelge int hpattach(),hpustart(),hpstart(),hpdtint(); 2052383Swnj struct mba_driver hpdriver = 2062978Swnj { hpattach, 0, hpustart, hpstart, hpdtint, 0, 2072978Swnj hptypes, "hp", 0, hpinfo }; 2082383Swnj 20912836Ssam /* 21016225Skarels * These variable are all measured in sectors. 21116225Skarels * Sdist is how much to "lead" in the search for a desired sector 21216225Skarels * (i.e. if want N, search for N-sdist.) 21316225Skarels * Maxdist and mindist define the region right before our desired sector within 21416225Skarels * which we don't bother searching. We don't search when we are already less 21516225Skarels * then maxdist and more than mindist sectors "before" our desired sector. 21616225Skarels * Maxdist should be >= sdist. 21716225Skarels * 21816225Skarels * Beware, sdist, mindist and maxdist are not well tuned 21912836Ssam * for many of the drives listed in this table. 22012836Ssam * Try patching things with something i/o intensive 22112836Ssam * running and watch iostat. 22212836Ssam */ 2232383Swnj struct hpst { 22412836Ssam short nsect; /* # sectors/track */ 22512836Ssam short ntrak; /* # tracks/cylinder */ 22612836Ssam short nspc; /* # sector/cylinders */ 22712836Ssam short ncyl; /* # cylinders */ 22812836Ssam struct size *sizes; /* partition tables */ 22912836Ssam short sdist; /* seek distance metric */ 23016225Skarels short maxdist; /* boundaries of non-searched area */ 23116225Skarels short mindist; /* preceding the target sector */ 23228908Skarels char *name; /* name of disk type */ 2332383Swnj } hpst[] = { 23428908Skarels { 32, 5, 32*5, 823, rm03_sizes, 7, 4, 1, "RM03" }, 23528908Skarels { 32, 19, 32*19, 823, rm05_sizes, 7, 4, 1, "RM05" }, 23628908Skarels { 22,19, 22*19, 815, rp06_sizes, 7, 4, 1, "RP06"}, 23728908Skarels { 31, 14, 31*14, 559, rm80_sizes, 7, 4, 1, "RM80"}, 23828908Skarels { 22, 19, 22*19, 411, rp05_sizes, 7, 4, 1, "RP04"}, 23928908Skarels { 22, 19, 22*19, 411, rp05_sizes, 7, 4, 1, "RP05"}, 24028908Skarels { 50, 32, 50*32, 630, rp07_sizes, 15, 8, 3, "RP07"}, 24128908Skarels { 1, 1, 1, 1, 0, 0, 0, 0, "ML11A"}, 24228908Skarels { 1, 1, 1, 1, 0, 0, 0, 0, "ML11B" }, 24328908Skarels { 32, 40, 32*40, 843, cdc9775_sizes, 7, 4, 1, "9775" }, 24428908Skarels { 32, 10, 32*10, 823, cdc9730_sizes, 7, 4, 1, "9730-160" }, 24528908Skarels { 32, 16, 32*16, 1024, capricorn_sizes,10,4, 3, "capricorn" }, 24628908Skarels { 48, 20, 48*20, 842, eagle_sizes, 15, 8, 3, "eagle" }, 24728908Skarels { 32, 19, 32*19, 815, ampex_sizes, 7, 4, 1, "9300" }, 24828908Skarels { 64, 20, 64*20, 842, fj2361_sizes, 15, 8, 3, "2361" }, 2492383Swnj }; 2502383Swnj 2512624Swnj u_char hp_offset[16] = { 2523093Swnj HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, 2533093Swnj HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, 2543093Swnj HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, 2553093Swnj 0, 0, 0, 0, 25621Sbill }; 25721Sbill 2582624Swnj struct buf rhpbuf[NHP]; 2593706Sroot struct buf bhpbuf[NHP]; 2603706Sroot struct dkbad hpbad[NHP]; 26121Sbill 26210857Ssam struct hpsoftc { 26310857Ssam u_char sc_hpinit; /* drive initialized */ 26410857Ssam u_char sc_recal; /* recalibrate state */ 26510857Ssam u_char sc_hdr; /* next i/o includes header */ 26610857Ssam u_char sc_doseeks; /* perform explicit seeks */ 26710857Ssam daddr_t sc_mlsize; /* ML11 size */ 26825198Skarels int sc_blkdone; /* amount sucessfully transfered */ 26917071Sralph daddr_t sc_badbn; /* replacement block number */ 27010857Ssam } hpsoftc[NHP]; 27110857Ssam 27221Sbill #define b_cylin b_resid 27321Sbill 2745726Sroot /* #define ML11 0 to remove ML11 support */ 2755726Sroot #define ML11 (hptypes[mi->mi_type] == MBDT_ML11A) 2765726Sroot #define RP06 (hptypes[mi->mi_type] <= MBDT_RP06) 2775726Sroot #define RM80 (hptypes[mi->mi_type] == MBDT_RM80) 2785726Sroot 27924738Sbloom #define hpunit(dev) (minor(dev) >> 3) 28011202Ssam #define MASKREG(reg) ((reg)&0xffff) 28126375Skarels #ifdef lint 28226375Skarels #define HPWAIT(mi, addr) (hpwait(mi)) 28326375Skarels #else 28418411Skarels #define HPWAIT(mi, addr) (((addr)->hpds & HPDS_DRY) || hpwait(mi)) 28526375Skarels #endif 28611202Ssam 2872978Swnj /*ARGSUSED*/ 2882978Swnj hpattach(mi, slave) 28910734Ssam register struct mba_device *mi; 2902604Swnj { 29110734Ssam 29210734Ssam mi->mi_type = hpmaptype(mi); 29310734Ssam if (!ML11 && mi->mi_dk >= 0) { 29410734Ssam struct hpst *st = &hpst[mi->mi_type]; 29510734Ssam 29610734Ssam dk_mspw[mi->mi_dk] = 1.0 / 60 / (st->nsect * 256); 29710734Ssam } 29810734Ssam } 29910734Ssam 30010734Ssam /* 30110734Ssam * Map apparent MASSBUS drive type into manufacturer 30210734Ssam * specific configuration. For SI controllers this is done 30310734Ssam * based on codes in the serial number register. For 30410734Ssam * EMULEX controllers, the track and sector attributes are 30510734Ssam * used when the drive type is an RM02 (not supported by DEC). 30610734Ssam */ 30710734Ssam hpmaptype(mi) 30810734Ssam register struct mba_device *mi; 30910734Ssam { 3106927Ssam register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 31110734Ssam register int type = mi->mi_type; 3126927Ssam 3136927Ssam /* 31411281Ssam * Model-byte processing for SI controllers. 3156927Ssam * NB: Only deals with RM03 and RM05 emulations. 3166927Ssam */ 31710734Ssam if (type == HPDT_RM03 || type == HPDT_RM05) { 31810734Ssam int hpsn = hpaddr->hpsn; 3196927Ssam 3206927Ssam if ((hpsn & SIMB_LU) != mi->mi_drive) 32110734Ssam return (type); 3226927Ssam switch ((hpsn & SIMB_MB) & ~(SIMB_S6|SIRM03|SIRM05)) { 3236927Ssam 3246927Ssam case SI9775D: 32511281Ssam printf("hp%d: 9775 (direct)\n", mi->mi_unit); 32610734Ssam type = HPDT_9775; 3276927Ssam break; 3286927Ssam 3296927Ssam case SI9730D: 33011281Ssam printf("hp%d: 9730 (direct)\n", mi->mi_unit); 33110734Ssam type = HPDT_9730; 3326927Ssam break; 3336927Ssam 3346927Ssam case SI9766: 33528908Skarels printf("hp%d: 9766\n", mi->mi_unit); 33628908Skarels type = HPDT_RM05; 3376927Ssam break; 3386927Ssam 3396927Ssam case SI9762: 3406927Ssam printf("hp%d: 9762\n", mi->mi_unit); 34110734Ssam type = HPDT_RM03; 3426927Ssam break; 34311281Ssam 34411281Ssam case SICAPD: 34511281Ssam printf("hp%d: capricorn\n", mi->mi_unit); 34611281Ssam type = HPDT_CAPRICORN; 34711281Ssam break; 34811281Ssam 34911281Ssam case SI9751D: 35011281Ssam printf("hp%d: eagle\n", mi->mi_unit); 35111281Ssam type = HPDT_EAGLE; 35211281Ssam break; 3536927Ssam } 35410734Ssam return (type); 35510734Ssam } 3566927Ssam 3576927Ssam /* 35810734Ssam * EMULEX SC750 or SC780. Poke the holding register. 3596927Ssam */ 36010734Ssam if (type == HPDT_RM02) { 36128908Skarels int nsectors, ntracks, ncyl; 36210734Ssam 36311315Ssam hpaddr->hpof = HPOF_FMT22; 36411315Ssam mbclrattn(mi); 3656927Ssam hpaddr->hpcs1 = HP_NOP; 3666927Ssam hpaddr->hphr = HPHR_MAXTRAK; 36711202Ssam ntracks = MASKREG(hpaddr->hphr) + 1; 36828908Skarels DELAY(100); 36910734Ssam hpaddr->hpcs1 = HP_NOP; 37010734Ssam hpaddr->hphr = HPHR_MAXSECT; 37111202Ssam nsectors = MASKREG(hpaddr->hphr) + 1; 37228908Skarels DELAY(100); 37328908Skarels hpaddr->hpcs1 = HP_NOP; 37428908Skarels hpaddr->hphr = HPHR_MAXCYL; 37528908Skarels ncyl = MASKREG(hpaddr->hphr) + 1; 37628908Skarels for (type = 0; hptypes[type] != 0; type++) 37728908Skarels if (hpst[type].nsect == nsectors && 37828908Skarels hpst[type].ntrak == ntracks && 37928908Skarels hpst[type].ncyl == ncyl) 38028908Skarels break; 38128908Skarels 38228908Skarels if (hptypes[type] == 0) { 38328908Skarels printf("hp%d: %d sectors, %d tracks, %d cylinders: unknown device\n", 38428908Skarels mi->mi_unit, nsectors, ntracks, ncyl); 38528908Skarels type = HPDT_RM02; 38610734Ssam } 38728908Skarels printf("hp%d: %s\n", mi->mi_unit, hpst[type].name); 3886927Ssam hpaddr->hpcs1 = HP_DCLR|HP_GO; 38911315Ssam mbclrattn(mi); /* conservative */ 39010734Ssam return (type); 39128908Skarels } 3926927Ssam 39310734Ssam /* 39410734Ssam * Map all ML11's to the same type. Also calculate 39510734Ssam * transfer rates based on device characteristics. 39610734Ssam */ 39710734Ssam if (type == HPDT_ML11A || type == HPDT_ML11B) { 39810857Ssam register struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; 39910857Ssam register int trt; 4002604Swnj 40110857Ssam sc->sc_mlsize = hpaddr->hpmr & HPMR_SZ; 4025726Sroot if ((hpaddr->hpmr & HPMR_ARRTYP) == 0) 40310857Ssam sc->sc_mlsize >>= 2; 4045726Sroot if (mi->mi_dk >= 0) { 4055726Sroot trt = (hpaddr->hpmr & HPMR_TRT) >> 8; 4065726Sroot dk_mspw[mi->mi_dk] = 1.0 / (1<<(20-trt)); 4075726Sroot } 40810734Ssam type = HPDT_ML11A; 4096927Ssam } 41010734Ssam return (type); 4112604Swnj } 4122604Swnj 4138579Sroot hpopen(dev) 4148579Sroot dev_t dev; 4158579Sroot { 41624738Sbloom register int unit = hpunit(dev); 4178579Sroot register struct mba_device *mi; 4188579Sroot 4198579Sroot if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0) 4208579Sroot return (ENXIO); 4218579Sroot return (0); 4228579Sroot } 4238579Sroot 42421Sbill hpstrategy(bp) 4252383Swnj register struct buf *bp; 42621Sbill { 4272978Swnj register struct mba_device *mi; 4282383Swnj register struct hpst *st; 4292383Swnj register int unit; 43024783Skarels long sz; 4312383Swnj int xunit = minor(bp->b_dev) & 07; 4325432Sroot int s; 43321Sbill 43421Sbill sz = bp->b_bcount; 43521Sbill sz = (sz+511) >> 9; 43624738Sbloom unit = hpunit(bp->b_dev); 43724738Sbloom if (unit >= NHP) { 43824738Sbloom bp->b_error = ENXIO; 4392383Swnj goto bad; 44024738Sbloom } 4412383Swnj mi = hpinfo[unit]; 44224738Sbloom if (mi == 0 || mi->mi_alive == 0) { 44324738Sbloom bp->b_error = ENXIO; 4442383Swnj goto bad; 44524738Sbloom } 4462383Swnj st = &hpst[mi->mi_type]; 4475726Sroot if (ML11) { 44810857Ssam struct hpsoftc *sc = &hpsoftc[unit]; 44910857Ssam 4505726Sroot if (bp->b_blkno < 0 || 45124738Sbloom bp->b_blkno+sz > sc->sc_mlsize) { 45224783Skarels if (bp->b_blkno == sc->sc_mlsize) { 45324783Skarels bp->b_resid = bp->b_bcount; 45424738Sbloom goto done; 45524783Skarels } 45624738Sbloom bp->b_error = EINVAL; 4575726Sroot goto bad; 45824738Sbloom } 4595726Sroot bp->b_cylin = 0; 4605726Sroot } else { 4615726Sroot if (bp->b_blkno < 0 || 46224783Skarels bp->b_blkno+sz > st->sizes[xunit].nblocks) { 46324783Skarels if (bp->b_blkno == st->sizes[xunit].nblocks) { 46424783Skarels bp->b_resid = bp->b_bcount; 46524738Sbloom goto done; 46624783Skarels } 46724738Sbloom bp->b_error = EINVAL; 4685726Sroot goto bad; 46924738Sbloom } 47024783Skarels bp->b_cylin = bp->b_blkno/st->nspc + st->sizes[xunit].cyloff; 4715726Sroot } 4725432Sroot s = spl5(); 4732383Swnj disksort(&mi->mi_tab, bp); 4742383Swnj if (mi->mi_tab.b_active == 0) 4752383Swnj mbustart(mi); 4765432Sroot splx(s); 4772383Swnj return; 4782383Swnj 4792383Swnj bad: 4802383Swnj bp->b_flags |= B_ERROR; 48124738Sbloom done: 4822383Swnj iodone(bp); 4832383Swnj return; 48421Sbill } 48521Sbill 4862383Swnj hpustart(mi) 4872978Swnj register struct mba_device *mi; 48821Sbill { 4892624Swnj register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 4902383Swnj register struct buf *bp = mi->mi_tab.b_actf; 49111315Ssam register struct hpst *st; 49210857Ssam struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; 49321Sbill daddr_t bn; 49416791Skarels int sn, tn, dist; 49521Sbill 49611315Ssam st = &hpst[mi->mi_type]; 4973706Sroot hpaddr->hpcs1 = 0; 4982624Swnj if ((hpaddr->hpcs1&HP_DVA) == 0) 4992383Swnj return (MBU_BUSY); 50025198Skarels 50125198Skarels switch (sc->sc_recal) { 50225198Skarels 50325198Skarels case 1: 50426375Skarels (void)HPWAIT(mi, hpaddr); 50525198Skarels hpaddr->hpdc = bp->b_cylin; 50625198Skarels hpaddr->hpcs1 = HP_SEEK|HP_GO; 50725198Skarels sc->sc_recal++; 50825198Skarels return (MBU_STARTED); 50925198Skarels case 2: 51025198Skarels break; 51125198Skarels } 51225198Skarels sc->sc_recal = 0; 51310857Ssam if ((hpaddr->hpds & HPDS_VV) == 0 || !sc->sc_hpinit) { 5143706Sroot struct buf *bbp = &bhpbuf[mi->mi_unit]; 5153706Sroot 51610857Ssam sc->sc_hpinit = 1; 5172624Swnj hpaddr->hpcs1 = HP_DCLR|HP_GO; 5183140Swnj if (mi->mi_mba->mba_drv[0].mbd_as & (1<<mi->mi_drive)) 5193140Swnj printf("DCLR attn\n"); 5202624Swnj hpaddr->hpcs1 = HP_PRESET|HP_GO; 5215726Sroot if (!ML11) 5225726Sroot hpaddr->hpof = HPOF_FMT22; 5233140Swnj mbclrattn(mi); 5245726Sroot if (!ML11) { 5255726Sroot bbp->b_flags = B_READ|B_BUSY; 5265726Sroot bbp->b_dev = bp->b_dev; 5275726Sroot bbp->b_bcount = 512; 5285726Sroot bbp->b_un.b_addr = (caddr_t)&hpbad[mi->mi_unit]; 5295726Sroot bbp->b_blkno = st->ncyl*st->nspc - st->nsect; 5305726Sroot bbp->b_cylin = st->ncyl - 1; 5315726Sroot mi->mi_tab.b_actf = bbp; 5325726Sroot bbp->av_forw = bp; 5335726Sroot bp = bbp; 5345726Sroot } 53521Sbill } 53625198Skarels if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1) { 53725198Skarels if (mi->mi_tab.b_errcnt >= 16 && (bp->b_flags & B_READ)) { 53825198Skarels hpaddr->hpof = 53925198Skarels hp_offset[mi->mi_tab.b_errcnt & 017]|HPOF_FMT22; 54025198Skarels hpaddr->hpcs1 = HP_OFFSET|HP_GO; 54126375Skarels (void)HPWAIT(mi, hpaddr); 54225198Skarels mbclrattn(mi); 54325198Skarels } 5442383Swnj return (MBU_DODATA); 54525198Skarels } 5465726Sroot if (ML11) 5475726Sroot return (MBU_DODATA); 5483093Swnj if ((hpaddr->hpds & HPDS_DREADY) != HPDS_DREADY) 5492383Swnj return (MBU_DODATA); 55024738Sbloom bn = bp->b_blkno; 55116791Skarels sn = bn % st->nspc; 55216791Skarels tn = sn / st->nsect; 55316791Skarels sn = sn % st->nsect; 55411202Ssam if (bp->b_cylin == MASKREG(hpaddr->hpdc)) { 55510908Ssam if (sc->sc_doseeks) 5562383Swnj return (MBU_DODATA); 55716225Skarels dist = sn - (MASKREG(hpaddr->hpla) >> 6) - 1; 5582383Swnj if (dist < 0) 5592383Swnj dist += st->nsect; 56016225Skarels if (dist > st->maxdist || dist < st->mindist) 5612383Swnj return (MBU_DODATA); 5622614Swnj } else 5632614Swnj hpaddr->hpdc = bp->b_cylin; 56410908Ssam if (sc->sc_doseeks) 5652624Swnj hpaddr->hpcs1 = HP_SEEK|HP_GO; 566305Sbill else { 56716225Skarels sn = (sn + st->nsect - st->sdist) % st->nsect; 56816791Skarels hpaddr->hpda = (tn << 8) + sn; 5692624Swnj hpaddr->hpcs1 = HP_SEARCH|HP_GO; 570305Sbill } 5712383Swnj return (MBU_STARTED); 57221Sbill } 57321Sbill 5742383Swnj hpstart(mi) 5752978Swnj register struct mba_device *mi; 57621Sbill { 5772624Swnj register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 5782383Swnj register struct buf *bp = mi->mi_tab.b_actf; 5792383Swnj register struct hpst *st = &hpst[mi->mi_type]; 58010857Ssam struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; 58121Sbill daddr_t bn; 58225198Skarels int sn, tn, cn; 58321Sbill 5845726Sroot if (ML11) 58525198Skarels hpaddr->hpda = bp->b_blkno + sc->sc_blkdone; 5865726Sroot else { 58725198Skarels if (bp->b_flags & B_BAD) { 58825198Skarels bn = sc->sc_badbn; 58925198Skarels cn = bn / st->nspc; 59025198Skarels } else { 59125198Skarels bn = bp->b_blkno; 59225198Skarels cn = bp->b_cylin; 59325198Skarels } 59425198Skarels sn = bn % st->nspc; 59525198Skarels if ((bp->b_flags & B_BAD) == 0) 59625198Skarels sn += sc->sc_blkdone; 59725198Skarels tn = sn / st->nsect; 5985726Sroot sn %= st->nsect; 59925198Skarels cn += tn / st->ntrak; 60025198Skarels tn %= st->ntrak; 6015726Sroot hpaddr->hpda = (tn << 8) + sn; 60225198Skarels hpaddr->hpdc = cn; 6035726Sroot } 60426041Skarels mi->mi_tab.b_bdone = dbtob(sc->sc_blkdone); 60510857Ssam if (sc->sc_hdr) { 6065726Sroot if (bp->b_flags & B_READ) 6075726Sroot return (HP_RHDR|HP_GO); 6085726Sroot else 6095726Sroot return (HP_WHDR|HP_GO); 6105726Sroot } 6115726Sroot return (0); 61221Sbill } 61321Sbill 6143102Swnj hpdtint(mi, mbsr) 6152978Swnj register struct mba_device *mi; 6163102Swnj int mbsr; 61721Sbill { 6182624Swnj register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 6192383Swnj register struct buf *bp = mi->mi_tab.b_actf; 6205893Swnj register int er1, er2; 62110857Ssam struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; 62226289Skarels int retry = 0; 62326041Skarels int npf; 62426041Skarels daddr_t bn; 62526041Skarels int bcr; 62621Sbill 62726041Skarels bcr = MASKREG(-mi->mi_mba->mba_bcr); 6283102Swnj if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) { 62914145Shelge er1 = hpaddr->hper1; 63014145Shelge er2 = hpaddr->hper2; 63126041Skarels if (bp->b_flags & B_BAD) { 63226041Skarels npf = bp->b_error; 63326041Skarels bn = sc->sc_badbn; 63426041Skarels } else { 63526041Skarels npf = btop(bp->b_bcount - bcr); 63626041Skarels if (er1 & (HPER1_DCK | HPER1_ECH)) 63726041Skarels npf--; 63826041Skarels bn = bp->b_blkno + npf; 63926041Skarels } 64018411Skarels if (HPWAIT(mi, hpaddr) == 0) 64118411Skarels goto hard; 6423706Sroot #ifdef HPDEBUG 6433289Swnj if (hpdebug) { 6443706Sroot int dc = hpaddr->hpdc, da = hpaddr->hpda; 6453706Sroot 64625198Skarels log(LOG_DEBUG, 64725198Skarels "hperr: bp %x cyl %d blk %d blkdone %d as %o dc %x da %x\n", 64826041Skarels bp, bp->b_cylin, bn, sc->sc_blkdone, 64925198Skarels hpaddr->hpas&0xff, MASKREG(dc), MASKREG(da)); 65026041Skarels log(LOG_DEBUG, 65126041Skarels "errcnt %d mbsr=%b er1=%b er2=%b bcr -%d\n", 65225198Skarels mi->mi_tab.b_errcnt, mbsr, mbsr_bits, 65325198Skarels MASKREG(er1), HPER1_BITS, 65426041Skarels MASKREG(er2), HPER2_BITS, bcr); 6553289Swnj } 6563706Sroot #endif 6575893Swnj if (er1 & HPER1_HCRC) { 6585858Swnj er1 &= ~(HPER1_HCE|HPER1_FER); 6595893Swnj er2 &= ~HPER2_BSE; 6605893Swnj } 66116791Skarels if (er1 & HPER1_WLE) { 66224844Seric log(LOG_WARNING, "hp%d: write locked\n", 66324738Sbloom hpunit(bp->b_dev)); 6642826Swnj bp->b_flags |= B_ERROR; 66516791Skarels } else if (sc->sc_hdr) { 66616791Skarels goto hard; 66717071Sralph } else if (RM80 && er2&HPER2_SSE) { 66817071Sralph (void) hpecc(mi, SSE); 66917071Sralph return (MBD_RESTARTED); 67016791Skarels } else if ((er2 & HPER2_BSE) && !ML11) { 6715726Sroot if (hpecc(mi, BSE)) 67211202Ssam return (MBD_RESTARTED); 67311202Ssam goto hard; 67416791Skarels } else if (MASKREG(er1) == HPER1_FER && RP06) { 67516791Skarels if (hpecc(mi, BSE)) 67616791Skarels return (MBD_RESTARTED); 67716791Skarels goto hard; 67817071Sralph } else if ((er1 & (HPER1_DCK | HPER1_ECH)) == HPER1_DCK && 67925198Skarels mi->mi_tab.b_errcnt >= 3) { 68016791Skarels if (hpecc(mi, ECC)) 68116791Skarels return (MBD_RESTARTED); 68225398Skarels /* 68325398Skarels * ECC corrected. Only log retries below 68425398Skarels * if we got errors other than soft ECC 68525398Skarels * (as indicated by additional retries). 68625398Skarels */ 68725398Skarels if (mi->mi_tab.b_errcnt == 3) 68825398Skarels mi->mi_tab.b_errcnt = 0; 68924780Skarels } else if ((er1 & HPER1_HCRC) && !ML11 && hpecc(mi, BSE)) { 69024780Skarels /* 69124780Skarels * HCRC means the header is screwed up and the sector 69224780Skarels * might well exist in the bad sector table, 69324780Skarels * better check.... 69424780Skarels */ 69524780Skarels return (MBD_RESTARTED); 6962826Swnj } else if (++mi->mi_tab.b_errcnt > 27 || 69716791Skarels (ML11 && mi->mi_tab.b_errcnt > 15) || 6983102Swnj mbsr & MBSR_HARD || 6995858Swnj er1 & HPER1_HARD || 7005893Swnj (!ML11 && (er2 & HPER2_HARD))) { 7013706Sroot hard: 70226041Skarels bp->b_blkno = bn; /* XXX */ 7032925Swnj harderr(bp, "hp"); 7043271Swnj if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC))) 7053271Swnj printf("mbsr=%b ", mbsr, mbsr_bits); 7063706Sroot printf("er1=%b er2=%b", 70714145Shelge MASKREG(hpaddr->hper1), HPER1_BITS, 70814145Shelge MASKREG(hpaddr->hper2), HPER2_BITS); 70914134Shelge if (sc->sc_hdr) 71014134Shelge printf(" (hdr i/o)"); 7113706Sroot printf("\n"); 7122826Swnj bp->b_flags |= B_ERROR; 71317071Sralph bp->b_flags &= ~B_BAD; 7142826Swnj } else 7152826Swnj retry = 1; 7162826Swnj hpaddr->hpcs1 = HP_DCLR|HP_GO; 71725506Skarels if (retry && (mi->mi_tab.b_errcnt & 07) == 4) { 7182826Swnj hpaddr->hpcs1 = HP_RECAL|HP_GO; 71910857Ssam sc->sc_recal = 1; 72025198Skarels return (MBD_REPOSITION); 72121Sbill } 7222826Swnj } 7233706Sroot #ifdef HPDEBUG 7243289Swnj else 72510857Ssam if (hpdebug && sc->sc_recal) { 72625198Skarels log(LOG_DEBUG, 72725198Skarels "recal %d errcnt %d mbsr=%b er1=%b er2=%b\n", 72825198Skarels sc->sc_recal, mi->mi_tab.b_errcnt, mbsr, mbsr_bits, 7293289Swnj hpaddr->hper1, HPER1_BITS, 7303289Swnj hpaddr->hper2, HPER2_BITS); 7313289Swnj } 7323706Sroot #endif 73326375Skarels (void)HPWAIT(mi, hpaddr); 73425198Skarels if (retry) 7352892Swnj return (MBD_RETRY); 7363640Swnj if (mi->mi_tab.b_errcnt >= 16) { 7373093Swnj /* 7383093Swnj * This is fast and occurs rarely; we don't 7393093Swnj * bother with interrupts. 7403093Swnj */ 7412624Swnj hpaddr->hpcs1 = HP_RTC|HP_GO; 74226375Skarels (void)HPWAIT(mi, hpaddr); 7432383Swnj mbclrattn(mi); 74421Sbill } 74525398Skarels if (mi->mi_tab.b_errcnt && (bp->b_flags & B_ERROR) == 0) 74625198Skarels log(LOG_INFO, "hp%d%c: %d retries %sing sn%d\n", 74725198Skarels hpunit(bp->b_dev), 'a'+(minor(bp->b_dev)&07), 74825198Skarels mi->mi_tab.b_errcnt, 74925198Skarels (bp->b_flags & B_READ) ? "read" : "writ", 75025198Skarels (bp->b_flags & B_BAD) ? 75125198Skarels sc->sc_badbn : bp->b_blkno + sc->sc_blkdone); 75217071Sralph if ((bp->b_flags & B_BAD) && hpecc(mi, CONT)) 75317071Sralph return (MBD_RESTARTED); 75417071Sralph sc->sc_hdr = 0; 75525198Skarels sc->sc_blkdone = 0; 75626041Skarels bp->b_resid = bcr; 7575726Sroot if (!ML11) { 7585726Sroot hpaddr->hpof = HPOF_FMT22; 7595726Sroot hpaddr->hpcs1 = HP_RELEASE|HP_GO; 7605726Sroot } 7612383Swnj return (MBD_DONE); 76221Sbill } 76321Sbill 76418411Skarels /* 76518411Skarels * Wait (for a bit) for a drive to come ready; 76618411Skarels * returns nonzero on success. 76718411Skarels */ 76818411Skarels hpwait(mi) 76918411Skarels register struct mba_device *mi; 77018411Skarels { 77118411Skarels register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 77218411Skarels register i = 100000; 77318411Skarels 77418411Skarels while ((hpaddr->hpds & HPDS_DRY) == 0 && --i) 77518411Skarels DELAY(10); 77618411Skarels if (i == 0) 77718411Skarels printf("hp%d: intr, not ready\n", mi->mi_unit); 77818411Skarels return (i); 77918411Skarels } 78018411Skarels 7817738Sroot hpread(dev, uio) 7822624Swnj dev_t dev; 7837738Sroot struct uio *uio; 78421Sbill { 78524738Sbloom register int unit = hpunit(dev); 78621Sbill 7872624Swnj if (unit >= NHP) 7888156Sroot return (ENXIO); 7898156Sroot return (physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys, uio)); 79021Sbill } 79121Sbill 7927831Sroot hpwrite(dev, uio) 7932624Swnj dev_t dev; 7947831Sroot struct uio *uio; 79521Sbill { 79624738Sbloom register int unit = hpunit(dev); 79721Sbill 7982624Swnj if (unit >= NHP) 7998156Sroot return (ENXIO); 8008156Sroot return (physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys, uio)); 80121Sbill } 80221Sbill 8035726Sroot /*ARGSUSED*/ 8047635Ssam hpioctl(dev, cmd, data, flag) 8055726Sroot dev_t dev; 8065726Sroot int cmd; 8077635Ssam caddr_t data; 8085726Sroot int flag; 8095726Sroot { 8105726Sroot 8115726Sroot switch (cmd) { 8127635Ssam 8135726Sroot case DKIOCHDR: /* do header read/write */ 81424738Sbloom hpsoftc[hpunit(dev)].sc_hdr = 1; 8158579Sroot return (0); 8165726Sroot 8175726Sroot default: 8188579Sroot return (ENXIO); 8195726Sroot } 8205726Sroot } 8215726Sroot 8223706Sroot hpecc(mi, flag) 8232978Swnj register struct mba_device *mi; 8243706Sroot int flag; 82521Sbill { 8262383Swnj register struct mba_regs *mbp = mi->mi_mba; 8272624Swnj register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv; 8282383Swnj register struct buf *bp = mi->mi_tab.b_actf; 8293706Sroot register struct hpst *st = &hpst[mi->mi_type]; 83017071Sralph struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; 8313706Sroot int npf, o; 8322383Swnj int bn, cn, tn, sn; 833914Sbill int bcr; 83421Sbill 83518411Skarels bcr = MASKREG(-mbp->mba_bcr); 83617071Sralph if (bp->b_flags & B_BAD) 8373706Sroot npf = bp->b_error; 838*28987Skarels else { 839*28987Skarels npf = bp->b_bcount - bcr; 840*28987Skarels /* 841*28987Skarels * Watch out for fractional sector at end of transfer; 842*28987Skarels * want to round up if finished, otherwise round down. 843*28987Skarels */ 844*28987Skarels if (bcr == 0) 845*28987Skarels npf += 511; 846*28987Skarels npf = btodb(npf); 847*28987Skarels } 848420Sbill o = (int)bp->b_un.b_addr & PGOFSET; 84924738Sbloom bn = bp->b_blkno; 850420Sbill cn = bp->b_cylin; 85118411Skarels sn = bn%(st->nspc) + npf; 8522383Swnj tn = sn/st->nsect; 8532383Swnj sn %= st->nsect; 8542383Swnj cn += tn/st->ntrak; 8552383Swnj tn %= st->ntrak; 85624187Skarels bn += npf; 8573706Sroot switch (flag) { 85810856Ssam case ECC: { 8593706Sroot register int i; 8603706Sroot caddr_t addr; 8613706Sroot struct pte mpte; 8623706Sroot int bit, byte, mask; 8633706Sroot 8643706Sroot npf--; /* because block in error is previous block */ 86518411Skarels bn--; 86617071Sralph if (bp->b_flags & B_BAD) 86717071Sralph bn = sc->sc_badbn; 86824844Seric log(LOG_WARNING, "hp%d%c: soft ecc sn%d\n", hpunit(bp->b_dev), 86917071Sralph 'a'+(minor(bp->b_dev)&07), bn); 87011202Ssam mask = MASKREG(rp->hpec2); 87111202Ssam i = MASKREG(rp->hpec1) - 1; /* -1 makes 0 origin */ 8723706Sroot bit = i&07; 8733706Sroot i = (i&~07)>>3; 8743706Sroot byte = i + o; 87526041Skarels while (i < 512 && (int)dbtob(npf)+i < bp->b_bcount && bit > -11) { 8763706Sroot mpte = mbp->mba_map[npf+btop(byte)]; 8773706Sroot addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET); 8783706Sroot putmemc(addr, getmemc(addr)^(mask<<bit)); 8793706Sroot byte++; 8803706Sroot i++; 8813706Sroot bit -= 8; 8823706Sroot } 88318411Skarels if (bcr == 0) 8843706Sroot return (0); 8853847Sroot npf++; 8863706Sroot break; 8873706Sroot } 8883706Sroot 8893706Sroot case SSE: 8903706Sroot rp->hpof |= HPOF_SSEI; 89117071Sralph if (bp->b_flags & B_BAD) { 89217071Sralph bn = sc->sc_badbn; 89317071Sralph goto fixregs; 89417071Sralph } 8953706Sroot mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf)); 8963706Sroot break; 8973706Sroot 8983706Sroot case BSE: 89917071Sralph if (rp->hpof & HPOF_SSEI) 90017071Sralph sn++; 9013706Sroot #ifdef HPBDEBUG 9023706Sroot if (hpbdebug) 90325198Skarels log(LOG_DEBUG, "hpecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn); 9043706Sroot #endif 90517071Sralph if (bp->b_flags & B_BAD) 90617071Sralph return (0); 9073706Sroot if ((bn = isbad(&hpbad[mi->mi_unit], cn, tn, sn)) < 0) 90811202Ssam return (0); 9093706Sroot bp->b_flags |= B_BAD; 9103706Sroot bp->b_error = npf + 1; 91117071Sralph rp->hpof &= ~HPOF_SSEI; 9123706Sroot bn = st->ncyl*st->nspc - st->nsect - 1 - bn; 91317071Sralph sc->sc_badbn = bn; 91417071Sralph fixregs: 9153706Sroot cn = bn/st->nspc; 9163706Sroot sn = bn%st->nspc; 9173706Sroot tn = sn/st->nsect; 9183706Sroot sn %= st->nsect; 91926375Skarels bcr = bp->b_bcount - (int)ptob(npf); 92026375Skarels bcr = MIN(bcr, 512); 92126375Skarels mbp->mba_bcr = -bcr; 9223706Sroot #ifdef HPBDEBUG 9233706Sroot if (hpbdebug) 92425198Skarels log(LOG_DEBUG, "revector to cn %d tn %d sn %d\n", cn, tn, sn); 9253706Sroot #endif 9263706Sroot break; 9273706Sroot 9283706Sroot case CONT: 9293706Sroot #ifdef HPBDEBUG 9303706Sroot if (hpbdebug) 93125198Skarels log(LOG_DEBUG, "hpecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn); 9323706Sroot #endif 9333706Sroot bp->b_flags &= ~B_BAD; 93424780Skarels if ((int)ptob(npf) >= bp->b_bcount) 93524780Skarels return (0); 9363706Sroot mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf)); 9373706Sroot break; 9383706Sroot } 9393706Sroot rp->hpcs1 = HP_DCLR|HP_GO; 94017071Sralph if (rp->hpof & HPOF_SSEI) 9412883Swnj sn++; 942420Sbill rp->hpdc = cn; 943420Sbill rp->hpda = (tn<<8) + sn; 944420Sbill mbp->mba_sr = -1; 9453706Sroot mbp->mba_var = (int)ptob(npf) + o; 9463706Sroot rp->hpcs1 = bp->b_flags&B_READ ? HP_RCOM|HP_GO : HP_WCOM|HP_GO; 9473706Sroot mi->mi_tab.b_errcnt = 0; /* error has been corrected */ 94825198Skarels sc->sc_blkdone = npf; 949420Sbill return (1); 95021Sbill } 9512362Swnj 9522362Swnj #define DBSIZE 20 9532362Swnj 9542362Swnj hpdump(dev) 9552362Swnj dev_t dev; 9562362Swnj { 9572978Swnj register struct mba_device *mi; 9582383Swnj register struct mba_regs *mba; 9592624Swnj struct hpdevice *hpaddr; 9602362Swnj char *start; 9612383Swnj int num, unit; 9622383Swnj register struct hpst *st; 9632362Swnj 9642362Swnj num = maxfree; 9652362Swnj start = 0; 96624738Sbloom unit = hpunit(dev); 9672827Swnj if (unit >= NHP) 9682827Swnj return (ENXIO); 9692383Swnj #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 9702978Swnj mi = phys(hpinfo[unit],struct mba_device *); 9712827Swnj if (mi == 0 || mi->mi_alive == 0) 9722827Swnj return (ENXIO); 9732383Swnj mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 9743102Swnj mba->mba_cr = MBCR_INIT; 9752624Swnj hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive]; 9763093Swnj if ((hpaddr->hpds & HPDS_VV) == 0) { 9772624Swnj hpaddr->hpcs1 = HP_DCLR|HP_GO; 9782624Swnj hpaddr->hpcs1 = HP_PRESET|HP_GO; 9793093Swnj hpaddr->hpof = HPOF_FMT22; 9802362Swnj } 9812383Swnj st = &hpst[mi->mi_type]; 98224224Sbloom if (dumplo < 0) 9832827Swnj return (EINVAL); 98424224Sbloom if (dumplo + num >= st->sizes[minor(dev)&07].nblocks) 98524224Sbloom num = st->sizes[minor(dev)&07].nblocks - dumplo; 9862362Swnj while (num > 0) { 9872383Swnj register struct pte *hpte = mba->mba_map; 9882362Swnj register int i; 9892383Swnj int blk, cn, sn, tn; 9902362Swnj daddr_t bn; 9912362Swnj 9922362Swnj blk = num > DBSIZE ? DBSIZE : num; 9932362Swnj bn = dumplo + btop(start); 9942383Swnj cn = bn/st->nspc + st->sizes[minor(dev)&07].cyloff; 9952383Swnj sn = bn%st->nspc; 9962383Swnj tn = sn/st->nsect; 9972383Swnj sn = sn%st->nsect; 9982362Swnj hpaddr->hpdc = cn; 9992362Swnj hpaddr->hpda = (tn << 8) + sn; 10002362Swnj for (i = 0; i < blk; i++) 10012362Swnj *(int *)hpte++ = (btop(start)+i) | PG_V; 10022383Swnj mba->mba_sr = -1; 10032383Swnj mba->mba_bcr = -(blk*NBPG); 10042383Swnj mba->mba_var = 0; 10052624Swnj hpaddr->hpcs1 = HP_WCOM | HP_GO; 10063093Swnj while ((hpaddr->hpds & HPDS_DRY) == 0) 100716791Skarels DELAY(10); 10083093Swnj if (hpaddr->hpds&HPDS_ERR) 10092827Swnj return (EIO); 10102362Swnj start += blk*NBPG; 10112362Swnj num -= blk; 10122362Swnj } 10132362Swnj return (0); 10142362Swnj } 101512506Ssam 101612506Ssam hpsize(dev) 101712506Ssam dev_t dev; 101812506Ssam { 101924738Sbloom int unit = hpunit(dev); 102012506Ssam struct mba_device *mi; 102112506Ssam struct hpst *st; 102212506Ssam 102312506Ssam if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0) 102412506Ssam return (-1); 102512506Ssam st = &hpst[mi->mi_type]; 102612506Ssam return ((int)st->sizes[minor(dev) & 07].nblocks); 102712506Ssam } 10281565Sbill #endif 1029