132529Sbostic /* 232529Sbostic * Stand alone driver for the HDC controller 332557Sbostic * 4*32560Sbostic * @(#)hd.c 7.3 (Berkeley) 10/28/87 532529Sbostic */ 632557Sbostic #define KERNEL 732529Sbostic 832557Sbostic #include "machine/mtpr.h" 932557Sbostic #include "param.h" 1032557Sbostic #include "systm.h" 1132557Sbostic #include "buf.h" 1232557Sbostic #include "time.h" 1332557Sbostic #include "inode.h" 1432557Sbostic #include "fs.h" 1532557Sbostic #include "ioctl.h" 1632557Sbostic #include "tahoevba/dsk.h" 1732557Sbostic #include "tahoevba/dskio.h" 1832557Sbostic #include "tahoevba/hdc.h" 1932557Sbostic #include "saio.h" 2032529Sbostic 2132557Sbostic #define NHD 4 2232557Sbostic #define NDRIVE 8 /* drives per controller */ 2332557Sbostic #define HDSLAVE(x) ((x) % NDRIVE) 2432557Sbostic #define HDCTLR(x) ((x) / NDRIVE) 2532529Sbostic 2632557Sbostic #define HDREG(x) (ctlr_addr->x) /* standalone io to an hdc register */ 2732557Sbostic #define HID_HDC 0x01 /* hvme_id for HDC */ 2832529Sbostic 2932529Sbostic /* 3032529Sbostic * hdc controller table. It contains information about the hdc controller. 3132529Sbostic */ 3232529Sbostic typedef struct { 3332529Sbostic int ctlr; /* controller number (0-15) */ 3432529Sbostic hdc_regs_type *registers; /* base address of hdc io registers */ 3532529Sbostic hdc_mid_type mid; /* the module id is read to here */ 36*32560Sbostic master_mcb_type master_mcb; /* the master mcb for this hdc */ 3732529Sbostic mcb_type mcb; /* an mcb for i/o to the controller */ 3832529Sbostic } hdctlr_type; 3932529Sbostic 4032529Sbostic hdctlr_type hdc_ctlr[HDC_MAXCTLR][HDC_MAXBUS]; 4132529Sbostic 4232529Sbostic /* 4332529Sbostic * hdc unit table. It contains information about the hdc drive. 4432529Sbostic * Some information is obtained from the profile prom and geometry block. 4532529Sbostic */ 4632529Sbostic typedef struct { 47*32560Sbostic par_tab partition[GB_MAXPART]; /* partition definitions */ 48*32560Sbostic int ctlr; /* the controller number (0-15) */ 49*32560Sbostic int slave; /* the slave number (0-4) */ 50*32560Sbostic int unit; /* the unit number (0-31) */ 51*32560Sbostic int id; /* identifies the disk model */ 52*32560Sbostic int cylinders; /* number of logical cylinders */ 53*32560Sbostic int heads; /* number of logical heads */ 54*32560Sbostic int sectors; /* number of logical sectors/track */ 55*32560Sbostic int phys_cylinders; /* number of physical cylinders */ 56*32560Sbostic int phys_heads; /* number of physical heads */ 57*32560Sbostic int phys_sectors; /* number of physical sectors/track */ 58*32560Sbostic int def_cyl; /* logical cylinder of drive def */ 59*32560Sbostic int def_cyl_count; /* number of logical def cylinders */ 60*32560Sbostic int diag_cyl; /* logical cylinder of diag area */ 61*32560Sbostic int diag_cyl_count; /* number of logical diag cylinders */ 62*32560Sbostic int rpm; /* disk rpm */ 63*32560Sbostic int bytes_per_sec; /* bytes/sector -vendorflaw conversn*/ 64*32560Sbostic int format; /* format program is active */ 65*32560Sbostic u_long phio_data[HDC_PHIO_SIZE]; /* data for physical io */ 6632529Sbostic } hdunit_type; 6732529Sbostic 68*32560Sbostic hdunit_type hdc_unit [HDC_MAXDRIVE] [HDC_MAXCTLR] [HDC_MAXBUS]; 6932529Sbostic 7032529Sbostic /************************************************************************* 7132529Sbostic * Procedure: hdopen 7232529Sbostic * 73*32560Sbostic * Description: The hdc open routine. Initializes the hdc and reads the 74*32560Sbostic * hdc status and the geometry block. 7532529Sbostic * 76*32560Sbostic * Returns: 0 open was successful 77*32560Sbostic * -1 this is not an hdc controller 7832529Sbostic **************************************************************************/ 7932529Sbostic hdopen(io) 80*32560Sbostic register struct iob *io; /* i/o block */ 8132529Sbostic { 8232529Sbostic mcb_type *mcb; /* an mcb to send commands to hdc */ 8332529Sbostic hdunit_type *hu; /* disk unit information table */ 8432529Sbostic hdctlr_type *hc; /* hdc ctlr information table */ 8532529Sbostic hdc_mid_type *id; /* the hdc module id */ 86*32560Sbostic geometry_sector geometry; /* the geometry block sector */ 8732529Sbostic geometry_block *geo; /* the geometry block */ 8832529Sbostic drive_stat_type status; /* the hdc status is read to here */ 89*32560Sbostic long ctlr; /* the controller number */ 90*32560Sbostic long junk; /* badaddr will write junk here */ 9132529Sbostic int par; /* partition number */ 92*32560Sbostic int drive; /* the drive number */ 93*32560Sbostic int bus; /* the bus number */ 94*32560Sbostic int i; /* temp */ 9532529Sbostic hdc_regs_type *ctlr_addr; /* hdc i/o registers */ 9632529Sbostic 97*32560Sbostic par = io->i_boff; /* io->i_part; */ 98*32560Sbostic bus = 0; /* io->i_bus; */ 99*32560Sbostic ctlr = HDCTLR(io->i_unit); /* io->i_ctlr; */ 100*32560Sbostic drive = HDSLAVE(io->i_unit); /* io->i_drive; */ 10132529Sbostic hu = &hdc_unit[drive][ctlr][bus]; 10232529Sbostic hc = &hdc_ctlr[ctlr][bus]; 10332529Sbostic mcb = &hc->mcb; 10432529Sbostic 10532529Sbostic /* 10632529Sbostic * Validate the device specification 10732529Sbostic */ 10832557Sbostic if (ctlr >= HDC_MAXCTLR) { 10932557Sbostic printf("invalid controller number\n"); 110*32560Sbostic return(ENXIO); 11132557Sbostic } 112*32560Sbostic if (drive < 0 || drive > HDC_MAXDRIVE - 1) { 11332529Sbostic printf("hdc: bad drive number.\n"); 114*32560Sbostic return(EUNIT); 11532529Sbostic } 11632529Sbostic if (par < 0 || par > 7) { 11732529Sbostic printf("hdc: bad partition number.\n"); 118*32560Sbostic return(EUNIT); 11932529Sbostic } 12032557Sbostic ctlr_addr = (hdc_regs_type *)(bus == 0 ? 12132529Sbostic 0xC0000000 | ctlr << 24 | HDC_MID << 16 : 12232557Sbostic 0x80000000 | ctlr << 24 | HDC_MID << 16); 12332529Sbostic 12432529Sbostic /* 12532529Sbostic * Init drive structure. 12632529Sbostic */ 12732529Sbostic hu->slave = drive; 12832529Sbostic hc->registers = ctlr_addr; 12932529Sbostic 13032529Sbostic /* 13132529Sbostic * Insure that this is an hdc, then reset the hdc. 13232529Sbostic */ 13332557Sbostic junk = 0; 13432557Sbostic if (wbadaddr(&ctlr_addr->module_id_reg, 4, &junk)) { 135*32560Sbostic printf("hd%d: %x: invalid csr\n", ctlr, (u_int)ctlr_addr); 136*32560Sbostic return(ENXIO); 13732557Sbostic } 13832529Sbostic HDREG(soft_reset_reg) = 0; 13932529Sbostic DELAY(1000000); 14032529Sbostic 14132529Sbostic /* 142*32560Sbostic * Read in the hdc module id word. The controller is bad if the 143*32560Sbostic * hdc's writeable control store is not loaded or if the hdc failed 144*32560Sbostic * the functional integrity test for any reason. 14532529Sbostic */ 14632529Sbostic id = &hc->mid; 147*32560Sbostic HDREG(module_id_reg) = (u_long)id; 14832529Sbostic DELAY(10000); 14932557Sbostic mtpr(PADC, 0); 150*32560Sbostic if (id->module_id != (u_char)HDC_MID) { 151*32560Sbostic printf("hdc: Controller bad module id: id = %x\n", 152*32560Sbostic id->module_id); 153*32560Sbostic return(-1); 15432529Sbostic } 155*32560Sbostic if (id->code_rev == (u_char)0xFF) { 156*32560Sbostic printf("hdc: Controller micro-code is not loaded.\n"); 157*32560Sbostic return(ENXIO); 15832529Sbostic } 159*32560Sbostic if (id->fit != (u_char)0xFF) { 160*32560Sbostic printf("hdc: Controller FIT test failed: error= %x\n", 161*32560Sbostic id->fit); 162*32560Sbostic return(ENXIO); 16332529Sbostic } 16432529Sbostic 16532529Sbostic /* 16632529Sbostic * Read the drive status. Save important info. 16732529Sbostic */ 16832529Sbostic mcb->command = HCMD_STATUS; 16932529Sbostic mcb->drive = drive; 17032529Sbostic mcb->cyl = 0; 17132529Sbostic mcb->head = 0; 17232529Sbostic mcb->sector = 0; 173*32560Sbostic mcb->chain[0].lwc = (long)sizeof(drive_stat_type) / 4; 174*32560Sbostic mcb->chain[0].ta = (long)&status; 17532529Sbostic if (hdmcb(mcb, io)) 176*32560Sbostic return(EIO); 17732529Sbostic hu->cylinders = status.max_cyl+1; 17832529Sbostic hu->heads = status.max_head+1; 17932529Sbostic hu->sectors = status.max_sector+1; 18032529Sbostic hu->def_cyl = status.def_cyl; 18132529Sbostic hu->def_cyl_count = status.def_cyl_count; 18232529Sbostic hu->diag_cyl = status.diag_cyl; 18332529Sbostic hu->diag_cyl_count = status.diag_cyl_count; 18432529Sbostic hu->phys_cylinders = status.max_phys_cyl+1; 18532529Sbostic hu->phys_heads = status.max_phys_head+1; 18632529Sbostic hu->phys_sectors = status.max_phys_sector+1; 18732529Sbostic hu->bytes_per_sec = status.bytes_per_sec; 18832529Sbostic hu->id = status.id; 18932529Sbostic hu->rpm = status.rpm; 19032529Sbostic hu->partition[HDC_DEFPART].start= 19132529Sbostic hu->def_cyl * hu->sectors * hu->heads / HDC_SPB; 19232529Sbostic hu->partition[HDC_DEFPART].length = 19332529Sbostic hu->def_cyl_count * hu->sectors * hu->heads / HDC_SPB; 194*32560Sbostic io->i_boff = hu->partition[HDC_DEFPART].start; /* default */ 19532529Sbostic 19632529Sbostic /* 19732529Sbostic * Report drive down if anything in the drive status is bad. 19832529Sbostic * If fault condition, reading geo will try to clear the fault. 19932529Sbostic */ 20032529Sbostic if (status.drs & DRS_FAULT) 20132529Sbostic printf("hdc: clearing drive fault.\n"); 202*32560Sbostic if (!(status.drs & DRS_ONLINE)) { 20332529Sbostic printf("hdc: drive is not online.\n"); 204*32560Sbostic return(EIO); 20532529Sbostic } 20632529Sbostic 20732529Sbostic /* 20832529Sbostic * Read the geometry block (at head=0 sector=0 of the drive 20932529Sbostic * definition cylinder), validate it (must have the correct 21032529Sbostic * version number, header, and checksum). 21132529Sbostic */ 21232529Sbostic geo = &geometry.geometry_block; 21332529Sbostic mcb->command = HCMD_READ; 21432529Sbostic mcb->drive = drive; 21532529Sbostic mcb->cyl = status.def_cyl; 21632529Sbostic mcb->head = 0; 21732529Sbostic mcb->sector = 0; 21832529Sbostic mcb->chain[0].lwc = sizeof(geometry_sector) / 4; 219*32560Sbostic mcb->chain[0].ta = (long)&geometry; 22032529Sbostic if (hdmcb(mcb, io)) { 22132529Sbostic printf("hdc: could not read geometry block\n"); 222*32560Sbostic return(EIO); 22332529Sbostic } 22432529Sbostic io->i_boff = 0; 225*32560Sbostic if (geo->version > 64000 || geo->version < 0) { 22632529Sbostic printf("hdc: bad geometry block version#\n"); 227*32560Sbostic return(ENXIO); 22832529Sbostic } 229*32560Sbostic if (strcmp(&geo->id[0], GB_ID) != 0) { 23032529Sbostic printf("hdc: bad geometry block header\n"); 231*32560Sbostic return(ENXIO); 23232529Sbostic } 233*32560Sbostic GB_CHECKSUM(geo, i); 23432529Sbostic if (geometry.checksum != i) { 23532529Sbostic printf("hdc: bad geometry block checksum\n"); 236*32560Sbostic return(ENXIO); 23732529Sbostic } 23832529Sbostic 23932529Sbostic /* 24032529Sbostic * Set the partition start/size info. 24132529Sbostic * Note: this info was already defaulted to be the disk 24232529Sbostic * definition partition. 24332529Sbostic */ 244*32560Sbostic if (par != HDC_DEFPART) 24532557Sbostic if (geo->partition[par].length == 0) { 24632529Sbostic printf("hdc: null partition\n"); 247*32560Sbostic return(ENXIO); 24832557Sbostic } 24932529Sbostic else { 25032529Sbostic hu->partition[par].start = geo->partition[par].start; 25132529Sbostic hu->partition[par].length = geo->partition[par].length; 25232529Sbostic io->i_boff = hu->partition[par].start; 25332529Sbostic } 254*32560Sbostic return(0); 25532529Sbostic } 25632529Sbostic 25732529Sbostic /************************************************************************* 25832529Sbostic * Procedure: hdstrategy 25932529Sbostic * 260*32560Sbostic * Description: The hdc strategy routine. This routine does the disk 261*32560Sbostic * reads/writes. If this is the format program, read/writes 262*32560Sbostic * are forced to be within the disk definition partition. 26332529Sbostic * 264*32560Sbostic * Returns: The number of bytes transfered. 26532529Sbostic **************************************************************************/ 266*32560Sbostic hdstrategy(io, cmd) 267*32560Sbostic register struct iob *io; /* i/o block */ 268*32560Sbostic int cmd; /* i/o operation to perform */ 26932529Sbostic { 27032529Sbostic mcb_type *mcb; /* mcb to send to the hdc */ 27132529Sbostic hdunit_type *hu; /* disk unit information table */ 27232529Sbostic hdctlr_type *hc; /* hdc ctlr information table */ 27332529Sbostic long err; /* error code */ 27432529Sbostic long sector; /* sector number for i/o */ 275*32560Sbostic int partstart; /* block number of partition start */ 276*32560Sbostic int partlen; /* number of blocks in partition */ 277*32560Sbostic int bytes; /* number of bytes to transfer */ 27832529Sbostic int bus; /* bus number */ 279*32560Sbostic int ctlr; /* the controller number */ 280*32560Sbostic int drive; /* the drive number */ 28132529Sbostic 282*32560Sbostic bus = 0; /* io->i_bus; */ 283*32560Sbostic ctlr = HDCTLR(io->i_unit); /* io->i_ctlr; */ 284*32560Sbostic drive = HDSLAVE(io->i_unit); /* io->i_drive; */ 28532529Sbostic hu = &hdc_unit[drive][ctlr][bus]; 28632529Sbostic hc = &hdc_ctlr[ctlr][bus]; 28732529Sbostic 28832529Sbostic /* 28932529Sbostic * Only the format program can access the disk definition tracks. 29032529Sbostic */ 291*32560Sbostic if (io->i_boff == HDC_DEFPART && !hu->format) { 292*32560Sbostic printf("hdc: partition 7 is protected\n"); 293*32560Sbostic return(0); 294*32560Sbostic } 29532529Sbostic 29632529Sbostic /* 29732529Sbostic * Insure the transfer fits in the partition. 29832529Sbostic * Set and validate transfer size. 29932529Sbostic */ 300*32560Sbostic partstart = hu->partition[io->i_boff].start; 301*32560Sbostic partlen = hu->partition[io->i_boff].length; 302*32560Sbostic if (io->i_bn < partstart || io->i_bn >= partstart + partlen) 303*32560Sbostic return(0); 304*32560Sbostic bytes = MIN(io->i_cc, DEV_BSIZE * (partstart + partlen-io->i_bn)); 30532529Sbostic if (io->i_cc & 3) { 306*32560Sbostic printf("hdc: i/o not a longword multiple\n"); 307*32560Sbostic return(0); 30832529Sbostic } 30932529Sbostic 31032529Sbostic /* 31132529Sbostic * Set up the mcb and send it to the hdc. 31232529Sbostic */ 31332529Sbostic mcb = &hc->mcb; 31432529Sbostic sector = io->i_bn * HDC_SPB; 315*32560Sbostic mcb->command = (cmd == READ) ? HCMD_READ : HCMD_WRITE; 31632529Sbostic mcb->drive = hu->slave; 31732529Sbostic mcb->cyl = sector / (hu->sectors * hu->heads); 318*32560Sbostic mcb->head = (sector / hu->sectors) % hu->heads; 31932529Sbostic mcb->sector = sector % hu->sectors; 320*32560Sbostic mcb->chain[0].ta = (u_long)io->i_ma; 32132529Sbostic mcb->chain[0].lwc = (bytes + 3) / 4; 32232529Sbostic err = hdmcb(mcb, io); 32332529Sbostic io->i_error = err; 324*32560Sbostic return(err ? 0 : bytes); 32532529Sbostic } 32632529Sbostic 32732529Sbostic /************************************************************************* 32832529Sbostic * Procedure: hdioctl 32932529Sbostic * 330*32560Sbostic * Description: ioctl routine. 33132529Sbostic * 332*32560Sbostic * Returns: 0 no errors 333*32560Sbostic * non-0 error 33432529Sbostic **************************************************************************/ 33532529Sbostic hdioctl(io, command, arg) 336*32560Sbostic struct iob *io; /* i/o block */ 337*32560Sbostic int command; /* The ioctl commmand */ 338*32560Sbostic int arg; /* Data. Format depends on ioctl */ 33932529Sbostic { 340*32560Sbostic register int i; 34132529Sbostic mcb_type *mcb; 342*32560Sbostic hdunit_type *hu; /* disk unit information table */ 343*32560Sbostic hdctlr_type *hc; /* hdc ctlr information table */ 344*32560Sbostic int bus; /* bus number */ 345*32560Sbostic int ctlr; /* the controller number */ 346*32560Sbostic int drive; /* the drive number */ 34732529Sbostic 348*32560Sbostic bus = 0; /* io->i_bus; */ 349*32560Sbostic ctlr = HDCTLR(io->i_unit); /* io->i_ctlr; */ 350*32560Sbostic drive = HDSLAVE(io->i_unit); /* io->i_drive; */ 35132529Sbostic hu = &hdc_unit[drive][ctlr][bus]; 35232529Sbostic hc = &hdc_ctlr[ctlr][bus]; 35332529Sbostic 35432529Sbostic switch (command) { 35532529Sbostic 35632529Sbostic case DSKIOCFORMAT: { 35732529Sbostic 35832529Sbostic /* 35932529Sbostic * Format a disk track. The received argument is a pointer 36032529Sbostic * to a "formatop" structure describing the track to format. 36132529Sbostic * 36232529Sbostic * Set up a buffer with each longword corresponding to a 36332529Sbostic * sector on the track; a 1 means no flaw, a 0 means a flaw. 36432529Sbostic * Send an mcb to the hdc to format the track. 36532529Sbostic */ 36632529Sbostic 36732529Sbostic register struct formatop *track; 36832529Sbostic 36932529Sbostic if (!hu->format) 37032529Sbostic return(1); 371*32560Sbostic track = (struct formatop *)arg; 37232529Sbostic mcb = &hc->mcb; 373*32560Sbostic for (i = 0; i < hu->phys_sectors; i++) 37432529Sbostic hu->phio_data[i] = 1; 375*32560Sbostic for (i = 0; i < track->flaw_count; i++) 376*32560Sbostic hu->phio_data[track->flaw[i]] = 0; 37732529Sbostic mcb->command = HCMD_FORMAT; 37832529Sbostic mcb->drive = hu->slave; 379*32560Sbostic 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)) 385*32560Sbostic return(EIO); 38632529Sbostic break; 38732529Sbostic } 38832529Sbostic 38932529Sbostic case DSKIOCCERTIFY: { 39032529Sbostic 39132529Sbostic /* 39232529Sbostic * Certify a disk track. The received argument is a pointer 39332529Sbostic * to a "formatop" structure describing the track to certify. 39432529Sbostic * 39532529Sbostic * Send an mcb to the hdc to certify the track. 39632529Sbostic * The controller returns data in which each longword 39732529Sbostic * corresponds to a sector on the track; a 1 means no flaw, 39832529Sbostic * a 0 means a flaw. 39932529Sbostic */ 40032529Sbostic 40132529Sbostic register struct formatop *track; 40232529Sbostic 40332529Sbostic if (!hu->format) 404*32560Sbostic return(1); 405*32560Sbostic track = (struct formatop *)arg; 40632529Sbostic mcb = &hc->mcb; 40732529Sbostic mcb->command = HCMD_CERTIFY; 40832529Sbostic mcb->drive = hu->slave; 409*32560Sbostic mcb->chain[0].ta = (u_long)hu->phio_data; 41032529Sbostic mcb->chain[0].lwc = hu->phys_sectors; 41132529Sbostic mcb->cyl = track->cylinder; 41232529Sbostic mcb->head = track->head; 41332529Sbostic mcb->sector = 0; 41432529Sbostic if (hdmcb(mcb, io)) 415*32560Sbostic return(EIO); 41632529Sbostic track->flaw_count = 0; 417*32560Sbostic for (i = 0; i < hu->phys_sectors; i++) { 418*32560Sbostic if (track->flaw_count >= MAXVFLAW) 419*32560Sbostic break; 420*32560Sbostic if (hu->phio_data[i] == 0) { 42132529Sbostic track->flaw[track->flaw_count] = i; 42232529Sbostic track->flaw_count++; 42332529Sbostic } 42432529Sbostic } 42532529Sbostic break; 42632529Sbostic } 42732529Sbostic 42832529Sbostic case DSKIOCVERIFY: { 42932529Sbostic 43032529Sbostic /* 43132529Sbostic * Verify a disk track. The received argument is a pointer 43232529Sbostic * to a "formatop" structure describing the track to verify. 43332529Sbostic */ 43432529Sbostic 43532529Sbostic register struct formatop *track; 43632529Sbostic 43732529Sbostic if (!hu->format) 43832529Sbostic return(1); 439*32560Sbostic track = (struct formatop *)arg; 44032529Sbostic mcb = &hc->mcb; 44132529Sbostic mcb->command = HCMD_VERIFY; 44232529Sbostic mcb->drive = hu->slave; 44332529Sbostic mcb->chain[0].ta = 0; 44432529Sbostic mcb->chain[0].lwc = 0; 44532529Sbostic mcb->cyl = track->cylinder; 44632529Sbostic mcb->head = track->head; 44732529Sbostic mcb->sector = 0; 44832529Sbostic if (hdmcb(mcb, io)) 449*32560Sbostic return(EIO); 45032529Sbostic break; 45132529Sbostic } 45232529Sbostic 45332529Sbostic case DSKIOCFORMATCTL: { 45432529Sbostic 45532529Sbostic /* 45632529Sbostic * This ioctl provides special format control. 45732529Sbostic * Currently the valid arguments are: 45832529Sbostic * 459*32560Sbostic * arg = 0 disable formatting; 46032529Sbostic * 461*32560Sbostic * arg = 1 enable formatting (allow privileged access); 462*32560Sbostic * formatting must not already be enabled; 463*32560Sbostic * For formatting, change to use partition 7. 46432529Sbostic */ 46532529Sbostic 466*32560Sbostic if (arg < 0 || arg > 1) 467*32560Sbostic return(1); 468*32560Sbostic if (arg == 1) { 469*32560Sbostic if (hu->format) 470*32560Sbostic return(1); 47132529Sbostic /* If not already formatting.... */ 472*32560Sbostic hu->format = 1; 47332557Sbostic /* io->i_part = HDC_DEFPART; */ 47432529Sbostic io->i_boff = hu->partition[HDC_DEFPART].start; 47532529Sbostic } 47632529Sbostic else 477*32560Sbostic hu->format = 0; 47832529Sbostic break; 47932529Sbostic } 48032529Sbostic 48132529Sbostic case DSKIOCSTATUS: { 48232529Sbostic 48332529Sbostic /* 48432529Sbostic * Return info about the disk. Caller's parameter is a 48532529Sbostic * pointer to a dsk_status structure. 48632529Sbostic */ 48732529Sbostic 48832529Sbostic register dsk_status *status; 48932529Sbostic 490*32560Sbostic status = (dsk_status *)arg; 491*32560Sbostic status->id = hu->id; 492*32560Sbostic status->drive_status = 0; 493*32560Sbostic status->rpm = hu->rpm; 49432529Sbostic status->bytes_per_sec = hu->bytes_per_sec; 495*32560Sbostic status->cylinders = hu->cylinders; 496*32560Sbostic status->heads = hu->heads; 497*32560Sbostic status->sectors = hu->sectors; 498*32560Sbostic status->phys_cylinders = hu->phys_cylinders; 499*32560Sbostic status->phys_heads = hu->phys_heads; 500*32560Sbostic status->phys_sectors = hu->phys_sectors; 501*32560Sbostic status->diag_cyl = hu->diag_cyl; 502*32560Sbostic status->diag_cylinders = hu->diag_cyl_count; 503*32560Sbostic status->def_cyl = hu->def_cyl; 504*32560Sbostic status->def_cylinders = hu->def_cyl_count; 50532529Sbostic break; 50632529Sbostic } 50732529Sbostic 50832529Sbostic case DSKIOCVENDORFLAW: { 50932529Sbostic 51032529Sbostic /* 51132529Sbostic * Return vendor flaw info. 51232529Sbostic * 51332529Sbostic * Read in the vendor data (data for each track is at 51432529Sbostic * relative sector 0 of the track); then copy the 51532529Sbostic * vendor flaw data to the caller's buffer. 51632529Sbostic */ 51732529Sbostic 51832529Sbostic register vflaw_type *vflaw; 51932529Sbostic register struct flaw *vendor; 52032529Sbostic 52132529Sbostic if (!hu->format) 52232529Sbostic return(1); 523*32560Sbostic vflaw = (vflaw_type *)arg; 52432529Sbostic mcb = &hc->mcb; 52532529Sbostic mcb->command = HCMD_VENDOR; 52632529Sbostic mcb->drive = hu->slave; 52732529Sbostic mcb->chain[0].lwc = HDC_VDATA_SIZE; 528*32560Sbostic mcb->chain[0].ta = (u_long)hu->phio_data; 52932529Sbostic mcb->cyl = vflaw->cylinder; 53032529Sbostic mcb->head = vflaw->head; 53132529Sbostic mcb->sector = 0; 53232529Sbostic if (hdmcb(mcb, io)) 533*32560Sbostic return(EIO); 534*32560Sbostic vendor = (struct flaw *)&hu->phio_data[0]; 535*32560Sbostic for (i = 0; i < MAXVFLAW; i++) { 53632529Sbostic vflaw->flaw[i].offset = vendor[i].offset; 53732529Sbostic vflaw->flaw[i].length = vendor[i].length; 53832529Sbostic } 53932529Sbostic break; 54032529Sbostic } 54132529Sbostic } 542*32560Sbostic return(0); 54332529Sbostic } 54432529Sbostic 54532529Sbostic /************************************************************************* 54632529Sbostic * Procedure: hdmcb 54732529Sbostic * 548*32560Sbostic * Description: Internal routine used to send mcb's to the hdc. 54932529Sbostic * 550*32560Sbostic * Returns: 0 normal 551*32560Sbostic * non-zero error occurred 55232529Sbostic **************************************************************************/ 55332529Sbostic hdmcb(mcb, io) 554*32560Sbostic register mcb_type *mcb; /* mcb to send to the hdc */ 555*32560Sbostic register struct iob *io; /* i/o block */ 55632529Sbostic { 557*32560Sbostic master_mcb_type *master_mcb; /* the hdc's master mcb */ 558*32560Sbostic hdctlr_type *hc; /* hdc ctlr information table */ 559*32560Sbostic hdc_regs_type *ctlr_addr; /* pointer to hdc i/o registers */ 560*32560Sbostic int timeout; /* used to timeout the mcb */ 561*32560Sbostic int bus; /* bus number */ 562*32560Sbostic int ctlr; /* the controller number */ 563*32560Sbostic int i, end; 564*32560Sbostic u_int *ptr; 56532529Sbostic 566*32560Sbostic bus = 0; /* io->i_bus; */ 567*32560Sbostic ctlr = HDCTLR(io->i_unit); /* io->i_ctlr; */ 56832529Sbostic hc = &hdc_ctlr[ctlr][bus]; 56932529Sbostic 57032529Sbostic mcb->interrupt = FALSE; 57132529Sbostic mcb->priority = 0; 57232529Sbostic mcb->forw_phaddr = 0; 57332529Sbostic mcb->context = 0; 57432529Sbostic mcb->reserved[0] = 0; 57532529Sbostic mcb->reserved[1] = 0; 57632529Sbostic master_mcb = &hc->master_mcb; 577*32560Sbostic master_mcb->forw_phaddr = (long)&mcb->forw_phaddr; 57832529Sbostic master_mcb->mcs = 0; 57932529Sbostic master_mcb->interrupt = 0; 580*32560Sbostic master_mcb->reserve1 = 0; 581*32560Sbostic master_mcb->reserve2 = 0; 582*32560Sbostic master_mcb->context = 0; 58332529Sbostic master_mcb->mcl = MCL_IMMEDIATE; 584*32560Sbostic for (i = 0; i < HDC_XSTAT_SIZE; i++) 585*32560Sbostic master_mcb->xstatus[i] = 0; 586*32560Sbostic ctlr_addr = hc->registers; 587*32560Sbostic HDREG(master_mcb_reg) = (u_long)master_mcb; 58832529Sbostic timeout = 15000; 589*32560Sbostic for (;;) { 59032529Sbostic DELAY(1000); 59132557Sbostic mtpr(PADC, 0); 592*32560Sbostic if (master_mcb->mcs & MCS_DONE && 593*32560Sbostic !(master_mcb->mcs & MCS_FATALERROR)) 594*32560Sbostic return(0); 59532529Sbostic timeout--; 596*32560Sbostic if (timeout > 0 && !(master_mcb->mcs & MCS_FATALERROR)) 597*32560Sbostic continue; 598*32560Sbostic if (master_mcb->mcs & MCS_FATALERROR) 59932529Sbostic printf("hdc: controller fatal error\n"); 60032529Sbostic else 60132529Sbostic printf("hdc: controller timed out\n"); 60232529Sbostic 60332529Sbostic printf("mmcb: "); 604*32560Sbostic ptr = (u_int *)master_mcb; 605*32560Sbostic for (i = 0; i < 8; i++) 606*32560Sbostic printf(" %x", ptr[i]); 607*32560Sbostic for (i = 7 + HDC_XSTAT_SIZE; i > 7; i--) { 60832529Sbostic end = i; 609*32560Sbostic if (ptr[i] != 0) 610*32560Sbostic break; 61132529Sbostic } 612*32560Sbostic for (i = 8; i <= end; i++) 613*32560Sbostic printf(" %x", ptr[i]); 61432529Sbostic printf("\n"); 61532529Sbostic 61632529Sbostic printf("mcb: "); 617*32560Sbostic ptr = (u_int *)&mcb->forw_phaddr; 618*32560Sbostic for (i = 0; i < 6; i++) 619*32560Sbostic printf(" %x", ptr[i]); 620*32560Sbostic for (i = 6; i < 72; i += 2) { 62132529Sbostic printf(" %x %x", ptr[i], ptr[i+1]); 622*32560Sbostic if (!(ptr[i] & 0x80000000)) 623*32560Sbostic break; 62432529Sbostic } 62532529Sbostic printf("\n"); 62632529Sbostic return(1); 62732529Sbostic } 62832529Sbostic } 629