Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 3588 → Rev 3589

/kernel/branches/Kolibri-acpi/bus/usb/ehci.inc
222,7 → 222,7
; ------------------------------ hardware fields ------------------------------
FrameList rd 1024
; Entry n corresponds to the head of the frame list to be executed in
; the frames n,n+1024,n+2048,n+3096,...
; the frames n,n+1024,n+2048,n+3072,...
; The first bit of each entry is Terminate bit, 1 = the frame is empty.
; Bits 1-2 are Type field, one of EHCI_TYPE_* constants.
; Bits 3-4 must be zero.
/kernel/branches/Kolibri-acpi/bus/usb/uhci.inc
126,7 → 126,7
; ------------------------------ hardware fields ------------------------------
FrameList rd 1024
; Entry n corresponds to the head of the frame list to be executed in
; the frames n,n+1024,n+2048,n+3096,...
; the frames n,n+1024,n+2048,n+3072,...
; The first bit of each entry is Terminate bit, 1 = the frame is empty.
; The second bit of each entry is QH/TD select bit, 1 = the entry points to
; QH, 0 = to TD.
/kernel/branches/Kolibri-acpi/data32.inc
375,9 → 375,6
PUTPIXEL rd 1
GETPIXEL rd 1
 
BgrDrawMode rd 1
BgrDataWidth rd 1
BgrDataHeight rd 1
REDRAW_BACKGROUND rb 4
 
MOUSE_PICTURE rd 1
480,6 → 477,12
mem_BACKGROUND rd 1
static_background_data rd 1
 
BgrDrawMode rd 1
BgrDataWidth rd 1
BgrDataHeight rd 1
 
skin_data rd 1
 
cache_ide0:
cache_ide0_pointer rd 1
cache_ide0_size rd 1 ; not use
553,7 → 556,6
FLOPPY_BUFF: rb 16*1024
BUTTON_INFO: rb 16*1024
BgrAuxTable: rb 32*1024
skin_data: rb 32*1024
 
;IDE_DMA: rb 32*1024
 
/kernel/branches/Kolibri-acpi/docs/sysfuncs.txt
2394,8 → 2394,17
</UL>
 
======================================================================
=========================== Function 52 ==============================
======================================================================
 
WARNING: This function is obsolete and is only present in the
documentation as a guide to understand/port the older network
applications. For new programs, use function 74
 
======================================================================
=== Function 52, subfunction 0 - get network driver configuration. ===
======================================================================
 
Parameters:
* eax = 52 - function number
* ebx = 0 - subfunction number
2558,6 → 2567,14
* for other ecx: eax = -1 indicates an error
 
======================================================================
=========================== Function 53 ==============================
======================================================================
 
WARNING: This function is obsolete and is only present in the
documentation as a guide to understand/port the older network
applications. For new programs, use function 75.
 
======================================================================
============ Function 53, subfunction 0 - open UDP-socket. ===========
======================================================================
Parameters:
4581,6 → 4598,201
* function does not return value
 
======================================================================
= Function 74, Subfunction -1, Get number of active network devices. =
======================================================================
Parameters:
* eax = 74 - function number
* bl = -1 - subfunction number
Returned value:
* eax = number of active network devices
 
======================================================================
======== Function 74, Subfunction 0, Get network device type. ========
======================================================================
Parameters:
* eax = 74 - function number
* bl = 0 - subfunction number
* bh = device number
Returned value:
* eax = device type
 
======================================================================
======== Function 74, Subfunction 1, Get network device name. ========
======================================================================
Parameters:
* eax = 74 - function number
* bl = 1 - subfunction number
* bh = device number
* ecx = pointer to 64 byte buffer
Returned value:
* eax = -1 on error
* The network device name is written into the buffer, on success
 
======================================================================
========= Function 74, Subfunction 2, Reset network device. ==========
======================================================================
Parameters:
* eax = 74 - function number
* bl = 2 - subfunction number
* bh = device number
Returned value:
* eax = -1 on error
 
======================================================================
========== Function 74, Subfunction 3, Stop network device. ==========
======================================================================
Parameters:
* eax = 74 - function number
* bl = 3 - subfunction number
* bh = device number
Returned value:
* eax = -1 on error
 
======================================================================
============== Function 75, Subfunction 0, Open socket. ==============
======================================================================
Parameters:
* eax = 75 - function number
* bl = 0 - subfunction number
* ecx = domain
* edx = type
* esi = protocol
Returned value:
* eax = socket number, -1 on error
 
======================================================================
============= Function 75, Subfunction 1, Close socket. ==============
======================================================================
Parameters:
* eax = 75 - function number
* bl = 1 - subfunction number
* ecx = socket number
Returned value:
* eax = -1 on error
 
======================================================================
================== Function 75, Subfunction 2, Bind. =================
======================================================================
Parameters:
* eax = 75 - function number
* bl = 2 - subfunction number
* ecx = socket number
* edx = pointer to sockaddr structure
* esi = length of sockaddr structure
Returned value:
* eax = -1 on error
 
======================================================================
================= Function 75, Subfunction 3, Listen. ================
======================================================================
Parameters:
* eax = 75 - function number
* bl = 3 - subfunction number
* ecx = socket number
* edx = backlog
Returned value:
* eax = -1 on error
 
======================================================================
================ Function 75, Subfunction 4, Connect. ================
======================================================================
Parameters:
* eax = 75 - function number
* bl = 4 - subfunction number
* ecx = socket number
* edx = pointer to sockaddr structure
* esi = length of sockaddr structure
Returned value:
* eax = -1 on error
 
======================================================================
================= Function 75, Subfunction 5, Accept. ================
======================================================================
Parameters:
* eax = 75 - function number
* bl = 5 - subfunction number
* ecx = socket number
* edx = pointer to sockaddr structure
* esi = length of sockaddr structure
Returned value:
* eax = -1 on error
 
======================================================================
================== Function 75, Subfunction 6, Send. =================
======================================================================
Parameters:
* eax = 75 - function number
* bl = 6 - subfunction number
* ecx = socket number
* edx = pointer to buffer
* esi = length of buffer
Returned value:
* eax = number of bytes copied, -1 on error
 
======================================================================
================ Function 75, Subfunction 7, Receive. ================
======================================================================
Parameters:
* eax = 75 - function number
* bl = 7 - subfunction number
* ecx = socket number
* edx = pointer to buffer
* esi = length of buffer
* edi = flags
Returned value:
* eax = number of bytes copied, -1 on error
 
======================================================================
=========== Function 75, Subfunction 8, Set socket options. ==========
======================================================================
Parameters:
* eax = 75 - function number
* bl = 8 - subfunction number
* ecx = socket number
* edx = pointer to optstruct
Returned value:
* eax = -1 on error
Remarks:
 
Optstruct: dd level
dd optionname
dd optlength
db options...
 
======================================================================
=========== Function 75, Subfunction 9, Get socket options. ==========
======================================================================
Parameters:
* eax = 75 - function number
* bl = 9 - subfunction number
* ecx = socket number
* edx = pointer to optstruct
Returned value:
* eax = -1 on error
Remarks:
 
Optstruct: dd level
dd optionname
dd optlength
db options...
 
======================================================================
============ Function 75, Subfunction 10, Get socketpair. ===========
======================================================================
Parameters:
* eax = 75 - function number
* bl = 10 - subfunction number
Returned value:
* eax = socketnum1, -1 on error
* ebx = socketnum2
Remarks:
 
Optstruct: dd level
dd optionname
dd optlength
db options...
 
======================================================================
=============== Function -1 - terminate thread/process ===============
======================================================================
Parameters:
/kernel/branches/Kolibri-acpi/docs/usbapi.txt
4,8 → 4,8
print some information, reads and parses configuration descriptor. For every
interface the kernel looks for class code of this interface and loads the
corresponding COFF driver. Currently the correspondence is hardcoded into
the kernel code and looks as follows: 3 = usbhid.obj, 8 = usbstor.obj,
9 is handled by the kernel itself, other = usbother.obj.
the kernel code and looks as follows: 3 = usbhid.obj, 7 = usbprint.obj,
8 = usbstor.obj, 9 is handled by the kernel itself, other = usbother.obj.
 
The driver must be standard driver in COFF format, exporting procedure
named "START" and a variable named "version". Loader calls "START" procedure
46,7 → 46,7
void* interfacedescr
);
 
The parameter 'controlpipe' is a handle of the control pipe for endpoint zero
The parameter 'pipe0' is a handle of the control pipe for endpoint zero
of the device. It can be used as the argument of USBControlTransferAsync.
The parameter 'configdescr' points to USB configuration descriptor
and all associated data, as returned by GET_DESCRIPTOR request.
93,7 → 93,20
The parameter 'interval' is ignored for control and bulk endpoints.
For interrupt endpoints, it sets the polling interval in milliseconds.
The function returns a handle to the pipe or NULL on failure.
The output handle becomes invalid when a) it is explicitly closed with
the following function or b) the function DeviceDisconnected provided
by the driver returns.
 
void __stdcall USBClosePipe(
void* pipe
);
 
Releases all resources associated with the given pipe. The only parameter
must be a handle returned by USBOpenPipe.
When a device is disconnected, all associated pipes are closed by the kernel;
there is no need to ever call this function if all pipes are used continuously
while a device is connected.
 
