Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1626 → Rev 1627

/drivers/ddk/Makefile
34,15 → 34,26
string/_strncmp.S \
string/_strncpy.S \
string/_strnlen.S \
string/bcmp.S \
string/bcopy.S \
string/bzero.S \
string/index.S \
string/memchr.S \
string/memcmp.S \
string/memcpy.S \
string/memcmp.S \
string/memmove.S \
string/memset.S \
string/rindex.S \
string/strcat.S \
string/strchr.S \
string/strcmp.S \
string/strcpy.S \
string/strlen.S \
string/strncat.S \
string/strncmp.S \
string/strncpy.S \
string/strncmp.S \
string/strlen.S
string/strnlen.S \
string/strrchr.S
 
 
 
64,7 → 75,7
$(LD) -shared -s --out-implib $@ --output-def core.def -o core.dll core.o
%.o: %.S Makefile
$(AS) -o $@ $<
$(CC) $(CFLAGS) -o $@ $<
 
%.o: %.c Makefile
$(CC) $(CFLAGS) -o $@ $<
/drivers/ddk/string/_memmove.S
1,67 → 1,60
# _memmove() Author: Kees J. Bot 2 Jan 1994
/* _memmove() Author: Kees J. Bot */
/* 2 Jan 1994 */
 
# void *_memmove(void *s1, const void *s2, size_t n)
# Copy a chunk of memory. Handle overlap.
/* void *_memmove(void *s1, const void *s2, size_t n) */
/* Copy a chunk of memory. Handle overlap. */
/* */
 
.intel_syntax
#include "asm.h"
 
.globl __memmove, __memcpy
ENTRY(_memmove)
push %ebp
movl %esp, %ebp
push %esi
push %edi
movl 8(%ebp), %edi /* String s1 */
movl 12(%ebp), %esi /* String s2 */
movl 16(%ebp), %ecx /* Length */
movl %edi, %eax
subl %esi, %eax
cmpl %ecx, %eax
jb downwards /* if (s2 - s1) < n then copy downwards */
LABEL(_memcpy)
cld /* Clear direction bit: upwards */
cmpl $16, %ecx
jb upbyte /* Don't bother being smart with short arrays */
movl %esi, %eax
orl %edi, %eax
testb $1, %al
jne upbyte /* Bit 0 set, use byte copy */
testb $2, %al
jne upword /* Bit 1 set, use word copy */
uplword:
shrdl $2, %ecx, %eax /* Save low 2 bits of ecx in eax */
shrl $2, %ecx
 
.text
rep movsl /* Copy longwords. */
shldl $2, %eax, %ecx /* Restore excess count */
upword:
shrl $1, %ecx
 
.align 16
__memmove:
push ebp
mov ebp, esp
 
push esi
push edi
 
mov edi, [ebp+8] # String s1
mov esi, [ebp+12] # String s2
mov ecx, [ebp+16] # Length
 
mov eax, edi
sub eax, esi
cmp eax, ecx
jb downwards # if (s2 - s1) < n then copy downwards
__memcpy:
cld # Clear direction bit: upwards
cmp ecx, 16
jb upbyte # Don't bother being smart with short arrays
 
mov eax, esi
or eax, edi
testb al, 1
jnz upbyte # Bit 0 set, use byte copy
 
testb al, 2
 
jnz upword # Bit 1 set, use word copy
uplword:
shrd eax, ecx, 2 # Save low 2 bits of ecx in eax
shr ecx, 2
rep movsd # Copy longwords.
shld ecx, eax, 2 # Restore excess count
upword:
shr ecx, 1
rep movsw # Copy words
adc ecx, ecx # One more byte?
rep movsw /* Copy words */
adcl %ecx, %ecx /* One more byte? */
upbyte:
rep movsb # Copy bytes
rep movsb /* Copy bytes */
done:
mov eax, [ebp+8] # Absolutely noone cares about this value
pop edi
pop esi
pop ebp
movl 8(%ebp), %eax /* Absolutely noone cares about this value */
pop %edi
pop %esi
pop %ebp
ret
 
# Handle bad overlap by copying downwards, don't bother to do word copies.
/* Handle bad overlap by copying downwards, don't bother to do word copies. */
downwards:
std /* Set direction bit: downwards */
leal -1(%esi,%ecx,1), %esi
leal -1(%edi,%ecx,1), %edi
 
downwards:
std # Set direction bit: downwards
lea esi, [esi+ecx-1]
lea edi, [edi+ecx-1]
rep movsb # Copy bytes
rep movsb /* Copy bytes */
cld
jmp done
/drivers/ddk/string/_strncat.S
1,43 → 1,40
# _strncat() Author: Kees J. Bot
# 1 Jan 1994
# char *_strncat(char *s1, const char *s2, size_t edx)
# Append string s2 to s1.
#
/* _strncat() Author: Kees J. Bot */
/* 1 Jan 1994 */
 
.intel_syntax
/* char *_strncat(char *s1, const char *s2, size_t edx) */
/* Append string s2 to s1. */
/* */
#include "asm.h"
 
.global __strncat
ENTRY(_strncat)
push %ebp
movl %esp, %ebp
push %esi
push %edi
movl 8(%ebp), %edi /* String s1 */
movl $-1, %ecx
xorb %al, %al /* Null byte */
cld
 
.text
.align 16
__strncat:
push ebp
mov ebp, esp
push esi
push edi
mov edi, [ebp+8] # String s1
mov ecx, -1
xorb al, al # Null byte
cld
repne
scasb # Look for the zero byte in s1
dec edi # Back one up (and clear 'Z' flag)
push edi # Save end of s1
mov edi, [12+ebp] # edi = string s2
mov ecx, edx # Maximum count
repne
scasb # Look for the end of s2
repne scasb /* Look for the zero byte in s1 */
decl %edi /* Back one up (and clear 'Z' flag) */
push %edi /* Save end of s1 */
movl 12(%ebp), %edi /* edi = string s2 */
movl %edx, %ecx /* Maximum count */
 
repne scasb /* Look for the end of s2 */
jne no0
inc ecx # Exclude null byte
no0: sub edx, ecx # Number of bytes in s2
mov ecx, edx
mov esi, [12+ebp] # esi = string s2
pop edi # edi = end of string s1
rep
movsb # Copy bytes
stosb # Add a terminating null
mov eax, [8+ebp] # Return s1
pop edi
pop esi
pop ebp
incl %ecx /* Exclude null byte */
no0:
subl %ecx, %edx /* Number of bytes in s2 */
movl %edx, %ecx
movl 12(%ebp), %esi /* esi = string s2 */
pop %edi /* edi = end of string s1 */
 
rep movsb /* Copy bytes */
stosb /* Add a terminating null */
movl 8(%ebp), %eax /* Return s1 */
pop %edi
pop %esi
pop %ebp
ret
/drivers/ddk/string/_strncmp.S
1,44 → 1,34
# strncmp() Author: Kees J. Bot 1 Jan 1994
/* strncmp() Author: Kees J. Bot */
/* 1 Jan 1994 */
 
# int strncmp(const char *s1, const char *s2, size_t ecx)
# Compare two strings.
#
/* int strncmp(const char *s1, const char *s2, size_t ecx) */
/* Compare two strings. */
/* */
#include "asm.h"
 
.intel_syntax
 
.globl __strncmp
 
.text
.align 16
__strncmp:
push ebp
mov ebp, esp
 
push esi
push edi
 
test ecx, ecx # Max length is zero?
ENTRY(_strncmp)
push %ebp
movl %esp, %ebp
push %esi
push %edi
testl %ecx, %ecx /* Max length is zero? */
je done
 
mov esi, [ebp+8] # esi = string s1
mov edi, [ebp+12] # edi = string s2
movl 8(%ebp), %esi /* esi = string s1 */
movl 12(%ebp), %edi /* edi = string s2 */
cld
compare:
cmpsb # Compare two bytes
cmpsb /* Compare two bytes */
jne done
 
cmpb [esi-1], 0 # End of string?
cmpb $0, -1(%esi) /* End of string? */
je done
 
dec ecx # Length limit reached?
decl %ecx /* Length limit reached? */
jne compare
done:
seta al # al = (s1 > s2)
setb ah # ah = (s1 < s2)
subb al, ah
movsx eax, al # eax = (s1 > s2) - (s1 < s2), i.e. -1, 0, 1
 
pop edi
pop esi
pop ebp
seta %al /* al = (s1 > s2) */
setb %ah /* ah = (s1 < s2) */
subb %ah, %al
movsbl %al, %eax /* eax = (s1 > s2) - (s1 < s2), i.e. -1, 0, 1 */
pop %edi
pop %esi
pop %ebp
ret
/drivers/ddk/string/_strncpy.S
1,27 → 1,22
# _strncpy() Author: Kees J. Bot
# 1 Jan 1994
/* _strncpy() Author: Kees J. Bot */
/* 1 Jan 1994 */
 
# char *_strncpy(char *s1, const char *s2, size_t ecx)
# Copy string s2 to s1.
#
/* char *_strncpy(char *s1, const char *s2, size_t ecx) */
/* Copy string s2 to s1. */
/* */
#include "asm.h"
 
.intel_syntax
ENTRY(_strncpy)
movl 12(%ebp), %edi /* edi = string s2 */
xorb %al, %al /* Look for a zero byte */
movl %ecx, %edx /* Save maximum count */
cld
 
.text
.globl __strncpy
.align 16
repne scasb /* Look for end of s2 */
subl %ecx, %edx /* Number of bytes in s2 including null */
xchgl %edx, %ecx
movl 12(%ebp), %esi /* esi = string s2 */
movl 8(%ebp), %edi /* edi = string s1 */
 
__strncpy:
mov edi, [ebp+12] # edi = string s2
xorb al, al # Look for a zero byte
mov edx, ecx # Save maximum count
cld
repne
scasb # Look for end of s2
sub edx, ecx # Number of bytes in s2 including null
xchg ecx, edx
mov esi, [ebp+12] # esi = string s2
mov edi, [ebp+8] # edi = string s1
rep
movsb # Copy bytes
rep movsb /* Copy bytes */
ret
/drivers/ddk/string/_strnlen.S
1,30 → 1,27
# _strnlen() Author: Kees J. Bot 1 Jan 1994
/* _strnlen() Author: Kees J. Bot */
/* 1 Jan 1994 */
 
# size_t _strnlen(const char *s, size_t ecx)
# Return the length of a string.
/* size_t _strnlen(const char *s, size_t ecx) */
/* Return the length of a string. */
/* */
#include "asm.h"
 
.intel_syntax
ENTRY(_strnlen)
push %ebp
movl %esp, %ebp
push %edi
movl 8(%ebp), %edi /* edi = string */
xorb %al, %al /* Look for a zero byte */
movl %ecx, %edx /* Save maximum count */
cmpb $1, %cl /* 'Z' bit must be clear if ecx = 0 */
cld
 
.globl __strnlen
 
.text
.align 16
__strnlen:
push ebp
mov ebp, esp
push edi
mov edi, [ebp+8] # edi = string
xorb al, al # Look for a zero byte
mov edx, ecx # Save maximum count
cmpb cl, 1 # 'Z' bit must be clear if ecx = 0
cld
repne
scasb # Look for zero
repne scasb /* Look for zero */
jne no0
inc ecx # Don't count zero byte
incl %ecx /* Don't count zero byte */
no0:
mov eax, edx
sub eax, ecx # Compute bytes scanned
pop edi
pop ebp
movl %edx, %eax
subl %ecx, %eax /* Compute bytes scanned */
pop %edi
pop %ebp
ret
/drivers/ddk/string/asm.h
0,0 → 1,61
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)asm.h 5.5 (Berkeley) 5/7/91
*/
 
#ifndef _I386_ASM_H_
#define _I386_ASM_H_
 
#define _C_LABEL(x) _ ## x
#define _ASM_LABEL(x) x
 
/* allow overriding entrypoint alignment */
#if !defined(_ALIGN_TEXT)
# define _ALIGN_TEXT .align 16
#endif
 
#define _ENTRY(x) \
.text; _ALIGN_TEXT; .globl x; x:
 
#define _LABEL(x) \
.globl x; x:
 
#define ENTRY(y) _ENTRY(_C_LABEL(y))
#define NENTRY(y) _ENTRY(_C_LABEL(y))
#define ASENTRY(y) _ENTRY(_ASM_LABEL(y))
#define LABEL(y) _LABEL(_C_LABEL(y))
#define END(y) .size y, . - y
 
#define IMPORT(sym) \
.extern _C_LABEL(sym)
 
#endif /* !_I386_ASM_H_ */
/drivers/ddk/string/bcmp.S
0,0 → 1,27
/* bcmp() Author: Kees J. Bot */
/* 2 Jan 1994 */
 
/* int bcmp(const void *s1, const void *s2, size_t n) */
/* Compare two chunks of memory. */
/* This is a BSD routine that escaped from the kernel. Don't use. */
/* (Alas it is not without some use, it reports the number of bytes */
/* after the bytes that are equal. So it can't be simply replaced.) */
/* */
#include "asm.h"
 
ENTRY(bcmp)
push %ebp
movl %esp, %ebp
push 16(%ebp)
push 12(%ebp)
push 8(%ebp)
call _C_LABEL(memcmp) /* Let memcmp do the work */
testl %eax, %eax
je equal
subl 8(%ebp), %edx /* Memcmp was nice enough to leave "esi" in edx */
decl %edx /* Number of bytes that are equal */
movl 16(%ebp), %eax
subl %edx, %eax /* Number of bytes that are unequal */
equal:
leave
ret
/drivers/ddk/string/bcopy.S
0,0 → 1,14
/* bcopy() Author: Kees J. Bot */
/* 2 Jan 1994 */
 
/* void bcopy(const void *s1, void *s2, size_t n) */
/* Copy a chunk of memory. Handle overlap. */
/* This is a BSD routine that escaped from the kernel. Don't use. */
/* */
#include "asm.h"
 
ENTRY(bcopy)
movl 4(%esp), %eax /* Exchange string arguments */
xchgl 8(%esp), %eax
movl %eax, 4(%esp)
jmp _C_LABEL(_memmove) /* Call the proper routine */
/drivers/ddk/string/bzero.S
0,0 → 1,18
/* bzero() Author: Kees J. Bot */
/* 2 Jan 1994 */
 
/* void bzero(void *s, size_t n) */
/* Set a chunk of memory to zero. */
/* This is a BSD routine that escaped from the kernel. Don't use. */
/* */
#include "asm.h"
 
