132529Sbostic /* 232529Sbostic * Stand alone driver for the HDC controller 3*32557Sbostic * 4*32557Sbostic * @(#)hd.c 7.2 (Berkeley) 10/27/87 532529Sbostic */ 6*32557Sbostic #define KERNEL 732529Sbostic 8*32557Sbostic #include "machine/mtpr.h" 9*32557Sbostic #include "param.h" 10*32557Sbostic #include "systm.h" 11*32557Sbostic #include "buf.h" 12*32557Sbostic #include "time.h" 13*32557Sbostic #include "inode.h" 14*32557Sbostic #include "fs.h" 15*32557Sbostic #include "ioctl.h" 16*32557Sbostic #include "tahoevba/dsk.h" 17*32557Sbostic #include "tahoevba/dskio.h" 18*32557Sbostic #include "tahoevba/hdc.h" 19*32557Sbostic #include "saio.h" 2032529Sbostic 21*32557Sbostic #define NHD 4 22*32557Sbostic #define NDRIVE 8 /* drives per controller */ 23*32557Sbostic #define HDSLAVE(x) ((x) % NDRIVE) 24*32557Sbostic #define HDCTLR(x) ((x) / NDRIVE) 2532529Sbostic 26*32557Sbostic #define HDREG(x) (ctlr_addr->x) /* standalone io to an hdc register */ 27*32557Sbostic #define HID_HDC 0x01 /* hvme_id for HDC */ 2832529Sbostic 2932529Sbostic /* 3032529Sbostic * hdc controller table. It contains information about the hdc controller. 3132529Sbostic */ 3232529Sbostic 3332529Sbostic typedef struct { 3432529Sbostic int ctlr; /* controller number (0-15) */ 3532529Sbostic hdc_regs_type *registers; /* base address of hdc io registers */ 3632529Sbostic hdc_mid_type mid; /* the module id is read to here */ 3732529Sbostic master_mcb_type master_mcb; /* the master mcb for this hdc */ 3832529Sbostic mcb_type mcb; /* an mcb for i/o to the controller */ 3932529Sbostic } hdctlr_type; 4032529Sbostic 4132529Sbostic hdctlr_type hdc_ctlr[HDC_MAXCTLR][HDC_MAXBUS]; 4232529Sbostic 4332529Sbostic /* 4432529Sbostic * hdc unit table. It contains information about the hdc drive. 4532529Sbostic * Some information is obtained from the profile prom and geometry block. 4632529Sbostic */ 4732529Sbostic 4832529Sbostic typedef struct { 4932529Sbostic par_tab partition[GB_MAXPART]; /* partition definitions */ 5032529Sbostic int ctlr; /* the controller number (0-15) */ 5132529Sbostic int slave; /* the slave number (0-4) */ 5232529Sbostic int unit; /* the unit number (0-31) */ 5332529Sbostic int id; /* identifies the disk model */ 5432529Sbostic int cylinders; /* number of logical cylinders */ 5532529Sbostic int heads; /* number of logical heads */ 5632529Sbostic int sectors; /* number of logical sectors/track */ 5732529Sbostic int phys_cylinders; /* number of physical cylinders */ 5832529Sbostic int phys_heads; /* number of physical heads */ 5932529Sbostic int phys_sectors; /* number of physical sectors/track */ 6032529Sbostic int def_cyl; /* logical cylinder of drive def */ 6132529Sbostic int def_cyl_count; /* number of logical def cylinders */ 6232529Sbostic int diag_cyl; /* logical cylinder of diag area */ 6332529Sbostic int diag_cyl_count; /* number of logical diag cylinders */ 6432529Sbostic int rpm; /* disk rpm */ 6532529Sbostic int bytes_per_sec; /* bytes/sector -vendorflaw conversn*/ 6632529Sbostic int format; /* format program is active */ 6732529Sbostic unsigned long phio_data[HDC_PHIO_SIZE]; /* data for physical io */ 6832529Sbostic } hdunit_type; 6932529Sbostic 7032529Sbostic hdunit_type hdc_unit [HDC_MAXDRIVE] [HDC_MAXCTLR] [HDC_MAXBUS] ; 7132529Sbostic 7232529Sbostic /************************************************************************* 7332529Sbostic * Procedure: hdopen 7432529Sbostic * 7532529Sbostic * Description: The hdc open routine. Initializes the hdc and reads the 7632529Sbostic * hdc status and the geometry block. 7732529Sbostic * 7832529Sbostic * Returns: 0 open was not successful 7932529Sbostic * 1 open was successful 8032529Sbostic * -1 this is not an hdc controller 8132529Sbostic **************************************************************************/ 8232529Sbostic 8332529Sbostic hdopen(io) 8432529Sbostic 8532529Sbostic register struct iob *io ; /* i/o block 8632529Sbostic */ 8732529Sbostic { 8832529Sbostic mcb_type *mcb; /* an mcb to send commands to hdc */ 8932529Sbostic hdunit_type *hu; /* disk unit information table */ 9032529Sbostic hdctlr_type *hc; /* hdc ctlr information table */ 9132529Sbostic hdc_mid_type *id; /* the hdc module id */ 9232529Sbostic geometry_sector geometry; /* the geometry block sector */ 9332529Sbostic geometry_block *geo; /* the geometry block */ 9432529Sbostic drive_stat_type status; /* the hdc status is read to here */ 9532529Sbostic int par; /* partition number */ 9632529Sbostic int ctlr; /* the controller number */ 9732529Sbostic int drive; /* the drive number */ 9832529Sbostic int bus; /* the bus number */ 9932529Sbostic int unit; /* the unit number */ 10032529Sbostic int i; /* temp */ 101*32557Sbostic long junk; /* badaddr will write junk here */ 10232529Sbostic hdc_regs_type *ctlr_addr; /* hdc i/o registers */ 10332529Sbostic 104*32557Sbostic par = io->i_boff; /* io->i_part; */ 105*32557Sbostic bus = 0; /* io->i_bus; */ 106*32557Sbostic ctlr = HDCTLR(io->i_unit); /* io->i_ctlr; */ 107*32557Sbostic drive = HDSLAVE(io->i_unit); /* io->i_drive; */ 10832529Sbostic hu = &hdc_unit[drive][ctlr][bus]; 10932529Sbostic hc = &hdc_ctlr[ctlr][bus]; 11032529Sbostic mcb = &hc->mcb; 11132529Sbostic 11232529Sbostic /* 11332529Sbostic * Validate the device specification 11432529Sbostic */ 11532529Sbostic 116*32557Sbostic if (ctlr >= HDC_MAXCTLR) { 117*32557Sbostic printf("invalid controller number\n"); 118*32557Sbostic return (ENXIO); 119*32557Sbostic } 12032529Sbostic if (drive < 0 || drive > (HDC_MAXDRIVE-1)) { 12132529Sbostic printf("hdc: bad drive number.\n"); 122*32557Sbostic return( 1 ); 12332529Sbostic } 12432529Sbostic if (par < 0 || par > 7) { 12532529Sbostic printf("hdc: bad partition number.\n"); 126*32557Sbostic return( 1 ); 12732529Sbostic } 128*32557Sbostic ctlr_addr = (hdc_regs_type *)(bus == 0 ? 12932529Sbostic 0xC0000000 | ctlr << 24 | HDC_MID << 16 : 130*32557Sbostic 0x80000000 | ctlr << 24 | HDC_MID << 16); 131*32557Sbostic /* ctlr_addr = (hdc_regs_type *) io->i_ctlr_addr; */ 13232529Sbostic 13332529Sbostic /* 13432529Sbostic * Init drive structure. 13532529Sbostic */ 13632529Sbostic 13732529Sbostic hu->slave = drive; 13832529Sbostic hc->registers = ctlr_addr; 13932529Sbostic 14032529Sbostic /* 14132529Sbostic * Insure that this is an hdc, then reset the hdc. 14232529Sbostic */ 143*32557Sbostic junk = 0; 144*32557Sbostic if (wbadaddr(&ctlr_addr->module_id_reg, 4, &junk)) { 145*32557Sbostic printf("hd%d: %x: invalid csr\n", ctlr, ctlr_addr); 146*32557Sbostic return (ENXIO); 147*32557Sbostic } 14832529Sbostic HDREG(soft_reset_reg) = 0; 14932529Sbostic DELAY(1000000); 15032529Sbostic 15132529Sbostic /* 15232529Sbostic * Read in the hdc module id word. 15332529Sbostic * The controller is bad if the hdc's writeable control 15432529Sbostic * store is not loaded or if the hdc failed the 15532529Sbostic * functional integrity test for any reason. 15632529Sbostic */ 15732529Sbostic 15832529Sbostic id = &hc->mid; 15932529Sbostic HDREG(module_id_reg) = (unsigned long) id; 16032529Sbostic DELAY(10000); 161*32557Sbostic mtpr(PADC, 0); 16232529Sbostic if (id->module_id != (unsigned char) HDC_MID) { 16332529Sbostic printf("hdc: Controller bad module id: id= %x\n",id->module_id); 16432529Sbostic return( -1 ); 16532529Sbostic } 16632529Sbostic if (id->code_rev == (unsigned char) 0xFF ) { 16732529Sbostic printf("hdc: Controller micro-code is not loaded.\n"); 168*32557Sbostic return( 1 ); 16932529Sbostic } 17032529Sbostic if (id->fit != (unsigned char) 0xFF ) { 17132529Sbostic printf("hdc: Controller FIT test failed: error= %x\n",id->fit); 172*32557Sbostic return( 1 ); 17332529Sbostic } 17432529Sbostic 17532529Sbostic /* 17632529Sbostic * Read the drive status. Save important info. 17732529Sbostic */ 17832529Sbostic 17932529Sbostic mcb->command = HCMD_STATUS; 18032529Sbostic mcb->drive = drive; 18132529Sbostic mcb->cyl = 0; 18232529Sbostic mcb->head = 0; 18332529Sbostic mcb->sector = 0; 18432529Sbostic mcb->chain[0].lwc = (long) sizeof(drive_stat_type) / 4; 18532529Sbostic mcb->chain[0].ta = (long) &status; 18632529Sbostic if (hdmcb(mcb, io)) 187*32557Sbostic return( 1 ); 18832529Sbostic hu->cylinders = status.max_cyl+1; 18932529Sbostic hu->heads = status.max_head+1; 19032529Sbostic hu->sectors = status.max_sector+1; 19132529Sbostic hu->def_cyl = status.def_cyl; 19232529Sbostic hu->def_cyl_count = status.def_cyl_count; 19332529Sbostic hu->diag_cyl = status.diag_cyl; 19432529Sbostic hu->diag_cyl_count = status.diag_cyl_count; 19532529Sbostic hu->phys_cylinders = status.max_phys_cyl+1; 19632529Sbostic hu->phys_heads = status.max_phys_head+1; 19732529Sbostic hu->phys_sectors = status.max_phys_sector+1; 19832529Sbostic hu->bytes_per_sec = status.bytes_per_sec; 19932529Sbostic hu->id = status.id; 20032529Sbostic hu->rpm = status.rpm; 20132529Sbostic hu->partition[HDC_DEFPART].start= 20232529Sbostic hu->def_cyl * hu->sectors * hu->heads / HDC_SPB; 20332529Sbostic hu->partition[HDC_DEFPART].length = 20432529Sbostic hu->def_cyl_count * hu->sectors * hu->heads / HDC_SPB; 20532529Sbostic io->i_boff = hu->partition[HDC_DEFPART].start; /* default */ 20632529Sbostic 20732529Sbostic /* 20832529Sbostic * Report drive down if anything in the drive status is bad. 20932529Sbostic * If fault condition, reading geo will try to clear the fault. 21032529Sbostic */ 21132529Sbostic 21232529Sbostic if (status.drs & DRS_FAULT) 21332529Sbostic printf("hdc: clearing drive fault.\n"); 21432529Sbostic if ( !(status.drs & DRS_ONLINE)) { 21532529Sbostic printf("hdc: drive is not online.\n"); 216*32557Sbostic return( 1 ); 21732529Sbostic } 21832529Sbostic 21932529Sbostic /* 22032529Sbostic * Read the geometry block (at head=0 sector=0 of the drive 22132529Sbostic * definition cylinder), validate it (must have the correct 22232529Sbostic * version number, header, and checksum). 22332529Sbostic */ 22432529Sbostic 22532529Sbostic geo = &geometry.geometry_block; 22632529Sbostic mcb->command = HCMD_READ; 22732529Sbostic mcb->drive = drive; 22832529Sbostic mcb->cyl = status.def_cyl; 22932529Sbostic mcb->head = 0; 23032529Sbostic mcb->sector = 0; 23132529Sbostic mcb->chain[0].lwc = sizeof(geometry_sector) / 4; 23232529Sbostic mcb->chain[0].ta = (long) &geometry; 23332529Sbostic if (hdmcb(mcb, io)) { 23432529Sbostic printf("hdc: could not read geometry block\n"); 23532529Sbostic return( 1 ); 23632529Sbostic } 23732529Sbostic io->i_boff = 0; 23832529Sbostic if ( geo->version > 64000 || geo->version < 0 ) { 23932529Sbostic printf("hdc: bad geometry block version#\n"); 24032529Sbostic return( 1 ); 24132529Sbostic } 24232529Sbostic if (strcmp(&geo->id[0],GB_ID) != 0) { 24332529Sbostic printf("hdc: bad geometry block header\n"); 24432529Sbostic return( 1 ); 24532529Sbostic } 24632529Sbostic GB_CHECKSUM( geo, i ); 24732529Sbostic if (geometry.checksum != i) { 24832529Sbostic printf("hdc: bad geometry block checksum\n"); 24932529Sbostic return( 1 ); 25032529Sbostic } 25132529Sbostic 25232529Sbostic /* 25332529Sbostic * Set the partition start/size info. 25432529Sbostic * Note: this info was already defaulted to be the disk 25532529Sbostic * definition partition. 25632529Sbostic */ 25732529Sbostic 25832529Sbostic if (par != HDC_DEFPART) { 259*32557Sbostic if (geo->partition[par].length == 0) { 26032529Sbostic printf("hdc: null partition\n"); 261*32557Sbostic return ( 1 ); 262*32557Sbostic } 26332529Sbostic else { 26432529Sbostic hu->partition[par].start = geo->partition[par].start; 26532529Sbostic hu->partition[par].length = geo->partition[par].length; 26632529Sbostic io->i_boff = hu->partition[par].start; 26732529Sbostic } 26832529Sbostic } 269*32557Sbostic return( 0 ) ; 27032529Sbostic } 27132529Sbostic 27232529Sbostic /************************************************************************* 27332529Sbostic * Procedure: hdstrategy 27432529Sbostic * 27532529Sbostic * Description: The hdc strategy routine. This routine does the disk 27632529Sbostic * reads/writes. If this is the format program, read/writes 27732529Sbostic * are forced to be within the disk definition partition. 27832529Sbostic * 27932529Sbostic * Returns: The number of bytes transfered. 28032529Sbostic **************************************************************************/ 28132529Sbostic 28232529Sbostic hdstrategy(io,func) 28332529Sbostic 28432529Sbostic register struct iob *io ; /* i/o block 28532529Sbostic */ 28632529Sbostic long func ; /* i/o operation to perform 28732529Sbostic */ 28832529Sbostic { 28932529Sbostic mcb_type *mcb; /* mcb to send to the hdc */ 29032529Sbostic hdunit_type *hu; /* disk unit information table */ 29132529Sbostic hdctlr_type *hc; /* hdc ctlr information table */ 29232529Sbostic long err; /* error code */ 29332529Sbostic long sector; /* sector number for i/o */ 29432529Sbostic int partstart; /* block number of partition start */ 29532529Sbostic int partlen; /* number of blocks in partition */ 29632529Sbostic int bytes; /* number of bytes to transfer */ 29732529Sbostic int bus; /* bus number */ 29832529Sbostic int ctlr; /* the controller number */ 29932529Sbostic int drive; /* the drive number */ 30032529Sbostic 301*32557Sbostic bus = 0; /* io->i_bus; */ 302*32557Sbostic ctlr = HDCTLR(io->i_unit); /* io->i_ctlr; */ 303*32557Sbostic drive = HDSLAVE(io->i_unit); /* io->i_drive; */ 30432529Sbostic hu = &hdc_unit[drive][ctlr][bus]; 30532529Sbostic hc = &hdc_ctlr[ctlr][bus]; 30632529Sbostic 30732529Sbostic /* 30832529Sbostic * Only the format program can access the disk definition tracks. 30932529Sbostic */ 31032529Sbostic 311*32557Sbostic if (io->i_boff == HDC_DEFPART) 31232529Sbostic if (!hu->format) { 31332529Sbostic printf("hdc: partition 7 is protected\n"); 31432529Sbostic return 0; 31532529Sbostic }; 31632529Sbostic 31732529Sbostic /* 31832529Sbostic * Insure the transfer fits in the partition. 31932529Sbostic * Set and validate transfer size. 32032529Sbostic */ 32132529Sbostic 322*32557Sbostic partstart = hu->partition[io->i_boff].start ; 323*32557Sbostic partlen = hu->partition[io->i_boff].length ; 32432529Sbostic if ( (io->i_bn < partstart) || (io->i_bn >= partstart+partlen) ) 32532529Sbostic return( 0 ) ; 326*32557Sbostic bytes = MIN( io->i_cc, DEV_BSIZE*(partstart+partlen-io->i_bn) ); 32732529Sbostic if (io->i_cc & 3) { 32832529Sbostic printf("hdc: i/o not a longword multiple\n"); 32932529Sbostic return 0; 33032529Sbostic } 33132529Sbostic 33232529Sbostic /* 33332529Sbostic * Set up the mcb and send it to the hdc. 33432529Sbostic */ 33532529Sbostic 33632529Sbostic mcb = &hc->mcb; 33732529Sbostic sector = io->i_bn * HDC_SPB; 33832529Sbostic mcb->command = (func == READ) ? HCMD_READ : HCMD_WRITE; 33932529Sbostic mcb->drive = hu->slave; 34032529Sbostic mcb->cyl = sector / (hu->sectors * hu->heads); 34132529Sbostic mcb->head = (sector/hu->sectors) % hu->heads; 34232529Sbostic mcb->sector = sector % hu->sectors; 34332529Sbostic mcb->chain[0].ta = (unsigned long) io->i_ma; 34432529Sbostic mcb->chain[0].lwc = (bytes + 3) / 4; 34532529Sbostic err = hdmcb(mcb, io); 34632529Sbostic io->i_error = err; 34732529Sbostic return (err ? 0 : bytes ); 34832529Sbostic } 34932529Sbostic 35032529Sbostic /************************************************************************* 35132529Sbostic * Procedure: hdioctl 35232529Sbostic * 35332529Sbostic * Description: ioctl routine. 35432529Sbostic * 35532529Sbostic * Returns: 0 no errors 35632529Sbostic * non-0 error 35732529Sbostic **************************************************************************/ 35832529Sbostic 35932529Sbostic int 36032529Sbostic hdioctl(io, command, arg) 36132529Sbostic 36232529Sbostic struct iob *io ; /* i/o block. 36332529Sbostic */ 36432529Sbostic int command ; /* The ioctl commmand. 36532529Sbostic */ 36632529Sbostic int arg ; /* Data. Format depends on ioctl. 36732529Sbostic */ 36832529Sbostic { 36932529Sbostic mcb_type *mcb; 37032529Sbostic hdunit_type *hu; /* disk unit information table */ 37132529Sbostic hdctlr_type *hc; /* hdc ctlr information table */ 37232529Sbostic register int i; 37332529Sbostic int bus; /* bus number */ 37432529Sbostic int ctlr; /* the controller number */ 37532529Sbostic int drive; /* the drive number */ 37632529Sbostic 377*32557Sbostic bus = 0; /* io->i_bus; */ 378*32557Sbostic ctlr = HDCTLR(io->i_unit); /* io->i_ctlr; */ 379*32557Sbostic drive = HDSLAVE(io->i_unit); /* io->i_drive; */ 38032529Sbostic hu = &hdc_unit[drive][ctlr][bus]; 38132529Sbostic hc = &hdc_ctlr[ctlr][bus]; 38232529Sbostic 38332529Sbostic switch (command) { 38432529Sbostic 38532529Sbostic case DSKIOCFORMAT: { 38632529Sbostic 38732529Sbostic /* 38832529Sbostic * Format a disk track. The received argument is a pointer 38932529Sbostic * to a "formatop" structure describing the track to format. 39032529Sbostic * 39132529Sbostic * Set up a buffer with each longword corresponding to a 39232529Sbostic * sector on the track; a 1 means no flaw, a 0 means a flaw. 39332529Sbostic * Send an mcb to the hdc to format the track. 39432529Sbostic */ 39532529Sbostic 39632529Sbostic register struct formatop *track; 39732529Sbostic 39832529Sbostic if (!hu->format) 39932529Sbostic return(1); 40032529Sbostic track = (struct formatop *) arg; 40132529Sbostic mcb = &hc->mcb; 40232529Sbostic for (i=0; i<hu->phys_sectors; i++) 40332529Sbostic hu->phio_data[i] = 1; 40432529Sbostic for (i=0; i<track->flaw_count; i++) 40532529Sbostic hu->phio_data[track->flaw[i]]=0; 40632529Sbostic mcb->command = HCMD_FORMAT; 40732529Sbostic mcb->drive = hu->slave; 40832529Sbostic mcb->chain[0].ta = (unsigned long) hu->phio_data; 40932529Sbostic mcb->chain[0].lwc = hu->phys_sectors; 41032529Sbostic mcb->cyl = track->cylinder; 41132529Sbostic mcb->head = track->head; 41232529Sbostic mcb->sector = 0; 41332529Sbostic if (hdmcb(mcb, io)) 41432529Sbostic return EIO; 41532529Sbostic break; 41632529Sbostic } 41732529Sbostic 41832529Sbostic case DSKIOCCERTIFY: { 41932529Sbostic 42032529Sbostic /* 42132529Sbostic * Certify a disk track. The received argument is a pointer 42232529Sbostic * to a "formatop" structure describing the track to certify. 42332529Sbostic * 42432529Sbostic * Send an mcb to the hdc to certify the track. 42532529Sbostic * The controller returns data in which each longword 42632529Sbostic * corresponds to a sector on the track; a 1 means no flaw, 42732529Sbostic * a 0 means a flaw. 42832529Sbostic */ 42932529Sbostic 43032529Sbostic register struct formatop *track; 43132529Sbostic 43232529Sbostic if (!hu->format) 43332529Sbostic return 1; 43432529Sbostic track = (struct formatop *) arg; 43532529Sbostic mcb = &hc->mcb; 43632529Sbostic mcb->command = HCMD_CERTIFY; 43732529Sbostic mcb->drive = hu->slave; 43832529Sbostic mcb->chain[0].ta = (unsigned long) hu->phio_data; 43932529Sbostic mcb->chain[0].lwc = hu->phys_sectors; 44032529Sbostic mcb->cyl = track->cylinder; 44132529Sbostic mcb->head = track->head; 44232529Sbostic mcb->sector = 0; 44332529Sbostic if (hdmcb(mcb, io)) 44432529Sbostic return EIO; 44532529Sbostic track->flaw_count = 0; 44632529Sbostic for (i=0; i<hu->phys_sectors; i++) { 44732529Sbostic if (track->flaw_count >= MAXVFLAW) break; 44832529Sbostic if (hu->phio_data[i]==0) { 44932529Sbostic track->flaw[track->flaw_count] = i; 45032529Sbostic track->flaw_count++; 45132529Sbostic } 45232529Sbostic } 45332529Sbostic break; 45432529Sbostic } 45532529Sbostic 45632529Sbostic case DSKIOCVERIFY: { 45732529Sbostic 45832529Sbostic /* 45932529Sbostic * Verify a disk track. The received argument is a pointer 46032529Sbostic * to a "formatop" structure describing the track to verify. 46132529Sbostic */ 46232529Sbostic 46332529Sbostic register struct formatop *track; 46432529Sbostic 46532529Sbostic if (!hu->format) 46632529Sbostic return(1); 46732529Sbostic track = (struct formatop *) arg; 46832529Sbostic mcb = &hc->mcb; 46932529Sbostic mcb->command = HCMD_VERIFY; 47032529Sbostic mcb->drive = hu->slave; 47132529Sbostic mcb->chain[0].ta = 0; 47232529Sbostic mcb->chain[0].lwc = 0; 47332529Sbostic mcb->cyl = track->cylinder; 47432529Sbostic mcb->head = track->head; 47532529Sbostic mcb->sector = 0; 47632529Sbostic if (hdmcb(mcb, io)) 47732529Sbostic return EIO; 47832529Sbostic break; 47932529Sbostic } 48032529Sbostic 48132529Sbostic case DSKIOCFORMATCTL: { 48232529Sbostic 48332529Sbostic /* 48432529Sbostic * This ioctl provides special format control. 48532529Sbostic * Currently the valid arguments are: 48632529Sbostic * 48732529Sbostic * arg= 0 disable formatting; 48832529Sbostic * 48932529Sbostic * arg= 1 enable formatting (allow privileged access); 49032529Sbostic * formatting must not already be enabled; 49132529Sbostic * For formatting, change to use partition 7. 49232529Sbostic */ 49332529Sbostic 49432529Sbostic if (arg<0 || arg>1) 49532529Sbostic return (1); 49632529Sbostic if (arg==1) { 49732529Sbostic if (hu->format) return (1); 49832529Sbostic /* If not already formatting.... */ 49932529Sbostic hu->format = 1 ; 500*32557Sbostic /* io->i_part = HDC_DEFPART; */ 50132529Sbostic io->i_boff = hu->partition[HDC_DEFPART].start; 50232529Sbostic } 50332529Sbostic else 50432529Sbostic hu->format = 0 ; 50532529Sbostic break; 50632529Sbostic } 50732529Sbostic 50832529Sbostic case DSKIOCSTATUS: { 50932529Sbostic 51032529Sbostic /* 51132529Sbostic * Return info about the disk. Caller's parameter is a 51232529Sbostic * pointer to a dsk_status structure. 51332529Sbostic */ 51432529Sbostic 51532529Sbostic register dsk_status *status; 51632529Sbostic 51732529Sbostic status = (dsk_status *) arg; 51832529Sbostic status->id = hu->id; 51932529Sbostic status->drive_status = 0; 52032529Sbostic status->rpm = hu->rpm; 52132529Sbostic status->bytes_per_sec = hu->bytes_per_sec; 52232529Sbostic status->cylinders = hu->cylinders; 52332529Sbostic status->heads = hu->heads; 52432529Sbostic status->sectors = hu->sectors; 52532529Sbostic status->phys_cylinders= hu->phys_cylinders; 52632529Sbostic status->phys_heads = hu->phys_heads; 52732529Sbostic status->phys_sectors = hu->phys_sectors; 52832529Sbostic status->diag_cyl = hu->diag_cyl; 52932529Sbostic status->diag_cylinders= hu->diag_cyl_count; 53032529Sbostic status->def_cyl = hu->def_cyl; 53132529Sbostic status->def_cylinders = hu->def_cyl_count; 53232529Sbostic break; 53332529Sbostic } 53432529Sbostic 53532529Sbostic case DSKIOCVENDORFLAW: { 53632529Sbostic 53732529Sbostic /* 53832529Sbostic * Return vendor flaw info. 53932529Sbostic * 54032529Sbostic * Read in the vendor data (data for each track is at 54132529Sbostic * relative sector 0 of the track); then copy the 54232529Sbostic * vendor flaw data to the caller's buffer. 54332529Sbostic */ 54432529Sbostic 54532529Sbostic register vflaw_type *vflaw; 54632529Sbostic register struct flaw *vendor; 54732529Sbostic 54832529Sbostic if (!hu->format) 54932529Sbostic return(1); 55032529Sbostic vflaw = (vflaw_type *) arg; 55132529Sbostic mcb = &hc->mcb; 55232529Sbostic mcb->command = HCMD_VENDOR; 55332529Sbostic mcb->drive = hu->slave; 55432529Sbostic mcb->chain[0].lwc = HDC_VDATA_SIZE; 55532529Sbostic mcb->chain[0].ta = (unsigned long) hu->phio_data; 55632529Sbostic mcb->cyl = vflaw->cylinder; 55732529Sbostic mcb->head = vflaw->head; 55832529Sbostic mcb->sector = 0; 55932529Sbostic if (hdmcb(mcb, io)) 56032529Sbostic return EIO; 56132529Sbostic vendor = (struct flaw *) &hu->phio_data[0]; 56232529Sbostic for (i=0; i<MAXVFLAW; i++) { 56332529Sbostic vflaw->flaw[i].offset = vendor[i].offset; 56432529Sbostic vflaw->flaw[i].length = vendor[i].length; 56532529Sbostic } 56632529Sbostic break; 56732529Sbostic } 56832529Sbostic } 56932529Sbostic return 0; 57032529Sbostic } 57132529Sbostic 57232529Sbostic /************************************************************************* 57332529Sbostic * Procedure: hdmcb 57432529Sbostic * 57532529Sbostic * Description: Internal routine used to send mcb's to the hdc. 57632529Sbostic * 57732529Sbostic * Returns: 0 normal 57832529Sbostic * non-zero error occurred 57932529Sbostic **************************************************************************/ 58032529Sbostic 58132529Sbostic int 58232529Sbostic hdmcb(mcb, io) 58332529Sbostic 58432529Sbostic register mcb_type *mcb ; /* mcb to send to the hdc */ 58532529Sbostic register struct iob *io ; /* i/o block */ 58632529Sbostic 58732529Sbostic { 58832529Sbostic master_mcb_type *master_mcb; /* the hdc's master mcb */ 58932529Sbostic hdctlr_type *hc; /* hdc ctlr information table */ 59032529Sbostic hdc_regs_type *ctlr_addr; /* pointer to hdc i/o registers */ 59132529Sbostic int timeout; /* used to timeout the mcb */ 59232529Sbostic int bus; /* bus number */ 59332529Sbostic int ctlr; /* the controller number */ 59432529Sbostic int i,end; 59532529Sbostic unsigned int *ptr; 59632529Sbostic 597*32557Sbostic bus = 0; /* io->i_bus; */ 598*32557Sbostic ctlr = HDCTLR(io->i_unit); /* io->i_ctlr; */ 59932529Sbostic hc = &hdc_ctlr[ctlr][bus]; 60032529Sbostic 60132529Sbostic mcb->interrupt = FALSE; 60232529Sbostic mcb->priority = 0; 60332529Sbostic mcb->forw_phaddr = 0; 60432529Sbostic mcb->context = 0; 60532529Sbostic mcb->reserved[0] = 0; 60632529Sbostic mcb->reserved[1] = 0; 60732529Sbostic master_mcb = &hc->master_mcb; 60832529Sbostic master_mcb->forw_phaddr = (long) &mcb->forw_phaddr; 60932529Sbostic master_mcb->mcs = 0; 61032529Sbostic master_mcb->interrupt = 0; 61132529Sbostic master_mcb->reserve1 = 0; 61232529Sbostic master_mcb->reserve2 = 0; 61332529Sbostic master_mcb->context = 0; 61432529Sbostic master_mcb->mcl = MCL_IMMEDIATE; 61532529Sbostic for (i=0;i<HDC_XSTAT_SIZE;i++) master_mcb->xstatus[i] = 0; 61632529Sbostic ctlr_addr = hc->registers; 61732529Sbostic HDREG(master_mcb_reg) = (unsigned long) master_mcb; 61832529Sbostic timeout = 15000; 61932529Sbostic while (TRUE) { 62032529Sbostic DELAY(1000); 621*32557Sbostic mtpr(PADC, 0); 62232529Sbostic if ( (master_mcb->mcs & MCS_DONE) && 62332529Sbostic !(master_mcb->mcs & MCS_FATALERROR) ) return 0; 62432529Sbostic timeout--; 62532529Sbostic if ( timeout > 0 && 62632529Sbostic !(master_mcb->mcs & MCS_FATALERROR) ) continue; 62732529Sbostic if ( master_mcb->mcs & MCS_FATALERROR ) 62832529Sbostic printf("hdc: controller fatal error\n"); 62932529Sbostic else 63032529Sbostic printf("hdc: controller timed out\n"); 63132529Sbostic 63232529Sbostic printf("mmcb: "); 63332529Sbostic ptr = (unsigned int *) master_mcb; 63432529Sbostic for (i=0;i<8;i++) 63532529Sbostic printf(" %x",ptr[i]); 63632529Sbostic for (i=7+HDC_XSTAT_SIZE; i>7; i--) { 63732529Sbostic end = i; 63832529Sbostic if (ptr[i] != 0) break; 63932529Sbostic } 64032529Sbostic for (i=8;i<=end;i++) 64132529Sbostic printf(" %x",ptr[i]); 64232529Sbostic printf("\n"); 64332529Sbostic 64432529Sbostic printf("mcb: "); 64532529Sbostic ptr = (unsigned int *) &mcb->forw_phaddr; 64632529Sbostic for (i=0; i<6; i++) 64732529Sbostic printf(" %x",ptr[i]); 64832529Sbostic for (i=6; i<72; i+=2) { 64932529Sbostic printf(" %x %x", ptr[i], ptr[i+1]); 65032529Sbostic if ( !(ptr[i] & 0x80000000)) break; 65132529Sbostic } 65232529Sbostic printf("\n"); 65332529Sbostic return(1); 65432529Sbostic } 65532529Sbostic } 656