void* __stdcall USBNormalTransferAsync(
void* pipe,
void* buffer,
104,7 → 117,7
);
void* __stdcall USBControlTransferAsync(
void* pipe,
void* config,
void* setup,
void* buffer,
int size,
void* callback,
116,12 → 129,12
for given pipe. Type and direction of transfer are fixed for bulk and interrupt
endpoints and are set in USBOpenPipe. The second function inserts a control
transfer to the transfer queue for given pipe. Direction of a control transfer
is concluded from 'config' packet, bit 7 of byte 0 is set for IN transfers
is concluded from 'setup' packet, bit 7 of byte 0 is set for IN transfers
and cleared for OUT transfers. These function return immediately; when data
are transferred, the callback function will be called.
 
The parameter 'pipe' is a handle returned by USBOpenPipe.
The parameter 'config' of USBControlTransferAsync points to 8-byte
The parameter 'setup' of USBControlTransferAsync points to 8-byte
configuration packet as defined by USB.
The parameter 'buffer' is a pointer to buffer. For IN transfers, it will be
filled with the data. For OUT transfers, it should contain data to be
174,10 → 187,12
; possible only for isochronous transfers
USB_STATUS_BUFUNDERRUN = 13 ; underflow of internal controller buffer
; possible only for isochronous transfers
USB_STATUS_DISCONNECTED = 16 ; device disconnected
USB_STATUS_CLOSED = 16 ; pipe closed, either explicitly with USBClosePipe
; or due to device disconnect
 
If several transfers are queued for the same pipe, their callback functions
are called in the same order as they were queued.
When the device is disconnected, all callback functions are called
with USB_STATUS_DISCONNECTED. The call to DeviceDisconnected() occurs after
When a pipe is closed, either explicitly with USBClosePipe, or
implicitly due to device disconnect, all callback functions are called
with USB_STATUS_CLOSED. The call to DeviceDisconnected() occurs after
all callbacks.
/kernel/branches/Kolibri-acpi/drivers/usbhid.asm
0,0 → 1,696
; standard driver stuff
format MS COFF
 
DEBUG = 1
 
; this is for DEBUGF macro from 'fdo.inc'
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1
 
include 'proc32.inc'
include 'imports.inc'
include 'fdo.inc'
 
public START
public version
 
; USB constants
DEVICE_DESCR_TYPE = 1
CONFIG_DESCR_TYPE = 2
STRING_DESCR_TYPE = 3
INTERFACE_DESCR_TYPE = 4
ENDPOINT_DESCR_TYPE = 5
DEVICE_QUALIFIER_DESCR_TYPE = 6
 
CONTROL_PIPE = 0
ISOCHRONOUS_PIPE = 1
BULK_PIPE = 2
INTERRUPT_PIPE = 3
 
; USB structures
virtual at 0
config_descr:
.bLength db ?
.bDescriptorType db ?
.wTotalLength dw ?
.bNumInterfaces db ?
.bConfigurationValue db ?
.iConfiguration db ?
.bmAttributes db ?
.bMaxPower db ?
.sizeof:
end virtual
 
virtual at 0
interface_descr:
.bLength db ?
.bDescriptorType db ?
.bInterfaceNumber db ?
.bAlternateSetting db ?
.bNumEndpoints db ?
.bInterfaceClass db ?
.bInterfaceSubClass db ?
.bInterfaceProtocol db ?
.iInterface db ?
.sizeof:
end virtual
 
virtual at 0
endpoint_descr:
.bLength db ?
.bDescriptorType db ?
.bEndpointAddress db ?
.bmAttributes db ?
.wMaxPacketSize dw ?
.bInterval db ?
.sizeof:
end virtual
 
; Driver data for all devices
virtual at 0
device_data:
.type dd ? ; 1 = keyboard, 2 = mouse
.intpipe dd ? ; interrupt pipe handle
.packetsize dd ?
.packet rb 8 ; packet with data from device
.control rb 8 ; control packet to device
.sizeof:
end virtual
 
; Driver data for mouse
virtual at device_data.sizeof
mouse_data:
; no additional data
.sizeof:
end virtual
 
; Driver data for keyboard
virtual at device_data.sizeof
keyboard_data:
.handle dd ? ; keyboard handle from RegKeyboard
.configpipe dd ? ; config pipe handle
.prevpacket rb 8 ; previous packet with data from device
.timer dd ? ; auto-repeat timer handle
.repeatkey db ? ; auto-repeat key code
.ledstate db ? ; state of LEDs
align 4
.sizeof:
end virtual
 
section '.flat' code readable align 16
; The start procedure.
START:
; 1. Test whether the procedure is called with the argument DRV_ENTRY.
; If not, return 0.
xor eax, eax ; initialize return value
cmp dword [esp+4], 1 ; compare the argument
jnz .nothing
; 2. Register self as a USB driver.
; The name is my_driver = 'usbhid'; IOCTL interface is not supported;
; usb_functions is an offset of a structure with callback functions.
stdcall RegUSBDriver, my_driver, eax, usb_functions
; 3. Return the returned value of RegUSBDriver.
.nothing:
ret 4
 
; This procedure is called when new HID device is detected.
; It initializes the device.
AddDevice:
; Arguments are addressed through esp. In this point of the function,
; [esp+4] = a handle of the config pipe, [esp+8] points to config_descr
; structure, [esp+12] points to interface_descr structure.
; 1. Check device type. Currently only mice and keyboards with
; boot protocol are supported.
; 1a. Get the subclass and the protocol. Since bInterfaceSubClass and
; bInterfaceProtocol are subsequent in interface_descr, just one
; memory reference is used for both.
mov edx, [esp+12]
push ebx ; save used register to be stdcall
mov cx, word [edx+interface_descr.bInterfaceSubClass]
; 1b. For boot protocol, subclass must be 1 and protocol must be either 1 for
; a keyboard or 2 for a mouse. Check.
cmp cx, 0x0101
jz .keyboard
cmp cx, 0x0201
jz .mouse
; 1c. If the device is neither a keyboard nor a mouse, print a message and
; go to 6c.
DEBUGF 1,'K : unknown HID device\n'
jmp .nothing
; 1d. If the device is a keyboard or a mouse, print a message and continue
; configuring.
.keyboard:
DEBUGF 1,'K : USB keyboard detected\n'
push keyboard_data.sizeof
jmp .common
.mouse:
DEBUGF 1,'K : USB mouse detected\n'
push mouse_data.sizeof
.common:
; 2. Allocate memory for device data.
pop eax ; get size of device data
; 2a. Call the kernel, saving and restoring register edx.
push edx
call Kmalloc
pop edx
; 2b. Check result. If failed, say a message and go to 6c.
test eax, eax
jnz @f
DEBUGF 1,'K : no memory\n'
jmp .nothing
@@:
xchg eax, ebx
; HID devices use one IN interrupt endpoint for polling the device
; and an optional OUT interrupt endpoint. We do not use the later,
; but must locate the first. Look for the IN interrupt endpoint.
; 3. Get the upper bound of all descriptors' data.
mov eax, [esp+8+4] ; configuration descriptor
movzx ecx, [eax+config_descr.wTotalLength]
add eax, ecx
; 4. Loop over all descriptors until
; either end-of-data reached - this is fail
; or interface descriptor found - this is fail, all further data
; correspond to that interface
; or endpoint descriptor found.
; 4a. Loop start: eax points to the interface descriptor.
.lookep:
; 4b. Get next descriptor.
movzx ecx, byte [edx] ; the first byte of all descriptors is length
add edx, ecx
; 4c. Check that at least two bytes are readable. The opposite is an error.
inc edx
cmp edx, eax
jae .errorep
dec edx
; 4d. Check that this descriptor is not interface descriptor. The opposite is
; an error.
cmp byte [edx+endpoint_descr.bDescriptorType], INTERFACE_DESCR_TYPE
jz .errorep
; 4e. Test whether this descriptor is an endpoint descriptor. If not, continue
; the loop.
cmp byte [edx+endpoint_descr.bDescriptorType], ENDPOINT_DESCR_TYPE
jnz .lookep
; 5. Check that the descriptor contains all required data and all data are
; readable. If so, proceed to 7.
cmp byte [edx+endpoint_descr.bLength], endpoint_descr.sizeof
jb .errorep
sub eax, endpoint_descr.sizeof
cmp edx, eax
jbe @f
; 6. An error occured during processing endpoint descriptor.
.errorep:
; 6a. Print a message.
DEBUGF 1,'K : error: invalid endpoint descriptor\n'
; 6b. Free memory allocated for device data.
.free:
xchg eax, ebx
call Kfree
.nothing:
; 6c. Return an error.
xor eax, eax
pop ebx
ret 12
@@:
; 7. Check that the endpoint is IN interrupt endpoint. If not, go to 6.
test [edx+endpoint_descr.bEndpointAddress], 80h
jz .errorep
mov cl, [edx+endpoint_descr.bmAttributes]
and cl, 3
cmp cl, INTERRUPT_PIPE
jnz .errorep
; 8. Open pipe for the endpoint.
; 8a. Load parameters from the descriptor.
movzx ecx, [edx+endpoint_descr.bEndpointAddress]
movzx eax, [edx+endpoint_descr.bInterval]
movzx edx, [edx+endpoint_descr.wMaxPacketSize]
; 8b. Call the kernel, saving and restoring edx.
push edx
stdcall USBOpenPipe, [esp+4+24], ecx, edx, INTERRUPT_PIPE, eax
pop edx
; 8c. Check result. If failed, go to 6b.
test eax, eax
jz .free
; We use 12 bytes for device type, interrupt pipe and interrupt packet size,
; 8 bytes for a packet and 8 bytes for previous packet, used by a keyboard.
; 9. Initialize device data.
mov [ebx+device_data.intpipe], eax
push 8
pop ecx
cmp edx, ecx
jb @f
mov edx, ecx
@@:
xor eax, eax
mov [ebx+device_data.packetsize], edx
mov dword [ebx+device_data.packet], eax
mov dword [ebx+device_data.packet+4], eax
mov edx, [esp+12+4] ; interface descriptor
movzx ecx, [edx+interface_descr.bInterfaceProtocol]
mov [ebx+device_data.type], ecx
cmp ecx, 1
jnz @f
mov [ebx+keyboard_data.handle], eax
mov [ebx+keyboard_data.timer], eax
mov [ebx+keyboard_data.repeatkey], al
mov dword [ebx+keyboard_data.prevpacket], eax
mov dword [ebx+keyboard_data.prevpacket+4], eax
mov eax, [esp+4+4]
mov [ebx+keyboard_data.configpipe], eax
@@:
; 10. Send the control packet SET_PROTOCOL(Boot Protocol) to the interface.
lea eax, [ebx+device_data.control]
mov dword [eax], 21h + (0Bh shl 8) + (0 shl 16) ; class request to interface + SET_PROTOCOL + Boot protocol
and dword [eax+4], 0
mov dl, [edx+interface_descr.bInterfaceNumber]
mov [eax+4], dl
; Callback function is mouse_configured for mice and keyboard_configured1 for keyboards.
mov edx, keyboard_configured1
cmp ecx, 1
jz @f
mov edx, mouse_configured
@@:
stdcall USBControlTransferAsync, [esp+4+28], eax, 0, 0, edx, ebx, 0
; 11. Return with pointer to device data as returned value.
xchg eax, ebx
pop ebx
ret 12
 
; This function is called when SET_PROTOCOL command for keyboard is done,
; either successful or unsuccessful.
keyboard_configured1:
xor edx, edx
; 1. Check the status of the transfer.
; If the transfer was failed, go to the common error handler.
cmp dword [esp+8], edx ; status is zero?
jnz keyboard_data_ready.error
; 2. Send the control packet SET_IDLE(infinity). HID auto-repeat is not useful.
mov eax, [esp+20]
push edx ; flags for USBControlTransferAsync
push eax ; userdata for USBControlTransferAsync
add eax, device_data.control
mov dword [eax], 21h + (0Ah shl 8) + (0 shl 24) ; class request to interface + SET_IDLE + no autorepeat
stdcall USBControlTransferAsync, dword [eax+keyboard_data.configpipe-device_data.control], \
eax, edx, edx, keyboard_configured2; , <userdata>, <flags>
; 3. Return.
ret 20
 
; This function is called when SET_IDLE command for keyboard is done,
; either successful or unsuccessful.
keyboard_configured2:
; Check the status of the transfer and go to the corresponding label
; in the main handler.
cmp dword [esp+8], 0
jnz keyboard_data_ready.error
mov edx, [esp+20]
push edx
stdcall RegKeyboard, usbkbd_functions, edx
pop edx
mov [edx+keyboard_data.handle], eax
jmp keyboard_data_ready.next
 
; This function is called when another interrupt packet arrives,
; processed either successfully or unsuccessfully.
; It should parse the packet and initiate another transfer with
; the same callback function.
keyboard_data_ready:
; 1. Check the status of the transfer.
mov eax, [esp+8]
test eax, eax
jnz .error
; Parse the packet, comparing with the previous packet.
; For boot protocol, USB keyboard packet consists of the first byte
; with status keys that are currently pressed. The second byte should
; be ignored, and other 5 bytes denote keys that are currently pressed.
push esi ebx ; save used registers to be stdcall
; 2. Process control keys.
; 2a. Initialize before loop for control keys. edx = mask for control bits
; that were changed.
mov ebx, [esp+20+8]
movzx edx, byte [ebx+device_data.packet] ; get state of control keys
xor dl, byte [ebx+keyboard_data.prevpacket] ; compare with previous state
; 2b. If state of control keys has not changed, advance to 3.
jz .nocontrol
; 2c. Otherwise, loop over control keys; esi = bit number.
xor esi, esi
.controlloop:
; 2d. Skip bits that have not changed.
bt edx, esi
jnc .controlnext
push edx ; save register which is possibly modified by API
; The state of the current control key has changed.
; 2e. For extended control keys, send the prefix 0xE0.
mov al, [control_keys+esi]
test al, al
jns @f
push eax
mov ecx, 0xE0
call SetKeyboardData
pop eax
and al, 0x7F
@@:
; 2f. If the current state of the control key is "pressed", send normal
; scancode. Otherwise, the key is released, so set the high bit in scancode.
movzx ecx, al
bt dword [ebx+device_data.packet], esi
jc @f
or cl, 0x80
@@:
call SetKeyboardData
pop edx ; restore register which was possibly modified by API
.controlnext:
; 2g. We have 8 control keys.
inc esi
cmp esi, 8
jb .controlloop
.nocontrol:
; 3. Initialize before loop for normal keys. esi = index.
push 2
pop esi
.normalloop:
; 4. Process one key which was pressed in the previous packet.
; 4a. Get the next pressed key from the previous packet.
movzx eax, byte [ebx+esi+keyboard_data.prevpacket]
; 4b. Ignore special codes.
cmp al, 3
jbe .normalnext1
; 4c. Ignore keys that are still pressed in the current packet.
lea ecx, [ebx+device_data.packet]
call haskey
jz .normalnext1
; 4d. Say warning about keys with strange codes.
cmp eax, normal_keys_number
jae .badkey1
movzx ecx, [normal_keys+eax]
jecxz .badkey1
; 4e. For extended keys, send the prefix 0xE0.
push ecx ; save keycode
test cl, cl
jns @f
push ecx
mov ecx, 0xE0
call SetKeyboardData
pop ecx
@@:
; 4f. Send the release event.
or cl, 0x80
call SetKeyboardData
; 4g. If this key is autorepeating, stop the timer.
pop ecx ; restore keycode
cmp cl, [ebx+keyboard_data.repeatkey]
jnz .normalnext1
mov eax, [ebx+keyboard_data.timer]
test eax, eax
jz .normalnext1
stdcall CancelTimerHS, eax
and [ebx+keyboard_data.timer], 0
jmp .normalnext1
.badkey1:
DEBUGF 1,'K : unknown keycode: %x\n',al
.normalnext1:
; 5. Process one key which is pressed in the current packet.
; 5a. Get the next pressed key from the current packet.
movzx eax, byte [ebx+esi+device_data.packet]
; 5b. Ignore special codes.
cmp al, 3
jbe .normalnext2
; 5c. Ignore keys that were already pressed in the previous packet.
lea ecx, [ebx+keyboard_data.prevpacket]
call haskey
jz .normalnext2
; 5d. Say warning about keys with strange codes.
cmp eax, normal_keys_number
jae .badkey2
movzx ecx, [normal_keys+eax]
jecxz .badkey2
; 5e. For extended keys, send the prefix 0xE0.
push ecx ; save keycode
test cl, cl
jns @f
push ecx
mov ecx, 0xE0
call SetKeyboardData
pop ecx
@@:
; 5f. Send the press event.
and cl, not 0x80
call SetKeyboardData
; 5g. Stop the current auto-repeat timer, if present.
mov eax, [ebx+keyboard_data.timer]
test eax, eax
jz @f
stdcall CancelTimerHS, eax
@@:
; 5h. Start the auto-repeat timer.
pop ecx ; restore keycode
mov [ebx+keyboard_data.repeatkey], cl
stdcall TimerHS, 25, 5, autorepeat_timer, ebx
mov [ebx+keyboard_data.timer], eax
jmp .normalnext2
.badkey2:
DEBUGF 1,'K : unknown keycode: %x\n',al
.normalnext2:
; 6. Advance to next key.
inc esi
cmp esi, 8
jb .normalloop
; 7. Save the packet data for future reference.
mov eax, dword [ebx+device_data.packet]
mov dword [ebx+keyboard_data.prevpacket], eax
mov eax, dword [ebx+device_data.packet+4]
mov dword [ebx+keyboard_data.prevpacket+4], eax
pop ebx esi ; restore registers to be stdcall
.next:
; 8. Initiate transfer on the interrupt pipe.
mov eax, [esp+20]
push 1 ; flags for USBNormalTransferAsync
push eax ; userdata for USBNormalTransferAsync
add eax, device_data.packet
stdcall USBNormalTransferAsync, dword [eax+device_data.intpipe-device_data.packet], \
eax, dword [eax+device_data.packetsize-device_data.packet], \
keyboard_data_ready;, <userdata>, <flags>
; 9. Return.
.nothing:
ret 20
.error:
; An error has occured.
; 10. If an error is caused by the disconnect, do nothing, it is handled
; in DeviceDisconnected. Otherwise, say a message.
cmp eax, 16
jz @f
push esi
mov esi, errormsgkbd
call SysMsgBoardStr
pop esi
@@:
ret 20
 
; Auxiliary procedure for keyboard_data_ready.
haskey:
push 2
pop edx
@@:
cmp byte [ecx+edx], al
jz @f
inc edx
cmp edx, 7
jbe @b
@@:
ret
 
; Timer function for auto-repeat.
autorepeat_timer:
mov eax, [esp+4]
movzx ecx, [eax+keyboard_data.repeatkey]
test cl, cl
jns @f
push ecx
mov ecx, 0xE0
call SetKeyboardData
pop ecx
and cl, not 0x80
@@:
call SetKeyboardData
ret 4
 
; This function is called to update LED state on the keyboard.
SetKeyboardLights:
mov eax, [esp+4]
add eax, device_data.control
mov dword [eax], 21h + (9 shl 8) + (2 shl 24)
; class request to interface + SET_REPORT + Output zero report
mov byte [eax+6], 1
mov edx, [esp+8]
shr dl, 1
jnc @f
or dl, 4
@@:
lea ecx, [eax+keyboard_data.ledstate-device_data.control]
mov [ecx], dl
stdcall USBControlTransferAsync, dword [eax+keyboard_data.configpipe-device_data.control], \
eax, ecx, 1, keyboard_data_ready.nothing, 0, 0
ret 8
 
; This function is called when it is safe to free keyboard data.
CloseKeyboard:
mov eax, [esp+4]
push ebx
call Kfree
pop ebx
ret 4
 
; This function is called when SET_PROTOCOL command for mouse is done,
; either successful or unsuccessful.
mouse_configured:
; Check the status of the transfer and go to the corresponding label
; in the main handler.
cmp dword [esp+8], 0
jnz mouse_data_ready.error
mov eax, [esp+20]
add eax, device_data.packet
jmp mouse_data_ready.next
 
; This function is called when another interrupt packet arrives,
; processed either successfully or unsuccessfully.
; It should parse the packet and initiate another transfer with
; the same callback function.
mouse_data_ready:
; 1. Check the status of the transfer.
mov eax, [esp+8]
test eax, eax
jnz .error
mov edx, [esp+16]
; 2. Parse the packet.
; For boot protocol, USB mouse packet consists of at least 3 bytes.
; The first byte is state of mouse buttons, the next two bytes are
; x and y movements.
; Normal mice do not distinguish between boot protocol and report protocol;
; in this case, scroll data are also present. Advanced mice, however,
; support two different protocols, boot protocol is used for compatibility
; and does not contain extended buttons or scroll data.
mov eax, [esp+12] ; buffer
push eax
xor ecx, ecx
cmp edx, 4
jbe @f
movsx ecx, byte [eax+4]
@@:
push ecx
xor ecx, ecx
cmp edx, 3
jbe @f
movsx ecx, byte [eax+3]
neg ecx
@@:
push ecx
xor ecx, ecx
cmp edx, 2
jbe @f
movsx ecx, byte [eax+2]
neg ecx
@@:
push ecx
movsx ecx, byte [eax+1]
push ecx
movzx ecx, byte [eax]
push ecx
call SetMouseData
pop eax
.next:
; 3. Initiate transfer on the interrupt pipe.
stdcall USBNormalTransferAsync, dword [eax+device_data.intpipe-device_data.packet], \
eax, dword [eax+device_data.packetsize-device_data.packet], mouse_data_ready, eax, 1
; 4. Return.
ret 20
.error:
; An error has occured.
; 5. If an error is caused by the disconnect, do nothing, it is handled
; in DeviceDisconnected. Otherwise, say a message.
cmp eax, 16
jz @f
push esi
mov esi, errormsgmouse
call SysMsgBoardStr
pop esi
@@:
ret 20
 
; This function is called when the device is disconnected.
DeviceDisconnected:
push ebx ; save used register to be stdcall
; 1. Say a message. Use different messages for keyboards and mice.
mov ebx, [esp+4+4]
push esi
mov esi, disconnectmsgk
cmp byte [ebx+device_data.type], 1
jz @f
mov esi, disconnectmsgm
@@:
stdcall SysMsgBoardStr
pop esi
; 2. If device is keyboard, then we must unregister it as a keyboard and
; possibly stop the auto-repeat timer.
cmp byte [ebx+device_data.type], 1
jnz .nokbd
mov eax, [ebx+keyboard_data.timer]
test eax, eax
jz @f
stdcall CancelTimerHS, eax
@@:
mov ecx, [ebx+keyboard_data.handle]
jecxz .nokbd
stdcall DelKeyboard, ecx
; If keyboard is registered, then we should free data in CloseKeyboard, not here.
jmp .nothing
.nokbd:
; 3. Free the device data.
xchg eax, ebx
call Kfree
; 4. Return.
.nothing:
pop ebx ; restore used register to be stdcall
ret 4 ; purge one dword argument to be stdcall
 
; strings
my_driver db 'usbhid',0
errormsgmouse db 'K : USB transfer error, disabling mouse',10,0
errormsgkbd db 'K : USB transfer error, disabling keyboard',10,0
disconnectmsgm db 'K : USB mouse disconnected',10,0
disconnectmsgk db 'K : USB keyboard disconnected',10,0
 
; data for keyboard: correspondence between HID usage keys and PS/2 scancodes.
EX = 80h
label control_keys byte
db 1Dh, 2Ah, 38h, 5Bh+EX, 1Dh+EX, 36h, 38h+EX, 5Ch+EX
label normal_keys byte
db 00h, 00h, 00h, 00h, 1Eh, 30h, 2Eh, 20h, 12h, 21h, 22h, 23h, 17h, 24h, 25h, 26h ; 0x
db 32h, 31h, 18h, 19h, 10h, 13h, 1Fh, 14h, 16h, 2Fh, 11h, 2Dh, 15h, 2Ch, 02h, 03h ; 1x
db 04h, 05h, 06h, 07h, 08h, 09h, 0Ah, 0Bh, 1Ch, 01h, 0Eh, 0Fh, 39h, 0Ch, 0Dh, 1Ah ; 2x
db 1Bh, 2Bh, 2Bh, 27h, 28h, 29h, 33h, 34h, 35h, 3Ah, 3Bh, 3Ch, 3Dh, 3Eh, 3Fh, 40h ; 3x
db 41h, 42h, 43h, 44h, 57h, 58h,37h+EX,46h,0,52h+EX,47h+EX,49h+EX,53h+EX,4Fh+EX,51h+EX,4Dh+EX ; 4x
db 4Bh+EX,50h+EX,48h+EX,45h,35h+EX,37h,4Ah,4Eh,1Ch+EX,4Fh,50h,51h,4Bh,4Ch,4Dh,47h ; 5x
db 48h, 49h, 52h, 53h, 56h,5Dh+EX,5Eh+EX,59h,64h,65h,66h, 67h, 68h, 69h, 6Ah, 6Bh ; 6x
db 6Ch, 6Dh, 6Eh, 76h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h, 00h ; 7x
db 00h, 00h, 00h, 00h, 00h, 7Eh, 00h, 73h, 70h, 7Dh, 79h, 7Bh, 5Ch, 00h, 00h, 00h ; 8x
db 0F2h,0F1h,78h, 77h, 76h
normal_keys_number = $ - normal_keys
 
; Exported variable: kernel API version.
align 4
version dd 50005h
; Structure with callback functions.
usb_functions:
dd 12
dd AddDevice
dd DeviceDisconnected
 
; Structure with callback functions for keyboards.
usbkbd_functions:
dd 12
dd CloseKeyboard
dd SetKeyboardLights
 
; for DEBUGF macro
include_debug_strings
 
; for uninitialized data
section '.data' data readable writable align 16
/kernel/branches/Kolibri-acpi/drivers/usbstor.asm
0,0 → 1,1609
; standard driver stuff
format MS COFF
 
DEBUG = 1
DUMP_PACKETS = 0
 
; this is for DEBUGF macro from 'fdo.inc'
__DEBUG__ = 1
__DEBUG_LEVEL__ = 1
 
include 'proc32.inc'
include 'imports.inc'
include 'fdo.inc'
 
public START
public version
 
; USB constants
DEVICE_DESCR_TYPE = 1
CONFIG_DESCR_TYPE = 2
STRING_DESCR_TYPE = 3
INTERFACE_DESCR_TYPE = 4
ENDPOINT_DESCR_TYPE = 5
DEVICE_QUALIFIER_DESCR_TYPE = 6
 
CONTROL_PIPE = 0
ISOCHRONOUS_PIPE = 1
BULK_PIPE = 2
INTERRUPT_PIPE = 3
 
; USB structures
virtual at 0
config_descr:
.bLength db ?
.bDescriptorType db ?
.wTotalLength dw ?
.bNumInterfaces db ?
.bConfigurationValue db ?
.iConfiguration db ?
.bmAttributes db ?
.bMaxPower db ?
.sizeof:
end virtual
 
virtual at 0
interface_descr:
.bLength db ?
.bDescriptorType db ?
.bInterfaceNumber db ?
.bAlternateSetting db ?
.bNumEndpoints db ?
.bInterfaceClass db ?
.bInterfaceSubClass db ?
.bInterfaceProtocol db ?
.iInterface db ?
.sizeof:
end virtual
 
virtual at 0
endpoint_descr:
.bLength db ?
.bDescriptorType db ?
.bEndpointAddress db ?
.bmAttributes db ?
.wMaxPacketSize dw ?
.bInterval db ?
.sizeof:
end virtual
 
; Mass storage protocol constants, USB layer
REQUEST_GETMAXLUN = 0xFE ; get max lun
REQUEST_BORESET = 0xFF ; bulk-only reset
 
; Mass storage protocol structures, USB layer
; Sent from host to device in the first stage of an operation.
struc command_block_wrapper
{
.Signature dd ? ; the constant 'USBC'
.Tag dd ? ; identifies response with request
.Length dd ? ; length of data-transport phase
.Flags db ? ; one of CBW_FLAG_*
CBW_FLAG_OUT = 0
CBW_FLAG_IN = 80h
.LUN db ? ; addressed unit
.CommandLength db ? ; the length of the following field
.Command rb 16
.sizeof:
}
virtual at 0
command_block_wrapper command_block_wrapper
end virtual
 
; Sent from device to host in the last stage of an operation.
struc command_status_wrapper
{
.Signature dd ? ; the constant 'USBS'
.Tag dd ? ; identifies response with request
.LengthRest dd ? ; .Length - (size of data which were transferred)
.Status db ? ; one of CSW_STATUS_*
CSW_STATUS_OK = 0
CSW_STATUS_FAIL = 1
CSW_STATUS_FATAL = 2
.sizeof:
}
virtual at 0
command_status_wrapper command_status_wrapper
end virtual
 
; Constants of SCSI layer
SCSI_REQUEST_SENSE = 3
SCSI_INQUIRY = 12h
SCSI_READ_CAPACITY = 25h
SCSI_READ10 = 28h
SCSI_WRITE10 = 2Ah
 
; Result of SCSI REQUEST SENSE command.
SENSE_UNKNOWN = 0
SENSE_RECOVERED_ERROR = 1
SENSE_NOT_READY = 2
SENSE_MEDIUM_ERROR = 3
SENSE_HARDWARE_ERROR = 4
SENSE_ILLEGAL_REQUEST = 5
SENSE_UNIT_ATTENTION = 6
SENSE_DATA_PROTECT = 7
SENSE_BLANK_CHECK = 8
; 9 is vendor-specific
SENSE_COPY_ABORTED = 10
SENSE_ABORTED_COMMAND = 11
SENSE_EQUAL = 12
SENSE_VOLUME_OVERFLOW = 13
SENSE_MISCOMPARE = 14
; 15 is reserved
 
; Structures of SCSI layer
; Result of SCSI INQUIRY request.
struc inquiry_data
{
.PeripheralDevice db ? ; lower 5 bits are PeripheralDeviceType
; upper 3 bits are PeripheralQualifier
.RemovableMedium db ? ; upper bit is RemovableMedium
; other bits are for compatibility
.Version db ? ; lower 3 bits are ANSI-Approved version
; next 3 bits are ECMA version
; upper 2 bits are ISO version
.ResponseDataFormat db ? ; lower 4 bits are ResponseDataFormat
; bit 6 is TrmIOP
; bit 7 is AENC
.AdditionalLength db ?
dw ? ; reserved
.Flags db ?
.VendorID rb 8 ; vendor ID, big-endian
.ProductID rb 16 ; product ID, big-endian
.ProductRevBE dd ? ; product revision, big-endian
.sizeof:
}
virtual at 0
inquiry_data inquiry_data
end virtual
 
struc sense_data
{
.ErrorCode db ? ; lower 7 bits are error code:
; 70h = current error,
; 71h = deferred error
; upper bit is InformationValid
.SegmentNumber db ? ; number of segment descriptor
; for commands COPY [+VERIFY], COMPARE
.SenseKey db ? ; bits 0-3 are one of SENSE_*
; bit 4 is reserved
; bit 5 is IncorrectLengthIndicator
; bits 6 and 7 are used by
; sequential-access devices
.Information dd ? ; command-specific
.AdditionalLength db ? ; length of data starting here
.CommandInformation dd ? ; command-specific
.AdditionalSenseCode db ? ; \ more detailed error code
.AdditionalSenseQual db ? ; / standard has a large table of them
.FRUCode db ? ; which part of device has failed
; (device-specific, not regulated)
.SenseKeySpecific rb 3 ; depends on SenseKey
.sizeof:
}
virtual at 0
sense_data sense_data
end virtual
 
; Device data
; USB Mass storage device has one or more logical units, identified by LUN,
; logical unit number. The highest value of LUN, that is, number of units
; minus 1, can be obtained via control request Get Max LUN.
virtual at 0
usb_device_data:
.ConfigPipe dd ? ; configuration pipe
.OutPipe dd ? ; pipe for OUT bulk endpoint
.InPipe dd ? ; pipe for IN bulk endpoint
.MaxLUN dd ? ; maximum Logical Unit Number
.LogicalDevices dd ? ; pointer to array of usb_unit_data
; 1 for a connected USB device, 1 for each disk device
; the structure can be freed when .NumReferences decreases to zero
.NumReferences dd ? ; number of references
.ConfigRequest rb 8 ; buffer for configuration requests
.LengthRest dd ? ; Length - (size of data which were transferred)
; All requests to a given device are serialized,
; only one request to a given device can be processed at a time.
; The current request and all pending requests are organized in the following
; queue, the head being the current request.
; NB: the queue must be device-wide due to the protocol:
; data stage is not tagged (unlike command_*_wrapper), so the only way to know
; what request the data are associated with is to guarantee that only one
; request is processing at the time.
.RequestsQueue rd 2
.QueueLock rd 3 ; protects .RequestsQueue
.InquiryData inquiry_data ; information about device
; data for the current request
.Command command_block_wrapper
.DeviceDisconnected db ?
.Status command_status_wrapper
.Sense sense_data
.sizeof:
end virtual
 
; Information about one logical device.
virtual at 0
usb_unit_data:
.Parent dd ? ; pointer to parent usb_device_data
.LUN db ? ; index in usb_device_data.LogicalDevices array
.DiskIndex db ? ; for name "usbhd<index>"
.MediaPresent db ?
db ? ; alignment
.DiskDevice dd ? ; handle of disk device or NULL
.SectorSize dd ? ; sector size
; For some devices, the first request to the medium fails with 'unit not ready'.
; When the code sees this status, it retries the command several times.
; Two following variables track the retry count and total time for those;
; total time is currently used only for debug output.
.UnitReadyAttempts dd ?
.TimerTicks dd ?
.sizeof:
end virtual
 
; This is the structure for items in the queue usb_device_data.RequestsQueue.
virtual at 0
request_queue_item:
.Next dd ? ; next item in the queue
.Prev dd ? ; prev item in the queue
.ReqBuilder dd ? ; procedure to fill command_block_wrapper
.Buffer dd ? ; input or output data
; (length is command_block_wrapper.Length)
.Callback dd ? ; procedure to call in the end of transfer
.UserData dd ? ; passed as-is to .Callback
; There are 3 possible stages of any request, one of them optional:
; command stage (host sends command_block_wrapper to device),
; optional data stage,
; status stage (device sends command_status_wrapper to host).
; Also, if a request fails, the code queues additional request
; SCSI_REQUEST_SENSE; sense_data from SCSI_REQUEST_SENSE
; contains some information about the error.
.Stage db ?
.sizeof:
end virtual
 
section '.flat' code readable align 16
; The start procedure.
proc START
virtual at esp
dd ? ; return address
.reason dd ? ; DRV_ENTRY or DRV_EXIT
end virtual
; 1. Test whether the procedure is called with the argument DRV_ENTRY.
; If not, return 0.
xor eax, eax ; initialize return value
cmp [.reason], 1 ; compare the argument
jnz .nothing
; 2. Initialize: we have one global mutex.
mov ecx, free_numbers_lock
call MutexInit
; 3. Register self as a USB driver.
; The name is my_driver = 'usbstor'; IOCTL interface is not supported;
; usb_functions is an offset of a structure with callback functions.
stdcall RegUSBDriver, my_driver, 0, usb_functions
; 4. Return the returned value of RegUSBDriver.
.nothing:
ret 4
endp
 
; Helper procedures to work with requests queue.
 
; Add a request to the queue. Stdcall with 5 arguments.
proc queue_request
push ebx esi
virtual at esp
rd 2 ; saved registers
dd ? ; return address
.device dd ? ; pointer to usb_device_data
.ReqBuilder dd ? ; request_queue_item.ReqBuilder
.Buffer dd ? ; request_queue_item.Buffer
.Callback dd ? ; request_queue_item.Callback
.UserData dd ? ; request_queue_item.UserData
end virtual
; 1. Allocate the memory for the request description.
push request_queue_item.sizeof
pop eax
call Kmalloc
test eax, eax
jnz @f
mov esi, nomemory
call SysMsgBoardStr
pop esi ebx
ret 20
@@:
; 2. Fill user-provided parts of the request description.
push edi
xchg eax, ebx
lea esi, [.ReqBuilder+4]
lea edi, [ebx+request_queue_item.ReqBuilder]
movsd ; ReqBuilder
movsd ; Buffer
movsd ; Callback
movsd ; UserData
pop edi
; 3. Set stage to zero: not started.
mov [ebx+request_queue_item.Stage], 0
; 4. Lock the queue.
mov esi, [.device]
lea ecx, [esi+usb_device_data.QueueLock]
call MutexLock
; 5. Insert the request to the tail of the queue.
add esi, usb_device_data.RequestsQueue
mov edx, [esi+request_queue_item.Prev]
mov [ebx+request_queue_item.Next], esi
mov [ebx+request_queue_item.Prev], edx
mov [edx+request_queue_item.Next], ebx
mov [esi+request_queue_item.Prev], ebx
; 6. Test whether the queue was empty
; and the request should be started immediately.
cmp [esi+request_queue_item.Next], ebx
jnz .unlock
; 8. If the step 6 shows that the request is the first in the queue,
; start it.
sub esi, usb_device_data.RequestsQueue
call setup_request
jmp .nothing
.unlock:
call MutexUnlock
; 9. Return.
.nothing:
pop esi ebx
ret 20
endp
 
; The current request is completed. Call the callback,
; remove the request from the queue, start the next
; request if there is one.
; esi points to usb_device_data
proc complete_request
; 1. Print common debug messages on fails.
if DEBUG
cmp [esi+usb_device_data.Status.Status], CSW_STATUS_FAIL
jb .normal
jz .fail
DEBUGF 1, 'K : Fatal error during execution of command %x\n', [esi+usb_device_data.Command.Command]:2
jmp .normal
.fail:
DEBUGF 1, 'K : Command %x failed\n', [esi+usb_device_data.Command.Command]:2
.normal:
end if
; 2. Get the current request.
mov ebx, [esi+usb_device_data.RequestsQueue+request_queue_item.Next]
; 3. Call the callback.
stdcall [ebx+request_queue_item.Callback], esi, [ebx+request_queue_item.UserData]
; 4. Lock the queue.
lea ecx, [esi+usb_device_data.QueueLock]
call MutexLock
; 5. Remove the request.
lea edx, [esi+usb_device_data.RequestsQueue]
mov eax, [ebx+request_queue_item.Next]
mov [eax+request_queue_item.Prev], edx
mov [edx+request_queue_item.Next], eax
; 6. Free the request memory.
push eax edx
xchg eax, ebx
call Kfree
pop edx ebx
; 7. If there is a next request, start processing.
cmp ebx, edx
jnz setup_request
; 8. Unlock the queue and return.
lea ecx, [esi+usb_device_data.QueueLock]
call MutexUnlock
ret
endp
 
; Start processing the request. Called either by queue_request
; or when the previous request has been processed.
; Do not call directly, use queue_request.
; Must be called when queue is locked; unlocks the queue when returns.
proc setup_request
xor eax, eax
; 1. If DeviceDisconnected has been run, then all handles of pipes
; are invalid, so we must fail immediately.
; (That is why this function needs the locked queue: this
; guarantee that either DeviceDisconnected has been already run, or
; DeviceDisconnected will not return before the queue is unlocked.)
cmp [esi+usb_device_data.DeviceDisconnected], al
jnz .fatal
; 2. If the previous command has encountered a fatal error,
; perform reset recovery.
cmp [esi+usb_device_data.Status.Status], CSW_STATUS_FATAL
jb .norecovery
; 2a. Send Bulk-Only Mass Storage Reset command to config pipe.
lea edx, [esi+usb_device_data.ConfigRequest]
mov word [edx], (REQUEST_BORESET shl 8) + 21h ; class request
mov word [edx+6], ax ; length = 0
stdcall USBControlTransferAsync, [esi+usb_device_data.ConfigPipe], edx, eax, eax, recovery_callback1, esi, eax
; 2b. Fail here = fatal error.
test eax, eax
jz .fatal
; 2c. Otherwise, unlock the queue and return. recovery_callback1 will continue processing.
.unlock_return:
lea ecx, [esi+usb_device_data.QueueLock]
call MutexUnlock
ret
.norecovery:
; 3. Send the command. Fail (no memory or device disconnected) = fatal error.
; Otherwise, go to 2c.
call request_stage1
test eax, eax
jnz .unlock_return
.fatal:
; 4. Fatal error. Set status = FATAL, unlock the queue, complete the request.
mov [esi+usb_device_data.Status.Status], CSW_STATUS_FATAL
lea ecx, [esi+usb_device_data.QueueLock]
call MutexUnlock
jmp complete_request
endp
 
; Initiate USB transfer for the first stage of a request (send command).
proc request_stage1
mov ebx, [esi+usb_device_data.RequestsQueue+request_queue_item.Next]
; 1. Set the stage to 1 = command stage.
inc [ebx+request_queue_item.Stage]
; 2. Generate the command. Zero-initialize and use the caller-provided proc.
lea edx, [esi+usb_device_data.Command]
xor eax, eax
mov [edx+command_block_wrapper.CommandLength], 12
mov dword [edx+command_block_wrapper.Command], eax
mov dword [edx+command_block_wrapper.Command+4], eax
mov dword [edx+command_block_wrapper.Command+8], eax
mov dword [edx+command_block_wrapper.Command+12], eax
inc [edx+command_block_wrapper.Tag]
stdcall [ebx+request_queue_item.ReqBuilder], edx, [ebx+request_queue_item.UserData]
; 4. Initiate USB transfer.
lea edx, [esi+usb_device_data.Command]
if DUMP_PACKETS
DEBUGF 1,'K : USBSTOR out:'
mov eax, edx
mov ecx, command_block_wrapper.sizeof
call debug_dump
DEBUGF 1,'\n'
end if
stdcall USBNormalTransferAsync, [esi+usb_device_data.OutPipe], edx, command_block_wrapper.sizeof, request_callback1, esi, 0
ret
endp
 
if DUMP_PACKETS
proc debug_dump
test ecx, ecx
jz .done
.loop:
test ecx, 0Fh
jnz @f
DEBUGF 1,'\nK :'
@@:
DEBUGF 1,' %x',[eax]:2
inc eax
dec ecx
jnz .loop
.done:
ret
endp
end if
 
; Called when the Reset command is completed,
; either successfully or not.
proc recovery_callback1
virtual at esp
dd ? ; return address
.pipe dd ?
.status dd ?
.buffer dd ?
.length dd ?
.calldata dd ?
end virtual
cmp [.status], 0
jnz .error
; todo: reset pipes
push ebx esi
mov esi, [.calldata+8]
call request_stage1
pop esi ebx
test eax, eax
jz .error
ret 20
.error:
DEBUGF 1, 'K : error %d while resetting', [.status]
jmp request_callback1.common_error
endp
 
; Called when the first stage of request is completed,
; either successfully or not.
proc request_callback1
virtual at esp
dd ? ; return address
.pipe dd ?
.status dd ?
.buffer dd ?
.length dd ?
.calldata dd ?
end virtual
; 1. Initialize.
mov ecx, [.calldata]
mov eax, [.status]
; 2. Test for error.
test eax, eax
jnz .error
; No error.
; 3. Increment the stage.
mov edx, [ecx+usb_device_data.RequestsQueue+request_queue_item.Next]
inc [edx+request_queue_item.Stage]
; 4. If there is no data, skip this stage.
cmp [ecx+usb_device_data.Command.Length], 0
jz ..request_get_status
; 5. Initiate USB transfer. If this fails, go to the error handler.
mov eax, [ecx+usb_device_data.InPipe]
cmp [ecx+usb_device_data.Command.Flags], 0
js @f
mov eax, [ecx+usb_device_data.OutPipe]
if DUMP_PACKETS
DEBUGF 1,'K : USBSTOR out:'
push eax ecx
mov eax, [edx+request_queue_item.Buffer]
mov ecx, [ecx+usb_device_data.Command.Length]
call debug_dump
pop ecx eax
DEBUGF 1,'\n'
end if
@@:
stdcall USBNormalTransferAsync, eax, [edx+request_queue_item.Buffer], [ecx+usb_device_data.Command.Length], request_callback2, ecx, 0
test eax, eax
jz .error
; 6. Return.
ret 20
.error:
; Error.
; 7. Print debug message and complete the request as failed.
DEBUGF 1,'K : error %d after %d bytes in request stage\n',eax,[.length]
.common_error:
; TODO: add recovery after STALL
mov ecx, [.calldata]
mov [ecx+usb_device_data.Status.Status], CSW_STATUS_FATAL
push ebx esi
mov esi, ecx
call complete_request
pop esi ebx
ret 20
endp
 
; Called when the second stage of request is completed,
; either successfully or not.
proc request_callback2
virtual at esp
dd ? ; return address
.pipe dd ?
.status dd ?
.buffer dd ?
.length dd ?
.calldata dd ?
end virtual
if DUMP_PACKETS
mov eax, [.calldata]
mov eax, [eax+usb_device_data.InPipe]
cmp [.pipe], eax
jnz @f
DEBUGF 1,'K : USBSTOR in:'
push eax ecx
mov eax, [.buffer+8]
mov ecx, [.length+8]
call debug_dump
pop ecx eax
DEBUGF 1,'\n'
@@:
end if
; 1. Initialize.
mov ecx, [.calldata]
mov eax, [.status]
; 2. Test for error.
test eax, eax
jnz .error
; No error.
..request_get_status:
; 3. Increment the stage.
mov edx, [ecx+usb_device_data.RequestsQueue+request_queue_item.Next]
inc [edx+request_queue_item.Stage]
; 4. Initiate USB transfer. If this fails, go to the error handler.
lea edx, [ecx+usb_device_data.Status]
stdcall USBNormalTransferAsync, [ecx+usb_device_data.InPipe], edx, command_status_wrapper.sizeof, request_callback3, ecx, 0
test eax, eax
jz .error
ret 20
.error:
; Error.
; 7. Print debug message and complete the request as failed.
DEBUGF 1,'K : error %d after %d bytes in data stage\n',eax,[.length]
jmp request_callback1.common_error
endp
 
; Called when the third stage of request is completed,
; either successfully or not.
proc request_callback3
virtual at esp
dd ? ; return address
.pipe dd ?
.status dd ?
.buffer dd ?
.length dd ?
.calldata dd ?
end virtual
if DUMP_PACKETS
DEBUGF 1,'K : USBSTOR in:'
mov eax, [.buffer]
mov ecx, [.length]
call debug_dump
DEBUGF 1,'\n'
end if
; 1. Initialize.
mov eax, [.status]
; 2. Test for error.
test eax, eax
jnz .transfer_error
; Transfer is OK.
; 3. Validate the status. Invalid status = fatal error.
push ebx esi
mov esi, [.calldata+8]
mov ebx, [esi+usb_device_data.RequestsQueue+request_queue_item.Next]
cmp [esi+usb_device_data.Status.Signature], 'USBS'
jnz .invalid
mov eax, [esi+usb_device_data.Command.Tag]
cmp [esi+usb_device_data.Status.Tag], eax
jnz .invalid
cmp [esi+usb_device_data.Status.Status], CSW_STATUS_FATAL
ja .invalid
; 4. The status block is valid. Check the status code.
jz .complete
; 5. If this command was not REQUEST_SENSE, copy status data to safe place.
; Otherwise, the original command has failed, so restore the fail status.
cmp byte [esi+usb_device_data.Command.Command], SCSI_REQUEST_SENSE
jz .request_sense
mov eax, [esi+usb_device_data.Status.LengthRest]
mov [esi+usb_device_data.LengthRest], eax
cmp [esi+usb_device_data.Status.Status], CSW_STATUS_FAIL
jz .fail
.complete:
call complete_request
.nothing:
pop esi ebx
ret 20
.request_sense:
mov [esi+usb_device_data.Status.Status], CSW_STATUS_FAIL
jmp .complete
.invalid:
; 6. Invalid status block. Say error, set status to fatal and complete request.
push esi
mov esi, invresponse
call SysMsgBoardStr
pop esi
mov [esi+usb_device_data.Status.Status], CSW_STATUS_FATAL
jmp .complete
.fail:
; 7. The command has failed.
; If this command was not REQUEST_SENSE, schedule the REQUEST_SENSE command
; to determine the reason of fail. Otherwise, assume that there is no error data.
cmp [esi+usb_device_data.Command.Command], SCSI_REQUEST_SENSE
jz .fail_request_sense
mov [ebx+request_queue_item.ReqBuilder], request_sense_req
lea eax, [esi+usb_device_data.Sense]
mov [ebx+request_queue_item.Buffer], eax
call request_stage1
test eax, eax
jnz .nothing
.fail_request_sense:
DEBUGF 1,'K : fail during REQUEST SENSE\n'
mov byte [esi+usb_device_data.Sense], 0
jmp .complete
.transfer_error:
; TODO: add recovery after STALL
DEBUGF 1,'K : error %d after %d bytes in status stage\n',eax,[.length]
jmp request_callback1.common_error
endp
 
; Builder for SCSI_REQUEST_SENSE request.
; edx = first argument = pointer to usb_device_data.Command,
; second argument = custom data given to queue_request (ignored).
proc request_sense_req
mov [edx+command_block_wrapper.Length], sense_data.sizeof
mov [edx+command_block_wrapper.Flags], CBW_FLAG_IN
mov byte [edx+command_block_wrapper.Command+0], SCSI_REQUEST_SENSE
mov byte [edx+command_block_wrapper.Command+4], sense_data.sizeof
ret 8
endp
 
; This procedure is called when new mass-storage device is detected.
; It initializes the device.
; Technically, initialization implies sending several USB queries,
; so it is split in several procedures. The first is AddDevice,
; other are callbacks which will be called at some time in the future,
; when the device will respond.
; The general scheme:
; * AddDevice parses descriptors, opens pipes; if everything is ok,
; AddDevice sends REQUEST_GETMAXLUN with callback known_lun_callback;
; * known_lun_callback allocates memory for LogicalDevices and sends
; SCSI_TEST_UNIT_READY to all logical devices with test_unit_ready_callback;
; * test_unit_ready_callback checks whether the unit is ready;
; if not, it repeats the same request several times;
; if ok or there were too many attempts, it sends SCSI_INQUIRY with
; callback inquiry_callback;
; * inquiry_callback checks that a logical device is a block device
; and the unit was ready; if so, it notifies the kernel about new disk device.
proc AddDevice
push ebx esi
virtual at esp
rd 2 ; saved registers ebx, esi
dd ? ; return address
.pipe0 dd ? ; handle of the config pipe
.config dd ? ; pointer to config_descr
.interface dd ? ; pointer to interface_descr
end virtual
; 1. Check device type. Currently only SCSI-command-set Bulk-only devices
; are supported.
; 1a. Get the subclass and the protocol. Since bInterfaceSubClass and
; bInterfaceProtocol are subsequent in interface_descr, just one
; memory reference is used for both.
mov esi, [.interface]
xor ebx, ebx
mov cx, word [esi+interface_descr.bInterfaceSubClass]
; 1b. For Mass-storage SCSI-command-set Bulk-only devices subclass must be 6
; and protocol must be 50h. Check.
cmp cx, 0x5006
jz .known
; There are devices with subclass 5 which use the same protocol 50h.
; The difference is not important for the code except for this test,
; so allow them to proceed also.
cmp cx, 0x5005
jz .known
; 1c. If the device is unknown, print a message and go to 11c.
mov esi, unkdevice
call SysMsgBoardStr
jmp .nothing
; 1d. If the device uses known command set, print a message and continue
; configuring.
.known:
push esi
mov esi, okdevice
call SysMsgBoardStr
pop esi
; 2. Allocate memory for internal device data.
; 2a. Call the kernel.
mov eax, usb_device_data.sizeof
call Kmalloc
; 2b. Check return value.
test eax, eax
jnz @f
; 2c. If failed, say a message and go to 11c.
mov esi, nomemory
call SysMsgBoardStr
jmp .nothing
@@:
; 2d. If succeeded, zero the contents and continue configuring.
xchg ebx, eax ; ebx will point to usb_device_data
xor eax, eax
mov [ebx+usb_device_data.OutPipe], eax
mov [ebx+usb_device_data.InPipe], eax
mov [ebx+usb_device_data.MaxLUN], eax
mov [ebx+usb_device_data.LogicalDevices], eax
mov dword [ebx+usb_device_data.ConfigRequest], eax
mov dword [ebx+usb_device_data.ConfigRequest+4], eax
mov [ebx+usb_device_data.Status.Status], al
mov [ebx+usb_device_data.DeviceDisconnected], al
; 2e. There is one reference: a connected USB device.
inc eax
mov [ebx+usb_device_data.NumReferences], eax
; 2f. Save handle of configuration pipe for reset recovery.
mov eax, [.pipe0]
mov [ebx+usb_device_data.ConfigPipe], eax
; 2g. Save the interface number for configuration requests.
mov al, [esi+interface_descr.bInterfaceNumber]
mov [ebx+usb_device_data.ConfigRequest+4], al
; 2h. Initialize common fields in command wrapper.
mov [ebx+usb_device_data.Command.Signature], 'USBC'
mov [ebx+usb_device_data.Command.Tag], 'xxxx'
; 2i. Initialize requests queue.
lea eax, [ebx+usb_device_data.RequestsQueue]
mov [eax+request_queue_item.Next], eax
mov [eax+request_queue_item.Prev], eax
lea ecx, [ebx+usb_device_data.QueueLock]
call MutexInit
; Bulk-only mass storage devices use one OUT bulk endpoint for sending
; command/data and one IN bulk endpoint for receiving data/status.
; Look for those endpoints.
; 3. Get the upper bound of all descriptors' data.
mov edx, [.config] ; configuration descriptor
movzx ecx, [edx+config_descr.wTotalLength]
add edx, ecx
; 4. Loop over all descriptors until
; either end-of-data reached - this is fail
; or interface descriptor found - this is fail, all further data
; correspond to that interface
; or both endpoint descriptors found.
; 4a. Loop start: esi points to the interface descriptor,
.lookep:
; 4b. Get next descriptor.
movzx ecx, byte [esi] ; the first byte of all descriptors is length
add esi, ecx
; 4c. Check that at least two bytes are readable. The opposite is an error.
inc esi
cmp esi, edx
jae .errorep
dec esi
; 4d. Check that this descriptor is not interface descriptor. The opposite is
; an error.
cmp byte [esi+endpoint_descr.bDescriptorType], INTERFACE_DESCR_TYPE
jz .errorep
; 4e. Test whether this descriptor is an endpoint descriptor. If not, continue
; the loop.
cmp byte [esi+endpoint_descr.bDescriptorType], ENDPOINT_DESCR_TYPE
jnz .lookep
; 5. Check that the descriptor contains all required data and all data are
; readable. The opposite is an error.
cmp byte [esi+endpoint_descr.bLength], endpoint_descr.sizeof
jb .errorep
lea ecx, [esi+endpoint_descr.sizeof]
cmp ecx, edx
ja .errorep
; 6. Check that the endpoint is bulk endpoint. The opposite is an error.
mov cl, [esi+endpoint_descr.bmAttributes]
and cl, 3
cmp cl, BULK_PIPE
jnz .errorep
; 7. Get the direction of this endpoint.
movzx ecx, [esi+endpoint_descr.bEndpointAddress]
shr ecx, 7
; 8. Test whether a pipe for this direction is already opened. If so, continue
; the loop.
cmp [ebx+usb_device_data.OutPipe+ecx*4], 0
jnz .lookep
; 9. Open pipe for this endpoint.
; 9a. Save registers.
push ecx edx
; 9b. Load parameters from the descriptor.
movzx ecx, [esi+endpoint_descr.bEndpointAddress]
movzx edx, [esi+endpoint_descr.wMaxPacketSize]
movzx eax, [esi+endpoint_descr.bInterval] ; not used for USB1, may be important for USB2
; 9c. Call the kernel.
stdcall USBOpenPipe, [ebx+usb_device_data.ConfigPipe], ecx, edx, BULK_PIPE, eax
; 9d. Restore registers.
pop edx ecx
; 9e. Check result. If failed, go to 11b.
test eax, eax
jz .free
; 9f. Save result.
mov [ebx+usb_device_data.OutPipe+ecx*4], eax
; 10. Test whether the second pipe is already opened. If not, continue loop.
xor ecx, 1
cmp [ebx+usb_device_data.OutPipe+ecx*4], 0
jz .lookep
jmp .created
; 11. An error occured during processing endpoint descriptor.
.errorep:
; 11a. Print a message.
DEBUGF 1,'K : error: invalid endpoint descriptor\n'
.free:
; 11b. Free the allocated usb_device_data.
xchg eax, ebx
call Kfree
.nothing:
; 11c. Return an error.
xor eax, eax
jmp .return
.created:
; 12. Pipes are opened. Send GetMaxLUN control request.
lea eax, [ebx+usb_device_data.ConfigRequest]
mov byte [eax], 0A1h ; class request from interface
mov byte [eax+1], REQUEST_GETMAXLUN
mov byte [eax+6], 1 ; transfer 1 byte
lea ecx, [ebx+usb_device_data.MaxLUN]
if DUMP_PACKETS
DEBUGF 1,'K : GETMAXLUN: %x %x %x %x %x %x %x %x\n',[eax]:2,[eax+1]:2,[eax+2]:2,[eax+3]:2,[eax+4]:2,[eax+5]:2,[eax+6]:2,[eax+7]:2
end if
stdcall USBControlTransferAsync, [ebx+usb_device_data.ConfigPipe], eax, ecx, 1, known_lun_callback, ebx, 0
; 13. Return with pointer to device data as returned value.
xchg eax, ebx
.return:
pop esi ebx
ret 12
endp
 
; This function is called when REQUEST_GETMAXLUN is done,
; either successful or unsuccessful.
proc known_lun_callback
push ebx esi
virtual at esp
rd 2 ; saved registers
dd ? ; return address
.pipe dd ?
.status dd ?
.buffer dd ?
.length dd ?
.calldata dd ?
end virtual
; 1. Check the status. If the request failed, assume that MaxLUN is zero.
mov ebx, [.calldata]
mov eax, [.status]
test eax, eax
jz @f
DEBUGF 1, 'K : GETMAXLUN failed with status %d, assuming zero\n', eax
mov [ebx+usb_device_data.MaxLUN], 0
@@:
; 2. Allocate the memory for logical devices.
mov eax, [ebx+usb_device_data.MaxLUN]
inc eax
DEBUGF 1,'K : %d logical unit(s)\n',eax
imul eax, usb_unit_data.sizeof
push ebx
call Kmalloc
pop ebx
; If failed, print a message and do nothing.
test eax, eax
jnz @f
mov esi, nomemory
call SysMsgBoardStr
pop esi ebx
ret 20
@@:
mov [ebx+usb_device_data.LogicalDevices], eax
; 3. Initialize logical devices and initiate TEST_UNIT_READY request.
xchg esi, eax
xor ecx, ecx
.looplun:
mov [esi+usb_unit_data.Parent], ebx
mov [esi+usb_unit_data.LUN], cl
xor eax, eax
mov [esi+usb_unit_data.MediaPresent], al
mov [esi+usb_unit_data.DiskDevice], eax
mov [esi+usb_unit_data.SectorSize], eax
mov [esi+usb_unit_data.UnitReadyAttempts], eax
push ecx
call GetTimerTicks
mov [esi+usb_unit_data.TimerTicks], eax
stdcall queue_request, ebx, test_unit_ready_req, 0, test_unit_ready_callback, esi
pop ecx
inc ecx
add esi, usb_unit_data.sizeof
cmp ecx, [ebx+usb_device_data.MaxLUN]
jbe .looplun
; 4. Return.
pop esi ebx
ret 20
endp
 
; Builder for SCSI INQUIRY request.
; edx = first argument = pointer to usb_device_data.Command,
; second argument = custom data given to queue_request.
proc inquiry_req
mov eax, [esp+8]
mov al, [eax+usb_unit_data.LUN]
mov [edx+command_block_wrapper.Length], inquiry_data.sizeof
mov [edx+command_block_wrapper.Flags], CBW_FLAG_IN
mov [edx+command_block_wrapper.LUN], al
mov byte [edx+command_block_wrapper.Command+0], SCSI_INQUIRY
mov byte [edx+command_block_wrapper.Command+4], inquiry_data.sizeof
ret 8
endp
 
; Called when SCSI INQUIRY request is completed.
proc inquiry_callback
; 1. Check the status.
mov ecx, [esp+4]
cmp [ecx+usb_device_data.Status.Status], CSW_STATUS_OK
jnz .fail
; 2. The command has completed successfully.
; Print a message showing device type, ignore anything but block devices.
mov al, [ecx+usb_device_data.InquiryData.PeripheralDevice]
and al, 1Fh
DEBUGF 1,'K : peripheral device type is %x\n',al
test al, al
jnz .nothing
DEBUGF 1,'K : direct-access mass storage device detected\n'
; 3. We have found a new disk device. Increment number of references.
lock inc [ecx+usb_device_data.NumReferences]
; Unfortunately, we are now in the context of the USB thread,
; so we can't notify the kernel immediately: it would try to do something
; with a new disk, those actions would be synchronous and would require
; waiting for results of USB requests, but we need to exit this callback
; to allow the USB thread to continue working and handling those requests.
; 4. Thus, create a temporary kernel thread which would do it.
mov edx, [esp+8]
push ebx ecx
push 51
pop eax
push 1
pop ebx
mov ecx, new_disk_thread
; edx = parameter
int 0x40
pop ecx ebx
cmp eax, -1
jnz .nothing
; on error, reverse step 3
lock dec [ecx+usb_device_data.NumReferences]
.nothing:
ret 8
.fail:
; 4. The command has failed. Print a message and do nothing.
push esi
mov esi, inquiry_fail
call SysMsgBoardStr
pop esi
ret 8
endp
 
; Builder for SCSI TEST_UNIT_READY request.
; edx = first argument = pointer to usb_device_data.Command,
; second argument = custom data given to queue_request.
proc test_unit_ready_req
mov eax, [esp+8]
mov al, [eax+usb_unit_data.LUN]
mov [edx+command_block_wrapper.Length], 0
mov [edx+command_block_wrapper.Flags], CBW_FLAG_IN
mov [edx+command_block_wrapper.LUN], al
ret 8
endp
 
; Called when SCSI TEST_UNIT_READY request is completed.
proc test_unit_ready_callback
virtual at esp
dd ? ; return address
.device dd ?
.calldata dd ?
end virtual
; 1. Check the status.
mov ecx, [.device]
mov edx, [.calldata]
cmp [ecx+usb_device_data.Status.Status], CSW_STATUS_OK
jnz .fail
; 2. The command has completed successfully,
; possibly after some repetitions. Print a debug message showing
; number and time of those. Remember that media is ready and go to 4.
DEBUGF 1,'K : media is ready\n'
call GetTimerTicks
sub eax, [edx+usb_unit_data.TimerTicks]
DEBUGF 1,'K : %d attempts, %d ticks\n',[edx+usb_unit_data.UnitReadyAttempts],eax
inc [edx+usb_unit_data.MediaPresent]
jmp .inquiry
.fail:
; 3. The command has failed.
; Retry the same request up to 3 times with 10ms delay;
; if limit of retries is not reached, exit from the function.
; Otherwise, go to 4.
inc [edx+usb_unit_data.UnitReadyAttempts]
cmp [edx+usb_unit_data.UnitReadyAttempts], 3
jz @f
push ecx edx esi
push 10
pop esi
call Sleep
pop esi edx ecx
stdcall queue_request, ecx, test_unit_ready_req, 0, test_unit_ready_callback, edx
ret 8
@@:
DEBUGF 1,'K : media not ready\n'
.inquiry:
; 4. initiate INQUIRY request.
lea eax, [ecx+usb_device_data.InquiryData]
stdcall queue_request, ecx, inquiry_req, eax, inquiry_callback, edx
ret 8
endp
 
; Temporary thread for initial actions with a new disk device.
proc new_disk_thread
sub esp, 32
virtual at esp
.name rb 32 ; device name
.param dd ? ; contents of edx at the moment of int 0x40/eax=51
dd ? ; stack segment
end virtual
; We are ready to notify the kernel about a new disk device.
mov esi, [.param]
; 1. Generate name.
; 1a. Find a free index.
mov ecx, free_numbers_lock
call MutexLock
xor eax, eax
@@:
bsf edx, [free_numbers+eax]
jnz @f
add eax, 4
cmp eax, 4*4
jnz @b
call MutexUnlock
push esi
mov esi, noindex
call SysMsgBoardStr
pop esi
jmp .drop_reference
@@:
; 1b. Mark the index as busy.
btr [free_numbers+eax], edx
lea eax, [eax*8+edx]
push eax
call MutexUnlock
pop eax
; 1c. Generate a name of the form "usbhd<index>" in the stack.
mov dword [esp], 'usbh'
lea edi, [esp+5]
mov byte [edi-1], 'd'
push eax
push -'0'
push 10
pop ecx
@@:
cdq
div ecx
push edx
test eax, eax
jnz @b
@@:
pop eax
add al, '0'
stosb
jnz @b
pop ecx
mov edx, esp
; 3d. Store the index in usb_unit_data to free it later.
mov [esi+usb_unit_data.DiskIndex], cl
; 4. Notify the kernel about a new disk.
; 4a. Add a disk.
; stdcall queue_request, ecx, read_capacity_req, eax, read_capacity_callback, eax
stdcall DiskAdd, disk_functions, edx, esi, 0
mov ebx, eax
; 4b. If it failed, release the index and do nothing.
test eax, eax
jz .free_index
; 4c. Notify the kernel that a media is present.
stdcall DiskMediaChanged, eax, 1
; 5. Lock the requests queue, check that device is not disconnected,
; store the disk handle, unlock the requests queue.
mov ecx, [esi+usb_unit_data.Parent]
add ecx, usb_device_data.QueueLock
call MutexLock
cmp byte [ecx+usb_device_data.DeviceDisconnected-usb_device_data.QueueLock], 0
jnz .disconnected
mov [esi+usb_unit_data.DiskDevice], ebx
call MutexUnlock
jmp .exit
.disconnected:
call MutexUnlock
stdcall disk_close, ebx
jmp .exit
.free_index:
mov ecx, free_numbers_lock
call MutexLock
movzx eax, [esi+usb_unit_data.DiskIndex]
bts [free_numbers], eax
call MutexUnlock
.drop_reference:
mov esi, [esi+usb_unit_data.Parent]
lock dec [esi+usb_device_data.NumReferences]
jnz .exit
mov eax, [esi+usb_device_data.LogicalDevices]
call Kfree
xchg eax, esi
call Kfree
.exit:
or eax, -1
int 0x40
endp
 
; This function is called when the device is disconnected.
proc DeviceDisconnected
push ebx esi
virtual at esp
rd 2 ; saved registers
dd ? ; return address
.device dd ?
end virtual
; 1. Say a message.
mov esi, disconnectmsg
call SysMsgBoardStr
; 2. Lock the requests queue, set .DeviceDisconnected to 1,
; unlock the requests queue.
; Locking is required for synchronization with queue_request:
; all USB callbacks are executed in the same thread and are
; synchronized automatically, but queue_request can be running
; from any thread which wants to do something with a filesystem.
; Without locking, it would be possible that queue_request has
; been started, has checked that device is not yet disconnected,
; then DeviceDisconnected completes and all handles become invalid,
; then queue_request tries to use them.
mov esi, [.device]
lea ecx, [esi+usb_device_data.QueueLock]
call MutexLock
mov [esi+usb_device_data.DeviceDisconnected], 1
call MutexUnlock
; 3. Drop one reference to the structure and check whether
; that was the last reference.
lock dec [esi+usb_device_data.NumReferences]
jz .free
; 4. If not, there are some additional references due to disk devices;
; notify the kernel that those disks are deleted.
; Note that new disks cannot be added while we are looping here,
; because new_disk_thread checks for .DeviceDisconnected.
mov ebx, [esi+usb_device_data.MaxLUN]
mov esi, [esi+usb_device_data.LogicalDevices]
inc ebx
.diskdel:
mov eax, [esi+usb_unit_data.DiskDevice]
test eax, eax
jz @f
stdcall DiskDel, eax
@@:
add esi, usb_unit_data.sizeof
dec ebx
jnz .diskdel
; In this case, some operations with those disks are still possible,
; so we can't do anything more now. disk_close will take care of the rest.
.return:
pop esi ebx
ret 4
; 5. If there are no disk devices, free all resources which were allocated.
.free:
mov eax, [esi+usb_device_data.LogicalDevices]
test eax, eax
jz @f
call Kfree
@@:
xchg eax, esi
call Kfree
jmp .return
endp
 
; Disk functions.
DISK_STATUS_OK = 0 ; success
DISK_STATUS_GENERAL_ERROR = -1; if no other code is suitable
DISK_STATUS_INVALID_CALL = 1 ; invalid input parameters
DISK_STATUS_NO_MEDIA = 2 ; no media present
DISK_STATUS_END_OF_MEDIA = 3 ; end of media while reading/writing data
 
; Called when all operations with the given disk are done.
proc disk_close
push ebx esi
virtual at esp
rd 2 ; saved registers
dd ? ; return address
.userdata dd ?
end virtual
mov esi, [.userdata]
mov ecx, free_numbers_lock
call MutexLock
movzx eax, [esi+usb_unit_data.DiskIndex]
bts [free_numbers], eax
call MutexUnlock
mov esi, [esi+usb_unit_data.Parent]
lock dec [esi+usb_device_data.NumReferences]
jnz .nothing
mov eax, [esi+usb_device_data.LogicalDevices]
call Kfree
xchg eax, esi
call Kfree
.nothing:
pop esi ebx
ret 4
endp
 
; Returns sector size, capacity and flags of the media.
proc disk_querymedia stdcall uses ebx esi edi, \
userdata:dword, mediainfo:dword
; 1. Create event for waiting.
xor esi, esi
xor ecx, ecx
call CreateEvent
test eax, eax
jz .generic_fail
push eax
push edx
push ecx
push 0
push 0
virtual at ebp-.localsize
.locals:
; two following dwords are the output of READ_CAPACITY
.LastLBABE dd ?
.SectorSizeBE dd ?
.Status dd ?
; two following dwords identify an event
.event_code dd ?
.event dd ?
rd 3 ; saved registers
.localsize = $ - .locals
dd ? ; saved ebp
dd ? ; return address
.userdata dd ?
.mediainfo dd ?
end virtual
; 2. Initiate SCSI READ_CAPACITY request.
mov eax, [userdata]
mov ecx, [eax+usb_unit_data.Parent]
mov edx, esp
stdcall queue_request, ecx, read_capacity_req, edx, read_capacity_callback, edx
; 3. Wait for event. This destroys it.
mov eax, [.event]
mov ebx, [.event_code]
call WaitEvent
; 4. Get the status and results.
pop ecx
bswap ecx ; .LastLBA
pop edx
bswap edx ; .SectorSize
pop eax ; .Status
; 5. If the request has completed successfully, store results.
test eax, eax
jnz @f
DEBUGF 1,'K : sector size is %d, last sector is %d\n',edx,ecx
mov ebx, [mediainfo]
mov [ebx], eax ; flags = 0
mov [ebx+4], edx ; sectorsize
add ecx, 1
adc eax, 0
mov [ebx+8], ecx
mov [ebx+12], eax ; capacity
mov eax, [userdata]
mov [eax+usb_unit_data.SectorSize], edx
xor eax, eax
@@:
; 6. Restore the stack and return.
pop ecx
pop ecx
ret
.generic_fail:
or eax, -1
ret
endp
 
; Builder for SCSI READ_CAPACITY request.
; edx = first argument = pointer to usb_device_data.Command,
; second argument = custom data given to queue_request,
; pointer to disk_querymedia.locals.
proc read_capacity_req
mov eax, [esp+8]
mov eax, [eax+disk_querymedia.userdata-disk_querymedia.locals]
mov al, [eax+usb_unit_data.LUN]
mov [edx+command_block_wrapper.Length], 8
mov [edx+command_block_wrapper.Flags], CBW_FLAG_IN
mov [edx+command_block_wrapper.LUN], al
mov byte [edx+command_block_wrapper.Command+0], SCSI_READ_CAPACITY
ret 8
endp
 
; Called when SCSI READ_CAPACITY request is completed.
proc read_capacity_callback
; Transform the status to return value of disk_querymedia
; and set the event.
mov ecx, [esp+4]
xor eax, eax
cmp [ecx+usb_device_data.Status.Status], al
jz @f
or eax, -1
@@:
mov ecx, [esp+8]
mov [ecx+disk_querymedia.Status-disk_querymedia.locals], eax
push ebx esi edi
mov eax, [ecx+disk_querymedia.event-disk_querymedia.locals]
mov ebx, [ecx+disk_querymedia.event_code-disk_querymedia.locals]
xor edx, edx
xor esi, esi
call RaiseEvent
pop edi esi ebx
ret 8
endp
 
disk_write:
mov al, SCSI_WRITE10
jmp disk_read_write
 
disk_read:
mov al, SCSI_READ10
 
; Reads from the device or writes to the device.
proc disk_read_write stdcall uses ebx esi edi, \
userdata:dword, buffer:dword, startsector:qword, numsectors:dword
; 1. Initialize.
push eax ; .command
mov eax, [userdata]
mov eax, [eax+usb_unit_data.SectorSize]
push eax ; .SectorSize
push 0 ; .processed
mov eax, [numsectors]
mov eax, [eax]
; 2. The transfer length for SCSI_{READ,WRITE}10 commands can not be greater
; than 0xFFFF, so split the request to slices with <= 0xFFFF sectors.
max_sectors_at_time = 0xFFFF
.split:
push eax ; .length_rest
cmp eax, max_sectors_at_time
jb @f
mov eax, max_sectors_at_time
@@:
sub [esp], eax
push eax ; .length_cur
; 3. startsector must fit in 32 bits, otherwise abort the request.
cmp dword [startsector+4], 0
jnz .generic_fail
; 4. Create event for waiting.
xor esi, esi
xor ecx, ecx
call CreateEvent
test eax, eax
jz .generic_fail
push eax ; .event
push edx ; .event_code
push ecx ; .status
virtual at ebp-.localsize
.locals:
.status dd ?
.event_code dd ?
.event dd ?
.length_cur dd ?
.length_rest dd ?
.processed dd ?
.SectorSize dd ?
.command db ?
rb 3
rd 3 ; saved registers
.localsize = $ - .locals
dd ? ; saved ebp
dd ? ; return address
.userdata dd ?
.buffer dd ?
.startsector dq ?
.numsectors dd ?
end virtual
; 5. Initiate SCSI READ10 or WRITE10 request.
mov eax, [userdata]
mov ecx, [eax+usb_unit_data.Parent]
stdcall queue_request, ecx, read_write_req, [buffer], read_write_callback, esp
; 6. Wait for event. This destroys it.
mov eax, [.event]
mov ebx, [.event_code]
call WaitEvent
; 7. Get the status. If the operation has failed, abort.
pop eax ; .status
pop ecx ecx ; cleanup .event_code, .event
pop ecx ; .length_cur
test eax, eax
jnz .return
; 8. Otherwise, continue the loop started at step 2.
add dword [startsector], ecx
adc dword [startsector+4], eax
imul ecx, [.SectorSize]
add [buffer], ecx
pop eax
test eax, eax
jnz .split
push eax
.return:
; 9. Restore the stack, store .processed to [numsectors], return.
pop ecx ; .length_rest
pop ecx ; .processed
mov edx, [numsectors]
mov [edx], ecx
pop ecx ; .SectorSize
pop ecx ; .command
ret
.generic_fail:
or eax, -1
pop ecx ; .length_cur
jmp .return
endp
 
; Builder for SCSI READ10 or WRITE10 request.
; edx = first argument = pointer to usb_device_data.Command,
; second argument = custom data given to queue_request,
; pointer to disk_read_write.locals.
proc read_write_req
mov eax, [esp+8]
mov ecx, [eax+disk_read_write.userdata-disk_read_write.locals]
mov cl, [ecx+usb_unit_data.LUN]
mov [edx+command_block_wrapper.LUN], cl
mov ecx, [eax+disk_read_write.length_cur-disk_read_write.locals]
imul ecx, [eax+disk_read_write.SectorSize-disk_read_write.locals]
mov [edx+command_block_wrapper.Length], ecx
mov cl, [eax+disk_read_write.command-disk_read_write.locals]
mov [edx+command_block_wrapper.Flags], CBW_FLAG_OUT
cmp cl, SCSI_READ10
jnz @f
mov [edx+command_block_wrapper.Flags], CBW_FLAG_IN
@@:
mov byte [edx+command_block_wrapper.Command], cl
mov ecx, dword [eax+disk_read_write.startsector-disk_read_write.locals]
bswap ecx
mov dword [edx+command_block_wrapper.Command+2], ecx
mov ecx, [eax+disk_read_write.length_cur-disk_read_write.locals]
xchg cl, ch
mov word [edx+command_block_wrapper.Command+7], cx
ret 8
endp
 
; Called when SCSI READ10 or WRITE10 request is completed.
proc read_write_callback
; 1. Initialize.
push ebx esi edi
virtual at esp
rd 3 ; saved registers
dd ? ; return address
.device dd ?
.calldata dd ?
end virtual
mov ecx, [.device]
mov esi, [.calldata]
; 2. Get the number of sectors which were read.
; If the status is OK or FAIL, the field .LengthRest is valid.
; Otherwise, it is invalid, so assume zero sectors.
xor eax, eax
cmp [ecx+usb_device_data.Status.Status], CSW_STATUS_FAIL
ja .sectors_calculated
mov eax, [ecx+usb_device_data.LengthRest]
xor edx, edx
div [esi+disk_read_write.SectorSize-disk_read_write.locals]
test edx, edx
jz @f
inc eax
@@:
mov edx, eax
mov eax, [esi+disk_read_write.length_cur-disk_read_write.locals]
sub eax, edx
jae .sectors_calculated
xor eax, eax
.sectors_calculated:
; 3. Increase the total number of processed sectors.
add [esi+disk_read_write.processed-disk_read_write.locals], eax
; 4. Set status to OK if all sectors were read, to ERROR otherwise.
cmp eax, [esi+disk_read_write.length_cur-disk_read_write.locals]
setz al
movzx eax, al
dec eax
mov [esi+disk_read_write.status-disk_read_write.locals], eax
; 5. Set the event.
mov eax, [esi+disk_read_write.event-disk_read_write.locals]
mov ebx, [esi+disk_read_write.event_code-disk_read_write.locals]
xor edx, edx
xor esi, esi
call RaiseEvent
; 6. Return.
pop edi esi ebx
ret 8
endp
 
; strings
my_driver db 'usbstor',0
disconnectmsg db 'K : USB mass storage device disconnected',13,10,0
nomemory db 'K : no memory',13,10,0
unkdevice db 'K : unknown mass storage device',13,10,0
okdevice db 'K : USB mass storage device detected',13,10,0
transfererror db 'K : USB transfer error, disabling mass storage',13,10,0
invresponse db 'K : invalid response from mass storage device',13,10,0
fatalerr db 'K : mass storage device reports fatal error',13,10,0
inquiry_fail db 'K : INQUIRY command failed',13,10,0
;read_capacity_fail db 'K : READ CAPACITY command failed',13,10,0
;read_fail db 'K : READ command failed',13,10,0
noindex db 'K : failed to generate disk name',13,10,0
 
; Exported variable: kernel API version.
align 4
version dd 50005h
; Structure with callback functions.
usb_functions:
dd usb_functions_end - usb_functions
dd AddDevice
dd DeviceDisconnected
usb_functions_end:
 
disk_functions:
dd disk_functions_end - disk_functions
dd disk_close
dd 0 ; closemedia
dd disk_querymedia
dd disk_read
dd disk_write
dd 0 ; flush
dd 0 ; adjust_cache_size: use default cache
disk_functions_end:
 
free_numbers_lock rd 3
; 128 devices should be enough for everybody
free_numbers dd -1, -1, -1, -1
 
; for DEBUGF macro
include_debug_strings
 
; for uninitialized data
section '.data' data readable writable align 16
/kernel/branches/Kolibri-acpi/gui/event.inc
516,7 → 516,7
btr ecx, eax ; сбрасываем проверяемый бит маски
; переходим на обработчик этого (eax) бита
cmp eax, 10
jae .loop ; eax=[10..31], ignored (event 10...32)
jae .loop ; eax=[10..31], ignored (event 11...32)
 
cmp eax, 3
je .loop ; eax=3, ignored (event 4)
/kernel/branches/Kolibri-acpi/gui/skincode.inc
17,21 → 17,16
stdcall load_file, ebx
test eax, eax
jz .notfound
 
cmp dword [eax], 'SKIN'
jnz .noskin
cmp ebx, 32*1024
jb @f
mov ebx, 32*1024
;--------------------------------------
align 4
 
xchg eax, [skin_data]
test eax, eax
jz @f
 
stdcall kernel_free, eax
@@:
lea ecx, [ebx+3]
shr ecx, 2
mov esi, eax
mov edi, skin_data
rep movsd
stdcall kernel_free, eax
 
call parse_skin_data
xor eax, eax
ret
45,8 → 40,7
align 4
.noskin:
stdcall kernel_free, eax
push 2
pop eax
mov eax, 2
ret
;------------------------------------------------------------------------------
struct SKIN_HEADER
98,7 → 92,7
;------------------------------------------------------------------------------
align 4
parse_skin_data:
mov ebp, skin_data
mov ebp, [skin_data]
cmp [ebp+SKIN_HEADER.ident], 'SKIN'
jne .exit
 
109,7 → 103,7
rep stosd
 
mov ebx, [ebp+SKIN_HEADER.params]
add ebx, skin_data
add ebx, [skin_data]
mov eax, [ebx+SKIN_PARAMS.skin_height]
mov [_skinh], eax
mov eax, [ebx+SKIN_PARAMS.colors.inner]
135,7 → 129,7
mov dword[_skinmargins+4], eax
 
mov ebx, [ebp+SKIN_HEADER.bitmaps]
add ebx, skin_data
add ebx, [skin_data]
;--------------------------------------
align 4
.lp1:
160,7 → 154,7
dec eax
jnz .not_oper
mov esi, [ebx+SKIN_BITMAPS.data]
add esi, skin_data
add esi, [skin_data]
mov eax, [esi+0]
neg eax
mov edx, skin_active.oper.data
195,7 → 189,7
align 4
.next_bitmap:
mov ecx, [ebx+SKIN_BITMAPS.data]
add ecx, skin_data
add ecx, [skin_data]
mov [edx+4], eax
mov eax, [ecx+0]
mov [edx+8], eax
207,7 → 201,7
align 4
.end_bitmaps:
mov ebx, [ebp+SKIN_HEADER.buttons]
add ebx, skin_data
add ebx, [skin_data]
;--------------------------------------
align 4
.lp2:
396,7 → 390,8
;--------------------------------------
align 4
@@:
cmp dword[skin_data], 'SKIN'
mov eax, [skin_data]
cmp [eax], dword 'SKIN'
je @f
xor eax, eax
xor ebx, ebx
438,7 → 433,8
;--------------------------------------
align 4
_noinside2:
cmp dword[skin_data], 'SKIN'
mov eax, [skin_data]
cmp [eax], dword 'SKIN'
jne no_skin_add_button
;* close button
mov edi, [BTN_ADDR]
/kernel/branches/Kolibri-acpi/gui/window.inc
1024,6 → 1024,8
; no it's not, just activate the window
call window._.window_activate
xor eax, eax
ret
 
;--------------------------------------
align 4
.exit:
/kernel/branches/Kolibri-acpi/kernel.asm
77,7 → 77,7
USE_COM_IRQ equ 1 ; make irq 3 and irq 4 available for PCI devices
 
; Enabling the next line will enable serial output console
debug_com_base equ 0x3f8 ; 0x3f8 is com1, 0x2f8 is com2, 0x3e8 is com3, 0x2e8 is com4, no irq's are used
;debug_com_base equ 0x3f8 ; 0x3f8 is com1, 0x2f8 is com2, 0x3e8 is com3, 0x2e8 is com4, no irq's are used
; The following constant, if nonzero, duplicates debug output to the screen.
debug_direct_print equ 0
 
163,35 → 163,6
include "bus/pci/pci16.inc"
include "detect/biosdisk.inc"
 
FDD_BUFF equ (OS_BASE+0x000D000)
 
sys_pgdir equ (OS_BASE+0x006F000)
 
VGABasePtr equ (OS_BASE+0x00A0000)
 
RAMDISK equ (OS_BASE+0x0100000)
 
CLEAN_ZONE equ 0x284000
IDE_DMA equ 0x284000
 
BOOT_VAR equ (OS_BASE+0x02E0000)
 
TASK_COUNT equ (CURRENT_TASK+0x04)
TASK_BASE equ (CURRENT_TASK+0x10)
TASK_DATA equ (CURRENT_TASK+0x20)
TASK_EVENT equ (CURRENT_TASK+0x20)
 
BPSLine_calc_area equ (OS_BASE+0x02C4000)
 
d_width_calc_area equ (OS_BASE+0x02CA000)
 
stack_data_start equ (OS_BASE+0x02F0000)
eth_data_start equ (OS_BASE+0x02F0000)
stack_data equ (OS_BASE+0x02F4000)
stack_data_end equ (OS_BASE+0x030ffff)
resendQ equ (OS_BASE+0x0310000)
 
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; SWITCH TO 32 BIT PROTECTED MODE ;;
434,15 → 405,17
dec eax
mov [Screen_Max_Y], eax
mov [screen_workarea.bottom], eax
mov ax, word [BOOT_VAR+BOOT_VESA_MODE] ; screen mode
mov [SCR_MODE], ax
mov [BytesPerScanLine], 640*4 ; Bytes PerScanLine
cmp [SCR_MODE], 0x13 ; 320x200
movzx eax, word [BOOT_VAR+BOOT_VESA_MODE]; screen mode
mov [SCR_MODE], eax
; mov eax, [BOOT_VAR+0x9014] ; Vesa 1.2 bnk sw add
; mov [BANK_SWITCH], eax
mov [BytesPerScanLine], word 640*4 ; Bytes PerScanLine
cmp [SCR_MODE], word 0x13 ; 320x200
je @f
cmp [SCR_MODE], 0x12 ; VGA 640x480
cmp [SCR_MODE], word 0x12 ; VGA 640x480
je @f
movzx eax, word[BOOT_VAR+BOOT_PITCH] ; for other modes
mov [BytesPerScanLine], eax
mov [BytesPerScanLine], ax
mov [_display.pitch], eax
@@:
mov eax, [_display.width]
1268,6 → 1241,7
xor eax, eax
mov [BTN_ADDR], dword BUTTON_INFO ; address of button list
 
mov byte [MOUSE_BUFF_COUNT], al ; mouse buffer
mov byte [KEY_COUNT], al ; keyboard buffer
mov byte [BTN_COUNT], al ; button buffer
; mov [MOUSE_X],dword 100*65536+100 ; mouse x/y
4995,7 → 4969,7
.1: ; resolution
mov eax, [Screen_Max_X]
shl eax, 16
mov ax, word [Screen_Max_Y]
mov ax, [Screen_Max_Y]
add eax, 0x00010001
mov [esp+32], eax
ret
5094,9 → 5068,9
 
align 4
syscall_getscreensize: ; GetScreenSize
mov eax, [Screen_Max_X]
mov ax, [Screen_Max_X]
shl eax, 16
mov ax, word [Screen_Max_Y]
mov ax, [Screen_Max_Y]
mov [esp + 32], eax
ret
 
/kernel/branches/Kolibri-acpi/network/eth_drv/pci.inc
File deleted
Property changes:
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv/ethernet.inc
File deleted
Property changes:
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv/arp.inc
File deleted
Property changes:
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/sis900.inc
File deleted
Property changes:
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/rtl8169.inc
File deleted
Property changes:
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/r6040.inc
File deleted
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/3c59x.inc
File deleted
Property changes:
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/pcnet32.inc
File deleted
Property changes:
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/forcedeth.inc
File deleted
Property changes:
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/rtl8029.inc
File deleted
Property changes:
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/i8255x.inc
File deleted
Property changes:
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers/rtl8139.inc
File deleted
Property changes:
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/eth_drv/drivers
Property changes:
Deleted: svn:ignore
-*.mnt
-lang.inc
-*.bat
-out.txt
-scin*
-*.obj
/kernel/branches/Kolibri-acpi/network/eth_drv
Property changes:
Deleted: svn:ignore
-*.mnt
-lang.inc
-*.bat
-out.txt
-scin*
-*.obj
/kernel/branches/Kolibri-acpi/network/ip.inc
File deleted
Property changes:
Deleted: svn:keywords
-Rev
\ No newline at end of property
/kernel/branches/Kolibri-acpi/network/ARP.inc
177,7 → 177,7
 
inc [ARP_PACKETS_RX + 4*edi] ; update stats
 
DEBUGF 1,"ARP_input: got packet from %u.%u.%u.%u through device %u\n",\
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: got packet from %u.%u.%u.%u through device %u\n",\
[edx + ARP_header.SenderIP]:1, [edx + ARP_header.SenderIP + 1]:1,\
[edx + ARP_header.SenderIP + 2]:1, [edx + ARP_header.SenderIP + 3]:1, edi
 
194,7 → 194,7
cmp [edx + ARP_header.Opcode], ARP_REP_OPCODE
jne .maybe_request
 
DEBUGF 1,"ARP_input: It's a reply\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: It's a reply\n"
 
mov ecx, [NumARP]
test ecx, ecx
208,16 → 208,16
dec ecx
jnz .loop
 
DEBUGF 1,"ARP_input: no matching entry found\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: no matching entry found\n"
jmp .exit
 
.gotit:
DEBUGF 1,"ARP_input: found matching entry\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: found matching entry\n"
 
cmp [esi + ARP_entry.TTL], ARP_STATIC_ENTRY ; if it is a static entry, dont touch it
je .exit
 
DEBUGF 1,"ARP_input: updating entry\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: updating entry\n"
 
mov [esi + ARP_entry.Status], ARP_VALID_MAPPING
mov [esi + ARP_entry.TTL], ARP_ENTRY_TTL
236,7 → 236,7
cmp [edx + ARP_header.Opcode], ARP_REQ_OPCODE
jne .exit
 
DEBUGF 1,"ARP_input: its a request\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: its a request\n"
 
mov eax, [IP_LIST + 4*edi]
cmp eax, [edx + ARP_header.TargetIP] ; Is it looking for my IP address?
277,7 → 277,7
; mov ax , ETHER_ARP ; It's already there, I'm sure of it!
; stosw
 
DEBUGF 1,"ARP_input: Sending reply\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: Sending reply\n"
 
call [ebx + NET_DEVICE.transmit]
ret
284,13 → 284,13
 
.collision:
inc [ARP_CONFLICTS + 4*edi]
DEBUGF 1,"ARP_input: IP address conflict detected!\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: IP address conflict detected!\n"
 
.exit:
call kernel_free
add esp, 4 ; pop (balance stack)
 
DEBUGF 1,"ARP_input: exiting\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_input: exiting\n"
ret
 
 
310,7 → 310,7
pushd [IP_LIST + edi] ; SenderIP
inc [ARP_PACKETS_TX + edi] ; assume we will succeed
 
DEBUGF 1,"ARP_output_request: ip=%u.%u.%u.%u\n",\
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_output_request: ip=%u.%u.%u.%u\n",\
[esp + 4]:1, [esp + 5]:1, [esp + 6]:1, [esp + 7]:1
 
mov ebx, [NET_DRV_LIST + edi] ; device ptr
344,7 → 344,7
pop eax ; DestIP
stosd ;
 
DEBUGF 1,"ARP_output_request: device=%x\n", ebx
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_output_request: device=%x\n", ebx
 
push edx ecx
call [ebx + NET_DEVICE.transmit]
352,7 → 352,7
 
.exit:
add esp, 4 + 4
DEBUGF 1,"ARP_output_request: failed\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_output_request: failed\n"
sub eax, eax
ret
 
369,7 → 369,7
align 4
ARP_add_entry:
 
DEBUGF 1,"ARP_add_entry: "
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_add_entry: "
 
mov ecx, [NumARP]
cmp ecx, ARP_TABLE_SIZE ; list full ?
400,12 → 400,12
rep movsw
inc [NumARP]
sub edi, sizeof.ARP_entry
DEBUGF 1,"entry=%u\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "entry=%u\n", eax
 
ret
 
.error:
DEBUGF 1,"failed\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "failed\n"
mov eax, -1
ret
 
421,8 → 421,8
align 4
ARP_del_entry:
 
DEBUGF 1,"ARP_del_entry: entry=%x entrys=%u\n", esi, [NumARP]
DEBUGF 1,"ARP_del_entry: IP=%u.%u.%u.%u\n", \
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_del_entry: entry=%x entrys=%u\n", esi, [NumARP]
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_del_entry: IP=%u.%u.%u.%u\n", \
[esi + ARP_entry.IP]:1, [esi + ARP_entry.IP + 1]:1, [esi + ARP_entry.IP + 2]:1, [esi + ARP_entry.IP + 3]:1
 
mov ecx, ARP_table + (ARP_TABLE_SIZE - 1) * sizeof.ARP_entry
438,7 → 438,7
rep stosw
 
dec [NumARP]
DEBUGF 1,"ARP_del_entry: success\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_del_entry: success\n"
 
ret
 
463,9 → 463,9
align 4
ARP_IP_to_MAC:
 
DEBUGF 1,"ARP_IP_to_MAC: %u.%u", al, ah
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: %u.%u", al, ah
rol eax, 16
DEBUGF 1,".%u.%u\n", al, ah
DEBUGF DEBUG_NETWORK_VERBOSE, ".%u.%u\n", al, ah
rol eax, 16
 
cmp eax, 0xffffffff
485,7 → 485,7
loop .scan_loop
 
.not_in_list:
DEBUGF 1,"ARP_IP_to_MAC: preparing for ARP request\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: preparing for ARP request\n"
 
;--------------------
; Send an ARP request
535,16 → 535,16
end if
 
.valid:
DEBUGF 1,"ARP_IP_to_MAC: found MAC\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: found MAC\n"
movzx eax, word[esi + ARP_entry.MAC]
mov ebx, dword[esi + ARP_entry.MAC + 2]
ret
 
.full:
DEBUGF 1,"ARP_IP_to_MAC: table is full!\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: table is full!\n"
add esp, 8
.give_up:
DEBUGF 1,"ARP_IP_to_MAC: entry has no valid mapping!\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_IP_to_MAC: entry has no valid mapping!\n"
mov eax, -1
ret
 
/kernel/branches/Kolibri-acpi/network/IPv4.inc
112,7 → 112,7
jmp .done
 
.died:
DEBUGF 2,"IPv4 Fragment slot timed-out!\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4 Fragment slot timed-out!\n"
;;; TODO: clear all entry's of timed-out slot
jmp .next
 
205,10 → 205,10
align 4
IPv4_input: ; TODO: add IPv4 raw sockets support
 
DEBUGF 2,"IPv4_input, packet from: %u.%u.%u.%u ",\
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input, packet from: %u.%u.%u.%u ",\
[edx + IPv4_header.SourceAddress + 0]:1,[edx + IPv4_header.SourceAddress + 1]:1,\
[edx + IPv4_header.SourceAddress + 2]:1,[edx + IPv4_header.SourceAddress + 3]:1
DEBUGF 2,"to: %u.%u.%u.%u\n",\
DEBUGF DEBUG_NETWORK_VERBOSE, "to: %u.%u.%u.%u\n",\
[edx + IPv4_header.DestinationAddress + 0]:1,[edx + IPv4_header.DestinationAddress + 1]:1,\
[edx + IPv4_header.DestinationAddress + 2]:1,[edx + IPv4_header.DestinationAddress + 3]:1
 
218,7 → 218,7
IPv4_checksum edx
jnz .dump ; if checksum isn't valid then dump packet
 
DEBUGF 1,"IPv4_input: Checksum ok\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Checksum ok\n"
 
;-----------------------------------
; Check if destination IP is correct
256,7 → 256,7
 
; or it's just not meant for us.. :(
 
DEBUGF 2,"IPv4_input: Destination address does not match!\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Destination address does not match!\n"
jmp .dump
 
;------------------------
300,10 → 300,10
cmp al, IP_PROTO_ICMP
je ICMP_input
 
DEBUGF 2,"IPv4_input: unknown protocol %u\n", al
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: unknown protocol %u\n", al
 
.dump:
DEBUGF 1,"IPv4_input: dumping\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: dumping\n"
inc [IP_packets_dumped] ; FIXME: use correct interface
call kernel_free
add esp, 4 ; pop (balance stack)
319,7 → 319,7
xchg al, ah
shl ax, 3
 
DEBUGF 1,"IPv4_input: fragmented packet offset=%u id=%x\n", ax, [edx + IPv4_header.Identification]:4
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: fragmented packet offset=%u id=%x\n", ax, [edx + IPv4_header.Identification]:4
 
test ax, ax ; Is this the first packet of the fragment?
jz .is_first_fragment
328,7 → 328,7
;-------------------------------------------------------
; We have a fragmented IP packet, but it's not the first
 
DEBUGF 1,"IPv4_input: Middle fragment packet received!\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Middle fragment packet received!\n"
 
call IPv4_find_fragment_slot
cmp esi, -1
361,7 → 361,7
; We have received the first fragment
 
.is_first_fragment:
DEBUGF 1,"IPv4_input: First fragment packet received!\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: First fragment packet received!\n"
; try to locate a free slot..
mov ecx, MAX_FRAGMENTS
mov esi, FRAGMENT_LIST
395,7 → 395,7
; We have received the last fragment
 
.is_last_fragment:
DEBUGF 1,"IPv4_input: Last fragment packet received!\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Last fragment packet received!\n"
 
call IPv4_find_fragment_slot
cmp esi, -1
411,12 → 411,12
jne .destroy_slot_pop ; Damn, something screwed up, remove the whole slot (and free buffers too if possible!)
mov cx, [esi + sizeof.FRAGMENT_entry + IPv4_header.TotalLength] ; Add total length
xchg cl, ch
DEBUGF 1,"IPv4_input: Packet size=%u\n", cx
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Packet size=%u\n", cx
add ax, cx
movzx cx, [esi + sizeof.FRAGMENT_entry + IPv4_header.VersionAndIHL] ; Sub Header length
and cx, 0x000F
shl cx, 2
DEBUGF 1,"IPv4_input: Header size=%u\n", cx
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Header size=%u\n", cx
sub ax, cx
mov edi, esi
mov esi, [esi + FRAGMENT_entry.NextPtr]
431,9 → 431,9
 
mov cx, [edx + IPv4_header.TotalLength] ; Note: This time we dont substract Header length
xchg cl, ch
DEBUGF 1,"IPv4_input: Packet size=%u\n", cx
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Packet size=%u\n", cx
add ax, cx
DEBUGF 1,"IPv4_input: Total Received data size=%u\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Total Received data size=%u\n", eax
 
push eax
mov ax, [edx + IPv4_header.FlagsAndFragmentOffset]
441,7 → 441,7
shl ax, 3
add cx, ax
pop eax
DEBUGF 1,"IPv4_input: Total Fragment size=%u\n", ecx
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Total Fragment size=%u\n", ecx
 
cmp ax, cx
jne .destroy_slot_pop
457,7 → 457,7
movzx ecx, [edx + sizeof.FRAGMENT_entry + IPv4_header.FlagsAndFragmentOffset] ; Calculate the fragment offset
xchg cl, ch ; intel byte order
shl cx, 3 ; multiply by 8 and clear first 3 bits
DEBUGF 1,"IPv4_input: Fragment offset=%u\n", cx
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Fragment offset=%u\n", cx
 
lea edi, [eax + ecx] ; Notice that edi will be equal to eax for first fragment
movzx ebx, [edx + sizeof.FRAGMENT_entry + IPv4_header.VersionAndIHL] ; Find header size (in ebx) of fragment
504,7 → 504,7
.destroy_slot_pop:
add esp, 4
.destroy_slot:
DEBUGF 1,"IPv4_input: Destroy fragment slot!\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_input: Destroy fragment slot!\n"
; TODO!
jmp .dump
 
568,7 → 568,7
align 4
IPv4_output:
 
DEBUGF 1,"IPv4_output: size=%u\n", ecx
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_output: size=%u\n", ecx
 
cmp ecx, 65500 ; Max IPv4 packet size
ja .too_large
614,23 → 614,23
 
IPv4_checksum edi
add edi, sizeof.IPv4_header
DEBUGF 2,"IPv4_output: success!\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_output: success!\n"
ret
 
.eth_error:
DEBUGF 2,"IPv4_output: ethernet error\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_output: ethernet error\n"
add esp, 3*4+2+6
xor edi, edi
ret
 
.arp_error:
DEBUGF 2,"IPv4_output: ARP error=%x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_output: ARP error=%x\n", eax
add esp, 3*4+2
xor edi, edi
ret
 
.too_large:
DEBUGF 2,"IPv4_output: Packet too large!\n"
DEBUGF DEBUG_NETWORK_ERROR, "IPv4_output: Packet too large!\n"
xor edi, edi
ret
 
713,7 → 713,7
 
IPv4_checksum edi ;;;; todo: checksum for IP packet with options!
add edi, sizeof.IPv4_header
DEBUGF 2,"IPv4_output_raw: device=%x\n", ebx
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_output_raw: device=%x\n", ebx
call [ebx + NET_DEVICE.transmit]
ret
 
722,7 → 722,7
.arp_error:
add esp, 8+4+4
.too_large:
DEBUGF 2,"IPv4_output_raw: Failed\n"
DEBUGF DEBUG_NETWORK_ERROR, "IPv4_output_raw: Failed\n"
sub edi, edi
ret
 
742,7 → 742,7
align 4
IPv4_fragment:
 
DEBUGF 1,"IPv4_fragment\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_fragment\n"
 
and ecx, not 111b ; align 4
 
770,7 → 770,7
push dword 0 ; offset
 
.new_fragment:
DEBUGF 1,"Ipv4_fragment: new fragment"
DEBUGF DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: new fragment"
 
 
mov eax, [esp + 3*4]
792,7 → 792,7
add esi, [esp] ; offset
 
mov ecx, [esp + 1*4]
DEBUGF 1,"IPv4_fragment: copying %u bytes\n", ecx
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_fragment: copying %u bytes\n", ecx
rep movsb
 
; now, correct header
829,7 → 829,7
sub ecx, [esp+2*4] ; ptr to ip header
add ecx, [esp] ; offset
 
DEBUGF 1,"Ipv4_fragment: %u bytes remaining\n", ecx
DEBUGF DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: %u bytes remaining\n", ecx
 
cmp ecx, [esp+1*4]
jae .new_fragment
838,11 → 838,11
jmp .new_fragment
 
.err:
DEBUGF 1,"Ipv4_fragment: failed\n"
DEBUGF DEBUG_NETWORK_ERROR, "Ipv4_fragment: failed\n"
.done:
add esp, 12 + 4 + 6
.err2:
DEBUGF 1,"Ipv4_fragment: dumping\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: dumping\n"
call kernel_free
add esp, 4
 
886,7 → 886,7
mov eax, [GATEWAY_LIST]
 
.found_it:
DEBUGF 1,"IPv4_dest_to_dev: %u\n", edi
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_route: %u\n", edi
ret
 
.broadcast:
/kernel/branches/Kolibri-acpi/network/IPv6.inc
83,7 → 83,7
align 4
IPv6_input:
 
DEBUGF 2,"IPv6_input from: %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x\n",\
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input from: %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x\n",\
[edx + IPv6_header.SourceAddress + 0]:2,[edx + IPv6_header.SourceAddress + 1]:2,\
[edx + IPv6_header.SourceAddress + 2]:2,[edx + IPv6_header.SourceAddress + 3]:2,\
[edx + IPv6_header.SourceAddress + 4]:2,[edx + IPv6_header.SourceAddress + 5]:2,\
93,7 → 93,7
[edx + IPv6_header.SourceAddress + 12]:2,[edx + IPv6_header.SourceAddress + 13]:2,\
[edx + IPv6_header.SourceAddress + 14]:2,[edx + IPv6_header.SourceAddress + 15]:2
 
DEBUGF 1,"IPv6_input to: %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x\n",\
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input to: %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x\n",\
[edx + IPv6_header.DestinationAddress + 0]:2,[edx + IPv6_header.DestinationAddress + 1]:2,\
[edx + IPv6_header.DestinationAddress + 2]:2,[edx + IPv6_header.DestinationAddress + 3]:2,\
[edx + IPv6_header.DestinationAddress + 4]:2,[edx + IPv6_header.DestinationAddress + 5]:2,\
143,10 → 143,10
; cmp al, 58
; je ICMP6_input
 
DEBUGF 2,"IPv6_input - unknown protocol: %u\n", al
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - unknown protocol: %u\n", al
 
.dump:
DEBUGF 1,"IPv6_input - dumping\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - dumping\n"
call kernel_free
add esp, 4
 
166,7 → 166,7
; Hop-by-Hop
 
.hop_by_hop:
DEBUGF 1,"IPv6_input - hop by hop\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - hop by hop\n"
pushw [esi] ; 8 bit identifier for option type
movzx eax, byte[esi + 1] ; Hdr Ext Len
inc eax ; first 8 octets not counted
195,7 → 195,7
 
.pad_n:
movzx eax, byte[esi + 1]
DEBUGF 1,"IPv6_input - pad %u\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - pad %u\n", eax
inc esi
inc esi
add esi, eax
203,7 → 203,7
jmp .hop_by_hop
 
.pad_1:
DEBUGF 1,"IPv6_input - pad 1\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - pad 1\n"
inc esi
dec ecx
jmp .hop_by_hop
211,11 → 211,11
 
 
.dest_opts:
DEBUGF 1,"IPv6_input - dest opts\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - dest opts\n"
jmp .nextheader
 
.routing:
DEBUGF 1,"IPv6_input - routing\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - routing\n"
pushw [esi] ; 8 bit identifier for option type
movzx eax, byte[esi + 1] ; Hdr Ext Len
inc eax ; first 8 octets not counted
238,7 → 238,7
jmp .nextheader
 
.fragment:
DEBUGF 1,"IPv6_input - fragment\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv6_input - fragment\n"
 
jmp .nextheader
 
/kernel/branches/Kolibri-acpi/network/PPPoE.inc
59,7 → 59,7
align 4
PPPoE_discovery_input:
 
DEBUGF 2,"PPPoE_discovery_input\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_discovery_input\n"
 
; First, find open PPPoE socket
 
84,7 → 84,7
jmp SOCKET_input
 
.dump:
DEBUGF 1,'PPPoE_discovery_input: dumping\n'
DEBUGF DEBUG_NETWORK_VERBOSE, 'PPPoE_discovery_input: dumping\n'
call kernel_free
add esp, 4
ret
103,7 → 103,7
align 4
PPPoE_discovery_output:
 
DEBUGF 2,"PPPoE_discovery_output: socket=%x buffer=%x size=%d\n", eax, esi, ecx
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_discovery_output: socket=%x buffer=%x size=%d\n", eax, esi, ecx
 
; RFC2516: An entire PADI packet (including the PPPoE header) MUST NOT
; exceed 1484 octets.
123,7 → 123,7
cmp [ebx + NET_DEVICE.type], NET_TYPE_ETH
jne .bad
 
DEBUGF 2,"PPPoE_discovery_output: device=%x\n", ebx
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_discovery_output: device=%x\n", ebx
 
; Create packet.
push ecx esi
193,7 → 193,7
xchg cl, ch
 
mov ax, [edx + PPPoE_frame.SessionID]
DEBUGF 2,"PPPoE_input: session ID=%x, length=%u\n", ax, cx
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_input: session ID=%x, length=%u\n", ax, cx
cmp ax, [PPPoE_SID]
jne .dump
 
207,10 → 207,10
; je IPv6_input
 
jmp PPPoE_discovery_input ; Send LCP,CHAP,CBCP,... packets to the PPP dialer
DEBUGF 2,"PPPoE_input: Unknown protocol=%x\n", ax
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_input: Unknown protocol=%x\n", ax
 
.dump:
DEBUGF 2,"PPPoE_input: dumping\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_input: dumping\n"
call kernel_free
add esp, 4
ret
238,7 → 238,7
align 4
PPPoE_output:
 
DEBUGF 1,"PPPoE_output: size=%u device=%x\n", ecx, ebx
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_output: size=%u device=%x\n", ecx, ebx
 
pushw di
pushw [PPPoE_SID]
263,7 → 263,7
sub ecx, 2
add edi, PPPoE_frame.Payload + 2
 
DEBUGF 1,"PPPoE_output: success!\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_output: success!\n"
ret
 
 
276,7 → 276,7
 
PPPoE_start_connection:
 
DEBUGF 2,"PPPoE_start_connection: %x\n", cx
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_start_connection: %x\n", cx
 
cmp [PPPoE_SID], 0
jne .fail
296,7 → 296,7
align 4
PPPoE_stop_connection:
 
DEBUGF 2,"PPPoE_stop_connection\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "PPPoE_stop_connection\n"
 
xor eax, eax
mov [PPPoE_SID], ax
/kernel/branches/Kolibri-acpi/network/ethernet.inc
56,7 → 56,7
mov eax, [esp]
mov ecx, [esp+4]
 
DEBUGF 1,"ETH_input: size=%u\n", ecx
DEBUGF DEBUG_NETWORK_VERBOSE,"ETH_input: size=%u\n", ecx
cmp ecx, ETH_FRAME_MINIMUM
jb .dump
sub ecx, sizeof.ETH_header
79,10 → 79,10
cmp ax, ETHER_PPP_SESSION
je PPPoE_session_input
 
DEBUGF 2,"ETH_input: Unknown packet type=%x\n", ax
DEBUGF DEBUG_NETWORK_ERROR, "ETH_input: Unknown packet type=%x\n", ax
 
.dump:
DEBUGF 2,"ETH_input: dumping\n"
DEBUGF DEBUG_NETWORK_VERBOSE,"ETH_input: dumping\n"
call kernel_free
add esp, 4
ret
107,7 → 107,7
align 4
ETH_output:
 
DEBUGF 1,"ETH_output: size=%u device=%x\n", ecx, ebx
DEBUGF DEBUG_NETWORK_VERBOSE, "ETH_output: size=%u device=%x\n", ecx, ebx
 
cmp ecx, [ebx + NET_DEVICE.mtu]
ja .exit
137,7 → 137,7
cmp edx, ETH_FRAME_MINIMUM
jbe .adjust_size
.done:
DEBUGF 1,"ETH_output: ptr=%x size=%u\n", eax, edx
DEBUGF DEBUG_NETWORK_VERBOSE, "ETH_output: ptr=%x size=%u\n", eax, edx
ret
 
.adjust_size:
146,13 → 146,13
jmp .done
 
.out_of_ram:
DEBUGF 2,"ETH_output: Out of ram!\n"
DEBUGF DEBUG_NETWORK_ERROR, "ETH_output: Out of ram!\n"
add esp, 4+4+2+4
sub edi, edi
ret
 
.exit:
DEBUGF 2,"ETH_output: Packet too large!\n"
DEBUGF DEBUG_NETWORK_ERROR, "ETH_output: Packet too large!\n"
sub edi, edi
ret
 
/kernel/branches/Kolibri-acpi/network/icmp.inc
142,7 → 142,7
align 4
ICMP_input:
 
DEBUGF 1,"ICMP_input:\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "ICMP_input:\n"
 
; First, check the checksum (altough some implementations ignore it)
 
163,7 → 163,7
; We well re-use the packet so we can create the response as fast as possible
; Notice: this only works on pure ethernet
 
DEBUGF 1,"got echo request\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "got echo request\n"
mov [edx + ICMP_header.Type], ICMP_ECHOREPLY ; Change Packet type to reply
 
mov esi, [esp] ; Start of buffer
258,7 → 258,7
; je .dump
; inc [ICMP_PACKETS_RX+edi]
 
DEBUGF 1,"socket=%x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "socket=%x\n", eax
 
pusha
lea ecx, [eax + SOCKET.mutex]
270,10 → 270,10
 
 
.checksum_mismatch:
DEBUGF 1,"checksum mismatch\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "checksum mismatch\n"
 
.dump:
DEBUGF 1,"ICMP_input: dumping\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "ICMP_input: dumping\n"
 
call kernel_free
add esp, 4 ; pop (balance stack)
297,7 → 297,7
align 4
ICMP_output:
 
DEBUGF 1,"Creating ICMP Packet\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet\n"
 
push esi edi dx
 
308,7 → 308,7
call IPv4_output
jz .exit
 
DEBUGF 1,"full icmp packet size: %u\n", edx
DEBUGF DEBUG_NETWORK_VERBOSE, "full icmp packet size: %u\n", edx
 
pop word [edi + ICMP_header.Type] ; Write both type and code bytes at once
pop dword [edi + ICMP_header.Identifier] ; identifier and sequence number
333,11 → 333,11
 
sub edi, edx ;;; TODO: find a better way to remember start of packet
push edx edi
DEBUGF 1,"Sending ICMP Packet\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
call [ebx + NET_DEVICE.transmit]
ret
.exit:
DEBUGF 1,"Creating ICMP Packet failed\n"
DEBUGF DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
add esp, 2*4 + 2
ret
 
356,7 → 356,7
align 4
ICMP_output_raw:
 
DEBUGF 1,"Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
DEBUGF DEBUG_NETWORK_VERBOSE, "Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
 
push edx
 
371,7 → 371,7
push eax
 
push edi ecx
DEBUGF 1,"copying %u bytes from %x to %x\n", ecx, esi, edi
DEBUGF DEBUG_NETWORK_VERBOSE, "copying %u bytes from %x to %x\n", ecx, esi, edi
rep movsb
pop ecx edi
 
383,11 → 383,11
call checksum_2
mov [edi + ICMP_header.Checksum], dx
 
DEBUGF 1,"Sending ICMP Packet\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "Sending ICMP Packet\n"
call [ebx + NET_DEVICE.transmit]
ret
.exit:
DEBUGF 1,"Creating ICMP Packet failed\n"
DEBUGF DEBUG_NETWORK_ERROR, "Creating ICMP Packet failed\n"
add esp, 4
ret
 
/kernel/branches/Kolibri-acpi/network/loopback.inc
59,7 → 59,7
push ecx
push eax
 
DEBUGF 1,"LOOP_input: size=%u\n", ecx
DEBUGF DEBUG_NETWORK_VERBOSE, "LOOP_input: size=%u\n", ecx
lea edx, [eax + 2]
mov ax, word[eax]
mov ebx, LOOPBACK_DEVICE
67,10 → 67,10
cmp ax, ETHER_IPv4
je IPv4_input
 
DEBUGF 2,"LOOP_input: Unknown packet type=%x\n", ax
DEBUGF DEBUG_NETWORK_VERBOSE, "LOOP_input: Unknown packet type=%x\n", ax
 
.dump:
DEBUGF 2,"LOOP_input: dumping\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "LOOP_input: dumping\n"
call kernel_free
add esp, 4
ret
93,7 → 93,7
align 4
LOOP_output:
 
DEBUGF 1,"LOOP_output\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "LOOP_output\n"
 
push ecx
push di
114,11 → 114,11
mov ebx, LOOPBACK_DEVICE
 
.done:
DEBUGF 2,"LOOP_output: ptr=%x size=%u\n", eax, edx
DEBUGF DEBUG_NETWORK_VERBOSE, "LOOP_output: ptr=%x size=%u\n", eax, edx
ret
 
.out_of_ram:
DEBUGF 2,"LOOP_output: failed\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "LOOP_output: failed\n"
add esp, 2+4
sub edi, edi
ret
/kernel/branches/Kolibri-acpi/network/socket.inc
263,7 → 263,7
.number = ($ - .table) / 4 - 1
 
s_error:
DEBUGF 2,"SOCKET: error\n"
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET: error\n"
mov dword [esp+32], -1
 
ret
281,7 → 281,7
align 4
SOCKET_open:
 
DEBUGF 2,"SOCKET_open: domain=%u type=%u protocol=%x ", ecx, edx, esi
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_open: domain=%u type=%u protocol=%x ", ecx, edx, esi
 
push ecx edx esi
call SOCKET_alloc
289,7 → 289,7
jz s_error
 
mov [esp+32], edi ; return socketnumber
DEBUGF 2,"socknum=%u\n", edi
DEBUGF DEBUG_NETWORK_VERBOSE, "socknum=%u\n", edi
 
; push edx
; and edx, SO_NONBLOCK
321,7 → 321,7
je .pppoe
 
.no_ppp:
DEBUGF 2,"Unknown socket family/protocol\n"
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_open: Unknown socket family/protocol\n"
ret
 
align 4
394,7 → 394,7
align 4
SOCKET_bind:
 
DEBUGF 2,"SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
 
call SOCKET_num_to_ptr
jz s_error
444,7 → 444,7
call SOCKET_check_port
jz s_error ; ZF is set by socket_check_port, on error
 
DEBUGF 1,"SOCKET_bind: local ip=%u.%u.%u.%u\n",\
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_bind: local ip=%u.%u.%u.%u\n",\
[eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\
[eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1
 
467,7 → 467,7
align 4
SOCKET_connect:
 
DEBUGF 2,"SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
 
call SOCKET_num_to_ptr
jz s_error
616,7 → 616,7
align 4
SOCKET_listen:
 
DEBUGF 2,"SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx
 
call SOCKET_num_to_ptr
jz s_error
668,7 → 668,7
align 4
SOCKET_accept:
 
DEBUGF 2,"SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
 
call SOCKET_num_to_ptr
jz s_error
718,7 → 718,7
align 4
SOCKET_close:
 
DEBUGF 2,"SOCKET_close: socknum=%u\n", ecx
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_close: socknum=%u\n", ecx
 
call SOCKET_num_to_ptr
jz s_error
767,18 → 767,21
align 4
SOCKET_receive:
 
DEBUGF 2,"SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi
 
call SOCKET_num_to_ptr
jz s_error
 
jmp [eax + SOCKET.rcv_proc]
call [eax + SOCKET.rcv_proc]
 
mov [esp+32], eax
ret
 
 
align 4
SOCKET_receive_dgram:
 
DEBUGF 1,"SOCKET_receive: DGRAM\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: DGRAM\n"
 
mov ebx, esi
mov edi, edx ; addr to buffer
787,15 → 790,15
get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .block ; destroys esi and ecx
 
mov ecx, [esi + socket_queue_entry.data_size]
DEBUGF 1,"SOCKET_receive: %u bytes data\n", ecx
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: %u bytes data\n", ecx
 
cmp ecx, ebx
ja .too_small
 
push ecx
push [esi + socket_queue_entry.buf_ptr] ; save the buffer addr so we can clear it later
mov esi, [esi + socket_queue_entry.data_ptr]
DEBUGF 1,"SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi
mov [esp+32+4], ecx ; return number of bytes copied
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi
 
; copy the data
shr ecx, 1
812,16 → 815,20
.nd:
 
call kernel_free ; remove the packet
pop eax
 
ret
 
.too_small:
 
DEBUGF 2,"SOCKET_receive: Buffer too small\n"
jmp s_error
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: Buffer too small\n"
.fail:
mov eax, -1
ret
 
.block:
test [eax + SOCKET.options], SO_NONBLOCK
jnz s_error
jnz .fail
 
call SOCKET_block
jmp .loop
846,7 → 853,7
align 4
SOCKET_receive_stream:
 
DEBUGF 1,"SOCKET_receive: STREAM\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_receive: STREAM\n"
 
mov ebx, edi
mov ecx, esi
866,12 → 873,11
call SOCKET_ring_read
call SOCKET_ring_free
 
mov [esp+32], ecx ; return number of bytes copied
mov eax, ecx ; return number of bytes copied
ret
 
.peek:
mov ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
mov [esp+32], ecx ; return number of bytes available
mov eax, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
ret
 
.block:
882,11 → 888,18
jmp .loop
 
.return0:
xor ecx, ecx
mov [esp+32], ecx
test [eax + SOCKET.options], SS_CANTRCVMORE
jz .ok
 
xor eax, eax
dec eax
ret
 
.ok:
xor eax, eax
ret
 
 
;-----------------------------------------------------------------
;
; SOCKET_send
902,7 → 915,7
align 4
SOCKET_send:
 
DEBUGF 2,"SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi
 
call SOCKET_num_to_ptr
jz s_error
916,7 → 929,7
align 4
SOCKET_send_udp:
 
DEBUGF 1,"SOCKET_send: UDP\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: UDP\n"
 
mov [esp+32], ecx
call UDP_output
928,7 → 941,7
align 4
SOCKET_send_tcp:
 
DEBUGF 1,"SOCKET_send: TCP\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: TCP\n"
 
push eax
add eax, STREAM_SOCKET.snd
944,7 → 957,7
align 4
SOCKET_send_ip:
 
DEBUGF 1,"SOCKET_send: IPv4\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: IPv4\n"
 
mov [esp+32], ecx
call IPv4_output_raw
956,7 → 969,7
align 4
SOCKET_send_icmp:
 
DEBUGF 1,"SOCKET_send: ICMP\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: ICMP\n"
 
mov [esp+32], ecx
call ICMP_output_raw
968,7 → 981,7
align 4
SOCKET_send_pppoe:
 
DEBUGF 1,"SOCKET_send: PPPoE\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: PPPoE\n"
 
mov [esp+32], ecx
mov ebx, [eax + SOCKET.device]
998,7 → 1011,7
align 4
SOCKET_send_local_:
 
DEBUGF 1,"SOCKET_send: LOCAL\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_send: LOCAL\n"
 
; get the other side's socket and check if it still exists
mov eax, [eax + SOCKET.device]
1037,7 → 1050,7
align 4
SOCKET_get_opt:
 
DEBUGF 2,"SOCKET_get_opt\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_get_opt\n"
 
call SOCKET_num_to_ptr
jz s_error
1087,7 → 1100,7
align 4
SOCKET_set_opt:
 
DEBUGF 2,"SOCKET_set_opt\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt\n"
 
call SOCKET_num_to_ptr
jz s_error
1116,7 → 1129,7
jz s_error
mov [eax + SOCKET.device], edx
 
DEBUGF 1,"SOCKET_set_opt: Bound socket %x to device %x\n",eax, edx
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt: Bound socket %x to device %x\n",eax, edx
 
mov dword [esp+32], 0 ; success!
ret
1158,7 → 1171,7
align 4
SOCKET_pair:
 
DEBUGF 2,"SOCKET_pair\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_pair\n"
 
call SOCKET_alloc
jz s_error
1217,7 → 1230,7
align 4
SOCKET_debug:
 
DEBUGF 1,"SOCKET_debug\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_debug\n"
 
mov edi, edx
 
1266,7 → 1279,7
align 4
SOCKET_find_port:
 
DEBUGF 2,"SOCKET_find_port\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_find_port\n"
 
push ebx esi ecx
 
1327,7 → 1340,7
align 4
SOCKET_check_port:
 
DEBUGF 2,"SOCKET_check_port: "
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_check_port: "
 
mov ecx, [eax + SOCKET.Protocol]
mov edx, [eax + IP_SOCKET.LocalIP]
1347,11 → 1360,11
cmp [esi + UDP_SOCKET.LocalPort], bx
jne .next_socket
 
DEBUGF 2,"local port %x already in use\n", bx ; FIXME: find a way to print big endian values with debugf
DEBUGF DEBUG_NETWORK_VERBOSE, "local port %x already in use\n", bx ; FIXME: find a way to print big endian values with debugf
ret
 
.port_ok:
DEBUGF 2,"local port %x is free\n", bx ; FIXME: find a way to print big endian values with debugf
DEBUGF DEBUG_NETWORK_VERBOSE, "local port %x is free\n", bx ; FIXME: find a way to print big endian values with debugf
mov [eax + UDP_SOCKET.LocalPort], bx
or bx, bx ; clear the zero-flag
ret
1378,7 → 1391,7
align 4
SOCKET_input:
 
DEBUGF 2,"SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx
 
mov [esp+4], ecx
push esi
1386,7 → 1399,7
 
add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, SOCKET_input.full
 
DEBUGF 1,"SOCKET_input: success\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_input: success\n"
add esp, sizeof.socket_queue_entry
 
pusha
1397,7 → 1410,7
jmp SOCKET_notify
 
.full:
DEBUGF 2,"SOCKET_input: socket %x is full!\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket %x is full!\n", eax
 
pusha
lea ecx, [eax + SOCKET.mutex]
1424,7 → 1437,7
stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SW
pop edx
 
DEBUGF 1,"SOCKET_ring_created: %x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_created: %x\n", eax
 
pusha
lea ecx, [esi + RING_BUFFER.mutex]
1458,7 → 1471,7
align 4
SOCKET_ring_write:
 
DEBUGF 1,"SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
 
; lock mutex
pusha
1474,7 → 1487,7
mov ecx, edi
.copy:
mov edi, [eax + RING_BUFFER.write_ptr]
DEBUGF 2,"SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi
 
; update write ptr
push edi
1532,7 → 1545,7
align 4
SOCKET_ring_read:
 
DEBUGF 1,"SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx
 
pusha
lea ecx, [eax + RING_BUFFER.mutex]
1555,7 → 1568,7
ja .less_data
 
.copy:
DEBUGF 2,"SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
push ecx
shr ecx, 1
jnc .nb
1578,7 → 1591,7
call mutex_unlock ; TODO: check what registers this function actually destroys
popa
 
DEBUGF 1,"SOCKET_ring_read: no data at all!\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: no data at all!\n"
xor ecx, ecx
ret
 
1602,7 → 1615,7
align 4
SOCKET_ring_free:
 
DEBUGF 1,"SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
 
push eax ecx
lea ecx, [eax + RING_BUFFER.mutex]
1627,7 → 1640,7
ret
 
.error: ; we could free all available bytes, but that would be stupid, i guess..
DEBUGF 1,"SOCKET_ring_free: buffer=%x error!\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: buffer=%x error!\n", eax
add [eax + RING_BUFFER.size], ecx
 
push eax
1652,7 → 1665,7
align 4
SOCKET_block:
 
DEBUGF 1,"SOCKET_block: %x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_block: %x\n", eax
 
pushf
cli
1667,7 → 1680,7
 
; Remember the thread ID so we can wake it up again
mov edx, [edx + TASKDATA.pid]
DEBUGF 1,"SOCKET_block: suspending thread: %u\n", edx
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_block: suspending thread: %u\n", edx
mov [eax + SOCKET.TID], edx
pop edx
 
1674,7 → 1687,7
call change_task
popf
 
DEBUGF 1,"SOCKET_block: continueing\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_block: continueing\n"
 
ret
 
1692,7 → 1705,7
align 4
SOCKET_notify:
 
DEBUGF 1,"SOCKET_notify: %x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_notify: %x\n", eax
 
call SOCKET_check
jz .error
1728,7 → 1741,7
shl ecx, 8
or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK
 
DEBUGF 1,"SOCKET_notify: Raised a network event!\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Raised a network event!\n"
 
jmp .done
 
1756,7 → 1769,7
 
; Run the thread
mov [esi + TASKDATA.state], 0 ; Running
DEBUGF 1,"SOCKET_notify: Unblocked socket!\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Unblocked socket!\n"
 
.done:
pop esi ecx eax
1785,7 → 1798,7
push ebx
 
stdcall kernel_alloc, SOCKETBUFFSIZE
DEBUGF 1, "SOCKET_alloc: ptr=%x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: ptr=%x\n", eax
or eax, eax
jz .exit
 
1821,7 → 1834,7
.last_socket:
mov [last_socket_num], edi
mov [eax + SOCKET.Number], edi
DEBUGF 1, "SOCKET_alloc: number=%u\n", edi
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: number=%u\n", edi
 
; Fill in PID
mov ebx, [TASK_BASE]
1878,7 → 1891,7
align 4
SOCKET_free:
 
DEBUGF 1, "SOCKET_free: %x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_free: %x\n", eax
 
call SOCKET_check
jz .error
1906,7 → 1919,7
mov ebx, [eax + SOCKET.NextPtr]
mov eax, [eax + SOCKET.PrevPtr]
 
DEBUGF 1, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
 
test eax, eax
jz @f
1921,7 → 1934,7
call kernel_free
pop ebx
 
DEBUGF 1, "SOCKET_free: success!\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_free: success!\n"
 
.error:
ret
1939,7 → 1952,7
align 4
SOCKET_fork:
 
DEBUGF 1,"SOCKET_fork: %x\n", ebx
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_fork: %x\n", ebx
 
; Exit if backlog queue is full
mov eax, [ebx + SOCKET_QUEUE_LOCATION + queue.size]
1971,7 → 1984,7
.fail2:
add esp, 4+4+4
.fail:
DEBUGF 1,"SOCKET_fork: failed\n"
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_fork: failed\n"
xor eax, eax
ret
 
1990,7 → 2003,7
align 4
SOCKET_num_to_ptr:
 
DEBUGF 1,"SOCKET_num_to_ptr: num=%u ", ecx
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_num_to_ptr: num=%u ", ecx
 
mov eax, net_sockets
 
2003,11 → 2016,11
 
test eax, eax
 
DEBUGF 1,"ptr=%x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "ptr=%x\n", eax
ret
 
.error:
DEBUGF 1,"not found\n", eax
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_nuto_ptr: not found\n", eax
ret
 
 
2025,7 → 2038,7
align 4
SOCKET_ptr_to_num:
 
DEBUGF 1,"SOCKET_ptr_to_num: ptr=%x ", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_ptr_to_num: ptr=%x ", eax
 
call SOCKET_check
jz .error
2032,11 → 2045,11
 
mov eax, [eax + SOCKET.Number]
 
DEBUGF 1,"num=%u\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "num=%u\n", eax
ret
 
.error:
DEBUGF 1,"not found\n", eax
DEBUGF DEBUG_NETWORK_ERROR, "SOCKET_ptr_to_num: not found\n", eax
ret
 
 
2054,7 → 2067,7
align 4
SOCKET_check:
 
DEBUGF 1,"SOCKET_check: %x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_check: %x\n", eax
 
push ebx
mov ebx, net_sockets
2088,7 → 2101,7
align 4
SOCKET_check_owner:
 
DEBUGF 1,"SOCKET_check_owner: %x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_check_owner: %x\n", eax
 
push ebx
mov ebx, [TASK_BASE]
2116,7 → 2129,7
align 4
SOCKET_process_end:
 
DEBUGF 1, "SOCKET_process_end: %x\n", edx
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: %x\n", edx
 
push ebx
mov ebx, net_sockets
2130,7 → 2143,7
cmp [ebx + SOCKET.PID], edx
jne .next_socket
 
DEBUGF 1, "SOCKET_process_end: killing socket %x\n", ebx
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: killing socket %x\n", ebx
 
mov [ebx + SOCKET.PID], 0
mov eax, ebx
2160,7 → 2173,7
align 4
SOCKET_is_connecting:
 
DEBUGF 1,"SOCKET_is_connecting: %x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_is_connecting: %x\n", eax
 
and [eax + SOCKET.options], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING)
or [eax + SOCKET.options], SS_ISCONNECTING
2181,7 → 2194,7
align 4
SOCKET_is_connected:
 
