138624Skarels /*
238624Skarels * Datakit driver
338624Skarels * DR11C version without KMC
438624Skarels *
538624Skarels * uses mbufs for transmission
638624Skarels *
738624Skarels * SCCSID[] = "@(#)dkit_dr.c 1.5 Garage 84/04/11"
838624Skarels */
938624Skarels
1038624Skarels #include "dkitdr.h"
1138624Skarels #if NDKITDR>0
1238624Skarels #include "datakit.h"
1338624Skarels
14*45800Sbostic #include "../include/pte.h"
15*45800Sbostic #include "sys/param.h"
16*45800Sbostic #include "sys/time.h"
17*45800Sbostic #include "sys/kernel.h"
18*45800Sbostic #include "sys/buf.h"
19*45800Sbostic #include "sys/mbuf.h"
20*45800Sbostic #include "sys/errno.h"
21*45800Sbostic #include "sys/socket.h"
22*45800Sbostic #include "sys/syslog.h"
23*45800Sbostic #include "net/if.h"
24*45800Sbostic #include "../uba/ubareg.h"
25*45800Sbostic #include "../uba/ubavar.h"
2638624Skarels
2738624Skarels #include "dk.h"
2838624Skarels #include "dkit.h"
2938624Skarels #include "dkdr.h"
3038624Skarels
3138624Skarels
3238624Skarels #define PKBHOG 64 /* max temp buffers per channel */
3338624Skarels #define DKNPKB (200+4*NDATAKIT)
3438624Skarels #define DKNSTB 10
3538624Skarels
3638624Skarels struct dkchan dkit[NDATAKIT];
3738624Skarels extern int dk_nchan;
3838624Skarels
3938624Skarels int dkdr_npk = DKNPKB;
4038624Skarels struct dkpkbufr dk_pkbuf[DKNPKB];
4138624Skarels
4238624Skarels int dkdr_nstat = DKNSTB;
4338624Skarels struct dkstat dkdr_stat[DKNSTB];
4438624Skarels
4538624Skarels int dkattached = 0; /* Is it really there? */
4638624Skarels
4738624Skarels #ifdef KALYPSO
4838624Skarels #define URPDEBUG 5000
4938624Skarels #else
5038624Skarels #define URPDEBUG 500
5138624Skarels #endif
5238624Skarels
5338624Skarels #ifdef URPDEBUG
5438624Skarels int dkurpdebug = 0;
5538624Skarels #define URPTRACE(chan, chr, Dkp) if (dkurpdebug == (chan)) \
5638624Skarels dkurptrace(chr, Dkp);
5738624Skarels #endif
5838624Skarels
5938624Skarels /*
6038624Skarels * structure of data in first mbuf on chain (type DKM_HDR)
6138624Skarels *
6238624Skarels */
6338624Skarels struct mpacket {
6438624Skarels short mp_len; /* Total length left */
6538624Skarels char mp_ctl; /* Control character */
6638624Skarels int mp_eob; /* Send end-of-block indicator */
6738624Skarels int (*mp_endfcn)(); /* End-action function */
6838624Skarels caddr_t mp_endparm; /* Parameter to above function */
6938624Skarels };
7038624Skarels
7138624Skarels /*
7238624Skarels * dr11-c bit definitions
7338624Skarels */
7438624Skarels #define DKTENAB 0100 /* transmit interrupt enable */
7538624Skarels #define DKRENAB 040 /* receiver interrupt enable */
7638624Skarels #define ENABS 0140 /* both enables */
7738624Skarels #define DKCOM 03 /* dr11-c command bits */
7838624Skarels #define DKTDONE 0200 /* transmit done bit */
7938624Skarels #define DKRDONE 0100000 /* receiver done bit */
8038624Skarels #define DKMARK 01000 /* start of packet bit */
8138624Skarels #define DKOVF 040000 /* receiver overflow bit (in drin) */
8238624Skarels #define DKDATA 0400 /* bit 9 ... indicates non-control */
8338624Skarels
8438624Skarels #define DKCHUNK 16 /* packet size */
8538624Skarels
8638624Skarels /*
8738624Skarels * dr11c commands
8838624Skarels */
8938624Skarels #define D_OSEQ 0
9038624Skarels #define D_READ 1
9138624Skarels #define D_WRITE 2
9238624Skarels #define D_XPACK 3
9338624Skarels
9438624Skarels /*
9538624Skarels * error control protocol definitions
9638624Skarels */
9738624Skarels #define SEQ 0010 /* 8 sequence numbers to end trailers */
9838624Skarels #define ECHO 0020 /* 8 echoes, data given to host */
9938624Skarels #define REJ 0030 /* 8 rejections, transmission error */
10038624Skarels #define ACK 0040 /* first of 8 acks, correct reception */
10138624Skarels #define BOT 0050 /* normal beginning of trailer */
10238624Skarels #define BOTM 0051 /* trailer with more data to follow */
10338624Skarels #define BOTS 0052 /* seq update algorithm on this trailer */
10438624Skarels #define SOI 0053 /* start of interrupt trailer */
10538624Skarels #define EOI 0054 /* end of interrupt trailer */
10638624Skarels #define ENQ 0055 /* xmitter request flow/error status */
10738624Skarels #define CHECK 0056 /* xmitter request error status */
10838624Skarels #define INITREQ 0057 /* request initialization */
10938624Skarels #define INIT0 0060 /* disable trailer processing */
11038624Skarels #define INIT1 0061 /* enable trailer processing */
11138624Skarels #define AINIT 0062 /* response to INIT0/INIT1 */
11238624Skarels
11338624Skarels #define DKBMASK 03 /* this xmitter has window size of 4, */
11438624Skarels /* #define DKBLOCK 60 /* each message is 60 bytes */
11538624Skarels #define DKBLOCK 28 /* each message is 60 bytes */
11638624Skarels
11738624Skarels
11838624Skarels /*
11938624Skarels * some commonly used macros
12038624Skarels */
12138624Skarels
12238624Skarels
12338624Skarels
12438624Skarels struct dkpkbufr *dk_Sfree;
12538624Skarels extern int dkdr_npk;
12638624Skarels extern struct dkpkbufr dk_pkbuf[];
12738624Skarels
12838624Skarels int dknopkb = 1 ; /* Counter for 'no dkpkbufr' condition. */
12938624Skarels int dkstray; /* number of stray interrupts since last timeout */
13038624Skarels int dkdrlostint; /* Number of lost receiver interrupts */
13138624Skarels int dkdisabled; /* flag to indicate that DK interface has been disabled
13238624Skarels due to stray interrupts, etc. */
13338624Skarels #define MAX_STRAY 10 /* maximum number of stray interrupts
13438624Skarels before temporarily disabling DK interrupts */
13538624Skarels
13638624Skarels /*
13738624Skarels * dr11c device registers
13838624Skarels */
13938624Skarels struct rdevice {
14038624Skarels short dkcsr;
14138624Skarels short dko;
14238624Skarels short dki;
14338624Skarels };
14438624Skarels
14538624Skarels extern int dkdr_nstat;
14638624Skarels extern struct dkstat dkdr_stat[];
14738624Skarels
14838624Skarels static char Hstat, Tstat;
14938624Skarels
15038624Skarels #define DKADDR ((struct rdevice *) dkitdrdinfo[0]->ui_addr)
15138624Skarels
15238624Skarels
15338624Skarels /*
15438624Skarels * Intermediate level command codes
15538624Skarels */
15638624Skarels #define KS_SEND 20
15738624Skarels #define KS_RDB 21
15838624Skarels #define KS_EOI 22
15938624Skarels #define KS_CNTL 23
16038624Skarels #define KS_ERR 24
16138624Skarels
16238624Skarels
16338624Skarels
16438624Skarels int dkdebug = 512 ;
16538624Skarels int dkactive ;
16638624Skarels
16738624Skarels static int timeron;
16838624Skarels
16938624Skarels
17038624Skarels int dkitdrprobe(), dkitdrattach();
17138624Skarels struct uba_device *dkitdrdinfo[1];
17238624Skarels u_short dkitdrstd[] = { 0 };
17338624Skarels struct uba_driver dkitdrdriver =
17438624Skarels { dkitdrprobe, 0, dkitdrattach, 0, dkitdrstd, "dkitdr", dkitdrdinfo };
17538624Skarels
dkitdrprobe(reg)17638624Skarels dkitdrprobe(reg)
17738624Skarels caddr_t reg;
17838624Skarels {
17938624Skarels register int br, cvec; /* value-result */
18038624Skarels register struct rdevice *draddr = (struct rdevice *) reg;
18138624Skarels register int i, c;
18238624Skarels
18338624Skarels #ifdef lint
18438624Skarels br = 0; cvec = br; br = cvec;
18538624Skarels dkdrrint(0); dkdrxint(0);
18638624Skarels #endif
18738624Skarels draddr->dkcsr = D_READ;
18838624Skarels for (i = 0; i < 1024; i++)
18938624Skarels if (draddr->dkcsr & DKRDONE) c = draddr->dki;
19038624Skarels else break;
19138624Skarels #ifdef lint
19238624Skarels c = c;
19338624Skarels #endif
19438624Skarels draddr->dkcsr = D_WRITE;
19538624Skarels draddr->dko = DKMARK | (dk_nchan-1); /* pack on 511 */
19638624Skarels draddr->dkcsr = D_XPACK + DKTENAB;
19738624Skarels draddr->dko = 0;
19838624Skarels DELAY(10000);
19938624Skarels draddr->dkcsr = 0;
20038624Skarels return(sizeof(struct rdevice));
20138624Skarels }
20238624Skarels
20338624Skarels /*ARGSUSED*/
20438624Skarels dkitdrattach(ui)
20538624Skarels struct uba_device *ui;
20638624Skarels {
20738624Skarels dkattached = 1;
20838624Skarels
20938624Skarels #if defined(INET) && NDKI>0
21038624Skarels dkiattach();
21138624Skarels #endif
21238624Skarels }
21338624Skarels
21438624Skarels
21538624Skarels static
dk_init()21638624Skarels dk_init()
21738624Skarels {
21838624Skarels register struct rdevice *raddr = DKADDR;
21938624Skarels register s ;
22038624Skarels /*
22138624Skarels * At attach time for the hardware device
22238624Skarels * initialize and check things out to the
22338624Skarels * (grumble) limited extent that is possible.
22438624Skarels */
22538624Skarels
22638624Skarels s = spl5() ;
22738624Skarels Hstat = Tstat = 0 ;
22838624Skarels dkdisabled = 0;
22938624Skarels dkstray = 0;
23038624Skarels {
23138624Skarels register struct dkchan *dkp ;
23238624Skarels
23338624Skarels for (dkp = &dkit[0]; dkp < &dkit[dk_nchan]; dkp++) {
23438624Skarels dkp->dk_rlen = 0 ;
23538624Skarels dkp->dk_xlen = 0 ;
23638624Skarels dkp->dk_X = XM_OFF;
23738624Skarels dkp->dk_rq = NULL ;
23838624Skarels dkp->dk_outq.ifq_len = 0;
23938624Skarels dkp->dk_outq.ifq_maxlen = 20;
24038624Skarels dkp->dk_outq.ifq_drops = 0;
24138624Skarels dkp->dk_outq.ifq_head = NULL;
24238624Skarels dkp->dk_outq.ifq_tail = NULL;
24338624Skarels }
24438624Skarels } { register struct dkpkbufr *pkb ;
24538624Skarels
24638624Skarels for (pkb = &dk_pkbuf[1]; pkb < &dk_pkbuf[dkdr_npk-1]; pkb++) {
24738624Skarels pkb->Pnext = pkb + 1 ;
24838624Skarels }
24938624Skarels dk_pkbuf[dkdr_npk-1].Pnext = NULL ;
25038624Skarels dk_Sfree = &dk_pkbuf[1] ;
25138624Skarels dk_pkbuf[0].Pnext = NULL ;
25238624Skarels } {
25338624Skarels register int seq, i, c ;
25438624Skarels
25538624Skarels raddr->dkcsr = D_OSEQ ;
25638624Skarels raddr->dko = 0 ; /* clears all FIFO's */
25738624Skarels seq = 0 ;
25838624Skarels while (raddr->dkcsr & DKTDONE) {
25938624Skarels seq += (((raddr->dki)>>10) & 017) + 2 ;
26038624Skarels if (seq > 100) {
26138624Skarels dkreport(KS_ERR, 0, 1, 0, 1) ;
26238624Skarels splx(s) ;
26338624Skarels return -EIO ;
26438624Skarels }
26538624Skarels }
26638624Skarels raddr->dkcsr = D_READ;
26738624Skarels for (i = 0; i < 1024; i++)
26838624Skarels if (raddr->dkcsr & DKRDONE) c = raddr->dki;
26938624Skarels else break;
27038624Skarels #ifdef lint
27138624Skarels c = c;
27238624Skarels #endif
27338624Skarels }
27438624Skarels raddr->dkcsr = ENABS ;
27538624Skarels if(!timeron){
27638624Skarels dk_timeout();
27738624Skarels timeron++;
27838624Skarels }
27938624Skarels
28038624Skarels splx(s) ;
28138624Skarels dkactive = 1 ;
28238624Skarels
28338624Skarels
28438624Skarels return 0 ;
28538624Skarels }
28638624Skarels
28738624Skarels /*ARGSUSED*/
dkitreset(uban)28838624Skarels dkitreset(uban)
28938624Skarels int uban;
29038624Skarels {
29138624Skarels register struct rdevice *raddr ;
29238624Skarels
29338624Skarels raddr = DKADDR;
29438624Skarels raddr->dkcsr = ENABS;
29538624Skarels log(LOG_ERR, " dkit_dr%d", 0);
29638624Skarels }
29738624Skarels
dk_open(chan,supfcn)29838624Skarels dk_open(chan, supfcn)
29938624Skarels register chan ;
30038624Skarels int (*supfcn)() ;
30138624Skarels {
30238624Skarels register struct dkchan *dkp;
30338624Skarels register s ;
30438624Skarels extern dkkint() ;
30538624Skarels static firsttime = 1;
30638624Skarels static init;
30738624Skarels extern int commchan;
30838624Skarels
30938624Skarels if (chan >= dk_nchan || !dkattached)
31038624Skarels return -ENXIO ;
31138624Skarels if (firsttime) {
31238624Skarels if ((init = dk_init()) < 0) return init;
31338624Skarels firsttime = 0;
31438624Skarels }
31538624Skarels dkp = &dkit[chan] ;
31638624Skarels s = spl5() ;
31738624Skarels /*
31838624Skarels * Channel 0 (0-3 in ISN) is reserved for maintenance.
31938624Skarels * An open on channel 0 is interpreted as a request
32038624Skarels * for an unused channel. Channel 1 (4 in ISN or RADIAN)
32138624Skarels * is the common supervisory channel.
32238624Skarels */
32338624Skarels if (chan == 0) {
32438624Skarels chan = commchan+1 ; /* Start above commchan */
32538624Skarels while (1) {
32638624Skarels dkp = &dkit[chan] ;
32738624Skarels if (dkp->dk_state == 0)
32838624Skarels break ;
32938624Skarels chan++ ;
33038624Skarels if (chan >= dk_nchan) {
33138624Skarels splx(s) ;
33238624Skarels return -EADDRNOTAVAIL ;
33338624Skarels }
33438624Skarels }
33538624Skarels }
33638624Skarels
33738624Skarels
33838624Skarels /*
33938624Skarels * Finish setting up dkp struct.
34038624Skarels */
34138624Skarels if ((dkp->dk_state & DK_OPEN) ==0) {
34238624Skarels if (chan > dkdebug)
34338624Skarels log(LOG_ERR, "dkopen %d: %x\n", chan, supfcn) ;
34438624Skarels dkp->dk_S = 1 ;
34538624Skarels dkp->dk_R = 0 ;
34638624Skarels dkp->dk_X = 0 ;
34738624Skarels dkp->dk_A = 0 ;
34838624Skarels dkp->dk_rejcnt = 0;
34938624Skarels dkp->dk_srejcnt = 0;
35038624Skarels dkp->dk_ackrejcnt = 0;
35138624Skarels dkp->dk_enqcnt = 0;
35238624Skarels dksend(chan, INIT1) ;
35338624Skarels flushall(dkp, 0);
35438624Skarels dkp->dk_state &= ~DK_LINGR ;
35538624Skarels dkp->dk_state |= DK_OPEN;
35638624Skarels }
35738624Skarels dkp->dk_supfcn = supfcn ;
35838624Skarels splx(s) ;
35938624Skarels return chan ;
36038624Skarels }
36138624Skarels
36238624Skarels
36338624Skarels /*
36438624Skarels * Close a channel:
36538624Skarels */
36638624Skarels
dk_close(chan)36738624Skarels dk_close(chan)
36838624Skarels {
36938624Skarels register struct dkchan *dkp;
37038624Skarels register s ;
37138624Skarels
37238624Skarels s = spl5() ;
37338624Skarels if (chan > dkdebug)
37438624Skarels log(LOG_ERR, "dkclose %d\n", chan) ;
37538624Skarels dkp = &dkit[chan] ;
37638624Skarels if (chan == 0) {
37738624Skarels if (!dkattached) return -ENXIO;
37838624Skarels for (dkp = &dkit[1]; dkp < &dkit[dk_nchan]; dkp++) {
37938624Skarels if (dkp->dk_state & (DK_OPEN|DK_BUSY|DK_RCV)) {
38038624Skarels dkp->dk_state |= DK_RESET ;
38138624Skarels flushall(dkp, 0) ;
38238624Skarels }
38338624Skarels }
38438624Skarels dkactive = 0 ;
38538624Skarels splx(s);
38638624Skarels return dk_init() ;
38738624Skarels } else {
38838624Skarels dkp->dk_state |= DK_OPEN ;
38938624Skarels flushall(dkp, 0) ;
39038624Skarels dkp->dk_state = DK_LINGR ;
39138624Skarels dkp->dk_X = XM_OFF;
39238624Skarels dkp->dk_trmode = 0 ;
39338624Skarels }
39438624Skarels splx(s) ;
39538624Skarels return 0;
39638624Skarels }
39738624Skarels
39838624Skarels /*
39938624Skarels * Close phase 2 - mark available for reassignment
40038624Skarels */
dk_free(chan)40138624Skarels dk_free(chan)
40238624Skarels {
40338624Skarels if (chan > dkdebug)
40438624Skarels log(LOG_ERR, "dkfree %d\n", chan) ;
40538624Skarels dkit[chan].dk_state &= ~DK_LINGR ;
40638624Skarels }
40738624Skarels
40838624Skarels
40938624Skarels /*
41038624Skarels * Reset a channel
41138624Skarels * prevents further I/O until close
41238624Skarels */
dk_reset(chan)41338624Skarels dk_reset(chan)
41438624Skarels {
41538624Skarels register struct dkchan *dkp ;
41638624Skarels register s ;
41738624Skarels
41838624Skarels if (chan > dkdebug)
41938624Skarels log(LOG_ERR, "dkreset %d\n", chan) ;
42038624Skarels s = spl5() ;
42138624Skarels dkp = &dkit[chan] ;
42238624Skarels dkp->dk_state |= DK_RESET ;
42338624Skarels flushall(dkp, 0) ;
42438624Skarels splx(s) ;
42538624Skarels }
42638624Skarels
42738624Skarels
42838624Skarels
42938624Skarels /*
43038624Skarels * Xmit a short control (interrupt) packet
43138624Skarels */
dk_xint(chan,intr)43238624Skarels dk_xint(chan, intr)
43338624Skarels {
43438624Skarels register struct rdevice *raddr ;
43538624Skarels register s ;
43638624Skarels register struct dkchan *dkp ;
43738624Skarels
43838624Skarels dkp = &dkit[chan] ;
43938624Skarels if (chan == 0 || dkp->dk_X < XM_INIT)
44038624Skarels return -1 ;
44138624Skarels s = spl5() ;
44238624Skarels if (chan > dkdebug)
44338624Skarels log(LOG_ERR, "dkxint %d: %o %o\n", chan, (intr & 0377), ((intr >>8)&0377)) ;
44438624Skarels raddr = DKADDR ;
44538624Skarels raddr->dkcsr = D_WRITE ;
44638624Skarels raddr->dko = chan | DKMARK ;
44738624Skarels raddr->dko = SOI ;
44838624Skarels raddr->dko = (intr & 0377) | DKDATA ;
44938624Skarels raddr->dko = ((intr >> 8) & 0377) | DKDATA ;
45038624Skarels raddr->dko = EOI ;
45138624Skarels raddr->dkcsr = D_XPACK ;
45238624Skarels raddr->dko = 0 ;
45338624Skarels if(dkdisabled)
45438624Skarels raddr->dko = 0;
45538624Skarels else
45638624Skarels raddr->dko = ENABS;
45738624Skarels splx(s) ;
45838624Skarels return 0 ;
45938624Skarels }
46038624Skarels
46138624Skarels
46238624Skarels /*
46338624Skarels * Adjust window size
46438624Skarels */
46538624Skarels dk_winsize(chan, win)
46638624Skarels struct diocxwin win;
46738624Skarels {
46838624Skarels return EINVAL; /* For now... */
46938624Skarels }
47038624Skarels
47138624Skarels
47238624Skarels /*
47338624Skarels * Xmit data on a channel
47438624Skarels * NOTE * * * * *
47538624Skarels * Although it is never checked here, buffer addresses
47638624Skarels * in this version of the driver must be kernel addressable.
47738624Skarels */
47838624Skarels dk_xmit(chan, m, eob, ctlchar, endfcn, endparm)
47938624Skarels struct mbuf *m ;
48038624Skarels int (*endfcn)() ;
48138624Skarels caddr_t endparm ;
48238624Skarels {
48338624Skarels register struct dkchan *dkp ;
48438624Skarels register struct mpacket *mbp ;
48538624Skarels register struct mbuf *mb;
48638624Skarels int s ;
48738624Skarels
48838624Skarels s = spl5() ;
48938624Skarels dkp = &dkit[chan] ;
49038624Skarels if ((dkp->dk_state & DK_RESET) || (mb = m_get(M_DONTWAIT,DKMT_HDR)) == NULL) {
49138624Skarels m_freem(m);
49238624Skarels splx(s) ;
49338624Skarels return 0 ;
49438624Skarels }
49538624Skarels
49638624Skarels if (ctlchar == '\001') eob = 0;
49738624Skarels mb->m_len = 0;
49838624Skarels mbp = mtod(mb, struct mpacket *);
49938624Skarels mbp->mp_endfcn = endfcn ;
50038624Skarels mbp->mp_endparm = endparm ;
50138624Skarels mbp->mp_eob = eob;
50238624Skarels mb->m_next = m;
50338624Skarels
50438624Skarels mbp->mp_len = 0;
50538624Skarels while (m) {
50638624Skarels #ifdef notdef
50738624Skarels if (m->m_type != DKMT_DATA && m->m_type != DKMT_CTL) {
50838624Skarels log(LOG_ERR, "dk_xmit %d: got type %x\n", chan, m->m_type);
50938624Skarels m_freem(mb);
51038624Skarels return 0;
51138624Skarels }
51238624Skarels #endif
51338624Skarels mbp->mp_len += m->m_len;
51438624Skarels m = m->m_next;
51538624Skarels }
51638624Skarels
51738624Skarels if ((ctlchar & 0300) == 0100) {
51838624Skarels register struct mbuf *n = mb, *mc;
51938624Skarels
52038624Skarels mc = m_get(M_DONTWAIT, DKMT_CTL);
52138624Skarels if (mc == NULL) {
52238624Skarels m_freem(mb);
52338624Skarels splx(s);
52438624Skarels return 0;
52538624Skarels }
52638624Skarels *mtod(mc, char *) = ctlchar;
52738624Skarels mc->m_len = 1;
52838624Skarels
52938624Skarels /* Append it -- can't use m_cat because type field counts */
53038624Skarels while (n->m_next) n = n->m_next;
53138624Skarels n->m_next = mc;
53238624Skarels mbp->mp_len++;
53338624Skarels ctlchar = 0;
53438624Skarels }
53538624Skarels mbp->mp_ctl = ctlchar;
53638624Skarels
53738624Skarels if ((dkp->dk_state & DK_BUSY) == 0) {
53838624Skarels dkp->dk_state |= DK_BUSY ;
53938624Skarels dkp->dk_curout = mb;
54038624Skarels dkp->dk_xlen = mbp->mp_len ;
54138624Skarels if (chan > dkdebug)
54238624Skarels log(LOG_ERR, "xmit %d: %x len %d\n", chan,
54338624Skarels mb->m_next, mbp->mp_len) ;
54438624Skarels dkxmit(dkp, chan, 2) ;
54538624Skarels splx(s) ;
54638624Skarels return dkp->dk_state ;
54738624Skarels }
54838624Skarels if (IF_QFULL(&dkp->dk_outq)) {
54938624Skarels IF_DROP(&dkp->dk_outq);
55038624Skarels m_freem(mb);
55138624Skarels }
55238624Skarels else
55338624Skarels IF_ENQUEUE(&dkp->dk_outq, mb);
55438624Skarels splx(s) ;
55538624Skarels return dkp->dk_state ;
55638624Skarels }
55738624Skarels
55838624Skarels /*
55938624Skarels * Receive into a block buffer
56038624Skarels */
dk_recv(chan,addr,len,mode,endfcn,endparm)56138624Skarels dk_recv(chan, addr, len, mode, endfcn, endparm)
56238624Skarels caddr_t addr ;
56338624Skarels int (*endfcn)() ;
56438624Skarels caddr_t endparm ;
56538624Skarels {
56638624Skarels register struct dkchan *dkp ;
56738624Skarels register s ;
56838624Skarels
56938624Skarels if (addr == 0) {
57038624Skarels log(LOG_ERR, "dk_recv: channel %d endfcn %x: invalid address specification\n", chan, endfcn);
57138624Skarels return 0;
57238624Skarels }
57338624Skarels
57438624Skarels s = spl5() ;
57538624Skarels dkp = &dkit[chan] ;
57638624Skarels if (dkp->dk_state & (DK_RCV | DK_RESET)) {
57738624Skarels splx(s) ;
57838624Skarels return 0 ;
57938624Skarels }
58038624Skarels dkp->dk_state |= DK_RCV ;
58138624Skarels dkp->dk_endfcn = endfcn ;
58238624Skarels dkp->dk_endparm = endparm ;
58338624Skarels dkp->dk_rmode = mode ;
58438624Skarels dkp->dk_rlen = len ;
58538624Skarels dkp->dk_raddr = (caddr_t)addr ;
58638624Skarels if (chan > dkdebug)
58738624Skarels log(LOG_ERR, "dkrecv %d: %x len %d mode %o\n", chan, (caddr_t)addr, len, mode) ;
58838624Skarels dkrcv(dkp, chan, 2) ;
58938624Skarels splx(s) ;
59038624Skarels return dkp->dk_state ;
59138624Skarels }
59238624Skarels
59338624Skarels
59438624Skarels dk_rabort(chan, nendfcn, nendparm)
59538624Skarels int (*nendfcn)() ;
59638624Skarels caddr_t nendparm ;
59738624Skarels {
59838624Skarels register struct dkchan *dkp ;
59938624Skarels register s ;
60038624Skarels
60138624Skarels dkp = &dkit[chan] ;
60238624Skarels s = spl5() ;
60338624Skarels if (dkp->dk_state & DK_RCV) {
60438624Skarels dkp->dk_state &= ~DK_RCV ;
60538624Skarels if (dkp->dk_rlen) {
60638624Skarels if (chan > dkdebug)
60738624Skarels log(LOG_ERR, "rcvabo %d: rlen %d\n", chan, dkp->dk_rlen) ;
60838624Skarels (*nendfcn)(nendparm, chan, dkp->dk_rlen, DKR_ABORT, 0) ;
60938624Skarels }
61038624Skarels dkp->dk_rlen = 0 ;
61138624Skarels }
61238624Skarels splx(s) ;
61338624Skarels return dkp->dk_state ;
61438624Skarels }
61538624Skarels
61638624Skarels
61738624Skarels
dk_status(chan)61838624Skarels dk_status(chan)
61938624Skarels {
62038624Skarels if (chan >= dk_nchan)
62138624Skarels return 0 ;
62238624Skarels return dkit[chan].dk_state ;
62338624Skarels }
62438624Skarels
62538624Skarels
dk_timeout()62638624Skarels dk_timeout()
62738624Skarels {
62838624Skarels register struct rdevice *raddr;
62938624Skarels register struct dkchan *dkp;
63038624Skarels register chan ;
63138624Skarels int s = spl5();
63238624Skarels
63338624Skarels chan = 0 ;
63438624Skarels for (dkp = &dkit[0]; dkp < &dkit[dk_nchan]; dkp++) {
63538624Skarels if (dkp->dk_X != XM_OFF) {
63638624Skarels if (dkp->dk_X == 0)
63738624Skarels dksend(chan, INIT1) ;
63838624Skarels else
63938624Skarels if (dkp->dk_S != ((dkp->dk_R + 1) & 07)) {
64038624Skarels if (dkp->dk_X & XM_ENQ) {
64138624Skarels dksend(chan, ENQ) ;
64238624Skarels dkp->dk_X &= ~XM_REJ ;
64338624Skarels dkp->dk_enqcnt++;
64438624Skarels URPTRACE(chan, ENQ, dkp);
64538624Skarels }
64638624Skarels else dkp->dk_X |= XM_ENQ;
64738624Skarels }
64838624Skarels }
64938624Skarels chan++ ;
65038624Skarels }
65138624Skarels
65238624Skarels dkstray = 0;
65338624Skarels if(dkdisabled){
65438624Skarels if(dkdisabled++ > 10){
65538624Skarels /* try re-enabling interrupts */
65638624Skarels dkdisabled = 0;
65738624Skarels log(LOG_ERR, "re-enabling DK interface\n");
65838624Skarels raddr = DKADDR;
65938624Skarels raddr->dkcsr = ENABS;
66038624Skarels }
66138624Skarels }
66238624Skarels else {
66338624Skarels /* Look for lost interrupts */
66438624Skarels if (raddr->dkcsr < 0) {
66538624Skarels dkdrlostint++;
66638624Skarels dkdrxint(0);
66738624Skarels }
66838624Skarels }
66938624Skarels
67038624Skarels timeout(dk_timeout, (caddr_t) 0, 1*hz);
67138624Skarels splx(s);
67238624Skarels }
67338624Skarels
dk_cmd(chan,cmd)67438624Skarels dk_cmd(chan, cmd)
67538624Skarels {
67638624Skarels register struct dkchan *dkp ;
67738624Skarels int s = spl5();
67838624Skarels
67938624Skarels if (chan > dkdebug)
68038624Skarels log(LOG_ERR, "dkcmd %d: %o\n", chan, cmd) ;
68138624Skarels dkp = &dkit[chan] ;
68238624Skarels if (cmd & DKC_XINIT) {
68338624Skarels dkp->dk_X = dkp->dk_R = dkp->dk_A = 0 ;
68438624Skarels dkp->dk_S = 1 ;
68538624Skarels dksend(chan, INIT1) ;
68638624Skarels }
68738624Skarels if (cmd & DKC_FLUSH) {
68838624Skarels flushall(dkp, -1) ;
68938624Skarels }
69038624Skarels if (cmd & DKC_SPND)
69138624Skarels dkp->dk_state |= DK_SPND ;
69238624Skarels if (cmd & DKC_RSME) {
69338624Skarels dkp->dk_state &= ~DK_SPND ;
69438624Skarels dkxmit(dkp, chan, 2) ;
69538624Skarels }
69638624Skarels splx(s);
69738624Skarels }
69838624Skarels
69938624Skarels
70038624Skarels static
flushall(dkp,rwflag)70138624Skarels flushall(dkp, rwflag)
70238624Skarels register struct dkchan *dkp ;
70338624Skarels {
70438624Skarels register s ;
70538624Skarels struct mpacket *mbp;
70638624Skarels
70738624Skarels s = spl5() ;
70838624Skarels if ((dkp->dk_state & DK_RCV) && (rwflag >= 0)) {
70938624Skarels dkp->dk_state &= ~DK_RCV ;
71038624Skarels if (dkp->dk_endfcn)
71138624Skarels (*dkp->dk_endfcn)(dkp->dk_endparm, dkp-dkit, dkp->dk_rlen, DKR_ABORT, 0) ;
71238624Skarels dkp->dk_rlen = 0 ;
71338624Skarels }
71438624Skarels if ((dkp->dk_state & DK_BUSY) && (rwflag <= 0)) {
71538624Skarels register struct mbuf *m ;
71638624Skarels
71738624Skarels dkp->dk_xlen = 0;
71838624Skarels if (dkp->dk_curout) {
71938624Skarels mbp = mtod(dkp->dk_curout, struct mpacket *);
72038624Skarels if (mbp->mp_endfcn)
72138624Skarels (mbp->mp_endfcn)(mbp->mp_endparm, dkp-dkit);
72238624Skarels m_freem(dkp->dk_curout);
72338624Skarels dkp->dk_curout = NULL;
72438624Skarels }
72538624Skarels while (1) {
72638624Skarels IF_DEQUEUE(&dkp->dk_outq, m);
72738624Skarels if (!m) break;
72838624Skarels mbp = mtod(m, struct mpacket *);
72938624Skarels if (mbp->mp_endfcn)
73038624Skarels (mbp->mp_endfcn)(mbp->mp_endparm, dkp-dkit);
73138624Skarels m_freem(m);
73238624Skarels }
73338624Skarels dkp->dk_state &= ~DK_BUSY ;
73438624Skarels }
73538624Skarels if ((dkp->dk_state & DK_OPEN) && (rwflag >= 0)) {
73638624Skarels register struct dkpkbufr *dbp ;
73738624Skarels
73838624Skarels dkp->dk_rlen = 0 ;
73938624Skarels dkp->dk_xlen = 0 ;
74038624Skarels dkp->dk_C = 0 ;
74138624Skarels while (dbp = dkp->dk_rq) {
74238624Skarels dkp->dk_rq = dbp->Pnext ;
74338624Skarels dbp->Pnext = dk_Sfree ;
74438624Skarels dk_Sfree = dbp ;
74538624Skarels }
74638624Skarels while (dbp = dkp->dk_rb) {
74738624Skarels dkp->dk_rb = dbp->Pnext ;
74838624Skarels dbp->Pnext = dk_Sfree ;
74938624Skarels dk_Sfree = dbp ;
75038624Skarels }
75138624Skarels }
75238624Skarels splx(s) ;
75338624Skarels }
75438624Skarels
75538624Skarels
75638624Skarels /*
75738624Skarels * Routine to handle completion status
75838624Skarels */
75938624Skarels static
dkkint()76038624Skarels dkkint()
76138624Skarels {
76238624Skarels register struct dkchan *dkp;
76338624Skarels register struct dkstat *sp;
76438624Skarels register chan;
76538624Skarels struct mbuf *m ,*om;
76638624Skarels struct mpacket *mbp;
76738624Skarels static char *cmpltype[] = {"send", "rdb", "eoi", "cntl", "err"};
76838624Skarels
76938624Skarels while (Tstat != Hstat) {
77038624Skarels sp = &dkdr_stat[Hstat];
77138624Skarels chan = sp->k_chan;
77238624Skarels dkp = &dkit[chan];
77338624Skarels if (sp->k_chan > dkdebug) {
77438624Skarels if (sp->k_type >= KS_SEND && sp->k_type <= KS_ERR)
77538624Skarels log(LOG_ERR, "dkdone: type %s chan %d info %o-%o\n",
77638624Skarels cmpltype[sp->k_type-KS_SEND],
77738624Skarels sp->k_chan, sp->k_info1, sp->k_info2) ;
77838624Skarels else log(LOG_ERR, "dkdone: type %d chan %d info %o-%o\n",
77938624Skarels sp->k_type, sp->k_chan, sp->k_info1, sp->k_info2) ;
78038624Skarels }
78138624Skarels if (Hstat==dkdr_nstat-1) Hstat=0; else Hstat++;
78238624Skarels switch(sp->k_type) {
78338624Skarels case KS_CNTL:
78438624Skarels if (dkp->dk_supfcn)
78538624Skarels (*dkp->dk_supfcn)(chan, sp->k_info1) ;
78638624Skarels break ;
78738624Skarels case KS_EOI:
78838624Skarels break ;
78938624Skarels case KS_SEND:
79038624Skarels om = dkp->dk_curout ;
79138624Skarels if (om == NULL) {
79238624Skarels log(LOG_ERR, "dkk: xbufout\n");
79338624Skarels break;
79438624Skarels }
79538624Skarels IF_DEQUEUE(&dkp->dk_outq, m);
79638624Skarels if (m == NULL) {
79738624Skarels dkp->dk_state &= ~DK_BUSY;
79838624Skarels dkp->dk_curout = NULL;
79938624Skarels } else {
80038624Skarels dkp->dk_curout = m;
80138624Skarels mbp = mtod(m, struct mpacket *);
80238624Skarels dkp->dk_xlen = mbp->mp_len ;
80338624Skarels if (chan > dkdebug)
80438624Skarels log(LOG_ERR, "xmiti %d: %x len %d\n", chan,
80538624Skarels m->m_next, mbp->mp_len) ;
80638624Skarels dkxmit(dkp, chan, 0) ;
80738624Skarels }
80838624Skarels mbp = mtod(om, struct mpacket *);
80938624Skarels if (mbp->mp_endfcn != NULL)
81038624Skarels (mbp->mp_endfcn)(mbp->mp_endparm, chan) ;
81138624Skarels m_freem(om);
81238624Skarels break;
81338624Skarels case KS_RDB:
81438624Skarels dkp->dk_state &= ~(DK_RCV|DK_RCVQ) ;
81538624Skarels if (sp->k_info2 == DKR_TIME && dkp->dk_rlen == 0)
81638624Skarels break ; /* another coming later */
81738624Skarels if (dkp->dk_rlen) {
81838624Skarels sp->k_info1 = dkp->dk_rlen ;
81938624Skarels dkp->dk_rlen = 0 ;
82038624Skarels }
82138624Skarels if (dkp->dk_endfcn != NULL)
82238624Skarels (*dkp->dk_endfcn)(dkp->dk_endparm, dkp-dkit, sp->k_info1, sp->k_info2&0377,
82338624Skarels (sp->k_info2>>8)&0377) ;
82438624Skarels break;
82538624Skarels case KS_ERR:
82638624Skarels log(LOG_ERR, "err in dkit.c: chan - %d, code - %o\n",
82738624Skarels chan, sp->k_info1);
82838624Skarels break;
82938624Skarels } /* end switch */
83038624Skarels
83138624Skarels } /* end while */
83238624Skarels }
83338624Skarels
83438624Skarels
83538624Skarels
83638624Skarels
83738624Skarels
83838624Skarels
83938624Skarels
84038624Skarels /* static */
84138624Skarels int dkxmitpanic = 0;
84238624Skarels
84338624Skarels dkxmit(dkp, stechan, intrpt)
84438624Skarels struct dkchan *dkp ;
84538624Skarels {
84638624Skarels register struct rdevice *raddr ;
84738624Skarels register char *ptr ;
84838624Skarels register struct mbuf *m;
84938624Skarels register int wtype;
85038624Skarels short pklen ;
85138624Skarels short mlen, unacked ;
85238624Skarels short blklen ;
85338624Skarels unsigned short totlen ;
85438624Skarels struct mpacket *mbp ;
85538624Skarels #ifdef notdef
85638624Skarels short scheck ;
85738624Skarels #endif
85838624Skarels
85938624Skarels if( dkp->dk_curout == NULL || stechan ==0 )
86038624Skarels return ;
86138624Skarels mbp = mtod(dkp->dk_curout, struct mpacket *);
86238624Skarels raddr = DKADDR ;
86338624Skarels if ((dkp->dk_S & DKBMASK) == (dkp->dk_R & DKBMASK) || (dkp->dk_state & DK_SPND))
86438624Skarels goto ctlchk ;
86538624Skarels if ((dkp->dk_xlen || ((mbp->mp_ctl & 0200) == 0)) && dkp->dk_X < XM_INIT)
86638624Skarels goto ctlchk ;
86738624Skarels #ifdef notdef
86838624Skarels if ((dkp->dk_S & DKBMASK) == ((dkp->dk_R + 1) & DKBMASK))
86938624Skarels scheck = 0 ;
87038624Skarels else
87138624Skarels scheck = 1 ;
87238624Skarels #endif
87338624Skarels
87438624Skarels unacked = ((dkp->dk_S - dkp->dk_A - 1) & 07) * DKBLOCK ;
87538624Skarels mlen = MIN(unacked, dkp->dk_xlen) ;
87638624Skarels totlen = dkp->dk_xlen - mlen;
87738624Skarels if (totlen == 0)
87838624Skarels goto ctlchk ;
87938624Skarels
88038624Skarels /* Skip over stuff sent but not acked */
88138624Skarels for (m = dkp->dk_curout->m_next; m && (mlen > 0); m = m->m_next)
88238624Skarels if (mlen > m->m_len) mlen -= m->m_len;
88338624Skarels else break;
88438624Skarels
88538624Skarels while (totlen && ((dkp->dk_S ^ dkp->dk_R) & DKBMASK)) {
88638624Skarels if (dkxmitpanic) panic("dkxmit -- panic 1");
88738624Skarels blklen = MIN (totlen, DKBLOCK) ;
88838624Skarels pklen = 0 ;
88938624Skarels raddr->dkcsr = D_WRITE ;
89038624Skarels raddr->dko = stechan | DKMARK ;
89138624Skarels while (blklen) {
89238624Skarels if (dkxmitpanic) panic("dkxmit -- panic 2");
89338624Skarels if (m == NULL) panic("dkxmit mlen");
89438624Skarels ptr = mtod(m, char *) + mlen;
89538624Skarels mlen = MIN(blklen, m->m_len - mlen);
89638624Skarels blklen -= mlen;
89738624Skarels wtype = (m->m_type == DKMT_CTL ? 0 : DKDATA);
89838624Skarels while (mlen--) {
89938624Skarels if (dkxmitpanic) panic("dkxmit -- panic 3");
90038624Skarels raddr->dko = (*ptr++ & 0377) | wtype ;
90138624Skarels pklen++ ;
90238624Skarels if ((pklen & (DKCHUNK-1)) == 0) {
90338624Skarels raddr->dkcsr = D_XPACK ;
90438624Skarels raddr->dko = 0 ;
90538624Skarels raddr->dkcsr = D_WRITE ;
90638624Skarels raddr->dko = stechan|DKMARK ;
90738624Skarels }
90838624Skarels }
90938624Skarels if (ptr == (mtod(m, char *) + m->m_len)) {
91038624Skarels m = m->m_next;
91138624Skarels mlen = 0;
91238624Skarels }
91338624Skarels else mlen = ptr - mtod(m, char *);
91438624Skarels }
91538624Skarels blklen = MIN (totlen, DKBLOCK) ;
91638624Skarels if ((pklen & (DKCHUNK-1)) > (DKCHUNK-4)) {
91738624Skarels raddr->dkcsr = D_XPACK ;
91838624Skarels raddr->dko = 0 ;
91938624Skarels raddr->dkcsr = D_WRITE ;
92038624Skarels raddr->dko = stechan|DKMARK ;
92138624Skarels }
92238624Skarels if (blklen == totlen && mbp->mp_eob)
92338624Skarels raddr->dko = BOT ;
92438624Skarels else
92538624Skarels raddr->dko = BOTM ;
92638624Skarels raddr->dko = (blklen & 0377) | DKDATA ;
92738624Skarels raddr->dko = ((blklen>>8) & 0377) | DKDATA ;
92838624Skarels raddr->dko = SEQ + dkp->dk_S ;
92938624Skarels raddr->dkcsr = D_XPACK ;
93038624Skarels raddr->dko = 0 ;
93138624Skarels URPTRACE(stechan, SEQ + dkp->dk_S, dkp);
93238624Skarels dkp->dk_S++ ;
93338624Skarels dkp->dk_S &= 07 ;
93438624Skarels totlen -= blklen ;
93538624Skarels }
93638624Skarels #ifdef notdef
93738624Skarels if (totlen == 0 && dkp->dk_xlen && scheck) {
93838624Skarels raddr->dkcsr = D_WRITE ;
93938624Skarels raddr->dko = stechan|DKMARK ;
94038624Skarels raddr->dko = CHECK ;
94138624Skarels raddr->dkcsr = D_XPACK ;
94238624Skarels raddr->dko = 0 ;
94338624Skarels URPTRACE(stechan, CHECK, dkp);
94438624Skarels }
94538624Skarels #endif
94638624Skarels ctlchk:
94738624Skarels if (mbp->mp_ctl & 0200) {
94838624Skarels raddr->dkcsr = D_WRITE ;
94938624Skarels raddr->dko = stechan|DKMARK ;
95038624Skarels raddr->dko = mbp->mp_ctl & 0377 ;
95138624Skarels raddr->dkcsr = D_XPACK ;
95238624Skarels raddr->dko = 0 ;
95338624Skarels mbp->mp_ctl = 0 ;
95438624Skarels if (dkp->dk_xlen == 0)
95538624Skarels dkreport(KS_SEND, stechan, 0, 0, intrpt) ;
95638624Skarels }
95738624Skarels if(dkdisabled)
95838624Skarels raddr->dkcsr = 0;
95938624Skarels else
96038624Skarels raddr->dkcsr = ENABS ;
96138624Skarels }
96238624Skarels
96338624Skarels
96438624Skarels static
96538624Skarels dkrcv(dkp, stechan, intrpt)
96638624Skarels struct dkchan *dkp ;
96738624Skarels {
96838624Skarels register char *ptr1 ;
96938624Skarels register char *ptr2 ;
97038624Skarels register len ;
97138624Skarels short final ;
97238624Skarels short hibits ;
97338624Skarels struct dkpkbufr *pkb ;
97438624Skarels short tlen ;
97538624Skarels
97638624Skarels if ((dkp->dk_rlen == 0) || (dkp->dk_rq == NULL))
97738624Skarels return ;
97838624Skarels final = 0 ;
97938624Skarels tlen = 0 ;
98038624Skarels while (final == 0 && (pkb = dkp->dk_rq)) {
98138624Skarels if (dkp->dk_rlen == 0)
98238624Skarels final |= DKR_FULL ;
98338624Skarels ptr1 = &pkb->Pdata[0] ;
98438624Skarels ptr2 = dkp->dk_raddr ;
98538624Skarels len = MIN(pkb->Plen, dkp->dk_rlen) ;
98638624Skarels hibits = pkb->Phibits ;
98738624Skarels while (len--) {
98838624Skarels if (hibits < 0)
98938624Skarels break ;
99038624Skarels hibits <<= 1 ;
99138624Skarels *ptr2++ = *ptr1++ ;
99238624Skarels }
99338624Skarels len = ptr2 - dkp->dk_raddr ;
99438624Skarels tlen += len ;
99538624Skarels dkp->dk_rlen -= len ;
99638624Skarels dkp->dk_raddr = ptr2 ;
99738624Skarels if ((pkb->Plen -= len) && hibits < 0) {
99838624Skarels final |= ((*ptr1++ & 0377) << 8) | DKR_CNTL ;
99938624Skarels hibits <<= 1 ;
100038624Skarels pkb->Plen-- ;
100138624Skarels }
100238624Skarels if (len = pkb->Plen) {
100338624Skarels ptr2 = &pkb->Pdata[0] ;
100438624Skarels while (len--)
100538624Skarels *ptr2++ = *ptr1++ ;
100638624Skarels pkb->Phibits = hibits ;
100738624Skarels }
100838624Skarels while (pkb && (pkb->Plen == 0)) {
100938624Skarels if ((pkb->Pseq & 0370) == ACK) {
101038624Skarels pkb->Pseq += ECHO - ACK ;
101138624Skarels final |= dkp->dk_rmode & DKR_BLOCK ;
101238624Skarels }
101338624Skarels if (pkb->Pseq) {
101438624Skarels dksend(stechan, pkb->Pseq) ;
101538624Skarels dkp->dk_C = pkb->Pseq ;
101638624Skarels }
101738624Skarels dkp->dk_rq = pkb->Pnext ;
101838624Skarels pkb->Pnext = dk_Sfree ;
101938624Skarels dk_Sfree = pkb ;
102038624Skarels pkb = dkp->dk_rq ;
102138624Skarels }
102238624Skarels }
102338624Skarels if (tlen && (dkp->dk_rmode & DKR_TIME))
102438624Skarels final |= DKR_TIME ;
102538624Skarels if (dkp->dk_rlen == 0)
102638624Skarels final |= DKR_FULL ;
102738624Skarels if (final && (final != DKR_TIME || ((dkp->dk_state & DK_RCVQ) == 0))) {
102838624Skarels dkp->dk_state |= DK_RCVQ ;
102938624Skarels len = dkp->dk_rlen ;
103038624Skarels if (final != DKR_TIME)
103138624Skarels dkp->dk_rlen = 0 ;
103238624Skarels dkreport(KS_RDB, stechan, len, final, (final == DKR_TIME)?2:intrpt) ;
103338624Skarels }
103438624Skarels }
103538624Skarels
103638624Skarels
103738624Skarels
103838624Skarels static
dksend(stechan,val)103938624Skarels dksend(stechan, val)
104038624Skarels {
104138624Skarels register struct rdevice *raddr ;
104238624Skarels register savcsr ;
104338624Skarels
104438624Skarels if(stechan == 0)
104538624Skarels return;
104638624Skarels
104738624Skarels raddr = DKADDR ;
104838624Skarels savcsr = raddr->dkcsr ;
104938624Skarels raddr->dkcsr = D_WRITE ;
105038624Skarels raddr->dko = stechan| DKMARK ;
105138624Skarels raddr->dko = val ;
105238624Skarels raddr->dkcsr = D_XPACK ;
105338624Skarels raddr->dko = 0 ;
105438624Skarels raddr->dkcsr = savcsr ;
105538624Skarels }
105638624Skarels
105738624Skarels
105838624Skarels /*ARGSUSED*/
dkdrrint(dev)105938624Skarels dkdrrint(dev) /* ?? */ /* needed for UNIX OS */
106038624Skarels {
106138624Skarels register struct rdevice *raddr ;
106238624Skarels register c ;
106338624Skarels register cnt;
106438624Skarels
106538624Skarels #ifdef lint
106638624Skarels c = 0; cnt = c;
106738624Skarels #endif
106838624Skarels cnt = 0;
106938624Skarels raddr = DKADDR ;
107038624Skarels raddr->dkcsr = D_OSEQ ;
107138624Skarels if((raddr->dkcsr & DKTDONE) == 0){
107238624Skarels if(dkstray++ >= MAX_STRAY){
107338624Skarels log(LOG_ERR, "DK err 1 (Cabling?)\n");
107438624Skarels raddr->dkcsr = 0;
107538624Skarels dkdisabled = 1;
107638624Skarels return;
107738624Skarels }
107838624Skarels }
107938624Skarels while (raddr->dkcsr & DKTDONE){
108038624Skarels c = raddr->dki ;
108138624Skarels if(cnt++ > 65){
108238624Skarels log(LOG_ERR, "DK err 2 (Cabling?)\n");
108338624Skarels raddr->dkcsr = 0;
108438624Skarels dkdisabled = 1;
108538624Skarels return;
108638624Skarels }
108738624Skarels }
108838624Skarels raddr->dkcsr = ENABS ;
108938624Skarels if (Hstat != Tstat)
109038624Skarels dkkint() ;
109138624Skarels }
109238624Skarels
109338624Skarels /*ARGSUSED*/
dkdrxint(dev)109438624Skarels dkdrxint(dev) /* ?? */
109538624Skarels {
109638624Skarels register struct rdevice *raddr ;
109738624Skarels register char *ptr ;
109838624Skarels struct dkchan *dkp ;
109938624Skarels register c ;
110038624Skarels short badpacks ;
110138624Skarels struct dkpkbufr *pkb ;
110238624Skarels short stechan ;
110338624Skarels short len, xlen ;
110438624Skarels unsigned short bitloc ;
110538624Skarels
110638624Skarels badpacks = 0 ;
110738624Skarels raddr = DKADDR ;
110838624Skarels pkb = NULL ;
110938624Skarels if(raddr->dkcsr >= 0){
111038624Skarels if(dkstray++ > MAX_STRAY){
111138624Skarels log(LOG_ERR, "DK err 3 (Cabling?)\n");
111238624Skarels goto disable;
111338624Skarels }
111438624Skarels }
111538624Skarels while (raddr->dkcsr < 0) {
111638624Skarels raddr->dkcsr = D_READ ;
111738624Skarels c = raddr->dki ;
111838624Skarels while (raddr->dkcsr < 0 && (c & DKMARK)) {
111938624Skarels c &= 0777 ;
112038624Skarels if (c >= dk_nchan) {
112138624Skarels if (++badpacks > 20) {
112238624Skarels log(LOG_ERR, "DK err 4 (Cabling?)\n");
112338624Skarels dkreport(KS_ERR, 0, 2, 0, 1) ;
112438624Skarels goto disable ;
112538624Skarels }
112638624Skarels break ;
112738624Skarels }
112838624Skarels /* discard all chl 0 packets;
112938624Skarels * the LDI version of the CPM-DR and CPM-422
113038624Skarels * puts out packets on chl 0 occasionally.
113138624Skarels */
113238624Skarels if(c == 0) break;
113338624Skarels
113438624Skarels dkp = &dkit[c] ;
113538624Skarels stechan = c ;
113638624Skarels qpkb:
113738624Skarels if (pkb && pkb->Plen) {
113838624Skarels dkrcvq(stechan, dkp, pkb, 0) ;
113938624Skarels pkb = NULL ;
114038624Skarels }
114138624Skarels if (pkb == NULL) {
114238624Skarels if ((pkb = dk_Sfree) != NULL) {
114338624Skarels dk_Sfree = pkb->Pnext ;
114438624Skarels pkb->Pseq = 0 ;
114538624Skarels pkb->Plen = 0 ;
114638624Skarels pkb->Pnext = NULL ;
114738624Skarels pkb->Phibits = 0 ;
114838624Skarels } else {
114938624Skarels /*
115038624Skarels ** Oops, no more dkpkbufr's.
115138624Skarels ** Let outer loop gobble up
115238624Skarels ** the entire packet.
115338624Skarels ** Report to the console
115438624Skarels ** every 100th occurrence.
115538624Skarels */
115638624Skarels if ( dknopkb++ >= 100 ) {
115738624Skarels dknopkb = 1 ;
115838624Skarels dkreport(KS_ERR, 0, 3, 0, 1) ;
115938624Skarels }
116038624Skarels break ;
116138624Skarels }
116238624Skarels }
116338624Skarels raddr->dkcsr = D_READ ;
116438624Skarels ptr = &pkb->Pdata[0] ;
116538624Skarels bitloc = 0100000 ;
116638624Skarels while (raddr->dkcsr < 0 && ((c = raddr->dki) & DKMARK) == 0)
116738624Skarels switch (c = c & 0777) {
116838624Skarels case NULL:
116938624Skarels break ;
117038624Skarels case AINIT:
117138624Skarels dkp->dk_X = XM_INIT ;
117238624Skarels dkp->dk_R = 0 ;
117338624Skarels dkp->dk_S = 1 ;
117438624Skarels dkp->dk_A = 0 ;
117538624Skarels dkxmit(dkp, stechan, 1) ;
117638624Skarels raddr->dkcsr = D_READ ;
117738624Skarels break ;
117838624Skarels case INIT0:
117938624Skarels dksend(stechan, AINIT) ;
118038624Skarels dkp->dk_trmode = 0 ;
118138624Skarels dkp->dk_C = dkp->dk_rseq = 0 ;
118238624Skarels break ;
118338624Skarels case INIT1:
118438624Skarels dksend(stechan, AINIT) ;
118538624Skarels dkp->dk_trmode = 1 ;
118638624Skarels dkp->dk_C = dkp->dk_tail1 = dkp->dk_tail2 = dkp->dk_rseq = 0 ;
118738624Skarels while (pkb) {
118838624Skarels pkb->Pnext = dk_Sfree ;
118938624Skarels dk_Sfree = pkb ;
119038624Skarels if (pkb = dkp->dk_rq)
119138624Skarels dkp->dk_rq = pkb->Pnext ;
119238624Skarels if (pkb == NULL)
119338624Skarels if (pkb = dkp->dk_rb)
119438624Skarels dkp->dk_rb = pkb->Pnext ;
119538624Skarels }
119638624Skarels goto qpkb ;
119738624Skarels case INITREQ:
119838624Skarels dksend(stechan, INIT1) ;
119938624Skarels dkp->dk_X = 0 ;
120038624Skarels break ;
120138624Skarels case ENQ:
120238624Skarels dksend(stechan, dkp->dk_C) ;
120338624Skarels case CHECK:
120438624Skarels dksend(stechan, ACK+dkp->dk_rseq) ;
120538624Skarels while (pkb) {
120638624Skarels pkb->Pnext = dk_Sfree ;
120738624Skarels dk_Sfree = pkb ;
120838624Skarels if (pkb = dkp->dk_rb)
120938624Skarels dkp->dk_rb = pkb->Pnext ;
121038624Skarels }
121138624Skarels dkp->dk_rblen = 0 ;
121238624Skarels goto qpkb ;
121338624Skarels case EOI:
121438624Skarels if (dkp->dk_tail1 == ((SOI<<8)|2))
121538624Skarels dkreport(KS_EOI, stechan, dkp->dk_tail2, 0, 1) ;
121638624Skarels dkp->dk_tail1 = 0 ;
121738624Skarels break ;
121838624Skarels default:
121938624Skarels if (c & DKDATA) {
122038624Skarels if (dkp->dk_tail1) {
122138624Skarels dkp->dk_tail2 = ((dkp->dk_tail2 >> 8) & 0377) | (c<<8) ;
122238624Skarels dkp->dk_tail1++ ;
122338624Skarels if ((dkp->dk_tail1 & 0377) > 3)
122438624Skarels dkp->dk_tail1 = 0 ;
122538624Skarels } else {
122638624Skarels *ptr++ = c & 0377 ;
122738624Skarels pkb->Plen++ ;
122838624Skarels bitloc >>= 1 ;
122938624Skarels }
123038624Skarels break ;
123138624Skarels }
123238624Skarels if (((c & 0770) == ECHO) || ((c & 0770) == REJ)) {
123338624Skarels URPTRACE(stechan, c, dkp);
123438624Skarels dkp->dk_R = c & 07 ;
123538624Skarels if (((dkp->dk_S - dkp->dk_R - 1) & 07) <
123638624Skarels ((dkp->dk_S - dkp->dk_A - 1) & 07)) {
123738624Skarels gotack:
123838624Skarels dkp->dk_X &= ~(XM_REJ | XM_ENQ);
123938624Skarels xlen = dkp->dk_xlen ;
124038624Skarels len = ((c - dkp->dk_A) & 07) * DKBLOCK ;
124138624Skarels len = MIN(len, xlen);
124238624Skarels dkp->dk_xlen -= len;
124338624Skarels if (dkp->dk_curout)
124438624Skarels m_adj(dkp->dk_curout->m_next, len) ;
124538624Skarels dkp->dk_A = c & 07 ;
124638624Skarels if (len || xlen)
124738624Skarels if ((dkp->dk_xlen) == 0)
124838624Skarels dkreport(KS_SEND, stechan, 0, 0, 1) ;
124938624Skarels }
125038624Skarels dkxmit(dkp, stechan, 1) ;
125138624Skarels raddr->dkcsr = D_READ ;
125238624Skarels if ((c & 0770) == REJ && ((dkp->dk_X & XM_REJ) == 0)) {
125338624Skarels dkp->dk_rejcnt++;
125438624Skarels gotrej:
125538624Skarels dkp->dk_S = (c+1) & 07 ;
125638624Skarels dkxmit(dkp, stechan, 1) ;
125738624Skarels raddr->dkcsr = D_READ ;
125838624Skarels dkp->dk_X |= XM_REJ ;
125938624Skarels }
126038624Skarels break ;
126138624Skarels }
126238624Skarels if ((c & 0770) == ACK) {
126338624Skarels URPTRACE(stechan, c, dkp);
126438624Skarels if (dkp->dk_A != (c & 07))
126538624Skarels goto gotack ;
126638624Skarels if ((dkp->dk_X & XM_REJ) == 0) {
126738624Skarels dkp->dk_ackrejcnt++;
126838624Skarels goto gotrej ;
126938624Skarels }
127038624Skarels break ;
127138624Skarels }
127238624Skarels if ((c & 0774) == BOT) {
127338624Skarels dkp->dk_tail1 = c << 8 ;
127438624Skarels break ;
127538624Skarels }
127638624Skarels if ((c & 0770) == SEQ) {
127738624Skarels pkb->Pseq = c - SEQ + ECHO ;
127838624Skarels dkrcvq(stechan, dkp, pkb, 0) ;
127938624Skarels if (dkp->dk_trmode) {
128038624Skarels if (dkp->dk_rblen == dkp->dk_tail2 &&
128138624Skarels (dkp->dk_tail1 & 0377) == 2 &&
128238624Skarels ((dkp->dk_tail1 >> 8) & 0377) != SOI &&
128338624Skarels ((dkp->dk_rseq+1) & 07) == (c & 07)) {
128438624Skarels dkp->dk_rseq = c & 07 ;
128538624Skarels if (((dkp->dk_tail1>>8) & 0377) != BOTM)
128638624Skarels pkb->Pseq += ACK - ECHO ;
128738624Skarels dkrcvq(stechan, dkp, dkp->dk_rb, 1) ;
128838624Skarels } else {
128938624Skarels while (pkb = dkp->dk_rb) {
129038624Skarels dkp->dk_rb = pkb->Pnext ;
129138624Skarels pkb->Pnext = dk_Sfree ;
129238624Skarels dk_Sfree = pkb ;
129338624Skarels }
129438624Skarels pkb = dk_Sfree ;
129538624Skarels dk_Sfree = pkb->Pnext ;
129638624Skarels pkb->Plen = 0 ;
129738624Skarels pkb->Pnext = NULL ;
129838624Skarels pkb->Pseq = REJ + dkp->dk_rseq ;
129938624Skarels dkp->dk_srejcnt++;
130038624Skarels if (((dkp->dk_tail1>>8) & 0377) == BOTS) {
130138624Skarels dkp->dk_rseq = c & 07 ;
130238624Skarels pkb->Pseq = ECHO + dkp->dk_rseq ;
130338624Skarels }
130438624Skarels dkrcvq(stechan, dkp, pkb, 1) ;
130538624Skarels }
130638624Skarels dkp->dk_rb = NULL ;
130738624Skarels dkp->dk_rblen = 0 ;
130838624Skarels dkp->dk_tail1 = 0 ;
130938624Skarels } else
131038624Skarels /* always keep seq no up to date */
131138624Skarels dkp->dk_rseq = c & 07;
131238624Skarels pkb = NULL ;
131338624Skarels goto qpkb ;
131438624Skarels }
131538624Skarels if (c & 0200) {
131638624Skarels dkreport(KS_CNTL, stechan, c, 0, 1) ;
131738624Skarels raddr->dkcsr = D_READ ;
131838624Skarels } else {
131938624Skarels *ptr++ = c & 0377 ;
132038624Skarels pkb->Plen++ ;
132138624Skarels pkb->Phibits |= bitloc ;
132238624Skarels bitloc >>= 1 ;
132338624Skarels }
132438624Skarels }
132538624Skarels if (pkb && pkb->Plen) {
132638624Skarels dkrcvq(stechan, dkp, pkb, 0) ;
132738624Skarels pkb = NULL ;
132838624Skarels }
132938624Skarels }
133038624Skarels }
133138624Skarels
133238624Skarels if (pkb) {
133338624Skarels if (pkb->Plen)
133438624Skarels dkrcvq(stechan, dkp, pkb, 0) ;
133538624Skarels else {
133638624Skarels pkb->Pnext = dk_Sfree ;
133738624Skarels dk_Sfree = pkb ;
133838624Skarels }
133938624Skarels }
134038624Skarels raddr->dkcsr = ENABS ;
134138624Skarels return;
134238624Skarels
134338624Skarels disable:
134438624Skarels if(pkb){
134538624Skarels pkb->Pnext = dk_Sfree;
134638624Skarels dk_Sfree = pkb;
134738624Skarels }
134838624Skarels raddr->dkcsr = 0;
134938624Skarels dkdisabled = 1;
135038624Skarels }
135138624Skarels
dkrcvq(stechan,dkp,npkb,where)135238624Skarels dkrcvq(stechan, dkp, npkb, where)
135338624Skarels register struct dkchan *dkp ;
135438624Skarels struct dkpkbufr *npkb ;
135538624Skarels {
135638624Skarels register struct dkpkbufr *pkb ;
135738624Skarels int i ;
135838624Skarels
135938624Skarels i = 0 ;
136038624Skarels if (dkp->dk_trmode && where == 0)
136138624Skarels pkb = (struct dkpkbufr *)&dkp->dk_rb ;
136238624Skarels else
136338624Skarels pkb = (struct dkpkbufr *)&dkp->dk_rq ;
136438624Skarels
136538624Skarels while (pkb->Pnext) {
136638624Skarels pkb = pkb->Pnext ;
136738624Skarels i++ ;
136838624Skarels }
136938624Skarels if ( i >= PKBHOG ) {
137038624Skarels /*
137138624Skarels ** This channel has too many buffers.
137238624Skarels ** Do not queue any more.
137338624Skarels ** Return the new buffer to the free list.
137438624Skarels */
137538624Skarels npkb->Pnext = dk_Sfree ;
137638624Skarels dk_Sfree = npkb ;
137738624Skarels return ;
137838624Skarels }
137938624Skarels pkb->Pnext = npkb ;
138038624Skarels
138138624Skarels if (dkp->dk_trmode && where == 0)
138238624Skarels dkp->dk_rblen += npkb->Plen ;
138338624Skarels else
138438624Skarels dkrcv(dkp, stechan, 1) ;
138538624Skarels }
138638624Skarels
138738624Skarels
138838624Skarels
dkreport(type,chan,info1,info2,intrpt)138938624Skarels dkreport(type, chan, info1, info2, intrpt)
139038624Skarels /* intrpt parameter controlls whether the pdp-11 interrupt is called.
139138624Skarels * Value 0 says no (means dkxint queued already)
139238624Skarels * Value 1 says call it immediately (like from dr11c interrupt)
139338624Skarels * Value 2 says to queue a call as soon as processor priority lowers
139438624Skarels * (by sending a dummy packet on a channel and getting dkxint)
139538624Skarels */
139638624Skarels {
139738624Skarels register struct dkstat *sp;
139838624Skarels
139938624Skarels if ((Tstat + 1) % dkdr_nstat == Hstat) { /* room in queue? */
140038624Skarels log(LOG_ERR, "dkit_dr: No room in status queue, Channel %d\n", chan);
140138624Skarels return;
140238624Skarels }
140338624Skarels
140438624Skarels sp = &dkdr_stat[Tstat] ;
140538624Skarels sp->k_chan = chan ;
140638624Skarels sp->k_type = type ;
140738624Skarels sp->k_info1 = info1 ;
140838624Skarels sp->k_info2 = info2 ;
140938624Skarels if (Tstat == dkdr_nstat-1) Tstat = 0 ; else Tstat++ ;
141038624Skarels if (intrpt==1) {
141138624Skarels dkkint() ;
141238624Skarels } else if (intrpt==2) {
141338624Skarels register struct rdevice *raddr ;
141438624Skarels raddr = DKADDR ;
141538624Skarels raddr->dkcsr = D_WRITE ;
141638624Skarels
141738624Skarels /* Chl (dk_nchan-1) is used instead of 511 because
141838624Skarels * the LDI switch module will complain if we use
141938624Skarels * a chl outside the range set up in its route tables.
142038624Skarels */
142138624Skarels raddr->dko = (dk_nchan-1) | DKMARK ;
142238624Skarels
142338624Skarels /*
142438624Skarels * A null is used here because it should always
142538624Skarels * be ignored by the far end of the circuit.
142638624Skarels */
142738624Skarels raddr->dko = 0 ;
142838624Skarels
142938624Skarels raddr->dkcsr = D_XPACK ;
143038624Skarels raddr->dko = 0 ;
143138624Skarels raddr->dkcsr = ENABS ;
143238624Skarels }
143338624Skarels }
143438624Skarels
143538624Skarels #ifdef URPDEBUG
143638624Skarels struct dkurps {
143738624Skarels char dku_ctl;
143838624Skarels char dku_S;
143938624Skarels char dku_R;
144038624Skarels char dku_A;
144138624Skarels } dkurps[URPDEBUG];
144238624Skarels int dkurpsize = URPDEBUG;
144338624Skarels
144438624Skarels struct dkurps *dkurpsp = dkurps;
144538624Skarels int dkurpreset;
144638624Skarels
dkurptrace(ctl,dkp)144738624Skarels dkurptrace(ctl, dkp) char ctl; register struct dkchan *dkp;
144838624Skarels {
144938624Skarels #ifdef lint
145038624Skarels dkurpsize = dkurpsize;
145138624Skarels #endif
145238624Skarels if (dkurpreset) {
145338624Skarels dkurpsp = dkurps;
145438624Skarels dkurpreset = 0;
145538624Skarels }
145638624Skarels dkurpsp->dku_ctl = ctl;
145738624Skarels dkurpsp->dku_S = dkp->dk_S;
145838624Skarels dkurpsp->dku_R = dkp->dk_R;
145938624Skarels dkurpsp->dku_A = dkp->dk_A;
146038624Skarels if (++dkurpsp == dkurps+URPDEBUG)
146138624Skarels dkurpsp = dkurps;
146238624Skarels }
146338624Skarels #endif URPDEBUG
146438624Skarels #endif
1465