- sectors /= (disk_parms->heads * disk_parms->cyls);
- disk_parms->sectors = sectors; /* dubious on SCSI*//*XXX*/
- }
-
- sd->flags |= SDVALID;
- return(0);
-}
-
-/*******************************************************\
-* close the device.. only called if we are the LAST *
-* occurence of an open device *
-* convenient now but usually a pain *
-\*******************************************************/
-sdclose(dev)
-dev_t dev;
-{
- unsigned char unit, part;
- unsigned int old_priority;
- struct sd_data *sd;
-
- unit = UNIT(dev);
- part = PARTITION(dev);
- sd = sd_data[unit];
- sd->partflags[part] &= ~SDOPEN;
- sd->openparts &= ~(1 << part);
- sd_prevent(unit,PR_ALLOW,SCSI_SILENT|SCSI_ERR_OK);
- return(0);
-}
-
-/*******************************************************\
-* This routine is called by the scsi interrupt when *
-* the transfer is complete.
-\*******************************************************/
-int sd_done(unit,xs)
-int unit;
-struct scsi_xfer *xs;
-{
- struct buf *bp;
- int retval;
- int retries = 0;
-
-#ifdef SDDEBUG
- if(scsi_debug & PRINTROUTINES) printf("sd_done%d ",unit);
-#endif /*SDDEBUG*/
-#ifdef PARANOID
- if (! (xs->flags & INUSE))
- panic("scsi_xfer not in use!");
-#endif
- if((bp = xs->bp) == NULL)
- {
- /***********************************************\
- * if it's a normal user level request, then ask *
- * The user level code to handle error checking *
- * rather than doing it here at interrupt time *
- \***********************************************/
- wakeup(xs);
- return;
- }
-
- /***********************************************\
- * If it has a buf, we might be working with *
- * a request from the buffer cache or some other *
- * piece of code that requires us to process *
- * errors right now, despite cost *
- \***********************************************/
- switch(xs->error)
- {
- case XS_NOERROR:
- bp->b_error = 0;
- bp->b_resid = 0;
- break;
-
- case XS_SENSE:
- retval = (sd_interpret_sense(unit,xs));
- if(retval)
- {
- bp->b_flags |= B_ERROR;
- bp->b_error = retval;
- }
- break;
-
- case XS_BUSY:
- /*should somehow arange for a 1 sec delay here (how?)*/
- case XS_TIMEOUT:
- /***********************************************\
- * If we can, resubmit it to the adapter. *
- \***********************************************/
- if(xs->retries--)
- {
- xs->error = XS_NOERROR;
- xs->flags &= ~ITSDONE;
- if ( (*(sd_data[unit]->sc_sw->scsi_cmd))(xs)
- == SUCCESSFULLY_QUEUED)
- { /* don't wake the job, ok? */
- return;
- }
- xs->flags |= ITSDONE;
- } /* fall through */
-
- case XS_DRIVER_STUFFUP:
- bp->b_flags |= B_ERROR;
- bp->b_error = EIO;
- break;
- default:
- printf("sd%d: unknown error category from scsi driver\n"
- ,unit);
- }
- /*******************************\
- * tell the owner we're done *
- * then free our resources *
- * and see if there's more work *
- \*******************************/
- biodone(bp);
- sd_free_xs(unit,xs,0);
- sdstart(unit); /* If there's anything waiting.. do it */
-}
-
-/*******************************************************\
-* ask the scsi driver to perform a command for us. *
-* Call it through the switch table, and tell it which *
-* sub-unit we want, and what target and lu we wish to *
-* talk to. Also tell it where to find the command *
-* and how long it is. *
-* Also tell it where to read/write the data, and how *
-* long the data is supposed to be. If we have a buf *
-* to associate with the transfer, we need that too. *
-\*******************************************************/
-int sd_scsi_cmd(unit,scsi_cmd,cmdlen,data_addr,datalen,timeout,bp,flags)
-
-int unit,flags;
-struct scsi_generic *scsi_cmd;
-int cmdlen;
-int timeout;
-u_char *data_addr;
-int datalen;
-struct buf *bp;
-{
- struct scsi_xfer *xs;
- int retval;
- int s;
- struct sd_data *sd = sd_data[unit];
-
-#ifdef SDDEBUG
- if(scsi_debug & PRINTROUTINES) printf("\nsd_scsi_cmd%d ",unit);
-#endif /*SDDEBUG*/
-
-#ifdef PARANOID
- if(!(sd->sc_sw)) /* If we have a scsi driver */
- {/* How we got here is anyone's guess */
- printf("sd%d: not set up\n",unit);
- return(EINVAL);
- }
-#endif
- xs = sd_get_xs(unit,flags); /* should wait unless booting */
-#ifdef PARANOID
- if(!xs)
- {
- printf("sd_scsi_cmd%d: controller busy"
- " (this should never happen)\n",unit);
- return(EBUSY);
- }
-#endif
- /*******************************************************\
- * Fill out the scsi_xfer structure *
- \*******************************************************/
- xs->flags = INUSE | flags;
- xs->adapter = sd->ctlr;
- xs->targ = sd->targ;
- xs->lu = sd->lu;
- xs->retries = SD_RETRIES;
- xs->timeout = timeout;
- xs->cmd = scsi_cmd;
- xs->cmdlen = cmdlen;
- xs->data = data_addr;
- xs->datalen = datalen;
- xs->resid = datalen;
- xs->when_done = sd_done;
- xs->done_arg = unit;
- xs->done_arg2 = (int)xs;
- xs->bp = bp;
-retry: xs->error = XS_NOERROR;
-
- /*******************************************************\
- * Do the transfer. If we are polling we will return: *
- * COMPLETE, Was poll, and sd_done has been called *
- * HAD_ERROR, Was poll and an error was encountered *
- * TRY_AGAIN_LATER, Adapter short resources, try again *
- * *
- * if under full steam (interrupts) it will return: *
- * SUCCESSFULLY_QUEUED, will do a wakeup when complete *
- * HAD_ERROR, had an erro before it could queue *
- * TRY_AGAIN_LATER, (as for polling) *
- * After the wakeup, we must still check if it succeeded *
- * *
- * If we have a bp however, all the error proccessing *
- * and the buffer code both expect us to return straight *
- * to them, so as soon as the command is queued, return *
- \*******************************************************/
- retval = (*(sd->sc_sw->scsi_cmd))(xs);
- if(bp) return retval; /* will sleep (or not) elsewhere */
-
- /*******************************************************\
- * Only here for non I/O cmds. It's cheaper to process *
- * the error status here than at interrupt time so *
- * sd_done will have done nothing except wake us up. *
- \*******************************************************/
- switch(retval)
- {
- case SUCCESSFULLY_QUEUED:
- s = splbio();
- while(!(xs->flags & ITSDONE))
- sleep(xs,PRIBIO+1);
- splx(s);
- /* fall through to check success of completed command */
-
- case HAD_ERROR:
- switch(xs->error)
- {
- case XS_NOERROR: /* nearly always hit this one */
- retval = ESUCCESS;
- break;
-
- case XS_SENSE:
- retval = (sd_interpret_sense(unit,xs));
- break;
- case XS_BUSY:
- /* should sleep 1 sec here */
- case XS_TIMEOUT:
- if(xs->retries-- )
- {
- xs->flags &= ~ITSDONE;
- goto retry;
- }
- case XS_DRIVER_STUFFUP:
- retval = EIO;
- break;
- default:
- retval = EIO;
- printf("sd%d: unknown error category from scsi driver\n"
- ,unit);
- }
- break;
- case COMPLETE: /* Polling command completed ok */
- retval = ESUCCESS;
- break;
-
- case TRY_AGAIN_LATER: /* adapter resource shortage */
- /* should sleep 1 sec here */
- if(xs->retries-- )
- {
- xs->flags &= ~ITSDONE;
- goto retry;