New snapshot of the dp files, scn changes due to change in ttioctl call.
This commit is contained in:
parent
4c881187a6
commit
d3751424a3
@ -69,6 +69,8 @@
|
||||
|
||||
#include "../pc532/icu.h"
|
||||
|
||||
#define DP_DEBUG 0
|
||||
|
||||
/* Some constants (may need to be changed!) */
|
||||
#define DP_NSEG 16
|
||||
|
||||
@ -78,6 +80,7 @@ int dp_scsi_cmd(struct scsi_xfer *);
|
||||
void dpminphys(struct buf *);
|
||||
long int dp_adapter_info(int);
|
||||
void dp_intr(void);
|
||||
void dp_intr_work(void);
|
||||
|
||||
struct scsidevs *
|
||||
scsi_probe(int masunit, struct scsi_switch *sw, int physid, int type, int want);
|
||||
@ -97,7 +100,7 @@ struct scsi_switch dp_switch = {
|
||||
};
|
||||
|
||||
/* Sense command. */
|
||||
u_char sense_cmd[] = { 3, 0, 0, 0, sizeof(struct scsi_sense_data), 0};
|
||||
static u_char sense_cmd[] = { 3, 0, 0, 0, 0, 0};
|
||||
|
||||
/* Do we need to initialize. */
|
||||
int dp_needs_init = 1;
|
||||
@ -120,6 +123,18 @@ int dp_try_count;
|
||||
/* Give the interrupt routine access to the current scsi_xfer info block. */
|
||||
struct scsi_xfer *cur_xs = NULL;
|
||||
|
||||
/* names of phases for debug printouts */
|
||||
const char *dp_phase_names[] = {
|
||||
"DATA OUT",
|
||||
"DATA IN",
|
||||
"CMD",
|
||||
"STATUS",
|
||||
"PHASE 4",
|
||||
"PHASE 5",
|
||||
"MSG OUT",
|
||||
"MSG IN",
|
||||
};
|
||||
|
||||
/* Initial probe for a device. If it is using the dp controller,
|
||||
just say yes so that attach can be the one to find the real drive. */
|
||||
|
||||
@ -161,6 +176,48 @@ long int dp_adapter_info(int unit)
|
||||
return (1); /* only 1 outstanding request. */
|
||||
}
|
||||
|
||||
#if DP_DEBUG
|
||||
void
|
||||
dp_print_stat1(u_char stat1)
|
||||
{
|
||||
printf("stat1=");
|
||||
if ( stat1 & 0x80 ) printf(" /RST");
|
||||
if ( stat1 & 0x40 ) printf(" /BSY");
|
||||
if ( stat1 & 0x20 ) printf(" /REQ");
|
||||
if ( stat1 & 0x10 ) printf(" /MSG");
|
||||
if ( stat1 & 0x08 ) printf(" /CD");
|
||||
if ( stat1 & 0x04 ) printf(" /IO");
|
||||
if ( stat1 & 0x02 ) printf(" /SEL");
|
||||
if ( stat1 & 0x01 ) printf(" /DBP");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void
|
||||
dp_print_stat2(u_char stat2)
|
||||
{
|
||||
printf("stat2=");
|
||||
if ( stat2 & 0x80 ) printf(" EDMA");
|
||||
if ( stat2 & 0x40 ) printf(" DRQ");
|
||||
if ( stat2 & 0x20 ) printf(" SPER");
|
||||
if ( stat2 & 0x10 ) printf(" INT");
|
||||
if ( stat2 & 0x08 ) printf(" PHSM");
|
||||
if ( stat2 & 0x04 ) printf(" BSY");
|
||||
if ( stat2 & 0x02 ) printf(" /ATN");
|
||||
if ( stat2 & 0x01 ) printf(" /ACK");
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if DP_DEBUG
|
||||
void
|
||||
dp_print_regs()
|
||||
{
|
||||
u_char stat1 = RD_ADR(u_char, DP_STAT1);
|
||||
u_char stat2 = RD_ADR(u_char, DP_STAT2);
|
||||
dp_print_stat1(stat1);
|
||||
dp_print_stat2(stat2);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Do a scsi command. */
|
||||
|
||||
@ -173,10 +230,13 @@ int dp_scsi_cmd(struct scsi_xfer *xs)
|
||||
int dvr_state;
|
||||
int ti_val; /* For timeouts. */
|
||||
|
||||
#if DP_DEBUG
|
||||
printf("\n");
|
||||
#endif
|
||||
x = splhigh();
|
||||
if (dp_dvr_state == DP_DVR_READY)
|
||||
dp_dvr_state = DP_DVR_STARTED;
|
||||
dvr_state = dp_dvr_state;
|
||||
if (dvr_state == DP_DVR_READY)
|
||||
dvr_state = dp_dvr_state = DP_DVR_STARTED;
|
||||
splx(x);
|
||||
|
||||
if (dvr_state != DP_DVR_STARTED)
|
||||
@ -187,48 +247,74 @@ int dp_scsi_cmd(struct scsi_xfer *xs)
|
||||
/* Some initial checks. */
|
||||
flags = xs->flags;
|
||||
if (!(flags & INUSE)) {
|
||||
#if DP_DEBUG
|
||||
printf("dp xs not in use!\n");
|
||||
#endif
|
||||
xs->flags |= INUSE;
|
||||
}
|
||||
if (flags & ITSDONE) {
|
||||
#if DP_DEBUG
|
||||
printf("dp xs already done!\n");
|
||||
#endif
|
||||
xs->flags &= ~ITSDONE;
|
||||
}
|
||||
|
||||
if (dp_needs_reset)
|
||||
if (dp_needs_reset || (xs->flags & SCSI_RESET))
|
||||
dp_reset();
|
||||
|
||||
/* info ... */
|
||||
printf ("\nscsi_cmd: flags=0x%x, targ=%d, lu=%d, cmdlen=%d, cmd=%x\n",
|
||||
#if DP_DEBUG
|
||||
printf ("scsi_cmd: flags=0x%x, targ=%d, lu=%d, cmdlen=%d, cmd=%x\n",
|
||||
xs->flags, xs->targ, xs->lu, xs->cmdlen, xs->cmd->opcode);
|
||||
|
||||
retval = dp_start_cmd (xs);
|
||||
|
||||
if (retval == SUCCESSFULLY_QUEUED && (xs->flags & SCSI_NOMASK)) {
|
||||
/* No interrupts available! */
|
||||
ti_val = WAIT_MUL * xs->timeout;
|
||||
while (dp_dvr_state != DP_DVR_READY) {
|
||||
if (RD_ADR(u_char, DP_STAT2) & DP_S_IRQ) {
|
||||
dp_intr();
|
||||
ti_val = WAIT_MUL * xs->timeout;
|
||||
}
|
||||
if (--ti_val == 0) {
|
||||
/* Software Timeout! */
|
||||
printf ("scsi timeout! stat1=0x%x stat2=0x%x\n",
|
||||
RD_ADR(u_char,DP_STAT1), RD_ADR(u_char,DP_STAT2));
|
||||
dp_reset();
|
||||
xs->error = XS_SWTIMEOUT;
|
||||
dp_dvr_state = DP_DVR_READY;
|
||||
return HAD_ERROR;
|
||||
}
|
||||
}
|
||||
retval = dp_intr_retval;
|
||||
#endif
|
||||
#if 1
|
||||
/* we don't always get NOMASK passed in, so this hack fakes it. */
|
||||
{
|
||||
if ( !initproc )
|
||||
xs->flags |= SCSI_NOMASK;
|
||||
}
|
||||
|
||||
return (retval);
|
||||
#endif
|
||||
if (!(xs->flags & SCSI_NOMASK)) {
|
||||
x = splbio();
|
||||
retval = dp_start_cmd(xs);
|
||||
splx(x);
|
||||
return retval;
|
||||
}
|
||||
/* No interrupts available! */
|
||||
retval = dp_start_cmd(xs);
|
||||
if (retval != SUCCESSFULLY_QUEUED)
|
||||
return retval;
|
||||
#if DP_DEBUG > 1
|
||||
printf("polling for interrupts\n");
|
||||
#endif
|
||||
ti_val = WAIT_MUL * xs->timeout;
|
||||
while (dp_dvr_state != DP_DVR_READY) {
|
||||
if (RD_ADR(u_char, DP_STAT2) & DP_S_IRQ) {
|
||||
dp_intr_work();
|
||||
ti_val = WAIT_MUL * xs->timeout;
|
||||
retval = dp_intr_retval;
|
||||
}
|
||||
if (--ti_val == 0) {
|
||||
/* Software Timeout! */
|
||||
xs->error = XS_SWTIMEOUT;
|
||||
dp_dvr_state = DP_DVR_READY;
|
||||
retval = HAD_ERROR;
|
||||
}
|
||||
}
|
||||
if (xs->error == XS_SWTIMEOUT) {
|
||||
/* Software Timeout! */
|
||||
printf ("scsi timeout!\n");
|
||||
#if DP_DEBUG
|
||||
dp_print_regs();
|
||||
printf("TCMD = 0x%x\n", RD_ADR(u_char, DP_TCMD));
|
||||
#endif
|
||||
dp_reset();
|
||||
}
|
||||
#if 1
|
||||
/* another hack: read cannot handle anything but SUCCESSFULLY_QUEUED */
|
||||
if (xs->cmd->opcode == 0x28)
|
||||
return SUCCESSFULLY_QUEUED;
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* dp_intr *
|
||||
*===========================================================================*/
|
||||
@ -238,46 +324,78 @@ RD_ADR(u_char,DP_STAT1), RD_ADR(u_char,DP_STAT2));
|
||||
routine. It uses dp_dvr_state to determine the next actions along with
|
||||
cur_xs->flags. */
|
||||
|
||||
void dp_intr (void)
|
||||
void dp_intr(void)
|
||||
{
|
||||
u_char isr;
|
||||
u_char new_phase;
|
||||
u_char status;
|
||||
u_char stat1;
|
||||
u_char stat2;
|
||||
u_char message;
|
||||
int ret;
|
||||
int x = splhigh();
|
||||
#if DP_DEBUG
|
||||
printf("\n REAL dp_intr\n");
|
||||
#endif
|
||||
dp_intr_work();
|
||||
splx(x);
|
||||
}
|
||||
|
||||
scsi_select_ctlr (DP8490);
|
||||
WR_ADR(u_char, DP_EMR_ISR, DP_EF_ISR_NEXT);
|
||||
isr = RD_ADR (u_char, DP_EMR_ISR);
|
||||
dp_clear_isr();
|
||||
void dp_intr_work(void)
|
||||
{
|
||||
u_char isr;
|
||||
u_char new_phase;
|
||||
u_char stat1;
|
||||
u_char stat2;
|
||||
static u_char status;
|
||||
static u_char message;
|
||||
int ret;
|
||||
|
||||
|
||||
if (isr & DP_ISR_BSYERR) {
|
||||
printf ("Busy error?\n");
|
||||
}
|
||||
|
||||
if (!(isr & DP_ISR_APHS)) {
|
||||
printf ("Not an APHS!\n");
|
||||
return;
|
||||
}
|
||||
scsi_select_ctlr (DP8490);
|
||||
WR_ADR(u_char, DP_EMR_ISR, DP_EF_ISR_NEXT);
|
||||
isr = RD_ADR (u_char, DP_EMR_ISR);
|
||||
dp_clear_isr();
|
||||
|
||||
stat1 = RD_ADR(u_char, DP_STAT1);
|
||||
new_phase = (stat1 >> 2) & 7;
|
||||
|
||||
printf ("dp_intr dvr_state %d isr=0x%x new_phase = 0x%x stat1 = 0x%x\n",
|
||||
dp_dvr_state, isr, new_phase, stat1);
|
||||
#if DP_DEBUG
|
||||
printf ("dp_intr: dvr_state %d isr=0x%x new_phase = %d %s\n",
|
||||
dp_dvr_state, isr, new_phase, dp_phase_names[new_phase]);
|
||||
#if DP_DEBUG > 1
|
||||
dp_print_regs();
|
||||
#endif
|
||||
#endif
|
||||
#if 0
|
||||
/* de-assert the bus */
|
||||
WR_ADR(u_char, DP_ICMD, DP_EMODE);
|
||||
/* disable dma */
|
||||
RD_ADR(u_char, DP_MODE) &= ~DP_M_DMA;
|
||||
#endif
|
||||
if (isr & DP_ISR_BSYERR) {
|
||||
#if DP_DEBUG
|
||||
printf("dp_intr: Busy error\n");
|
||||
#endif
|
||||
}
|
||||
if (isr & DP_ISR_EDMA) {
|
||||
#if DP_DEBUG > 1
|
||||
printf("dp_intr: EDMA detected\n");
|
||||
#endif
|
||||
RD_ADR(u_char, DP_MODE) &= ~DP_M_DMA;
|
||||
WR_ADR(u_char, DP_ICMD, DP_EMODE);
|
||||
}
|
||||
if (!(isr & DP_ISR_APHS)) {
|
||||
#if DP_DEBUG > 1
|
||||
printf("dp_intr: Not an APHS!\n");
|
||||
printf("dp_intr: dvr_state %d isr=0x%x (exit)\n",
|
||||
dp_dvr_state, isr);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
switch (dp_dvr_state) {
|
||||
|
||||
case DP_DVR_ARB: /* Next comes the command phase! */
|
||||
if (new_phase != DP_PHASE_CMD) {
|
||||
#if DP_DEBUG
|
||||
printf ("Phase mismatch cmd!\n");
|
||||
#endif
|
||||
goto phase_mismatch;
|
||||
}
|
||||
dp_dvr_state = DP_DVR_CMD;
|
||||
ret = dp_pdma_out (cur_xs->cmd, cur_xs->cmdlen, DP_PHASE_CMD);
|
||||
ret = dp_pdma_out(cur_xs->cmd, cur_xs->cmdlen, DP_PHASE_CMD);
|
||||
dp_clear_isr();
|
||||
break;
|
||||
|
||||
@ -293,25 +411,43 @@ printf ("dp_intr dvr_state %d isr=0x%x new_phase = 0x%x stat1 = 0x%x\n",
|
||||
panic ("scsi uio");
|
||||
}
|
||||
if (new_phase == DP_PHASE_DATAI) {
|
||||
#if 1
|
||||
/* just a quick hack until we
|
||||
can trust flags to be correct
|
||||
*/
|
||||
if (!cur_xs->data) {
|
||||
#else
|
||||
if (!(cur_xs->flags & SCSI_DATA_IN)) {
|
||||
printf ("Phase mismatch in.\n");
|
||||
#endif
|
||||
#if DP_DEBUG
|
||||
printf("Phase mismatch in.\n");
|
||||
#endif
|
||||
goto phase_mismatch;
|
||||
}
|
||||
/* expect STAT phase next */
|
||||
dp_dvr_state = DP_DVR_DATA;
|
||||
ret = dp_pdma_in (cur_xs->data, cur_xs->datalen,
|
||||
ret = dp_pdma_in(cur_xs->data, cur_xs->datalen,
|
||||
DP_PHASE_DATAI);
|
||||
dp_clear_isr();
|
||||
break;
|
||||
}
|
||||
else if (new_phase == DP_PHASE_DATAO) {
|
||||
#if 1
|
||||
/* just a quick hack until we
|
||||
can trust flags to be correct
|
||||
*/
|
||||
if (!cur_xs->data) {
|
||||
#else
|
||||
if (!(cur_xs->flags & SCSI_DATA_OUT)) {
|
||||
printf ("Phase mismatch out.\n");
|
||||
#endif
|
||||
#if DP_DEBUG
|
||||
printf("Phase mismatch out.\n");
|
||||
#endif
|
||||
goto phase_mismatch;
|
||||
}
|
||||
/* expect STAT phase next */
|
||||
dp_dvr_state = DP_DVR_DATA;
|
||||
ret = dp_pdma_out (cur_xs->data, cur_xs->datalen,
|
||||
ret = dp_pdma_out(cur_xs->data, cur_xs->datalen,
|
||||
DP_PHASE_DATAO);
|
||||
dp_clear_isr();
|
||||
break;
|
||||
@ -319,29 +455,39 @@ printf ("dp_intr dvr_state %d isr=0x%x new_phase = 0x%x stat1 = 0x%x\n",
|
||||
/* Fall through to next phase. */
|
||||
case DP_DVR_DATA: /* Next comes the stat phase */
|
||||
if (new_phase != DP_PHASE_STATUS) {
|
||||
printf ("Phase mismatch stat.\n");
|
||||
#if DP_DEBUG
|
||||
printf("Phase mismatch stat.\n");
|
||||
#endif
|
||||
goto phase_mismatch;
|
||||
}
|
||||
dp_dvr_state = DP_DVR_STAT;
|
||||
dp_pdma_in (&status, 1, DP_PHASE_STATUS);
|
||||
dp_pdma_in(&status, 1, DP_PHASE_STATUS);
|
||||
dp_clear_isr();
|
||||
while (!((stat2 = RD_ADR(u_char, DP_STAT2)) & DP_S_IRQ))
|
||||
;
|
||||
stat1 = RD_ADR(u_char, DP_STAT1);
|
||||
new_phase = (stat1 >> 2) & 7;
|
||||
#if DP_DEBUG > 1
|
||||
printf("status = 0x%x\n", status);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case DP_DVR_STAT:
|
||||
if (new_phase != DP_PHASE_MSGI) {
|
||||
#if DP_DEBUG
|
||||
printf ("msgi phase mismatch\n");
|
||||
#endif
|
||||
goto phase_mismatch;
|
||||
}
|
||||
dp_pdma_in (&message, 1, DP_PHASE_MSGI);
|
||||
dp_dvr_state = DP_DVR_MSGI;
|
||||
dp_pdma_in(&message, 1, DP_PHASE_MSGI);
|
||||
dp_clear_isr();
|
||||
while (!((stat2 = RD_ADR(u_char, DP_STAT2)) & DP_S_IRQ))
|
||||
;
|
||||
dp_clear_isr();
|
||||
printf ("status = 0x%x, message = 0x%x\n", status, message);
|
||||
#if DP_DEBUG > 1
|
||||
printf("message = 0x%x\n", message);
|
||||
#endif
|
||||
#if 0
|
||||
if (status != SCSI_OK && dp_try_count < cur_xs->retries) {
|
||||
printf ("dp_intr: retry: dp_try_count = %d\n", dp_try_count);
|
||||
printf("dp_intr: retry: dp_try_count = %d\n",
|
||||
dp_try_count);
|
||||
dp_restart_cmd();
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -357,8 +503,10 @@ phase_mismatch:
|
||||
}
|
||||
}
|
||||
|
||||
if (dp_dvr_state == DP_DVR_STAT) {
|
||||
printf ("dvr_stat: dp_try_count = %d\n", dp_try_count);
|
||||
if (dp_dvr_state == DP_DVR_MSGI) {
|
||||
#if DP_DEBUG > 1
|
||||
printf ("dvr_stat: dp_try_count = %d\n", dp_try_count);
|
||||
#endif
|
||||
WR_ADR (u_char, DP_MODE, 0); /* Turn off monbsy, dma, ... */
|
||||
if (status == SCSI_OK) {
|
||||
cur_xs->error = XS_NOERROR;
|
||||
@ -374,13 +522,21 @@ printf ("dvr_stat: dp_try_count = %d\n", dp_try_count);
|
||||
}
|
||||
cur_xs->flags |= ITSDONE;
|
||||
dp_dvr_state = DP_DVR_READY;
|
||||
#if DP_DEBUG > 1
|
||||
printf("calling wakeup on 0x%x\n", cur_xs);
|
||||
#endif
|
||||
wakeup((caddr_t) cur_xs);
|
||||
/* If this true interrupt code, call the done routine. */
|
||||
if (cur_xs->when_done) {
|
||||
printf("dp_intr: calling when_done\n");
|
||||
#if DP_DEBUG > 1
|
||||
printf("dp_intr: calling when_done 0x%x\n", cur_xs->when_done);
|
||||
#endif
|
||||
(*(cur_xs->when_done))(cur_xs->done_arg, cur_xs->done_arg2);
|
||||
}
|
||||
}
|
||||
printf ("exit dp_intr.\n");
|
||||
#if DP_DEBUG > 1
|
||||
printf ("exit dp_intr.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -390,7 +546,9 @@ printf ("exit dp_intr.\n");
|
||||
|
||||
dp_initialize()
|
||||
{
|
||||
printf("dp_initialize()\n");
|
||||
#if DP_DEBUG
|
||||
printf("dp_initialize()\n");
|
||||
#endif
|
||||
scsi_select_ctlr (DP8490);
|
||||
WR_ADR (u_char, DP_ICMD, DP_EMODE); /* Set Enhanced mode */
|
||||
WR_ADR (u_char, DP_MODE, 0); /* Disable everything. */
|
||||
@ -398,9 +556,9 @@ printf("dp_initialize()\n");
|
||||
WR_ADR (u_char, DP_EMR_ISR, DP_EF_NOP);
|
||||
WR_ADR (u_char, DP_SER, 0x80); /* scsi adr 7. */
|
||||
dp_scsi_phase = DP_PHASE_NONE;
|
||||
dp_needs_init = 0;
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* dp_reset *
|
||||
*===========================================================================*/
|
||||
@ -455,7 +613,10 @@ dp_wait_bus_free()
|
||||
if (stat1 & (DP_S_BSY | DP_S_SEL)) continue;
|
||||
return OK;
|
||||
}
|
||||
printf("wait bus free failed, stat1 = 0x%x\n", stat1);
|
||||
#if DP_DEBUG
|
||||
printf("wait bus free failed\n");
|
||||
dp_print_stat1(stat1);
|
||||
#endif
|
||||
dp_needs_reset = 1;
|
||||
return NOT_OK;
|
||||
}
|
||||
@ -471,7 +632,9 @@ long adr;
|
||||
{
|
||||
int i, stat1;
|
||||
|
||||
printf("dp_select(0x%x)\n", adr);
|
||||
#if DP_DEBUG > 1
|
||||
printf("dp_select(0x%x)\n", adr);
|
||||
#endif
|
||||
WR_ADR (u_char, DP_TCMD, 0); /* get to harmless state */
|
||||
WR_ADR (u_char, DP_MODE, 0); /* get to harmless state */
|
||||
WR_ADR (u_char, DP_OUTDATA, adr); /* SCSI bus address */
|
||||
@ -483,9 +646,11 @@ printf("dp_select(0x%x)\n", adr);
|
||||
u_char isr;
|
||||
WR_ADR(u_char, DP_EMR_ISR, DP_EF_ISR_NEXT);
|
||||
isr = RD_ADR (u_char, DP_EMR_ISR);
|
||||
#if DP_DEBUG
|
||||
printf ("SCSI: SELECT timeout adr %d\n", adr);
|
||||
printf("STAT1 = 0x%x ICMD = 0x%x isr = 0x%x\n", stat1,
|
||||
RD_ADR(u_char, DP_ICMD), isr);
|
||||
dp_print_regs();
|
||||
printf("ICMD = 0x%x isr = 0x%x\n", RD_ADR(u_char, DP_ICMD), isr);
|
||||
#endif
|
||||
dp_reset();
|
||||
return NOT_OK;
|
||||
}
|
||||
@ -532,11 +697,17 @@ int dp_start_cmd(struct scsi_xfer *xs)
|
||||
chip do the select for us and interrupt at the end. */
|
||||
|
||||
if (!dp_wait_bus_free()) {
|
||||
#if DP_DEBUG
|
||||
printf("dp_start_cmd: DP DRIVER BUSY\n");
|
||||
#endif
|
||||
xs->error = XS_BUSY;
|
||||
return TRY_AGAIN_LATER;
|
||||
}
|
||||
|
||||
if (!dp_select (1 << xs->targ)) {
|
||||
if (!dp_select(1 << xs->targ)) {
|
||||
#if DP_DEBUG
|
||||
printf("dp_start_cmd: DP DRIVER STUFFUP\n");
|
||||
#endif
|
||||
xs->error = XS_DRIVER_STUFFUP;
|
||||
return HAD_ERROR;
|
||||
}
|
||||
@ -548,7 +719,9 @@ int dp_start_cmd(struct scsi_xfer *xs)
|
||||
|
||||
if (!(xs->flags & SCSI_NOMASK)) {
|
||||
/* Set up the timeout! */
|
||||
printf ("dp timeouts not done\n");
|
||||
#if DP_DEBUG > 1
|
||||
printf ("dp_start_cmd: dp timeouts not done\n");
|
||||
#endif
|
||||
}
|
||||
return SUCCESSFULLY_QUEUED;
|
||||
}
|
||||
@ -568,31 +741,39 @@ int dp_restart_cmd()
|
||||
/* This is not the "right" way to start it. We should just have the
|
||||
chip do the select for us and interrupt at the end. */
|
||||
|
||||
DELAY(50);
|
||||
printf ("restart .. stat1=0x%x stat2=0x%x\n", RD_ADR(u_char, DP_STAT1),
|
||||
RD_ADR(u_char, DP_STAT2));
|
||||
DELAY(50);
|
||||
#if DP_DEBUG
|
||||
printf ("restart .. stat1=0x%x stat2=0x%x\n", RD_ADR(u_char, DP_STAT1),
|
||||
RD_ADR(u_char, DP_STAT2));
|
||||
#endif
|
||||
if (!dp_wait_bus_free()) {
|
||||
cur_xs->error = XS_BUSY;
|
||||
return;
|
||||
}
|
||||
|
||||
printf ("restart .1 stat1=0x%x stat2=0x%x\n", RD_ADR(u_char, DP_STAT1),
|
||||
RD_ADR(u_char, DP_STAT2));
|
||||
printf ("cur_xs->targ=%d\n",cur_xs->targ);
|
||||
#if DP_DEBUG
|
||||
printf ("restart .1 stat1=0x%x stat2=0x%x\n", RD_ADR(u_char, DP_STAT1),
|
||||
RD_ADR(u_char, DP_STAT2));
|
||||
printf ("cur_xs->targ=%d\n",cur_xs->targ);
|
||||
#endif
|
||||
if (!dp_select (1 << cur_xs->targ)) {
|
||||
cur_xs->error = XS_DRIVER_STUFFUP;
|
||||
return;
|
||||
}
|
||||
|
||||
printf ("restart .2 stat1=0x%x stat2=0x%x\n", RD_ADR(u_char, DP_STAT1),
|
||||
RD_ADR(u_char, DP_STAT2));
|
||||
#if DP_DEBUG
|
||||
printf ("restart .2 stat1=0x%x stat2=0x%x\n", RD_ADR(u_char, DP_STAT1),
|
||||
RD_ADR(u_char, DP_STAT2));
|
||||
#endif
|
||||
/* After selection, we now wait for the APHS interrupt! */
|
||||
dp_dvr_state = DP_DVR_ARB; /* Just finished the select/arbitration */
|
||||
dp_try_count++;
|
||||
|
||||
if (!(cur_xs->flags & SCSI_NOMASK)) {
|
||||
/* Set up the timeout! */
|
||||
printf ("dp timeouts not done\n");
|
||||
#if DP_DEBUG
|
||||
printf ("dp_restart_cmd: dp timeouts not done\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -606,47 +787,64 @@ RD_ADR(u_char, DP_STAT2));
|
||||
|
||||
int dp_pdma_out(char *buf, int count, int phase)
|
||||
{
|
||||
int cnt;
|
||||
int ret = OK;
|
||||
u_int stat2;
|
||||
|
||||
#if DP_DEBUG
|
||||
printf("dp_pdma_out: write %d bytes\n", count);
|
||||
#endif
|
||||
#if DP_DEBUG > 1
|
||||
if (RD_ADR(u_char, DP_STAT2) & DP_S_IRQ)
|
||||
printf("WARNING: stat2:IRQ set on call to dp_pdma_out\n");
|
||||
#endif
|
||||
|
||||
/* Set it up. */
|
||||
WR_ADR(u_char, DP_TCMD, phase);
|
||||
RD_ADR(u_char, DP_MODE) |= DP_M_DMA;
|
||||
WR_ADR(u_char, DP_ICMD, DP_ENABLE_DB | DP_EMODE);
|
||||
WR_ADR(u_char, DP_START_SEND, 0);
|
||||
|
||||
/* Do the pdma */
|
||||
/* Do the pdma: first longs, then bytes. */
|
||||
while (count > sizeof(long)) {
|
||||
WR_ADR(long, DP_DMA, *(((long *)buf)++));
|
||||
count -= sizeof(long);
|
||||
}
|
||||
|
||||
/* All but the last byte. */
|
||||
while (count-- > 1) {
|
||||
WR_ADR(u_char, DP_DMA, *(buf++));
|
||||
}
|
||||
|
||||
/* wait for DRQ to be asserted for the last byte, or an
|
||||
* interrupt request to be signaled
|
||||
*/
|
||||
while (1) {
|
||||
stat2 = RD_ADR(u_char, DP_STAT2);
|
||||
if (stat2 & (DP_S_IRQ | DP_S_DRQ)) break;
|
||||
}
|
||||
|
||||
if (stat2 & DP_S_DRQ)
|
||||
if (stat2 & DP_S_DRQ) {
|
||||
WR_ADR(u_char, DP_DMA_EOP, *buf);
|
||||
}
|
||||
else {
|
||||
/* dma error! */
|
||||
printf ("dma write error!\n");
|
||||
#if DP_DEBUG
|
||||
printf ("dma write error!\n");
|
||||
dp_print_stat1(RD_ADR(u_char, DP_STAT1));
|
||||
dp_print_stat2(stat2);
|
||||
#endif
|
||||
cur_xs->error = XS_DRIVER_STUFFUP;
|
||||
/* Clear dma mode, just in case, and disable the bus. */
|
||||
RD_ADR (u_char, DP_MODE) &= ~DP_M_DMA;
|
||||
WR_ADR (u_char, DP_ICMD, DP_EMODE);
|
||||
return NOT_OK;
|
||||
ret = NOT_OK;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Clear dma mode, just in case, and disable the bus. */
|
||||
RD_ADR (u_char, DP_MODE) &= ~DP_M_DMA;
|
||||
WR_ADR (u_char, DP_ICMD, DP_EMODE);
|
||||
#endif
|
||||
|
||||
return OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
@ -659,8 +857,14 @@ printf ("dma write error!\n");
|
||||
|
||||
int dp_pdma_in(char *buf, int count, int phase)
|
||||
{
|
||||
int ret = OK;
|
||||
int i_count = count;
|
||||
u_int stat2;
|
||||
u_char *dma_adr = (u_char *) DP_DMA; /* Address for last few bytes. */
|
||||
|
||||
#if DP_DEBUG > 1
|
||||
printf("dp_pdma_in: read %d bytes\n", count);
|
||||
#endif
|
||||
/* Set it up. */
|
||||
WR_ADR(u_char, DP_TCMD, phase);
|
||||
RD_ADR(u_char, DP_MODE) |= DP_M_DMA;
|
||||
@ -677,10 +881,62 @@ int dp_pdma_in(char *buf, int count, int phase)
|
||||
}
|
||||
|
||||
/* Clear dma mode, just in case, and disable the bus. */
|
||||
RD_ADR (u_char, DP_MODE) &= ~DP_M_DMA;
|
||||
WR_ADR (u_char, DP_ICMD, DP_EMODE);
|
||||
RD_ADR(u_char, DP_MODE) &= ~DP_M_DMA;
|
||||
WR_ADR(u_char, DP_ICMD, DP_EMODE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return OK;
|
||||
dp_wait_for_edma()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 1000000; ++i) {
|
||||
u_char tcmd = RD_ADR(u_char, DP_TCMD);
|
||||
if (tcmd & DP_TCMD_EDMA) {
|
||||
#if DP_DEBUG > 1
|
||||
printf("dp_wait_for_phase: EDMA detected\n");
|
||||
#endif
|
||||
RD_ADR(u_char, DP_MODE) &= ~DP_M_DMA;
|
||||
WR_ADR(u_char, DP_ICMD, DP_EMODE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
printf("wait for edma timeout\n");
|
||||
#if DP_DEBUG
|
||||
dp_print_regs();
|
||||
#endif
|
||||
panic("dp: wait for edma");
|
||||
}
|
||||
|
||||
dp_wait_for_phase(u_char phase)
|
||||
{
|
||||
int i;
|
||||
u_char isr;
|
||||
|
||||
#if DP_DEBUG > 1
|
||||
printf("wait for phase %d...", phase);
|
||||
#endif
|
||||
/* set the TCR register */
|
||||
WR_ADR(u_char, DP_TCMD, phase);
|
||||
/* wait for phase match */
|
||||
for (i = 0; i < 1000000; ++i) {
|
||||
u_char stat2 = RD_ADR(u_char, DP_STAT2);
|
||||
if (stat2 & DP_S_PHASE) {
|
||||
#if DP_DEBUG > 1
|
||||
printf("done\n");
|
||||
#endif
|
||||
/* completely clear the isr */
|
||||
WR_ADR(u_char, DP_EMR_ISR, DP_EF_ISR_NEXT);
|
||||
isr = RD_ADR (u_char, DP_EMR_ISR);
|
||||
dp_clear_isr();
|
||||
return;
|
||||
}
|
||||
}
|
||||
printf("wait for phase %d timeout\n", phase);
|
||||
#if DP_DEBUG
|
||||
dp_print_regs();
|
||||
#endif
|
||||
panic("dp: wait for phase");
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
@ -689,53 +945,100 @@ int dp_pdma_in(char *buf, int count, int phase)
|
||||
|
||||
dp_get_sense (struct scsi_xfer *xs)
|
||||
{
|
||||
u_char status;
|
||||
u_char message;
|
||||
int ret;
|
||||
u_char status;
|
||||
u_char message;
|
||||
u_char isr;
|
||||
int ret;
|
||||
|
||||
printf ("sense 1.\n");
|
||||
if (!dp_wait_bus_free()) {
|
||||
bzero((u_char *) &xs->sense, sizeof(xs->sense));
|
||||
|
||||
/* completely clear the isr on entry */
|
||||
WR_ADR(u_char, DP_EMR_ISR, DP_EF_ISR_NEXT);
|
||||
isr = RD_ADR (u_char, DP_EMR_ISR);
|
||||
dp_clear_isr();
|
||||
|
||||
RD_ADR(u_char, DP_MODE) &= ~DP_M_DMA;
|
||||
WR_ADR(u_char, DP_ICMD, DP_EMODE);
|
||||
|
||||
#if DP_DEBUG > 2
|
||||
printf ("sense 1: wait bus free\n");
|
||||
#endif
|
||||
if (!dp_wait_bus_free()) {
|
||||
#if DP_DEBUG > 2
|
||||
printf("sense 1: wait-bus-free failed\n");
|
||||
#endif
|
||||
xs->error = XS_BUSY;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
printf ("sense 2.\n");
|
||||
if (!dp_select (1 << xs->targ)) {
|
||||
#if DP_DEBUG > 2
|
||||
printf ("sense 2: select device\n");
|
||||
#endif
|
||||
if (!dp_select (1 << xs->targ)) {
|
||||
#if DP_DEBUG
|
||||
printf("sense 2: select failed\n");
|
||||
#endif
|
||||
xs->error = XS_DRIVER_STUFFUP;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* completely clear the isr */
|
||||
WR_ADR(u_char, DP_EMR_ISR, DP_EF_ISR_NEXT);
|
||||
isr = RD_ADR (u_char, DP_EMR_ISR);
|
||||
dp_clear_isr();
|
||||
|
||||
printf ("sense 3.\n");
|
||||
sense_cmd[1] = xs->lu << 5;
|
||||
ret = dp_pdma_out (sense_cmd, 6, DP_PHASE_CMD);
|
||||
printf ("dp_pdma_out ret=%d\n", ret);
|
||||
dp_clear_isr();
|
||||
/* send the command */
|
||||
sense_cmd[1] = xs->lu << 5;
|
||||
#if 0
|
||||
sense_cmd[4] = sizeof(struct scsi_sense_data);
|
||||
#else
|
||||
sense_cmd[4] = 0x04;
|
||||
#endif
|
||||
dp_wait_for_phase(DP_PHASE_CMD);
|
||||
ret = dp_pdma_out(sense_cmd, sizeof(sense_cmd), DP_PHASE_CMD);
|
||||
if (ret != OK) {
|
||||
#if DP_DEBUG
|
||||
printf("dp_pdma_out: ret=%d\n", ret);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
printf ("sense 4. ");
|
||||
printf ("stat1=0x%x stat2=0x%x\n", RD_ADR(u_char, DP_STAT1),
|
||||
RD_ADR(u_char, DP_STAT2));
|
||||
while (!(RD_ADR(u_char, DP_STAT2) & DP_S_IRQ)) /* wait */;
|
||||
|
||||
printf ("sense 5.\n");
|
||||
dp_pdma_in ((u_char *)&xs->sense, sizeof(struct scsi_sense_data), DP_PHASE_DATAI);
|
||||
dp_clear_isr();
|
||||
/* read sense data */
|
||||
dp_wait_for_edma();
|
||||
dp_wait_for_phase(DP_PHASE_DATAI);
|
||||
ret = dp_pdma_in((u_char *) &xs->sense, sense_cmd[4], DP_PHASE_DATAI);
|
||||
if (ret != OK) {
|
||||
#if DP_DEBUG
|
||||
printf ("dp_pdma_in: ret=%d\n", ret);
|
||||
#endif
|
||||
}
|
||||
|
||||
printf ("sense 6.\n");
|
||||
while (!(RD_ADR(u_char, DP_STAT2) & DP_S_IRQ)) ;
|
||||
/* read status */
|
||||
dp_wait_for_phase(DP_PHASE_STATUS);
|
||||
ret = dp_pdma_in(&status, 1, DP_PHASE_STATUS);
|
||||
if (ret != OK) {
|
||||
#if DP_DEBUG
|
||||
printf ("dp_pdma_in: ret=%d\n", ret);
|
||||
#endif
|
||||
}
|
||||
|
||||
printf ("sense 7.\n");
|
||||
dp_pdma_in (&status, 1, DP_PHASE_STATUS);
|
||||
dp_clear_isr();
|
||||
/* read message */
|
||||
dp_wait_for_phase(DP_PHASE_MSGI);
|
||||
ret = dp_pdma_in(&message, 1, DP_PHASE_MSGI);
|
||||
if (ret != OK) {
|
||||
#if DP_DEBUG
|
||||
printf ("dp_pdma_in: ret=%d\n", ret);
|
||||
#endif
|
||||
}
|
||||
|
||||
printf ("sense 8.\n");
|
||||
while (!(RD_ADR(u_char, DP_STAT2) & DP_S_IRQ)) /* wait */;
|
||||
dp_pdma_in (&message, 1, DP_PHASE_MSGI);
|
||||
dp_clear_isr();
|
||||
#if DP_DEBUG
|
||||
printf("sense status = 0x%x\n", status);
|
||||
printf(" sense (0x%x) valid = %d code = 0x%x class = 0x%x\n",
|
||||
*(u_char *) &xs->sense,
|
||||
xs->sense.valid, xs->sense.error_code, xs->sense.error_class);
|
||||
#endif
|
||||
|
||||
printf ("sense status = 0x%x\n", status);
|
||||
|
||||
if (status & SCSI_BUSY) {
|
||||
if (status & SCSI_BUSY) {
|
||||
xs->error = XS_BUSY;
|
||||
}
|
||||
WR_ADR (u_char, DP_MODE, 0); /* Turn off monbsy, dma, ... */
|
||||
}
|
||||
WR_ADR (u_char, DP_MODE, 0); /* Turn off monbsy, dma, ... */
|
||||
}
|
||||
|
@ -63,8 +63,10 @@
|
||||
#define DP_S_PHASE 0x08
|
||||
#define DP_S_IRQ 0x10
|
||||
#define DP_S_DRQ 0x40
|
||||
#define DP_TCMD_EDMA 0x80 /* true end of dma in tcmd */
|
||||
#define DP_M_DMA 0x02
|
||||
#define DP_M_BSY 0x04
|
||||
#define DP_M_EDMA 0x08
|
||||
#define DP_ENABLE_DB 0x01
|
||||
#define DP_EMODE 0x40 /* enhanced mode */
|
||||
#define DP_EF_NOP 0x00 /* enhanced functions */
|
||||
@ -76,7 +78,8 @@
|
||||
#define DP_ISR_BSYERR 0x04
|
||||
#define DP_ISR_APHS 0x08
|
||||
#define DP_ISR_DPHS 0x10
|
||||
#define DP_INT_MASK (~(DP_ISR_APHS | DP_ISR_BSYERR))
|
||||
#define DP_ISR_EDMA 0x20
|
||||
#define DP_INT_MASK (~(DP_ISR_APHS | DP_ISR_BSYERR | DP_ISR_EDMA))
|
||||
|
||||
#define DP_PHASE_DATAO 0 /* Data out */
|
||||
#define DP_PHASE_DATAI 1 /* Data in */
|
||||
@ -94,7 +97,8 @@
|
||||
#define DP_DVR_CMD 3
|
||||
#define DP_DVR_DATA 4
|
||||
#define DP_DVR_STAT 5
|
||||
#define DP_DVR_SENSE 6
|
||||
#define DP_DVR_MSGI 6
|
||||
#define DP_DVR_SENSE 7
|
||||
|
||||
#define dp_clear_isr() /* clear 8490 interrupts */ \
|
||||
WR_ADR (u_char, DP_EMR_ISR, DP_EF_RESETIP); \
|
||||
|
@ -31,7 +31,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)com.c 7.5 (Berkeley) 5/16/91
|
||||
* $Id: scn.c,v 1.2 1993/09/13 07:25:06 phil Exp $
|
||||
* $Id: scn.c,v 1.3 1994/02/21 06:43:31 phil Exp $
|
||||
*/
|
||||
|
||||
#include "scn.h"
|
||||
@ -65,7 +65,8 @@
|
||||
#include "../pc532/icu.h"
|
||||
#include "sl.h"
|
||||
|
||||
int scnprobe(), scnattach(), scnintr(), scnstart(), scnparam();
|
||||
int scnprobe(), scnattach(), scnintr(), scnparam();
|
||||
void scnstart();
|
||||
|
||||
struct pc532_driver scndriver = {
|
||||
scnprobe, scnattach, "scn"
|
||||
@ -782,9 +783,12 @@ commint(unit, com)
|
||||
}
|
||||
#endif
|
||||
|
||||
scnioctl(dev, cmd, data, flag)
|
||||
scnioctl(dev, cmd, data, flag, p)
|
||||
dev_t dev;
|
||||
int cmd;
|
||||
caddr_t data;
|
||||
int flag;
|
||||
struct proc *p;
|
||||
{
|
||||
register struct tty *tp;
|
||||
register int unit = UNIT(dev);
|
||||
@ -793,10 +797,10 @@ scnioctl(dev, cmd, data, flag)
|
||||
register int error;
|
||||
|
||||
tp = scn_tty[unit];
|
||||
error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
|
||||
error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
|
||||
if (error >= 0)
|
||||
return (error);
|
||||
error = ttioctl(tp, cmd, data, flag);
|
||||
error = ttioctl(tp, cmd, data, flag, p);
|
||||
if (error >= 0)
|
||||
return (error);
|
||||
|
||||
@ -900,7 +904,8 @@ scnparam(tp, t)
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
scnstart(tp)
|
||||
register struct tty *tp;
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user