Subversion Repositories Kolibri OS

Rev

Rev 1 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 ha 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3
;;  ETHERNET.INC                                                   ;;
4
;;                                                                 ;;
5
;;  Ethernet network layer for Menuet OS                           ;;
6
;;                                                                 ;;
7
;;  Version 0.4  22 September 2003                                 ;;
8
;;                                                                 ;;
9
;;  This file contains the following:                              ;;
10
;;      PCI bus scanning for valid devices                         ;;
11
;;      Table of supported ethernet drivers                        ;;
12
;;      Code to identify and activate a supported driver           ;;
13
;;      ARP handler                                                ;;
14
;;      Driver interface to the IP layer                           ;;
15
;;      Gateway support                                            ;;
16
;;                                                                 ;;
17
;;  Individual driver files are included here                      ;;
18
;;                                                                 ;;
19
;;  The PCI bus scanning code was ported from the etherboot        ;;
20
;;  5.0.6 project. The copyright statement for that code is        ;;
21
;;                                                                 ;;
22
;;          GNU GENERAL PUBLIC LICENSE                             ;;
23
;;             Version 2, June 1991                                ;;
24
;;                                                                 ;;
25
;;  remaining parts Copyright 2002 Mike Hibbett                    ;;
26
;;   mikeh@oceanfree.net                                           ;;
27
;;                                                                 ;;
28
;;  See file COPYING for details                                   ;;
29
;;                                                                 ;;
30
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
31
 
32
;********************************************************************
33
;   Interface
34
;      ethernet_driver   called by stack_handler in stack.inc
35
;      eth_probe         called by app_stack_handler in stack.inc
36
;
37
;********************************************************************
38
 
39
; Some useful information on data structures
40
 
41
;     Ethernet Packet - ARP Request example
42
;
43
;   0                   1                   2                   3
44
;   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
45
;
46
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47
;   |       Dest   H/W Address                                      |
48
;   |                    ( 14 byte header )                         |
49
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50
;   |                               |     Source     H/W Address    |
51
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52
;   |                                                               |
53
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54
;   |    Protocol - ARP 08  06      |
55
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56
 
57
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58
;   |  H/W Type  00           01    |  Protocol Type   08 00        |
59
;   |                   ( ARP Request packet )                      |
60
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61
;   | HLen    0x06  | PLen    0x04  |    OpCode        00   01      |
62
;   |               ( 0001 for request, 0002 for reply )            |
63
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
64
;   | Source Hardware Address ( MAC Address )                       |
65
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66
;   |                               |  Source IP Address            |
67
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
68
;   |                               | Destination Hardware Address  |
69
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
70
;   |                                                               |
71
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
72
;   | Destination IP Address                                        |
73
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
74
 
75
; Include individual drivers source files at this point.
76
; If you create a new driver, include it below.
77
 
78
include "rtl8029.inc"
79
include "i8255x.inc"
80
include "rtl8139.inc"
81
include "3c59x.inc"
82
include "sis900.inc"
83
include "pcnet32.inc"
84
 
85
; DEBUGGING_STATE enables or disables output of received and transmitted
86
; data over the serial port
87
DEBUGGING_ENABLED           equ     1
88
DEBUGGING_DISABLED          equ     0
89
DEBUGGING_STATE             equ     DEBUGGING_DISABLED
90
 
91
; PCICards
92
; ========
93
; PCI vendor and hardware types for hardware supported by the above drivers
94
; If you add a driver, ensure you update this datastructure, otherwise the
95
; card will not be probed.
96
; Each driver is defined by 4 double words. These are
97
;   PCIVendorDevice  probeFunction ResetFunction PollFunction transmitFunction
98
; The last entry must be kept at all zeros, to indicate the end of the list
99
; As a PCI driver may support more than one hardware implementation, there may
100
; be several lines which refer to the same functions.
101
; The first driver found on the PCI bus will be the one used.
102
 
103
PCICARDS_ENTRY_SIZE         equ     20    ; Size of each PCICARDS entry
104
 
105
iglobal
106
PCICards:
107
dd  0x12098086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit
108
dd  0x10298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit
109
dd  0x12298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit
110
dd  0x10308086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit
111
dd  0x24498086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit
112
dd  0x802910ec, rtl8029_probe, rtl8029_reset, rtl8029_poll, rtl8029_transmit
113
dd  0x12111113, rtl8029_probe, rtl8029_reset, rtl8029_poll, rtl8029_transmit
114
dd  0x813910ec, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit
115
dd  0x590010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
116
dd  0x592010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
117
dd  0x597010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
118
dd  0x595010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
119
dd  0x595110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
120
dd  0x595210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
121
dd  0x900010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
122
dd  0x900110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
123
dd  0x900410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
124
dd  0x900510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
125
dd  0x900610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
126
dd  0x900A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
127
dd  0x905010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
128
dd  0x905110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
129
dd  0x905510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
130
dd  0x905810b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
131
dd  0x905A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
132
dd  0x920010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
133
dd  0x980010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
134
dd  0x980510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
135
dd  0x764610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
136
dd  0x505510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
137
dd  0x605510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
138
dd  0x605610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
139
dd  0x5b5710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
140
dd  0x505710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
141
dd  0x515710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
142
dd  0x525710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
143
dd  0x656010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
144
dd  0x656210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
145
dd  0x656410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
146
dd  0x450010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit
147
dd  0x09001039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit
148
dd  0x20001022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit
149
dd  0x26251022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit
150
dd  0x20011022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit
151
; following card is untested
152
dd  0x70161039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit
153
dd  0,0,0,0,0  ; end of list marker, do not remove
154
endg
155
 
156
; PCI Bus defines
157
PCI_HEADER_TYPE             equ     0x0e  ;8 bit
158
PCI_BASE_ADDRESS_0          equ     0x10  ;32 bit
159
PCI_BASE_ADDRESS_5          equ     0x24  ;32 bits
160
PCI_BASE_ADDRESS_SPACE_IO   equ     0x01
161
PCI_VENDOR_ID               equ     0x00  ;16 bit
162
PCI_BASE_ADDRESS_IO_MASK    equ     0xFFFFFFFC
163
 
164
ETHER_IP                    equ     0x0008      ; Reversed from 0800 for intel
165
ETHER_ARP                   equ     0x0608      ; Reversed from 0806 for intel
166
ETHER_RARP                  equ     0x3580
167
ARP_REQ_OPCODE              equ     0x0100
168
ARP_REP_OPCODE              equ     0x0200
169
 
170
uglobal
171
  arp_rx_count:       dd  0
172
  ip_rx_count:        dd  0
173
  dumped_rx_count:    dd  0
174
  ip_tx_count:        dd  0
175
  node_addr:          db  0,0,0,0,0,0
176
  eth_rx_data_len:    dw  0
177
  eth_status:         dd  0
178
  io_addr:            dd  0
179
  hdrtype:            db  0
180
  vendor_device:      dd  0
181
  pci_data:           dd  0
182
  pci_dev:            dd  0
183
  pci_bus:            dd  0
184
 
185
  ; These will hold pointers to the selected driver functions
186
  drvr_probe:         dd  0
