void buggotest( int n, unsigned int pattern, boolean_t verbose) { struct io_req io; register int i, rec; if (n <= 0) n = 1; if(pattern) for (i = 0; i < buggo_write_size/4; i++) buggo_out_buffer[i] = i + pattern; for (i = 0; i < n; i++) { register int j; buggo_out_buffer[0] = i + pattern; buggo_out_buffer[(buggo_write_size/4)-1] = i + pattern; bzero(&io, sizeof(io)); io.io_unit = buggo_dev; io.io_data = (char*)buggo_out_buffer; io.io_op = IO_WRITE; io.io_count = buggo_write_size; io.io_recnum = i % 1024; scdisk_strategy(&io); bzero(buggo_in_buffer, sizeof(buggo_in_buffer)); iowait(&io); if (verbose) printf("Done write with %x", io.io_error); bzero(&io, sizeof(io)); io.io_unit = buggo_dev; io.io_data = (char*)buggo_in_buffer; io.io_op = IO_READ; io.io_count = buggo_write_size; io.io_recnum = i % 1024; scdisk_strategy(&io); iowait(&io); if (verbose) printf("Done read with %x", io.io_error); for (j = 0; j < buggo_write_size/4; j++) if (buggo_out_buffer[j] != buggo_in_buffer[j]){ printf("Difference at %d-th word: %x %x\n", buggo_out_buffer[j], buggo_in_buffer[j]); return i; } } printf("Test ok\n"); return n; }
/* Write back a label to the disk */ scsi_ret_t scdisk_writelabel( target_info_t *tgt) { io_req_t ior; char *data; struct disklabel *label; io_return_t error; io_req_alloc(ior); #ifdef MACH_KERNEL data = (char *) kalloc(tgt->block_size); #else /*MACH_KERNEL*/ data = (char *)ior->io_data; #endif /*MACH_KERNEL*/ ior->io_next = 0; ior->io_prev = 0; ior->io_data = data; ior->io_count = tgt->block_size; ior->io_op = IO_READ; ior->io_error = 0; if (grab_it(tgt, ior) != D_SUCCESS) { error = D_ALREADY_OPEN; goto ret; } scdisk_read( tgt, LABELSECTOR, ior); iowait(ior); if (error = ior->io_error) goto ret; label = (struct disklabel *) &data[LABELOFFSET % tgt->block_size]; *label = tgt->dev_info.disk.l; ior->io_next = 0; ior->io_prev = 0; ior->io_data = data; ior->io_count = tgt->block_size; ior->io_op = IO_WRITE; ior->io_error = 0; tgt->ior = ior; /*?*/ while (grab_it(tgt, ior) != D_SUCCESS) ; /* ahem */ scdisk_write( tgt, LABELSECTOR, ior); iowait(ior); error = ior->io_error; ret: #ifdef MACH_KERNEL kfree((vm_offset_t) data, tgt->block_size); #endif io_req_free(ior); return error; }
breada(adev, blkno, rablkno) { register struct buf *rbp, *rabp; register int dev; dev = adev; rbp = 0; if (!incore(dev, blkno)) { rbp = getblk(dev, blkno); if ((rbp->b_flags&B_DONE) == 0) { rbp->b_flags =| B_READ; rbp->b_wcount = -256; (*bdevsw[adev.d_major].d_strategy)(rbp); } } if (rablkno && !incore(dev, rablkno) && raflag) { rabp = getblk(dev, rablkno); if (rabp->b_flags & B_DONE) brelse(rabp); else { rabp->b_flags =| B_READ|B_ASYNC; rabp->b_wcount = -256; (*bdevsw[adev.d_major].d_strategy)(rabp); } } if (rbp==0) return(bread(dev, blkno)); iowait(rbp); return(rbp); }
char scsi_read_defect( register target_info_t *tgt, register unsigned char mode, io_req_t ior) { scsi_cmd_long_read_t *cmd; register unsigned len; len = ior->io_count; if (len > 0xffff) len = 0xffff; cmd = (scsi_cmd_read_defect_t*) (tgt->cmd_ptr); cmd->scsi_cmd_code = SCSI_CMD_READ_DEFECT_DATA; cmd->scsi_cmd_lun_and_relbit = 0; cmd->scsi_cmd_lba1 = mode & 0x1f; cmd->scsi_cmd_lba2 = 0; cmd->scsi_cmd_lba3 = 0; cmd->scsi_cmd_lba4 = 0; cmd->scsi_cmd_xxx = 0; cmd->scsi_cmd_xfer_len_1 = (len) >> 8; cmd->scsi_cmd_xfer_len_2 = (len); cmd->scsi_cmd_ctrl_byte = 0; /* not linked */ /* ++ HACK Alert */ /* tgt->cur_cmd = SCSI_CMD_READ_DEFECT_DATA;*/ tgt->cur_cmd = SCSI_CMD_LONG_READ; /* -- HACK Alert */ scsi_go(tgt, sizeof(*cmd), len, FALSE); iowait(ior); return tgt->done; }
/* * Find and convert from a DEC label to BSD */ boolean_t rz_dec_label( target_info_t *tgt, struct disklabel *label, io_req_t ior) { /* here look for a DEC label */ register scsi_dec_label_t *part; char *data; int i, dev_bsize = tgt->block_size; ior->io_count = dev_bsize; ior->io_op = IO_READ; tgt->ior = ior; scdisk_read( tgt, DEC_LABEL_BYTE_OFFSET/dev_bsize, ior); iowait(ior); data = (char *)ior->io_data; part = (scsi_dec_label_t*)&data[DEC_LABEL_BYTE_OFFSET%dev_bsize]; if (part->magic == DEC_LABEL_MAGIC) { if (scsi_debug) printf("{Using DEC label}"); for (i = 0; i < 8; i++) { label->d_partitions[i].p_size = part->partitions[i].n_sectors; label->d_partitions[i].p_offset = part->partitions[i].offset; } return TRUE; } return FALSE; }
/** * @fn struct buf *breada(int dev, bc_daddr_t blkno, bc_daddr_t rablkno) * Lit le bloc demandé et lance une e/s sur le bloc suivant du device * * Read in the block, like bread, but also start I/O on the * read-ahead block (which is not allocated to the caller) * @param dev : device (major+minor) * @param blkno : numéro de bloc * @param rablkno : read-ahead bloc * @return le buffer associé au device dev et de numéro de bloc blkno */ struct buf *breada(int dev, bc_daddr_t blkno, bc_daddr_t rablkno) { struct buf *bp, *rabp; bp = NULL; if (!incore(dev, blkno)) { bp = getblk(dev, blkno); if ((bp->b_flags&B_DONE) == 0) { bp->b_flags |= B_READ; bp->b_count = BSIZE; (*bdevsw[major(dev)].d_strategy)(bp); } } if (rablkno && !incore(dev, rablkno)) { rabp = getblk(dev, rablkno); if (rabp->b_flags & B_DONE) brelse(rabp); else { rabp->b_flags |= B_READ|B_ASYNC; rabp->b_count = BSIZE; (*bdevsw[major(dev)].d_strategy)(rabp); } } if(bp == NULL) return(bread(dev, blkno)); iowait(bp); return(bp); }
bread(dev, blkno) { register struct buf *rbp; rbp = getblk(dev, blkno); if (rbp->b_flags&B_DONE) return(rbp); rbp->b_flags =| B_READ; rbp->b_wcount = -256; (*bdevsw[dev.d_major].d_strategy)(rbp); iowait(rbp); return(rbp); }
boolean_t rz_bios_bsd_label( target_info_t *tgt, struct disklabel *label, io_req_t ior, struct bios_partition_info *ospart) { struct disklabel *dlp; int dev_bsize = tgt->block_size; int i; extern int allow_bsd_label; ior->io_count = dev_bsize; ior->io_op = IO_READ; tgt->ior = ior; scdisk_read( tgt, (ospart->offset + LBLLOC) * 512 / dev_bsize, ior); iowait(ior); dlp = (struct disklabel *)ior->io_data; if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { if (OS == BSDOS) { printf("NO BSD LABEL!!\n"); } return FALSE; } printf("BSD LABEL "); LABEL_DEBUG(2,print_bsd_label(dlp, "dk:")); /* * here's where we dump label */ if (allow_bsd_label == 0) return FALSE; i = label->d_secperunit; *label = *dlp; label->d_secperunit = i; /* * The disklabel program should insure the invariant below * when it writes a label. But it does not seem to. */ label->d_partitions[MAXPARTITIONS].p_size = -1; label->d_partitions[MAXPARTITIONS].p_offset = 0; label->d_checksum = dkcksum(label); tgt->dev_info.disk.labeloffset = 0; tgt->dev_info.disk.labelsector = (ospart->offset + LBLLOC) * 512 / dev_bsize; LABEL_DEBUG(0x20,print_bsd_label(dlp, " ")); return TRUE; }
int scsi_read_fun(scsi_driver_info *param, int sectornum, void *buff) { char *psave; int result = TRUE; /* SUCCESS */ psave=param->ior->io_data; /* is this necessary ? */ param->ior->io_data=buff; param->ior->io_count = param->sectorsize; param->ior->io_op = IO_READ; param->ior->io_error = 0; param->tgt->ior = param->ior; (*param->readfun)( param->tgt, sectornum, param->ior); iowait(param->ior); param->ior->io_data=psave; /* restore the io_data pointer ?? */ return(result); }
/* * Find and convert from a Omron label to BSD */ boolean_t rz_omron_label( target_info_t *tgt, struct disklabel *label, io_req_t ior) { /* here look for an Omron label */ register scsi_omron_label_t *part; char *data; int i, dev_bsize = tgt->block_size; ior->io_count = dev_bsize; ior->io_op = IO_READ; tgt->ior = ior; scdisk_read( tgt, OMRON_LABEL_BYTE_OFFSET/dev_bsize, ior); iowait(ior); data = (char *)ior->io_data; part = (scsi_omron_label_t*)&data[OMRON_LABEL_BYTE_OFFSET%dev_bsize]; if (part->magic == OMRON_LABEL_MAGIC) { if (scsi_debug) printf("{Using OMRON label}"); for (i = 0; i < 8; i++) { label->d_partitions[i].p_size = part->partitions[i].n_sectors; label->d_partitions[i].p_offset = part->partitions[i].offset; } bcopy(part->packname, label->d_packname, 16); label->d_ncylinders = part->ncyl; label->d_acylinders = part->acyl; label->d_ntracks = part->nhead; label->d_nsectors = part->nsect; /* Many disks have this wrong, therefore.. */ #if 0 label->d_secperunit = part->maxblk; #else label->d_secperunit = label->d_ncylinders * label->d_ntracks * label->d_nsectors; #endif return TRUE; } return FALSE; }
void read_test() { static int buffer[(8192*2)/sizeof(int)]; struct io_req io; register int i, rec; bzero(&io, sizeof(io)); io.io_unit = test_read_bdev; io.io_op = IO_READ; io.io_count = test_read_size; io.io_data = (char*) buffer; for (rec = 0, i = 0; i < test_read_nreads; i++) { io.io_op = IO_READ; io.io_recnum = rec; scdisk_strategy(&io); rec += test_read_skew; iowait(&io); } }
hcommand(dev, com) { register struct buf *bp; bp = &chtbuf; VOID spl5(); while(bp->b_flags&B_BUSY) { bp->b_flags |= B_WANTED; sleep((caddr_t)bp, PRIBIO); } VOID spl0(); bp->b_dev = dev; bp->b_resid = com; bp->b_blkno = 0; bp->b_flags = B_BUSY|B_READ; htstrategy(bp); iowait(bp); if(bp->b_flags&B_WANTED) wakeup((caddr_t)bp); bp->b_flags = 0; return(bp->b_resid); }
/* * Devops write routine */ io_return_t datadev_write( dev_t dev, io_req_t ior) { void (*write)(void *, io_req_t); kern_return_t rc; void *arg; spl_t s; boolean_t wait; datadev_t ddp; rc = device_write_get(ior, &wait); if (rc != KERN_SUCCESS) return (rc); s = splsched(); mutex_lock(&datadev_lock); queue_iterate(&datadev_curr, ddp, datadev_t, dd_chain) if (ddp->dd_dev == dev) break; assert(ddp != (datadev_t)0); write = ddp->dd_write; arg = ddp->dd_arg; mutex_unlock(&datadev_lock); splx(s); (*write)(arg, ior); if (wait || (ior->io_op & IO_SYNC)) { iowait(ior); return (D_SUCCESS); } return (D_IO_QUEUED); }
/* * Devops read routine */ io_return_t datadev_read( dev_t dev, io_req_t ior) { kern_return_t rc; spl_t s; datadev_t ddp; rc = device_read_alloc(ior, (vm_size_t)ior->io_count); if (rc != KERN_SUCCESS) return (rc); s = splsched(); mutex_lock(&datadev_lock); queue_iterate(&datadev_curr, ddp, datadev_t, dd_chain) if (ddp->dd_dev == dev) break; if (!queue_end(&datadev_curr, (queue_entry_t)ddp) || datadev_ior != (io_req_t)0) { mutex_unlock(&datadev_lock); splx(s); return (D_INVALID_OPERATION); } datadev_ior = ior; mutex_unlock(&datadev_lock); splx(s); datadev_request((datadev_t)0); if ((ior->io_op & IO_SYNC) == 0) return (D_IO_QUEUED); iowait(ior); return (D_SUCCESS); }
void pic_remap(uint32_t offset1, uint32_t offset2) { uint8_t mask1, mask2; mask1 = inb(OL_PIC1_DATA); mask2 = inb(OL_PIC2_DATA); // sent the initialise commands to the master and slave pic outb(OL_PIC1_COMMAND, OL_ICW1_INIT|OL_ICW1_ICW4); outb(OL_PIC2_COMMAND, OL_ICW1_INIT|OL_ICW1_ICW4); iowait(); // define the vectors outb(OL_PIC1_DATA, offset1); outb(OL_PIC2_DATA, offset2); iowait(); // connect to the slave outb(OL_PIC1_DATA, OL_ICW3_MASTER); outb(OL_PIC2_DATA, OL_ICW3_SLAVE); iowait(); outb(OL_PIC1_DATA, OL_ICW4_8086); outb(OL_PIC2_DATA, OL_ICW4_8086); iowait(); outb(OL_PIC1_DATA, mask1); outb(OL_PIC2_DATA, mask2); iowait(); outb(0x21, 0x3c); outb(0xa1, 0x3f); #if 0 outb(OL_PIC2_DATA, 0xff); // disable irq's, not yet implemented. outb(OL_PIC2_COMMAND, 0xff); iowait(); #endif }
boolean_t rz_bios_label( target_info_t *tgt, struct disklabel *label, io_req_t ior) { /* here look for a BIOS label */ char *data; int i, dev_bsize = tgt->block_size; scsi_bios_label_t part; ior->io_count = dev_bsize; ior->io_op = IO_READ; tgt->ior = ior; scdisk_read( tgt, BIOS_LABEL_BYTE_OFFSET/dev_bsize, ior); iowait(ior); data = (char *)ior->io_data; /* * It's safer to just copy the data here and not worry about * scdisk_read's down the line will clobber the buffer. */ part = *(scsi_bios_label_t*)&data[BIOS_LABEL_BYTE_OFFSET%dev_bsize]; if (((scsi_bios_label_t*)&data[BIOS_LABEL_BYTE_OFFSET%dev_bsize])->magic == BIOS_LABEL_MAGIC) { struct bios_partition_info *bpart, *ospart = (struct bios_partition_info *)0; if (scsi_debug) printf("{Using BIOS label}"); for (i = 0; i < 4; i++) { bpart = &(((struct bios_partition_info *)part.partitions)[i]); LABEL_DEBUG(1,print_dos_partition(i, bpart)); label->d_partitions[i].p_size = bpart->n_sectors; label->d_partitions[i].p_offset = bpart->offset; if (bpart->systid == UNIXOS || bpart->systid == BSDOS) { if (ospart != 0) { if (bpart->bootid == BIOS_BOOTABLE) ospart = bpart; } else ospart = bpart; } } tgt->dev_info.disk.l.d_partitions[MAXPARTITIONS].p_offset= 0; tgt->dev_info.disk.l.d_partitions[MAXPARTITIONS].p_size = -1; if (ospart == 0) return FALSE; OS = ospart->systid; if (OS == UNIXOS) printf("sd%d: MACH OS ", tgt->target_id); if (OS == BSDOS) printf("sd%d: XXXBSD OS ", tgt->target_id); if (rz_bios_bsd_label(tgt, label, ior, ospart)) return TRUE; #ifdef AT386 /* this goes away real fast */ if (!grab_bob_label(tgt, label, ior, ((struct bios_partition_info *)part.partitions))) return FALSE; /* take default setup of "a" and "c" */ #else label->d_npartitions = 4; #endif label->d_bbsize = BIOS_BOOT0_SIZE; return TRUE; } return FALSE; }
/*ARGSUSED*/ scsi_ret_t scdisk_open( target_info_t *tgt, io_req_t req) { register int i; register scsi_ret_t ret = SCSI_RET_SUCCESS; unsigned int disk_size, secs_per_cyl, sector_size; unsigned int nsectors, ntracks, ncylinders; scsi_rcap_data_t *cap; struct disklabel *label = 0; io_req_t ior; void (*readfun)( target_info_t *tgt, unsigned int secno, io_req_t ior) = scdisk_read; char *data, *rdata = 0; boolean_t look_for_label; if (tgt->flags & TGT_ONLINE) return SCSI_RET_SUCCESS; tgt->lun = rzlun(req->io_unit); /* * Dummy ior for proper sync purposes */ io_req_alloc(ior); bzero((char *)ior, sizeof(*ior)); simple_lock_init(&(ior)->io_req_lock, ETAP_IO_REQ); #if 0 /* * Set the LBN to tgt->block_size with a MODE SELECT. * xxx do a MODE SENSE instead ? */ /* * Ugh. Can't use tgt->block_size here -- not set up * yet. Also can't use DEV_BSIZE. So...since MK6 * dispenses with this command entirely, let's do * so as well. */ for (i = 0; i < 5; i++) { ior->io_op = IO_INTERNAL; ior->io_error = 0; ret = scdisk_mode_select(tgt, tgt->block_size, ior,0,0,FALSE); if (ret == SCSI_RET_SUCCESS) break; if (ret == SCSI_RET_RETRY) { timeout((timeout_fcn_t)wakeup, tgt, 2*hz); await(tgt); } if (ret == SCSI_RET_DEVICE_DOWN) goto done; } if (ret != SCSI_RET_SUCCESS) { scsi_error( tgt, SCSI_ERR_MSEL, ret, 0); ret = D_INVALID_SIZE; goto done; } #endif #ifdef hp_pa if (tgt->flags & TGT_REMOVABLE_MEDIA) { scsi_mode_sense_page5_t *page5; unsigned char mode_save[0xff]; scsi_mode_select_param_t *parm; int length; if((ret = scsi_mode_sense(tgt, 0x05, 0xff, 0)) != SCSI_RET_SUCCESS) goto done; length = *tgt->cmd_ptr + 1; bcopy(tgt->cmd_ptr, mode_save, length); page5 = (scsi_mode_sense_page5_t *)(mode_save + 4 + mode_save[3]); #if 1 /* force sector size to 512 */ parm = (scsi_mode_select_param_t *)mode_save; parm->reserved1 = 0; parm->medium_type = 2; parm->device_spec &= ~0x90; parm->descs[0].density_code = 2; parm->descs[0].nblocks1 = 0; parm->descs[0].nblocks2 = 0; parm->descs[0].nblocks3 = 0; parm->descs[0].reclen1 = 0x2; parm->descs[0].reclen2 = 0; parm->descs[0].reclen3 = 0; page5->ps = 0; page5->page_code &= ~0x80; page5->sectors_per_track = page5->sectors_per_track * (page5->bytes_per_sector_msb << 8 | page5->bytes_per_sector_lsb) / 512; page5->bytes_per_sector_msb = 2; page5->bytes_per_sector_lsb = 0; length -= parm->desc_len; parm->desc_len = 0; bcopy((const char*)page5, mode_save+4, sizeof(*page5)); if((ret = scdisk_mode_select(tgt, 0, 0, mode_save, length, 0)) != SCSI_RET_SUCCESS) goto done; if((ret = scsi_mode_sense(tgt, 0x05, 0xff, 0)) != SCSI_RET_SUCCESS) goto done; length = *tgt->cmd_ptr + 1; bcopy(tgt->cmd_ptr, mode_save, length); #endif ntracks = page5->number_of_heads; nsectors = page5->sectors_per_track; sector_size = page5->bytes_per_sector_msb << 8 | page5->bytes_per_sector_lsb; ncylinders = page5->number_of_cylinders_msb << 8 | page5->number_of_cylinders_lsb; secs_per_cyl = nsectors * ntracks; look_for_label = FALSE; geom_done = TRUE; } #endif /* * Do a READ CAPACITY to get max size. Check LBN too. */ for (i = 0; i < 5; i++) { ior->io_op = IO_INTERNAL; ior->io_error = 0; ret = scsi_read_capacity(tgt, 0, ior); if (ret == SCSI_RET_SUCCESS) break; if (ret == SCSI_RET_RETRY) { timeout((timeout_fcn_t)wakeup, tgt, 2*hz); await(tgt); } if (ret == SCSI_RET_DEVICE_DOWN) goto done; } if (ret != SCSI_RET_SUCCESS) { scsi_error( tgt, SCSI_ERR_MSEL, ret, 0); ret = D_INVALID_SIZE; goto done; } cap = (scsi_rcap_data_t*) tgt->cmd_ptr; disk_size = (cap->lba1<<24) | (cap->lba2<<16) | (cap->lba3<< 8) | cap->lba4 + 1; if (scsi_debug) printf("rz%d holds %d blocks\n", tgt->unit_no, disk_size); tgt->block_size = (cap->blen1<<24) | (cap->blen2<<16) | (cap->blen3<<8 ) | cap->blen4; if (scsi_debug) { printf("rz%d block size is %d bytes/block\n", tgt->unit_no, tgt->block_size); } if (tgt->block_size > RZDISK_MAX_SECTOR || tgt->block_size <= 0) { ret = D_INVALID_SIZE; goto done; } rdata = (char *) kalloc(2*tgt->block_size); if (round_page(rdata) == round_page(rdata + tgt->block_size)) data = rdata; else data = (char *)round_page(rdata); #ifdef POWERMAC /* XXX TODO NMGS remove! must be cache aligned for now */ if ((unsigned long)data & 0x1f) data = (char*)((unsigned long)(data + 0x1f) & ~0x1f); if (round_page(data) != round_page(data + tgt->block_size)) data = (char *)round_page(data); #endif /* POWERMAC */ if (disk_size > SCSI_CMD_READ_MAX_LBA) tgt->flags |= TGT_BIG; /* * Mandatory long-form commands ? */ if (BGET(scsi_use_long_form,(unsigned char)tgt->masterno,tgt->target_id)) tgt->flags |= TGT_BIG; if (tgt->flags & TGT_BIG) readfun = scsi_long_read; ior->io_op = IO_INTERNAL; ior->io_error = 0; #ifdef hp_pa if(geom_done) goto setup_label; #endif /* * Find out about the phys disk geometry */ #if PARAGON860 /* * The NCR RAID controller does not support a read capacity command * with the Partial Medium Indicator (PMI) bit set. Therefore we * have to calculate the number of sectors per cylinder from data * in the mode select pages. This method should work for standalone * disks as well. */ /* * Read page 3 to find the number of sectors/track and bytes/sector */ ret = scsi_mode_sense(tgt, 0x03, 0xff, ior); /* scsi_error(...) */ { scsi_mode_sense_page3_t *page3; page3 = (scsi_mode_sense_page3_t *) (((scsi_mode_sense_data_t *)tgt->cmd_ptr) + 1); nsectors = (page3->sectors_per_track_msb << 8) | page3->sectors_per_track_lsb; sector_size = (page3->bytes_per_sector_msb << 8) | page3->bytes_per_sector_lsb; } ior->io_op = IO_INTERNAL; ior->io_error = 0; /* * Read page 4 to find the number of cylinders and tracks/cylinder */ ret = scsi_mode_sense(tgt, 0x04, 0xff, ior); /* scsi_error(...) */ { scsi_mode_sense_page4_t *page4; page4 = (scsi_mode_sense_page4_t *) (((scsi_mode_sense_data_t *)tgt->cmd_ptr) + 1); ncylinders = (page4->number_of_cylinders_msb << 16) | (page4->number_of_cylinders << 8) | page4->number_of_cylinders_lsb; ntracks = page4->number_of_heads; } /* * Calculate the sectors per cylinder (sec/track * tracks/cyl) */ secs_per_cyl = nsectors * ntracks; if (scsi_debug) { printf("rz%d: %d bytes/sec %d sec/track\n", tgt->unit_no, sector_size, nsectors); printf(" %d tracks/cyl %d cyl/unit\n", ntracks, ncylinders); } #else /* PARAGON860 */ /* Read page one to get read / write error recovery info */ ret = scsi_mode_sense(tgt, 0x01, 0xff, ior); if(ret == SCSI_RET_SUCCESS) { scsi_mode_sense_page1_t *page1; unsigned char mode_save[0xff]; int length; length = *tgt->cmd_ptr + 1; bcopy(tgt->cmd_ptr, mode_save, length); page1 = (scsi_mode_sense_page1_t *)(mode_save + 4 + mode_save[3]); *mode_save = 0; /* mode data length */ page1->ps = 0; page1->flags = PAGE1_AWRE | PAGE1_ARRE | PAGE1_TB | PAGE1_PER; /* * Enable automatic reallocation of bad blocks, * Report any recovered errors. */ ior->io_op = IO_INTERNAL; ior->io_error = 0; ret = scdisk_mode_select(tgt, 0, ior, mode_save, length, 0); if(ret != SCSI_RET_SUCCESS) { if (scsi_debug) printf("rz%d: Can't change error recovery parameters\n", tgt->unit_no); } } ior->io_op = IO_INTERNAL; ior->io_error = 0; #ifdef POWERMAC tgt->flags |= TGT_OPTIONAL_CMD; #endif ret = scsi_read_capacity( tgt, 1, ior); #ifdef POWERMAC tgt->flags &= ~TGT_OPTIONAL_CMD; #endif /* scsi_error(...) */ if (ret) { secs_per_cyl = 16; sector_size = tgt->block_size; } else { cap = (scsi_rcap_data_t*) tgt->cmd_ptr; secs_per_cyl = (cap->lba1<<24) | (cap->lba2<<16) | (cap->lba3<< 8) | cap->lba4; secs_per_cyl += 1; sector_size = (cap->blen1<<24) | (cap->blen2<<16) | (cap->blen3<<8 ) | cap->blen4; } if (scsi_debug) printf("rz%d: %d sect/cyl %d bytes/sec\n", tgt->unit_no, secs_per_cyl, sector_size); #endif /* PARAGON860 */ #if NSCSI2 > 0 /* * ... and a bunch of other things for scsi2 */ #endif /* NSCSI2 > 0 */ /* * Get partition table off pack */ if (tgt->dev_ops == &scsi_devsw[SCSI_CDROM]) { /* no label on a CD-ROM */ look_for_label = FALSE; } else { look_for_label = TRUE; } setup_label: if (look_for_label) { /* first look for a BSD label */ ior->io_data = data; ior->io_count = tgt->block_size; ior->io_op = IO_READ; ior->io_error = 0; tgt->ior = ior; (*readfun)( tgt, LABELOFFSET/tgt->block_size, ior); iowait(ior); if (!ior->io_error) { /* Search for BSD label, might be a bit further along */ register int j; for (i = LABELOFFSET % tgt->block_size; i < (tgt->block_size-sizeof(struct disklabel)); i += sizeof(int)) { label = (struct disklabel *) &data[i]; if (label->d_magic == DISKMAGIC && label->d_magic2 == DISKMAGIC) { break; } else label = (struct disklabel *) 0; } } } else { label = (struct disklabel *) 0; } if (label) { if (scsi_debug) printf("{Using BSD label}"); tgt->dev_info.disk.l = *label; } else { /* then look for a vendor's label, but first fill in defaults and what we found */ label = &tgt->dev_info.disk.l; *label = scsi_default_label; label->d_secsize = sector_size; label->d_nsectors = nsectors; label->d_ntracks = ntracks; label->d_ncylinders = ncylinders; label->d_secpercyl = secs_per_cyl; label->d_secperunit = disk_size; ior->io_data = data; if (!look_for_label || !rz_vendor_label(tgt, label, ior)) { if (look_for_label) { printf("%s rz%d, %s\n", "WARNING: No valid disk label on", tgt->unit_no, "using defaults"); } /* Validate partitions a and c for initialization */ tgt->dev_info.disk.l.d_partitions[0].p_offset = 0; tgt->dev_info.disk.l.d_partitions[0].p_size = disk_size; tgt->dev_info.disk.l.d_partitions[2].p_offset = 0; tgt->dev_info.disk.l.d_partitions[2].p_size = disk_size; tgt->dev_info.disk.l.d_partitions[MAXPARTITIONS].p_offset = 0; tgt->dev_info.disk.l.d_partitions[MAXPARTITIONS].p_size = -1; } label->d_checksum = 0; label->d_checksum = dkcksum(label); } ret = SCSI_RET_SUCCESS; done: if (rdata) kfree((vm_offset_t) rdata, 2 * tgt->block_size); io_req_free(ior); return ret; }
/* * Find and convert from an HPUX label to BSD */ boolean_t read_hpux_label( target_info_t *tgt, struct disklabel *label, io_req_t ior) { struct lif_header *l_header; struct lif_label *l_label; struct disklabel *dlp; vm_offset_t data; boolean_t rc = FALSE; if (kmem_alloc(kernel_map, (vm_offset_t *)&data, DEV_BSIZE) != KERN_SUCCESS) { printf("cant read LIF header\n"); return(FALSE); } if (label->d_secperunit == 0) label->d_secperunit = 0x1fffffff; label->d_npartitions = 1; if (label->d_partitions[0].p_size == 0) label->d_partitions[0].p_size = 0x1fffffff; label->d_partitions[0].p_offset = 0; ior->io_count = DEV_BSIZE; ior->io_op = IO_READ; ior->io_data = (char *)data; tgt->ior = ior; scdisk_read( tgt, LIF_HEADER_OFF/tgt->block_size, ior); iowait(ior); l_header = (struct lif_header*)ior->io_data; if (l_header->magic != LIF_MAGIC) { printf("cant find LIF_HEADER block\n"); rc = FALSE; goto out; } if (!IS_OSF1_DISK(l_header)) { ior->io_count = DEV_BSIZE; ior->io_op = IO_READ; tgt->ior = ior; scdisk_read( tgt, LIF_LABEL_OFF/tgt->block_size, ior); iowait(ior); if (!convert_lif_to_osf1((struct lif_label*)ior->io_data, label)) { printf("No FS detected in LIF block\n"); rc = FALSE; goto out; } else rc = TRUE; } else { ior->io_count = DEV_BSIZE; ior->io_op = IO_READ; tgt->ior = ior; scdisk_read( tgt, LABELSECTOR, ior); iowait(ior); for (dlp = (struct disklabel *)ior->io_data; dlp <= (struct disklabel *)(ior->io_data +DEV_BSIZE-sizeof(*dlp)); dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { continue; } else if (dlp->d_npartitions > MAXPARTITIONS || dkcksum(dlp) != 0) { printf("disk label corrupted\n"); rc = FALSE; goto out; } else { rc = TRUE; *label = *dlp; break; } } if (rc == FALSE) printf("no disk label\n"); } out: if (data) (void) kmem_free(kernel_map, data, DEV_BSIZE); return rc; }