Subversion Repositories Kolibri OS

Rev

Rev 7251 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
9159 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2021. All rights reserved.    ;;
3545 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  Broadcom NetXtreme 57xx driver for KolibriOS                   ;;
7
;;                                                                 ;;
8
;;          GNU GENERAL PUBLIC LICENSE                             ;;
9
;;             Version 2, June 1991                                ;;
10
;;                                                                 ;;
11
;; Broadcom's programmers's manual for the BCM57xx                 ;;
12
;; http://www.broadcom.com/collateral/pg/57XX-PG105-R.pdf          ;;
13
;;                                                                 ;;
14
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
15
 
4663 hidnplayr 16
format PE DLL native
17
entry START
3545 hidnplayr 18
 
4663 hidnplayr 19
        CURRENT_API             = 0x0200
20
        COMPATIBLE_API          = 0x0100
21
        API_VERSION             = (COMPATIBLE_API shl 16) + CURRENT_API
3545 hidnplayr 22
 
9159 hidnplayr 23
; configureable area
24
 
3545 hidnplayr 25
        MAX_DEVICES             = 16
26
 
27
        __DEBUG__               = 1
28
        __DEBUG_LEVEL__         = 2
29
 
9159 hidnplayr 30
        TX_RING_SIZE            = 128   ; Number of packets in send ring buffer
31
        RX_RING_SIZE            = 128   ; Number of packets in receive ring buffer
32
 
33
; end configureable area
34
 
4663 hidnplayr 35
section '.flat' readable writable executable
36
 
37
include '../proc32.inc'
4467 hidnplayr 38
include '../struct.inc'
39
include '../macros.inc'
3545 hidnplayr 40
include '../fdo.inc'
5074 hidnplayr 41
include '../netdrv.inc'
3545 hidnplayr 42
 
9159 hidnplayr 43
if (bsr TX_RING_SIZE)>(bsf TX_RING_SIZE)
44
  display 'TX_RING_SIZE must be a power of two'
45
  err
46
end if
47
 
48
if (bsr RX_RING_SIZE)>(bsf RX_RING_SIZE)
49
  display 'RX_RING_SIZE must be a power of two'
50
  err
51
end if
52
 
4663 hidnplayr 53
struct  device          ETH_DEVICE
3545 hidnplayr 54
 
4663 hidnplayr 55
        mmio_addr       dd ?
56
        pci_bus         dd ?
57
        pci_dev         dd ?
58
        irq_line        db ?
3545 hidnplayr 59
 
4663 hidnplayr 60
        cur_tx          dd ?
61
        last_tx         dd ?
3545 hidnplayr 62
 
4663 hidnplayr 63
        rb 0x100 - ($ and 0xff) ; align 256
64
        rx_desc         rd 256/8
3545 hidnplayr 65
 
4663 hidnplayr 66
        rb 0x100 - ($ and 0xff) ; align 256
67
        tx_desc         rd 256/8
3545 hidnplayr 68
 
4663 hidnplayr 69
ends
3545 hidnplayr 70
 
71
 
72
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
73
;;                        ;;
74
;; proc START             ;;
75
;;                        ;;
76
;; (standard driver proc) ;;
77
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
78
 
4663 hidnplayr 79
proc START c, reason:dword, cmdline:dword
3545 hidnplayr 80
 
4663 hidnplayr 81
        cmp     [reason], DRV_ENTRY
82
        jne     .fail
3545 hidnplayr 83
 
4663 hidnplayr 84
        DEBUGF  1,"Loading driver\n"
85
        invoke  RegService, my_service, service_proc
3545 hidnplayr 86
        ret
87
 
88
  .fail:
4663 hidnplayr 89
        xor     eax, eax
3545 hidnplayr 90
        ret
91
 
92
endp
93
 
94
 
95
 
96
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
97
;;                        ;;
98
;; proc SERVICE_PROC      ;;
99
;;                        ;;
100
;; (standard driver proc) ;;
101
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
102
 
103
proc service_proc stdcall, ioctl:dword
104
 
105
        mov     edx, [ioctl]
4470 hidnplayr 106
        mov     eax, [edx + IOCTL.io_code]
3545 hidnplayr 107
 
108
;------------------------------------------------------
109
 
110
        cmp     eax, 0 ;SRV_GETVERSION
111
        jne     @F
112
 
4470 hidnplayr 113
        cmp     [edx + IOCTL.out_size], 4
3545 hidnplayr 114
        jb      .fail
4470 hidnplayr 115
        mov     eax, [edx + IOCTL.output]
