BYTE acsi_cmd(BYTE ReadNotWrite, BYTE *cmd, BYTE cmdLength, BYTE *buffer, WORD sectorCount) { DWORD status; WORD i, wr1, wr2; //--------------------- for(i=0; i<4*12; i++) { // copy cmd1 to cmd0, cmd2 to cmd1, and so on cmdLog[i] = cmdLog[i + 12]; } for(i=0; i<cmdLength; i++) { // copy the new command to the end of cmdLog cmdLog[48 + i] = cmd[i]; } //--------------------- *FLOCK = -1; /* disable FDC operations */ setdma((DWORD) buffer); /* setup DMA transfer address */ /*********************************/ /* transfer 0th cmd byte */ *dmaAddrMode = NO_DMA | HDC; /* write 1st byte (0) with A1 low */ *dmaAddrData = cmd[0]; *dmaAddrMode = NO_DMA | HDC | A0; /* A1 high again */ if (qdone() != OK) { /* wait for ack */ hdone(); /* restore DMA device to normal */ cmdLog[59] = ACSIERROR; return ACSIERROR; } /*********************************/ /* transfer middle cmd bytes */ for(i=1; i<(cmdLength-1); i++) { *dmaAddrData = cmd[i]; *dmaAddrMode = NO_DMA | HDC | A0; if (qdone() != OK) { /* wait for ack */ hdone(); /* restore DMA device to normal */ cmdLog[59] = ACSIERROR; return ACSIERROR; } } /* wr1 and wr2 are defined so we could toggle R/W bit and then setup Read / Write operation */ if(ReadNotWrite==1) { wr1 = DMA_WR; wr2 = 0; } else { wr1 = 0; wr2 = DMA_WR; } if(acsiBufferClear) { *dmaAddrMode = wr1 | NO_DMA | SC_REG; /* clear FIFO = toggle R/W bit */ } *dmaAddrMode = wr2 | NO_DMA | SC_REG; /* and select sector count reg */ *dmaAddrSectCnt = sectorCount; /* write sector cnt to DMA device */ *dmaAddrMode = wr2 | NO_DMA | HDC | A0; /* select DMA data register again */ *dmaAddrData = cmd[cmdLength - 1]; /* transfer the last command byte */ *dmaAddrMode = wr2; /* start DMA transfer */ status = endcmd(wr2 | NO_DMA | HDC | A0); /* wait for DMA completion */ hdone(); /* restore DMA device to normal */ cmdLog[59] = status; return status; }
// -------------------------------------- void acsi_cmd(BYTE ReadNotWrite, BYTE *cmd, BYTE cmdLength, BYTE *buffer, WORD sectorCount) { WORD i, wr1, wr2; //-------- // init result to fail codes hdIf.success = FALSE; hdIf.statusByte = ACSIERROR; hdIf.phaseChanged = FALSE; //------------------ if(hdIf.forceFlock) { // should force FLOCK? just set it *FLOCK = -1; // disable FDC operations } else { // should wait before acquiring FLOCK? wait... // try to acquire FLOCK if possible DWORD end = getTicks() + 200; // calculate the terminating tick count, where we should stop looking for unlocked FLOCK WORD locked; while(1) { // while not time out, try again locked = *FLOCK; // read current lock value if(!locked) { // if not locked, lock and continue *FLOCK = -1; // disable FDC operations break; } if(getTicks() >= end) { // on time out - fail, return ACSIERROR hdIf.success = FALSE; return; } } } //------------------ // FLOCK acquired, continue with rest setdma((DWORD) buffer); // setup DMA transfer address //******************************* // transfer 0th cmd byte *dmaAddrMode = NO_DMA | HDC; // write 1st byte (0) with A1 low *dmaAddrData = cmd[0]; *dmaAddrMode = NO_DMA | HDC | A0; // A1 high again if (qdone() != OK) { // wait for ack hdone(); // restore DMA device to normal hdIf.success = FALSE; return; } //******************************* // transfer middle cmd bytes for(i=1; i<(cmdLength-1); i++) { *dmaAddrData = cmd[i]; *dmaAddrMode = NO_DMA | HDC | A0; if (qdone() != OK) { // wait for ack hdone(); // restore DMA device to normal hdIf.success = FALSE; return; } } // wr1 and wr2 are defined so we could toggle R/W bit and then setup Read / Write operation if(ReadNotWrite==1) { wr1 = DMA_WR; wr2 = HDC | A0; } else { wr1 = 0; wr2 = DMA_WR | HDC | A0; } *dmaAddrMode = wr1 | NO_DMA | SC_REG; // clear FIFO = toggle R/W bit *dmaAddrMode = wr2 | NO_DMA | SC_REG; // and select sector count reg *dmaAddrSectCnt = sectorCount; // write sector cnt to DMA device *dmaAddrMode = wr2 | NO_DMA | HDC | A0; // select DMA data register again *dmaAddrData = cmd[cmdLength - 1]; // transfer the last command byte *dmaAddrMode = wr2; // start DMA transfer endcmd(wr2 | NO_DMA | HDC | A0); // wait for DMA completion hdone(); // restore DMA device to normal }
int main() { int rc; int val; /* Non-blocking receiver case. */ int ch1 = chmake(sizeof(int)); errno_assert(ch1 >= 0); int hndl1 = go(sender1(ch1, 555)); errno_assert(hndl1 >= 0); struct chclause cls1[] = {{CHRECV, ch1, &val, sizeof(val)}}; rc = choose(cls1, 1, -1); choose_assert(0, 0); assert(val == 555); hclose(ch1); rc = hclose(hndl1); errno_assert(rc == 0); /* Blocking receiver case. */ int ch2 = chmake(sizeof(int)); errno_assert(ch2 >= 0); int hndl2 = go(sender2(ch2, 666)); errno_assert(hndl2 >= 0); struct chclause cls2[] = {{CHRECV, ch2, &val, sizeof(val)}}; rc = choose(cls2, 1, -1); choose_assert(0, 0); assert(val == 666); hclose(ch2); rc = hclose(hndl2); errno_assert(rc == 0); /* Non-blocking sender case. */ int ch3 = chmake(sizeof(int)); errno_assert(ch3 >= 0); int hndl3 = go(receiver1(ch3, 777)); errno_assert(hndl3 >= 0); val = 777; struct chclause cls3[] = {{CHSEND, ch3, &val, sizeof(val)}}; rc = choose(cls3, 1, -1); choose_assert(0, 0); hclose(ch3); rc = hclose(hndl3); errno_assert(rc == 0); /* Blocking sender case. */ int ch4 = chmake(sizeof(int)); errno_assert(ch4 >= 0); int hndl4 = go(receiver2(ch4, 888)); errno_assert(hndl4 >= 0); val = 888; struct chclause cls4[] = {{CHSEND, ch4, &val, sizeof(val)}}; rc = choose(cls4, 1, -1); choose_assert(0, 0); hclose(ch4); rc = hclose(hndl4); errno_assert(rc == 0); /* Check with two channels. */ int hndl5[2]; int ch5 = chmake(sizeof(int)); errno_assert(ch5 >= 0); int ch6 = chmake(sizeof(int)); errno_assert(ch6 >= 0); hndl5[0] = go(sender1(ch6, 555)); errno_assert(hndl5 >= 0); struct chclause cls5[] = { {CHRECV, ch5, &val, sizeof(val)}, {CHRECV, ch6, &val, sizeof(val)} }; rc = choose(cls5, 2, -1); choose_assert(1, 0); assert(val == 555); hndl5[1] = go(sender2(ch5, 666)); errno_assert(hndl5 >= 0); rc = choose(cls5, 2, -1); choose_assert(0, 0); assert(val == 666); hclose(ch5); hclose(ch6); rc = hclose(hndl5[0]); errno_assert(rc == 0); rc = hclose(hndl5[1]); errno_assert(rc == 0); /* Test whether selection of in channels is random. */ int ch7 = chmake(sizeof(int)); errno_assert(ch7 >= 0); int ch8 = chmake(sizeof(int)); errno_assert(ch8 >= 0); int hndl6[2]; hndl6[0] = go(feeder(ch7, 111)); errno_assert(hndl6[0] >= 0); hndl6[1] = go(feeder(ch8, 222)); errno_assert(hndl6[1] >= 0); int i; int first = 0; int second = 0; int third = 0; for(i = 0; i != 100; ++i) { struct chclause cls6[] = { {CHRECV, ch7, &val, sizeof(val)}, {CHRECV, ch8, &val, sizeof(val)} }; rc = choose(cls6, 2, -1); errno_assert(rc == 0 || rc == 1); if(rc == 0) { assert(val == 111); ++first; } if(rc == 1) { assert(val == 222); ++second; } int rc = yield(); errno_assert(rc == 0); } assert(first > 1 && second > 1); hclose(hndl6[0]); hclose(hndl6[1]); hclose(ch7); hclose(ch8); /* Test 'otherwise' clause. */ int ch9 = chmake(sizeof(int)); errno_assert(ch9 >= 0); struct chclause cls7[] = {{CHRECV, ch9, &val, sizeof(val)}}; rc = choose(cls7, 1, 0); choose_assert(-1, ETIMEDOUT); hclose(ch9); rc = choose(NULL, 0, 0); choose_assert(-1, ETIMEDOUT); /* Test two simultaneous senders vs. choose statement. */ int ch10 = chmake(sizeof(int)); errno_assert(ch10 >= 0); int hndl7[2]; hndl7[0] = go(sender1(ch10, 888)); errno_assert(hndl7[0] >= 0); hndl7[1] = go(sender1(ch10, 999)); errno_assert(hndl7[1] >= 0); val = 0; struct chclause cls8[] = {{CHRECV, ch10, &val, sizeof(val)}}; rc = choose(cls8, 1, -1); choose_assert(0, 0); assert(val == 888); val = 0; rc = choose(cls8, 1, -1); choose_assert(0, 0); assert(val == 999); hclose(ch10); rc = hclose(hndl7[0]); errno_assert(rc == 0); rc = hclose(hndl7[1]); errno_assert(rc == 0); /* Test two simultaneous receivers vs. choose statement. */ int ch11 = chmake(sizeof(int)); errno_assert(ch11 >= 0); int hndl8[2]; hndl8[0] = go(receiver1(ch11, 333)); errno_assert(hndl8[0] >= 0); hndl8[1] = go(receiver1(ch11, 444)); errno_assert(hndl8[1] >= 0); val = 333; struct chclause cls9[] = {{CHSEND, ch11, &val, sizeof(val)}}; rc = choose(cls9, 1, -1); choose_assert(0, 0); val = 444; rc = choose(cls9, 1, -1); choose_assert(0, 0); hclose(ch11); rc = hclose(hndl8[0]); errno_assert(rc == 0); rc = hclose(hndl8[1]); errno_assert(rc == 0); /* Choose vs. choose. */ int ch12 = chmake(sizeof(int)); errno_assert(ch12 >= 0); int hndl9 = go(choosesender(ch12, 111)); errno_assert(hndl9 >= 0); struct chclause cls10[] = {{CHRECV, ch12, &val, sizeof(val)}}; rc = choose(cls10, 1, -1); choose_assert(0, 0); assert(val == 111); hclose(ch12); rc = hclose(hndl9); errno_assert(rc == 0); /* Test transferring a large object. */ int ch17 = chmake(sizeof(struct large)); errno_assert(ch17 >= 0); int hndl10 = go(sender4(ch17)); errno_assert(hndl9 >= 0); struct large lrg; struct chclause cls14[] = {{CHRECV, ch17, &lrg, sizeof(lrg)}}; rc = choose(cls14, 1, -1); choose_assert(0, 0); hclose(ch17); /* Test that 'in' on done-with channel fires. */ int ch18 = chmake(sizeof(int)); errno_assert(ch18 >= 0); rc = hdone(ch18); errno_assert(rc == 0); struct chclause cls15[] = {{CHRECV, ch18, &val, sizeof(val)}}; rc = choose(cls15, 1, -1); choose_assert(0, EPIPE); hclose(ch18); /* Test expiration of 'deadline' clause. */ int ch21 = chmake(sizeof(int)); errno_assert(ch21 >= 0); int64_t start = now(); struct chclause cls17[] = {{CHRECV, ch21, &val, sizeof(val)}}; rc = choose(cls17, 1, start + 50); choose_assert(-1, ETIMEDOUT); int64_t diff = now() - start; time_assert(diff, 50); hclose(ch21); /* Test unexpired 'deadline' clause. */ int ch22 = chmake(sizeof(int)); errno_assert(ch22 >= 0); start = now(); int hndl11 = go(sender3(ch22, 4444, start + 50)); errno_assert(hndl11 >= 0); struct chclause cls18[] = {{CHRECV, ch22, &val, sizeof(val)}}; rc = choose(cls17, 1, start + 1000); choose_assert(0, 0); assert(val == 4444); diff = now() - start; time_assert(diff, 50); hclose(ch22); rc = hclose(hndl11); errno_assert(rc == 0); /* Test that first channel in the array is prioritized. */ int ch23 = chmake(sizeof(int)); errno_assert(ch23 >= 0); int ch24 = chmake(sizeof(int)); errno_assert(ch24 >= 0); int hndl12 = go(sender1(ch23, 0)); errno_assert(hndl12 >= 0); int hndl13 = go(sender1(ch24, 0)); errno_assert(hndl13 >= 0); struct chclause cls19[] = { {CHRECV, ch24, &val, sizeof(val)}, {CHRECV, ch23, &val, sizeof(val)} }; rc = choose(cls19, 2, -1); choose_assert(0, 0); rc = chrecv(ch23, &val, sizeof(val), -1); errno_assert(rc == 0); rc = hclose(hndl13); errno_assert(rc == 0); rc = hclose(hndl12); errno_assert(rc == 0); rc = hclose(ch24); errno_assert(rc == 0); rc = hclose(ch23); errno_assert(rc == 0); /* Try adding the same channel to choose twice. Doing so is pointless, but it shouldn't crash the application. */ int ch25 = chmake(sizeof(int)); errno_assert(ch25 >= 0); struct chclause cls20[] = { {CHRECV, ch25, &val, sizeof(val)}, {CHRECV, ch25, &val, sizeof(val)} }; rc = choose(cls20, 2, now() + 50); choose_assert(-1, ETIMEDOUT); rc = hclose(ch25); errno_assert(rc == 0); return 0; }
int headerbody(buffer *b,void (*dohf)(),void (*hdone)(),void (*dobl)()) //substdio *ss; //void (*dohf)(); //void (*hdone)(); //void (*dobl)(); { int match; int flaglineok; match = 1; flaglineok = 0; for (;;) { switch(getsa(b,&nextline,&match)) { case -1: return -1; case 0: if (flaglineok) dohf(&line); hdone(); /* no message body; could insert blank line here */ return 0; } if (flaglineok) { if ((nextline.s[0] == ' ') || (nextline.s[0] == '\t')) { if (!stralloc_cat(&line,&nextline)) return -1; continue; } dohf(&line); } if (nextline.len == 1) { hdone(); dobl(&nextline); break; } if (stralloc_starts(&nextline,"From ")) { if (!stralloc_copys(&line,"MBOX-Line: ")) return -1; if (!stralloc_cat(&line,&nextline)) return -1; } else if (hfield_valid(nextline.s,nextline.len)) { if (!stralloc_copy(&line,&nextline)) return -1; } else { hdone(); if (!stralloc_copys(&line,"\n")) return -1; dobl(&line); dobl(&nextline); break; } flaglineok = 1; } for (;;) switch(getsa(b,&nextline,&match)) { case -1: return -1; case 0: return 0; case 1: dobl(&nextline); } }