DEBUGF 1,"SOCKET_is_connected: %x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_is_connected: %x\n", eax
 
and [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING)
or [eax + SOCKET.options], SS_ISCONNECTED
2203,7 → 2216,7
align 4
SOCKET_is_disconnecting:
 
DEBUGF 1,"SOCKET_is_disconnecting: %x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnecting: %x\n", eax
 
and [eax + SOCKET.options], not (SS_ISCONNECTING)
or [eax + SOCKET.options], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE
2224,7 → 2237,7
align 4
SOCKET_is_disconnected:
 
DEBUGF 1,"SOCKET_is_disconnected: %x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnected: %x\n", eax
 
and [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING)
or [eax + SOCKET.options], SS_CANTRCVMORE + SS_CANTSENDMORE
2257,10 → 2270,12
align 4
SOCKET_cant_recv_more:
 
DEBUGF 1,"SOCKET_cant_recv_more: %x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_cant_recv_more: %x\n", eax
 
or [eax + SOCKET.options], SS_CANTRCVMORE
 
call SOCKET_notify
 
ret
 
 
2277,8 → 2292,11
align 4
SOCKET_cant_send_more:
 
DEBUGF 1,"SOCKET_cant_send_more: %x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "SOCKET_cant_send_more: %x\n", eax
 