ENTRY(bzero)
push %ebp
movl %esp, %ebp
push 12(%ebp) /* Size */
push $0 /* Zero */
push 8(%ebp) /* String */
call _C_LABEL(memset) /* Call the proper routine */
leave
ret
/drivers/ddk/string/index.S
0,0 → 1,11
/* index() Author: Kees J. Bot */
/* 2 Jan 1994 */
 
/* char *index(const char *s, int c) */
/* Look for a character in a string. Has suffered from a hostile */
/* takeover by strchr(). */
/* */
#include "asm.h"
 
ENTRY(index)
jmp _C_LABEL(strchr)
/drivers/ddk/string/memchr.S
0,0 → 1,29
/* memchr() Author: Kees J. Bot */
/* 2 Jan 1994 */
 
/* void *memchr(const void *s, int c, size_t n) */
/* Look for a character in a chunk of memory. */
/* */
#include "asm.h"
 
ENTRY(memchr)
push %ebp
movl %esp, %ebp
push %edi
movl 8(%ebp), %edi /* edi = string */
movb 12(%ebp), %al /* The character to look for */
movl 16(%ebp), %ecx /* Length */
cmpb $1, %cl /* 'Z' bit must be clear if ecx = 0 */
cld
 
repne scasb
jne failure
leal -1(%edi), %eax /* Found */
pop %edi
pop %ebp
ret
failure:
xorl %eax, %eax
pop %edi
pop %ebp
ret
/drivers/ddk/string/memcmp.S
1,59 → 1,57
# memcmp() Author: Kees J. Bot
# 2 Jan 1994
/* memcmp() Author: Kees J. Bot */
/* 2 Jan 1994 */
 
# int memcmp(const void *s1, const void *s2, size_t n)
# Compare two chunks of memory.
#
/* int memcmp(const void *s1, const void *s2, size_t n) */
/* Compare two chunks of memory. */
/* */
#include "asm.h"
 
.intel_syntax
ENTRY(memcmp)
cld
push %ebp
movl %esp, %ebp
push %esi
push %edi
movl 8(%ebp), %esi /* String s1 */
movl 12(%ebp), %edi /* String s2 */
movl 16(%ebp), %ecx /* Length */
cmpl $16, %ecx
jb cbyte /* Don't bother being smart with short arrays */
movl %esi, %eax
orl %edi, %eax
testb $1, %al
jne cbyte /* Bit 0 set, use byte compare */
testb $2, %al
jne cword /* Bit 1 set, use word compare */
clword:
shrdl $2, %ecx, %eax /* Save low two bits of ecx in eax */
shrl $2, %ecx
 
.globl _memcmp
repe cmpsl /* Compare longwords */
subl $4, %esi
subl $4, %edi
incl %ecx /* Recompare the last longword */
shldl $2, %eax, %ecx /* And any excess bytes */
jmp last
cword:
shrdl $1, %ecx, %eax /* Save low bit of ecx in eax */
shrl $1, %ecx
 
.text
.align 16
_memcmp:
cld
push ebp
mov ebp, esp
push esi
push edi
mov esi, [8+ebp] # String s1
mov edi, [12+ebp] # String s2
mov ecx, [16+ebp] # Length
cmp ecx, 16
jb cbyte # Don't bother being smart with short arrays
mov eax, esi
or eax, edi
testb al, 1
jnz cbyte # Bit 0 set, use byte compare
testb al, 2
jnz cword # Bit 1 set, use word compare
clword: shrd eax, ecx, 2 # Save low two bits of ecx in eax
shr ecx, 2
repe
cmpsd # Compare longwords
sub esi, 4
sub edi, 4
inc ecx # Recompare the last longword
shld ecx, eax, 2 # And any excess bytes
jmp last
cword: shrd eax, ecx, 1 # Save low bit of ecx in eax
shr ecx, 1
repe
cmpsw # Compare words
sub esi, 2
sub edi, 2
inc ecx # Recompare the last word
shld ecx, eax, 1 # And one more byte?
cbyte: test ecx, ecx # Set 'Z' flag if ecx = 0
last: repe
cmpsb # Look for the first differing byte
seta al # al = (s1 > s2)
setb ah # ah = (s1 < s2)
subb al, ah
movsxb eax, al # eax = (s1 > s2) - (s1 < s2), i.e. -1, 0, 1
mov edx, esi # For bcmp() to play with
pop edi
pop esi
pop ebp
repe cmpsw /* Compare words */
subl $2, %esi
subl $2, %edi
incl %ecx /* Recompare the last word */
shldl $1, %eax, %ecx /* And one more byte? */
cbyte:
testl %ecx, %ecx /* Set 'Z' flag if ecx = 0 */
last:
repe cmpsb /* Look for the first differing byte */
seta %al /* al = (s1 > s2) */
setb %ah /* ah = (s1 < s2) */
subb %ah, %al
movsbl %al, %eax /* eax = (s1 > s2) - (s1 < s2), i.e. -1, 0, 1 */
movl %esi, %edx /* For bcmp() to play with */
pop %edi
pop %esi
pop %ebp
ret
/drivers/ddk/string/memcpy.S
1,26 → 1,22
# memcpy() Author: Kees J. Bot 2 Jan 1994
/* memcpy() Author: Kees J. Bot */
/* 2 Jan 1994 */
 
# void *memcpy(void *s1, const void *s2, size_t n)
# Copy a chunk of memory.
# This routine need not handle overlap, so it does not handle overlap.
# One could simply call __memmove, the cost of the overlap check is
# negligible, but you are dealing with a programmer who believes that
# if anything can go wrong, it should go wrong.
/* void *memcpy(void *s1, const void *s2, size_t n) */
/* Copy a chunk of memory. */
/* This routine need not handle overlap, so it does not handle overlap. */
/* One could simply call __memmove, the cost of the overlap check is */
/* negligible, but you are dealing with a programmer who believes that if */
/* anything can go wrong, it should go wrong. */
/* */
#include "asm.h"
 
.intel_syntax
 
.globl _memcpy
 
.text
 
.align 16
_memcpy:
push ebp
mov ebp, esp
push esi
push edi
mov edi, [ebp+8] # String s1
mov esi, [ebp+12] # String s2
mov ecx, [ebp+16] # Length
# No overlap check here
jmp __memcpy # Call the part of __memmove that copies up
ENTRY(memcpy)
push %ebp
movl %esp, %ebp
push %esi
push %edi
movl 8(%ebp), %edi /* String s1 */
movl 12(%ebp), %esi /* String s2 */
movl 16(%ebp), %ecx /* Length */
/* No overlap check here */
jmp _C_LABEL(_memcpy) /* Call the part of __memmove that copies up */
/drivers/ddk/string/memmove.S
0,0 → 1,10
/* memmove() Author: Kees J. Bot */
/* 2 Jan 1994 */
 
/* void *memmove(void *s1, const void *s2, size_t n) */
/* Copy a chunk of memory. Handle overlap. */
/* */
#include "asm.h"
 
ENTRY(memmove)
jmp _C_LABEL(_memmove) /* Call common code */
/drivers/ddk/string/memset.S
1,47 → 1,45
# memset() Author: Kees J. Bot
# 2 Jan 1994
# void *memset(void *s, int c, size_t n)
# Set a chunk of memory to the same byte value.
#
/* memset() Author: Kees J. Bot */
/* 2 Jan 1994 */
 
.intel_syntax
/* void *memset(void *s, int c, size_t n) */
/* Set a chunk of memory to the same byte value. */
/* */
#include "asm.h"
 
.global _memset
 
.text
.align 16
_memset:
push ebp
mov ebp, esp
push edi
mov edi, [8+ebp] # The string
movzx eax, byte ptr [12+ebp] # The fill byte
mov ecx, [16+ebp] # Length
ENTRY(memset)
push %ebp
movl %esp, %ebp
push %edi
movl 8(%ebp), %edi /* The string */
movzbl 12(%ebp), %eax /* The fill byte */
movl 16(%ebp), %ecx /* Length */
cld
cmp ecx, 16
jb sbyte # Don't bother being smart with short arrays
test edi, 1
jnz sbyte # Bit 0 set, use byte store
test edi, 2
jnz sword # Bit 1 set, use word store
cmpl $16, %ecx
jb sbyte /* Don't bother being smart with short arrays */
testl $1, %edi
jne sbyte /* Bit 0 set, use byte store */
testl $2, %edi
jne sword /* Bit 1 set, use word store */
slword:
movb ah, al
mov edx, eax
sal edx, 16
or eax, edx # One byte to four bytes
shrd edx, ecx, 2 # Save low two bits of ecx in edx
shr ecx, 2
rep stosd # Store longwords.
shld ecx, edx, 2 # Restore low two bits
movb %al, %ah
movl %eax, %edx
sall $16, %edx
orl %edx, %eax /* One byte to four bytes */
shrdl $2, %ecx, %edx /* Save low two bits of ecx in edx */
shrl $2, %ecx
 
rep stosl /* Store longwords. */
shldl $2, %edx, %ecx /* Restore low two bits */
sword:
movb ah, al # One byte to two bytes
shr ecx, 1
rep stosw # Store words
adc ecx, ecx # One more byte?
movb %al, %ah /* One byte to two bytes */
shrl $1, %ecx
 
rep stosw /* Store words */
adcl %ecx, %ecx /* One more byte? */
sbyte:
rep stosb # Store bytes
rep stosb /* Store bytes */
done:
mov eax, [8+ebp] # Return some value you have no need for
pop edi
pop ebp
movl 8(%ebp), %eax /* Return some value you have no need for */
pop %edi
pop %ebp
ret
/drivers/ddk/string/rindex.S
0,0 → 1,11
/* rindex() Author: Kees J. Bot */
/* 2 Jan 1994 */
 
/* char *rindex(const char *s, int c) */
/* Look for the last occurrence a character in a string. Has suffered */
/* from a hostile takeover by strrchr(). */
/* */
#include "asm.h"
 
ENTRY(rindex)
jmp _C_LABEL(strrchr)
/drivers/ddk/string/strcat.S
1,15 → 1,11
# strcat() Author: Kees J. Bot
# 1 Jan 1994
# char *strcat(char *s1, const char *s2)
# Append string s2 to s1.
#
/* strcat() Author: Kees J. Bot */
/* 1 Jan 1994 */
 
.intel_syntax
/* char *strcat(char *s1, const char *s2) */
/* Append string s2 to s1. */
/* */
#include "asm.h"
 
.global _strcat
 
.text
.align 16
_strcat:
mov edx, -1 # Unlimited length
jmp __strncat # Common code
ENTRY(strcat)
movl $-1, %edx /* Unlimited length */
jmp _C_LABEL(_strncat) /* Common code */
/drivers/ddk/string/strchr.S
1,46 → 1,41
# strchr() Author: Kees J. Bot 1 Jan 1994
/* strchr() Author: Kees J. Bot */
/* 1 Jan 1994 */
 
# char *strchr(const char *s, int c)
# Look for a character in a string.
/* char *strchr(const char *s, int c) */
/* Look for a character in a string. */
/* */
#include "asm.h"
 
.intel_syntax
 
.globl _strchr
 
.text
.align 16
_strchr:
push ebp
mov ebp, esp
push edi
ENTRY(strchr)
push %ebp
movl %esp, %ebp
push %edi
cld
mov edi, [ebp+8] # edi = string
mov edx, 16 # Look at small chunks of the string
movl 8(%ebp), %edi /* edi = string */
movl $16, %edx /* Look at small chunks of the string */
next:
shl edx, 1 # Chunks become bigger each time
mov ecx, edx
xorb al, al # Look for the zero at the end
shll $1, %edx /* Chunks become bigger each time */
movl %edx, %ecx
xorb %al, %al /* Look for the zero at the end */
 
repne scasb
pushf /* Remember the flags */
subl %edx, %ecx
negl %ecx /* Some or all of the chunk */
subl %ecx, %edi /* Step back */
movb 12(%ebp), %al /* The character to look for */
 
pushf # Remember the flags
sub ecx, edx
neg ecx # Some or all of the chunk
sub edi, ecx # Step back
movb al, [ebp+12] # The character to look for
repne scasb
je found
 
popf # Did we find the end of string earlier?
 
jne next # No, try again
 
xor eax, eax # Return NULL
pop edi
pop ebp
popf /* Did we find the end of string earlier? */
jne next /* No, try again */
xorl %eax, %eax /* Return NULL */
pop %edi
pop %ebp
ret
found:
pop eax # Get rid of those flags
lea eax, [edi-1] # Address of byte found
pop edi
pop ebp
pop %eax /* Get rid of those flags */
leal -1(%edi), %eax /* Address of byte found */
pop %edi
pop %ebp
ret
/drivers/ddk/string/strcmp.S
0,0 → 1,11
/* strcmp() Author: Kees J. Bot */
/* 1 Jan 1994 */
 
/* int strcmp(const char *s1, const char *s2) */
/* Compare two strings. */
/* */
#include "asm.h"
 
ENTRY(strcmp)
movl $-1, %ecx /* Unlimited length */
jmp _C_LABEL(_strncmp) /* Common code */
/drivers/ddk/string/strcpy.S
1,24 → 1,20
# strcpy() Author: Kees J. Bot
# 1 Jan 1994
# char *strcpy(char *s1, const char *s2)
# Copy string s2 to s1.
#
/* strcpy() Author: Kees J. Bot */
/* 1 Jan 1994 */
 
.intel_syntax
/* char *strcpy(char *s1, const char *s2) */
/* Copy string s2 to s1. */
/* */
#include "asm.h"
 
.global _strcpy
 
.text
.align 16
_strcpy:
push ebp
mov ebp, esp
push esi
push edi
mov ecx, -1 # Unlimited length
call _strncpy # Common code
mov eax, [8+ebp] # Return s1
pop edi
pop esi
pop ebp
ENTRY(strcpy)
push %ebp
movl %esp, %ebp
push %esi
push %edi
movl $-1, %ecx /* Unlimited length */
call _C_LABEL(_strncpy) /* Common code */
movl 8(%ebp), %eax /* Return s1 */
pop %edi
pop %esi
pop %ebp
ret
/drivers/ddk/string/strlen.S
1,15 → 1,11
# strlen() Author: Kees J. Bot 1 Jan 1994
/* strlen() Author: Kees J. Bot */
/* 1 Jan 1994 */
 
# size_t strlen(const char *s)
# Return the length of a string.
/* size_t strlen(const char *s) */
/* Return the length of a string. */
/* */
#include "asm.h"
 
.intel_syntax
 