3545 hidnplayr 116
        mov     [eax], dword API_VERSION
117
 
118
        xor     eax, eax
119
        ret
120
 
121
;------------------------------------------------------
122
  @@:
123
        cmp     eax, 1 ;SRV_HOOK
124
        jne     .fail
125
 
4470 hidnplayr 126
        cmp     [edx + IOCTL.inp_size], 3               ; Data input must be at least 3 bytes
3545 hidnplayr 127
        jb      .fail
128
 
4470 hidnplayr 129
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 130
        cmp     byte [eax], 1                           ; 1 means device number and bus number (pci) are given
131
        jne     .fail                                   ; other types arent supported for this card yet
132
 
133
; check if the device is already listed
134
 
135
        mov     esi, device_list
136
        mov     ecx, [devices]
137
        test    ecx, ecx
138
        jz      .firstdevice
139
 
4470 hidnplayr 140
;        mov     eax, [edx + IOCTL.input]                      ; get the pci bus and device numbers
3545 hidnplayr 141
        mov     ax, [eax+1]                             ;
142
  .nextdevice:
143
        mov     ebx, [esi]
4663 hidnplayr 144
        cmp     al, byte [ebx + device.pci_bus]
3545 hidnplayr 145
        jne     .next
4663 hidnplayr 146
        cmp     ah, byte [ebx + device.pci_dev]
3545 hidnplayr 147
        je      .find_devicenum                         ; Device is already loaded, let's find it's device number
148
  .next:
149
        add     esi, 4
150
        loop    .nextdevice
151
 
152
 
153
; This device doesnt have its own eth_device structure yet, lets create one
154
  .firstdevice:
155
        cmp     [devices], MAX_DEVICES                  ; First check if the driver can handle one more card
156
        jae     .fail
157
 
4663 hidnplayr 158
        allocate_and_clear ebx, sizeof.device, .fail      ; Allocate the buffer for device structure
3545 hidnplayr 159
 
160
; Fill in the direct call addresses into the struct
161
 
4663 hidnplayr 162
        mov     [ebx + device.reset], reset
163
        mov     [ebx + device.transmit], transmit
164
        mov     [ebx + device.unload], unload
165
        mov     [ebx + device.name], my_service
3545 hidnplayr 166
 
167
; save the pci bus and device numbers
168
 
4470 hidnplayr 169
        mov     eax, [edx + IOCTL.input]
3545 hidnplayr 170
        movzx   ecx, byte [eax+1]
4663 hidnplayr 171
        mov     [ebx + device.pci_bus], ecx
3545 hidnplayr 172
        movzx   ecx, byte [eax+2]
4663 hidnplayr 173
        mov     [ebx + device.pci_dev], ecx
3545 hidnplayr 174
 
175
; Now, it's time to find the base mmio addres of the PCI device
176
 
7251 hidnplayr 177
        stdcall PCI_find_mmio, [ebx + device.pci_bus], [ebx + device.pci_dev]
178
        test    eax, eax
179
        jz      .destroy
3545 hidnplayr 180
 
181
; Create virtual mapping of the physical memory
182
 
7251 hidnplayr 183
        invoke  MapIoMem, eax, 10000h, PG_SW+PG_NOCACHE
4663 hidnplayr 184
        mov     [ebx + device.mmio_addr], eax
3545 hidnplayr 185
 
186
; We've found the mmio address, find IRQ now
187
 
4663 hidnplayr 188
        invoke  PciRead8, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.interrupt_line
189
        mov     [ebx + device.irq_line], al
3545 hidnplayr 190
 
191
        DEBUGF  1,"Hooking into device, dev:%x, bus:%x, irq:%x, addr:%x\n",\
4663 hidnplayr 192
        [ebx + device.pci_dev]:1,[ebx + device.pci_bus]:1,[ebx + device.irq_line]:1,[ebx + device.mmio_addr]:8
3545 hidnplayr 193
 
194
; Ok, the eth_device structure is ready, let's probe the device
195
        call    probe                                                   ; this function will output in eax
196
        test    eax, eax
197
        jnz     .err                                                    ; If an error occured, exit
198
 
199
        mov     eax, [devices]                                          ; Add the device structure to our device list
200
        mov     [device_list+4*eax], ebx                                ; (IRQ handler uses this list to find device)
201
        inc     [devices]                                               ;
202
 
4663 hidnplayr 203
        mov     [ebx + device.type], NET_TYPE_ETH
204
        invoke  NetRegDev
3545 hidnplayr 205
 