or [eax + SOCKET.options], SS_CANTSENDMORE
mov [eax + SOCKET.snd_proc], s_error
 
call SOCKET_notify
 
ret
/kernel/branches/Kolibri-acpi/network/stack.inc
28,6 → 28,9
net_tmr_count dw ?
endg
 
DEBUG_NETWORK_ERROR = 1
DEBUG_NETWORK_VERBOSE = 0
 
MAX_NET_DEVICES = 16
ARP_BLOCK = 1 ; true or false
 
305,12 → 308,12
align 4
NET_link_changed:
 
DEBUGF 1,"NET_link_changed device=0x%x status=0x%x\n", ebx, [ebx + NET_DEVICE.state]
DEBUGF DEBUG_NETWORK_VERBOSE, "NET_link_changed device=0x%x status=0x%x\n", ebx, [ebx + NET_DEVICE.state]
 
align 4
NET_send_event:
 
DEBUGF 1,"NET_send_event\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "NET_send_event\n"
 
; Send event to all applications
push edi ecx
340,7 → 343,7
align 4
NET_add_device:
 
DEBUGF 1,"NET_Add_Device: %x\n", ebx ;;; TODO: use mutex to lock net device list
DEBUGF DEBUG_NETWORK_VERBOSE, "NET_Add_Device: %x\n", ebx ;;; TODO: use mutex to lock net device list
 
