⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sscsi.c

📁 scsi脚本文件(scripts)编程例子
💻 C
📖 第 1 页 / 共 2 页
字号:
/*--------------------------------------------------*/
/*                                                  */
/* Module SSCSI.C                                   */
/*                                                  */
/* SCSI utility routines for Symbios 53C8XX.        */
/*                                                  */
/* Adapted from Symbios Logic                       */
/*    Software Development Kit                      */
/*                                                  */
/* Project: A Programmer's Guide to SCSI            */
/* Copyright (C) 1997, Brian Sawert.                */
/* All rights reserved.                             */
/*                                                  */
/*--------------------------------------------------*/


#include <stdio.h>
#include <stdlib.h>
#include <mem.h>
#include <dos.h>

#include "gen_tool.h"         // generic tools
#include "spci.h"             // PCI definitions
#include "s8xx.h"             // Symbios 8XX definitions
#include "sscsi.h"            // SCSI utility definitions

#include "genscsi.h"          // compiled SCRIPTS code


/*---------- defines and macros ----------*/

#define TABLE_SIZE 7          // number of table entries

enum table_offsets {          // table offsets
   SCSI_ID = 0,
   MSGOUT_BUF,
   CMD_BUF,
   STAT_BUF,
   MSGIN_BUF,
   EXMSGIN_BUF,
   DATAIN_BUF
};


/*---------- global variables ----------*/

DWORD *pscript;               // pointer to script
table_entry *ptable;          // pointer to table

DWORD scsi_id;                // encoded SCSI ID
BYTE msgout_buf[2];           // message out buffer
BYTE cmd_buf[10];             // command buffer
BYTE stat_buf;                // status byte
BYTE msgin_buf[2];            // message in buffer
BYTE exmsgin_buf[4];          // extended message buffer
BYTE datain_buf[128];         // data in buffer
BYTE block_buf[1024];         // block read buffer
BYTE sense_buf[32];           // sense data buffer
BYTE sense_key;               // sense data
BYTE sense_asc;
BYTE sense_ascq;



/*---------- external variables ----------*/

/*---------- local functions ----------*/

/*---------- external functions ----------*/

/*---------- function definitions ----------*/


/*--------------------------------------------------*/
/*                                                  */
/* Routine to allocate and align buffer.            */
/*                                                  */
/* Usage:   DWORD *alloc_buffer(WORD size);         */
/*                                                  */
/* Parameters:                                      */
/*    size:          size of buffer needed          */
/*                                                  */
/* Return value:                                    */
/*    Returns pointer to aligned buffer on success, */
/*    0 otherwise.                                  */
/*                                                  */
/* Note:                                            */
/*    We never free this buffer, so we don't save   */
/*    the temporary pointer we use to allocate.     */
/*                                                  */
/*--------------------------------------------------*/

DWORD *alloc_buffer(WORD size)
{
   BYTE *pbuf;                // temporary pointer
   WORD seg, off;             // pointer parts
   DWORD *newptr = NULL;


   // allocate buffer
   pbuf = malloc(size + 4);

   if (pbuf) {
   // allocated buffer memory
   // DWORD align the buffer
      seg = FP_SEG(pbuf);
      off = FP_OFF(pbuf);
      off += (4 - (off & 0x03));
      newptr = (DWORD *) MK_FP(seg, off);
   }

   return newptr;
}



/*--------------------------------------------------*/
/*                                                  */
/* Routine to check for completion by polling ISTAT */
/* register.                                        */
/*                                                  */
/* Usage:   int poll_istat(DWORD io_base,           */
/*    DWORD *vector, BYTE *dstat, BYTE *istat,      */
/*    WORD *sist);                                  */
/*                                                  */
/* Parameters:                                      */
/*    io_base:       host I/O base address          */
/*    vector:        pointer to result vector       */
/*    dstat:         pointer to DSTAT buffer        */
/*    istat:         pointer to ISTAT buffer        */
/*    sist:          pointer to SIEN & SIST buffers */
/*                                                  */
/* Return value:                                    */
/*    Returns 1 on success, 0 otherwise.            */
/*                                                  */
/*--------------------------------------------------*/

int poll_istat(DWORD io_base, DWORD *vector,
   BYTE *dstat, BYTE *istat, WORD *sist)
{
	DWORD starttime;
   DWORD tempsist;


   // get start time
   starttime = Get_Time();

   // wait for interrupt or timeout
	while (!(IORead8(io_base + ISTAT) & 0x3)) {
   // no interrupt - check timeout

		if (HasTimeElapsed(starttime, DEF_TIMEOUT)) {
      // time has expired
         return 0;
      }
	}

	// got an interrupt - clear buffers
	*istat = 0;
	*dstat = 0;
	*sist = 0;
	*vector = 0xFFFFFFFFL;

	while (IORead8(io_base + ISTAT) & 0x03) {
	// read all interrupts

		*istat |= IORead8(io_base + ISTAT);

		if (*istat & 0x01) {
      // DMA interrupt occurred
      // read DMA status register
			*dstat |= IORead8(io_base + DSTAT);
      }

		if (*istat & 0x02) {
      // SCSI interrupt occurred
      // read SCSI interrupt registers
			tempsist = (IORead32(io_base + SIEN0));
			*sist |= (WORD) (tempsist >> 16);
      }
	}

   if (*dstat & C8XX_INT_SIR) {
   // a script interrupt occurred
   // get the result vector
		*vector = IORead32(io_base + DSPS);
   }

   // get the DMA FIFO full bit
	*dstat |= IORead8(io_base + DSTAT);

	return(1);
}



