summaryrefslogtreecommitdiff
path: root/scsi/rz_disk.c
diff options
context:
space:
mode:
Diffstat (limited to 'scsi/rz_disk.c')
-rw-r--r--scsi/rz_disk.c1222
1 files changed, 0 insertions, 1222 deletions
diff --git a/scsi/rz_disk.c b/scsi/rz_disk.c
deleted file mode 100644
index 87a992b..0000000
--- a/scsi/rz_disk.c
+++ /dev/null
@@ -1,1222 +0,0 @@
-/*
- * Mach Operating System
- * Copyright (c) 1991,1990 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
-/*
- * File: rz_disk.c
- * Author: Alessandro Forin, Carnegie Mellon University
- * Date: 10/90
- *
- * Top layer of the SCSI driver: interface with the MI.
- * This file contains operations specific to disk-like devices.
- *
- * Modified by Kevin T. Van Maren to use a common partition code
- * with the ide driver, and support 'slices'.
- */
-
-
-#include <scsi/scsi.h>
-#if (NSCSI > 0)
-
-#include <device/buf.h>
-#include <device/disk_status.h>
-#include <device/device_types.h>
-#include <device/param.h>
-#include <device/errno.h>
-
-#include <kern/time_out.h>
-#include <machine/machspl.h> /* spl definitions */
-#include <mach/std_types.h>
-#include <platforms.h>
-
-#include <scsi/compat_30.h>
-#include <scsi/scsi.h>
-#include <scsi/scsi_defs.h>
-#include <scsi/rz.h>
-#include <scsi/rz_labels.h>
-
-#ifdef MACH_KERNEL
-#else /*MACH_KERNEL*/
-#include <sys/kernel.h> /* for hz */
-#endif /*MACH_KERNEL*/
-
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include "vm_param.h"
-#include <vm/vm_kern.h>
-#include <vm/pmap.h>
-
-extern void scdisk_read(), scdisk_write(),
- scsi_long_read(), scsi_long_write();
-
-void scdisk_start(); /* forwards */
-void scdisk_start_rw();
-unsigned dkcksum();
-
-#if 0
-struct diskpart scsi_array[8*64];
-#endif 0
-
-
-/* THIS IS THE BOTTOM LAYER FOR THE SCSI PARTITION CODE */
-typedef struct scsi_driver_info {
- target_info_t *tgt;
- io_req_t ior;
- void (*readfun)();
- int sectorsize;
-} scsi_driver_info;
-
-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);
-}
-
-
-
-/*
- * Specialized side of the open routine for disks
- */
-scsi_ret_t scdisk_open(tgt, req)
- target_info_t *tgt;
- io_req_t req;
-{
- register int i, dev_bsize;
- scsi_ret_t ret = /* SCSI_RET_SUCCESS; */ -1;
- unsigned int disk_size, secs_per_cyl, sector_size;
- scsi_rcap_data_t *cap;
- struct disklabel *label;
- io_req_t ior;
- void (*readfun)() = scdisk_read;
- char *data = (char *)0;
-
- int numpart;
-
- scsi_driver_info scsi_info;
- char drive_name[10]; /* used for disklabel strings */
-
- if (tgt->flags & TGT_ONLINE)
- return SCSI_RET_SUCCESS;
-
- /*
- * Dummy ior for proper sync purposes
- */
- io_req_alloc(ior,0);
- ior->io_next = 0;
- ior->io_count = 0;
-
- /*
- * Set the LBN to DEV_BSIZE with a MODE SELECT.
- * If this fails we try a couple other tricks.
- */
- dev_bsize = 0;
- for (i = 0; i < 5; i++) {
- ior->io_op = IO_INTERNAL;
- ior->io_error = 0;
- ret = scdisk_mode_select(tgt, DEV_BSIZE, ior, 0, 0, 0);
- if (ret == SCSI_RET_SUCCESS) {
- dev_bsize = DEV_BSIZE;
- break;
- }
- if (ret == SCSI_RET_RETRY) {
- timeout(wakeup, tgt, 2*hz);
- await(tgt);
- }
- if (ret == SCSI_RET_DEVICE_DOWN)
- goto done;
- }
-#if 0
- if (ret != SCSI_RET_SUCCESS) {
- scsi_error( tgt, SCSI_ERR_MSEL, ret, 0);
- ret = D_INVALID_SIZE;
- goto done;
- }
-#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_SUCCESS) {
- int val;
-
- cap = (scsi_rcap_data_t*) tgt->cmd_ptr;
- disk_size = (cap->lba1<<24) |
- (cap->lba2<<16) |
- (cap->lba3<< 8) |
- cap->lba4;
- if (scsi_debug)
- printf("rz%d holds %d blocks\n", tgt->unit_no, disk_size);
- val = (cap->blen1<<24) |
- (cap->blen2<<16) |
- (cap->blen3<<8 ) |
- cap->blen4;
- if (dev_bsize == 0)
- dev_bsize = val;
- else
- if (val != dev_bsize) panic("read capacity bad");
-
- if (disk_size > SCSI_CMD_READ_MAX_LBA)
- tgt->flags |= TGT_BIG;
-
- } else {
- printf("Unknown disk capacity??\n");
- disk_size = -1;
- }
- /*
- * 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;
-
- /*
- * Some CDROMS truly dislike 512 as LBN.
- * Use a MODE_SENSE to cover for this case.
- */
- if (dev_bsize == 0) {
- scsi_mode_sense_data_t *m;
-
- ior->io_op = IO_INTERNAL;
- ior->io_error = 0;
- ret = scsi_mode_sense(tgt, 0/*pagecode*/, 32/*?*/, ior);
- if (ret == SCSI_RET_SUCCESS) {
- m = (scsi_mode_sense_data_t *) tgt->cmd_ptr;
- dev_bsize =
- m->bdesc[0].blen_msb << 16 |
- m->bdesc[0].blen << 8 |
- m->bdesc[0].blen_lsb;
- }
- }
-
- /*
- * Find out about the phys disk geometry -- scsi specific
- */
-
- ior->io_op = IO_INTERNAL;
- ior->io_error = 0;
- ret = scsi_read_capacity( tgt, 1, ior);
- if (ret == SCSI_RET_SUCCESS) {
- 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;
- } else {
- sector_size = dev_bsize ? dev_bsize : DEV_BSIZE;
- secs_per_cyl = disk_size;
- }
- if (dev_bsize == 0)
- dev_bsize = sector_size;
-
- if (scsi_debug)
- printf("rz%d: %d sect/cyl %d bytes/sec\n", tgt->unit_no,
- secs_per_cyl, sector_size);
-
- /*
- * At this point, one way or other, we are committed to
- * a given disk capacity and sector size.
- */
- tgt->block_size = dev_bsize;
-
- /*
- * Get partition table off pack
- */
-
-#ifdef MACH_KERNEL
- ior->io_data = (char *)kalloc(sector_size);
-#endif /*MACH_KERNEL*/
-
- scsi_info.tgt=tgt;
- scsi_info.ior=ior;
- scsi_info.readfun=readfun;
- scsi_info.sectorsize=sector_size;
-
- /* label has NOT been allocated space yet! set to the tgt disklabel */
- label=&scsi_info.tgt->dev_info.disk.l;
-
- sprintf(drive_name, "sd%d:", tgt->unit_no);
-
- if (scsi_debug)
- printf("Using bogus geometry: 32 sectors/track, 64 heads\n");
-
- fudge_bsd_label(label, DTYPE_SCSI, disk_size /* /(32*64)*/ ,
- 64, 32, sector_size, 8);
-
- numpart=get_only_partition(&scsi_info, (*scsi_read_fun),
- tgt->dev_info.disk.scsi_array, MAX_SCSI_PARTS, disk_size, drive_name);
-
- printf("%s %d partitions found\n",drive_name,numpart);
-
- ret=SCSI_RET_SUCCESS; /* if 0, return SCSI_RET_SUCCESS */
-
-
-done:
- io_req_free(ior);
-
- return(ret);
-}
-
-
-/*
- * Disk strategy routine
- */
-int scdisk_strategy(ior)
- register io_req_t ior;
-{
- target_info_t *tgt;
- register scsi_softc_t *sc;
- register int i = ior->io_unit, part;
- register unsigned rec, max;
- spl_t s;
- struct diskpart *label;
-
- sc = scsi_softc[rzcontroller(i)];
- tgt = sc->target[rzslave(i)];
- part = rzpartition(i);
-
- /*
- * Validate request
- */
-
- /* readonly ? */
- if ((tgt->flags & TGT_READONLY) &&
- (ior->io_op & (IO_READ|IO_INTERNAL) == 0)) {
- ior->io_error = D_READ_ONLY;
- ior->io_op |= IO_ERROR;
- ior->io_residual = ior->io_count;
- iodone(ior);
- return ior->io_error;
- }
-
- rec = ior->io_recnum;
-
- label=lookup_part(tgt->dev_info.disk.scsi_array, part);
- if (!label) {
- if (scsi_debug)
- printf("sc strategy -- bad partition\n");
- ior->io_error = D_INVALID_SIZE;
- ior->io_op |= IO_ERROR;
- ior->io_residual = ior->io_count;
- iodone(ior);
- return ior->io_error;
- }
- else max=label->size;
- if (max == -1) /* what about 0? */
- max = tgt->dev_info.disk.l.d_secperunit -
-
- label->start;
-
- i = (ior->io_count + tgt->block_size - 1) / tgt->block_size;
- if (((rec + i) > max) || (ior->io_count < 0) ||
-#if later
- ((rec <= LABELSECTOR) && ((tgt->flags & TGT_WRITE_LABEL) == 0))
-#else
- FALSE
-#endif
- ) {
- ior->io_error = D_INVALID_SIZE;
- ior->io_op |= IO_ERROR;
- ior->io_residual = ior->io_count;
- iodone(ior);
- return ior->io_error;
- }
- /*
- * Find location on disk: secno and cyl (for disksort)
- */
- rec += label->start;
- ior->io_residual = rec / tgt->dev_info.disk.l.d_secpercyl;
-
- /*
- * Enqueue operation
- */
- s = splbio();
- simple_lock(&tgt->target_lock);
- if (tgt->ior) {
- disksort(tgt->ior, ior);
- simple_unlock(&tgt->target_lock);
- splx(s);
- } else {
- ior->io_next = 0;
- tgt->ior = ior;
- simple_unlock(&tgt->target_lock);
- splx(s);
-
- scdisk_start(tgt,FALSE);
- }
-
- return D_SUCCESS;
-}
-
-/*#define CHECKSUM*/
-#ifdef CHECKSUM
-int max_checksum_size = 0x2000;
-#endif CHECKSUM
-
-/*
- * Start/completion routine for disks
- */
-void scdisk_start(tgt, done)
- target_info_t *tgt;
- boolean_t done;
-{
- register io_req_t ior = tgt->ior;
- register unsigned part;
-#ifdef CHECKSUM
- register unsigned secno;
-#endif
- struct diskpart *label;
-
- if (ior == 0)
- return;
-
- if (tgt->flags & TGT_BBR_ACTIVE)
- {
- scdisk_bbr_start(tgt, done);
- return;
- }
-
- if (done) {
- register unsigned int xferred;
- unsigned int max_dma_data;
-
- max_dma_data = scsi_softc[(unsigned char)tgt->masterno]->max_dma_data;
- /* see if we must retry */
- if ((tgt->done == SCSI_RET_RETRY) &&
- ((ior->io_op & IO_INTERNAL) == 0)) {
- delay(1000000);/*XXX*/
- goto start;
- } else
- /* got a bus reset ? pifff.. */
- if ((tgt->done == (SCSI_RET_ABORTED|SCSI_RET_RETRY)) &&
- ((ior->io_op & IO_INTERNAL) == 0)) {
- if (xferred = ior->io_residual) {
- ior->io_data -= xferred;
- ior->io_count += xferred;
- ior->io_recnum -= xferred / tgt->block_size;
- ior->io_residual = 0;
- }
- goto start;
- } else
- /*
- * Quickly check for errors: if anything goes wrong
- * we do a request sense, see if that is what we did.
- */
- if (tgt->cur_cmd == SCSI_CMD_REQUEST_SENSE) {
- scsi_sense_data_t *sns;
- unsigned int blockno;
- char *outcome;
-
- ior->io_op = ior->io_temporary;
-
- sns = (scsi_sense_data_t *)tgt->cmd_ptr;
- if (sns->addr_valid)
- blockno = sns->u.xtended.info0 << 24 |
- sns->u.xtended.info1 << 16 |
- sns->u.xtended.info2 << 8 |
- sns->u.xtended.info3;
- else {
- part = rzpartition(ior->io_unit);
- label = lookup_part(tgt->dev_info.disk.scsi_array, part);
- blockno = label->start;
- blockno += ior->io_recnum;
- if (!label) blockno=-1;
- }
-
- if (scsi_check_sense_data(tgt, sns)) {
- ior->io_error = 0;
- if ((tgt->done == SCSI_RET_RETRY) &&
- ((ior->io_op & IO_INTERNAL) == 0)) {
- delay(1000000);/*XXX*/
- goto start;
- }
- outcome = "Recovered";
- } else {
- outcome = "Unrecoverable";
- ior->io_error = D_IO_ERROR;
- ior->io_op |= IO_ERROR;
- }
- if ((tgt->flags & TGT_OPTIONAL_CMD) == 0) {
- printf("%s Error, rz%d: %s%s%d\n", outcome,
- tgt->target_id + (tgt->masterno * 8),
- (ior->io_op & IO_READ) ? "Read" :
- ((ior->io_op & IO_INTERNAL) ? "(command)" : "Write"),
- " disk error, phys block no. ", blockno);
-
- scsi_print_sense_data(sns);
-
- /*
- * On fatal read/write errors try replacing the bad block
- * The bbr routine will return TRUE iff it took control
- * over the target for all subsequent operations. In this
- * event, the queue of requests is effectively frozen.
- */
- if (ior->io_error &&
- ((sns->error_class == SCSI_SNS_XTENDED_SENSE_DATA) &&
- ((sns->u.xtended.sense_key == SCSI_SNS_HW_ERR) ||
- (sns->u.xtended.sense_key == SCSI_SNS_MEDIUM_ERR))) &&
- scdisk_bad_block_repl(tgt, blockno))
- return;
- }
- }
-
- /*
- * See if we had errors
- */
- else if (tgt->done != SCSI_RET_SUCCESS) {
-
- if (tgt->done == SCSI_RET_NEED_SENSE) {
-
- ior->io_temporary = ior->io_op;
- ior->io_op = IO_INTERNAL;
- scsi_request_sense(tgt, ior, 0);
- return;
-
- } else if (tgt->done == SCSI_RET_DEVICE_DOWN) {
- ior->io_error = D_DEVICE_DOWN;
- ior->io_op |= IO_ERROR;
- } else {
- printf("%s%x\n", "?rz_disk Disk error, ret=x", tgt->done);
- ior->io_error = D_IO_ERROR;
- ior->io_op |= IO_ERROR;
- }
- }
- /*
- * No errors.
- * See if we requested more than the max
- * (We use io_residual in a flip-side way here)
- */
- else if (ior->io_count > (xferred = max_dma_data)) {
- ior->io_residual += xferred;
- ior->io_count -= xferred;
- ior->io_data += xferred;
- ior->io_recnum += xferred / tgt->block_size;
- goto start;
- }
- else if (xferred = ior->io_residual) {
- ior->io_data -= xferred;
- ior->io_count += xferred;
- ior->io_recnum -= xferred / tgt->block_size;
- ior->io_residual = 0;
- } /* that's it */
-
-#ifdef CHECKSUM
- if ((ior->io_op & IO_READ) && (ior->io_count < max_checksum_size)) {
- part = rzpartition(ior->io_unit);
- label=lookup_part(tgt->dev_info.disk.scsi_array, part);
- if (!label) printf("NOT FOUND!\n");
- secno = ior->io_recnum + label->start;
- scdisk_bcheck(secno, ior->io_data, ior->io_count);
- }
-#endif CHECKSUM
-
- /* dequeue next one */
- {
- io_req_t next;
-
- simple_lock(&tgt->target_lock);
- next = ior->io_next;
- tgt->ior = next;
- simple_unlock(&tgt->target_lock);
-
- iodone(ior);
- if (next == 0)
- return;
-
- ior = next;
- }
-
-#ifdef CHECKSUM
- if (((ior->io_op & IO_READ) == 0) && (ior->io_count < max_checksum_size)) {
- part = rzpartition(ior->io_unit);
- label=lookup_part(tgt->dev_info.disk.scsi_array, part);
- secno = ior->io_recnum + label->start;
- scdisk_checksum(secno, ior->io_data, ior->io_count);
- }
-#endif CHECKSUM
- }
- ior->io_residual = 0;
-start:
- scdisk_start_rw( tgt, ior);
-}
-
-void scdisk_start_rw( tgt, ior)
- target_info_t *tgt;
- register io_req_t ior;
-{
- unsigned int part, secno;
- register boolean_t long_form;
- struct diskpart *label;
-
- part = rzpartition(ior->io_unit);
- label=lookup_part(tgt->dev_info.disk.scsi_array, part);
- if (!label)
- printf("NOT FOUND!\n");
- secno = ior->io_recnum + label->start;
-
- /* Use long form if either big block addresses or
- the size is more than we can fit in one byte */
- long_form = (tgt->flags & TGT_BIG) ||
- (ior->io_count > (256 * tgt->block_size));
- if (ior->io_op & IO_READ)
- (long_form ? scsi_long_read : scdisk_read)(tgt, secno, ior);
- else if ((ior->io_op & IO_INTERNAL) == 0)
- (long_form ? scsi_long_write : scdisk_write)(tgt, secno, ior);
-}
-
-#include <sys/ioctl.h>
-#ifdef ULTRIX_COMPAT
-#include <mips/PMAX/rzdisk.h>
-#endif /*ULTRIX_COMPAT*/
-
-io_return_t
-scdisk_get_status(dev, tgt, flavor, status, status_count)
- int dev;
- target_info_t *tgt;
- dev_flavor_t flavor;
- dev_status_t status;
- natural_t *status_count;
-{
- struct disklabel *lp;
- struct diskpart *label;
-
- lp = &tgt->dev_info.disk.l;
-
- switch (flavor) {
-#ifdef MACH_KERNEL
- case DEV_GET_SIZE:
-
- label=lookup_part(tgt->dev_info.disk.scsi_array, rzpartition(dev));
- status[DEV_GET_SIZE_DEVICE_SIZE] = label->size * lp->d_secsize;
- status[DEV_GET_SIZE_RECORD_SIZE] = tgt->block_size;
- *status_count = DEV_GET_SIZE_COUNT;
- break;
-#endif
-
- case DIOCGDINFO:
- *(struct disklabel *)status = *lp;
-#ifdef MACH_KERNEL
- *status_count = sizeof(struct disklabel)/sizeof(int);
-#endif MACH_KERNEL
- break;
-
- case DIOCGDINFO - (0x10<<16):
- *(struct disklabel *)status = *lp;
-#ifdef MACH_KERNEL
- *status_count = sizeof(struct disklabel)/sizeof(int) - 4;
-#endif MACH_KERNEL
- break;
-
-#ifdef MACH_KERNEL
-#else /*MACH_KERNEL*/
-#if ULTRIX_COMPAT
- case SCSI_MODE_SENSE: /*_IOWR(p, 9, struct mode_sel_sns_params) */
- break;
- case DIOCGETPT: /*_IOR(p, 1, struct pt) */
- case SCSI_GET_SENSE: /*_IOR(p, 10, struct extended_sense) */
- return ul_disk_ioctl(tgt, flavor, status, status_count);
-#endif /*ULTRIX_COMPAT*/
-#endif /*!MACH_KERNEL*/
-
-#if 0
- case DIOCRFORMAT:
- break;
-#endif
- default:
-#ifdef i386
- return(scsi_i386_get_status(dev, tgt, flavor, status, status_count));
-#else i386
- return(D_INVALID_OPERATION);
-#endif i386
- }
- return D_SUCCESS;
-}
-
-io_return_t
-scdisk_set_status(dev, tgt, flavor, status, status_count)
- int dev;
- target_info_t *tgt;
- dev_flavor_t flavor;
- dev_status_t status;
- natural_t status_count;
-{
- io_return_t error = D_SUCCESS;
- struct disklabel *lp;
-
- lp = &tgt->dev_info.disk.l;
-
-
- switch (flavor) {
- case DIOCSRETRIES:
-#ifdef MACH_KERNEL
- if (status_count != sizeof(int))
- return D_INVALID_SIZE;
-#endif /* MACH_KERNEL */
- scsi_bbr_retries = *(int *)status;
- break;
-
- case DIOCWLABEL:
- case DIOCWLABEL - (0x10<<16):
- if (*(int*)status)
- tgt->flags |= TGT_WRITE_LABEL;
- else
- tgt->flags &= ~TGT_WRITE_LABEL;
- break;
- case DIOCSDINFO:
- case DIOCSDINFO - (0x10<<16):
- case DIOCWDINFO:
- case DIOCWDINFO - (0x10<<16):
-#ifdef MACH_KERNEL
- if (status_count != sizeof(struct disklabel) / sizeof(int))
- return D_INVALID_SIZE;
-#endif /* MACH_KERNEL */
- error = setdisklabel(lp, (struct disklabel*) status);
- if (error || (flavor == DIOCSDINFO) || (flavor == DIOCSDINFO - (0x10<<16)))
- return error;
- error = scdisk_writelabel(tgt);
- break;
-
-#ifdef MACH_KERNEL
-#else /*MACH_KERNEL*/
-#if ULTRIX_COMPAT
- case SCSI_FORMAT_UNIT: /*_IOW(p, 4, struct format_params) */
- case SCSI_REASSIGN_BLOCK: /*_IOW(p, 5, struct reassign_params) */
- case SCSI_READ_DEFECT_DATA: /*_IOW(p, 6, struct read_defect_params) */
- case SCSI_VERIFY_DATA: /*_IOW(p, 7, struct verify_params) */
- case SCSI_MODE_SELECT: /*_IOW(p, 8, struct mode_sel_sns_params) */
- case SCSI_MODE_SENSE: /*_IOW(p, 9, struct mode_sel_sns_params) */
- case SCSI_GET_INQUIRY_DATA: /*_IOW(p, 11, struct inquiry_info) */
- return ul_disk_ioctl(tgt, flavor, status, status_count);
-#endif /*ULTRIX_COMPAT*/
-#endif /*!MACH_KERNEL*/
-
-#if notyet
- case DIOCWFORMAT:
- case DIOCSBAD: /* ?? how ? */
-#endif
- default:
-#ifdef i386
- error = scsi_i386_set_status(dev, tgt, flavor, status, status_count);
-#else i386
- error = D_INVALID_OPERATION;
-#endif i386
- }
- return error;
-}
-
-static int grab_it(tgt, ior)
- target_info_t *tgt;
- io_req_t ior;
-{
- spl_t s;
-
- s = splbio();
- simple_lock(&tgt->target_lock);
- if (!tgt->ior)
- tgt->ior = ior;
- simple_unlock(&tgt->target_lock);
- splx(s);
-
- if (tgt->ior != ior)
- return D_ALREADY_OPEN;
- return D_SUCCESS;
-}
-
-/* Write back a label to the disk */
-io_return_t scdisk_writelabel(tgt)
- target_info_t *tgt;
-{
-
-printf("scdisk_writelabel: NO LONGER IMPLEMENTED\n");
-#if 0
-/* Taken out at Bryan's suggestion until 'fixed' for slices */
-
- io_req_t ior;
- char *data = (char *)0;
- struct disklabel *label;
- io_return_t error;
- int dev_bsize = tgt->block_size;
-
- io_req_alloc(ior,0);
-#ifdef MACH_KERNEL
- data = (char *)kalloc(dev_bsize);
-#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 = dev_bsize;
- 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, tgt->dev_info.disk.labelsector, ior);
- iowait(ior);
- if (error = ior->io_error)
- goto ret;
-
- label = (struct disklabel *) &data[tgt->dev_info.disk.labeloffset];
- *label = tgt->dev_info.disk.l;
-
- ior->io_next = 0;
- ior->io_prev = 0;
- ior->io_data = data;
- ior->io_count = dev_bsize;
- ior->io_op = IO_WRITE;
-
- while (grab_it(tgt, ior) != D_SUCCESS) ; /* ahem */
-
- scdisk_write( tgt, tgt->dev_info.disk.labelsector, ior);
- iowait(ior);
-
- error = ior->io_error;
-ret:
-#ifdef MACH_KERNEL
- if (data) kfree((int)data, dev_bsize);
-#endif /*MACH_KERNEL*/
- io_req_free(ior);
- return error;
-
-#endif 0 scdisk_writelabel
-return -1; /* FAILURE ? */
-}
-
-#ifdef MACH_KERNEL
-#else /*MACH_KERNEL*/
-#if ULTRIX_COMPAT
-
-io_return_t ul_disk_ioctl(tgt, flavor, status, status_count)
- target_info_t *tgt;
- dev_flavor_t flavor;
- dev_status_t status;
- natural_t status_count;
-{
- io_return_t ret;
- scsi_ret_t err = SCSI_RET_ABORTED;/*xxx*/
- io_req_t ior;
-
- if (!suser())
- return EACCES;
-
- ior = geteblk(sizeof(struct defect_descriptors));
- ior->io_next = 0;
- ior->io_count = 0;
- ior->io_op = IO_INTERNAL;
- ior->io_error = 0;
- ior->io_recnum = 0;
- ior->io_residual = 0;
-
- switch (flavor) {
-
- case DIOCGETPT: { /*_IOR(p, 1, struct pt) */
- scsi_dec_label_t *p;
- struct disklabel *lp;
- int i;
-
- lp = &tgt->dev_info.disk.l;
- p = (scsi_dec_label_t *)status;
-
- p->magic = DEC_PARTITION_MAGIC;
- p->in_use = 1;
- for (i = 0; i < 8; i++) {
- label=lookup_part(tgt->dev_info.disk.scsi_array, part);
- p->partitions[i].n_sectors = label->size;
- p->partitions[i].offset = label->start;
- }
- err = SCSI_RET_SUCCESS;
- }
- break;
-
- case SCSI_GET_SENSE: { /*_IOR(p, 10, struct extended_sense) */
- scsi_sense_data_t *s;
-
- s = (scsi_sense_data_t*)tgt->cmd_ptr;
- bcopy(s, status, sizeof(*s) + s->u.xtended.add_len - 1);
- err = SCSI_RET_SUCCESS;
- /* only once */
- bzero(tgt->cmd_ptr, sizeof(scsi_sense_data_t));
- }
- break;
-
- case SCSI_GET_INQUIRY_DATA: { /*_IOR(p, 11, struct inquiry_info) */
- struct mode_sel_sns_params *ms;
-
- ms = (struct mode_sel_sns_params*)status;
- err = scsi_inquiry( tgt, SCSI_INQ_STD_DATA);
- if (copyout(tgt->cmd_ptr, ms->msp_addr, sizeof(struct inquiry_info))){
- ret = EFAULT;
- goto out;
- }
- }
- break;
-
- case SCSI_FORMAT_UNIT: { /*_IOW(p, 4, struct format_params) */
- struct format_params *fp;
- struct defect_descriptors *df;
- unsigned char mode;
- unsigned int old_timeout;
-
- fp = (struct format_params *)status;
- df = (struct defect_descriptors*)ior->io_data;
- if (fp->fp_length != 0) {
- if (copyin(fp->fp_addr, df, sizeof(*df))) {
- ret = EFAULT;
- goto out;
- }
- ior->io_count = sizeof(*df);
- } else
- ior->io_count = 0;
- mode = fp->fp_format & SCSI_CMD_FMT_LIST_TYPE;
- switch (fp->fp_defects) {
- case VENDOR_DEFECTS:
- mode |= SCSI_CMD_FMT_FMTDATA|SCSI_CMD_FMT_CMPLIST;
- break;
- case KNOWN_DEFECTS:
- mode |= SCSI_CMD_FMT_FMTDATA;
- break;
- case NO_DEFECTS:
- default:
- break;
- }
- old_timeout = scsi_watchdog_period;
- scsi_watchdog_period = 60*60; /* 1 hour should be enough, I hope */
- err = scsi_format_unit( tgt, mode, fp->fp_pattern,
- fp->fp_interleave, ior);
- scsi_watchdog_period = old_timeout;
- /* Make sure we re-read all info afresh */
- tgt->flags = TGT_ALIVE |
- (tgt->flags & (TGT_REMOVABLE_MEDIA|TGT_FULLY_PROBED));
- }
- break;
-
- case SCSI_REASSIGN_BLOCK: { /*_IOW(p, 5, struct reassign_params) */
- struct reassign_params *r;
- int ndef;
-
- r = (struct reassign_params*) status;
- ndef = r->rp_header.defect_len0 | (r->rp_header.defect_len1 >> 8);
- ndef >>= 2;
- tgt->ior = ior;
- (void) scsi_reassign_blocks( tgt, &r->rp_lbn3, ndef, ior);
- iowait(ior);
- err = tgt->done;
- }
- break;
-
- case SCSI_READ_DEFECT_DATA: { /*_IOW(p, 6, struct read_defect_params) */
- struct read_defect_params *dp;
-
- dp = (struct read_defect_params *)status;
- ior->io_count = ior->io_alloc_size;
- if (dp->rdp_alclen > ior->io_count)
- dp->rdp_alclen = ior->io_count;
- else
- ior->io_count = dp->rdp_alclen;
- ior->io_op |= IO_READ;
- tgt->ior = ior;
- err = scsi_read_defect(tgt, dp->rdp_format|0x18, ior);
- if (copyout(ior->io_data, dp->rdp_addr, dp->rdp_alclen)) {
- ret = EFAULT;
- goto out;
- }
- }
- break;
-
- case SCSI_VERIFY_DATA: { /*_IOW(p, 7, struct verify_params) */
- struct verify_params *v;
- unsigned int old_timeout;
-
- old_timeout = scsi_watchdog_period;
- scsi_watchdog_period = 5*60; /* 5 mins enough, I hope */
- v = (struct verify_params *)status;
- ior->io_count = 0;
- err = scdisk_verify( tgt, v->vp_lbn, v->vp_length, ior);
- scsi_watchdog_period = old_timeout;
- }
- break;
-
- case SCSI_MODE_SELECT: { /*_IOW(p, 8, struct mode_sel_sns_params) */
- struct mode_sel_sns_params *ms;
-
- ms = (struct mode_sel_sns_params*)status;
- if(copyin(ms->msp_addr, ior->io_data, ms->msp_length)) {
- ret = EFAULT;
- goto out;
- }
- err = scdisk_mode_select( tgt, DEV_BSIZE, ior, ior->io_data,
- ms->msp_length, ms->msp_setps);
- }
- break;
-
- case SCSI_MODE_SENSE: { /*_IOWR(p, 9, struct mode_sel_sns_params) */
- struct mode_sel_sns_params *ms;
- unsigned char pagecode;
-
- ms = (struct mode_sel_sns_params*)status;
- pagecode = (ms->msp_pgcode & 0x3f) | (ms->msp_pgctrl << 6);
- err = scsi_mode_sense( tgt, pagecode, ms->msp_length, ior);
- if (copyout(tgt->cmd_ptr, ms->msp_addr, ms->msp_length)){
- ret = EFAULT;
- goto out;
- }
- }
- break;
- }
-
- ret = (err == SCSI_RET_SUCCESS) ? D_SUCCESS : D_IO_ERROR;
- if (ior->io_op & IO_ERROR)
- ret = D_IO_ERROR;
-out:
- brelse(ior);
- return ret;
-}
-#endif /*ULTRIX_COMPAT*/
-#endif /*!MACH_KERNEL*/
-
-#ifdef CHECKSUM
-
-#define SUMSIZE 0x10000
-#define SUMHASH(b) (((b)>>1) & (SUMSIZE - 1))
-struct {
- long blockno;
- long sum;
-} scdisk_checksums[SUMSIZE];
-
-void scdisk_checksum(bno, addr, size)
- long bno;
- register unsigned int *addr;
-{
- register int i = size/sizeof(int);
- register unsigned int sum = -1;
-
- while (i-- > 0)
- sum ^= *addr++;
- scdisk_checksums[SUMHASH(bno)].blockno = bno;
- scdisk_checksums[SUMHASH(bno)].sum = sum;
-}
-
-void scdisk_bcheck(bno, addr, size)
- long bno;
- register unsigned int *addr;
-{
- register int i = size/sizeof(int);
- register unsigned int sum = -1;
- unsigned int *start = addr;
-
- if (scdisk_checksums[SUMHASH(bno)].blockno != bno) {
-if (scsi_debug) printf("No checksum for block x%x\n", bno);
- return;
- }
-
- while (i-- > 0)
- sum ^= *addr++;
-
- if (scdisk_checksums[SUMHASH(bno)].sum != sum) {
- printf("Bad checksum (x%x != x%x), bno x%x size x%x at x%x\n",
- sum,
- scdisk_checksums[bno & (SUMSIZE - 1)].sum,
- bno, size, start);
- gimmeabreak();
- scdisk_checksums[SUMHASH(bno)].sum = sum;
- }
-}
-
-
-#endif CHECKSUM
-
-/*#define PERF */
-#ifdef PERF
-int test_read_size = 512;
-int test_read_skew = 12;
-int test_read_skew_min = 0;
-int test_read_nreads = 1000;
-int test_read_bdev = 0;
-
-#include <sys/time.h>
-
-void test_read(max)
-{
- int i, ssk, usecs;
- struct timeval start, stop;
-
- if (max == 0)
- max = test_read_skew + 1;
- ssk = test_read_skew;
- for (i = test_read_skew_min; i < max; i++){
- test_read_skew = i;
-
- start = time;
- read_test();
- stop = time;
-
- usecs = stop.tv_usec - start.tv_usec;
- if (usecs < 0) {
- stop.tv_sec -= 1;
- usecs += 1000000;
- }
- printf("Skew %3d size %d count %d time %3d sec %d us\n",
- i, test_read_size, test_read_nreads,
- stop.tv_sec - start.tv_sec, usecs);
- }
- test_read_skew = ssk;
-}
-
-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);
- }
-}
-
-void tur_test()
-{
- struct io_req io;
- register int i;
- char *a, *b;
- struct timeval start, stop;
-
- bzero(&io, sizeof(io));
- io.io_unit = test_read_bdev;
- io.io_data = (char*)&io;/*unused but kernel space*/
-
- start = time;
- for (i = 0; i < test_read_nreads; i++) {
- io.io_op = IO_INTERNAL;
- rz_check(io.io_unit, &a, &b);
- scsi_test_unit_ready(b,&io);
- }
- stop = time;
- i = stop.tv_usec - start.tv_usec;
- if (i < 0) {
- stop.tv_sec -= 1;
- i += 1000000;
- }
- printf("%d test-unit-ready took %3d sec %d us\n",
- test_read_nreads,
- stop.tv_sec - start.tv_sec, i);
-}
-
-#endif PERF
-
-/*#define WDEBUG*/
-#ifdef WDEBUG
-
-int buggo_write_size = 8192;
-int buggo_dev = 2; /* rz0b */ /* changed by KTVM from 1 (still b) */
-int buggo_out_buffer[8192/2];
-int buggo_in_buffer[8192/2];
-int buggotest(n, pattern, 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;
-}
-#endif WDEBUG
-#endif /* NSCSI > 0 */