187
  drvr_reset:         dd  0
188
  drvr_poll:          dd  0
189
  drvr_transmit:      dd  0
190
 
191
  ; These hold the destination Host identity for ARP responses
192
  remote_ip_add:      dd  0
193
  remote_hw_add:      db  0, 0, 0, 0, 0, 0
194
endg
195
 
196
iglobal
197
  broadcast_add:      db  0xff,0xff,0xff,0xff,0xff,0xff
198
  subnet_mask:        dd  0x00ffffff
199
endg
200
 
201
uglobal
202
  ; This is used by getMACfromIP
203
  MACAddress:         db  0,0,0,0,0,0
204
  gateway_ip:         db  0, 0, 0, 0
205
  dns_ip:             dd  0
206
endg
207
 
208
; The follow is the ARP Table.
209
; This table must be manually updated and the kernel recompilied if
210
; changes are made to it.
211
; ARP_TABLE_SIZE defines the size of the table
212
; ARP_TABLE_ENTRIES defines the number of entries in the table
213
; Each entry is 10 bytes: 4 Byte IP address, 6 byte MAC Address,
214
;                         2 bytes status, 2 bytes TTL ( in seconds )
215
; Empty entries are filled with zeros
216
; The TTL field is decremented every second, and is deleted when it
217
; reaches 0. It is refreshed every time a packet is received
218
; If the TTL field is 0xFFFF it is a permanent entry and is never deleted
219
; The status field can be the following values
220
; 0x0000  entry not used
221
; 0x0001  entry holds a valid mapping
222
; 0x0002  entry contains an IP address, awaiting ARP response
223
; 0x0003  No response received to ARP request.
224
; The last status value is provided to allow the network layer to delete
225
; a packet that is queued awaiting an ARP response
226
 
227
ARP_NO_ENTRY                equ 0
228
ARP_VALID_MAPPING           equ 1
229
ARP_AWAITING_RESPONSE       equ 2
230
ARP_RESPONSE_TIMEOUT        equ 3
231
 
232
ARP_ENTRY_SIZE              equ     14          ; Number of bytes per entry
233
ARP_TABLE_SIZE              equ     20          ; Size of table
234
ARP_TABLE_ENTRIES           equ     0           ; Inital, hardcoded entries
235
 
236
uglobal
237
  ARPTable:
238
  times ( ARP_TABLE_SIZE - ARP_TABLE_ENTRIES ) * ARP_ENTRY_SIZE  db 0
239
endg
240
 
241
iglobal
242
  NumARP:        db    ARP_TABLE_ENTRIES
243
endg
244
 
245
;***************************************************************************
246
;   Function
247
;      eth_probe
248
;   Description
249
;      Searches for an ethernet card. If found, the card is enabled and
250
;      the ethernet -> IP link established
251
;
252
;      This function scans the PCI bus looking for a supported device.
253
;      ISA bus is currently not supported.
254
;
255
;        eax is 0 if no hardware found
256
;***************************************************************************
257
eth_probe:
258
    ; Find a card on the PCI bus, and get it's address
259
    call    scan_bus                    ; Find the ethernet cards PIC address
260
    xor     eax, eax
261
    cmp     [io_addr], eax
262
    je      ep_00x                      ; Return 0 in eax if no cards found
263
 
264
    call    dword [drvr_probe]          ; Call the drivers probe function
265
 
266
    mov     eax, [io_addr]              ; return a non zero value
267
 
268
ep_00x:
269
    ret
270
 
271
;***************************************************************************
272
;   Function
273
;      ethernet_driver
274
;
275
;   Description
276
;       The ethernet RX and TX handler
277
;       This is a kernel function, called by stack_handler
278
;
279
;***************************************************************************
280
ethernet_driver:
281
    ; Do nothing if the driver is inactive
282
    cmp     [ethernet_active], byte 0
283
    je      eth_exit
284
 
285
    call    eth_rx
286
    call    eth_tx
287
 
288
eth_exit:
289
    ret
290
 
291
;***************************************************************************
292
;   Function
293
;      eth_rx
294
;
295
;   Description
296
;      Polls the ethernet card for received data. Extracts if present
297
;       Depending on the Protocol within the packet:
298
;         ARP : Pass to ARP_handler. This may result in an ARP reply
299
;               being tx'ed
300
;         IP  : Store in an IP buffer
301
;
302
;***************************************************************************
303
eth_rx:
304
    xor     ax, ax
305
    mov     [eth_rx_data_len], ax
306
    call    dword [drvr_poll]       ; Call the drivers poll function
307
 
308
    mov     ax, [eth_rx_data_len]
309
    cmp     ax, 0
310
    je      erx_exit
311
 
312
if DEBUGGING_STATE = DEBUGGING_ENABLED
313
    pusha
314
    mov     eax, 0                    ;Indicate that this is a received packet
315
    mov     cx, [eth_rx_data_len]
316
    mov     esi, Ether_buffer
317
    cmp     word [esi + 12], ETHER_IP
318
    jnz     erxd_done
319
;    cmp     byte [esi + 14 + 9], 0x06  ; TCP
320
;    jnz     erxd_done
321
    call    eth_dump
322
erxd_done:
323
    popa
324
end if
325
 
326
    ; Check the protocol. Call appropriate handler
327
    mov     eax, Ether_buffer
328
    add     eax, 12                  ; The address of the protocol word
329
 
330
    mov     ax, [eax]
331
 
332
    cmp     ax, ETHER_ARP
333
    je      erx_001                  ; It is ARP
334
 
335
    cmp     ax, ETHER_IP
336
    je      erx_002                  ; It's IP
337
 
338
;    inc     dword [dumped_rx_count]
339
 
340
    jmp     erx_exit               ; If not IP or ARP, ignore
341
 
342
erx_001:
343
    mov     eax, [arp_rx_count]
344
    inc     eax
345
    mov     [arp_rx_count], eax
346
 
347
    ; At this point, the packet is still in the Ether_buffer
348
    call    arp_handler
349
 
350
    jmp     erx_exit
351
 
352
erx_002:
353
    mov     eax, [ip_rx_count]
354
    inc     eax
355
    mov     [ip_rx_count], eax
356
 
357
    ; Check to see if the MAC address is in our arp table
358
    ; refresh the arp ttl if so
359
 
360
    mov     esi, Ether_buffer
361
    add     esi, 6
362
 
363
    call    refreshARP
364
 
365
    call    ether_IP_handler
366
 
367
    jmp     erx_exit
368
 
369
erx_exit:
370
    ret
371
 
372
;***************************************************************************
373
;   Function
374
;      eth_tx
375
;
376
;   Description
377
;      Looks at the NET1OUT_QUEUE for data to send.
378
;      Stores that destination IP in a location used by the tx routine
379
;      Looks up the MAC address in the ARP table; stores that where
380
;      the tx routine can get it
381
;      Get the length of the data. Store that where the tx routine wants it
382
;      Call tx
383
;      Places buffer on empty queue when the tx routine finished
384
;
385
;***************************************************************************
386
eth_tx:
387
    ; Look for a buffer to tx
388
    mov     eax, NET1OUT_QUEUE