.globl _strlen
 
.text
 
.align 16
_strlen:
mov ecx, -1 # Unlimited length
jmp __strnlen # Common code
ENTRY(strlen)
movl $-1, %ecx /* Unlimited length */
jmp _C_LABEL(_strnlen) /* Common code */
/drivers/ddk/string/strncat.S
0,0 → 1,11
/* strncat() Author: Kees J. Bot */
/* 1 Jan 1994 */
 
/* size_t strncat(char *s1, const char *s2, size_t n) */
/* Append string s2 to s1. */
/* */
#include "asm.h"
 
ENTRY(strncat)
movl 12(%esp), %edx /* Maximum length */
jmp _C_LABEL(_strncat) /* Common code */
/drivers/ddk/string/strncmp.S
1,22 → 1,11
# strncmp() Author: Kees J. Bot 1 Jan 1994
/* strncmp() Author: Kees J. Bot */
/* 1 Jan 1994 */
 
# int strncmp(const char *s1, const char *s2, size_t n)
# Compare two strings.
#
/* int strncmp(const char *s1, const char *s2, size_t n) */
/* Compare two strings. */
/* */
#include "asm.h"
 
.intel_syntax
 
.globl _strncmp
.globl _strcmp
 
.text
.align 16
_strncmp:
mov ecx, [esp+12] # Maximum length
jmp __strncmp # Common code
 
 
.align 16
_strcmp:
mov ecx, -1 # Maximum length
jmp __strncmp # Common code
ENTRY(strncmp)
movl 12(%esp), %ecx /* Maximum length */
jmp _C_LABEL(_strncmp) /* Common code */
/drivers/ddk/string/strncpy.S
1,28 → 1,23
# strncpy() Author: Kees J. Bot
# 1 Jan 1994
# char *strncpy(char *s1, const char *s2, size_t n)
# Copy string s2 to s1.
#
/* strncpy() Author: Kees J. Bot */
/* 1 Jan 1994 */
 
.intel_syntax
/* char *strncpy(char *s1, const char *s2, size_t n) */
/* Copy string s2 to s1. */
/* */
#include "asm.h"
 
.text
ENTRY(strncpy)
push %ebp
movl %esp, %ebp
push %esi
push %edi
movl 16(%ebp), %ecx /* Maximum length */
call _C_LABEL(_strncpy) /* Common code */
movl %edx, %ecx /* Number of bytes not copied */
 
.globl _strncpy
 
.align 16
_strncpy:
push ebp
mov ebp, esp
push esi
push edi
mov ecx, [ebp+16] # Maximum length
call __strncpy # Common code
mov ecx, edx # Number of bytes not copied
rep
stosb # strncpy always copies n bytes by null padding
mov eax, [ebp+8] # Return s1
pop edi
pop esi
pop ebp
rep stosb /* strncpy always copies n bytes by null padding */
movl 8(%ebp), %eax /* Return s1 */
pop %edi
pop %esi
pop %ebp
ret
/drivers/ddk/string/strnlen.S
0,0 → 1,11
/* strnlen() Author: Kees J. Bot */
/* 1 Jan 1994 */
 
/* size_t strnlen(const char *s, size_t n) */
/* Return the length of a string. */
/* */
#include "asm.h"
 
ENTRY(strnlen)
movl 8(%esp), %ecx /* Maximum length */
jmp _C_LABEL(_strnlen) /* Common code */
/drivers/ddk/string/strrchr.S
0,0 → 1,35
/* strrchr() Author: Kees J. Bot */
/* 2 Jan 1994 */
 
/* char *strrchr(const char *s, int c) */
/* Look for the last occurrence a character in a string. */
/* */
#include "asm.h"
 
ENTRY(strrchr)
push %ebp
movl %esp, %ebp
push %edi
movl 8(%ebp), %edi /* edi = string */
movl $-1, %ecx
xorb %al, %al
cld
 
repne scasb /* Look for the end of the string */
notl %ecx /* -1 - ecx = Length of the string + null */
decl %edi /* Put edi back on the zero byte */
movb 12(%ebp), %al /* The character to look for */
std /* Downwards search */
 
repne scasb
cld /* Direction bit back to default */
jne failure
leal 1(%edi), %eax /* Found it */
pop %edi
pop %ebp
ret
failure:
xorl %eax, %eax /* Not there */
pop %edi
pop %ebp
ret
/drivers/devman/Makefile
24,7 → 24,10
 
NAME= acpi
 
NAME_SRCS= acpi.c
NAME_SRCS= acpi.c \
scan.c \
pci_irq.c \
pci/pci.c
 
 
all: $(NAME).dll
/drivers/devman/acpi.c
6,7 → 6,10
#include <syscall.h>
 
#include "acpi.h"
#include "acpi_bus.h"
 
#define PREFIX "ACPI: "
 
#define ACPI_BUS_CLASS "system_bus"
#define ACPI_BUS_HID "KLBSYBUS"
#define ACPI_BUS_DEVICE_NAME "System Bus"
16,8 → 19,8
 
static LIST_HEAD(acpi_device_list);
static LIST_HEAD(acpi_bus_id_list);
DEFINE_MUTEX(acpi_device_lock);
 
 
struct acpi_device_bus_id
{
char bus_id[15];
44,40 → 47,7
ACPI_BUS_REMOVAL_TYPE_COUNT
};
 
enum acpi_bus_device_type {
ACPI_BUS_TYPE_DEVICE = 0,
ACPI_BUS_TYPE_POWER,
ACPI_BUS_TYPE_PROCESSOR,
ACPI_BUS_TYPE_THERMAL,
ACPI_BUS_TYPE_POWER_BUTTON,
ACPI_BUS_TYPE_SLEEP_BUTTON,
ACPI_BUS_DEVICE_TYPE_COUNT
};
 
/*
* _HID definitions
* HIDs must conform to ACPI spec(6.1.4)
* KolibriOS specific HIDs do not apply to this and begin with KOS:
*/
 
#define ACPI_POWER_HID "KLBPOWER"
#define ACPI_PROCESSOR_OBJECT_HID "KLBCPU"
#define ACPI_SYSTEM_HID "KLBSYSTM"
#define ACPI_THERMAL_HID "KLBTHERM"
#define ACPI_BUTTON_HID_POWERF "KLBPWRBN"
#define ACPI_BUTTON_HID_SLEEPF "KLBSLPBN"
#define ACPI_VIDEO_HID "KLBVIDEO"
#define ACPI_BAY_HID "KLBIOBAY"
#define ACPI_DOCK_HID "KLBDOCK"
/* Quirk for broken IBM BIOSes */
#define ACPI_SMBUS_IBM_HID "SMBUSIBM"
 
 
#define STRUCT_TO_INT(s) (*((int*)&s))
 
#define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \
ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING)
 
#define PCI_MAX_DEVICES 32
#define PCI_MAX_PINS 4
 
96,850 → 66,521
#define acpi_remap( addr ) MapIoMem((void*)(addr),4096, 0x01)
 
 
struct acpi_bus_ops
{
u32_t acpi_op_add:1;
u32_t acpi_op_start:1;
};
struct acpi_device *acpi_root;
 
struct acpi_device_flags {
u32 dynamic_status:1;
u32 bus_address:1;
u32 removable:1;
u32 ejectable:1;
u32 lockable:1;
u32 suprise_removal_ok:1;
u32 power_manageable:1;
u32 performance_manageable:1;
u32 wake_capable:1; /* Wakeup(_PRW) supported? */
u32 force_power_state:1;
u32 reserved:22;
};
extern struct resource iomem_resource;
extern struct resource ioport_resource;
 
struct acpi_device_status {
u32 present:1;
u32 enabled:1;
u32 show_in_ui:1;
u32 functional:1;
u32 battery_present:1;
u32 reserved:27;
enum pic_mode
{
IO_PIC = 0,
IO_APIC
};
 
static void set_pic_mode(enum pic_mode mode)
{
ACPI_OBJECT arg1;
ACPI_OBJECT_LIST args;
ACPI_STATUS as;
 
typedef char acpi_bus_id[8];
typedef unsigned long acpi_bus_address;
typedef char acpi_device_name[40];
typedef char acpi_device_class[20];
arg1.Type = ACPI_TYPE_INTEGER;
arg1.Integer.Value = mode;
args.Count = 1;
args.Pointer = &arg1;
 
struct acpi_hardware_id {
struct list_head list;
char *id;
};
as = AcpiEvaluateObject(ACPI_ROOT_OBJECT, "_PIC", &args, NULL);
/*
* We can silently ignore failure as it may not be implemented, ACPI should
* provide us with correct information anyway
*/
if (ACPI_SUCCESS(as))
dbgprintf(PREFIX "machine set to %s mode\n", mode ? "APIC" : "PIC");
}
 
struct acpi_device_pnp
void print_device_tree(struct acpi_device *device)
{
acpi_bus_id bus_id; /* Object name */
acpi_bus_address bus_address; /* _ADR */
char *unique_id; /* _UID */
struct list_head ids; /* _HID and _CIDs */
acpi_device_name device_name; /* Driver-determined */
acpi_device_class device_class; /* " */
};
struct acpi_device *child;
 
dbgprintf("%s\n", device->pnp.bus_id);
 
struct acpi_device
list_for_each_entry(child, &device->children, node)
{
int device_type;
ACPI_HANDLE handle; /* no handle for fixed hardware */
struct acpi_device *parent;
struct list_head children;
struct list_head node;
// struct list_head wakeup_list;
struct acpi_device_status status;
struct acpi_device_flags flags;
struct acpi_device_pnp pnp;
// struct acpi_device_power power;
// struct acpi_device_wakeup wakeup;
// struct acpi_device_perf performance;
// struct acpi_device_dir dir;
// struct acpi_device_ops ops;
// struct acpi_driver *driver;
void *driver_data;
// struct device dev;
struct acpi_bus_ops bus_ops; /* workaround for different code path for hotplug */
// enum acpi_bus_removal_type removal_type; /* indicate for different removal type */
print_device_tree(child);
};
};
 
struct acpi_device *acpi_root;
 
 
static void
acpi_util_eval_error(ACPI_HANDLE h, ACPI_STRING p, ACPI_STATUS s)
/*
int acpi_pci_bind_root(struct acpi_device *device)
{
#ifdef ACPI_DEBUG_OUTPUT
char prefix[80] = {'\0'};
ACPI_BUFFER buffer = {sizeof(prefix), prefix};
AcpiGetName(h, ACPI_FULL_PATHNAME, &buffer);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n",
(char *) prefix, p, AcpiFormatException(s)));
#else
return;
#endif
}
device->ops.bind = acpi_pci_bind;
device->ops.unbind = acpi_pci_unbind;
 
ACPI_STATUS
acpi_evaluate_integer(ACPI_HANDLE handle, ACPI_STRING pathname,
ACPI_OBJECT_LIST *arguments, unsigned long long *data)
{
ACPI_STATUS status = AE_OK;
ACPI_OBJECT element;
ACPI_BUFFER buffer = { 0, NULL };
 
if (!data)
return AE_BAD_PARAMETER;
 
buffer.Length = sizeof(ACPI_OBJECT);
buffer.Pointer = &element;
status = AcpiEvaluateObject(handle, pathname, arguments, &buffer);
if (ACPI_FAILURE(status)) {
acpi_util_eval_error(handle, pathname, status);
return status;
return 0;
}
*/
 
if (element.Type != ACPI_TYPE_INTEGER) {
acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
return AE_BAD_DATA;
}
static bool pci_use_crs = false;
 
*data = element.Integer.Value;
#define IORESOURCE_BUS 0x00001000
 
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%llu]\n", *data));
struct acpi_pci_root {
struct list_head node;
struct acpi_device * device;
struct acpi_pci_id id;
struct pci_bus *bus;
u16 segment;
struct resource secondary; /* downstream bus range */
 
return AE_OK;
}
};
 
void acpi_bus_data_handler(ACPI_HANDLE handle, void *context)
{
static LIST_HEAD(acpi_pci_roots);
 
/* TBD */
#define ACPI_PCI_ROOT_CLASS "pci_bridge"
#define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge"
 
return;
}
 
 
int acpi_bus_get_device(ACPI_HANDLE handle, struct acpi_device **device)
static ACPI_STATUS
get_root_bridge_busnr_callback(ACPI_RESOURCE *resource, void *data)
{
ACPI_STATUS status = AE_OK;
struct resource *res = data;
ACPI_RESOURCE_ADDRESS64 address;
 
if (!device)
{
return -EINVAL;
};
if (resource->Type != ACPI_RESOURCE_TYPE_ADDRESS16 &&
resource->Type != ACPI_RESOURCE_TYPE_ADDRESS32 &&
resource->Type != ACPI_RESOURCE_TYPE_ADDRESS64)
return AE_OK;
 
/* TBD: Support fixed-feature devices */
 
status = AcpiGetData(handle, acpi_bus_data_handler, (void **)device);
if (ACPI_FAILURE(status) || !*device) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
handle));
return -ENODEV;
AcpiResourceToAddress64(resource, &address);
if ((address.AddressLength > 0) &&
(address.ResourceType == ACPI_BUS_NUMBER_RANGE)) {
res->start = address.Minimum;
res->end = address.Minimum + address.AddressLength - 1;
}
return 0;
}
 
 
ACPI_STATUS acpi_bus_get_status_handle(ACPI_HANDLE handle,
unsigned long long *sta)
{
ACPI_STATUS status;
 
status = acpi_evaluate_integer(handle, "_STA", NULL, sta);
if (ACPI_SUCCESS(status))
{
return AE_OK;
};
 
if (status == AE_NOT_FOUND)
{
*sta = ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED |
ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING;
return AE_OK;
}
return status;
}
 
 
 
static int acpi_bus_type_and_status(ACPI_HANDLE handle, int *type,
unsigned long long *sta)
static ACPI_STATUS try_get_root_bridge_busnr(ACPI_HANDLE handle,
struct resource *res)
{
ACPI_STATUS status;
ACPI_OBJECT_TYPE acpi_type;
 
status = AcpiGetType(handle, &acpi_type);
res->start = -1;
status =
AcpiWalkResources(handle, METHOD_NAME__CRS,
get_root_bridge_busnr_callback, res);
if (ACPI_FAILURE(status))
{
return -ENODEV;
};
return status;
if (res->start == -1)
return AE_ERROR;
return AE_OK;
}
 