cmp [NET_RUNNING], MAX_NET_DEVICES
jae .error
384,12 → 387,12
 
call NET_send_event
 
DEBUGF 1,"Device number: %u\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "Device number: %u\n", eax
ret
 
.error:
or eax, -1
DEBUGF 2,"Adding network device failed\n"
DEBUGF DEBUG_NETWORK_ERROR, "Adding network device failed\n"
ret
 
 
407,7 → 410,7
align 4
NET_set_default:
 
DEBUGF 1,"NET_set_default: device=%x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "NET_set_default: device=%x\n", eax
 
cmp eax, MAX_NET_DEVICES
jae .error
417,12 → 420,12
 
mov [NET_DEFAULT], eax
 
DEBUGF 1,"NET_set_default: succes\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "NET_set_default: succes\n"
ret
 
.error:
or eax, -1
DEBUGF 1,"NET_set_default: failed\n"
DEBUGF DEBUG_NETWORK_ERROR, "NET_set_default: failed\n"
ret
 
 
634,7 → 637,7
.not_zero:
xchg dl, dh
 
DEBUGF 1,"Checksum: %x\n", dx
DEBUGF DEBUG_NETWORK_VERBOSE, "Checksum: %x\n", dx
 
ret
 
/kernel/branches/Kolibri-acpi/network/tcp_input.inc
60,7 → 60,7
 
