	public	set_multicast_list
set_multicast_list:
;enter with ds:si ->list of multicast addresses, ax = number of addresses,
;  cx = number of bytes.
;return nc if we set all of them, or cy,dh=error if we didn't.
	assume ds:code

	mov	cx,ax			;keep a count of addresses in cx.
	mov	di,offset mcast_list_bits
	xor	ax,ax
	mov	[di+0],ax
	mov	[di+2],ax
	mov	[di+4],ax
	mov	[di+6],ax
	jcxz	set_mcl_2
set_mcl_1:
	call	add_mc_bits
	loop	set_mcl_1
set_mcl_2:
	call    set_hw_multi	; Set the multicast mask bits in chip
	clc
	ret

add_mc_bits:
;entry:	ds:si -> multicast address, di-> sixty-four bit multicast filter.
;preserve cx, di, increment si by EADDR_LEN
	push	cx
	mov	cx,EADDR_LEN
	mov	dx,0ffffh			; this is msw.
	mov	bx,0ffffh			; set 32 bit number
add_mcb_1:
	lodsb
	call	upd_crc			; update crc
	loop	add_mcb_1		; and loop.

  ifdef MULTICRC_REVERSE
	mov	cl,8
add_mcb_2:
	shl	dh,1
	rcr	dl,1
	loop	add_mcb_2
	mov	dh,dl
  endif

	mov	al,dh			; get ms 8 bits,
	rol	al,1
	rol	al,1
	rol	al,1			; put 3 bits at bottom
	and	al,7
	mov	bl,al			; save in bl
	xor	bh,bh			; make bx into an index to the byte.

	mov	al,dh			; get ms 8 bits,
	ror	al,1
	ror	al,1			; but at bottom
	and	al,7
	mov	cl,al			; save in cl
	mov	al,1
	shl	al,cl			; set the correct bit,

	or	[bx+di],al
	pop	cx
	ret

;
;	dx is high,
;	bx is low.
;	al is data

upd_crc:
	push	cx
	mov	cx,8		; do 8 bits
	mov	ah,0
upd_crc1:
	shl	bx,1		; shift bx
	rcl	dx,1		; through dx
	rcl	ah,1		; carry is at bottom of ah
	xor	ah,al		; xor with lsb of data
	rcr	ah,1		; and put in carry bit
	jnc	upd_crc2
;
;	autodin is x^32+x^26+x^23x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1
;
	xor	dx,0000010011000001b
	xor	bx,0001110110110110b + 1	;plus one for end-around carry.
upd_crc2:
	shr	al,1		; shift the data
	loop	upd_crc1
	pop	cx
	ret