switch (acpi_type)
{
case ACPI_TYPE_ANY: /* for ACPI_ROOT_OBJECT */
case ACPI_TYPE_DEVICE:
*type = ACPI_BUS_TYPE_DEVICE;
status = acpi_bus_get_status_handle(handle, sta);
if (ACPI_FAILURE(status))
{
return -ENODEV;
};
break;
 
case ACPI_TYPE_PROCESSOR:
*type = ACPI_BUS_TYPE_PROCESSOR;
status = acpi_bus_get_status_handle(handle, sta);
if (ACPI_FAILURE(status))
struct pci_root_info
{
return -ENODEV;
struct acpi_device *bridge;
char *name;
unsigned int res_num;
struct resource *res;
struct pci_bus *bus;
int busnum;
};
break;
case ACPI_TYPE_THERMAL:
*type = ACPI_BUS_TYPE_THERMAL;
*sta = ACPI_STA_DEFAULT;
break;
case ACPI_TYPE_POWER:
*type = ACPI_BUS_TYPE_POWER;
*sta = ACPI_STA_DEFAULT;
break;
default:
return -ENODEV;
}
 
return 0;
}
 
static struct acpi_device *acpi_bus_get_parent(ACPI_HANDLE handle)
static ACPI_STATUS
resource_to_addr(ACPI_RESOURCE *resource, ACPI_RESOURCE_ADDRESS64 *addr)
{
ACPI_STATUS status;
struct acpi_device *device;
int ret;
struct acpi_resource_memory24 *memory24;
struct acpi_resource_memory32 *memory32;
struct acpi_resource_fixed_memory32 *fixed_memory32;
 
/*
* Fixed hardware devices do not appear in the namespace and do not
* have handles, but we fabricate acpi_devices for them, so we have
* to deal with them specially.
*/
if (handle == NULL)
{
return acpi_root;
};
 
do
{
status = AcpiGetParent(handle, &handle);
if (status == AE_NULL_ENTRY)
{
return NULL;
};
if (ACPI_FAILURE(status))
{
return acpi_root;
};
 
ret = acpi_bus_get_device(handle, &device);
if (ret == 0)
{
return device;
};
} while (1);
memset(addr, 0, sizeof(*addr));
switch (resource->Type) {
case ACPI_RESOURCE_TYPE_MEMORY24:
memory24 = &resource->Data.Memory24;
addr->ResourceType = ACPI_MEMORY_RANGE;
addr->Minimum = memory24->Minimum;
addr->AddressLength = memory24->AddressLength;
addr->Maximum = addr->Minimum + addr->AddressLength - 1;
return AE_OK;
case ACPI_RESOURCE_TYPE_MEMORY32:
memory32 = &resource->Data.Memory32;
addr->ResourceType = ACPI_MEMORY_RANGE;
addr->Minimum = memory32->Minimum;
addr->AddressLength = memory32->AddressLength;
addr->Maximum = addr->Minimum + addr->AddressLength - 1;
return AE_OK;
case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
fixed_memory32 = &resource->Data.FixedMemory32;
addr->ResourceType = ACPI_MEMORY_RANGE;
addr->Minimum = fixed_memory32->Address;
addr->AddressLength = fixed_memory32->AddressLength;
addr->Maximum = addr->Minimum + addr->AddressLength - 1;
return AE_OK;
case ACPI_RESOURCE_TYPE_ADDRESS16:
case ACPI_RESOURCE_TYPE_ADDRESS32:
case ACPI_RESOURCE_TYPE_ADDRESS64:
status = AcpiResourceToAddress64(resource, addr);
if (ACPI_SUCCESS(status) &&
(addr->ResourceType == ACPI_MEMORY_RANGE ||
addr->ResourceType == ACPI_IO_RANGE) &&
addr->AddressLength > 0) {
return AE_OK;
}
 
 
static void acpi_device_get_busid(struct acpi_device *device)
{
char bus_id[5] = { '?', 0 };
struct acpi_buffer buffer = { sizeof(bus_id), bus_id };
int i = 0;
 
/*
* Bus ID
* ------
* The device's Bus ID is simply the object name.
* TBD: Shouldn't this value be unique (within the ACPI namespace)?
*/
if (ACPI_IS_ROOT_DEVICE(device)) {
strcpy(device->pnp.bus_id, "ACPI");
return;
}
 
switch (device->device_type)
{
case ACPI_BUS_TYPE_POWER_BUTTON:
strcpy(device->pnp.bus_id, "PWRF");
break;
case ACPI_BUS_TYPE_SLEEP_BUTTON:
strcpy(device->pnp.bus_id, "SLPF");
break;
default:
AcpiGetName(device->handle, ACPI_SINGLE_NAME, &buffer);
/* Clean up trailing underscores (if any) */
for (i = 3; i > 1; i--)
{
if (bus_id[i] == '_')
bus_id[i] = '\0';
else
break;
}
strcpy(device->pnp.bus_id, bus_id);
break;
return AE_ERROR;
}
}
 
 
static int acpi_bus_get_flags(struct acpi_device *device)
static ACPI_STATUS
count_resource(ACPI_RESOURCE *acpi_res, void *data)
{
ACPI_STATUS status = AE_OK;
ACPI_HANDLE temp = NULL;
struct pci_root_info *info = data;
ACPI_RESOURCE_ADDRESS64 addr;
ACPI_STATUS status;
 
/* Presence of _STA indicates 'dynamic_status' */
status = AcpiGetHandle(device->handle, "_STA", &temp);
status = resource_to_addr(acpi_res, &addr);
if (ACPI_SUCCESS(status))
device->flags.dynamic_status = 1;
 
/* Presence of _RMV indicates 'removable' */
status = AcpiGetHandle(device->handle, "_RMV", &temp);
if (ACPI_SUCCESS(status))
device->flags.removable = 1;
 
/* Presence of _EJD|_EJ0 indicates 'ejectable' */
status = AcpiGetHandle(device->handle, "_EJD", &temp);
if (ACPI_SUCCESS(status))
device->flags.ejectable = 1;
else {
status = AcpiGetHandle(device->handle, "_EJ0", &temp);
if (ACPI_SUCCESS(status))
device->flags.ejectable = 1;
info->res_num++;
return AE_OK;
}
 
/* Presence of _LCK indicates 'lockable' */
status = AcpiGetHandle(device->handle, "_LCK", &temp);
if (ACPI_SUCCESS(status))
device->flags.lockable = 1;
 
/* Presence of _PS0|_PR0 indicates 'power manageable' */
status = AcpiGetHandle(device->handle, "_PS0", &temp);
if (ACPI_FAILURE(status))
status = AcpiGetHandle(device->handle, "_PR0", &temp);
if (ACPI_SUCCESS(status))
device->flags.power_manageable = 1;
static ACPI_STATUS setup_resource(ACPI_RESOURCE *acpi_res, void *data)
{
struct pci_root_info *info = data;
struct resource *res;
struct acpi_resource_address64 addr;
ACPI_STATUS status;
unsigned long flags;
struct resource *root, *conflict;
u64 start, end;
 
/* Presence of _PRW indicates wake capable */
status = AcpiGetHandle(device->handle, "_PRW", &temp);
if (ACPI_SUCCESS(status))
device->flags.wake_capable = 1;
status = resource_to_addr(acpi_res, &addr);
if (!ACPI_SUCCESS(status))
return AE_OK;
 
/* TBD: Performance management */
 
return 0;
if (addr.ResourceType == ACPI_MEMORY_RANGE)
{
root = &iomem_resource;
flags = IORESOURCE_MEM;
if (addr.Info.Mem.Caching == ACPI_PREFETCHABLE_MEMORY)
flags |= IORESOURCE_PREFETCH;
}
else if (addr.ResourceType == ACPI_IO_RANGE)
{
root = &ioport_resource;
flags = IORESOURCE_IO;
} else
return AE_OK;
 
/*
* acpi_bay_match - see if a device is an ejectable driver bay
*
* If an acpi object is ejectable and has one of the ACPI ATA methods defined,
* then we can safely call it an ejectable drive bay
*/
static int acpi_bay_match(struct acpi_device *device){
ACPI_STATUS status;
ACPI_HANDLE handle;
ACPI_HANDLE tmp;
ACPI_HANDLE phandle;
start = addr.Minimum + addr.TranslationOffset;
end = addr.Maximum + addr.TranslationOffset;
 
handle = device->handle;
res = &info->res[info->res_num];
res->name = info->name;
res->flags = flags;
res->start = start;
res->end = end;
res->child = NULL;
 
status = AcpiGetHandle(handle, "_EJ0", &tmp);
if (ACPI_FAILURE(status))
return -ENODEV;
 
if ((ACPI_SUCCESS(AcpiGetHandle(handle, "_GTF", &tmp))) ||
(ACPI_SUCCESS(AcpiGetHandle(handle, "_GTM", &tmp))) ||
(ACPI_SUCCESS(AcpiGetHandle(handle, "_STM", &tmp))) ||
(ACPI_SUCCESS(AcpiGetHandle(handle, "_SDD", &tmp))))
return 0;
 
if (AcpiGetParent(handle, &phandle))
return -ENODEV;
 
if ((ACPI_SUCCESS(AcpiGetHandle(phandle, "_GTF", &tmp))) ||
(ACPI_SUCCESS(AcpiGetHandle(phandle, "_GTM", &tmp))) ||
(ACPI_SUCCESS(AcpiGetHandle(phandle, "_STM", &tmp))) ||
(ACPI_SUCCESS(AcpiGetHandle(phandle, "_SDD", &tmp))))
return 0;
 
return -ENODEV;
if (!pci_use_crs) {
printk("host bridge window %pR (ignored)\n", res);
return AE_OK;
}
 
/*
* acpi_dock_match - see if a device has a _DCK method
*/
static int acpi_dock_match(struct acpi_device *device)
{
ACPI_HANDLE tmp;
return AcpiGetHandle(device->handle, "_DCK", &tmp);
#if 0
conflict = insert_resource_conflict(root, res);
if (conflict) {
dev_err(&info->bridge->dev,
"address space collision: host bridge window %pR "
"conflicts with %s %pR\n",
res, conflict->name, conflict);
} else {
pci_bus_add_resource(info->bus, res, 0);
info->res_num++;
if (addr.translation_offset)
dev_info(&info->bridge->dev, "host bridge window %pR "
"(PCI address [%#llx-%#llx])\n",
res, res->start - addr.translation_offset,
res->end - addr.translation_offset);
else
dev_info(&info->bridge->dev,
"host bridge window %pR\n", res);
}
 
char *acpi_device_hid(struct acpi_device *device)
{
struct acpi_hardware_id *hid;
 
hid = list_first_entry(&device->pnp.ids, struct acpi_hardware_id, list);
return hid->id;
return AE_OK;
#endif
}
 
 
 
static void acpi_add_id(struct acpi_device *device, const char *dev_id)
static void
get_current_resources(struct acpi_device *device, int busnum,
int domain, struct pci_bus *bus)
{
struct acpi_hardware_id *id;
struct pci_root_info info;
size_t size;
 
id = kmalloc(sizeof(*id), GFP_KERNEL);
if (!id)
{
return;
};
char buf[64];
 
INIT_LIST_HEAD(&id->list);
// if (pci_use_crs)
// pci_bus_remove_resources(bus);
 
id->id = kmalloc(strlen(dev_id) + 1, GFP_KERNEL);
if (!id->id) {
kfree(id);
info.bridge = device;
info.bus = bus;
info.res_num = 0;
AcpiWalkResources(device->handle, METHOD_NAME__CRS, count_resource,
&info);
if (!info.res_num)
return;
}
 
strcpy(id->id, dev_id);
size = sizeof(*info.res) * info.res_num;
info.res = kmalloc(size, GFP_KERNEL);
if (!info.res)
goto res_alloc_fail;
 
list_add_tail(&id->list, &device->pnp.ids);
}
vsprintf(buf,"PCI Bus %04x:%02x", domain, busnum);
info.name = strdup(buf);
 
#define ACPI_VIDEO_OUTPUT_SWITCHING 0x0001
#define ACPI_VIDEO_DEVICE_POSTING 0x0002
#define ACPI_VIDEO_ROM_AVAILABLE 0x0004
#define ACPI_VIDEO_BACKLIGHT 0x0008
#define ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR 0x0010
#define ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO 0x0020
#define ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR 0x0040
#define ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO 0x0080
#define ACPI_VIDEO_BACKLIGHT_DMI_VENDOR 0x0100
#define ACPI_VIDEO_BACKLIGHT_DMI_VIDEO 0x0200
#define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR 0x0400
#define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO 0x0800
if (!info.name)
goto name_alloc_fail;
 
info.res_num = 0;
AcpiWalkResources(device->handle, METHOD_NAME__CRS, setup_resource,
&info);
 
long acpi_is_video_device(struct acpi_device *device)
{
ACPI_HANDLE h_dummy;
long video_caps = 0;
return;
 
if (!device)
return 0;
name_alloc_fail:
kfree(info.res);
res_alloc_fail:
return;
}
 
/* Is this device able to support video switching ? */
if (ACPI_SUCCESS(AcpiGetHandle(device->handle, "_DOD", &h_dummy)) ||
ACPI_SUCCESS(AcpiGetHandle(device->handle, "_DOS", &h_dummy)))
video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING;
 
/* Is this device able to retrieve a video ROM ? */
if (ACPI_SUCCESS(AcpiGetHandle(device->handle, "_ROM", &h_dummy)))
video_caps |= ACPI_VIDEO_ROM_AVAILABLE;
 
/* Is this device able to configure which video head to be POSTed ? */
if (ACPI_SUCCESS(AcpiGetHandle(device->handle, "_VPO", &h_dummy)) &&
ACPI_SUCCESS(AcpiGetHandle(device->handle, "_GPD", &h_dummy)) &&
ACPI_SUCCESS(AcpiGetHandle(device->handle, "_SPD", &h_dummy)))
video_caps |= ACPI_VIDEO_DEVICE_POSTING;
 
return video_caps;
}
struct pci_ops pci_root_ops = {
.read = NULL,
.write = NULL,
};
 
 
static void acpi_device_set_id(struct acpi_device *device)
struct pci_bus* pci_acpi_scan_root(struct acpi_pci_root *root)
{
ACPI_STATUS status;
ACPI_DEVICE_INFO *info;
ACPI_DEVICE_ID_LIST *cid_list;
int i;
struct acpi_device *device = root->device;
int domain = root->segment;
int busnum = root->secondary.start;
struct pci_bus *bus;
struct pci_sysdata *sd;
int node = 0;
 
switch (device->device_type)
{
case ACPI_BUS_TYPE_DEVICE:
if (ACPI_IS_ROOT_DEVICE(device))
{
acpi_add_id(device, ACPI_SYSTEM_HID);
break;
if (domain ) {
printk(KERN_WARNING "pci_bus %04x:%02x: "
"ignored (multiple domains not supported)\n",
domain, busnum);
return NULL;
}
 
status = AcpiGetObjectInfo(device->handle, &info);
if (ACPI_FAILURE(status)) {
printk(KERN_ERR "%s: Error reading device info\n", __func__);
return;
/* Allocate per-root-bus (not per bus) arch-specific data.
* TODO: leak; this memory is never freed.
* It's arguable whether it's worth the trouble to care.
*/
sd = kzalloc(sizeof(*sd), GFP_KERNEL);
if (!sd) {
printk(KERN_WARNING "pci_bus %04x:%02x: "
"ignored (out of memory)\n", domain, busnum);
return NULL;
}
 
if (info->Valid & ACPI_VALID_HID)
acpi_add_id(device, info->HardwareId.String);
if (info->Valid & ACPI_VALID_CID)
{
cid_list = &info->CompatibleIdList;
for (i = 0; i < cid_list->Count; i++)
acpi_add_id(device, cid_list->Ids[i].String);
sd->domain = domain;
sd->node = node;
/*
* Maybe the desired pci bus has been already scanned. In such case
* it is unnecessary to scan the pci bus with the given domain,busnum.
*/
bus = pci_find_bus(domain, busnum);
if (bus) {
/*
* If the desired bus exits, the content of bus->sysdata will
* be replaced by sd.
*/
memcpy(bus->sysdata, sd, sizeof(*sd));
kfree(sd);
} else {
bus = pci_create_bus(busnum, &pci_root_ops, sd);
if (bus) {
get_current_resources(device, busnum, domain, bus);
// bus->subordinate = pci_scan_child_bus(bus);
}
if (info->Valid & ACPI_VALID_ADR) {
device->pnp.bus_address = info->Address;
device->flags.bus_address = 1;
}
 
kfree(info);
if (!bus)
kfree(sd);
 
/*
* Some devices don't reliably have _HIDs & _CIDs, so add
* synthetic HIDs to make sure drivers can find them.
*/
if (acpi_is_video_device(device))
acpi_add_id(device, ACPI_VIDEO_HID);
else if (ACPI_SUCCESS(acpi_bay_match(device)))
acpi_add_id(device, ACPI_BAY_HID);
else if (ACPI_SUCCESS(acpi_dock_match(device)))
acpi_add_id(device, ACPI_DOCK_HID);
else if (!acpi_device_hid(device) &&
ACPI_IS_ROOT_DEVICE(device->parent)) {
acpi_add_id(device, ACPI_BUS_HID); /* \_SB, LNXSYBUS */
strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME);
strcpy(device->pnp.device_class, ACPI_BUS_CLASS);
if (bus && node != -1) {
printk("on NUMA node %d\n", node);
}
 
break;
case ACPI_BUS_TYPE_POWER:
acpi_add_id(device, ACPI_POWER_HID);
break;
case ACPI_BUS_TYPE_PROCESSOR:
acpi_add_id(device, ACPI_PROCESSOR_OBJECT_HID);
break;
case ACPI_BUS_TYPE_THERMAL:
acpi_add_id(device, ACPI_THERMAL_HID);
break;
case ACPI_BUS_TYPE_POWER_BUTTON:
acpi_add_id(device, ACPI_BUTTON_HID_POWERF);
break;
case ACPI_BUS_TYPE_SLEEP_BUTTON:
acpi_add_id(device, ACPI_BUTTON_HID_SLEEPF);
break;
return bus;
}
 
/*
* We build acpi_devices for some objects that don't have _HID or _CID,
* e.g., PCI bridges and slots. Drivers can't bind to these objects,
* but we do use them indirectly by traversing the acpi_device tree.
* This generic ID isn't useful for driver binding, but it provides
* the useful property that "every acpi_device has an ID."
*/
if (list_empty(&device->pnp.ids))
acpi_add_id(device, "device");
}
 
 
static int acpi_device_set_context(struct acpi_device *device)
static int acpi_pci_root_add(struct acpi_device *device)
{
unsigned long long segment, bus;
ACPI_STATUS status;
int result;
struct acpi_pci_root *root;
ACPI_HANDLE handle;
struct acpi_device *child;
u32 flags, base_flags;
 
/*
* Context
* -------
* Attach this 'struct acpi_device' to the ACPI object. This makes
* resolutions from handle->device very efficient. Fixed hardware
* devices have no handles, so we skip them.
*/
if (!device->handle)
return 0;
root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
if (!root)
return -ENOMEM;
 
status = AcpiAttachData(device->handle,
acpi_bus_data_handler, device);
if (ACPI_SUCCESS(status))
return 0;
 
dbgprintf(KERN_ERR "Error attaching device data\n");
return -ENODEV;
segment = 0;
status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL,
&segment);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
printk(KERN_ERR PREFIX "can't evaluate _SEG\n");
result = -ENODEV;
goto end;
}
 
 
static int acpi_device_register(struct acpi_device *device)
/* Check _CRS first, then _BBN. If no _BBN, default to zero. */
root->secondary.flags = IORESOURCE_BUS;
status = try_get_root_bridge_busnr(device->handle, &root->secondary);
if (ACPI_FAILURE(status))
{
int result;
struct acpi_device_bus_id *acpi_device_bus_id, *new_bus_id;
int found = 0;
 
/*
* Linkage
* -------
* Link this device to its parent and siblings.
* We need both the start and end of the downstream bus range
* to interpret _CBA (MMCONFIG base address), so it really is
* supposed to be in _CRS. If we don't find it there, all we
* can do is assume [_BBN-0xFF] or [0-0xFF].
*/
INIT_LIST_HEAD(&device->children);
INIT_LIST_HEAD(&device->node);
 
new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
if (!new_bus_id) {
dbgprintf(KERN_ERR "Memory allocation error\n");
return -ENOMEM;
root->secondary.end = 0xFF;
printk(KERN_WARNING PREFIX
"no secondary bus range in _CRS\n");
status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL, &bus);
if (ACPI_SUCCESS(status))
root->secondary.start = bus;
else if (status == AE_NOT_FOUND)
root->secondary.start = 0;
else {
printk(KERN_ERR PREFIX "can't evaluate _BBN\n");
result = -ENODEV;
goto end;
}
 
mutex_lock(&acpi_device_lock);
/*
* Find suitable bus_id and instance number in acpi_bus_id_list
* If failed, create one and link it into acpi_bus_id_list
*/
list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node)
{
if (!strcmp(acpi_device_bus_id->bus_id, acpi_device_hid(device)))
{
acpi_device_bus_id->instance_no++;
found = 1;
kfree(new_bus_id);
break;
}
}
if (!found)
{
acpi_device_bus_id = new_bus_id;
strcpy(acpi_device_bus_id->bus_id, acpi_device_hid(device));
acpi_device_bus_id->instance_no = 0;
list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list);
}
 
// dev_set_name(&device->dev, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no);
INIT_LIST_HEAD(&root->node);
root->device = device;
root->segment = segment & 0xFFFF;
strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
device->driver_data = root;
 
if (device->parent)
list_add_tail(&device->node, &device->parent->children);
 
mutex_unlock(&acpi_device_lock);
 
// device->dev.bus = &acpi_bus_type;
// device->dev.release = &acpi_device_release;
// result = device_register(&device->dev);
// if (result) {
// dev_err(&device->dev, "Error registering device\n");
// goto end;
// }
 
 
// device->removal_type = ACPI_BUS_REMOVAL_NORMAL;
return 0;
end:
mutex_lock(&acpi_device_lock);
if (device->parent)
list_del(&device->node);
mutex_unlock(&acpi_device_lock);
return result;
}
 
 
 
static int acpi_add_single_object(struct acpi_device **child,
ACPI_HANDLE handle, int type,
unsigned long long sta,
struct acpi_bus_ops *ops)
{
int result;
struct acpi_device *device;
ACPI_BUFFER buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 
device = kzalloc(sizeof(struct acpi_device), GFP_KERNEL);
if (!device) {
dbgprintf("%s: Memory allocation error\n", __FUNCTION__);
return -ENOMEM;
}
 
INIT_LIST_HEAD(&device->pnp.ids);
device->device_type = type;
device->handle = handle;
device->parent = acpi_bus_get_parent(handle);
device->bus_ops = *ops; /* workround for not call .start */
STRUCT_TO_INT(device->status) = sta;
 
acpi_device_get_busid(device);
 
/*
* Flags
* -----
* Note that we only look for object handles -- cannot evaluate objects
* until we know the device is present and properly initialized.
* All supported architectures that use ACPI have support for
* PCI domains, so we indicate this in _OSC support capabilities.
*/
result = acpi_bus_get_flags(device);
if (result)
goto end;
// flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
// acpi_pci_osc_support(root, flags);
 
/*
* Initialize Device
* -----------------
* TBD: Synch with Core's enumeration/initialization process.
* TBD: Need PCI interface for enumeration/configuration of roots.
*/
acpi_device_set_id(device);
 
/* TBD: Locking */
list_add_tail(&root->node, &acpi_pci_roots);
 
if ((result = acpi_device_set_context(device)))
goto end;
printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n",
acpi_device_name(device), acpi_device_bid(device),
root->segment, &root->secondary);
 
result = acpi_device_register(device);
 
/*
* Bind _ADR-Based Devices when hot add
* Scan the Root Bridge
* --------------------
* Must do this prior to any attempt to bind the root device, as the
* PCI namespace does not get created until this call is made (and
* thus the root bridge's pci_dev does not exist).
*/
// if (device->flags.bus_address) {
// if (device->parent && device->parent->ops.bind)
// device->parent->ops.bind(device);
// }
 
end:
if (!result) {
AcpiGetName(handle, ACPI_FULL_PATHNAME, &buffer);
dbgprintf("Adding [%s]\n", (char *)buffer.Pointer);
kfree(buffer.Pointer);
*child = device;
};
return result;
root->bus = pci_acpi_scan_root(root);
if (!root->bus) {
printk(KERN_ERR PREFIX
"Bus %04x:%02x not present in PCI namespace\n",
root->segment, (unsigned int)root->secondary.start);
result = -ENODEV;
goto end;
}
 
 
 
 
static ACPI_STATUS acpi_bus_check_add(ACPI_HANDLE handle, u32 lvl,
void *context, void **return_value)
{
struct acpi_bus_ops *ops = context;
int type;
unsigned long long sta;
struct acpi_device *device;
ACPI_STATUS status;
int result;
 
result = acpi_bus_type_and_status(handle, &type, &sta);
 
if (result)
{
return AE_OK;
};
 
if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
!(sta & ACPI_STA_DEVICE_FUNCTIONING))
{
return AE_CTRL_DEPTH;
};
 
/*
* We may already have an acpi_device from a previous enumeration. If
* so, we needn't add it again, but we may still have to start it.
* Attach ACPI-PCI Context
* -----------------------
* Thus binding the ACPI and PCI devices.
*/
device = NULL;
acpi_bus_get_device(handle, &device);
if (ops->acpi_op_add && !device)
acpi_add_single_object(&device, handle, type, sta, ops);
// result = acpi_pci_bind_root(device);
// if (result)
// goto end;
 
if (!device)
{
return AE_CTRL_DEPTH;
};
/*
if (ops->acpi_op_start && !(ops->acpi_op_add)) {
status = acpi_start_single_object(device);
if (ACPI_FAILURE(status))
return AE_CTRL_DEPTH;
}
* PCI Routing Table
* -----------------
* Evaluate and parse _PRT, if exists.
*/
 
if (!*return_value)
*return_value = device;
 
return AE_OK;
}
 
 
 
static int acpi_bus_scan(ACPI_HANDLE handle, struct acpi_bus_ops *ops,
struct acpi_device **child)
{
ACPI_STATUS status;
void *device = NULL;
 
ENTER();
 
status = acpi_bus_check_add(handle, 0, ops, &device);
 
status = AcpiGetHandle(device->handle, METHOD_NAME__PRT, &handle);
if (ACPI_SUCCESS(status))
AcpiWalkNamespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
acpi_bus_check_add, NULL, ops, &device);
result = acpi_pci_irq_add_prt(device->handle, root->bus);
 
if (child)
*child = device;
/*
* Scan and bind all _ADR-Based Devices
*/
// list_for_each_entry(child, &device->children, node)
// acpi_pci_bridge_scan(child);
 
LEAVE();
return 0;
 
if (device)
return 0;
else
return -ENODEV;
end:
if (!list_empty(&root->node))
list_del(&root->node);
kfree(root);
return result;
}
 
 
 
int acpi_scan()
static const struct acpi_device_ids root_device_ids[] =
{
int err;
struct acpi_bus_ops ops;
 
memset(&ops, 0, sizeof(ops));
ops.acpi_op_add = 1;
ops.acpi_op_start = 1;
 
err = acpi_bus_scan(ACPI_ROOT_OBJECT, &ops, &acpi_root);
 
return err;
{"PNP0A03", 0},
{"", 0},
};
 
void acpi_init_pci(struct acpi_device *device)
{
struct acpi_device *child;
 
enum pic_mode
if ( !acpi_match_device_ids(device, root_device_ids) )
{
IO_PIC = 0,
IO_APIC
dbgprintf(PREFIX "PCI root %s\n", device->pnp.bus_id);
acpi_pci_root_add(device);
};
 
static void set_pic_mode(enum pic_mode mode)
{
ACPI_OBJECT arg1;
ACPI_OBJECT_LIST args;
ACPI_STATUS as;
 
arg1.Type = ACPI_TYPE_INTEGER;
arg1.Integer.Value = mode;
args.Count = 1;
args.Pointer = &arg1;
 
as = AcpiEvaluateObject(ACPI_ROOT_OBJECT, "_PIC", &args, NULL);
/*
* We can silently ignore failure as it may not be implemented, ACPI should
* provide us with correct information anyway
*/
if (ACPI_SUCCESS(as))
dbgprintf("ACPI: machine set to %s mode\n", mode ? "APIC" : "PIC");
}
 
void print_device_tree(struct acpi_device *device)
{
struct acpi_device *child;
 
dbgprintf("%s\n", device->pnp.bus_id);
 
list_for_each_entry(child, &device->children, node)
{
print_device_tree(child);
acpi_init_pci(child);
};
 
};
 
 
u32_t drvEntry(int action, char *cmdline)
{
u32_t retval;
1004,74 → 645,12
 
set_pic_mode(IO_APIC);
 
#if 0
scan_devices();
acpi_scan();
 
{
bool retval = false;
u32_t bus, last_bus;
// print_device_tree(acpi_root);
 
if( (last_bus = PciApi(1))==-1)
return retval;
acpi_init_pci(acpi_root);
 
dbgprintf("last bus %x\n", last_bus);
 
for(bus=0; bus <= last_bus; bus++)
{
u32_t dev;
 
for(dev = 0; dev < 32; dev++)
{
u32_t fn;
 
for(fn = 0; fn < 8; fn++)
{
 
u32_t id;
u32_t irq_bios, irq_acpi;
u32_t irq_pin;
u16_t pcicmd;
u32_t tmp;
 
u32_t devfn = (dev<<3 )|fn;
 
id = PciRead32(bus,devfn, PCI_VENDOR_ID);
 
/* some broken boards return 0 or ~0 if a slot is empty: */
if (id == 0xffffffff || id == 0x00000000 ||
id == 0x0000ffff || id == 0xffff0000)
continue;
 
pcicmd = PciRead16(bus,devfn, PCI_COMMAND);
if (! pcicmd & PCI_COMMAND_IO)
continue;
 
tmp = PciRead32(bus,devfn, 0x3C);
 
irq_bios = tmp & 0xFF;
irq_pin = (tmp >> 8) & 0xFF;
 
int slot = (fn >> 3) & 0x1f;
 
irq_acpi = irqtable[ dev * PCI_MAX_PINS +(irq_pin-1) ];
 
if( irq_acpi < 0)
dbgprintf("PCI: no ACPI IRQ routing for "
"device %d.%d.%d INT%c\n",bus,dev,fn,'A'+irq_pin-1);
 
dbgprintf("pci device %x_%x bus %d dev %d fn %d,"
"IRQ PIN %d BIOS IRQ %d ACPI IRQ %d\n",
id & 0xFFFF, id>>16, bus, dev, fn, irq_pin, irq_bios, irq_acpi);
};
}
};
};
#endif
 
acpi_scan();
 
print_device_tree(acpi_root);
 
/*
ACPI_HANDLE bus_handle;
ACPI_HANDLE pci_root;
1182,7 → 761,71
 
};
 
#if 0
scan_devices();
 
{
bool retval = false;
u32_t bus, last_bus;
 
if( (last_bus = PciApi(1))==-1)
return retval;
 
dbgprintf("last bus %x\n", last_bus);
 
for(bus=0; bus <= last_bus; bus++)
{
u32_t dev;
 
for(dev = 0; dev < 32; dev++)
{
u32_t fn;
 
for(fn = 0; fn < 8; fn++)
{
 
u32_t id;
u32_t irq_bios, irq_acpi;
u32_t irq_pin;
u16_t pcicmd;
u32_t tmp;
 
u32_t devfn = (dev<<3 )|fn;
 
id = PciRead32(bus,devfn, PCI_VENDOR_ID);
 
/* some broken boards return 0 or ~0 if a slot is empty: */
if (id == 0xffffffff || id == 0x00000000 ||
id == 0x0000ffff || id == 0xffff0000)
continue;
 
pcicmd = PciRead16(bus,devfn, PCI_COMMAND);
if (! pcicmd & PCI_COMMAND_IO)
continue;
 
tmp = PciRead32(bus,devfn, 0x3C);
 
irq_bios = tmp & 0xFF;
irq_pin = (tmp >> 8) & 0xFF;
 
int slot = (fn >> 3) & 0x1f;
 
irq_acpi = irqtable[ dev * PCI_MAX_PINS +(irq_pin-1) ];
 
if( irq_acpi < 0)
dbgprintf("PCI: no ACPI IRQ routing for "
"device %d.%d.%d INT%c\n",bus,dev,fn,'A'+irq_pin-1);
 
dbgprintf("pci device %x_%x bus %d dev %d fn %d,"
"IRQ PIN %d BIOS IRQ %d ACPI IRQ %d\n",
id & 0xFFFF, id>>16, bus, dev, fn, irq_pin, irq_bios, irq_acpi);
};
}
};
};
#endif
 
 
#if 0
 
ACPI_STATUS
1379,3 → 1022,15
}
 
#endif
 
char* strdup(const char *str)
{
size_t len = strlen (str) + 1;
char *copy = malloc(len);
if (copy)
{
memcpy (copy, str, len);
}
return copy;
}
 
/drivers/devman/acpi_bus.h
0,0 → 1,128
 
 
struct resource_list {
struct resource_list *next;
struct resource *res;
// struct pci_dev *dev;
};
 
enum acpi_bus_device_type {
ACPI_BUS_TYPE_DEVICE = 0,
ACPI_BUS_TYPE_POWER,
ACPI_BUS_TYPE_PROCESSOR,
ACPI_BUS_TYPE_THERMAL,
ACPI_BUS_TYPE_POWER_BUTTON,
ACPI_BUS_TYPE_SLEEP_BUTTON,
ACPI_BUS_DEVICE_TYPE_COUNT
};
 
/*
* _HID definitions
* HIDs must conform to ACPI spec(6.1.4)
* KolibriOS specific HIDs do not apply to this and begin with KOS:
*/
 
 
#define ACPI_POWER_HID "KLBPOWER"
#define ACPI_PROCESSOR_OBJECT_HID "KLBCPU"
#define ACPI_SYSTEM_HID "KLBSYSTM"
#define ACPI_THERMAL_HID "KLBTHERM"
#define ACPI_BUTTON_HID_POWERF "KLBPWRBN"
#define ACPI_BUTTON_HID_SLEEPF "KLBSLPBN"
#define ACPI_VIDEO_HID "KLBVIDEO"
#define ACPI_BAY_HID "KLBIOBAY"
#define ACPI_DOCK_HID "KLBDOCK"
/* Quirk for broken IBM BIOSes */
#define ACPI_SMBUS_IBM_HID "SMBUSIBM"
 
 
struct acpi_bus_ops
{
u32_t acpi_op_add:1;
u32_t acpi_op_start:1;
};
 
 
#define ACPI_ID_LEN 16 /* only 9 bytes needed here, 16 bytes are used */
/* to workaround crosscompile issues */
 
struct acpi_device_ids
{
u8 id[ACPI_ID_LEN];
u32 driver_data;
};
 
struct acpi_device_flags {
u32 dynamic_status:1;
u32 bus_address:1;
u32 removable:1;
u32 ejectable:1;
u32 lockable:1;
u32 suprise_removal_ok:1;
u32 power_manageable:1;
u32 performance_manageable:1;
u32 wake_capable:1; /* Wakeup(_PRW) supported? */
u32 force_power_state:1;
u32 reserved:22;
};
 
struct acpi_device_status {
u32 present:1;
u32 enabled:1;
u32 show_in_ui:1;
u32 functional:1;
u32 battery_present:1;
u32 reserved:27;
};
typedef char acpi_bus_id[8];
typedef unsigned long acpi_bus_address;
typedef char acpi_device_name[40];
typedef char acpi_device_class[20];
 
 
struct acpi_device_pnp
{
acpi_bus_id bus_id; /* Object name */
acpi_bus_address bus_address; /* _ADR */
char *unique_id; /* _UID */
struct list_head ids; /* _HID and _CIDs */
acpi_device_name device_name; /* Driver-determined */
acpi_device_class device_class; /* " */
};
 
 
struct acpi_device
{
int device_type;
ACPI_HANDLE handle; /* no handle for fixed hardware */
struct acpi_device *parent;
struct list_head children;
struct list_head node;
// struct list_head wakeup_list;
struct acpi_device_status status;
struct acpi_device_flags flags;
struct acpi_device_pnp pnp;
// struct acpi_device_power power;
// struct acpi_device_wakeup wakeup;
// struct acpi_device_perf performance;
// struct acpi_device_dir dir;
// struct acpi_device_ops ops;
// struct acpi_driver *driver;
void *driver_data;
// struct device dev;
struct acpi_bus_ops bus_ops; /* workaround for different code path for hotplug */
// enum acpi_bus_removal_type removal_type; /* indicate for different removal type */
};
 
 
 
#define acpi_device_bid(d) ((d)->pnp.bus_id)
#define acpi_device_adr(d) ((d)->pnp.bus_address)
char *acpi_device_hid(struct acpi_device *device);
#define acpi_device_name(d) ((d)->pnp.device_name)
#define acpi_device_class(d) ((d)->pnp.device_class)
 
int acpi_match_device_ids(struct acpi_device *device,
const struct acpi_device_ids *ids);
 
int acpi_pci_irq_add_prt(ACPI_HANDLE handle, struct pci_bus *bus);
/drivers/devman/pci/pci.c
0,0 → 1,151
 
#include <ddk.h>
#include <linux/errno.h>
#include <mutex.h>
#include <pci.h>
#include <syscall.h>
 
LIST_HEAD(pci_root_buses);
 
#define IO_SPACE_LIMIT 0xffff
 
struct resource ioport_resource = {
.name = "PCI IO",
.start = 0,
.end = IO_SPACE_LIMIT,
.flags = IORESOURCE_IO,
};
 
struct resource iomem_resource = {
.name = "PCI mem",
.start = 0,
.end = -1,
.flags = IORESOURCE_MEM,
};
 
 
static inline int pci_domain_nr(struct pci_bus *bus)
{
struct pci_sysdata *sd = bus->sysdata;
return sd->domain;
}
 
static struct pci_bus * pci_alloc_bus(void)
{
struct pci_bus *b;
 
b = kzalloc(sizeof(*b), GFP_KERNEL);
if (b) {
INIT_LIST_HEAD(&b->node);
INIT_LIST_HEAD(&b->children);
INIT_LIST_HEAD(&b->devices);
INIT_LIST_HEAD(&b->slots);
INIT_LIST_HEAD(&b->resources);
}
return b;
}
 
struct pci_bus * pci_create_bus(int bus, struct pci_ops *ops, void *sysdata)
{
int error;
struct pci_bus *b, *b2;
 
b = pci_alloc_bus();
if (!b)
return NULL;
 
b->sysdata = sysdata;
b->ops = ops;
 
b2 = pci_find_bus(pci_domain_nr(b), bus);
if (b2) {
/* If we already got to this bus through a different bridge, ignore it */
dbgprintf("bus already known\n");
goto err_out;
}
 
// down_write(&pci_bus_sem);
list_add_tail(&b->node, &pci_root_buses);
// up_write(&pci_bus_sem);
 
b->number = b->secondary = bus;
b->resource[0] = &ioport_resource;
b->resource[1] = &iomem_resource;
 
return b;
 
err_out:
kfree(b);
return NULL;
}
 
 
 
 
 
static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)
{
struct pci_bus* child;
struct list_head *tmp;
 
if(bus->number == busnr)
return bus;
 
list_for_each(tmp, &bus->children) {
child = pci_do_find_bus(pci_bus_b(tmp), busnr);
if(child)
return child;
}
return NULL;
}
 
 
/**
* pci_find_bus - locate PCI bus from a given domain and bus number
* @domain: number of PCI domain to search
* @busnr: number of desired PCI bus
*
* Given a PCI bus number and domain number, the desired PCI bus is located
* in the global list of PCI buses. If the bus is found, a pointer to its
* data structure is returned. If no bus is found, %NULL is returned.
*/
struct pci_bus * pci_find_bus(int domain, int busnr)
{
struct pci_bus *bus = NULL;
struct pci_bus *tmp_bus;
 
while ((bus = pci_find_next_bus(bus)) != NULL) {
if (pci_domain_nr(bus) != domain)
continue;
tmp_bus = pci_do_find_bus(bus, busnr);
if (tmp_bus)
return tmp_bus;
}
return NULL;
}
 