389
    call    dequeue
390
    cmp     ax, NO_BUFFER
391
    je      eth_exit            ; Exit if no buffer available
392
 
393
    push    eax
394
 
395
    ; convert buffer pointer eax to the absolute address
396
    mov     ecx, IPBUFFSIZE
397
    mul     ecx
398
    add     eax, IPbuffs
399
 
400
    ; Extract the destination IP
401
    ; find the destination IP in the ARP table, get MAC
402
    ; store this MAC in 'MACAddress'
403
    mov     ebx, eax               ; Save buffer address
404
    mov     edx, [ebx + 16]        ; get destination address
405
 
406
    ; If the destination address is 255.255.255.255,
407
    ; set the MACAddress to all ones ( broadcast )
408
    mov     [MACAddress], dword 0xffffffff
409
    mov     [MACAddress + 4], word 0xffff
410
    cmp     edx, 0xffffffff
411
    je      etx_send                ; If it is broadcast, just send
412
 
413
    call    getMACfromIP           ; Get the MAC address.
414
 
415
    cmp     eax, ARP_VALID_MAPPING
416
    jz      etx_send
417
 
418
    ; No valid entry. Are we waiting for a response?
419
    cmp     eax, ARP_AWAITING_RESPONSE
420
    jne     etx_001
421
 
422
    ; Re-queue the packet, and exit
423
    pop     ebx
424
    mov     eax, NET1OUT_QUEUE
425
    call    queue
426
    jmp     etx_exit
427
 
428
etx_001:
429
    ; HAs the request been sent, but timed out?
430
    cmp     eax, ARP_RESPONSE_TIMEOUT
431
    jne     etx_002
432
 
433
    pop     eax
434
    call    freeBuff
435
    jmp     etx_exit
436
 
437
etx_002:
438
    ; There is no entry. Re queue the request, and ask ARP to send a request
439
 
440
    ; IP address is in edx
441
    push    edx
442
    call    arp_request
443
    pop     ebx
444
 
445
    ; Add an entry in the ARP table, awaiting response
446
 
447
    cmp     byte [NumARP], ARP_TABLE_SIZE
448
    je      etx_003            ; We cannot add a new entry in the table
449
 
450
    inc     byte [NumARP]
451
 
452
    movzx   eax, byte [NumARP]
453
    mov     ecx, ARP_ENTRY_SIZE
454
    mul     ecx
455
    sub     eax, ARP_ENTRY_SIZE
456
 
457
    mov     [eax + ARPTable], ebx
458
    xor     ebx, ebx
459
    mov     [eax + ARPTable + 4], ebx
460
    mov     [eax + ARPTable + 8], bx
461
 
462
    ; set the status field up - awaiting response
463
    mov     cl, 0x00
464
    mov     [eax + ARPTable + 10], cl
465
    mov     cl, 0x02
466
    mov     [eax + ARPTable + 11], cl
467
 
468
    ; Initialise the time to live field - 10s
469
    mov     cx, 0x000A
470
    mov     [eax + ARPTable + 12], cx
471
 
472
etx_003:
473
    pop     ebx                        ; Get the buffer back
474
    mov     eax, NET1OUT_QUEUE
475
    call    queue
476
    jmp     etx_exit
477
 
478
etx_send:
479
    xor     ecx, ecx
480
    mov     ch, [ebx+2]
481
    mov     cl, [ebx+3]          ; ; Size of IP packet to send
482
 
483
    mov     esi, ebx
484
 
485
    mov     edi, MACAddress
486
 
487
if DEBUGGING_STATE = DEBUGGING_ENABLED
488
    pusha
489
    mov     cx, 42
490
    mov     eax, 1                    ; Indicate that this is a tx packet
491
    call    eth_dump
492
    popa
493
end if
494
 
495
    mov     bx, ETHER_IP
496
    call    dword [drvr_transmit]       ; Call the drivers transmit function
497
 
498
    ; OK, we have sent a packet, so increment the count
499
    inc     dword [ip_tx_count]
500
 
501
    ; And finally, return the buffer to the free queue
502
    pop     eax
503
    call    freeBuff
504
 
505
etx_exit:
506
    ret
507
 
508
;***************************************************************************
509
;   Function
510
;      ether_IP_handler
511
;
512
;   Description
513
;      Called when an IP ethernet packet is received on the ethernet
514
;      Header + Data is in Ether_buffer[]
515
;      We just need to get a buffer from the 'free' queue, and
516
;      store the packet in it, then insert the packet number into the
517
;      IPRX queue.
518
;      If no queue entry is available, the packet is silently discarded
519
;      All registers may be destroyed
520
;
521
;***************************************************************************
522
ether_IP_handler:
523
    mov     eax, EMPTY_QUEUE
524
    call    dequeue
525
    cmp     ax, NO_BUFFER
526
    je      eiph00x
527
 
528
    ; convert buffer pointer eax to the absolute address
529
    push    eax
530
    mov     ecx, IPBUFFSIZE
531
    mul     ecx
532
    add     eax, IPbuffs
533
 
534
    mov     edi, eax
535
 
536
    ; get a pointer to the start of the DATA
537
    mov     esi, Ether_buffer + 14
538
 
539
    ; Now store it all away
540
    mov     ecx, IPBUFFSIZE / 4     ; Copy all of the available
541
                              ; data across - worse case
542
    cld
543
    rep     movsd
544
 
545
    ; And finally, place the buffer in the IPRX queue
546
    pop     ebx
547
    mov     eax, IPIN_QUEUE
548
    call    queue
549
 
550
eiph00x:
551
    ret
552
 
553
;***************************************************************************
554
;
555
;  ARP CODE FOLLOWS
556
;
557
;  The ARP code is used by ethernet drivers to translate an destination
558
;  IP address into an ethernet hardware address. Functions to broadcast
559
;  requests and handle response are (or will be) here.
560
;  The IP layer has no knowledge of ARP, as this is a network interface
561
;  issue
562
;
563
;***************************************************************************
564
 
565
;***************************************************************************
566
;   Function
567
;      arp_timer
568
;
569
;   Description
570
;      Called every 1s
571
;      It is responsible for removing expired routes
572
;      All registers may be destroyed
573
;
574
;***************************************************************************
575
arp_timer:
576
    ; loop through all the ARP entries, decrementing each one
577
    ; that doesn't have a TTL of 0xFFFF
578
    movzx   eax, byte [NumARP]
579
 
580
arp_001:
581
    cmp     eax, 0
582
    je      arp_003
583
 
584
    push    eax
585
    dec     eax
586
    mov     ecx, ARP_ENTRY_SIZE
587
    mul     ecx
588
    cmp     word [ eax + ARPTable + 12], 0xFFFF
589
    je      arp_002
590
 
591
    cmp     word [ eax + ARPTable + 12], 0
592
    je      arp_002
593
 
594
    dec     word [eax + ARPTable + 12]
595
 
596
arp_002:
597
    pop     eax
598
    dec     eax
599
    jmp     arp_001
600
 
601
    ; Now, look for entries with a TTL of 0
602
    ; Valid entries and response timeout entries get removed
