Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1772558259 | ||
|
|
bd071d588b | ||
|
|
9ec66b0eba | ||
|
|
95bcf78537 | ||
|
|
6f3cae4e0c | ||
|
|
b59e371c0e | ||
|
|
939505198f | ||
|
|
75cb80fd33 | ||
|
|
6ba901606d | ||
|
|
b1d329da2a | ||
|
|
df9946fe80 |
No files matched your search
@@ -54,3 +54,27 @@
|
||||
src: "{{ stable_artifact_path }}/"
|
||||
dest: "{{ storage_path }}/../"
|
||||
mode: preserve
|
||||
|
||||
# older builds shrink to compressed images and lose their unpacked tree; the newest few keep both
|
||||
- name: Looking for zstd on the storage server
|
||||
ansible.builtin.shell: command -v zstd
|
||||
register: zstd_present
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Requiring zstd for compaction
|
||||
ansible.builtin.assert:
|
||||
that: zstd_present.rc == 0
|
||||
fail_msg: >-
|
||||
zstd is not installed on the storage server, so older builds cannot
|
||||
be compacted. Install it and re-run this build.
|
||||
|
||||
- name: Compacting older builds
|
||||
ansible.builtin.script:
|
||||
cmd: >-
|
||||
../../utils/compact-builds.sh
|
||||
{{ storage_path | quote }}
|
||||
{{ compact_keep | default(5) | int }}
|
||||
{{ compact_max | default(10) | int }}
|
||||
register: compaction
|
||||
changed_when: "'compacted 0 of' not in compaction.stdout"
|
||||
Executable
+74
@@ -0,0 +1,74 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# SPDX-FileCopyrightText: 2026 KolibriOS team
|
||||
|
||||
# Shrink older builds on the storage server: compress their images and drop
|
||||
# their unpacked tree, which is rebuildable from the commit. sha256sums.txt
|
||||
# keeps naming the bare images, so a compacted build has to be decompressed
|
||||
# before it can be verified.
|
||||
#
|
||||
# Layout: <root>/<version>/<lang>/kolibrios-<descr>-<lang>.{img,iso,raw} -> .zst
|
||||
# <root>/<version>/<lang>/data/ -> removed
|
||||
#
|
||||
# Usage: compact-builds.sh <storage-root> [keep] [max-per-run]
|
||||
# DRY_RUN=1 walks the same selection and changes nothing
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
root=${1:?storage root required}
|
||||
# the build just published is always among these, so an upload in flight is safe
|
||||
keep=${2:-5}
|
||||
# a build is hundreds of MiB to re-compress: cap the first pass over the backlog
|
||||
max=${3:-10}
|
||||
dry=${DRY_RUN:-0}
|
||||
verb=compacted
|
||||
[ "$dry" = 1 ] && verb="would compact"
|
||||
|
||||
# --rm drops the source only once the archive is written; the box serves the
|
||||
# site over NFS, so compaction yields to it
|
||||
compress_image() {
|
||||
nice -n 10 ionice -c3 zstd -12 -T1 -q --rm "$1"
|
||||
}
|
||||
export -f compress_image
|
||||
|
||||
leftovers() {
|
||||
local build=$1
|
||||
find "$build" -mindepth 2 -maxdepth 2 \
|
||||
\( -type d -name data \
|
||||
-o -type f \( -name '*.img' -o -name '*.iso' -o -name '*.raw' \) \) \
|
||||
-print -quit
|
||||
}
|
||||
|
||||
compacted=0
|
||||
pending=0
|
||||
|
||||
while IFS= read -r version; do
|
||||
dir="$root/$version"
|
||||
[ -n "$(leftovers "$dir")" ] || continue
|
||||
|
||||
pending=$((pending + 1))
|
||||
[ "$compacted" -lt "$max" ] || continue
|
||||
|
||||
if [ "$dry" = 1 ]; then
|
||||
compacted=$((compacted + 1))
|
||||
echo "$verb $version"
|
||||
continue
|
||||
fi
|
||||
|
||||
# a build holds nine images: one per core, each zstd kept to one thread so
|
||||
# the two levels of parallelism do not fight. Archive before dropping the
|
||||
# tree, so a failure here leaves the build merely uncompacted and the next
|
||||
# run picks it up again
|
||||
find "$dir" -mindepth 2 -maxdepth 2 -type f \
|
||||
\( -name '*.img' -o -name '*.iso' -o -name '*.raw' \) -print0 \
|
||||
| xargs -0 -r -P "$(nproc)" -I{} bash -c 'compress_image "$@"' _ {}
|
||||
|
||||
find "$dir" -mindepth 2 -maxdepth 2 -type d -name data -exec rm -rf {} +
|
||||
|
||||
compacted=$((compacted + 1))
|
||||
echo "$verb $version"
|
||||
# <tag>-<commit count>-g<sha>: order by the count, never by mtime
|
||||
done < <(find "$root" -mindepth 1 -maxdepth 1 -type d -name '*-*-g*' -printf '%f\n' \
|
||||
| sort -t- -k2,2n | head -n "-$keep")
|
||||
|
||||
echo "$verb $compacted of $pending older build(s), $((pending - compacted)) left for the next run"
|
||||
@@ -34,10 +34,11 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
token: ${{ secrets.BOT_TOKEN }}
|
||||
|
||||
- name: Bump ${{ matrix.name }} and open PR
|
||||
env:
|
||||
TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
TOKEN: ${{ secrets.BOT_TOKEN }}
|
||||
API: ${{ github.api_url }}
|
||||
REPO: ${{ github.repository }}
|
||||
NAME: ${{ matrix.name }}
|
||||
|
||||
@@ -427,6 +427,7 @@ tup.append_table(img_files, {
|
||||
{"DEFAULT.SKN", VAR_SKINS .. "/../skins/Leency/Shkvorka/Shkvorka.skn"},
|
||||
{"DISPTEST", VAR_PROGS .. "/testing/disptest/disptest"},
|
||||
{"END", VAR_PROGS .. "/system/end/light/end"},
|
||||
{"ESKIN", VAR_PROGS .. "/system/eskin/eskin"},
|
||||
{"GMON", VAR_PROGS .. "/system/gmon/gmon"},
|
||||
{"HDD_INFO", VAR_PROGS .. "/system/hdd_info/hdd_info"},
|
||||
{"KBD", VAR_PROGS .. "/testing/kbd/kbd"},
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
/SYS/SETUP BOOT 0 # Load device settings
|
||||
/SYS/LOADDRV I2CHID 0 # Start I2C touchpad driver
|
||||
/SYS/@TASKBAR "" 0 # Start taskbar
|
||||
/SYS/ESKIN "" 0 # Set style
|
||||
/SYS/@ICON "" 0 # Multithread desktop icons
|
||||
/SYS/TMPDISK A0 0 # Add virtual RAM disk /tmp0/1
|
||||
/SYS/@RESHARE "" 0 # Shared resources
|
||||
|
||||
@@ -3,6 +3,7 @@ language=en
|
||||
font file=/sys/Fonts/Tahoma.kf
|
||||
font smoothing=sbp
|
||||
font height=9
|
||||
speaker mute=off
|
||||
|
||||
[touchpad]
|
||||
speed=100
|
||||
@@ -28,7 +29,6 @@ double_click_delay=64
|
||||
[low-level]
|
||||
LBA=off
|
||||
PCI=on
|
||||
speaker=on
|
||||
|
||||
;timeout in minutes
|
||||
;program needs a full path
|
||||
|
||||
@@ -20,6 +20,7 @@ disptest;
|
||||
docpack;Документация / Блок документов;asm;http://git.kolibrios.org/KolibriOS/kolibrios/src/branch/main/programs/system/docpack;;http://wiki.kolibrios.org/wiki/Docpack/ru
|
||||
easyshot;Простой скриншотер;c--;http://git.kolibrios.org/KolibriOS/kolibrios/src/branch/main/programs/cmm/misc/easyshot.c;http://board.kolibrios.org/viewtopic.php?t=3695;
|
||||
end;Программа завершения работы;asm;http://git.kolibrios.org/KolibriOS/kolibrios/src/branch/main/programs/system/end;http://board.kolibrios.org/viewtopic.php?t=2442;http://wiki.kolibrios.org/wiki/End/ru
|
||||
eskin;Установщик фона и скина при старте системы;asm;http://git.kolibrios.org/KolibriOS/kolibrios/src/branch/main/programs/system/eskin;http://board.kolibrios.org/viewtopic.php?t=2424;
|
||||
fb2read;Читалка FB2;oberon07;http://git.kolibrios.org/KolibriOS/kolibrios/src/branch/main/programs/other/fb2reader;http://board.kolibrios.org/viewtopic.php?t=3128;
|
||||
fspeed;Тестирование скорости диска;asm;http://git.kolibrios.org/KolibriOS/kolibrios/src/branch/main/programs/testing/fspeed;http://board.kolibrios.org/viewtopic.php?t=2660;
|
||||
gmon;Информация о загрузке системы;asm;http://git.kolibrios.org/KolibriOS/kolibrios/src/branch/main/programs/system/gmon;http://board.kolibrios.org/viewtopic.php?t=470;http://wiki.kolibrios.org/wiki/Gmon/ru
|
||||
|
||||
|
+100
-14
@@ -130,6 +130,8 @@ RU_STATUS_IDLE = 0000b shl 2
|
||||
RU_STATUS_SUSPENDED = 0001b shl 2
|
||||
RU_STATUS_NO_RESOURCES = 0010b shl 2
|
||||
RU_STATUS_READY = 0100b shl 2
|
||||
SCB_STATUS_CUS = 11000000b ; CU Status
|
||||
CU_STATUS_ACTIVE = 10b shl 6
|
||||
SCB_STATUS_FCP = 1 shl 8 ; Flow Control Pause
|
||||
SCB_STATUS_SWI = 1 shl 10 ; Software Interrupt
|
||||
SCB_STATUS_MDI = 1 shl 11 ; MDI read/write complete
|
||||
@@ -183,6 +185,8 @@ struct txfd
|
||||
|
||||
ends
|
||||
|
||||
TXFD_STATUS_C = 1 shl 15
|
||||
|
||||
TXFD_CMD_IA = 1 shl 0
|
||||
TXFD_CMD_CFG = 1 shl 1
|
||||
TXFD_CMD_TX = 1 shl 2
|
||||
@@ -628,6 +632,9 @@ reset:
|
||||
mov ax, CU_START or INT_MASK
|
||||
out dx, ax
|
||||
call cmd_wait
|
||||
; cmd_wait only means the SCB accepted the command. The Configure below
|
||||
; reuses confcmd, so a slow chip would read it instead of our MAC.
|
||||
call confcmd_wait
|
||||
|
||||
;-------------
|
||||
; Configure CU
|
||||
@@ -652,6 +659,7 @@ reset:
|
||||
mov ax, CU_START ; expect Interrupts from now on
|
||||
out dx, ax
|
||||
call cmd_wait
|
||||
call confcmd_wait
|
||||
|
||||
; Start media check timer
|
||||
mov [ebx + device.state], ETH_LINK_DOWN
|
||||
@@ -678,6 +686,11 @@ init_rx_ring:
|
||||
;---------------------
|
||||
; build rxfd structure
|
||||
|
||||
cmp [ebx + device.rx_desc], 0 ; the RFD of an earlier reset
|
||||
je @f
|
||||
invoke NetFree, [ebx + device.rx_desc]
|
||||
mov [ebx + device.rx_desc], 0
|
||||
@@:
|
||||
invoke NetAlloc, 2000
|
||||
test eax, eax
|
||||
jz .out_of_mem
|
||||
@@ -689,6 +702,7 @@ init_rx_ring:
|
||||
mov [esi + sizeof.NET_BUFF + rxfd.command], RXFD_CMD_EL or RXFD_CMD_SUSPEND
|
||||
mov [esi + sizeof.NET_BUFF + rxfd.link], eax
|
||||
mov [esi + sizeof.NET_BUFF + rxfd.count], 0
|
||||
mov [esi + sizeof.NET_BUFF + rxfd.rx_buf_addr], 0xffffffff ; simplified mode, no RBD
|
||||
mov [esi + sizeof.NET_BUFF + rxfd.size], 1528
|
||||
|
||||
ret
|
||||
@@ -709,6 +723,15 @@ init_tx_ring:
|
||||
invoke GetPhysAddr
|
||||
mov ecx, TX_RING_SIZE
|
||||
.next_desc:
|
||||
; after a reset with frames still unreclaimed: free them, or transmit sees the
|
||||
; descriptor busy (virt_addr) and reports TX overrun forever
|
||||
cmp [esi + txfd.virt_addr], 0
|
||||
je @f
|
||||
push eax ecx
|
||||
invoke NetFree, [esi + txfd.virt_addr]
|
||||
pop ecx eax
|
||||
mov [esi + txfd.virt_addr], 0
|
||||
@@:
|
||||
mov [esi + txfd.status], 0
|
||||
mov [esi + txfd.command], 0
|
||||
lea edx, [eax + txfd.buf_addr]
|
||||
@@ -763,7 +786,7 @@ proc transmit stdcall bufferptr
|
||||
lea edi, [ebx + device.tx_ring + eax]
|
||||
|
||||
; Check if current descriptor is free or still in use
|
||||
cmp [edi + txfd.status], 0
|
||||
cmp [edi + txfd.virt_addr], 0 ; buffer not reclaimed yet
|
||||
jne .overrun
|
||||
|
||||
; Fill in status and command values
|
||||
@@ -786,6 +809,22 @@ proc transmit stdcall bufferptr
|
||||
mov eax, edi
|
||||
invoke GetPhysAddr
|
||||
set_io [ebx + device.io_addr], 0
|
||||
|
||||
; CU_START is only valid while the CU is idle or suspended:
|
||||
; wait for the previous frame to leave (1.2 ms at 10 Mbit)
|
||||
push eax ecx
|
||||
set_io [ebx + device.io_addr], REG_SCB_STATUS
|
||||
mov ecx, 100000
|
||||
.cu_busy:
|
||||
in al, dx
|
||||
and al, SCB_STATUS_CUS
|
||||
cmp al, CU_STATUS_ACTIVE
|
||||
jne .cu_free
|
||||
dec ecx
|
||||
jnz .cu_busy
|
||||
DEBUGF 2, "CU still active, starting anyway\n"
|
||||
.cu_free:
|
||||
pop ecx eax
|
||||
set_io [ebx + device.io_addr], REG_SCB_PTR
|
||||
out dx, eax
|
||||
|
||||
@@ -854,7 +893,7 @@ int_handler:
|
||||
|
||||
DEBUGF 1,"Status: %x\n", ax
|
||||
|
||||
test ax, SCB_STATUS_FR ; did we receive a frame?
|
||||
test ax, SCB_STATUS_FR or SCB_STATUS_RNR ; frame received or receiver stopped?
|
||||
jz .no_rx
|
||||
|
||||
push ax
|
||||
@@ -901,6 +940,7 @@ int_handler:
|
||||
mov [esi + sizeof.NET_BUFF + rxfd.command], RXFD_CMD_EL or RXFD_CMD_SUSPEND
|
||||
mov [esi + sizeof.NET_BUFF + rxfd.link], eax
|
||||
mov [esi + sizeof.NET_BUFF + rxfd.count], 0
|
||||
mov [esi + sizeof.NET_BUFF + rxfd.rx_buf_addr], 0xffffffff ; simplified mode, no RBD
|
||||
mov [esi + sizeof.NET_BUFF + rxfd.size], 1528
|
||||
|
||||
; restart RX
|
||||
@@ -916,11 +956,22 @@ int_handler:
|
||||
mov ax, RX_START
|
||||
out dx, ax
|
||||
call cmd_wait
|
||||
.out_of_mem:
|
||||
|
||||
; Hand the frame over to the kernel
|
||||
jmp [EthInput]
|
||||
|
||||
.out_of_mem:
|
||||
; The buffer is still our only RFD: drop the frame and reuse it
|
||||
mov esi, [esp] ; the buffer
|
||||
mov ecx, [esi + NET_BUFF.length]
|
||||
dec [ebx + device.packets_rx] ; counted above, before the allocation
|
||||
sub dword [ebx + device.bytes_rx], ecx
|
||||
sbb dword [ebx + device.bytes_rx + 4], 0
|
||||
inc [ebx + device.packets_rx_drop]
|
||||
add esp, 12 ; buffer, .rx_loop, ebx
|
||||
mov esi, [ebx + device.rx_desc]
|
||||
jmp .not_ok
|
||||
|
||||
.not_ok:
|
||||
; Reset the FD
|
||||
mov [esi + sizeof.NET_BUFF + rxfd.status], 0
|
||||
@@ -945,6 +996,27 @@ int_handler:
|
||||
|
||||
.no_rx_:
|
||||
DEBUGF 1, "no more data\n"
|
||||
|
||||
; With a single RFD the receiver sits in No Resources/Suspended whenever a
|
||||
; frame arrived before we re-armed it. Nothing restarts it but us.
|
||||
set_io [ebx + device.io_addr], 0
|
||||
set_io [ebx + device.io_addr], REG_SCB_STATUS
|
||||
in al, dx
|
||||
and al, SCB_STATUS_RUS
|
||||
cmp al, RU_STATUS_READY
|
||||
je .ru_ready
|
||||
test byte[esp], 1 ; bit 0 of the saved status is reserved,
|
||||
jnz .ru_ready ; we mark it: one restart per IRQ
|
||||
or byte[esp], 1
|
||||
movzx eax, al
|
||||
DEBUGF 1, "Restarting receiver, RU status %x\n", eax:2
|
||||
mov esi, [ebx + device.rx_desc]
|
||||
push ebx
|
||||
test [esi + sizeof.NET_BUFF + rxfd.status], RXFD_STATUS_C
|
||||
jnz .rx_loop ; a frame completed meanwhile
|
||||
add esp, 4
|
||||
jmp .not_ok ; re-arm the empty RFD
|
||||
.ru_ready:
|
||||
pop ax
|
||||
|
||||
.no_rx:
|
||||
@@ -955,13 +1027,13 @@ int_handler:
|
||||
|
||||
push eax
|
||||
.loop_tx:
|
||||
mov edi, [ebx + device.last_tx]
|
||||
mov eax, sizeof.txfd
|
||||
mul eax
|
||||
mov eax, [ebx + device.last_tx]
|
||||
mov edx, sizeof.txfd
|
||||
mul edx
|
||||
lea edi, [ebx + device.tx_ring + eax]
|
||||
|
||||
cmp [edi + txfd.status], 0
|
||||
je .tx_done
|
||||
test [edi + txfd.status], TXFD_STATUS_C ; sent by the device?
|
||||
jz .tx_done
|
||||
|
||||
cmp [edi + txfd.virt_addr], 0
|
||||
je .tx_done
|
||||
@@ -970,6 +1042,7 @@ int_handler:
|
||||
|
||||
push [edi + txfd.virt_addr]
|
||||
mov [edi + txfd.virt_addr], 0
|
||||
mov [edi + txfd.status], 0 ; free for transmit again
|
||||
invoke NetFree
|
||||
|
||||
inc [ebx + device.last_tx]
|
||||
@@ -980,12 +1053,6 @@ int_handler:
|
||||
pop eax
|
||||
.no_tx:
|
||||
|
||||
test ax, RU_STATUS_NO_RESOURCES
|
||||
jz .not_out_of_resources
|
||||
|
||||
DEBUGF 2, "Out of resources!\n"
|
||||
|
||||
.not_out_of_resources:
|
||||
pop edi esi ebx
|
||||
xor eax, eax
|
||||
inc eax
|
||||
@@ -1079,6 +1146,25 @@ proc check_media_mii stdcall dev:dword
|
||||
endp
|
||||
|
||||
|
||||
; Wait (up to 1 s) until the device has executed the command in confcmd.
|
||||
align 4
|
||||
confcmd_wait:
|
||||
mov ecx, 1000 ; udelay = Sleep(1), 1 ms
|
||||
.loop:
|
||||
test [ebx + device.confcmd.status], TXFD_STATUS_C
|
||||
jnz .done
|
||||
call udelay
|
||||
dec ecx
|
||||
jnz .loop
|
||||
movzx eax, [ebx + device.confcmd.command]
|
||||
DEBUGF 2, "Command 0x%x not completed\n", eax:4
|
||||
ret
|
||||
.done:
|
||||
movzx eax, [ebx + device.confcmd.command]
|
||||
movzx ecx, [ebx + device.confcmd.status]
|
||||
DEBUGF 1, "Command 0x%x done, status 0x%x\n", eax:4, ecx:4
|
||||
ret
|
||||
|
||||
align 4
|
||||
cmd_wait:
|
||||
|
||||
|
||||
+604
-74
@@ -38,10 +38,7 @@ DEBUG = 1
|
||||
__DEBUG__ = 1
|
||||
__DEBUG_LEVEL__ = 2 ; 1 = verbose, 2 = errors/events only
|
||||
|
||||
; 1 = print per-second RX/TX rate statistics to the debug board while
|
||||
; traffic flows (cb/fr = transfers/frames, B = bytes, tx = frames sent,
|
||||
; wnd = advertised TCP window). Costs a few counters per frame and one
|
||||
; line of board output per second; invaluable for throughput debugging.
|
||||
; 1 = per-second RX/TX counters and a frame log on the debug board
|
||||
DEBUG_STATS = 0
|
||||
|
||||
include '../../struct.inc'
|
||||
@@ -84,6 +81,9 @@ OID_GEN_CURRENT_PACKET_FILTER = 0x0001010E
|
||||
|
||||
; NDIS packet filter: directed | multicast | all-multicast | broadcast
|
||||
RNDIS_PACKET_FILTER = 0x0000000F
|
||||
; With a host address of our own choosing (see random_mac) also
|
||||
; promiscuous, as Linux always sets: the device never learns that address.
|
||||
RNDIS_FILTER_PROMISC = 0x00000020
|
||||
|
||||
RNDIS_STATUS_MEDIA_CONNECT = 0x4001000B
|
||||
RNDIS_STATUS_MEDIA_DISCONNECT = 0x4001000C
|
||||
@@ -98,13 +98,32 @@ STATE_RUN = 4 ; registered, data path live
|
||||
ETH_FRAME_MIN = 60 ; minimal ethernet frame (without FCS)
|
||||
ETH_FRAME_MAX = 1514 ; maximal ethernet frame (without FCS)
|
||||
RNDIS_HDR_SIZE = 44 ; REMOTE_NDIS_PACKET_MSG header
|
||||
RNDIS_RX_BUF = 8192 ; our max transfer, advertised in INIT
|
||||
RNDIS_RX_BUFFERS = 2 ; ping-pong pair for the bulk IN pipe
|
||||
; Our MaxTransferSize and the RX buffer size: one frame, as in Linux.
|
||||
; With 8192 phones split messages across transfers and we lost them.
|
||||
RNDIS_RX_BUF = 2048
|
||||
; Bulk IN transfers kept in flight: up to 32 frames per 10 ms wakeup
|
||||
; of the USB thread (~38 Mbit/s). See the note in rndis_start.
|
||||
RNDIS_RX_BUFFERS = 32
|
||||
RNDIS_RX_MAX_ERRORS = 32 ; consecutive RX errors before receive
|
||||
; stops (anti retry-storm)
|
||||
; The same for the interrupt IN pipe (was an endless retry storm).
|
||||
RNDIS_NOTIFY_MAX_ERRORS = 16
|
||||
RNDIS_RSP_BUF = 1024 ; encapsulated response buffer
|
||||
RNDIS_TX_MAX_PENDING = 32 ; max messages in flight on bulk OUT
|
||||
RNDIS_QUERY_LEN = 28 + 48 ; QUERY_MSG with a 48-byte input buffer,
|
||||
; what Linux rndis_host sends; also the
|
||||
; size of CmdBuf, the longest command
|
||||
; Bulk OUT messages in flight, each in a slot of a preallocated pool
|
||||
; (Kmalloc's 128 KB heap ran out). TX completions wait up to 10 ms for
|
||||
; the USB thread, and 96 slots were still exhausted during uploads.
|
||||
; A 2 KB slot never crosses a page, so 192 TRBs fit the 256-entry ring.
|
||||
RNDIS_TX_MAX_PENDING = 192 ; slots, a multiple of 32 (free bitmap)
|
||||
RNDIS_TX_SLOT = 2048 ; [context ptr][message <= 1559 bytes]
|
||||
RNDIS_FLOWS = 8 ; TCP flows tracked by DEBUG_STATS (power of 2)
|
||||
RNDIS_LOG_BURST = 40 ; frame-log lines allowed per second (DEBUG_STATS)
|
||||
RNDIS_GET_RETRIES = 200 ; response polls per command (see below)
|
||||
; 1/100 s to wait for MEDIA_CONNECT before taking the link as up.
|
||||
; A phone just switched to tethering drops the first DHCP DISCOVER.
|
||||
RNDIS_LINK_WAIT = 100
|
||||
|
||||
; USB structures
|
||||
struct usb_descr
|
||||
@@ -177,6 +196,8 @@ struct rndis_dev ETH_DEVICE
|
||||
InitState dd ? ; STATE_* of the init chain
|
||||
DevMaxTx dd ? ; device's max transfer (from INIT_C)
|
||||
LinkDown dd ? ; a MEDIA_DISCONNECT was indicated
|
||||
LinkKnown dd ? ; the device has indicated its media state
|
||||
LinkTimer dd ? ; TimerHS handle of the link-up fallback
|
||||
|
||||
TxPending dd ? ; messages in flight on bulk OUT
|
||||
Dead dd ? ; set on disconnect/fatal error
|
||||
@@ -187,9 +208,16 @@ struct rndis_dev ETH_DEVICE
|
||||
KaPending dd ? ; a keepalive reply is in flight
|
||||
GetRetries dd ? ; polls left for the current command
|
||||
|
||||
RxBufs rd RNDIS_RX_BUFFERS ; bulk IN buffers (KernelAlloc)
|
||||
RxArea dd ? ; one KernelAlloc holding all RX buffers
|
||||
RxBufs rd RNDIS_RX_BUFFERS ; bulk IN buffers, slices of RxArea
|
||||
RxSize dd ? ; size of one buffer
|
||||
TxArea dd ? ; KernelAlloc'ed pool of TX slots
|
||||
TxFree rd RNDIS_TX_MAX_PENDING/32 ; bit set = slot free
|
||||
RxErrRun dd ? ; consecutive failed RX transfers
|
||||
NotifyErrRun dd ? ; consecutive failed notification polls
|
||||
RxArmed dd ? ; transfers outstanding on the bulk IN
|
||||
; pipe; zero means receive has died
|
||||
LenErrNoted dd ? ; refused-frame lengths already logged
|
||||
|
||||
; per-second statistics, only maintained when DEBUG_STATS = 1
|
||||
StatTicks dd ? ; last print time, timer ticks
|
||||
@@ -199,11 +227,24 @@ struct rndis_dev ETH_DEVICE
|
||||
StatTxPkts dd ? ; packets_tx snapshot at last print
|
||||
StatWnd dd ? ; TCP receive window we advertised
|
||||
; in the last outgoing TCP frame
|
||||
StatTxHigh dd ? ; deepest the bulk OUT queue has been
|
||||
StatTail dd ? ; received bytes no frame was made of
|
||||
StatRxUni dd ? ; frames received addressed to our MAC
|
||||
StatRxBc dd ? ; frames received as broadcast/multicast
|
||||
LogTicks dd ? ; start of the current frame-log second
|
||||
LogCount dd ? ; frame-log lines printed in it
|
||||
StatLogDrop dd ? ; frame-log lines suppressed by the limit
|
||||
StatGap dd ? ; TCP segments that arrived beyond a
|
||||
; hole in their flow (loss/reorder)
|
||||
StatRetx dd ? ; TCP segments with data already seen
|
||||
; (the peer retransmitting)
|
||||
FlowNext dd ? ; next slot of Flows to recycle
|
||||
Flows rd RNDIS_FLOWS*2 ; [key][next expected seq]
|
||||
|
||||
SetupCmd rb 8 ; setup packet: SEND_ENCAPSULATED_CMD
|
||||
SetupRsp rb 8 ; setup packet: GET_ENCAPSULATED_RSP
|
||||
SetupKa rb 8 ; setup packet: keepalive reply
|
||||
CmdBuf rb 64 ; init chain command messages
|
||||
CmdBuf rb RNDIS_QUERY_LEN ; init chain command messages
|
||||
KaBuf rb 16 ; keepalive reply message
|
||||
NotifBuf rb 16 ; interrupt notification buffer
|
||||
RspBuf rb RNDIS_RSP_BUF ; encapsulated responses
|
||||
@@ -239,6 +280,18 @@ proc START c, reason:dword, cmdline:dword
|
||||
jne .nothing
|
||||
|
||||
DEBUGF 2,"loading (RNDIS host network driver)\n"
|
||||
|
||||
; one random host address per boot (see random_mac)
|
||||
rdtsc
|
||||
xor eax, edx
|
||||
imul eax, eax, 0x9E3779B1
|
||||
mov dword [random_mac], eax
|
||||
imul eax, eax, 0x85EBCA6B
|
||||
rol eax, 13
|
||||
mov word [random_mac+4], ax
|
||||
and byte [random_mac], 0xFE ; unicast
|
||||
or byte [random_mac], 0x02 ; locally administered
|
||||
|
||||
invoke RegUSBDriver, my_service, service_proc, usb_functions
|
||||
|
||||
.nothing:
|
||||
@@ -693,7 +746,16 @@ proc rndis_notify_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword,
|
||||
cmp [.status], USB_STATUS_STALL
|
||||
je .ret ; don't hammer a stalled pipe
|
||||
cmp [.status], 0
|
||||
jne .rearm ; transient error: retry
|
||||
je .status_ok
|
||||
; transient error: retry, but not for ever
|
||||
inc [ebx+rndis_dev.NotifyErrRun]
|
||||
cmp [ebx+rndis_dev.NotifyErrRun], RNDIS_NOTIFY_MAX_ERRORS
|
||||
jb .rearm
|
||||
DEBUGF 2,"notification pipe stopped after %u errors (status %u)\n", \
|
||||
[ebx+rndis_dev.NotifyErrRun], [.status]
|
||||
ret
|
||||
.status_ok:
|
||||
mov [ebx+rndis_dev.NotifyErrRun], 0
|
||||
|
||||
cmp [.length], 8
|
||||
jb .rearm
|
||||
@@ -763,17 +825,23 @@ proc rndis_response_callback stdcall uses ebx esi edi, .pipe:dword, .status:dwor
|
||||
mov [ebx+rndis_dev.DevMaxTx], eax
|
||||
DEBUGF 2,"initialized, device max transfer %u\n", eax
|
||||
|
||||
; query the permanent MAC address
|
||||
; query the permanent MAC address, with an unused input buffer as Linux
|
||||
; sends it: QEMU's usb-net stalls a query without one
|
||||
lea edi, [ebx+rndis_dev.CmdBuf]
|
||||
push edi
|
||||
xor eax, eax
|
||||
mov ecx, RNDIS_QUERY_LEN / 4
|
||||
rep stosd
|
||||
pop edi
|
||||
mov dword [edi], RNDIS_MSG_QUERY
|
||||
mov dword [edi+4], 28 ; MessageLength
|
||||
mov dword [edi+4], RNDIS_QUERY_LEN ; MessageLength
|
||||
mov dword [edi+8], 2 ; RequestID
|
||||
mov dword [edi+12], OID_802_3_PERMANENT_ADDRESS
|
||||
mov dword [edi+16], 0 ; InformationBufferLength
|
||||
mov dword [edi+16], RNDIS_QUERY_LEN - 28 ; InformationBufferLength
|
||||
mov dword [edi+20], 20 ; InformationBufferOffset
|
||||
mov dword [edi+24], 0 ; DeviceVcHandle
|
||||
mov [ebx+rndis_dev.InitState], STATE_MAC
|
||||
mov eax, 28
|
||||
mov eax, RNDIS_QUERY_LEN
|
||||
call rndis_send_command
|
||||
test eax, eax
|
||||
jz .fail
|
||||
@@ -804,6 +872,24 @@ proc rndis_response_callback stdcall uses ebx esi edi, .pipe:dword, .status:dwor
|
||||
[ebx+rndis_dev.mac+0]:2,[ebx+rndis_dev.mac+1]:2,[ebx+rndis_dev.mac+2]:2,\
|
||||
[ebx+rndis_dev.mac+3]:2,[ebx+rndis_dev.mac+4]:2,[ebx+rndis_dev.mac+5]:2
|
||||
|
||||
; A locally administered address is the same on every plug-in, so each
|
||||
; boot repeated the previous boot's connections into stale phone NAT
|
||||
; state. Replace it with a random one per boot, as Linux does.
|
||||
mov edx, RNDIS_PACKET_FILTER
|
||||
test byte [ebx+rndis_dev.mac], 0x02
|
||||
jz .mac_done
|
||||
mov eax, dword [random_mac]
|
||||
mov dword [ebx+rndis_dev.mac], eax
|
||||
mov ax, word [random_mac+4]
|
||||
mov word [ebx+rndis_dev.mac+4], ax
|
||||
or edx, RNDIS_FILTER_PROMISC
|
||||
push edx
|
||||
DEBUGF 2,"using random MAC %x-%x-%x-%x-%x-%x\n",\
|
||||
[ebx+rndis_dev.mac+0]:2,[ebx+rndis_dev.mac+1]:2,[ebx+rndis_dev.mac+2]:2,\
|
||||
[ebx+rndis_dev.mac+3]:2,[ebx+rndis_dev.mac+4]:2,[ebx+rndis_dev.mac+5]:2
|
||||
pop edx
|
||||
.mac_done:
|
||||
|
||||
; enable reception: set the packet filter
|
||||
lea edi, [ebx+rndis_dev.CmdBuf]
|
||||
mov dword [edi], RNDIS_MSG_SET
|
||||
@@ -813,7 +899,7 @@ proc rndis_response_callback stdcall uses ebx esi edi, .pipe:dword, .status:dwor
|
||||
mov dword [edi+16], 4 ; InformationBufferLength
|
||||
mov dword [edi+20], 20 ; InformationBufferOffset
|
||||
mov dword [edi+24], 0 ; DeviceVcHandle
|
||||
mov dword [edi+28], RNDIS_PACKET_FILTER
|
||||
mov dword [edi+28], edx
|
||||
mov [ebx+rndis_dev.InitState], STATE_FILTER
|
||||
mov eax, 32
|
||||
call rndis_send_command
|
||||
@@ -864,11 +950,13 @@ proc rndis_response_callback stdcall uses ebx esi edi, .pipe:dword, .status:dwor
|
||||
je .media_up
|
||||
cmp eax, RNDIS_STATUS_MEDIA_DISCONNECT
|
||||
jne .done
|
||||
mov [ebx+rndis_dev.LinkKnown], 1
|
||||
mov [ebx+rndis_dev.LinkDown], 1
|
||||
mov [ebx+rndis_dev.state], ETH_LINK_DOWN
|
||||
DEBUGF 2,"link down\n"
|
||||
jmp .media_changed
|
||||
.media_up:
|
||||
mov [ebx+rndis_dev.LinkKnown], 1
|
||||
mov [ebx+rndis_dev.LinkDown], 0
|
||||
mov [ebx+rndis_dev.state], ETH_LINK_SPEED_10M or ETH_LINK_FULL_DUPLEX
|
||||
DEBUGF 2,"link up\n"
|
||||
@@ -926,6 +1014,28 @@ proc rndis_response_callback stdcall uses ebx esi edi, .pipe:dword, .status:dwor
|
||||
|
||||
endp
|
||||
|
||||
; The link-up fallback (see RNDIS_LINK_WAIT): the device said nothing
|
||||
; about its media in time, take the link as up. Runs from the kernel's
|
||||
; timer list, the context is the one given to TimerHS.
|
||||
proc rndis_link_timer stdcall uses ebx, .ctx:dword
|
||||
|
||||
mov ebx, [.ctx]
|
||||
mov [ebx+rndis_dev.LinkTimer], 0
|
||||
cmp [ebx+rndis_dev.Dead], 0
|
||||
jne .ret
|
||||
cmp [ebx+rndis_dev.LinkKnown], 0
|
||||
jne .ret ; the device spoke meanwhile
|
||||
mov [ebx+rndis_dev.LinkKnown], 1
|
||||
DEBUGF 2,"no media indication, assuming link up\n"
|
||||
mov [ebx+rndis_dev.state], ETH_LINK_SPEED_10M or ETH_LINK_FULL_DUPLEX
|
||||
push ebx
|
||||
invoke NetLinkChanged
|
||||
pop ebx
|
||||
.ret:
|
||||
ret
|
||||
|
||||
endp
|
||||
|
||||
; Init chain complete: allocate the receive buffers, register in the
|
||||
; network stack, bring the link up and start receiving.
|
||||
; IN: ebx = device context
|
||||
@@ -934,15 +1044,32 @@ proc rndis_start
|
||||
mov [ebx+rndis_dev.InitState], STATE_RUN
|
||||
mov [ebx+rndis_dev.RxSize], RNDIS_RX_BUF
|
||||
|
||||
xor edi, edi
|
||||
.alloc_loop:
|
||||
invoke KernelAlloc, RNDIS_RX_BUF
|
||||
; All receive buffers come from one page-aligned block: a 2 KB slice of
|
||||
; it never crosses a page, so every transfer is a single TRB.
|
||||
invoke KernelAlloc, RNDIS_RX_BUF * RNDIS_RX_BUFFERS
|
||||
test eax, eax
|
||||
jz .fail
|
||||
mov [ebx+rndis_dev.RxArea], eax
|
||||
xor edi, edi
|
||||
.slice_loop:
|
||||
mov [ebx+rndis_dev.RxBufs+edi*4], eax
|
||||
add eax, RNDIS_RX_BUF
|
||||
inc edi
|
||||
cmp edi, RNDIS_RX_BUFFERS
|
||||
jb .alloc_loop
|
||||
jb .slice_loop
|
||||
|
||||
; The pool of transmit slots, all free. It must exist before NetRegDev:
|
||||
; the stack may transmit as soon as the device is registered.
|
||||
invoke KernelAlloc, RNDIS_TX_SLOT * RNDIS_TX_MAX_PENDING
|
||||
test eax, eax
|
||||
jz .fail
|
||||
mov [ebx+rndis_dev.TxArea], eax
|
||||
xor edi, edi
|
||||
.free_loop:
|
||||
or [ebx+rndis_dev.TxFree+edi*4], -1
|
||||
inc edi
|
||||
cmp edi, RNDIS_TX_MAX_PENDING/32
|
||||
jb .free_loop
|
||||
|
||||
push ebx
|
||||
invoke NetRegDev
|
||||
@@ -952,8 +1079,9 @@ proc rndis_start
|
||||
mov [ebx+rndis_dev.Registered], 1
|
||||
DEBUGF 2,"registered as network device %u\n", eax
|
||||
|
||||
; An LTE router bridge is up unless the device indicated otherwise
|
||||
; before we finished initializing.
|
||||
; the link follows the media indication, or RNDIS_LINK_WAIT expires
|
||||
cmp [ebx+rndis_dev.LinkKnown], 0
|
||||
je .link_wait
|
||||
cmp [ebx+rndis_dev.LinkDown], 0
|
||||
jne @f
|
||||
mov [ebx+rndis_dev.state], ETH_LINK_SPEED_10M or ETH_LINK_FULL_DUPLEX
|
||||
@@ -961,18 +1089,40 @@ proc rndis_start
|
||||
push ebx
|
||||
invoke NetLinkChanged
|
||||
pop ebx
|
||||
jmp .link_done
|
||||
.link_wait:
|
||||
invoke TimerHS, RNDIS_LINK_WAIT, 0, rndis_link_timer, ebx
|
||||
mov [ebx+rndis_dev.LinkTimer], eax
|
||||
test eax, eax
|
||||
jnz .link_done
|
||||
DEBUGF 2,"no timer for the link, assuming it is up\n"
|
||||
mov [ebx+rndis_dev.LinkKnown], 1
|
||||
mov [ebx+rndis_dev.state], ETH_LINK_SPEED_10M or ETH_LINK_FULL_DUPLEX
|
||||
push ebx
|
||||
invoke NetLinkChanged
|
||||
pop ebx
|
||||
.link_done:
|
||||
|
||||
; Arm the first receive. From here on the RX callback ping-pongs between
|
||||
; the two buffers: it re-arms the pipe with the other buffer BEFORE
|
||||
; parsing the completed one, so the device streams the next frames while
|
||||
; the host walks the current buffer. Exactly one transfer is outstanding
|
||||
; at any time - queueing several short-packet-terminated bulk IN
|
||||
; transfers breaks the EHCI stack (see the note in usbcdc.asm).
|
||||
; Arm every receive buffer at once. Callbacks run in the USB thread,
|
||||
; woken up to 10 ms after the IRQ; with one transfer in flight a device
|
||||
; sending one frame per transfer is capped at ~1 Mbit/s. Each callback
|
||||
; re-arms its own buffer at the ring tail, so frame order is kept.
|
||||
; NB: on EHCI this used to hurt (see usbcdc.asm); if so, use 2 buffers.
|
||||
xor edi, edi
|
||||
.arm_loop:
|
||||
invoke USBNormalTransferAsync, [ebx+rndis_dev.InPipe], \
|
||||
[ebx+rndis_dev.RxBufs], [ebx+rndis_dev.RxSize], \
|
||||
[ebx+rndis_dev.RxBufs+edi*4], [ebx+rndis_dev.RxSize], \
|
||||
rndis_rx_callback, ebx, 1
|
||||
test eax, eax
|
||||
jz .fail
|
||||
jz .armed
|
||||
inc [ebx+rndis_dev.RxArmed]
|
||||
inc edi
|
||||
cmp edi, RNDIS_RX_BUFFERS
|
||||
jb .arm_loop
|
||||
.armed:
|
||||
cmp [ebx+rndis_dev.RxArmed], 0
|
||||
je .fail
|
||||
DEBUGF 2,"receive queue depth %u\n", [ebx+rndis_dev.RxArmed]
|
||||
ret
|
||||
|
||||
.fail:
|
||||
@@ -983,10 +1133,8 @@ proc rndis_start
|
||||
endp
|
||||
|
||||
if DEBUG_STATS
|
||||
; Print transfer-rate statistics to the debug board about once a second
|
||||
; while traffic flows (called from the RX callback). Shows where the
|
||||
; bottleneck is: cb/fr = USB transfers and frames per interval (RX),
|
||||
; tx = frames sent per interval (the TCP ACK clock on downloads).
|
||||
; Print RX/TX counters about once a second while traffic flows.
|
||||
; cb/fr = transfers/frames received, tx = frames sent.
|
||||
; IN: ebx = device context
|
||||
proc rndis_stats
|
||||
|
||||
@@ -1001,10 +1149,16 @@ proc rndis_stats
|
||||
jb .done
|
||||
mov ecx, [ebx+rndis_dev.packets_tx]
|
||||
sub ecx, [ebx+rndis_dev.StatTxPkts]
|
||||
DEBUGF 2,"stat %ut: cb %u fr %u B %u tx %u wnd %u txovr %u rxdrop %u\n", \
|
||||
DEBUGF 2,"stat %ut: cb %u fr %u B %u tx %u wnd %u txovr %u txerr %u rxdrop %u rxovr %u gap %u retx %u txq %u tail %u rxu %u rxb %u logdrop %u\n", \
|
||||
edx, [ebx+rndis_dev.StatCb], [ebx+rndis_dev.StatFrames], \
|
||||
[ebx+rndis_dev.StatBytes], ecx, [ebx+rndis_dev.StatWnd], \
|
||||
[ebx+rndis_dev.packets_tx_ovr], [ebx+rndis_dev.packets_rx_drop]
|
||||
[ebx+rndis_dev.packets_tx_ovr], [ebx+rndis_dev.packets_tx_err], \
|
||||
[ebx+rndis_dev.packets_rx_drop], [ebx+rndis_dev.packets_rx_ovr], \
|
||||
[ebx+rndis_dev.StatGap], [ebx+rndis_dev.StatRetx], \
|
||||
[ebx+rndis_dev.StatTxHigh], [ebx+rndis_dev.StatTail], \
|
||||
[ebx+rndis_dev.StatRxUni], [ebx+rndis_dev.StatRxBc], \
|
||||
[ebx+rndis_dev.StatLogDrop]
|
||||
mov [ebx+rndis_dev.StatTxHigh], 0
|
||||
mov [ebx+rndis_dev.StatCb], 0
|
||||
mov [ebx+rndis_dev.StatFrames], 0
|
||||
mov [ebx+rndis_dev.StatBytes], 0
|
||||
@@ -1016,6 +1170,281 @@ proc rndis_stats
|
||||
pop edx ecx eax
|
||||
ret
|
||||
|
||||
endp
|
||||
|
||||
; Log ARP, ICMP, DNS, DHCP and TCP SYN/FIN/RST in both directions, at
|
||||
; most RNDIS_LOG_BURST lines a second (the rest counted in logdrop).
|
||||
; Also counts arrivals to our MAC (rxu) and to a group (rxb).
|
||||
; IN: ebx = device context, esi -> ethernet frame, ecx = frame length,
|
||||
; edi = 0 received, 1 sent. Destroys everything, the caller saves it.
|
||||
align 4
|
||||
rndis_log_frame:
|
||||
|
||||
mov ebp, edi ; direction
|
||||
test ebp, ebp
|
||||
jnz .classified
|
||||
test byte [esi], 1 ; group bit of destination MAC
|
||||
jz .unicast
|
||||
inc [ebx+rndis_dev.StatRxBc]
|
||||
jmp .classified
|
||||
.unicast:
|
||||
mov eax, [esi]
|
||||
cmp eax, dword [ebx+rndis_dev.mac]
|
||||
jne .classified
|
||||
mov ax, [esi+4]
|
||||
cmp ax, word [ebx+rndis_dev.mac+4]
|
||||
jne .classified
|
||||
inc [ebx+rndis_dev.StatRxUni]
|
||||
.classified:
|
||||
|
||||
; Pick out the frames worth a line; edx -> transport header.
|
||||
cmp word [esi+12], 0x0608 ; EtherType ARP (BE 08 06)
|
||||
je .arp
|
||||
cmp word [esi+12], 0x0008 ; EtherType IPv4
|
||||
jne .done
|
||||
cmp ecx, 14+20
|
||||
jb .done
|
||||
movzx eax, byte [esi+14]
|
||||
and eax, 15
|
||||
shl eax, 2 ; IP header length
|
||||
cmp eax, 20
|
||||
jb .done
|
||||
test word [esi+20], 0xFF1F ; not the first fragment
|
||||
jnz .done
|
||||
lea edx, [esi+14+eax]
|
||||
add eax, 14+8 ; room for an ICMP/UDP header
|
||||
cmp ecx, eax
|
||||
jb .done
|
||||
cmp byte [esi+23], 1 ; ICMP
|
||||
je .limit
|
||||
cmp byte [esi+23], 17 ; UDP
|
||||
je .udp
|
||||
cmp byte [esi+23], 6 ; TCP
|
||||
jne .done
|
||||
add eax, 20-8
|
||||
cmp ecx, eax
|
||||
jb .done
|
||||
test byte [edx+13], 7 ; FIN, SYN or RST
|
||||
jz .done
|
||||
jmp .limit
|
||||
.udp:
|
||||
mov eax, [edx] ; both ports, big-endian
|
||||
mov ecx, 2
|
||||
.udp_port:
|
||||
cmp ax, 53 shl 8 ; DNS
|
||||
je .limit
|
||||
cmp ax, 67 shl 8 ; DHCP server
|
||||
je .limit
|
||||
cmp ax, 68 shl 8 ; DHCP client
|
||||
je .limit
|
||||
shr eax, 16
|
||||
dec ecx
|
||||
jnz .udp_port
|
||||
jmp .done
|
||||
.arp:
|
||||
cmp ecx, 42
|
||||
jb .done
|
||||
|
||||
; Rate limit: RNDIS_LOG_BURST lines per 100 ticks.
|
||||
.limit:
|
||||
push edx
|
||||
invoke GetTimerTicks
|
||||
pop edx
|
||||
mov ecx, eax
|
||||
sub ecx, [ebx+rndis_dev.LogTicks]
|
||||
cmp ecx, 100
|
||||
jb @f
|
||||
mov [ebx+rndis_dev.LogTicks], eax
|
||||
mov [ebx+rndis_dev.LogCount], 0
|
||||
@@:
|
||||
cmp [ebx+rndis_dev.LogCount], RNDIS_LOG_BURST
|
||||
jb @f
|
||||
inc [ebx+rndis_dev.StatLogDrop]
|
||||
ret
|
||||
@@:
|
||||
inc [ebx+rndis_dev.LogCount]
|
||||
|
||||
; eax = ticks, ebp = direction, esi -> frame, edx -> transport header
|
||||
cmp word [esi+12], 0x0608
|
||||
je .print_arp
|
||||
cmp byte [esi+23], 1
|
||||
je .print_icmp
|
||||
cmp byte [esi+23], 17
|
||||
je .print_udp
|
||||
|
||||
;--------------------------------- TCP
|
||||
push ebp ; direction, tested below
|
||||
movzx ecx, word [esi+16]
|
||||
xchg cl, ch ; IP total length
|
||||
movzx ebx, byte [esi+14]
|
||||
and ebx, 15
|
||||
shl ebx, 2
|
||||
sub ecx, ebx ; minus the IP header
|
||||
movzx ebx, byte [edx+12]
|
||||
shr ebx, 4
|
||||
shl ebx, 2
|
||||
sub ecx, ebx ; minus the TCP header
|
||||
jns @f
|
||||
xor ecx, ecx
|
||||
@@:
|
||||
mov ebp, ecx ; payload length
|
||||
movzx ecx, word [edx]
|
||||
xchg cl, ch ; source port
|
||||
mov di, [edx+2]
|
||||
rol di, 8
|
||||
movzx edi, di ; destination port
|
||||
movzx ebx, word [edx+14]
|
||||
xchg bl, bh ; window (unscaled)
|
||||
cmp dword [esp], 0
|
||||
jne .tcp_out
|
||||
DEBUGF 2,"t%u in TCP %u.%u.%u.%u:%u > %u.%u.%u.%u:%u flags %x win %u len %u\n", eax, \
|
||||
[esi+26]:1, [esi+27]:1, [esi+28]:1, [esi+29]:1, ecx, \
|
||||
[esi+30]:1, [esi+31]:1, [esi+32]:1, [esi+33]:1, edi, \
|
||||
[edx+13]:2, ebx, ebp
|
||||
pop eax
|
||||
ret
|
||||
.tcp_out:
|
||||
DEBUGF 2,"t%u out TCP %u.%u.%u.%u:%u > %u.%u.%u.%u:%u flags %x win %u len %u\n", eax, \
|
||||
[esi+26]:1, [esi+27]:1, [esi+28]:1, [esi+29]:1, ecx, \
|
||||
[esi+30]:1, [esi+31]:1, [esi+32]:1, [esi+33]:1, edi, \
|
||||
[edx+13]:2, ebx, ebp
|
||||
pop eax
|
||||
ret
|
||||
|
||||
;--------------------------------- UDP (DNS, DHCP)
|
||||
.print_udp:
|
||||
movzx ecx, word [edx]
|
||||
xchg cl, ch ; source port
|
||||
mov di, [edx+2]
|
||||
rol di, 8
|
||||
movzx edi, di ; destination port
|
||||
movzx ebx, word [edx+4]
|
||||
xchg bl, bh
|
||||
sub ebx, 8 ; payload length
|
||||
test ebp, ebp
|
||||
jnz .udp_out
|
||||
DEBUGF 2,"t%u in UDP %u.%u.%u.%u:%u > %u.%u.%u.%u:%u len %u\n", eax, \
|
||||
[esi+26]:1, [esi+27]:1, [esi+28]:1, [esi+29]:1, ecx, \
|
||||
[esi+30]:1, [esi+31]:1, [esi+32]:1, [esi+33]:1, edi, ebx
|
||||
ret
|
||||
.udp_out:
|
||||
DEBUGF 2,"t%u out UDP %u.%u.%u.%u:%u > %u.%u.%u.%u:%u len %u\n", eax, \
|
||||
[esi+26]:1, [esi+27]:1, [esi+28]:1, [esi+29]:1, ecx, \
|
||||
[esi+30]:1, [esi+31]:1, [esi+32]:1, [esi+33]:1, edi, ebx
|
||||
ret
|
||||
|
||||
;--------------------------------- ICMP
|
||||
.print_icmp:
|
||||
test ebp, ebp
|
||||
jnz .icmp_out
|
||||
DEBUGF 2,"t%u in ICMP %u.%u.%u.%u > %u.%u.%u.%u type %u code %u\n", eax, \
|
||||
[esi+26]:1, [esi+27]:1, [esi+28]:1, [esi+29]:1, \
|
||||
[esi+30]:1, [esi+31]:1, [esi+32]:1, [esi+33]:1, \
|
||||
[edx]:1, [edx+1]:1
|
||||
ret
|
||||
.icmp_out:
|
||||
DEBUGF 2,"t%u out ICMP %u.%u.%u.%u > %u.%u.%u.%u type %u code %u\n", eax, \
|
||||
[esi+26]:1, [esi+27]:1, [esi+28]:1, [esi+29]:1, \
|
||||
[esi+30]:1, [esi+31]:1, [esi+32]:1, [esi+33]:1, \
|
||||
[edx]:1, [edx+1]:1
|
||||
ret
|
||||
|
||||
;--------------------------------- ARP
|
||||
; a request names who asks; a reply names the MAC, which tells a stale
|
||||
; entry (the phone's address changed) from a missing one
|
||||
.print_arp:
|
||||
cmp byte [esi+21], 2 ; opcode: 1 request, 2 reply
|
||||
je .arp_reply
|
||||
test ebp, ebp
|
||||
jnz .arp_req_out
|
||||
DEBUGF 2,"t%u in ARP who-has %u.%u.%u.%u tell %u.%u.%u.%u\n", eax, \
|
||||
[esi+38]:1, [esi+39]:1, [esi+40]:1, [esi+41]:1, \
|
||||
[esi+28]:1, [esi+29]:1, [esi+30]:1, [esi+31]:1
|
||||
ret
|
||||
.arp_req_out:
|
||||
DEBUGF 2,"t%u out ARP who-has %u.%u.%u.%u tell %u.%u.%u.%u\n", eax, \
|
||||
[esi+38]:1, [esi+39]:1, [esi+40]:1, [esi+41]:1, \
|
||||
[esi+28]:1, [esi+29]:1, [esi+30]:1, [esi+31]:1
|
||||
ret
|
||||
.arp_reply:
|
||||
test ebp, ebp
|
||||
jnz .arp_rep_out
|
||||
DEBUGF 2,"t%u in ARP %u.%u.%u.%u is-at %x-%x-%x-%x-%x-%x\n", eax, \
|
||||
[esi+28]:1, [esi+29]:1, [esi+30]:1, [esi+31]:1, \
|
||||
[esi+22]:2, [esi+23]:2, [esi+24]:2, [esi+25]:2, [esi+26]:2, [esi+27]:2
|
||||
ret
|
||||
.arp_rep_out:
|
||||
DEBUGF 2,"t%u out ARP %u.%u.%u.%u is-at %x-%x-%x-%x-%x-%x\n", eax, \
|
||||
[esi+28]:1, [esi+29]:1, [esi+30]:1, [esi+31]:1, \
|
||||
[esi+22]:2, [esi+23]:2, [esi+24]:2, [esi+25]:2, [esi+26]:2, [esi+27]:2
|
||||
.done:
|
||||
ret
|
||||
|
||||
; Track incoming TCP sequence numbers per flow: gap counts segments
|
||||
; past a hole, retx segments with data already received (cumulative).
|
||||
; IN: ebx = device context, esi -> ethernet frame, ecx = frame length
|
||||
; Destroys everything but ebx and ebp.
|
||||
proc rndis_track_tcp
|
||||
|
||||
cmp ecx, 54 ; eth+min IP+min TCP
|
||||
jb .done
|
||||
cmp word [esi+12], 0x0008 ; EtherType IPv4
|
||||
jne .done
|
||||
cmp byte [esi+23], 6 ; IP protocol TCP
|
||||
jne .done
|
||||
movzx edx, byte [esi+14]
|
||||
and edx, 15
|
||||
shl edx, 2 ; IP header length
|
||||
movzx eax, word [esi+16]
|
||||
xchg al, ah ; IP total length
|
||||
sub eax, edx
|
||||
jbe .done
|
||||
lea edi, [esi+14+edx] ; TCP header
|
||||
movzx edx, byte [edi+12]
|
||||
shr edx, 4
|
||||
shl edx, 2 ; TCP header length
|
||||
sub eax, edx ; payload length
|
||||
jbe .done ; pure ACK: no sequence space
|
||||
mov ecx, eax
|
||||
mov edx, [esi+26] ; source IP
|
||||
xor edx, [edi] ; ^ source/destination ports
|
||||
mov eax, [edi+4]
|
||||
bswap eax ; sequence number
|
||||
|
||||
lea esi, [ebx+rndis_dev.Flows]
|
||||
mov edi, RNDIS_FLOWS
|
||||
.find:
|
||||
cmp [esi], edx
|
||||
je .found
|
||||
add esi, 8
|
||||
dec edi
|
||||
jnz .find
|
||||
; a new flow: take over the oldest slot
|
||||
mov edi, [ebx+rndis_dev.FlowNext]
|
||||
inc [ebx+rndis_dev.FlowNext]
|
||||
and edi, RNDIS_FLOWS-1
|
||||
lea esi, [ebx+rndis_dev.Flows+edi*8]
|
||||
mov [esi], edx
|
||||
jmp .advance
|
||||
|
||||
.found:
|
||||
mov edx, eax
|
||||
sub edx, [esi+4] ; seq - expected
|
||||
jz .advance
|
||||
js .old
|
||||
inc [ebx+rndis_dev.StatGap]
|
||||
jmp .advance
|
||||
.old:
|
||||
inc [ebx+rndis_dev.StatRetx]
|
||||
lea edx, [eax+ecx]
|
||||
sub edx, [esi+4]
|
||||
jle .done ; nothing new in it
|
||||
.advance:
|
||||
add eax, ecx
|
||||
mov [esi+4], eax
|
||||
.done:
|
||||
ret
|
||||
|
||||
endp
|
||||
end if ; DEBUG_STATS
|
||||
|
||||
@@ -1031,11 +1460,12 @@ proc rndis_rx_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword, .bu
|
||||
|
||||
locals
|
||||
msg_off dd ? ; offset of the current message
|
||||
rearmed dd ? ; the other buffer is already armed
|
||||
endl
|
||||
|
||||
mov ebx, [.calldata]
|
||||
DEBUGF 1,"RX cb st %u len %u\n", [.status], [.length]
|
||||
; this transfer has left the queue, whatever its outcome
|
||||
dec [ebx+rndis_dev.RxArmed]
|
||||
cmp [ebx+rndis_dev.Dead], 0
|
||||
jne .ret
|
||||
cmp [.status], USB_STATUS_CLOSED
|
||||
@@ -1059,28 +1489,13 @@ end if
|
||||
jae .rx_dead
|
||||
invoke USBNormalTransferAsync, [ebx+rndis_dev.InPipe], [.buffer], \
|
||||
[ebx+rndis_dev.RxSize], rndis_rx_callback, ebx, 1
|
||||
test eax, eax
|
||||
jz .check_dry
|
||||
inc [ebx+rndis_dev.RxArmed]
|
||||
jmp .ret
|
||||
.status_ok:
|
||||
mov [ebx+rndis_dev.RxErrRun], 0 ; the error run is broken
|
||||
|
||||
; Re-arm the pipe with the other buffer BEFORE parsing this one: the
|
||||
; device streams the next frames while the host walks the current
|
||||
; buffer. The completed transfer is already off the queue, so still at
|
||||
; most one transfer is outstanding (a hard requirement of the EHCI
|
||||
; stack, see the note in usbcdc.asm).
|
||||
mov [rearmed], 0
|
||||
mov eax, [ebx+rndis_dev.RxBufs]
|
||||
cmp eax, [.buffer]
|
||||
jne @f
|
||||
mov eax, [ebx+rndis_dev.RxBufs+4]
|
||||
@@:
|
||||
invoke USBNormalTransferAsync, [ebx+rndis_dev.InPipe], eax, \
|
||||
[ebx+rndis_dev.RxSize], rndis_rx_callback, ebx, 1
|
||||
test eax, eax
|
||||
jz @f
|
||||
mov [rearmed], 1
|
||||
@@:
|
||||
|
||||
mov [msg_off], 0
|
||||
|
||||
.msg_loop:
|
||||
@@ -1151,9 +1566,30 @@ end if
|
||||
if DEBUG_STATS
|
||||
inc [ebx+rndis_dev.StatFrames]
|
||||
add [ebx+rndis_dev.StatBytes], ecx
|
||||
pushad
|
||||
lea esi, [edi+NET_BUFF.data]
|
||||
xor edi, edi
|
||||
call rndis_log_frame
|
||||
popad
|
||||
pushad
|
||||
lea esi, [edi+NET_BUFF.data]
|
||||
call rndis_track_tcp
|
||||
popad
|
||||
end if
|
||||
DEBUGF 1,"->host frame %u bytes\n", [edi+NET_BUFF.length]
|
||||
|
||||
; Frames arrive, so the link is up despite MEDIA_DISCONNECT (a phone
|
||||
; tethering at cold boot never sends MEDIA_CONNECT).
|
||||
cmp [ebx+rndis_dev.LinkDown], 0
|
||||
je .link_ok
|
||||
mov [ebx+rndis_dev.LinkDown], 0
|
||||
mov [ebx+rndis_dev.state], ETH_LINK_SPEED_10M or ETH_LINK_FULL_DUPLEX
|
||||
DEBUGF 2,"frames arrive while the link is down, taking it as up\n"
|
||||
pushad
|
||||
invoke NetLinkChanged
|
||||
popad
|
||||
.link_ok:
|
||||
|
||||
; hand the buffer to the network stack. EthInput consumes
|
||||
; [esp] = buffer and returns to the address at [esp+4].
|
||||
push ebp ebx esi
|
||||
@@ -1168,19 +1604,31 @@ end if
|
||||
inc [ebx+rndis_dev.packets_rx_drop]
|
||||
jmp .msg_loop
|
||||
|
||||
; End of processing. If arming the other buffer failed at entry, fall
|
||||
; back to re-submitting the just-parsed buffer so receive does not stop.
|
||||
; put this buffer back at the tail of the queue
|
||||
.rearm:
|
||||
if DEBUG_STATS
|
||||
; bytes of the transfer not turned into frames; must stay 0
|
||||
mov eax, [.length]
|
||||
sub eax, [msg_off]
|
||||
jbe @f
|
||||
add [ebx+rndis_dev.StatTail], eax
|
||||
@@:
|
||||
call rndis_stats
|
||||
end if
|
||||
cmp [rearmed], 0
|
||||
jne .ret
|
||||
invoke USBNormalTransferAsync, [ebx+rndis_dev.InPipe], [.buffer], \
|
||||
[ebx+rndis_dev.RxSize], rndis_rx_callback, ebx, 1
|
||||
test eax, eax
|
||||
jnz .ret
|
||||
jz .rearm_failed
|
||||
inc [ebx+rndis_dev.RxArmed]
|
||||
ret
|
||||
.rearm_failed:
|
||||
DEBUGF 2,"failed to re-arm RX\n"
|
||||
; Losing one buffer of the queue is survivable as long as something is
|
||||
; still outstanding; if nothing is, receive has stopped for good.
|
||||
.check_dry:
|
||||
cmp [ebx+rndis_dev.RxArmed], 0
|
||||
jne .ret
|
||||
DEBUGF 2,"receive queue ran dry, receive stopped\n"
|
||||
.ret:
|
||||
ret
|
||||
|
||||
@@ -1188,7 +1636,11 @@ end if
|
||||
DEBUGF 2,"bulk IN stalled, receive stopped\n"
|
||||
ret
|
||||
|
||||
; Every buffer still in the queue arrives here in turn; report the death
|
||||
; of the pipe only once.
|
||||
.rx_dead:
|
||||
cmp [ebx+rndis_dev.state], ETH_LINK_DOWN
|
||||
je .ret
|
||||
DEBUGF 2,"RX stopped after repeated transfer errors\n"
|
||||
mov [ebx+rndis_dev.state], ETH_LINK_DOWN
|
||||
push ebx
|
||||
@@ -1213,7 +1665,50 @@ proc rndis_tx_callback stdcall uses ebx esi edi, .pipe:dword, .status:dword, .bu
|
||||
DEBUGF 1,"TX error %u\n", [.status]
|
||||
@@:
|
||||
mov eax, [.calldata]
|
||||
invoke Kfree
|
||||
call rndis_tx_release
|
||||
ret
|
||||
|
||||
endp
|
||||
|
||||
; Take a free transmit slot.
|
||||
; IN: ebx = device context. OUT: eax = slot, 0 if none. Destroys ecx, edx.
|
||||
; The stack transmits on its own thread while completions run on the USB
|
||||
; thread, possibly on another CPU, hence the locked bit operations.
|
||||
if RNDIS_TX_SLOT <> 2048
|
||||
err "rndis_tx_claim/rndis_tx_release shift by 11 for 2 KB slots"
|
||||
end if
|
||||
proc rndis_tx_claim
|
||||
|
||||
xor edx, edx
|
||||
.scan:
|
||||
mov eax, [ebx+rndis_dev.TxFree+edx*4]
|
||||
test eax, eax
|
||||
jz .next
|
||||
bsf ecx, eax
|
||||
lock btr [ebx+rndis_dev.TxFree+edx*4], ecx
|
||||
jnc .scan ; taken meanwhile: look again
|
||||
shl edx, 5
|
||||
add edx, ecx ; slot number
|
||||
shl edx, 11
|
||||
mov eax, [ebx+rndis_dev.TxArea]
|
||||
add eax, edx
|
||||
ret
|
||||
.next:
|
||||
inc edx
|
||||
cmp edx, RNDIS_TX_MAX_PENDING/32
|
||||
jb .scan
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
endp
|
||||
|
||||
; Give a transmit slot back.
|
||||
; IN: ebx = device context, eax = slot. Destroys eax.
|
||||
proc rndis_tx_release
|
||||
|
||||
sub eax, [ebx+rndis_dev.TxArea]
|
||||
shr eax, 11 ; slot number
|
||||
lock bts [ebx+rndis_dev.TxFree], eax
|
||||
ret
|
||||
|
||||
endp
|
||||
@@ -1227,8 +1722,8 @@ endp
|
||||
;; ;;
|
||||
;; The frame is prepended with a 44-byte REMOTE_NDIS_PACKET_MSG. ;;
|
||||
;; If the transfer would be a multiple of the endpoint packet ;;
|
||||
;; size, one extra zero byte is sent (not counted in the message ;;
|
||||
;; length) so that the transfer ends in a short packet. ;;
|
||||
;; size, one extra zero byte is sent so that the transfer ends in ;;
|
||||
;; a short packet; it is counted in MessageLength (QEMU needs it). ;;
|
||||
;; ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
@@ -1251,13 +1746,22 @@ endl
|
||||
je .drop
|
||||
mov ecx, [esi+NET_BUFF.length]
|
||||
cmp ecx, 14
|
||||
jb .err
|
||||
jb .badlen
|
||||
cmp ecx, ETH_FRAME_MAX
|
||||
ja .err
|
||||
ja .badlen
|
||||
DEBUGF 1,"host-> frame %u bytes\n", ecx
|
||||
|
||||
; limit the number of messages in flight
|
||||
lock inc [ebx+rndis_dev.TxPending]
|
||||
if DEBUG_STATS
|
||||
; remember how deep the queue actually gets: the margin left before
|
||||
; frames start being refused
|
||||
mov eax, [ebx+rndis_dev.TxPending]
|
||||
cmp eax, [ebx+rndis_dev.StatTxHigh]
|
||||
jbe @f
|
||||
mov [ebx+rndis_dev.StatTxHigh], eax
|
||||
@@:
|
||||
end if
|
||||
cmp [ebx+rndis_dev.TxPending], RNDIS_TX_MAX_PENDING
|
||||
ja .overrun
|
||||
|
||||
@@ -1276,6 +1780,7 @@ endl
|
||||
test eax, edx
|
||||
jnz @f
|
||||
inc eax
|
||||
mov [msglen], eax ; the pad byte is part of it
|
||||
@@:
|
||||
mov [xferlen], eax
|
||||
; never exceed what the device declared it can receive
|
||||
@@ -1285,9 +1790,8 @@ endl
|
||||
cmp eax, edx
|
||||
ja .toobig
|
||||
@@:
|
||||
; allocate [context dword][message]
|
||||
add eax, 4
|
||||
invoke Kmalloc
|
||||
; take a slot for [context dword][message]
|
||||
call rndis_tx_claim
|
||||
test eax, eax
|
||||
jz .no_memory
|
||||
mov [alloc], eax
|
||||
@@ -1321,6 +1825,15 @@ endl
|
||||
rep stosb
|
||||
|
||||
if DEBUG_STATS
|
||||
; stats: spell out the control frames we send
|
||||
pushad
|
||||
mov esi, [alloc]
|
||||
add esi, 4+RNDIS_HDR_SIZE ; frame start
|
||||
mov ecx, edx ; frame length
|
||||
movi edi, 1
|
||||
call rndis_log_frame
|
||||
popad
|
||||
|
||||
; stats: remember the TCP receive window we advertise (rwnd health on
|
||||
; downloads; parsed from the outgoing frame: eth+IPv4+TCP)
|
||||
cmp edx, 54 ; eth+min IP+min TCP
|
||||
@@ -1359,7 +1872,7 @@ end if
|
||||
|
||||
.submit_failed:
|
||||
mov eax, [alloc]
|
||||
invoke Kfree
|
||||
call rndis_tx_release
|
||||
lock dec [ebx+rndis_dev.TxPending]
|
||||
jmp .err
|
||||
|
||||
@@ -1376,6 +1889,16 @@ end if
|
||||
inc [ebx+rndis_dev.packets_tx_ovr]
|
||||
jmp .drop
|
||||
|
||||
; A frame the stack handed down does not fit an ethernet frame at all.
|
||||
; Report the first few: the length says at once whether the stack built
|
||||
; an oversized segment (t_maxseg not clamped to our mtu, which shows up
|
||||
; as an endlessly retransmitting connection) or something else.
|
||||
.badlen:
|
||||
cmp [ebx+rndis_dev.LenErrNoted], 4
|
||||
jae .err
|
||||
inc [ebx+rndis_dev.LenErrNoted]
|
||||
DEBUGF 2,"refusing a frame of %u bytes\n", ecx
|
||||
|
||||
.err:
|
||||
inc [ebx+rndis_dev.packets_tx_err]
|
||||
.drop:
|
||||
@@ -1410,6 +1933,11 @@ proc DeviceDisconnected stdcall uses ebx esi edi, .devdata:dword
|
||||
mov ebx, [.devdata]
|
||||
DEBUGF 2,"device disconnected\n"
|
||||
mov [ebx+rndis_dev.Dead], 1
|
||||
mov eax, [ebx+rndis_dev.LinkTimer]
|
||||
test eax, eax
|
||||
jz @f
|
||||
invoke CancelTimerHS, eax ; must not fire on a freed context
|
||||
@@:
|
||||
cmp [ebx+rndis_dev.Registered], 0
|
||||
je @f
|
||||
mov [ebx+rndis_dev.state], ETH_LINK_DOWN
|
||||
@@ -1421,16 +1949,17 @@ proc DeviceDisconnected stdcall uses ebx esi edi, .devdata:dword
|
||||
pop ebx
|
||||
mov [ebx+rndis_dev.Registered], 0
|
||||
@@:
|
||||
xor esi, esi
|
||||
.free_loop:
|
||||
mov eax, [ebx+rndis_dev.RxBufs+esi*4]
|
||||
; every transfer callback has run by now, so no slot or buffer is in use
|
||||
mov eax, [ebx+rndis_dev.RxArea]
|
||||
test eax, eax
|
||||
jz @f
|
||||
invoke KernelFree, eax
|
||||
@@:
|
||||
mov eax, [ebx+rndis_dev.TxArea]
|
||||
test eax, eax
|
||||
jz @f
|
||||
invoke KernelFree, eax
|
||||
@@:
|
||||
inc esi
|
||||
cmp esi, RNDIS_RX_BUFFERS
|
||||
jb .free_loop
|
||||
mov eax, ebx
|
||||
invoke Kfree
|
||||
ret
|
||||
@@ -1480,5 +2009,6 @@ end data
|
||||
|
||||
align 4
|
||||
parse_scratch rndis_parse
|
||||
random_mac rb 6 ; host address used instead of a made-up one
|
||||
|
||||
include_debug_strings
|
||||
+970
-105
File diff suppressed because it is too large.
Load diff
@@ -83,6 +83,31 @@ macro arp_init {
|
||||
|
||||
}
|
||||
|
||||
;-----------------------------------------------------------------;
|
||||
; ;
|
||||
; arp_clear_device: Empty the ARP table and counters of a removed ;
|
||||
; device. ;
|
||||
; ;
|
||||
; IN: edi = device number * 4 ;
|
||||
; ;
|
||||
;-----------------------------------------------------------------;
|
||||
macro arp_clear_device {
|
||||
|
||||
xor eax, eax
|
||||
mov [ARP_entries + edi], eax
|
||||
mov [ARP_packets_tx + edi], eax
|
||||
mov [ARP_packets_rx + edi], eax
|
||||
mov [ARP_conflicts + edi], eax
|
||||
|
||||
push edi
|
||||
imul edi, (ARP_TABLE_SIZE * sizeof.ARP_entry)/4
|
||||
add edi, ARP_table
|
||||
mov ecx, (ARP_TABLE_SIZE * sizeof.ARP_entry)/2
|
||||
rep stosw
|
||||
pop edi
|
||||
|
||||
}
|
||||
|
||||
;-----------------------------------------------------------------;
|
||||
; ;
|
||||
; arp_decrease_entry_ttls ;
|
||||
@@ -313,6 +338,9 @@ arp_output_request:
|
||||
DEBUGF DEBUG_NETWORK_VERBOSE, "ARP_output_request: ip=%u.%u.%u.%u device=0x%x\n",\
|
||||
[esp]:1, [esp + 1]:1, [esp + 2]:1, [esp + 3]:1, ebx
|
||||
|
||||
test ebx, ebx ; device is gone
|
||||
jz .exit
|
||||
|
||||
mov ax, ETHER_PROTO_ARP
|
||||
mov ecx, sizeof.ARP_header
|
||||
mov edx, ETH_BROADCAST ; broadcast mac
|
||||
|
||||
@@ -105,6 +105,29 @@ macro ipv4_init {
|
||||
}
|
||||
|
||||
|
||||
;-----------------------------------------------------------------;
|
||||
; ;
|
||||
; ipv4_clear_device: Reset the IPv4 settings of a removed device, ;
|
||||
; so no route points to it anymore. ;
|
||||
; ;
|
||||
; IN: edi = device number * 4 ;
|
||||
; ;
|
||||
;-----------------------------------------------------------------;
|
||||
macro ipv4_clear_device {
|
||||
|
||||
xor eax, eax
|
||||
mov [IPv4_address + edi], eax
|
||||
mov [IPv4_subnet + edi], eax
|
||||
mov [IPv4_nameserver + edi], eax
|
||||
mov [IPv4_gateway + edi], eax
|
||||
mov [IPv4_broadcast + edi], eax
|
||||
mov [IPv4_packets_tx + edi], eax
|
||||
mov [IPv4_packets_rx + edi], eax
|
||||
mov [IPv4_packets_dumped + edi], eax
|
||||
|
||||
}
|
||||
|
||||
|
||||
;-----------------------------------------------------------------;
|
||||
; ;
|
||||
; Decrease TimeToLive of all fragment slots ;
|
||||
@@ -757,6 +780,8 @@ ipv4_output_raw:
|
||||
push esi eax
|
||||
|
||||
call ipv4_route
|
||||
test eax, eax
|
||||
jz .arp_error
|
||||
call arp_ip_to_mac
|
||||
|
||||
test eax, 0xffff0000 ; error bits
|
||||
@@ -967,6 +992,8 @@ ipv4_route:
|
||||
; Check for on-link
|
||||
xor edi, edi
|
||||
.loop:
|
||||
cmp [net_device_list + edi], 0 ; skip slots without a device
|
||||
je .next
|
||||
mov ebx, [IPv4_address + edi]
|
||||
and ebx, [IPv4_subnet + edi]
|
||||
jz .next
|
||||
@@ -983,7 +1010,10 @@ ipv4_route:
|
||||
mov edi, 4 ; skip loopback device
|
||||
.loop_gw:
|
||||
cmp [IPv4_gateway + edi], 0
|
||||
je .next_gw
|
||||
cmp [net_device_list + edi], 0
|
||||
jne .found_gw
|
||||
.next_gw:
|
||||
add edi, 4
|
||||
cmp edi, 4*NET_DEVICES_MAX
|
||||
jb .loop_gw
|
||||
@@ -1049,14 +1079,23 @@ ipv4_route:
|
||||
cmp eax, 0xffffffff
|
||||
je @f
|
||||
|
||||
; An interface without an address (DHCP not done yet, or the lease
|
||||
; dropped when the link went down) can send nothing but broadcasts: with
|
||||
; address and mask both zero every destination compared as on-link, and
|
||||
; the stack went asking ARP for internet addresses on behalf of 0.0.0.0.
|
||||
test edx, edx
|
||||
jz .fail
|
||||
|
||||
; Check if we should route to gateway or not
|
||||
mov ebx, [IPv4_address + edi]
|
||||
mov ebx, edx
|
||||
and ebx, [IPv4_subnet + edi]
|
||||
mov ecx, eax
|
||||
and ecx, [IPv4_subnet + edi]
|
||||
cmp ecx, ebx
|
||||
je @f
|
||||
mov eax, [IPv4_gateway + edi]
|
||||
test eax, eax
|
||||
jz .fail ; off-link and no gateway
|
||||
@@:
|
||||
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_route: %u\n", edi
|
||||
ret
|
||||
|
||||
@@ -61,6 +61,41 @@ macro eth_init {
|
||||
|
||||
}
|
||||
|
||||
;-----------------------------------------------------------------;
|
||||
; ;
|
||||
; eth_clear_device: Drop the frames of a removed device that are ;
|
||||
; still waiting in the input queue, their ;
|
||||
; NET_BUFF.device will not be valid anymore. ;
|
||||
; ;
|
||||
; IN: ebx = device ptr ;
|
||||
; ;
|
||||
;-----------------------------------------------------------------;
|
||||
macro eth_clear_device {
|
||||
|
||||
local .loop, .done
|
||||
|
||||
spin_lock_irqsave
|
||||
mov esi, [ETH_frame_head]
|
||||
.loop:
|
||||
cmp esi, ETH_frame_head
|
||||
je .done
|
||||
mov eax, esi
|
||||
mov esi, [esi + NET_BUFF.NextPtr]
|
||||
cmp [eax + NET_BUFF.device], ebx
|
||||
jne .loop
|
||||
|
||||
; unlink it, ETH_frame_head/tail double as the NextPtr/PrevPtr of the list head
|
||||
mov ecx, [eax + NET_BUFF.PrevPtr]
|
||||
mov [ecx + NET_BUFF.NextPtr], esi
|
||||
mov [esi + NET_BUFF.PrevPtr], ecx
|
||||
dec [ETH_frame_queued]
|
||||
stdcall net_buff_free, eax
|
||||
jmp .loop
|
||||
.done:
|
||||
spin_unlock_irqrestore
|
||||
|
||||
}
|
||||
|
||||
align 4
|
||||
; This function is called by ethernet drivers.
|
||||
; Push the received ethernet packet onto the ethernet input queue.
|
||||
@@ -245,6 +280,9 @@ eth_output:
|
||||
|
||||
DEBUGF DEBUG_NETWORK_VERBOSE, "ETH_output: size=%u device=%x\n", ecx, ebx
|
||||
|
||||
test ebx, ebx
|
||||
jz .no_device
|
||||
|
||||
cmp ecx, [ebx + ETH_DEVICE.mtu]
|
||||
ja .too_large
|
||||
|
||||
@@ -295,11 +333,16 @@ eth_output:
|
||||
ret
|
||||
|
||||
.too_large:
|
||||
inc [eax + NET_DEVICE.packets_tx_err]
|
||||
inc [ebx + NET_DEVICE.packets_tx_err]
|
||||
DEBUGF DEBUG_NETWORK_VERBOSE, "ETH_output: Packet too large!\n"
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
.no_device:
|
||||
DEBUGF DEBUG_NETWORK_ERROR, "ETH_output: no device!\n"
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;-----------------------------------------------------------------;
|
||||
|
||||
@@ -597,6 +597,16 @@ net_remove_device:
|
||||
mov dword [edi-4], eax
|
||||
dec [net_device_count]
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
; Forget everything the protocols still know about this interface.
|
||||
; Otherwise its IP address keeps matching in ipv4_route, and output
|
||||
; ends up calling through the now empty net_device_list slot.
|
||||
|
||||
sub edi, net_device_list + 4 ; device number * 4
|
||||
ipv4_clear_device
|
||||
arp_clear_device
|
||||
eth_clear_device
|
||||
|
||||
call net_send_event
|
||||
|
||||
xor eax, eax
|
||||
|
||||
@@ -1422,10 +1422,14 @@ endl
|
||||
test [edx + TCP_header.Flags], TH_ACK
|
||||
jz .drop
|
||||
|
||||
mov eax, ebx
|
||||
push ebx
|
||||
lea ecx, [ebx + SOCKET.mutex]
|
||||
call mutex_unlock
|
||||
pop eax
|
||||
|
||||
mov ebx, ECONNREFUSED
|
||||
call tcp_drop
|
||||
jmp .drop
|
||||
jmp .drop_no_socket
|
||||
@@:
|
||||
|
||||
;-----------------------------------------------------------------------------------
|
||||
|
||||
@@ -234,23 +234,25 @@ endl
|
||||
mov ebx, TCP_max_win
|
||||
shl ebx, cl
|
||||
pop ecx
|
||||
sub ebx, [eax + TCP_SOCKET.RCV_ADV]
|
||||
add ebx, [eax + TCP_SOCKET.RCV_NXT]
|
||||
|
||||
; Clamp to available window first, then subtract what the peer already knows (as in BSD)
|
||||
|
||||
cmp ebx, ecx
|
||||
jl @f
|
||||
jbe @f
|
||||
mov ebx, ecx
|
||||
@@:
|
||||
sub ebx, [eax + TCP_SOCKET.RCV_ADV]
|
||||
add ebx, [eax + TCP_SOCKET.RCV_NXT]
|
||||
|
||||
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_output: we can increase window by %d bytes\n", ebx
|
||||
|
||||
mov edi, [eax + TCP_SOCKET.t_maxseg]
|
||||
shl edi, 1
|
||||
cmp ebx, edi
|
||||
jae .send
|
||||
cmp ebx, edi ; signed: may be negative if window shrank
|
||||
jge .send
|
||||
|
||||
cmp ebx, SOCKET_BUFFER_SIZE/2
|
||||
jae .send
|
||||
jge .send
|
||||
|
||||
.no_window:
|
||||
|
||||
|
||||
@@ -180,6 +180,8 @@ tcp_connect:
|
||||
|
||||
.nomem:
|
||||
pop edx eax
|
||||
lea ecx, [eax + SOCKET.mutex]
|
||||
call mutex_unlock
|
||||
xor eax, eax
|
||||
dec eax
|
||||
mov ebx, ENOMEM
|
||||
@@ -194,6 +196,8 @@ tcp_connect:
|
||||
.enoroute:
|
||||
pop eax
|
||||
popa
|
||||
lea ecx, [eax + SOCKET.mutex]
|
||||
call mutex_unlock
|
||||
xor eax, eax
|
||||
dec eax
|
||||
mov ebx, EADDRNOTAVAIL
|
||||
|
||||
+1
-1
Submodule programs/develop/cmm updated: 84fdec8562...4aeaee3386.
@@ -1618,21 +1618,23 @@ endl
|
||||
|
||||
; Open a new TCP socket
|
||||
mcall socket, AF_INET4, SOCK_STREAM, 0
|
||||
test eax, eax
|
||||
jz .error3
|
||||
cmp eax, -1
|
||||
je .error3
|
||||
mov [socketnum], eax
|
||||
DEBUGF 1, "Socket: 0x%x\n", eax
|
||||
|
||||
; Connect to the server
|
||||
mcall connect, [socketnum], [sockaddr], 18
|
||||
test eax, eax
|
||||
jnz .error3
|
||||
jnz .error4
|
||||
DEBUGF 1, "Socket is now connected.\n"
|
||||
|
||||
invoke freeaddrinfo ; Free allocated memory
|
||||
mov eax, [socketnum]
|
||||
ret
|
||||
|
||||
.error4:
|
||||
mcall close, [socketnum]
|
||||
.error3:
|
||||
DEBUGF 2, "Could not connect to the remote server\n"
|
||||
invoke freeaddrinfo ; Free allocated memory
|
||||
|
||||
@@ -501,7 +501,8 @@ img.decode.jpg:
|
||||
jnz .no_create_palette
|
||||
push ecx edi
|
||||
mov edi, [eax + Image.Palette]
|
||||
xor eax, eax
|
||||
mov eax, 0xFF000000 ; opaque, like the palettes of the other decoders:
|
||||
; converted to 32 bpp, alpha 0 made the picture invisible
|
||||
mov ecx, 256
|
||||
@@:
|
||||
stosd
|
||||
|
||||
@@ -1,256 +0,0 @@
|
||||
; SPDX-License-Identifier: NOASSERTION
|
||||
;
|
||||
; System settings: read them from the kernel or from system.ini,
|
||||
; apply them to the kernel and save them to system.ini.
|
||||
|
||||
;---------------------------------------------------------------
|
||||
; Take the current values from the kernel, the mouse ones at system start only
|
||||
settings_read_boot:
|
||||
mcall 18,19,0
|
||||
mov [mouseSpeed],eax
|
||||
mcall 18,,2
|
||||
mov [mouseAccel],eax
|
||||
mcall 18,,6
|
||||
mov [mouseDelay],eax
|
||||
settings_read_system:
|
||||
mcall 26,5
|
||||
dec eax ; the kernel counts languages from 1
|
||||
cmp eax,LANGUAGES
|
||||
jb @f
|
||||
xor eax,eax
|
||||
@@:
|
||||
mov [language],eax
|
||||
mcall 26,11
|
||||
mov [lba],eax
|
||||
mcall 26,12
|
||||
mov [pci],eax
|
||||
mcall 18,8,1
|
||||
mov [speakerMute],eax
|
||||
mcall 48,9
|
||||
mov [fontSmoothing],eax
|
||||
mcall 48,11
|
||||
mov [fontHeight],eax
|
||||
; keep the font height within what the window shows and steps through
|
||||
font_height_limits:
|
||||
mov eax,[fontHeight]
|
||||
cmp eax,FONT_H_MIN
|
||||
jge @f
|
||||
mov eax,FONT_H_MIN
|
||||
@@:
|
||||
cmp eax,FONT_H_MAX
|
||||
jle @f
|
||||
mov eax,FONT_H_MAX
|
||||
@@:
|
||||
mov [fontHeight],eax
|
||||
ret
|
||||
|
||||
;---------------------------------------------------------------
|
||||
; Override the values with the ones stored in system.ini.
|
||||
; A missing or unknown value keeps the current one.
|
||||
settings_read_ini:
|
||||
mov esi,iniSettings
|
||||
.next:
|
||||
mov edi,[esi+12]
|
||||
test edi,edi
|
||||
jnz .word
|
||||
mov eax,[esi+8]
|
||||
invoke ini.get_int, sz_ini, [esi], [esi+4], [eax]
|
||||
jmp .store
|
||||
.word:
|
||||
and [iniWord],0
|
||||
invoke ini.get_str, sz_ini, [esi], [esi+4], iniWord, 4, 0
|
||||
mov eax,[iniWord]
|
||||
or eax,0x20202020 ; lowercase, zeroes become spaces
|
||||
xor edx,edx
|
||||
@@:
|
||||
cmp eax,[edi+4+edx*4]
|
||||
jz .found
|
||||
inc edx
|
||||
cmp edx,[edi]
|
||||
jb @b
|
||||
jmp .skip
|
||||
.found:
|
||||
mov eax,edx
|
||||
.store:
|
||||
mov edx,[esi+8]
|
||||
mov [edx],eax
|
||||
.skip:
|
||||
add esi,16
|
||||
cmp esi,iniSettings.end
|
||||
jb .next
|
||||
jmp font_height_limits
|
||||
|
||||
;---------------------------------------------------------------
|
||||
; Store the values to system.ini (all but the mouse ones).
|
||||
; Not ebx for the loop: ini_set_str returns with ebx = 13.
|
||||
settings_save_ini:
|
||||
mov esi,iniSettings
|
||||
.next:
|
||||
mov eax,[esi+8]
|
||||
mov eax,[eax]
|
||||
mov edi,[esi+12]
|
||||
test edi,edi
|
||||
jnz .word
|
||||
invoke ini.set_int, sz_ini, [esi], [esi+4], eax
|
||||
jmp .done
|
||||
.word:
|
||||
mov eax,[edi+4+eax*4]
|
||||
mov [iniWord],eax
|
||||
xor ecx,ecx ; length of the word
|
||||
@@:
|
||||
cmp byte[iniWord+ecx],' '
|
||||
jz @f
|
||||
inc ecx
|
||||
cmp ecx,4
|
||||
jb @b
|
||||
@@:
|
||||
invoke ini.set_str, sz_ini, [esi], [esi+4], iniWord, ecx
|
||||
.done:
|
||||
add esi,16
|
||||
cmp esi,iniSettings.saved
|
||||
jb .next
|
||||
ret
|
||||
|
||||
;---------------------------------------------------------------
|
||||
; Pass the values to the kernel, the mouse ones at system start only
|
||||
settings_apply_boot:
|
||||
mcall 18,19,1,[mouseSpeed]
|
||||
mcall 18,,3,[mouseAccel]
|
||||
mcall 18,,7,[mouseDelay]
|
||||
settings_apply:
|
||||
mov ecx,[language]
|
||||
inc ecx
|
||||
mcall 21,5
|
||||
mcall 21,11,[lba]
|
||||
mcall 21,12,[pci]
|
||||
mcall 48,10,[fontSmoothing]
|
||||
mcall 48,12,[fontHeight]
|
||||
; the speaker can only be toggled
|
||||
mcall 18,8,1
|
||||
cmp eax,[speakerMute]
|
||||
jz @f
|
||||
mcall 18,,2
|
||||
@@:
|
||||
ret
|
||||
|
||||
;---------------------------------------------------------------
|
||||
; Button style, desktop background and skin from the [style] section.
|
||||
; Used at system start only.
|
||||
style_apply:
|
||||
invoke ini.get_int, sz_ini, sz_style, sz_buttonStyle, 0
|
||||
mcall 48,1,eax
|
||||
|
||||
; the background is set by a program: bg_program with bg_param
|
||||
invoke ini.get_str, sz_ini, sz_style, sz_bgProgram, bgProgram, PATH_MAX, 0
|
||||
cmp byte[bgProgram],0
|
||||
jz .skin
|
||||
invoke ini.get_str, sz_ini, sz_style, sz_bgParam, bgParam, PATH_MAX, 0
|
||||
cmp byte[bgParam],'\' ; KIV param like '\S__/path/to/img'
|
||||
jnz @f
|
||||
mov [fileInfo.path],bgParam+4
|
||||
call wait_for_file
|
||||
@@:
|
||||
mcall 70,runBgProgram
|
||||
|
||||
.skin:
|
||||
invoke ini.get_str, sz_ini, sz_style, sz_skin, skinPath, PATH_MAX, 0
|
||||
cmp byte[skinPath],0
|
||||
jz @f
|
||||
mov [fileInfo.path],skinPath
|
||||
call wait_for_file
|
||||
mcall 48,8,skinPath
|
||||
@@:
|
||||
ret
|
||||
|
||||
; Files on /kolibrios and /usbhd may appear a few seconds after boot:
|
||||
; try to read the file for up to 5 seconds
|
||||
wait_for_file:
|
||||
mov edi,5
|
||||
@@:
|
||||
mcall 70,fileInfo
|
||||
test eax,eax
|
||||
jz @f
|
||||
mcall 5,100
|
||||
dec edi
|
||||
jnz @b
|
||||
@@:
|
||||
ret
|
||||
|
||||
;---------------------------------------------------------------
|
||||
; DATA
|
||||
; The languages of the kernel
|
||||
LANGUAGES = 8
|
||||
FONT_H_MIN = 9
|
||||
FONT_H_MAX = 99 ; two digits in the window
|
||||
PATH_MAX = 256
|
||||
|
||||
; Every value stored in system.ini: section, key, variable, words.
|
||||
; Words = 0 for a number, otherwise the list of words for 0, 1, 2...
|
||||
align 4
|
||||
iniSettings:
|
||||
dd sz_system, sz_language, language, wordsLanguage
|
||||
dd sz_system, sz_fontHeight, fontHeight, 0
|
||||
dd sz_system, sz_fontSmooth, fontSmoothing, wordsSmoothing
|
||||
dd sz_lowLevel, sz_lba, lba, wordsOnOff
|
||||
dd sz_lowLevel, sz_pci, pci, wordsOnOff
|
||||
dd sz_lowLevel, sz_speaker, speakerMute, wordsSpeaker
|
||||
.saved: ; the mouse is configured by its own application
|
||||
dd sz_mouse, sz_speed, mouseSpeed, 0
|
||||
dd sz_mouse, sz_accel, mouseAccel, 0
|
||||
dd sz_mouse, sz_dblClick, mouseDelay, 0
|
||||
.end:
|
||||
|
||||
wordsOnOff dd 2, 'off ','on '
|
||||
wordsSpeaker dd 2, 'on ','off ' ; the ini keeps 'speaker on', not 'mute'
|
||||
wordsSmoothing dd 3, 'off ','on ','sbp '
|
||||
wordsLanguage dd LANGUAGES, 'en ','fi ','de ','ru ','fr ','et ','es ','it '
|
||||
|
||||
runBgProgram:
|
||||
dd 7, 0, bgParam, 0, 0
|
||||
db 0
|
||||
dd bgProgram
|
||||
|
||||
fileInfo:
|
||||
dd 0, 0, 0, 4, fileBuf
|
||||
db 0
|
||||
.path dd ?
|
||||
|
||||
sz_ini db "/sys/settings/system.ini",0
|
||||
|
||||
sz_system db "system",0
|
||||
sz_language db "language",0
|
||||
sz_fontHeight db "font height",0
|
||||
sz_fontSmooth db "font smoothing",0
|
||||
sz_speaker db "speaker",0
|
||||
|
||||
sz_lowLevel db "low-level",0
|
||||
sz_lba db "LBA",0
|
||||
sz_pci db "PCI",0
|
||||
|
||||
sz_mouse db "mouse",0
|
||||
sz_speed db "speed",0
|
||||
sz_accel db "acceleration",0
|
||||
sz_dblClick db "double_click_delay",0
|
||||
|
||||
sz_style db "style",0
|
||||
sz_buttonStyle db "buttons_gradient",0
|
||||
sz_bgProgram db "bg_program",0
|
||||
sz_bgParam db "bg_param",0
|
||||
sz_skin db "skin",0
|
||||
|
||||
; not stored in the program file
|
||||
language dd ?
|
||||
lba dd ?
|
||||
pci dd ?
|
||||
speakerMute dd ?
|
||||
fontSmoothing dd ?
|
||||
fontHeight dd ?
|
||||
mouseSpeed dd ?
|
||||
mouseAccel dd ?
|
||||
mouseDelay dd ?
|
||||
|
||||
iniWord dd ? ; a word of system.ini
|
||||
fileBuf dd ?
|
||||
bgProgram rb PATH_MAX
|
||||
bgParam rb PATH_MAX
|
||||
skinPath rb PATH_MAX
|
||||
+480
-346
@@ -1,316 +1,462 @@
|
||||
; SPDX-License-Identifier: NOASSERTION
|
||||
;
|
||||
; System settings.
|
||||
; SETUP BOOT - apply the settings from system.ini (run from AUTORUN.DAT)
|
||||
; SETUP - window to change and save them
|
||||
;
|
||||
; Texts are UTF-8
|
||||
|
||||
include '../../macros.inc'
|
||||
format meos 01
|
||||
entry START
|
||||
stack 4096
|
||||
; Text encoded with Code Page 866 - Cyrillic
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; SYSTEM SETTINGS ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
format binary as ""
|
||||
use32
|
||||
org 0
|
||||
|
||||
db 'MENUET01'
|
||||
dd 1
|
||||
dd START
|
||||
dd IM_END
|
||||
dd I_END
|
||||
dd I_END
|
||||
dd param
|
||||
dd 0
|
||||
|
||||
include '../../proc32.inc'
|
||||
include '../../macros.inc'
|
||||
include '../../dll.inc'
|
||||
;---------------------------------------------------------------
|
||||
BootSettings:
|
||||
; Set system language
|
||||
mov word[param],0
|
||||
invoke ini.get_str, sz_ini, sz_system, sz_language, param, 2, 0
|
||||
mov ax, [param]
|
||||
or ax, 0x2020 ; convert to lowercase
|
||||
mov ecx,langMarks.size/2
|
||||
mov edi,langMarks
|
||||
repnz scasw
|
||||
jnz @f
|
||||
neg ecx
|
||||
add ecx,langMarks.size/2
|
||||
mcall 21,5
|
||||
@@:
|
||||
|
||||
; Set font smoothing
|
||||
mov dword[param],0
|
||||
invoke ini.get_str, sz_ini, sz_system, sz_fontSmooth, param, 4, 0
|
||||
xor ecx,ecx
|
||||
mov eax,[param]
|
||||
or eax,0x20202020
|
||||
cmp eax,'off '
|
||||
jz @f
|
||||
inc ecx
|
||||
cmp eax,'on '
|
||||
jz @f
|
||||
cmp eax,'sbp '
|
||||
jnz .skipFont
|
||||
inc ecx
|
||||
@@:
|
||||
mcall 48,10
|
||||
.skipFont:
|
||||
|
||||
; Enable/disable system speaker
|
||||
mov dword[param],0
|
||||
invoke ini.get_str, sz_ini, sz_system, sz_speaker, param, 4, 0
|
||||
mov eax,[param]
|
||||
or eax,0x20202020
|
||||
cmp eax,'off '
|
||||
jz @f
|
||||
cmp eax,'on '
|
||||
jnz .skipSpeaker
|
||||
inc [speaker_mute]
|
||||
@@:
|
||||
call _speaker_mute
|
||||
.skipSpeaker:
|
||||
|
||||
; Set font size
|
||||
invoke ini.get_int, sz_ini, sz_system, sz_fontSize, 9
|
||||
mov ecx,eax
|
||||
mcall 48,12
|
||||
|
||||
; Set mouse speed
|
||||
invoke ini.get_int, sz_ini, sz_mouse, sz_speed, 1
|
||||
mov edx,eax
|
||||
mcall 18,19,1
|
||||
|
||||
; Set mouse acceleration
|
||||
invoke ini.get_int, sz_ini, sz_mouse, sz_acceleration, 1
|
||||
mov edx,eax
|
||||
mcall 18,19,3
|
||||
|
||||
; Set mouse double click delay
|
||||
invoke ini.get_int, sz_ini, sz_mouse, sz_double_click_delay, 1
|
||||
mov edx,eax
|
||||
mcall 18,19,7
|
||||
|
||||
; Enable/disable LBA access for applications
|
||||
mov dword[param],0
|
||||
invoke ini.get_str, sz_ini, sz_low_level, sz_lba, param, 4, 0
|
||||
xor ecx,ecx
|
||||
mov eax,[param]
|
||||
or eax,0x20202020
|
||||
cmp eax,'off '
|
||||
jz @f
|
||||
cmp eax,'on '
|
||||
jnz .skipLBA
|
||||
inc ecx
|
||||
@@:
|
||||
mcall 21,11
|
||||
.skipLBA:
|
||||
|
||||
; Enable/disable PCI access for applications
|
||||
mov dword[param],0
|
||||
invoke ini.get_str, sz_ini, sz_low_level, sz_pci, param, 4, 0
|
||||
xor ecx,ecx
|
||||
mov eax,[param]
|
||||
or eax,0x20202020
|
||||
cmp eax,'off '
|
||||
jz @f
|
||||
cmp eax,'on '
|
||||
jnz close
|
||||
inc ecx
|
||||
@@:
|
||||
mcall 21,12
|
||||
jmp close
|
||||
;---------------------------------------------------------------
|
||||
START:
|
||||
mcall 68,11
|
||||
stdcall dll.Load, @IMPORT
|
||||
push eax
|
||||
test eax,eax
|
||||
jnz quit
|
||||
jnz close
|
||||
|
||||
GetCommandLine eax
|
||||
cmp dword[eax],'BOOT'
|
||||
jnz @f
|
||||
cmp [param],dword 'BOOT'
|
||||
jz BootSettings
|
||||
pop eax
|
||||
|
||||
call settings_read_boot
|
||||
call settings_read_ini
|
||||
call settings_apply_boot
|
||||
call style_apply
|
||||
quit:
|
||||
mcall -1
|
||||
; get current settings
|
||||
mcall 26,5
|
||||
dec eax
|
||||
mov [syslang],eax
|
||||
|
||||
@@:
|
||||
call settings_read_system
|
||||
; the checkbox image is shared by @RESHARE, 0 if it is not running
|
||||
mcall 68,22,sz_checkbox,0,0
|
||||
mov [checkboxImage],eax
|
||||
mcall 26,11
|
||||
mov [lba_read],eax
|
||||
|
||||
mcall 26,12
|
||||
mov [pci_acc],eax
|
||||
|
||||
mcall 18,8,1
|
||||
mov [speaker_mute],eax
|
||||
|
||||
mcall 48,9
|
||||
mov [fontSmoothing],eax
|
||||
|
||||
mcall 48,11
|
||||
mov [fontSize],eax
|
||||
|
||||
loadtxt:
|
||||
cmp [syslang],3
|
||||
jz .ru
|
||||
cmp [syslang],5
|
||||
jz .et
|
||||
mov [text],texteng
|
||||
jmp draw_window
|
||||
.et:
|
||||
mov [text],textet
|
||||
jmp draw_window
|
||||
.ru:
|
||||
mov [text],textrus
|
||||
|
||||
;---------------------------------------------------------------
|
||||
draw_window:
|
||||
mov eax,[language]
|
||||
mov eax,[texts+eax*4]
|
||||
mov [text],eax
|
||||
|
||||
mcall 12,1
|
||||
mcall 48,3,sc,sizeof.system_colors
|
||||
mov byte[sc.work_text+3],FONT
|
||||
mov byte[sc.work_button_text+3],FONT
|
||||
mcall 48,4
|
||||
lea ecx,[eax+(50 shl 16)+CLIENT_H+4]
|
||||
mov edx,[sc.work]
|
||||
or edx,0x34000000
|
||||
mcall 0,<50,CLIENT_W+9>,,,0,title
|
||||
|
||||
; a row: label, value (drawn by draw_values), '-' and '+' buttons
|
||||
xor ebp,ebp
|
||||
.row:
|
||||
imul edi,ebp,ROW_STEP
|
||||
add edi,TOP ; y of the row
|
||||
mov ecx,edi
|
||||
shl ecx,16
|
||||
add ecx,ROW_H-1 ; the button is 1 pixel bigger than given
|
||||
lea edx,[FIRST_ROW_BUTTON+ebp*2]
|
||||
mcall 8,<BUTTON1_X,ROW_H-1>,,,[sc.work_button]
|
||||
lea edx,[FIRST_ROW_BUTTON+1+ebp*2]
|
||||
mcall 8,<BUTTON2_X,ROW_H-1>
|
||||
; the kernel leaves the corners of a button out: one frame for both,
|
||||
; its right corners stay out
|
||||
mov edx,[sc.work_button]
|
||||
shr edx,1
|
||||
and edx,0x7F7F7F ; the border colour of a button
|
||||
mov cx,1
|
||||
mcall 13,<BUTTON1_X,BUTTON2_X+ROW_H-1-BUTTON1_X>
|
||||
add ecx,(ROW_H-1) shl 16
|
||||
mcall 13
|
||||
|
||||
lea ebx,[edi+TEXT_DY+(LABEL_X shl 16)]
|
||||
mov ecx,ebp
|
||||
call get_text
|
||||
mcall 4,,[sc.work_text]
|
||||
|
||||
lea ebx,[edi+TEXT_DY+((BUTTON1_X+8) shl 16)]
|
||||
lea edx,[glyphs+ebp*4]
|
||||
mcall 4,,[sc.work_button_text]
|
||||
lea ebx,[edi+TEXT_DY+((BUTTON2_X+8) shl 16)]
|
||||
lea edx,[glyphs+2+ebp*4]
|
||||
mcall 4
|
||||
|
||||
inc ebp
|
||||
cmp ebp,ROWS
|
||||
jb .row
|
||||
|
||||
; group box of the checkboxes: a frame, its title over it on the work colour
|
||||
mcall 13,<GROUP_X,GROUP_W>,<GROUP_Y,GROUP_H>,[sc.work_graph]
|
||||
mcall 13,<GROUP_X+1,GROUP_W-2>,<GROUP_Y+1,GROUP_H-2>,[sc.work]
|
||||
mov ecx,T_GROUP
|
||||
call get_text
|
||||
mov ecx,[sc.work_text]
|
||||
or ecx,0x40000000
|
||||
mcall 4,<GROUP_TITLE_X,GROUP_TITLE_Y>,,,,[sc.work]
|
||||
|
||||
; The checkboxes are spread over the group, the last one ends at its end.
|
||||
; LBA and PCI are fixed, so the step only depends on the speaker label.
|
||||
mov ecx,T_SPEAKER
|
||||
call get_text
|
||||
mov eax,ITEM_END-ITEM_X-CHECK_SIZE-8
|
||||
.length:
|
||||
mov cl,[edx]
|
||||
mov ecx,50*65536+32*(4+stringsAmount)
|
||||
mcall 0,<50,700>,,0xB4111199,0,title
|
||||
; Main buttons
|
||||
mov eax,8
|
||||
mov ecx,6*65536+26
|
||||
mov edx,4
|
||||
mov esi,0x5580c0
|
||||
mov ebp,stringsAmount
|
||||
@@:
|
||||
mcall ,<490,24>
|
||||
inc edx
|
||||
test cl,cl
|
||||
jz .step
|
||||
and cl,0xC0
|
||||
cmp cl,0x80 ; UTF-8 continuation byte
|
||||
jz .length
|
||||
sub eax,8
|
||||
jmp .length
|
||||
.step:
|
||||
shr eax,1
|
||||
mov [checkStep],eax
|
||||
|
||||
; a checkbox: the box (drawn by draw_values), then the label, both under
|
||||
; one button up to the end of the group. The next button covers the rest.
|
||||
xor ebp,ebp
|
||||
.check:
|
||||
mov edi,[checkStep]
|
||||
imul edi,ebp
|
||||
add edi,ITEM_X ; x of the box
|
||||
lea ebx,[edi+CHECK_SIZE+8]
|
||||
shl ebx,16
|
||||
add ebx,CHECK_Y+TEXT_DY
|
||||
call check_label
|
||||
mcall 4,,[sc.work_text]
|
||||
mov ebx,edi
|
||||
shl ebx,16
|
||||
add ebx,ITEM_END
|
||||
sub ebx,edi
|
||||
lea edx,[FIRST_CHECK_BUTTON+BT_HIDE+BT_NOFRAME+ebp]
|
||||
mcall 8,,<CHECK_Y,ROW_H-1>
|
||||
inc ebp
|
||||
cmp ebp,CHECKS
|
||||
jb .check
|
||||
|
||||
mcall ,<526,24>
|
||||
inc edx
|
||||
mcall ,<562,120>
|
||||
inc edx
|
||||
add ecx,32*65536
|
||||
dec ebp
|
||||
jnz @b
|
||||
; APPLY ALL
|
||||
add ecx,32*65536
|
||||
mcall ,<514,168>,,3,0x005588dd
|
||||
; SAVE ALL
|
||||
add ecx,32*65536
|
||||
dec edx
|
||||
mcall
|
||||
mcall 12,2
|
||||
|
||||
;---------------------------------------------------------------
|
||||
draw_values:
|
||||
mov edx,languageNames
|
||||
mov ecx,[language]
|
||||
call nth_string
|
||||
mov [valueText],edx
|
||||
draw_infotext:
|
||||
mov eax,[syslang]
|
||||
mov edi,[text]
|
||||
lea esi,[eax*8+langs]
|
||||
add edi,28
|
||||
movsd
|
||||
movsd
|
||||
add edi,LLL-8
|
||||
|
||||
mov edx,sz_subpixel
|
||||
mov ecx,[fontSmoothing]
|
||||
cmp ecx,2
|
||||
jae @f
|
||||
add ecx,T_OFF
|
||||
call get_text
|
||||
mov eax,[lba_read]
|
||||
call onoff
|
||||
mov [edi],ebx
|
||||
|
||||
mov eax,[pci_acc]
|
||||
call onoff
|
||||
mov [edi+LLL],ebx
|
||||
|
||||
mov eax,[speaker_mute]
|
||||
call onoff
|
||||
mov [edi+LLL*2],ebx
|
||||
|
||||
mov ebx,'SUBP'
|
||||
mov ecx,'IXEL'
|
||||
cmp [fontSmoothing],2
|
||||
jz @f
|
||||
mov eax,[fontSmoothing]
|
||||
call onoff
|
||||
mov ecx,' '
|
||||
@@:
|
||||
mov [valueText+4],edx
|
||||
mov [edi+LLL*3],ebx
|
||||
mov [edi+LLL*3+4],ecx
|
||||
|
||||
mov eax,[fontHeight]
|
||||
mov bl,10
|
||||
mov eax,[fontSize]
|
||||
mov bl, 10
|
||||
div bl
|
||||
add ax,'00'
|
||||
mov word[heightText],ax
|
||||
mov [valueText+8],heightText
|
||||
add ax, '00'
|
||||
mov [edi+LLL*4],ax
|
||||
; draw text
|
||||
mcall 13,<342,96>,32*stringsAmount,80111199h
|
||||
mov eax,4
|
||||
mov ebx,6*65536+11
|
||||
mov ecx,1ffffffh
|
||||
mov edx,[text]
|
||||
mov esi,LLL
|
||||
mov ebp,stringsAmount
|
||||
newline:
|
||||
mcall
|
||||
add ebx,32
|
||||
add edx,esi
|
||||
dec ebp
|
||||
jnz newline
|
||||
|
||||
; each value in a light box framed on three sides, the button is the fourth,
|
||||
; the left corners are cut off
|
||||
xor ebp,ebp
|
||||
.row:
|
||||
imul edi,ebp,ROW_STEP
|
||||
add edi,TOP
|
||||
mov ecx,edi
|
||||
shl ecx,16
|
||||
add ecx,ROW_H
|
||||
mcall 13,<VALUE_X+1,VALUE_W-1>,,[sc.work_graph]
|
||||
add ecx,(1 shl 16)-2
|
||||
mcall 13,<VALUE_X,VALUE_W>
|
||||
; sunken, the inner lines of a button reversed: three boxes, each 1 pixel
|
||||
; smaller, leave darker lines left and top and lighter right and bottom
|
||||
mov edx,[sc.work_light]
|
||||
mov eax,edx
|
||||
shr eax,3
|
||||
and eax,0x1F1F1F
|
||||
sub edx,eax ; 1/8 darker
|
||||
mcall 13,<VALUE_X+1,VALUE_W-1>
|
||||
mov edx,[sc.work_light]
|
||||
or edx,0x1F1F1F ; lighter
|
||||
add ecx,(1 shl 16)-1
|
||||
mcall 13,<VALUE_X+2,VALUE_W-2>
|
||||
dec ecx
|
||||
mcall 13,<VALUE_X+2,VALUE_W-3>,,[sc.work_light]
|
||||
lea ebx,[edi+TEXT_DY+((VALUE_X+VALUE_PAD) shl 16)]
|
||||
mov edx,[valueText+ebp*4]
|
||||
mcall 4,,[sc.work_text]
|
||||
inc ebp
|
||||
cmp ebp,ROWS
|
||||
jb .row
|
||||
mov ebp,2
|
||||
add ebx,32
|
||||
@@:
|
||||
mcall
|
||||
add ebx,32
|
||||
add edx,esi
|
||||
dec ebp
|
||||
jnz @b
|
||||
|
||||
; checkboxes: a frame, light inside, the @RESHARE image when set
|
||||
xor ebp,ebp
|
||||
.check:
|
||||
mov ebx,[checkStep]
|
||||
imul ebx,ebp
|
||||
add ebx,ITEM_X
|
||||
shl ebx,16
|
||||
add ebx,CHECK_SIZE
|
||||
mcall 13,,<CHECK_BOX_Y,CHECK_SIZE>,[sc.work_graph]
|
||||
add ebx,(1 shl 16)-2
|
||||
mcall 13,,<CHECK_BOX_Y+1,CHECK_SIZE-2>,[sc.work_light]
|
||||
mov eax,[checks+ebp*8]
|
||||
mov eax,[eax]
|
||||
xor eax,[checks+ebp*8+4]
|
||||
jz .next
|
||||
mov edx,ebx
|
||||
mov dx,CHECK_BOX_Y+1
|
||||
mov ebx,[checkboxImage]
|
||||
test ebx,ebx ; no @RESHARE: the box stays empty
|
||||
jz .next
|
||||
mcall 7,,<CHECK_SIZE-2,CHECK_SIZE-2>
|
||||
.next:
|
||||
inc ebp
|
||||
cmp ebp,CHECKS
|
||||
jb .check
|
||||
|
||||
;---------------------------------------------------------------
|
||||
still:
|
||||
mcall 10
|
||||
cmp eax,1
|
||||
jz draw_window
|
||||
|
||||
cmp eax,2
|
||||
jz .key
|
||||
jz key
|
||||
|
||||
cmp eax,3
|
||||
jnz still
|
||||
jz button
|
||||
|
||||
mcall 17
|
||||
shr eax,8
|
||||
cmp eax,1
|
||||
jz quit
|
||||
sub eax,FIRST_ROW_BUTTON
|
||||
jb still ; 0: no button after all
|
||||
cmp eax,FIRST_CHECK_BUTTON-FIRST_ROW_BUTTON
|
||||
jae .check
|
||||
|
||||
; '-' or '+' of a row: step the value within the limits of the row
|
||||
shr eax,1 ; eax = row, CF = '+'
|
||||
lea esi,[eax*3]
|
||||
lea esi,[rows+esi*4]
|
||||
mov edi,[esi]
|
||||
mov ecx,[edi]
|
||||
jc .plus
|
||||
cmp ecx,[esi+4]
|
||||
jbe still
|
||||
dec ecx
|
||||
jmp .set
|
||||
.plus:
|
||||
cmp ecx,[esi+8]
|
||||
jae still
|
||||
inc ecx
|
||||
.set:
|
||||
mov [edi],ecx
|
||||
push eax
|
||||
call apply_and_save
|
||||
pop eax
|
||||
cmp eax,1 ; the language and the font smoothing
|
||||
jbe draw_window ; change all the texts: repaint the window
|
||||
jmp draw_values
|
||||
|
||||
.check:
|
||||
mov eax,[checks-(FIRST_CHECK_BUTTON-FIRST_ROW_BUTTON)*8+eax*8]
|
||||
xor dword[eax],1
|
||||
call apply_and_save
|
||||
jmp draw_values
|
||||
|
||||
.key:
|
||||
jmp still
|
||||
;---------------------------------------------------------------
|
||||
key:
|
||||
mcall 2
|
||||
jmp still
|
||||
|
||||
;---------------------------------------------------------------
|
||||
; every change takes effect at once and is kept in system.ini
|
||||
apply_and_save:
|
||||
call settings_apply
|
||||
jmp settings_save_ini
|
||||
|
||||
; edx = label of the checkbox ebp
|
||||
check_label:
|
||||
mov edx,[checkLabels+ebp*4]
|
||||
test edx,edx
|
||||
jnz @f
|
||||
mov ecx,T_SPEAKER
|
||||
call get_text
|
||||
button:
|
||||
mcall 17
|
||||
shr eax,8
|
||||
call dword[eax*4+buttonTab-4]
|
||||
jmp draw_infotext
|
||||
close:
|
||||
pop eax
|
||||
mcall -1
|
||||
language1:
|
||||
dec [syslang]
|
||||
jns @f
|
||||
mov [syslang],7
|
||||
jmp @f
|
||||
language2:
|
||||
inc [syslang]
|
||||
cmp [syslang],8
|
||||
jc @f
|
||||
mov [syslang],0
|
||||
@@:
|
||||
pop eax
|
||||
jmp loadtxt
|
||||
LBA1:
|
||||
btr [lba_read],0
|
||||
ret
|
||||
LBA2:
|
||||
bts [lba_read],0
|
||||
ret
|
||||
PCI1:
|
||||
btr [pci_acc],0
|
||||
ret
|
||||
PCI2:
|
||||
bts [pci_acc],0
|
||||
ret
|
||||
SPEAKER1:
|
||||
btr [speaker_mute],0
|
||||
ret
|
||||
SPEAKER2:
|
||||
bts [speaker_mute],0
|
||||
ret
|
||||
font1:
|
||||
cmp [fontSmoothing],0
|
||||
jz @f
|
||||
dec [fontSmoothing]
|
||||
ret
|
||||
font2:
|
||||
cmp [fontSmoothing],2
|
||||
jz @f
|
||||
inc [fontSmoothing]
|
||||
ret
|
||||
fontSize1:
|
||||
cmp [fontSize],10
|
||||
jc @f
|
||||
dec [fontSize]
|
||||
@@:
|
||||
ret
|
||||
|
||||
; edx = string number ecx of the window language
|
||||
get_text:
|
||||
mov edx,[text]
|
||||
; edx = string number ecx of the zero separated list at edx
|
||||
nth_string:
|
||||
jecxz .done
|
||||
@@:
|
||||
inc edx
|
||||
cmp byte[edx-1],0
|
||||
jnz @b
|
||||
loop @b
|
||||
.done:
|
||||
fontSize2:
|
||||
inc [fontSize]
|
||||
ret
|
||||
apply_all:
|
||||
call _lba_read
|
||||
call _pci_acc
|
||||
call _speaker_mute
|
||||
call fontApply
|
||||
call fontSizeApply
|
||||
_syslang:
|
||||
mov ecx,[syslang]
|
||||
inc ecx
|
||||
mcall 21,5
|
||||
ret
|
||||
_lba_read:
|
||||
mcall 21,11,[lba_read]
|
||||
ret
|
||||
_pci_acc:
|
||||
mcall 21,12,[pci_acc]
|
||||
ret
|
||||
fontApply:
|
||||
mcall 48,10,[fontSmoothing]
|
||||
ret
|
||||
fontSizeApply:
|
||||
mcall 48,12,[fontSize]
|
||||
ret
|
||||
_speaker_mute:
|
||||
mcall 18,8,1
|
||||
cmp [speaker_mute],eax
|
||||
jz @f
|
||||
inc ecx
|
||||
mcall 18
|
||||
@@:
|
||||
ret
|
||||
;---------------------------------------------------------------
|
||||
onoff:
|
||||
cmp [syslang],3
|
||||
jz .ru
|
||||
cmp [syslang],5
|
||||
jz .et
|
||||
mov ebx,'OFF '
|
||||
test eax,eax
|
||||
jz @f
|
||||
mov ebx,'ON '
|
||||
ret
|
||||
.ru:
|
||||
mov ebx,'НЕТ '
|
||||
test eax,eax
|
||||
jz @f
|
||||
mov ebx,'ДА '
|
||||
ret
|
||||
.et:
|
||||
mov ebx,'V─L.'
|
||||
test eax,eax
|
||||
jz @f
|
||||
mov ebx,'SEES'
|
||||
@@:
|
||||
ret
|
||||
;---------------------------------------------------------------
|
||||
saveAll:
|
||||
; system language
|
||||
mov eax,[syslang]
|
||||
mov ax, word[eax*2+langMarks]
|
||||
mov [param],eax
|
||||
invoke ini.set_str, sz_ini, sz_system, sz_language, param, 2
|
||||
|
||||
; font size
|
||||
invoke ini.set_int, sz_ini, sz_system, sz_fontSize, [fontSize]
|
||||
|
||||
; font smoothing
|
||||
mov dword[param],'off'
|
||||
cmp [fontSmoothing],0
|
||||
jz @f
|
||||
mov dword[param],'on '
|
||||
cmp [fontSmoothing],1
|
||||
jz @f
|
||||
mov dword[param],'sbp'
|
||||
@@:
|
||||
invoke ini.set_str, sz_ini, sz_system, sz_fontSmooth, param, 3
|
||||
|
||||
; system speaker
|
||||
mov dword[param],'off'
|
||||
cmp [speaker_mute],0
|
||||
jz @f
|
||||
mov dword[param],'on '
|
||||
@@:
|
||||
invoke ini.set_str, sz_ini, sz_system, sz_speaker, param, 3
|
||||
|
||||
; LBA access for applications
|
||||
mov dword[param],'off'
|
||||
cmp [lba_read],0
|
||||
jz @f
|
||||
mov dword[param],'on '
|
||||
@@:
|
||||
invoke ini.set_str, sz_ini, sz_low_level, sz_lba, param, 3
|
||||
|
||||
; PCI access for applications
|
||||
mov dword[param],'off'
|
||||
cmp [pci_acc],0
|
||||
jz @f
|
||||
mov dword[param],'on '
|
||||
@@:
|
||||
invoke ini.set_str, sz_ini, sz_low_level, sz_pci, param, 3
|
||||
ret
|
||||
;---------------------------------------------------------------
|
||||
; DATA
|
||||
align 4
|
||||
buttonTab: ; button handler pointers: -,+,apply
|
||||
dd close
|
||||
dd saveAll
|
||||
dd apply_all
|
||||
dd language1
|
||||
dd language2
|
||||
dd _syslang
|
||||
dd LBA1
|
||||
dd LBA2
|
||||
dd _lba_read
|
||||
dd PCI1
|
||||
dd PCI2
|
||||
dd _pci_acc
|
||||
dd SPEAKER1
|
||||
dd SPEAKER2
|
||||
dd _speaker_mute
|
||||
dd font1
|
||||
dd font2
|
||||
dd fontApply
|
||||
dd fontSize1
|
||||
dd fontSize2
|
||||
dd fontSizeApply
|
||||
|
||||
@IMPORT:
|
||||
library libini, 'libini.obj'
|
||||
import libini, \
|
||||
@@ -319,88 +465,76 @@ import libini, \
|
||||
ini.set_str, 'ini_set_str',\
|
||||
ini.set_int, 'ini_set_int'
|
||||
|
||||
ROWS = 3
|
||||
CHECKS = 3
|
||||
FIRST_ROW_BUTTON = 10 ; row N has '-' = 10+N*2 and '+' = 11+N*2
|
||||
FIRST_CHECK_BUTTON = 20
|
||||
FONT = 0xB0 ; text flags: zero terminated, 8x16 UTF-8
|
||||
|
||||
; layout of the client area: controls ROW_H high, GAP empty pixels apart,
|
||||
; EDGE to the window border, GAP at the top
|
||||
LABEL_CHARS = 20 ; the longest label, Spanish
|
||||
GAP = 12
|
||||
EDGE = 8
|
||||
TOP = GAP
|
||||
ROW_H = 24
|
||||
ROW_STEP = ROW_H + GAP
|
||||
TEXT_DY = 5 ; the capitals, rows 2..11 of the font, centred in ROW_H
|
||||
LABEL_X = EDGE - 1 ; column 0 of a letter is empty: aligned with the group frame
|
||||
VALUE_X = LABEL_X + LABEL_CHARS*8 + GAP
|
||||
VALUE_PAD = GAP
|
||||
VALUE_W = 8*8 + VALUE_PAD*2
|
||||
BUTTON1_X = VALUE_X + VALUE_W ; right after the value box
|
||||
BUTTON2_X = BUTTON1_X + ROW_H - 1 ; the buttons share a border
|
||||
CLIENT_W = BUTTON2_X + ROW_H + EDGE
|
||||
GROUP_X = EDGE
|
||||
GROUP_W = CLIENT_W - EDGE*2
|
||||
GROUP_Y = TOP + ROWS*ROW_STEP + 5 ; GAP to the capitals of the title
|
||||
GROUP_TITLE_Y = GROUP_Y - 7 ; the frame crosses the capitals
|
||||
CHECK_Y = GROUP_Y + 1 + GAP ; the row of the checkboxes
|
||||
GROUP_H = 1 + GAP + ROW_H + GAP + 1
|
||||
CHECK_SIZE = 15
|
||||
CHECK_BOX_Y = CHECK_Y + (ROW_H-CHECK_SIZE)/2
|
||||
ITEM_X = GROUP_X + 1 + GAP
|
||||
ITEM_END = GROUP_X + GROUP_W - GAP ; the last column of a letter is empty
|
||||
GROUP_TITLE_X = ITEM_X - 8 - 1 ; a space, then a letter from its column 1
|
||||
CLIENT_H = GROUP_Y + GROUP_H + EDGE
|
||||
|
||||
; variable, min, max of every row
|
||||
align 4
|
||||
rows:
|
||||
dd language, 0, LANGUAGES-1
|
||||
dd fontSmoothing, 0, 2
|
||||
dd fontHeight, FONT_H_MIN, FONT_H_MAX
|
||||
|
||||
; variable and the value of it that means 'not checked'
|
||||
checks dd lba,0, pci,0, speakerMute,1
|
||||
checkLabels dd sz_lba, sz_pci, 0 ; 0: the speaker label of the language
|
||||
|
||||
glyphs db '<',0,'>',0,'<',0,'>',0,'-',0,'+',0
|
||||
sz_subpixel db 'Subpixel',0
|
||||
languageNames db 'English',0,'Finnish',0,'German',0,'Russian',0
|
||||
db 'French',0,'Estonian',0,'Spanish',0,'Italian',0
|
||||
|
||||
title db "System settings",0
|
||||
sz_checkbox db "CHECKBOX",0
|
||||
sz_ini db "/sys/settings/system.ini",0
|
||||
|
||||
; Texts of the window languages: zero terminated strings in this order
|
||||
; (row labels, group title, speaker label, 'off', 'on')
|
||||
T_GROUP = ROWS
|
||||
T_SPEAKER = ROWS + 1
|
||||
T_OFF = ROWS + 2
|
||||
sz_system db "system",0
|
||||
sz_language db "language",0
|
||||
sz_fontSize db "font height",0
|
||||
sz_fontSmooth db "font smoothing",0
|
||||
sz_speaker db "speaker mute",0
|
||||
|
||||
; the texts of every kernel language, English where there is no translation
|
||||
texts dd texteng, texteng, texteng, textrus, texteng, texteng, textspa, texteng
|
||||
sz_mouse db "mouse",0
|
||||
sz_speed db "speed",0
|
||||
sz_acceleration db "acceleration",0
|
||||
sz_double_click_delay db "double_click_delay",0
|
||||
|
||||
texteng db 'System language',0, 'Font smoothing',0, 'Font height',0
|
||||
db ' Access settings ',0, 'Speaker',0
|
||||
db 'Off',0, 'On',0
|
||||
sz_low_level db "low-level",0
|
||||
sz_lba db "LBA",0
|
||||
sz_pci db "PCI",0
|
||||
|
||||
textspa db 'Idioma del sistema',0, 'Suavizado de fuentes',0, 'Altura de fuente',0
|
||||
db ' Ajustes de acceso ',0, 'Altavoz',0
|
||||
db 'No',0, 'Sí',0
|
||||
LLL = 56
|
||||
stringsAmount = 6
|
||||
|
||||
textrus db 'Язык системы',0, 'Сглаживание шрифтов',0, 'Высота шрифтов',0
|
||||
db ' Настройки доступа ',0, 'Динамик',0
|
||||
db 'Нет',0, 'Да',0
|
||||
align 4
|
||||
langs:
|
||||
db 'ENGLISH FINNISH GERMAN RUSSIAN FRENCH ESTONIANSPANISH ITALIAN '
|
||||
sz langMarks, 'en','fi','de','ru','fr','et','es','it'
|
||||
|
||||
;---------------------------------------------------------------
|
||||
include 'settings.inc'
|
||||
textrus:
|
||||
db 'Язык системы : < > Применить'
|
||||
db 'Включить LBA : - + Применить'
|
||||
db 'Доступ к шине PCI : - + Применить'
|
||||
db 'Выключить SPEAKER : - + Применить'
|
||||
db 'Сглаживание шрифтов : - + Применить'
|
||||
db 'Высота шрифтов : - + Применить'
|
||||
|
||||
db 'ВНИМАНИЕ: Применить все'
|
||||
db 'НЕ ЗАБУДЬТЕ СОХРАНИТЬ НАСТРОЙКИ Сохранить все'
|
||||
|
||||
text dd ? ; texts of the window language
|
||||
checkboxImage dd ?
|
||||
checkStep dd ? ; x distance of two checkboxes
|
||||
sc system_colors
|
||||
valueText rd ROWS ; the strings shown in the value boxes
|
||||
heightText rb 4
|
||||
texteng:
|
||||
db 'System language : < > Apply '
|
||||
db 'Allow LBA access : - + Apply '
|
||||
db 'Allow PCI access : - + Apply '
|
||||
db 'Disable SPEAKER : - + Apply '
|
||||
db 'Font smoothing : - + Apply '
|
||||
db 'Font height : - + Apply '
|
||||
|
||||
db 'NOTE: Apply all '
|
||||
db 'SAVE YOUR SETTINGS BEFORE QUITING KOLIBRI Save all '
|
||||
|
||||
textet:
|
||||
db 'S№steemi keel : < > Kinnita '
|
||||
db 'LBA lugemine lubatud : - + Kinnita '
|
||||
db 'PCI juurdepффs programm. : - + Kinnita '
|
||||
db 'Disable SPEAKER : - + Kinnita '
|
||||
db 'Font smoothing : - + Kinnita '
|
||||
db 'Font height : - + Kinnita '
|
||||
|
||||
db 'M─RKUS: Kinnita kїik '
|
||||
db 'SALVESTA SEADED ENNE KOLIBRIST V─LJUMIST Salvesta kїik'
|
||||
|
||||
IM_END:
|
||||
|
||||
text dd ?
|
||||
|
||||
syslang dd ?
|
||||
lba_read dd ?
|
||||
pci_acc dd ?
|
||||
speaker_mute dd ?
|
||||
fontSmoothing dd ?
|
||||
fontSize dd ?
|
||||
|
||||
param:
|
||||
rb 1024
|
||||
I_END:
|
||||
Reference in new issue
Block a user