.fail:
popf
DEBUGF 2, "TCP incoming queue is full, discarding packet!\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP incoming queue is full, discarding packet!\n"
 
inc [TCP_segments_missed] ; FIXME: use correct interface
 
97,7 → 97,7
mov edi, [esi + TCP_queue_entry.ip_ptr] ; ptr to ipv4 source address, followed by ipv4 destination address
mov esi, [esi + TCP_queue_entry.segment_ptr] ; change esi last
 
DEBUGF 1,"TCP_input: size=%u time=%d\n", ecx, [timer_ticks]
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: size=%u time=%d\n", ecx, [timer_ticks]
 
mov edx, esi
 
127,7 → 127,7
movzx eax, [edx + TCP_header.DataOffset]
sub ecx, eax ; substract TCP header size from total segment size
jb .drop_no_socket ; If total segment size is less then the advertised header size, drop packet
DEBUGF 1,"TCP_input: %u bytes of data\n", ecx
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes of data\n", ecx
 
;-------------------------------------------
; Convert Big-endian values to little endian
176,7 → 176,7
test ax, ax
jnz .socket_loop
.found_socket: ; ebx now contains the socketpointer
DEBUGF 1,"TCP_input: socket ptr=%x state=%u flags=%x\n", ebx, [ebx + TCP_SOCKET.t_state], [edx + TCP_header.Flags]:2
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: socket ptr=%x state=%u flags=%x\n", ebx, [ebx + TCP_SOCKET.t_state], [edx + TCP_header.Flags]:2
 