/**
* pci_find_next_bus - begin or continue searching for a PCI bus
* @from: Previous PCI bus found, or %NULL for new search.
*
* Iterates through the list of known PCI busses. A new search is
* initiated by passing %NULL as the @from argument. Otherwise if
* @from is not %NULL, searches continue from next device on the
* global list.
*/
struct pci_bus *
pci_find_next_bus(const struct pci_bus *from)
{
struct list_head *n;
struct pci_bus *b = NULL;
 
// WARN_ON(in_interrupt());
// down_read(&pci_bus_sem);
n = from ? from->node.next : pci_root_buses.next;
if (n != &pci_root_buses)
b = pci_bus_b(n);
// up_read(&pci_bus_sem);
return b;
}
 
 
/drivers/devman/pci_irq.c
0,0 → 1,131
 
#include <ddk.h>
#include <linux/errno.h>
#include <mutex.h>
#include <linux/spinlock.h>
#include <pci.h>
#include <syscall.h>
 
#include "acpi.h"
#include "acpi_bus.h"
 
#define PREFIX "ACPI: "
 
struct acpi_prt_entry
{
struct list_head list;
ACPI_PCI_ID id;
u8 pin;
ACPI_HANDLE link;
u32 index; /* GSI, or link _CRS index */
};
 