206
        cmp     eax, -1
207
        je      .destroy
208
 
209
        ret
210
 
211
; If the device was already loaded, find the device number and return it in eax
212
 
213
  .find_devicenum:
214
        DEBUGF  1,"Trying to find device number of already registered device\n"
4663 hidnplayr 215
        invoke  NetPtrToNum                                             ; This kernel procedure converts a pointer to device struct in ebx
3545 hidnplayr 216
                                                                        ; into a device number in edi
217
        mov     eax, edi                                                ; Application wants it in eax instead
218
        DEBUGF  1,"Kernel says: %u\n", eax
219
        ret
220
 
221
; If an error occured, remove all allocated data and exit (returning -1 in eax)
222
 
223
  .destroy:
224
        ; todo: reset device into virgin state
225
 
226
  .err:
4663 hidnplayr 227
        invoke  KernelFree, ebx
3545 hidnplayr 228
 
229
  .fail:
230
        or      eax, -1
231
        ret
232
 
233
;------------------------------------------------------
234
endp
235
 
236
 
237
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
238
;;                                                                        ;;
239
;;        Actual Hardware dependent code starts here                      ;;
240
;;                                                                        ;;
241
;;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\;;
242
 
243
unload:
244
        ; TODO: (in this particular order)
245
        ;
246
        ; - Stop the device
247
        ; - Detach int handler
248
        ; - Remove device from local list (device_list)
249
        ; - call unregister function in kernel
250
        ; - Remove all allocated structures and buffers the card used
251
 
252
        or      eax, -1
253
 
254
ret
255
 
256
 
257
 
258
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
259
;;
4663 hidnplayr 260
;;  probe: enables the device (if it really is BCM57XX)
3545 hidnplayr 261
;;
262
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4663 hidnplayr 263
 
3545 hidnplayr 264
probe:
265
 
266
        DEBUGF  1,"Probe\n"
267
 
4663 hidnplayr 268
; Make the device a bus master
269
        invoke  PciRead32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command
9159 hidnplayr 270
        or      al, PCI_CMD_MASTER + PCI_CMD_MMIO + PCI_CMD_PIO
4663 hidnplayr 271
        invoke  PciWrite32, [ebx + device.pci_bus], [ebx + device.pci_dev], PCI_header00.command, eax
3545 hidnplayr 272
 
273
        ; TODO: validate the device
274
 
275
reset:
276
 
277
        DEBUGF  1,"Reset\n"
278
 
4663 hidnplayr 279
        movzx   eax, [ebx + device.irq_line]
3545 hidnplayr 280
        DEBUGF  1,"Attaching int handler to irq %x\n", eax:1
4663 hidnplayr 281
        invoke  AttachIntHandler, eax, int_handler, ebx
3545 hidnplayr 282
        test    eax, eax
283
        jnz     @f
284
        DEBUGF  1,"\nCould not attach int handler!\n"
285
;        or      eax, -1
286
;        ret
287
  @@:
288
 
289
        call    read_mac
290
 
291
; Set the mtu, kernel will be able to send now
4663 hidnplayr 292
        mov     [ebx + device.mtu], 1514
3545 hidnplayr 293
 
294
; Set link state to unknown
4663 hidnplayr 295
        mov     [ebx + device.state], ETH_LINK_UNKNOWN
3545 hidnplayr 296
 
297
        ret
298
 
299
 
300
 
301
 
302
align 4
303
read_mac:
304
 
305
        DEBUGF  1,"Read MAC\n"
306
 
4663 hidnplayr 307
        mov     esi, [ebx + device.mmio_addr]
308
        lea     edi, [ebx + device.mac]
3545 hidnplayr 309
        movsd
310
        movsw
311
 
312
  .mac_ok:
313
        DEBUGF  1,"MAC = %x-%x-%x-%x-%x-%x\n",\
4663 hidnplayr 314
        [ebx + device.mac+0]:2,[ebx + device.mac+1]:2,[ebx + device.mac+2]:2,[ebx + device.mac+3]:2,[ebx + device.mac+4]:2,[ebx + device.mac+5]:2
3545 hidnplayr 315
 
316
        ret
317
 
318
 
319
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
320
;;                                         ;;
321
;; Transmit                                ;;
322
;;                                         ;;
9159 hidnplayr 323
;; In: pointer to device structure in ebx  ;;
324
;; Out: eax = 0 on success                 ;;
3545 hidnplayr 325
;;                                         ;;
326
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9159 hidnplayr 327
align 16
4663 hidnplayr 328
proc transmit stdcall bufferptr, buffersize
329
 
