9 * There are two kinds of messages: urgent and relaxed.
11 * Urgent messages may be due for speedy transmission. The due urgent
12 * message with the highest priority is always transmitted as soon as
13 * a slot is available. This is known as `speedy transmission'.
15 * When no urgent messages are due for speedy transmission, messages
16 * (urgent or relaxed) are transmitted in a round-robin fashion. This
17 * round-robin transmission is completely independent of the speedy
20 * Each urgent message is due for speedy transmission as follows:
21 * - When it is first queued and has not yet been
22 * speedily transmitted:
23 * immediately due, with maximum priority
24 * - Following each speedy transmission:
25 * due after an interval since the previous
26 * transmission; this interval increases exponentially
27 * for each transmission
28 * with priority which decreases with later transmissions
29 * until it has been speedily transmitted a certain number of times
31 * no longer ever due; subject to round-robin transmission only.
32 * Intervals are measured in messages regardless of length.
36 * All messages are on one of the relaxed queues; urgent messages
37 * are on the relaxed[0] queue and messages which are explicitly
38 * relaxed are on the relaxed[1] queue. This gives the previously-
39 * urgent messages 50% of the bandwidth.
40 * There is one queue for each speedy retransmission; messages are on
41 * it in chronological order of dueness.
46 #include "retransmit-table.h"
48 #define RETRANSMIT_TIME_SIGNED_MAX ((~(Retransmit__Time)0) >> 1)
50 static PicInsn linefill;
52 static DLIST2_HEAD(RetransmitRelaxedNode) relaxed[2];
53 static int last_relaxed_qn;
54 static Retransmit__Time elapsed;
55 static PerSpeedyTrans speedies[] = SPEEDIESINIT;
57 static void debug_hex(const Byte *d, int l) {
59 for (i=0; i<l; i++) DPRINTFA(" %02x", d[i]);
62 static void debug_message(const PicInsn *pi, const Nmra *n) {
63 DPRINTFA(" :"); debug_hex(pi->d, pi->l);
64 if (n) { DPRINTFA(" <="); debug_hex(n->d, n->l); }
68 static void retransmit_this(const PicInsn *pi) {
69 if (DEBUGP(retransmit,message)) debug_message(pi, 0);
74 void retransmit_start(void) {
79 nmra_encodeforpic(&n, &linefill);
81 retransmit_something();
82 retransmit_something();
83 retransmit_something();
86 void retransmit_something(void) {
88 RetransmitUrgentNode *urg;
89 RetransmitRelaxedNode *rlx;
92 DPRINTF1(retransmit,message,"xmit ");
94 for (ix=0, spd=speedies;
98 if (!urg) { DPRINTF2("-"); continue; }
99 if (elapsed - urg->u.when > RETRANSMIT_TIME_SIGNED_MAX)
100 { DPRINTF2("<"); continue; }
102 DPRINTF2("%*s spd%-2d", SPEEDYCOUNT-ix,"", ix);
104 /* found one to transmit: */
105 DLIST2_REMOVE(spd->queue,urg,u.queue);
106 if (++ix < SPEEDYCOUNT) {
107 DPRINTF2(" ->spd%-2d =%p",ix, urg);
109 urg->u.when= elapsed + spd->interval;
111 DLIST2_APPEND(spd->queue,urg,u.queue);
113 DPRINTF2(" ->rlx =%p", urg);
116 retransmit_this(&urg->pi);
120 for (ix=0; ix<2; ix++) {
121 int qn= last_relaxed_qn ^ ix ^ 1;
122 rlx= relaxed[qn].head;
123 if (!rlx) { DPRINTF2("%d",qn); continue; }
125 DPRINTF2("%-*s rlx%d =%p", 2-ix,"", qn, rlx);
127 DLIST2_REMOVE(relaxed[qn],rlx,rr);
128 DLIST2_APPEND(relaxed[qn],rlx,rr);
131 retransmit_this(&rlx->pi);
135 serial_transmit(&linefill);
138 static void relaxed_queue(int qn, RetransmitRelaxedNode *rn, Nmra *n,
139 const char *debugwhat) {
141 if (n) { nmra_addchecksum(n); nmra_encodeforpic(n, &rn->pi); }
142 DPRINTF1(retransmit,queue, "%s %p", debugwhat, rn);
143 if (DP) debug_message(&rn->pi, n);
144 DLIST2_PREPEND(relaxed[qn],rn,rr);
146 static void relaxed_cancel(int qn, RetransmitRelaxedNode *rlx,
147 const char *debugwhat) {
148 if (debugwhat) DPRINTF(retransmit,queue, "%s %p\n", debugwhat, &rlx->pi);
149 DLIST2_REMOVE(relaxed[qn],rlx,rr);
152 void retransmit_relaxed_queue(RetransmitRelaxedNode *rn, Nmra *n) {
153 relaxed_queue(1,rn,n, "retransmit_relaxed_queue");
155 void retransmit_relaxed_cancel(RetransmitRelaxedNode *rlx) {
156 relaxed_cancel(1,rlx, "retransmit_relaxed_cancel");
159 static void urgent_queue(RetransmitUrgentNode *urg, Nmra *n,
160 const char *debugwhat) {
161 relaxed_queue(0, &urg->u.relaxed, n, debugwhat);
163 urg->u.when= elapsed;
164 DLIST2_APPEND(speedies[0].queue,urg,u.queue);
166 static void urgent_cancel(RetransmitUrgentNode *urg,
167 const char *debugwhat) {
169 DLIST2_REMOVE(speedies[urg->u.ix].queue,urg,u.queue);
170 relaxed_cancel(0, &urg->u.relaxed, debugwhat);
173 void retransmit_urgent_queue(RetransmitUrgentNode *urg, Nmra *n) {
174 urgent_queue(urg,n, "retransmit_urgent_queue");
176 void retransmit_urgent_queue_relaxed(RetransmitUrgentNode *urg, Nmra *n){
177 relaxed_queue(0, &urg->u.relaxed, n, "retransmit_urgent_queue_relaxed");
179 urg->u.when= elapsed;
181 void retransmit_urgent_requeue(RetransmitUrgentNode *rn, Nmra *n) {
182 urgent_cancel(rn, 0);
183 urgent_queue(rn, n, "retransmit_urgent_requeue");
185 void retransmit_urgent_cancel(RetransmitUrgentNode *urg) {
186 urgent_cancel(urg, "retransmit_urgent_cancel");
190 void on_pic_nmradone(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
192 if (sta_state == Sta_Run || sta_state == Sta_Manual)
194 retransmit_something();
196 if (sta_state > Sta_Settling)
197 die("PIC sent NMRADONE in %s", stastatelist[sta_state]);