#include <sys/param.h>
#include <lib/libsa/stand.h>
#include <machine/mtpr.h>
#include <machine/rsp.h>
#include "vaxstand.h"
static short ctu_cksum(unsigned short *, int);
enum tu_state {
SC_INIT,
SC_READY,
SC_SEND_CMD,
SC_GET_RESP,
};
volatile struct tu_softc {
enum tu_state sc_state;
char sc_rsp[15];
u_char *sc_xfptr;
int sc_nbytes;
int sc_xbytes;
int sc_bbytes;
} tu_sc;
void ctutintr(void);
void cturintr(void);
int
ctuopen(struct open_file *f, int adapt, int ctlr, int unit, int part)
{
tu_sc.sc_state = SC_INIT;
mtpr(RSP_TYP_INIT, PR_CSTD);
cturintr();
tu_sc.sc_state = SC_READY;
return 0;
}
int
ctustrategy(void *f, int func, daddr_t dblk, size_t size, void *buf, size_t *rsize)
{
struct rsp *rsp = (struct rsp *)tu_sc.sc_rsp;
tu_sc.sc_xfptr = buf;
tu_sc.sc_nbytes = size;
tu_sc.sc_xbytes = tu_sc.sc_bbytes = 0;
rsp->rsp_typ = RSP_TYP_COMMAND;
rsp->rsp_sz = 012;
rsp->rsp_op = RSP_OP_READ;
rsp->rsp_mod = 0;
rsp->rsp_drv = 0;
rsp->rsp_sw = rsp->rsp_xx1 = rsp->rsp_xx2 = 0;
rsp->rsp_cnt = tu_sc.sc_nbytes;
rsp->rsp_blk = dblk;
rsp->rsp_sum = ctu_cksum((u_short *)rsp, 6);
tu_sc.sc_state = SC_SEND_CMD;
while (tu_sc.sc_state != SC_GET_RESP)
ctutintr();
while (tu_sc.sc_state != SC_READY)
cturintr();
*rsize = size;
return 0;
}
void
cturintr(void)
{
int status;
while ((mfpr(PR_CSRS) & 0x80) == 0)
;
status = mfpr(PR_CSRD);
switch (tu_sc.sc_state) {
case SC_INIT:
break;
case SC_GET_RESP:
if (tu_sc.sc_xbytes == tu_sc.sc_nbytes) {
tu_sc.sc_bbytes++;
if (tu_sc.sc_bbytes == 146)
tu_sc.sc_state = SC_READY;
break;
}
tu_sc.sc_bbytes++;
if (tu_sc.sc_bbytes < 3)
break;
if (tu_sc.sc_bbytes == 132) {
tu_sc.sc_bbytes = 0;
break;
}
if (tu_sc.sc_bbytes == 131)
break;
tu_sc.sc_xfptr[tu_sc.sc_xbytes++] = status;
break;
case SC_READY:
case SC_SEND_CMD:
break;
}
}
void
ctutintr(void)
{
int c;
while ((mfpr(PR_CSTS) & 0x80) == 0)
;
c = tu_sc.sc_rsp[tu_sc.sc_xbytes++] & 0xff;
mtpr(c, PR_CSTD);
if (tu_sc.sc_xbytes > 13) {
tu_sc.sc_state = SC_GET_RESP;
tu_sc.sc_xbytes = 0;
}
}
short
ctu_cksum(unsigned short *buf, int words)
{
int i, cksum;
for (i = cksum = 0; i < words; i++)
cksum += buf[i];
hej: if (cksum > 65535) {
cksum = (cksum & 65535) + (cksum >> 16);
goto hej;
}
return cksum;
}