clang-format

This commit is contained in:
2024-09-10 13:03:02 -04:00
parent 53c617d779
commit d66450e427
381 changed files with 28864 additions and 34170 deletions

View File

@@ -30,7 +30,6 @@
#ifndef _MIPS_CURRENT_H_
#define _MIPS_CURRENT_H_
/*
* Macro for current thread, or current cpu.
*
@@ -60,7 +59,7 @@
*/
#ifdef __GNUC__
register struct thread *curthread __asm("$23"); /* s7 register */
register struct thread *curthread __asm("$23"); /* s7 register */
#else
#error "Don't know how to declare curthread in this compiler"
#endif

View File

@@ -34,25 +34,23 @@
* MIPS machine-dependent definitions for the ELF binary format.
*/
/* The ELF executable type. */
#define EM_MACHINE EM_MIPS
#define EM_MACHINE EM_MIPS
/* Linker relocation codes. SIZE DESCRIPTION */
#define R_MIPS_NONE 0 /* --- nop */
#define R_MIPS_16 1 /* u16 value */
#define R_MIPS_32 2 /* u32 value */
#define R_MIPS_REL32 3 /* u32 value relative to patched address */
#define R_MIPS_26 4 /* u26 j/jal instruction address field */
#define R_MIPS_HI16 5 /* u16 %hi(sym) as below */
#define R_MIPS_LO16 6 /* s16 %lo(sym) as below */
#define R_MIPS_GPREL16 7 /* s16 offset from GP register */
#define R_MIPS_LITERAL 8 /* s16 GPREL16 for file-local symbols (?) */
#define R_MIPS_GOT16 9 /* u16 offset into global offset table */
#define R_MIPS_PC16 10 /* s16 PC-relative reference */
#define R_MIPS_CALL16 11 /* u16 call through global offset table */
#define R_MIPS_GPREL32 12 /* s32 offset from GP register */
#define R_MIPS_NONE 0 /* --- nop */
#define R_MIPS_16 1 /* u16 value */
#define R_MIPS_32 2 /* u32 value */
#define R_MIPS_REL32 3 /* u32 value relative to patched address */
#define R_MIPS_26 4 /* u26 j/jal instruction address field */
#define R_MIPS_HI16 5 /* u16 %hi(sym) as below */
#define R_MIPS_LO16 6 /* s16 %lo(sym) as below */
#define R_MIPS_GPREL16 7 /* s16 offset from GP register */
#define R_MIPS_LITERAL 8 /* s16 GPREL16 for file-local symbols (?) */
#define R_MIPS_GOT16 9 /* u16 offset into global offset table */
#define R_MIPS_PC16 10 /* s16 PC-relative reference */
#define R_MIPS_CALL16 11 /* u16 call through global offset table */
#define R_MIPS_GPREL32 12 /* s32 offset from GP register */
/* %hi/%lo are defined so %hi(sym) << 16 + %lo(sym) = sym */
#endif /* _MIPS_ELF_H_ */

View File

@@ -36,39 +36,37 @@
#ifndef _KERN_MIPS_REGDEFS_H_
#define _KERN_MIPS_REGDEFS_H_
#define z0 $0 /* always zero register */
#define AT $1 /* assembler temp register */
#define v0 $2 /* value 0 */
#define v1 $3 /* value 1 */
#define a0 $4 /* argument 0 */
#define a1 $5 /* argument 1 */
#define a2 $6 /* argument 2 */
#define a3 $7 /* argument 3 */
#define t0 $8 /* temporary (caller-save) 0 */
#define t1 $9 /* temporary (caller-save) 1 */
#define t2 $10 /* temporary (caller-save) 2 */
#define t3 $11 /* temporary (caller-save) 3 */
#define t4 $12 /* temporary (caller-save) 4 */
#define t5 $13 /* temporary (caller-save) 5 */
#define t6 $14 /* temporary (caller-save) 6 */
#define t7 $15 /* temporary (caller-save) 7 */
#define s0 $16 /* saved (callee-save) 0 */
#define s1 $17 /* saved (callee-save) 1 */
#define s2 $18 /* saved (callee-save) 2 */
#define s3 $19 /* saved (callee-save) 3 */
#define s4 $20 /* saved (callee-save) 4 */
#define s5 $21 /* saved (callee-save) 5 */
#define s6 $22 /* saved (callee-save) 6 */
#define s7 $23 /* saved (callee-save) 7 */
#define t8 $24 /* temporary (caller-save) 8 */
#define t9 $25 /* temporary (caller-save) 9 */
#define k0 $26 /* kernel temporary 0 */
#define k1 $27 /* kernel temporary 1 */
#define gp $28 /* global pointer */
#define sp $29 /* stack pointer */
#define s8 $30 /* saved (callee-save) 8 = frame pointer */
#define ra $31 /* return address */
#define z0 $0 /* always zero register */
#define AT $1 /* assembler temp register */
#define v0 $2 /* value 0 */
#define v1 $3 /* value 1 */
#define a0 $4 /* argument 0 */
#define a1 $5 /* argument 1 */
#define a2 $6 /* argument 2 */
#define a3 $7 /* argument 3 */
#define t0 $8 /* temporary (caller-save) 0 */
#define t1 $9 /* temporary (caller-save) 1 */
#define t2 $10 /* temporary (caller-save) 2 */
#define t3 $11 /* temporary (caller-save) 3 */
#define t4 $12 /* temporary (caller-save) 4 */
#define t5 $13 /* temporary (caller-save) 5 */
#define t6 $14 /* temporary (caller-save) 6 */
#define t7 $15 /* temporary (caller-save) 7 */
#define s0 $16 /* saved (callee-save) 0 */
#define s1 $17 /* saved (callee-save) 1 */
#define s2 $18 /* saved (callee-save) 2 */
#define s3 $19 /* saved (callee-save) 3 */
#define s4 $20 /* saved (callee-save) 4 */
#define s5 $21 /* saved (callee-save) 5 */
#define s6 $22 /* saved (callee-save) 6 */
#define s7 $23 /* saved (callee-save) 7 */
#define t8 $24 /* temporary (caller-save) 8 */
#define t9 $25 /* temporary (caller-save) 9 */
#define k0 $26 /* kernel temporary 0 */
#define k1 $27 /* kernel temporary 1 */
#define gp $28 /* global pointer */
#define sp $29 /* stack pointer */
#define s8 $30 /* saved (callee-save) 8 = frame pointer */
#define ra $31 /* return address */
#endif /* _KERN_MIPS_REGDEFS_H_ */

View File

@@ -38,10 +38,9 @@
* Must save: s0-s8, sp, ra (11 registers)
* Don't change __JB_REGS without adjusting mips_setjmp.S accordingly.
*/
#define __JB_REGS 11
#define __JB_REGS 11
/* A jmp_buf is an array of __JB_REGS registers */
typedef uint32_t jmp_buf[__JB_REGS];
#endif /* _MIPS_SETJMP_H_ */

View File

@@ -27,7 +27,6 @@
* SUCH DAMAGE.
*/
#ifndef _KERN_MIPS_SIGNAL_H_
#define _KERN_MIPS_SIGNAL_H_
@@ -39,7 +38,7 @@
* probably won't.)
*/
struct sigcontext {
/* Dummy. */
/* Dummy. */
};
#endif /* _KERN_MIPS_SIGNAL_H_ */

View File

@@ -38,21 +38,20 @@
* See kern/types.h for an explanation of the underscores.
*/
/* Sized integer types, with convenient short names */
typedef char __i8; /* 8-bit signed integer */
typedef short __i16; /* 16-bit signed integer */
typedef int __i32; /* 32-bit signed integer */
typedef long long __i64; /* 64-bit signed integer */
typedef char __i8; /* 8-bit signed integer */
typedef short __i16; /* 16-bit signed integer */
typedef int __i32; /* 32-bit signed integer */
typedef long long __i64; /* 64-bit signed integer */
typedef unsigned char __u8; /* 8-bit unsigned integer */
typedef unsigned short __u16; /* 16-bit unsigned integer */
typedef unsigned int __u32; /* 32-bit unsigned integer */
typedef unsigned long long __u64; /* 64-bit unsigned integer */
typedef unsigned char __u8; /* 8-bit unsigned integer */
typedef unsigned short __u16; /* 16-bit unsigned integer */
typedef unsigned int __u32; /* 32-bit unsigned integer */
typedef unsigned long long __u64; /* 64-bit unsigned integer */
/* Further standard C types */
typedef long __intptr_t; /* Signed pointer-sized integer */
typedef unsigned long __uintptr_t; /* Unsigned pointer-sized integer */
typedef long __intptr_t; /* Signed pointer-sized integer */
typedef unsigned long __uintptr_t; /* Unsigned pointer-sized integer */
/*
* Since we're a 32-bit platform, size_t, ssize_t, and ptrdiff_t can
@@ -62,17 +61,16 @@ typedef unsigned long __uintptr_t; /* Unsigned pointer-sized integer */
* errors involving size_t, try changing this.
*/
#if 1
typedef unsigned __size_t; /* Size of a memory region */
typedef int __ssize_t; /* Signed type of same size */
typedef int __ptrdiff_t; /* Difference of two pointers */
typedef unsigned __size_t; /* Size of a memory region */
typedef int __ssize_t; /* Signed type of same size */
typedef int __ptrdiff_t; /* Difference of two pointers */
#else
typedef unsigned long __size_t; /* Size of a memory region */
typedef long __ssize_t; /* Signed type of same size */
typedef long __ptrdiff_t; /* Difference of two pointers */
typedef unsigned long __size_t; /* Size of a memory region */
typedef long __ssize_t; /* Signed type of same size */
typedef long __ptrdiff_t; /* Difference of two pointers */
#endif
/* Number of bits per byte. */
#define __CHAR_BIT 8
#define __CHAR_BIT 8
#endif /* _KERN_MIPS_TYPES_H_ */

View File

@@ -41,17 +41,14 @@
*/
MEMBAR_INLINE
void
membar_any_any(void)
{
__asm volatile(
".set push;" /* save assembler mode */
".set mips32;" /* allow MIPS32 instructions */
"sync;" /* do it */
".set pop" /* restore assembler mode */
: /* no outputs */
: /* no inputs */
: "memory"); /* "changes" memory */
void membar_any_any(void) {
__asm volatile(".set push;" /* save assembler mode */
".set mips32;" /* allow MIPS32 instructions */
"sync;" /* do it */
".set pop" /* restore assembler mode */
: /* no outputs */
: /* no inputs */
: "memory"); /* "changes" memory */
}
MEMBAR_INLINE void membar_load_load(void) { membar_any_any(); }
@@ -59,5 +56,4 @@ MEMBAR_INLINE void membar_store_store(void) { membar_any_any(); }
MEMBAR_INLINE void membar_store_any(void) { membar_any_any(); }
MEMBAR_INLINE void membar_any_store(void) { membar_any_any(); }
#endif /* _MIPS_MEMBAR_H_ */

View File

@@ -30,62 +30,61 @@
#ifndef _MIPS_SPECIALREG_H_
#define _MIPS_SPECIALREG_H_
/*
* Coprocessor 0 (system processor) register numbers
*/
#define c0_index $0 /* TLB entry index register */
#define c0_random $1 /* TLB random slot register */
#define c0_entrylo $2 /* TLB entry contents (low-order half) */
/* c0_entrylo0 $2 */ /* MIPS-II and up only */
/* c0_entrylo1 $3 */ /* MIPS-II and up only */
#define c0_context $4 /* some precomputed pagetable stuff */
/* c0_pagemask $5 */ /* MIPS-II and up only */
/* c0_wired $6 */ /* MIPS-II and up only */
#define c0_vaddr $8 /* virtual addr of failing memory access */
#define c0_count $9 /* cycle counter (MIPS-II and up) */
#define c0_entryhi $10 /* TLB entry contents (high-order half) */
#define c0_compare $11 /* on-chip timer control (MIPS-II and up) */
#define c0_status $12 /* processor status register */
#define c0_cause $13 /* exception cause register */
#define c0_epc $14 /* exception PC register */
#define c0_prid $15 /* processor ID register */
/* c0_config $16 */ /* MIPS-II and up only */
/* c0_lladdr $17 */ /* MIPS-II and up only */
/* c0_watchlo $18 */ /* MIPS-II and up only */
/* c0_watchhi $19 */ /* MIPS-II and up only */
#define c0_index $0 /* TLB entry index register */
#define c0_random $1 /* TLB random slot register */
#define c0_entrylo $2 /* TLB entry contents (low-order half) */
/* c0_entrylo0 $2 */ /* MIPS-II and up only */
/* c0_entrylo1 $3 */ /* MIPS-II and up only */
#define c0_context $4 /* some precomputed pagetable stuff */
/* c0_pagemask $5 */ /* MIPS-II and up only */
/* c0_wired $6 */ /* MIPS-II and up only */
#define c0_vaddr $8 /* virtual addr of failing memory access */
#define c0_count $9 /* cycle counter (MIPS-II and up) */
#define c0_entryhi $10 /* TLB entry contents (high-order half) */
#define c0_compare $11 /* on-chip timer control (MIPS-II and up) */
#define c0_status $12 /* processor status register */
#define c0_cause $13 /* exception cause register */
#define c0_epc $14 /* exception PC register */
#define c0_prid $15 /* processor ID register */
/* c0_config $16 */ /* MIPS-II and up only */
/* c0_lladdr $17 */ /* MIPS-II and up only */
/* c0_watchlo $18 */ /* MIPS-II and up only */
/* c0_watchhi $19 */ /* MIPS-II and up only */
/*
* Mode bits in c0_status
*/
#define CST_IEc 0x00000001 /* current: interrupt enable */
#define CST_KUc 0x00000002 /* current: user mode */
#define CST_IEp 0x00000004 /* previous: interrupt enable */
#define CST_KUp 0x00000008 /* previous: user mode */
#define CST_IEo 0x00000010 /* old: interrupt enable */
#define CST_KUo 0x00000020 /* old: user mode */
#define CST_IEc 0x00000001 /* current: interrupt enable */
#define CST_KUc 0x00000002 /* current: user mode */
#define CST_IEp 0x00000004 /* previous: interrupt enable */
#define CST_KUp 0x00000008 /* previous: user mode */
#define CST_IEo 0x00000010 /* old: interrupt enable */
#define CST_KUo 0x00000020 /* old: user mode */
#define CST_MODEMASK 0x0000003f /* mask for the above */
#define CST_IRQMASK 0x0000ff00 /* mask for the individual irq enable bits */
#define CST_BEV 0x00400000 /* bootstrap exception vectors flag */
#define CST_IRQMASK 0x0000ff00 /* mask for the individual irq enable bits */
#define CST_BEV 0x00400000 /* bootstrap exception vectors flag */
/*
* Fields of the c0_cause register
*/
#define CCA_UTLB 0x00000001 /* true if UTLB exception (set by our asm) */
#define CCA_CODE 0x0000003c /* EX_foo in trapframe.h */
#define CCA_IRQS 0x0000ff00 /* Currently pending interrupts */
#define CCA_COPN 0x30000000 /* Coprocessor number for EX_CPU */
#define CCA_JD 0x80000000 /* True if exception happened in jump delay */
#define CCA_UTLB 0x00000001 /* true if UTLB exception (set by our asm) */
#define CCA_CODE 0x0000003c /* EX_foo in trapframe.h */
#define CCA_IRQS 0x0000ff00 /* Currently pending interrupts */
#define CCA_COPN 0x30000000 /* Coprocessor number for EX_CPU */
#define CCA_JD 0x80000000 /* True if exception happened in jump delay */
#define CCA_CODESHIFT 2 /* shift for CCA_CODE field */
#define CCA_CODESHIFT 2 /* shift for CCA_CODE field */
/*
* Fields of the c0_index register
*/
#define CIN_P 0x80000000 /* nonzero -> TLB probe found nothing */
#define CIN_INDEX 0x00003f00 /* 6-bit index into TLB */
#define CIN_P 0x80000000 /* nonzero -> TLB probe found nothing */
#define CIN_INDEX 0x00003f00 /* 6-bit index into TLB */
#define CIN_INDEXSHIFT 8 /* shift for CIN_INDEX field */
#define CIN_INDEXSHIFT 8 /* shift for CIN_INDEX field */
/*
* Fields of the c0_context register
@@ -102,16 +101,15 @@
* there's no other good place in the chip to put it. See discussions
* elsewhere.
*/
#define CTX_VSHIFT 0x001ffffc /* shifted/masked copy of c0_vaddr */
#define CTX_PTBASE 0xffe00000 /* page table base address */
#define CTX_VSHIFT 0x001ffffc /* shifted/masked copy of c0_vaddr */
#define CTX_PTBASE 0xffe00000 /* page table base address */
#define CTX_PTBASESHIFT 21 /* shift for CTX_PBASE field */
#define CTX_PTBASESHIFT 21 /* shift for CTX_PBASE field */
/*
* Hardwired exception handler addresses.
*/
#define EXADDR_UTLB 0x80000000
#define EXADDR_GENERAL 0x80000080
#define EXADDR_UTLB 0x80000000
#define EXADDR_GENERAL 0x80000080
#endif /* _MIPS_SPECIALREG_H_ */

View File

@@ -32,12 +32,11 @@
#include <cdefs.h>
/* Type of value needed to actually spin on */
typedef unsigned spinlock_data_t;
/* Initializer for use by SPINLOCK_INITIALIZER */
#define SPINLOCK_DATA_INITIALIZER 0
#define SPINLOCK_DATA_INITIALIZER 0
/* Atomic operations on spinlock_data_t */
SPINLOCK_INLINE
@@ -55,10 +54,8 @@ spinlock_data_t spinlock_data_testandset(volatile spinlock_data_t *sd);
* memory.
*/
SPINLOCK_INLINE
void
spinlock_data_set(volatile spinlock_data_t *sd, unsigned val)
{
*sd = val;
void spinlock_data_set(volatile spinlock_data_t *sd, unsigned val) {
*sd = val;
}
/*
@@ -66,11 +63,7 @@ spinlock_data_set(volatile spinlock_data_t *sd, unsigned val)
* instruction, and instructions are atomic with respect to memory.
*/
SPINLOCK_INLINE
spinlock_data_t
spinlock_data_get(volatile spinlock_data_t *sd)
{
return *sd;
}
spinlock_data_t spinlock_data_get(volatile spinlock_data_t *sd) { return *sd; }
/*
* Test-and-set a spinlock_data_t. Use the LL/SC instructions to
@@ -86,37 +79,34 @@ spinlock_data_get(volatile spinlock_data_t *sd)
* to atomically update one machine word.
*/
SPINLOCK_INLINE
spinlock_data_t
spinlock_data_testandset(volatile spinlock_data_t *sd)
{
spinlock_data_t x;
spinlock_data_t y;
spinlock_data_t spinlock_data_testandset(volatile spinlock_data_t *sd) {
spinlock_data_t x;
spinlock_data_t y;
/*
* Test-and-set using LL/SC.
*
* Load the existing value into X, and use Y to store 1.
* After the SC, Y contains 1 if the store succeeded,
* 0 if it failed.
*
* On failure, return 1 to pretend that the spinlock
* was already held.
*/
/*
* Test-and-set using LL/SC.
*
* Load the existing value into X, and use Y to store 1.
* After the SC, Y contains 1 if the store succeeded,
* 0 if it failed.
*
* On failure, return 1 to pretend that the spinlock
* was already held.
*/
y = 1;
__asm volatile(
".set push;" /* save assembler mode */
".set mips32;" /* allow MIPS32 instructions */
".set volatile;" /* avoid unwanted optimization */
"ll %0, 0(%2);" /* x = *sd */
"sc %1, 0(%2);" /* *sd = y; y = success? */
".set pop" /* restore assembler mode */
: "=&r" (x), "+r" (y) : "r" (sd));
if (y == 0) {
return 1;
}
return x;
y = 1;
__asm volatile(".set push;" /* save assembler mode */
".set mips32;" /* allow MIPS32 instructions */
".set volatile;" /* avoid unwanted optimization */
"ll %0, 0(%2);" /* x = *sd */
"sc %1, 0(%2);" /* *sd = y; y = success? */
".set pop" /* restore assembler mode */
: "=&r"(x), "+r"(y)
: "r"(sd));
if (y == 0) {
return 1;
}
return x;
}
#endif /* _MIPS_SPINLOCK_H_ */

View File

@@ -30,7 +30,6 @@
#ifndef _MIPS_THREAD_H_
#define _MIPS_THREAD_H_
/*
* Machine-dependent thread bits.
*/
@@ -40,9 +39,8 @@
typedef void (*badfaultfunc_t)(void);
struct thread_machdep {
badfaultfunc_t tm_badfaultfunc; /* fault hook used by copyin/out */
jmp_buf tm_copyjmp; /* longjmp area used by copyin/out */
badfaultfunc_t tm_badfaultfunc; /* fault hook used by copyin/out */
jmp_buf tm_copyjmp; /* longjmp area used by copyin/out */
};
#endif /* _MIPS_THREAD_H_ */

View File

@@ -77,14 +77,14 @@ int tlb_probe(uint32_t entryhi, uint32_t entrylo);
*/
/* Fields in the high-order word */
#define TLBHI_VPAGE 0xfffff000
#define TLBHI_VPAGE 0xfffff000
/* TLBHI_PID 0x00000fc0 */
/* Fields in the low-order word */
#define TLBLO_PPAGE 0xfffff000
#define TLBLO_PPAGE 0xfffff000
#define TLBLO_NOCACHE 0x00000800
#define TLBLO_DIRTY 0x00000400
#define TLBLO_VALID 0x00000200
#define TLBLO_DIRTY 0x00000400
#define TLBLO_VALID 0x00000200
/* TLBLO_GLOBAL 0x00000100 */
/*
@@ -92,14 +92,13 @@ int tlb_probe(uint32_t entryhi, uint32_t entrylo);
* be passed to TLBHI_INVALID; this prevents loading the same invalid
* entry into multiple TLB slots.
*/
#define TLBHI_INVALID(entryno) ((0x80000+(entryno))<<12)
#define TLBLO_INVALID() (0)
#define TLBHI_INVALID(entryno) ((0x80000 + (entryno)) << 12)
#define TLBLO_INVALID() (0)
/*
* Number of TLB entries in the processor.
*/
#define NUM_TLB 64
#define NUM_TLB 64
#endif /* _MIPS_TLB_H_ */

View File

@@ -38,59 +38,59 @@
*/
struct trapframe {
uint32_t tf_vaddr; /* coprocessor 0 vaddr register */
uint32_t tf_status; /* coprocessor 0 status register */
uint32_t tf_cause; /* coprocessor 0 cause register */
uint32_t tf_lo;
uint32_t tf_hi;
uint32_t tf_ra; /* Saved register 31 */
uint32_t tf_at; /* Saved register 1 (AT) */
uint32_t tf_v0; /* Saved register 2 (v0) */
uint32_t tf_v1; /* etc. */
uint32_t tf_a0;
uint32_t tf_a1;
uint32_t tf_a2;
uint32_t tf_a3;
uint32_t tf_t0;
uint32_t tf_t1;
uint32_t tf_t2;
uint32_t tf_t3;
uint32_t tf_t4;
uint32_t tf_t5;
uint32_t tf_t6;
uint32_t tf_t7;
uint32_t tf_s0;
uint32_t tf_s1;
uint32_t tf_s2;
uint32_t tf_s3;
uint32_t tf_s4;
uint32_t tf_s5;
uint32_t tf_s6;
uint32_t tf_s7;
uint32_t tf_t8;
uint32_t tf_t9;
uint32_t tf_gp;
uint32_t tf_sp;
uint32_t tf_s8;
uint32_t tf_epc; /* coprocessor 0 epc register */
uint32_t tf_vaddr; /* coprocessor 0 vaddr register */
uint32_t tf_status; /* coprocessor 0 status register */
uint32_t tf_cause; /* coprocessor 0 cause register */
uint32_t tf_lo;
uint32_t tf_hi;
uint32_t tf_ra; /* Saved register 31 */
uint32_t tf_at; /* Saved register 1 (AT) */
uint32_t tf_v0; /* Saved register 2 (v0) */
uint32_t tf_v1; /* etc. */
uint32_t tf_a0;
uint32_t tf_a1;
uint32_t tf_a2;
uint32_t tf_a3;
uint32_t tf_t0;
uint32_t tf_t1;
uint32_t tf_t2;
uint32_t tf_t3;
uint32_t tf_t4;
uint32_t tf_t5;
uint32_t tf_t6;
uint32_t tf_t7;
uint32_t tf_s0;
uint32_t tf_s1;
uint32_t tf_s2;
uint32_t tf_s3;
uint32_t tf_s4;
uint32_t tf_s5;
uint32_t tf_s6;
uint32_t tf_s7;
uint32_t tf_t8;
uint32_t tf_t9;
uint32_t tf_gp;
uint32_t tf_sp;
uint32_t tf_s8;
uint32_t tf_epc; /* coprocessor 0 epc register */
};
/*
* MIPS exception codes.
*/
#define EX_IRQ 0 /* Interrupt */
#define EX_MOD 1 /* TLB Modify (write to read-only page) */
#define EX_TLBL 2 /* TLB miss on load */
#define EX_TLBS 3 /* TLB miss on store */
#define EX_ADEL 4 /* Address error on load */
#define EX_ADES 5 /* Address error on store */
#define EX_IBE 6 /* Bus error on instruction fetch */
#define EX_DBE 7 /* Bus error on data load *or* store */
#define EX_SYS 8 /* Syscall */
#define EX_BP 9 /* Breakpoint */
#define EX_RI 10 /* Reserved (illegal) instruction */
#define EX_CPU 11 /* Coprocessor unusable */
#define EX_OVF 12 /* Arithmetic overflow */
#define EX_IRQ 0 /* Interrupt */
#define EX_MOD 1 /* TLB Modify (write to read-only page) */
#define EX_TLBL 2 /* TLB miss on load */
#define EX_TLBS 3 /* TLB miss on store */
#define EX_ADEL 4 /* Address error on load */
#define EX_ADES 5 /* Address error on store */
#define EX_IBE 6 /* Bus error on instruction fetch */
#define EX_DBE 7 /* Bus error on data load *or* store */
#define EX_SYS 8 /* Syscall */
#define EX_BP 9 /* Breakpoint */
#define EX_RI 10 /* Reserved (illegal) instruction */
#define EX_CPU 11 /* Coprocessor unusable */
#define EX_OVF 12 /* Arithmetic overflow */
/*
* Function to enter user mode. Does not return. The trapframe must
@@ -104,5 +104,4 @@ __DEAD void mips_usermode(struct trapframe *tf);
extern vaddr_t cpustacks[];
extern vaddr_t cputhreads[];
#endif /* _MIPS_TRAPFRAME_H_ */

View File

@@ -30,13 +30,12 @@
#ifndef _MIPS_VM_H_
#define _MIPS_VM_H_
/*
* Machine-dependent VM system definitions.
*/
#define PAGE_SIZE 4096 /* size of VM page */
#define PAGE_FRAME 0xfffff000 /* mask for getting page number from addr */
#define PAGE_SIZE 4096 /* size of VM page */
#define PAGE_FRAME 0xfffff000 /* mask for getting page number from addr */
/*
* MIPS-I hardwired memory layout:
@@ -48,10 +47,10 @@
* (mips32 is a little different)
*/
#define MIPS_KUSEG 0x00000000
#define MIPS_KSEG0 0x80000000
#define MIPS_KSEG1 0xa0000000
#define MIPS_KSEG2 0xc0000000
#define MIPS_KUSEG 0x00000000
#define MIPS_KSEG0 0x80000000
#define MIPS_KSEG1 0xa0000000
#define MIPS_KSEG2 0xc0000000
/*
* The first 512 megs of physical space can be addressed in both kseg0 and
@@ -65,13 +64,13 @@
* exception handler code) when converted to a vaddr it's *not* NULL, *is*
* a valid address, and will make a *huge* mess if you scribble on it.
*/
#define PADDR_TO_KVADDR(paddr) ((paddr)+MIPS_KSEG0)
#define PADDR_TO_KVADDR(paddr) ((paddr) + MIPS_KSEG0)
/*
* The top of user space. (Actually, the address immediately above the
* last valid user address.)
*/
#define USERSPACETOP MIPS_KSEG0
#define USERSPACETOP MIPS_KSEG0
/*
* The starting value for the stack pointer at user level. Because
@@ -81,7 +80,7 @@
* We put the stack at the very top of user virtual memory because it
* grows downwards.
*/
#define USERSTACK USERSPACETOP
#define USERSTACK USERSPACETOP
/*
* Interface to the low-level module that looks after the amount of
@@ -117,13 +116,12 @@ paddr_t ram_getfirstfree(void);
*/
struct tlbshootdown {
/*
* Change this to what you need for your VM design.
*/
int ts_placeholder;
/*
* Change this to what you need for your VM design.
*/
int ts_placeholder;
};
#define TLBSHOOTDOWN_MAX 16
#endif /* _MIPS_VM_H_ */

View File

@@ -40,81 +40,68 @@
#include <mainbus.h>
#include <syscall.h>
/* in exception-*.S */
extern __DEAD void asm_usermode(struct trapframe *tf);
/* called only from assembler, so not declared in a header */
void mips_trap(struct trapframe *tf);
/* Names for trap codes */
#define NTRAPCODES 13
static const char *const trapcodenames[NTRAPCODES] = {
"Interrupt",
"TLB modify trap",
"TLB miss on load",
"TLB miss on store",
"Address error on load",
"Address error on store",
"Bus error on code",
"Bus error on data",
"System call",
"Break instruction",
"Illegal instruction",
"Coprocessor unusable",
"Arithmetic overflow",
"Interrupt", "TLB modify trap", "TLB miss on load",
"TLB miss on store", "Address error on load", "Address error on store",
"Bus error on code", "Bus error on data", "System call",
"Break instruction", "Illegal instruction", "Coprocessor unusable",
"Arithmetic overflow",
};
/*
* Function called when user-level code hits a fatal fault.
*/
static
void
kill_curthread(vaddr_t epc, unsigned code, vaddr_t vaddr)
{
int sig = 0;
static void kill_curthread(vaddr_t epc, unsigned code, vaddr_t vaddr) {
int sig = 0;
KASSERT(code < NTRAPCODES);
switch (code) {
case EX_IRQ:
case EX_IBE:
case EX_DBE:
case EX_SYS:
/* should not be seen */
KASSERT(0);
sig = SIGABRT;
break;
case EX_MOD:
case EX_TLBL:
case EX_TLBS:
sig = SIGSEGV;
break;
case EX_ADEL:
case EX_ADES:
sig = SIGBUS;
break;
case EX_BP:
sig = SIGTRAP;
break;
case EX_RI:
sig = SIGILL;
break;
case EX_CPU:
sig = SIGSEGV;
break;
case EX_OVF:
sig = SIGFPE;
break;
}
KASSERT(code < NTRAPCODES);
switch (code) {
case EX_IRQ:
case EX_IBE:
case EX_DBE:
case EX_SYS:
/* should not be seen */
KASSERT(0);
sig = SIGABRT;
break;
case EX_MOD:
case EX_TLBL:
case EX_TLBS:
sig = SIGSEGV;
break;
case EX_ADEL:
case EX_ADES:
sig = SIGBUS;
break;
case EX_BP:
sig = SIGTRAP;
break;
case EX_RI:
sig = SIGILL;
break;
case EX_CPU:
sig = SIGSEGV;
break;
case EX_OVF:
sig = SIGFPE;
break;
}
/*
* You will probably want to change this.
*/
/*
* You will probably want to change this.
*/
kprintf("Fatal user mode trap %u sig %d (%s, epc 0x%x, vaddr 0x%x)\n",
code, sig, trapcodenames[code], epc, vaddr);
panic("I don't know how to handle this\n");
kprintf("Fatal user mode trap %u sig %d (%s, epc 0x%x, vaddr 0x%x)\n", code,
sig, trapcodenames[code], epc, vaddr);
panic("I don't know how to handle this\n");
}
/*
@@ -122,229 +109,223 @@ kill_curthread(vaddr_t epc, unsigned code, vaddr_t vaddr)
* This is called by the assembly-language exception handler once
* the trapframe has been set up.
*/
void
mips_trap(struct trapframe *tf)
{
uint32_t code;
/*bool isutlb; -- not used */
bool iskern;
int spl;
void mips_trap(struct trapframe *tf) {
uint32_t code;
/*bool isutlb; -- not used */
bool iskern;
int spl;
/* The trap frame is supposed to be 35 registers long. */
KASSERT(sizeof(struct trapframe)==(35*4));
/* The trap frame is supposed to be 35 registers long. */
KASSERT(sizeof(struct trapframe) == (35 * 4));
/*
* Extract the exception code info from the register fields.
*/
code = (tf->tf_cause & CCA_CODE) >> CCA_CODESHIFT;
/*isutlb = (tf->tf_cause & CCA_UTLB) != 0;*/
iskern = (tf->tf_status & CST_KUp) == 0;
/*
* Extract the exception code info from the register fields.
*/
code = (tf->tf_cause & CCA_CODE) >> CCA_CODESHIFT;
/*isutlb = (tf->tf_cause & CCA_UTLB) != 0;*/
iskern = (tf->tf_status & CST_KUp) == 0;
KASSERT(code < NTRAPCODES);
KASSERT(code < NTRAPCODES);
/* Make sure we haven't run off our stack */
if (curthread != NULL && curthread->t_stack != NULL) {
KASSERT((vaddr_t)tf > (vaddr_t)curthread->t_stack);
KASSERT((vaddr_t)tf < (vaddr_t)(curthread->t_stack
+ STACK_SIZE));
}
/* Make sure we haven't run off our stack */
if (curthread != NULL && curthread->t_stack != NULL) {
KASSERT((vaddr_t)tf > (vaddr_t)curthread->t_stack);
KASSERT((vaddr_t)tf < (vaddr_t)(curthread->t_stack + STACK_SIZE));
}
/* Interrupt? Call the interrupt handler and return. */
if (code == EX_IRQ) {
int old_in;
bool doadjust;
/* Interrupt? Call the interrupt handler and return. */
if (code == EX_IRQ) {
int old_in;
bool doadjust;
old_in = curthread->t_in_interrupt;
curthread->t_in_interrupt = 1;
old_in = curthread->t_in_interrupt;
curthread->t_in_interrupt = 1;
/*
* The processor has turned interrupts off; if the
* currently recorded interrupt state is interrupts on
* (spl of 0), adjust the recorded state to match, and
* restore after processing the interrupt.
*
* How can we get an interrupt if the recorded state
* is interrupts off? Well, as things currently stand
* when the CPU finishes idling it flips interrupts on
* and off to allow things to happen, but leaves
* curspl high while doing so.
*
* While we're here, assert that the interrupt
* handling code hasn't leaked a spinlock or an
* splhigh().
*/
/*
* The processor has turned interrupts off; if the
* currently recorded interrupt state is interrupts on
* (spl of 0), adjust the recorded state to match, and
* restore after processing the interrupt.
*
* How can we get an interrupt if the recorded state
* is interrupts off? Well, as things currently stand
* when the CPU finishes idling it flips interrupts on
* and off to allow things to happen, but leaves
* curspl high while doing so.
*
* While we're here, assert that the interrupt
* handling code hasn't leaked a spinlock or an
* splhigh().
*/
if (curthread->t_curspl == 0) {
KASSERT(curthread->t_curspl == 0);
KASSERT(curthread->t_iplhigh_count == 0);
curthread->t_curspl = IPL_HIGH;
curthread->t_iplhigh_count++;
doadjust = true;
}
else {
doadjust = false;
}
if (curthread->t_curspl == 0) {
KASSERT(curthread->t_curspl == 0);
KASSERT(curthread->t_iplhigh_count == 0);
curthread->t_curspl = IPL_HIGH;
curthread->t_iplhigh_count++;
doadjust = true;
} else {
doadjust = false;
}
mainbus_interrupt(tf);
mainbus_interrupt(tf);
if (doadjust) {
KASSERT(curthread->t_curspl == IPL_HIGH);
KASSERT(curthread->t_iplhigh_count == 1);
curthread->t_iplhigh_count--;
curthread->t_curspl = 0;
}
if (doadjust) {
KASSERT(curthread->t_curspl == IPL_HIGH);
KASSERT(curthread->t_iplhigh_count == 1);
curthread->t_iplhigh_count--;
curthread->t_curspl = 0;
}
curthread->t_in_interrupt = old_in;
goto done2;
}
curthread->t_in_interrupt = old_in;
goto done2;
}
/*
* The processor turned interrupts off when it took the trap.
*
* While we're in the kernel, and not actually handling an
* interrupt, restore the interrupt state to where it was in
* the previous context, which may be low (interrupts on).
*
* Do this by forcing splhigh(), which may do a redundant
* cpu_irqoff() but forces the stored MI interrupt state into
* sync, then restoring the previous state.
*/
spl = splhigh();
splx(spl);
/*
* The processor turned interrupts off when it took the trap.
*
* While we're in the kernel, and not actually handling an
* interrupt, restore the interrupt state to where it was in
* the previous context, which may be low (interrupts on).
*
* Do this by forcing splhigh(), which may do a redundant
* cpu_irqoff() but forces the stored MI interrupt state into
* sync, then restoring the previous state.
*/
spl = splhigh();
splx(spl);
/* Syscall? Call the syscall handler and return. */
if (code == EX_SYS) {
/* Interrupts should have been on while in user mode. */
KASSERT(curthread->t_curspl == 0);
KASSERT(curthread->t_iplhigh_count == 0);
/* Syscall? Call the syscall handler and return. */
if (code == EX_SYS) {
/* Interrupts should have been on while in user mode. */
KASSERT(curthread->t_curspl == 0);
KASSERT(curthread->t_iplhigh_count == 0);
DEBUG(DB_SYSCALL, "syscall: #%d, args %x %x %x %x\n",
tf->tf_v0, tf->tf_a0, tf->tf_a1, tf->tf_a2, tf->tf_a3);
DEBUG(DB_SYSCALL, "syscall: #%d, args %x %x %x %x\n", tf->tf_v0, tf->tf_a0,
tf->tf_a1, tf->tf_a2, tf->tf_a3);
syscall(tf);
goto done;
}
syscall(tf);
goto done;
}
/*
* Ok, it wasn't any of the really easy cases.
* Call vm_fault on the TLB exceptions.
* Panic on the bus error exceptions.
*/
switch (code) {
case EX_MOD:
if (vm_fault(VM_FAULT_READONLY, tf->tf_vaddr)==0) {
goto done;
}
break;
case EX_TLBL:
if (vm_fault(VM_FAULT_READ, tf->tf_vaddr)==0) {
goto done;
}
break;
case EX_TLBS:
if (vm_fault(VM_FAULT_WRITE, tf->tf_vaddr)==0) {
goto done;
}
break;
case EX_IBE:
case EX_DBE:
/*
* This means you loaded invalid TLB entries, or
* touched invalid parts of the direct-mapped
* segments. These are serious kernel errors, so
* panic.
*
* The MIPS won't even tell you what invalid address
* caused the bus error.
*/
panic("Bus error exception, PC=0x%x\n", tf->tf_epc);
break;
}
/*
* Ok, it wasn't any of the really easy cases.
* Call vm_fault on the TLB exceptions.
* Panic on the bus error exceptions.
*/
switch (code) {
case EX_MOD:
if (vm_fault(VM_FAULT_READONLY, tf->tf_vaddr) == 0) {
goto done;
}
break;
case EX_TLBL:
if (vm_fault(VM_FAULT_READ, tf->tf_vaddr) == 0) {
goto done;
}
break;
case EX_TLBS:
if (vm_fault(VM_FAULT_WRITE, tf->tf_vaddr) == 0) {
goto done;
}
break;
case EX_IBE:
case EX_DBE:
/*
* This means you loaded invalid TLB entries, or
* touched invalid parts of the direct-mapped
* segments. These are serious kernel errors, so
* panic.
*
* The MIPS won't even tell you what invalid address
* caused the bus error.
*/
panic("Bus error exception, PC=0x%x\n", tf->tf_epc);
break;
}
/*
* If we get to this point, it's a fatal fault - either it's
* one of the other exceptions, like illegal instruction, or
* it was a page fault we couldn't handle.
*/
/*
* If we get to this point, it's a fatal fault - either it's
* one of the other exceptions, like illegal instruction, or
* it was a page fault we couldn't handle.
*/
if (!iskern) {
/*
* Fatal fault in user mode.
* Kill the current user process.
*/
kill_curthread(tf->tf_epc, code, tf->tf_vaddr);
goto done;
}
if (!iskern) {
/*
* Fatal fault in user mode.
* Kill the current user process.
*/
kill_curthread(tf->tf_epc, code, tf->tf_vaddr);
goto done;
}
/*
* Fatal fault in kernel mode.
*
* If pcb_badfaultfunc is set, we do not panic; badfaultfunc is
* set by copyin/copyout and related functions to signify that
* the addresses they're accessing are userlevel-supplied and
* not trustable. What we actually want to do is resume
* execution at the function pointed to by badfaultfunc. That's
* going to be "copyfail" (see copyinout.c), which longjmps
* back to copyin/copyout or wherever and returns EFAULT.
*
* Note that we do not just *call* this function, because that
* won't necessarily do anything. We want the control flow
* that is currently executing in copyin (or whichever), and
* is stopped while we process the exception, to *teleport* to
* copyfail.
*
* This is accomplished by changing tf->tf_epc and returning
* from the exception handler.
*/
/*
* Fatal fault in kernel mode.
*
* If pcb_badfaultfunc is set, we do not panic; badfaultfunc is
* set by copyin/copyout and related functions to signify that
* the addresses they're accessing are userlevel-supplied and
* not trustable. What we actually want to do is resume
* execution at the function pointed to by badfaultfunc. That's
* going to be "copyfail" (see copyinout.c), which longjmps
* back to copyin/copyout or wherever and returns EFAULT.
*
* Note that we do not just *call* this function, because that
* won't necessarily do anything. We want the control flow
* that is currently executing in copyin (or whichever), and
* is stopped while we process the exception, to *teleport* to
* copyfail.
*
* This is accomplished by changing tf->tf_epc and returning
* from the exception handler.
*/
if (curthread != NULL &&
curthread->t_machdep.tm_badfaultfunc != NULL) {
tf->tf_epc = (vaddr_t) curthread->t_machdep.tm_badfaultfunc;
goto done;
}
if (curthread != NULL && curthread->t_machdep.tm_badfaultfunc != NULL) {
tf->tf_epc = (vaddr_t)curthread->t_machdep.tm_badfaultfunc;
goto done;
}
/*
* Really fatal kernel-mode fault.
*/
/*
* Really fatal kernel-mode fault.
*/
kprintf("panic: Fatal exception %u (%s) in kernel mode\n", code,
trapcodenames[code]);
kprintf("panic: EPC 0x%x, exception vaddr 0x%x\n",
tf->tf_epc, tf->tf_vaddr);
kprintf("panic: Fatal exception %u (%s) in kernel mode\n", code,
trapcodenames[code]);
kprintf("panic: EPC 0x%x, exception vaddr 0x%x\n", tf->tf_epc, tf->tf_vaddr);
panic("I can't handle this... I think I'll just die now...\n");
panic("I can't handle this... I think I'll just die now...\n");
done:
/*
* Turn interrupts off on the processor, without affecting the
* stored interrupt state.
*/
cpu_irqoff();
done2:
done:
/*
* Turn interrupts off on the processor, without affecting the
* stored interrupt state.
*/
cpu_irqoff();
done2:
/*
* The boot thread can get here (e.g. on interrupt return) but
* since it doesn't go to userlevel, it can't be returning to
* userlevel, so there's no need to set cputhreads[] and
* cpustacks[]. Just return.
*/
if (curthread->t_stack == NULL) {
return;
}
/*
* The boot thread can get here (e.g. on interrupt return) but
* since it doesn't go to userlevel, it can't be returning to
* userlevel, so there's no need to set cputhreads[] and
* cpustacks[]. Just return.
*/
if (curthread->t_stack == NULL) {
return;
}
cputhreads[curcpu->c_number] = (vaddr_t)curthread;
cpustacks[curcpu->c_number] = (vaddr_t)curthread->t_stack + STACK_SIZE;
cputhreads[curcpu->c_number] = (vaddr_t)curthread;
cpustacks[curcpu->c_number] = (vaddr_t)curthread->t_stack + STACK_SIZE;
/*
* This assertion will fail if either
* (1) curthread->t_stack is corrupted, or
* (2) the trap frame is somehow on the wrong kernel stack.
*
* If cpustacks[] is corrupted, the next trap back to the
* kernel will (most likely) hang the system, so it's better
* to find out now.
*/
KASSERT(SAME_STACK(cpustacks[curcpu->c_number]-1, (vaddr_t)tf));
/*
* This assertion will fail if either
* (1) curthread->t_stack is corrupted, or
* (2) the trap frame is somehow on the wrong kernel stack.
*
* If cpustacks[] is corrupted, the next trap back to the
* kernel will (most likely) hang the system, so it's better
* to find out now.
*/
KASSERT(SAME_STACK(cpustacks[curcpu->c_number] - 1, (vaddr_t)tf));
}
/*
@@ -364,43 +345,41 @@ mips_trap(struct trapframe *tf)
* - enter_new_process, for use by exec and equivalent.
* - enter_forked_process, in syscall.c, for use by fork.
*/
void
mips_usermode(struct trapframe *tf)
{
void mips_usermode(struct trapframe *tf) {
/*
* Interrupts should be off within the kernel while entering
* user mode. However, while in user mode, interrupts should
* be on. To interact properly with the spl-handling logic
* above, we explicitly call spl0() and then call cpu_irqoff().
*/
spl0();
cpu_irqoff();
/*
* Interrupts should be off within the kernel while entering
* user mode. However, while in user mode, interrupts should
* be on. To interact properly with the spl-handling logic
* above, we explicitly call spl0() and then call cpu_irqoff().
*/
spl0();
cpu_irqoff();
cputhreads[curcpu->c_number] = (vaddr_t)curthread;
cpustacks[curcpu->c_number] = (vaddr_t)curthread->t_stack + STACK_SIZE;
cputhreads[curcpu->c_number] = (vaddr_t)curthread;
cpustacks[curcpu->c_number] = (vaddr_t)curthread->t_stack + STACK_SIZE;
/*
* This assertion will fail if either
* (1) cpustacks[] is corrupted, or
* (2) the trap frame is not on our own kernel stack, or
* (3) the boot thread tries to enter user mode.
*
* If cpustacks[] is corrupted, the next trap back to the
* kernel will (most likely) hang the system, so it's better
* to find out now.
*
* It's necessary for the trap frame used here to be on the
* current thread's own stack. It cannot correctly be on
* either another thread's stack or in the kernel heap.
* (Exercise: why?)
*/
KASSERT(SAME_STACK(cpustacks[curcpu->c_number]-1, (vaddr_t)tf));
/*
* This assertion will fail if either
* (1) cpustacks[] is corrupted, or
* (2) the trap frame is not on our own kernel stack, or
* (3) the boot thread tries to enter user mode.
*
* If cpustacks[] is corrupted, the next trap back to the
* kernel will (most likely) hang the system, so it's better
* to find out now.
*
* It's necessary for the trap frame used here to be on the
* current thread's own stack. It cannot correctly be on
* either another thread's stack or in the kernel heap.
* (Exercise: why?)
*/
KASSERT(SAME_STACK(cpustacks[curcpu->c_number] - 1, (vaddr_t)tf));
/*
* This actually does it. See exception-*.S.
*/
asm_usermode(tf);
/*
* This actually does it. See exception-*.S.
*/
asm_usermode(tf);
}
/*
@@ -419,20 +398,18 @@ mips_usermode(struct trapframe *tf)
*
* Works by creating an ersatz trapframe.
*/
void
enter_new_process(int argc, userptr_t argv, userptr_t env,
vaddr_t stack, vaddr_t entry)
{
struct trapframe tf;
void enter_new_process(int argc, userptr_t argv, userptr_t env, vaddr_t stack,
vaddr_t entry) {
struct trapframe tf;
bzero(&tf, sizeof(tf));
bzero(&tf, sizeof(tf));
tf.tf_status = CST_IRQMASK | CST_IEp | CST_KUp;
tf.tf_epc = entry;
tf.tf_a0 = argc;
tf.tf_a1 = (vaddr_t)argv;
tf.tf_a2 = (vaddr_t)env;
tf.tf_sp = stack;
tf.tf_status = CST_IRQMASK | CST_IEp | CST_KUp;
tf.tf_epc = entry;
tf.tf_a0 = argc;
tf.tf_a1 = (vaddr_t)argv;
tf.tf_a2 = (vaddr_t)env;
tf.tf_sp = stack;
mips_usermode(&tf);
mips_usermode(&tf);
}

View File

@@ -36,7 +36,6 @@
#include <current.h>
#include <syscall.h>
/*
* System call dispatcher.
*
@@ -75,75 +74,70 @@
* stack, starting at sp+16 to skip over the slots for the
* registerized values, with copyin().
*/
void
syscall(struct trapframe *tf)
{
int callno;
int32_t retval;
int err;
void syscall(struct trapframe *tf) {
int callno;
int32_t retval;
int err;
KASSERT(curthread != NULL);
KASSERT(curthread->t_curspl == 0);
KASSERT(curthread->t_iplhigh_count == 0);
KASSERT(curthread != NULL);
KASSERT(curthread->t_curspl == 0);
KASSERT(curthread->t_iplhigh_count == 0);
callno = tf->tf_v0;
callno = tf->tf_v0;
/*
* Initialize retval to 0. Many of the system calls don't
* really return a value, just 0 for success and -1 on
* error. Since retval is the value returned on success,
* initialize it to 0 by default; thus it's not necessary to
* deal with it except for calls that return other values,
* like write.
*/
/*
* Initialize retval to 0. Many of the system calls don't
* really return a value, just 0 for success and -1 on
* error. Since retval is the value returned on success,
* initialize it to 0 by default; thus it's not necessary to
* deal with it except for calls that return other values,
* like write.
*/
retval = 0;
retval = 0;
switch (callno) {
case SYS_reboot:
err = sys_reboot(tf->tf_a0);
break;
switch (callno) {
case SYS_reboot:
err = sys_reboot(tf->tf_a0);
break;
case SYS___time:
err = sys___time((userptr_t)tf->tf_a0,
(userptr_t)tf->tf_a1);
break;
case SYS___time:
err = sys___time((userptr_t)tf->tf_a0, (userptr_t)tf->tf_a1);
break;
/* Add stuff here */
/* Add stuff here */
default:
kprintf("Unknown syscall %d\n", callno);
err = ENOSYS;
break;
}
default:
kprintf("Unknown syscall %d\n", callno);
err = ENOSYS;
break;
}
if (err) {
/*
* Return the error code. This gets converted at
* userlevel to a return value of -1 and the error
* code in errno.
*/
tf->tf_v0 = err;
tf->tf_a3 = 1; /* signal an error */
} else {
/* Success. */
tf->tf_v0 = retval;
tf->tf_a3 = 0; /* signal no error */
}
if (err) {
/*
* Return the error code. This gets converted at
* userlevel to a return value of -1 and the error
* code in errno.
*/
tf->tf_v0 = err;
tf->tf_a3 = 1; /* signal an error */
}
else {
/* Success. */
tf->tf_v0 = retval;
tf->tf_a3 = 0; /* signal no error */
}
/*
* Now, advance the program counter, to avoid restarting
* the syscall over and over again.
*/
/*
* Now, advance the program counter, to avoid restarting
* the syscall over and over again.
*/
tf->tf_epc += 4;
tf->tf_epc += 4;
/* Make sure the syscall code didn't forget to lower spl */
KASSERT(curthread->t_curspl == 0);
/* ...or leak any spinlocks */
KASSERT(curthread->t_iplhigh_count == 0);
/* Make sure the syscall code didn't forget to lower spl */
KASSERT(curthread->t_curspl == 0);
/* ...or leak any spinlocks */
KASSERT(curthread->t_iplhigh_count == 0);
}
/*
@@ -154,8 +148,4 @@ syscall(struct trapframe *tf)
*
* Thus, you can trash it and do things another way if you prefer.
*/
void
enter_forked_process(struct trapframe *tf)
{
(void)tf;
}
void enter_forked_process(struct trapframe *tf) { (void)tf; }

View File

@@ -72,30 +72,27 @@ vaddr_t cputhreads[MAXCPUS];
* associated with a new cpu. Note that we're not running on the new
* cpu when this is called.
*/
void
cpu_machdep_init(struct cpu *c)
{
vaddr_t stackpointer;
void cpu_machdep_init(struct cpu *c) {
vaddr_t stackpointer;
KASSERT(c->c_number < MAXCPUS);
KASSERT(c->c_number < MAXCPUS);
if (c->c_curthread->t_stack == NULL) {
/* boot cpu; don't need to do anything here */
}
else {
/*
* Stick the stack in cpustacks[], and thread pointer
* in cputhreads[].
*/
if (c->c_curthread->t_stack == NULL) {
/* boot cpu; don't need to do anything here */
} else {
/*
* Stick the stack in cpustacks[], and thread pointer
* in cputhreads[].
*/
/* stack base address */
stackpointer = (vaddr_t) c->c_curthread->t_stack;
/* since stacks grow down, get the top */
stackpointer += STACK_SIZE;
/* stack base address */
stackpointer = (vaddr_t)c->c_curthread->t_stack;
/* since stacks grow down, get the top */
stackpointer += STACK_SIZE;
cpustacks[c->c_number] = stackpointer;
cputhreads[c->c_number] = (vaddr_t)c->c_curthread;
}
cpustacks[c->c_number] = stackpointer;
cputhreads[c->c_number] = (vaddr_t)c->c_curthread;
}
}
////////////////////////////////////////////////////////////
@@ -107,73 +104,61 @@ cpu_machdep_init(struct cpu *c)
* System/161 processor-ID values.
*/
#define SYS161_PRID_ORIG 0x000003ff
#define SYS161_PRID_2X 0x000000a1
#define SYS161_PRID_ORIG 0x000003ff
#define SYS161_PRID_2X 0x000000a1
static inline
uint32_t
cpu_getprid(void)
{
uint32_t prid;
static inline uint32_t cpu_getprid(void) {
uint32_t prid;
__asm volatile("mfc0 %0,$15" : "=r" (prid));
return prid;
__asm volatile("mfc0 %0,$15" : "=r"(prid));
return prid;
}
static inline
uint32_t
cpu_getfeatures(void)
{
uint32_t features;
static inline uint32_t cpu_getfeatures(void) {
uint32_t features;
__asm volatile(".set push;" /* save assembler mode */
".set mips32;" /* allow mips32 instructions */
"mfc0 %0,$15,1;" /* get cop0 reg 15 sel 1 */
".set pop" /* restore assembler mode */
: "=r" (features));
return features;
__asm volatile(".set push;" /* save assembler mode */
".set mips32;" /* allow mips32 instructions */
"mfc0 %0,$15,1;" /* get cop0 reg 15 sel 1 */
".set pop" /* restore assembler mode */
: "=r"(features));
return features;
}
static inline
uint32_t
cpu_getifeatures(void)
{
uint32_t features;
static inline uint32_t cpu_getifeatures(void) {
uint32_t features;
__asm volatile(".set push;" /* save assembler mode */
".set mips32;" /* allow mips32 instructions */
"mfc0 %0,$15,2;" /* get cop0 reg 15 sel 2 */
".set pop" /* restore assembler mode */
: "=r" (features));
return features;
__asm volatile(".set push;" /* save assembler mode */
".set mips32;" /* allow mips32 instructions */
"mfc0 %0,$15,2;" /* get cop0 reg 15 sel 2 */
".set pop" /* restore assembler mode */
: "=r"(features));
return features;
}
void
cpu_identify(char *buf, size_t max)
{
uint32_t prid;
uint32_t features;
void cpu_identify(char *buf, size_t max) {
uint32_t prid;
uint32_t features;
prid = cpu_getprid();
switch (prid) {
case SYS161_PRID_ORIG:
snprintf(buf, max, "MIPS/161 (System/161 1.x and pre-2.x)");
break;
case SYS161_PRID_2X:
features = cpu_getfeatures();
snprintf(buf, max, "MIPS/161 (System/161 2.x) features 0x%x",
features);
features = cpu_getifeatures();
if (features != 0) {
kprintf("WARNING: unknown CPU incompatible features "
"0x%x\n", features);
}
break;
default:
snprintf(buf, max, "32-bit MIPS (unknown type, CPU ID 0x%x)",
prid);
break;
}
prid = cpu_getprid();
switch (prid) {
case SYS161_PRID_ORIG:
snprintf(buf, max, "MIPS/161 (System/161 1.x and pre-2.x)");
break;
case SYS161_PRID_2X:
features = cpu_getfeatures();
snprintf(buf, max, "MIPS/161 (System/161 2.x) features 0x%x", features);
features = cpu_getifeatures();
if (features != 0) {
kprintf("WARNING: unknown CPU incompatible features "
"0x%x\n",
features);
}
break;
default:
snprintf(buf, max, "32-bit MIPS (unknown type, CPU ID 0x%x)", prid);
break;
}
}
////////////////////////////////////////////////////////////
@@ -200,50 +185,43 @@ cpu_identify(char *buf, size_t max)
* These considerations do not (currently) apply to System/161,
* however.
*/
#define GET_STATUS(x) __asm volatile("mfc0 %0,$12" : "=r" (x))
#define SET_STATUS(x) __asm volatile("mtc0 %0,$12" :: "r" (x))
#define GET_STATUS(x) __asm volatile("mfc0 %0,$12" : "=r"(x))
#define SET_STATUS(x) __asm volatile("mtc0 %0,$12" ::"r"(x))
/*
* Interrupts on.
*/
void
cpu_irqon(void)
{
uint32_t x;
void cpu_irqon(void) {
uint32_t x;
GET_STATUS(x);
x |= CST_IEc;
SET_STATUS(x);
GET_STATUS(x);
x |= CST_IEc;
SET_STATUS(x);
}
/*
* Interrupts off.
*/
void
cpu_irqoff(void)
{
uint32_t x;
void cpu_irqoff(void) {
uint32_t x;
GET_STATUS(x);
x &= ~(uint32_t)CST_IEc;
SET_STATUS(x);
GET_STATUS(x);
x &= ~(uint32_t)CST_IEc;
SET_STATUS(x);
}
/*
* Used below.
*/
static
void
cpu_irqonoff(void)
{
uint32_t x, xon, xoff;
static void cpu_irqonoff(void) {
uint32_t x, xon, xoff;
GET_STATUS(x);
xon = x | CST_IEc;
xoff = x & ~(uint32_t)CST_IEc;
SET_STATUS(xon);
__asm volatile("nop; nop; nop; nop");
SET_STATUS(xoff);
GET_STATUS(x);
xon = x | CST_IEc;
xoff = x & ~(uint32_t)CST_IEc;
SET_STATUS(xon);
__asm volatile("nop; nop; nop; nop");
SET_STATUS(xoff);
}
////////////////////////////////////////////////////////////
@@ -261,49 +239,40 @@ cpu_irqonoff(void)
* appropriate the mips32 WAIT instruction.
*/
static
inline
void
wait(void)
{
/*
* The WAIT instruction goes into powersave mode until an
* interrupt is trying to occur.
*
* Then switch interrupts on and off again, so we actually
* take the interrupt.
*
* Note that the precise behavior of this instruction in the
* System/161 simulator is partly guesswork. This code may not
* work on a real mips.
*/
__asm volatile(
".set push;" /* save assembler mode */
".set mips32;" /* allow MIPS32 instructions */
".set volatile;" /* avoid unwanted optimization */
"wait;" /* suspend until interrupted */
".set pop" /* restore assembler mode */
);
static inline void wait(void) {
/*
* The WAIT instruction goes into powersave mode until an
* interrupt is trying to occur.
*
* Then switch interrupts on and off again, so we actually
* take the interrupt.
*
* Note that the precise behavior of this instruction in the
* System/161 simulator is partly guesswork. This code may not
* work on a real mips.
*/
__asm volatile(".set push;" /* save assembler mode */
".set mips32;" /* allow MIPS32 instructions */
".set volatile;" /* avoid unwanted optimization */
"wait;" /* suspend until interrupted */
".set pop" /* restore assembler mode */
);
}
/*
* Idle the processor until something happens.
*/
void
cpu_idle(void)
{
wait();
cpu_irqonoff();
void cpu_idle(void) {
wait();
cpu_irqonoff();
}
/*
* Halt the CPU permanently.
*/
void
cpu_halt(void)
{
cpu_irqoff();
while (1) {
wait();
}
void cpu_halt(void) {
cpu_irqoff();
while (1) {
wait();
}
}

View File

@@ -37,7 +37,6 @@
/* in threadstart.S */
extern void mips_threadstart(/* arguments are in unusual registers */);
/*
* Function to initialize the switchframe of a new thread, which is
* *not* the one that is currently running.
@@ -51,48 +50,46 @@ extern void mips_threadstart(/* arguments are in unusual registers */);
* store the arguments in the s* registers, and use a bit of asm
* (mips_threadstart) to move them and then jump to thread_startup.
*/
void
switchframe_init(struct thread *thread,
void (*entrypoint)(void *data1, unsigned long data2),
void *data1, unsigned long data2)
{
vaddr_t stacktop;
struct switchframe *sf;
void switchframe_init(struct thread *thread,
void (*entrypoint)(void *data1, unsigned long data2),
void *data1, unsigned long data2) {
vaddr_t stacktop;
struct switchframe *sf;
/*
* MIPS stacks grow down. t_stack is just a hunk of memory, so
* get the other end of it. Then set up a switchframe on the
* top of the stack.
*/
stacktop = ((vaddr_t)thread->t_stack) + STACK_SIZE;
sf = ((struct switchframe *) stacktop) - 1;
/*
* MIPS stacks grow down. t_stack is just a hunk of memory, so
* get the other end of it. Then set up a switchframe on the
* top of the stack.
*/
stacktop = ((vaddr_t)thread->t_stack) + STACK_SIZE;
sf = ((struct switchframe *)stacktop) - 1;
/* Zero out the switchframe. */
bzero(sf, sizeof(*sf));
/* Zero out the switchframe. */
bzero(sf, sizeof(*sf));
/*
* Now set the important parts: pass through the three arguments,
* and set the return address register to the place we want
* execution to begin.
*
* Thus, when switchframe_switch does its "j ra", it will
* actually jump to mips_threadstart, which will move the
* arguments into the right register and jump to
* thread_startup().
*
* Note that this means that when we call switchframe_switch()
* in thread_switch(), we may not come back out the same way
* in the next thread. (Though we will come back out the same
* way when we later come back to the same thread again.)
*
* This has implications for code at the bottom of
* thread_switch, described in thread.c.
*/
sf->sf_s0 = (uint32_t)entrypoint;
sf->sf_s1 = (uint32_t)data1;
sf->sf_s2 = (uint32_t)data2;
sf->sf_ra = (uint32_t)mips_threadstart;
/*
* Now set the important parts: pass through the three arguments,
* and set the return address register to the place we want
* execution to begin.
*
* Thus, when switchframe_switch does its "j ra", it will
* actually jump to mips_threadstart, which will move the
* arguments into the right register and jump to
* thread_startup().
*
* Note that this means that when we call switchframe_switch()
* in thread_switch(), we may not come back out the same way
* in the next thread. (Though we will come back out the same
* way when we later come back to the same thread again.)
*
* This has implications for code at the bottom of
* thread_switch, described in thread.c.
*/
sf->sf_s0 = (uint32_t)entrypoint;
sf->sf_s1 = (uint32_t)data1;
sf->sf_s2 = (uint32_t)data2;
sf->sf_ra = (uint32_t)mips_threadstart;
/* Set ->t_context, and we're done. */
thread->t_context = sf;
/* Set ->t_context, and we're done. */
thread->t_context = sf;
}

View File

@@ -37,16 +37,16 @@
*/
struct switchframe {
uint32_t sf_s0;
uint32_t sf_s1;
uint32_t sf_s2;
uint32_t sf_s3;
uint32_t sf_s4;
uint32_t sf_s5;
uint32_t sf_s6;
uint32_t sf_s8;
uint32_t sf_gp;
uint32_t sf_ra;
uint32_t sf_s0;
uint32_t sf_s1;
uint32_t sf_s2;
uint32_t sf_s3;
uint32_t sf_s4;
uint32_t sf_s5;
uint32_t sf_s6;
uint32_t sf_s8;
uint32_t sf_gp;
uint32_t sf_ra;
};
#endif /* _MIPS_SWITCHFRAME_H_ */

View File

@@ -36,14 +36,10 @@
#include <thread.h>
#include <threadprivate.h>
void
thread_machdep_init(struct thread_machdep *tm)
{
tm->tm_badfaultfunc = NULL;
void thread_machdep_init(struct thread_machdep *tm) {
tm->tm_badfaultfunc = NULL;
}
void
thread_machdep_cleanup(struct thread_machdep *tm)
{
KASSERT(tm->tm_badfaultfunc == NULL);
void thread_machdep_cleanup(struct thread_machdep *tm) {
KASSERT(tm->tm_badfaultfunc == NULL);
}

View File

@@ -57,18 +57,14 @@
/* under dumbvm, always have 72k of user stack */
/* (this must be > 64K so argument blocks of size ARG_MAX will fit) */
#define DUMBVM_STACKPAGES 18
#define DUMBVM_STACKPAGES 18
/*
* Wrap ram_stealmem in a spinlock.
*/
static struct spinlock stealmem_lock = SPINLOCK_INITIALIZER;
void
vm_bootstrap(void)
{
/* Do nothing. */
}
void vm_bootstrap(void) { /* Do nothing. */ }
/*
* Check if we're in a context that can sleep. While most of the
@@ -77,351 +73,311 @@ vm_bootstrap(void)
* avoid the situation where syscall-layer code that works ok with
* dumbvm starts blowing up during the VM assignment.
*/
static
void
dumbvm_can_sleep(void)
{
if (CURCPU_EXISTS()) {
/* must not hold spinlocks */
KASSERT(curcpu->c_spinlocks == 0);
static void dumbvm_can_sleep(void) {
if (CURCPU_EXISTS()) {
/* must not hold spinlocks */
KASSERT(curcpu->c_spinlocks == 0);
/* must not be in an interrupt handler */
KASSERT(curthread->t_in_interrupt == 0);
}
/* must not be in an interrupt handler */
KASSERT(curthread->t_in_interrupt == 0);
}
}
static
paddr_t
getppages(unsigned long npages)
{
paddr_t addr;
static paddr_t getppages(unsigned long npages) {
paddr_t addr;
spinlock_acquire(&stealmem_lock);
spinlock_acquire(&stealmem_lock);
addr = ram_stealmem(npages);
addr = ram_stealmem(npages);
spinlock_release(&stealmem_lock);
return addr;
spinlock_release(&stealmem_lock);
return addr;
}
/* Allocate/free some kernel-space virtual pages */
vaddr_t
alloc_kpages(unsigned npages)
{
paddr_t pa;
vaddr_t alloc_kpages(unsigned npages) {
paddr_t pa;
dumbvm_can_sleep();
pa = getppages(npages);
if (pa==0) {
return 0;
}
return PADDR_TO_KVADDR(pa);
dumbvm_can_sleep();
pa = getppages(npages);
if (pa == 0) {
return 0;
}
return PADDR_TO_KVADDR(pa);
}
void
free_kpages(vaddr_t addr)
{
/* nothing - leak the memory. */
void free_kpages(vaddr_t addr) {
/* nothing - leak the memory. */
(void)addr;
(void)addr;
}
void
vm_tlbshootdown(const struct tlbshootdown *ts)
{
(void)ts;
panic("dumbvm tried to do tlb shootdown?!\n");
void vm_tlbshootdown(const struct tlbshootdown *ts) {
(void)ts;
panic("dumbvm tried to do tlb shootdown?!\n");
}
int
vm_fault(int faulttype, vaddr_t faultaddress)
{
vaddr_t vbase1, vtop1, vbase2, vtop2, stackbase, stacktop;
paddr_t paddr;
int i;
uint32_t ehi, elo;
struct addrspace *as;
int spl;
int vm_fault(int faulttype, vaddr_t faultaddress) {
vaddr_t vbase1, vtop1, vbase2, vtop2, stackbase, stacktop;
paddr_t paddr;
int i;
uint32_t ehi, elo;
struct addrspace *as;
int spl;
faultaddress &= PAGE_FRAME;
faultaddress &= PAGE_FRAME;
DEBUG(DB_VM, "dumbvm: fault: 0x%x\n", faultaddress);
DEBUG(DB_VM, "dumbvm: fault: 0x%x\n", faultaddress);
switch (faulttype) {
case VM_FAULT_READONLY:
/* We always create pages read-write, so we can't get this */
panic("dumbvm: got VM_FAULT_READONLY\n");
case VM_FAULT_READ:
case VM_FAULT_WRITE:
break;
default:
return EINVAL;
}
switch (faulttype) {
case VM_FAULT_READONLY:
/* We always create pages read-write, so we can't get this */
panic("dumbvm: got VM_FAULT_READONLY\n");
case VM_FAULT_READ:
case VM_FAULT_WRITE:
break;
default:
return EINVAL;
}
if (curproc == NULL) {
/*
* No process. This is probably a kernel fault early
* in boot. Return EFAULT so as to panic instead of
* getting into an infinite faulting loop.
*/
return EFAULT;
}
if (curproc == NULL) {
/*
* No process. This is probably a kernel fault early
* in boot. Return EFAULT so as to panic instead of
* getting into an infinite faulting loop.
*/
return EFAULT;
}
as = proc_getas();
if (as == NULL) {
/*
* No address space set up. This is probably also a
* kernel fault early in boot.
*/
return EFAULT;
}
as = proc_getas();
if (as == NULL) {
/*
* No address space set up. This is probably also a
* kernel fault early in boot.
*/
return EFAULT;
}
/* Assert that the address space has been set up properly. */
KASSERT(as->as_vbase1 != 0);
KASSERT(as->as_pbase1 != 0);
KASSERT(as->as_npages1 != 0);
KASSERT(as->as_vbase2 != 0);
KASSERT(as->as_pbase2 != 0);
KASSERT(as->as_npages2 != 0);
KASSERT(as->as_stackpbase != 0);
KASSERT((as->as_vbase1 & PAGE_FRAME) == as->as_vbase1);
KASSERT((as->as_pbase1 & PAGE_FRAME) == as->as_pbase1);
KASSERT((as->as_vbase2 & PAGE_FRAME) == as->as_vbase2);
KASSERT((as->as_pbase2 & PAGE_FRAME) == as->as_pbase2);
KASSERT((as->as_stackpbase & PAGE_FRAME) == as->as_stackpbase);
/* Assert that the address space has been set up properly. */
KASSERT(as->as_vbase1 != 0);
KASSERT(as->as_pbase1 != 0);
KASSERT(as->as_npages1 != 0);
KASSERT(as->as_vbase2 != 0);
KASSERT(as->as_pbase2 != 0);
KASSERT(as->as_npages2 != 0);
KASSERT(as->as_stackpbase != 0);
KASSERT((as->as_vbase1 & PAGE_FRAME) == as->as_vbase1);
KASSERT((as->as_pbase1 & PAGE_FRAME) == as->as_pbase1);
KASSERT((as->as_vbase2 & PAGE_FRAME) == as->as_vbase2);
KASSERT((as->as_pbase2 & PAGE_FRAME) == as->as_pbase2);
KASSERT((as->as_stackpbase & PAGE_FRAME) == as->as_stackpbase);
vbase1 = as->as_vbase1;
vtop1 = vbase1 + as->as_npages1 * PAGE_SIZE;
vbase2 = as->as_vbase2;
vtop2 = vbase2 + as->as_npages2 * PAGE_SIZE;
stackbase = USERSTACK - DUMBVM_STACKPAGES * PAGE_SIZE;
stacktop = USERSTACK;
vbase1 = as->as_vbase1;
vtop1 = vbase1 + as->as_npages1 * PAGE_SIZE;
vbase2 = as->as_vbase2;
vtop2 = vbase2 + as->as_npages2 * PAGE_SIZE;
stackbase = USERSTACK - DUMBVM_STACKPAGES * PAGE_SIZE;
stacktop = USERSTACK;
if (faultaddress >= vbase1 && faultaddress < vtop1) {
paddr = (faultaddress - vbase1) + as->as_pbase1;
}
else if (faultaddress >= vbase2 && faultaddress < vtop2) {
paddr = (faultaddress - vbase2) + as->as_pbase2;
}
else if (faultaddress >= stackbase && faultaddress < stacktop) {
paddr = (faultaddress - stackbase) + as->as_stackpbase;
}
else {
return EFAULT;
}
if (faultaddress >= vbase1 && faultaddress < vtop1) {
paddr = (faultaddress - vbase1) + as->as_pbase1;
} else if (faultaddress >= vbase2 && faultaddress < vtop2) {
paddr = (faultaddress - vbase2) + as->as_pbase2;
} else if (faultaddress >= stackbase && faultaddress < stacktop) {
paddr = (faultaddress - stackbase) + as->as_stackpbase;
} else {
return EFAULT;
}
/* make sure it's page-aligned */
KASSERT((paddr & PAGE_FRAME) == paddr);
/* make sure it's page-aligned */
KASSERT((paddr & PAGE_FRAME) == paddr);
/* Disable interrupts on this CPU while frobbing the TLB. */
spl = splhigh();
/* Disable interrupts on this CPU while frobbing the TLB. */
spl = splhigh();
for (i=0; i<NUM_TLB; i++) {
tlb_read(&ehi, &elo, i);
if (elo & TLBLO_VALID) {
continue;
}
ehi = faultaddress;
elo = paddr | TLBLO_DIRTY | TLBLO_VALID;
DEBUG(DB_VM, "dumbvm: 0x%x -> 0x%x\n", faultaddress, paddr);
tlb_write(ehi, elo, i);
splx(spl);
return 0;
}
for (i = 0; i < NUM_TLB; i++) {
tlb_read(&ehi, &elo, i);
if (elo & TLBLO_VALID) {
continue;
}
ehi = faultaddress;
elo = paddr | TLBLO_DIRTY | TLBLO_VALID;
DEBUG(DB_VM, "dumbvm: 0x%x -> 0x%x\n", faultaddress, paddr);
tlb_write(ehi, elo, i);
splx(spl);
return 0;
}
kprintf("dumbvm: Ran out of TLB entries - cannot handle page fault\n");
splx(spl);
return EFAULT;
kprintf("dumbvm: Ran out of TLB entries - cannot handle page fault\n");
splx(spl);
return EFAULT;
}
struct addrspace *
as_create(void)
{
struct addrspace *as = kmalloc(sizeof(struct addrspace));
if (as==NULL) {
return NULL;
}
struct addrspace *as_create(void) {
struct addrspace *as = kmalloc(sizeof(struct addrspace));
if (as == NULL) {
return NULL;
}
as->as_vbase1 = 0;
as->as_pbase1 = 0;
as->as_npages1 = 0;
as->as_vbase2 = 0;
as->as_pbase2 = 0;
as->as_npages2 = 0;
as->as_stackpbase = 0;
as->as_vbase1 = 0;
as->as_pbase1 = 0;
as->as_npages1 = 0;
as->as_vbase2 = 0;
as->as_pbase2 = 0;
as->as_npages2 = 0;
as->as_stackpbase = 0;
return as;
return as;
}
void
as_destroy(struct addrspace *as)
{
dumbvm_can_sleep();
kfree(as);
void as_destroy(struct addrspace *as) {
dumbvm_can_sleep();
kfree(as);
}
void
as_activate(void)
{
int i, spl;
struct addrspace *as;
void as_activate(void) {
int i, spl;
struct addrspace *as;
as = proc_getas();
if (as == NULL) {
return;
}
as = proc_getas();
if (as == NULL) {
return;
}
/* Disable interrupts on this CPU while frobbing the TLB. */
spl = splhigh();
/* Disable interrupts on this CPU while frobbing the TLB. */
spl = splhigh();
for (i=0; i<NUM_TLB; i++) {
tlb_write(TLBHI_INVALID(i), TLBLO_INVALID(), i);
}
for (i = 0; i < NUM_TLB; i++) {
tlb_write(TLBHI_INVALID(i), TLBLO_INVALID(), i);
}
splx(spl);
splx(spl);
}
void
as_deactivate(void)
{
/* nothing */
void as_deactivate(void) { /* nothing */ }
int as_define_region(struct addrspace *as, vaddr_t vaddr, size_t sz,
int readable, int writeable, int executable) {
size_t npages;
dumbvm_can_sleep();
/* Align the region. First, the base... */
sz += vaddr & ~(vaddr_t)PAGE_FRAME;
vaddr &= PAGE_FRAME;
/* ...and now the length. */
sz = (sz + PAGE_SIZE - 1) & PAGE_FRAME;
npages = sz / PAGE_SIZE;
/* We don't use these - all pages are read-write */
(void)readable;
(void)writeable;
(void)executable;
if (as->as_vbase1 == 0) {
as->as_vbase1 = vaddr;
as->as_npages1 = npages;
return 0;
}
if (as->as_vbase2 == 0) {
as->as_vbase2 = vaddr;
as->as_npages2 = npages;
return 0;
}
/*
* Support for more than two regions is not available.
*/
kprintf("dumbvm: Warning: too many regions\n");
return ENOSYS;
}
int
as_define_region(struct addrspace *as, vaddr_t vaddr, size_t sz,
int readable, int writeable, int executable)
{
size_t npages;
dumbvm_can_sleep();
/* Align the region. First, the base... */
sz += vaddr & ~(vaddr_t)PAGE_FRAME;
vaddr &= PAGE_FRAME;
/* ...and now the length. */
sz = (sz + PAGE_SIZE - 1) & PAGE_FRAME;
npages = sz / PAGE_SIZE;
/* We don't use these - all pages are read-write */
(void)readable;
(void)writeable;
(void)executable;
if (as->as_vbase1 == 0) {
as->as_vbase1 = vaddr;
as->as_npages1 = npages;
return 0;
}
if (as->as_vbase2 == 0) {
as->as_vbase2 = vaddr;
as->as_npages2 = npages;
return 0;
}
/*
* Support for more than two regions is not available.
*/
kprintf("dumbvm: Warning: too many regions\n");
return ENOSYS;
static void as_zero_region(paddr_t paddr, unsigned npages) {
bzero((void *)PADDR_TO_KVADDR(paddr), npages * PAGE_SIZE);
}
static
void
as_zero_region(paddr_t paddr, unsigned npages)
{
bzero((void *)PADDR_TO_KVADDR(paddr), npages * PAGE_SIZE);
int as_prepare_load(struct addrspace *as) {
KASSERT(as->as_pbase1 == 0);
KASSERT(as->as_pbase2 == 0);
KASSERT(as->as_stackpbase == 0);
dumbvm_can_sleep();
as->as_pbase1 = getppages(as->as_npages1);
if (as->as_pbase1 == 0) {
return ENOMEM;
}
as->as_pbase2 = getppages(as->as_npages2);
if (as->as_pbase2 == 0) {
return ENOMEM;
}
as->as_stackpbase = getppages(DUMBVM_STACKPAGES);
if (as->as_stackpbase == 0) {
return ENOMEM;
}
as_zero_region(as->as_pbase1, as->as_npages1);
as_zero_region(as->as_pbase2, as->as_npages2);
as_zero_region(as->as_stackpbase, DUMBVM_STACKPAGES);
return 0;
}
int
as_prepare_load(struct addrspace *as)
{
KASSERT(as->as_pbase1 == 0);
KASSERT(as->as_pbase2 == 0);
KASSERT(as->as_stackpbase == 0);
dumbvm_can_sleep();
as->as_pbase1 = getppages(as->as_npages1);
if (as->as_pbase1 == 0) {
return ENOMEM;
}
as->as_pbase2 = getppages(as->as_npages2);
if (as->as_pbase2 == 0) {
return ENOMEM;
}
as->as_stackpbase = getppages(DUMBVM_STACKPAGES);
if (as->as_stackpbase == 0) {
return ENOMEM;
}
as_zero_region(as->as_pbase1, as->as_npages1);
as_zero_region(as->as_pbase2, as->as_npages2);
as_zero_region(as->as_stackpbase, DUMBVM_STACKPAGES);
return 0;
int as_complete_load(struct addrspace *as) {
dumbvm_can_sleep();
(void)as;
return 0;
}
int
as_complete_load(struct addrspace *as)
{
dumbvm_can_sleep();
(void)as;
return 0;
int as_define_stack(struct addrspace *as, vaddr_t *stackptr) {
KASSERT(as->as_stackpbase != 0);
*stackptr = USERSTACK;
return 0;
}
int
as_define_stack(struct addrspace *as, vaddr_t *stackptr)
{
KASSERT(as->as_stackpbase != 0);
int as_copy(struct addrspace *old, struct addrspace **ret) {
struct addrspace *new;
*stackptr = USERSTACK;
return 0;
}
int
as_copy(struct addrspace *old, struct addrspace **ret)
{
struct addrspace *new;
dumbvm_can_sleep();
new = as_create();
if (new==NULL) {
return ENOMEM;
}
new->as_vbase1 = old->as_vbase1;
new->as_npages1 = old->as_npages1;
new->as_vbase2 = old->as_vbase2;
new->as_npages2 = old->as_npages2;
/* (Mis)use as_prepare_load to allocate some physical memory. */
if (as_prepare_load(new)) {
as_destroy(new);
return ENOMEM;
}
KASSERT(new->as_pbase1 != 0);
KASSERT(new->as_pbase2 != 0);
KASSERT(new->as_stackpbase != 0);
memmove((void *)PADDR_TO_KVADDR(new->as_pbase1),
(const void *)PADDR_TO_KVADDR(old->as_pbase1),
old->as_npages1*PAGE_SIZE);
memmove((void *)PADDR_TO_KVADDR(new->as_pbase2),
(const void *)PADDR_TO_KVADDR(old->as_pbase2),
old->as_npages2*PAGE_SIZE);
memmove((void *)PADDR_TO_KVADDR(new->as_stackpbase),
(const void *)PADDR_TO_KVADDR(old->as_stackpbase),
DUMBVM_STACKPAGES*PAGE_SIZE);
*ret = new;
return 0;
dumbvm_can_sleep();
new = as_create();
if (new == NULL) {
return ENOMEM;
}
new->as_vbase1 = old->as_vbase1;
new->as_npages1 = old->as_npages1;
new->as_vbase2 = old->as_vbase2;
new->as_npages2 = old->as_npages2;
/* (Mis)use as_prepare_load to allocate some physical memory. */
if (as_prepare_load(new)) {
as_destroy(new);
return ENOMEM;
}
KASSERT(new->as_pbase1 != 0);
KASSERT(new->as_pbase2 != 0);
KASSERT(new->as_stackpbase != 0);
memmove((void *)PADDR_TO_KVADDR(new->as_pbase1),
(const void *)PADDR_TO_KVADDR(old->as_pbase1),
old->as_npages1 * PAGE_SIZE);
memmove((void *)PADDR_TO_KVADDR(new->as_pbase2),
(const void *)PADDR_TO_KVADDR(old->as_pbase2),
old->as_npages2 * PAGE_SIZE);
memmove((void *)PADDR_TO_KVADDR(new->as_stackpbase),
(const void *)PADDR_TO_KVADDR(old->as_stackpbase),
DUMBVM_STACKPAGES * PAGE_SIZE);
*ret = new;
return 0;
}

View File

@@ -32,45 +32,41 @@
#include <vm.h>
#include <mainbus.h>
vaddr_t firstfree; /* first free virtual address; set by start.S */
vaddr_t firstfree; /* first free virtual address; set by start.S */
static paddr_t firstpaddr; /* address of first free physical page */
static paddr_t lastpaddr; /* one past end of last free physical page */
static paddr_t firstpaddr; /* address of first free physical page */
static paddr_t lastpaddr; /* one past end of last free physical page */
/*
* Called very early in system boot to figure out how much physical
* RAM is available.
*/
void
ram_bootstrap(void)
{
size_t ramsize;
void ram_bootstrap(void) {
size_t ramsize;
/* Get size of RAM. */
ramsize = mainbus_ramsize();
/* Get size of RAM. */
ramsize = mainbus_ramsize();
/*
* This is the same as the last physical address, as long as
* we have less than 512 megabytes of memory. If we had more,
* we wouldn't be able to access it all through kseg0 and
* everything would get a lot more complicated. This is not a
* case we are going to worry about.
*/
if (ramsize > 512*1024*1024) {
ramsize = 512*1024*1024;
}
/*
* This is the same as the last physical address, as long as
* we have less than 512 megabytes of memory. If we had more,
* we wouldn't be able to access it all through kseg0 and
* everything would get a lot more complicated. This is not a
* case we are going to worry about.
*/
if (ramsize > 512 * 1024 * 1024) {
ramsize = 512 * 1024 * 1024;
}
lastpaddr = ramsize;
lastpaddr = ramsize;
/*
* Get first free virtual address from where start.S saved it.
* Convert to physical address.
*/
firstpaddr = firstfree - MIPS_KSEG0;
/*
* Get first free virtual address from where start.S saved it.
* Convert to physical address.
*/
firstpaddr = firstfree - MIPS_KSEG0;
kprintf("%uk physical memory available\n",
(lastpaddr-firstpaddr)/1024);
kprintf("%uk physical memory available\n", (lastpaddr - firstpaddr) / 1024);
}
/*
@@ -91,22 +87,20 @@ ram_bootstrap(void)
* This function should not be called once the VM system is initialized,
* so it is not synchronized.
*/
paddr_t
ram_stealmem(unsigned long npages)
{
size_t size;
paddr_t paddr;
paddr_t ram_stealmem(unsigned long npages) {
size_t size;
paddr_t paddr;
size = npages * PAGE_SIZE;
size = npages * PAGE_SIZE;
if (firstpaddr + size > lastpaddr) {
return 0;
}
if (firstpaddr + size > lastpaddr) {
return 0;
}
paddr = firstpaddr;
firstpaddr += size;
paddr = firstpaddr;
firstpaddr += size;
return paddr;
return paddr;
}
/*
@@ -124,11 +118,7 @@ ram_stealmem(unsigned long npages)
* initialize the VM system, after which the VM system should take
* charge of knowing what memory exists.
*/
paddr_t
ram_getsize(void)
{
return lastpaddr;
}
paddr_t ram_getsize(void) { return lastpaddr; }
/*
* This function is intended to be called by the VM system when it
@@ -142,12 +132,10 @@ ram_getsize(void)
* This function should not be called once the VM system is initialized,
* so it is not synchronized.
*/
paddr_t
ram_getfirstfree(void)
{
paddr_t ret;
paddr_t ram_getfirstfree(void) {
paddr_t ret;
ret = firstpaddr;
firstpaddr = lastpaddr = 0;
return ret;
ret = firstpaddr;
firstpaddr = lastpaddr = 0;
return ret;
}

View File

@@ -60,20 +60,16 @@
* matches the c0_compare register, the timer interrupt line is
* asserted. Writing to c0_compare again clears the interrupt.
*/
static
void
mips_timer_set(uint32_t count)
{
/*
* $11 == c0_compare; we can't use the symbolic name inside
* the asm string.
*/
__asm volatile(
".set push;" /* save assembler mode */
".set mips32;" /* allow MIPS32 registers */
"mtc0 %0, $11;" /* do it */
".set pop" /* restore assembler mode */
:: "r" (count));
static void mips_timer_set(uint32_t count) {
/*
* $11 == c0_compare; we can't use the symbolic name inside
* the asm string.
*/
__asm volatile(".set push;" /* save assembler mode */
".set mips32;" /* allow MIPS32 registers */
"mtc0 %0, $11;" /* do it */
".set pop" /* restore assembler mode */
::"r"(count));
}
/*
@@ -83,138 +79,122 @@ mips_timer_set(uint32_t count)
*/
static struct lamebus_softc *lamebus;
void
mainbus_bootstrap(void)
{
/* Interrupts should be off (and have been off since startup) */
KASSERT(curthread->t_curspl > 0);
void mainbus_bootstrap(void) {
/* Interrupts should be off (and have been off since startup) */
KASSERT(curthread->t_curspl > 0);
/* Initialize the system LAMEbus data */
lamebus = lamebus_init();
/* Initialize the system LAMEbus data */
lamebus = lamebus_init();
/* Probe CPUs (should these be done as device attachments instead?) */
lamebus_find_cpus(lamebus);
/* Probe CPUs (should these be done as device attachments instead?) */
lamebus_find_cpus(lamebus);
/*
* Print the device name for the main bus.
*/
kprintf("lamebus0 (system main bus)\n");
/*
* Print the device name for the main bus.
*/
kprintf("lamebus0 (system main bus)\n");
/*
* Now we can take interrupts without croaking, so turn them on.
* Some device probes might require being able to get interrupts.
*/
/*
* Now we can take interrupts without croaking, so turn them on.
* Some device probes might require being able to get interrupts.
*/
spl0();
spl0();
/*
* Now probe all the devices attached to the bus.
* (This amounts to all devices.)
*/
autoconf_lamebus(lamebus, 0);
/*
* Now probe all the devices attached to the bus.
* (This amounts to all devices.)
*/
autoconf_lamebus(lamebus, 0);
/*
* Configure the MIPS on-chip timer to interrupt HZ times a second.
*/
mips_timer_set(CPU_FREQUENCY / HZ);
/*
* Configure the MIPS on-chip timer to interrupt HZ times a second.
*/
mips_timer_set(CPU_FREQUENCY / HZ);
}
/*
* Start all secondary CPUs.
*/
void
mainbus_start_cpus(void)
{
lamebus_start_cpus(lamebus);
}
void mainbus_start_cpus(void) { lamebus_start_cpus(lamebus); }
/*
* Function to generate the memory address (in the uncached segment)
* for the specified offset into the specified slot's region of the
* LAMEbus.
*/
void *
lamebus_map_area(struct lamebus_softc *bus, int slot, uint32_t offset)
{
uint32_t address;
void *lamebus_map_area(struct lamebus_softc *bus, int slot, uint32_t offset) {
uint32_t address;
(void)bus; // not needed
(void)bus; // not needed
KASSERT(slot >= 0 && slot < LB_NSLOTS);
KASSERT(slot >= 0 && slot < LB_NSLOTS);
address = LB_BASEADDR + slot*LB_SLOT_SIZE + offset;
return (void *)address;
address = LB_BASEADDR + slot * LB_SLOT_SIZE + offset;
return (void *)address;
}
/*
* Read a 32-bit register from a LAMEbus device.
*/
uint32_t
lamebus_read_register(struct lamebus_softc *bus, int slot, uint32_t offset)
{
uint32_t *ptr;
uint32_t lamebus_read_register(struct lamebus_softc *bus, int slot,
uint32_t offset) {
uint32_t *ptr;
ptr = lamebus_map_area(bus, slot, offset);
ptr = lamebus_map_area(bus, slot, offset);
/*
* Make sure the load happens after anything the device has
* been doing.
*/
membar_load_load();
/*
* Make sure the load happens after anything the device has
* been doing.
*/
membar_load_load();
return *ptr;
return *ptr;
}
/*
* Write a 32-bit register of a LAMEbus device.
*/
void
lamebus_write_register(struct lamebus_softc *bus, int slot,
uint32_t offset, uint32_t val)
{
uint32_t *ptr;
void lamebus_write_register(struct lamebus_softc *bus, int slot,
uint32_t offset, uint32_t val) {
uint32_t *ptr;
ptr = lamebus_map_area(bus, slot, offset);
*ptr = val;
ptr = lamebus_map_area(bus, slot, offset);
*ptr = val;
/*
* Make sure the store happens before we do anything else to
* the device.
*/
membar_store_store();
/*
* Make sure the store happens before we do anything else to
* the device.
*/
membar_store_store();
}
/*
* Power off the system.
*/
void
mainbus_poweroff(void)
{
/*
*
* Note that lamebus_write_register() doesn't actually access
* the bus argument, so this will still work if we get here
* before the bus is initialized.
*/
lamebus_poweroff(lamebus);
void mainbus_poweroff(void) {
/*
*
* Note that lamebus_write_register() doesn't actually access
* the bus argument, so this will still work if we get here
* before the bus is initialized.
*/
lamebus_poweroff(lamebus);
}
/*
* Reboot the system.
*/
void
mainbus_reboot(void)
{
/*
* The MIPS doesn't appear to have any on-chip reset.
* LAMEbus doesn't have a reset control, so we just
* power off instead of rebooting. This would not be
* so great in a real system, but it's fine for what
* we're doing.
*/
kprintf("Cannot reboot - powering off instead, sorry.\n");
mainbus_poweroff();
void mainbus_reboot(void) {
/*
* The MIPS doesn't appear to have any on-chip reset.
* LAMEbus doesn't have a reset control, so we just
* power off instead of rebooting. This would not be
* so great in a real system, but it's fine for what
* we're doing.
*/
kprintf("Cannot reboot - powering off instead, sorry.\n");
mainbus_poweroff();
}
/*
@@ -222,11 +202,7 @@ mainbus_reboot(void)
* On some systems, this would return to the boot monitor. But we don't
* have one.
*/
void
mainbus_halt(void)
{
cpu_halt();
}
void mainbus_halt(void) { cpu_halt(); }
/*
* Called to reset the system from panic().
@@ -235,110 +211,94 @@ mainbus_halt(void)
* as to panic recursively if we do much of anything. So just power off.
* (We'd reboot, but System/161 doesn't do that.)
*/
void
mainbus_panic(void)
{
mainbus_poweroff();
}
void mainbus_panic(void) { mainbus_poweroff(); }
/*
* Function to get the size of installed physical RAM from the LAMEbus
* controller.
*/
uint32_t
mainbus_ramsize(void)
{
uint32_t ramsize;
uint32_t mainbus_ramsize(void) {
uint32_t ramsize;
ramsize = lamebus_ramsize();
ramsize = lamebus_ramsize();
/*
* This is the same as the last physical address, as long as
* we have less than 508 megabytes of memory. The LAMEbus I/O
* area occupies the space between 508 megabytes and 512
* megabytes, so if we had more RAM than this it would have to
* be discontiguous. This is not a case we are going to worry
* about.
*/
if (ramsize > 508*1024*1024) {
ramsize = 508*1024*1024;
}
/*
* This is the same as the last physical address, as long as
* we have less than 508 megabytes of memory. The LAMEbus I/O
* area occupies the space between 508 megabytes and 512
* megabytes, so if we had more RAM than this it would have to
* be discontiguous. This is not a case we are going to worry
* about.
*/
if (ramsize > 508 * 1024 * 1024) {
ramsize = 508 * 1024 * 1024;
}
return ramsize;
return ramsize;
}
/*
* Send IPI.
*/
void
mainbus_send_ipi(struct cpu *target)
{
lamebus_assert_ipi(lamebus, target);
void mainbus_send_ipi(struct cpu *target) {
lamebus_assert_ipi(lamebus, target);
}
/*
* Trigger the debugger.
*/
void
mainbus_debugger(void)
{
ltrace_stop(0);
}
void mainbus_debugger(void) { ltrace_stop(0); }
/*
* Interrupt dispatcher.
*/
/* Wiring of LAMEbus interrupts to bits in the cause register */
#define LAMEBUS_IRQ_BIT 0x00000400 /* all system bus slots */
#define LAMEBUS_IPI_BIT 0x00000800 /* inter-processor interrupt */
#define MIPS_TIMER_BIT 0x00008000 /* on-chip timer */
#define LAMEBUS_IRQ_BIT 0x00000400 /* all system bus slots */
#define LAMEBUS_IPI_BIT 0x00000800 /* inter-processor interrupt */
#define MIPS_TIMER_BIT 0x00008000 /* on-chip timer */
void
mainbus_interrupt(struct trapframe *tf)
{
uint32_t cause;
bool seen = false;
void mainbus_interrupt(struct trapframe *tf) {
uint32_t cause;
bool seen = false;
/* interrupts should be off */
KASSERT(curthread->t_curspl > 0);
/* interrupts should be off */
KASSERT(curthread->t_curspl > 0);
cause = tf->tf_cause;
if (cause & LAMEBUS_IRQ_BIT) {
lamebus_interrupt(lamebus);
seen = true;
}
if (cause & LAMEBUS_IPI_BIT) {
interprocessor_interrupt();
lamebus_clear_ipi(lamebus, curcpu);
seen = true;
}
if (cause & MIPS_TIMER_BIT) {
/* Reset the timer (this clears the interrupt) */
mips_timer_set(CPU_FREQUENCY / HZ);
/* and call hardclock */
hardclock();
seen = true;
}
cause = tf->tf_cause;
if (cause & LAMEBUS_IRQ_BIT) {
lamebus_interrupt(lamebus);
seen = true;
}
if (cause & LAMEBUS_IPI_BIT) {
interprocessor_interrupt();
lamebus_clear_ipi(lamebus, curcpu);
seen = true;
}
if (cause & MIPS_TIMER_BIT) {
/* Reset the timer (this clears the interrupt) */
mips_timer_set(CPU_FREQUENCY / HZ);
/* and call hardclock */
hardclock();
seen = true;
}
if (!seen) {
if ((cause & CCA_IRQS) == 0) {
/*
* Don't panic here; this can happen if an
* interrupt line asserts (very) briefly and
* turns off again before we get as far as
* reading the cause register. This was
* actually seen... once.
*/
}
else {
/*
* But if we get an interrupt on an interrupt
* line that's not supposed to be wired up,
* complain.
*/
panic("Unknown interrupt; cause register is %08x\n",
cause);
}
}
if (!seen) {
if ((cause & CCA_IRQS) == 0) {
/*
* Don't panic here; this can happen if an
* interrupt line asserts (very) briefly and
* turns off again before we get as far as
* reading the cause register. This was
* actually seen... once.
*/
} else {
/*
* But if we get an interrupt on an interrupt
* line that's not supposed to be wired up,
* complain.
*/
panic("Unknown interrupt; cause register is %08x\n", cause);
}
}
}

View File

@@ -37,24 +37,22 @@
* This would need to be a bit more complicated if that weren't the case.
*/
#include <machine/vm.h> /* for MIPS_KSEG1 */
#include <lamebus/lamebus.h> /* for LAMEbus definitions */
#include <machine/vm.h> /* for MIPS_KSEG1 */
#include <lamebus/lamebus.h> /* for LAMEbus definitions */
#define bus_write_register(bus, slot, offset, val) \
lamebus_write_register(bus, slot, offset, val)
#define bus_write_register(bus, slot, offset, val) \
lamebus_write_register(bus, slot, offset, val)
#define bus_read_register(bus, slot, offset) \
lamebus_read_register(bus, slot, offset)
#define bus_read_register(bus, slot, offset) \
lamebus_read_register(bus, slot, offset)
#define bus_map_area(bus, slot, offset) \
lamebus_map_area(bus, slot, offset)
#define bus_map_area(bus, slot, offset) lamebus_map_area(bus, slot, offset)
/*
* Machine-dependent LAMEbus definitions
*/
/* Base address of the LAMEbus mapping area */
#define LB_BASEADDR (MIPS_KSEG1 + 0x1fe00000)
#define LB_BASEADDR (MIPS_KSEG1 + 0x1fe00000)
#endif /* _SYS161_BUS_H_ */

View File

@@ -46,26 +46,21 @@
static struct beep_softc *the_beep = NULL;
int
config_beep(struct beep_softc *bs, int unit)
{
/* We use only the first beep device. */
if (unit!=0) {
return ENODEV;
}
int config_beep(struct beep_softc *bs, int unit) {
/* We use only the first beep device. */
if (unit != 0) {
return ENODEV;
}
KASSERT(the_beep==NULL);
the_beep = bs;
return 0;
KASSERT(the_beep == NULL);
the_beep = bs;
return 0;
}
void
beep(void)
{
if (the_beep!=NULL) {
the_beep->bs_beep(the_beep->bs_devdata);
}
else {
kprintf("beep: Warning: no beep device\n");
}
void beep(void) {
if (the_beep != NULL) {
the_beep->bs_beep(the_beep->bs_devdata);
} else {
kprintf("beep: Warning: no beep device\n");
}
}

View File

@@ -36,8 +36,8 @@
*/
struct beep_softc {
void *bs_devdata;
void (*bs_beep)(void *devdata);
void *bs_devdata;
void (*bs_beep)(void *devdata);
};
#endif /* _GENERIC_BEEP_H_ */

View File

@@ -79,32 +79,26 @@ static struct lock *con_userlock_write = NULL;
* console is set up. Upon console setup they are dumped
* to the actual console; thenceforth this space is unused.
*/
#define DELAYBUFSIZE 1024
#define DELAYBUFSIZE 1024
static char delayed_outbuf[DELAYBUFSIZE];
static size_t delayed_outbuf_pos=0;
static size_t delayed_outbuf_pos = 0;
static
void
putch_delayed(int ch)
{
/*
* No synchronization needed: called only during system startup
* by main thread.
*/
static void putch_delayed(int ch) {
/*
* No synchronization needed: called only during system startup
* by main thread.
*/
KASSERT(delayed_outbuf_pos < sizeof(delayed_outbuf));
delayed_outbuf[delayed_outbuf_pos++] = ch;
KASSERT(delayed_outbuf_pos < sizeof(delayed_outbuf));
delayed_outbuf[delayed_outbuf_pos++] = ch;
}
static
void
flush_delay_buf(void)
{
size_t i;
for (i=0; i<delayed_outbuf_pos; i++) {
putch(delayed_outbuf[i]);
}
delayed_outbuf_pos = 0;
static void flush_delay_buf(void) {
size_t i;
for (i = 0; i < delayed_outbuf_pos; i++) {
putch(delayed_outbuf[i]);
}
delayed_outbuf_pos = 0;
}
//////////////////////////////////////////////////
@@ -113,11 +107,8 @@ flush_delay_buf(void)
* Print a character, using polling instead of interrupts to wait for
* I/O completion.
*/
static
void
putch_polled(struct con_softc *cs, int ch)
{
cs->cs_sendpolled(cs->cs_devdata, ch);
static void putch_polled(struct con_softc *cs, int ch) {
cs->cs_sendpolled(cs->cs_devdata, ch);
}
//////////////////////////////////////////////////
@@ -125,28 +116,21 @@ putch_polled(struct con_softc *cs, int ch)
/*
* Print a character, using interrupts to wait for I/O completion.
*/
static
void
putch_intr(struct con_softc *cs, int ch)
{
P(cs->cs_wsem);
cs->cs_send(cs->cs_devdata, ch);
static void putch_intr(struct con_softc *cs, int ch) {
P(cs->cs_wsem);
cs->cs_send(cs->cs_devdata, ch);
}
/*
* Read a character, using interrupts to wait for I/O completion.
*/
static
int
getch_intr(struct con_softc *cs)
{
unsigned char ret;
static int getch_intr(struct con_softc *cs) {
unsigned char ret;
P(cs->cs_rsem);
ret = cs->cs_gotchars[cs->cs_gotchars_tail];
cs->cs_gotchars_tail =
(cs->cs_gotchars_tail + 1) % CONSOLE_INPUT_BUFFER_SIZE;
return ret;
P(cs->cs_rsem);
ret = cs->cs_gotchars[cs->cs_gotchars_tail];
cs->cs_gotchars_tail = (cs->cs_gotchars_tail + 1) % CONSOLE_INPUT_BUFFER_SIZE;
return ret;
}
/*
@@ -158,33 +142,29 @@ getch_intr(struct con_softc *cs)
* too) would be with a second semaphore used with a nonblocking P,
* but we don't have that in OS/161.
*/
void
con_input(void *vcs, int ch)
{
struct con_softc *cs = vcs;
unsigned nexthead;
void con_input(void *vcs, int ch) {
struct con_softc *cs = vcs;
unsigned nexthead;
nexthead = (cs->cs_gotchars_head + 1) % CONSOLE_INPUT_BUFFER_SIZE;
if (nexthead == cs->cs_gotchars_tail) {
/* overflow; drop character */
return;
}
nexthead = (cs->cs_gotchars_head + 1) % CONSOLE_INPUT_BUFFER_SIZE;
if (nexthead == cs->cs_gotchars_tail) {
/* overflow; drop character */
return;
}
cs->cs_gotchars[cs->cs_gotchars_head] = ch;
cs->cs_gotchars_head = nexthead;
cs->cs_gotchars[cs->cs_gotchars_head] = ch;
cs->cs_gotchars_head = nexthead;
V(cs->cs_rsem);
V(cs->cs_rsem);
}
/*
* Called from underlying device when a write-done interrupt occurs.
*/
void
con_start(void *vcs)
{
struct con_softc *cs = vcs;
void con_start(void *vcs) {
struct con_softc *cs = vcs;
V(cs->cs_wsem);
V(cs->cs_wsem);
}
//////////////////////////////////////////////////
@@ -197,32 +177,25 @@ con_start(void *vcs)
* not, and does not.
*/
void
putch(int ch)
{
struct con_softc *cs = the_console;
void putch(int ch) {
struct con_softc *cs = the_console;
if (cs==NULL) {
putch_delayed(ch);
}
else if (curthread->t_in_interrupt ||
curthread->t_curspl > 0 ||
curcpu->c_spinlocks > 0) {
putch_polled(cs, ch);
}
else {
putch_intr(cs, ch);
}
if (cs == NULL) {
putch_delayed(ch);
} else if (curthread->t_in_interrupt || curthread->t_curspl > 0 ||
curcpu->c_spinlocks > 0) {
putch_polled(cs, ch);
} else {
putch_intr(cs, ch);
}
}
int
getch(void)
{
struct con_softc *cs = the_console;
KASSERT(cs != NULL);
KASSERT(!curthread->t_in_interrupt && curthread->t_iplhigh_count == 0);
int getch(void) {
struct con_softc *cs = the_console;
KASSERT(cs != NULL);
KASSERT(!curthread->t_in_interrupt && curthread->t_iplhigh_count == 0);
return getch_intr(cs);
return getch_intr(cs);
}
////////////////////////////////////////////////////////////
@@ -231,107 +204,93 @@ getch(void)
* VFS interface functions
*/
static
int
con_eachopen(struct device *dev, int openflags)
{
(void)dev;
(void)openflags;
return 0;
static int con_eachopen(struct device *dev, int openflags) {
(void)dev;
(void)openflags;
return 0;
}
static
int
con_io(struct device *dev, struct uio *uio)
{
int result;
char ch;
struct lock *lk;
static int con_io(struct device *dev, struct uio *uio) {
int result;
char ch;
struct lock *lk;
(void)dev; // unused
(void)dev; // unused
if (uio->uio_rw==UIO_READ) {
lk = con_userlock_read;
}
else {
lk = con_userlock_write;
}
if (uio->uio_rw == UIO_READ) {
lk = con_userlock_read;
} else {
lk = con_userlock_write;
}
KASSERT(lk != NULL);
lock_acquire(lk);
KASSERT(lk != NULL);
lock_acquire(lk);
while (uio->uio_resid > 0) {
if (uio->uio_rw==UIO_READ) {
ch = getch();
if (ch=='\r') {
ch = '\n';
}
result = uiomove(&ch, 1, uio);
if (result) {
lock_release(lk);
return result;
}
if (ch=='\n') {
break;
}
}
else {
result = uiomove(&ch, 1, uio);
if (result) {
lock_release(lk);
return result;
}
if (ch=='\n') {
putch('\r');
}
putch(ch);
}
}
lock_release(lk);
return 0;
while (uio->uio_resid > 0) {
if (uio->uio_rw == UIO_READ) {
ch = getch();
if (ch == '\r') {
ch = '\n';
}
result = uiomove(&ch, 1, uio);
if (result) {
lock_release(lk);
return result;
}
if (ch == '\n') {
break;
}
} else {
result = uiomove(&ch, 1, uio);
if (result) {
lock_release(lk);
return result;
}
if (ch == '\n') {
putch('\r');
}
putch(ch);
}
}
lock_release(lk);
return 0;
}
static
int
con_ioctl(struct device *dev, int op, userptr_t data)
{
/* No ioctls. */
(void)dev;
(void)op;
(void)data;
return EINVAL;
static int con_ioctl(struct device *dev, int op, userptr_t data) {
/* No ioctls. */
(void)dev;
(void)op;
(void)data;
return EINVAL;
}
static const struct device_ops console_devops = {
.devop_eachopen = con_eachopen,
.devop_io = con_io,
.devop_ioctl = con_ioctl,
.devop_eachopen = con_eachopen,
.devop_io = con_io,
.devop_ioctl = con_ioctl,
};
static
int
attach_console_to_vfs(struct con_softc *cs)
{
struct device *dev;
int result;
static int attach_console_to_vfs(struct con_softc *cs) {
struct device *dev;
int result;
dev = kmalloc(sizeof(*dev));
if (dev==NULL) {
return ENOMEM;
}
dev = kmalloc(sizeof(*dev));
if (dev == NULL) {
return ENOMEM;
}
dev->d_ops = &console_devops;
dev->d_blocks = 0;
dev->d_blocksize = 1;
dev->d_data = cs;
dev->d_ops = &console_devops;
dev->d_blocks = 0;
dev->d_blocksize = 1;
dev->d_data = cs;
result = vfs_adddev("con", dev, 0);
if (result) {
kfree(dev);
return result;
}
result = vfs_adddev("con", dev, 0);
if (result) {
kfree(dev);
return result;
}
return 0;
return 0;
}
////////////////////////////////////////////////////////////
@@ -340,58 +299,56 @@ attach_console_to_vfs(struct con_softc *cs)
* Config routine called by autoconf.c after we are attached to something.
*/
int
config_con(struct con_softc *cs, int unit)
{
struct semaphore *rsem, *wsem;
struct lock *rlk, *wlk;
int config_con(struct con_softc *cs, int unit) {
struct semaphore *rsem, *wsem;
struct lock *rlk, *wlk;
/*
* Only allow one system console.
* Further devices that could be the system console are ignored.
*
* Do not hardwire the console to be "con1" instead of "con0",
* or these asserts will go off.
*/
if (unit>0) {
KASSERT(the_console!=NULL);
return ENODEV;
}
KASSERT(the_console==NULL);
/*
* Only allow one system console.
* Further devices that could be the system console are ignored.
*
* Do not hardwire the console to be "con1" instead of "con0",
* or these asserts will go off.
*/
if (unit > 0) {
KASSERT(the_console != NULL);
return ENODEV;
}
KASSERT(the_console == NULL);
rsem = sem_create("console read", 0);
if (rsem == NULL) {
return ENOMEM;
}
wsem = sem_create("console write", 1);
if (wsem == NULL) {
sem_destroy(rsem);
return ENOMEM;
}
rlk = lock_create("console-lock-read");
if (rlk == NULL) {
sem_destroy(rsem);
sem_destroy(wsem);
return ENOMEM;
}
wlk = lock_create("console-lock-write");
if (wlk == NULL) {
lock_destroy(rlk);
sem_destroy(rsem);
sem_destroy(wsem);
return ENOMEM;
}
rsem = sem_create("console read", 0);
if (rsem == NULL) {
return ENOMEM;
}
wsem = sem_create("console write", 1);
if (wsem == NULL) {
sem_destroy(rsem);
return ENOMEM;
}
rlk = lock_create("console-lock-read");
if (rlk == NULL) {
sem_destroy(rsem);
sem_destroy(wsem);
return ENOMEM;
}
wlk = lock_create("console-lock-write");
if (wlk == NULL) {
lock_destroy(rlk);
sem_destroy(rsem);
sem_destroy(wsem);
return ENOMEM;
}
cs->cs_rsem = rsem;
cs->cs_wsem = wsem;
cs->cs_gotchars_head = 0;
cs->cs_gotchars_tail = 0;
cs->cs_rsem = rsem;
cs->cs_wsem = wsem;
cs->cs_gotchars_head = 0;
cs->cs_gotchars_tail = 0;
the_console = cs;
con_userlock_read = rlk;
con_userlock_write = wlk;
the_console = cs;
con_userlock_read = rlk;
con_userlock_write = wlk;
flush_delay_buf();
flush_delay_buf();
return attach_console_to_vfs(cs);
return attach_console_to_vfs(cs);
}

View File

@@ -40,17 +40,17 @@
#define CONSOLE_INPUT_BUFFER_SIZE 32
struct con_softc {
/* initialized by attach routine */
void *cs_devdata;
void (*cs_send)(void *devdata, int ch);
void (*cs_sendpolled)(void *devdata, int ch);
/* initialized by attach routine */
void *cs_devdata;
void (*cs_send)(void *devdata, int ch);
void (*cs_sendpolled)(void *devdata, int ch);
/* initialized by config routine */
struct semaphore *cs_rsem;
struct semaphore *cs_wsem;
unsigned char cs_gotchars[CONSOLE_INPUT_BUFFER_SIZE];
unsigned cs_gotchars_head; /* next slot to put a char in */
unsigned cs_gotchars_tail; /* next slot to take a char out */
/* initialized by config routine */
struct semaphore *cs_rsem;
struct semaphore *cs_wsem;
unsigned char cs_gotchars[CONSOLE_INPUT_BUFFER_SIZE];
unsigned cs_gotchars_head; /* next slot to put a char in */
unsigned cs_gotchars_tail; /* next slot to take a char out */
};
/*

View File

@@ -53,106 +53,90 @@ static struct random_softc *the_random = NULL;
* VFS device functions.
* open: allow reading only.
*/
static
int
randeachopen(struct device *dev, int openflags)
{
(void)dev;
static int randeachopen(struct device *dev, int openflags) {
(void)dev;
if (openflags != O_RDONLY) {
return EIO;
}
if (openflags != O_RDONLY) {
return EIO;
}
return 0;
return 0;
}
/*
* VFS I/O function. Hand off to implementation.
*/
static
int
randio(struct device *dev, struct uio *uio)
{
struct random_softc *rs = dev->d_data;
static int randio(struct device *dev, struct uio *uio) {
struct random_softc *rs = dev->d_data;
if (uio->uio_rw != UIO_READ) {
return EIO;
}
if (uio->uio_rw != UIO_READ) {
return EIO;
}
return rs->rs_read(rs->rs_devdata, uio);
return rs->rs_read(rs->rs_devdata, uio);
}
/*
* VFS ioctl function.
*/
static
int
randioctl(struct device *dev, int op, userptr_t data)
{
/*
* We don't support any ioctls.
*/
(void)dev;
(void)op;
(void)data;
return EIOCTL;
static int randioctl(struct device *dev, int op, userptr_t data) {
/*
* We don't support any ioctls.
*/
(void)dev;
(void)op;
(void)data;
return EIOCTL;
}
static const struct device_ops random_devops = {
.devop_eachopen = randeachopen,
.devop_io = randio,
.devop_ioctl = randioctl,
.devop_eachopen = randeachopen,
.devop_io = randio,
.devop_ioctl = randioctl,
};
/*
* Config function.
*/
int
config_random(struct random_softc *rs, int unit)
{
int result;
int config_random(struct random_softc *rs, int unit) {
int result;
/* We use only the first random device. */
if (unit!=0) {
return ENODEV;
}
/* We use only the first random device. */
if (unit != 0) {
return ENODEV;
}
KASSERT(the_random==NULL);
the_random = rs;
KASSERT(the_random == NULL);
the_random = rs;
rs->rs_dev.d_ops = &random_devops;
rs->rs_dev.d_blocks = 0;
rs->rs_dev.d_blocksize = 1;
rs->rs_dev.d_data = rs;
rs->rs_dev.d_ops = &random_devops;
rs->rs_dev.d_blocks = 0;
rs->rs_dev.d_blocksize = 1;
rs->rs_dev.d_data = rs;
/* Add the VFS device structure to the VFS device list. */
result = vfs_adddev("random", &rs->rs_dev, 0);
if (result) {
return result;
}
/* Add the VFS device structure to the VFS device list. */
result = vfs_adddev("random", &rs->rs_dev, 0);
if (result) {
return result;
}
return 0;
return 0;
}
/*
* Random number functions exported to the rest of the kernel.
*/
uint32_t
random(void)
{
if (the_random==NULL) {
panic("No random device\n");
}
return the_random->rs_random(the_random->rs_devdata);
uint32_t random(void) {
if (the_random == NULL) {
panic("No random device\n");
}
return the_random->rs_random(the_random->rs_devdata);
}
uint32_t
randmax(void)
{
if (the_random==NULL) {
panic("No random device\n");
}
return the_random->rs_randmax(the_random->rs_devdata);
uint32_t randmax(void) {
if (the_random == NULL) {
panic("No random device\n");
}
return the_random->rs_randmax(the_random->rs_devdata);
}

View File

@@ -34,13 +34,13 @@
struct uio;
struct random_softc {
/* Initialized by lower-level attach routine */
void *rs_devdata;
uint32_t (*rs_random)(void *devdata);
uint32_t (*rs_randmax)(void *devdata);
int (*rs_read)(void *devdata, struct uio *uio);
/* Initialized by lower-level attach routine */
void *rs_devdata;
uint32_t (*rs_random)(void *devdata);
uint32_t (*rs_randmax)(void *devdata);
int (*rs_read)(void *devdata, struct uio *uio);
struct device rs_dev;
struct device rs_dev;
};
#endif /* _GENERIC_RANDOM_H_ */

View File

@@ -49,22 +49,18 @@
static struct rtclock_softc *the_clock = NULL;
int
config_rtclock(struct rtclock_softc *rtc, int unit)
{
/* We use only the first clock device. */
if (unit!=0) {
return ENODEV;
}
int config_rtclock(struct rtclock_softc *rtc, int unit) {
/* We use only the first clock device. */
if (unit != 0) {
return ENODEV;
}
KASSERT(the_clock==NULL);
the_clock = rtc;
return 0;
KASSERT(the_clock == NULL);
the_clock = rtc;
return 0;
}
void
gettime(struct timespec *ts)
{
KASSERT(the_clock!=NULL);
the_clock->rtc_gettime(the_clock->rtc_devdata, ts);
void gettime(struct timespec *ts) {
KASSERT(the_clock != NULL);
the_clock->rtc_gettime(the_clock->rtc_devdata, ts);
}

View File

@@ -38,8 +38,8 @@
struct timespec;
struct rtclock_softc {
void *rtc_devdata;
void (*rtc_gettime)(void *devdata, struct timespec *);
void *rtc_devdata;
void (*rtc_gettime)(void *devdata, struct timespec *);
};
#endif /* _GENERIC_RTCLOCK_H_ */

View File

@@ -38,18 +38,16 @@
#include <lamebus/ltimer.h>
#include "autoconf.h"
struct beep_softc *
attach_beep_to_ltimer(int beepno, struct ltimer_softc *ls)
{
struct beep_softc *bs = kmalloc(sizeof(struct beep_softc));
if (bs==NULL) {
return NULL;
}
struct beep_softc *attach_beep_to_ltimer(int beepno, struct ltimer_softc *ls) {
struct beep_softc *bs = kmalloc(sizeof(struct beep_softc));
if (bs == NULL) {
return NULL;
}
(void)beepno; // unused
(void)beepno; // unused
bs->bs_devdata = ls;
bs->bs_beep = ltimer_beep;
bs->bs_devdata = ls;
bs->bs_beep = ltimer_beep;
return bs;
return bs;
}

View File

@@ -38,22 +38,19 @@
#include <lamebus/lscreen.h>
#include "autoconf.h"
struct con_softc *
attach_con_to_lscreen(int consno, struct lscreen_softc *ls)
{
struct con_softc *cs = kmalloc(sizeof(struct con_softc));
if (cs==NULL) {
return NULL;
}
struct con_softc *attach_con_to_lscreen(int consno, struct lscreen_softc *ls) {
struct con_softc *cs = kmalloc(sizeof(struct con_softc));
if (cs == NULL) {
return NULL;
}
cs->cs_devdata = ls;
cs->cs_send = lscreen_write;
cs->cs_sendpolled = lscreen_write;
cs->cs_devdata = ls;
cs->cs_send = lscreen_write;
cs->cs_sendpolled = lscreen_write;
ls->ls_devdata = cs;
ls->ls_start = con_start;
ls->ls_input = con_input;
ls->ls_devdata = cs;
ls->ls_start = con_start;
ls->ls_input = con_input;
return cs;
return cs;
}

View File

@@ -38,24 +38,21 @@
#include <lamebus/lser.h>
#include "autoconf.h"
struct con_softc *
attach_con_to_lser(int consno, struct lser_softc *ls)
{
struct con_softc *cs = kmalloc(sizeof(struct con_softc));
if (cs==NULL) {
return NULL;
}
struct con_softc *attach_con_to_lser(int consno, struct lser_softc *ls) {
struct con_softc *cs = kmalloc(sizeof(struct con_softc));
if (cs == NULL) {
return NULL;
}
(void)consno; // unused
(void)consno; // unused
cs->cs_devdata = ls;
cs->cs_send = lser_write;
cs->cs_sendpolled = lser_writepolled;
cs->cs_devdata = ls;
cs->cs_send = lser_write;
cs->cs_sendpolled = lser_writepolled;
ls->ls_devdata = cs;
ls->ls_start = con_start;
ls->ls_input = con_input;
ls->ls_devdata = cs;
ls->ls_start = con_start;
ls->ls_input = con_input;
return cs;
return cs;
}

File diff suppressed because it is too large Load Diff

View File

@@ -30,9 +30,8 @@
#ifndef _LAMEBUS_EMU_H_
#define _LAMEBUS_EMU_H_
#define EMU_MAXIO 16384
#define EMU_ROOTHANDLE 0
#define EMU_MAXIO 16384
#define EMU_ROOTHANDLE 0
/*
* The per-device data used by the emufs device driver.
@@ -41,22 +40,21 @@
*/
struct emu_softc {
/* Initialized by lower-level attach code */
void *e_busdata;
uint32_t e_buspos;
int e_unit;
/* Initialized by lower-level attach code */
void *e_busdata;
uint32_t e_buspos;
int e_unit;
/* Initialized by config_emu() */
struct lock *e_lock;
struct semaphore *e_sem;
void *e_iobuf;
/* Initialized by config_emu() */
struct lock *e_lock;
struct semaphore *e_sem;
void *e_iobuf;
/* Written by the interrupt handler */
uint32_t e_result;
/* Written by the interrupt handler */
uint32_t e_result;
};
/* Functions called by lower-level drivers */
void emu_irq(/*struct emu_softc*/ void *);
#endif /* _LAMEBUS_EMU_H_ */

View File

@@ -38,29 +38,27 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 1
#define LOW_VERSION 1
struct emu_softc *
attach_emu_to_lamebus(int emuno, struct lamebus_softc *sc)
{
struct emu_softc *es;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_EMUFS,
LOW_VERSION, NULL);
if (slot < 0) {
return NULL;
}
struct emu_softc *attach_emu_to_lamebus(int emuno, struct lamebus_softc *sc) {
struct emu_softc *es;
int slot =
lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_EMUFS, LOW_VERSION, NULL);
if (slot < 0) {
return NULL;
}
es = kmalloc(sizeof(struct emu_softc));
if (es==NULL) {
return NULL;
}
es = kmalloc(sizeof(struct emu_softc));
if (es == NULL) {
return NULL;
}
es->e_busdata = sc;
es->e_buspos = slot;
es->e_unit = emuno;
es->e_busdata = sc;
es->e_buspos = slot;
es->e_unit = emuno;
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, es, emu_irq);
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, es, emu_irq);
return es;
return es;
}

View File

@@ -40,147 +40,124 @@
#include <lamebus/lamebus.h>
/* Register offsets within each config region */
#define CFGREG_VID 0 /* Vendor ID */
#define CFGREG_DID 4 /* Device ID */
#define CFGREG_DRL 8 /* Device Revision Level */
#define CFGREG_VID 0 /* Vendor ID */
#define CFGREG_DID 4 /* Device ID */
#define CFGREG_DRL 8 /* Device Revision Level */
/* LAMEbus controller private registers (offsets within its config region) */
#define CTLREG_RAMSZ 0x200
#define CTLREG_IRQS 0x204
#define CTLREG_PWR 0x208
#define CTLREG_IRQE 0x20c
#define CTLREG_CPUS 0x210
#define CTLREG_CPUE 0x214
#define CTLREG_SELF 0x218
#define CTLREG_RAMSZ 0x200
#define CTLREG_IRQS 0x204
#define CTLREG_PWR 0x208
#define CTLREG_IRQE 0x20c
#define CTLREG_CPUS 0x210
#define CTLREG_CPUE 0x214
#define CTLREG_SELF 0x218
/* LAMEbus CPU control registers (offsets within each per-cpu region) */
#define CTLCPU_CIRQE 0x000
#define CTLCPU_CIPI 0x004
#define CTLCPU_CRAM 0x300
#define CTLCPU_CIRQE 0x000
#define CTLCPU_CIPI 0x004
#define CTLCPU_CRAM 0x300
/*
* Read a config register for the given slot.
*/
static
inline
uint32_t
read_cfg_register(struct lamebus_softc *lb, int slot, uint32_t offset)
{
/* Note that lb might be NULL on some platforms in some contexts. */
offset += LB_CONFIG_SIZE*slot;
return lamebus_read_register(lb, LB_CONTROLLER_SLOT, offset);
static inline uint32_t read_cfg_register(struct lamebus_softc *lb, int slot,
uint32_t offset) {
/* Note that lb might be NULL on some platforms in some contexts. */
offset += LB_CONFIG_SIZE * slot;
return lamebus_read_register(lb, LB_CONTROLLER_SLOT, offset);
}
/*
* Write a config register for a given slot.
*/
static
inline
void
write_cfg_register(struct lamebus_softc *lb, int slot, uint32_t offset,
uint32_t val)
{
offset += LB_CONFIG_SIZE*slot;
lamebus_write_register(lb, LB_CONTROLLER_SLOT, offset, val);
static inline void write_cfg_register(struct lamebus_softc *lb, int slot,
uint32_t offset, uint32_t val) {
offset += LB_CONFIG_SIZE * slot;
lamebus_write_register(lb, LB_CONTROLLER_SLOT, offset, val);
}
/*
* Read one of the bus controller's registers.
*/
static
inline
uint32_t
read_ctl_register(struct lamebus_softc *lb, uint32_t offset)
{
/* Note that lb might be NULL on some platforms in some contexts. */
return read_cfg_register(lb, LB_CONTROLLER_SLOT, offset);
static inline uint32_t read_ctl_register(struct lamebus_softc *lb,
uint32_t offset) {
/* Note that lb might be NULL on some platforms in some contexts. */
return read_cfg_register(lb, LB_CONTROLLER_SLOT, offset);
}
/*
* Write one of the bus controller's registers.
*/
static
inline
void
write_ctl_register(struct lamebus_softc *lb, uint32_t offset, uint32_t val)
{
write_cfg_register(lb, LB_CONTROLLER_SLOT, offset, val);
static inline void write_ctl_register(struct lamebus_softc *lb, uint32_t offset,
uint32_t val) {
write_cfg_register(lb, LB_CONTROLLER_SLOT, offset, val);
}
/*
* Write one of the bus controller's CPU control registers.
*/
static
inline
void
write_ctlcpu_register(struct lamebus_softc *lb, unsigned hw_cpunum,
uint32_t offset, uint32_t val)
{
offset += LB_CTLCPU_OFFSET + hw_cpunum * LB_CTLCPU_SIZE;
lamebus_write_register(lb, LB_CONTROLLER_SLOT, offset, val);
static inline void write_ctlcpu_register(struct lamebus_softc *lb,
unsigned hw_cpunum, uint32_t offset,
uint32_t val) {
offset += LB_CTLCPU_OFFSET + hw_cpunum * LB_CTLCPU_SIZE;
lamebus_write_register(lb, LB_CONTROLLER_SLOT, offset, val);
}
/*
* Find and create secondary CPUs.
*/
void
lamebus_find_cpus(struct lamebus_softc *lamebus)
{
uint32_t mainboard_vid, mainboard_did;
uint32_t cpumask, self, bit, val;
unsigned i, numcpus, bootcpu;
unsigned hwnum[32];
void lamebus_find_cpus(struct lamebus_softc *lamebus) {
uint32_t mainboard_vid, mainboard_did;
uint32_t cpumask, self, bit, val;
unsigned i, numcpus, bootcpu;
unsigned hwnum[32];
mainboard_vid = read_cfg_register(lamebus, LB_CONTROLLER_SLOT,
CFGREG_VID);
mainboard_did = read_cfg_register(lamebus, LB_CONTROLLER_SLOT,
CFGREG_DID);
if (mainboard_vid == LB_VENDOR_CS161 &&
mainboard_did == LBCS161_UPBUSCTL) {
/* Old uniprocessor mainboard; no cpu registers. */
lamebus->ls_uniprocessor = 1;
return;
}
mainboard_vid = read_cfg_register(lamebus, LB_CONTROLLER_SLOT, CFGREG_VID);
mainboard_did = read_cfg_register(lamebus, LB_CONTROLLER_SLOT, CFGREG_DID);
if (mainboard_vid == LB_VENDOR_CS161 && mainboard_did == LBCS161_UPBUSCTL) {
/* Old uniprocessor mainboard; no cpu registers. */
lamebus->ls_uniprocessor = 1;
return;
}
cpumask = read_ctl_register(lamebus, CTLREG_CPUS);
self = read_ctl_register(lamebus, CTLREG_SELF);
cpumask = read_ctl_register(lamebus, CTLREG_CPUS);
self = read_ctl_register(lamebus, CTLREG_SELF);
numcpus = 0;
bootcpu = 0;
for (i=0; i<32; i++) {
bit = (uint32_t)1 << i;
if ((cpumask & bit) != 0) {
if (self & bit) {
bootcpu = numcpus;
curcpu->c_hardware_number = i;
}
hwnum[numcpus] = i;
numcpus++;
}
}
numcpus = 0;
bootcpu = 0;
for (i = 0; i < 32; i++) {
bit = (uint32_t)1 << i;
if ((cpumask & bit) != 0) {
if (self & bit) {
bootcpu = numcpus;
curcpu->c_hardware_number = i;
}
hwnum[numcpus] = i;
numcpus++;
}
}
for (i=0; i<numcpus; i++) {
if (i != bootcpu) {
cpu_create(hwnum[i]);
}
}
for (i = 0; i < numcpus; i++) {
if (i != bootcpu) {
cpu_create(hwnum[i]);
}
}
/*
* By default, route all interrupts only to the boot cpu. We
* could be arbitrarily more elaborate, up to things like
* dynamic load balancing.
*/
/*
* By default, route all interrupts only to the boot cpu. We
* could be arbitrarily more elaborate, up to things like
* dynamic load balancing.
*/
for (i=0; i<numcpus; i++) {
if (i != bootcpu) {
val = 0;
}
else {
val = 0xffffffff;
}
write_ctlcpu_register(lamebus, hwnum[i], CTLCPU_CIRQE, val);
}
for (i = 0; i < numcpus; i++) {
if (i != bootcpu) {
val = 0;
} else {
val = 0xffffffff;
}
write_ctlcpu_register(lamebus, hwnum[i], CTLCPU_CIRQE, val);
}
}
/*
@@ -193,43 +170,40 @@ lamebus_find_cpus(struct lamebus_softc *lamebus)
* LAMEbus; if in some environment there are other CPUs about as well
* this logic will have to be made more complex.
*/
void
lamebus_start_cpus(struct lamebus_softc *lamebus)
{
uint32_t cpumask, self, bit;
uint32_t ctlcpuoffset;
uint32_t *cram;
unsigned i;
unsigned cpunum;
void lamebus_start_cpus(struct lamebus_softc *lamebus) {
uint32_t cpumask, self, bit;
uint32_t ctlcpuoffset;
uint32_t *cram;
unsigned i;
unsigned cpunum;
if (lamebus->ls_uniprocessor) {
return;
}
if (lamebus->ls_uniprocessor) {
return;
}
cpumask = read_ctl_register(lamebus, CTLREG_CPUS);
self = read_ctl_register(lamebus, CTLREG_SELF);
cpumask = read_ctl_register(lamebus, CTLREG_CPUS);
self = read_ctl_register(lamebus, CTLREG_SELF);
/* Poke in the startup address. */
cpunum = 1;
for (i=0; i<32; i++) {
bit = (uint32_t)1 << i;
if ((cpumask & bit) != 0) {
if (self & bit) {
continue;
}
ctlcpuoffset = LB_CTLCPU_OFFSET + i * LB_CTLCPU_SIZE;
cram = lamebus_map_area(lamebus,
LB_CONTROLLER_SLOT,
ctlcpuoffset + CTLCPU_CRAM);
cram[0] = (uint32_t)cpu_start_secondary;
cram[1] = cpunum++;
}
}
/* Ensure all the above writes get flushed. */
membar_store_store();
/* Poke in the startup address. */
cpunum = 1;
for (i = 0; i < 32; i++) {
bit = (uint32_t)1 << i;
if ((cpumask & bit) != 0) {
if (self & bit) {
continue;
}
ctlcpuoffset = LB_CTLCPU_OFFSET + i * LB_CTLCPU_SIZE;
cram = lamebus_map_area(lamebus, LB_CONTROLLER_SLOT,
ctlcpuoffset + CTLCPU_CRAM);
cram[0] = (uint32_t)cpu_start_secondary;
cram[1] = cpunum++;
}
}
/* Ensure all the above writes get flushed. */
membar_store_store();
/* Now, enable them all. */
write_ctl_register(lamebus, CTLREG_CPUE, cpumask);
/* Now, enable them all. */
write_ctl_register(lamebus, CTLREG_CPUE, cpumask);
}
/*
@@ -247,58 +221,55 @@ lamebus_start_cpus(struct lamebus_softc *lamebus)
* more specific checks.
*/
int
lamebus_probe(struct lamebus_softc *sc,
uint32_t vendorid, uint32_t deviceid,
uint32_t lowver, uint32_t *version_ret)
{
int slot;
uint32_t val;
int lamebus_probe(struct lamebus_softc *sc, uint32_t vendorid,
uint32_t deviceid, uint32_t lowver, uint32_t *version_ret) {
int slot;
uint32_t val;
/*
* Because the slot information in sc is used when dispatching
* interrupts, disable interrupts while working with it.
*/
/*
* Because the slot information in sc is used when dispatching
* interrupts, disable interrupts while working with it.
*/
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
for (slot=0; slot<LB_NSLOTS; slot++) {
if (sc->ls_slotsinuse & (1<<slot)) {
/* Slot already in use; skip */
continue;
}
for (slot = 0; slot < LB_NSLOTS; slot++) {
if (sc->ls_slotsinuse & (1 << slot)) {
/* Slot already in use; skip */
continue;
}
val = read_cfg_register(sc, slot, CFGREG_VID);
if (val!=vendorid) {
/* Wrong vendor id */
continue;
}
val = read_cfg_register(sc, slot, CFGREG_VID);
if (val != vendorid) {
/* Wrong vendor id */
continue;
}
val = read_cfg_register(sc, slot, CFGREG_DID);
if (val != deviceid) {
/* Wrong device id */
continue;
}
val = read_cfg_register(sc, slot, CFGREG_DID);
if (val != deviceid) {
/* Wrong device id */
continue;
}
val = read_cfg_register(sc, slot, CFGREG_DRL);
if (val < lowver) {
/* Unsupported device revision */
continue;
}
if (version_ret != NULL) {
*version_ret = val;
}
val = read_cfg_register(sc, slot, CFGREG_DRL);
if (val < lowver) {
/* Unsupported device revision */
continue;
}
if (version_ret != NULL) {
*version_ret = val;
}
/* Found something */
/* Found something */
spinlock_release(&sc->ls_lock);
return slot;
}
spinlock_release(&sc->ls_lock);
return slot;
}
/* Found nothing */
/* Found nothing */
spinlock_release(&sc->ls_lock);
return -1;
spinlock_release(&sc->ls_lock);
return -1;
}
/*
@@ -306,360 +277,328 @@ lamebus_probe(struct lamebus_softc *sc,
* This prevents the probe routine from returning the same device over
* and over again.
*/
void
lamebus_mark(struct lamebus_softc *sc, int slot)
{
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot>=0 && slot < LB_NSLOTS);
void lamebus_mark(struct lamebus_softc *sc, int slot) {
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
if ((sc->ls_slotsinuse & mask)!=0) {
panic("lamebus_mark: slot %d already in use\n", slot);
}
if ((sc->ls_slotsinuse & mask) != 0) {
panic("lamebus_mark: slot %d already in use\n", slot);
}
sc->ls_slotsinuse |= mask;
sc->ls_slotsinuse |= mask;
spinlock_release(&sc->ls_lock);
spinlock_release(&sc->ls_lock);
}
/*
* Mark that a slot is no longer in use.
*/
void
lamebus_unmark(struct lamebus_softc *sc, int slot)
{
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot>=0 && slot < LB_NSLOTS);
void lamebus_unmark(struct lamebus_softc *sc, int slot) {
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
if ((sc->ls_slotsinuse & mask)==0) {
panic("lamebus_mark: slot %d not marked in use\n", slot);
}
if ((sc->ls_slotsinuse & mask) == 0) {
panic("lamebus_mark: slot %d not marked in use\n", slot);
}
sc->ls_slotsinuse &= ~mask;
sc->ls_slotsinuse &= ~mask;
spinlock_release(&sc->ls_lock);
spinlock_release(&sc->ls_lock);
}
/*
* Register a function (and a device context pointer) to be called
* when a particular slot signals an interrupt.
*/
void
lamebus_attach_interrupt(struct lamebus_softc *sc, int slot,
void *devdata,
void (*irqfunc)(void *devdata))
{
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot>=0 && slot < LB_NSLOTS);
void lamebus_attach_interrupt(struct lamebus_softc *sc, int slot, void *devdata,
void (*irqfunc)(void *devdata)) {
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
if ((sc->ls_slotsinuse & mask)==0) {
panic("lamebus_attach_interrupt: slot %d not marked in use\n",
slot);
}
if ((sc->ls_slotsinuse & mask) == 0) {
panic("lamebus_attach_interrupt: slot %d not marked in use\n", slot);
}
KASSERT(sc->ls_devdata[slot]==NULL);
KASSERT(sc->ls_irqfuncs[slot]==NULL);
KASSERT(sc->ls_devdata[slot] == NULL);
KASSERT(sc->ls_irqfuncs[slot] == NULL);
sc->ls_devdata[slot] = devdata;
sc->ls_irqfuncs[slot] = irqfunc;
sc->ls_devdata[slot] = devdata;
sc->ls_irqfuncs[slot] = irqfunc;
spinlock_release(&sc->ls_lock);
spinlock_release(&sc->ls_lock);
}
/*
* Unregister a function that was being called when a particular slot
* signaled an interrupt.
*/
void
lamebus_detach_interrupt(struct lamebus_softc *sc, int slot)
{
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot>=0 && slot < LB_NSLOTS);
void lamebus_detach_interrupt(struct lamebus_softc *sc, int slot) {
uint32_t mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
if ((sc->ls_slotsinuse & mask)==0) {
panic("lamebus_detach_interrupt: slot %d not marked in use\n",
slot);
}
if ((sc->ls_slotsinuse & mask) == 0) {
panic("lamebus_detach_interrupt: slot %d not marked in use\n", slot);
}
KASSERT(sc->ls_irqfuncs[slot]!=NULL);
KASSERT(sc->ls_irqfuncs[slot] != NULL);
sc->ls_devdata[slot] = NULL;
sc->ls_irqfuncs[slot] = NULL;
sc->ls_devdata[slot] = NULL;
sc->ls_irqfuncs[slot] = NULL;
spinlock_release(&sc->ls_lock);
spinlock_release(&sc->ls_lock);
}
/*
* Mask/unmask an interrupt using the global IRQE register.
*/
void
lamebus_mask_interrupt(struct lamebus_softc *lamebus, int slot)
{
uint32_t bits, mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
void lamebus_mask_interrupt(struct lamebus_softc *lamebus, int slot) {
uint32_t bits, mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
spinlock_acquire(&lamebus->ls_lock);
bits = read_ctl_register(lamebus, CTLREG_IRQE);
bits &= ~mask;
write_ctl_register(lamebus, CTLREG_IRQE, bits);
spinlock_release(&lamebus->ls_lock);
spinlock_acquire(&lamebus->ls_lock);
bits = read_ctl_register(lamebus, CTLREG_IRQE);
bits &= ~mask;
write_ctl_register(lamebus, CTLREG_IRQE, bits);
spinlock_release(&lamebus->ls_lock);
}
void
lamebus_unmask_interrupt(struct lamebus_softc *lamebus, int slot)
{
uint32_t bits, mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
void lamebus_unmask_interrupt(struct lamebus_softc *lamebus, int slot) {
uint32_t bits, mask = ((uint32_t)1) << slot;
KASSERT(slot >= 0 && slot < LB_NSLOTS);
spinlock_acquire(&lamebus->ls_lock);
bits = read_ctl_register(lamebus, CTLREG_IRQE);
bits |= mask;
write_ctl_register(lamebus, CTLREG_IRQE, bits);
spinlock_release(&lamebus->ls_lock);
spinlock_acquire(&lamebus->ls_lock);
bits = read_ctl_register(lamebus, CTLREG_IRQE);
bits |= mask;
write_ctl_register(lamebus, CTLREG_IRQE, bits);
spinlock_release(&lamebus->ls_lock);
}
/*
* LAMEbus interrupt handling function. (Machine-independent!)
*/
void
lamebus_interrupt(struct lamebus_softc *lamebus)
{
/*
* Note that despite the fact that "spl" stands for "set
* priority level", we don't actually support interrupt
* priorities. When an interrupt happens, we look through the
* slots to find the first interrupting device and call its
* interrupt routine, no matter what that device is.
*
* Note that the entire LAMEbus uses only one on-cpu interrupt line.
* Thus, we do not use any on-cpu interrupt priority system either.
*/
void lamebus_interrupt(struct lamebus_softc *lamebus) {
/*
* Note that despite the fact that "spl" stands for "set
* priority level", we don't actually support interrupt
* priorities. When an interrupt happens, we look through the
* slots to find the first interrupting device and call its
* interrupt routine, no matter what that device is.
*
* Note that the entire LAMEbus uses only one on-cpu interrupt line.
* Thus, we do not use any on-cpu interrupt priority system either.
*/
int slot;
uint32_t mask;
uint32_t irqs;
void (*handler)(void *);
void *data;
int slot;
uint32_t mask;
uint32_t irqs;
void (*handler)(void *);
void *data;
/* For keeping track of how many bogus things happen in a row. */
static int duds = 0;
int duds_this_time = 0;
/* For keeping track of how many bogus things happen in a row. */
static int duds = 0;
int duds_this_time = 0;
/* and we better have a valid bus instance. */
KASSERT(lamebus != NULL);
/* and we better have a valid bus instance. */
KASSERT(lamebus != NULL);
/* Lock the softc */
spinlock_acquire(&lamebus->ls_lock);
/* Lock the softc */
spinlock_acquire(&lamebus->ls_lock);
/*
* Read the LAMEbus controller register that tells us which
* slots are asserting an interrupt condition.
*/
irqs = read_ctl_register(lamebus, CTLREG_IRQS);
/*
* Read the LAMEbus controller register that tells us which
* slots are asserting an interrupt condition.
*/
irqs = read_ctl_register(lamebus, CTLREG_IRQS);
if (irqs == 0) {
/*
* Huh? None of them? Must be a glitch.
*/
kprintf("lamebus: stray interrupt on cpu %u\n",
curcpu->c_number);
duds++;
duds_this_time++;
if (irqs == 0) {
/*
* Huh? None of them? Must be a glitch.
*/
kprintf("lamebus: stray interrupt on cpu %u\n", curcpu->c_number);
duds++;
duds_this_time++;
/*
* We could just return now, but instead we'll
* continue ahead. Because irqs == 0, nothing in the
* loop will execute, and passing through it gets us
* to the code that checks how many duds we've
* seen. This is important, because we just might get
* a stray interrupt that latches itself on. If that
* happens, we're pretty much toast, but it's better
* to panic and hopefully reset the system than to
* loop forever printing "stray interrupt".
*/
}
/*
* We could just return now, but instead we'll
* continue ahead. Because irqs == 0, nothing in the
* loop will execute, and passing through it gets us
* to the code that checks how many duds we've
* seen. This is important, because we just might get
* a stray interrupt that latches itself on. If that
* happens, we're pretty much toast, but it's better
* to panic and hopefully reset the system than to
* loop forever printing "stray interrupt".
*/
}
/*
* Go through the bits in the value we got back to see which
* ones are set.
*/
/*
* Go through the bits in the value we got back to see which
* ones are set.
*/
for (mask=1, slot=0; slot<LB_NSLOTS; mask<<=1, slot++) {
if ((irqs & mask) == 0) {
/* Nope. */
continue;
}
for (mask = 1, slot = 0; slot < LB_NSLOTS; mask <<= 1, slot++) {
if ((irqs & mask) == 0) {
/* Nope. */
continue;
}
/*
* This slot is signalling an interrupt.
*/
/*
* This slot is signalling an interrupt.
*/
if ((lamebus->ls_slotsinuse & mask)==0) {
/*
* No device driver is using this slot.
*/
duds++;
duds_this_time++;
continue;
}
if ((lamebus->ls_slotsinuse & mask) == 0) {
/*
* No device driver is using this slot.
*/
duds++;
duds_this_time++;
continue;
}
if (lamebus->ls_irqfuncs[slot]==NULL) {
/*
* The device driver hasn't installed an interrupt
* handler.
*/
duds++;
duds_this_time++;
continue;
}
if (lamebus->ls_irqfuncs[slot] == NULL) {
/*
* The device driver hasn't installed an interrupt
* handler.
*/
duds++;
duds_this_time++;
continue;
}
/*
* Call the interrupt handler. Release the spinlock
* while we do so, in case other CPUs are handling
* interrupts on other devices.
*/
handler = lamebus->ls_irqfuncs[slot];
data = lamebus->ls_devdata[slot];
spinlock_release(&lamebus->ls_lock);
/*
* Call the interrupt handler. Release the spinlock
* while we do so, in case other CPUs are handling
* interrupts on other devices.
*/
handler = lamebus->ls_irqfuncs[slot];
data = lamebus->ls_devdata[slot];
spinlock_release(&lamebus->ls_lock);
handler(data);
handler(data);
spinlock_acquire(&lamebus->ls_lock);
spinlock_acquire(&lamebus->ls_lock);
/*
* Reload the mask of pending IRQs - if we just called
* hardclock, we might not have come back to this
* context for some time, and it might have changed.
*/
/*
* Reload the mask of pending IRQs - if we just called
* hardclock, we might not have come back to this
* context for some time, and it might have changed.
*/
irqs = read_ctl_register(lamebus, CTLREG_IRQS);
}
irqs = read_ctl_register(lamebus, CTLREG_IRQS);
}
/*
* If we get interrupts for a slot with no driver or no
* interrupt handler, it's fairly serious. Because LAMEbus
* uses level-triggered interrupts, if we don't shut off the
* condition, we'll keep getting interrupted continuously and
* the system will make no progress. But we don't know how to
* do that if there's no driver or no interrupt handler.
*
* So, if we get too many dud interrupts, panic, since it's
* better to panic and reset than to hang.
*
* If we get through here without seeing any duds this time,
* the condition, whatever it was, has gone away. It might be
* some stupid device we don't have a driver for, or it might
* have been an electrical transient. In any case, warn and
* clear the dud count.
*/
/*
* If we get interrupts for a slot with no driver or no
* interrupt handler, it's fairly serious. Because LAMEbus
* uses level-triggered interrupts, if we don't shut off the
* condition, we'll keep getting interrupted continuously and
* the system will make no progress. But we don't know how to
* do that if there's no driver or no interrupt handler.
*
* So, if we get too many dud interrupts, panic, since it's
* better to panic and reset than to hang.
*
* If we get through here without seeing any duds this time,
* the condition, whatever it was, has gone away. It might be
* some stupid device we don't have a driver for, or it might
* have been an electrical transient. In any case, warn and
* clear the dud count.
*/
if (duds_this_time == 0 && duds > 0) {
kprintf("lamebus: %d dud interrupts\n", duds);
duds = 0;
}
if (duds_this_time == 0 && duds > 0) {
kprintf("lamebus: %d dud interrupts\n", duds);
duds = 0;
}
if (duds > 10000) {
panic("lamebus: too many (%d) dud interrupts\n", duds);
}
if (duds > 10000) {
panic("lamebus: too many (%d) dud interrupts\n", duds);
}
/* Unlock the softc */
spinlock_release(&lamebus->ls_lock);
/* Unlock the softc */
spinlock_release(&lamebus->ls_lock);
}
/*
* Have the bus controller power the system off.
*/
void
lamebus_poweroff(struct lamebus_softc *lamebus)
{
/*
* Write 0 to the power register to shut the system off.
*/
void lamebus_poweroff(struct lamebus_softc *lamebus) {
/*
* Write 0 to the power register to shut the system off.
*/
cpu_irqoff();
write_ctl_register(lamebus, CTLREG_PWR, 0);
cpu_irqoff();
write_ctl_register(lamebus, CTLREG_PWR, 0);
/* The power doesn't go off instantly... so halt the cpu. */
cpu_halt();
/* The power doesn't go off instantly... so halt the cpu. */
cpu_halt();
}
/*
* Ask the bus controller how much memory we have.
*/
uint32_t
lamebus_ramsize(void)
{
/*
* Note that this has to work before bus initialization.
* On machines where lamebus_read_register doesn't work
* before bus initialization, this function can't be used
* for initial RAM size lookup.
*/
uint32_t lamebus_ramsize(void) {
/*
* Note that this has to work before bus initialization.
* On machines where lamebus_read_register doesn't work
* before bus initialization, this function can't be used
* for initial RAM size lookup.
*/
return read_ctl_register(NULL, CTLREG_RAMSZ);
return read_ctl_register(NULL, CTLREG_RAMSZ);
}
/*
* Turn on or off the interprocessor interrupt line for a given CPU.
*/
void
lamebus_assert_ipi(struct lamebus_softc *lamebus, struct cpu *target)
{
if (lamebus->ls_uniprocessor) {
return;
}
write_ctlcpu_register(lamebus, target->c_hardware_number,
CTLCPU_CIPI, 1);
void lamebus_assert_ipi(struct lamebus_softc *lamebus, struct cpu *target) {
if (lamebus->ls_uniprocessor) {
return;
}
write_ctlcpu_register(lamebus, target->c_hardware_number, CTLCPU_CIPI, 1);
}
void
lamebus_clear_ipi(struct lamebus_softc *lamebus, struct cpu *target)
{
if (lamebus->ls_uniprocessor) {
return;
}
write_ctlcpu_register(lamebus, target->c_hardware_number,
CTLCPU_CIPI, 0);
void lamebus_clear_ipi(struct lamebus_softc *lamebus, struct cpu *target) {
if (lamebus->ls_uniprocessor) {
return;
}
write_ctlcpu_register(lamebus, target->c_hardware_number, CTLCPU_CIPI, 0);
}
/*
* Initial setup.
* Should be called from mainbus_bootstrap().
*/
struct lamebus_softc *
lamebus_init(void)
{
struct lamebus_softc *lamebus;
int i;
struct lamebus_softc *lamebus_init(void) {
struct lamebus_softc *lamebus;
int i;
/* Allocate space for lamebus data */
lamebus = kmalloc(sizeof(struct lamebus_softc));
if (lamebus==NULL) {
panic("lamebus_init: Out of memory\n");
}
/* Allocate space for lamebus data */
lamebus = kmalloc(sizeof(struct lamebus_softc));
if (lamebus == NULL) {
panic("lamebus_init: Out of memory\n");
}
spinlock_init(&lamebus->ls_lock);
spinlock_init(&lamebus->ls_lock);
/*
* Initialize the LAMEbus data structure.
*/
lamebus->ls_slotsinuse = 1 << LB_CONTROLLER_SLOT;
/*
* Initialize the LAMEbus data structure.
*/
lamebus->ls_slotsinuse = 1 << LB_CONTROLLER_SLOT;
for (i=0; i<LB_NSLOTS; i++) {
lamebus->ls_devdata[i] = NULL;
lamebus->ls_irqfuncs[i] = NULL;
}
for (i = 0; i < LB_NSLOTS; i++) {
lamebus->ls_devdata[i] = NULL;
lamebus->ls_irqfuncs[i] = NULL;
}
lamebus->ls_uniprocessor = 0;
lamebus->ls_uniprocessor = 0;
return lamebus;
return lamebus;
}

View File

@@ -39,39 +39,38 @@
* Machine-independent definitions.
*/
/* Vendors */
#define LB_VENDOR_CS161 1
#define LB_VENDOR_CS161 1
/* CS161 devices */
#define LBCS161_UPBUSCTL 1
#define LBCS161_TIMER 2
#define LBCS161_DISK 3
#define LBCS161_SERIAL 4
#define LBCS161_SCREEN 5
#define LBCS161_NET 6
#define LBCS161_EMUFS 7
#define LBCS161_TRACE 8
#define LBCS161_RANDOM 9
#define LBCS161_MPBUSCTL 10
#define LBCS161_UPBUSCTL 1
#define LBCS161_TIMER 2
#define LBCS161_DISK 3
#define LBCS161_SERIAL 4
#define LBCS161_SCREEN 5
#define LBCS161_NET 6
#define LBCS161_EMUFS 7
#define LBCS161_TRACE 8
#define LBCS161_RANDOM 9
#define LBCS161_MPBUSCTL 10
/* LAMEbus controller always goes in slot 31 */
#define LB_CONTROLLER_SLOT 31
#define LB_CONTROLLER_SLOT 31
/* Number of slots */
#define LB_NSLOTS 32
#define LB_NSLOTS 32
/* LAMEbus controller per-slot config space */
#define LB_CONFIG_SIZE 1024
#define LB_CONFIG_SIZE 1024
/* LAMEbus controller per-cpu control space */
#define LB_CTLCPU_SIZE 1024
#define LB_CTLCPU_SIZE 1024
/* LAMEbus controller slot offset to per-cpu control space */
#define LB_CTLCPU_OFFSET 32768
#define LB_CTLCPU_OFFSET 32768
/* LAMEbus mapping size per slot */
#define LB_SLOT_SIZE 65536
#define LB_SLOT_SIZE 65536
/* Pointer to kind of function called on interrupt */
typedef void (*lb_irqfunc)(void *devdata);
@@ -80,15 +79,15 @@ typedef void (*lb_irqfunc)(void *devdata);
* Driver data
*/
struct lamebus_softc {
struct spinlock ls_lock;
struct spinlock ls_lock;
/* Accessed from interrupts; synchronized with ls_lock */
uint32_t ls_slotsinuse;
void *ls_devdata[LB_NSLOTS];
lb_irqfunc ls_irqfuncs[LB_NSLOTS];
/* Accessed from interrupts; synchronized with ls_lock */
uint32_t ls_slotsinuse;
void *ls_devdata[LB_NSLOTS];
lb_irqfunc ls_irqfuncs[LB_NSLOTS];
/* Read-only once set early in boot */
unsigned ls_uniprocessor;
/* Read-only once set early in boot */
unsigned ls_uniprocessor;
};
/*
@@ -113,9 +112,8 @@ void lamebus_start_cpus(struct lamebus_softc *lamebus);
*
* Returns a slot number (0-31) or -1 if no such device is found.
*/
int lamebus_probe(struct lamebus_softc *,
uint32_t vendorid, uint32_t deviceid,
uint32_t lowver, uint32_t *version_ret);
int lamebus_probe(struct lamebus_softc *, uint32_t vendorid, uint32_t deviceid,
uint32_t lowver, uint32_t *version_ret);
/*
* Mark a slot in-use (that is, has a device driver attached to it),
@@ -128,9 +126,8 @@ void lamebus_unmark(struct lamebus_softc *, int slot);
/*
* Attach to an interrupt.
*/
void lamebus_attach_interrupt(struct lamebus_softc *, int slot,
void *devdata,
void (*irqfunc)(void *devdata));
void lamebus_attach_interrupt(struct lamebus_softc *, int slot, void *devdata,
void (*irqfunc)(void *devdata));
/*
* Detach from interrupt.
*/
@@ -168,15 +165,13 @@ void lamebus_clear_ipi(struct lamebus_softc *, struct cpu *targetcpu);
* (Machine dependent.)
*/
uint32_t lamebus_read_register(struct lamebus_softc *, int slot,
uint32_t offset);
void lamebus_write_register(struct lamebus_softc *, int slot,
uint32_t offset, uint32_t val);
uint32_t offset);
void lamebus_write_register(struct lamebus_softc *, int slot, uint32_t offset,
uint32_t val);
/*
* Map a buffer that starts at offset OFFSET within slot SLOT.
*/
void *lamebus_map_area(struct lamebus_softc *, int slot,
uint32_t offset);
void *lamebus_map_area(struct lamebus_softc *, int slot, uint32_t offset);
#endif /* _LAMEBUS_H_ */

View File

@@ -43,68 +43,60 @@
#include "autoconf.h"
/* Registers (offsets within slot) */
#define LHD_REG_NSECT 0 /* Number of sectors */
#define LHD_REG_STAT 4 /* Status */
#define LHD_REG_SECT 8 /* Sector for I/O */
#define LHD_REG_RPM 12 /* Disk rotation speed (revs per minute) */
#define LHD_REG_NSECT 0 /* Number of sectors */
#define LHD_REG_STAT 4 /* Status */
#define LHD_REG_SECT 8 /* Sector for I/O */
#define LHD_REG_RPM 12 /* Disk rotation speed (revs per minute) */
/* Status codes */
#define LHD_IDLE 0 /* Device idle */
#define LHD_WORKING 1 /* Operation in progress */
#define LHD_OK 4 /* Operation succeeded */
#define LHD_INVSECT 12 /* Invalid sector requested */
#define LHD_MEDIA 20 /* Media error */
#define LHD_ISWRITE 2 /* OR with above: I/O is a write */
#define LHD_STATEMASK 0x1d /* mask for masking out LHD_ISWRITE */
#define LHD_IDLE 0 /* Device idle */
#define LHD_WORKING 1 /* Operation in progress */
#define LHD_OK 4 /* Operation succeeded */
#define LHD_INVSECT 12 /* Invalid sector requested */
#define LHD_MEDIA 20 /* Media error */
#define LHD_ISWRITE 2 /* OR with above: I/O is a write */
#define LHD_STATEMASK 0x1d /* mask for masking out LHD_ISWRITE */
/* Buffer (offset within slot) */
#define LHD_BUFFER 32768
#define LHD_BUFFER 32768
/*
* Shortcut for reading a register.
*/
static
inline
uint32_t lhd_rdreg(struct lhd_softc *lh, uint32_t reg)
{
return bus_read_register(lh->lh_busdata, lh->lh_buspos, reg);
static inline uint32_t lhd_rdreg(struct lhd_softc *lh, uint32_t reg) {
return bus_read_register(lh->lh_busdata, lh->lh_buspos, reg);
}
/*
* Shortcut for writing a register.
*/
static
inline
void lhd_wreg(struct lhd_softc *lh, uint32_t reg, uint32_t val)
{
bus_write_register(lh->lh_busdata, lh->lh_buspos, reg, val);
static inline void lhd_wreg(struct lhd_softc *lh, uint32_t reg, uint32_t val) {
bus_write_register(lh->lh_busdata, lh->lh_buspos, reg, val);
}
/*
* Convert a result code from the hardware to an errno value.
*/
static
int lhd_code_to_errno(struct lhd_softc *lh, int code)
{
switch (code & LHD_STATEMASK) {
case LHD_OK: return 0;
case LHD_INVSECT: return EINVAL;
case LHD_MEDIA: return EIO;
}
kprintf("lhd%d: Unknown result code %d\n", lh->lh_unit, code);
return EAGAIN;
static int lhd_code_to_errno(struct lhd_softc *lh, int code) {
switch (code & LHD_STATEMASK) {
case LHD_OK:
return 0;
case LHD_INVSECT:
return EINVAL;
case LHD_MEDIA:
return EIO;
}
kprintf("lhd%d: Unknown result code %d\n", lh->lh_unit, code);
return EAGAIN;
}
/*
* Record that an I/O has completed: save the result and poke the
* completion semaphore.
*/
static
void
lhd_iodone(struct lhd_softc *lh, int err)
{
lh->lh_result = err;
V(lh->lh_done);
static void lhd_iodone(struct lhd_softc *lh, int err) {
lh->lh_result = err;
V(lh->lh_done);
}
/*
@@ -112,57 +104,49 @@ lhd_iodone(struct lhd_softc *lh, int err)
* Read the status register; if an operation finished, clear the status
* register and report completion.
*/
void
lhd_irq(void *vlh)
{
struct lhd_softc *lh = vlh;
uint32_t val;
void lhd_irq(void *vlh) {
struct lhd_softc *lh = vlh;
uint32_t val;
val = lhd_rdreg(lh, LHD_REG_STAT);
val = lhd_rdreg(lh, LHD_REG_STAT);
switch (val & LHD_STATEMASK) {
case LHD_IDLE:
case LHD_WORKING:
break;
case LHD_OK:
case LHD_INVSECT:
case LHD_MEDIA:
lhd_wreg(lh, LHD_REG_STAT, 0);
lhd_iodone(lh, lhd_code_to_errno(lh, val));
break;
}
switch (val & LHD_STATEMASK) {
case LHD_IDLE:
case LHD_WORKING:
break;
case LHD_OK:
case LHD_INVSECT:
case LHD_MEDIA:
lhd_wreg(lh, LHD_REG_STAT, 0);
lhd_iodone(lh, lhd_code_to_errno(lh, val));
break;
}
}
/*
* Function called when we are open()'d.
*/
static
int
lhd_eachopen(struct device *d, int openflags)
{
/*
* Don't need to do anything.
*/
(void)d;
(void)openflags;
static int lhd_eachopen(struct device *d, int openflags) {
/*
* Don't need to do anything.
*/
(void)d;
(void)openflags;
return 0;
return 0;
}
/*
* Function for handling ioctls.
*/
static
int
lhd_ioctl(struct device *d, int op, userptr_t data)
{
/*
* We don't support any ioctls.
*/
(void)d;
(void)op;
(void)data;
return EIOCTL;
static int lhd_ioctl(struct device *d, int op, userptr_t data) {
/*
* We don't support any ioctls.
*/
(void)d;
(void)op;
(void)data;
return EIOCTL;
}
#if 0
@@ -182,127 +166,122 @@ lhd_reset(struct lhd_softc *lh)
/*
* I/O function (for both reads and writes)
*/
static
int
lhd_io(struct device *d, struct uio *uio)
{
struct lhd_softc *lh = d->d_data;
static int lhd_io(struct device *d, struct uio *uio) {
struct lhd_softc *lh = d->d_data;
uint32_t sector = uio->uio_offset / LHD_SECTSIZE;
uint32_t sectoff = uio->uio_offset % LHD_SECTSIZE;
uint32_t len = uio->uio_resid / LHD_SECTSIZE;
uint32_t lenoff = uio->uio_resid % LHD_SECTSIZE;
uint32_t i;
uint32_t statval = LHD_WORKING;
int result;
uint32_t sector = uio->uio_offset / LHD_SECTSIZE;
uint32_t sectoff = uio->uio_offset % LHD_SECTSIZE;
uint32_t len = uio->uio_resid / LHD_SECTSIZE;
uint32_t lenoff = uio->uio_resid % LHD_SECTSIZE;
uint32_t i;
uint32_t statval = LHD_WORKING;
int result;
/* Don't allow I/O that isn't sector-aligned. */
if (sectoff != 0 || lenoff != 0) {
return EINVAL;
}
/* Don't allow I/O that isn't sector-aligned. */
if (sectoff != 0 || lenoff != 0) {
return EINVAL;
}
/* Don't allow I/O past the end of the disk. */
/* XXX this check can overflow */
if (sector+len > lh->lh_dev.d_blocks) {
return EINVAL;
}
/* Don't allow I/O past the end of the disk. */
/* XXX this check can overflow */
if (sector + len > lh->lh_dev.d_blocks) {
return EINVAL;
}
/* Set up the value to write into the status register. */
if (uio->uio_rw==UIO_WRITE) {
statval |= LHD_ISWRITE;
}
/* Set up the value to write into the status register. */
if (uio->uio_rw == UIO_WRITE) {
statval |= LHD_ISWRITE;
}
/* Loop over all the sectors we were asked to do. */
for (i=0; i<len; i++) {
/* Loop over all the sectors we were asked to do. */
for (i = 0; i < len; i++) {
/* Wait until nobody else is using the device. */
P(lh->lh_clear);
/* Wait until nobody else is using the device. */
P(lh->lh_clear);
/*
* Are we writing? If so, transfer the data to the
* on-card buffer.
*/
if (uio->uio_rw == UIO_WRITE) {
result = uiomove(lh->lh_buf, LHD_SECTSIZE, uio);
membar_store_store();
if (result) {
V(lh->lh_clear);
return result;
}
}
/*
* Are we writing? If so, transfer the data to the
* on-card buffer.
*/
if (uio->uio_rw == UIO_WRITE) {
result = uiomove(lh->lh_buf, LHD_SECTSIZE, uio);
membar_store_store();
if (result) {
V(lh->lh_clear);
return result;
}
}
/* Tell it what sector we want... */
lhd_wreg(lh, LHD_REG_SECT, sector+i);
/* Tell it what sector we want... */
lhd_wreg(lh, LHD_REG_SECT, sector + i);
/* and start the operation. */
lhd_wreg(lh, LHD_REG_STAT, statval);
/* and start the operation. */
lhd_wreg(lh, LHD_REG_STAT, statval);
/* Now wait until the interrupt handler tells us we're done. */
P(lh->lh_done);
/* Now wait until the interrupt handler tells us we're done. */
P(lh->lh_done);
/* Get the result value saved by the interrupt handler. */
result = lh->lh_result;
/* Get the result value saved by the interrupt handler. */
result = lh->lh_result;
/*
* Are we reading? If so, and if we succeeded,
* transfer the data out of the on-card buffer.
*/
if (result==0 && uio->uio_rw==UIO_READ) {
membar_load_load();
result = uiomove(lh->lh_buf, LHD_SECTSIZE, uio);
}
/*
* Are we reading? If so, and if we succeeded,
* transfer the data out of the on-card buffer.
*/
if (result == 0 && uio->uio_rw == UIO_READ) {
membar_load_load();
result = uiomove(lh->lh_buf, LHD_SECTSIZE, uio);
}
/* Tell another thread it's cleared to go ahead. */
V(lh->lh_clear);
/* Tell another thread it's cleared to go ahead. */
V(lh->lh_clear);
/* If we failed, return the error. */
if (result) {
return result;
}
}
/* If we failed, return the error. */
if (result) {
return result;
}
}
return 0;
return 0;
}
static const struct device_ops lhd_devops = {
.devop_eachopen = lhd_eachopen,
.devop_io = lhd_io,
.devop_ioctl = lhd_ioctl,
.devop_eachopen = lhd_eachopen,
.devop_io = lhd_io,
.devop_ioctl = lhd_ioctl,
};
/*
* Setup routine called by autoconf.c when an lhd is found.
*/
int
config_lhd(struct lhd_softc *lh, int lhdno)
{
char name[32];
int config_lhd(struct lhd_softc *lh, int lhdno) {
char name[32];
/* Figure out what our name is. */
snprintf(name, sizeof(name), "lhd%d", lhdno);
/* Figure out what our name is. */
snprintf(name, sizeof(name), "lhd%d", lhdno);
/* Get a pointer to the on-chip buffer. */
lh->lh_buf = bus_map_area(lh->lh_busdata, lh->lh_buspos, LHD_BUFFER);
/* Get a pointer to the on-chip buffer. */
lh->lh_buf = bus_map_area(lh->lh_busdata, lh->lh_buspos, LHD_BUFFER);
/* Create the semaphores. */
lh->lh_clear = sem_create("lhd-clear", 1);
if (lh->lh_clear == NULL) {
return ENOMEM;
}
lh->lh_done = sem_create("lhd-done", 0);
if (lh->lh_done == NULL) {
sem_destroy(lh->lh_clear);
lh->lh_clear = NULL;
return ENOMEM;
}
/* Create the semaphores. */
lh->lh_clear = sem_create("lhd-clear", 1);
if (lh->lh_clear == NULL) {
return ENOMEM;
}
lh->lh_done = sem_create("lhd-done", 0);
if (lh->lh_done == NULL) {
sem_destroy(lh->lh_clear);
lh->lh_clear = NULL;
return ENOMEM;
}
/* Set up the VFS device structure. */
lh->lh_dev.d_ops = &lhd_devops;
lh->lh_dev.d_blocks = bus_read_register(lh->lh_busdata, lh->lh_buspos,
LHD_REG_NSECT);
lh->lh_dev.d_blocksize = LHD_SECTSIZE;
lh->lh_dev.d_data = lh;
/* Set up the VFS device structure. */
lh->lh_dev.d_ops = &lhd_devops;
lh->lh_dev.d_blocks =
bus_read_register(lh->lh_busdata, lh->lh_buspos, LHD_REG_NSECT);
lh->lh_dev.d_blocksize = LHD_SECTSIZE;
lh->lh_dev.d_data = lh;
/* Add the VFS device structure to the VFS device list. */
return vfs_adddev(name, &lh->lh_dev, 1);
/* Add the VFS device structure to the VFS device list. */
return vfs_adddev(name, &lh->lh_dev, 1);
}

View File

@@ -35,30 +35,30 @@
/*
* Our sector size
*/
#define LHD_SECTSIZE 512
#define LHD_SECTSIZE 512
/*
* Hardware device data associated with lhd (LAMEbus hard disk)
*/
struct lhd_softc {
/* Initialized by lower-level attach code */
void *lh_busdata; /* The bus we're on */
uint32_t lh_buspos; /* Our slot on that bus */
int lh_unit; /* What number lhd we are */
/* Initialized by lower-level attach code */
void *lh_busdata; /* The bus we're on */
uint32_t lh_buspos; /* Our slot on that bus */
int lh_unit; /* What number lhd we are */
/*
* Initialized by config_lhd
*/
/*
* Initialized by config_lhd
*/
void *lh_buf; /* Pointer to on-card I/O buffer */
int lh_result; /* Result from I/O operation */
struct semaphore *lh_clear; /* Synchronization */
struct semaphore *lh_done;
void *lh_buf; /* Pointer to on-card I/O buffer */
int lh_result; /* Result from I/O operation */
struct semaphore *lh_clear; /* Synchronization */
struct semaphore *lh_done;
struct device lh_dev; /* VFS device structure */
struct device lh_dev; /* VFS device structure */
};
/* Functions called by lower-level drivers */
void lhd_irq(/*struct lhd_softc*/ void *); /* Interrupt handler */
void lhd_irq(/*struct lhd_softc*/ void *); /* Interrupt handler */
#endif /* _LAMEBUS_LHD_H_ */

View File

@@ -37,33 +37,31 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 2
#define LOW_VERSION 2
struct lhd_softc *
attach_lhd_to_lamebus(int lhdno, struct lamebus_softc *sc)
{
struct lhd_softc *lh;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_DISK,
LOW_VERSION, NULL);
if (slot < 0) {
/* None found */
return NULL;
}
struct lhd_softc *attach_lhd_to_lamebus(int lhdno, struct lamebus_softc *sc) {
struct lhd_softc *lh;
int slot =
lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_DISK, LOW_VERSION, NULL);
if (slot < 0) {
/* None found */
return NULL;
}
lh = kmalloc(sizeof(struct lhd_softc));
if (lh==NULL) {
/* Out of memory */
return NULL;
}
lh = kmalloc(sizeof(struct lhd_softc));
if (lh == NULL) {
/* Out of memory */
return NULL;
}
/* Record what the lhd is attached to */
lh->lh_busdata = sc;
lh->lh_buspos = slot;
lh->lh_unit = lhdno;
/* Record what the lhd is attached to */
lh->lh_busdata = sc;
lh->lh_buspos = slot;
lh->lh_unit = lhdno;
/* Mark the slot in use and collect interrupts */
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, lh, lhd_irq);
/* Mark the slot in use and collect interrupts */
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, lh, lhd_irq);
return lh;
return lh;
}

View File

@@ -33,14 +33,10 @@
/*#include <lamebus/lnet.h>*/ /* not yet */
#include "autoconf.h"
int
config_lnet(struct lnet_softc *sc, int lnetno)
{
(void)sc;
int config_lnet(struct lnet_softc *sc, int lnetno) {
(void)sc;
kprintf("lnet%d: No network support in system\n", lnetno);
kprintf("lnet%d: No network support in system\n", lnetno);
return ENODEV;
return ENODEV;
}

View File

@@ -33,20 +33,19 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 1
#define LOW_VERSION 1
/* Highest revision we support */
#define HIGH_VERSION 1
#define HIGH_VERSION 1
struct lnet_softc *
attach_lnet_to_lamebus(int lnetno, struct lamebus_softc *sc)
{
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_NET,
LOW_VERSION, HIGH_VERSION);
if (slot < 0) {
return NULL;
}
struct lnet_softc *attach_lnet_to_lamebus(int lnetno,
struct lamebus_softc *sc) {
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_NET, LOW_VERSION,
HIGH_VERSION);
if (slot < 0) {
return NULL;
}
kprintf("lnet%d: No network support in system\n", lnetno);
kprintf("lnet%d: No network support in system\n", lnetno);
return NULL;
return NULL;
}

View File

@@ -38,48 +38,39 @@
#include "autoconf.h"
/* Registers (offsets within slot) */
#define LR_REG_RAND 0 /* random register */
#define LR_REG_RAND 0 /* random register */
/* Constants */
#define LR_RANDMAX 0xffffffff
#define LR_RANDMAX 0xffffffff
int
config_lrandom(struct lrandom_softc *lr, int lrandomno)
{
(void)lrandomno;
(void)lr;
return 0;
int config_lrandom(struct lrandom_softc *lr, int lrandomno) {
(void)lrandomno;
(void)lr;
return 0;
}
uint32_t
lrandom_random(void *devdata)
{
struct lrandom_softc *lr = devdata;
return bus_read_register(lr->lr_bus, lr->lr_buspos, LR_REG_RAND);
uint32_t lrandom_random(void *devdata) {
struct lrandom_softc *lr = devdata;
return bus_read_register(lr->lr_bus, lr->lr_buspos, LR_REG_RAND);
}
uint32_t
lrandom_randmax(void *devdata)
{
(void)devdata;
return LR_RANDMAX;
uint32_t lrandom_randmax(void *devdata) {
(void)devdata;
return LR_RANDMAX;
}
int
lrandom_read(void *devdata, struct uio *uio)
{
struct lrandom_softc *lr = devdata;
uint32_t val;
int result;
int lrandom_read(void *devdata, struct uio *uio) {
struct lrandom_softc *lr = devdata;
uint32_t val;
int result;
while (uio->uio_resid > 0) {
val = bus_read_register(lr->lr_bus, lr->lr_buspos,
LR_REG_RAND);
result = uiomove(&val, sizeof(val), uio);
if (result) {
return result;
}
}
while (uio->uio_resid > 0) {
val = bus_read_register(lr->lr_bus, lr->lr_buspos, LR_REG_RAND);
result = uiomove(&val, sizeof(val), uio);
if (result) {
return result;
}
}
return 0;
return 0;
}

View File

@@ -33,9 +33,9 @@
struct uio;
struct lrandom_softc {
/* Initialized by lower-level attach routine */
void *lr_bus;
uint32_t lr_buspos;
/* Initialized by lower-level attach routine */
void *lr_bus;
uint32_t lr_buspos;
};
/* Functions called by higher-level drivers */

View File

@@ -34,29 +34,28 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 1
#define LOW_VERSION 1
struct lrandom_softc *
attach_lrandom_to_lamebus(int lrandomno, struct lamebus_softc *sc)
{
struct lrandom_softc *lr;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_RANDOM,
LOW_VERSION, NULL);
if (slot < 0) {
return NULL;
}
struct lrandom_softc *attach_lrandom_to_lamebus(int lrandomno,
struct lamebus_softc *sc) {
struct lrandom_softc *lr;
int slot =
lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_RANDOM, LOW_VERSION, NULL);
if (slot < 0) {
return NULL;
}
lr = kmalloc(sizeof(struct lrandom_softc));
if (lr==NULL) {
return NULL;
}
lr = kmalloc(sizeof(struct lrandom_softc));
if (lr == NULL) {
return NULL;
}
(void)lrandomno; // unused
(void)lrandomno; // unused
lr->lr_bus = sc;
lr->lr_buspos = slot;
lr->lr_bus = sc;
lr->lr_buspos = slot;
lamebus_mark(sc, slot);
lamebus_mark(sc, slot);
return lr;
return lr;
}

View File

@@ -41,37 +41,29 @@
#include "autoconf.h"
/* Registers (offsets within slot) */
#define LSCR_REG_POSN 0 /* Cursor position */
#define LSCR_REG_SIZE 4 /* Display size */
#define LSCR_REG_CHAR 8 /* Character in */
#define LSCR_REG_RIRQ 12 /* Read interrupt status */
#define LSCR_REG_POSN 0 /* Cursor position */
#define LSCR_REG_SIZE 4 /* Display size */
#define LSCR_REG_CHAR 8 /* Character in */
#define LSCR_REG_RIRQ 12 /* Read interrupt status */
/* Bits in the IRQ registers */
#define LSCR_IRQ_ENABLE 1
#define LSCR_IRQ_ACTIVE 2
#define LSCR_IRQ_ENABLE 1
#define LSCR_IRQ_ACTIVE 2
/* Offset within slot of screen buffer */
#define LSCR_SCREEN 32768
#define LSCR_SCREEN 32768
/* Convert a 32-bit X/Y pair to X and Y coordinates. */
static
inline
void
splitxy(uint32_t xy, unsigned *x, unsigned *y)
{
*x = xy >> 16;
*y = xy & 0xffff;
static inline void splitxy(uint32_t xy, unsigned *x, unsigned *y) {
*x = xy >> 16;
*y = xy & 0xffff;
}
/* Convert X and Y coordinates to a single 32-bit value. */
static
inline
uint32_t
mergexy(unsigned x, unsigned y)
{
uint32_t val = x;
static inline uint32_t mergexy(unsigned x, unsigned y) {
uint32_t val = x;
return (val << 16) | y;
return (val << 16) | y;
}
////////////////////////////////////////////////////////////
@@ -79,29 +71,25 @@ mergexy(unsigned x, unsigned y)
/*
* Interrupt handler.
*/
void
lscreen_irq(void *vsc)
{
struct lscreen_softc *sc = vsc;
uint32_t ch, x;
void lscreen_irq(void *vsc) {
struct lscreen_softc *sc = vsc;
uint32_t ch, x;
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_RIRQ);
if (x & LSCR_IRQ_ACTIVE) {
ch = bus_read_register(sc->ls_busdata, sc->ls_buspos,
LSCR_REG_CHAR);
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSCR_REG_RIRQ, LSCR_IRQ_ENABLE);
x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_RIRQ);
if (x & LSCR_IRQ_ACTIVE) {
ch = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_CHAR);
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_RIRQ,
LSCR_IRQ_ENABLE);
spinlock_release(&sc->ls_lock);
if (sc->ls_input) {
sc->ls_input(sc->ls_devdata, ch);
}
}
else {
spinlock_release(&sc->ls_lock);
}
spinlock_release(&sc->ls_lock);
if (sc->ls_input) {
sc->ls_input(sc->ls_devdata, ch);
}
} else {
spinlock_release(&sc->ls_lock);
}
}
////////////////////////////////////////////////////////////
@@ -109,74 +97,68 @@ lscreen_irq(void *vsc)
/*
* Handle a newline on the screen.
*/
static
void
lscreen_newline(struct lscreen_softc *sc)
{
if (sc->ls_cy >= sc->ls_height-1) {
/*
* Scroll
*/
static void lscreen_newline(struct lscreen_softc *sc) {
if (sc->ls_cy >= sc->ls_height - 1) {
/*
* Scroll
*/
memmove(sc->ls_screen, sc->ls_screen + sc->ls_width,
sc->ls_width * (sc->ls_height-1));
bzero(sc->ls_screen + sc->ls_width * (sc->ls_height-1),
sc->ls_width);
}
else {
sc->ls_cy++;
}
sc->ls_cx=0;
memmove(sc->ls_screen, sc->ls_screen + sc->ls_width,
sc->ls_width * (sc->ls_height - 1));
bzero(sc->ls_screen + sc->ls_width * (sc->ls_height - 1), sc->ls_width);
} else {
sc->ls_cy++;
}
sc->ls_cx = 0;
}
/*
* Handle a printable character being written to the screen.
*/
static
void
lscreen_char(struct lscreen_softc *sc, int ch)
{
if (sc->ls_cx >= sc->ls_width) {
lscreen_newline(sc);
}
static void lscreen_char(struct lscreen_softc *sc, int ch) {
if (sc->ls_cx >= sc->ls_width) {
lscreen_newline(sc);
}
sc->ls_screen[sc->ls_cy*sc->ls_width + sc->ls_cx] = ch;
sc->ls_cx++;
sc->ls_screen[sc->ls_cy * sc->ls_width + sc->ls_cx] = ch;
sc->ls_cx++;
}
/*
* Send a character to the screen.
* This should probably know about backspace and tab.
*/
void
lscreen_write(void *vsc, int ch)
{
struct lscreen_softc *sc = vsc;
int ccx, ccy;
void lscreen_write(void *vsc, int ch) {
struct lscreen_softc *sc = vsc;
int ccx, ccy;
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
switch (ch) {
case '\n': lscreen_newline(sc); break;
default: lscreen_char(sc, ch); break;
}
switch (ch) {
case '\n':
lscreen_newline(sc);
break;
default:
lscreen_char(sc, ch);
break;
}
/*
* ccx/ccy = corrected cursor position
* (The cursor marks the next space text will appear in. But
* at the very end of the line, it should not move off the edge.)
*/
ccx = sc->ls_cx;
ccy = sc->ls_cy;
if (ccx==sc->ls_width) {
ccx--;
}
/*
* ccx/ccy = corrected cursor position
* (The cursor marks the next space text will appear in. But
* at the very end of the line, it should not move off the edge.)
*/
ccx = sc->ls_cx;
ccy = sc->ls_cy;
if (ccx == sc->ls_width) {
ccx--;
}
/* Set the cursor position */
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSCR_REG_POSN, mergexy(ccx, ccy));
/* Set the cursor position */
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_POSN,
mergexy(ccx, ccy));
spinlock_release(&sc->ls_lock);
spinlock_release(&sc->ls_lock);
}
////////////////////////////////////////////////////////////
@@ -184,42 +166,36 @@ lscreen_write(void *vsc, int ch)
/*
* Setup routine called by autoconf.c when an lscreen is found.
*/
int
config_lscreen(struct lscreen_softc *sc, int lscreenno)
{
uint32_t val;
int config_lscreen(struct lscreen_softc *sc, int lscreenno) {
uint32_t val;
(void)lscreenno;
(void)lscreenno;
spinlock_init(&sc->ls_lock);
spinlock_init(&sc->ls_lock);
/*
* Enable interrupting.
*/
/*
* Enable interrupting.
*/
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSCR_REG_RIRQ, LSCR_IRQ_ENABLE);
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_RIRQ,
LSCR_IRQ_ENABLE);
/*
* Get screen size.
*/
val = bus_read_register(sc->ls_busdata, sc->ls_buspos,
LSCR_REG_SIZE);
splitxy(val, &sc->ls_width, &sc->ls_height);
/*
* Get screen size.
*/
val = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_SIZE);
splitxy(val, &sc->ls_width, &sc->ls_height);
/*
* Get cursor position.
*/
val = bus_read_register(sc->ls_busdata, sc->ls_buspos,
LSCR_REG_POSN);
splitxy(val, &sc->ls_cx, &sc->ls_cy);
/*
* Get cursor position.
*/
val = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSCR_REG_POSN);
splitxy(val, &sc->ls_cx, &sc->ls_cy);
/*
* Get a pointer to the memory-mapped screen area.
*/
sc->ls_screen = bus_map_area(sc->ls_busdata, sc->ls_buspos,
LSCR_SCREEN);
/*
* Get a pointer to the memory-mapped screen area.
*/
sc->ls_screen = bus_map_area(sc->ls_busdata, sc->ls_buspos, LSCR_SCREEN);
return 0;
return 0;
}

View File

@@ -34,24 +34,24 @@
* Hardware device data for memory-mapped fullscreen text console.
*/
struct lscreen_softc {
/* Initialized by config function */
struct spinlock ls_lock; // protects data and device regs
unsigned ls_width, ls_height; // screen size
unsigned ls_cx, ls_cy; // cursor position
char *ls_screen; // memory-mapped screen buffer
/* Initialized by config function */
struct spinlock ls_lock; // protects data and device regs
unsigned ls_width, ls_height; // screen size
unsigned ls_cx, ls_cy; // cursor position
char *ls_screen; // memory-mapped screen buffer
/* Initialized by lower-level attachment function */
void *ls_busdata; // bus we're on
uint32_t ls_buspos; // position on that bus
/* Initialized by lower-level attachment function */
void *ls_busdata; // bus we're on
uint32_t ls_buspos; // position on that bus
/* Initialized by higher-level attachment function */
void *ls_devdata; // data and functions for
void (*ls_start)(void *devdata); // upper device (perhaps
void (*ls_input)(void *devdata, int ch); // console)
/* Initialized by higher-level attachment function */
void *ls_devdata; // data and functions for
void (*ls_start)(void *devdata); // upper device (perhaps
void (*ls_input)(void *devdata, int ch); // console)
};
/* Functions called by lower-level drivers */
void lscreen_irq(/*struct lser_softc*/ void *sc); // interrupt handler
void lscreen_irq(/*struct lser_softc*/ void *sc); // interrupt handler
/* Functions called by higher-level drivers */
void lscreen_write(/*struct lser_softc*/ void *sc, int ch); // output function

View File

@@ -37,34 +37,33 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 1
#define LOW_VERSION 1
/* Highest revision we support */
#define HIGH_VERSION 1
#define HIGH_VERSION 1
struct lscreen_softc *
attach_lscreen_to_lamebus(int lscreenno, struct lamebus_softc *sc)
{
struct lscreen_softc *ls;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_SCREEN,
LOW_VERSION, HIGH_VERSION);
if (slot < 0) {
/* Not found */
return NULL;
}
struct lscreen_softc *attach_lscreen_to_lamebus(int lscreenno,
struct lamebus_softc *sc) {
struct lscreen_softc *ls;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_SCREEN, LOW_VERSION,
HIGH_VERSION);
if (slot < 0) {
/* Not found */
return NULL;
}
ls = kmalloc(sizeof(struct lscreen_softc));
if (ls==NULL) {
/* Out of memory */
return NULL;
}
ls = kmalloc(sizeof(struct lscreen_softc));
if (ls == NULL) {
/* Out of memory */
return NULL;
}
/* Record what it's attached to */
ls->ls_busdata = sc;
ls->ls_buspos = slot;
/* Record what it's attached to */
ls->ls_busdata = sc;
ls->ls_buspos = slot;
/* Mark the slot in use and hook the interrupt */
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, ls, lscreen_irq);
/* Mark the slot in use and hook the interrupt */
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, ls, lscreen_irq);
return ls;
return ls;
}

View File

@@ -35,158 +35,139 @@
#include "autoconf.h"
/* Registers (offsets within slot) */
#define LSER_REG_CHAR 0 /* Character in/out */
#define LSER_REG_WIRQ 4 /* Write interrupt status */
#define LSER_REG_RIRQ 8 /* Read interrupt status */
#define LSER_REG_CHAR 0 /* Character in/out */
#define LSER_REG_WIRQ 4 /* Write interrupt status */
#define LSER_REG_RIRQ 8 /* Read interrupt status */
/* Bits in the IRQ registers */
#define LSER_IRQ_ENABLE 1
#define LSER_IRQ_ACTIVE 2
#define LSER_IRQ_FORCE 4
#define LSER_IRQ_ENABLE 1
#define LSER_IRQ_ACTIVE 2
#define LSER_IRQ_FORCE 4
void
lser_irq(void *vsc)
{
struct lser_softc *sc = vsc;
uint32_t x;
bool clear_to_write = false;
bool got_a_read = false;
uint32_t ch = 0;
void lser_irq(void *vsc) {
struct lser_softc *sc = vsc;
uint32_t x;
bool clear_to_write = false;
bool got_a_read = false;
uint32_t ch = 0;
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ);
if (x & LSER_IRQ_ACTIVE) {
x = LSER_IRQ_ENABLE;
sc->ls_wbusy = 0;
clear_to_write = true;
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_WIRQ, x);
}
x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ);
if (x & LSER_IRQ_ACTIVE) {
x = LSER_IRQ_ENABLE;
sc->ls_wbusy = 0;
clear_to_write = true;
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ, x);
}
x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_RIRQ);
if (x & LSER_IRQ_ACTIVE) {
x = LSER_IRQ_ENABLE;
ch = bus_read_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_CHAR);
got_a_read = true;
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_RIRQ, x);
}
x = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_RIRQ);
if (x & LSER_IRQ_ACTIVE) {
x = LSER_IRQ_ENABLE;
ch = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_CHAR);
got_a_read = true;
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_RIRQ, x);
}
spinlock_release(&sc->ls_lock);
spinlock_release(&sc->ls_lock);
if (clear_to_write && sc->ls_start != NULL) {
sc->ls_start(sc->ls_devdata);
}
if (got_a_read && sc->ls_input != NULL) {
sc->ls_input(sc->ls_devdata, ch);
}
if (clear_to_write && sc->ls_start != NULL) {
sc->ls_start(sc->ls_devdata);
}
if (got_a_read && sc->ls_input != NULL) {
sc->ls_input(sc->ls_devdata, ch);
}
}
void
lser_write(void *vls, int ch)
{
struct lser_softc *ls = vls;
void lser_write(void *vls, int ch) {
struct lser_softc *ls = vls;
spinlock_acquire(&ls->ls_lock);
spinlock_acquire(&ls->ls_lock);
if (ls->ls_wbusy) {
/*
* We're not clear to write.
*
* This should not happen. It's the job of the driver
* attached to us to not write until we call
* ls->ls_start.
*
* (Note: if we're the console, the panic will go to
* lser_writepolled for printing, because we hold a
* spinlock and interrupts are off; it won't recurse.)
*/
panic("lser: Not clear to write\n");
}
ls->ls_wbusy = true;
if (ls->ls_wbusy) {
/*
* We're not clear to write.
*
* This should not happen. It's the job of the driver
* attached to us to not write until we call
* ls->ls_start.
*
* (Note: if we're the console, the panic will go to
* lser_writepolled for printing, because we hold a
* spinlock and interrupts are off; it won't recurse.)
*/
panic("lser: Not clear to write\n");
}
ls->ls_wbusy = true;
bus_write_register(ls->ls_busdata, ls->ls_buspos, LSER_REG_CHAR, ch);
bus_write_register(ls->ls_busdata, ls->ls_buspos, LSER_REG_CHAR, ch);
spinlock_release(&ls->ls_lock);
spinlock_release(&ls->ls_lock);
}
static
void
lser_poll_until_write(struct lser_softc *sc)
{
uint32_t val;
static void lser_poll_until_write(struct lser_softc *sc) {
uint32_t val;
KASSERT(spinlock_do_i_hold(&sc->ls_lock));
KASSERT(spinlock_do_i_hold(&sc->ls_lock));
do {
val = bus_read_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_WIRQ);
}
while ((val & LSER_IRQ_ACTIVE) == 0);
do {
val = bus_read_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ);
} while ((val & LSER_IRQ_ACTIVE) == 0);
}
void
lser_writepolled(void *vsc, int ch)
{
struct lser_softc *sc = vsc;
bool irqpending;
void lser_writepolled(void *vsc, int ch) {
struct lser_softc *sc = vsc;
bool irqpending;
spinlock_acquire(&sc->ls_lock);
spinlock_acquire(&sc->ls_lock);
if (sc->ls_wbusy) {
irqpending = true;
lser_poll_until_write(sc);
/* Clear the ready condition, but leave the IRQ asserted */
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_WIRQ,
LSER_IRQ_FORCE|LSER_IRQ_ENABLE);
}
else {
irqpending = false;
/* Clear the interrupt enable bit */
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_WIRQ, 0);
}
if (sc->ls_wbusy) {
irqpending = true;
lser_poll_until_write(sc);
/* Clear the ready condition, but leave the IRQ asserted */
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ,
LSER_IRQ_FORCE | LSER_IRQ_ENABLE);
} else {
irqpending = false;
/* Clear the interrupt enable bit */
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ, 0);
}
/* Send the character. */
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_CHAR, ch);
/* Send the character. */
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_CHAR, ch);
/* Wait until it's done. */
lser_poll_until_write(sc);
/* Wait until it's done. */
lser_poll_until_write(sc);
/*
* If there wasn't already an IRQ pending, clear the ready
* condition and turn interruption back on. But if there was,
* leave the register alone, with the ready condition set (and
* the force bit still on); in due course we'll get to the
* interrupt handler and they'll be cleared.
*/
if (!irqpending) {
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_WIRQ, LSER_IRQ_ENABLE);
}
/*
* If there wasn't already an IRQ pending, clear the ready
* condition and turn interruption back on. But if there was,
* leave the register alone, with the ready condition set (and
* the force bit still on); in due course we'll get to the
* interrupt handler and they'll be cleared.
*/
if (!irqpending) {
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ,
LSER_IRQ_ENABLE);
}
spinlock_release(&sc->ls_lock);
spinlock_release(&sc->ls_lock);
}
int
config_lser(struct lser_softc *sc, int lserno)
{
(void)lserno;
int config_lser(struct lser_softc *sc, int lserno) {
(void)lserno;
/*
* Enable interrupting.
*/
/*
* Enable interrupting.
*/
spinlock_init(&sc->ls_lock);
sc->ls_wbusy = false;
spinlock_init(&sc->ls_lock);
sc->ls_wbusy = false;
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_RIRQ, LSER_IRQ_ENABLE);
bus_write_register(sc->ls_busdata, sc->ls_buspos,
LSER_REG_WIRQ, LSER_IRQ_ENABLE);
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_RIRQ,
LSER_IRQ_ENABLE);
bus_write_register(sc->ls_busdata, sc->ls_buspos, LSER_REG_WIRQ,
LSER_IRQ_ENABLE);
return 0;
return 0;
}

View File

@@ -33,18 +33,18 @@
#include <spinlock.h>
struct lser_softc {
/* Initialized by config function */
struct spinlock ls_lock; /* protects ls_wbusy and device regs */
volatile bool ls_wbusy; /* true if write in progress */
/* Initialized by config function */
struct spinlock ls_lock; /* protects ls_wbusy and device regs */
volatile bool ls_wbusy; /* true if write in progress */
/* Initialized by lower-level attachment function */
void *ls_busdata;
uint32_t ls_buspos;
/* Initialized by lower-level attachment function */
void *ls_busdata;
uint32_t ls_buspos;
/* Initialized by higher-level attachment function */
void *ls_devdata;
void (*ls_start)(void *devdata);
void (*ls_input)(void *devdata, int ch);
/* Initialized by higher-level attachment function */
void *ls_devdata;
void (*ls_start)(void *devdata);
void (*ls_input)(void *devdata, int ch);
};
/* Functions called by lower-level drivers */

View File

@@ -34,30 +34,29 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 1
#define LOW_VERSION 1
struct lser_softc *
attach_lser_to_lamebus(int lserno, struct lamebus_softc *sc)
{
struct lser_softc *ls;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_SERIAL,
LOW_VERSION, NULL);
if (slot < 0) {
return NULL;
}
struct lser_softc *attach_lser_to_lamebus(int lserno,
struct lamebus_softc *sc) {
struct lser_softc *ls;
int slot =
lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_SERIAL, LOW_VERSION, NULL);
if (slot < 0) {
return NULL;
}
ls = kmalloc(sizeof(struct lser_softc));
if (ls==NULL) {
return NULL;
}
ls = kmalloc(sizeof(struct lser_softc));
if (ls == NULL) {
return NULL;
}
(void)lserno; // unused
(void)lserno; // unused
ls->ls_busdata = sc;
ls->ls_buspos = slot;
ls->ls_busdata = sc;
ls->ls_buspos = slot;
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, ls, lser_irq);
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, ls, lser_irq);
return ls;
return ls;
}

View File

@@ -39,92 +39,87 @@
#include "autoconf.h"
/* Registers (offsets within slot) */
#define LT_REG_SEC 0 /* time of day: seconds */
#define LT_REG_NSEC 4 /* time of day: nanoseconds */
#define LT_REG_ROE 8 /* Restart On countdown-timer Expiry flag */
#define LT_REG_IRQ 12 /* Interrupt status register */
#define LT_REG_COUNT 16 /* Time for countdown timer (usec) */
#define LT_REG_SPKR 20 /* Beep control */
#define LT_REG_SEC 0 /* time of day: seconds */
#define LT_REG_NSEC 4 /* time of day: nanoseconds */
#define LT_REG_ROE 8 /* Restart On countdown-timer Expiry flag */
#define LT_REG_IRQ 12 /* Interrupt status register */
#define LT_REG_COUNT 16 /* Time for countdown timer (usec) */
#define LT_REG_SPKR 20 /* Beep control */
/* Granularity of countdown timer (usec) */
#define LT_GRANULARITY 1000000
#define LT_GRANULARITY 1000000
static bool havetimerclock;
/*
* Setup routine called by autoconf stuff when an ltimer is found.
*/
int
config_ltimer(struct ltimer_softc *lt, int ltimerno)
{
/*
* Running on System/161 2.x, we always use the processor
* on-chip timer for hardclock and we don't need ltimer as
* hardclock.
*
* Ideally there should be code here that will use an ltimer
* for hardclock if nothing else is available; e.g. if we
* wanted to make OS/161 2.x run on System/161 1.x. However,
* that requires a good bit more infrastructure for handling
* timers than we have and it doesn't seem worthwhile.
*
* It would also require some hacking, because all CPUs need
* to receive timer interrupts. (Exercise: how would you make
* sure all CPUs receive exactly one timer interrupt? Remember
* that LAMEbus uses level-triggered interrupts, so the
* hardware interrupt line will cause repeated interrupts if
* it's not reset on the device; but if it's reset on the
* device before all CPUs manage to see it, those CPUs won't
* be interrupted at all.)
*
* Note that the beep and rtclock devices *do* attach to
* ltimer.
*/
(void)ltimerno;
lt->lt_hardclock = 0;
int config_ltimer(struct ltimer_softc *lt, int ltimerno) {
/*
* Running on System/161 2.x, we always use the processor
* on-chip timer for hardclock and we don't need ltimer as
* hardclock.
*
* Ideally there should be code here that will use an ltimer
* for hardclock if nothing else is available; e.g. if we
* wanted to make OS/161 2.x run on System/161 1.x. However,
* that requires a good bit more infrastructure for handling
* timers than we have and it doesn't seem worthwhile.
*
* It would also require some hacking, because all CPUs need
* to receive timer interrupts. (Exercise: how would you make
* sure all CPUs receive exactly one timer interrupt? Remember
* that LAMEbus uses level-triggered interrupts, so the
* hardware interrupt line will cause repeated interrupts if
* it's not reset on the device; but if it's reset on the
* device before all CPUs manage to see it, those CPUs won't
* be interrupted at all.)
*
* Note that the beep and rtclock devices *do* attach to
* ltimer.
*/
(void)ltimerno;
lt->lt_hardclock = 0;
/*
* We do, however, use ltimer for the timer clock, since the
* on-chip timer can't do that.
*/
if (!havetimerclock) {
havetimerclock = true;
lt->lt_timerclock = 1;
/*
* We do, however, use ltimer for the timer clock, since the
* on-chip timer can't do that.
*/
if (!havetimerclock) {
havetimerclock = true;
lt->lt_timerclock = 1;
/* Wire it to go off once every second. */
bus_write_register(lt->lt_bus, lt->lt_buspos, LT_REG_ROE, 1);
bus_write_register(lt->lt_bus, lt->lt_buspos, LT_REG_COUNT,
LT_GRANULARITY);
}
/* Wire it to go off once every second. */
bus_write_register(lt->lt_bus, lt->lt_buspos, LT_REG_ROE, 1);
bus_write_register(lt->lt_bus, lt->lt_buspos, LT_REG_COUNT, LT_GRANULARITY);
}
return 0;
return 0;
}
/*
* Interrupt handler.
*/
void
ltimer_irq(void *vlt)
{
struct ltimer_softc *lt = vlt;
uint32_t val;
void ltimer_irq(void *vlt) {
struct ltimer_softc *lt = vlt;
uint32_t val;
val = bus_read_register(lt->lt_bus, lt->lt_buspos, LT_REG_IRQ);
if (val) {
/*
* Only call hardclock if we're responsible for hardclock.
* (Any additional timer devices are unused.)
*/
if (lt->lt_hardclock) {
hardclock();
}
/*
* Likewise for timerclock.
*/
if (lt->lt_timerclock) {
timerclock();
}
}
val = bus_read_register(lt->lt_bus, lt->lt_buspos, LT_REG_IRQ);
if (val) {
/*
* Only call hardclock if we're responsible for hardclock.
* (Any additional timer devices are unused.)
*/
if (lt->lt_hardclock) {
hardclock();
}
/*
* Likewise for timerclock.
*/
if (lt->lt_timerclock) {
timerclock();
}
}
}
/*
@@ -132,12 +127,10 @@ ltimer_irq(void *vlt)
* doesn't matter what value you write. This function is called if
* the beep device is attached to this timer.
*/
void
ltimer_beep(void *vlt)
{
struct ltimer_softc *lt = vlt;
void ltimer_beep(void *vlt) {
struct ltimer_softc *lt = vlt;
bus_write_register(lt->lt_bus, lt->lt_buspos, LT_REG_SPKR, 440);
bus_write_register(lt->lt_bus, lt->lt_buspos, LT_REG_SPKR, 440);
}
/*
@@ -145,43 +138,37 @@ ltimer_beep(void *vlt)
* This function gets called if the rtclock device is attached
* to this timer.
*/
void
ltimer_gettime(void *vlt, struct timespec *ts)
{
struct ltimer_softc *lt = vlt;
uint32_t secs1, secs2;
int spl;
void ltimer_gettime(void *vlt, struct timespec *ts) {
struct ltimer_softc *lt = vlt;
uint32_t secs1, secs2;
int spl;
/*
* Read the seconds twice, on either side of the nanoseconds.
* If nsecs is small, use the *later* value of seconds, in case
* the nanoseconds turned over between the time we got the earlier
* value and the time we got nsecs.
*
* Note that the clock in the ltimer device is accurate down
* to a single processor cycle, so this might actually matter
* now and then.
*
* Do it with interrupts off on the current processor to avoid
* getting garbage if we get an interrupt among the register
* reads.
*/
/*
* Read the seconds twice, on either side of the nanoseconds.
* If nsecs is small, use the *later* value of seconds, in case
* the nanoseconds turned over between the time we got the earlier
* value and the time we got nsecs.
*
* Note that the clock in the ltimer device is accurate down
* to a single processor cycle, so this might actually matter
* now and then.
*
* Do it with interrupts off on the current processor to avoid
* getting garbage if we get an interrupt among the register
* reads.
*/
spl = splhigh();
spl = splhigh();
secs1 = bus_read_register(lt->lt_bus, lt->lt_buspos,
LT_REG_SEC);
ts->tv_nsec = bus_read_register(lt->lt_bus, lt->lt_buspos,
LT_REG_NSEC);
secs2 = bus_read_register(lt->lt_bus, lt->lt_buspos,
LT_REG_SEC);
secs1 = bus_read_register(lt->lt_bus, lt->lt_buspos, LT_REG_SEC);
ts->tv_nsec = bus_read_register(lt->lt_bus, lt->lt_buspos, LT_REG_NSEC);
secs2 = bus_read_register(lt->lt_bus, lt->lt_buspos, LT_REG_SEC);
splx(spl);
splx(spl);
if (ts->tv_nsec < 5000000) {
ts->tv_sec = secs2;
}
else {
ts->tv_sec = secs1;
}
if (ts->tv_nsec < 5000000) {
ts->tv_sec = secs2;
} else {
ts->tv_sec = secs1;
}
}

View File

@@ -36,21 +36,21 @@ struct timespec;
* Hardware device data for LAMEbus timer device
*/
struct ltimer_softc {
/* Initialized by config function */
int lt_hardclock; /* true if we should call hardclock() */
int lt_timerclock; /* true if we should call timerclock() */
/* Initialized by config function */
int lt_hardclock; /* true if we should call hardclock() */
int lt_timerclock; /* true if we should call timerclock() */
/* Initialized by lower-level attach routine */
void *lt_bus; /* bus we're on */
uint32_t lt_buspos; /* position (slot) on that bus */
/* Initialized by lower-level attach routine */
void *lt_bus; /* bus we're on */
uint32_t lt_buspos; /* position (slot) on that bus */
};
/* Functions called by lower-level drivers */
void ltimer_irq(/*struct ltimer_softc*/ void *lt); // interrupt handler
void ltimer_irq(/*struct ltimer_softc*/ void *lt); // interrupt handler
/* Functions called by higher-level devices */
void ltimer_beep(/*struct ltimer_softc*/ void *devdata); // for beep device
void ltimer_beep(/*struct ltimer_softc*/ void *devdata); // for beep device
void ltimer_gettime(/*struct ltimer_softc*/ void *devdata,
struct timespec *ts); // for rtclock
struct timespec *ts); // for rtclock
#endif /* _LAMEBUS_LTIMER_H_ */

View File

@@ -37,34 +37,33 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 1
#define LOW_VERSION 1
struct ltimer_softc *
attach_ltimer_to_lamebus(int ltimerno, struct lamebus_softc *sc)
{
struct ltimer_softc *lt;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_TIMER,
LOW_VERSION, NULL);
if (slot < 0) {
/* No ltimer (or no additional ltimer) found */
return NULL;
}
struct ltimer_softc *attach_ltimer_to_lamebus(int ltimerno,
struct lamebus_softc *sc) {
struct ltimer_softc *lt;
int slot =
lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_TIMER, LOW_VERSION, NULL);
if (slot < 0) {
/* No ltimer (or no additional ltimer) found */
return NULL;
}
lt = kmalloc(sizeof(struct ltimer_softc));
if (lt==NULL) {
/* out of memory */
return NULL;
}
lt = kmalloc(sizeof(struct ltimer_softc));
if (lt == NULL) {
/* out of memory */
return NULL;
}
(void)ltimerno; // unused
(void)ltimerno; // unused
/* Record what bus it's on */
lt->lt_bus = sc;
lt->lt_buspos = slot;
/* Record what bus it's on */
lt->lt_bus = sc;
lt->lt_buspos = slot;
/* Mark the slot in use and hook that slot's interrupt */
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, lt, ltimer_irq);
/* Mark the slot in use and hook that slot's interrupt */
lamebus_mark(sc, slot);
lamebus_attach_interrupt(sc, slot, lt, ltimer_irq);
return lt;
return lt;
}

View File

@@ -34,83 +34,67 @@
#include "autoconf.h"
/* Registers (offsets within slot) */
#define LTRACE_REG_TRON 0 /* trace on */
#define LTRACE_REG_TROFF 4 /* trace off */
#define LTRACE_REG_DEBUG 8 /* debug code */
#define LTRACE_REG_DUMP 12 /* dump the system */
#define LTRACE_REG_STOP 16 /* stop for the debugger */
#define LTRACE_REG_PROFEN 20 /* turn profiling on/off */
#define LTRACE_REG_PROFCL 24 /* clear the profile */
#define LTRACE_REG_TRON 0 /* trace on */
#define LTRACE_REG_TROFF 4 /* trace off */
#define LTRACE_REG_DEBUG 8 /* debug code */
#define LTRACE_REG_DUMP 12 /* dump the system */
#define LTRACE_REG_STOP 16 /* stop for the debugger */
#define LTRACE_REG_PROFEN 20 /* turn profiling on/off */
#define LTRACE_REG_PROFCL 24 /* clear the profile */
static struct ltrace_softc *the_trace;
void
ltrace_on(uint32_t code)
{
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_TRON, code);
}
void ltrace_on(uint32_t code) {
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_TRON, code);
}
}
void
ltrace_off(uint32_t code)
{
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_TROFF, code);
}
void ltrace_off(uint32_t code) {
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_TROFF, code);
}
}
void
ltrace_debug(uint32_t code)
{
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_DEBUG, code);
}
void ltrace_debug(uint32_t code) {
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_DEBUG, code);
}
}
void
ltrace_dump(uint32_t code)
{
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_DUMP, code);
}
void ltrace_dump(uint32_t code) {
if (the_trace != NULL) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_DUMP, code);
}
}
void
ltrace_stop(uint32_t code)
{
if (the_trace != NULL && the_trace->lt_canstop) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_STOP, code);
}
void ltrace_stop(uint32_t code) {
if (the_trace != NULL && the_trace->lt_canstop) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_STOP, code);
}
}
void
ltrace_setprof(uint32_t onoff)
{
if (the_trace != NULL && the_trace->lt_canprof) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_PROFEN, onoff);
}
void ltrace_setprof(uint32_t onoff) {
if (the_trace != NULL && the_trace->lt_canprof) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_PROFEN, onoff);
}
}
void
ltrace_eraseprof(void)
{
if (the_trace != NULL && the_trace->lt_canprof) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_PROFCL, 1);
}
void ltrace_eraseprof(void) {
if (the_trace != NULL && the_trace->lt_canprof) {
bus_write_register(the_trace->lt_busdata, the_trace->lt_buspos,
LTRACE_REG_PROFCL, 1);
}
}
int
config_ltrace(struct ltrace_softc *sc, int ltraceno)
{
(void)ltraceno;
the_trace = sc;
return 0;
int config_ltrace(struct ltrace_softc *sc, int ltraceno) {
(void)ltraceno;
the_trace = sc;
return 0;
}

View File

@@ -31,11 +31,11 @@
#define _LAMEBUS_LTRACE_H_
struct ltrace_softc {
/* Initialized by lower-level attachment function */
void *lt_busdata;
uint32_t lt_buspos;
bool lt_canstop;
bool lt_canprof;
/* Initialized by lower-level attachment function */
void *lt_busdata;
uint32_t lt_buspos;
bool lt_canstop;
bool lt_canprof;
};
/*

View File

@@ -34,36 +34,35 @@
#include "autoconf.h"
/* Lowest revision we support */
#define LOW_VERSION 1
#define LOW_VERSION 1
/* Revision that supports ltrace_stop() */
#define STOP_VERSION 2
#define STOP_VERSION 2
/* Revision that supports ltrace_prof() */
#define PROF_VERSION 3
#define PROF_VERSION 3
struct ltrace_softc *
attach_ltrace_to_lamebus(int ltraceno, struct lamebus_softc *sc)
{
struct ltrace_softc *lt;
uint32_t drl;
int slot = lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_TRACE,
LOW_VERSION, &drl);
if (slot < 0) {
return NULL;
}
struct ltrace_softc *attach_ltrace_to_lamebus(int ltraceno,
struct lamebus_softc *sc) {
struct ltrace_softc *lt;
uint32_t drl;
int slot =
lamebus_probe(sc, LB_VENDOR_CS161, LBCS161_TRACE, LOW_VERSION, &drl);
if (slot < 0) {
return NULL;
}
lt = kmalloc(sizeof(struct ltrace_softc));
if (lt==NULL) {
return NULL;
}
lt = kmalloc(sizeof(struct ltrace_softc));
if (lt == NULL) {
return NULL;
}
(void)ltraceno; // unused
(void)ltraceno; // unused
lt->lt_busdata = sc;
lt->lt_buspos = slot;
lt->lt_canstop = drl >= STOP_VERSION;
lt->lt_canprof = drl >= PROF_VERSION;
lt->lt_busdata = sc;
lt->lt_buspos = slot;
lt->lt_canstop = drl >= STOP_VERSION;
lt->lt_canprof = drl >= PROF_VERSION;
lamebus_mark(sc, slot);
lamebus_mark(sc, slot);
return lt;
return lt;
}

View File

@@ -38,20 +38,19 @@
#include <lamebus/lrandom.h>
#include "autoconf.h"
struct random_softc *
attach_random_to_lrandom(int randomno, struct lrandom_softc *ls)
{
struct random_softc *rs = kmalloc(sizeof(struct random_softc));
if (rs==NULL) {
return NULL;
}
struct random_softc *attach_random_to_lrandom(int randomno,
struct lrandom_softc *ls) {
struct random_softc *rs = kmalloc(sizeof(struct random_softc));
if (rs == NULL) {
return NULL;
}
(void)randomno; // unused
(void)randomno; // unused
rs->rs_devdata = ls;
rs->rs_random = lrandom_random;
rs->rs_randmax = lrandom_randmax;
rs->rs_read = lrandom_read;
rs->rs_devdata = ls;
rs->rs_random = lrandom_random;
rs->rs_randmax = lrandom_randmax;
rs->rs_read = lrandom_read;
return rs;
return rs;
}

View File

@@ -44,23 +44,22 @@
#include <lamebus/ltimer.h>
#include "autoconf.h"
struct rtclock_softc *
attach_rtclock_to_ltimer(int rtclockno, struct ltimer_softc *ls)
{
/*
* No need to probe; ltimer always has a clock.
* Just allocate the rtclock, set our fields, and return it.
*/
struct rtclock_softc *rtc = kmalloc(sizeof(struct rtclock_softc));
if (rtc==NULL) {
/* Out of memory */
return NULL;
}
struct rtclock_softc *attach_rtclock_to_ltimer(int rtclockno,
struct ltimer_softc *ls) {
/*
* No need to probe; ltimer always has a clock.
* Just allocate the rtclock, set our fields, and return it.
*/
struct rtclock_softc *rtc = kmalloc(sizeof(struct rtclock_softc));
if (rtc == NULL) {
/* Out of memory */
return NULL;
}
(void)rtclockno; // unused
(void)rtclockno; // unused
rtc->rtc_devdata = ls;
rtc->rtc_gettime = ltimer_gettime;
rtc->rtc_devdata = ls;
rtc->rtc_gettime = ltimer_gettime;
return rtc;
return rtc;
}

View File

@@ -42,7 +42,7 @@
* Constants
*/
#define SEMFS_ROOTDIR 0xffffffffU /* semnum for root dir */
#define SEMFS_ROOTDIR 0xffffffffU /* semnum for root dir */
/*
* A user-facing semaphore.
@@ -52,11 +52,11 @@
* XXX: or would we? review once all this is done.
*/
struct semfs_sem {
struct lock *sems_lock; /* Lock to protect count */
struct cv *sems_cv; /* CV to wait */
unsigned sems_count; /* Semaphore count */
bool sems_hasvnode; /* The vnode exists */
bool sems_linked; /* In the directory */
struct lock *sems_lock; /* Lock to protect count */
struct cv *sems_cv; /* CV to wait */
unsigned sems_count; /* Semaphore count */
bool sems_hasvnode; /* The vnode exists */
bool sems_linked; /* In the directory */
};
DECLARRAY(semfs_sem, SEMFS_INLINE);
@@ -64,8 +64,8 @@ DECLARRAY(semfs_sem, SEMFS_INLINE);
* Directory entry; name and reference to a semaphore.
*/
struct semfs_direntry {
char *semd_name; /* Name */
unsigned semd_semnum; /* Which semaphore */
char *semd_name; /* Name */
unsigned semd_semnum; /* Which semaphore */
};
DECLARRAY(semfs_direntry, SEMFS_INLINE);
@@ -77,9 +77,9 @@ DECLARRAY(semfs_direntry, SEMFS_INLINE);
* practice. XXX: review after finishing)
*/
struct semfs_vnode {
struct vnode semv_absvn; /* Abstract vnode */
struct semfs *semv_semfs; /* Back-pointer to fs */
unsigned semv_semnum; /* Which semaphore */
struct vnode semv_absvn; /* Abstract vnode */
struct semfs *semv_semfs; /* Back-pointer to fs */
unsigned semv_semnum; /* Which semaphore */
};
/*
@@ -87,14 +87,14 @@ struct semfs_vnode {
* is only one of these.
*/
struct semfs {
struct fs semfs_absfs; /* Abstract fs object */
struct fs semfs_absfs; /* Abstract fs object */
struct lock *semfs_tablelock; /* Lock for following */
struct vnodearray *semfs_vnodes; /* Currently extant vnodes */
struct semfs_semarray *semfs_sems; /* Semaphores */
struct lock *semfs_tablelock; /* Lock for following */
struct vnodearray *semfs_vnodes; /* Currently extant vnodes */
struct semfs_semarray *semfs_sems; /* Semaphores */
struct lock *semfs_dirlock; /* Lock for following */
struct semfs_direntryarray *semfs_dents; /* The root directory */
struct lock *semfs_dirlock; /* Lock for following */
struct semfs_direntryarray *semfs_dents; /* The root directory */
};
/*
@@ -104,7 +104,6 @@ struct semfs {
DEFARRAY(semfs_sem, SEMFS_INLINE);
DEFARRAY(semfs_direntry, SEMFS_INLINE);
/*
* Functions.
*/
@@ -119,5 +118,4 @@ void semfs_direntry_destroy(struct semfs_direntry *);
/* in semfs_vnops.c */
int semfs_getvnode(struct semfs *, unsigned, struct vnode **ret);
#endif /* SEMFS_H */

View File

@@ -42,185 +42,163 @@
/*
* Sync doesn't need to do anything.
*/
static
int
semfs_sync(struct fs *fs)
{
(void)fs;
return 0;
static int semfs_sync(struct fs *fs) {
(void)fs;
return 0;
}
/*
* We have only one volume name and it's hardwired.
*/
static
const char *
semfs_getvolname(struct fs *fs)
{
(void)fs;
return "sem";
static const char *semfs_getvolname(struct fs *fs) {
(void)fs;
return "sem";
}
/*
* Get the root directory vnode.
*/
static
int
semfs_getroot(struct fs *fs, struct vnode **ret)
{
struct semfs *semfs = fs->fs_data;
struct vnode *vn;
int result;
static int semfs_getroot(struct fs *fs, struct vnode **ret) {
struct semfs *semfs = fs->fs_data;
struct vnode *vn;
int result;
result = semfs_getvnode(semfs, SEMFS_ROOTDIR, &vn);
if (result) {
kprintf("semfs: couldn't load root vnode: %s\n",
strerror(result));
return result;
}
*ret = vn;
return 0;
result = semfs_getvnode(semfs, SEMFS_ROOTDIR, &vn);
if (result) {
kprintf("semfs: couldn't load root vnode: %s\n", strerror(result));
return result;
}
*ret = vn;
return 0;
}
////////////////////////////////////////////////////////////
// mount and unmount logic
/*
* Destructor for struct semfs.
*/
static
void
semfs_destroy(struct semfs *semfs)
{
struct semfs_sem *sem;
struct semfs_direntry *dent;
unsigned i, num;
static void semfs_destroy(struct semfs *semfs) {
struct semfs_sem *sem;
struct semfs_direntry *dent;
unsigned i, num;
num = semfs_semarray_num(semfs->semfs_sems);
for (i=0; i<num; i++) {
sem = semfs_semarray_get(semfs->semfs_sems, i);
semfs_sem_destroy(sem);
}
semfs_semarray_setsize(semfs->semfs_sems, 0);
num = semfs_semarray_num(semfs->semfs_sems);
for (i = 0; i < num; i++) {
sem = semfs_semarray_get(semfs->semfs_sems, i);
semfs_sem_destroy(sem);
}
semfs_semarray_setsize(semfs->semfs_sems, 0);
num = semfs_direntryarray_num(semfs->semfs_dents);
for (i=0; i<num; i++) {
dent = semfs_direntryarray_get(semfs->semfs_dents, i);
semfs_direntry_destroy(dent);
}
semfs_direntryarray_setsize(semfs->semfs_dents, 0);
num = semfs_direntryarray_num(semfs->semfs_dents);
for (i = 0; i < num; i++) {
dent = semfs_direntryarray_get(semfs->semfs_dents, i);
semfs_direntry_destroy(dent);
}
semfs_direntryarray_setsize(semfs->semfs_dents, 0);
semfs_direntryarray_destroy(semfs->semfs_dents);
lock_destroy(semfs->semfs_dirlock);
semfs_semarray_destroy(semfs->semfs_sems);
vnodearray_destroy(semfs->semfs_vnodes);
lock_destroy(semfs->semfs_tablelock);
kfree(semfs);
semfs_direntryarray_destroy(semfs->semfs_dents);
lock_destroy(semfs->semfs_dirlock);
semfs_semarray_destroy(semfs->semfs_sems);
vnodearray_destroy(semfs->semfs_vnodes);
lock_destroy(semfs->semfs_tablelock);
kfree(semfs);
}
/*
* Unmount routine. XXX: Since semfs is attached at boot and can't be
* remounted, maybe unmounting it shouldn't be allowed.
*/
static
int
semfs_unmount(struct fs *fs)
{
struct semfs *semfs = fs->fs_data;
static int semfs_unmount(struct fs *fs) {
struct semfs *semfs = fs->fs_data;
lock_acquire(semfs->semfs_tablelock);
if (vnodearray_num(semfs->semfs_vnodes) > 0) {
lock_release(semfs->semfs_tablelock);
return EBUSY;
}
lock_acquire(semfs->semfs_tablelock);
if (vnodearray_num(semfs->semfs_vnodes) > 0) {
lock_release(semfs->semfs_tablelock);
return EBUSY;
}
lock_release(semfs->semfs_tablelock);
semfs_destroy(semfs);
lock_release(semfs->semfs_tablelock);
semfs_destroy(semfs);
return 0;
return 0;
}
/*
* Operations table.
*/
static const struct fs_ops semfs_fsops = {
.fsop_sync = semfs_sync,
.fsop_getvolname = semfs_getvolname,
.fsop_getroot = semfs_getroot,
.fsop_unmount = semfs_unmount,
.fsop_sync = semfs_sync,
.fsop_getvolname = semfs_getvolname,
.fsop_getroot = semfs_getroot,
.fsop_unmount = semfs_unmount,
};
/*
* Constructor for struct semfs.
*/
static
struct semfs *
semfs_create(void)
{
struct semfs *semfs;
static struct semfs *semfs_create(void) {
struct semfs *semfs;
semfs = kmalloc(sizeof(*semfs));
if (semfs == NULL) {
goto fail_total;
}
semfs = kmalloc(sizeof(*semfs));
if (semfs == NULL) {
goto fail_total;
}
semfs->semfs_tablelock = lock_create("semfs_table");
if (semfs->semfs_tablelock == NULL) {
goto fail_semfs;
}
semfs->semfs_vnodes = vnodearray_create();
if (semfs->semfs_vnodes == NULL) {
goto fail_tablelock;
}
semfs->semfs_sems = semfs_semarray_create();
if (semfs->semfs_sems == NULL) {
goto fail_vnodes;
}
semfs->semfs_tablelock = lock_create("semfs_table");
if (semfs->semfs_tablelock == NULL) {
goto fail_semfs;
}
semfs->semfs_vnodes = vnodearray_create();
if (semfs->semfs_vnodes == NULL) {
goto fail_tablelock;
}
semfs->semfs_sems = semfs_semarray_create();
if (semfs->semfs_sems == NULL) {
goto fail_vnodes;
}
semfs->semfs_dirlock = lock_create("semfs_dir");
if (semfs->semfs_dirlock == NULL) {
goto fail_sems;
}
semfs->semfs_dents = semfs_direntryarray_create();
if (semfs->semfs_dents == NULL) {
goto fail_dirlock;
}
semfs->semfs_dirlock = lock_create("semfs_dir");
if (semfs->semfs_dirlock == NULL) {
goto fail_sems;
}
semfs->semfs_dents = semfs_direntryarray_create();
if (semfs->semfs_dents == NULL) {
goto fail_dirlock;
}
semfs->semfs_absfs.fs_data = semfs;
semfs->semfs_absfs.fs_ops = &semfs_fsops;
return semfs;
semfs->semfs_absfs.fs_data = semfs;
semfs->semfs_absfs.fs_ops = &semfs_fsops;
return semfs;
fail_dirlock:
lock_destroy(semfs->semfs_dirlock);
fail_sems:
semfs_semarray_destroy(semfs->semfs_sems);
fail_vnodes:
vnodearray_destroy(semfs->semfs_vnodes);
fail_tablelock:
lock_destroy(semfs->semfs_tablelock);
fail_semfs:
kfree(semfs);
fail_total:
return NULL;
fail_dirlock:
lock_destroy(semfs->semfs_dirlock);
fail_sems:
semfs_semarray_destroy(semfs->semfs_sems);
fail_vnodes:
vnodearray_destroy(semfs->semfs_vnodes);
fail_tablelock:
lock_destroy(semfs->semfs_tablelock);
fail_semfs:
kfree(semfs);
fail_total:
return NULL;
}
/*
* Create the semfs. There is only one semfs and it's attached as
* "sem:" during bootup.
*/
void
semfs_bootstrap(void)
{
struct semfs *semfs;
int result;
void semfs_bootstrap(void) {
struct semfs *semfs;
int result;
semfs = semfs_create();
if (semfs == NULL) {
panic("Out of memory creating semfs\n");
}
result = vfs_addfs("sem", &semfs->semfs_absfs);
if (result) {
panic("Attaching semfs: %s\n", strerror(result));
}
semfs = semfs_create();
if (semfs == NULL) {
panic("Out of memory creating semfs\n");
}
result = vfs_addfs("sem", &semfs->semfs_absfs);
if (result) {
panic("Attaching semfs: %s\n", strerror(result));
}
}

View File

@@ -40,74 +40,69 @@
/*
* Constructor for semfs_sem.
*/
struct semfs_sem *
semfs_sem_create(const char *name)
{
struct semfs_sem *sem;
char lockname[32];
char cvname[32];
struct semfs_sem *semfs_sem_create(const char *name) {
struct semfs_sem *sem;
char lockname[32];
char cvname[32];
snprintf(lockname, sizeof(lockname), "sem:l.%s", name);
snprintf(cvname, sizeof(cvname), "sem:%s", name);
snprintf(lockname, sizeof(lockname), "sem:l.%s", name);
snprintf(cvname, sizeof(cvname), "sem:%s", name);
sem = kmalloc(sizeof(*sem));
if (sem == NULL) {
goto fail_return;
}
sem->sems_lock = lock_create(lockname);
if (sem->sems_lock == NULL) {
goto fail_sem;
}
sem->sems_cv = cv_create(cvname);
if (sem->sems_cv == NULL) {
goto fail_lock;
}
sem->sems_count = 0;
sem->sems_hasvnode = false;
sem->sems_linked = false;
return sem;
sem = kmalloc(sizeof(*sem));
if (sem == NULL) {
goto fail_return;
}
sem->sems_lock = lock_create(lockname);
if (sem->sems_lock == NULL) {
goto fail_sem;
}
sem->sems_cv = cv_create(cvname);
if (sem->sems_cv == NULL) {
goto fail_lock;
}
sem->sems_count = 0;
sem->sems_hasvnode = false;
sem->sems_linked = false;
return sem;
fail_lock:
lock_destroy(sem->sems_lock);
fail_sem:
kfree(sem);
fail_return:
return NULL;
fail_lock:
lock_destroy(sem->sems_lock);
fail_sem:
kfree(sem);
fail_return:
return NULL;
}
/*
* Destructor for semfs_sem.
*/
void
semfs_sem_destroy(struct semfs_sem *sem)
{
cv_destroy(sem->sems_cv);
lock_destroy(sem->sems_lock);
kfree(sem);
void semfs_sem_destroy(struct semfs_sem *sem) {
cv_destroy(sem->sems_cv);
lock_destroy(sem->sems_lock);
kfree(sem);
}
/*
* Helper to insert a semfs_sem into the semaphore table.
*/
int
semfs_sem_insert(struct semfs *semfs, struct semfs_sem *sem, unsigned *ret)
{
unsigned i, num;
int semfs_sem_insert(struct semfs *semfs, struct semfs_sem *sem,
unsigned *ret) {
unsigned i, num;
KASSERT(lock_do_i_hold(semfs->semfs_tablelock));
num = semfs_semarray_num(semfs->semfs_sems);
if (num == SEMFS_ROOTDIR) {
/* Too many */
return ENOSPC;
}
for (i=0; i<num; i++) {
if (semfs_semarray_get(semfs->semfs_sems, i) == NULL) {
semfs_semarray_set(semfs->semfs_sems, i, sem);
*ret = i;
return 0;
}
}
return semfs_semarray_add(semfs->semfs_sems, sem, ret);
KASSERT(lock_do_i_hold(semfs->semfs_tablelock));
num = semfs_semarray_num(semfs->semfs_sems);
if (num == SEMFS_ROOTDIR) {
/* Too many */
return ENOSPC;
}
for (i = 0; i < num; i++) {
if (semfs_semarray_get(semfs->semfs_sems, i) == NULL) {
semfs_semarray_set(semfs->semfs_sems, i, sem);
*ret = i;
return 0;
}
}
return semfs_semarray_add(semfs->semfs_sems, sem, ret);
}
////////////////////////////////////////////////////////////
@@ -116,30 +111,27 @@ semfs_sem_insert(struct semfs *semfs, struct semfs_sem *sem, unsigned *ret)
/*
* Constructor for semfs_direntry.
*/
struct semfs_direntry *
semfs_direntry_create(const char *name, unsigned semnum)
{
struct semfs_direntry *dent;
struct semfs_direntry *semfs_direntry_create(const char *name,
unsigned semnum) {
struct semfs_direntry *dent;
dent = kmalloc(sizeof(*dent));
if (dent == NULL) {
return NULL;
}
dent->semd_name = kstrdup(name);
if (dent->semd_name == NULL) {
kfree(dent);
return NULL;
}
dent->semd_semnum = semnum;
return dent;
dent = kmalloc(sizeof(*dent));
if (dent == NULL) {
return NULL;
}
dent->semd_name = kstrdup(name);
if (dent->semd_name == NULL) {
kfree(dent);
return NULL;
}
dent->semd_semnum = semnum;
return dent;
}
/*
* Destructor for semfs_direntry.
*/
void
semfs_direntry_destroy(struct semfs_direntry *dent)
{
kfree(dent->semd_name);
kfree(dent);
void semfs_direntry_destroy(struct semfs_direntry *dent) {
kfree(dent->semd_name);
kfree(dent);
}

File diff suppressed because it is too large Load Diff

View File

@@ -41,63 +41,53 @@
/*
* Zero out a disk block.
*/
static
int
sfs_clearblock(struct sfs_fs *sfs, daddr_t block)
{
/* static -> automatically initialized to zero */
static char zeros[SFS_BLOCKSIZE];
static int sfs_clearblock(struct sfs_fs *sfs, daddr_t block) {
/* static -> automatically initialized to zero */
static char zeros[SFS_BLOCKSIZE];
return sfs_writeblock(sfs, block, zeros, SFS_BLOCKSIZE);
return sfs_writeblock(sfs, block, zeros, SFS_BLOCKSIZE);
}
/*
* Allocate a block.
*/
int
sfs_balloc(struct sfs_fs *sfs, daddr_t *diskblock)
{
int result;
int sfs_balloc(struct sfs_fs *sfs, daddr_t *diskblock) {
int result;
result = bitmap_alloc(sfs->sfs_freemap, diskblock);
if (result) {
return result;
}
sfs->sfs_freemapdirty = true;
result = bitmap_alloc(sfs->sfs_freemap, diskblock);
if (result) {
return result;
}
sfs->sfs_freemapdirty = true;
if (*diskblock >= sfs->sfs_sb.sb_nblocks) {
panic("sfs: %s: balloc: invalid block %u\n",
sfs->sfs_sb.sb_volname, *diskblock);
}
if (*diskblock >= sfs->sfs_sb.sb_nblocks) {
panic("sfs: %s: balloc: invalid block %u\n", sfs->sfs_sb.sb_volname,
*diskblock);
}
/* Clear block before returning it */
result = sfs_clearblock(sfs, *diskblock);
if (result) {
bitmap_unmark(sfs->sfs_freemap, *diskblock);
}
return result;
/* Clear block before returning it */
result = sfs_clearblock(sfs, *diskblock);
if (result) {
bitmap_unmark(sfs->sfs_freemap, *diskblock);
}
return result;
}
/*
* Free a block.
*/
void
sfs_bfree(struct sfs_fs *sfs, daddr_t diskblock)
{
bitmap_unmark(sfs->sfs_freemap, diskblock);
sfs->sfs_freemapdirty = true;
void sfs_bfree(struct sfs_fs *sfs, daddr_t diskblock) {
bitmap_unmark(sfs->sfs_freemap, diskblock);
sfs->sfs_freemapdirty = true;
}
/*
* Check if a block is in use.
*/
int
sfs_bused(struct sfs_fs *sfs, daddr_t diskblock)
{
if (diskblock >= sfs->sfs_sb.sb_nblocks) {
panic("sfs: %s: sfs_bused called on out of range block %u\n",
sfs->sfs_sb.sb_volname, diskblock);
}
return bitmap_isset(sfs->sfs_freemap, diskblock);
int sfs_bused(struct sfs_fs *sfs, daddr_t diskblock) {
if (diskblock >= sfs->sfs_sb.sb_nblocks) {
panic("sfs: %s: sfs_bused called on out of range block %u\n",
sfs->sfs_sb.sb_volname, diskblock);
}
return bitmap_isset(sfs->sfs_freemap, diskblock);
}

View File

@@ -45,259 +45,250 @@
* file. If DOALLOC is set, and no such block exists, one will be
* allocated.
*/
int
sfs_bmap(struct sfs_vnode *sv, uint32_t fileblock, bool doalloc,
daddr_t *diskblock)
{
/*
* I/O buffer for handling indirect blocks.
*
* Note: in real life (and when you've done the fs assignment)
* you would get space from the disk buffer cache for this,
* not use a static area.
*/
static uint32_t idbuf[SFS_DBPERIDB];
int sfs_bmap(struct sfs_vnode *sv, uint32_t fileblock, bool doalloc,
daddr_t *diskblock) {
/*
* I/O buffer for handling indirect blocks.
*
* Note: in real life (and when you've done the fs assignment)
* you would get space from the disk buffer cache for this,
* not use a static area.
*/
static uint32_t idbuf[SFS_DBPERIDB];
struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data;
daddr_t block;
daddr_t idblock;
uint32_t idnum, idoff;
int result;
struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data;
daddr_t block;
daddr_t idblock;
uint32_t idnum, idoff;
int result;
KASSERT(sizeof(idbuf)==SFS_BLOCKSIZE);
KASSERT(sizeof(idbuf) == SFS_BLOCKSIZE);
/* Since we're using a static buffer, we'd better be locked. */
KASSERT(vfs_biglock_do_i_hold());
/* Since we're using a static buffer, we'd better be locked. */
KASSERT(vfs_biglock_do_i_hold());
/*
* If the block we want is one of the direct blocks...
*/
if (fileblock < SFS_NDIRECT) {
/*
* Get the block number
*/
block = sv->sv_i.sfi_direct[fileblock];
/*
* If the block we want is one of the direct blocks...
*/
if (fileblock < SFS_NDIRECT) {
/*
* Get the block number
*/
block = sv->sv_i.sfi_direct[fileblock];
/*
* Do we need to allocate?
*/
if (block==0 && doalloc) {
result = sfs_balloc(sfs, &block);
if (result) {
return result;
}
/*
* Do we need to allocate?
*/
if (block == 0 && doalloc) {
result = sfs_balloc(sfs, &block);
if (result) {
return result;
}
/* Remember what we allocated; mark inode dirty */
sv->sv_i.sfi_direct[fileblock] = block;
sv->sv_dirty = true;
}
/* Remember what we allocated; mark inode dirty */
sv->sv_i.sfi_direct[fileblock] = block;
sv->sv_dirty = true;
}
/*
* Hand back the block
*/
if (block != 0 && !sfs_bused(sfs, block)) {
panic("sfs: %s: Data block %u (block %u of file %u) "
"marked free\n", sfs->sfs_sb.sb_volname,
block, fileblock, sv->sv_ino);
}
*diskblock = block;
return 0;
}
/*
* Hand back the block
*/
if (block != 0 && !sfs_bused(sfs, block)) {
panic("sfs: %s: Data block %u (block %u of file %u) "
"marked free\n",
sfs->sfs_sb.sb_volname, block, fileblock, sv->sv_ino);
}
*diskblock = block;
return 0;
}
/*
* It's not a direct block; it must be in the indirect block.
* Subtract off the number of direct blocks, so FILEBLOCK is
* now the offset into the indirect block space.
*/
/*
* It's not a direct block; it must be in the indirect block.
* Subtract off the number of direct blocks, so FILEBLOCK is
* now the offset into the indirect block space.
*/
fileblock -= SFS_NDIRECT;
fileblock -= SFS_NDIRECT;
/* Get the indirect block number and offset w/i that indirect block */
idnum = fileblock / SFS_DBPERIDB;
idoff = fileblock % SFS_DBPERIDB;
/* Get the indirect block number and offset w/i that indirect block */
idnum = fileblock / SFS_DBPERIDB;
idoff = fileblock % SFS_DBPERIDB;
/*
* We only have one indirect block. If the offset we were asked for
* is too large, we can't handle it, so fail.
*/
if (idnum >= SFS_NINDIRECT) {
return EFBIG;
}
/*
* We only have one indirect block. If the offset we were asked for
* is too large, we can't handle it, so fail.
*/
if (idnum >= SFS_NINDIRECT) {
return EFBIG;
}
/* Get the disk block number of the indirect block. */
idblock = sv->sv_i.sfi_indirect;
/* Get the disk block number of the indirect block. */
idblock = sv->sv_i.sfi_indirect;
if (idblock==0 && !doalloc) {
/*
* There's no indirect block allocated. We weren't
* asked to allocate anything, so pretend the indirect
* block was filled with all zeros.
*/
*diskblock = 0;
return 0;
}
else if (idblock==0) {
/*
* There's no indirect block allocated, but we need to
* allocate a block whose number needs to be stored in
* the indirect block. Thus, we need to allocate an
* indirect block.
*/
result = sfs_balloc(sfs, &idblock);
if (result) {
return result;
}
if (idblock == 0 && !doalloc) {
/*
* There's no indirect block allocated. We weren't
* asked to allocate anything, so pretend the indirect
* block was filled with all zeros.
*/
*diskblock = 0;
return 0;
} else if (idblock == 0) {
/*
* There's no indirect block allocated, but we need to
* allocate a block whose number needs to be stored in
* the indirect block. Thus, we need to allocate an
* indirect block.
*/
result = sfs_balloc(sfs, &idblock);
if (result) {
return result;
}
/* Remember the block we just allocated */
sv->sv_i.sfi_indirect = idblock;
/* Remember the block we just allocated */
sv->sv_i.sfi_indirect = idblock;
/* Mark the inode dirty */
sv->sv_dirty = true;
/* Mark the inode dirty */
sv->sv_dirty = true;
/* Clear the indirect block buffer */
bzero(idbuf, sizeof(idbuf));
}
else {
/*
* We already have an indirect block allocated; load it.
*/
result = sfs_readblock(sfs, idblock, idbuf, sizeof(idbuf));
if (result) {
return result;
}
}
/* Clear the indirect block buffer */
bzero(idbuf, sizeof(idbuf));
} else {
/*
* We already have an indirect block allocated; load it.
*/
result = sfs_readblock(sfs, idblock, idbuf, sizeof(idbuf));
if (result) {
return result;
}
}
/* Get the block out of the indirect block buffer */
block = idbuf[idoff];
/* Get the block out of the indirect block buffer */
block = idbuf[idoff];
/* If there's no block there, allocate one */
if (block==0 && doalloc) {
result = sfs_balloc(sfs, &block);
if (result) {
return result;
}
/* If there's no block there, allocate one */
if (block == 0 && doalloc) {
result = sfs_balloc(sfs, &block);
if (result) {
return result;
}
/* Remember the block we allocated */
idbuf[idoff] = block;
/* Remember the block we allocated */
idbuf[idoff] = block;
/* The indirect block is now dirty; write it back */
result = sfs_writeblock(sfs, idblock, idbuf, sizeof(idbuf));
if (result) {
return result;
}
}
/* The indirect block is now dirty; write it back */
result = sfs_writeblock(sfs, idblock, idbuf, sizeof(idbuf));
if (result) {
return result;
}
}
/* Hand back the result and return. */
if (block != 0 && !sfs_bused(sfs, block)) {
panic("sfs: %s: Data block %u (block %u of file %u) "
"marked free\n", sfs->sfs_sb.sb_volname,
block, fileblock, sv->sv_ino);
}
*diskblock = block;
return 0;
/* Hand back the result and return. */
if (block != 0 && !sfs_bused(sfs, block)) {
panic("sfs: %s: Data block %u (block %u of file %u) "
"marked free\n",
sfs->sfs_sb.sb_volname, block, fileblock, sv->sv_ino);
}
*diskblock = block;
return 0;
}
/*
* Called for ftruncate() and from sfs_reclaim.
*/
int
sfs_itrunc(struct sfs_vnode *sv, off_t len)
{
/*
* I/O buffer for handling the indirect block.
*
* Note: in real life (and when you've done the fs assignment)
* you would get space from the disk buffer cache for this,
* not use a static area.
*/
static uint32_t idbuf[SFS_DBPERIDB];
int sfs_itrunc(struct sfs_vnode *sv, off_t len) {
/*
* I/O buffer for handling the indirect block.
*
* Note: in real life (and when you've done the fs assignment)
* you would get space from the disk buffer cache for this,
* not use a static area.
*/
static uint32_t idbuf[SFS_DBPERIDB];
struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data;
struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data;
/* Length in blocks (divide rounding up) */
uint32_t blocklen = DIVROUNDUP(len, SFS_BLOCKSIZE);
/* Length in blocks (divide rounding up) */
uint32_t blocklen = DIVROUNDUP(len, SFS_BLOCKSIZE);
uint32_t i, j;
daddr_t block, idblock;
uint32_t baseblock, highblock;
int result;
int hasnonzero, iddirty;
uint32_t i, j;
daddr_t block, idblock;
uint32_t baseblock, highblock;
int result;
int hasnonzero, iddirty;
KASSERT(sizeof(idbuf)==SFS_BLOCKSIZE);
KASSERT(sizeof(idbuf) == SFS_BLOCKSIZE);
vfs_biglock_acquire();
vfs_biglock_acquire();
/*
* Go through the direct blocks. Discard any that are
* past the limit we're truncating to.
*/
for (i=0; i<SFS_NDIRECT; i++) {
block = sv->sv_i.sfi_direct[i];
if (i >= blocklen && block != 0) {
sfs_bfree(sfs, block);
sv->sv_i.sfi_direct[i] = 0;
sv->sv_dirty = true;
}
}
/*
* Go through the direct blocks. Discard any that are
* past the limit we're truncating to.
*/
for (i = 0; i < SFS_NDIRECT; i++) {
block = sv->sv_i.sfi_direct[i];
if (i >= blocklen && block != 0) {
sfs_bfree(sfs, block);
sv->sv_i.sfi_direct[i] = 0;
sv->sv_dirty = true;
}
}
/* Indirect block number */
idblock = sv->sv_i.sfi_indirect;
/* Indirect block number */
idblock = sv->sv_i.sfi_indirect;
/* The lowest block in the indirect block */
baseblock = SFS_NDIRECT;
/* The lowest block in the indirect block */
baseblock = SFS_NDIRECT;
/* The highest block in the indirect block */
highblock = baseblock + SFS_DBPERIDB - 1;
/* The highest block in the indirect block */
highblock = baseblock + SFS_DBPERIDB - 1;
if (blocklen < highblock && idblock != 0) {
/* We're past the proposed EOF; may need to free stuff */
if (blocklen < highblock && idblock != 0) {
/* We're past the proposed EOF; may need to free stuff */
/* Read the indirect block */
result = sfs_readblock(sfs, idblock, idbuf, sizeof(idbuf));
if (result) {
vfs_biglock_release();
return result;
}
/* Read the indirect block */
result = sfs_readblock(sfs, idblock, idbuf, sizeof(idbuf));
if (result) {
vfs_biglock_release();
return result;
}
hasnonzero = 0;
iddirty = 0;
for (j=0; j<SFS_DBPERIDB; j++) {
/* Discard any blocks that are past the new EOF */
if (blocklen < baseblock+j && idbuf[j] != 0) {
sfs_bfree(sfs, idbuf[j]);
idbuf[j] = 0;
iddirty = 1;
}
/* Remember if we see any nonzero blocks in here */
if (idbuf[j]!=0) {
hasnonzero=1;
}
}
hasnonzero = 0;
iddirty = 0;
for (j = 0; j < SFS_DBPERIDB; j++) {
/* Discard any blocks that are past the new EOF */
if (blocklen < baseblock + j && idbuf[j] != 0) {
sfs_bfree(sfs, idbuf[j]);
idbuf[j] = 0;
iddirty = 1;
}
/* Remember if we see any nonzero blocks in here */
if (idbuf[j] != 0) {
hasnonzero = 1;
}
}
if (!hasnonzero) {
/* The whole indirect block is empty now; free it */
sfs_bfree(sfs, idblock);
sv->sv_i.sfi_indirect = 0;
sv->sv_dirty = true;
}
else if (iddirty) {
/* The indirect block is dirty; write it back */
result = sfs_writeblock(sfs, idblock, idbuf,
sizeof(idbuf));
if (result) {
vfs_biglock_release();
return result;
}
}
}
if (!hasnonzero) {
/* The whole indirect block is empty now; free it */
sfs_bfree(sfs, idblock);
sv->sv_i.sfi_indirect = 0;
sv->sv_dirty = true;
} else if (iddirty) {
/* The indirect block is dirty; write it back */
result = sfs_writeblock(sfs, idblock, idbuf, sizeof(idbuf));
if (result) {
vfs_biglock_release();
return result;
}
}
}
/* Set the file size */
sv->sv_i.sfi_size = len;
/* Set the file size */
sv->sv_i.sfi_size = len;
/* Mark the inode dirty */
sv->sv_dirty = true;
/* Mark the inode dirty */
sv->sv_dirty = true;
vfs_biglock_release();
return 0;
vfs_biglock_release();
return 0;
}

View File

@@ -43,33 +43,29 @@
* Read the directory entry out of slot SLOT of a directory vnode.
* The "slot" is the index of the directory entry, starting at 0.
*/
static
int
sfs_readdir(struct sfs_vnode *sv, int slot, struct sfs_direntry *sd)
{
off_t actualpos;
static int sfs_readdir(struct sfs_vnode *sv, int slot,
struct sfs_direntry *sd) {
off_t actualpos;
/* Compute the actual position in the directory to read. */
actualpos = slot * sizeof(struct sfs_direntry);
/* Compute the actual position in the directory to read. */
actualpos = slot * sizeof(struct sfs_direntry);
return sfs_metaio(sv, actualpos, sd, sizeof(*sd), UIO_READ);
return sfs_metaio(sv, actualpos, sd, sizeof(*sd), UIO_READ);
}
/*
* Write (overwrite) the directory entry in slot SLOT of a directory
* vnode.
*/
static
int
sfs_writedir(struct sfs_vnode *sv, int slot, struct sfs_direntry *sd)
{
off_t actualpos;
static int sfs_writedir(struct sfs_vnode *sv, int slot,
struct sfs_direntry *sd) {
off_t actualpos;
/* Compute the actual position in the directory. */
KASSERT(slot>=0);
actualpos = slot * sizeof(struct sfs_direntry);
/* Compute the actual position in the directory. */
KASSERT(slot >= 0);
actualpos = slot * sizeof(struct sfs_direntry);
return sfs_metaio(sv, actualpos, sd, sizeof(*sd), UIO_WRITE);
return sfs_metaio(sv, actualpos, sd, sizeof(*sd), UIO_WRITE);
}
/*
@@ -77,22 +73,19 @@ sfs_writedir(struct sfs_vnode *sv, int slot, struct sfs_direntry *sd)
* This actually computes the number of existing slots, and does not
* account for empty slots.
*/
static
int
sfs_dir_nentries(struct sfs_vnode *sv)
{
struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data;
off_t size;
static int sfs_dir_nentries(struct sfs_vnode *sv) {
struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data;
off_t size;
KASSERT(sv->sv_i.sfi_type == SFS_TYPE_DIR);
KASSERT(sv->sv_i.sfi_type == SFS_TYPE_DIR);
size = sv->sv_i.sfi_size;
if (size % sizeof(struct sfs_direntry) != 0) {
panic("sfs: %s: directory %u: Invalid size %llu\n",
sfs->sfs_sb.sb_volname, sv->sv_ino, size);
}
size = sv->sv_i.sfi_size;
if (size % sizeof(struct sfs_direntry) != 0) {
panic("sfs: %s: directory %u: Invalid size %llu\n", sfs->sfs_sb.sb_volname,
sv->sv_ino, size);
}
return size / sizeof(struct sfs_direntry);
return size / sizeof(struct sfs_direntry);
}
/*
@@ -100,140 +93,130 @@ sfs_dir_nentries(struct sfs_vnode *sv)
* return its inode number, its slot, and/or the slot number of an
* empty directory slot if one is found.
*/
int
sfs_dir_findname(struct sfs_vnode *sv, const char *name,
uint32_t *ino, int *slot, int *emptyslot)
{
struct sfs_direntry tsd;
int found, nentries, i, result;
int sfs_dir_findname(struct sfs_vnode *sv, const char *name, uint32_t *ino,
int *slot, int *emptyslot) {
struct sfs_direntry tsd;
int found, nentries, i, result;
nentries = sfs_dir_nentries(sv);
nentries = sfs_dir_nentries(sv);
/* For each slot... */
found = 0;
for (i=0; i<nentries; i++) {
/* For each slot... */
found = 0;
for (i = 0; i < nentries; i++) {
/* Read the entry from that slot */
result = sfs_readdir(sv, i, &tsd);
if (result) {
return result;
}
if (tsd.sfd_ino == SFS_NOINO) {
/* Free slot - report it back if one was requested */
if (emptyslot != NULL) {
*emptyslot = i;
}
}
else {
/* Ensure null termination, just in case */
tsd.sfd_name[sizeof(tsd.sfd_name)-1] = 0;
if (!strcmp(tsd.sfd_name, name)) {
/* Read the entry from that slot */
result = sfs_readdir(sv, i, &tsd);
if (result) {
return result;
}
if (tsd.sfd_ino == SFS_NOINO) {
/* Free slot - report it back if one was requested */
if (emptyslot != NULL) {
*emptyslot = i;
}
} else {
/* Ensure null termination, just in case */
tsd.sfd_name[sizeof(tsd.sfd_name) - 1] = 0;
if (!strcmp(tsd.sfd_name, name)) {
/* Each name may legally appear only once... */
KASSERT(found==0);
/* Each name may legally appear only once... */
KASSERT(found == 0);
found = 1;
if (slot != NULL) {
*slot = i;
}
if (ino != NULL) {
*ino = tsd.sfd_ino;
}
}
}
}
found = 1;
if (slot != NULL) {
*slot = i;
}
if (ino != NULL) {
*ino = tsd.sfd_ino;
}
}
}
}
return found ? 0 : ENOENT;
return found ? 0 : ENOENT;
}
/*
* Create a link in a directory to the specified inode by number, with
* the specified name, and optionally hand back the slot.
*/
int
sfs_dir_link(struct sfs_vnode *sv, const char *name, uint32_t ino, int *slot)
{
int emptyslot = -1;
int result;
struct sfs_direntry sd;
int sfs_dir_link(struct sfs_vnode *sv, const char *name, uint32_t ino,
int *slot) {
int emptyslot = -1;
int result;
struct sfs_direntry sd;
/* Look up the name. We want to make sure it *doesn't* exist. */
result = sfs_dir_findname(sv, name, NULL, NULL, &emptyslot);
if (result!=0 && result!=ENOENT) {
return result;
}
if (result==0) {
return EEXIST;
}
/* Look up the name. We want to make sure it *doesn't* exist. */
result = sfs_dir_findname(sv, name, NULL, NULL, &emptyslot);
if (result != 0 && result != ENOENT) {
return result;
}
if (result == 0) {
return EEXIST;
}
if (strlen(name)+1 > sizeof(sd.sfd_name)) {
return ENAMETOOLONG;
}
if (strlen(name) + 1 > sizeof(sd.sfd_name)) {
return ENAMETOOLONG;
}
/* If we didn't get an empty slot, add the entry at the end. */
if (emptyslot < 0) {
emptyslot = sfs_dir_nentries(sv);
}
/* If we didn't get an empty slot, add the entry at the end. */
if (emptyslot < 0) {
emptyslot = sfs_dir_nentries(sv);
}
/* Set up the entry. */
bzero(&sd, sizeof(sd));
sd.sfd_ino = ino;
strcpy(sd.sfd_name, name);
/* Set up the entry. */
bzero(&sd, sizeof(sd));
sd.sfd_ino = ino;
strcpy(sd.sfd_name, name);
/* Hand back the slot, if so requested. */
if (slot) {
*slot = emptyslot;
}
/* Hand back the slot, if so requested. */
if (slot) {
*slot = emptyslot;
}
/* Write the entry. */
return sfs_writedir(sv, emptyslot, &sd);
/* Write the entry. */
return sfs_writedir(sv, emptyslot, &sd);
}
/*
* Unlink a name in a directory, by slot number.
*/
int
sfs_dir_unlink(struct sfs_vnode *sv, int slot)
{
struct sfs_direntry sd;
int sfs_dir_unlink(struct sfs_vnode *sv, int slot) {
struct sfs_direntry sd;
/* Initialize a suitable directory entry... */
bzero(&sd, sizeof(sd));
sd.sfd_ino = SFS_NOINO;
/* Initialize a suitable directory entry... */
bzero(&sd, sizeof(sd));
sd.sfd_ino = SFS_NOINO;
/* ... and write it */
return sfs_writedir(sv, slot, &sd);
/* ... and write it */
return sfs_writedir(sv, slot, &sd);
}
/*
* Look for a name in a directory and hand back a vnode for the
* file, if there is one.
*/
int
sfs_lookonce(struct sfs_vnode *sv, const char *name,
struct sfs_vnode **ret,
int *slot)
{
struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data;
uint32_t ino;
int result;
int sfs_lookonce(struct sfs_vnode *sv, const char *name, struct sfs_vnode **ret,
int *slot) {
struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data;
uint32_t ino;
int result;
result = sfs_dir_findname(sv, name, &ino, slot, NULL);
if (result) {
return result;
}
result = sfs_dir_findname(sv, name, &ino, slot, NULL);
if (result) {
return result;
}
result = sfs_loadvnode(sfs, ino, SFS_TYPE_INVAL, ret);
if (result) {
return result;
}
result = sfs_loadvnode(sfs, ino, SFS_TYPE_INVAL, ret);
if (result) {
return result;
}
if ((*ret)->sv_i.sfi_linkcount == 0) {
panic("sfs: %s: name %s (inode %u) in dir %u has "
"linkcount 0\n", sfs->sfs_sb.sb_volname,
name, (*ret)->sv_ino, sv->sv_ino);
}
if ((*ret)->sv_i.sfi_linkcount == 0) {
panic("sfs: %s: name %s (inode %u) in dir %u has "
"linkcount 0\n",
sfs->sfs_sb.sb_volname, name, (*ret)->sv_ino, sv->sv_ino);
}
return 0;
return 0;
}

View File

@@ -44,11 +44,10 @@
#include <sfs.h>
#include "sfsprivate.h"
/* Shortcuts for the size macros in kern/sfs.h */
#define SFS_FS_NBLOCKS(sfs) ((sfs)->sfs_sb.sb_nblocks)
#define SFS_FS_FREEMAPBITS(sfs) SFS_FREEMAPBITS(SFS_FS_NBLOCKS(sfs))
#define SFS_FS_FREEMAPBLOCKS(sfs) SFS_FREEMAPBLOCKS(SFS_FS_NBLOCKS(sfs))
#define SFS_FS_NBLOCKS(sfs) ((sfs)->sfs_sb.sb_nblocks)
#define SFS_FS_FREEMAPBITS(sfs) SFS_FREEMAPBITS(SFS_FS_NBLOCKS(sfs))
#define SFS_FS_FREEMAPBLOCKS(sfs) SFS_FREEMAPBLOCKS(SFS_FS_NBLOCKS(sfs))
/*
* Routine for doing I/O (reads or writes) on the free block bitmap.
@@ -67,170 +66,152 @@
* The sectors used by the superblock and the bitmap itself are
* likewise marked in use by mksfs.
*/
static
int
sfs_freemapio(struct sfs_fs *sfs, enum uio_rw rw)
{
uint32_t j, freemapblocks;
char *freemapdata;
int result;
static int sfs_freemapio(struct sfs_fs *sfs, enum uio_rw rw) {
uint32_t j, freemapblocks;
char *freemapdata;
int result;
/* Number of blocks in the free block bitmap. */
freemapblocks = SFS_FS_FREEMAPBLOCKS(sfs);
/* Number of blocks in the free block bitmap. */
freemapblocks = SFS_FS_FREEMAPBLOCKS(sfs);
/* Pointer to our freemap data in memory. */
freemapdata = bitmap_getdata(sfs->sfs_freemap);
/* Pointer to our freemap data in memory. */
freemapdata = bitmap_getdata(sfs->sfs_freemap);
/* For each block in the free block bitmap... */
for (j=0; j<freemapblocks; j++) {
/* For each block in the free block bitmap... */
for (j = 0; j < freemapblocks; j++) {
/* Get a pointer to its data */
void *ptr = freemapdata + j*SFS_BLOCKSIZE;
/* Get a pointer to its data */
void *ptr = freemapdata + j * SFS_BLOCKSIZE;
/* and read or write it. The freemap starts at sector 2. */
if (rw == UIO_READ) {
result = sfs_readblock(sfs, SFS_FREEMAP_START+j, ptr,
SFS_BLOCKSIZE);
}
else {
result = sfs_writeblock(sfs, SFS_FREEMAP_START+j, ptr,
SFS_BLOCKSIZE);
}
/* and read or write it. The freemap starts at sector 2. */
if (rw == UIO_READ) {
result = sfs_readblock(sfs, SFS_FREEMAP_START + j, ptr, SFS_BLOCKSIZE);
} else {
result = sfs_writeblock(sfs, SFS_FREEMAP_START + j, ptr, SFS_BLOCKSIZE);
}
/* If we failed, stop. */
if (result) {
return result;
}
}
return 0;
/* If we failed, stop. */
if (result) {
return result;
}
}
return 0;
}
/*
* Sync routine for the vnode table.
*/
static
int
sfs_sync_vnodes(struct sfs_fs *sfs)
{
unsigned i, num;
static int sfs_sync_vnodes(struct sfs_fs *sfs) {
unsigned i, num;
/* Go over the array of loaded vnodes, syncing as we go. */
num = vnodearray_num(sfs->sfs_vnodes);
for (i=0; i<num; i++) {
struct vnode *v = vnodearray_get(sfs->sfs_vnodes, i);
VOP_FSYNC(v);
}
return 0;
/* Go over the array of loaded vnodes, syncing as we go. */
num = vnodearray_num(sfs->sfs_vnodes);
for (i = 0; i < num; i++) {
struct vnode *v = vnodearray_get(sfs->sfs_vnodes, i);
VOP_FSYNC(v);
}
return 0;
}
/*
* Sync routine for the freemap.
*/
static
int
sfs_sync_freemap(struct sfs_fs *sfs)
{
int result;
static int sfs_sync_freemap(struct sfs_fs *sfs) {
int result;
if (sfs->sfs_freemapdirty) {
result = sfs_freemapio(sfs, UIO_WRITE);
if (result) {
return result;
}
sfs->sfs_freemapdirty = false;
}
if (sfs->sfs_freemapdirty) {
result = sfs_freemapio(sfs, UIO_WRITE);
if (result) {
return result;
}
sfs->sfs_freemapdirty = false;
}
return 0;
return 0;
}
/*
* Sync routine for the superblock.
*/
static
int
sfs_sync_superblock(struct sfs_fs *sfs)
{
int result;
static int sfs_sync_superblock(struct sfs_fs *sfs) {
int result;
if (sfs->sfs_superdirty) {
result = sfs_writeblock(sfs, SFS_SUPER_BLOCK, &sfs->sfs_sb,
sizeof(sfs->sfs_sb));
if (result) {
return result;
}
sfs->sfs_superdirty = false;
}
return 0;
if (sfs->sfs_superdirty) {
result =
sfs_writeblock(sfs, SFS_SUPER_BLOCK, &sfs->sfs_sb, sizeof(sfs->sfs_sb));
if (result) {
return result;
}
sfs->sfs_superdirty = false;
}
return 0;
}
/*
* Sync routine. This is what gets invoked if you do FS_SYNC on the
* sfs filesystem structure.
*/
static
int
sfs_sync(struct fs *fs)
{
struct sfs_fs *sfs;
int result;
static int sfs_sync(struct fs *fs) {
struct sfs_fs *sfs;
int result;
vfs_biglock_acquire();
vfs_biglock_acquire();
/*
* Get the sfs_fs from the generic abstract fs.
*
* Note that the abstract struct fs, which is all the VFS
* layer knows about, is actually a member of struct sfs_fs.
* The pointer in the struct fs points back to the top of the
* struct sfs_fs - essentially the same object. This can be a
* little confusing at first.
*
* The following diagram may help:
*
* struct sfs_fs <-------------\
* : |
* : sfs_absfs (struct fs) | <------\
* : : | |
* : : various members | |
* : : | |
* : : fs_data ----------/ |
* : : ...|...
* : . VFS .
* : . layer .
* : other members .......
* :
* :
*
* This construct is repeated with vnodes and devices and other
* similar things all over the place in OS/161, so taking the
* time to straighten it out in your mind is worthwhile.
*/
/*
* Get the sfs_fs from the generic abstract fs.
*
* Note that the abstract struct fs, which is all the VFS
* layer knows about, is actually a member of struct sfs_fs.
* The pointer in the struct fs points back to the top of the
* struct sfs_fs - essentially the same object. This can be a
* little confusing at first.
*
* The following diagram may help:
*
* struct sfs_fs <-------------\
* : |
* : sfs_absfs (struct fs) | <------\
* : : | |
* : : various members | |
* : : | |
* : : fs_data ----------/ |
* : : ...|...
* : . VFS .
* : . layer .
* : other members .......
* :
* :
*
* This construct is repeated with vnodes and devices and other
* similar things all over the place in OS/161, so taking the
* time to straighten it out in your mind is worthwhile.
*/
sfs = fs->fs_data;
sfs = fs->fs_data;
/* If any vnodes need to be written, write them. */
result = sfs_sync_vnodes(sfs);
if (result) {
vfs_biglock_release();
return result;
}
/* If any vnodes need to be written, write them. */
result = sfs_sync_vnodes(sfs);
if (result) {
vfs_biglock_release();
return result;
}
/* If the free block map needs to be written, write it. */
result = sfs_sync_freemap(sfs);
if (result) {
vfs_biglock_release();
return result;
}
/* If the free block map needs to be written, write it. */
result = sfs_sync_freemap(sfs);
if (result) {
vfs_biglock_release();
return result;
}
/* If the superblock needs to be written, write it. */
result = sfs_sync_superblock(sfs);
if (result) {
vfs_biglock_release();
return result;
}
/* If the superblock needs to be written, write it. */
result = sfs_sync_superblock(sfs);
if (result) {
vfs_biglock_release();
return result;
}
vfs_biglock_release();
return 0;
vfs_biglock_release();
return 0;
}
/*
@@ -238,33 +219,27 @@ sfs_sync(struct fs *fs)
* to by their volume name followed by a colon as well as the name
* of the device they're mounted on.
*/
static
const char *
sfs_getvolname(struct fs *fs)
{
struct sfs_fs *sfs = fs->fs_data;
const char *ret;
static const char *sfs_getvolname(struct fs *fs) {
struct sfs_fs *sfs = fs->fs_data;
const char *ret;
vfs_biglock_acquire();
ret = sfs->sfs_sb.sb_volname;
vfs_biglock_release();
vfs_biglock_acquire();
ret = sfs->sfs_sb.sb_volname;
vfs_biglock_release();
return ret;
return ret;
}
/*
* Destructor for struct sfs_fs.
*/
static
void
sfs_fs_destroy(struct sfs_fs *sfs)
{
if (sfs->sfs_freemap != NULL) {
bitmap_destroy(sfs->sfs_freemap);
}
vnodearray_destroy(sfs->sfs_vnodes);
KASSERT(sfs->sfs_device == NULL);
kfree(sfs);
static void sfs_fs_destroy(struct sfs_fs *sfs) {
if (sfs->sfs_freemap != NULL) {
bitmap_destroy(sfs->sfs_freemap);
}
vnodearray_destroy(sfs->sfs_vnodes);
KASSERT(sfs->sfs_device == NULL);
kfree(sfs);
}
/*
@@ -272,43 +247,40 @@ sfs_fs_destroy(struct sfs_fs *sfs)
*
* VFS calls FS_SYNC on the filesystem prior to unmounting it.
*/
static
int
sfs_unmount(struct fs *fs)
{
struct sfs_fs *sfs = fs->fs_data;
static int sfs_unmount(struct fs *fs) {
struct sfs_fs *sfs = fs->fs_data;
vfs_biglock_acquire();
vfs_biglock_acquire();
/* Do we have any files open? If so, can't unmount. */
if (vnodearray_num(sfs->sfs_vnodes) > 0) {
vfs_biglock_release();
return EBUSY;
}
/* Do we have any files open? If so, can't unmount. */
if (vnodearray_num(sfs->sfs_vnodes) > 0) {
vfs_biglock_release();
return EBUSY;
}
/* We should have just had sfs_sync called. */
KASSERT(sfs->sfs_superdirty == false);
KASSERT(sfs->sfs_freemapdirty == false);
/* We should have just had sfs_sync called. */
KASSERT(sfs->sfs_superdirty == false);
KASSERT(sfs->sfs_freemapdirty == false);
/* The vfs layer takes care of the device for us */
sfs->sfs_device = NULL;
/* The vfs layer takes care of the device for us */
sfs->sfs_device = NULL;
/* Destroy the fs object; once we start nuking stuff we can't fail. */
sfs_fs_destroy(sfs);
/* Destroy the fs object; once we start nuking stuff we can't fail. */
sfs_fs_destroy(sfs);
/* nothing else to do */
vfs_biglock_release();
return 0;
/* nothing else to do */
vfs_biglock_release();
return 0;
}
/*
* File system operations table.
*/
static const struct fs_ops sfs_fsops = {
.fsop_sync = sfs_sync,
.fsop_getvolname = sfs_getvolname,
.fsop_getroot = sfs_getroot,
.fsop_unmount = sfs_unmount,
.fsop_sync = sfs_sync,
.fsop_getvolname = sfs_getvolname,
.fsop_getroot = sfs_getroot,
.fsop_unmount = sfs_unmount,
};
/*
@@ -316,56 +288,53 @@ static const struct fs_ops sfs_fsops = {
* but skips stuff that requires reading the volume, like allocating
* the freemap.
*/
static
struct sfs_fs *
sfs_fs_create(void)
{
struct sfs_fs *sfs;
static struct sfs_fs *sfs_fs_create(void) {
struct sfs_fs *sfs;
/*
* Make sure our on-disk structures aren't messed up
*/
COMPILE_ASSERT(sizeof(struct sfs_superblock)==SFS_BLOCKSIZE);
COMPILE_ASSERT(sizeof(struct sfs_dinode)==SFS_BLOCKSIZE);
COMPILE_ASSERT(SFS_BLOCKSIZE % sizeof(struct sfs_direntry) == 0);
/*
* Make sure our on-disk structures aren't messed up
*/
COMPILE_ASSERT(sizeof(struct sfs_superblock) == SFS_BLOCKSIZE);
COMPILE_ASSERT(sizeof(struct sfs_dinode) == SFS_BLOCKSIZE);
COMPILE_ASSERT(SFS_BLOCKSIZE % sizeof(struct sfs_direntry) == 0);
/* Allocate object */
sfs = kmalloc(sizeof(struct sfs_fs));
if (sfs==NULL) {
goto fail;
}
/* Allocate object */
sfs = kmalloc(sizeof(struct sfs_fs));
if (sfs == NULL) {
goto fail;
}
/*
* Fill in fields
*/
/*
* Fill in fields
*/
/* abstract vfs-level fs */
sfs->sfs_absfs.fs_data = sfs;
sfs->sfs_absfs.fs_ops = &sfs_fsops;
/* abstract vfs-level fs */
sfs->sfs_absfs.fs_data = sfs;
sfs->sfs_absfs.fs_ops = &sfs_fsops;
/* superblock */
/* (ignore sfs_super, we'll read in over it shortly) */
sfs->sfs_superdirty = false;
/* superblock */
/* (ignore sfs_super, we'll read in over it shortly) */
sfs->sfs_superdirty = false;
/* device we mount on */
sfs->sfs_device = NULL;
/* device we mount on */
sfs->sfs_device = NULL;
/* vnode table */
sfs->sfs_vnodes = vnodearray_create();
if (sfs->sfs_vnodes == NULL) {
goto cleanup_object;
}
/* vnode table */
sfs->sfs_vnodes = vnodearray_create();
if (sfs->sfs_vnodes == NULL) {
goto cleanup_object;
}
/* freemap */
sfs->sfs_freemap = NULL;
sfs->sfs_freemapdirty = false;
/* freemap */
sfs->sfs_freemap = NULL;
sfs->sfs_freemapdirty = false;
return sfs;
return sfs;
cleanup_object:
kfree(sfs);
kfree(sfs);
fail:
return NULL;
return NULL;
}
/*
@@ -381,101 +350,95 @@ fail:
* filesystems with the same name mounted at once, or two filesystems
* mounted on the same device at once.
*/
static
int
sfs_domount(void *options, struct device *dev, struct fs **ret)
{
int result;
struct sfs_fs *sfs;
static int sfs_domount(void *options, struct device *dev, struct fs **ret) {
int result;
struct sfs_fs *sfs;
vfs_biglock_acquire();
vfs_biglock_acquire();
/* We don't pass any options through mount */
(void)options;
/* We don't pass any options through mount */
(void)options;
/*
* We can't mount on devices with the wrong sector size.
*
* (Note: for all intents and purposes here, "sector" and
* "block" are interchangeable terms. Technically a filesystem
* block may be composed of several hardware sectors, but we
* don't do that in sfs.)
*/
if (dev->d_blocksize != SFS_BLOCKSIZE) {
vfs_biglock_release();
kprintf("sfs: Cannot mount on device with blocksize %zu\n",
dev->d_blocksize);
return ENXIO;
}
/*
* We can't mount on devices with the wrong sector size.
*
* (Note: for all intents and purposes here, "sector" and
* "block" are interchangeable terms. Technically a filesystem
* block may be composed of several hardware sectors, but we
* don't do that in sfs.)
*/
if (dev->d_blocksize != SFS_BLOCKSIZE) {
vfs_biglock_release();
kprintf("sfs: Cannot mount on device with blocksize %zu\n",
dev->d_blocksize);
return ENXIO;
}
sfs = sfs_fs_create();
if (sfs == NULL) {
vfs_biglock_release();
return ENOMEM;
}
sfs = sfs_fs_create();
if (sfs == NULL) {
vfs_biglock_release();
return ENOMEM;
}
/* Set the device so we can use sfs_readblock() */
sfs->sfs_device = dev;
/* Set the device so we can use sfs_readblock() */
sfs->sfs_device = dev;
/* Load superblock */
result = sfs_readblock(sfs, SFS_SUPER_BLOCK, &sfs->sfs_sb,
sizeof(sfs->sfs_sb));
if (result) {
sfs->sfs_device = NULL;
sfs_fs_destroy(sfs);
vfs_biglock_release();
return result;
}
/* Load superblock */
result =
sfs_readblock(sfs, SFS_SUPER_BLOCK, &sfs->sfs_sb, sizeof(sfs->sfs_sb));
if (result) {
sfs->sfs_device = NULL;
sfs_fs_destroy(sfs);
vfs_biglock_release();
return result;
}
/* Make some simple sanity checks */
/* Make some simple sanity checks */
if (sfs->sfs_sb.sb_magic != SFS_MAGIC) {
kprintf("sfs: Wrong magic number in superblock "
"(0x%x, should be 0x%x)\n",
sfs->sfs_sb.sb_magic,
SFS_MAGIC);
sfs->sfs_device = NULL;
sfs_fs_destroy(sfs);
vfs_biglock_release();
return EINVAL;
}
if (sfs->sfs_sb.sb_magic != SFS_MAGIC) {
kprintf("sfs: Wrong magic number in superblock "
"(0x%x, should be 0x%x)\n",
sfs->sfs_sb.sb_magic, SFS_MAGIC);
sfs->sfs_device = NULL;
sfs_fs_destroy(sfs);
vfs_biglock_release();
return EINVAL;
}
if (sfs->sfs_sb.sb_nblocks > dev->d_blocks) {
kprintf("sfs: warning - fs has %u blocks, device has %u\n",
sfs->sfs_sb.sb_nblocks, dev->d_blocks);
}
if (sfs->sfs_sb.sb_nblocks > dev->d_blocks) {
kprintf("sfs: warning - fs has %u blocks, device has %u\n",
sfs->sfs_sb.sb_nblocks, dev->d_blocks);
}
/* Ensure null termination of the volume name */
sfs->sfs_sb.sb_volname[sizeof(sfs->sfs_sb.sb_volname)-1] = 0;
/* Ensure null termination of the volume name */
sfs->sfs_sb.sb_volname[sizeof(sfs->sfs_sb.sb_volname) - 1] = 0;
/* Load free block bitmap */
sfs->sfs_freemap = bitmap_create(SFS_FS_FREEMAPBITS(sfs));
if (sfs->sfs_freemap == NULL) {
sfs->sfs_device = NULL;
sfs_fs_destroy(sfs);
vfs_biglock_release();
return ENOMEM;
}
result = sfs_freemapio(sfs, UIO_READ);
if (result) {
sfs->sfs_device = NULL;
sfs_fs_destroy(sfs);
vfs_biglock_release();
return result;
}
/* Load free block bitmap */
sfs->sfs_freemap = bitmap_create(SFS_FS_FREEMAPBITS(sfs));
if (sfs->sfs_freemap == NULL) {
sfs->sfs_device = NULL;
sfs_fs_destroy(sfs);
vfs_biglock_release();
return ENOMEM;
}
result = sfs_freemapio(sfs, UIO_READ);
if (result) {
sfs->sfs_device = NULL;
sfs_fs_destroy(sfs);
vfs_biglock_release();
return result;
}
/* Hand back the abstract fs */
*ret = &sfs->sfs_absfs;
/* Hand back the abstract fs */
*ret = &sfs->sfs_absfs;
vfs_biglock_release();
return 0;
vfs_biglock_release();
return 0;
}
/*
* Actual function called from high-level code to mount an sfs.
*/
int
sfs_mount(const char *device)
{
return vfs_mount(device, NULL, sfs_domount);
int sfs_mount(const char *device) {
return vfs_mount(device, NULL, sfs_domount);
}

View File

@@ -39,25 +39,21 @@
#include <sfs.h>
#include "sfsprivate.h"
/*
* Write an on-disk inode structure back out to disk.
*/
int
sfs_sync_inode(struct sfs_vnode *sv)
{
struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data;
int result;
int sfs_sync_inode(struct sfs_vnode *sv) {
struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data;
int result;
if (sv->sv_dirty) {
result = sfs_writeblock(sfs, sv->sv_ino, &sv->sv_i,
sizeof(sv->sv_i));
if (result) {
return result;
}
sv->sv_dirty = false;
}
return 0;
if (sv->sv_dirty) {
result = sfs_writeblock(sfs, sv->sv_ino, &sv->sv_i, sizeof(sv->sv_i));
if (result) {
return result;
}
sv->sv_dirty = false;
}
return 0;
}
/*
@@ -65,256 +61,249 @@ sfs_sync_inode(struct sfs_vnode *sv)
*
* This function should try to avoid returning errors other than EBUSY.
*/
int
sfs_reclaim(struct vnode *v)
{
struct sfs_vnode *sv = v->vn_data;
struct sfs_fs *sfs = v->vn_fs->fs_data;
unsigned ix, i, num;
int result;
int sfs_reclaim(struct vnode *v) {
struct sfs_vnode *sv = v->vn_data;
struct sfs_fs *sfs = v->vn_fs->fs_data;
unsigned ix, i, num;
int result;
vfs_biglock_acquire();
vfs_biglock_acquire();
/*
* Make sure someone else hasn't picked up the vnode since the
* decision was made to reclaim it. (You must also synchronize
* this with sfs_loadvnode.)
*/
spinlock_acquire(&v->vn_countlock);
if (v->vn_refcount != 1) {
/*
* Make sure someone else hasn't picked up the vnode since the
* decision was made to reclaim it. (You must also synchronize
* this with sfs_loadvnode.)
*/
spinlock_acquire(&v->vn_countlock);
if (v->vn_refcount != 1) {
/* consume the reference VOP_DECREF gave us */
KASSERT(v->vn_refcount>1);
v->vn_refcount--;
/* consume the reference VOP_DECREF gave us */
KASSERT(v->vn_refcount > 1);
v->vn_refcount--;
spinlock_release(&v->vn_countlock);
vfs_biglock_release();
return EBUSY;
}
spinlock_release(&v->vn_countlock);
spinlock_release(&v->vn_countlock);
vfs_biglock_release();
return EBUSY;
}
spinlock_release(&v->vn_countlock);
/* If there are no on-disk references to the file either, erase it. */
if (sv->sv_i.sfi_linkcount == 0) {
result = sfs_itrunc(sv, 0);
if (result) {
vfs_biglock_release();
return result;
}
}
/* If there are no on-disk references to the file either, erase it. */
if (sv->sv_i.sfi_linkcount == 0) {
result = sfs_itrunc(sv, 0);
if (result) {
vfs_biglock_release();
return result;
}
}
/* Sync the inode to disk */
result = sfs_sync_inode(sv);
if (result) {
vfs_biglock_release();
return result;
}
/* Sync the inode to disk */
result = sfs_sync_inode(sv);
if (result) {
vfs_biglock_release();
return result;
}
/* If there are no on-disk references, discard the inode */
if (sv->sv_i.sfi_linkcount==0) {
sfs_bfree(sfs, sv->sv_ino);
}
/* If there are no on-disk references, discard the inode */
if (sv->sv_i.sfi_linkcount == 0) {
sfs_bfree(sfs, sv->sv_ino);
}
/* Remove the vnode structure from the table in the struct sfs_fs. */
num = vnodearray_num(sfs->sfs_vnodes);
ix = num;
for (i=0; i<num; i++) {
struct vnode *v2 = vnodearray_get(sfs->sfs_vnodes, i);
struct sfs_vnode *sv2 = v2->vn_data;
if (sv2 == sv) {
ix = i;
break;
}
}
if (ix == num) {
panic("sfs: %s: reclaim vnode %u not in vnode pool\n",
sfs->sfs_sb.sb_volname, sv->sv_ino);
}
vnodearray_remove(sfs->sfs_vnodes, ix);
/* Remove the vnode structure from the table in the struct sfs_fs. */
num = vnodearray_num(sfs->sfs_vnodes);
ix = num;
for (i = 0; i < num; i++) {
struct vnode *v2 = vnodearray_get(sfs->sfs_vnodes, i);
struct sfs_vnode *sv2 = v2->vn_data;
if (sv2 == sv) {
ix = i;
break;
}
}
if (ix == num) {
panic("sfs: %s: reclaim vnode %u not in vnode pool\n",
sfs->sfs_sb.sb_volname, sv->sv_ino);
}
vnodearray_remove(sfs->sfs_vnodes, ix);
vnode_cleanup(&sv->sv_absvn);
vnode_cleanup(&sv->sv_absvn);
vfs_biglock_release();
vfs_biglock_release();
/* Release the storage for the vnode structure itself. */
kfree(sv);
/* Release the storage for the vnode structure itself. */
kfree(sv);
/* Done */
return 0;
/* Done */
return 0;
}
/*
* Function to load a inode into memory as a vnode, or dig up one
* that's already resident.
*/
int
sfs_loadvnode(struct sfs_fs *sfs, uint32_t ino, int forcetype,
struct sfs_vnode **ret)
{
struct vnode *v;
struct sfs_vnode *sv;
const struct vnode_ops *ops;
unsigned i, num;
int result;
int sfs_loadvnode(struct sfs_fs *sfs, uint32_t ino, int forcetype,
struct sfs_vnode **ret) {
struct vnode *v;
struct sfs_vnode *sv;
const struct vnode_ops *ops;
unsigned i, num;
int result;
/* Look in the vnodes table */
num = vnodearray_num(sfs->sfs_vnodes);
/* Look in the vnodes table */
num = vnodearray_num(sfs->sfs_vnodes);
/* Linear search. Is this too slow? You decide. */
for (i=0; i<num; i++) {
v = vnodearray_get(sfs->sfs_vnodes, i);
sv = v->vn_data;
/* Linear search. Is this too slow? You decide. */
for (i = 0; i < num; i++) {
v = vnodearray_get(sfs->sfs_vnodes, i);
sv = v->vn_data;
/* Every inode in memory must be in an allocated block */
if (!sfs_bused(sfs, sv->sv_ino)) {
panic("sfs: %s: Found inode %u in unallocated block\n",
sfs->sfs_sb.sb_volname, sv->sv_ino);
}
/* Every inode in memory must be in an allocated block */
if (!sfs_bused(sfs, sv->sv_ino)) {
panic("sfs: %s: Found inode %u in unallocated block\n",
sfs->sfs_sb.sb_volname, sv->sv_ino);
}
if (sv->sv_ino==ino) {
/* Found */
if (sv->sv_ino == ino) {
/* Found */
/* forcetype is only allowed when creating objects */
KASSERT(forcetype==SFS_TYPE_INVAL);
/* forcetype is only allowed when creating objects */
KASSERT(forcetype == SFS_TYPE_INVAL);
VOP_INCREF(&sv->sv_absvn);
*ret = sv;
return 0;
}
}
VOP_INCREF(&sv->sv_absvn);
*ret = sv;
return 0;
}
}
/* Didn't have it loaded; load it */
/* Didn't have it loaded; load it */
sv = kmalloc(sizeof(struct sfs_vnode));
if (sv==NULL) {
return ENOMEM;
}
sv = kmalloc(sizeof(struct sfs_vnode));
if (sv == NULL) {
return ENOMEM;
}
/* Must be in an allocated block */
if (!sfs_bused(sfs, ino)) {
panic("sfs: %s: Tried to load inode %u from "
"unallocated block\n", sfs->sfs_sb.sb_volname, ino);
}
/* Must be in an allocated block */
if (!sfs_bused(sfs, ino)) {
panic("sfs: %s: Tried to load inode %u from "
"unallocated block\n",
sfs->sfs_sb.sb_volname, ino);
}
/* Read the block the inode is in */
result = sfs_readblock(sfs, ino, &sv->sv_i, sizeof(sv->sv_i));
if (result) {
kfree(sv);
return result;
}
/* Read the block the inode is in */
result = sfs_readblock(sfs, ino, &sv->sv_i, sizeof(sv->sv_i));
if (result) {
kfree(sv);
return result;
}
/* Not dirty yet */
sv->sv_dirty = false;
/* Not dirty yet */
sv->sv_dirty = false;
/*
* FORCETYPE is set if we're creating a new file, because the
* block on disk will have been zeroed out by sfs_balloc and
* thus the type recorded there will be SFS_TYPE_INVAL.
*/
if (forcetype != SFS_TYPE_INVAL) {
KASSERT(sv->sv_i.sfi_type == SFS_TYPE_INVAL);
sv->sv_i.sfi_type = forcetype;
sv->sv_dirty = true;
}
/*
* FORCETYPE is set if we're creating a new file, because the
* block on disk will have been zeroed out by sfs_balloc and
* thus the type recorded there will be SFS_TYPE_INVAL.
*/
if (forcetype != SFS_TYPE_INVAL) {
KASSERT(sv->sv_i.sfi_type == SFS_TYPE_INVAL);
sv->sv_i.sfi_type = forcetype;
sv->sv_dirty = true;
}
/*
* Choose the function table based on the object type.
*/
switch (sv->sv_i.sfi_type) {
case SFS_TYPE_FILE:
ops = &sfs_fileops;
break;
case SFS_TYPE_DIR:
ops = &sfs_dirops;
break;
default:
panic("sfs: %s: loadvnode: Invalid inode type "
"(inode %u, type %u)\n", sfs->sfs_sb.sb_volname,
ino, sv->sv_i.sfi_type);
}
/*
* Choose the function table based on the object type.
*/
switch (sv->sv_i.sfi_type) {
case SFS_TYPE_FILE:
ops = &sfs_fileops;
break;
case SFS_TYPE_DIR:
ops = &sfs_dirops;
break;
default:
panic("sfs: %s: loadvnode: Invalid inode type "
"(inode %u, type %u)\n",
sfs->sfs_sb.sb_volname, ino, sv->sv_i.sfi_type);
}
/* Call the common vnode initializer */
result = vnode_init(&sv->sv_absvn, ops, &sfs->sfs_absfs, sv);
if (result) {
kfree(sv);
return result;
}
/* Call the common vnode initializer */
result = vnode_init(&sv->sv_absvn, ops, &sfs->sfs_absfs, sv);
if (result) {
kfree(sv);
return result;
}
/* Set the other fields in our vnode structure */
sv->sv_ino = ino;
/* Set the other fields in our vnode structure */
sv->sv_ino = ino;
/* Add it to our table */
result = vnodearray_add(sfs->sfs_vnodes, &sv->sv_absvn, NULL);
if (result) {
vnode_cleanup(&sv->sv_absvn);
kfree(sv);
return result;
}
/* Add it to our table */
result = vnodearray_add(sfs->sfs_vnodes, &sv->sv_absvn, NULL);
if (result) {
vnode_cleanup(&sv->sv_absvn);
kfree(sv);
return result;
}
/* Hand it back */
*ret = sv;
return 0;
/* Hand it back */
*ret = sv;
return 0;
}
/*
* Create a new filesystem object and hand back its vnode.
*/
int
sfs_makeobj(struct sfs_fs *sfs, int type, struct sfs_vnode **ret)
{
uint32_t ino;
int result;
int sfs_makeobj(struct sfs_fs *sfs, int type, struct sfs_vnode **ret) {
uint32_t ino;
int result;
/*
* First, get an inode. (Each inode is a block, and the inode
* number is the block number, so just get a block.)
*/
/*
* First, get an inode. (Each inode is a block, and the inode
* number is the block number, so just get a block.)
*/
result = sfs_balloc(sfs, &ino);
if (result) {
return result;
}
result = sfs_balloc(sfs, &ino);
if (result) {
return result;
}
/*
* Now load a vnode for it.
*/
/*
* Now load a vnode for it.
*/
result = sfs_loadvnode(sfs, ino, type, ret);
if (result) {
sfs_bfree(sfs, ino);
}
return result;
result = sfs_loadvnode(sfs, ino, type, ret);
if (result) {
sfs_bfree(sfs, ino);
}
return result;
}
/*
* Get vnode for the root of the filesystem.
* The root vnode is always found in block 1 (SFS_ROOTDIR_INO).
*/
int
sfs_getroot(struct fs *fs, struct vnode **ret)
{
struct sfs_fs *sfs = fs->fs_data;
struct sfs_vnode *sv;
int result;
int sfs_getroot(struct fs *fs, struct vnode **ret) {
struct sfs_fs *sfs = fs->fs_data;
struct sfs_vnode *sv;
int result;
vfs_biglock_acquire();
vfs_biglock_acquire();
result = sfs_loadvnode(sfs, SFS_ROOTDIR_INO, SFS_TYPE_INVAL, &sv);
if (result) {
kprintf("sfs: %s: getroot: Cannot load root vnode\n",
sfs->sfs_sb.sb_volname);
vfs_biglock_release();
return result;
}
result = sfs_loadvnode(sfs, SFS_ROOTDIR_INO, SFS_TYPE_INVAL, &sv);
if (result) {
kprintf("sfs: %s: getroot: Cannot load root vnode\n",
sfs->sfs_sb.sb_volname);
vfs_biglock_release();
return result;
}
if (sv->sv_i.sfi_type != SFS_TYPE_DIR) {
kprintf("sfs: %s: getroot: not directory (type %u)\n",
sfs->sfs_sb.sb_volname, sv->sv_i.sfi_type);
vfs_biglock_release();
return EINVAL;
}
if (sv->sv_i.sfi_type != SFS_TYPE_DIR) {
kprintf("sfs: %s: getroot: not directory (type %u)\n",
sfs->sfs_sb.sb_volname, sv->sv_i.sfi_type);
vfs_biglock_release();
return EINVAL;
}
vfs_biglock_release();
vfs_biglock_release();
*ret = &sv->sv_absvn;
return 0;
*ret = &sv->sv_absvn;
return 0;
}

View File

@@ -55,80 +55,67 @@
/*
* Read or write a block, retrying I/O errors.
*/
static
int
sfs_rwblock(struct sfs_fs *sfs, struct uio *uio)
{
int result;
int tries=0;
static int sfs_rwblock(struct sfs_fs *sfs, struct uio *uio) {
int result;
int tries = 0;
KASSERT(vfs_biglock_do_i_hold());
KASSERT(vfs_biglock_do_i_hold());
DEBUG(DB_SFS, "sfs: %s %llu\n",
uio->uio_rw == UIO_READ ? "read" : "write",
uio->uio_offset / SFS_BLOCKSIZE);
DEBUG(DB_SFS, "sfs: %s %llu\n", uio->uio_rw == UIO_READ ? "read" : "write",
uio->uio_offset / SFS_BLOCKSIZE);
retry:
result = DEVOP_IO(sfs->sfs_device, uio);
if (result == EINVAL) {
/*
* This means the sector we requested was out of range,
* or the seek address we gave wasn't sector-aligned,
* or a couple of other things that are our fault.
*/
panic("sfs: %s: DEVOP_IO returned EINVAL\n",
sfs->sfs_sb.sb_volname);
}
if (result == EIO) {
if (tries == 0) {
tries++;
kprintf("sfs: %s: block %llu I/O error, retrying\n",
sfs->sfs_sb.sb_volname,
uio->uio_offset / SFS_BLOCKSIZE);
goto retry;
}
else if (tries < 10) {
tries++;
goto retry;
}
else {
kprintf("sfs: %s: block %llu I/O error, giving up "
"after %d retries\n",
sfs->sfs_sb.sb_volname,
uio->uio_offset / SFS_BLOCKSIZE, tries);
}
}
return result;
retry:
result = DEVOP_IO(sfs->sfs_device, uio);
if (result == EINVAL) {
/*
* This means the sector we requested was out of range,
* or the seek address we gave wasn't sector-aligned,
* or a couple of other things that are our fault.
*/
panic("sfs: %s: DEVOP_IO returned EINVAL\n", sfs->sfs_sb.sb_volname);
}
if (result == EIO) {
if (tries == 0) {
tries++;
kprintf("sfs: %s: block %llu I/O error, retrying\n",
sfs->sfs_sb.sb_volname, uio->uio_offset / SFS_BLOCKSIZE);
goto retry;
} else if (tries < 10) {
tries++;
goto retry;
} else {
kprintf("sfs: %s: block %llu I/O error, giving up "
"after %d retries\n",
sfs->sfs_sb.sb_volname, uio->uio_offset / SFS_BLOCKSIZE, tries);
}
}
return result;
}
/*
* Read a block.
*/
int
sfs_readblock(struct sfs_fs *sfs, daddr_t block, void *data, size_t len)
{
struct iovec iov;
struct uio ku;
int sfs_readblock(struct sfs_fs *sfs, daddr_t block, void *data, size_t len) {
struct iovec iov;
struct uio ku;
KASSERT(len == SFS_BLOCKSIZE);
KASSERT(len == SFS_BLOCKSIZE);
SFSUIO(&iov, &ku, data, block, UIO_READ);
return sfs_rwblock(sfs, &ku);
SFSUIO(&iov, &ku, data, block, UIO_READ);
return sfs_rwblock(sfs, &ku);
}
/*
* Write a block.
*/
int
sfs_writeblock(struct sfs_fs *sfs, daddr_t block, void *data, size_t len)
{
struct iovec iov;
struct uio ku;
int sfs_writeblock(struct sfs_fs *sfs, daddr_t block, void *data, size_t len) {
struct iovec iov;
struct uio ku;
KASSERT(len == SFS_BLOCKSIZE);
KASSERT(len == SFS_BLOCKSIZE);
SFSUIO(&iov, &ku, data, block, UIO_WRITE);
return sfs_rwblock(sfs, &ku);
SFSUIO(&iov, &ku, data, block, UIO_WRITE);
return sfs_rwblock(sfs, &ku);
}
////////////////////////////////////////////////////////////
@@ -145,247 +132,237 @@ sfs_writeblock(struct sfs_fs *sfs, daddr_t block, void *data, size_t len)
* the sector; LEN is the number of bytes to actually read or write.
* UIO is the area to do the I/O into.
*/
static
int
sfs_partialio(struct sfs_vnode *sv, struct uio *uio,
uint32_t skipstart, uint32_t len)
{
/*
* I/O buffer for handling partial sectors.
*
* Note: in real life (and when you've done the fs assignment)
* you would get space from the disk buffer cache for this,
* not use a static area.
*/
static char iobuf[SFS_BLOCKSIZE];
static int sfs_partialio(struct sfs_vnode *sv, struct uio *uio,
uint32_t skipstart, uint32_t len) {
/*
* I/O buffer for handling partial sectors.
*
* Note: in real life (and when you've done the fs assignment)
* you would get space from the disk buffer cache for this,
* not use a static area.
*/
static char iobuf[SFS_BLOCKSIZE];
struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data;
daddr_t diskblock;
uint32_t fileblock;
int result;
struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data;
daddr_t diskblock;
uint32_t fileblock;
int result;
/* Allocate missing blocks if and only if we're writing */
bool doalloc = (uio->uio_rw==UIO_WRITE);
/* Allocate missing blocks if and only if we're writing */
bool doalloc = (uio->uio_rw == UIO_WRITE);
KASSERT(skipstart + len <= SFS_BLOCKSIZE);
KASSERT(skipstart + len <= SFS_BLOCKSIZE);
/* We're using a global static buffer; it had better be locked */
KASSERT(vfs_biglock_do_i_hold());
/* We're using a global static buffer; it had better be locked */
KASSERT(vfs_biglock_do_i_hold());
/* Compute the block offset of this block in the file */
fileblock = uio->uio_offset / SFS_BLOCKSIZE;
/* Compute the block offset of this block in the file */
fileblock = uio->uio_offset / SFS_BLOCKSIZE;
/* Get the disk block number */
result = sfs_bmap(sv, fileblock, doalloc, &diskblock);
if (result) {
return result;
}
/* Get the disk block number */
result = sfs_bmap(sv, fileblock, doalloc, &diskblock);
if (result) {
return result;
}
if (diskblock == 0) {
/*
* There was no block mapped at this point in the file.
* Zero the buffer.
*/
KASSERT(uio->uio_rw == UIO_READ);
bzero(iobuf, sizeof(iobuf));
}
else {
/*
* Read the block.
*/
result = sfs_readblock(sfs, diskblock, iobuf, sizeof(iobuf));
if (result) {
return result;
}
}
if (diskblock == 0) {
/*
* There was no block mapped at this point in the file.
* Zero the buffer.
*/
KASSERT(uio->uio_rw == UIO_READ);
bzero(iobuf, sizeof(iobuf));
} else {
/*
* Read the block.
*/
result = sfs_readblock(sfs, diskblock, iobuf, sizeof(iobuf));
if (result) {
return result;
}
}
/*
* Now perform the requested operation into/out of the buffer.
*/
result = uiomove(iobuf+skipstart, len, uio);
if (result) {
return result;
}
/*
* Now perform the requested operation into/out of the buffer.
*/
result = uiomove(iobuf + skipstart, len, uio);
if (result) {
return result;
}
/*
* If it was a write, write back the modified block.
*/
if (uio->uio_rw == UIO_WRITE) {
result = sfs_writeblock(sfs, diskblock, iobuf, sizeof(iobuf));
if (result) {
return result;
}
}
/*
* If it was a write, write back the modified block.
*/
if (uio->uio_rw == UIO_WRITE) {
result = sfs_writeblock(sfs, diskblock, iobuf, sizeof(iobuf));
if (result) {
return result;
}
}
return 0;
return 0;
}
/*
* Do I/O (either read or write) of a single whole block.
*/
static
int
sfs_blockio(struct sfs_vnode *sv, struct uio *uio)
{
struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data;
daddr_t diskblock;
uint32_t fileblock;
int result;
bool doalloc = (uio->uio_rw==UIO_WRITE);
off_t saveoff;
off_t diskoff;
off_t saveres;
off_t diskres;
static int sfs_blockio(struct sfs_vnode *sv, struct uio *uio) {
struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data;
daddr_t diskblock;
uint32_t fileblock;
int result;
bool doalloc = (uio->uio_rw == UIO_WRITE);
off_t saveoff;
off_t diskoff;
off_t saveres;
off_t diskres;
/* Get the block number within the file */
fileblock = uio->uio_offset / SFS_BLOCKSIZE;
/* Get the block number within the file */
fileblock = uio->uio_offset / SFS_BLOCKSIZE;
/* Look up the disk block number */
result = sfs_bmap(sv, fileblock, doalloc, &diskblock);
if (result) {
return result;
}
/* Look up the disk block number */
result = sfs_bmap(sv, fileblock, doalloc, &diskblock);
if (result) {
return result;
}
if (diskblock == 0) {
/*
* No block - fill with zeros.
*
* We must be reading, or sfs_bmap would have
* allocated a block for us.
*/
KASSERT(uio->uio_rw == UIO_READ);
return uiomovezeros(SFS_BLOCKSIZE, uio);
}
if (diskblock == 0) {
/*
* No block - fill with zeros.
*
* We must be reading, or sfs_bmap would have
* allocated a block for us.
*/
KASSERT(uio->uio_rw == UIO_READ);
return uiomovezeros(SFS_BLOCKSIZE, uio);
}
/*
* Do the I/O directly to the uio region. Save the uio_offset,
* and substitute one that makes sense to the device.
*/
saveoff = uio->uio_offset;
diskoff = diskblock * SFS_BLOCKSIZE;
uio->uio_offset = diskoff;
/*
* Do the I/O directly to the uio region. Save the uio_offset,
* and substitute one that makes sense to the device.
*/
saveoff = uio->uio_offset;
diskoff = diskblock * SFS_BLOCKSIZE;
uio->uio_offset = diskoff;
/*
* Temporarily set the residue to be one block size.
*/
KASSERT(uio->uio_resid >= SFS_BLOCKSIZE);
saveres = uio->uio_resid;
diskres = SFS_BLOCKSIZE;
uio->uio_resid = diskres;
/*
* Temporarily set the residue to be one block size.
*/
KASSERT(uio->uio_resid >= SFS_BLOCKSIZE);
saveres = uio->uio_resid;
diskres = SFS_BLOCKSIZE;
uio->uio_resid = diskres;
result = sfs_rwblock(sfs, uio);
result = sfs_rwblock(sfs, uio);
/*
* Now, restore the original uio_offset and uio_resid and update
* them by the amount of I/O done.
*/
uio->uio_offset = (uio->uio_offset - diskoff) + saveoff;
uio->uio_resid = (uio->uio_resid - diskres) + saveres;
/*
* Now, restore the original uio_offset and uio_resid and update
* them by the amount of I/O done.
*/
uio->uio_offset = (uio->uio_offset - diskoff) + saveoff;
uio->uio_resid = (uio->uio_resid - diskres) + saveres;
return result;
return result;
}
/*
* Do I/O of a whole region of data, whether or not it's block-aligned.
*/
int
sfs_io(struct sfs_vnode *sv, struct uio *uio)
{
uint32_t blkoff;
uint32_t nblocks, i;
int result = 0;
uint32_t origresid, extraresid = 0;
int sfs_io(struct sfs_vnode *sv, struct uio *uio) {
uint32_t blkoff;
uint32_t nblocks, i;
int result = 0;
uint32_t origresid, extraresid = 0;
origresid = uio->uio_resid;
origresid = uio->uio_resid;
/*
* If reading, check for EOF. If we can read a partial area,
* remember how much extra there was in EXTRARESID so we can
* add it back to uio_resid at the end.
*/
if (uio->uio_rw == UIO_READ) {
off_t size = sv->sv_i.sfi_size;
off_t endpos = uio->uio_offset + uio->uio_resid;
/*
* If reading, check for EOF. If we can read a partial area,
* remember how much extra there was in EXTRARESID so we can
* add it back to uio_resid at the end.
*/
if (uio->uio_rw == UIO_READ) {
off_t size = sv->sv_i.sfi_size;
off_t endpos = uio->uio_offset + uio->uio_resid;
if (uio->uio_offset >= size) {
/* At or past EOF - just return */
return 0;
}
if (uio->uio_offset >= size) {
/* At or past EOF - just return */
return 0;
}
if (endpos > size) {
extraresid = endpos - size;
KASSERT(uio->uio_resid > extraresid);
uio->uio_resid -= extraresid;
}
}
if (endpos > size) {
extraresid = endpos - size;
KASSERT(uio->uio_resid > extraresid);
uio->uio_resid -= extraresid;
}
}
/*
* First, do any leading partial block.
*/
blkoff = uio->uio_offset % SFS_BLOCKSIZE;
if (blkoff != 0) {
/* Number of bytes at beginning of block to skip */
uint32_t skip = blkoff;
/*
* First, do any leading partial block.
*/
blkoff = uio->uio_offset % SFS_BLOCKSIZE;
if (blkoff != 0) {
/* Number of bytes at beginning of block to skip */
uint32_t skip = blkoff;
/* Number of bytes to read/write after that point */
uint32_t len = SFS_BLOCKSIZE - blkoff;
/* Number of bytes to read/write after that point */
uint32_t len = SFS_BLOCKSIZE - blkoff;
/* ...which might be less than the rest of the block */
if (len > uio->uio_resid) {
len = uio->uio_resid;
}
/* ...which might be less than the rest of the block */
if (len > uio->uio_resid) {
len = uio->uio_resid;
}
/* Call sfs_partialio() to do it. */
result = sfs_partialio(sv, uio, skip, len);
if (result) {
goto out;
}
}
/* Call sfs_partialio() to do it. */
result = sfs_partialio(sv, uio, skip, len);
if (result) {
goto out;
}
}
/* If we're done, quit. */
if (uio->uio_resid==0) {
goto out;
}
/* If we're done, quit. */
if (uio->uio_resid == 0) {
goto out;
}
/*
* Now we should be block-aligned. Do the remaining whole blocks.
*/
KASSERT(uio->uio_offset % SFS_BLOCKSIZE == 0);
nblocks = uio->uio_resid / SFS_BLOCKSIZE;
for (i=0; i<nblocks; i++) {
result = sfs_blockio(sv, uio);
if (result) {
goto out;
}
}
/*
* Now we should be block-aligned. Do the remaining whole blocks.
*/
KASSERT(uio->uio_offset % SFS_BLOCKSIZE == 0);
nblocks = uio->uio_resid / SFS_BLOCKSIZE;
for (i = 0; i < nblocks; i++) {
result = sfs_blockio(sv, uio);
if (result) {
goto out;
}
}
/*
* Now do any remaining partial block at the end.
*/
KASSERT(uio->uio_resid < SFS_BLOCKSIZE);
/*
* Now do any remaining partial block at the end.
*/
KASSERT(uio->uio_resid < SFS_BLOCKSIZE);
if (uio->uio_resid > 0) {
result = sfs_partialio(sv, uio, 0, uio->uio_resid);
if (result) {
goto out;
}
}
if (uio->uio_resid > 0) {
result = sfs_partialio(sv, uio, 0, uio->uio_resid);
if (result) {
goto out;
}
}
out:
out:
/* If writing and we did anything, adjust file length */
if (uio->uio_resid != origresid &&
uio->uio_rw == UIO_WRITE &&
uio->uio_offset > (off_t)sv->sv_i.sfi_size) {
sv->sv_i.sfi_size = uio->uio_offset;
sv->sv_dirty = true;
}
/* If writing and we did anything, adjust file length */
if (uio->uio_resid != origresid && uio->uio_rw == UIO_WRITE &&
uio->uio_offset > (off_t)sv->sv_i.sfi_size) {
sv->sv_i.sfi_size = uio->uio_offset;
sv->sv_dirty = true;
}
/* Add in any extra amount we couldn't read because of EOF */
uio->uio_resid += extraresid;
/* Add in any extra amount we couldn't read because of EOF */
uio->uio_resid += extraresid;
/* Done */
return result;
/* Done */
return result;
}
////////////////////////////////////////////////////////////
@@ -402,79 +379,75 @@ sfs_io(struct sfs_vnode *sv, struct uio *uio)
* more advanced things to handle metadata and user data I/O
* differently.
*/
int
sfs_metaio(struct sfs_vnode *sv, off_t actualpos, void *data, size_t len,
enum uio_rw rw)
{
struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data;
off_t endpos;
uint32_t vnblock;
uint32_t blockoffset;
daddr_t diskblock;
bool doalloc;
int result;
int sfs_metaio(struct sfs_vnode *sv, off_t actualpos, void *data, size_t len,
enum uio_rw rw) {
struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data;
off_t endpos;
uint32_t vnblock;
uint32_t blockoffset;
daddr_t diskblock;
bool doalloc;
int result;
/*
* I/O buffer for metadata ops.
*
* Note: in real life (and when you've done the fs assignment) you
* would get space from the disk buffer cache for this, not use a
* static area.
*/
static char metaiobuf[SFS_BLOCKSIZE];
/*
* I/O buffer for metadata ops.
*
* Note: in real life (and when you've done the fs assignment) you
* would get space from the disk buffer cache for this, not use a
* static area.
*/
static char metaiobuf[SFS_BLOCKSIZE];
/* We're using a global static buffer; it had better be locked */
KASSERT(vfs_biglock_do_i_hold());
/* We're using a global static buffer; it had better be locked */
KASSERT(vfs_biglock_do_i_hold());
/* Figure out which block of the vnode (directory, whatever) this is */
vnblock = actualpos / SFS_BLOCKSIZE;
blockoffset = actualpos % SFS_BLOCKSIZE;
/* Figure out which block of the vnode (directory, whatever) this is */
vnblock = actualpos / SFS_BLOCKSIZE;
blockoffset = actualpos % SFS_BLOCKSIZE;
/* Get the disk block number */
doalloc = (rw == UIO_WRITE);
result = sfs_bmap(sv, vnblock, doalloc, &diskblock);
if (result) {
return result;
}
/* Get the disk block number */
doalloc = (rw == UIO_WRITE);
result = sfs_bmap(sv, vnblock, doalloc, &diskblock);
if (result) {
return result;
}
if (diskblock == 0) {
/* Should only get block 0 back if doalloc is false */
KASSERT(rw == UIO_READ);
if (diskblock == 0) {
/* Should only get block 0 back if doalloc is false */
KASSERT(rw == UIO_READ);
/* Sparse file, read as zeros. */
bzero(data, len);
return 0;
}
/* Sparse file, read as zeros. */
bzero(data, len);
return 0;
}
/* Read the block */
result = sfs_readblock(sfs, diskblock, metaiobuf, sizeof(metaiobuf));
if (result) {
return result;
}
/* Read the block */
result = sfs_readblock(sfs, diskblock, metaiobuf, sizeof(metaiobuf));
if (result) {
return result;
}
if (rw == UIO_READ) {
/* Copy out the selected region */
memcpy(data, metaiobuf + blockoffset, len);
}
else {
/* Update the selected region */
memcpy(metaiobuf + blockoffset, data, len);
if (rw == UIO_READ) {
/* Copy out the selected region */
memcpy(data, metaiobuf + blockoffset, len);
} else {
/* Update the selected region */
memcpy(metaiobuf + blockoffset, data, len);
/* Write the block back */
result = sfs_writeblock(sfs, diskblock,
metaiobuf, sizeof(metaiobuf));
if (result) {
return result;
}
/* Write the block back */
result = sfs_writeblock(sfs, diskblock, metaiobuf, sizeof(metaiobuf));
if (result) {
return result;
}
/* Update the vnode size if needed */
endpos = actualpos + len;
if (endpos > (off_t)sv->sv_i.sfi_size) {
sv->sv_i.sfi_size = endpos;
sv->sv_dirty = true;
}
}
/* Update the vnode size if needed */
endpos = actualpos + len;
if (endpos > (off_t)sv->sv_i.sfi_size) {
sv->sv_i.sfi_size = endpos;
sv->sv_dirty = true;
}
}
/* Done */
return 0;
/* Done */
return 0;
}

View File

@@ -48,210 +48,177 @@
/*
* This is called on *each* open().
*/
static
int
sfs_eachopen(struct vnode *v, int openflags)
{
/*
* At this level we do not need to handle O_CREAT, O_EXCL,
* O_TRUNC, or O_APPEND.
*
* Any of O_RDONLY, O_WRONLY, and O_RDWR are valid, so we don't need
* to check that either.
*/
static int sfs_eachopen(struct vnode *v, int openflags) {
/*
* At this level we do not need to handle O_CREAT, O_EXCL,
* O_TRUNC, or O_APPEND.
*
* Any of O_RDONLY, O_WRONLY, and O_RDWR are valid, so we don't need
* to check that either.
*/
(void)v;
(void)openflags;
(void)v;
(void)openflags;
return 0;
return 0;
}
/*
* This is called on *each* open() of a directory.
* Directories may only be open for read.
*/
static
int
sfs_eachopendir(struct vnode *v, int openflags)
{
switch (openflags & O_ACCMODE) {
case O_RDONLY:
break;
case O_WRONLY:
case O_RDWR:
default:
return EISDIR;
}
if (openflags & O_APPEND) {
return EISDIR;
}
static int sfs_eachopendir(struct vnode *v, int openflags) {
switch (openflags & O_ACCMODE) {
case O_RDONLY:
break;
case O_WRONLY:
case O_RDWR:
default:
return EISDIR;
}
if (openflags & O_APPEND) {
return EISDIR;
}
(void)v;
return 0;
(void)v;
return 0;
}
/*
* Called for read(). sfs_io() does the work.
*/
static
int
sfs_read(struct vnode *v, struct uio *uio)
{
struct sfs_vnode *sv = v->vn_data;
int result;
static int sfs_read(struct vnode *v, struct uio *uio) {
struct sfs_vnode *sv = v->vn_data;
int result;
KASSERT(uio->uio_rw==UIO_READ);
KASSERT(uio->uio_rw == UIO_READ);
vfs_biglock_acquire();
result = sfs_io(sv, uio);
vfs_biglock_release();
vfs_biglock_acquire();
result = sfs_io(sv, uio);
vfs_biglock_release();
return result;
return result;
}
/*
* Called for write(). sfs_io() does the work.
*/
static
int
sfs_write(struct vnode *v, struct uio *uio)
{
struct sfs_vnode *sv = v->vn_data;
int result;
static int sfs_write(struct vnode *v, struct uio *uio) {
struct sfs_vnode *sv = v->vn_data;
int result;
KASSERT(uio->uio_rw==UIO_WRITE);
KASSERT(uio->uio_rw == UIO_WRITE);
vfs_biglock_acquire();
result = sfs_io(sv, uio);
vfs_biglock_release();
vfs_biglock_acquire();
result = sfs_io(sv, uio);
vfs_biglock_release();
return result;
return result;
}
/*
* Called for ioctl()
*/
static
int
sfs_ioctl(struct vnode *v, int op, userptr_t data)
{
/*
* No ioctls.
*/
static int sfs_ioctl(struct vnode *v, int op, userptr_t data) {
/*
* No ioctls.
*/
(void)v;
(void)op;
(void)data;
(void)v;
(void)op;
(void)data;
return EINVAL;
return EINVAL;
}
/*
* Called for stat/fstat/lstat.
*/
static
int
sfs_stat(struct vnode *v, struct stat *statbuf)
{
struct sfs_vnode *sv = v->vn_data;
int result;
static int sfs_stat(struct vnode *v, struct stat *statbuf) {
struct sfs_vnode *sv = v->vn_data;
int result;
/* Fill in the stat structure */
bzero(statbuf, sizeof(struct stat));
/* Fill in the stat structure */
bzero(statbuf, sizeof(struct stat));
result = VOP_GETTYPE(v, &statbuf->st_mode);
if (result) {
return result;
}
result = VOP_GETTYPE(v, &statbuf->st_mode);
if (result) {
return result;
}
statbuf->st_size = sv->sv_i.sfi_size;
statbuf->st_nlink = sv->sv_i.sfi_linkcount;
statbuf->st_size = sv->sv_i.sfi_size;
statbuf->st_nlink = sv->sv_i.sfi_linkcount;
/* We don't support this yet */
statbuf->st_blocks = 0;
/* We don't support this yet */
statbuf->st_blocks = 0;
/* Fill in other fields as desired/possible... */
/* Fill in other fields as desired/possible... */
return 0;
return 0;
}
/*
* Return the type of the file (types as per kern/stat.h)
*/
static
int
sfs_gettype(struct vnode *v, uint32_t *ret)
{
struct sfs_vnode *sv = v->vn_data;
struct sfs_fs *sfs = v->vn_fs->fs_data;
static int sfs_gettype(struct vnode *v, uint32_t *ret) {
struct sfs_vnode *sv = v->vn_data;
struct sfs_fs *sfs = v->vn_fs->fs_data;
vfs_biglock_acquire();
vfs_biglock_acquire();
switch (sv->sv_i.sfi_type) {
case SFS_TYPE_FILE:
*ret = S_IFREG;
vfs_biglock_release();
return 0;
case SFS_TYPE_DIR:
*ret = S_IFDIR;
vfs_biglock_release();
return 0;
}
panic("sfs: %s: gettype: Invalid inode type (inode %u, type %u)\n",
sfs->sfs_sb.sb_volname, sv->sv_ino, sv->sv_i.sfi_type);
return EINVAL;
switch (sv->sv_i.sfi_type) {
case SFS_TYPE_FILE:
*ret = S_IFREG;
vfs_biglock_release();
return 0;
case SFS_TYPE_DIR:
*ret = S_IFDIR;
vfs_biglock_release();
return 0;
}
panic("sfs: %s: gettype: Invalid inode type (inode %u, type %u)\n",
sfs->sfs_sb.sb_volname, sv->sv_ino, sv->sv_i.sfi_type);
return EINVAL;
}
/*
* Check if seeking is allowed. The answer is "yes".
*/
static
bool
sfs_isseekable(struct vnode *v)
{
(void)v;
return true;
static bool sfs_isseekable(struct vnode *v) {
(void)v;
return true;
}
/*
* Called for fsync(), and also on filesystem unmount, global sync(),
* and some other cases.
*/
static
int
sfs_fsync(struct vnode *v)
{
struct sfs_vnode *sv = v->vn_data;
int result;
static int sfs_fsync(struct vnode *v) {
struct sfs_vnode *sv = v->vn_data;
int result;
vfs_biglock_acquire();
result = sfs_sync_inode(sv);
vfs_biglock_release();
vfs_biglock_acquire();
result = sfs_sync_inode(sv);
vfs_biglock_release();
return result;
return result;
}
/*
* Called for mmap().
*/
static
int
sfs_mmap(struct vnode *v /* add stuff as needed */)
{
(void)v;
return ENOSYS;
static int sfs_mmap(struct vnode *v /* add stuff as needed */) {
(void)v;
return ENOSYS;
}
/*
* Truncate a file.
*/
static
int
sfs_truncate(struct vnode *v, off_t len)
{
struct sfs_vnode *sv = v->vn_data;
static int sfs_truncate(struct vnode *v, off_t len) {
struct sfs_vnode *sv = v->vn_data;
return sfs_itrunc(sv, len);
return sfs_itrunc(sv, len);
}
/*
@@ -260,90 +227,84 @@ sfs_truncate(struct vnode *v, off_t len)
* and hand back the empty string. (The VFS layer takes care of the
* device name, leading slash, etc.)
*/
static
int
sfs_namefile(struct vnode *vv, struct uio *uio)
{
struct sfs_vnode *sv = vv->vn_data;
KASSERT(sv->sv_ino == SFS_ROOTDIR_INO);
static int sfs_namefile(struct vnode *vv, struct uio *uio) {
struct sfs_vnode *sv = vv->vn_data;
KASSERT(sv->sv_ino == SFS_ROOTDIR_INO);
/* send back the empty string - just return */
/* send back the empty string - just return */
(void)uio;
(void)uio;
return 0;
return 0;
}
/*
* Create a file. If EXCL is set, insist that the filename not already
* exist; otherwise, if it already exists, just open it.
*/
static
int
sfs_creat(struct vnode *v, const char *name, bool excl, mode_t mode,
struct vnode **ret)
{
struct sfs_fs *sfs = v->vn_fs->fs_data;
struct sfs_vnode *sv = v->vn_data;
struct sfs_vnode *newguy;
uint32_t ino;
int result;
static int sfs_creat(struct vnode *v, const char *name, bool excl, mode_t mode,
struct vnode **ret) {
struct sfs_fs *sfs = v->vn_fs->fs_data;
struct sfs_vnode *sv = v->vn_data;
struct sfs_vnode *newguy;
uint32_t ino;
int result;
vfs_biglock_acquire();
vfs_biglock_acquire();
/* Look up the name */
result = sfs_dir_findname(sv, name, &ino, NULL, NULL);
if (result!=0 && result!=ENOENT) {
vfs_biglock_release();
return result;
}
/* Look up the name */
result = sfs_dir_findname(sv, name, &ino, NULL, NULL);
if (result != 0 && result != ENOENT) {
vfs_biglock_release();
return result;
}
/* If it exists and we didn't want it to, fail */
if (result==0 && excl) {
vfs_biglock_release();
return EEXIST;
}
/* If it exists and we didn't want it to, fail */
if (result == 0 && excl) {
vfs_biglock_release();
return EEXIST;
}
if (result==0) {
/* We got something; load its vnode and return */
result = sfs_loadvnode(sfs, ino, SFS_TYPE_INVAL, &newguy);
if (result) {
vfs_biglock_release();
return result;
}
*ret = &newguy->sv_absvn;
vfs_biglock_release();
return 0;
}
if (result == 0) {
/* We got something; load its vnode and return */
result = sfs_loadvnode(sfs, ino, SFS_TYPE_INVAL, &newguy);
if (result) {
vfs_biglock_release();
return result;
}
*ret = &newguy->sv_absvn;
vfs_biglock_release();
return 0;
}
/* Didn't exist - create it */
result = sfs_makeobj(sfs, SFS_TYPE_FILE, &newguy);
if (result) {
vfs_biglock_release();
return result;
}
/* Didn't exist - create it */
result = sfs_makeobj(sfs, SFS_TYPE_FILE, &newguy);
if (result) {
vfs_biglock_release();
return result;
}
/* We don't currently support file permissions; ignore MODE */
(void)mode;
/* We don't currently support file permissions; ignore MODE */
(void)mode;
/* Link it into the directory */
result = sfs_dir_link(sv, name, newguy->sv_ino, NULL);
if (result) {
VOP_DECREF(&newguy->sv_absvn);
vfs_biglock_release();
return result;
}
/* Link it into the directory */
result = sfs_dir_link(sv, name, newguy->sv_ino, NULL);
if (result) {
VOP_DECREF(&newguy->sv_absvn);
vfs_biglock_release();
return result;
}
/* Update the linkcount of the new file */
newguy->sv_i.sfi_linkcount++;
/* Update the linkcount of the new file */
newguy->sv_i.sfi_linkcount++;
/* and consequently mark it dirty. */
newguy->sv_dirty = true;
/* and consequently mark it dirty. */
newguy->sv_dirty = true;
*ret = &newguy->sv_absvn;
*ret = &newguy->sv_absvn;
vfs_biglock_release();
return 0;
vfs_biglock_release();
return 0;
}
/*
@@ -351,74 +312,68 @@ sfs_creat(struct vnode *v, const char *name, bool excl, mode_t mode,
* The VFS layer should prevent this being called unless both
* vnodes are ours.
*/
static
int
sfs_link(struct vnode *dir, const char *name, struct vnode *file)
{
struct sfs_vnode *sv = dir->vn_data;
struct sfs_vnode *f = file->vn_data;
int result;
static int sfs_link(struct vnode *dir, const char *name, struct vnode *file) {
struct sfs_vnode *sv = dir->vn_data;
struct sfs_vnode *f = file->vn_data;
int result;
KASSERT(file->vn_fs == dir->vn_fs);
KASSERT(file->vn_fs == dir->vn_fs);
vfs_biglock_acquire();
vfs_biglock_acquire();
/* Hard links to directories aren't allowed. */
if (f->sv_i.sfi_type == SFS_TYPE_DIR) {
vfs_biglock_release();
return EINVAL;
}
/* Hard links to directories aren't allowed. */
if (f->sv_i.sfi_type == SFS_TYPE_DIR) {
vfs_biglock_release();
return EINVAL;
}
/* Create the link */
result = sfs_dir_link(sv, name, f->sv_ino, NULL);
if (result) {
vfs_biglock_release();
return result;
}
/* Create the link */
result = sfs_dir_link(sv, name, f->sv_ino, NULL);
if (result) {
vfs_biglock_release();
return result;
}
/* and update the link count, marking the inode dirty */
f->sv_i.sfi_linkcount++;
f->sv_dirty = true;
/* and update the link count, marking the inode dirty */
f->sv_i.sfi_linkcount++;
f->sv_dirty = true;
vfs_biglock_release();
return 0;
vfs_biglock_release();
return 0;
}
/*
* Delete a file.
*/
static
int
sfs_remove(struct vnode *dir, const char *name)
{
struct sfs_vnode *sv = dir->vn_data;
struct sfs_vnode *victim;
int slot;
int result;
static int sfs_remove(struct vnode *dir, const char *name) {
struct sfs_vnode *sv = dir->vn_data;
struct sfs_vnode *victim;
int slot;
int result;
vfs_biglock_acquire();
vfs_biglock_acquire();
/* Look for the file and fetch a vnode for it. */
result = sfs_lookonce(sv, name, &victim, &slot);
if (result) {
vfs_biglock_release();
return result;
}
/* Look for the file and fetch a vnode for it. */
result = sfs_lookonce(sv, name, &victim, &slot);
if (result) {
vfs_biglock_release();
return result;
}
/* Erase its directory entry. */
result = sfs_dir_unlink(sv, slot);
if (result==0) {
/* If we succeeded, decrement the link count. */
KASSERT(victim->sv_i.sfi_linkcount > 0);
victim->sv_i.sfi_linkcount--;
victim->sv_dirty = true;
}
/* Erase its directory entry. */
result = sfs_dir_unlink(sv, slot);
if (result == 0) {
/* If we succeeded, decrement the link count. */
KASSERT(victim->sv_i.sfi_linkcount > 0);
victim->sv_i.sfi_linkcount--;
victim->sv_dirty = true;
}
/* Discard the reference that sfs_lookonce got us */
VOP_DECREF(&victim->sv_absvn);
/* Discard the reference that sfs_lookonce got us */
VOP_DECREF(&victim->sv_absvn);
vfs_biglock_release();
return result;
vfs_biglock_release();
return result;
}
/*
@@ -427,88 +382,83 @@ sfs_remove(struct vnode *dir, const char *name)
* Since we don't support subdirectories, assumes that the two
* directories passed are the same.
*/
static
int
sfs_rename(struct vnode *d1, const char *n1,
struct vnode *d2, const char *n2)
{
struct sfs_vnode *sv = d1->vn_data;
struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data;
struct sfs_vnode *g1;
int slot1, slot2;
int result, result2;
static int sfs_rename(struct vnode *d1, const char *n1, struct vnode *d2,
const char *n2) {
struct sfs_vnode *sv = d1->vn_data;
struct sfs_fs *sfs = sv->sv_absvn.vn_fs->fs_data;
struct sfs_vnode *g1;
int slot1, slot2;
int result, result2;
vfs_biglock_acquire();
vfs_biglock_acquire();
KASSERT(d1==d2);
KASSERT(sv->sv_ino == SFS_ROOTDIR_INO);
KASSERT(d1 == d2);
KASSERT(sv->sv_ino == SFS_ROOTDIR_INO);
/* Look up the old name of the file and get its inode and slot number*/
result = sfs_lookonce(sv, n1, &g1, &slot1);
if (result) {
vfs_biglock_release();
return result;
}
/* Look up the old name of the file and get its inode and slot number*/
result = sfs_lookonce(sv, n1, &g1, &slot1);
if (result) {
vfs_biglock_release();
return result;
}
/* We don't support subdirectories */
KASSERT(g1->sv_i.sfi_type == SFS_TYPE_FILE);
/* We don't support subdirectories */
KASSERT(g1->sv_i.sfi_type == SFS_TYPE_FILE);
/*
* Link it under the new name.
*
* We could theoretically just overwrite the original
* directory entry, except that we need to check to make sure
* the new name doesn't already exist; might as well use the
* existing link routine.
*/
result = sfs_dir_link(sv, n2, g1->sv_ino, &slot2);
if (result) {
goto puke;
}
/*
* Link it under the new name.
*
* We could theoretically just overwrite the original
* directory entry, except that we need to check to make sure
* the new name doesn't already exist; might as well use the
* existing link routine.
*/
result = sfs_dir_link(sv, n2, g1->sv_ino, &slot2);
if (result) {
goto puke;
}
/* Increment the link count, and mark inode dirty */
g1->sv_i.sfi_linkcount++;
g1->sv_dirty = true;
/* Increment the link count, and mark inode dirty */
g1->sv_i.sfi_linkcount++;
g1->sv_dirty = true;
/* Unlink the old slot */
result = sfs_dir_unlink(sv, slot1);
if (result) {
goto puke_harder;
}
/* Unlink the old slot */
result = sfs_dir_unlink(sv, slot1);
if (result) {
goto puke_harder;
}
/*
* Decrement the link count again, and mark the inode dirty again,
* in case it's been synced behind our back.
*/
KASSERT(g1->sv_i.sfi_linkcount>0);
g1->sv_i.sfi_linkcount--;
g1->sv_dirty = true;
/*
* Decrement the link count again, and mark the inode dirty again,
* in case it's been synced behind our back.
*/
KASSERT(g1->sv_i.sfi_linkcount > 0);
g1->sv_i.sfi_linkcount--;
g1->sv_dirty = true;
/* Let go of the reference to g1 */
VOP_DECREF(&g1->sv_absvn);
/* Let go of the reference to g1 */
VOP_DECREF(&g1->sv_absvn);
vfs_biglock_release();
return 0;
vfs_biglock_release();
return 0;
puke_harder:
/*
* Error recovery: try to undo what we already did
*/
result2 = sfs_dir_unlink(sv, slot2);
if (result2) {
kprintf("sfs: %s: rename: %s\n",
sfs->sfs_sb.sb_volname, strerror(result));
kprintf("sfs: %s: rename: while cleaning up: %s\n",
sfs->sfs_sb.sb_volname, strerror(result2));
panic("sfs: %s: rename: Cannot recover\n",
sfs->sfs_sb.sb_volname);
}
g1->sv_i.sfi_linkcount--;
puke:
/* Let go of the reference to g1 */
VOP_DECREF(&g1->sv_absvn);
vfs_biglock_release();
return result;
puke_harder:
/*
* Error recovery: try to undo what we already did
*/
result2 = sfs_dir_unlink(sv, slot2);
if (result2) {
kprintf("sfs: %s: rename: %s\n", sfs->sfs_sb.sb_volname, strerror(result));
kprintf("sfs: %s: rename: while cleaning up: %s\n", sfs->sfs_sb.sb_volname,
strerror(result2));
panic("sfs: %s: rename: Cannot recover\n", sfs->sfs_sb.sb_volname);
}
g1->sv_i.sfi_linkcount--;
puke:
/* Let go of the reference to g1 */
VOP_DECREF(&g1->sv_absvn);
vfs_biglock_release();
return result;
}
/*
@@ -518,31 +468,28 @@ sfs_rename(struct vnode *d1, const char *n1,
* Since we don't support subdirectories, this is very easy -
* return the root dir and copy the path.
*/
static
int
sfs_lookparent(struct vnode *v, char *path, struct vnode **ret,
char *buf, size_t buflen)
{
struct sfs_vnode *sv = v->vn_data;
static int sfs_lookparent(struct vnode *v, char *path, struct vnode **ret,
char *buf, size_t buflen) {
struct sfs_vnode *sv = v->vn_data;
vfs_biglock_acquire();
vfs_biglock_acquire();
if (sv->sv_i.sfi_type != SFS_TYPE_DIR) {
vfs_biglock_release();
return ENOTDIR;
}
if (sv->sv_i.sfi_type != SFS_TYPE_DIR) {
vfs_biglock_release();
return ENOTDIR;
}
if (strlen(path)+1 > buflen) {
vfs_biglock_release();
return ENAMETOOLONG;
}
strcpy(buf, path);
if (strlen(path) + 1 > buflen) {
vfs_biglock_release();
return ENAMETOOLONG;
}
strcpy(buf, path);
VOP_INCREF(&sv->sv_absvn);
*ret = &sv->sv_absvn;
VOP_INCREF(&sv->sv_absvn);
*ret = &sv->sv_absvn;
vfs_biglock_release();
return 0;
vfs_biglock_release();
return 0;
}
/*
@@ -551,31 +498,28 @@ sfs_lookparent(struct vnode *v, char *path, struct vnode **ret,
* Since we don't support subdirectories, it's easy - just look up the
* name.
*/
static
int
sfs_lookup(struct vnode *v, char *path, struct vnode **ret)
{
struct sfs_vnode *sv = v->vn_data;
struct sfs_vnode *final;
int result;
static int sfs_lookup(struct vnode *v, char *path, struct vnode **ret) {
struct sfs_vnode *sv = v->vn_data;
struct sfs_vnode *final;
int result;
vfs_biglock_acquire();
vfs_biglock_acquire();
if (sv->sv_i.sfi_type != SFS_TYPE_DIR) {
vfs_biglock_release();
return ENOTDIR;
}
if (sv->sv_i.sfi_type != SFS_TYPE_DIR) {
vfs_biglock_release();
return ENOTDIR;
}
result = sfs_lookonce(sv, path, &final, NULL);
if (result) {
vfs_biglock_release();
return result;
}
result = sfs_lookonce(sv, path, &final, NULL);
if (result) {
vfs_biglock_release();
return result;
}
*ret = &final->sv_absvn;
*ret = &final->sv_absvn;
vfs_biglock_release();
return 0;
vfs_biglock_release();
return 0;
}
////////////////////////////////////////////////////////////
@@ -585,66 +529,66 @@ sfs_lookup(struct vnode *v, char *path, struct vnode **ret)
* Function table for sfs files.
*/
const struct vnode_ops sfs_fileops = {
.vop_magic = VOP_MAGIC, /* mark this a valid vnode ops table */
.vop_magic = VOP_MAGIC, /* mark this a valid vnode ops table */
.vop_eachopen = sfs_eachopen,
.vop_reclaim = sfs_reclaim,
.vop_eachopen = sfs_eachopen,
.vop_reclaim = sfs_reclaim,
.vop_read = sfs_read,
.vop_readlink = vopfail_uio_notdir,
.vop_getdirentry = vopfail_uio_notdir,
.vop_write = sfs_write,
.vop_ioctl = sfs_ioctl,
.vop_stat = sfs_stat,
.vop_gettype = sfs_gettype,
.vop_isseekable = sfs_isseekable,
.vop_fsync = sfs_fsync,
.vop_mmap = sfs_mmap,
.vop_truncate = sfs_truncate,
.vop_namefile = vopfail_uio_notdir,
.vop_read = sfs_read,
.vop_readlink = vopfail_uio_notdir,
.vop_getdirentry = vopfail_uio_notdir,
.vop_write = sfs_write,
.vop_ioctl = sfs_ioctl,
.vop_stat = sfs_stat,
.vop_gettype = sfs_gettype,
.vop_isseekable = sfs_isseekable,
.vop_fsync = sfs_fsync,
.vop_mmap = sfs_mmap,
.vop_truncate = sfs_truncate,
.vop_namefile = vopfail_uio_notdir,
.vop_creat = vopfail_creat_notdir,
.vop_symlink = vopfail_symlink_notdir,
.vop_mkdir = vopfail_mkdir_notdir,
.vop_link = vopfail_link_notdir,
.vop_remove = vopfail_string_notdir,
.vop_rmdir = vopfail_string_notdir,
.vop_rename = vopfail_rename_notdir,
.vop_creat = vopfail_creat_notdir,
.vop_symlink = vopfail_symlink_notdir,
.vop_mkdir = vopfail_mkdir_notdir,
.vop_link = vopfail_link_notdir,
.vop_remove = vopfail_string_notdir,
.vop_rmdir = vopfail_string_notdir,
.vop_rename = vopfail_rename_notdir,
.vop_lookup = vopfail_lookup_notdir,
.vop_lookparent = vopfail_lookparent_notdir,
.vop_lookup = vopfail_lookup_notdir,
.vop_lookparent = vopfail_lookparent_notdir,
};
/*
* Function table for the sfs directory.
*/
const struct vnode_ops sfs_dirops = {
.vop_magic = VOP_MAGIC, /* mark this a valid vnode ops table */
.vop_magic = VOP_MAGIC, /* mark this a valid vnode ops table */
.vop_eachopen = sfs_eachopendir,
.vop_reclaim = sfs_reclaim,
.vop_eachopen = sfs_eachopendir,
.vop_reclaim = sfs_reclaim,
.vop_read = vopfail_uio_isdir,
.vop_readlink = vopfail_uio_inval,
.vop_getdirentry = vopfail_uio_nosys,
.vop_write = vopfail_uio_isdir,
.vop_ioctl = sfs_ioctl,
.vop_stat = sfs_stat,
.vop_gettype = sfs_gettype,
.vop_isseekable = sfs_isseekable,
.vop_fsync = sfs_fsync,
.vop_mmap = vopfail_mmap_isdir,
.vop_truncate = vopfail_truncate_isdir,
.vop_namefile = sfs_namefile,
.vop_read = vopfail_uio_isdir,
.vop_readlink = vopfail_uio_inval,
.vop_getdirentry = vopfail_uio_nosys,
.vop_write = vopfail_uio_isdir,
.vop_ioctl = sfs_ioctl,
.vop_stat = sfs_stat,
.vop_gettype = sfs_gettype,
.vop_isseekable = sfs_isseekable,
.vop_fsync = sfs_fsync,
.vop_mmap = vopfail_mmap_isdir,
.vop_truncate = vopfail_truncate_isdir,
.vop_namefile = sfs_namefile,
.vop_creat = sfs_creat,
.vop_symlink = vopfail_symlink_nosys,
.vop_mkdir = vopfail_mkdir_nosys,
.vop_link = sfs_link,
.vop_remove = sfs_remove,
.vop_rmdir = vopfail_string_nosys,
.vop_rename = sfs_rename,
.vop_creat = sfs_creat,
.vop_symlink = vopfail_symlink_nosys,
.vop_mkdir = vopfail_mkdir_nosys,
.vop_link = sfs_link,
.vop_remove = sfs_remove,
.vop_rmdir = vopfail_string_nosys,
.vop_rename = sfs_rename,
.vop_lookup = sfs_lookup,
.vop_lookparent = sfs_lookparent,
.vop_lookup = sfs_lookup,
.vop_lookparent = sfs_lookparent,
};

View File

@@ -32,15 +32,13 @@
#include <uio.h> /* for uio_rw */
/* ops tables (in sfs_vnops.c) */
extern const struct vnode_ops sfs_fileops;
extern const struct vnode_ops sfs_dirops;
/* Macro for initializing a uio structure */
#define SFSUIO(iov, uio, ptr, block, rw) \
uio_kinit(iov, uio, ptr, SFS_BLOCKSIZE, ((off_t)(block))*SFS_BLOCKSIZE, rw)
#define SFSUIO(iov, uio, ptr, block, rw) \
uio_kinit(iov, uio, ptr, SFS_BLOCKSIZE, ((off_t)(block)) * SFS_BLOCKSIZE, rw)
/* Functions in sfs_balloc.c */
int sfs_balloc(struct sfs_fs *sfs, daddr_t *diskblock);
@@ -49,24 +47,23 @@ int sfs_bused(struct sfs_fs *sfs, daddr_t diskblock);
/* Functions in sfs_bmap.c */
int sfs_bmap(struct sfs_vnode *sv, uint32_t fileblock, bool doalloc,
daddr_t *diskblock);
daddr_t *diskblock);
int sfs_itrunc(struct sfs_vnode *sv, off_t len);
/* Functions in sfs_dir.c */
int sfs_dir_findname(struct sfs_vnode *sv, const char *name,
uint32_t *ino, int *slot, int *emptyslot);
int sfs_dir_findname(struct sfs_vnode *sv, const char *name, uint32_t *ino,
int *slot, int *emptyslot);
int sfs_dir_link(struct sfs_vnode *sv, const char *name, uint32_t ino,
int *slot);
int *slot);
int sfs_dir_unlink(struct sfs_vnode *sv, int slot);
int sfs_lookonce(struct sfs_vnode *sv, const char *name,
struct sfs_vnode **ret,
int *slot);
int sfs_lookonce(struct sfs_vnode *sv, const char *name, struct sfs_vnode **ret,
int *slot);
/* Functions in sfs_inode.c */
int sfs_sync_inode(struct sfs_vnode *sv);
int sfs_reclaim(struct vnode *v);
int sfs_loadvnode(struct sfs_fs *sfs, uint32_t ino, int forcetype,
struct sfs_vnode **ret);
struct sfs_vnode **ret);
int sfs_makeobj(struct sfs_fs *sfs, int type, struct sfs_vnode **ret);
int sfs_getroot(struct fs *fs, struct vnode **ret);
@@ -75,7 +72,6 @@ int sfs_readblock(struct sfs_fs *sfs, daddr_t block, void *data, size_t len);
int sfs_writeblock(struct sfs_fs *sfs, daddr_t block, void *data, size_t len);
int sfs_io(struct sfs_vnode *sv, struct uio *uio);
int sfs_metaio(struct sfs_vnode *sv, off_t pos, void *data, size_t len,
enum uio_rw rw);
enum uio_rw rw);
#endif /* _SFSPRIVATE_H_ */

View File

@@ -34,13 +34,11 @@
* Address space structure and operations.
*/
#include <vm.h>
#include "opt-dumbvm.h"
struct vnode;
/*
* Address space - data structure associated with the virtual memory
* space of a process.
@@ -50,15 +48,15 @@ struct vnode;
struct addrspace {
#if OPT_DUMBVM
vaddr_t as_vbase1;
paddr_t as_pbase1;
size_t as_npages1;
vaddr_t as_vbase2;
paddr_t as_pbase2;
size_t as_npages2;
paddr_t as_stackpbase;
vaddr_t as_vbase1;
paddr_t as_pbase1;
size_t as_npages1;
vaddr_t as_vbase2;
paddr_t as_pbase2;
size_t as_npages2;
paddr_t as_stackpbase;
#else
/* Put stuff here for your VM system */
/* Put stuff here for your VM system */
#endif
};
@@ -104,20 +102,16 @@ struct addrspace {
*/
struct addrspace *as_create(void);
int as_copy(struct addrspace *src, struct addrspace **ret);
void as_activate(void);
void as_deactivate(void);
void as_destroy(struct addrspace *);
int as_define_region(struct addrspace *as,
vaddr_t vaddr, size_t sz,
int readable,
int writeable,
int executable);
int as_prepare_load(struct addrspace *as);
int as_complete_load(struct addrspace *as);
int as_define_stack(struct addrspace *as, vaddr_t *initstackptr);
int as_copy(struct addrspace *src, struct addrspace **ret);
void as_activate(void);
void as_deactivate(void);
void as_destroy(struct addrspace *);
int as_define_region(struct addrspace *as, vaddr_t vaddr, size_t sz,
int readable, int writeable, int executable);
int as_prepare_load(struct addrspace *as);
int as_complete_load(struct addrspace *as);
int as_define_stack(struct addrspace *as, vaddr_t *initstackptr);
/*
* Functions in loadelf.c
@@ -128,5 +122,4 @@ int as_define_stack(struct addrspace *as, vaddr_t *initstackptr);
int load_elf(struct vnode *v, vaddr_t *entrypoint);
#endif /* _ADDRSPACE_H_ */

View File

@@ -68,8 +68,8 @@
*/
struct array {
void **v;
unsigned num, max;
void **v;
unsigned num, max;
};
struct array *array_create(void);
@@ -88,42 +88,32 @@ void array_remove(struct array *, unsigned index);
* Inlining for base operations
*/
ARRAYINLINE unsigned
array_num(const struct array *a)
{
return a->num;
ARRAYINLINE unsigned array_num(const struct array *a) { return a->num; }
ARRAYINLINE void *array_get(const struct array *a, unsigned index) {
ARRAYASSERT(index < a->num);
return a->v[index];
}
ARRAYINLINE void *
array_get(const struct array *a, unsigned index)
{
ARRAYASSERT(index < a->num);
return a->v[index];
ARRAYINLINE void array_set(const struct array *a, unsigned index, void *val) {
ARRAYASSERT(index < a->num);
a->v[index] = val;
}
ARRAYINLINE void
array_set(const struct array *a, unsigned index, void *val)
{
ARRAYASSERT(index < a->num);
a->v[index] = val;
}
ARRAYINLINE int array_add(struct array *a, void *val, unsigned *index_ret) {
unsigned index;
int ret;
ARRAYINLINE int
array_add(struct array *a, void *val, unsigned *index_ret)
{
unsigned index;
int ret;
index = a->num;
ret = array_setsize(a, index+1);
if (ret) {
return ret;
}
a->v[index] = val;
if (index_ret != NULL) {
*index_ret = index;
}
return 0;
index = a->num;
ret = array_setsize(a, index + 1);
if (ret) {
return ret;
}
a->v[index] = val;
if (index_ret != NULL) {
*index_ret = index;
}
return 0;
}
/*
@@ -165,95 +155,69 @@ array_add(struct array *a, void *val, unsigned *index_ret)
* the base array, except typed.
*/
#define DECLARRAY_BYTYPE(ARRAY, T, INLINE) \
struct ARRAY { \
struct array arr; \
}; \
\
INLINE struct ARRAY *ARRAY##_create(void); \
INLINE void ARRAY##_destroy(struct ARRAY *a); \
INLINE void ARRAY##_init(struct ARRAY *a); \
INLINE void ARRAY##_cleanup(struct ARRAY *a); \
INLINE unsigned ARRAY##_num(const struct ARRAY *a); \
INLINE T *ARRAY##_get(const struct ARRAY *a, unsigned index); \
INLINE void ARRAY##_set(struct ARRAY *a, unsigned index, T *val); \
INLINE int ARRAY##_preallocate(struct ARRAY *a, unsigned num); \
INLINE int ARRAY##_setsize(struct ARRAY *a, unsigned num); \
INLINE int ARRAY##_add(struct ARRAY *a, T *val, unsigned *index_ret); \
INLINE void ARRAY##_remove(struct ARRAY *a, unsigned index)
#define DECLARRAY_BYTYPE(ARRAY, T, INLINE) \
struct ARRAY { \
struct array arr; \
}; \
\
INLINE struct ARRAY *ARRAY##_create(void); \
INLINE void ARRAY##_destroy(struct ARRAY *a); \
INLINE void ARRAY##_init(struct ARRAY *a); \
INLINE void ARRAY##_cleanup(struct ARRAY *a); \
INLINE unsigned ARRAY##_num(const struct ARRAY *a); \
INLINE T *ARRAY##_get(const struct ARRAY *a, unsigned index); \
INLINE void ARRAY##_set(struct ARRAY *a, unsigned index, T *val); \
INLINE int ARRAY##_preallocate(struct ARRAY *a, unsigned num); \
INLINE int ARRAY##_setsize(struct ARRAY *a, unsigned num); \
INLINE int ARRAY##_add(struct ARRAY *a, T *val, unsigned *index_ret); \
INLINE void ARRAY##_remove(struct ARRAY *a, unsigned index)
#define DEFARRAY_BYTYPE(ARRAY, T, INLINE) \
INLINE struct ARRAY * \
ARRAY##_create(void) \
{ \
struct ARRAY *a = kmalloc(sizeof(*a)); \
if (a == NULL) { \
return NULL; \
} \
array_init(&a->arr); \
return a; \
} \
\
INLINE void \
ARRAY##_destroy(struct ARRAY *a) \
{ \
array_cleanup(&a->arr); \
kfree(a); \
} \
\
INLINE void \
ARRAY##_init(struct ARRAY *a) \
{ \
array_init(&a->arr); \
} \
\
INLINE void \
ARRAY##_cleanup(struct ARRAY *a) \
{ \
array_cleanup(&a->arr); \
} \
\
INLINE unsigned \
ARRAY##_num(const struct ARRAY *a) \
{ \
return array_num(&a->arr); \
} \
\
INLINE T * \
ARRAY##_get(const struct ARRAY *a, unsigned index) \
{ \
return (T *)array_get(&a->arr, index); \
} \
\
INLINE void \
ARRAY##_set(struct ARRAY *a, unsigned index, T *val) \
{ \
array_set(&a->arr, index, (void *)val); \
} \
\
INLINE int \
ARRAY##_preallocate(struct ARRAY *a, unsigned num) \
{ \
return array_preallocate(&a->arr, num); \
} \
\
INLINE int \
ARRAY##_setsize(struct ARRAY *a, unsigned num) \
{ \
return array_setsize(&a->arr, num); \
} \
\
INLINE int \
ARRAY##_add(struct ARRAY *a, T *val, unsigned *index_ret) \
{ \
return array_add(&a->arr, (void *)val, index_ret); \
} \
\
INLINE void \
ARRAY##_remove(struct ARRAY *a, unsigned index) \
{ \
array_remove(&a->arr, index); \
}
#define DEFARRAY_BYTYPE(ARRAY, T, INLINE) \
INLINE struct ARRAY *ARRAY##_create(void) { \
struct ARRAY *a = kmalloc(sizeof(*a)); \
if (a == NULL) { \
return NULL; \
} \
array_init(&a->arr); \
return a; \
} \
\
INLINE void ARRAY##_destroy(struct ARRAY *a) { \
array_cleanup(&a->arr); \
kfree(a); \
} \
\
INLINE void ARRAY##_init(struct ARRAY *a) { array_init(&a->arr); } \
\
INLINE void ARRAY##_cleanup(struct ARRAY *a) { array_cleanup(&a->arr); } \
\
INLINE unsigned ARRAY##_num(const struct ARRAY *a) { \
return array_num(&a->arr); \
} \
\
INLINE T *ARRAY##_get(const struct ARRAY *a, unsigned index) { \
return (T *)array_get(&a->arr, index); \
} \
\
INLINE void ARRAY##_set(struct ARRAY *a, unsigned index, T *val) { \
array_set(&a->arr, index, (void *)val); \
} \
\
INLINE int ARRAY##_preallocate(struct ARRAY *a, unsigned num) { \
return array_preallocate(&a->arr, num); \
} \
\
INLINE int ARRAY##_setsize(struct ARRAY *a, unsigned num) { \
return array_setsize(&a->arr, num); \
} \
\
INLINE int ARRAY##_add(struct ARRAY *a, T *val, unsigned *index_ret) { \
return array_add(&a->arr, (void *)val, index_ret); \
} \
\
INLINE void ARRAY##_remove(struct ARRAY *a, unsigned index) { \
array_remove(&a->arr, index); \
}
#define DECLARRAY(T, INLINE) DECLARRAY_BYTYPE(T##array, struct T, INLINE)
#define DEFARRAY(T, INLINE) DEFARRAY_BYTYPE(T##array, struct T, INLINE)
@@ -265,5 +229,4 @@ array_add(struct array *a, void *val, unsigned *index_ret)
DECLARRAY_BYTYPE(stringarray, char, ARRAYINLINE);
DEFARRAY_BYTYPE(stringarray, char, ARRAYINLINE);
#endif /* ARRAY_H */

View File

@@ -44,16 +44,14 @@
* bitmap_destroy - destroy bitmap.
*/
struct bitmap; /* Opaque. */
struct bitmap; /* Opaque. */
struct bitmap *bitmap_create(unsigned nbits);
void *bitmap_getdata(struct bitmap *);
int bitmap_alloc(struct bitmap *, unsigned *index);
void bitmap_mark(struct bitmap *, unsigned index);
void bitmap_unmark(struct bitmap *, unsigned index);
int bitmap_isset(struct bitmap *, unsigned index);
void bitmap_destroy(struct bitmap *);
void *bitmap_getdata(struct bitmap *);
int bitmap_alloc(struct bitmap *, unsigned *index);
void bitmap_mark(struct bitmap *, unsigned index);
void bitmap_unmark(struct bitmap *, unsigned index);
int bitmap_isset(struct bitmap *, unsigned index);
void bitmap_destroy(struct bitmap *);
#endif /* _BITMAP_H_ */

View File

@@ -34,36 +34,32 @@
* Some miscellaneous C language definitions and related matters.
*/
/*
* Build-time assertion. Doesn't generate any code. The error message
* on failure is less than ideal, but you can't have everything.
*/
#define COMPILE_ASSERT(x) ((void)sizeof(struct { unsigned : ((x)?1:-1); }))
#define COMPILE_ASSERT(x) ((void)sizeof(struct { unsigned : ((x) ? 1 : -1); }))
/*
* Handy macro for the number of elements in a static array.
*/
#define ARRAYCOUNT(arr) (sizeof(arr) / sizeof((arr)[0]))
/*
* Tell GCC how to check printf formats. Also tell it about functions
* that don't return, as this is helpful for avoiding bogus warnings
* about uninitialized variables.
*/
#ifdef __GNUC__
#define __PF(a,b) __attribute__((__format__(__printf__, a, b)))
#define __DEAD __attribute__((__noreturn__))
#define __UNUSED __attribute__((__unused__))
#define __PF(a, b) __attribute__((__format__(__printf__, a, b)))
#define __DEAD __attribute__((__noreturn__))
#define __UNUSED __attribute__((__unused__))
#else
#define __PF(a,b)
#define __PF(a, b)
#define __DEAD
#define __UNUSED
#endif
/*
* Material for supporting inline functions.
*
@@ -137,5 +133,4 @@
#define INLINE static __UNUSED inline
#endif
#endif /* _CDEFS_H_ */

View File

@@ -36,14 +36,13 @@
#include <kern/time.h>
/*
* hardclock() is called on every CPU HZ times a second, possibly only
* when the CPU is not idle, for scheduling.
*/
/* hardclocks per second */
#define HZ 100
#define HZ 100
void hardclock_bootstrap(void);
void hardclock(void);
@@ -66,12 +65,10 @@ void gettime(struct timespec *ret);
* sub: ret = t1 - t2
*/
void timespec_add(const struct timespec *t1,
const struct timespec *t2,
struct timespec *ret);
void timespec_sub(const struct timespec *t1,
const struct timespec *t2,
struct timespec *ret);
void timespec_add(const struct timespec *t1, const struct timespec *t2,
struct timespec *ret);
void timespec_sub(const struct timespec *t1, const struct timespec *t2,
struct timespec *ret);
/*
* clocksleep() suspends execution for the requested number of seconds,
@@ -79,5 +76,4 @@ void timespec_sub(const struct timespec *t1,
*/
void clocksleep(int seconds);
#endif /* _CLOCK_H_ */

View File

@@ -30,7 +30,6 @@
#ifndef _COPYINOUT_H_
#define _COPYINOUT_H_
/*
* copyin/copyout/copyinstr/copyoutstr are standard BSD kernel functions.
*
@@ -69,5 +68,4 @@ int copyout(const void *src, userptr_t userdest, size_t len);
int copyinstr(const_userptr_t usersrc, char *dest, size_t len, size_t *got);
int copyoutstr(const char *src, userptr_t userdest, size_t len, size_t *got);
#endif /* _COPYINOUT_H_ */

View File

@@ -30,11 +30,9 @@
#ifndef _CPU_H_
#define _CPU_H_
#include <spinlock.h>
#include <threadlist.h>
#include <machine/vm.h> /* for TLBSHOOTDOWN_MAX */
#include <machine/vm.h> /* for TLBSHOOTDOWN_MAX */
/*
* Per-cpu structure
@@ -47,51 +45,51 @@
*/
struct cpu {
/*
* Fixed after allocation.
*/
struct cpu *c_self; /* Canonical address of this struct */
unsigned c_number; /* This cpu's cpu number */
unsigned c_hardware_number; /* Hardware-defined cpu number */
/*
* Fixed after allocation.
*/
struct cpu *c_self; /* Canonical address of this struct */
unsigned c_number; /* This cpu's cpu number */
unsigned c_hardware_number; /* Hardware-defined cpu number */
/*
* Accessed only by this cpu.
*/
struct thread *c_curthread; /* Current thread on cpu */
struct threadlist c_zombies; /* List of exited threads */
unsigned c_hardclocks; /* Counter of hardclock() calls */
unsigned c_spinlocks; /* Counter of spinlocks held */
/*
* Accessed only by this cpu.
*/
struct thread *c_curthread; /* Current thread on cpu */
struct threadlist c_zombies; /* List of exited threads */
unsigned c_hardclocks; /* Counter of hardclock() calls */
unsigned c_spinlocks; /* Counter of spinlocks held */
/*
* Accessed by other cpus.
* Protected by the runqueue lock.
*/
bool c_isidle; /* True if this cpu is idle */
struct threadlist c_runqueue; /* Run queue for this cpu */
struct spinlock c_runqueue_lock;
/*
* Accessed by other cpus.
* Protected by the runqueue lock.
*/
bool c_isidle; /* True if this cpu is idle */
struct threadlist c_runqueue; /* Run queue for this cpu */
struct spinlock c_runqueue_lock;
/*
* Accessed by other cpus.
* Protected by the IPI lock.
*
* TLB shootdown requests made to this CPU are queued in
* c_shootdown[], with c_numshootdown holding the number of
* requests. TLBSHOOTDOWN_MAX is the maximum number that can
* be queued at once, which is machine-dependent.
*
* The contents of struct tlbshootdown are also machine-
* dependent and might reasonably be either an address space
* and vaddr pair, or a paddr, or something else.
*/
uint32_t c_ipi_pending; /* One bit for each IPI number */
struct tlbshootdown c_shootdown[TLBSHOOTDOWN_MAX];
unsigned c_numshootdown;
struct spinlock c_ipi_lock;
/*
* Accessed by other cpus.
* Protected by the IPI lock.
*
* TLB shootdown requests made to this CPU are queued in
* c_shootdown[], with c_numshootdown holding the number of
* requests. TLBSHOOTDOWN_MAX is the maximum number that can
* be queued at once, which is machine-dependent.
*
* The contents of struct tlbshootdown are also machine-
* dependent and might reasonably be either an address space
* and vaddr pair, or a paddr, or something else.
*/
uint32_t c_ipi_pending; /* One bit for each IPI number */
struct tlbshootdown c_shootdown[TLBSHOOTDOWN_MAX];
unsigned c_numshootdown;
struct spinlock c_ipi_lock;
/*
* Accessed by other cpus. Protected inside hangman.c.
*/
HANGMAN_ACTOR(c_hangman);
/*
* Accessed by other cpus. Protected inside hangman.c.
*/
HANGMAN_ACTOR(c_hangman);
};
/*
@@ -161,10 +159,10 @@ void cpu_halt(void);
*/
/* IPI types */
#define IPI_PANIC 0 /* System has called panic() */
#define IPI_OFFLINE 1 /* CPU is requested to go offline */
#define IPI_UNIDLE 2 /* Runnable threads are available */
#define IPI_TLBSHOOTDOWN 3 /* MMU mapping(s) need invalidation */
#define IPI_PANIC 0 /* System has called panic() */
#define IPI_OFFLINE 1 /* CPU is requested to go offline */
#define IPI_UNIDLE 2 /* Runnable threads are available */
#define IPI_TLBSHOOTDOWN 3 /* MMU mapping(s) need invalidation */
void ipi_send(struct cpu *target, int code);
void ipi_broadcast(int code);
@@ -172,5 +170,4 @@ void ipi_tlbshootdown(struct cpu *target, const struct tlbshootdown *mapping);
void interprocessor_interrupt(void);
#endif /* _CPU_H_ */

View File

@@ -89,5 +89,4 @@
#define curproc (curthread->t_proc)
#endif /* _CURRENT_H_ */

View File

@@ -34,21 +34,20 @@
* Devices.
*/
struct uio; /* in <uio.h> */
struct uio; /* in <uio.h> */
/*
* Filesystem-namespace-accessible device.
*/
struct device {
const struct device_ops *d_ops;
const struct device_ops *d_ops;
blkcnt_t d_blocks;
blksize_t d_blocksize;
blkcnt_t d_blocks;
blksize_t d_blocksize;
dev_t d_devnumber; /* serial number for this device */
dev_t d_devnumber; /* serial number for this device */
void *d_data; /* device-specific data */
void *d_data; /* device-specific data */
};
/*
@@ -58,18 +57,17 @@ struct device {
* devop_ioctl - miscellaneous control operations
*/
struct device_ops {
int (*devop_eachopen)(struct device *, int flags_from_open);
int (*devop_io)(struct device *, struct uio *);
int (*devop_ioctl)(struct device *, int op, userptr_t data);
int (*devop_eachopen)(struct device *, int flags_from_open);
int (*devop_io)(struct device *, struct uio *);
int (*devop_ioctl)(struct device *, int op, userptr_t data);
};
/*
* Macros to shorten the calling sequences.
*/
#define DEVOP_EACHOPEN(d, f) ((d)->d_ops->devop_eachopen(d, f))
#define DEVOP_IO(d, u) ((d)->d_ops->devop_io(d, u))
#define DEVOP_IOCTL(d, op, p) ((d)->d_ops->devop_ioctl(d, op, p))
#define DEVOP_EACHOPEN(d, f) ((d)->d_ops->devop_eachopen(d, f))
#define DEVOP_IO(d, u) ((d)->d_ops->devop_io(d, u))
#define DEVOP_IOCTL(d, op, p) ((d)->d_ops->devop_ioctl(d, op, p))
/* Create vnode for a vfs-level device. */
struct vnode *dev_create_vnode(struct device *dev);
@@ -83,5 +81,4 @@ void devnull_create(void);
/* Function that kicks off device probe and attach. */
void dev_bootstrap(void);
#endif /* _DEVICE_H_ */

View File

@@ -30,7 +30,6 @@
#ifndef _ELF_H_
#define _ELF_H_
/*
* Simplified ELF definitions for OS/161 and System/161.
*
@@ -43,121 +42,118 @@
/* Get MD bits */
#include <machine/elf.h>
/*
* ELF file header. This appears at the very beginning of an ELF file.
*/
#define ELF_NIDENT 16
#define ELF_NIDENT 16
typedef struct {
unsigned char e_ident[ELF_NIDENT]; /* magic number et al. */
uint16_t e_type; /* type of file this is */
uint16_t e_machine; /* processor type file is for */
uint32_t e_version; /* ELF version */
uint32_t e_entry; /* address of program entry point */
uint32_t e_phoff; /* location in file of phdrs */
uint32_t e_shoff; /* ignore */
uint32_t e_flags; /* ignore */
uint16_t e_ehsize; /* actual size of file header */
uint16_t e_phentsize; /* actual size of phdr */
uint16_t e_phnum; /* number of phdrs */
uint16_t e_shentsize; /* ignore */
uint16_t e_shnum; /* ignore */
uint16_t e_shstrndx; /* ignore */
unsigned char e_ident[ELF_NIDENT]; /* magic number et al. */
uint16_t e_type; /* type of file this is */
uint16_t e_machine; /* processor type file is for */
uint32_t e_version; /* ELF version */
uint32_t e_entry; /* address of program entry point */
uint32_t e_phoff; /* location in file of phdrs */
uint32_t e_shoff; /* ignore */
uint32_t e_flags; /* ignore */
uint16_t e_ehsize; /* actual size of file header */
uint16_t e_phentsize; /* actual size of phdr */
uint16_t e_phnum; /* number of phdrs */
uint16_t e_shentsize; /* ignore */
uint16_t e_shnum; /* ignore */
uint16_t e_shstrndx; /* ignore */
} Elf32_Ehdr;
/* Offsets for the 1-byte fields within e_ident[] */
#define EI_MAG0 0 /* '\177' */
#define EI_MAG1 1 /* 'E' */
#define EI_MAG2 2 /* 'L' */
#define EI_MAG3 3 /* 'F' */
#define EI_CLASS 4 /* File class - always ELFCLASS32 */
#define EI_DATA 5 /* Data encoding - ELFDATA2LSB or ELFDATA2MSB*/
#define EI_VERSION 6 /* ELF version - EV_CURRENT*/
#define EI_OSABI 7 /* OS/syscall ABI identification */
#define EI_ABIVERSION 8 /* syscall ABI version */
#define EI_PAD 9 /* Start of padding bytes up to EI_NIDENT*/
#define EI_MAG0 0 /* '\177' */
#define EI_MAG1 1 /* 'E' */
#define EI_MAG2 2 /* 'L' */
#define EI_MAG3 3 /* 'F' */
#define EI_CLASS 4 /* File class - always ELFCLASS32 */
#define EI_DATA 5 /* Data encoding - ELFDATA2LSB or ELFDATA2MSB*/
#define EI_VERSION 6 /* ELF version - EV_CURRENT*/
#define EI_OSABI 7 /* OS/syscall ABI identification */
#define EI_ABIVERSION 8 /* syscall ABI version */
#define EI_PAD 9 /* Start of padding bytes up to EI_NIDENT*/
/* Values for these fields */
/* For e_ident[EI_MAG0..3] */
#define ELFMAG0 0x7f
#define ELFMAG1 'E'
#define ELFMAG2 'L'
#define ELFMAG3 'F'
#define ELFMAG0 0x7f
#define ELFMAG1 'E'
#define ELFMAG2 'L'
#define ELFMAG3 'F'
/* For e_ident[EI_CLASS] */
#define ELFCLASSNONE 0 /* Invalid class */
#define ELFCLASS32 1 /* 32-bit objects */
#define ELFCLASS64 2 /* 64-bit objects */
#define ELFCLASSNONE 0 /* Invalid class */
#define ELFCLASS32 1 /* 32-bit objects */
#define ELFCLASS64 2 /* 64-bit objects */
/* e_ident[EI_DATA] */
#define ELFDATANONE 0 /* Invalid data encoding */
#define ELFDATA2LSB 1 /* 2's complement values, LSB first */
#define ELFDATA2MSB 2 /* 2's complement values, MSB first */
#define ELFDATANONE 0 /* Invalid data encoding */
#define ELFDATA2LSB 1 /* 2's complement values, LSB first */
#define ELFDATA2MSB 2 /* 2's complement values, MSB first */
/* e_ident[EI_VERSION] */
#define EV_NONE 0 /* Invalid version */
#define EV_CURRENT 1 /* Current version */
#define EV_NONE 0 /* Invalid version */
#define EV_CURRENT 1 /* Current version */
/* e_ident[EI_OSABI] */
#define ELFOSABI_SYSV 0 /* UNIX System V ABI */
#define ELFOSABI_HPUX 1 /* HP-UX operating system */
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
#define ELFOSABI_SYSV 0 /* UNIX System V ABI */
#define ELFOSABI_HPUX 1 /* HP-UX operating system */
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
/*
* Values for e_type
*/
#define ET_NONE 0 /* No file type */
#define ET_REL 1 /* Relocatable file */
#define ET_EXEC 2 /* Executable file */
#define ET_DYN 3 /* Shared object file */
#define ET_CORE 4 /* Core file */
#define ET_NUM 5
#define ET_NONE 0 /* No file type */
#define ET_REL 1 /* Relocatable file */
#define ET_EXEC 2 /* Executable file */
#define ET_DYN 3 /* Shared object file */
#define ET_CORE 4 /* Core file */
#define ET_NUM 5
/*
* Values for e_machine
*/
#define EM_NONE 0 /* No machine */
#define EM_M32 1 /* AT&T WE 32100 */
#define EM_SPARC 2 /* SPARC */
#define EM_386 3 /* Intel 80386 */
#define EM_68K 4 /* Motorola 68000 */
#define EM_88K 5 /* Motorola 88000 */
#define EM_486 6 /* Intel 80486 */
#define EM_860 7 /* Intel 80860 */
#define EM_MIPS 8 /* MIPS I Architecture */
#define EM_S370 9 /* Amdahl UTS on System/370 */
#define EM_MIPS_RS3_LE 10 /* MIPS RS3000 Little-endian */
#define EM_RS6000 11 /* IBM RS/6000 XXX reserved */
#define EM_PARISC 15 /* Hewlett-Packard PA-RISC */
#define EM_NCUBE 16 /* NCube XXX reserved */
#define EM_VPP500 17 /* Fujitsu VPP500 */
#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */
#define EM_960 19 /* Intel 80960 */
#define EM_PPC 20 /* PowerPC */
#define EM_V800 36 /* NEC V800 */
#define EM_FR20 37 /* Fujitsu FR20 */
#define EM_RH32 38 /* TRW RH-32 */
#define EM_RCE 39 /* Motorola RCE */
#define EM_ARM 40 /* Advanced RISC Machines ARM */
#define EM_ALPHA 41 /* DIGITAL Alpha */
#define EM_SH 42 /* Hitachi Super-H */
#define EM_SPARCV9 43 /* SPARC Version 9 */
#define EM_TRICORE 44 /* Siemens Tricore */
#define EM_ARC 45 /* Argonaut RISC Core */
#define EM_H8_300 46 /* Hitachi H8/300 */
#define EM_H8_300H 47 /* Hitachi H8/300H */
#define EM_H8S 48 /* Hitachi H8S */
#define EM_H8_500 49 /* Hitachi H8/500 */
#define EM_IA_64 50 /* Intel Merced Processor */
#define EM_MIPS_X 51 /* Stanford MIPS-X */
#define EM_COLDFIRE 52 /* Motorola Coldfire */
#define EM_68HC12 53 /* Motorola MC68HC12 */
#define EM_VAX 75 /* DIGITAL VAX */
#define EM_ALPHA_EXP 36902 /* used by NetBSD/alpha; obsolete */
#define EM_NUM 36903
#define EM_NONE 0 /* No machine */
#define EM_M32 1 /* AT&T WE 32100 */
#define EM_SPARC 2 /* SPARC */
#define EM_386 3 /* Intel 80386 */
#define EM_68K 4 /* Motorola 68000 */
#define EM_88K 5 /* Motorola 88000 */
#define EM_486 6 /* Intel 80486 */
#define EM_860 7 /* Intel 80860 */
#define EM_MIPS 8 /* MIPS I Architecture */
#define EM_S370 9 /* Amdahl UTS on System/370 */
#define EM_MIPS_RS3_LE 10 /* MIPS RS3000 Little-endian */
#define EM_RS6000 11 /* IBM RS/6000 XXX reserved */
#define EM_PARISC 15 /* Hewlett-Packard PA-RISC */
#define EM_NCUBE 16 /* NCube XXX reserved */
#define EM_VPP500 17 /* Fujitsu VPP500 */
#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */
#define EM_960 19 /* Intel 80960 */
#define EM_PPC 20 /* PowerPC */
#define EM_V800 36 /* NEC V800 */
#define EM_FR20 37 /* Fujitsu FR20 */
#define EM_RH32 38 /* TRW RH-32 */
#define EM_RCE 39 /* Motorola RCE */
#define EM_ARM 40 /* Advanced RISC Machines ARM */
#define EM_ALPHA 41 /* DIGITAL Alpha */
#define EM_SH 42 /* Hitachi Super-H */
#define EM_SPARCV9 43 /* SPARC Version 9 */
#define EM_TRICORE 44 /* Siemens Tricore */
#define EM_ARC 45 /* Argonaut RISC Core */
#define EM_H8_300 46 /* Hitachi H8/300 */
#define EM_H8_300H 47 /* Hitachi H8/300H */
#define EM_H8S 48 /* Hitachi H8S */
#define EM_H8_500 49 /* Hitachi H8/500 */
#define EM_IA_64 50 /* Intel Merced Processor */
#define EM_MIPS_X 51 /* Stanford MIPS-X */
#define EM_COLDFIRE 52 /* Motorola Coldfire */
#define EM_68HC12 53 /* Motorola MC68HC12 */
#define EM_VAX 75 /* DIGITAL VAX */
#define EM_ALPHA_EXP 36902 /* used by NetBSD/alpha; obsolete */
#define EM_NUM 36903
/*
* "Program Header" - runtime segment header.
@@ -166,35 +162,33 @@ typedef struct {
* Note: if p_memsz > p_filesz, the leftover space should be zero-filled.
*/
typedef struct {
uint32_t p_type; /* Type of segment */
uint32_t p_offset; /* Location of data within file */
uint32_t p_vaddr; /* Virtual address */
uint32_t p_paddr; /* Ignore */
uint32_t p_filesz; /* Size of data within file */
uint32_t p_memsz; /* Size of data to be loaded into memory*/
uint32_t p_flags; /* Flags */
uint32_t p_align; /* Required alignment - can ignore */
uint32_t p_type; /* Type of segment */
uint32_t p_offset; /* Location of data within file */
uint32_t p_vaddr; /* Virtual address */
uint32_t p_paddr; /* Ignore */
uint32_t p_filesz; /* Size of data within file */
uint32_t p_memsz; /* Size of data to be loaded into memory*/
uint32_t p_flags; /* Flags */
uint32_t p_align; /* Required alignment - can ignore */
} Elf32_Phdr;
/* values for p_type */
#define PT_NULL 0 /* Program header table entry unused */
#define PT_LOAD 1 /* Loadable program segment */
#define PT_DYNAMIC 2 /* Dynamic linking information */
#define PT_INTERP 3 /* Program interpreter */
#define PT_NOTE 4 /* Auxiliary information */
#define PT_SHLIB 5 /* Reserved, unspecified semantics */
#define PT_PHDR 6 /* Entry for header table itself */
#define PT_NUM 7
#define PT_MIPS_REGINFO 0x70000000
#define PT_NULL 0 /* Program header table entry unused */
#define PT_LOAD 1 /* Loadable program segment */
#define PT_DYNAMIC 2 /* Dynamic linking information */
#define PT_INTERP 3 /* Program interpreter */
#define PT_NOTE 4 /* Auxiliary information */
#define PT_SHLIB 5 /* Reserved, unspecified semantics */
#define PT_PHDR 6 /* Entry for header table itself */
#define PT_NUM 7
#define PT_MIPS_REGINFO 0x70000000
/* values for p_flags */
#define PF_R 0x4 /* Segment is readable */
#define PF_W 0x2 /* Segment is writable */
#define PF_X 0x1 /* Segment is executable */
#define PF_R 0x4 /* Segment is readable */
#define PF_W 0x2 /* Segment is writable */
#define PF_X 0x1 /* Segment is executable */
typedef Elf32_Ehdr Elf_Ehdr;
typedef Elf32_Phdr Elf_Phdr;
#endif /* _ELF_H_ */

View File

@@ -30,7 +30,6 @@
#ifndef _EMUFS_H_
#define _EMUFS_H_
/*
* Get abstract structure definitions
*/
@@ -42,17 +41,16 @@
*/
struct emufs_vnode {
struct vnode ev_v; /* abstract vnode structure */
struct emu_softc *ev_emu; /* device */
uint32_t ev_handle; /* file handle */
struct vnode ev_v; /* abstract vnode structure */
struct emu_softc *ev_emu; /* device */
uint32_t ev_handle; /* file handle */
};
struct emufs_fs {
struct fs ef_fs; /* abstract filesystem structure */
struct emu_softc *ef_emu; /* device */
struct emufs_vnode *ef_root; /* root vnode */
struct vnodearray *ef_vnodes; /* table of loaded vnodes */
struct fs ef_fs; /* abstract filesystem structure */
struct emu_softc *ef_emu; /* device */
struct emufs_vnode *ef_root; /* root vnode */
struct vnodearray *ef_vnodes; /* table of loaded vnodes */
};
#endif /* _EMUFS_H_ */

View File

@@ -51,5 +51,4 @@ uint64_t htonll(uint64_t);
void join32to64(uint32_t x1, uint32_t x2, uint64_t *y2);
void split64to32(uint64_t x, uint32_t *y1, uint32_t *y2);
#endif /* _ENDIAN_H_ */

View File

@@ -32,7 +32,6 @@
struct vnode; /* in vnode.h */
/*
* Abstract file system. (Or device accessible as a file.)
*
@@ -40,8 +39,8 @@ struct vnode; /* in vnode.h */
*/
struct fs {
void *fs_data;
const struct fs_ops *fs_ops;
void *fs_data;
const struct fs_ops *fs_ops;
};
/*
@@ -70,22 +69,21 @@ struct fs {
* filesystem should have been discarded/released.
*/
struct fs_ops {
int (*fsop_sync)(struct fs *);
const char *(*fsop_getvolname)(struct fs *);
int (*fsop_getroot)(struct fs *, struct vnode **);
int (*fsop_unmount)(struct fs *);
int (*fsop_sync)(struct fs *);
const char *(*fsop_getvolname)(struct fs *);
int (*fsop_getroot)(struct fs *, struct vnode **);
int (*fsop_unmount)(struct fs *);
};
/*
* Macros to shorten the calling sequences.
*/
#define FSOP_SYNC(fs) ((fs)->fs_ops->fsop_sync(fs))
#define FSOP_GETVOLNAME(fs) ((fs)->fs_ops->fsop_getvolname(fs))
#define FSOP_SYNC(fs) ((fs)->fs_ops->fsop_sync(fs))
#define FSOP_GETVOLNAME(fs) ((fs)->fs_ops->fsop_getvolname(fs))
#define FSOP_GETROOT(fs, ret) ((fs)->fs_ops->fsop_getroot(fs, ret))
#define FSOP_UNMOUNT(fs) ((fs)->fs_ops->fsop_unmount(fs))
#define FSOP_UNMOUNT(fs) ((fs)->fs_ops->fsop_unmount(fs))
/* Initialization functions for builtin fake file systems. */
void semfs_bootstrap(void);
#endif /* _FS_H_ */

View File

@@ -40,30 +40,30 @@
#if OPT_HANGMAN
struct hangman_actor {
const char *a_name;
const struct hangman_lockable *a_waiting;
const char *a_name;
const struct hangman_lockable *a_waiting;
};
struct hangman_lockable {
const char *l_name;
const struct hangman_actor *l_holding;
const char *l_name;
const struct hangman_actor *l_holding;
};
void hangman_wait(struct hangman_actor *a, struct hangman_lockable *l);
void hangman_acquire(struct hangman_actor *a, struct hangman_lockable *l);
void hangman_release(struct hangman_actor *a, struct hangman_lockable *l);
#define HANGMAN_ACTOR(sym) struct hangman_actor sym
#define HANGMAN_LOCKABLE(sym) struct hangman_lockable sym
#define HANGMAN_ACTOR(sym) struct hangman_actor sym
#define HANGMAN_LOCKABLE(sym) struct hangman_lockable sym
#define HANGMAN_ACTORINIT(a, n) ((a)->a_name = (n), (a)->a_waiting = NULL)
#define HANGMAN_LOCKABLEINIT(l, n) ((l)->l_name = (n), (l)->l_holding = NULL)
#define HANGMAN_ACTORINIT(a, n) ((a)->a_name = (n), (a)->a_waiting = NULL)
#define HANGMAN_LOCKABLEINIT(l, n) ((l)->l_name = (n), (l)->l_holding = NULL)
#define HANGMAN_LOCKABLE_INITIALIZER { "spinlock", NULL }
#define HANGMAN_LOCKABLE_INITIALIZER {"spinlock", NULL}
#define HANGMAN_WAIT(a, l) hangman_wait(a, l)
#define HANGMAN_ACQUIRE(a, l) hangman_acquire(a, l)
#define HANGMAN_RELEASE(a, l) hangman_release(a, l)
#define HANGMAN_WAIT(a, l) hangman_wait(a, l)
#define HANGMAN_ACQUIRE(a, l) hangman_acquire(a, l)
#define HANGMAN_RELEASE(a, l) hangman_release(a, l)
#else

View File

@@ -40,11 +40,10 @@
*/
#define _LITTLE_ENDIAN 1234
#define _BIG_ENDIAN 4321
#define _PDP_ENDIAN 3412
#define _BIG_ENDIAN 4321
#define _PDP_ENDIAN 3412
/* This defines _BYTE_ORDER to one of the above. */
#include <kern/machine/endian.h>
#endif /* _KERN_ENDIAN_H_ */

View File

@@ -39,76 +39,76 @@
* lib/misc.c; for userland it's lib/libc/strerror.c.
*/
const char *const sys_errlist[] = {
"Operation succeeded", /* 0 */
"Function not implemented", /* ENOSYS */
"(undefined error 2)", /* unused */
"Out of memory", /* ENOMEM */
"Operation would block", /* EAGAIN (also EWOULDBLOCK) */
"Interrupted system call", /* EINTR */
"Bad memory reference", /* EFAULT */
"String too long", /* ENAMETOOLONG */
"Invalid argument", /* EINVAL */
"Operation not permitted", /* EPERM */
"Permission denied", /* EACCES */
"Too many processes", /* EMPROC (EPROCLIM in Unix) */
"Too many processes in system",/* ENPROC */
"File is not executable", /* ENOEXEC */
"Argument list too long", /* E2BIG */
"No such process", /* ESRCH */
"No child processes", /* ECHILD */
"Not a directory", /* ENOTDIR */
"Is a directory", /* EISDIR */
"No such file or directory", /* ENOENT */
"Too many levels of symbolic links",/* ELOOP */
"Directory not empty", /* ENOTEMPTY */
"File or object exists", /* EEXIST */
"Too many hard links", /* EMLINK */
"Cross-device link", /* EXDEV */
"No such device", /* ENODEV */
"Device not available", /* ENXIO */
"Device or resource busy", /* EBUSY */
"Too many open files", /* EMFILE */
"Too many open files in system",/* ENFILE */
"Bad file number", /* EBADF */
"Invalid or inappropriate ioctl",/* EIOCTL (ENOTTY in Unix) */
"Input/output error", /* EIO */
"Illegal seek", /* ESPIPE */
"Broken pipe", /* EPIPE */
"Read-only file system", /* EROFS */
"No space left on device", /* ENOSPC */
"Disc quota exceeded", /* EDQUOT */
"File too large", /* EFBIG */
"Invalid file type or format",/* EFTYPE */
"Argument out of range", /* EDOM */
"Result out of range", /* ERANGE */
"Invalid multibyte character sequence",/* EILSEQ */
"Not a socket", /* ENOTSOCK */
"Is a socket", /* EISSOCK (EOPNOTSUPP in Unix) */
"Socket is already connected",/* EISCONN */
"Socket is not connected", /* ENOTCONN */
"Socket has been shut down", /* ESHUTDOWN */
"Protocol family not supported",/* EPFNOSUPPORT */
"Socket type not supported", /* ESOCKTNOSUPPORT */
"Protocol not supported", /* EPROTONOSUPPORT */
"Protocol wrong type for socket",/* EPROTOTYPE */
"Address family not supported by protocol family",/* EAFNOSUPPORT */
"Protocol option not available",/* ENOPROTOOPT */
"Address already in use", /* EADDRINUSE */
"Cannot assign requested address",/* EADDRNOTAVAIL */
"Network is down", /* ENETDOWN */
"Network is unreachable", /* ENETUNREACH */
"Host is down", /* EHOSTDOWN */
"Host is unreachable", /* EHOSTUNREACH */
"Connection refused", /* ECONNREFUSED */
"Connection timed out", /* ETIMEDOUT */
"Connection reset by peer", /* ECONNRESET */
"Message too large", /* EMSGSIZE */
"Threads operation not supported",/* ENOTSUP */
"Operation succeeded", /* 0 */
"Function not implemented", /* ENOSYS */
"(undefined error 2)", /* unused */
"Out of memory", /* ENOMEM */
"Operation would block", /* EAGAIN (also EWOULDBLOCK) */
"Interrupted system call", /* EINTR */
"Bad memory reference", /* EFAULT */
"String too long", /* ENAMETOOLONG */
"Invalid argument", /* EINVAL */
"Operation not permitted", /* EPERM */
"Permission denied", /* EACCES */
"Too many processes", /* EMPROC (EPROCLIM in Unix) */
"Too many processes in system", /* ENPROC */
"File is not executable", /* ENOEXEC */
"Argument list too long", /* E2BIG */
"No such process", /* ESRCH */
"No child processes", /* ECHILD */
"Not a directory", /* ENOTDIR */
"Is a directory", /* EISDIR */
"No such file or directory", /* ENOENT */
"Too many levels of symbolic links", /* ELOOP */
"Directory not empty", /* ENOTEMPTY */
"File or object exists", /* EEXIST */
"Too many hard links", /* EMLINK */
"Cross-device link", /* EXDEV */
"No such device", /* ENODEV */
"Device not available", /* ENXIO */
"Device or resource busy", /* EBUSY */
"Too many open files", /* EMFILE */
"Too many open files in system", /* ENFILE */
"Bad file number", /* EBADF */
"Invalid or inappropriate ioctl", /* EIOCTL (ENOTTY in Unix) */
"Input/output error", /* EIO */
"Illegal seek", /* ESPIPE */
"Broken pipe", /* EPIPE */
"Read-only file system", /* EROFS */
"No space left on device", /* ENOSPC */
"Disc quota exceeded", /* EDQUOT */
"File too large", /* EFBIG */
"Invalid file type or format", /* EFTYPE */
"Argument out of range", /* EDOM */
"Result out of range", /* ERANGE */
"Invalid multibyte character sequence", /* EILSEQ */
"Not a socket", /* ENOTSOCK */
"Is a socket", /* EISSOCK (EOPNOTSUPP in Unix) */
"Socket is already connected", /* EISCONN */
"Socket is not connected", /* ENOTCONN */
"Socket has been shut down", /* ESHUTDOWN */
"Protocol family not supported", /* EPFNOSUPPORT */
"Socket type not supported", /* ESOCKTNOSUPPORT */
"Protocol not supported", /* EPROTONOSUPPORT */
"Protocol wrong type for socket", /* EPROTOTYPE */
"Address family not supported by protocol family", /* EAFNOSUPPORT */
"Protocol option not available", /* ENOPROTOOPT */
"Address already in use", /* EADDRINUSE */
"Cannot assign requested address", /* EADDRNOTAVAIL */
"Network is down", /* ENETDOWN */
"Network is unreachable", /* ENETUNREACH */
"Host is down", /* EHOSTDOWN */
"Host is unreachable", /* EHOSTUNREACH */
"Connection refused", /* ECONNREFUSED */
"Connection timed out", /* ETIMEDOUT */
"Connection reset by peer", /* ECONNRESET */
"Message too large", /* EMSGSIZE */
"Threads operation not supported", /* ENOTSUP */
};
/*
* Number of entries in sys_errlist.
*/
const int sys_nerr = sizeof(sys_errlist)/sizeof(const char *);
const int sys_nerr = sizeof(sys_errlist) / sizeof(const char *);
#endif /* _KERN_ERRMSG_H_ */

View File

@@ -42,70 +42,69 @@
* contain only symbolic constants.
*/
#define ENOSYS 1 /* Function not implemented */
#define ENOSYS 1 /* Function not implemented */
/* unused 2 */
#define ENOMEM 3 /* Out of memory */
#define EAGAIN 4 /* Operation would block */
#define EINTR 5 /* Interrupted system call */
#define EFAULT 6 /* Bad memory reference */
#define ENAMETOOLONG 7 /* String too long */
#define EINVAL 8 /* Invalid argument */
#define EPERM 9 /* Operation not permitted */
#define EACCES 10 /* Permission denied */
#define EMPROC 11 /* Too many processes */
#define ENPROC 12 /* Too many processes in system */
#define ENOEXEC 13 /* File is not executable */
#define E2BIG 14 /* Argument list too long */
#define ESRCH 15 /* No such process */
#define ECHILD 16 /* No child processes */
#define ENOTDIR 17 /* Not a directory */
#define EISDIR 18 /* Is a directory */
#define ENOENT 19 /* No such file or directory */
#define ELOOP 20 /* Too many levels of symbolic links */
#define ENOTEMPTY 21 /* Directory not empty */
#define EEXIST 22 /* File or object exists */
#define EMLINK 23 /* Too many hard links */
#define EXDEV 24 /* Cross-device link */
#define ENODEV 25 /* No such device */
#define ENXIO 26 /* Device not available */
#define EBUSY 27 /* Device or resource busy */
#define EMFILE 28 /* Too many open files */
#define ENFILE 29 /* Too many open files in system */
#define EBADF 30 /* Bad file number */
#define EIOCTL 31 /* Invalid or inappropriate ioctl */
#define EIO 32 /* Input/output error */
#define ESPIPE 33 /* Illegal seek */
#define EPIPE 34 /* Broken pipe */
#define EROFS 35 /* Read-only file system */
#define ENOSPC 36 /* No space left on device */
#define EDQUOT 37 /* Disc quota exceeded */
#define EFBIG 38 /* File too large */
#define EFTYPE 39 /* Invalid file type or format */
#define EDOM 40 /* Argument out of range */
#define ERANGE 41 /* Result out of range */
#define EILSEQ 42 /* Invalid multibyte character sequence */
#define ENOTSOCK 43 /* Not a socket */
#define EISSOCK 44 /* Is a socket */
#define EISCONN 45 /* Socket is already connected */
#define ENOTCONN 46 /* Socket is not connected */
#define ESHUTDOWN 47 /* Socket has been shut down */
#define EPFNOSUPPORT 48 /* Protocol family not supported */
#define ESOCKTNOSUPPORT 49 /* Socket type not supported */
#define EPROTONOSUPPORT 50 /* Protocol not supported */
#define EPROTOTYPE 51 /* Protocol wrong type for socket */
#define EAFNOSUPPORT 52 /* Address family not supported by protocol family */
#define ENOPROTOOPT 53 /* Protocol option not available */
#define EADDRINUSE 54 /* Address already in use */
#define EADDRNOTAVAIL 55 /* Cannot assign requested address */
#define ENETDOWN 56 /* Network is down */
#define ENETUNREACH 57 /* Network is unreachable */
#define EHOSTDOWN 58 /* Host is down */
#define EHOSTUNREACH 59 /* Host is unreachable */
#define ECONNREFUSED 60 /* Connection refused */
#define ETIMEDOUT 61 /* Connection timed out */
#define ECONNRESET 62 /* Connection reset by peer */
#define EMSGSIZE 63 /* Message too large */
#define ENOTSUP 64 /* Threads operation not supported */
#define ENOMEM 3 /* Out of memory */
#define EAGAIN 4 /* Operation would block */
#define EINTR 5 /* Interrupted system call */
#define EFAULT 6 /* Bad memory reference */
#define ENAMETOOLONG 7 /* String too long */
#define EINVAL 8 /* Invalid argument */
#define EPERM 9 /* Operation not permitted */
#define EACCES 10 /* Permission denied */
#define EMPROC 11 /* Too many processes */
#define ENPROC 12 /* Too many processes in system */
#define ENOEXEC 13 /* File is not executable */
#define E2BIG 14 /* Argument list too long */
#define ESRCH 15 /* No such process */
#define ECHILD 16 /* No child processes */
#define ENOTDIR 17 /* Not a directory */
#define EISDIR 18 /* Is a directory */
#define ENOENT 19 /* No such file or directory */
#define ELOOP 20 /* Too many levels of symbolic links */
#define ENOTEMPTY 21 /* Directory not empty */
#define EEXIST 22 /* File or object exists */
#define EMLINK 23 /* Too many hard links */
#define EXDEV 24 /* Cross-device link */
#define ENODEV 25 /* No such device */
#define ENXIO 26 /* Device not available */
#define EBUSY 27 /* Device or resource busy */
#define EMFILE 28 /* Too many open files */
#define ENFILE 29 /* Too many open files in system */
#define EBADF 30 /* Bad file number */
#define EIOCTL 31 /* Invalid or inappropriate ioctl */
#define EIO 32 /* Input/output error */
#define ESPIPE 33 /* Illegal seek */
#define EPIPE 34 /* Broken pipe */
#define EROFS 35 /* Read-only file system */
#define ENOSPC 36 /* No space left on device */
#define EDQUOT 37 /* Disc quota exceeded */
#define EFBIG 38 /* File too large */
#define EFTYPE 39 /* Invalid file type or format */
#define EDOM 40 /* Argument out of range */
#define ERANGE 41 /* Result out of range */
#define EILSEQ 42 /* Invalid multibyte character sequence */
#define ENOTSOCK 43 /* Not a socket */
#define EISSOCK 44 /* Is a socket */
#define EISCONN 45 /* Socket is already connected */
#define ENOTCONN 46 /* Socket is not connected */
#define ESHUTDOWN 47 /* Socket has been shut down */
#define EPFNOSUPPORT 48 /* Protocol family not supported */
#define ESOCKTNOSUPPORT 49 /* Socket type not supported */
#define EPROTONOSUPPORT 50 /* Protocol not supported */
#define EPROTOTYPE 51 /* Protocol wrong type for socket */
#define EAFNOSUPPORT 52 /* Address family not supported by protocol family */
#define ENOPROTOOPT 53 /* Protocol option not available */
#define EADDRINUSE 54 /* Address already in use */
#define EADDRNOTAVAIL 55 /* Cannot assign requested address */
#define ENETDOWN 56 /* Network is down */
#define ENETUNREACH 57 /* Network is unreachable */
#define EHOSTDOWN 58 /* Host is down */
#define EHOSTUNREACH 59 /* Host is unreachable */
#define ECONNREFUSED 60 /* Connection refused */
#define ETIMEDOUT 61 /* Connection timed out */
#define ECONNRESET 62 /* Connection reset by peer */
#define EMSGSIZE 63 /* Message too large */
#define ENOTSUP 64 /* Threads operation not supported */
#endif /* _KERN_ERRNO_H_ */

View File

@@ -34,67 +34,65 @@
* Constants for libc's <fcntl.h>.
*/
/*
* Important
*/
/* Flags for open: choose one of these: */
#define O_RDONLY 0 /* Open for read */
#define O_WRONLY 1 /* Open for write */
#define O_RDWR 2 /* Open for read and write */
#define O_RDONLY 0 /* Open for read */
#define O_WRONLY 1 /* Open for write */
#define O_RDWR 2 /* Open for read and write */
/* then or in any of these: */
#define O_CREAT 4 /* Create file if it doesn't exist */
#define O_EXCL 8 /* With O_CREAT, fail if file already exists */
#define O_TRUNC 16 /* Truncate file upon open */
#define O_APPEND 32 /* All writes happen at EOF (optional feature) */
#define O_NOCTTY 64 /* Required by POSIX, != 0, but does nothing */
#define O_CREAT 4 /* Create file if it doesn't exist */
#define O_EXCL 8 /* With O_CREAT, fail if file already exists */
#define O_TRUNC 16 /* Truncate file upon open */
#define O_APPEND 32 /* All writes happen at EOF (optional feature) */
#define O_NOCTTY 64 /* Required by POSIX, != 0, but does nothing */
/* Additional related definition */
#define O_ACCMODE 3 /* mask for O_RDONLY/O_WRONLY/O_RDWR */
#define O_ACCMODE 3 /* mask for O_RDONLY/O_WRONLY/O_RDWR */
/*
* Not so important
*/
/* operation codes for flock() */
#define LOCK_SH 1 /* shared lock */
#define LOCK_EX 2 /* exclusive lock */
#define LOCK_UN 3 /* release the lock */
#define LOCK_NB 4 /* flag: don't block */
#define LOCK_SH 1 /* shared lock */
#define LOCK_EX 2 /* exclusive lock */
#define LOCK_UN 3 /* release the lock */
#define LOCK_NB 4 /* flag: don't block */
/*
* Mostly pretty useless
*/
/* fcntl() operations */
#define F_DUPFD 0 /* like dup() but not quite */
#define F_GETFD 1 /* get per-handle flags */
#define F_SETFD 2 /* set per-handle flags */
#define F_GETFL 3 /* get per-file flags (O_* open flags) */
#define F_SETFL 4 /* set per-file flags (O_* open flags) */
#define F_GETOWN 5 /* get process/pgroup for SIGURG and SIGIO */
#define F_SETOWN 6 /* set process/pgroup for SIGURG and SIGIO */
#define F_GETLK 7 /* inspect record locks */
#define F_SETLK 8 /* acquire record locks nonblocking */
#define F_SETLKW 9 /* acquire record locks and wait */
#define F_DUPFD 0 /* like dup() but not quite */
#define F_GETFD 1 /* get per-handle flags */
#define F_SETFD 2 /* set per-handle flags */
#define F_GETFL 3 /* get per-file flags (O_* open flags) */
#define F_SETFL 4 /* set per-file flags (O_* open flags) */
#define F_GETOWN 5 /* get process/pgroup for SIGURG and SIGIO */
#define F_SETOWN 6 /* set process/pgroup for SIGURG and SIGIO */
#define F_GETLK 7 /* inspect record locks */
#define F_SETLK 8 /* acquire record locks nonblocking */
#define F_SETLKW 9 /* acquire record locks and wait */
/* flag for F_GETFD and F_SETFD */
#define FD_CLOEXEC 1 /* close-on-exec */
#define FD_CLOEXEC 1 /* close-on-exec */
/* modes for fcntl (F_GETLK/SETLK) locking */
#define F_RDLCK 0 /* shared lock */
#define F_WRLCK 1 /* exclusive lock */
#define F_UNLCK 2 /* unlock */
#define F_RDLCK 0 /* shared lock */
#define F_WRLCK 1 /* exclusive lock */
#define F_UNLCK 2 /* unlock */
/* struct for fcntl (F_GETLK/SETLK) locking */
struct flock {
off_t l_start; /* place in file */
int l_whence; /* SEEK_SET, SEEK_CUR, or SEEK_END */
int l_type; /* F_RDLCK or F_WRLCK */
off_t l_len; /* length of locked region */
pid_t l_pid; /* process that holds the lock */
off_t l_start; /* place in file */
int l_whence; /* SEEK_SET, SEEK_CUR, or SEEK_END */
int l_type; /* F_RDLCK or F_WRLCK */
off_t l_len; /* length of locked region */
pid_t l_pid; /* process that holds the lock */
};
#endif /* _KERN_FCNTL_H_ */

View File

@@ -36,33 +36,33 @@
*/
struct iovec {
/*
* For maximum type safety, when in the kernel, distinguish
* user pointers from kernel pointers.
*
* (A pointer is a user pointer if it *came* from userspace,
* not necessarily if it *points* to userspace. If a system
* call passes 0xdeadbeef, it points to the kernel, but it's
* still a user pointer.)
*
* In userspace, there are only user pointers; also, the name
* iov_base is defined by POSIX.
*
* Note that to work properly (without extra unwanted fiddling
* around) this scheme requires that void* and userptr_t have
* the same machine representation. Machines where this isn't
* true are theoretically possible under the C standard, but
* do not exist in practice.
*/
/*
* For maximum type safety, when in the kernel, distinguish
* user pointers from kernel pointers.
*
* (A pointer is a user pointer if it *came* from userspace,
* not necessarily if it *points* to userspace. If a system
* call passes 0xdeadbeef, it points to the kernel, but it's
* still a user pointer.)
*
* In userspace, there are only user pointers; also, the name
* iov_base is defined by POSIX.
*
* Note that to work properly (without extra unwanted fiddling
* around) this scheme requires that void* and userptr_t have
* the same machine representation. Machines where this isn't
* true are theoretically possible under the C standard, but
* do not exist in practice.
*/
#ifdef _KERNEL
union {
userptr_t iov_ubase; /* user-supplied pointer */
void *iov_kbase; /* kernel-supplied pointer */
};
union {
userptr_t iov_ubase; /* user-supplied pointer */
void *iov_kbase; /* kernel-supplied pointer */
};
#else
void *iov_base; /* user-supplied pointer */
void *iov_base; /* user-supplied pointer */
#endif
size_t iov_len; /* Length of data */
size_t iov_len; /* Length of data */
};
#endif /* _KERN_IOVEC_H_ */

View File

@@ -47,7 +47,6 @@
* implementation.
*/
/*
* Important, both as part of the system call API and for system behavior.
*
@@ -57,14 +56,13 @@
*/
/* Longest filename (without directory) not including null terminator */
#define __NAME_MAX 255
#define __NAME_MAX 255
/* Longest full path name */
#define __PATH_MAX 1024
#define __PATH_MAX 1024
/* Max bytes for an exec function (should be at least 16K) */
#define __ARG_MAX (64 * 1024)
#define __ARG_MAX (64 * 1024)
/*
* Important for system behavior, but not a big part of the API.
@@ -74,17 +72,16 @@
*/
/* Min value for a process ID (that can be assigned to a user process) */
#define __PID_MIN 2
#define __PID_MIN 2
/* Max value for a process ID (change this to match your implementation) */
#define __PID_MAX 32767
#define __PID_MAX 32767
/* Max open files per process */
#define __OPEN_MAX 128
#define __OPEN_MAX 128
/* Max bytes for atomic pipe I/O -- see description in the pipe() man page */
#define __PIPE_BUF 512
#define __PIPE_BUF 512
/*
* Not so important parts of the API. (Especially in OS/161 where we
@@ -92,18 +89,16 @@
*/
/* Max number of supplemental group IDs in process credentials */
#define __NGROUPS_MAX 32
#define __NGROUPS_MAX 32
/* Max login name size (for setlogin/getlogin), incl. null */
#define __LOGIN_NAME_MAX 17
/*
* Not very important at all.
*/
/* Max number of iovec structures at once for readv/writev/preadv/pwritev */
#define __IOV_MAX 1024
#define __IOV_MAX 1024
#endif /* _KERN_LIMITS_H_ */

View File

@@ -35,11 +35,9 @@
* (Not all that important.)
*/
/* Codes for reboot */
#define RB_REBOOT 0 /* Reboot system */
#define RB_HALT 1 /* Halt system and do not reboot */
#define RB_POWEROFF 2 /* Halt system and power off */
#define RB_REBOOT 0 /* Reboot system */
#define RB_HALT 1 /* Halt system and do not reboot */
#define RB_POWEROFF 2 /* Halt system and power off */
#endif /* _KERN_REBOOT_H_ */

View File

@@ -36,57 +36,56 @@
* Not very important.
*/
/* priorities for setpriority() */
#define PRIO_MIN (-20)
#define PRIO_MAX 20
#define PRIO_MIN (-20)
#define PRIO_MAX 20
/* "which" codes for setpriority() */
#define PRIO_PROCESS 0
#define PRIO_PGRP 1
#define PRIO_USER 2
#define PRIO_PROCESS 0
#define PRIO_PGRP 1
#define PRIO_USER 2
/* flags for getrusage() */
#define RUSAGE_SELF 0
#define RUSAGE_CHILDREN (-1)
#define RUSAGE_SELF 0
#define RUSAGE_CHILDREN (-1)
struct rusage {
struct timeval ru_utime;
struct timeval ru_stime;
__size_t ru_maxrss; /* maximum RSS during lifespan (kb) */
__counter_t ru_ixrss; /* text memory usage (kb-ticks) */
__counter_t ru_idrss; /* data memory usage (kb-ticks) */
__counter_t ru_isrss; /* stack memory usage (kb-ticks) */
__counter_t ru_minflt; /* minor VM faults (count) */
__counter_t ru_majflt; /* major VM faults (count) */
__counter_t ru_nswap; /* whole-process swaps (count) */
__counter_t ru_inblock; /* file blocks read (count) */
__counter_t ru_oublock; /* file blocks written (count) */
__counter_t ru_msgrcv; /* socket/pipe packets rcv'd (count) */
__counter_t ru_msgsnd; /* socket/pipe packets sent (count) */
__counter_t ru_nsignals; /* signals delivered (count) */
__counter_t ru_nvcsw; /* voluntary context switches (count)*/
__counter_t ru_nivcsw; /* involuntary ditto (count) */
struct timeval ru_utime;
struct timeval ru_stime;
__size_t ru_maxrss; /* maximum RSS during lifespan (kb) */
__counter_t ru_ixrss; /* text memory usage (kb-ticks) */
__counter_t ru_idrss; /* data memory usage (kb-ticks) */
__counter_t ru_isrss; /* stack memory usage (kb-ticks) */
__counter_t ru_minflt; /* minor VM faults (count) */
__counter_t ru_majflt; /* major VM faults (count) */
__counter_t ru_nswap; /* whole-process swaps (count) */
__counter_t ru_inblock; /* file blocks read (count) */
__counter_t ru_oublock; /* file blocks written (count) */
__counter_t ru_msgrcv; /* socket/pipe packets rcv'd (count) */
__counter_t ru_msgsnd; /* socket/pipe packets sent (count) */
__counter_t ru_nsignals; /* signals delivered (count) */
__counter_t ru_nvcsw; /* voluntary context switches (count)*/
__counter_t ru_nivcsw; /* involuntary ditto (count) */
};
/* limit codes for getrusage/setrusage */
#define RLIMIT_NPROC 0 /* max procs per user (count) */
#define RLIMIT_NOFILE 1 /* max open files per proc (count) */
#define RLIMIT_CPU 2 /* cpu usage (seconds) */
#define RLIMIT_DATA 3 /* max .data/sbrk size (bytes) */
#define RLIMIT_STACK 4 /* max stack size (bytes) */
#define RLIMIT_MEMLOCK 5 /* max locked memory region (bytes) */
#define RLIMIT_RSS 6 /* max RSS (bytes) */
#define RLIMIT_CORE 7 /* core file size (bytes) */
#define RLIMIT_FSIZE 8 /* max file size (bytes) */
#define __RLIMIT_NUM 9 /* number of limits */
#define RLIMIT_NPROC 0 /* max procs per user (count) */
#define RLIMIT_NOFILE 1 /* max open files per proc (count) */
#define RLIMIT_CPU 2 /* cpu usage (seconds) */
#define RLIMIT_DATA 3 /* max .data/sbrk size (bytes) */
#define RLIMIT_STACK 4 /* max stack size (bytes) */
#define RLIMIT_MEMLOCK 5 /* max locked memory region (bytes) */
#define RLIMIT_RSS 6 /* max RSS (bytes) */
#define RLIMIT_CORE 7 /* core file size (bytes) */
#define RLIMIT_FSIZE 8 /* max file size (bytes) */
#define __RLIMIT_NUM 9 /* number of limits */
struct rlimit {
__rlim_t rlim_cur; /* soft limit */
__rlim_t rlim_max; /* hard limit */
__rlim_t rlim_cur; /* soft limit */
__rlim_t rlim_max; /* hard limit */
};
#define RLIM_INFINITY (~(__rlim_t)0)
#define RLIM_INFINITY (~(__rlim_t)0)
#endif /* _KERN_RESOURCE_H_ */

View File

@@ -39,9 +39,8 @@
* really not recommended.
*/
#define SEEK_SET 0 /* Seek relative to beginning of file */
#define SEEK_CUR 1 /* Seek relative to current position in file */
#define SEEK_END 2 /* Seek relative to end of file */
#define SEEK_SET 0 /* Seek relative to beginning of file */
#define SEEK_CUR 1 /* Seek relative to current position in file */
#define SEEK_END 2 /* Seek relative to end of file */
#endif /* _KERN_SEEK_H_ */

View File

@@ -30,72 +30,70 @@
#ifndef _KERN_SFS_H_
#define _KERN_SFS_H_
/*
* SFS definitions visible to userspace. This covers the on-disk format
* and is used by tools that work on SFS volumes, such as mksfs.
*/
#define SFS_MAGIC 0xabadf001 /* magic number identifying us */
#define SFS_BLOCKSIZE 512 /* size of our blocks */
#define SFS_VOLNAME_SIZE 32 /* max length of volume name */
#define SFS_NDIRECT 15 /* # of direct blocks in inode */
#define SFS_NINDIRECT 1 /* # of indirect blocks in inode */
#define SFS_NDINDIRECT 0 /* # of 2x indirect blocks in inode */
#define SFS_NTINDIRECT 0 /* # of 3x indirect blocks in inode */
#define SFS_DBPERIDB 128 /* # direct blks per indirect blk */
#define SFS_NAMELEN 60 /* max length of filename */
#define SFS_SUPER_BLOCK 0 /* block the superblock lives in */
#define SFS_FREEMAP_START 2 /* 1st block of the freemap */
#define SFS_NOINO 0 /* inode # for free dir entry */
#define SFS_ROOTDIR_INO 1 /* loc'n of the root dir inode */
#define SFS_MAGIC 0xabadf001 /* magic number identifying us */
#define SFS_BLOCKSIZE 512 /* size of our blocks */
#define SFS_VOLNAME_SIZE 32 /* max length of volume name */
#define SFS_NDIRECT 15 /* # of direct blocks in inode */
#define SFS_NINDIRECT 1 /* # of indirect blocks in inode */
#define SFS_NDINDIRECT 0 /* # of 2x indirect blocks in inode */
#define SFS_NTINDIRECT 0 /* # of 3x indirect blocks in inode */
#define SFS_DBPERIDB 128 /* # direct blks per indirect blk */
#define SFS_NAMELEN 60 /* max length of filename */
#define SFS_SUPER_BLOCK 0 /* block the superblock lives in */
#define SFS_FREEMAP_START 2 /* 1st block of the freemap */
#define SFS_NOINO 0 /* inode # for free dir entry */
#define SFS_ROOTDIR_INO 1 /* loc'n of the root dir inode */
/* Number of bits in a block */
#define SFS_BITSPERBLOCK (SFS_BLOCKSIZE * CHAR_BIT)
/* Utility macro */
#define SFS_ROUNDUP(a,b) ((((a)+(b)-1)/(b))*b)
#define SFS_ROUNDUP(a, b) ((((a) + (b) - 1) / (b)) * b)
/* Size of free block bitmap (in bits) */
#define SFS_FREEMAPBITS(nblocks) SFS_ROUNDUP(nblocks, SFS_BITSPERBLOCK)
/* Size of free block bitmap (in blocks) */
#define SFS_FREEMAPBLOCKS(nblocks) (SFS_FREEMAPBITS(nblocks)/SFS_BITSPERBLOCK)
#define SFS_FREEMAPBLOCKS(nblocks) (SFS_FREEMAPBITS(nblocks) / SFS_BITSPERBLOCK)
/* File types for sfi_type */
#define SFS_TYPE_INVAL 0 /* Should not appear on disk */
#define SFS_TYPE_FILE 1
#define SFS_TYPE_DIR 2
#define SFS_TYPE_INVAL 0 /* Should not appear on disk */
#define SFS_TYPE_FILE 1
#define SFS_TYPE_DIR 2
/*
* On-disk superblock
*/
struct sfs_superblock {
uint32_t sb_magic; /* Magic number; should be SFS_MAGIC */
uint32_t sb_nblocks; /* Number of blocks in fs */
char sb_volname[SFS_VOLNAME_SIZE]; /* Name of this volume */
uint32_t reserved[118]; /* unused, set to 0 */
uint32_t sb_magic; /* Magic number; should be SFS_MAGIC */
uint32_t sb_nblocks; /* Number of blocks in fs */
char sb_volname[SFS_VOLNAME_SIZE]; /* Name of this volume */
uint32_t reserved[118]; /* unused, set to 0 */
};
/*
* On-disk inode
*/
struct sfs_dinode {
uint32_t sfi_size; /* Size of this file (bytes) */
uint16_t sfi_type; /* One of SFS_TYPE_* above */
uint16_t sfi_linkcount; /* # hard links to this file */
uint32_t sfi_direct[SFS_NDIRECT]; /* Direct blocks */
uint32_t sfi_indirect; /* Indirect block */
uint32_t sfi_waste[128-3-SFS_NDIRECT]; /* unused space, set to 0 */
uint32_t sfi_size; /* Size of this file (bytes) */
uint16_t sfi_type; /* One of SFS_TYPE_* above */
uint16_t sfi_linkcount; /* # hard links to this file */
uint32_t sfi_direct[SFS_NDIRECT]; /* Direct blocks */
uint32_t sfi_indirect; /* Indirect block */
uint32_t sfi_waste[128 - 3 - SFS_NDIRECT]; /* unused space, set to 0 */
};
/*
* On-disk directory entry
*/
struct sfs_direntry {
uint32_t sfd_ino; /* Inode number */
char sfd_name[SFS_NAMELEN]; /* Filename */
uint32_t sfd_ino; /* Inode number */
char sfd_name[SFS_NAMELEN]; /* Filename */
};
#endif /* _KERN_SFS_H_ */

View File

@@ -41,7 +41,6 @@
* Machine-independent definitions for signals.
*/
/*
* The signals.
*
@@ -53,68 +52,67 @@
* ways. It is gross.
*/
#define SIGHUP 1 /* Hangup */
#define SIGINT 2 /* Interrupt (^C) */
#define SIGQUIT 3 /* Quit (typically ^\) */
#define SIGILL 4 /* Illegal instruction */
#define SIGTRAP 5 /* Breakpoint trap */
#define SIGABRT 6 /* abort() call */
#define SIGEMT 7 /* Emulator trap */
#define SIGFPE 8 /* Floating point exception */
#define SIGKILL 9 /* Hard kill (unblockable) */
#define SIGBUS 10 /* Bus error, typically bad pointer alignment*/
#define SIGSEGV 11 /* Segmentation fault */
#define SIGSYS 12 /* Bad system call */
#define SIGPIPE 13 /* Broken pipe */
#define SIGALRM 14 /* alarm() expired */
#define SIGTERM 15 /* Termination requested (default kill) */
#define SIGURG 16 /* Urgent data on socket */
#define SIGSTOP 17 /* Hard process stop (unblockable) */
#define SIGTSTP 18 /* Terminal stop (^Z) */
#define SIGCONT 19 /* Time to continue after stop */
#define SIGCHLD 20 /* Child process exited */
#define SIGTTIN 21 /* Stop on tty read while in background */
#define SIGTTOU 22 /* Stop on tty write while in background */
#define SIGIO 23 /* Nonblocking or async I/O is now ready */
#define SIGXCPU 24 /* CPU time resource limit exceeded */
#define SIGXFSZ 25 /* File size resource limit exceeded */
#define SIGVTALRM 26 /* Like SIGALRM but in virtual time */
#define SIGPROF 27 /* Profiling timer */
#define SIGWINCH 28 /* Window size change on tty */
#define SIGINFO 29 /* Information request (typically ^T) */
#define SIGUSR1 20 /* Application-defined */
#define SIGUSR2 31 /* Application-defined */
#define SIGPWR 32 /* Power failure */
#define _NSIG 32
#define SIGHUP 1 /* Hangup */
#define SIGINT 2 /* Interrupt (^C) */
#define SIGQUIT 3 /* Quit (typically ^\) */
#define SIGILL 4 /* Illegal instruction */
#define SIGTRAP 5 /* Breakpoint trap */
#define SIGABRT 6 /* abort() call */
#define SIGEMT 7 /* Emulator trap */
#define SIGFPE 8 /* Floating point exception */
#define SIGKILL 9 /* Hard kill (unblockable) */
#define SIGBUS 10 /* Bus error, typically bad pointer alignment*/
#define SIGSEGV 11 /* Segmentation fault */
#define SIGSYS 12 /* Bad system call */
#define SIGPIPE 13 /* Broken pipe */
#define SIGALRM 14 /* alarm() expired */
#define SIGTERM 15 /* Termination requested (default kill) */
#define SIGURG 16 /* Urgent data on socket */
#define SIGSTOP 17 /* Hard process stop (unblockable) */
#define SIGTSTP 18 /* Terminal stop (^Z) */
#define SIGCONT 19 /* Time to continue after stop */
#define SIGCHLD 20 /* Child process exited */
#define SIGTTIN 21 /* Stop on tty read while in background */
#define SIGTTOU 22 /* Stop on tty write while in background */
#define SIGIO 23 /* Nonblocking or async I/O is now ready */
#define SIGXCPU 24 /* CPU time resource limit exceeded */
#define SIGXFSZ 25 /* File size resource limit exceeded */
#define SIGVTALRM 26 /* Like SIGALRM but in virtual time */
#define SIGPROF 27 /* Profiling timer */
#define SIGWINCH 28 /* Window size change on tty */
#define SIGINFO 29 /* Information request (typically ^T) */
#define SIGUSR1 20 /* Application-defined */
#define SIGUSR2 31 /* Application-defined */
#define SIGPWR 32 /* Power failure */
#define _NSIG 32
/* Type for a set of signals; used by e.g. sigprocmask(). */
typedef __u32 sigset_t;
/* flags for sigaction.sa_flags */
#define SA_ONSTACK 1 /* Use sigaltstack() stack. */
#define SA_RESTART 2 /* Restart syscall instead of interrupting. */
#define SA_RESETHAND 4 /* Clear handler after one usage. */
#define SA_ONSTACK 1 /* Use sigaltstack() stack. */
#define SA_RESTART 2 /* Restart syscall instead of interrupting. */
#define SA_RESETHAND 4 /* Clear handler after one usage. */
/* codes for sigprocmask() */
#define SIG_BLOCK 1 /* Block selected signals. */
#define SIG_UNBLOCK 2 /* Unblock selected signals. */
#define SIG_SETMASK 3 /* Set mask to the selected signals. */
#define SIG_BLOCK 1 /* Block selected signals. */
#define SIG_UNBLOCK 2 /* Unblock selected signals. */
#define SIG_SETMASK 3 /* Set mask to the selected signals. */
/* Type for a signal handler function. */
typedef void (*__sigfunc)(int);
/* Magic values for signal handlers. */
#define SIG_DFL ((__sigfunc) 0) /* Default behavior. */
#define SIG_IGN ((__sigfunc) 1) /* Ignore the signal. */
#define SIG_DFL ((__sigfunc)0) /* Default behavior. */
#define SIG_IGN ((__sigfunc)1) /* Ignore the signal. */
/*
* Struct for sigaction().
*/
struct sigaction {
__sigfunc sa_handler;
sigset_t sa_mask;
unsigned sa_flags;
__sigfunc sa_handler;
sigset_t sa_mask;
unsigned sa_flags;
};
/*
@@ -122,10 +120,9 @@ struct sigaction {
* (not very important)
*/
struct sigaltstack {
void *ss_sp;
size_t ss_size;
unsigned ss_flags;
void *ss_sp;
size_t ss_size;
unsigned ss_flags;
};
#endif /* _KERN_SIGNAL_H_ */

View File

@@ -34,27 +34,26 @@
* Socket-related definitions, for <sys/socket.h>.
*/
/*
* Important
*/
/* Socket types that we (might) support. */
#define SOCK_STREAM 1 /* stream */
#define SOCK_DGRAM 2 /* packet */
#define SOCK_RAW 3 /* raw packet */
#define SOCK_STREAM 1 /* stream */
#define SOCK_DGRAM 2 /* packet */
#define SOCK_RAW 3 /* raw packet */
/* Address families that we (might) support. */
#define AF_UNSPEC 0
#define AF_UNIX 1
#define AF_INET 2
#define AF_INET6 3
#define AF_UNSPEC 0
#define AF_UNIX 1
#define AF_INET 2
#define AF_INET6 3
/* Protocol families. Pointless layer of indirection in the standard API. */
#define PF_UNSPEC AF_UNSPEC
#define PF_UNIX AF_UNIX
#define PF_INET AF_INET
#define PF_INET6 AF_INET6
#define PF_UNSPEC AF_UNSPEC
#define PF_UNIX AF_UNIX
#define PF_INET AF_INET
#define PF_INET6 AF_INET6
/*
* Socket address structures. Socket addresses are polymorphic, and
@@ -71,22 +70,21 @@
*/
struct sockaddr {
__u8 sa_len;
__u8 sa_family;
__u8 sa_len;
__u8 sa_family;
};
#define _SS_SIZE 128
#define _SS_SIZE 128
struct sockaddr_storage {
__u8 ss_len;
__u8 ss_family;
__u8 __ss_pad1;
__u8 __ss_pad2;
__u32 __ss_pad3;
__u64 __ss_pad4;
char __ss_pad5[_SS_SIZE - sizeof(__u64) - sizeof(__u32) - 4*sizeof(__u8)];
__u8 ss_len;
__u8 ss_family;
__u8 __ss_pad1;
__u8 __ss_pad2;
__u32 __ss_pad3;
__u64 __ss_pad4;
char __ss_pad5[_SS_SIZE - sizeof(__u64) - sizeof(__u32) - 4 * sizeof(__u8)];
};
/*
* Not very important.
*/
@@ -96,21 +94,20 @@ struct sockaddr_storage {
*/
struct msghdr {
void *msg_name; /* really sockaddr; address, or null */
socklen_t msg_namelen; /* size of msg_name object, or 0 */
struct iovec *msg_iov; /* I/O buffers */
int msg_iovlen; /* number of iovecs */
void *msg_control; /* auxiliary data area, or null */
socklen_t msg_controllen; /* size of msg_control area */
int msg_flags; /* flags */
void *msg_name; /* really sockaddr; address, or null */
socklen_t msg_namelen; /* size of msg_name object, or 0 */
struct iovec *msg_iov; /* I/O buffers */
int msg_iovlen; /* number of iovecs */
void *msg_control; /* auxiliary data area, or null */
socklen_t msg_controllen; /* size of msg_control area */
int msg_flags; /* flags */
};
struct cmsghdr {
socklen_t cmsg_len; /* length of control data, including header */
int cmsg_level; /* protocol layer item originates from */
int cmsg_type; /* protocol-specific message type */
/* char cmsg_data[];*/ /* data follows the header */
socklen_t cmsg_len; /* length of control data, including header */
int cmsg_level; /* protocol layer item originates from */
int cmsg_type; /* protocol-specific message type */
/* char cmsg_data[];*/ /* data follows the header */
};
#endif /* _KERN_SOCKET_H_ */

View File

@@ -40,32 +40,32 @@
* The file types are in kern/stattypes.h.
*/
struct stat {
/* Essential fields */
off_t st_size; /* file size in bytes */
mode_t st_mode; /* file type and protection mode */
nlink_t st_nlink; /* number of hard links */
blkcnt_t st_blocks; /* number of blocks file is using */
/* Essential fields */
off_t st_size; /* file size in bytes */
mode_t st_mode; /* file type and protection mode */
nlink_t st_nlink; /* number of hard links */
blkcnt_t st_blocks; /* number of blocks file is using */
/* Identity */
dev_t st_dev; /* device object lives on */
ino_t st_ino; /* inode number (serial number) of object */
dev_t st_rdev; /* device object is (if a device) */
/* Identity */
dev_t st_dev; /* device object lives on */
ino_t st_ino; /* inode number (serial number) of object */
dev_t st_rdev; /* device object is (if a device) */
/* Timestamps */
time_t st_atime; /* last access time: seconds */
time_t st_ctime; /* inode change time: seconds */
time_t st_mtime; /* modification time: seconds */
__u32 st_atimensec; /* last access time: nanoseconds */
__u32 st_ctimensec; /* inode change time: nanoseconds */
__u32 st_mtimensec; /* modification time: nanoseconds */
/* Timestamps */
time_t st_atime; /* last access time: seconds */
time_t st_ctime; /* inode change time: seconds */
time_t st_mtime; /* modification time: seconds */
__u32 st_atimensec; /* last access time: nanoseconds */
__u32 st_ctimensec; /* inode change time: nanoseconds */
__u32 st_mtimensec; /* modification time: nanoseconds */
/* Permissions (also st_mode) */
uid_t st_uid; /* owner */
gid_t st_gid; /* group */
/* Permissions (also st_mode) */
uid_t st_uid; /* owner */
gid_t st_gid; /* group */
/* Other */
__u32 st_gen; /* file generation number (root only) */
blksize_t st_blksize; /* recommended I/O block size */
/* Other */
__u32 st_gen; /* file generation number (root only) */
blksize_t st_blksize; /* recommended I/O block size */
};
#endif /* _KERN_STAT_H_ */

Some files were not shown because too many files have changed in this diff Show More