603
    ; awaiting response gets converted into a response timeout, with a
604
    ; short life time - this allows queued packets to be flushed
605
arp_003:
606
    movzx   edx, byte [NumARP]
607
    cmp     edx, 0
608
    je      arp_exit
609
 
610
    ; EDX holds the # of entries to search through
611
    mov     eax, 0
612
 
613
arp_005:
614
    cmp     word [ eax + ARPTable + 12], 0
615
    jne     arp_004
616
 
617
    ; If it's status code is 0001 or 0003, delete the entry
618
    cmp     word [eax + ARPTable + 10], 0x0100
619
    je      arp_007
620
    cmp     word [eax + ARPTable + 10], 0x0300
621
    je      arp_007
622
 
623
    ; The only other valid code is 0002 - indicating a
624
    ; timeout while waiting for a response. Change the
625
    ; entry to response timed out
626
 
627
    mov     [eax + ARPTable + 10], word 0x0300
628
    mov     [eax + ARPTable + 12], word 0x000A
629
    jmp     arp_004
630
 
631
arp_007:
632
    ; Delete this entry
633
    mov     edi, ARPTable
634
    add     edi, eax
635
    mov     esi, edi
636
    add     esi, ARP_ENTRY_SIZE
637
 
638
    mov     ecx, (ARP_TABLE_SIZE - 1) * ARP_ENTRY_SIZE
639
    sub     ecx, eax
640
 
641
    rep     movsb
642
 
643
    dec     byte [NumARP]
644
    jmp     arp_006
645
 
646
arp_004:
647
    add     eax, ARP_ENTRY_SIZE
648
arp_006:
649
    dec     edx
650
    cmp     edx, 0
651
    jne     arp_005
652
 
653
arp_exit:
654
    ret
655
 
656
;***************************************************************************
657
;   Function
658
;      arp_request
659
;
660
;   Description
661
;      Sends an ARP request on the ethernet
662
;        The requested IP address is in edx
663
;      All registers may be destroyed
664
;
665
;***************************************************************************
666
arp_request:
667
    mov     ebx, Ether_buffer
668
    mov     ax, 0x0100
669
    mov     [ebx], ax
670
    add     ebx, 2
671
 
672
    mov     ax, 0x0008
673
    mov     [ebx], ax
674
    add     ebx, 2
675
 
676
    mov     ax, 0x0406
677
    mov     [ebx], ax
678
    add     ebx, 2
679
 
680
    mov     ax, 0x0100
681
    mov     [ebx], ax
682
    add     ebx, 2
683
 
684
    mov     ecx, node_addr
685
    mov     eax, [ecx]
686
    mov     [ebx], eax
687
    add     ecx, 4
688
    add     ebx, 4
689
    mov     ax, [ecx]
690
    mov     [ebx], ax
691
    add     ebx, 2
692
    mov     eax, [stack_ip]
693
    mov     [ebx], eax
694
    add     ebx, 4
695
 
696
    xor     eax, eax
697
    mov     [ebx], eax
698
    add     ebx, 4
699
    mov     [ebx], ax
700
 
701
    add     ebx, 2
702
    mov     [ebx], edx
703
 
704
    ; Now, send it!
705
 
706
    ; Pointer to 48 bit destination address in edi
707
    ; Type of packet in bx
708
    ; size of packet in ecx
709
    ; pointer to packet data in esi
710
    mov      edi, broadcast_add
711
 
712
;if DEBUGGING_STATE = DEBUGGING_ENABLED
713
;    pusha
714
;    mov     eax, 1                    ; Indicate that this is a tx packet
715
;    mov     ecx, 28
716
;   mov      esi, Ether_buffer
717
;    call    eth_dump
718
;    popa
719
;end if
720
 
721
    mov     bx, ETHER_ARP
722
    mov     ecx, 28
723
    mov     esi, Ether_buffer
724
    call    dword [drvr_transmit]       ; Call the drivers transmit function
725
    ret
726
 
727
;***************************************************************************
728
;   Function
729
;      arp_handler
730
;
731
;   Description
732
;      Called when an ARP packet is received on the ethernet
733
;      Header + Data is in Ether_buffer[]
734
;       It looks to see if the packet is a request to resolve this Hosts
735
;       IP address. If it is, send the ARP reply packet.
736
;      This Hosts IP address is in dword [stack_ip]  ( in network format )
737
;       This Hosts MAC address is in node_addr[6]
738
;      All registers may be destroyed
739
;
740
;***************************************************************************
741
arp_handler:
742
    ; Is this a REQUEST?
743
    ; Is this a request for My Host IP
744
    ; Yes - So construct a response message.
745
    ; Send this message to the ethernet card for transmission
746
 
747
    mov     ebx, Ether_buffer
748
 
749
    mov     edx, ebx
750
    add     edx, 20
751
    mov     ax, [edx]
752
    cmp     ax, ARP_REQ_OPCODE      ; Is this a request packet?
753
    jne     arph_resp            ; No - so test for response
754
 
755
    mov     edx, ebx
756
    add     edx, 38
757
    mov     eax, [edx]
758
 
759
    cmp     eax, [stack_ip]         ; Is it looking for my IP address?
760
    jne     arph_exit            ; No - so quit now
761
 
762
    ; OK, it is a request for my MAC address. Build the frame and send it
763
 
764
    ; Save the important data from the original packet
765
    ; remote MAC address first
766
    mov     ecx, remote_hw_add
767
    mov     edx, ebx
768
    add     edx, 22               ; edx points to Source h/w address
769
    mov     eax, [edx]
770
    mov     [ecx], eax
771
    add     edx, 4
772
    add     ecx, 4
773
    mov     ax, [edx]
774
    mov     [ecx],ax
775
 
776
    ; and also the remote IP address
777
    add     edx, 2
778
    mov     eax,[edx]
779
    mov     [remote_ip_add], eax
780
 
781
    ; So now we can reuse the packet. ebx still holds the address of
782
    ; the header + packet
783
    ; We dont need the header ( first 14 bytes )
784
 
785
    mov     edx, ebx
786
    add     edx, 20
787
    mov     ax, ARP_REP_OPCODE
788
    mov     [edx], ax
789
    add     edx, 2
790
 
791
    mov     ecx, node_addr
792
    mov     eax, [ecx]
793
    mov     [edx], eax
794
    add     ecx, 4
795
    add     edx, 4
796
    mov     ax, [ecx]
797
    mov     [edx], ax
798
    add     edx, 2
799
    mov     eax, [stack_ip]
800
    mov     [edx], eax
801
    add     edx, 4
802
    mov     ecx, remote_hw_add
803
    mov     eax, [ecx]
804
    mov     [edx], eax
805
    add     ecx, 4
806
    add     edx, 4
807
    mov     ax, [ecx]
808
    mov     [edx], ax
809
 
810
    add     edx, 2
811
    mov     eax, [remote_ip_add]
812
    mov     [edx], eax
813
 
814
    ; Now, send it!
815
 
816
    ; Pointer to 48 bit destination address in edi
817
    ; Type of packet in bx
818
    ; size of packet in ecx
819
    ; pointer to packet data in esi
