Subject: Hydra driver problem
To: None <amiga@NetBSD.ORG>
From: David Jones <>
List: amiga
Date: 03/24/1995 21:55:40
A while back I reported a problem with my Hydra Ethernet.  Here are
the complete details:

Hardware: A3000/16, 8M RAM, Hydra Ethernet, PCB rev. 1.1.

The symptom: files are corrupted when copying data from a remote NFS
partition to a local drive.

The cause: There appears to be a contention problem that occurs when the
ed driver reads from the Hydra packet buffer RAM at the same time a packet
is being recieved from the wire.  The word read by the Amiga is corrupted.
Since the packet image in the packet buffer is not corrupted, no CRC
error is flagged - the card received the packet correctly.

The problem can be demonstrated with the following:

begin 644 blast.tar.gz
M'XL( '71<R\  .T8:T_C1I"O^%<,]+AS@A.<EP,)(*%R/:%RM.)Z'ZH[%#G.X
M)EG%L:/=38 B_GMG=M<)":]>)0Y=ZY%@U[/SWGDL=.-0JG*T]I(  $$0 *T X
M_LH*4&W6?8!&LU8/FD$MJ %4_$:]L0;^BUIE82I5* #6PC$?A$_0/7?^@\)/X
M./[L\(3P#KM23"3 $P7I!$]Z[0P5#?&^BH@,Q:#M.'&:#* [[7^I59O![D7;X
MH0 ;!U"JF'!<<A4-P8WT5Q1*!N_$NY:S3N+0$104JI2[YG(H.G30%2Q$XRV]X
MG-.CST\S]%@_G,;*TO<G AWONYB!3 BT[R2.V0#=H_Q(DQ:4MJ*OR29&.9/#X
MKKAR*_1U:^]%+[P/[H:^!)-9%]J;>^+/*%@45L ,H?M@4J)\$C<7;*32[R$SX
M.B=G[__(LFI$V:\+W?W=G'CPZ;>??^T<?S@_^NB!?\=[)-Y'! 5@@FZGPMTTX
MK \%=LX5I4G"(H7<'F@_EUS"'%V5:1D>%4KE0X5-25N$:B,HP XT;&&(>S5BX
MTE_-RFK6D2PRY_9[:A!5'Z%-+2,F2WT/SCZ?GB[_?JMF9)" [0-M >ZM @&'X
MF_^UH+XZ__%)D,__[P&O,?_Y( GC)Z?_4T.=II_B*)8&O)Z(P]%#\]V#-)W(X
MY<E'(OT+4]ITNBCT^3.@\N^> =2E[%-@P[P%YK5L^_SF^ZL)=@:4L.7O7GDPX
MQ4D'!F-.@=&D)GA&AHZ-O@_WT\F'H]-S;-=T;KME&(=BK'OG*[]HB !;.PI.X
MZ#CZRR*11+/:#^+36YS@FKIEN3*Z[(L(K;S7#D ..>200PXYY)!##CGDD$,.X
5.>200PXYY)##?Q3^!KN-'^  *   X

Usage: blast -r <rate> -s <size> <host>

will send <size>-byte packets to the given <host>, at <rate> packets
per second.  Each packet contains pseudo-random data.

The listen command will listen for these packets.  The first word in each
packet is used to seed the same pseudo-random number generator so that
the remaining words in the packet can be verified.

Listen will print the current packets received per second, as well as
as cumulative receive errors.

When run at low speeds (blast -r 50 -s 512), there is no problem.

When run using long packets (such as NFS) (blast -r 40 -s 4096), you will
receive errors.  In each case, the Amiga will read more "1" bits from
the bus than are actually in the word.  I have tried my Hydra as well
as a friend's (PCB rev. 1.0) and both have the problem.

Note: blast/listen can also be used to perform rudimentary throughput

At low rates, the Amiga can fetch the packet from the card before the next
packet arrives.  Since the Amiga's reads and the NIC's DMA writes do
not overlap, there is no problem.

As the packet rate increases, the likelihood that write DMA and Amiga reads
become concurrent increases.

A crude fix is to patch the ed driver to read each word from the packet
buffer twice, and to re-read if the two reads don't match.  I have
implemented this patch (given below) and the problem does indeed go away,
but at a noticeable loss in performance.  It is unclear how well using
assembler to do the reads would improve the performance.

*** if_ed.c.old	Sat Mar 25 02:32:51 1995
--- if_ed.c	Sat Mar 25 02:28:09 1995
*** 468,473 ****
--- 468,489 ----
+ void inline
+ word_copy_in(u_short *a, u_short *b, int len)
+ {
+ register u_short tmp1;
+ register u_short *volatile p;
+ 	len /= 2;
+ 	p = a;
+ 	while(len--) {
+ 		while (tmp1 = *p, tmp1 != *p);
+ 		*b++ = tmp1;
+ 		p++;
+ 	}
+ }
   * Copy packet from mbuf to the board memory
*** 551,557 ****
  	eh = mtod(head, struct ether_header *);
! 	word_copy((u_short *)nic_ram_ptr, mtod(head, u_short *),
  	    sizeof(struct ether_header));
  	nic_ram_ptr += sizeof(struct ether_header)/2;
--- 567,573 ----
  	eh = mtod(head, struct ether_header *);
! 	word_copy_in((u_short *)nic_ram_ptr, mtod(head, u_short *),
  	    sizeof(struct ether_header));
  	nic_ram_ptr += sizeof(struct ether_header)/2;
*** 597,603 ****
  		printf("copying %d bytes (%d left)\n", len1, len - len1);
! 		word_copy((u_short *)nic_ram_ptr,
  		    (u_short *)(mtod(m, caddr_t) + m->m_len), len1);
  		m->m_len += len1;
--- 613,619 ----
  		printf("copying %d bytes (%d left)\n", len1, len - len1);
! 		word_copy_in((u_short *)nic_ram_ptr,
  		    (u_short *)(mtod(m, caddr_t) + m->m_len), len1);
  		m->m_len += len1;

David Jones, M.A.Sc student, Electronics Group (VLSI), University of Toronto
           email:, finger for PGP public key
         For a good time, telnet and log in as `guest'.
          Click me!