Exemple #1
0
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;
}
Exemple #2
0
/* 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;
}
Exemple #3
0
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);
}
Exemple #4
0
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;
}
Exemple #5
0
/*
 * 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;
}
Exemple #6
0
Fichier : bio.c Projet : vnea/UPMC
/**
 * @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);
}
Exemple #7
0
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);
}
Exemple #8
0
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;
}
Exemple #9
0
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);
}
Exemple #10
0
/*
 * 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;
}
Exemple #11
0
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);
	}
}
Exemple #12
0
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);
}
Exemple #13
0
/*
 * 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);
}
Exemple #14
0
/*
 * 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);
}
Exemple #15
0
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
}
Exemple #16
0
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;
}
Exemple #17
0
/*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;
}
Exemple #18
0
/*
 * 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;
}