820
    mov     edi, remote_hw_add
821
 
822
;if DEBUGGING_STATE = DEBUGGING_ENABLED
823
;    pusha
824
;    mov     eax, 1                    ; Indicate that this is a tx packet
825
;    mov     ecx, 28
826
;   mov      esi, Ether_buffer + 14
827
 ;   call    eth_dump
828
;    popa
829
;end if
830
 
831
    mov     bx, ETHER_ARP
832
    mov     ecx, 28
833
    mov     esi, Ether_buffer + 14
834
    call    dword [drvr_transmit]       ; Call the drivers transmit function
835
    jmp     arph_exit
836
 
837
arph_resp:
838
    cmp     ax, ARP_REP_OPCODE      ; Is this a replypacket?
839
    jne     arph_resp            ; No - so quit
840
 
841
    ; This was a reply, probably directed at me.
842
    ; save the remotes MAC & IP
843
    mov     ecx, remote_hw_add
844
    mov     edx, ebx
845
    add     edx, 22               ; edx points to Source h/w address
846
    mov     eax, [edx]
847
    mov     [ecx], eax
848
    add     edx, 4
849
    add     ecx, 4
850
    mov     ax, [edx]
851
    mov     [ecx],ax
852
 
853
    ; and also the remote IP address
854
    add     edx, 2
855
    mov     eax,[edx]
856
    mov     [remote_ip_add], eax
857
 
858
    ; Now, add an entry in the table for this IP address if it doesn't exist
859
 
860
    push    eax
861
    movzx   eax, byte [NumARP]
862
    mov     ecx, ARP_ENTRY_SIZE
863
    mul     ecx
864
    pop     edx
865
    movzx   ecx, byte [NumARP]
866
    cmp     ecx, 0
867
    je      arph_002
868
 
869
arph_001:
870
    sub     eax, ARP_ENTRY_SIZE
871
    cmp     [eax + ARPTable], edx
872
    loopnz  arph_001                      ; Return back if non match
873
 
874
    jnz     arph_002                   ; None found, add to end
875
 
876
    mov     ecx, [remote_hw_add]
877
    mov     [eax + ARPTable + 4], ecx
878
    mov     cx, [remote_hw_add+4]
879
    mov     [eax + ARPTable + 8], cx
880
 
881
    ; specify the type - a valid entry
882
    mov     cl, 0x00
883
    mov     [eax + ARPTable + 10], cl
884
    mov     cl, 0x01
885
    mov     [eax + ARPTable + 11], cl
886
 
887
    ; Initialise the time to live field - 1 hour
888
    mov     cx, 0x0E10
889
    mov     [eax + ARPTable + 12], cx
890
    jmp     arph_exit
891
 
892
arph_002:
893
 
894
    cmp     byte [NumARP], ARP_TABLE_SIZE
895
    je      arph_exit
896
 
897
    inc     byte [NumARP]
898
 
899
    movzx   eax, byte [NumARP]
900
    mov     ecx, ARP_ENTRY_SIZE
901
    mul     ecx
902
    sub     eax, ARP_ENTRY_SIZE
903
 
904
    mov     ecx, [remote_ip_add]
905
    mov     [eax + ARPTable], ecx
906
    mov     ecx, [remote_hw_add]
907
    mov     [eax + ARPTable + 4], ecx
908
    mov     cx, [remote_hw_add+4]
909
    mov     [eax + ARPTable + 8], cx
910
 
911
    mov     cl, 0x00
912
    mov     [eax + ARPTable + 10], cl
913
    mov     cl, 0x01
914
    mov     [eax + ARPTable + 11], cl
915
 
916
    ; Initialise the time to live field - 1 hour
917
    mov     cx, 0x0E10
918
    mov     [eax + ARPTable + 12], cx
919
 
920
arph_exit:
921
    ret
922
 
923
; pointer to MAC in esi
924
refreshARP:
925
    mov     ebx, [esi]
926
    mov     dx, [esi+4]
927
    push    edx
928
    movzx   eax, byte [NumARP]
929
    mov     ecx, ARP_ENTRY_SIZE
930
    mul     ecx
931
    pop     edx
932
    movzx   ecx, byte [NumARP]
933
    cmp     ecx, 0
934
    je      rf_exit
935
 
936
rf_001:
937
    sub     eax, ARP_ENTRY_SIZE
938
    cmp     [eax + ARPTable+4], ebx
939
 
940
    je      rf_002
941
    loop    rf_001
942
    jmp     rf_exit
943
 
944
rf_002:
945
    cmp     [eax + ARPTable+8], dx
946
    je      rf_gotone
947
    loop    rf_001
948
    jmp     rf_exit
949
 
950
rf_gotone:
951
    ; Initialise the time to live field - 1 hour
952
    mov     cx, 0x0E10
953
    mov     [eax + ARPTable + 12], cx
954
 
955
rf_exit:
956
    ret
957
 
958
;***************************************************************************
959
;   Function
960
;      getMACfromIP
961
;
962
;   Description
963
;       Takes an IP address in edx and scans the ARP table for
964
;        a matching entry
965
;       If a match is found, it's MAC address is stored in MACAddress.
966
;      Otherwise the value 0 is writen to MACAddress
967
;      eax holds ARP table entry status code ( ARP_ )
968
;      ebx unchanged
969
;
970
;***************************************************************************
971
getMACfromIP:
972
    ; first, check destination IP to see if it is on 'this' network.
973
    ; The test is:
974
    ; if ( destIP & subnet_mask == stack_ip & subnet_mask )
975
    ;   desitnation is local
976
    ; else
977
    ;  destination is remote, so pass to gateway
978
 
979
    mov     eax, edx
980
    and     eax, [subnet_mask]
981
    mov     ecx, [stack_ip]
982
    and     ecx, [subnet_mask]
983
    cmp     eax, ecx
984
    je      gm0
985
 
986
    mov     edx, [gateway_ip]
987
gm0:
988
    push    edx
989
    xor     eax, eax
990
    mov     [MACAddress], eax
991
    mov     [MACAddress + 4], ax
992
 
993
    movzx   eax, byte [NumARP]
994
    mov     ecx, ARP_ENTRY_SIZE
995
    mul     ecx
996
 
997
    pop     edx
998
 
999
    movzx   ecx, byte [NumARP]
1000
    cmp     ecx, 0
1001
    je      gm_none
1002
gm1:
1003
    sub     eax, ARP_ENTRY_SIZE
1004
    cmp     [eax + ARPTable], edx
1005
    loopnz  gm1                      ; Return back if non match
1006
    jnz     gm_none                   ; Quit if none found
1007
 
1008
    ; eax holds index
1009
    mov     ecx, [eax + ARPTable + 4]
1010
    mov     [MACAddress], ecx
1011
    mov     cx, [eax + ARPTable + 8]
1012
    mov     [MACAddress+4], cx
1013
 
1014
    ; Return the entry status in eax
1015
    mov     ch, [eax + ARPTable + 10]
1016
    mov     cl, [eax + ARPTable + 11]
1017
    movzx   eax, cx
1018
    jmp     gm_exit
1019
 
