132529Sbostic /* 232529Sbostic * Stand alone driver for the HDC controller 332557Sbostic * 4*33164Sbostic * @(#)hd.c 7.4 (Berkeley) 12/28/87 532529Sbostic */ 632557Sbostic #define KERNEL 732529Sbostic 832557Sbostic #include "machine/mtpr.h" 9*33164Sbostic 1032557Sbostic #include "param.h" 1132557Sbostic #include "inode.h" 1232557Sbostic #include "fs.h" 13*33164Sbostic #include "buf.h" 1432557Sbostic #include "ioctl.h" 15*33164Sbostic #include "disklabel.h" 1632557Sbostic #include "saio.h" 1732529Sbostic 18*33164Sbostic #include "../tahoevba/dsk.h" 19*33164Sbostic #include "../tahoevba/dskio.h" 20*33164Sbostic #include "../tahoevba/hdc.h" 21*33164Sbostic 2232557Sbostic #define NHD 4 2332557Sbostic #define NDRIVE 8 /* drives per controller */ 2432557Sbostic #define HDSLAVE(x) ((x) % NDRIVE) 2532557Sbostic #define HDCTLR(x) ((x) / NDRIVE) 2632529Sbostic 27*33164Sbostic #define HDC_DEFBUS 0 /* we only handle bus zero, for now */ 2832557Sbostic #define HDREG(x) (ctlr_addr->x) /* standalone io to an hdc register */ 2932557Sbostic #define HID_HDC 0x01 /* hvme_id for HDC */ 3032529Sbostic 3132529Sbostic /* 3232529Sbostic * hdc controller table. It contains information about the hdc controller. 3332529Sbostic */ 3432529Sbostic typedef struct { 35*33164Sbostic int ctlr; /* controller number (0-15) */ 3632529Sbostic hdc_regs_type *registers; /* base address of hdc io registers */ 37*33164Sbostic hdc_mid_type mid; /* the module id is read to here */ 38*33164Sbostic master_mcb_type master_mcb; /* the master mcb for this hdc */ 3932529Sbostic mcb_type mcb; /* an mcb for i/o to the controller */ 4032529Sbostic } hdctlr_type; 4132529Sbostic 4232529Sbostic hdctlr_type hdc_ctlr[HDC_MAXCTLR][HDC_MAXBUS]; 4332529Sbostic 4432529Sbostic /* 4532529Sbostic * hdc unit table. It contains information about the hdc drive. 4632529Sbostic * Some information is obtained from the profile prom and geometry block. 4732529Sbostic */ 4832529Sbostic typedef struct { 49*33164Sbostic par_tab partition[GB_MAXPART]; /* partition definitions */ 50*33164Sbostic int ctlr; /* the controller number (0-15) */ 51*33164Sbostic int slave; /* the slave number (0-4) */ 52*33164Sbostic int unit; /* the unit number (0-31) */ 53*33164Sbostic int id; /* identifies the disk model */ 54*33164Sbostic int cylinders; /* number of logical cylinders */ 55*33164Sbostic int heads; /* number of logical heads */ 56*33164Sbostic int sectors; /* number of logical sectors/track */ 57*33164Sbostic int phys_cylinders; /* number of physical cylinders */ 58*33164Sbostic int phys_heads; /* number of physical heads */ 5932560Sbostic int phys_sectors; /* number of physical sectors/track */ 60*33164Sbostic int def_cyl; /* logical cylinder of drive def */ 61*33164Sbostic int def_cyl_count; /* number of logical def cylinders */ 62*33164Sbostic int diag_cyl; /* logical cylinder of diag area */ 6332560Sbostic int diag_cyl_count; /* number of logical diag cylinders */ 64*33164Sbostic int rpm; /* disk rpm */ 65*33164Sbostic int bytes_per_sec; /* bytes/sector -vendorflaw conversn */ 66*33164Sbostic int format; /* format program is active */ 67*33164Sbostic u_long phio_data[HDC_PHIO_SIZE]; /* data for physical io */ 6832529Sbostic } hdunit_type; 6932529Sbostic 70*33164Sbostic hdunit_type hdc_unit [HDC_MAXDRIVE] [HDC_MAXCTLR] [HDC_MAXBUS]; 7132529Sbostic 72*33164Sbostic /* 73*33164Sbostic * hdopen -- 74*33164Sbostic * initialize the hdc and read the disk label 75*33164Sbostic */ 7632529Sbostic hdopen(io) 7732560Sbostic register struct iob *io; /* i/o block */ 7832529Sbostic { 79*33164Sbostic drive_stat_type status; /* the hdc status is read to here */ 80*33164Sbostic hdc_mid_type *id; /* the hdc module id */ 81*33164Sbostic hdc_regs_type *ctlr_addr; /* hdc i/o registers */ 82*33164Sbostic hdctlr_type *hc; /* hdc ctlr information table */ 83*33164Sbostic hdunit_type *hu; /* disk unit information table */ 84*33164Sbostic geometry_sector geometry; /* the geometry block sector */ 85*33164Sbostic geometry_block *geo; /* the geometry block */ 86*33164Sbostic mcb_type *mcb; /* an mcb to send commands to hdc */ 87*33164Sbostic long junk = 0; /* badaddr will write junk here */ 88*33164Sbostic int par; /* partition number */ 89*33164Sbostic int bus, ctlr, drive, error, i, unit; 9032529Sbostic 91*33164Sbostic /* validate the device specification */ 92*33164Sbostic if ((ctlr = HDCTLR(io->i_unit)) >= HDC_MAXCTLR) { 9332557Sbostic printf("invalid controller number\n"); 9432560Sbostic return(ENXIO); 9532557Sbostic } 96*33164Sbostic if ((drive = HDSLAVE(io->i_unit)) < 0 || drive > HDC_MAXDRIVE - 1) { 9732529Sbostic printf("hdc: bad drive number.\n"); 9832560Sbostic return(EUNIT); 9932529Sbostic } 100*33164Sbostic if ((par = io->i_boff) < 0 || par > 7) { 10132529Sbostic printf("hdc: bad partition number.\n"); 10232560Sbostic return(EUNIT); 10332529Sbostic } 104*33164Sbostic bus = HDC_DEFBUS; 10532529Sbostic 106*33164Sbostic ctlr_addr = (hdc_regs_type *)(bus ? 107*33164Sbostic 0x80000000 | ctlr << 24 | HDC_MID << 16 : 108*33164Sbostic 0xC0000000 | ctlr << 24 | HDC_MID << 16); 109*33164Sbostic 110*33164Sbostic hu = &hdc_unit[drive][ctlr][bus]; 111*33164Sbostic hc = &hdc_ctlr[ctlr][bus]; 112*33164Sbostic mcb = &hc->mcb; 113*33164Sbostic 114*33164Sbostic /* init drive structure. */ 11532529Sbostic hu->slave = drive; 11632529Sbostic hc->registers = ctlr_addr; 11732529Sbostic 118*33164Sbostic /* insure that this is an hdc, then reset the hdc. */ 11932557Sbostic if (wbadaddr(&ctlr_addr->module_id_reg, 4, &junk)) { 12032560Sbostic printf("hd%d: %x: invalid csr\n", ctlr, (u_int)ctlr_addr); 12132560Sbostic return(ENXIO); 12232557Sbostic } 12332529Sbostic HDREG(soft_reset_reg) = 0; 12432529Sbostic DELAY(1000000); 12532529Sbostic 12632529Sbostic /* 12732560Sbostic * Read in the hdc module id word. The controller is bad if the 12832560Sbostic * hdc's writeable control store is not loaded or if the hdc failed 12932560Sbostic * the functional integrity test for any reason. 13032529Sbostic */ 13132529Sbostic id = &hc->mid; 13232560Sbostic HDREG(module_id_reg) = (u_long)id; 13332529Sbostic DELAY(10000); 13432557Sbostic mtpr(PADC, 0); 135*33164Sbostic 13632560Sbostic if (id->module_id != (u_char)HDC_MID) { 13732560Sbostic printf("hdc: Controller bad module id: id = %x\n", 13832560Sbostic id->module_id); 139*33164Sbostic return(ENXIO); 14032529Sbostic } 14132560Sbostic if (id->code_rev == (u_char)0xFF) { 14232560Sbostic printf("hdc: Controller micro-code is not loaded.\n"); 14332560Sbostic return(ENXIO); 14432529Sbostic } 14532560Sbostic if (id->fit != (u_char)0xFF) { 14632560Sbostic printf("hdc: Controller FIT test failed: error= %x\n", 14732560Sbostic id->fit); 14832560Sbostic return(ENXIO); 14932529Sbostic } 15032529Sbostic 151*33164Sbostic /* Read the drive status. Save important info. */ 15232529Sbostic mcb->command = HCMD_STATUS; 15332529Sbostic mcb->drive = drive; 15432529Sbostic mcb->cyl = 0; 15532529Sbostic mcb->head = 0; 15632529Sbostic mcb->sector = 0; 157*33164Sbostic mcb->chain[0].lwc = (long)sizeof(drive_stat_type) / sizeof(long); 15832560Sbostic mcb->chain[0].ta = (long)&status; 15932529Sbostic if (hdmcb(mcb, io)) 16032560Sbostic return(EIO); 161*33164Sbostic 162*33164Sbostic /* 163*33164Sbostic * Report drive down if anything in the drive status is bad. 164*33164Sbostic * If fault condition, reading will try to clear the fault. 165*33164Sbostic */ 166*33164Sbostic if (status.drs & DRS_FAULT) 167*33164Sbostic printf("hdc: clearing drive fault.\n"); 168*33164Sbostic if (!(status.drs & DRS_ONLINE)) { 169*33164Sbostic printf("hdc: drive is not online.\n"); 170*33164Sbostic return(EIO); 171*33164Sbostic } 172*33164Sbostic 17332529Sbostic hu->cylinders = status.max_cyl+1; 17432529Sbostic hu->heads = status.max_head+1; 17532529Sbostic hu->sectors = status.max_sector+1; 17632529Sbostic hu->def_cyl = status.def_cyl; 17732529Sbostic hu->def_cyl_count = status.def_cyl_count; 17832529Sbostic hu->diag_cyl = status.diag_cyl; 17932529Sbostic hu->diag_cyl_count = status.diag_cyl_count; 18032529Sbostic hu->phys_cylinders = status.max_phys_cyl+1; 18132529Sbostic hu->phys_heads = status.max_phys_head+1; 18232529Sbostic hu->phys_sectors = status.max_phys_sector+1; 18332529Sbostic hu->bytes_per_sec = status.bytes_per_sec; 18432529Sbostic hu->id = status.id; 18532529Sbostic hu->rpm = status.rpm; 18632529Sbostic hu->partition[HDC_DEFPART].start= 18732529Sbostic hu->def_cyl * hu->sectors * hu->heads / HDC_SPB; 18832529Sbostic hu->partition[HDC_DEFPART].length = 18932529Sbostic hu->def_cyl_count * hu->sectors * hu->heads / HDC_SPB; 19032529Sbostic 19132529Sbostic /* 19232529Sbostic * Read the geometry block (at head=0 sector=0 of the drive 19332529Sbostic * definition cylinder), validate it (must have the correct 19432529Sbostic * version number, header, and checksum). 19532529Sbostic */ 19632529Sbostic geo = &geometry.geometry_block; 19732529Sbostic mcb->command = HCMD_READ; 19832529Sbostic mcb->drive = drive; 199*33164Sbostic mcb->cyl = hu->def_cyl; 20032529Sbostic mcb->head = 0; 20132529Sbostic mcb->sector = 0; 202*33164Sbostic mcb->chain[0].lwc = sizeof(geometry_sector) / sizeof(long); 20332560Sbostic mcb->chain[0].ta = (long)&geometry; 204*33164Sbostic io->i_boff = hu->partition[HDC_DEFPART].start; /* default */ 20532529Sbostic if (hdmcb(mcb, io)) { 20632529Sbostic printf("hdc: could not read geometry block\n"); 20732560Sbostic return(EIO); 20832529Sbostic } 20932529Sbostic io->i_boff = 0; 21032560Sbostic if (geo->version > 64000 || geo->version < 0) { 21132529Sbostic printf("hdc: bad geometry block version#\n"); 21232560Sbostic return(ENXIO); 21332529Sbostic } 21432560Sbostic if (strcmp(&geo->id[0], GB_ID) != 0) { 21532529Sbostic printf("hdc: bad geometry block header\n"); 21632560Sbostic return(ENXIO); 21732529Sbostic } 21832560Sbostic GB_CHECKSUM(geo, i); 21932529Sbostic if (geometry.checksum != i) { 22032529Sbostic printf("hdc: bad geometry block checksum\n"); 22132560Sbostic return(ENXIO); 22232529Sbostic } 22332529Sbostic 22432529Sbostic /* 22532529Sbostic * Set the partition start/size info. 22632529Sbostic * Note: this info was already defaulted to be the disk 22732529Sbostic * definition partition. 22832529Sbostic */ 22932560Sbostic if (par != HDC_DEFPART) 230*33164Sbostic if (geo->partition[par].length == 0) { /* XXX */ 231*33164Sbostic printf("hdc: null partition\n"); 23232560Sbostic return(ENXIO); 23332557Sbostic } 23432529Sbostic else { 23532529Sbostic hu->partition[par].start = geo->partition[par].start; 23632529Sbostic hu->partition[par].length = geo->partition[par].length; 23732529Sbostic io->i_boff = hu->partition[par].start; 23832529Sbostic } 23932560Sbostic return(0); 24032529Sbostic } 24132529Sbostic 242*33164Sbostic /* 243*33164Sbostic * hdstrategy -- 244*33164Sbostic * The hdc strategy routine. This routine does the disk reads/writes. If 245*33164Sbostic * this is the format program, read/writes are forced to be within the 246*33164Sbostic * disk definition partition. Returns the number of bytes transferred. 247*33164Sbostic */ 24832560Sbostic hdstrategy(io, cmd) 24932560Sbostic register struct iob *io; /* i/o block */ 25032560Sbostic int cmd; /* i/o operation to perform */ 25132529Sbostic { 252*33164Sbostic mcb_type *mcb; /* mcb to send to the hdc */ 253*33164Sbostic hdunit_type *hu; /* disk unit information table */ 254*33164Sbostic hdctlr_type *hc; /* hdc ctlr information table */ 255*33164Sbostic long err; /* error code */ 256*33164Sbostic long sector; /* sector number for i/o */ 257*33164Sbostic int partstart; /* block number of partition start */ 258*33164Sbostic int partlen; /* number of blocks in partition */ 259*33164Sbostic int bytes; /* number of bytes to transfer */ 260*33164Sbostic int bus, ctlr, drive; 26132529Sbostic 262*33164Sbostic bus = HDC_DEFBUS; 263*33164Sbostic ctlr = HDCTLR(io->i_unit); 264*33164Sbostic drive = HDSLAVE(io->i_unit); 26532529Sbostic hu = &hdc_unit[drive][ctlr][bus]; 26632529Sbostic hc = &hdc_ctlr[ctlr][bus]; 26732529Sbostic 26832529Sbostic /* 26932529Sbostic * Only the format program can access the disk definition tracks. 27032529Sbostic */ 27132560Sbostic if (io->i_boff == HDC_DEFPART && !hu->format) { 27232560Sbostic printf("hdc: partition 7 is protected\n"); 27332560Sbostic return(0); 27432560Sbostic } 27532529Sbostic 27632529Sbostic /* 27732529Sbostic * Insure the transfer fits in the partition. 27832529Sbostic * Set and validate transfer size. 27932529Sbostic */ 28032560Sbostic partstart = hu->partition[io->i_boff].start; 28132560Sbostic partlen = hu->partition[io->i_boff].length; 28232560Sbostic if (io->i_bn < partstart || io->i_bn >= partstart + partlen) 28332560Sbostic return(0); 28432560Sbostic bytes = MIN(io->i_cc, DEV_BSIZE * (partstart + partlen-io->i_bn)); 28532529Sbostic if (io->i_cc & 3) { 28632560Sbostic printf("hdc: i/o not a longword multiple\n"); 28732560Sbostic return(0); 28832529Sbostic } 28932529Sbostic 29032529Sbostic /* 29132529Sbostic * Set up the mcb and send it to the hdc. 29232529Sbostic */ 29332529Sbostic mcb = &hc->mcb; 29432529Sbostic sector = io->i_bn * HDC_SPB; 29532560Sbostic mcb->command = (cmd == READ) ? HCMD_READ : HCMD_WRITE; 29632529Sbostic mcb->drive = hu->slave; 29732529Sbostic mcb->cyl = sector / (hu->sectors * hu->heads); 29832560Sbostic mcb->head = (sector / hu->sectors) % hu->heads; 29932529Sbostic mcb->sector = sector % hu->sectors; 30032560Sbostic mcb->chain[0].ta = (u_long)io->i_ma; 301*33164Sbostic mcb->chain[0].lwc = (bytes + 3) / sizeof(long); 30232529Sbostic err = hdmcb(mcb, io); 30332529Sbostic io->i_error = err; 30432560Sbostic return(err ? 0 : bytes); 30532529Sbostic } 30632529Sbostic 30732529Sbostic hdioctl(io, command, arg) 30832560Sbostic struct iob *io; /* i/o block */ 309*33164Sbostic int command; /* ioctl commmand */ 310*33164Sbostic int arg; /* data; format depends on ioctl */ 31132529Sbostic { 31232560Sbostic register int i; 31332529Sbostic mcb_type *mcb; 314*33164Sbostic hdunit_type *hu; /* disk unit information table */ 315*33164Sbostic hdctlr_type *hc; /* hdc ctlr information table */ 316*33164Sbostic int bus, ctlr, drive; 31732529Sbostic 318*33164Sbostic bus = HDC_DEFBUS; 319*33164Sbostic ctlr = HDCTLR(io->i_unit); 320*33164Sbostic drive = HDSLAVE(io->i_unit); 32132529Sbostic hu = &hdc_unit[drive][ctlr][bus]; 32232529Sbostic hc = &hdc_ctlr[ctlr][bus]; 32332529Sbostic 32432529Sbostic switch (command) { 32532529Sbostic 32632529Sbostic case DSKIOCFORMAT: { 32732529Sbostic 32832529Sbostic /* 32932529Sbostic * Format a disk track. The received argument is a pointer 33032529Sbostic * to a "formatop" structure describing the track to format. 33132529Sbostic * 33232529Sbostic * Set up a buffer with each longword corresponding to a 33332529Sbostic * sector on the track; a 1 means no flaw, a 0 means a flaw. 33432529Sbostic * Send an mcb to the hdc to format the track. 33532529Sbostic */ 33632529Sbostic 33732529Sbostic register struct formatop *track; 33832529Sbostic 33932529Sbostic if (!hu->format) 34032529Sbostic return(1); 34132560Sbostic track = (struct formatop *)arg; 34232529Sbostic mcb = &hc->mcb; 34332560Sbostic for (i = 0; i < hu->phys_sectors; i++) 34432529Sbostic hu->phio_data[i] = 1; 34532560Sbostic for (i = 0; i < track->flaw_count; i++) 34632560Sbostic hu->phio_data[track->flaw[i]] = 0; 34732529Sbostic mcb->command = HCMD_FORMAT; 34832529Sbostic mcb->drive = hu->slave; 34932560Sbostic mcb->chain[0].ta = (u_long)hu->phio_data; 35032529Sbostic mcb->chain[0].lwc = hu->phys_sectors; 35132529Sbostic mcb->cyl = track->cylinder; 35232529Sbostic mcb->head = track->head; 35332529Sbostic mcb->sector = 0; 35432529Sbostic if (hdmcb(mcb, io)) 35532560Sbostic return(EIO); 35632529Sbostic break; 35732529Sbostic } 35832529Sbostic 35932529Sbostic case DSKIOCCERTIFY: { 36032529Sbostic 36132529Sbostic /* 36232529Sbostic * Certify a disk track. The received argument is a pointer 36332529Sbostic * to a "formatop" structure describing the track to certify. 36432529Sbostic * 36532529Sbostic * Send an mcb to the hdc to certify the track. 36632529Sbostic * The controller returns data in which each longword 36732529Sbostic * corresponds to a sector on the track; a 1 means no flaw, 36832529Sbostic * a 0 means a flaw. 36932529Sbostic */ 37032529Sbostic 37132529Sbostic register struct formatop *track; 37232529Sbostic 37332529Sbostic if (!hu->format) 37432560Sbostic return(1); 37532560Sbostic track = (struct formatop *)arg; 37632529Sbostic mcb = &hc->mcb; 37732529Sbostic mcb->command = HCMD_CERTIFY; 37832529Sbostic mcb->drive = hu->slave; 37932560Sbostic mcb->chain[0].ta = (u_long)hu->phio_data; 38032529Sbostic mcb->chain[0].lwc = hu->phys_sectors; 38132529Sbostic mcb->cyl = track->cylinder; 38232529Sbostic mcb->head = track->head; 38332529Sbostic mcb->sector = 0; 38432529Sbostic if (hdmcb(mcb, io)) 38532560Sbostic return(EIO); 38632529Sbostic track->flaw_count = 0; 38732560Sbostic for (i = 0; i < hu->phys_sectors; i++) { 38832560Sbostic if (track->flaw_count >= MAXVFLAW) 38932560Sbostic break; 39032560Sbostic if (hu->phio_data[i] == 0) { 39132529Sbostic track->flaw[track->flaw_count] = i; 39232529Sbostic track->flaw_count++; 39332529Sbostic } 39432529Sbostic } 39532529Sbostic break; 39632529Sbostic } 39732529Sbostic 39832529Sbostic case DSKIOCVERIFY: { 39932529Sbostic 40032529Sbostic /* 40132529Sbostic * Verify a disk track. The received argument is a pointer 40232529Sbostic * to a "formatop" structure describing the track to verify. 40332529Sbostic */ 40432529Sbostic 40532529Sbostic register struct formatop *track; 40632529Sbostic 40732529Sbostic if (!hu->format) 40832529Sbostic return(1); 40932560Sbostic track = (struct formatop *)arg; 41032529Sbostic mcb = &hc->mcb; 41132529Sbostic mcb->command = HCMD_VERIFY; 41232529Sbostic mcb->drive = hu->slave; 41332529Sbostic mcb->chain[0].ta = 0; 41432529Sbostic mcb->chain[0].lwc = 0; 41532529Sbostic mcb->cyl = track->cylinder; 41632529Sbostic mcb->head = track->head; 41732529Sbostic mcb->sector = 0; 41832529Sbostic if (hdmcb(mcb, io)) 41932560Sbostic return(EIO); 42032529Sbostic break; 42132529Sbostic } 42232529Sbostic 42332529Sbostic case DSKIOCFORMATCTL: { 42432529Sbostic 42532529Sbostic /* 42632529Sbostic * This ioctl provides special format control. 42732529Sbostic * Currently the valid arguments are: 42832529Sbostic * 42932560Sbostic * arg = 0 disable formatting; 43032529Sbostic * 43132560Sbostic * arg = 1 enable formatting (allow privileged access); 43232560Sbostic * formatting must not already be enabled; 43332560Sbostic * For formatting, change to use partition 7. 43432529Sbostic */ 43532529Sbostic 43632560Sbostic if (arg < 0 || arg > 1) 43732560Sbostic return(1); 43832560Sbostic if (arg == 1) { 43932560Sbostic if (hu->format) 44032560Sbostic return(1); 44132529Sbostic /* If not already formatting.... */ 44232560Sbostic hu->format = 1; 44332557Sbostic /* io->i_part = HDC_DEFPART; */ 44432529Sbostic io->i_boff = hu->partition[HDC_DEFPART].start; 44532529Sbostic } 44632529Sbostic else 44732560Sbostic hu->format = 0; 44832529Sbostic break; 44932529Sbostic } 45032529Sbostic 45132529Sbostic case DSKIOCSTATUS: { 45232529Sbostic 45332529Sbostic /* 45432529Sbostic * Return info about the disk. Caller's parameter is a 45532529Sbostic * pointer to a dsk_status structure. 45632529Sbostic */ 45732529Sbostic 45832529Sbostic register dsk_status *status; 45932529Sbostic 46032560Sbostic status = (dsk_status *)arg; 46132560Sbostic status->id = hu->id; 46232560Sbostic status->drive_status = 0; 46332560Sbostic status->rpm = hu->rpm; 46432529Sbostic status->bytes_per_sec = hu->bytes_per_sec; 46532560Sbostic status->cylinders = hu->cylinders; 46632560Sbostic status->heads = hu->heads; 46732560Sbostic status->sectors = hu->sectors; 46832560Sbostic status->phys_cylinders = hu->phys_cylinders; 46932560Sbostic status->phys_heads = hu->phys_heads; 47032560Sbostic status->phys_sectors = hu->phys_sectors; 47132560Sbostic status->diag_cyl = hu->diag_cyl; 47232560Sbostic status->diag_cylinders = hu->diag_cyl_count; 47332560Sbostic status->def_cyl = hu->def_cyl; 47432560Sbostic status->def_cylinders = hu->def_cyl_count; 47532529Sbostic break; 47632529Sbostic } 47732529Sbostic 47832529Sbostic case DSKIOCVENDORFLAW: { 47932529Sbostic 48032529Sbostic /* 48132529Sbostic * Return vendor flaw info. 48232529Sbostic * 48332529Sbostic * Read in the vendor data (data for each track is at 48432529Sbostic * relative sector 0 of the track); then copy the 48532529Sbostic * vendor flaw data to the caller's buffer. 48632529Sbostic */ 48732529Sbostic 48832529Sbostic register vflaw_type *vflaw; 48932529Sbostic register struct flaw *vendor; 49032529Sbostic 49132529Sbostic if (!hu->format) 49232529Sbostic return(1); 49332560Sbostic vflaw = (vflaw_type *)arg; 49432529Sbostic mcb = &hc->mcb; 49532529Sbostic mcb->command = HCMD_VENDOR; 49632529Sbostic mcb->drive = hu->slave; 49732529Sbostic mcb->chain[0].lwc = HDC_VDATA_SIZE; 49832560Sbostic mcb->chain[0].ta = (u_long)hu->phio_data; 49932529Sbostic mcb->cyl = vflaw->cylinder; 50032529Sbostic mcb->head = vflaw->head; 50132529Sbostic mcb->sector = 0; 50232529Sbostic if (hdmcb(mcb, io)) 50332560Sbostic return(EIO); 50432560Sbostic vendor = (struct flaw *)&hu->phio_data[0]; 50532560Sbostic for (i = 0; i < MAXVFLAW; i++) { 50632529Sbostic vflaw->flaw[i].offset = vendor[i].offset; 50732529Sbostic vflaw->flaw[i].length = vendor[i].length; 50832529Sbostic } 50932529Sbostic break; 51032529Sbostic } 51132529Sbostic } 51232560Sbostic return(0); 51332529Sbostic } 51432529Sbostic 515*33164Sbostic /* 516*33164Sbostic * hdmcb -- 517*33164Sbostic * internal routine used to send mcb's to the hdc 518*33164Sbostic */ 519*33164Sbostic static 52032529Sbostic hdmcb(mcb, io) 521*33164Sbostic register mcb_type *mcb; /* mcb to send to the hdc */ 522*33164Sbostic register struct iob *io; /* i/o block */ 52332529Sbostic { 524*33164Sbostic register u_int *ptr; 525*33164Sbostic master_mcb_type *master_mcb; /* the hdc's master mcb */ 526*33164Sbostic hdctlr_type *hc; /* hdc ctlr information table */ 527*33164Sbostic hdc_regs_type *ctlr_addr; /* pointer to hdc i/o registers */ 528*33164Sbostic int timeout; /* used to timeout the mcb */ 529*33164Sbostic int bus, ctlr, i, end; 53032529Sbostic 531*33164Sbostic bus = HDC_DEFBUS; 532*33164Sbostic ctlr = HDCTLR(io->i_unit); 53332529Sbostic hc = &hdc_ctlr[ctlr][bus]; 53432529Sbostic 53532529Sbostic mcb->interrupt = FALSE; 53632529Sbostic mcb->priority = 0; 53732529Sbostic mcb->forw_phaddr = 0; 53832529Sbostic mcb->context = 0; 53932529Sbostic mcb->reserved[0] = 0; 54032529Sbostic mcb->reserved[1] = 0; 54132529Sbostic master_mcb = &hc->master_mcb; 54232560Sbostic master_mcb->forw_phaddr = (long)&mcb->forw_phaddr; 54332529Sbostic master_mcb->mcs = 0; 54432529Sbostic master_mcb->interrupt = 0; 54532560Sbostic master_mcb->reserve1 = 0; 54632560Sbostic master_mcb->reserve2 = 0; 54732560Sbostic master_mcb->context = 0; 54832529Sbostic master_mcb->mcl = MCL_IMMEDIATE; 54932560Sbostic for (i = 0; i < HDC_XSTAT_SIZE; i++) 55032560Sbostic master_mcb->xstatus[i] = 0; 55132560Sbostic ctlr_addr = hc->registers; 55232560Sbostic HDREG(master_mcb_reg) = (u_long)master_mcb; 55332529Sbostic timeout = 15000; 55432560Sbostic for (;;) { 55532529Sbostic DELAY(1000); 55632557Sbostic mtpr(PADC, 0); 55732560Sbostic if (master_mcb->mcs & MCS_DONE && 55832560Sbostic !(master_mcb->mcs & MCS_FATALERROR)) 55932560Sbostic return(0); 560*33164Sbostic if (--timeout > 0 && !(master_mcb->mcs & MCS_FATALERROR)) 56132560Sbostic continue; 56232560Sbostic if (master_mcb->mcs & MCS_FATALERROR) 56332529Sbostic printf("hdc: controller fatal error\n"); 56432529Sbostic else 56532529Sbostic printf("hdc: controller timed out\n"); 56632529Sbostic 56732529Sbostic printf("mmcb: "); 56832560Sbostic ptr = (u_int *)master_mcb; 56932560Sbostic for (i = 0; i < 8; i++) 57032560Sbostic printf(" %x", ptr[i]); 57132560Sbostic for (i = 7 + HDC_XSTAT_SIZE; i > 7; i--) { 57232529Sbostic end = i; 57332560Sbostic if (ptr[i] != 0) 57432560Sbostic break; 57532529Sbostic } 57632560Sbostic for (i = 8; i <= end; i++) 57732560Sbostic printf(" %x", ptr[i]); 57832529Sbostic 579*33164Sbostic printf("\nmcb: "); 58032560Sbostic ptr = (u_int *)&mcb->forw_phaddr; 58132560Sbostic for (i = 0; i < 6; i++) 58232560Sbostic printf(" %x", ptr[i]); 58332560Sbostic for (i = 6; i < 72; i += 2) { 58432529Sbostic printf(" %x %x", ptr[i], ptr[i+1]); 58532560Sbostic if (!(ptr[i] & 0x80000000)) 58632560Sbostic break; 58732529Sbostic } 58832529Sbostic printf("\n"); 58932529Sbostic return(1); 59032529Sbostic } 59132529Sbostic } 592