static LIST_HEAD(acpi_prt_list);
static DEFINE_SPINLOCK(acpi_prt_lock);
 
static inline char pin_name(int pin)
{
return 'A' + pin - 1;
}
 
 
static int acpi_pci_irq_add_entry(ACPI_HANDLE handle, struct pci_bus *bus,
struct acpi_pci_routing_table *prt)
{
struct acpi_prt_entry *entry;
 
entry = kzalloc(sizeof(struct acpi_prt_entry), GFP_KERNEL);
if (!entry)
return -ENOMEM;
 
/*
* Note that the _PRT uses 0=INTA, 1=INTB, etc, while PCI uses
* 1=INTA, 2=INTB. We use the PCI encoding throughout, so convert
* it here.
*/
entry->id.Segment = pci_domain_nr(bus);
entry->id.Bus = bus->number;
entry->id.Device = (prt->Address >> 16) & 0xFFFF;
entry->pin = prt->Pin + 1;
 
// do_prt_fixups(entry, prt);
 
entry->index = prt->SourceIndex;
 
/*
* Type 1: Dynamic
* ---------------
* The 'source' field specifies the PCI interrupt link device used to
* configure the IRQ assigned to this slot|dev|pin. The 'source_index'
* indicates which resource descriptor in the resource template (of
* the link device) this interrupt is allocated from.
*
* NOTE: Don't query the Link Device for IRQ information at this time
* because Link Device enumeration may not have occurred yet
* (e.g. exists somewhere 'below' this _PRT entry in the ACPI
* namespace).
*/
if (prt->Source[0])
AcpiGetHandle(handle, prt->Source, &entry->link);
 
/*
* Type 2: Static
* --------------
* The 'source' field is NULL, and the 'source_index' field specifies
* the IRQ value, which is hardwired to specific interrupt inputs on
* the interrupt controller.
*/
 
dbgprintf(PREFIX " %04x:%02x:%02x[%c] -> %s[%d]\n",
entry->id.Segment, entry->id.Bus,
entry->id.Device, pin_name(entry->pin),
prt->Source, entry->index);
 
spin_lock(&acpi_prt_lock);
list_add_tail(&entry->list, &acpi_prt_list);
spin_unlock(&acpi_prt_lock);
 
return 0;
}
 
 
 