1020
gm_none:
1021
    mov     eax, ARP_NO_ENTRY
1022
 
1023
gm_exit:
1024
    ret
1025
 
1026
;***************************************************************************
1027
;
1028
;  PCI CODE FOLLOWS
1029
;
1030
;  the following functions provide access to the PCI interface.
1031
;  These functions are used by scan_bus, and also some ethernet drivers
1032
;
1033
;***************************************************************************
1034
 
1035
;***************************************************************************
1036
;   Function
1037
;      config_cmd
1038
;
1039
;   Description
1040
;       creates a command dword  for use with the PCI bus
1041
;       bus # in ebx
1042
;      devfn in ecx
1043
;       where in edx
1044
;
1045
;      command dword returned in eax
1046
;       Only eax destroyed
1047
;***************************************************************************
1048
config_cmd:
1049
    push    ecx
1050
    mov     eax, ebx
1051
    shl     eax, 16
1052
    or      eax, 0x80000000
1053
    shl     ecx, 8
1054
    or      eax, ecx
1055
    pop     ecx
1056
    or      eax, edx
1057
    and     eax, 0xFFFFFFFC
1058
    ret
1059
 
1060
;***************************************************************************
1061
;   Function
1062
;      pcibios_read_config_byte
1063
;
1064
;   Description
1065
;       reads a byte from the PCI config space
1066
;       bus # in ebx
1067
;      devfn in ecx
1068
;       where in edx ( ls 16 bits significant )
1069
;
1070
;      byte returned in al ( rest of eax zero )
1071
;       Only eax/edx destroyed
1072
;***************************************************************************
1073
pcibios_read_config_byte:
1074
    call    config_cmd
1075
    push    dx
1076
    mov     dx, 0xCF8
1077
    out     dx, eax
1078
    pop     dx
1079
 
1080
    xor     eax, eax
1081
    and     dx, 0x03
1082
    add     dx, 0xCFC
1083
;   and     dx, 0xFFC
1084
    in      al, dx
1085
    ret
1086
 
1087
;***************************************************************************
1088
;   Function
1089
;      pcibios_read_config_word
1090
;
1091
;   Description
1092
;       reads a word from the PCI config space
1093
;       bus # in ebx
1094
;      devfn in ecx
1095
;       where in edx ( ls 16 bits significant )
1096
;
1097
;      word returned in ax ( rest of eax zero )
1098
;       Only eax/edx destroyed
1099
;***************************************************************************
1100
pcibios_read_config_word:
1101
    call    config_cmd
1102
    push    dx
1103
    mov     dx, 0xCF8
1104
    out     dx, eax
1105
    pop     dx
1106
 
1107
    xor     eax, eax
1108
    and     dx, 0x02
1109
    add     dx, 0xCFC
1110
;   and     dx, 0xFFC
1111
    in      ax, dx
1112
    ret
1113
 
1114
;***************************************************************************
1115
;   Function
1116
;      pcibios_read_config_dword
1117
;
1118
;   Description
1119
;       reads a dword from the PCI config space
1120
;       bus # in ebx
1121
;      devfn in ecx
1122
;       where in edx ( ls 16 bits significant )
1123
;
1124
;      dword returned in eax
1125
;       Only eax/edx destroyed
1126
;***************************************************************************
1127
pcibios_read_config_dword:
1128
    push    edx
1129
    call    config_cmd
1130
    push    dx
1131
    mov     dx, 0xCF8
1132
    out     dx, eax
1133
    pop     dx
1134
    xor     eax, eax
1135
    mov     dx, 0xCFC
1136
    in      eax, dx
1137
    pop     edx
1138
    ret
1139
 
1140
;***************************************************************************
1141
;   Function
1142
;      pcibios_write_config_byte
1143
;
1144
;   Description
1145
;       write a byte in al to the PCI config space
1146
;       bus # in ebx
1147
;      devfn in ecx
1148
;       where in edx ( ls 16 bits significant )
1149
;
1150
;       Only eax/edx destroyed
1151
;***************************************************************************
1152
pcibios_write_config_byte:
1153
    push    ax
1154
    call    config_cmd
1155
    push    dx
1156
    mov     dx, 0xCF8
1157
    out     dx, eax
1158
    pop     dx
1159
    pop     ax
1160
 
1161
    and     dx, 0x03
1162
    add     dx, 0xCFC
1163
    out     dx, al
1164
    ret
1165
 
1166
;***************************************************************************
1167
;   Function
1168
;      pcibios_write_config_word
1169
;
1170
;   Description
1171
;       write a word in ax to the PCI config space
1172
;       bus # in ebx
1173
;      devfn in ecx
1174
;       where in edx ( ls 16 bits significant )
1175
;
1176
;       Only eax/edx destroyed
1177
;***************************************************************************
1178
pcibios_write_config_word:
1179
    push    ax
1180
    call    config_cmd
1181
    push    dx
1182
    mov     dx, 0xCF8
1183
    out     dx, eax
1184
    pop     dx
1185
    pop     ax
1186
 
1187
    and     dx, 0x02
1188
    add     dx, 0xCFC
1189
    out     dx, ax
1190
    ret
1191
 
1192
;***************************************************************************
1193
;   Function
1194
;      delay_us
1195
;
1196
;   Description
1197
;       delays for 30 to 60 us
1198
;
1199
;        I would prefer this routine to be able to delay for
1200
;       a selectable number of microseconds, but this works for now.
1201
;
1202
;       If you know a better way to do 2us delay, pleae tell me!
1203
;***************************************************************************
1204
delay_us:
1205
    push    eax
1206
    push    ecx
1207
 
1208
    mov     ecx,2
1209
 
1210
    in      al,0x61
1211
    and     al,0x10
1212
    mov     ah,al
1213
    cld
1214
 
1215
dcnt1:
1216
    in      al,0x61
1217
    and     al,0x10
1218
    cmp     al,ah
1219
    jz      dcnt1
1220
 
1221
    mov     ah,al
1222
    loop    dcnt1
1223
 
1224
    pop     ecx
1225
    pop     eax
1226
 
1227
    ret
1228
 
1229
;***************************************************************************
1230
;   Function
1231
;      scan_bus
1232
;
1233
;   Description
1234
;       Scans the PCI bus for a supported device
1235
;        If a supported device is found, the drvr_ variables are initialised
1236
;       to that drivers functions ( as defined in the PCICards table)
1237
;
1238
;        io_addr   holds card I/O space. 32 bit, but only LS 16 bits valid
1239
;        pci_data  holds the PCI vendor + device code
1240
;       pci_dev   holds PCI bus dev #
1241
;       pci_bus   holds PCI bus #
1242
;
1243
;        io_addr will be zero if no card found
1244
;
1245
;***************************************************************************
1246
scan_bus:
1247
    xor     eax, eax
1248
    mov     [hdrtype], al
1249
    mov     [pci_data], eax
1250
 
1251
    xor     ebx, ebx         ; ebx = bus# 0 .. 255
1252
 
1253
sb_bus_loop:
1254
    xor     ecx, ecx         ; ecx = devfn# 0 .. 254  ( not 255? )
1255
 
1256
sb_devf_loop:
1257
    mov     eax, ecx