;-------------
; update stats
197,7 → 197,7
call mutex_lock
popa
 
DEBUGF 1,"TCP_input: socket locked\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: socket locked\n"
 
;---------------------------
; disable all temporary bits
220,7 → 220,7
test [ebx + SOCKET.options], SO_ACCEPTCON
jz .no_accept
 
DEBUGF 1,"TCP_input: Accepting new connection\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Accepting new connection\n"
 
pusha
lea ecx, [ebx + SOCKET.mutex]
263,7 → 263,7
cmp ecx, sizeof.TCP_header ; Does header contain any options?
je .no_options
 
DEBUGF 1,"TCP_input: Segment has options\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Segment has options\n"
 
;;; FIXME: for LISTEN, options should be called after we determined route, we need it for MSS
;;; cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state
290,7 → 290,7
; je .opt_sack
cmp al, TCP_OPT_TIMESTAMP
je .opt_timestamp
DEBUGF 1,"TCP_input: unknown option:%u\n", al
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: unknown option:%u\n", al
jmp .no_options ; If we reach here, some unknown options were received, skip them all!
 
.opt_maxseg:
303,7 → 303,7
 
lodsw
rol ax, 8
DEBUGF 1,"TCP_input: Maxseg=%u\n", ax
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Maxseg=%u\n", ax
call TCP_mss
@@:
jmp .opt_loop
317,7 → 317,7
test [edx + TCP_header.Flags], TH_SYN
jz @f
 
