+#include <stdio.h>
+#include <dos.h>
+#include <conio.h>
+#include <alloc.h>
+#include <mem.h>
+
+#include "i89.h"
+
+extern i89_task_block tb_memcpy_mov, tb_memcpy_mov16, tb_memcpy_xfer, tb_memcpy_xfer16;
+
+struct memcpy_parameter_block {
+ i89_channel_parameter_block_t cpb;
+ unsigned int far * src;
+ unsigned int far * dest;
+ unsigned int count;
+};
+
+struct i89_channel far * ccb;
+struct memcpy_parameter_block memcpy_pb = { 0 };
+
+unsigned long int st_to_ticks(const struct time *t) {
+ return t->ti_hour * 360000 + t->ti_min * 6000 + t->ti_sec * 100 + t->ti_hund;
+}
+
+void memcpy_naive(void * dest, const void * src, size_t n) {
+ char * d = dest;
+ char * s = src;
+ while (n > 0) {
+ *d = *s;
+ d++;
+ s++;
+ n--;
+ }
+}
+
+void memcpy_naive16(void * dest, const void * src, size_t n) {
+ int * d = dest;
+ int * s = src;
+ n >>= 1;
+ while (n > 0) {
+ *d = *s;
+ d++;
+ s++;
+ n--;
+ }
+}
+
+void memcpy_i89(void * dest, const void * src, size_t n) {
+ memcpy_pb.cpb.tbp = &tb_memcpy_mov;
+ ccb[1].ccw = 0x03;
+ ccb[1].ppb = &memcpy_pb.cpb;
+ memcpy_pb.src = src;
+ memcpy_pb.dest = dest;
+ memcpy_pb.count = n;
+ outportb(0x72, 0);
+}
+
+void memcpy_i89_16(void * dest, const void * src, size_t n) {
+ memcpy_pb.cpb.tbp = &tb_memcpy_mov16;
+ ccb[1].ccw = 0x03;
+ ccb[1].ppb = &memcpy_pb.cpb;
+ memcpy_pb.src = src;
+ memcpy_pb.dest = dest;
+ memcpy_pb.count = n >> 1;
+ outportb(0x72, 0);
+}
+
+void memcpy_i89_xfer(void * dest, const void * src, size_t n) {
+ memcpy_pb.cpb.tbp = &tb_memcpy_xfer;
+ ccb[1].ccw = 0x03;
+ ccb[1].ppb = &memcpy_pb.cpb;
+ memcpy_pb.src = src;
+ memcpy_pb.dest = dest;
+ memcpy_pb.count = n;
+ outportb(0x72, 0);
+}
+
+void memcpy_i89_xfer_16(void * dest, const void * src, size_t n) {
+ memcpy_pb.cpb.tbp = &tb_memcpy_xfer16;
+ ccb[1].ccw = 0x03;
+ ccb[1].ppb = &memcpy_pb.cpb;
+ memcpy_pb.src = src;
+ memcpy_pb.dest = dest;
+ memcpy_pb.count = n;
+ outportb(0x72, 0);
+}
+
+void test_done(void * b1, void * b2, size_t len, const struct time * t0,
+ const struct time * t1, const char *test_name) {
+ long int t_acc = st_to_ticks(t1) - st_to_ticks(t0);
+ printf("%-20s%ld.%ld ticks\n", test_name, t_acc / 10, t_acc % 10);
+ if (memcmp(b1, b2, len) != 0) {
+ printf("data compare error\n");
+ exit(1);
+ }
+ memset(b2, 0, len);
+}
+
+void main() {
+ long int i;
+ size_t copy_len = 32768;
+ struct time t0, t1;
+ char far * buffer1;
+ char far * buffer2;
+
+ buffer1 = farmalloc(copy_len);
+ printf("buffer1: %Fp\n", buffer1);
+ if (buffer1 == NULL) {
+ printf("Could not allocate buffer1\n");
+ return;
+ }
+ buffer2 = farmalloc(copy_len);
+ printf("buffer2: %Fp\n", buffer2);
+ if (buffer2 == NULL) {
+ printf("Could not allocate buffer2\n");
+ return;
+ }
+ ccb = MK_FP(0x0000, 0x0500);
+
+ for (i = 0; i < copy_len; i++) {
+ buffer1[i] = (unsigned char)i;
+ }
+
+ gettime(&t0);
+ memcpy(buffer2, buffer1, copy_len);
+ memcpy(buffer2, buffer1, copy_len);
+ memcpy(buffer2, buffer1, copy_len);
+ memcpy(buffer2, buffer1, copy_len);
+ memcpy(buffer2, buffer1, copy_len);
+ memcpy(buffer2, buffer1, copy_len);
+ memcpy(buffer2, buffer1, copy_len);
+ memcpy(buffer2, buffer1, copy_len);
+ memcpy(buffer2, buffer1, copy_len);
+ memcpy(buffer2, buffer1, copy_len);
+ gettime(&t1);
+ test_done(buffer1, buffer2, copy_len, &t0, &t1, "memcpy");
+
+ gettime(&t0);
+ memcpy_naive(buffer2, buffer1, copy_len);
+ memcpy_naive(buffer2, buffer1, copy_len);
+ memcpy_naive(buffer2, buffer1, copy_len);
+ memcpy_naive(buffer2, buffer1, copy_len);
+ memcpy_naive(buffer2, buffer1, copy_len);
+ memcpy_naive(buffer2, buffer1, copy_len);
+ memcpy_naive(buffer2, buffer1, copy_len);
+ memcpy_naive(buffer2, buffer1, copy_len);
+ memcpy_naive(buffer2, buffer1, copy_len);
+ memcpy_naive(buffer2, buffer1, copy_len);
+ gettime(&t1);
+ test_done(buffer1, buffer2, copy_len, &t0, &t1, "memcpy_naive");
+
+ gettime(&t0);
+ memcpy_naive16(buffer2, buffer1, copy_len);
+ memcpy_naive16(buffer2, buffer1, copy_len);
+ memcpy_naive16(buffer2, buffer1, copy_len);
+ memcpy_naive16(buffer2, buffer1, copy_len);
+ memcpy_naive16(buffer2, buffer1, copy_len);
+ memcpy_naive16(buffer2, buffer1, copy_len);
+ memcpy_naive16(buffer2, buffer1, copy_len);
+ memcpy_naive16(buffer2, buffer1, copy_len);
+ memcpy_naive16(buffer2, buffer1, copy_len);
+ memcpy_naive16(buffer2, buffer1, copy_len);
+ gettime(&t1);
+ test_done(buffer1, buffer2, copy_len, &t0, &t1, "memcpy_naive16");
+
+ gettime(&t0);
+ memcpy_i89(buffer2, buffer1, copy_len);
+ memcpy_i89(buffer2, buffer1, copy_len);
+ memcpy_i89(buffer2, buffer1, copy_len);
+ memcpy_i89(buffer2, buffer1, copy_len);
+ memcpy_i89(buffer2, buffer1, copy_len);
+ memcpy_i89(buffer2, buffer1, copy_len);
+ memcpy_i89(buffer2, buffer1, copy_len);
+ memcpy_i89(buffer2, buffer1, copy_len);
+ memcpy_i89(buffer2, buffer1, copy_len);
+ memcpy_i89(buffer2, buffer1, copy_len);
+ gettime(&t1);
+ test_done(buffer1, buffer2, copy_len, &t0, &t1, "memcpy_i89_mov");
+
+ gettime(&t0);
+ memcpy_i89_16(buffer2, buffer1, copy_len);
+ memcpy_i89_16(buffer2, buffer1, copy_len);
+ memcpy_i89_16(buffer2, buffer1, copy_len);
+ memcpy_i89_16(buffer2, buffer1, copy_len);
+ memcpy_i89_16(buffer2, buffer1, copy_len);
+ memcpy_i89_16(buffer2, buffer1, copy_len);
+ memcpy_i89_16(buffer2, buffer1, copy_len);
+ memcpy_i89_16(buffer2, buffer1, copy_len);
+ memcpy_i89_16(buffer2, buffer1, copy_len);
+ memcpy_i89_16(buffer2, buffer1, copy_len);
+ gettime(&t1);
+ test_done(buffer1, buffer2, copy_len, &t0, &t1, "memcpy_i89_mov16");
+
+ gettime(&t0);
+ memcpy_i89_xfer(buffer2, buffer1, copy_len);
+ memcpy_i89_xfer(buffer2, buffer1, copy_len);
+ memcpy_i89_xfer(buffer2, buffer1, copy_len);
+ memcpy_i89_xfer(buffer2, buffer1, copy_len);
+ memcpy_i89_xfer(buffer2, buffer1, copy_len);
+ memcpy_i89_xfer(buffer2, buffer1, copy_len);
+ memcpy_i89_xfer(buffer2, buffer1, copy_len);
+ memcpy_i89_xfer(buffer2, buffer1, copy_len);
+ memcpy_i89_xfer(buffer2, buffer1, copy_len);
+ memcpy_i89_xfer(buffer2, buffer1, copy_len);
+ gettime(&t1);
+ test_done(buffer1, buffer2, copy_len, &t0, &t1, "memcpy_i89_xfer");
+
+ gettime(&t0);
+ memcpy_i89_xfer_16(buffer2, buffer1, copy_len);
+ memcpy_i89_xfer_16(buffer2, buffer1, copy_len);
+ memcpy_i89_xfer_16(buffer2, buffer1, copy_len);
+ memcpy_i89_xfer_16(buffer2, buffer1, copy_len);
+ memcpy_i89_xfer_16(buffer2, buffer1, copy_len);
+ memcpy_i89_xfer_16(buffer2, buffer1, copy_len);
+ memcpy_i89_xfer_16(buffer2, buffer1, copy_len);
+ memcpy_i89_xfer_16(buffer2, buffer1, copy_len);
+ memcpy_i89_xfer_16(buffer2, buffer1, copy_len);
+ memcpy_i89_xfer_16(buffer2, buffer1, copy_len);
+ gettime(&t1);
+ test_done(buffer1, buffer2, copy_len, &t0, &t1, "memcpy_i89_xfer16");
+
+ printf("Looping tests...\n");
+
+ while (1) {
+ outportb(0x48, 0x01);
+ memcpy(buffer2, buffer1, copy_len);
+ outportb(0x48, 0);
+
+ outportb(0x48, 0x02);
+ memcpy_naive(buffer2, buffer1, copy_len);
+ outportb(0x48, 0);
+
+ outportb(0x48, 0x04);
+ memcpy_naive16(buffer2, buffer1, copy_len);
+ outportb(0x48, 0);
+
+ outportb(0x48, 0x10);
+ memcpy_i89(buffer2, buffer1, copy_len);
+ outportb(0x48, 0);
+
+ outportb(0x48, 0x20);
+ memcpy_i89_16(buffer2, buffer1, copy_len);
+ outportb(0x48, 0);
+
+ outportb(0x48, 0x40);
+ memcpy_i89_xfer(buffer2, buffer1, copy_len);
+ outportb(0x48, 0);
+
+ outportb(0x48, 0x80);
+ memcpy_i89_xfer_16(buffer2, buffer1, copy_len);
+ outportb(0x48, 0);
+
+ kbhit();
+ }
+}