1258
    and     eax, 0x07
1259
 
1260
    cmp     eax, 0
1261
    jne     sb_001
1262
 
1263
    mov     edx, PCI_HEADER_TYPE
1264
    call    pcibios_read_config_byte
1265
    mov     [hdrtype], al
1266
    jmp     sb_002
1267
 
1268
sb_001:
1269
    mov     al, [hdrtype]
1270
    and     al, 0x80
1271
    cmp     al, 0x80
1272
    jne     sb_inc_devf
1273
 
1274
sb_002:
1275
    mov     edx, PCI_VENDOR_ID
1276
    call    pcibios_read_config_dword
1277
    mov     [vendor_device], eax
1278
    cmp     eax, 0xffffffff
1279
    je      sb_empty
1280
    cmp     eax, 0
1281
    jne     sb_check_vendor
1282
 
1283
sb_empty:
1284
    mov     [hdrtype], byte 0
1285
    jmp     sb_inc_devf
1286
 
1287
sb_check_vendor:
1288
    ; iterate though PCICards until end or match found
1289
    mov     esi, PCICards
1290
 
1291
sb_check:
1292
    cmp     [esi], dword 0
1293
    je      sb_inc_devf                ; Quit if at last entry
1294
    cmp     eax, [esi]
1295
    je      sb_got_card
1296
    add     esi, PCICARDS_ENTRY_SIZE
1297
    jmp     sb_check
1298
 
1299
sb_got_card:
1300
    ; indicate that we have found the card
1301
    mov     [pci_data], eax
1302
    mov     [pci_dev], ecx
1303
    mov     [pci_bus], ebx
1304
 
1305
    ; Define the driver functions
1306
    push    eax
1307
    mov     eax, [esi+4]
1308
    mov     [drvr_probe], eax
1309
    mov     eax, [esi+8]
1310
    mov     [drvr_reset], eax
1311
    mov     eax, [esi+12]
1312
    mov     [drvr_poll], eax
1313
    mov     eax, [esi+16]
1314
    mov     [drvr_transmit], eax
1315
    pop     eax
1316
 
1317
    mov     edx, PCI_BASE_ADDRESS_0
1318
 
1319
sb_reg_check:
1320
    call    pcibios_read_config_dword
1321
    mov     [io_addr], eax
1322
    and     eax, PCI_BASE_ADDRESS_IO_MASK
1323
    cmp     eax, 0
1324
    je      sb_inc_reg
1325
    mov     eax, [io_addr]
1326
    and     eax, PCI_BASE_ADDRESS_SPACE_IO
1327
    cmp     eax, 0
1328
    je      sb_inc_reg
1329
 
1330
    mov     eax, [io_addr]
1331
    and     eax, PCI_BASE_ADDRESS_IO_MASK
1332
    mov     [io_addr], eax
1333
 
1334
sb_exit1:
1335
    ret
1336
 
1337
sb_inc_reg:
1338
    add     edx, 4
1339
    cmp     edx, PCI_BASE_ADDRESS_5
1340
    jbe     sb_reg_check
1341
 
1342
sb_inc_devf:
1343
    inc     ecx
1344
    cmp     ecx, 255
1345
    jb      sb_devf_loop
1346
    inc     ebx
1347
    cmp     ebx, 256
1348
    jb      sb_bus_loop
1349
 
1350
    ; We get here if we didn't find our card
1351
    ; set io_addr to 0 as an indication
1352
    xor     eax, eax
1353
    mov     [io_addr], eax
1354
 
1355
sb_exit2:
1356
    ret
1357
 
1358
;***************************************************************************
1359
;
1360
;  DEBUGGING CODE FOLLOWS
1361
;
1362
;  If debugging data output is not required, ALL code & data below may
1363
;  be removed.
1364
;
1365
;***************************************************************************
1366
 
1367
if DEBUGGING_STATE = DEBUGGING_ENABLED
1368
 
1369
;***************************************************************************
1370
;   Function
1371
;      eth_dump
1372
;
1373
;   Description
1374
;       Dumps a tx or rx ethernet packet over the rs232 link
1375
;       This is a debugging routine that seriously slows down the stack.
1376
;       Use with caution.
1377
;
1378
;       Baud rate is 57600, 8n1  com1
1379
;         eax : type (0 == rx, 1 == tx )
1380
;          cx : # of bytes in buffer
1381
;         esi : address of buffer start
1382
;         edi : pointer to MACAddress ( tx only )
1383
;
1384
;***************************************************************************
1385
eth_dump:
1386
    pusha
1387
 
1388
    ; Set the port to the desired speed
1389
    mov     ebx, 0x3f8                     ; combase
1390
 
1391
    mov     edx, ebx
1392
    add     edx, 3                        ; data format register
1393
    mov     al, 0x80                    ; enable access to divisor latch
1394
    out     dx, al
1395
 
1396
    mov     edx, ebx
1397
    add     edx, 1                        ; interrupt enable register
1398
    mov     al, 0x00                    ; No interruts enabled
1399
    out     dx, al
1400
 
1401
    mov     edx, ebx
1402
    mov     al, 0x20 / 16                ; set baud rate to 57600 0x10 =115200
1403
    out     dx, al
1404
 
1405
    mov     edx, ebx
1406
    add     edx, 3                        ; data format register
1407
    mov     al, 0x03                    ; 8 data bits
1408
    out     dx, al
1409
 
1410
    mov     edx, ebx
1411
    add     edx, 4                        ; Modem control register
1412
    mov     al, 0x08                    ; out2 enabled. No handshaking.
1413
    out     dx, al
1414
 
1415
    mov     edx, ebx
1416
    add     edx, 1                        ; interrupt enable register
1417
    mov     al, 0x01                    ; Receive data interrupt enabled,
1418
    out     dx, al
1419
 
1420
    popa
1421
 
1422
    ; First, display the type of the buffer.
1423
    ; If it is a tx buffer, display the macaddress
1424
 
1425
    pusha
1426
 
1427
    cmp     eax, 0
1428
    jne     dd001
1429
 
1430
    mov     bl, 0x0a
1431
    call    tx_byted
1432
    mov     bl, 0x0d
1433
    call    tx_byted
1434
 
1435
    ; Output "RX:"
1436
    mov     bl, 'R'
1437
    call    tx_byted
1438
    mov     bl, 'X'
1439
    call    tx_byted
1440
    mov     bl, ':'
1441
    call    tx_byted
1442
    jmp     dump_data
1443
 
1444
dd001:
1445
    mov     bl, 0x0a
1446
    call    tx_byted
1447
    mov     bl, 0x0d
1448
    call    tx_byted
1449
 
1450
    ; Output TX: xxxxxxxxxxxx
1451
    mov     bl, 'T'
1452
    call    tx_byted
1453
    mov     bl, 'X'
1454
    call    tx_byted
1455
    mov     bl, ':'
1456
    call    tx_byted
1457
    mov     bl, ' '
1458
    call    tx_byted
1459
 
1460
    ; Display MAC address
1461
    xor     eax, eax
1462
    mov     al, [edi]
1463
    shr     al, 4
