1*32529Sbostic /* 2*32529Sbostic * Stand alone driver for the HDC controller 3*32529Sbostic */ 4*32529Sbostic 5*32529Sbostic #define KERNEL 6*32529Sbostic 7*32529Sbostic #include "../uts/machine/ml/mtpr.h" 8*32529Sbostic #include "../uts/machine/sys/param.h" 9*32529Sbostic #include "../uts/machine/sys/systm.h" 10*32529Sbostic #include "../uts/machine/sys/buf.h" 11*32529Sbostic #include "../uts/machine/sys/time.h" 12*32529Sbostic #include "../uts/machine/sys/vnode.h" 13*32529Sbostic #include "../uts/machine/ufs/inode.h" 14*32529Sbostic #include "../uts/machine/ufs/fs.h" 15*32529Sbostic #include "../uts/machine/sys/vbavar.h" 16*32529Sbostic #include "../uts/machine/sys/ioctl.h" 17*32529Sbostic #include "../uts/machine/sys/dsk.h" 18*32529Sbostic #include "../uts/machine/sys/dskio.h" 19*32529Sbostic #include "../uts/machine/sys/hdc.h" 20*32529Sbostic #include "../stand/saio.h" 21*32529Sbostic 22*32529Sbostic #define HDREG(x) (ctlr_addr->x) /* standalone io to an hdc register */ 23*32529Sbostic 24*32529Sbostic /* 25*32529Sbostic * hdc controller table. It contains information about the hdc controller. 26*32529Sbostic */ 27*32529Sbostic 28*32529Sbostic typedef struct { 29*32529Sbostic int ctlr; /* controller number (0-15) */ 30*32529Sbostic hdc_regs_type *registers; /* base address of hdc io registers */ 31*32529Sbostic hdc_mid_type mid; /* the module id is read to here */ 32*32529Sbostic master_mcb_type master_mcb; /* the master mcb for this hdc */ 33*32529Sbostic mcb_type mcb; /* an mcb for i/o to the controller */ 34*32529Sbostic } hdctlr_type; 35*32529Sbostic 36*32529Sbostic hdctlr_type hdc_ctlr[HDC_MAXCTLR][HDC_MAXBUS]; 37*32529Sbostic 38*32529Sbostic /* 39*32529Sbostic * hdc unit table. It contains information about the hdc drive. 40*32529Sbostic * Some information is obtained from the profile prom and geometry block. 41*32529Sbostic */ 42*32529Sbostic 43*32529Sbostic typedef struct { 44*32529Sbostic par_tab partition[GB_MAXPART]; /* partition definitions */ 45*32529Sbostic int ctlr; /* the controller number (0-15) */ 46*32529Sbostic int slave; /* the slave number (0-4) */ 47*32529Sbostic int unit; /* the unit number (0-31) */ 48*32529Sbostic int id; /* identifies the disk model */ 49*32529Sbostic int cylinders; /* number of logical cylinders */ 50*32529Sbostic int heads; /* number of logical heads */ 51*32529Sbostic int sectors; /* number of logical sectors/track */ 52*32529Sbostic int phys_cylinders; /* number of physical cylinders */ 53*32529Sbostic int phys_heads; /* number of physical heads */ 54*32529Sbostic int phys_sectors; /* number of physical sectors/track */ 55*32529Sbostic int def_cyl; /* logical cylinder of drive def */ 56*32529Sbostic int def_cyl_count; /* number of logical def cylinders */ 57*32529Sbostic int diag_cyl; /* logical cylinder of diag area */ 58*32529Sbostic int diag_cyl_count; /* number of logical diag cylinders */ 59*32529Sbostic int rpm; /* disk rpm */ 60*32529Sbostic int bytes_per_sec; /* bytes/sector -vendorflaw conversn*/ 61*32529Sbostic int format; /* format program is active */ 62*32529Sbostic unsigned long phio_data[HDC_PHIO_SIZE]; /* data for physical io */ 63*32529Sbostic } hdunit_type; 64*32529Sbostic 65*32529Sbostic hdunit_type hdc_unit [HDC_MAXDRIVE] [HDC_MAXCTLR] [HDC_MAXBUS] ; 66*32529Sbostic 67*32529Sbostic /************************************************************************* 68*32529Sbostic * Procedure: hdopen 69*32529Sbostic * 70*32529Sbostic * Description: The hdc open routine. Initializes the hdc and reads the 71*32529Sbostic * hdc status and the geometry block. 72*32529Sbostic * 73*32529Sbostic * Returns: 0 open was not successful 74*32529Sbostic * 1 open was successful 75*32529Sbostic * -1 this is not an hdc controller 76*32529Sbostic **************************************************************************/ 77*32529Sbostic 78*32529Sbostic hdopen(io) 79*32529Sbostic 80*32529Sbostic register struct iob *io ; /* i/o block 81*32529Sbostic */ 82*32529Sbostic { 83*32529Sbostic mcb_type *mcb; /* an mcb to send commands to hdc */ 84*32529Sbostic hdunit_type *hu; /* disk unit information table */ 85*32529Sbostic hdctlr_type *hc; /* hdc ctlr information table */ 86*32529Sbostic hdc_mid_type *id; /* the hdc module id */ 87*32529Sbostic geometry_sector geometry; /* the geometry block sector */ 88*32529Sbostic geometry_block *geo; /* the geometry block */ 89*32529Sbostic drive_stat_type status; /* the hdc status is read to here */ 90*32529Sbostic int par; /* partition number */ 91*32529Sbostic int ctlr; /* the controller number */ 92*32529Sbostic int drive; /* the drive number */ 93*32529Sbostic int bus; /* the bus number */ 94*32529Sbostic int unit; /* the unit number */ 95*32529Sbostic int i; /* temp */ 96*32529Sbostic hdc_regs_type *ctlr_addr; /* hdc i/o registers */ 97*32529Sbostic int junk; /* badaddr will write junk here */ 98*32529Sbostic 99*32529Sbostic par = io->i_part; 100*32529Sbostic bus = io->i_bus; 101*32529Sbostic ctlr = io->i_ctlr; 102*32529Sbostic drive = io->i_drive; 103*32529Sbostic hu = &hdc_unit[drive][ctlr][bus]; 104*32529Sbostic hc = &hdc_ctlr[ctlr][bus]; 105*32529Sbostic mcb = &hc->mcb; 106*32529Sbostic 107*32529Sbostic /* 108*32529Sbostic * Validate the device specification 109*32529Sbostic */ 110*32529Sbostic 111*32529Sbostic if (ctlr < 1 || ctlr > HDC_MAXCTLR) 112*32529Sbostic return( -1 ); 113*32529Sbostic if (drive < 0 || drive > (HDC_MAXDRIVE-1)) { 114*32529Sbostic printf("hdc: bad drive number.\n"); 115*32529Sbostic return( 0 ); 116*32529Sbostic } 117*32529Sbostic if (par < 0 || par > 7) { 118*32529Sbostic printf("hdc: bad partition number.\n"); 119*32529Sbostic return( 0 ); 120*32529Sbostic } 121*32529Sbostic io->i_ctlr_addr = bus == 0 ? 122*32529Sbostic 0xC0000000 | ctlr << 24 | HDC_MID << 16 : 123*32529Sbostic 0x80000000 | ctlr << 24 | HDC_MID << 16; 124*32529Sbostic ctlr_addr = (hdc_regs_type *) io->i_ctlr_addr; 125*32529Sbostic 126*32529Sbostic /* 127*32529Sbostic * Init drive structure. 128*32529Sbostic */ 129*32529Sbostic 130*32529Sbostic hu->slave = drive; 131*32529Sbostic hc->registers = ctlr_addr; 132*32529Sbostic 133*32529Sbostic /* 134*32529Sbostic * Insure that this is an hdc, then reset the hdc. 135*32529Sbostic */ 136*32529Sbostic 137*32529Sbostic if (badaddr(&ctlr_addr->module_id_reg,4,&junk)) 138*32529Sbostic return( -1 ); 139*32529Sbostic HDREG(soft_reset_reg) = 0; 140*32529Sbostic DELAY(1000000); 141*32529Sbostic 142*32529Sbostic /* 143*32529Sbostic * Read in the hdc module id word. 144*32529Sbostic * The controller is bad if the hdc's writeable control 145*32529Sbostic * store is not loaded or if the hdc failed the 146*32529Sbostic * functional integrity test for any reason. 147*32529Sbostic */ 148*32529Sbostic 149*32529Sbostic id = &hc->mid; 150*32529Sbostic HDREG(module_id_reg) = (unsigned long) id; 151*32529Sbostic DELAY(10000); 152*32529Sbostic mtpr(0,PADC); 153*32529Sbostic if (id->module_id != (unsigned char) HDC_MID) { 154*32529Sbostic printf("hdc: Controller bad module id: id= %x\n",id->module_id); 155*32529Sbostic return( -1 ); 156*32529Sbostic } 157*32529Sbostic if (id->code_rev == (unsigned char) 0xFF ) { 158*32529Sbostic printf("hdc: Controller micro-code is not loaded.\n"); 159*32529Sbostic return( 0 ); 160*32529Sbostic } 161*32529Sbostic if (id->fit != (unsigned char) 0xFF ) { 162*32529Sbostic printf("hdc: Controller FIT test failed: error= %x\n",id->fit); 163*32529Sbostic return( 0 ); 164*32529Sbostic } 165*32529Sbostic 166*32529Sbostic /* 167*32529Sbostic * Read the drive status. Save important info. 168*32529Sbostic */ 169*32529Sbostic 170*32529Sbostic mcb->command = HCMD_STATUS; 171*32529Sbostic mcb->drive = drive; 172*32529Sbostic mcb->cyl = 0; 173*32529Sbostic mcb->head = 0; 174*32529Sbostic mcb->sector = 0; 175*32529Sbostic mcb->chain[0].lwc = (long) sizeof(drive_stat_type) / 4; 176*32529Sbostic mcb->chain[0].ta = (long) &status; 177*32529Sbostic if (hdmcb(mcb, io)) 178*32529Sbostic return( 0 ); 179*32529Sbostic hu->cylinders = status.max_cyl+1; 180*32529Sbostic hu->heads = status.max_head+1; 181*32529Sbostic hu->sectors = status.max_sector+1; 182*32529Sbostic hu->def_cyl = status.def_cyl; 183*32529Sbostic hu->def_cyl_count = status.def_cyl_count; 184*32529Sbostic hu->diag_cyl = status.diag_cyl; 185*32529Sbostic hu->diag_cyl_count = status.diag_cyl_count; 186*32529Sbostic hu->phys_cylinders = status.max_phys_cyl+1; 187*32529Sbostic hu->phys_heads = status.max_phys_head+1; 188*32529Sbostic hu->phys_sectors = status.max_phys_sector+1; 189*32529Sbostic hu->bytes_per_sec = status.bytes_per_sec; 190*32529Sbostic hu->id = status.id; 191*32529Sbostic hu->rpm = status.rpm; 192*32529Sbostic hu->partition[HDC_DEFPART].start= 193*32529Sbostic hu->def_cyl * hu->sectors * hu->heads / HDC_SPB; 194*32529Sbostic hu->partition[HDC_DEFPART].length = 195*32529Sbostic hu->def_cyl_count * hu->sectors * hu->heads / HDC_SPB; 196*32529Sbostic io->i_boff = hu->partition[HDC_DEFPART].start; /* default */ 197*32529Sbostic 198*32529Sbostic /* 199*32529Sbostic * Report drive down if anything in the drive status is bad. 200*32529Sbostic * If fault condition, reading geo will try to clear the fault. 201*32529Sbostic */ 202*32529Sbostic 203*32529Sbostic if (status.drs & DRS_FAULT) 204*32529Sbostic printf("hdc: clearing drive fault.\n"); 205*32529Sbostic if ( !(status.drs & DRS_ONLINE)) { 206*32529Sbostic printf("hdc: drive is not online.\n"); 207*32529Sbostic return( 0 ); 208*32529Sbostic } 209*32529Sbostic 210*32529Sbostic /* 211*32529Sbostic * Read the geometry block (at head=0 sector=0 of the drive 212*32529Sbostic * definition cylinder), validate it (must have the correct 213*32529Sbostic * version number, header, and checksum). 214*32529Sbostic */ 215*32529Sbostic 216*32529Sbostic geo = &geometry.geometry_block; 217*32529Sbostic mcb->command = HCMD_READ; 218*32529Sbostic mcb->drive = drive; 219*32529Sbostic mcb->cyl = status.def_cyl; 220*32529Sbostic mcb->head = 0; 221*32529Sbostic mcb->sector = 0; 222*32529Sbostic mcb->chain[0].lwc = sizeof(geometry_sector) / 4; 223*32529Sbostic mcb->chain[0].ta = (long) &geometry; 224*32529Sbostic if (hdmcb(mcb, io)) { 225*32529Sbostic printf("hdc: could not read geometry block\n"); 226*32529Sbostic return( 1 ); 227*32529Sbostic } 228*32529Sbostic io->i_boff = 0; 229*32529Sbostic if ( geo->version > 64000 || geo->version < 0 ) { 230*32529Sbostic printf("hdc: bad geometry block version#\n"); 231*32529Sbostic return( 1 ); 232*32529Sbostic } 233*32529Sbostic if (strcmp(&geo->id[0],GB_ID) != 0) { 234*32529Sbostic printf("hdc: bad geometry block header\n"); 235*32529Sbostic return( 1 ); 236*32529Sbostic } 237*32529Sbostic GB_CHECKSUM( geo, i ); 238*32529Sbostic if (geometry.checksum != i) { 239*32529Sbostic printf("hdc: bad geometry block checksum\n"); 240*32529Sbostic return( 1 ); 241*32529Sbostic } 242*32529Sbostic 243*32529Sbostic /* 244*32529Sbostic * Set the partition start/size info. 245*32529Sbostic * Note: this info was already defaulted to be the disk 246*32529Sbostic * definition partition. 247*32529Sbostic */ 248*32529Sbostic 249*32529Sbostic if (par != HDC_DEFPART) { 250*32529Sbostic if (geo->partition[par].length == 0) 251*32529Sbostic printf("hdc: null partition\n"); 252*32529Sbostic else { 253*32529Sbostic hu->partition[par].start = geo->partition[par].start; 254*32529Sbostic hu->partition[par].length = geo->partition[par].length; 255*32529Sbostic io->i_boff = hu->partition[par].start; 256*32529Sbostic } 257*32529Sbostic } 258*32529Sbostic return( 1 ) ; 259*32529Sbostic } 260*32529Sbostic 261*32529Sbostic /************************************************************************* 262*32529Sbostic * Procedure: hdstrategy 263*32529Sbostic * 264*32529Sbostic * Description: The hdc strategy routine. This routine does the disk 265*32529Sbostic * reads/writes. If this is the format program, read/writes 266*32529Sbostic * are forced to be within the disk definition partition. 267*32529Sbostic * 268*32529Sbostic * Returns: The number of bytes transfered. 269*32529Sbostic **************************************************************************/ 270*32529Sbostic 271*32529Sbostic hdstrategy(io,func) 272*32529Sbostic 273*32529Sbostic register struct iob *io ; /* i/o block 274*32529Sbostic */ 275*32529Sbostic long func ; /* i/o operation to perform 276*32529Sbostic */ 277*32529Sbostic { 278*32529Sbostic mcb_type *mcb; /* mcb to send to the hdc */ 279*32529Sbostic hdunit_type *hu; /* disk unit information table */ 280*32529Sbostic hdctlr_type *hc; /* hdc ctlr information table */ 281*32529Sbostic long err; /* error code */ 282*32529Sbostic long sector; /* sector number for i/o */ 283*32529Sbostic int partstart; /* block number of partition start */ 284*32529Sbostic int partlen; /* number of blocks in partition */ 285*32529Sbostic int bytes; /* number of bytes to transfer */ 286*32529Sbostic int bus; /* bus number */ 287*32529Sbostic int ctlr; /* the controller number */ 288*32529Sbostic int drive; /* the drive number */ 289*32529Sbostic 290*32529Sbostic bus = io->i_bus; 291*32529Sbostic ctlr = io->i_ctlr; 292*32529Sbostic drive = io->i_drive; 293*32529Sbostic hu = &hdc_unit[drive][ctlr][bus]; 294*32529Sbostic hc = &hdc_ctlr[ctlr][bus]; 295*32529Sbostic 296*32529Sbostic /* 297*32529Sbostic * Only the format program can access the disk definition tracks. 298*32529Sbostic */ 299*32529Sbostic 300*32529Sbostic if (io->i_part == HDC_DEFPART) 301*32529Sbostic if (!hu->format) { 302*32529Sbostic printf("hdc: partition 7 is protected\n"); 303*32529Sbostic return 0; 304*32529Sbostic }; 305*32529Sbostic 306*32529Sbostic /* 307*32529Sbostic * Insure the transfer fits in the partition. 308*32529Sbostic * Set and validate transfer size. 309*32529Sbostic */ 310*32529Sbostic 311*32529Sbostic partstart = hu->partition[io->i_part].start ; 312*32529Sbostic partlen = hu->partition[io->i_part].length ; 313*32529Sbostic if ( (io->i_bn < partstart) || (io->i_bn >= partstart+partlen) ) 314*32529Sbostic return( 0 ) ; 315*32529Sbostic bytes = min( io->i_cc, DEV_BSIZE*(partstart+partlen-io->i_bn) ); 316*32529Sbostic if (io->i_cc & 3) { 317*32529Sbostic printf("hdc: i/o not a longword multiple\n"); 318*32529Sbostic return 0; 319*32529Sbostic } 320*32529Sbostic 321*32529Sbostic /* 322*32529Sbostic * Set up the mcb and send it to the hdc. 323*32529Sbostic */ 324*32529Sbostic 325*32529Sbostic mcb = &hc->mcb; 326*32529Sbostic sector = io->i_bn * HDC_SPB; 327*32529Sbostic mcb->command = (func == READ) ? HCMD_READ : HCMD_WRITE; 328*32529Sbostic mcb->drive = hu->slave; 329*32529Sbostic mcb->cyl = sector / (hu->sectors * hu->heads); 330*32529Sbostic mcb->head = (sector/hu->sectors) % hu->heads; 331*32529Sbostic mcb->sector = sector % hu->sectors; 332*32529Sbostic mcb->chain[0].ta = (unsigned long) io->i_ma; 333*32529Sbostic mcb->chain[0].lwc = (bytes + 3) / 4; 334*32529Sbostic err = hdmcb(mcb, io); 335*32529Sbostic io->i_error = err; 336*32529Sbostic return (err ? 0 : bytes ); 337*32529Sbostic } 338*32529Sbostic 339*32529Sbostic /************************************************************************* 340*32529Sbostic * Procedure: hdioctl 341*32529Sbostic * 342*32529Sbostic * Description: ioctl routine. 343*32529Sbostic * 344*32529Sbostic * Returns: 0 no errors 345*32529Sbostic * non-0 error 346*32529Sbostic **************************************************************************/ 347*32529Sbostic 348*32529Sbostic int 349*32529Sbostic hdioctl(io, command, arg) 350*32529Sbostic 351*32529Sbostic struct iob *io ; /* i/o block. 352*32529Sbostic */ 353*32529Sbostic int command ; /* The ioctl commmand. 354*32529Sbostic */ 355*32529Sbostic int arg ; /* Data. Format depends on ioctl. 356*32529Sbostic */ 357*32529Sbostic { 358*32529Sbostic mcb_type *mcb; 359*32529Sbostic hdunit_type *hu; /* disk unit information table */ 360*32529Sbostic hdctlr_type *hc; /* hdc ctlr information table */ 361*32529Sbostic register int i; 362*32529Sbostic int bus; /* bus number */ 363*32529Sbostic int ctlr; /* the controller number */ 364*32529Sbostic int drive; /* the drive number */ 365*32529Sbostic 366*32529Sbostic bus = io->i_bus; 367*32529Sbostic ctlr = io->i_ctlr; 368*32529Sbostic drive = io->i_drive; 369*32529Sbostic hu = &hdc_unit[drive][ctlr][bus]; 370*32529Sbostic hc = &hdc_ctlr[ctlr][bus]; 371*32529Sbostic 372*32529Sbostic switch (command) { 373*32529Sbostic 374*32529Sbostic case DSKIOCFORMAT: { 375*32529Sbostic 376*32529Sbostic /* 377*32529Sbostic * Format a disk track. The received argument is a pointer 378*32529Sbostic * to a "formatop" structure describing the track to format. 379*32529Sbostic * 380*32529Sbostic * Set up a buffer with each longword corresponding to a 381*32529Sbostic * sector on the track; a 1 means no flaw, a 0 means a flaw. 382*32529Sbostic * Send an mcb to the hdc to format the track. 383*32529Sbostic */ 384*32529Sbostic 385*32529Sbostic register struct formatop *track; 386*32529Sbostic 387*32529Sbostic if (!hu->format) 388*32529Sbostic return(1); 389*32529Sbostic track = (struct formatop *) arg; 390*32529Sbostic mcb = &hc->mcb; 391*32529Sbostic for (i=0; i<hu->phys_sectors; i++) 392*32529Sbostic hu->phio_data[i] = 1; 393*32529Sbostic for (i=0; i<track->flaw_count; i++) 394*32529Sbostic hu->phio_data[track->flaw[i]]=0; 395*32529Sbostic mcb->command = HCMD_FORMAT; 396*32529Sbostic mcb->drive = hu->slave; 397*32529Sbostic mcb->chain[0].ta = (unsigned long) hu->phio_data; 398*32529Sbostic mcb->chain[0].lwc = hu->phys_sectors; 399*32529Sbostic mcb->cyl = track->cylinder; 400*32529Sbostic mcb->head = track->head; 401*32529Sbostic mcb->sector = 0; 402*32529Sbostic if (hdmcb(mcb, io)) 403*32529Sbostic return EIO; 404*32529Sbostic break; 405*32529Sbostic } 406*32529Sbostic 407*32529Sbostic case DSKIOCCERTIFY: { 408*32529Sbostic 409*32529Sbostic /* 410*32529Sbostic * Certify a disk track. The received argument is a pointer 411*32529Sbostic * to a "formatop" structure describing the track to certify. 412*32529Sbostic * 413*32529Sbostic * Send an mcb to the hdc to certify the track. 414*32529Sbostic * The controller returns data in which each longword 415*32529Sbostic * corresponds to a sector on the track; a 1 means no flaw, 416*32529Sbostic * a 0 means a flaw. 417*32529Sbostic */ 418*32529Sbostic 419*32529Sbostic register struct formatop *track; 420*32529Sbostic 421*32529Sbostic if (!hu->format) 422*32529Sbostic return 1; 423*32529Sbostic track = (struct formatop *) arg; 424*32529Sbostic mcb = &hc->mcb; 425*32529Sbostic mcb->command = HCMD_CERTIFY; 426*32529Sbostic mcb->drive = hu->slave; 427*32529Sbostic mcb->chain[0].ta = (unsigned long) hu->phio_data; 428*32529Sbostic mcb->chain[0].lwc = hu->phys_sectors; 429*32529Sbostic mcb->cyl = track->cylinder; 430*32529Sbostic mcb->head = track->head; 431*32529Sbostic mcb->sector = 0; 432*32529Sbostic if (hdmcb(mcb, io)) 433*32529Sbostic return EIO; 434*32529Sbostic track->flaw_count = 0; 435*32529Sbostic for (i=0; i<hu->phys_sectors; i++) { 436*32529Sbostic if (track->flaw_count >= MAXVFLAW) break; 437*32529Sbostic if (hu->phio_data[i]==0) { 438*32529Sbostic track->flaw[track->flaw_count] = i; 439*32529Sbostic track->flaw_count++; 440*32529Sbostic } 441*32529Sbostic } 442*32529Sbostic break; 443*32529Sbostic } 444*32529Sbostic 445*32529Sbostic case DSKIOCVERIFY: { 446*32529Sbostic 447*32529Sbostic /* 448*32529Sbostic * Verify a disk track. The received argument is a pointer 449*32529Sbostic * to a "formatop" structure describing the track to verify. 450*32529Sbostic */ 451*32529Sbostic 452*32529Sbostic register struct formatop *track; 453*32529Sbostic 454*32529Sbostic if (!hu->format) 455*32529Sbostic return(1); 456*32529Sbostic track = (struct formatop *) arg; 457*32529Sbostic mcb = &hc->mcb; 458*32529Sbostic mcb->command = HCMD_VERIFY; 459*32529Sbostic mcb->drive = hu->slave; 460*32529Sbostic mcb->chain[0].ta = 0; 461*32529Sbostic mcb->chain[0].lwc = 0; 462*32529Sbostic mcb->cyl = track->cylinder; 463*32529Sbostic mcb->head = track->head; 464*32529Sbostic mcb->sector = 0; 465*32529Sbostic if (hdmcb(mcb, io)) 466*32529Sbostic return EIO; 467*32529Sbostic break; 468*32529Sbostic } 469*32529Sbostic 470*32529Sbostic case DSKIOCFORMATCTL: { 471*32529Sbostic 472*32529Sbostic /* 473*32529Sbostic * This ioctl provides special format control. 474*32529Sbostic * Currently the valid arguments are: 475*32529Sbostic * 476*32529Sbostic * arg= 0 disable formatting; 477*32529Sbostic * 478*32529Sbostic * arg= 1 enable formatting (allow privileged access); 479*32529Sbostic * formatting must not already be enabled; 480*32529Sbostic * For formatting, change to use partition 7. 481*32529Sbostic */ 482*32529Sbostic 483*32529Sbostic if (arg<0 || arg>1) 484*32529Sbostic return (1); 485*32529Sbostic if (arg==1) { 486*32529Sbostic if (hu->format) return (1); 487*32529Sbostic /* If not already formatting.... */ 488*32529Sbostic hu->format = 1 ; 489*32529Sbostic io->i_part = HDC_DEFPART; 490*32529Sbostic io->i_boff = hu->partition[HDC_DEFPART].start; 491*32529Sbostic } 492*32529Sbostic else 493*32529Sbostic hu->format = 0 ; 494*32529Sbostic break; 495*32529Sbostic } 496*32529Sbostic 497*32529Sbostic case DSKIOCSTATUS: { 498*32529Sbostic 499*32529Sbostic /* 500*32529Sbostic * Return info about the disk. Caller's parameter is a 501*32529Sbostic * pointer to a dsk_status structure. 502*32529Sbostic */ 503*32529Sbostic 504*32529Sbostic register dsk_status *status; 505*32529Sbostic 506*32529Sbostic status = (dsk_status *) arg; 507*32529Sbostic status->id = hu->id; 508*32529Sbostic status->drive_status = 0; 509*32529Sbostic status->rpm = hu->rpm; 510*32529Sbostic status->bytes_per_sec = hu->bytes_per_sec; 511*32529Sbostic status->cylinders = hu->cylinders; 512*32529Sbostic status->heads = hu->heads; 513*32529Sbostic status->sectors = hu->sectors; 514*32529Sbostic status->phys_cylinders= hu->phys_cylinders; 515*32529Sbostic status->phys_heads = hu->phys_heads; 516*32529Sbostic status->phys_sectors = hu->phys_sectors; 517*32529Sbostic status->diag_cyl = hu->diag_cyl; 518*32529Sbostic status->diag_cylinders= hu->diag_cyl_count; 519*32529Sbostic status->def_cyl = hu->def_cyl; 520*32529Sbostic status->def_cylinders = hu->def_cyl_count; 521*32529Sbostic break; 522*32529Sbostic } 523*32529Sbostic 524*32529Sbostic case DSKIOCVENDORFLAW: { 525*32529Sbostic 526*32529Sbostic /* 527*32529Sbostic * Return vendor flaw info. 528*32529Sbostic * 529*32529Sbostic * Read in the vendor data (data for each track is at 530*32529Sbostic * relative sector 0 of the track); then copy the 531*32529Sbostic * vendor flaw data to the caller's buffer. 532*32529Sbostic */ 533*32529Sbostic 534*32529Sbostic register vflaw_type *vflaw; 535*32529Sbostic register struct flaw *vendor; 536*32529Sbostic 537*32529Sbostic if (!hu->format) 538*32529Sbostic return(1); 539*32529Sbostic vflaw = (vflaw_type *) arg; 540*32529Sbostic mcb = &hc->mcb; 541*32529Sbostic mcb->command = HCMD_VENDOR; 542*32529Sbostic mcb->drive = hu->slave; 543*32529Sbostic mcb->chain[0].lwc = HDC_VDATA_SIZE; 544*32529Sbostic mcb->chain[0].ta = (unsigned long) hu->phio_data; 545*32529Sbostic mcb->cyl = vflaw->cylinder; 546*32529Sbostic mcb->head = vflaw->head; 547*32529Sbostic mcb->sector = 0; 548*32529Sbostic if (hdmcb(mcb, io)) 549*32529Sbostic return EIO; 550*32529Sbostic vendor = (struct flaw *) &hu->phio_data[0]; 551*32529Sbostic for (i=0; i<MAXVFLAW; i++) { 552*32529Sbostic vflaw->flaw[i].offset = vendor[i].offset; 553*32529Sbostic vflaw->flaw[i].length = vendor[i].length; 554*32529Sbostic } 555*32529Sbostic break; 556*32529Sbostic } 557*32529Sbostic } 558*32529Sbostic return 0; 559*32529Sbostic } 560*32529Sbostic 561*32529Sbostic /************************************************************************* 562*32529Sbostic * Procedure: hdmcb 563*32529Sbostic * 564*32529Sbostic * Description: Internal routine used to send mcb's to the hdc. 565*32529Sbostic * 566*32529Sbostic * Returns: 0 normal 567*32529Sbostic * non-zero error occurred 568*32529Sbostic **************************************************************************/ 569*32529Sbostic 570*32529Sbostic int 571*32529Sbostic hdmcb(mcb, io) 572*32529Sbostic 573*32529Sbostic register mcb_type *mcb ; /* mcb to send to the hdc */ 574*32529Sbostic register struct iob *io ; /* i/o block */ 575*32529Sbostic 576*32529Sbostic { 577*32529Sbostic master_mcb_type *master_mcb; /* the hdc's master mcb */ 578*32529Sbostic hdctlr_type *hc; /* hdc ctlr information table */ 579*32529Sbostic hdc_regs_type *ctlr_addr; /* pointer to hdc i/o registers */ 580*32529Sbostic int timeout; /* used to timeout the mcb */ 581*32529Sbostic int bus; /* bus number */ 582*32529Sbostic int ctlr; /* the controller number */ 583*32529Sbostic int i,end; 584*32529Sbostic unsigned int *ptr; 585*32529Sbostic 586*32529Sbostic bus = io->i_bus; 587*32529Sbostic ctlr = io->i_ctlr; 588*32529Sbostic hc = &hdc_ctlr[ctlr][bus]; 589*32529Sbostic 590*32529Sbostic mcb->interrupt = FALSE; 591*32529Sbostic mcb->priority = 0; 592*32529Sbostic mcb->forw_phaddr = 0; 593*32529Sbostic mcb->context = 0; 594*32529Sbostic mcb->reserved[0] = 0; 595*32529Sbostic mcb->reserved[1] = 0; 596*32529Sbostic master_mcb = &hc->master_mcb; 597*32529Sbostic master_mcb->forw_phaddr = (long) &mcb->forw_phaddr; 598*32529Sbostic master_mcb->mcs = 0; 599*32529Sbostic master_mcb->interrupt = 0; 600*32529Sbostic master_mcb->reserve1 = 0; 601*32529Sbostic master_mcb->reserve2 = 0; 602*32529Sbostic master_mcb->context = 0; 603*32529Sbostic master_mcb->mcl = MCL_IMMEDIATE; 604*32529Sbostic for (i=0;i<HDC_XSTAT_SIZE;i++) master_mcb->xstatus[i] = 0; 605*32529Sbostic ctlr_addr = hc->registers; 606*32529Sbostic HDREG(master_mcb_reg) = (unsigned long) master_mcb; 607*32529Sbostic timeout = 15000; 608*32529Sbostic while (TRUE) { 609*32529Sbostic DELAY(1000); 610*32529Sbostic mtpr(0,PADC); 611*32529Sbostic if ( (master_mcb->mcs & MCS_DONE) && 612*32529Sbostic !(master_mcb->mcs & MCS_FATALERROR) ) return 0; 613*32529Sbostic timeout--; 614*32529Sbostic if ( timeout > 0 && 615*32529Sbostic !(master_mcb->mcs & MCS_FATALERROR) ) continue; 616*32529Sbostic if ( master_mcb->mcs & MCS_FATALERROR ) 617*32529Sbostic printf("hdc: controller fatal error\n"); 618*32529Sbostic else 619*32529Sbostic printf("hdc: controller timed out\n"); 620*32529Sbostic 621*32529Sbostic printf("mmcb: "); 622*32529Sbostic ptr = (unsigned int *) master_mcb; 623*32529Sbostic for (i=0;i<8;i++) 624*32529Sbostic printf(" %x",ptr[i]); 625*32529Sbostic for (i=7+HDC_XSTAT_SIZE; i>7; i--) { 626*32529Sbostic end = i; 627*32529Sbostic if (ptr[i] != 0) break; 628*32529Sbostic } 629*32529Sbostic for (i=8;i<=end;i++) 630*32529Sbostic printf(" %x",ptr[i]); 631*32529Sbostic printf("\n"); 632*32529Sbostic 633*32529Sbostic printf("mcb: "); 634*32529Sbostic ptr = (unsigned int *) &mcb->forw_phaddr; 635*32529Sbostic for (i=0; i<6; i++) 636*32529Sbostic printf(" %x",ptr[i]); 637*32529Sbostic for (i=6; i<72; i+=2) { 638*32529Sbostic printf(" %x %x", ptr[i], ptr[i+1]); 639*32529Sbostic if ( !(ptr[i] & 0x80000000)) break; 640*32529Sbostic } 641*32529Sbostic printf("\n"); 642*32529Sbostic return(1); 643*32529Sbostic } 644*32529Sbostic } 645