Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
129 | mikedld | 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_ENABLED |
||
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 | ; /+/ Новые вендоры сетевых карт на базе 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 | ; /-/ |
||
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 |