home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / NCSATELN / TEL23SRC.ZIP / NET / ENET / NET9210.ASM < prev    next >
Encoding:
Assembly Source File  |  1991-05-15  |  23.6 KB  |  946 lines

  1. ;  MICOM NI 9210 driver code
  2. ;  Tim Krauskopf
  3. ;****************************************************************************
  4. ;*                                                                          *
  5. ;*                                                                          *
  6. ;*      part of NCSA Telnet                                                 *
  7. ;*      by Tim Krauskopf, VT100 by Gaige Paulsen, Tek by Aaron Contorer     *
  8. ;*                                                                          *
  9. ;*      National Center for Supercomputing Applications                     *
  10. ;*      152 Computing Applications Building                                 *
  11. ;*      605 E. Springfield Ave.                                             *
  12. ;*      Champaign, IL  61820                                                *
  13. ;*                                                                          *
  14. ;****************************************************************************
  15. ;
  16.  
  17.     TITLE    NETSUPPORT -- LOW LEVEL DRIVERS FOR ETHERNET
  18. ;
  19. ;  Assembler support for Ethernet I/O on the PC
  20. ;
  21. ;  Tim Krauskopf
  22. ;  9/1/87  Ungermann-Bass driver started, PC bus
  23. ;  9/14/87 MICOM NI5210 driver started, PC bus
  24. ;  4/88    Modified for combined drivers, version 2.2
  25. ;  9/88    NI9210 mods, just some I/O addr changes
  26. ;
  27. ;
  28. ;Microsoft EQU 1
  29. ;Lattice EQU 1
  30. ifndef Microsoft
  31.     ifndef Lattice
  32.         if2
  33.             %out
  34.             %out ERROR: You have to specify "/DMicrosoft" OR "/DLattice" on the
  35.             %out        MASM command line to determine the type of assembly.
  36.             %out
  37.         endif
  38.         end
  39.     endif
  40. endif
  41.  
  42.     NAME    MNET
  43. ifdef Microsoft
  44. X    EQU    6
  45.     DOSSEG
  46.     .MODEL    LARGE
  47. else
  48.     INCLUDE    DOS.MAC
  49.     SETX
  50. endif
  51. ;
  52. ;  Equates for controlling the MICOM board
  53. ;
  54. ;  I/O addresses, writing anything in AL trips these gates
  55. ;
  56. ;  First six addresses are the EPROM board Ether address (read)
  57. ;
  58. IORESET    EQU    0        ; reset the board
  59. IOCA    EQU    2        ; execute command which is in SCB
  60. IODIS    EQU    4        ; disable network connect
  61. IOENA    EQU    6        ; enable network
  62. ;
  63. ;  Structure elements specific to the Intel 82586 chip
  64. ;
  65. BDBASE    EQU    1874        ; base address for 30 buffer descriptors
  66. BUFBASE    EQU    2174        ; base address for 30 200 byte buffers
  67. BDSTAT    EQU    0        ; status word in BD
  68. BDLINK    EQU    2        ; 16pointer to next BD
  69. BDPTR    EQU    4        ; 24pointer to actual buffer
  70. BDSIZE    EQU    8        ; size of the buffer
  71. ;
  72. SCB    EQU    10        ; system control block base
  73. SSTAT    EQU    0        ; status word for SCB
  74. SCOM    EQU    2        ; command word in SCB
  75. SCBL    EQU    4        ; 16pointer to command block list
  76. SRFA    EQU    6        ; 16pointer to receive frame list
  77. SERRS    EQU    8        ; 4 words of error counts
  78. ;
  79. FDBASE    EQU    1214        ; base addr for 30 frame descriptors
  80. FDSTAT    EQU    0        ; status word for frame
  81. FDEOL    EQU    2        ; end of FD list flag
  82. FDLINK    EQU    4        ; 16pointer to next FD
  83. FDPTR    EQU    6        ; 16pointer to list of BD's
  84. ;
  85. TSTAT    EQU    0        ; status word for xmit
  86. TCOM    EQU    2        ; command to transmit
  87. TLINK    EQU    4        ; 16pointer to next command (always ffff)
  88. TPTR    EQU    6        ; 16pointer to xmit TBD
  89. TTRIES    EQU    8        ; number of transmit retries
  90. ;
  91. SCPTR    EQU    01ff6h        ; hardwired address for SCP
  92. ISCPTR    EQU    01feeh        ; my address for ISCP, points to SCB
  93. CCBPTR    EQU    26        ; offset of configure command block
  94. TCBPTR    EQU    44        ; xmit CB offset
  95. TBDPTR    EQU    60        ; xmit BD offset
  96. TBUFPTR    EQU    68        ; xmit buffer offset
  97. ;
  98. ;  Data segment
  99. ;
  100. ifdef Microsoft
  101.     .data
  102. ;DGROUP    group    _DATA
  103. ;_DATA    segment    public 'DATA'
  104. ;    assume    DS:DGROUP
  105. else
  106.     DSEG
  107. endif
  108. ;
  109. ;  The pointers below are actually DWORDs but we access them two
  110. ;  bytes at a time.
  111. ;
  112. ; STAT change to RSTAT because of name clash with MSC library routine
  113. ifdef Microsoft
  114.     RSTAT    EQU    <_RSTAT>
  115.     BUFPT    EQU    <_BUFPT>
  116.     BUFORG    EQU    <_BUFORG>
  117.     BUFEND    EQU    <_BUFEND>
  118.     BUFREAD    EQU    <_BUFREAD>
  119.     BUFBIG    EQU    <_BUFBIG>
  120.     BUFLIM    EQU    <_BUFLIM>
  121. ifdef QAK
  122.     EXTRN    _RSTAT:BYTE    ; last status from read
  123.     EXTRN    _BUFPT:WORD    ; current buffer pointer
  124.     EXTRN    _BUFORG:WORD    ; pointer to beginning of buffer
  125.     EXTRN    _BUFEND:WORD    ; pointer to end of buffer
  126.     EXTRN    _BUFREAD:WORD    ; pointer to where program is reading
  127.     EXTRN    _BUFBIG:WORD    ; integer, how many bytes we have
  128.     EXTRN    _BUFLIM:WORD    ; integer, max bytes we can have
  129. endif
  130. endif
  131.     EXTRN    RSTAT:BYTE    ; last status from read
  132.     EXTRN    BUFPT:WORD    ; current buffer pointer
  133.     EXTRN    BUFORG:WORD    ; pointer to beginning of buffer
  134.     EXTRN    BUFEND:WORD    ; pointer to end of buffer
  135.     EXTRN    BUFREAD:WORD    ; pointer to where program is reading
  136.     EXTRN    BUFBIG:WORD    ; integer, how many bytes we have
  137.     EXTRN    BUFLIM:WORD    ; integer, max bytes we can have
  138.  
  139. ICNT    DB    00h
  140.  
  141. SAVECS    DW    00H        ; where to save the old interrupt ptr
  142. SAVEIP    DW    00H
  143. LFPP    DB    00h        ; Full Page pointer
  144. DEAF    DB    00H        ; when we can't handle any more packets
  145. OFFS    DW    00H        ; how many times the handler was turned off
  146. FIRSTFD    dw    FDBASE        ; start of FD queue
  147. LASTFD    DW    0        ; end of the FD chain
  148. LASTBD    DW    0        ; end of the BD chain
  149. IOADDR    DW    0300h        ; I/O address for card (jumpers)
  150. UBASE    DW      0d000h        ; base segment for board (jumper set)
  151. ;
  152. ;  data for configuring and setting up the MICOM board
  153. ;
  154. ;  chip always looks at SCP for config info which points to ISCP for the
  155. ;  pointer to the CONTROL BLOCK which handles everything from there.
  156. ;  Kind of indirect, but it works.
  157. ;
  158. SCP    DB    1        ; bus use flag
  159.     DB    5 DUP(0)    ; unused
  160.     DW    ISCPTR        ; 24pointer to ISCP offset
  161.     DW    0        ; high part
  162. ;
  163. ; Intermediate SCP
  164. ;
  165. ISCP    DW    1        ; busy flag
  166.     DW    SCB        ; 16pointer to SCB
  167.     DW    0,0        ; base for all 16 pointers, lo, hi
  168.                 ; board is hardwired to 0 for these values
  169. ;
  170. ; Configuration block for 82586, this comprises one config command
  171. ;  Parameters taken from MICOM driver
  172. ;
  173. CBCONF    DW    0        ; status word
  174.     DW    8002H        ; end of command list + configure command
  175.     DW    0ffffh        ; link to next command (not used)
  176.     DW    080CH        ; fifo=8, byte count=C
  177.     DW    2E00H        ; important! Addr (AL) not inserted on the fly!
  178.     DW    6000H        ; IFS = 60h
  179.     DW    0F200H        ; retry=F, slot time=200h
  180.     DW    0            ; flags, set to 1 for promiscuous
  181.     DW    40H            ; min frame length=40h
  182. ;
  183. ; CB for xmit, followed by BD for xmit, copied together
  184. ;
  185. TCB    DW    0        ; status word
  186.     DW    08004H        ; command word for xmit + EL
  187.     DW    0ffffh        ; no command link
  188.     DW    TBDPTR        ; 16pointer to xmit BD
  189.     DW    0,0,0,0        ; no addressing used here
  190. ;
  191. ; BD template for xmit
  192. TBD    DW    0
  193.     DW    0        ; next BD pointer, unused
  194.     DW    TBUFPTR        ; 24pointer to xmit buffer
  195.     DW    0        ; high part of pointer
  196.  
  197. ifdef Microsoft
  198. ;_DATA    ends
  199. else
  200.     ENDDS
  201. endif
  202. ;
  203. ;
  204. ;
  205. ;   The subroutines to call from C
  206. ;
  207. ifdef Microsoft
  208.     .code
  209.     PUBLIC    _M9RECV,_M9ETOPEN,_M9ETCLOSE,_M9GETADDR,_M9XMIT,_M9ETUPDATE
  210. else
  211.     PSEG
  212.     PUBLIC    M9RECV,M9ETOPEN,M9ETCLOSE,M9GETADDR,M9XMIT,M9ETUPDATE
  213. endif
  214.  
  215. ;******************************************************************
  216. ;  ETOPEN
  217. ;     Initialize the Ethernet board, set receive type.
  218. ;
  219. ;  usage:  etopen(s,irq,address,ioaddr)
  220. ;           char s[6];       ethernet address
  221. ;           int irq;         (unused, we don't use no interrupts)
  222. ;           int address         base mem address
  223. ;           int ioaddr       io base address
  224. ;
  225. ifdef Microsoft
  226. _M9ETOPEN    PROC    FAR
  227. else
  228. M9ETOPEN    PROC    FAR
  229. endif
  230.     PUSH    BP
  231.     MOV    BP,SP
  232.     PUSH    ES
  233.     PUSH    SI
  234.     PUSH    DI
  235.  
  236.     mov    ax,[bp+X+6]    ; second parameter
  237.     mov    UBASE,ax    ; base address
  238. ;    mov    ax,UBASE    ; get a copy (temporary)
  239.     mov    es,ax        ; set to base address
  240.     mov    ax,[bp+X+8]    ; get I/O address
  241.     mov    IOADDR,ax    ; save a copy
  242. ;    mov    ax,IOADDR    ; get a copy (temporary)
  243. ;
  244. ;  check for correct EPROM location
  245. ;
  246.     mov    dx,ax        ; i/o address
  247.     add    dx,12
  248.     in    al,dx
  249.     mov    bl,al        ; assemble pattern to check
  250.     inc    dx
  251.     inc dx
  252.     in    al,dx
  253.     mov    bh,al
  254.     cmp    bx,05500h    ; pattern known to be there in ROM
  255.     jz    goinit
  256.     mov    ax,-1
  257.     POP        DI
  258.     POP        SI
  259.     pop    es
  260.     pop    bp
  261.     ret
  262. goinit:
  263. ;
  264. ;  Initialize MICOM 9210
  265. ;
  266. ;  Install 8K SCP, we only use 8K bytes no matter what
  267. ;
  268.     mov    si,offset SCP    ; get pre-set values
  269.     mov    di,SCPTR
  270.     mov    cx,5        ; 5 words
  271.     rep    movsw        ; install SCP
  272. ;
  273. ;  Install 16K SCP
  274. ;
  275.     mov    si,offset SCP    ; get pre-set values
  276.     mov    di,SCPTR+02000h        ; offset for 16K board
  277.     mov    cx,5        ; 5 words
  278.     rep    movsw        ; install SCP
  279. ;
  280. ;  Intermediate SCP
  281. ;
  282.     mov    si,offset ISCP    ; addr of pre-set values
  283.     mov    di,ISCPTR
  284.     mov    cx,4        ; 4 words
  285.     rep    movsw        ; install ISCP
  286. ;
  287. ;  Turn off interrupts, I don't want them
  288. ;  can't turn off on 9210, shouldn't get any anyway
  289. ;    mov    dx,IOADDR    ; base for IO control
  290. ;    add    dx,IOINTOF    ; turn ints off
  291. ;    out    dx,al        ; any value in ax
  292.  
  293.     mov dx,IOADDR    ; base address = reset
  294.     out    dx,al        ; reset the chip
  295. ;
  296. ;  Issue a CA to initialize the chip after reset
  297. ;
  298.     add    dx,IOCA
  299.     out    dx,al        ; CA
  300. ;
  301. ;  Disconnect from network
  302.     add    dx,2
  303.     out    dx,al
  304. ;
  305. ;  configure 82586
  306. ;
  307.     mov    si,offset CBCONF    ; configure command
  308.     mov    di,CCBPTR        ; where command will reside
  309.     mov    cx,9
  310.     rep    movsw            ; copy to board
  311. ;
  312. ;  issue the configure command
  313. ;
  314.     mov    word ptr es:[SCB+SCOM],0100h    ; do-command command
  315.     mov    word ptr es:[SCB+SCBL],CCBPTR    ; where conf command is
  316.     mov    word ptr es:[SCB+SERRS],0    ; zero errs field
  317.     mov    word ptr es:[SCB+SERRS+2],0    ; zero errs field
  318.     mov    word ptr es:[SCB+SERRS+4],0    ; zero errs field
  319.     mov    word ptr es:[SCB+SERRS+6],0    ; zero errs field
  320.     mov    dx,IOADDR
  321.     add    dx,IOCA            ; CA
  322.     out    dx,al            ; send it
  323.     xor    cx,cx            ; timeout
  324. waitconf:
  325.     mov    ax,word ptr es:[CCBPTR]    ; get status word
  326.     test    ax,08000h        ; is command complete?
  327.     loopz    waitconf
  328.     jnz    confok
  329.     mov    ax,-3            ; timeout problem
  330.     POP        DI
  331.     POP        SI
  332.     pop    es
  333.     pop    bp
  334.     ret
  335. ;
  336. confok:
  337. ;
  338. ;  Next step, load our address into the board
  339. ;     reuses the space that the configure command used, with different command 
  340. ;
  341.     mov    di,CCBPTR        ; start of config command block
  342.     xor    ax,ax
  343. ifdef QAK
  344.     stosw                ; zero status word for commmand
  345.     mov    ax,8001h        ; IA setup command + EL
  346.     stosw
  347.     xor    ax,ax
  348.     dec    ax
  349.     stosw                ; set link value to -1 (unused)
  350. else
  351.         stosw                ;set up ia command
  352.         mov    [di], 8001h
  353.         inc    di
  354.         inc    di
  355.         stosw
  356. endif
  357.  
  358. ;  move my addr onto board location inside IA command
  359. ;  es:di is already set
  360. ;
  361.     PUSH     DS        ; save my DS
  362.     MOV    AX,[BP+X+2]    ; get new one
  363.     MOV    DS,AX           ; set new one
  364.     MOV    SI,[BP+X]    ; get pointer, ds:si is ready
  365.     ;
  366.     movsw
  367.     movsw
  368.     movsw
  369.     POP    DS        ; get back DS of local data
  370. ;
  371. ;  start the IA setup command, 
  372. ;
  373.     mov    word ptr es:[SCB+SCOM],0100h    ; do-command command
  374. ifndef QAK
  375.     mov    word ptr es:[SCB+SCBL],CCBPTR    ; where conf command is
  376.     mov    word ptr es:[SCB+SERRS],0    ; zero errs field
  377.     mov    word ptr es:[SCB+SERRS+2],0    ; zero errs field
  378.     mov    word ptr es:[SCB+SERRS+4],0    ; zero errs field
  379.     mov    word ptr es:[SCB+SERRS+6],0    ; zero errs field
  380. endif
  381.     mov    dx,IOADDR
  382.     add    dx,IOCA            ; CA
  383.     out    dx,al            ; send it
  384.     xor    cx,cx            ; timeout
  385. waitia:
  386.     mov    ax,word ptr es:[CCBPTR]    ; get status word
  387.     test    ax,08000h        ; is command complete?
  388.     loopz    waitia
  389.     jnz    iaok
  390.     mov    ax,-2            ; timeout problem
  391.  
  392.     POP        DI
  393.     POP        SI
  394.     pop    es
  395.     pop    bp
  396.     ret
  397. ;
  398. iaok:
  399. ;
  400. ;  IA sent, setup all of the other data structures on the board
  401. ;  start with xmit command descriptors
  402. ;
  403.     mov    si,offset TCB        ; template for xmit
  404.     mov    di,TCBPTR        ; where it goes on board
  405.     mov    cx,12            ; copies CB and BD for xmit
  406.     rep    movsw
  407. ;
  408. ;  Set up frame and buffer descriptors, 30 each
  409. ;
  410.     mov    cx,30            ; # of FDs
  411.     mov    di,FDBASE        ; base addr for FDs
  412. fdloop:
  413.     xor    ax,ax
  414.     mov    bx,di            ; save pointer
  415.     stosw                ; clear status wd
  416.     stosw                ; clear EL field
  417.     add    bx,22            ; points to next one
  418.     mov    es:[di],bx        ; put in link ptr
  419.     inc    di
  420.     inc    di
  421.     dec    ax
  422.     stosw                ; clear BD ptr to -1
  423.     add    di,14
  424.     loop    fdloop
  425. ;
  426.     sub    di,20            ; point back to last EL field
  427.     mov    ax,08000h        ; end of list
  428.     stosw                ; put into last FD
  429.     sub    di,4            ; back to beginning of last FD
  430.     mov    LASTFD,di        ; save the pointer
  431.     mov    word ptr es:[di+FDLINK],FDBASE    ; make list circular, from last to first
  432.     
  433. ;
  434.     mov    ax,BDBASE        ; first BD
  435.     mov    word ptr es:[FDBASE+FDPTR],ax    ; put it in the first FD frame
  436. ;
  437. ;  now BDs
  438.     mov    cx,30
  439.     mov    di,BDBASE        ; start of BD area
  440.     mov    dx,BUFBASE        ; start of buffer area
  441. bdloop:
  442.     xor    ax,ax
  443.     mov    bx,di            ; save pointer
  444.     stosw                ; zero status field
  445.     add    bx,10            ; point to next record
  446.     mov    es:[di],bx        ; put in link ptr
  447.     inc    di
  448.     inc    di
  449.     mov    es:[di],dx        ; address of buffer, lo part
  450.     inc    di
  451.     inc    di
  452.     stosw                ; zero out high part
  453.     mov    ax,200
  454.     stosw                ; store length field    
  455.     add    dx,ax            ; add in length of buffer, updates ptr
  456.     loop    bdloop
  457. ;
  458.     sub    di,2            ; back to last BD size field
  459.     mov    ax,08000h+200        ; end of list + 200
  460.     stosw                ; mark end of list
  461.     sub    di,8            ; back to last BDLINK field
  462.     mov    ax,BDBASE
  463.     stosw                ; put link to beginning of list here
  464.     sub    di,4            ; back to beginning of last BD
  465.     mov    LASTBD,di        ; save pointer to end of list
  466. ;
  467. ;  minor detail, but important
  468. ;  Change SCB command block pointer to setup for xmit commands
  469. ;      = only commands needed when operational
  470. ;
  471.     mov    word ptr es:[SCB+SCBL],TCBPTR    ; where xmit command is
  472. ;
  473. ;  configure to connect to network
  474. ;
  475.     mov    dx,IOADDR
  476.     add    dx,IOENA        ; enable network
  477.     out    dx,al            ; any al value
  478. ;
  479. ;  Start the RU, doesn't need CB, only SCB parms.
  480. ;   command, to start receiving
  481. ;
  482.     mov    word ptr es:[SCB],0        ; clear status word
  483.     mov    word ptr es:[SCB+SRFA],FDBASE    ; set to frame descriptors
  484.     mov    word ptr es:[SCB+SCOM],010h    ; start RU
  485.     mov    dx,IOADDR
  486.     add    dx,IOCA            ; issue CA
  487.     out    dx,al
  488. ;
  489. ;  don't wait for response, we are done
  490. ;
  491.     xor    ax,ax
  492.     POP    DI
  493.     POP    SI
  494.     POP    ES
  495.     POP    BP
  496.     RET
  497. ifdef Microsoft
  498. _M9ETOPEN    ENDP
  499. else
  500. M9ETOPEN    ENDP
  501. endif
  502. ;
  503. ;
  504. ;*******************************************************************
  505. ;  GETADDR
  506. ;     get the Ethernet address off of the board
  507. ;
  508. ;   usage:  getaddr(s,address,ioaddr);
  509. ;    char s[6];           will get six bytes from the PROM
  510. ;
  511. ifdef Microsoft
  512. _M9GETADDR    PROC    FAR
  513. else
  514. M9GETADDR    PROC    FAR
  515. endif
  516.     PUSH    BP
  517.     MOV    BP,SP
  518.     PUSH     ES        ; save mine
  519.     PUSH    DI
  520.  
  521.     mov    dx,[BP+X+6]    ; get board's base io addr
  522. ;    mov    dx,IOADDR    ; (temporary)
  523.     MOV    AX,[BP+X+2]    ; get new one
  524.     MOV    ES,AX           ; set new one
  525.     MOV    DI,[BP+X]    ; get pointer, es:di is ready
  526.     ;
  527.     mov    cx,6
  528.     CLD
  529. getonee:
  530.     in    al,dx        ; get a byte of the EPROM address
  531.     STOSB            ; put it away
  532.     add    dx,2        ; next register
  533.     loop getonee        ; go back for rest
  534.  
  535.     xor    ax,ax
  536.     POP        DI
  537.     POP     ES
  538.     POP    BP        
  539.     RET
  540. ifdef Microsoft
  541. _M9GETADDR    ENDP
  542. else
  543. M9GETADDR    ENDP
  544. endif
  545. ;
  546. ;***********************************************************************
  547. ;  ETCLOSE
  548. ;        shut it down if necessary
  549. ;        MICOM board never interrupts, so we can leave it running.
  550. ;        Who cares, right?
  551. ;
  552. ifdef Microsoft
  553. _M9ETCLOSE    PROC    FAR
  554. else
  555. M9ETCLOSE    PROC    FAR
  556. endif
  557.     RET
  558. ifdef Microsoft
  559. _M9ETCLOSE    ENDP
  560. else
  561. M9ETCLOSE    ENDP
  562. endif
  563. ;
  564. ;
  565. ;************************************************************************
  566. ;  XMIT         
  567. ;     send a packet to Ethernet
  568. ;     Is not interrupt driven, just call it when you need it.
  569. ;
  570. ;  usage:   xmit(packet,count)
  571. ;        char *packet;
  572. ;        int count;
  573. ;
  574. ;   Takes a packet raw, Ethernet packets start with destination address,
  575. ;   and puts it out onto the wire.  Count is the length of packet < 2048
  576. ;
  577. ;   checks for packets under the Ethernet size limit of 60 and handles them
  578. ;
  579. ifdef Microsoft
  580. _M9XMIT    PROC    FAR
  581. else
  582. M9XMIT    PROC    FAR
  583. endif
  584.     PUSH    BP
  585.     MOV    BP,SP
  586.     PUSH    ES
  587.     PUSH    SI
  588.     PUSH    DI
  589.  
  590.     mov    ax,ubase
  591.     mov    es,ax        ; base for board
  592.     PUSH    DS        ; set up proper ds for the buffer
  593.     MOV    AX,[BP+X+2]
  594.     MOV    DS,AX
  595.     MOV    SI,[BP+X]    ; offset for buffer
  596.  
  597.     MOV    DX,[BP+X+4]    ; count of bytes
  598.     MOV    CX,DX        ; save a copy, might be less than 60, ok
  599.  
  600.     CMP    DX,60        ; minimum length for Ether
  601.     JNB    OKLEN
  602.     MOV    DX,60        ; make sure size at least 60
  603. OKLEN:
  604.     mov    di,TBUFPTR    ; start of xmit buffer
  605.  
  606. ;
  607. ;  check for previous xmit
  608. xwait:
  609.     mov    bx,word ptr es:[SCB+SCOM]    ; is command zeroed yet?
  610.     or    bx,bx
  611.     jnz    xwait        ; not there yet, wait for it
  612. ;
  613. ;  move the data
  614.     rep    movsb        ; copy into buffer
  615. ;
  616. ;  put the correct size into the TDB
  617. ;
  618.     or    dx,08000h    ; end of frame bit flag
  619.     mov    word ptr es:[TBDPTR],dx        ; store it
  620.     mov    word ptr es:[TCBPTR],0        ; zero status wd
  621.     mov    word ptr es:[TCBPTR+TCOM],08004h; xmit command in TCB
  622.     mov    word ptr es:[SCB+SCOM],0100h    ; execute command
  623. ;    test    bx,0100h            ; suspended?
  624. ;    jz    nosus
  625. ;    mov    word ptr es:[SCB+SCOM],0400h    ; stop command
  626. ;nosus:
  627.     pop    ds            ; get back my ds
  628.     mov    dx,IOADDR
  629.     add    dx,IOCA
  630.     out    dx,al        ; issue CA to get it going
  631.     xor     ax,ax
  632.     POP        DI
  633.     POP        SI
  634.     POP    ES
  635.     POP    BP
  636.     RET
  637. ifdef Microsoft
  638. _M9XMIT    ENDP
  639. else
  640. M9XMIT    ENDP
  641. endif
  642. ;
  643. ;
  644. ;***********************************************************************
  645. ;   Receive
  646. ;   This is a CPU hook for boards that must be polled before we can
  647. ;   deliver packets into the receive buffer.  (i.e. no interrupts used)
  648. ;
  649. ;   The 3COM 3C501 version uses interrupts, so this routine is a NOP
  650. ;   for that board.
  651. ;
  652. ;    usage:  recv();
  653. ;
  654. ;
  655. ifdef Microsoft
  656. _M9RECV    proc    far
  657. else
  658. M9RECV    proc    far
  659. endif
  660.     push    bp
  661.     push    es
  662.     PUSH    SI
  663.     PUSH    DI
  664.  
  665.     MOV    AX,word ptr [BUFPT+2]    ; buffer's ds
  666.     MOV    DI,BUFPT    ; where buffer is
  667.     MOV    ES,AX
  668.  
  669. ;
  670. ;  check for buffer overrun or catching up with reader
  671. ;
  672. ;  implicit 64K max buffer, should stop before 64K anyway
  673. ;
  674.     MOV    AX,BUFBIG    ; how much stuff is in buffer
  675.     MOV    BX,BUFLIM    ; what is our size limit?
  676.     CMP    AX,BX
  677.     JNA    ISROOM        ; we are ok
  678. ;
  679. ;  no room at the Inn. 
  680. ;
  681.     JMP    ENDINT        ; can't do much, we lose packets until restarted
  682.  
  683. ;
  684. ;  wrap pointer around at end, we know that we have room
  685. ;
  686. ISROOM:
  687.     MOV    DX,BUFEND    ; right before 2K safety area
  688.     CMP    DX,DI        ; see if pointer is over limit
  689.     JA    OKAYREAD    ; we are not at wrap-around
  690.  
  691.     MOV    AX,BUFORG    ; wrap to here
  692.     MOV    BUFPT,AX    ; wrap-around
  693.     MOV    DI,AX        ; di also
  694. ;
  695. ;  here, DI contains where we want to put the packet.
  696. ;  Add 2 to allow for space to put the size value
  697. ;
  698. OKAYREAD:
  699.     inc    di
  700.     inc    di        ; room for size word
  701.     mov    bx,FIRSTFD    ; get addr of first FD in list
  702.     mov    dx,ubase    ; base for board
  703.     push    ds
  704.     mov    ds,dx
  705. ;
  706. ;  
  707. CKFRAME:
  708.     mov    ax,[bx]        ; status word of frame
  709.     test    ax,08000h    ; frame written?
  710.     jnz    IREADONE    ; yes, read it in
  711.     pop    ds
  712.     call    rust        ; restore receiver if necessary
  713.     jmp    STOPINT
  714. ;
  715. ;  we have a frame, read it in
  716. ;
  717. IREADONE:
  718.     test    ax,02000h    ; check frame OK bit
  719.     jnz    frameok        ; ok, read it
  720.     mov    cx,ds
  721.     pop    ds
  722.     call    rust        ; preserves cx, restart RU if necessary
  723.     jmp SHORT freespace   ; not OK, just free the frame
  724.  
  725. frameok:
  726.     mov    si,[bx+FDPTR]    ; get pointer to buffer descriptor
  727.  
  728. copybuf:            ; es:di is already set to receive packet
  729.     mov    dx,si        ; save a copy of current BD ptr
  730.     mov    ax,[si]        ; get status and count word for BD
  731.     push    ax        ; save for EOF bit
  732.     test    ax,04000h    ; is count field there?
  733.     jnz    okcount
  734.     pop    ax    
  735.     mov    cx,ds
  736.     pop    ds
  737.     jmp SHORT freespace   ; free the frame, etc
  738. okcount:
  739.     xor    cx,cx
  740.     mov    cl,al        ; 200 bytes is largest this can be
  741.     mov    si,[si+BDPTR]    ; get offset of data
  742.     rep    movsb        ; copy the bytes from this packet segment
  743.     mov    si,dx        ; get back current BD ptr
  744.     pop    ax        ; get back EOF bit
  745.     test    ax,08000h    ; check bit
  746.     jnz    ptrupdate    ; free the frame, no more data here
  747.     mov    si,[si+BDLINK]    ; go to next BD in list
  748.     jmp    copybuf        ; copy the next buffer
  749. ;
  750. ;
  751. ptrupdate:
  752. ;
  753. ;  DI now contains updated value for BUFPT
  754. ;
  755.     mov    cx,ds        ; save board segment
  756.     pop    ds
  757.     mov    bx,BUFPT    ; get where size field for this packet goes
  758.     mov    ax,di        ; where pointer is now
  759.     sub    ax,bx        ; where is was then, difference is size
  760.     MOV    DX,BUFBIG    ; total amount of stuff in buffer
  761.     ADD    DX,AX        ; add in size of this packet
  762.     MOV    BUFBIG,DX    ; after adding in current packet size
  763.  
  764.     dec    ax
  765.     dec    ax        ; account for length field
  766.     mov    [bx],ax        ; put the accumulated size there
  767.  
  768.     MOV    BUFPT,DI    ; it is here, now
  769.  
  770. ;
  771. freespace:
  772. ;
  773. ;  we are done with the frame, do the list management
  774. ;    cx=DS for board  DS=DGROUP
  775. ;
  776.     mov    bx,FIRSTFD    ; the frame we are working with
  777.     mov    di,LASTBD    ; where end of BD list is now
  778.     mov    es,cx        ; reload board segment
  779.  
  780.     mov    si,es:[bx+FDPTR]    ; first BD in frame list
  781. nextbd:
  782.     mov    cx,es:[si]    ; count word for BD, EOF bit
  783.     test    cx,08000h    ; EOF bit, if set, save si in lastbd
  784.     jnz    dolastbd
  785.     mov    word ptr es:[si],0    ; clear status word, EOF bit
  786.     cmp    si,LASTBD        ; see if we are wrapping
  787.     jz    dolastbd        ; yes, just undo it
  788.     mov    si,es:[si+BDLINK]    ; follow link
  789.     jmp    nextbd
  790. dolastbd:
  791.     mov    LASTBD,si    ; store last known BD
  792.     mov    word ptr es:[si+BDSIZE],08000h+200    ; end of list here
  793.     mov    word ptr es:[si],0    ; clear status word, EOF bit
  794. ; size field for not end of list
  795.     mov    word ptr es:[di+BDSIZE],200    ; remove old end-of-list
  796.  
  797. ;
  798. ;  update the FD list flags, new end-of-list
  799. ;
  800.     mov    di,LASTFD    ; get old end-of-list
  801.     mov    word ptr es:[bx+FDEOL],08000h    ; store new EOL
  802.     mov    word ptr es:[bx],0        ; clear status word for frame
  803.     mov    word ptr es:[di+FDEOL],0    ; zero old one
  804.     mov    LASTFD,bx    ; update stored pointer
  805.     mov    si,es:[bx+FDLINK]        ; where next fd is
  806.     mov    FIRSTFD,si    ; store that info for next time
  807. ;    mov    bx,LASTBD    ; last of the BD list
  808. ;    mov    ax,es:[bx+BDLINK]        ; get link field from lastBD
  809. ;    mov    es:[si+FDPTR],ax        ; store into next frame
  810. ;
  811. ;  signs that something is actually happening - for debugging
  812. ;
  813. ;    MOV    AX,0B000H       ; screen
  814. ;    MOV    ES,AX
  815. ;    MOV    DI,3998        ; lower right corner
  816. ;    INC    ICNT
  817. ;    MOV    al,ICNT        ; character
  818. ;    STOSB
  819.  
  820. ;
  821. ;  set up to read the next packet from the net
  822. ;
  823. STOPINT:
  824.  
  825. ENDINT:
  826.     POP        DI
  827.     POP        SI
  828.     POP    ES
  829.     POP    BP
  830.     RET
  831. ifdef Microsoft
  832. _M9RECV    ENDP
  833. else
  834. M9RECV    ENDP
  835. endif
  836.  
  837. rust    proc    near        ; re-start receiver
  838. ;
  839. ;  check to see if the receiver went off because of no resources
  840. ;  and restart receiver if necessary
  841. ;  ds=dgroup, no other requirements
  842. ;
  843.     push    es
  844.     mov    ax,ubase
  845.     mov    es,ax
  846.     mov    ax,es:[SCB]    ; status word for SCB
  847.     and    ax,070h        ; receiver status
  848.     cmp    al,020h        ; receiver has no resources
  849.     jnz    hasres
  850. ;
  851. ;  setup lists for starting the RU on the chip
  852. ;  we know that there isn't anything in the buffer that we want
  853. ;
  854.     mov    bx,FIRSTFD    ; get first FD on free list (assume free)
  855.     mov    word ptr es:[SCB+SRFA],bx    ; put into SCB
  856.     mov    si,LASTBD    ; pointer to a BD, end of chain
  857.     mov    ax,word ptr es:[si+BDLINK]    ; pointer to next BD
  858.     mov    word ptr es:[bx+FDPTR],ax    ; set to start of BDs
  859. ;
  860. ;
  861. ;  Start the RU, doesn't need CB, only SCB parms.
  862. ;   command, to start receiving again
  863. ;
  864.     mov    word ptr es:[SCB],0        ; clear status word
  865.     mov    word ptr es:[SCB+SCOM],010h    ; start RU
  866.     mov    dx,IOADDR
  867.     add    dx,IOCA            ; issue CA
  868.     out    dx,al
  869. hasres:
  870.     pop    es
  871.     ret    
  872. rust    endp
  873. ;
  874. ;*************************************************************************
  875. ;  ETUPDATE
  876. ;      update pointers and/or restart receiver when read routine has
  877. ;      already removed the current packet
  878. ;
  879. ifdef Microsoft
  880. _M9ETUPDATE    PROC    FAR
  881. else
  882. M9ETUPDATE    PROC    FAR
  883. endif
  884.     PUSH     ES
  885.  
  886.     MOV    AX,word ptr [BUFPT+2]    ; establish data segment to buffer
  887.     MOV    ES,AX        ; put that in es
  888. ;
  889.     MOV    BX,BUFREAD    ; where read pointer is now
  890.     MOV    DX,ES:[BX]    ; get size of this packet
  891.     INC    DX
  892.     INC    DX        ; TWO MORE FOR LENGTH VALUE
  893.  
  894.     ADD    BX,DX        ; increment bufread by size of packet
  895.  
  896.     MOV    CX,BUFEND    ; right before 2K safety area
  897.     CMP    BX,CX        ; see if pointer is over limit
  898.     JB    NOWRAPRD    ; we are not at wrap-around
  899.     
  900.     MOV    BX,BUFORG    ; wrap to here
  901. NOWRAPRD:
  902.     MOV    BUFREAD,BX    ; buffer pointer has been updated
  903.  
  904. ;
  905. ;  DECREMENT TOTAL BUFFER SIZE
  906. ;
  907.     CLI            ; keep interrupt handler from bothering dec
  908.     MOV    CX,BUFBIG    ; size before removing packet
  909.     SUB    CX,DX        ; remove size of current packet
  910.     MOV    BUFBIG,CX    ; put it back
  911.     STI
  912. ;
  913. ;  IF RECEIVER IS ON, THEN CHECKING BUFLIM IS UNNECESSARY.
  914. ;
  915.     MOV    AL,DEAF        ; is the receiver turned off?
  916.     OR    AL,AL        ; 0 = reading, 1 = deaf
  917.     JZ    ALIVE
  918. ;
  919. ;  CHECK FOR ROOM IN THE BUFFER, IF THERE IS, TURN ON RECEIVER
  920. ;
  921.     MOV    AX,BUFLIM    ; what is our limit?
  922.     CMP    CX,AX        ; compare to limit
  923.     JA    ALIVE        ; not really alive, but can't turn on yet
  924.  
  925.     XOR    AL,AL
  926.     MOV    DEAF,AL        ; reset flag
  927.  
  928.     INC    OFFS        ; keep count how many times this happened
  929.  
  930. ALIVE:
  931.     POP    ES
  932.     RET
  933. ifdef Microsoft
  934. _M9ETUPDATE    ENDP
  935. else
  936. M9ETUPDATE    ENDP
  937. endif
  938.  
  939.  
  940. ifdef Microsoft
  941. ;_TEXT    ends
  942. else
  943.     ENDPS
  944. endif
  945.     END
  946.