Your drvopen() routine should first use scsi_info to determine whether a device is present on the SCSI bus and to examine the inquiry information to see what type of device it is. Remember, SCSI target 3 may be a disk on one system but a tape drive on another. So be sure to check the inquiry information to determine whether your driver is appropriate to the device in question.
After your driver has determined that it is appropriate to talk to a device, it must then use scsi_alloc to initialize a connection between your device driver and the host adapter driver.
Your driver can free the connection by using scsi_free. Remember that if your driver uses the exclusive option, no other SCSI device driver can communicate with a target until your driver calls scsi_free. Similarly, if your driver uses a sense callback, no other driver can use a sense callback until your driver calls scsi_free, although other drivers that do not need a sense callback may still communicate with the target.
Because the IRIX SCSI interface transfers data using direct memory access (DMA) only, your driver must use the kernel routine physio() and a drvstrategy() routine for SCSI I/O to transfer data to pages that a user process is using. Internally generated requests that transfer data into kernel memory (either statically allocated at compile time in the driver or allocated through kmem_alloc() or similar functions) do not need to use physio(). However, in this case your driver must do its own cache flushing.
When filling out a scsi_request structure in preparation for a call to scsi_command, be sure to fill out the sr_ctlr, sr_target, sr_lun, and sr_tag fields with appropriate values. The sr_command field must point to an array of characters filled out with the SCSI command byte values, and sr_cmdlen must be the length of the command. sr_flags is used to specify the direction of data transfer, if any, whether cache flushes need to be done, and what kind of mapping needs to be done. If the data transfer involves direct mapped K0SEG or K1SEG memory, then no mapping need be specified, although the host adapter may still perform some mapping. The flags must also acknowledge an error by setting the SRF_AEN_ACK bit on the next command or the command will fail immediately.
sr_timeout must be the command timeout in clock ticks (defined by Hz), typically 1/100 of a second.[13] sr_buffer must be a pointer to the start of the buffer to be transferred to, unless there is no data transfer or the SRF_MAPBP flag in sr_flags is set, in which case sr_buffer can be NULL. sr_buflen must be an amount equal to the maximum amount of data to be transferred in the command.
If your driver wants to examine sense data from a request sense caused by a check condition that occurs as a result of the command you issued, it can set the sr_sense field to point to such a buffer, with sr_senselen set to the size of the buffer. The sr_notify must point to your driver "interrupt" routine. This is not a real interrupt routine--it is called indirectly as a result of an interrupt from the interrupt handler--so it can have any name you desire. This routine is called when the host adapter driver has completed processing your command.
If the SRF_MAPBP flag is set, sr_bp must point to the buf structure that generated the SCSI request. Sometimes your driver strategy function will get a buf that is not mapped into kernel virtual memory. In this case, BP_ISMAPPED(bp), where bp is a pointer to the buf, will return false. If SRF_MAPBP is not used, sr_bp is free to be used by your driver for other purposes. sr_dev is always a spare field usable by your driver, often for linking lists of active or queued requests or to keep special information.
After your notify function is called, your driver must check the sr_status, sr_scsi_status, and sr_sensegotten fields to see whether there were any errors. See /usr/include/sys/scsi.h for additional information on return values for the sr_status field. The sr_scsi_status field corresponds to the SCSI status byte that a target sends at the end of every command. However, if a target sends a check condition (status 2), a request sense is issued instead; otherwise sr_scsi_status is 0. sr_sensegotten is nonzero: -1 if there is an error getting sense data or the amount of sense data actually received. Otherwise, sr_resid will be the difference between sr_buflen and the amount of data actually transferred.