These haven't been use for a long time. Move 'em to the attic.

This commit is contained in:
matt 2002-03-31 07:32:18 +00:00
parent a5b7362c83
commit 15bab55a0c
4 changed files with 0 additions and 1080 deletions

View File

@ -1,297 +0,0 @@
/* $NetBSD: scsi_hi.c,v 1.1 1996/08/02 11:22:31 ragge Exp $ */
/****************************************************************************
* NS32K Monitor SCSI high-level driver
* Bruce Culbertson
* 8 March 1990
* (This source is public domain source)
*
* There are three monitor SCSI commands. "Read" and "write" I think are
* fairly self explanatory once you read the help messages. They, in fact,
* execute the "extended read", "extended write", and "request sense"
* commands from the SCSI standard.
*
* "Raw" lets you execute any SCSI command but you need a SCSI reference to
* know what the commands are and what their formats are. The SCSI
* standard specifies that there are six buffers which, for example, hold a
* SCSI command or are the source or destination for data. You provide
* "raw" with an array of pointers to the six buffers. Using "edit", you
* can enter a SCSI command somewhere in memory and you can create the
* array of pointers. The array must actually be eight entries long; two
* entries are not used. By typing "raw <array address>", the SCSI command
* is executed.
*
* By the way, "read", "write", and "raw" talk only to the DP8490 SCSI
* controller. I have not had time to read the Adaptec data sheet and
* write a driver for it.
****************************************************************************/
#include "so.h"
#define OK 0
#define NOT_OK OK+1
#define PRIVATE
#define PUBLIC
#define U8 unsigned char
long scsiAdr = DEFAULT_SCSI_ADR, /* default SCSI address */
scsiLun = DEFAULT_SCSI_LUN;
struct cmd_desc { /* SCSI command description */
const U8 *cmd; /* command string */
const U8 *odata; /* data to output, if any */
const struct cmd_desc *chain; /* next command */
};
struct drive { /* SCSI drive description */
U8 adr, lun; /* SCSI address and LUN */
U8 flags; /* drive characteristics */
U8 stat; /* drive state */
const struct cmd_desc *init; /* list of initialize commands */
};
/* for drive.flags */
#define EXTENDED_RDWR 1 /* device does extended read, write */
#define EXTENDED_SENSE 2 /* device does extended sense */
/* for drive.stat */
#define INITIALIZED 1 /* device is initialized */
PRIVATE struct drive drive_tbl[] = {
#if 1
{0, 0, 0, 1, 0},
{1, 0, 0, 1, 0},
{2, 0, 0, 1, 0},
{3, 0, 0, 1, 0},
{4, 0, 0, 1, 0},
{5, 0, 0, 1, 0},
{6, 0, 0, 1, 0},
{7, 0, 0, 1, 0},
#else
{0, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
{1, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
{2, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
{3, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
{4, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
{5, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
{6, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
{7, 0, EXTENDED_RDWR | EXTENDED_SENSE, 1, 0},
#endif
};
#define DRV_TBL_SZ (sizeof (drive_tbl) / sizeof (struct drive))
/* Round up to multiple of four since SCSI transfers are always multiples
* of four bytes.
*/
#define CMD_LEN 12 /* longest SCSI command */
#define SENSE_LEN 24 /* extended sense length */
#define MSG_LEN 4
#define STAT_LEN 4
#define MAX_SCSI_RETRIES 6
#define CMD_IX 2
#define CMD_SENSE 0x03
#define CMD_READ 0x08
#define CMD_WRITE 0x0a
#define CMD_XREAD 0x28
#define CMD_XWRITE 0x2a
PRIVATE U8 cmd_buf[CMD_LEN];
#define SENSE_KEY 2
#define NO_SENSE 0
#define RECOVERY_ERR 1
#define UNIT_ATTN 6
#define ADD_SENSE_CODE 12
#define SENSE_RST 0x29
PRIVATE U8 sense_buf[SENSE_LEN];
#define CHECK_CONDITION 2
#define STAT_IX 3
#define STAT_MASK 0x1f
PRIVATE U8 stat_buf[STAT_LEN];
#define IMSG_IX 7
PRIVATE U8 msg_buf[MSG_LEN];
#define ODATA_IX 0
#define IDATA_IX 1
PRIVATE struct scsi_args scsi_args;
/*===========================================================================*
* sc_rdwt *
*===========================================================================*/
/* Carry out a read or write request for the SCSI disk. */
PRIVATE int
sc_rdwt(op, block, ram_adr, len, sc_adr, lun)
long block, ram_adr, len, sc_adr, lun;
{
int retries, ret;
U8 *p;
struct drive *dp;
printf ("sc_rdwt: op %x, block %d, ram %x, len %d, sc_adr %d, lun %d\n",
op, block, ram_adr, len, sc_adr, lun);
/* get drive characteristics */
for (dp = drive_tbl; dp < drive_tbl + DRV_TBL_SZ - 1; ++dp)
if (dp->adr == sc_adr && dp->lun == lun) break;
if (dp == drive_tbl + DRV_TBL_SZ - 1) {
dp->adr = sc_adr; /* have default, set adr, lun */
dp->lun = lun;
}
for (retries = 0; retries < MAX_SCSI_RETRIES; ++retries) {
if (dp->init && !(dp->stat & INITIALIZED))
if (OK != sc_initialize (dp)) {
printf("SCSI cannot initialize device\n");
return NOT_OK;
}
p = cmd_buf; /* build SCSI command */
if (dp->flags & EXTENDED_RDWR) { /* use extended commands */
*p++ = (op == DISK_READ)? CMD_XREAD: CMD_XWRITE;
*p++ = lun << 5;
*p++ = (block >> 24) & 0xff;
*p++ = (block >> 16) & 0xff;
*p++ = (block >> 8) & 0xff;
*p++ = (block >> 0) & 0xff;
*p++ = 0;
*p++ = (len >> 8) & 0xff;
*p++ = (len >> 0) & 0xff;
*p = 0;
} else { /* use short (SASI) commands */
*p++ = (op == DISK_READ)? CMD_READ: CMD_WRITE;
*p++ = (lun << 5) | ((block >> 16) & 0x1f);
*p++ = (block >> 8) & 0xff;
*p++ = (block >> 0) & 0xff;
*p++ = len;
*p = 0;
}
if (op == DISK_READ)
ret = exec_scsi_hi (cmd_buf, (U8 *)ram_adr, (U8 *)0, dp);
else
ret = exec_scsi_hi (cmd_buf, (U8 *)0, (U8 *)ram_adr, dp);
if (OK == ret) return OK;
dp->stat &= ~INITIALIZED;
}
printf("SCSI %s, block %d failed even after retries\n",
op == DISK_READ? "READ": "WRITE", block);
return NOT_OK;
}
/*===========================================================================*
* sc_initialize *
*===========================================================================*/
/* Execute the list of initialization commands for the given drive.
*/
int
sc_initialize (dp)
struct drive *dp;
{
const struct cmd_desc *cp;
for (cp = dp->init; cp != 0; cp = cp->chain)
if (OK != exec_scsi_hi (cp->cmd, 0, cp->odata, dp)) {
dp->stat &= ~INITIALIZED;
return NOT_OK;
}
dp->stat |= INITIALIZED;
return OK;
}
/*===========================================================================*
* exec_scsi_hi *
*===========================================================================*/
/* Execute a "high-level" SCSI command. This means execute a low level
* command and, if it fails, execute a request sense to find out why.
*/
PRIVATE int
exec_scsi_hi(cmd, data_in, data_out, dp)
U8 *cmd, *data_out, *data_in;
struct drive *dp;
{
scsi_args.ptr[CMD_IX] = (long)cmd;
scsi_args.ptr[STAT_IX] = (long)stat_buf;
scsi_args.ptr[IMSG_IX] = (long)msg_buf;
scsi_args.ptr[IDATA_IX] = (long)data_in;
scsi_args.ptr[ODATA_IX] = (long)data_out;
if (OK != exec_scsi_low (&scsi_args, dp->adr))
return NOT_OK;
*stat_buf &= STAT_MASK; /* strip off lun */
if (*stat_buf == 0)
/* Success -- this should be the usual case */
return OK;
if (*stat_buf != CHECK_CONDITION) {
/* do not know how to handle this so return error */
printf("SCSI device returned unknown status: %d\n", *stat_buf);
return NOT_OK;
}
/* Something funny happened, need to execute request-sense command
* to learn more.
*/
if (OK == get_sense(dp))
/* Something funny happened, but the device recovered from it and
* the command succeeded.
*/
return OK;
return NOT_OK;
}
/*===========================================================================*
* get_sense *
*===========================================================================*/
/* Execute a "request sense" SCSI command and check results. When a SCSI
* command returns CHECK_CONDITION, a request-sense command must be executed.
* A request-sense command provides information about the original command.
* The original command might have succeeded, in which case it does not
* need to be retried and OK is returned. Examples: read error corrected
* with error correction code, or error corrected by retries performed by
* the SCSI device. The original command also could have failed, in
* which case NOT_OK is returned.
*/
#define XLOGICAL_ADR \
(sense_buf[3]<<24 | sense_buf[4]<<16 | sense_buf[5]<<8 | sense_buf[6])
#define LOGICAL_ADR \
(sense_buf[1]<<16 | sense_buf[2]<<8 | sense_buf[3])
PRIVATE int
get_sense (dp)
struct drive *dp;
{
U8 *p;
p = cmd_buf; /* build SCSI command */
*p++ = CMD_SENSE;
*p++ = dp->lun << 5;
*p++ = 0;
*p++ = 0;
*p++ = (dp->flags & EXTENDED_SENSE)? SENSE_LEN: 0;
*p = 0;
scsi_args.ptr[IDATA_IX] = (long)sense_buf;
scsi_args.ptr[ODATA_IX] = 0;
scsi_args.ptr[CMD_IX] = (long)cmd_buf;
scsi_args.ptr[STAT_IX] = (long)stat_buf;
scsi_args.ptr[IMSG_IX] = (long)msg_buf;
if (OK != exec_scsi_low (&scsi_args, dp->adr)) {
printf("SCSI SENSE command failed\n");
return NOT_OK;
}
if ((*stat_buf & STAT_MASK) != 0) {
printf("SCSI SENSE returned wrong status %d\n", *stat_buf);
return NOT_OK;
}
if (0 == (dp->flags & EXTENDED_SENSE)) {
printf("SCSI request sense, code 0x%x, log_adr 0x%x\n",
sense_buf[0], LOGICAL_ADR);
return NOT_OK;
}
switch (sense_buf[SENSE_KEY] & 0xf) {
case NO_SENSE:
case UNIT_ATTN: /* reset */
return NOT_OK; /* must retry command */
case RECOVERY_ERR:
/* eventually, we probably do not want to hear about these. */
printf("SCSI ok with recovery, code 0x%x, logical address 0x%x\n",
sense_buf[ADD_SENSE_CODE], XLOGICAL_ADR);
return OK; /* orig command was ok with recovery */
default:
printf("SCSI failure: key 0x%x code 0x%x log adr 0x%x sense buf 0x%x\n",
sense_buf[SENSE_KEY], sense_buf[ADD_SENSE_CODE],
XLOGICAL_ADR, sense_buf);
return NOT_OK; /* orig command failed */
}
}

View File

@ -1,479 +0,0 @@
/* $NetBSD: scsi_low.c,v 1.1 1996/08/02 11:22:34 ragge Exp $ */
/****************************************************************************
* NS32K Monitor SCSI low-level driver
* Bruce Culbertson
* 8 March 1990
* (This source is public domain source.)
*
* Originally written by Bruce Culbertson for a ns32016 port of Minix.
* Adapted from that for the pc532 (ns32632) monitor.
* Adapted from that for NetBSD/pc532 by Philip L. Bunde.
*
* Do not use DMA -- makes 32016 and pc532 versions compatible.
* Do not use interrupts -- makes it harder for the user code to bomb
* this code.
****************************************************************************/
#include "so.h"
#include "ka410.h"
#define BB_DEBUG(x) printf x
#define CLEAR_INTR() *ka410_intclr=INTR_SC
#define CHECK_INTR() *ka410_intreq&INTR_SC
#define OK 0
#define NOT_OK OK+1
#define PRIVATE
#define PUBLIC
#define WR_ADR(adr,val) (*((volatile unsigned char *)(adr))=(val))
#define RD_ADR(adr) (*((volatile unsigned char *)(adr)))
/* #define AIC6250 0 */
/* #define DP8490 1 */
#define MAX_CACHE 0x4000
/* SCSI bus phases
*/
#define PH_ODATA 0
#define PH_IDATA 1
#define PH_CMD 2
#define PH_STAT 3
#define PH_IMSG 7
#define PH_NONE 8
#define PH_IN(phase) ((phase) & 1)
/* NCR5380 SCSI controller registers
*/
#define SC_CTL 0x200C0080 /* base for control registers */
#define SC_DMA 0x200D0000 /* base for data registers (8/16K) */
#define SC_CURDATA SC_CTL+(4*0)
#define SC_OUTDATA SC_CTL+(4*0)
#define SC_ICMD SC_CTL+(4*1)
#define SC_MODE SC_CTL+(4*2)
#define SC_TCMD SC_CTL+(4*3)
#define SC_STAT1 SC_CTL+(4*4)
#define SC_STAT2 SC_CTL+(4*5)
#define SC_START_SEND SC_CTL+(4*5)
#define SC_INDATA SC_CTL+(4*6)
#define SC_RESETIP SC_CTL+(4*7)
#define SC_START_RCV SC_CTL+(4*7)
/* Bits in NCR5380 registers
*/
#define SC_A_RST 0x80
#define SC_A_SEL 0x04
#define SC_S_SEL 0x02
#define SC_S_REQ 0x20
#define SC_S_BSY 0x40
#define SC_S_BSYERR 0x04
#define SC_S_PHASE 0x08
#define SC_S_IRQ 0x10
#define SC_S_DRQ 0x40
#define SC_M_DMA 0x02
#define SC_M_BSY 0x04
#define SC_ENABLE_DB 0x01
/* Status of interrupt routine, returned in m1_i1 field of message.
*/
#define ISR_NOTDONE 0
#define ISR_OK 1
#define ISR_BSYERR 2
#define ISR_RSTERR 3
#define ISR_BADPHASE 4
#define ISR_TIMEOUT 5
#define ICU_ADR 0xfffffe00
#define ICU_IO (ICU_ADR+20)
#define ICU_DIR (ICU_ADR+21)
#define ICU_DATA (ICU_ADR+19)
#define ICU_SCSI_BIT 0x80
/* Miscellaneous
*/
#define MAX_WAIT (1000*1000)
#define SC_LOG_LEN 32
PRIVATE struct scsi_args *sc_ptrs;
PRIVATE char sc_cur_phase,
sc_reset_done = 1,
sc_have_msg,
sc_accept_int,
sc_dma_dir;
long sc_dma_port = SC_DMA,
sc_dma_adr;
#ifdef DEBUG
struct sc_log {
unsigned char stat1, stat2;
} sc_log [SC_LOG_LEN],
*sc_log_head = sc_log;
int sc_spurious_int;
#endif
unsigned char
sc_watchdog_error; /* watch dog error */
/* error messages */
char *scsi_errors[] = {
0, /* ISR_NOTDONE */
0, /* ISR_OK */
"busy error", /* ISR_BSYERR */
"reset error", /* ISR_RSTERR */
"NULL pointer for current phase", /* ISR_BADPHASE */
"timeout", /* ISR_TIMEOUT */
};
/*===========================================================================*
* exec_scsi_low *
*===========================================================================*/
/* Execute a generic SCSI command. Passed pointers to eight buffers:
* data-out, data-in, command, status, dummy, dummy, message-out, message-in.
*/
PUBLIC
int
exec_scsi_low (args, scsi_adr)
struct scsi_args *args;
long scsi_adr;
{
int ret;
BB_DEBUG (("exec_scsi_low(0x%x, %d)\n", args, scsi_adr));
sc_ptrs = args; /* make pointers globally accessible */
/* bertram ??? scCtlrSelect (DP8490); */
if (!sc_reset_done) sc_reset();
/* TCMD has some undocumented behavior in initiator mode. I think the
* data bus cannot be enabled if i/o is asserted.
*/
WR_ADR (SC_TCMD, 0);
if (OK != sc_wait_bus_free ()) { /* bus-free phase */
printf("SCSI: bus not free\n");
return NOT_OK;
}
sc_cur_phase = PH_NONE;
sc_have_msg = 0;
if (OK != sc_select (scsi_adr)) /* select phase */
return NOT_OK;
sc_watchdog_error = 0;
ret = sc_receive (); /* isr does the rest */
if (ret == ISR_OK) return OK;
else {
sc_reset();
printf("SCSI: %s\n", scsi_errors[ret]);
return NOT_OK;
}
}
/*===========================================================================*
* sc_reset *
*===========================================================================*/
/*
* Reset SCSI bus.
*/
PRIVATE
sc_reset()
{
volatile int i;
BB_DEBUG (("sc_reset()\n"));
WR_ADR (SC_MODE, 0); /* get into harmless state */
WR_ADR (SC_OUTDATA, 0);
WR_ADR (SC_ICMD, SC_A_RST); /* assert RST on SCSI bus */
i = 200; /* wait 25 usec */
while (i--);
WR_ADR (SC_ICMD, 0); /* deassert RST, get off bus */
sc_reset_done = 1;
}
/*===========================================================================*
* sc_wait_bus_free *
*===========================================================================*/
PRIVATE int
sc_wait_bus_free()
{
int i = MAX_WAIT;
volatile int j;
BB_DEBUG (("sc_wait_bus_free()\n"));
while (i--) {
/* Must be clear for 2 usec, so read twice */
if (RD_ADR (SC_STAT1) & (SC_S_BSY | SC_S_SEL)) continue;
for (j = 0; j < 25; ++j);
if (RD_ADR (SC_STAT1) & (SC_S_BSY | SC_S_SEL)) continue;
return OK;
}
sc_reset_done = 0;
return NOT_OK;
}
/*===========================================================================*
* sc_select *
*===========================================================================*/
/* This duplicates much of the work that the interrupt routine would do on a
* phase mismatch and, in fact, the original plan was to just do the select,
* let a phase mismatch occur, and let the interrupt routine do the rest.
* That didn't work because the 5380 did not reliably generate the phase
* mismatch interrupt after selection.
*/
PRIVATE int
sc_select(adr)
long adr;
{
int i, stat1;
long new_ptr;
BB_DEBUG (("sc_select(%d)\n", adr));
CLEAR_INTR();
WR_ADR (SC_OUTDATA, adr); /* SCSI bus address */
WR_ADR (SC_ICMD, SC_A_SEL | SC_ENABLE_DB);
for (i = 0;; ++i) { /* wait for target to assert SEL */
if (CHECK_INTR() == 0)
continue;
stat1 = RD_ADR (SC_STAT1);
if (stat1 & SC_S_BSY) break; /* select successful */
if (i > MAX_WAIT) { /* timeout */
printf("SCSI: SELECT timeout\n");
sc_reset();
return NOT_OK;
}
}
CLEAR_INTR();
WR_ADR (SC_ICMD, 0); /* clear SEL, disable data out */
WR_ADR (SC_OUTDATA, 0);
for (i = 0;; ++i) { /* wait for target to assert REQ */
if (CHECK_INTR() == 0)
continue;
if (stat1 & SC_S_REQ) break; /* target requesting transfer */
if (i > MAX_WAIT) { /* timeout */
printf("SCSI: REQ timeout\n");
sc_reset();
return NOT_OK;
}
stat1 = RD_ADR (SC_STAT1);
}
sc_cur_phase = (stat1 >> 2) & 7; /* get new phase from controller */
if (sc_cur_phase != PH_CMD) {
printf("SCSI: bad phase = %d\n", sc_cur_phase);
sc_reset();
return NOT_OK;
}
new_ptr = sc_ptrs->ptr[PH_CMD];
if (new_ptr == 0) {
printf("SCSI: NULL command pointer\n");
sc_reset();
return NOT_OK;
}
sc_accept_int = 1;
sc_dma_setup (DISK_WRITE, new_ptr);
CLEAR_INTR();
WR_ADR (SC_TCMD, PH_CMD);
WR_ADR (SC_ICMD, SC_ENABLE_DB);
WR_ADR (SC_MODE, SC_M_BSY | SC_M_DMA);
WR_ADR (SC_START_SEND, 0);
return OK;
}
/*===========================================================================*
* scsi_interrupt *
*===========================================================================*/
/* SCSI interrupt handler.
*/
PUBLIC
int
scsi_interrupt()
{
unsigned char stat2, dummy;
long new_ptr;
int ret = ISR_NOTDONE;
BB_DEBUG (("scsi_interrupt()\n"));
stat2 = RD_ADR (SC_STAT2); /* get status before clearing request */
# ifdef DEBUG /* debugging log of interrupts */
sc_log_head->stat1 = RD_ADR (SC_STAT1);
sc_log_head->stat2 = stat2;
if (++sc_log_head >= sc_log + SC_LOG_LEN) sc_log_head = sc_log;
sc_log_head->stat1 = sc_log_head->stat2 = 0xff;
# endif
for (;;) {
dummy = RD_ADR (SC_RESETIP); /* clear interrupt request */
if (!sc_accept_int || /* return if spurious interrupt */
(!sc_watchdog_error &&
(stat2 & SC_S_BSYERR) == 0 && (stat2 & SC_S_PHASE) != 0))
{
# ifdef DEBUG
++sc_spurious_int;
# endif
printf ("sc_spurious_int\n");
return ret;
}
RD_ADR (SC_MODE) &= ~SC_M_DMA; /* clear DMA mode */
WR_ADR (SC_ICMD, 0); /* disable data bus */
if (sc_cur_phase != PH_NONE) { /* if did DMA, save the new pointer */
new_ptr = sc_dma_adr; /* fetch new pointer from DMA cntlr */
if (sc_cur_phase == PH_IMSG && /* have message? */
new_ptr != sc_ptrs->ptr[PH_IMSG]) sc_have_msg = 1;
sc_ptrs->ptr[sc_cur_phase] = /* save pointer */
new_ptr;
}
if (sc_watchdog_error) ret = ISR_TIMEOUT;
else if (stat2 & SC_S_BSYERR) { /* target deasserted BSY? */
printf ("target deasserted BSY?\n");
if (sc_have_msg) ret = ISR_OK;
else ret = ISR_BSYERR;
} else if (!(stat2 & SC_S_PHASE)) {/* if phase mismatch, setup new phase */
printf ("phase mismatch\n");
sc_cur_phase = /* get new phase from controller */
(RD_ADR (SC_STAT1) >> 2) & 7;
new_ptr = sc_ptrs->ptr[sc_cur_phase];
if (new_ptr == 0) ret = ISR_BADPHASE;
else {
WR_ADR (SC_TCMD, sc_cur_phase); /* write new phase into TCMD */
if (PH_IN (sc_cur_phase)) { /* set DMA controller */
sc_dma_setup (DISK_READ, new_ptr);
RD_ADR (SC_MODE) |= SC_M_DMA;
CLEAR_INTR();
WR_ADR (SC_START_RCV, 0); /* tell SCSI to start DMA */
} else {
sc_dma_setup (DISK_WRITE, new_ptr);
RD_ADR (SC_MODE) |= SC_M_DMA;
WR_ADR (SC_ICMD, SC_ENABLE_DB);
CLEAR_INTR();
WR_ADR (SC_START_SEND, 0);
}
}
} else ret = ISR_RSTERR;
if (ret != ISR_NOTDONE) { /* if done, send message to task */
sc_watchdog_error = 0;
sc_accept_int = 0;
WR_ADR (SC_MODE, 0); /* clear monbsy, dma */
break; /* reti re-enables ints */
}
if (0 == ((stat2 = /* check for another interrupt */
RD_ADR (SC_STAT2)) & SC_S_IRQ))
{
break;
}
}
return ret;
}
/*===========================================================================*
* sc_dma_setup *
*===========================================================================*/
/* Fake DMA setup. Just store pointers and direction in global variables.
*
* The pseudo-DMA is subtler than it looks because of the cache.
*
* 1) When accessing I/O devices through a cache, some mechanism is
* necessary to ensure you access the device rather than the cache.
* On the 32532, the IODEC signal is supposed to be asserted for I/O
* addresses to accomplish this. However, a bug makes this much
* slower than necessary and severely hurts pseudo-DMA performance.
* Hence, IODEC is not asserted for the SCSI DMA port.
*
* 2) Because of (1), we must devise our own method of forcing the
* SCSI DMA port to be read. 0x8000000 addresses have been decoded
* to all access this port. By always using new addresses to access
* the DMA port (wrapping only after reading MAX_CACHE bytes), we
* force cache misses and, hence, device reads. Since the cache
* is write-through, we do not need to worry about writes.
*
* 3) It is possible to miss the last few bytes of a transfer if
* bus transfer size is not considered. The loop in sc_receive()
* transfers data until the interrupt signal is asserted. If
* bytes are transferred, the attempt to move the first byte of a
* double word causes the whole word to be read into the cache.
* Then the byte is transferred. If reading the double word
* completed the SCSI transfer, then the loop exits since
* interrupt is asserted. However, the last few bytes have only
* been moved into the cache -- they have not been moved to the
* DMA destination.
*
* 4) It is also possible to miss the first few bytes of a transfer.
* If the address used to access pseudo-dma port is not double word
* aligned, the whole double word is read into the cache, and then
* data is moved from the middle of the word (i.e. something other
* than the first bytes read from the SCSI controller) by the
* pseudo-dma loop in sc_receive().
*/
sc_dma_setup (dir, adr)
int dir;
long adr;
{
BB_DEBUG (("sc_dma_setup(%d, %d)\n", dir, adr));
CLEAR_INTR();
/* if (sc_dma_port > SC_DMA + MAX_CACHE) */
sc_dma_port = SC_DMA;
sc_dma_dir = dir;
sc_dma_adr = adr;
}
/*===========================================================================*
* sc_receive *
*===========================================================================*/
/* Replacement for Minix receive(), which waits for a message. This code
* spins, waiting for data to transfer or interrupt requests to handle.
* See sc_dma_setup for details.
*/
int
sc_receive()
{
int stat2, isr_ret;
int i, c;
BB_DEBUG (("sc_receive()\n"));
/*
* check the interrupt-flag and wait if it reappears...
*/
c = *ka410_intreq;
printf ("begin: %x/%x ", c, *ka410_intreq);
for (i=0; i<100; i++) {
if ((c = *ka410_intreq) & INTR_SC)
break;
printf (" %x ", c);
}
if (i==100)
printf ("timeout in sc_receive.\n");
#if 1
for (;;) {
stat2 = RD_ADR (SC_STAT2);
if (stat2 & SC_S_IRQ) {
if (ISR_NOTDONE != (isr_ret = scsi_interrupt())) break;
} else if (stat2 & SC_S_DRQ) { /* test really not necessary on pc532 */
if (sc_dma_dir == DISK_READ)
*((long *)sc_dma_adr)++ = *((volatile long *)sc_dma_port)++;
else *((volatile long *)sc_dma_port)++ = *((long *)sc_dma_adr)++;
}
}
#endif
printf ("isr_ret: %d (ISR_NOTDONE: %d)\n", isr_ret, ISR_NOTDONE);
return isr_ret;
}
/*===========================================================================*
* scCtlrSelect
*===========================================================================*/
/* Select a SCSI device.
*/
scCtlrSelect (ctlr)
int ctlr;
{
BB_DEBUG (("scCtlrSelect()\n"));
#if 0
RD_ADR (ICU_IO) &= ~ICU_SCSI_BIT; /* i/o, not port */
RD_ADR (ICU_DIR) &= ~ICU_SCSI_BIT; /* output */
if (ctlr == DP8490)
RD_ADR (ICU_DATA) &= ~ICU_SCSI_BIT; /* select = 0 for 8490 */
else
RD_ADR (ICU_DATA) |= ICU_SCSI_BIT; /* select = 1 for AIC6250 */
#endif
}

View File

@ -1,247 +0,0 @@
/* $NetBSD: sd.c,v 1.1 1996/08/02 11:22:36 ragge Exp $ */
/*
* Copyright (c) 1988 University of Utah.
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Van Jacobson of Lawrence Berkeley Laboratory and the Systems
* Programming Group of the University of Utah Computer Science Department.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: Utah $Hdr: sd.c 1.9 92/12/21$
*
* @(#)sd.c 8.1 (Berkeley) 6/10/93
*/
/*
* SCSI CCS disk driver
*/
#include <sys/param.h>
#include <sys/disklabel.h>
#include "stand.h"
#include "samachdep.h"
#define SC_DEBUG 1 /* bertram */
#define SD_DEBUG 1 /* bertram */
/*----------------------------------------------------------------------*/
int
scsialive(int ctlr)
{
return 1; /* controller always alive! */
}
/* call functions in scsi_hi.c */
#include "so.h"
int
scsi_tt_read(ctlr, slave, buf, len, blk, nblk)
int ctlr, slave;
u_char *buf;
u_int len;
daddr_t blk;
u_int nblk;
{
#ifdef SC_DEBUG
printf("scsi_tt_read: ctlr %d, slave %d, len %d, blk %d, nblk %d\n",
ctlr, slave, len, blk, nblk );
#endif
if (sc_rdwt(DISK_READ, blk, buf, nblk, 1<<slave, 0) == 0)
return 0;
return -2;
}
int
scsi_tt_write(ctlr, slave, buf, len, blk, nblk)
int ctlr, slave;
u_char *buf;
u_int len;
daddr_t blk;
u_int nblk;
{
#ifdef SC_DEBUG
printf("scsi_tt_write: ctlr %d, slave %d, len %d, blk %d, nblk %d\n",
ctlr, slave, len, blk, nblk );
#endif
#if 0
if (sc_rdwt(DISK_WRITE, blk, buf, nblk, 1<<slave, 0) == 0)
return 0;
#endif
return -2;
}
/*----------------------------------------------------------------------*/
struct sd_softc {
int sc_ctlr;
int sc_unit;
int sc_part;
char sc_retry;
char sc_alive;
struct disklabel sc_label;
} sd_softc[NSCSI][NSD];
#ifdef SD_DEBUG
int debug = SD_DEBUG;
#endif
#define SDRETRY 2
sdinit(ctlr, unit)
int ctlr, unit;
{
register struct sd_softc *ss = &sd_softc[ctlr][unit];
/* HP version does test_unit_ready
* followed by read_capacity to get blocksize
*/
ss->sc_alive = 1;
return (1);
}
sdreset(ctlr, unit)
int ctlr, unit;
{
}
char io_buf[MAXBSIZE];
sdgetinfo(ss)
register struct sd_softc *ss;
{
register struct disklabel *lp;
char *msg, *getdisklabel();
int sdstrategy(), i, err;
lp = &sd_softc[ss->sc_ctlr][ss->sc_unit].sc_label;
bzero((caddr_t)lp, sizeof *lp);
lp->d_secsize = DEV_BSIZE;
lp->d_secpercyl = 1;
lp->d_npartitions = MAXPARTITIONS;
lp->d_partitions[ss->sc_part].p_offset = 0;
lp->d_partitions[ss->sc_part].p_size = 0x7fffffff;
if (err = sdstrategy(ss, F_READ,
LABELSECTOR, DEV_BSIZE, io_buf, &i) < 0) {
printf("sdgetinfo: sdstrategy error %d\n", err);
return 0;
}
msg = getdisklabel(io_buf, lp);
if (msg) {
printf("sd(%d,%d,%d): %s\n",
ss->sc_ctlr, ss->sc_unit, ss->sc_part, msg);
return 0;
}
return(1);
}
sdopen(f, ctlr, unit, part)
struct open_file *f;
int ctlr, unit, part;
{
register struct sd_softc *ss;
register struct disklabel *lp;
#ifdef SD_DEBUG
if (debug)
printf("sdopen: ctlr=%d unit=%d part=%d\n",
ctlr, unit, part);
#endif
if (ctlr >= NSCSI || !scsialive(ctlr))
return (EADAPT);
if (unit >= NSD)
return (ECTLR);
ss = &sd_softc[ctlr][unit]; /* XXX alloc()? keep pointers? */
ss->sc_part = part;
ss->sc_unit = unit;
ss->sc_ctlr = ctlr;
if (!ss->sc_alive) {
if (!sdinit(ctlr, unit))
return (ENXIO);
if (!sdgetinfo(ss))
return (ERDLAB);
}
lp = &sd_softc[ctlr][unit].sc_label;
if (part >= lp->d_npartitions || lp->d_partitions[part].p_size == 0)
return (EPART);
f->f_devdata = (void *)ss;
return (0);
}
int
sdstrategy(ss, func, dblk, size, buf, rsize)
register struct sd_softc *ss;
int func;
daddr_t dblk; /* block number */
u_int size; /* request size in bytes */
char *buf;
u_int *rsize; /* out: bytes transferred */
{
register int ctlr = ss->sc_ctlr;
register int unit = ss->sc_unit;
register int part = ss->sc_part;
register struct partition *pp = &ss->sc_label.d_partitions[part];
u_int nblk = size >> DEV_BSHIFT;
u_int blk = dblk + pp->p_offset;
char stat;
if (size == 0)
return(0);
ss->sc_retry = 0;
#ifdef SD_DEBUG
if (debug)
printf("sdstrategy(%d,%d): size=%d blk=%d nblk=%d\n",
ctlr, unit, size, blk, nblk);
#endif
retry:
if (func == F_READ)
stat = scsi_tt_read(ctlr, unit, buf, size, blk, nblk);
else
stat = scsi_tt_write(ctlr, unit, buf, size, blk, nblk);
if (stat) {
printf("sd(%d,%d,%d): block=%x, error=0x%x\n",
ctlr, unit, ss->sc_part, blk, stat);
if (++ss->sc_retry > SDRETRY)
return(EIO);
goto retry;
}
*rsize = size;
return(0);
}

View File

@ -1,57 +0,0 @@
/* $NetBSD: so.h,v 1.1 1996/08/02 11:22:41 ragge Exp $ */
#ifndef _SO_H_INCLUDE
#define _SO_H_INCLUDE
/* Definitions for standalone I/O lib */
/* #define SCSI_POLLED 0x200C0080 */
#define SCSI_DMA 0x200D0000
/* Which SCSI device to use by default */
#define DEFAULT_SCSI_ADR 1
#define DEFAULT_SCSI_LUN 0
/* Low level scsi operation codes */
#define DISK_READ 3
#define DISK_WRITE 4
/* The size of a disk block */
#define DBLKSIZE 512
/* Some disk address that will never be used */
#define INSANE_BADDR 0x800000
struct scsi_args {
long ptr [8];
};
#ifndef NULL
#define NULL 0L
#endif
/*
* The next macro defines where the "break" area in memory ends for
* malloc() and friends. The area between edata and this address will
* then be reserved and should not be used for anything else (or you will
* no doubt have big problems). Depending on where your program's end-of-data
* is, you may wish to locate this in such a way as to usurp a minimum
* amount of memory.
*/
#define BREAK_END_ADDR ((char *)0x400000) /* to 4MB */
/* Selectivly enable inline functions */
#ifndef NO_INLINE
#define Inline inline
#else
#define Inline
#endif
extern void fatal(), warn();
extern long ulimit(int, long);
extern int brk(char *);
extern char *sbrk(int);
extern int sc_rdwt();
#endif /* _SO_H_INCLUDE */