int acpi_pci_irq_add_prt(ACPI_HANDLE handle, struct pci_bus *bus)
{
ACPI_STATUS status;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_pci_routing_table *entry;
 
/* 'handle' is the _PRT's parent (root bridge or PCI-PCI bridge) */
status = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buffer);
if (ACPI_FAILURE(status))
return -ENODEV;
 
printk(KERN_DEBUG "ACPI: PCI Interrupt Routing Table [%s._PRT]\n",
(char *) buffer.Pointer);
 
kfree(buffer.Pointer);
 
buffer.Length = ACPI_ALLOCATE_BUFFER;
buffer.Pointer = NULL;
 
status = AcpiGetIrqRoutingTable(handle, &buffer);
if (ACPI_FAILURE(status))
{
dbgprintf("AcpiGetIrqRoutingTable failed "
"evaluating _PRT [%s]\n",AcpiFormatException(status));
kfree(buffer.Pointer);
return -ENODEV;
}
 
entry = buffer.Pointer;
while (entry && (entry->Length > 0)) {
acpi_pci_irq_add_entry(handle, bus, entry);
entry = (struct acpi_pci_routing_table *)
((unsigned long)entry + entry->Length);
}
 
kfree(buffer.Pointer);
return 0;
}
 
/drivers/devman/scan.c
0,0 → 1,766
 
 
#include <ddk.h>
#include <linux/errno.h>
#include <mutex.h>
#include <pci.h>
#include <syscall.h>
 
#include "acpi.h"
#include "acpi_bus.h"
 
 
#define PREFIX "ACPI: "
 
#define ACPI_BUS_CLASS "system_bus"
#define ACPI_BUS_HID "KLBSYBUS"
#define ACPI_BUS_DEVICE_NAME "System Bus"
 
 
#define ACPI_IS_ROOT_DEVICE(device) (!(device)->parent)
 
#define STRUCT_TO_INT(s) (*((int*)&s))
 
 
extern struct acpi_device *acpi_root;
 
static LIST_HEAD(acpi_device_list);
static LIST_HEAD(acpi_bus_id_list);
DEFINE_MUTEX(acpi_device_lock);
 
 
struct acpi_device_bus_id{
char bus_id[15];
unsigned int instance_no;
struct list_head node;
};
 
 
struct acpi_hardware_id {
struct list_head list;
char *id;
};
 
#define acpi_device_name(d) ((d)->pnp.device_name)
#define acpi_device_class(d) ((d)->pnp.device_class)
 
 
static void
acpi_util_eval_error(ACPI_HANDLE h, ACPI_STRING p, ACPI_STATUS s)
{
#ifdef ACPI_DEBUG_OUTPUT
char prefix[80] = {'\0'};
ACPI_BUFFER buffer = {sizeof(prefix), prefix};
AcpiGetName(h, ACPI_FULL_PATHNAME, &buffer);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n",
(char *) prefix, p, AcpiFormatException(s)));
#else
return;
#endif
}
 
ACPI_STATUS
acpi_evaluate_integer(ACPI_HANDLE handle, ACPI_STRING pathname,
ACPI_OBJECT_LIST *arguments, unsigned long long *data)
{
ACPI_STATUS status = AE_OK;
ACPI_OBJECT element;
ACPI_BUFFER buffer = { 0, NULL };
 
if (!data)
return AE_BAD_PARAMETER;
 
buffer.Length = sizeof(ACPI_OBJECT);
buffer.Pointer = &element;
status = AcpiEvaluateObject(handle, pathname, arguments, &buffer);
if (ACPI_FAILURE(status)) {
acpi_util_eval_error(handle, pathname, status);
return status;
}
 
if (element.Type != ACPI_TYPE_INTEGER) {
acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
return AE_BAD_DATA;
}
 
*data = element.Integer.Value;
 
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%llu]\n", *data));
 
return AE_OK;
}
 
 
void acpi_bus_data_handler(ACPI_HANDLE handle, void *context)
{
 
/* TBD */
 
return;
}
 
int acpi_bus_get_device(ACPI_HANDLE handle, struct acpi_device **device)
{
ACPI_STATUS status = AE_OK;
 
if (!device)
{
return -EINVAL;
};
 
/* TBD: Support fixed-feature devices */
 
status = AcpiGetData(handle, acpi_bus_data_handler, (void **)device);
if (ACPI_FAILURE(status) || !*device) {
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n",
handle));
return -ENODEV;
}
return 0;
}
 
 
ACPI_STATUS acpi_bus_get_status_handle(ACPI_HANDLE handle,
unsigned long long *sta)
{
ACPI_STATUS status;
 
status = acpi_evaluate_integer(handle, "_STA", NULL, sta);
if (ACPI_SUCCESS(status))
{
return AE_OK;
};
 
if (status == AE_NOT_FOUND)
{
*sta = ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED |
ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING;
return AE_OK;
}
return status;
}
 
 
 
/* --------------------------------------------------------------------------
ACPI Bus operations
-------------------------------------------------------------------------- */
 
int acpi_match_device_ids(struct acpi_device *device,
const struct acpi_device_ids *ids)
{
const struct acpi_device_ids *id;
struct acpi_hardware_id *hwid;
 
/*
* If the device is not present, it is unnecessary to load device
* driver for it.
*/
// if (!device->status.present)
// return -ENODEV;
 
for (id = ids; id->id[0]; id++)
list_for_each_entry(hwid, &device->pnp.ids, list)
if (!strcmp((char *) id->id, hwid->id))
return 0;
 
return -ENOENT;
}
 
 
static int acpi_device_register(struct acpi_device *device)
{
int result;
struct acpi_device_bus_id *acpi_device_bus_id, *new_bus_id;
int found = 0;
 
/*
* Linkage
* -------
* Link this device to its parent and siblings.
*/
INIT_LIST_HEAD(&device->children);
INIT_LIST_HEAD(&device->node);
 
new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
if (!new_bus_id) {
printk(KERN_ERR PREFIX "Memory allocation error\n");
return -ENOMEM;
}
 
mutex_lock(&acpi_device_lock);
/*
* Find suitable bus_id and instance number in acpi_bus_id_list
* If failed, create one and link it into acpi_bus_id_list
*/
list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node)
{
if (!strcmp(acpi_device_bus_id->bus_id,
acpi_device_hid(device)))
{
acpi_device_bus_id->instance_no++;
found = 1;
kfree(new_bus_id);
break;
}
};
 
if (!found)
{
acpi_device_bus_id = new_bus_id;
strcpy(acpi_device_bus_id->bus_id, acpi_device_hid(device));
acpi_device_bus_id->instance_no = 0;
list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list);
}
 
// dev_set_name(&device->dev, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no);
 
if (device->parent)
list_add_tail(&device->node, &device->parent->children);
 
mutex_unlock(&acpi_device_lock);
 
// device->dev.bus = &acpi_bus_type;
// device->dev.release = &acpi_device_release;
// result = device_register(&device->dev);
// if (result) {
// dev_err(&device->dev, "Error registering device\n");
// goto end;
// }
 
 
// device->removal_type = ACPI_BUS_REMOVAL_NORMAL;
return 0;
end:
mutex_lock(&acpi_device_lock);
if (device->parent)
list_del(&device->node);
mutex_unlock(&acpi_device_lock);
return result;
}
 
 
static struct acpi_device *acpi_bus_get_parent(ACPI_HANDLE handle)
{
ACPI_STATUS status;
struct acpi_device *device;
int ret;
 
/*
* Fixed hardware devices do not appear in the namespace and do not
* have handles, but we fabricate acpi_devices for them, so we have
* to deal with them specially.
*/
if (handle == NULL)
return acpi_root;
 
do {
status = AcpiGetParent(handle, &handle);
if (status == AE_NULL_ENTRY)
return NULL;
if (ACPI_FAILURE(status))
return acpi_root;
 
ret = acpi_bus_get_device(handle, &device);
if (ret == 0)
return device;
} while (1);
}
 
 
static int acpi_bus_get_flags(struct acpi_device *device)
{
ACPI_STATUS status = AE_OK;
ACPI_HANDLE temp = NULL;
 
/* Presence of _STA indicates 'dynamic_status' */
status = AcpiGetHandle(device->handle, "_STA", &temp);
if (ACPI_SUCCESS(status))
device->flags.dynamic_status = 1;
 
/* Presence of _RMV indicates 'removable' */
status = AcpiGetHandle(device->handle, "_RMV", &temp);
if (ACPI_SUCCESS(status))
device->flags.removable = 1;
 
/* Presence of _EJD|_EJ0 indicates 'ejectable' */
status = AcpiGetHandle(device->handle, "_EJD", &temp);
if (ACPI_SUCCESS(status))
device->flags.ejectable = 1;
else {
status = AcpiGetHandle(device->handle, "_EJ0", &temp);
if (ACPI_SUCCESS(status))
device->flags.ejectable = 1;
}
 
/* Presence of _LCK indicates 'lockable' */
status = AcpiGetHandle(device->handle, "_LCK", &temp);
if (ACPI_SUCCESS(status))
device->flags.lockable = 1;
 
/* Presence of _PS0|_PR0 indicates 'power manageable' */
status = AcpiGetHandle(device->handle, "_PS0", &temp);
if (ACPI_FAILURE(status))
status = AcpiGetHandle(device->handle, "_PR0", &temp);
if (ACPI_SUCCESS(status))
device->flags.power_manageable = 1;
 
/* Presence of _PRW indicates wake capable */
status = AcpiGetHandle(device->handle, "_PRW", &temp);
if (ACPI_SUCCESS(status))
device->flags.wake_capable = 1;
 
/* TBD: Performance management */
 
return 0;
}
 
static void acpi_device_get_busid(struct acpi_device *device)
{
char bus_id[5] = { '?', 0 };
struct acpi_buffer buffer = { sizeof(bus_id), bus_id };
int i = 0;
 
/*
* Bus ID
* ------
* The device's Bus ID is simply the object name.
* TBD: Shouldn't this value be unique (within the ACPI namespace)?
*/
if (ACPI_IS_ROOT_DEVICE(device)) {
strcpy(device->pnp.bus_id, "ACPI");
return;
}
 
switch (device->device_type)
{
case ACPI_BUS_TYPE_POWER_BUTTON:
strcpy(device->pnp.bus_id, "PWRF");
break;
case ACPI_BUS_TYPE_SLEEP_BUTTON:
strcpy(device->pnp.bus_id, "SLPF");
break;
default:
AcpiGetName(device->handle, ACPI_SINGLE_NAME, &buffer);
/* Clean up trailing underscores (if any) */
for (i = 3; i > 1; i--) {
if (bus_id[i] == '_')
bus_id[i] = '\0';
else
break;
}
strcpy(device->pnp.bus_id, bus_id);
break;
}
}
 
 
#define ACPI_VIDEO_OUTPUT_SWITCHING 0x0001
#define ACPI_VIDEO_DEVICE_POSTING 0x0002
#define ACPI_VIDEO_ROM_AVAILABLE 0x0004
#define ACPI_VIDEO_BACKLIGHT 0x0008
#define ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR 0x0010
#define ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO 0x0020
#define ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VENDOR 0x0040
#define ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO 0x0080
#define ACPI_VIDEO_BACKLIGHT_DMI_VENDOR 0x0100
#define ACPI_VIDEO_BACKLIGHT_DMI_VIDEO 0x0200
#define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VENDOR 0x0400
#define ACPI_VIDEO_OUTPUT_SWITCHING_DMI_VIDEO 0x0800
 
 
long acpi_is_video_device(struct acpi_device *device)
{
ACPI_HANDLE h_dummy;
long video_caps = 0;
 
if (!device)
return 0;
 
/* Is this device able to support video switching ? */
if (ACPI_SUCCESS(AcpiGetHandle(device->handle, "_DOD", &h_dummy)) ||
ACPI_SUCCESS(AcpiGetHandle(device->handle, "_DOS", &h_dummy)))
video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING;
 
/* Is this device able to retrieve a video ROM ? */
if (ACPI_SUCCESS(AcpiGetHandle(device->handle, "_ROM", &h_dummy)))
video_caps |= ACPI_VIDEO_ROM_AVAILABLE;
 
/* Is this device able to configure which video head to be POSTed ? */
if (ACPI_SUCCESS(AcpiGetHandle(device->handle, "_VPO", &h_dummy)) &&
ACPI_SUCCESS(AcpiGetHandle(device->handle, "_GPD", &h_dummy)) &&
ACPI_SUCCESS(AcpiGetHandle(device->handle, "_SPD", &h_dummy)))
video_caps |= ACPI_VIDEO_DEVICE_POSTING;
 
return video_caps;
}
 
/*
* acpi_bay_match - see if a device is an ejectable driver bay
*
* If an acpi object is ejectable and has one of the ACPI ATA methods defined,
* then we can safely call it an ejectable drive bay
*/
static int acpi_bay_match(struct acpi_device *device){
ACPI_STATUS status;
ACPI_HANDLE handle;
ACPI_HANDLE tmp;
ACPI_HANDLE phandle;
 
handle = device->handle;
 
status = AcpiGetHandle(handle, "_EJ0", &tmp);
if (ACPI_FAILURE(status))
return -ENODEV;
 
if ((ACPI_SUCCESS(AcpiGetHandle(handle, "_GTF", &tmp))) ||
(ACPI_SUCCESS(AcpiGetHandle(handle, "_GTM", &tmp))) ||
(ACPI_SUCCESS(AcpiGetHandle(handle, "_STM", &tmp))) ||
(ACPI_SUCCESS(AcpiGetHandle(handle, "_SDD", &tmp))))
return 0;
 
if (AcpiGetParent(handle, &phandle))
return -ENODEV;
 
if ((ACPI_SUCCESS(AcpiGetHandle(phandle, "_GTF", &tmp))) ||
(ACPI_SUCCESS(AcpiGetHandle(phandle, "_GTM", &tmp))) ||
(ACPI_SUCCESS(AcpiGetHandle(phandle, "_STM", &tmp))) ||
(ACPI_SUCCESS(AcpiGetHandle(phandle, "_SDD", &tmp))))
return 0;
 
return -ENODEV;
}
 