1464
    mov     bl, [eax + hexchars]
1465
    call    tx_byted ; byte in bl eax ebx edx destroyed
1466
 
1467
    xor     eax, eax
1468
    mov     al, [edi]
1469
    and     al, 0x0f
1470
    mov     bl, [eax + hexchars]
1471
    call    tx_byted ; byte in bl eax ebx edx destroyed
1472
 
1473
    inc     edi
1474
    xor     eax, eax
1475
    mov     al, [edi]
1476
    shr     al, 4
1477
    mov     bl, [eax + hexchars]
1478
    call    tx_byted ; byte in bl eax ebx edx destroyed
1479
 
1480
    xor     eax, eax
1481
    mov     al, [edi]
1482
    and     al, 0x0f
1483
    mov     bl, [eax + hexchars]
1484
    call    tx_byted ; byte in bl eax ebx edx destroyed
1485
 
1486
    inc     edi
1487
    xor     eax, eax
1488
    mov     al, [edi]
1489
    shr     al, 4
1490
    mov     bl, [eax + hexchars]
1491
    call    tx_byted ; byte in bl eax ebx edx destroyed
1492
 
1493
    xor     eax, eax
1494
    mov     al, [edi]
1495
    and     al, 0x0f
1496
    mov     bl, [eax + hexchars]
1497
    call    tx_byted ; byte in bl eax ebx edx destroyed
1498
 
1499
    inc     edi
1500
    xor     eax, eax
1501
    mov     al, [edi]
1502
    shr     al, 4
1503
    mov     bl, [eax + hexchars]
1504
    call    tx_byted ; byte in bl eax ebx edx destroyed
1505
 
1506
    xor     eax, eax
1507
    mov     al, [edi]
1508
    and     al, 0x0f
1509
    mov     bl, [eax + hexchars]
1510
    call    tx_byted ; byte in bl eax ebx edx destroyed
1511
 
1512
    inc     edi
1513
    xor     eax, eax
1514
    mov     al, [edi]
1515
    shr     al, 4
1516
    mov     bl, [eax + hexchars]
1517
    call    tx_byted ; byte in bl eax ebx edx destroyed
1518
 
1519
    xor     eax, eax
1520
    mov     al, [edi]
1521
    and     al, 0x0f
1522
    mov     bl, [eax + hexchars]
1523
    call    tx_byted ; byte in bl eax ebx edx destroyed
1524
 
1525
    inc     edi
1526
    xor     eax, eax
1527
    mov     al, [edi]
1528
    shr     al, 4
1529
    mov     bl, [eax + hexchars]
1530
    call    tx_byted ; byte in bl eax ebx edx destroyed
1531
 
1532
    xor     eax, eax
1533
    mov     al, [edi]
1534
    and     al, 0x0f
1535
    mov     bl, [eax + hexchars]
1536
    call    tx_byted ; byte in bl eax ebx edx destroyed
1537
 
1538
dump_data:
1539
    popa
1540
 
1541
    ; OK, we come in here with
1542
    ; cx == number of byte to send
1543
    ; esi == buffer start
1544
    ;
1545
dd_000:
1546
    mov     bl, 0x0a
1547
    call    tx_byted
1548
    mov     bl, 0x0d
1549
    call    tx_byted
1550
 
1551
    mov     eax, 16        ; Number of characters on the line
1552
    mov     edi, esi    ; Save first byte position for later
1553
 
1554
    push    ecx
1555
 
1556
dd_001:
1557
    push    eax
1558
 
1559
    ; Print a byte, and a space
1560
    xor     eax, eax
1561
    mov     al, [esi]
1562
    shr     al, 4
1563
    mov     bl, [eax + hexchars]
1564
    call    tx_byted ; byte in bl eax ebx edx destroyed
1565
 
1566
    xor     eax, eax
1567
    mov     al, [esi]
1568
    and     al, 0x0f
1569
    mov     bl, [eax + hexchars]
1570
    call    tx_byted ; byte in bl eax ebx edx destroyed
1571
 
1572
    mov     bl, ' '
1573
    call    tx_byted
1574
 
1575
    pop     eax
1576
 
1577
    inc     esi
1578
    dec     ecx
1579
    cmp     ecx, 0
1580
    je      dd_0011            ; Print the ASCII format
1581
 
1582
    dec     eax
1583
 
1584
    cmp     eax, 0
1585
    je      dd_002            ; Print the ASCII format
1586
    jmp     dd_001            ; Print rest of line
1587
 
1588
dd_0011:
1589
    ; First, complete the 16 bytes of data, by printing spaces
1590
    dec     eax
1591
    cmp     eax, 0
1592
    je      dd_002
1593
 
1594
    push    eax
1595
    mov     bl, ' '
1596
    call    tx_byted
1597
    mov     bl, ' '
1598
    call    tx_byted
1599
    mov     bl, ' '
1600
    call    tx_byted
1601
    pop     eax
1602
    jmp     dd_0011
1603
 
1604
dd_002:
1605
    pop     ecx
1606
    mov     esi, edi        ; Go back to the start of the line data
1607
 
1608
    mov     eax, 16
1609
 
1610
outLineAscii:
1611
    push    eax
1612
 
1613
    xor     eax, eax
1614
    mov     al, [esi]
1615
    mov     bl, '.'
1616
 
1617
    cmp     al, 0x1F
1618
    jle     outAscii
1619
    cmp     al, 0x7e
1620
    jge     outAscii
1621
 
1622
    mov     bl, al
1623
 
1624
outAscii:
1625
    call    tx_byted ; byte in bl eax ebx edx destroyed
1626
 
1627
    pop     eax
1628
    dec     ecx
1629
    inc     esi
1630
    cmp     ecx, 0
1631
    je      dd_003
1632
 
1633
    dec     eax
1634
    cmp     eax, 0
1635
    je      dd_003
1636
    jmp     outLineAscii
1637
 
1638
dd_003:
1639
    cmp     ecx, 0
1640
    je      dd_004
1641
    jmp     dd_000
1642
 
1643
dd_004:
1644
    ret
1645
 
1646
;***************************************************************************
1647
;   Function
1648
;      tx_byte
1649
;
1650
;   Description
1651
;       Send a byte in bl out of the com port 1
1652
;       destroys eax, edx
1653
;
1654
;***************************************************************************
1655
tx_byted:
1656
    push    ebx                     ; Save the byte
1657
 
1658
    mov     ebx, 0x3f8            ; get the com port address
1659
 
1660
    ; Wait for transmit buffer to empty. This could take 1ms @ 9600baud
1661
 
1662
    mov     edx, ebx
1663
    add     edx, 5
1664
 
1665
wait_txd:
1666
    in      al, dx                   ; read uart serialisation status
1667
    and     al, 0x40
1668
    cmp     al, 0
1669
    jz      wait_txd                  ; loop until free
1670
 
1671
    mov     edx, ebx
1672
    pop     eax                     ; restore the byte to send
1673
    out     dx, al
1674
    ret
1675
 
1676
iglobal
1677
  ; This is used for translating hex to ASCII for display or output
1678
  hexchars    db '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
1679
endg
1680
end if
1681