9159 hidnplayr 330
        spin_lock_irqsave
4663 hidnplayr 331
 
332
        DEBUGF  1,"Transmitting packet, buffer:%x, size:%u\n", [bufferptr], [buffersize]
333
        mov     eax, [bufferptr]
334
        DEBUGF  1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
3545 hidnplayr 335
        [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
336
        [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
337
        [eax+13]:2,[eax+12]:2
338
 
4663 hidnplayr 339
        cmp     [buffersize], 1514
9159 hidnplayr 340
        ja      .error
4663 hidnplayr 341
        cmp     [buffersize], 60
9159 hidnplayr 342
        jb      .error
3545 hidnplayr 343
 
9159 hidnplayr 344
; Program the descriptor
3545 hidnplayr 345
 
9159 hidnplayr 346
;        test   [something], STILL_BUSY?
347
;        jnz    .overrun
3545 hidnplayr 348
 
9159 hidnplayr 349
; TODO: Program the descriptor
3545 hidnplayr 350
 
351
; Update stats
4663 hidnplayr 352
        inc     [ebx + device.packets_tx]
353
        mov     eax, [buffersize]
354
        add     dword[ebx + device.bytes_tx], eax
355
        adc     dword[ebx + device.bytes_tx + 4], 0
3545 hidnplayr 356
 
4663 hidnplayr 357
        DEBUGF  1,"Transmit OK\n"
9159 hidnplayr 358
        spin_unlock_irqrestore
4334 hidnplayr 359
        xor     eax, eax
4663 hidnplayr 360
        ret
3545 hidnplayr 361
 
9159 hidnplayr 362
  .error:
363
        DEBUGF  2, "TX packet error\n"
364
        inc     [ebx + device.packets_tx_err]
365
        invoke  NetFree, [bufferptr]
366
 
367
        spin_unlock_irqrestore
4334 hidnplayr 368
        or      eax, -1
4663 hidnplayr 369
        ret
3545 hidnplayr 370
 
9159 hidnplayr 371
  .overrun:
372
        DEBUGF  2, "TX overrun\n"
373
        inc     [ebx + device.packets_tx_ovr]
374
        invoke  NetFree, [bufferptr]
375
 
376
        spin_unlock_irqrestore
377
        or      eax, -1
378
        ret
379
 
4663 hidnplayr 380
endp
3545 hidnplayr 381
 
4663 hidnplayr 382
 
3545 hidnplayr 383
;;;;;;;;;;;;;;;;;;;;;;;
384
;;                   ;;
385
;; Interrupt handler ;;
386
;;                   ;;
387
;;;;;;;;;;;;;;;;;;;;;;;
9159 hidnplayr 388
align 16
3545 hidnplayr 389
int_handler:
390
 
391
        push    ebx esi edi
392
 
9159 hidnplayr 393
        mov     ebx, [esp+4*4]
394
        DEBUGF  1,"INT for 0x%x\n", ebx
3545 hidnplayr 395
 
9159 hidnplayr 396
; TODO? if we are paranoid, we can check that the value from ebx is present in the current device_list
3545 hidnplayr 397
 
9159 hidnplayr 398
        mov     edi, [ebx + device.mmio_addr]
3545 hidnplayr 399
;        mov     eax, [edi + REG_ICR]
400
        test    eax, eax
9159 hidnplayr 401
        jz      .nothing
402
 
403
        DEBUGF  1,"Status: %x ", eax
404
 
405
; TODO: handle interrupts
406
 
3545 hidnplayr 407
        pop     edi esi ebx
408
        xor     eax, eax
9159 hidnplayr 409
        inc     eax
3545 hidnplayr 410
 
411
        ret
412
 
9159 hidnplayr 413
  .nothing:
3545 hidnplayr 414
        pop     edi esi ebx
415
        xor     eax, eax
416
 
417
        ret
418
 
419
 
420
 
421
 
422
; End of code
423
 
4663 hidnplayr 424
data fixups
425
end data
3545 hidnplayr 426
 
4663 hidnplayr 427
include '../peimport.inc'
428
 
3545 hidnplayr 429
my_service      db 'BCM57XX',0                   ; max 16 chars include zero
430
 
431
include_debug_strings                           ; All data wich FDO uses will be included here
432
 
4663 hidnplayr 433
align 4
434
devices         dd 0
3545 hidnplayr 435
device_list     rd MAX_DEVICES                  ; This list contains all pointers to device structures the driver is handling
436