/*
* acpi_dock_match - see if a device has a _DCK method
*/
static int acpi_dock_match(struct acpi_device *device)
{
ACPI_HANDLE tmp;
return AcpiGetHandle(device->handle, "_DCK", &tmp);
}
 
char *acpi_device_hid(struct acpi_device *device)
{
struct acpi_hardware_id *hid;
 
hid = list_first_entry(&device->pnp.ids, struct acpi_hardware_id, list);
return hid->id;
}
 
static void acpi_add_id(struct acpi_device *device, const char *dev_id)
{
struct acpi_hardware_id *id;
 
id = kmalloc(sizeof(*id), GFP_KERNEL);
if (!id)
return;
 
INIT_LIST_HEAD(&id->list);
 
id->id = kmalloc(strlen(dev_id) + 1, GFP_KERNEL);
if (!id->id) {
kfree(id);
return;
}
 
strcpy(id->id, dev_id);
list_add_tail(&id->list, &device->pnp.ids);
}
 
 
 
static void acpi_device_set_id(struct acpi_device *device)
{
ACPI_STATUS status;
ACPI_DEVICE_INFO *info;
ACPI_DEVICE_ID_LIST *cid_list;
int i;
 
switch (device->device_type)
{
case ACPI_BUS_TYPE_DEVICE:
if (ACPI_IS_ROOT_DEVICE(device)) {
acpi_add_id(device, ACPI_SYSTEM_HID);
break;
}
 
status = AcpiGetObjectInfo(device->handle, &info);
if (ACPI_FAILURE(status)) {
printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__);
return;
}
 
if (info->Valid & ACPI_VALID_HID)
acpi_add_id(device, info->HardwareId.String);
if (info->Valid & ACPI_VALID_CID)
{
cid_list = &info->CompatibleIdList;
for (i = 0; i < cid_list->Count; i++)
acpi_add_id(device, cid_list->Ids[i].String);
}
if (info->Valid & ACPI_VALID_ADR) {
device->pnp.bus_address = info->Address;
device->flags.bus_address = 1;
}
 
kfree(info);
 
/*
* Some devices don't reliably have _HIDs & _CIDs, so add
* synthetic HIDs to make sure drivers can find them.
*/
if (acpi_is_video_device(device))
acpi_add_id(device, ACPI_VIDEO_HID);
else if (ACPI_SUCCESS(acpi_bay_match(device)))
acpi_add_id(device, ACPI_BAY_HID);
else if (ACPI_SUCCESS(acpi_dock_match(device)))
acpi_add_id(device, ACPI_DOCK_HID);
else if (!acpi_device_hid(device) &&
ACPI_IS_ROOT_DEVICE(device->parent)) {
acpi_add_id(device, ACPI_BUS_HID); /* \_SB, LNXSYBUS */
strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME);
strcpy(device->pnp.device_class, ACPI_BUS_CLASS);
}
 
break;
case ACPI_BUS_TYPE_POWER:
acpi_add_id(device, ACPI_POWER_HID);
break;
case ACPI_BUS_TYPE_PROCESSOR:
acpi_add_id(device, ACPI_PROCESSOR_OBJECT_HID);
break;
case ACPI_BUS_TYPE_THERMAL:
acpi_add_id(device, ACPI_THERMAL_HID);
break;
case ACPI_BUS_TYPE_POWER_BUTTON:
acpi_add_id(device, ACPI_BUTTON_HID_POWERF);
break;
case ACPI_BUS_TYPE_SLEEP_BUTTON:
acpi_add_id(device, ACPI_BUTTON_HID_SLEEPF);
break;
}
 
/*
* We build acpi_devices for some objects that don't have _HID or _CID,
* e.g., PCI bridges and slots. Drivers can't bind to these objects,
* but we do use them indirectly by traversing the acpi_device tree.
* This generic ID isn't useful for driver binding, but it provides
* the useful property that "every acpi_device has an ID."
*/
if (list_empty(&device->pnp.ids))
acpi_add_id(device, "device");
}
 
static int acpi_device_set_context(struct acpi_device *device)
{
ACPI_STATUS status;
 
/*
* Context
* -------
* Attach this 'struct acpi_device' to the ACPI object. This makes
* resolutions from handle->device very efficient. Fixed hardware
* devices have no handles, so we skip them.
*/
if (!device->handle)
return 0;
 
status = AcpiAttachData(device->handle,
acpi_bus_data_handler, device);
if (ACPI_SUCCESS(status))
return 0;
 
printk(KERN_ERR PREFIX "Error attaching device data\n");
return -ENODEV;
}
 
 
static int acpi_add_single_object(struct acpi_device **child,
ACPI_HANDLE handle, int type,
unsigned long long sta,
struct acpi_bus_ops *ops)
{
int result;
struct acpi_device *device;
ACPI_BUFFER buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 
device = kzalloc(sizeof(struct acpi_device), GFP_KERNEL);
if (!device) {
printk(KERN_ERR PREFIX "Memory allocation error\n");
return -ENOMEM;
}
 
INIT_LIST_HEAD(&device->pnp.ids);
device->device_type = type;
device->handle = handle;
device->parent = acpi_bus_get_parent(handle);
device->bus_ops = *ops; /* workround for not call .start */
STRUCT_TO_INT(device->status) = sta;
 
acpi_device_get_busid(device);
 
/*
* Flags
* -----
* Note that we only look for object handles -- cannot evaluate objects
* until we know the device is present and properly initialized.
*/
result = acpi_bus_get_flags(device);
if (result)
goto end;
 
/*
* Initialize Device
* -----------------
* TBD: Synch with Core's enumeration/initialization process.
*/
acpi_device_set_id(device);
 
 
if ((result = acpi_device_set_context(device)))
goto end;
 
result = acpi_device_register(device);
 
/*
* Bind _ADR-Based Devices when hot add
*/
// if (device->flags.bus_address) {
// if (device->parent && device->parent->ops.bind)
// device->parent->ops.bind(device);
// }
 
end:
if (!result) {
AcpiGetName(handle, ACPI_FULL_PATHNAME, &buffer);
dbgprintf(PREFIX "Adding [%s]\n", (char *)buffer.Pointer);
kfree(buffer.Pointer);
*child = device;
};
return result;
}
 
#define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \
ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING)
 
static int acpi_bus_type_and_status(ACPI_HANDLE handle, int *type,
unsigned long long *sta)
{
ACPI_STATUS status;
ACPI_OBJECT_TYPE acpi_type;
 
status = AcpiGetType(handle, &acpi_type);
if (ACPI_FAILURE(status))
return -ENODEV;
 
switch (acpi_type)
{
case ACPI_TYPE_ANY: /* for ACPI_ROOT_OBJECT */
case ACPI_TYPE_DEVICE:
*type = ACPI_BUS_TYPE_DEVICE;
status = acpi_bus_get_status_handle(handle, sta);
if (ACPI_FAILURE(status))
return -ENODEV;
break;
case ACPI_TYPE_PROCESSOR:
*type = ACPI_BUS_TYPE_PROCESSOR;
status = acpi_bus_get_status_handle(handle, sta);
if (ACPI_FAILURE(status))
return -ENODEV;
break;
case ACPI_TYPE_THERMAL:
*type = ACPI_BUS_TYPE_THERMAL;
*sta = ACPI_STA_DEFAULT;
break;
case ACPI_TYPE_POWER:
*type = ACPI_BUS_TYPE_POWER;
*sta = ACPI_STA_DEFAULT;
break;
default:
return -ENODEV;
}
 
return 0;
}
 
 
static ACPI_STATUS acpi_bus_check_add(ACPI_HANDLE handle, u32 lvl,
void *context, void **return_value)
{
struct acpi_bus_ops *ops = context;
int type;
unsigned long long sta;
struct acpi_device *device;
ACPI_STATUS status;
int result;
 
result = acpi_bus_type_and_status(handle, &type, &sta);
if (result)
return AE_OK;
 
if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
!(sta & ACPI_STA_DEVICE_FUNCTIONING))
return AE_CTRL_DEPTH;
 
/*
* We may already have an acpi_device from a previous enumeration. If
* so, we needn't add it again, but we may still have to start it.
*/
device = NULL;
acpi_bus_get_device(handle, &device);
if (ops->acpi_op_add && !device)
acpi_add_single_object(&device, handle, type, sta, ops);
 
if (!device)
return AE_CTRL_DEPTH;
 
/*
if (ops->acpi_op_start && !(ops->acpi_op_add)) {
status = acpi_start_single_object(device);
if (ACPI_FAILURE(status))
return AE_CTRL_DEPTH;
}
*/
 
if (!*return_value)
*return_value = device;
return AE_OK;
}
 
 
static int acpi_bus_scan(ACPI_HANDLE handle, struct acpi_bus_ops *ops,
struct acpi_device **child)
{
ACPI_STATUS status;
void *device = NULL;
 
status = acpi_bus_check_add(handle, 0, ops, &device);
if (ACPI_SUCCESS(status))
AcpiWalkNamespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
acpi_bus_check_add, NULL, ops, &device);
 
if (child)
*child = device;
 
if (device)
return 0;
else
return -ENODEV;
}
 
 
int acpi_scan()
{
int err;
struct acpi_bus_ops ops;
 
memset(&ops, 0, sizeof(ops));
ops.acpi_op_add = 1;
ops.acpi_op_start = 1;
 
err = acpi_bus_scan(ACPI_ROOT_OBJECT, &ops, &acpi_root);
 
return err;
};
 
/drivers/include/ddk.h
11,6 → 11,9
 
#define MANUAL_DESTROY 0x80000000
 
#define ENTER() dbgprintf("enter %s\n",__FUNCTION__)
#define LEAVE() dbgprintf("leave %s\n",__FUNCTION__)
 
typedef struct
{
u32_t code;
/drivers/include/linux/pci.h
349,12 → 349,45
{
resource_size_t start;
resource_size_t end;
// const char *name;
const char *name;
unsigned long flags;
// struct resource *parent, *sibling, *child;
struct resource *parent, *sibling, *child;
};
 
 
/*
* For PCI devices, the region numbers are assigned this way:
*/
enum {
/* #0-5: standard PCI resources */
PCI_STD_RESOURCES,
PCI_STD_RESOURCE_END = 5,
 
/* #6: expansion ROM resource */
PCI_ROM_RESOURCE,
 
/* device specific resources */
#ifdef CONFIG_PCI_IOV
PCI_IOV_RESOURCES,
PCI_IOV_RESOURCE_END = PCI_IOV_RESOURCES + PCI_SRIOV_NUM_BARS - 1,
#endif
 
/* resources assigned to buses behind the bridge */
#define PCI_BRIDGE_RESOURCE_NUM 4
 
PCI_BRIDGE_RESOURCES,
PCI_BRIDGE_RESOURCE_END = PCI_BRIDGE_RESOURCES +
PCI_BRIDGE_RESOURCE_NUM - 1,
 
/* total resources associated with a PCI device */
PCI_NUM_RESOURCES,
 
/* preserve this for compatibility */
DEVICE_COUNT_RESOURCE
};
 
 
/*
* IO resources have these defined flags.
*/
#define IORESOURCE_BITS 0x000000ff /* Bus-specific bits */
549,6 → 582,71
struct pci_dev pci_dev;
}pci_dev_t;
 
 
typedef unsigned short __bitwise pci_bus_flags_t;
enum pci_bus_flags {
PCI_BUS_FLAGS_NO_MSI = (__force pci_bus_flags_t) 1,
PCI_BUS_FLAGS_NO_MMRBC = (__force pci_bus_flags_t) 2,
};
 
struct pci_sysdata
{
int domain; /* PCI domain */
int node; /* NUMA node */
#ifdef CONFIG_X86_64
void *iommu; /* IOMMU private data */
#endif
};
 
struct pci_bus;
 
struct pci_ops
{
int (*read)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val);
int (*write)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val);
};
 
 
struct pci_bus {
struct list_head node; /* node in list of buses */
struct pci_bus *parent; /* parent bus this bridge is on */
struct list_head children; /* list of child buses */
struct list_head devices; /* list of devices on this bus */
struct pci_dev *self; /* bridge device as seen by parent */
struct list_head slots; /* list of slots on this bus */
struct resource *resource[PCI_BRIDGE_RESOURCE_NUM];
struct list_head resources; /* address space routed to this bus */
 
struct pci_ops *ops; /* configuration access functions */
void *sysdata; /* hook for sys-specific extension */
 
unsigned char number; /* bus number */
unsigned char primary; /* number of primary bridge */
unsigned char secondary; /* number of secondary bridge */
unsigned char subordinate; /* max number of subordinate buses */
 
char name[48];
 
unsigned short bridge_ctl; /* manage NO_ISA/FBB/et al behaviors */
pci_bus_flags_t bus_flags; /* Inherited by child busses */
// struct device *bridge;
// struct device dev;
// struct bin_attribute *legacy_io; /* legacy I/O for this bus */
// struct bin_attribute *legacy_mem; /* legacy mem */
unsigned int is_added:1;
};
 
#define pci_bus_b(n) list_entry(n, struct pci_bus, node)
#define to_pci_bus(n) container_of(n, struct pci_bus, dev)
 
 
static inline int pci_domain_nr(struct pci_bus *bus)
{
struct pci_sysdata *sd = bus->sysdata;
return sd->domain;
}
 
 
int enum_pci_devices(void);
 
struct pci_device_id*
558,7 → 656,12
 
int pci_set_dma_mask(struct pci_dev *dev, u64 mask);
 
struct pci_bus * pci_create_bus(int bus, struct pci_ops *ops, void *sysdata);
struct pci_bus * pci_find_bus(int domain, int busnr);
struct pci_bus * pci_find_next_bus(const struct pci_bus *from);
 
 
 
#define pci_name(x) "radeon"
 
#endif //__PCI__H__
/drivers/include/linux/types.h
330,11 → 330,6
 
 
 
#define ENTER() dbgprintf("enter %s\n",__FUNCTION__)
#define LEAVE() dbgprintf("leave %s\n",__FUNCTION__)
 
 
 
#define PCI_DEVICE_ID_ATI_RADEON_QY 0x5159
 
#endif /* _LINUX_TYPES_H */