;;; -*- Mode:LISP; Package:SYSTEM-INTERNALS; Cold-Load:T; Base:8; Readtable:ZL -*- ;;; This file contains the definitions for the mini ethernet system ;;; that are specific to the 3com ethernet board hosted on the multibus. ;;; these use plus because + may be funbound in the cold load!!. Problem is it's ;;; set up by the crash list, and the order of evaluation is not assured. (defconst 3com-mebase #x30000 "address of 3com ethernet controller") (defconst 3com-mecsr 3com-mebase "control/status register for 3com interface") (defconst 3com-meback (plus 2 3com-mecsr) "jam backoff counter for 3com interface") (defconst 3com-address-rom (plus 3com-mebase #x400) "3com ethernet address ROM") (defconst 3com-address-ram (plus 3com-mebase #x600) "3com ethernet address RAM") (defconst 3com-transmit-buffer (plus 3com-mebase #x800) "3com transmit buffer") (defconst 3com-buffer-a (plus 3com-mebase #x1000) "3com receive buffer A") (defconst 3com-buffer-b (plus 3com-mebase #x1800) "3com receive buffer B") (defconst 3com-meahdr 3com-buffer-a "header word of 3com buffer A") (defconst 3com-mebhdr 3com-buffer-b "header word of 3com buffer B") ;;; Note: this code operates with the byte-ordering switch ON on the 3-COM board. ;;; This sets "low byte first" mode, like the 8086 and unlike the 68000. ;;; Setting it this way means data CAN be read from packet buffers with 32 bit transfers. ;;; This is NOT the way the board was shipped by 3-COM. ;;; This means the pictures in the manual are byte reversed! ;;; In particular, the byte offset words in the buffer headers are byte reversed!!! ;;; The #. s below avoid bombout because byte is a defsubst and not in the cold load. (defconst bbsw #.(byte 1 7)) ;set if buffer B belongs to ether. (defconst absw #.(byte 1 6)) ;set if buffer A belongs to ether. (defconst tbsw #.(byte 1 5)) ;set if transmit buffer belongs to ether. (defconst jam #.(byte 1 4)) ;writing 1 clears jam. (defconst amsw #.(byte 1 3)) ;address in RAM is valid (defconst rbba #.(byte 1 2)) ;A/B receive buffer ordering. ; bit 1 not used (defconst reset #.(byte 1 0)) ;reset the controller. (defconst binten #.(byte 1 15.)) ;enable interrupts on buffer B. (defconst ainten #.(byte 1 14.)) ;enable interrupts on buffer A. (defconst tinten #.(byte 1 13.)) ;enable interrupts on transmit buffer. (defconst jinten #.(byte 1 12.)) ;enable interrupts on jam. (defconst pa #.(byte 4 8.)) ;which frame addresses to accept (defconst 3com-csr-background-bits (logior (dpb 7 pa 0) (dpb 1 amsw 0))) (defun arm-ethernet-for-receive () (arm-3com-receive-buffer ABSW) (arm-3com-receive-buffer BBSW)) (defun write-3com-csr (new-csr) ; (%multibus-write-8 3com-mecsr new-csr) (%multibus-write-16 3com-mecsr new-csr)) (defun read-3com-csr () (%multibus-read-16 3com-mecsr)) (defun 3com-ethernet-reset () (write-3com-csr 1) ;reset (setq *mini-my-ethernet-address* 0) (dotimes (i 6) (let ((next-byte (%multibus-read-8 (+ 3com-address-rom i)))) (%multibus-write-8 (+ 3com-address-ram i) next-byte) (setq *mini-my-ethernet-address* (dpb next-byte 0010 (ash *mini-my-ethernet-address* 8.))))) ;set up normal csr - address RAM valid, receive MINE + Broadcast packets (write-3com-csr 3com-csr-background-bits)) (defun wait-for-3com-buffer () (do () ((3com-mini-pkt-available)))) ;;; multibus 3com receive buffer contains ;;; buffer-base: meahdr (note byte reversed!!) ;;; +2: destination ;;; +8: source ;;; +14: type ;;; +16: data (defun write-lambda-3com-frame-header (buffer-base offset source destination type) (setq offset (- offset 14.)) (%multibus-write-8 (1+ buffer-base) (ldb 0010 offset)) ;offset reg is reversed!!! (%multibus-write-8 buffer-base (ldb 1010 offset)) (%multibus-write-8 (+ buffer-base offset ) (ldb 5010 destination)) (%multibus-write-8 (+ buffer-base offset 1) (ldb 4010 destination)) (%multibus-write-8 (+ buffer-base offset 2) (ldb 3010 destination)) (%multibus-write-8 (+ buffer-base offset 3) (ldb 2010 destination)) (%multibus-write-8 (+ buffer-base offset 4) (ldb 1010 destination)) (%multibus-write-8 (+ buffer-base offset 5) (ldb 0010 destination)) (%multibus-write-8 (+ buffer-base offset 6) (ldb 5010 source)) (%multibus-write-8 (+ buffer-base offset 7) (ldb 4010 source)) (%multibus-write-8 (+ buffer-base offset 10) (ldb 3010 source)) (%multibus-write-8 (+ buffer-base offset 11) (ldb 2010 source)) (%multibus-write-8 (+ buffer-base offset 12) (ldb 1010 source)) (%multibus-write-8 (+ buffer-base offset 13) (ldb 0010 source)) (%multibus-write-8 (+ buffer-base offset 14) (ldb 0010 type)) (%multibus-write-8 (+ buffer-base offset 15) (ldb 1010 type))) (defun 3com-transmit-ethernet-16b-array (from-ether-host to-ether-host array nwords e-type) (let* ((physical-size (max (* nwords 2) 60.)) (offset (- 2048. physical-size)) (beginning-address (+ 3com-transmit-buffer offset))) (prog (csr start-time) (setq start-time (%fixnum-microsecond-time)) l (setq csr (read-3com-csr)) (cond ((not (zerop (ldb jam csr))) ;;(write-3com-csr (dpb 1 jam 3com-csr-background-bits)) ;reset jam (write-3com-csr (dpb 1 reset 0)) (write-3com-csr 3com-csr-background-bits) (go l)) ((not (zerop (ldb tbsw csr))) (cond ((> (time-difference (%fixnum-microsecond-time) start-time) 100000.) (return nil)) ;give up. (t (go l))))) (do ((adr beginning-address (+ adr 2)) (from-index 0 (1+ from-index)) (n (* nwords 2) (1- n))) ((zerop n)) (let ((data (aref array from-index))) (%multibus-write-8 adr (ldb 0010 data)) (%multibus-write-8 (1+ adr) (ldb 1010 data)))) (write-lambda-3com-frame-header 3com-transmit-buffer offset from-ether-host to-ether-host e-type) (write-3com-csr (dpb 1 tbsw 3com-csr-background-bits)) (do () ((or (zerop (ldb tbsw (read-3com-csr))) (not (zerop (ldb jam (read-3com-csr))))))) (cond ((not (zerop (ldb jam (read-3com-csr)))) (write-3com-csr (dpb 1 reset 0)) (write-3com-csr 3com-csr-background-bits)))))) (defun 3com-mini-pkt-available () (or (zerop (ldb absw (read-3com-csr))) (zerop (ldb bbsw (read-3com-csr))))) (defun 3com-receive-ethernet-16b-array (array) (wait-for-3com-buffer) (do ((got-one nil)) ((not (null got-one)) array) (setq got-one (receive-ethernet-with-buffer-ready array)))) (defun 3com-receive-ethernet-with-buffer-ready (array &aux got-one) (cond ((zerop (ldb absw (read-3com-csr))) (setq got-one (receive-3com-ethernet-pkt-into-array 3com-buffer-a array)) (arm-3com-receive-buffer ABSW)) ((zerop (ldb bbsw (read-3com-csr))) (setq got-one (receive-3com-ethernet-pkt-into-array 3com-buffer-b array)) (arm-3com-receive-buffer BBSW))) got-one) (DEFUN ARM-3COM-RECEIVE-BUFFER (BYTE-PTR) (PROG () L (COND ((NOT (ZEROP (LDB TBSW (READ-3COM-CSR)))) (cond ((not (zerop (ldb jam (read-3com-csr)))) ;; (write-3com-csr (dpb 1 jam 3com-csr-background-bits)) (write-3com-csr (dpb 1 reset 0)) (write-3com-csr 3com-csr-background-bits))) (GO L))) (WITHOUT-INTERRUPTS (COND ((NOT (ZEROP (LDB TBSW (READ-3COM-CSR)))) (GO L))) (write-3com-csr (dpb 1 BYTE-PTR 3com-csr-background-bits))))) (defun 3com-get-ethernet-packet-type (buffer-base) (dpb (%multibus-read-8 (+ buffer-base 17)) (byte 8. 8.) (%multibus-read-8 (+ buffer-base 16)))) ;returns nil if the packet is not an interesting chaos packet (defun receive-3com-ethernet-pkt-into-array (buffer-base array) (cond ((not (zerop (logand 250 (%multibus-read-8 buffer-base)))) ;fcs error, etc nil) (t (let ((type (3com-get-ethernet-packet-type buffer-base))) (select type (#x408 ;chaos-ethernet-type (do ((adr (+ buffer-base 16.) (+ adr 2)) (wd-count 0 (1+ wd-count))) ((>= wd-count 374)) ;chaos:max-words-per-pkt (aset (dpb (%multibus-read-8 (+ adr 1)) (byte 8. 8.) (%multibus-read-8 adr)) array wd-count)) ;code to reread and check ; (do ((adr (+ buffer-base 16.) (+ adr 2)) ; (wd-count 0 (1+ wd-count))) ; ((>= wd-count 374)) ;chaos:max-words-per-pkt ; (if (or (not (= (%multibus-read-8 adr) (ldb (byte 8 0) (aref array wd-count)))) ; (not (= (%multibus-read-8 (+ adr 1)) (ldb (byte 8 8) (aref array wd-count))))) ; (ferror nil "read differently second time"))) t) (#x608 ;address-resolution-type ;;copy received data into pkt (do ((adr (+ buffer-base 16.) (+ adr 2)) (wd-count 0 (1+ wd-count))) ((>= wd-count 374)) (aset (dpb (%multibus-read-8 (+ adr 1)) (byte 8. 8.) (%multibus-read-8 adr)) array wd-count)) (receive-addr-pkt array) ;record address; maybe send reply nil))))))