DEBUGF 1,"TCP_input: Got window scale option\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Got window scale option\n"
or [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
 
lodsb
336,7 → 336,7
test [edx + TCP_header.Flags], TH_SYN
jz @f
 
DEBUGF 1,"TCP_input: Selective Acknowledgement permitted\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Selective Acknowledgement permitted\n"
or [ebx + TCP_SOCKET.t_flags], TF_SACK_PERMIT
 
@@:
348,7 → 348,7
cmp al, 10 ; length must be 10
jne .no_options
 
DEBUGF 1,"TCP_input: Got timestamp option\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Got timestamp option\n"
 
test [edx + TCP_header.Flags], TH_SYN
jz @f
372,7 → 372,7
cmp eax, [ebx + TCP_SOCKET.ts_val]
jge .no_paws
 
DEBUGF 1,"TCP_input: PAWS: detected an old segment\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: PAWS: detected an old segment\n"
 
mov eax, [esp+4+4] ; tcp_now
sub eax, [ebx + TCP_SOCKET.ts_recent_age]
450,7 → 450,7
sub eax, [ebx + TCP_SOCKET.SND_UNA]
jbe .not_uni_xfer
 
DEBUGF 1,"TCP_input: Header prediction: we are sender\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are sender\n"
 
;---------------------------------
; Packet is a pure ACK, process it
524,7 → 524,7
 
; Complete processing of received data
 
DEBUGF 1,"TCP_input: Header prediction: we are receiving %u bytes\n", ecx
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are receiving %u bytes\n", ecx
 
add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied
 
545,7 → 545,7
 
.not_uni_xfer:
 
DEBUGF 1,"TCP_input: Header prediction failed\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction failed\n"
 
; Calculate receive window size
 
558,7 → 558,7
jg @f
mov eax, edx
@@:
DEBUGF 1,"Receive window size=%d\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "Receive window size=%d\n", eax
mov [ebx + TCP_SOCKET.RCV_WND], eax
pop edx
 
579,12 → 579,12
sub eax, [edx + TCP_header.SequenceNumber]
jle .no_duplicate
 
DEBUGF 1,"TCP_input: %u bytes duplicate data!\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes duplicate data!\n", eax
 
test [edx + TCP_header.Flags], TH_SYN
jz .no_dup_syn
 
DEBUGF 1,"TCP_input: got duplicate syn\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: got duplicate syn\n"
 
and [edx + TCP_header.Flags], not (TH_SYN)
inc [edx + TCP_header.SequenceNumber]
613,7 → 613,7
 
; send an ACK and resynchronize and drop any data.
; But keep on processing for RST or ACK
DEBUGF 1, "616\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "616\n"
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
mov eax, ecx
;TODO: update stats
658,7 → 658,7
sub eax, [ebx + TCP_SOCKET.RCV_WND] ; eax now holds the number of bytes to drop
jle .no_excess_data
 
DEBUGF 1,"%d bytes beyond right edge of window\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "%d bytes beyond right edge of window\n", eax
 
;;; TODO: update stats
cmp eax, ecx
687,7 → 687,7
cmp eax, [ebx + TCP_SOCKET.RCV_NXT]
jne .drop_after_ack
 
DEBUGF 1, "690\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "690\n"
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
;;; TODO: update stats
jmp .no_excess_data
715,7 → 715,7
sub eax, ecx
jae .no_timestamp
 
DEBUGF 1,"Recording timestamp\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "Recording timestamp\n"
 
mov eax, [esp + 4] ; tcp_now
mov [ebx + TCP_SOCKET.ts_recent_age], eax
729,7 → 729,7
test [edx + TCP_header.Flags], TH_RST
jz .no_rst
 
DEBUGF 1,"TCP_input: Got an RST flag\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Got an RST flag\n"
 
mov eax, [ebx + TCP_SOCKET.t_state]
shl eax, 2
749,18 → 749,18
dd .rst_close ; TCPS_TIMED_WAIT
 
.econnrefused:
DEBUGF 1,"TCP_input: Connection refused\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Connection refused\n"
 
mov [ebx + SOCKET.errorcode], ECONNREFUSED
jmp .close
 
.econnreset:
DEBUGF 1,"TCP_input: Connection reset\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Connection reset\n"
 
mov [ebx + SOCKET.errorcode], ECONNRESET
 
.close:
DEBUGF 1,"TCP_input: Closing connection\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Closing connection\n"
 
mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
;;; TODO: update stats (tcp drops)
769,7 → 769,7
jmp .drop_no_socket
 
.rst_close:
DEBUGF 1,"TCP_input: Closing with reset\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Closing with reset\n"
 
mov eax, ebx
call TCP_close
799,7 → 799,7
jb .ack_processed ; states: closed, listen, syn_sent
ja .no_syn_rcv ; established, fin_wait_1, fin_wait_2, close_wait, closing, last_ack, time_wait
 
DEBUGF 1,"TCP_input: state=syn_received\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_received\n"
 
mov eax, [edx + TCP_header.AckNumber]
cmp [ebx + TCP_SOCKET.SND_UNA], eax
846,7 → 846,7
cmp eax, [ebx + TCP_SOCKET.SND_WND]
jne .reset_dupacks
 
DEBUGF 1,"TCP_input: Processing duplicate ACK\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Processing duplicate ACK\n"
 
; If we have outstanding data, other than a window probe, this is a completely duplicate ACK
; (window info didnt change) The ACK is the biggest we've seen and we've seen exactly our rexmt threshold of them,
927,7 → 927,7
.no_re_xmit:
jbe .not_dup_ack
 
DEBUGF 1,"TCP_input: Increasing congestion window\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Increasing congestion window\n"
 
mov eax, [ebx + TCP_SOCKET.t_maxseg]
add [ebx + TCP_SOCKET.SND_CWND], eax
980,7 → 980,7
 
;;; TODO: update stats
 
DEBUGF 1,"TCP_input: acceptable ACK for %u bytes\n", edi
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: acceptable ACK for %u bytes\n", edi
 
;------------------------------------------
; RTT measurements and retransmission timer (912-926)
1073,7 → 1073,7
call SOCKET_ring_free
pop ebx edx ecx
 
DEBUGF 1,"TCP_input: our FIN is acked\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is acked\n"
stc
 
jmp .wakeup
1088,7 → 1088,7
sub [ebx + TCP_SOCKET.SND_WND], ecx
pop edx ecx
 
DEBUGF 1,"TCP_input: our FIN is not acked\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is not acked\n"
clc
 
;----------------------------------------
1176,7 → 1176,7
align 4
.LISTEN:
 
DEBUGF 1,"TCP_input: state=listen\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: state=listen\n"
 
test [edx + TCP_header.Flags], TH_RST
jnz .drop
1228,7 → 1228,7
align 4
.SYN_SENT:
 
DEBUGF 1,"TCP_input: state=syn_sent\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_sent\n"
 
test [edx + TCP_header.Flags], TH_ACK
jz @f
1288,7 → 1288,7
test [edx + TCP_header.Flags], TH_ACK
jz .simultaneous_open
 
DEBUGF 1,"TCP_input: active open\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: active open\n"
 
;;; TODO: update stats
 
1316,7 → 1316,7
 
.simultaneous_open:
 
DEBUGF 1,"TCP_input: simultaneous open\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: simultaneous open\n"
; We have received a syn but no ACK, so we are having a simultaneous open..
mov [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
 
1339,7 → 1339,7
 
.ack_processed:
 
DEBUGF 1,"TCP_input: ACK processed\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: ACK processed\n"
 
;----------------------------------------------
; check if we need to update window information
1373,7 → 1373,7
@@:
mov [ebx + TCP_SOCKET.SND_WND], eax
 
DEBUGF 1,"TCP_input: Updating window to %u\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Updating window to %u\n", eax
 
push [edx + TCP_header.SequenceNumber]
pop [ebx + TCP_SOCKET.SND_WL1]
1467,7 → 1467,7
 
call TCP_reassemble
 
DEBUGF 1, "1470\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "1470\n"
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
 
.data_done:
1478,12 → 1478,12
test [edx + TCP_header.Flags], TH_FIN
jz .final_processing
 
DEBUGF 1,"TCP_input: Processing FIN\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Processing FIN\n"
 
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
jae .not_first_fin
 
DEBUGF 1,"TCP_input: First FIN for this connection\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: First FIN for this connection\n"
 
mov eax, ebx
call SOCKET_cant_recv_more
1534,7 → 1534,7
 
 
.drop_after_ack:
DEBUGF 1,"TCP_input: Drop after ACK\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Drop after ACK\n"
 
push edx ebx
lea ecx, [ebx + SOCKET.mutex]
1548,7 → 1548,7
jmp .need_output
 
.drop_with_reset:
DEBUGF 1,"TCP_input: Drop with reset\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Drop with reset\n"
 
push ebx edx
lea ecx, [ebx + SOCKET.mutex]
1571,7 → 1571,7
; Final processing
 
.final_processing:
DEBUGF 1,"TCP_input: Final processing\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Final processing\n"
 
push ebx
lea ecx, [ebx + SOCKET.mutex]
1583,14 → 1583,14
 
test [eax + TCP_SOCKET.t_flags], TF_ACKNOW
jz .dumpit
DEBUGF 1,"TCP_input: ACK now!\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: ACK now!\n"
 
.need_output:
DEBUGF 1,"TCP_input: need output\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: need output\n"
call TCP_output
 
.dumpit:
DEBUGF 1,"TCP_input: dumping\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: dumping\n"
 
call kernel_free
add esp, 4
1641,7 → 1641,7
; Drop
 
.drop:
DEBUGF 1,"TCP_input: Dropping segment\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Dropping segment\n"
 
pusha
lea ecx, [ebx + SOCKET.mutex]
1656,7 → 1656,7
call SOCKET_free
 
.drop_no_socket:
DEBUGF 1,"TCP_input: Drop (no socket)\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Drop (no socket)\n"
 
call kernel_free
add esp, 4
/kernel/branches/Kolibri-acpi/network/tcp_output.inc
28,7 → 28,7
align 4
TCP_output:
 
DEBUGF 1,"TCP_output: socket=%x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: socket=%x\n", eax
 
push eax
lea ecx, [eax + SOCKET.mutex]
78,7 → 78,7
cmp [eax + TCP_SOCKET.t_force], 0
je .no_force
 
DEBUGF 1,"TCP_output: forcing data out\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: forcing data out\n"
 
test ecx, ecx
jnz .no_zero_window
202,7 → 202,7
;----------------------------------------
; Check if a window update should be sent (154)
 
DEBUGF 1,"TCP_output: window=%d\n", ecx
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: window=%d\n", ecx
 
; Compare available window to amount of window known to peer (as advertised window less next expected input)
; If the difference is at least two max size segments, or at least 50% of the maximum possible window,
237,7 → 237,7
;--------------------------
; Should a segment be sent? (174)
 
DEBUGF 1,"TCP_output: 174\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: 174\n"
 
test [eax + TCP_SOCKET.t_flags], TF_ACKNOW ; we need to ACK
jnz TCP_send
273,7 → 273,7
cmp [eax + TCP_SOCKET.timer_persist], 0 ; Persist timer already expired?
jne @f
 
DEBUGF 1,"TCP_output: Entering persist state\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: Entering persist state\n"
 
mov [eax + TCP_SOCKET.t_rxtshift], 0
call TCP_set_persist
282,7 → 282,7
;----------------------------
; No reason to send a segment (219)
 
DEBUGF 1,"TCP_output: No reason to send a segment\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: No reason to send a segment\n"
 
pusha
lea ecx, [eax + SOCKET.mutex]
313,7 → 313,7
align 4
TCP_send:
 
DEBUGF 1,"TCP_send: socket=%x length=%u flags=%x\n", eax, esi, dl
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: socket=%x length=%u flags=%x\n", eax, esi, dl
 
push eax ; save socket ptr
push esi ; and data length too
337,7 → 337,7
push ecx
add di, 4
 
DEBUGF 1,"TCP_send: added maxseg option\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: added maxseg option\n"
 
test [eax + TCP_SOCKET.t_flags], TF_REQ_SCALE
jz .no_scale
355,7 → 355,7
pushw TCP_OPT_WINDOW + 3 shl 8
add di, 4
 
DEBUGF 1,"TCP_send: added scale option\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: added scale option\n"
 
.no_scale:
.no_syn:
381,7 → 381,7
pushd TCP_OPT_NOP + TCP_OPT_NOP shl 8 + TCP_OPT_TIMESTAMP shl 16 + 10 shl 24
add di, 12
 
DEBUGF 1,"TCP_send: added timestamp\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: added timestamp\n"
 
.no_timestamp:
 
538,7 → 538,7
;----------------
; Send the packet
 
DEBUGF 1,"TCP_send: Sending with device %x\n", ebx
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: Sending with device %x\n", ebx
call [ebx + NET_DEVICE.transmit]
jnz .send_error
 
580,7 → 580,7
test [eax + TCP_SOCKET.temp_bits], TCP_BIT_SENDALOT
jnz TCP_output.again
 
DEBUGF 1,"TCP_send: success!\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: success!\n"
 
xor eax, eax
ret
597,7 → 597,7
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
 
DEBUGF 1,"TCP_send: IP error\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: IP error\n"
 
or eax, -1
ret
609,7 → 609,7
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
 
DEBUGF 1,"TCP_send: sending failed\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_send: sending failed\n"
 
or eax, -2
ret
/kernel/branches/Kolibri-acpi/network/tcp_subr.inc
119,7 → 119,7
align 4
TCP_pull_out_of_band:
 
DEBUGF 1,"TCP_pull_out_of_band\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_pull_out_of_band\n"
 
;;;; 1282-1305
 
145,7 → 145,7
align 4
TCP_drop:
 
DEBUGF 1,"TCP_drop: %x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_drop: %x\n", eax
 
cmp [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
jb .no_syn_received
184,7 → 184,7
align 4
TCP_close:
 
DEBUGF 1,"TCP_close: %x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_close: %x\n", eax
 
;;; TODO: update RTT and mean deviation
;;; TODO: update slow start threshold
212,7 → 212,7
mov edx, [eax + TCP_SOCKET.t_state]
movzx edx, byte [edx + .flaglist]
 
DEBUGF 1,"TCP_outflags: socket=%x flags=%x\n", eax, dl
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_outflags: socket=%x flags=%x\n", eax, dl
 
ret
 
248,7 → 248,7
align 4
TCP_respond:
 
DEBUGF 1,"TCP_respond_socket: socket=%x flags=%x\n", ebx, cl
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_respond_socket: socket=%x flags=%x\n", ebx, cl
 
;---------------------
; Create the IP packet
305,7 → 305,7
ret
 
.error:
DEBUGF 1,"TCP_respond_socket: failed\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_respond_socket: failed\n"
add esp, 2 + 4
 
ret
327,7 → 327,7
align 4
TCP_respond_segment:
 
DEBUGF 1,"TCP_respond_segment: frame=%x flags=%x\n", edx, cl
DEBUGF DEBUG_NETWORK_VERBOSE,"TCP_respond_segment: frame=%x flags=%x\n", edx, cl
 
;---------------------
; Create the IP packet
381,7 → 381,7
ret
 
.error:
DEBUGF 1,"TCP_respond_segment: failed\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_respond_segment: failed\n"
add esp, 2+4
 
ret
416,7 → 416,7
align 4
TCP_set_persist:
 
DEBUGF 1,"TCP_set_persist\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_set_persist\n"
 
; First, check if retransmit timer is not set, retransmit and persist are mutually exclusive
 
454,7 → 454,7
align 4
TCP_xmit_timer:
 
DEBUGF 1,"TCP_xmit_timer: socket=%x rtt=%d0ms\n", ebx, eax
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_xmit_timer: socket=%x rtt=%d0ms\n", ebx, eax
 
;TODO: update stats
 
/kernel/branches/Kolibri-acpi/network/tcp_timer.inc
87,7 → 87,7
dec [eax + TCP_SOCKET.timer_retransmission]
jnz .check_more2
 
DEBUGF 1,"socket %x: Retransmission timer expired\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "socket %x: Retransmission timer expired\n", eax
 
push eax
call TCP_output
97,7 → 97,7
dec [eax + TCP_SOCKET.timer_keepalive]
jnz .check_more3
 
DEBUGF 1,"socket %x: Keepalive expired\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "socket %x: Keepalive expired\n", eax
 
cmp [eax + TCP_SOCKET.state], TCPS_ESTABLISHED
ja .dont_kill
126,13 → 126,13
dec [eax + TCP_SOCKET.timer_timed_wait]
jnz .check_more5
 
DEBUGF 1,"socket %x: 2MSL timer expired\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "socket %x: 2MSL timer expired\n", eax
 
.check_more5:
dec [eax + TCP_SOCKET.timer_persist]
jnz .loop
 
DEBUGF 1,"socket %x: persist timer expired\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "socket %x: persist timer expired\n", eax
 
call TCP_set_persist
mov [eax + TCP_SOCKET.t_force], 1
/kernel/branches/Kolibri-acpi/network/tcp_usreq.inc
27,7 → 27,7
align 4
TCP_usrclosed:
 
DEBUGF 1,"TCP_usrclosed: %x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_usrclosed: %x\n", eax
 
push ebx
mov ebx, [eax + TCP_SOCKET.t_state]
87,7 → 87,7
align 4
TCP_disconnect:
 
DEBUGF 1,"TCP_disconnect: %x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_disconnect: %x\n", eax
 
cmp [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED
jb TCP_close
/kernel/branches/Kolibri-acpi/network/udp.inc
116,7 → 116,7
align 4
UDP_input:
 
DEBUGF 1,"UDP_input: size=%u\n", ecx
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: size=%u\n", ecx
 
; First validate, checksum
 
129,7 → 129,7
jnz .checksum_mismatch
 
.no_checksum:
DEBUGF 1,"UDP_input: checksum ok\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: checksum ok\n"
 
; Convert length to little endian
 
158,7 → 158,7
cmp [eax + UDP_SOCKET.LocalPort], dx
jne .next_socket
 
DEBUGF 1,"UDP_input: socket=%x\n", eax
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: socket=%x\n", eax
 
;;; TODO: when packet is processed, check more sockets!
 
196,7 → 196,7
call mutex_lock
popa
 
DEBUGF 1,"UDP_input: new remote port=%x\n", cx ; FIXME: find a way to print big endian values with debugf
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: new remote port=%x\n", cx ; FIXME: find a way to print big endian values with debugf
mov [eax + UDP_SOCKET.RemotePort], cx
inc [eax + UDP_SOCKET.firstpacket]
 
204,12 → 204,12
 
 
.checksum_mismatch:
DEBUGF 2,"UDP_input: checksum mismatch\n"
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_input: checksum mismatch\n"
 
.dump:
call kernel_free
add esp, 4 ; pop (balance stack)
DEBUGF 2,"UDP_input: dumping\n"
DEBUGF DEBUG_NETWORK_VERBOSE,"UDP_input: dumping\n"
 
ret
 
229,13 → 229,13
align 4
UDP_output:
 
DEBUGF 1,"UDP_output: socket=%x bytes=%u data_ptr=%x\n", eax, ecx, esi
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_output: socket=%x bytes=%u data_ptr=%x\n", eax, ecx, esi
 
mov dx, [eax + UDP_SOCKET.RemotePort]
DEBUGF 1,"UDP_output: remote port=%x, ", dx ; FIXME: find a way to print big endian values with debugf
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_output: remote port=%x, ", dx ; FIXME: find a way to print big endian values with debugf
rol edx, 16
mov dx, [eax + UDP_SOCKET.LocalPort]
DEBUGF 1,"local port=%x\n", dx
DEBUGF DEBUG_NETWORK_VERBOSE, "local port=%x\n", dx
 
sub esp, 8 ; Data ptr and data size will be placed here
push edx esi
270,7 → 270,7
mov [edi + UDP_header.Checksum], 0
UDP_checksum (edi-4), (edi-8) ; FIXME: IPv4 packet could have options..
 
DEBUGF 1,"UDP_output: sending with device %x\n", ebx
DEBUGF DEBUG_NETWORK_VERBOSE, "UDP_output: sending with device %x\n", ebx
call [ebx + NET_DEVICE.transmit]
test eax, eax
jnz @f
280,7 → 280,7
ret
 
.fail:
DEBUGF 1,"UDP_output: failed\n"
DEBUGF DEBUG_NETWORK_ERROR, "UDP_output: failed\n"
add esp, 4+4+8
or eax, -1
ret