Compare commits
97
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36854f1382 | ||
|
|
f990a48b98 | ||
|
|
fb2906bc1d | ||
|
|
9c58dc1f04 | ||
|
|
bd071d588b | ||
|
|
9ec66b0eba | ||
|
|
95bcf78537 | ||
|
|
6f3cae4e0c | ||
|
|
b59e371c0e | ||
|
|
939505198f | ||
|
|
75cb80fd33 | ||
|
|
6ba901606d | ||
|
|
b1d329da2a | ||
|
|
df9946fe80 | ||
|
|
e3d744f1b5 | ||
|
|
8ca3758efb | ||
|
|
02916ed0ee | ||
|
|
873d4de379 | ||
|
|
b2f9cc9809 | ||
|
|
298155191d | ||
|
|
49b8cdcd54 | ||
|
|
c121db7a88 | ||
|
|
9527a0f3d1 | ||
|
|
1e05d19c4c | ||
|
|
ecdebae231 | ||
|
|
0150178c90 | ||
|
|
3caf2a7a72 | ||
|
|
019f2629dc | ||
|
|
63ee53f4a3 | ||
|
|
7c8eba2ed4 | ||
|
|
15396a0304 | ||
|
|
0969869ba8 | ||
|
|
dd3af88a30 | ||
|
|
85ae0c8703 | ||
|
|
2ad11d3acc | ||
|
|
450054a86c | ||
|
|
b0055ba472 | ||
|
|
f711f9286b | ||
|
|
7802c7b18a | ||
|
|
8a94db94a5 | ||
|
|
513af11464 | ||
|
|
e0e8a35364 | ||
|
|
f2ea10c1cd | ||
|
|
302bf7e221 | ||
|
|
a3af661ed6 | ||
|
|
e74f989500 | ||
|
|
4fe3987e39 | ||
|
|
060ec1a5d0 | ||
|
|
882f1f0242 | ||
|
|
02070aa233 | ||
|
|
d0244f1513 | ||
|
|
44465b3cc2 | ||
|
|
1df9d8496d | ||
|
|
7917972a37 | ||
|
|
8334324d9c | ||
|
|
2757ea7d3e | ||
|
|
bf8ae67dbf | ||
|
|
69bd99e991 | ||
|
|
3bde56821f | ||
|
|
2c22604f39 | ||
|
|
de952921ee | ||
|
|
7f44db1b7f | ||
|
|
f143ca1928 | ||
|
|
931071a0e9 | ||
|
|
bed9528756 | ||
|
|
570a432a84 | ||
|
|
1215116155 | ||
|
|
e470ef5db5 | ||
|
|
24d1b5877a | ||
|
|
aa8913ea33 | ||
|
|
647f35ea10 | ||
|
|
f44ceb560c | ||
|
|
6defa11a9e | ||
|
|
944d74f013 | ||
|
|
2bebbcbdc3 | ||
|
|
201e8b2de3 | ||
|
|
0390ad41e4 | ||
|
|
2515d1fa37 | ||
|
|
da0e6f492b | ||
|
|
3c2bdfb418 | ||
|
|
67770ec3f4 | ||
|
|
76294451d2 | ||
|
|
031fe62338 | ||
|
|
8766bfc546 | ||
|
|
2db92868a9 | ||
|
|
4bdee82489 | ||
|
|
b9fe23b7b2 | ||
|
|
d33a03c2e4
|
||
|
|
35f35b39e7 | ||
|
|
a020a2c434 | ||
|
|
77d600c663 | ||
|
|
f7dd4033ba | ||
|
|
0ca124d6cb | ||
|
|
7365a98326 | ||
|
|
9941a5dfc9 | ||
|
|
041029b406 | ||
|
|
7c4d3f57e6 |
No files matched your search
@@ -0,0 +1,54 @@
|
||||
# =============================================================================
|
||||
# Apps
|
||||
# User-facing applications, games, multimedia, UI and desktop resources
|
||||
# =============================================================================
|
||||
|
||||
^programs/(cmm|demos|emulator|games|media|other)/.* @KolibriOS/apps
|
||||
^contrib/(games|media|other)/.* @KolibriOS/apps
|
||||
^skins/.* @KolibriOS/apps
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# System
|
||||
# Kernel, drivers, filesystems, SDK, libraries, toolchain and system utilities
|
||||
# =============================================================================
|
||||
|
||||
^kernel/.* @KolibriOS/system
|
||||
^drivers/.* @KolibriOS/system
|
||||
|
||||
^programs/(bcc32|develop|fs|hd_load|system|testing)/.* @KolibriOS/system
|
||||
^contrib/(C_Layer|sdk|toolchain)/.* @KolibriOS/system
|
||||
|
||||
# Shared system/API includes in programs/
|
||||
^programs/[^/]+\\.inc$ @KolibriOS/system
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Network
|
||||
# Network stack, network drivers, protocols, libraries and network applications
|
||||
# =============================================================================
|
||||
|
||||
^kernel/trunk/network/.* @KolibriOS/network
|
||||
|
||||
^drivers/ethernet/.* @KolibriOS/network
|
||||
^drivers/(mii|netdrv)\\.inc$ @KolibriOS/network
|
||||
|
||||
^programs/network/.* @KolibriOS/network
|
||||
^programs/network\\.inc$ @KolibriOS/network
|
||||
|
||||
^programs/develop/libraries/(http|network|kos_mbedtls)/.* @KolibriOS/network
|
||||
|
||||
^contrib/network/.* @KolibriOS/network
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# DevOps
|
||||
# CI/CD, repository infrastructure, build system and autobuild configuration
|
||||
# =============================================================================
|
||||
|
||||
^\\.gitea/.* @KolibriOS/devops
|
||||
^_tools/.* @KolibriOS/devops
|
||||
|
||||
^\\.gitmodules$ @KolibriOS/devops
|
||||
^build\\.txt$ @KolibriOS/devops
|
||||
^tup\\.config\\.template$ @KolibriOS/devops
|
||||
@@ -19,3 +19,62 @@
|
||||
owner: "{{ storage_user }}"
|
||||
group: "{{ storage_user }}"
|
||||
mode: preserve
|
||||
|
||||
# per-program binaries browsable at <version>/<lang>/data/, like on the old builds server
|
||||
- name: Creating build tree folders
|
||||
ansible.builtin.file:
|
||||
path: "{{ storage_path }}/{{ version }}/{{ item | basename | regex_replace('\\.tar\\.gz$', '') }}/data"
|
||||
state: directory
|
||||
owner: "{{ storage_user }}"
|
||||
group: "{{ storage_user }}"
|
||||
mode: '0755'
|
||||
with_fileglob: "{{ tree_artifact_path }}/*.tar.gz"
|
||||
|
||||
- name: Unpacking build trees
|
||||
ansible.builtin.unarchive:
|
||||
src: "{{ item }}"
|
||||
dest: "{{ storage_path }}/{{ version }}/{{ item | basename | regex_replace('\\.tar\\.gz$', '') }}/data"
|
||||
owner: "{{ storage_user }}"
|
||||
group: "{{ storage_user }}"
|
||||
with_fileglob: "{{ tree_artifact_path }}/*.tar.gz"
|
||||
|
||||
# stable URL for the newest build: <storage_path>/latest/<lang>/...
|
||||
- name: Updating latest symlink
|
||||
ansible.builtin.file:
|
||||
src: "{{ version }}"
|
||||
dest: "{{ storage_path }}/latest"
|
||||
state: link
|
||||
force: true
|
||||
owner: "{{ storage_user }}"
|
||||
group: "{{ storage_user }}"
|
||||
|
||||
# emulators hardcode <site root>/<lang>/data/data/kolibri.img; storage_path is the ci folder, one level under the site root
|
||||
- name: Sending bare images to stable emulator paths
|
||||
ansible.builtin.copy:
|
||||
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"
|
||||
+90
-24
@@ -62,7 +62,7 @@ jobs:
|
||||
make -f Makefile.lin32
|
||||
chmod +x c--
|
||||
mv c-- /home/autobuild/tools/win32/bin/c--
|
||||
cp ${{ gitea.workspace }}/programs/cmm/c--/c--.ini /home/autobuild/tools/win32/bin/c--.ini
|
||||
cp ${{ gitea.workspace }}/programs/develop/cmm/c--.ini /home/autobuild/tools/win32/bin/c--.ini
|
||||
make -f Makefile.lin32 clean
|
||||
|
||||
- name: Install TCC
|
||||
@@ -128,7 +128,8 @@ jobs:
|
||||
fi
|
||||
|
||||
# cache restore resets ctimes; realign tup DB to skip a full rebuild,
|
||||
# but keep files changed since the cache's commit dirty so tup rebuilds them
|
||||
# but keep files changed since the cache's commit dirty so tup rebuilds them.
|
||||
# A submodule bump diffs as a bare gitlink, so expand it to its whole subtree
|
||||
- name: Sync tup DB with filesystem ctime
|
||||
if: steps.check-tup-cache.outputs.cache_restored == 'true'
|
||||
run: |
|
||||
@@ -136,6 +137,10 @@ jobs:
|
||||
BASE=$(cat .tup/build-commit 2>/dev/null || true)
|
||||
if [ -n "$BASE" ] && git cat-file -e "${BASE}^{commit}" 2>/dev/null; then
|
||||
git -c core.quotePath=false diff --name-only "$BASE" HEAD > "$DIRTY"
|
||||
git diff --raw "$BASE" HEAD | awk '$2 == "160000" { print $NF }' |
|
||||
while read -r sub; do
|
||||
git -C "$sub" -c core.quotePath=false ls-files | sed "s|^|$sub/|"
|
||||
done >> "$DIRTY"
|
||||
echo "Cache built at $BASE; $(wc -l < "$DIRTY") changed files kept dirty"
|
||||
python3 .gitea/utils/sync-tup-ctime.py .tup/db "$DIRTY"
|
||||
else
|
||||
@@ -162,12 +167,13 @@ jobs:
|
||||
tup init
|
||||
tup variant ${{ matrix.lang }}.config
|
||||
|
||||
# build the image for language variant
|
||||
# build the image for language variant; keep the tup log for publishing
|
||||
- name: Build KolibriOS
|
||||
run: |
|
||||
set -o pipefail
|
||||
export PATH=/home/autobuild/tools/win32/bin:$PATH
|
||||
source kos32-export-env-vars ${{ gitea.workspace }}
|
||||
tup build-${{ matrix.lang }}
|
||||
tup build-${{ matrix.lang }} 2>&1 | tee build.log
|
||||
|
||||
# stamp the cache with its commit so later builds diff against it
|
||||
- name: Record cache base commit
|
||||
@@ -181,15 +187,26 @@ jobs:
|
||||
id: vars
|
||||
run: echo "descr=$(git describe --tags)" >> $GITEA_OUTPUT
|
||||
|
||||
# rename build outputs to their final names so artifacts are bare files
|
||||
- name: Rename images
|
||||
# stage build outputs under their final names, plus distribution kit and checksums
|
||||
- name: Prepare artifacts
|
||||
run: |
|
||||
set -e
|
||||
BASE="kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}"
|
||||
for ext in img iso raw; do
|
||||
cp "build-${{ matrix.lang }}/data/kolibri.$ext" \
|
||||
"kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.$ext"
|
||||
cp "build-${{ matrix.lang }}/data/kolibri.$ext" "$BASE.$ext"
|
||||
done
|
||||
# zip: distr targets Windows/DOS users, Explorer opens it natively
|
||||
(cd "build-${{ matrix.lang }}/data" && zip -r -9 -q "${{ gitea.workspace }}/$BASE.distr.zip" distribution_kit)
|
||||
# whole build tree for per-program downloads; the big images ship separately
|
||||
tar -C "build-${{ matrix.lang }}" \
|
||||
--exclude './data/kolibri.iso' \
|
||||
--exclude './data/kolibri.raw' \
|
||||
--exclude './data/distribution_kit' \
|
||||
-czf "$BASE.tree.tar.gz" .
|
||||
sha256sum "$BASE".img "$BASE".iso "$BASE".raw "$BASE".distr.zip > "$BASE.sha256sums.txt"
|
||||
mv build.log "$BASE.build.log"
|
||||
|
||||
#publish the three images; longer retention for the floppy image.
|
||||
# publish the images; longer retention for the floppy image
|
||||
- name: Upload floppy image
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -211,6 +228,34 @@ jobs:
|
||||
path: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.raw
|
||||
retention-days: 15
|
||||
|
||||
- name: Upload distribution kit
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.distr.zip
|
||||
path: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.distr.zip
|
||||
retention-days: 30
|
||||
|
||||
- name: Upload checksums
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.sha256sums.txt
|
||||
path: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.sha256sums.txt
|
||||
retention-days: 90
|
||||
|
||||
- name: Upload build log
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.build.log
|
||||
path: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.build.log
|
||||
retention-days: 90
|
||||
|
||||
- name: Upload build tree
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.tree.tar.gz
|
||||
path: kolibrios-${{ steps.vars.outputs.descr }}-${{ matrix.lang }}.tree.tar.gz
|
||||
retention-days: 15
|
||||
|
||||
deploy:
|
||||
name: "Publish Images"
|
||||
runs-on: ubuntu-latest
|
||||
@@ -235,31 +280,50 @@ jobs:
|
||||
run: |
|
||||
set -eu
|
||||
|
||||
rm -rf ./norm-artifacts
|
||||
mkdir -p ./norm-artifacts
|
||||
rm -rf ./norm-artifacts ./stable-artifacts ./tree-artifacts
|
||||
mkdir -p ./norm-artifacts ./stable-artifacts ./tree-artifacts
|
||||
|
||||
find ./artifacts -type f \( \
|
||||
-name 'kolibrios-*.img' -o \
|
||||
-name 'kolibrios-*.iso' -o \
|
||||
-name 'kolibrios-*.raw' \
|
||||
\) | while read -r file; do
|
||||
fname="$(basename "$file")" # kolibrios-<descr>-<lang>.<ext>
|
||||
name_without_ext="${fname%.*}"
|
||||
lang="${name_without_ext##*-}"
|
||||
find ./artifacts -type f -name 'kolibrios-*' | while read -r file; do
|
||||
fname="$(basename "$file")" # kolibrios-<descr>-<lang>.<suffix>
|
||||
case "$fname" in
|
||||
*.tree.tar.gz) stem="${fname%.tree.tar.gz}";;
|
||||
*.distr.zip) stem="${fname%.distr.zip}";;
|
||||
*.sha256sums.txt) stem="${fname%.sha256sums.txt}";;
|
||||
*.build.log) stem="${fname%.build.log}";;
|
||||
*.img) stem="${fname%.img}";;
|
||||
*.iso) stem="${fname%.iso}";;
|
||||
*.raw) stem="${fname%.raw}";;
|
||||
*) continue;;
|
||||
esac
|
||||
lang="${stem##*-}" # <lang> has no dashes, <descr> may
|
||||
|
||||
mkdir -p "./norm-artifacts/$lang"
|
||||
cp "$file" "./norm-artifacts/$lang/$fname"
|
||||
case "$fname" in
|
||||
*.tree.tar.gz)
|
||||
# unpacked on the server into <version>/<lang>/data/ for per-program downloads
|
||||
cp "$file" "./tree-artifacts/$lang.tar.gz";;
|
||||
*.sha256sums.txt)
|
||||
cp "$file" "./norm-artifacts/$lang/sha256sums.txt";;
|
||||
*.build.log)
|
||||
cp "$file" "./norm-artifacts/$lang/build.log";;
|
||||
*.img)
|
||||
cp "$file" "./norm-artifacts/$lang/$fname"
|
||||
# emulators (e.g. v86) hardcode <lang>/data/data/kolibri.img at the site root
|
||||
mkdir -p "./stable-artifacts/$lang/data/data"
|
||||
cp "$file" "./stable-artifacts/$lang/data/data/kolibri.img";;
|
||||
*)
|
||||
cp "$file" "./norm-artifacts/$lang/$fname";;
|
||||
esac
|
||||
done
|
||||
|
||||
# derive the version (git describe) from an artifact name:
|
||||
# kolibrios-<descr>-<lang>.<ext> -> <descr>
|
||||
sample="$(find ./norm-artifacts -type f -name 'kolibrios-*' | head -n1)"
|
||||
# derive the version (git describe) from an artifact name: kolibrios-<descr>-<lang>.iso -> <descr>
|
||||
sample="$(find ./norm-artifacts -type f -name 'kolibrios-*.iso' | head -n1)"
|
||||
base="$(basename "${sample%.*}")" # kolibrios-<descr>-<lang>
|
||||
version="${base%-*}" # kolibrios-<descr>
|
||||
version="${version#kolibrios-}" # <descr>
|
||||
echo "version=$version" >> $GITEA_OUTPUT
|
||||
|
||||
find ./norm-artifacts -type f -print
|
||||
find ./norm-artifacts ./stable-artifacts ./tree-artifacts -type f -print
|
||||
|
||||
- name: Setup SSH
|
||||
run: |
|
||||
@@ -285,4 +349,6 @@ jobs:
|
||||
-e "storage_path=${{ secrets.STORAGE_PATH }}" \
|
||||
-e "version=${{ steps.normalize.outputs.version }}" \
|
||||
-e "artifact_path=${{ gitea.workspace }}/norm-artifacts" \
|
||||
-e "stable_artifact_path=${{ gitea.workspace }}/stable-artifacts" \
|
||||
-e "tree_artifact_path=${{ gitea.workspace }}/tree-artifacts" \
|
||||
-v
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
make -f Makefile.lin32
|
||||
chmod +x c--
|
||||
mv c-- /home/autobuild/tools/win32/bin/c--
|
||||
cp ${{ gitea.workspace }}/programs/cmm/c--/c--.ini /home/autobuild/tools/win32/bin/c--.ini
|
||||
cp ${{ gitea.workspace }}/programs/develop/cmm/c--.ini /home/autobuild/tools/win32/bin/c--.ini
|
||||
make -f Makefile.lin32 clean
|
||||
|
||||
- name: Install TCC
|
||||
|
||||
@@ -24,6 +24,8 @@ jobs:
|
||||
path: programs/develop/cmm
|
||||
- name: oberon07
|
||||
path: programs/develop/oberon07
|
||||
- name: cmm_apps
|
||||
path: programs/cmm
|
||||
- name: kterm
|
||||
path: programs/other/kterm
|
||||
|
||||
@@ -68,7 +70,7 @@ jobs:
|
||||
git config user.name "kolibri-bot"
|
||||
git config user.email "bot@kolibrios.org"
|
||||
git checkout -B "$BRANCH"
|
||||
git commit -m "$NAME: bump submodule to $WANT" -- "$PATH_"
|
||||
git commit -m "chore/submodules: bump $NAME to $WANT" -- "$PATH_"
|
||||
git push -f origin "$BRANCH"
|
||||
|
||||
# Open a PR via the Gitea API.
|
||||
@@ -77,7 +79,7 @@ jobs:
|
||||
http=$(curl -sS -o /tmp/pr.json -w '%{http_code}' -X POST \
|
||||
-H "Authorization: token ${TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"head\":\"${BRANCH}\",\"base\":\"main\",\"title\":\"${NAME}: bump submodule to upstream\"}" \
|
||||
-d "{\"head\":\"${BRANCH}\",\"base\":\"main\",\"title\":\"chore/submodules: bump ${NAME} to upstream\"}" \
|
||||
"${API}/repos/${REPO}/pulls")
|
||||
echo "PR API HTTP status: $http"
|
||||
cat /tmp/pr.json; echo
|
||||
|
||||
+5
-1
@@ -4,8 +4,12 @@
|
||||
branch = main
|
||||
[submodule "programs/develop/oberon07"]
|
||||
path = programs/develop/oberon07
|
||||
url = https://github.com/AntKrotov/oberon-07-compiler.git
|
||||
url = https://git.kolibrios.org/KolibriOS/oberon-07-compiler.git
|
||||
branch = master
|
||||
[submodule "programs/cmm"]
|
||||
path = programs/cmm
|
||||
url = https://git.kolibrios.org/KolibriOS/cmm_apps.git
|
||||
branch = main
|
||||
[submodule "programs/other/kterm"]
|
||||
path = programs/other/kterm
|
||||
url = https://git.kolibrios.org/b00bl1k/kterm.git
|
||||
|
||||
@@ -59,6 +59,12 @@ Co-authored-by: ANOTHER-NAME <ANOTHER-NAME@EXAMPLE.COM>
|
||||
|
||||
to the end commit message body on a new line.
|
||||
|
||||
If you used AI tools while preparing the commit, you are encouraged to include an Assisted-by tag:
|
||||
|
||||
```
|
||||
Assisted-by: AGENT_NAME:MODEL_VERSION
|
||||
```
|
||||
|
||||
### Merge commits
|
||||
|
||||
> [!WARNING]
|
||||
|
||||
+38
-27
@@ -41,10 +41,6 @@ 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"},
|
||||
@@ -58,8 +54,7 @@ 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", SRC_PROGS .. "/system/taskbar/KEYMAP.KEY"},
|
||||
{"SETTINGS/KOLIBRI.LBL", build_type .. "/settings/kolibri.lbl"},
|
||||
{"SETTINGS/KEYMAP.KEY", VAR_PROGS .. "/system/taskbar/keymap.key.kpack"},
|
||||
{"SETTINGS/LANG.INI", build_type .. "/settings/lang.ini"},
|
||||
{"SETTINGS/MENU.DAT", build_type .. "/settings/menu.dat"},
|
||||
{"SETTINGS/NETWORK.INI", "common/settings/network.ini"},
|
||||
@@ -74,7 +69,6 @@ if build_type == "ru_RU" then tup.append_table(img_files, {
|
||||
{"WELCOME.HTM", VAR_DATA .. "/" .. build_type .. "/welcome.htm.kpack"},
|
||||
{"EXAMPLE.ASM", SRC_PROGS .. "/develop/examples/example/rus/example.asm"},
|
||||
{"DEVELOP/BACKY", SRC_PROGS .. "/develop/backy/Backy_ru"},
|
||||
{"GAMES/BASEKURS.KLA", build_type .. "/games/basekurs.kla"},
|
||||
{"File Managers/KFAR.INI", build_type .. "/File Managers/kfar.ini"},
|
||||
{"GAMES/DESCENT", build_type .. "/games/descent"},
|
||||
{"SETTINGS/.shell", SRC_PROGS .. "/system/shell/bin/rus/.shell"},
|
||||
@@ -170,8 +164,6 @@ extra_files = {
|
||||
{"kolibrios/demos/life2", "common/demos/life2"},
|
||||
{"kolibrios/demos/relay.lif", "common/demos/relay.lif"},
|
||||
{"kolibrios/demos/rpento.lif", "common/demos/rpento.lif"},
|
||||
{"kolibrios/develop/c--/c--.ini", SRC_PROGS .. "/cmm/c--/c--.ini"},
|
||||
{"kolibrios/develop/c--/manual_c--.htm", SRC_PROGS .. "/cmm/c--/manual_c--.htm"},
|
||||
{"kolibrios/develop/fpc/", "common/develop/fpc/*"},
|
||||
{"kolibrios/develop/fpc/examples/", "../programs/develop/fp/examples/src/*"},
|
||||
{"kolibrios/develop/oberon07/compiler.kex", SRC_PROGS .. "/develop/oberon07/Compiler.kex"},
|
||||
@@ -194,6 +186,12 @@ extra_files = {
|
||||
{"kolibrios/develop/tcc/samples/", SRC_PROGS .. "/develop/ktcc/libc.obj/samples/*.sh"},
|
||||
{"kolibrios/develop/tcc/samples/clayer/", SRC_PROGS .. "/develop/ktcc/libc.obj/samples/clayer/*"},
|
||||
{"kolibrios/develop/utils/SPEDump", SRC_PROGS .. "/develop/SPEDump/SPEDump.kex"},
|
||||
{"kolibrios/develop/XDPascal/", SRC_PROGS .. "/develop/XDPascal/xdpk/*"},
|
||||
{"kolibrios/develop/XDPascal/projects2025/", SRC_PROGS .. "/develop/XDPascal/xdpk/projects2025/*"},
|
||||
{"kolibrios/develop/XDPascal/projects2025/Compiler/", SRC_PROGS .. "/develop/XDPascal/xdpk/projects2025/Compiler/*"},
|
||||
{"kolibrios/develop/XDPascal/projects2026/", SRC_PROGS .. "/develop/XDPascal/xdpk/projects2026/*"},
|
||||
{"kolibrios/develop/XDPascal/source/", SRC_PROGS .. "/develop/XDPascal/xdpk/source/*"},
|
||||
{"kolibrios/develop/XDPascal/units/", SRC_PROGS .. "/develop/XDPascal/xdpk/units/*"},
|
||||
{"kolibrios/emul/", "common/emul/*"},
|
||||
{"kolibrios/emul/dosbox/", "common/emul/DosBox/*"},
|
||||
{"kolibrios/emul/e80/readme.txt", SRC_PROGS .. "/emulator/e80/readme.txt"},
|
||||
@@ -270,6 +268,10 @@ 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"},
|
||||
@@ -293,8 +295,6 @@ extra_files = {
|
||||
{"kolibrios/utils/vmode", "common/vmode"},
|
||||
{"kolibrios/utils/texture", "common/utils/texture"},
|
||||
{"kolibrios/utils/kterm/kterm", VAR_PROGS .. "/other/kterm/kterm"},
|
||||
{"kolibrios/utils/kterm/serial.sys", VAR_DRVS .. "/serial/serial.sys"},
|
||||
{"kolibrios/utils/kterm/install.sh", SRC .. "/drivers/serial/install.sh"},
|
||||
{"kolibrios/utils/cnc_editor/cnc_editor", VAR_PROGS .. "/other/cnc_editor/cnc_editor"},
|
||||
{"kolibrios/utils/cnc_editor/kolibri.NC", SRC_PROGS .. "/other/cnc_editor/kolibri.NC"},
|
||||
{"kolibrios/utils/kfm/kfm.ini", "common/File Managers/kfm.ini"},
|
||||
@@ -428,7 +428,6 @@ tup.append_table(img_files, {
|
||||
{"DISPTEST", VAR_PROGS .. "/testing/disptest/disptest"},
|
||||
{"END", VAR_PROGS .. "/system/end/light/end"},
|
||||
{"ESKIN", VAR_PROGS .. "/system/eskin/eskin"},
|
||||
{"FSPEED", VAR_PROGS .. "/testing/fspeed/fspeed"},
|
||||
{"GMON", VAR_PROGS .. "/system/gmon/gmon"},
|
||||
{"HDD_INFO", VAR_PROGS .. "/system/hdd_info/hdd_info"},
|
||||
{"KBD", VAR_PROGS .. "/testing/kbd/kbd"},
|
||||
@@ -437,7 +436,6 @@ tup.append_table(img_files, {
|
||||
{"LOADDRV", VAR_PROGS .. "/system/loaddrv/loaddrv"},
|
||||
{"MAGNIFY", VAR_PROGS .. "/system/magnify/magnify"},
|
||||
{"MADMOUSE", VAR_PROGS .. "/other/madmouse/madmouse"},
|
||||
{"MGB", VAR_PROGS .. "/testing/mgb/mgb"},
|
||||
{"MOUSEMUL", VAR_PROGS .. "/system/mousemul/mousemul"},
|
||||
{"MOUSEPOS", VAR_PROGS .. "/other/mousepos/mousepos"},
|
||||
{"MYKEY", VAR_PROGS .. "/system/MyKey/MyKey"},
|
||||
@@ -488,11 +486,6 @@ 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"},
|
||||
@@ -543,7 +536,7 @@ tup.append_table(img_files, {
|
||||
{"NETWORK/PING", VAR_PROGS .. "/network/ping/ping"},
|
||||
{"NETWORK/NETCFG", VAR_PROGS .. "/network/netcfg/netcfg"},
|
||||
{"NETWORK/NETSTAT", VAR_PROGS .. "/network/netstat/netstat"},
|
||||
{"NETWORK/NSINST", VAR_PROGS .. "/network/netsurf/nsinstall"},
|
||||
{"NETWORK/NETSURF", VAR_PROGS .. "/network/netsurf/netsurf"},
|
||||
{"NETWORK/NSLOOKUP", VAR_PROGS .. "/network/nslookup/nslookup"},
|
||||
{"NETWORK/PASTA", VAR_PROGS .. "/network/pasta/pasta"},
|
||||
{"NETWORK/SYNERGYC", VAR_PROGS .. "/network/synergyc/synergyc"},
|
||||
@@ -574,12 +567,15 @@ tup.append_table(img_files, {
|
||||
{"DRIVERS/UHCI.SYS", VAR_DRVS .. "/usb/uhci.sys"},
|
||||
{"DRIVERS/OHCI.SYS", VAR_DRVS .. "/usb/ohci.sys"},
|
||||
{"DRIVERS/EHCI.SYS", VAR_DRVS .. "/usb/ehci.sys"},
|
||||
{"DRIVERS/XHCI.SYS", VAR_DRVS .. "/usb/xhci/xhci.sys"},
|
||||
{"DRIVERS/USBHID.SYS", VAR_DRVS .. "/usb/usbhid/usbhid.sys"},
|
||||
{"DRIVERS/USBFTDI.SYS", VAR_DRVS .. "/usb/usbftdi/usbftdi.sys"},
|
||||
{"DRIVERS/USBOTHER.SYS",VAR_DRVS .. "/usb/usbother/usbother.sys"},
|
||||
{"DRIVERS/USBCDC.SYS", VAR_DRVS .. "/usb/usbnet/usbcdc.sys"},
|
||||
{"DRIVERS/USBRNDIS.SYS", VAR_DRVS .. "/usb/usbnet/usbrndis.sys"},
|
||||
{"DRIVERS/USBSTOR.SYS", VAR_DRVS .. "/usb/usbstor.sys"},
|
||||
{"DRIVERS/RDC.SYS", VAR_DRVS .. "/video/rdc.sys"},
|
||||
{"DRIVERS/SERIAL.SYS", VAR_DRVS .. "/serial/serial.sys"},
|
||||
{"DRIVERS/COMMOUSE.SYS", VAR_DRVS .. "/mouse/commouse.sys"},
|
||||
{"DRIVERS/PS2MOUSE.SYS", VAR_DRVS .. "/mouse/ps2mouse4d/ps2mouse.sys"},
|
||||
{"DRIVERS/TMPDISK.SYS", VAR_DRVS .. "/disk/tmpdisk.sys"},
|
||||
@@ -596,6 +592,7 @@ tup.append_table(img_files, {
|
||||
{"DRIVERS/VT823X.SYS", VAR_DRVS .. "/audio/vt823x.sys"},
|
||||
{"DRIVERS/SIS.SYS", VAR_DRVS .. "/audio/sis.sys"},
|
||||
{"DRIVERS/SDHCI.SYS", "../drivers/sdhci/sdhci.sys"},
|
||||
{"DRIVERS/I2CHID.SYS", VAR_DRVS .. "/i2chid/i2chid.sys"},
|
||||
})
|
||||
tup.append_table(extra_files, {
|
||||
{"HD_Load/9x2klbr/", VAR_PROGS .. "/hd_load/9x2klbr/9x2klbr.exe"},
|
||||
@@ -642,24 +639,35 @@ tup.append_table(extra_files, {
|
||||
{"kolibrios/media/zsea/plugins/rotate.obj", VAR_PROGS .. "/media/zsea/plugins/rotate/rotate.obj"},
|
||||
{"kolibrios/media/zsea/plugins/scaling.obj", VAR_PROGS .. "/media/zsea/plugins/scaling/scaling.obj"},
|
||||
{"kolibrios/utils/AMDtemp", VAR_PROGS .. "/system/amd_temp_view/AMDtemp"},
|
||||
{"kolibrios/utils/fspeed", VAR_PROGS .. "/testing/fspeed/fspeed"},
|
||||
{"kolibrios/utils/mgb", VAR_PROGS .. "/testing/mgb/mgb"},
|
||||
{"kolibrios/utils/kfm/kfm", VAR_PROGS .. "/fs/kfm/kfm"},
|
||||
{"kolibrios/utils/tedit/t_edit", VAR_PROGS .. "/other/t_edit/t_edit"},
|
||||
{"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/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"}
|
||||
})
|
||||
-- For russian build, add russian-only programs.
|
||||
if build_type == "ru_RU" then tup.append_table(img_files, {
|
||||
{"GAMES/KLAVISHA", VAR_PROGS .. "/games/klavisha/klavisha"},
|
||||
{"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'
|
||||
@@ -683,6 +691,7 @@ tup.append_table(img_files, {
|
||||
{"EASYSHOT", VAR_PROGS .. "/cmm/misc/easyshot.com"},
|
||||
{"MOUSECFG", VAR_PROGS .. "/cmm/mousecfg/mousecfg.com"},
|
||||
{"BARSCFG", VAR_PROGS .. "/cmm/barscfg/barscfg.com"},
|
||||
{"BBENCH", VAR_PROGS .. "/cmm/bbench/bbench.com"},
|
||||
{"SEARCH", VAR_PROGS .. "/cmm/misc/search.com"},
|
||||
{"SYSPANEL", VAR_PROGS .. "/cmm/misc/software_widget.com"},
|
||||
{"SYSMON", VAR_PROGS .. "/cmm/sysmon/sysmon.com"},
|
||||
@@ -811,6 +820,8 @@ tup.append_table(extra_files, {
|
||||
{"kolibrios/utils/minizip/minizip", VAR_PROGS .. "/fs/minizip/minizip"},
|
||||
{"kolibrios/utils/minizip/miniunz", VAR_PROGS .. "/fs/minizip/miniunz"},
|
||||
{"kolibrios/develop/c--/c--", VAR_PROGS .. "/develop/cmm/cmm"},
|
||||
{"kolibrios/develop/c--/c--.ini", SRC_PROGS .. "/develop/cmm/c--.ini"},
|
||||
{"kolibrios/develop/c--/manual_c--.htm", SRC_PROGS .. "/develop/cmm/manual_c--.htm"},
|
||||
{"kolibrios/develop/tcc/tcc", VAR_PROGS .. "/develop/ktcc/source/tcc"},
|
||||
{"kolibrios/develop/sqlite3/sqlite3", VAR_CONTRIB .. "/sdk/sources/sqlite3/shell/sqlite3"},
|
||||
{"kolibrios/develop/utils/objconv", VAR_PROGS .. "/develop/objconv/objconv"},
|
||||
|
||||
@@ -48,7 +48,7 @@ mht=/sys/network/WebView
|
||||
docx=/sys/network/WebView
|
||||
url=/sys/network/WebView
|
||||
fb2=/sys/fb2read
|
||||
kla=/sys/games/klavisha
|
||||
kla=/kolibrios/games/klavisha/klavisha
|
||||
pdf=/kolibrios/media/updf
|
||||
avi=/kolibrios/media/fplay_run
|
||||
mpg=/kolibrios/media/fplay_run
|
||||
|
||||
Binary file not shown.
@@ -6,8 +6,9 @@
|
||||
#/SYS/CROPFLAT "XS800 YS480" 1 # set limits of screen
|
||||
#/SYS/LOADDRV COMMOUSE 1 # serial mouse driver
|
||||
#/SYS/DEVELOP/BOARD "" 0 # Load DEBUG board
|
||||
#/SYS/LOADDRV RDC 0 # videodriver for RDC M2010/M2012
|
||||
/SYS/SETUP BOOT 0 # Load device settings
|
||||
/SYS/LOADDRV RDC 0 # videodriver for RDC M2010/M2012
|
||||
/SYS/LOADDRV I2CHID 0 # Start I2C touchpad driver
|
||||
/SYS/@TASKBAR "" 0 # Start taskbar
|
||||
/SYS/ESKIN "" 0 # Set style
|
||||
/SYS/@ICON "" 0 # Multithread desktop icons
|
||||
|
||||
@@ -179,7 +179,7 @@ stl=/sys/3d/view3ds
|
||||
skn=/sys/skincfg
|
||||
dtp=/sys/skincfg
|
||||
lif=/kolibrios/demos/life2
|
||||
kla=/sys/games/klavisha
|
||||
kla=/kolibrios/games/klavisha/klavisha
|
||||
pdf=/kolibrios/media/updf
|
||||
|
||||
smc=/kolibrios/emul/zsnes/zsnes
|
||||
|
||||
@@ -39,7 +39,7 @@ Donkey=/kg/donkey
|
||||
Loderunner=/kg/LRL/LRL,41
|
||||
; 21days=/kg/21days,104 ;rus only
|
||||
BabyPainter=/kg/BabyPainter,87
|
||||
Klavisha=games/klavisha,69
|
||||
Klavisha=/kg/klavisha/klavisha,69
|
||||
Millioneer=/kg/WHOWTBAM/whowtbam,114
|
||||
StarTrek71=/kg/sstartrek/SStarTrek
|
||||
Descent=games/descent
|
||||
|
||||
@@ -35,7 +35,6 @@ Console Board=develop/dbgboard,19
|
||||
PCI Devices=pcidev,38
|
||||
CPU Info=cpuid,37
|
||||
Display Test=disptest,113
|
||||
Graphic Bench=mgb,121
|
||||
Benchmark=bbench,121
|
||||
HDD Info=hdd_info,50
|
||||
File Speed=fspeed,45
|
||||
Network Speed=network/dl|-test,51
|
||||
@@ -5,6 +5,22 @@ font smoothing=sbp
|
||||
font height=9
|
||||
speaker mute=off
|
||||
|
||||
[touchpad]
|
||||
speed=100
|
||||
; how far a finger must move before the pointer follows, in pad units;
|
||||
; larger is steadier under a pressing finger, 0 turns the filter off
|
||||
jitter=1
|
||||
; the same, for a finger that landed on the button strip: it is pressing
|
||||
; rather than steering there, so it needs a stricter margin
|
||||
jitter_buttons=45
|
||||
scroll_step=64
|
||||
scroll_invert=0
|
||||
tap_enable=1
|
||||
tap_drag=1
|
||||
right_click=1
|
||||
button_zone=15
|
||||
right_split=50
|
||||
|
||||
[mouse]
|
||||
speed=4
|
||||
acceleration=3
|
||||
|
||||
@@ -243,7 +243,7 @@ x=204
|
||||
y=0
|
||||
[22]
|
||||
name=NETSURF
|
||||
path=/sys/NETWORK/NSINST
|
||||
path=/sys/NETWORK/NETSURF
|
||||
param=
|
||||
ico=125
|
||||
x=204
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
06 zSea Image Viewer * |/kolibrios/media/zsea/zsea
|
||||
38 Animage |media/animage
|
||||
38 IconEdit |media/iconedit
|
||||
40 Image Filtering |media/imgf/imgf
|
||||
40 Image Filtering * |/kolibrios/media/ImgF/ImgF
|
||||
52 Palitra |media/palitra
|
||||
39 Pipet |develop/pipet
|
||||
#4 **** MULTIMEDIA
|
||||
@@ -116,6 +116,7 @@
|
||||
33 HTTPGet |network/httpget
|
||||
33 Downloader |network/dl
|
||||
12 WebView Browser |network/webview
|
||||
12 NetSurf |network/netsurf
|
||||
#13 **** SERVERS
|
||||
24 FTP |network/ftpd
|
||||
#14 **** OTHER
|
||||
|
||||
@@ -243,7 +243,7 @@ x=204
|
||||
y=0
|
||||
[22]
|
||||
name=NETSURF
|
||||
path=/sys/NETWORK/NSINST
|
||||
path=/sys/NETWORK/NETSURF
|
||||
param=
|
||||
ico=125
|
||||
x=204
|
||||
|
||||
@@ -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 |media/imgf/imgf
|
||||
16 Efectos de imаgenes * |/kolibrios/media/ImgF/ImgF
|
||||
16 Palitra |media/palitra
|
||||
#4 **** MULTIMEDIA
|
||||
16 Pixie Audioplayer |media/pixie
|
||||
@@ -121,6 +121,7 @@
|
||||
16 HTTPGet |network/httpget
|
||||
16 Descargas |network/dl
|
||||
16 Navegador WebView |network/webview
|
||||
12 NetSurf |network/netsurf
|
||||
#15 **** OTROS
|
||||
16 Reloj analвgico |demos/aclock
|
||||
16 Reloj binario |demos/bcdclk
|
||||
|
||||
@@ -35,7 +35,6 @@ Consola de depuracion=develop/dbgboard,19
|
||||
Dispositivos PCI=pcidev,38
|
||||
CPU Info=cpuid,37
|
||||
Prueba de pantalla=disptest,113
|
||||
Rendimiento grafico=mgb,121
|
||||
Benchmark=bbench,121
|
||||
Info de disco=hdd_info,50
|
||||
Velocidad FS=fspeed,45
|
||||
Velocidad de red=network/dl|-test,51
|
||||
@@ -41,7 +41,7 @@
|
||||
06 Image viewer zSea * |/kolibrios/media/zsea/zsea
|
||||
38 Animage |media/animage
|
||||
38 IconEdit |media/iconedit
|
||||
16 Image Filtering |media/imgf/imgf
|
||||
16 Image Filtering * |/kolibrios/media/ImgF/ImgF
|
||||
52 Palitra |media/palitra
|
||||
39 Pipet |develop/pipet
|
||||
#4 **** MULTIMEDIA ****
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
06 Image viewer zSea * |/kolibrios/media/zsea/zsea
|
||||
38 Animage |media/animage
|
||||
38 IconEdit |media/iconedit
|
||||
40 Image Filtering |media/imgf/imgf
|
||||
40 Image Filtering * |/kolibrios/media/ImgF/ImgF
|
||||
52 Palitra |media/palitra
|
||||
39 Pipet |develop/pipet
|
||||
#4 **** MULTIMEDIA
|
||||
|
||||
@@ -39,7 +39,7 @@ docx=/sys/network/WebView
|
||||
url=/sys/network/WebView
|
||||
fb2=/sys/fb2read
|
||||
mht=/sys/network/WebView
|
||||
kla=/sys/games/klavisha
|
||||
kla=/kolibrios/games/klavisha/klavisha
|
||||
pdf=/kolibrios/media/updf
|
||||
avi=/kolibrios/media/fplay_run
|
||||
mpg=/kolibrios/media/fplay_run
|
||||
|
||||
@@ -39,7 +39,7 @@ Donkey=/kg/donkey
|
||||
Loderunner=/kg/LRL/LRL,41
|
||||
21days=/kg/21days,104 ;rus only
|
||||
BabyPainter=/kg/BabyPainter,87
|
||||
Klavisha=games/klavisha,69
|
||||
Klavisha=/kg/klavisha/klavisha,69
|
||||
Millioneer=/kg/WHOWTBAM/whowtbam,114
|
||||
StarTrek71=/kg/sstartrek/SStarTrek
|
||||
Descent=games/descent
|
||||
|
||||
@@ -243,7 +243,7 @@ x=204
|
||||
y=0
|
||||
[22]
|
||||
name=NETSURF
|
||||
path=/sys/NETWORK/NSINST
|
||||
path=/sys/NETWORK/NETSURF
|
||||
param=
|
||||
ico=125
|
||||
x=204
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
06 Просмотр фото zSea |/kolibrios/media/zsea/zsea
|
||||
38 Редактор Animage |media/animage
|
||||
38 Редактор иконок |media/iconedit
|
||||
40 Наложение фильтров |media/imgf/imgf
|
||||
40 Наложение фильтров * |/kolibrios/media/ImgF/ImgF
|
||||
52 Палитра |media/palitra
|
||||
39 Пипетка |develop/pipet
|
||||
#4 **** Звук и видео
|
||||
@@ -115,6 +115,7 @@
|
||||
33 HTTPGet |network/httpget
|
||||
33 Загрузчик |network/dl
|
||||
12 Браузер WebView |network/webview
|
||||
12 Браузер NetSurf |network/netsurf
|
||||
#14 **** Разное
|
||||
00 Эмуляторы* > |@6
|
||||
45 Создание скриншотов |scrshoot
|
||||
@@ -122,7 +123,7 @@
|
||||
18 FB2 Читалка |fb2read
|
||||
16 Аналоговые часы |aclock
|
||||
21 Таблица Менделеева |/kolibrios/utils/period
|
||||
59 Тренажёр KJ|ABuIIIA |games/klavisha
|
||||
59 Тренажёр KJIABuIIIA |/kolibrios/games/klavisha/klavisha
|
||||
16 Бинарные часы |demos/bcdclk
|
||||
53 Таймер |timer
|
||||
09 Разархиватор Unz |unz
|
||||
|
||||
@@ -35,7 +35,6 @@ AMDtemp=/k/utils/AMDtemp,128
|
||||
Устройства PCI=pcidev,38
|
||||
CPU Info=cpuid,37
|
||||
Тест экрана=disptest,113
|
||||
Скорость графики=mgb,121
|
||||
Benchmark=bbench,121
|
||||
Информация о дисках=hdd_info,50
|
||||
Скорость ФС=fspeed,45
|
||||
Скорость сети=network/dl|-test,51
|
||||
@@ -515,20 +515,18 @@ HDA_AMP_VOLMASK equ 0x7F
|
||||
|
||||
|
||||
; unsolicited event handler
|
||||
HDA_UNSOL_QUEUE_SIZE equ 64
|
||||
HDA_UNSOL_QUEUE_SIZE equ 64 ; must stay a power of 2 (used as a bitmask for wrap)
|
||||
|
||||
;struc HDA_BUS_UNSOLICITED
|
||||
;{
|
||||
; ; ring buffer
|
||||
; .queue:
|
||||
; times HDA_UNSOL_QUEUE_SIZE*2 dd ?
|
||||
; .rp dd ?
|
||||
; .wp dd ?
|
||||
;
|
||||
; ; workqueue
|
||||
; .work dd ?;struct work_struct work;
|
||||
; .bus dd ? ;struct hda_bus ;bus
|
||||
;};
|
||||
struc HDA_BUS_UNSOLICITED
|
||||
{
|
||||
; ring buffer
|
||||
.queue rd HDA_UNSOL_QUEUE_SIZE * 2 ; 2 dword for each event (res and res_ex)
|
||||
.rp dd ? ; Read pointer
|
||||
.wp dd ? ; Write pointer
|
||||
; ; workqueue
|
||||
; .work dd ? ;struct work_struct work;
|
||||
; .bus dd ? ;struct hda_bus ;bus
|
||||
}
|
||||
|
||||
; Helper for automatic ping configuration
|
||||
AUTO_PIN_MIC equ 0
|
||||
|
||||
@@ -273,8 +273,8 @@ RIRB_INT_RESPONSE equ 0x01
|
||||
RIRB_INT_OVERRUN equ 0x04
|
||||
RIRB_INT_MASK equ 0x05
|
||||
|
||||
; STATESTS int mask: SD2,SD1,SD0
|
||||
STATESTS_INT_MASK equ 0x07
|
||||
; STATESTS int mask: SDIWAKE[14:0], a 16-bit register
|
||||
STATESTS_INT_MASK equ 0x7FFF
|
||||
AZX_MAX_CODECS equ 4
|
||||
|
||||
; SD_CTL bits
|
||||
@@ -402,6 +402,7 @@ struc AC_CNTRL ;AC controller base class
|
||||
.response_reset dd 0
|
||||
.polling_mode db 0
|
||||
.poll_count db 0
|
||||
.no_irq db 0 ; no interrupt line: a thread runs hda_irq
|
||||
.posbuf dd ?
|
||||
.start_wallclk dd ? ; start + minimum wallclk
|
||||
.period_wallclk dd ? ; wallclk for period
|
||||
@@ -505,8 +506,6 @@ macro spin_unlock
|
||||
pop ebx eax
|
||||
}
|
||||
|
||||
data fixups
|
||||
end data
|
||||
|
||||
include '../../struct.inc'
|
||||
include '../../macros.inc'
|
||||
@@ -607,9 +606,6 @@ if IRQ_REMAP
|
||||
invoke SysMsgBoardStr
|
||||
end if
|
||||
|
||||
mov ebx, [ctrl.int_line]
|
||||
invoke AttachIntHandler, ebx, hda_irq, dword 0
|
||||
|
||||
;Asper This part is from "azx_probe" proc. [
|
||||
call azx_codec_create
|
||||
cmp eax, 0
|
||||
@@ -654,7 +650,15 @@ end if
|
||||
stdcall hda_codec_setup_stream, eax, SDO_TAG, 0, 0x11 ; Left & Right channels (Back panel)
|
||||
;Asper+ ]
|
||||
|
||||
invoke TimerHS, 1, 0, snd_hda_automute, 0
|
||||
if USE_UNSOL_EV = 0
|
||||
invoke TimerHS, 1, 0, snd_hda_automute, 1
|
||||
else
|
||||
; Keep the unsolicited-event mode on the event-driven path. Running
|
||||
; snd_hda_automute at startup can issue codec commands before the new
|
||||
; unsolicited-response flow is ready, which hangs some systems.
|
||||
invoke TimerHS, 1, 0, process_unsol_events, 0
|
||||
end if
|
||||
|
||||
if USE_SINGLE_MODE
|
||||
mov esi, msgSingleMode
|
||||
invoke SysMsgBoardStr
|
||||
@@ -850,13 +854,13 @@ end if
|
||||
|
||||
mov edx, ICH6_REG_SD_STS + SDO_OFS
|
||||
call azx_readb
|
||||
mov bl, al
|
||||
mov cl, al
|
||||
|
||||
mov al, SD_INT_MASK
|
||||
mov edx, ICH6_REG_SD_STS + SDO_OFS
|
||||
call azx_writeb
|
||||
|
||||
test bl, SD_INT_COMPLETE
|
||||
test cl, SD_INT_COMPLETE
|
||||
jz @f
|
||||
|
||||
mov eax, [ctrl.civ_val]
|
||||
@@ -893,13 +897,13 @@ end if
|
||||
;if 0
|
||||
; clear state status int
|
||||
mov edx, ICH6_REG_STATESTS
|
||||
call azx_readb
|
||||
test al, 0x04
|
||||
call azx_readw
|
||||
and eax, STATESTS_INT_MASK
|
||||
jz @f
|
||||
|
||||
mov al, 0x04
|
||||
; ack all state-change bits, else the level IRQ line stays asserted
|
||||
mov edx, ICH6_REG_STATESTS
|
||||
call azx_writeb
|
||||
call azx_writew
|
||||
@@:
|
||||
;end if
|
||||
or eax, 1
|
||||
@@ -907,6 +911,24 @@ end if
|
||||
ret
|
||||
endp
|
||||
|
||||
; Stand-in for the interrupt when no interrupt line is available. A thread,
|
||||
; not a TimerHS callback: the kernel calls timer callbacks with the global
|
||||
; timer list lock held, and hda_irq may stall and refill the audio buffer.
|
||||
; hda_irq runs with interrupts off, as it would in IRQ context: it holds
|
||||
; aspinlock, which azx_rirb_get_response waits for with interrupts off, so
|
||||
; a holder that could be preempted would hang the machine.
|
||||
proc hda_poll_thread
|
||||
.loop:
|
||||
pushfd
|
||||
cli
|
||||
call hda_irq
|
||||
popfd
|
||||
mov eax, 5 ; delay, sleeping instead of spinning
|
||||
mov ebx, 1 ; 10 ms; a 16 KB period is ~85 ms at 48 kHz
|
||||
int 0x40
|
||||
jmp .loop
|
||||
endp
|
||||
|
||||
|
||||
align 4
|
||||
proc create_primary_buff
|
||||
@@ -1195,6 +1217,26 @@ end if
|
||||
; allocate CORB/RIRB
|
||||
call azx_alloc_cmd_io
|
||||
|
||||
; attach the IRQ handler BEFORE the controller may raise interrupts:
|
||||
; azx_init_chip enables GIE/CIE and a codec state-change can fire
|
||||
; right away; an unclaimed level IRQ makes the
|
||||
; kernel poll foreign handlers and relink their IRQH nodes onto our
|
||||
; line (see irq_serv .try_other_irqs), corrupting the dispatch list
|
||||
; a warm reboot can leave GIE and a stale completion bit behind, and
|
||||
; civ_val is never resynced, so silence the controller before attaching
|
||||
call azx_int_disable
|
||||
mov ebx, [ctrl.int_line]
|
||||
invoke AttachIntHandler, ebx, hda_irq, dword 0
|
||||
test eax, eax
|
||||
jnz @f
|
||||
; No usable interrupt line (INTLINE=0xFF on boards that route INTx only
|
||||
; through ACPI _PRT or MSI, which the kernel does not parse). The
|
||||
; controller still latches INTSTS/SD_STS, we only lose the wakeup - so
|
||||
; poll the RIRB for codec replies and run the interrupt handler from a
|
||||
; thread. A flag of its own: polling_mode is the timeout recovery state.
|
||||
mov [ctrl.no_irq], 1
|
||||
@@:
|
||||
|
||||
; initialize chip
|
||||
call azx_init_pci
|
||||
|
||||
@@ -1202,6 +1244,32 @@ end if
|
||||
call azx_init_chip
|
||||
;] Asper
|
||||
|
||||
; no IRQ line: let a polling thread stand in for the interrupt.
|
||||
; Started only now - earlier, hda_irq could ack STATESTS in the window
|
||||
; before reset_controller reads it into codec_mask
|
||||
cmp [ctrl.no_irq], 0
|
||||
je @f
|
||||
push esi edi ; CreateThread clobbers them, START needs esi
|
||||
mov ebx, 1
|
||||
mov ecx, hda_poll_thread
|
||||
xor edx, edx
|
||||
invoke CreateThread
|
||||
pop edi esi
|
||||
test eax, eax
|
||||
jns .thread_ok
|
||||
; nothing would ever complete a period and playback would stall,
|
||||
; so fail the init rather than register a service that hangs
|
||||
mov esi, msgNoIrqThread
|
||||
invoke SysMsgBoardStr
|
||||
xor eax, eax
|
||||
ret
|
||||
.thread_ok:
|
||||
if DEBUG
|
||||
mov esi, msgNoIrqPoll
|
||||
invoke SysMsgBoardStr
|
||||
end if
|
||||
@@:
|
||||
|
||||
xor eax, eax
|
||||
inc eax
|
||||
ret
|
||||
@@ -1235,7 +1303,7 @@ endl
|
||||
; clear STATESTS
|
||||
mov eax, STATESTS_INT_MASK
|
||||
mov edx, ICH6_REG_STATESTS
|
||||
call azx_writeb
|
||||
call azx_writew
|
||||
|
||||
; reset controller
|
||||
mov edx, ICH6_REG_GCTL
|
||||
@@ -1446,6 +1514,12 @@ endp
|
||||
|
||||
proc azx_alloc_cmd_io
|
||||
push eax ecx edx
|
||||
; the unsolicited-event ring lives in reserved storage, so its
|
||||
; pointers hold garbage until we clear them here - do it before
|
||||
; reset_controller enables unsolicited responses in GCTL
|
||||
mov [unsol_events.rp], 0
|
||||
mov [unsol_events.wp], 0
|
||||
|
||||
; single page (at least 4096 bytes) must suffice for both ringbuffers
|
||||
invoke KernelAlloc, 4096
|
||||
mov [ctrl.rb], eax
|
||||
@@ -1646,14 +1720,24 @@ endl
|
||||
mov ecx, 1000;+1000
|
||||
.next_try:
|
||||
mov al, [ctrl.polling_mode]
|
||||
test al, al
|
||||
or al, [ctrl.no_irq]
|
||||
jnz .poll
|
||||
mov ah, [do_poll]
|
||||
test ah, ah
|
||||
jz @f
|
||||
.poll:
|
||||
spin_lock_irq
|
||||
; take the lock hda_irq holds so two RIRB readers never overlap
|
||||
push eax ebx
|
||||
mov eax, aspinlock
|
||||
.poll_lock:
|
||||
mov ebx, SPINLOCK_BUSY
|
||||
lock xchg [eax], ebx
|
||||
cmp ebx, SPINLOCK_FREE
|
||||
jnz .poll_lock
|
||||
pop ebx eax
|
||||
call azx_update_rirb
|
||||
mov [aspinlock], SPINLOCK_FREE
|
||||
spin_unlock_irq
|
||||
@@:
|
||||
mov eax, [ctrl.rirb_cmd]
|
||||
@@ -1934,6 +2018,7 @@ proc azx_int_disable
|
||||
mov ebx, ICH6_INT_CTRL_EN or ICH6_INT_GLOBAL_EN
|
||||
xor ebx, -1
|
||||
and eax, ebx
|
||||
mov edx, ICH6_REG_INTCTL ; azx_readl turned edx into the absolute address
|
||||
call azx_writel
|
||||
pop edx ebx eax
|
||||
ret
|
||||
@@ -1949,9 +2034,9 @@ proc azx_int_clear
|
||||
call azx_writeb
|
||||
|
||||
; clear STATESTS
|
||||
mov al, STATESTS_INT_MASK
|
||||
mov ax, STATESTS_INT_MASK
|
||||
mov edx, ICH6_REG_STATESTS
|
||||
call azx_writeb
|
||||
call azx_writew
|
||||
|
||||
; clear rirb status
|
||||
mov al, RIRB_INT_MASK
|
||||
@@ -2635,7 +2720,7 @@ proc snd_hda_automute stdcall, data:dword
|
||||
test eax, eax
|
||||
jz .out
|
||||
|
||||
stdcall snd_hda_read_pin_sense, edx, 1
|
||||
stdcall snd_hda_read_pin_sense, edx, [data]
|
||||
test eax, AC_PINSENSE_PRESENCE
|
||||
jnz @f
|
||||
xchg ecx, esi
|
||||
@@ -2664,24 +2749,65 @@ proc snd_hda_automute stdcall, data:dword
|
||||
endp
|
||||
|
||||
|
||||
;Asper remember to add this functions:
|
||||
proc snd_hda_queue_unsol_event stdcall, par1:dword, par2:dword
|
||||
;if DEBUG
|
||||
; push esi
|
||||
; mov esi, msgUnsolEvent
|
||||
; invoke SysMsgBoardStr
|
||||
; pop esi
|
||||
;end if
|
||||
if USE_UNSOL_EV = 1
|
||||
;Test. Do not make queue, process immediately!
|
||||
;stdcall here snd_hda_read_pin_sense stdcall, nid:dword, trigger_sense:dword
|
||||
;and then mute/unmute pin based on the results
|
||||
invoke TimerHS, 1, 0, snd_hda_automute, 0
|
||||
end if
|
||||
ret
|
||||
endp
|
||||
;...
|
||||
; ;Asper remember to add this functions:
|
||||
; proc snd_hda_queue_unsol_event stdcall, par1:dword, par2:dword
|
||||
; ;if DEBUG
|
||||
; ; push esi
|
||||
; ; mov esi, msgUnsolEvent
|
||||
; ; invoke SysMsgBoardStr
|
||||
; ; pop esi
|
||||
; ;end if
|
||||
; if USE_UNSOL_EV = 1
|
||||
; ;Test. Do not make queue, process immediately!
|
||||
; ;stdcall here snd_hda_read_pin_sense stdcall, nid:dword, trigger_sense:dword
|
||||
; ;and then mute/unmute pin based on the results
|
||||
; invoke TimerHS, 1, 0, snd_hda_automute, 0
|
||||
; end if
|
||||
; ret
|
||||
; endp
|
||||
; ;...
|
||||
|
||||
align 4
|
||||
proc snd_hda_queue_unsol_event stdcall, res:dword, res_ex:dword
|
||||
; Single-producer (HDA IRQ) lock-free enqueue. The caller azx_update_rirb
|
||||
; only carries EBX across iterations and reloads the rest, and TimerHS
|
||||
; preserves EBX too - so by using scratch regs only we need no saves.
|
||||
mov eax, [unsol_events.wp]
|
||||
and eax, HDA_UNSOL_QUEUE_SIZE - 1 ; never index the ring wild
|
||||
lea edx, [eax+1]
|
||||
and edx, HDA_UNSOL_QUEUE_SIZE - 1 ; next write pos (size must be 2^n)
|
||||
cmp edx, [unsol_events.rp]
|
||||
je .full ; ring full -> drop, keep 1 slot free
|
||||
|
||||
mov ecx, [res]
|
||||
mov [unsol_events.queue + eax*8], ecx
|
||||
mov ecx, [res_ex]
|
||||
mov [unsol_events.queue + eax*8 + 4], ecx
|
||||
mov [unsol_events.wp], edx ; publish only after data is stored
|
||||
|
||||
invoke TimerHS, 1, 0, process_unsol_events, 0
|
||||
.full:
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
proc process_unsol_events stdcall, data:dword
|
||||
; Runs from TimerHS (single consumer). Uses only EAX (scratch) and calls
|
||||
; snd_hda_automute, which preserves every register, so nothing is saved.
|
||||
.loop:
|
||||
mov eax, [unsol_events.rp]
|
||||
cmp eax, [unsol_events.wp]
|
||||
je .done
|
||||
; The event payload is at [unsol_events.queue + eax*8] (res) and +4 (res_ex).
|
||||
; Per-pin tag parsing is not implemented yet, so just re-evaluate jack state.
|
||||
inc eax
|
||||
and eax, HDA_UNSOL_QUEUE_SIZE - 1
|
||||
mov [unsol_events.rp], eax
|
||||
stdcall snd_hda_automute, 0
|
||||
jmp .loop
|
||||
.done:
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
proc fdword2str stdcall, flags:dword ; bit 0 - skipLeadZeroes; bit 1 - newLine; other bits undefined
|
||||
@@ -2950,6 +3076,7 @@ sz_sound_srv db 'SOUND',0
|
||||
|
||||
msgInit db 'detect hardware...',13,10,0
|
||||
msgFail db 'device not found',13,10,0
|
||||
msgNoIrqThread db 'no IRQ line: cannot create polling thread',13,10,0
|
||||
msgAttchIRQ db 'IRQ line not supported', 13,10,0
|
||||
msgInvIRQ db 'IRQ line not assigned or invalid', 13,10,0
|
||||
msgPlay db 'start play', 13,10,0
|
||||
@@ -3019,6 +3146,7 @@ if DEBUG
|
||||
msgTCSEL db 'PCI TCSEL ',0
|
||||
msgTV db 'HDA test version ',TEST_VERSION_NUMBER,13,10,0
|
||||
msgGCap db 'GCAP = ',0
|
||||
msgNoIrqPoll db 'no IRQ line: polling thread',13,10,0
|
||||
end if
|
||||
|
||||
if USE_SINGLE_MODE
|
||||
@@ -3053,10 +3181,16 @@ end if
|
||||
|
||||
;] Asper
|
||||
|
||||
; relocation table lives after all code and initialized data: placed before the
|
||||
; code its size feeds back into every relocation site and fasm may never converge
|
||||
data fixups
|
||||
end data
|
||||
|
||||
aspinlock dd SPINLOCK_FREE
|
||||
|
||||
codec CODEC
|
||||
ctrl AC_CNTRL
|
||||
unsol_events HDA_BUS_UNSOLICITED
|
||||
|
||||
;Asper: BDL must be aligned to 128 according to HDA specification.
|
||||
pcmout_bdl rd 1
|
||||
|
||||
+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:
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
if tup.getconfig("NO_FASM") ~= "" then return end
|
||||
ROOT = "../.."
|
||||
tup.rule("i2chid.asm", "fasm %f %o " .. tup.getconfig("PESTRIP_CMD") .. tup.getconfig("KPACK_CMD"), "%B.sys")
|
||||
@@ -0,0 +1,438 @@
|
||||
; Synopsys DesignWare I2C master, polled (PIO) mode only.
|
||||
; This is the controller inside Intel LPSS blocks (Skylake and newer, plus
|
||||
; Atom-derived SoCs); the same IP is used by many other vendors.
|
||||
;
|
||||
; The register file is always accessed as dwords. The controller must be
|
||||
; disabled to change IC_TAR, so every transfer disables it, programs the
|
||||
; target address, enables it back and feeds the TX FIFO by hand.
|
||||
|
||||
; ------------------------------ Registers ------------------------------------
|
||||
DwIcCon = 0x00
|
||||
DwIcTar = 0x04
|
||||
DwIcDataCmd = 0x10
|
||||
DwIcSsSclHcnt = 0x14
|
||||
DwIcSsSclLcnt = 0x18
|
||||
DwIcFsSclHcnt = 0x1C
|
||||
DwIcFsSclLcnt = 0x20
|
||||
DwIcIntrStat = 0x2C
|
||||
DwIcIntrMask = 0x30
|
||||
DwIcRawIntrStat = 0x34
|
||||
DwIcRxTl = 0x38
|
||||
DwIcTxTl = 0x3C
|
||||
DwIcClrIntr = 0x40
|
||||
DwIcClrTxAbrt = 0x54
|
||||
DwIcEnable = 0x6C
|
||||
DwIcStatus = 0x70
|
||||
DwIcTxflr = 0x74
|
||||
DwIcRxflr = 0x78
|
||||
DwIcSdaHold = 0x7C
|
||||
DwIcTxAbrtSource = 0x80
|
||||
DwIcEnableStatus = 0x9C
|
||||
DwIcCompParam1 = 0xF4
|
||||
DwIcCompVersion = 0xF8
|
||||
DwIcCompType = 0xFC
|
||||
|
||||
; "DW_apb_i2c" component signature ('DW' + 0x0140).
|
||||
DW_COMP_TYPE_VALUE = 0x44570140
|
||||
|
||||
; IC_CON: master, standard speed (100 kHz), restarts allowed, slave disabled.
|
||||
DW_CON_MASTER = 1 shl 0
|
||||
DW_CON_SPEED_STD = 1 shl 1
|
||||
DW_CON_SPEED_FAST = 2 shl 1
|
||||
DW_CON_RESTART_EN = 1 shl 5
|
||||
DW_CON_SLAVE_DIS = 1 shl 6
|
||||
|
||||
; IC_DATA_CMD bits above the data byte.
|
||||
DW_CMD_READ = 1 shl 8
|
||||
DW_CMD_STOP = 1 shl 9
|
||||
DW_CMD_RESTART = 1 shl 10
|
||||
|
||||
; IC_STATUS bits
|
||||
DW_STAT_TFNF = 1 shl 1 ; TX FIFO not full
|
||||
DW_STAT_TFE = 1 shl 2 ; TX FIFO empty
|
||||
DW_STAT_RFNE = 1 shl 3 ; RX FIFO not empty
|
||||
DW_STAT_MST_ACT = 1 shl 5 ; master FSM busy
|
||||
|
||||
; IC_RAW_INTR_STAT bits
|
||||
DW_INT_TX_ABRT = 1 shl 6
|
||||
|
||||
; SCL timing for standard mode. The LPSS input clock is 100 MHz on the PCH
|
||||
; parts and 133 MHz on the Atom-derived SoCs (Apollo Lake, Gemini Lake), and
|
||||
; nothing in PCI config space says which one this is, so the counts are
|
||||
; picked to satisfy the fast-mode minimums at the fastest of them: at
|
||||
; 133 MHz that is tHIGH = 0.98 us and tLOW = 1.5 us, 400 kHz. On a 100 MHz
|
||||
; part the same counts run the bus at 300 kHz, which is just as legal.
|
||||
; Fast mode rather than standard: HID over I2C requires every device to
|
||||
; support it, that is what Windows drives them at, and a polled host pays
|
||||
; for every byte with busy-waiting - at 100 kHz a 64-byte input read costs
|
||||
; 6 ms, more than a fast pad takes to produce the next report, and the
|
||||
; backlog that builds up plays back as the cursor coasting after the finger
|
||||
; has stopped. SDA hold stays well below tLOW.
|
||||
DW_FS_HCNT = 130
|
||||
DW_FS_LCNT = 200
|
||||
DW_SDA_HOLD = 28
|
||||
; The AMD FCH feeds its DesignWare masters from a 150 MHz reference, so
|
||||
; the same minimums need more counts there: 145/225 give tHIGH = 0.97 us,
|
||||
; tLOW = 1.5 us, again 400 kHz; SDA hold 45 = 300 ns.
|
||||
DW_AMD_FS_HCNT = 145
|
||||
DW_AMD_FS_LCNT = 225
|
||||
DW_AMD_SDA_HOLD = 45
|
||||
|
||||
; A transfer gives up after [XferTimeout] hundredths of a second. The init
|
||||
; value must cover a full report descriptor read: descriptors run up to 2 KB
|
||||
; and the bus may be as slow as 77 kHz, so at 9 SCL cycles per byte a single
|
||||
; transfer takes ~240 ms of wall-clock time. Polling is generous too now that it runs in its own thread
|
||||
; rather than in a timer callback - a wedged bus costs this thread its slice
|
||||
; and nothing else.
|
||||
DW_TIMEOUT_INIT = 60
|
||||
DW_TIMEOUT_POLL = 20
|
||||
|
||||
; Disables the controller and waits until it reports itself disabled.
|
||||
; in: ebx = MMIO base. Clobbers eax, ecx.
|
||||
proc dw_ctrl_disable
|
||||
mov dword [ebx+DwIcEnable], 0
|
||||
mov ecx, 100000
|
||||
@@:
|
||||
test dword [ebx+DwIcEnableStatus], 1
|
||||
jz .done
|
||||
pause
|
||||
loop @b
|
||||
.done:
|
||||
ret
|
||||
endp
|
||||
|
||||
; Aborts a stuck transfer cleanly: the ABORT bit makes the master issue STOP,
|
||||
; flush the TX FIFO and raise TX_ABRT, which releases a slave that is holding
|
||||
; the bus (a clock-stretching touchpad, for instance). Simply disabling the
|
||||
; controller in the middle of a byte would leave SDA held low and every
|
||||
; following transfer would time out too. Older cores without the ABORT bit
|
||||
; just ignore the write and fall through after the wait.
|
||||
; in: ebx = MMIO base. Clobbers eax, ecx.
|
||||
proc dw_ctrl_abort
|
||||
mov dword [ebx+DwIcEnable], 3
|
||||
mov ecx, 100000
|
||||
@@:
|
||||
test dword [ebx+DwIcRawIntrStat], DW_INT_TX_ABRT
|
||||
jnz @f
|
||||
pause
|
||||
loop @b
|
||||
@@:
|
||||
mov eax, [ebx+DwIcClrTxAbrt]
|
||||
call dw_ctrl_disable
|
||||
ret
|
||||
endp
|
||||
|
||||
; One idle step of a transfer wait loop.
|
||||
; A healthy transfer is over within a few milliseconds, well inside the
|
||||
; first two timer ticks, and spins through them: a transfer that yields
|
||||
; its slice is at the scheduler's mercy for the rest of it. Past that the
|
||||
; bus is stuck or crawling, and the wait gives up the CPU a tick at a time
|
||||
; instead of burning a core until XferTimeout.
|
||||
; in: eax = ticks elapsed since the transfer began. Preserves all but eax.
|
||||
DW_SPIN_TICKS = 2
|
||||
|
||||
proc dw_wait_step
|
||||
cmp eax, DW_SPIN_TICKS
|
||||
jae .yield
|
||||
pause
|
||||
ret
|
||||
.yield:
|
||||
push ebx
|
||||
movi ebx, 1
|
||||
invoke Delay ; preserves every register
|
||||
pop ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
; One-time controller setup after mapping.
|
||||
; in: ebx = MMIO base.
|
||||
proc dw_ctrl_init
|
||||
push eax ecx
|
||||
call dw_ctrl_disable
|
||||
mov dword [ebx+DwIcCon], DW_CON_MASTER + DW_CON_SPEED_FAST + \
|
||||
DW_CON_RESTART_EN + DW_CON_SLAVE_DIS
|
||||
; The counts come from variables: they depend on the reference clock, which
|
||||
; is decided by whoever found the controller (PCI LPSS or AMD FCH). The
|
||||
; standard-mode registers get the same values scaled up so that they are
|
||||
; sane should anything ever switch the speed bits back.
|
||||
mov eax, [DwHcnt]
|
||||
mov [ebx+DwIcFsSclHcnt], eax
|
||||
lea eax, [eax*4]
|
||||
mov [ebx+DwIcSsSclHcnt], eax
|
||||
mov eax, [DwLcnt]
|
||||
mov [ebx+DwIcFsSclLcnt], eax
|
||||
lea eax, [eax*4]
|
||||
mov [ebx+DwIcSsSclLcnt], eax
|
||||
mov eax, [DwSdaHold]
|
||||
mov [ebx+DwIcSdaHold], eax
|
||||
mov dword [ebx+DwIcIntrMask], 0
|
||||
mov dword [ebx+DwIcRxTl], 0
|
||||
mov dword [ebx+DwIcTxTl], 0
|
||||
mov eax, [ebx+DwIcClrIntr]
|
||||
pop ecx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; One combined I2C transaction: optional write phase, then optional read phase
|
||||
; with a repeated START between them. Fully polled.
|
||||
; out: eax = 0 on success, IC_TX_ABRT_SOURCE value on NAK/abort, -1 on timeout.
|
||||
proc dw_xfer stdcall uses ebx esi edi, addr:dword, wbuf:dword, wlen:dword, \
|
||||
rbuf:dword, rlen:dword
|
||||
locals
|
||||
wsent dd ?
|
||||
rqueued dd ?
|
||||
rgot dd ?
|
||||
t0 dd ?
|
||||
endl
|
||||
mov ebx, [I2cMmio]
|
||||
call dw_ctrl_disable
|
||||
mov eax, [addr]
|
||||
mov [ebx+DwIcTar], eax
|
||||
mov eax, [ebx+DwIcClrIntr]
|
||||
mov dword [ebx+DwIcEnable], 1
|
||||
xor eax, eax
|
||||
mov [wsent], eax
|
||||
mov [rqueued], eax
|
||||
mov [rgot], eax
|
||||
invoke GetTimerTicks
|
||||
mov [t0], eax
|
||||
.loop:
|
||||
; Abort (NAK and friends) ends the transfer immediately.
|
||||
test dword [ebx+DwIcRawIntrStat], DW_INT_TX_ABRT
|
||||
jnz .abort
|
||||
; Drain the RX FIFO first so it can never overflow.
|
||||
test dword [ebx+DwIcStatus], DW_STAT_RFNE
|
||||
jz .no_rx
|
||||
mov edx, [rgot]
|
||||
cmp edx, [rlen]
|
||||
jae .no_rx
|
||||
mov eax, [ebx+DwIcDataCmd]
|
||||
mov edi, [rbuf]
|
||||
mov [edi+edx], al
|
||||
inc edx
|
||||
mov [rgot], edx
|
||||
jmp .loop
|
||||
.no_rx:
|
||||
; Feed the write phase.
|
||||
mov eax, [wsent]
|
||||
cmp eax, [wlen]
|
||||
jae .push_reads
|
||||
test dword [ebx+DwIcStatus], DW_STAT_TFNF
|
||||
jz .check_done
|
||||
mov esi, [wbuf]
|
||||
movzx edx, byte [esi+eax]
|
||||
inc eax
|
||||
cmp eax, [wlen]
|
||||
jne @f
|
||||
cmp [rlen], 0
|
||||
jne @f
|
||||
or edx, DW_CMD_STOP ; last byte of a write-only transfer
|
||||
@@:
|
||||
mov [ebx+DwIcDataCmd], edx
|
||||
mov [wsent], eax
|
||||
jmp .loop
|
||||
.push_reads:
|
||||
; Feed read commands, at most 8 outstanding so the RX FIFO keeps up.
|
||||
mov eax, [rqueued]
|
||||
cmp eax, [rlen]
|
||||
jae .check_done
|
||||
mov edx, eax
|
||||
sub edx, [rgot]
|
||||
cmp edx, 8
|
||||
jae .check_done
|
||||
test dword [ebx+DwIcStatus], DW_STAT_TFNF
|
||||
jz .check_done
|
||||
mov edx, DW_CMD_READ
|
||||
test eax, eax
|
||||
jnz @f
|
||||
cmp [wlen], 0
|
||||
je @f
|
||||
or edx, DW_CMD_RESTART ; repeated START after the write phase
|
||||
@@:
|
||||
mov ecx, [rlen]
|
||||
dec ecx
|
||||
cmp eax, ecx
|
||||
jne @f
|
||||
or edx, DW_CMD_STOP
|
||||
@@:
|
||||
mov [ebx+DwIcDataCmd], edx
|
||||
inc eax
|
||||
mov [rqueued], eax
|
||||
jmp .loop
|
||||
.check_done:
|
||||
mov eax, [rgot]
|
||||
cmp eax, [rlen]
|
||||
jne .not_done
|
||||
mov eax, [wsent]
|
||||
cmp eax, [wlen]
|
||||
jne .not_done
|
||||
mov eax, [ebx+DwIcStatus]
|
||||
test eax, DW_STAT_TFE
|
||||
jz .not_done
|
||||
test eax, DW_STAT_MST_ACT
|
||||
jnz .not_done
|
||||
call dw_ctrl_disable
|
||||
xor eax, eax
|
||||
ret
|
||||
.not_done:
|
||||
invoke GetTimerTicks
|
||||
sub eax, [t0]
|
||||
cmp eax, [XferTimeout]
|
||||
jae .timeout
|
||||
call dw_wait_step
|
||||
jmp .loop
|
||||
.abort:
|
||||
mov esi, [ebx+DwIcTxAbrtSource]
|
||||
mov eax, [ebx+DwIcClrTxAbrt]
|
||||
call dw_ctrl_disable
|
||||
mov eax, esi
|
||||
test eax, eax
|
||||
jnz @f
|
||||
or eax, 0x80000000
|
||||
@@:
|
||||
ret
|
||||
.timeout:
|
||||
call dw_ctrl_abort
|
||||
or eax, -1
|
||||
ret
|
||||
endp
|
||||
|
||||
; Reads one HID input report as a single continuous bus transaction, the way
|
||||
; interrupt-driven hosts (Windows, Linux) do it: the optional register-address
|
||||
; write and every read command are queued into the TX FIFO before the bytes
|
||||
; start flowing, so nothing on the wire depends on how fast the host loop
|
||||
; runs. The previous adaptive read (fetch 2 length bytes, decide, fetch the
|
||||
; rest, stop short) was cut down on the wire to 3 bytes for an empty poll -
|
||||
; and the SIPODEV/Hantick touchpad firmwares are exactly the kind of thing
|
||||
; that wedges when an input read is shorter than the frame they prepared.
|
||||
; rlen should not exceed the TX FIFO depth (IC_COMP_PARAM_1 bits 23:16, plus
|
||||
; one) or the queue loop degrades to feeding the FIFO on the fly, which
|
||||
; reintroduces pauses.
|
||||
; in: addr = slave, wlen bytes at wbuf written first (0 = plain read),
|
||||
; rlen bytes read into buf.
|
||||
; out: eax = 0 ok, IC_TX_ABRT_SOURCE on NAK/abort, -1 on timeout.
|
||||
; Timeout check for the dw_read_block wait spots; expands inside the proc so
|
||||
; [t0] and [XferTimeout] resolve in the caller's own frame.
|
||||
macro BLOCK_TICK fail_label {
|
||||
invoke GetTimerTicks
|
||||
sub eax, [t0]
|
||||
cmp eax, [XferTimeout]
|
||||
jae fail_label
|
||||
call dw_wait_step
|
||||
}
|
||||
|
||||
proc dw_read_block stdcall uses ebx esi edi, addr:dword, wbuf:dword, wlen:dword, buf:dword, rlen:dword
|
||||
locals
|
||||
rgot dd ?
|
||||
t0 dd ?
|
||||
endl
|
||||
mov ebx, [I2cMmio]
|
||||
call dw_ctrl_disable
|
||||
mov eax, [addr]
|
||||
mov [ebx+DwIcTar], eax
|
||||
mov eax, [ebx+DwIcClrIntr]
|
||||
mov dword [ebx+DwIcEnable], 1
|
||||
invoke GetTimerTicks
|
||||
mov [t0], eax
|
||||
mov [rgot], 0
|
||||
; Write phase: the register address bytes, no STOP - the read continues the
|
||||
; same transaction after a repeated START.
|
||||
xor ecx, ecx
|
||||
.wr:
|
||||
cmp ecx, [wlen]
|
||||
jae .queue_reads
|
||||
test dword [ebx+DwIcRawIntrStat], DW_INT_TX_ABRT
|
||||
jnz .abort
|
||||
test dword [ebx+DwIcStatus], DW_STAT_TFNF
|
||||
jz .wr_wait
|
||||
mov esi, [wbuf]
|
||||
movzx edx, byte [esi+ecx]
|
||||
mov [ebx+DwIcDataCmd], edx
|
||||
inc ecx
|
||||
jmp .wr
|
||||
.wr_wait:
|
||||
BLOCK_TICK .timeout
|
||||
jmp .wr
|
||||
.queue_reads:
|
||||
xor ecx, ecx
|
||||
.rq:
|
||||
cmp ecx, [rlen]
|
||||
jae .drain
|
||||
test dword [ebx+DwIcRawIntrStat], DW_INT_TX_ABRT
|
||||
jnz .abort
|
||||
test dword [ebx+DwIcStatus], DW_STAT_TFNF
|
||||
jz .rq_wait
|
||||
mov edx, DW_CMD_READ
|
||||
test ecx, ecx
|
||||
jnz .not_first
|
||||
cmp [wlen], 0
|
||||
je .not_first
|
||||
or edx, DW_CMD_RESTART
|
||||
.not_first:
|
||||
mov eax, [rlen]
|
||||
dec eax
|
||||
cmp ecx, eax
|
||||
jne @f
|
||||
or edx, DW_CMD_STOP
|
||||
@@:
|
||||
mov [ebx+DwIcDataCmd], edx
|
||||
inc ecx
|
||||
; Drain opportunistically so a FIFO shallower than rlen cannot deadlock the
|
||||
; queue loop (the RX side fills while the TX side is full).
|
||||
test dword [ebx+DwIcStatus], DW_STAT_RFNE
|
||||
jz .rq
|
||||
call .take_byte
|
||||
jmp .rq
|
||||
.rq_wait:
|
||||
BLOCK_TICK .timeout
|
||||
jmp .rq
|
||||
.drain:
|
||||
test dword [ebx+DwIcRawIntrStat], DW_INT_TX_ABRT
|
||||
jnz .abort
|
||||
test dword [ebx+DwIcStatus], DW_STAT_RFNE
|
||||
jz .chk
|
||||
call .take_byte
|
||||
jmp .drain
|
||||
; Moves one byte from the RX FIFO into the caller's buffer. Exactly rlen
|
||||
; reads are queued into freshly flushed FIFOs, so a byte beyond rlen should
|
||||
; never arrive; if one does anyway it is still taken off the FIFO, so the
|
||||
; drain loop cannot stall on it, but it is dropped rather than written
|
||||
; past the end of the buffer.
|
||||
.take_byte:
|
||||
mov edx, [rgot]
|
||||
mov eax, [ebx+DwIcDataCmd]
|
||||
cmp edx, [rlen]
|
||||
jae @f
|
||||
mov edi, [buf]
|
||||
mov [edi+edx], al
|
||||
inc edx
|
||||
mov [rgot], edx
|
||||
@@:
|
||||
retn
|
||||
.chk:
|
||||
mov eax, [rgot]
|
||||
cmp eax, [rlen]
|
||||
jne .wait
|
||||
test dword [ebx+DwIcStatus], DW_STAT_MST_ACT
|
||||
jnz .wait
|
||||
call dw_ctrl_disable
|
||||
xor eax, eax
|
||||
ret
|
||||
.wait:
|
||||
BLOCK_TICK .timeout
|
||||
jmp .drain
|
||||
.abort:
|
||||
mov esi, [ebx+DwIcTxAbrtSource]
|
||||
mov eax, [ebx+DwIcClrTxAbrt]
|
||||
call dw_ctrl_disable
|
||||
mov eax, esi
|
||||
test eax, eax
|
||||
jnz @f
|
||||
or eax, 0x80000000
|
||||
@@:
|
||||
ret
|
||||
.timeout:
|
||||
call dw_ctrl_abort
|
||||
or eax, -1
|
||||
ret
|
||||
endp
|
||||
@@ -0,0 +1,646 @@
|
||||
; Minimal HID report descriptor parser.
|
||||
;
|
||||
; The goal is not a full HID implementation: the parser walks the descriptor
|
||||
; once and remembers the bit layout of the first input report that contains
|
||||
; relative X and relative Y (Generic Desktop / X, Y) - i.e. the mouse
|
||||
; compatibility collection that every I2C mouse and every Windows Precision
|
||||
; Touchpad exposes. Buttons (Usage Page 9) and a relative wheel found in the
|
||||
; same report are picked up too. Absolute (digitizer) reports are advanced
|
||||
; over but otherwise ignored.
|
||||
;
|
||||
; Report IDs are honoured: bit positions are counted separately per report ID
|
||||
; and the chosen ID is checked in every incoming packet.
|
||||
;
|
||||
; Alongside the mouse report, the parser also maps the touchpad (Windows
|
||||
; Precision Touchpad) report: the report that carries Tip Switch usages.
|
||||
; Each Tip Switch opens a new finger block; the absolute X and Y that follow
|
||||
; it belong to that finger; Contact Count and the Button-page fields of the
|
||||
; same report are recorded too. Once the pad is switched into touchpad mode
|
||||
; those offsets are what the frame decoder reads - every vendor lays the
|
||||
; frame out differently, and only the descriptor knows how.
|
||||
HID_MAX_FINGERS = 5
|
||||
|
||||
HID_MAX_USAGES = 16
|
||||
HID_MAX_REPIDS = 16
|
||||
|
||||
; Returns the pointer to the input bit counter of the current report ID,
|
||||
; allocating a new slot on first use.
|
||||
; out: ebx -> dword bit counter. Clobbers eax, ecx.
|
||||
proc hid_get_bits_slot
|
||||
mov eax, [p_report_id]
|
||||
xor ecx, ecx
|
||||
.scan:
|
||||
cmp ecx, [p_idcnt]
|
||||
jae .add
|
||||
cmp eax, [p_ids+ecx*4]
|
||||
jz .found
|
||||
inc ecx
|
||||
jmp .scan
|
||||
.add:
|
||||
cmp ecx, HID_MAX_REPIDS
|
||||
jb @f
|
||||
dec ecx ; table full: reuse the last slot
|
||||
jmp .found
|
||||
@@:
|
||||
mov [p_ids+ecx*4], eax
|
||||
mov dword [p_bits+ecx*4], 0
|
||||
mov dword [p_fbits+ecx*4], 0
|
||||
inc [p_idcnt]
|
||||
.found:
|
||||
lea ebx, [p_bits+ecx*4]
|
||||
ret
|
||||
endp
|
||||
|
||||
; Handles one Input main item. v_flags = item data (bit 2 = relative).
|
||||
proc hid_process_input
|
||||
push eax ebx ecx edx
|
||||
call hid_get_bits_slot
|
||||
mov eax, [ebx]
|
||||
mov [v_base], eax
|
||||
; Advance the counter over this field right away.
|
||||
mov eax, [p_report_size]
|
||||
imul eax, [p_report_count]
|
||||
add [ebx], eax
|
||||
; Remember the largest logical maximum ever attached to Generic Desktop X
|
||||
; and Y. The mouse collection declares a tiny relative range there while
|
||||
; the touchpad collection declares the real surface extents, so the
|
||||
; maximum over the whole descriptor is the size of the pad - which is what
|
||||
; the button zones are measured against, and it differs per model.
|
||||
cmp [p_usage_cnt], 0
|
||||
je .no_extent
|
||||
xor ecx, ecx
|
||||
.ext_loop:
|
||||
cmp ecx, [p_usage_cnt]
|
||||
jae .no_extent
|
||||
mov eax, [p_usages+ecx*4]
|
||||
cmp eax, 0x00010030
|
||||
jne .ext_y
|
||||
mov eax, [p_log_max]
|
||||
cmp eax, [t_padmaxx]
|
||||
jbe .ext_next
|
||||
mov [t_padmaxx], eax
|
||||
jmp .ext_next
|
||||
.ext_y:
|
||||
cmp eax, 0x00010031
|
||||
jne .ext_next
|
||||
mov eax, [p_log_max]
|
||||
cmp eax, [t_padmaxy]
|
||||
jbe .ext_next
|
||||
mov [t_padmaxy], eax
|
||||
.ext_next:
|
||||
inc ecx
|
||||
jmp .ext_loop
|
||||
.no_extent:
|
||||
; Button-style field: Usage Minimum/Maximum on the Button page.
|
||||
cmp [p_usage_min], -1
|
||||
je .not_buttons
|
||||
cmp [p_usage_max], -1
|
||||
je .not_buttons
|
||||
cmp [p_usage_page], 9
|
||||
jne .not_buttons
|
||||
cmp [p_report_size], 1 ; buttons are always 1-bit fields
|
||||
jne .done
|
||||
mov eax, [v_base]
|
||||
mov ecx, [p_report_count]
|
||||
call hid_note_buttons
|
||||
jmp .done
|
||||
.not_buttons:
|
||||
cmp [p_usage_cnt], 0
|
||||
je .done
|
||||
call hid_note_touchpad
|
||||
; Usage-list field: look for GD/X, GD/Y, GD/Wheel among the usages.
|
||||
test [v_flags], 4 ; only relative fields are interesting
|
||||
jz .done
|
||||
xor ecx, ecx
|
||||
.usage_loop:
|
||||
cmp ecx, [p_report_count]
|
||||
jae .done
|
||||
; usage index = min(field index, usage count - 1): a short usage list
|
||||
; applies its last usage to the remaining fields.
|
||||
mov edx, [p_usage_cnt]
|
||||
dec edx
|
||||
mov eax, ecx
|
||||
cmp eax, edx
|
||||
jbe @f
|
||||
mov eax, edx
|
||||
@@:
|
||||
mov eax, [p_usages+eax*4]
|
||||
cmp eax, 0x00010030
|
||||
je .is_x
|
||||
cmp eax, 0x00010031
|
||||
je .is_y
|
||||
cmp eax, 0x00010038
|
||||
je .is_wheel
|
||||
.next_usage:
|
||||
inc ecx
|
||||
jmp .usage_loop
|
||||
.is_x:
|
||||
test [t_have], 1
|
||||
jnz .next_usage
|
||||
call hid_claim_report_id
|
||||
jc .next_usage
|
||||
call hid_field_offset
|
||||
mov [t_xoff], eax
|
||||
mov eax, [p_report_size]
|
||||
mov [t_xsize], eax
|
||||
or [t_have], 1
|
||||
jmp .next_usage
|
||||
.is_y:
|
||||
test [t_have], 2
|
||||
jnz .next_usage
|
||||
call hid_claim_report_id
|
||||
jc .next_usage
|
||||
call hid_field_offset
|
||||
mov [t_yoff], eax
|
||||
mov eax, [p_report_size]
|
||||
mov [t_ysize], eax
|
||||
or [t_have], 2
|
||||
jmp .next_usage
|
||||
.is_wheel:
|
||||
test [t_have], 8
|
||||
jnz .next_usage
|
||||
mov eax, [t_id]
|
||||
cmp eax, -1 ; wheel never claims a report on its own
|
||||
je .next_usage
|
||||
cmp eax, [p_report_id]
|
||||
jne .next_usage
|
||||
call hid_field_offset
|
||||
mov [t_woff], eax
|
||||
mov eax, [p_report_size]
|
||||
mov [t_wsize], eax
|
||||
or [t_have], 8
|
||||
jmp .next_usage
|
||||
.done:
|
||||
pop edx ecx ebx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Records a run of 1-bit Button-page fields starting at bit eax, ecx of them.
|
||||
; The mouse decoder wants the buttons of ITS report: an item from some other
|
||||
; report is kept only until a better one turns up, and .eof drops it if it
|
||||
; still does not match. The touchpad report keeps its own copy.
|
||||
proc hid_note_buttons
|
||||
push eax ecx edx
|
||||
cmp ecx, 8
|
||||
jbe @f
|
||||
mov ecx, 8
|
||||
@@:
|
||||
mov edx, [p_report_id]
|
||||
cmp edx, [t_ptp_id]
|
||||
jne .mouse
|
||||
cmp [t_pbtn_cnt], 0
|
||||
jne .mouse
|
||||
mov [t_pbtn_off], eax
|
||||
mov [t_pbtn_cnt], ecx
|
||||
.mouse:
|
||||
cmp [t_btncnt], 0
|
||||
je .take
|
||||
mov edx, [t_btnid]
|
||||
cmp edx, [t_id] ; already the chosen report's: keep
|
||||
je .done
|
||||
mov edx, [p_report_id]
|
||||
cmp edx, [t_btnid] ; a second run in the same report: keep the first
|
||||
je .done
|
||||
.take:
|
||||
mov [t_btnoff], eax
|
||||
mov [t_btncnt], ecx
|
||||
mov eax, [p_report_id]
|
||||
mov [t_btnid], eax
|
||||
.done:
|
||||
pop edx ecx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Walks the usages of the current input item looking for the touchpad
|
||||
; fields. Field k takes usage min(k, count-1), as in the mouse search.
|
||||
proc hid_note_touchpad
|
||||
push eax ebx ecx edx
|
||||
xor ecx, ecx
|
||||
.field:
|
||||
cmp ecx, [p_report_count]
|
||||
jae .done
|
||||
mov edx, [p_usage_cnt]
|
||||
dec edx
|
||||
mov eax, ecx
|
||||
cmp eax, edx
|
||||
jbe @f
|
||||
mov eax, edx
|
||||
@@:
|
||||
mov ebx, [p_usages+eax*4] ; ebx = usage of field ecx
|
||||
call hid_field_offset ; eax = its bit offset
|
||||
cmp ebx, 0x000D0042 ; Tip Switch: a new finger
|
||||
je .tip
|
||||
cmp ebx, 0x000D0054 ; Contact Count
|
||||
je .count
|
||||
cmp ebx, 0x000D0051 ; Contact Identifier
|
||||
je .cid
|
||||
cmp ebx, 0x00010030
|
||||
je .x
|
||||
cmp ebx, 0x00010031
|
||||
je .y
|
||||
shr ebx, 16
|
||||
cmp ebx, 9 ; buttons written as a usage list
|
||||
jne .next
|
||||
push ecx
|
||||
neg ecx
|
||||
add ecx, [p_report_count] ; the fields from here to the end
|
||||
call hid_note_buttons
|
||||
pop ecx
|
||||
jmp .done ; one run per item is enough
|
||||
.tip:
|
||||
cmp [t_ptp_id], -1
|
||||
jne @f
|
||||
mov edx, [p_report_id]
|
||||
mov [t_ptp_id], edx ; the first report with fingers is the one
|
||||
@@:
|
||||
call hid_in_ptp
|
||||
jne .next
|
||||
mov edx, [t_fcount]
|
||||
cmp edx, HID_MAX_FINGERS
|
||||
jae .next
|
||||
mov [t_ftip+edx*4], eax
|
||||
mov dword [t_fxs+edx*4], 0
|
||||
mov dword [t_fys+edx*4], 0
|
||||
mov dword [t_fcids+edx*4], 0
|
||||
inc [t_fcount]
|
||||
jmp .next
|
||||
.cid:
|
||||
call hid_in_ptp
|
||||
jne .next
|
||||
mov edx, [t_fcount]
|
||||
test edx, edx
|
||||
jz .next
|
||||
dec edx
|
||||
cmp dword [t_fcids+edx*4], 0
|
||||
jne .next
|
||||
mov [t_fcid+edx*4], eax
|
||||
mov eax, [p_report_size]
|
||||
mov [t_fcids+edx*4], eax
|
||||
jmp .next
|
||||
.count:
|
||||
call hid_in_ptp
|
||||
jne .next
|
||||
mov [t_ccnt_off], eax
|
||||
mov eax, [p_report_size]
|
||||
mov [t_ccnt_size], eax
|
||||
jmp .next
|
||||
.x:
|
||||
test [v_flags], 4 ; absolute only; relative is the mouse
|
||||
jnz .next
|
||||
call hid_in_ptp
|
||||
jne .next
|
||||
mov edx, [t_fcount]
|
||||
test edx, edx
|
||||
jz .next
|
||||
dec edx
|
||||
cmp dword [t_fxs+edx*4], 0
|
||||
jne .next
|
||||
mov [t_fx+edx*4], eax
|
||||
mov eax, [p_report_size]
|
||||
mov [t_fxs+edx*4], eax
|
||||
jmp .next
|
||||
.y:
|
||||
test [v_flags], 4
|
||||
jnz .next
|
||||
call hid_in_ptp
|
||||
jne .next
|
||||
mov edx, [t_fcount]
|
||||
test edx, edx
|
||||
jz .next
|
||||
dec edx
|
||||
cmp dword [t_fys+edx*4], 0
|
||||
jne .next
|
||||
mov [t_fy+edx*4], eax
|
||||
mov eax, [p_report_size]
|
||||
mov [t_fys+edx*4], eax
|
||||
.next:
|
||||
inc ecx
|
||||
jmp .field
|
||||
.done:
|
||||
pop edx ecx ebx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; ZF set when the current item belongs to the touchpad report.
|
||||
proc hid_in_ptp
|
||||
push eax
|
||||
mov eax, [p_report_id]
|
||||
cmp eax, [t_ptp_id]
|
||||
pop eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Size in bytes of the feature report with id eax; 0 when the descriptor
|
||||
; never mentioned one.
|
||||
proc hid_feature_bytes
|
||||
push ecx
|
||||
xor ecx, ecx
|
||||
@@:
|
||||
cmp ecx, [p_idcnt]
|
||||
jae .none
|
||||
cmp eax, [p_ids+ecx*4]
|
||||
je .found
|
||||
inc ecx
|
||||
jmp @b
|
||||
.found:
|
||||
mov eax, [p_fbits+ecx*4]
|
||||
add eax, 7
|
||||
shr eax, 3
|
||||
pop ecx
|
||||
ret
|
||||
.none:
|
||||
xor eax, eax
|
||||
pop ecx
|
||||
ret
|
||||
endp
|
||||
|
||||
; Locks the candidate report ID to the current one, or fails (CF=1) when a
|
||||
; different report already holds X/Y.
|
||||
proc hid_claim_report_id
|
||||
mov eax, [t_id]
|
||||
cmp eax, -1
|
||||
jne @f
|
||||
mov eax, [p_report_id]
|
||||
mov [t_id], eax
|
||||
clc
|
||||
ret
|
||||
@@:
|
||||
cmp eax, [p_report_id]
|
||||
jne .taken
|
||||
clc
|
||||
ret
|
||||
.taken:
|
||||
stc
|
||||
ret
|
||||
endp
|
||||
|
||||
; Bit offset of field #ecx of the current item.
|
||||
; in: ecx = field index. out: eax = v_base + ecx * report_size.
|
||||
proc hid_field_offset
|
||||
mov eax, [p_report_size]
|
||||
imul eax, ecx
|
||||
add eax, [v_base]
|
||||
ret
|
||||
endp
|
||||
|
||||
; Parses the report descriptor.
|
||||
; in: esi -> descriptor, ecx = length.
|
||||
; out: eax = 1 and f_* variables filled if a usable report was found.
|
||||
proc hid_parse_report_desc uses ebx esi edi
|
||||
lea edi, [esi+ecx]
|
||||
xor eax, eax
|
||||
mov [p_usage_page], eax
|
||||
mov [p_report_size], eax
|
||||
mov [p_report_count], eax
|
||||
mov [p_report_id], eax
|
||||
mov [p_uses_repid], eax
|
||||
mov [p_usage_cnt], eax
|
||||
mov [p_idcnt], eax
|
||||
mov [p_log_max], eax
|
||||
mov [t_padmaxx], eax
|
||||
mov [t_padmaxy], eax
|
||||
mov [t_have], eax
|
||||
mov [t_btncnt], eax
|
||||
mov [t_wsize], eax
|
||||
mov [p_usage_min], -1
|
||||
mov [p_usage_max], -1
|
||||
mov [t_id], -1
|
||||
mov [t_btnid], -2
|
||||
mov [t_ptp_id], -1
|
||||
mov [t_fcount], eax
|
||||
mov [t_ccnt_size], eax
|
||||
mov [t_pbtn_cnt], eax
|
||||
mov [t_ptp_bytes], eax
|
||||
.loop:
|
||||
cmp esi, edi
|
||||
jae .eof
|
||||
movzx eax, byte [esi]
|
||||
inc esi
|
||||
cmp al, 0xFE
|
||||
je .long_item
|
||||
mov ecx, eax
|
||||
and ecx, 3
|
||||
cmp ecx, 3
|
||||
jne @f
|
||||
inc ecx ; size code 3 means 4 bytes
|
||||
@@:
|
||||
lea ebx, [esi+ecx]
|
||||
cmp ebx, edi
|
||||
ja .eof
|
||||
xor edx, edx
|
||||
jecxz .no_data
|
||||
cmp ecx, 1
|
||||
jne @f
|
||||
movzx edx, byte [esi]
|
||||
jmp .have_data
|
||||
@@:
|
||||
cmp ecx, 2
|
||||
jne @f
|
||||
movzx edx, word [esi]
|
||||
jmp .have_data
|
||||
@@:
|
||||
mov edx, [esi]
|
||||
.have_data:
|
||||
add esi, ecx
|
||||
.no_data:
|
||||
and eax, 0xFC
|
||||
; Global items
|
||||
cmp al, 0x04
|
||||
je .g_usage_page
|
||||
cmp al, 0x84
|
||||
je .g_report_id
|
||||
cmp al, 0x74
|
||||
je .g_report_size
|
||||
cmp al, 0x94
|
||||
je .g_report_count
|
||||
cmp al, 0x24
|
||||
je .g_log_max
|
||||
; Local items
|
||||
cmp al, 0x08
|
||||
je .l_usage
|
||||
cmp al, 0x18
|
||||
je .l_usage_min
|
||||
cmp al, 0x28
|
||||
je .l_usage_max
|
||||
; Main items
|
||||
cmp al, 0x80
|
||||
je .m_input
|
||||
cmp al, 0x90
|
||||
je .m_clear_locals
|
||||
cmp al, 0xB0
|
||||
je .m_feature
|
||||
cmp al, 0xA0
|
||||
je .m_clear_locals
|
||||
cmp al, 0xC0
|
||||
je .m_clear_locals
|
||||
jmp .loop
|
||||
.g_usage_page:
|
||||
and edx, 0xFFFF
|
||||
mov [p_usage_page], edx
|
||||
jmp .loop
|
||||
.g_report_id:
|
||||
mov [p_report_id], edx
|
||||
mov [p_uses_repid], 1
|
||||
jmp .loop
|
||||
.g_report_size:
|
||||
mov [p_report_size], edx
|
||||
jmp .loop
|
||||
.g_report_count:
|
||||
mov [p_report_count], edx
|
||||
jmp .loop
|
||||
.g_log_max:
|
||||
mov [p_log_max], edx
|
||||
jmp .loop
|
||||
.l_usage:
|
||||
mov ebx, [p_usage_cnt]
|
||||
cmp ebx, HID_MAX_USAGES
|
||||
jae .loop
|
||||
cmp ecx, 4 ; 4-byte usage carries its own page
|
||||
je @f
|
||||
mov eax, [p_usage_page]
|
||||
shl eax, 16
|
||||
or edx, eax
|
||||
@@:
|
||||
mov [p_usages+ebx*4], edx
|
||||
inc [p_usage_cnt]
|
||||
jmp .loop
|
||||
.l_usage_min:
|
||||
mov [p_usage_min], edx
|
||||
jmp .loop
|
||||
.l_usage_max:
|
||||
mov [p_usage_max], edx
|
||||
jmp .loop
|
||||
.m_input:
|
||||
mov [v_flags], edx
|
||||
call hid_process_input
|
||||
jmp .m_clear_locals ; input bits are not feature bits
|
||||
.m_feature:
|
||||
; Feature reports are only ever written, never decoded, but writing one
|
||||
; needs its exact size: a SET_REPORT shorter than the report is ignored by
|
||||
; some firmwares (the Elan Input Mode report has two bytes, mode and the
|
||||
; selective-reporting switches - one byte does nothing there).
|
||||
call hid_get_bits_slot
|
||||
mov eax, [p_report_size]
|
||||
imul eax, [p_report_count]
|
||||
add [p_fbits+ecx*4], eax
|
||||
.m_clear_locals:
|
||||
xor eax, eax
|
||||
mov [p_usage_cnt], eax
|
||||
mov [p_usage_min], -1
|
||||
mov [p_usage_max], -1
|
||||
jmp .loop
|
||||
.long_item:
|
||||
cmp esi, edi
|
||||
jae .eof
|
||||
movzx ecx, byte [esi]
|
||||
lea esi, [esi+ecx+2]
|
||||
jmp .loop
|
||||
.eof:
|
||||
; Size of the touchpad report, when there is one.
|
||||
mov eax, [t_ptp_id]
|
||||
cmp eax, -1
|
||||
je .no_ptp
|
||||
xor ecx, ecx
|
||||
@@:
|
||||
cmp ecx, [p_idcnt]
|
||||
jae .no_ptp
|
||||
cmp eax, [p_ids+ecx*4]
|
||||
je @f
|
||||
inc ecx
|
||||
jmp @b
|
||||
@@:
|
||||
mov eax, [p_bits+ecx*4]
|
||||
add eax, 7
|
||||
shr eax, 3
|
||||
mov [t_ptp_bytes], eax
|
||||
.no_ptp:
|
||||
; Success needs relative X and Y in the same report - or, failing that, a
|
||||
; touchpad report with at least one complete finger, which is then the only
|
||||
; thing the device will be driven through.
|
||||
mov eax, [t_have]
|
||||
and eax, 3
|
||||
cmp eax, 3
|
||||
je .have_mouse
|
||||
cmp [t_fcount], 0
|
||||
je .fail
|
||||
cmp dword [t_fxs], 0
|
||||
je .fail
|
||||
cmp dword [t_fys], 0
|
||||
je .fail
|
||||
mov [f_repid], -1 ; no mouse report to match
|
||||
mov [f_bytes], 0
|
||||
mov [t_btncnt], 0
|
||||
movi eax, 1
|
||||
ret
|
||||
.have_mouse:
|
||||
; Keep buttons/wheel only when they live in the chosen report.
|
||||
mov eax, [t_btnid]
|
||||
cmp eax, [t_id]
|
||||
je @f
|
||||
mov [t_btncnt], 0
|
||||
@@:
|
||||
; Final layout.
|
||||
mov eax, [t_id]
|
||||
mov [f_repid], eax
|
||||
xor ecx, ecx
|
||||
@@:
|
||||
cmp ecx, [p_idcnt]
|
||||
jae .no_bits
|
||||
cmp eax, [p_ids+ecx*4]
|
||||
je .got_bits
|
||||
inc ecx
|
||||
jmp @b
|
||||
.got_bits:
|
||||
mov eax, [p_bits+ecx*4]
|
||||
add eax, 7
|
||||
shr eax, 3
|
||||
mov [f_bytes], eax
|
||||
movi eax, 1
|
||||
ret
|
||||
.no_bits:
|
||||
.fail:
|
||||
xor eax, eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Extracts an unsigned field from an input report.
|
||||
; in: esi -> report data, eax = bit offset, ecx = bit count (1..24).
|
||||
; out: eax = value.
|
||||
proc hid_extract_u
|
||||
push ebx ecx edx
|
||||
mov edx, eax
|
||||
shr edx, 3
|
||||
mov ebx, [esi+edx] ; buffer has spare bytes at the end
|
||||
and eax, 7
|
||||
push ecx
|
||||
mov ecx, eax
|
||||
shr ebx, cl
|
||||
pop ecx
|
||||
neg ecx
|
||||
add ecx, 32
|
||||
shl ebx, cl
|
||||
shr ebx, cl
|
||||
mov eax, ebx
|
||||
pop edx ecx ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
; Same, sign-extended.
|
||||
proc hid_extract_s
|
||||
push ebx ecx edx
|
||||
mov edx, eax
|
||||
shr edx, 3
|
||||
mov ebx, [esi+edx]
|
||||
and eax, 7
|
||||
push ecx
|
||||
mov ecx, eax
|
||||
shr ebx, cl
|
||||
pop ecx
|
||||
neg ecx
|
||||
add ecx, 32
|
||||
shl ebx, cl
|
||||
sar ebx, cl
|
||||
mov eax, ebx
|
||||
pop edx ecx ebx
|
||||
ret
|
||||
endp
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,26 @@
|
||||
[touchpad]
|
||||
; pointer speed in percent of the driver's default (on top of the [mouse]
|
||||
; speed above; pads differ in resolution)
|
||||
speed=100
|
||||
; how far a finger must move before the pointer follows, in pad units;
|
||||
; larger is steadier under a pressing finger, 0 turns the filter off
|
||||
jitter=1
|
||||
; the same, for a finger that landed on the button strip: it is pressing
|
||||
; rather than steering there, so it needs a stricter margin
|
||||
jitter_buttons=45
|
||||
; pad units of two-finger travel per wheel step, and the direction
|
||||
scroll_step=64
|
||||
scroll_invert=0
|
||||
; turn a short, still touch into a click: one finger left, two right,
|
||||
; three middle
|
||||
tap_enable=1
|
||||
; tap, then touch again at once and move: the button stays down for that
|
||||
; second touch - this is how text is selected and how one draws
|
||||
tap_drag=1
|
||||
; right click: 0 never, 1 bottom-right corner, 2 by finger count (two
|
||||
; fingers right, three middle), 3 either
|
||||
right_click=1
|
||||
; button strip along the bottom edge, in percent of the surface: its
|
||||
; height, and where its left half ends
|
||||
button_zone=15
|
||||
right_split=50
|
||||
@@ -0,0 +1,72 @@
|
||||
; Asks the I2C touchpad driver to read its settings again.
|
||||
;
|
||||
; The driver takes everything it can be tuned with from the [touchpad] section
|
||||
; of /sys/settings/system.ini, and it reads that file once while loading. This
|
||||
; tells it to read the file again, so editing a setting takes effect straight
|
||||
; away instead of at the next boot.
|
||||
;
|
||||
; There is no window: the outcome goes to the debug board, the way the driver
|
||||
; reports everything else.
|
||||
|
||||
format binary as ""
|
||||
use32
|
||||
db 'MENUET01'
|
||||
dd 1, start, i_end, mem, mem, 0, 0
|
||||
|
||||
include '../../programs/macros.inc'
|
||||
|
||||
SRV_RELOAD_CONF = 1
|
||||
|
||||
start:
|
||||
; 1. Find the driver's service by name.
|
||||
mcall 68, 16, srv_name
|
||||
test eax, eax
|
||||
jz .no_driver
|
||||
mov [ioctl.handle], eax
|
||||
; 2. Ask it to reload. No data travels either way: the driver reads the file
|
||||
; itself, so the settings file stays the only place they are written down.
|
||||
mcall 68, 17, ioctl
|
||||
test eax, eax
|
||||
jnz .refused
|
||||
mov esi, msg_ok
|
||||
jmp .say
|
||||
.no_driver:
|
||||
mov esi, msg_no_driver
|
||||
jmp .say
|
||||
.refused:
|
||||
mov esi, msg_refused
|
||||
.say:
|
||||
call board_str
|
||||
or eax, -1
|
||||
mcall
|
||||
|
||||
; Writes a zero-terminated string to the debug board.
|
||||
; in: esi -> string
|
||||
board_str:
|
||||
lodsb
|
||||
test al, al
|
||||
jz .done
|
||||
mov cl, al
|
||||
mcall 63, 1
|
||||
jmp board_str
|
||||
.done:
|
||||
ret
|
||||
|
||||
srv_name db 'I2CHID', 0
|
||||
|
||||
align 4
|
||||
ioctl:
|
||||
.handle dd 0
|
||||
.io_code dd SRV_RELOAD_CONF
|
||||
.input dd 0
|
||||
.inp_size dd 0
|
||||
.output dd 0
|
||||
.out_size dd 0
|
||||
|
||||
msg_ok db 'tpreload: touchpad settings reloaded', 13, 10, 0
|
||||
msg_no_driver db 'tpreload: the I2C touchpad driver is not loaded', 13, 10, 0
|
||||
msg_refused db 'tpreload: the driver refused the request', 13, 10, 0
|
||||
|
||||
i_end:
|
||||
rb 1024
|
||||
mem:
|
||||
@@ -139,6 +139,7 @@ import core,\
|
||||
RegKeyboard,\
|
||||
DelKeyboard,\
|
||||
Sleep,\
|
||||
Delay,\
|
||||
GetTimerTicks,\
|
||||
\
|
||||
strncat,\
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SERIAL_COMPATIBLE_API_VER = 0 ; increments in case of breaking changes
|
||||
SERIAL_COMPATIBLE_API_VER = 1 ; increments in case of breaking changes
|
||||
|
||||
SERIAL_API_GET_VERSION = 0
|
||||
SERIAL_API_SRV_ADD_PORT = 1
|
||||
@@ -9,6 +9,7 @@ SERIAL_API_CLOSE_PORT = 5
|
||||
SERIAL_API_SETUP_PORT = 6
|
||||
SERIAL_API_READ = 7
|
||||
SERIAL_API_WRITE = 8
|
||||
SERIAL_API_ENUM_PORTS = 9
|
||||
|
||||
SERIAL_API_ERR_PORT_INVALID = 1
|
||||
SERIAL_API_ERR_PORT_BUSY = 2
|
||||
@@ -29,6 +30,9 @@ SERIAL_CONF_STOP_BITS_2 = 2
|
||||
|
||||
SERIAL_CONF_FLOW_CTRL_NONE = 0
|
||||
|
||||
SERIAL_INFO_DRIVER_LEN = 16
|
||||
SERIAL_INFO_DESCR_LEN = 64
|
||||
|
||||
struct SP_DRIVER
|
||||
size dd ? ; size of this struct
|
||||
startup dd ? ; int __stdcall (*startup)(void *drv_data, const struct serial_conf *conf);
|
||||
@@ -46,7 +50,20 @@ struct SP_CONF
|
||||
flow_ctrl db ?
|
||||
ends
|
||||
|
||||
proc serial_add_port stdcall, drv:dword, drv_data:dword
|
||||
struct SP_PORT_INFO
|
||||
size dd ? ; size of this struct
|
||||
driver dd ? ; ASCIIZ driver name, e.g. "uart16550", "usb-cdc"
|
||||
descr dd ? ; ASCIIZ description, may be NULL
|
||||
ends
|
||||
|
||||
struct SP_PORT_ENUM_ENTRY
|
||||
id dd ? ; unique port number (SERIAL_PORT.id)
|
||||
busy dd ? ; 0 = free, non-zero = port is opened
|
||||
driver rb SERIAL_INFO_DRIVER_LEN
|
||||
descr rb SERIAL_INFO_DESCR_LEN
|
||||
ends
|
||||
|
||||
proc serial_add_port stdcall, drv:dword, drv_data:dword, info:dword
|
||||
locals
|
||||
handler dd ?
|
||||
io_code dd ?
|
||||
@@ -60,7 +77,7 @@ endl
|
||||
mov [io_code], SERIAL_API_SRV_ADD_PORT
|
||||
lea eax, [drv]
|
||||
mov [input], eax
|
||||
mov [inp_size], 8
|
||||
mov [inp_size], 12
|
||||
xor eax, eax
|
||||
mov [output], eax
|
||||
mov [out_size], eax
|
||||
@@ -129,7 +146,7 @@ proc serial_port_init
|
||||
ret
|
||||
endp
|
||||
|
||||
proc serial_port_get_version stdcall, version:dword
|
||||
proc serial_port_get_version stdcall uses ebx, version:dword
|
||||
locals
|
||||
.handler dd ?
|
||||
.io_code dd ?
|
||||
@@ -149,7 +166,7 @@ endl
|
||||
|
||||
lea ecx, [.handler]
|
||||
mcall SF_SYS_MISC, SSF_CONTROL_DRIVER
|
||||
|
||||
|
||||
ret
|
||||
endp
|
||||
|
||||
@@ -297,6 +314,43 @@ endl
|
||||
ret
|
||||
endp
|
||||
|
||||
proc serial_port_enum stdcall uses ebx, buf:dword, buf_size:dword, \
|
||||
total:dword, filled:dword
|
||||
locals
|
||||
.handler dd ?
|
||||
.io_code dd ?
|
||||
.input dd ?
|
||||
.inp_size dd ?
|
||||
.output dd ?
|
||||
.out_size dd ?
|
||||
endl
|
||||
push [buf_size]
|
||||
push [buf]
|
||||
mov eax, [serial_drv_handle]
|
||||
mov [.handler], eax
|
||||
mov dword [.io_code], SERIAL_API_ENUM_PORTS
|
||||
mov [.input], esp
|
||||
mov dword [.inp_size], 8
|
||||
sub esp, 8
|
||||
mov [.output], esp
|
||||
mov dword [.out_size], 8
|
||||
|
||||
lea ecx, [.handler]
|
||||
mcall SF_SYS_MISC, SSF_CONTROL_DRIVER
|
||||
|
||||
pop ebx edx
|
||||
cmp eax, -1
|
||||
je .err
|
||||
mov ecx, [total]
|
||||
mov [ecx], ebx
|
||||
mov ecx, [filled]
|
||||
mov [ecx], edx
|
||||
.err:
|
||||
|
||||
add esp, 8
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
serial_drv_name db "SERIAL", 0
|
||||
serial_drv_handle dd ?
|
||||
@@ -1,5 +0,0 @@
|
||||
#SHS
|
||||
echo Installing serial driver for kterm...
|
||||
cp /kolibrios/utils/kterm/serial.sys /sys/drivers/
|
||||
/sys/loaddrv serial
|
||||
echo Serial driver successfully installed!
|
||||
+148
-7
@@ -44,6 +44,8 @@ struct SERIAL_PORT
|
||||
rx_buf RING_BUF
|
||||
tx_buf RING_BUF
|
||||
conf SP_CONF
|
||||
driver rb SERIAL_INFO_DRIVER_LEN ; ASCIIZ, copied from SP_PORT_INFO.driver in add_port
|
||||
descr rb SERIAL_INFO_DESCR_LEN ; ASCIIZ, copied from SP_PORT_INFO.descr in add_port (may be empty)
|
||||
ends
|
||||
|
||||
proc START c, reason:dword, cmdline:dword
|
||||
@@ -57,7 +59,7 @@ proc START c, reason:dword, cmdline:dword
|
||||
stdcall uart_probe, 0x2f8, 3
|
||||
stdcall uart_probe, 0x3e8, 4
|
||||
stdcall uart_probe, 0x2e8, 3
|
||||
invoke RegService, drv_name, service_proc
|
||||
invoke RegService, serial_drv_name, service_proc
|
||||
ret
|
||||
|
||||
.fail:
|
||||
@@ -75,7 +77,7 @@ srv_calls:
|
||||
dd service_proc.setup
|
||||
dd service_proc.read
|
||||
dd service_proc.write
|
||||
; TODO enumeration
|
||||
dd service_proc.enum_ports
|
||||
srv_calls_end:
|
||||
|
||||
proc service_proc stdcall uses ebx esi edi, ioctl:dword
|
||||
@@ -97,11 +99,13 @@ proc service_proc stdcall uses ebx esi edi, ioctl:dword
|
||||
; in:
|
||||
; +0: driver
|
||||
; +4: driver data
|
||||
cmp [edx + IOCTL.inp_size], 8
|
||||
; +8: port info (SP_PORT_INFO*)
|
||||
cmp [edx + IOCTL.inp_size], 12
|
||||
jb .err
|
||||
mov ebx, [edx + IOCTL.input]
|
||||
mov ecx, [ebx]
|
||||
mov edx, [ebx + 4]
|
||||
mov ebx, [ebx + 8]
|
||||
call add_port
|
||||
ret
|
||||
|
||||
@@ -137,6 +141,7 @@ proc service_proc stdcall uses ebx esi edi, ioctl:dword
|
||||
; +4 addr to SERIAL_CONF
|
||||
; out:
|
||||
; +0 port handle if success
|
||||
; eax = 0 if success, otherwise an error code SERIAL_API_ERR_*
|
||||
cmp [edx + IOCTL.inp_size], 8
|
||||
jb .err
|
||||
cmp [edx + IOCTL.out_size], 4
|
||||
@@ -220,25 +225,60 @@ proc service_proc stdcall uses ebx esi edi, ioctl:dword
|
||||
mov [ebx], ecx
|
||||
ret
|
||||
|
||||
.enum_ports:
|
||||
; in:
|
||||
; +0 output buffer (array of SP_PORT_ENUM_ENTRY), may be NULL
|
||||
; +4 output buffer size in bytes
|
||||
; out:
|
||||
; +0 total number of ports in the system
|
||||
; +4 number of entries actually filled into the buffer
|
||||
; eax = 0 if success, -1 otherwise
|
||||
cmp [edx + IOCTL.inp_size], 8
|
||||
jb .err
|
||||
cmp [edx + IOCTL.out_size], 8
|
||||
jb .err
|
||||
mov ebx, [edx + IOCTL.input]
|
||||
push edx
|
||||
mov eax, [ebx]
|
||||
mov edx, [ebx + 4]
|
||||
call sp_enum
|
||||
pop edx
|
||||
mov ebx, [edx + IOCTL.output]
|
||||
mov [ebx], eax
|
||||
mov [ebx + 4], ecx
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
.err:
|
||||
or eax, -1
|
||||
ret
|
||||
endp
|
||||
|
||||
; struct SERIAL_PORT __fastcall *add_port(const struct SP_DRIVER *drv, const void *drv_data);
|
||||
align 4
|
||||
; @param ecx pointer to SP_DRIVER
|
||||
; @param edx driver-specific argument
|
||||
; @param ebx pointer to SP_PORT_INFO
|
||||
; @return SERIAL_PORT descriptor
|
||||
proc add_port uses edi
|
||||
DEBUGF L_DBG, "serial.sys: add port drv=%x drv_data=%x\n", ecx, edx
|
||||
DEBUGF L_DBG, "serial.sys: add port drv=%x drv_data=%x info=%x\n", ecx, edx, ebx
|
||||
|
||||
mov eax, [ecx + SP_DRIVER.size]
|
||||
cmp eax, sizeof.SP_DRIVER
|
||||
jne .fail
|
||||
|
||||
test ebx, ebx
|
||||
jz .fail
|
||||
mov eax, [ebx + SP_PORT_INFO.size]
|
||||
cmp eax, sizeof.SP_PORT_INFO
|
||||
jne .fail
|
||||
|
||||
; alloc memory for serial port descriptor
|
||||
push ecx
|
||||
push edx
|
||||
push ebx
|
||||
movi eax, sizeof.SERIAL_PORT
|
||||
invoke Kmalloc
|
||||
pop ebx
|
||||
pop edx
|
||||
pop ecx
|
||||
test eax, eax
|
||||
@@ -252,6 +292,17 @@ proc add_port uses edi
|
||||
invoke MutexInit
|
||||
and [edi + SERIAL_PORT.con], 0
|
||||
|
||||
; copy port info strings
|
||||
mov eax, [ebx + SP_PORT_INFO.driver]
|
||||
lea edx, [edi + SERIAL_PORT.driver]
|
||||
mov ecx, SERIAL_INFO_DRIVER_LEN
|
||||
call copy_bounded_str
|
||||
|
||||
mov eax, [ebx + SP_PORT_INFO.descr]
|
||||
lea edx, [edi + SERIAL_PORT.descr]
|
||||
mov ecx, SERIAL_INFO_DESCR_LEN
|
||||
call copy_bounded_str
|
||||
|
||||
mov ecx, port_list_mutex
|
||||
invoke MutexLock
|
||||
|
||||
@@ -282,7 +333,35 @@ proc add_port uses edi
|
||||
endp
|
||||
|
||||
align 4
|
||||
; u32 __fastcall *remove_port(struct SERIAL_PORT *port);
|
||||
; copies an ASCIIZ string into a fixed-size buffer: copies up to (size - 1)
|
||||
; bytes or until the NUL, then zero-pads the rest of the buffer
|
||||
; @param eax source ASCIIZ ptr, may be NULL
|
||||
; @param edx dest buffer ptr
|
||||
; @param ecx dest buffer size in bytes, must be >= 1
|
||||
proc copy_bounded_str uses esi edi
|
||||
mov esi, eax
|
||||
mov edi, edx
|
||||
dec ecx ; reserve the last byte for the NUL terminator
|
||||
.copy:
|
||||
test ecx, ecx
|
||||
jz .pad
|
||||
test esi, esi
|
||||
jz .pad
|
||||
lodsb
|
||||
test al, al
|
||||
jz .pad
|
||||
stosb
|
||||
dec ecx
|
||||
jmp .copy
|
||||
.pad:
|
||||
inc ecx ; account for the reserved NUL byte
|
||||
xor al, al
|
||||
rep stosb
|
||||
ret
|
||||
endp
|
||||
|
||||
align 4
|
||||
; @param ecx serial port descriptor
|
||||
proc remove_port uses esi
|
||||
mov esi, ecx
|
||||
mov ecx, port_list_mutex
|
||||
@@ -657,7 +736,69 @@ proc sp_write
|
||||
ret
|
||||
endp
|
||||
|
||||
drv_name db 'SERIAL', 0
|
||||
align 4
|
||||
; @param eax buf
|
||||
; @param edx buf_size (bytes)
|
||||
; @return eax total port count in the system
|
||||
; ecx entries filled into buf
|
||||
proc sp_enum uses ebx esi edi
|
||||
mov ecx, eax
|
||||
mov eax, edx
|
||||
xor edx, edx
|
||||
mov ebx, sizeof.SP_PORT_ENUM_ENTRY
|
||||
div ebx
|
||||
; eax max entries count
|
||||
|
||||
mov edi, ecx
|
||||
imul eax, sizeof.SP_PORT_ENUM_ENTRY
|
||||
add eax, ecx
|
||||
mov edx, eax ; end-of-buffer boundary
|
||||
|
||||
xor ebx, ebx ; total port count
|
||||
xor ecx, ecx ; filled count
|
||||
|
||||
push ecx edx
|
||||
mov ecx, port_list_mutex
|
||||
invoke MutexLock
|
||||
pop edx ecx
|
||||
|
||||
mov esi, port_list
|
||||
.next:
|
||||
mov esi, [esi + SERIAL_PORT.fd]
|
||||
cmp esi, port_list
|
||||
jz .done
|
||||
inc ebx
|
||||
cmp edi, edx
|
||||
jae .next
|
||||
|
||||
mov eax, [esi + SERIAL_PORT.id]
|
||||
mov [edi + SP_PORT_ENUM_ENTRY.id], eax
|
||||
xor eax, eax
|
||||
cmp dword [esi + SERIAL_PORT.con], 0
|
||||
setnz al
|
||||
mov [edi + SP_PORT_ENUM_ENTRY.busy], eax
|
||||
|
||||
push ecx esi edi
|
||||
lea esi, [esi + SERIAL_PORT.driver]
|
||||
lea edi, [edi + SP_PORT_ENUM_ENTRY.driver]
|
||||
mov ecx, (SERIAL_INFO_DRIVER_LEN + SERIAL_INFO_DESCR_LEN) / 4
|
||||
rep movsd
|
||||
pop edi esi ecx
|
||||
|
||||
add edi, sizeof.SP_PORT_ENUM_ENTRY
|
||||
inc ecx
|
||||
jmp .next
|
||||
|
||||
.done:
|
||||
push ecx
|
||||
mov ecx, port_list_mutex
|
||||
invoke MutexUnlock
|
||||
pop ecx
|
||||
|
||||
mov eax, ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
include_debug_strings
|
||||
|
||||
align 4
|
||||
|
||||
@@ -169,6 +169,7 @@ proc uart_probe stdcall uses ebx esi edi, io_addr:dword, irqn:dword
|
||||
; register port
|
||||
lea ecx, [uart_drv]
|
||||
mov edx, edi
|
||||
lea ebx, [uart_port_info]
|
||||
call add_port
|
||||
test eax, eax
|
||||
jz .free_desc ; TODO detach_int_handler?
|
||||
@@ -406,3 +407,11 @@ uart_drv:
|
||||
dd uart_reconf
|
||||
dd uart_tx
|
||||
uart_drv_end:
|
||||
|
||||
align 4
|
||||
uart_port_info:
|
||||
dd uart_port_end - uart_port_info
|
||||
dd uart_port_name
|
||||
dd 0
|
||||
uart_port_end:
|
||||
uart_port_name db 'uart16550', 0
|
||||
+203
-310
@@ -1,6 +1,6 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2026. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; FTDI chips driver for KolibriOS ;;
|
||||
@@ -15,10 +15,11 @@
|
||||
format PE DLL native 0.05
|
||||
entry START
|
||||
|
||||
DEBUG = 1
|
||||
L_DBG = 1
|
||||
L_ERR = 2
|
||||
|
||||
__DEBUG__ = 1
|
||||
__DEBUG_LEVEL__ = 1
|
||||
__DEBUG_LEVEL__ = L_ERR
|
||||
|
||||
node equ ftdi_context
|
||||
node.next equ ftdi_context.next_context
|
||||
@@ -122,9 +123,10 @@ TYPE_232H=6
|
||||
TYPE_230X=7
|
||||
|
||||
;strings
|
||||
my_driver db 'usbother',0
|
||||
my_driver db 'usbftdi',0
|
||||
serial_driver db 'SERIAL',0
|
||||
nomemory_msg db 'K : no memory',13,10,0
|
||||
nomemory_msg db 'ftdi: no memory',13,10,0
|
||||
ftdi_port_name db 'ftdi',0
|
||||
|
||||
; Structures
|
||||
struct ftdi_context
|
||||
@@ -200,10 +202,13 @@ endp
|
||||
|
||||
|
||||
proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD, .interface:DWORD
|
||||
|
||||
locals
|
||||
.pinfo rb sizeof.SP_PORT_INFO
|
||||
endl
|
||||
|
||||
invoke USBGetParam, [.config_pipe], 0
|
||||
mov edx, eax
|
||||
DEBUGF 2,'K : Detected device vendor: 0x%x\n', [eax+usb_descr.idVendor]
|
||||
DEBUGF L_DBG, 'ftdi: Detected device vendor: 0x%x\n', [eax+usb_descr.idVendor]
|
||||
cmp word[eax+usb_descr.idVendor], 0x0403
|
||||
jnz .notftdi
|
||||
mov eax, sizeof.ftdi_context
|
||||
@@ -214,7 +219,7 @@ proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD
|
||||
invoke SysMsgBoardStr
|
||||
jmp .nothing
|
||||
@@:
|
||||
DEBUGF 2,'K : Adding struct to list 0x%x\n', eax
|
||||
DEBUGF L_DBG, 'ftdi: Adding struct to list 0x%x\n', eax
|
||||
call linkedlist_add
|
||||
|
||||
mov ebx, [.config_pipe]
|
||||
@@ -233,7 +238,7 @@ proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD
|
||||
jmp .slow
|
||||
|
||||
mov cx, [edx+usb_descr.bcdDevice]
|
||||
DEBUGF 2, 'K : Chip type 0x%x\n', ecx
|
||||
DEBUGF L_DBG, 'ftdi: Chip type 0x%x\n', ecx
|
||||
cmp cx, 0x400
|
||||
jnz @f
|
||||
mov [eax + ftdi_context.chipType], TYPE_BM
|
||||
@@ -287,8 +292,13 @@ proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD
|
||||
mov eax, [serial_drv_entry]
|
||||
test eax, eax
|
||||
jz @f
|
||||
stdcall serial_add_port, uart_drv, ebx
|
||||
DEBUGF 1, "usbftdi: add serial port with result %x\n", eax
|
||||
mov dword [.pinfo + SP_PORT_INFO.size], sizeof.SP_PORT_INFO
|
||||
mov dword [.pinfo + SP_PORT_INFO.driver], ftdi_port_name
|
||||
; TODO obtain iManufacturer, iProduct and iSerial strings
|
||||
mov dword [.pinfo + SP_PORT_INFO.descr], 0
|
||||
lea ecx, [.pinfo]
|
||||
stdcall serial_add_port, uart_drv, ebx, ecx
|
||||
DEBUGF L_DBG, 'ftdi: add serial port with result %x\n', eax
|
||||
@@:
|
||||
mov [ebx + ftdi_context.port_handle], eax
|
||||
|
||||
@@ -296,7 +306,7 @@ proc AddDevice stdcall uses ebx esi edi, .config_pipe:DWORD, .config_descr:DWORD
|
||||
ret
|
||||
|
||||
.notftdi:
|
||||
DEBUGF 1,'K : Skipping not FTDI device\n'
|
||||
DEBUGF L_DBG, 'ftdi: Skipping not FTDI device\n'
|
||||
.nothing:
|
||||
xor eax, eax
|
||||
ret
|
||||
@@ -317,7 +327,7 @@ EventData rd 3
|
||||
endl
|
||||
mov edi, [ioctl]
|
||||
mov eax, [edi+io_code]
|
||||
DEBUGF 1,'K : FTDI got the request: %d\n', eax
|
||||
DEBUGF L_DBG, 'ftdi: FTDI got the request: %d\n', eax
|
||||
test eax, eax ;0
|
||||
jz .version
|
||||
dec eax ;1
|
||||
@@ -416,7 +426,7 @@ endl
|
||||
.version:
|
||||
jmp .endswitch
|
||||
.error:
|
||||
DEBUGF 1, 'K : FTDI error occured! %d\n', eax
|
||||
DEBUGF L_ERR, 'ftdi: error occured! %d\n', eax
|
||||
;mov esi, [edi+output]
|
||||
;mov [esi], dword 'ERR0'
|
||||
;or [esi], eax
|
||||
@@ -449,7 +459,7 @@ endl
|
||||
mov word[ConfPacket+6], cx
|
||||
.own_index:
|
||||
mov ebx, [edi+4]
|
||||
DEBUGF 2,'K : ConfPacket 0x%x 0x%x\n', [ConfPacket], [ConfPacket+4]
|
||||
DEBUGF L_DBG, 'ftdi: ConfPacket 0x%x 0x%x\n', [ConfPacket], [ConfPacket+4]
|
||||
lea esi, [ConfPacket]
|
||||
lea edi, [EventData]
|
||||
invoke USBControlTransferAsync, [ebx + ftdi_context.nullP], esi, 0,\
|
||||
@@ -465,7 +475,7 @@ endl
|
||||
jmp .error
|
||||
|
||||
.ftdi_setrtshigh:
|
||||
DEBUGF 2,'K : FTDI Setting RTS pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Setting RTS pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
|
||||
@@ -473,7 +483,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_setrtslow:
|
||||
DEBUGF 2,'K : FTDI Setting RTS pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Setting RTS pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
|
||||
@@ -481,7 +491,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_setdtrhigh:
|
||||
DEBUGF 2,'K : FTDI Setting DTR pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Setting DTR pin HIGH PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
|
||||
@@ -489,7 +499,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_setdtrlow:
|
||||
DEBUGF 2,'K : FTDI Setting DTR pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Setting DTR pin LOW PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_MODEM_CTRL_REQUEST shl 8) \
|
||||
@@ -497,7 +507,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_usb_reset:
|
||||
DEBUGF 2,'K : FTDI Reseting PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Reseting PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_RESET_REQUEST shl 8) \
|
||||
@@ -505,7 +515,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_purge_rx_buf:
|
||||
DEBUGF 2, 'K : FTDI Purge TX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Purge TX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_RESET_REQUEST shl 8) \
|
||||
@@ -513,7 +523,7 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_purge_tx_buf:
|
||||
DEBUGF 2, 'K : FTDI Purge RX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Purge RX buffer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_RESET_REQUEST shl 8) \
|
||||
@@ -521,42 +531,42 @@ endl
|
||||
jmp .ftdi_out_control_transfer_noinp
|
||||
|
||||
.ftdi_set_bitmode:
|
||||
DEBUGF 2, 'K : FTDI Set bitmode 0x%x, bitmask 0x%x %d PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF L_DBG, 'ftdi: Set bitmode 0x%x, bitmask 0x%x %d PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8]:2,[edi+10]:2,[edi],[edi+4]
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_BITMODE_REQUEST shl 8)
|
||||
jmp .ftdi_out_control_transfer_withinp
|
||||
|
||||
.ftdi_set_line_property:
|
||||
DEBUGF 2, 'K : FTDI Set line property 0x%x PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF L_DBG, 'ftdi: Set line property 0x%x PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8]:4,[edi],[edi+4]
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_DATA_REQUEST shl 8)
|
||||
jmp .ftdi_out_control_transfer_withinp
|
||||
|
||||
.ftdi_set_latency_timer:
|
||||
DEBUGF 2, 'K : FTDI Set latency %d PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF L_DBG, 'ftdi: Set latency %d PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8],[edi],[edi+4]
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_LATENCY_TIMER_REQUEST shl 8)
|
||||
jmp .ftdi_out_control_transfer_withinp
|
||||
|
||||
.ftdi_set_event_char:
|
||||
DEBUGF 2, 'K : FTDI Set event char %c PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF L_DBG, 'ftdi: Set event char %c PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8],[edi],[edi+4]
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_EVENT_CHAR_REQUEST shl 8)
|
||||
jmp .ftdi_out_control_transfer_withinp
|
||||
|
||||
.ftdi_set_error_char:
|
||||
DEBUGF 2, 'K : FTDI Set error char %c PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF L_DBG, 'ftdi: Set error char %c PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8],[edi],[edi+4]
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_ERROR_CHAR_REQUEST shl 8)
|
||||
jmp .ftdi_out_control_transfer_withinp
|
||||
|
||||
.ftdi_setflowctrl:
|
||||
DEBUGF 2, 'K : FTDI Set flow control PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Set flow control PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_FLOW_CTRL_REQUEST shl 8) + (0 shl 16)
|
||||
@@ -569,7 +579,7 @@ endl
|
||||
jmp .own_index
|
||||
|
||||
.ftdi_read_pins:
|
||||
DEBUGF 2, 'K : FTDI Read pins PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Read pins PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov ebx, [edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_IN_REQTYPE) \
|
||||
@@ -598,7 +608,7 @@ endl
|
||||
jmp .error
|
||||
|
||||
.ftdi_set_wchunksize:
|
||||
DEBUGF 2, 'K : FTDI Set write chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF L_DBG, 'ftdi: Set write chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8], [edi], [edi+4]
|
||||
mov ebx, [edi+4]
|
||||
mov ecx, [edi+8]
|
||||
@@ -608,7 +618,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_get_wchunksize:
|
||||
DEBUGF 2, 'K : FTDI Get write chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Get write chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov esi, [edi+output]
|
||||
mov edi, [edi+input]
|
||||
@@ -618,7 +628,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_set_rchunksize:
|
||||
DEBUGF 2, 'K : FTDI Set read chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
|
||||
DEBUGF L_DBG, 'ftdi: Set read chunksize %d bytes PID: %d Dev handler 0x0x%x\n', \
|
||||
[edi+8], [edi], [edi+4]
|
||||
mov ebx, [edi+4]
|
||||
mov ecx, [edi+8]
|
||||
@@ -628,7 +638,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_get_rchunksize:
|
||||
DEBUGF 2, 'K : FTDI Get read chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Get read chunksize PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov esi, [edi+output]
|
||||
mov edi, [edi+input]
|
||||
@@ -638,7 +648,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_write_data:
|
||||
DEBUGF 2, 'K : FTDI Write %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
|
||||
DEBUGF L_DBG, 'ftdi: Write %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
|
||||
[edi], [edi+4]
|
||||
mov esi, edi
|
||||
add esi, 12
|
||||
@@ -685,7 +695,7 @@ endl
|
||||
jmp .write_loop
|
||||
|
||||
.ftdi_read_data:
|
||||
DEBUGF 2, 'K : FTDI Read %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
|
||||
DEBUGF L_DBG, 'ftdi: Read %d bytes PID: %d Dev handler 0x%x\n', [edi+8],\
|
||||
[edi], [edi+4]
|
||||
mov edi, [ioctl]
|
||||
mov esi, [edi+input]
|
||||
@@ -743,7 +753,7 @@ endl
|
||||
;---Dirty hack end
|
||||
|
||||
.ftdi_poll_modem_status:
|
||||
DEBUGF 2, 'K : FTDI Poll modem status PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Poll modem status PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov ebx, [edi+4]
|
||||
mov dword[ConfPacket], (FTDI_DEVICE_IN_REQTYPE) \
|
||||
@@ -767,7 +777,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_get_latency_timer:
|
||||
DEBUGF 2, 'K : FTDI Get latency timer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
DEBUGF L_DBG, 'ftdi: Get latency timer PID: %d Dev handler 0x0x%x\n', [edi],\
|
||||
[edi+4]
|
||||
mov ebx, [edi+4]
|
||||
mov dword[ConfPacket], FTDI_DEVICE_IN_REQTYPE \
|
||||
@@ -787,7 +797,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_get_list:
|
||||
DEBUGF 2, 'K : FTDI devices list request\n'
|
||||
DEBUGF L_DBG, 'ftdi: devices list request\n'
|
||||
mov edi, [edi+output]
|
||||
xor ecx, ecx
|
||||
call linkedlist_gethead
|
||||
@@ -817,7 +827,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_lock:
|
||||
DEBUGF 2, 'K : FTDI Lock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
|
||||
DEBUGF L_DBG, 'ftdi: Lock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
|
||||
mov esi, [edi+input]
|
||||
mov ebx, [esi+4]
|
||||
mov eax, [ebx + ftdi_context.lockPID]
|
||||
@@ -831,7 +841,7 @@ endl
|
||||
jmp .endswitch
|
||||
|
||||
.ftdi_unlock:
|
||||
DEBUGF 2, 'K : FTDI Unlock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
|
||||
DEBUGF L_DBG, 'ftdi: Unlock PID: %d Dev handler 0x0x%x\n', [edi], [edi+4]
|
||||
mov esi, [edi+input]
|
||||
mov edi, [edi+output]
|
||||
mov ebx, [esi+4]
|
||||
@@ -845,145 +855,19 @@ endl
|
||||
mov [edi], eax
|
||||
jmp .endswitch
|
||||
|
||||
H_CLK = 120000000
|
||||
C_CLK = 48000000
|
||||
.ftdi_set_baudrate:
|
||||
DEBUGF 2, 'K : FTDI Set baudrate to %d PID: %d Dev handle: 0x%x\n',\
|
||||
DEBUGF L_DBG, 'ftdi: Set baudrate to %d PID: %d Dev handle: 0x%x\n',\
|
||||
[edi+8], [edi], [edi+4]
|
||||
mov ebx, [edi+4]
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jl .c_clk
|
||||
imul eax, [edi+8], 10
|
||||
cmp eax, H_CLK / 0x3FFF
|
||||
jle .c_clk
|
||||
.h_clk:
|
||||
cmp dword[edi+8], H_CLK/10
|
||||
jl .h_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, H_CLK/10
|
||||
jmp .calcend
|
||||
|
||||
.c_clk:
|
||||
cmp dword[edi+8], C_CLK/16
|
||||
jl .c_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, C_CLK/16
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud1:
|
||||
cmp dword[edi+8], H_CLK/(10 + 10/2)
|
||||
jl .h_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, H_CLK/(10 + 10/2)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud1:
|
||||
cmp dword[edi+8], C_CLK/(16 + 16/2)
|
||||
jl .c_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, C_CLK/(16 + 16/2)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud2:
|
||||
cmp dword[edi+8], H_CLK/(2*10)
|
||||
jl .h_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, H_CLK/(2*10)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud2:
|
||||
cmp dword[edi+8], C_CLK/(2*16)
|
||||
jl .c_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, C_CLK/(2*16)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud3:
|
||||
mov eax, H_CLK*16/10 ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div dword[edi+8] ; [edi+8] - baudrate
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jz .h_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.h_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .h_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.h_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, H_CLK*16/10
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jz .rounddownbaud
|
||||
inc ecx
|
||||
jmp .rounddownbaud
|
||||
|
||||
.c_nextbaud3:
|
||||
mov eax, C_CLK ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div dword[edi+8] ; [edi+8] - baudrate
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jnz .c_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.c_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .c_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.c_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, C_CLK
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jnz .rounddownbaud
|
||||
inc ecx
|
||||
|
||||
.rounddownbaud:
|
||||
mov edx, eax ; edx - encoded_divisor
|
||||
shr edx, 3
|
||||
and eax, 0x7
|
||||
push 7 6 5 1 4 2 3 0
|
||||
mov eax, [esp+eax*4]
|
||||
shl eax, 14
|
||||
or edx, eax
|
||||
add esp, 32
|
||||
|
||||
.calcend:
|
||||
mov eax, edx ; eax - *value
|
||||
mov ecx, edx ; ecx - *index
|
||||
and eax, 0xFFFF
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jge .foxyindex
|
||||
shr ecx, 16
|
||||
jmp .preparepacket
|
||||
.foxyindex:
|
||||
shr ecx, 8
|
||||
and ecx, 0xFF00
|
||||
or ecx, [ebx + ftdi_context.index]
|
||||
|
||||
.preparepacket:
|
||||
mov esi, [edi+8]
|
||||
call ftdi_calc_baud_divisor
|
||||
mov word[ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_BAUDRATE_REQUEST shl 8)
|
||||
mov word[ConfPacket+2], ax
|
||||
mov word[ConfPacket+4], cx
|
||||
mov word[ConfPacket+6], 0
|
||||
jmp .own_index
|
||||
|
||||
jmp .own_index
|
||||
|
||||
endp
|
||||
restore handle
|
||||
restore io_code
|
||||
@@ -993,10 +877,143 @@ restore output
|
||||
restore out_size
|
||||
|
||||
|
||||
proc ftdi_calc_baud_divisor
|
||||
; in: ebx = ftdi_context pointer
|
||||
; esi = baud rate
|
||||
; out: ax = encoded value
|
||||
; cx = encoded index
|
||||
; destroys: eax, ecx, edx, esi
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jl .c_clk
|
||||
imul eax, esi, 10
|
||||
cmp eax, H_CLK / 0x3FFF
|
||||
jle .c_clk
|
||||
.h_clk:
|
||||
cmp esi, H_CLK / 10
|
||||
jl .h_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, H_CLK / 10
|
||||
jmp .calcend
|
||||
|
||||
.c_clk:
|
||||
cmp esi, C_CLK / 16
|
||||
jl .c_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, C_CLK / 16
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud1:
|
||||
cmp esi, H_CLK / (10 + 10 / 2)
|
||||
jl .h_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, H_CLK / (10 + 10 / 2)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud1:
|
||||
cmp esi, C_CLK / (16 + 16 / 2)
|
||||
jl .c_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, C_CLK/(16 + 16 / 2)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud2:
|
||||
cmp esi, H_CLK / (2 * 10)
|
||||
jl .h_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, H_CLK / (2 * 10)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud2:
|
||||
cmp esi, C_CLK / (2 * 16)
|
||||
jl .c_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, C_CLK / (2 * 16)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud3:
|
||||
mov eax, H_CLK * 16 / 10 ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div esi
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jz .h_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.h_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .h_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.h_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, H_CLK * 16 / 10
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jz .rounddownbaud
|
||||
inc ecx
|
||||
jmp .rounddownbaud
|
||||
|
||||
.c_nextbaud3:
|
||||
mov eax, C_CLK ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div esi
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jnz .c_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.c_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .c_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.c_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, C_CLK
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jnz .rounddownbaud
|
||||
inc ecx
|
||||
|
||||
.rounddownbaud:
|
||||
mov edx, eax ; edx - encoded_divisor
|
||||
shr edx, 3
|
||||
and eax, 0x7
|
||||
push 7 6 5 1 4 2 3 0
|
||||
mov eax, [esp + eax * 4]
|
||||
shl eax, 14
|
||||
or edx, eax
|
||||
add esp, 32
|
||||
|
||||
.calcend:
|
||||
mov eax, edx ; eax - *value
|
||||
mov ecx, edx ; ecx - *index
|
||||
and eax, 0xFFFF
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jge .foxyindex
|
||||
shr ecx, 16
|
||||
ret
|
||||
.foxyindex:
|
||||
shr ecx, 8
|
||||
and ecx, 0xFF00
|
||||
or ecx, [ebx + ftdi_context.index]
|
||||
ret
|
||||
endp
|
||||
|
||||
proc control_callback stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
.buffer:DWORD, .length:DWORD, .calldata:DWORD
|
||||
|
||||
DEBUGF 1, 'K : status is %d\n', [.status]
|
||||
DEBUGF L_DBG, 'ftdi: status is %d\n', [.status]
|
||||
mov ecx, [.calldata]
|
||||
mov eax, [ecx]
|
||||
mov ebx, [ecx+4]
|
||||
@@ -1011,7 +1028,7 @@ endp
|
||||
proc bulk_callback stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
.buffer:DWORD, .length:DWORD, .calldata:DWORD
|
||||
|
||||
DEBUGF 1, 'K : status is %d\n', [.status]
|
||||
DEBUGF L_DBG, 'ftdi: status is %d\n', [.status]
|
||||
mov ecx, [.calldata]
|
||||
mov eax, [ecx]
|
||||
mov ebx, [ecx+4]
|
||||
@@ -1034,7 +1051,7 @@ endp
|
||||
|
||||
proc DeviceDisconnected stdcall uses ebx esi edi, .device_data:DWORD
|
||||
|
||||
DEBUGF 1, 'K : FTDI deleting device data 0x%x\n', [.device_data]
|
||||
DEBUGF L_DBG, 'ftdi: deleting device data 0x%x\n', [.device_data]
|
||||
mov esi, [.device_data]
|
||||
mov eax, [esi + ftdi_context.readBufPtr]
|
||||
test eax, eax
|
||||
@@ -1062,7 +1079,7 @@ proc bulk_in_complete stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
mov eax, [.status]
|
||||
test eax, eax
|
||||
jz @f
|
||||
DEBUGF 2, 'ftdi: bulk in error %x\n', eax
|
||||
DEBUGF L_ERR, 'ftdi: bulk in error %x\n', eax
|
||||
@@:
|
||||
mov ebx, [.calldata]
|
||||
btr dword [ebx + ftdi_context.writeBufLock], 0
|
||||
@@ -1075,7 +1092,7 @@ proc bulk_out_complete stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
mov eax, [.status]
|
||||
test eax, eax
|
||||
jz @f
|
||||
DEBUGF 2, 'ftdi: bulk out error %x\n', eax
|
||||
DEBUGF L_ERR, 'ftdi: bulk out error %x\n', eax
|
||||
@@:
|
||||
mov ebx, [.calldata]
|
||||
mov ecx, [.length]
|
||||
@@ -1092,18 +1109,18 @@ proc bulk_out_complete stdcall uses ebx edi esi, .pipe:DWORD, .status:DWORD, \
|
||||
endp
|
||||
|
||||
proc uart_startup stdcall uses ebx, data:dword, conf:dword
|
||||
DEBUGF 1, "ftdi: startup %x %x\n", [data], [conf]
|
||||
DEBUGF L_DBG, "ftdi: startup %x %x\n", [data], [conf]
|
||||
stdcall uart_reconf, [data], [conf]
|
||||
test eax, eax
|
||||
jz @f
|
||||
DEBUGF 2, "ftdi: uart reconf error %x\n", eax
|
||||
DEBUGF L_ERR, "ftdi: uart reconf error %x\n", eax
|
||||
jmp .exit
|
||||
@@:
|
||||
mov ebx, [data]
|
||||
invoke TimerHS, 2, 2, uart_rx, ebx
|
||||
test eax, eax
|
||||
jnz @f
|
||||
DEBUGF 2, "ftdi: timer creation error\n"
|
||||
DEBUGF L_ERR, "ftdi: timer creation error\n"
|
||||
or eax, -1
|
||||
jmp .exit
|
||||
@@:
|
||||
@@ -1114,7 +1131,7 @@ proc uart_startup stdcall uses ebx, data:dword, conf:dword
|
||||
endp
|
||||
|
||||
proc uart_shutdown stdcall uses ebx, data:dword
|
||||
DEBUGF 1, "ftdi: shutdown %x\n", [data]
|
||||
DEBUGF L_DBG, "ftdi: shutdown %x\n", [data]
|
||||
mov ebx, [data]
|
||||
cmp [ebx + ftdi_context.rx_timer], 0
|
||||
jz @f
|
||||
@@ -1246,137 +1263,14 @@ proc uart_rx stdcall uses ebx esi, data:dword
|
||||
ret
|
||||
endp
|
||||
|
||||
proc ftdi_set_baudrate stdcall uses ebx, dev:dword, baud:dword
|
||||
proc ftdi_set_baudrate stdcall uses ebx esi, dev:dword, baud:dword
|
||||
locals
|
||||
ConfPacket rb 8
|
||||
endl
|
||||
mov ebx, [dev]
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jl .c_clk
|
||||
imul eax, [baud], 10
|
||||
cmp eax, H_CLK / 0x3FFF
|
||||
jle .c_clk
|
||||
.h_clk:
|
||||
cmp dword [baud], H_CLK / 10
|
||||
jl .h_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, H_CLK / 10
|
||||
jmp .calcend
|
||||
mov esi, [baud]
|
||||
call ftdi_calc_baud_divisor
|
||||
|
||||
.c_clk:
|
||||
cmp dword [baud], C_CLK / 16
|
||||
jl .c_nextbaud1
|
||||
xor edx, edx
|
||||
mov ecx, C_CLK / 16
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud1:
|
||||
cmp dword [baud], H_CLK / (10 + 10 / 2)
|
||||
jl .h_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, H_CLK / (10 + 10 / 2)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud1:
|
||||
cmp dword [baud], C_CLK / (16 + 16 / 2)
|
||||
jl .c_nextbaud2
|
||||
mov edx, 1
|
||||
mov ecx, C_CLK/(16 + 16 / 2)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud2:
|
||||
cmp dword [baud], H_CLK / (2 * 10)
|
||||
jl .h_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, H_CLK / (2 * 10)
|
||||
jmp .calcend
|
||||
|
||||
.c_nextbaud2:
|
||||
cmp dword [baud], C_CLK / (2 * 16)
|
||||
jl .c_nextbaud3
|
||||
mov edx, 2
|
||||
mov ecx, C_CLK / (2 * 16)
|
||||
jmp .calcend
|
||||
|
||||
.h_nextbaud3:
|
||||
mov eax, H_CLK * 16 / 10 ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div dword [baud]
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jz .h_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.h_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .h_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.h_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, H_CLK * 16 / 10
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jz .rounddownbaud
|
||||
inc ecx
|
||||
jmp .rounddownbaud
|
||||
|
||||
.c_nextbaud3:
|
||||
mov eax, C_CLK ; eax - best_divisor
|
||||
xor edx, edx
|
||||
div dword [baud]
|
||||
push eax
|
||||
and eax, 1
|
||||
pop eax
|
||||
shr eax, 1
|
||||
jnz .c_rounddowndiv ; jump by result of and eax, 1
|
||||
inc eax
|
||||
.c_rounddowndiv:
|
||||
cmp eax, 0x20000
|
||||
jle .c_best_divok
|
||||
mov eax, 0x1FFFF
|
||||
.c_best_divok:
|
||||
mov ecx, eax
|
||||
mov eax, C_CLK
|
||||
xor edx, edx
|
||||
div ecx
|
||||
xchg ecx, eax ; ecx - best_baud
|
||||
push ecx
|
||||
and ecx, 1
|
||||
pop ecx
|
||||
shr ecx, 1
|
||||
jnz .rounddownbaud
|
||||
inc ecx
|
||||
|
||||
.rounddownbaud:
|
||||
mov edx, eax ; edx - encoded_divisor
|
||||
shr edx, 3
|
||||
and eax, 0x7
|
||||
push 7 6 5 1 4 2 3 0
|
||||
mov eax, [esp + eax * 4]
|
||||
shl eax, 14
|
||||
or edx, eax
|
||||
add esp, 32
|
||||
|
||||
.calcend:
|
||||
mov eax, edx ; eax - *value
|
||||
mov ecx, edx ; ecx - *index
|
||||
and eax, 0xFFFF
|
||||
cmp [ebx + ftdi_context.chipType], TYPE_2232H
|
||||
jge .foxyindex
|
||||
shr ecx, 16
|
||||
jmp .preparepacket
|
||||
.foxyindex:
|
||||
shr ecx, 8
|
||||
and ecx, 0xFF00
|
||||
or ecx, [ebx + ftdi_context.index]
|
||||
|
||||
.preparepacket:
|
||||
mov word [ConfPacket], (FTDI_DEVICE_OUT_REQTYPE) \
|
||||
+ (SIO_SET_BAUDRATE_REQUEST shl 8)
|
||||
mov word [ConfPacket + 2], ax
|
||||
@@ -1451,10 +1345,9 @@ uart_drv:
|
||||
dd uart_tx
|
||||
uart_drv_end:
|
||||
|
||||
serial_drv_entry dd 0
|
||||
include_debug_strings
|
||||
|
||||
data fixups
|
||||
end data
|
||||
|
||||
;for DEBUGF macro
|
||||
include_debug_strings
|
||||
|
||||
serial_drv_entry dd ?
|
||||
@@ -2204,6 +2204,9 @@ proc acm_arm_rx
|
||||
endp
|
||||
|
||||
proc acm_add_device stdcall uses ebx esi edi, .pipe0:dword, .config:dword, .interface:dword
|
||||
locals
|
||||
.pinfo rb sizeof.SP_PORT_INFO
|
||||
endl
|
||||
|
||||
; 1. Parse the descriptors (the ACM data interface is alt setting 0).
|
||||
xor eax, eax
|
||||
@@ -2264,7 +2267,12 @@ proc acm_add_device stdcall uses ebx esi edi, .pipe0:dword, .config:dword, .inte
|
||||
|
||||
cmp [serial_drv_entry], 0
|
||||
je .no_serial
|
||||
stdcall serial_add_port, acm_sp_driver, ebx
|
||||
mov dword [.pinfo+SP_PORT_INFO.size], sizeof.SP_PORT_INFO
|
||||
mov dword [.pinfo+SP_PORT_INFO.driver], acm_port_name
|
||||
; TODO obtain iManufacturer, iProduct and iSerial strings
|
||||
mov dword [.pinfo+SP_PORT_INFO.descr], 0
|
||||
lea ecx, [.pinfo]
|
||||
stdcall serial_add_port, acm_sp_driver, ebx, ecx
|
||||
mov [ebx+acm_dev.PortHandle], eax
|
||||
test eax, eax
|
||||
jz .no_serial
|
||||
@@ -2652,6 +2660,7 @@ endp
|
||||
|
||||
; strings and static data
|
||||
my_service db 'usbcdc', 0
|
||||
acm_port_name db 'cdc-acm', 0
|
||||
netdev_name db 'USB CDC-NCM', 0
|
||||
ecm_netdev_name db 'USB CDC-ECM', 0
|
||||
ecm_zlp_dummy db 0 ; address for zero-length transfers
|
||||
|
||||
@@ -1754,8 +1754,14 @@ proc disk_read_write stdcall uses ebx esi edi, \
|
||||
mov eax, [numsectors]
|
||||
mov eax, [eax]
|
||||
; 2. The transfer length for SCSI_{READ,WRITE}10 commands can not be greater
|
||||
; than 0xFFFF, so split the request to slices with <= 0xFFFF sectors.
|
||||
max_sectors_at_time = 0xFFFF
|
||||
; than 0xFFFF sectors, but that is not the practical limit: the field size is
|
||||
; the only thing the standard bounds, while real sticks hang their firmware on
|
||||
; multi-megabyte single commands. The kernel disk cache asks for as much as
|
||||
; CACHE_MAX_ALLOC_SIZE (4 MB) in one call, i.e. 8192 sectors, and that is
|
||||
; exactly where such sticks stop answering and re-enumerate. Linux caps
|
||||
; usb-storage at 240 sectors (120 KB) for the same reason; do the same and
|
||||
; split larger requests into slices.
|
||||
max_sectors_at_time = 240
|
||||
.split:
|
||||
push eax ; .length_rest
|
||||
cmp eax, max_sectors_at_time
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
if tup.getconfig("NO_FASM") ~= "" then return end
|
||||
ROOT = "../../.."
|
||||
tup.rule("xhci.asm", "fasm %f %o " .. tup.getconfig("PESTRIP_CMD") .. tup.getconfig("KPACK_CMD"), "%B.sys")
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,993 @@
|
||||
; Device slots, contexts and pipes for the xHCI driver.
|
||||
; This file is included from xhci.asm.
|
||||
|
||||
; =============================================================================
|
||||
; ============================ Context helpers ================================
|
||||
; =============================================================================
|
||||
|
||||
; Returns the address of one context inside a context structure.
|
||||
; in: eax = base of the structure, ecx = index of the context,
|
||||
; esi -> usb_controller.
|
||||
; out: eax = address of the context.
|
||||
proc xhci_context
|
||||
push ecx edx
|
||||
mov edx, [esi+xhci_controller.ContextSize-XCD]
|
||||
imul edx, ecx
|
||||
add eax, edx
|
||||
pop edx ecx
|
||||
ret
|
||||
endp
|
||||
|
||||
; Zeroes the Input Context. The caller must hold CmdLock.
|
||||
; in: esi -> usb_controller.
|
||||
proc xhci_clear_input_ctx
|
||||
push eax ecx edi
|
||||
mov edi, [esi+xhci_controller.InputCtx-XCD]
|
||||
xor eax, eax
|
||||
mov ecx, 33*64/4
|
||||
rep stosd
|
||||
pop edi ecx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Returns the pipe of the default control endpoint of the same device, which
|
||||
; represents the device as a whole.
|
||||
; in: ebx -> xhci_pipe. out: eax -> xhci_pipe or 0.
|
||||
proc xhci_ctrl_pipe
|
||||
mov eax, [ebx+xhci_pipe.DevPage]
|
||||
test eax, eax
|
||||
jz .nothing
|
||||
mov eax, [eax+XHCI_PIPES_OFS+1*4]
|
||||
test eax, eax
|
||||
jz .nothing
|
||||
sub eax, sizeof.xhci_pipe
|
||||
.nothing:
|
||||
ret
|
||||
endp
|
||||
|
||||
; Fills the Slot Context of the Input Context from the device description kept
|
||||
; in a pipe. The caller must hold CmdLock.
|
||||
; in: esi -> usb_controller, ebx -> xhci_pipe describing the device,
|
||||
; ecx = value for the Context Entries field.
|
||||
proc xhci_fill_slot_ctx
|
||||
push eax ecx edx edi
|
||||
mov eax, [esi+xhci_controller.InputCtx-XCD]
|
||||
push ecx
|
||||
movi ecx, 1
|
||||
call xhci_context
|
||||
pop ecx
|
||||
mov edi, eax
|
||||
; dword 0: Route String, Speed and Context Entries.
|
||||
mov eax, [ebx+xhci_pipe.Route]
|
||||
and eax, 0FFFFFh
|
||||
if XHCI_SUPERSPEED
|
||||
; A SuperSpeed root-port device carries the raw PORTSC speed identifier;
|
||||
; its kernel-visible Speed pretends high-speed and must not get here.
|
||||
mov edx, [ebx+xhci_pipe.PSIV]
|
||||
test edx, edx
|
||||
jnz .havespeed
|
||||
end if
|
||||
mov edx, [ebx+xhci_pipe.Speed]
|
||||
cmp edx, USB_SPEED_FS
|
||||
jz .fs
|
||||
cmp edx, USB_SPEED_LS
|
||||
jz .ls
|
||||
movi edx, XHCI_PSI_HS
|
||||
jmp .havespeed
|
||||
.fs:
|
||||
movi edx, XHCI_PSI_FS
|
||||
jmp .havespeed
|
||||
.ls:
|
||||
movi edx, XHCI_PSI_LS
|
||||
.havespeed:
|
||||
shl edx, 20
|
||||
or eax, edx
|
||||
shl ecx, 27
|
||||
or eax, ecx
|
||||
mov [edi], eax
|
||||
; dword 1: Root Hub Port Number.
|
||||
mov eax, [ebx+xhci_pipe.RootPort]
|
||||
shl eax, 16
|
||||
mov [edi+4], eax
|
||||
; dword 2: the Transaction Translator, if the device is served by one.
|
||||
mov eax, [ebx+xhci_pipe.TTSlot]
|
||||
test eax, eax
|
||||
jz @f
|
||||
mov edx, [ebx+xhci_pipe.TTPort]
|
||||
shl edx, 8
|
||||
or eax, edx
|
||||
@@:
|
||||
mov [edi+8], eax
|
||||
and dword [edi+12], 0
|
||||
pop edi edx ecx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Fills the Endpoint Context of the Input Context for the given pipe.
|
||||
; The caller must hold CmdLock.
|
||||
; in: esi -> usb_controller, ebx -> xhci_pipe.
|
||||
proc xhci_fill_ep_ctx
|
||||
push eax ecx edx edi
|
||||
mov eax, [esi+xhci_controller.InputCtx-XCD]
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
inc ecx
|
||||
call xhci_context
|
||||
mov edi, eax
|
||||
; dword 0: Interval.
|
||||
mov eax, [ebx+xhci_pipe.Interval]
|
||||
shl eax, 16
|
||||
mov [edi], eax
|
||||
; dword 1: Error Count, Endpoint Type, Max Burst Size and Max Packet Size.
|
||||
mov eax, [ebx+xhci_pipe.EpType]
|
||||
shl eax, 3
|
||||
or eax, 3 shl 1 ; three retries before giving up
|
||||
mov edx, [ebx+xhci_pipe.MaxPacket]
|
||||
mov ecx, edx
|
||||
shr ecx, 11
|
||||
and ecx, 3 ; extra transactions per microframe
|
||||
shl ecx, 8
|
||||
or eax, ecx
|
||||
if XHCI_SUPERSPEED
|
||||
; A SuperSpeed bulk endpoint may allow bursts of several packets; the field
|
||||
; shares its bits with the extra-transactions ones, which are zero then.
|
||||
mov ecx, [ebx+xhci_pipe.MaxBurst]
|
||||
shl ecx, 8
|
||||
or eax, ecx
|
||||
end if
|
||||
and edx, 7FFh
|
||||
shl edx, 16
|
||||
or eax, edx
|
||||
mov [edi+4], eax
|
||||
; dwords 2 and 3: the TR Dequeue Pointer with the Dequeue Cycle State.
|
||||
mov eax, [ebx+xhci_pipe.Enqueue]
|
||||
shl eax, 4
|
||||
add eax, [ebx+xhci_pipe.RingPhys]
|
||||
or eax, [ebx+xhci_pipe.Cycle]
|
||||
mov [edi+8], eax
|
||||
and dword [edi+12], 0
|
||||
; dword 4: Average TRB Length, only a hint for the bandwidth scheduler.
|
||||
mov eax, [ebx+xhci_pipe.MaxPacket]
|
||||
and eax, 7FFh
|
||||
cmp [ebx+xhci_pipe.EpType], XHCI_EP_CONTROL
|
||||
jnz @f
|
||||
movi eax, 8
|
||||
@@:
|
||||
mov [edi+16], eax
|
||||
and dword [edi+20], 0
|
||||
pop edi edx ecx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; =============================================================================
|
||||
; ============================== Slot commands ================================
|
||||
; =============================================================================
|
||||
|
||||
; Issues the Address Device command for a newly created default control pipe.
|
||||
; in: esi -> usb_controller, ebx -> xhci_pipe. out: eax = 0 on failure.
|
||||
proc xhci_address_device
|
||||
push ebx ecx edx edi
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexLock
|
||||
call xhci_clear_input_ctx
|
||||
mov edx, [esi+xhci_controller.InputCtx-XCD]
|
||||
mov dword [edx+4], 3 ; add the Slot Context and endpoint zero
|
||||
movi ecx, 1
|
||||
call xhci_fill_slot_ctx
|
||||
call xhci_fill_ep_ctx
|
||||
mov [ebx+xhci_pipe.MaxDCI], 1
|
||||
; Point the DCBAA entry of the slot at the Device Context.
|
||||
mov eax, [esi+xhci_controller.CommonPage-XCD]
|
||||
mov ecx, [ebx+xhci_pipe.SlotId]
|
||||
mov edx, [ebx+xhci_pipe.DevPagePhys]
|
||||
mov [eax+ecx*8], edx
|
||||
and dword [eax+ecx*8+4], 0
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, XHCI_TRB_ADDRESS_DEV shl 10
|
||||
mov eax, [esi+xhci_controller.InputCtxPhys-XCD]
|
||||
push ebx
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_submit
|
||||
pop ebx
|
||||
push eax
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexUnlock
|
||||
pop eax
|
||||
cmp eax, XHCI_CC_SUCCESS
|
||||
jz .ok
|
||||
DEBUGF 1,'K : XHCI: Address Device failed, code %d\n',eax
|
||||
xor eax, eax
|
||||
jmp .nothing
|
||||
.ok:
|
||||
movi eax, 1
|
||||
.nothing:
|
||||
pop edi edx ecx ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
; Issues a Configure Endpoint command that adds the given endpoint.
|
||||
; in: esi -> usb_controller, ebx -> xhci_pipe of the endpoint,
|
||||
; edi -> xhci_pipe of the default control endpoint of the same device.
|
||||
; out: eax = completion code.
|
||||
proc xhci_configure_endpoint
|
||||
push ebx ecx edx esi edi
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexLock
|
||||
call xhci_clear_input_ctx
|
||||
; Drop the endpoint and add it again, so that reopening an endpoint that has
|
||||
; been closed before also works.
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
movi eax, 1
|
||||
shl eax, cl
|
||||
mov edx, [esi+xhci_controller.InputCtx-XCD]
|
||||
mov [edx], eax
|
||||
or eax, 1 ; the Slot Context is always added
|
||||
mov [edx+4], eax
|
||||
call xhci_fill_ep_ctx
|
||||
; The Context Entries field must cover every endpoint in use by the device.
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
cmp ecx, [edi+xhci_pipe.MaxDCI]
|
||||
jae @f
|
||||
mov ecx, [edi+xhci_pipe.MaxDCI]
|
||||
@@:
|
||||
mov [edi+xhci_pipe.MaxDCI], ecx
|
||||
push ebx
|
||||
mov ebx, edi
|
||||
call xhci_fill_slot_ctx
|
||||
pop ebx
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, XHCI_TRB_CONFIG_EP shl 10
|
||||
mov eax, [esi+xhci_controller.InputCtxPhys-XCD]
|
||||
push ebx
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_submit
|
||||
pop ebx
|
||||
push eax
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexUnlock
|
||||
pop eax
|
||||
pop edi esi edx ecx ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
; Tells the controller where the endpoint has to continue from.
|
||||
; in: esi -> usb_controller, ebx -> xhci_pipe.
|
||||
proc xhci_set_dequeue
|
||||
pushad
|
||||
cmp [ebx+xhci_pipe.SlotId], 0
|
||||
jz .nothing
|
||||
mov eax, [ebx+xhci_pipe.Dequeue]
|
||||
shl eax, 4
|
||||
add eax, [ebx+xhci_pipe.RingPhys]
|
||||
or eax, [ebx+xhci_pipe.Cycle]
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
shl ecx, 16
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, ecx
|
||||
or edx, XHCI_TRB_SET_DEQ shl 10
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_sync
|
||||
cmp eax, XHCI_CC_SUCCESS
|
||||
jz .nothing
|
||||
DEBUGF 1,'K : XHCI: Set TR Dequeue Pointer failed, code %d\n',eax
|
||||
.nothing:
|
||||
popad
|
||||
ret
|
||||
endp
|
||||
|
||||
; =============================================================================
|
||||
; =============================== New device ==================================
|
||||
; =============================================================================
|
||||
|
||||
; Called from xhci_port_init and from the hub support code when a new device
|
||||
; has been connected and reset. Enables a device slot for it and hands it over
|
||||
; to the protocol layer.
|
||||
; in: esi -> usb_controller, eax = speed. out: eax = 0 on failure.
|
||||
proc xhci_new_device
|
||||
push ebx ecx edx edi
|
||||
mov [esi+usb_controller.ResettingSpeed], al
|
||||
; 1. Reserve room for the pseudo-pipe that describes the new device. Only the
|
||||
; fields read by xhci_init_pipe are filled in; the layout matches a real pipe,
|
||||
; so the result can be passed to usb_new_device as a usb_pipe pointer.
|
||||
sub esp, sizeof.xhci_pipe + 4
|
||||
mov ebx, esp
|
||||
push ebx
|
||||
mov edi, ebx
|
||||
xor eax, eax
|
||||
mov ecx, (sizeof.xhci_pipe + 4)/4
|
||||
rep stosd
|
||||
pop ebx
|
||||
mov [ebx+sizeof.xhci_pipe], esi ; usb_pipe.Controller
|
||||
movzx eax, [esi+usb_controller.ResettingSpeed]
|
||||
mov [ebx+xhci_pipe.Speed], eax
|
||||
; 2. Compute the root hub port, the route string and the tier of the device.
|
||||
movzx edx, [esi+usb_controller.ResettingPort]
|
||||
mov edi, [esi+usb_controller.ResettingHub]
|
||||
test edi, edi
|
||||
jnz .behind_hub
|
||||
mov eax, [esi+xhci_controller.PortMap-XCD+edx*4]
|
||||
mov [ebx+xhci_pipe.RootPort], eax
|
||||
if XHCI_SUPERSPEED
|
||||
mov eax, [esi+xhci_controller.ResettingPSIV-XCD]
|
||||
mov [ebx+xhci_pipe.PSIV], eax
|
||||
end if
|
||||
jmp .have_topology
|
||||
.behind_hub:
|
||||
; The parent hub is a device too, and its own pipe carries the topology data.
|
||||
mov eax, [edi+USB_HUB_CONFIGPIPE]
|
||||
sub eax, sizeof.xhci_pipe
|
||||
mov ecx, [eax+xhci_pipe.RootPort]
|
||||
mov [ebx+xhci_pipe.RootPort], ecx
|
||||
mov ecx, [eax+xhci_pipe.Depth]
|
||||
mov eax, [eax+xhci_pipe.Route]
|
||||
; The route string holds one nibble per tier, at most five of them.
|
||||
cmp ecx, 5
|
||||
jae .have_route
|
||||
push ecx edx
|
||||
shl ecx, 2
|
||||
inc edx ; the route uses 1-based port numbers
|
||||
cmp edx, 15
|
||||
jbe @f
|
||||
movi edx, 15
|
||||
@@:
|
||||
shl edx, cl
|
||||
or eax, edx
|
||||
pop edx ecx
|
||||
.have_route:
|
||||
inc ecx
|
||||
mov [ebx+xhci_pipe.Depth], ecx
|
||||
mov [ebx+xhci_pipe.Route], eax
|
||||
; 3. Low- and full-speed devices behind a high-speed hub need the address of
|
||||
; the Transaction Translator that serves them.
|
||||
cmp [ebx+xhci_pipe.Speed], USB_SPEED_HS
|
||||
jz .have_topology
|
||||
push ebx
|
||||
mov ecx, edx
|
||||
mov edx, edi
|
||||
invoke usbhc_api.usb_get_tt
|
||||
pop ebx
|
||||
test edx, edx
|
||||
jz .have_topology
|
||||
sub edx, sizeof.xhci_pipe
|
||||
mov eax, [edx+xhci_pipe.SlotId]
|
||||
mov [ebx+xhci_pipe.TTSlot], eax
|
||||
inc ecx
|
||||
mov [ebx+xhci_pipe.TTPort], ecx
|
||||
.have_topology:
|
||||
; 4. Ask the controller for a device slot.
|
||||
xor eax, eax
|
||||
push ebx
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
mov edx, XHCI_TRB_ENABLE_SLOT shl 10
|
||||
call xhci_cmd_sync
|
||||
pop ebx
|
||||
cmp eax, XHCI_CC_SUCCESS
|
||||
jnz .fail
|
||||
test edx, edx
|
||||
jz .fail
|
||||
mov [ebx+xhci_pipe.SlotId], edx
|
||||
DEBUGF 1,'K : XHCI new device: slot %d, root port %d, route %x, speed %d\n',edx,[ebx+xhci_pipe.RootPort],[ebx+xhci_pipe.Route],[ebx+xhci_pipe.Speed]
|
||||
; 5. Hand the device over to the protocol layer. It opens the pipe of the
|
||||
; default control endpoint, and that is where the slot is really addressed.
|
||||
lea ecx, [ebx+sizeof.xhci_pipe]
|
||||
invoke usbhc_api.usb_new_device
|
||||
test eax, eax
|
||||
jnz .done
|
||||
; 6. The protocol layer has failed; release the slot again.
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, XHCI_TRB_DISABLE_SLOT shl 10
|
||||
xor eax, eax
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_sync
|
||||
xor eax, eax
|
||||
jmp .done
|
||||
.fail:
|
||||
dbgstr 'XHCI: Enable Slot failed'
|
||||
xor eax, eax
|
||||
.done:
|
||||
add esp, sizeof.xhci_pipe + 4
|
||||
pop edi edx ecx ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
; =============================================================================
|
||||
; ================================= Pipes =====================================
|
||||
; =============================================================================
|
||||
|
||||
proc xhci_alloc_pipe
|
||||
push ebx ecx edi
|
||||
mov ebx, xhci_ep_mutex
|
||||
invoke usbhc_api.usb_allocate_common, sizeof.xhci_pipe + sizeof.usb_pipe
|
||||
test eax, eax
|
||||
jz @f
|
||||
; Zero the whole block: the kernel may call FreePipe for a pipe whose InitPipe
|
||||
; has never run, and that path must not act on garbage.
|
||||
mov edi, eax
|
||||
push eax
|
||||
xor eax, eax
|
||||
movi ecx, (sizeof.xhci_pipe + sizeof.usb_pipe + 3)/4
|
||||
rep stosd
|
||||
pop eax
|
||||
add eax, sizeof.xhci_pipe
|
||||
@@:
|
||||
pop edi ecx ebx
|
||||
ret
|
||||
endp
|
||||
|
||||
proc xhci_free_pipe stdcall, ptr:dword
|
||||
push ebx esi edi
|
||||
mov ebx, [ptr]
|
||||
sub ebx, sizeof.xhci_pipe
|
||||
mov esi, [ebx+sizeof.xhci_pipe+usb_pipe.Controller]
|
||||
test esi, esi
|
||||
jz .free
|
||||
cmp [ebx+xhci_pipe.SlotId], 0
|
||||
jz .drop_pipe
|
||||
cmp [ebx+xhci_pipe.DCI], 1
|
||||
jnz .drop_pipe
|
||||
; This is the default control endpoint, that is, the handle of the whole
|
||||
; device: release the slot together with the per-device page.
|
||||
mov ecx, [ebx+xhci_pipe.SlotId]
|
||||
mov edx, ecx
|
||||
shl edx, 24
|
||||
or edx, XHCI_TRB_DISABLE_SLOT shl 10
|
||||
xor eax, eax
|
||||
push ebx
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_sync
|
||||
pop ebx
|
||||
; The controller may access the Device Context until the command above
|
||||
; completes, so only now may the DCBAA entry and the slot table forget it.
|
||||
mov ecx, [ebx+xhci_pipe.SlotId]
|
||||
mov edi, [esi+xhci_controller.CommonPage-XCD]
|
||||
and dword [edi+ecx*8], 0
|
||||
and dword [edi+ecx*8+4], 0
|
||||
and [esi+xhci_controller.SlotPages-XCD+ecx*4], 0
|
||||
mov eax, [ebx+xhci_pipe.DevPage]
|
||||
test eax, eax
|
||||
jz .drop_ring
|
||||
invoke KernelFree, eax
|
||||
and [ebx+xhci_pipe.DevPage], 0
|
||||
jmp .drop_ring
|
||||
.drop_pipe:
|
||||
; Remove the pipe from the per-device table, if it is still listed there.
|
||||
; On disconnect the kernel releases the pipes of a device in arbitrary order,
|
||||
; and the pipe of the default control endpoint - the owner of the per-device
|
||||
; page - may well be freed before this one, taking the page with it. The
|
||||
; authoritative pointer is the one in SlotPages: it is cleared when the slot
|
||||
; is released, so it can never point to freed memory.
|
||||
mov ecx, [ebx+xhci_pipe.SlotId]
|
||||
test ecx, ecx
|
||||
jz .drop_ring
|
||||
mov eax, [esi+xhci_controller.SlotPages-XCD+ecx*4]
|
||||
test eax, eax
|
||||
jz .drop_ring
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
cmp ecx, 32
|
||||
jae .drop_ring
|
||||
and dword [eax+XHCI_PIPES_OFS+ecx*4], 0
|
||||
.drop_ring:
|
||||
mov eax, [ebx+xhci_pipe.Ring]
|
||||
test eax, eax
|
||||
jz @f
|
||||
invoke KernelFree, eax
|
||||
and [ebx+xhci_pipe.Ring], 0
|
||||
@@:
|
||||
mov eax, [ebx+xhci_pipe.RingMap]
|
||||
test eax, eax
|
||||
jz .free
|
||||
invoke KernelFree, eax
|
||||
and [ebx+xhci_pipe.RingMap], 0
|
||||
.free:
|
||||
pop edi esi ebx
|
||||
mov eax, [ptr]
|
||||
sub eax, sizeof.xhci_pipe
|
||||
invoke usbhc_api.usb_free_common, eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Allocates the transfer ring of a pipe.
|
||||
; in: ebx -> xhci_pipe. out: eax = 0 on failure.
|
||||
proc xhci_alloc_ring
|
||||
push ecx edx
|
||||
call xhci_alloc_page
|
||||
test eax, eax
|
||||
jz .nothing
|
||||
mov [ebx+xhci_pipe.RingMap], eax
|
||||
call xhci_alloc_page
|
||||
test eax, eax
|
||||
jnz @f
|
||||
invoke KernelFree, [ebx+xhci_pipe.RingMap]
|
||||
and [ebx+xhci_pipe.RingMap], 0
|
||||
xor eax, eax
|
||||
jmp .nothing
|
||||
@@:
|
||||
mov [ebx+xhci_pipe.Ring], eax
|
||||
mov [ebx+xhci_pipe.RingPhys], edx
|
||||
; The last entry returns to the beginning of the ring and toggles the cycle.
|
||||
lea ecx, [eax+(XHCI_RING_TRBS-1)*16]
|
||||
mov [ecx], edx
|
||||
mov dword [ecx+12], (XHCI_TRB_LINK shl 10) + XHCI_TRB_TC
|
||||
and [ebx+xhci_pipe.Enqueue], 0
|
||||
and [ebx+xhci_pipe.Dequeue], 0
|
||||
and [ebx+xhci_pipe.Reserved], 0
|
||||
and [ebx+xhci_pipe.FirstFix], 0
|
||||
mov [ebx+xhci_pipe.Cycle], XHCI_TRB_C
|
||||
movi eax, 1
|
||||
.nothing:
|
||||
pop edx ecx
|
||||
ret
|
||||
endp
|
||||
|
||||
; Stores the pipe in the per-device table used by the event ring handler.
|
||||
; in: ebx -> xhci_pipe.
|
||||
proc xhci_register_pipe
|
||||
push eax ecx edx
|
||||
mov eax, [ebx+xhci_pipe.DevPage]
|
||||
test eax, eax
|
||||
jz @f
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
cmp ecx, 32
|
||||
jae @f
|
||||
lea edx, [ebx+sizeof.xhci_pipe]
|
||||
mov [eax+XHCI_PIPES_OFS+ecx*4], edx
|
||||
@@:
|
||||
pop edx ecx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Computes the Interval field of the Endpoint Context of an interrupt endpoint.
|
||||
; The kernel passes bInterval from the endpoint descriptor: for high-speed
|
||||
; devices it is an exponent of 125 us periods, for low- and full-speed devices
|
||||
; it is a number of frames.
|
||||
; in: ebx -> xhci_pipe, eax = bInterval.
|
||||
proc xhci_calc_interval
|
||||
push eax ecx
|
||||
cmp [ebx+xhci_pipe.Speed], USB_SPEED_HS
|
||||
jnz .low_speed
|
||||
test eax, eax
|
||||
jz @f
|
||||
dec eax
|
||||
@@:
|
||||
jmp .clamp
|
||||
.low_speed:
|
||||
; One frame equals eight periods of 125 us, hence the offset of three.
|
||||
test eax, eax
|
||||
jnz @f
|
||||
movi eax, 1
|
||||
@@:
|
||||
bsr ecx, eax
|
||||
lea eax, [ecx+3]
|
||||
.clamp:
|
||||
cmp eax, 15
|
||||
jbe @f
|
||||
movi eax, 15
|
||||
@@:
|
||||
mov [ebx+xhci_pipe.Interval], eax
|
||||
pop ecx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Called from usb_open_pipe.
|
||||
; in: edi -> usb_pipe for the target, ecx -> usb_pipe of the config pipe,
|
||||
; esi -> usb_controller, eax -> usb_gtd of the first descriptor,
|
||||
; [ebp+12] = endpoint, [ebp+16] = maxpacket, [ebp+20] = type,
|
||||
; [ebp+24] = interval.
|
||||
; out: eax = 0 on failure.
|
||||
proc xhci_init_pipe
|
||||
virtual at ebp+8
|
||||
.config_pipe dd ?
|
||||
.endpoint dd ?
|
||||
.maxpacket dd ?
|
||||
.type dd ?
|
||||
.interval dd ?
|
||||
end virtual
|
||||
push ebx
|
||||
sub edi, sizeof.xhci_pipe
|
||||
sub ecx, sizeof.xhci_pipe
|
||||
mov ebx, edi ; ebx -> xhci_pipe being initialized
|
||||
; 1. Copy the description of the device from the config pipe.
|
||||
mov eax, [ecx+xhci_pipe.SlotId]
|
||||
mov [ebx+xhci_pipe.SlotId], eax
|
||||
mov eax, [ecx+xhci_pipe.DevPage]
|
||||
mov [ebx+xhci_pipe.DevPage], eax
|
||||
mov eax, [ecx+xhci_pipe.DevPagePhys]
|
||||
mov [ebx+xhci_pipe.DevPagePhys], eax
|
||||
mov eax, [ecx+xhci_pipe.Speed]
|
||||
mov [ebx+xhci_pipe.Speed], eax
|
||||
mov eax, [ecx+xhci_pipe.RootPort]
|
||||
mov [ebx+xhci_pipe.RootPort], eax
|
||||
mov eax, [ecx+xhci_pipe.Route]
|
||||
mov [ebx+xhci_pipe.Route], eax
|
||||
mov eax, [ecx+xhci_pipe.Depth]
|
||||
mov [ebx+xhci_pipe.Depth], eax
|
||||
mov eax, [ecx+xhci_pipe.TTSlot]
|
||||
mov [ebx+xhci_pipe.TTSlot], eax
|
||||
mov eax, [ecx+xhci_pipe.TTPort]
|
||||
mov [ebx+xhci_pipe.TTPort], eax
|
||||
if XHCI_SUPERSPEED
|
||||
mov eax, [ecx+xhci_pipe.PSIV]
|
||||
mov [ebx+xhci_pipe.PSIV], eax
|
||||
end if
|
||||
; 2. Work out the Device Context Index and the endpoint type.
|
||||
mov eax, [.endpoint]
|
||||
test eax, eax
|
||||
jz .control_ep
|
||||
mov ecx, eax
|
||||
and ecx, 15
|
||||
add ecx, ecx
|
||||
test al, 80h
|
||||
jz @f
|
||||
inc ecx
|
||||
or [ebx+xhci_pipe.Flags], XHCI_PIPE_IN
|
||||
@@:
|
||||
mov [ebx+xhci_pipe.DCI], ecx
|
||||
mov eax, [.type]
|
||||
cmp eax, BULK_PIPE
|
||||
jz .bulk
|
||||
cmp eax, INTERRUPT_PIPE
|
||||
jz .interrupt
|
||||
; A control endpoint other than endpoint zero is unusual but legal.
|
||||
mov [ebx+xhci_pipe.EpType], XHCI_EP_CONTROL
|
||||
jmp .have_type
|
||||
.bulk:
|
||||
movi eax, XHCI_EP_BULK_OUT
|
||||
test [ebx+xhci_pipe.Flags], XHCI_PIPE_IN
|
||||
jz @f
|
||||
movi eax, XHCI_EP_BULK_IN
|
||||
@@:
|
||||
mov [ebx+xhci_pipe.EpType], eax
|
||||
jmp .have_type
|
||||
.interrupt:
|
||||
movi eax, XHCI_EP_INT_OUT
|
||||
test [ebx+xhci_pipe.Flags], XHCI_PIPE_IN
|
||||
jz @f
|
||||
movi eax, XHCI_EP_INT_IN
|
||||
@@:
|
||||
mov [ebx+xhci_pipe.EpType], eax
|
||||
mov eax, [.interval]
|
||||
call xhci_calc_interval
|
||||
.have_type:
|
||||
mov eax, [.maxpacket]
|
||||
mov [ebx+xhci_pipe.MaxPacket], eax
|
||||
if XHCI_SUPERSPEED
|
||||
call xhci_ss_get_burst
|
||||
end if
|
||||
jmp .alloc_ring
|
||||
.control_ep:
|
||||
; The default control endpoint always has index one. Until the real packet size
|
||||
; is known from the device descriptor, use the value the specification requires
|
||||
; for the speed of the device: the kernel asks for 64 regardless of the speed,
|
||||
; which is wrong for low- and full-speed devices.
|
||||
mov [ebx+xhci_pipe.DCI], 1
|
||||
mov [ebx+xhci_pipe.EpType], XHCI_EP_CONTROL
|
||||
movi eax, 64
|
||||
cmp [ebx+xhci_pipe.Speed], USB_SPEED_HS
|
||||
jz @f
|
||||
movi eax, 8
|
||||
@@:
|
||||
if XHCI_SUPERSPEED
|
||||
; A SuperSpeed device always uses 512 bytes on the default control endpoint.
|
||||
cmp [ebx+xhci_pipe.PSIV], XHCI_PSI_SS
|
||||
jb @f
|
||||
mov eax, 512
|
||||
@@:
|
||||
end if
|
||||
mov [ebx+xhci_pipe.MaxPacket], eax
|
||||
.alloc_ring:
|
||||
; 3. Allocate the transfer ring.
|
||||
call xhci_alloc_ring
|
||||
test eax, eax
|
||||
jz .fail
|
||||
; 4. Choose the software list the pipe belongs to and insert it there. The
|
||||
; hardware knows nothing about these lists; they exist only so that the kernel
|
||||
; can walk all pipes and reinsert an aborted one.
|
||||
lea edx, [esi+xhci_controller.ControlED-XCD]
|
||||
cmp [.type], BULK_PIPE
|
||||
jb @f
|
||||
lea edx, [esi+xhci_controller.BulkED-XCD]
|
||||
jz @f
|
||||
lea edx, [esi+xhci_controller.IntED-XCD]
|
||||
@@:
|
||||
lea edi, [ebx+sizeof.xhci_pipe]
|
||||
mov [edi+usb_pipe.BaseList], edx
|
||||
mov ecx, [edx+usb_pipe.NextVirt]
|
||||
mov [edi+usb_pipe.NextVirt], ecx
|
||||
mov [edi+usb_pipe.PrevVirt], edx
|
||||
mov [ecx+usb_pipe.PrevVirt], edi
|
||||
mov [edx+usb_pipe.NextVirt], edi
|
||||
; 5. Now do the hardware part.
|
||||
cmp [.endpoint], 0
|
||||
jz .address_device
|
||||
call xhci_register_pipe
|
||||
mov edi, [.config_pipe]
|
||||
sub edi, sizeof.xhci_pipe
|
||||
call xhci_configure_endpoint
|
||||
xhci_trace 'K : XHCI open pipe: slot %d dci %d\n', [ebx+xhci_pipe.SlotId], [ebx+xhci_pipe.DCI]
|
||||
cmp eax, XHCI_CC_SUCCESS
|
||||
jz .success
|
||||
DEBUGF 1,'K : XHCI: Configure Endpoint failed, code %d\n',eax
|
||||
jmp .unlink_fail
|
||||
.address_device:
|
||||
; 6. This is a new device: allocate its Device Context, publish the slot and
|
||||
; let the controller give the device a bus address.
|
||||
call xhci_alloc_page
|
||||
test eax, eax
|
||||
jz .unlink_fail
|
||||
mov [ebx+xhci_pipe.DevPage], eax
|
||||
mov [ebx+xhci_pipe.DevPagePhys], edx
|
||||
mov ecx, [ebx+xhci_pipe.SlotId]
|
||||
mov [esi+xhci_controller.SlotPages-XCD+ecx*4], eax
|
||||
call xhci_register_pipe
|
||||
call xhci_address_device
|
||||
test eax, eax
|
||||
jz .free_devpage
|
||||
.success:
|
||||
; usb_open_pipe keeps the pointer to the new pipe in edi across this call, so
|
||||
; it has to be handed back untouched; the branch above has overwritten it with
|
||||
; the pipe of the default control endpoint.
|
||||
lea edi, [ebx+sizeof.xhci_pipe]
|
||||
pop ebx
|
||||
movi eax, 1
|
||||
ret
|
||||
.free_devpage:
|
||||
mov ecx, [ebx+xhci_pipe.SlotId]
|
||||
and [esi+xhci_controller.SlotPages-XCD+ecx*4], 0
|
||||
mov eax, [ebx+xhci_pipe.DevPage]
|
||||
invoke KernelFree, eax
|
||||
and [ebx+xhci_pipe.DevPage], 0
|
||||
.unlink_fail:
|
||||
; Undo the insertion into the software list before failing.
|
||||
lea edi, [ebx+sizeof.xhci_pipe]
|
||||
mov eax, [edi+usb_pipe.NextVirt]
|
||||
mov edx, [edi+usb_pipe.PrevVirt]
|
||||
mov [eax+usb_pipe.PrevVirt], edx
|
||||
mov [edx+usb_pipe.NextVirt], eax
|
||||
.fail:
|
||||
lea edi, [ebx+sizeof.xhci_pipe]
|
||||
pop ebx
|
||||
xor eax, eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; Removes the pipe from the hardware configuration of the device.
|
||||
; in: esi -> usb_controller, ebx -> usb_pipe.
|
||||
proc xhci_unlink_pipe
|
||||
pushad
|
||||
sub ebx, sizeof.xhci_pipe
|
||||
cmp [ebx+xhci_pipe.SlotId], 0
|
||||
jz .nothing
|
||||
cmp [ebx+xhci_pipe.DCI], 1
|
||||
jz .nothing ; the slot itself is released by FreePipe
|
||||
call xhci_ctrl_pipe
|
||||
test eax, eax
|
||||
jz .nothing
|
||||
mov edi, eax ; edi -> pipe of endpoint zero
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexLock
|
||||
call xhci_clear_input_ctx
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
movi eax, 1
|
||||
shl eax, cl
|
||||
mov edx, [esi+xhci_controller.InputCtx-XCD]
|
||||
mov [edx], eax ; drop this endpoint
|
||||
mov dword [edx+4], 1 ; keep the Slot Context
|
||||
mov ecx, [edi+xhci_pipe.MaxDCI]
|
||||
test ecx, ecx
|
||||
jnz @f
|
||||
movi ecx, 1
|
||||
@@:
|
||||
push ebx
|
||||
mov ebx, edi
|
||||
call xhci_fill_slot_ctx
|
||||
pop ebx
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, XHCI_TRB_CONFIG_EP shl 10
|
||||
mov eax, [esi+xhci_controller.InputCtxPhys-XCD]
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_submit
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexUnlock
|
||||
.nothing:
|
||||
popad
|
||||
ret
|
||||
endp
|
||||
|
||||
; Temporarily removes the pipe from the hardware schedule.
|
||||
; in: esi -> usb_controller, ebx -> usb_pipe.
|
||||
proc xhci_disable_pipe
|
||||
pushad
|
||||
sub ebx, sizeof.xhci_pipe
|
||||
cmp [ebx+xhci_pipe.SlotId], 0
|
||||
jz .nothing
|
||||
mov ecx, [ebx+xhci_pipe.DCI]
|
||||
shl ecx, 16
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, ecx
|
||||
or edx, XHCI_TRB_STOP_EP shl 10
|
||||
xor eax, eax
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_sync
|
||||
.nothing:
|
||||
popad
|
||||
ret
|
||||
endp
|
||||
|
||||
; Reinserts the pipe into the hardware schedule after xhci_disable_pipe, with
|
||||
; an empty transfer queue.
|
||||
; in: esi -> usb_controller, ebx -> usb_pipe,
|
||||
; edx -> current descriptor, eax -> new last descriptor.
|
||||
proc xhci_enable_pipe
|
||||
pushad
|
||||
sub ebx, sizeof.xhci_pipe
|
||||
mov eax, [ebx+xhci_pipe.Ring]
|
||||
test eax, eax
|
||||
jz .nothing
|
||||
; The queue is empty now, so the ring can be restarted from its beginning.
|
||||
mov edi, eax
|
||||
xor eax, eax
|
||||
mov ecx, 0x1000/4
|
||||
rep stosd
|
||||
mov edi, [ebx+xhci_pipe.RingMap]
|
||||
mov ecx, 0x1000/4
|
||||
rep stosd
|
||||
mov edi, [ebx+xhci_pipe.Ring]
|
||||
add edi, (XHCI_RING_TRBS-1)*16
|
||||
mov eax, [ebx+xhci_pipe.RingPhys]
|
||||
mov [edi], eax
|
||||
mov dword [edi+12], (XHCI_TRB_LINK shl 10) + XHCI_TRB_TC
|
||||
and [ebx+xhci_pipe.Enqueue], 0
|
||||
and [ebx+xhci_pipe.Dequeue], 0
|
||||
and [ebx+xhci_pipe.Reserved], 0
|
||||
and [ebx+xhci_pipe.FirstFix], 0
|
||||
mov [ebx+xhci_pipe.Cycle], XHCI_TRB_C
|
||||
call xhci_set_dequeue
|
||||
.nothing:
|
||||
popad
|
||||
ret
|
||||
endp
|
||||
|
||||
; =============================================================================
|
||||
; ========================== Address and packet size ==========================
|
||||
; =============================================================================
|
||||
|
||||
; Called from usb_set_address_callback. The bus address is chosen by the
|
||||
; controller itself while executing the Address Device command, so the only
|
||||
; thing left to do is to remember the number the kernel has reserved: it asks
|
||||
; for it back on disconnect in order to mark it free again.
|
||||
; in: esi -> usb_controller, ebx -> usb_pipe, cl = address.
|
||||
proc xhci_set_device_address
|
||||
movzx eax, cl
|
||||
mov [ebx+xhci_pipe.Address-sizeof.xhci_pipe], eax
|
||||
jmp [usbhc_api.usb_subscribe_control]
|
||||
endp
|
||||
|
||||
; in: esi -> usb_controller, ebx -> usb_pipe. out: eax = address.
|
||||
proc xhci_get_device_address
|
||||
mov eax, [ebx+xhci_pipe.Address-sizeof.xhci_pipe]
|
||||
ret
|
||||
endp
|
||||
|
||||
; Called from usb_get_descr8_callback once the real packet size of the default
|
||||
; control endpoint is known. On xHCI that value lives in the Endpoint Context,
|
||||
; so an Evaluate Context command is needed to update it.
|
||||
; in: esi -> usb_controller, ebx -> usb_pipe, ecx = packet size.
|
||||
proc xhci_set_endpoint_packet_size
|
||||
push ebx ecx edx edi
|
||||
sub ebx, sizeof.xhci_pipe
|
||||
if XHCI_SUPERSPEED
|
||||
; For a SuperSpeed device bMaxPacketSize0 is an exponent, and the only value
|
||||
; the specification allows is 9: use 512 directly instead of the raw byte.
|
||||
cmp [ebx+xhci_pipe.PSIV], XHCI_PSI_SS
|
||||
jb @f
|
||||
mov ecx, 512
|
||||
@@:
|
||||
end if
|
||||
mov [ebx+xhci_pipe.MaxPacket], ecx
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexLock
|
||||
call xhci_clear_input_ctx
|
||||
mov edx, [esi+xhci_controller.InputCtx-XCD]
|
||||
mov dword [edx+4], 2 ; evaluate the default control endpoint
|
||||
call xhci_fill_ep_ctx
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, XHCI_TRB_EVAL_CTX shl 10
|
||||
mov eax, [esi+xhci_controller.InputCtxPhys-XCD]
|
||||
push ebx
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_submit
|
||||
pop ebx
|
||||
cmp eax, XHCI_CC_SUCCESS
|
||||
jz @f
|
||||
DEBUGF 1,'K : XHCI: Evaluate Context failed, code %d\n',eax
|
||||
@@:
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexUnlock
|
||||
pop edi edx ecx ebx
|
||||
jmp [usbhc_api.usb_subscribe_control]
|
||||
endp
|
||||
|
||||
; If the descriptor that has just completed is the answer to a request for the
|
||||
; hub descriptor, tell the controller that the device is a hub: it has to know
|
||||
; that in order to serve the devices behind it.
|
||||
; in: ebx -> usb_gtd.
|
||||
proc xhci_check_hub_descriptor
|
||||
pushad
|
||||
cmp [ebx+usb_gtd.Callback], 0
|
||||
jz .nothing
|
||||
mov eax, [ebx+usb_gtd.Pipe]
|
||||
mov esi, [eax+usb_pipe.Controller]
|
||||
sub eax, sizeof.xhci_pipe
|
||||
test [eax+xhci_pipe.Flags], XHCI_PIPE_HUBPEND
|
||||
jz .nothing
|
||||
and [eax+xhci_pipe.Flags], not XHCI_PIPE_HUBPEND
|
||||
cmp [ebx+xhci_gtd.Status-sizeof.xhci_gtd], XHCI_CC_SUCCESS
|
||||
jnz .nothing
|
||||
mov edx, [eax+xhci_pipe.HubBuf]
|
||||
test edx, edx
|
||||
jz .nothing
|
||||
cmp byte [edx+1], 29h ; bDescriptorType
|
||||
jnz .nothing
|
||||
or [eax+xhci_pipe.Flags], XHCI_PIPE_ISHUB
|
||||
mov ebx, eax ; ebx -> xhci_pipe of the hub
|
||||
movzx edi, byte [edx+2] ; bNbrPorts
|
||||
movzx ebp, byte [edx+3] ; low byte of wHubCharacteristics
|
||||
shr ebp, 5
|
||||
and ebp, 3 ; Transaction Translator Think Time
|
||||
DEBUGF 1,'K : XHCI: device on slot %d is a hub with %d ports\n',[ebx+xhci_pipe.SlotId],edi
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexLock
|
||||
call xhci_clear_input_ctx
|
||||
mov eax, [esi+xhci_controller.InputCtx-XCD]
|
||||
mov dword [eax+4], 1 ; only the Slot Context is evaluated
|
||||
mov ecx, [ebx+xhci_pipe.MaxDCI]
|
||||
test ecx, ecx
|
||||
jnz @f
|
||||
movi ecx, 1
|
||||
@@:
|
||||
call xhci_fill_slot_ctx
|
||||
; Patch the Slot Context with the fields that describe a hub. Only Configure
|
||||
; Endpoint takes them into account, Evaluate Context would ignore them.
|
||||
mov eax, [esi+xhci_controller.InputCtx-XCD]
|
||||
movi ecx, 1
|
||||
call xhci_context
|
||||
or dword [eax], 1 shl 26 ; this device is a hub
|
||||
cmp [ebx+xhci_pipe.Speed], USB_SPEED_HS
|
||||
jnz @f
|
||||
shl ebp, 16
|
||||
or [eax+8], ebp
|
||||
@@:
|
||||
shl edi, 24
|
||||
or [eax+4], edi ; Number of Ports
|
||||
mov edx, [ebx+xhci_pipe.SlotId]
|
||||
shl edx, 24
|
||||
or edx, XHCI_TRB_CONFIG_EP shl 10
|
||||
mov eax, [esi+xhci_controller.InputCtxPhys-XCD]
|
||||
xor ebx, ebx
|
||||
xor ecx, ecx
|
||||
call xhci_cmd_submit
|
||||
cmp eax, XHCI_CC_SUCCESS
|
||||
jz @f
|
||||
DEBUGF 1,'K : XHCI: cannot mark the device as a hub, code %d\n',eax
|
||||
@@:
|
||||
lea ecx, [esi+xhci_controller.CmdLock-XCD]
|
||||
invoke MutexUnlock
|
||||
.nothing:
|
||||
popad
|
||||
ret
|
||||
endp
|
||||
@@ -0,0 +1,135 @@
|
||||
; SuperSpeed support for the xHCI driver, included from xhci.asm when
|
||||
; XHCI_SUPERSPEED is enabled. The pieces too small to live here - the port
|
||||
; map, the Slot Context speed, the 512-byte default control endpoint, the
|
||||
; Max Burst field of the Endpoint Context - sit in the other files under
|
||||
; "if XHCI_SUPERSPEED" guards; this file keeps the self-contained procedures.
|
||||
;
|
||||
; The kernel USB stack knows nothing about SuperSpeed, so it never learns
|
||||
; about it: a SuperSpeed device is announced as a high-speed one, which also
|
||||
; keeps the Transaction Translator logic away from it. The raw PORTSC speed
|
||||
; identifier travels in xhci_pipe.PSIV instead and reaches everything that
|
||||
; really needs it. SuperSpeed hubs are not supported: the kernel only speaks
|
||||
; the USB2 hub protocol, so a device behind a USB3 hub is served by the USB2
|
||||
; half of that hub at high speed.
|
||||
|
||||
; =============================================================================
|
||||
; ============================ SuperSpeed ports ===============================
|
||||
; =============================================================================
|
||||
|
||||
; Called from xhci_new_port for a SuperSpeed root port instead of the USB2
|
||||
; reset entry point: a SuperSpeed link trains itself and the port enables
|
||||
; itself on connect, reporting the speed with no reset at all. When the link
|
||||
; is already up, skip straight to the reset recovery stage, after which
|
||||
; xhci_port_init picks the device up; otherwise try a warm reset.
|
||||
; in: esi -> usb_controller, ecx = port index.
|
||||
proc xhci_ss_start_port
|
||||
push eax edx
|
||||
and [esi+usb_controller.ResettingHub], 0
|
||||
mov [esi+usb_controller.ResettingPort], cl
|
||||
push ecx
|
||||
invoke GetTimerTicks
|
||||
pop ecx
|
||||
mov [esi+usb_controller.ResetTime], eax
|
||||
mov [esi+xhci_controller.ResetStart-XCD], eax
|
||||
call xhci_port_reg
|
||||
mov eax, [edx]
|
||||
test al, XHCI_PORT_PED
|
||||
jz .warm_reset
|
||||
mov [esi+usb_controller.ResettingStatus], 2
|
||||
DEBUGF 1,'K : XHCI %x: SS port %d link is up, PORTSC=%x\n',esi,ecx,eax
|
||||
jmp .nothing
|
||||
.warm_reset:
|
||||
; Connected, but the link has not come up. The Port Reset bit is set while a
|
||||
; warm reset is running, so the ordinary reset-wait machinery in
|
||||
; xhci_port_reset_done serves this case unchanged; the extra WRC change bit is
|
||||
; acknowledged there together with the usual ones.
|
||||
mov dword [edx], XHCI_PORT_PP + XHCI_PORT_WPR
|
||||
mov [esi+usb_controller.ResettingStatus], 1
|
||||
DEBUGF 1,'K : XHCI %x: warm-resetting port %d, PORTSC=%x\n',esi,ecx,eax
|
||||
.nothing:
|
||||
pop edx eax
|
||||
ret
|
||||
endp
|
||||
|
||||
; The kernel restarts pending root ports through the NewPortReset entry of
|
||||
; usb_hardware_func directly, bypassing xhci_new_port; SuperSpeed ports must
|
||||
; not get the USB2 reset on that path either, so the entry points here.
|
||||
; in: esi -> usb_controller, ecx = port index.
|
||||
proc xhci_ss_port_reset
|
||||
bt [esi+xhci_controller.SSPortMask-XCD], ecx
|
||||
jnc xhci_new_port.reset
|
||||
call xhci_ss_start_port
|
||||
ret
|
||||
endp
|
||||
|
||||
; =============================================================================
|
||||
; ===================== Endpoint Companion descriptors ========================
|
||||
; =============================================================================
|
||||
|
||||
; Reads the SuperSpeed Endpoint Companion descriptor of a bulk endpoint and
|
||||
; keeps its bMaxBurst for the Endpoint Context, allowing bursts of up to
|
||||
; bMaxBurst+1 packets per transaction. Zero (no bursts) is always legal, so
|
||||
; any failure just leaves the field alone. Only bulk endpoints are considered:
|
||||
; a nonzero burst on a periodic endpoint would also require the Max ESIT
|
||||
; Payload fields, and real interrupt endpoints do not burst anyway.
|
||||
; Relies on the stack frame of usb_open_pipe exactly like xhci_init_pipe does:
|
||||
; [ebp+8] is the config pipe of the device.
|
||||
; in: ebx -> xhci_pipe of a non-control endpoint being opened.
|
||||
proc xhci_ss_get_burst
|
||||
push eax ecx edx edi
|
||||
; 1. Only SuperSpeed bulk endpoints are of interest.
|
||||
cmp [ebx+xhci_pipe.PSIV], XHCI_PSI_SS
|
||||
jb .nothing
|
||||
mov eax, [ebx+xhci_pipe.EpType]
|
||||
and al, 3
|
||||
cmp al, 2 ; bulk endpoint types are 2 and 6
|
||||
jnz .nothing
|
||||
; 2. Find the configuration data kept by the kernel behind the device
|
||||
; descriptor; it holds the endpoint descriptors with their companions.
|
||||
mov eax, [ebp+8]
|
||||
mov eax, [eax+usb_pipe.DeviceData]
|
||||
test eax, eax
|
||||
jz .nothing
|
||||
movzx edx, [eax+usb_device_data.DeviceDescrSize]
|
||||
mov edi, [eax+usb_device_data.ConfigDataSize]
|
||||
lea ecx, [eax+edx+usb_device_data.DeviceDescriptor]
|
||||
add edi, ecx ; edi -> end of the configuration data
|
||||
; 3. Reconstruct bEndpointAddress from the Device Context Index.
|
||||
mov edx, [ebx+xhci_pipe.DCI]
|
||||
shr edx, 1
|
||||
test [ebx+xhci_pipe.Flags], XHCI_PIPE_IN
|
||||
jz @f
|
||||
or dl, 80h
|
||||
@@:
|
||||
; 4. Walk the descriptors to the one of this endpoint.
|
||||
.walk:
|
||||
lea eax, [ecx+2]
|
||||
cmp eax, edi
|
||||
ja .nothing
|
||||
movzx eax, byte [ecx] ; bLength
|
||||
test eax, eax
|
||||
jz .nothing ; malformed data, stop
|
||||
cmp byte [ecx+1], 5 ; an endpoint descriptor?
|
||||
jnz .advance
|
||||
cmp [ecx+2], dl ; bEndpointAddress
|
||||
jnz .advance
|
||||
; 5. The companion descriptor (type 30h) immediately follows its endpoint.
|
||||
add ecx, eax
|
||||
lea eax, [ecx+3]
|
||||
cmp eax, edi
|
||||
ja .nothing
|
||||
cmp byte [ecx+1], 30h ; SuperSpeed Endpoint Companion
|
||||
jnz .nothing
|
||||
movzx eax, byte [ecx+2] ; bMaxBurst
|
||||
cmp eax, 15
|
||||
ja .nothing
|
||||
mov [ebx+xhci_pipe.MaxBurst], eax
|
||||
DEBUGF 1,'K : XHCI: slot %d dci %d bursts %d+1 packets\n',[ebx+xhci_pipe.SlotId],[ebx+xhci_pipe.DCI],eax
|
||||
jmp .nothing
|
||||
.advance:
|
||||
add ecx, eax
|
||||
jmp .walk
|
||||
.nothing:
|
||||
pop edi edx ecx eax
|
||||
ret
|
||||
endp
|
||||
File diff suppressed because it is too large.
Load diff
+1767
-190
File diff suppressed because it is too large.
Load diff
@@ -842,8 +842,7 @@ disk_scan_partitions:
|
||||
cmp ebx, mbr_buffer
|
||||
jz .release_partition_buffer
|
||||
; 15b. If we have allocated it, free it.
|
||||
xchg eax, ebx
|
||||
call free
|
||||
stdcall kernel_free, ebx
|
||||
jmp .nothing
|
||||
; 15c. Otherwise, release reference.
|
||||
.release_partition_buffer:
|
||||
@@ -1489,19 +1488,31 @@ dyndisk_handler:
|
||||
; 12. The fs operation has specified some partition.
|
||||
push edx ecx
|
||||
xor eax, eax
|
||||
mov ecx, eax
|
||||
lodsb
|
||||
@@:
|
||||
lea ecx, [ecx*4 + ecx]
|
||||
shl ecx, 1
|
||||
|
||||
sub eax, '0'
|
||||
jz .dyndisk_cleanup
|
||||
jb .dyndisk_cleanup
|
||||
cmp eax, 10
|
||||
jnc .dyndisk_cleanup
|
||||
mov ecx, eax
|
||||
|
||||
add ecx, eax
|
||||
cmp ecx, MAX_NUM_PARTITIONS
|
||||
ja .dyndisk_cleanup
|
||||
|
||||
lodsb
|
||||
cmp eax, '/'
|
||||
jz @f
|
||||
test eax, eax
|
||||
jnz .dyndisk_cleanup
|
||||
jnz @b
|
||||
dec esi
|
||||
@@:
|
||||
test ecx, ecx
|
||||
jz .dyndisk_cleanup
|
||||
|
||||
cmp byte [esi], 0
|
||||
jnz @f
|
||||
; partition info
|
||||
|
||||
@@ -183,6 +183,8 @@ EFLAGS_ID = 0x200000 ; id flag
|
||||
IRQ_PIC = 0
|
||||
IRQ_APIC = 1
|
||||
|
||||
IO_MAP_SIZE = 65536/8 ; 8192 or 2 PAGE_SIZE
|
||||
|
||||
struct TSS
|
||||
_back rw 2
|
||||
_esp0 rd 1
|
||||
@@ -290,6 +292,9 @@ sys_proc = OS_BASE + 0x008E000
|
||||
|
||||
SLOT_BASE = OS_BASE + 0x0090000
|
||||
|
||||
APPDATA_IDLE_THREAD = SLOT_BASE + sizeof.APPDATA*1 ; poiner to IDLE thread
|
||||
APPDATA_OS_THREAD = SLOT_BASE + sizeof.APPDATA*2 ; poiner to OS thread
|
||||
|
||||
VGABasePtr = OS_BASE + 0x00A0000
|
||||
|
||||
virtual at OS_BASE + 0x05FFF80
|
||||
@@ -570,7 +575,7 @@ struct APPDATA
|
||||
ipc_start dd ? ;+160
|
||||
ipc_size dd ? ;+164
|
||||
occurred_events dd ? ;+168 ; mask which accumulates occurred events
|
||||
debugger_slot dd ? ;+172 ; index in SLOT_BASE array
|
||||
debugger_thread dd ? ;+172 ; pointer to APPDATA or 0
|
||||
terminate_protection dd ? ;+176
|
||||
keyboard_mode db ? ;+180
|
||||
rb 3
|
||||
|
||||
+41
-77
@@ -8,8 +8,8 @@
|
||||
|
||||
; diamond, 2006
|
||||
sys_debug_services:
|
||||
cmp ebx, 9
|
||||
ja @f
|
||||
cmp ebx, sys_debug_services_table.count
|
||||
jae @f
|
||||
jmp dword [sys_debug_services_table + ebx*4]
|
||||
@@:
|
||||
ret
|
||||
@@ -26,7 +26,9 @@ sys_debug_services_table:
|
||||
dd debug_write_process_memory
|
||||
dd debug_terminate
|
||||
dd debug_set_drx
|
||||
.count = ($ - sys_debug_services_table)/4
|
||||
endg
|
||||
|
||||
debug_set_event_data:
|
||||
; in: ecx = pointer
|
||||
; destroys eax
|
||||
@@ -34,22 +36,20 @@ debug_set_event_data:
|
||||
mov [eax + APPDATA.dbg_event_mem], ecx
|
||||
ret
|
||||
|
||||
get_debuggee_slot:
|
||||
get_debuggee_thread:
|
||||
; in: ecx=PID
|
||||
; out: CF=1 if error
|
||||
; CF=0 and eax=slot*0x20 if ok
|
||||
; CF=0 and eax = pointer to APPDATA if ok
|
||||
; out: interrupts disabled
|
||||
cli
|
||||
mov eax, ecx
|
||||
call pid_to_slot
|
||||
;call pid_to_appdata
|
||||
call pid_to_thread
|
||||
test eax, eax
|
||||
jz .ret_bad
|
||||
shl eax, BSF sizeof.APPDATA
|
||||
|
||||
push ebx
|
||||
mov ebx, [current_slot_idx]
|
||||
cmp [SLOT_BASE + eax + APPDATA.debugger_slot], ebx
|
||||
;cmp [eax + APPDATA.debugger_slot], ebx
|
||||
mov ebx, [current_slot]
|
||||
cmp [eax + APPDATA.debugger_thread], ebx
|
||||
pop ebx
|
||||
jnz .ret_bad
|
||||
; clc ; automatically
|
||||
@@ -61,10 +61,9 @@ get_debuggee_slot:
|
||||
debug_detach:
|
||||
; in: ecx=pid
|
||||
; destroys eax,ebx
|
||||
call get_debuggee_slot
|
||||
call get_debuggee_thread
|
||||
jc .ret
|
||||
and dword [eax + SLOT_BASE + APPDATA.debugger_slot], 0
|
||||
;and dword [eax + APPDATA.debugger_slot], 0
|
||||
and dword [eax + APPDATA.debugger_thread], 0
|
||||
call do_resume
|
||||
.ret:
|
||||
sti
|
||||
@@ -72,40 +71,27 @@ debug_detach:
|
||||
|
||||
debug_terminate:
|
||||
; in: ecx=pid
|
||||
call get_debuggee_slot
|
||||
call get_debuggee_thread
|
||||
jc debug_detach.ret
|
||||
mov ecx, eax
|
||||
|
||||
shr ecx, BSF sizeof.APPDATA
|
||||
;movzx ecx, ch ; del when sysfn_term... will using APPDATA
|
||||
|
||||
; push 2
|
||||
; pop ebx
|
||||
mov edx, esi ; what?
|
||||
movzx ecx, ch ; del when sysfn_term... will using APPDATA
|
||||
jmp sysfn_terminate
|
||||
|
||||
debug_suspend:
|
||||
; in: ecx=pid
|
||||
; destroys eax,ecx
|
||||
; { Patch by Coldy (rev. 7125), reason: http://board.kolibrios.org/viewtopic.php?f=1&t=1712&p=75957#p75957
|
||||
; cli
|
||||
; mov eax, ecx
|
||||
; call pid_to_slot
|
||||
; shl eax, 5
|
||||
; jz .ret
|
||||
call get_debuggee_slot
|
||||
call get_debuggee_thread
|
||||
jc .ret
|
||||
; } End patch
|
||||
mov cl, [SLOT_BASE + eax + APPDATA.state] ; process state
|
||||
;mov cl, [eax + APPDATA.state] ; process state
|
||||
|
||||
mov cl, [eax + APPDATA.state] ; process state
|
||||
test cl, cl
|
||||
jz .1
|
||||
cmp cl, TSTATE_WAITING
|
||||
jnz .ret
|
||||
mov cl, TSTATE_WAIT_SUSPENDED
|
||||
.2:
|
||||
mov [SLOT_BASE + eax + APPDATA.state], cl
|
||||
;mov [eax + APPDATA.state], cl
|
||||
mov [eax + APPDATA.state], cl
|
||||
.ret:
|
||||
sti
|
||||
ret
|
||||
@@ -114,16 +100,14 @@ debug_suspend:
|
||||
jmp .2
|
||||
|
||||
do_resume:
|
||||
mov cl, [SLOT_BASE + eax + APPDATA.state]
|
||||
;mov cl, [eax + APPDATA.state]
|
||||
mov cl, [eax + APPDATA.state]
|
||||
cmp cl, TSTATE_RUN_SUSPENDED
|
||||
jz .1
|
||||
cmp cl, TSTATE_WAIT_SUSPENDED
|
||||
jnz .ret
|
||||
mov cl, TSTATE_WAITING
|
||||
.2:
|
||||
mov [SLOT_BASE + eax + APPDATA.state], cl
|
||||
;mov [eax + APPDATA.state], cl
|
||||
mov [eax + APPDATA.state], cl
|
||||
.ret:
|
||||
ret
|
||||
.1:
|
||||
@@ -133,11 +117,9 @@ do_resume:
|
||||
debug_resume:
|
||||
; in: ecx=pid
|
||||
; destroys eax,ebx
|
||||
cli
|
||||
mov eax, ecx
|
||||
call pid_to_slot
|
||||
shl eax, BSF sizeof.APPDATA
|
||||
jz .ret
|
||||
call get_debuggee_thread
|
||||
jc .ret
|
||||
|
||||
call do_resume
|
||||
.ret:
|
||||
sti
|
||||
@@ -160,21 +142,15 @@ debug_getcontext:
|
||||
inc ebx ; 1 - get sse context
|
||||
; TODO legacy 32-bit FPU/MMX context
|
||||
.std_ctx:
|
||||
call get_debuggee_slot
|
||||
call get_debuggee_thread
|
||||
jc .ret
|
||||
|
||||
shr eax, BSF sizeof.APPDATA
|
||||
;movzx ebp, ah
|
||||
|
||||
cmp eax, [fpu_owner]
|
||||
;cmp ebp, [fpu_owner]
|
||||
jne @f
|
||||
inc bh ; set swap context flag
|
||||
@@:
|
||||
shl eax, BSF sizeof.APPDATA
|
||||
mov edi, esi
|
||||
mov eax, [SLOT_BASE + eax + APPDATA.pl0_stack]
|
||||
;mov eax, [eax + APPDATA.pl0_stack]
|
||||
mov eax, [eax + APPDATA.pl0_stack]
|
||||
lea esi, [eax + RING0_STACK_SIZE]
|
||||
|
||||
.ring0:
|
||||
@@ -240,11 +216,10 @@ debug_setcontext:
|
||||
cmp edx, 28h
|
||||
jnz .ret
|
||||
|
||||
call get_debuggee_slot
|
||||
call get_debuggee_thread
|
||||
jc .stiret
|
||||
; mov esi, edx
|
||||
mov eax, [eax + SLOT_BASE+APPDATA.pl0_stack]
|
||||
;mov eax, [eax + APPDATA.pl0_stack]
|
||||
|
||||
mov eax, [eax + APPDATA.pl0_stack]
|
||||
lea edi, [eax + RING0_STACK_SIZE]
|
||||
|
||||
.ring0:
|
||||
@@ -277,15 +252,16 @@ debug_setcontext:
|
||||
ret
|
||||
|
||||
debug_set_drx:
|
||||
call get_debuggee_slot
|
||||
call get_debuggee_thread
|
||||
jc .errret
|
||||
|
||||
mov ebp, eax
|
||||
lea eax, [eax + SLOT_BASE + APPDATA.dbg_regs]
|
||||
;lea eax, [eax + APPDATA.dbg_regs]
|
||||
lea eax, [eax + APPDATA.dbg_regs]
|
||||
; [eax]=dr0, [eax+4]=dr1, [eax+8]=dr2, [eax+C]=dr3
|
||||
; [eax+10]=dr7
|
||||
cmp esi, OS_BASE
|
||||
jae .errret
|
||||
|
||||
cmp dl, 3
|
||||
ja .errret
|
||||
mov ecx, dr7
|
||||
@@ -306,10 +282,7 @@ debug_set_drx:
|
||||
btr dword [eax + 10h], edx ; clear L<i> bit
|
||||
test byte [eax + 10h], 55h
|
||||
jnz .okret
|
||||
; imul eax, ebp, tss_step/32
|
||||
; and byte [eax + tss_data + TSS._trap], not 1
|
||||
and [SLOT_BASE + ebp + APPDATA.dbg_state], not 1
|
||||
;and [ebp + APPDATA.dbg_state], not 1
|
||||
and [ebp + APPDATA.dbg_state], not 1
|
||||
.okret:
|
||||
and dword [esp + SYSCALL_STACK.eax], 0
|
||||
sti
|
||||
@@ -354,10 +327,7 @@ debug_set_drx:
|
||||
not ebx
|
||||
and [eax + 10h+2], bx
|
||||
or [eax + 10h+2], dx ; set R/W and LEN fields
|
||||
; imul eax, ebp, tss_step/32
|
||||
; or byte [eax + tss_data + TSS._trap], 1
|
||||
or [SLOT_BASE + ebp + APPDATA.dbg_state], 1
|
||||
;or [ebp + APPDATA.dbg_state], 1
|
||||
or [ebp + APPDATA.dbg_state], 1
|
||||
jmp .okret
|
||||
|
||||
debug_read_process_memory:
|
||||
@@ -368,10 +338,9 @@ debug_read_process_memory:
|
||||
; esi=address in debuggee
|
||||
; out: [esp+36]=sizeof(read)
|
||||
; destroys all
|
||||
call get_debuggee_slot
|
||||
call get_debuggee_thread
|
||||
jc .err
|
||||
shr eax, BSF sizeof.APPDATA
|
||||
;movzx eax,ah
|
||||
|
||||
mov ecx, edi
|
||||
call read_process_memory
|
||||
sti
|
||||
@@ -389,10 +358,9 @@ debug_write_process_memory:
|
||||
; esi=address in debuggee
|
||||
; out: [esp+36]=sizeof(write)
|
||||
; destroys all
|
||||
call get_debuggee_slot
|
||||
call get_debuggee_thread
|
||||
jc debug_read_process_memory.err
|
||||
shr eax, BSF sizeof.APPDATA
|
||||
;movzx eax,ah
|
||||
|
||||
mov ecx, edi
|
||||
call write_process_memory
|
||||
sti
|
||||
@@ -400,7 +368,7 @@ debug_write_process_memory:
|
||||
ret
|
||||
|
||||
debugger_notify:
|
||||
; in: eax=debugger slot
|
||||
; in: eax=debugger thread
|
||||
; ecx=size of debug message
|
||||
; [esp+4]..[esp+4+ecx]=message
|
||||
; interrupts must be disabled!
|
||||
@@ -410,9 +378,7 @@ debugger_notify:
|
||||
mov edi, [timer_ticks]
|
||||
add edi, 500 ; 5 sec timeout
|
||||
.1:
|
||||
mov eax, ebp
|
||||
shl eax, BSF sizeof.APPDATA
|
||||
mov esi, [SLOT_BASE + eax + APPDATA.dbg_event_mem]
|
||||
mov esi, [ebp + APPDATA.dbg_event_mem]
|
||||
test esi, esi
|
||||
jz .ret
|
||||
; read buffer header
|
||||
@@ -466,8 +432,6 @@ debugger_notify:
|
||||
pop edx
|
||||
call write_process_memory
|
||||
; new debug event
|
||||
mov eax, ebp
|
||||
shl eax, BSF sizeof.APPDATA
|
||||
or [SLOT_BASE + eax + APPDATA.occurred_events], EVENT_DEBUG
|
||||
or [ebp + APPDATA.occurred_events], EVENT_DEBUG
|
||||
.ret:
|
||||
ret
|
||||
+49
-37
@@ -150,10 +150,10 @@ init_avx512:
|
||||
|
||||
ret
|
||||
|
||||
; param
|
||||
; eax= 512 bytes memory area aligned on a 16-byte boundary
|
||||
|
||||
align 4
|
||||
; @brief Export function - Save FPU context in buffer
|
||||
; @param eax - 512 bytes memory area aligned on a 16-byte boundary
|
||||
; @return not return
|
||||
fpu_save:
|
||||
push ecx
|
||||
push esi
|
||||
@@ -166,7 +166,7 @@ fpu_save:
|
||||
mov edi, eax
|
||||
|
||||
mov ecx, [fpu_owner]
|
||||
mov esi, [current_slot_idx]
|
||||
mov esi, [current_slot]
|
||||
cmp ecx, esi
|
||||
jne .save
|
||||
|
||||
@@ -175,14 +175,11 @@ fpu_save:
|
||||
.save:
|
||||
mov [fpu_owner], esi
|
||||
|
||||
shl ecx, BSF sizeof.APPDATA
|
||||
mov eax, [SLOT_BASE + ecx + APPDATA.fpu_state]
|
||||
|
||||
mov eax, [ecx + APPDATA.fpu_state]
|
||||
call save_context
|
||||
|
||||
; first 512 bytes of XSAVE area have the same format as FXSAVE
|
||||
shl esi, BSF sizeof.APPDATA
|
||||
mov esi, [SLOT_BASE + esi + APPDATA.fpu_state]
|
||||
mov esi, [esi + APPDATA.fpu_state]
|
||||
mov ecx, 512/4
|
||||
cld
|
||||
rep movsd
|
||||
@@ -194,14 +191,16 @@ fpu_save:
|
||||
pop ecx
|
||||
ret
|
||||
|
||||
; @brief Export function - Get size from AVX context
|
||||
; @return size of buffer
|
||||
avx_save_size:
|
||||
mov eax, [xsave_area_size]
|
||||
ret
|
||||
|
||||
; param
|
||||
; eax= avx_save_size() bytes memory area aligned on a 64-byte boundary
|
||||
|
||||
align 4
|
||||
; @brief Export function - Save AVX context in buffer
|
||||
; @param eax - avx_save_size() bytes memory area aligned on a 64-byte boundary
|
||||
; @return not return
|
||||
avx_save:
|
||||
push ecx
|
||||
push esi
|
||||
@@ -214,7 +213,7 @@ avx_save:
|
||||
mov edi, eax
|
||||
|
||||
mov ecx, [fpu_owner]
|
||||
mov esi, [current_slot_idx]
|
||||
mov esi, [current_slot]
|
||||
cmp ecx, esi
|
||||
jne .save
|
||||
|
||||
@@ -223,13 +222,10 @@ avx_save:
|
||||
.save:
|
||||
mov [fpu_owner], esi
|
||||
|
||||
shl ecx, BSF sizeof.APPDATA
|
||||
mov eax, [SLOT_BASE + ecx + APPDATA.fpu_state]
|
||||
|
||||
mov eax, [ecx + APPDATA.fpu_state]
|
||||
call save_context
|
||||
|
||||
shl esi, BSF sizeof.APPDATA
|
||||
mov esi, [SLOT_BASE + esi + APPDATA.fpu_state]
|
||||
mov esi, [esi + APPDATA.fpu_state]
|
||||
mov ecx, [xsave_area_size]
|
||||
add ecx, 3
|
||||
shr ecx, 2
|
||||
@@ -264,9 +260,13 @@ save_fpu_context:
|
||||
|
||||
|
||||
align 4
|
||||
; @brief Export function - Restore FPU context
|
||||
; @param eax - 512 bytes memory area aligned on a 16-byte boundary
|
||||
; @return not return
|
||||
fpu_restore:
|
||||
push ecx
|
||||
push esi
|
||||
push edi
|
||||
|
||||
mov esi, eax
|
||||
|
||||
@@ -274,7 +274,7 @@ fpu_restore:
|
||||
cli
|
||||
|
||||
mov ecx, [fpu_owner]
|
||||
mov eax, [current_slot_idx]
|
||||
mov eax, [current_slot]
|
||||
cmp ecx, eax
|
||||
jne .copy
|
||||
|
||||
@@ -284,6 +284,8 @@ fpu_restore:
|
||||
|
||||
fxrstor [esi]
|
||||
popfd
|
||||
|
||||
pop edi
|
||||
pop esi
|
||||
pop ecx
|
||||
ret
|
||||
@@ -291,24 +293,31 @@ fpu_restore:
|
||||
fnclex ;fix possible problems
|
||||
frstor [esi]
|
||||
popfd
|
||||
|
||||
pop edi
|
||||
pop esi
|
||||
pop ecx
|
||||
ret
|
||||
.copy:
|
||||
shl eax, BSF sizeof.APPDATA
|
||||
mov edi, [SLOT_BASE + eax + APPDATA.fpu_state]
|
||||
mov edi, [eax + APPDATA.fpu_state]
|
||||
mov ecx, 512/4
|
||||
cld
|
||||
rep movsd
|
||||
popfd
|
||||
|
||||
pop edi
|
||||
pop esi
|
||||
pop ecx
|
||||
ret
|
||||
|
||||
align 4
|
||||
; @brief Export function - Restore AVX context
|
||||
; @param eax - avx_save_size() bytes memory area aligned on a 64-byte boundary
|
||||
; @return not return
|
||||
avx_restore:
|
||||
push ecx
|
||||
push esi
|
||||
push edi
|
||||
|
||||
mov esi, eax
|
||||
|
||||
@@ -316,7 +325,7 @@ avx_restore:
|
||||
cli
|
||||
|
||||
mov ecx, [fpu_owner]
|
||||
mov eax, [current_slot_idx]
|
||||
mov eax, [current_slot]
|
||||
cmp ecx, eax
|
||||
jne .copy
|
||||
|
||||
@@ -329,6 +338,8 @@ avx_restore:
|
||||
xrstor [esi]
|
||||
pop edx
|
||||
popfd
|
||||
|
||||
pop edi
|
||||
pop esi
|
||||
pop ecx
|
||||
ret
|
||||
@@ -338,6 +349,8 @@ avx_restore:
|
||||
|
||||
fxrstor [esi]
|
||||
popfd
|
||||
|
||||
pop edi
|
||||
pop esi
|
||||
pop ecx
|
||||
ret
|
||||
@@ -345,18 +358,21 @@ avx_restore:
|
||||
fnclex ;fix possible problems
|
||||
frstor [esi]
|
||||
popfd
|
||||
|
||||
pop edi
|
||||
pop esi
|
||||
pop ecx
|
||||
ret
|
||||
.copy:
|
||||
shl eax, BSF sizeof.APPDATA
|
||||
mov edi, [SLOT_BASE + eax + APPDATA.fpu_state]
|
||||
mov edi, [eax + APPDATA.fpu_state]
|
||||
mov ecx, [xsave_area_size]
|
||||
add ecx, 3
|
||||
shr ecx, 2
|
||||
cld
|
||||
rep movsd
|
||||
popfd
|
||||
|
||||
pop edi
|
||||
pop esi
|
||||
pop ecx
|
||||
ret
|
||||
@@ -370,21 +386,19 @@ except_7: ;#NM exception handler
|
||||
mov es, ax
|
||||
|
||||
mov ebx, [fpu_owner]
|
||||
cmp ebx, [current_slot_idx]
|
||||
cmp ebx, [current_slot]
|
||||
je .exit
|
||||
|
||||
shl ebx, BSF sizeof.APPDATA
|
||||
mov eax, [SLOT_BASE + ebx + APPDATA.fpu_state]
|
||||
mov eax, [ebx + APPDATA.fpu_state]
|
||||
bt [cpu_caps + (CAPS_OSXSAVE/32)*4], CAPS_OSXSAVE mod 32
|
||||
jnc .no_xsave
|
||||
mov ecx, eax
|
||||
mov eax, [xsave_eax]
|
||||
mov edx, [xsave_edx]
|
||||
xsave [ecx]
|
||||
mov ebx, [current_slot_idx]
|
||||
mov ebx, [current_slot]
|
||||
mov [fpu_owner], ebx
|
||||
shl ebx, BSF sizeof.APPDATA
|
||||
mov ecx, [SLOT_BASE + ebx + APPDATA.fpu_state]
|
||||
mov ecx, [ebx + APPDATA.fpu_state]
|
||||
xrstor [ecx]
|
||||
.exit:
|
||||
restore_ring3_context
|
||||
@@ -394,24 +408,22 @@ except_7: ;#NM exception handler
|
||||
jnc .no_SSE
|
||||
|
||||
fxsave [eax]
|
||||
mov ebx, [current_slot_idx]
|
||||
mov ebx, [current_slot]
|
||||
mov [fpu_owner], ebx
|
||||
shl ebx, BSF sizeof.APPDATA
|
||||
mov eax, [SLOT_BASE + ebx + APPDATA.fpu_state]
|
||||
mov eax, [ebx + APPDATA.fpu_state]
|
||||
fxrstor [eax]
|
||||
restore_ring3_context
|
||||
iret
|
||||
|
||||
.no_SSE:
|
||||
fnsave [eax]
|
||||
mov ebx, [current_slot_idx]
|
||||
mov ebx, [current_slot]
|
||||
mov [fpu_owner], ebx
|
||||
shl ebx, BSF sizeof.APPDATA
|
||||
mov eax, [SLOT_BASE + ebx + APPDATA.fpu_state]
|
||||
mov eax, [ebx + APPDATA.fpu_state]
|
||||
frstor [eax]
|
||||
restore_ring3_context
|
||||
iret
|
||||
|
||||
iglobal
|
||||
fpu_owner dd 2
|
||||
fpu_owner dd APPDATA_OS_THREAD
|
||||
endg
|
||||
@@ -463,7 +463,7 @@ proc kernel_alloc stdcall, size:dword
|
||||
and eax, -PAGE_SIZE;
|
||||
mov [size], eax
|
||||
and eax, eax
|
||||
jz .err
|
||||
jz .err0
|
||||
mov ebx, eax
|
||||
shr ebx, 12
|
||||
mov [pages_count], ebx
|
||||
@@ -509,6 +509,13 @@ proc kernel_alloc stdcall, size:dword
|
||||
pop ebx
|
||||
ret
|
||||
.err:
|
||||
mov eax, [lin_addr]
|
||||
test eax, eax
|
||||
jz .err0
|
||||
mov ecx, [pages_count]
|
||||
call release_pages
|
||||
stdcall free_kernel_space, [lin_addr]
|
||||
.err0:
|
||||
xor eax, eax
|
||||
pop edi
|
||||
pop ebx
|
||||
|
||||
@@ -605,7 +605,7 @@ proc page_fault_handler
|
||||
|
||||
mov edi, [.err_addr]
|
||||
and edi, -PAGE_SIZE
|
||||
mov ecx, 1024
|
||||
mov ecx, PAGE_SIZE/4
|
||||
xor eax, eax
|
||||
;cld ;caller is duty for this
|
||||
rep stosd
|
||||
@@ -664,7 +664,7 @@ proc page_fault_handler
|
||||
cmp ebx, tss._io_map_0
|
||||
jb .fail
|
||||
|
||||
cmp ebx, tss._io_map_0+8192
|
||||
cmp ebx, tss._io_map_0 + IO_MAP_SIZE
|
||||
jae .fail
|
||||
|
||||
; io permission map
|
||||
@@ -695,7 +695,7 @@ proc page_fault_handler
|
||||
endp
|
||||
|
||||
; returns number of mapped bytes
|
||||
proc map_mem_ipc stdcall, lin_addr:dword,slot:dword,\
|
||||
proc map_mem_ipc stdcall, lin_addr:dword,thread:dword,\
|
||||
ofs:dword,buf_size:dword,req_access:dword
|
||||
locals
|
||||
count dd ?
|
||||
@@ -706,9 +706,8 @@ proc map_mem_ipc stdcall, lin_addr:dword,slot:dword,\
|
||||
cmp [buf_size], 0
|
||||
jz .exit
|
||||
|
||||
mov eax, [slot]
|
||||
shl eax, BSF sizeof.APPDATA
|
||||
mov eax, [SLOT_BASE + eax + APPDATA.process]
|
||||
mov eax, [thread]
|
||||
mov eax, [eax + APPDATA.process]
|
||||
test eax, eax
|
||||
jz .exit
|
||||
|
||||
@@ -732,7 +731,7 @@ proc map_mem_ipc stdcall, lin_addr:dword,slot:dword,\
|
||||
shr edx, 12
|
||||
and edx, 0x3FF
|
||||
.map:
|
||||
stdcall safe_map_page, [slot], [req_access], [ofs]
|
||||
stdcall safe_map_page, [process], [req_access], [ofs]
|
||||
jnc .exit
|
||||
add [count], PAGE_SIZE
|
||||
add [ofs], PAGE_SIZE
|
||||
@@ -758,7 +757,7 @@ proc map_mem_ipc stdcall, lin_addr:dword,slot:dword,\
|
||||
ret
|
||||
endp
|
||||
|
||||
proc map_memEx stdcall, lin_addr:dword,slot:dword,\
|
||||
proc map_memEx stdcall, lin_addr:dword,thread:dword,\
|
||||
ofs:dword,buf_size:dword,req_access:dword
|
||||
locals
|
||||
count dd ?
|
||||
@@ -769,9 +768,8 @@ proc map_memEx stdcall, lin_addr:dword,slot:dword,\
|
||||
cmp [buf_size], 0
|
||||
jz .exit
|
||||
|
||||
mov eax, [slot]
|
||||
shl eax, BSF sizeof.APPDATA
|
||||
mov eax, [SLOT_BASE + eax + APPDATA.process]
|
||||
mov eax, [thread]
|
||||
mov eax, [eax + APPDATA.process]
|
||||
test eax, eax
|
||||
jz .exit
|
||||
|
||||
@@ -795,7 +793,7 @@ proc map_memEx stdcall, lin_addr:dword,slot:dword,\
|
||||
shr edx, 12
|
||||
and edx, 0x3FF
|
||||
.map:
|
||||
stdcall safe_map_page, [slot], [req_access], [ofs]
|
||||
stdcall safe_map_page, [process], [req_access], [ofs]
|
||||
jnc .exit
|
||||
add [count], PAGE_SIZE
|
||||
add [ofs], PAGE_SIZE
|
||||
@@ -826,7 +824,7 @@ endp
|
||||
; in: edi = linear address to map
|
||||
; out: CF cleared <=> failed
|
||||
; destroys: only eax
|
||||
proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword
|
||||
proc safe_map_page stdcall, process:dword, req_access:dword, ofs:dword
|
||||
mov eax, [esi + edx*4]
|
||||
test al, PG_READ
|
||||
jz .not_present
|
||||
@@ -861,9 +859,7 @@ proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword
|
||||
cli
|
||||
cld
|
||||
push ebx ecx
|
||||
mov eax, [slot]
|
||||
shl eax, BSF sizeof.APPDATA
|
||||
mov eax, [SLOT_BASE + eax + APPDATA.process]
|
||||
mov eax, [process]
|
||||
mov eax, [eax + PROC.dlls_list_ptr]
|
||||
test eax, eax
|
||||
jz .no_hdll
|
||||
@@ -953,7 +949,7 @@ sys_IPC:
|
||||
|
||||
proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
|
||||
locals
|
||||
dst_slot dd ?
|
||||
dst_thread dd ?
|
||||
dst_offset dd ?
|
||||
buf_size dd ?
|
||||
used_buf dd ?
|
||||
@@ -963,13 +959,12 @@ proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
|
||||
cli
|
||||
|
||||
mov eax, [PID]
|
||||
call pid_to_slot
|
||||
call pid_to_thread
|
||||
test eax, eax
|
||||
jz .no_pid
|
||||
|
||||
mov [dst_slot], eax
|
||||
shl eax, BSF sizeof.APPDATA
|
||||
mov edi, [SLOT_BASE + eax + APPDATA.ipc_start] ;is ipc area defined?
|
||||
mov [dst_thread], eax
|
||||
mov edi, [eax + APPDATA.ipc_start] ;is ipc area defined?
|
||||
test edi, edi
|
||||
jz .no_ipc_area
|
||||
|
||||
@@ -977,7 +972,7 @@ proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
|
||||
and ebx, 0xFFF
|
||||
mov [dst_offset], ebx
|
||||
|
||||
mov esi, [SLOT_BASE + eax + APPDATA.ipc_size]
|
||||
mov esi, [eax + APPDATA.ipc_size]
|
||||
mov [buf_size], esi
|
||||
|
||||
mov ecx, [ipc_tmp]
|
||||
@@ -990,7 +985,7 @@ proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
|
||||
pop edi esi
|
||||
@@:
|
||||
mov [used_buf], ecx
|
||||
stdcall map_mem_ipc, ecx, [dst_slot], \
|
||||
stdcall map_mem_ipc, ecx, [dst_thread], \
|
||||
edi, esi, PG_SWR
|
||||
|
||||
mov edi, [dst_offset]
|
||||
@@ -1039,9 +1034,8 @@ proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword
|
||||
mov [page_tabs + ebx*4], eax
|
||||
invlpg [edx]
|
||||
|
||||
mov eax, [dst_slot]
|
||||
shl eax, BSF sizeof.APPDATA
|
||||
or [SLOT_BASE + eax + APPDATA.occurred_events], EVENT_IPC
|
||||
mov eax, [dst_thread]
|
||||
or [eax + APPDATA.occurred_events], EVENT_IPC
|
||||
push 0
|
||||
jmp .ret
|
||||
.no_pid:
|
||||
@@ -1403,7 +1397,9 @@ proc create_ring_buffer stdcall, size:dword, flags:dword
|
||||
mov [page_tabs + edi], eax
|
||||
mov [page_tabs + edi + edx], eax
|
||||
invlpg [ebx]
|
||||
invlpg [ebx+0x10000]
|
||||
add ebx, [size]
|
||||
invlpg [ebx] ; the mirror half
|
||||
sub ebx, [size]
|
||||
add eax, 0x1000
|
||||
add ebx, 0x1000
|
||||
add edi, 4
|
||||
@@ -1422,6 +1418,62 @@ proc create_ring_buffer stdcall, size:dword, flags:dword
|
||||
ret
|
||||
endp
|
||||
|
||||
; Same as create_ring_buffer, but from non-contiguous pages.
|
||||
; Not for DMA. Free with kernel_free.
|
||||
align 4
|
||||
proc create_ring_buffer_sparse stdcall, size:dword, flags:dword
|
||||
locals
|
||||
buf_ptr dd ?
|
||||
endl
|
||||
|
||||
mov eax, [size]
|
||||
test eax, eax
|
||||
jz .fail
|
||||
|
||||
add eax, eax
|
||||
stdcall alloc_kernel_space, eax
|
||||
test eax, eax
|
||||
jz .fail
|
||||
mov [buf_ptr], eax
|
||||
|
||||
push ebx esi edi
|
||||
mov ebx, eax ; page being mapped
|
||||
mov esi, [size] ; distance to its mirror
|
||||
mov edi, esi
|
||||
shr edi, 12 ; pages left
|
||||
.page:
|
||||
call alloc_page
|
||||
test eax, eax
|
||||
jz .mm_fail
|
||||
or eax, [flags]
|
||||
mov edx, ebx
|
||||
shr edx, 12
|
||||
mov [page_tabs + edx*4], eax
|
||||
invlpg [ebx]
|
||||
lea edx, [ebx + esi]
|
||||
shr edx, 12
|
||||
mov [page_tabs + edx*4], eax
|
||||
invlpg [ebx + esi]
|
||||
add ebx, PAGE_SIZE
|
||||
dec edi
|
||||
jnz .page
|
||||
|
||||
mov eax, [buf_ptr]
|
||||
pop edi esi ebx
|
||||
ret
|
||||
|
||||
.mm_fail:
|
||||
mov eax, [buf_ptr]
|
||||
mov ecx, [size]
|
||||
shr ecx, 11 ; both halves, in pages
|
||||
call release_pages
|
||||
stdcall free_kernel_space, [buf_ptr]
|
||||
pop edi esi ebx
|
||||
xor eax, eax
|
||||
.fail:
|
||||
ret
|
||||
endp
|
||||
|
||||
|
||||
align 4
|
||||
proc print_mem
|
||||
|
||||
@@ -139,14 +139,13 @@ do_change_task:
|
||||
mov eax, [xsave_eax]
|
||||
mov edx, [xsave_edx]
|
||||
xsave [ecx]
|
||||
mov ecx, [current_slot_idx]
|
||||
mov [fpu_owner], ecx
|
||||
mov ecx, [current_slot]
|
||||
mov [fpu_owner], ecx
|
||||
mov ecx, [ecx + APPDATA.fpu_state]
|
||||
xrstor [ecx]
|
||||
.no_xsave:
|
||||
; set CR0.TS
|
||||
cmp bh, byte[fpu_owner] ;bh == incoming task (new)
|
||||
cmp ebx, [fpu_owner] ;ebx == incoming task (new)
|
||||
clts ;clear a task switch flag
|
||||
je @f
|
||||
mov eax, cr0 ;and set it again if the owner
|
||||
|
||||
+19
-16
@@ -165,7 +165,7 @@ exc_c: ; exceptions (all but 7th - #NM)
|
||||
jnz IRetToUserHook
|
||||
@@:
|
||||
cli
|
||||
mov eax, [esi + APPDATA.debugger_slot]
|
||||
mov eax, [esi + APPDATA.debugger_thread]
|
||||
test eax, eax
|
||||
jnz .debug
|
||||
; not debuggee => say error and terminate
|
||||
@@ -514,28 +514,30 @@ destroy_thread:
|
||||
@@:
|
||||
mov eax, [esi + APPOBJ.fd]
|
||||
test eax, eax
|
||||
jz @F
|
||||
jz @f
|
||||
|
||||
cmp eax, esi
|
||||
je @F
|
||||
je @f
|
||||
|
||||
push esi
|
||||
call [eax + APPOBJ.destroy]
|
||||
DEBUGF 1,"%s",msg_obj_destroy
|
||||
pop esi
|
||||
jmp @B
|
||||
jmp @b
|
||||
@@:
|
||||
mov esi, [.slot]
|
||||
shl esi, BSF sizeof.APPDATA
|
||||
add esi, SLOT_BASE
|
||||
cmp [fpu_owner], esi ; if user fpu last -> fpu user = 2
|
||||
jne @F
|
||||
jne @f
|
||||
|
||||
mov [fpu_owner], 2
|
||||
mov eax, [SLOT_BASE + sizeof.APPDATA*2 + APPDATA.fpu_state]
|
||||
mov [fpu_owner], APPDATA_OS_THREAD
|
||||
mov eax, [APPDATA_OS_THREAD + APPDATA.fpu_state]
|
||||
clts
|
||||
bt [cpu_caps], CAPS_SSE
|
||||
jnc .no_SSE
|
||||
fxrstor [eax]
|
||||
jmp @F
|
||||
jmp @f
|
||||
.no_SSE:
|
||||
fnclex
|
||||
frstor [eax]
|
||||
@@ -544,8 +546,8 @@ destroy_thread:
|
||||
mov [KEY_COUNT], byte 0 ; empty keyboard buffer
|
||||
mov [BTN_COUNT], byte 0 ; empty button buffer
|
||||
|
||||
|
||||
; remove defined hotkeys
|
||||
mov esi, [.slot]
|
||||
mov eax, hotkey_list
|
||||
.loop:
|
||||
cmp [eax+8], esi
|
||||
@@ -638,7 +640,7 @@ destroy_thread:
|
||||
pushad
|
||||
mov edi, esi
|
||||
shl edi, BSF sizeof.APPDATA
|
||||
mov eax, [SLOT_BASE + edi + APPDATA.debugger_slot]
|
||||
mov eax, [SLOT_BASE + edi + APPDATA.debugger_thread]
|
||||
test eax, eax
|
||||
jz .nodebug
|
||||
movi ecx, 8
|
||||
@@ -666,12 +668,12 @@ destroy_thread:
|
||||
add edi, SLOT_BASE
|
||||
|
||||
mov eax, [edi + APPDATA.io_map]
|
||||
cmp eax, [SLOT_BASE + sizeof.APPDATA+APPDATA.io_map]
|
||||
cmp eax, [APPDATA_IDLE_THREAD + APPDATA.io_map]
|
||||
je @F
|
||||
call free_page
|
||||
@@:
|
||||
mov eax, [edi+APPDATA.io_map+4]
|
||||
cmp eax, [SLOT_BASE+sizeof.APPDATA+APPDATA.io_map+4]
|
||||
cmp eax, [APPDATA_IDLE_THREAD + APPDATA.io_map+4]
|
||||
je @F
|
||||
call free_page
|
||||
@@:
|
||||
@@ -712,12 +714,12 @@ destroy_thread:
|
||||
call free_cd_channel
|
||||
and [cd_status], 0
|
||||
@@:
|
||||
pop esi
|
||||
cmp [bgrlockpid], esi
|
||||
jnz @f
|
||||
and [bgrlockpid], 0
|
||||
and [bgrlock], 0
|
||||
@@:
|
||||
pop esi
|
||||
|
||||
pusha ; remove all port reservations
|
||||
mov edx, esi
|
||||
@@ -778,14 +780,15 @@ destroy_thread:
|
||||
|
||||
mov edi, esi ; do not run this process slot
|
||||
shl edi, BSF sizeof.APPDATA
|
||||
mov [SLOT_BASE + edi + APPDATA.state], TSTATE_FREE
|
||||
add edi, SLOT_BASE
|
||||
mov [edi + APPDATA.state], TSTATE_FREE
|
||||
; debugger test - terminate all debuggees
|
||||
mov eax, 2
|
||||
mov ecx, SLOT_BASE + 2*sizeof.APPDATA + APPDATA.debugger_slot
|
||||
mov ecx, APPDATA_OS_THREAD + APPDATA.debugger_thread
|
||||
.xd0:
|
||||
cmp eax, [thread_count]
|
||||
ja .xd1
|
||||
cmp dword [ecx], esi
|
||||
cmp dword [ecx], edi
|
||||
jnz @f
|
||||
and dword [ecx], 0
|
||||
pushad
|
||||
|
||||
@@ -537,21 +537,21 @@ pid_to_slot:
|
||||
align 4
|
||||
proc read_process_memory
|
||||
;Input:
|
||||
; eax - process slot
|
||||
; eax - process thread
|
||||
; ecx - buffer address
|
||||
; edx - buffer size
|
||||
; esi - start address in other process
|
||||
;Output:
|
||||
; eax - number of bytes read.
|
||||
locals
|
||||
slot dd ?
|
||||
thread dd ?
|
||||
buff dd ?
|
||||
r_count dd ?
|
||||
offset dd ?
|
||||
tmp_r_cnt dd ?
|
||||
endl
|
||||
|
||||
mov [slot], eax
|
||||
mov [thread], eax
|
||||
mov [buff], ecx
|
||||
and [r_count], 0
|
||||
mov [tmp_r_cnt], edx
|
||||
@@ -577,7 +577,7 @@ proc read_process_memory
|
||||
|
||||
push ecx
|
||||
stdcall map_memEx, [proc_mem_map], \
|
||||
[slot], ebx, ecx, PG_READ
|
||||
[thread], ebx, ecx, PG_READ
|
||||
pop ecx
|
||||
|
||||
mov esi, [offset]
|
||||
@@ -607,7 +607,7 @@ endp
|
||||
align 4
|
||||
proc write_process_memory
|
||||
;Input:
|
||||
; eax - process slot
|
||||
; eax - process thread
|
||||
; ecx - buffer address
|
||||
; edx - buffer size
|
||||
; esi - start address in other process
|
||||
@@ -615,14 +615,14 @@ proc write_process_memory
|
||||
; eax - number of bytes written
|
||||
|
||||
locals
|
||||
slot dd ?
|
||||
thread dd ?
|
||||
buff dd ?
|
||||
w_count dd ?
|
||||
offset dd ?
|
||||
tmp_w_cnt dd ?
|
||||
endl
|
||||
|
||||
mov [slot], eax
|
||||
mov [thread], eax
|
||||
mov [buff], ecx
|
||||
and [w_count], 0
|
||||
mov [tmp_w_cnt], edx
|
||||
@@ -647,7 +647,7 @@ proc write_process_memory
|
||||
mov ebx, [offset]
|
||||
push ecx
|
||||
stdcall map_memEx, [proc_mem_map], \
|
||||
[slot], ebx, ecx, PG_SWR
|
||||
[thread], ebx, ecx, PG_SWR
|
||||
pop ecx
|
||||
|
||||
mov edi, [offset]
|
||||
@@ -906,7 +906,7 @@ common_app_entry:
|
||||
stdcall free_kernel_space, [ebp+APP_HDR.img_base]
|
||||
stdcall kernel_free, ebp
|
||||
mov ebx, [current_slot]
|
||||
cmp [ebx + APPDATA.debugger_slot], 0
|
||||
cmp [ebx + APPDATA.debugger_thread], 0
|
||||
je .exit
|
||||
mov [ebx + APPDATA.state], TSTATE_RUN_SUSPENDED
|
||||
mov [ebx + APPDATA.state], TSTATE_RUN_SUSPENDED
|
||||
@@ -1054,8 +1054,8 @@ proc set_app_params stdcall,slot:dword, params:dword, flags:dword
|
||||
; set if debuggee
|
||||
test byte [flags], 1
|
||||
jz .no_debug
|
||||
mov eax, [current_slot_idx]
|
||||
mov [SLOT_BASE + ebx + APPDATA.debugger_slot], eax
|
||||
mov eax, [current_slot]
|
||||
mov [SLOT_BASE + ebx + APPDATA.debugger_thread], eax
|
||||
.no_debug:
|
||||
mov [SLOT_BASE + ebx + APPDATA.state], dl
|
||||
lea edx, [SLOT_BASE + ebx]
|
||||
@@ -1074,27 +1074,24 @@ get_curr_slot:
|
||||
mov eax, [current_slot]
|
||||
ret
|
||||
|
||||
pid_to_appdata:
|
||||
;Input:
|
||||
; eax - pid of process
|
||||
;Output:
|
||||
; eax - 0 - not found or pointer on APPDATA
|
||||
; @brief Get pointer to APPDATA by PID
|
||||
; @param eax - TID of thread
|
||||
; @return eax - 0 - not found or pointer on APPDATA
|
||||
pid_to_thread:
|
||||
push ebx
|
||||
push ecx
|
||||
mov ebx, [thread_count]
|
||||
shl ebx, BSF sizeof.APPDATA ; multiply by size
|
||||
; skip first process in the task table
|
||||
mov ecx, SLOT_BASE
|
||||
add ebx, ecx
|
||||
mov ecx, APPDATA_IDLE_THREAD
|
||||
.loop:
|
||||
add ecx, sizeof.APPDATA
|
||||
cmp [ecx + APPDATA.state], TSTATE_FREE
|
||||
jz @f ;skip empty slots
|
||||
cmp [ecx + APPDATA.tid], eax
|
||||
jz .pid_found
|
||||
@@:
|
||||
cmp ecx, ebx
|
||||
jb .loop
|
||||
add ecx, sizeof.APPDATA
|
||||
dec ebx
|
||||
jnz .loop
|
||||
|
||||
pop ecx
|
||||
pop ebx
|
||||
|
||||
@@ -48,7 +48,7 @@ endg
|
||||
|
||||
; This internal function acquires the lock for the global list.
|
||||
lock_timer_list:
|
||||
mov edx, [current_slot_idx]
|
||||
mov edx, [current_slot]
|
||||
@@:
|
||||
xor eax, eax
|
||||
lock cmpxchg [timer_list_owner], edx
|
||||
|
||||
@@ -2507,7 +2507,7 @@ dword-значение цвета 0x00RRGGBB
|
||||
* иначе eax = TID - идентификатор потока
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_CREATE_THREAD (51) /
|
||||
eax - SF_THREAD_CONTROL (51) /
|
||||
ebx - SSF_CREATE_THREAD (1), SSF_GET_CURR_THREAD_SLOT (2),
|
||||
SSF_GET_THREAD_PRIORITY (3), SSF_SET_THREAD_PRIORITY (4)
|
||||
|
||||
@@ -4098,6 +4098,9 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* подфункция 7 - запуск программы
|
||||
* подфункция 8 - удаление файла/папки
|
||||
* подфункция 9 - создание папки
|
||||
* подфункция 10 - переименование/перемещение
|
||||
* подфункция 11 - создание симлинка
|
||||
* подфункция 12 - чтение симлинка
|
||||
Для CD-приводов в связи с аппаратными ограничениями доступны
|
||||
только подфункции 0,1,5 и 7, вызов других подфункций завершится
|
||||
ошибкой с кодом 2.
|
||||
@@ -4112,7 +4115,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
[ebx] - SSF_READ_FILE (0), SSF_READ_FOLDER (1), SSF_CREATE_FILE (2),
|
||||
SSF_WRITE_FILE (3), SSF_SET_END (4), SSF_GET_INFO (5),
|
||||
SSF_SET_INFO (6), SSF_START_APP (7), SSF_DELETE (8),
|
||||
SSF_CREATE_FOLDER (9)
|
||||
SSF_CREATE_FOLDER (9), SSF_RENAME (10), SSF_CREATE_SYMLINK (11),
|
||||
SSF_READ_SYMLINK (12)
|
||||
======================================================================
|
||||
= Функция 70, подфункция 0 - чтение файла с поддержкой длинных имён. =
|
||||
======================================================================
|
||||
@@ -4464,6 +4468,62 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* Формирование нового пути отличается от общих правил:
|
||||
относительный путь относится к папке целевого файла (или папки),
|
||||
абсолютный путь считается от корня раздела.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_RENAME (10)
|
||||
======================================================================
|
||||
=========== Функция 70, подфункция 11 - создание симлинка. ===========
|
||||
======================================================================
|
||||
Параметры:
|
||||
* eax = 70 - номер функции
|
||||
* ebx = указатель на информационную структуру
|
||||
Формат информационной структуры:
|
||||
* +0: dword: 11 = номер подфункции
|
||||
* +4: dword: 0 (зарезервировано)
|
||||
* +8: dword: 0 (зарезервировано)
|
||||
* +12 = +0xC: dword: 0 (зарезервировано)
|
||||
* +16 = +0x10: dword: указатель на строку с целевым путём
|
||||
* +20 = +0x14: путь, правила формирования имён указаны в общем
|
||||
описании (путь ссылки)
|
||||
Возвращаемое значение:
|
||||
* eax = 0 - успешно, иначе код ошибки файловой системы
|
||||
* ebx разрушается
|
||||
Замечания:
|
||||
* Родительская папка должна существовать.
|
||||
* Для CD функция не поддерживается (возвращает код ошибки 2).
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_CREATE_SYMLINK (11)
|
||||
======================================================================
|
||||
============ Функция 70, подфункция 12 - чтение симлинка. ============
|
||||
======================================================================
|
||||
Параметры:
|
||||
* eax = 70 - номер функции
|
||||
* ebx = указатель на информационную структуру
|
||||
Формат информационной структуры:
|
||||
* +0: dword: 12 = номер подфункции
|
||||
* +4: dword: 0 (зарезервировано)
|
||||
* +8: dword: 0 (зарезервировано)
|
||||
* +12 = +0xC: dword: размер буфера в байтах
|
||||
* +16 = +0x10: dword: указатель на буфер для целевого пути
|
||||
* +20 = +0x14: путь, правила формирования имён указаны в общем
|
||||
описании (путь ссылки)
|
||||
Возвращаемое значение:
|
||||
* eax = 0 - успешно, иначе код ошибки файловой системы
|
||||
* ebx = число байт, записанных в буфер
|
||||
Замечания:
|
||||
* Функция не следует по симлинку; она читает целевой путь,
|
||||
на который указывает симлинк.
|
||||
* Целевой путь всегда завершается нулём, в том числе при обрезании;
|
||||
записывается не более (размер буфера - 1) байт пути.
|
||||
* Значение в ebx включает завершающий 0, как в подфункции 2
|
||||
функции 30.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_READ_SYMLINK (12)
|
||||
======================================================================
|
||||
========== Функция 71 - установить заголовок окна программы ==========
|
||||
======================================================================
|
||||
@@ -5059,8 +5119,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* eax = дескриптор фьютекса, 0 при ошибке
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_CREATE (0)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_CREATE (0)
|
||||
======================================================================
|
||||
============= Функция 77, подфункция 1, Удалить фьютекс. =============
|
||||
======================================================================
|
||||
@@ -5074,8 +5134,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* Ядро автоматически удаляет фьютексы при завершении процесса.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_DESTROY (1)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_DESTROY (1)
|
||||
======================================================================
|
||||
================= Функция 77, подфункция 2, Ожидать. =================
|
||||
======================================================================
|
||||
@@ -5091,8 +5151,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
-2 - контрольное значение фьютекса не соответствует
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_WAIT (2)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_WAIT (2)
|
||||
======================================================================
|
||||
================ Функция 77, подфункция 3, Разбудить. ================
|
||||
======================================================================
|
||||
@@ -5105,8 +5165,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* eax = количество разбуженых
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_WAKE (3)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_WAKE (3)
|
||||
======================================================================
|
||||
Замечания:
|
||||
* Подфункции 4-7 зарезервированы и сейчас возвращают -1.
|
||||
@@ -5128,8 +5188,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* Поддерживаются только pipe-дескрипторы.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_FILE_READ (10)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_READ (10)
|
||||
|
||||
======================================================================
|
||||
======== Функция 77, подфункция 11, Записать из буфера в файл. =======
|
||||
@@ -5148,8 +5208,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
* Поддерживаются только pipe-дескрипторы.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_FILE_WRITE (11)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_WRITE (11)
|
||||
|
||||
======================================================================
|
||||
=========== Функция 77, подфункция 13, Создать новый pipe. ===========
|
||||
@@ -5173,8 +5233,8 @@ Architecture Software Developer's Manual, Volume 3, Appendix B);
|
||||
- дескриптором записи.
|
||||
|
||||
---------------------- Константы для регистров: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_PIPE_CREATE (13)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_PIPE2 (13)
|
||||
|
||||
======================================================================
|
||||
========== Функция -1 - завершить выполнение потока/процесса =========
|
||||
|
||||
@@ -2492,7 +2492,7 @@ Returned value:
|
||||
* otherwise eax = TID - thread identifier
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_CREATE_THREAD (51)
|
||||
eax - SF_THREAD_CONTROL (51)
|
||||
ebx - SSF_CREATE_THREAD (1), SSF_GET_CURR_THREAD_SLOT (2),
|
||||
SSF_GET_THREAD_PRIORITY (3), SSF_SET_THREAD_PRIORITY (4)
|
||||
======================================================================
|
||||
@@ -4060,6 +4060,9 @@ Available subfunctions:
|
||||
* subfunction 7 - start application
|
||||
* subfunction 8 - delete file/folder
|
||||
* subfunction 9 - create folder
|
||||
* subfunction 10 - rename/move
|
||||
* subfunction 11 - create symlink
|
||||
* subfunction 12 - read symlink
|
||||
For CD-drives due to hardware limitations only subfunctions
|
||||
0,1,5 and 7 are available, other subfunctions return error
|
||||
with code 2.
|
||||
@@ -4073,7 +4076,8 @@ is called for corresponding device.
|
||||
[ebx] - SSF_READ_FILE (0), SSF_READ_FOLDER (1), SSF_CREATE_FILE (2),
|
||||
SSF_WRITE_FILE (3), SSF_SET_END (4), SSF_GET_INFO (5),
|
||||
SSF_SET_INFO (6), SSF_START_APP (7), SSF_DELETE (8),
|
||||
SSF_CREATE_FOLDER (9)
|
||||
SSF_CREATE_FOLDER (9), SSF_RENAME (10), SSF_CREATE_SYMLINK (11),
|
||||
SSF_READ_SYMLINK (12)
|
||||
======================================================================
|
||||
=== Function 70, subfunction 0 - read file with long names support. ==
|
||||
======================================================================
|
||||
@@ -4144,6 +4148,7 @@ Structure of block of data for folder entry (BDFE):
|
||||
and after archiving this bit is cleared - it can be useful
|
||||
for automatically creating of backup-archives as at writing
|
||||
this bit is usually set
|
||||
* bit 6 (mask 0x40): this is a symbolic link (currently only set by the ext driver).
|
||||
* +4: dword: encoding, equals to field +8 in the information structure
|
||||
* +8: 4*byte: time of file creation
|
||||
* +12 = +0xC: 4*byte: date of file creation
|
||||
@@ -4423,6 +4428,60 @@ Remarks:
|
||||
* New path forming differs from general rules:
|
||||
relative path relates to the target's parent folder,
|
||||
absolute path relates to the partition's root folder.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_RENAME (10)
|
||||
======================================================================
|
||||
=========== Function 70, subfunction 11 - create symlink. ============
|
||||
======================================================================
|
||||
Parameters:
|
||||
* eax = 70 - function number
|
||||
* ebx = pointer to the information structure
|
||||
Format of the information structure:
|
||||
* +0: dword: 11 = subfunction number
|
||||
* +4: dword: 0 (reserved)
|
||||
* +8: dword: 0 (reserved)
|
||||
* +12 = +0xC: dword: 0 (reserved)
|
||||
* +16 = +0x10: dword: pointer to the target path string
|
||||
* +20 = +0x14: path, general rules of names forming (link path)
|
||||
Returned value:
|
||||
* eax = 0 - success, otherwise file system error code
|
||||
* ebx destroyed
|
||||
Remarks:
|
||||
* The parent folder must already exist.
|
||||
* The function is not supported for CD (returns error code 2).
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_CREATE_SYMLINK (11)
|
||||
======================================================================
|
||||
============ Function 70, subfunction 12 - read symlink. =============
|
||||
======================================================================
|
||||
Parameters:
|
||||
* eax = 70 - function number
|
||||
* ebx = pointer to the information structure
|
||||
Format of the information structure:
|
||||
* +0: dword: 12 = subfunction number
|
||||
* +4: dword: 0 (reserved)
|
||||
* +8: dword: 0 (reserved)
|
||||
* +12 = +0xC: dword: buffer size in bytes
|
||||
* +16 = +0x10: dword: pointer to buffer for target path
|
||||
* +20 = +0x14: path, general rules of names forming (link path)
|
||||
Returned value:
|
||||
* eax = 0 - success, otherwise file system error code
|
||||
* ebx = number of bytes written to the buffer
|
||||
Remarks:
|
||||
* The function does not follow the symlink; it reads the target path
|
||||
that the symlink points to.
|
||||
* The target path is always terminated with 0, even when truncated;
|
||||
at most (buffer size - 1) path bytes are written.
|
||||
* The value returned in ebx includes the terminating 0, as in
|
||||
subfunction 2 of function 30.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FILE (70)
|
||||
[ebx] - SSF_READ_SYMLINK (12)
|
||||
======================================================================
|
||||
================== Function 71 - set window caption ==================
|
||||
======================================================================
|
||||
@@ -5273,8 +5332,8 @@ Returned value:
|
||||
* eax = futex handle, 0 on error
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_CREATE (0)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_CREATE (0)
|
||||
======================================================================
|
||||
========= Function 77, Subfunction 1, Destroy futex object ===========
|
||||
======================================================================
|
||||
@@ -5289,8 +5348,8 @@ Remarks:
|
||||
terminates.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_DESTROY (1)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_DESTROY (1)
|
||||
======================================================================
|
||||
=============== Function 77, Subfunction 2, Futex wait ===============
|
||||
======================================================================
|
||||
@@ -5306,8 +5365,8 @@ Returned value:
|
||||
-2 - futex control value doesn't match
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_WAIT (2)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_WAIT (2)
|
||||
======================================================================
|
||||
=============== Function 77, Subfunction 3, Futex wake ===============
|
||||
======================================================================
|
||||
@@ -5320,8 +5379,8 @@ Returned value:
|
||||
* eax = number of waiters that were woken up
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_WAKE (3)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FUTEX_WAKE (3)
|
||||
======================================================================
|
||||
Remarks:
|
||||
* Subfunctions 4-7 are reserved and currently return -1.
|
||||
@@ -5343,8 +5402,8 @@ Remarks:
|
||||
* Only pipe descriptors are supported.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_FILE_READ (10)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_READ (10)
|
||||
======================================================================
|
||||
=========== Function 77, Subfunction 11, Write to file. =============
|
||||
======================================================================
|
||||
@@ -5362,8 +5421,8 @@ Remarks:
|
||||
* Only pipe descriptors are supported.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_FILE_WRITE (11)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_WRITE (11)
|
||||
======================================================================
|
||||
========== Function 77, Subfunction 13, Create pipe. ================
|
||||
======================================================================
|
||||
@@ -5381,8 +5440,8 @@ Remarks:
|
||||
write handle.
|
||||
|
||||
---------------------- Constants for registers: ----------------------
|
||||
eax - SF_FUTEX (77)
|
||||
ebx - SSF_PIPE_CREATE (13)
|
||||
eax - SF_POSIX (77)
|
||||
ebx - SSF_FD_PIPE2 (13)
|
||||
======================================================================
|
||||
=== Function 80 - file system interface with parameter of encoding ===
|
||||
======================================================================
|
||||
|
||||
+1041
-72
File diff suppressed because it is too large.
Load diff
@@ -2405,11 +2405,12 @@ fat_Write:
|
||||
; hd_extend_file can return three error codes: FAT table error, device error or disk full.
|
||||
; First two cases are fatal errors, in third case we may write some data
|
||||
cmp al, ERROR_DISK_FULL
|
||||
jnz @f
|
||||
jnz .noWrite
|
||||
; correct number of bytes to write
|
||||
mov ecx, [edi+28]
|
||||
cmp ecx, ebx
|
||||
ja .length_ok
|
||||
.noWrite:
|
||||
push 0
|
||||
.ret:
|
||||
pop eax eax eax ecx ecx
|
||||
|
||||
@@ -182,10 +182,22 @@ proc file_system_is_operation_safe stdcall, inf_struct_ptr: dword
|
||||
|
||||
.case6:
|
||||
cmp dword [ebx], 6
|
||||
jnz .switch_none
|
||||
jnz .case11
|
||||
mov ecx, 32
|
||||
jmp .end_switch
|
||||
|
||||
.case11:
|
||||
cmp dword [ebx], 11
|
||||
jnz .case12
|
||||
stdcall is_string_userspace, edx
|
||||
jmp .ret
|
||||
|
||||
.case12:
|
||||
cmp dword [ebx], 12
|
||||
jnz .switch_none
|
||||
mov ecx, dword [ebx + 12]
|
||||
jmp .end_switch
|
||||
|
||||
.switch_none:
|
||||
cmp ecx, ecx
|
||||
jmp .ret
|
||||
|
||||
@@ -253,9 +253,10 @@ UTF16to8_string:
|
||||
|
||||
UTF16to8:
|
||||
; in:
|
||||
; eax = UTF-16 char
|
||||
; ax = UTF-16 char
|
||||
; edi -> buffer for UTF-8 char (increasing)
|
||||
; ecx = byte counter (decreasing)
|
||||
movzx eax, ax
|
||||
dec ecx
|
||||
js .ret
|
||||
cmp eax, 80h
|
||||
|
||||
@@ -193,7 +193,8 @@ align 4
|
||||
;--------------------------------------
|
||||
align 4
|
||||
@@:
|
||||
mov eax, [current_slot_idx]
|
||||
mov eax, [current_slot]
|
||||
mov eax, [eax + APPDATA.tid]
|
||||
mov [bgrlockpid], eax
|
||||
cmp [img_background], static_background_data
|
||||
jz .nomem
|
||||
@@ -241,7 +242,8 @@ nosb6:
|
||||
jnz nosb7
|
||||
cmp [bgrlock], 0
|
||||
jz .err
|
||||
mov eax, [current_slot_idx]
|
||||
mov eax, [current_slot]
|
||||
mov eax, [eax + APPDATA.tid]
|
||||
cmp [bgrlockpid], eax
|
||||
jnz .err
|
||||
mov eax, ecx
|
||||
|
||||
@@ -48,6 +48,10 @@ dtext:
|
||||
add esp, 28
|
||||
ret
|
||||
|
||||
.nomem:
|
||||
add esp, 40
|
||||
ret
|
||||
|
||||
.redirect:
|
||||
mov ebp, [edi]
|
||||
add edi, 8
|
||||
@@ -81,6 +85,8 @@ dtext:
|
||||
mov [esp+32], eax
|
||||
imul ebp, eax
|
||||
stdcall kernel_alloc, ebp
|
||||
test eax, eax
|
||||
jz .nomem
|
||||
mov ecx, ebp
|
||||
shr ecx, 2
|
||||
mov [esp+36], eax
|
||||
|
||||
@@ -1997,6 +1997,8 @@ align 4
|
||||
; esi - slot
|
||||
push eax ecx edx esi
|
||||
xchg eax, esi
|
||||
shl eax, BSF sizeof.APPDATA
|
||||
add eax, SLOT_BASE
|
||||
lea ecx, [esp + 12]
|
||||
mov edx, 1
|
||||
call read_process_memory
|
||||
|
||||
+17
-18
@@ -55,7 +55,6 @@ launcher_start db 1
|
||||
endg
|
||||
|
||||
max_processes = 255
|
||||
tss_step = 128 + 8192 ; tss & i/o - 65535 ports, * 256=557056*4
|
||||
|
||||
os_stack = os_data_l - gdts ; GDTs
|
||||
os_code = os_code_l - gdts
|
||||
@@ -389,7 +388,7 @@ high_code:
|
||||
mov edi, tss._io_map_0
|
||||
xor eax, eax
|
||||
not eax
|
||||
mov ecx, 8192/4
|
||||
mov ecx, IO_MAP_SIZE/4
|
||||
rep stosd ; access to 4096*8=65536 ports
|
||||
|
||||
mov ax, tss0
|
||||
@@ -410,7 +409,7 @@ high_code:
|
||||
stdcall alloc_kernel_space, 0x50000 ; FIXME check size
|
||||
mov [default_io_map], eax
|
||||
|
||||
add eax, 0x2000
|
||||
add eax, IO_MAP_SIZE
|
||||
mov [ipc_tmp], eax
|
||||
mov ebx, 0x1000
|
||||
|
||||
@@ -535,7 +534,7 @@ high_code:
|
||||
dec ecx
|
||||
jns @b
|
||||
|
||||
mov edx, SLOT_BASE + sizeof.APPDATA*1
|
||||
mov edx, APPDATA_IDLE_THREAD
|
||||
mov ebx, [os_stack_seg]
|
||||
add ebx, RING0_STACK_SIZE
|
||||
add ebx, [xsave_area_size]
|
||||
@@ -547,7 +546,7 @@ high_code:
|
||||
mov ecx, IDLE_PRIORITY
|
||||
call scheduler_add_thread
|
||||
|
||||
mov edx, SLOT_BASE + sizeof.APPDATA*2
|
||||
mov edx, APPDATA_OS_THREAD
|
||||
mov ebx, [os_stack_seg]
|
||||
call setup_os_slot
|
||||
mov dword [edx], 'OS'
|
||||
@@ -556,7 +555,7 @@ high_code:
|
||||
|
||||
mov [current_slot_idx], 2
|
||||
mov [thread_count], 2
|
||||
mov [current_slot], SLOT_BASE + sizeof.APPDATA*2
|
||||
mov [current_slot], APPDATA_OS_THREAD
|
||||
|
||||
; Move other CPUs to deep sleep, if it is useful
|
||||
uglobal
|
||||
@@ -848,15 +847,15 @@ include "detect/vortex86.inc" ; Vortex86 SoC detection code
|
||||
call reserve_irqs_ports
|
||||
|
||||
mov [SLOT_BASE + APPDATA.window], window_data
|
||||
mov [SLOT_BASE + sizeof.APPDATA + APPDATA.window], window_data + sizeof.WDATA
|
||||
mov [SLOT_BASE + sizeof.APPDATA*2 + APPDATA.window], window_data + sizeof.WDATA*2
|
||||
mov [APPDATA_IDLE_THREAD + APPDATA.window], background_window
|
||||
mov [APPDATA_OS_THREAD + APPDATA.window], window_data + sizeof.WDATA*2
|
||||
mov [window_data + WDATA.thread], SLOT_BASE
|
||||
mov [window_data + sizeof.WDATA + WDATA.thread], SLOT_BASE + sizeof.APPDATA
|
||||
mov [window_data + sizeof.WDATA*2 + WDATA.thread], SLOT_BASE + sizeof.APPDATA*2
|
||||
mov [background_window + WDATA.thread], APPDATA_IDLE_THREAD
|
||||
mov [window_data + sizeof.WDATA*2 + WDATA.thread], APPDATA_OS_THREAD
|
||||
|
||||
call init_display
|
||||
mov eax, [def_cursor]
|
||||
mov [window_data + sizeof.WDATA + WDATA.cursor], eax
|
||||
mov [background_window + WDATA.cursor], eax
|
||||
mov [window_data + sizeof.WDATA*2 + WDATA.cursor], eax
|
||||
|
||||
; PRINT CPU FREQUENCY
|
||||
@@ -953,14 +952,14 @@ include "detect/vortex86.inc" ; Vortex86 SoC detection code
|
||||
; Protect I/O permission map
|
||||
|
||||
mov esi, [default_io_map]
|
||||
stdcall map_page, esi, [SLOT_BASE + sizeof.APPDATA + APPDATA.io_map], PG_READ
|
||||
stdcall map_page, esi, [APPDATA_IDLE_THREAD + APPDATA.io_map], PG_READ
|
||||
add esi, 0x1000
|
||||
stdcall map_page, esi, [SLOT_BASE + sizeof.APPDATA + APPDATA.io_map + 4], PG_READ
|
||||
stdcall map_page, esi, [APPDATA_IDLE_THREAD + APPDATA.io_map + 4], PG_READ
|
||||
|
||||
stdcall map_page, tss._io_map_0, \
|
||||
[SLOT_BASE + sizeof.APPDATA + APPDATA.io_map], PG_READ
|
||||
[APPDATA_IDLE_THREAD + APPDATA.io_map], PG_READ
|
||||
stdcall map_page, tss._io_map_1, \
|
||||
[SLOT_BASE + sizeof.APPDATA + APPDATA.io_map + 4], PG_READ
|
||||
[APPDATA_IDLE_THREAD + APPDATA.io_map + 4], PG_READ
|
||||
|
||||
; SET KEYBOARD PARAMETERS
|
||||
mov al, 0xf6 ; reset keyboard, scan enabled
|
||||
@@ -1865,7 +1864,7 @@ sysfn_shutdown: ; 18.9 = system shutdown
|
||||
; out: Z/z -- is/not kernel thread
|
||||
is_kernel_thread:
|
||||
mov eax, [eax + APPDATA.process]
|
||||
cmp eax, [SLOT_BASE + 2*sizeof.APPDATA + APPDATA.process] ; OS
|
||||
cmp eax, [APPDATA_OS_THREAD + APPDATA.process] ; OS
|
||||
ret
|
||||
;------------------------------------------------------------------------------
|
||||
sysfn_terminate: ; 18.2 = TERMINATE
|
||||
@@ -2065,7 +2064,7 @@ sysfn_zmodif:
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
sysfn_getidletime: ; 18.4 = GET IDLETIME
|
||||
mov eax, [SLOT_BASE + sizeof.APPDATA + APPDATA.cpu_usage]
|
||||
mov eax, [APPDATA_IDLE_THREAD + APPDATA.cpu_usage]
|
||||
mov [esp + SYSCALL_STACK.eax], eax
|
||||
ret
|
||||
;------------------------------------------------------------------------------
|
||||
@@ -2825,7 +2824,7 @@ no_mark_system_shutdown:
|
||||
align 4
|
||||
noshutdown:
|
||||
mov eax, [thread_count] ; termination
|
||||
mov ebx, SLOT_BASE + sizeof.APPDATA + APPDATA.state
|
||||
mov ebx, APPDATA_IDLE_THREAD + APPDATA.state
|
||||
mov esi, 1
|
||||
;--------------------------------------
|
||||
align 4
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2024. All rights reserved. ;;
|
||||
;; Copyright (C) KolibriOS team 2004-2026. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; IPv4.INC ;;
|
||||
@@ -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
|
||||
@@ -765,9 +790,9 @@ ipv4_output_raw:
|
||||
push ebx ; push the mac
|
||||
push ax
|
||||
|
||||
inc [IPv4_packets_tx + 4*edi]
|
||||
inc [IPv4_packets_tx + edi]
|
||||
mov ax, ETHER_PROTO_IPv4
|
||||
mov ebx, [net_device_list + 4*edi]
|
||||
mov ebx, [net_device_list + edi]
|
||||
mov ecx, [esp + 6 + 4]
|
||||
add ecx, sizeof.IPv4_header
|
||||
mov edx, esp
|
||||
@@ -951,7 +976,7 @@ endp
|
||||
; edi = device number*4 ;
|
||||
; ;
|
||||
; DESTROYED: ;
|
||||
; ecx ;
|
||||
; ebx, ecx ;
|
||||
; ;
|
||||
;-----------------------------------------------------------------;
|
||||
align 4
|
||||
@@ -964,8 +989,11 @@ ipv4_route:
|
||||
cmp eax, 0xffffffff
|
||||
je .broadcast
|
||||
|
||||
; 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
|
||||
@@ -978,9 +1006,58 @@ ipv4_route:
|
||||
cmp edi, 4*NET_DEVICES_MAX
|
||||
jb .loop
|
||||
|
||||
mov eax, [IPv4_gateway + 4] ; TODO: let user (or a user space daemon) configure default route
|
||||
; no on-link match, find first device with a gateway
|
||||
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
|
||||
jmp .loopback ; no gateway found, fall-back to loopback device
|
||||
|
||||
.found_gw:
|
||||
mov eax, [IPv4_gateway + edi]
|
||||
jmp .got_it
|
||||
|
||||
.broadcast:
|
||||
mov edi, 4 ; TODO: same as above
|
||||
; broadcast: we will do our best without full routing..
|
||||
|
||||
; find the first non loopback device which has an active link without IP address
|
||||
mov edi, 4 ; skip loopback device
|
||||
.bc_loop1:
|
||||
mov ebx, [net_device_list + edi]
|
||||
test ebx, ebx
|
||||
jz @f
|
||||
cmp [ebx + NET_DEVICE.link_state], 0
|
||||
je @f
|
||||
cmp [IPv4_address + edi], 0
|
||||
je .got_it
|
||||
@@:
|
||||
add edi, 4
|
||||
cmp edi, 4*NET_DEVICES_MAX
|
||||
jb .bc_loop1
|
||||
|
||||
; If there is no such device, try the one with active link and IP address
|
||||
mov edi, 4 ; skip loopback device
|
||||
.bc_loop2:
|
||||
mov ebx, [net_device_list + edi]
|
||||
test ebx, ebx
|
||||
jz @f
|
||||
cmp [ebx + NET_DEVICE.link_state], 0
|
||||
jne .got_it
|
||||
@@:
|
||||
add edi, 4
|
||||
cmp edi, 4*NET_DEVICES_MAX
|
||||
jb .bc_loop2
|
||||
; jmp .loopback ; no gateway found, fall-back to loopback device
|
||||
|
||||
.loopback:
|
||||
xor edi, edi ; nowhere to go for now.. route it to the loopback device
|
||||
|
||||
.got_it:
|
||||
DEBUGF DEBUG_NETWORK_VERBOSE, "IPv4_route: %u\n", edi
|
||||
test edx, edx
|
||||
@@ -1002,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
|
||||
|
||||
|
||||
|
||||
;-----------------------------------------------------------------;
|
||||
|
||||
@@ -198,6 +198,10 @@ ends
|
||||
|
||||
SOCKET_STRUCT_SIZE = 4096 ; in bytes
|
||||
|
||||
if sizeof.STREAM_SOCKET > SOCKET_STRUCT_SIZE
|
||||
err "STREAM_SOCKET does not fit in SOCKET_STRUCT_SIZE"
|
||||
end if
|
||||
|
||||
SOCKET_QUEUE_SIZE = 10 ; maximum number of incoming packets queued for 1 socket
|
||||
; the incoming packet queue for sockets is placed in the socket struct itself, at this location from start
|
||||
SOCKET_QUEUE_LOCATION = (SOCKET_STRUCT_SIZE - SOCKET_QUEUE_SIZE*sizeof.socket_queue_entry - sizeof.queue)
|
||||
@@ -780,8 +784,6 @@ socket_close:
|
||||
|
||||
cmp [eax + SOCKET.Protocol], IP_PROTO_TCP
|
||||
jne .free
|
||||
test [eax + SOCKET.state], SS_ISCONNECTED
|
||||
jz @f
|
||||
test [eax + SOCKET.state], SS_ISDISCONNECTING
|
||||
jnz @f
|
||||
call tcp_disconnect
|
||||
@@ -1649,7 +1651,7 @@ socket_ring_create:
|
||||
mov esi, eax
|
||||
|
||||
push edx
|
||||
stdcall create_ring_buffer, SOCKET_BUFFER_SIZE, PG_SWR
|
||||
stdcall create_ring_buffer_sparse, SOCKET_BUFFER_SIZE, PG_SWR
|
||||
pop edx
|
||||
test eax, eax
|
||||
jz .fail
|
||||
@@ -2126,11 +2128,11 @@ socket_free:
|
||||
mov ebx, eax
|
||||
cmp [eax + STREAM_SOCKET.rcv.start_ptr], 0
|
||||
je @f
|
||||
stdcall free_kernel_space, [eax + STREAM_SOCKET.rcv.start_ptr]
|
||||
stdcall kernel_free, [eax + STREAM_SOCKET.rcv.start_ptr]
|
||||
@@:
|
||||
cmp [ebx + STREAM_SOCKET.snd.start_ptr], 0
|
||||
je @f
|
||||
stdcall free_kernel_space, [ebx + STREAM_SOCKET.snd.start_ptr]
|
||||
stdcall kernel_free, [ebx + STREAM_SOCKET.snd.start_ptr]
|
||||
@@:
|
||||
mov eax, ebx
|
||||
.no_stream:
|
||||
|
||||
@@ -118,7 +118,7 @@ SS_MORETOCOME = 0x4000
|
||||
SS_BLOCKED = 0x8000
|
||||
|
||||
|
||||
SOCKET_BUFFER_SIZE = 4096*8 ; must be 4096*(power of 2) where 'power of 2' is at least 8
|
||||
SOCKET_BUFFER_SIZE = 4096*32 ; must be 4096*(power of 2) where 'power of 2' is at least 8
|
||||
MAX_backlog = 20 ; maximum backlog for stream sockets
|
||||
|
||||
; Error Codes
|
||||
@@ -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
|
||||
|
||||
@@ -355,9 +355,14 @@ endl
|
||||
DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Got window scale option\n"
|
||||
or [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
|
||||
|
||||
; remember the peer's scale factor; it is applied to SND_SCALE when the
|
||||
; connection is established (together with our RCV_SCALE)
|
||||
lodsb
|
||||
mov [ebx + TCP_SOCKET.SND_SCALE], al
|
||||
;;;;; TODO
|
||||
cmp al, TCP_max_winshift
|
||||
jbe .wscale_capped
|
||||
mov al, TCP_max_winshift
|
||||
.wscale_capped:
|
||||
mov [ebx + TCP_SOCKET.requested_s_scale], al
|
||||
|
||||
@@:
|
||||
jmp .opt_loop
|
||||
@@ -1417,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:
|
||||
|
||||
|
||||
@@ -320,12 +320,12 @@ tcp_respond:
|
||||
stosb
|
||||
mov eax, SOCKET_BUFFER_SIZE
|
||||
sub eax, [esi + STREAM_SOCKET.rcv.size]
|
||||
cmp eax, TCP_max_win
|
||||
mov cl, [esi + TCP_SOCKET.RCV_SCALE]
|
||||
shr eax, cl ; scale first, then clamp to the
|
||||
cmp eax, TCP_max_win ; 16-bit field maximum
|
||||
jbe .lessthanmax
|
||||
mov eax, TCP_max_win
|
||||
.lessthanmax:
|
||||
mov cl, [esi + TCP_SOCKET.RCV_SCALE]
|
||||
shr eax, cl
|
||||
|
||||
xchg al, ah
|
||||
stosw ; window
|
||||
@@ -488,7 +488,7 @@ tcp_set_persist:
|
||||
; Start/restart persistence timer.
|
||||
|
||||
tcpt_rangeset [eax + TCP_SOCKET.timer_persist], ebx, TCP_time_pers_min, TCP_time_pers_max
|
||||
or [ebx + TCP_SOCKET.timer_flags], timer_flag_persist
|
||||
or [eax + TCP_SOCKET.timer_flags], timer_flag_persist
|
||||
pop ebx
|
||||
|
||||
cmp [eax + TCP_SOCKET.t_rxtshift], TCP_max_rxtshift
|
||||
|
||||
@@ -111,13 +111,13 @@ proc tcp_timer_640ms
|
||||
|
||||
DEBUGF DEBUG_NETWORK_VERBOSE, "socket %x: Keepalive expired\n", eax
|
||||
|
||||
cmp [eax + TCP_SOCKET.state], TCPS_ESTABLISHED
|
||||
ja .dont_kill
|
||||
cmp [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED
|
||||
jae .dont_kill
|
||||
|
||||
push eax
|
||||
push [eax + SOCKET.NextPtr]
|
||||
call tcp_disconnect
|
||||
pop eax
|
||||
jmp .loop
|
||||
jmp .check_only
|
||||
|
||||
.dont_kill:
|
||||
test [eax + SOCKET.options], SO_KEEPALIVE
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -148,9 +148,10 @@ ReadNoteByte:
|
||||
push esi
|
||||
|
||||
mov eax, [pidProcessNote]
|
||||
call pid_to_slot
|
||||
call pid_to_thread
|
||||
test eax, eax
|
||||
jz .failed
|
||||
|
||||
lea ecx, [esp+12]
|
||||
mov edx, 1
|
||||
mov esi, [memAdrNote]
|
||||
|
||||
@@ -125,7 +125,7 @@ SF_STYLE_SETTINGS=48
|
||||
SSF_SET_FONT_SIZE=12
|
||||
SF_APM=49
|
||||
SF_SET_WINDOW_SHAPE=50
|
||||
SF_CREATE_THREAD=51
|
||||
SF_THREAD_CONTROL=51
|
||||
SSF_CREATE_THREAD=1
|
||||
SSF_GET_CURR_THREAD_SLOT=2
|
||||
SSF_GET_THREAD_PRIORITY=3
|
||||
@@ -281,14 +281,14 @@ SF_NETWORK_PROTOCOL=76
|
||||
SSF_ARP_DEL_ENTRY=50005h
|
||||
SSF_ARP_SEND_ANNOUNCE=50006h
|
||||
SSF_ARP_CONFLICTS_COUNT=50007h
|
||||
SF_FUTEX=77
|
||||
SSF_CREATE=0
|
||||
SSF_DESTROY=1
|
||||
SSF_WAIT=2
|
||||
SSF_WAKE=3
|
||||
SSF_FILE_READ=10
|
||||
SSF_FILE_WRITE=11
|
||||
SSF_PIPE_CREATE=13
|
||||
SF_POSIX=77
|
||||
SSF_FUTEX_CREATE=0
|
||||
SSF_FUTEX_DESTROY=1
|
||||
SSF_FUTEX_WAIT=2
|
||||
SSF_FUTEX_WAKE=3
|
||||
SSF_FD_READ=10
|
||||
SSF_FD_WRITE=11
|
||||
SSF_FD_PIPE2=13
|
||||
|
||||
; File system errors:
|
||||
FSERR_SUCCESS=0
|
||||
|
||||
@@ -1111,7 +1111,7 @@ end if
|
||||
mov dword [edx+8],ebx
|
||||
mov dword [edx+4],ecx
|
||||
mov dword [edx],Kolibri_ThreadFinish
|
||||
mov eax,SF_CREATE_THREAD
|
||||
mov eax,SF_THREAD_CONTROL
|
||||
mov ebx,1
|
||||
mov ecx,@Kolibri@ThreadMain$qpvt1
|
||||
int 0x40
|
||||
|
||||
Submodule
+1
Submodule programs/cmm added at 86b0211da7.
@@ -1,6 +0,0 @@
|
||||
if tup.getconfig("NO_CMM") ~= "" then return end
|
||||
if tup.getconfig("LANG") == "ru_RU"
|
||||
then C_LANG = "LANG_RUS"
|
||||
else C_LANG = "LANG_ENG" -- this includes default case without config
|
||||
end
|
||||
tup.rule("app_plus.c", "c-- /D=$(C_LANG) /OPATH=%o %f" .. tup.getconfig("KPACK_CMD"), "app_plus.com")
|
||||
@@ -1,18 +0,0 @@
|
||||
|
||||
struct sysdir
|
||||
{
|
||||
char name[64];
|
||||
char path[64];
|
||||
} sysdir;
|
||||
|
||||
|
||||
:int SetAdditionalSystemDirectory(dword tName, tPath)
|
||||
{
|
||||
int i;
|
||||
strcpy(#sysdir.name, tName);
|
||||
strcpy(#sysdir.path, tPath);
|
||||
$mov eax, 30
|
||||
$mov ebx, 3
|
||||
ECX = #sysdir;
|
||||
$int 0x40
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
#define MEMSIZE 1024*60
|
||||
|
||||
#include "..\lib\gui.h"
|
||||
#include "..\lib\obj\proc_lib.h"
|
||||
#include "..\lib\patterns\simple_open_dialog.h"
|
||||
#include "..\lib\patterns\restart_process.h"
|
||||
#include "added_sysdir.c"
|
||||
|
||||
//===================================================//
|
||||
// //
|
||||
// DATA //
|
||||
// //
|
||||
//===================================================//
|
||||
|
||||
#define WINW 570
|
||||
#define WINH 300
|
||||
#define CONX 28 //content X pos
|
||||
#define CONY 25 //content Y pos
|
||||
|
||||
char default_dir[] = "/sys";
|
||||
od_filter filter2;
|
||||
|
||||
#define BTN_MANUAL_SEARCH 10
|
||||
#define BTN_OPEN_ANYWAY 11
|
||||
|
||||
#define APP_PLUS_INI_PATH "/sys/settings/app_plus.ini"
|
||||
|
||||
//===================================================//
|
||||
// //
|
||||
// TRANSLATIONS //
|
||||
// //
|
||||
//===================================================//
|
||||
|
||||
#ifdef LANG_RUS
|
||||
?define WINDOW_TITLE_TEXT "Внимание!"
|
||||
?define CONTENT_HEADER_TEXT "KolibriOS работает в режиме дискеты"
|
||||
?define DESCRIPTION_TEXT "Многие приложения сейчас недоступны.
|
||||
|
||||
Причина в том, что не смонтирован дополнительный системный
|
||||
каталог. Но вы можете найти и задать его вручную. Его название
|
||||
'kolibrios'. Вы также можете загрузить latest-dirstr.7z через
|
||||
WebView и найти его внутри."
|
||||
?define MANUALLY_BUTTON_TEXT "Указать папку /kolibrios/..."
|
||||
?define OPEN_ANYWAY_BUTTON_TEXT "Запустить APP+ (некоторые программы будут недоступны)"
|
||||
#else
|
||||
?define WINDOW_TITLE_TEXT "Warning!"
|
||||
?define CONTENT_HEADER_TEXT "KolibriOS is running in floppy mode"
|
||||
?define DESCRIPTION_TEXT "A lot of apps aren't available.
|
||||
|
||||
The reason is that additional system directory is not mounted.
|
||||
But you can find and set it manually. Its name is 'kolibrios'.
|
||||
You can also download latest-dirstr.7z via WebView and find
|
||||
it inside."
|
||||
?define MANUALLY_BUTTON_TEXT "Choose /kolibrios/ folder..."
|
||||
?define OPEN_ANYWAY_BUTTON_TEXT "Open APP+ anyway (some programs won't be available)"
|
||||
#endif
|
||||
|
||||
//===================================================//
|
||||
// //
|
||||
// CODE //
|
||||
// //
|
||||
//===================================================//
|
||||
|
||||
void main()
|
||||
{
|
||||
if (param) {
|
||||
SetAdditionalSystemDirectory("kolibrios", #param+1);
|
||||
ExitProcess();
|
||||
}
|
||||
|
||||
WaitAutosearch();
|
||||
CheckKosMounted();
|
||||
|
||||
o_dialog.type = 2;
|
||||
#define NO_DLL_INIT
|
||||
load_dll(Proc_lib, #OpenDialog_init,0);
|
||||
OpenDialog_init stdcall (#o_dialog);
|
||||
active_button_id = BTN_MANUAL_SEARCH;
|
||||
|
||||
loop() switch(@WaitEvent())
|
||||
{
|
||||
case evButton:
|
||||
EventButton(GetButtonID());
|
||||
break;
|
||||
case evKey:
|
||||
@GetKeyScancode();
|
||||
if (AL == SCAN_CODE_ENTER) {
|
||||
EventButton(active_button_id);
|
||||
} else if (AL == SCAN_CODE_TAB) {
|
||||
active_button_id = active_button_id-10^1 + 10;
|
||||
DrawButtons();
|
||||
}
|
||||
break;
|
||||
|
||||
case evReDraw:
|
||||
draw_window();
|
||||
}
|
||||
}
|
||||
|
||||
void draw_window()
|
||||
{
|
||||
sc.get();
|
||||
DefineAndDrawWindow(screen.w-WINW/2, 100, WINW, WINH+skin_h, 0x34, sc.work, WINDOW_TITLE_TEXT,0);
|
||||
draw_icon_16w(CONX+2, CONY-3, 5);
|
||||
WriteTextB(CONX+27+2,CONY+2,0x81,MixColors(sc.work, 0xB92234,220),CONTENT_HEADER_TEXT);
|
||||
WriteTextB(CONX+27,CONY,0x81,0xB92234,CONTENT_HEADER_TEXT);
|
||||
WriteTextLines(CONX,CONY+42,0x90,sc.work_text,DESCRIPTION_TEXT,20);
|
||||
DrawButtons();
|
||||
}
|
||||
|
||||
void DrawButtons()
|
||||
{
|
||||
DrawStandartCaptButton(CONX, WINH-CONY-58, BTN_MANUAL_SEARCH, MANUALLY_BUTTON_TEXT);
|
||||
DrawStandartCaptButton(CONX, WINH-CONY-22, BTN_OPEN_ANYWAY, OPEN_ANYWAY_BUTTON_TEXT);
|
||||
}
|
||||
|
||||
void CheckKosMounted()
|
||||
{
|
||||
if (dir_exists("/kolibrios"))
|
||||
{
|
||||
if (file_exists(APP_PLUS_INI_PATH)) EventOpenApp();
|
||||
ExitProcess();
|
||||
}
|
||||
}
|
||||
|
||||
void WaitAutosearch()
|
||||
{
|
||||
while (CheckProcessExists("SEARCHAP")) pause(2);
|
||||
}
|
||||
|
||||
//===================================================//
|
||||
// //
|
||||
// EVENTS //
|
||||
// //
|
||||
//===================================================//
|
||||
|
||||
void EventManualSearch()
|
||||
{
|
||||
OpenDialog_start stdcall (#o_dialog);
|
||||
if (o_dialog.status) SetAdditionalSystemDirectory("kolibrios", #openfile_path+1);
|
||||
pause(3);
|
||||
CheckKosMounted();
|
||||
}
|
||||
|
||||
void EventOpenApp()
|
||||
{
|
||||
if (RunProgram("/sys/syspanel", APP_PLUS_INI_PATH) < 0) {
|
||||
notify("'App+ cannot start because\n/sys/syspanel does not exist' -E");
|
||||
}
|
||||
}
|
||||
|
||||
void EventButton(dword id)
|
||||
{
|
||||
if (id==CLOSE_BTN) ExitProcess();
|
||||
else if (id==BTN_MANUAL_SEARCH) EventManualSearch();
|
||||
else if (id==BTN_OPEN_ANYWAY) {
|
||||
EventOpenApp();
|
||||
ExitProcess();
|
||||
}
|
||||
}
|
||||
|
||||
stop:
|
||||
@@ -1,6 +0,0 @@
|
||||
@c-- /D=LANG_ENG app_plus.c
|
||||
@del *.
|
||||
@rename *.com *.
|
||||
@del warning.txt
|
||||
@pause
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
@c-- /D=LANG_RUS app_plus.c
|
||||
@del *.
|
||||
@rename *.com *.
|
||||
@del warning.txt
|
||||
@pause
|
||||
@@ -1,6 +0,0 @@
|
||||
if tup.getconfig("NO_CMM") ~= "" then return end
|
||||
if tup.getconfig("LANG") == "ru_RU"
|
||||
then C_LANG = "LANG_RUS"
|
||||
else C_LANG = "LANG_ENG" -- this includes default case without config
|
||||
end
|
||||
tup.rule("appearance.c", "c-- /D=AUTOBUILD /D=$(C_LANG) /OPATH=%o %f" .. tup.getconfig("KPACK_CMD"), "appearance.com")
|
||||
@@ -1,472 +0,0 @@
|
||||
//11.03.12 - start!
|
||||
|
||||
#define MEMSIZE 1024*70
|
||||
#include "../lib/mem.h"
|
||||
#include "../lib/strings.h"
|
||||
#include "../lib/io.h"
|
||||
#include "../lib/list_box.h"
|
||||
#include "../lib/gui.h"
|
||||
|
||||
#include "../lib/obj/box_lib.h"
|
||||
#include "../lib/obj/proc_lib.h"
|
||||
#include "../lib/obj/libini.h"
|
||||
|
||||
#include "../lib/patterns/select_list.h"
|
||||
#include "../lib/patterns/simple_open_dialog.h"
|
||||
#include "../lib/patterns/restart_process.h"
|
||||
|
||||
dword fmas;
|
||||
|
||||
#include "ui_elements_preview.h"
|
||||
#include "const.h"
|
||||
|
||||
//===================================================//
|
||||
// //
|
||||
// DATA //
|
||||
// //
|
||||
//===================================================//
|
||||
|
||||
int active_skin=-1, active_wallpaper=-1, active_screensaver=-1;
|
||||
|
||||
checkbox optionbox_stretch = { T_CHECKBOX_STRETCH, false };
|
||||
checkbox optionbox_tiled = { T_CHECKBOX_TILED, false };
|
||||
checkbox optionbox_auto = { T_CHECKBOX_AUTO, true };
|
||||
|
||||
char ss_available[200];
|
||||
|
||||
collection list;
|
||||
|
||||
|
||||
//===================================================//
|
||||
// //
|
||||
// CODE //
|
||||
// //
|
||||
//===================================================//
|
||||
|
||||
void main()
|
||||
{
|
||||
int id, i;
|
||||
load_dll(boxlib, #box_lib_init,0);
|
||||
load_dll(libini, #lib_init,1);
|
||||
load_dll(Proc_lib, #OpenDialog_init,0);
|
||||
OpenDialog_init stdcall (#o_dialog);
|
||||
|
||||
GetIniSettings();
|
||||
|
||||
tabs.add(#t_skins, #EventTabSkinsClick);
|
||||
tabs.add(#t_wallpapers, #EventTabWallpappersClick);
|
||||
tabs.add(#t_screensaver, #EventTabScreensaverClick);
|
||||
tabs.draw_active_tab();
|
||||
|
||||
SetEventMask(EVM_REDRAW + EVM_KEY + EVM_BUTTON + EVM_MOUSE + EVM_MOUSE_FILTER);
|
||||
loop() switch(WaitEvent())
|
||||
{
|
||||
case evMouse:
|
||||
SelectList_ProcessMouse();
|
||||
if (tabs.active_tab == TAB_SCREENSAVERS) {
|
||||
scrollbar_h_mouse stdcall (#ss_timeout);
|
||||
if (ss_timeout.redraw) {
|
||||
draw_timeout();
|
||||
ss_timeout.redraw = false; //reset flag
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case evButton:
|
||||
id=GetButtonID();
|
||||
if (id==1) EventExit();
|
||||
tabs.click(id);
|
||||
if (tabs.active_tab == TAB_SKINS) {
|
||||
checkbox1.click(id);
|
||||
spinbox1.click(id);
|
||||
}
|
||||
if (tabs.active_tab == TAB_WALLPAPERS) {
|
||||
if (id==BTN_SELECT_WALLP_FOLDER) EventSelectWallpFolder();
|
||||
if (optionbox_stretch.click(id)) EventSetWallpMode(1,0,0);
|
||||
if (optionbox_tiled.click(id)) EventSetWallpMode(0,1,0);
|
||||
if (optionbox_auto.click(id)) EventSetWallpMode(0,0,1);
|
||||
}
|
||||
if (tabs.active_tab == TAB_SCREENSAVERS) {
|
||||
if (id==BTN_TEST_SCREENSAVER) EventOpenFile();
|
||||
if (id==BTN_SET_SCREENSAVER) EventSetSs();
|
||||
}
|
||||
break;
|
||||
|
||||
case evKey:
|
||||
GetKeys();
|
||||
if (select_list.ProcessKey(key_scancode)) { EventApply(); break; }
|
||||
if (key_scancode==SCAN_CODE_ENTER) { EventOpenFile(); break; }
|
||||
if (key_scancode==SCAN_CODE_DEL) { EventDeleteFile(); break; }
|
||||
if (key_scancode==SCAN_CODE_TAB) {
|
||||
id = tabs.active_tab+1;
|
||||
if(id==3)id=0;
|
||||
tabs.click(id + tabs.base_id);
|
||||
break;
|
||||
}
|
||||
for (i=select_list.cur_y+1; i<select_list.count; i++)
|
||||
{
|
||||
id = list.get(i) + strrchr(list.get(i), '/');
|
||||
if (ESBYTE[id]==key_ascii) || (ESBYTE[id]==key_ascii-32)
|
||||
{
|
||||
select_list.cur_y = i - 1;
|
||||
select_list.KeyDown();
|
||||
EventApply();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case evReDraw:
|
||||
draw_window();
|
||||
}
|
||||
}
|
||||
|
||||
void draw_window()
|
||||
{
|
||||
sc.get();
|
||||
DefineAndDrawWindow(screen.w-WIN_W-9/2,80,WIN_W+9,WIN_H+4+skin_h,0x74,sc.work,WINDOW_HEADER,0);
|
||||
|
||||
DrawBar(0, 0, WIN_W, PANEL_H-2, sc.work); //top
|
||||
DrawBar(0, PANEL_H-2, LP-2, WIN_H-PANEL_H-LP+4, EDX); //left
|
||||
DrawBar(LIST_W+LP+20, PANEL_H-2, WIN_W-LIST_W-26, WIN_H-PANEL_H-LP+4, EDX); //right
|
||||
DrawBar(0, WIN_H-LP+2, WIN_W, LP-2, EDX); //bottom
|
||||
|
||||
tabs.draw();
|
||||
draw_icon_16w(tabs.x + TAB_P, LP+5, 17);
|
||||
draw_icon_16w(sizeof(t_skins)-1*8 + TAB_P + TAB_P + tabs.x, LP+5, 6);
|
||||
draw_icon_16w(sizeof(t_wallpapers)+sizeof(t_skins)-2*8 + TAB_P + TAB_P + TAB_P + tabs.x, LP+5, 61);
|
||||
|
||||
if (tabs.active_tab == TAB_SKINS)
|
||||
{
|
||||
DrawFrame(RIGHTx, PANEL_H+5, RIGHTw, RIGHTh, T_UI_PREVIEW);
|
||||
DrawUiElementsPreview(RIGHTx+20, PANEL_H+5, RIGHTh);
|
||||
}
|
||||
if (tabs.active_tab == TAB_WALLPAPERS)
|
||||
{
|
||||
DrawFrame(RIGHTx, PANEL_H+5, 180, 105, T_PICTURE_MODE);
|
||||
optionbox_stretch.draw(RIGHTx+14, PANEL_H+25);
|
||||
optionbox_tiled.draw(RIGHTx+14, PANEL_H+52);
|
||||
optionbox_auto.draw(RIGHTx+14, PANEL_H+79);
|
||||
DrawStandartCaptButton(RIGHTx, PANEL_H+130, BTN_SELECT_WALLP_FOLDER, T_SELECT_FOLDER);
|
||||
}
|
||||
if (tabs.active_tab == TAB_SCREENSAVERS)
|
||||
{
|
||||
draw_timeout();
|
||||
ss_timeout.line_col = sc.line;
|
||||
ss_timeout.frnt_col = sc.work;
|
||||
scrollbar_h_draw stdcall (#ss_timeout);
|
||||
DrawRectangle(RIGHTx, RIGHTy+25, RIGHTw-20, 15, sc.line);
|
||||
ESI = DrawStandartCaptButton(RIGHTx, PANEL_H + 65, BTN_TEST_SCREENSAVER, T_SS_PREVIEW);
|
||||
DrawStandartCaptButton(RIGHTx+ESI, PANEL_H + 65, BTN_SET_SCREENSAVER, T_SS_SET);
|
||||
}
|
||||
|
||||
$push select_list.cur_y
|
||||
SelectList_Init(
|
||||
LP,
|
||||
PANEL_H,
|
||||
LIST_W,
|
||||
WIN_H - LP - PANEL_H
|
||||
);
|
||||
$pop select_list.cur_y
|
||||
|
||||
SelectList_Draw();
|
||||
SelectList_DrawBorder();
|
||||
}
|
||||
|
||||
void draw_timeout()
|
||||
{
|
||||
miniprintf(#param, T_SS_TIMEOUT, ss_timeout.position+1);
|
||||
WriteTextWithBg(RIGHTx, PANEL_H, 0xD0, sc.work_text, #param, sc.work);
|
||||
}
|
||||
|
||||
void add_filesnames_into_the_list()
|
||||
{
|
||||
int j;
|
||||
for (j=0; j<select_list.count; j++) {
|
||||
miniprintf(#param,"%s/",#folder_path);
|
||||
strcat(#param, io.dir.position(ESDWORD[j*4+fmas]));
|
||||
list.add(#param);
|
||||
}
|
||||
}
|
||||
|
||||
void Open_Dir()
|
||||
{
|
||||
int j;
|
||||
dword ext;
|
||||
select_list.ClearList();
|
||||
|
||||
if (io.dir.buffer) free(io.dir.buffer);
|
||||
io.dir.load(#folder_path,DIR_ONLYREAL);
|
||||
|
||||
if (fmas) free(fmas);
|
||||
fmas = malloc(io.dir.count * 4);
|
||||
|
||||
for (j=0; j<io.dir.count; j++)
|
||||
{
|
||||
strncpy(#param, io.dir.position(j), PATHLEN);
|
||||
strlwr(#param);
|
||||
ext = #param + strrchr(#param,'.');
|
||||
if (tabs.active_tab==TAB_SKINS) {
|
||||
if (!streq(ext,"skn")) continue;
|
||||
}
|
||||
if (tabs.active_tab==TAB_WALLPAPERS) {
|
||||
if (!streq(ext,"png")) && (!streq(ext,"jpg"))
|
||||
&& (!streq(ext,"jpeg")) && (!streq(ext,"bmp"))
|
||||
&& (!streq(ext,"gif")) continue;
|
||||
}
|
||||
ESDWORD[select_list.count*4 + fmas] = j;
|
||||
select_list.count++;
|
||||
}
|
||||
sort_by_name(0, select_list.count-1);
|
||||
|
||||
list.drop();
|
||||
//save current item for tab change
|
||||
//add default item
|
||||
if(tabs.active_tab == TAB_SKINS)
|
||||
{
|
||||
select_list.count++;
|
||||
list.add(#default_skin);
|
||||
add_filesnames_into_the_list();
|
||||
if (active_skin==-1) && (ESBYTE[#previous_skin])
|
||||
{
|
||||
for (j=0; j<select_list.count; j++) {
|
||||
if (streq(list.get(j), #previous_skin)) {
|
||||
active_skin = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
select_list.cur_y = active_skin;
|
||||
} else {
|
||||
select_list.count++;
|
||||
list.add(#default_wallp);
|
||||
add_filesnames_into_the_list();
|
||||
if (active_wallpaper==-1) && (ESBYTE[#previous_wallp]=='\\')
|
||||
{
|
||||
for (j=0; j<select_list.count; j++) {
|
||||
if (streq(list.get(j), #previous_wallp+4)) {
|
||||
active_wallpaper = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
select_list.cur_y = active_wallpaper;
|
||||
}
|
||||
|
||||
if (!select_list.count) notify(T_NO_FILES);
|
||||
if (select_list.cur_y>SL_VISIBLE) {
|
||||
select_list.first = -SL_VISIBLE/2 + select_list.cur_y;
|
||||
}
|
||||
select_list.CheckDoesValuesOkey();
|
||||
if (LIST_W) draw_window();
|
||||
}
|
||||
|
||||
void SelectList_DrawLine(dword i)
|
||||
{
|
||||
int draw_y = i*SELECT_LIST_ITEMH+PANEL_H;
|
||||
int i_abs = select_list.first + i;
|
||||
dword text_color = 0xFFFfff;
|
||||
dword bg_color = 0x000000;
|
||||
char filename_buf[PATHLEN];
|
||||
char* filename = #filename_buf;
|
||||
|
||||
strcpy(filename, list.get(i_abs));
|
||||
if (EAX = strrchr(filename,'/')) filename += EAX;
|
||||
if (ESBYTE[filename]=='T') && (ESBYTE[filename+1]=='_') filename+=2;
|
||||
EAX = math.min(strrchr(filename,'.')-1, LIST_W - 24 / 8);
|
||||
if(EAX) ESBYTE[filename+EAX] = '\0';
|
||||
|
||||
//save current item for tab change
|
||||
switch(tabs.active_tab) {
|
||||
CASE TAB_SKINS:
|
||||
active_skin = select_list.cur_y;
|
||||
if (!i_abs) filename = T_DEFAULT;
|
||||
BREAK;
|
||||
CASE TAB_WALLPAPERS:
|
||||
active_wallpaper = select_list.cur_y;
|
||||
if (!i_abs) filename = T_DEFAULT;
|
||||
BREAK;
|
||||
CASE TAB_SCREENSAVERS:
|
||||
active_screensaver = select_list.cur_y;
|
||||
if (!i_abs) filename = T_NO_SS;
|
||||
}
|
||||
|
||||
if (select_list.cur_y == i_abs) {
|
||||
text_color = sc.button;
|
||||
bg_color = sc.button_text;
|
||||
}
|
||||
DrawBar(select_list.x, draw_y, LIST_W, SELECT_LIST_ITEMH, text_color);
|
||||
WriteText(select_list.x+12,draw_y+select_list.text_y,select_list.font_type,bg_color, filename);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GetIniSettings()
|
||||
{
|
||||
ini.section = "style";
|
||||
ini.GetString("default_skin", #default_skin, PATHLEN, 0);
|
||||
ini.GetString("default_wallp", #default_wallp, PATHLEN, 0);
|
||||
ini.GetString("skin", #previous_skin, PATHLEN, 0);
|
||||
ini.GetString("bg_param", #previous_wallp, PATHLEN, 0);
|
||||
|
||||
ini.section = "screensaver";
|
||||
ss_timeout.position = ini.GetInt("timeout", 10) - 1;
|
||||
ini.GetString("available", #ss_available, sizeof(ss_available), 0);
|
||||
ini.GetString("program", #previous_ss, PATHLEN, 0);
|
||||
}
|
||||
|
||||
//===================================================//
|
||||
// //
|
||||
// EVENTS //
|
||||
// //
|
||||
//===================================================//
|
||||
|
||||
void EventTabSkinsClick()
|
||||
{
|
||||
miniprintf(#folder_path, "%s/res/skins", get_real_kolibrios_path());
|
||||
Open_Dir();
|
||||
}
|
||||
|
||||
void EventTabWallpappersClick()
|
||||
{
|
||||
if (opendir_path) {
|
||||
strcpy(#folder_path, #opendir_path);
|
||||
} else {
|
||||
miniprintf(#folder_path, "%s/res/wallpapers", get_real_kolibrios_path());
|
||||
}
|
||||
Open_Dir();
|
||||
}
|
||||
|
||||
void EventTabScreensaverClick()
|
||||
{
|
||||
dword j;
|
||||
char ssmas[sizeof(ss_available)];
|
||||
list.drop();
|
||||
select_list.ClearList();
|
||||
|
||||
select_list.count++;
|
||||
list.add("");
|
||||
|
||||
strcpy(#ssmas, #ss_available);
|
||||
do {
|
||||
j = strrchr(#ssmas, '|');
|
||||
if (ssmas[j]=='/') {
|
||||
strcpy(#param, #ssmas + j);
|
||||
} else {
|
||||
miniprintf(#param, "/sys/%s", #ssmas + j);
|
||||
}
|
||||
list.add(#param);
|
||||
ESBYTE[#ssmas + j - 1] = '\0';
|
||||
select_list.count++;
|
||||
} while (j);
|
||||
|
||||
if (active_screensaver == -1) && (ESBYTE[#previous_ss]) {
|
||||
for (j=0; j<select_list.count; j++) {
|
||||
if (strstr(list.get(j), #previous_ss)) active_screensaver = j;
|
||||
}
|
||||
}
|
||||
select_list.cur_y = active_screensaver;
|
||||
|
||||
if (LIST_W) draw_window();
|
||||
}
|
||||
|
||||
void EventDeleteFile()
|
||||
{
|
||||
if (select_list.cur_y) DeleteFile(list.get(select_list.cur_y)); //no not delete default
|
||||
Open_Dir();
|
||||
EventApply();
|
||||
}
|
||||
|
||||
void EventSelectWallpFolder()
|
||||
{
|
||||
o_dialog.type = 2; //select folder
|
||||
OpenDialog_start stdcall (#o_dialog);
|
||||
if (o_dialog.status) EventTabWallpappersClick();
|
||||
}
|
||||
|
||||
void EventSetWallpMode(dword _stretch, _titled, _auto)
|
||||
{
|
||||
optionbox_stretch.checked = _stretch;
|
||||
optionbox_tiled.checked = _titled;
|
||||
optionbox_auto.checked = _auto;
|
||||
optionbox_tiled.redraw();
|
||||
optionbox_stretch.redraw();
|
||||
optionbox_auto.redraw();
|
||||
EventApply();
|
||||
}
|
||||
|
||||
void EventApply()
|
||||
{
|
||||
char kivparam[4096+10];
|
||||
dword file_name = list.get(select_list.cur_y);
|
||||
if (tabs.active_tab==TAB_SKINS)
|
||||
{
|
||||
strcpy(#cur_skin_path, list.get(select_list.cur_y));
|
||||
SetSystemSkin(#cur_skin_path);
|
||||
MoveSize(OLD, OLD, OLD, WIN_H+4+GetSkinHeight());
|
||||
}
|
||||
if (tabs.active_tab==TAB_WALLPAPERS)
|
||||
{
|
||||
SelectList_Draw();
|
||||
miniprintf(#kivparam, "\\S__%s", list.get(select_list.cur_y));
|
||||
if (optionbox_tiled.checked) || (!select_list.cur_y) kivparam[1]='T';
|
||||
if (optionbox_auto.checked) {
|
||||
file_name += strrchr(file_name, '/');
|
||||
if (ESBYTE[file_name] == 'T') && (ESBYTE[file_name+1] == '_') {
|
||||
kivparam[1]='T';
|
||||
}
|
||||
}
|
||||
RunProgram("/sys/media/kiv", #kivparam);
|
||||
}
|
||||
if (tabs.active_tab==TAB_SCREENSAVERS)
|
||||
{
|
||||
SelectList_Draw();
|
||||
}
|
||||
}
|
||||
|
||||
void EventOpenFile()
|
||||
{
|
||||
switch (tabs.active_tab) {
|
||||
case TAB_SKINS:
|
||||
RunProgram("/sys/skincfg", list.get(select_list.cur_y));
|
||||
break;
|
||||
case TAB_WALLPAPERS:
|
||||
RunProgram("/sys/media/kiv", list.get(select_list.cur_y));
|
||||
break;
|
||||
case TAB_SCREENSAVERS:
|
||||
if(select_list.cur_y) {
|
||||
KillProcessByName("@ss", MULTIPLE);
|
||||
RunProgram(list.get(select_list.cur_y), "@ss");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventExit()
|
||||
{
|
||||
if (get_real_kolibrios_path()) && (ESBYTE[#cur_skin_path]) {
|
||||
ini.section = "style";
|
||||
ini.SetString("skin", #cur_skin_path, strlen(#cur_skin_path));
|
||||
}
|
||||
ExitProcess();
|
||||
}
|
||||
|
||||
void EventSetSs()
|
||||
{
|
||||
dword cur_ss = list.get(select_list.cur_y);
|
||||
ini.section = "screensaver";
|
||||
ini.SetString("program", cur_ss, strlen(cur_ss));
|
||||
ini.SetInt("timeout", ss_timeout.position+1);
|
||||
RestartProcessByName("/sys/@ss", MULTIPLE);
|
||||
}
|
||||
|
||||
stop:
|
||||
|
||||
char folder_path[PATHLEN];
|
||||
char cur_skin_path[PATHLEN];
|
||||
|
||||
char default_skin[PATHLEN];
|
||||
char default_wallp[PATHLEN];
|
||||
|
||||
char previous_skin[PATHLEN];
|
||||
char previous_wallp[PATHLEN];
|
||||
char previous_ss[PATHLEN];
|
||||
@@ -1,5 +0,0 @@
|
||||
@c-- /D=LANG_ENG appearance.c
|
||||
@del *.
|
||||
@rename *.com *.
|
||||
@del warning.txt
|
||||
if not exist appearance ( @pause )
|
||||
@@ -1,5 +0,0 @@
|
||||
@c-- /D=LANG_RUS appearance.c
|
||||
@del *.
|
||||
@rename *.com *.
|
||||
@del warning.txt
|
||||
if not exist appearance ( @pause )
|
||||
@@ -1,106 +0,0 @@
|
||||
#ifdef LANG_RUS
|
||||
char t_skins[] = " Стиль окон";
|
||||
char t_wallpapers[] = " Обои";
|
||||
char t_screensaver[] = " Скринсейвер";
|
||||
?define WINDOW_HEADER "Настройки оформления"
|
||||
?define T_SELECT_FOLDER "Выбрать папку"
|
||||
?define T_PICTURE_MODE " Положение картинки "
|
||||
?define T_CHECKBOX_STRETCH "Растянуть"
|
||||
?define T_CHECKBOX_TILED "Замостить"
|
||||
?define T_CHECKBOX_AUTO "Автоматически"
|
||||
?define T_UPDATE_DOCK "Обновлять Dock-панель"
|
||||
?define T_NO_FILES "'Поддерживаемые файлы не найдены' -E"
|
||||
?define T_UI_PREVIEW " Пример компонентов "
|
||||
?define T_SS_TIMEOUT "Интервал в минутах: %i "
|
||||
?define T_SS_PREVIEW "Просмотр"
|
||||
?define T_SS_SET "Установить"
|
||||
?define T_NO_SS "[Выключен]"
|
||||
?define T_DEFAULT "[По умолчанию]"
|
||||
#else
|
||||
char t_skins[] = " Skins";
|
||||
char t_wallpapers[] = " Wallpapers";
|
||||
char t_screensaver[] = " Screensaver";
|
||||
?define WINDOW_HEADER "Appearance"
|
||||
?define T_SELECT_FOLDER "Select folder"
|
||||
?define T_PICTURE_MODE " Picture Mode "
|
||||
?define T_CHECKBOX_STRETCH "Stretch"
|
||||
?define T_CHECKBOX_TILED "Tiled"
|
||||
?define T_CHECKBOX_AUTO "Auto"
|
||||
?define T_UPDATE_DOCK "Update Dock"
|
||||
?define T_NO_FILES "'No supported files were found' -E"
|
||||
?define T_UI_PREVIEW " Components Preview "
|
||||
?define T_SS_TIMEOUT "Wait in minutes: %i "
|
||||
?define T_SS_PREVIEW "View"
|
||||
?define T_SS_SET "Set"
|
||||
?define T_NO_SS "[Disable]"
|
||||
?define T_DEFAULT "[Default]"
|
||||
#endif
|
||||
|
||||
#define WIN_W 560
|
||||
#define WIN_H 445
|
||||
#define LIST_W 260
|
||||
#define PANEL_H 50
|
||||
#define LP 6 //LIST_PADDING
|
||||
#define SL_VISIBLE WIN_H - PANEL_H - LP / SELECT_LIST_ITEMH
|
||||
|
||||
#define RIGHTx LP + LIST_W + TAB_P + 30
|
||||
#define RIGHTy PANEL_H
|
||||
#define RIGHTw WIN_W - RIGHTx - LP - TAB_P
|
||||
#define RIGHTh 215
|
||||
|
||||
enum {
|
||||
TAB_SKINS,
|
||||
TAB_WALLPAPERS,
|
||||
TAB_SCREENSAVERS
|
||||
};
|
||||
|
||||
enum {
|
||||
BASE_TAB_BUTTON_ID=3,
|
||||
BTN_SELECT_WALLP_FOLDER=10,
|
||||
BTN_TEST_SCREENSAVER,
|
||||
BTN_SET_SCREENSAVER
|
||||
};
|
||||
|
||||
_ini ini = { "/sys/settings/system.ini" };
|
||||
|
||||
char default_dir[] = "/sys";
|
||||
od_filter filter2 = { 8, "TXT\0\0" };
|
||||
|
||||
_tabs tabs = { -sizeof(t_skins)-sizeof(t_wallpapers)-sizeof(t_screensaver)
|
||||
-3*8+WIN_W - TAB_P / 2, LP, NULL, BASE_TAB_BUTTON_ID };
|
||||
|
||||
scroll_bar ss_timeout = { RIGHTw-19,RIGHTx,15,RIGHTy+25,0,3,89,10,0,0xFFFfff,
|
||||
0xBBBbbb,0xeeeeee};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void sort_by_name(int a, b) // for the first call: a = 0, b = sizeof(mas) - 1
|
||||
{
|
||||
int j;
|
||||
int isn = a;
|
||||
if (a >= b) return;
|
||||
for (j = a; j <= b; j++) {
|
||||
if (strcmpi(io.dir.position(ESDWORD[j*4+fmas]), io.dir.position(ESDWORD[b*4+fmas]))<=0) {
|
||||
ESDWORD[isn*4+fmas] >< ESDWORD[j*4+fmas];
|
||||
isn++;
|
||||
}
|
||||
}
|
||||
sort_by_name(a, isn-2);
|
||||
sort_by_name(isn, b);
|
||||
}
|
||||
|
||||
dword get_real_kolibrios_path()
|
||||
{
|
||||
char real_kolibrios_path[256];
|
||||
if (!dir_exists("/kolibrios")) return 0;
|
||||
SetCurDir("/kolibrios");
|
||||
GetCurDir(#real_kolibrios_path, sizeof(real_kolibrios_path));
|
||||
return #real_kolibrios_path;
|
||||
}
|
||||
|
||||
void SelectList_LineChanged()
|
||||
{
|
||||
EventApply();
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
|
||||
checkbox checkbox1 = { "Checkbox", true };
|
||||
more_less_box spinbox1 = { 23, 0, 999, "SpinBox" };
|
||||
edit_box edit_cmm = {180,NULL,NULL,0xffffff,0x94AECE,0xFFFfff,0xffffff,
|
||||
0x10000000,sizeof(param)-2,#param,0, 0b};
|
||||
char st_str[16];
|
||||
edit_box edit_st = {180,NULL,NULL,0xffffff,0x94AECE,0xFFFfff,0xffffff,
|
||||
0x10000000,sizeof(st_str)-2,#st_str,0, 0b};
|
||||
|
||||
|
||||
void DrawUiElementsPreview(dword x,y,h)
|
||||
{
|
||||
incn y2;
|
||||
spinbox1.draw(x, y2.set(y+30));
|
||||
WriteText(x, y2.inc(30), 0x90, sc.work_text, "C-- Edit");
|
||||
DrawEditBoxPos(x, y2.inc(20), #edit_cmm);
|
||||
WriteText(x, y2.inc(35), 0x90, sc.work_text, "Standard Edit");
|
||||
DrawStEditBoxPos(x, y2.inc(20), #edit_st);
|
||||
DrawStandartCaptButton(x, y+h-40, GetFreeButtonId(), "Button1");
|
||||
DrawStandartCaptButton(x+100, y+h-40, GetFreeButtonId(), "Button2");
|
||||
}
|
||||
|
||||
:void DrawStEditBoxPos(dword x,y, edit_box_pointer)
|
||||
{
|
||||
dword c_inactive = MixColors(sc.line, sc.work, 128);
|
||||
dword c_active = MixColors(sc.line, 0, 128);
|
||||
ESI = edit_box_pointer;
|
||||
ESI.edit_box.left = x;
|
||||
ESI.edit_box.top = y;
|
||||
ESI.edit_box.border_color = c_inactive;
|
||||
ESI.edit_box.focus_border_color = c_active;
|
||||
edit_box_draw stdcall (edit_box_pointer);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
if tup.getconfig("NO_CMM") ~= "" then return end
|
||||
if tup.getconfig("LANG") == "ru_RU"
|
||||
then C_LANG = "LANG_RUS"
|
||||
else C_LANG = "LANG_ENG" -- this includes default case without config
|
||||
end
|
||||
tup.rule("barscfg.c", "c-- /D=$(C_LANG) /OPATH=%o %f" .. tup.getconfig("KPACK_CMD"), "barscfg.com")
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 400 B |
Binary file not shown.
Binary file not shown.
Loaded 100 of 665 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user