Compare commits

..
Author SHA1 Message Date
Leency dc92660b81 drivers/usbstor: one poll thread for the driver, poll card readers only
Test PR / Build (ru_RU) (pull_request) Failing after 1m18s
Test PR / Build (en_US) (pull_request) Successful in 1m51s
Test PR / Build (es_ES) (pull_request) Successful in 1m54s
- one thread walks a list of devices instead of a thread per device
- poll multi-LUN devices and units empty at attach; plain sticks are skipped
- treat UNIT ATTENTION 06/3A as medium removed

Assisted-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-30 07:23:26 +03:00
Leency 14977ed33f drivers/usbstor: delete disks before dropping the device reference
Test PR / Build (en_US) (pull_request) Successful in 1m45s
Test PR / Build (ru_RU) (pull_request) Successful in 1m52s
Test PR / Build (es_ES) (pull_request) Successful in 1m55s
DeviceDisconnected dropped its reference first and walked the units
afterwards. The polling thread holds its own reference and can release it
at any moment, freeing the unit array under the loop. Delete the disks
while the reference still keeps the structure alive.

Assisted-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-26 18:55:04 +03:00
Leency 5234aadac8 drivers/usbstor: detect media insertion and removal in card readers
Test PR / Build (ru_RU) (pull_request) Successful in 1m48s
Test PR / Build (en_US) (pull_request) Successful in 1m54s
Test PR / Build (es_ES) (pull_request) Successful in 1m58s
A card inserted into an empty slot of a card reader was never seen: empty
units were skipped at attach time and nothing looked at them again.

Every device now gets a thread which sends TEST UNIT READY to its removable
units every 2 s. A unit that becomes ready gets a disk; a unit reporting
"medium not present" (02/3A) or "medium may have changed" (06/28) loses it.
Poll failures are not logged.

Also fix new_disk_thread passing the DISK handle to disk_close when the
device went away during registration; delete the disk instead.

Assisted-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-26 18:42:22 +03:00
25 changed files with 431 additions and 1411 deletions

No files matched your search

-24
View File
@@ -54,27 +54,3 @@
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"
-74
View File
@@ -1,74 +0,0 @@
#!/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"
+1 -2
View File
@@ -34,11 +34,10 @@ jobs:
uses: actions/checkout@v4
with:
submodules: true
token: ${{ secrets.BOT_TOKEN }}
- name: Bump ${{ matrix.name }} and open PR
env:
TOKEN: ${{ secrets.BOT_TOKEN }}
TOKEN: ${{ secrets.GITEA_TOKEN }}
API: ${{ github.api_url }}
REPO: ${{ github.repository }}
NAME: ${{ matrix.name }}
+18 -20
View File
@@ -41,6 +41,10 @@ img_files = {
{"LIB/KMENU.OBJ", "common/lib/kmenu.obj"},
{"LIB/PIXLIB.OBJ", "common/lib/pixlib.obj"},
{"MEDIA/AC97SND", "common/media/ac97snd"},
{"MEDIA/IMGF/IMGF", "common/media/ImgF/ImgF"},
{"MEDIA/IMGF/CEDG.OBJ", "common/media/ImgF/cEdg.obj"},
{"MEDIA/IMGF/DITHER.OBJ", "common/media/ImgF/dither.obj"},
{"MEDIA/IMGF/INVSOL.OBJ", "common/media/ImgF/invSol.obj"},
{"NETWORK/FTPC.INI", SRC_PROGS .. "/network/ftpc/ftpc.ini"},
{"NETWORK/FTPD.INI", "common/network/ftpd.ini"},
{"NETWORK/KNMAP", "common/network/knmap"},
@@ -54,7 +58,8 @@ img_files = {
{"SETTINGS/FB2READ.INI", "common/settings/fb2read.ini"},
{"SETTINGS/HA.CFG", SRC_PROGS .. "/other/ha/SETTINGS/HA.CFG"},
{"SETTINGS/ICON.INI", build_type .. "/settings/icon.ini"},
{"SETTINGS/KEYMAP.KEY", VAR_PROGS .. "/system/taskbar/keymap.key.kpack"},
{"SETTINGS/KEYMAP.KEY", SRC_PROGS .. "/system/taskbar/KEYMAP.KEY"},
{"SETTINGS/KOLIBRI.LBL", build_type .. "/settings/kolibri.lbl"},
{"SETTINGS/LANG.INI", build_type .. "/settings/lang.ini"},
{"SETTINGS/MENU.DAT", build_type .. "/settings/menu.dat"},
{"SETTINGS/NETWORK.INI", "common/settings/network.ini"},
@@ -268,10 +273,6 @@ extra_files = {
{"kolibrios/lib/i915_dri.drv", "common/lib/i915_dri.drv"},
{"kolibrios/media/fplay", "common/media/fplay"},
{"kolibrios/media/fplay_run", "common/media/fplay_run"},
{"kolibrios/media/ImgF/ImgF", "common/media/ImgF/ImgF"},
{"kolibrios/media/ImgF/cEdg.obj", "common/media/ImgF/cEdg.obj"},
{"kolibrios/media/ImgF/dither.obj", "common/media/ImgF/dither.obj"},
{"kolibrios/media/ImgF/invSol.obj", "common/media/ImgF/invSol.obj"},
{"kolibrios/media/minimp3", "common/media/minimp3"},
{"kolibrios/media/updf", SRC .. "/contrib/media/updf/build/uPDF"},
{"kolibrios/media/vttf", "common/media/vttf"},
@@ -486,6 +487,11 @@ tup.append_table(img_files, {
{"DEVELOP/MTDBG", VAR_PROGS .. "/develop/mtdbg/mtdbg"},
{"DEVELOP/MSTATE", VAR_PROGS .. "/develop/mstate/mstate"},
{"DEVELOP/SCANCODE", VAR_PROGS .. "/develop/scancode/scancode"},
{"DEVELOP/EXAMPLES/CIRCLE", VAR_PROGS .. "/develop/examples/circle/circle"},
{"DEVELOP/EXAMPLES/COLORREF", VAR_PROGS .. "/demos/colorref/colorref"},
{"DEVELOP/EXAMPLES/CONGET", VAR_PROGS .. "/develop/libraries/console_coff/examples/test_gets"},
{"DEVELOP/EXAMPLES/CSLIDE", VAR_PROGS .. "/demos/cslide/cslide"},
{"DEVELOP/EXAMPLES/THREAD", VAR_PROGS .. "/develop/examples/thread/thread"},
{"File Managers/KFAR", VAR_PROGS .. "/fs/kfar/kfar"},
{"File Managers/OPENDIAL", VAR_PROGS .. "/fs/opendial/opendial"},
{"LOD", VAR_PROGS .. "/fs/lod/lod"},
@@ -646,28 +652,20 @@ tup.append_table(extra_files, {
{"kolibrios/3D/blocks/block.bin", VAR_PROGS .. "/bcc32/games/blocks/block.bin"},
{"kolibrios/develop/tcc/lib/crt0.o", VAR_PROGS .. "/develop/ktcc/bin/lib/crt0.o", group = "../programs/develop/ktcc/<crt0.o>"},
{"kolibrios/develop/tcc/lib/tiny.o", VAR_PROGS .. "/develop/ktcc/bin/lib/tiny.o", group = "../programs/develop/ktcc/<tiny.o>"},
{"kolibrios/develop/tcc/lib/libsound.a", VAR_PROGS .. "/develop/ktcc/bin/lib/libsound.a", group = "../programs/develop/ktcc/<libsound.a>"},
{"kolibrios/develop/examples/circle", VAR_PROGS .. "/develop/examples/circle/circle"},
{"kolibrios/develop/examples/colorref", VAR_PROGS .. "/demos/colorref/colorref"},
{"kolibrios/develop/examples/conget", VAR_PROGS .. "/develop/libraries/console_coff/examples/test_gets"},
{"kolibrios/develop/examples/cslide", VAR_PROGS .. "/demos/cslide/cslide"},
{"kolibrios/develop/examples/thread", VAR_PROGS .. "/develop/examples/thread/thread"}
{"kolibrios/develop/tcc/lib/libsound.a", VAR_PROGS .. "/develop/ktcc/bin/lib/libsound.a", group = "../programs/develop/ktcc/<libsound.a>"}
})
-- -- For russian build, add russian-only programs.
-- if build_type == "ru_RU" then tup.append_table(img_files, {
-- {"DEVELOP/EXAMPLES/TESTCON2", VAR_PROGS .. "/develop/libraries/console_coff/examples/testcon2_rus"},
-- }) else tup.append_table(img_files, {
-- {"DEVELOP/EXAMPLES/TESTCON2", VAR_PROGS .. "/develop/libraries/console_coff/examples/testcon2_eng"},
-- }) end
-- For russian build, add russian-only programs.
if build_type == "ru_RU" then tup.append_table(img_files, {
{"DEVELOP/EXAMPLES/TESTCON2", VAR_PROGS .. "/develop/libraries/console_coff/examples/testcon2_rus"},
}) else tup.append_table(img_files, {
{"DEVELOP/EXAMPLES/TESTCON2", VAR_PROGS .. "/develop/libraries/console_coff/examples/testcon2_eng"},
}) end
if build_type == "ru_RU" then tup.append_table(extra_files, {
{"kolibrios/develop/examples/testcon2", VAR_PROGS .. "/develop/libraries/console_coff/examples/testcon2_rus"},
{"kolibrios/utils/period", VAR_PROGS .. "/other/period/period"},
{"kolibrios/games/Dungeons/Dungeons", VAR_PROGS .. "/games/Dungeons/Dungeons"},
{"kolibrios/games/klavisha/klavisha", VAR_PROGS .. "/games/klavisha/klavisha"},
{"kolibrios/games/klavisha/basekurs.kla", "ru_RU/games/basekurs.kla"},
}) else tup.append_table(extra_files, {
{"kolibrios/develop/examples/testcon2", VAR_PROGS .. "/develop/libraries/console_coff/examples/testcon2_eng"},
}) end
end -- tup.getconfig('NO_FASM') ~= 'full'
+1 -1
View File
@@ -40,7 +40,7 @@
06 zSea Image Viewer * |/kolibrios/media/zsea/zsea
38 Animage |media/animage
38 IconEdit |media/iconedit
40 Image Filtering * |/kolibrios/media/ImgF/ImgF
40 Image Filtering |media/imgf/imgf
52 Palitra |media/palitra
39 Pipet |develop/pipet
#4 **** MULTIMEDIA
+1 -1
View File
@@ -41,7 +41,7 @@
16 Image viewer KIV |media/kiv
16 Image viewer zSea * |/kolibrios/media/zsea/zsea
16 Animage |media/animage
16 Efectos de imаgenes * |/kolibrios/media/ImgF/ImgF
16 Efectos de imаgenes |media/imgf/imgf
16 Palitra |media/palitra
#4 **** MULTIMEDIA
16 Pixie Audioplayer |media/pixie
+1 -1
View File
@@ -41,7 +41,7 @@
06 Image viewer zSea * |/kolibrios/media/zsea/zsea
38 Animage |media/animage
38 IconEdit |media/iconedit
16 Image Filtering * |/kolibrios/media/ImgF/ImgF
16 Image Filtering |media/imgf/imgf
52 Palitra |media/palitra
39 Pipet |develop/pipet
#4 **** MULTIMEDIA ****
+1 -1
View File
@@ -41,7 +41,7 @@
06 Image viewer zSea * |/kolibrios/media/zsea/zsea
38 Animage |media/animage
38 IconEdit |media/iconedit
40 Image Filtering * |/kolibrios/media/ImgF/ImgF
40 Image Filtering |media/imgf/imgf
52 Palitra |media/palitra
39 Pipet |develop/pipet
#4 **** MULTIMEDIA
+1 -1
View File
@@ -40,7 +40,7 @@
06 Просмотр фото zSea |/kolibrios/media/zsea/zsea
38 Редактор Animage |media/animage
38 Редактор иконок |media/iconedit
40 Наложение фильтров * |/kolibrios/media/ImgF/ImgF
40 Наложение фильтров |media/imgf/imgf
52 Палитра |media/palitra
39 Пипетка |develop/pipet
#4 **** Звук и видео
+14 -100
View File
@@ -130,8 +130,6 @@ 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
@@ -185,8 +183,6 @@ 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
@@ -632,9 +628,6 @@ 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
@@ -659,7 +652,6 @@ 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
@@ -686,11 +678,6 @@ 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
@@ -702,7 +689,6 @@ 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
@@ -723,15 +709,6 @@ 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]
@@ -786,7 +763,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.virt_addr], 0 ; buffer not reclaimed yet
cmp [edi + txfd.status], 0
jne .overrun
; Fill in status and command values
@@ -809,22 +786,6 @@ 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
@@ -893,7 +854,7 @@ int_handler:
DEBUGF 1,"Status: %x\n", ax
test ax, SCB_STATUS_FR or SCB_STATUS_RNR ; frame received or receiver stopped?
test ax, SCB_STATUS_FR ; did we receive a frame?
jz .no_rx
push ax
@@ -940,7 +901,6 @@ 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
@@ -956,22 +916,11 @@ 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
@@ -996,27 +945,6 @@ 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:
@@ -1027,13 +955,13 @@ int_handler:
push eax
.loop_tx:
mov eax, [ebx + device.last_tx]
mov edx, sizeof.txfd
mul edx
mov edi, [ebx + device.last_tx]
mov eax, sizeof.txfd
mul eax
lea edi, [ebx + device.tx_ring + eax]
test [edi + txfd.status], TXFD_STATUS_C ; sent by the device?
jz .tx_done
cmp [edi + txfd.status], 0
je .tx_done
cmp [edi + txfd.virt_addr], 0
je .tx_done
@@ -1042,7 +970,6 @@ 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]
@@ -1053,6 +980,12 @@ 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
@@ -1146,25 +1079,6 @@ 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:
+249 -24
View File
@@ -167,6 +167,8 @@ LogicalDevices dd ? ; pointer to array of usb_unit_data
; 1 for a connected USB device, 1 for each disk device
; the structure can be freed when .NumReferences decreases to zero
NumReferences dd ? ; number of references
PollNext dd ?
PollPrev dd ?
ConfigRequest rb 8 ; buffer for configuration requests
LengthRest dd ? ; Length - (size of data which were transferred)
; All requests to a given device are serialized,
@@ -193,7 +195,7 @@ Parent dd ? ; pointer to parent usb_device_data
LUN db ? ; index in usb_device_data.LogicalDevices array
DiskIndex db ? ; for name "usbhd<index>"
MediaPresent db ?
db ? ; alignment
Polled db ?
DiskDevice dd ? ; handle of disk device or NULL
SectorSize dd ? ; sector size
; For some devices, the first request to the medium fails with 'unit not ready'.
@@ -248,6 +250,20 @@ end virtual
; The name is my_driver = 'usbstor'; IOCTL interface is not supported;
; usb_functions is an offset of a structure with callback functions.
invoke RegUSBDriver, my_driver, 0, usb_functions
test eax, eax
jz .nothing
push eax ebx
mov ecx, poll_lock
invoke MutexInit
mov [poll_head], poll_list
mov [poll_head+4], poll_list
movi ebx, 1
mov ecx, poll_thread
xor edx, edx
invoke CreateThread
cmp eax, -1
setnz [poll_running]
pop ebx eax
; 4. Return the returned value of RegUSBDriver.
.nothing:
ret
@@ -324,6 +340,9 @@ endp
proc complete_request
; 1. Print common debug messages on fails.
if DEBUG
mov ebx, [esi+usb_device_data.RequestsQueue+request_queue_item.Next]
cmp [ebx+request_queue_item.Callback], poll_tur_callback
jz .normal
cmp [esi+usb_device_data.Status.Status], CSW_STATUS_FAIL
jb .normal
jz .fail
@@ -1293,6 +1312,7 @@ end virtual
mov [esi+usb_unit_data.LUN], cl
xor eax, eax
mov [esi+usb_unit_data.MediaPresent], al
mov [esi+usb_unit_data.Polled], al
mov [esi+usb_unit_data.DiskDevice], eax
mov [esi+usb_unit_data.SectorSize], eax
mov [esi+usb_unit_data.UnitReadyAttempts], eax
@@ -1305,6 +1325,19 @@ end virtual
add esi, sizeof.usb_unit_data
cmp ecx, [ebx+usb_device_data.MaxLUN]
jbe .looplun
cmp [poll_running], 0
jz @f
lock inc [ebx+usb_device_data.NumReferences]
mov ecx, poll_lock
invoke MutexLock
mov eax, [poll_head+4]
mov [ebx+usb_device_data.PollNext], poll_list
mov [ebx+usb_device_data.PollPrev], eax
mov [eax+usb_device_data.PollNext], ebx
mov [poll_head+4], ebx
mov ecx, poll_lock
invoke MutexUnlock
@@:
; 4. Return.
pop esi ebx
ret 20
@@ -1338,11 +1371,14 @@ proc inquiry_callback
test al, al
jnz .nothing
DEBUGF 1,'K : direct-access mass storage device detected\n'
; Units that report 'medium not present' (the empty card slot of an LTE
; modem or card reader) are not registered: the kernel has no media
; change detection, so such a disk would only sit dead in the file
; managers. Replugging the device after inserting a card registers it.
mov edx, [esp+8]
cmp [ecx+usb_device_data.MaxLUN], 0
jnz .poll
cmp [edx+usb_unit_data.MediaPresent], 0
jnz @f
.poll:
mov [edx+usb_unit_data.Polled], 1
@@:
cmp [edx+usb_unit_data.MediaPresent], 0
jnz @f
DEBUGF 1,'K : no media, not registering the disk\n'
@@ -1435,15 +1471,16 @@ end virtual
endp
; Temporary thread for initial actions with a new disk device.
proc new_disk_thread
new_disk_thread:
stdcall add_disk, [esp]
or eax, -1
int 0x40
proc add_disk
push ebx esi edi
mov esi, [esp+16]
sub esp, 32
virtual at esp
.name rb 32 ; device name
.param dd ? ; contents of edx at the moment of int 0x40/eax=51
dd ? ; stack segment
end virtual
; We are ready to notify the kernel about a new disk device.
mov esi, [.param]
; 1. Generate name.
; 1a. Find a free index.
mov ecx, free_numbers_lock
@@ -1512,7 +1549,7 @@ end virtual
jmp .exit
.disconnected:
invoke MutexUnlock
stdcall disk_close, ebx
invoke DiskDel, ebx
jmp .exit
.free_index:
mov ecx, free_numbers_lock
@@ -1521,6 +1558,7 @@ end virtual
bts [free_numbers], eax
invoke MutexUnlock
.drop_reference:
mov [esi+usb_unit_data.MediaPresent], 0
mov esi, [esi+usb_unit_data.Parent]
lock dec [esi+usb_device_data.NumReferences]
jnz .exit
@@ -1529,8 +1567,186 @@ end virtual
xchg eax, esi
invoke Kfree
.exit:
or eax, -1
add esp, 32
pop edi esi ebx
ret 4
endp
; Every POLL_INTERVAL, check removable units for inserted or removed media.
POLL_INTERVAL = 200
POLL_READY = 0
POLL_NO_MEDIA = 1
POLL_CHANGED = 2
POLL_OTHER = 3
proc poll_thread
.loop:
movi eax, 5
mov ebx, POLL_INTERVAL
int 0x40
mov ecx, poll_lock
invoke MutexLock
mov ebx, [poll_head]
.device:
cmp ebx, poll_list
jz .done
mov ecx, poll_lock
invoke MutexUnlock
cmp [ebx+usb_device_data.DeviceDisconnected], 0
jnz .remove
mov esi, [ebx+usb_device_data.LogicalDevices]
mov edi, [ebx+usb_device_data.MaxLUN]
inc edi
.unit:
cmp [esi+usb_unit_data.Polled], 0
jz .next
call poll_unit
.next:
add esi, sizeof.usb_unit_data
dec edi
jnz .unit
mov ecx, poll_lock
invoke MutexLock
mov ebx, [ebx+usb_device_data.PollNext]
jmp .device
.remove:
mov ecx, poll_lock
invoke MutexLock
mov eax, [ebx+usb_device_data.PollNext]
mov edx, [ebx+usb_device_data.PollPrev]
mov [edx+usb_device_data.PollNext], eax
mov [eax+usb_device_data.PollPrev], edx
push eax
lock dec [ebx+usb_device_data.NumReferences]
jnz @f
mov eax, [ebx+usb_device_data.LogicalDevices]
invoke Kfree
xchg eax, ebx
invoke Kfree
@@:
pop ebx
jmp .device
.done:
mov ecx, poll_lock
invoke MutexUnlock
jmp .loop
endp
proc poll_unit
push edi
stdcall poll_tur, ebx, esi
cmp [esi+usb_unit_data.MediaPresent], 0
jnz .registered
cmp eax, POLL_CHANGED
jnz @f
stdcall poll_tur, ebx, esi
@@:
cmp eax, POLL_READY
jnz .done
movzx eax, [esi+usb_unit_data.LUN]
DEBUGF 1,'K : medium inserted, LUN %d\n',eax
mov [esi+usb_unit_data.MediaPresent], 1
lock inc [ebx+usb_device_data.NumReferences]
stdcall add_disk, esi
jmp .done
.registered:
cmp eax, POLL_NO_MEDIA
jz .removed
cmp eax, POLL_CHANGED
jnz .done
.removed:
lea ecx, [ebx+usb_device_data.QueueLock]
invoke MutexLock
xor edi, edi
cmp [ebx+usb_device_data.DeviceDisconnected], 0
jnz @f
xchg edi, [esi+usb_unit_data.DiskDevice]
@@:
lea ecx, [ebx+usb_device_data.QueueLock]
invoke MutexUnlock
test edi, edi
jz .done
movzx eax, [esi+usb_unit_data.LUN]
DEBUGF 1,'K : medium removed, LUN %d\n',eax
invoke DiskDel, edi
.done:
pop edi
ret
endp
proc poll_tur stdcall uses ebx esi edi, device:dword, unit:dword
xor esi, esi
xor ecx, ecx
invoke CreateEvent
test eax, eax
jz .fail
push eax
push edx
push POLL_OTHER
push [unit]
mov edx, esp
stdcall queue_request, [device], poll_tur_req, 0, poll_tur_callback, edx
mov eax, [esp+12]
mov ebx, [esp+8]
invoke WaitEvent
mov eax, [esp+4]
add esp, 16
ret
.fail:
movi eax, POLL_OTHER
ret
endp
proc poll_tur_req
mov eax, [esp+8]
mov eax, [eax]
mov al, [eax+usb_unit_data.LUN]
mov [edx+command_block_wrapper.Length], 0
mov [edx+command_block_wrapper.Flags], CBW_FLAG_IN
mov [edx+command_block_wrapper.LUN], al
mov byte [edx+usb_device_data.Sense.ErrorCode-usb_device_data.Command], 0
ret 8
endp
proc poll_tur_callback
mov ecx, [esp+4]
xor eax, eax
mov dl, [ecx+usb_device_data.Status.Status]
cmp dl, CSW_STATUS_OK
jz .done
mov al, POLL_OTHER
cmp dl, CSW_STATUS_FAIL
jnz .done
mov dl, [ecx+usb_device_data.Sense.ErrorCode]
and dl, 7Eh
cmp dl, 70h
jnz .done
mov dl, [ecx+usb_device_data.Sense.SenseKey]
and dl, 0Fh
mov dh, [ecx+usb_device_data.Sense.AdditionalSenseCode]
cmp dx, (3Ah shl 8) + SENSE_NOT_READY
jz .no_media
cmp dx, (3Ah shl 8) + SENSE_UNIT_ATTENTION
jnz @f
.no_media:
mov al, POLL_NO_MEDIA
jmp .done
@@:
cmp dx, (28h shl 8) + SENSE_UNIT_ATTENTION
jnz .done
mov al, POLL_CHANGED
.done:
mov ecx, [esp+8]
mov [ecx+4], eax
push ebx esi edi
mov eax, [ecx+12]
mov ebx, [ecx+8]
xor edx, edx
xor esi, esi
invoke RaiseEvent
pop edi esi ebx
ret 8
endp
; This function is called when the device is disconnected.
@@ -1559,16 +1775,15 @@ end virtual
invoke MutexLock
mov [esi+usb_device_data.DeviceDisconnected], 1
invoke MutexUnlock
; 3. Drop one reference to the structure and check whether
; that was the last reference.
lock dec [esi+usb_device_data.NumReferences]
jz .free
; 4. If not, there are some additional references due to disk devices;
; notify the kernel that those disks are deleted.
; 3. Notify the kernel that all disk devices are deleted.
; Note that new disks cannot be added while we are looping here,
; because new_disk_thread checks for .DeviceDisconnected.
mov eax, [esi+usb_device_data.LogicalDevices]
test eax, eax
jz .unref
push esi
mov ebx, [esi+usb_device_data.MaxLUN]
mov esi, [esi+usb_device_data.LogicalDevices]
mov esi, eax
inc ebx
.diskdel:
mov eax, [esi+usb_unit_data.DiskDevice]
@@ -1579,12 +1794,17 @@ end virtual
add esi, sizeof.usb_unit_data
dec ebx
jnz .diskdel
; In this case, some operations with those disks are still possible,
; so we can't do anything more now. disk_close will take care of the rest.
pop esi
.unref:
; 4. Drop one reference to the structure and check whether
; that was the last reference. If not, some operations with the disks
; are still possible; disk_close will take care of the rest.
lock dec [esi+usb_device_data.NumReferences]
jz .free
.return:
pop esi ebx
ret 4
; 5. If there are no disk devices, free all resources which were allocated.
; 5. If that was the last reference, free all resources which were allocated.
.free:
mov eax, [esi+usb_device_data.LogicalDevices]
test eax, eax
@@ -1617,6 +1837,7 @@ end virtual
movzx eax, [esi+usb_unit_data.DiskIndex]
bts [free_numbers], eax
invoke MutexUnlock
mov [esi+usb_unit_data.MediaPresent], 0
mov esi, [esi+usb_unit_data.Parent]
lock dec [esi+usb_device_data.NumReferences]
jnz .nothing
@@ -2066,6 +2287,10 @@ data fixups
end data
free_numbers_lock rd 3
poll_lock rd 3
poll_head rd 2
poll_list = poll_head - usb_device_data.PollNext
poll_running db ?
; 128 devices should be enough for everybody
free_numbers dd -1, -1, -1, -1
File diff suppressed because it is too large. Load diff
+13 -15
View File
@@ -1233,27 +1233,25 @@ f68:
mov eax, [ecx + SRV.entry]
test eax, eax
jz .fail
mov eax, -2 ;error free RAM
cmp [ecx + SRV.base], 0
je .fail
push ecx ;save handl
push ecx ;save handl
mov ebp, esp ;START may be cdecl or stdcall
push edx ;cmdline
push DRV_EXIT
call [ecx + SRV.entry] ;the result is not checked
mov esp, ebp
pop esi
call eax ;the result is not checked
lea esp, [esp+8]
push ecx
mov eax, [esi + SRV.fd]
mov edx, [esi + SRV.bk]
mov ebx, [ecx + SRV.base]
mov eax, -2 ;error free RAM
test ebx, ebx
jz .fail
stdcall kernel_free, ebx ;del driver
mov eax, [ecx + SRV.fd]
mov edx, [ecx + SRV.bk]
mov [edx + SRV.fd], eax
mov [eax + SRV.bk], edx
push eax
stdcall kernel_free, [esi + SRV.base] ;del driver
mov eax, esi
call free ;eax = mem
pop eax
stdcall free, ecx
;dec [count_services]
mov [esp + SYSCALL_STACK.eax], eax
-28
View File
@@ -83,31 +83,6 @@ 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 ;
@@ -338,9 +313,6 @@ 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
+1 -40
View File
@@ -105,29 +105,6 @@ 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 ;
@@ -780,8 +757,6 @@ 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
@@ -992,8 +967,6 @@ 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
@@ -1010,10 +983,7 @@ 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
@@ -1079,23 +1049,14 @@ 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, edx
mov ebx, [IPv4_address + edi]
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
+1 -44
View File
@@ -61,41 +61,6 @@ 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.
@@ -280,9 +245,6 @@ 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
@@ -333,16 +295,11 @@ eth_output:
ret
.too_large:
inc [ebx + NET_DEVICE.packets_tx_err]
inc [eax + 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
;-----------------------------------------------------------------;
-10
View File
@@ -597,16 +597,6 @@ 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
+2 -6
View File
@@ -1422,14 +1422,10 @@ endl
test [edx + TCP_header.Flags], TH_ACK
jz .drop
push ebx
lea ecx, [ebx + SOCKET.mutex]
call mutex_unlock
pop eax
mov eax, ebx
mov ebx, ECONNREFUSED
call tcp_drop
jmp .drop_no_socket
jmp .drop
@@:
;-----------------------------------------------------------------------------------
+8 -10
View File
@@ -234,25 +234,23 @@ endl
mov ebx, TCP_max_win
shl ebx, cl
pop ecx
; Clamp to available window first, then subtract what the peer already knows (as in BSD)
cmp ebx, ecx
jbe @f
mov ebx, ecx
@@:
sub ebx, [eax + TCP_SOCKET.RCV_ADV]
add ebx, [eax + TCP_SOCKET.RCV_NXT]
cmp ebx, ecx
jl @f
mov ebx, ecx
@@:
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 ; signed: may be negative if window shrank
jge .send
cmp ebx, edi
jae .send
cmp ebx, SOCKET_BUFFER_SIZE/2
jge .send
jae .send
.no_window:
-4
View File
@@ -180,8 +180,6 @@ tcp_connect:
.nomem:
pop edx eax
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
xor eax, eax
dec eax
mov ebx, ENOMEM
@@ -196,8 +194,6 @@ tcp_connect:
.enoroute:
pop eax
popa
lea ecx, [eax + SOCKET.mutex]
call mutex_unlock
xor eax, eax
dec eax
mov ebx, EADDRNOTAVAIL
+3 -5
View File
@@ -1618,23 +1618,21 @@ endl
; Open a new TCP socket
mcall socket, AF_INET4, SOCK_STREAM, 0
cmp eax, -1
je .error3
test eax, eax
jz .error3
mov [socketnum], eax
DEBUGF 1, "Socket: 0x%x\n", eax
; Connect to the server
mcall connect, [socketnum], [sockaddr], 18
test eax, eax
jnz .error4
jnz .error3
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,8 +501,7 @@ img.decode.jpg:
jnz .no_create_palette
push ecx edi
mov edi, [eax + Image.Palette]
mov eax, 0xFF000000 ; opaque, like the palettes of the other decoders:
; converted to 32 bpp, alpha 0 made the picture invisible
xor eax, eax
mov ecx, 256
@@:
stosd
+10 -25
View File
@@ -104,26 +104,10 @@ applyKeymap:
cmp al, 9
jnc @f
push eax
push esi edi
shl eax,7
lea edi,[eax*2+eax] ; offset of the layout = index*384
cmp [keymap_file],0
jnz .loaded
mcall 68,27,keymap_path
test eax,eax
jz .fail
mov [keymap_file],eax
mov [keymap_size],edx
.loaded:
lea eax,[edi+384]
cmp eax,[keymap_size]
ja .fail
mov esi,[keymap_file]
add esi,edi
mov edi,current_keymap
mov ecx,384/4
rep movsd
pop edi esi
lea eax,[eax*2+eax]
mov [point],eax
mcall 70,get_key
mcall 21,2,1,current_keymap
inc ecx
mcall 21,,,current_keymap_shift
@@ -134,9 +118,6 @@ applyKeymap:
mcall 21,,9
@@:
ret
.fail:
pop edi esi eax
ret
;---------------------------------------------------------------
align 4
current_keymap rb 128
@@ -151,9 +132,13 @@ point2 dd 0
dd inicont
db '/sys/settings/lang.ini',0
keymap_path db '/sys/settings/keymap.key',0
keymap_file dd 0
keymap_size dd 0
get_key:
dd 0
point dd 0
dd 0
dd 384
dd current_keymap
db '/sys/settings/keymap.key',0
key_r db 0
key_r2 db 0
-3
View File
@@ -1,6 +1,3 @@
-- @taskbar loads keymap.key with f68.27, which unpacks kpack'ed files.
tup.rule("KEYMAP.KEY", "cp %f %o" .. tup.getconfig("KPACK_CMD"), "keymap.key.kpack")
if tup.getconfig("NO_FASM") ~= "" then return end
HELPERDIR = (tup.getconfig("HELPERDIR") == "") and "../.." or tup.getconfig("HELPERDIR")
tup.include(HELPERDIR .. "/use_fasm.lua")