Subversion Repositories Kolibri OS

Rev

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