/*--------------------------------------------------*/
/*                                                  */
/* Routine to set up script and data buffers.       */
/*                                                  */
/* Usage:   int init_buffers(void);                 */
/*                                                  */
/* Parameters:                                      */
/*    None                                          */
/*                                                  */
/* Return value:                                    */
/*    Returns 1 on success, 0 otherwise.            */
/*                                                  */
/*--------------------------------------------------*/

int init_buffers(void)
{
   int retval = 0;


   // allocate script buffer
   pscript = alloc_buffer(sizeof(GEN_SCRIPT));

   if (pscript) {
   // allocated script memory
      memcpy(pscript, GEN_SCRIPT, sizeof(GEN_SCRIPT));
      
      // allocate table memory
      ptable = (table_entry *) alloc_buffer(TABLE_SIZE *
         sizeof(table_entry));

      if (ptable) {
      // allocated table memory

         // set default select info
         ptable[SCSI_ID].count = 0x33000000L;
         ptable[SCSI_ID].address = 0L;

         // set default message out
         ptable[MSGOUT_BUF].count = 1L; 
         ptable[MSGOUT_BUF].address =
            getPhysAddr(msgout_buf);
  
         // set command buffer
         ptable[CMD_BUF].count =
            sizeof(cmd_buf);
         ptable[CMD_BUF].address =
            getPhysAddr(cmd_buf);

         // set status buffer
         ptable[STAT_BUF].count = 1L;
         ptable[STAT_BUF].address =
            getPhysAddr(&stat_buf);

         // set message in buffer
         ptable[MSGIN_BUF].count = 1L;
         ptable[MSGIN_BUF].address =
            getPhysAddr(msgin_buf);

         // set extended message in buffer
         ptable[EXMSGIN_BUF].count = 2L;
         ptable[EXMSGIN_BUF].address =
            getPhysAddr(exmsgin_buf);

         // set data input buffer
         ptable[DATAIN_BUF].count =
            sizeof(datain_buf);
         ptable[DATAIN_BUF].address =
            getPhysAddr(datain_buf);
      
         retval = 1;
      }
   }

   return retval;
}



/*--------------------------------------------------*/
/*                                                  */
/* Routine to check status and retrieve sense       */
/* data if available.                               */
/*                                                  */
/* Usage:   int check_status(                       */
/*    pci_device *ppcidev,                          */
/*    scsi_device *pscsidev);                       */
/*                                                  */
/* Parameters:                                      */
/*    ppcidev:       pointer to PCI device          */
/*    pscsidev:      pointer to target SCSI device  */
/*                                                  */
/* Return value:                                    */
/*    Returns error code defined in SSCSI.H         */
/*                                                  */
/*--------------------------------------------------*/

int check_status(pci_device *ppcidev,
   scsi_device *pscsidev)
{
   int retval = ERR_OTHER;


   switch (stat_buf) {
   // handle status codes
      case STAT_GOOD:
      // command successful
         retval = ERR_SUCCESS;
         break;
         
      case STAT_CHECK_CONDITION:
      // sense data available
         
         if (request_sense(ppcidev,
            pscsidev) == ERR_SUCCESS) {
         // got sense data

            sense_key = sense_asc = sense_ascq = 0;

            if ((sense_buf[0] & 0x7E) == 0x70) {
            // valid sense data
               sense_key = (sense_buf[2] & 0x0F);
               sense_asc = sense_buf[12];
               sense_ascq = sense_buf[13];
            }

            retval = ERR_SENSE;
         }

         break;

      default:
         break;
   }

   return retval;
}



/*--------------------------------------------------*/
/*                                                  */
/* Routine to execute Test Unit Ready command.      */
/*                                                  */
/* Usage:   int test_unit_ready(                    */
/*    pci_device *ppcidev,                          */
/*    scsi_device *pscsidev);                       */
/*                                                  */
/* Parameters:                                      */
/*    ppcidev:       pointer to PCI device          */
/*    pscsidev:      pointer to target SCSI device  */
/*                                                  */
/* Return value:                                    */
/*    Returns error code defined in SSCSI.H         */
/*                                                  */
/*--------------------------------------------------*/

int test_unit_ready(pci_device *ppcidev,
   scsi_device *pscsidev)
{
   int retval= ERR_OTHER;
	BYTE dstat, istat;
	WORD sist;
	DWORD vector;


	// set the DSA register to the table address
	IOWrite32(ppcidev->io_base + DSA,
      getPhysAddr(ptable));

	// set selection info
   ptable[SCSI_ID].count =
      (0x0300L | pscsidev->targ_id) << 16;

   // set identify message
   ptable[MSGOUT_BUF].count = 1L; 
   msgout_buf[0] = 0x80;

   // set command buffer for Test Unit Ready
   memset(cmd_buf, 0, sizeof(cmd_buf));

   ptable[CMD_BUF].count = 6L;
   cmd_buf[0] = CMD_TEST_UNIT_READY;

	// start script execution
	IOWrite32(ppcidev->io_base + DSP,
      getPhysAddr(pscript) + Ent_start_scsi);
	
   // wait for interrupt to complete
	if (poll_istat(ppcidev->io_base,
      &vector, &dstat, &istat, &sist)) {
   // check interrupt type

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -