Page MenuHomeFreeBSD

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
Index: projects/altix/lib/libstand
===================================================================
--- projects/altix/lib/libstand (revision 218875)
+++ projects/altix/lib/libstand (revision 218876)
Property changes on: projects/altix/lib/libstand
___________________________________________________________________
Modified: svn:mergeinfo
## -0,0 +0,1 ##
Merged /head/lib/libstand:r218817-218875
Index: projects/altix/sys/amd64/include/xen
===================================================================
--- projects/altix/sys/amd64/include/xen (revision 218875)
+++ projects/altix/sys/amd64/include/xen (revision 218876)
Property changes on: projects/altix/sys/amd64/include/xen
___________________________________________________________________
Modified: svn:mergeinfo
## -0,0 +0,1 ##
Merged /head/sys/amd64/include/xen:r218817-218875
Index: projects/altix/sys/boot/i386/efi/ldscript.amd64
===================================================================
--- projects/altix/sys/boot/i386/efi/ldscript.amd64 (revision 218875)
+++ projects/altix/sys/boot/i386/efi/ldscript.amd64 (revision 218876)
@@ -1,75 +1,75 @@
/* $FreeBSD$ */
-OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
+OUTPUT_FORMAT("elf64-x86-64-freebsd", "elf64-x86-64-freebsd", "elf64-x86-64-freebsd")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_start)
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = 0;
ImageBase = .;
. = SIZEOF_HEADERS;
. = ALIGN(4096);
.eh_frame : {
*(.eh_frame)
}
.text : {
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.plt)
} =0x00300000010070000002000001000400
. = ALIGN(4096);
.data : {
*(.rodata .rodata.* .gnu.linkonce.r.*)
*(.rodata1)
*(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
*(.sbss2 .sbss2.* .gnu.linkonce.sb2.*)
*(.opd)
*(.data .data.* .gnu.linkonce.d.*)
*(.data1)
*(.plabel)
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
}
. = ALIGN(4096);
set_Xcommand_set : {
__start_set_Xcommand_set = .;
*(set_Xcommand_set)
__stop_set_Xcommand_set = .;
}
. = ALIGN(4096);
__gp = .;
.sdata : {
*(.got.plt .got)
*(.sdata .sdata.* .gnu.linkonce.s.*)
*(dynsbss)
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
}
. = ALIGN(4096);
.dynamic : { *(.dynamic) }
. = ALIGN(4096);
.rel.dyn : {
*(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
*(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
*(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
*(.rel.got)
*(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*)
*(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*)
*(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*)
*(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*)
*(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
*(.rel.plt)
*(.relset_*)
*(.rel.dyn .rel.dyn.*)
}
. = ALIGN(4096);
.reloc : { *(.reloc) }
. = ALIGN(4096);
.hash : { *(.hash) }
. = ALIGN(4096);
.dynsym : { *(.dynsym) }
. = ALIGN(4096);
.dynstr : { *(.dynstr) }
}
Index: projects/altix/sys/boot/i386/efi
===================================================================
--- projects/altix/sys/boot/i386/efi (revision 218875)
+++ projects/altix/sys/boot/i386/efi (revision 218876)
Property changes on: projects/altix/sys/boot/i386/efi
___________________________________________________________________
Added: svn:mergeinfo
## -0,0 +0,11 ##
Merged /projects/cambria/sys/boot/i386/efi:r186008-186350
Merged /user/peter/kinfo/sys/boot/i386/efi:r185413-185547
Merged /user/piso/ipfw/sys/boot/i386/efi:r190918,190921,190923,190926
Merged /projects/quota64/sys/boot/i386/efi:r184125-207707
Merged /projects/binutils-2.17/sys/boot/i386/efi:r213992-218817
Merged /user/dfr/xenhvm/6/sys/boot/i386/efi:r189304,189451
Merged /user/dfr/xenhvm/7/sys/boot/i386/efi:r188574-189614
Merged /head/sys/boot/i386/efi:r204938-218875
Merged /user/mav/ata/sys/boot/i386/efi:r189793-190578
Merged /user/piso/sys/boot/i386/efi:r186543,186723,186725-186726,186742,186770-186771,186774,186777-186779,187984-187985,190555,190572,190589,190592,190614,190625,190830
Merged /user/thompsa/usb/sys/boot/i386/efi:r187190
Index: projects/altix/sys/boot/ia64/efi/ldscript.ia64
===================================================================
--- projects/altix/sys/boot/ia64/efi/ldscript.ia64 (revision 218875)
+++ projects/altix/sys/boot/ia64/efi/ldscript.ia64 (revision 218876)
@@ -1,73 +1,73 @@
/* $FreeBSD$ */
-OUTPUT_FORMAT("elf64-ia64-little", "elf64-ia64-little", "elf64-ia64-little")
+OUTPUT_FORMAT("elf64-ia64-freebsd", "elf64-ia64-freebsd", "elf64-ia64-freebsd")
OUTPUT_ARCH(ia64)
ENTRY(_start_plabel)
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = 0;
ImageBase = .;
. = SIZEOF_HEADERS;
. = ALIGN(4096);
.text : {
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.plt)
} =0x00300000010070000002000001000400
. = ALIGN(4096);
+ __start_set_Xcommand_set = .;
+ set_Xcommand_set : { *(set_Xcommand_set) }
+ __stop_set_Xcommand_set = .;
.data : {
*(.rodata .rodata.* .gnu.linkonce.r.*)
*(.rodata1)
*(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
*(.sbss2 .sbss2.* .gnu.linkonce.sb2.*)
*(.opd)
- *(.IA_64.unwind_info* .gnu.linkonce.ia64unwi.*)
- *(.IA_64.unwind* .gnu.linkonce.ia64unw.*)
- __start_set_Xcommand_set = .;
- *(set_Xcommand_set)
- __stop_set_Xcommand_set = .;
*(.data .data.* .gnu.linkonce.d.*)
*(.data1)
*(.plabel)
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
}
+ .IA_64.unwind_info : { *(.IA_64.unwind_info* .gnu.linkonce.ia64unwi.*) }
+ .IA_64.unwind : { *(.IA_64.unwind* .gnu.linkonce.ia64unw.*) }
. = ALIGN(4096);
__gp = .;
.sdata : {
*(.got.plt .got)
*(.IA_64.pltoff)
*(.sdata .sdata.* .gnu.linkonce.s.*)
*(dynsbss)
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
}
. = ALIGN(4096);
.dynamic : { *(.dynamic) }
. = ALIGN(4096);
.rela.dyn : {
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
*(.rela.got)
*(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*)
*(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*)
*(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*)
*(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*)
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
*(.rela.plt)
*(.rela.IA_64.pltoff)
*(.relaset_*)
*(.rela.dyn .rela.dyn.*)
}
. = ALIGN(4096);
.reloc : { *(.reloc) }
. = ALIGN(4096);
.hash : { *(.hash) }
. = ALIGN(4096);
.dynsym : { *(.dynsym) }
. = ALIGN(4096);
.dynstr : { *(.dynstr) }
}
Index: projects/altix/sys/boot/ia64/efi
===================================================================
--- projects/altix/sys/boot/ia64/efi (revision 218875)
+++ projects/altix/sys/boot/ia64/efi (revision 218876)
Property changes on: projects/altix/sys/boot/ia64/efi
___________________________________________________________________
Added: svn:mergeinfo
## -0,0 +0,11 ##
Merged /projects/cambria/sys/boot/ia64/efi:r186008-186350
Merged /user/peter/kinfo/sys/boot/ia64/efi:r185413-185547
Merged /projects/quota64/sys/boot/ia64/efi:r184125-207707
Merged /head/sys/boot/ia64/efi:r204938-218875
Merged /user/dfr/xenhvm/6/sys/boot/ia64/efi:r189304,189451
Merged /user/dfr/xenhvm/7/sys/boot/ia64/efi:r188574-189614
Merged /user/mav/ata/sys/boot/ia64/efi:r189793-190578
Merged /user/piso/ipfw/sys/boot/ia64/efi:r190918,190921,190923,190926
Merged /user/thompsa/usb/sys/boot/ia64/efi:r187190
Merged /user/piso/sys/boot/ia64/efi:r186543,186723,186725-186726,186742,186770-186771,186774,186777-186779,187984-187985,190555,190572,190589,190592,190614,190625,190830
Merged /projects/binutils-2.17/sys/boot/ia64/efi:r213992-218818
Index: projects/altix/sys/boot/ia64/ski/ldscript.ia64
===================================================================
--- projects/altix/sys/boot/ia64/ski/ldscript.ia64 (revision 218875)
+++ projects/altix/sys/boot/ia64/ski/ldscript.ia64 (revision 218876)
@@ -1,61 +1,61 @@
/* $FreeBSD$ */
-OUTPUT_FORMAT("elf64-ia64-little", "elf64-ia64-little", "elf64-ia64-little")
+OUTPUT_FORMAT("elf64-ia64-freebsd", "elf64-ia64-freebsd", "elf64-ia64-freebsd")
OUTPUT_ARCH(ia64)
ENTRY(_start)
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = 0x100000;
.text : {
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.plt)
} =0x00300000010070000002000001000400
+ __start_set_Xcommand_set = .;
+ set_Xcommand_set : { *(set_Xcommand_set) }
+ __stop_set_Xcommand_set = .;
.data : {
*(.rodata .rodata.* .gnu.linkonce.r.*)
*(.rodata1)
*(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
*(.sbss2 .sbss2.* .gnu.linkonce.sb2.*)
*(.opd)
- *(.IA_64.unwind_info* .gnu.linkonce.ia64unwi.*)
- *(.IA_64.unwind* .gnu.linkonce.ia64unw.*)
- __start_set_Xcommand_set = .;
- *(set_Xcommand_set)
- __stop_set_Xcommand_set = .;
*(.data .data.* .gnu.linkonce.d.*)
*(.data1)
*(.plabel)
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
}
+ .IA_64.unwind_info : { *(.IA_64.unwind_info* .gnu.linkonce.ia64unwi.*) }
+ .IA_64.unwind : { *(.IA_64.unwind* .gnu.linkonce.ia64unw.*) }
__gp = .;
.sdata : {
*(.got.plt .got)
*(.IA_64.pltoff)
*(.sdata .sdata.* .gnu.linkonce.s.*)
*(dynsbss)
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
}
.dynamic : { *(.dynamic) }
.rela : {
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
*(.rela.got)
*(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*)
*(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*)
*(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*)
*(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*)
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
*(.rela.plt)
*(.rela.IA_64.pltoff)
*(.relaset_*)
*(.rela.dyn .rela.dyn.*)
}
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
}
Index: projects/altix/sys/boot/ia64/ski
===================================================================
--- projects/altix/sys/boot/ia64/ski (revision 218875)
+++ projects/altix/sys/boot/ia64/ski (revision 218876)
Property changes on: projects/altix/sys/boot/ia64/ski
___________________________________________________________________
Added: svn:mergeinfo
## -0,0 +0,11 ##
Merged /user/piso/ipfw/sys/boot/ia64/ski:r190918,190921,190923,190926
Merged /projects/cambria/sys/boot/ia64/ski:r186008-186350
Merged /projects/binutils-2.17/sys/boot/ia64/ski:r213992-218818
Merged /user/peter/kinfo/sys/boot/ia64/ski:r185413-185547
Merged /projects/quota64/sys/boot/ia64/ski:r184125-207707
Merged /head/sys/boot/ia64/ski:r204938-218875
Merged /user/dfr/xenhvm/6/sys/boot/ia64/ski:r189304,189451
Merged /user/dfr/xenhvm/7/sys/boot/ia64/ski:r188574-189614
Merged /user/mav/ata/sys/boot/ia64/ski:r189793-190578
Merged /user/piso/sys/boot/ia64/ski:r186543,186723,186725-186726,186742,186770-186771,186774,186777-186779,187984-187985,190555,190572,190589,190592,190614,190625,190830
Merged /user/thompsa/usb/sys/boot/ia64/ski:r187190
Index: projects/altix/sys/boot/pc98/boot2/boot2.c
===================================================================
--- projects/altix/sys/boot/pc98/boot2/boot2.c (revision 218875)
+++ projects/altix/sys/boot/pc98/boot2/boot2.c (revision 218876)
@@ -1,842 +1,825 @@
/*-
* Copyright (c) 2008-2009 TAKAHASHI Yoshihiro
* Copyright (c) 1998 Robert Nordier
* All rights reserved.
*
* Redistribution and use in source and binary forms are freely
* permitted provided that the above copyright notice and this
* paragraph and the following disclaimer are duplicated in all
* such forms.
*
* This software is provided "AS IS" and without any express or
* implied warranties, including, without limitation, the implied
* warranties of merchantability and fitness for a particular
* purpose.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/disklabel.h>
#include <sys/diskpc98.h>
#include <sys/dirent.h>
#include <sys/reboot.h>
#include <machine/bootinfo.h>
#include <machine/cpufunc.h>
#include <machine/elf.h>
#include <machine/psl.h>
#include <stdarg.h>
#include <a.out.h>
#include <btxv86.h>
#include "boot2.h"
#include "lib.h"
#define IO_KEYBOARD 1
#define IO_SERIAL 2
#define SECOND 1 /* Circa that many ticks in a second. */
#define RBX_ASKNAME 0x0 /* -a */
#define RBX_SINGLE 0x1 /* -s */
/* 0x2 is reserved for log2(RB_NOSYNC). */
/* 0x3 is reserved for log2(RB_HALT). */
/* 0x4 is reserved for log2(RB_INITNAME). */
#define RBX_DFLTROOT 0x5 /* -r */
#define RBX_KDB 0x6 /* -d */
/* 0x7 is reserved for log2(RB_RDONLY). */
/* 0x8 is reserved for log2(RB_DUMP). */
/* 0x9 is reserved for log2(RB_MINIROOT). */
#define RBX_CONFIG 0xa /* -c */
#define RBX_VERBOSE 0xb /* -v */
#define RBX_SERIAL 0xc /* -h */
#define RBX_CDROM 0xd /* -C */
/* 0xe is reserved for log2(RB_POWEROFF). */
#define RBX_GDB 0xf /* -g */
#define RBX_MUTE 0x10 /* -m */
/* 0x11 is reserved for log2(RB_SELFTEST). */
/* 0x12 is reserved for boot programs. */
/* 0x13 is reserved for boot programs. */
#define RBX_PAUSE 0x14 /* -p */
#define RBX_QUIET 0x15 /* -q */
#define RBX_NOINTR 0x1c /* -n */
/* 0x1d is reserved for log2(RB_MULTIPLE) and is just misnamed here. */
#define RBX_DUAL 0x1d /* -D */
/* 0x1f is reserved for log2(RB_BOOTINFO). */
/* pass: -a, -s, -r, -d, -c, -v, -h, -C, -g, -m, -p, -D */
#define RBX_MASK (OPT_SET(RBX_ASKNAME) | OPT_SET(RBX_SINGLE) | \
OPT_SET(RBX_DFLTROOT) | OPT_SET(RBX_KDB ) | \
OPT_SET(RBX_CONFIG) | OPT_SET(RBX_VERBOSE) | \
OPT_SET(RBX_SERIAL) | OPT_SET(RBX_CDROM) | \
OPT_SET(RBX_GDB ) | OPT_SET(RBX_MUTE) | \
OPT_SET(RBX_PAUSE) | OPT_SET(RBX_DUAL))
#define PATH_CONFIG "/boot.config"
#define PATH_BOOT3 "/boot/loader"
#define PATH_KERNEL "/boot/kernel/kernel"
#define ARGS 0x900
#define NOPT 14
#define NDEV 3
#define V86_CY(x) ((x) & PSL_C)
#define V86_ZR(x) ((x) & PSL_Z)
#define DRV_DISK 0xf0
#define DRV_UNIT 0x0f
#define TYPE_AD 0
#define TYPE_DA 1
#define TYPE_FD 2
#define OPT_SET(opt) (1 << (opt))
#define OPT_CHECK(opt) ((opts) & OPT_SET(opt))
extern uint32_t _end;
static const char optstr[NOPT] = "DhaCcdgmnpqrsv"; /* Also 'P', 'S' */
static const unsigned char flags[NOPT] = {
RBX_DUAL,
RBX_SERIAL,
RBX_ASKNAME,
RBX_CDROM,
RBX_CONFIG,
RBX_KDB,
RBX_GDB,
RBX_MUTE,
RBX_NOINTR,
RBX_PAUSE,
RBX_QUIET,
RBX_DFLTROOT,
RBX_SINGLE,
RBX_VERBOSE
};
static const char *const dev_nm[NDEV] = {"ad", "da", "fd"};
static const unsigned char dev_maj[NDEV] = {30, 4, 2};
static const unsigned char dev_daua[NDEV] = {0x80, 0xa0, 0x90};
static struct dsk {
unsigned daua;
unsigned type;
unsigned disk;
unsigned unit;
unsigned head;
unsigned sec;
unsigned slice;
unsigned part;
unsigned start;
} dsk;
static char cmd[512], cmddup[512];
static char kname[1024];
static uint16_t opts;
static int comspeed = SIOSPD;
static struct bootinfo bootinfo;
static uint8_t ioctrl = IO_KEYBOARD;
void exit(int);
static void load(void);
static int parse(void);
static int xfsread(ino_t, void *, size_t);
static int dskread(void *, unsigned, unsigned);
static void printf(const char *,...);
static void putchar(int);
static uint32_t memsize(void);
static int drvread(void *, unsigned);
static int keyhit(unsigned);
static int xputc(int);
static int xgetc(int);
static int getc(int);
static void memcpy(void *, const void *, int);
static void
memcpy(void *dst, const void *src, int len)
{
const char *s = src;
char *d = dst;
while (len--)
*d++ = *s++;
}
static inline int
strcmp(const char *s1, const char *s2)
{
for (; *s1 == *s2 && *s1; s1++, s2++);
return (unsigned char)*s1 - (unsigned char)*s2;
}
#define UFS_SMALL_CGBASE
#include "ufsread.c"
static inline int
xfsread(ino_t inode, void *buf, size_t nbyte)
{
if ((size_t)fsread(inode, buf, nbyte) != nbyte) {
printf("Invalid %s\n", "format");
return -1;
}
return 0;
}
static inline uint32_t
memsize(void)
{
return (*(u_char *)PTOV(0x401) * 128 * 1024 +
*(uint16_t *)PTOV(0x594) * 1024 * 1024);
}
static inline void
getstr(void)
{
char *s;
int c;
s = cmd;
for (;;) {
switch (c = xgetc(0)) {
case 0:
break;
case '\177':
case '\b':
if (s > cmd) {
s--;
printf("\b \b");
}
break;
case '\n':
case '\r':
*s = 0;
return;
default:
if (s - cmd < sizeof(cmd) - 1)
*s++ = c;
putchar(c);
}
}
}
static inline void
putc(int c)
{
v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS;
v86.addr = PUTCORG; /* call to putc in boot1 */
v86.eax = c;
v86int();
v86.ctl = V86_FLAGS;
}
static inline int
is_scsi_hd(void)
{
if ((*(u_char *)PTOV(0x482) >> dsk.unit) & 0x01)
return 1;
return 0;
}
static inline void
fix_sector_size(void)
{
u_char *p;
p = (u_char *)PTOV(0x460 + dsk.unit * 4); /* SCSI equipment parameter */
if ((p[0] & 0x1f) == 7) { /* SCSI MO */
if (!(p[3] & 0x30)) { /* 256B / sector */
p[3] |= 0x10; /* forced set 512B / sector */
p[3 + 0xa1000] |= 0x10;
}
}
}
static inline uint32_t
get_diskinfo(void)
{
if (dsk.disk == 0x30) { /* 1440KB FD */
/* 80 cylinders, 2 heads, 18 sectors */
return (80 << 16) | (2 << 8) | 18;
} else if (dsk.disk == 0x90) { /* 1200KB FD */
/* 80 cylinders, 2 heads, 15 sectors */
return (80 << 16) | (2 << 8) | 15;
} else if (dsk.disk == 0x80 || is_scsi_hd()) { /* IDE or SCSI HDD */
v86.addr = 0x1b;
v86.eax = 0x8400 | dsk.daua;
v86int();
return (v86.ecx << 16) | v86.edx;
}
/* SCSI MO or CD */
fix_sector_size(); /* SCSI MO */
/* other SCSI devices */
return (65535 << 16) | (8 << 8) | 32;
}
static void
set_dsk(void)
{
uint32_t di;
di = get_diskinfo();
dsk.head = (di >> 8) & 0xff;
dsk.sec = di & 0xff;
dsk.start = 0;
}
#ifdef GET_BIOSGEOM
static uint32_t
bd_getbigeom(int bunit)
{
int hds = 0;
int unit = 0x80; /* IDE HDD */
u_int addr = 0x55d;
while (unit < 0xa7) {
if (*(u_char *)PTOV(addr) & (1 << (unit & 0x0f)))
if (hds++ == bunit)
break;
if (unit >= 0xA0) {
int media = ((unsigned *)PTOV(0x460))[unit & 0x0F] & 0x1F;
if (media == 7 && hds++ == bunit) /* SCSI MO */
return(0xFFFE0820); /* C:65535 H:8 S:32 */
}
if (++unit == 0x84) {
unit = 0xA0; /* SCSI HDD */
addr = 0x482;
}
}
if (unit == 0xa7)
return 0x4F020F; /* 1200KB FD C:80 H:2 S:15 */
v86.addr = 0x1b;
v86.eax = 0x8400 | unit;
v86int();
if (v86.efl & 0x1)
return 0x4F020F; /* 1200KB FD C:80 H:2 S:15 */
return ((v86.ecx & 0xffff) << 16) | (v86.edx & 0xffff);
}
#endif
static int
check_slice(void)
{
struct pc98_partition *dp;
char *sec;
unsigned i, cyl;
sec = dmadat->secbuf;
cyl = *(uint16_t *)PTOV(ARGS);
set_dsk();
if (dsk.type == TYPE_FD)
return (WHOLE_DISK_SLICE);
if (drvread(sec, DOSBBSECTOR + 1))
return (WHOLE_DISK_SLICE); /* Read error */
dp = (void *)(sec + DOSPARTOFF);
for (i = 0; i < NDOSPART; i++) {
if (dp[i].dp_mid == DOSMID_386BSD) {
if (dp[i].dp_scyl <= cyl && cyl <= dp[i].dp_ecyl)
return (BASE_SLICE + i);
}
}
return (WHOLE_DISK_SLICE);
}
int
main(void)
{
#ifdef GET_BIOSGEOM
int i;
#endif
uint8_t autoboot;
ino_t ino;
dmadat = (void *)(roundup2(__base + (int32_t)&_end, 0x10000) - __base);
v86.ctl = V86_FLAGS;
v86.efl = PSL_RESERVED_DEFAULT | PSL_I;
dsk.daua = *(uint8_t *)PTOV(0x584);
dsk.disk = dsk.daua & DRV_DISK;
dsk.unit = dsk.daua & DRV_UNIT;
if (dsk.disk == 0x80)
dsk.type = TYPE_AD;
else if (dsk.disk == 0xa0)
dsk.type = TYPE_DA;
else /* if (dsk.disk == 0x30 || dsk.disk == 0x90) */
dsk.type = TYPE_FD;
dsk.slice = check_slice();
#ifdef GET_BIOSGEOM
for (i = 0; i < N_BIOS_GEOM; i++)
bootinfo.bi_bios_geom[i] = bd_getbigeom(i);
#endif
bootinfo.bi_version = BOOTINFO_VERSION;
bootinfo.bi_size = sizeof(bootinfo);
bootinfo.bi_basemem = 0; /* XXX will be filled by loader or kernel */
bootinfo.bi_extmem = memsize();
bootinfo.bi_memsizes_valid++;
/* Process configuration file */
autoboot = 1;
if ((ino = lookup(PATH_CONFIG)))
fsread(ino, cmd, sizeof(cmd));
if (*cmd) {
memcpy(cmddup, cmd, sizeof(cmd));
if (parse())
autoboot = 0;
if (!OPT_CHECK(RBX_QUIET))
printf("%s: %s", PATH_CONFIG, cmddup);
/* Do not process this command twice */
*cmd = 0;
}
/*
* Try to exec stage 3 boot loader. If interrupted by a keypress,
* or in case of failure, try to load a kernel directly instead.
*/
if (autoboot && !*kname) {
memcpy(kname, PATH_BOOT3, sizeof(PATH_BOOT3));
if (!keyhit(3*SECOND)) {
load();
memcpy(kname, PATH_KERNEL, sizeof(PATH_KERNEL));
}
}
/* Present the user with the boot2 prompt. */
for (;;) {
if (!autoboot || !OPT_CHECK(RBX_QUIET))
printf("\nFreeBSD/pc98 boot\n"
"Default: %u:%s(%u,%c)%s\n"
"boot: ",
dsk.unit, dev_nm[dsk.type], dsk.unit,
'a' + dsk.part, kname);
if (ioctrl & IO_SERIAL)
sio_flush();
if (!autoboot || keyhit(5*SECOND))
getstr();
else if (!autoboot || !OPT_CHECK(RBX_QUIET))
putchar('\n');
autoboot = 0;
if (parse())
putchar('\a');
else
load();
}
}
/* XXX - Needed for btxld to link the boot2 binary; do not remove. */
void
exit(int x)
{
}
static void
load(void)
{
union {
struct exec ex;
Elf32_Ehdr eh;
} hdr;
static Elf32_Phdr ep[2];
static Elf32_Shdr es[2];
caddr_t p;
ino_t ino;
uint32_t addr, x;
int i, j;
uint8_t fmt;
if (!(ino = lookup(kname))) {
if (!ls)
printf("No %s\n", kname);
return;
}
if (xfsread(ino, &hdr, sizeof(hdr)))
return;
if (N_GETMAGIC(hdr.ex) == ZMAGIC)
fmt = 0;
else if (IS_ELF(hdr.eh))
fmt = 1;
else {
printf("Invalid %s\n", "format");
return;
}
if (fmt == 0) {
addr = hdr.ex.a_entry & 0xffffff;
p = PTOV(addr);
fs_off = PAGE_SIZE;
if (xfsread(ino, p, hdr.ex.a_text))
return;
p += roundup2(hdr.ex.a_text, PAGE_SIZE);
if (xfsread(ino, p, hdr.ex.a_data))
return;
- p += hdr.ex.a_data + roundup2(hdr.ex.a_bss, PAGE_SIZE);
- bootinfo.bi_symtab = VTOP(p);
- *(uint32_t*)p = hdr.ex.a_syms;
- p += sizeof(hdr.ex.a_syms);
- if (hdr.ex.a_syms) {
- if (xfsread(ino, p, hdr.ex.a_syms))
- return;
- p += hdr.ex.a_syms;
- if (xfsread(ino, p, sizeof(int)))
- return;
- x = *(uint32_t *)p;
- p += sizeof(int);
- x -= sizeof(int);
- if (xfsread(ino, p, x))
- return;
- p += x;
- }
} else {
fs_off = hdr.eh.e_phoff;
for (j = i = 0; i < hdr.eh.e_phnum && j < 2; i++) {
if (xfsread(ino, ep + j, sizeof(ep[0])))
return;
if (ep[j].p_type == PT_LOAD)
j++;
}
for (i = 0; i < 2; i++) {
p = PTOV(ep[i].p_paddr & 0xffffff);
fs_off = ep[i].p_offset;
if (xfsread(ino, p, ep[i].p_filesz))
return;
}
p += roundup2(ep[1].p_memsz, PAGE_SIZE);
bootinfo.bi_symtab = VTOP(p);
if (hdr.eh.e_shnum == hdr.eh.e_shstrndx + 3) {
fs_off = hdr.eh.e_shoff + sizeof(es[0]) *
(hdr.eh.e_shstrndx + 1);
if (xfsread(ino, &es, sizeof(es)))
return;
for (i = 0; i < 2; i++) {
*(Elf32_Word *)p = es[i].sh_size;
p += sizeof(es[i].sh_size);
fs_off = es[i].sh_offset;
if (xfsread(ino, p, es[i].sh_size))
return;
p += es[i].sh_size;
}
}
addr = hdr.eh.e_entry & 0xffffff;
+ bootinfo.bi_esymtab = VTOP(p);
}
- bootinfo.bi_esymtab = VTOP(p);
bootinfo.bi_kernelname = VTOP(kname);
bootinfo.bi_bios_dev = dsk.daua;
__exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),
MAKEBOOTDEV(dev_maj[dsk.type], dsk.slice, dsk.unit, dsk.part),
0, 0, 0, VTOP(&bootinfo));
}
static int
parse()
{
char *arg = cmd;
char *ep, *p, *q;
const char *cp;
unsigned int drv;
int c, i, j;
while ((c = *arg++)) {
if (c == ' ' || c == '\t' || c == '\n')
continue;
for (p = arg; *p && *p != '\n' && *p != ' ' && *p != '\t'; p++);
ep = p;
if (*p)
*p++ = 0;
if (c == '-') {
while ((c = *arg++)) {
if (c == 'P') {
if (*(uint8_t *)PTOV(0x481) & 0x48) {
cp = "yes";
} else {
opts |= OPT_SET(RBX_DUAL) | OPT_SET(RBX_SERIAL);
cp = "no";
}
printf("Keyboard: %s\n", cp);
continue;
} else if (c == 'S') {
j = 0;
while ((unsigned int)(i = *arg++ - '0') <= 9)
j = j * 10 + i;
if (j > 0 && i == -'0') {
comspeed = j;
break;
}
/* Fall through to error below ('S' not in optstr[]). */
}
for (i = 0; c != optstr[i]; i++)
if (i == NOPT - 1)
return -1;
opts ^= OPT_SET(flags[i]);
}
ioctrl = OPT_CHECK(RBX_DUAL) ? (IO_SERIAL|IO_KEYBOARD) :
OPT_CHECK(RBX_SERIAL) ? IO_SERIAL : IO_KEYBOARD;
if (ioctrl & IO_SERIAL)
sio_init(115200 / comspeed);
} else {
for (q = arg--; *q && *q != '('; q++);
if (*q) {
drv = -1;
if (arg[1] == ':') {
drv = *arg - '0';
if (drv > 9)
return (-1);
arg += 2;
}
if (q - arg != 2)
return -1;
for (i = 0; arg[0] != dev_nm[i][0] ||
arg[1] != dev_nm[i][1]; i++)
if (i == NDEV - 1)
return -1;
dsk.type = i;
arg += 3;
dsk.unit = *arg - '0';
if (arg[1] != ',' || dsk.unit > 9)
return -1;
arg += 2;
dsk.slice = WHOLE_DISK_SLICE;
if (arg[1] == ',') {
dsk.slice = *arg - '0' + 1;
if (dsk.slice > NDOSPART + 1)
return -1;
arg += 2;
}
if (arg[1] != ')')
return -1;
dsk.part = *arg - 'a';
if (dsk.part > 7)
return (-1);
arg += 2;
if (drv == -1)
drv = dsk.unit;
dsk.disk = dev_daua[dsk.type];
dsk.daua = dsk.disk | dsk.unit;
dsk_meta = 0;
}
if ((i = ep - arg)) {
if ((size_t)i >= sizeof(kname))
return -1;
memcpy(kname, arg, i + 1);
}
}
arg = p;
}
return 0;
}
static int
dskread(void *buf, unsigned lba, unsigned nblk)
{
struct pc98_partition *dp;
struct disklabel *d;
char *sec;
unsigned sl, i;
u_char *p;
if (!dsk_meta) {
sec = dmadat->secbuf;
set_dsk();
if (dsk.type == TYPE_FD)
goto unsliced;
if (drvread(sec, DOSBBSECTOR + 1))
return -1;
dp = (void *)(sec + DOSPARTOFF);
sl = dsk.slice;
if (sl < BASE_SLICE) {
for (i = 0; i < NDOSPART; i++)
if (dp[i].dp_mid == DOSMID_386BSD) {
sl = BASE_SLICE + i;
break;
}
dsk.slice = sl;
}
if (sl != WHOLE_DISK_SLICE) {
dp += sl - BASE_SLICE;
if (dp->dp_mid != DOSMID_386BSD) {
printf("Invalid %s\n", "slice");
return -1;
}
dsk.start = dp->dp_scyl * dsk.head * dsk.sec +
dp->dp_shd * dsk.sec + dp->dp_ssect;
}
if (drvread(sec, dsk.start + LABELSECTOR))
return -1;
d = (void *)(sec + LABELOFFSET);
if (d->d_magic != DISKMAGIC || d->d_magic2 != DISKMAGIC) {
if (dsk.part != RAW_PART) {
printf("Invalid %s\n", "label");
return -1;
}
} else {
if (dsk.part >= d->d_npartitions ||
!d->d_partitions[dsk.part].p_size) {
printf("Invalid %s\n", "partition");
return -1;
}
dsk.start += d->d_partitions[dsk.part].p_offset;
dsk.start -= d->d_partitions[RAW_PART].p_offset;
}
unsliced: ;
}
for (p = buf; nblk; p += 512, lba++, nblk--) {
if ((i = drvread(p, dsk.start + lba)))
return i;
}
return 0;
}
static void
printf(const char *fmt,...)
{
va_list ap;
char buf[10];
char *s;
unsigned u;
int c;
va_start(ap, fmt);
while ((c = *fmt++)) {
if (c == '%') {
c = *fmt++;
switch (c) {
case 'c':
putchar(va_arg(ap, int));
continue;
case 's':
for (s = va_arg(ap, char *); *s; s++)
putchar(*s);
continue;
case 'u':
u = va_arg(ap, unsigned);
s = buf;
do
*s++ = '0' + u % 10U;
while (u /= 10U);
while (--s >= buf)
putchar(*s);
continue;
}
}
putchar(c);
}
va_end(ap);
return;
}
static void
putchar(int c)
{
if (c == '\n')
xputc('\r');
xputc(c);
}
static int
drvread(void *buf, unsigned lba)
{
static unsigned c = 0x2d5c7c2f;
unsigned bpc, x, cyl, head, sec;
bpc = dsk.sec * dsk.head;
cyl = lba / bpc;
x = lba % bpc;
head = x / dsk.sec;
sec = x % dsk.sec;
if (!OPT_CHECK(RBX_QUIET))
printf("%c\b", c = c << 8 | c >> 24);
v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS;
v86.addr = READORG; /* call to read in boot1 */
v86.ecx = cyl;
v86.edx = (head << 8) | sec;
v86.edi = lba;
v86.ebx = 512;
v86.es = VTOPSEG(buf);
v86.ebp = VTOPOFF(buf);
v86int();
v86.ctl = V86_FLAGS;
if (V86_CY(v86.efl)) {
printf("error %u c/h/s %u/%u/%u lba %u\n", v86.eax >> 8 & 0xff,
cyl, head, sec, lba);
return -1;
}
return 0;
}
static inline void
delay(void)
{
int i;
i = 800;
do {
outb(0x5f, 0); /* about 600ns */
} while (--i >= 0);
}
static int
keyhit(unsigned sec)
{
unsigned i;
if (OPT_CHECK(RBX_NOINTR))
return 0;
for (i = 0; i < sec * 1000; i++) {
if (xgetc(1))
return 1;
delay();
}
return 0;
}
static int
xputc(int c)
{
if (ioctrl & IO_KEYBOARD)
putc(c);
if (ioctrl & IO_SERIAL)
sio_putc(c);
return c;
}
static int
xgetc(int fn)
{
if (OPT_CHECK(RBX_NOINTR))
return 0;
for (;;) {
if (ioctrl & IO_KEYBOARD && getc(1))
return fn ? 1 : getc(0);
if (ioctrl & IO_SERIAL && sio_ischar())
return fn ? 1 : sio_getc();
if (fn)
return 0;
}
}
static int
getc(int fn)
{
v86.addr = 0x18;
v86.eax = fn << 8;
v86int();
if (fn)
return (v86.ebx >> 8) & 0x01;
else
return v86.eax & 0xff;
}
Index: projects/altix/sys/boot/powerpc/boot1.chrp/boot1.c
===================================================================
--- projects/altix/sys/boot/powerpc/boot1.chrp/boot1.c (revision 218875)
+++ projects/altix/sys/boot/powerpc/boot1.chrp/boot1.c (revision 218876)
@@ -1,768 +1,769 @@
/*-
* Copyright (c) 1998 Robert Nordier
* All rights reserved.
* Copyright (c) 2001 Robert Drehmel
* All rights reserved.
*
* Redistribution and use in source and binary forms are freely
* permitted provided that the above copyright notice and this
* paragraph and the following disclaimer are duplicated in all
* such forms.
*
* This software is provided "AS IS" and without any express or
* implied warranties, including, without limitation, the implied
* warranties of merchantability and fitness for a particular
* purpose.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/dirent.h>
#include <machine/elf.h>
#include <machine/stdarg.h>
#define _PATH_LOADER "/boot/loader"
#define _PATH_KERNEL "/boot/kernel/kernel"
#define BSIZEMAX 16384
typedef int putc_func_t(char c, void *arg);
typedef int32_t ofwh_t;
struct sp_data {
char *sp_buf;
u_int sp_len;
u_int sp_size;
};
static const char digits[] = "0123456789abcdef";
static char bootpath[128];
static char bootargs[128];
static ofwh_t bootdev;
static struct fs fs;
static ino_t inomap;
static char blkbuf[BSIZEMAX];
static unsigned int fsblks;
static uint32_t fs_off;
int main(int ac, char **av);
static void exit(int) __dead2;
static void load(const char *);
static int dskread(void *, u_int64_t, int);
static void usage(void);
static void bcopy(const void *src, void *dst, size_t len);
static void bzero(void *b, size_t len);
static int mount(const char *device, int quiet);
static void panic(const char *fmt, ...) __dead2;
static int printf(const char *fmt, ...);
static int putchar(char c, void *arg);
static int vprintf(const char *fmt, va_list ap);
static int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);
static int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap);
static int __putc(char c, void *arg);
static int __puts(const char *s, putc_func_t *putc, void *arg);
static int __sputc(char c, void *arg);
static char *__uitoa(char *buf, u_int val, int base);
static char *__ultoa(char *buf, u_long val, int base);
/*
* Open Firmware interface functions
*/
typedef u_int32_t ofwcell_t;
typedef u_int32_t u_ofwh_t;
typedef int (*ofwfp_t)(void *);
ofwfp_t ofw; /* the prom Open Firmware entry */
ofwh_t chosenh;
void ofw_init(void *, int, int (*)(void *), char *, int);
static ofwh_t ofw_finddevice(const char *);
static ofwh_t ofw_open(const char *);
static int ofw_close(ofwh_t);
static int ofw_getprop(ofwh_t, const char *, void *, size_t);
static int ofw_setprop(ofwh_t, const char *, void *, size_t);
static int ofw_read(ofwh_t, void *, size_t);
static int ofw_write(ofwh_t, const void *, size_t);
static int ofw_claim(void *virt, size_t len, u_int align);
static int ofw_seek(ofwh_t, u_int64_t);
static void ofw_exit(void) __dead2;
ofwh_t bootdevh;
ofwh_t stdinh, stdouth;
__asm(" \n\
.data \n\
+ .align 4 \n\
stack: \n\
.space 16384 \n\
\n\
.text \n\
.globl _start \n\
_start: \n\
lis %r1,stack@ha \n\
addi %r1,%r1,stack@l \n\
addi %r1,%r1,8192 \n\
\n\
b ofw_init \n\
");
void
ofw_init(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl)
{
char *av[16];
char *p;
int ac;
ofw = openfirm;
chosenh = ofw_finddevice("/chosen");
ofw_getprop(chosenh, "stdin", &stdinh, sizeof(stdinh));
ofw_getprop(chosenh, "stdout", &stdouth, sizeof(stdouth));
ofw_getprop(chosenh, "bootargs", bootargs, sizeof(bootargs));
ofw_getprop(chosenh, "bootpath", bootpath, sizeof(bootpath));
bootargs[sizeof(bootargs) - 1] = '\0';
bootpath[sizeof(bootpath) - 1] = '\0';
p = bootpath;
while (*p != '\0') {
if (*p == ':') {
*(++p) = '\0';
break;
}
p++;
}
ac = 0;
p = bootargs;
for (;;) {
while (*p == ' ' && *p != '\0')
p++;
if (*p == '\0' || ac >= 16)
break;
av[ac++] = p;
while (*p != ' ' && *p != '\0')
p++;
if (*p != '\0')
*p++ = '\0';
}
exit(main(ac, av));
}
static ofwh_t
ofw_finddevice(const char *name)
{
ofwcell_t args[] = {
(ofwcell_t)"finddevice",
1,
1,
(ofwcell_t)name,
0
};
if ((*ofw)(args)) {
printf("ofw_finddevice: name=\"%s\"\n", name);
return (1);
}
return (args[4]);
}
static int
ofw_getprop(ofwh_t ofwh, const char *name, void *buf, size_t len)
{
ofwcell_t args[] = {
(ofwcell_t)"getprop",
4,
1,
(u_ofwh_t)ofwh,
(ofwcell_t)name,
(ofwcell_t)buf,
len,
0
};
if ((*ofw)(args)) {
printf("ofw_getprop: ofwh=0x%x buf=%p len=%u\n",
ofwh, buf, len);
return (1);
}
return (0);
}
static int
ofw_setprop(ofwh_t ofwh, const char *name, void *buf, size_t len)
{
ofwcell_t args[] = {
(ofwcell_t)"setprop",
4,
1,
(u_ofwh_t)ofwh,
(ofwcell_t)name,
(ofwcell_t)buf,
len,
0
};
if ((*ofw)(args)) {
printf("ofw_setprop: ofwh=0x%x buf=%p len=%u\n",
ofwh, buf, len);
return (1);
}
return (0);
}
static ofwh_t
ofw_open(const char *path)
{
ofwcell_t args[] = {
(ofwcell_t)"open",
1,
1,
(ofwcell_t)path,
0
};
if ((*ofw)(args)) {
printf("ofw_open: path=\"%s\"\n", path);
return (-1);
}
return (args[4]);
}
static int
ofw_close(ofwh_t devh)
{
ofwcell_t args[] = {
(ofwcell_t)"close",
1,
0,
(u_ofwh_t)devh
};
if ((*ofw)(args)) {
printf("ofw_close: devh=0x%x\n", devh);
return (1);
}
return (0);
}
static int
ofw_claim(void *virt, size_t len, u_int align)
{
ofwcell_t args[] = {
(ofwcell_t)"claim",
3,
1,
(ofwcell_t)virt,
len,
align,
0,
0
};
if ((*ofw)(args)) {
printf("ofw_claim: virt=%p len=%u\n", virt, len);
return (1);
}
return (0);
}
static int
ofw_read(ofwh_t devh, void *buf, size_t len)
{
ofwcell_t args[] = {
(ofwcell_t)"read",
3,
1,
(u_ofwh_t)devh,
(ofwcell_t)buf,
len,
0
};
if ((*ofw)(args)) {
printf("ofw_read: devh=0x%x buf=%p len=%u\n", devh, buf, len);
return (1);
}
return (0);
}
static int
ofw_write(ofwh_t devh, const void *buf, size_t len)
{
ofwcell_t args[] = {
(ofwcell_t)"write",
3,
1,
(u_ofwh_t)devh,
(ofwcell_t)buf,
len,
0
};
if ((*ofw)(args)) {
printf("ofw_write: devh=0x%x buf=%p len=%u\n", devh, buf, len);
return (1);
}
return (0);
}
static int
ofw_seek(ofwh_t devh, u_int64_t off)
{
ofwcell_t args[] = {
(ofwcell_t)"seek",
3,
1,
(u_ofwh_t)devh,
off >> 32,
off,
0
};
if ((*ofw)(args)) {
printf("ofw_seek: devh=0x%x off=0x%lx\n", devh, off);
return (1);
}
return (0);
}
static void
ofw_exit(void)
{
ofwcell_t args[3];
args[0] = (ofwcell_t)"exit";
args[1] = 0;
args[2] = 0;
for (;;)
(*ofw)(args);
}
static void
bcopy(const void *src, void *dst, size_t len)
{
const char *s = src;
char *d = dst;
while (len-- != 0)
*d++ = *s++;
}
static void
memcpy(void *dst, const void *src, size_t len)
{
bcopy(src, dst, len);
}
static void
bzero(void *b, size_t len)
{
char *p = b;
while (len-- != 0)
*p++ = 0;
}
static int
strcmp(const char *s1, const char *s2)
{
for (; *s1 == *s2 && *s1; s1++, s2++)
;
return ((u_char)*s1 - (u_char)*s2);
}
#include "ufsread.c"
int
main(int ac, char **av)
{
const char *path;
char bootpath_full[255];
int i, len;
path = _PATH_LOADER;
for (i = 0; i < ac; i++) {
switch (av[i][0]) {
case '-':
switch (av[i][1]) {
default:
usage();
}
break;
default:
path = av[i];
break;
}
}
printf(" \n>> FreeBSD/powerpc Open Firmware boot block\n"
" Boot path: %s\n"
" Boot loader: %s\n", bootpath, path);
len = 0;
while (bootpath[len] != '\0') len++;
memcpy(bootpath_full,bootpath,len+1);
if (bootpath_full[len-1] == ':') {
for (i = 0; i < 16; i++) {
if (i < 10) {
bootpath_full[len] = i + '0';
bootpath_full[len+1] = '\0';
} else {
bootpath_full[len] = '1';
bootpath_full[len+1] = i - 10 + '0';
bootpath_full[len+2] = '\0';
}
if (mount(bootpath_full,1) >= 0)
break;
if (bootdev > 0)
ofw_close(bootdev);
}
if (i >= 16)
panic("mount");
} else {
if (mount(bootpath_full,0) == -1)
panic("mount");
}
printf(" Boot volume: %s\n",bootpath_full);
ofw_setprop(chosenh, "bootargs", bootpath_full, len+2);
load(path);
return (1);
}
static void
usage(void)
{
printf("usage: boot device [/path/to/loader]\n");
exit(1);
}
static void
exit(int code)
{
ofw_exit();
}
static struct dmadat __dmadat;
static int
mount(const char *device, int quiet)
{
dmadat = &__dmadat;
if ((bootdev = ofw_open(device)) == -1) {
printf("mount: can't open device\n");
return (-1);
}
if (fsread(0, NULL, 0)) {
if (!quiet)
printf("mount: can't read superblock\n");
return (-1);
}
return (0);
}
static void
load(const char *fname)
{
Elf32_Ehdr eh;
Elf32_Phdr ph;
caddr_t p;
ino_t ino;
int i;
if ((ino = lookup(fname)) == 0) {
printf("File %s not found\n", fname);
return;
}
if (fsread(ino, &eh, sizeof(eh)) != sizeof(eh)) {
printf("Can't read elf header\n");
return;
}
if (!IS_ELF(eh)) {
printf("Not an ELF file\n");
return;
}
for (i = 0; i < eh.e_phnum; i++) {
fs_off = eh.e_phoff + i * eh.e_phentsize;
if (fsread(ino, &ph, sizeof(ph)) != sizeof(ph)) {
printf("Can't read program header %d\n", i);
return;
}
if (ph.p_type != PT_LOAD)
continue;
fs_off = ph.p_offset;
p = (caddr_t)ph.p_vaddr;
ofw_claim(p,(ph.p_filesz > ph.p_memsz) ?
ph.p_filesz : ph.p_memsz,0);
if (fsread(ino, p, ph.p_filesz) != ph.p_filesz) {
printf("Can't read content of section %d\n", i);
return;
}
if (ph.p_filesz != ph.p_memsz)
bzero(p + ph.p_filesz, ph.p_memsz - ph.p_filesz);
}
ofw_close(bootdev);
(*(void (*)(void *, int, ofwfp_t, char *, int))eh.e_entry)(NULL, 0,
ofw,NULL,0);
}
static int
dskread(void *buf, u_int64_t lba, int nblk)
{
/*
* The Open Firmware should open the correct partition for us.
* That means, if we read from offset zero on an open instance handle,
* we should read from offset zero of that partition.
*/
ofw_seek(bootdev, lba * DEV_BSIZE);
ofw_read(bootdev, buf, nblk * DEV_BSIZE);
return (0);
}
static void
panic(const char *fmt, ...)
{
char buf[128];
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, sizeof buf, fmt, ap);
printf("panic: %s\n", buf);
va_end(ap);
exit(1);
}
static int
printf(const char *fmt, ...)
{
va_list ap;
int ret;
/* Don't annoy the user as we probe for partitions */
if (strcmp(fmt,"Not ufs\n") == 0)
return 0;
va_start(ap, fmt);
ret = vprintf(fmt, ap);
va_end(ap);
return (ret);
}
static int
putchar(char c, void *arg)
{
char buf;
if (c == '\n') {
buf = '\r';
ofw_write(stdouth, &buf, 1);
}
buf = c;
ofw_write(stdouth, &buf, 1);
return (1);
}
static int
vprintf(const char *fmt, va_list ap)
{
int ret;
ret = __printf(fmt, putchar, 0, ap);
return (ret);
}
static int
vsnprintf(char *str, size_t sz, const char *fmt, va_list ap)
{
struct sp_data sp;
int ret;
sp.sp_buf = str;
sp.sp_len = 0;
sp.sp_size = sz;
ret = __printf(fmt, __sputc, &sp, ap);
return (ret);
}
static int
__printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap)
{
char buf[(sizeof(long) * 8) + 1];
char *nbuf;
u_long ul;
u_int ui;
int lflag;
int sflag;
char *s;
int pad;
int ret;
int c;
nbuf = &buf[sizeof buf - 1];
ret = 0;
while ((c = *fmt++) != 0) {
if (c != '%') {
ret += putc(c, arg);
continue;
}
lflag = 0;
sflag = 0;
pad = 0;
reswitch: c = *fmt++;
switch (c) {
case '#':
sflag = 1;
goto reswitch;
case '%':
ret += putc('%', arg);
break;
case 'c':
c = va_arg(ap, int);
ret += putc(c, arg);
break;
case 'd':
if (lflag == 0) {
ui = (u_int)va_arg(ap, int);
if (ui < (int)ui) {
ui = -ui;
ret += putc('-', arg);
}
s = __uitoa(nbuf, ui, 10);
} else {
ul = (u_long)va_arg(ap, long);
if (ul < (long)ul) {
ul = -ul;
ret += putc('-', arg);
}
s = __ultoa(nbuf, ul, 10);
}
ret += __puts(s, putc, arg);
break;
case 'l':
lflag = 1;
goto reswitch;
case 'o':
if (lflag == 0) {
ui = (u_int)va_arg(ap, u_int);
s = __uitoa(nbuf, ui, 8);
} else {
ul = (u_long)va_arg(ap, u_long);
s = __ultoa(nbuf, ul, 8);
}
ret += __puts(s, putc, arg);
break;
case 'p':
ul = (u_long)va_arg(ap, void *);
s = __ultoa(nbuf, ul, 16);
ret += __puts("0x", putc, arg);
ret += __puts(s, putc, arg);
break;
case 's':
s = va_arg(ap, char *);
ret += __puts(s, putc, arg);
break;
case 'u':
if (lflag == 0) {
ui = va_arg(ap, u_int);
s = __uitoa(nbuf, ui, 10);
} else {
ul = va_arg(ap, u_long);
s = __ultoa(nbuf, ul, 10);
}
ret += __puts(s, putc, arg);
break;
case 'x':
if (lflag == 0) {
ui = va_arg(ap, u_int);
s = __uitoa(nbuf, ui, 16);
} else {
ul = va_arg(ap, u_long);
s = __ultoa(nbuf, ul, 16);
}
if (sflag)
ret += __puts("0x", putc, arg);
ret += __puts(s, putc, arg);
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
pad = pad * 10 + c - '0';
goto reswitch;
default:
break;
}
}
return (ret);
}
static int
__sputc(char c, void *arg)
{
struct sp_data *sp;
sp = arg;
if (sp->sp_len < sp->sp_size)
sp->sp_buf[sp->sp_len++] = c;
sp->sp_buf[sp->sp_len] = '\0';
return (1);
}
static int
__puts(const char *s, putc_func_t *putc, void *arg)
{
const char *p;
int ret;
ret = 0;
for (p = s; *p != '\0'; p++)
ret += putc(*p, arg);
return (ret);
}
static char *
__uitoa(char *buf, u_int ui, int base)
{
char *p;
p = buf;
*p = '\0';
do
*--p = digits[ui % base];
while ((ui /= base) != 0);
return (p);
}
static char *
__ultoa(char *buf, u_long ul, int base)
{
char *p;
p = buf;
*p = '\0';
do
*--p = digits[ul % base];
while ((ul /= base) != 0);
return (p);
}
Index: projects/altix/sys/boot/powerpc/boot1.chrp
===================================================================
--- projects/altix/sys/boot/powerpc/boot1.chrp (revision 218875)
+++ projects/altix/sys/boot/powerpc/boot1.chrp (revision 218876)
Property changes on: projects/altix/sys/boot/powerpc/boot1.chrp
___________________________________________________________________
Added: svn:mergeinfo
## -0,0 +0,11 ##
Merged /user/piso/sys/boot/powerpc/boot1.chrp:r186543,186723,186725-186726,186742,186770-186771,186774,186777-186779,187984-187985,190555,190572,190589,190592,190614,190625,190830
Merged /projects/cambria/sys/boot/powerpc/boot1.chrp:r186008-186350
Merged /user/peter/kinfo/sys/boot/powerpc/boot1.chrp:r185413-185547
Merged /projects/quota64/sys/boot/powerpc/boot1.chrp:r184125-207707
Merged /user/piso/ipfw/sys/boot/powerpc/boot1.chrp:r190918,190921,190923,190926
Merged /head/sys/boot/powerpc/boot1.chrp:r204938-218875
Merged /projects/binutils-2.17/sys/boot/powerpc/boot1.chrp:r213992-218818
Merged /user/dfr/xenhvm/6/sys/boot/powerpc/boot1.chrp:r189304,189451
Merged /user/dfr/xenhvm/7/sys/boot/powerpc/boot1.chrp:r188574-189614
Merged /user/mav/ata/sys/boot/powerpc/boot1.chrp:r189793-190578
Merged /user/thompsa/usb/sys/boot/powerpc/boot1.chrp:r187190
Index: projects/altix/sys/boot/powerpc/ofw/start.c
===================================================================
--- projects/altix/sys/boot/powerpc/ofw/start.c (revision 218875)
+++ projects/altix/sys/boot/powerpc/ofw/start.c (revision 218876)
@@ -1,73 +1,74 @@
/* $NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $ */
/*-
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
* Copyright (C) 1995, 1996 TooLs GmbH.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <stand.h>
#include "libofw.h"
void startup(void *, int, int (*)(void *), char *, int);
__asm(" \n\
.data \n\
+ .align 4 \n\
stack: \n\
.space 16388 \n\
\n\
.text \n\
.globl _start \n\
_start: \n\
lis %r1,stack@ha \n\
addi %r1,%r1,stack@l \n\
addi %r1,%r1,8192 \n\
\n\
/* Clear the .bss!!! */ \n\
li %r0,0 \n\
lis %r8,_edata@ha \n\
addi %r8,%r8,_edata@l\n\
lis %r9,_end@ha \n\
addi %r9,%r9,_end@l \n\
\n\
1: cmpw 0,%r8,%r9 \n\
bge 2f \n\
stw %r0,0(%r8) \n\
addi %r8,%r8,4 \n\
b 1b \n\
\n\
2: b startup \n\
");
void
startup(void *vpd, int res, int (*openfirm)(void *), char *arg, int argl)
{
main(openfirm);
}
Index: projects/altix/sys/boot/powerpc/ofw
===================================================================
--- projects/altix/sys/boot/powerpc/ofw (revision 218875)
+++ projects/altix/sys/boot/powerpc/ofw (revision 218876)
Property changes on: projects/altix/sys/boot/powerpc/ofw
___________________________________________________________________
Added: svn:mergeinfo
## -0,0 +0,11 ##
Merged /user/thompsa/usb/sys/boot/powerpc/ofw:r187190
Merged /user/piso/ipfw/sys/boot/powerpc/ofw:r190918,190921,190923,190926
Merged /projects/binutils-2.17/sys/boot/powerpc/ofw:r213992-218818
Merged /projects/cambria/sys/boot/powerpc/ofw:r186008-186350
Merged /user/peter/kinfo/sys/boot/powerpc/ofw:r185413-185547
Merged /projects/quota64/sys/boot/powerpc/ofw:r184125-207707
Merged /user/dfr/xenhvm/6/sys/boot/powerpc/ofw:r189304,189451
Merged /user/dfr/xenhvm/7/sys/boot/powerpc/ofw:r188574-189614
Merged /head/sys/boot/powerpc/ofw:r204938-218875
Merged /user/mav/ata/sys/boot/powerpc/ofw:r189793-190578
Merged /user/piso/sys/boot/powerpc/ofw:r186543,186723,186725-186726,186742,186770-186771,186774,186777-186779,187984-187985,190555,190572,190589,190592,190614,190625,190830
Index: projects/altix/sys/cddl/contrib/opensolaris
===================================================================
--- projects/altix/sys/cddl/contrib/opensolaris (revision 218875)
+++ projects/altix/sys/cddl/contrib/opensolaris (revision 218876)
Property changes on: projects/altix/sys/cddl/contrib/opensolaris
___________________________________________________________________
Modified: svn:mergeinfo
## -0,0 +0,1 ##
Merged /head/sys/cddl/contrib/opensolaris:r218817-218875
Index: projects/altix/sys/conf/kern.mk
===================================================================
--- projects/altix/sys/conf/kern.mk (revision 218875)
+++ projects/altix/sys/conf/kern.mk (revision 218876)
@@ -1,121 +1,128 @@
# $FreeBSD$
#
# Warning flags for compiling the kernel and components of the kernel.
#
# Note that the newly added -Wcast-qual is responsible for generating
# most of the remaining warnings. Warnings introduced with -Wall will
# also pop up, but are easier to fix.
.if ${CC:T:Micc} == "icc"
#CWARNFLAGS= -w2 # use this if you are terribly bored
CWARNFLAGS=
.else
CWARNFLAGS?= -Wall -Wredundant-decls -Wnested-externs -Wstrict-prototypes \
-Wmissing-prototypes -Wpointer-arith -Winline -Wcast-qual \
-Wundef -Wno-pointer-sign -fformat-extensions
.endif
#
# The following flags are next up for working on:
# -W
#
# On the i386, do not align the stack to 16-byte boundaries. Otherwise GCC
# 2.95 adds code to the entry and exit point of every function to align the
# stack to 16-byte boundaries -- thus wasting approximately 12 bytes of stack
# per function call. While the 16-byte alignment may benefit micro benchmarks,
# it is probably an overall loss as it makes the code bigger (less efficient
# use of code cache tag lines) and uses more stack (less efficient use of data
# cache tag lines). Explicitly prohibit the use of SSE and other SIMD
# operations inside the kernel itself. These operations are exclusively
# reserved for user applications.
#
.if ${MACHINE_CPUARCH} == "i386" && ${CC:T:Micc} != "icc"
.if ${CC:T:Mclang} != "clang"
CFLAGS+= -mno-align-long-strings -mpreferred-stack-boundary=2
.endif
CFLAGS+= -mno-mmx -mno-3dnow -mno-sse -mno-sse2 -mno-sse3 -msoft-float
INLINE_LIMIT?= 8000
.endif
.if ${MACHINE_CPUARCH} == "arm"
INLINE_LIMIT?= 8000
.endif
#
# For IA-64, we use r13 for the kernel globals pointer and we only use
# a very small subset of float registers for integer divides.
#
.if ${MACHINE_CPUARCH} == "ia64"
CFLAGS+= -ffixed-r13 -mfixed-range=f32-f127 -fpic #-mno-sdata
INLINE_LIMIT?= 15000
.endif
#
# For sparc64 we want medlow code model, and we tell gcc to use floating
# point emulation. This avoids using floating point registers for integer
# operations which it has a tendency to do.
#
.if ${MACHINE_CPUARCH} == "sparc64"
CFLAGS+= -mcmodel=medany -msoft-float
INLINE_LIMIT?= 15000
.endif
#
# For AMD64, we explicitly prohibit the use of FPU, SSE and other SIMD
# operations inside the kernel itself. These operations are exclusively
# reserved for user applications.
#
.if ${MACHINE_CPUARCH} == "amd64"
CFLAGS+= -mcmodel=kernel -mno-red-zone \
-mfpmath=387 -mno-mmx -mno-3dnow -mno-sse -mno-sse2 -mno-sse3 \
-msoft-float -fno-asynchronous-unwind-tables
INLINE_LIMIT?= 8000
.endif
#
# For PowerPC we tell gcc to use floating point emulation. This avoids using
# floating point registers for integer operations which it has a tendency to do.
# Also explicitly disable Altivec instructions inside the kernel.
#
.if ${MACHINE_CPUARCH} == "powerpc"
CFLAGS+= -msoft-float -mno-altivec
INLINE_LIMIT?= 15000
.endif
#
+# Use dot symbols on powerpc64 to make ddb happy
+#
+.if ${MACHINE_ARCH} == "powerpc64"
+CFLAGS+= -mcall-aixdesc
+.endif
+
+#
# For MIPS we also tell gcc to use floating point emulation
#
.if ${MACHINE_CPUARCH} == "mips"
CFLAGS+= -msoft-float
INLINE_LIMIT?= 8000
.endif
#
# GCC 3.0 and above like to do certain optimizations based on the
# assumption that the program is linked against libc. Stop this.
#
.if ${CC:T:Micc} == "icc"
CFLAGS+= -nolib_inline
.else
CFLAGS+= -ffreestanding
.endif
.if ${CC:T:Micc} == "icc"
CFLAGS+= -restrict
.endif
#
# GCC SSP support.
#
.if ${MK_SSP} != "no" && ${CC:T:Micc} != "icc" && \
${MACHINE_CPUARCH} != "ia64" && ${MACHINE_CPUARCH} != "arm" && \
${MACHINE_CPUARCH} != "mips"
CFLAGS+= -fstack-protector
.endif
#
# Enable CTF conversation on request.
#
.if defined(WITH_CTF)
.undef NO_CTF
.endif
Index: projects/altix/sys/conf/ldscript.amd64
===================================================================
--- projects/altix/sys/conf/ldscript.amd64 (revision 218875)
+++ projects/altix/sys/conf/ldscript.amd64 (revision 218876)
@@ -1,173 +1,220 @@
/* $FreeBSD$ */
-OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
+OUTPUT_FORMAT("elf64-x86-64-freebsd", "elf64-x86-64-freebsd", "elf64-x86-64-freebsd")
OUTPUT_ARCH(i386:x86-64)
ENTRY(btext)
SEARCH_DIR("/usr/lib");
SECTIONS
{
/* Read-only sections, merged into text segment: */
- . = kernbase + 0x00100000 + SIZEOF_HEADERS;
+ . = kernbase + CONSTANT (MAXPAGESIZE) + SIZEOF_HEADERS;
.interp : { *(.interp) }
.hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
.rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
.rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
+ .rel.data.rel.ro : { *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) }
+ .rela.data.rel.ro : { *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) }
.rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
.rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
.rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
.rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
.rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
.rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
.rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
+ .rel.ldata : { *(.rel.ldata .rel.ldata.* .rel.gnu.linkonce.l.*) }
+ .rela.ldata : { *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*) }
+ .rel.lbss : { *(.rel.lbss .rel.lbss.* .rel.gnu.linkonce.lb.*) }
+ .rela.lbss : { *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*) }
+ .rel.lrodata : { *(.rel.lrodata .rel.lrodata.* .rel.gnu.linkonce.lr.*) }
+ .rela.lrodata : { *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.init :
{
KEEP (*(.init))
} =0x90909090
.plt : { *(.plt) }
.text :
{
*(.text .stub .text.* .gnu.linkonce.t.*)
+ KEEP (*(.text.*personality*))
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
} =0x90909090
.fini :
{
KEEP (*(.fini))
} =0x90909090
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.eh_frame_hdr : { *(.eh_frame_hdr) }
+ .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+ .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
- . = DATA_SEGMENT_ALIGN(0x100000, 0x1000);
- /* Ensure the __preinit_array_start label is properly aligned. We
- could instead move the label definition inside the section, but
- the linker would then create the section even if it turns out to
- be empty, which isn't pretty. */
- . = ALIGN(64 / 8);
- PROVIDE (__preinit_array_start = .);
- .preinit_array : { *(.preinit_array) }
- PROVIDE (__preinit_array_end = .);
- PROVIDE (__init_array_start = .);
- .init_array : { *(.init_array) }
- PROVIDE (__init_array_end = .);
- PROVIDE (__fini_array_start = .);
- .fini_array : { *(.fini_array) }
- PROVIDE (__fini_array_end = .);
- .data :
- {
- *(.data .data.* .gnu.linkonce.d.*)
- SORT(CONSTRUCTORS)
- }
- .data1 : { *(.data1) }
+ . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+ /* Exception handling */
+ .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+ .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+ /* Thread Local Storage sections */
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
- .eh_frame : { KEEP (*(.eh_frame)) }
- .gcc_except_table : { *(.gcc_except_table) }
- .dynamic : { *(.dynamic) }
+ .preinit_array :
+ {
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ }
+ .init_array :
+ {
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ }
+ .fini_array :
+ {
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(.fini_array))
+ KEEP (*(SORT(.fini_array.*)))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ }
_start_ctors = .;
PROVIDE (start_ctors = .);
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
+ KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
- from the crtend.o file until after the sorted ctors.
+ the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
- KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
_stop_ctors = .;
PROVIDE (stop_ctors = .);
.dtors :
{
KEEP (*crtbegin.o(.dtors))
- KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
+ KEEP (*crtbegin?.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.jcr : { KEEP (*(.jcr)) }
- .got : { *(.got.plt) *(.got) }
- _edata = .;
- PROVIDE (edata = .);
+ .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
+ .dynamic : { *(.dynamic) }
+ .got : { *(.got) }
+ . = DATA_SEGMENT_RELRO_END (24, .);
+ .got.plt : { *(.got.plt) }
+ .data :
+ {
+ *(.data .data.* .gnu.linkonce.d.*)
+ KEEP (*(.gnu.linkonce.d.*personality*))
+ SORT(CONSTRUCTORS)
+ }
+ .data1 : { *(.data1) }
+ _edata = .; PROVIDE (edata = .);
__bss_start = .;
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
- .bss section disappears because there are no input sections. */
- . = ALIGN(64 / 8);
+ .bss section disappears because there are no input sections.
+ FIXME: Why do we need it? When there is no .bss section, we don't
+ pad the .data section. */
+ . = ALIGN(. != 0 ? 64 / 8 : 1);
}
+ .lbss :
+ {
+ *(.dynlbss)
+ *(.lbss .lbss.* .gnu.linkonce.lb.*)
+ *(LARGE_COMMON)
+ }
. = ALIGN(64 / 8);
- _end = .;
- PROVIDE (end = .);
+ .lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+ {
+ *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
+ }
+ .ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+ {
+ *(.ldata .ldata.* .gnu.linkonce.l.*)
+ . = ALIGN(. != 0 ? 64 / 8 : 1);
+ }
+ . = ALIGN(64 / 8);
+ _end = .; PROVIDE (end = .);
. = DATA_SEGMENT_END (.);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
+ /* DWARF 3 */
+ .debug_pubtypes 0 : { *(.debug_pubtypes) }
+ .debug_ranges 0 : { *(.debug_ranges) }
+ .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+ /DISCARD/ : { *(.note.GNU-stack) }
}
Index: projects/altix/sys/conf/ldscript.i386
===================================================================
--- projects/altix/sys/conf/ldscript.i386 (revision 218875)
+++ projects/altix/sys/conf/ldscript.i386 (revision 218876)
@@ -1,134 +1,199 @@
/* $FreeBSD$ */
OUTPUT_FORMAT("elf32-i386-freebsd", "elf32-i386-freebsd", "elf32-i386-freebsd")
OUTPUT_ARCH(i386)
ENTRY(btext)
SEARCH_DIR(/usr/lib);
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = kernbase + kernload + SIZEOF_HEADERS;
- .interp : { *(.interp) }
- .hash : { *(.hash) }
- .dynsym : { *(.dynsym) }
- .dynstr : { *(.dynstr) }
- .gnu.version : { *(.gnu.version) }
- .gnu.version_d : { *(.gnu.version_d) }
- .gnu.version_r : { *(.gnu.version_r) }
- .rel.text :
- { *(.rel.text) *(.rel.gnu.linkonce.t*) }
- .rela.text :
- { *(.rela.text) *(.rela.gnu.linkonce.t*) }
- .rel.data :
- { *(.rel.data) *(.rel.gnu.linkonce.d*) }
- .rela.data :
- { *(.rela.data) *(.rela.gnu.linkonce.d*) }
- .rel.rodata :
- { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
- .rela.rodata :
- { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
- .rel.got : { *(.rel.got) }
- .rela.got : { *(.rela.got) }
- .rel.ctors : { *(.rel.ctors) }
- .rela.ctors : { *(.rela.ctors) }
- .rel.dtors : { *(.rel.dtors) }
- .rela.dtors : { *(.rela.dtors) }
- .rel.init : { *(.rel.init) }
- .rela.init : { *(.rela.init) }
- .rel.fini : { *(.rel.fini) }
- .rela.fini : { *(.rela.fini) }
- .rel.bss : { *(.rel.bss) }
- .rela.bss : { *(.rela.bss) }
- .rel.plt : { *(.rel.plt) }
- .rela.plt : { *(.rela.plt) }
- .init : { *(.init) } =0x9090
- .plt : { *(.plt) }
- .text :
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rel.init : { *(.rel.init) }
+ .rela.init : { *(.rela.init) }
+ .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
+ .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
+ .rel.fini : { *(.rel.fini) }
+ .rela.fini : { *(.rela.fini) }
+ .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
+ .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
+ .rel.data.rel.ro : { *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) }
+ .rela.data.rel.ro : { *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) }
+ .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
+ .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
+ .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
+ .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
+ .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
+ .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
+ .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init :
{
- *(.text)
- *(.stub)
+ KEEP (*(.init))
+ } =0x90909090
+ .plt : { *(.plt) }
+ .text :
+ {
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ KEEP (*(.text.*personality*))
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
- *(.gnu.linkonce.t*)
- } =0x9090
- _etext = .;
+ } =0x90909090
+ .fini :
+ {
+ KEEP (*(.fini))
+ } =0x90909090
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
PROVIDE (etext = .);
- .fini : { *(.fini) } =0x9090
- .rodata : { *(.rodata) *(.gnu.linkonce.r*) }
- .rodata1 : { *(.rodata1) }
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+ .rodata1 : { *(.rodata1) }
+ .eh_frame_hdr : { *(.eh_frame_hdr) }
+ .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+ .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
- . = ALIGN(0x1000) + (. & (0x1000 - 1)) ;
- .data :
+ . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+ /* Exception handling */
+ .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+ .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+ /* Thread Local Storage sections */
+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+ .preinit_array :
{
- *(.data)
- *(.gnu.linkonce.d*)
- CONSTRUCTORS
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
}
- .data1 : { *(.data1) }
- . = ALIGN(32 / 8);
+ .init_array :
+ {
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ }
+ .fini_array :
+ {
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(.fini_array))
+ KEEP (*(SORT(.fini_array.*)))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ }
_start_ctors = .;
PROVIDE (start_ctors = .);
- .ctors :
+ .ctors :
{
- *(.ctors)
+ /* gcc uses crtbegin.o to find the start of
+ the constructors, so we make sure it is
+ first. Because this is a wildcard, it
+ doesn't matter if the user does not
+ actually link against crtbegin.o; the
+ linker won't look for a file to match a
+ wildcard. The wildcard also means that it
+ doesn't matter which directory crtbegin.o
+ is in. */
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*crtbegin?.o(.ctors))
+ /* We don't want to include the .ctor section from
+ the crtend.o file until after the sorted ctors.
+ The .ctor section from the crtend file contains the
+ end of ctors marker and it must be last */
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
}
_stop_ctors = .;
PROVIDE (stop_ctors = .);
- .dtors :
+ .dtors :
{
- *(.dtors)
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*crtbegin?.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
}
- .got : { *(.got.plt) *(.got) }
- .dynamic : { *(.dynamic) }
- /* We want the small data sections together, so single-instruction offsets
- can access them all, and initialized data all before uninitialized, so
- we can shorten the on-disk segment size. */
- .sdata : { *(.sdata) }
- _edata = .;
- PROVIDE (edata = .);
+ .jcr : { KEEP (*(.jcr)) }
+ .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
+ .dynamic : { *(.dynamic) }
+ .got : { *(.got) }
+ . = DATA_SEGMENT_RELRO_END (12, .);
+ .got.plt : { *(.got.plt) }
+ .data :
+ {
+ *(.data .data.* .gnu.linkonce.d.*)
+ KEEP (*(.gnu.linkonce.d.*personality*))
+ SORT(CONSTRUCTORS)
+ }
+ .data1 : { *(.data1) }
+ _edata = .; PROVIDE (edata = .);
__bss_start = .;
- .sbss : { *(.sbss) *(.scommon) }
- .bss :
+ .bss :
{
*(.dynbss)
- *(.bss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
+ /* Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections.
+ FIXME: Why do we need it? When there is no .bss section, we don't
+ pad the .data section. */
+ . = ALIGN(. != 0 ? 32 / 8 : 1);
}
. = ALIGN(32 / 8);
- _end = . ;
- PROVIDE (end = .);
+ . = ALIGN(32 / 8);
+ _end = .; PROVIDE (end = .);
+ . = DATA_SEGMENT_END (.);
/* Stabs debugging sections. */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- .stab.excl 0 : { *(.stab.excl) }
- .stab.exclstr 0 : { *(.stab.exclstr) }
- .stab.index 0 : { *(.stab.index) }
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
- .comment 0 : { *(.comment) }
+ .comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
- .debug_info 0 : { *(.debug_info) }
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
- /* These must appear regardless of . */
+ /* DWARF 3 */
+ .debug_pubtypes 0 : { *(.debug_pubtypes) }
+ .debug_ranges 0 : { *(.debug_ranges) }
+ .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+ /DISCARD/ : { *(.note.GNU-stack) }
}
Index: projects/altix/sys/conf/ldscript.ia64
===================================================================
--- projects/altix/sys/conf/ldscript.ia64 (revision 218875)
+++ projects/altix/sys/conf/ldscript.ia64 (revision 218876)
@@ -1,148 +1,148 @@
/* $FreeBSD$ */
-OUTPUT_FORMAT("elf64-ia64-little", "elf64-ia64-little", "elf64-ia64-little")
+OUTPUT_FORMAT("elf64-ia64-freebsd", "elf64-ia64-freebsd", "elf64-ia64-freebsd")
OUTPUT_ARCH(ia64)
ENTRY(__start)
SEARCH_DIR(/usr/lib);
kernel_text = 0xe000003400000000; /* XXX_ALTIX_TODO */
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = kernel_text + SIZEOF_HEADERS;
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rela.init : { *(.rela.init) }
.rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
.rela.fini : { *(.rela.fini) }
.rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
.rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
.rela.ctors : { *(.rela.ctors) }
.rela.dtors : { *(.rela.dtors) }
.rela.got : { *(.rela.got) }
.rela.sdata : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) }
.rela.sbss : { *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) }
.rela.sdata2 : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) }
.rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) }
.rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
.rela.plt : { *(.rela.plt) }
.rela.IA_64.pltoff : { *(.rela.IA_64.pltoff) }
PROVIDE (btext = .);
.init :
{
*(.init)
} =0x00300000010070000002000001000400
.plt : { *(.plt) }
.text :
{
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
} =0x00300000010070000002000001000400
.fini :
{
*(.fini)
} =0x00300000010070000002000001000400
_etext = .;
PROVIDE (etext = .);
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.sdata2 : { *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) }
.sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
.opd : { *(.opd) }
.IA_64.unwind_info : { *(.IA_64.unwind_info* .gnu.linkonce.ia64unwi.*) }
.IA_64.unwind : { *(.IA_64.unwind* .gnu.linkonce.ia64unw.*) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = . + 8192;
.data :
{
*(.data.proc0 .data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
.data1 : { *(.data1) }
.dynamic : { *(.dynamic) }
.ctors :
{
*(.ctors)
*(SORT(.ctors.*))
}
.dtors :
{
*(.dtors)
*(SORT(.dtors.*))
}
. = ALIGN(16);
__gp = . + 0x200000;
.got : { *(.got.plt) *(.got) }
.IA_64.pltoff : { *(.IA_64.pltoff) }
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
.sdata :
{
*(.sdata .sdata.* .gnu.linkonce.s.*)
}
_edata = .;
PROVIDE (edata = .);
__bss_start = .;
.sbss :
{
PROVIDE (__sbss_start = .);
PROVIDE (___sbss_start = .);
*(.dynsbss)
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
PROVIDE (__sbss_end = .);
PROVIDE (___sbss_end = .);
}
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections. */
. = ALIGN(64 / 8);
}
. = ALIGN(64 / 8);
_end = .;
PROVIDE (end = .);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
}
Index: projects/altix/sys/conf/ldscript.sparc64
===================================================================
--- projects/altix/sys/conf/ldscript.sparc64 (revision 218875)
+++ projects/altix/sys/conf/ldscript.sparc64 (revision 218876)
@@ -1,265 +1,265 @@
/* $FreeBSD$ */
-OUTPUT_FORMAT("elf64-sparc", "elf64-sparc",
- "elf64-sparc")
+OUTPUT_FORMAT("elf64-sparc-freebsd", "elf64-sparc-freebsd",
+ "elf64-sparc-freebsd")
OUTPUT_ARCH(sparc:v9)
ENTRY(_start)
SEARCH_DIR(/usr/lib);
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = kernbase + SIZEOF_HEADERS;
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.text :
{
*(.rel.text)
*(.rel.text.*)
*(.rel.gnu.linkonce.t.*)
}
.rela.text :
{
*(.rela.text)
*(.rela.text.*)
*(.rela.gnu.linkonce.t.*)
}
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.rodata :
{
*(.rel.rodata)
*(.rel.rodata.*)
*(.rel.gnu.linkonce.r.*)
}
.rela.rodata :
{
*(.rela.rodata)
*(.rela.rodata.*)
*(.rela.gnu.linkonce.r.*)
}
.rel.data :
{
*(.rel.data)
*(.rel.data.*)
*(.rel.gnu.linkonce.d.*)
}
.rela.data :
{
*(.rela.data)
*(.rela.data.*)
*(.rela.gnu.linkonce.d.*)
}
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.sdata :
{
*(.rel.sdata)
*(.rel.sdata.*)
*(.rel.gnu.linkonce.s.*)
}
.rela.sdata :
{
*(.rela.sdata)
*(.rela.sdata.*)
*(.rela.gnu.linkonce.s.*)
}
.rel.sbss :
{
*(.rel.sbss)
*(.rel.sbss.*)
*(.rel.gnu.linkonce.sb.*)
}
.rela.sbss :
{
*(.rela.sbss)
*(.rela.sbss.*)
*(.rel.gnu.linkonce.sb.*)
}
.rel.sdata2 :
{
*(.rel.sdata2)
*(.rel.sdata2.*)
*(.rel.gnu.linkonce.s2.*)
}
.rela.sdata2 :
{
*(.rela.sdata2)
*(.rela.sdata2.*)
*(.rela.gnu.linkonce.s2.*)
}
.rel.sbss2 :
{
*(.rel.sbss2)
*(.rel.sbss2.*)
*(.rel.gnu.linkonce.sb2.*)
}
.rela.sbss2 :
{
*(.rela.sbss2)
*(.rela.sbss2.*)
*(.rela.gnu.linkonce.sb2.*)
}
.rel.bss :
{
*(.rel.bss)
*(.rel.bss.*)
*(.rel.gnu.linkonce.b.*)
}
.rela.bss :
{
*(.rela.bss)
*(.rela.bss.*)
*(.rela.gnu.linkonce.b.*)
}
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.init :
{
KEEP (*(.init))
} =0x1000000
.text :
{
*(.trap)
*(.text)
*(.text.*)
*(.stub)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.gnu.linkonce.t.*)
} =0x1000000
.fini :
{
KEEP (*(.fini))
} =0x1000000
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : { *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.sdata2 : { *(.sdata2) *(.sdata2.*) *(.gnu.linkonce.s2.*) }
.sbss2 : { *(.sbss2) *(.sbss2.*) *(.gnu.linkonce.sb2.*) }
. = ALIGN(0x2000) + (. & (0x2000 - 1));
.data :
{
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
.data1 : { *(.data1) }
.eh_frame : { KEEP (*(.eh_frame)) }
.gcc_except_table : { *(.gcc_except_table) }
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
/* We don't want to include the .ctor section from
from the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.plt : { *(.plt) }
.got : { *(.got.plt) *(.got) }
.dynamic : { *(.dynamic) }
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
.sdata :
{
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
}
_edata = .;
PROVIDE (edata = .);
__bss_start = .;
.sbss :
{
PROVIDE (__sbss_start = .);
PROVIDE (___sbss_start = .);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
PROVIDE (__sbss_end = .);
PROVIDE (___sbss_end = .);
}
.bss :
{
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections. */
. = ALIGN(64 / 8);
}
. = ALIGN(64 / 8);
_end = .;
PROVIDE (end = .);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* These must appear regardless of . */
}
Index: projects/altix/sys/conf
===================================================================
--- projects/altix/sys/conf (revision 218875)
+++ projects/altix/sys/conf (revision 218876)
Property changes on: projects/altix/sys/conf
___________________________________________________________________
Added: svn:mergeinfo
## -0,0 +0,11 ##
Merged /projects/binutils-2.17/sys/conf:r213992-218818
Merged /user/peter/kinfo/sys/conf:r185413-185547
Merged /projects/quota64/sys/conf:r184125-207707
Merged /head/sys/conf:r204938-218875
Merged /user/mav/ata/sys/conf:r189793-190578
Merged /user/thompsa/usb/sys/conf:r187190
Merged /user/dfr/xenhvm/6/sys/conf:r189304,189451
Merged /user/dfr/xenhvm/7/sys/conf:r188574-189614
Merged /user/piso/ipfw/sys/conf:r190918,190921,190923,190926
Merged /projects/cambria/sys/conf:r186008-186350
Merged /user/piso/sys/conf:r186543,186723,186725-186726,186742,186770-186771,186774,186777-186779,187984-187985,190555,190572,190589,190592,190614,190625,190830
Index: projects/altix/sys/contrib/dev/acpica
===================================================================
--- projects/altix/sys/contrib/dev/acpica (revision 218875)
+++ projects/altix/sys/contrib/dev/acpica (revision 218876)
Property changes on: projects/altix/sys/contrib/dev/acpica
___________________________________________________________________
Modified: svn:mergeinfo
## -0,0 +0,1 ##
Merged /head/sys/contrib/dev/acpica:r218817-218875
Index: projects/altix/sys/contrib/octeon-sdk
===================================================================
--- projects/altix/sys/contrib/octeon-sdk (revision 218875)
+++ projects/altix/sys/contrib/octeon-sdk (revision 218876)
Property changes on: projects/altix/sys/contrib/octeon-sdk
___________________________________________________________________
Modified: svn:mergeinfo
## -0,0 +0,1 ##
Merged /head/sys/contrib/octeon-sdk:r218817-218875
Index: projects/altix/sys/contrib/pf
===================================================================
--- projects/altix/sys/contrib/pf (revision 218875)
+++ projects/altix/sys/contrib/pf (revision 218876)
Property changes on: projects/altix/sys/contrib/pf
___________________________________________________________________
Modified: svn:mergeinfo
## -0,0 +0,1 ##
Merged /head/sys/contrib/pf:r218817-218875
Index: projects/altix/sys/contrib/x86emu
===================================================================
--- projects/altix/sys/contrib/x86emu (revision 218875)
+++ projects/altix/sys/contrib/x86emu (revision 218876)
Property changes on: projects/altix/sys/contrib/x86emu
___________________________________________________________________
Modified: svn:mergeinfo
## -0,0 +0,1 ##
Merged /head/sys/contrib/x86emu:r218817-218875
Index: projects/altix/sys/ddb/db_command.c
===================================================================
--- projects/altix/sys/ddb/db_command.c (revision 218875)
+++ projects/altix/sys/ddb/db_command.c (revision 218876)
@@ -1,827 +1,833 @@
/*-
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
/*
* Author: David B. Golub, Carnegie Mellon University
* Date: 7/90
*/
/*
* Command dispatcher.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/linker_set.h>
#include <sys/lock.h>
#include <sys/kdb.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/reboot.h>
#include <sys/signalvar.h>
#include <sys/systm.h>
#include <sys/cons.h>
#include <sys/watchdog.h>
#include <sys/kernel.h>
#include <ddb/ddb.h>
#include <ddb/db_command.h>
#include <ddb/db_lex.h>
#include <ddb/db_output.h>
#include <machine/cpu.h>
#include <machine/setjmp.h>
/*
* Exported global variables
*/
boolean_t db_cmd_loop_done;
db_addr_t db_dot;
db_addr_t db_last_addr;
db_addr_t db_prev;
db_addr_t db_next;
static db_cmdfcn_t db_fncall;
static db_cmdfcn_t db_gdb;
static db_cmdfcn_t db_halt;
static db_cmdfcn_t db_kill;
static db_cmdfcn_t db_reset;
static db_cmdfcn_t db_stack_trace;
static db_cmdfcn_t db_stack_trace_all;
static db_cmdfcn_t db_watchdog;
/*
* 'show' commands
*/
static struct command db_show_all_cmds[] = {
{ "trace", db_stack_trace_all, 0, 0 },
};
struct command_table db_show_all_table =
LIST_HEAD_INITIALIZER(db_show_all_table);
static struct command db_show_cmds[] = {
{ "all", 0, 0, &db_show_all_table },
{ "registers", db_show_regs, 0, 0 },
{ "breaks", db_listbreak_cmd, 0, 0 },
{ "threads", db_show_threads, 0, 0 },
};
struct command_table db_show_table = LIST_HEAD_INITIALIZER(db_show_table);
static struct command db_cmds[] = {
{ "print", db_print_cmd, 0, 0 },
{ "p", db_print_cmd, 0, 0 },
{ "examine", db_examine_cmd, CS_SET_DOT, 0 },
{ "x", db_examine_cmd, CS_SET_DOT, 0 },
{ "search", db_search_cmd, CS_OWN|CS_SET_DOT, 0 },
{ "set", db_set_cmd, CS_OWN, 0 },
{ "write", db_write_cmd, CS_MORE|CS_SET_DOT, 0 },
{ "w", db_write_cmd, CS_MORE|CS_SET_DOT, 0 },
{ "delete", db_delete_cmd, 0, 0 },
{ "d", db_delete_cmd, 0, 0 },
{ "break", db_breakpoint_cmd, 0, 0 },
{ "b", db_breakpoint_cmd, 0, 0 },
{ "dwatch", db_deletewatch_cmd, 0, 0 },
{ "watch", db_watchpoint_cmd, CS_MORE,0 },
{ "dhwatch", db_deletehwatch_cmd, 0, 0 },
{ "hwatch", db_hwatchpoint_cmd, 0, 0 },
{ "step", db_single_step_cmd, 0, 0 },
{ "s", db_single_step_cmd, 0, 0 },
{ "continue", db_continue_cmd, 0, 0 },
{ "c", db_continue_cmd, 0, 0 },
{ "until", db_trace_until_call_cmd,0, 0 },
{ "next", db_trace_until_matching_cmd,0, 0 },
{ "match", db_trace_until_matching_cmd,0, 0 },
{ "trace", db_stack_trace, CS_OWN, 0 },
{ "t", db_stack_trace, CS_OWN, 0 },
/* XXX alias for all trace */
{ "alltrace", db_stack_trace_all, 0, 0 },
{ "where", db_stack_trace, CS_OWN, 0 },
{ "bt", db_stack_trace, CS_OWN, 0 },
{ "call", db_fncall, CS_OWN, 0 },
{ "show", 0, 0, &db_show_table },
{ "ps", db_ps, 0, 0 },
{ "gdb", db_gdb, 0, 0 },
{ "halt", db_halt, 0, 0 },
{ "reboot", db_reset, 0, 0 },
{ "reset", db_reset, 0, 0 },
{ "kill", db_kill, CS_OWN, 0 },
{ "watchdog", db_watchdog, 0, 0 },
{ "thread", db_set_thread, CS_OWN, 0 },
{ "run", db_run_cmd, CS_OWN, 0 },
{ "script", db_script_cmd, CS_OWN, 0 },
{ "scripts", db_scripts_cmd, 0, 0 },
{ "unscript", db_unscript_cmd, CS_OWN, 0 },
{ "capture", db_capture_cmd, CS_OWN, 0 },
{ "textdump", db_textdump_cmd, CS_OWN, 0 },
};
struct command_table db_cmd_table = LIST_HEAD_INITIALIZER(db_cmd_table);
static struct command *db_last_command = 0;
/*
* if 'ed' style: 'dot' is set at start of last item printed,
* and '+' points to next line.
* Otherwise: 'dot' points to next item, '..' points to last.
*/
static boolean_t db_ed_style = TRUE;
/*
* Utility routine - discard tokens through end-of-line.
*/
void
db_skip_to_eol()
{
int t;
do {
t = db_read_token();
} while (t != tEOL);
}
/*
* Results of command search.
*/
#define CMD_UNIQUE 0
#define CMD_FOUND 1
#define CMD_NONE 2
#define CMD_AMBIGUOUS 3
#define CMD_HELP 4
static void db_cmd_match(char *name, struct command *cmd,
struct command **cmdp, int *resultp);
static void db_cmd_list(struct command_table *table);
static int db_cmd_search(char *name, struct command_table *table,
struct command **cmdp);
static void db_command(struct command **last_cmdp,
struct command_table *cmd_table, int dopager);
/*
* Initialize the command lists from the static tables.
*/
void
db_command_init(void)
{
#define N(a) (sizeof(a) / sizeof(a[0]))
int i;
for (i = 0; i < N(db_cmds); i++)
db_command_register(&db_cmd_table, &db_cmds[i]);
for (i = 0; i < N(db_show_cmds); i++)
db_command_register(&db_show_table, &db_show_cmds[i]);
for (i = 0; i < N(db_show_all_cmds); i++)
db_command_register(&db_show_all_table, &db_show_all_cmds[i]);
#undef N
}
/*
* Register a command.
*/
void
db_command_register(struct command_table *list, struct command *cmd)
{
struct command *c, *last;
last = NULL;
LIST_FOREACH(c, list, next) {
int n = strcmp(cmd->name, c->name);
/* Check that the command is not already present. */
if (n == 0) {
printf("%s: Warning, the command \"%s\" already exists;"
" ignoring request\n", __func__, cmd->name);
return;
}
if (n < 0) {
/* NB: keep list sorted lexicographically */
LIST_INSERT_BEFORE(c, cmd, next);
return;
}
last = c;
}
if (last == NULL)
LIST_INSERT_HEAD(list, cmd, next);
else
LIST_INSERT_AFTER(last, cmd, next);
}
/*
* Remove a command previously registered with db_command_register.
*/
void
db_command_unregister(struct command_table *list, struct command *cmd)
{
struct command *c;
LIST_FOREACH(c, list, next) {
if (cmd == c) {
LIST_REMOVE(cmd, next);
return;
}
}
/* NB: intentionally quiet */
}
/*
* Helper function to match a single command.
*/
static void
db_cmd_match(name, cmd, cmdp, resultp)
char * name;
struct command *cmd;
struct command **cmdp; /* out */
int * resultp;
{
char *lp, *rp;
int c;
lp = name;
rp = cmd->name;
while ((c = *lp) == *rp) {
if (c == 0) {
/* complete match */
*cmdp = cmd;
*resultp = CMD_UNIQUE;
return;
}
lp++;
rp++;
}
if (c == 0) {
/* end of name, not end of command -
partial match */
if (*resultp == CMD_FOUND) {
*resultp = CMD_AMBIGUOUS;
/* but keep looking for a full match -
this lets us match single letters */
} else {
*cmdp = cmd;
*resultp = CMD_FOUND;
}
}
}
/*
* Search for command prefix.
*/
static int
db_cmd_search(name, table, cmdp)
char * name;
struct command_table *table;
struct command **cmdp; /* out */
{
struct command *cmd;
int result = CMD_NONE;
LIST_FOREACH(cmd, table, next) {
db_cmd_match(name,cmd,cmdp,&result);
if (result == CMD_UNIQUE)
break;
}
if (result == CMD_NONE) {
/* check for 'help' */
if (name[0] == 'h' && name[1] == 'e'
&& name[2] == 'l' && name[3] == 'p')
result = CMD_HELP;
}
return (result);
}
static void
db_cmd_list(table)
struct command_table *table;
{
register struct command *cmd;
LIST_FOREACH(cmd, table, next) {
db_printf("%-12s", cmd->name);
db_end_line(12);
}
}
static void
db_command(last_cmdp, cmd_table, dopager)
struct command **last_cmdp; /* IN_OUT */
struct command_table *cmd_table;
int dopager;
{
struct command *cmd = NULL;
int t;
char modif[TOK_STRING_SIZE];
db_expr_t addr, count;
boolean_t have_addr = FALSE;
int result;
t = db_read_token();
if (t == tEOL) {
/* empty line repeats last command, at 'next' */
cmd = *last_cmdp;
addr = (db_expr_t)db_next;
have_addr = FALSE;
count = 1;
modif[0] = '\0';
}
else if (t == tEXCL) {
db_fncall((db_expr_t)0, (boolean_t)0, (db_expr_t)0, (char *)0);
return;
}
else if (t != tIDENT) {
db_printf("?\n");
db_flush_lex();
return;
}
else {
/*
* Search for command
*/
while (cmd_table) {
result = db_cmd_search(db_tok_string,
cmd_table,
&cmd);
switch (result) {
case CMD_NONE:
db_printf("No such command\n");
db_flush_lex();
return;
case CMD_AMBIGUOUS:
db_printf("Ambiguous\n");
db_flush_lex();
return;
case CMD_HELP:
db_cmd_list(cmd_table);
db_flush_lex();
return;
default:
break;
}
if ((cmd_table = cmd->more) != NULL) {
t = db_read_token();
if (t != tIDENT) {
db_cmd_list(cmd_table);
db_flush_lex();
return;
}
}
}
if ((cmd->flag & CS_OWN) == 0) {
/*
* Standard syntax:
* command [/modifier] [addr] [,count]
*/
t = db_read_token();
if (t == tSLASH) {
t = db_read_token();
if (t != tIDENT) {
db_printf("Bad modifier\n");
db_flush_lex();
return;
}
db_strcpy(modif, db_tok_string);
}
else {
db_unread_token(t);
modif[0] = '\0';
}
if (db_expression(&addr)) {
db_dot = (db_addr_t) addr;
db_last_addr = db_dot;
have_addr = TRUE;
}
else {
addr = (db_expr_t) db_dot;
have_addr = FALSE;
}
t = db_read_token();
if (t == tCOMMA) {
if (!db_expression(&count)) {
db_printf("Count missing\n");
db_flush_lex();
return;
}
}
else {
db_unread_token(t);
count = -1;
}
if ((cmd->flag & CS_MORE) == 0) {
db_skip_to_eol();
}
}
}
*last_cmdp = cmd;
if (cmd != 0) {
/*
* Execute the command.
*/
if (dopager)
db_enable_pager();
else
db_disable_pager();
(*cmd->fcn)(addr, have_addr, count, modif);
if (dopager)
db_disable_pager();
if (cmd->flag & CS_SET_DOT) {
/*
* If command changes dot, set dot to
* previous address displayed (if 'ed' style).
*/
if (db_ed_style) {
db_dot = db_prev;
}
else {
db_dot = db_next;
}
}
else {
/*
* If command does not change dot,
* set 'next' location to be the same.
*/
db_next = db_dot;
}
}
}
/*
* At least one non-optional command must be implemented using
* DB_COMMAND() so that db_cmd_set gets created. Here is one.
*/
DB_COMMAND(panic, db_panic)
{
db_disable_pager();
panic("from debugger");
}
void
db_command_loop()
{
/*
* Initialize 'prev' and 'next' to dot.
*/
db_prev = db_dot;
db_next = db_dot;
db_cmd_loop_done = 0;
while (!db_cmd_loop_done) {
if (db_print_position() != 0)
db_printf("\n");
db_printf("db> ");
(void) db_read_line();
db_command(&db_last_command, &db_cmd_table, /* dopager */ 1);
}
}
/*
* Execute a command on behalf of a script. The caller is responsible for
* making sure that the command string is < DB_MAXLINE or it will be
* truncated.
*
* XXXRW: Runs by injecting faked input into DDB input stream; it would be
* nicer to use an alternative approach that didn't mess with the previous
* command buffer.
*/
void
db_command_script(const char *command)
{
db_prev = db_next = db_dot;
db_inject_line(command);
db_command(&db_last_command, &db_cmd_table, /* dopager */ 0);
}
void
db_error(s)
const char *s;
{
if (s)
db_printf("%s", s);
db_flush_lex();
kdb_reenter();
}
/*
* Call random function:
* !expr(arg,arg,arg)
*/
/* The generic implementation supports a maximum of 10 arguments. */
typedef db_expr_t __db_f(db_expr_t, db_expr_t, db_expr_t, db_expr_t,
db_expr_t, db_expr_t, db_expr_t, db_expr_t, db_expr_t, db_expr_t);
static __inline int
db_fncall_generic(db_expr_t addr, db_expr_t *rv, int nargs, db_expr_t args[])
{
__db_f *f = (__db_f *)addr;
if (nargs > 10) {
db_printf("Too many arguments (max 10)\n");
return (0);
}
*rv = (*f)(args[0], args[1], args[2], args[3], args[4], args[5],
args[6], args[7], args[8], args[9]);
return (1);
}
static void
db_fncall(dummy1, dummy2, dummy3, dummy4)
db_expr_t dummy1;
boolean_t dummy2;
db_expr_t dummy3;
char * dummy4;
{
db_expr_t fn_addr;
db_expr_t args[DB_MAXARGS];
int nargs = 0;
db_expr_t retval;
int t;
if (!db_expression(&fn_addr)) {
db_printf("Bad function\n");
db_flush_lex();
return;
}
t = db_read_token();
if (t == tLPAREN) {
if (db_expression(&args[0])) {
nargs++;
while ((t = db_read_token()) == tCOMMA) {
if (nargs == DB_MAXARGS) {
db_printf("Too many arguments (max %d)\n", DB_MAXARGS);
db_flush_lex();
return;
}
if (!db_expression(&args[nargs])) {
db_printf("Argument missing\n");
db_flush_lex();
return;
}
nargs++;
}
db_unread_token(t);
}
if (db_read_token() != tRPAREN) {
db_printf("?\n");
db_flush_lex();
return;
}
}
db_skip_to_eol();
db_disable_pager();
if (DB_CALL(fn_addr, &retval, nargs, args))
db_printf("= %#lr\n", (long)retval);
}
static void
db_halt(db_expr_t dummy, boolean_t dummy2, db_expr_t dummy3, char *dummy4)
{
cpu_halt();
}
static void
db_kill(dummy1, dummy2, dummy3, dummy4)
db_expr_t dummy1;
boolean_t dummy2;
db_expr_t dummy3;
char * dummy4;
{
db_expr_t old_radix, pid, sig;
struct proc *p;
#define DB_ERROR(f) do { db_printf f; db_flush_lex(); goto out; } while (0)
/*
* PIDs and signal numbers are typically represented in base
* 10, so make that the default here. It can, of course, be
* overridden by specifying a prefix.
*/
old_radix = db_radix;
db_radix = 10;
/* Retrieve arguments. */
if (!db_expression(&sig))
DB_ERROR(("Missing signal number\n"));
if (!db_expression(&pid))
DB_ERROR(("Missing process ID\n"));
db_skip_to_eol();
if (!_SIG_VALID(sig))
DB_ERROR(("Signal number out of range\n"));
/*
* Find the process in question. allproc_lock is not needed
* since we're in DDB.
*/
/* sx_slock(&allproc_lock); */
FOREACH_PROC_IN_SYSTEM(p)
if (p->p_pid == pid)
break;
/* sx_sunlock(&allproc_lock); */
if (p == NULL)
DB_ERROR(("Can't find process with pid %ld\n", (long) pid));
/* If it's already locked, bail; otherwise, do the deed. */
if (PROC_TRYLOCK(p) == 0)
DB_ERROR(("Can't lock process with pid %ld\n", (long) pid));
else {
pksignal(p, sig, NULL);
PROC_UNLOCK(p);
}
out:
db_radix = old_radix;
#undef DB_ERROR
}
/*
* Reboot. In case there is an additional argument, take it as delay in
* seconds. Default to 15s if we cannot parse it and make sure we will
* never wait longer than 1 week. Some code is similar to
* kern_shutdown.c:shutdown_panic().
*/
#ifndef DB_RESET_MAXDELAY
#define DB_RESET_MAXDELAY (3600 * 24 * 7)
#endif
static void
db_reset(db_expr_t addr, boolean_t have_addr, db_expr_t count __unused,
char *modif __unused)
{
int delay, loop;
if (have_addr) {
delay = (int)db_hex2dec(addr);
/* If we parse to fail, use 15s. */
if (delay == -1)
delay = 15;
/* Cap at one week. */
if ((uintmax_t)delay > (uintmax_t)DB_RESET_MAXDELAY)
delay = DB_RESET_MAXDELAY;
db_printf("Automatic reboot in %d seconds - "
"press a key on the console to abort\n", delay);
for (loop = delay * 10; loop > 0; --loop) {
DELAY(1000 * 100); /* 1/10th second */
/* Did user type a key? */
if (cncheckc() != -1)
return;
}
}
cpu_reset();
}
static void
db_watchdog(dummy1, dummy2, dummy3, dummy4)
db_expr_t dummy1;
boolean_t dummy2;
db_expr_t dummy3;
char * dummy4;
{
int i;
/*
* XXX: It might make sense to be able to set the watchdog to a
* XXX: timeout here so that failure or hang as a result of subsequent
* XXX: ddb commands could be recovered by a reset.
*/
EVENTHANDLER_INVOKE(watchdog_list, 0, &i);
}
static void
db_gdb(db_expr_t dummy1, boolean_t dummy2, db_expr_t dummy3, char *dummy4)
{
- if (kdb_dbbe_select("gdb") != 0)
+ if (kdb_dbbe_select("gdb") != 0) {
db_printf("The remote GDB backend could not be selected.\n");
- else
- db_printf("Step to enter the remote GDB backend.\n");
+ return;
+ }
+ /*
+ * Mark that we are done in the debugger. kdb_trap()
+ * should re-enter with the new backend.
+ */
+ db_cmd_loop_done = 1;
+ db_printf("(ctrl-c will return control to ddb)\n");
}
static void
db_stack_trace(db_expr_t tid, boolean_t hastid, db_expr_t count, char *modif)
{
struct thread *td;
db_expr_t radix;
pid_t pid;
int t;
/*
* We parse our own arguments. We don't like the default radix.
*/
radix = db_radix;
db_radix = 10;
hastid = db_expression(&tid);
t = db_read_token();
if (t == tCOMMA) {
if (!db_expression(&count)) {
db_printf("Count missing\n");
db_flush_lex();
return;
}
} else {
db_unread_token(t);
count = -1;
}
db_skip_to_eol();
db_radix = radix;
if (hastid) {
td = kdb_thr_lookup((lwpid_t)tid);
if (td == NULL)
td = kdb_thr_from_pid((pid_t)tid);
if (td == NULL) {
db_printf("Thread %d not found\n", (int)tid);
return;
}
} else
td = kdb_thread;
if (td->td_proc != NULL)
pid = td->td_proc->p_pid;
else
pid = -1;
db_printf("Tracing pid %d tid %ld td %p\n", pid, (long)td->td_tid, td);
db_trace_thread(td, count);
}
static void
db_stack_trace_all(db_expr_t dummy, boolean_t dummy2, db_expr_t dummy3,
char *dummy4)
{
struct proc *p;
struct thread *td;
jmp_buf jb;
void *prev_jb;
FOREACH_PROC_IN_SYSTEM(p) {
prev_jb = kdb_jmpbuf(jb);
if (setjmp(jb) == 0) {
FOREACH_THREAD_IN_PROC(p, td) {
db_printf("\nTracing command %s pid %d tid %ld td %p\n",
p->p_comm, p->p_pid, (long)td->td_tid, td);
db_trace_thread(td, -1);
if (db_pager_quit) {
kdb_jmpbuf(prev_jb);
return;
}
}
}
kdb_jmpbuf(prev_jb);
}
}
/*
* Take the parsed expression value from the command line that was parsed
* as a hexadecimal value and convert it as if the expression was parsed
* as a decimal value. Returns -1 if the expression was not a valid
* decimal value.
*/
db_expr_t
db_hex2dec(db_expr_t expr)
{
uintptr_t x, y;
db_expr_t val;
y = 1;
val = 0;
x = expr;
while (x != 0) {
if (x % 16 > 9)
return (-1);
val += (x % 16) * (y);
x >>= 4;
y *= 10;
}
return (val);
}
Index: projects/altix/sys/dev/dc/if_dc.c
===================================================================
--- projects/altix/sys/dev/dc/if_dc.c (revision 218875)
+++ projects/altix/sys/dev/dc/if_dc.c (revision 218876)
@@ -1,3928 +1,4082 @@
/*-
* Copyright (c) 1997, 1998, 1999
* Bill Paul <wpaul@ee.columbia.edu>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Bill Paul.
* 4. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* DEC "tulip" clone ethernet driver. Supports the DEC/Intel 21143
* series chips and several workalikes including the following:
*
* Macronix 98713/98715/98725/98727/98732 PMAC (www.macronix.com)
* Macronix/Lite-On 82c115 PNIC II (www.macronix.com)
* Lite-On 82c168/82c169 PNIC (www.litecom.com)
* ASIX Electronics AX88140A (www.asix.com.tw)
* ASIX Electronics AX88141 (www.asix.com.tw)
* ADMtek AL981 (www.admtek.com.tw)
* ADMtek AN983 (www.admtek.com.tw)
* ADMtek CardBus AN985 (www.admtek.com.tw)
* Netgear FA511 (www.netgear.com) Appears to be rebadged ADMTek CardBus AN985
* Davicom DM9100, DM9102, DM9102A (www.davicom8.com)
* Accton EN1217 (www.accton.com)
* Xircom X3201 (www.xircom.com)
* Abocom FE2500
* Conexant LANfinity (www.conexant.com)
* 3Com OfficeConnect 10/100B 3CSOHO100B (www.3com.com)
*
* Datasheets for the 21143 are available at developer.intel.com.
* Datasheets for the clone parts can be found at their respective sites.
* (Except for the PNIC; see www.freebsd.org/~wpaul/PNIC/pnic.ps.gz.)
* The PNIC II is essentially a Macronix 98715A chip; the only difference
* worth noting is that its multicast hash table is only 128 bits wide
* instead of 512.
*
* Written by Bill Paul <wpaul@ee.columbia.edu>
* Electrical Engineering Department
* Columbia University, New York City
*/
/*
* The Intel 21143 is the successor to the DEC 21140. It is basically
* the same as the 21140 but with a few new features. The 21143 supports
* three kinds of media attachments:
*
* o MII port, for 10Mbps and 100Mbps support and NWAY
* autonegotiation provided by an external PHY.
* o SYM port, for symbol mode 100Mbps support.
* o 10baseT port.
* o AUI/BNC port.
*
* The 100Mbps SYM port and 10baseT port can be used together in
* combination with the internal NWAY support to create a 10/100
* autosensing configuration.
*
* Note that not all tulip workalikes are handled in this driver: we only
* deal with those which are relatively well behaved. The Winbond is
* handled separately due to its different register offsets and the
* special handling needed for its various bugs. The PNIC is handled
* here, but I'm not thrilled about it.
*
* All of the workalike chips use some form of MII transceiver support
* with the exception of the Macronix chips, which also have a SYM port.
* The ASIX AX88140A is also documented to have a SYM port, but all
* the cards I've seen use an MII transceiver, probably because the
* AX88140A doesn't support internal NWAY.
*/
#ifdef HAVE_KERNEL_OPTION_HEADERS
#include "opt_device_polling.h"
#endif
#include <sys/param.h>
#include <sys/endian.h>
#include <sys/systm.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <net/ethernet.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <net/if_vlan_var.h>
#include <net/bpf.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
-#define DC_USEIOSPACE
+#define DC_USEIOSPACE
#include <dev/dc/if_dcreg.h>
#ifdef __sparc64__
#include <dev/ofw/openfirm.h>
#include <machine/ofw_machdep.h>
#endif
MODULE_DEPEND(dc, pci, 1, 1, 1);
MODULE_DEPEND(dc, ether, 1, 1, 1);
MODULE_DEPEND(dc, miibus, 1, 1, 1);
/*
* "device miibus" is required in kernel config. See GENERIC if you get
* errors here.
*/
#include "miibus_if.h"
/*
* Various supported device vendors/types and their names.
*/
static const struct dc_type dc_devs[] = {
{ DC_DEVID(DC_VENDORID_DEC, DC_DEVICEID_21143), 0,
"Intel 21143 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_DAVICOM, DC_DEVICEID_DM9009), 0,
"Davicom DM9009 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_DAVICOM, DC_DEVICEID_DM9100), 0,
"Davicom DM9100 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_DAVICOM, DC_DEVICEID_DM9102), DC_REVISION_DM9102A,
"Davicom DM9102A 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_DAVICOM, DC_DEVICEID_DM9102), 0,
"Davicom DM9102 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_ADMTEK, DC_DEVICEID_AL981), 0,
"ADMtek AL981 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_ADMTEK, DC_DEVICEID_AN983), 0,
"ADMtek AN983 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_ADMTEK, DC_DEVICEID_AN985), 0,
"ADMtek AN985 CardBus 10/100BaseTX or clone" },
{ DC_DEVID(DC_VENDORID_ADMTEK, DC_DEVICEID_ADM9511), 0,
"ADMtek ADM9511 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_ADMTEK, DC_DEVICEID_ADM9513), 0,
"ADMtek ADM9513 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_ASIX, DC_DEVICEID_AX88140A), DC_REVISION_88141,
"ASIX AX88141 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_ASIX, DC_DEVICEID_AX88140A), 0,
"ASIX AX88140A 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_MX, DC_DEVICEID_98713), DC_REVISION_98713A,
"Macronix 98713A 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_MX, DC_DEVICEID_98713), 0,
"Macronix 98713 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_CP, DC_DEVICEID_98713_CP), DC_REVISION_98713A,
"Compex RL100-TX 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_CP, DC_DEVICEID_98713_CP), 0,
"Compex RL100-TX 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_MX, DC_DEVICEID_987x5), DC_REVISION_98725,
"Macronix 98725 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_MX, DC_DEVICEID_987x5), DC_REVISION_98715AEC_C,
"Macronix 98715AEC-C 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_MX, DC_DEVICEID_987x5), 0,
"Macronix 98715/98715A 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_MX, DC_DEVICEID_98727), 0,
"Macronix 98727/98732 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_LO, DC_DEVICEID_82C115), 0,
"LC82C115 PNIC II 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_LO, DC_DEVICEID_82C168), DC_REVISION_82C169,
"82c169 PNIC 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_LO, DC_DEVICEID_82C168), 0,
"82c168 PNIC 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_ACCTON, DC_DEVICEID_EN1217), 0,
"Accton EN1217 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_ACCTON, DC_DEVICEID_EN2242), 0,
"Accton EN2242 MiniPCI 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_XIRCOM, DC_DEVICEID_X3201), 0,
"Xircom X3201 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_DLINK, DC_DEVICEID_DRP32TXD), 0,
"Neteasy DRP-32TXD Cardbus 10/100" },
{ DC_DEVID(DC_VENDORID_ABOCOM, DC_DEVICEID_FE2500), 0,
"Abocom FE2500 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_ABOCOM, DC_DEVICEID_FE2500MX), 0,
"Abocom FE2500MX 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_CONEXANT, DC_DEVICEID_RS7112), 0,
"Conexant LANfinity MiniPCI 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_HAWKING, DC_DEVICEID_HAWKING_PN672TX), 0,
"Hawking CB102 CardBus 10/100" },
{ DC_DEVID(DC_VENDORID_PLANEX, DC_DEVICEID_FNW3602T), 0,
"PlaneX FNW-3602-T CardBus 10/100" },
{ DC_DEVID(DC_VENDORID_3COM, DC_DEVICEID_3CSOHOB), 0,
"3Com OfficeConnect 10/100B" },
{ DC_DEVID(DC_VENDORID_MICROSOFT, DC_DEVICEID_MSMN120), 0,
"Microsoft MN-120 CardBus 10/100" },
{ DC_DEVID(DC_VENDORID_MICROSOFT, DC_DEVICEID_MSMN130), 0,
"Microsoft MN-130 10/100" },
{ DC_DEVID(DC_VENDORID_LINKSYS, DC_DEVICEID_PCMPC200_AB08), 0,
"Linksys PCMPC200 CardBus 10/100" },
{ DC_DEVID(DC_VENDORID_LINKSYS, DC_DEVICEID_PCMPC200_AB09), 0,
"Linksys PCMPC200 CardBus 10/100" },
{ 0, 0, NULL }
};
static int dc_probe(device_t);
static int dc_attach(device_t);
static int dc_detach(device_t);
static int dc_suspend(device_t);
static int dc_resume(device_t);
static const struct dc_type *dc_devtype(device_t);
-static int dc_newbuf(struct dc_softc *, int, int);
+static void dc_discard_rxbuf(struct dc_softc *, int);
+static int dc_newbuf(struct dc_softc *, int);
static int dc_encap(struct dc_softc *, struct mbuf **);
static void dc_pnic_rx_bug_war(struct dc_softc *, int);
static int dc_rx_resync(struct dc_softc *);
static int dc_rxeof(struct dc_softc *);
static void dc_txeof(struct dc_softc *);
static void dc_tick(void *);
static void dc_tx_underrun(struct dc_softc *);
static void dc_intr(void *);
static void dc_start(struct ifnet *);
static void dc_start_locked(struct ifnet *);
static int dc_ioctl(struct ifnet *, u_long, caddr_t);
static void dc_init(void *);
static void dc_init_locked(struct dc_softc *);
static void dc_stop(struct dc_softc *);
static void dc_watchdog(void *);
static int dc_shutdown(device_t);
static int dc_ifmedia_upd(struct ifnet *);
static void dc_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+static int dc_dma_alloc(struct dc_softc *);
+static void dc_dma_free(struct dc_softc *);
+static void dc_dma_map_addr(void *, bus_dma_segment_t *, int, int);
+
static void dc_delay(struct dc_softc *);
static void dc_eeprom_idle(struct dc_softc *);
static void dc_eeprom_putbyte(struct dc_softc *, int);
-static void dc_eeprom_getword(struct dc_softc *, int, u_int16_t *);
-static void dc_eeprom_getword_pnic(struct dc_softc *, int, u_int16_t *);
-static void dc_eeprom_getword_xircom(struct dc_softc *, int, u_int16_t *);
+static void dc_eeprom_getword(struct dc_softc *, int, uint16_t *);
+static void dc_eeprom_getword_pnic(struct dc_softc *, int, uint16_t *);
+static void dc_eeprom_getword_xircom(struct dc_softc *, int, uint16_t *);
static void dc_eeprom_width(struct dc_softc *);
static void dc_read_eeprom(struct dc_softc *, caddr_t, int, int, int);
static void dc_mii_writebit(struct dc_softc *, int);
static int dc_mii_readbit(struct dc_softc *);
static void dc_mii_sync(struct dc_softc *);
-static void dc_mii_send(struct dc_softc *, u_int32_t, int);
+static void dc_mii_send(struct dc_softc *, uint32_t, int);
static int dc_mii_readreg(struct dc_softc *, struct dc_mii_frame *);
static int dc_mii_writereg(struct dc_softc *, struct dc_mii_frame *);
static int dc_miibus_readreg(device_t, int, int);
static int dc_miibus_writereg(device_t, int, int, int);
static void dc_miibus_statchg(device_t);
static void dc_miibus_mediainit(device_t);
static void dc_setcfg(struct dc_softc *, int);
static uint32_t dc_mchash_le(struct dc_softc *, const uint8_t *);
static uint32_t dc_mchash_be(const uint8_t *);
static void dc_setfilt_21143(struct dc_softc *);
static void dc_setfilt_asix(struct dc_softc *);
static void dc_setfilt_admtek(struct dc_softc *);
static void dc_setfilt_xircom(struct dc_softc *);
static void dc_setfilt(struct dc_softc *);
static void dc_reset(struct dc_softc *);
static int dc_list_rx_init(struct dc_softc *);
static int dc_list_tx_init(struct dc_softc *);
static int dc_read_srom(struct dc_softc *, int);
static int dc_parse_21143_srom(struct dc_softc *);
static int dc_decode_leaf_sia(struct dc_softc *, struct dc_eblock_sia *);
static int dc_decode_leaf_mii(struct dc_softc *, struct dc_eblock_mii *);
static int dc_decode_leaf_sym(struct dc_softc *, struct dc_eblock_sym *);
static void dc_apply_fixup(struct dc_softc *, int);
static int dc_check_multiport(struct dc_softc *);
#ifdef DC_USEIOSPACE
-#define DC_RES SYS_RES_IOPORT
-#define DC_RID DC_PCI_CFBIO
+#define DC_RES SYS_RES_IOPORT
+#define DC_RID DC_PCI_CFBIO
#else
-#define DC_RES SYS_RES_MEMORY
-#define DC_RID DC_PCI_CFBMA
+#define DC_RES SYS_RES_MEMORY
+#define DC_RID DC_PCI_CFBMA
#endif
static device_method_t dc_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, dc_probe),
DEVMETHOD(device_attach, dc_attach),
DEVMETHOD(device_detach, dc_detach),
DEVMETHOD(device_suspend, dc_suspend),
DEVMETHOD(device_resume, dc_resume),
DEVMETHOD(device_shutdown, dc_shutdown),
/* bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_driver_added, bus_generic_driver_added),
/* MII interface */
DEVMETHOD(miibus_readreg, dc_miibus_readreg),
DEVMETHOD(miibus_writereg, dc_miibus_writereg),
DEVMETHOD(miibus_statchg, dc_miibus_statchg),
DEVMETHOD(miibus_mediainit, dc_miibus_mediainit),
{ 0, 0 }
};
static driver_t dc_driver = {
"dc",
dc_methods,
sizeof(struct dc_softc)
};
static devclass_t dc_devclass;
DRIVER_MODULE(dc, pci, dc_driver, dc_devclass, 0, 0);
DRIVER_MODULE(miibus, dc, miibus_driver, miibus_devclass, 0, 0);
-#define DC_SETBIT(sc, reg, x) \
+#define DC_SETBIT(sc, reg, x) \
CSR_WRITE_4(sc, reg, CSR_READ_4(sc, reg) | (x))
-#define DC_CLRBIT(sc, reg, x) \
+#define DC_CLRBIT(sc, reg, x) \
CSR_WRITE_4(sc, reg, CSR_READ_4(sc, reg) & ~(x))
-#define SIO_SET(x) DC_SETBIT(sc, DC_SIO, (x))
-#define SIO_CLR(x) DC_CLRBIT(sc, DC_SIO, (x))
+#define SIO_SET(x) DC_SETBIT(sc, DC_SIO, (x))
+#define SIO_CLR(x) DC_CLRBIT(sc, DC_SIO, (x))
static void
dc_delay(struct dc_softc *sc)
{
int idx;
for (idx = (300 / 33) + 1; idx > 0; idx--)
CSR_READ_4(sc, DC_BUSCTL);
}
static void
dc_eeprom_width(struct dc_softc *sc)
{
int i;
/* Force EEPROM to idle state. */
dc_eeprom_idle(sc);
/* Enter EEPROM access mode. */
CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL);
dc_delay(sc);
DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ);
dc_delay(sc);
DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
dc_delay(sc);
DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS);
dc_delay(sc);
for (i = 3; i--;) {
if (6 & (1 << i))
DC_SETBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
else
DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
dc_delay(sc);
DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK);
dc_delay(sc);
DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
dc_delay(sc);
}
for (i = 1; i <= 12; i++) {
DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK);
dc_delay(sc);
if (!(CSR_READ_4(sc, DC_SIO) & DC_SIO_EE_DATAOUT)) {
DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
dc_delay(sc);
break;
}
DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
dc_delay(sc);
}
/* Turn off EEPROM access mode. */
dc_eeprom_idle(sc);
if (i < 4 || i > 12)
sc->dc_romwidth = 6;
else
sc->dc_romwidth = i;
/* Enter EEPROM access mode. */
CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL);
dc_delay(sc);
DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ);
dc_delay(sc);
DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
dc_delay(sc);
DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS);
dc_delay(sc);
/* Turn off EEPROM access mode. */
dc_eeprom_idle(sc);
}
static void
dc_eeprom_idle(struct dc_softc *sc)
{
int i;
CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL);
dc_delay(sc);
DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ);
dc_delay(sc);
DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
dc_delay(sc);
DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS);
dc_delay(sc);
for (i = 0; i < 25; i++) {
DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
dc_delay(sc);
DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK);
dc_delay(sc);
}
DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
dc_delay(sc);
DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CS);
dc_delay(sc);
CSR_WRITE_4(sc, DC_SIO, 0x00000000);
}
/*
* Send a read command and address to the EEPROM, check for ACK.
*/
static void
dc_eeprom_putbyte(struct dc_softc *sc, int addr)
{
int d, i;
d = DC_EECMD_READ >> 6;
for (i = 3; i--; ) {
if (d & (1 << i))
DC_SETBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
else
DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
dc_delay(sc);
DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK);
dc_delay(sc);
DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
dc_delay(sc);
}
/*
* Feed in each bit and strobe the clock.
*/
for (i = sc->dc_romwidth; i--;) {
if (addr & (1 << i)) {
SIO_SET(DC_SIO_EE_DATAIN);
} else {
SIO_CLR(DC_SIO_EE_DATAIN);
}
dc_delay(sc);
SIO_SET(DC_SIO_EE_CLK);
dc_delay(sc);
SIO_CLR(DC_SIO_EE_CLK);
dc_delay(sc);
}
}
/*
* Read a word of data stored in the EEPROM at address 'addr.'
* The PNIC 82c168/82c169 has its own non-standard way to read
* the EEPROM.
*/
static void
-dc_eeprom_getword_pnic(struct dc_softc *sc, int addr, u_int16_t *dest)
+dc_eeprom_getword_pnic(struct dc_softc *sc, int addr, uint16_t *dest)
{
int i;
- u_int32_t r;
+ uint32_t r;
CSR_WRITE_4(sc, DC_PN_SIOCTL, DC_PN_EEOPCODE_READ | addr);
for (i = 0; i < DC_TIMEOUT; i++) {
DELAY(1);
r = CSR_READ_4(sc, DC_SIO);
if (!(r & DC_PN_SIOCTL_BUSY)) {
- *dest = (u_int16_t)(r & 0xFFFF);
+ *dest = (uint16_t)(r & 0xFFFF);
return;
}
}
}
/*
* Read a word of data stored in the EEPROM at address 'addr.'
* The Xircom X3201 has its own non-standard way to read
* the EEPROM, too.
*/
static void
-dc_eeprom_getword_xircom(struct dc_softc *sc, int addr, u_int16_t *dest)
+dc_eeprom_getword_xircom(struct dc_softc *sc, int addr, uint16_t *dest)
{
SIO_SET(DC_SIO_ROMSEL | DC_SIO_ROMCTL_READ);
addr *= 2;
CSR_WRITE_4(sc, DC_ROM, addr | 0x160);
- *dest = (u_int16_t)CSR_READ_4(sc, DC_SIO) & 0xff;
+ *dest = (uint16_t)CSR_READ_4(sc, DC_SIO) & 0xff;
addr += 1;
CSR_WRITE_4(sc, DC_ROM, addr | 0x160);
- *dest |= ((u_int16_t)CSR_READ_4(sc, DC_SIO) & 0xff) << 8;
+ *dest |= ((uint16_t)CSR_READ_4(sc, DC_SIO) & 0xff) << 8;
SIO_CLR(DC_SIO_ROMSEL | DC_SIO_ROMCTL_READ);
}
/*
* Read a word of data stored in the EEPROM at address 'addr.'
*/
static void
-dc_eeprom_getword(struct dc_softc *sc, int addr, u_int16_t *dest)
+dc_eeprom_getword(struct dc_softc *sc, int addr, uint16_t *dest)
{
int i;
- u_int16_t word = 0;
+ uint16_t word = 0;
/* Force EEPROM to idle state. */
dc_eeprom_idle(sc);
/* Enter EEPROM access mode. */
CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL);
dc_delay(sc);
DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ);
dc_delay(sc);
DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
dc_delay(sc);
DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS);
dc_delay(sc);
/*
* Send address of word we want to read.
*/
dc_eeprom_putbyte(sc, addr);
/*
* Start reading bits from EEPROM.
*/
for (i = 0x8000; i; i >>= 1) {
SIO_SET(DC_SIO_EE_CLK);
dc_delay(sc);
if (CSR_READ_4(sc, DC_SIO) & DC_SIO_EE_DATAOUT)
word |= i;
dc_delay(sc);
SIO_CLR(DC_SIO_EE_CLK);
dc_delay(sc);
}
/* Turn off EEPROM access mode. */
dc_eeprom_idle(sc);
*dest = word;
}
/*
* Read a sequence of words from the EEPROM.
*/
static void
dc_read_eeprom(struct dc_softc *sc, caddr_t dest, int off, int cnt, int be)
{
int i;
- u_int16_t word = 0, *ptr;
+ uint16_t word = 0, *ptr;
for (i = 0; i < cnt; i++) {
if (DC_IS_PNIC(sc))
dc_eeprom_getword_pnic(sc, off + i, &word);
else if (DC_IS_XIRCOM(sc))
dc_eeprom_getword_xircom(sc, off + i, &word);
else
dc_eeprom_getword(sc, off + i, &word);
- ptr = (u_int16_t *)(dest + (i * 2));
+ ptr = (uint16_t *)(dest + (i * 2));
if (be)
*ptr = be16toh(word);
else
*ptr = le16toh(word);
}
}
/*
* The following two routines are taken from the Macronix 98713
* Application Notes pp.19-21.
*/
/*
* Write a bit to the MII bus.
*/
static void
dc_mii_writebit(struct dc_softc *sc, int bit)
{
uint32_t reg;
reg = DC_SIO_ROMCTL_WRITE | (bit != 0 ? DC_SIO_MII_DATAOUT : 0);
CSR_WRITE_4(sc, DC_SIO, reg);
CSR_BARRIER_4(sc, DC_SIO,
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
DELAY(1);
CSR_WRITE_4(sc, DC_SIO, reg | DC_SIO_MII_CLK);
CSR_BARRIER_4(sc, DC_SIO,
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
DELAY(1);
CSR_WRITE_4(sc, DC_SIO, reg);
CSR_BARRIER_4(sc, DC_SIO,
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
DELAY(1);
}
/*
* Read a bit from the MII bus.
*/
static int
dc_mii_readbit(struct dc_softc *sc)
{
uint32_t reg;
reg = DC_SIO_ROMCTL_READ | DC_SIO_MII_DIR;
CSR_WRITE_4(sc, DC_SIO, reg);
CSR_BARRIER_4(sc, DC_SIO,
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
DELAY(1);
(void)CSR_READ_4(sc, DC_SIO);
CSR_WRITE_4(sc, DC_SIO, reg | DC_SIO_MII_CLK);
CSR_BARRIER_4(sc, DC_SIO,
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
DELAY(1);
CSR_WRITE_4(sc, DC_SIO, reg);
CSR_BARRIER_4(sc, DC_SIO,
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
DELAY(1);
if (CSR_READ_4(sc, DC_SIO) & DC_SIO_MII_DATAIN)
return (1);
return (0);
}
/*
* Sync the PHYs by setting data bit and strobing the clock 32 times.
*/
static void
dc_mii_sync(struct dc_softc *sc)
{
int i;
CSR_WRITE_4(sc, DC_SIO, DC_SIO_ROMCTL_WRITE);
CSR_BARRIER_4(sc, DC_SIO,
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
DELAY(1);
for (i = 0; i < 32; i++)
dc_mii_writebit(sc, 1);
}
/*
* Clock a series of bits through the MII.
*/
static void
-dc_mii_send(struct dc_softc *sc, u_int32_t bits, int cnt)
+dc_mii_send(struct dc_softc *sc, uint32_t bits, int cnt)
{
int i;
for (i = (0x1 << (cnt - 1)); i; i >>= 1)
dc_mii_writebit(sc, bits & i);
}
/*
* Read an PHY register through the MII.
*/
static int
dc_mii_readreg(struct dc_softc *sc, struct dc_mii_frame *frame)
{
int i;
/*
* Set up frame for RX.
*/
frame->mii_stdelim = DC_MII_STARTDELIM;
frame->mii_opcode = DC_MII_READOP;
/*
* Sync the PHYs.
*/
dc_mii_sync(sc);
/*
* Send command/address info.
*/
dc_mii_send(sc, frame->mii_stdelim, 2);
dc_mii_send(sc, frame->mii_opcode, 2);
dc_mii_send(sc, frame->mii_phyaddr, 5);
dc_mii_send(sc, frame->mii_regaddr, 5);
/*
* Now try reading data bits. If the turnaround failed, we still
* need to clock through 16 cycles to keep the PHY(s) in sync.
*/
frame->mii_turnaround = dc_mii_readbit(sc);
if (frame->mii_turnaround != 0) {
for (i = 0; i < 16; i++)
dc_mii_readbit(sc);
goto fail;
}
for (i = 0x8000; i; i >>= 1) {
if (dc_mii_readbit(sc))
frame->mii_data |= i;
}
fail:
/* Clock the idle bits. */
dc_mii_writebit(sc, 0);
dc_mii_writebit(sc, 0);
if (frame->mii_turnaround != 0)
return (1);
return (0);
}
/*
* Write to a PHY register through the MII.
*/
static int
dc_mii_writereg(struct dc_softc *sc, struct dc_mii_frame *frame)
{
/*
* Set up frame for TX.
*/
frame->mii_stdelim = DC_MII_STARTDELIM;
frame->mii_opcode = DC_MII_WRITEOP;
frame->mii_turnaround = DC_MII_TURNAROUND;
/*
* Sync the PHYs.
*/
dc_mii_sync(sc);
dc_mii_send(sc, frame->mii_stdelim, 2);
dc_mii_send(sc, frame->mii_opcode, 2);
dc_mii_send(sc, frame->mii_phyaddr, 5);
dc_mii_send(sc, frame->mii_regaddr, 5);
dc_mii_send(sc, frame->mii_turnaround, 2);
dc_mii_send(sc, frame->mii_data, 16);
/* Clock the idle bits. */
dc_mii_writebit(sc, 0);
dc_mii_writebit(sc, 0);
return (0);
}
static int
dc_miibus_readreg(device_t dev, int phy, int reg)
{
struct dc_mii_frame frame;
struct dc_softc *sc;
int i, rval, phy_reg = 0;
sc = device_get_softc(dev);
bzero(&frame, sizeof(frame));
if (sc->dc_pmode != DC_PMODE_MII) {
if (phy == (MII_NPHY - 1)) {
switch (reg) {
case MII_BMSR:
/*
* Fake something to make the probe
* code think there's a PHY here.
*/
return (BMSR_MEDIAMASK);
break;
case MII_PHYIDR1:
if (DC_IS_PNIC(sc))
return (DC_VENDORID_LO);
return (DC_VENDORID_DEC);
break;
case MII_PHYIDR2:
if (DC_IS_PNIC(sc))
return (DC_DEVICEID_82C168);
return (DC_DEVICEID_21143);
break;
default:
return (0);
break;
}
} else
return (0);
}
if (DC_IS_PNIC(sc)) {
CSR_WRITE_4(sc, DC_PN_MII, DC_PN_MIIOPCODE_READ |
(phy << 23) | (reg << 18));
for (i = 0; i < DC_TIMEOUT; i++) {
DELAY(1);
rval = CSR_READ_4(sc, DC_PN_MII);
if (!(rval & DC_PN_MII_BUSY)) {
rval &= 0xFFFF;
return (rval == 0xFFFF ? 0 : rval);
}
}
return (0);
}
if (DC_IS_COMET(sc)) {
switch (reg) {
case MII_BMCR:
phy_reg = DC_AL_BMCR;
break;
case MII_BMSR:
phy_reg = DC_AL_BMSR;
break;
case MII_PHYIDR1:
phy_reg = DC_AL_VENID;
break;
case MII_PHYIDR2:
phy_reg = DC_AL_DEVID;
break;
case MII_ANAR:
phy_reg = DC_AL_ANAR;
break;
case MII_ANLPAR:
phy_reg = DC_AL_LPAR;
break;
case MII_ANER:
phy_reg = DC_AL_ANER;
break;
default:
device_printf(dev, "phy_read: bad phy register %x\n",
reg);
return (0);
break;
}
rval = CSR_READ_4(sc, phy_reg) & 0x0000FFFF;
if (rval == 0xFFFF)
return (0);
return (rval);
}
frame.mii_phyaddr = phy;
frame.mii_regaddr = reg;
if (sc->dc_type == DC_TYPE_98713) {
phy_reg = CSR_READ_4(sc, DC_NETCFG);
CSR_WRITE_4(sc, DC_NETCFG, phy_reg & ~DC_NETCFG_PORTSEL);
}
dc_mii_readreg(sc, &frame);
if (sc->dc_type == DC_TYPE_98713)
CSR_WRITE_4(sc, DC_NETCFG, phy_reg);
return (frame.mii_data);
}
static int
dc_miibus_writereg(device_t dev, int phy, int reg, int data)
{
struct dc_softc *sc;
struct dc_mii_frame frame;
int i, phy_reg = 0;
sc = device_get_softc(dev);
bzero(&frame, sizeof(frame));
if (DC_IS_PNIC(sc)) {
CSR_WRITE_4(sc, DC_PN_MII, DC_PN_MIIOPCODE_WRITE |
(phy << 23) | (reg << 10) | data);
for (i = 0; i < DC_TIMEOUT; i++) {
if (!(CSR_READ_4(sc, DC_PN_MII) & DC_PN_MII_BUSY))
break;
}
return (0);
}
if (DC_IS_COMET(sc)) {
switch (reg) {
case MII_BMCR:
phy_reg = DC_AL_BMCR;
break;
case MII_BMSR:
phy_reg = DC_AL_BMSR;
break;
case MII_PHYIDR1:
phy_reg = DC_AL_VENID;
break;
case MII_PHYIDR2:
phy_reg = DC_AL_DEVID;
break;
case MII_ANAR:
phy_reg = DC_AL_ANAR;
break;
case MII_ANLPAR:
phy_reg = DC_AL_LPAR;
break;
case MII_ANER:
phy_reg = DC_AL_ANER;
break;
default:
device_printf(dev, "phy_write: bad phy register %x\n",
reg);
return (0);
break;
}
CSR_WRITE_4(sc, phy_reg, data);
return (0);
}
frame.mii_phyaddr = phy;
frame.mii_regaddr = reg;
frame.mii_data = data;
if (sc->dc_type == DC_TYPE_98713) {
phy_reg = CSR_READ_4(sc, DC_NETCFG);
CSR_WRITE_4(sc, DC_NETCFG, phy_reg & ~DC_NETCFG_PORTSEL);
}
dc_mii_writereg(sc, &frame);
if (sc->dc_type == DC_TYPE_98713)
CSR_WRITE_4(sc, DC_NETCFG, phy_reg);
return (0);
}
static void
dc_miibus_statchg(device_t dev)
{
struct dc_softc *sc;
struct ifnet *ifp;
struct mii_data *mii;
struct ifmedia *ifm;
sc = device_get_softc(dev);
mii = device_get_softc(sc->dc_miibus);
ifp = sc->dc_ifp;
if (mii == NULL || ifp == NULL ||
(ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
return;
ifm = &mii->mii_media;
if (DC_IS_DAVICOM(sc) &&
IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1) {
dc_setcfg(sc, ifm->ifm_media);
sc->dc_if_media = ifm->ifm_media;
return;
}
sc->dc_link = 0;
if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
(IFM_ACTIVE | IFM_AVALID)) {
switch (IFM_SUBTYPE(mii->mii_media_active)) {
case IFM_10_T:
case IFM_100_TX:
sc->dc_link = 1;
break;
default:
break;
}
}
if (sc->dc_link == 0)
return;
sc->dc_if_media = mii->mii_media_active;
if (DC_IS_ADMTEK(sc))
return;
dc_setcfg(sc, mii->mii_media_active);
}
/*
* Special support for DM9102A cards with HomePNA PHYs. Note:
* with the Davicom DM9102A/DM9801 eval board that I have, it seems
* to be impossible to talk to the management interface of the DM9801
* PHY (its MDIO pin is not connected to anything). Consequently,
* the driver has to just 'know' about the additional mode and deal
* with it itself. *sigh*
*/
static void
dc_miibus_mediainit(device_t dev)
{
struct dc_softc *sc;
struct mii_data *mii;
struct ifmedia *ifm;
int rev;
rev = pci_get_revid(dev);
sc = device_get_softc(dev);
mii = device_get_softc(sc->dc_miibus);
ifm = &mii->mii_media;
if (DC_IS_DAVICOM(sc) && rev >= DC_REVISION_DM9102A)
ifmedia_add(ifm, IFM_ETHER | IFM_HPNA_1, 0, NULL);
}
-#define DC_BITS_512 9
-#define DC_BITS_128 7
-#define DC_BITS_64 6
+#define DC_BITS_512 9
+#define DC_BITS_128 7
+#define DC_BITS_64 6
static uint32_t
dc_mchash_le(struct dc_softc *sc, const uint8_t *addr)
{
uint32_t crc;
/* Compute CRC for the address value. */
crc = ether_crc32_le(addr, ETHER_ADDR_LEN);
/*
* The hash table on the PNIC II and the MX98715AEC-C/D/E
* chips is only 128 bits wide.
*/
if (sc->dc_flags & DC_128BIT_HASH)
return (crc & ((1 << DC_BITS_128) - 1));
/* The hash table on the MX98715BEC is only 64 bits wide. */
if (sc->dc_flags & DC_64BIT_HASH)
return (crc & ((1 << DC_BITS_64) - 1));
/* Xircom's hash filtering table is different (read: weird) */
/* Xircom uses the LEAST significant bits */
if (DC_IS_XIRCOM(sc)) {
if ((crc & 0x180) == 0x180)
return ((crc & 0x0F) + (crc & 0x70) * 3 + (14 << 4));
else
return ((crc & 0x1F) + ((crc >> 1) & 0xF0) * 3 +
(12 << 4));
}
return (crc & ((1 << DC_BITS_512) - 1));
}
/*
* Calculate CRC of a multicast group address, return the lower 6 bits.
*/
static uint32_t
dc_mchash_be(const uint8_t *addr)
{
uint32_t crc;
/* Compute CRC for the address value. */
crc = ether_crc32_be(addr, ETHER_ADDR_LEN);
/* Return the filter bit position. */
return ((crc >> 26) & 0x0000003F);
}
/*
* 21143-style RX filter setup routine. Filter programming is done by
* downloading a special setup frame into the TX engine. 21143, Macronix,
* PNIC, PNIC II and Davicom chips are programmed this way.
*
* We always program the chip using 'hash perfect' mode, i.e. one perfect
* address (our node address) and a 512-bit hash filter for multicast
* frames. We also sneak the broadcast address into the hash filter since
* we need that too.
*/
static void
dc_setfilt_21143(struct dc_softc *sc)
{
uint16_t eaddr[(ETHER_ADDR_LEN+1)/2];
struct dc_desc *sframe;
- u_int32_t h, *sp;
+ uint32_t h, *sp;
struct ifmultiaddr *ifma;
struct ifnet *ifp;
int i;
ifp = sc->dc_ifp;
i = sc->dc_cdata.dc_tx_prod;
DC_INC(sc->dc_cdata.dc_tx_prod, DC_TX_LIST_CNT);
sc->dc_cdata.dc_tx_cnt++;
- sframe = &sc->dc_ldata->dc_tx_list[i];
+ sframe = &sc->dc_ldata.dc_tx_list[i];
sp = sc->dc_cdata.dc_sbuf;
bzero(sp, DC_SFRAME_LEN);
- sframe->dc_data = htole32(sc->dc_saddr);
+ sframe->dc_data = htole32(DC_ADDR_LO(sc->dc_saddr));
sframe->dc_ctl = htole32(DC_SFRAME_LEN | DC_TXCTL_SETUP |
DC_TXCTL_TLINK | DC_FILTER_HASHPERF | DC_TXCTL_FINT);
sc->dc_cdata.dc_tx_chain[i] = (struct mbuf *)sc->dc_cdata.dc_sbuf;
/* If we want promiscuous mode, set the allframes bit. */
if (ifp->if_flags & IFF_PROMISC)
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC);
else
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC);
if (ifp->if_flags & IFF_ALLMULTI)
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
else
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
h = dc_mchash_le(sc,
LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
sp[h >> 4] |= htole32(1 << (h & 0xF));
}
if_maddr_runlock(ifp);
if (ifp->if_flags & IFF_BROADCAST) {
h = dc_mchash_le(sc, ifp->if_broadcastaddr);
sp[h >> 4] |= htole32(1 << (h & 0xF));
}
/* Set our MAC address. */
bcopy(IF_LLADDR(sc->dc_ifp), eaddr, ETHER_ADDR_LEN);
sp[39] = DC_SP_MAC(eaddr[0]);
sp[40] = DC_SP_MAC(eaddr[1]);
sp[41] = DC_SP_MAC(eaddr[2]);
sframe->dc_status = htole32(DC_TXSTAT_OWN);
+ bus_dmamap_sync(sc->dc_stag, sc->dc_smap, BUS_DMASYNC_PREWRITE);
CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF);
/*
* The PNIC takes an exceedingly long time to process its
* setup frame; wait 10ms after posting the setup frame
* before proceeding, just so it has time to swallow its
* medicine.
*/
DELAY(10000);
sc->dc_wdog_timer = 5;
}
static void
dc_setfilt_admtek(struct dc_softc *sc)
{
uint8_t eaddr[ETHER_ADDR_LEN];
struct ifnet *ifp;
struct ifmultiaddr *ifma;
int h = 0;
- u_int32_t hashes[2] = { 0, 0 };
+ uint32_t hashes[2] = { 0, 0 };
ifp = sc->dc_ifp;
/* Init our MAC address. */
bcopy(IF_LLADDR(sc->dc_ifp), eaddr, ETHER_ADDR_LEN);
CSR_WRITE_4(sc, DC_AL_PAR0, eaddr[3] << 24 | eaddr[2] << 16 |
eaddr[1] << 8 | eaddr[0]);
CSR_WRITE_4(sc, DC_AL_PAR1, eaddr[5] << 8 | eaddr[4]);
/* If we want promiscuous mode, set the allframes bit. */
if (ifp->if_flags & IFF_PROMISC)
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC);
else
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC);
if (ifp->if_flags & IFF_ALLMULTI)
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
else
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
/* First, zot all the existing hash bits. */
CSR_WRITE_4(sc, DC_AL_MAR0, 0);
CSR_WRITE_4(sc, DC_AL_MAR1, 0);
/*
* If we're already in promisc or allmulti mode, we
* don't have to bother programming the multicast filter.
*/
if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI))
return;
/* Now program new ones. */
if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
if (DC_IS_CENTAUR(sc))
h = dc_mchash_le(sc,
LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
else
h = dc_mchash_be(
LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
if (h < 32)
hashes[0] |= (1 << h);
else
hashes[1] |= (1 << (h - 32));
}
if_maddr_runlock(ifp);
CSR_WRITE_4(sc, DC_AL_MAR0, hashes[0]);
CSR_WRITE_4(sc, DC_AL_MAR1, hashes[1]);
}
static void
dc_setfilt_asix(struct dc_softc *sc)
{
uint32_t eaddr[(ETHER_ADDR_LEN+3)/4];
struct ifnet *ifp;
struct ifmultiaddr *ifma;
int h = 0;
- u_int32_t hashes[2] = { 0, 0 };
+ uint32_t hashes[2] = { 0, 0 };
ifp = sc->dc_ifp;
/* Init our MAC address. */
bcopy(IF_LLADDR(sc->dc_ifp), eaddr, ETHER_ADDR_LEN);
CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_PAR0);
CSR_WRITE_4(sc, DC_AX_FILTDATA, eaddr[0]);
CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_PAR1);
CSR_WRITE_4(sc, DC_AX_FILTDATA, eaddr[1]);
/* If we want promiscuous mode, set the allframes bit. */
if (ifp->if_flags & IFF_PROMISC)
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC);
else
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC);
if (ifp->if_flags & IFF_ALLMULTI)
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
else
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
/*
* The ASIX chip has a special bit to enable reception
* of broadcast frames.
*/
if (ifp->if_flags & IFF_BROADCAST)
DC_SETBIT(sc, DC_NETCFG, DC_AX_NETCFG_RX_BROAD);
else
DC_CLRBIT(sc, DC_NETCFG, DC_AX_NETCFG_RX_BROAD);
/* first, zot all the existing hash bits */
CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR0);
CSR_WRITE_4(sc, DC_AX_FILTDATA, 0);
CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR1);
CSR_WRITE_4(sc, DC_AX_FILTDATA, 0);
/*
* If we're already in promisc or allmulti mode, we
* don't have to bother programming the multicast filter.
*/
if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI))
return;
/* now program new ones */
if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
h = dc_mchash_be(LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
if (h < 32)
hashes[0] |= (1 << h);
else
hashes[1] |= (1 << (h - 32));
}
if_maddr_runlock(ifp);
CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR0);
CSR_WRITE_4(sc, DC_AX_FILTDATA, hashes[0]);
CSR_WRITE_4(sc, DC_AX_FILTIDX, DC_AX_FILTIDX_MAR1);
CSR_WRITE_4(sc, DC_AX_FILTDATA, hashes[1]);
}
static void
dc_setfilt_xircom(struct dc_softc *sc)
{
uint16_t eaddr[(ETHER_ADDR_LEN+1)/2];
struct ifnet *ifp;
struct ifmultiaddr *ifma;
struct dc_desc *sframe;
- u_int32_t h, *sp;
+ uint32_t h, *sp;
int i;
ifp = sc->dc_ifp;
DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_TX_ON | DC_NETCFG_RX_ON));
i = sc->dc_cdata.dc_tx_prod;
DC_INC(sc->dc_cdata.dc_tx_prod, DC_TX_LIST_CNT);
sc->dc_cdata.dc_tx_cnt++;
- sframe = &sc->dc_ldata->dc_tx_list[i];
+ sframe = &sc->dc_ldata.dc_tx_list[i];
sp = sc->dc_cdata.dc_sbuf;
bzero(sp, DC_SFRAME_LEN);
- sframe->dc_data = htole32(sc->dc_saddr);
+ sframe->dc_data = htole32(DC_ADDR_LO(sc->dc_saddr));
sframe->dc_ctl = htole32(DC_SFRAME_LEN | DC_TXCTL_SETUP |
DC_TXCTL_TLINK | DC_FILTER_HASHPERF | DC_TXCTL_FINT);
sc->dc_cdata.dc_tx_chain[i] = (struct mbuf *)sc->dc_cdata.dc_sbuf;
/* If we want promiscuous mode, set the allframes bit. */
if (ifp->if_flags & IFF_PROMISC)
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC);
else
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_PROMISC);
if (ifp->if_flags & IFF_ALLMULTI)
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
else
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_RX_ALLMULTI);
if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
h = dc_mchash_le(sc,
LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
sp[h >> 4] |= htole32(1 << (h & 0xF));
}
if_maddr_runlock(ifp);
if (ifp->if_flags & IFF_BROADCAST) {
h = dc_mchash_le(sc, ifp->if_broadcastaddr);
sp[h >> 4] |= htole32(1 << (h & 0xF));
}
/* Set our MAC address. */
bcopy(IF_LLADDR(sc->dc_ifp), eaddr, ETHER_ADDR_LEN);
sp[0] = DC_SP_MAC(eaddr[0]);
sp[1] = DC_SP_MAC(eaddr[1]);
sp[2] = DC_SP_MAC(eaddr[2]);
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ON);
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
sframe->dc_status = htole32(DC_TXSTAT_OWN);
+ bus_dmamap_sync(sc->dc_stag, sc->dc_smap, BUS_DMASYNC_PREWRITE);
CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF);
/*
* Wait some time...
*/
DELAY(1000);
sc->dc_wdog_timer = 5;
}
static void
dc_setfilt(struct dc_softc *sc)
{
if (DC_IS_INTEL(sc) || DC_IS_MACRONIX(sc) || DC_IS_PNIC(sc) ||
DC_IS_PNICII(sc) || DC_IS_DAVICOM(sc) || DC_IS_CONEXANT(sc))
dc_setfilt_21143(sc);
if (DC_IS_ASIX(sc))
dc_setfilt_asix(sc);
if (DC_IS_ADMTEK(sc))
dc_setfilt_admtek(sc);
if (DC_IS_XIRCOM(sc))
dc_setfilt_xircom(sc);
}
/*
* In order to fiddle with the 'full-duplex' and '100Mbps' bits in
* the netconfig register, we first have to put the transmit and/or
* receive logic in the idle state.
*/
static void
dc_setcfg(struct dc_softc *sc, int media)
{
int i, restart = 0, watchdogreg;
- u_int32_t isr;
+ uint32_t isr;
if (IFM_SUBTYPE(media) == IFM_NONE)
return;
if (CSR_READ_4(sc, DC_NETCFG) & (DC_NETCFG_TX_ON | DC_NETCFG_RX_ON)) {
restart = 1;
DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_TX_ON | DC_NETCFG_RX_ON));
for (i = 0; i < DC_TIMEOUT; i++) {
isr = CSR_READ_4(sc, DC_ISR);
if (isr & DC_ISR_TX_IDLE &&
((isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED ||
(isr & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT))
break;
DELAY(10);
}
if (i == DC_TIMEOUT) {
if (!(isr & DC_ISR_TX_IDLE) && !DC_IS_ASIX(sc))
device_printf(sc->dc_dev,
"%s: failed to force tx to idle state\n",
__func__);
if (!((isr & DC_ISR_RX_STATE) == DC_RXSTATE_STOPPED ||
(isr & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT) &&
!DC_HAS_BROKEN_RXSTATE(sc))
device_printf(sc->dc_dev,
"%s: failed to force rx to idle state\n",
__func__);
}
}
if (IFM_SUBTYPE(media) == IFM_100_TX) {
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_SPEEDSEL);
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_HEARTBEAT);
if (sc->dc_pmode == DC_PMODE_MII) {
if (DC_IS_INTEL(sc)) {
/* There's a write enable bit here that reads as 1. */
watchdogreg = CSR_READ_4(sc, DC_WATCHDOG);
watchdogreg &= ~DC_WDOG_CTLWREN;
watchdogreg |= DC_WDOG_JABBERDIS;
CSR_WRITE_4(sc, DC_WATCHDOG, watchdogreg);
} else {
DC_SETBIT(sc, DC_WATCHDOG, DC_WDOG_JABBERDIS);
}
DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_PCS |
DC_NETCFG_PORTSEL | DC_NETCFG_SCRAMBLER));
if (sc->dc_type == DC_TYPE_98713)
DC_SETBIT(sc, DC_NETCFG, (DC_NETCFG_PCS |
DC_NETCFG_SCRAMBLER));
if (!DC_IS_DAVICOM(sc))
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
DC_CLRBIT(sc, DC_10BTCTRL, 0xFFFF);
} else {
if (DC_IS_PNIC(sc)) {
DC_PN_GPIO_SETBIT(sc, DC_PN_GPIO_SPEEDSEL);
DC_PN_GPIO_SETBIT(sc, DC_PN_GPIO_100TX_LOOP);
DC_SETBIT(sc, DC_PN_NWAY, DC_PN_NWAY_SPEEDSEL);
}
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PCS);
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_SCRAMBLER);
}
}
if (IFM_SUBTYPE(media) == IFM_10_T) {
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_SPEEDSEL);
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_HEARTBEAT);
if (sc->dc_pmode == DC_PMODE_MII) {
/* There's a write enable bit here that reads as 1. */
if (DC_IS_INTEL(sc)) {
watchdogreg = CSR_READ_4(sc, DC_WATCHDOG);
watchdogreg &= ~DC_WDOG_CTLWREN;
watchdogreg |= DC_WDOG_JABBERDIS;
CSR_WRITE_4(sc, DC_WATCHDOG, watchdogreg);
} else {
DC_SETBIT(sc, DC_WATCHDOG, DC_WDOG_JABBERDIS);
}
DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_PCS |
DC_NETCFG_PORTSEL | DC_NETCFG_SCRAMBLER));
if (sc->dc_type == DC_TYPE_98713)
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PCS);
if (!DC_IS_DAVICOM(sc))
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
DC_CLRBIT(sc, DC_10BTCTRL, 0xFFFF);
} else {
if (DC_IS_PNIC(sc)) {
DC_PN_GPIO_CLRBIT(sc, DC_PN_GPIO_SPEEDSEL);
DC_PN_GPIO_SETBIT(sc, DC_PN_GPIO_100TX_LOOP);
DC_CLRBIT(sc, DC_PN_NWAY, DC_PN_NWAY_SPEEDSEL);
}
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PCS);
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_SCRAMBLER);
if (DC_IS_INTEL(sc)) {
DC_CLRBIT(sc, DC_SIARESET, DC_SIA_RESET);
DC_CLRBIT(sc, DC_10BTCTRL, 0xFFFF);
if ((media & IFM_GMASK) == IFM_FDX)
DC_SETBIT(sc, DC_10BTCTRL, 0x7F3D);
else
DC_SETBIT(sc, DC_10BTCTRL, 0x7F3F);
DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET);
DC_CLRBIT(sc, DC_10BTCTRL,
DC_TCTL_AUTONEGENBL);
DELAY(20000);
}
}
}
/*
* If this is a Davicom DM9102A card with a DM9801 HomePNA
* PHY and we want HomePNA mode, set the portsel bit to turn
* on the external MII port.
*/
if (DC_IS_DAVICOM(sc)) {
if (IFM_SUBTYPE(media) == IFM_HPNA_1) {
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
sc->dc_link = 1;
} else {
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
}
}
if ((media & IFM_GMASK) == IFM_FDX) {
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_FULLDUPLEX);
if (sc->dc_pmode == DC_PMODE_SYM && DC_IS_PNIC(sc))
DC_SETBIT(sc, DC_PN_NWAY, DC_PN_NWAY_DUPLEX);
} else {
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_FULLDUPLEX);
if (sc->dc_pmode == DC_PMODE_SYM && DC_IS_PNIC(sc))
DC_CLRBIT(sc, DC_PN_NWAY, DC_PN_NWAY_DUPLEX);
}
if (restart)
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON | DC_NETCFG_RX_ON);
}
static void
dc_reset(struct dc_softc *sc)
{
int i;
DC_SETBIT(sc, DC_BUSCTL, DC_BUSCTL_RESET);
for (i = 0; i < DC_TIMEOUT; i++) {
DELAY(10);
if (!(CSR_READ_4(sc, DC_BUSCTL) & DC_BUSCTL_RESET))
break;
}
if (DC_IS_ASIX(sc) || DC_IS_ADMTEK(sc) || DC_IS_CONEXANT(sc) ||
DC_IS_XIRCOM(sc) || DC_IS_INTEL(sc)) {
DELAY(10000);
DC_CLRBIT(sc, DC_BUSCTL, DC_BUSCTL_RESET);
i = 0;
}
if (i == DC_TIMEOUT)
device_printf(sc->dc_dev, "reset never completed!\n");
/* Wait a little while for the chip to get its brains in order. */
DELAY(1000);
CSR_WRITE_4(sc, DC_IMR, 0x00000000);
CSR_WRITE_4(sc, DC_BUSCTL, 0x00000000);
CSR_WRITE_4(sc, DC_NETCFG, 0x00000000);
/*
* Bring the SIA out of reset. In some cases, it looks
* like failing to unreset the SIA soon enough gets it
* into a state where it will never come out of reset
* until we reset the whole chip again.
*/
if (DC_IS_INTEL(sc)) {
DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET);
CSR_WRITE_4(sc, DC_10BTCTRL, 0xFFFFFFFF);
CSR_WRITE_4(sc, DC_WATCHDOG, 0);
}
}
static const struct dc_type *
dc_devtype(device_t dev)
{
const struct dc_type *t;
- u_int32_t devid;
- u_int8_t rev;
+ uint32_t devid;
+ uint8_t rev;
t = dc_devs;
devid = pci_get_devid(dev);
rev = pci_get_revid(dev);
while (t->dc_name != NULL) {
if (devid == t->dc_devid && rev >= t->dc_minrev)
return (t);
t++;
}
return (NULL);
}
/*
* Probe for a 21143 or clone chip. Check the PCI vendor and device
* IDs against our list and return a device name if we find a match.
* We do a little bit of extra work to identify the exact type of
* chip. The MX98713 and MX98713A have the same PCI vendor/device ID,
* but different revision IDs. The same is true for 98715/98715A
* chips and the 98725, as well as the ASIX and ADMtek chips. In some
* cases, the exact chip revision affects driver behavior.
*/
static int
dc_probe(device_t dev)
{
const struct dc_type *t;
t = dc_devtype(dev);
if (t != NULL) {
device_set_desc(dev, t->dc_name);
return (BUS_PROBE_DEFAULT);
}
return (ENXIO);
}
static void
dc_apply_fixup(struct dc_softc *sc, int media)
{
struct dc_mediainfo *m;
- u_int8_t *p;
+ uint8_t *p;
int i;
- u_int32_t reg;
+ uint32_t reg;
m = sc->dc_mi;
while (m != NULL) {
if (m->dc_media == media)
break;
m = m->dc_next;
}
if (m == NULL)
return;
for (i = 0, p = m->dc_reset_ptr; i < m->dc_reset_len; i++, p += 2) {
reg = (p[0] | (p[1] << 8)) << 16;
CSR_WRITE_4(sc, DC_WATCHDOG, reg);
}
for (i = 0, p = m->dc_gp_ptr; i < m->dc_gp_len; i++, p += 2) {
reg = (p[0] | (p[1] << 8)) << 16;
CSR_WRITE_4(sc, DC_WATCHDOG, reg);
}
}
static int
dc_decode_leaf_sia(struct dc_softc *sc, struct dc_eblock_sia *l)
{
struct dc_mediainfo *m;
m = malloc(sizeof(struct dc_mediainfo), M_DEVBUF, M_NOWAIT | M_ZERO);
if (m == NULL) {
device_printf(sc->dc_dev, "Could not allocate mediainfo\n");
return (ENOMEM);
}
switch (l->dc_sia_code & ~DC_SIA_CODE_EXT) {
case DC_SIA_CODE_10BT:
m->dc_media = IFM_10_T;
break;
case DC_SIA_CODE_10BT_FDX:
m->dc_media = IFM_10_T | IFM_FDX;
break;
case DC_SIA_CODE_10B2:
m->dc_media = IFM_10_2;
break;
case DC_SIA_CODE_10B5:
m->dc_media = IFM_10_5;
break;
default:
break;
}
/*
* We need to ignore CSR13, CSR14, CSR15 for SIA mode.
* Things apparently already work for cards that do
* supply Media Specific Data.
*/
if (l->dc_sia_code & DC_SIA_CODE_EXT) {
m->dc_gp_len = 2;
m->dc_gp_ptr =
- (u_int8_t *)&l->dc_un.dc_sia_ext.dc_sia_gpio_ctl;
+ (uint8_t *)&l->dc_un.dc_sia_ext.dc_sia_gpio_ctl;
} else {
m->dc_gp_len = 2;
m->dc_gp_ptr =
- (u_int8_t *)&l->dc_un.dc_sia_noext.dc_sia_gpio_ctl;
+ (uint8_t *)&l->dc_un.dc_sia_noext.dc_sia_gpio_ctl;
}
m->dc_next = sc->dc_mi;
sc->dc_mi = m;
sc->dc_pmode = DC_PMODE_SIA;
return (0);
}
static int
dc_decode_leaf_sym(struct dc_softc *sc, struct dc_eblock_sym *l)
{
struct dc_mediainfo *m;
m = malloc(sizeof(struct dc_mediainfo), M_DEVBUF, M_NOWAIT | M_ZERO);
if (m == NULL) {
device_printf(sc->dc_dev, "Could not allocate mediainfo\n");
return (ENOMEM);
}
if (l->dc_sym_code == DC_SYM_CODE_100BT)
m->dc_media = IFM_100_TX;
if (l->dc_sym_code == DC_SYM_CODE_100BT_FDX)
m->dc_media = IFM_100_TX | IFM_FDX;
m->dc_gp_len = 2;
- m->dc_gp_ptr = (u_int8_t *)&l->dc_sym_gpio_ctl;
+ m->dc_gp_ptr = (uint8_t *)&l->dc_sym_gpio_ctl;
m->dc_next = sc->dc_mi;
sc->dc_mi = m;
sc->dc_pmode = DC_PMODE_SYM;
return (0);
}
static int
dc_decode_leaf_mii(struct dc_softc *sc, struct dc_eblock_mii *l)
{
struct dc_mediainfo *m;
- u_int8_t *p;
+ uint8_t *p;
m = malloc(sizeof(struct dc_mediainfo), M_DEVBUF, M_NOWAIT | M_ZERO);
if (m == NULL) {
device_printf(sc->dc_dev, "Could not allocate mediainfo\n");
return (ENOMEM);
}
/* We abuse IFM_AUTO to represent MII. */
m->dc_media = IFM_AUTO;
m->dc_gp_len = l->dc_gpr_len;
- p = (u_int8_t *)l;
+ p = (uint8_t *)l;
p += sizeof(struct dc_eblock_mii);
m->dc_gp_ptr = p;
p += 2 * l->dc_gpr_len;
m->dc_reset_len = *p;
p++;
m->dc_reset_ptr = p;
m->dc_next = sc->dc_mi;
sc->dc_mi = m;
return (0);
}
static int
dc_read_srom(struct dc_softc *sc, int bits)
{
int size;
size = DC_ROM_SIZE(bits);
sc->dc_srom = malloc(size, M_DEVBUF, M_NOWAIT);
if (sc->dc_srom == NULL) {
device_printf(sc->dc_dev, "Could not allocate SROM buffer\n");
return (ENOMEM);
}
dc_read_eeprom(sc, (caddr_t)sc->dc_srom, 0, (size / 2), 0);
return (0);
}
static int
dc_parse_21143_srom(struct dc_softc *sc)
{
struct dc_leaf_hdr *lhdr;
struct dc_eblock_hdr *hdr;
int error, have_mii, i, loff;
char *ptr;
have_mii = 0;
loff = sc->dc_srom[27];
lhdr = (struct dc_leaf_hdr *)&(sc->dc_srom[loff]);
ptr = (char *)lhdr;
ptr += sizeof(struct dc_leaf_hdr) - 1;
/*
* Look if we got a MII media block.
*/
for (i = 0; i < lhdr->dc_mcnt; i++) {
hdr = (struct dc_eblock_hdr *)ptr;
if (hdr->dc_type == DC_EBLOCK_MII)
have_mii++;
ptr += (hdr->dc_len & 0x7F);
ptr++;
}
/*
* Do the same thing again. Only use SIA and SYM media
* blocks if no MII media block is available.
*/
ptr = (char *)lhdr;
ptr += sizeof(struct dc_leaf_hdr) - 1;
error = 0;
for (i = 0; i < lhdr->dc_mcnt; i++) {
hdr = (struct dc_eblock_hdr *)ptr;
switch (hdr->dc_type) {
case DC_EBLOCK_MII:
error = dc_decode_leaf_mii(sc, (struct dc_eblock_mii *)hdr);
break;
case DC_EBLOCK_SIA:
if (! have_mii)
error = dc_decode_leaf_sia(sc,
(struct dc_eblock_sia *)hdr);
break;
case DC_EBLOCK_SYM:
if (! have_mii)
error = dc_decode_leaf_sym(sc,
(struct dc_eblock_sym *)hdr);
break;
default:
/* Don't care. Yet. */
break;
}
ptr += (hdr->dc_len & 0x7F);
ptr++;
}
return (error);
}
static void
dc_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
- u_int32_t *paddr;
+ bus_addr_t *paddr;
KASSERT(nseg == 1,
("%s: wrong number of segments (%d)", __func__, nseg));
paddr = arg;
*paddr = segs->ds_addr;
}
+static int
+dc_dma_alloc(struct dc_softc *sc)
+{
+ int error, i;
+
+ error = bus_dma_tag_create(bus_get_dma_tag(sc->dc_dev), 1, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT, 0,
+ NULL, NULL, &sc->dc_ptag);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "failed to allocate parent DMA tag\n");
+ goto fail;
+ }
+
+ /* Allocate a busdma tag and DMA safe memory for TX/RX descriptors. */
+ error = bus_dma_tag_create(sc->dc_ptag, DC_LIST_ALIGN, 0,
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, DC_RX_LIST_SZ, 1,
+ DC_RX_LIST_SZ, 0, NULL, NULL, &sc->dc_rx_ltag);
+ if (error) {
+ device_printf(sc->dc_dev, "failed to create RX list DMA tag\n");
+ goto fail;
+ }
+
+ error = bus_dma_tag_create(sc->dc_ptag, DC_LIST_ALIGN, 0,
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, DC_TX_LIST_SZ, 1,
+ DC_TX_LIST_SZ, 0, NULL, NULL, &sc->dc_tx_ltag);
+ if (error) {
+ device_printf(sc->dc_dev, "failed to create TX list DMA tag\n");
+ goto fail;
+ }
+
+ /* RX descriptor list. */
+ error = bus_dmamem_alloc(sc->dc_rx_ltag,
+ (void **)&sc->dc_ldata.dc_rx_list, BUS_DMA_NOWAIT |
+ BUS_DMA_ZERO | BUS_DMA_COHERENT, &sc->dc_rx_lmap);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "failed to allocate DMA'able memory for RX list\n");
+ goto fail;
+ }
+ error = bus_dmamap_load(sc->dc_rx_ltag, sc->dc_rx_lmap,
+ sc->dc_ldata.dc_rx_list, DC_RX_LIST_SZ, dc_dma_map_addr,
+ &sc->dc_ldata.dc_rx_list_paddr, BUS_DMA_NOWAIT);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "failed to load DMA'able memory for RX list\n");
+ goto fail;
+ }
+ /* TX descriptor list. */
+ error = bus_dmamem_alloc(sc->dc_tx_ltag,
+ (void **)&sc->dc_ldata.dc_tx_list, BUS_DMA_NOWAIT |
+ BUS_DMA_ZERO | BUS_DMA_COHERENT, &sc->dc_tx_lmap);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "failed to allocate DMA'able memory for TX list\n");
+ goto fail;
+ }
+ error = bus_dmamap_load(sc->dc_tx_ltag, sc->dc_tx_lmap,
+ sc->dc_ldata.dc_tx_list, DC_TX_LIST_SZ, dc_dma_map_addr,
+ &sc->dc_ldata.dc_tx_list_paddr, BUS_DMA_NOWAIT);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "cannot load DMA'able memory for TX list\n");
+ goto fail;
+ }
+
+ /*
+ * Allocate a busdma tag and DMA safe memory for the multicast
+ * setup frame.
+ */
+ error = bus_dma_tag_create(sc->dc_ptag, DC_LIST_ALIGN, 0,
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+ DC_SFRAME_LEN + DC_MIN_FRAMELEN, 1, DC_SFRAME_LEN + DC_MIN_FRAMELEN,
+ 0, NULL, NULL, &sc->dc_stag);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "failed to create DMA tag for setup frame\n");
+ goto fail;
+ }
+ error = bus_dmamem_alloc(sc->dc_stag, (void **)&sc->dc_cdata.dc_sbuf,
+ BUS_DMA_NOWAIT, &sc->dc_smap);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "failed to allocate DMA'able memory for setup frame\n");
+ goto fail;
+ }
+ error = bus_dmamap_load(sc->dc_stag, sc->dc_smap, sc->dc_cdata.dc_sbuf,
+ DC_SFRAME_LEN, dc_dma_map_addr, &sc->dc_saddr, BUS_DMA_NOWAIT);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "cannot load DMA'able memory for setup frame\n");
+ goto fail;
+ }
+
+ /* Allocate a busdma tag for RX mbufs. */
+ error = bus_dma_tag_create(sc->dc_ptag, DC_RXBUF_ALIGN, 0,
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+ MCLBYTES, 1, MCLBYTES, 0, NULL, NULL, &sc->dc_rx_mtag);
+ if (error) {
+ device_printf(sc->dc_dev, "failed to create RX mbuf tag\n");
+ goto fail;
+ }
+
+ /* Allocate a busdma tag for TX mbufs. */
+ error = bus_dma_tag_create(sc->dc_ptag, 1, 0,
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+ MCLBYTES * DC_MAXFRAGS, DC_MAXFRAGS, MCLBYTES,
+ 0, NULL, NULL, &sc->dc_tx_mtag);
+ if (error) {
+ device_printf(sc->dc_dev, "failed to create TX mbuf tag\n");
+ goto fail;
+ }
+
+ /* Create the TX/RX busdma maps. */
+ for (i = 0; i < DC_TX_LIST_CNT; i++) {
+ error = bus_dmamap_create(sc->dc_tx_mtag, 0,
+ &sc->dc_cdata.dc_tx_map[i]);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "failed to create TX mbuf dmamap\n");
+ goto fail;
+ }
+ }
+ for (i = 0; i < DC_RX_LIST_CNT; i++) {
+ error = bus_dmamap_create(sc->dc_rx_mtag, 0,
+ &sc->dc_cdata.dc_rx_map[i]);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "failed to create RX mbuf dmamap\n");
+ goto fail;
+ }
+ }
+ error = bus_dmamap_create(sc->dc_rx_mtag, 0, &sc->dc_sparemap);
+ if (error) {
+ device_printf(sc->dc_dev,
+ "failed to create spare RX mbuf dmamap\n");
+ goto fail;
+ }
+
+fail:
+ return (error);
+}
+
+static void
+dc_dma_free(struct dc_softc *sc)
+{
+ int i;
+
+ /* RX buffers. */
+ if (sc->dc_rx_mtag != NULL) {
+ for (i = 0; i < DC_RX_LIST_CNT; i++) {
+ if (sc->dc_cdata.dc_rx_map[i] != NULL)
+ bus_dmamap_destroy(sc->dc_rx_mtag,
+ sc->dc_cdata.dc_rx_map[i]);
+ }
+ if (sc->dc_sparemap != NULL)
+ bus_dmamap_destroy(sc->dc_rx_mtag, sc->dc_sparemap);
+ bus_dma_tag_destroy(sc->dc_rx_mtag);
+ }
+
+ /* TX buffers. */
+ if (sc->dc_rx_mtag != NULL) {
+ for (i = 0; i < DC_TX_LIST_CNT; i++) {
+ if (sc->dc_cdata.dc_tx_map[i] != NULL)
+ bus_dmamap_destroy(sc->dc_tx_mtag,
+ sc->dc_cdata.dc_tx_map[i]);
+ }
+ bus_dma_tag_destroy(sc->dc_tx_mtag);
+ }
+
+ /* RX descriptor list. */
+ if (sc->dc_rx_ltag) {
+ if (sc->dc_rx_lmap != NULL)
+ bus_dmamap_unload(sc->dc_rx_ltag, sc->dc_rx_lmap);
+ if (sc->dc_rx_lmap != NULL && sc->dc_ldata.dc_rx_list != NULL)
+ bus_dmamem_free(sc->dc_rx_ltag, sc->dc_ldata.dc_rx_list,
+ sc->dc_rx_lmap);
+ bus_dma_tag_destroy(sc->dc_rx_ltag);
+ }
+
+ /* TX descriptor list. */
+ if (sc->dc_tx_ltag) {
+ if (sc->dc_tx_lmap != NULL)
+ bus_dmamap_unload(sc->dc_tx_ltag, sc->dc_tx_lmap);
+ if (sc->dc_tx_lmap != NULL && sc->dc_ldata.dc_tx_list != NULL)
+ bus_dmamem_free(sc->dc_tx_ltag, sc->dc_ldata.dc_tx_list,
+ sc->dc_tx_lmap);
+ bus_dma_tag_destroy(sc->dc_tx_ltag);
+ }
+
+ /* multicast setup frame. */
+ if (sc->dc_stag) {
+ if (sc->dc_smap != NULL)
+ bus_dmamap_unload(sc->dc_stag, sc->dc_smap);
+ if (sc->dc_smap != NULL && sc->dc_cdata.dc_sbuf != NULL)
+ bus_dmamem_free(sc->dc_stag, sc->dc_cdata.dc_sbuf,
+ sc->dc_smap);
+ bus_dma_tag_destroy(sc->dc_stag);
+ }
+}
+
/*
* Attach the interface. Allocate softc structures, do ifmedia
* setup and ethernet/BPF attach.
*/
static int
dc_attach(device_t dev)
{
uint32_t eaddr[(ETHER_ADDR_LEN+3)/4];
- u_int32_t command;
+ uint32_t command;
struct dc_softc *sc;
struct ifnet *ifp;
struct dc_mediainfo *m;
- u_int32_t reg, revision;
- int error, i, mac_offset, phy, rid, tmp;
- u_int8_t *mac;
+ uint32_t reg, revision;
+ int error, mac_offset, phy, rid, tmp;
+ uint8_t *mac;
sc = device_get_softc(dev);
sc->dc_dev = dev;
mtx_init(&sc->dc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF);
/*
* Map control/status registers.
*/
pci_enable_busmaster(dev);
rid = DC_RID;
sc->dc_res = bus_alloc_resource_any(dev, DC_RES, &rid, RF_ACTIVE);
if (sc->dc_res == NULL) {
device_printf(dev, "couldn't map ports/memory\n");
error = ENXIO;
goto fail;
}
sc->dc_btag = rman_get_bustag(sc->dc_res);
sc->dc_bhandle = rman_get_bushandle(sc->dc_res);
/* Allocate interrupt. */
rid = 0;
sc->dc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_SHAREABLE | RF_ACTIVE);
if (sc->dc_irq == NULL) {
device_printf(dev, "couldn't map interrupt\n");
error = ENXIO;
goto fail;
}
/* Need this info to decide on a chip type. */
sc->dc_info = dc_devtype(dev);
revision = pci_get_revid(dev);
error = 0;
/* Get the eeprom width, but PNIC and XIRCOM have diff eeprom */
if (sc->dc_info->dc_devid !=
DC_DEVID(DC_VENDORID_LO, DC_DEVICEID_82C168) &&
sc->dc_info->dc_devid !=
DC_DEVID(DC_VENDORID_XIRCOM, DC_DEVICEID_X3201))
dc_eeprom_width(sc);
switch (sc->dc_info->dc_devid) {
case DC_DEVID(DC_VENDORID_DEC, DC_DEVICEID_21143):
sc->dc_type = DC_TYPE_21143;
sc->dc_flags |= DC_TX_POLL | DC_TX_USE_TX_INTR;
sc->dc_flags |= DC_REDUCED_MII_POLL;
/* Save EEPROM contents so we can parse them later. */
error = dc_read_srom(sc, sc->dc_romwidth);
if (error != 0)
goto fail;
break;
case DC_DEVID(DC_VENDORID_DAVICOM, DC_DEVICEID_DM9009):
case DC_DEVID(DC_VENDORID_DAVICOM, DC_DEVICEID_DM9100):
case DC_DEVID(DC_VENDORID_DAVICOM, DC_DEVICEID_DM9102):
sc->dc_type = DC_TYPE_DM9102;
sc->dc_flags |= DC_TX_COALESCE | DC_TX_INTR_ALWAYS;
sc->dc_flags |= DC_REDUCED_MII_POLL | DC_TX_STORENFWD;
sc->dc_flags |= DC_TX_ALIGN;
sc->dc_pmode = DC_PMODE_MII;
/* Increase the latency timer value. */
pci_write_config(dev, PCIR_LATTIMER, 0x80, 1);
break;
case DC_DEVID(DC_VENDORID_ADMTEK, DC_DEVICEID_AL981):
sc->dc_type = DC_TYPE_AL981;
sc->dc_flags |= DC_TX_USE_TX_INTR;
sc->dc_flags |= DC_TX_ADMTEK_WAR;
sc->dc_pmode = DC_PMODE_MII;
error = dc_read_srom(sc, sc->dc_romwidth);
if (error != 0)
goto fail;
break;
case DC_DEVID(DC_VENDORID_ADMTEK, DC_DEVICEID_AN983):
case DC_DEVID(DC_VENDORID_ADMTEK, DC_DEVICEID_AN985):
case DC_DEVID(DC_VENDORID_ADMTEK, DC_DEVICEID_ADM9511):
case DC_DEVID(DC_VENDORID_ADMTEK, DC_DEVICEID_ADM9513):
case DC_DEVID(DC_VENDORID_DLINK, DC_DEVICEID_DRP32TXD):
case DC_DEVID(DC_VENDORID_ABOCOM, DC_DEVICEID_FE2500):
case DC_DEVID(DC_VENDORID_ABOCOM, DC_DEVICEID_FE2500MX):
case DC_DEVID(DC_VENDORID_ACCTON, DC_DEVICEID_EN2242):
case DC_DEVID(DC_VENDORID_HAWKING, DC_DEVICEID_HAWKING_PN672TX):
case DC_DEVID(DC_VENDORID_PLANEX, DC_DEVICEID_FNW3602T):
case DC_DEVID(DC_VENDORID_3COM, DC_DEVICEID_3CSOHOB):
case DC_DEVID(DC_VENDORID_MICROSOFT, DC_DEVICEID_MSMN120):
case DC_DEVID(DC_VENDORID_MICROSOFT, DC_DEVICEID_MSMN130):
case DC_DEVID(DC_VENDORID_LINKSYS, DC_DEVICEID_PCMPC200_AB08):
case DC_DEVID(DC_VENDORID_LINKSYS, DC_DEVICEID_PCMPC200_AB09):
sc->dc_type = DC_TYPE_AN983;
sc->dc_flags |= DC_64BIT_HASH;
sc->dc_flags |= DC_TX_USE_TX_INTR;
sc->dc_flags |= DC_TX_ADMTEK_WAR;
sc->dc_pmode = DC_PMODE_MII;
/* Don't read SROM for - auto-loaded on reset */
break;
case DC_DEVID(DC_VENDORID_MX, DC_DEVICEID_98713):
case DC_DEVID(DC_VENDORID_CP, DC_DEVICEID_98713_CP):
if (revision < DC_REVISION_98713A) {
sc->dc_type = DC_TYPE_98713;
}
if (revision >= DC_REVISION_98713A) {
sc->dc_type = DC_TYPE_98713A;
sc->dc_flags |= DC_21143_NWAY;
}
sc->dc_flags |= DC_REDUCED_MII_POLL;
sc->dc_flags |= DC_TX_POLL | DC_TX_USE_TX_INTR;
break;
case DC_DEVID(DC_VENDORID_MX, DC_DEVICEID_987x5):
case DC_DEVID(DC_VENDORID_ACCTON, DC_DEVICEID_EN1217):
/*
* Macronix MX98715AEC-C/D/E parts have only a
* 128-bit hash table. We need to deal with these
* in the same manner as the PNIC II so that we
* get the right number of bits out of the
* CRC routine.
*/
if (revision >= DC_REVISION_98715AEC_C &&
revision < DC_REVISION_98725)
sc->dc_flags |= DC_128BIT_HASH;
sc->dc_type = DC_TYPE_987x5;
sc->dc_flags |= DC_TX_POLL | DC_TX_USE_TX_INTR;
sc->dc_flags |= DC_REDUCED_MII_POLL | DC_21143_NWAY;
break;
case DC_DEVID(DC_VENDORID_MX, DC_DEVICEID_98727):
sc->dc_type = DC_TYPE_987x5;
sc->dc_flags |= DC_TX_POLL | DC_TX_USE_TX_INTR;
sc->dc_flags |= DC_REDUCED_MII_POLL | DC_21143_NWAY;
break;
case DC_DEVID(DC_VENDORID_LO, DC_DEVICEID_82C115):
sc->dc_type = DC_TYPE_PNICII;
sc->dc_flags |= DC_TX_POLL | DC_TX_USE_TX_INTR | DC_128BIT_HASH;
sc->dc_flags |= DC_REDUCED_MII_POLL | DC_21143_NWAY;
break;
case DC_DEVID(DC_VENDORID_LO, DC_DEVICEID_82C168):
sc->dc_type = DC_TYPE_PNIC;
sc->dc_flags |= DC_TX_STORENFWD | DC_TX_INTR_ALWAYS;
sc->dc_flags |= DC_PNIC_RX_BUG_WAR;
sc->dc_pnic_rx_buf = malloc(DC_RXLEN * 5, M_DEVBUF, M_NOWAIT);
if (sc->dc_pnic_rx_buf == NULL) {
device_printf(sc->dc_dev,
"Could not allocate PNIC RX buffer\n");
error = ENOMEM;
goto fail;
}
if (revision < DC_REVISION_82C169)
sc->dc_pmode = DC_PMODE_SYM;
break;
case DC_DEVID(DC_VENDORID_ASIX, DC_DEVICEID_AX88140A):
sc->dc_type = DC_TYPE_ASIX;
sc->dc_flags |= DC_TX_USE_TX_INTR | DC_TX_INTR_FIRSTFRAG;
sc->dc_flags |= DC_REDUCED_MII_POLL;
sc->dc_pmode = DC_PMODE_MII;
break;
case DC_DEVID(DC_VENDORID_XIRCOM, DC_DEVICEID_X3201):
sc->dc_type = DC_TYPE_XIRCOM;
sc->dc_flags |= DC_TX_INTR_ALWAYS | DC_TX_COALESCE |
DC_TX_ALIGN;
/*
* We don't actually need to coalesce, but we're doing
* it to obtain a double word aligned buffer.
* The DC_TX_COALESCE flag is required.
*/
sc->dc_pmode = DC_PMODE_MII;
break;
case DC_DEVID(DC_VENDORID_CONEXANT, DC_DEVICEID_RS7112):
sc->dc_type = DC_TYPE_CONEXANT;
sc->dc_flags |= DC_TX_INTR_ALWAYS;
sc->dc_flags |= DC_REDUCED_MII_POLL;
sc->dc_pmode = DC_PMODE_MII;
error = dc_read_srom(sc, sc->dc_romwidth);
if (error != 0)
goto fail;
break;
default:
device_printf(dev, "unknown device: %x\n",
sc->dc_info->dc_devid);
break;
}
/* Save the cache line size. */
if (DC_IS_DAVICOM(sc))
sc->dc_cachesize = 0;
else
sc->dc_cachesize = pci_get_cachelnsz(dev);
/* Reset the adapter. */
dc_reset(sc);
/* Take 21143 out of snooze mode */
if (DC_IS_INTEL(sc) || DC_IS_XIRCOM(sc)) {
command = pci_read_config(dev, DC_PCI_CFDD, 4);
command &= ~(DC_CFDD_SNOOZE_MODE | DC_CFDD_SLEEP_MODE);
pci_write_config(dev, DC_PCI_CFDD, command, 4);
}
/*
* Try to learn something about the supported media.
* We know that ASIX and ADMtek and Davicom devices
* will *always* be using MII media, so that's a no-brainer.
* The tricky ones are the Macronix/PNIC II and the
* Intel 21143.
*/
if (DC_IS_INTEL(sc)) {
error = dc_parse_21143_srom(sc);
if (error != 0)
goto fail;
} else if (DC_IS_MACRONIX(sc) || DC_IS_PNICII(sc)) {
if (sc->dc_type == DC_TYPE_98713)
sc->dc_pmode = DC_PMODE_MII;
else
sc->dc_pmode = DC_PMODE_SYM;
} else if (!sc->dc_pmode)
sc->dc_pmode = DC_PMODE_MII;
/*
* Get station address from the EEPROM.
*/
switch(sc->dc_type) {
case DC_TYPE_98713:
case DC_TYPE_98713A:
case DC_TYPE_987x5:
case DC_TYPE_PNICII:
dc_read_eeprom(sc, (caddr_t)&mac_offset,
(DC_EE_NODEADDR_OFFSET / 2), 1, 0);
dc_read_eeprom(sc, (caddr_t)&eaddr, (mac_offset / 2), 3, 0);
break;
case DC_TYPE_PNIC:
dc_read_eeprom(sc, (caddr_t)&eaddr, 0, 3, 1);
break;
case DC_TYPE_DM9102:
dc_read_eeprom(sc, (caddr_t)&eaddr, DC_EE_NODEADDR, 3, 0);
#ifdef __sparc64__
/*
* If this is an onboard dc(4) the station address read from
* the EEPROM is all zero and we have to get it from the FCode.
*/
if (eaddr[0] == 0 && (eaddr[1] & ~0xffff) == 0)
OF_getetheraddr(dev, (caddr_t)&eaddr);
#endif
break;
case DC_TYPE_21143:
case DC_TYPE_ASIX:
dc_read_eeprom(sc, (caddr_t)&eaddr, DC_EE_NODEADDR, 3, 0);
break;
case DC_TYPE_AL981:
case DC_TYPE_AN983:
reg = CSR_READ_4(sc, DC_AL_PAR0);
mac = (uint8_t *)&eaddr[0];
mac[0] = (reg >> 0) & 0xff;
mac[1] = (reg >> 8) & 0xff;
mac[2] = (reg >> 16) & 0xff;
mac[3] = (reg >> 24) & 0xff;
reg = CSR_READ_4(sc, DC_AL_PAR1);
mac[4] = (reg >> 0) & 0xff;
mac[5] = (reg >> 8) & 0xff;
break;
case DC_TYPE_CONEXANT:
bcopy(sc->dc_srom + DC_CONEXANT_EE_NODEADDR, &eaddr,
ETHER_ADDR_LEN);
break;
case DC_TYPE_XIRCOM:
/* The MAC comes from the CIS. */
mac = pci_get_ether(dev);
if (!mac) {
device_printf(dev, "No station address in CIS!\n");
error = ENXIO;
goto fail;
}
bcopy(mac, eaddr, ETHER_ADDR_LEN);
break;
default:
dc_read_eeprom(sc, (caddr_t)&eaddr, DC_EE_NODEADDR, 3, 0);
break;
}
bcopy(eaddr, sc->dc_eaddr, sizeof(eaddr));
/*
* If we still have invalid station address, see whether we can
* find station address for chip 0. Some multi-port controllers
* just store station address for chip 0 if they have a shared
* SROM.
*/
if ((sc->dc_eaddr[0] == 0 && (sc->dc_eaddr[1] & ~0xffff) == 0) ||
(sc->dc_eaddr[0] == 0xffffffff &&
(sc->dc_eaddr[1] & 0xffff) == 0xffff)) {
error = dc_check_multiport(sc);
if (error == 0) {
bcopy(sc->dc_eaddr, eaddr, sizeof(eaddr));
/* Extract media information. */
if (DC_IS_INTEL(sc) && sc->dc_srom != NULL) {
while (sc->dc_mi != NULL) {
m = sc->dc_mi->dc_next;
free(sc->dc_mi, M_DEVBUF);
sc->dc_mi = m;
}
error = dc_parse_21143_srom(sc);
if (error != 0)
goto fail;
}
} else if (error == ENOMEM)
goto fail;
else
error = 0;
}
- /* Allocate a busdma tag and DMA safe memory for TX/RX descriptors. */
- error = bus_dma_tag_create(bus_get_dma_tag(dev), PAGE_SIZE, 0,
- BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
- sizeof(struct dc_list_data), 1, sizeof(struct dc_list_data),
- 0, NULL, NULL, &sc->dc_ltag);
- if (error) {
- device_printf(dev, "failed to allocate busdma tag\n");
- error = ENXIO;
+ if ((error = dc_dma_alloc(sc)) != 0)
goto fail;
- }
- error = bus_dmamem_alloc(sc->dc_ltag, (void **)&sc->dc_ldata,
- BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sc->dc_lmap);
- if (error) {
- device_printf(dev, "failed to allocate DMA safe memory\n");
- error = ENXIO;
- goto fail;
- }
- error = bus_dmamap_load(sc->dc_ltag, sc->dc_lmap, sc->dc_ldata,
- sizeof(struct dc_list_data), dc_dma_map_addr, &sc->dc_laddr,
- BUS_DMA_NOWAIT);
- if (error) {
- device_printf(dev, "cannot get address of the descriptors\n");
- error = ENXIO;
- goto fail;
- }
- /*
- * Allocate a busdma tag and DMA safe memory for the multicast
- * setup frame.
- */
- error = bus_dma_tag_create(bus_get_dma_tag(dev), PAGE_SIZE, 0,
- BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
- DC_SFRAME_LEN + DC_MIN_FRAMELEN, 1, DC_SFRAME_LEN + DC_MIN_FRAMELEN,
- 0, NULL, NULL, &sc->dc_stag);
- if (error) {
- device_printf(dev, "failed to allocate busdma tag\n");
- error = ENXIO;
- goto fail;
- }
- error = bus_dmamem_alloc(sc->dc_stag, (void **)&sc->dc_cdata.dc_sbuf,
- BUS_DMA_NOWAIT, &sc->dc_smap);
- if (error) {
- device_printf(dev, "failed to allocate DMA safe memory\n");
- error = ENXIO;
- goto fail;
- }
- error = bus_dmamap_load(sc->dc_stag, sc->dc_smap, sc->dc_cdata.dc_sbuf,
- DC_SFRAME_LEN, dc_dma_map_addr, &sc->dc_saddr, BUS_DMA_NOWAIT);
- if (error) {
- device_printf(dev, "cannot get address of the descriptors\n");
- error = ENXIO;
- goto fail;
- }
-
- /* Allocate a busdma tag for mbufs. */
- error = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
- BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
- MCLBYTES * DC_MAXFRAGS, DC_MAXFRAGS, MCLBYTES,
- 0, NULL, NULL, &sc->dc_mtag);
- if (error) {
- device_printf(dev, "failed to allocate busdma tag\n");
- error = ENXIO;
- goto fail;
- }
-
- /* Create the TX/RX busdma maps. */
- for (i = 0; i < DC_TX_LIST_CNT; i++) {
- error = bus_dmamap_create(sc->dc_mtag, 0,
- &sc->dc_cdata.dc_tx_map[i]);
- if (error) {
- device_printf(dev, "failed to init TX ring\n");
- error = ENXIO;
- goto fail;
- }
- }
- for (i = 0; i < DC_RX_LIST_CNT; i++) {
- error = bus_dmamap_create(sc->dc_mtag, 0,
- &sc->dc_cdata.dc_rx_map[i]);
- if (error) {
- device_printf(dev, "failed to init RX ring\n");
- error = ENXIO;
- goto fail;
- }
- }
- error = bus_dmamap_create(sc->dc_mtag, 0, &sc->dc_sparemap);
- if (error) {
- device_printf(dev, "failed to init RX ring\n");
- error = ENXIO;
- goto fail;
- }
-
ifp = sc->dc_ifp = if_alloc(IFT_ETHER);
if (ifp == NULL) {
device_printf(dev, "can not if_alloc()\n");
error = ENOSPC;
goto fail;
}
ifp->if_softc = sc;
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_ioctl = dc_ioctl;
ifp->if_start = dc_start;
ifp->if_init = dc_init;
IFQ_SET_MAXLEN(&ifp->if_snd, DC_TX_LIST_CNT - 1);
ifp->if_snd.ifq_drv_maxlen = DC_TX_LIST_CNT - 1;
IFQ_SET_READY(&ifp->if_snd);
/*
* Do MII setup. If this is a 21143, check for a PHY on the
* MII bus after applying any necessary fixups to twiddle the
* GPIO bits. If we don't end up finding a PHY, restore the
* old selection (SIA only or SIA/SYM) and attach the dcphy
* driver instead.
*/
tmp = 0;
if (DC_IS_INTEL(sc)) {
dc_apply_fixup(sc, IFM_AUTO);
tmp = sc->dc_pmode;
sc->dc_pmode = DC_PMODE_MII;
}
/*
* Setup General Purpose port mode and data so the tulip can talk
* to the MII. This needs to be done before mii_attach so that
* we can actually see them.
*/
if (DC_IS_XIRCOM(sc)) {
CSR_WRITE_4(sc, DC_SIAGP, DC_SIAGP_WRITE_EN | DC_SIAGP_INT1_EN |
DC_SIAGP_MD_GP2_OUTPUT | DC_SIAGP_MD_GP0_OUTPUT);
DELAY(10);
CSR_WRITE_4(sc, DC_SIAGP, DC_SIAGP_INT1_EN |
DC_SIAGP_MD_GP2_OUTPUT | DC_SIAGP_MD_GP0_OUTPUT);
DELAY(10);
}
phy = MII_PHY_ANY;
/*
* Note: both the AL981 and AN983 have internal PHYs, however the
* AL981 provides direct access to the PHY registers while the AN983
* uses a serial MII interface. The AN983's MII interface is also
* buggy in that you can read from any MII address (0 to 31), but
* only address 1 behaves normally. To deal with both cases, we
* pretend that the PHY is at MII address 1.
*/
if (DC_IS_ADMTEK(sc))
phy = DC_ADMTEK_PHYADDR;
/*
* Note: the ukphy probes of the RS7112 report a PHY at MII address
* 0 (possibly HomePNA?) and 1 (ethernet) so we only respond to the
* correct one.
*/
if (DC_IS_CONEXANT(sc))
phy = DC_CONEXANT_PHYADDR;
error = mii_attach(dev, &sc->dc_miibus, ifp, dc_ifmedia_upd,
dc_ifmedia_sts, BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0);
if (error && DC_IS_INTEL(sc)) {
sc->dc_pmode = tmp;
if (sc->dc_pmode != DC_PMODE_SIA)
sc->dc_pmode = DC_PMODE_SYM;
sc->dc_flags |= DC_21143_NWAY;
mii_attach(dev, &sc->dc_miibus, ifp, dc_ifmedia_upd,
dc_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY,
MII_OFFSET_ANY, 0);
/*
* For non-MII cards, we need to have the 21143
* drive the LEDs. Except there are some systems
* like the NEC VersaPro NoteBook PC which have no
* LEDs, and twiddling these bits has adverse effects
* on them. (I.e. you suddenly can't get a link.)
*/
if (!(pci_get_subvendor(dev) == 0x1033 &&
pci_get_subdevice(dev) == 0x8028))
sc->dc_flags |= DC_TULIP_LEDS;
error = 0;
}
if (error) {
device_printf(dev, "attaching PHYs failed\n");
goto fail;
}
if (DC_IS_ADMTEK(sc)) {
/*
* Set automatic TX underrun recovery for the ADMtek chips
*/
DC_SETBIT(sc, DC_AL_CR, DC_AL_CR_ATUR);
}
/*
* Tell the upper layer(s) we support long frames.
*/
ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
ifp->if_capabilities |= IFCAP_VLAN_MTU;
ifp->if_capenable = ifp->if_capabilities;
#ifdef DEVICE_POLLING
ifp->if_capabilities |= IFCAP_POLLING;
#endif
callout_init_mtx(&sc->dc_stat_ch, &sc->dc_mtx, 0);
callout_init_mtx(&sc->dc_wdog_ch, &sc->dc_mtx, 0);
/*
* Call MI attach routine.
*/
ether_ifattach(ifp, (caddr_t)eaddr);
/* Hook interrupt last to avoid having to lock softc */
error = bus_setup_intr(dev, sc->dc_irq, INTR_TYPE_NET | INTR_MPSAFE,
NULL, dc_intr, sc, &sc->dc_intrhand);
if (error) {
device_printf(dev, "couldn't set up irq\n");
ether_ifdetach(ifp);
goto fail;
}
fail:
if (error)
dc_detach(dev);
return (error);
}
/*
* Shutdown hardware and free up resources. This can be called any
* time after the mutex has been initialized. It is called in both
* the error case in attach and the normal detach case so it needs
* to be careful about only freeing resources that have actually been
* allocated.
*/
static int
dc_detach(device_t dev)
{
struct dc_softc *sc;
struct ifnet *ifp;
struct dc_mediainfo *m;
- int i;
sc = device_get_softc(dev);
KASSERT(mtx_initialized(&sc->dc_mtx), ("dc mutex not initialized"));
ifp = sc->dc_ifp;
#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
ether_poll_deregister(ifp);
#endif
/* These should only be active if attach succeeded */
if (device_is_attached(dev)) {
DC_LOCK(sc);
dc_stop(sc);
DC_UNLOCK(sc);
callout_drain(&sc->dc_stat_ch);
callout_drain(&sc->dc_wdog_ch);
ether_ifdetach(ifp);
}
if (sc->dc_miibus)
device_delete_child(dev, sc->dc_miibus);
bus_generic_detach(dev);
if (sc->dc_intrhand)
bus_teardown_intr(dev, sc->dc_irq, sc->dc_intrhand);
if (sc->dc_irq)
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->dc_irq);
if (sc->dc_res)
bus_release_resource(dev, DC_RES, DC_RID, sc->dc_res);
if (ifp)
if_free(ifp);
- if (sc->dc_cdata.dc_sbuf != NULL)
- bus_dmamem_free(sc->dc_stag, sc->dc_cdata.dc_sbuf, sc->dc_smap);
- if (sc->dc_ldata != NULL)
- bus_dmamem_free(sc->dc_ltag, sc->dc_ldata, sc->dc_lmap);
- if (sc->dc_mtag) {
- for (i = 0; i < DC_TX_LIST_CNT; i++)
- if (sc->dc_cdata.dc_tx_map[i] != NULL)
- bus_dmamap_destroy(sc->dc_mtag,
- sc->dc_cdata.dc_tx_map[i]);
- for (i = 0; i < DC_RX_LIST_CNT; i++)
- if (sc->dc_cdata.dc_rx_map[i] != NULL)
- bus_dmamap_destroy(sc->dc_mtag,
- sc->dc_cdata.dc_rx_map[i]);
- bus_dmamap_destroy(sc->dc_mtag, sc->dc_sparemap);
- }
- if (sc->dc_stag)
- bus_dma_tag_destroy(sc->dc_stag);
- if (sc->dc_mtag)
- bus_dma_tag_destroy(sc->dc_mtag);
- if (sc->dc_ltag)
- bus_dma_tag_destroy(sc->dc_ltag);
+ dc_dma_free(sc);
free(sc->dc_pnic_rx_buf, M_DEVBUF);
while (sc->dc_mi != NULL) {
m = sc->dc_mi->dc_next;
free(sc->dc_mi, M_DEVBUF);
sc->dc_mi = m;
}
free(sc->dc_srom, M_DEVBUF);
mtx_destroy(&sc->dc_mtx);
return (0);
}
/*
* Initialize the transmit descriptors.
*/
static int
dc_list_tx_init(struct dc_softc *sc)
{
struct dc_chain_data *cd;
struct dc_list_data *ld;
int i, nexti;
cd = &sc->dc_cdata;
- ld = sc->dc_ldata;
+ ld = &sc->dc_ldata;
for (i = 0; i < DC_TX_LIST_CNT; i++) {
if (i == DC_TX_LIST_CNT - 1)
nexti = 0;
else
nexti = i + 1;
+ ld->dc_tx_list[i].dc_status = 0;
+ ld->dc_tx_list[i].dc_ctl = 0;
+ ld->dc_tx_list[i].dc_data = 0;
ld->dc_tx_list[i].dc_next = htole32(DC_TXDESC(sc, nexti));
cd->dc_tx_chain[i] = NULL;
- ld->dc_tx_list[i].dc_data = 0;
- ld->dc_tx_list[i].dc_ctl = 0;
}
cd->dc_tx_prod = cd->dc_tx_cons = cd->dc_tx_cnt = 0;
- bus_dmamap_sync(sc->dc_ltag, sc->dc_lmap,
+ cd->dc_tx_pkts = 0;
+ bus_dmamap_sync(sc->dc_tx_ltag, sc->dc_tx_lmap,
BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
return (0);
}
/*
* Initialize the RX descriptors and allocate mbufs for them. Note that
* we arrange the descriptors in a closed ring, so that the last descriptor
* points back to the first.
*/
static int
dc_list_rx_init(struct dc_softc *sc)
{
struct dc_chain_data *cd;
struct dc_list_data *ld;
int i, nexti;
cd = &sc->dc_cdata;
- ld = sc->dc_ldata;
+ ld = &sc->dc_ldata;
for (i = 0; i < DC_RX_LIST_CNT; i++) {
- if (dc_newbuf(sc, i, 1) != 0)
+ if (dc_newbuf(sc, i) != 0)
return (ENOBUFS);
if (i == DC_RX_LIST_CNT - 1)
nexti = 0;
else
nexti = i + 1;
ld->dc_rx_list[i].dc_next = htole32(DC_RXDESC(sc, nexti));
}
cd->dc_rx_prod = 0;
- bus_dmamap_sync(sc->dc_ltag, sc->dc_lmap,
+ bus_dmamap_sync(sc->dc_rx_ltag, sc->dc_rx_lmap,
BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
return (0);
}
/*
* Initialize an RX descriptor and attach an MBUF cluster.
*/
static int
-dc_newbuf(struct dc_softc *sc, int i, int alloc)
+dc_newbuf(struct dc_softc *sc, int i)
{
- struct mbuf *m_new;
- bus_dmamap_t tmp;
+ struct mbuf *m;
+ bus_dmamap_t map;
bus_dma_segment_t segs[1];
int error, nseg;
- if (alloc) {
- m_new = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
- if (m_new == NULL)
- return (ENOBUFS);
- } else {
- m_new = sc->dc_cdata.dc_rx_chain[i];
- m_new->m_data = m_new->m_ext.ext_buf;
- }
- m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
- m_adj(m_new, sizeof(u_int64_t));
+ m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+ if (m == NULL)
+ return (ENOBUFS);
+ m->m_len = m->m_pkthdr.len = MCLBYTES;
+ m_adj(m, sizeof(u_int64_t));
/*
* If this is a PNIC chip, zero the buffer. This is part
* of the workaround for the receive bug in the 82c168 and
* 82c169 chips.
*/
if (sc->dc_flags & DC_PNIC_RX_BUG_WAR)
- bzero(mtod(m_new, char *), m_new->m_len);
+ bzero(mtod(m, char *), m->m_len);
- /* No need to remap the mbuf if we're reusing it. */
- if (alloc) {
- error = bus_dmamap_load_mbuf_sg(sc->dc_mtag, sc->dc_sparemap,
- m_new, segs, &nseg, 0);
- if (error) {
- m_freem(m_new);
- return (error);
- }
- KASSERT(nseg == 1,
- ("%s: wrong number of segments (%d)", __func__, nseg));
- sc->dc_ldata->dc_rx_list[i].dc_data = htole32(segs->ds_addr);
- bus_dmamap_unload(sc->dc_mtag, sc->dc_cdata.dc_rx_map[i]);
- tmp = sc->dc_cdata.dc_rx_map[i];
- sc->dc_cdata.dc_rx_map[i] = sc->dc_sparemap;
- sc->dc_sparemap = tmp;
- sc->dc_cdata.dc_rx_chain[i] = m_new;
+ error = bus_dmamap_load_mbuf_sg(sc->dc_rx_mtag, sc->dc_sparemap,
+ m, segs, &nseg, 0);
+ if (error) {
+ m_freem(m);
+ return (error);
}
+ KASSERT(nseg == 1, ("%s: wrong number of segments (%d)", __func__,
+ nseg));
+ if (sc->dc_cdata.dc_rx_chain[i] != NULL)
+ bus_dmamap_unload(sc->dc_rx_mtag, sc->dc_cdata.dc_rx_map[i]);
- sc->dc_ldata->dc_rx_list[i].dc_ctl = htole32(DC_RXCTL_RLINK | DC_RXLEN);
- sc->dc_ldata->dc_rx_list[i].dc_status = htole32(DC_RXSTAT_OWN);
- bus_dmamap_sync(sc->dc_mtag, sc->dc_cdata.dc_rx_map[i],
+ map = sc->dc_cdata.dc_rx_map[i];
+ sc->dc_cdata.dc_rx_map[i] = sc->dc_sparemap;
+ sc->dc_sparemap = map;
+ sc->dc_cdata.dc_rx_chain[i] = m;
+ bus_dmamap_sync(sc->dc_rx_mtag, sc->dc_cdata.dc_rx_map[i],
BUS_DMASYNC_PREREAD);
- bus_dmamap_sync(sc->dc_ltag, sc->dc_lmap,
+
+ sc->dc_ldata.dc_rx_list[i].dc_ctl = htole32(DC_RXCTL_RLINK | DC_RXLEN);
+ sc->dc_ldata.dc_rx_list[i].dc_data =
+ htole32(DC_ADDR_LO(segs[0].ds_addr));
+ sc->dc_ldata.dc_rx_list[i].dc_status = htole32(DC_RXSTAT_OWN);
+ bus_dmamap_sync(sc->dc_rx_ltag, sc->dc_rx_lmap,
BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
return (0);
}
/*
* Grrrrr.
* The PNIC chip has a terrible bug in it that manifests itself during
* periods of heavy activity. The exact mode of failure if difficult to
* pinpoint: sometimes it only happens in promiscuous mode, sometimes it
* will happen on slow machines. The bug is that sometimes instead of
* uploading one complete frame during reception, it uploads what looks
* like the entire contents of its FIFO memory. The frame we want is at
* the end of the whole mess, but we never know exactly how much data has
* been uploaded, so salvaging the frame is hard.
*
* There is only one way to do it reliably, and it's disgusting.
* Here's what we know:
*
* - We know there will always be somewhere between one and three extra
* descriptors uploaded.
*
* - We know the desired received frame will always be at the end of the
* total data upload.
*
* - We know the size of the desired received frame because it will be
* provided in the length field of the status word in the last descriptor.
*
* Here's what we do:
*
* - When we allocate buffers for the receive ring, we bzero() them.
* This means that we know that the buffer contents should be all
* zeros, except for data uploaded by the chip.
*
* - We also force the PNIC chip to upload frames that include the
* ethernet CRC at the end.
*
* - We gather all of the bogus frame data into a single buffer.
*
* - We then position a pointer at the end of this buffer and scan
* backwards until we encounter the first non-zero byte of data.
* This is the end of the received frame. We know we will encounter
* some data at the end of the frame because the CRC will always be
* there, so even if the sender transmits a packet of all zeros,
* we won't be fooled.
*
* - We know the size of the actual received frame, so we subtract
* that value from the current pointer location. This brings us
* to the start of the actual received packet.
*
* - We copy this into an mbuf and pass it on, along with the actual
* frame length.
*
* The performance hit is tremendous, but it beats dropping frames all
* the time.
*/
-#define DC_WHOLEFRAME (DC_RXSTAT_FIRSTFRAG | DC_RXSTAT_LASTFRAG)
+#define DC_WHOLEFRAME (DC_RXSTAT_FIRSTFRAG | DC_RXSTAT_LASTFRAG)
static void
dc_pnic_rx_bug_war(struct dc_softc *sc, int idx)
{
struct dc_desc *cur_rx;
struct dc_desc *c = NULL;
struct mbuf *m = NULL;
unsigned char *ptr;
int i, total_len;
- u_int32_t rxstat = 0;
+ uint32_t rxstat = 0;
i = sc->dc_pnic_rx_bug_save;
- cur_rx = &sc->dc_ldata->dc_rx_list[idx];
+ cur_rx = &sc->dc_ldata.dc_rx_list[idx];
ptr = sc->dc_pnic_rx_buf;
bzero(ptr, DC_RXLEN * 5);
/* Copy all the bytes from the bogus buffers. */
while (1) {
- c = &sc->dc_ldata->dc_rx_list[i];
+ c = &sc->dc_ldata.dc_rx_list[i];
rxstat = le32toh(c->dc_status);
m = sc->dc_cdata.dc_rx_chain[i];
bcopy(mtod(m, char *), ptr, DC_RXLEN);
ptr += DC_RXLEN;
/* If this is the last buffer, break out. */
if (i == idx || rxstat & DC_RXSTAT_LASTFRAG)
break;
- dc_newbuf(sc, i, 0);
+ dc_discard_rxbuf(sc, i);
DC_INC(i, DC_RX_LIST_CNT);
}
/* Find the length of the actual receive frame. */
total_len = DC_RXBYTES(rxstat);
/* Scan backwards until we hit a non-zero byte. */
while (*ptr == 0x00)
ptr--;
/* Round off. */
if ((uintptr_t)(ptr) & 0x3)
ptr -= 1;
/* Now find the start of the frame. */
ptr -= total_len;
if (ptr < sc->dc_pnic_rx_buf)
ptr = sc->dc_pnic_rx_buf;
/*
* Now copy the salvaged frame to the last mbuf and fake up
* the status word to make it look like a successful
* frame reception.
*/
- dc_newbuf(sc, i, 0);
bcopy(ptr, mtod(m, char *), total_len);
cur_rx->dc_status = htole32(rxstat | DC_RXSTAT_FIRSTFRAG);
}
/*
* This routine searches the RX ring for dirty descriptors in the
* event that the rxeof routine falls out of sync with the chip's
* current descriptor pointer. This may happen sometimes as a result
* of a "no RX buffer available" condition that happens when the chip
* consumes all of the RX buffers before the driver has a chance to
* process the RX ring. This routine may need to be called more than
* once to bring the driver back in sync with the chip, however we
* should still be getting RX DONE interrupts to drive the search
* for new packets in the RX ring, so we should catch up eventually.
*/
static int
dc_rx_resync(struct dc_softc *sc)
{
struct dc_desc *cur_rx;
int i, pos;
pos = sc->dc_cdata.dc_rx_prod;
for (i = 0; i < DC_RX_LIST_CNT; i++) {
- cur_rx = &sc->dc_ldata->dc_rx_list[pos];
+ bus_dmamap_sync(sc->dc_rx_ltag, sc->dc_rx_lmap,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+ cur_rx = &sc->dc_ldata.dc_rx_list[pos];
if (!(le32toh(cur_rx->dc_status) & DC_RXSTAT_OWN))
break;
DC_INC(pos, DC_RX_LIST_CNT);
}
/* If the ring really is empty, then just return. */
if (i == DC_RX_LIST_CNT)
return (0);
/* We've fallen behing the chip: catch it. */
sc->dc_cdata.dc_rx_prod = pos;
return (EAGAIN);
}
+static void
+dc_discard_rxbuf(struct dc_softc *sc, int i)
+{
+ struct mbuf *m;
+
+ if (sc->dc_flags & DC_PNIC_RX_BUG_WAR) {
+ m = sc->dc_cdata.dc_rx_chain[i];
+ bzero(mtod(m, char *), m->m_len);
+ }
+
+ sc->dc_ldata.dc_rx_list[i].dc_ctl = htole32(DC_RXCTL_RLINK | DC_RXLEN);
+ sc->dc_ldata.dc_rx_list[i].dc_status = htole32(DC_RXSTAT_OWN);
+ bus_dmamap_sync(sc->dc_rx_ltag, sc->dc_rx_lmap, BUS_DMASYNC_PREREAD |
+ BUS_DMASYNC_PREWRITE);
+}
+
/*
* A frame has been uploaded: pass the resulting mbuf chain up to
* the higher level protocols.
*/
static int
dc_rxeof(struct dc_softc *sc)
{
- struct mbuf *m, *m0;
+ struct mbuf *m;
struct ifnet *ifp;
struct dc_desc *cur_rx;
int i, total_len, rx_npkts;
- u_int32_t rxstat;
+ uint32_t rxstat;
DC_LOCK_ASSERT(sc);
ifp = sc->dc_ifp;
- i = sc->dc_cdata.dc_rx_prod;
- total_len = 0;
rx_npkts = 0;
- bus_dmamap_sync(sc->dc_ltag, sc->dc_lmap, BUS_DMASYNC_POSTREAD);
- while (!(le32toh(sc->dc_ldata->dc_rx_list[i].dc_status) &
- DC_RXSTAT_OWN)) {
+ bus_dmamap_sync(sc->dc_rx_ltag, sc->dc_rx_lmap, BUS_DMASYNC_POSTREAD |
+ BUS_DMASYNC_POSTWRITE);
+ for (i = sc->dc_cdata.dc_rx_prod;
+ (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0;
+ DC_INC(i, DC_RX_LIST_CNT)) {
#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING) {
if (sc->rxcycles <= 0)
break;
sc->rxcycles--;
}
#endif
- cur_rx = &sc->dc_ldata->dc_rx_list[i];
+ cur_rx = &sc->dc_ldata.dc_rx_list[i];
rxstat = le32toh(cur_rx->dc_status);
+ if ((rxstat & DC_RXSTAT_OWN) != 0)
+ break;
m = sc->dc_cdata.dc_rx_chain[i];
- bus_dmamap_sync(sc->dc_mtag, sc->dc_cdata.dc_rx_map[i],
+ bus_dmamap_sync(sc->dc_rx_mtag, sc->dc_cdata.dc_rx_map[i],
BUS_DMASYNC_POSTREAD);
total_len = DC_RXBYTES(rxstat);
if (sc->dc_flags & DC_PNIC_RX_BUG_WAR) {
if ((rxstat & DC_WHOLEFRAME) != DC_WHOLEFRAME) {
if (rxstat & DC_RXSTAT_FIRSTFRAG)
sc->dc_pnic_rx_bug_save = i;
- if ((rxstat & DC_RXSTAT_LASTFRAG) == 0) {
- DC_INC(i, DC_RX_LIST_CNT);
+ if ((rxstat & DC_RXSTAT_LASTFRAG) == 0)
continue;
- }
dc_pnic_rx_bug_war(sc, i);
rxstat = le32toh(cur_rx->dc_status);
total_len = DC_RXBYTES(rxstat);
}
}
/*
* If an error occurs, update stats, clear the
* status word and leave the mbuf cluster in place:
* it should simply get re-used next time this descriptor
* comes up in the ring. However, don't report long
* frames as errors since they could be vlans.
*/
if ((rxstat & DC_RXSTAT_RXERR)) {
if (!(rxstat & DC_RXSTAT_GIANT) ||
(rxstat & (DC_RXSTAT_CRCERR | DC_RXSTAT_DRIBBLE |
DC_RXSTAT_MIIERE | DC_RXSTAT_COLLSEEN |
DC_RXSTAT_RUNT | DC_RXSTAT_DE))) {
ifp->if_ierrors++;
if (rxstat & DC_RXSTAT_COLLSEEN)
ifp->if_collisions++;
- dc_newbuf(sc, i, 0);
- if (rxstat & DC_RXSTAT_CRCERR) {
- DC_INC(i, DC_RX_LIST_CNT);
+ dc_discard_rxbuf(sc, i);
+ if (rxstat & DC_RXSTAT_CRCERR)
continue;
- } else {
+ else {
dc_init_locked(sc);
return (rx_npkts);
}
}
}
/* No errors; receive the packet. */
total_len -= ETHER_CRC_LEN;
#ifdef __NO_STRICT_ALIGNMENT
/*
* On architectures without alignment problems we try to
* allocate a new buffer for the receive ring, and pass up
* the one where the packet is already, saving the expensive
* copy done in m_devget().
* If we are on an architecture with alignment problems, or
* if the allocation fails, then use m_devget and leave the
* existing buffer in the receive ring.
*/
- if (dc_newbuf(sc, i, 1) == 0) {
- m->m_pkthdr.rcvif = ifp;
- m->m_pkthdr.len = m->m_len = total_len;
- DC_INC(i, DC_RX_LIST_CNT);
- } else
-#endif
+ if (dc_newbuf(sc, i) != 0) {
+ dc_discard_rxbuf(sc, i);
+ ifp->if_iqdrops++;
+ continue;
+ }
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = m->m_len = total_len;
+#else
{
+ struct mbuf *m0;
+
m0 = m_devget(mtod(m, char *), total_len,
ETHER_ALIGN, ifp, NULL);
- dc_newbuf(sc, i, 0);
- DC_INC(i, DC_RX_LIST_CNT);
+ dc_discard_rxbuf(sc, i);
if (m0 == NULL) {
- ifp->if_ierrors++;
+ ifp->if_iqdrops++;
continue;
}
m = m0;
}
+#endif
ifp->if_ipackets++;
DC_UNLOCK(sc);
(*ifp->if_input)(ifp, m);
DC_LOCK(sc);
rx_npkts++;
}
sc->dc_cdata.dc_rx_prod = i;
return (rx_npkts);
}
/*
* A frame was downloaded to the chip. It's safe for us to clean up
* the list buffers.
*/
static void
dc_txeof(struct dc_softc *sc)
{
- struct dc_desc *cur_tx = NULL;
+ struct dc_desc *cur_tx;
struct ifnet *ifp;
- int idx;
- u_int32_t ctl, txstat;
+ int idx, setup;
+ uint32_t ctl, txstat;
+ if (sc->dc_cdata.dc_tx_cnt == 0)
+ return;
+
ifp = sc->dc_ifp;
/*
* Go through our tx list and free mbufs for those
* frames that have been transmitted.
*/
- bus_dmamap_sync(sc->dc_ltag, sc->dc_lmap, BUS_DMASYNC_POSTREAD);
- idx = sc->dc_cdata.dc_tx_cons;
- while (idx != sc->dc_cdata.dc_tx_prod) {
-
- cur_tx = &sc->dc_ldata->dc_tx_list[idx];
+ bus_dmamap_sync(sc->dc_rx_ltag, sc->dc_tx_lmap, BUS_DMASYNC_POSTREAD |
+ BUS_DMASYNC_POSTWRITE);
+ setup = 0;
+ for (idx = sc->dc_cdata.dc_tx_cons; idx != sc->dc_cdata.dc_tx_prod;
+ DC_INC(idx, DC_TX_LIST_CNT), sc->dc_cdata.dc_tx_cnt--) {
+ cur_tx = &sc->dc_ldata.dc_tx_list[idx];
txstat = le32toh(cur_tx->dc_status);
ctl = le32toh(cur_tx->dc_ctl);
if (txstat & DC_TXSTAT_OWN)
break;
- if (!(ctl & DC_TXCTL_LASTFRAG) || ctl & DC_TXCTL_SETUP) {
- if (ctl & DC_TXCTL_SETUP) {
- /*
- * Yes, the PNIC is so brain damaged
- * that it will sometimes generate a TX
- * underrun error while DMAing the RX
- * filter setup frame. If we detect this,
- * we have to send the setup frame again,
- * or else the filter won't be programmed
- * correctly.
- */
- if (DC_IS_PNIC(sc)) {
- if (txstat & DC_TXSTAT_ERRSUM)
- dc_setfilt(sc);
- }
- sc->dc_cdata.dc_tx_chain[idx] = NULL;
+ if (sc->dc_cdata.dc_tx_chain[idx] == NULL)
+ continue;
+
+ if (ctl & DC_TXCTL_SETUP) {
+ cur_tx->dc_ctl = htole32(ctl & ~DC_TXCTL_SETUP);
+ setup++;
+ bus_dmamap_sync(sc->dc_stag, sc->dc_smap,
+ BUS_DMASYNC_POSTWRITE);
+ /*
+ * Yes, the PNIC is so brain damaged
+ * that it will sometimes generate a TX
+ * underrun error while DMAing the RX
+ * filter setup frame. If we detect this,
+ * we have to send the setup frame again,
+ * or else the filter won't be programmed
+ * correctly.
+ */
+ if (DC_IS_PNIC(sc)) {
+ if (txstat & DC_TXSTAT_ERRSUM)
+ dc_setfilt(sc);
}
- sc->dc_cdata.dc_tx_cnt--;
- DC_INC(idx, DC_TX_LIST_CNT);
+ sc->dc_cdata.dc_tx_chain[idx] = NULL;
continue;
}
if (DC_IS_XIRCOM(sc) || DC_IS_CONEXANT(sc)) {
/*
* XXX: Why does my Xircom taunt me so?
* For some reason it likes setting the CARRLOST flag
* even when the carrier is there. wtf?!?
* Who knows, but Conexant chips have the
* same problem. Maybe they took lessons
* from Xircom.
*/
if (/*sc->dc_type == DC_TYPE_21143 &&*/
sc->dc_pmode == DC_PMODE_MII &&
((txstat & 0xFFFF) & ~(DC_TXSTAT_ERRSUM |
DC_TXSTAT_NOCARRIER)))
txstat &= ~DC_TXSTAT_ERRSUM;
} else {
if (/*sc->dc_type == DC_TYPE_21143 &&*/
sc->dc_pmode == DC_PMODE_MII &&
((txstat & 0xFFFF) & ~(DC_TXSTAT_ERRSUM |
DC_TXSTAT_NOCARRIER | DC_TXSTAT_CARRLOST)))
txstat &= ~DC_TXSTAT_ERRSUM;
}
if (txstat & DC_TXSTAT_ERRSUM) {
ifp->if_oerrors++;
if (txstat & DC_TXSTAT_EXCESSCOLL)
ifp->if_collisions++;
if (txstat & DC_TXSTAT_LATECOLL)
ifp->if_collisions++;
if (!(txstat & DC_TXSTAT_UNDERRUN)) {
dc_init_locked(sc);
return;
}
- }
-
+ } else
+ ifp->if_opackets++;
ifp->if_collisions += (txstat & DC_TXSTAT_COLLCNT) >> 3;
- ifp->if_opackets++;
- if (sc->dc_cdata.dc_tx_chain[idx] != NULL) {
- bus_dmamap_sync(sc->dc_mtag,
- sc->dc_cdata.dc_tx_map[idx],
- BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(sc->dc_mtag,
- sc->dc_cdata.dc_tx_map[idx]);
- m_freem(sc->dc_cdata.dc_tx_chain[idx]);
- sc->dc_cdata.dc_tx_chain[idx] = NULL;
- }
-
- sc->dc_cdata.dc_tx_cnt--;
- DC_INC(idx, DC_TX_LIST_CNT);
+ bus_dmamap_sync(sc->dc_tx_mtag, sc->dc_cdata.dc_tx_map[idx],
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->dc_tx_mtag, sc->dc_cdata.dc_tx_map[idx]);
+ m_freem(sc->dc_cdata.dc_tx_chain[idx]);
+ sc->dc_cdata.dc_tx_chain[idx] = NULL;
}
sc->dc_cdata.dc_tx_cons = idx;
- if (DC_TX_LIST_CNT - sc->dc_cdata.dc_tx_cnt > DC_TX_LIST_RSVD)
+ if (sc->dc_cdata.dc_tx_cnt <= DC_TX_LIST_CNT - DC_TX_LIST_RSVD) {
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-
- if (sc->dc_cdata.dc_tx_cnt == 0)
- sc->dc_wdog_timer = 0;
+ if (sc->dc_cdata.dc_tx_cnt == 0)
+ sc->dc_wdog_timer = 0;
+ }
+ if (setup > 0)
+ bus_dmamap_sync(sc->dc_tx_ltag, sc->dc_tx_lmap,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
}
static void
dc_tick(void *xsc)
{
struct dc_softc *sc;
struct mii_data *mii;
struct ifnet *ifp;
- u_int32_t r;
+ uint32_t r;
sc = xsc;
DC_LOCK_ASSERT(sc);
ifp = sc->dc_ifp;
mii = device_get_softc(sc->dc_miibus);
+ /*
+ * Reclaim transmitted frames for controllers that do
+ * not generate TX completion interrupt for every frame.
+ */
+ if (sc->dc_flags & DC_TX_USE_TX_INTR)
+ dc_txeof(sc);
+
if (sc->dc_flags & DC_REDUCED_MII_POLL) {
if (sc->dc_flags & DC_21143_NWAY) {
r = CSR_READ_4(sc, DC_10BTSTAT);
if (IFM_SUBTYPE(mii->mii_media_active) ==
IFM_100_TX && (r & DC_TSTAT_LS100)) {
sc->dc_link = 0;
mii_mediachg(mii);
}
if (IFM_SUBTYPE(mii->mii_media_active) ==
IFM_10_T && (r & DC_TSTAT_LS10)) {
sc->dc_link = 0;
mii_mediachg(mii);
}
if (sc->dc_link == 0)
mii_tick(mii);
} else {
/*
* For NICs which never report DC_RXSTATE_WAIT, we
* have to bite the bullet...
*/
if ((DC_HAS_BROKEN_RXSTATE(sc) || (CSR_READ_4(sc,
DC_ISR) & DC_ISR_RX_STATE) == DC_RXSTATE_WAIT) &&
sc->dc_cdata.dc_tx_cnt == 0)
mii_tick(mii);
}
} else
mii_tick(mii);
/*
* When the init routine completes, we expect to be able to send
* packets right away, and in fact the network code will send a
* gratuitous ARP the moment the init routine marks the interface
* as running. However, even though the MAC may have been initialized,
* there may be a delay of a few seconds before the PHY completes
* autonegotiation and the link is brought up. Any transmissions
* made during that delay will be lost. Dealing with this is tricky:
* we can't just pause in the init routine while waiting for the
* PHY to come ready since that would bring the whole system to
* a screeching halt for several seconds.
*
* What we do here is prevent the TX start routine from sending
* any packets until a link has been established. After the
* interface has been initialized, the tick routine will poll
* the state of the PHY until the IFM_ACTIVE flag is set. Until
* that time, packets will stay in the send queue, and once the
* link comes up, they will be flushed out to the wire.
*/
if (sc->dc_link != 0 && !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
dc_start_locked(ifp);
if (sc->dc_flags & DC_21143_NWAY && !sc->dc_link)
callout_reset(&sc->dc_stat_ch, hz/10, dc_tick, sc);
else
callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc);
}
/*
* A transmit underrun has occurred. Back off the transmit threshold,
* or switch to store and forward mode if we have to.
*/
static void
dc_tx_underrun(struct dc_softc *sc)
{
- u_int32_t isr;
+ uint32_t isr;
int i;
if (DC_IS_DAVICOM(sc))
dc_init_locked(sc);
if (DC_IS_INTEL(sc)) {
/*
* The real 21143 requires that the transmitter be idle
* in order to change the transmit threshold or store
* and forward state.
*/
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
for (i = 0; i < DC_TIMEOUT; i++) {
isr = CSR_READ_4(sc, DC_ISR);
if (isr & DC_ISR_TX_IDLE)
break;
DELAY(10);
}
if (i == DC_TIMEOUT) {
device_printf(sc->dc_dev,
"%s: failed to force tx to idle state\n",
__func__);
dc_init_locked(sc);
}
}
device_printf(sc->dc_dev, "TX underrun -- ");
sc->dc_txthresh += DC_TXTHRESH_INC;
if (sc->dc_txthresh > DC_TXTHRESH_MAX) {
printf("using store and forward mode\n");
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
} else {
printf("increasing TX threshold\n");
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_THRESH);
DC_SETBIT(sc, DC_NETCFG, sc->dc_txthresh);
}
if (DC_IS_INTEL(sc))
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
}
#ifdef DEVICE_POLLING
static poll_handler_t dc_poll;
static int
dc_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
{
struct dc_softc *sc = ifp->if_softc;
int rx_npkts = 0;
DC_LOCK(sc);
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
DC_UNLOCK(sc);
return (rx_npkts);
}
sc->rxcycles = count;
rx_npkts = dc_rxeof(sc);
dc_txeof(sc);
if (!IFQ_IS_EMPTY(&ifp->if_snd) &&
!(ifp->if_drv_flags & IFF_DRV_OACTIVE))
dc_start_locked(ifp);
if (cmd == POLL_AND_CHECK_STATUS) { /* also check status register */
- u_int32_t status;
+ uint32_t status;
status = CSR_READ_4(sc, DC_ISR);
status &= (DC_ISR_RX_WATDOGTIMEO | DC_ISR_RX_NOBUF |
DC_ISR_TX_NOBUF | DC_ISR_TX_IDLE | DC_ISR_TX_UNDERRUN |
DC_ISR_BUS_ERR);
if (!status) {
DC_UNLOCK(sc);
return (rx_npkts);
}
/* ack what we have */
CSR_WRITE_4(sc, DC_ISR, status);
if (status & (DC_ISR_RX_WATDOGTIMEO | DC_ISR_RX_NOBUF)) {
- u_int32_t r = CSR_READ_4(sc, DC_FRAMESDISCARDED);
+ uint32_t r = CSR_READ_4(sc, DC_FRAMESDISCARDED);
ifp->if_ierrors += (r & 0xffff) + ((r >> 17) & 0x7ff);
if (dc_rx_resync(sc))
dc_rxeof(sc);
}
/* restart transmit unit if necessary */
if (status & DC_ISR_TX_IDLE && sc->dc_cdata.dc_tx_cnt)
CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF);
if (status & DC_ISR_TX_UNDERRUN)
dc_tx_underrun(sc);
if (status & DC_ISR_BUS_ERR) {
if_printf(ifp, "%s: bus error\n", __func__);
dc_reset(sc);
dc_init_locked(sc);
}
}
DC_UNLOCK(sc);
return (rx_npkts);
}
#endif /* DEVICE_POLLING */
static void
dc_intr(void *arg)
{
struct dc_softc *sc;
struct ifnet *ifp;
- u_int32_t status;
+ uint32_t r, status;
+ int curpkts, n;
sc = arg;
if (sc->suspended)
return;
- if ((CSR_READ_4(sc, DC_ISR) & DC_INTRS) == 0)
- return;
-
DC_LOCK(sc);
+ status = CSR_READ_4(sc, DC_ISR);
+ if (status == 0xFFFFFFFF || (status & DC_INTRS) == 0) {
+ DC_UNLOCK(sc);
+ return;
+ }
ifp = sc->dc_ifp;
#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING) {
DC_UNLOCK(sc);
return;
}
#endif
-
- /* Suppress unwanted interrupts */
- if (!(ifp->if_flags & IFF_UP)) {
- if (CSR_READ_4(sc, DC_ISR) & DC_INTRS)
- dc_stop(sc);
- DC_UNLOCK(sc);
- return;
- }
-
/* Disable interrupts. */
CSR_WRITE_4(sc, DC_IMR, 0x00000000);
- while (((status = CSR_READ_4(sc, DC_ISR)) & DC_INTRS) &&
- status != 0xFFFFFFFF &&
- (ifp->if_drv_flags & IFF_DRV_RUNNING)) {
-
+ for (n = 16; n > 0; n--) {
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ break;
+ /* Ack interrupts. */
CSR_WRITE_4(sc, DC_ISR, status);
if (status & DC_ISR_RX_OK) {
- int curpkts;
curpkts = ifp->if_ipackets;
dc_rxeof(sc);
if (curpkts == ifp->if_ipackets) {
while (dc_rx_resync(sc))
dc_rxeof(sc);
}
}
if (status & (DC_ISR_TX_OK | DC_ISR_TX_NOBUF))
dc_txeof(sc);
if (status & DC_ISR_TX_IDLE) {
dc_txeof(sc);
if (sc->dc_cdata.dc_tx_cnt) {
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF);
}
}
if (status & DC_ISR_TX_UNDERRUN)
dc_tx_underrun(sc);
if ((status & DC_ISR_RX_WATDOGTIMEO)
|| (status & DC_ISR_RX_NOBUF)) {
- int curpkts;
+ r = CSR_READ_4(sc, DC_FRAMESDISCARDED);
+ ifp->if_ierrors += (r & 0xffff) + ((r >> 17) & 0x7ff);
curpkts = ifp->if_ipackets;
dc_rxeof(sc);
if (curpkts == ifp->if_ipackets) {
while (dc_rx_resync(sc))
dc_rxeof(sc);
}
}
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ dc_start_locked(ifp);
+
if (status & DC_ISR_BUS_ERR) {
dc_reset(sc);
dc_init_locked(sc);
+ DC_UNLOCK(sc);
+ return;
}
+ status = CSR_READ_4(sc, DC_ISR);
+ if (status == 0xFFFFFFFF || (status & DC_INTRS) == 0)
+ break;
}
/* Re-enable interrupts. */
- CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
- if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- dc_start_locked(ifp);
-
DC_UNLOCK(sc);
}
/*
* Encapsulate an mbuf chain in a descriptor by coupling the mbuf data
* pointers to the fragment pointers.
*/
static int
dc_encap(struct dc_softc *sc, struct mbuf **m_head)
{
bus_dma_segment_t segs[DC_MAXFRAGS];
+ bus_dmamap_t map;
struct dc_desc *f;
struct mbuf *m;
int cur, defragged, error, first, frag, i, idx, nseg;
- /*
- * If there's no way we can send any packets, return now.
- */
- if (DC_TX_LIST_CNT - sc->dc_cdata.dc_tx_cnt <= DC_TX_LIST_RSVD)
- return (ENOBUFS);
-
m = NULL;
defragged = 0;
if (sc->dc_flags & DC_TX_COALESCE &&
((*m_head)->m_next != NULL || sc->dc_flags & DC_TX_ALIGN)) {
m = m_defrag(*m_head, M_DONTWAIT);
defragged = 1;
} else {
/*
* Count the number of frags in this chain to see if we
* need to m_collapse. Since the descriptor list is shared
* by all packets, we'll m_collapse long chains so that they
* do not use up the entire list, even if they would fit.
*/
i = 0;
for (m = *m_head; m != NULL; m = m->m_next)
i++;
if (i > DC_TX_LIST_CNT / 4 ||
DC_TX_LIST_CNT - i + sc->dc_cdata.dc_tx_cnt <=
DC_TX_LIST_RSVD) {
m = m_collapse(*m_head, M_DONTWAIT, DC_MAXFRAGS);
defragged = 1;
}
}
if (defragged != 0) {
if (m == NULL) {
m_freem(*m_head);
*m_head = NULL;
return (ENOBUFS);
}
*m_head = m;
}
idx = sc->dc_cdata.dc_tx_prod;
- error = bus_dmamap_load_mbuf_sg(sc->dc_mtag,
+ error = bus_dmamap_load_mbuf_sg(sc->dc_tx_mtag,
sc->dc_cdata.dc_tx_map[idx], *m_head, segs, &nseg, 0);
if (error == EFBIG) {
if (defragged != 0 || (m = m_collapse(*m_head, M_DONTWAIT,
DC_MAXFRAGS)) == NULL) {
m_freem(*m_head);
*m_head = NULL;
return (defragged != 0 ? error : ENOBUFS);
}
*m_head = m;
- error = bus_dmamap_load_mbuf_sg(sc->dc_mtag,
+ error = bus_dmamap_load_mbuf_sg(sc->dc_tx_mtag,
sc->dc_cdata.dc_tx_map[idx], *m_head, segs, &nseg, 0);
if (error != 0) {
m_freem(*m_head);
*m_head = NULL;
return (error);
}
} else if (error != 0)
return (error);
KASSERT(nseg <= DC_MAXFRAGS,
("%s: wrong number of segments (%d)", __func__, nseg));
if (nseg == 0) {
m_freem(*m_head);
*m_head = NULL;
return (EIO);
}
+ /* Check descriptor overruns. */
+ if (sc->dc_cdata.dc_tx_cnt + nseg > DC_TX_LIST_CNT - DC_TX_LIST_RSVD) {
+ bus_dmamap_unload(sc->dc_tx_mtag, sc->dc_cdata.dc_tx_map[idx]);
+ return (ENOBUFS);
+ }
+ bus_dmamap_sync(sc->dc_tx_mtag, sc->dc_cdata.dc_tx_map[idx],
+ BUS_DMASYNC_PREWRITE);
+
first = cur = frag = sc->dc_cdata.dc_tx_prod;
for (i = 0; i < nseg; i++) {
if ((sc->dc_flags & DC_TX_ADMTEK_WAR) &&
(frag == (DC_TX_LIST_CNT - 1)) &&
(first != sc->dc_cdata.dc_tx_first)) {
- bus_dmamap_unload(sc->dc_mtag,
+ bus_dmamap_unload(sc->dc_tx_mtag,
sc->dc_cdata.dc_tx_map[first]);
m_freem(*m_head);
*m_head = NULL;
return (ENOBUFS);
}
- f = &sc->dc_ldata->dc_tx_list[frag];
+ f = &sc->dc_ldata.dc_tx_list[frag];
f->dc_ctl = htole32(DC_TXCTL_TLINK | segs[i].ds_len);
if (i == 0) {
f->dc_status = 0;
f->dc_ctl |= htole32(DC_TXCTL_FIRSTFRAG);
} else
f->dc_status = htole32(DC_TXSTAT_OWN);
- f->dc_data = htole32(segs[i].ds_addr);
+ f->dc_data = htole32(DC_ADDR_LO(segs[i].ds_addr));
cur = frag;
DC_INC(frag, DC_TX_LIST_CNT);
}
sc->dc_cdata.dc_tx_prod = frag;
sc->dc_cdata.dc_tx_cnt += nseg;
sc->dc_cdata.dc_tx_chain[cur] = *m_head;
- sc->dc_ldata->dc_tx_list[cur].dc_ctl |= htole32(DC_TXCTL_LASTFRAG);
+ sc->dc_ldata.dc_tx_list[cur].dc_ctl |= htole32(DC_TXCTL_LASTFRAG);
if (sc->dc_flags & DC_TX_INTR_FIRSTFRAG)
- sc->dc_ldata->dc_tx_list[first].dc_ctl |=
+ sc->dc_ldata.dc_tx_list[first].dc_ctl |=
htole32(DC_TXCTL_FINT);
if (sc->dc_flags & DC_TX_INTR_ALWAYS)
- sc->dc_ldata->dc_tx_list[cur].dc_ctl |= htole32(DC_TXCTL_FINT);
- if (sc->dc_flags & DC_TX_USE_TX_INTR && sc->dc_cdata.dc_tx_cnt > 64)
- sc->dc_ldata->dc_tx_list[cur].dc_ctl |= htole32(DC_TXCTL_FINT);
- sc->dc_ldata->dc_tx_list[first].dc_status = htole32(DC_TXSTAT_OWN);
+ sc->dc_ldata.dc_tx_list[cur].dc_ctl |= htole32(DC_TXCTL_FINT);
+ if (sc->dc_flags & DC_TX_USE_TX_INTR &&
+ ++sc->dc_cdata.dc_tx_pkts >= 8) {
+ sc->dc_cdata.dc_tx_pkts = 0;
+ sc->dc_ldata.dc_tx_list[cur].dc_ctl |= htole32(DC_TXCTL_FINT);
+ }
+ sc->dc_ldata.dc_tx_list[first].dc_status = htole32(DC_TXSTAT_OWN);
- bus_dmamap_sync(sc->dc_mtag, sc->dc_cdata.dc_tx_map[idx],
- BUS_DMASYNC_PREWRITE);
- bus_dmamap_sync(sc->dc_ltag, sc->dc_lmap,
- BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+ bus_dmamap_sync(sc->dc_tx_ltag, sc->dc_tx_lmap,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+
+ /*
+ * Swap the last and the first dmamaps to ensure the map for
+ * this transmission is placed at the last descriptor.
+ */
+ map = sc->dc_cdata.dc_tx_map[cur];
+ sc->dc_cdata.dc_tx_map[cur] = sc->dc_cdata.dc_tx_map[first];
+ sc->dc_cdata.dc_tx_map[first] = map;
+
return (0);
}
static void
dc_start(struct ifnet *ifp)
{
struct dc_softc *sc;
sc = ifp->if_softc;
DC_LOCK(sc);
dc_start_locked(ifp);
DC_UNLOCK(sc);
}
/*
* Main transmit routine
* To avoid having to do mbuf copies, we put pointers to the mbuf data
* regions directly in the transmit lists. We also save a copy of the
* pointers since the transmit list fragment pointers are physical
* addresses.
*/
static void
dc_start_locked(struct ifnet *ifp)
{
struct dc_softc *sc;
- struct mbuf *m_head = NULL;
- unsigned int queued = 0;
- int idx;
+ struct mbuf *m_head;
+ int queued;
sc = ifp->if_softc;
DC_LOCK_ASSERT(sc);
- if (!sc->dc_link && ifp->if_snd.ifq_len < 10)
+ if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
+ IFF_DRV_RUNNING || sc->dc_link == 0)
return;
- if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
- return;
+ sc->dc_cdata.dc_tx_first = sc->dc_cdata.dc_tx_prod;
- idx = sc->dc_cdata.dc_tx_first = sc->dc_cdata.dc_tx_prod;
-
- while (sc->dc_cdata.dc_tx_chain[idx] == NULL) {
+ for (queued = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd); ) {
+ /*
+ * If there's no way we can send any packets, return now.
+ */
+ if (sc->dc_cdata.dc_tx_cnt > DC_TX_LIST_CNT - DC_TX_LIST_RSVD) {
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ break;
+ }
IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
if (m_head == NULL)
break;
if (dc_encap(sc, &m_head)) {
if (m_head == NULL)
break;
IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
}
- idx = sc->dc_cdata.dc_tx_prod;
queued++;
/*
* If there's a BPF listener, bounce a copy of this frame
* to him.
*/
BPF_MTAP(ifp, m_head);
}
if (queued > 0) {
/* Transmit */
if (!(sc->dc_flags & DC_TX_POLL))
CSR_WRITE_4(sc, DC_TXSTART, 0xFFFFFFFF);
/*
* Set a timeout in case the chip goes out to lunch.
*/
sc->dc_wdog_timer = 5;
}
}
static void
dc_init(void *xsc)
{
struct dc_softc *sc = xsc;
DC_LOCK(sc);
dc_init_locked(sc);
DC_UNLOCK(sc);
}
static void
dc_init_locked(struct dc_softc *sc)
{
struct ifnet *ifp = sc->dc_ifp;
struct mii_data *mii;
struct ifmedia *ifm;
DC_LOCK_ASSERT(sc);
mii = device_get_softc(sc->dc_miibus);
/*
* Cancel pending I/O and free all RX/TX buffers.
*/
dc_stop(sc);
dc_reset(sc);
if (DC_IS_INTEL(sc)) {
ifm = &mii->mii_media;
dc_apply_fixup(sc, ifm->ifm_media);
}
/*
* Set cache alignment and burst length.
*/
if (DC_IS_ASIX(sc) || DC_IS_DAVICOM(sc))
CSR_WRITE_4(sc, DC_BUSCTL, 0);
else
CSR_WRITE_4(sc, DC_BUSCTL, DC_BUSCTL_MRME | DC_BUSCTL_MRLE);
/*
* Evenly share the bus between receive and transmit process.
*/
if (DC_IS_INTEL(sc))
DC_SETBIT(sc, DC_BUSCTL, DC_BUSCTL_ARBITRATION);
if (DC_IS_DAVICOM(sc) || DC_IS_INTEL(sc)) {
DC_SETBIT(sc, DC_BUSCTL, DC_BURSTLEN_USECA);
} else {
DC_SETBIT(sc, DC_BUSCTL, DC_BURSTLEN_16LONG);
}
if (sc->dc_flags & DC_TX_POLL)
DC_SETBIT(sc, DC_BUSCTL, DC_TXPOLL_1);
switch(sc->dc_cachesize) {
case 32:
DC_SETBIT(sc, DC_BUSCTL, DC_CACHEALIGN_32LONG);
break;
case 16:
DC_SETBIT(sc, DC_BUSCTL, DC_CACHEALIGN_16LONG);
break;
case 8:
DC_SETBIT(sc, DC_BUSCTL, DC_CACHEALIGN_8LONG);
break;
case 0:
default:
DC_SETBIT(sc, DC_BUSCTL, DC_CACHEALIGN_NONE);
break;
}
if (sc->dc_flags & DC_TX_STORENFWD)
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
else {
if (sc->dc_txthresh > DC_TXTHRESH_MAX) {
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
} else {
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_STORENFWD);
DC_SETBIT(sc, DC_NETCFG, sc->dc_txthresh);
}
}
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_NO_RXCRC);
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_BACKOFF);
if (DC_IS_MACRONIX(sc) || DC_IS_PNICII(sc)) {
/*
* The app notes for the 98713 and 98715A say that
* in order to have the chips operate properly, a magic
* number must be written to CSR16. Macronix does not
* document the meaning of these bits so there's no way
* to know exactly what they do. The 98713 has a magic
* number all its own; the rest all use a different one.
*/
DC_CLRBIT(sc, DC_MX_MAGICPACKET, 0xFFFF0000);
if (sc->dc_type == DC_TYPE_98713)
DC_SETBIT(sc, DC_MX_MAGICPACKET, DC_MX_MAGIC_98713);
else
DC_SETBIT(sc, DC_MX_MAGICPACKET, DC_MX_MAGIC_98715);
}
if (DC_IS_XIRCOM(sc)) {
/*
* setup General Purpose Port mode and data so the tulip
* can talk to the MII.
*/
CSR_WRITE_4(sc, DC_SIAGP, DC_SIAGP_WRITE_EN | DC_SIAGP_INT1_EN |
DC_SIAGP_MD_GP2_OUTPUT | DC_SIAGP_MD_GP0_OUTPUT);
DELAY(10);
CSR_WRITE_4(sc, DC_SIAGP, DC_SIAGP_INT1_EN |
DC_SIAGP_MD_GP2_OUTPUT | DC_SIAGP_MD_GP0_OUTPUT);
DELAY(10);
}
DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_TX_THRESH);
DC_SETBIT(sc, DC_NETCFG, DC_TXTHRESH_MIN);
/* Init circular RX list. */
if (dc_list_rx_init(sc) == ENOBUFS) {
device_printf(sc->dc_dev,
"initialization failed: no memory for rx buffers\n");
dc_stop(sc);
return;
}
/*
* Init TX descriptors.
*/
dc_list_tx_init(sc);
/*
* Load the address of the RX list.
*/
CSR_WRITE_4(sc, DC_RXADDR, DC_RXDESC(sc, 0));
CSR_WRITE_4(sc, DC_TXADDR, DC_TXDESC(sc, 0));
/*
* Enable interrupts.
*/
#ifdef DEVICE_POLLING
/*
* ... but only if we are not polling, and make sure they are off in
* the case of polling. Some cards (e.g. fxp) turn interrupts on
* after a reset.
*/
if (ifp->if_capenable & IFCAP_POLLING)
CSR_WRITE_4(sc, DC_IMR, 0x00000000);
else
#endif
CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
CSR_WRITE_4(sc, DC_ISR, 0xFFFFFFFF);
/* Enable transmitter. */
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_TX_ON);
/*
* If this is an Intel 21143 and we're not using the
* MII port, program the LED control pins so we get
* link and activity indications.
*/
if (sc->dc_flags & DC_TULIP_LEDS) {
CSR_WRITE_4(sc, DC_WATCHDOG,
DC_WDOG_CTLWREN | DC_WDOG_LINK | DC_WDOG_ACTIVITY);
CSR_WRITE_4(sc, DC_WATCHDOG, 0);
}
/*
* Load the RX/multicast filter. We do this sort of late
* because the filter programming scheme on the 21143 and
* some clones requires DMAing a setup frame via the TX
* engine, and we need the transmitter enabled for that.
*/
dc_setfilt(sc);
/* Enable receiver. */
DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_RX_ON);
CSR_WRITE_4(sc, DC_RXSTART, 0xFFFFFFFF);
ifp->if_drv_flags |= IFF_DRV_RUNNING;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
mii_mediachg(mii);
dc_setcfg(sc, sc->dc_if_media);
+ /* Clear missed frames and overflow counter. */
+ CSR_READ_4(sc, DC_FRAMESDISCARDED);
+
/* Don't start the ticker if this is a homePNA link. */
if (IFM_SUBTYPE(mii->mii_media.ifm_media) == IFM_HPNA_1)
sc->dc_link = 1;
else {
if (sc->dc_flags & DC_21143_NWAY)
callout_reset(&sc->dc_stat_ch, hz/10, dc_tick, sc);
else
callout_reset(&sc->dc_stat_ch, hz, dc_tick, sc);
}
sc->dc_wdog_timer = 0;
callout_reset(&sc->dc_wdog_ch, hz, dc_watchdog, sc);
}
/*
* Set media options.
*/
static int
dc_ifmedia_upd(struct ifnet *ifp)
{
struct dc_softc *sc;
struct mii_data *mii;
struct ifmedia *ifm;
sc = ifp->if_softc;
mii = device_get_softc(sc->dc_miibus);
DC_LOCK(sc);
mii_mediachg(mii);
ifm = &mii->mii_media;
if (DC_IS_INTEL(sc))
dc_setcfg(sc, ifm->ifm_media);
else if (DC_IS_DAVICOM(sc) &&
IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1)
dc_setcfg(sc, ifm->ifm_media);
else
sc->dc_link = 0;
DC_UNLOCK(sc);
return (0);
}
/*
* Report current media status.
*/
static void
dc_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
{
struct dc_softc *sc;
struct mii_data *mii;
struct ifmedia *ifm;
sc = ifp->if_softc;
mii = device_get_softc(sc->dc_miibus);
DC_LOCK(sc);
mii_pollstat(mii);
ifm = &mii->mii_media;
if (DC_IS_DAVICOM(sc)) {
if (IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1) {
ifmr->ifm_active = ifm->ifm_media;
ifmr->ifm_status = 0;
DC_UNLOCK(sc);
return;
}
}
ifmr->ifm_active = mii->mii_media_active;
ifmr->ifm_status = mii->mii_media_status;
DC_UNLOCK(sc);
}
static int
dc_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
{
struct dc_softc *sc = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *)data;
struct mii_data *mii;
int error = 0;
switch (command) {
case SIOCSIFFLAGS:
DC_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
int need_setfilt = (ifp->if_flags ^ sc->dc_if_flags) &
(IFF_PROMISC | IFF_ALLMULTI);
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
if (need_setfilt)
dc_setfilt(sc);
} else {
sc->dc_txthresh = 0;
dc_init_locked(sc);
}
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
dc_stop(sc);
}
sc->dc_if_flags = ifp->if_flags;
DC_UNLOCK(sc);
- error = 0;
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
DC_LOCK(sc);
- dc_setfilt(sc);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ dc_setfilt(sc);
DC_UNLOCK(sc);
- error = 0;
break;
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
mii = device_get_softc(sc->dc_miibus);
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
break;
case SIOCSIFCAP:
#ifdef DEVICE_POLLING
if (ifr->ifr_reqcap & IFCAP_POLLING &&
!(ifp->if_capenable & IFCAP_POLLING)) {
error = ether_poll_register(dc_poll, ifp);
if (error)
return(error);
DC_LOCK(sc);
/* Disable interrupts */
CSR_WRITE_4(sc, DC_IMR, 0x00000000);
ifp->if_capenable |= IFCAP_POLLING;
DC_UNLOCK(sc);
return (error);
}
if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
ifp->if_capenable & IFCAP_POLLING) {
error = ether_poll_deregister(ifp);
/* Enable interrupts. */
DC_LOCK(sc);
CSR_WRITE_4(sc, DC_IMR, DC_INTRS);
ifp->if_capenable &= ~IFCAP_POLLING;
DC_UNLOCK(sc);
return (error);
}
#endif /* DEVICE_POLLING */
break;
default:
error = ether_ioctl(ifp, command, data);
break;
}
return (error);
}
static void
dc_watchdog(void *xsc)
{
struct dc_softc *sc = xsc;
struct ifnet *ifp;
DC_LOCK_ASSERT(sc);
if (sc->dc_wdog_timer == 0 || --sc->dc_wdog_timer != 0) {
callout_reset(&sc->dc_wdog_ch, hz, dc_watchdog, sc);
return;
}
ifp = sc->dc_ifp;
ifp->if_oerrors++;
device_printf(sc->dc_dev, "watchdog timeout\n");
dc_stop(sc);
dc_reset(sc);
dc_init_locked(sc);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
dc_start_locked(ifp);
}
/*
* Stop the adapter and free any mbufs allocated to the
* RX and TX lists.
*/
static void
dc_stop(struct dc_softc *sc)
{
struct ifnet *ifp;
struct dc_list_data *ld;
struct dc_chain_data *cd;
int i;
- u_int32_t ctl;
+ uint32_t ctl;
DC_LOCK_ASSERT(sc);
ifp = sc->dc_ifp;
- ld = sc->dc_ldata;
+ ld = &sc->dc_ldata;
cd = &sc->dc_cdata;
callout_stop(&sc->dc_stat_ch);
callout_stop(&sc->dc_wdog_ch);
sc->dc_wdog_timer = 0;
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ON | DC_NETCFG_TX_ON));
CSR_WRITE_4(sc, DC_IMR, 0x00000000);
CSR_WRITE_4(sc, DC_TXADDR, 0x00000000);
CSR_WRITE_4(sc, DC_RXADDR, 0x00000000);
sc->dc_link = 0;
/*
* Free data in the RX lists.
*/
for (i = 0; i < DC_RX_LIST_CNT; i++) {
if (cd->dc_rx_chain[i] != NULL) {
+ bus_dmamap_sync(sc->dc_rx_mtag,
+ cd->dc_rx_map[i], BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->dc_rx_mtag,
+ cd->dc_rx_map[i]);
m_freem(cd->dc_rx_chain[i]);
cd->dc_rx_chain[i] = NULL;
}
}
- bzero(&ld->dc_rx_list, sizeof(ld->dc_rx_list));
+ bzero(ld->dc_rx_list, DC_RX_LIST_SZ);
+ bus_dmamap_sync(sc->dc_rx_ltag, sc->dc_rx_lmap,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
/*
* Free the TX list buffers.
*/
for (i = 0; i < DC_TX_LIST_CNT; i++) {
if (cd->dc_tx_chain[i] != NULL) {
ctl = le32toh(ld->dc_tx_list[i].dc_ctl);
- if ((ctl & DC_TXCTL_SETUP) ||
- !(ctl & DC_TXCTL_LASTFRAG)) {
- cd->dc_tx_chain[i] = NULL;
- continue;
+ if (ctl & DC_TXCTL_SETUP) {
+ bus_dmamap_sync(sc->dc_stag, sc->dc_smap,
+ BUS_DMASYNC_POSTWRITE);
+ } else {
+ bus_dmamap_sync(sc->dc_tx_mtag,
+ cd->dc_tx_map[i], BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->dc_tx_mtag,
+ cd->dc_tx_map[i]);
+ m_freem(cd->dc_tx_chain[i]);
}
- bus_dmamap_unload(sc->dc_mtag, cd->dc_tx_map[i]);
- m_freem(cd->dc_tx_chain[i]);
cd->dc_tx_chain[i] = NULL;
}
}
- bzero(&ld->dc_tx_list, sizeof(ld->dc_tx_list));
+ bzero(ld->dc_tx_list, DC_TX_LIST_SZ);
+ bus_dmamap_sync(sc->dc_tx_ltag, sc->dc_tx_lmap,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
}
/*
* Device suspend routine. Stop the interface and save some PCI
* settings in case the BIOS doesn't restore them properly on
* resume.
*/
static int
dc_suspend(device_t dev)
{
struct dc_softc *sc;
sc = device_get_softc(dev);
DC_LOCK(sc);
dc_stop(sc);
sc->suspended = 1;
DC_UNLOCK(sc);
return (0);
}
/*
* Device resume routine. Restore some PCI settings in case the BIOS
* doesn't, re-enable busmastering, and restart the interface if
* appropriate.
*/
static int
dc_resume(device_t dev)
{
struct dc_softc *sc;
struct ifnet *ifp;
sc = device_get_softc(dev);
ifp = sc->dc_ifp;
/* reinitialize interface if necessary */
DC_LOCK(sc);
if (ifp->if_flags & IFF_UP)
dc_init_locked(sc);
sc->suspended = 0;
DC_UNLOCK(sc);
return (0);
}
/*
* Stop all chip I/O so that the kernel's probe routines don't
* get confused by errant DMAs when rebooting.
*/
static int
dc_shutdown(device_t dev)
{
struct dc_softc *sc;
sc = device_get_softc(dev);
DC_LOCK(sc);
dc_stop(sc);
DC_UNLOCK(sc);
return (0);
}
static int
dc_check_multiport(struct dc_softc *sc)
{
struct dc_softc *dsc;
devclass_t dc;
device_t child;
uint8_t *eaddr;
int unit;
dc = devclass_find("dc");
for (unit = 0; unit < devclass_get_maxunit(dc); unit++) {
child = devclass_get_device(dc, unit);
if (child == NULL)
continue;
if (child == sc->dc_dev)
continue;
if (device_get_parent(child) != device_get_parent(sc->dc_dev))
continue;
if (unit > device_get_unit(sc->dc_dev))
continue;
if (device_is_attached(child) == 0)
continue;
dsc = device_get_softc(child);
device_printf(sc->dc_dev,
"Using station address of %s as base\n",
device_get_nameunit(child));
bcopy(dsc->dc_eaddr, sc->dc_eaddr, ETHER_ADDR_LEN);
eaddr = (uint8_t *)sc->dc_eaddr;
eaddr[5]++;
/* Prepare SROM to parse again. */
if (DC_IS_INTEL(sc) && dsc->dc_srom != NULL &&
sc->dc_romwidth != 0) {
free(sc->dc_srom, M_DEVBUF);
sc->dc_romwidth = dsc->dc_romwidth;
sc->dc_srom = malloc(DC_ROM_SIZE(sc->dc_romwidth),
M_DEVBUF, M_NOWAIT);
if (sc->dc_srom == NULL) {
device_printf(sc->dc_dev,
"Could not allocate SROM buffer\n");
return (ENOMEM);
}
bcopy(dsc->dc_srom, sc->dc_srom,
DC_ROM_SIZE(sc->dc_romwidth));
}
return (0);
}
return (ENOENT);
}
Index: projects/altix/sys/dev/dc/if_dcreg.h
===================================================================
--- projects/altix/sys/dev/dc/if_dcreg.h (revision 218875)
+++ projects/altix/sys/dev/dc/if_dcreg.h (revision 218876)
@@ -1,1174 +1,1186 @@
/*-
* Copyright (c) 1997, 1998, 1999
* Bill Paul <wpaul@ee.columbia.edu>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Bill Paul.
* 4. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
/*
* 21143 and clone common register definitions.
*/
-#define DC_BUSCTL 0x00 /* bus control */
-#define DC_TXSTART 0x08 /* tx start demand */
-#define DC_RXSTART 0x10 /* rx start demand */
-#define DC_RXADDR 0x18 /* rx descriptor list start addr */
-#define DC_TXADDR 0x20 /* tx descriptor list start addr */
-#define DC_ISR 0x28 /* interrupt status register */
-#define DC_NETCFG 0x30 /* network config register */
-#define DC_IMR 0x38 /* interrupt mask */
-#define DC_FRAMESDISCARDED 0x40 /* # of discarded frames */
-#define DC_SIO 0x48 /* MII and ROM/EEPROM access */
-#define DC_ROM 0x50 /* ROM programming address */
-#define DC_TIMER 0x58 /* general timer */
-#define DC_10BTSTAT 0x60 /* SIA status */
-#define DC_SIARESET 0x68 /* SIA connectivity */
-#define DC_10BTCTRL 0x70 /* SIA transmit and receive */
-#define DC_WATCHDOG 0x78 /* SIA and general purpose port */
-#define DC_SIAGP 0x78 /* SIA and general purpose port (X3201) */
+#define DC_BUSCTL 0x00 /* bus control */
+#define DC_TXSTART 0x08 /* tx start demand */
+#define DC_RXSTART 0x10 /* rx start demand */
+#define DC_RXADDR 0x18 /* rx descriptor list start addr */
+#define DC_TXADDR 0x20 /* tx descriptor list start addr */
+#define DC_ISR 0x28 /* interrupt status register */
+#define DC_NETCFG 0x30 /* network config register */
+#define DC_IMR 0x38 /* interrupt mask */
+#define DC_FRAMESDISCARDED 0x40 /* # of discarded frames */
+#define DC_SIO 0x48 /* MII and ROM/EEPROM access */
+#define DC_ROM 0x50 /* ROM programming address */
+#define DC_TIMER 0x58 /* general timer */
+#define DC_10BTSTAT 0x60 /* SIA status */
+#define DC_SIARESET 0x68 /* SIA connectivity */
+#define DC_10BTCTRL 0x70 /* SIA transmit and receive */
+#define DC_WATCHDOG 0x78 /* SIA and general purpose port */
+#define DC_SIAGP 0x78 /* SIA and general purpose port (X3201) */
/*
* There are two general 'types' of MX chips that we need to be
* concerned with. One is the original 98713, which has its internal
* NWAY support controlled via the MDIO bits in the serial I/O
* register. The other is everything else (from the 98713A on up),
* which has its internal NWAY controlled via CSR13, CSR14 and CSR15,
* just like the 21143. This type setting also governs which of the
* 'magic' numbers we write to CSR16. The PNIC II falls into the
* 98713A/98715/98715A/98725 category.
*/
-#define DC_TYPE_98713 0x1
-#define DC_TYPE_98713A 0x2
-#define DC_TYPE_987x5 0x3
+#define DC_TYPE_98713 0x1
+#define DC_TYPE_98713A 0x2
+#define DC_TYPE_987x5 0x3
/* Other type of supported chips. */
-#define DC_TYPE_21143 0x4 /* Intel 21143 */
-#define DC_TYPE_ASIX 0x5 /* ASIX AX88140A/AX88141 */
-#define DC_TYPE_AL981 0x6 /* ADMtek AL981 Comet */
-#define DC_TYPE_AN983 0x7 /* ADMtek AN983 Centaur */
-#define DC_TYPE_DM9102 0x8 /* Davicom DM9102 */
-#define DC_TYPE_PNICII 0x9 /* 82c115 PNIC II */
-#define DC_TYPE_PNIC 0xA /* 82c168/82c169 PNIC I */
+#define DC_TYPE_21143 0x4 /* Intel 21143 */
+#define DC_TYPE_ASIX 0x5 /* ASIX AX88140A/AX88141 */
+#define DC_TYPE_AL981 0x6 /* ADMtek AL981 Comet */
+#define DC_TYPE_AN983 0x7 /* ADMtek AN983 Centaur */
+#define DC_TYPE_DM9102 0x8 /* Davicom DM9102 */
+#define DC_TYPE_PNICII 0x9 /* 82c115 PNIC II */
+#define DC_TYPE_PNIC 0xA /* 82c168/82c169 PNIC I */
#define DC_TYPE_XIRCOM 0xB /* Xircom X3201 */
-#define DC_TYPE_CONEXANT 0xC /* Conexant LANfinity RS7112 */
+#define DC_TYPE_CONEXANT 0xC /* Conexant LANfinity RS7112 */
-#define DC_IS_MACRONIX(x) \
+#define DC_IS_MACRONIX(x) \
(x->dc_type == DC_TYPE_98713 || \
x->dc_type == DC_TYPE_98713A || \
x->dc_type == DC_TYPE_987x5)
-#define DC_IS_ADMTEK(x) \
+#define DC_IS_ADMTEK(x) \
(x->dc_type == DC_TYPE_AL981 || \
x->dc_type == DC_TYPE_AN983)
-#define DC_IS_INTEL(x) (x->dc_type == DC_TYPE_21143)
-#define DC_IS_ASIX(x) (x->dc_type == DC_TYPE_ASIX)
-#define DC_IS_COMET(x) (x->dc_type == DC_TYPE_AL981)
-#define DC_IS_CENTAUR(x) (x->dc_type == DC_TYPE_AN983)
-#define DC_IS_DAVICOM(x) (x->dc_type == DC_TYPE_DM9102)
-#define DC_IS_PNICII(x) (x->dc_type == DC_TYPE_PNICII)
-#define DC_IS_PNIC(x) (x->dc_type == DC_TYPE_PNIC)
+#define DC_IS_INTEL(x) (x->dc_type == DC_TYPE_21143)
+#define DC_IS_ASIX(x) (x->dc_type == DC_TYPE_ASIX)
+#define DC_IS_COMET(x) (x->dc_type == DC_TYPE_AL981)
+#define DC_IS_CENTAUR(x) (x->dc_type == DC_TYPE_AN983)
+#define DC_IS_DAVICOM(x) (x->dc_type == DC_TYPE_DM9102)
+#define DC_IS_PNICII(x) (x->dc_type == DC_TYPE_PNICII)
+#define DC_IS_PNIC(x) (x->dc_type == DC_TYPE_PNIC)
#define DC_IS_XIRCOM(x) (x->dc_type == DC_TYPE_XIRCOM)
-#define DC_IS_CONEXANT(x) (x->dc_type == DC_TYPE_CONEXANT)
+#define DC_IS_CONEXANT(x) (x->dc_type == DC_TYPE_CONEXANT)
/* MII/symbol mode port types */
-#define DC_PMODE_MII 0x1
-#define DC_PMODE_SYM 0x2
-#define DC_PMODE_SIA 0x3
+#define DC_PMODE_MII 0x1
+#define DC_PMODE_SYM 0x2
+#define DC_PMODE_SIA 0x3
/*
* Bus control bits.
*/
-#define DC_BUSCTL_RESET 0x00000001
-#define DC_BUSCTL_ARBITRATION 0x00000002
-#define DC_BUSCTL_SKIPLEN 0x0000007C
-#define DC_BUSCTL_BUF_BIGENDIAN 0x00000080
-#define DC_BUSCTL_BURSTLEN 0x00003F00
-#define DC_BUSCTL_CACHEALIGN 0x0000C000
-#define DC_BUSCTL_TXPOLL 0x000E0000
-#define DC_BUSCTL_DBO 0x00100000
-#define DC_BUSCTL_MRME 0x00200000
-#define DC_BUSCTL_MRLE 0x00800000
-#define DC_BUSCTL_MWIE 0x01000000
-#define DC_BUSCTL_ONNOW_ENB 0x04000000
+#define DC_BUSCTL_RESET 0x00000001
+#define DC_BUSCTL_ARBITRATION 0x00000002
+#define DC_BUSCTL_SKIPLEN 0x0000007C
+#define DC_BUSCTL_BUF_BIGENDIAN 0x00000080
+#define DC_BUSCTL_BURSTLEN 0x00003F00
+#define DC_BUSCTL_CACHEALIGN 0x0000C000
+#define DC_BUSCTL_TXPOLL 0x000E0000
+#define DC_BUSCTL_DBO 0x00100000
+#define DC_BUSCTL_MRME 0x00200000
+#define DC_BUSCTL_MRLE 0x00800000
+#define DC_BUSCTL_MWIE 0x01000000
+#define DC_BUSCTL_ONNOW_ENB 0x04000000
-#define DC_SKIPLEN_1LONG 0x00000004
-#define DC_SKIPLEN_2LONG 0x00000008
-#define DC_SKIPLEN_3LONG 0x00000010
-#define DC_SKIPLEN_4LONG 0x00000020
-#define DC_SKIPLEN_5LONG 0x00000040
+#define DC_SKIPLEN_1LONG 0x00000004
+#define DC_SKIPLEN_2LONG 0x00000008
+#define DC_SKIPLEN_3LONG 0x00000010
+#define DC_SKIPLEN_4LONG 0x00000020
+#define DC_SKIPLEN_5LONG 0x00000040
-#define DC_CACHEALIGN_NONE 0x00000000
-#define DC_CACHEALIGN_8LONG 0x00004000
-#define DC_CACHEALIGN_16LONG 0x00008000
-#define DC_CACHEALIGN_32LONG 0x0000C000
+#define DC_CACHEALIGN_NONE 0x00000000
+#define DC_CACHEALIGN_8LONG 0x00004000
+#define DC_CACHEALIGN_16LONG 0x00008000
+#define DC_CACHEALIGN_32LONG 0x0000C000
-#define DC_BURSTLEN_USECA 0x00000000
-#define DC_BURSTLEN_1LONG 0x00000100
-#define DC_BURSTLEN_2LONG 0x00000200
-#define DC_BURSTLEN_4LONG 0x00000400
-#define DC_BURSTLEN_8LONG 0x00000800
-#define DC_BURSTLEN_16LONG 0x00001000
-#define DC_BURSTLEN_32LONG 0x00002000
+#define DC_BURSTLEN_USECA 0x00000000
+#define DC_BURSTLEN_1LONG 0x00000100
+#define DC_BURSTLEN_2LONG 0x00000200
+#define DC_BURSTLEN_4LONG 0x00000400
+#define DC_BURSTLEN_8LONG 0x00000800
+#define DC_BURSTLEN_16LONG 0x00001000
+#define DC_BURSTLEN_32LONG 0x00002000
-#define DC_TXPOLL_OFF 0x00000000
-#define DC_TXPOLL_1 0x00020000
-#define DC_TXPOLL_2 0x00040000
-#define DC_TXPOLL_3 0x00060000
-#define DC_TXPOLL_4 0x00080000
-#define DC_TXPOLL_5 0x000A0000
-#define DC_TXPOLL_6 0x000C0000
-#define DC_TXPOLL_7 0x000E0000
+#define DC_TXPOLL_OFF 0x00000000
+#define DC_TXPOLL_1 0x00020000
+#define DC_TXPOLL_2 0x00040000
+#define DC_TXPOLL_3 0x00060000
+#define DC_TXPOLL_4 0x00080000
+#define DC_TXPOLL_5 0x000A0000
+#define DC_TXPOLL_6 0x000C0000
+#define DC_TXPOLL_7 0x000E0000
/*
* Interrupt status bits.
*/
-#define DC_ISR_TX_OK 0x00000001
-#define DC_ISR_TX_IDLE 0x00000002
-#define DC_ISR_TX_NOBUF 0x00000004
-#define DC_ISR_TX_JABBERTIMEO 0x00000008
-#define DC_ISR_LINKGOOD 0x00000010
-#define DC_ISR_TX_UNDERRUN 0x00000020
-#define DC_ISR_RX_OK 0x00000040
-#define DC_ISR_RX_NOBUF 0x00000080
-#define DC_ISR_RX_READ 0x00000100
-#define DC_ISR_RX_WATDOGTIMEO 0x00000200
-#define DC_ISR_TX_EARLY 0x00000400
-#define DC_ISR_TIMER_EXPIRED 0x00000800
-#define DC_ISR_LINKFAIL 0x00001000
-#define DC_ISR_BUS_ERR 0x00002000
-#define DC_ISR_RX_EARLY 0x00004000
-#define DC_ISR_ABNORMAL 0x00008000
-#define DC_ISR_NORMAL 0x00010000
-#define DC_ISR_RX_STATE 0x000E0000
-#define DC_ISR_TX_STATE 0x00700000
-#define DC_ISR_BUSERRTYPE 0x03800000
-#define DC_ISR_100MBPSLINK 0x08000000
-#define DC_ISR_MAGICKPACK 0x10000000
+#define DC_ISR_TX_OK 0x00000001
+#define DC_ISR_TX_IDLE 0x00000002
+#define DC_ISR_TX_NOBUF 0x00000004
+#define DC_ISR_TX_JABBERTIMEO 0x00000008
+#define DC_ISR_LINKGOOD 0x00000010
+#define DC_ISR_TX_UNDERRUN 0x00000020
+#define DC_ISR_RX_OK 0x00000040
+#define DC_ISR_RX_NOBUF 0x00000080
+#define DC_ISR_RX_READ 0x00000100
+#define DC_ISR_RX_WATDOGTIMEO 0x00000200
+#define DC_ISR_TX_EARLY 0x00000400
+#define DC_ISR_TIMER_EXPIRED 0x00000800
+#define DC_ISR_LINKFAIL 0x00001000
+#define DC_ISR_BUS_ERR 0x00002000
+#define DC_ISR_RX_EARLY 0x00004000
+#define DC_ISR_ABNORMAL 0x00008000
+#define DC_ISR_NORMAL 0x00010000
+#define DC_ISR_RX_STATE 0x000E0000
+#define DC_ISR_TX_STATE 0x00700000
+#define DC_ISR_BUSERRTYPE 0x03800000
+#define DC_ISR_100MBPSLINK 0x08000000
+#define DC_ISR_MAGICKPACK 0x10000000
-#define DC_RXSTATE_STOPPED 0x00000000 /* 000 - Stopped */
-#define DC_RXSTATE_FETCH 0x00020000 /* 001 - Fetching descriptor */
-#define DC_RXSTATE_ENDCHECK 0x00040000 /* 010 - check for rx end */
-#define DC_RXSTATE_WAIT 0x00060000 /* 011 - waiting for packet */
-#define DC_RXSTATE_SUSPEND 0x00080000 /* 100 - suspend rx */
-#define DC_RXSTATE_CLOSE 0x000A0000 /* 101 - close tx desc */
-#define DC_RXSTATE_FLUSH 0x000C0000 /* 110 - flush from FIFO */
-#define DC_RXSTATE_DEQUEUE 0x000E0000 /* 111 - dequeue from FIFO */
+#define DC_RXSTATE_STOPPED 0x00000000 /* 000 - Stopped */
+#define DC_RXSTATE_FETCH 0x00020000 /* 001 - Fetching descriptor */
+#define DC_RXSTATE_ENDCHECK 0x00040000 /* 010 - check for rx end */
+#define DC_RXSTATE_WAIT 0x00060000 /* 011 - waiting for packet */
+#define DC_RXSTATE_SUSPEND 0x00080000 /* 100 - suspend rx */
+#define DC_RXSTATE_CLOSE 0x000A0000 /* 101 - close tx desc */
+#define DC_RXSTATE_FLUSH 0x000C0000 /* 110 - flush from FIFO */
+#define DC_RXSTATE_DEQUEUE 0x000E0000 /* 111 - dequeue from FIFO */
#define DC_HAS_BROKEN_RXSTATE(x) \
(DC_IS_CENTAUR(x) || DC_IS_CONEXANT(x) || (DC_IS_DAVICOM(x) && \
pci_get_revid((x)->dc_dev) >= DC_REVISION_DM9102A))
-#define DC_TXSTATE_RESET 0x00000000 /* 000 - reset */
-#define DC_TXSTATE_FETCH 0x00100000 /* 001 - fetching descriptor */
-#define DC_TXSTATE_WAITEND 0x00200000 /* 010 - wait for tx end */
-#define DC_TXSTATE_READING 0x00300000 /* 011 - read and enqueue */
-#define DC_TXSTATE_RSVD 0x00400000 /* 100 - reserved */
-#define DC_TXSTATE_SETUP 0x00500000 /* 101 - setup packet */
-#define DC_TXSTATE_SUSPEND 0x00600000 /* 110 - suspend tx */
-#define DC_TXSTATE_CLOSE 0x00700000 /* 111 - close tx desc */
+#define DC_TXSTATE_RESET 0x00000000 /* 000 - reset */
+#define DC_TXSTATE_FETCH 0x00100000 /* 001 - fetching descriptor */
+#define DC_TXSTATE_WAITEND 0x00200000 /* 010 - wait for tx end */
+#define DC_TXSTATE_READING 0x00300000 /* 011 - read and enqueue */
+#define DC_TXSTATE_RSVD 0x00400000 /* 100 - reserved */
+#define DC_TXSTATE_SETUP 0x00500000 /* 101 - setup packet */
+#define DC_TXSTATE_SUSPEND 0x00600000 /* 110 - suspend tx */
+#define DC_TXSTATE_CLOSE 0x00700000 /* 111 - close tx desc */
/*
* Network config bits.
*/
-#define DC_NETCFG_RX_HASHPERF 0x00000001
-#define DC_NETCFG_RX_ON 0x00000002
-#define DC_NETCFG_RX_HASHONLY 0x00000004
-#define DC_NETCFG_RX_BADFRAMES 0x00000008
-#define DC_NETCFG_RX_INVFILT 0x00000010
-#define DC_NETCFG_BACKOFFCNT 0x00000020
-#define DC_NETCFG_RX_PROMISC 0x00000040
-#define DC_NETCFG_RX_ALLMULTI 0x00000080
-#define DC_NETCFG_FULLDUPLEX 0x00000200
-#define DC_NETCFG_LOOPBACK 0x00000C00
-#define DC_NETCFG_FORCECOLL 0x00001000
-#define DC_NETCFG_TX_ON 0x00002000
-#define DC_NETCFG_TX_THRESH 0x0000C000
-#define DC_NETCFG_TX_BACKOFF 0x00020000
-#define DC_NETCFG_PORTSEL 0x00040000 /* 0 == 10, 1 == 100 */
-#define DC_NETCFG_HEARTBEAT 0x00080000
-#define DC_NETCFG_STORENFWD 0x00200000
-#define DC_NETCFG_SPEEDSEL 0x00400000 /* 1 == 10, 0 == 100 */
-#define DC_NETCFG_PCS 0x00800000
-#define DC_NETCFG_SCRAMBLER 0x01000000
-#define DC_NETCFG_NO_RXCRC 0x02000000
-#define DC_NETCFG_RX_ALL 0x40000000
-#define DC_NETCFG_CAPEFFECT 0x80000000
+#define DC_NETCFG_RX_HASHPERF 0x00000001
+#define DC_NETCFG_RX_ON 0x00000002
+#define DC_NETCFG_RX_HASHONLY 0x00000004
+#define DC_NETCFG_RX_BADFRAMES 0x00000008
+#define DC_NETCFG_RX_INVFILT 0x00000010
+#define DC_NETCFG_BACKOFFCNT 0x00000020
+#define DC_NETCFG_RX_PROMISC 0x00000040
+#define DC_NETCFG_RX_ALLMULTI 0x00000080
+#define DC_NETCFG_FULLDUPLEX 0x00000200
+#define DC_NETCFG_LOOPBACK 0x00000C00
+#define DC_NETCFG_FORCECOLL 0x00001000
+#define DC_NETCFG_TX_ON 0x00002000
+#define DC_NETCFG_TX_THRESH 0x0000C000
+#define DC_NETCFG_TX_BACKOFF 0x00020000
+#define DC_NETCFG_PORTSEL 0x00040000 /* 0 == 10, 1 == 100 */
+#define DC_NETCFG_HEARTBEAT 0x00080000
+#define DC_NETCFG_STORENFWD 0x00200000
+#define DC_NETCFG_SPEEDSEL 0x00400000 /* 1 == 10, 0 == 100 */
+#define DC_NETCFG_PCS 0x00800000
+#define DC_NETCFG_SCRAMBLER 0x01000000
+#define DC_NETCFG_NO_RXCRC 0x02000000
+#define DC_NETCFG_RX_ALL 0x40000000
+#define DC_NETCFG_CAPEFFECT 0x80000000
-#define DC_OPMODE_NORM 0x00000000
-#define DC_OPMODE_INTLOOP 0x00000400
-#define DC_OPMODE_EXTLOOP 0x00000800
+#define DC_OPMODE_NORM 0x00000000
+#define DC_OPMODE_INTLOOP 0x00000400
+#define DC_OPMODE_EXTLOOP 0x00000800
#if 0
-#define DC_TXTHRESH_72BYTES 0x00000000
-#define DC_TXTHRESH_96BYTES 0x00004000
-#define DC_TXTHRESH_128BYTES 0x00008000
-#define DC_TXTHRESH_160BYTES 0x0000C000
+#define DC_TXTHRESH_72BYTES 0x00000000
+#define DC_TXTHRESH_96BYTES 0x00004000
+#define DC_TXTHRESH_128BYTES 0x00008000
+#define DC_TXTHRESH_160BYTES 0x0000C000
#endif
-#define DC_TXTHRESH_MIN 0x00000000
-#define DC_TXTHRESH_INC 0x00004000
-#define DC_TXTHRESH_MAX 0x0000C000
+#define DC_TXTHRESH_MIN 0x00000000
+#define DC_TXTHRESH_INC 0x00004000
+#define DC_TXTHRESH_MAX 0x0000C000
/*
* Interrupt mask bits.
*/
-#define DC_IMR_TX_OK 0x00000001
-#define DC_IMR_TX_IDLE 0x00000002
-#define DC_IMR_TX_NOBUF 0x00000004
-#define DC_IMR_TX_JABBERTIMEO 0x00000008
-#define DC_IMR_LINKGOOD 0x00000010
-#define DC_IMR_TX_UNDERRUN 0x00000020
-#define DC_IMR_RX_OK 0x00000040
-#define DC_IMR_RX_NOBUF 0x00000080
-#define DC_IMR_RX_READ 0x00000100
-#define DC_IMR_RX_WATDOGTIMEO 0x00000200
-#define DC_IMR_TX_EARLY 0x00000400
-#define DC_IMR_TIMER_EXPIRED 0x00000800
-#define DC_IMR_LINKFAIL 0x00001000
-#define DC_IMR_BUS_ERR 0x00002000
-#define DC_IMR_RX_EARLY 0x00004000
-#define DC_IMR_ABNORMAL 0x00008000
-#define DC_IMR_NORMAL 0x00010000
-#define DC_IMR_100MBPSLINK 0x08000000
-#define DC_IMR_MAGICKPACK 0x10000000
+#define DC_IMR_TX_OK 0x00000001
+#define DC_IMR_TX_IDLE 0x00000002
+#define DC_IMR_TX_NOBUF 0x00000004
+#define DC_IMR_TX_JABBERTIMEO 0x00000008
+#define DC_IMR_LINKGOOD 0x00000010
+#define DC_IMR_TX_UNDERRUN 0x00000020
+#define DC_IMR_RX_OK 0x00000040
+#define DC_IMR_RX_NOBUF 0x00000080
+#define DC_IMR_RX_READ 0x00000100
+#define DC_IMR_RX_WATDOGTIMEO 0x00000200
+#define DC_IMR_TX_EARLY 0x00000400
+#define DC_IMR_TIMER_EXPIRED 0x00000800
+#define DC_IMR_LINKFAIL 0x00001000
+#define DC_IMR_BUS_ERR 0x00002000
+#define DC_IMR_RX_EARLY 0x00004000
+#define DC_IMR_ABNORMAL 0x00008000
+#define DC_IMR_NORMAL 0x00010000
+#define DC_IMR_100MBPSLINK 0x08000000
+#define DC_IMR_MAGICKPACK 0x10000000
-#define DC_INTRS \
+#define DC_INTRS \
(DC_IMR_RX_OK|DC_IMR_TX_OK|DC_IMR_RX_NOBUF|DC_IMR_RX_WATDOGTIMEO|\
DC_IMR_TX_NOBUF|DC_IMR_TX_UNDERRUN|DC_IMR_BUS_ERR| \
DC_IMR_ABNORMAL|DC_IMR_NORMAL/*|DC_IMR_TX_EARLY*/)
/*
* Serial I/O (EEPROM/ROM) bits.
*/
-#define DC_SIO_EE_CS 0x00000001 /* EEPROM chip select */
-#define DC_SIO_EE_CLK 0x00000002 /* EEPROM clock */
-#define DC_SIO_EE_DATAIN 0x00000004 /* EEPROM data output */
-#define DC_SIO_EE_DATAOUT 0x00000008 /* EEPROM data input */
-#define DC_SIO_ROMDATA4 0x00000010
-#define DC_SIO_ROMDATA5 0x00000020
-#define DC_SIO_ROMDATA6 0x00000040
-#define DC_SIO_ROMDATA7 0x00000080
-#define DC_SIO_EESEL 0x00000800
-#define DC_SIO_ROMSEL 0x00001000
-#define DC_SIO_ROMCTL_WRITE 0x00002000
-#define DC_SIO_ROMCTL_READ 0x00004000
-#define DC_SIO_MII_CLK 0x00010000 /* MDIO clock */
-#define DC_SIO_MII_DATAOUT 0x00020000 /* MDIO data out */
-#define DC_SIO_MII_DIR 0x00040000 /* MDIO dir */
-#define DC_SIO_MII_DATAIN 0x00080000 /* MDIO data in */
+#define DC_SIO_EE_CS 0x00000001 /* EEPROM chip select */
+#define DC_SIO_EE_CLK 0x00000002 /* EEPROM clock */
+#define DC_SIO_EE_DATAIN 0x00000004 /* EEPROM data output */
+#define DC_SIO_EE_DATAOUT 0x00000008 /* EEPROM data input */
+#define DC_SIO_ROMDATA4 0x00000010
+#define DC_SIO_ROMDATA5 0x00000020
+#define DC_SIO_ROMDATA6 0x00000040
+#define DC_SIO_ROMDATA7 0x00000080
+#define DC_SIO_EESEL 0x00000800
+#define DC_SIO_ROMSEL 0x00001000
+#define DC_SIO_ROMCTL_WRITE 0x00002000
+#define DC_SIO_ROMCTL_READ 0x00004000
+#define DC_SIO_MII_CLK 0x00010000 /* MDIO clock */
+#define DC_SIO_MII_DATAOUT 0x00020000 /* MDIO data out */
+#define DC_SIO_MII_DIR 0x00040000 /* MDIO dir */
+#define DC_SIO_MII_DATAIN 0x00080000 /* MDIO data in */
-#define DC_EECMD_WRITE 0x140
-#define DC_EECMD_READ 0x180
-#define DC_EECMD_ERASE 0x1c0
+#define DC_EECMD_WRITE 0x140
+#define DC_EECMD_READ 0x180
+#define DC_EECMD_ERASE 0x1c0
-#define DC_EE_NODEADDR_OFFSET 0x70
-#define DC_EE_NODEADDR 10
+#define DC_EE_NODEADDR_OFFSET 0x70
+#define DC_EE_NODEADDR 10
/*
* General purpose timer register
*/
-#define DC_TIMER_VALUE 0x0000FFFF
-#define DC_TIMER_CONTINUOUS 0x00010000
+#define DC_TIMER_VALUE 0x0000FFFF
+#define DC_TIMER_CONTINUOUS 0x00010000
/*
* 10baseT status register
*/
-#define DC_TSTAT_MIIACT 0x00000001 /* MII port activity */
-#define DC_TSTAT_LS100 0x00000002 /* link status of 100baseTX */
-#define DC_TSTAT_LS10 0x00000004 /* link status of 10baseT */
-#define DC_TSTAT_AUTOPOLARITY 0x00000008
-#define DC_TSTAT_AUIACT 0x00000100 /* AUI activity */
-#define DC_TSTAT_10BTACT 0x00000200 /* 10baseT activity */
-#define DC_TSTAT_NSN 0x00000400 /* non-stable FLPs detected */
-#define DC_TSTAT_REMFAULT 0x00000800
-#define DC_TSTAT_ANEGSTAT 0x00007000
-#define DC_TSTAT_LP_CAN_NWAY 0x00008000 /* link partner supports NWAY */
-#define DC_TSTAT_LPCODEWORD 0xFFFF0000 /* link partner's code word */
+#define DC_TSTAT_MIIACT 0x00000001 /* MII port activity */
+#define DC_TSTAT_LS100 0x00000002 /* link status of 100baseTX */
+#define DC_TSTAT_LS10 0x00000004 /* link status of 10baseT */
+#define DC_TSTAT_AUTOPOLARITY 0x00000008
+#define DC_TSTAT_AUIACT 0x00000100 /* AUI activity */
+#define DC_TSTAT_10BTACT 0x00000200 /* 10baseT activity */
+#define DC_TSTAT_NSN 0x00000400 /* non-stable FLPs detected */
+#define DC_TSTAT_REMFAULT 0x00000800
+#define DC_TSTAT_ANEGSTAT 0x00007000
+#define DC_TSTAT_LP_CAN_NWAY 0x00008000 /* link partner supports NWAY */
+#define DC_TSTAT_LPCODEWORD 0xFFFF0000 /* link partner's code word */
-#define DC_ASTAT_DISABLE 0x00000000
-#define DC_ASTAT_TXDISABLE 0x00001000
-#define DC_ASTAT_ABDETECT 0x00002000
-#define DC_ASTAT_ACKDETECT 0x00003000
-#define DC_ASTAT_CMPACKDETECT 0x00004000
-#define DC_ASTAT_AUTONEGCMP 0x00005000
-#define DC_ASTAT_LINKCHECK 0x00006000
+#define DC_ASTAT_DISABLE 0x00000000
+#define DC_ASTAT_TXDISABLE 0x00001000
+#define DC_ASTAT_ABDETECT 0x00002000
+#define DC_ASTAT_ACKDETECT 0x00003000
+#define DC_ASTAT_CMPACKDETECT 0x00004000
+#define DC_ASTAT_AUTONEGCMP 0x00005000
+#define DC_ASTAT_LINKCHECK 0x00006000
/*
* PHY reset register
*/
-#define DC_SIA_RESET 0x00000001
-#define DC_SIA_AUI 0x00000008 /* AUI or 10baseT */
+#define DC_SIA_RESET 0x00000001
+#define DC_SIA_AUI 0x00000008 /* AUI or 10baseT */
/*
* 10baseT control register
*/
-#define DC_TCTL_ENCODER_ENB 0x00000001
-#define DC_TCTL_LOOPBACK 0x00000002
-#define DC_TCTL_DRIVER_ENB 0x00000004
-#define DC_TCTL_LNKPULSE_ENB 0x00000008
-#define DC_TCTL_HALFDUPLEX 0x00000040
-#define DC_TCTL_AUTONEGENBL 0x00000080
-#define DC_TCTL_RX_SQUELCH 0x00000100
-#define DC_TCTL_COLL_SQUELCH 0x00000200
-#define DC_TCTL_COLL_DETECT 0x00000400
-#define DC_TCTL_SQE_ENB 0x00000800
-#define DC_TCTL_LINKTEST 0x00001000
-#define DC_TCTL_AUTOPOLARITY 0x00002000
-#define DC_TCTL_SET_POL_PLUS 0x00004000
-#define DC_TCTL_AUTOSENSE 0x00008000 /* 10bt/AUI autosense */
-#define DC_TCTL_100BTXHALF 0x00010000
-#define DC_TCTL_100BTXFULL 0x00020000
-#define DC_TCTL_100BT4 0x00040000
+#define DC_TCTL_ENCODER_ENB 0x00000001
+#define DC_TCTL_LOOPBACK 0x00000002
+#define DC_TCTL_DRIVER_ENB 0x00000004
+#define DC_TCTL_LNKPULSE_ENB 0x00000008
+#define DC_TCTL_HALFDUPLEX 0x00000040
+#define DC_TCTL_AUTONEGENBL 0x00000080
+#define DC_TCTL_RX_SQUELCH 0x00000100
+#define DC_TCTL_COLL_SQUELCH 0x00000200
+#define DC_TCTL_COLL_DETECT 0x00000400
+#define DC_TCTL_SQE_ENB 0x00000800
+#define DC_TCTL_LINKTEST 0x00001000
+#define DC_TCTL_AUTOPOLARITY 0x00002000
+#define DC_TCTL_SET_POL_PLUS 0x00004000
+#define DC_TCTL_AUTOSENSE 0x00008000 /* 10bt/AUI autosense */
+#define DC_TCTL_100BTXHALF 0x00010000
+#define DC_TCTL_100BTXFULL 0x00020000
+#define DC_TCTL_100BT4 0x00040000
/*
* Watchdog timer register
*/
-#define DC_WDOG_JABBERDIS 0x00000001
-#define DC_WDOG_HOSTUNJAB 0x00000002
-#define DC_WDOG_JABBERCLK 0x00000004
-#define DC_WDOG_RXWDOGDIS 0x00000010
-#define DC_WDOG_RXWDOGCLK 0x00000020
-#define DC_WDOG_MUSTBEZERO 0x00000100
-#define DC_WDOG_AUIBNC 0x00100000
-#define DC_WDOG_ACTIVITY 0x00200000
-#define DC_WDOG_RX_MATCH 0x00400000
-#define DC_WDOG_LINK 0x00800000
-#define DC_WDOG_CTLWREN 0x08000000
+#define DC_WDOG_JABBERDIS 0x00000001
+#define DC_WDOG_HOSTUNJAB 0x00000002
+#define DC_WDOG_JABBERCLK 0x00000004
+#define DC_WDOG_RXWDOGDIS 0x00000010
+#define DC_WDOG_RXWDOGCLK 0x00000020
+#define DC_WDOG_MUSTBEZERO 0x00000100
+#define DC_WDOG_AUIBNC 0x00100000
+#define DC_WDOG_ACTIVITY 0x00200000
+#define DC_WDOG_RX_MATCH 0x00400000
+#define DC_WDOG_LINK 0x00800000
+#define DC_WDOG_CTLWREN 0x08000000
/*
* SIA and General Purpose Port register (X3201)
*/
-#define DC_SIAGP_RXMATCH 0x40000000
-#define DC_SIAGP_INT1 0x20000000
-#define DC_SIAGP_INT0 0x10000000
-#define DC_SIAGP_WRITE_EN 0x08000000
-#define DC_SIAGP_RXMATCH_EN 0x04000000
-#define DC_SIAGP_INT1_EN 0x02000000
-#define DC_SIAGP_INT0_EN 0x01000000
-#define DC_SIAGP_LED3 0x00800000
-#define DC_SIAGP_LED2 0x00400000
-#define DC_SIAGP_LED1 0x00200000
-#define DC_SIAGP_LED0 0x00100000
-#define DC_SIAGP_MD_GP3_OUTPUT 0x00080000
-#define DC_SIAGP_MD_GP2_OUTPUT 0x00040000
-#define DC_SIAGP_MD_GP1_OUTPUT 0x00020000
-#define DC_SIAGP_MD_GP0_OUTPUT 0x00010000
+#define DC_SIAGP_RXMATCH 0x40000000
+#define DC_SIAGP_INT1 0x20000000
+#define DC_SIAGP_INT0 0x10000000
+#define DC_SIAGP_WRITE_EN 0x08000000
+#define DC_SIAGP_RXMATCH_EN 0x04000000
+#define DC_SIAGP_INT1_EN 0x02000000
+#define DC_SIAGP_INT0_EN 0x01000000
+#define DC_SIAGP_LED3 0x00800000
+#define DC_SIAGP_LED2 0x00400000
+#define DC_SIAGP_LED1 0x00200000
+#define DC_SIAGP_LED0 0x00100000
+#define DC_SIAGP_MD_GP3_OUTPUT 0x00080000
+#define DC_SIAGP_MD_GP2_OUTPUT 0x00040000
+#define DC_SIAGP_MD_GP1_OUTPUT 0x00020000
+#define DC_SIAGP_MD_GP0_OUTPUT 0x00010000
/*
* Size of a setup frame.
*/
-#define DC_SFRAME_LEN 192
+#define DC_SFRAME_LEN 192
/*
* 21x4x TX/RX list structure.
*/
struct dc_desc {
- u_int32_t dc_status;
- u_int32_t dc_ctl;
- u_int32_t dc_ptr1;
- u_int32_t dc_ptr2;
+ uint32_t dc_status;
+ uint32_t dc_ctl;
+ uint32_t dc_ptr1;
+ uint32_t dc_ptr2;
};
-#define dc_data dc_ptr1
-#define dc_next dc_ptr2
+#define dc_data dc_ptr1
+#define dc_next dc_ptr2
-#define DC_RXSTAT_FIFOOFLOW 0x00000001
-#define DC_RXSTAT_CRCERR 0x00000002
-#define DC_RXSTAT_DRIBBLE 0x00000004
-#define DC_RXSTAT_MIIERE 0x00000008
-#define DC_RXSTAT_WATCHDOG 0x00000010
-#define DC_RXSTAT_FRAMETYPE 0x00000020 /* 0 == IEEE 802.3 */
-#define DC_RXSTAT_COLLSEEN 0x00000040
-#define DC_RXSTAT_GIANT 0x00000080
-#define DC_RXSTAT_LASTFRAG 0x00000100
-#define DC_RXSTAT_FIRSTFRAG 0x00000200
-#define DC_RXSTAT_MULTICAST 0x00000400
-#define DC_RXSTAT_RUNT 0x00000800
-#define DC_RXSTAT_RXTYPE 0x00003000
-#define DC_RXSTAT_DE 0x00004000
-#define DC_RXSTAT_RXERR 0x00008000
-#define DC_RXSTAT_RXLEN 0x3FFF0000
-#define DC_RXSTAT_OWN 0x80000000
+#define DC_RXSTAT_FIFOOFLOW 0x00000001
+#define DC_RXSTAT_CRCERR 0x00000002
+#define DC_RXSTAT_DRIBBLE 0x00000004
+#define DC_RXSTAT_MIIERE 0x00000008
+#define DC_RXSTAT_WATCHDOG 0x00000010
+#define DC_RXSTAT_FRAMETYPE 0x00000020 /* 0 == IEEE 802.3 */
+#define DC_RXSTAT_COLLSEEN 0x00000040
+#define DC_RXSTAT_GIANT 0x00000080
+#define DC_RXSTAT_LASTFRAG 0x00000100
+#define DC_RXSTAT_FIRSTFRAG 0x00000200
+#define DC_RXSTAT_MULTICAST 0x00000400
+#define DC_RXSTAT_RUNT 0x00000800
+#define DC_RXSTAT_RXTYPE 0x00003000
+#define DC_RXSTAT_DE 0x00004000
+#define DC_RXSTAT_RXERR 0x00008000
+#define DC_RXSTAT_RXLEN 0x3FFF0000
+#define DC_RXSTAT_OWN 0x80000000
-#define DC_RXBYTES(x) ((x & DC_RXSTAT_RXLEN) >> 16)
-#define DC_RXSTAT (DC_RXSTAT_FIRSTFRAG|DC_RXSTAT_LASTFRAG|DC_RXSTAT_OWN)
+#define DC_RXBYTES(x) ((x & DC_RXSTAT_RXLEN) >> 16)
+#define DC_RXSTAT (DC_RXSTAT_FIRSTFRAG|DC_RXSTAT_LASTFRAG|DC_RXSTAT_OWN)
-#define DC_RXCTL_BUFLEN1 0x00000FFF
-#define DC_RXCTL_BUFLEN2 0x00FFF000
-#define DC_RXCTL_RLINK 0x01000000
-#define DC_RXCTL_RLAST 0x02000000
+#define DC_RXCTL_BUFLEN1 0x00000FFF
+#define DC_RXCTL_BUFLEN2 0x00FFF000
+#define DC_RXCTL_RLINK 0x01000000
+#define DC_RXCTL_RLAST 0x02000000
-#define DC_TXSTAT_DEFER 0x00000001
-#define DC_TXSTAT_UNDERRUN 0x00000002
-#define DC_TXSTAT_LINKFAIL 0x00000003
-#define DC_TXSTAT_COLLCNT 0x00000078
-#define DC_TXSTAT_SQE 0x00000080
-#define DC_TXSTAT_EXCESSCOLL 0x00000100
-#define DC_TXSTAT_LATECOLL 0x00000200
-#define DC_TXSTAT_NOCARRIER 0x00000400
-#define DC_TXSTAT_CARRLOST 0x00000800
-#define DC_TXSTAT_JABTIMEO 0x00004000
-#define DC_TXSTAT_ERRSUM 0x00008000
-#define DC_TXSTAT_OWN 0x80000000
+#define DC_TXSTAT_DEFER 0x00000001
+#define DC_TXSTAT_UNDERRUN 0x00000002
+#define DC_TXSTAT_LINKFAIL 0x00000003
+#define DC_TXSTAT_COLLCNT 0x00000078
+#define DC_TXSTAT_SQE 0x00000080
+#define DC_TXSTAT_EXCESSCOLL 0x00000100
+#define DC_TXSTAT_LATECOLL 0x00000200
+#define DC_TXSTAT_NOCARRIER 0x00000400
+#define DC_TXSTAT_CARRLOST 0x00000800
+#define DC_TXSTAT_JABTIMEO 0x00004000
+#define DC_TXSTAT_ERRSUM 0x00008000
+#define DC_TXSTAT_OWN 0x80000000
-#define DC_TXCTL_BUFLEN1 0x000007FF
-#define DC_TXCTL_BUFLEN2 0x003FF800
-#define DC_TXCTL_FILTTYPE0 0x00400000
-#define DC_TXCTL_PAD 0x00800000
-#define DC_TXCTL_TLINK 0x01000000
-#define DC_TXCTL_TLAST 0x02000000
-#define DC_TXCTL_NOCRC 0x04000000
-#define DC_TXCTL_SETUP 0x08000000
-#define DC_TXCTL_FILTTYPE1 0x10000000
-#define DC_TXCTL_FIRSTFRAG 0x20000000
-#define DC_TXCTL_LASTFRAG 0x40000000
-#define DC_TXCTL_FINT 0x80000000
+#define DC_TXCTL_BUFLEN1 0x000007FF
+#define DC_TXCTL_BUFLEN2 0x003FF800
+#define DC_TXCTL_FILTTYPE0 0x00400000
+#define DC_TXCTL_PAD 0x00800000
+#define DC_TXCTL_TLINK 0x01000000
+#define DC_TXCTL_TLAST 0x02000000
+#define DC_TXCTL_NOCRC 0x04000000
+#define DC_TXCTL_SETUP 0x08000000
+#define DC_TXCTL_FILTTYPE1 0x10000000
+#define DC_TXCTL_FIRSTFRAG 0x20000000
+#define DC_TXCTL_LASTFRAG 0x40000000
+#define DC_TXCTL_FINT 0x80000000
-#define DC_FILTER_PERFECT 0x00000000
-#define DC_FILTER_HASHPERF 0x00400000
-#define DC_FILTER_INVERSE 0x10000000
-#define DC_FILTER_HASHONLY 0x10400000
+#define DC_FILTER_PERFECT 0x00000000
+#define DC_FILTER_HASHPERF 0x00400000
+#define DC_FILTER_INVERSE 0x10000000
+#define DC_FILTER_HASHONLY 0x10400000
-#define DC_MAXFRAGS 16
+#define DC_MAXFRAGS 16
#ifdef DEVICE_POLLING
-#define DC_RX_LIST_CNT 192
+#define DC_RX_LIST_CNT 192
#else
-#define DC_RX_LIST_CNT 64
+#define DC_RX_LIST_CNT 64
#endif
-#define DC_TX_LIST_CNT 256
-#define DC_TX_LIST_RSVD 5
-#define DC_MIN_FRAMELEN 60
-#define DC_RXLEN 1536
+#define DC_TX_LIST_CNT 256
+#define DC_TX_LIST_RSVD 5
+#define DC_MIN_FRAMELEN 60
+#define DC_RXLEN 1536
-#define DC_INC(x, y) (x) = (x + 1) % y
+#define DC_INC(x, y) (x) = (x + 1) % y
+#define DC_LIST_ALIGN (sizeof(struct dc_desc))
+#define DC_RXBUF_ALIGN 4
+
/* Macros to easily get the DMA address of a descriptor. */
-#define DC_RXDESC(sc, i) (sc->dc_laddr + \
- (uintptr_t)(sc->dc_ldata->dc_rx_list + i) - (uintptr_t)sc->dc_ldata)
-#define DC_TXDESC(sc, i) (sc->dc_laddr + \
- (uintptr_t)(sc->dc_ldata->dc_tx_list + i) - (uintptr_t)sc->dc_ldata)
+#define DC_ADDR_LO(x) ((uint64_t)(x) & 0xFFFFFFFF)
+#define DC_RXDESC(sc, i) \
+ (DC_ADDR_LO(sc->dc_ldata.dc_rx_list_paddr + (sizeof(struct dc_desc) * i)))
+#define DC_TXDESC(sc, i) \
+ (DC_ADDR_LO(sc->dc_ldata.dc_tx_list_paddr + (sizeof(struct dc_desc) * i)))
#if BYTE_ORDER == BIG_ENDIAN
-#define DC_SP_MAC(x) ((x) << 16)
+#define DC_SP_MAC(x) ((x) << 16)
#else
-#define DC_SP_MAC(x) (x)
+#define DC_SP_MAC(x) (x)
#endif
struct dc_list_data {
- struct dc_desc dc_rx_list[DC_RX_LIST_CNT];
- struct dc_desc dc_tx_list[DC_TX_LIST_CNT];
+ struct dc_desc *dc_rx_list;
+ bus_addr_t dc_rx_list_paddr;
+ struct dc_desc *dc_tx_list;
+ bus_addr_t dc_tx_list_paddr;
};
+#define DC_RX_LIST_SZ ((sizeof(struct dc_desc) * DC_RX_LIST_CNT))
+#define DC_TX_LIST_SZ ((sizeof(struct dc_desc) * DC_TX_LIST_CNT))
+
struct dc_chain_data {
struct mbuf *dc_rx_chain[DC_RX_LIST_CNT];
struct mbuf *dc_tx_chain[DC_TX_LIST_CNT];
bus_dmamap_t dc_rx_map[DC_RX_LIST_CNT];
bus_dmamap_t dc_tx_map[DC_TX_LIST_CNT];
- u_int32_t *dc_sbuf;
- u_int8_t dc_pad[DC_MIN_FRAMELEN];
+ uint32_t *dc_sbuf;
+ uint8_t dc_pad[DC_MIN_FRAMELEN];
+ int dc_tx_pkts;
int dc_tx_first;
int dc_tx_prod;
int dc_tx_cons;
int dc_tx_cnt;
int dc_rx_prod;
};
struct dc_mediainfo {
int dc_media;
- u_int8_t *dc_gp_ptr;
- u_int8_t dc_gp_len;
- u_int8_t *dc_reset_ptr;
- u_int8_t dc_reset_len;
+ uint8_t *dc_gp_ptr;
+ uint8_t dc_gp_len;
+ uint8_t *dc_reset_ptr;
+ uint8_t dc_reset_len;
struct dc_mediainfo *dc_next;
};
struct dc_type {
- u_int32_t dc_devid;
- u_int8_t dc_minrev;
+ uint32_t dc_devid;
+ uint8_t dc_minrev;
char *dc_name;
};
struct dc_mii_frame {
- u_int8_t mii_stdelim;
- u_int8_t mii_opcode;
- u_int8_t mii_phyaddr;
- u_int8_t mii_regaddr;
- u_int8_t mii_turnaround;
- u_int16_t mii_data;
+ uint8_t mii_stdelim;
+ uint8_t mii_opcode;
+ uint8_t mii_phyaddr;
+ uint8_t mii_regaddr;
+ uint8_t mii_turnaround;
+ uint16_t mii_data;
};
/*
* MII constants
*/
-#define DC_MII_STARTDELIM 0x01
-#define DC_MII_READOP 0x02
-#define DC_MII_WRITEOP 0x01
-#define DC_MII_TURNAROUND 0x02
+#define DC_MII_STARTDELIM 0x01
+#define DC_MII_READOP 0x02
+#define DC_MII_WRITEOP 0x01
+#define DC_MII_TURNAROUND 0x02
/*
* Registers specific to clone devices.
* This mainly relates to RX filter programming: not all 21x4x clones
* use the standard DEC filter programming mechanism.
*/
/*
* ADMtek specific registers and constants for the AL981 and AN983.
* The AN983 doesn't use the magic PHY registers.
*/
-#define DC_AL_CR 0x88 /* command register */
-#define DC_AL_PAR0 0xA4 /* station address */
-#define DC_AL_PAR1 0xA8 /* station address */
-#define DC_AL_MAR0 0xAC /* multicast hash filter */
-#define DC_AL_MAR1 0xB0 /* multicast hash filter */
-#define DC_AL_BMCR 0xB4 /* built in PHY control */
-#define DC_AL_BMSR 0xB8 /* built in PHY status */
-#define DC_AL_VENID 0xBC /* built in PHY ID0 */
-#define DC_AL_DEVID 0xC0 /* built in PHY ID1 */
-#define DC_AL_ANAR 0xC4 /* built in PHY autoneg advert */
-#define DC_AL_LPAR 0xC8 /* bnilt in PHY link part. ability */
-#define DC_AL_ANER 0xCC /* built in PHY autoneg expansion */
+#define DC_AL_CR 0x88 /* command register */
+#define DC_AL_PAR0 0xA4 /* station address */
+#define DC_AL_PAR1 0xA8 /* station address */
+#define DC_AL_MAR0 0xAC /* multicast hash filter */
+#define DC_AL_MAR1 0xB0 /* multicast hash filter */
+#define DC_AL_BMCR 0xB4 /* built in PHY control */
+#define DC_AL_BMSR 0xB8 /* built in PHY status */
+#define DC_AL_VENID 0xBC /* built in PHY ID0 */
+#define DC_AL_DEVID 0xC0 /* built in PHY ID1 */
+#define DC_AL_ANAR 0xC4 /* built in PHY autoneg advert */
+#define DC_AL_LPAR 0xC8 /* bnilt in PHY link part. ability */
+#define DC_AL_ANER 0xCC /* built in PHY autoneg expansion */
-#define DC_AL_CR_ATUR 0x00000001 /* automatic TX underrun recovery */
-#define DC_ADMTEK_PHYADDR 0x1
-#define DC_AL_EE_NODEADDR 4
+#define DC_AL_CR_ATUR 0x00000001 /* automatic TX underrun recovery */
+#define DC_ADMTEK_PHYADDR 0x1
+#define DC_AL_EE_NODEADDR 4
/* End of ADMtek specific registers */
/*
* ASIX specific registers.
*/
-#define DC_AX_FILTIDX 0x68 /* RX filter index */
-#define DC_AX_FILTDATA 0x70 /* RX filter data */
+#define DC_AX_FILTIDX 0x68 /* RX filter index */
+#define DC_AX_FILTDATA 0x70 /* RX filter data */
/*
* Special ASIX-specific bits in the ASIX NETCFG register (CSR6).
*/
-#define DC_AX_NETCFG_RX_BROAD 0x00000100
+#define DC_AX_NETCFG_RX_BROAD 0x00000100
/*
* RX Filter Index Register values
*/
-#define DC_AX_FILTIDX_PAR0 0x00000000
-#define DC_AX_FILTIDX_PAR1 0x00000001
-#define DC_AX_FILTIDX_MAR0 0x00000002
-#define DC_AX_FILTIDX_MAR1 0x00000003
+#define DC_AX_FILTIDX_PAR0 0x00000000
+#define DC_AX_FILTIDX_PAR1 0x00000001
+#define DC_AX_FILTIDX_MAR0 0x00000002
+#define DC_AX_FILTIDX_MAR1 0x00000003
/* End of ASIX specific registers */
/*
* Macronix specific registers. The Macronix chips have a special
* register for reading the NWAY status, which we don't use, plus
* a magic packet register, which we need to tweak a bit per the
* Macronix application notes.
*/
-#define DC_MX_MAGICPACKET 0x80
-#define DC_MX_NWAYSTAT 0xA0
+#define DC_MX_MAGICPACKET 0x80
+#define DC_MX_NWAYSTAT 0xA0
/*
* Magic packet register
*/
-#define DC_MX_MPACK_DISABLE 0x00400000
+#define DC_MX_MPACK_DISABLE 0x00400000
/*
* NWAY status register.
*/
-#define DC_MX_NWAY_10BTHALF 0x08000000
-#define DC_MX_NWAY_10BTFULL 0x10000000
-#define DC_MX_NWAY_100BTHALF 0x20000000
-#define DC_MX_NWAY_100BTFULL 0x40000000
-#define DC_MX_NWAY_100BT4 0x80000000
+#define DC_MX_NWAY_10BTHALF 0x08000000
+#define DC_MX_NWAY_10BTFULL 0x10000000
+#define DC_MX_NWAY_100BTHALF 0x20000000
+#define DC_MX_NWAY_100BTFULL 0x40000000
+#define DC_MX_NWAY_100BT4 0x80000000
/*
* These are magic values that must be written into CSR16
* (DC_MX_MAGICPACKET) in order to put the chip into proper
* operating mode. The magic numbers are documented in the
* Macronix 98715 application notes.
*/
-#define DC_MX_MAGIC_98713 0x0F370000
-#define DC_MX_MAGIC_98713A 0x0B3C0000
-#define DC_MX_MAGIC_98715 0x0B3C0000
-#define DC_MX_MAGIC_98725 0x0B3C0000
+#define DC_MX_MAGIC_98713 0x0F370000
+#define DC_MX_MAGIC_98713A 0x0B3C0000
+#define DC_MX_MAGIC_98715 0x0B3C0000
+#define DC_MX_MAGIC_98725 0x0B3C0000
/* End of Macronix specific registers */
/*
* PNIC 82c168/82c169 specific registers.
* The PNIC has its own special NWAY support, which doesn't work,
* and shortcut ways of reading the EEPROM and MII bus.
*/
-#define DC_PN_GPIO 0x60 /* general purpose pins control */
-#define DC_PN_PWRUP_CFG 0x90 /* config register, set by EEPROM */
-#define DC_PN_SIOCTL 0x98 /* serial EEPROM control register */
-#define DC_PN_MII 0xA0 /* MII access register */
-#define DC_PN_NWAY 0xB8 /* Internal NWAY register */
+#define DC_PN_GPIO 0x60 /* general purpose pins control */
+#define DC_PN_PWRUP_CFG 0x90 /* config register, set by EEPROM */
+#define DC_PN_SIOCTL 0x98 /* serial EEPROM control register */
+#define DC_PN_MII 0xA0 /* MII access register */
+#define DC_PN_NWAY 0xB8 /* Internal NWAY register */
/* Serial I/O EEPROM register */
-#define DC_PN_SIOCTL_DATA 0x0000003F
-#define DC_PN_SIOCTL_OPCODE 0x00000300
-#define DC_PN_SIOCTL_BUSY 0x80000000
+#define DC_PN_SIOCTL_DATA 0x0000003F
+#define DC_PN_SIOCTL_OPCODE 0x00000300
+#define DC_PN_SIOCTL_BUSY 0x80000000
-#define DC_PN_EEOPCODE_ERASE 0x00000300
-#define DC_PN_EEOPCODE_READ 0x00000600
-#define DC_PN_EEOPCODE_WRITE 0x00000100
+#define DC_PN_EEOPCODE_ERASE 0x00000300
+#define DC_PN_EEOPCODE_READ 0x00000600
+#define DC_PN_EEOPCODE_WRITE 0x00000100
/*
* The first two general purpose pins control speed selection and
* 100Mbps loopback on the 82c168 chip. The control bits should always
* be set (to make the data pins outputs) and the speed selction and
* loopback bits set accordingly when changing media. Physically, this
* will set the state of a relay mounted on the card.
*/
-#define DC_PN_GPIO_DATA0 0x000000001
-#define DC_PN_GPIO_DATA1 0x000000002
-#define DC_PN_GPIO_DATA2 0x000000004
-#define DC_PN_GPIO_DATA3 0x000000008
-#define DC_PN_GPIO_CTL0 0x000000010
-#define DC_PN_GPIO_CTL1 0x000000020
-#define DC_PN_GPIO_CTL2 0x000000040
-#define DC_PN_GPIO_CTL3 0x000000080
-#define DC_PN_GPIO_SPEEDSEL DC_PN_GPIO_DATA0/* 1 == 100Mbps, 0 == 10Mbps */
-#define DC_PN_GPIO_100TX_LOOP DC_PN_GPIO_DATA1/* 1 == normal, 0 == loop */
-#define DC_PN_GPIO_BNC_ENB DC_PN_GPIO_DATA2
-#define DC_PN_GPIO_100TX_LNK DC_PN_GPIO_DATA3
-#define DC_PN_GPIO_SETBIT(sc, r) \
+#define DC_PN_GPIO_DATA0 0x000000001
+#define DC_PN_GPIO_DATA1 0x000000002
+#define DC_PN_GPIO_DATA2 0x000000004
+#define DC_PN_GPIO_DATA3 0x000000008
+#define DC_PN_GPIO_CTL0 0x000000010
+#define DC_PN_GPIO_CTL1 0x000000020
+#define DC_PN_GPIO_CTL2 0x000000040
+#define DC_PN_GPIO_CTL3 0x000000080
+#define DC_PN_GPIO_SPEEDSEL DC_PN_GPIO_DATA0/* 1 == 100Mbps, 0 == 10Mbps */
+#define DC_PN_GPIO_100TX_LOOP DC_PN_GPIO_DATA1/* 1 == normal, 0 == loop */
+#define DC_PN_GPIO_BNC_ENB DC_PN_GPIO_DATA2
+#define DC_PN_GPIO_100TX_LNK DC_PN_GPIO_DATA3
+#define DC_PN_GPIO_SETBIT(sc, r) \
DC_SETBIT(sc, DC_PN_GPIO, ((r) | (r << 4)))
-#define DC_PN_GPIO_CLRBIT(sc, r) \
+#define DC_PN_GPIO_CLRBIT(sc, r) \
{ \
DC_SETBIT(sc, DC_PN_GPIO, ((r) << 4)); \
DC_CLRBIT(sc, DC_PN_GPIO, (r)); \
}
-
+
/* shortcut MII access register */
-#define DC_PN_MII_DATA 0x0000FFFF
-#define DC_PN_MII_RESERVER 0x00020000
-#define DC_PN_MII_REGADDR 0x007C0000
-#define DC_PN_MII_PHYADDR 0x0F800000
-#define DC_PN_MII_OPCODE 0x30000000
-#define DC_PN_MII_BUSY 0x80000000
+#define DC_PN_MII_DATA 0x0000FFFF
+#define DC_PN_MII_RESERVER 0x00020000
+#define DC_PN_MII_REGADDR 0x007C0000
+#define DC_PN_MII_PHYADDR 0x0F800000
+#define DC_PN_MII_OPCODE 0x30000000
+#define DC_PN_MII_BUSY 0x80000000
-#define DC_PN_MIIOPCODE_READ 0x60020000
-#define DC_PN_MIIOPCODE_WRITE 0x50020000
+#define DC_PN_MIIOPCODE_READ 0x60020000
+#define DC_PN_MIIOPCODE_WRITE 0x50020000
/* Internal NWAY bits */
-#define DC_PN_NWAY_RESET 0x00000001 /* reset */
-#define DC_PN_NWAY_PDOWN 0x00000002 /* power down */
-#define DC_PN_NWAY_BYPASS 0x00000004 /* bypass */
-#define DC_PN_NWAY_AUILOWCUR 0x00000008 /* AUI low current */
-#define DC_PN_NWAY_TPEXTEND 0x00000010 /* low squelch voltage */
-#define DC_PN_NWAY_POLARITY 0x00000020 /* 0 == on, 1 == off */
-#define DC_PN_NWAY_TP 0x00000040 /* 1 == tp, 0 == AUI */
-#define DC_PN_NWAY_AUIVOLT 0x00000080 /* 1 == full, 0 == half */
-#define DC_PN_NWAY_DUPLEX 0x00000100 /* LED, 1 == full, 0 == half */
-#define DC_PN_NWAY_LINKTEST 0x00000200 /* 0 == on, 1 == off */
-#define DC_PN_NWAY_AUTODETECT 0x00000400 /* 1 == off, 0 == on */
-#define DC_PN_NWAY_SPEEDSEL 0x00000800 /* LED, 0 = 10, 1 == 100 */
-#define DC_PN_NWAY_NWAY_ENB 0x00001000 /* 0 == off, 1 == on */
-#define DC_PN_NWAY_CAP10HDX 0x00002000
-#define DC_PN_NWAY_CAP10FDX 0x00004000
-#define DC_PN_NWAY_CAP100FDX 0x00008000
-#define DC_PN_NWAY_CAP100HDX 0x00010000
-#define DC_PN_NWAY_CAP100T4 0x00020000
-#define DC_PN_NWAY_ANEGRESTART 0x02000000 /* resets when aneg done */
-#define DC_PN_NWAY_REMFAULT 0x04000000
-#define DC_PN_NWAY_LPAR10HDX 0x08000000
-#define DC_PN_NWAY_LPAR10FDX 0x10000000
-#define DC_PN_NWAY_LPAR100FDX 0x20000000
-#define DC_PN_NWAY_LPAR100HDX 0x40000000
-#define DC_PN_NWAY_LPAR100T4 0x80000000
+#define DC_PN_NWAY_RESET 0x00000001 /* reset */
+#define DC_PN_NWAY_PDOWN 0x00000002 /* power down */
+#define DC_PN_NWAY_BYPASS 0x00000004 /* bypass */
+#define DC_PN_NWAY_AUILOWCUR 0x00000008 /* AUI low current */
+#define DC_PN_NWAY_TPEXTEND 0x00000010 /* low squelch voltage */
+#define DC_PN_NWAY_POLARITY 0x00000020 /* 0 == on, 1 == off */
+#define DC_PN_NWAY_TP 0x00000040 /* 1 == tp, 0 == AUI */
+#define DC_PN_NWAY_AUIVOLT 0x00000080 /* 1 == full, 0 == half */
+#define DC_PN_NWAY_DUPLEX 0x00000100 /* LED, 1 == full, 0 == half */
+#define DC_PN_NWAY_LINKTEST 0x00000200 /* 0 == on, 1 == off */
+#define DC_PN_NWAY_AUTODETECT 0x00000400 /* 1 == off, 0 == on */
+#define DC_PN_NWAY_SPEEDSEL 0x00000800 /* LED, 0 = 10, 1 == 100 */
+#define DC_PN_NWAY_NWAY_ENB 0x00001000 /* 0 == off, 1 == on */
+#define DC_PN_NWAY_CAP10HDX 0x00002000
+#define DC_PN_NWAY_CAP10FDX 0x00004000
+#define DC_PN_NWAY_CAP100FDX 0x00008000
+#define DC_PN_NWAY_CAP100HDX 0x00010000
+#define DC_PN_NWAY_CAP100T4 0x00020000
+#define DC_PN_NWAY_ANEGRESTART 0x02000000 /* resets when aneg done */
+#define DC_PN_NWAY_REMFAULT 0x04000000
+#define DC_PN_NWAY_LPAR10HDX 0x08000000
+#define DC_PN_NWAY_LPAR10FDX 0x10000000
+#define DC_PN_NWAY_LPAR100FDX 0x20000000
+#define DC_PN_NWAY_LPAR100HDX 0x40000000
+#define DC_PN_NWAY_LPAR100T4 0x80000000
/* End of PNIC specific registers */
/*
* CONEXANT specific registers.
*/
-#define DC_CONEXANT_PHYADDR 0x1
-#define DC_CONEXANT_EE_NODEADDR 0x19A
+#define DC_CONEXANT_PHYADDR 0x1
+#define DC_CONEXANT_EE_NODEADDR 0x19A
/* End of CONEXANT specific registers */
struct dc_softc {
struct ifnet *dc_ifp; /* interface info */
device_t dc_dev; /* device info */
bus_space_handle_t dc_bhandle; /* bus space handle */
bus_space_tag_t dc_btag; /* bus space tag */
- bus_dma_tag_t dc_ltag; /* tag for descriptor ring */
- bus_dmamap_t dc_lmap; /* map for descriptor ring */
- u_int32_t dc_laddr; /* DMA address of dc_ldata */
- bus_dma_tag_t dc_mtag; /* tag for mbufs */
+ bus_dma_tag_t dc_ptag; /* parent DMA tag */
bus_dmamap_t dc_sparemap;
+ bus_dma_tag_t dc_rx_ltag; /* tag for RX descriptors */
+ bus_dmamap_t dc_rx_lmap;
+ bus_dma_tag_t dc_tx_ltag; /* tag for TX descriptors */
+ bus_dmamap_t dc_tx_lmap;
bus_dma_tag_t dc_stag; /* tag for the setup frame */
bus_dmamap_t dc_smap; /* map for the setup frame */
- u_int32_t dc_saddr; /* DMA address of setup frame */
+ bus_addr_t dc_saddr; /* DMA address of setup frame */
+ bus_dma_tag_t dc_rx_mtag; /* tag for RX mbufs */
+ bus_dma_tag_t dc_tx_mtag; /* tag for TX mbufs */
void *dc_intrhand;
struct resource *dc_irq;
struct resource *dc_res;
const struct dc_type *dc_info; /* adapter info */
device_t dc_miibus;
- u_int8_t dc_type;
- u_int8_t dc_pmode;
- u_int8_t dc_link;
- u_int8_t dc_cachesize;
+ uint8_t dc_type;
+ uint8_t dc_pmode;
+ uint8_t dc_link;
+ uint8_t dc_cachesize;
int dc_romwidth;
int dc_pnic_rx_bug_save;
unsigned char *dc_pnic_rx_buf;
int dc_if_flags;
int dc_if_media;
- u_int32_t dc_flags;
- u_int32_t dc_txthresh;
- u_int32_t dc_eaddr[2];
- u_int8_t *dc_srom;
+ uint32_t dc_flags;
+ uint32_t dc_txthresh;
+ uint32_t dc_eaddr[2];
+ uint8_t *dc_srom;
struct dc_mediainfo *dc_mi;
- struct dc_list_data *dc_ldata;
+ struct dc_list_data dc_ldata;
struct dc_chain_data dc_cdata;
struct callout dc_stat_ch;
struct callout dc_wdog_ch;
int dc_wdog_timer;
struct mtx dc_mtx;
#ifdef DEVICE_POLLING
int rxcycles; /* ... when polling */
#endif
int suspended; /* 0 = normal 1 = suspended */
};
#define DC_LOCK(_sc) mtx_lock(&(_sc)->dc_mtx)
#define DC_UNLOCK(_sc) mtx_unlock(&(_sc)->dc_mtx)
#define DC_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->dc_mtx, MA_OWNED)
-#define DC_TX_POLL 0x00000001
-#define DC_TX_COALESCE 0x00000002
-#define DC_TX_ADMTEK_WAR 0x00000004
-#define DC_TX_USE_TX_INTR 0x00000008
-#define DC_RX_FILTER_TULIP 0x00000010
-#define DC_TX_INTR_FIRSTFRAG 0x00000020
-#define DC_PNIC_RX_BUG_WAR 0x00000040
-#define DC_TX_FIXED_RING 0x00000080
-#define DC_TX_STORENFWD 0x00000100
-#define DC_REDUCED_MII_POLL 0x00000200
-#define DC_TX_INTR_ALWAYS 0x00000400
-#define DC_21143_NWAY 0x00000800
-#define DC_128BIT_HASH 0x00001000
-#define DC_64BIT_HASH 0x00002000
-#define DC_TULIP_LEDS 0x00004000
-#define DC_TX_ALIGN 0x00010000 /* align mbuf on tx */
+#define DC_TX_POLL 0x00000001
+#define DC_TX_COALESCE 0x00000002
+#define DC_TX_ADMTEK_WAR 0x00000004
+#define DC_TX_USE_TX_INTR 0x00000008
+#define DC_RX_FILTER_TULIP 0x00000010
+#define DC_TX_INTR_FIRSTFRAG 0x00000020
+#define DC_PNIC_RX_BUG_WAR 0x00000040
+#define DC_TX_FIXED_RING 0x00000080
+#define DC_TX_STORENFWD 0x00000100
+#define DC_REDUCED_MII_POLL 0x00000200
+#define DC_TX_INTR_ALWAYS 0x00000400
+#define DC_21143_NWAY 0x00000800
+#define DC_128BIT_HASH 0x00001000
+#define DC_64BIT_HASH 0x00002000
+#define DC_TULIP_LEDS 0x00004000
+#define DC_TX_ALIGN 0x00010000 /* align mbuf on tx */
/*
* register space access macros
*/
-#define CSR_WRITE_4(sc, reg, val) \
+#define CSR_WRITE_4(sc, reg, val) \
bus_space_write_4(sc->dc_btag, sc->dc_bhandle, reg, val)
-#define CSR_READ_4(sc, reg) \
+#define CSR_READ_4(sc, reg) \
bus_space_read_4(sc->dc_btag, sc->dc_bhandle, reg)
-#define CSR_BARRIER_4(sc, reg, flags) \
+#define CSR_BARRIER_4(sc, reg, flags) \
bus_space_barrier(sc->dc_btag, sc->dc_bhandle, reg, 4, flags)
-#define DC_TIMEOUT 1000
-#define ETHER_ALIGN 2
+#define DC_TIMEOUT 1000
/*
* General constants that are fun to know.
*/
/*
* DEC PCI vendor ID
*/
-#define DC_VENDORID_DEC 0x1011
+#define DC_VENDORID_DEC 0x1011
/*
* DEC/Intel 21143 PCI device ID
*/
-#define DC_DEVICEID_21143 0x0019
+#define DC_DEVICEID_21143 0x0019
/*
* Macronix PCI vendor ID
*/
#define DC_VENDORID_MX 0x10D9
/*
* Macronix PMAC device IDs.
*/
-#define DC_DEVICEID_98713 0x0512
-#define DC_DEVICEID_987x5 0x0531
-#define DC_DEVICEID_98727 0x0532
-#define DC_DEVICEID_98732 0x0532
+#define DC_DEVICEID_98713 0x0512
+#define DC_DEVICEID_987x5 0x0531
+#define DC_DEVICEID_98727 0x0532
+#define DC_DEVICEID_98732 0x0532
/* Macronix PCI revision codes. */
-#define DC_REVISION_98713 0x00
-#define DC_REVISION_98713A 0x10
-#define DC_REVISION_98715 0x20
-#define DC_REVISION_98715AEC_C 0x25
-#define DC_REVISION_98725 0x30
+#define DC_REVISION_98713 0x00
+#define DC_REVISION_98713A 0x10
+#define DC_REVISION_98715 0x20
+#define DC_REVISION_98715AEC_C 0x25
+#define DC_REVISION_98725 0x30
/*
* Compex PCI vendor ID.
*/
-#define DC_VENDORID_CP 0x11F6
+#define DC_VENDORID_CP 0x11F6
/*
* Compex PMAC PCI device IDs.
*/
-#define DC_DEVICEID_98713_CP 0x9881
+#define DC_DEVICEID_98713_CP 0x9881
/*
* Lite-On PNIC PCI vendor ID
*/
-#define DC_VENDORID_LO 0x11AD
+#define DC_VENDORID_LO 0x11AD
/*
* 82c168/82c169 PNIC device IDs. Both chips have the same device
* ID but different revisions. Revision 0x10 is the 82c168, and
* 0x20 is the 82c169.
*/
-#define DC_DEVICEID_82C168 0x0002
+#define DC_DEVICEID_82C168 0x0002
-#define DC_REVISION_82C168 0x10
-#define DC_REVISION_82C169 0x20
+#define DC_REVISION_82C168 0x10
+#define DC_REVISION_82C169 0x20
/*
* Lite-On PNIC II device ID. Note: this is actually a Macronix 98715A
* with wake on lan/magic packet support.
*/
-#define DC_DEVICEID_82C115 0xc115
+#define DC_DEVICEID_82C115 0xc115
/*
* Davicom vendor ID.
*/
-#define DC_VENDORID_DAVICOM 0x1282
+#define DC_VENDORID_DAVICOM 0x1282
/*
* Davicom device IDs.
*/
-#define DC_DEVICEID_DM9009 0x9009
-#define DC_DEVICEID_DM9100 0x9100
-#define DC_DEVICEID_DM9102 0x9102
+#define DC_DEVICEID_DM9009 0x9009
+#define DC_DEVICEID_DM9100 0x9100
+#define DC_DEVICEID_DM9102 0x9102
/*
* The DM9102A has the same PCI device ID as the DM9102,
* but a higher revision code.
*/
-#define DC_REVISION_DM9102 0x10
-#define DC_REVISION_DM9102A 0x30
+#define DC_REVISION_DM9102 0x10
+#define DC_REVISION_DM9102A 0x30
/*
* ADMtek vendor ID.
*/
-#define DC_VENDORID_ADMTEK 0x1317
+#define DC_VENDORID_ADMTEK 0x1317
/*
* ADMtek device IDs.
*/
-#define DC_DEVICEID_AL981 0x0981
-#define DC_DEVICEID_AN983 0x0985
-#define DC_DEVICEID_AN985 0x1985
-#define DC_DEVICEID_ADM9511 0x9511
-#define DC_DEVICEID_ADM9513 0x9513
+#define DC_DEVICEID_AL981 0x0981
+#define DC_DEVICEID_AN983 0x0985
+#define DC_DEVICEID_AN985 0x1985
+#define DC_DEVICEID_ADM9511 0x9511
+#define DC_DEVICEID_ADM9513 0x9513
/*
* 3COM PCI vendor ID
*/
-#define DC_VENDORID_3COM 0x10b7
+#define DC_VENDORID_3COM 0x10b7
/*
* 3COM OfficeConnect 10/100B (3CSOHO100B-TX)
*/
-#define DC_DEVICEID_3CSOHOB 0x9300
+#define DC_DEVICEID_3CSOHOB 0x9300
/*
* ASIX vendor ID.
*/
-#define DC_VENDORID_ASIX 0x125B
+#define DC_VENDORID_ASIX 0x125B
/*
* ASIX device IDs.
*/
-#define DC_DEVICEID_AX88140A 0x1400
+#define DC_DEVICEID_AX88140A 0x1400
/*
* The ASIX AX88140 and ASIX AX88141 have the same vendor and
* device IDs but different revision values.
*/
-#define DC_REVISION_88140 0x00
-#define DC_REVISION_88141 0x10
+#define DC_REVISION_88140 0x00
+#define DC_REVISION_88141 0x10
/*
* Accton vendor ID.
*/
-#define DC_VENDORID_ACCTON 0x1113
+#define DC_VENDORID_ACCTON 0x1113
/*
* Accton device IDs.
*/
-#define DC_DEVICEID_EN1217 0x1217
+#define DC_DEVICEID_EN1217 0x1217
#define DC_DEVICEID_EN2242 0x1216
/*
* Xircom vendor ID
*/
#define DC_VENDORID_XIRCOM 0x115d
/*
* Xircom device IDs.
*/
#define DC_DEVICEID_X3201 0x0003
/*
* D-Link vendor ID
*/
#define DC_VENDORID_DLINK 0x1186
/*
* D-Link device IDs.
*/
#define DC_DEVICEID_DRP32TXD 0x1561
/*
* Abocom vendor ID
*/
-#define DC_VENDORID_ABOCOM 0x13d1
+#define DC_VENDORID_ABOCOM 0x13d1
/*
* Abocom device IDs.
*/
-#define DC_DEVICEID_FE2500 0xAB02
-#define DC_DEVICEID_FE2500MX 0xab08
+#define DC_DEVICEID_FE2500 0xAB02
+#define DC_DEVICEID_FE2500MX 0xab08
/*
* Conexant vendor ID.
*/
-#define DC_VENDORID_CONEXANT 0x14f1
+#define DC_VENDORID_CONEXANT 0x14f1
/*
* Conexant device IDs.
*/
-#define DC_DEVICEID_RS7112 0x1803
+#define DC_DEVICEID_RS7112 0x1803
/*
* Planex vendor ID
*/
-#define DC_VENDORID_PLANEX 0x14ea
+#define DC_VENDORID_PLANEX 0x14ea
/*
* Planex device IDs.
*/
-#define DC_DEVICEID_FNW3602T 0xab08
+#define DC_DEVICEID_FNW3602T 0xab08
/*
* Not sure who this vendor should be, so we'll go with HAWKING until
* I can locate the right one.
*/
-#define DC_VENDORID_HAWKING 0x17b3
+#define DC_VENDORID_HAWKING 0x17b3
/*
* Sure looks like an abocom device ID, but it found on my hawking PN672TX
* card. Use that for now, and upgrade later.
*/
-#define DC_DEVICEID_HAWKING_PN672TX 0xab08
+#define DC_DEVICEID_HAWKING_PN672TX 0xab08
/*
* Microsoft device ID.
*/
-#define DC_VENDORID_MICROSOFT 0x1414
+#define DC_VENDORID_MICROSOFT 0x1414
/*
* Supported Microsoft PCI and CardBus NICs. These are really
* ADMtek parts in disguise.
*/
-#define DC_DEVICEID_MSMN120 0x0001
-#define DC_DEVICEID_MSMN130 0x0002
+#define DC_DEVICEID_MSMN120 0x0001
+#define DC_DEVICEID_MSMN130 0x0002
/*
* Linksys vendor ID.
*/
-#define DC_VENDORID_LINKSYS 0x1737
+#define DC_VENDORID_LINKSYS 0x1737
/*
* Linksys device IDs.
*/
-#define DC_DEVICEID_PCMPC200_AB08 0xab08
-#define DC_DEVICEID_PCMPC200_AB09 0xab09
+#define DC_DEVICEID_PCMPC200_AB08 0xab08
+#define DC_DEVICEID_PCMPC200_AB09 0xab09
#define DC_DEVID(vendor, device) ((device) << 16 | (vendor))
/*
* PCI low memory base and low I/O base register, and
* other PCI registers.
*/
-#define DC_PCI_CFBIO PCIR_BAR(0) /* Base I/O address */
-#define DC_PCI_CFBMA PCIR_BAR(1) /* Base memory address */
-#define DC_PCI_CFDD 0x40 /* Device and driver area */
-#define DC_PCI_CWUA0 0x44 /* Wake-Up LAN addr 0 */
-#define DC_PCI_CWUA1 0x48 /* Wake-Up LAN addr 1 */
-#define DC_PCI_SOP0 0x4C /* SecureON passwd 0 */
-#define DC_PCI_SOP1 0x50 /* SecureON passwd 1 */
-#define DC_PCI_CWUC 0x54 /* Configuration Wake-Up cmd */
+#define DC_PCI_CFBIO PCIR_BAR(0) /* Base I/O address */
+#define DC_PCI_CFBMA PCIR_BAR(1) /* Base memory address */
+#define DC_PCI_CFDD 0x40 /* Device and driver area */
+#define DC_PCI_CWUA0 0x44 /* Wake-Up LAN addr 0 */
+#define DC_PCI_CWUA1 0x48 /* Wake-Up LAN addr 1 */
+#define DC_PCI_SOP0 0x4C /* SecureON passwd 0 */
+#define DC_PCI_SOP1 0x50 /* SecureON passwd 1 */
+#define DC_PCI_CWUC 0x54 /* Configuration Wake-Up cmd */
-#define DC_21143_PB_REV 0x00000030
-#define DC_21143_TB_REV 0x00000030
-#define DC_21143_PC_REV 0x00000030
-#define DC_21143_TC_REV 0x00000030
-#define DC_21143_PD_REV 0x00000041
-#define DC_21143_TD_REV 0x00000041
+#define DC_21143_PB_REV 0x00000030
+#define DC_21143_TB_REV 0x00000030
+#define DC_21143_PC_REV 0x00000030
+#define DC_21143_TC_REV 0x00000030
+#define DC_21143_PD_REV 0x00000041
+#define DC_21143_TD_REV 0x00000041
/* Configuration and driver area */
-#define DC_CFDD_DRVUSE 0x0000FFFF
-#define DC_CFDD_SNOOZE_MODE 0x40000000
-#define DC_CFDD_SLEEP_MODE 0x80000000
+#define DC_CFDD_DRVUSE 0x0000FFFF
+#define DC_CFDD_SNOOZE_MODE 0x40000000
+#define DC_CFDD_SLEEP_MODE 0x80000000
/* Configuration wake-up command register */
-#define DC_CWUC_MUST_BE_ZERO 0x00000001
-#define DC_CWUC_SECUREON_ENB 0x00000002
-#define DC_CWUC_FORCE_WUL 0x00000004
-#define DC_CWUC_BNC_ABILITY 0x00000008
-#define DC_CWUC_AUI_ABILITY 0x00000010
-#define DC_CWUC_TP10_ABILITY 0x00000020
-#define DC_CWUC_MII_ABILITY 0x00000040
-#define DC_CWUC_SYM_ABILITY 0x00000080
-#define DC_CWUC_LOCK 0x00000100
+#define DC_CWUC_MUST_BE_ZERO 0x00000001
+#define DC_CWUC_SECUREON_ENB 0x00000002
+#define DC_CWUC_FORCE_WUL 0x00000004
+#define DC_CWUC_BNC_ABILITY 0x00000008
+#define DC_CWUC_AUI_ABILITY 0x00000010
+#define DC_CWUC_TP10_ABILITY 0x00000020
+#define DC_CWUC_MII_ABILITY 0x00000040
+#define DC_CWUC_SYM_ABILITY 0x00000080
+#define DC_CWUC_LOCK 0x00000100
/*
* SROM nonsense.
*/
#define DC_ROM_SIZE(bits) (2 << (bits))
-#define DC_IB_CTLRCNT 0x13
-#define DC_IB_LEAF0_CNUM 0x1A
-#define DC_IB_LEAF0_OFFSET 0x1B
+#define DC_IB_CTLRCNT 0x13
+#define DC_IB_LEAF0_CNUM 0x1A
+#define DC_IB_LEAF0_OFFSET 0x1B
struct dc_info_leaf {
- u_int16_t dc_conntype;
- u_int8_t dc_blkcnt;
- u_int8_t dc_rsvd;
- u_int16_t dc_infoblk;
+ uint16_t dc_conntype;
+ uint8_t dc_blkcnt;
+ uint8_t dc_rsvd;
+ uint16_t dc_infoblk;
};
-#define DC_CTYPE_10BT 0x0000
-#define DC_CTYPE_10BT_NWAY 0x0100
-#define DC_CTYPE_10BT_FDX 0x0204
-#define DC_CTYPE_10B2 0x0001
-#define DC_CTYPE_10B5 0x0002
-#define DC_CTYPE_100BT 0x0003
-#define DC_CTYPE_100BT_FDX 0x0205
-#define DC_CTYPE_100T4 0x0006
-#define DC_CTYPE_100FX 0x0007
-#define DC_CTYPE_100FX_FDX 0x0208
-#define DC_CTYPE_MII_10BT 0x0009
-#define DC_CTYPE_MII_10BT_FDX 0x020A
-#define DC_CTYPE_MII_100BT 0x000D
-#define DC_CTYPE_MII_100BT_FDX 0x020E
-#define DC_CTYPE_MII_100T4 0x000F
-#define DC_CTYPE_MII_100FX 0x0010
-#define DC_CTYPE_MII_100FX_FDX 0x0211
-#define DC_CTYPE_DYN_PUP_AUTOSENSE 0x0800
-#define DC_CTYPE_PUP_AUTOSENSE 0x8800
-#define DC_CTYPE_NOMEDIA 0xFFFF
+#define DC_CTYPE_10BT 0x0000
+#define DC_CTYPE_10BT_NWAY 0x0100
+#define DC_CTYPE_10BT_FDX 0x0204
+#define DC_CTYPE_10B2 0x0001
+#define DC_CTYPE_10B5 0x0002
+#define DC_CTYPE_100BT 0x0003
+#define DC_CTYPE_100BT_FDX 0x0205
+#define DC_CTYPE_100T4 0x0006
+#define DC_CTYPE_100FX 0x0007
+#define DC_CTYPE_100FX_FDX 0x0208
+#define DC_CTYPE_MII_10BT 0x0009
+#define DC_CTYPE_MII_10BT_FDX 0x020A
+#define DC_CTYPE_MII_100BT 0x000D
+#define DC_CTYPE_MII_100BT_FDX 0x020E
+#define DC_CTYPE_MII_100T4 0x000F
+#define DC_CTYPE_MII_100FX 0x0010
+#define DC_CTYPE_MII_100FX_FDX 0x0211
+#define DC_CTYPE_DYN_PUP_AUTOSENSE 0x0800
+#define DC_CTYPE_PUP_AUTOSENSE 0x8800
+#define DC_CTYPE_NOMEDIA 0xFFFF
-#define DC_EBLOCK_SIA 0x0002
-#define DC_EBLOCK_MII 0x0003
-#define DC_EBLOCK_SYM 0x0004
-#define DC_EBLOCK_RESET 0x0005
-#define DC_EBLOCK_PHY_SHUTDOWN 0x0006
+#define DC_EBLOCK_SIA 0x0002
+#define DC_EBLOCK_MII 0x0003
+#define DC_EBLOCK_SYM 0x0004
+#define DC_EBLOCK_RESET 0x0005
+#define DC_EBLOCK_PHY_SHUTDOWN 0x0006
struct dc_leaf_hdr {
- u_int16_t dc_mtype;
- u_int8_t dc_mcnt;
- u_int8_t dc_rsvd;
+ uint16_t dc_mtype;
+ uint8_t dc_mcnt;
+ uint8_t dc_rsvd;
};
struct dc_eblock_hdr {
- u_int8_t dc_len;
- u_int8_t dc_type;
+ uint8_t dc_len;
+ uint8_t dc_type;
};
struct dc_eblock_sia {
struct dc_eblock_hdr dc_sia_hdr;
- u_int8_t dc_sia_code;
+ uint8_t dc_sia_code;
union {
struct dc_sia_ext { /* if (dc_sia_code & DC_SIA_CODE_EXT) */
- u_int8_t dc_sia_mediaspec[6]; /* CSR13, CSR14, CSR15 */
- u_int8_t dc_sia_gpio_ctl[2];
- u_int8_t dc_sia_gpio_dat[2];
+ uint8_t dc_sia_mediaspec[6]; /* CSR13, CSR14, CSR15 */
+ uint8_t dc_sia_gpio_ctl[2];
+ uint8_t dc_sia_gpio_dat[2];
} dc_sia_ext;
struct dc_sia_noext {
- u_int8_t dc_sia_gpio_ctl[2];
- u_int8_t dc_sia_gpio_dat[2];
+ uint8_t dc_sia_gpio_ctl[2];
+ uint8_t dc_sia_gpio_dat[2];
} dc_sia_noext;
} dc_un;
};
-#define DC_SIA_CODE_10BT 0x00
-#define DC_SIA_CODE_10B2 0x01
-#define DC_SIA_CODE_10B5 0x02
-#define DC_SIA_CODE_10BT_FDX 0x04
-#define DC_SIA_CODE_EXT 0x40
+#define DC_SIA_CODE_10BT 0x00
+#define DC_SIA_CODE_10B2 0x01
+#define DC_SIA_CODE_10B5 0x02
+#define DC_SIA_CODE_10BT_FDX 0x04
+#define DC_SIA_CODE_EXT 0x40
/*
* Note that the first word in the gpr and reset
* sequences is always a control word.
*/
struct dc_eblock_mii {
struct dc_eblock_hdr dc_mii_hdr;
- u_int8_t dc_mii_phynum;
- u_int8_t dc_gpr_len;
-/* u_int16_t dc_gpr_dat[n]; */
-/* u_int8_t dc_reset_len; */
-/* u_int16_t dc_reset_dat[n]; */
+ uint8_t dc_mii_phynum;
+ uint8_t dc_gpr_len;
+/* uint16_t dc_gpr_dat[n]; */
+/* uint8_t dc_reset_len; */
+/* uint16_t dc_reset_dat[n]; */
/* There are other fields after these, but we don't
* care about them since they can be determined by looking
* at the PHY.
*/
};
struct dc_eblock_sym {
struct dc_eblock_hdr dc_sym_hdr;
- u_int8_t dc_sym_code;
- u_int8_t dc_sym_gpio_ctl[2];
- u_int8_t dc_sym_gpio_dat[2];
- u_int8_t dc_sym_cmd[2];
+ uint8_t dc_sym_code;
+ uint8_t dc_sym_gpio_ctl[2];
+ uint8_t dc_sym_gpio_dat[2];
+ uint8_t dc_sym_cmd[2];
};
-#define DC_SYM_CODE_100BT 0x03
-#define DC_SYM_CODE_100BT_FDX 0x05
-#define DC_SYM_CODE_100T4 0x06
-#define DC_SYM_CODE_100FX 0x07
-#define DC_SYM_CODE_100FX_FDX 0x08
+#define DC_SYM_CODE_100BT 0x03
+#define DC_SYM_CODE_100BT_FDX 0x05
+#define DC_SYM_CODE_100T4 0x06
+#define DC_SYM_CODE_100FX 0x07
+#define DC_SYM_CODE_100FX_FDX 0x08
struct dc_eblock_reset {
struct dc_eblock_hdr dc_reset_hdr;
- u_int8_t dc_reset_len;
-/* u_int16_t dc_reset_dat[n]; */
+ uint8_t dc_reset_len;
+/* uint16_t dc_reset_dat[n]; */
};
Index: projects/altix/sys/dev/ppc/ppc_pci.c
===================================================================
--- projects/altix/sys/dev/ppc/ppc_pci.c (revision 218875)
+++ projects/altix/sys/dev/ppc/ppc_pci.c (revision 218876)
@@ -1,112 +1,113 @@
/*-
* Copyright (c) 2006 Marcel Moolenaar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <dev/pci/pcivar.h>
#include <dev/ppbus/ppbconf.h>
#include <dev/ppbus/ppb_msq.h>
#include <dev/ppc/ppcvar.h>
#include <dev/ppc/ppcreg.h>
#include "ppbus_if.h"
static int ppc_pci_probe(device_t dev);
static device_method_t ppc_pci_methods[] = {
/* device interface */
DEVMETHOD(device_probe, ppc_pci_probe),
DEVMETHOD(device_attach, ppc_attach),
DEVMETHOD(device_detach, ppc_detach),
/* bus interface */
DEVMETHOD(bus_read_ivar, ppc_read_ivar),
DEVMETHOD(bus_write_ivar, ppc_write_ivar),
DEVMETHOD(bus_alloc_resource, ppc_alloc_resource),
DEVMETHOD(bus_release_resource, ppc_release_resource),
/* ppbus interface */
DEVMETHOD(ppbus_io, ppc_io),
DEVMETHOD(ppbus_exec_microseq, ppc_exec_microseq),
DEVMETHOD(ppbus_reset_epp, ppc_reset_epp),
DEVMETHOD(ppbus_setmode, ppc_setmode),
DEVMETHOD(ppbus_ecp_sync, ppc_ecp_sync),
DEVMETHOD(ppbus_read, ppc_read),
DEVMETHOD(ppbus_write, ppc_write),
{ 0, 0 }
};
static driver_t ppc_pci_driver = {
ppc_driver_name,
ppc_pci_methods,
sizeof(struct ppc_data),
};
struct pci_id {
uint32_t type;
const char *desc;
int rid;
};
static struct pci_id pci_ids[] = {
{ 0x1020131f, "SIIG Cyber Parallel PCI (10x family)", 0x18 },
{ 0x2020131f, "SIIG Cyber Parallel PCI (20x family)", 0x10 },
{ 0x05111407, "Lava SP BIDIR Parallel PCI", 0x10 },
{ 0x80001407, "Lava Computers 2SP-PCI parallel port", 0x10 },
{ 0x84031415, "Oxford Semiconductor OX12PCI840 Parallel port", 0x10 },
{ 0x95131415, "Oxford Semiconductor OX16PCI954 Parallel port", 0x10 },
{ 0x98059710, "NetMos NM9805 1284 Printer port", 0x10 },
+ { 0x98659710, "MosChip MCS9865 1284 Printer port", 0x10 },
{ 0x99019710, "MosChip MCS9901 PCIe to Peripheral Controller", 0x10 },
{ 0xffff }
};
static int
ppc_pci_probe(device_t dev)
{
struct pci_id *id;
uint32_t type;
type = pci_get_devid(dev);
id = pci_ids;
while (id->type != 0xffff && id->type != type)
id++;
if (id->type == 0xffff)
return (ENXIO);
device_set_desc(dev, id->desc);
return (ppc_probe(dev, id->rid));
}
DRIVER_MODULE(ppc, pci, ppc_pci_driver, ppc_devclass, 0, 0);
Index: projects/altix/sys/dev/usb/net/if_udav.c
===================================================================
--- projects/altix/sys/dev/usb/net/if_udav.c (revision 218875)
+++ projects/altix/sys/dev/usb/net/if_udav.c (revision 218876)
@@ -1,857 +1,861 @@
/* $NetBSD: if_udav.c,v 1.2 2003/09/04 15:17:38 tsutsui Exp $ */
/* $nabe: if_udav.c,v 1.3 2003/08/21 16:57:19 nabe Exp $ */
/* $FreeBSD$ */
/*-
* Copyright (c) 2003
* Shingo WATANABE <nabe@nabechan.org>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/*
* DM9601(DAVICOM USB to Ethernet MAC Controller with Integrated 10/100 PHY)
* The spec can be found at the following url.
* http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9601-DS-P01-930914.pdf
*/
/*
* TODO:
* Interrupt Endpoint support
* External PHYs
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/module.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
#include <sys/sysctl.h>
#include <sys/sx.h>
#include <sys/unistd.h>
#include <sys/callout.h>
#include <sys/malloc.h>
#include <sys/priv.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
#include "usbdevs.h"
#define USB_DEBUG_VAR udav_debug
#include <dev/usb/usb_debug.h>
#include <dev/usb/usb_process.h>
#include <dev/usb/net/usb_ethernet.h>
#include <dev/usb/net/if_udavreg.h>
/* prototypes */
static device_probe_t udav_probe;
static device_attach_t udav_attach;
static device_detach_t udav_detach;
static usb_callback_t udav_bulk_write_callback;
static usb_callback_t udav_bulk_read_callback;
static usb_callback_t udav_intr_callback;
static uether_fn_t udav_attach_post;
static uether_fn_t udav_init;
static uether_fn_t udav_stop;
static uether_fn_t udav_start;
static uether_fn_t udav_tick;
static uether_fn_t udav_setmulti;
static uether_fn_t udav_setpromisc;
static int udav_csr_read(struct udav_softc *, uint16_t, void *, int);
static int udav_csr_write(struct udav_softc *, uint16_t, void *, int);
static uint8_t udav_csr_read1(struct udav_softc *, uint16_t);
static int udav_csr_write1(struct udav_softc *, uint16_t, uint8_t);
static void udav_reset(struct udav_softc *);
static int udav_ifmedia_upd(struct ifnet *);
static void udav_ifmedia_status(struct ifnet *, struct ifmediareq *);
static miibus_readreg_t udav_miibus_readreg;
static miibus_writereg_t udav_miibus_writereg;
static miibus_statchg_t udav_miibus_statchg;
static const struct usb_config udav_config[UDAV_N_TRANSFER] = {
[UDAV_BULK_DT_WR] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.bufsize = (MCLBYTES + 2),
.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
.callback = udav_bulk_write_callback,
.timeout = 10000, /* 10 seconds */
},
[UDAV_BULK_DT_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.bufsize = (MCLBYTES + 3),
.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
.callback = udav_bulk_read_callback,
.timeout = 0, /* no timeout */
},
[UDAV_INTR_DT_RD] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
.bufsize = 0, /* use wMaxPacketSize */
.callback = udav_intr_callback,
},
};
static device_method_t udav_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, udav_probe),
DEVMETHOD(device_attach, udav_attach),
DEVMETHOD(device_detach, udav_detach),
/* bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_driver_added, bus_generic_driver_added),
/* MII interface */
DEVMETHOD(miibus_readreg, udav_miibus_readreg),
DEVMETHOD(miibus_writereg, udav_miibus_writereg),
DEVMETHOD(miibus_statchg, udav_miibus_statchg),
{0, 0}
};
static driver_t udav_driver = {
.name = "udav",
.methods = udav_methods,
.size = sizeof(struct udav_softc),
};
static devclass_t udav_devclass;
DRIVER_MODULE(udav, uhub, udav_driver, udav_devclass, NULL, 0);
DRIVER_MODULE(miibus, udav, miibus_driver, miibus_devclass, 0, 0);
MODULE_DEPEND(udav, uether, 1, 1, 1);
MODULE_DEPEND(udav, usb, 1, 1, 1);
MODULE_DEPEND(udav, ether, 1, 1, 1);
MODULE_DEPEND(udav, miibus, 1, 1, 1);
MODULE_VERSION(udav, 1);
static const struct usb_ether_methods udav_ue_methods = {
.ue_attach_post = udav_attach_post,
.ue_start = udav_start,
.ue_init = udav_init,
.ue_stop = udav_stop,
.ue_tick = udav_tick,
.ue_setmulti = udav_setmulti,
.ue_setpromisc = udav_setpromisc,
.ue_mii_upd = udav_ifmedia_upd,
.ue_mii_sts = udav_ifmedia_status,
};
#ifdef USB_DEBUG
static int udav_debug = 0;
SYSCTL_NODE(_hw_usb, OID_AUTO, udav, CTLFLAG_RW, 0, "USB udav");
SYSCTL_INT(_hw_usb_udav, OID_AUTO, debug, CTLFLAG_RW, &udav_debug, 0,
"Debug level");
#endif
#define UDAV_SETBIT(sc, reg, x) \
udav_csr_write1(sc, reg, udav_csr_read1(sc, reg) | (x))
#define UDAV_CLRBIT(sc, reg, x) \
udav_csr_write1(sc, reg, udav_csr_read1(sc, reg) & ~(x))
static const struct usb_device_id udav_devs[] = {
/* ShanTou DM9601 USB NIC */
{USB_VPI(USB_VENDOR_SHANTOU, USB_PRODUCT_SHANTOU_DM9601, 0)},
/* ShanTou ST268 USB NIC */
{USB_VPI(USB_VENDOR_SHANTOU, USB_PRODUCT_SHANTOU_ST268, 0)},
/* Corega USB-TXC */
{USB_VPI(USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB_TXC, 0)},
+ /* ShanTou AMD8515 USB NIC */
+ {USB_VPI(USB_VENDOR_SHANTOU, USB_PRODUCT_SHANTOU_ADM8515, 0)},
+ /* Kontron AG USB Ethernet */
+ {USB_VPI(USB_VENDOR_KONTRON, USB_PRODUCT_KONTRON_DM9601, 0)},
};
static void
udav_attach_post(struct usb_ether *ue)
{
struct udav_softc *sc = uether_getsc(ue);
/* reset the adapter */
udav_reset(sc);
/* Get Ethernet Address */
udav_csr_read(sc, UDAV_PAR, ue->ue_eaddr, ETHER_ADDR_LEN);
}
static int
udav_probe(device_t dev)
{
struct usb_attach_arg *uaa = device_get_ivars(dev);
if (uaa->usb_mode != USB_MODE_HOST)
return (ENXIO);
if (uaa->info.bConfigIndex != UDAV_CONFIG_INDEX)
return (ENXIO);
if (uaa->info.bIfaceIndex != UDAV_IFACE_INDEX)
return (ENXIO);
return (usbd_lookup_id_by_uaa(udav_devs, sizeof(udav_devs), uaa));
}
static int
udav_attach(device_t dev)
{
struct usb_attach_arg *uaa = device_get_ivars(dev);
struct udav_softc *sc = device_get_softc(dev);
struct usb_ether *ue = &sc->sc_ue;
uint8_t iface_index;
int error;
sc->sc_flags = USB_GET_DRIVER_INFO(uaa);
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
iface_index = UDAV_IFACE_INDEX;
error = usbd_transfer_setup(uaa->device, &iface_index,
sc->sc_xfer, udav_config, UDAV_N_TRANSFER, sc, &sc->sc_mtx);
if (error) {
device_printf(dev, "allocating USB transfers failed\n");
goto detach;
}
ue->ue_sc = sc;
ue->ue_dev = dev;
ue->ue_udev = uaa->device;
ue->ue_mtx = &sc->sc_mtx;
ue->ue_methods = &udav_ue_methods;
error = uether_ifattach(ue);
if (error) {
device_printf(dev, "could not attach interface\n");
goto detach;
}
return (0); /* success */
detach:
udav_detach(dev);
return (ENXIO); /* failure */
}
static int
udav_detach(device_t dev)
{
struct udav_softc *sc = device_get_softc(dev);
struct usb_ether *ue = &sc->sc_ue;
usbd_transfer_unsetup(sc->sc_xfer, UDAV_N_TRANSFER);
uether_ifdetach(ue);
mtx_destroy(&sc->sc_mtx);
return (0);
}
#if 0
static int
udav_mem_read(struct udav_softc *sc, uint16_t offset, void *buf,
int len)
{
struct usb_device_request req;
len &= 0xff;
req.bmRequestType = UT_READ_VENDOR_DEVICE;
req.bRequest = UDAV_REQ_MEM_READ;
USETW(req.wValue, 0x0000);
USETW(req.wIndex, offset);
USETW(req.wLength, len);
return (uether_do_request(&sc->sc_ue, &req, buf, 1000));
}
static int
udav_mem_write(struct udav_softc *sc, uint16_t offset, void *buf,
int len)
{
struct usb_device_request req;
len &= 0xff;
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
req.bRequest = UDAV_REQ_MEM_WRITE;
USETW(req.wValue, 0x0000);
USETW(req.wIndex, offset);
USETW(req.wLength, len);
return (uether_do_request(&sc->sc_ue, &req, buf, 1000));
}
static int
udav_mem_write1(struct udav_softc *sc, uint16_t offset,
uint8_t ch)
{
struct usb_device_request req;
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
req.bRequest = UDAV_REQ_MEM_WRITE1;
USETW(req.wValue, ch);
USETW(req.wIndex, offset);
USETW(req.wLength, 0x0000);
return (uether_do_request(&sc->sc_ue, &req, NULL, 1000));
}
#endif
static int
udav_csr_read(struct udav_softc *sc, uint16_t offset, void *buf, int len)
{
struct usb_device_request req;
len &= 0xff;
req.bmRequestType = UT_READ_VENDOR_DEVICE;
req.bRequest = UDAV_REQ_REG_READ;
USETW(req.wValue, 0x0000);
USETW(req.wIndex, offset);
USETW(req.wLength, len);
return (uether_do_request(&sc->sc_ue, &req, buf, 1000));
}
static int
udav_csr_write(struct udav_softc *sc, uint16_t offset, void *buf, int len)
{
struct usb_device_request req;
offset &= 0xff;
len &= 0xff;
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
req.bRequest = UDAV_REQ_REG_WRITE;
USETW(req.wValue, 0x0000);
USETW(req.wIndex, offset);
USETW(req.wLength, len);
return (uether_do_request(&sc->sc_ue, &req, buf, 1000));
}
static uint8_t
udav_csr_read1(struct udav_softc *sc, uint16_t offset)
{
uint8_t val;
udav_csr_read(sc, offset, &val, 1);
return (val);
}
static int
udav_csr_write1(struct udav_softc *sc, uint16_t offset,
uint8_t ch)
{
struct usb_device_request req;
offset &= 0xff;
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
req.bRequest = UDAV_REQ_REG_WRITE1;
USETW(req.wValue, ch);
USETW(req.wIndex, offset);
USETW(req.wLength, 0x0000);
return (uether_do_request(&sc->sc_ue, &req, NULL, 1000));
}
static void
udav_init(struct usb_ether *ue)
{
struct udav_softc *sc = ue->ue_sc;
struct ifnet *ifp = uether_getifp(&sc->sc_ue);
UDAV_LOCK_ASSERT(sc, MA_OWNED);
/*
* Cancel pending I/O
*/
udav_stop(ue);
/* set MAC address */
udav_csr_write(sc, UDAV_PAR, IF_LLADDR(ifp), ETHER_ADDR_LEN);
/* initialize network control register */
/* disable loopback */
UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_LBK0 | UDAV_NCR_LBK1);
/* Initialize RX control register */
UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_DIS_LONG | UDAV_RCR_DIS_CRC);
/* load multicast filter and update promiscious mode bit */
udav_setpromisc(ue);
/* enable RX */
UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_RXEN);
/* clear POWER_DOWN state of internal PHY */
UDAV_SETBIT(sc, UDAV_GPCR, UDAV_GPCR_GEP_CNTL0);
UDAV_CLRBIT(sc, UDAV_GPR, UDAV_GPR_GEPIO0);
usbd_xfer_set_stall(sc->sc_xfer[UDAV_BULK_DT_WR]);
ifp->if_drv_flags |= IFF_DRV_RUNNING;
udav_start(ue);
}
static void
udav_reset(struct udav_softc *sc)
{
int i;
/* Select PHY */
#if 1
/*
* XXX: force select internal phy.
* external phy routines are not tested.
*/
UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY);
#else
if (sc->sc_flags & UDAV_EXT_PHY)
UDAV_SETBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY);
else
UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY);
#endif
UDAV_SETBIT(sc, UDAV_NCR, UDAV_NCR_RST);
for (i = 0; i < UDAV_TX_TIMEOUT; i++) {
if (!(udav_csr_read1(sc, UDAV_NCR) & UDAV_NCR_RST))
break;
if (uether_pause(&sc->sc_ue, hz / 100))
break;
}
uether_pause(&sc->sc_ue, hz / 100);
}
#define UDAV_BITS 6
static void
udav_setmulti(struct usb_ether *ue)
{
struct udav_softc *sc = ue->ue_sc;
struct ifnet *ifp = uether_getifp(&sc->sc_ue);
struct ifmultiaddr *ifma;
uint8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
int h = 0;
UDAV_LOCK_ASSERT(sc, MA_OWNED);
if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL|UDAV_RCR_PRMSC);
return;
}
/* first, zot all the existing hash bits */
memset(hashtbl, 0x00, sizeof(hashtbl));
hashtbl[7] |= 0x80; /* broadcast address */
udav_csr_write(sc, UDAV_MAR, hashtbl, sizeof(hashtbl));
/* now program new ones */
if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
{
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
h = ether_crc32_be(LLADDR((struct sockaddr_dl *)
ifma->ifma_addr), ETHER_ADDR_LEN) >> 26;
hashtbl[h / 8] |= 1 << (h % 8);
}
if_maddr_runlock(ifp);
/* disable all multicast */
UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_ALL);
/* write hash value to the register */
udav_csr_write(sc, UDAV_MAR, hashtbl, sizeof(hashtbl));
}
static void
udav_setpromisc(struct usb_ether *ue)
{
struct udav_softc *sc = ue->ue_sc;
struct ifnet *ifp = uether_getifp(&sc->sc_ue);
uint8_t rxmode;
rxmode = udav_csr_read1(sc, UDAV_RCR);
rxmode &= ~(UDAV_RCR_ALL | UDAV_RCR_PRMSC);
if (ifp->if_flags & IFF_PROMISC)
rxmode |= UDAV_RCR_ALL | UDAV_RCR_PRMSC;
else if (ifp->if_flags & IFF_ALLMULTI)
rxmode |= UDAV_RCR_ALL;
/* write new mode bits */
udav_csr_write1(sc, UDAV_RCR, rxmode);
}
static void
udav_start(struct usb_ether *ue)
{
struct udav_softc *sc = ue->ue_sc;
/*
* start the USB transfers, if not already started:
*/
usbd_transfer_start(sc->sc_xfer[UDAV_INTR_DT_RD]);
usbd_transfer_start(sc->sc_xfer[UDAV_BULK_DT_RD]);
usbd_transfer_start(sc->sc_xfer[UDAV_BULK_DT_WR]);
}
static void
udav_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct udav_softc *sc = usbd_xfer_softc(xfer);
struct ifnet *ifp = uether_getifp(&sc->sc_ue);
struct usb_page_cache *pc;
struct mbuf *m;
int extra_len;
int temp_len;
uint8_t buf[2];
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
DPRINTFN(11, "transfer complete\n");
ifp->if_opackets++;
/* FALLTHROUGH */
case USB_ST_SETUP:
tr_setup:
if ((sc->sc_flags & UDAV_FLAG_LINK) == 0) {
/*
* don't send anything if there is no link !
*/
return;
}
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
return;
if (m->m_pkthdr.len > MCLBYTES)
m->m_pkthdr.len = MCLBYTES;
if (m->m_pkthdr.len < UDAV_MIN_FRAME_LEN) {
extra_len = UDAV_MIN_FRAME_LEN - m->m_pkthdr.len;
} else {
extra_len = 0;
}
temp_len = (m->m_pkthdr.len + extra_len);
/*
* the frame length is specified in the first 2 bytes of the
* buffer
*/
buf[0] = (uint8_t)(temp_len);
buf[1] = (uint8_t)(temp_len >> 8);
temp_len += 2;
pc = usbd_xfer_get_frame(xfer, 0);
usbd_copy_in(pc, 0, buf, 2);
usbd_m_copy_in(pc, 2, m, 0, m->m_pkthdr.len);
if (extra_len)
usbd_frame_zero(pc, temp_len - extra_len, extra_len);
/*
* if there's a BPF listener, bounce a copy
* of this frame to him:
*/
BPF_MTAP(ifp, m);
m_freem(m);
usbd_xfer_set_frame_len(xfer, 0, temp_len);
usbd_transfer_submit(xfer);
return;
default: /* Error */
DPRINTFN(11, "transfer error, %s\n",
usbd_errstr(error));
ifp->if_oerrors++;
if (error != USB_ERR_CANCELLED) {
/* try to clear stall first */
usbd_xfer_set_stall(xfer);
goto tr_setup;
}
return;
}
}
static void
udav_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct udav_softc *sc = usbd_xfer_softc(xfer);
struct usb_ether *ue = &sc->sc_ue;
struct ifnet *ifp = uether_getifp(ue);
struct usb_page_cache *pc;
struct udav_rxpkt stat;
int len;
int actlen;
usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
if (actlen < sizeof(stat) + ETHER_CRC_LEN) {
ifp->if_ierrors++;
goto tr_setup;
}
pc = usbd_xfer_get_frame(xfer, 0);
usbd_copy_out(pc, 0, &stat, sizeof(stat));
actlen -= sizeof(stat);
len = min(actlen, le16toh(stat.pktlen));
len -= ETHER_CRC_LEN;
if (stat.rxstat & UDAV_RSR_LCS) {
ifp->if_collisions++;
goto tr_setup;
}
if (stat.rxstat & UDAV_RSR_ERR) {
ifp->if_ierrors++;
goto tr_setup;
}
uether_rxbuf(ue, pc, sizeof(stat), len);
/* FALLTHROUGH */
case USB_ST_SETUP:
tr_setup:
usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
usbd_transfer_submit(xfer);
uether_rxflush(ue);
return;
default: /* Error */
DPRINTF("bulk read error, %s\n",
usbd_errstr(error));
if (error != USB_ERR_CANCELLED) {
/* try to clear stall first */
usbd_xfer_set_stall(xfer);
goto tr_setup;
}
return;
}
}
static void
udav_intr_callback(struct usb_xfer *xfer, usb_error_t error)
{
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
case USB_ST_SETUP:
tr_setup:
usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
usbd_transfer_submit(xfer);
return;
default: /* Error */
if (error != USB_ERR_CANCELLED) {
/* try to clear stall first */
usbd_xfer_set_stall(xfer);
goto tr_setup;
}
return;
}
}
static void
udav_stop(struct usb_ether *ue)
{
struct udav_softc *sc = ue->ue_sc;
struct ifnet *ifp = uether_getifp(&sc->sc_ue);
UDAV_LOCK_ASSERT(sc, MA_OWNED);
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
sc->sc_flags &= ~UDAV_FLAG_LINK;
/*
* stop all the transfers, if not already stopped:
*/
usbd_transfer_stop(sc->sc_xfer[UDAV_BULK_DT_WR]);
usbd_transfer_stop(sc->sc_xfer[UDAV_BULK_DT_RD]);
usbd_transfer_stop(sc->sc_xfer[UDAV_INTR_DT_RD]);
udav_reset(sc);
}
static int
udav_ifmedia_upd(struct ifnet *ifp)
{
struct udav_softc *sc = ifp->if_softc;
struct mii_data *mii = GET_MII(sc);
UDAV_LOCK_ASSERT(sc, MA_OWNED);
sc->sc_flags &= ~UDAV_FLAG_LINK;
if (mii->mii_instance) {
struct mii_softc *miisc;
LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
mii_phy_reset(miisc);
}
mii_mediachg(mii);
return (0);
}
static void
udav_ifmedia_status(struct ifnet *ifp, struct ifmediareq *ifmr)
{
struct udav_softc *sc = ifp->if_softc;
struct mii_data *mii = GET_MII(sc);
UDAV_LOCK(sc);
mii_pollstat(mii);
UDAV_UNLOCK(sc);
ifmr->ifm_active = mii->mii_media_active;
ifmr->ifm_status = mii->mii_media_status;
}
static void
udav_tick(struct usb_ether *ue)
{
struct udav_softc *sc = ue->ue_sc;
struct mii_data *mii = GET_MII(sc);
UDAV_LOCK_ASSERT(sc, MA_OWNED);
mii_tick(mii);
if ((sc->sc_flags & UDAV_FLAG_LINK) == 0
&& mii->mii_media_status & IFM_ACTIVE &&
IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
sc->sc_flags |= UDAV_FLAG_LINK;
udav_start(ue);
}
}
static int
udav_miibus_readreg(device_t dev, int phy, int reg)
{
struct udav_softc *sc = device_get_softc(dev);
uint16_t data16;
uint8_t val[2];
int locked;
/* XXX: one PHY only for the internal PHY */
if (phy != 0)
return (0);
locked = mtx_owned(&sc->sc_mtx);
if (!locked)
UDAV_LOCK(sc);
/* select internal PHY and set PHY register address */
udav_csr_write1(sc, UDAV_EPAR,
UDAV_EPAR_PHY_ADR0 | (reg & UDAV_EPAR_EROA_MASK));
/* select PHY operation and start read command */
udav_csr_write1(sc, UDAV_EPCR, UDAV_EPCR_EPOS | UDAV_EPCR_ERPRR);
/* XXX: should we wait? */
/* end read command */
UDAV_CLRBIT(sc, UDAV_EPCR, UDAV_EPCR_ERPRR);
/* retrieve the result from data registers */
udav_csr_read(sc, UDAV_EPDRL, val, 2);
data16 = (val[0] | (val[1] << 8));
DPRINTFN(11, "phy=%d reg=0x%04x => 0x%04x\n",
phy, reg, data16);
if (!locked)
UDAV_UNLOCK(sc);
return (data16);
}
static int
udav_miibus_writereg(device_t dev, int phy, int reg, int data)
{
struct udav_softc *sc = device_get_softc(dev);
uint8_t val[2];
int locked;
/* XXX: one PHY only for the internal PHY */
if (phy != 0)
return (0);
locked = mtx_owned(&sc->sc_mtx);
if (!locked)
UDAV_LOCK(sc);
/* select internal PHY and set PHY register address */
udav_csr_write1(sc, UDAV_EPAR,
UDAV_EPAR_PHY_ADR0 | (reg & UDAV_EPAR_EROA_MASK));
/* put the value to the data registers */
val[0] = (data & 0xff);
val[1] = (data >> 8) & 0xff;
udav_csr_write(sc, UDAV_EPDRL, val, 2);
/* select PHY operation and start write command */
udav_csr_write1(sc, UDAV_EPCR, UDAV_EPCR_EPOS | UDAV_EPCR_ERPRW);
/* XXX: should we wait? */
/* end write command */
UDAV_CLRBIT(sc, UDAV_EPCR, UDAV_EPCR_ERPRW);
if (!locked)
UDAV_UNLOCK(sc);
return (0);
}
static void
udav_miibus_statchg(device_t dev)
{
/* nothing to do */
}
Index: projects/altix/sys/dev/usb/usbdevs
===================================================================
--- projects/altix/sys/dev/usb/usbdevs (revision 218875)
+++ projects/altix/sys/dev/usb/usbdevs (revision 218876)
@@ -1,3451 +1,3456 @@
$FreeBSD$
/* $NetBSD: usbdevs,v 1.392 2004/12/29 08:38:44 imp Exp $ */
/*-
* Copyright (c) 1998-2004 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Lennart Augustsson (lennart@augustsson.net) at
* Carlstedt Research & Technology.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* List of known USB vendors
*
* USB.org publishes a VID list of USB-IF member companies at
* http://www.usb.org/developers/tools
* Note that it does not show companies that have obtained a Vendor ID
* without becoming full members.
*
* Please note that these IDs do not do anything. Adding an ID here and
* regenerating the usbdevs.h and usbdevs_data.h only makes a symbolic name
* available to the source code and does not change any functionality, nor
* does it make your device available to a specific driver.
* It will however make the descriptive string available if a device does not
* provide the string itself.
*
* After adding a vendor ID VNDR and a product ID PRDCT you will have the
* following extra defines:
* #define USB_VENDOR_VNDR 0x????
* #define USB_PRODUCT_VNDR_PRDCT 0x????
*
* You may have to add these defines to the respective probe routines to
* make the device recognised by the appropriate device driver.
*/
vendor UNKNOWN1 0x0053 Unknown vendor
vendor UNKNOWN2 0x0105 Unknown vendor
vendor EGALAX2 0x0123 eGalax, Inc.
vendor CHIPSBANK 0x0204 Chipsbank Microelectronics Co.
vendor HUMAX 0x02ad HUMAX
vendor LTS 0x0386 LTS
vendor BWCT 0x03da Bernd Walter Computer Technology
vendor AOX 0x03e8 AOX
vendor THESYS 0x03e9 Thesys
vendor DATABROADCAST 0x03ea Data Broadcasting
vendor ATMEL 0x03eb Atmel
vendor IWATSU 0x03ec Iwatsu America
vendor MITSUMI 0x03ee Mitsumi
vendor HP 0x03f0 Hewlett Packard
vendor GENOA 0x03f1 Genoa
vendor OAK 0x03f2 Oak
vendor ADAPTEC 0x03f3 Adaptec
vendor DIEBOLD 0x03f4 Diebold
vendor SIEMENSELECTRO 0x03f5 Siemens Electromechanical
vendor EPSONIMAGING 0x03f8 Epson Imaging
vendor KEYTRONIC 0x03f9 KeyTronic
vendor OPTI 0x03fb OPTi
vendor ELITEGROUP 0x03fc Elitegroup
vendor XILINX 0x03fd Xilinx
vendor FARALLON 0x03fe Farallon Communications
vendor NATIONAL 0x0400 National Semiconductor
vendor NATIONALREG 0x0401 National Registry
vendor ACERLABS 0x0402 Acer Labs
vendor FTDI 0x0403 Future Technology Devices
vendor NCR 0x0404 NCR
vendor SYNOPSYS2 0x0405 Synopsys
vendor FUJITSUICL 0x0406 Fujitsu-ICL
vendor FUJITSU2 0x0407 Fujitsu Personal Systems
vendor QUANTA 0x0408 Quanta
vendor NEC 0x0409 NEC
vendor KODAK 0x040a Eastman Kodak
vendor WELTREND 0x040b Weltrend
vendor VIA 0x040d VIA
vendor MCCI 0x040e MCCI
vendor MELCO 0x0411 Melco
vendor LEADTEK 0x0413 Leadtek
vendor WINBOND 0x0416 Winbond
vendor PHOENIX 0x041a Phoenix
vendor CREATIVE 0x041e Creative Labs
vendor NOKIA 0x0421 Nokia
vendor ADI 0x0422 ADI Systems
vendor CATC 0x0423 Computer Access Technology
vendor SMC2 0x0424 Standard Microsystems
vendor MOTOROLA_HK 0x0425 Motorola HK
vendor GRAVIS 0x0428 Advanced Gravis Computer
vendor CIRRUSLOGIC 0x0429 Cirrus Logic
vendor INNOVATIVE 0x042c Innovative Semiconductors
vendor MOLEX 0x042f Molex
vendor SUN 0x0430 Sun Microsystems
vendor UNISYS 0x0432 Unisys
vendor TAUGA 0x0436 Taugagreining HF
vendor AMD 0x0438 Advanced Micro Devices
vendor LEXMARK 0x043d Lexmark International
vendor LG 0x043e LG Electronics
vendor NANAO 0x0440 NANAO
vendor GATEWAY 0x0443 Gateway 2000
vendor NMB 0x0446 NMB
vendor ALPS 0x044e Alps Electric
vendor THRUST 0x044f Thrustmaster
vendor TI 0x0451 Texas Instruments
vendor ANALOGDEVICES 0x0456 Analog Devices
vendor SIS 0x0457 Silicon Integrated Systems Corp.
vendor KYE 0x0458 KYE Systems
vendor DIAMOND2 0x045a Diamond (Supra)
vendor RENESAS 0x045b Renesas
vendor MICROSOFT 0x045e Microsoft
vendor PRIMAX 0x0461 Primax Electronics
vendor MGE 0x0463 MGE UPS Systems
vendor AMP 0x0464 AMP
vendor CHERRY 0x046a Cherry Mikroschalter
vendor MEGATRENDS 0x046b American Megatrends
vendor LOGITECH 0x046d Logitech
vendor BTC 0x046e Behavior Tech. Computer
vendor PHILIPS 0x0471 Philips
vendor SUN2 0x0472 Sun Microsystems (offical)
vendor SANYO 0x0474 Sanyo Electric
vendor SEAGATE 0x0477 Seagate
vendor CONNECTIX 0x0478 Connectix
vendor SEMTECH 0x047a Semtech
vendor KENSINGTON 0x047d Kensington
vendor LUCENT 0x047e Lucent
vendor PLANTRONICS 0x047f Plantronics
vendor KYOCERA 0x0482 Kyocera Wireless Corp.
vendor STMICRO 0x0483 STMicroelectronics
vendor FOXCONN 0x0489 Foxconn
vendor MEIZU 0x0492 Meizu Electronics
vendor YAMAHA 0x0499 YAMAHA
vendor COMPAQ 0x049f Compaq
vendor HITACHI 0x04a4 Hitachi
vendor ACERP 0x04a5 Acer Peripherals
vendor DAVICOM 0x04a6 Davicom
vendor VISIONEER 0x04a7 Visioneer
vendor CANON 0x04a9 Canon
vendor NIKON 0x04b0 Nikon
vendor PAN 0x04b1 Pan International
vendor IBM 0x04b3 IBM
vendor CYPRESS 0x04b4 Cypress Semiconductor
vendor ROHM 0x04b5 ROHM
vendor COMPAL 0x04b7 Compal
vendor EPSON 0x04b8 Seiko Epson
vendor RAINBOW 0x04b9 Rainbow Technologies
vendor IODATA 0x04bb I-O Data
vendor TDK 0x04bf TDK
vendor 3COMUSR 0x04c1 U.S. Robotics
vendor METHODE 0x04c2 Methode Electronics Far East
vendor MAXISWITCH 0x04c3 Maxi Switch
vendor LOCKHEEDMER 0x04c4 Lockheed Martin Energy Research
vendor FUJITSU 0x04c5 Fujitsu
vendor TOSHIBAAM 0x04c6 Toshiba America
vendor MICROMACRO 0x04c7 Micro Macro Technologies
vendor KONICA 0x04c8 Konica
vendor LITEON 0x04ca Lite-On Technology
vendor FUJIPHOTO 0x04cb Fuji Photo Film
vendor PHILIPSSEMI 0x04cc Philips Semiconductors
vendor TATUNG 0x04cd Tatung Co. Of America
vendor SCANLOGIC 0x04ce ScanLogic
vendor MYSON 0x04cf Myson Technology
vendor DIGI2 0x04d0 Digi
vendor ITTCANON 0x04d1 ITT Canon
vendor ALTEC 0x04d2 Altec Lansing
vendor LSI 0x04d4 LSI
vendor MENTORGRAPHICS 0x04d6 Mentor Graphics
vendor ITUNERNET 0x04d8 I-Tuner Networks
vendor HOLTEK 0x04d9 Holtek Semiconductor, Inc.
vendor PANASONIC 0x04da Panasonic (Matsushita)
vendor HUANHSIN 0x04dc Huan Hsin
vendor SHARP 0x04dd Sharp
vendor IIYAMA 0x04e1 Iiyama
vendor SHUTTLE 0x04e6 Shuttle Technology
vendor ELO 0x04e7 Elo TouchSystems
vendor SAMSUNG 0x04e8 Samsung Electronics
vendor NORTHSTAR 0x04eb Northstar
vendor TOKYOELECTRON 0x04ec Tokyo Electron
vendor ANNABOOKS 0x04ed Annabooks
vendor JVC 0x04f1 JVC
vendor CHICONY 0x04f2 Chicony Electronics
vendor ELAN 0x04f3 Elan
vendor NEWNEX 0x04f7 Newnex
vendor BROTHER 0x04f9 Brother Industries
vendor DALLAS 0x04fa Dallas Semiconductor
vendor AIPTEK2 0x04fc AIPTEK International
vendor PFU 0x04fe PFU
vendor FUJIKURA 0x0501 Fujikura/DDK
vendor ACER 0x0502 Acer
vendor 3COM 0x0506 3Com
vendor HOSIDEN 0x0507 Hosiden Corporation
vendor AZTECH 0x0509 Aztech Systems
vendor BELKIN 0x050d Belkin Components
vendor KAWATSU 0x050f Kawatsu Semiconductor
vendor FCI 0x0514 FCI
vendor LONGWELL 0x0516 Longwell
vendor COMPOSITE 0x0518 Composite
vendor STAR 0x0519 Star Micronics
vendor APC 0x051d American Power Conversion
vendor SCIATLANTA 0x051e Scientific Atlanta
vendor TSM 0x0520 TSM
vendor CONNECTEK 0x0522 Advanced Connectek USA
vendor NETCHIP 0x0525 NetChip Technology
vendor ALTRA 0x0527 ALTRA
vendor ATI 0x0528 ATI Technologies
vendor AKS 0x0529 Aladdin Knowledge Systems
vendor TEKOM 0x052b Tekom
vendor CANONDEV 0x052c Canon
vendor WACOMTECH 0x0531 Wacom
vendor INVENTEC 0x0537 Inventec
vendor SHYHSHIUN 0x0539 Shyh Shiun Terminals
vendor PREHWERKE 0x053a Preh Werke Gmbh & Co. KG
vendor SYNOPSYS 0x053f Synopsys
vendor UNIACCESS 0x0540 Universal Access
vendor VIEWSONIC 0x0543 ViewSonic
vendor XIRLINK 0x0545 Xirlink
vendor ANCHOR 0x0547 Anchor Chips
vendor SONY 0x054c Sony
vendor FUJIXEROX 0x0550 Fuji Xerox
vendor VISION 0x0553 VLSI Vision
vendor ASAHIKASEI 0x0556 Asahi Kasei Microsystems
vendor ATEN 0x0557 ATEN International
vendor SAMSUNG2 0x055d Samsung Electronics
vendor MUSTEK 0x055f Mustek Systems
vendor TELEX 0x0562 Telex Communications
vendor CHINON 0x0564 Chinon
vendor PERACOM 0x0565 Peracom Networks
vendor ALCOR2 0x0566 Alcor Micro
vendor XYRATEX 0x0567 Xyratex
vendor WACOM 0x056a WACOM
vendor ETEK 0x056c e-TEK Labs
vendor EIZO 0x056d EIZO
vendor ELECOM 0x056e Elecom
vendor CONEXANT 0x0572 Conexant
vendor HAUPPAUGE 0x0573 Hauppauge Computer Works
vendor BAFO 0x0576 BAFO/Quality Computer Accessories
vendor YEDATA 0x057b Y-E Data
vendor AVM 0x057c AVM
vendor QUICKSHOT 0x057f Quickshot
vendor ROLAND 0x0582 Roland
vendor ROCKFIRE 0x0583 Rockfire
vendor RATOC 0x0584 RATOC Systems
vendor ZYXEL 0x0586 ZyXEL Communication
vendor INFINEON 0x058b Infineon
vendor MICREL 0x058d Micrel
vendor ALCOR 0x058f Alcor Micro
vendor OMRON 0x0590 OMRON
vendor ZORAN 0x0595 Zoran Microelectronics
vendor NIIGATA 0x0598 Niigata
vendor IOMEGA 0x059b Iomega
vendor ATREND 0x059c A-Trend Technology
vendor AID 0x059d Advanced Input Devices
vendor LACIE 0x059f LaCie
vendor FUJIFILM 0x05a2 Fuji Film
vendor ARC 0x05a3 ARC
vendor ORTEK 0x05a4 Ortek
vendor CISCOLINKSYS3 0x05a6 Cisco-Linksys
vendor BOSE 0x05a7 Bose
vendor OMNIVISION 0x05a9 OmniVision
vendor INSYSTEM 0x05ab In-System Design
vendor APPLE 0x05ac Apple Computer
vendor YCCABLE 0x05ad Y.C. Cable
vendor DIGITALPERSONA 0x05ba DigitalPersona
vendor 3G 0x05bc 3G Green Green Globe
vendor RAFI 0x05bd RAFI
vendor TYCO 0x05be Tyco
vendor KAWASAKI 0x05c1 Kawasaki
vendor DIGI 0x05c5 Digi International
vendor QUALCOMM2 0x05c6 Qualcomm
vendor QTRONIX 0x05c7 Qtronix
vendor FOXLINK 0x05c8 Foxlink
vendor RICOH 0x05ca Ricoh
vendor ELSA 0x05cc ELSA
vendor SCIWORX 0x05ce sci-worx
vendor BRAINBOXES 0x05d1 Brainboxes Limited
vendor ULTIMA 0x05d8 Ultima
vendor AXIOHM 0x05d9 Axiohm Transaction Solutions
vendor MICROTEK 0x05da Microtek
vendor SUNTAC 0x05db SUN Corporation
vendor LEXAR 0x05dc Lexar Media
vendor ADDTRON 0x05dd Addtron
vendor SYMBOL 0x05e0 Symbol Technologies
vendor SYNTEK 0x05e1 Syntek
vendor GENESYS 0x05e3 Genesys Logic
vendor FUJI 0x05e5 Fuji Electric
vendor KEITHLEY 0x05e6 Keithley Instruments
vendor EIZONANAO 0x05e7 EIZO Nanao
vendor KLSI 0x05e9 Kawasaki LSI
vendor FFC 0x05eb FFC
vendor ANKO 0x05ef Anko Electronic
vendor PIENGINEERING 0x05f3 P.I. Engineering
vendor AOC 0x05f6 AOC International
vendor CHIC 0x05fe Chic Technology
vendor BARCO 0x0600 Barco Display Systems
vendor BRIDGE 0x0607 Bridge Information
vendor SOLIDYEAR 0x060b Solid Year
vendor BIORAD 0x0614 Bio-Rad Laboratories
vendor MACALLY 0x0618 Macally
vendor ACTLABS 0x061c Act Labs
vendor ALARIS 0x0620 Alaris
vendor APEX 0x0624 Apex
vendor CREATIVE3 0x062a Creative Labs
vendor VIVITAR 0x0636 Vivitar
vendor GUNZE 0x0637 Gunze Electronics USA
vendor AVISION 0x0638 Avision
vendor TEAC 0x0644 TEAC
vendor SGI 0x065e Silicon Graphics
vendor SANWASUPPLY 0x0663 Sanwa Supply
vendor MEGATEC 0x0665 Megatec
vendor LINKSYS 0x066b Linksys
vendor ACERSA 0x066e Acer Semiconductor America
vendor SIGMATEL 0x066f Sigmatel
vendor DRAYTEK 0x0675 DrayTek
vendor AIWA 0x0677 Aiwa
vendor ACARD 0x0678 ACARD Technology
vendor PROLIFIC 0x067b Prolific Technology
vendor SIEMENS 0x067c Siemens
vendor AVANCELOGIC 0x0680 Avance Logic
vendor SIEMENS2 0x0681 Siemens
vendor MINOLTA 0x0686 Minolta
vendor CHPRODUCTS 0x068e CH Products
vendor HAGIWARA 0x0693 Hagiwara Sys-Com
vendor CTX 0x0698 Chuntex
vendor ASKEY 0x069a Askey Computer
vendor SAITEK 0x06a3 Saitek
vendor ALCATELT 0x06b9 Alcatel Telecom
vendor AGFA 0x06bd AGFA-Gevaert
vendor ASIAMD 0x06be Asia Microelectronic Development
vendor BIZLINK 0x06c4 Bizlink International
vendor KEYSPAN 0x06cd Keyspan / InnoSys Inc.
vendor AASHIMA 0x06d6 Aashima Technology
vendor LIEBERT 0x06da Liebert
vendor MULTITECH 0x06e0 MultiTech
vendor ADS 0x06e1 ADS Technologies
vendor ALCATELM 0x06e4 Alcatel Microelectronics
vendor SIRIUS 0x06ea Sirius Technologies
vendor GUILLEMOT 0x06f8 Guillemot
vendor BOSTON 0x06fd Boston Acoustics
vendor SMC 0x0707 Standard Microsystems
vendor PUTERCOM 0x0708 Putercom
vendor MCT 0x0711 MCT
vendor IMATION 0x0718 Imation
vendor TECLAST 0x071b Teclast
vendor SONYERICSSON 0x0731 Sony Ericsson
vendor EICON 0x0734 Eicon Networks
vendor SYNTECH 0x0745 Syntech Information
vendor DIGITALSTREAM 0x074e Digital Stream
vendor AUREAL 0x0755 Aureal Semiconductor
vendor MIDIMAN 0x0763 Midiman
vendor CYBERPOWER 0x0764 Cyber Power Systems, Inc.
vendor SURECOM 0x0769 Surecom Technology
vendor HIDGLOBAL 0x076b HID Global
vendor LINKSYS2 0x077b Linksys
vendor GRIFFIN 0x077d Griffin Technology
vendor SANDISK 0x0781 SanDisk
vendor JENOPTIK 0x0784 Jenoptik
vendor LOGITEC 0x0789 Logitec
vendor NOKIA2 0x078b Nokia
vendor BRIMAX 0x078e Brimax
vendor AXIS 0x0792 Axis Communications
vendor ABL 0x0794 ABL Electronics
vendor SAGEM 0x079b Sagem
vendor SUNCOMM 0x079c Sun Communications, Inc.
vendor ALFADATA 0x079d Alfadata Computer
vendor NATIONALTECH 0x07a2 National Technical Systems
vendor ONNTO 0x07a3 Onnto
vendor BE 0x07a4 Be
vendor ADMTEK 0x07a6 ADMtek
vendor COREGA 0x07aa Corega
vendor FREECOM 0x07ab Freecom
vendor MICROTECH 0x07af Microtech
vendor GENERALINSTMNTS 0x07b2 General Instruments (Motorola)
vendor OLYMPUS 0x07b4 Olympus
vendor ABOCOM 0x07b8 AboCom Systems
vendor KEISOKUGIKEN 0x07c1 Keisokugiken
vendor ONSPEC 0x07c4 OnSpec
vendor APG 0x07c5 APG Cash Drawer
vendor BUG 0x07c8 B.U.G.
vendor ALLIEDTELESYN 0x07c9 Allied Telesyn International
vendor AVERMEDIA 0x07ca AVerMedia Technologies
vendor SIIG 0x07cc SIIG
vendor CASIO 0x07cf CASIO
vendor DLINK2 0x07d1 D-Link
vendor APTIO 0x07d2 Aptio Products
vendor ARASAN 0x07da Arasan Chip Systems
vendor ALLIEDCABLE 0x07e6 Allied Cable
vendor STSN 0x07ef STSN
vendor CENTURY 0x07f7 Century Corp
vendor NEWLINK 0x07ff NEWlink
vendor ZOOM 0x0803 Zoom Telephonics
vendor PCS 0x0810 Personal Communication Systems
vendor ALPHASMART 0x081e AlphaSmart, Inc.
vendor BROADLOGIC 0x0827 BroadLogic
vendor HANDSPRING 0x082d Handspring
vendor PALM 0x0830 Palm Computing
vendor SOURCENEXT 0x0833 SOURCENEXT
vendor ACTIONSTAR 0x0835 Action Star Enterprise
vendor SAMSUNG_TECHWIN 0x0839 Samsung Techwin
vendor ACCTON 0x083a Accton Technology
vendor DIAMOND 0x0841 Diamond
vendor NETGEAR 0x0846 BayNETGEAR
vendor TOPRE 0x0853 Topre Corporation
vendor ACTIVEWIRE 0x0854 ActiveWire
vendor BBELECTRONICS 0x0856 B&B Electronics
vendor PORTGEAR 0x085a PortGear
vendor NETGEAR2 0x0864 Netgear
vendor SYSTEMTALKS 0x086e System Talks
vendor METRICOM 0x0870 Metricom
vendor ADESSOKBTEK 0x087c ADESSO/Kbtek America
vendor JATON 0x087d Jaton
vendor APT 0x0880 APT Technologies
vendor BOCARESEARCH 0x0885 Boca Research
vendor ANDREA 0x08a8 Andrea Electronics
vendor BURRBROWN 0x08bb Burr-Brown Japan
vendor 2WIRE 0x08c8 2Wire
vendor AIPTEK 0x08ca AIPTEK International
vendor SMARTBRIDGES 0x08d1 SmartBridges
vendor FUJITSUSIEMENS 0x08d4 Fujitsu-Siemens
vendor BILLIONTON 0x08dd Billionton Systems
vendor GEMALTO 0x08e6 Gemalto SA
vendor EXTENDED 0x08e9 Extended Systems
vendor MSYSTEMS 0x08ec M-Systems
vendor DIGIANSWER 0x08fd Digianswer
vendor AUTHENTEC 0x08ff AuthenTec
vendor AUDIOTECHNICA 0x0909 Audio-Technica
vendor TRUMPION 0x090a Trumpion Microelectronics
vendor FEIYA 0x090c Feiya
vendor ALATION 0x0910 Alation Systems
vendor GLOBESPAN 0x0915 Globespan
vendor CONCORDCAMERA 0x0919 Concord Camera
vendor GARMIN 0x091e Garmin International
vendor GOHUBS 0x0921 GoHubs
vendor XEROX 0x0924 Xerox
vendor BIOMETRIC 0x0929 American Biometric Company
vendor TOSHIBA 0x0930 Toshiba
vendor PLEXTOR 0x093b Plextor
vendor INTREPIDCS 0x093c Intrepid
vendor YANO 0x094f Yano
vendor KINGSTON 0x0951 Kingston Technology
vendor BLUEWATER 0x0956 BlueWater Systems
vendor AGILENT 0x0957 Agilent Technologies
vendor GUDE 0x0959 Gude ADS
vendor PORTSMITH 0x095a Portsmith
vendor ACERW 0x0967 Acer
vendor ADIRONDACK 0x0976 Adirondack Wire & Cable
vendor BECKHOFF 0x0978 Beckhoff
vendor MINDSATWORK 0x097a Minds At Work
vendor POINTCHIPS 0x09a6 PointChips
vendor INTERSIL 0x09aa Intersil
vendor ALTIUS 0x09b3 Altius Solutions
vendor ARRIS 0x09c1 Arris Interactive
vendor ACTIVCARD 0x09c3 ACTIVCARD
vendor ACTISYS 0x09c4 ACTiSYS
vendor NOVATEL2 0x09d7 Novatel Wireless
vendor AFOURTECH 0x09da A-FOUR TECH
vendor AIMEX 0x09dc AIMEX
vendor ADDONICS 0x09df Addonics Technologies
vendor AKAI 0x09e8 AKAI professional M.I.
vendor ARESCOM 0x09f5 ARESCOM
vendor BAY 0x09f9 Bay Associates
vendor ALTERA 0x09fb Altera
vendor CSR 0x0a12 Cambridge Silicon Radio
vendor TREK 0x0a16 Trek Technology
vendor ASAHIOPTICAL 0x0a17 Asahi Optical
vendor BOCASYSTEMS 0x0a43 Boca Systems
vendor SHANTOU 0x0a46 ShanTou
vendor MEDIAGEAR 0x0a48 MediaGear
vendor BROADCOM 0x0a5c Broadcom
vendor GREENHOUSE 0x0a6b GREENHOUSE
vendor GEOCAST 0x0a79 Geocast Network Systems
vendor IDQUANTIQUE 0x0aba id Quantique
vendor ZYDAS 0x0ace Zydas Technology Corporation
vendor NEODIO 0x0aec Neodio
vendor OPTION 0x0af0 Option N.V.
vendor ASUS 0x0b05 ASUSTeK Computer
vendor TODOS 0x0b0c Todos Data System
vendor SIIG2 0x0b39 SIIG
vendor TEKRAM 0x0b3b Tekram Technology
vendor HAL 0x0b41 HAL Corporation
vendor EMS 0x0b43 EMS Production
vendor NEC2 0x0b62 NEC
vendor ADLINK 0x0b63 ADLINK Technoligy, Inc.
vendor ATI2 0x0b6f ATI
vendor ZEEVO 0x0b7a Zeevo, Inc.
vendor KURUSUGAWA 0x0b7e Kurusugawa Electronics, Inc.
vendor SMART 0x0b8c Smart Technologies
vendor ASIX 0x0b95 ASIX Electronics
vendor O2MICRO 0x0b97 O2 Micro, Inc.
vendor USR 0x0baf U.S. Robotics
vendor AMBIT 0x0bb2 Ambit Microsystems
vendor HTC 0x0bb4 HTC
vendor REALTEK 0x0bda Realtek
vendor MEI 0x0bed MEI
vendor ADDONICS2 0x0bf6 Addonics Technology
vendor FSC 0x0bf8 Fujitsu Siemens Computers
vendor AGATE 0x0c08 Agate Technologies
vendor DMI 0x0c0b DMI
vendor CHICONY2 0x0c45 Chicony
vendor REINERSCT 0x0c4b Reiner-SCT
vendor SEALEVEL 0x0c52 Sealevel System
vendor LUWEN 0x0c76 Luwen
vendor KYOCERA2 0x0c88 Kyocera Wireless Corp.
vendor ZCOM 0x0cde Z-Com
vendor ATHEROS2 0x0cf3 Atheros Communications
vendor TANGTOP 0x0d3d Tangtop
vendor SMC3 0x0d5c Standard Microsystems
vendor ADDON 0x0d7d Add-on Technology
vendor ACDC 0x0d7e American Computer & Digital Components
vendor CMEDIA 0x0d8c CMEDIA
vendor CONCEPTRONIC 0x0d8e Conceptronic
vendor SKANHEX 0x0d96 Skanhex Technology, Inc.
vendor MSI 0x0db0 Micro Star International
vendor ELCON 0x0db7 ELCON Systemtechnik
vendor NETAC 0x0dd8 Netac
vendor SITECOMEU 0x0df6 Sitecom Europe
vendor MOBILEACTION 0x0df7 Mobile Action
vendor AMIGO 0x0e0b Amigo Technology
vendor SPEEDDRAGON 0x0e55 Speed Dragon Multimedia
vendor HAWKING 0x0e66 Hawking
vendor FOSSIL 0x0e67 Fossil, Inc
vendor GMATE 0x0e7e G.Mate, Inc
vendor MEDIATEK 0x0e8d MediaTek, Inc.
vendor OTI 0x0ea0 Ours Technology
vendor YISO 0x0eab Yiso Wireless Co.
vendor PILOTECH 0x0eaf Pilotech
vendor NOVATECH 0x0eb0 NovaTech
vendor ITEGNO 0x0eba iTegno
vendor WINMAXGROUP 0x0ed1 WinMaxGroup
vendor TOD 0x0ede TOD
vendor EGALAX 0x0eef eGalax, Inc.
vendor AIRPRIME 0x0f3d AirPrime, Inc.
vendor MICROTUNE 0x0f4d Microtune
vendor VTECH 0x0f88 VTech
vendor FALCOM 0x0f94 Falcom Wireless Communications GmbH
vendor RIM 0x0fca Research In Motion
vendor DYNASTREAM 0x0fcf Dynastream Innovations
+vendor KONTRON 0x0fe6 Kontron AG
vendor QUALCOMM 0x1004 Qualcomm
vendor APACER 0x1005 Apacer
vendor MOTOROLA4 0x100d Motorola
vendor AIRPLUS 0x1011 Airplus
vendor DESKNOTE 0x1019 Desknote
vendor GIGABYTE 0x1044 GIGABYTE
vendor WESTERN 0x1058 Western Digital
vendor MOTOROLA 0x1063 Motorola
vendor CCYU 0x1065 CCYU Technology
vendor CURITEL 0x106c Curitel Communications Inc
vendor SILABS2 0x10a6 SILABS2
vendor USI 0x10ab USI
vendor PLX 0x10b5 PLX
vendor ASANTE 0x10bd Asante
vendor SILABS 0x10c4 Silicon Labs
vendor SILABS3 0x10c5 Silicon Labs
vendor SILABS4 0x10ce Silicon Labs
vendor ACTIONS 0x10d6 Actions
vendor ANALOG 0x1110 Analog Devices
vendor TENX 0x1130 Ten X Technology, Inc.
vendor ISSC 0x1131 Integrated System Solution Corp.
vendor JRC 0x1145 Japan Radio Company
vendor SPHAIRON 0x114b Sphairon Access Systems GmbH
vendor DELORME 0x1163 DeLorme
vendor SERVERWORKS 0x1166 ServerWorks
vendor DLINK3 0x1186 Dlink
vendor ACERCM 0x1189 Acer Communications & Multimedia
vendor SIERRA 0x1199 Sierra Wireless
vendor SANWA 0x11ad Sanwa Electric Instrument Co., Ltd.
vendor TOPFIELD 0x11db Topfield Co., Ltd
vendor SIEMENS3 0x11f5 Siemens
vendor NETINDEX 0x11f6 NetIndex
vendor ALCATEL 0x11f7 Alcatel
vendor UNKNOWN3 0x1233 Unknown vendor
vendor TSUNAMI 0x1241 Tsunami
vendor PHEENET 0x124a Pheenet
vendor TARGUS 0x1267 Targus
vendor TWINMOS 0x126f TwinMOS
vendor TENDA 0x1286 Tenda
vendor CREATIVE2 0x1292 Creative Labs
vendor BELKIN2 0x1293 Belkin Components
vendor CYBERTAN 0x129b CyberTAN Technology
vendor HUAWEI 0x12d1 Huawei Technologies
vendor ARANEUS 0x12d8 Araneus Information Systems
vendor TAPWAVE 0x12ef Tapwave
vendor AINCOMM 0x12fd Aincomm
vendor MOBILITY 0x1342 Mobility
vendor DICKSMITH 0x1371 Dick Smith Electronics
vendor NETGEAR3 0x1385 Netgear
vendor BALTECH 0x13ad Baltech
vendor CISCOLINKSYS 0x13b1 Cisco-Linksys
vendor SHARK 0x13d2 Shark
vendor AZUREWAVE 0x13d3 AsureWave
vendor EMTEC 0x13fe Emtec
vendor NOVATEL 0x1410 Novatel Wireless
vendor MERLIN 0x1416 Merlin
vendor WISTRONNEWEB 0x1435 Wistron NeWeb
vendor RADIOSHACK 0x1453 Radio Shack
vendor HUAWEI3COM 0x1472 Huawei-3Com
vendor ABOCOM2 0x1482 AboCom Systems
vendor SILICOM 0x1485 Silicom
vendor RALINK 0x148f Ralink Technology
vendor IMAGINATION 0x149a Imagination Technologies
vendor CONCEPTRONIC2 0x14b2 Conceptronic
vendor SUPERTOP 0x14cd Super Top
vendor PLANEX3 0x14ea Planex Communications
vendor SILICONPORTALS 0x1527 Silicon Portals
vendor UBIQUAM 0x1529 UBIQUAM Co., Ltd.
vendor JMICRON 0x152d JMicron
vendor UBLOX 0x1546 U-blox
vendor PNY 0x154b PNY
vendor OWEN 0x1555 Owen
vendor OQO 0x1557 OQO
vendor UMEDIA 0x157e U-MEDIA Communications
vendor FIBERLINE 0x1582 Fiberline
vendor SPARKLAN 0x15a9 SparkLAN
vendor AMIT2 0x15c5 AMIT
vendor SOHOWARE 0x15e8 SOHOware
vendor UMAX 0x1606 UMAX Data Systems
vendor INSIDEOUT 0x1608 Inside Out Networks
vendor AMOI 0x1614 Amoi Electronics
vendor GOODWAY 0x1631 Good Way Technology
vendor ENTREGA 0x1645 Entrega
vendor ACTIONTEC 0x1668 Actiontec Electronics
vendor CLIPSAL 0x166a Clipsal
vendor CISCOLINKSYS2 0x167b Cisco-Linksys
vendor ATHEROS 0x168c Atheros Communications
vendor GIGASET 0x1690 Gigaset
vendor GLOBALSUN 0x16ab Global Sun Technology
vendor ANYDATA 0x16d5 AnyDATA Corporation
vendor JABLOTRON 0x16d6 Jablotron
vendor CMOTECH 0x16d8 C-motech
vendor WIENERPLEINBAUS 0x16dc WIENER Plein & Baus GmbH.
vendor AXESSTEL 0x1726 Axesstel Co., Ltd.
vendor LINKSYS4 0x1737 Linksys
vendor SENAO 0x1740 Senao
vendor ASUS2 0x1761 ASUS
vendor SWEEX2 0x177f Sweex
vendor METAGEEK 0x1781 MetaGeek
vendor WAVESENSE 0x17f4 WaveSense
vendor VAISALA 0x1843 Vaisala
vendor AMIT 0x18c5 AMIT
vendor GOOGLE 0x18d1 Google
vendor QCOM 0x18e8 Qcom
vendor ELV 0x18ef ELV
vendor LINKSYS3 0x1915 Linksys
vendor QUALCOMMINC 0x19d2 Qualcomm, Incorporated
vendor WCH2 0x1a86 QinHeng Electronics
vendor STELERA 0x1a8d Stelera Wireless
vendor MATRIXORBITAL 0x1b3d Matrix Orbital
vendor OVISLINK 0x1b75 OvisLink
vendor TCTMOBILE 0x1bbb TCT Mobile
vendor WAGO 0x1be3 WAGO Kontakttechnik GmbH.
vendor TELIT 0x1bc7 Telit
vendor LONGCHEER 0x1c9e Longcheer Holdings, Ltd.
vendor MPMAN 0x1cae MpMan
vendor DRESDENELEKTRONIK 0x1cf1 dresden elektronik
vendor NEOTEL 0x1d09 Neotel
vendor PEGATRON 0x1d4d Pegatron
vendor QISDA 0x1da5 Qisda
vendor METAGEEK2 0x1dd5 MetaGeek
vendor ALINK 0x1e0e Alink
vendor AIRTIES 0x1eda AirTies
vendor DLINK 0x2001 D-Link
vendor PLANEX2 0x2019 Planex Communications
vendor HAUPPAUGE2 0x2040 Hauppauge Computer Works
vendor TLAYTECH 0x20b9 Tlay Tech
vendor ENCORE 0x203d Encore
vendor PARA 0x20b8 PARA Industrial
vendor ERICSSON 0x2282 Ericsson
vendor MOTOROLA2 0x22b8 Motorola
vendor TRIPPLITE 0x2478 Tripp-Lite
vendor HIROSE 0x2631 Hirose Electric
vendor NHJ 0x2770 NHJ
vendor PLANEX 0x2c02 Planex Communications
vendor VIDZMEDIA 0x3275 VidzMedia Pte Ltd
vendor AEI 0x3334 AEI
vendor HANK 0x3353 Hank Connection
vendor PQI 0x3538 PQI
vendor DAISY 0x3579 Daisy Technology
vendor NI 0x3923 National Instruments
vendor MICRONET 0x3980 Micronet Communications
vendor IODATA2 0x40bb I-O Data
vendor IRIVER 0x4102 iRiver
vendor DELL 0x413c Dell
vendor WCH 0x4348 QinHeng Electronics
vendor ACEECA 0x4766 Aceeca
vendor AVERATEC 0x50c2 Averatec
vendor SWEEX 0x5173 Sweex
vendor PROLIFIC2 0x5372 Prolific Technologies
vendor ONSPEC2 0x55aa OnSpec Electronic Inc.
vendor ZINWELL 0x5a57 Zinwell
vendor SITECOM 0x6189 Sitecom
vendor ARKMICRO 0x6547 Arkmicro Technologies Inc.
vendor 3COM2 0x6891 3Com
vendor EDIMAX 0x7392 Edimax
vendor INTEL 0x8086 Intel
vendor INTEL2 0x8087 Intel
vendor ALLWIN 0x8516 ALLWIN Tech
vendor SITECOM2 0x9016 Sitecom
vendor MOSCHIP 0x9710 MosChip Semiconductor
vendor MARVELL 0x9e88 Marvell Technology Group Ltd.
vendor 3COM3 0xa727 3Com
vendor DATAAPEX 0xdaae DataApex
vendor HP2 0xf003 Hewlett Packard
vendor USRP 0xfffe GNU Radio USRP
/*
* List of known products. Grouped by vendor.
*/
/* 3Com products */
product 3COM HOMECONN 0x009d HomeConnect Camera
product 3COM 3CREB96 0x00a0 Bluetooth USB Adapter
product 3COM 3C19250 0x03e8 3C19250 Ethernet Adapter
product 3COM 3CRSHEW696 0x0a01 3CRSHEW696 Wireless Adapter
product 3COM 3C460 0x11f8 HomeConnect 3C460
product 3COM USR56K 0x3021 U.S.Robotics 56000 Voice FaxModem Pro
product 3COM 3C460B 0x4601 HomeConnect 3C460B
product 3COM2 3CRUSB10075 0xa727 3CRUSB10075
product 3COM3 AR5523_1 0x6893 AR5523
product 3COM3 AR5523_2 0x6895 AR5523
product 3COM3 AR5523_3 0x6897 AR5523
product 3COMUSR OFFICECONN 0x0082 3Com OfficeConnect Analog Modem
product 3COMUSR USRISDN 0x008f 3Com U.S. Robotics Pro ISDN TA
product 3COMUSR HOMECONN 0x009d 3Com HomeConnect Camera
product 3COMUSR USR56K 0x3021 U.S. Robotics 56000 Voice FaxModem Pro
/* AboCom products */
product ABOCOM XX1 0x110c XX1
product ABOCOM XX2 0x200c XX2
product ABOCOM RT2770 0x2770 RT2770
product ABOCOM RT2870 0x2870 RT2870
product ABOCOM RT3070 0x3070 RT3070
product ABOCOM RT3071 0x3071 RT3071
product ABOCOM RT3072 0x3072 RT3072
product ABOCOM2 RT2870_1 0x3c09 RT2870
product ABOCOM URE450 0x4000 URE450 Ethernet Adapter
product ABOCOM UFE1000 0x4002 UFE1000 Fast Ethernet Adapter
product ABOCOM DSB650TX_PNA 0x4003 1/10/100 Ethernet Adapter
product ABOCOM XX4 0x4004 XX4
product ABOCOM XX5 0x4007 XX5
product ABOCOM XX6 0x400b XX6
product ABOCOM XX7 0x400c XX7
product ABOCOM RTL8151 0x401a RTL8151
product ABOCOM XX8 0x4102 XX8
product ABOCOM XX9 0x4104 XX9
product ABOCOM UF200 0x420a UF200 Ethernet
product ABOCOM WL54 0x6001 WL54
product ABOCOM XX10 0xabc1 XX10
product ABOCOM BWU613 0xb000 BWU613
product ABOCOM HWU54DM 0xb21b HWU54DM
product ABOCOM RT2573_2 0xb21c RT2573
product ABOCOM RT2573_3 0xb21d RT2573
product ABOCOM RT2573_4 0xb21e RT2573
product ABOCOM WUG2700 0xb21f WUG2700
/* Accton products */
product ACCTON USB320_EC 0x1046 USB320-EC Ethernet Adapter
product ACCTON 2664W 0x3501 2664W
product ACCTON 111 0x3503 T-Sinus 111 Wireless Adapter
product ACCTON SMCWUSBG_NF 0x4505 SMCWUSB-G (no firmware)
product ACCTON SMCWUSBG 0x4506 SMCWUSB-G
product ACCTON SMCWUSBTG2_NF 0x4507 SMCWUSBT-G2 (no firmware)
product ACCTON SMCWUSBTG2 0x4508 SMCWUSBT-G2
product ACCTON PRISM_GT 0x4521 PrismGT USB 2.0 WLAN
product ACCTON SS1001 0x5046 SpeedStream Ethernet Adapter
product ACCTON RT2870_2 0x6618 RT2870
product ACCTON RT3070 0x7511 RT3070
product ACCTON RT2770 0x7512 RT2770
product ACCTON RT2870_3 0x7522 RT2870
product ACCTON RT2870_5 0x8522 RT2870
product ACCTON RT3070_4 0xa512 RT3070
product ACCTON RT2870_4 0xa618 RT2870
product ACCTON RT3070_1 0xa701 RT3070
product ACCTON RT3070_2 0xa702 RT3070
product ACCTON RT2870_1 0xb522 RT2870
product ACCTON RT3070_3 0xc522 RT3070
product ACCTON RT3070_5 0xd522 RT3070
product ACCTON ZD1211B 0xe501 ZD1211B
/* Aceeca products */
product ACEECA MEZ1000 0x0001 MEZ1000 RDA
/* Acer Communications & Multimedia (oemd by Surecom) */
product ACERCM EP1427X2 0x0893 EP-1427X-2 Ethernet Adapter
/* Acer Labs products */
product ACERLABS M5632 0x5632 USB 2.0 Data Link
/* Acer Peripherals, Inc. products */
product ACERP ACERSCAN_C310U 0x12a6 Acerscan C310U
product ACERP ACERSCAN_320U 0x2022 Acerscan 320U
product ACERP ACERSCAN_640U 0x2040 Acerscan 640U
product ACERP ACERSCAN_620U 0x2060 Acerscan 620U
product ACERP ACERSCAN_4300U 0x20b0 Benq 3300U/4300U
product ACERP ACERSCAN_640BT 0x20be Acerscan 640BT
product ACERP ACERSCAN_1240U 0x20c0 Acerscan 1240U
product ACERP S81 0x4027 BenQ S81 phone
product ACERP H10 0x4068 AWL400 Wireless Adapter
product ACERP ATAPI 0x6003 ATA/ATAPI Adapter
product ACERP AWL300 0x9000 AWL300 Wireless Adapter
product ACERP AWL400 0x9001 AWL400 Wireless Adapter
/* Acer Warp products */
product ACERW WARPLINK 0x0204 Warplink
/* Actions products */
product ACTIONS MP4 0x1101 Actions MP4 Player
/* Actiontec, Inc. products */
product ACTIONTEC PRISM_25 0x0408 Prism2.5 Wireless Adapter
product ACTIONTEC PRISM_25A 0x0421 Prism2.5 Wireless Adapter A
product ACTIONTEC FREELAN 0x6106 ROPEX FreeLan 802.11b
product ACTIONTEC UAT1 0x7605 UAT1 Wireless Ethernet Adapter
/* ACTiSYS products */
product ACTISYS IR2000U 0x0011 ACT-IR2000U FIR
/* ActiveWire, Inc. products */
product ACTIVEWIRE IOBOARD 0x0100 I/O Board
product ACTIVEWIRE IOBOARD_FW1 0x0101 I/O Board, rev. 1 firmware
/* Adaptec products */
product ADAPTEC AWN8020 0x0020 AWN-8020 WLAN
/* Addtron products */
product ADDTRON AWU120 0xff31 AWU-120
/* ADLINK Texhnology products */
product ADLINK ND6530 0x6530 ND-6530 USB-Serial
/* ADMtek products */
product ADMTEK PEGASUSII_4 0x07c2 AN986A Ethernet
product ADMTEK PEGASUS 0x0986 AN986 Ethernet
product ADMTEK PEGASUSII 0x8511 AN8511 Ethernet
product ADMTEK PEGASUSII_2 0x8513 AN8513 Ethernet
product ADMTEK PEGASUSII_3 0x8515 AN8515 Ethernet
/* ADDON products */
/* PNY OEMs these */
product ADDON ATTACHE 0x1300 USB 2.0 Flash Drive
product ADDON ATTACHE 0x1300 USB 2.0 Flash Drive
product ADDON A256MB 0x1400 Attache 256MB USB 2.0 Flash Drive
product ADDON DISKPRO512 0x1420 USB 2.0 Flash Drive (DANE-ELEC zMate 512MB USB flash drive)
/* Addonics products */
product ADDONICS2 CABLE_205 0xa001 Cable 205
/* ADS products */
product ADS UBS10BT 0x0008 UBS-10BT Ethernet
product ADS UBS10BTX 0x0009 UBS-10BT Ethernet
/* AEI products */
product AEI FASTETHERNET 0x1701 Fast Ethernet
/* Agate Technologies products */
product AGATE QDRIVE 0x0378 Q-Drive
/* AGFA products */
product AGFA SNAPSCAN1212U 0x0001 SnapScan 1212U
product AGFA SNAPSCAN1236U 0x0002 SnapScan 1236U
product AGFA SNAPSCANTOUCH 0x0100 SnapScan Touch
product AGFA SNAPSCAN1212U2 0x2061 SnapScan 1212U
product AGFA SNAPSCANE40 0x208d SnapScan e40
product AGFA SNAPSCANE50 0x208f SnapScan e50
product AGFA SNAPSCANE20 0x2091 SnapScan e20
product AGFA SNAPSCANE25 0x2095 SnapScan e25
product AGFA SNAPSCANE26 0x2097 SnapScan e26
product AGFA SNAPSCANE52 0x20fd SnapScan e52
/* Ain Communication Technology products */
product AINCOMM AWU2000B 0x1001 AWU2000B Wireless Adapter
/* AIPTEK products */
product AIPTEK POCKETCAM3M 0x2011 PocketCAM 3Mega
product AIPTEK2 PENCAM_MEGA_1_3 0x504a PenCam Mega 1.3
product AIPTEK2 SUNPLUS_TECH 0x0c15 Sunplus Technology Inc.
/* AirPlis products */
product AIRPLUS MCD650 0x3198 MCD650 modem
/* AirPrime products */
product AIRPRIME PC5220 0x0112 CDMA Wireless PC Card
/* AirTies products */
product AIRTIES RT3070 0x2310 RT3070
/* AKS products */
product AKS USBHASP 0x0001 USB-HASP 0.06
/* Alcatel products */
product ALCATEL OT535 0x02df One Touch 535/735
/* Alcor Micro, Inc. products */
product ALCOR2 KBD_HUB 0x2802 Kbd Hub
product ALCOR SDCR_6335 0x6335 SD/MMC Card Reader
product ALCOR SDCR_6362 0x6362 SD/MMC Card Reader
product ALCOR TRANSCEND 0x6387 Transcend JetFlash Drive
product ALCOR MA_KBD_HUB 0x9213 MacAlly Kbd Hub
product ALCOR AU9814 0x9215 AU9814 Hub
product ALCOR UMCR_9361 0x9361 USB Multimedia Card Reader
product ALCOR SM_KBD 0x9410 MicroConnectors/StrongMan Keyboard
product ALCOR NEC_KBD_HUB 0x9472 NEC Kbd Hub
product ALCOR AU9720 0x9720 USB2 - RS-232
product ALCOR AU6390 0x6390 AU6390 USB-IDE converter
/* Alink products */
product ALINK DWM652U5 0xce16 DWM-652
product ALINK 3G 0x9000 3G modem
product ALINK 3GU 0x9200 3G modem
/* Altec Lansing products */
product ALTEC ADA70 0x0070 ADA70 Speakers
product ALTEC ASC495 0xff05 ASC495 Speakers
/* Allied Telesyn International products */
product ALLIEDTELESYN ATUSB100 0xb100 AT-USB100
/* ALLWIN Tech products */
product ALLWIN RT2070 0x2070 RT2070
product ALLWIN RT2770 0x2770 RT2770
product ALLWIN RT2870 0x2870 RT2870
product ALLWIN RT3070 0x3070 RT3070
product ALLWIN RT3071 0x3071 RT3071
product ALLWIN RT3072 0x3072 RT3072
product ALLWIN RT3572 0x3572 RT3572
/* AlphaSmart, Inc. products */
product ALPHASMART DANA_KB 0xdbac AlphaSmart Dana Keyboard
product ALPHASMART DANA_SYNC 0xdf00 AlphaSmart Dana HotSync
/* Amoi products */
product AMOI H01 0x0800 H01 3G modem
product AMOI H01A 0x7002 H01A 3G modem
product AMOI H02 0x0802 H02 3G modem
/* American Power Conversion products */
product APC UPS 0x0002 Uninterruptible Power Supply
/* Ambit Microsystems products */
product AMBIT WLAN 0x0302 WLAN
product AMBIT NTL_250 0x6098 NTL 250 cable modem
/* Apacer products */
product APACER HT202 0xb113 USB 2.0 Flash Drive
/* American Power Conversion products */
product APC UPS 0x0002 Uninterruptible Power Supply
/* Amigo Technology products */
product AMIGO RT2870_1 0x9031 RT2870
product AMIGO RT2870_2 0x9041 RT2870
/* AMIT products */
product AMIT CGWLUSB2GO 0x0002 CG-WLUSB2GO
product AMIT CGWLUSB2GNR 0x0008 CG-WLUSB2GNR
product AMIT RT2870_1 0x0012 RT2870
/* AMIT(2) products */
product AMIT2 RT2870 0x0008 RT2870
/* Anchor products */
product ANCHOR SERIAL 0x2008 Serial
product ANCHOR EZUSB 0x2131 EZUSB
product ANCHOR EZLINK 0x2720 EZLINK
/* AnyData products */
product ANYDATA ADU_620UW 0x6202 CDMA 2000 EV-DO USB Modem
product ANYDATA ADU_E100X 0x6501 CDMA 2000 1xRTT/EV-DO USB Modem
product ANYDATA ADU_500A 0x6502 CDMA 2000 EV-DO USB Modem
/* AOX, Inc. products */
product AOX USB101 0x0008 Ethernet
/* American Power Conversion products */
product APC UPS 0x0002 Uninterruptible Power Supply
/* Apple Computer products */
product APPLE IMAC_KBD 0x0201 USB iMac Keyboard
product APPLE KBD 0x0202 USB Keyboard M2452
product APPLE EXT_KBD 0x020c Apple Extended USB Keyboard
product APPLE KBD_TP_ANSI 0x0223 Apple Internal Keyboard/Trackpad (Wellspring/ANSI)
product APPLE KBD_TP_ISO 0x0224 Apple Internal Keyboard/Trackpad (Wellspring/ISO)
product APPLE KBD_TP_JIS 0x0225 Apple Internal Keyboard/Trackpad (Wellspring/JIS)
product APPLE KBD_TP_ANSI2 0x0230 Apple Internal Keyboard/Trackpad (Wellspring2/ANSI)
product APPLE KBD_TP_ISO2 0x0231 Apple Internal Keyboard/Trackpad (Wellspring2/ISO)
product APPLE KBD_TP_JIS2 0x0232 Apple Internal Keyboard/Trackpad (Wellspring2/JIS)
product APPLE MOUSE 0x0301 Mouse M4848
product APPLE OPTMOUSE 0x0302 Optical mouse
product APPLE MIGHTYMOUSE 0x0304 Mighty Mouse
product APPLE KBD_HUB 0x1001 Hub in Apple USB Keyboard
product APPLE EXT_KBD_HUB 0x1003 Hub in Apple Extended USB Keyboard
product APPLE SPEAKERS 0x1101 Speakers
product APPLE IPOD 0x1201 iPod
product APPLE IPOD2G 0x1202 iPod 2G
product APPLE IPOD3G 0x1203 iPod 3G
product APPLE IPOD_04 0x1204 iPod '04'
product APPLE IPODMINI 0x1205 iPod Mini
product APPLE IPOD_06 0x1206 iPod '06'
product APPLE IPOD_07 0x1207 iPod '07'
product APPLE IPOD_08 0x1208 iPod '08'
product APPLE IPODVIDEO 0x1209 iPod Video
product APPLE IPODNANO 0x120a iPod Nano
product APPLE IPHONE 0x1290 iPhone
product APPLE IPOD_TOUCH 0x1291 iPod Touch
product APPLE IPHONE_3G 0x1292 iPhone 3G
product APPLE IPHONE_3GS 0x1294 iPhone 3GS
product APPLE IPHONE_4 0x1297 iPhone 4
product APPLE IPAD 0x129a iPad
product APPLE ETHERNET 0x1402 Ethernet A1277
/* Arkmicro Technologies */
product ARKMICRO ARK3116 0x0232 ARK3116 Serial
/* Asahi Optical products */
product ASAHIOPTICAL OPTIO230 0x0004 Digital camera
product ASAHIOPTICAL OPTIO330 0x0006 Digital camera
/* Asante products */
product ASANTE EA 0x1427 Ethernet
/* ASIX Electronics products */
product ASIX AX88172 0x1720 10/100 Ethernet
product ASIX AX88178 0x1780 AX88178
product ASIX AX88772 0x7720 AX88772
product ASIX AX88772A 0x772a AX88772A USB 2.0 10/100 Ethernet
/* ASUS products */
product ASUS2 USBN11 0x0b05 USB-N11
product ASUS WL167G 0x1707 WL-167g Wireless Adapter
product ASUS WL159G 0x170c WL-159g
product ASUS A9T_WIFI 0x171b A9T wireless
product ASUS P5B_WIFI 0x171d P5B wireless
product ASUS RT2573_1 0x1723 RT2573
product ASUS RT2573_2 0x1724 RT2573
product ASUS LCM 0x1726 LCM display
product ASUS RT2870_1 0x1731 RT2870
product ASUS RT2870_2 0x1732 RT2870
product ASUS RT2870_3 0x1742 RT2870
product ASUS RT2870_4 0x1760 RT2870
product ASUS RT2870_5 0x1761 RT2870
product ASUS USBN13 0x1784 USB-N13
product ASUS RT3070_1 0x1790 RT3070
product ASUS A730W 0x4202 ASUS MyPal A730W
product ASUS P535 0x420f ASUS P535 PDA
product ASUS GMSC 0x422f ASUS Generic Mass Storage
product ASUS RT2570 0x1706 RT2500USB Wireless Adapter
/* ATen products */
product ATEN UC1284 0x2001 Parallel printer
product ATEN UC10T 0x2002 10Mbps Ethernet
product ATEN UC110T 0x2007 UC-110T Ethernet
product ATEN UC232A 0x2008 Serial
product ATEN UC210T 0x2009 UC-210T Ethernet
product ATEN DSB650C 0x4000 DSB-650C
/* Atheros Communications products */
product ATHEROS AR5523 0x0001 AR5523
product ATHEROS AR5523_NF 0x0002 AR5523 (no firmware)
product ATHEROS2 AR5523_1 0x0001 AR5523
product ATHEROS2 AR5523_1_NF 0x0002 AR5523 (no firmware)
product ATHEROS2 AR5523_2 0x0003 AR5523
product ATHEROS2 AR5523_2_NF 0x0004 AR5523 (no firmware)
product ATHEROS2 AR5523_3 0x0005 AR5523
product ATHEROS2 AR5523_3_NF 0x0006 AR5523 (no firmware)
/* Atmel Comp. products */
product ATMEL STK541 0x2109 Zigbee Controller
product ATMEL UHB124 0x3301 UHB124 hub
product ATMEL DWL120 0x7603 DWL-120 Wireless Adapter
product ATMEL BW002 0x7605 BW002 Wireless Adapter
product ATMEL WL1130USB 0x7613 WL-1130 USB
product ATMEL AT76C505A 0x7614 AT76c505a Wireless Adapter
/* AuthenTec products */
product AUTHENTEC AES1610 0x1600 AES1610 Fingerprint Sensor
/* Avision products */
product AVISION 1200U 0x0268 1200U scanner
/* Axesstel products */
product AXESSTEL DATAMODEM 0x1000 Data Modem
/* AsureWave products */
product AZUREWAVE RT2870_1 0x3247 RT2870
product AZUREWAVE RT2870_2 0x3262 RT2870
product AZUREWAVE RT3070_1 0x3273 RT3070
product AZUREWAVE RT3070_2 0x3284 RT3070
product AZUREWAVE RT3070_3 0x3305 RT3070
/* Baltech products */
product BALTECH CARDREADER 0x9999 Card reader
/* B&B Electronics products */
product BBELECTRONICS USOTL4 0xAC01 RS-422/485
/* Belkin products */
/*product BELKIN F5U111 0x???? F5U111 Ethernet*/
product BELKIN F5D6050 0x0050 F5D6050 802.11b Wireless Adapter
product BELKIN FBT001V 0x0081 FBT001v2 Bluetooth
product BELKIN FBT003V 0x0084 FBT003v2 Bluetooth
product BELKIN F5U103 0x0103 F5U103 Serial
product BELKIN F5U109 0x0109 F5U109 Serial
product BELKIN USB2SCSI 0x0115 USB to SCSI
product BELKIN F8T012 0x0121 F8T012xx1 Bluetooth USB Adapter
product BELKIN USB2LAN 0x0121 USB to LAN
product BELKIN F5U208 0x0208 F5U208 VideoBus II
product BELKIN F5U237 0x0237 F5U237 USB 2.0 7-Port Hub
product BELKIN F5U257 0x0257 F5U257 Serial
product BELKIN F5U409 0x0409 F5U409 Serial
product BELKIN F6C550AVR 0x0551 F6C550-AVR UPS
product BELKIN F5U120 0x1203 F5U120-PC Hub
product BELKIN ZD1211B 0x4050 ZD1211B
product BELKIN F5D5055 0x5055 F5D5055
product BELKIN F5D7050 0x7050 F5D7050 Wireless Adapter
product BELKIN F5D7051 0x7051 F5D7051 54g USB Network Adapter
product BELKIN F5D7050A 0x705a F5D7050A Wireless Adapter
/* Also sold as 'Ativa 802.11g wireless card' */
product BELKIN F5D7050_V4000 0x705c F5D7050 v4000 Wireless Adapter
product BELKIN F5D7050E 0x705e F5D7050E Wireless Adapter
product BELKIN RT2870_1 0x8053 RT2870
product BELKIN RT2870_2 0x805c RT2870
product BELKIN F5D8053V3 0x815c F5D8053 v3
product BELKIN F5D8055 0x825a F5D8055
product BELKIN F5D9050V3 0x905b F5D9050 ver 3 Wireless Adapter
product BELKIN2 F5U002 0x0002 F5U002 Parallel printer
product BELKIN F6D4050V1 0x935a F6D4050 v1
/* Billionton products */
product BILLIONTON USB100 0x0986 USB100N 10/100 FastEthernet
product BILLIONTON USBLP100 0x0987 USB100LP
product BILLIONTON USBEL100 0x0988 USB100EL
product BILLIONTON USBE100 0x8511 USBE100
product BILLIONTON USB2AR 0x90ff USB2AR Ethernet
/* Broadcom products */
product BROADCOM BCM2033 0x2033 BCM2033 Bluetooth USB dongle
/* Brother Industries products */
product BROTHER HL1050 0x0002 HL-1050 laser printer
product BROTHER MFC8600_9650 0x0100 MFC8600/9650 multifunction device
/* Behavior Technology Computer products */
product BTC BTC6100 0x5550 6100C Keyboard
product BTC BTC7932 0x6782 Keyboard with mouse port
/* Canon, Inc. products */
product CANON N656U 0x2206 CanoScan N656U
product CANON N1220U 0x2207 CanoScan N1220U
product CANON D660U 0x2208 CanoScan D660U
product CANON N676U 0x220d CanoScan N676U
product CANON N1240U 0x220e CanoScan N1240U
product CANON LIDE25 0x2220 CanoScan LIDE 25
product CANON S10 0x3041 PowerShot S10
product CANON S100 0x3045 PowerShot S100
product CANON S200 0x3065 PowerShot S200
product CANON REBELXT 0x30ef Digital Rebel XT
/* CATC products */
product CATC NETMATE 0x000a Netmate Ethernet
product CATC NETMATE2 0x000c Netmate2 Ethernet
product CATC CHIEF 0x000d USB Chief Bus & Protocol Analyzer
product CATC ANDROMEDA 0x1237 Andromeda hub
/* CASIO products */
product CASIO QV_DIGICAM 0x1001 QV DigiCam
product CASIO EXS880 0x1105 Exilim EX-S880
product CASIO BE300 0x2002 BE-300 PDA
product CASIO NAMELAND 0x4001 CASIO Nameland EZ-USB
/* CCYU products */
product CCYU ED1064 0x2136 EasyDisk ED1064
/* Century products */
product CENTURY EX35QUAT 0x011e Century USB Disk Enclosure
product CENTURY EX35SW4_SB4 0x011f Century USB Disk Enclosure
/* Cherry products */
product CHERRY MY3000KBD 0x0001 My3000 keyboard
product CHERRY MY3000HUB 0x0003 My3000 hub
product CHERRY CYBOARD 0x0004 CyBoard Keyboard
/* Chic Technology products */
product CHIC MOUSE1 0x0001 mouse
product CHIC CYPRESS 0x0003 Cypress USB Mouse
/* Chicony products */
product CHICONY KB8933 0x0001 KB-8933 keyboard
product CHICONY KU0325 0x0116 KU-0325 keyboard
product CHICONY CNF7129 0xb071 Notebook Web Camera
product CHICONY2 TWINKLECAM 0x600d TwinkleCam USB camera
/* CH Products */
product CHPRODUCTS PROTHROTTLE 0x00f1 Pro Throttle
product CHPRODUCTS PROPEDALS 0x00f2 Pro Pedals
product CHPRODUCTS FIGHTERSTICK 0x00f3 Fighterstick
product CHPRODUCTS FLIGHTYOKE 0x00ff Flight Sim Yoke
/* Cisco-Linksys products */
product CISCOLINKSYS WUSB54AG 0x000c WUSB54AG Wireless Adapter
product CISCOLINKSYS WUSB54G 0x000d WUSB54G Wireless Adapter
product CISCOLINKSYS WUSB54GP 0x0011 WUSB54GP Wireless Adapter
product CISCOLINKSYS USB200MV2 0x0018 USB200M v2
product CISCOLINKSYS HU200TS 0x001a HU200TS Wireless Adapter
product CISCOLINKSYS WUSB54GC 0x0020 WUSB54GC
product CISCOLINKSYS WUSB54GR 0x0023 WUSB54GR
product CISCOLINKSYS WUSBF54G 0x0024 WUSBF54G
product CISCOLINKSYS2 RT3070 0x4001 RT3070
product CISCOLINKSYS3 RT3070 0x0101 RT3070
/* Clipsal products */
product CLIPSAL 5500PCU 0x0303 5500PCU C-Bus
/* CMOTECH products */
product CMOTECH CNU510 0x5141 CDMA Technologies USB modem
product CMOTECH CNU550 0x5543 CDMA 2000 1xRTT/1xEVDO USB modem
product CMOTECH CGU628 0x6006 CGU-628
product CMOTECH CDMA_MODEM1 0x6280 CDMA Technologies USB modem
product CMOTECH DISK 0xf000 disk mode
/* Compaq products */
product COMPAQ IPAQPOCKETPC 0x0003 iPAQ PocketPC
product COMPAQ PJB100 0x504a Personal Jukebox PJB100
product COMPAQ IPAQLINUX 0x505a iPAQ Linux
/* Composite Corp products looks the same as "TANGTOP" */
product COMPOSITE USBPS2 0x0001 USB to PS2 Adaptor
/* Conceptronic products */
product CONCEPTRONIC PRISM_GT 0x3762 PrismGT USB 2.0 WLAN
product CONCEPTRONIC C11U 0x7100 C11U
product CONCEPTRONIC WL210 0x7110 WL-210
product CONCEPTRONIC AR5523_1 0x7801 AR5523
product CONCEPTRONIC AR5523_1_NF 0x7802 AR5523 (no firmware)
product CONCEPTRONIC AR5523_2 0x7811 AR5523
product CONCEPTRONIC AR5523_2_NF 0x7812 AR5523 (no firmware)
product CONCEPTRONIC2 C54RU 0x3c02 C54RU WLAN
product CONCEPTRONIC2 C54RU2 0x3c22 C54RU
product CONCEPTRONIC2 RT3070_1 0x3c08 RT3070
product CONCEPTRONIC2 RT3070_2 0x3c11 RT3070
product CONCEPTRONIC2 VIGORN61 0x3c25 VIGORN61
product CONCEPTRONIC2 RT2870_1 0x3c06 RT2870
product CONCEPTRONIC2 RT2870_2 0x3c07 RT2870
product CONCEPTRONIC2 RT2870_7 0x3c09 RT2870
product CONCEPTRONIC2 RT2870_8 0x3c12 RT2870
product CONCEPTRONIC2 RT2870_3 0x3c23 RT2870
product CONCEPTRONIC2 RT2870_4 0x3c25 RT2870
product CONCEPTRONIC2 RT2870_5 0x3c27 RT2870
product CONCEPTRONIC2 RT2870_6 0x3c28 RT2870
/* Connectix products */
product CONNECTIX QUICKCAM 0x0001 QuickCam
/* Corega products */
product COREGA ETHER_USB_T 0x0001 Ether USB-T
product COREGA FETHER_USB_TX 0x0004 FEther USB-TX
product COREGA WLAN_USB_USB_11 0x000c WirelessLAN USB-11
product COREGA FETHER_USB_TXS 0x000d FEther USB-TXS
product COREGA WLANUSB 0x0012 Wireless LAN Stick-11
product COREGA FETHER_USB2_TX 0x0017 FEther USB2-TX
product COREGA WLUSB_11_KEY 0x001a ULUSB-11 Key
product COREGA CGUSBRS232R 0x002a CG-USBRS232R
product COREGA CGWLUSB2GL 0x002d CG-WLUSB2GL
product COREGA CGWLUSB2GPX 0x002e CG-WLUSB2GPX
product COREGA RT2870_1 0x002f RT2870
product COREGA RT2870_2 0x003c RT2870
product COREGA RT2870_3 0x003f RT2870
product COREGA RT3070 0x0041 RT3070
product COREGA CGWLUSB300GNM 0x0042 CG-WLUSB300GNM
product COREGA WLUSB_11_STICK 0x7613 WLAN USB Stick 11
product COREGA FETHER_USB_TXC 0x9601 FEther USB-TXC
/* Creative products */
product CREATIVE NOMAD_II 0x1002 Nomad II MP3 player
product CREATIVE NOMAD_IIMG 0x4004 Nomad II MG
product CREATIVE NOMAD 0x4106 Nomad
product CREATIVE2 VOIP_BLASTER 0x0258 Voip Blaster
product CREATIVE3 OPTICAL_MOUSE 0x0001 Notebook Optical Mouse
/* Cambridge Silicon Radio Ltd. products */
product CSR BT_DONGLE 0x0001 Bluetooth USB dongle
product CSR CSRDFU 0xffff USB Bluetooth Device in DFU State
/* Chipsbank Microelectronics Co., Ltd */
product CHIPSBANK USBMEMSTICK 0x6025 CBM2080 Flash drive controller
product CHIPSBANK USBMEMSTICK1 0x6026 CBM1180 Flash drive controller
/* CTX products */
product CTX EX1300 0x9999 Ex1300 hub
/* Curitel products */
product CURITEL HX550C 0x1101 CDMA 2000 1xRTT USB modem (HX-550C)
product CURITEL HX57XB 0x2101 CDMA 2000 1xRTT USB modem (HX-570/575B/PR-600)
product CURITEL PC5740 0x3701 Broadband Wireless modem
product CURITEL UM150 0x3711 EVDO modem
product CURITEL UM175 0x3714 EVDO modem
/* CyberPower products */
product CYBERPOWER 1500CAVRLCD 0x0501 1500CAVRLCD
/* CyberTAN Technology products */
product CYBERTAN TG54USB 0x1666 TG54USB
product CYBERTAN RT2870 0x1828 RT2870
/* Cypress Semiconductor products */
product CYPRESS MOUSE 0x0001 mouse
product CYPRESS THERMO 0x0002 thermometer
product CYPRESS WISPY1A 0x0bad MetaGeek Wi-Spy
product CYPRESS KBDHUB 0x0101 Keyboard/Hub
product CYPRESS FMRADIO 0x1002 FM Radio
product CYPRESS IKARILASER 0x121f Ikari Laser SteelSeries ApS
product CYPRESS USBRS232 0x5500 USB-RS232 Interface
product CYPRESS SLIM_HUB 0x6560 Slim Hub
product CYPRESS XX6830XX 0x6830 PATA Storage Device
product CYPRESS SILVERSHIELD 0xfd13 Gembird Silver Shield PM
/* Daisy Technology products */
product DAISY DMC 0x6901 USB MultiMedia Reader
/* Dallas Semiconductor products */
product DALLAS J6502 0x4201 J-6502 speakers
/* DataApex products */
product DATAAPEX MULTICOM 0xead6 MultiCom
/* Dell products */
product DELL PORT 0x0058 Port Replicator
product DELL AIO926 0x5115 Photo AIO Printer 926
product DELL BC02 0x8000 BC02 Bluetooth USB Adapter
product DELL PRISM_GT_1 0x8102 PrismGT USB 2.0 WLAN
product DELL TM350 0x8103 TrueMobile 350 Bluetooth USB Adapter
product DELL PRISM_GT_2 0x8104 PrismGT USB 2.0 WLAN
product DELL U5700 0x8114 Dell 5700 3G
product DELL U5500 0x8115 Dell 5500 3G
product DELL U5505 0x8116 Dell 5505 3G
product DELL U5700_2 0x8117 Dell 5700 3G
product DELL U5510 0x8118 Dell 5510 3G
product DELL U5700_3 0x8128 Dell 5700 3G
product DELL U5700_4 0x8129 Dell 5700 3G
product DELL U5720 0x8133 Dell 5720 3G
product DELL U5720_2 0x8134 Dell 5720 3G
product DELL U740 0x8135 Dell U740 CDMA
product DELL U5520 0x8136 Dell 5520 3G
product DELL U5520_2 0x8137 Dell 5520 3G
product DELL U5520_3 0x8138 Dell 5520 3G
product DELL U5730 0x8180 Dell 5730 3G
product DELL U5730_2 0x8181 Dell 5730 3G
product DELL U5730_3 0x8182 Dell 5730 3G
product DELL DW700 0x9500 Dell DW700 GPS
/* Delorme Paublishing products */
product DELORME EARTHMATE 0x0100 Earthmate GPS
/* Desknote products */
product DESKNOTE UCR_61S2B 0x0c55 UCR-61S2B
/* Diamond products */
product DIAMOND RIO500USB 0x0001 Rio 500 USB
/* Dick Smith Electronics (really C-Net) products */
product DICKSMITH RT2573 0x9022 RT2573
product DICKSMITH CWD854F 0x9032 C-Net CWD-854 rev F
/* Digi International products */
product DIGI ACCELEPORT2 0x0002 AccelePort USB 2
product DIGI ACCELEPORT4 0x0004 AccelePort USB 4
product DIGI ACCELEPORT8 0x0008 AccelePort USB 8
/* Digianswer A/S products */
product DIGIANSWER ZIGBEE802154 0x000a ZigBee/802.15.4 MAC
/* D-Link products */
/*product DLINK DSBS25 0x0100 DSB-S25 serial*/
product DLINK DUBE100 0x1a00 10/100 Ethernet
product DLINK DSB650TX4 0x200c 10/100 Ethernet
product DLINK DWL120E 0x3200 DWL-120 rev E
product DLINK DWL122 0x3700 DWL-122
product DLINK DWLG120 0x3701 DWL-G120
product DLINK DWL120F 0x3702 DWL-120 rev F
product DLINK DWLAG132 0x3a00 DWL-AG132
product DLINK DWLAG132_NF 0x3a01 DWL-AG132 (no firmware)
product DLINK DWLG132 0x3a02 DWL-G132
product DLINK DWLG132_NF 0x3a03 DWL-G132 (no firmware)
product DLINK DWLAG122 0x3a04 DWL-AG122
product DLINK DWLAG122_NF 0x3a05 DWL-AG122 (no firmware)
product DLINK DWLG122 0x3c00 DWL-G122 b1 Wireless Adapter
product DLINK DUBE100B1 0x3c05 DUB-E100 rev B1
product DLINK RT2870 0x3c09 RT2870
product DLINK RT3072 0x3c0a RT3072
product DLINK DSB650C 0x4000 10Mbps Ethernet
product DLINK DSB650TX1 0x4001 10/100 Ethernet
product DLINK DSB650TX 0x4002 10/100 Ethernet
product DLINK DSB650TX_PNA 0x4003 1/10/100 Ethernet
product DLINK DSB650TX3 0x400b 10/100 Ethernet
product DLINK DSB650TX2 0x4102 10/100 Ethernet
product DLINK DSB650 0xabc1 10/100 Ethernet
product DLINK DUBH7 0xf103 DUB-H7 USB 2.0 7-Port Hub
product DLINK2 DWA120 0x3a0c DWA-120
product DLINK2 DWA120_NF 0x3a0d DWA-120 (no firmware)
product DLINK2 DWLG122C1 0x3c03 DWL-G122 c1
product DLINK2 WUA1340 0x3c04 WUA-1340
product DLINK2 DWA111 0x3c06 DWA-111
product DLINK2 RT2870_1 0x3c09 RT2870
product DLINK2 DWA110 0x3c07 DWA-110
product DLINK2 RT3072 0x3c0a RT3072
product DLINK2 RT3072_1 0x3c0b RT3072
product DLINK2 RT3070_1 0x3c0d RT3070
product DLINK2 RT3070_2 0x3c0e RT3070
product DLINK2 RT3070_3 0x3c0f RT3070
product DLINK2 RT2870_2 0x3c11 RT2870
product DLINK2 DWA130 0x3c13 DWA-130
product DLINK2 RT3070_4 0x3c15 RT3070
product DLINK2 RT3070_5 0x3c16 RT3070
product DLINK3 DWM652 0x3e04 DWM-652
/* DMI products */
product DMI CFSM_RW 0xa109 CF/SM Reader/Writer
product DMI DISK 0x2bcf Generic Disk
/* DrayTek products */
product DRAYTEK VIGOR550 0x0550 Vigor550
/* dresden elektronik products */
product DRESDENELEKTRONIK SENSORTERMINALBOARD 0x0001 SensorTerminalBoard
product DRESDENELEKTRONIK WIRELESSHANDHELDTERMINAL 0x0004 Wireless Handheld Terminal
/* Dynastream Innovations */
product DYNASTREAM ANTDEVBOARD 0x1003 ANT dev board
product DYNASTREAM ANT2USB 0x1004 ANT2USB
product DYNASTREAM ANTDEVBOARD2 0x1006 ANT dev board
/* Edimax products */
product EDIMAX EW7318USG 0x7318 USB Wireless dongle
product EDIMAX RT2870_1 0x7711 RT2870
product EDIMAX EW7717 0x7717 EW-7717
product EDIMAX EW7718 0x7718 EW-7718
/* eGalax Products */
product EGALAX TPANEL 0x0001 Touch Panel
product EGALAX TPANEL2 0x0002 Touch Panel
product EGALAX2 TPANEL 0x0001 Touch Panel
/* Eicon Networks */
product EICON DIVA852 0x4905 Diva 852 ISDN TA
/* EIZO products */
product EIZO HUB 0x0000 hub
product EIZO MONITOR 0x0001 monitor
/* ELCON Systemtechnik products */
product ELCON PLAN 0x0002 Goldpfeil P-LAN
/* Elecom products */
product ELECOM MOUSE29UO 0x0002 mouse 29UO
product ELECOM LDUSBTX0 0x200c LD-USB/TX
product ELECOM LDUSBTX1 0x4002 LD-USB/TX
product ELECOM LDUSBLTX 0x4005 LD-USBL/TX
product ELECOM LDUSBTX2 0x400b LD-USB/TX
product ELECOM LDUSB20 0x4010 LD-USB20
product ELECOM UCSGT 0x5003 UC-SGT
product ELECOM UCSGT0 0x5004 UC-SGT
product ELECOM LDUSBTX3 0xabc1 LD-USB/TX
/* Elsa products */
product ELSA MODEM1 0x2265 ELSA Modem Board
product ELSA USB2ETHERNET 0x3000 Microlink USB2Ethernet
/* ELV products */
product ELV USBI2C 0xe00f USB-I2C interface
/* EMS products */
product EMS DUAL_SHOOTER 0x0003 PSX gun controller converter
/* Encore products */
product ENCORE RT3070_1 0x1480 RT3070
product ENCORE RT3070_2 0x14a1 RT3070
product ENCORE RT3070_3 0x14a9 RT3070
/* Entrega products */
product ENTREGA 1S 0x0001 1S serial
product ENTREGA 2S 0x0002 2S serial
product ENTREGA 1S25 0x0003 1S25 serial
product ENTREGA 4S 0x0004 4S serial
product ENTREGA E45 0x0005 E45 Ethernet
product ENTREGA CENTRONICS 0x0006 Parallel Port
product ENTREGA XX1 0x0008 Ethernet
product ENTREGA 1S9 0x0093 1S9 serial
product ENTREGA EZUSB 0x8000 EZ-USB
/*product ENTREGA SERIAL 0x8001 DB25 Serial*/
product ENTREGA 2U4S 0x8004 2U4S serial/usb hub
product ENTREGA XX2 0x8005 Ethernet
/*product ENTREGA SERIAL_DB9 0x8093 DB9 Serial*/
/* Epson products */
product EPSON PRINTER1 0x0001 USB Printer
product EPSON PRINTER2 0x0002 ISD USB Smart Cable for Mac
product EPSON PRINTER3 0x0003 ISD USB Smart Cable
product EPSON PRINTER5 0x0005 USB Printer
product EPSON 636 0x0101 Perfection 636U / 636Photo scanner
product EPSON 610 0x0103 Perfection 610 scanner
product EPSON 1200 0x0104 Perfection 1200U / 1200Photo scanner
product EPSON 1600 0x0107 Expression 1600 scanner
product EPSON 1640 0x010a Perfection 1640SU scanner
product EPSON 1240 0x010b Perfection 1240U / 1240Photo scanner
product EPSON 640U 0x010c Perfection 640U scanner
product EPSON 1250 0x010f Perfection 1250U / 1250Photo scanner
product EPSON 1650 0x0110 Perfection 1650 scanner
product EPSON GT9700F 0x0112 GT-9700F scanner
product EPSON GT9300UF 0x011b GT-9300UF scanner
product EPSON 3200 0x011c Perfection 3200 scanner
product EPSON 1260 0x011d Perfection 1260 scanner
product EPSON 1660 0x011e Perfection 1660 scanner
product EPSON 1670 0x011f Perfection 1670 scanner
product EPSON 1270 0x0120 Perfection 1270 scanner
product EPSON 2480 0x0121 Perfection 2480 scanner
product EPSON 3590 0x0122 Perfection 3590 scanner
product EPSON 4990 0x012a Perfection 4990 Photo scanner
product EPSON CRESSI_EDY 0x0521 Cressi Edy diving computer
product EPSON N2ITION3 0x0522 Zeagle N2iTion3 diving computer
product EPSON STYLUS_875DC 0x0601 Stylus Photo 875DC Card Reader
product EPSON STYLUS_895 0x0602 Stylus Photo 895 Card Reader
product EPSON CX5400 0x0808 CX5400 scanner
product EPSON 3500 0x080e CX-3500/3600/3650 MFP
product EPSON RX425 0x080f Stylus Photo RX425 scanner
product EPSON DX3800 0x0818 CX3700/CX3800/DX38x0 MFP scanner
product EPSON 4800 0x0819 CX4700/CX4800/DX48x0 MFP scanner
product EPSON 4200 0x0820 CX4100/CX4200/DX4200 MFP scanner
product EPSON 5000 0x082b CX4900/CX5000/DX50x0 MFP scanner
product EPSON 6000 0x082e CX5900/CX6000/DX60x0 MFP scanner
product EPSON DX4000 0x082f DX4000 MFP scanner
product EPSON DX7400 0x0838 CX7300/CX7400/DX7400 MFP scanner
product EPSON DX8400 0x0839 CX8300/CX8400/DX8400 MFP scanner
product EPSON SX100 0x0841 SX100/NX100 MFP scanner
product EPSON NX300 0x0848 NX300 MFP scanner
product EPSON SX200 0x0849 SX200/SX205 MFP scanner
product EPSON SX400 0x084a SX400/NX400/TX400 MFP scanner
/* e-TEK Labs products */
product ETEK 1COM 0x8007 Serial
/* Extended Systems products */
product EXTENDED XTNDACCESS 0x0100 XTNDAccess IrDA
/* Falcom products */
product FALCOM TWIST 0x0001 USB GSM/GPRS Modem
/* FEIYA products */
product FEIYA 5IN1 0x1132 5-in-1 Card Reader
/* Fiberline */
product FIBERLINE WL430U 0x6003 WL-430U
/* Fossil, Inc products */
product FOSSIL WRISTPDA 0x0002 Wrist PDA
/* Foxconn products */
product FOXCONN TCOM_TC_300 0xe000 T-Com TC 300
product FOXCONN PIRELLI_DP_L10 0xe003 Pirelli DP-L10
/* Freecom products */
product FREECOM DVD 0xfc01 DVD drive
product FREECOM HDD 0xfc05 Classic SL Hard Drive
/* Fujitsu Siemens Computers products */
product FSC E5400 0x1009 PrismGT USB 2.0 WLAN
/* Future Technology Devices products */
product FTDI SERIAL_8U100AX 0x8372 8U100AX Serial
product FTDI SERIAL_8U232AM 0x6001 8U232AM Serial
product FTDI SERIAL_8U232AM4 0x6004 8U232AM Serial
product FTDI SERIAL_2232C 0x6010 FT2232C Dual port Serial
product FTDI SERIAL_2232D 0x9e90 FT2232D Dual port Serial
product FTDI SERIAL_4232H 0x6011 FT4232H Quad port Serial
/* Gude Analog- und Digitalsysteme products also uses FTDI's id: */
product FTDI TACTRIX_OPENPORT_13M 0xcc48 OpenPort 1.3 Mitsubishi
product FTDI TACTRIX_OPENPORT_13S 0xcc49 OpenPort 1.3 Subaru
product FTDI TACTRIX_OPENPORT_13U 0xcc4a OpenPort 1.3 Universal
product FTDI GAMMASCOUT 0xd678 Gamma-Scout
product FTDI KBS 0xe6c8 Pyramid KBS USB LCD
product FTDI EISCOU 0xe888 Expert ISDN Control USB
product FTDI UOPTBR 0xe889 USB-RS232 OptoBridge
product FTDI EMCU2D 0xe88a Expert mouseCLOCK USB II
product FTDI PCMSFU 0xe88b Precision Clock MSF USB
product FTDI EMCU2H 0xe88c Expert mouseCLOCK USB II HBG
product FTDI MAXSTREAM 0xee18 Maxstream PKG-U
product FTDI USB_UIRT 0xf850 USB-UIRT
product FTDI USBSERIAL 0xfa00 Matrix Orbital USB Serial
product FTDI MX2_3 0xfa01 Matrix Orbital MX2 or MX3
product FTDI MX4_5 0xfa02 Matrix Orbital MX4 or MX5
product FTDI LK202 0xfa03 Matrix Orbital VK/LK202 Family
product FTDI LK204 0xfa04 Matrix Orbital VK/LK204 Family
product FTDI CFA_632 0xfc08 Crystalfontz CFA-632 USB LCD
product FTDI CFA_634 0xfc09 Crystalfontz CFA-634 USB LCD
product FTDI CFA_633 0xfc0b Crystalfontz CFA-633 USB LCD
product FTDI CFA_631 0xfc0c Crystalfontz CFA-631 USB LCD
product FTDI CFA_635 0xfc0d Crystalfontz CFA-635 USB LCD
product FTDI SEMC_DSS20 0xfc82 SEMC DSS-20 SyncStation
/* Commerzielle und Technische Informationssysteme GmbH products */
product FTDI CTI_USB_NANO_485 0xf60b CTI USB-Nano 485
product FTDI CTI_USB_MINI_485 0xf608 CTI USB-Mini 485
/* Fuji photo products */
product FUJIPHOTO MASS0100 0x0100 Mass Storage
/* Fujitsu protducts */
product FUJITSU AH_F401U 0x105b AH-F401U Air H device
/* Fujitsu-Siemens protducts */
product FUJITSUSIEMENS SCR 0x0009 Fujitsu-Siemens SCR USB Reader
/* Garmin products */
product GARMIN IQUE_3600 0x0004 iQue 3600
/* Gemalto products */
product GEMALTO PROXPU 0x5501 Prox-PU/CU
/* General Instruments (Motorola) products */
product GENERALINSTMNTS SB5100 0x5100 SURFboard SB5100 Cable modem
/* Genesys Logic products */
product GENESYS GL620USB 0x0501 GL620USB Host-Host interface
product GENESYS GL650 0x0604 GL650 HUB
product GENESYS GL606 0x0606 USB 2.0 HUB
product GENESYS GL641USB 0x0700 GL641USB CompactFlash Card Reader
product GENESYS GL641USB2IDE_2 0x0701 GL641USB USB-IDE Bridge No 2
product GENESYS GL641USB2IDE 0x0702 GL641USB USB-IDE Bridge
product GENESYS GL641USB_2 0x0760 GL641USB 6-in-1 Card Reader
/* GIGABYTE products */
product GIGABYTE GN54G 0x8001 GN-54G
product GIGABYTE GNBR402W 0x8002 GN-BR402W
product GIGABYTE GNWLBM101 0x8003 GN-WLBM101
product GIGABYTE GNWBKG 0x8007 GN-WBKG
product GIGABYTE GNWB01GS 0x8008 GN-WB01GS
product GIGABYTE GNWI05GS 0x800a GN-WI05GS
/* Gigaset products */
product GIGASET WLAN 0x0701 WLAN
product GIGASET SMCWUSBTG 0x0710 SMCWUSBT-G
product GIGASET SMCWUSBTG_NF 0x0711 SMCWUSBT-G (no firmware)
product GIGASET AR5523 0x0712 AR5523
product GIGASET AR5523_NF 0x0713 AR5523 (no firmware)
product GIGASET RT2573 0x0722 RT2573
product GIGASET RT3070_1 0x0740 RT3070
product GIGASET RT3070_2 0x0744 RT3070
product GIGABYTE RT2870_1 0x800b RT2870
product GIGABYTE GNWB31N 0x800c GN-WB31N
product GIGABYTE GNWB32L 0x800d GN-WB32L
/* Global Sun Technology product */
product GLOBALSUN AR5523_1 0x7801 AR5523
product GLOBALSUN AR5523_1_NF 0x7802 AR5523 (no firmware)
product GLOBALSUN AR5523_2 0x7811 AR5523
product GLOBALSUN AR5523_2_NF 0x7812 AR5523 (no firmware)
/* Globespan products */
product GLOBESPAN PRISM_GT_1 0x2000 PrismGT USB 2.0 WLAN
product GLOBESPAN PRISM_GT_2 0x2002 PrismGT USB 2.0 WLAN
/* G.Mate, Inc products */
product GMATE YP3X00 0x1001 YP3X00 PDA
/* GoHubs products */
product GOHUBS GOCOM232 0x1001 GoCOM232 Serial
/* Good Way Technology products */
product GOODWAY GWUSB2E 0x6200 GWUSB2E
product GOODWAY RT2573 0xc019 RT2573
/* Google products */
product GOOGLE NEXUSONE 0x4e11 Nexus One
/* Gravis products */
product GRAVIS GAMEPADPRO 0x4001 GamePad Pro
/* GREENHOUSE products */
product GREENHOUSE KANA21 0x0001 CF-writer with MP3
/* Griffin Technology */
product GRIFFIN IMATE 0x0405 iMate, ADB Adapter
/* Guillemot Corporation */
product GUILLEMOT DALEADER 0xa300 DA Leader
product GUILLEMOT HWGUSB254 0xe000 HWGUSB2-54 WLAN
product GUILLEMOT HWGUSB254LB 0xe010 HWGUSB2-54-LB
product GUILLEMOT HWGUSB254V2AP 0xe020 HWGUSB2-54V2-AP
product GUILLEMOT HWNU300 0xe030 HWNU-300
/* Hagiwara products */
product HAGIWARA FGSM 0x0002 FlashGate SmartMedia Card Reader
product HAGIWARA FGCF 0x0003 FlashGate CompactFlash Card Reader
product HAGIWARA FG 0x0005 FlashGate
/* HAL Corporation products */
product HAL IMR001 0x0011 Crossam2+USB IR commander
/* Handspring, Inc. */
product HANDSPRING VISOR 0x0100 Handspring Visor
product HANDSPRING TREO 0x0200 Handspring Treo
product HANDSPRING TREO600 0x0300 Handspring Treo 600
/* Hauppauge Computer Works */
product HAUPPAUGE WINTV_USB_FM 0x4d12 WinTV USB FM
product HAUPPAUGE2 NOVAT500 0x9580 NovaT 500Stick
/* Hawking Technologies products */
product HAWKING RT2870_1 0x0001 RT2870
product HAWKING RT2870_2 0x0003 RT2870
product HAWKING HWUN2 0x0009 HWUN2
product HAWKING RT3070 0x000b RT3070
product HAWKING UF100 0x400c 10/100 USB Ethernet
/* HID Global GmbH products */
product HIDGLOBAL CM2020 0x0596 Omnikey Cardman 2020
product HIDGLOBAL CM6020 0x1784 Omnikey Cardman 6020
/* Hitachi, Ltd. products */
product HITACHI DVDCAM_DZ_MV100A 0x0004 DVD-CAM DZ-MV100A Camcorder
product HITACHI DVDCAM_USB 0x001e DVDCAM USB HS Interface
/* HP products */
product HP 895C 0x0004 DeskJet 895C
product HP 4100C 0x0101 Scanjet 4100C
product HP S20 0x0102 Photosmart S20
product HP 880C 0x0104 DeskJet 880C
product HP 4200C 0x0105 ScanJet 4200C
product HP CDWRITERPLUS 0x0107 CD-Writer Plus
product HP KBDHUB 0x010c Multimedia Keyboard Hub
product HP G55XI 0x0111 OfficeJet G55xi
product HP HN210W 0x011c HN210W 802.11b WLAN
product HP 49GPLUS 0x0121 49g+ graphing calculator
product HP 6200C 0x0201 ScanJet 6200C
product HP S20b 0x0202 PhotoSmart S20
product HP 815C 0x0204 DeskJet 815C
product HP 3300C 0x0205 ScanJet 3300C
product HP CDW8200 0x0207 CD-Writer Plus 8200e
product HP MMKEYB 0x020c Multimedia keyboard
product HP 1220C 0x0212 DeskJet 1220C
product HP 810C 0x0304 DeskJet 810C/812C
product HP 4300C 0x0305 Scanjet 4300C
product HP CDW4E 0x0307 CD-Writer+ CD-4e
product HP G85XI 0x0311 OfficeJet G85xi
product HP 1200 0x0317 LaserJet 1200
product HP 5200C 0x0401 Scanjet 5200C
product HP 830C 0x0404 DeskJet 830C
product HP 3400CSE 0x0405 ScanJet 3400cse
product HP 6300C 0x0601 Scanjet 6300C
product HP 840C 0x0604 DeskJet 840c
product HP 2200C 0x0605 ScanJet 2200C
product HP 5300C 0x0701 Scanjet 5300C
product HP 4400C 0x0705 Scanjet 4400C
product HP 4470C 0x0805 Scanjet 4470C
product HP 82x0C 0x0b01 Scanjet 82x0C
product HP 2300D 0x0b17 Laserjet 2300d
product HP 970CSE 0x1004 Deskjet 970Cse
product HP 5400C 0x1005 Scanjet 5400C
product HP 2215 0x1016 iPAQ 22xx/Jornada 548
product HP 568J 0x1116 Jornada 568
product HP 930C 0x1204 DeskJet 930c
product HP P2000U 0x1801 Inkjet P-2000U
product HP HS2300 0x1e1d HS2300 HSDPA (aka MC8775)
product HP 640C 0x2004 DeskJet 640c
product HP 4670V 0x3005 ScanJet 4670v
product HP P1100 0x3102 Photosmart P1100
product HP LD220 0x3524 LD220 POS Display
product HP OJ4215 0x3d11 OfficeJet 4215
product HP HN210E 0x811c Ethernet HN210E
product HP2 C500 0x6002 PhotoSmart C500
product HP EV2200 0x1b1d ev2200 HSDPA (aka MC5720)
product HP HS2300 0x1e1d hs2300 HSDPA (aka MC8775)
/* HTC products */
product HTC WINMOBILE 0x00ce HTC USB Sync
product HTC PPC6700MODEM 0x00cf PPC6700 Modem
product HTC SMARTPHONE 0x0a51 SmartPhone USB Sync
product HTC WIZARD 0x0bce HTC Wizard USB Sync
product HTC LEGENDSYNC 0x0c97 HTC Legend USB Sync
product HTC LEGEND 0x0ff9 HTC Legend
product HTC LEGENDINTERNET 0x0ffe HTC Legend Internet Sharing
/* HUAWEI products */
product HUAWEI MOBILE 0x1001 Huawei Mobile
product HUAWEI E220 0x1003 HSDPA modem
product HUAWEI E220BIS 0x1004 HSDPA modem
product HUAWEI E1401 0x1401 3G modem
product HUAWEI E1402 0x1402 3G modem
product HUAWEI E1403 0x1403 3G modem
product HUAWEI E1404 0x1404 3G modem
product HUAWEI E1405 0x1405 3G modem
product HUAWEI E1406 0x1406 3G modem
product HUAWEI E1407 0x1407 3G modem
product HUAWEI E1408 0x1408 3G modem
product HUAWEI E1409 0x1409 3G modem
product HUAWEI E140A 0x140a 3G modem
product HUAWEI E140B 0x140b 3G modem
product HUAWEI E180V 0x140c E180V
product HUAWEI E140D 0x140d 3G modem
product HUAWEI E140E 0x140e 3G modem
product HUAWEI E140F 0x140f 3G modem
product HUAWEI E1410 0x1410 3G modem
product HUAWEI E1411 0x1411 3G modem
product HUAWEI E1412 0x1412 3G modem
product HUAWEI E1413 0x1413 3G modem
product HUAWEI E1414 0x1414 3G modem
product HUAWEI E1415 0x1415 3G modem
product HUAWEI E1416 0x1416 3G modem
product HUAWEI E1417 0x1417 3G modem
product HUAWEI E1418 0x1418 3G modem
product HUAWEI E1419 0x1419 3G modem
product HUAWEI E141A 0x141a 3G modem
product HUAWEI E141B 0x141b 3G modem
product HUAWEI E141C 0x141c 3G modem
product HUAWEI E141D 0x141d 3G modem
product HUAWEI E141E 0x141e 3G modem
product HUAWEI E141F 0x141f 3G modem
product HUAWEI E1420 0x1420 3G modem
product HUAWEI E1421 0x1421 3G modem
product HUAWEI E1422 0x1422 3G modem
product HUAWEI E1423 0x1423 3G modem
product HUAWEI E1424 0x1424 3G modem
product HUAWEI E1425 0x1425 3G modem
product HUAWEI E1426 0x1426 3G modem
product HUAWEI E1427 0x1427 3G modem
product HUAWEI E1428 0x1428 3G modem
product HUAWEI E1429 0x1429 3G modem
product HUAWEI E142A 0x142a 3G modem
product HUAWEI E142B 0x142b 3G modem
product HUAWEI E142C 0x142c 3G modem
product HUAWEI E142D 0x142d 3G modem
product HUAWEI E142E 0x142e 3G modem
product HUAWEI E142F 0x142f 3G modem
product HUAWEI E1430 0x1430 3G modem
product HUAWEI E1431 0x1431 3G modem
product HUAWEI E1432 0x1432 3G modem
product HUAWEI E1433 0x1433 3G modem
product HUAWEI E1434 0x1434 3G modem
product HUAWEI E1435 0x1435 3G modem
product HUAWEI E1436 0x1436 3G modem
product HUAWEI E1437 0x1437 3G modem
product HUAWEI E1438 0x1438 3G modem
product HUAWEI E1439 0x1439 3G modem
product HUAWEI E143A 0x143a 3G modem
product HUAWEI E143B 0x143b 3G modem
product HUAWEI E143C 0x143c 3G modem
product HUAWEI E143D 0x143d 3G modem
product HUAWEI E143E 0x143e 3G modem
product HUAWEI E143F 0x143f 3G modem
product HUAWEI E1752 0x1446 3G modem
product HUAWEI K3765 0x1465 3G modem
product HUAWEI E1820 0x14ac E1820 HSPA+ USB Slider
product HUAWEI K3765_INIT 0x1520 K3765 Initial
/* HUAWEI 3com products */
product HUAWEI3COM WUB320G 0x0009 Aolynk WUB320g
/* IBM Corporation */
product IBM USBCDROMDRIVE 0x4427 USB CD-ROM Drive
/* Imagination Technologies products */
product IMAGINATION DBX1 0x2107 DBX1 DSP core
/* Inside Out Networks products */
product INSIDEOUT EDGEPORT4 0x0001 EdgePort/4 serial ports
/* In-System products */
product INSYSTEM F5U002 0x0002 Parallel printer
product INSYSTEM ATAPI 0x0031 ATAPI Adapter
product INSYSTEM ISD110 0x0200 IDE Adapter ISD110
product INSYSTEM ISD105 0x0202 IDE Adapter ISD105
product INSYSTEM USBCABLE 0x081a USB cable
product INSYSTEM STORAGE_V2 0x5701 USB Storage Adapter V2
/* Intel products */
product INTEL EASYPC_CAMERA 0x0110 Easy PC Camera
product INTEL TESTBOARD 0x9890 82930 test board
product INTEL2 IRMH 0x0020 Integrated Rate Matching Hub
/* Intersil products */
product INTERSIL PRISM_GT 0x1000 PrismGT USB 2.0 WLAN
product INTERSIL PRISM_2X 0x3642 Prism2.x or Atmel WLAN
/* Interpid Control Systems products */
product INTREPIDCS VALUECAN 0x0601 ValueCAN CAN bus interface
product INTREPIDCS NEOVI 0x0701 NeoVI Blue vehicle bus interface
/* I/O DATA products */
product IODATA IU_CD2 0x0204 DVD Multi-plus unit iU-CD2
product IODATA DVR_UEH8 0x0206 DVD Multi-plus unit DVR-UEH8
product IODATA USBSSMRW 0x0314 USB-SSMRW SD-card
product IODATA USBSDRW 0x031e USB-SDRW SD-card
product IODATA USBETT 0x0901 USB ETT
product IODATA USBETTX 0x0904 USB ETTX
product IODATA USBETTXS 0x0913 USB ETTX
product IODATA USBWNB11A 0x0919 USB WN-B11
product IODATA USBWNB11 0x0922 USB Airport WN-B11
product IODATA ETGUS2 0x0930 ETG-US2
product IODATA RT3072_1 0x0944 RT3072
product IODATA RT3072_2 0x0945 RT3072
product IODATA RT3072_3 0x0947 RT3072
product IODATA RT3072_4 0x0948 RT3072
product IODATA USBRSAQ 0x0a03 Serial USB-RSAQ1
product IODATA USBRSAQ5 0x0a0e Serial USB-RSAQ5
product IODATA2 USB2SC 0x0a09 USB2.0-SCSI Bridge USB2-SC
/* Iomega products */
product IOMEGA ZIP100 0x0001 Zip 100
product IOMEGA ZIP250 0x0030 Zip 250
/* Integrated System Solution Corp. products */
product ISSC ISSCBTA 0x1001 Bluetooth USB Adapter
/* iTegno products */
product ITEGNO WM1080A 0x1080 WM1080A GSM/GPRS modem
product ITEGNO WM2080A 0x2080 WM2080A CDMA modem
/* Ituner networks products */
product ITUNERNET USBLCD2X20 0x0002 USB-LCD 2x20
product ITUNERNET USBLCD4X20 0xc001 USB-LCD 4x20
/* Jablotron products */
product JABLOTRON PC60B 0x0001 PC-60B
/* Jaton products */
product JATON EDA 0x5704 Ethernet
/* JMicron products */
product JMICRON JM20336 0x2336 USB to SATA Bridge
product JMICRON JM20337 0x2338 USB to ATA/ATAPI Bridge
/* JVC products */
product JVC GR_DX95 0x000a GR-DX95
product JVC MP_PRX1 0x3008 MP-PRX1 Ethernet
/* JRC products */
product JRC AH_J3001V_J3002V 0x0001 AirH PHONE AH-J3001V/J3002V
/* Kawatsu products */
product KAWATSU MH4000P 0x0003 MiniHub 4000P
/* Keisokugiken Corp. products */
product KEISOKUGIKEN USBDAQ 0x0068 HKS-0200 USBDAQ
/* Kensington products */
product KENSINGTON ORBIT 0x1003 Orbit USB/PS2 trackball
product KENSINGTON TURBOBALL 0x1005 TurboBall
/* Keyspan products */
product KEYSPAN USA28_NF 0x0101 USA-28 serial Adapter (no firmware)
product KEYSPAN USA28X_NF 0x0102 USA-28X serial Adapter (no firmware)
product KEYSPAN USA19_NF 0x0103 USA-19 serial Adapter (no firmware)
product KEYSPAN USA18_NF 0x0104 USA-18 serial Adapter (no firmware)
product KEYSPAN USA18X_NF 0x0105 USA-18X serial Adapter (no firmware)
product KEYSPAN USA19W_NF 0x0106 USA-19W serial Adapter (no firmware)
product KEYSPAN USA19 0x0107 USA-19 serial Adapter
product KEYSPAN USA19W 0x0108 USA-19W serial Adapter
product KEYSPAN USA49W_NF 0x0109 USA-49W serial Adapter (no firmware)
product KEYSPAN USA49W 0x010a USA-49W serial Adapter
product KEYSPAN USA19QI_NF 0x010b USA-19QI serial Adapter (no firmware)
product KEYSPAN USA19QI 0x010c USA-19QI serial Adapter
product KEYSPAN USA19Q_NF 0x010d USA-19Q serial Adapter (no firmware)
product KEYSPAN USA19Q 0x010e USA-19Q serial Adapter
product KEYSPAN USA28 0x010f USA-28 serial Adapter
product KEYSPAN USA28XXB 0x0110 USA-28X/XB serial Adapter
product KEYSPAN USA18 0x0111 USA-18 serial Adapter
product KEYSPAN USA18X 0x0112 USA-18X serial Adapter
product KEYSPAN USA28XB_NF 0x0113 USA-28XB serial Adapter (no firmware)
product KEYSPAN USA28XA_NF 0x0114 USA-28XB serial Adapter (no firmware)
product KEYSPAN USA28XA 0x0115 USA-28XA serial Adapter
product KEYSPAN USA18XA_NF 0x0116 USA-18XA serial Adapter (no firmware)
product KEYSPAN USA18XA 0x0117 USA-18XA serial Adapter
product KEYSPAN USA19QW_NF 0x0118 USA-19WQ serial Adapter (no firmware)
product KEYSPAN USA19QW 0x0119 USA-19WQ serial Adapter
product KEYSPAN USA19HA 0x0121 USA-19HS serial Adapter
product KEYSPAN UIA10 0x0201 UIA-10 remote control
product KEYSPAN UIA11 0x0202 UIA-11 remote control
/* Kingston products */
product KINGSTON XX1 0x0008 Ethernet
product KINGSTON KNU101TX 0x000a KNU101TX USB Ethernet
/* Kawasaki products */
product KLSI DUH3E10BT 0x0008 USB Ethernet
product KLSI DUH3E10BTN 0x0009 USB Ethernet
/* Kodak products */
product KODAK DC220 0x0100 Digital Science DC220
product KODAK DC260 0x0110 Digital Science DC260
product KODAK DC265 0x0111 Digital Science DC265
product KODAK DC290 0x0112 Digital Science DC290
product KODAK DC240 0x0120 Digital Science DC240
product KODAK DC280 0x0130 Digital Science DC280
+/* Kontron AG products */
+product KONTRON DM9601 0x8101 USB Ethernet
+
/* Konica Corp. Products */
product KONICA CAMERA 0x0720 Digital Color Camera
/* KYE products */
product KYE NICHE 0x0001 Niche mouse
product KYE NETSCROLL 0x0003 Genius NetScroll mouse
product KYE FLIGHT2000 0x1004 Flight 2000 joystick
product KYE VIVIDPRO 0x2001 ColorPage Vivid-Pro scanner
/* Kyocera products */
product KYOCERA FINECAM_S3X 0x0100 Finecam S3x
product KYOCERA FINECAM_S4 0x0101 Finecam S4
product KYOCERA FINECAM_S5 0x0103 Finecam S5
product KYOCERA FINECAM_L3 0x0105 Finecam L3
product KYOCERA AHK3001V 0x0203 AH-K3001V
product KYOCERA2 CDMA_MSM_K 0x17da Qualcomm Kyocera CDMA Technologies MSM
product KYOCERA2 KPC680 0x180a Qualcomm Kyocera CDMA Technologies MSM
/* LaCie products */
product LACIE HD 0xa601 Hard Disk
product LACIE CDRW 0xa602 CD R/W
/* Leadtek products */
product LEADTEK 9531 0x2101 9531 GPS
/* Lexar products */
product LEXAR JUMPSHOT 0x0001 jumpSHOT CompactFlash Reader
product LEXAR CF_READER 0xb002 USB CF Reader
/* Lexmark products */
product LEXMARK S2450 0x0009 Optra S 2450
/* Liebert products */
product LIEBERT POWERSURE_PXT 0xffff PowerSure Personal XT
/* Linksys products */
product LINKSYS MAUSB2 0x0105 Camedia MAUSB-2
product LINKSYS USB10TX1 0x200c USB10TX
product LINKSYS USB10T 0x2202 USB10T Ethernet
product LINKSYS USB100TX 0x2203 USB100TX Ethernet
product LINKSYS USB100H1 0x2204 USB100H1 Ethernet/HPNA
product LINKSYS USB10TA 0x2206 USB10TA Ethernet
product LINKSYS USB10TX2 0x400b USB10TX
product LINKSYS2 WUSB11 0x2219 WUSB11 Wireless Adapter
product LINKSYS2 USB200M 0x2226 USB 2.0 10/100 Ethernet
product LINKSYS3 WUSB11v28 0x2233 WUSB11 v2.8 Wireless Adapter
product LINKSYS4 USB1000 0x0039 USB1000
product LINKSYS4 WUSB100 0x0070 WUSB100
product LINKSYS4 WUSB600N 0x0071 WUSB600N
product LINKSYS4 WUSB54GCV2 0x0073 WUSB54GC v2
product LINKSYS4 WUSB54GCV3 0x0077 WUSB54GC v3
product LINKSYS4 RT3070 0x0078 RT3070
product LINKSYS4 WUSB600NV2 0x0079 WUSB600N v2
/* Logitech products */
product LOGITECH M2452 0x0203 M2452 keyboard
product LOGITECH M4848 0x0301 M4848 mouse
product LOGITECH PAGESCAN 0x040f PageScan
product LOGITECH QUICKCAMWEB 0x0801 QuickCam Web
product LOGITECH QUICKCAMPRO 0x0810 QuickCam Pro
product LOGITECH QUICKCAMEXP 0x0840 QuickCam Express
product LOGITECH QUICKCAM 0x0850 QuickCam
product LOGITECH QUICKCAMPRO3 0x0990 QuickCam Pro 9000
product LOGITECH N43 0xc000 N43
product LOGITECH N48 0xc001 N48 mouse
product LOGITECH MBA47 0xc002 M-BA47 mouse
product LOGITECH WMMOUSE 0xc004 WingMan Gaming Mouse
product LOGITECH BD58 0xc00c BD58 mouse
product LOGITECH UN58A 0xc030 iFeel Mouse
product LOGITECH UN53B 0xc032 iFeel MouseMan
product LOGITECH WMPAD 0xc208 WingMan GamePad Extreme
product LOGITECH WMRPAD 0xc20a WingMan RumblePad
product LOGITECH WMJOY 0xc281 WingMan Force joystick
product LOGITECH BB13 0xc401 USB-PS/2 Trackball
product LOGITECH RK53 0xc501 Cordless mouse
product LOGITECH RB6 0xc503 Cordless keyboard
product LOGITECH MX700 0xc506 Cordless optical mouse
product LOGITECH QUICKCAMPRO2 0xd001 QuickCam Pro
/* Logitec Corp. products */
product LOGITEC LDR_H443SU2 0x0033 DVD Multi-plus unit LDR-H443SU2
product LOGITEC LDR_H443U2 0x00b3 DVD Multi-plus unit LDR-H443U2
product LOGITEC LAN_GTJU2A 0x0160 LAN-GTJ/U2A Ethernet
product LOGITEC RT2870_1 0x0162 RT2870
product LOGITEC RT2870_2 0x0163 RT2870
product LOGITEC RT2870_3 0x0164 RT2870
/* Longcheer Holdings, Ltd. products */
product LONGCHEER WM66 0x6061 Longcheer WM66 HSDPA
product LONGCHEER W14 0x9603 Mobilcom W14
product LONGCHEER DISK 0xf000 Driver disk
/* Lucent products */
product LUCENT EVALKIT 0x1001 USS-720 evaluation kit
/* Luwen products */
product LUWEN EASYDISK 0x0005 EasyDisc
/* Macally products */
product MACALLY MOUSE1 0x0101 mouse
/* Marvell Technology Group, Ltd. products */
product MARVELL SHEEVAPLUG 0x9e8f SheevaPlug serial interface
/* Matrix Orbital products */
product MATRIXORBITAL MOUA 0x0153 Martrix Orbital MOU-Axxxx LCD displays
/* MCT Corp. */
product MCT HUB0100 0x0100 Hub
product MCT DU_H3SP_USB232 0x0200 D-Link DU-H3SP USB BAY Hub
product MCT USB232 0x0210 USB-232 Interface
product MCT SITECOM_USB232 0x0230 Sitecom USB-232 Products
/* MediaTek, Inc. */
product MEDIATEK MTK3329 0x3329 MTK II GPS Receiver
/* Meizu Electronics */
product MEIZU M6_SL 0x0140 MiniPlayer M6 (SL)
/* Melco, Inc products */
product MELCO LUATX1 0x0001 LUA-TX Ethernet
product MELCO LUATX5 0x0005 LUA-TX Ethernet
product MELCO LUA2TX5 0x0009 LUA2-TX Ethernet
product MELCO LUAKTX 0x0012 LUA-KTX Ethernet
product MELCO DUBPXXG 0x001c DUB-PxxG
product MELCO LUAU2KTX 0x003d LUA-U2-KTX Ethernet
product MELCO KG54YB 0x005e WLI-U2-KG54-YB WLAN
product MELCO KG54 0x0066 WLI-U2-KG54 WLAN
product MELCO KG54AI 0x0067 WLI-U2-KG54-AI WLAN
product MELCO LUA3U2AGT 0x006e LUA3-U2-AGT
product MELCO NINWIFI 0x008b Nintendo Wi-Fi
product MELCO PCOPRS1 0x00b3 PC-OP-RS1 RemoteStation
product MELCO SG54HP 0x00d8 WLI-U2-SG54HP
product MELCO G54HP 0x00d9 WLI-U2-G54HP
product MELCO KG54L 0x00da WLI-U2-KG54L
product MELCO WLIUCG300N 0x00e8 WLI-UC-G300N
product MELCO SG54HG 0x00f4 WLI-U2-SG54HG
product MELCO WLRUCG 0x0116 WLR-UC-G
product MELCO WLRUCGAOSS 0x0119 WLR-UC-G-AOSS
product MELCO WLIUCAG300N 0x012e WLI-UC-AG300N
product MELCO WLIUCG 0x0137 WLI-UC-G
product MELCO RT2870_1 0x0148 RT2870
product MELCO RT2870_2 0x0150 RT2870
product MELCO WLIUCGN 0x015d WLI-UC-GN
/* Merlin products */
product MERLIN V620 0x1110 Merlin V620
/* MetaGeek products */
product METAGEEK WISPY1B 0x083e MetaGeek Wi-Spy
product METAGEEK WISPY24X 0x083f MetaGeek Wi-Spy 2.4x
product METAGEEK2 WISPYDBX 0x5000 MetaGeek Wi-Spy DBx
/* Metricom products */
product METRICOM RICOCHET_GS 0x0001 Ricochet GS
/* MGE UPS Systems */
product MGE UPS1 0x0001 MGE UPS SYSTEMS PROTECTIONCENTER 1
product MGE UPS2 0xffff MGE UPS SYSTEMS PROTECTIONCENTER 2
/* MEI products */
product MEI CASHFLOW_SC 0x1100 Cashflow-SC Cash Acceptor
product MEI S2000 0x1101 Seies 2000 Combo Acceptor
/* Micro Star International products */
product MSI BT_DONGLE 0x1967 Bluetooth USB dongle
product MSI RT3070_1 0x3820 RT3070
product MSI RT3070_2 0x3821 RT3070
product MSI RT3070_8 0x3822 RT3070
product MSI RT3070_3 0x3870 RT3070
product MSI RT3070_9 0x3871 RT3070
product MSI UB11B 0x6823 UB11B
product MSI RT2570 0x6861 RT2570
product MSI RT2570_2 0x6865 RT2570
product MSI RT2570_3 0x6869 RT2570
product MSI RT2573_1 0x6874 RT2573
product MSI RT2573_2 0x6877 RT2573
product MSI RT3070_4 0x6899 RT3070
product MSI RT3070_5 0x821a RT3070
product MSI RT3070_10 0x822a RT3070
product MSI RT3070_6 0x870a RT3070
product MSI RT3070_11 0x871a RT3070
product MSI RT3070_7 0x899a RT3070
product MSI RT2573_3 0xa861 RT2573
product MSI RT2573_4 0xa874 RT2573
/* Microsoft products */
product MICROSOFT SIDEPREC 0x0008 SideWinder Precision Pro
product MICROSOFT INTELLIMOUSE 0x0009 IntelliMouse
product MICROSOFT NATURALKBD 0x000b Natural Keyboard Elite
product MICROSOFT DDS80 0x0014 Digital Sound System 80
product MICROSOFT SIDEWINDER 0x001a Sidewinder Precision Racing Wheel
product MICROSOFT INETPRO 0x001c Internet Keyboard Pro
product MICROSOFT TBEXPLORER 0x0024 Trackball Explorer
product MICROSOFT INTELLIEYE 0x0025 IntelliEye mouse
product MICROSOFT INETPRO2 0x002b Internet Keyboard Pro
product MICROSOFT INTELLIMOUSE5 0x0039 IntelliMouse 1.1 5-Button Mouse
product MICROSOFT WHEELMOUSE 0x0040 Wheel Mouse Optical
product MICROSOFT MN510 0x006e MN510 Wireless
product MICROSOFT 700WX 0x0079 Palm 700WX
product MICROSOFT MN110 0x007a 10/100 USB NIC
product MICROSOFT WLINTELLIMOUSE 0x008c Wireless Optical IntelliMouse
product MICROSOFT WLNOTEBOOK 0x00b9 Wireless Optical Mouse (Model 1023)
product MICROSOFT COMFORT3000 0x00d1 Comfort Optical Mouse 3000 (Model 1043)
product MICROSOFT WLNOTEBOOK3 0x00d2 Wireless Optical Mouse 3000 (Model 1049)
product MICROSOFT NATURAL4000 0x00db Natural Ergonomic Keyboard 4000
product MICROSOFT WLNOTEBOOK2 0x00e1 Wireless Optical Mouse 3000 (Model 1056)
product MICROSOFT XBOX360 0x0292 XBOX 360 WLAN
/* Microtech products */
product MICROTECH SCSIDB25 0x0004 USB-SCSI-DB25
product MICROTECH SCSIHD50 0x0005 USB-SCSI-HD50
product MICROTECH DPCM 0x0006 USB CameraMate
product MICROTECH FREECOM 0xfc01 Freecom USB-IDE
/* Microtek products */
product MICROTEK 336CX 0x0094 Phantom 336CX - C3 scanner
product MICROTEK X6U 0x0099 ScanMaker X6 - X6U
product MICROTEK C6 0x009a Phantom C6 scanner
product MICROTEK 336CX2 0x00a0 Phantom 336CX - C3 scanner
product MICROTEK V6USL 0x00a3 ScanMaker V6USL
product MICROTEK V6USL2 0x80a3 ScanMaker V6USL
product MICROTEK V6UL 0x80ac ScanMaker V6UL
/* Microtune, Inc. products */
product MICROTUNE BT_DONGLE 0x1000 Bluetooth USB dongle
/* Midiman products */
product MIDIMAN MIDISPORT2X2 0x1001 Midisport 2x2
/* MindsAtWork products */
product MINDSATWORK WALLET 0x0001 Digital Wallet
/* Minolta Co., Ltd. */
product MINOLTA 2300 0x4001 Dimage 2300
product MINOLTA S304 0x4007 Dimage S304
product MINOLTA X 0x4009 Dimage X
product MINOLTA 5400 0x400e Dimage 5400
product MINOLTA F300 0x4011 Dimage F300
product MINOLTA E223 0x4017 Dimage E223
/* Mitsumi products */
product MITSUMI CDRRW 0x0000 CD-R/RW Drive
product MITSUMI BT_DONGLE 0x641f Bluetooth USB dongle
product MITSUMI FDD 0x6901 USB FDD
/* Mobile Action products */
product MOBILEACTION MA620 0x0620 MA-620 Infrared Adapter
/* Mobility products */
product MOBILITY EA 0x0204 Ethernet
product MOBILITY EASIDOCK 0x0304 EasiDock Ethernet
/* MosChip products */
product MOSCHIP MCS7703 0x7703 MCS7703 Serial Port Adapter
product MOSCHIP MCS7730 0x7730 MCS7730 Ethernet
product MOSCHIP MCS7830 0x7830 MCS7830 Ethernet
/* Motorola products */
product MOTOROLA MC141555 0x1555 MC141555 hub controller
product MOTOROLA SB4100 0x4100 SB4100 USB Cable Modem
product MOTOROLA2 T720C 0x2822 T720c
product MOTOROLA2 A41XV32X 0x2a22 A41x/V32x Mobile Phones
product MOTOROLA2 E398 0x4810 E398 Mobile Phone
product MOTOROLA2 USBLAN 0x600c USBLAN
product MOTOROLA2 USBLAN2 0x6027 USBLAN
product MOTOROLA4 RT2770 0x9031 RT2770
product MOTOROLA4 RT3070 0x9032 RT3070
/* MultiTech products */
product MULTITECH ATLAS 0xf101 MT5634ZBA-USB modem
/* Mustek products */
product MUSTEK 1200CU 0x0001 1200 CU scanner
product MUSTEK 600CU 0x0002 600 CU scanner
product MUSTEK 1200USB 0x0003 1200 USB scanner
product MUSTEK 1200UB 0x0006 1200 UB scanner
product MUSTEK 1200USBPLUS 0x0007 1200 USB Plus scanner
product MUSTEK 1200CUPLUS 0x0008 1200 CU Plus scanner
product MUSTEK BEARPAW1200F 0x0010 BearPaw 1200F scanner
product MUSTEK BEARPAW2400TA 0x0218 BearPaw 2400TA scanner
product MUSTEK BEARPAW1200TA 0x021e BearPaw 1200TA scanner
product MUSTEK 600USB 0x0873 600 USB scanner
product MUSTEK MDC800 0xa800 MDC-800 digital camera
/* M-Systems products */
product MSYSTEMS DISKONKEY 0x0010 DiskOnKey
product MSYSTEMS DISKONKEY2 0x0011 DiskOnKey
/* Myson products */
product MYSON HEDEN_8813 0x8813 USB-IDE
product MYSON HEDEN 0x8818 USB-IDE
product MYSON HUBREADER 0x8819 COMBO Card reader with USB HUB
product MYSON STARREADER 0x9920 USB flash card adapter
/* National Semiconductor */
product NATIONAL BEARPAW1200 0x1000 BearPaw 1200
product NATIONAL BEARPAW2400 0x1001 BearPaw 2400
/* NEC products */
product NEC HUB_0050 0x0050 USB 2.0 7-Port Hub
product NEC HUB_005A 0x005a USB 2.0 4-Port Hub
product NEC HUB 0x55aa hub
product NEC HUB_B 0x55ab hub
/* NEODIO products */
product NEODIO ND3260 0x3260 8-in-1 Multi-format Flash Controller
product NEODIO ND5010 0x5010 Multi-format Flash Controller
/* Neotel products */
product NEOTEL PRIME 0x4000 Prime USB modem
/* Netac products */
product NETAC CF_CARD 0x1060 USB-CF-Card
product NETAC ONLYDISK 0x0003 OnlyDisk
/* NetChip Technology Products */
product NETCHIP TURBOCONNECT 0x1080 Turbo-Connect
product NETCHIP CLIK_40 0xa140 USB Clik! 40
product NETCHIP ETHERNETGADGET 0xa4a2 Linux Ethernet/RNDIS gadget on pxa210/25x/26x
/* Netgear products */
product NETGEAR EA101 0x1001 Ethernet
product NETGEAR EA101X 0x1002 Ethernet
product NETGEAR FA101 0x1020 Ethernet 10/100, USB1.1
product NETGEAR FA120 0x1040 USB 2.0 Ethernet
product NETGEAR WG111V2_2 0x4240 PrismGT USB 2.0 WLAN
product NETGEAR WG111V3 0x4260 WG111v3
product NETGEAR WG111U 0x4300 WG111U
product NETGEAR WG111U_NF 0x4301 WG111U (no firmware)
product NETGEAR WG111V2 0x6a00 WG111V2
product NETGEAR2 MA101 0x4100 MA101
product NETGEAR2 MA101B 0x4102 MA101 Rev B
product NETGEAR3 WG111T 0x4250 WG111T
product NETGEAR3 WG111T_NF 0x4251 WG111T (no firmware)
product NETGEAR3 WPN111 0x5f00 WPN111
product NETGEAR3 WPN111_NF 0x5f01 WPN111 (no firmware)
product NETGEAR3 WPN111_2 0x5f02 WPN111
/* NetIndex products */
product NETINDEX WS002IN 0x2001 Willcom WS002IN
/* NEWlink */
product NEWLINK USB2IDEBRIDGE 0x00ff USB 2.0 Hard Drive Enclosure
/* Nikon products */
product NIKON E990 0x0102 Digital Camera E990
product NIKON LS40 0x4000 CoolScan LS40 ED
product NIKON D300 0x041a Digital Camera D300
/* NovaTech Products */
product NOVATECH NV902 0x9020 NovaTech NV-902W
product NOVATECH RT2573 0x9021 RT2573
/* Nokia products */
product NOKIA N958GB 0x0070 Nokia N95 8GBc
product NOKIA2 CA42 0x1234 CA-42 cable
/* Novatel Wireless products */
product NOVATEL V640 0x1100 Merlin V620
product NOVATEL CDMA_MODEM 0x1110 Novatel Wireless Merlin CDMA
product NOVATEL V620 0x1110 Merlin V620
product NOVATEL V740 0x1120 Merlin V740
product NOVATEL V720 0x1130 Merlin V720
product NOVATEL U740 0x1400 Merlin U740
product NOVATEL U740_2 0x1410 Merlin U740
product NOVATEL U870 0x1420 Merlin U870
product NOVATEL XU870 0x1430 Merlin XU870
product NOVATEL X950D 0x1450 Merlin X950D
product NOVATEL ES620 0x2100 Expedite ES620
product NOVATEL E725 0x2120 Expedite E725
product NOVATEL ES620_2 0x2130 Expedite ES620
product NOVATEL ES620 0x2100 ES620 CDMA
product NOVATEL U720 0x2110 Merlin U720
product NOVATEL EU730 0x2400 Expedite EU730
product NOVATEL EU740 0x2410 Expedite EU740
product NOVATEL EU870D 0x2420 Expedite EU870D
product NOVATEL U727 0x4100 Merlin U727 CDMA
product NOVATEL MC950D 0x4400 Novatel MC950D HSUPA
product NOVATEL ZEROCD 0x5010 Novatel ZeroCD
product NOVATEL ZEROCD2 0x5030 Novatel ZeroCD
product NOVATEL U727_2 0x5100 Merlin U727 CDMA
product NOVATEL U760 0x6000 Novatel U760
product NOVATEL MC760 0x6002 Novatel MC760
product NOVATEL MC547 0x7042 Novatel MC547
product NOVATEL2 FLEXPACKGPS 0x0100 NovAtel FlexPack GPS receiver
/* Merlin products */
product MERLIN V620 0x1110 Merlin V620
/* O2Micro products */
product O2MICRO OZ776_HUB 0x7761 OZ776 hub
product O2MICRO OZ776_CCID_SC 0x7772 OZ776 CCID SC Reader
/* Olympus products */
product OLYMPUS C1 0x0102 C-1 Digital Camera
product OLYMPUS C700 0x0105 C-700 Ultra Zoom
/* OmniVision Technologies, Inc. products */
product OMNIVISION OV511 0x0511 OV511 Camera
product OMNIVISION OV511PLUS 0xa511 OV511+ Camera
/* OnSpec Electronic, Inc. */
product ONSPEC SDS_HOTFIND_D 0x0400 SDS-infrared.com Hotfind-D Infrared Camera
product ONSPEC MDCFE_B_CF_READER 0xa000 MDCFE-B USB CF Reader
product ONSPEC CFMS_RW 0xa001 SIIG/Datafab Memory Stick+CF Reader/Writer
product ONSPEC READER 0xa003 Datafab-based Reader
product ONSPEC CFSM_READER 0xa005 PNY/Datafab CF+SM Reader
product ONSPEC CFSM_READER2 0xa006 Simple Tech/Datafab CF+SM Reader
product ONSPEC MDSM_B_READER 0xa103 MDSM-B reader
product ONSPEC CFSM_COMBO 0xa109 USB to CF + SM Combo (LC1)
product ONSPEC UCF100 0xa400 FlashLink UCF-100 CompactFlash Reader
product ONSPEC2 IMAGEMATE_SDDR55 0xa103 ImageMate SDDR55
/* Option products */
product OPTION VODAFONEMC3G 0x5000 Vodafone Mobile Connect 3G datacard
product OPTION GT3G 0x6000 GlobeTrotter 3G datacard
product OPTION GT3GQUAD 0x6300 GlobeTrotter 3G QUAD datacard
product OPTION GT3GPLUS 0x6600 GlobeTrotter 3G+ datacard
product OPTION GTICON322 0xd033 GlobeTrotter Icon322 storage
product OPTION GTMAX36 0x6701 GlobeTrotter Max 3.6 Modem
product OPTION GTHSDPA 0x6971 GlobeTrotter HSDPA
product OPTION GTMAXHSUPA 0x7001 GlobeTrotter HSUPA
product OPTION GTMAXHSUPAE 0x6901 GlobeTrotter HSUPA PCIe
product OPTION GTMAX380HSUPAE 0x7211 GlobeTrotter 380HSUPA PCIe
product OPTION GT3G_1 0x6050 3G modem
product OPTION GT3G_2 0x6100 3G modem
product OPTION GT3G_3 0x6150 3G modem
product OPTION GT3G_4 0x6200 3G modem
product OPTION GT3G_5 0x6250 3G modem
product OPTION GT3G_6 0x6350 3G modem
product OPTION E6500 0x6500 3G modem
product OPTION E6501 0x6501 3G modem
product OPTION E6601 0x6601 3G modem
product OPTION E6721 0x6721 3G modem
product OPTION E6741 0x6741 3G modem
product OPTION E6761 0x6761 3G modem
product OPTION E6800 0x6800 3G modem
product OPTION E7021 0x7021 3G modem
product OPTION E7041 0x7041 3G modem
product OPTION E7061 0x7061 3G modem
product OPTION E7100 0x7100 3G modem
product OPTION GTM380 0x7201 3G modem
product OPTION GE40X 0x7601 Globetrotter HSUPA
product OPTION GSICON72 0x6911 GlobeSurfer iCON
product OPTION GSICONHSUPA 0x7251 Globetrotter HSUPA
product OPTION ICON401 0x7401 GlobeSurfer iCON 401
product OPTION GTHSUPA 0x7011 Globetrotter HSUPA
product OPTION GMT382 0x7501 Globetrotter HSUPA
product OPTION GE40X_1 0x7301 Globetrotter HSUPA
product OPTION GE40X_2 0x7361 Globetrotter HSUPA
product OPTION GE40X_3 0x7381 Globetrotter HSUPA
product OPTION ICONEDGE 0xc031 GlobeSurfer iCON EDGE
product OPTION MODHSXPA 0xd013 Globetrotter HSUPA
product OPTION ICON321 0xd031 Globetrotter HSUPA
product OPTION ICON505 0xd055 Globetrotter iCON 505
product OPTION ICON452 0x7901 Globetrotter iCON 452
/* OvisLink product */
product OVISLINK RT3072 0x3072 RT3072
/* OQO */
product OQO WIFI01 0x0002 model 01 WiFi interface
product OQO BT01 0x0003 model 01 Bluetooth interface
product OQO ETHER01PLUS 0x7720 model 01+ Ethernet
product OQO ETHER01 0x8150 model 01 Ethernet interface
/* Ours Technology Inc. */
product OTI DKU5 0x6858 DKU-5 Serial
/* Owen.ru products */
product OWEN AC4 0x0004 AC4 USB-RS485 converter
/* Palm Computing, Inc. product */
product PALM SERIAL 0x0080 USB Serial
product PALM M500 0x0001 Palm m500
product PALM M505 0x0002 Palm m505
product PALM M515 0x0003 Palm m515
product PALM I705 0x0020 Palm i705
product PALM TUNGSTEN_Z 0x0031 Palm Tungsten Z
product PALM M125 0x0040 Palm m125
product PALM M130 0x0050 Palm m130
product PALM TUNGSTEN_T 0x0060 Palm Tungsten T
product PALM ZIRE31 0x0061 Palm Zire 31
product PALM ZIRE 0x0070 Palm Zire
/* Panasonic products */
product PANASONIC LS120CAM 0x0901 LS-120 Camera
product PANASONIC KXL840AN 0x0d01 CD-R Drive KXL-840AN
product PANASONIC KXLRW32AN 0x0d09 CD-R Drive KXL-RW32AN
product PANASONIC KXLCB20AN 0x0d0a CD-R Drive KXL-CB20AN
product PANASONIC KXLCB35AN 0x0d0e DVD-ROM & CD-R/RW
product PANASONIC SDCAAE 0x1b00 MultiMediaCard
product PANASONIC TYTP50P6S 0x3900 TY-TP50P6-S 50in Touch Panel
/* PARA Industrial products */
product PARA RT3070 0x8888 RT3070
/* Pegatron products */
product PEGATRON RT2870 0x0002 RT2870
product PEGATRON RT3070 0x000c RT3070
product PEGATRON RT3070_2 0x000e RT3070
product PEGATRON RT3070_3 0x0010 RT3070
/* Peracom products */
product PERACOM SERIAL1 0x0001 Serial
product PERACOM ENET 0x0002 Ethernet
product PERACOM ENET3 0x0003 At Home Ethernet
product PERACOM ENET2 0x0005 Ethernet
/* Philips products */
product PHILIPS DSS350 0x0101 DSS 350 Digital Speaker System
product PHILIPS DSS 0x0104 DSS XXX Digital Speaker System
product PHILIPS HUB 0x0201 hub
product PHILIPS PCA646VC 0x0303 PCA646VC PC Camera
product PHILIPS PCVC680K 0x0308 PCVC680K Vesta Pro PC Camera
product PHILIPS DSS150 0x0471 DSS 150 Digital Speaker System
product PHILIPS ACE1001 0x066a AKTAKOM ACE-1001 cable
product PHILIPS SPE3030CC 0x083a USB 2.0 External Disk
product PHILIPS SNU5600 0x1236 SNU5600
product PHILIPS UM10016 0x1552 ISP 1581 Hi-Speed USB MPEG2 Encoder Reference Kit
product PHILIPS DIVAUSB 0x1801 DIVA USB mp3 player
product PHILIPS RT2870 0x200f RT2870
/* Philips Semiconductor products */
product PHILIPSSEMI HUB1122 0x1122 HUB
/* Megatec */
product MEGATEC UPS 0x5161 Phoenixtec protocol based UPS
/* P.I. Engineering products */
product PIENGINEERING PS2USB 0x020b PS2 to Mac USB Adapter
/* Planex Communications products */
product PLANEX GW_US11H 0x14ea GW-US11H WLAN
product PLANEX2 GW_US11S 0x3220 GW-US11S WLAN
product PLANEX2 GW_US54GXS 0x5303 GW-US54GXS WLAN
product PLANEX2 GWUS54HP 0xab01 GW-US54HP
product PLANEX2 GWUS300MINIS 0xab24 GW-US300MiniS
product PLANEX2 RT3070 0xab25 RT3070
product PLANEX2 GWUS54MINI2 0xab50 GW-US54Mini2
product PLANEX2 GWUS54SG 0xc002 GW-US54SG
product PLANEX2 GWUS54GZL 0xc007 GW-US54GZL
product PLANEX2 GWUS54GD 0xed01 GW-US54GD
product PLANEX2 GWUSMM 0xed02 GW-USMM
product PLANEX2 RT2870 0xed06 RT2870
product PLANEX2 GWUSMICRON 0xed14 GW-USMicroN
product PLANEX3 GWUS54GZ 0xab10 GW-US54GZ
product PLANEX3 GU1000T 0xab11 GU-1000T
product PLANEX3 GWUS54MINI 0xab13 GW-US54Mini
/* Plextor Corp. */
product PLEXTOR 40_12_40U 0x0011 PlexWriter 40/12/40U
/* PLX products */
product PLX TESTBOARD 0x9060 test board
product PLX CA42 0xac70 CA-42
/* PNY products */
product PNY ATTACHE2 0x0010 USB 2.0 Flash Drive
/* PortGear products */
product PORTGEAR EA8 0x0008 Ethernet
product PORTGEAR EA9 0x0009 Ethernet
/* Portsmith products */
product PORTSMITH EEA 0x3003 Express Ethernet
/* Primax products */
product PRIMAX G2X300 0x0300 G2-200 scanner
product PRIMAX G2E300 0x0301 G2E-300 scanner
product PRIMAX G2300 0x0302 G2-300 scanner
product PRIMAX G2E3002 0x0303 G2E-300 scanner
product PRIMAX 9600 0x0340 Colorado USB 9600 scanner
product PRIMAX 600U 0x0341 Colorado 600u scanner
product PRIMAX 6200 0x0345 Visioneer 6200 scanner
product PRIMAX 19200 0x0360 Colorado USB 19200 scanner
product PRIMAX 1200U 0x0361 Colorado 1200u scanner
product PRIMAX G600 0x0380 G2-600 scanner
product PRIMAX 636I 0x0381 ReadyScan 636i
product PRIMAX G2600 0x0382 G2-600 scanner
product PRIMAX G2E600 0x0383 G2E-600 scanner
product PRIMAX COMFORT 0x4d01 Comfort
product PRIMAX MOUSEINABOX 0x4d02 Mouse-in-a-Box
product PRIMAX PCGAUMS1 0x4d04 Sony PCGA-UMS1
product PRIMAX HP_RH304AA 0x4d17 HP RH304AA mouse
/* Prolific products */
product PROLIFIC PL2301 0x0000 PL2301 Host-Host interface
product PROLIFIC PL2302 0x0001 PL2302 Host-Host interface
product PROLIFIC RSAQ2 0x04bb PL2303 Serial (IODATA USB-RSAQ2)
product PROLIFIC ALLTRONIX_GPRS 0x0609 Alltronix ACM003U00 modem
product PROLIFIC ALDIGA_AL11U 0x0611 AlDiga AL-11U modem
product PROLIFIC MICROMAX_610U 0x0612 Micromax 610U
product PROLIFIC DCU11 0x1234 DCU-11 Phone Cable
product PROLIFIC UIC_MSR206 0x206a UIC MSR206 Card Reader
product PROLIFIC PL2303 0x2303 PL2303 Serial (ATEN/IOGEAR UC232A)
product PROLIFIC PL2305 0x2305 Parallel printer
product PROLIFIC ATAPI4 0x2307 ATAPI-4 Controller
product PROLIFIC PL2501 0x2501 PL2501 Host-Host interface
product PROLIFIC PL2506 0x2506 PL2506 USB to IDE Bridge
product PROLIFIC HCR331 0x331a HCR331 Hybrid Card Reader
product PROLIFIC PHAROS 0xaaa0 Prolific Pharos
product PROLIFIC RSAQ3 0xaaa2 PL2303 Serial Adapter (IODATA USB-RSAQ3)
product PROLIFIC2 PL2303 0x2303 PL2303 Serial Adapter
/* Putercom products */
product PUTERCOM UPA100 0x047e USB-1284 BRIDGE
/* Qcom products */
product QCOM RT2573 0x6196 RT2573
product QCOM RT2573_2 0x6229 RT2573
product QCOM RT2573_3 0x6238 RT2573
product QCOM RT2870 0x6259 RT2870
/* Qisda products */
product QISDA H21_1 0x4512 3G modem
product QISDA H21_2 0x4523 3G modem
product QISDA H20_1 0x4515 3G modem
product QISDA H20_2 0x4519 3G modem
/* Qualcomm products */
product QUALCOMM CDMA_MSM 0x6000 CDMA Technologies MSM phone
product QUALCOMM2 MF330 0x6613 MF330
product QUALCOMM2 RWT_FCT 0x3100 RWT FCT-CDMA 2000 1xRTT modem
product QUALCOMM2 CDMA_MSM 0x3196 CDMA Technologies MSM modem
product QUALCOMM2 AC8700 0x6000 AC8700
product QUALCOMMINC CDMA_MSM 0x0001 CDMA Technologies MSM modem
product QUALCOMMINC E0002 0x0002 3G modem
product QUALCOMMINC E0003 0x0003 3G modem
product QUALCOMMINC E0004 0x0004 3G modem
product QUALCOMMINC E0005 0x0005 3G modem
product QUALCOMMINC E0006 0x0006 3G modem
product QUALCOMMINC E0007 0x0007 3G modem
product QUALCOMMINC E0008 0x0008 3G modem
product QUALCOMMINC E0009 0x0009 3G modem
product QUALCOMMINC E000A 0x000a 3G modem
product QUALCOMMINC E000B 0x000b 3G modem
product QUALCOMMINC E000C 0x000c 3G modem
product QUALCOMMINC E000D 0x000d 3G modem
product QUALCOMMINC E000E 0x000e 3G modem
product QUALCOMMINC E000F 0x000f 3G modem
product QUALCOMMINC E0010 0x0010 3G modem
product QUALCOMMINC E0011 0x0011 3G modem
product QUALCOMMINC E0012 0x0012 3G modem
product QUALCOMMINC E0013 0x0013 3G modem
product QUALCOMMINC E0014 0x0014 3G modem
product QUALCOMMINC MF628 0x0015 3G modem
product QUALCOMMINC MF633R 0x0016 ZTE WCDMA modem
product QUALCOMMINC E0017 0x0017 3G modem
product QUALCOMMINC E0018 0x0018 3G modem
product QUALCOMMINC E0019 0x0019 3G modem
product QUALCOMMINC E0020 0x0020 3G modem
product QUALCOMMINC E0021 0x0021 3G modem
product QUALCOMMINC E0022 0x0022 3G modem
product QUALCOMMINC E0023 0x0023 3G modem
product QUALCOMMINC E0024 0x0024 3G modem
product QUALCOMMINC E0025 0x0025 3G modem
product QUALCOMMINC E0026 0x0026 3G modem
product QUALCOMMINC E0027 0x0027 3G modem
product QUALCOMMINC E0028 0x0028 3G modem
product QUALCOMMINC E0029 0x0029 3G modem
product QUALCOMMINC E0030 0x0030 3G modem
product QUALCOMMINC MF626 0x0031 3G modem
product QUALCOMMINC E0032 0x0032 3G modem
product QUALCOMMINC E0033 0x0033 3G modem
product QUALCOMMINC E0037 0x0037 3G modem
product QUALCOMMINC E0039 0x0039 3G modem
product QUALCOMMINC E0042 0x0042 3G modem
product QUALCOMMINC E0043 0x0043 3G modem
product QUALCOMMINC E0048 0x0048 3G modem
product QUALCOMMINC E0049 0x0049 3G modem
product QUALCOMMINC E0051 0x0051 3G modem
product QUALCOMMINC E0052 0x0052 3G modem
product QUALCOMMINC ZTE_STOR2 0x0053 USB ZTE Storage
product QUALCOMMINC E0054 0x0054 3G modem
product QUALCOMMINC E0055 0x0055 3G modem
product QUALCOMMINC E0057 0x0057 3G modem
product QUALCOMMINC E0058 0x0058 3G modem
product QUALCOMMINC E0059 0x0059 3G modem
product QUALCOMMINC E0060 0x0060 3G modem
product QUALCOMMINC E0061 0x0061 3G modem
product QUALCOMMINC E0062 0x0062 3G modem
product QUALCOMMINC E0063 0x0063 3G modem
product QUALCOMMINC E0064 0x0064 3G modem
product QUALCOMMINC E0066 0x0066 3G modem
product QUALCOMMINC E0069 0x0069 3G modem
product QUALCOMMINC E0070 0x0070 3G modem
product QUALCOMMINC E0073 0x0073 3G modem
product QUALCOMMINC E0076 0x0076 3G modem
product QUALCOMMINC E0078 0x0078 3G modem
product QUALCOMMINC E0082 0x0082 3G modem
product QUALCOMMINC E0086 0x0086 3G modem
product QUALCOMMINC SURFSTICK 0x0117 1&1 Surf Stick
product QUALCOMMINC ZTE_STOR 0x2000 USB ZTE Storage
product QUALCOMMINC E2002 0x2002 3G modem
product QUALCOMMINC E2003 0x2003 3G modem
product QUALCOMMINC AC8710 0xfff1 3G modem
product QUALCOMMINC AC2726 0xfff5 3G modem
product QUALCOMMINC AC8700 0xfffe CDMA 1xEVDO USB modem
/* Quanta products */
product QUANTA RW6815_1 0x00ce HP iPAQ rw6815
product QUANTA RT3070 0x0304 RT3070
product QUANTA Q101_STOR 0x1000 USB Q101 Storage
product QUANTA Q101 0xea02 HSDPA modem
product QUANTA Q111 0xea03 HSDPA modem
product QUANTA GLX 0xea04 HSDPA modem
product QUANTA GKE 0xea05 HSDPA modem
product QUANTA GLE 0xea06 HSDPA modem
product QUANTA RW6815R 0xf003 HP iPAQ rw6815 RNDIS
/* Qtronix products */
product QTRONIX 980N 0x2011 Scorpion-980N keyboard
/* Quickshot products */
product QUICKSHOT STRIKEPAD 0x6238 USB StrikePad
/* Radio Shack */
product RADIOSHACK USBCABLE 0x4026 USB to Serial Cable
/* Rainbow Technologies products */
product RAINBOW IKEY2000 0x1200 i-Key 2000
/* Ralink Technology products */
product RALINK RT2570 0x1706 RT2500USB Wireless Adapter
product RALINK RT2070 0x2070 RT2070
product RALINK RT2570_2 0x2570 RT2500USB Wireless Adapter
product RALINK RT2573 0x2573 RT2501USB Wireless Adapter
product RALINK RT2671 0x2671 RT2601USB Wireless Adapter
product RALINK RT2770 0x2770 RT2770
product RALINK RT2870 0x2870 RT2870
product RALINK RT3070 0x3070 RT3070
product RALINK RT3071 0x3071 RT3071
product RALINK RT3072 0x3072 RT3072
product RALINK RT3370 0x3370 RT3370
product RALINK RT3572 0x3572 RT3572
product RALINK RT8070 0x8070 RT8070
product RALINK RT2570_3 0x9020 RT2500USB Wireless Adapter
product RALINK RT2573_2 0x9021 RT2501USB Wireless Adapter
/* RATOC Systems products */
product RATOC REXUSB60 0xb000 USB serial adapter REX-USB60
product RATOC REXUSB60F 0xb020 USB serial adapter REX-USB60F
/* ReakTek products */
/* Green House and CompUSA OEM this part */
product REALTEK USB20CRW 0x0158 USB20CRW Card Reader
product REALTEK USBKR100 0x8150 USBKR100 USB Ethernet
product REALTEK RTL8187 0x8187 RTL8187 Wireless Adapter
product REALTEK RTL8187B_0 0x8189 RTL8187B Wireless Adapter
product REALTEK RTL8187B_1 0x8197 RTL8187B Wireless Adapter
product REALTEK RTL8187B_2 0x8198 RTL8187B Wireless Adapter
/* Renesas products */
product RENESAS RX610 0x0053 RX610 RX-Stick
/* Ricoh products */
product RICOH VGPVCC2 0x1830 VGP-VCC2 Camera
product RICOH VGPVCC3 0x1832 VGP-VCC3 Camera
product RICOH VGPVCC2_2 0x1833 VGP-VCC2 Camera
product RICOH VGPVCC2_3 0x1834 VGP-VCC2 Camera
product RICOH VGPVCC7 0x183a VGP-VCC7 Camera
product RICOH VGPVCC8 0x183b VGP-VCC8 Camera
/* Reiner-SCT products */
product REINERSCT CYBERJACK_ECOM 0x0100 e-com cyberJack
/* Roland products */
product ROLAND UM1 0x0009 UM-1 MIDI I/F
product ROLAND UM880N 0x0014 EDIROL UM-880 MIDI I/F (native)
product ROLAND UM880G 0x0015 EDIROL UM-880 MIDI I/F (generic)
/* Rockfire products */
product ROCKFIRE GAMEPAD 0x2033 gamepad 203USB
/* RATOC Systems products */
product RATOC REXUSB60 0xb000 REX-USB60
product RATOC REXUSB60F 0xb020 REX-USB60F
/* Sagem products */
product SAGEM USBSERIAL 0x0027 USB-Serial Controller
product SAGEM XG760A 0x004a XG-760A
product SAGEM XG76NA 0x0062 XG-76NA
/* Samsung products */
product SAMSUNG ML6060 0x3008 ML-6060 laser printer
product SAMSUNG YP_U2 0x5050 YP-U2 MP3 Player
product SAMSUNG YP_U4 0x5092 YP-U4 MP3 Player
product SAMSUNG I500 0x6601 I500 Palm USB Phone
product SAMSUNG I330 0x8001 I330 phone cradle
product SAMSUNG2 RT2870_1 0x2018 RT2870
/* Samsung Techwin products */
product SAMSUNG_TECHWIN DIGIMAX_410 0x000a Digimax 410
/* SanDisk products */
product SANDISK SDDR05A 0x0001 ImageMate SDDR-05a
product SANDISK SDDR31 0x0002 ImageMate SDDR-31
product SANDISK SDDR05 0x0005 ImageMate SDDR-05
product SANDISK SDDR12 0x0100 ImageMate SDDR-12
product SANDISK SDDR09 0x0200 ImageMate SDDR-09
product SANDISK SDDR75 0x0810 ImageMate SDDR-75
product SANDISK SDCZ2_256 0x7104 Cruzer Mini 256MB
product SANDISK SDCZ4_128 0x7112 Cruzer Micro 128MB
product SANDISK SDCZ4_256 0x7113 Cruzer Micro 256MB
/* Sanwa Electric Instrument Co., Ltd. products */
product SANWA KB_USB2 0x0701 KB-USB2 multimeter cable
/* Sanyo Electric products */
product SANYO SCP4900 0x0701 Sanyo SCP-4900 USB Phone
/* ScanLogic products */
product SCANLOGIC SL11R 0x0002 SL11R IDE Adapter
product SCANLOGIC 336CX 0x0300 Phantom 336CX - C3 scanner
/* Senao products */
product SENAO RT2870_3 0x0605 RT2870
product SENAO RT2870_4 0x0615 RT2870
product SENAO NUB8301 0x2000 NUB-8301
product SENAO RT2870_1 0x9701 RT2870
product SENAO RT2870_2 0x9702 RT2870
product SENAO RT3070 0x9703 RT3070
product SENAO RT3071 0x9705 RT3071
product SENAO RT3072_1 0x9706 RT3072
product SENAO RT3072_2 0x9707 RT3072
product SENAO RT3072_3 0x9708 RT3072
product SENAO RT3072_4 0x9709 RT3072
product SENAO RT3072_5 0x9801 RT3072
/* ShanTou products */
product SHANTOU ST268 0x0268 ST268
product SHANTOU DM9601 0x9601 DM 9601
+product SHANTOU ADM8515 0x8515 ADM8515
/* Shark products */
product SHARK PA 0x0400 Pocket Adapter
/* Sharp products */
product SHARP SL5500 0x8004 Zaurus SL-5500 PDA
product SHARP SLA300 0x8005 Zaurus SL-A300 PDA
product SHARP SL5600 0x8006 Zaurus SL-5600 PDA
product SHARP SLC700 0x8007 Zaurus SL-C700 PDA
product SHARP SLC750 0x9031 Zaurus SL-C750 PDA
product SHARP WZERO3ES 0x9123 W-ZERO3 ES Smartphone
product SHARP WZERO3ADES 0x91ac Advanced W-ZERO3 ES Smartphone
product SHARP WILLCOM03 0x9242 WILLCOM03
/* Shuttle Technology products */
product SHUTTLE EUSB 0x0001 E-USB Bridge
product SHUTTLE EUSCSI 0x0002 eUSCSI Bridge
product SHUTTLE SDDR09 0x0003 ImageMate SDDR09
product SHUTTLE EUSBCFSM 0x0005 eUSB SmartMedia / CompactFlash Adapter
product SHUTTLE ZIOMMC 0x0006 eUSB MultiMediaCard Adapter
product SHUTTLE HIFD 0x0007 Sony Hifd
product SHUTTLE EUSBATAPI 0x0009 eUSB ATA/ATAPI Adapter
product SHUTTLE CF 0x000a eUSB CompactFlash Adapter
product SHUTTLE EUSCSI_B 0x000b eUSCSI Bridge
product SHUTTLE EUSCSI_C 0x000c eUSCSI Bridge
product SHUTTLE CDRW 0x0101 CD-RW Device
product SHUTTLE EUSBORCA 0x0325 eUSB ORCA Quad Reader
/* Siemens products */
product SIEMENS SPEEDSTREAM 0x1001 SpeedStream
product SIEMENS SPEEDSTREAM22 0x1022 SpeedStream 1022
product SIEMENS2 WLL013 0x001b WLL013
product SIEMENS2 ES75 0x0034 GSM module MC35
product SIEMENS2 WL54G 0x3c06 54g USB Network Adapter
product SIEMENS3 SX1 0x0001 SX1
product SIEMENS3 X65 0x0003 X65
product SIEMENS3 X75 0x0004 X75
product SIEMENS3 EF81 0x0005 EF81
/* Sierra Wireless products */
product SIERRA EM5625 0x0017 EM5625
product SIERRA MC5720_2 0x0018 MC5720
product SIERRA MC5725 0x0020 MC5725
product SIERRA AIRCARD580 0x0112 Sierra Wireless AirCard 580
product SIERRA AIRCARD595 0x0019 Sierra Wireless AirCard 595
product SIERRA AC595U 0x0120 Sierra Wireless AirCard 595U
product SIERRA AC597E 0x0021 Sierra Wireless AirCard 597E
product SIERRA EM5725 0x0022 EM5725
product SIERRA C597 0x0023 Sierra Wireless Compass 597
product SIERRA MC5727 0x0024 MC5727
product SIERRA T598 0x0025 T598
product SIERRA T11 0x0026 T11
product SIERRA AC402 0x0027 AC402
product SIERRA MC5728 0x0028 MC5728
product SIERRA E0029 0x0029 E0029
product SIERRA AIRCARD580 0x0112 Sierra Wireless AirCard 580
product SIERRA AC595U 0x0120 Sierra Wireless AirCard 595U
product SIERRA MC5720 0x0218 MC5720 Wireless Modem
product SIERRA MINI5725 0x0220 Sierra Wireless miniPCI 5275
product SIERRA MC5727_2 0x0224 MC5727
product SIERRA MC8755_2 0x6802 MC8755
product SIERRA MC8765 0x6803 MC8765
product SIERRA MC8755 0x6804 MC8755
product SIERRA MC8765_2 0x6805 MC8765
product SIERRA MC8755_4 0x6808 MC8755
product SIERRA MC8765_3 0x6809 MC8765
product SIERRA AC875U 0x6812 AC875U HSDPA USB Modem
product SIERRA MC8755_3 0x6813 MC8755 HSDPA
product SIERRA MC8775_2 0x6815 MC8775
product SIERRA MC8775 0x6816 MC8775
product SIERRA AC875 0x6820 Sierra Wireless AirCard 875
product SIERRA AC875U_2 0x6821 AC875U
product SIERRA AC875E 0x6822 AC875E
product SIERRA MC8780 0x6832 MC8780
product SIERRA MC8781 0x6833 MC8781
product SIERRA MC8780_2 0x6834 MC8780
product SIERRA MC8781_2 0x6835 MC8781
product SIERRA MC8780_3 0x6838 MC8780
product SIERRA MC8781_3 0x6839 MC8781
product SIERRA MC8785 0x683A MC8785
product SIERRA MC8785_2 0x683B MC8785
product SIERRA MC8790 0x683C MC8790
product SIERRA MC8791 0x683D MC8791
product SIERRA MC8792 0x683E MC8792
product SIERRA AC880 0x6850 Sierra Wireless AirCard 880
product SIERRA AC881 0x6851 Sierra Wireless AirCard 881
product SIERRA AC880E 0x6852 Sierra Wireless AirCard 880E
product SIERRA AC881E 0x6853 Sierra Wireless AirCard 881E
product SIERRA AC880U 0x6855 Sierra Wireless AirCard 880U
product SIERRA AC881U 0x6856 Sierra Wireless AirCard 881U
product SIERRA AC885E 0x6859 AC885E
product SIERRA AC885E_2 0x685A AC885E
product SIERRA AC885U 0x6880 Sierra Wireless AirCard 885U
product SIERRA C888 0x6890 C888
product SIERRA C22 0x6891 C22
product SIERRA E6892 0x6892 E6892
product SIERRA E6893 0x6893 E6893
product SIERRA MC8700 0x68A3 MC8700
product SIERRA AIRCARD875 0x6820 Aircard 875 HSDPA
product SIERRA TRUINSTALL 0x0fff Aircard Tru Installer
/* Sigmatel products */
product SIGMATEL WBT_3052 0x4200 WBT-3052 IrDA/USB Bridge
product SIGMATEL I_BEAD100 0x8008 i-Bead 100 MP3 Player
/* SIIG products */
/* Also: Omnidirectional Control Technology products */
product SIIG DIGIFILMREADER 0x0004 DigiFilm-Combo Reader
product SIIG WINTERREADER 0x0330 WINTERREADER Reader
product SIIG2 USBTOETHER 0x0109 USB TO Ethernet
product SIIG2 US2308 0x0421 Serial
/* Silicom products */
product SILICOM U2E 0x0001 U2E
product SILICOM GPE 0x0002 Psion Gold Port Ethernet
/* SI Labs */
product SILABS VSTABI 0x0f91 Vstabi
product SILABS ARKHAM_DS101_M 0x1101 Arkham DS101 Monitor
product SILABS ARKHAM_DS101_A 0x1601 Arkham DS101 Adapter
product SILABS BSM7DUSB 0x800a BSM7-D-USB
product SILABS POLOLU 0x803b Pololu Serial
product SILABS CYGNAL_DEBUG 0x8044 Cygnal Debug Adapter
product SILABS SB_PARAMOUNT_ME 0x8043 Software Bisque Paramount ME
product SILABS SAEL 0x8053 SA-EL USB
product SILABS GSM2228 0x8054 Enfora GSM2228 USB
product SILABS ARGUSISP 0x8066 Argussoft ISP
product SILABS IMS_USB_RS422 0x806f IMS USB-RS422
product SILABS CRUMB128 0x807a Crumb128 board
product SILABS DEGREE 0x80ca Degree Controls Inc
product SILABS TRACIENT 0x80dd Tracient RFID
product SILABS TRAQMATE 0x80ed Track Systems Traqmate
product SILABS SUUNTO 0x80f6 Suunto Sports Instrument
product SILABS ARYGON_MIFARE 0x8115 Arygon Mifare RFID reader
product SILABS BURNSIDE 0x813d Burnside Telecon Deskmobile
product SILABS TAMSMASTER 0x813f Tams Master Easy Control
product SILABS WMRBATT 0x814a WMR RIGblaster Plug&Play
product SILABS WMRRIGBLASTER 0x814a WMR RIGblaster Plug&Play
product SILABS WMRRIGTALK 0x814b WMR RIGtalk RT1
product SILABS B_G_H3000 0x8156 B&G H3000 Data Cable
product SILABS HELICOM 0x815e Helicomm IP-Link 1220-DVM
product SILABS AVIT_USB_TTL 0x818b AVIT Research USB-TTL
product SILABS MJS_TOSLINK 0x819f MJS USB-TOSLINk
product SILABS WAVIT 0x81a6 ThinkOptics WavIt
product SILABS MSD_DASHHAWK 0x81ac MSD DashHawk
product SILABS INSYS_MODEM 0x81ad INSYS Modem
product SILABS LIPOWSKY_JTAG 0x81c8 Lipowsky Baby-JTAG
product SILABS LIPOWSKY_LIN 0x81e2 Lipowsky Baby-LIN
product SILABS AEROCOMM 0x81e7 Aerocomm Radio
product SILABS ZEPHYR_BIO 0x81e8 Zephyr Bioharness
product SILABS EMS_C1007 0x81f2 EMS C1007 HF RFID controller
product SILABS LIPOWSKY_HARP 0x8218 Lipowsky HARP-1
product SILABS C2_EDGE_MODEM 0x822b Commander 2 EDGE(GSM) Modem
product SILABS CYGNAL_GPS 0x826b Cygnal Fasttrax GPS
product SILABS TELEGESYS_ETRX2 0x8293 Telegesys ETRX2USB
product SILABS PROCYON_AVS 0x82f9 Procyon AVS
product SILABS MC35PU 0x8341 MC35pu
product SILABS CYGNAL 0x8382 Cygnal
product SILABS AMBER_AMB2560 0x83a8 Amber Wireless AMB2560
product SILABS KYOCERA_GPS 0x8411 Kyocera GPS
product SILABS BEI_VCP 0x846e BEI USB Sensor (VCP)
product SILABS BALLUFF_RFID 0x8477 Balluff RFID reader
product SILABS CP2102 0xea60 SILABS USB UART
product SILABS CP210X_2 0xea61 CP210x Serial
product SILABS INFINITY_MIC 0xea71 Infinity GPS-MIC-1 Radio Monophone
product SILABS USBSCOPE50 0xf001 USBscope50
product SILABS USBWAVE12 0xf002 USBwave12
product SILABS USBPULSE100 0xf003 USBpulse100
product SILABS USBCOUNT50 0xf004 USBcount50
product SILABS2 DCU11CLONE 0xaa26 DCU-11 clone
product SILABS3 GPRS_MODEM 0xea61 GPRS Modem
product SILABS4 100EU_MODEM 0xea61 GPRS Modem 100EU
/* Silicon Portals Inc. */
product SILICONPORTALS YAPPH_NF 0x0200 YAP Phone (no firmware)
product SILICONPORTALS YAPPHONE 0x0201 YAP Phone
/* Sirius Technologies products */
product SIRIUS ROADSTER 0x0001 NetComm Roadster II 56 USB
/* Sitecom products */
product SITECOM LN029 0x182d USB 2.0 Ethernet
product SITECOM SERIAL 0x2068 USB to serial cable (v2)
product SITECOM2 WL022 0x182d WL-022
/* Sitecom Europe products */
product SITECOMEU RT2870_1 0x0017 RT2870
product SITECOMEU WL168V1 0x000d WL-168 v1
product SITECOMEU LN030 0x0021 MCS7830
product SITECOMEU WL168V4 0x0028 WL-168 v4
product SITECOMEU RT2870_2 0x002b RT2870
product SITECOMEU RT2870_3 0x002c RT2870
product SITECOMEU RT2870_4 0x002d RT2870
product SITECOMEU RT2770 0x0039 RT2770
product SITECOMEU RT3070_2 0x003b RT3070
product SITECOMEU RT3070_3 0x003c RT3070
product SITECOMEU RT3070_4 0x003d RT3070
product SITECOMEU RT3070 0x003e RT3070
product SITECOMEU WL608 0x003f WL-608
product SITECOMEU RT3071 0x0040 RT3071
product SITECOMEU RT3072_1 0x0041 RT3072
product SITECOMEU RT3072_2 0x0042 RT3072
product SITECOMEU RT3072_3 0x0047 RT3072
product SITECOMEU RT3072_4 0x0048 RT3072
product SITECOMEU RT3072_5 0x004a RT3072
product SITECOMEU RT3072_6 0x004d RT3072
product SITECOMEU LN028 0x061c LN-028
product SITECOMEU WL113 0x9071 WL-113
product SITECOMEU ZD1211B 0x9075 ZD1211B
product SITECOMEU WL172 0x90ac WL-172
product SITECOMEU WL113R2 0x9712 WL-113 rev 2
/* Skanhex Technology products */
product SKANHEX MD_7425 0x410a MD 7425 Camera
product SKANHEX SX_520Z 0x5200 SX 520z Camera
/* Smart Technologies products */
product SMART PL2303 0x2303 Serial adapter
/* SmartBridges products */
product SMARTBRIDGES SMARTLINK 0x0001 SmartLink USB Ethernet
product SMARTBRIDGES SMARTNIC 0x0003 smartNIC 2 PnP Ethernet
/* SMC products */
product SMC 2102USB 0x0100 10Mbps Ethernet
product SMC 2202USB 0x0200 10/100 Ethernet
product SMC 2206USB 0x0201 EZ Connect USB Ethernet
product SMC 2862WG 0xee13 EZ Connect Wireless Adapter
product SMC2 2020HUB 0x2020 USB Hub
product SMC2 2514HUB 0x2514 USB Hub
product SMC3 2662WUSB 0xa002 2662W-AR Wireless
/* SOHOware products */
product SOHOWARE NUB100 0x9100 10/100 USB Ethernet
product SOHOWARE NUB110 0x9110 10/100 USB Ethernet
/* SOLID YEAR products */
product SOLIDYEAR KEYBOARD 0x2101 Solid Year USB keyboard
/* SONY products */
product SONY DSC 0x0010 DSC cameras
product SONY MS_NW_MS7 0x0025 Memorystick NW-MS7
product SONY PORTABLE_HDD_V2 0x002b Portable USB Harddrive V2
product SONY MSACUS1 0x002d Memorystick MSAC-US1
product SONY HANDYCAM 0x002e Handycam
product SONY MSC 0x0032 MSC memory stick slot
product SONY CLIE_35 0x0038 Sony Clie v3.5
product SONY MS_PEG_N760C 0x0058 PEG N760c Memorystick
product SONY CLIE_40 0x0066 Sony Clie v4.0
product SONY MS_MSC_U03 0x0069 Memorystick MSC-U03
product SONY CLIE_40_MS 0x006d Sony Clie v4.0 Memory Stick slot
product SONY CLIE_S360 0x0095 Sony Clie s360
product SONY CLIE_41_MS 0x0099 Sony Clie v4.1 Memory Stick slot
product SONY CLIE_41 0x009a Sony Clie v4.1
product SONY CLIE_NX60 0x00da Sony Clie nx60
product SONY CLIE_TH55 0x0144 Sony Clie th55
product SONY CLIE_TJ37 0x0169 Sony Clie tj37
product SONY RF_RECEIVER 0x01db Sony RF mouse/kbd Receiver VGP-WRC1
product SONY QN3 0x0437 Sony QN3 CMD-Jxx phone cable
/* Sony Ericsson products */
product SONYERICSSON DCU10 0x0528 DCU-10 Phone Data Cable
product SONYERICSSON DATAPILOT 0x2003 Datapilot Phone Cable
/* SOURCENEXT products */
product SOURCENEXT KEIKAI8 0x039f KeikaiDenwa 8
product SOURCENEXT KEIKAI8_CHG 0x012e KeikaiDenwa 8 with charger
/* SparkLAN products */
product SPARKLAN RT2573 0x0004 RT2573
product SPARKLAN RT2870_1 0x0006 RT2870
product SPARKLAN RT3070 0x0010 RT3070
/* Speed Dragon Multimedia products */
product SPEEDDRAGON MS3303H 0x110b MS3303H Serial
/* Sphairon Access Systems GmbH products */
product SPHAIRON UB801R 0x0110 UB801R
/* Stelera Wireless products */
product STELERA ZEROCD 0x1000 Zerocd Installer
product STELERA C105 0x1002 Stelera/Bandrish C105 USB
product STELERA E1003 0x1003 3G modem
product STELERA E1004 0x1004 3G modem
product STELERA E1005 0x1005 3G modem
product STELERA E1006 0x1006 3G modem
product STELERA E1007 0x1007 3G modem
product STELERA E1008 0x1008 3G modem
product STELERA E1009 0x1009 3G modem
product STELERA E100A 0x100a 3G modem
product STELERA E100B 0x100b 3G modem
product STELERA E100C 0x100c 3G modem
product STELERA E100D 0x100d 3G modem
product STELERA E100E 0x100e 3G modem
product STELERA E100F 0x100f 3G modem
product STELERA E1010 0x1010 3G modem
product STELERA E1011 0x1011 3G modem
product STELERA E1012 0x1012 3G modem
/* MpMan products */
product MPMAN MPF400_1 0x36d0 MPF400 Music Player 1Go
product MPMAN MPF400_2 0x25a8 MPF400 Music Player 2Go
/* STMicroelectronics products */
product STMICRO BIOCPU 0x2016 Biometric Coprocessor
product STMICRO COMMUNICATOR 0x7554 USB Communicator
/* STSN products */
product STSN STSN0001 0x0001 Internet Access Device
/* SUN Corporation products */
product SUNTAC DS96L 0x0003 SUNTAC U-Cable type D2
product SUNTAC PS64P1 0x0005 SUNTAC U-Cable type P1
product SUNTAC VS10U 0x0009 SUNTAC Slipper U
product SUNTAC IS96U 0x000a SUNTAC Ir-Trinity
product SUNTAC AS64LX 0x000b SUNTAC U-Cable type A3
product SUNTAC AS144L4 0x0011 SUNTAC U-Cable type A4
/* Sun Microsystems products */
product SUN KEYBOARD_TYPE_6 0x0005 Type 6 USB keyboard
product SUN KEYBOARD_TYPE_7 0x00a2 Type 7 USB keyboard
/* XXX The above is a North American PC style keyboard possibly */
product SUN MOUSE 0x0100 Type 6 USB mouse
product SUN KBD_HUB 0x100e Kbd Hub
/* Super Top products */
product SUPERTOP IDE 0x6600 USB-IDE
/* Syntech products */
product SYNTECH CPT8001C 0x0001 CPT-8001C Barcode scanner
product SYNTECH CYPHERLAB100 0x1000 CipherLab USB Barcode Scanner
/* Teclast products */
product TECLAST TLC300 0x3203 USB Media Player
/* Supra products */
product DIAMOND2 SUPRAEXPRESS56K 0x07da Supra Express 56K modem
product DIAMOND2 SUPRA2890 0x0b4a SupraMax 2890 56K Modem
product DIAMOND2 RIO600USB 0x5001 Rio 600 USB
product DIAMOND2 RIO800USB 0x5002 Rio 800 USB
/* Surecom Technology products */
product SURECOM EP9001G2A 0x11f2 EP-9001-G rev 2A
product SURECOM RT2570 0x11f3 RT2570
product SURECOM RT2573 0x31f3 RT2573
/* Sweex products */
product SWEEX ZD1211 0x1809 ZD1211
product SWEEX2 LW153 0x0153 LW153
product SWEEX2 LW303 0x0302 LW303
product SWEEX2 LW313 0x0313 LW313
/* System TALKS, Inc. */
product SYSTEMTALKS SGCX2UL 0x1920 SGC-X2UL
/* Tapwave products */
product TAPWAVE ZODIAC 0x0100 Zodiac
/* Taugagreining products */
product TAUGA CAMERAMATE 0x0005 CameraMate (DPCM_USB)
/* TCTMobile products */
product TCTMOBILE X060S 0x0000 X060S 3G modem
product TCTMOBILE X080S 0xf000 X080S 3G modem
/* TDK products */
product TDK UPA9664 0x0115 USB-PDC Adapter UPA9664
product TDK UCA1464 0x0116 USB-cdmaOne Adapter UCA1464
product TDK UHA6400 0x0117 USB-PHS Adapter UHA6400
product TDK UPA6400 0x0118 USB-PHS Adapter UPA6400
product TDK BT_DONGLE 0x0309 Bluetooth USB dongle
/* TEAC products */
product TEAC FD05PUB 0x0000 FD-05PUB floppy
/* Tekram Technology products */
product TEKRAM QUICKWLAN 0x1630 QuickWLAN
product TEKRAM ZD1211_1 0x5630 ZD1211
product TEKRAM ZD1211_2 0x6630 ZD1211
/* Telex Communications products */
product TELEX MIC1 0x0001 Enhanced USB Microphone
/* Telit products */
product TELIT UC864E 0x1003 UC864E 3G modem
product TELIT UC864G 0x1004 UC864G 3G modem
/* Ten X Technology, Inc. */
product TENX UAUDIO0 0xf211 USB audio headset
/* Texas Intel products */
product TI UTUSB41 0x1446 UT-USB41 hub
product TI TUSB2046 0x2046 TUSB2046 hub
/* Thrustmaster products */
product THRUST FUSION_PAD 0xa0a3 Fusion Digital Gamepad
/* TLayTech products */
product TLAYTECH TEU800 0x1682 TEU800 3G modem
/* Topre Corporation products */
product TOPRE HHKB 0x0100 HHKB Professional
/* Toshiba Corporation products */
product TOSHIBA POCKETPC_E740 0x0706 PocketPC e740
product TOSHIBA RT3070 0x0a07 RT3070
product TOSHIBA G450 0x0d45 G450 modem
product TOSHIBA HSDPA 0x1302 G450 modem
/* Trek Technology products */
product TREK THUMBDRIVE 0x1111 ThumbDrive
product TREK MEMKEY 0x8888 IBM USB Memory Key
product TREK THUMBDRIVE_8MB 0x9988 ThumbDrive_8MB
/* Tripp-Lite products */
product TRIPPLITE U209 0x2008 Serial
/* Trumpion products */
product TRUMPION T33520 0x1001 T33520 USB Flash Card Controller
product TRUMPION C3310 0x1100 Comotron C3310 MP3 player
product TRUMPION MP3 0x1200 MP3 player
/* TwinMOS */
product TWINMOS G240 0xa006 G240
product TWINMOS MDIV 0x1325 Memory Disk IV
/* Ubiquam products */
product UBIQUAM UALL 0x3100 CDMA 1xRTT USB Modem (U-100/105/200/300/520)
/* Ultima products */
product ULTIMA 1200UBPLUS 0x4002 1200 UB Plus scanner
/* UMAX products */
product UMAX ASTRA1236U 0x0002 Astra 1236U Scanner
product UMAX ASTRA1220U 0x0010 Astra 1220U Scanner
product UMAX ASTRA2000U 0x0030 Astra 2000U Scanner
product UMAX ASTRA2100U 0x0130 Astra 2100U Scanner
product UMAX ASTRA2200U 0x0230 Astra 2200U Scanner
product UMAX ASTRA3400 0x0060 Astra 3400 Scanner
/* U-MEDIA Communications products */
product UMEDIA TEW444UBEU 0x3006 TEW-444UB EU
product UMEDIA TEW444UBEU_NF 0x3007 TEW-444UB EU (no firmware)
product UMEDIA TEW429UB_A 0x300a TEW-429UB_A
product UMEDIA TEW429UB 0x300b TEW-429UB
product UMEDIA TEW429UBC1 0x300d TEW-429UB C1
product UMEDIA RT2870_1 0x300e RT2870
product UMEDIA ALL0298V2 0x3204 ALL0298 v2
product UMEDIA AR5523_2 0x3205 AR5523
product UMEDIA AR5523_2_NF 0x3206 AR5523 (no firmware)
/* Universal Access products */
product UNIACCESS PANACHE 0x0101 Panache Surf USB ISDN Adapter
/* USI products */
product USI MC60 0x10c5 MC60 Serial
/* U.S. Robotics products */
product USR USR5422 0x0118 USR5422 WLAN
product USR USR5423 0x0121 USR5423 WLAN
/* VIA Technologies products */
product VIA USB2IDEBRIDGE 0x6204 USB 2.0 IDE Bridge
/* Vaisala products */
product VAISALA CABLE 0x0200 USB Interface cable
/* VidzMedia products */
product VIDZMEDIA MONSTERTV 0x4fb1 MonsterTV P2H
/* Vision products */
product VISION VC6452V002 0x0002 CPiA Camera
/* Visioneer products */
product VISIONEER 7600 0x0211 OneTouch 7600
product VISIONEER 5300 0x0221 OneTouch 5300
product VISIONEER 3000 0x0224 Scanport 3000
product VISIONEER 6100 0x0231 OneTouch 6100
product VISIONEER 6200 0x0311 OneTouch 6200
product VISIONEER 8100 0x0321 OneTouch 8100
product VISIONEER 8600 0x0331 OneTouch 8600
/* Vivitar products */
product VIVITAR 35XX 0x0003 Vivicam 35Xx
/* VTech products */
product VTECH RT2570 0x3012 RT2570
product VTECH ZD1211B 0x3014 ZD1211B
/* Wacom products */
product WACOM CT0405U 0x0000 CT-0405-U Tablet
product WACOM GRAPHIRE 0x0010 Graphire
product WACOM GRAPHIRE3_4X5 0x0013 Graphire 3 4x5
product WACOM INTUOSA5 0x0021 Intuos A5
product WACOM GD0912U 0x0022 Intuos 9x12 Graphics Tablet
/* WAGO Kontakttechnik GmbH products */
product WAGO SERVICECABLE 0x07a6 USB Service Cable 750-923
/* WaveSense products */
product WAVESENSE JAZZ 0xaaaa Jazz blood glucose meter
/* WCH products */
product WCH CH341SER 0x5523 CH341/CH340 USB-Serial Bridge
product WCH2 CH341SER 0x7523 CH341/CH340 USB-Serial Bridge
/* Western Digital products */
product WESTERN COMBO 0x0200 Firewire USB Combo
product WESTERN EXTHDD 0x0400 External HDD
product WESTERN HUB 0x0500 USB HUB
product WESTERN MYBOOK 0x0901 MyBook External HDD
product WESTERN MYPASSWORD 0x0704 MyPassword External HDD
/* WIENER Plein & Baus GmbH products */
product WIENERPLEINBAUS PL512 0x0010 PL512 PSU
product WIENERPLEINBAUS RCM 0x0011 RCM Remote Control
product WIENERPLEINBAUS MPOD 0x0012 MPOD PSU
product WIENERPLEINBAUS CML 0x0015 CML Data Logger
/* Windbond Electronics */
product WINBOND UH104 0x5518 4-port USB Hub
/* WinMaxGroup products */
product WINMAXGROUP FLASH64MC 0x6660 USB Flash Disk 64M-C
/* Wistron NeWeb products */
product WISTRONNEWEB UR045G 0x0427 PrismGT USB 2.0 WLAN
product WISTRONNEWEB UR055G 0x0711 UR055G
product WISTRONNEWEB AR5523_1 0x0826 AR5523
product WISTRONNEWEB AR5523_1_NF 0x0827 AR5523 (no firmware)
product WISTRONNEWEB AR5523_2 0x082a AR5523
product WISTRONNEWEB AR5523_2_NF 0x0829 AR5523 (no firmware)
/* Xerox products */
product XEROX WCM15 0xffef WorkCenter M15
/* Xirlink products */
product XIRLINK PCCAM 0x8080 IBM PC Camera
/* Xyratex products */
product XYRATEX PRISM_GT_1 0x2000 PrismGT USB 2.0 WLAN
product XYRATEX PRISM_GT_2 0x2002 PrismGT USB 2.0 WLAN
/* Yamaha products */
product YAMAHA UX256 0x1000 UX256 MIDI I/F
product YAMAHA UX96 0x1008 UX96 MIDI I/F
product YAMAHA RTA54I 0x4000 NetVolante RTA54i Broadband&ISDN Router
product YAMAHA RTA55I 0x4004 NetVolante RTA55i Broadband VoIP Router
product YAMAHA RTW65B 0x4001 NetVolante RTW65b Broadband Wireless Router
product YAMAHA RTW65I 0x4002 NetVolante RTW65i Broadband&ISDN Wireless Router
/* Yano products */
product YANO U640MO 0x0101 U640MO-03
product YANO FW800HD 0x05fc METALWEAR-HDD
/* Y.C. Cable products */
product YCCABLE PL2303 0x0fba PL2303 Serial
/* Y-E Data products */
product YEDATA FLASHBUSTERU 0x0000 Flashbuster-U
/* Yiso Wireless Co. products */
product YISO C893 0xc893 CDMA 2000 1xEVDO PC Card
/* Z-Com products */
product ZCOM M4Y750 0x0001 M4Y-750
product ZCOM XI725 0x0002 XI-725/726
product ZCOM XI735 0x0005 XI-735
product ZCOM XG703A 0x0008 PrismGT USB 2.0 WLAN
product ZCOM ZD1211 0x0011 ZD1211
product ZCOM AR5523 0x0012 AR5523
product ZCOM AR5523_NF 0x0013 AR5523 driver (no firmware)
product ZCOM XM142 0x0015 XM-142
product ZCOM ZD1211B 0x001a ZD1211B
product ZCOM RT2870_1 0x0022 RT2870
product ZCOM RT2870_2 0x0025 RT2870
/* Zinwell products */
product ZINWELL RT2570 0x0260 RT2570
product ZINWELL RT2870_1 0x0280 RT2870
product ZINWELL RT2870_2 0x0282 RT2870
product ZINWELL RT3072_1 0x0283 RT3072
product ZINWELL RT3072_2 0x0284 RT3072
product ZINWELL RT3070 0x5257 RT3070
/* Zoom Telephonics, Inc. products */
product ZOOM 2986L 0x9700 2986L Fax modem
/* Zoran Microelectronics products */
product ZORAN EX20DSC 0x4343 Digital Camera EX-20 DSC
/* Zydas Technology Corporation products */
product ZYDAS ZD1211 0x1211 ZD1211 WLAN abg
product ZYDAS ZD1211B 0x1215 ZD1211B
/* ZyXEL Communication Co. products */
product ZYXEL OMNI56K 0x1500 Omni 56K Plus
product ZYXEL 980N 0x2011 Scorpion-980N keyboard
product ZYXEL ZYAIRG220 0x3401 ZyAIR G-220
product ZYXEL G200V2 0x3407 G-200 v2
product ZYXEL AG225H 0x3409 AG-225H
product ZYXEL M202 0x340a M-202
product ZYXEL G220V2 0x340f G-220 v2
product ZYXEL G202 0x3410 G-202
product ZYXEL RT2870_1 0x3416 RT2870
product ZYXEL RT2870_2 0x341a RT2870
Index: projects/altix/sys/dev/xen/xenpci
===================================================================
--- projects/altix/sys/dev/xen/xenpci (revision 218875)
+++ projects/altix/sys/dev/xen/xenpci (revision 218876)
Property changes on: projects/altix/sys/dev/xen/xenpci
___________________________________________________________________
Deleted: svn:mergeinfo
## -0,10 +0,0 ##
Reverse-merged /user/mav/ata/sys/dev/xen/xenpci:r189793-190578
Reverse-merged /user/thompsa/usb/sys/dev/xen/xenpci:r187190
Reverse-merged /projects/cambria/sys/dev/xen/xenpci:r186008-186350
Reverse-merged /user/dfr/xenhvm/6/sys/dev/xen/xenpci:r189304,189451
Reverse-merged /user/dfr/xenhvm/7/sys/dev/xen/xenpci:r188574-188684
Reverse-merged /user/peter/kinfo/sys/dev/xen/xenpci:r185413-185547
Reverse-merged /projects/releng_6_xen/sys/dev/xen/xenpci:r185181-186767
Reverse-merged /user/piso/sys/dev/xen/xenpci:r186543,186723,186725-186726,186742,186770-186771,186774,186777-186779,187984-187985,190555,190572,190589,190592,190614,190625,190830
Reverse-merged /user/piso/ipfw/sys/dev/xen/xenpci:r190918,190921,190923,190926
Reverse-merged /head/sys/dev/xen/xenpci:r2-184124,204938-214309
Index: projects/altix/sys/fs/tmpfs/tmpfs_vnops.c
===================================================================
--- projects/altix/sys/fs/tmpfs/tmpfs_vnops.c (revision 218875)
+++ projects/altix/sys/fs/tmpfs/tmpfs_vnops.c (revision 218876)
@@ -1,1626 +1,1625 @@
/* $NetBSD: tmpfs_vnops.c,v 1.39 2007/07/23 15:41:01 jmmv Exp $ */
/*-
* Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Julio M. Merino Vidal, developed as part of Google's Summer of Code
* 2005 program.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* tmpfs vnode interface.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/fcntl.h>
#include <sys/lockf.h>
#include <sys/namei.h>
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/sf_buf.h>
#include <sys/stat.h>
#include <sys/systm.h>
#include <sys/unistd.h>
#include <sys/vnode.h>
#include <vm/vm.h>
#include <vm/vm_object.h>
#include <vm/vm_page.h>
#include <vm/vm_pager.h>
#include <machine/_inttypes.h>
#include <fs/fifofs/fifo.h>
#include <fs/tmpfs/tmpfs_vnops.h>
#include <fs/tmpfs/tmpfs.h>
/* --------------------------------------------------------------------- */
static int
tmpfs_lookup(struct vop_cachedlookup_args *v)
{
struct vnode *dvp = v->a_dvp;
struct vnode **vpp = v->a_vpp;
struct componentname *cnp = v->a_cnp;
int error;
struct tmpfs_dirent *de;
struct tmpfs_node *dnode;
dnode = VP_TO_TMPFS_DIR(dvp);
*vpp = NULLVP;
/* Check accessibility of requested node as a first step. */
error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, cnp->cn_thread);
if (error != 0)
goto out;
/* We cannot be requesting the parent directory of the root node. */
MPASS(IMPLIES(dnode->tn_type == VDIR &&
dnode->tn_dir.tn_parent == dnode,
!(cnp->cn_flags & ISDOTDOT)));
TMPFS_ASSERT_LOCKED(dnode);
if (dnode->tn_dir.tn_parent == NULL) {
error = ENOENT;
goto out;
}
if (cnp->cn_flags & ISDOTDOT) {
int ltype = 0;
ltype = VOP_ISLOCKED(dvp);
vhold(dvp);
VOP_UNLOCK(dvp, 0);
/* Allocate a new vnode on the matching entry. */
error = tmpfs_alloc_vp(dvp->v_mount, dnode->tn_dir.tn_parent,
cnp->cn_lkflags, vpp);
vn_lock(dvp, ltype | LK_RETRY);
vdrop(dvp);
} else if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
VREF(dvp);
*vpp = dvp;
error = 0;
} else {
de = tmpfs_dir_lookup(dnode, NULL, cnp);
if (de != NULL && de->td_node == NULL)
cnp->cn_flags |= ISWHITEOUT;
if (de == NULL || de->td_node == NULL) {
/* The entry was not found in the directory.
* This is OK if we are creating or renaming an
* entry and are working on the last component of
* the path name. */
if ((cnp->cn_flags & ISLASTCN) &&
(cnp->cn_nameiop == CREATE || \
cnp->cn_nameiop == RENAME ||
(cnp->cn_nameiop == DELETE &&
cnp->cn_flags & DOWHITEOUT &&
cnp->cn_flags & ISWHITEOUT))) {
error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred,
cnp->cn_thread);
if (error != 0)
goto out;
/* Keep the component name in the buffer for
* future uses. */
cnp->cn_flags |= SAVENAME;
error = EJUSTRETURN;
} else
error = ENOENT;
} else {
struct tmpfs_node *tnode;
/* The entry was found, so get its associated
* tmpfs_node. */
tnode = de->td_node;
/* If we are not at the last path component and
* found a non-directory or non-link entry (which
* may itself be pointing to a directory), raise
* an error. */
if ((tnode->tn_type != VDIR &&
tnode->tn_type != VLNK) &&
!(cnp->cn_flags & ISLASTCN)) {
error = ENOTDIR;
goto out;
}
/* If we are deleting or renaming the entry, keep
* track of its tmpfs_dirent so that it can be
* easily deleted later. */
if ((cnp->cn_flags & ISLASTCN) &&
(cnp->cn_nameiop == DELETE ||
cnp->cn_nameiop == RENAME)) {
error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred,
cnp->cn_thread);
if (error != 0)
goto out;
/* Allocate a new vnode on the matching entry. */
error = tmpfs_alloc_vp(dvp->v_mount, tnode,
cnp->cn_lkflags, vpp);
if (error != 0)
goto out;
if ((dnode->tn_mode & S_ISTXT) &&
VOP_ACCESS(dvp, VADMIN, cnp->cn_cred, cnp->cn_thread) &&
VOP_ACCESS(*vpp, VADMIN, cnp->cn_cred, cnp->cn_thread)) {
error = EPERM;
vput(*vpp);
*vpp = NULL;
goto out;
}
cnp->cn_flags |= SAVENAME;
} else {
error = tmpfs_alloc_vp(dvp->v_mount, tnode,
cnp->cn_lkflags, vpp);
}
}
}
/* Store the result of this lookup in the cache. Avoid this if the
* request was for creation, as it does not improve timings on
* emprical tests. */
if ((cnp->cn_flags & MAKEENTRY) && cnp->cn_nameiop != CREATE)
cache_enter(dvp, *vpp, cnp);
out:
/* If there were no errors, *vpp cannot be null and it must be
* locked. */
MPASS(IFF(error == 0, *vpp != NULLVP && VOP_ISLOCKED(*vpp)));
return error;
}
/* --------------------------------------------------------------------- */
static int
tmpfs_create(struct vop_create_args *v)
{
struct vnode *dvp = v->a_dvp;
struct vnode **vpp = v->a_vpp;
struct componentname *cnp = v->a_cnp;
struct vattr *vap = v->a_vap;
MPASS(vap->va_type == VREG || vap->va_type == VSOCK);
return tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL);
}
/* --------------------------------------------------------------------- */
static int
tmpfs_mknod(struct vop_mknod_args *v)
{
struct vnode *dvp = v->a_dvp;
struct vnode **vpp = v->a_vpp;
struct componentname *cnp = v->a_cnp;
struct vattr *vap = v->a_vap;
if (vap->va_type != VBLK && vap->va_type != VCHR &&
vap->va_type != VFIFO)
return EINVAL;
return tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL);
}
/* --------------------------------------------------------------------- */
static int
tmpfs_open(struct vop_open_args *v)
{
struct vnode *vp = v->a_vp;
int mode = v->a_mode;
int error;
struct tmpfs_node *node;
MPASS(VOP_ISLOCKED(vp));
node = VP_TO_TMPFS_NODE(vp);
/* The file is still active but all its names have been removed
* (e.g. by a "rmdir $(pwd)"). It cannot be opened any more as
* it is about to die. */
if (node->tn_links < 1)
return (ENOENT);
/* If the file is marked append-only, deny write requests. */
if (node->tn_flags & APPEND && (mode & (FWRITE | O_APPEND)) == FWRITE)
error = EPERM;
else {
error = 0;
vnode_create_vobject(vp, node->tn_size, v->a_td);
}
MPASS(VOP_ISLOCKED(vp));
return error;
}
/* --------------------------------------------------------------------- */
static int
tmpfs_close(struct vop_close_args *v)
{
struct vnode *vp = v->a_vp;
struct tmpfs_node *node;
MPASS(VOP_ISLOCKED(vp));
node = VP_TO_TMPFS_NODE(vp);
if (node->tn_links > 0) {
/* Update node times. No need to do it if the node has
* been deleted, because it will vanish after we return. */
tmpfs_update(vp);
}
return 0;
}
/* --------------------------------------------------------------------- */
int
tmpfs_access(struct vop_access_args *v)
{
struct vnode *vp = v->a_vp;
accmode_t accmode = v->a_accmode;
struct ucred *cred = v->a_cred;
int error;
struct tmpfs_node *node;
MPASS(VOP_ISLOCKED(vp));
node = VP_TO_TMPFS_NODE(vp);
switch (vp->v_type) {
case VDIR:
/* FALLTHROUGH */
case VLNK:
/* FALLTHROUGH */
case VREG:
if (accmode & VWRITE && vp->v_mount->mnt_flag & MNT_RDONLY) {
error = EROFS;
goto out;
}
break;
case VBLK:
/* FALLTHROUGH */
case VCHR:
/* FALLTHROUGH */
case VSOCK:
/* FALLTHROUGH */
case VFIFO:
break;
default:
error = EINVAL;
goto out;
}
if (accmode & VWRITE && node->tn_flags & IMMUTABLE) {
error = EPERM;
goto out;
}
error = vaccess(vp->v_type, node->tn_mode, node->tn_uid,
node->tn_gid, accmode, cred, NULL);
out:
MPASS(VOP_ISLOCKED(vp));
return error;
}
/* --------------------------------------------------------------------- */
int
tmpfs_getattr(struct vop_getattr_args *v)
{
struct vnode *vp = v->a_vp;
struct vattr *vap = v->a_vap;
struct tmpfs_node *node;
node = VP_TO_TMPFS_NODE(vp);
tmpfs_update(vp);
vap->va_type = vp->v_type;
vap->va_mode = node->tn_mode;
vap->va_nlink = node->tn_links;
vap->va_uid = node->tn_uid;
vap->va_gid = node->tn_gid;
vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
vap->va_fileid = node->tn_id;
vap->va_size = node->tn_size;
vap->va_blocksize = PAGE_SIZE;
vap->va_atime = node->tn_atime;
vap->va_mtime = node->tn_mtime;
vap->va_ctime = node->tn_ctime;
vap->va_birthtime = node->tn_birthtime;
vap->va_gen = node->tn_gen;
vap->va_flags = node->tn_flags;
vap->va_rdev = (vp->v_type == VBLK || vp->v_type == VCHR) ?
node->tn_rdev : NODEV;
vap->va_bytes = round_page(node->tn_size);
vap->va_filerev = 0;
return 0;
}
/* --------------------------------------------------------------------- */
/* XXX Should this operation be atomic? I think it should, but code in
* XXX other places (e.g., ufs) doesn't seem to be... */
int
tmpfs_setattr(struct vop_setattr_args *v)
{
struct vnode *vp = v->a_vp;
struct vattr *vap = v->a_vap;
struct ucred *cred = v->a_cred;
struct thread *td = curthread;
int error;
MPASS(VOP_ISLOCKED(vp));
error = 0;
/* Abort if any unsettable attribute is given. */
if (vap->va_type != VNON ||
vap->va_nlink != VNOVAL ||
vap->va_fsid != VNOVAL ||
vap->va_fileid != VNOVAL ||
vap->va_blocksize != VNOVAL ||
vap->va_gen != VNOVAL ||
vap->va_rdev != VNOVAL ||
vap->va_bytes != VNOVAL)
error = EINVAL;
if (error == 0 && (vap->va_flags != VNOVAL))
error = tmpfs_chflags(vp, vap->va_flags, cred, td);
if (error == 0 && (vap->va_size != VNOVAL))
error = tmpfs_chsize(vp, vap->va_size, cred, td);
if (error == 0 && (vap->va_uid != VNOVAL || vap->va_gid != VNOVAL))
error = tmpfs_chown(vp, vap->va_uid, vap->va_gid, cred, td);
if (error == 0 && (vap->va_mode != (mode_t)VNOVAL))
error = tmpfs_chmod(vp, vap->va_mode, cred, td);
if (error == 0 && ((vap->va_atime.tv_sec != VNOVAL &&
vap->va_atime.tv_nsec != VNOVAL) ||
(vap->va_mtime.tv_sec != VNOVAL &&
vap->va_mtime.tv_nsec != VNOVAL) ||
(vap->va_birthtime.tv_sec != VNOVAL &&
vap->va_birthtime.tv_nsec != VNOVAL)))
error = tmpfs_chtimes(vp, &vap->va_atime, &vap->va_mtime,
&vap->va_birthtime, vap->va_vaflags, cred, td);
/* Update the node times. We give preference to the error codes
* generated by this function rather than the ones that may arise
* from tmpfs_update. */
tmpfs_update(vp);
MPASS(VOP_ISLOCKED(vp));
return error;
}
/* --------------------------------------------------------------------- */
static int
tmpfs_nocacheread(vm_object_t tobj, vm_pindex_t idx,
vm_offset_t offset, size_t tlen, struct uio *uio)
{
vm_page_t m;
int error;
VM_OBJECT_LOCK(tobj);
vm_object_pip_add(tobj, 1);
m = vm_page_grab(tobj, idx, VM_ALLOC_WIRED |
VM_ALLOC_ZERO | VM_ALLOC_NORMAL | VM_ALLOC_RETRY);
if (m->valid != VM_PAGE_BITS_ALL) {
if (vm_pager_has_page(tobj, idx, NULL, NULL)) {
error = vm_pager_get_pages(tobj, &m, 1, 0);
if (error != 0) {
printf("tmpfs get pages from pager error [read]\n");
goto out;
}
} else
vm_page_zero_invalid(m, TRUE);
}
VM_OBJECT_UNLOCK(tobj);
error = uiomove_fromphys(&m, offset, tlen, uio);
VM_OBJECT_LOCK(tobj);
out:
vm_page_lock(m);
vm_page_unwire(m, TRUE);
vm_page_unlock(m);
vm_page_wakeup(m);
vm_object_pip_subtract(tobj, 1);
VM_OBJECT_UNLOCK(tobj);
return (error);
}
static __inline int
tmpfs_nocacheread_buf(vm_object_t tobj, vm_pindex_t idx,
vm_offset_t offset, size_t tlen, void *buf)
{
struct uio uio;
struct iovec iov;
uio.uio_iovcnt = 1;
uio.uio_iov = &iov;
iov.iov_base = buf;
iov.iov_len = tlen;
uio.uio_offset = 0;
uio.uio_resid = tlen;
uio.uio_rw = UIO_READ;
uio.uio_segflg = UIO_SYSSPACE;
uio.uio_td = curthread;
return (tmpfs_nocacheread(tobj, idx, offset, tlen, &uio));
}
static int
tmpfs_mappedread(vm_object_t vobj, vm_object_t tobj, size_t len, struct uio *uio)
{
struct sf_buf *sf;
vm_pindex_t idx;
vm_page_t m;
vm_offset_t offset;
off_t addr;
size_t tlen;
char *ma;
int error;
addr = uio->uio_offset;
idx = OFF_TO_IDX(addr);
offset = addr & PAGE_MASK;
tlen = MIN(PAGE_SIZE - offset, len);
if ((vobj == NULL) ||
(vobj->resident_page_count == 0 && vobj->cache == NULL))
goto nocache;
VM_OBJECT_LOCK(vobj);
lookupvpg:
if (((m = vm_page_lookup(vobj, idx)) != NULL) &&
vm_page_is_valid(m, offset, tlen)) {
if ((m->oflags & VPO_BUSY) != 0) {
/*
* Reference the page before unlocking and sleeping so
* that the page daemon is less likely to reclaim it.
*/
vm_page_lock_queues();
vm_page_flag_set(m, PG_REFERENCED);
vm_page_sleep(m, "tmfsmr");
goto lookupvpg;
}
vm_page_busy(m);
VM_OBJECT_UNLOCK(vobj);
error = uiomove_fromphys(&m, offset, tlen, uio);
VM_OBJECT_LOCK(vobj);
vm_page_wakeup(m);
VM_OBJECT_UNLOCK(vobj);
return (error);
} else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) {
KASSERT(offset == 0,
("unexpected offset in tmpfs_mappedread for sendfile"));
if ((m->oflags & VPO_BUSY) != 0) {
/*
* Reference the page before unlocking and sleeping so
* that the page daemon is less likely to reclaim it.
*/
vm_page_lock_queues();
vm_page_flag_set(m, PG_REFERENCED);
vm_page_sleep(m, "tmfsmr");
goto lookupvpg;
}
vm_page_busy(m);
VM_OBJECT_UNLOCK(vobj);
sched_pin();
sf = sf_buf_alloc(m, SFB_CPUPRIVATE);
ma = (char *)sf_buf_kva(sf);
error = tmpfs_nocacheread_buf(tobj, idx, 0, tlen, ma);
if (error == 0) {
if (tlen != PAGE_SIZE)
bzero(ma + tlen, PAGE_SIZE - tlen);
uio->uio_offset += tlen;
uio->uio_resid -= tlen;
}
sf_buf_free(sf);
sched_unpin();
VM_OBJECT_LOCK(vobj);
if (error == 0)
m->valid = VM_PAGE_BITS_ALL;
vm_page_wakeup(m);
VM_OBJECT_UNLOCK(vobj);
return (error);
}
VM_OBJECT_UNLOCK(vobj);
nocache:
error = tmpfs_nocacheread(tobj, idx, offset, tlen, uio);
return (error);
}
static int
tmpfs_read(struct vop_read_args *v)
{
struct vnode *vp = v->a_vp;
struct uio *uio = v->a_uio;
struct tmpfs_node *node;
vm_object_t uobj;
size_t len;
int resid;
int error = 0;
node = VP_TO_TMPFS_NODE(vp);
if (vp->v_type != VREG) {
error = EISDIR;
goto out;
}
if (uio->uio_offset < 0) {
error = EINVAL;
goto out;
}
node->tn_status |= TMPFS_NODE_ACCESSED;
uobj = node->tn_reg.tn_aobj;
while ((resid = uio->uio_resid) > 0) {
error = 0;
if (node->tn_size <= uio->uio_offset)
break;
len = MIN(node->tn_size - uio->uio_offset, resid);
if (len == 0)
break;
error = tmpfs_mappedread(vp->v_object, uobj, len, uio);
if ((error != 0) || (resid == uio->uio_resid))
break;
}
out:
return error;
}
/* --------------------------------------------------------------------- */
static int
tmpfs_mappedwrite(vm_object_t vobj, vm_object_t tobj, size_t len, struct uio *uio)
{
vm_pindex_t idx;
vm_page_t vpg, tpg;
vm_offset_t offset;
off_t addr;
size_t tlen;
int error;
error = 0;
addr = uio->uio_offset;
idx = OFF_TO_IDX(addr);
offset = addr & PAGE_MASK;
tlen = MIN(PAGE_SIZE - offset, len);
if ((vobj == NULL) ||
(vobj->resident_page_count == 0 && vobj->cache == NULL)) {
vpg = NULL;
goto nocache;
}
VM_OBJECT_LOCK(vobj);
lookupvpg:
if (((vpg = vm_page_lookup(vobj, idx)) != NULL) &&
vm_page_is_valid(vpg, offset, tlen)) {
if ((vpg->oflags & VPO_BUSY) != 0) {
/*
* Reference the page before unlocking and sleeping so
* that the page daemon is less likely to reclaim it.
*/
vm_page_lock_queues();
vm_page_flag_set(vpg, PG_REFERENCED);
vm_page_sleep(vpg, "tmfsmw");
goto lookupvpg;
}
vm_page_busy(vpg);
vm_page_undirty(vpg);
VM_OBJECT_UNLOCK(vobj);
error = uiomove_fromphys(&vpg, offset, tlen, uio);
} else {
if (__predict_false(vobj->cache != NULL))
vm_page_cache_free(vobj, idx, idx + 1);
VM_OBJECT_UNLOCK(vobj);
vpg = NULL;
}
nocache:
VM_OBJECT_LOCK(tobj);
vm_object_pip_add(tobj, 1);
tpg = vm_page_grab(tobj, idx, VM_ALLOC_WIRED |
VM_ALLOC_ZERO | VM_ALLOC_NORMAL | VM_ALLOC_RETRY);
if (tpg->valid != VM_PAGE_BITS_ALL) {
if (vm_pager_has_page(tobj, idx, NULL, NULL)) {
error = vm_pager_get_pages(tobj, &tpg, 1, 0);
if (error != 0) {
printf("tmpfs get pages from pager error [write]\n");
goto out;
}
} else
vm_page_zero_invalid(tpg, TRUE);
}
VM_OBJECT_UNLOCK(tobj);
if (vpg == NULL)
error = uiomove_fromphys(&tpg, offset, tlen, uio);
else {
KASSERT(vpg->valid == VM_PAGE_BITS_ALL, ("parts of vpg invalid"));
pmap_copy_page(vpg, tpg);
}
VM_OBJECT_LOCK(tobj);
out:
if (vobj != NULL)
VM_OBJECT_LOCK(vobj);
if (error == 0) {
KASSERT(tpg->valid == VM_PAGE_BITS_ALL,
("parts of tpg invalid"));
vm_page_dirty(tpg);
}
vm_page_lock(tpg);
vm_page_unwire(tpg, TRUE);
vm_page_unlock(tpg);
vm_page_wakeup(tpg);
if (vpg != NULL)
vm_page_wakeup(vpg);
if (vobj != NULL)
VM_OBJECT_UNLOCK(vobj);
vm_object_pip_subtract(tobj, 1);
VM_OBJECT_UNLOCK(tobj);
return (error);
}
static int
tmpfs_write(struct vop_write_args *v)
{
struct vnode *vp = v->a_vp;
struct uio *uio = v->a_uio;
int ioflag = v->a_ioflag;
boolean_t extended;
int error = 0;
off_t oldsize;
struct tmpfs_node *node;
vm_object_t uobj;
size_t len;
int resid;
node = VP_TO_TMPFS_NODE(vp);
oldsize = node->tn_size;
if (uio->uio_offset < 0 || vp->v_type != VREG) {
error = EINVAL;
goto out;
}
if (uio->uio_resid == 0) {
error = 0;
goto out;
}
if (ioflag & IO_APPEND)
uio->uio_offset = node->tn_size;
if (uio->uio_offset + uio->uio_resid >
VFS_TO_TMPFS(vp->v_mount)->tm_maxfilesize)
return (EFBIG);
if (vn_rlimit_fsize(vp, uio, uio->uio_td))
return (EFBIG);
extended = uio->uio_offset + uio->uio_resid > node->tn_size;
if (extended) {
error = tmpfs_reg_resize(vp, uio->uio_offset + uio->uio_resid);
if (error != 0)
goto out;
}
uobj = node->tn_reg.tn_aobj;
while ((resid = uio->uio_resid) > 0) {
if (node->tn_size <= uio->uio_offset)
break;
len = MIN(node->tn_size - uio->uio_offset, resid);
if (len == 0)
break;
error = tmpfs_mappedwrite(vp->v_object, uobj, len, uio);
if ((error != 0) || (resid == uio->uio_resid))
break;
}
node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_MODIFIED |
(extended ? TMPFS_NODE_CHANGED : 0);
if (node->tn_mode & (S_ISUID | S_ISGID)) {
if (priv_check_cred(v->a_cred, PRIV_VFS_RETAINSUGID, 0))
node->tn_mode &= ~(S_ISUID | S_ISGID);
}
if (error != 0)
(void)tmpfs_reg_resize(vp, oldsize);
out:
MPASS(IMPLIES(error == 0, uio->uio_resid == 0));
MPASS(IMPLIES(error != 0, oldsize == node->tn_size));
return error;
}
/* --------------------------------------------------------------------- */
static int
tmpfs_fsync(struct vop_fsync_args *v)
{
struct vnode *vp = v->a_vp;
MPASS(VOP_ISLOCKED(vp));
tmpfs_update(vp);
return 0;
}
/* --------------------------------------------------------------------- */
static int
tmpfs_remove(struct vop_remove_args *v)
{
struct vnode *dvp = v->a_dvp;
struct vnode *vp = v->a_vp;
int error;
struct tmpfs_dirent *de;
struct tmpfs_mount *tmp;
struct tmpfs_node *dnode;
struct tmpfs_node *node;
MPASS(VOP_ISLOCKED(dvp));
MPASS(VOP_ISLOCKED(vp));
if (vp->v_type == VDIR) {
error = EISDIR;
goto out;
}
dnode = VP_TO_TMPFS_DIR(dvp);
node = VP_TO_TMPFS_NODE(vp);
tmp = VFS_TO_TMPFS(vp->v_mount);
de = tmpfs_dir_lookup(dnode, node, v->a_cnp);
MPASS(de != NULL);
/* Files marked as immutable or append-only cannot be deleted. */
if ((node->tn_flags & (IMMUTABLE | APPEND | NOUNLINK)) ||
(dnode->tn_flags & APPEND)) {
error = EPERM;
goto out;
}
/* Remove the entry from the directory; as it is a file, we do not
* have to change the number of hard links of the directory. */
tmpfs_dir_detach(dvp, de);
if (v->a_cnp->cn_flags & DOWHITEOUT)
tmpfs_dir_whiteout_add(dvp, v->a_cnp);
/* Free the directory entry we just deleted. Note that the node
* referred by it will not be removed until the vnode is really
* reclaimed. */
tmpfs_free_dirent(tmp, de, TRUE);
if (node->tn_links > 0)
- node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | \
- TMPFS_NODE_MODIFIED;
+ node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED;
error = 0;
out:
return error;
}
/* --------------------------------------------------------------------- */
static int
tmpfs_link(struct vop_link_args *v)
{
struct vnode *dvp = v->a_tdvp;
struct vnode *vp = v->a_vp;
struct componentname *cnp = v->a_cnp;
int error;
struct tmpfs_dirent *de;
struct tmpfs_node *node;
MPASS(VOP_ISLOCKED(dvp));
MPASS(cnp->cn_flags & HASBUF);
MPASS(dvp != vp); /* XXX When can this be false? */
node = VP_TO_TMPFS_NODE(vp);
/* XXX: Why aren't the following two tests done by the caller? */
/* Hard links of directories are forbidden. */
if (vp->v_type == VDIR) {
error = EPERM;
goto out;
}
/* Cannot create cross-device links. */
if (dvp->v_mount != vp->v_mount) {
error = EXDEV;
goto out;
}
/* Ensure that we do not overflow the maximum number of links imposed
* by the system. */
MPASS(node->tn_links <= LINK_MAX);
if (node->tn_links == LINK_MAX) {
error = EMLINK;
goto out;
}
/* We cannot create links of files marked immutable or append-only. */
if (node->tn_flags & (IMMUTABLE | APPEND)) {
error = EPERM;
goto out;
}
/* Allocate a new directory entry to represent the node. */
error = tmpfs_alloc_dirent(VFS_TO_TMPFS(vp->v_mount), node,
cnp->cn_nameptr, cnp->cn_namelen, &de);
if (error != 0)
goto out;
/* Insert the new directory entry into the appropriate directory. */
if (cnp->cn_flags & ISWHITEOUT)
tmpfs_dir_whiteout_remove(dvp, cnp);
tmpfs_dir_attach(dvp, de);
/* vp link count has changed, so update node times. */
node->tn_status |= TMPFS_NODE_CHANGED;
tmpfs_update(vp);
error = 0;
out:
return error;
}
/* --------------------------------------------------------------------- */
static int
tmpfs_rename(struct vop_rename_args *v)
{
struct vnode *fdvp = v->a_fdvp;
struct vnode *fvp = v->a_fvp;
struct componentname *fcnp = v->a_fcnp;
struct vnode *tdvp = v->a_tdvp;
struct vnode *tvp = v->a_tvp;
struct componentname *tcnp = v->a_tcnp;
char *newname;
int error;
struct tmpfs_dirent *de;
struct tmpfs_mount *tmp;
struct tmpfs_node *fdnode;
struct tmpfs_node *fnode;
struct tmpfs_node *tnode;
struct tmpfs_node *tdnode;
MPASS(VOP_ISLOCKED(tdvp));
MPASS(IMPLIES(tvp != NULL, VOP_ISLOCKED(tvp)));
MPASS(fcnp->cn_flags & HASBUF);
MPASS(tcnp->cn_flags & HASBUF);
tnode = (tvp == NULL) ? NULL : VP_TO_TMPFS_NODE(tvp);
/* Disallow cross-device renames.
* XXX Why isn't this done by the caller? */
if (fvp->v_mount != tdvp->v_mount ||
(tvp != NULL && fvp->v_mount != tvp->v_mount)) {
error = EXDEV;
goto out;
}
tmp = VFS_TO_TMPFS(tdvp->v_mount);
tdnode = VP_TO_TMPFS_DIR(tdvp);
/* If source and target are the same file, there is nothing to do. */
if (fvp == tvp) {
error = 0;
goto out;
}
/* If we need to move the directory between entries, lock the
* source so that we can safely operate on it. */
if (tdvp != fdvp) {
error = vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY);
if (error != 0)
goto out;
}
fdnode = VP_TO_TMPFS_DIR(fdvp);
fnode = VP_TO_TMPFS_NODE(fvp);
de = tmpfs_dir_lookup(fdnode, fnode, fcnp);
/* Entry can disappear before we lock fdvp,
* also avoid manipulating '.' and '..' entries. */
if (de == NULL) {
if ((fcnp->cn_flags & ISDOTDOT) != 0 ||
(fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.'))
error = EINVAL;
else
error = ENOENT;
goto out_locked;
}
MPASS(de->td_node == fnode);
/* If re-naming a directory to another preexisting directory
* ensure that the target directory is empty so that its
* removal causes no side effects.
* Kern_rename gurantees the destination to be a directory
* if the source is one. */
if (tvp != NULL) {
MPASS(tnode != NULL);
if ((tnode->tn_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
(tdnode->tn_flags & (APPEND | IMMUTABLE))) {
error = EPERM;
goto out_locked;
}
if (fnode->tn_type == VDIR && tnode->tn_type == VDIR) {
if (tnode->tn_size > 0) {
error = ENOTEMPTY;
goto out_locked;
}
} else if (fnode->tn_type == VDIR && tnode->tn_type != VDIR) {
error = ENOTDIR;
goto out_locked;
} else if (fnode->tn_type != VDIR && tnode->tn_type == VDIR) {
error = EISDIR;
goto out_locked;
} else {
MPASS(fnode->tn_type != VDIR &&
tnode->tn_type != VDIR);
}
}
if ((fnode->tn_flags & (NOUNLINK | IMMUTABLE | APPEND))
|| (fdnode->tn_flags & (APPEND | IMMUTABLE))) {
error = EPERM;
goto out_locked;
}
/* Ensure that we have enough memory to hold the new name, if it
* has to be changed. */
if (fcnp->cn_namelen != tcnp->cn_namelen ||
bcmp(fcnp->cn_nameptr, tcnp->cn_nameptr, fcnp->cn_namelen) != 0) {
newname = malloc(tcnp->cn_namelen, M_TMPFSNAME, M_WAITOK);
} else
newname = NULL;
/* If the node is being moved to another directory, we have to do
* the move. */
if (fdnode != tdnode) {
/* In case we are moving a directory, we have to adjust its
* parent to point to the new parent. */
if (de->td_node->tn_type == VDIR) {
struct tmpfs_node *n;
/* Ensure the target directory is not a child of the
* directory being moved. Otherwise, we'd end up
* with stale nodes. */
n = tdnode;
/* TMPFS_LOCK garanties that no nodes are freed while
* traversing the list. Nodes can only be marked as
* removed: tn_parent == NULL. */
TMPFS_LOCK(tmp);
TMPFS_NODE_LOCK(n);
while (n != n->tn_dir.tn_parent) {
struct tmpfs_node *parent;
if (n == fnode) {
TMPFS_NODE_UNLOCK(n);
TMPFS_UNLOCK(tmp);
error = EINVAL;
if (newname != NULL)
free(newname, M_TMPFSNAME);
goto out_locked;
}
parent = n->tn_dir.tn_parent;
TMPFS_NODE_UNLOCK(n);
if (parent == NULL) {
n = NULL;
break;
}
TMPFS_NODE_LOCK(parent);
if (parent->tn_dir.tn_parent == NULL) {
TMPFS_NODE_UNLOCK(parent);
n = NULL;
break;
}
n = parent;
}
TMPFS_UNLOCK(tmp);
if (n == NULL) {
error = EINVAL;
if (newname != NULL)
free(newname, M_TMPFSNAME);
goto out_locked;
}
TMPFS_NODE_UNLOCK(n);
/* Adjust the parent pointer. */
TMPFS_VALIDATE_DIR(fnode);
TMPFS_NODE_LOCK(de->td_node);
de->td_node->tn_dir.tn_parent = tdnode;
TMPFS_NODE_UNLOCK(de->td_node);
/* As a result of changing the target of the '..'
* entry, the link count of the source and target
* directories has to be adjusted. */
TMPFS_NODE_LOCK(tdnode);
TMPFS_ASSERT_LOCKED(tdnode);
tdnode->tn_links++;
TMPFS_NODE_UNLOCK(tdnode);
TMPFS_NODE_LOCK(fdnode);
TMPFS_ASSERT_LOCKED(fdnode);
fdnode->tn_links--;
TMPFS_NODE_UNLOCK(fdnode);
}
/* Do the move: just remove the entry from the source directory
* and insert it into the target one. */
tmpfs_dir_detach(fdvp, de);
if (fcnp->cn_flags & DOWHITEOUT)
tmpfs_dir_whiteout_add(fdvp, fcnp);
if (tcnp->cn_flags & ISWHITEOUT)
tmpfs_dir_whiteout_remove(tdvp, tcnp);
tmpfs_dir_attach(tdvp, de);
}
/* If the name has changed, we need to make it effective by changing
* it in the directory entry. */
if (newname != NULL) {
MPASS(tcnp->cn_namelen <= MAXNAMLEN);
free(de->td_name, M_TMPFSNAME);
de->td_namelen = (uint16_t)tcnp->cn_namelen;
memcpy(newname, tcnp->cn_nameptr, tcnp->cn_namelen);
de->td_name = newname;
fnode->tn_status |= TMPFS_NODE_CHANGED;
tdnode->tn_status |= TMPFS_NODE_MODIFIED;
}
/* If we are overwriting an entry, we have to remove the old one
* from the target directory. */
if (tvp != NULL) {
/* Remove the old entry from the target directory. */
de = tmpfs_dir_lookup(tdnode, tnode, tcnp);
tmpfs_dir_detach(tdvp, de);
/* Free the directory entry we just deleted. Note that the
* node referred by it will not be removed until the vnode is
* really reclaimed. */
tmpfs_free_dirent(VFS_TO_TMPFS(tvp->v_mount), de, TRUE);
}
error = 0;
out_locked:
if (fdnode != tdnode)
VOP_UNLOCK(fdvp, 0);
out:
/* Release target nodes. */
/* XXX: I don't understand when tdvp can be the same as tvp, but
* other code takes care of this... */
if (tdvp == tvp)
vrele(tdvp);
else
vput(tdvp);
if (tvp != NULL)
vput(tvp);
/* Release source nodes. */
vrele(fdvp);
vrele(fvp);
return error;
}
/* --------------------------------------------------------------------- */
static int
tmpfs_mkdir(struct vop_mkdir_args *v)
{
struct vnode *dvp = v->a_dvp;
struct vnode **vpp = v->a_vpp;
struct componentname *cnp = v->a_cnp;
struct vattr *vap = v->a_vap;
MPASS(vap->va_type == VDIR);
return tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL);
}
/* --------------------------------------------------------------------- */
static int
tmpfs_rmdir(struct vop_rmdir_args *v)
{
struct vnode *dvp = v->a_dvp;
struct vnode *vp = v->a_vp;
int error;
struct tmpfs_dirent *de;
struct tmpfs_mount *tmp;
struct tmpfs_node *dnode;
struct tmpfs_node *node;
MPASS(VOP_ISLOCKED(dvp));
MPASS(VOP_ISLOCKED(vp));
tmp = VFS_TO_TMPFS(dvp->v_mount);
dnode = VP_TO_TMPFS_DIR(dvp);
node = VP_TO_TMPFS_DIR(vp);
/* Directories with more than two entries ('.' and '..') cannot be
* removed. */
if (node->tn_size > 0) {
error = ENOTEMPTY;
goto out;
}
if ((dnode->tn_flags & APPEND)
|| (node->tn_flags & (NOUNLINK | IMMUTABLE | APPEND))) {
error = EPERM;
goto out;
}
/* This invariant holds only if we are not trying to remove "..".
* We checked for that above so this is safe now. */
MPASS(node->tn_dir.tn_parent == dnode);
/* Get the directory entry associated with node (vp). This was
* filled by tmpfs_lookup while looking up the entry. */
de = tmpfs_dir_lookup(dnode, node, v->a_cnp);
MPASS(TMPFS_DIRENT_MATCHES(de,
v->a_cnp->cn_nameptr,
v->a_cnp->cn_namelen));
/* Check flags to see if we are allowed to remove the directory. */
if (dnode->tn_flags & APPEND
|| node->tn_flags & (NOUNLINK | IMMUTABLE | APPEND)) {
error = EPERM;
goto out;
}
/* Detach the directory entry from the directory (dnode). */
tmpfs_dir_detach(dvp, de);
if (v->a_cnp->cn_flags & DOWHITEOUT)
tmpfs_dir_whiteout_add(dvp, v->a_cnp);
/* No vnode should be allocated for this entry from this point */
TMPFS_NODE_LOCK(node);
TMPFS_ASSERT_ELOCKED(node);
node->tn_links--;
node->tn_dir.tn_parent = NULL;
node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | \
TMPFS_NODE_MODIFIED;
TMPFS_NODE_UNLOCK(node);
TMPFS_NODE_LOCK(dnode);
TMPFS_ASSERT_ELOCKED(dnode);
dnode->tn_links--;
dnode->tn_status |= TMPFS_NODE_ACCESSED | \
TMPFS_NODE_CHANGED | TMPFS_NODE_MODIFIED;
TMPFS_NODE_UNLOCK(dnode);
cache_purge(dvp);
cache_purge(vp);
/* Free the directory entry we just deleted. Note that the node
* referred by it will not be removed until the vnode is really
* reclaimed. */
tmpfs_free_dirent(tmp, de, TRUE);
/* Release the deleted vnode (will destroy the node, notify
* interested parties and clean it from the cache). */
dnode->tn_status |= TMPFS_NODE_CHANGED;
tmpfs_update(dvp);
error = 0;
out:
return error;
}
/* --------------------------------------------------------------------- */
static int
tmpfs_symlink(struct vop_symlink_args *v)
{
struct vnode *dvp = v->a_dvp;
struct vnode **vpp = v->a_vpp;
struct componentname *cnp = v->a_cnp;
struct vattr *vap = v->a_vap;
char *target = v->a_target;
#ifdef notyet /* XXX FreeBSD BUG: kern_symlink is not setting VLNK */
MPASS(vap->va_type == VLNK);
#else
vap->va_type = VLNK;
#endif
return tmpfs_alloc_file(dvp, vpp, vap, cnp, target);
}
/* --------------------------------------------------------------------- */
static int
tmpfs_readdir(struct vop_readdir_args *v)
{
struct vnode *vp = v->a_vp;
struct uio *uio = v->a_uio;
int *eofflag = v->a_eofflag;
u_long **cookies = v->a_cookies;
int *ncookies = v->a_ncookies;
int error;
off_t startoff;
off_t cnt = 0;
struct tmpfs_node *node;
/* This operation only makes sense on directory nodes. */
if (vp->v_type != VDIR)
return ENOTDIR;
node = VP_TO_TMPFS_DIR(vp);
startoff = uio->uio_offset;
if (uio->uio_offset == TMPFS_DIRCOOKIE_DOT) {
error = tmpfs_dir_getdotdent(node, uio);
if (error != 0)
goto outok;
cnt++;
}
if (uio->uio_offset == TMPFS_DIRCOOKIE_DOTDOT) {
error = tmpfs_dir_getdotdotdent(node, uio);
if (error != 0)
goto outok;
cnt++;
}
error = tmpfs_dir_getdents(node, uio, &cnt);
outok:
MPASS(error >= -1);
if (error == -1)
error = (cnt != 0) ? 0 : EINVAL;
if (eofflag != NULL)
*eofflag =
(error == 0 && uio->uio_offset == TMPFS_DIRCOOKIE_EOF);
/* Update NFS-related variables. */
if (error == 0 && cookies != NULL && ncookies != NULL) {
off_t i;
off_t off = startoff;
struct tmpfs_dirent *de = NULL;
*ncookies = cnt;
*cookies = malloc(cnt * sizeof(off_t), M_TEMP, M_WAITOK);
for (i = 0; i < cnt; i++) {
MPASS(off != TMPFS_DIRCOOKIE_EOF);
if (off == TMPFS_DIRCOOKIE_DOT) {
off = TMPFS_DIRCOOKIE_DOTDOT;
} else {
if (off == TMPFS_DIRCOOKIE_DOTDOT) {
de = TAILQ_FIRST(&node->tn_dir.tn_dirhead);
} else if (de != NULL) {
de = TAILQ_NEXT(de, td_entries);
} else {
de = tmpfs_dir_lookupbycookie(node,
off);
MPASS(de != NULL);
de = TAILQ_NEXT(de, td_entries);
}
if (de == NULL)
off = TMPFS_DIRCOOKIE_EOF;
else
off = tmpfs_dircookie(de);
}
(*cookies)[i] = off;
}
MPASS(uio->uio_offset == off);
}
return error;
}
/* --------------------------------------------------------------------- */
static int
tmpfs_readlink(struct vop_readlink_args *v)
{
struct vnode *vp = v->a_vp;
struct uio *uio = v->a_uio;
int error;
struct tmpfs_node *node;
MPASS(uio->uio_offset == 0);
MPASS(vp->v_type == VLNK);
node = VP_TO_TMPFS_NODE(vp);
error = uiomove(node->tn_link, MIN(node->tn_size, uio->uio_resid),
uio);
node->tn_status |= TMPFS_NODE_ACCESSED;
return error;
}
/* --------------------------------------------------------------------- */
static int
tmpfs_inactive(struct vop_inactive_args *v)
{
struct vnode *vp = v->a_vp;
struct thread *l = v->a_td;
struct tmpfs_node *node;
MPASS(VOP_ISLOCKED(vp));
node = VP_TO_TMPFS_NODE(vp);
if (node->tn_links == 0)
vrecycle(vp, l);
return 0;
}
/* --------------------------------------------------------------------- */
int
tmpfs_reclaim(struct vop_reclaim_args *v)
{
struct vnode *vp = v->a_vp;
struct tmpfs_mount *tmp;
struct tmpfs_node *node;
node = VP_TO_TMPFS_NODE(vp);
tmp = VFS_TO_TMPFS(vp->v_mount);
vnode_destroy_vobject(vp);
cache_purge(vp);
TMPFS_NODE_LOCK(node);
TMPFS_ASSERT_ELOCKED(node);
tmpfs_free_vp(vp);
/* If the node referenced by this vnode was deleted by the user,
* we must free its associated data structures (now that the vnode
* is being reclaimed). */
if (node->tn_links == 0 &&
(node->tn_vpstate & TMPFS_VNODE_ALLOCATING) == 0) {
node->tn_vpstate = TMPFS_VNODE_DOOMED;
TMPFS_NODE_UNLOCK(node);
tmpfs_free_node(tmp, node);
} else
TMPFS_NODE_UNLOCK(node);
MPASS(vp->v_data == NULL);
return 0;
}
/* --------------------------------------------------------------------- */
static int
tmpfs_print(struct vop_print_args *v)
{
struct vnode *vp = v->a_vp;
struct tmpfs_node *node;
node = VP_TO_TMPFS_NODE(vp);
printf("tag VT_TMPFS, tmpfs_node %p, flags 0x%x, links %d\n",
node, node->tn_flags, node->tn_links);
printf("\tmode 0%o, owner %d, group %d, size %" PRIdMAX
", status 0x%x\n",
node->tn_mode, node->tn_uid, node->tn_gid,
(uintmax_t)node->tn_size, node->tn_status);
if (vp->v_type == VFIFO)
fifo_printinfo(vp);
printf("\n");
return 0;
}
/* --------------------------------------------------------------------- */
static int
tmpfs_pathconf(struct vop_pathconf_args *v)
{
int name = v->a_name;
register_t *retval = v->a_retval;
int error;
error = 0;
switch (name) {
case _PC_LINK_MAX:
*retval = LINK_MAX;
break;
case _PC_NAME_MAX:
*retval = NAME_MAX;
break;
case _PC_PATH_MAX:
*retval = PATH_MAX;
break;
case _PC_PIPE_BUF:
*retval = PIPE_BUF;
break;
case _PC_CHOWN_RESTRICTED:
*retval = 1;
break;
case _PC_NO_TRUNC:
*retval = 1;
break;
case _PC_SYNC_IO:
*retval = 1;
break;
case _PC_FILESIZEBITS:
*retval = 0; /* XXX Don't know which value should I return. */
break;
default:
error = EINVAL;
}
return error;
}
static int
tmpfs_vptofh(struct vop_vptofh_args *ap)
{
struct tmpfs_fid *tfhp;
struct tmpfs_node *node;
tfhp = (struct tmpfs_fid *)ap->a_fhp;
node = VP_TO_TMPFS_NODE(ap->a_vp);
tfhp->tf_len = sizeof(struct tmpfs_fid);
tfhp->tf_id = node->tn_id;
tfhp->tf_gen = node->tn_gen;
return (0);
}
static int
tmpfs_whiteout(struct vop_whiteout_args *ap)
{
struct vnode *dvp = ap->a_dvp;
struct componentname *cnp = ap->a_cnp;
struct tmpfs_dirent *de;
switch (ap->a_flags) {
case LOOKUP:
return (0);
case CREATE:
de = tmpfs_dir_lookup(VP_TO_TMPFS_DIR(dvp), NULL, cnp);
if (de != NULL)
return (de->td_node == NULL ? 0 : EEXIST);
return (tmpfs_dir_whiteout_add(dvp, cnp));
case DELETE:
tmpfs_dir_whiteout_remove(dvp, cnp);
return (0);
default:
panic("tmpfs_whiteout: unknown op");
}
}
/* --------------------------------------------------------------------- */
/*
* vnode operations vector used for files stored in a tmpfs file system.
*/
struct vop_vector tmpfs_vnodeop_entries = {
.vop_default = &default_vnodeops,
.vop_lookup = vfs_cache_lookup,
.vop_cachedlookup = tmpfs_lookup,
.vop_create = tmpfs_create,
.vop_mknod = tmpfs_mknod,
.vop_open = tmpfs_open,
.vop_close = tmpfs_close,
.vop_access = tmpfs_access,
.vop_getattr = tmpfs_getattr,
.vop_setattr = tmpfs_setattr,
.vop_read = tmpfs_read,
.vop_write = tmpfs_write,
.vop_fsync = tmpfs_fsync,
.vop_remove = tmpfs_remove,
.vop_link = tmpfs_link,
.vop_rename = tmpfs_rename,
.vop_mkdir = tmpfs_mkdir,
.vop_rmdir = tmpfs_rmdir,
.vop_symlink = tmpfs_symlink,
.vop_readdir = tmpfs_readdir,
.vop_readlink = tmpfs_readlink,
.vop_inactive = tmpfs_inactive,
.vop_reclaim = tmpfs_reclaim,
.vop_print = tmpfs_print,
.vop_pathconf = tmpfs_pathconf,
.vop_vptofh = tmpfs_vptofh,
.vop_whiteout = tmpfs_whiteout,
.vop_bmap = VOP_EOPNOTSUPP,
};
Index: projects/altix/sys/gdb/gdb_main.c
===================================================================
--- projects/altix/sys/gdb/gdb_main.c (revision 218875)
+++ projects/altix/sys/gdb/gdb_main.c (revision 218876)
@@ -1,295 +1,306 @@
/*-
* Copyright (c) 2004 Marcel Moolenaar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kdb.h>
#include <sys/kernel.h>
#include <sys/pcpu.h>
#include <sys/proc.h>
#include <sys/reboot.h>
#include <machine/gdb_machdep.h>
#include <machine/kdb.h>
#include <gdb/gdb.h>
#include <gdb/gdb_int.h>
static dbbe_init_f gdb_init;
static dbbe_trap_f gdb_trap;
KDB_BACKEND(gdb, gdb_init, NULL, gdb_trap);
static struct gdb_dbgport null_gdb_dbgport;
DATA_SET(gdb_dbgport_set, null_gdb_dbgport);
SET_DECLARE(gdb_dbgport_set, struct gdb_dbgport);
struct gdb_dbgport *gdb_cur = NULL;
int gdb_listening = 0;
static int
gdb_init(void)
{
struct gdb_dbgport *dp, **iter;
int cur_pri, pri;
gdb_cur = NULL;
cur_pri = -1;
SET_FOREACH(iter, gdb_dbgport_set) {
dp = *iter;
pri = (dp->gdb_probe != NULL) ? dp->gdb_probe() : -1;
dp->gdb_active = (pri >= 0) ? 0 : -1;
if (pri > cur_pri) {
cur_pri = pri;
gdb_cur = dp;
}
}
if (gdb_cur != NULL) {
printf("GDB: debug ports:");
SET_FOREACH(iter, gdb_dbgport_set) {
dp = *iter;
if (dp->gdb_active == 0)
printf(" %s", dp->gdb_name);
}
printf("\n");
} else
printf("GDB: no debug ports present\n");
if (gdb_cur != NULL) {
gdb_cur->gdb_init();
printf("GDB: current port: %s\n", gdb_cur->gdb_name);
}
if (gdb_cur != NULL) {
cur_pri = (boothowto & RB_GDB) ? 2 : 0;
gdb_consinit();
} else
cur_pri = -1;
return (cur_pri);
}
static int
gdb_trap(int type, int code)
{
+ jmp_buf jb;
struct thread *thr_iter;
+ void *prev_jb;
+ prev_jb = kdb_jmpbuf(jb);
+ if (setjmp(jb) != 0) {
+ printf("%s bailing, hopefully back to ddb!\n", __func__);
+ gdb_listening = 0;
+ (void)kdb_jmpbuf(prev_jb);
+ return (1);
+ }
+
gdb_listening = 0;
/*
* Send a T packet. We currently do not support watchpoints (the
* awatch, rwatch or watch elements).
*/
gdb_tx_begin('T');
gdb_tx_hex(gdb_cpu_signal(type, code), 2);
gdb_tx_varhex(GDB_REG_PC);
gdb_tx_char(':');
gdb_tx_reg(GDB_REG_PC);
gdb_tx_char(';');
gdb_tx_str("thread:");
gdb_tx_varhex((long)kdb_thread->td_tid);
gdb_tx_char(';');
gdb_tx_end(); /* XXX check error condition. */
thr_iter = NULL;
while (gdb_rx_begin() == 0) {
/* printf("GDB: got '%s'\n", gdb_rxp); */
switch (gdb_rx_char()) {
case '?': /* Last signal. */
gdb_tx_begin('S');
gdb_tx_hex(gdb_cpu_signal(type, code), 2);
gdb_tx_end();
break;
case 'c': { /* Continue. */
uintmax_t addr;
register_t pc;
if (!gdb_rx_varhex(&addr)) {
pc = addr;
gdb_cpu_setreg(GDB_REG_PC, &pc);
}
kdb_cpu_clear_singlestep();
gdb_listening = 1;
return (1);
}
case 'C': { /* Continue with signal. */
uintmax_t addr, sig;
register_t pc;
if (!gdb_rx_varhex(&sig) && gdb_rx_char() == ';' &&
!gdb_rx_varhex(&addr)) {
pc = addr;
gdb_cpu_setreg(GDB_REG_PC, &pc);
}
kdb_cpu_clear_singlestep();
gdb_listening = 1;
return (1);
}
case 'D': { /* Detach */
gdb_tx_ok();
kdb_cpu_clear_singlestep();
return (1);
}
case 'g': { /* Read registers. */
size_t r;
gdb_tx_begin(0);
for (r = 0; r < GDB_NREGS; r++)
gdb_tx_reg(r);
gdb_tx_end();
break;
}
case 'G': /* Write registers. */
gdb_tx_err(0);
break;
case 'H': { /* Set thread. */
intmax_t tid;
struct thread *thr;
gdb_rx_char();
if (gdb_rx_varhex(&tid)) {
gdb_tx_err(EINVAL);
break;
}
if (tid > 0) {
thr = kdb_thr_lookup(tid);
if (thr == NULL) {
gdb_tx_err(ENOENT);
break;
}
kdb_thr_select(thr);
}
gdb_tx_ok();
break;
}
case 'k': /* Kill request. */
kdb_cpu_clear_singlestep();
gdb_listening = 1;
return (1);
case 'm': { /* Read memory. */
uintmax_t addr, size;
if (gdb_rx_varhex(&addr) || gdb_rx_char() != ',' ||
gdb_rx_varhex(&size)) {
gdb_tx_err(EINVAL);
break;
}
gdb_tx_begin(0);
if (gdb_tx_mem((char *)(uintptr_t)addr, size))
gdb_tx_end();
else
gdb_tx_err(EIO);
break;
}
case 'M': { /* Write memory. */
uintmax_t addr, size;
if (gdb_rx_varhex(&addr) || gdb_rx_char() != ',' ||
gdb_rx_varhex(&size) || gdb_rx_char() != ':') {
gdb_tx_err(EINVAL);
break;
}
if (gdb_rx_mem((char *)(uintptr_t)addr, size) == 0)
gdb_tx_err(EIO);
else
gdb_tx_ok();
break;
}
case 'P': { /* Write register. */
char *val;
uintmax_t reg;
val = gdb_rxp;
if (gdb_rx_varhex(&reg) || gdb_rx_char() != '=' ||
!gdb_rx_mem(val, gdb_cpu_regsz(reg))) {
gdb_tx_err(EINVAL);
break;
}
gdb_cpu_setreg(reg, val);
gdb_tx_ok();
break;
}
case 'q': /* General query. */
if (gdb_rx_equal("fThreadInfo")) {
thr_iter = kdb_thr_first();
gdb_tx_begin('m');
gdb_tx_hex((long)thr_iter->td_tid, 8);
gdb_tx_end();
} else if (gdb_rx_equal("sThreadInfo")) {
if (thr_iter == NULL) {
gdb_tx_err(ENXIO);
break;
}
thr_iter = kdb_thr_next(thr_iter);
if (thr_iter != NULL) {
gdb_tx_begin('m');
gdb_tx_hex((long)thr_iter->td_tid, 8);
gdb_tx_end();
} else {
gdb_tx_begin('l');
gdb_tx_end();
}
} else if (!gdb_cpu_query())
gdb_tx_empty();
break;
case 's': { /* Step. */
uintmax_t addr;
register_t pc;
if (!gdb_rx_varhex(&addr)) {
pc = addr;
gdb_cpu_setreg(GDB_REG_PC, &pc);
}
kdb_cpu_set_singlestep();
gdb_listening = 1;
return (1);
}
case 'S': { /* Step with signal. */
uintmax_t addr, sig;
register_t pc;
if (!gdb_rx_varhex(&sig) && gdb_rx_char() == ';' &&
!gdb_rx_varhex(&addr)) {
pc = addr;
gdb_cpu_setreg(GDB_REG_PC, &pc);
}
kdb_cpu_set_singlestep();
gdb_listening = 1;
return (1);
}
case 'T': { /* Thread alive. */
intmax_t tid;
if (gdb_rx_varhex(&tid)) {
gdb_tx_err(EINVAL);
break;
}
if (kdb_thr_lookup(tid) != NULL)
gdb_tx_ok();
else
gdb_tx_err(ENOENT);
break;
}
case -1:
/* Empty command. Treat as unknown command. */
/* FALLTHROUGH */
default:
/* Unknown command. Send empty response. */
gdb_tx_empty();
break;
}
}
+ (void)kdb_jmpbuf(prev_jb);
return (0);
}
Index: projects/altix/sys/gdb/gdb_packet.c
===================================================================
--- projects/altix/sys/gdb/gdb_packet.c (revision 218875)
+++ projects/altix/sys/gdb/gdb_packet.c (revision 218876)
@@ -1,310 +1,322 @@
/*-
* Copyright (c) 2004 Marcel Moolenaar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/ctype.h>
#include <sys/kdb.h>
+#include <sys/ttydefaults.h>
#include <machine/gdb_machdep.h>
#include <machine/kdb.h>
#include <gdb/gdb.h>
#include <gdb/gdb_int.h>
static char gdb_rxbuf[GDB_BUFSZ];
char *gdb_rxp = NULL;
size_t gdb_rxsz = 0;
static char gdb_txbuf[GDB_BUFSZ];
char *gdb_txp = NULL; /* Used in inline functions. */
#define C2N(c) (((c) < 'A') ? (c) - '0' : \
10 + (((c) < 'a') ? (c) - 'A' : (c) - 'a'))
#define N2C(n) (((n) < 10) ? (n) + '0' : (n) + 'a' - 10)
/*
* Get a single character
*/
static int
gdb_getc(void)
{
int c;
do
c = gdb_cur->gdb_getc();
while (c == -1);
+
+ if (c == CTRL('C')) {
+ printf("Received ^C; trying to switch back to ddb.\n");
+
+ if (kdb_dbbe_select("ddb") != 0)
+ printf("The ddb backend could not be selected.\n");
+ else {
+ printf("using longjmp, hope it works!\n");
+ kdb_reenter();
+ }
+ }
return (c);
}
/*
* Functions to receive and extract from a packet.
*/
int
gdb_rx_begin(void)
{
int c, cksum;
gdb_rxp = NULL;
do {
/*
* Wait for the start character, ignore all others.
* XXX needs a timeout.
*/
while ((c = gdb_getc()) != '$')
;
/* Read until a # or end of buffer is found. */
cksum = 0;
gdb_rxsz = 0;
while (gdb_rxsz < sizeof(gdb_rxbuf) - 1) {
c = gdb_getc();
if (c == '#')
break;
gdb_rxbuf[gdb_rxsz++] = c;
cksum += c;
}
gdb_rxbuf[gdb_rxsz] = 0;
cksum &= 0xff;
/* Bail out on a buffer overflow. */
if (c != '#') {
gdb_cur->gdb_putc('-');
return (ENOSPC);
}
c = gdb_getc();
cksum -= (C2N(c) << 4) & 0xf0;
c = gdb_getc();
cksum -= C2N(c) & 0x0f;
gdb_cur->gdb_putc((cksum == 0) ? '+' : '-');
if (cksum != 0)
printf("GDB: packet `%s' has invalid checksum\n",
gdb_rxbuf);
} while (cksum != 0);
gdb_rxp = gdb_rxbuf;
return (0);
}
int
gdb_rx_equal(const char *str)
{
int len;
len = strlen(str);
if (len > gdb_rxsz || strncmp(str, gdb_rxp, len) != 0)
return (0);
gdb_rxp += len;
gdb_rxsz -= len;
return (1);
}
int
gdb_rx_mem(unsigned char *addr, size_t size)
{
unsigned char *p;
void *prev;
jmp_buf jb;
size_t cnt;
int ret;
unsigned char c;
if (size * 2 != gdb_rxsz)
return (-1);
prev = kdb_jmpbuf(jb);
ret = setjmp(jb);
if (ret == 0) {
p = addr;
cnt = size;
while (cnt-- > 0) {
c = (C2N(gdb_rxp[0]) << 4) & 0xf0;
c |= C2N(gdb_rxp[1]) & 0x0f;
*p++ = c;
gdb_rxsz -= 2;
gdb_rxp += 2;
}
kdb_cpu_sync_icache(addr, size);
}
(void)kdb_jmpbuf(prev);
return ((ret == 0) ? 1 : 0);
}
int
gdb_rx_varhex(uintmax_t *vp)
{
uintmax_t v;
int c, neg;
c = gdb_rx_char();
neg = (c == '-') ? 1 : 0;
if (neg == 1)
c = gdb_rx_char();
if (!isxdigit(c)) {
gdb_rxp -= ((c == -1) ? 0 : 1) + neg;
gdb_rxsz += ((c == -1) ? 0 : 1) + neg;
return (-1);
}
v = 0;
do {
v <<= 4;
v += C2N(c);
c = gdb_rx_char();
} while (isxdigit(c));
if (c != -1) {
gdb_rxp--;
gdb_rxsz++;
}
*vp = (neg) ? -v : v;
return (0);
}
/*
* Function to build and send a package.
*/
void
gdb_tx_begin(char tp)
{
gdb_txp = gdb_txbuf;
if (tp != '\0')
gdb_tx_char(tp);
}
int
gdb_tx_end(void)
{
const char *p;
int runlen;
unsigned char c, cksum;
do {
gdb_cur->gdb_putc('$');
cksum = 0;
p = gdb_txbuf;
while (p < gdb_txp) {
/* Send a character and start run-length encoding. */
c = *p++;
gdb_cur->gdb_putc(c);
cksum += c;
runlen = 0;
/* Determine run-length and update checksum. */
while (p < gdb_txp && *p == c) {
runlen++;
p++;
}
/* Emit the run-length encoded string. */
while (runlen >= 97) {
gdb_cur->gdb_putc('*');
cksum += '*';
gdb_cur->gdb_putc(97+29);
cksum += 97+29;
runlen -= 97;
if (runlen > 0) {
gdb_cur->gdb_putc(c);
cksum += c;
runlen--;
}
}
if (runlen == 1) {
gdb_cur->gdb_putc(c);
cksum += c;
runlen--;
}
if (runlen == 0)
continue;
/* Don't emit '$', '#', '+' or '-'. */
if (runlen == 7) {
gdb_cur->gdb_putc(c);
cksum += c;
runlen--;
}
if (runlen == 6 || runlen == 14 || runlen == 16) {
gdb_cur->gdb_putc(c);
cksum += c;
runlen--;
}
gdb_cur->gdb_putc('*');
cksum += '*';
gdb_cur->gdb_putc(runlen+29);
cksum += runlen+29;
}
gdb_cur->gdb_putc('#');
c = cksum >> 4;
gdb_cur->gdb_putc(N2C(c));
c = cksum & 0x0f;
gdb_cur->gdb_putc(N2C(c));
c = gdb_getc();
} while (c != '+');
return (0);
}
int
gdb_tx_mem(const unsigned char *addr, size_t size)
{
void *prev;
jmp_buf jb;
int ret;
prev = kdb_jmpbuf(jb);
ret = setjmp(jb);
if (ret == 0) {
while (size-- > 0) {
*gdb_txp++ = N2C(*addr >> 4);
*gdb_txp++ = N2C(*addr & 0x0f);
addr++;
}
}
(void)kdb_jmpbuf(prev);
return ((ret == 0) ? 1 : 0);
}
void
gdb_tx_reg(int regnum)
{
unsigned char *regp;
size_t regsz;
regp = gdb_cpu_getreg(regnum, &regsz);
if (regp == NULL) {
/* Register unavailable. */
while (regsz--) {
gdb_tx_char('x');
gdb_tx_char('x');
}
} else
gdb_tx_mem(regp, regsz);
}
Index: projects/altix/sys/geom/part/g_part_pc98.c
===================================================================
--- projects/altix/sys/geom/part/g_part_pc98.c (revision 218875)
+++ projects/altix/sys/geom/part/g_part_pc98.c (revision 218876)
@@ -1,579 +1,605 @@
/*-
* Copyright (c) 2008 Marcel Moolenaar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bio.h>
#include <sys/diskpc98.h>
#include <sys/endian.h>
#include <sys/kernel.h>
#include <sys/kobj.h>
#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/queue.h>
#include <sys/sbuf.h>
#include <sys/systm.h>
#include <geom/geom.h>
#include <geom/part/g_part.h>
#include "g_part_if.h"
#define SECSIZE 512
#define MENUSIZE 7168
#define BOOTSIZE 8192
struct g_part_pc98_table {
struct g_part_table base;
u_char boot[SECSIZE];
u_char table[SECSIZE];
u_char menu[MENUSIZE];
};
struct g_part_pc98_entry {
struct g_part_entry base;
struct pc98_partition ent;
};
static int g_part_pc98_add(struct g_part_table *, struct g_part_entry *,
struct g_part_parms *);
static int g_part_pc98_bootcode(struct g_part_table *, struct g_part_parms *);
static int g_part_pc98_create(struct g_part_table *, struct g_part_parms *);
static int g_part_pc98_destroy(struct g_part_table *, struct g_part_parms *);
static void g_part_pc98_dumpconf(struct g_part_table *, struct g_part_entry *,
struct sbuf *, const char *);
static int g_part_pc98_dumpto(struct g_part_table *, struct g_part_entry *);
static int g_part_pc98_modify(struct g_part_table *, struct g_part_entry *,
struct g_part_parms *);
static const char *g_part_pc98_name(struct g_part_table *, struct g_part_entry *,
char *, size_t);
static int g_part_pc98_probe(struct g_part_table *, struct g_consumer *);
static int g_part_pc98_read(struct g_part_table *, struct g_consumer *);
static int g_part_pc98_setunset(struct g_part_table *, struct g_part_entry *,
const char *, unsigned int);
static const char *g_part_pc98_type(struct g_part_table *,
struct g_part_entry *, char *, size_t);
static int g_part_pc98_write(struct g_part_table *, struct g_consumer *);
static int g_part_pc98_resize(struct g_part_table *, struct g_part_entry *,
struct g_part_parms *);
static kobj_method_t g_part_pc98_methods[] = {
KOBJMETHOD(g_part_add, g_part_pc98_add),
KOBJMETHOD(g_part_bootcode, g_part_pc98_bootcode),
KOBJMETHOD(g_part_create, g_part_pc98_create),
KOBJMETHOD(g_part_destroy, g_part_pc98_destroy),
KOBJMETHOD(g_part_dumpconf, g_part_pc98_dumpconf),
KOBJMETHOD(g_part_dumpto, g_part_pc98_dumpto),
KOBJMETHOD(g_part_modify, g_part_pc98_modify),
KOBJMETHOD(g_part_resize, g_part_pc98_resize),
KOBJMETHOD(g_part_name, g_part_pc98_name),
KOBJMETHOD(g_part_probe, g_part_pc98_probe),
KOBJMETHOD(g_part_read, g_part_pc98_read),
KOBJMETHOD(g_part_setunset, g_part_pc98_setunset),
KOBJMETHOD(g_part_type, g_part_pc98_type),
KOBJMETHOD(g_part_write, g_part_pc98_write),
{ 0, 0 }
};
static struct g_part_scheme g_part_pc98_scheme = {
"PC98",
g_part_pc98_methods,
sizeof(struct g_part_pc98_table),
.gps_entrysz = sizeof(struct g_part_pc98_entry),
.gps_minent = NDOSPART,
.gps_maxent = NDOSPART,
.gps_bootcodesz = BOOTSIZE,
};
G_PART_SCHEME_DECLARE(g_part_pc98);
static int
pc98_parse_type(const char *type, u_char *dp_mid, u_char *dp_sid)
{
const char *alias;
char *endp;
long lt;
if (type[0] == '!') {
lt = strtol(type + 1, &endp, 0);
if (type[1] == '\0' || *endp != '\0' || lt <= 0 ||
lt >= 65536)
return (EINVAL);
/* Make sure the active and bootable flags aren't set. */
if (lt & ((PC98_SID_ACTIVE << 8) | PC98_MID_BOOTABLE))
return (ENOATTR);
*dp_mid = (*dp_mid & PC98_MID_BOOTABLE) | (u_char)lt;
*dp_sid = (*dp_sid & PC98_SID_ACTIVE) | (u_char)(lt >> 8);
return (0);
}
alias = g_part_alias_name(G_PART_ALIAS_FREEBSD);
if (!strcasecmp(type, alias)) {
*dp_mid = (*dp_mid & PC98_MID_BOOTABLE) | PC98_MID_386BSD;
*dp_sid = (*dp_sid & PC98_SID_ACTIVE) | PC98_SID_386BSD;
return (0);
}
return (EINVAL);
}
+static int
+pc98_set_slicename(const char *label, u_char *dp_name)
+{
+ int len;
+
+ len = strlen(label);
+ if (len > sizeof(((struct pc98_partition *)NULL)->dp_name))
+ return (EINVAL);
+ bzero(dp_name, sizeof(((struct pc98_partition *)NULL)->dp_name));
+ strncpy(dp_name, label, len);
+
+ return (0);
+}
+
static void
pc98_set_chs(struct g_part_table *table, uint32_t lba, u_short *cylp,
u_char *hdp, u_char *secp)
{
uint32_t cyl, hd, sec;
sec = lba % table->gpt_sectors + 1;
lba /= table->gpt_sectors;
hd = lba % table->gpt_heads;
lba /= table->gpt_heads;
cyl = lba;
*cylp = htole16(cyl);
*hdp = hd;
*secp = sec;
}
static int
g_part_pc98_add(struct g_part_table *basetable, struct g_part_entry *baseentry,
struct g_part_parms *gpp)
{
struct g_part_pc98_entry *entry;
struct g_part_pc98_table *table;
uint32_t cyl, start, size;
+ int error;
- if (gpp->gpp_parms & G_PART_PARM_LABEL)
- return (EINVAL);
-
cyl = basetable->gpt_heads * basetable->gpt_sectors;
entry = (struct g_part_pc98_entry *)baseentry;
table = (struct g_part_pc98_table *)basetable;
start = gpp->gpp_start;
size = gpp->gpp_size;
if (size < cyl)
return (EINVAL);
if (start % cyl) {
size = size - cyl + (start % cyl);
start = start - (start % cyl) + cyl;
}
if (size % cyl)
size = size - (size % cyl);
if (size < cyl)
return (EINVAL);
if (baseentry->gpe_deleted)
bzero(&entry->ent, sizeof(entry->ent));
else
entry->ent.dp_mid = entry->ent.dp_sid = 0;
KASSERT(baseentry->gpe_start <= start, (__func__));
KASSERT(baseentry->gpe_end >= start + size - 1, (__func__));
baseentry->gpe_start = start;
baseentry->gpe_end = start + size - 1;
pc98_set_chs(basetable, baseentry->gpe_start, &entry->ent.dp_scyl,
&entry->ent.dp_shd, &entry->ent.dp_ssect);
pc98_set_chs(basetable, baseentry->gpe_end, &entry->ent.dp_ecyl,
&entry->ent.dp_ehd, &entry->ent.dp_esect);
- return (pc98_parse_type(gpp->gpp_type, &entry->ent.dp_mid,
- &entry->ent.dp_sid));
+
+ error = pc98_parse_type(gpp->gpp_type, &entry->ent.dp_mid,
+ &entry->ent.dp_sid);
+ if (error)
+ return (error);
+
+ if (gpp->gpp_parms & G_PART_PARM_LABEL)
+ return (pc98_set_slicename(gpp->gpp_label, entry->ent.dp_name));
+
+ return (0);
}
static int
g_part_pc98_bootcode(struct g_part_table *basetable, struct g_part_parms *gpp)
{
struct g_part_pc98_table *table;
const u_char *codeptr;
if (gpp->gpp_codesize != BOOTSIZE)
return (EINVAL);
table = (struct g_part_pc98_table *)basetable;
codeptr = gpp->gpp_codeptr;
bcopy(codeptr, table->boot, SECSIZE);
bcopy(codeptr + SECSIZE*2, table->menu, MENUSIZE);
return (0);
}
static int
g_part_pc98_create(struct g_part_table *basetable, struct g_part_parms *gpp)
{
struct g_consumer *cp;
struct g_provider *pp;
struct g_part_pc98_table *table;
uint32_t cyl, msize;
pp = gpp->gpp_provider;
cp = LIST_FIRST(&pp->consumers);
- if (pp->sectorsize < SECSIZE || pp->mediasize < 2 * SECSIZE)
+ if (pp->sectorsize < SECSIZE || pp->mediasize < BOOTSIZE)
return (ENOSPC);
if (pp->sectorsize > SECSIZE)
return (ENXIO);
cyl = basetable->gpt_heads * basetable->gpt_sectors;
msize = MIN(pp->mediasize / SECSIZE, 0xffffffff);
basetable->gpt_first = cyl;
basetable->gpt_last = msize - (msize % cyl) - 1;
table = (struct g_part_pc98_table *)basetable;
le16enc(table->boot + DOSMAGICOFFSET, DOSMAGIC);
return (0);
}
static int
g_part_pc98_destroy(struct g_part_table *basetable, struct g_part_parms *gpp)
{
/* Wipe the first two sectors to clear the partitioning. */
basetable->gpt_smhead |= 3;
return (0);
}
static void
g_part_pc98_dumpconf(struct g_part_table *table,
struct g_part_entry *baseentry, struct sbuf *sb, const char *indent)
{
struct g_part_pc98_entry *entry;
char name[sizeof(entry->ent.dp_name) + 1];
u_int type;
entry = (struct g_part_pc98_entry *)baseentry;
if (entry == NULL) {
/* confxml: scheme information */
return;
}
type = entry->ent.dp_mid + (entry->ent.dp_sid << 8);
strncpy(name, entry->ent.dp_name, sizeof(name) - 1);
name[sizeof(name) - 1] = '\0';
if (indent == NULL) {
/* conftxt: libdisk compatibility */
sbuf_printf(sb, " xs PC98 xt %u sn %s", type, name);
} else {
/* confxml: partition entry information */
sbuf_printf(sb, "%s<label>%s</label>\n", indent, name);
if (entry->ent.dp_mid & PC98_MID_BOOTABLE)
sbuf_printf(sb, "%s<attrib>bootable</attrib>\n",
indent);
if (entry->ent.dp_sid & PC98_SID_ACTIVE)
sbuf_printf(sb, "%s<attrib>active</attrib>\n", indent);
sbuf_printf(sb, "%s<rawtype>%u</rawtype>\n", indent,
type & 0x7f7f);
}
}
static int
g_part_pc98_dumpto(struct g_part_table *table, struct g_part_entry *baseentry)
{
struct g_part_pc98_entry *entry;
/* Allow dumping to a FreeBSD partition only. */
entry = (struct g_part_pc98_entry *)baseentry;
return (((entry->ent.dp_mid & PC98_MID_MASK) == PC98_MID_386BSD &&
(entry->ent.dp_sid & PC98_SID_MASK) == PC98_SID_386BSD) ? 1 : 0);
}
static int
g_part_pc98_modify(struct g_part_table *basetable,
struct g_part_entry *baseentry, struct g_part_parms *gpp)
{
struct g_part_pc98_entry *entry;
+ int error;
+ entry = (struct g_part_pc98_entry *)baseentry;
+
+ if (gpp->gpp_parms & G_PART_PARM_TYPE) {
+ error = pc98_parse_type(gpp->gpp_type, &entry->ent.dp_mid,
+ &entry->ent.dp_sid);
+ if (error)
+ return (error);
+ }
+
if (gpp->gpp_parms & G_PART_PARM_LABEL)
- return (EINVAL);
+ return (pc98_set_slicename(gpp->gpp_label, entry->ent.dp_name));
- entry = (struct g_part_pc98_entry *)baseentry;
- if (gpp->gpp_parms & G_PART_PARM_TYPE)
- return (pc98_parse_type(gpp->gpp_type, &entry->ent.dp_mid,
- &entry->ent.dp_sid));
return (0);
}
static int
g_part_pc98_resize(struct g_part_table *basetable,
struct g_part_entry *baseentry, struct g_part_parms *gpp)
{
struct g_part_pc98_entry *entry;
uint32_t size, cyl;
cyl = basetable->gpt_heads * basetable->gpt_sectors;
size = gpp->gpp_size;
if (size < cyl)
return (EINVAL);
if (size % cyl)
size = size - (size % cyl);
if (size < cyl)
return (EINVAL);
entry = (struct g_part_pc98_entry *)baseentry;
baseentry->gpe_end = baseentry->gpe_start + size - 1;
pc98_set_chs(basetable, baseentry->gpe_end, &entry->ent.dp_ecyl,
&entry->ent.dp_ehd, &entry->ent.dp_esect);
return (0);
}
static const char *
g_part_pc98_name(struct g_part_table *table, struct g_part_entry *baseentry,
char *buf, size_t bufsz)
{
snprintf(buf, bufsz, "s%d", baseentry->gpe_index);
return (buf);
}
static int
g_part_pc98_probe(struct g_part_table *table, struct g_consumer *cp)
{
struct g_provider *pp;
u_char *buf, *p;
int error, index, res, sum;
uint16_t magic, ecyl, scyl;
pp = cp->provider;
/* Sanity-check the provider. */
if (pp->sectorsize < SECSIZE || pp->mediasize < BOOTSIZE)
return (ENOSPC);
if (pp->sectorsize > SECSIZE)
return (ENXIO);
/* Check that there's a PC98 partition table. */
buf = g_read_data(cp, 0L, 2 * SECSIZE, &error);
if (buf == NULL)
return (error);
/* We goto out on mismatch. */
res = ENXIO;
magic = le16dec(buf + DOSMAGICOFFSET);
if (magic != DOSMAGIC)
goto out;
sum = 0;
for (index = SECSIZE; index < 2 * SECSIZE; index++)
sum += buf[index];
if (sum == 0) {
res = G_PART_PROBE_PRI_LOW;
goto out;
}
for (index = 0; index < NDOSPART; index++) {
p = buf + SECSIZE + index * DOSPARTSIZE;
if (p[0] == 0 || p[1] == 0) /* !dp_mid || !dp_sid */
continue;
scyl = le16dec(p + 10);
ecyl = le16dec(p + 14);
if (scyl == 0 || ecyl == 0)
goto out;
if (p[8] == p[12] && /* dp_ssect == dp_esect */
p[9] == p[13] && /* dp_shd == dp_ehd */
scyl == ecyl)
goto out;
}
res = G_PART_PROBE_PRI_HIGH;
out:
g_free(buf);
return (res);
}
static int
g_part_pc98_read(struct g_part_table *basetable, struct g_consumer *cp)
{
struct pc98_partition ent;
struct g_provider *pp;
struct g_part_pc98_table *table;
struct g_part_pc98_entry *entry;
u_char *buf, *p;
off_t msize;
off_t start, end;
u_int cyl;
int error, index;
pp = cp->provider;
table = (struct g_part_pc98_table *)basetable;
msize = pp->mediasize / SECSIZE;
buf = g_read_data(cp, 0L, BOOTSIZE, &error);
if (buf == NULL)
return (error);
cyl = basetable->gpt_heads * basetable->gpt_sectors;
bcopy(buf, table->boot, sizeof(table->boot));
bcopy(buf + SECSIZE, table->table, sizeof(table->table));
bcopy(buf + SECSIZE*2, table->menu, sizeof(table->menu));
for (index = NDOSPART - 1; index >= 0; index--) {
p = buf + SECSIZE + index * DOSPARTSIZE;
ent.dp_mid = p[0];
ent.dp_sid = p[1];
ent.dp_dum1 = p[2];
ent.dp_dum2 = p[3];
ent.dp_ipl_sct = p[4];
ent.dp_ipl_head = p[5];
ent.dp_ipl_cyl = le16dec(p + 6);
ent.dp_ssect = p[8];
ent.dp_shd = p[9];
ent.dp_scyl = le16dec(p + 10);
ent.dp_esect = p[12];
ent.dp_ehd = p[13];
ent.dp_ecyl = le16dec(p + 14);
bcopy(p + 16, ent.dp_name, sizeof(ent.dp_name));
if (ent.dp_sid == 0)
continue;
start = ent.dp_scyl * cyl;
end = (ent.dp_ecyl + 1) * cyl - 1;
entry = (struct g_part_pc98_entry *)g_part_new_entry(basetable,
index + 1, start, end);
entry->ent = ent;
}
basetable->gpt_entries = NDOSPART;
basetable->gpt_first = cyl;
basetable->gpt_last = msize - (msize % cyl) - 1;
g_free(buf);
return (0);
}
static int
g_part_pc98_setunset(struct g_part_table *table, struct g_part_entry *baseentry,
const char *attrib, unsigned int set)
{
struct g_part_entry *iter;
struct g_part_pc98_entry *entry;
int changed, mid, sid;
mid = sid = 0;
if (strcasecmp(attrib, "active") == 0)
sid = 1;
else if (strcasecmp(attrib, "bootable") == 0)
mid = 1;
if (mid == 0 && sid == 0)
return (EINVAL);
LIST_FOREACH(iter, &table->gpt_entry, gpe_entry) {
if (iter->gpe_deleted)
continue;
if (iter != baseentry)
continue;
changed = 0;
entry = (struct g_part_pc98_entry *)iter;
if (set) {
if (mid && !(entry->ent.dp_mid & PC98_MID_BOOTABLE)) {
entry->ent.dp_mid |= PC98_MID_BOOTABLE;
changed = 1;
}
if (sid && !(entry->ent.dp_sid & PC98_SID_ACTIVE)) {
entry->ent.dp_sid |= PC98_SID_ACTIVE;
changed = 1;
}
} else {
if (mid && (entry->ent.dp_mid & PC98_MID_BOOTABLE)) {
entry->ent.dp_mid &= ~PC98_MID_BOOTABLE;
changed = 1;
}
if (sid && (entry->ent.dp_sid & PC98_SID_ACTIVE)) {
entry->ent.dp_sid &= ~PC98_SID_ACTIVE;
changed = 1;
}
}
if (changed && !iter->gpe_created)
iter->gpe_modified = 1;
}
return (0);
}
static const char *
g_part_pc98_type(struct g_part_table *basetable, struct g_part_entry *baseentry,
char *buf, size_t bufsz)
{
struct g_part_pc98_entry *entry;
u_int type;
entry = (struct g_part_pc98_entry *)baseentry;
type = (entry->ent.dp_mid & PC98_MID_MASK) |
((entry->ent.dp_sid & PC98_SID_MASK) << 8);
if (type == (PC98_MID_386BSD | (PC98_SID_386BSD << 8)))
return (g_part_alias_name(G_PART_ALIAS_FREEBSD));
snprintf(buf, bufsz, "!%d", type);
return (buf);
}
static int
g_part_pc98_write(struct g_part_table *basetable, struct g_consumer *cp)
{
struct g_part_entry *baseentry;
struct g_part_pc98_entry *entry;
struct g_part_pc98_table *table;
u_char *p;
int error, index;
table = (struct g_part_pc98_table *)basetable;
baseentry = LIST_FIRST(&basetable->gpt_entry);
for (index = 1; index <= basetable->gpt_entries; index++) {
p = table->table + (index - 1) * DOSPARTSIZE;
entry = (baseentry != NULL && index == baseentry->gpe_index)
? (struct g_part_pc98_entry *)baseentry : NULL;
if (entry != NULL && !baseentry->gpe_deleted) {
p[0] = entry->ent.dp_mid;
p[1] = entry->ent.dp_sid;
p[2] = entry->ent.dp_dum1;
p[3] = entry->ent.dp_dum2;
p[4] = entry->ent.dp_ipl_sct;
p[5] = entry->ent.dp_ipl_head;
le16enc(p + 6, entry->ent.dp_ipl_cyl);
p[8] = entry->ent.dp_ssect;
p[9] = entry->ent.dp_shd;
le16enc(p + 10, entry->ent.dp_scyl);
p[12] = entry->ent.dp_esect;
p[13] = entry->ent.dp_ehd;
le16enc(p + 14, entry->ent.dp_ecyl);
bcopy(entry->ent.dp_name, p + 16,
sizeof(entry->ent.dp_name));
} else
bzero(p, DOSPARTSIZE);
if (entry != NULL)
baseentry = LIST_NEXT(baseentry, gpe_entry);
}
error = g_write_data(cp, 0, table->boot, SECSIZE);
if (!error)
error = g_write_data(cp, SECSIZE, table->table, SECSIZE);
if (!error)
error = g_write_data(cp, SECSIZE*2, table->menu, MENUSIZE);
return (error);
}
Index: projects/altix/sys/kern/subr_busdma.c
===================================================================
--- projects/altix/sys/kern/subr_busdma.c (revision 218875)
+++ projects/altix/sys/kern/subr_busdma.c (revision 218876)
Property changes on: projects/altix/sys/kern/subr_busdma.c
___________________________________________________________________
Modified: svn:mergeinfo
## -0,0 +0,1 ##
Merged /head/sys/kern/subr_busdma.c:r218817-218875
Index: projects/altix/sys/kern/subr_kdb.c
===================================================================
--- projects/altix/sys/kern/subr_kdb.c (revision 218875)
+++ projects/altix/sys/kern/subr_kdb.c (revision 218876)
@@ -1,558 +1,552 @@
/*-
* Copyright (c) 2004 The FreeBSD Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_kdb.h"
#include "opt_stack.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kdb.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/pcpu.h>
#include <sys/proc.h>
+#include <sys/sbuf.h>
#include <sys/smp.h>
#include <sys/stack.h>
#include <sys/sysctl.h>
#include <machine/kdb.h>
#include <machine/pcb.h>
#ifdef SMP
#include <machine/smp.h>
#endif
int kdb_active = 0;
static void *kdb_jmpbufp = NULL;
struct kdb_dbbe *kdb_dbbe = NULL;
static struct pcb kdb_pcb;
struct pcb *kdb_thrctx = NULL;
struct thread *kdb_thread = NULL;
struct trapframe *kdb_frame = NULL;
KDB_BACKEND(null, NULL, NULL, NULL);
SET_DECLARE(kdb_dbbe_set, struct kdb_dbbe);
static int kdb_sysctl_available(SYSCTL_HANDLER_ARGS);
static int kdb_sysctl_current(SYSCTL_HANDLER_ARGS);
static int kdb_sysctl_enter(SYSCTL_HANDLER_ARGS);
static int kdb_sysctl_panic(SYSCTL_HANDLER_ARGS);
static int kdb_sysctl_trap(SYSCTL_HANDLER_ARGS);
static int kdb_sysctl_trap_code(SYSCTL_HANDLER_ARGS);
SYSCTL_NODE(_debug, OID_AUTO, kdb, CTLFLAG_RW, NULL, "KDB nodes");
SYSCTL_PROC(_debug_kdb, OID_AUTO, available, CTLTYPE_STRING | CTLFLAG_RD, NULL,
0, kdb_sysctl_available, "A", "list of available KDB backends");
SYSCTL_PROC(_debug_kdb, OID_AUTO, current, CTLTYPE_STRING | CTLFLAG_RW, NULL,
0, kdb_sysctl_current, "A", "currently selected KDB backend");
SYSCTL_PROC(_debug_kdb, OID_AUTO, enter, CTLTYPE_INT | CTLFLAG_RW, NULL, 0,
kdb_sysctl_enter, "I", "set to enter the debugger");
SYSCTL_PROC(_debug_kdb, OID_AUTO, panic, CTLTYPE_INT | CTLFLAG_RW, NULL, 0,
kdb_sysctl_panic, "I", "set to panic the kernel");
SYSCTL_PROC(_debug_kdb, OID_AUTO, trap, CTLTYPE_INT | CTLFLAG_RW, NULL, 0,
kdb_sysctl_trap, "I", "set to cause a page fault via data access");
SYSCTL_PROC(_debug_kdb, OID_AUTO, trap_code, CTLTYPE_INT | CTLFLAG_RW, NULL, 0,
kdb_sysctl_trap_code, "I", "set to cause a page fault via code access");
/*
* Flag indicating whether or not to IPI the other CPUs to stop them on
* entering the debugger. Sometimes, this will result in a deadlock as
* stop_cpus() waits for the other cpus to stop, so we allow it to be
* disabled. In order to maximize the chances of success, use a hard
* stop for that.
*/
#ifdef SMP
static int kdb_stop_cpus = 1;
SYSCTL_INT(_debug_kdb, OID_AUTO, stop_cpus, CTLFLAG_RW | CTLFLAG_TUN,
&kdb_stop_cpus, 0, "stop other CPUs when entering the debugger");
TUNABLE_INT("debug.kdb.stop_cpus", &kdb_stop_cpus);
#endif
/*
* Flag to indicate to debuggers why the debugger was entered.
*/
const char * volatile kdb_why = KDB_WHY_UNSET;
static int
kdb_sysctl_available(SYSCTL_HANDLER_ARGS)
{
- struct kdb_dbbe *be, **iter;
- char *avail, *p;
- ssize_t len, sz;
+ struct kdb_dbbe **iter;
+ struct sbuf sbuf;
int error;
- sz = 0;
+ sbuf_new_for_sysctl(&sbuf, NULL, 64, req);
SET_FOREACH(iter, kdb_dbbe_set) {
- be = *iter;
- if (be->dbbe_active == 0)
- sz += strlen(be->dbbe_name) + 1;
+ if ((*iter)->dbbe_active == 0)
+ sbuf_printf(&sbuf, "%s ", (*iter)->dbbe_name);
}
- sz++;
- avail = malloc(sz, M_TEMP, M_WAITOK);
- p = avail;
- *p = '\0';
-
- SET_FOREACH(iter, kdb_dbbe_set) {
- be = *iter;
- if (be->dbbe_active == 0) {
- len = snprintf(p, sz, "%s ", be->dbbe_name);
- p += len;
- sz -= len;
- }
- }
- KASSERT(sz >= 0, ("%s", __func__));
- error = sysctl_handle_string(oidp, avail, 0, req);
- free(avail, M_TEMP);
+ error = sbuf_finish(&sbuf);
+ sbuf_delete(&sbuf);
return (error);
}
static int
kdb_sysctl_current(SYSCTL_HANDLER_ARGS)
{
char buf[16];
int error;
- if (kdb_dbbe != NULL) {
- strncpy(buf, kdb_dbbe->dbbe_name, sizeof(buf));
- buf[sizeof(buf) - 1] = '\0';
- } else
+ if (kdb_dbbe != NULL)
+ strlcpy(buf, kdb_dbbe->dbbe_name, sizeof(buf));
+ else
*buf = '\0';
error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
if (error != 0 || req->newptr == NULL)
return (error);
if (kdb_active)
return (EBUSY);
return (kdb_dbbe_select(buf));
}
static int
kdb_sysctl_enter(SYSCTL_HANDLER_ARGS)
{
int error, i;
error = sysctl_wire_old_buffer(req, sizeof(int));
if (error == 0) {
i = 0;
error = sysctl_handle_int(oidp, &i, 0, req);
}
if (error != 0 || req->newptr == NULL)
return (error);
if (kdb_active)
return (EBUSY);
kdb_enter(KDB_WHY_SYSCTL, "sysctl debug.kdb.enter");
return (0);
}
static int
kdb_sysctl_panic(SYSCTL_HANDLER_ARGS)
{
int error, i;
error = sysctl_wire_old_buffer(req, sizeof(int));
if (error == 0) {
i = 0;
error = sysctl_handle_int(oidp, &i, 0, req);
}
if (error != 0 || req->newptr == NULL)
return (error);
panic("kdb_sysctl_panic");
return (0);
}
static int
kdb_sysctl_trap(SYSCTL_HANDLER_ARGS)
{
int error, i;
int *addr = (int *)0x10;
error = sysctl_wire_old_buffer(req, sizeof(int));
if (error == 0) {
i = 0;
error = sysctl_handle_int(oidp, &i, 0, req);
}
if (error != 0 || req->newptr == NULL)
return (error);
return (*addr);
}
static int
kdb_sysctl_trap_code(SYSCTL_HANDLER_ARGS)
{
int error, i;
void (*fp)(u_int, u_int, u_int) = (void *)0xdeadc0de;
error = sysctl_wire_old_buffer(req, sizeof(int));
if (error == 0) {
i = 0;
error = sysctl_handle_int(oidp, &i, 0, req);
}
if (error != 0 || req->newptr == NULL)
return (error);
(*fp)(0x11111111, 0x22222222, 0x33333333);
return (0);
}
void
kdb_panic(const char *msg)
{
#ifdef SMP
stop_cpus_hard(PCPU_GET(other_cpus));
#endif
printf("KDB: panic\n");
panic("%s", msg);
}
void
kdb_reboot(void)
{
printf("KDB: reboot requested\n");
shutdown_nice(0);
}
/*
* Solaris implements a new BREAK which is initiated by a character sequence
* CR ~ ^b which is similar to a familiar pattern used on Sun servers by the
* Remote Console.
*
* Note that this function may be called from almost anywhere, with interrupts
* disabled and with unknown locks held, so it must not access data other than
* its arguments. Its up to the caller to ensure that the state variable is
* consistent.
*/
#define KEY_CR 13 /* CR '\r' */
#define KEY_TILDE 126 /* ~ */
#define KEY_CRTLB 2 /* ^B */
#define KEY_CRTLP 16 /* ^P */
#define KEY_CRTLR 18 /* ^R */
int
kdb_alt_break(int key, int *state)
{
int brk;
brk = 0;
switch (*state) {
case 0:
if (key == KEY_CR)
*state = 1;
break;
case 1:
if (key == KEY_TILDE)
*state = 2;
break;
case 2:
if (key == KEY_CRTLB)
brk = KDB_REQ_DEBUGGER;
else if (key == KEY_CRTLP)
brk = KDB_REQ_PANIC;
else if (key == KEY_CRTLR)
brk = KDB_REQ_REBOOT;
*state = 0;
}
return (brk);
}
/*
* Print a backtrace of the calling thread. The backtrace is generated by
* the selected debugger, provided it supports backtraces. If no debugger
* is selected or the current debugger does not support backtraces, this
* function silently returns.
*/
void
kdb_backtrace(void)
{
if (kdb_dbbe != NULL && kdb_dbbe->dbbe_trace != NULL) {
printf("KDB: stack backtrace:\n");
kdb_dbbe->dbbe_trace();
}
#ifdef STACK
else {
struct stack st;
printf("KDB: stack backtrace:\n");
stack_save(&st);
stack_print_ddb(&st);
}
#endif
}
/*
* Set/change the current backend.
*/
int
kdb_dbbe_select(const char *name)
{
struct kdb_dbbe *be, **iter;
SET_FOREACH(iter, kdb_dbbe_set) {
be = *iter;
if (be->dbbe_active == 0 && strcmp(be->dbbe_name, name) == 0) {
kdb_dbbe = be;
return (0);
}
}
return (EINVAL);
}
/*
* Enter the currently selected debugger. If a message has been provided,
* it is printed first. If the debugger does not support the enter method,
* it is entered by using breakpoint(), which enters the debugger through
* kdb_trap(). The 'why' argument will contain a more mechanically usable
* string than 'msg', and is relied upon by DDB scripting to identify the
* reason for entering the debugger so that the right script can be run.
*/
void
kdb_enter(const char *why, const char *msg)
{
if (kdb_dbbe != NULL && kdb_active == 0) {
if (msg != NULL)
printf("KDB: enter: %s\n", msg);
kdb_why = why;
breakpoint();
kdb_why = KDB_WHY_UNSET;
}
}
/*
* Initialize the kernel debugger interface.
*/
void
kdb_init(void)
{
struct kdb_dbbe *be, **iter;
int cur_pri, pri;
kdb_active = 0;
kdb_dbbe = NULL;
cur_pri = -1;
SET_FOREACH(iter, kdb_dbbe_set) {
be = *iter;
pri = (be->dbbe_init != NULL) ? be->dbbe_init() : -1;
be->dbbe_active = (pri >= 0) ? 0 : -1;
if (pri > cur_pri) {
cur_pri = pri;
kdb_dbbe = be;
}
}
if (kdb_dbbe != NULL) {
printf("KDB: debugger backends:");
SET_FOREACH(iter, kdb_dbbe_set) {
be = *iter;
if (be->dbbe_active == 0)
printf(" %s", be->dbbe_name);
}
printf("\n");
printf("KDB: current backend: %s\n",
kdb_dbbe->dbbe_name);
}
}
/*
* Handle contexts.
*/
void *
kdb_jmpbuf(jmp_buf new)
{
void *old;
old = kdb_jmpbufp;
kdb_jmpbufp = new;
return (old);
}
void
kdb_reenter(void)
{
if (!kdb_active || kdb_jmpbufp == NULL)
return;
longjmp(kdb_jmpbufp, 1);
/* NOTREACHED */
}
/*
* Thread related support functions.
*/
struct pcb *
kdb_thr_ctx(struct thread *thr)
{
#if defined(SMP) && defined(KDB_STOPPEDPCB)
struct pcpu *pc;
#endif
if (thr == curthread)
return (&kdb_pcb);
#if defined(SMP) && defined(KDB_STOPPEDPCB)
SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
if (pc->pc_curthread == thr && (stopped_cpus & pc->pc_cpumask))
return (KDB_STOPPEDPCB(pc));
}
#endif
return (thr->td_pcb);
}
struct thread *
kdb_thr_first(void)
{
struct proc *p;
struct thread *thr;
p = LIST_FIRST(&allproc);
while (p != NULL) {
if (p->p_flag & P_INMEM) {
thr = FIRST_THREAD_IN_PROC(p);
if (thr != NULL)
return (thr);
}
p = LIST_NEXT(p, p_list);
}
return (NULL);
}
struct thread *
kdb_thr_from_pid(pid_t pid)
{
struct proc *p;
p = LIST_FIRST(&allproc);
while (p != NULL) {
if (p->p_flag & P_INMEM && p->p_pid == pid)
return (FIRST_THREAD_IN_PROC(p));
p = LIST_NEXT(p, p_list);
}
return (NULL);
}
struct thread *
kdb_thr_lookup(lwpid_t tid)
{
struct thread *thr;
thr = kdb_thr_first();
while (thr != NULL && thr->td_tid != tid)
thr = kdb_thr_next(thr);
return (thr);
}
struct thread *
kdb_thr_next(struct thread *thr)
{
struct proc *p;
p = thr->td_proc;
thr = TAILQ_NEXT(thr, td_plist);
do {
if (thr != NULL)
return (thr);
p = LIST_NEXT(p, p_list);
if (p != NULL && (p->p_flag & P_INMEM))
thr = FIRST_THREAD_IN_PROC(p);
} while (p != NULL);
return (NULL);
}
int
kdb_thr_select(struct thread *thr)
{
if (thr == NULL)
return (EINVAL);
kdb_thread = thr;
kdb_thrctx = kdb_thr_ctx(thr);
return (0);
}
/*
* Enter the debugger due to a trap.
*/
int
kdb_trap(int type, int code, struct trapframe *tf)
{
+ struct kdb_dbbe *be;
register_t intr;
#ifdef SMP
int did_stop_cpus;
#endif
int handled;
- if (kdb_dbbe == NULL || kdb_dbbe->dbbe_trap == NULL)
+ be = kdb_dbbe;
+ if (be == NULL || be->dbbe_trap == NULL)
return (0);
/* We reenter the debugger through kdb_reenter(). */
if (kdb_active)
return (0);
intr = intr_disable();
#ifdef SMP
if ((did_stop_cpus = kdb_stop_cpus) != 0)
stop_cpus_hard(PCPU_GET(other_cpus));
#endif
kdb_active++;
kdb_frame = tf;
/* Let MD code do its thing first... */
kdb_cpu_trap(type, code);
makectx(tf, &kdb_pcb);
kdb_thr_select(curthread);
- handled = kdb_dbbe->dbbe_trap(type, code);
+ for (;;) {
+ handled = be->dbbe_trap(type, code);
+ if (be == kdb_dbbe)
+ break;
+ be = kdb_dbbe;
+ if (be == NULL || be->dbbe_trap == NULL)
+ break;
+ printf("Switching to %s back-end\n", be->dbbe_name);
+ }
kdb_active--;
#ifdef SMP
if (did_stop_cpus)
restart_cpus(stopped_cpus);
#endif
intr_restore(intr);
return (handled);
}
Index: projects/altix/sys/kern/vfs_mount.c
===================================================================
--- projects/altix/sys/kern/vfs_mount.c (revision 218875)
+++ projects/altix/sys/kern/vfs_mount.c (revision 218876)
@@ -1,1973 +1,1976 @@
/*-
* Copyright (c) 1999-2004 Poul-Henning Kamp
* Copyright (c) 1999 Michael Smith
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/fcntl.h>
#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/libkern.h>
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/mutex.h>
#include <sys/namei.h>
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/filedesc.h>
#include <sys/reboot.h>
#include <sys/syscallsubr.h>
#include <sys/sysproto.h>
#include <sys/sx.h>
#include <sys/sysctl.h>
#include <sys/sysent.h>
#include <sys/systm.h>
#include <sys/vnode.h>
#include <vm/uma.h>
#include <geom/geom.h>
#include <machine/stdarg.h>
#include <security/audit/audit.h>
#include <security/mac/mac_framework.h>
#define VFS_MOUNTARG_SIZE_MAX (1024 * 64)
static int vfs_domount(struct thread *td, const char *fstype,
- char *fspath, int fsflags, void *fsdata);
+ char *fspath, int fsflags, struct vfsoptlist **optlist);
static void free_mntarg(struct mntarg *ma);
static int usermount = 0;
SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0,
"Unprivileged users may mount and unmount file systems");
MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount structure");
MALLOC_DEFINE(M_VNODE_MARKER, "vnodemarker", "vnode marker");
static uma_zone_t mount_zone;
/* List of mounted filesystems. */
struct mntlist mountlist = TAILQ_HEAD_INITIALIZER(mountlist);
/* For any iteration/modification of mountlist */
struct mtx mountlist_mtx;
MTX_SYSINIT(mountlist, &mountlist_mtx, "mountlist", MTX_DEF);
/*
* Global opts, taken by all filesystems
*/
static const char *global_opts[] = {
"errmsg",
"fstype",
"fspath",
"ro",
"rw",
"nosuid",
"noexec",
NULL
};
static int
mount_init(void *mem, int size, int flags)
{
struct mount *mp;
mp = (struct mount *)mem;
mtx_init(&mp->mnt_mtx, "struct mount mtx", NULL, MTX_DEF);
lockinit(&mp->mnt_explock, PVFS, "explock", 0, 0);
return (0);
}
static void
mount_fini(void *mem, int size)
{
struct mount *mp;
mp = (struct mount *)mem;
lockdestroy(&mp->mnt_explock);
mtx_destroy(&mp->mnt_mtx);
}
static void
vfs_mount_init(void *dummy __unused)
{
mount_zone = uma_zcreate("Mountpoints", sizeof(struct mount), NULL,
NULL, mount_init, mount_fini, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
}
SYSINIT(vfs_mount, SI_SUB_VFS, SI_ORDER_ANY, vfs_mount_init, NULL);
/*
* ---------------------------------------------------------------------
* Functions for building and sanitizing the mount options
*/
/* Remove one mount option. */
static void
vfs_freeopt(struct vfsoptlist *opts, struct vfsopt *opt)
{
TAILQ_REMOVE(opts, opt, link);
free(opt->name, M_MOUNT);
if (opt->value != NULL)
free(opt->value, M_MOUNT);
free(opt, M_MOUNT);
}
/* Release all resources related to the mount options. */
void
vfs_freeopts(struct vfsoptlist *opts)
{
struct vfsopt *opt;
while (!TAILQ_EMPTY(opts)) {
opt = TAILQ_FIRST(opts);
vfs_freeopt(opts, opt);
}
free(opts, M_MOUNT);
}
void
vfs_deleteopt(struct vfsoptlist *opts, const char *name)
{
struct vfsopt *opt, *temp;
if (opts == NULL)
return;
TAILQ_FOREACH_SAFE(opt, opts, link, temp) {
if (strcmp(opt->name, name) == 0)
vfs_freeopt(opts, opt);
}
}
/*
* Check if options are equal (with or without the "no" prefix).
*/
static int
vfs_equalopts(const char *opt1, const char *opt2)
{
char *p;
/* "opt" vs. "opt" or "noopt" vs. "noopt" */
if (strcmp(opt1, opt2) == 0)
return (1);
/* "noopt" vs. "opt" */
if (strncmp(opt1, "no", 2) == 0 && strcmp(opt1 + 2, opt2) == 0)
return (1);
/* "opt" vs. "noopt" */
if (strncmp(opt2, "no", 2) == 0 && strcmp(opt1, opt2 + 2) == 0)
return (1);
while ((p = strchr(opt1, '.')) != NULL &&
!strncmp(opt1, opt2, ++p - opt1)) {
opt2 += p - opt1;
opt1 = p;
/* "foo.noopt" vs. "foo.opt" */
if (strncmp(opt1, "no", 2) == 0 && strcmp(opt1 + 2, opt2) == 0)
return (1);
/* "foo.opt" vs. "foo.noopt" */
if (strncmp(opt2, "no", 2) == 0 && strcmp(opt1, opt2 + 2) == 0)
return (1);
}
return (0);
}
/*
* If a mount option is specified several times,
* (with or without the "no" prefix) only keep
* the last occurence of it.
*/
static void
vfs_sanitizeopts(struct vfsoptlist *opts)
{
struct vfsopt *opt, *opt2, *tmp;
TAILQ_FOREACH_REVERSE(opt, opts, vfsoptlist, link) {
opt2 = TAILQ_PREV(opt, vfsoptlist, link);
while (opt2 != NULL) {
if (vfs_equalopts(opt->name, opt2->name)) {
tmp = TAILQ_PREV(opt2, vfsoptlist, link);
vfs_freeopt(opts, opt2);
opt2 = tmp;
} else {
opt2 = TAILQ_PREV(opt2, vfsoptlist, link);
}
}
}
}
/*
* Build a linked list of mount options from a struct uio.
*/
int
vfs_buildopts(struct uio *auio, struct vfsoptlist **options)
{
struct vfsoptlist *opts;
struct vfsopt *opt;
size_t memused, namelen, optlen;
unsigned int i, iovcnt;
int error;
opts = malloc(sizeof(struct vfsoptlist), M_MOUNT, M_WAITOK);
TAILQ_INIT(opts);
memused = 0;
iovcnt = auio->uio_iovcnt;
for (i = 0; i < iovcnt; i += 2) {
namelen = auio->uio_iov[i].iov_len;
optlen = auio->uio_iov[i + 1].iov_len;
memused += sizeof(struct vfsopt) + optlen + namelen;
/*
* Avoid consuming too much memory, and attempts to overflow
* memused.
*/
if (memused > VFS_MOUNTARG_SIZE_MAX ||
optlen > VFS_MOUNTARG_SIZE_MAX ||
namelen > VFS_MOUNTARG_SIZE_MAX) {
error = EINVAL;
goto bad;
}
opt = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK);
opt->name = malloc(namelen, M_MOUNT, M_WAITOK);
opt->value = NULL;
opt->len = 0;
opt->pos = i / 2;
opt->seen = 0;
/*
* Do this early, so jumps to "bad" will free the current
* option.
*/
TAILQ_INSERT_TAIL(opts, opt, link);
if (auio->uio_segflg == UIO_SYSSPACE) {
bcopy(auio->uio_iov[i].iov_base, opt->name, namelen);
} else {
error = copyin(auio->uio_iov[i].iov_base, opt->name,
namelen);
if (error)
goto bad;
}
/* Ensure names are null-terminated strings. */
if (namelen == 0 || opt->name[namelen - 1] != '\0') {
error = EINVAL;
goto bad;
}
if (optlen != 0) {
opt->len = optlen;
opt->value = malloc(optlen, M_MOUNT, M_WAITOK);
if (auio->uio_segflg == UIO_SYSSPACE) {
bcopy(auio->uio_iov[i + 1].iov_base, opt->value,
optlen);
} else {
error = copyin(auio->uio_iov[i + 1].iov_base,
opt->value, optlen);
if (error)
goto bad;
}
}
}
vfs_sanitizeopts(opts);
*options = opts;
return (0);
bad:
vfs_freeopts(opts);
return (error);
}
/*
* Merge the old mount options with the new ones passed
* in the MNT_UPDATE case.
*
* XXX This function will keep a "nofoo" option in the
* new options if there is no matching "foo" option
* to be cancelled in the old options. This is a bug
* if the option's canonical name is "foo". E.g., "noro"
* shouldn't end up in the mount point's active options,
* but it can.
*/
static void
vfs_mergeopts(struct vfsoptlist *toopts, struct vfsoptlist *opts)
{
struct vfsopt *opt, *opt2, *new;
TAILQ_FOREACH(opt, opts, link) {
/*
* Check that this option hasn't been redefined
* nor cancelled with a "no" mount option.
*/
opt2 = TAILQ_FIRST(toopts);
while (opt2 != NULL) {
if (strcmp(opt2->name, opt->name) == 0)
goto next;
if (strncmp(opt2->name, "no", 2) == 0 &&
strcmp(opt2->name + 2, opt->name) == 0) {
vfs_freeopt(toopts, opt2);
goto next;
}
opt2 = TAILQ_NEXT(opt2, link);
}
/* We want this option, duplicate it. */
new = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK);
new->name = malloc(strlen(opt->name) + 1, M_MOUNT, M_WAITOK);
strcpy(new->name, opt->name);
if (opt->len != 0) {
new->value = malloc(opt->len, M_MOUNT, M_WAITOK);
bcopy(opt->value, new->value, opt->len);
} else {
new->value = NULL;
}
new->len = opt->len;
new->seen = opt->seen;
TAILQ_INSERT_TAIL(toopts, new, link);
next:
continue;
}
}
/*
* Mount a filesystem.
*/
int
nmount(td, uap)
struct thread *td;
struct nmount_args /* {
struct iovec *iovp;
unsigned int iovcnt;
int flags;
} */ *uap;
{
struct uio *auio;
int error;
u_int iovcnt;
AUDIT_ARG_FFLAGS(uap->flags);
CTR4(KTR_VFS, "%s: iovp %p with iovcnt %d and flags %d", __func__,
uap->iovp, uap->iovcnt, uap->flags);
/*
* Filter out MNT_ROOTFS. We do not want clients of nmount() in
* userspace to set this flag, but we must filter it out if we want
* MNT_UPDATE on the root file system to work.
* MNT_ROOTFS should only be set by the kernel when mounting its
* root file system.
*/
uap->flags &= ~MNT_ROOTFS;
iovcnt = uap->iovcnt;
/*
* Check that we have an even number of iovec's
* and that we have at least two options.
*/
if ((iovcnt & 1) || (iovcnt < 4)) {
CTR2(KTR_VFS, "%s: failed for invalid iovcnt %d", __func__,
uap->iovcnt);
return (EINVAL);
}
error = copyinuio(uap->iovp, iovcnt, &auio);
if (error) {
CTR2(KTR_VFS, "%s: failed for invalid uio op with %d errno",
__func__, error);
return (error);
}
error = vfs_donmount(td, uap->flags, auio);
free(auio, M_IOV);
return (error);
}
/*
* ---------------------------------------------------------------------
* Various utility functions
*/
void
vfs_ref(struct mount *mp)
{
CTR2(KTR_VFS, "%s: mp %p", __func__, mp);
MNT_ILOCK(mp);
MNT_REF(mp);
MNT_IUNLOCK(mp);
}
void
vfs_rel(struct mount *mp)
{
CTR2(KTR_VFS, "%s: mp %p", __func__, mp);
MNT_ILOCK(mp);
MNT_REL(mp);
MNT_IUNLOCK(mp);
}
/*
* Allocate and initialize the mount point struct.
*/
struct mount *
vfs_mount_alloc(struct vnode *vp, struct vfsconf *vfsp, const char *fspath,
struct ucred *cred)
{
struct mount *mp;
mp = uma_zalloc(mount_zone, M_WAITOK);
bzero(&mp->mnt_startzero,
__rangeof(struct mount, mnt_startzero, mnt_endzero));
TAILQ_INIT(&mp->mnt_nvnodelist);
mp->mnt_nvnodelistsize = 0;
mp->mnt_ref = 0;
(void) vfs_busy(mp, MBF_NOWAIT);
mp->mnt_op = vfsp->vfc_vfsops;
mp->mnt_vfc = vfsp;
vfsp->vfc_refcount++; /* XXX Unlocked */
mp->mnt_stat.f_type = vfsp->vfc_typenum;
mp->mnt_gen++;
strlcpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
mp->mnt_vnodecovered = vp;
mp->mnt_cred = crdup(cred);
mp->mnt_stat.f_owner = cred->cr_uid;
strlcpy(mp->mnt_stat.f_mntonname, fspath, MNAMELEN);
mp->mnt_iosize_max = DFLTPHYS;
#ifdef MAC
mac_mount_init(mp);
mac_mount_create(cred, mp);
#endif
arc4rand(&mp->mnt_hashseed, sizeof mp->mnt_hashseed, 0);
return (mp);
}
/*
* Destroy the mount struct previously allocated by vfs_mount_alloc().
*/
void
vfs_mount_destroy(struct mount *mp)
{
MNT_ILOCK(mp);
mp->mnt_kern_flag |= MNTK_REFEXPIRE;
if (mp->mnt_kern_flag & MNTK_MWAIT) {
mp->mnt_kern_flag &= ~MNTK_MWAIT;
wakeup(mp);
}
while (mp->mnt_ref)
msleep(mp, MNT_MTX(mp), PVFS, "mntref", 0);
KASSERT(mp->mnt_ref == 0,
("%s: invalid refcount in the drain path @ %s:%d", __func__,
__FILE__, __LINE__));
if (mp->mnt_writeopcount != 0)
panic("vfs_mount_destroy: nonzero writeopcount");
if (mp->mnt_secondary_writes != 0)
panic("vfs_mount_destroy: nonzero secondary_writes");
mp->mnt_vfc->vfc_refcount--;
if (!TAILQ_EMPTY(&mp->mnt_nvnodelist)) {
struct vnode *vp;
TAILQ_FOREACH(vp, &mp->mnt_nvnodelist, v_nmntvnodes)
vprint("", vp);
panic("unmount: dangling vnode");
}
if (mp->mnt_nvnodelistsize != 0)
panic("vfs_mount_destroy: nonzero nvnodelistsize");
if (mp->mnt_lockref != 0)
panic("vfs_mount_destroy: nonzero lock refcount");
MNT_IUNLOCK(mp);
#ifdef MAC
mac_mount_destroy(mp);
#endif
if (mp->mnt_opt != NULL)
vfs_freeopts(mp->mnt_opt);
crfree(mp->mnt_cred);
uma_zfree(mount_zone, mp);
}
int
vfs_donmount(struct thread *td, int fsflags, struct uio *fsoptions)
{
struct vfsoptlist *optlist;
struct vfsopt *opt, *noro_opt, *tmp_opt;
char *fstype, *fspath, *errmsg;
int error, fstypelen, fspathlen, errmsg_len, errmsg_pos;
int has_rw, has_noro;
errmsg = fspath = NULL;
errmsg_len = has_noro = has_rw = fspathlen = 0;
errmsg_pos = -1;
error = vfs_buildopts(fsoptions, &optlist);
if (error)
return (error);
if (vfs_getopt(optlist, "errmsg", (void **)&errmsg, &errmsg_len) == 0)
errmsg_pos = vfs_getopt_pos(optlist, "errmsg");
/*
* We need these two options before the others,
* and they are mandatory for any filesystem.
* Ensure they are NUL terminated as well.
*/
fstypelen = 0;
error = vfs_getopt(optlist, "fstype", (void **)&fstype, &fstypelen);
if (error || fstype[fstypelen - 1] != '\0') {
error = EINVAL;
if (errmsg != NULL)
strncpy(errmsg, "Invalid fstype", errmsg_len);
goto bail;
}
fspathlen = 0;
error = vfs_getopt(optlist, "fspath", (void **)&fspath, &fspathlen);
if (error || fspath[fspathlen - 1] != '\0') {
error = EINVAL;
if (errmsg != NULL)
strncpy(errmsg, "Invalid fspath", errmsg_len);
goto bail;
}
/*
* We need to see if we have the "update" option
* before we call vfs_domount(), since vfs_domount() has special
* logic based on MNT_UPDATE. This is very important
* when we want to update the root filesystem.
*/
TAILQ_FOREACH_SAFE(opt, optlist, link, tmp_opt) {
if (strcmp(opt->name, "update") == 0) {
fsflags |= MNT_UPDATE;
vfs_freeopt(optlist, opt);
}
else if (strcmp(opt->name, "async") == 0)
fsflags |= MNT_ASYNC;
else if (strcmp(opt->name, "force") == 0) {
fsflags |= MNT_FORCE;
vfs_freeopt(optlist, opt);
}
else if (strcmp(opt->name, "reload") == 0) {
fsflags |= MNT_RELOAD;
vfs_freeopt(optlist, opt);
}
else if (strcmp(opt->name, "multilabel") == 0)
fsflags |= MNT_MULTILABEL;
else if (strcmp(opt->name, "noasync") == 0)
fsflags &= ~MNT_ASYNC;
else if (strcmp(opt->name, "noatime") == 0)
fsflags |= MNT_NOATIME;
else if (strcmp(opt->name, "atime") == 0) {
free(opt->name, M_MOUNT);
opt->name = strdup("nonoatime", M_MOUNT);
}
else if (strcmp(opt->name, "noclusterr") == 0)
fsflags |= MNT_NOCLUSTERR;
else if (strcmp(opt->name, "clusterr") == 0) {
free(opt->name, M_MOUNT);
opt->name = strdup("nonoclusterr", M_MOUNT);
}
else if (strcmp(opt->name, "noclusterw") == 0)
fsflags |= MNT_NOCLUSTERW;
else if (strcmp(opt->name, "clusterw") == 0) {
free(opt->name, M_MOUNT);
opt->name = strdup("nonoclusterw", M_MOUNT);
}
else if (strcmp(opt->name, "noexec") == 0)
fsflags |= MNT_NOEXEC;
else if (strcmp(opt->name, "exec") == 0) {
free(opt->name, M_MOUNT);
opt->name = strdup("nonoexec", M_MOUNT);
}
else if (strcmp(opt->name, "nosuid") == 0)
fsflags |= MNT_NOSUID;
else if (strcmp(opt->name, "suid") == 0) {
free(opt->name, M_MOUNT);
opt->name = strdup("nonosuid", M_MOUNT);
}
else if (strcmp(opt->name, "nosymfollow") == 0)
fsflags |= MNT_NOSYMFOLLOW;
else if (strcmp(opt->name, "symfollow") == 0) {
free(opt->name, M_MOUNT);
opt->name = strdup("nonosymfollow", M_MOUNT);
}
else if (strcmp(opt->name, "noro") == 0) {
fsflags &= ~MNT_RDONLY;
has_noro = 1;
}
else if (strcmp(opt->name, "rw") == 0) {
fsflags &= ~MNT_RDONLY;
has_rw = 1;
}
else if (strcmp(opt->name, "ro") == 0)
fsflags |= MNT_RDONLY;
else if (strcmp(opt->name, "rdonly") == 0) {
free(opt->name, M_MOUNT);
opt->name = strdup("ro", M_MOUNT);
fsflags |= MNT_RDONLY;
}
else if (strcmp(opt->name, "suiddir") == 0)
fsflags |= MNT_SUIDDIR;
else if (strcmp(opt->name, "sync") == 0)
fsflags |= MNT_SYNCHRONOUS;
else if (strcmp(opt->name, "union") == 0)
fsflags |= MNT_UNION;
}
/*
* If "rw" was specified as a mount option, and we
* are trying to update a mount-point from "ro" to "rw",
* we need a mount option "noro", since in vfs_mergeopts(),
* "noro" will cancel "ro", but "rw" will not do anything.
*/
if (has_rw && !has_noro) {
noro_opt = malloc(sizeof(struct vfsopt), M_MOUNT, M_WAITOK);
noro_opt->name = strdup("noro", M_MOUNT);
noro_opt->value = NULL;
noro_opt->len = 0;
noro_opt->pos = -1;
noro_opt->seen = 1;
TAILQ_INSERT_TAIL(optlist, noro_opt, link);
}
/*
* Be ultra-paranoid about making sure the type and fspath
* variables will fit in our mp buffers, including the
* terminating NUL.
*/
if (fstypelen >= MFSNAMELEN - 1 || fspathlen >= MNAMELEN - 1) {
error = ENAMETOOLONG;
goto bail;
}
- error = vfs_domount(td, fstype, fspath, fsflags, optlist);
+ error = vfs_domount(td, fstype, fspath, fsflags, &optlist);
bail:
/* copyout the errmsg */
if (errmsg_pos != -1 && ((2 * errmsg_pos + 1) < fsoptions->uio_iovcnt)
&& errmsg_len > 0 && errmsg != NULL) {
if (fsoptions->uio_segflg == UIO_SYSSPACE) {
bcopy(errmsg,
fsoptions->uio_iov[2 * errmsg_pos + 1].iov_base,
fsoptions->uio_iov[2 * errmsg_pos + 1].iov_len);
} else {
copyout(errmsg,
fsoptions->uio_iov[2 * errmsg_pos + 1].iov_base,
fsoptions->uio_iov[2 * errmsg_pos + 1].iov_len);
}
}
- if (error != 0)
+ if (optlist != NULL)
vfs_freeopts(optlist);
return (error);
}
/*
* Old mount API.
*/
#ifndef _SYS_SYSPROTO_H_
struct mount_args {
char *type;
char *path;
int flags;
caddr_t data;
};
#endif
/* ARGSUSED */
int
mount(td, uap)
struct thread *td;
struct mount_args /* {
char *type;
char *path;
int flags;
caddr_t data;
} */ *uap;
{
char *fstype;
struct vfsconf *vfsp = NULL;
struct mntarg *ma = NULL;
int error;
AUDIT_ARG_FFLAGS(uap->flags);
/*
* Filter out MNT_ROOTFS. We do not want clients of mount() in
* userspace to set this flag, but we must filter it out if we want
* MNT_UPDATE on the root file system to work.
* MNT_ROOTFS should only be set by the kernel when mounting its
* root file system.
*/
uap->flags &= ~MNT_ROOTFS;
fstype = malloc(MFSNAMELEN, M_TEMP, M_WAITOK);
error = copyinstr(uap->type, fstype, MFSNAMELEN, NULL);
if (error) {
free(fstype, M_TEMP);
return (error);
}
AUDIT_ARG_TEXT(fstype);
mtx_lock(&Giant);
vfsp = vfs_byname_kld(fstype, td, &error);
free(fstype, M_TEMP);
if (vfsp == NULL) {
mtx_unlock(&Giant);
return (ENOENT);
}
if (vfsp->vfc_vfsops->vfs_cmount == NULL) {
mtx_unlock(&Giant);
return (EOPNOTSUPP);
}
ma = mount_argsu(ma, "fstype", uap->type, MNAMELEN);
ma = mount_argsu(ma, "fspath", uap->path, MNAMELEN);
ma = mount_argb(ma, uap->flags & MNT_RDONLY, "noro");
ma = mount_argb(ma, !(uap->flags & MNT_NOSUID), "nosuid");
ma = mount_argb(ma, !(uap->flags & MNT_NOEXEC), "noexec");
error = vfsp->vfc_vfsops->vfs_cmount(ma, uap->data, uap->flags);
mtx_unlock(&Giant);
return (error);
}
/*
* vfs_domount_first(): first file system mount (not update)
*/
static int
vfs_domount_first(
- struct thread *td, /* Calling thread. */
- struct vfsconf *vfsp, /* File system type. */
- char *fspath, /* Mount path. */
- struct vnode *vp, /* Vnode to be covered. */
- int fsflags, /* Flags common to all filesystems. */
- void *fsdata /* Options local to the filesystem. */
+ struct thread *td, /* Calling thread. */
+ struct vfsconf *vfsp, /* File system type. */
+ char *fspath, /* Mount path. */
+ struct vnode *vp, /* Vnode to be covered. */
+ int fsflags, /* Flags common to all filesystems. */
+ struct vfsoptlist **optlist /* Options local to the filesystem. */
)
{
struct vattr va;
struct mount *mp;
struct vnode *newdp;
int error;
mtx_assert(&Giant, MA_OWNED);
ASSERT_VOP_ELOCKED(vp, __func__);
KASSERT((fsflags & MNT_UPDATE) == 0, ("MNT_UPDATE shouldn't be here"));
/*
* If the user is not root, ensure that they own the directory
* onto which we are attempting to mount.
*/
error = VOP_GETATTR(vp, &va, td->td_ucred);
if (error == 0 && va.va_uid != td->td_ucred->cr_uid)
error = priv_check_cred(td->td_ucred, PRIV_VFS_ADMIN, 0);
if (error == 0)
error = vinvalbuf(vp, V_SAVE, 0, 0);
if (error == 0 && vp->v_type != VDIR)
error = ENOTDIR;
if (error == 0) {
VI_LOCK(vp);
if ((vp->v_iflag & VI_MOUNT) == 0 && vp->v_mountedhere == NULL)
vp->v_iflag |= VI_MOUNT;
else
error = EBUSY;
VI_UNLOCK(vp);
}
if (error != 0) {
vput(vp);
return (error);
}
VOP_UNLOCK(vp, 0);
/* Allocate and initialize the filesystem. */
mp = vfs_mount_alloc(vp, vfsp, fspath, td->td_ucred);
/* XXXMAC: pass to vfs_mount_alloc? */
- mp->mnt_optnew = fsdata;
+ mp->mnt_optnew = *optlist;
/* Set the mount level flags. */
mp->mnt_flag = (fsflags & (MNT_UPDATEMASK | MNT_ROOTFS | MNT_RDONLY));
/*
* Mount the filesystem.
* XXX The final recipients of VFS_MOUNT just overwrite the ndp they
* get. No freeing of cn_pnbuf.
*/
error = VFS_MOUNT(mp);
if (error != 0) {
vfs_unbusy(mp);
vfs_mount_destroy(mp);
VI_LOCK(vp);
vp->v_iflag &= ~VI_MOUNT;
VI_UNLOCK(vp);
vrele(vp);
return (error);
}
if (mp->mnt_opt != NULL)
vfs_freeopts(mp->mnt_opt);
mp->mnt_opt = mp->mnt_optnew;
+ *optlist = NULL;
(void)VFS_STATFS(mp, &mp->mnt_stat);
/*
* Prevent external consumers of mount options from reading mnt_optnew.
*/
mp->mnt_optnew = NULL;
MNT_ILOCK(mp);
if ((mp->mnt_flag & MNT_ASYNC) != 0 && mp->mnt_noasync == 0)
mp->mnt_kern_flag |= MNTK_ASYNC;
else
mp->mnt_kern_flag &= ~MNTK_ASYNC;
MNT_IUNLOCK(mp);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
cache_purge(vp);
VI_LOCK(vp);
vp->v_iflag &= ~VI_MOUNT;
VI_UNLOCK(vp);
vp->v_mountedhere = mp;
/* Place the new filesystem at the end of the mount list. */
mtx_lock(&mountlist_mtx);
TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
mtx_unlock(&mountlist_mtx);
vfs_event_signal(NULL, VQ_MOUNT, 0);
if (VFS_ROOT(mp, LK_EXCLUSIVE, &newdp))
panic("mount: lost mount");
VOP_UNLOCK(newdp, 0);
VOP_UNLOCK(vp, 0);
mountcheckdirs(vp, newdp);
vrele(newdp);
if ((mp->mnt_flag & MNT_RDONLY) == 0)
vfs_allocate_syncvnode(mp);
vfs_unbusy(mp);
return (0);
}
/*
* vfs_domount_update(): update of mounted file system
*/
static int
vfs_domount_update(
- struct thread *td, /* Calling thread. */
- struct vnode *vp, /* Mount point vnode. */
- int fsflags, /* Flags common to all filesystems. */
- void *fsdata /* Options local to the filesystem. */
+ struct thread *td, /* Calling thread. */
+ struct vnode *vp, /* Mount point vnode. */
+ int fsflags, /* Flags common to all filesystems. */
+ struct vfsoptlist **optlist /* Options local to the filesystem. */
)
{
struct oexport_args oexport;
struct export_args export;
struct mount *mp;
- int error, flag;
+ int error, export_error, flag;
mtx_assert(&Giant, MA_OWNED);
ASSERT_VOP_ELOCKED(vp, __func__);
KASSERT((fsflags & MNT_UPDATE) != 0, ("MNT_UPDATE should be here"));
if ((vp->v_vflag & VV_ROOT) == 0) {
vput(vp);
return (EINVAL);
}
mp = vp->v_mount;
/*
* We only allow the filesystem to be reloaded if it
* is currently mounted read-only.
*/
flag = mp->mnt_flag;
if ((fsflags & MNT_RELOAD) != 0 && (flag & MNT_RDONLY) == 0) {
vput(vp);
return (EOPNOTSUPP); /* Needs translation */
}
/*
* Only privileged root, or (if MNT_USER is set) the user that
* did the original mount is permitted to update it.
*/
error = vfs_suser(mp, td);
if (error != 0) {
vput(vp);
return (error);
}
if (vfs_busy(mp, MBF_NOWAIT)) {
vput(vp);
return (EBUSY);
}
VI_LOCK(vp);
if ((vp->v_iflag & VI_MOUNT) != 0 || vp->v_mountedhere != NULL) {
VI_UNLOCK(vp);
vfs_unbusy(mp);
vput(vp);
return (EBUSY);
}
vp->v_iflag |= VI_MOUNT;
VI_UNLOCK(vp);
VOP_UNLOCK(vp, 0);
MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_UPDATEMASK;
mp->mnt_flag |= fsflags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE |
MNT_SNAPSHOT | MNT_ROOTFS | MNT_UPDATEMASK | MNT_RDONLY);
if ((mp->mnt_flag & MNT_ASYNC) == 0)
mp->mnt_kern_flag &= ~MNTK_ASYNC;
MNT_IUNLOCK(mp);
- mp->mnt_optnew = fsdata;
+ mp->mnt_optnew = *optlist;
vfs_mergeopts(mp->mnt_optnew, mp->mnt_opt);
/*
* Mount the filesystem.
* XXX The final recipients of VFS_MOUNT just overwrite the ndp they
* get. No freeing of cn_pnbuf.
*/
error = VFS_MOUNT(mp);
+ export_error = 0;
if (error == 0) {
/* Process the export option. */
if (vfs_copyopt(mp->mnt_optnew, "export", &export,
sizeof(export)) == 0) {
- error = vfs_export(mp, &export);
+ export_error = vfs_export(mp, &export);
} else if (vfs_copyopt(mp->mnt_optnew, "export", &oexport,
sizeof(oexport)) == 0) {
export.ex_flags = oexport.ex_flags;
export.ex_root = oexport.ex_root;
export.ex_anon = oexport.ex_anon;
export.ex_addr = oexport.ex_addr;
export.ex_addrlen = oexport.ex_addrlen;
export.ex_mask = oexport.ex_mask;
export.ex_masklen = oexport.ex_masklen;
export.ex_indexfile = oexport.ex_indexfile;
export.ex_numsecflavors = 0;
- error = vfs_export(mp, &export);
+ export_error = vfs_export(mp, &export);
}
}
MNT_ILOCK(mp);
if (error == 0) {
mp->mnt_flag &= ~(MNT_UPDATE | MNT_RELOAD | MNT_FORCE |
MNT_SNAPSHOT);
} else {
/*
* If we fail, restore old mount flags. MNT_QUOTA is special,
* because it is not part of MNT_UPDATEMASK, but it could have
* changed in the meantime if quotactl(2) was called.
* All in all we want current value of MNT_QUOTA, not the old
* one.
*/
mp->mnt_flag = (mp->mnt_flag & MNT_QUOTA) | (flag & ~MNT_QUOTA);
}
if ((mp->mnt_flag & MNT_ASYNC) != 0 && mp->mnt_noasync == 0)
mp->mnt_kern_flag |= MNTK_ASYNC;
else
mp->mnt_kern_flag &= ~MNTK_ASYNC;
MNT_IUNLOCK(mp);
if (error != 0)
goto end;
if (mp->mnt_opt != NULL)
vfs_freeopts(mp->mnt_opt);
mp->mnt_opt = mp->mnt_optnew;
+ *optlist = NULL;
(void)VFS_STATFS(mp, &mp->mnt_stat);
/*
* Prevent external consumers of mount options from reading
* mnt_optnew.
*/
mp->mnt_optnew = NULL;
if ((mp->mnt_flag & MNT_RDONLY) == 0)
vfs_allocate_syncvnode(mp);
else
vfs_deallocate_syncvnode(mp);
end:
vfs_unbusy(mp);
VI_LOCK(vp);
vp->v_iflag &= ~VI_MOUNT;
VI_UNLOCK(vp);
vrele(vp);
- return (error);
+ return (error != 0 ? error : export_error);
}
/*
* vfs_domount(): actually attempt a filesystem mount.
*/
static int
vfs_domount(
- struct thread *td, /* Calling thread. */
- const char *fstype, /* Filesystem type. */
- char *fspath, /* Mount path. */
- int fsflags, /* Flags common to all filesystems. */
- void *fsdata /* Options local to the filesystem. */
+ struct thread *td, /* Calling thread. */
+ const char *fstype, /* Filesystem type. */
+ char *fspath, /* Mount path. */
+ int fsflags, /* Flags common to all filesystems. */
+ struct vfsoptlist **optlist /* Options local to the filesystem. */
)
{
struct vfsconf *vfsp;
struct nameidata nd;
struct vnode *vp;
int error;
/*
* Be ultra-paranoid about making sure the type and fspath
* variables will fit in our mp buffers, including the
* terminating NUL.
*/
if (strlen(fstype) >= MFSNAMELEN || strlen(fspath) >= MNAMELEN)
return (ENAMETOOLONG);
if (jailed(td->td_ucred) || usermount == 0) {
if ((error = priv_check(td, PRIV_VFS_MOUNT)) != 0)
return (error);
}
/*
* Do not allow NFS export or MNT_SUIDDIR by unprivileged users.
*/
if (fsflags & MNT_EXPORTED) {
error = priv_check(td, PRIV_VFS_MOUNT_EXPORTED);
if (error)
return (error);
}
if (fsflags & MNT_SUIDDIR) {
error = priv_check(td, PRIV_VFS_MOUNT_SUIDDIR);
if (error)
return (error);
}
/*
* Silently enforce MNT_NOSUID and MNT_USER for unprivileged users.
*/
if ((fsflags & (MNT_NOSUID | MNT_USER)) != (MNT_NOSUID | MNT_USER)) {
if (priv_check(td, PRIV_VFS_MOUNT_NONUSER) != 0)
fsflags |= MNT_NOSUID | MNT_USER;
}
/* Load KLDs before we lock the covered vnode to avoid reversals. */
vfsp = NULL;
if ((fsflags & MNT_UPDATE) == 0) {
/* Don't try to load KLDs if we're mounting the root. */
if (fsflags & MNT_ROOTFS)
vfsp = vfs_byname(fstype);
else
vfsp = vfs_byname_kld(fstype, td, &error);
if (vfsp == NULL)
return (ENODEV);
if (jailed(td->td_ucred) && !(vfsp->vfc_flags & VFCF_JAIL))
return (EPERM);
}
/*
* Get vnode to be covered or mount point's vnode in case of MNT_UPDATE.
*/
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
UIO_SYSSPACE, fspath, td);
error = namei(&nd);
if (error != 0)
return (error);
if (!NDHASGIANT(&nd))
mtx_lock(&Giant);
NDFREE(&nd, NDF_ONLY_PNBUF);
vp = nd.ni_vp;
if ((fsflags & MNT_UPDATE) == 0) {
error = vfs_domount_first(td, vfsp, fspath, vp, fsflags,
- fsdata);
+ optlist);
} else {
- error = vfs_domount_update(td, vp, fsflags, fsdata);
+ error = vfs_domount_update(td, vp, fsflags, optlist);
}
mtx_unlock(&Giant);
ASSERT_VI_UNLOCKED(vp, __func__);
ASSERT_VOP_UNLOCKED(vp, __func__);
return (error);
}
/*
* Unmount a filesystem.
*
* Note: unmount takes a path to the vnode mounted on as argument, not
* special file (as before).
*/
#ifndef _SYS_SYSPROTO_H_
struct unmount_args {
char *path;
int flags;
};
#endif
/* ARGSUSED */
int
unmount(td, uap)
struct thread *td;
register struct unmount_args /* {
char *path;
int flags;
} */ *uap;
{
struct mount *mp;
char *pathbuf;
int error, id0, id1;
AUDIT_ARG_VALUE(uap->flags);
if (jailed(td->td_ucred) || usermount == 0) {
error = priv_check(td, PRIV_VFS_UNMOUNT);
if (error)
return (error);
}
pathbuf = malloc(MNAMELEN, M_TEMP, M_WAITOK);
error = copyinstr(uap->path, pathbuf, MNAMELEN, NULL);
if (error) {
free(pathbuf, M_TEMP);
return (error);
}
mtx_lock(&Giant);
if (uap->flags & MNT_BYFSID) {
AUDIT_ARG_TEXT(pathbuf);
/* Decode the filesystem ID. */
if (sscanf(pathbuf, "FSID:%d:%d", &id0, &id1) != 2) {
mtx_unlock(&Giant);
free(pathbuf, M_TEMP);
return (EINVAL);
}
mtx_lock(&mountlist_mtx);
TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) {
if (mp->mnt_stat.f_fsid.val[0] == id0 &&
mp->mnt_stat.f_fsid.val[1] == id1)
break;
}
mtx_unlock(&mountlist_mtx);
} else {
AUDIT_ARG_UPATH1(td, pathbuf);
mtx_lock(&mountlist_mtx);
TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) {
if (strcmp(mp->mnt_stat.f_mntonname, pathbuf) == 0)
break;
}
mtx_unlock(&mountlist_mtx);
}
free(pathbuf, M_TEMP);
if (mp == NULL) {
/*
* Previously we returned ENOENT for a nonexistent path and
* EINVAL for a non-mountpoint. We cannot tell these apart
* now, so in the !MNT_BYFSID case return the more likely
* EINVAL for compatibility.
*/
mtx_unlock(&Giant);
return ((uap->flags & MNT_BYFSID) ? ENOENT : EINVAL);
}
/*
* Don't allow unmounting the root filesystem.
*/
if (mp->mnt_flag & MNT_ROOTFS) {
mtx_unlock(&Giant);
return (EINVAL);
}
error = dounmount(mp, uap->flags, td);
mtx_unlock(&Giant);
return (error);
}
/*
* Do the actual filesystem unmount.
*/
int
dounmount(mp, flags, td)
struct mount *mp;
int flags;
struct thread *td;
{
struct vnode *coveredvp, *fsrootvp;
int error;
int async_flag;
int mnt_gen_r;
mtx_assert(&Giant, MA_OWNED);
if ((coveredvp = mp->mnt_vnodecovered) != NULL) {
mnt_gen_r = mp->mnt_gen;
VI_LOCK(coveredvp);
vholdl(coveredvp);
vn_lock(coveredvp, LK_EXCLUSIVE | LK_INTERLOCK | LK_RETRY);
vdrop(coveredvp);
/*
* Check for mp being unmounted while waiting for the
* covered vnode lock.
*/
if (coveredvp->v_mountedhere != mp ||
coveredvp->v_mountedhere->mnt_gen != mnt_gen_r) {
VOP_UNLOCK(coveredvp, 0);
return (EBUSY);
}
}
/*
* Only privileged root, or (if MNT_USER is set) the user that did the
* original mount is permitted to unmount this filesystem.
*/
error = vfs_suser(mp, td);
if (error) {
if (coveredvp)
VOP_UNLOCK(coveredvp, 0);
return (error);
}
MNT_ILOCK(mp);
if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
MNT_IUNLOCK(mp);
if (coveredvp)
VOP_UNLOCK(coveredvp, 0);
return (EBUSY);
}
mp->mnt_kern_flag |= MNTK_UNMOUNT | MNTK_NOINSMNTQ;
/* Allow filesystems to detect that a forced unmount is in progress. */
if (flags & MNT_FORCE)
mp->mnt_kern_flag |= MNTK_UNMOUNTF;
error = 0;
if (mp->mnt_lockref) {
if ((flags & MNT_FORCE) == 0) {
mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_NOINSMNTQ |
MNTK_UNMOUNTF);
if (mp->mnt_kern_flag & MNTK_MWAIT) {
mp->mnt_kern_flag &= ~MNTK_MWAIT;
wakeup(mp);
}
MNT_IUNLOCK(mp);
if (coveredvp)
VOP_UNLOCK(coveredvp, 0);
return (EBUSY);
}
mp->mnt_kern_flag |= MNTK_DRAINING;
error = msleep(&mp->mnt_lockref, MNT_MTX(mp), PVFS,
"mount drain", 0);
}
MNT_IUNLOCK(mp);
KASSERT(mp->mnt_lockref == 0,
("%s: invalid lock refcount in the drain path @ %s:%d",
__func__, __FILE__, __LINE__));
KASSERT(error == 0,
("%s: invalid return value for msleep in the drain path @ %s:%d",
__func__, __FILE__, __LINE__));
vn_start_write(NULL, &mp, V_WAIT);
if (mp->mnt_flag & MNT_EXPUBLIC)
vfs_setpublicfs(NULL, NULL, NULL);
vfs_msync(mp, MNT_WAIT);
MNT_ILOCK(mp);
async_flag = mp->mnt_flag & MNT_ASYNC;
mp->mnt_flag &= ~MNT_ASYNC;
mp->mnt_kern_flag &= ~MNTK_ASYNC;
MNT_IUNLOCK(mp);
cache_purgevfs(mp); /* remove cache entries for this file sys */
vfs_deallocate_syncvnode(mp);
/*
* For forced unmounts, move process cdir/rdir refs on the fs root
* vnode to the covered vnode. For non-forced unmounts we want
* such references to cause an EBUSY error.
*/
if ((flags & MNT_FORCE) &&
VFS_ROOT(mp, LK_EXCLUSIVE, &fsrootvp) == 0) {
if (mp->mnt_vnodecovered != NULL)
mountcheckdirs(fsrootvp, mp->mnt_vnodecovered);
if (fsrootvp == rootvnode) {
vrele(rootvnode);
rootvnode = NULL;
}
vput(fsrootvp);
}
if (((mp->mnt_flag & MNT_RDONLY) ||
(error = VFS_SYNC(mp, MNT_WAIT)) == 0) || (flags & MNT_FORCE) != 0)
error = VFS_UNMOUNT(mp, flags);
vn_finished_write(mp);
/*
* If we failed to flush the dirty blocks for this mount point,
* undo all the cdir/rdir and rootvnode changes we made above.
* Unless we failed to do so because the device is reporting that
* it doesn't exist anymore.
*/
if (error && error != ENXIO) {
if ((flags & MNT_FORCE) &&
VFS_ROOT(mp, LK_EXCLUSIVE, &fsrootvp) == 0) {
if (mp->mnt_vnodecovered != NULL)
mountcheckdirs(mp->mnt_vnodecovered, fsrootvp);
if (rootvnode == NULL) {
rootvnode = fsrootvp;
vref(rootvnode);
}
vput(fsrootvp);
}
MNT_ILOCK(mp);
mp->mnt_kern_flag &= ~MNTK_NOINSMNTQ;
if ((mp->mnt_flag & MNT_RDONLY) == 0) {
MNT_IUNLOCK(mp);
vfs_allocate_syncvnode(mp);
MNT_ILOCK(mp);
}
mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
mp->mnt_flag |= async_flag;
if ((mp->mnt_flag & MNT_ASYNC) != 0 && mp->mnt_noasync == 0)
mp->mnt_kern_flag |= MNTK_ASYNC;
if (mp->mnt_kern_flag & MNTK_MWAIT) {
mp->mnt_kern_flag &= ~MNTK_MWAIT;
wakeup(mp);
}
MNT_IUNLOCK(mp);
if (coveredvp)
VOP_UNLOCK(coveredvp, 0);
return (error);
}
mtx_lock(&mountlist_mtx);
TAILQ_REMOVE(&mountlist, mp, mnt_list);
mtx_unlock(&mountlist_mtx);
if (coveredvp != NULL) {
coveredvp->v_mountedhere = NULL;
vput(coveredvp);
}
vfs_event_signal(NULL, VQ_UNMOUNT, 0);
vfs_mount_destroy(mp);
return (0);
}
/*
* Report errors during filesystem mounting.
*/
void
vfs_mount_error(struct mount *mp, const char *fmt, ...)
{
struct vfsoptlist *moptlist = mp->mnt_optnew;
va_list ap;
int error, len;
char *errmsg;
error = vfs_getopt(moptlist, "errmsg", (void **)&errmsg, &len);
if (error || errmsg == NULL || len <= 0)
return;
va_start(ap, fmt);
vsnprintf(errmsg, (size_t)len, fmt, ap);
va_end(ap);
}
void
vfs_opterror(struct vfsoptlist *opts, const char *fmt, ...)
{
va_list ap;
int error, len;
char *errmsg;
error = vfs_getopt(opts, "errmsg", (void **)&errmsg, &len);
if (error || errmsg == NULL || len <= 0)
return;
va_start(ap, fmt);
vsnprintf(errmsg, (size_t)len, fmt, ap);
va_end(ap);
}
/*
* ---------------------------------------------------------------------
* Functions for querying mount options/arguments from filesystems.
*/
/*
* Check that no unknown options are given
*/
int
vfs_filteropt(struct vfsoptlist *opts, const char **legal)
{
struct vfsopt *opt;
char errmsg[255];
const char **t, *p, *q;
int ret = 0;
TAILQ_FOREACH(opt, opts, link) {
p = opt->name;
q = NULL;
if (p[0] == 'n' && p[1] == 'o')
q = p + 2;
for(t = global_opts; *t != NULL; t++) {
if (strcmp(*t, p) == 0)
break;
if (q != NULL) {
if (strcmp(*t, q) == 0)
break;
}
}
if (*t != NULL)
continue;
for(t = legal; *t != NULL; t++) {
if (strcmp(*t, p) == 0)
break;
if (q != NULL) {
if (strcmp(*t, q) == 0)
break;
}
}
if (*t != NULL)
continue;
snprintf(errmsg, sizeof(errmsg),
"mount option <%s> is unknown", p);
ret = EINVAL;
}
if (ret != 0) {
TAILQ_FOREACH(opt, opts, link) {
if (strcmp(opt->name, "errmsg") == 0) {
strncpy((char *)opt->value, errmsg, opt->len);
break;
}
}
if (opt == NULL)
printf("%s\n", errmsg);
}
return (ret);
}
/*
* Get a mount option by its name.
*
* Return 0 if the option was found, ENOENT otherwise.
* If len is non-NULL it will be filled with the length
* of the option. If buf is non-NULL, it will be filled
* with the address of the option.
*/
int
vfs_getopt(opts, name, buf, len)
struct vfsoptlist *opts;
const char *name;
void **buf;
int *len;
{
struct vfsopt *opt;
KASSERT(opts != NULL, ("vfs_getopt: caller passed 'opts' as NULL"));
TAILQ_FOREACH(opt, opts, link) {
if (strcmp(name, opt->name) == 0) {
opt->seen = 1;
if (len != NULL)
*len = opt->len;
if (buf != NULL)
*buf = opt->value;
return (0);
}
}
return (ENOENT);
}
int
vfs_getopt_pos(struct vfsoptlist *opts, const char *name)
{
struct vfsopt *opt;
if (opts == NULL)
return (-1);
TAILQ_FOREACH(opt, opts, link) {
if (strcmp(name, opt->name) == 0) {
opt->seen = 1;
return (opt->pos);
}
}
return (-1);
}
char *
vfs_getopts(struct vfsoptlist *opts, const char *name, int *error)
{
struct vfsopt *opt;
*error = 0;
TAILQ_FOREACH(opt, opts, link) {
if (strcmp(name, opt->name) != 0)
continue;
opt->seen = 1;
if (opt->len == 0 ||
((char *)opt->value)[opt->len - 1] != '\0') {
*error = EINVAL;
return (NULL);
}
return (opt->value);
}
*error = ENOENT;
return (NULL);
}
int
vfs_flagopt(struct vfsoptlist *opts, const char *name, u_int *w, u_int val)
{
struct vfsopt *opt;
TAILQ_FOREACH(opt, opts, link) {
if (strcmp(name, opt->name) == 0) {
opt->seen = 1;
if (w != NULL)
*w |= val;
return (1);
}
}
if (w != NULL)
*w &= ~val;
return (0);
}
int
vfs_scanopt(struct vfsoptlist *opts, const char *name, const char *fmt, ...)
{
va_list ap;
struct vfsopt *opt;
int ret;
KASSERT(opts != NULL, ("vfs_getopt: caller passed 'opts' as NULL"));
TAILQ_FOREACH(opt, opts, link) {
if (strcmp(name, opt->name) != 0)
continue;
opt->seen = 1;
if (opt->len == 0 || opt->value == NULL)
return (0);
if (((char *)opt->value)[opt->len - 1] != '\0')
return (0);
va_start(ap, fmt);
ret = vsscanf(opt->value, fmt, ap);
va_end(ap);
return (ret);
}
return (0);
}
int
vfs_setopt(struct vfsoptlist *opts, const char *name, void *value, int len)
{
struct vfsopt *opt;
TAILQ_FOREACH(opt, opts, link) {
if (strcmp(name, opt->name) != 0)
continue;
opt->seen = 1;
if (opt->value == NULL)
opt->len = len;
else {
if (opt->len != len)
return (EINVAL);
bcopy(value, opt->value, len);
}
return (0);
}
return (ENOENT);
}
int
vfs_setopt_part(struct vfsoptlist *opts, const char *name, void *value, int len)
{
struct vfsopt *opt;
TAILQ_FOREACH(opt, opts, link) {
if (strcmp(name, opt->name) != 0)
continue;
opt->seen = 1;
if (opt->value == NULL)
opt->len = len;
else {
if (opt->len < len)
return (EINVAL);
opt->len = len;
bcopy(value, opt->value, len);
}
return (0);
}
return (ENOENT);
}
int
vfs_setopts(struct vfsoptlist *opts, const char *name, const char *value)
{
struct vfsopt *opt;
TAILQ_FOREACH(opt, opts, link) {
if (strcmp(name, opt->name) != 0)
continue;
opt->seen = 1;
if (opt->value == NULL)
opt->len = strlen(value) + 1;
else if (strlcpy(opt->value, value, opt->len) >= opt->len)
return (EINVAL);
return (0);
}
return (ENOENT);
}
/*
* Find and copy a mount option.
*
* The size of the buffer has to be specified
* in len, if it is not the same length as the
* mount option, EINVAL is returned.
* Returns ENOENT if the option is not found.
*/
int
vfs_copyopt(opts, name, dest, len)
struct vfsoptlist *opts;
const char *name;
void *dest;
int len;
{
struct vfsopt *opt;
KASSERT(opts != NULL, ("vfs_copyopt: caller passed 'opts' as NULL"));
TAILQ_FOREACH(opt, opts, link) {
if (strcmp(name, opt->name) == 0) {
opt->seen = 1;
if (len != opt->len)
return (EINVAL);
bcopy(opt->value, dest, opt->len);
return (0);
}
}
return (ENOENT);
}
/*
* This is a helper function for filesystems to traverse their
* vnodes. See MNT_VNODE_FOREACH() in sys/mount.h
*/
struct vnode *
__mnt_vnode_next(struct vnode **mvp, struct mount *mp)
{
struct vnode *vp;
mtx_assert(MNT_MTX(mp), MA_OWNED);
KASSERT((*mvp)->v_mount == mp, ("marker vnode mount list mismatch"));
if (should_yield()) {
MNT_IUNLOCK(mp);
kern_yield(-1);
MNT_ILOCK(mp);
}
vp = TAILQ_NEXT(*mvp, v_nmntvnodes);
while (vp != NULL && vp->v_type == VMARKER)
vp = TAILQ_NEXT(vp, v_nmntvnodes);
/* Check if we are done */
if (vp == NULL) {
__mnt_vnode_markerfree(mvp, mp);
return (NULL);
}
TAILQ_REMOVE(&mp->mnt_nvnodelist, *mvp, v_nmntvnodes);
TAILQ_INSERT_AFTER(&mp->mnt_nvnodelist, vp, *mvp, v_nmntvnodes);
return (vp);
}
struct vnode *
__mnt_vnode_first(struct vnode **mvp, struct mount *mp)
{
struct vnode *vp;
mtx_assert(MNT_MTX(mp), MA_OWNED);
vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
while (vp != NULL && vp->v_type == VMARKER)
vp = TAILQ_NEXT(vp, v_nmntvnodes);
/* Check if we are done */
if (vp == NULL) {
*mvp = NULL;
return (NULL);
}
MNT_REF(mp);
MNT_IUNLOCK(mp);
*mvp = (struct vnode *) malloc(sizeof(struct vnode),
M_VNODE_MARKER,
M_WAITOK | M_ZERO);
MNT_ILOCK(mp);
(*mvp)->v_type = VMARKER;
vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
while (vp != NULL && vp->v_type == VMARKER)
vp = TAILQ_NEXT(vp, v_nmntvnodes);
/* Check if we are done */
if (vp == NULL) {
MNT_IUNLOCK(mp);
free(*mvp, M_VNODE_MARKER);
MNT_ILOCK(mp);
*mvp = NULL;
MNT_REL(mp);
return (NULL);
}
(*mvp)->v_mount = mp;
TAILQ_INSERT_AFTER(&mp->mnt_nvnodelist, vp, *mvp, v_nmntvnodes);
return (vp);
}
void
__mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp)
{
if (*mvp == NULL)
return;
mtx_assert(MNT_MTX(mp), MA_OWNED);
KASSERT((*mvp)->v_mount == mp, ("marker vnode mount list mismatch"));
TAILQ_REMOVE(&mp->mnt_nvnodelist, *mvp, v_nmntvnodes);
MNT_IUNLOCK(mp);
free(*mvp, M_VNODE_MARKER);
MNT_ILOCK(mp);
*mvp = NULL;
MNT_REL(mp);
}
int
__vfs_statfs(struct mount *mp, struct statfs *sbp)
{
int error;
error = mp->mnt_op->vfs_statfs(mp, &mp->mnt_stat);
if (sbp != &mp->mnt_stat)
*sbp = mp->mnt_stat;
return (error);
}
void
vfs_mountedfrom(struct mount *mp, const char *from)
{
bzero(mp->mnt_stat.f_mntfromname, sizeof mp->mnt_stat.f_mntfromname);
strlcpy(mp->mnt_stat.f_mntfromname, from,
sizeof mp->mnt_stat.f_mntfromname);
}
/*
* ---------------------------------------------------------------------
* This is the api for building mount args and mounting filesystems from
* inside the kernel.
*
* The API works by accumulation of individual args. First error is
* latched.
*
* XXX: should be documented in new manpage kernel_mount(9)
*/
/* A memory allocation which must be freed when we are done */
struct mntaarg {
SLIST_ENTRY(mntaarg) next;
};
/* The header for the mount arguments */
struct mntarg {
struct iovec *v;
int len;
int error;
SLIST_HEAD(, mntaarg) list;
};
/*
* Add a boolean argument.
*
* flag is the boolean value.
* name must start with "no".
*/
struct mntarg *
mount_argb(struct mntarg *ma, int flag, const char *name)
{
KASSERT(name[0] == 'n' && name[1] == 'o',
("mount_argb(...,%s): name must start with 'no'", name));
return (mount_arg(ma, name + (flag ? 2 : 0), NULL, 0));
}
/*
* Add an argument printf style
*/
struct mntarg *
mount_argf(struct mntarg *ma, const char *name, const char *fmt, ...)
{
va_list ap;
struct mntaarg *maa;
struct sbuf *sb;
int len;
if (ma == NULL) {
ma = malloc(sizeof *ma, M_MOUNT, M_WAITOK | M_ZERO);
SLIST_INIT(&ma->list);
}
if (ma->error)
return (ma);
ma->v = realloc(ma->v, sizeof *ma->v * (ma->len + 2),
M_MOUNT, M_WAITOK);
ma->v[ma->len].iov_base = (void *)(uintptr_t)name;
ma->v[ma->len].iov_len = strlen(name) + 1;
ma->len++;
sb = sbuf_new_auto();
va_start(ap, fmt);
sbuf_vprintf(sb, fmt, ap);
va_end(ap);
sbuf_finish(sb);
len = sbuf_len(sb) + 1;
maa = malloc(sizeof *maa + len, M_MOUNT, M_WAITOK | M_ZERO);
SLIST_INSERT_HEAD(&ma->list, maa, next);
bcopy(sbuf_data(sb), maa + 1, len);
sbuf_delete(sb);
ma->v[ma->len].iov_base = maa + 1;
ma->v[ma->len].iov_len = len;
ma->len++;
return (ma);
}
/*
* Add an argument which is a userland string.
*/
struct mntarg *
mount_argsu(struct mntarg *ma, const char *name, const void *val, int len)
{
struct mntaarg *maa;
char *tbuf;
if (val == NULL)
return (ma);
if (ma == NULL) {
ma = malloc(sizeof *ma, M_MOUNT, M_WAITOK | M_ZERO);
SLIST_INIT(&ma->list);
}
if (ma->error)
return (ma);
maa = malloc(sizeof *maa + len, M_MOUNT, M_WAITOK | M_ZERO);
SLIST_INSERT_HEAD(&ma->list, maa, next);
tbuf = (void *)(maa + 1);
ma->error = copyinstr(val, tbuf, len, NULL);
return (mount_arg(ma, name, tbuf, -1));
}
/*
* Plain argument.
*
* If length is -1, treat value as a C string.
*/
struct mntarg *
mount_arg(struct mntarg *ma, const char *name, const void *val, int len)
{
if (ma == NULL) {
ma = malloc(sizeof *ma, M_MOUNT, M_WAITOK | M_ZERO);
SLIST_INIT(&ma->list);
}
if (ma->error)
return (ma);
ma->v = realloc(ma->v, sizeof *ma->v * (ma->len + 2),
M_MOUNT, M_WAITOK);
ma->v[ma->len].iov_base = (void *)(uintptr_t)name;
ma->v[ma->len].iov_len = strlen(name) + 1;
ma->len++;
ma->v[ma->len].iov_base = (void *)(uintptr_t)val;
if (len < 0)
ma->v[ma->len].iov_len = strlen(val) + 1;
else
ma->v[ma->len].iov_len = len;
ma->len++;
return (ma);
}
/*
* Free a mntarg structure
*/
static void
free_mntarg(struct mntarg *ma)
{
struct mntaarg *maa;
while (!SLIST_EMPTY(&ma->list)) {
maa = SLIST_FIRST(&ma->list);
SLIST_REMOVE_HEAD(&ma->list, next);
free(maa, M_MOUNT);
}
free(ma->v, M_MOUNT);
free(ma, M_MOUNT);
}
/*
* Mount a filesystem
*/
int
kernel_mount(struct mntarg *ma, int flags)
{
struct uio auio;
int error;
KASSERT(ma != NULL, ("kernel_mount NULL ma"));
KASSERT(ma->v != NULL, ("kernel_mount NULL ma->v"));
KASSERT(!(ma->len & 1), ("kernel_mount odd ma->len (%d)", ma->len));
auio.uio_iov = ma->v;
auio.uio_iovcnt = ma->len;
auio.uio_segflg = UIO_SYSSPACE;
error = ma->error;
if (!error)
error = vfs_donmount(curthread, flags, &auio);
free_mntarg(ma);
return (error);
}
/*
* A printflike function to mount a filesystem.
*/
int
kernel_vmount(int flags, ...)
{
struct mntarg *ma = NULL;
va_list ap;
const char *cp;
const void *vp;
int error;
va_start(ap, flags);
for (;;) {
cp = va_arg(ap, const char *);
if (cp == NULL)
break;
vp = va_arg(ap, const void *);
ma = mount_arg(ma, cp, vp, (vp != NULL ? -1 : 0));
}
va_end(ap);
error = kernel_mount(ma, flags);
return (error);
}
void
vfs_oexport_conv(const struct oexport_args *oexp, struct export_args *exp)
{
bcopy(oexp, exp, sizeof(*oexp));
exp->ex_numsecflavors = 0;
}
Index: projects/altix/sys/netinet/sctp_sysctl.c
===================================================================
--- projects/altix/sys/netinet/sctp_sysctl.c (revision 218875)
+++ projects/altix/sys/netinet/sctp_sysctl.c (revision 218876)
@@ -1,1128 +1,1129 @@
/*-
* Copyright (c) 2007, by Cisco Systems, Inc. All rights reserved.
* Copyright (c) 2008-2011, by Randall Stewart. All rights reserved.
* Copyright (c) 2008-2011, by Michael Tuexen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* b) Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the distribution.
*
* c) Neither the name of Cisco Systems, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <netinet/sctp_os.h>
#include <netinet/sctp.h>
#include <netinet/sctp_constants.h>
#include <netinet/sctp_sysctl.h>
#include <netinet/sctp_pcb.h>
#include <netinet/sctputil.h>
#include <netinet/sctp_output.h>
#include <sys/smp.h>
/*
* sysctl tunable variables
*/
void
sctp_init_sysctls()
{
SCTP_BASE_SYSCTL(sctp_sendspace) = SCTPCTL_MAXDGRAM_DEFAULT;
SCTP_BASE_SYSCTL(sctp_recvspace) = SCTPCTL_RECVSPACE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_auto_asconf) = SCTPCTL_AUTOASCONF_DEFAULT;
SCTP_BASE_SYSCTL(sctp_multiple_asconfs) = SCTPCTL_MULTIPLEASCONFS_DEFAULT;
SCTP_BASE_SYSCTL(sctp_ecn_enable) = SCTPCTL_ECN_ENABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_strict_sacks) = SCTPCTL_STRICT_SACKS_DEFAULT;
#if !defined(SCTP_WITH_NO_CSUM)
SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) = SCTPCTL_LOOPBACK_NOCSUM_DEFAULT;
#endif
SCTP_BASE_SYSCTL(sctp_strict_init) = SCTPCTL_STRICT_INIT_DEFAULT;
SCTP_BASE_SYSCTL(sctp_peer_chunk_oh) = SCTPCTL_PEER_CHKOH_DEFAULT;
SCTP_BASE_SYSCTL(sctp_max_burst_default) = SCTPCTL_MAXBURST_DEFAULT;
SCTP_BASE_SYSCTL(sctp_fr_max_burst_default) = SCTPCTL_FRMAXBURST_DEFAULT;
SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue) = SCTPCTL_MAXCHUNKS_DEFAULT;
SCTP_BASE_SYSCTL(sctp_hashtblsize) = SCTPCTL_TCBHASHSIZE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_pcbtblsize) = SCTPCTL_PCBHASHSIZE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_min_split_point) = SCTPCTL_MIN_SPLIT_POINT_DEFAULT;
SCTP_BASE_SYSCTL(sctp_chunkscale) = SCTPCTL_CHUNKSCALE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_delayed_sack_time_default) = SCTPCTL_DELAYED_SACK_TIME_DEFAULT;
SCTP_BASE_SYSCTL(sctp_sack_freq_default) = SCTPCTL_SACK_FREQ_DEFAULT;
SCTP_BASE_SYSCTL(sctp_system_free_resc_limit) = SCTPCTL_SYS_RESOURCE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_asoc_free_resc_limit) = SCTPCTL_ASOC_RESOURCE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_heartbeat_interval_default) = SCTPCTL_HEARTBEAT_INTERVAL_DEFAULT;
SCTP_BASE_SYSCTL(sctp_pmtu_raise_time_default) = SCTPCTL_PMTU_RAISE_TIME_DEFAULT;
SCTP_BASE_SYSCTL(sctp_shutdown_guard_time_default) = SCTPCTL_SHUTDOWN_GUARD_TIME_DEFAULT;
SCTP_BASE_SYSCTL(sctp_secret_lifetime_default) = SCTPCTL_SECRET_LIFETIME_DEFAULT;
SCTP_BASE_SYSCTL(sctp_rto_max_default) = SCTPCTL_RTO_MAX_DEFAULT;
SCTP_BASE_SYSCTL(sctp_rto_min_default) = SCTPCTL_RTO_MIN_DEFAULT;
SCTP_BASE_SYSCTL(sctp_rto_initial_default) = SCTPCTL_RTO_INITIAL_DEFAULT;
SCTP_BASE_SYSCTL(sctp_init_rto_max_default) = SCTPCTL_INIT_RTO_MAX_DEFAULT;
SCTP_BASE_SYSCTL(sctp_valid_cookie_life_default) = SCTPCTL_VALID_COOKIE_LIFE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_init_rtx_max_default) = SCTPCTL_INIT_RTX_MAX_DEFAULT;
SCTP_BASE_SYSCTL(sctp_assoc_rtx_max_default) = SCTPCTL_ASSOC_RTX_MAX_DEFAULT;
SCTP_BASE_SYSCTL(sctp_path_rtx_max_default) = SCTPCTL_PATH_RTX_MAX_DEFAULT;
SCTP_BASE_SYSCTL(sctp_add_more_threshold) = SCTPCTL_ADD_MORE_ON_OUTPUT_DEFAULT;
SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default) = SCTPCTL_OUTGOING_STREAMS_DEFAULT;
SCTP_BASE_SYSCTL(sctp_cmt_on_off) = SCTPCTL_CMT_ON_OFF_DEFAULT;
/* EY */
SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) = SCTPCTL_NR_SACK_ON_OFF_DEFAULT;
SCTP_BASE_SYSCTL(sctp_cmt_use_dac) = SCTPCTL_CMT_USE_DAC_DEFAULT;
SCTP_BASE_SYSCTL(sctp_cmt_pf) = SCTPCTL_CMT_PF_DEFAULT;
SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst) = SCTPCTL_CWND_MAXBURST_DEFAULT;
SCTP_BASE_SYSCTL(sctp_early_fr) = SCTPCTL_EARLY_FAST_RETRAN_DEFAULT;
SCTP_BASE_SYSCTL(sctp_early_fr_msec) = SCTPCTL_EARLY_FAST_RETRAN_MSEC_DEFAULT;
SCTP_BASE_SYSCTL(sctp_asconf_auth_nochk) = SCTPCTL_ASCONF_AUTH_NOCHK_DEFAULT;
SCTP_BASE_SYSCTL(sctp_auth_disable) = SCTPCTL_AUTH_DISABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_nat_friendly) = SCTPCTL_NAT_FRIENDLY_DEFAULT;
SCTP_BASE_SYSCTL(sctp_L2_abc_variable) = SCTPCTL_ABC_L_VAR_DEFAULT;
SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count) = SCTPCTL_MAX_CHAINED_MBUFS_DEFAULT;
SCTP_BASE_SYSCTL(sctp_do_drain) = SCTPCTL_DO_SCTP_DRAIN_DEFAULT;
SCTP_BASE_SYSCTL(sctp_hb_maxburst) = SCTPCTL_HB_MAX_BURST_DEFAULT;
SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit) = SCTPCTL_ABORT_AT_LIMIT_DEFAULT;
SCTP_BASE_SYSCTL(sctp_strict_data_order) = SCTPCTL_STRICT_DATA_ORDER_DEFAULT;
SCTP_BASE_SYSCTL(sctp_min_residual) = SCTPCTL_MIN_RESIDUAL_DEFAULT;
SCTP_BASE_SYSCTL(sctp_max_retran_chunk) = SCTPCTL_MAX_RETRAN_CHUNK_DEFAULT;
SCTP_BASE_SYSCTL(sctp_logging_level) = SCTPCTL_LOGGING_LEVEL_DEFAULT;
/* JRS - Variable for default congestion control module */
SCTP_BASE_SYSCTL(sctp_default_cc_module) = SCTPCTL_DEFAULT_CC_MODULE_DEFAULT;
/* RS - Variable for default stream scheduling module */
SCTP_BASE_SYSCTL(sctp_default_ss_module) = SCTPCTL_DEFAULT_SS_MODULE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_default_frag_interleave) = SCTPCTL_DEFAULT_FRAG_INTERLEAVE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_mobility_base) = SCTPCTL_MOBILITY_BASE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_mobility_fasthandoff) = SCTPCTL_MOBILITY_FASTHANDOFF_DEFAULT;
SCTP_BASE_SYSCTL(sctp_vtag_time_wait) = SCTPCTL_TIME_WAIT_DEFAULT;
SCTP_BASE_SYSCTL(sctp_buffer_splitting) = SCTPCTL_BUFFER_SPLITTING_DEFAULT;
SCTP_BASE_SYSCTL(sctp_initial_cwnd) = SCTPCTL_INITIAL_CWND_DEFAULT;
#if defined(SCTP_LOCAL_TRACE_BUF)
memset(&SCTP_BASE_SYSCTL(sctp_log), 0, sizeof(struct sctp_log));
#endif
SCTP_BASE_SYSCTL(sctp_udp_tunneling_for_client_enable) = SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_udp_tunneling_port) = SCTPCTL_UDP_TUNNELING_PORT_DEFAULT;
SCTP_BASE_SYSCTL(sctp_enable_sack_immediately) = SCTPCTL_SACK_IMMEDIATELY_ENABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly) = SCTPCTL_NAT_FRIENDLY_INITS_DEFAULT;
#if defined(SCTP_DEBUG)
SCTP_BASE_SYSCTL(sctp_debug_on) = SCTPCTL_DEBUG_DEFAULT;
#endif
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_BASE_SYSCTL(sctp_output_unlocked) = SCTPCTL_OUTPUT_UNLOCKED_DEFAULT;
#endif
}
/* It returns an upper limit. No filtering is done here */
static unsigned int
number_of_addresses(struct sctp_inpcb *inp)
{
int cnt;
struct sctp_vrf *vrf;
struct sctp_ifn *sctp_ifn;
struct sctp_ifa *sctp_ifa;
struct sctp_laddr *laddr;
cnt = 0;
/* neither Mac OS X nor FreeBSD support mulitple routing functions */
if ((vrf = sctp_find_vrf(inp->def_vrf_id)) == NULL) {
return (0);
}
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
if ((sctp_ifa->address.sa.sa_family == AF_INET) ||
(sctp_ifa->address.sa.sa_family == AF_INET6)) {
cnt++;
}
}
}
} else {
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
if ((laddr->ifa->address.sa.sa_family == AF_INET) ||
(laddr->ifa->address.sa.sa_family == AF_INET6)) {
cnt++;
}
}
}
return (cnt);
}
static int
copy_out_local_addresses(struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sysctl_req *req)
{
struct sctp_ifn *sctp_ifn;
struct sctp_ifa *sctp_ifa;
int loopback_scope, ipv4_local_scope, local_scope, site_scope;
int ipv4_addr_legal, ipv6_addr_legal;
struct sctp_vrf *vrf;
struct xsctp_laddr xladdr;
struct sctp_laddr *laddr;
int error;
/* Turn on all the appropriate scope */
if (stcb) {
/* use association specific values */
loopback_scope = stcb->asoc.loopback_scope;
ipv4_local_scope = stcb->asoc.ipv4_local_scope;
local_scope = stcb->asoc.local_scope;
site_scope = stcb->asoc.site_scope;
} else {
/* use generic values for endpoints */
loopback_scope = 1;
ipv4_local_scope = 1;
local_scope = 1;
site_scope = 1;
}
/* use only address families of interest */
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
ipv6_addr_legal = 1;
if (SCTP_IPV6_V6ONLY(inp)) {
ipv4_addr_legal = 0;
} else {
ipv4_addr_legal = 1;
}
} else {
ipv4_addr_legal = 1;
ipv6_addr_legal = 0;
}
/* neither Mac OS X nor FreeBSD support mulitple routing functions */
if ((vrf = sctp_find_vrf(inp->def_vrf_id)) == NULL) {
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
return (-1);
}
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
if ((loopback_scope == 0) && SCTP_IFN_IS_IFT_LOOP(sctp_ifn))
/* Skip loopback if loopback_scope not set */
continue;
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
if (stcb) {
/*
* ignore if blacklisted at
* association level
*/
if (sctp_is_addr_restricted(stcb, sctp_ifa))
continue;
}
switch (sctp_ifa->address.sa.sa_family) {
case AF_INET:
if (ipv4_addr_legal) {
struct sockaddr_in *sin;
sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
if (sin->sin_addr.s_addr == 0)
continue;
if ((ipv4_local_scope == 0) && (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)))
continue;
} else {
continue;
}
break;
#ifdef INET6
case AF_INET6:
if (ipv6_addr_legal) {
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
continue;
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
if (local_scope == 0)
continue;
if (sin6->sin6_scope_id == 0) {
/*
* bad link
* local
* address
*/
if (sa6_recoverscope(sin6) != 0)
continue;
}
}
if ((site_scope == 0) && (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)))
continue;
} else {
continue;
}
break;
#endif
default:
continue;
}
memset((void *)&xladdr, 0, sizeof(struct xsctp_laddr));
memcpy((void *)&xladdr.address, (const void *)&sctp_ifa->address, sizeof(union sctp_sockstore));
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
error = SYSCTL_OUT(req, &xladdr, sizeof(struct xsctp_laddr));
if (error) {
return (error);
} else {
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
}
}
}
} else {
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
/* ignore if blacklisted at association level */
if (stcb && sctp_is_addr_restricted(stcb, laddr->ifa))
continue;
memset((void *)&xladdr, 0, sizeof(struct xsctp_laddr));
memcpy((void *)&xladdr.address, (const void *)&laddr->ifa->address, sizeof(union sctp_sockstore));
xladdr.start_time.tv_sec = (uint32_t) laddr->start_time.tv_sec;
xladdr.start_time.tv_usec = (uint32_t) laddr->start_time.tv_usec;
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
error = SYSCTL_OUT(req, &xladdr, sizeof(struct xsctp_laddr));
if (error) {
return (error);
} else {
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
}
}
}
memset((void *)&xladdr, 0, sizeof(struct xsctp_laddr));
xladdr.last = 1;
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
error = SYSCTL_OUT(req, &xladdr, sizeof(struct xsctp_laddr));
if (error) {
return (error);
} else {
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
return (0);
}
}
/*
* sysctl functions
*/
static int
sctp_assoclist(SYSCTL_HANDLER_ARGS)
{
unsigned int number_of_endpoints;
unsigned int number_of_local_addresses;
unsigned int number_of_associations;
unsigned int number_of_remote_addresses;
unsigned int n;
int error;
struct sctp_inpcb *inp;
struct sctp_tcb *stcb;
struct sctp_nets *net;
struct xsctp_inpcb xinpcb;
struct xsctp_tcb xstcb;
struct xsctp_raddr xraddr;
struct socket *so;
number_of_endpoints = 0;
number_of_local_addresses = 0;
number_of_associations = 0;
number_of_remote_addresses = 0;
SCTP_INP_INFO_RLOCK();
if (req->oldptr == USER_ADDR_NULL) {
LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) {
SCTP_INP_RLOCK(inp);
number_of_endpoints++;
number_of_local_addresses += number_of_addresses(inp);
LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
number_of_associations++;
number_of_local_addresses += number_of_addresses(inp);
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
number_of_remote_addresses++;
}
}
SCTP_INP_RUNLOCK(inp);
}
SCTP_INP_INFO_RUNLOCK();
n = (number_of_endpoints + 1) * sizeof(struct xsctp_inpcb) +
(number_of_local_addresses + number_of_endpoints + number_of_associations) * sizeof(struct xsctp_laddr) +
(number_of_associations + number_of_endpoints) * sizeof(struct xsctp_tcb) +
(number_of_remote_addresses + number_of_associations) * sizeof(struct xsctp_raddr);
/* request some more memory than needed */
req->oldidx = (n + n / 8);
return 0;
}
if (req->newptr != USER_ADDR_NULL) {
SCTP_INP_INFO_RUNLOCK();
SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_SYSCTL, EPERM);
return EPERM;
}
LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) {
SCTP_INP_RLOCK(inp);
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) {
/* if its allgone it is being freed - skip it */
goto skip;
}
xinpcb.last = 0;
xinpcb.local_port = ntohs(inp->sctp_lport);
xinpcb.flags = inp->sctp_flags;
xinpcb.features = inp->sctp_features;
xinpcb.total_sends = inp->total_sends;
xinpcb.total_recvs = inp->total_recvs;
xinpcb.total_nospaces = inp->total_nospaces;
xinpcb.fragmentation_point = inp->sctp_frag_point;
so = inp->sctp_socket;
if ((so == NULL) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
xinpcb.qlen = 0;
xinpcb.maxqlen = 0;
} else {
xinpcb.qlen = so->so_qlen;
xinpcb.maxqlen = so->so_qlimit;
}
SCTP_INP_INCR_REF(inp);
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
error = SYSCTL_OUT(req, &xinpcb, sizeof(struct xsctp_inpcb));
if (error) {
SCTP_INP_DECR_REF(inp);
return error;
}
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
error = copy_out_local_addresses(inp, NULL, req);
if (error) {
SCTP_INP_DECR_REF(inp);
return error;
}
LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
SCTP_TCB_LOCK(stcb);
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
xstcb.last = 0;
xstcb.local_port = ntohs(inp->sctp_lport);
xstcb.remote_port = ntohs(stcb->rport);
if (stcb->asoc.primary_destination != NULL)
xstcb.primary_addr = stcb->asoc.primary_destination->ro._l_addr;
xstcb.heartbeat_interval = stcb->asoc.heart_beat_delay;
xstcb.state = SCTP_GET_STATE(&stcb->asoc); /* FIXME */
/* 7.0 does not support these */
xstcb.assoc_id = sctp_get_associd(stcb);
xstcb.peers_rwnd = stcb->asoc.peers_rwnd;
xstcb.in_streams = stcb->asoc.streamincnt;
xstcb.out_streams = stcb->asoc.streamoutcnt;
xstcb.max_nr_retrans = stcb->asoc.overall_error_count;
xstcb.primary_process = 0; /* not really supported
* yet */
xstcb.T1_expireries = stcb->asoc.timoinit + stcb->asoc.timocookie;
xstcb.T2_expireries = stcb->asoc.timoshutdown + stcb->asoc.timoshutdownack;
xstcb.retransmitted_tsns = stcb->asoc.marked_retrans;
xstcb.start_time.tv_sec = (uint32_t) stcb->asoc.start_time.tv_sec;
xstcb.start_time.tv_usec = (uint32_t) stcb->asoc.start_time.tv_usec;
xstcb.discontinuity_time.tv_sec = (uint32_t) stcb->asoc.discontinuity_time.tv_sec;
xstcb.discontinuity_time.tv_usec = (uint32_t) stcb->asoc.discontinuity_time.tv_usec;
xstcb.total_sends = stcb->total_sends;
xstcb.total_recvs = stcb->total_recvs;
xstcb.local_tag = stcb->asoc.my_vtag;
xstcb.remote_tag = stcb->asoc.peer_vtag;
xstcb.initial_tsn = stcb->asoc.init_seq_number;
xstcb.highest_tsn = stcb->asoc.sending_seq - 1;
xstcb.cumulative_tsn = stcb->asoc.last_acked_seq;
xstcb.cumulative_tsn_ack = stcb->asoc.cumulative_tsn;
xstcb.mtu = stcb->asoc.smallest_mtu;
xstcb.refcnt = stcb->asoc.refcnt;
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
error = SYSCTL_OUT(req, &xstcb, sizeof(struct xsctp_tcb));
if (error) {
SCTP_INP_DECR_REF(inp);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return error;
}
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
error = copy_out_local_addresses(inp, stcb, req);
if (error) {
SCTP_INP_DECR_REF(inp);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return error;
}
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
xraddr.last = 0;
xraddr.address = net->ro._l_addr;
xraddr.active = ((net->dest_state & SCTP_ADDR_REACHABLE) == SCTP_ADDR_REACHABLE);
xraddr.confirmed = ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0);
xraddr.heartbeat_enabled = ((net->dest_state & SCTP_ADDR_NOHB) == 0);
xraddr.rto = net->RTO;
xraddr.max_path_rtx = net->failure_threshold;
xraddr.rtx = net->marked_retrans;
xraddr.error_counter = net->error_count;
xraddr.cwnd = net->cwnd;
xraddr.flight_size = net->flight_size;
xraddr.mtu = net->mtu;
xraddr.rtt = net->rtt;
xraddr.start_time.tv_sec = (uint32_t) net->start_time.tv_sec;
xraddr.start_time.tv_usec = (uint32_t) net->start_time.tv_usec;
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
error = SYSCTL_OUT(req, &xraddr, sizeof(struct xsctp_raddr));
if (error) {
SCTP_INP_DECR_REF(inp);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return error;
}
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
}
atomic_subtract_int(&stcb->asoc.refcnt, 1);
memset((void *)&xraddr, 0, sizeof(struct xsctp_raddr));
xraddr.last = 1;
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
error = SYSCTL_OUT(req, &xraddr, sizeof(struct xsctp_raddr));
if (error) {
SCTP_INP_DECR_REF(inp);
return error;
}
SCTP_INP_INFO_RLOCK();
SCTP_INP_RLOCK(inp);
}
SCTP_INP_DECR_REF(inp);
SCTP_INP_RUNLOCK(inp);
SCTP_INP_INFO_RUNLOCK();
memset((void *)&xstcb, 0, sizeof(struct xsctp_tcb));
xstcb.last = 1;
error = SYSCTL_OUT(req, &xstcb, sizeof(struct xsctp_tcb));
if (error) {
return error;
}
skip:
SCTP_INP_INFO_RLOCK();
}
SCTP_INP_INFO_RUNLOCK();
memset((void *)&xinpcb, 0, sizeof(struct xsctp_inpcb));
xinpcb.last = 1;
error = SYSCTL_OUT(req, &xinpcb, sizeof(struct xsctp_inpcb));
return error;
}
#define RANGECHK(var, min, max) \
if ((var) < (min)) { (var) = (min); } \
else if ((var) > (max)) { (var) = (max); }
static int
sysctl_sctp_udp_tunneling_check(SYSCTL_HANDLER_ARGS)
{
int error;
uint32_t old_sctp_udp_tunneling_port;
SCTP_INP_INFO_RLOCK();
old_sctp_udp_tunneling_port = SCTP_BASE_SYSCTL(sctp_udp_tunneling_port);
SCTP_INP_INFO_RUNLOCK();
error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
if (error == 0) {
RANGECHK(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port), SCTPCTL_UDP_TUNNELING_PORT_MIN, SCTPCTL_UDP_TUNNELING_PORT_MAX);
if (old_sctp_udp_tunneling_port == SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)) {
error = 0;
goto out;
}
SCTP_INP_INFO_WLOCK();
if (old_sctp_udp_tunneling_port) {
sctp_over_udp_stop();
}
if (SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)) {
if (sctp_over_udp_start()) {
SCTP_BASE_SYSCTL(sctp_udp_tunneling_port) = 0;
}
}
SCTP_INP_INFO_WUNLOCK();
}
out:
return (error);
}
static int
sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
{
int error;
+#ifdef VIMAGE
+ error = vnet_sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
+#else
error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
+#endif
if (error == 0) {
RANGECHK(SCTP_BASE_SYSCTL(sctp_sendspace), SCTPCTL_MAXDGRAM_MIN, SCTPCTL_MAXDGRAM_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_recvspace), SCTPCTL_RECVSPACE_MIN, SCTPCTL_RECVSPACE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_auto_asconf), SCTPCTL_AUTOASCONF_MIN, SCTPCTL_AUTOASCONF_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_ecn_enable), SCTPCTL_ECN_ENABLE_MIN, SCTPCTL_ECN_ENABLE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_strict_sacks), SCTPCTL_STRICT_SACKS_MIN, SCTPCTL_STRICT_SACKS_MAX);
#if !defined(SCTP_WITH_NO_CSUM)
RANGECHK(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback), SCTPCTL_LOOPBACK_NOCSUM_MIN, SCTPCTL_LOOPBACK_NOCSUM_MAX);
#endif
RANGECHK(SCTP_BASE_SYSCTL(sctp_strict_init), SCTPCTL_STRICT_INIT_MIN, SCTPCTL_STRICT_INIT_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_peer_chunk_oh), SCTPCTL_PEER_CHKOH_MIN, SCTPCTL_PEER_CHKOH_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_max_burst_default), SCTPCTL_MAXBURST_MIN, SCTPCTL_MAXBURST_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_fr_max_burst_default), SCTPCTL_FRMAXBURST_MIN, SCTPCTL_FRMAXBURST_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue), SCTPCTL_MAXCHUNKS_MIN, SCTPCTL_MAXCHUNKS_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_hashtblsize), SCTPCTL_TCBHASHSIZE_MIN, SCTPCTL_TCBHASHSIZE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_pcbtblsize), SCTPCTL_PCBHASHSIZE_MIN, SCTPCTL_PCBHASHSIZE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_min_split_point), SCTPCTL_MIN_SPLIT_POINT_MIN, SCTPCTL_MIN_SPLIT_POINT_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_chunkscale), SCTPCTL_CHUNKSCALE_MIN, SCTPCTL_CHUNKSCALE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_delayed_sack_time_default), SCTPCTL_DELAYED_SACK_TIME_MIN, SCTPCTL_DELAYED_SACK_TIME_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_sack_freq_default), SCTPCTL_SACK_FREQ_MIN, SCTPCTL_SACK_FREQ_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_system_free_resc_limit), SCTPCTL_SYS_RESOURCE_MIN, SCTPCTL_SYS_RESOURCE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_asoc_free_resc_limit), SCTPCTL_ASOC_RESOURCE_MIN, SCTPCTL_ASOC_RESOURCE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_heartbeat_interval_default), SCTPCTL_HEARTBEAT_INTERVAL_MIN, SCTPCTL_HEARTBEAT_INTERVAL_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_pmtu_raise_time_default), SCTPCTL_PMTU_RAISE_TIME_MIN, SCTPCTL_PMTU_RAISE_TIME_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_shutdown_guard_time_default), SCTPCTL_SHUTDOWN_GUARD_TIME_MIN, SCTPCTL_SHUTDOWN_GUARD_TIME_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_secret_lifetime_default), SCTPCTL_SECRET_LIFETIME_MIN, SCTPCTL_SECRET_LIFETIME_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_rto_max_default), SCTPCTL_RTO_MAX_MIN, SCTPCTL_RTO_MAX_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_rto_min_default), SCTPCTL_RTO_MIN_MIN, SCTPCTL_RTO_MIN_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_rto_initial_default), SCTPCTL_RTO_INITIAL_MIN, SCTPCTL_RTO_INITIAL_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_init_rto_max_default), SCTPCTL_INIT_RTO_MAX_MIN, SCTPCTL_INIT_RTO_MAX_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_valid_cookie_life_default), SCTPCTL_VALID_COOKIE_LIFE_MIN, SCTPCTL_VALID_COOKIE_LIFE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_init_rtx_max_default), SCTPCTL_INIT_RTX_MAX_MIN, SCTPCTL_INIT_RTX_MAX_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_assoc_rtx_max_default), SCTPCTL_ASSOC_RTX_MAX_MIN, SCTPCTL_ASSOC_RTX_MAX_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_path_rtx_max_default), SCTPCTL_PATH_RTX_MAX_MIN, SCTPCTL_PATH_RTX_MAX_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_add_more_threshold), SCTPCTL_ADD_MORE_ON_OUTPUT_MIN, SCTPCTL_ADD_MORE_ON_OUTPUT_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default), SCTPCTL_OUTGOING_STREAMS_MIN, SCTPCTL_OUTGOING_STREAMS_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_cmt_on_off), SCTPCTL_CMT_ON_OFF_MIN, SCTPCTL_CMT_ON_OFF_MAX);
/* EY */
RANGECHK(SCTP_BASE_SYSCTL(sctp_nr_sack_on_off), SCTPCTL_NR_SACK_ON_OFF_MIN, SCTPCTL_NR_SACK_ON_OFF_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_cmt_use_dac), SCTPCTL_CMT_USE_DAC_MIN, SCTPCTL_CMT_USE_DAC_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_cmt_pf), SCTPCTL_CMT_PF_MIN, SCTPCTL_CMT_PF_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst), SCTPCTL_CWND_MAXBURST_MIN, SCTPCTL_CWND_MAXBURST_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_early_fr), SCTPCTL_EARLY_FAST_RETRAN_MIN, SCTPCTL_EARLY_FAST_RETRAN_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_early_fr_msec), SCTPCTL_EARLY_FAST_RETRAN_MSEC_MIN, SCTPCTL_EARLY_FAST_RETRAN_MSEC_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_asconf_auth_nochk), SCTPCTL_ASCONF_AUTH_NOCHK_MIN, SCTPCTL_ASCONF_AUTH_NOCHK_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_auth_disable), SCTPCTL_AUTH_DISABLE_MIN, SCTPCTL_AUTH_DISABLE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_nat_friendly), SCTPCTL_NAT_FRIENDLY_MIN, SCTPCTL_NAT_FRIENDLY_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_L2_abc_variable), SCTPCTL_ABC_L_VAR_MIN, SCTPCTL_ABC_L_VAR_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count), SCTPCTL_MAX_CHAINED_MBUFS_MIN, SCTPCTL_MAX_CHAINED_MBUFS_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_do_drain), SCTPCTL_DO_SCTP_DRAIN_MIN, SCTPCTL_DO_SCTP_DRAIN_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_hb_maxburst), SCTPCTL_HB_MAX_BURST_MIN, SCTPCTL_HB_MAX_BURST_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit), SCTPCTL_ABORT_AT_LIMIT_MIN, SCTPCTL_ABORT_AT_LIMIT_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_strict_data_order), SCTPCTL_STRICT_DATA_ORDER_MIN, SCTPCTL_STRICT_DATA_ORDER_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_min_residual), SCTPCTL_MIN_RESIDUAL_MIN, SCTPCTL_MIN_RESIDUAL_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_max_retran_chunk), SCTPCTL_MAX_RETRAN_CHUNK_MIN, SCTPCTL_MAX_RETRAN_CHUNK_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_logging_level), SCTPCTL_LOGGING_LEVEL_MIN, SCTPCTL_LOGGING_LEVEL_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_default_cc_module), SCTPCTL_DEFAULT_CC_MODULE_MIN, SCTPCTL_DEFAULT_CC_MODULE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_default_ss_module), SCTPCTL_DEFAULT_SS_MODULE_MIN, SCTPCTL_DEFAULT_SS_MODULE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_default_frag_interleave), SCTPCTL_DEFAULT_FRAG_INTERLEAVE_MIN, SCTPCTL_DEFAULT_FRAG_INTERLEAVE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_vtag_time_wait), SCTPCTL_TIME_WAIT_MIN, SCTPCTL_TIME_WAIT_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_buffer_splitting), SCTPCTL_BUFFER_SPLITTING_MIN, SCTPCTL_BUFFER_SPLITTING_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_initial_cwnd), SCTPCTL_INITIAL_CWND_MIN, SCTPCTL_INITIAL_CWND_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_mobility_base), SCTPCTL_MOBILITY_BASE_MIN, SCTPCTL_MOBILITY_BASE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_mobility_fasthandoff), SCTPCTL_MOBILITY_FASTHANDOFF_MIN, SCTPCTL_MOBILITY_FASTHANDOFF_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_udp_tunneling_for_client_enable), SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_MIN, SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_enable_sack_immediately), SCTPCTL_SACK_IMMEDIATELY_ENABLE_MIN, SCTPCTL_SACK_IMMEDIATELY_ENABLE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly), SCTPCTL_NAT_FRIENDLY_INITS_MIN, SCTPCTL_NAT_FRIENDLY_INITS_MAX);
#ifdef SCTP_DEBUG
RANGECHK(SCTP_BASE_SYSCTL(sctp_debug_on), SCTPCTL_DEBUG_MIN, SCTPCTL_DEBUG_MAX);
#endif
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
RANGECHK(SCTP_BASE_SYSCTL(sctp_output_unlocked), SCTPCTL_OUTPUT_UNLOCKED_MIN, SCTPCTL_OUTPUT_UNLOCKED_MAX);
#endif
}
return (error);
}
#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT)
static int
sysctl_stat_get(SYSCTL_HANDLER_ARGS)
{
int cpu, error;
struct sctpstat sb, *sarry, *cpin = NULL;
if ((req->newptr) && (req->newlen == sizeof(struct sctpstat))) {
/*
* User wants us to clear or at least reset the counters to
* the specified values.
*/
cpin = (struct sctpstat *)req->newptr;
} else if (req->newptr) {
/* Must be a stat structure */
return (EINVAL);
}
memset(&sb, 0, sizeof(sb));
for (cpu = 0; cpu < mp_maxid; cpu++) {
sarry = &SCTP_BASE_STATS[cpu];
if (sarry->sctps_discontinuitytime.tv_sec > sb.sctps_discontinuitytime.tv_sec) {
sb.sctps_discontinuitytime.tv_sec = sarry->sctps_discontinuitytime.tv_sec;
sb.sctps_discontinuitytime.tv_usec = sarry->sctps_discontinuitytime.tv_usec;
}
sb.sctps_currestab += sarry->sctps_currestab;
sb.sctps_activeestab += sarry->sctps_activeestab;
sb.sctps_restartestab += sarry->sctps_restartestab;
sb.sctps_collisionestab += sarry->sctps_collisionestab;
sb.sctps_passiveestab += sarry->sctps_passiveestab;
sb.sctps_aborted += sarry->sctps_aborted;
sb.sctps_shutdown += sarry->sctps_shutdown;
sb.sctps_outoftheblue += sarry->sctps_outoftheblue;
sb.sctps_checksumerrors += sarry->sctps_checksumerrors;
sb.sctps_outcontrolchunks += sarry->sctps_outcontrolchunks;
sb.sctps_outorderchunks += sarry->sctps_outorderchunks;
sb.sctps_outunorderchunks += sarry->sctps_outunorderchunks;
sb.sctps_incontrolchunks += sarry->sctps_incontrolchunks;
sb.sctps_inorderchunks += sarry->sctps_inorderchunks;
sb.sctps_inunorderchunks += sarry->sctps_inunorderchunks;
sb.sctps_fragusrmsgs += sarry->sctps_fragusrmsgs;
sb.sctps_reasmusrmsgs += sarry->sctps_reasmusrmsgs;
sb.sctps_outpackets += sarry->sctps_outpackets;
sb.sctps_inpackets += sarry->sctps_inpackets;
sb.sctps_recvpackets += sarry->sctps_recvpackets;
sb.sctps_recvdatagrams += sarry->sctps_recvdatagrams;
sb.sctps_recvpktwithdata += sarry->sctps_recvpktwithdata;
sb.sctps_recvsacks += sarry->sctps_recvsacks;
sb.sctps_recvdata += sarry->sctps_recvdata;
sb.sctps_recvdupdata += sarry->sctps_recvdupdata;
sb.sctps_recvheartbeat += sarry->sctps_recvheartbeat;
sb.sctps_recvheartbeatack += sarry->sctps_recvheartbeatack;
sb.sctps_recvecne += sarry->sctps_recvecne;
sb.sctps_recvauth += sarry->sctps_recvauth;
sb.sctps_recvauthmissing += sarry->sctps_recvauthmissing;
sb.sctps_recvivalhmacid += sarry->sctps_recvivalhmacid;
sb.sctps_recvivalkeyid += sarry->sctps_recvivalkeyid;
sb.sctps_recvauthfailed += sarry->sctps_recvauthfailed;
sb.sctps_recvexpress += sarry->sctps_recvexpress;
sb.sctps_recvexpressm += sarry->sctps_recvexpressm;
sb.sctps_recvnocrc += sarry->sctps_recvnocrc;
sb.sctps_recvswcrc += sarry->sctps_recvswcrc;
sb.sctps_recvhwcrc += sarry->sctps_recvhwcrc;
sb.sctps_sendpackets += sarry->sctps_sendpackets;
sb.sctps_sendsacks += sarry->sctps_sendsacks;
sb.sctps_senddata += sarry->sctps_senddata;
sb.sctps_sendretransdata += sarry->sctps_sendretransdata;
sb.sctps_sendfastretrans += sarry->sctps_sendfastretrans;
sb.sctps_sendmultfastretrans += sarry->sctps_sendmultfastretrans;
sb.sctps_sendheartbeat += sarry->sctps_sendheartbeat;
sb.sctps_sendecne += sarry->sctps_sendecne;
sb.sctps_sendauth += sarry->sctps_sendauth;
sb.sctps_senderrors += sarry->sctps_senderrors;
sb.sctps_sendnocrc += sarry->sctps_sendnocrc;
sb.sctps_sendswcrc += sarry->sctps_sendswcrc;
sb.sctps_sendhwcrc += sarry->sctps_sendhwcrc;
sb.sctps_pdrpfmbox += sarry->sctps_pdrpfmbox;
sb.sctps_pdrpfehos += sarry->sctps_pdrpfehos;
sb.sctps_pdrpmbda += sarry->sctps_pdrpmbda;
sb.sctps_pdrpmbct += sarry->sctps_pdrpmbct;
sb.sctps_pdrpbwrpt += sarry->sctps_pdrpbwrpt;
sb.sctps_pdrpcrupt += sarry->sctps_pdrpcrupt;
sb.sctps_pdrpnedat += sarry->sctps_pdrpnedat;
sb.sctps_pdrppdbrk += sarry->sctps_pdrppdbrk;
sb.sctps_pdrptsnnf += sarry->sctps_pdrptsnnf;
sb.sctps_pdrpdnfnd += sarry->sctps_pdrpdnfnd;
sb.sctps_pdrpdiwnp += sarry->sctps_pdrpdiwnp;
sb.sctps_pdrpdizrw += sarry->sctps_pdrpdizrw;
sb.sctps_pdrpbadd += sarry->sctps_pdrpbadd;
sb.sctps_pdrpmark += sarry->sctps_pdrpmark;
sb.sctps_timoiterator += sarry->sctps_timoiterator;
sb.sctps_timodata += sarry->sctps_timodata;
sb.sctps_timowindowprobe += sarry->sctps_timowindowprobe;
sb.sctps_timoinit += sarry->sctps_timoinit;
sb.sctps_timosack += sarry->sctps_timosack;
sb.sctps_timoshutdown += sarry->sctps_timoshutdown;
sb.sctps_timoheartbeat += sarry->sctps_timoheartbeat;
sb.sctps_timocookie += sarry->sctps_timocookie;
sb.sctps_timosecret += sarry->sctps_timosecret;
sb.sctps_timopathmtu += sarry->sctps_timopathmtu;
sb.sctps_timoshutdownack += sarry->sctps_timoshutdownack;
sb.sctps_timoshutdownguard += sarry->sctps_timoshutdownguard;
sb.sctps_timostrmrst += sarry->sctps_timostrmrst;
sb.sctps_timoearlyfr += sarry->sctps_timoearlyfr;
sb.sctps_timoasconf += sarry->sctps_timoasconf;
sb.sctps_timodelprim += sarry->sctps_timodelprim;
sb.sctps_timoautoclose += sarry->sctps_timoautoclose;
sb.sctps_timoassockill += sarry->sctps_timoassockill;
sb.sctps_timoinpkill += sarry->sctps_timoinpkill;
sb.sctps_earlyfrstart += sarry->sctps_earlyfrstart;
sb.sctps_earlyfrstop += sarry->sctps_earlyfrstop;
sb.sctps_earlyfrmrkretrans += sarry->sctps_earlyfrmrkretrans;
sb.sctps_earlyfrstpout += sarry->sctps_earlyfrstpout;
sb.sctps_earlyfrstpidsck1 += sarry->sctps_earlyfrstpidsck1;
sb.sctps_earlyfrstpidsck2 += sarry->sctps_earlyfrstpidsck2;
sb.sctps_earlyfrstpidsck3 += sarry->sctps_earlyfrstpidsck3;
sb.sctps_earlyfrstpidsck4 += sarry->sctps_earlyfrstpidsck4;
sb.sctps_earlyfrstrid += sarry->sctps_earlyfrstrid;
sb.sctps_earlyfrstrout += sarry->sctps_earlyfrstrout;
sb.sctps_earlyfrstrtmr += sarry->sctps_earlyfrstrtmr;
sb.sctps_hdrops += sarry->sctps_hdrops;
sb.sctps_badsum += sarry->sctps_badsum;
sb.sctps_noport += sarry->sctps_noport;
sb.sctps_badvtag += sarry->sctps_badvtag;
sb.sctps_badsid += sarry->sctps_badsid;
sb.sctps_nomem += sarry->sctps_nomem;
sb.sctps_fastretransinrtt += sarry->sctps_fastretransinrtt;
sb.sctps_markedretrans += sarry->sctps_markedretrans;
sb.sctps_naglesent += sarry->sctps_naglesent;
sb.sctps_naglequeued += sarry->sctps_naglequeued;
sb.sctps_maxburstqueued += sarry->sctps_maxburstqueued;
sb.sctps_ifnomemqueued += sarry->sctps_ifnomemqueued;
sb.sctps_windowprobed += sarry->sctps_windowprobed;
sb.sctps_lowlevelerr += sarry->sctps_lowlevelerr;
sb.sctps_lowlevelerrusr += sarry->sctps_lowlevelerrusr;
sb.sctps_datadropchklmt += sarry->sctps_datadropchklmt;
sb.sctps_datadroprwnd += sarry->sctps_datadroprwnd;
sb.sctps_ecnereducedcwnd += sarry->sctps_ecnereducedcwnd;
sb.sctps_vtagexpress += sarry->sctps_vtagexpress;
sb.sctps_vtagbogus += sarry->sctps_vtagbogus;
sb.sctps_primary_randry += sarry->sctps_primary_randry;
sb.sctps_cmt_randry += sarry->sctps_cmt_randry;
sb.sctps_slowpath_sack += sarry->sctps_slowpath_sack;
sb.sctps_wu_sacks_sent += sarry->sctps_wu_sacks_sent;
sb.sctps_sends_with_flags += sarry->sctps_sends_with_flags;
sb.sctps_sends_with_unord += sarry->sctps_sends_with_unord;
sb.sctps_sends_with_eof += sarry->sctps_sends_with_eof;
sb.sctps_sends_with_abort += sarry->sctps_sends_with_abort;
sb.sctps_protocol_drain_calls += sarry->sctps_protocol_drain_calls;
sb.sctps_protocol_drains_done += sarry->sctps_protocol_drains_done;
sb.sctps_read_peeks += sarry->sctps_read_peeks;
sb.sctps_cached_chk += sarry->sctps_cached_chk;
sb.sctps_cached_strmoq += sarry->sctps_cached_strmoq;
sb.sctps_left_abandon += sarry->sctps_left_abandon;
sb.sctps_send_burst_avoid += sarry->sctps_send_burst_avoid;
sb.sctps_send_cwnd_avoid += sarry->sctps_send_cwnd_avoid;
sb.sctps_fwdtsn_map_over += sarry->sctps_fwdtsn_map_over;
if (cpin) {
memcpy(sarry, cpin, sizeof(struct sctpstat));
}
}
error = SYSCTL_OUT(req, &sb, sizeof(sb));
return (error);
}
#endif
#if defined(SCTP_LOCAL_TRACE_BUF)
static int
sysctl_sctp_cleartrace(SYSCTL_HANDLER_ARGS)
{
int error = 0;
memset(&SCTP_BASE_SYSCTL(sctp_log), 0, sizeof(struct sctp_log));
return (error);
}
#endif
/*
* sysctl definitions
*/
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, sendspace, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, sendspace, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_sendspace), 0, sysctl_sctp_check, "IU",
SCTPCTL_MAXDGRAM_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, recvspace, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, recvspace, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_recvspace), 0, sysctl_sctp_check, "IU",
SCTPCTL_RECVSPACE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, auto_asconf, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, auto_asconf, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_auto_asconf), 0, sysctl_sctp_check, "IU",
SCTPCTL_AUTOASCONF_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, ecn_enable, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, ecn_enable, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_ecn_enable), 0, sysctl_sctp_check, "IU",
SCTPCTL_ECN_ENABLE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, strict_sacks, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, strict_sacks, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_strict_sacks), 0, sysctl_sctp_check, "IU",
SCTPCTL_STRICT_SACKS_DESC);
#if !defined(SCTP_WITH_NO_CSUM)
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, loopback_nocsum, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, loopback_nocsum, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback), 0, sysctl_sctp_check, "IU",
SCTPCTL_LOOPBACK_NOCSUM_DESC);
#endif
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, strict_init, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, strict_init, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_strict_init), 0, sysctl_sctp_check, "IU",
SCTPCTL_STRICT_INIT_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, peer_chkoh, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, peer_chkoh, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_peer_chunk_oh), 0, sysctl_sctp_check, "IU",
SCTPCTL_PEER_CHKOH_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, maxburst, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, maxburst, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_max_burst_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_MAXBURST_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, fr_maxburst, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, fr_maxburst, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_fr_max_burst_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_FRMAXBURST_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, maxchunks, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, maxchunks, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue), 0, sysctl_sctp_check, "IU",
SCTPCTL_MAXCHUNKS_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, tcbhashsize, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, tcbhashsize, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_hashtblsize), 0, sysctl_sctp_check, "IU",
SCTPCTL_TCBHASHSIZE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, pcbhashsize, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, pcbhashsize, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_pcbtblsize), 0, sysctl_sctp_check, "IU",
SCTPCTL_PCBHASHSIZE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, min_split_point, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, min_split_point, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_min_split_point), 0, sysctl_sctp_check, "IU",
SCTPCTL_MIN_SPLIT_POINT_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, chunkscale, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, chunkscale, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_chunkscale), 0, sysctl_sctp_check, "IU",
SCTPCTL_CHUNKSCALE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, delayed_sack_time, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, delayed_sack_time, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_delayed_sack_time_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_DELAYED_SACK_TIME_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, sack_freq, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, sack_freq, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_sack_freq_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_SACK_FREQ_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, sys_resource, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, sys_resource, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_system_free_resc_limit), 0, sysctl_sctp_check, "IU",
SCTPCTL_SYS_RESOURCE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, asoc_resource, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, asoc_resource, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_asoc_free_resc_limit), 0, sysctl_sctp_check, "IU",
SCTPCTL_ASOC_RESOURCE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, heartbeat_interval, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, heartbeat_interval, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_heartbeat_interval_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_HEARTBEAT_INTERVAL_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, pmtu_raise_time, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, pmtu_raise_time, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_pmtu_raise_time_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_PMTU_RAISE_TIME_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, shutdown_guard_time, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, shutdown_guard_time, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_shutdown_guard_time_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_SHUTDOWN_GUARD_TIME_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, secret_lifetime, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, secret_lifetime, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_secret_lifetime_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_SECRET_LIFETIME_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, rto_max, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rto_max, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_rto_max_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_RTO_MAX_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, rto_min, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rto_min, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_rto_min_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_RTO_MIN_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, rto_initial, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, rto_initial, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_rto_initial_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_RTO_INITIAL_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, init_rto_max, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, init_rto_max, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_init_rto_max_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_INIT_RTO_MAX_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, valid_cookie_life, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, valid_cookie_life, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_valid_cookie_life_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_VALID_COOKIE_LIFE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, init_rtx_max, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, init_rtx_max, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_init_rtx_max_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_INIT_RTX_MAX_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, assoc_rtx_max, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, assoc_rtx_max, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_assoc_rtx_max_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_ASSOC_RTX_MAX_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, path_rtx_max, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, path_rtx_max, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_path_rtx_max_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_PATH_RTX_MAX_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, add_more_on_output, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, add_more_on_output, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_add_more_threshold), 0, sysctl_sctp_check, "IU",
SCTPCTL_ADD_MORE_ON_OUTPUT_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, outgoing_streams, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, outgoing_streams, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_OUTGOING_STREAMS_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, cmt_on_off, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, cmt_on_off, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_cmt_on_off), 0, sysctl_sctp_check, "IU",
SCTPCTL_CMT_ON_OFF_DESC);
-/* EY */
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, nr_sack_on_off, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, nr_sack_on_off, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_nr_sack_on_off), 0, sysctl_sctp_check, "IU",
SCTPCTL_NR_SACK_ON_OFF_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, cmt_use_dac, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, cmt_use_dac, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_cmt_use_dac), 0, sysctl_sctp_check, "IU",
SCTPCTL_CMT_USE_DAC_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, cmt_pf, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, cmt_pf, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_cmt_pf), 0, sysctl_sctp_check, "IU",
SCTPCTL_CMT_PF_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, cwnd_maxburst, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, cwnd_maxburst, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst), 0, sysctl_sctp_check, "IU",
SCTPCTL_CWND_MAXBURST_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, early_fast_retran, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, early_fast_retran, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_early_fr), 0, sysctl_sctp_check, "IU",
SCTPCTL_EARLY_FAST_RETRAN_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, early_fast_retran_msec, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, early_fast_retran_msec, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_early_fr_msec), 0, sysctl_sctp_check, "IU",
SCTPCTL_EARLY_FAST_RETRAN_MSEC_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, asconf_auth_nochk, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, asconf_auth_nochk, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_asconf_auth_nochk), 0, sysctl_sctp_check, "IU",
SCTPCTL_ASCONF_AUTH_NOCHK_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, auth_disable, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, auth_disable, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_auth_disable), 0, sysctl_sctp_check, "IU",
SCTPCTL_AUTH_DISABLE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, nat_friendly, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, nat_friendly, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_nat_friendly), 0, sysctl_sctp_check, "IU",
SCTPCTL_NAT_FRIENDLY_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, abc_l_var, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, abc_l_var, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_L2_abc_variable), 0, sysctl_sctp_check, "IU",
SCTPCTL_ABC_L_VAR_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, max_chained_mbufs, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, max_chained_mbufs, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_mbuf_threshold_count), 0, sysctl_sctp_check, "IU",
SCTPCTL_MAX_CHAINED_MBUFS_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, do_sctp_drain, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, do_sctp_drain, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_do_drain), 0, sysctl_sctp_check, "IU",
SCTPCTL_DO_SCTP_DRAIN_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, hb_max_burst, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, hb_max_burst, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_hb_maxburst), 0, sysctl_sctp_check, "IU",
SCTPCTL_HB_MAX_BURST_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, abort_at_limit, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, abort_at_limit, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit), 0, sysctl_sctp_check, "IU",
SCTPCTL_ABORT_AT_LIMIT_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, strict_data_order, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, strict_data_order, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_strict_data_order), 0, sysctl_sctp_check, "IU",
SCTPCTL_STRICT_DATA_ORDER_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, min_residual, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, min_residual, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_min_residual), 0, sysctl_sctp_check, "IU",
SCTPCTL_MIN_RESIDUAL_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, max_retran_chunk, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, max_retran_chunk, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_max_retran_chunk), 0, sysctl_sctp_check, "IU",
SCTPCTL_MAX_RETRAN_CHUNK_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, log_level, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, log_level, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_logging_level), 0, sysctl_sctp_check, "IU",
SCTPCTL_LOGGING_LEVEL_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, default_cc_module, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, default_cc_module, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_default_cc_module), 0, sysctl_sctp_check, "IU",
SCTPCTL_DEFAULT_CC_MODULE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, default_ss_module, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, default_ss_module, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_default_ss_module), 0, sysctl_sctp_check, "IU",
SCTPCTL_DEFAULT_SS_MODULE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, default_frag_interleave, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, default_frag_interleave, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_default_frag_interleave), 0, sysctl_sctp_check, "IU",
SCTPCTL_DEFAULT_FRAG_INTERLEAVE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, mobility_base, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, mobility_base, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_mobility_base), 0, sysctl_sctp_check, "IU",
SCTPCTL_MOBILITY_BASE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, mobility_fasthandoff, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, mobility_fasthandoff, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_mobility_fasthandoff), 0, sysctl_sctp_check, "IU",
SCTPCTL_MOBILITY_FASTHANDOFF_DESC);
#if defined(SCTP_LOCAL_TRACE_BUF)
-SYSCTL_STRUCT(_net_inet_sctp, OID_AUTO, log, CTLFLAG_RD,
+SYSCTL_VNET_STRUCT(_net_inet_sctp, OID_AUTO, log, CTLFLAG_RD,
&SCTP_BASE_SYSCTL(sctp_log), sctp_log,
"SCTP logging (struct sctp_log)");
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, clear_trace, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, clear_trace, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_log), 0, sysctl_sctp_cleartrace, "IU",
"Clear SCTP Logging buffer");
-
-
-
#endif
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, udp_tunneling_for_client_enable, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, udp_tunneling_for_client_enable, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_udp_tunneling_for_client_enable), 0, sysctl_sctp_check, "IU",
SCTPCTL_UDP_TUNNELING_FOR_CLIENT_ENABLE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, udp_tunneling_port, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, udp_tunneling_port, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_udp_tunneling_port), 0, sysctl_sctp_udp_tunneling_check, "IU",
SCTPCTL_UDP_TUNNELING_PORT_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, enable_sack_immediately, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, enable_sack_immediately, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_enable_sack_immediately), 0, sysctl_sctp_check, "IU",
SCTPCTL_SACK_IMMEDIATELY_ENABLE_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, nat_friendly_init, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, nat_friendly_init, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly), 0, sysctl_sctp_check, "IU",
SCTPCTL_NAT_FRIENDLY_INITS_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, vtag_time_wait, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, vtag_time_wait, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_vtag_time_wait), 0, sysctl_sctp_check, "IU",
SCTPCTL_TIME_WAIT_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, buffer_splitting, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, buffer_splitting, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_buffer_splitting), 0, sysctl_sctp_check, "IU",
SCTPCTL_BUFFER_SPLITTING_DESC);
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, initial_cwnd, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, initial_cwnd, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_initial_cwnd), 0, sysctl_sctp_check, "IU",
SCTPCTL_INITIAL_CWND_DESC);
#ifdef SCTP_DEBUG
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, debug, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, debug, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_debug_on), 0, sysctl_sctp_check, "IU",
SCTPCTL_DEBUG_DESC);
-#endif /* SCTP_DEBUG */
+#endif
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, output_unlocked, CTLTYPE_UINT | CTLFLAG_RW,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, output_unlocked, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_output_unlocked), 0, sysctl_sctp_check, "IU",
SCTPCTL_OUTPUT_UNLOCKED_DESC);
#endif
+
#if defined(__FreeBSD__) && defined(SMP) && defined(SCTP_USE_PERCPU_STAT)
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, stats,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, stats,
CTLTYPE_STRUCT | CTLFLAG_RW,
0, 0, sysctl_stat_get, "S,sctpstat",
"SCTP statistics (struct sctp_stat)");
#else
-SYSCTL_STRUCT(_net_inet_sctp, OID_AUTO, stats, CTLFLAG_RW,
+SYSCTL_VNET_STRUCT(_net_inet_sctp, OID_AUTO, stats, CTLFLAG_RW,
&SCTP_BASE_STATS_SYSCTL, sctpstat,
"SCTP statistics (struct sctp_stat)");
#endif
-SYSCTL_PROC(_net_inet_sctp, OID_AUTO, assoclist, CTLTYPE_OPAQUE | CTLFLAG_RD,
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, assoclist, CTLTYPE_OPAQUE | CTLFLAG_RD,
0, 0, sctp_assoclist,
"S,xassoc", "List of active SCTP associations");
Index: projects/altix/sys/pc98/pc98/machdep.c
===================================================================
--- projects/altix/sys/pc98/pc98/machdep.c (revision 218875)
+++ projects/altix/sys/pc98/pc98/machdep.c (revision 218876)
@@ -1,2956 +1,2962 @@
/*-
* Copyright (c) 1992 Terrence R. Lambert.
* Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_atalk.h"
#include "opt_compat.h"
#include "opt_cpu.h"
#include "opt_ddb.h"
#include "opt_inet.h"
#include "opt_ipx.h"
#include "opt_isa.h"
#include "opt_kstack_pages.h"
#include "opt_maxmem.h"
#include "opt_npx.h"
#include "opt_perfmon.h"
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/bus.h>
#include <sys/callout.h>
#include <sys/cons.h>
#include <sys/cpu.h>
#include <sys/eventhandler.h>
#include <sys/exec.h>
#include <sys/imgact.h>
#include <sys/kdb.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
#include <sys/linker.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/msgbuf.h>
#include <sys/mutex.h>
#include <sys/pcpu.h>
#include <sys/ptrace.h>
#include <sys/reboot.h>
#include <sys/sched.h>
#include <sys/signalvar.h>
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
#include <sys/sysent.h>
#include <sys/sysproto.h>
#include <sys/ucontext.h>
#include <sys/vmmeter.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
#include <vm/vm_kern.h>
#include <vm/vm_page.h>
#include <vm/vm_map.h>
#include <vm/vm_object.h>
#include <vm/vm_pager.h>
#include <vm/vm_param.h>
#ifdef DDB
#ifndef KDB
#error KDB must be enabled in order for DDB to work!
#endif
#include <ddb/ddb.h>
#include <ddb/db_sym.h>
#endif
#include <pc98/pc98/pc98_machdep.h>
#include <net/netisr.h>
#include <machine/bootinfo.h>
#include <machine/clock.h>
#include <machine/cpu.h>
#include <machine/cputypes.h>
#include <machine/intr_machdep.h>
#include <x86/mca.h>
#include <machine/md_var.h>
#include <machine/pc/bios.h>
#include <machine/pcb.h>
#include <machine/pcb_ext.h>
#include <machine/proc.h>
#include <machine/reg.h>
#include <machine/sigframe.h>
#include <machine/specialreg.h>
#include <machine/vm86.h>
#ifdef PERFMON
#include <machine/perfmon.h>
#endif
#ifdef SMP
#include <machine/smp.h>
#endif
#ifdef DEV_ISA
#include <x86/isa/icu.h>
#endif
/* Sanity check for __curthread() */
CTASSERT(offsetof(struct pcpu, pc_curthread) == 0);
extern void init386(int first);
extern void dblfault_handler(void);
extern void printcpuinfo(void); /* XXX header file */
extern void finishidentcpu(void);
extern void panicifcpuunsupported(void);
extern void initializecpu(void);
#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL)
#define EFL_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
#if !defined(CPU_DISABLE_SSE) && defined(I686_CPU)
#define CPU_ENABLE_SSE
#endif
static void cpu_startup(void *);
static void fpstate_drop(struct thread *td);
static void get_fpcontext(struct thread *td, mcontext_t *mcp);
static int set_fpcontext(struct thread *td, const mcontext_t *mcp);
#ifdef CPU_ENABLE_SSE
static void set_fpregs_xmm(struct save87 *, struct savexmm *);
static void fill_fpregs_xmm(struct savexmm *, struct save87 *);
#endif /* CPU_ENABLE_SSE */
SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
int need_pre_dma_flush; /* If 1, use wbinvd befor DMA transfer. */
int need_post_dma_flush; /* If 1, use invd after DMA transfer. */
#ifdef DDB
extern vm_offset_t ksym_start, ksym_end;
#endif
int _udatasel, _ucodesel;
u_int basemem;
static int ispc98 = 1;
SYSCTL_INT(_machdep, OID_AUTO, ispc98, CTLFLAG_RD, &ispc98, 0, "");
int cold = 1;
#ifdef COMPAT_43
static void osendsig(sig_t catcher, ksiginfo_t *, sigset_t *mask);
#endif
#ifdef COMPAT_FREEBSD4
static void freebsd4_sendsig(sig_t catcher, ksiginfo_t *, sigset_t *mask);
#endif
long Maxmem = 0;
long realmem = 0;
/*
* The number of PHYSMAP entries must be one less than the number of
* PHYSSEG entries because the PHYSMAP entry that spans the largest
* physical address that is accessible by ISA DMA is split into two
* PHYSSEG entries.
*/
#define PHYSMAP_SIZE (2 * (VM_PHYSSEG_MAX - 1))
vm_paddr_t phys_avail[PHYSMAP_SIZE + 2];
vm_paddr_t dump_avail[PHYSMAP_SIZE + 2];
/* must be 2 less so 0 0 can signal end of chunks */
#define PHYS_AVAIL_ARRAY_END ((sizeof(phys_avail) / sizeof(phys_avail[0])) - 2)
#define DUMP_AVAIL_ARRAY_END ((sizeof(dump_avail) / sizeof(dump_avail[0])) - 2)
struct kva_md_info kmi;
static struct trapframe proc0_tf;
struct pcpu __pcpu[MAXCPU];
struct mtx icu_lock;
static void
cpu_startup(dummy)
void *dummy;
{
uintmax_t memsize;
/*
* Good {morning,afternoon,evening,night}.
*/
startrtclock();
printcpuinfo();
panicifcpuunsupported();
#ifdef PERFMON
perfmon_init();
#endif
realmem = Maxmem;
/*
* Display physical memory.
*/
memsize = ptoa((uintmax_t)Maxmem);
printf("real memory = %ju (%ju MB)\n", memsize, memsize >> 20);
/*
* Display any holes after the first chunk of extended memory.
*/
if (bootverbose) {
int indx;
printf("Physical memory chunk(s):\n");
for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) {
vm_paddr_t size;
size = phys_avail[indx + 1] - phys_avail[indx];
printf(
"0x%016jx - 0x%016jx, %ju bytes (%ju pages)\n",
(uintmax_t)phys_avail[indx],
(uintmax_t)phys_avail[indx + 1] - 1,
(uintmax_t)size, (uintmax_t)size / PAGE_SIZE);
}
}
vm_ksubmap_init(&kmi);
printf("avail memory = %ju (%ju MB)\n",
ptoa((uintmax_t)cnt.v_free_count),
ptoa((uintmax_t)cnt.v_free_count) / 1048576);
/*
* Set up buffers, so they can be used to read disk labels.
*/
bufinit();
vm_pager_bufferinit();
cpu_setregs();
}
/*
* Send an interrupt to process.
*
* Stack is set up to allow sigcode stored
* at top to call routine, followed by kcall
* to sigreturn routine below. After sigreturn
* resets the signal mask, the stack, and the
* frame pointer, it returns to the user
* specified pc, psl.
*/
#ifdef COMPAT_43
static void
osendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
{
struct osigframe sf, *fp;
struct proc *p;
struct thread *td;
struct sigacts *psp;
struct trapframe *regs;
int sig;
int oonstack;
td = curthread;
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
sig = ksi->ksi_signo;
psp = p->p_sigacts;
mtx_assert(&psp->ps_mtx, MA_OWNED);
regs = td->td_frame;
oonstack = sigonstack(regs->tf_esp);
/* Allocate space for the signal handler context. */
if ((td->td_pflags & TDP_ALTSTACK) && !oonstack &&
SIGISMEMBER(psp->ps_sigonstack, sig)) {
fp = (struct osigframe *)(td->td_sigstk.ss_sp +
td->td_sigstk.ss_size - sizeof(struct osigframe));
#if defined(COMPAT_43)
td->td_sigstk.ss_flags |= SS_ONSTACK;
#endif
} else
fp = (struct osigframe *)regs->tf_esp - 1;
/* Translate the signal if appropriate. */
if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
/* Build the argument list for the signal handler. */
sf.sf_signum = sig;
sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc;
bzero(&sf.sf_siginfo, sizeof(sf.sf_siginfo));
if (SIGISMEMBER(psp->ps_siginfo, sig)) {
/* Signal handler installed with SA_SIGINFO. */
sf.sf_arg2 = (register_t)&fp->sf_siginfo;
sf.sf_siginfo.si_signo = sig;
sf.sf_siginfo.si_code = ksi->ksi_code;
sf.sf_ahu.sf_action = (__osiginfohandler_t *)catcher;
sf.sf_addr = 0;
} else {
/* Old FreeBSD-style arguments. */
sf.sf_arg2 = ksi->ksi_code;
sf.sf_addr = (register_t)ksi->ksi_addr;
sf.sf_ahu.sf_handler = catcher;
}
mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
/* Save most if not all of trap frame. */
sf.sf_siginfo.si_sc.sc_eax = regs->tf_eax;
sf.sf_siginfo.si_sc.sc_ebx = regs->tf_ebx;
sf.sf_siginfo.si_sc.sc_ecx = regs->tf_ecx;
sf.sf_siginfo.si_sc.sc_edx = regs->tf_edx;
sf.sf_siginfo.si_sc.sc_esi = regs->tf_esi;
sf.sf_siginfo.si_sc.sc_edi = regs->tf_edi;
sf.sf_siginfo.si_sc.sc_cs = regs->tf_cs;
sf.sf_siginfo.si_sc.sc_ds = regs->tf_ds;
sf.sf_siginfo.si_sc.sc_ss = regs->tf_ss;
sf.sf_siginfo.si_sc.sc_es = regs->tf_es;
sf.sf_siginfo.si_sc.sc_fs = regs->tf_fs;
sf.sf_siginfo.si_sc.sc_gs = rgs();
sf.sf_siginfo.si_sc.sc_isp = regs->tf_isp;
/* Build the signal context to be used by osigreturn(). */
sf.sf_siginfo.si_sc.sc_onstack = (oonstack) ? 1 : 0;
SIG2OSIG(*mask, sf.sf_siginfo.si_sc.sc_mask);
sf.sf_siginfo.si_sc.sc_sp = regs->tf_esp;
sf.sf_siginfo.si_sc.sc_fp = regs->tf_ebp;
sf.sf_siginfo.si_sc.sc_pc = regs->tf_eip;
sf.sf_siginfo.si_sc.sc_ps = regs->tf_eflags;
sf.sf_siginfo.si_sc.sc_trapno = regs->tf_trapno;
sf.sf_siginfo.si_sc.sc_err = regs->tf_err;
/*
* If we're a vm86 process, we want to save the segment registers.
* We also change eflags to be our emulated eflags, not the actual
* eflags.
*/
if (regs->tf_eflags & PSL_VM) {
/* XXX confusing names: `tf' isn't a trapframe; `regs' is. */
struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
struct vm86_kernel *vm86 = &td->td_pcb->pcb_ext->ext_vm86;
sf.sf_siginfo.si_sc.sc_gs = tf->tf_vm86_gs;
sf.sf_siginfo.si_sc.sc_fs = tf->tf_vm86_fs;
sf.sf_siginfo.si_sc.sc_es = tf->tf_vm86_es;
sf.sf_siginfo.si_sc.sc_ds = tf->tf_vm86_ds;
if (vm86->vm86_has_vme == 0)
sf.sf_siginfo.si_sc.sc_ps =
(tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) |
(vm86->vm86_eflags & (PSL_VIF | PSL_VIP));
/* See sendsig() for comments. */
tf->tf_eflags &= ~(PSL_VM | PSL_NT | PSL_VIF | PSL_VIP);
}
/*
* Copy the sigframe out to the user's stack.
*/
if (copyout(&sf, fp, sizeof(*fp)) != 0) {
#ifdef DEBUG
printf("process %ld has trashed its stack\n", (long)p->p_pid);
#endif
PROC_LOCK(p);
sigexit(td, SIGILL);
}
regs->tf_esp = (int)fp;
regs->tf_eip = PS_STRINGS - szosigcode;
regs->tf_eflags &= ~(PSL_T | PSL_D);
regs->tf_cs = _ucodesel;
regs->tf_ds = _udatasel;
regs->tf_es = _udatasel;
regs->tf_fs = _udatasel;
load_gs(_udatasel);
regs->tf_ss = _udatasel;
PROC_LOCK(p);
mtx_lock(&psp->ps_mtx);
}
#endif /* COMPAT_43 */
#ifdef COMPAT_FREEBSD4
static void
freebsd4_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
{
struct sigframe4 sf, *sfp;
struct proc *p;
struct thread *td;
struct sigacts *psp;
struct trapframe *regs;
int sig;
int oonstack;
td = curthread;
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
sig = ksi->ksi_signo;
psp = p->p_sigacts;
mtx_assert(&psp->ps_mtx, MA_OWNED);
regs = td->td_frame;
oonstack = sigonstack(regs->tf_esp);
/* Save user context. */
bzero(&sf, sizeof(sf));
sf.sf_uc.uc_sigmask = *mask;
sf.sf_uc.uc_stack = td->td_sigstk;
sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
sf.sf_uc.uc_mcontext.mc_gs = rgs();
bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(*regs));
bzero(sf.sf_uc.uc_mcontext.mc_fpregs,
sizeof(sf.sf_uc.uc_mcontext.mc_fpregs));
bzero(sf.sf_uc.uc_mcontext.__spare__,
sizeof(sf.sf_uc.uc_mcontext.__spare__));
bzero(sf.sf_uc.__spare__, sizeof(sf.sf_uc.__spare__));
/* Allocate space for the signal handler context. */
if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
SIGISMEMBER(psp->ps_sigonstack, sig)) {
sfp = (struct sigframe4 *)(td->td_sigstk.ss_sp +
td->td_sigstk.ss_size - sizeof(struct sigframe4));
#if defined(COMPAT_43)
td->td_sigstk.ss_flags |= SS_ONSTACK;
#endif
} else
sfp = (struct sigframe4 *)regs->tf_esp - 1;
/* Translate the signal if appropriate. */
if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
/* Build the argument list for the signal handler. */
sf.sf_signum = sig;
sf.sf_ucontext = (register_t)&sfp->sf_uc;
bzero(&sf.sf_si, sizeof(sf.sf_si));
if (SIGISMEMBER(psp->ps_siginfo, sig)) {
/* Signal handler installed with SA_SIGINFO. */
sf.sf_siginfo = (register_t)&sfp->sf_si;
sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
/* Fill in POSIX parts */
sf.sf_si.si_signo = sig;
sf.sf_si.si_code = ksi->ksi_code;
sf.sf_si.si_addr = ksi->ksi_addr;
} else {
/* Old FreeBSD-style arguments. */
sf.sf_siginfo = ksi->ksi_code;
sf.sf_addr = (register_t)ksi->ksi_addr;
sf.sf_ahu.sf_handler = catcher;
}
mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
/*
* If we're a vm86 process, we want to save the segment registers.
* We also change eflags to be our emulated eflags, not the actual
* eflags.
*/
if (regs->tf_eflags & PSL_VM) {
struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
struct vm86_kernel *vm86 = &td->td_pcb->pcb_ext->ext_vm86;
sf.sf_uc.uc_mcontext.mc_gs = tf->tf_vm86_gs;
sf.sf_uc.uc_mcontext.mc_fs = tf->tf_vm86_fs;
sf.sf_uc.uc_mcontext.mc_es = tf->tf_vm86_es;
sf.sf_uc.uc_mcontext.mc_ds = tf->tf_vm86_ds;
if (vm86->vm86_has_vme == 0)
sf.sf_uc.uc_mcontext.mc_eflags =
(tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) |
(vm86->vm86_eflags & (PSL_VIF | PSL_VIP));
/*
* Clear PSL_NT to inhibit T_TSSFLT faults on return from
* syscalls made by the signal handler. This just avoids
* wasting time for our lazy fixup of such faults. PSL_NT
* does nothing in vm86 mode, but vm86 programs can set it
* almost legitimately in probes for old cpu types.
*/
tf->tf_eflags &= ~(PSL_VM | PSL_NT | PSL_VIF | PSL_VIP);
}
/*
* Copy the sigframe out to the user's stack.
*/
if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
#ifdef DEBUG
printf("process %ld has trashed its stack\n", (long)p->p_pid);
#endif
PROC_LOCK(p);
sigexit(td, SIGILL);
}
regs->tf_esp = (int)sfp;
regs->tf_eip = PS_STRINGS - szfreebsd4_sigcode;
regs->tf_eflags &= ~(PSL_T | PSL_D);
regs->tf_cs = _ucodesel;
regs->tf_ds = _udatasel;
regs->tf_es = _udatasel;
regs->tf_fs = _udatasel;
regs->tf_ss = _udatasel;
PROC_LOCK(p);
mtx_lock(&psp->ps_mtx);
}
#endif /* COMPAT_FREEBSD4 */
void
sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
{
struct sigframe sf, *sfp;
struct proc *p;
struct thread *td;
struct sigacts *psp;
char *sp;
struct trapframe *regs;
struct segment_descriptor *sdp;
int sig;
int oonstack;
td = curthread;
p = td->td_proc;
PROC_LOCK_ASSERT(p, MA_OWNED);
sig = ksi->ksi_signo;
psp = p->p_sigacts;
mtx_assert(&psp->ps_mtx, MA_OWNED);
#ifdef COMPAT_FREEBSD4
if (SIGISMEMBER(psp->ps_freebsd4, sig)) {
freebsd4_sendsig(catcher, ksi, mask);
return;
}
#endif
#ifdef COMPAT_43
if (SIGISMEMBER(psp->ps_osigset, sig)) {
osendsig(catcher, ksi, mask);
return;
}
#endif
regs = td->td_frame;
oonstack = sigonstack(regs->tf_esp);
/* Save user context. */
bzero(&sf, sizeof(sf));
sf.sf_uc.uc_sigmask = *mask;
sf.sf_uc.uc_stack = td->td_sigstk;
sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
sf.sf_uc.uc_mcontext.mc_gs = rgs();
bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(*regs));
sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */
get_fpcontext(td, &sf.sf_uc.uc_mcontext);
fpstate_drop(td);
/*
* Unconditionally fill the fsbase and gsbase into the mcontext.
*/
sdp = &td->td_pcb->pcb_fsd;
sf.sf_uc.uc_mcontext.mc_fsbase = sdp->sd_hibase << 24 |
sdp->sd_lobase;
sdp = &td->td_pcb->pcb_gsd;
sf.sf_uc.uc_mcontext.mc_gsbase = sdp->sd_hibase << 24 |
sdp->sd_lobase;
bzero(sf.sf_uc.uc_mcontext.mc_spare1,
sizeof(sf.sf_uc.uc_mcontext.mc_spare1));
bzero(sf.sf_uc.uc_mcontext.mc_spare2,
sizeof(sf.sf_uc.uc_mcontext.mc_spare2));
bzero(sf.sf_uc.__spare__, sizeof(sf.sf_uc.__spare__));
/* Allocate space for the signal handler context. */
if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
SIGISMEMBER(psp->ps_sigonstack, sig)) {
sp = td->td_sigstk.ss_sp +
td->td_sigstk.ss_size - sizeof(struct sigframe);
#if defined(COMPAT_43)
td->td_sigstk.ss_flags |= SS_ONSTACK;
#endif
} else
sp = (char *)regs->tf_esp - sizeof(struct sigframe);
/* Align to 16 bytes. */
sfp = (struct sigframe *)((unsigned int)sp & ~0xF);
/* Translate the signal if appropriate. */
if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
/* Build the argument list for the signal handler. */
sf.sf_signum = sig;
sf.sf_ucontext = (register_t)&sfp->sf_uc;
bzero(&sf.sf_si, sizeof(sf.sf_si));
if (SIGISMEMBER(psp->ps_siginfo, sig)) {
/* Signal handler installed with SA_SIGINFO. */
sf.sf_siginfo = (register_t)&sfp->sf_si;
sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher;
/* Fill in POSIX parts */
sf.sf_si = ksi->ksi_info;
sf.sf_si.si_signo = sig; /* maybe a translated signal */
} else {
/* Old FreeBSD-style arguments. */
sf.sf_siginfo = ksi->ksi_code;
sf.sf_addr = (register_t)ksi->ksi_addr;
sf.sf_ahu.sf_handler = catcher;
}
mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
/*
* If we're a vm86 process, we want to save the segment registers.
* We also change eflags to be our emulated eflags, not the actual
* eflags.
*/
if (regs->tf_eflags & PSL_VM) {
struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
struct vm86_kernel *vm86 = &td->td_pcb->pcb_ext->ext_vm86;
sf.sf_uc.uc_mcontext.mc_gs = tf->tf_vm86_gs;
sf.sf_uc.uc_mcontext.mc_fs = tf->tf_vm86_fs;
sf.sf_uc.uc_mcontext.mc_es = tf->tf_vm86_es;
sf.sf_uc.uc_mcontext.mc_ds = tf->tf_vm86_ds;
if (vm86->vm86_has_vme == 0)
sf.sf_uc.uc_mcontext.mc_eflags =
(tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) |
(vm86->vm86_eflags & (PSL_VIF | PSL_VIP));
/*
* Clear PSL_NT to inhibit T_TSSFLT faults on return from
* syscalls made by the signal handler. This just avoids
* wasting time for our lazy fixup of such faults. PSL_NT
* does nothing in vm86 mode, but vm86 programs can set it
* almost legitimately in probes for old cpu types.
*/
tf->tf_eflags &= ~(PSL_VM | PSL_NT | PSL_VIF | PSL_VIP);
}
/*
* Copy the sigframe out to the user's stack.
*/
if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
#ifdef DEBUG
printf("process %ld has trashed its stack\n", (long)p->p_pid);
#endif
PROC_LOCK(p);
sigexit(td, SIGILL);
}
regs->tf_esp = (int)sfp;
regs->tf_eip = PS_STRINGS - *(p->p_sysent->sv_szsigcode);
regs->tf_eflags &= ~(PSL_T | PSL_D);
regs->tf_cs = _ucodesel;
regs->tf_ds = _udatasel;
regs->tf_es = _udatasel;
regs->tf_fs = _udatasel;
regs->tf_ss = _udatasel;
PROC_LOCK(p);
mtx_lock(&psp->ps_mtx);
}
/*
* System call to cleanup state after a signal
* has been taken. Reset signal mask and
* stack state from context left by sendsig (above).
* Return to previous pc and psl as specified by
* context left by sendsig. Check carefully to
* make sure that the user has not modified the
* state to gain improper privileges.
*
* MPSAFE
*/
#ifdef COMPAT_43
int
osigreturn(td, uap)
struct thread *td;
struct osigreturn_args /* {
struct osigcontext *sigcntxp;
} */ *uap;
{
struct osigcontext sc;
struct trapframe *regs;
struct osigcontext *scp;
int eflags, error;
ksiginfo_t ksi;
regs = td->td_frame;
error = copyin(uap->sigcntxp, &sc, sizeof(sc));
if (error != 0)
return (error);
scp = &sc;
eflags = scp->sc_ps;
if (eflags & PSL_VM) {
struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
struct vm86_kernel *vm86;
/*
* if pcb_ext == 0 or vm86_inited == 0, the user hasn't
* set up the vm86 area, and we can't enter vm86 mode.
*/
if (td->td_pcb->pcb_ext == 0)
return (EINVAL);
vm86 = &td->td_pcb->pcb_ext->ext_vm86;
if (vm86->vm86_inited == 0)
return (EINVAL);
/* Go back to user mode if both flags are set. */
if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) {
ksiginfo_init_trap(&ksi);
ksi.ksi_signo = SIGBUS;
ksi.ksi_code = BUS_OBJERR;
ksi.ksi_addr = (void *)regs->tf_eip;
trapsignal(td, &ksi);
}
if (vm86->vm86_has_vme) {
eflags = (tf->tf_eflags & ~VME_USERCHANGE) |
(eflags & VME_USERCHANGE) | PSL_VM;
} else {
vm86->vm86_eflags = eflags; /* save VIF, VIP */
eflags = (tf->tf_eflags & ~VM_USERCHANGE) |
(eflags & VM_USERCHANGE) | PSL_VM;
}
tf->tf_vm86_ds = scp->sc_ds;
tf->tf_vm86_es = scp->sc_es;
tf->tf_vm86_fs = scp->sc_fs;
tf->tf_vm86_gs = scp->sc_gs;
tf->tf_ds = _udatasel;
tf->tf_es = _udatasel;
tf->tf_fs = _udatasel;
} else {
/*
* Don't allow users to change privileged or reserved flags.
*/
/*
* XXX do allow users to change the privileged flag PSL_RF.
* The cpu sets PSL_RF in tf_eflags for faults. Debuggers
* should sometimes set it there too. tf_eflags is kept in
* the signal context during signal handling and there is no
* other place to remember it, so the PSL_RF bit may be
* corrupted by the signal handler without us knowing.
* Corruption of the PSL_RF bit at worst causes one more or
* one less debugger trap, so allowing it is fairly harmless.
*/
if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) {
return (EINVAL);
}
/*
* Don't allow users to load a valid privileged %cs. Let the
* hardware check for invalid selectors, excess privilege in
* other selectors, invalid %eip's and invalid %esp's.
*/
if (!CS_SECURE(scp->sc_cs)) {
ksiginfo_init_trap(&ksi);
ksi.ksi_signo = SIGBUS;
ksi.ksi_code = BUS_OBJERR;
ksi.ksi_trapno = T_PROTFLT;
ksi.ksi_addr = (void *)regs->tf_eip;
trapsignal(td, &ksi);
return (EINVAL);
}
regs->tf_ds = scp->sc_ds;
regs->tf_es = scp->sc_es;
regs->tf_fs = scp->sc_fs;
}
/* Restore remaining registers. */
regs->tf_eax = scp->sc_eax;
regs->tf_ebx = scp->sc_ebx;
regs->tf_ecx = scp->sc_ecx;
regs->tf_edx = scp->sc_edx;
regs->tf_esi = scp->sc_esi;
regs->tf_edi = scp->sc_edi;
regs->tf_cs = scp->sc_cs;
regs->tf_ss = scp->sc_ss;
regs->tf_isp = scp->sc_isp;
regs->tf_ebp = scp->sc_fp;
regs->tf_esp = scp->sc_sp;
regs->tf_eip = scp->sc_pc;
regs->tf_eflags = eflags;
#if defined(COMPAT_43)
if (scp->sc_onstack & 1)
td->td_sigstk.ss_flags |= SS_ONSTACK;
else
td->td_sigstk.ss_flags &= ~SS_ONSTACK;
#endif
kern_sigprocmask(td, SIG_SETMASK, (sigset_t *)&scp->sc_mask, NULL,
SIGPROCMASK_OLD);
return (EJUSTRETURN);
}
#endif /* COMPAT_43 */
#ifdef COMPAT_FREEBSD4
/*
* MPSAFE
*/
int
freebsd4_sigreturn(td, uap)
struct thread *td;
struct freebsd4_sigreturn_args /* {
const ucontext4 *sigcntxp;
} */ *uap;
{
struct ucontext4 uc;
struct trapframe *regs;
struct ucontext4 *ucp;
int cs, eflags, error;
ksiginfo_t ksi;
error = copyin(uap->sigcntxp, &uc, sizeof(uc));
if (error != 0)
return (error);
ucp = &uc;
regs = td->td_frame;
eflags = ucp->uc_mcontext.mc_eflags;
if (eflags & PSL_VM) {
struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
struct vm86_kernel *vm86;
/*
* if pcb_ext == 0 or vm86_inited == 0, the user hasn't
* set up the vm86 area, and we can't enter vm86 mode.
*/
if (td->td_pcb->pcb_ext == 0)
return (EINVAL);
vm86 = &td->td_pcb->pcb_ext->ext_vm86;
if (vm86->vm86_inited == 0)
return (EINVAL);
/* Go back to user mode if both flags are set. */
if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) {
ksiginfo_init_trap(&ksi);
ksi.ksi_signo = SIGBUS;
ksi.ksi_code = BUS_OBJERR;
ksi.ksi_addr = (void *)regs->tf_eip;
trapsignal(td, &ksi);
}
if (vm86->vm86_has_vme) {
eflags = (tf->tf_eflags & ~VME_USERCHANGE) |
(eflags & VME_USERCHANGE) | PSL_VM;
} else {
vm86->vm86_eflags = eflags; /* save VIF, VIP */
eflags = (tf->tf_eflags & ~VM_USERCHANGE) |
(eflags & VM_USERCHANGE) | PSL_VM;
}
bcopy(&ucp->uc_mcontext.mc_fs, tf, sizeof(struct trapframe));
tf->tf_eflags = eflags;
tf->tf_vm86_ds = tf->tf_ds;
tf->tf_vm86_es = tf->tf_es;
tf->tf_vm86_fs = tf->tf_fs;
tf->tf_vm86_gs = ucp->uc_mcontext.mc_gs;
tf->tf_ds = _udatasel;
tf->tf_es = _udatasel;
tf->tf_fs = _udatasel;
} else {
/*
* Don't allow users to change privileged or reserved flags.
*/
/*
* XXX do allow users to change the privileged flag PSL_RF.
* The cpu sets PSL_RF in tf_eflags for faults. Debuggers
* should sometimes set it there too. tf_eflags is kept in
* the signal context during signal handling and there is no
* other place to remember it, so the PSL_RF bit may be
* corrupted by the signal handler without us knowing.
* Corruption of the PSL_RF bit at worst causes one more or
* one less debugger trap, so allowing it is fairly harmless.
*/
if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) {
uprintf("pid %d (%s): freebsd4_sigreturn eflags = 0x%x\n",
td->td_proc->p_pid, td->td_name, eflags);
return (EINVAL);
}
/*
* Don't allow users to load a valid privileged %cs. Let the
* hardware check for invalid selectors, excess privilege in
* other selectors, invalid %eip's and invalid %esp's.
*/
cs = ucp->uc_mcontext.mc_cs;
if (!CS_SECURE(cs)) {
uprintf("pid %d (%s): freebsd4_sigreturn cs = 0x%x\n",
td->td_proc->p_pid, td->td_name, cs);
ksiginfo_init_trap(&ksi);
ksi.ksi_signo = SIGBUS;
ksi.ksi_code = BUS_OBJERR;
ksi.ksi_trapno = T_PROTFLT;
ksi.ksi_addr = (void *)regs->tf_eip;
trapsignal(td, &ksi);
return (EINVAL);
}
bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(*regs));
}
#if defined(COMPAT_43)
if (ucp->uc_mcontext.mc_onstack & 1)
td->td_sigstk.ss_flags |= SS_ONSTACK;
else
td->td_sigstk.ss_flags &= ~SS_ONSTACK;
#endif
kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0);
return (EJUSTRETURN);
}
#endif /* COMPAT_FREEBSD4 */
/*
* MPSAFE
*/
int
sigreturn(td, uap)
struct thread *td;
struct sigreturn_args /* {
const struct __ucontext *sigcntxp;
} */ *uap;
{
ucontext_t uc;
struct trapframe *regs;
ucontext_t *ucp;
int cs, eflags, error, ret;
ksiginfo_t ksi;
error = copyin(uap->sigcntxp, &uc, sizeof(uc));
if (error != 0)
return (error);
ucp = &uc;
regs = td->td_frame;
eflags = ucp->uc_mcontext.mc_eflags;
if (eflags & PSL_VM) {
struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
struct vm86_kernel *vm86;
/*
* if pcb_ext == 0 or vm86_inited == 0, the user hasn't
* set up the vm86 area, and we can't enter vm86 mode.
*/
if (td->td_pcb->pcb_ext == 0)
return (EINVAL);
vm86 = &td->td_pcb->pcb_ext->ext_vm86;
if (vm86->vm86_inited == 0)
return (EINVAL);
/* Go back to user mode if both flags are set. */
if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) {
ksiginfo_init_trap(&ksi);
ksi.ksi_signo = SIGBUS;
ksi.ksi_code = BUS_OBJERR;
ksi.ksi_addr = (void *)regs->tf_eip;
trapsignal(td, &ksi);
}
if (vm86->vm86_has_vme) {
eflags = (tf->tf_eflags & ~VME_USERCHANGE) |
(eflags & VME_USERCHANGE) | PSL_VM;
} else {
vm86->vm86_eflags = eflags; /* save VIF, VIP */
eflags = (tf->tf_eflags & ~VM_USERCHANGE) |
(eflags & VM_USERCHANGE) | PSL_VM;
}
bcopy(&ucp->uc_mcontext.mc_fs, tf, sizeof(struct trapframe));
tf->tf_eflags = eflags;
tf->tf_vm86_ds = tf->tf_ds;
tf->tf_vm86_es = tf->tf_es;
tf->tf_vm86_fs = tf->tf_fs;
tf->tf_vm86_gs = ucp->uc_mcontext.mc_gs;
tf->tf_ds = _udatasel;
tf->tf_es = _udatasel;
tf->tf_fs = _udatasel;
} else {
/*
* Don't allow users to change privileged or reserved flags.
*/
/*
* XXX do allow users to change the privileged flag PSL_RF.
* The cpu sets PSL_RF in tf_eflags for faults. Debuggers
* should sometimes set it there too. tf_eflags is kept in
* the signal context during signal handling and there is no
* other place to remember it, so the PSL_RF bit may be
* corrupted by the signal handler without us knowing.
* Corruption of the PSL_RF bit at worst causes one more or
* one less debugger trap, so allowing it is fairly harmless.
*/
if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) {
uprintf("pid %d (%s): sigreturn eflags = 0x%x\n",
td->td_proc->p_pid, td->td_name, eflags);
return (EINVAL);
}
/*
* Don't allow users to load a valid privileged %cs. Let the
* hardware check for invalid selectors, excess privilege in
* other selectors, invalid %eip's and invalid %esp's.
*/
cs = ucp->uc_mcontext.mc_cs;
if (!CS_SECURE(cs)) {
uprintf("pid %d (%s): sigreturn cs = 0x%x\n",
td->td_proc->p_pid, td->td_name, cs);
ksiginfo_init_trap(&ksi);
ksi.ksi_signo = SIGBUS;
ksi.ksi_code = BUS_OBJERR;
ksi.ksi_trapno = T_PROTFLT;
ksi.ksi_addr = (void *)regs->tf_eip;
trapsignal(td, &ksi);
return (EINVAL);
}
ret = set_fpcontext(td, &ucp->uc_mcontext);
if (ret != 0)
return (ret);
bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(*regs));
}
#if defined(COMPAT_43)
if (ucp->uc_mcontext.mc_onstack & 1)
td->td_sigstk.ss_flags |= SS_ONSTACK;
else
td->td_sigstk.ss_flags &= ~SS_ONSTACK;
#endif
kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0);
return (EJUSTRETURN);
}
/*
* Machine dependent boot() routine
*
* I haven't seen anything to put here yet
* Possibly some stuff might be grafted back here from boot()
*/
void
cpu_boot(int howto)
{
}
/*
* Flush the D-cache for non-DMA I/O so that the I-cache can
* be made coherent later.
*/
void
cpu_flush_dcache(void *ptr, size_t len)
{
/* Not applicable */
}
/* Get current clock frequency for the given cpu id. */
int
cpu_est_clockrate(int cpu_id, uint64_t *rate)
{
register_t reg;
uint64_t tsc1, tsc2;
if (pcpu_find(cpu_id) == NULL || rate == NULL)
return (EINVAL);
if (!tsc_present)
return (EOPNOTSUPP);
/* If we're booting, trust the rate calibrated moments ago. */
if (cold) {
*rate = tsc_freq;
return (0);
}
#ifdef SMP
/* Schedule ourselves on the indicated cpu. */
thread_lock(curthread);
sched_bind(curthread, cpu_id);
thread_unlock(curthread);
#endif
/* Calibrate by measuring a short delay. */
reg = intr_disable();
tsc1 = rdtsc();
DELAY(1000);
tsc2 = rdtsc();
intr_restore(reg);
#ifdef SMP
thread_lock(curthread);
sched_unbind(curthread);
thread_unlock(curthread);
#endif
tsc2 -= tsc1;
if (tsc_freq != 0 && !tsc_is_broken) {
*rate = tsc2 * 1000;
return (0);
}
/*
* Subtract 0.5% of the total. Empirical testing has shown that
* overhead in DELAY() works out to approximately this value.
*/
*rate = tsc2 * 1000 - tsc2 * 5;
return (0);
}
/*
* Shutdown the CPU as much as possible
*/
void
cpu_halt(void)
{
for (;;)
__asm__ ("hlt");
}
static int idle_mwait = 1; /* Use MONITOR/MWAIT for short idle. */
TUNABLE_INT("machdep.idle_mwait", &idle_mwait);
SYSCTL_INT(_machdep, OID_AUTO, idle_mwait, CTLFLAG_RW, &idle_mwait,
0, "Use MONITOR/MWAIT for short idle");
#define STATE_RUNNING 0x0
#define STATE_MWAIT 0x1
#define STATE_SLEEPING 0x2
static void
cpu_idle_hlt(int busy)
{
int *state;
state = (int *)PCPU_PTR(monitorbuf);
*state = STATE_SLEEPING;
/*
* We must absolutely guarentee that hlt is the next instruction
* after sti or we introduce a timing window.
*/
disable_intr();
if (sched_runnable())
enable_intr();
else
__asm __volatile("sti; hlt");
*state = STATE_RUNNING;
}
/*
* MWAIT cpu power states. Lower 4 bits are sub-states.
*/
#define MWAIT_C0 0xf0
#define MWAIT_C1 0x00
#define MWAIT_C2 0x10
#define MWAIT_C3 0x20
#define MWAIT_C4 0x30
static void
cpu_idle_mwait(int busy)
{
int *state;
state = (int *)PCPU_PTR(monitorbuf);
*state = STATE_MWAIT;
if (!sched_runnable()) {
cpu_monitor(state, 0, 0);
if (*state == STATE_MWAIT)
cpu_mwait(0, MWAIT_C1);
}
*state = STATE_RUNNING;
}
static void
cpu_idle_spin(int busy)
{
int *state;
int i;
state = (int *)PCPU_PTR(monitorbuf);
*state = STATE_RUNNING;
for (i = 0; i < 1000; i++) {
if (sched_runnable())
return;
cpu_spinwait();
}
}
void (*cpu_idle_fn)(int) = cpu_idle_hlt;
void
cpu_idle(int busy)
{
CTR2(KTR_SPARE2, "cpu_idle(%d) at %d",
busy, curcpu);
#ifdef SMP
if (mp_grab_cpu_hlt())
return;
#endif
/* If we are busy - try to use fast methods. */
if (busy) {
if ((cpu_feature2 & CPUID2_MON) && idle_mwait) {
cpu_idle_mwait(busy);
goto out;
}
}
/* If we have time - switch timers into idle mode. */
if (!busy) {
critical_enter();
cpu_idleclock();
}
/* Call main idle method. */
cpu_idle_fn(busy);
/* Switch timers mack into active mode. */
if (!busy) {
cpu_activeclock();
critical_exit();
}
out:
CTR2(KTR_SPARE2, "cpu_idle(%d) at %d done",
busy, curcpu);
}
int
cpu_idle_wakeup(int cpu)
{
struct pcpu *pcpu;
int *state;
pcpu = pcpu_find(cpu);
state = (int *)pcpu->pc_monitorbuf;
/*
* This doesn't need to be atomic since missing the race will
* simply result in unnecessary IPIs.
*/
if (*state == STATE_SLEEPING)
return (0);
if (*state == STATE_MWAIT)
*state = STATE_RUNNING;
return (1);
}
/*
* Ordered by speed/power consumption.
*/
struct {
void *id_fn;
char *id_name;
} idle_tbl[] = {
{ cpu_idle_spin, "spin" },
{ cpu_idle_mwait, "mwait" },
{ cpu_idle_hlt, "hlt" },
{ NULL, NULL }
};
static int
idle_sysctl_available(SYSCTL_HANDLER_ARGS)
{
char *avail, *p;
int error;
int i;
avail = malloc(256, M_TEMP, M_WAITOK);
p = avail;
for (i = 0; idle_tbl[i].id_name != NULL; i++) {
if (strstr(idle_tbl[i].id_name, "mwait") &&
(cpu_feature2 & CPUID2_MON) == 0)
continue;
p += sprintf(p, "%s%s", p != avail ? ", " : "",
idle_tbl[i].id_name);
}
error = sysctl_handle_string(oidp, avail, 0, req);
free(avail, M_TEMP);
return (error);
}
SYSCTL_PROC(_machdep, OID_AUTO, idle_available, CTLTYPE_STRING | CTLFLAG_RD,
0, 0, idle_sysctl_available, "A", "list of available idle functions");
static int
idle_sysctl(SYSCTL_HANDLER_ARGS)
{
char buf[16];
int error;
char *p;
int i;
p = "unknown";
for (i = 0; idle_tbl[i].id_name != NULL; i++) {
if (idle_tbl[i].id_fn == cpu_idle_fn) {
p = idle_tbl[i].id_name;
break;
}
}
strncpy(buf, p, sizeof(buf));
error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
if (error != 0 || req->newptr == NULL)
return (error);
for (i = 0; idle_tbl[i].id_name != NULL; i++) {
if (strstr(idle_tbl[i].id_name, "mwait") &&
(cpu_feature2 & CPUID2_MON) == 0)
continue;
if (strcmp(idle_tbl[i].id_name, buf))
continue;
cpu_idle_fn = idle_tbl[i].id_fn;
return (0);
}
return (EINVAL);
}
SYSCTL_PROC(_machdep, OID_AUTO, idle, CTLTYPE_STRING | CTLFLAG_RW, 0, 0,
idle_sysctl, "A", "currently selected idle function");
/*
* Reset registers to default values on exec.
*/
void
exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
{
struct trapframe *regs = td->td_frame;
struct pcb *pcb = td->td_pcb;
/* Reset pc->pcb_gs and %gs before possibly invalidating it. */
pcb->pcb_gs = _udatasel;
load_gs(_udatasel);
mtx_lock_spin(&dt_lock);
if (td->td_proc->p_md.md_ldt)
user_ldt_free(td);
else
mtx_unlock_spin(&dt_lock);
bzero((char *)regs, sizeof(struct trapframe));
regs->tf_eip = imgp->entry_addr;
regs->tf_esp = stack;
regs->tf_eflags = PSL_USER | (regs->tf_eflags & PSL_T);
regs->tf_ss = _udatasel;
regs->tf_ds = _udatasel;
regs->tf_es = _udatasel;
regs->tf_fs = _udatasel;
regs->tf_cs = _ucodesel;
/* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */
regs->tf_ebx = imgp->ps_strings;
/*
* Reset the hardware debug registers if they were in use.
* They won't have any meaning for the newly exec'd process.
*/
if (pcb->pcb_flags & PCB_DBREGS) {
pcb->pcb_dr0 = 0;
pcb->pcb_dr1 = 0;
pcb->pcb_dr2 = 0;
pcb->pcb_dr3 = 0;
pcb->pcb_dr6 = 0;
pcb->pcb_dr7 = 0;
if (pcb == PCPU_GET(curpcb)) {
/*
* Clear the debug registers on the running
* CPU, otherwise they will end up affecting
* the next process we switch to.
*/
reset_dbregs();
}
pcb->pcb_flags &= ~PCB_DBREGS;
}
/*
* Initialize the math emulator (if any) for the current process.
* Actually, just clear the bit that says that the emulator has
* been initialized. Initialization is delayed until the process
* traps to the emulator (if it is done at all) mainly because
* emulators don't provide an entry point for initialization.
*/
td->td_pcb->pcb_flags &= ~FP_SOFTFP;
pcb->pcb_initial_npxcw = __INITIAL_NPXCW__;
/*
* Drop the FP state if we hold it, so that the process gets a
* clean FP state if it uses the FPU again.
*/
fpstate_drop(td);
/*
* XXX - Linux emulator
* Make sure sure edx is 0x0 on entry. Linux binaries depend
* on it.
*/
td->td_retval[1] = 0;
}
void
cpu_setregs(void)
{
unsigned int cr0;
cr0 = rcr0();
/*
* CR0_MP, CR0_NE and CR0_TS are set for NPX (FPU) support:
*
* Prepare to trap all ESC (i.e., NPX) instructions and all WAIT
* instructions. We must set the CR0_MP bit and use the CR0_TS
* bit to control the trap, because setting the CR0_EM bit does
* not cause WAIT instructions to trap. It's important to trap
* WAIT instructions - otherwise the "wait" variants of no-wait
* control instructions would degenerate to the "no-wait" variants
* after FP context switches but work correctly otherwise. It's
* particularly important to trap WAITs when there is no NPX -
* otherwise the "wait" variants would always degenerate.
*
* Try setting CR0_NE to get correct error reporting on 486DX's.
* Setting it should fail or do nothing on lesser processors.
*/
cr0 |= CR0_MP | CR0_NE | CR0_TS | CR0_WP | CR0_AM;
load_cr0(cr0);
load_gs(_udatasel);
}
u_long bootdev; /* not a struct cdev *- encoding is different */
SYSCTL_ULONG(_machdep, OID_AUTO, guessed_bootdev,
CTLFLAG_RD, &bootdev, 0, "Maybe the Boot device (not in struct cdev *format)");
/*
* Initialize 386 and configure to run kernel
*/
/*
* Initialize segments & interrupt table
*/
int _default_ldt;
union descriptor gdt[NGDT * MAXCPU]; /* global descriptor table */
union descriptor ldt[NLDT]; /* local descriptor table */
static struct gate_descriptor idt0[NIDT];
struct gate_descriptor *idt = &idt0[0]; /* interrupt descriptor table */
struct region_descriptor r_gdt, r_idt; /* table descriptors */
struct mtx dt_lock; /* lock for GDT and LDT */
#if defined(I586_CPU) && !defined(NO_F00F_HACK)
extern int has_f00f_bug;
#endif
static struct i386tss dblfault_tss;
static char dblfault_stack[PAGE_SIZE];
extern vm_offset_t proc0kstack;
/*
* software prototypes -- in more palatable form.
*
* GCODE_SEL through GUDATA_SEL must be in this order for syscall/sysret
* GUFS_SEL and GUGS_SEL must be in this order (swtch.s knows it)
*/
struct soft_segment_descriptor gdt_segs[] = {
/* GNULL_SEL 0 Null Descriptor */
{ .ssd_base = 0x0,
.ssd_limit = 0x0,
.ssd_type = 0,
.ssd_dpl = SEL_KPL,
.ssd_p = 0,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 0,
.ssd_gran = 0 },
/* GPRIV_SEL 1 SMP Per-Processor Private Data Descriptor */
{ .ssd_base = 0x0,
.ssd_limit = 0xfffff,
.ssd_type = SDT_MEMRWA,
.ssd_dpl = SEL_KPL,
.ssd_p = 1,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 1,
.ssd_gran = 1 },
/* GUFS_SEL 2 %fs Descriptor for user */
{ .ssd_base = 0x0,
.ssd_limit = 0xfffff,
.ssd_type = SDT_MEMRWA,
.ssd_dpl = SEL_UPL,
.ssd_p = 1,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 1,
.ssd_gran = 1 },
/* GUGS_SEL 3 %gs Descriptor for user */
{ .ssd_base = 0x0,
.ssd_limit = 0xfffff,
.ssd_type = SDT_MEMRWA,
.ssd_dpl = SEL_UPL,
.ssd_p = 1,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 1,
.ssd_gran = 1 },
/* GCODE_SEL 4 Code Descriptor for kernel */
{ .ssd_base = 0x0,
.ssd_limit = 0xfffff,
.ssd_type = SDT_MEMERA,
.ssd_dpl = SEL_KPL,
.ssd_p = 1,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 1,
.ssd_gran = 1 },
/* GDATA_SEL 5 Data Descriptor for kernel */
{ .ssd_base = 0x0,
.ssd_limit = 0xfffff,
.ssd_type = SDT_MEMRWA,
.ssd_dpl = SEL_KPL,
.ssd_p = 1,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 1,
.ssd_gran = 1 },
/* GUCODE_SEL 6 Code Descriptor for user */
{ .ssd_base = 0x0,
.ssd_limit = 0xfffff,
.ssd_type = SDT_MEMERA,
.ssd_dpl = SEL_UPL,
.ssd_p = 1,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 1,
.ssd_gran = 1 },
/* GUDATA_SEL 7 Data Descriptor for user */
{ .ssd_base = 0x0,
.ssd_limit = 0xfffff,
.ssd_type = SDT_MEMRWA,
.ssd_dpl = SEL_UPL,
.ssd_p = 1,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 1,
.ssd_gran = 1 },
/* GBIOSLOWMEM_SEL 8 BIOS access to realmode segment 0x40, must be #8 in GDT */
{ .ssd_base = 0x400,
.ssd_limit = 0xfffff,
.ssd_type = SDT_MEMRWA,
.ssd_dpl = SEL_KPL,
.ssd_p = 1,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 1,
.ssd_gran = 1 },
/* GPROC0_SEL 9 Proc 0 Tss Descriptor */
{
.ssd_base = 0x0,
.ssd_limit = sizeof(struct i386tss)-1,
.ssd_type = SDT_SYS386TSS,
.ssd_dpl = 0,
.ssd_p = 1,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 0,
.ssd_gran = 0 },
/* GLDT_SEL 10 LDT Descriptor */
{ .ssd_base = (int) ldt,
.ssd_limit = sizeof(ldt)-1,
.ssd_type = SDT_SYSLDT,
.ssd_dpl = SEL_UPL,
.ssd_p = 1,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 0,
.ssd_gran = 0 },
/* GUSERLDT_SEL 11 User LDT Descriptor per process */
{ .ssd_base = (int) ldt,
.ssd_limit = (512 * sizeof(union descriptor)-1),
.ssd_type = SDT_SYSLDT,
.ssd_dpl = 0,
.ssd_p = 1,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 0,
.ssd_gran = 0 },
/* GPANIC_SEL 12 Panic Tss Descriptor */
{ .ssd_base = (int) &dblfault_tss,
.ssd_limit = sizeof(struct i386tss)-1,
.ssd_type = SDT_SYS386TSS,
.ssd_dpl = 0,
.ssd_p = 1,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 0,
.ssd_gran = 0 },
/* GBIOSCODE32_SEL 13 BIOS 32-bit interface (32bit Code) */
{ .ssd_base = 0,
.ssd_limit = 0xfffff,
.ssd_type = SDT_MEMERA,
.ssd_dpl = 0,
.ssd_p = 1,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 0,
.ssd_gran = 1 },
/* GBIOSCODE16_SEL 14 BIOS 32-bit interface (16bit Code) */
{ .ssd_base = 0,
.ssd_limit = 0xfffff,
.ssd_type = SDT_MEMERA,
.ssd_dpl = 0,
.ssd_p = 1,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 0,
.ssd_gran = 1 },
/* GBIOSDATA_SEL 15 BIOS 32-bit interface (Data) */
{ .ssd_base = 0,
.ssd_limit = 0xfffff,
.ssd_type = SDT_MEMRWA,
.ssd_dpl = 0,
.ssd_p = 1,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 1,
.ssd_gran = 1 },
/* GBIOSUTIL_SEL 16 BIOS 16-bit interface (Utility) */
{ .ssd_base = 0,
.ssd_limit = 0xfffff,
.ssd_type = SDT_MEMRWA,
.ssd_dpl = 0,
.ssd_p = 1,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 0,
.ssd_gran = 1 },
/* GBIOSARGS_SEL 17 BIOS 16-bit interface (Arguments) */
{ .ssd_base = 0,
.ssd_limit = 0xfffff,
.ssd_type = SDT_MEMRWA,
.ssd_dpl = 0,
.ssd_p = 1,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 0,
.ssd_gran = 1 },
/* GNDIS_SEL 18 NDIS Descriptor */
{ .ssd_base = 0x0,
.ssd_limit = 0x0,
.ssd_type = 0,
.ssd_dpl = 0,
.ssd_p = 0,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 0,
.ssd_gran = 0 },
};
static struct soft_segment_descriptor ldt_segs[] = {
/* Null Descriptor - overwritten by call gate */
{ .ssd_base = 0x0,
.ssd_limit = 0x0,
.ssd_type = 0,
.ssd_dpl = 0,
.ssd_p = 0,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 0,
.ssd_gran = 0 },
/* Null Descriptor - overwritten by call gate */
{ .ssd_base = 0x0,
.ssd_limit = 0x0,
.ssd_type = 0,
.ssd_dpl = 0,
.ssd_p = 0,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 0,
.ssd_gran = 0 },
/* Null Descriptor - overwritten by call gate */
{ .ssd_base = 0x0,
.ssd_limit = 0x0,
.ssd_type = 0,
.ssd_dpl = 0,
.ssd_p = 0,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 0,
.ssd_gran = 0 },
/* Code Descriptor for user */
{ .ssd_base = 0x0,
.ssd_limit = 0xfffff,
.ssd_type = SDT_MEMERA,
.ssd_dpl = SEL_UPL,
.ssd_p = 1,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 1,
.ssd_gran = 1 },
/* Null Descriptor - overwritten by call gate */
{ .ssd_base = 0x0,
.ssd_limit = 0x0,
.ssd_type = 0,
.ssd_dpl = 0,
.ssd_p = 0,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 0,
.ssd_gran = 0 },
/* Data Descriptor for user */
{ .ssd_base = 0x0,
.ssd_limit = 0xfffff,
.ssd_type = SDT_MEMRWA,
.ssd_dpl = SEL_UPL,
.ssd_p = 1,
.ssd_xx = 0, .ssd_xx1 = 0,
.ssd_def32 = 1,
.ssd_gran = 1 },
};
void
setidt(idx, func, typ, dpl, selec)
int idx;
inthand_t *func;
int typ;
int dpl;
int selec;
{
struct gate_descriptor *ip;
ip = idt + idx;
ip->gd_looffset = (int)func;
ip->gd_selector = selec;
ip->gd_stkcpy = 0;
ip->gd_xx = 0;
ip->gd_type = typ;
ip->gd_dpl = dpl;
ip->gd_p = 1;
ip->gd_hioffset = ((int)func)>>16 ;
}
extern inthand_t
IDTVEC(div), IDTVEC(dbg), IDTVEC(nmi), IDTVEC(bpt), IDTVEC(ofl),
IDTVEC(bnd), IDTVEC(ill), IDTVEC(dna), IDTVEC(fpusegm),
IDTVEC(tss), IDTVEC(missing), IDTVEC(stk), IDTVEC(prot),
IDTVEC(page), IDTVEC(mchk), IDTVEC(rsvd), IDTVEC(fpu), IDTVEC(align),
IDTVEC(xmm), IDTVEC(lcall_syscall), IDTVEC(int0x80_syscall);
#ifdef DDB
/*
* Display the index and function name of any IDT entries that don't use
* the default 'rsvd' entry point.
*/
DB_SHOW_COMMAND(idt, db_show_idt)
{
struct gate_descriptor *ip;
int idx;
uintptr_t func;
ip = idt;
for (idx = 0; idx < NIDT && !db_pager_quit; idx++) {
func = (ip->gd_hioffset << 16 | ip->gd_looffset);
if (func != (uintptr_t)&IDTVEC(rsvd)) {
db_printf("%3d\t", idx);
db_printsym(func, DB_STGY_PROC);
db_printf("\n");
}
ip++;
}
}
/* Show privileged registers. */
DB_SHOW_COMMAND(sysregs, db_show_sysregs)
{
uint64_t idtr, gdtr;
idtr = ridt();
db_printf("idtr\t0x%08x/%04x\n",
(u_int)(idtr >> 16), (u_int)idtr & 0xffff);
gdtr = rgdt();
db_printf("gdtr\t0x%08x/%04x\n",
(u_int)(gdtr >> 16), (u_int)gdtr & 0xffff);
db_printf("ldtr\t0x%04x\n", rldt());
db_printf("tr\t0x%04x\n", rtr());
db_printf("cr0\t0x%08x\n", rcr0());
db_printf("cr2\t0x%08x\n", rcr2());
db_printf("cr3\t0x%08x\n", rcr3());
db_printf("cr4\t0x%08x\n", rcr4());
}
#endif
void
sdtossd(sd, ssd)
struct segment_descriptor *sd;
struct soft_segment_descriptor *ssd;
{
ssd->ssd_base = (sd->sd_hibase << 24) | sd->sd_lobase;
ssd->ssd_limit = (sd->sd_hilimit << 16) | sd->sd_lolimit;
ssd->ssd_type = sd->sd_type;
ssd->ssd_dpl = sd->sd_dpl;
ssd->ssd_p = sd->sd_p;
ssd->ssd_def32 = sd->sd_def32;
ssd->ssd_gran = sd->sd_gran;
}
static void
basemem_setup(void)
{
vm_paddr_t pa;
pt_entry_t *pte;
int i;
if (basemem > 640) {
printf("Preposterous BIOS basemem of %uK, truncating to 640K\n",
basemem);
basemem = 640;
}
/*
* XXX if biosbasemem is now < 640, there is a `hole'
* between the end of base memory and the start of
* ISA memory. The hole may be empty or it may
* contain BIOS code or data. Map it read/write so
* that the BIOS can write to it. (Memory from 0 to
* the physical end of the kernel is mapped read-only
* to begin with and then parts of it are remapped.
* The parts that aren't remapped form holes that
* remain read-only and are unused by the kernel.
* The base memory area is below the physical end of
* the kernel and right now forms a read-only hole.
* The part of it from PAGE_SIZE to
* (trunc_page(biosbasemem * 1024) - 1) will be
* remapped and used by the kernel later.)
*
* This code is similar to the code used in
* pmap_mapdev, but since no memory needs to be
* allocated we simply change the mapping.
*/
for (pa = trunc_page(basemem * 1024);
pa < ISA_HOLE_START; pa += PAGE_SIZE)
pmap_kenter(KERNBASE + pa, pa);
/*
* Map pages between basemem and ISA_HOLE_START, if any, r/w into
* the vm86 page table so that vm86 can scribble on them using
* the vm86 map too. XXX: why 2 ways for this and only 1 way for
* page 0, at least as initialized here?
*/
pte = (pt_entry_t *)vm86paddr;
for (i = basemem / 4; i < 160; i++)
pte[i] = (i << PAGE_SHIFT) | PG_V | PG_RW | PG_U;
}
/*
* Populate the (physmap) array with base/bound pairs describing the
* available physical memory in the system, then test this memory and
* build the phys_avail array describing the actually-available memory.
*
* If we cannot accurately determine the physical memory map, then use
* value from the 0xE801 call, and failing that, the RTC.
*
* Total memory size may be set by the kernel environment variable
* hw.physmem or the compile-time define MAXMEM.
*
* XXX first should be vm_paddr_t.
*/
static void
getmemsize(int first)
{
int off, physmap_idx, pa_indx, da_indx;
u_long physmem_tunable;
vm_paddr_t physmap[PHYSMAP_SIZE];
pt_entry_t *pte;
quad_t dcons_addr, dcons_size;
int i;
int pg_n;
u_int extmem;
u_int under16;
vm_paddr_t pa;
bzero(physmap, sizeof(physmap));
/* XXX - some of EPSON machines can't use PG_N */
pg_n = PG_N;
if (pc98_machine_type & M_EPSON_PC98) {
switch (epson_machine_id) {
#ifdef WB_CACHE
default:
#endif
case EPSON_PC486_HX:
case EPSON_PC486_HG:
case EPSON_PC486_HA:
pg_n = 0;
break;
}
}
under16 = pc98_getmemsize(&basemem, &extmem);
basemem_setup();
physmap[0] = 0;
physmap[1] = basemem * 1024;
physmap_idx = 2;
physmap[physmap_idx] = 0x100000;
physmap[physmap_idx + 1] = physmap[physmap_idx] + extmem * 1024;
/*
* Now, physmap contains a map of physical memory.
*/
#ifdef SMP
/* make hole for AP bootstrap code */
physmap[1] = mp_bootaddress(physmap[1]);
#endif
/*
* Maxmem isn't the "maximum memory", it's one larger than the
* highest page of the physical address space. It should be
* called something like "Maxphyspage". We may adjust this
* based on ``hw.physmem'' and the results of the memory test.
*/
Maxmem = atop(physmap[physmap_idx + 1]);
#ifdef MAXMEM
Maxmem = MAXMEM / 4;
#endif
if (TUNABLE_ULONG_FETCH("hw.physmem", &physmem_tunable))
Maxmem = atop(physmem_tunable);
if (atop(physmap[physmap_idx + 1]) != Maxmem &&
(boothowto & RB_VERBOSE))
printf("Physical memory use set to %ldK\n", Maxmem * 4);
/*
* If Maxmem has been increased beyond what the system has detected,
* extend the last memory segment to the new limit.
*/
if (atop(physmap[physmap_idx + 1]) < Maxmem)
physmap[physmap_idx + 1] = ptoa((vm_paddr_t)Maxmem);
/*
* We need to divide chunk if Maxmem is larger than 16MB and
* under 16MB area is not full of memory.
* (1) system area (15-16MB region) is cut off
* (2) extended memory is only over 16MB area (ex. Melco "HYPERMEMORY")
*/
if ((under16 != 16 * 1024) && (extmem > 15 * 1024)) {
/* 15M - 16M region is cut off, so need to divide chunk */
physmap[physmap_idx + 1] = under16 * 1024;
physmap_idx += 2;
physmap[physmap_idx] = 0x1000000;
physmap[physmap_idx + 1] = physmap[2] + extmem * 1024;
}
/* call pmap initialization to make new kernel address space */
pmap_bootstrap(first);
/*
* Size up each available chunk of physical memory.
*/
physmap[0] = PAGE_SIZE; /* mask off page 0 */
pa_indx = 0;
da_indx = 1;
phys_avail[pa_indx++] = physmap[0];
phys_avail[pa_indx] = physmap[0];
dump_avail[da_indx] = physmap[0];
pte = CMAP1;
/*
* Get dcons buffer address
*/
if (getenv_quad("dcons.addr", &dcons_addr) == 0 ||
getenv_quad("dcons.size", &dcons_size) == 0)
dcons_addr = 0;
/*
* physmap is in bytes, so when converting to page boundaries,
* round up the start address and round down the end address.
*/
for (i = 0; i <= physmap_idx; i += 2) {
vm_paddr_t end;
end = ptoa((vm_paddr_t)Maxmem);
if (physmap[i + 1] < end)
end = trunc_page(physmap[i + 1]);
for (pa = round_page(physmap[i]); pa < end; pa += PAGE_SIZE) {
int tmp, page_bad, full;
int *ptr = (int *)CADDR1;
full = FALSE;
/*
* block out kernel memory as not available.
*/
if (pa >= KERNLOAD && pa < first)
goto do_dump_avail;
/*
* block out dcons buffer
*/
if (dcons_addr > 0
&& pa >= trunc_page(dcons_addr)
&& pa < dcons_addr + dcons_size)
goto do_dump_avail;
page_bad = FALSE;
/*
* map page into kernel: valid, read/write,non-cacheable
*/
*pte = pa | PG_V | PG_RW | pg_n;
invltlb();
tmp = *(int *)ptr;
/*
* Test for alternating 1's and 0's
*/
*(volatile int *)ptr = 0xaaaaaaaa;
if (*(volatile int *)ptr != 0xaaaaaaaa)
page_bad = TRUE;
/*
* Test for alternating 0's and 1's
*/
*(volatile int *)ptr = 0x55555555;
if (*(volatile int *)ptr != 0x55555555)
page_bad = TRUE;
/*
* Test for all 1's
*/
*(volatile int *)ptr = 0xffffffff;
if (*(volatile int *)ptr != 0xffffffff)
page_bad = TRUE;
/*
* Test for all 0's
*/
*(volatile int *)ptr = 0x0;
if (*(volatile int *)ptr != 0x0)
page_bad = TRUE;
/*
* Restore original value.
*/
*(int *)ptr = tmp;
/*
* Adjust array of valid/good pages.
*/
if (page_bad == TRUE)
continue;
/*
* If this good page is a continuation of the
* previous set of good pages, then just increase
* the end pointer. Otherwise start a new chunk.
* Note that "end" points one higher than end,
* making the range >= start and < end.
* If we're also doing a speculative memory
* test and we at or past the end, bump up Maxmem
* so that we keep going. The first bad page
* will terminate the loop.
*/
if (phys_avail[pa_indx] == pa) {
phys_avail[pa_indx] += PAGE_SIZE;
} else {
pa_indx++;
if (pa_indx == PHYS_AVAIL_ARRAY_END) {
printf(
"Too many holes in the physical address space, giving up\n");
pa_indx--;
full = TRUE;
goto do_dump_avail;
}
phys_avail[pa_indx++] = pa; /* start */
phys_avail[pa_indx] = pa + PAGE_SIZE; /* end */
}
physmem++;
do_dump_avail:
if (dump_avail[da_indx] == pa) {
dump_avail[da_indx] += PAGE_SIZE;
} else {
da_indx++;
if (da_indx == DUMP_AVAIL_ARRAY_END) {
da_indx--;
goto do_next;
}
dump_avail[da_indx++] = pa; /* start */
dump_avail[da_indx] = pa + PAGE_SIZE; /* end */
}
do_next:
if (full)
break;
}
}
*pte = 0;
invltlb();
/*
* XXX
* The last chunk must contain at least one page plus the message
* buffer to avoid complicating other code (message buffer address
* calculation, etc.).
*/
while (phys_avail[pa_indx - 1] + PAGE_SIZE +
round_page(msgbufsize) >= phys_avail[pa_indx]) {
physmem -= atop(phys_avail[pa_indx] - phys_avail[pa_indx - 1]);
phys_avail[pa_indx--] = 0;
phys_avail[pa_indx--] = 0;
}
Maxmem = atop(phys_avail[pa_indx]);
/* Trim off space for the message buffer. */
phys_avail[pa_indx] -= round_page(msgbufsize);
/* Map the message buffer. */
for (off = 0; off < round_page(msgbufsize); off += PAGE_SIZE)
pmap_kenter((vm_offset_t)msgbufp + off, phys_avail[pa_indx] +
off);
}
void
init386(first)
int first;
{
struct gate_descriptor *gdp;
int gsel_tss, metadata_missing, x, pa;
size_t kstack0_sz;
struct pcpu *pc;
thread0.td_kstack = proc0kstack;
thread0.td_kstack_pages = KSTACK_PAGES;
kstack0_sz = thread0.td_kstack_pages * PAGE_SIZE;
thread0.td_pcb = (struct pcb *)(thread0.td_kstack + kstack0_sz) - 1;
/*
* This may be done better later if it gets more high level
* components in it. If so just link td->td_proc here.
*/
proc_linkup0(&proc0, &thread0);
/*
* Initialize DMAC
*/
pc98_init_dmac();
metadata_missing = 0;
if (bootinfo.bi_modulep) {
preload_metadata = (caddr_t)bootinfo.bi_modulep + KERNBASE;
preload_bootstrap_relocate(KERNBASE);
} else {
metadata_missing = 1;
}
if (envmode == 1)
kern_envp = static_env;
else if (bootinfo.bi_envp)
kern_envp = (caddr_t)bootinfo.bi_envp + KERNBASE;
/* Init basic tunables, hz etc */
init_param1();
/*
* Make gdt memory segments. All segments cover the full 4GB
* of address space and permissions are enforced at page level.
*/
gdt_segs[GCODE_SEL].ssd_limit = atop(0 - 1);
gdt_segs[GDATA_SEL].ssd_limit = atop(0 - 1);
gdt_segs[GUCODE_SEL].ssd_limit = atop(0 - 1);
gdt_segs[GUDATA_SEL].ssd_limit = atop(0 - 1);
gdt_segs[GUFS_SEL].ssd_limit = atop(0 - 1);
gdt_segs[GUGS_SEL].ssd_limit = atop(0 - 1);
pc = &__pcpu[0];
gdt_segs[GPRIV_SEL].ssd_limit = atop(0 - 1);
gdt_segs[GPRIV_SEL].ssd_base = (int) pc;
gdt_segs[GPROC0_SEL].ssd_base = (int) &pc->pc_common_tss;
for (x = 0; x < NGDT; x++)
ssdtosd(&gdt_segs[x], &gdt[x].sd);
r_gdt.rd_limit = NGDT * sizeof(gdt[0]) - 1;
r_gdt.rd_base = (int) gdt;
mtx_init(&dt_lock, "descriptor tables", NULL, MTX_SPIN);
lgdt(&r_gdt);
pcpu_init(pc, 0, sizeof(struct pcpu));
for (pa = first; pa < first + DPCPU_SIZE; pa += PAGE_SIZE)
pmap_kenter(pa + KERNBASE, pa);
dpcpu_init((void *)(first + KERNBASE), 0);
first += DPCPU_SIZE;
PCPU_SET(prvspace, pc);
PCPU_SET(curthread, &thread0);
PCPU_SET(curpcb, thread0.td_pcb);
/*
* Initialize mutexes.
*
* icu_lock: in order to allow an interrupt to occur in a critical
* section, to set pcpu->ipending (etc...) properly, we
* must be able to get the icu lock, so it can't be
* under witness.
*/
mutex_init();
mtx_init(&icu_lock, "icu", NULL, MTX_SPIN | MTX_NOWITNESS | MTX_NOPROFILE);
/* make ldt memory segments */
ldt_segs[LUCODE_SEL].ssd_limit = atop(0 - 1);
ldt_segs[LUDATA_SEL].ssd_limit = atop(0 - 1);
for (x = 0; x < sizeof ldt_segs / sizeof ldt_segs[0]; x++)
ssdtosd(&ldt_segs[x], &ldt[x].sd);
_default_ldt = GSEL(GLDT_SEL, SEL_KPL);
lldt(_default_ldt);
PCPU_SET(currentldt, _default_ldt);
/* exceptions */
for (x = 0; x < NIDT; x++)
setidt(x, &IDTVEC(rsvd), SDT_SYS386TGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
setidt(IDT_DE, &IDTVEC(div), SDT_SYS386TGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
setidt(IDT_DB, &IDTVEC(dbg), SDT_SYS386IGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
setidt(IDT_NMI, &IDTVEC(nmi), SDT_SYS386IGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
setidt(IDT_BP, &IDTVEC(bpt), SDT_SYS386IGT, SEL_UPL,
GSEL(GCODE_SEL, SEL_KPL));
setidt(IDT_OF, &IDTVEC(ofl), SDT_SYS386TGT, SEL_UPL,
GSEL(GCODE_SEL, SEL_KPL));
setidt(IDT_BR, &IDTVEC(bnd), SDT_SYS386TGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
setidt(IDT_UD, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
setidt(IDT_NM, &IDTVEC(dna), SDT_SYS386TGT, SEL_KPL
, GSEL(GCODE_SEL, SEL_KPL));
setidt(IDT_DF, 0, SDT_SYSTASKGT, SEL_KPL, GSEL(GPANIC_SEL, SEL_KPL));
setidt(IDT_FPUGP, &IDTVEC(fpusegm), SDT_SYS386TGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
setidt(IDT_TS, &IDTVEC(tss), SDT_SYS386TGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
setidt(IDT_NP, &IDTVEC(missing), SDT_SYS386TGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
setidt(IDT_SS, &IDTVEC(stk), SDT_SYS386TGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
setidt(IDT_GP, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
setidt(IDT_PF, &IDTVEC(page), SDT_SYS386IGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
setidt(IDT_MF, &IDTVEC(fpu), SDT_SYS386TGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
setidt(IDT_AC, &IDTVEC(align), SDT_SYS386TGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
setidt(IDT_MC, &IDTVEC(mchk), SDT_SYS386TGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
setidt(IDT_XF, &IDTVEC(xmm), SDT_SYS386TGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
setidt(IDT_SYSCALL, &IDTVEC(int0x80_syscall), SDT_SYS386TGT, SEL_UPL,
GSEL(GCODE_SEL, SEL_KPL));
r_idt.rd_limit = sizeof(idt0) - 1;
r_idt.rd_base = (int) idt;
lidt(&r_idt);
/*
* Initialize the i8254 before the console so that console
* initialization can use DELAY().
*/
i8254_init();
/*
* Initialize the console before we print anything out.
*/
cninit();
if (metadata_missing)
printf("WARNING: loader(8) metadata is missing!\n");
#ifdef DEV_ISA
atpic_startup();
#endif
#ifdef DDB
ksym_start = bootinfo.bi_symtab;
ksym_end = bootinfo.bi_esymtab;
#endif
kdb_init();
#ifdef KDB
if (boothowto & RB_KDB)
kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
#endif
finishidentcpu(); /* Final stage of CPU initialization */
setidt(IDT_UD, &IDTVEC(ill), SDT_SYS386TGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
setidt(IDT_GP, &IDTVEC(prot), SDT_SYS386TGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL));
initializecpu(); /* Initialize CPU registers */
/* make an initial tss so cpu can get interrupt stack on syscall! */
/* Note: -16 is so we can grow the trapframe if we came from vm86 */
PCPU_SET(common_tss.tss_esp0, thread0.td_kstack +
kstack0_sz - sizeof(struct pcb) - 16);
PCPU_SET(common_tss.tss_ss0, GSEL(GDATA_SEL, SEL_KPL));
gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
PCPU_SET(tss_gdt, &gdt[GPROC0_SEL].sd);
PCPU_SET(common_tssd, *PCPU_GET(tss_gdt));
PCPU_SET(common_tss.tss_ioopt, (sizeof (struct i386tss)) << 16);
ltr(gsel_tss);
/* pointer to selector slot for %fs/%gs */
PCPU_SET(fsgs_gdt, &gdt[GUFS_SEL].sd);
dblfault_tss.tss_esp = dblfault_tss.tss_esp0 = dblfault_tss.tss_esp1 =
dblfault_tss.tss_esp2 = (int)&dblfault_stack[sizeof(dblfault_stack)];
dblfault_tss.tss_ss = dblfault_tss.tss_ss0 = dblfault_tss.tss_ss1 =
dblfault_tss.tss_ss2 = GSEL(GDATA_SEL, SEL_KPL);
dblfault_tss.tss_cr3 = (int)IdlePTD;
dblfault_tss.tss_eip = (int)dblfault_handler;
dblfault_tss.tss_eflags = PSL_KERNEL;
dblfault_tss.tss_ds = dblfault_tss.tss_es =
dblfault_tss.tss_gs = GSEL(GDATA_SEL, SEL_KPL);
dblfault_tss.tss_fs = GSEL(GPRIV_SEL, SEL_KPL);
dblfault_tss.tss_cs = GSEL(GCODE_SEL, SEL_KPL);
dblfault_tss.tss_ldt = GSEL(GLDT_SEL, SEL_KPL);
vm86_initialize();
getmemsize(first);
init_param2(physmem);
/* now running on new page tables, configured,and u/iom is accessible */
msgbufinit(msgbufp, msgbufsize);
/* make a call gate to reenter kernel with */
gdp = &ldt[LSYS5CALLS_SEL].gd;
x = (int) &IDTVEC(lcall_syscall);
gdp->gd_looffset = x;
gdp->gd_selector = GSEL(GCODE_SEL,SEL_KPL);
gdp->gd_stkcpy = 1;
gdp->gd_type = SDT_SYS386CGT;
gdp->gd_dpl = SEL_UPL;
gdp->gd_p = 1;
gdp->gd_hioffset = x >> 16;
/* XXX does this work? */
/* XXX yes! */
ldt[LBSDICALLS_SEL] = ldt[LSYS5CALLS_SEL];
ldt[LSOL26CALLS_SEL] = ldt[LSYS5CALLS_SEL];
/* transfer to user mode */
_ucodesel = GSEL(GUCODE_SEL, SEL_UPL);
_udatasel = GSEL(GUDATA_SEL, SEL_UPL);
/* setup proc 0's pcb */
thread0.td_pcb->pcb_flags = 0;
thread0.td_pcb->pcb_cr3 = (int)IdlePTD;
thread0.td_pcb->pcb_ext = 0;
thread0.td_frame = &proc0_tf;
}
void
cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
{
}
void
spinlock_enter(void)
{
struct thread *td;
register_t flags;
td = curthread;
if (td->td_md.md_spinlock_count == 0) {
flags = intr_disable();
td->td_md.md_spinlock_count = 1;
td->td_md.md_saved_flags = flags;
} else
td->td_md.md_spinlock_count++;
critical_enter();
}
void
spinlock_exit(void)
{
struct thread *td;
register_t flags;
td = curthread;
critical_exit();
flags = td->td_md.md_saved_flags;
td->td_md.md_spinlock_count--;
if (td->td_md.md_spinlock_count == 0)
intr_restore(flags);
}
#if defined(I586_CPU) && !defined(NO_F00F_HACK)
static void f00f_hack(void *unused);
SYSINIT(f00f_hack, SI_SUB_INTRINSIC, SI_ORDER_FIRST, f00f_hack, NULL);
static void
f00f_hack(void *unused)
{
struct gate_descriptor *new_idt;
vm_offset_t tmp;
if (!has_f00f_bug)
return;
GIANT_REQUIRED;
printf("Intel Pentium detected, installing workaround for F00F bug\n");
tmp = kmem_alloc(kernel_map, PAGE_SIZE * 2);
if (tmp == 0)
panic("kmem_alloc returned 0");
/* Put the problematic entry (#6) at the end of the lower page. */
new_idt = (struct gate_descriptor*)
(tmp + PAGE_SIZE - 7 * sizeof(struct gate_descriptor));
bcopy(idt, new_idt, sizeof(idt0));
r_idt.rd_base = (u_int)new_idt;
lidt(&r_idt);
idt = new_idt;
if (vm_map_protect(kernel_map, tmp, tmp + PAGE_SIZE,
VM_PROT_READ, FALSE) != KERN_SUCCESS)
panic("vm_map_protect failed");
}
#endif /* defined(I586_CPU) && !NO_F00F_HACK */
/*
* Construct a PCB from a trapframe. This is called from kdb_trap() where
* we want to start a backtrace from the function that caused us to enter
* the debugger. We have the context in the trapframe, but base the trace
* on the PCB. The PCB doesn't have to be perfect, as long as it contains
* enough for a backtrace.
*/
void
makectx(struct trapframe *tf, struct pcb *pcb)
{
pcb->pcb_edi = tf->tf_edi;
pcb->pcb_esi = tf->tf_esi;
pcb->pcb_ebp = tf->tf_ebp;
pcb->pcb_ebx = tf->tf_ebx;
pcb->pcb_eip = tf->tf_eip;
pcb->pcb_esp = (ISPL(tf->tf_cs)) ? tf->tf_esp : (int)(tf + 1) - 8;
}
int
ptrace_set_pc(struct thread *td, u_long addr)
{
td->td_frame->tf_eip = addr;
return (0);
}
int
ptrace_single_step(struct thread *td)
{
td->td_frame->tf_eflags |= PSL_T;
return (0);
}
int
ptrace_clear_single_step(struct thread *td)
{
td->td_frame->tf_eflags &= ~PSL_T;
return (0);
}
int
fill_regs(struct thread *td, struct reg *regs)
{
struct pcb *pcb;
struct trapframe *tp;
tp = td->td_frame;
pcb = td->td_pcb;
+ regs->r_gs = pcb->pcb_gs;
+ return (fill_frame_regs(tp, regs));
+}
+
+int
+fill_frame_regs(struct trapframe *tp, struct reg *regs)
+{
regs->r_fs = tp->tf_fs;
regs->r_es = tp->tf_es;
regs->r_ds = tp->tf_ds;
regs->r_edi = tp->tf_edi;
regs->r_esi = tp->tf_esi;
regs->r_ebp = tp->tf_ebp;
regs->r_ebx = tp->tf_ebx;
regs->r_edx = tp->tf_edx;
regs->r_ecx = tp->tf_ecx;
regs->r_eax = tp->tf_eax;
regs->r_eip = tp->tf_eip;
regs->r_cs = tp->tf_cs;
regs->r_eflags = tp->tf_eflags;
regs->r_esp = tp->tf_esp;
regs->r_ss = tp->tf_ss;
- regs->r_gs = pcb->pcb_gs;
return (0);
}
int
set_regs(struct thread *td, struct reg *regs)
{
struct pcb *pcb;
struct trapframe *tp;
tp = td->td_frame;
if (!EFL_SECURE(regs->r_eflags, tp->tf_eflags) ||
!CS_SECURE(regs->r_cs))
return (EINVAL);
pcb = td->td_pcb;
tp->tf_fs = regs->r_fs;
tp->tf_es = regs->r_es;
tp->tf_ds = regs->r_ds;
tp->tf_edi = regs->r_edi;
tp->tf_esi = regs->r_esi;
tp->tf_ebp = regs->r_ebp;
tp->tf_ebx = regs->r_ebx;
tp->tf_edx = regs->r_edx;
tp->tf_ecx = regs->r_ecx;
tp->tf_eax = regs->r_eax;
tp->tf_eip = regs->r_eip;
tp->tf_cs = regs->r_cs;
tp->tf_eflags = regs->r_eflags;
tp->tf_esp = regs->r_esp;
tp->tf_ss = regs->r_ss;
pcb->pcb_gs = regs->r_gs;
return (0);
}
#ifdef CPU_ENABLE_SSE
static void
fill_fpregs_xmm(sv_xmm, sv_87)
struct savexmm *sv_xmm;
struct save87 *sv_87;
{
register struct env87 *penv_87 = &sv_87->sv_env;
register struct envxmm *penv_xmm = &sv_xmm->sv_env;
int i;
bzero(sv_87, sizeof(*sv_87));
/* FPU control/status */
penv_87->en_cw = penv_xmm->en_cw;
penv_87->en_sw = penv_xmm->en_sw;
penv_87->en_tw = penv_xmm->en_tw;
penv_87->en_fip = penv_xmm->en_fip;
penv_87->en_fcs = penv_xmm->en_fcs;
penv_87->en_opcode = penv_xmm->en_opcode;
penv_87->en_foo = penv_xmm->en_foo;
penv_87->en_fos = penv_xmm->en_fos;
/* FPU registers */
for (i = 0; i < 8; ++i)
sv_87->sv_ac[i] = sv_xmm->sv_fp[i].fp_acc;
}
static void
set_fpregs_xmm(sv_87, sv_xmm)
struct save87 *sv_87;
struct savexmm *sv_xmm;
{
register struct env87 *penv_87 = &sv_87->sv_env;
register struct envxmm *penv_xmm = &sv_xmm->sv_env;
int i;
/* FPU control/status */
penv_xmm->en_cw = penv_87->en_cw;
penv_xmm->en_sw = penv_87->en_sw;
penv_xmm->en_tw = penv_87->en_tw;
penv_xmm->en_fip = penv_87->en_fip;
penv_xmm->en_fcs = penv_87->en_fcs;
penv_xmm->en_opcode = penv_87->en_opcode;
penv_xmm->en_foo = penv_87->en_foo;
penv_xmm->en_fos = penv_87->en_fos;
/* FPU registers */
for (i = 0; i < 8; ++i)
sv_xmm->sv_fp[i].fp_acc = sv_87->sv_ac[i];
}
#endif /* CPU_ENABLE_SSE */
int
fill_fpregs(struct thread *td, struct fpreg *fpregs)
{
KASSERT(td == curthread || TD_IS_SUSPENDED(td),
("not suspended thread %p", td));
#ifdef DEV_NPX
npxgetregs(td);
#else
bzero(fpregs, sizeof(*fpregs));
#endif
#ifdef CPU_ENABLE_SSE
if (cpu_fxsr)
fill_fpregs_xmm(&td->td_pcb->pcb_user_save.sv_xmm,
(struct save87 *)fpregs);
else
#endif /* CPU_ENABLE_SSE */
bcopy(&td->td_pcb->pcb_user_save.sv_87, fpregs,
sizeof(*fpregs));
return (0);
}
int
set_fpregs(struct thread *td, struct fpreg *fpregs)
{
#ifdef CPU_ENABLE_SSE
if (cpu_fxsr)
set_fpregs_xmm((struct save87 *)fpregs,
&td->td_pcb->pcb_user_save.sv_xmm);
else
#endif /* CPU_ENABLE_SSE */
bcopy(fpregs, &td->td_pcb->pcb_user_save.sv_87,
sizeof(*fpregs));
#ifdef DEV_NPX
npxuserinited(td);
#endif
return (0);
}
/*
* Get machine context.
*/
int
get_mcontext(struct thread *td, mcontext_t *mcp, int flags)
{
struct trapframe *tp;
struct segment_descriptor *sdp;
tp = td->td_frame;
PROC_LOCK(curthread->td_proc);
mcp->mc_onstack = sigonstack(tp->tf_esp);
PROC_UNLOCK(curthread->td_proc);
mcp->mc_gs = td->td_pcb->pcb_gs;
mcp->mc_fs = tp->tf_fs;
mcp->mc_es = tp->tf_es;
mcp->mc_ds = tp->tf_ds;
mcp->mc_edi = tp->tf_edi;
mcp->mc_esi = tp->tf_esi;
mcp->mc_ebp = tp->tf_ebp;
mcp->mc_isp = tp->tf_isp;
mcp->mc_eflags = tp->tf_eflags;
if (flags & GET_MC_CLEAR_RET) {
mcp->mc_eax = 0;
mcp->mc_edx = 0;
mcp->mc_eflags &= ~PSL_C;
} else {
mcp->mc_eax = tp->tf_eax;
mcp->mc_edx = tp->tf_edx;
}
mcp->mc_ebx = tp->tf_ebx;
mcp->mc_ecx = tp->tf_ecx;
mcp->mc_eip = tp->tf_eip;
mcp->mc_cs = tp->tf_cs;
mcp->mc_esp = tp->tf_esp;
mcp->mc_ss = tp->tf_ss;
mcp->mc_len = sizeof(*mcp);
get_fpcontext(td, mcp);
sdp = &td->td_pcb->pcb_fsd;
mcp->mc_fsbase = sdp->sd_hibase << 24 | sdp->sd_lobase;
sdp = &td->td_pcb->pcb_gsd;
mcp->mc_gsbase = sdp->sd_hibase << 24 | sdp->sd_lobase;
bzero(mcp->mc_spare1, sizeof(mcp->mc_spare1));
bzero(mcp->mc_spare2, sizeof(mcp->mc_spare2));
return (0);
}
/*
* Set machine context.
*
* However, we don't set any but the user modifiable flags, and we won't
* touch the cs selector.
*/
int
set_mcontext(struct thread *td, const mcontext_t *mcp)
{
struct trapframe *tp;
int eflags, ret;
tp = td->td_frame;
if (mcp->mc_len != sizeof(*mcp))
return (EINVAL);
eflags = (mcp->mc_eflags & PSL_USERCHANGE) |
(tp->tf_eflags & ~PSL_USERCHANGE);
if ((ret = set_fpcontext(td, mcp)) == 0) {
tp->tf_fs = mcp->mc_fs;
tp->tf_es = mcp->mc_es;
tp->tf_ds = mcp->mc_ds;
tp->tf_edi = mcp->mc_edi;
tp->tf_esi = mcp->mc_esi;
tp->tf_ebp = mcp->mc_ebp;
tp->tf_ebx = mcp->mc_ebx;
tp->tf_edx = mcp->mc_edx;
tp->tf_ecx = mcp->mc_ecx;
tp->tf_eax = mcp->mc_eax;
tp->tf_eip = mcp->mc_eip;
tp->tf_eflags = eflags;
tp->tf_esp = mcp->mc_esp;
tp->tf_ss = mcp->mc_ss;
td->td_pcb->pcb_gs = mcp->mc_gs;
ret = 0;
}
return (ret);
}
static void
get_fpcontext(struct thread *td, mcontext_t *mcp)
{
#ifndef DEV_NPX
mcp->mc_fpformat = _MC_FPFMT_NODEV;
mcp->mc_ownedfp = _MC_FPOWNED_NONE;
bzero(mcp->mc_fpstate, sizeof(mcp->mc_fpstate));
#else
mcp->mc_ownedfp = npxgetregs(td);
bcopy(&td->td_pcb->pcb_user_save, &mcp->mc_fpstate,
sizeof(mcp->mc_fpstate));
mcp->mc_fpformat = npxformat();
#endif
}
static int
set_fpcontext(struct thread *td, const mcontext_t *mcp)
{
if (mcp->mc_fpformat == _MC_FPFMT_NODEV)
return (0);
else if (mcp->mc_fpformat != _MC_FPFMT_387 &&
mcp->mc_fpformat != _MC_FPFMT_XMM)
return (EINVAL);
else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE)
/* We don't care what state is left in the FPU or PCB. */
fpstate_drop(td);
else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU ||
mcp->mc_ownedfp == _MC_FPOWNED_PCB) {
#ifdef DEV_NPX
#ifdef CPU_ENABLE_SSE
if (cpu_fxsr)
((union savefpu *)&mcp->mc_fpstate)->sv_xmm.sv_env.
en_mxcsr &= cpu_mxcsr_mask;
#endif
npxsetregs(td, (union savefpu *)&mcp->mc_fpstate);
#endif
} else
return (EINVAL);
return (0);
}
static void
fpstate_drop(struct thread *td)
{
critical_enter();
#ifdef DEV_NPX
if (PCPU_GET(fpcurthread) == td)
npxdrop();
#endif
/*
* XXX force a full drop of the npx. The above only drops it if we
* owned it. npxgetregs() has the same bug in the !cpu_fxsr case.
*
* XXX I don't much like npxgetregs()'s semantics of doing a full
* drop. Dropping only to the pcb matches fnsave's behaviour.
* We only need to drop to !PCB_INITDONE in sendsig(). But
* sendsig() is the only caller of npxgetregs()... perhaps we just
* have too many layers.
*/
curthread->td_pcb->pcb_flags &= ~(PCB_NPXINITDONE |
PCB_NPXUSERINITDONE);
critical_exit();
}
int
fill_dbregs(struct thread *td, struct dbreg *dbregs)
{
struct pcb *pcb;
if (td == NULL) {
dbregs->dr[0] = rdr0();
dbregs->dr[1] = rdr1();
dbregs->dr[2] = rdr2();
dbregs->dr[3] = rdr3();
dbregs->dr[4] = rdr4();
dbregs->dr[5] = rdr5();
dbregs->dr[6] = rdr6();
dbregs->dr[7] = rdr7();
} else {
pcb = td->td_pcb;
dbregs->dr[0] = pcb->pcb_dr0;
dbregs->dr[1] = pcb->pcb_dr1;
dbregs->dr[2] = pcb->pcb_dr2;
dbregs->dr[3] = pcb->pcb_dr3;
dbregs->dr[4] = 0;
dbregs->dr[5] = 0;
dbregs->dr[6] = pcb->pcb_dr6;
dbregs->dr[7] = pcb->pcb_dr7;
}
return (0);
}
int
set_dbregs(struct thread *td, struct dbreg *dbregs)
{
struct pcb *pcb;
int i;
if (td == NULL) {
load_dr0(dbregs->dr[0]);
load_dr1(dbregs->dr[1]);
load_dr2(dbregs->dr[2]);
load_dr3(dbregs->dr[3]);
load_dr4(dbregs->dr[4]);
load_dr5(dbregs->dr[5]);
load_dr6(dbregs->dr[6]);
load_dr7(dbregs->dr[7]);
} else {
/*
* Don't let an illegal value for dr7 get set. Specifically,
* check for undefined settings. Setting these bit patterns
* result in undefined behaviour and can lead to an unexpected
* TRCTRAP.
*/
for (i = 0; i < 4; i++) {
if (DBREG_DR7_ACCESS(dbregs->dr[7], i) == 0x02)
return (EINVAL);
if (DBREG_DR7_LEN(dbregs->dr[7], i) == 0x02)
return (EINVAL);
}
pcb = td->td_pcb;
/*
* Don't let a process set a breakpoint that is not within the
* process's address space. If a process could do this, it
* could halt the system by setting a breakpoint in the kernel
* (if ddb was enabled). Thus, we need to check to make sure
* that no breakpoints are being enabled for addresses outside
* process's address space.
*
* XXX - what about when the watched area of the user's
* address space is written into from within the kernel
* ... wouldn't that still cause a breakpoint to be generated
* from within kernel mode?
*/
if (DBREG_DR7_ENABLED(dbregs->dr[7], 0)) {
/* dr0 is enabled */
if (dbregs->dr[0] >= VM_MAXUSER_ADDRESS)
return (EINVAL);
}
if (DBREG_DR7_ENABLED(dbregs->dr[7], 1)) {
/* dr1 is enabled */
if (dbregs->dr[1] >= VM_MAXUSER_ADDRESS)
return (EINVAL);
}
if (DBREG_DR7_ENABLED(dbregs->dr[7], 2)) {
/* dr2 is enabled */
if (dbregs->dr[2] >= VM_MAXUSER_ADDRESS)
return (EINVAL);
}
if (DBREG_DR7_ENABLED(dbregs->dr[7], 3)) {
/* dr3 is enabled */
if (dbregs->dr[3] >= VM_MAXUSER_ADDRESS)
return (EINVAL);
}
pcb->pcb_dr0 = dbregs->dr[0];
pcb->pcb_dr1 = dbregs->dr[1];
pcb->pcb_dr2 = dbregs->dr[2];
pcb->pcb_dr3 = dbregs->dr[3];
pcb->pcb_dr6 = dbregs->dr[6];
pcb->pcb_dr7 = dbregs->dr[7];
pcb->pcb_flags |= PCB_DBREGS;
}
return (0);
}
/*
* Return > 0 if a hardware breakpoint has been hit, and the
* breakpoint was in user space. Return 0, otherwise.
*/
int
user_dbreg_trap(void)
{
u_int32_t dr7, dr6; /* debug registers dr6 and dr7 */
u_int32_t bp; /* breakpoint bits extracted from dr6 */
int nbp; /* number of breakpoints that triggered */
caddr_t addr[4]; /* breakpoint addresses */
int i;
dr7 = rdr7();
if ((dr7 & 0x000000ff) == 0) {
/*
* all GE and LE bits in the dr7 register are zero,
* thus the trap couldn't have been caused by the
* hardware debug registers
*/
return 0;
}
nbp = 0;
dr6 = rdr6();
bp = dr6 & 0x0000000f;
if (!bp) {
/*
* None of the breakpoint bits are set meaning this
* trap was not caused by any of the debug registers
*/
return 0;
}
/*
* at least one of the breakpoints were hit, check to see
* which ones and if any of them are user space addresses
*/
if (bp & 0x01) {
addr[nbp++] = (caddr_t)rdr0();
}
if (bp & 0x02) {
addr[nbp++] = (caddr_t)rdr1();
}
if (bp & 0x04) {
addr[nbp++] = (caddr_t)rdr2();
}
if (bp & 0x08) {
addr[nbp++] = (caddr_t)rdr3();
}
for (i = 0; i < nbp; i++) {
if (addr[i] < (caddr_t)VM_MAXUSER_ADDRESS) {
/*
* addr[i] is in user space
*/
return nbp;
}
}
/*
* None of the breakpoints are in user space.
*/
return 0;
}
#ifdef KDB
/*
* Provide inb() and outb() as functions. They are normally only available as
* inline functions, thus cannot be called from the debugger.
*/
/* silence compiler warnings */
u_char inb_(u_short);
void outb_(u_short, u_char);
u_char
inb_(u_short port)
{
return inb(port);
}
void
outb_(u_short port, u_char data)
{
outb(port, data);
}
#endif /* KDB */
Index: projects/altix/sys/powerpc/aim/locore64.S
===================================================================
--- projects/altix/sys/powerpc/aim/locore64.S (revision 218875)
+++ projects/altix/sys/powerpc/aim/locore64.S (revision 218876)
@@ -1,369 +1,369 @@
/* $FreeBSD$ */
/* $NetBSD: locore.S,v 1.24 2000/05/31 05:09:17 thorpej Exp $ */
/*-
* Copyright (C) 2001 Benno Rice
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
* Copyright (C) 1995, 1996 TooLs GmbH.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "assym.s"
#include <sys/syscall.h>
#include <machine/trap.h>
#include <machine/param.h>
#include <machine/spr.h>
#include <machine/asm.h>
/* Locate the per-CPU data structure */
#define GET_CPUINFO(r) \
mfsprg0 r
/*
* Compiled KERNBASE location and the kernel load address
*/
.globl kernbase
.set kernbase, KERNBASE
#define TMPSTKSZ 8192 /* 8K temporary stack */
#define OFWSTKSZ 4096 /* 4K Open Firmware stack */
/*
* Globals
*/
.data
.align 4
GLOBAL(tmpstk)
.space TMPSTKSZ
GLOBAL(ofwstk)
.space OFWSTKSZ
GLOBAL(esym)
.llong 0 /* end of symbol table */
GLOBAL(ofmsr)
.llong 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */
#define INTRCNT_COUNT 256 /* max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */
GLOBAL(intrnames)
.space INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
GLOBAL(eintrnames)
.align 4
GLOBAL(intrcnt)
.space INTRCNT_COUNT * 4 * 2
GLOBAL(eintrcnt)
/*
* File-scope for locore.S
*/
idle_u:
.llong 0 /* fake uarea during idle after exit */
openfirmware_entry:
.llong 0 /* Open Firmware entry point */
srsave:
.llong 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.text
.globl btext
btext:
/*
* This symbol is here for the benefit of kvm_mkdb, and is supposed to
* mark the start of kernel text.
*/
.globl kernel_text
kernel_text:
/*
* Startup entry. Note, this must be the first thing in the text
* segment!
*/
.text
ASENTRY(__start)
li 8,0
li 9,0x100
mtctr 9
1:
dcbf 0,8
icbi 0,8
addi 8,8,0x20
bdnz 1b
sync
isync
/* Save the argument pointer and length */
mr 20,6
mr 21,7
lis 8,openfirmware_entry@ha
std 5,openfirmware_entry@l(8) /* save client interface handler */
/* Set up the stack pointer */
lis 1,(tmpstk+TMPSTKSZ-48)@ha
addi 1,1,(tmpstk+TMPSTKSZ-48)@l
/* Set up the TOC pointer */
lis 2,tocbase@ha
ld 2,tocbase@l(2)
mfmsr 0
lis 9,ofmsr@ha
stdu 0,ofmsr@l(9)
mfsprg0 0 /* save SPRG0-3 */
std 0,8(9) /* ofmsr[1] = sprg0 */
mfsprg1 0
std 0,16(9) /* ofmsr[2] = sprg1 */
mfsprg2 0
std 0,24(9) /* ofmsr[3] = sprg2 */
mfsprg3 0
std 0,32(9) /* ofmsr[4] = sprg3 */
/* Switch to 64-bit mode */
mfmsr 9
li 8,1
insrdi 9,8,1,0
mtmsrd 9
- bl .OF_initial_setup
+ bl OF_initial_setup
nop
lis 4,end@ha
addi 4,4,end@l
mr 5,4
lis 3,kernbase@ha
addi 3,3,kernbase@l
/* Restore the argument pointer and length */
mr 6,20
mr 7,21
- bl .powerpc_init
+ bl powerpc_init
nop
mr %r1, %r3
li %r3, 0
std %r3, 0(%r1)
- bl .mi_startup
+ bl mi_startup
nop
- b .OF_exit
+ b OF_exit
nop
/*
* PPC64 ABI TOC base
*/
.align 3
.globl tocbase
tocbase:
.llong .TOC.@tocbase
/*
* Open Firmware Real-mode Entry Point. This is a huge pain.
*/
ASENTRY(ofw_32bit_mode_entry)
mflr %r0
std %r0,16(%r1)
stdu %r1,-208(%r1)
/*
* We need to save the following, because OF's register save/
* restore code assumes that the contents of registers are
* at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
* get placed in that order in the stack.
*/
mfcr %r4
std %r4,48(%r1)
std %r13,56(%r1)
std %r14,64(%r1)
std %r15,72(%r1)
std %r16,80(%r1)
std %r17,88(%r1)
std %r18,96(%r1)
std %r19,104(%r1)
std %r20,112(%r1)
std %r21,120(%r1)
std %r22,128(%r1)
std %r23,136(%r1)
std %r24,144(%r1)
std %r25,152(%r1)
std %r26,160(%r1)
std %r27,168(%r1)
std %r28,176(%r1)
std %r29,184(%r1)
std %r30,192(%r1)
std %r31,200(%r1)
/* Record the old MSR */
mfmsr %r6
/* read client interface handler */
lis %r4,openfirmware_entry@ha
ld %r4,openfirmware_entry@l(%r4)
/*
* Set the MSR to the OF value. This has the side effect of disabling
* exceptions, which is important for the next few steps.
*/
lis %r5,ofmsr@ha
ld %r5,ofmsr@l(%r5)
mtmsrd %r5
isync
/*
* Set up OF stack. This needs to be accessible in real mode and
* use the 32-bit ABI stack frame format. The pointer to the current
* kernel stack is placed at the very top of the stack along with
* the old MSR so we can get them back later.
*/
mr %r5,%r1
lis %r1,(ofwstk+OFWSTKSZ-32)@ha
addi %r1,%r1,(ofwstk+OFWSTKSZ-32)@l
std %r5,8(%r1) /* Save real stack pointer */
std %r2,16(%r1) /* Save old TOC */
std %r6,24(%r1) /* Save old MSR */
li %r5,0
stw %r5,4(%r1)
stw %r5,0(%r1)
/* Finally, branch to OF */
mtctr %r4
bctrl
/* Reload stack pointer and MSR from the OFW stack */
ld %r6,24(%r1)
ld %r2,16(%r1)
ld %r1,8(%r1)
/* Now set the real MSR */
mtmsrd %r6
isync
/* Sign-extend the return value from OF */
extsw %r3,%r3
/* Restore all the non-volatile registers */
ld %r5,48(%r1)
mtcr %r5
ld %r13,56(%r1)
ld %r14,64(%r1)
ld %r15,72(%r1)
ld %r16,80(%r1)
ld %r17,88(%r1)
ld %r18,96(%r1)
ld %r19,104(%r1)
ld %r20,112(%r1)
ld %r21,120(%r1)
ld %r22,128(%r1)
ld %r23,136(%r1)
ld %r24,144(%r1)
ld %r25,152(%r1)
ld %r26,160(%r1)
ld %r27,168(%r1)
ld %r28,176(%r1)
ld %r29,184(%r1)
ld %r30,192(%r1)
ld %r31,200(%r1)
/* Restore the stack and link register */
ld %r1,0(%r1)
ld %r0,16(%r1)
mtlr %r0
blr
/*
* int setfault()
*
* Similar to setjmp to setup for handling faults on accesses to user memory.
* Any routine using this may only call bcopy, either the form below,
* or the (currently used) C code optimized, so it doesn't use any non-volatile
* registers.
*/
ASENTRY(setfault)
mflr 0
mfcr 12
mfsprg 4,0
ld 4,PC_CURTHREAD(4)
ld 4,TD_PCB(4)
std 3,PCB_ONFAULT(4)
std 0,0(3)
std 1,8(3)
std 2,16(3)
std %r12,24(%r3) /* Save the non-volatile GP regs. */
std %r13,24+1*8(%r3)
std %r14,24+2*8(%r3)
std %r15,24+3*8(%r3)
std %r16,24+4*8(%r3)
std %r17,24+5*8(%r3)
std %r18,24+6*8(%r3)
std %r19,24+7*8(%r3)
std %r20,24+8*8(%r3)
std %r21,24+9*8(%r3)
std %r22,24+10*8(%r3)
std %r23,24+11*8(%r3)
std %r24,24+12*8(%r3)
std %r25,24+13*8(%r3)
std %r26,24+14*8(%r3)
std %r27,24+15*8(%r3)
std %r28,24+16*8(%r3)
std %r29,24+17*8(%r3)
std %r30,24+18*8(%r3)
std %r31,24+19*8(%r3)
xor 3,3,3
blr
#include <powerpc/aim/trap_subr64.S>
Index: projects/altix/sys/powerpc/aim/swtch64.S
===================================================================
--- projects/altix/sys/powerpc/aim/swtch64.S (revision 218875)
+++ projects/altix/sys/powerpc/aim/swtch64.S (revision 218876)
@@ -1,286 +1,286 @@
/* $FreeBSD$ */
/* $NetBSD: locore.S,v 1.24 2000/05/31 05:09:17 thorpej Exp $ */
/*-
* Copyright (C) 2001 Benno Rice
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
* Copyright (C) 1995, 1996 TooLs GmbH.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "assym.s"
#include "opt_sched.h"
#include <sys/syscall.h>
#include <machine/trap.h>
#include <machine/param.h>
#include <machine/asm.h>
/*
* void cpu_throw(struct thread *old, struct thread *new)
*/
ENTRY(cpu_throw)
mr %r15, %r4
b cpu_switchin
/*
* void cpu_switch(struct thread *old,
* struct thread *new,
* struct mutex *mtx);
*
* Switch to a new thread saving the current state in the old thread.
*/
ENTRY(cpu_switch)
ld %r6,TD_PCB(%r3) /* Get the old thread's PCB ptr */
std %r12,PCB_CONTEXT(%r6) /* Save the non-volatile GP regs.
These can now be used for scratch */
std %r13,PCB_CONTEXT+1*8(%r6)
std %r14,PCB_CONTEXT+2*8(%r6)
std %r15,PCB_CONTEXT+3*8(%r6)
std %r16,PCB_CONTEXT+4*8(%r6)
std %r17,PCB_CONTEXT+5*8(%r6)
std %r18,PCB_CONTEXT+6*8(%r6)
std %r19,PCB_CONTEXT+7*8(%r6)
std %r20,PCB_CONTEXT+8*8(%r6)
std %r21,PCB_CONTEXT+9*8(%r6)
std %r22,PCB_CONTEXT+10*8(%r6)
std %r23,PCB_CONTEXT+11*8(%r6)
std %r24,PCB_CONTEXT+12*8(%r6)
std %r25,PCB_CONTEXT+13*8(%r6)
std %r26,PCB_CONTEXT+14*8(%r6)
std %r27,PCB_CONTEXT+15*8(%r6)
std %r28,PCB_CONTEXT+16*8(%r6)
std %r29,PCB_CONTEXT+17*8(%r6)
std %r30,PCB_CONTEXT+18*8(%r6)
std %r31,PCB_CONTEXT+19*8(%r6)
mfcr %r16 /* Save the condition register */
std %r16,PCB_CR(%r6)
mflr %r16 /* Save the link register */
std %r16,PCB_LR(%r6)
std %r1,PCB_SP(%r6) /* Save the stack pointer */
std %r2,PCB_TOC(%r6) /* Save the TOC pointer */
mr %r14,%r3 /* Copy the old thread ptr... */
mr %r15,%r4 /* and the new thread ptr in scratch */
mr %r16,%r5 /* and the new lock */
mr %r17,%r6 /* and the PCB */
stdu %r1,-48(%r1)
lwz %r7,PCB_FLAGS(%r17)
/* Save FPU context if needed */
andi. %r7, %r7, PCB_FPU
beq .L1
- bl .save_fpu
+ bl save_fpu
nop
.L1:
mr %r3,%r14 /* restore old thread ptr */
lwz %r7,PCB_FLAGS(%r17)
/* Save Altivec context if needed */
andi. %r7, %r7, PCB_VEC
beq .L2
- bl .save_vec
+ bl save_vec
nop
.L2:
mr %r3,%r14 /* restore old thread ptr */
- bl .pmap_deactivate /* Deactivate the current pmap */
+ bl pmap_deactivate /* Deactivate the current pmap */
nop
addi %r1,%r1,48
std %r16,TD_LOCK(%r14) /* ULE: update old thread's lock */
cpu_switchin:
#if defined(SMP) && defined(SCHED_ULE)
/* Wait for the new thread to become unblocked */
lis %r6,blocked_lock@ha
addi %r6,%r6,blocked_lock@l
blocked_loop:
ld %r7,TD_LOCK(%r15)
cmpd %r6,%r7
beq blocked_loop
#endif
mfsprg %r7,0 /* Get the pcpu pointer */
std %r15,PC_CURTHREAD(%r7) /* Store new current thread */
ld %r17,TD_PCB(%r15) /* Store new current PCB */
std %r17,PC_CURPCB(%r7)
stdu %r1,-48(%r1)
mr %r3,%r15 /* Get new thread ptr */
- bl .pmap_activate /* Activate the new address space */
+ bl pmap_activate /* Activate the new address space */
nop
lwz %r6, PCB_FLAGS(%r17)
/* Restore FPU context if needed */
andi. %r6, %r6, PCB_FPU
beq .L3
mr %r3,%r15 /* Pass curthread to enable_fpu */
- bl .enable_fpu
+ bl enable_fpu
nop
.L3:
lwz %r6, PCB_FLAGS(%r17)
/* Restore Altivec context if needed */
andi. %r6, %r6, PCB_VEC
beq .L4
mr %r3,%r15 /* Pass curthread to enable_vec */
- bl .enable_vec
+ bl enable_vec
nop
/* thread to restore is in r3 */
.L4:
addi %r1,%r1,48
mr %r3,%r17 /* Recover PCB ptr */
ld %r12,PCB_CONTEXT(%r3) /* Load the non-volatile GP regs. */
ld %r13,PCB_CONTEXT+1*8(%r3)
ld %r14,PCB_CONTEXT+2*8(%r3)
ld %r15,PCB_CONTEXT+3*8(%r3)
ld %r16,PCB_CONTEXT+4*8(%r3)
ld %r17,PCB_CONTEXT+5*8(%r3)
ld %r18,PCB_CONTEXT+6*8(%r3)
ld %r19,PCB_CONTEXT+7*8(%r3)
ld %r20,PCB_CONTEXT+8*8(%r3)
ld %r21,PCB_CONTEXT+9*8(%r3)
ld %r22,PCB_CONTEXT+10*8(%r3)
ld %r23,PCB_CONTEXT+11*8(%r3)
ld %r24,PCB_CONTEXT+12*8(%r3)
ld %r25,PCB_CONTEXT+13*8(%r3)
ld %r26,PCB_CONTEXT+14*8(%r3)
ld %r27,PCB_CONTEXT+15*8(%r3)
ld %r28,PCB_CONTEXT+16*8(%r3)
ld %r29,PCB_CONTEXT+17*8(%r3)
ld %r30,PCB_CONTEXT+18*8(%r3)
ld %r31,PCB_CONTEXT+19*8(%r3)
ld %r5,PCB_CR(%r3) /* Load the condition register */
mtcr %r5
ld %r5,PCB_LR(%r3) /* Load the link register */
mtlr %r5
ld %r1,PCB_SP(%r3) /* Load the stack pointer */
ld %r2,PCB_TOC(%r3) /* Load the TOC pointer */
lis %r5,USER_ADDR@highesta /* Load the copyin/out segment reg */
ori %r5,%r5,USER_ADDR@highera
sldi %r5,%r5,32
oris %r5,%r5,USER_ADDR@ha
isync
slbie %r5
lis %r6,USER_SLB_SLBE@highesta
ori %r6,%r6,USER_SLB_SLBE@highera
sldi %r6,%r6,32
oris %r6,%r6,USER_SLB_SLBE@ha
ori %r6,%r6,USER_SLB_SLBE@l
ld %r5,PCB_AIM_USR_VSID(%r3)
slbmte %r5,%r6
isync
/*
* Perform a dummy stdcx. to clear any reservations we may have
* inherited from the previous thread. It doesn't matter if the
* stdcx succeeds or not. pcb_context[0] can be clobbered.
*/
stdcx. %r1, 0, %r3
blr
/*
* savectx(pcb)
* Update pcb, saving current processor state
*/
ENTRY(savectx)
std %r12,PCB_CONTEXT(%r3) /* Save the non-volatile GP regs. */
std %r13,PCB_CONTEXT+1*8(%r3)
std %r14,PCB_CONTEXT+2*8(%r3)
std %r15,PCB_CONTEXT+3*8(%r3)
std %r16,PCB_CONTEXT+4*8(%r3)
std %r17,PCB_CONTEXT+5*8(%r3)
std %r18,PCB_CONTEXT+6*8(%r3)
std %r19,PCB_CONTEXT+7*8(%r3)
std %r20,PCB_CONTEXT+8*8(%r3)
std %r21,PCB_CONTEXT+9*8(%r3)
std %r22,PCB_CONTEXT+10*8(%r3)
std %r23,PCB_CONTEXT+11*8(%r3)
std %r24,PCB_CONTEXT+12*8(%r3)
std %r25,PCB_CONTEXT+13*8(%r3)
std %r26,PCB_CONTEXT+14*8(%r3)
std %r27,PCB_CONTEXT+15*8(%r3)
std %r28,PCB_CONTEXT+16*8(%r3)
std %r29,PCB_CONTEXT+17*8(%r3)
std %r30,PCB_CONTEXT+18*8(%r3)
std %r31,PCB_CONTEXT+19*8(%r3)
mfcr %r4 /* Save the condition register */
std %r4,PCB_CR(%r3)
std %r2,PCB_TOC(%r3) /* Save the TOC pointer */
blr
/*
* fork_trampoline()
* Set up the return from cpu_fork()
*/
ENTRY(fork_trampoline)
ld %r3,CF_FUNC(%r1)
ld %r4,CF_ARG0(%r1)
ld %r5,CF_ARG1(%r1)
stdu %r1,-48(%r1)
- bl .fork_exit
+ bl fork_exit
nop
addi %r1,%r1,48+CF_SIZE-FSP /* Allow 8 bytes in front of
trapframe to simulate FRAME_SETUP
does when allocating space for
a frame pointer/saved LR */
b trapexit
nop
Index: projects/altix/sys/powerpc/aim/trap_subr64.S
===================================================================
--- projects/altix/sys/powerpc/aim/trap_subr64.S (revision 218875)
+++ projects/altix/sys/powerpc/aim/trap_subr64.S (revision 218876)
@@ -1,648 +1,648 @@
/* $FreeBSD$ */
/* $NetBSD: trap_subr.S,v 1.20 2002/04/22 23:20:08 kleink Exp $ */
/*-
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
* Copyright (C) 1995, 1996 TooLs GmbH.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* NOTICE: This is not a standalone file. to use it, #include it in
* your port's locore.S, like so:
*
* #include <powerpc/aim/trap_subr.S>
*/
/*
* Save/restore segment registers
*/
/*
* Restore SRs for a pmap
*
* Requires that r28-r31 be scratch, with r28 initialized to the SLB cache
*/
/*
* User SRs are loaded through a pointer to the current pmap.
*/
restore_usersrs:
GET_CPUINFO(%r28);
ld %r28,PC_USERSLB(%r28);
li %r29, 0 /* Set the counter to zero */
slbia
slbmfee %r31,%r29
clrrdi %r31,%r31,28
slbie %r31
instuserslb:
ld %r31, 0(%r28); /* Load SLB entry pointer */
cmpli 0, %r31, 0; /* If NULL, stop */
beqlr;
ld %r30, 0(%r31) /* Load SLBV */
ld %r31, 8(%r31) /* Load SLBE */
or %r31, %r31, %r29 /* Set SLBE slot */
slbmte %r30, %r31; /* Install SLB entry */
addi %r28, %r28, 8; /* Advance pointer */
addi %r29, %r29, 1;
cmpli 0, %r29, 64; /* Repeat if we are not at the end */
blt instuserslb;
blr;
/*
* Kernel SRs are loaded directly from the PCPU fields
*/
restore_kernsrs:
GET_CPUINFO(%r28);
addi %r28,%r28,PC_KERNSLB;
li %r29, 0 /* Set the counter to zero */
slbia
slbmfee %r31,%r29
clrrdi %r31,%r31,28
slbie %r31
instkernslb:
ld %r31, 8(%r28); /* Load SLBE */
cmpli 0, %r31, 0; /* If SLBE is not valid, stop */
beqlr;
ld %r30, 0(%r28) /* Load SLBV */
slbmte %r30, %r31; /* Install SLB entry */
addi %r28, %r28, 16; /* Advance pointer */
addi %r29, %r29, 1;
cmpli 0, %r29, USER_SLB_SLOT; /* Repeat if we are not at the end */
blt instkernslb;
blr;
/*
* FRAME_SETUP assumes:
* SPRG1 SP (1)
* SPRG3 trap type
* savearea r27-r31,DAR,DSISR (DAR & DSISR only for DSI traps)
* r28 LR
* r29 CR
* r30 scratch
* r31 scratch
* r1 kernel stack
* SRR0/1 as at start of trap
*/
#define FRAME_SETUP(savearea) \
/* Have to enable translation to allow access of kernel stack: */ \
GET_CPUINFO(%r31); \
mfsrr0 %r30; \
std %r30,(savearea+CPUSAVE_SRR0)(%r31); /* save SRR0 */ \
mfsrr1 %r30; \
std %r30,(savearea+CPUSAVE_SRR1)(%r31); /* save SRR1 */ \
mfmsr %r30; \
ori %r30,%r30,(PSL_DR|PSL_IR|PSL_RI)@l; /* relocation on */ \
mtmsr %r30; /* stack can now be accessed */ \
isync; \
mfsprg1 %r31; /* get saved SP */ \
stdu %r31,-(FRAMELEN+288)(%r1); /* save it in the callframe */ \
std %r0, FRAME_0+48(%r1); /* save r0 in the trapframe */ \
std %r31,FRAME_1+48(%r1); /* save SP " " */ \
std %r2, FRAME_2+48(%r1); /* save r2 " " */ \
std %r28,FRAME_LR+48(%r1); /* save LR " " */ \
std %r29,FRAME_CR+48(%r1); /* save CR " " */ \
GET_CPUINFO(%r2); \
ld %r27,(savearea+CPUSAVE_R27)(%r2); /* get saved r27 */ \
ld %r28,(savearea+CPUSAVE_R28)(%r2); /* get saved r28 */ \
ld %r29,(savearea+CPUSAVE_R29)(%r2); /* get saved r29 */ \
ld %r30,(savearea+CPUSAVE_R30)(%r2); /* get saved r30 */ \
ld %r31,(savearea+CPUSAVE_R31)(%r2); /* get saved r31 */ \
std %r3, FRAME_3+48(%r1); /* save r3-r31 */ \
std %r4, FRAME_4+48(%r1); \
std %r5, FRAME_5+48(%r1); \
std %r6, FRAME_6+48(%r1); \
std %r7, FRAME_7+48(%r1); \
std %r8, FRAME_8+48(%r1); \
std %r9, FRAME_9+48(%r1); \
std %r10, FRAME_10+48(%r1); \
std %r11, FRAME_11+48(%r1); \
std %r12, FRAME_12+48(%r1); \
std %r13, FRAME_13+48(%r1); \
std %r14, FRAME_14+48(%r1); \
std %r15, FRAME_15+48(%r1); \
std %r16, FRAME_16+48(%r1); \
std %r17, FRAME_17+48(%r1); \
std %r18, FRAME_18+48(%r1); \
std %r19, FRAME_19+48(%r1); \
std %r20, FRAME_20+48(%r1); \
std %r21, FRAME_21+48(%r1); \
std %r22, FRAME_22+48(%r1); \
std %r23, FRAME_23+48(%r1); \
std %r24, FRAME_24+48(%r1); \
std %r25, FRAME_25+48(%r1); \
std %r26, FRAME_26+48(%r1); \
std %r27, FRAME_27+48(%r1); \
std %r28, FRAME_28+48(%r1); \
std %r29, FRAME_29+48(%r1); \
std %r30, FRAME_30+48(%r1); \
std %r31, FRAME_31+48(%r1); \
ld %r28,(savearea+CPUSAVE_AIM_DAR)(%r2); /* saved DAR */ \
ld %r29,(savearea+CPUSAVE_AIM_DSISR)(%r2);/* saved DSISR */\
ld %r30,(savearea+CPUSAVE_SRR0)(%r2); /* saved SRR0 */ \
ld %r31,(savearea+CPUSAVE_SRR1)(%r2); /* saved SRR1 */ \
mfxer %r3; \
mfctr %r4; \
mfsprg3 %r5; \
std %r3, FRAME_XER+48(1); /* save xer/ctr/exc */ \
std %r4, FRAME_CTR+48(1); \
std %r5, FRAME_EXC+48(1); \
std %r28,FRAME_AIM_DAR+48(1); \
std %r29,FRAME_AIM_DSISR+48(1); /* save dsisr/srr0/srr1 */ \
std %r30,FRAME_SRR0+48(1); \
std %r31,FRAME_SRR1+48(1)
#define FRAME_LEAVE(savearea) \
/* Now restore regs: */ \
ld %r2,FRAME_SRR0+48(%r1); \
ld %r3,FRAME_SRR1+48(%r1); \
ld %r4,FRAME_CTR+48(%r1); \
ld %r5,FRAME_XER+48(%r1); \
ld %r6,FRAME_LR+48(%r1); \
GET_CPUINFO(%r7); \
std %r2,(savearea+CPUSAVE_SRR0)(%r7); /* save SRR0 */ \
std %r3,(savearea+CPUSAVE_SRR1)(%r7); /* save SRR1 */ \
ld %r7,FRAME_CR+48(%r1); \
mtctr %r4; \
mtxer %r5; \
mtlr %r6; \
mtsprg1 %r7; /* save cr */ \
ld %r31,FRAME_31+48(%r1); /* restore r0-31 */ \
ld %r30,FRAME_30+48(%r1); \
ld %r29,FRAME_29+48(%r1); \
ld %r28,FRAME_28+48(%r1); \
ld %r27,FRAME_27+48(%r1); \
ld %r26,FRAME_26+48(%r1); \
ld %r25,FRAME_25+48(%r1); \
ld %r24,FRAME_24+48(%r1); \
ld %r23,FRAME_23+48(%r1); \
ld %r22,FRAME_22+48(%r1); \
ld %r21,FRAME_21+48(%r1); \
ld %r20,FRAME_20+48(%r1); \
ld %r19,FRAME_19+48(%r1); \
ld %r18,FRAME_18+48(%r1); \
ld %r17,FRAME_17+48(%r1); \
ld %r16,FRAME_16+48(%r1); \
ld %r15,FRAME_15+48(%r1); \
ld %r14,FRAME_14+48(%r1); \
ld %r13,FRAME_13+48(%r1); \
ld %r12,FRAME_12+48(%r1); \
ld %r11,FRAME_11+48(%r1); \
ld %r10,FRAME_10+48(%r1); \
ld %r9, FRAME_9+48(%r1); \
ld %r8, FRAME_8+48(%r1); \
ld %r7, FRAME_7+48(%r1); \
ld %r6, FRAME_6+48(%r1); \
ld %r5, FRAME_5+48(%r1); \
ld %r4, FRAME_4+48(%r1); \
ld %r3, FRAME_3+48(%r1); \
ld %r2, FRAME_2+48(%r1); \
ld %r0, FRAME_0+48(%r1); \
ld %r1, FRAME_1+48(%r1); \
/* Can't touch %r1 from here on */ \
mtsprg2 %r2; /* save r2 & r3 */ \
mtsprg3 %r3; \
/* Disable translation, machine check and recoverability: */ \
mfmsr %r2; \
andi. %r2,%r2,~(PSL_DR|PSL_IR|PSL_EE|PSL_ME|PSL_RI)@l; \
mtmsr %r2; \
isync; \
/* Decide whether we return to user mode: */ \
GET_CPUINFO(%r2); \
ld %r3,(savearea+CPUSAVE_SRR1)(%r2); \
mtcr %r3; \
bf 17,1f; /* branch if PSL_PR is false */ \
/* Restore user SRs */ \
GET_CPUINFO(%r3); \
std %r27,(savearea+CPUSAVE_R27)(%r3); \
std %r28,(savearea+CPUSAVE_R28)(%r3); \
std %r29,(savearea+CPUSAVE_R29)(%r3); \
std %r30,(savearea+CPUSAVE_R30)(%r3); \
std %r31,(savearea+CPUSAVE_R31)(%r3); \
mflr %r27; /* preserve LR */ \
bl restore_usersrs; /* uses r28-r31 */ \
mtlr %r27; \
ld %r31,(savearea+CPUSAVE_R31)(%r3); \
ld %r30,(savearea+CPUSAVE_R30)(%r3); \
ld %r29,(savearea+CPUSAVE_R29)(%r3); \
ld %r28,(savearea+CPUSAVE_R28)(%r3); \
ld %r27,(savearea+CPUSAVE_R27)(%r3); \
1: mfsprg1 %r2; /* restore cr */ \
mtcr %r2; \
GET_CPUINFO(%r2); \
ld %r3,(savearea+CPUSAVE_SRR0)(%r2); /* restore srr0 */ \
mtsrr0 %r3; \
ld %r3,(savearea+CPUSAVE_SRR1)(%r2); /* restore srr1 */ \
mtsrr1 %r3; \
mfsprg2 %r2; /* restore r2 & r3 */ \
mfsprg3 %r3
#ifdef SMP
/*
* Processor reset exception handler. These are typically
* the first instructions the processor executes after a
* software reset. We do this in two bits so that we are
* not still hanging around in the trap handling region
* once the MMU is turned on.
*/
.globl CNAME(rstcode), CNAME(rstsize)
CNAME(rstcode):
/* Explicitly set MSR[SF] */
mfmsr %r9
li %r8,1
insrdi %r9,%r8,1,0
mtmsrd %r9
isync
ba cpu_reset
CNAME(rstsize) = . - CNAME(rstcode)
cpu_reset:
lis %r1,(tmpstk+TMPSTKSZ-48)@ha /* get new SP */
addi %r1,%r1,(tmpstk+TMPSTKSZ-48)@l
lis %r3,tocbase@ha
ld %r2,tocbase@l(%r3)
lis %r3,1@l
- bl CNAME(.cpudep_ap_early_bootstrap) /* Set PCPU */
+ bl CNAME(cpudep_ap_early_bootstrap) /* Set PCPU */
nop
- bl CNAME(.pmap_cpu_bootstrap) /* Turn on virtual memory */
+ bl CNAME(pmap_cpu_bootstrap) /* Turn on virtual memory */
nop
- bl CNAME(.cpudep_ap_bootstrap) /* Set up PCPU and stack */
+ bl CNAME(cpudep_ap_bootstrap) /* Set up PCPU and stack */
nop
mr %r1,%r3 /* Use new stack */
- bl CNAME(.machdep_ap_bootstrap) /* And away! */
+ bl CNAME(machdep_ap_bootstrap) /* And away! */
nop
/* Should not be reached */
9:
b 9b
#endif
/*
* This code gets copied to all the trap vectors
* (except ISI/DSI, ALI, and the interrupts)
*/
.globl CNAME(trapcode),CNAME(trapsize)
CNAME(trapcode):
mtsprg1 %r1 /* save SP */
mflr %r1 /* Save the old LR in r1 */
mtsprg2 %r1 /* And then in SPRG2 */
li %r1, 0xA0 /* How to get the vector from LR */
bla generictrap /* LR & SPRG3 is exception # */
CNAME(trapsize) = .-CNAME(trapcode)
/*
* For ALI: has to save DSISR and DAR
*/
.globl CNAME(alitrap),CNAME(alisize)
CNAME(alitrap):
mtsprg1 %r1 /* save SP */
GET_CPUINFO(%r1)
std %r27,(PC_TEMPSAVE+CPUSAVE_R27)(%r1) /* free r27-r31 */
std %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
std %r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
std %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
std %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
mfdar %r30
mfdsisr %r31
std %r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1)
std %r31,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1)
mfsprg1 %r1 /* restore SP, in case of branch */
mflr %r28 /* save LR */
mfcr %r29 /* save CR */
/* Put our exception vector in SPRG3 */
li %r31, EXC_ALI
mtsprg3 %r31
/* Test whether we already had PR set */
mfsrr1 %r31
mtcr %r31
bla s_trap
CNAME(alisize) = .-CNAME(alitrap)
/*
* Similar to the above for DSI
* Has to handle BAT spills
* and standard pagetable spills
*/
.globl CNAME(dsitrap),CNAME(dsisize)
CNAME(dsitrap):
mtsprg1 %r1 /* save SP */
GET_CPUINFO(%r1)
std %r27,(PC_DISISAVE+CPUSAVE_R27)(%r1) /* free r27-r31 */
std %r28,(PC_DISISAVE+CPUSAVE_R28)(%r1)
std %r29,(PC_DISISAVE+CPUSAVE_R29)(%r1)
std %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1)
std %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1)
mfsprg1 %r1 /* restore SP */
mfcr %r29 /* save CR */
mfxer %r30 /* save XER */
mtsprg2 %r30 /* in SPRG2 */
mfsrr1 %r31 /* test kernel mode */
mtcr %r31
mflr %r28 /* save LR (SP already saved) */
bla disitrap
CNAME(dsisize) = .-CNAME(dsitrap)
/*
* Preamble code for DSI/ISI traps
*/
disitrap:
/* Write the trap vector to SPRG3 by computing LR & 0xff00 */
mflr %r1
andi. %r1,%r1,0xff00
mtsprg3 %r1
GET_CPUINFO(%r1)
ld %r31,(PC_DISISAVE+CPUSAVE_R27)(%r1)
std %r31,(PC_TEMPSAVE+CPUSAVE_R27)(%r1)
ld %r30,(PC_DISISAVE+CPUSAVE_R28)(%r1)
std %r30,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
ld %r31,(PC_DISISAVE+CPUSAVE_R29)(%r1)
std %r31,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
ld %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1)
std %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
ld %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1)
std %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
mfdar %r30
mfdsisr %r31
std %r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1)
std %r31,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1)
#ifdef KDB
/* Try and detect a kernel stack overflow */
mfsrr1 %r31
mtcr %r31
bt 17,realtrap /* branch is user mode */
mfsprg1 %r31 /* get old SP */
sub. %r30,%r31,%r30 /* SP - DAR */
bge 1f
neg %r30,%r30 /* modulo value */
1: cmpldi %cr0,%r30,4096 /* is DAR within a page of SP? */
bge %cr0,realtrap /* no, too far away. */
/* Now convert this DSI into a DDB trap. */
GET_CPUINFO(%r1)
ld %r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1) /* get DAR */
std %r30,(PC_DBSAVE +CPUSAVE_AIM_DAR)(%r1) /* save DAR */
ld %r30,(PC_TEMPSAVE+CPUSAVE_AIM_DSISR)(%r1) /* get DSISR */
std %r30,(PC_DBSAVE +CPUSAVE_AIM_DSISR)(%r1) /* save DSISR */
ld %r31,(PC_DISISAVE+CPUSAVE_R27)(%r1) /* get r27 */
std %r31,(PC_DBSAVE +CPUSAVE_R27)(%r1) /* save r27 */
ld %r30,(PC_DISISAVE+CPUSAVE_R28)(%r1) /* get r28 */
std %r30,(PC_DBSAVE +CPUSAVE_R28)(%r1) /* save r28 */
ld %r31,(PC_DISISAVE+CPUSAVE_R29)(%r1) /* get r29 */
std %r31,(PC_DBSAVE +CPUSAVE_R29)(%r1) /* save r29 */
ld %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) /* get r30 */
std %r30,(PC_DBSAVE +CPUSAVE_R30)(%r1) /* save r30 */
ld %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) /* get r31 */
std %r31,(PC_DBSAVE +CPUSAVE_R31)(%r1) /* save r31 */
b dbtrap
#endif
/* XXX need stack probe here */
realtrap:
/* Test whether we already had PR set */
mfsrr1 %r1
mtcr %r1
mfsprg1 %r1 /* restore SP (might have been
overwritten) */
bf 17,k_trap /* branch if PSL_PR is false */
GET_CPUINFO(%r1)
ld %r1,PC_CURPCB(%r1)
mr %r27,%r28 /* Save LR, r29 */
mtsprg2 %r29
bl restore_kernsrs /* enable kernel mapping */
mfsprg2 %r29
mr %r28,%r27
ba s_trap
/*
* generictrap does some standard setup for trap handling to minimize
* the code that need be installed in the actual vectors. It expects
* the following conditions.
*
* R1 - Trap vector = LR & (0xff00 | R1)
* SPRG1 - Original R1 contents
* SPRG2 - Original LR
*/
generictrap:
/* Save R1 for computing the exception vector */
mtsprg3 %r1
/* Save interesting registers */
GET_CPUINFO(%r1)
std %r27,(PC_TEMPSAVE+CPUSAVE_R27)(%r1) /* free r27-r31 */
std %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
std %r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
std %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
std %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
mfdar %r30
std %r30,(PC_TEMPSAVE+CPUSAVE_AIM_DAR)(%r1)
mfsprg1 %r1 /* restore SP, in case of branch */
mfsprg2 %r28 /* save LR */
mfcr %r29 /* save CR */
/* Compute the exception vector from the link register */
mfsprg3 %r31
ori %r31,%r31,0xff00
mflr %r30
and %r30,%r30,%r31
mtsprg3 %r30
/* Test whether we already had PR set */
mfsrr1 %r31
mtcr %r31
s_trap:
bf 17,k_trap /* branch if PSL_PR is false */
GET_CPUINFO(%r1)
u_trap:
ld %r1,PC_CURPCB(%r1)
mr %r27,%r28 /* Save LR, r29 */
mtsprg2 %r29
bl restore_kernsrs /* enable kernel mapping */
mfsprg2 %r29
mr %r28,%r27
/*
* Now the common trap catching code.
*/
k_trap:
FRAME_SETUP(PC_TEMPSAVE)
/* Call C interrupt dispatcher: */
trapagain:
lis %r3,tocbase@ha
ld %r2,tocbase@l(%r3)
addi %r3,%r1,48
- bl CNAME(.powerpc_interrupt)
+ bl CNAME(powerpc_interrupt)
nop
.globl CNAME(trapexit) /* backtrace code sentinel */
CNAME(trapexit):
/* Disable interrupts: */
mfmsr %r3
andi. %r3,%r3,~PSL_EE@l
mtmsr %r3
/* Test AST pending: */
ld %r5,FRAME_SRR1+48(%r1)
mtcr %r5
bf 17,1f /* branch if PSL_PR is false */
GET_CPUINFO(%r3) /* get per-CPU pointer */
ld %r4, PC_CURTHREAD(%r3) /* deref to get curthread */
lwz %r4, TD_FLAGS(%r4) /* get thread flags value */
lis %r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@h
ori %r5,%r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@l
and. %r4,%r4,%r5
beq 1f
mfmsr %r3 /* re-enable interrupts */
ori %r3,%r3,PSL_EE@l
mtmsr %r3
isync
lis %r3,tocbase@ha
ld %r2,tocbase@l(%r3)
addi %r3,%r1,48
- bl CNAME(.ast)
+ bl CNAME(ast)
nop
.globl CNAME(asttrapexit) /* backtrace code sentinel #2 */
CNAME(asttrapexit):
b trapexit /* test ast ret value ? */
1:
FRAME_LEAVE(PC_TEMPSAVE)
rfid
#if defined(KDB)
/*
* Deliberate entry to dbtrap
*/
ASENTRY(breakpoint)
mtsprg1 %r1
mfmsr %r3
mtsrr1 %r3
andi. %r3,%r3,~(PSL_EE|PSL_ME)@l
mtmsr %r3 /* disable interrupts */
isync
GET_CPUINFO(%r3)
std %r27,(PC_DBSAVE+CPUSAVE_R27)(%r3)
std %r28,(PC_DBSAVE+CPUSAVE_R28)(%r3)
std %r29,(PC_DBSAVE+CPUSAVE_R29)(%r3)
std %r30,(PC_DBSAVE+CPUSAVE_R30)(%r3)
std %r31,(PC_DBSAVE+CPUSAVE_R31)(%r3)
mflr %r28
li %r29,EXC_BPT
mtlr %r29
mfcr %r29
mtsrr0 %r28
/*
* Now the kdb trap catching code.
*/
dbtrap:
/* Write the trap vector to SPRG3 by computing LR & 0xff00 */
mflr %r1
andi. %r1,%r1,0xff00
mtsprg3 %r1
lis %r1,(tmpstk+TMPSTKSZ-48)@ha /* get new SP */
addi %r1,%r1,(tmpstk+TMPSTKSZ-48)@l
FRAME_SETUP(PC_DBSAVE)
/* Call C trap code: */
lis %r3,tocbase@ha
ld %r2,tocbase@l(%r3)
addi %r3,%r1,48
- bl CNAME(.db_trap_glue)
+ bl CNAME(db_trap_glue)
nop
or. %r3,%r3,%r3
bne dbleave
/* This wasn't for KDB, so switch to real trap: */
ld %r3,FRAME_EXC+48(%r1) /* save exception */
GET_CPUINFO(%r4)
std %r3,(PC_DBSAVE+CPUSAVE_R31)(%r4)
FRAME_LEAVE(PC_DBSAVE)
mtsprg1 %r1 /* prepare for entrance to realtrap */
GET_CPUINFO(%r1)
std %r27,(PC_TEMPSAVE+CPUSAVE_R27)(%r1)
std %r28,(PC_TEMPSAVE+CPUSAVE_R28)(%r1)
std %r29,(PC_TEMPSAVE+CPUSAVE_R29)(%r1)
std %r30,(PC_TEMPSAVE+CPUSAVE_R30)(%r1)
std %r31,(PC_TEMPSAVE+CPUSAVE_R31)(%r1)
mflr %r28
mfcr %r29
ld %r31,(PC_DBSAVE+CPUSAVE_R31)(%r1)
mtsprg3 %r31 /* SPRG3 was clobbered by FRAME_LEAVE */
mfsprg1 %r1
b realtrap
dbleave:
FRAME_LEAVE(PC_DBSAVE)
rfid
/*
* In case of KDB we want a separate trap catcher for it
*/
.globl CNAME(dblow),CNAME(dbsize)
CNAME(dblow):
mtsprg1 %r1 /* save SP */
mtsprg2 %r29 /* save r29 */
mfcr %r29 /* save CR in r29 */
mfsrr1 %r1
mtcr %r1
bf 17,1f /* branch if privileged */
/* Unprivileged case */
mtcr %r29 /* put the condition register back */
mfsprg2 %r29 /* ... and r29 */
mflr %r1 /* save LR */
mtsprg2 %r1 /* And then in SPRG2 */
li %r1, 0 /* How to get the vector from LR */
bla generictrap /* and we look like a generic trap */
1:
/* Privileged, so drop to KDB */
GET_CPUINFO(%r1)
std %r27,(PC_DBSAVE+CPUSAVE_R27)(%r1) /* free r27 */
std %r28,(PC_DBSAVE+CPUSAVE_R28)(%r1) /* free r28 */
mfsprg2 %r28 /* r29 holds cr... */
std %r28,(PC_DBSAVE+CPUSAVE_R29)(%r1) /* free r29 */
std %r30,(PC_DBSAVE+CPUSAVE_R30)(%r1) /* free r30 */
std %r31,(PC_DBSAVE+CPUSAVE_R31)(%r1) /* free r31 */
mflr %r28 /* save LR */
bla dbtrap
CNAME(dbsize) = .-CNAME(dblow)
#endif /* KDB */
Index: projects/altix/sys/powerpc/include/asm.h
===================================================================
--- projects/altix/sys/powerpc/include/asm.h (revision 218875)
+++ projects/altix/sys/powerpc/include/asm.h (revision 218876)
@@ -1,116 +1,111 @@
/*-
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
* Copyright (C) 1995, 1996 TooLs GmbH.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $NetBSD: asm.h,v 1.6.18.1 2000/07/25 08:37:14 kleink Exp $
* $FreeBSD$
*/
#ifndef _MACHINE_ASM_H_
#define _MACHINE_ASM_H_
#include <sys/cdefs.h>
-#ifdef PIC
+#if defined(PIC) && !defined(__powerpc64__)
#define PIC_PROLOGUE XXX
#define PIC_EPILOGUE XXX
#define PIC_PLT(x) x@plt
#ifdef __STDC__
#define PIC_GOT(x) XXX
#else /* not __STDC__ */
#define PIC_GOT(x) XXX
#endif /* __STDC__ */
#else
#define PIC_PROLOGUE
#define PIC_EPILOGUE
#define PIC_PLT(x) x
#define PIC_GOT(x) x
#endif
-#ifdef __powerpc64__
-#undef PIC_PLT
-#define PIC_PLT(x) __CONCAT(.,x)
-#endif
-
#define CNAME(csym) csym
#define ASMNAME(asmsym) asmsym
#ifdef __powerpc64__
#define HIDENAME(asmsym) __CONCAT(_,asmsym)
#else
#define HIDENAME(asmsym) __CONCAT(.,asmsym)
#endif
#define _GLOBAL(x) \
.data; .align 2; .globl x; x:
#ifdef __powerpc64__
#define _ENTRY(x) \
.text; .align 2; .globl x; .section ".opd","aw"; \
.align 3; x: \
- .quad .x,.TOC.@tocbase,0; .previous; \
- .align 4; .globl .x; .type .x,@function; .x:
+ .quad .L.x,.TOC.@tocbase,0; .size x,24; .previous; \
+ .align 4; .type x,@function; .L.x:
#else
#define _ENTRY(x) \
.text; .align 4; .globl x; .type x,@function; x:
#endif
#if defined(PROF) || (defined(_KERNEL) && defined(GPROF))
# define _PROF_PROLOGUE mflr 0; stw 0,4(1); bl _mcount
#else
# define _PROF_PROLOGUE
#endif
#define ENTRY(y) _ENTRY(CNAME(y)); _PROF_PROLOGUE
#define ASENTRY(y) _ENTRY(ASMNAME(y)); _PROF_PROLOGUE
#define GLOBAL(y) _GLOBAL(CNAME(y))
#define ASMSTR .asciz
#define RCSID(x) .text; .asciz x
#undef __FBSDID
#if !defined(lint) && !defined(STRIP_FBSDID)
#define __FBSDID(s) .ident s
#else
#define __FBSDID(s) /* nothing */
#endif /* not lint and not STRIP_FBSDID */
#define WEAK_ALIAS(alias,sym) \
.weak alias; \
alias = sym
#ifdef __STDC__
#define WARN_REFERENCES(_sym,_msg) \
.section .gnu.warning. ## _sym ; .ascii _msg ; .text
#else
#define WARN_REFERENCES(_sym,_msg) \
.section .gnu.warning./**/_sym ; .ascii _msg ; .text
#endif /* __STDC__ */
#endif /* !_MACHINE_ASM_H_ */
Index: projects/altix/sys/powerpc/include/profile.h
===================================================================
--- projects/altix/sys/powerpc/include/profile.h (revision 218875)
+++ projects/altix/sys/powerpc/include/profile.h (revision 218876)
@@ -1,221 +1,220 @@
/*-
* Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
* All rights reserved.
*
* Author: Chris G. Demetriou
*
* Permission to use, copy, modify and distribute this software and
* its documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
* from: NetBSD: profile.h,v 1.9 1997/04/06 08:47:37 cgd Exp
* from: FreeBSD: src/sys/alpha/include/profile.h,v 1.4 1999/12/29
* $FreeBSD$
*/
#ifndef _MACHINE_PROFILE_H_
#define _MACHINE_PROFILE_H_
#define _MCOUNT_DECL void __mcount
#define FUNCTION_ALIGNMENT 4
typedef __ptrdiff_t fptrdiff_t;
/*
* The mcount trampoline macro, expanded in libc/gmon/mcount.c
*
* For PowerPC SVR4 ABI profiling, the compiler will insert
* a data declaration and code sequence at the start of a routine of the form
*
* .function_mc: .data
* .align 2
* .long 0
* .text
*
* function: mflr %r0
* addis %r11,%r0, .function_mc@ha
* stw %r0,4(%r1)
* addi %r0,%r11, .function_mc@l
* bl _mcount
*
* The link register is saved in the LR save word in the caller's
* stack frame, r0 is set up to point to the allocated longword,
* and control is transferred to _mcount.
*
* On return from _mcount, the routine should function as it would
* with no profiling so _mcount must restore register state to that upon
* entry. Any routine called by the _mcount trampoline will save
* callee-save registers, so _mcount must make sure it saves volatile
* registers that may have state after it returns i.e. parameter registers.
*
* The FreeBSD libc mcount routine ignores the r0 longword pointer, but
* instead requires as parameters the current PC and called PC. The current
* PC is obtained from the link register, as a result of "bl _mcount" in
* the stub, while the caller's PC is obtained from the LR save word.
*
* On return from libc mcount, the return is done indirectly with the
* ctr register rather than the link register, to allow the link register
* to be restored to what it was on entry to the profiled routine.
*/
#ifdef __powerpc64__
#define MCOUNT \
__asm( " .text \n" \
" .align 2 \n" \
" .globl _mcount \n" \
" .section \".opd\",\"aw\" \n" \
" .align 3 \n" \
"_mcount: \n" \
- " .quad ._mcount,.TOC.@tocbase,0 \n" \
+ " .quad .L._mcount,.TOC.@tocbase,0\n" \
" .previous \n" \
+ " .type _mcount,@function \n" \
" .align 4 \n" \
- " .globl ._mcount \n" \
- " .type ._mcount,@function \n" \
- "._mcount: \n" \
- " stdu %r1,-(288+120)(%r1) \n" \
+ ".L._mcount: \n" \
+ " stdu %r1,-(288+128)(%r1) \n" \
" std %r3,48(%r1) \n" \
" std %r4,56(%r1) \n" \
" std %r5,64(%r1) \n" \
" std %r6,72(%r1) \n" \
" std %r7,80(%r1) \n" \
" std %r8,88(%r1) \n" \
" std %r9,96(%r1) \n" \
" std %r10,104(%r1) \n" \
" mflr %r4 \n" \
" std %r4,112(%r1) \n" \
" ld %r3,0(%r1) \n" \
" ld %r3,0(%r3) \n" \
" ld %r3,16(%r3) \n" \
- " bl .__mcount \n" \
+ " bl __mcount \n" \
" nop \n" \
" ld %r4,112(%r1) \n" \
" mtlr %r4 \n" \
" ld %r3,48(%r1) \n" \
" ld %r4,56(%r1) \n" \
" ld %r5,64(%r1) \n" \
" ld %r6,72(%r1) \n" \
" ld %r7,80(%r1) \n" \
" ld %r8,88(%r1) \n" \
" ld %r9,96(%r1) \n" \
" ld %r10,104(%r1) \n" \
- " addi %r1,%r1,(288+120) \n" \
+ " addi %r1,%r1,(288+128) \n" \
" blr \n");
#else
#ifdef PIC
#define _PLT "@plt"
#else
#define _PLT
#endif
#define MCOUNT \
__asm( " .globl _mcount \n" \
" .type _mcount,@function \n" \
" .align 4 \n" \
"_mcount: \n" \
" stwu %r1,-64(%r1) \n" \
" stw %r3,16(%r1) \n" \
" stw %r4,20(%r1) \n" \
" stw %r5,24(%r1) \n" \
" stw %r6,28(%r1) \n" \
" stw %r7,32(%r1) \n" \
" stw %r8,36(%r1) \n" \
" stw %r9,40(%r1) \n" \
" stw %r10,44(%r1) \n" \
" mflr %r4 \n" \
" stw %r4,48(%r1) \n" \
" lwz %r3,68(%r1) \n" \
" bl __mcount" _PLT " \n" \
" lwz %r3,68(%r1) \n" \
" mtlr %r3 \n" \
" lwz %r4,48(%r1) \n" \
" mtctr %r4 \n" \
" lwz %r3,16(%r1) \n" \
" lwz %r4,20(%r1) \n" \
" lwz %r5,24(%r1) \n" \
" lwz %r6,28(%r1) \n" \
" lwz %r7,32(%r1) \n" \
" lwz %r8,36(%r1) \n" \
" lwz %r9,40(%r1) \n" \
" lwz %r10,44(%r1) \n" \
" addi %r1,%r1,64 \n" \
" bctr \n" \
"_mcount_end: \n" \
" .size _mcount,_mcount_end-_mcount");
#endif
#ifdef _KERNEL
#define MCOUNT_ENTER(s) s = intr_disable()
#define MCOUNT_EXIT(s) intr_restore(s)
#define MCOUNT_DECL(s) register_t s;
#ifndef COMPILING_LINT
#ifdef AIM
#include <machine/trap.h>
#define __PROFILE_VECTOR_BASE EXC_RST
#define __PROFILE_VECTOR_TOP (EXC_LAST + 0x100)
#endif /* AIM */
#ifdef E500
extern char interrupt_vector_base[];
extern char interrupt_vector_top[];
#define __PROFILE_VECTOR_BASE (uintfptr_t)interrupt_vector_base
#define __PROFILE_VECTOR_TOP (uintfptr_t)interrupt_vector_top
#endif /* E500 */
#endif /* !COMPILING_LINT */
#ifndef __PROFILE_VECTOR_BASE
#define __PROFILE_VECTOR_BASE 0
#endif
#ifndef __PROFILE_VECTOR_TOP
#define __PROFILE_VECTOR_TOP 1
#endif
static __inline void
powerpc_profile_interrupt(void)
{
}
static __inline void
powerpc_profile_userspace(void)
{
}
#define MCOUNT_FROMPC_USER(pc) \
((pc < (uintfptr_t)VM_MAXUSER_ADDRESS) ? \
(uintfptr_t)powerpc_profile_userspace : pc)
#define MCOUNT_FROMPC_INTR(pc) \
((pc >= __PROFILE_VECTOR_BASE && \
pc < __PROFILE_VECTOR_TOP) ? \
(uintfptr_t)powerpc_profile_interrupt : ~0U)
void __mcount(uintfptr_t frompc, uintfptr_t selfpc);
#else /* !_KERNEL */
#ifdef __powerpc64__
typedef u_long uintfptr_t;
#else
typedef u_int uintfptr_t;
#endif
#endif /* _KERNEL */
#endif /* !_MACHINE_PROFILE_H_ */
Index: projects/altix/sys/sys/cdefs.h
===================================================================
--- projects/altix/sys/sys/cdefs.h (revision 218875)
+++ projects/altix/sys/sys/cdefs.h (revision 218876)
@@ -1,588 +1,577 @@
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Berkeley Software Design, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)cdefs.h 8.8 (Berkeley) 1/9/95
* $FreeBSD$
*/
#ifndef _SYS_CDEFS_H_
#define _SYS_CDEFS_H_
#if defined(__cplusplus)
#define __BEGIN_DECLS extern "C" {
#define __END_DECLS }
#else
#define __BEGIN_DECLS
#define __END_DECLS
#endif
/*
* This code has been put in place to help reduce the addition of
* compiler specific defines in FreeBSD code. It helps to aid in
* having a compiler-agnostic source tree.
*/
#if defined(__GNUC__) || defined(__INTEL_COMPILER)
#if __GNUC__ >= 3 || defined(__INTEL_COMPILER)
#define __GNUCLIKE_ASM 3
#define __GNUCLIKE_MATH_BUILTIN_CONSTANTS
#else
#define __GNUCLIKE_ASM 2
#endif
#define __GNUCLIKE___TYPEOF 1
#define __GNUCLIKE___OFFSETOF 1
#define __GNUCLIKE___SECTION 1
#ifndef __INTEL_COMPILER
# define __GNUCLIKE_CTOR_SECTION_HANDLING 1
#endif
#define __GNUCLIKE_BUILTIN_CONSTANT_P 1
# if defined(__INTEL_COMPILER) && defined(__cplusplus) \
&& __INTEL_COMPILER < 800
# undef __GNUCLIKE_BUILTIN_CONSTANT_P
# endif
#if (__GNUC_MINOR__ > 95 || __GNUC__ >= 3) && !defined(__INTEL_COMPILER)
# define __GNUCLIKE_BUILTIN_VARARGS 1
# define __GNUCLIKE_BUILTIN_STDARG 1
# define __GNUCLIKE_BUILTIN_VAALIST 1
#endif
#if defined(__GNUC__)
# define __GNUC_VA_LIST_COMPATIBILITY 1
#endif
#ifndef __INTEL_COMPILER
# define __GNUCLIKE_BUILTIN_NEXT_ARG 1
# define __GNUCLIKE_MATH_BUILTIN_RELOPS
#endif
#define __GNUCLIKE_BUILTIN_MEMCPY 1
/* XXX: if __GNUC__ >= 2: not tested everywhere originally, where replaced */
#define __CC_SUPPORTS_INLINE 1
#define __CC_SUPPORTS___INLINE 1
#define __CC_SUPPORTS___INLINE__ 1
#define __CC_SUPPORTS___FUNC__ 1
#define __CC_SUPPORTS_WARNING 1
#define __CC_SUPPORTS_VARADIC_XXX 1 /* see varargs.h */
#define __CC_SUPPORTS_DYNAMIC_ARRAY_INIT 1
#endif /* __GNUC__ || __INTEL_COMPILER */
/*
* Macro to test if we're using a specific version of gcc or later.
*/
#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
#define __GNUC_PREREQ__(ma, mi) \
(__GNUC__ > (ma) || __GNUC__ == (ma) && __GNUC_MINOR__ >= (mi))
#else
#define __GNUC_PREREQ__(ma, mi) 0
#endif
/*
* The __CONCAT macro is used to concatenate parts of symbol names, e.g.
* with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
* The __CONCAT macro is a bit tricky to use if it must work in non-ANSI
* mode -- there must be no spaces between its arguments, and for nested
* __CONCAT's, all the __CONCAT's must be at the left. __CONCAT can also
* concatenate double-quoted strings produced by the __STRING macro, but
* this only works with ANSI C.
*
* __XSTRING is like __STRING, but it expands any macros in its argument
* first. It is only available with ANSI C.
*/
#if defined(__STDC__) || defined(__cplusplus)
#define __P(protos) protos /* full-blown ANSI C */
#define __CONCAT1(x,y) x ## y
#define __CONCAT(x,y) __CONCAT1(x,y)
#define __STRING(x) #x /* stringify without expanding x */
#define __XSTRING(x) __STRING(x) /* expand x, then stringify */
#define __const const /* define reserved names to standard */
#define __signed signed
#define __volatile volatile
#if defined(__cplusplus)
#define __inline inline /* convert to C++ keyword */
#else
#if !(defined(__CC_SUPPORTS___INLINE))
#define __inline /* delete GCC keyword */
#endif /* ! __CC_SUPPORTS___INLINE */
#endif /* !__cplusplus */
#else /* !(__STDC__ || __cplusplus) */
#define __P(protos) () /* traditional C preprocessor */
#define __CONCAT(x,y) x/**/y
#define __STRING(x) "x"
#if !defined(__CC_SUPPORTS___INLINE)
#define __const /* delete pseudo-ANSI C keywords */
#define __inline
#define __signed
#define __volatile
/*
* In non-ANSI C environments, new programs will want ANSI-only C keywords
* deleted from the program and old programs will want them left alone.
* When using a compiler other than gcc, programs using the ANSI C keywords
* const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS.
* When using "gcc -traditional", we assume that this is the intent; if
* __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone.
*/
#ifndef NO_ANSI_KEYWORDS
#define const /* delete ANSI C keywords */
#define inline
#define signed
#define volatile
#endif /* !NO_ANSI_KEYWORDS */
#endif /* !__CC_SUPPORTS___INLINE */
#endif /* !(__STDC__ || __cplusplus) */
/*
* Compiler-dependent macros to help declare dead (non-returning) and
* pure (no side effects) functions, and unused variables. They are
* null except for versions of gcc that are known to support the features
* properly (old versions of gcc-2 supported the dead and pure features
* in a different (wrong) way). If we do not provide an implementation
* for a given compiler, let the compile fail if it is told to use
* a feature that we cannot live without.
*/
#ifdef lint
#define __dead2
#define __pure2
#define __unused
#define __packed
#define __aligned(x)
#define __section(x)
#else
#if !__GNUC_PREREQ__(2, 5) && !defined(__INTEL_COMPILER)
#define __dead2
#define __pure2
#define __unused
#endif
#if __GNUC__ == 2 && __GNUC_MINOR__ >= 5 && __GNUC_MINOR__ < 7 && !defined(__INTEL_COMPILER)
#define __dead2 __attribute__((__noreturn__))
#define __pure2 __attribute__((__const__))
#define __unused
/* XXX Find out what to do for __packed, __aligned and __section */
#endif
#if __GNUC_PREREQ__(2, 7)
#define __dead2 __attribute__((__noreturn__))
#define __pure2 __attribute__((__const__))
#define __unused __attribute__((__unused__))
#define __used __attribute__((__used__))
#define __packed __attribute__((__packed__))
#define __aligned(x) __attribute__((__aligned__(x)))
#define __section(x) __attribute__((__section__(x)))
#endif
#if defined(__INTEL_COMPILER)
#define __dead2 __attribute__((__noreturn__))
#define __pure2 __attribute__((__const__))
#define __unused __attribute__((__unused__))
#define __used __attribute__((__used__))
#define __packed __attribute__((__packed__))
#define __aligned(x) __attribute__((__aligned__(x)))
#define __section(x) __attribute__((__section__(x)))
#endif
#endif
#if __GNUC_PREREQ__(2, 96)
#define __malloc_like __attribute__((__malloc__))
#define __pure __attribute__((__pure__))
#else
#define __malloc_like
#define __pure
#endif
#if __GNUC_PREREQ__(3, 1) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 800)
#define __always_inline __attribute__((__always_inline__))
#else
#define __always_inline
#endif
#if __GNUC_PREREQ__(3, 1)
#define __noinline __attribute__ ((__noinline__))
#else
#define __noinline
#endif
#if __GNUC_PREREQ__(3, 3)
#define __nonnull(x) __attribute__((__nonnull__(x)))
#else
#define __nonnull(x)
#endif
/* XXX: should use `#if __STDC_VERSION__ < 199901'. */
#if !__GNUC_PREREQ__(2, 7) && !defined(__INTEL_COMPILER)
#define __func__ NULL
#endif
#if (defined(__INTEL_COMPILER) || (defined(__GNUC__) && __GNUC__ >= 2)) && !defined(__STRICT_ANSI__) || __STDC_VERSION__ >= 199901
#define __LONG_LONG_SUPPORTED
#endif
/*
* GCC 2.95 provides `__restrict' as an extension to C90 to support the
* C99-specific `restrict' type qualifier. We happen to use `__restrict' as
* a way to define the `restrict' type qualifier without disturbing older
* software that is unaware of C99 keywords.
*/
#if !(__GNUC__ == 2 && __GNUC_MINOR__ == 95)
#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901 || defined(lint)
#define __restrict
#else
#define __restrict restrict
#endif
#endif
/*
* GNU C version 2.96 adds explicit branch prediction so that
* the CPU back-end can hint the processor and also so that
* code blocks can be reordered such that the predicted path
* sees a more linear flow, thus improving cache behavior, etc.
*
* The following two macros provide us with a way to utilize this
* compiler feature. Use __predict_true() if you expect the expression
* to evaluate to true, and __predict_false() if you expect the
* expression to evaluate to false.
*
* A few notes about usage:
*
* * Generally, __predict_false() error condition checks (unless
* you have some _strong_ reason to do otherwise, in which case
* document it), and/or __predict_true() `no-error' condition
* checks, assuming you want to optimize for the no-error case.
*
* * Other than that, if you don't know the likelihood of a test
* succeeding from empirical or other `hard' evidence, don't
* make predictions.
*
* * These are meant to be used in places that are run `a lot'.
* It is wasteful to make predictions in code that is run
* seldomly (e.g. at subsystem initialization time) as the
* basic block reordering that this affects can often generate
* larger code.
*/
#if __GNUC_PREREQ__(2, 96)
#define __predict_true(exp) __builtin_expect((exp), 1)
#define __predict_false(exp) __builtin_expect((exp), 0)
#else
#define __predict_true(exp) (exp)
#define __predict_false(exp) (exp)
#endif
#if __GNUC_PREREQ__(4, 2)
#define __hidden __attribute__((__visibility__("hidden")))
#define __exported __attribute__((__visibility__("default")))
#else
#define __hidden
#define __exported
#endif
/*
* We define this here since <stddef.h>, <sys/queue.h>, and <sys/types.h>
* require it.
*/
#if __GNUC_PREREQ__(4, 1)
#define __offsetof(type, field) __builtin_offsetof(type, field)
#else
#ifndef __cplusplus
#define __offsetof(type, field) ((size_t)(&((type *)0)->field))
#else
#define __offsetof(type, field) \
(__offsetof__ (reinterpret_cast <size_t> \
(&reinterpret_cast <const volatile char &> \
(static_cast<type *> (0)->field))))
#endif
#endif
#define __rangeof(type, start, end) \
(__offsetof(type, end) - __offsetof(type, start))
/*
* Compiler-dependent macros to declare that functions take printf-like
* or scanf-like arguments. They are null except for versions of gcc
* that are known to support the features properly (old versions of gcc-2
* didn't permit keeping the keywords out of the application namespace).
*/
#if !__GNUC_PREREQ__(2, 7) && !defined(__INTEL_COMPILER)
#define __printflike(fmtarg, firstvararg)
#define __scanflike(fmtarg, firstvararg)
#define __format_arg(fmtarg)
#else
#define __printflike(fmtarg, firstvararg) \
__attribute__((__format__ (__printf__, fmtarg, firstvararg)))
#define __scanflike(fmtarg, firstvararg) \
__attribute__((__format__ (__scanf__, fmtarg, firstvararg)))
#define __format_arg(fmtarg) __attribute__((__format_arg__ (fmtarg)))
#endif
/* Compiler-dependent macros that rely on FreeBSD-specific extensions. */
#if __FreeBSD_cc_version >= 300001 && defined(__GNUC__) && !defined(__INTEL_COMPILER)
#define __printf0like(fmtarg, firstvararg) \
__attribute__((__format__ (__printf0__, fmtarg, firstvararg)))
#else
#define __printf0like(fmtarg, firstvararg)
#endif
#if defined(__GNUC__) || defined(__INTEL_COMPILER)
#ifndef __INTEL_COMPILER
#define __strong_reference(sym,aliassym) \
extern __typeof (sym) aliassym __attribute__ ((__alias__ (#sym)))
#endif
#ifdef __STDC__
-#ifdef __powerpc64__
#define __weak_reference(sym,alias) \
- __asm__(".weak " #alias); \
- __asm__(".equ " #alias ", " #sym); \
- __asm__(".weak ." #alias); \
- __asm__(".equ ." #alias ", ." #sym)
-#else
-#define __weak_reference(sym,alias) \
- __asm__(".weak " #alias); \
- __asm__(".equ " #alias ", " #sym)
-#endif
-#define __weak_reference_data(sym,alias)\
__asm__(".weak " #alias); \
__asm__(".equ " #alias ", " #sym)
#define __warn_references(sym,msg) \
__asm__(".section .gnu.warning." #sym); \
__asm__(".asciz \"" msg "\""); \
__asm__(".previous")
#define __sym_compat(sym,impl,verid) \
__asm__(".symver " #impl ", " #sym "@" #verid)
#define __sym_default(sym,impl,verid) \
__asm__(".symver " #impl ", " #sym "@@" #verid)
#else
#define __weak_reference(sym,alias) \
__asm__(".weak alias"); \
__asm__(".equ alias, sym")
#define __warn_references(sym,msg) \
__asm__(".section .gnu.warning.sym"); \
__asm__(".asciz \"msg\""); \
__asm__(".previous")
#define __sym_compat(sym,impl,verid) \
__asm__(".symver impl, sym@verid")
#define __sym_default(impl,sym,verid) \
__asm__(".symver impl, sym@@verid")
#endif /* __STDC__ */
#endif /* __GNUC__ || __INTEL_COMPILER */
#define __GLOBL1(sym) __asm__(".globl " #sym)
#define __GLOBL(sym) __GLOBL1(sym)
#if defined(__GNUC__) || defined(__INTEL_COMPILER)
#define __IDSTRING(name,string) __asm__(".ident\t\"" string "\"")
#else
/*
* The following definition might not work well if used in header files,
* but it should be better than nothing. If you want a "do nothing"
* version, then it should generate some harmless declaration, such as:
* #define __IDSTRING(name,string) struct __hack
*/
#define __IDSTRING(name,string) static const char name[] __unused = string
#endif
/*
* Embed the rcs id of a source file in the resulting library. Note that in
* more recent ELF binutils, we use .ident allowing the ID to be stripped.
* Usage:
* __FBSDID("$FreeBSD$");
*/
#ifndef __FBSDID
#if !defined(lint) && !defined(STRIP_FBSDID)
#define __FBSDID(s) __IDSTRING(__CONCAT(__rcsid_,__LINE__),s)
#else
#define __FBSDID(s) struct __hack
#endif
#endif
#ifndef __RCSID
#ifndef NO__RCSID
#define __RCSID(s) __IDSTRING(__CONCAT(__rcsid_,__LINE__),s)
#else
#define __RCSID(s) struct __hack
#endif
#endif
#ifndef __RCSID_SOURCE
#ifndef NO__RCSID_SOURCE
#define __RCSID_SOURCE(s) __IDSTRING(__CONCAT(__rcsid_source_,__LINE__),s)
#else
#define __RCSID_SOURCE(s) struct __hack
#endif
#endif
#ifndef __SCCSID
#ifndef NO__SCCSID
#define __SCCSID(s) __IDSTRING(__CONCAT(__sccsid_,__LINE__),s)
#else
#define __SCCSID(s) struct __hack
#endif
#endif
#ifndef __COPYRIGHT
#ifndef NO__COPYRIGHT
#define __COPYRIGHT(s) __IDSTRING(__CONCAT(__copyright_,__LINE__),s)
#else
#define __COPYRIGHT(s) struct __hack
#endif
#endif
#ifndef __DECONST
#define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
#endif
#ifndef __DEVOLATILE
#define __DEVOLATILE(type, var) ((type)(uintptr_t)(volatile void *)(var))
#endif
#ifndef __DEQUALIFY
#define __DEQUALIFY(type, var) ((type)(uintptr_t)(const volatile void *)(var))
#endif
/*-
* The following definitions are an extension of the behavior originally
* implemented in <sys/_posix.h>, but with a different level of granularity.
* POSIX.1 requires that the macros we test be defined before any standard
* header file is included.
*
* Here's a quick run-down of the versions:
* defined(_POSIX_SOURCE) 1003.1-1988
* _POSIX_C_SOURCE == 1 1003.1-1990
* _POSIX_C_SOURCE == 2 1003.2-1992 C Language Binding Option
* _POSIX_C_SOURCE == 199309 1003.1b-1993
* _POSIX_C_SOURCE == 199506 1003.1c-1995, 1003.1i-1995,
* and the omnibus ISO/IEC 9945-1: 1996
* _POSIX_C_SOURCE == 200112 1003.1-2001
* _POSIX_C_SOURCE == 200809 1003.1-2008
*
* In addition, the X/Open Portability Guide, which is now the Single UNIX
* Specification, defines a feature-test macro which indicates the version of
* that specification, and which subsumes _POSIX_C_SOURCE.
*
* Our macros begin with two underscores to avoid namespace screwage.
*/
/* Deal with IEEE Std. 1003.1-1990, in which _POSIX_C_SOURCE == 1. */
#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE == 1
#undef _POSIX_C_SOURCE /* Probably illegal, but beyond caring now. */
#define _POSIX_C_SOURCE 199009
#endif
/* Deal with IEEE Std. 1003.2-1992, in which _POSIX_C_SOURCE == 2. */
#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE == 2
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 199209
#endif
/* Deal with various X/Open Portability Guides and Single UNIX Spec. */
#ifdef _XOPEN_SOURCE
#if _XOPEN_SOURCE - 0 >= 700
#define __XSI_VISIBLE 700
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200809
#elif _XOPEN_SOURCE - 0 >= 600
#define __XSI_VISIBLE 600
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200112
#elif _XOPEN_SOURCE - 0 >= 500
#define __XSI_VISIBLE 500
#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 199506
#endif
#endif
/*
* Deal with all versions of POSIX. The ordering relative to the tests above is
* important.
*/
#if defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE)
#define _POSIX_C_SOURCE 198808
#endif
#ifdef _POSIX_C_SOURCE
#if _POSIX_C_SOURCE >= 200809
#define __POSIX_VISIBLE 200809
#define __ISO_C_VISIBLE 1999
#elif _POSIX_C_SOURCE >= 200112
#define __POSIX_VISIBLE 200112
#define __ISO_C_VISIBLE 1999
#elif _POSIX_C_SOURCE >= 199506
#define __POSIX_VISIBLE 199506
#define __ISO_C_VISIBLE 1990
#elif _POSIX_C_SOURCE >= 199309
#define __POSIX_VISIBLE 199309
#define __ISO_C_VISIBLE 1990
#elif _POSIX_C_SOURCE >= 199209
#define __POSIX_VISIBLE 199209
#define __ISO_C_VISIBLE 1990
#elif _POSIX_C_SOURCE >= 199009
#define __POSIX_VISIBLE 199009
#define __ISO_C_VISIBLE 1990
#else
#define __POSIX_VISIBLE 198808
#define __ISO_C_VISIBLE 0
#endif /* _POSIX_C_SOURCE */
#else
/*-
* Deal with _ANSI_SOURCE:
* If it is defined, and no other compilation environment is explicitly
* requested, then define our internal feature-test macros to zero. This
* makes no difference to the preprocessor (undefined symbols in preprocessing
* expressions are defined to have value zero), but makes it more convenient for
* a test program to print out the values.
*
* If a program mistakenly defines _ANSI_SOURCE and some other macro such as
* _POSIX_C_SOURCE, we will assume that it wants the broader compilation
* environment (and in fact we will never get here).
*/
#if defined(_ANSI_SOURCE) /* Hide almost everything. */
#define __POSIX_VISIBLE 0
#define __XSI_VISIBLE 0
#define __BSD_VISIBLE 0
#define __ISO_C_VISIBLE 1990
#elif defined(_C99_SOURCE) /* Localism to specify strict C99 env. */
#define __POSIX_VISIBLE 0
#define __XSI_VISIBLE 0
#define __BSD_VISIBLE 0
#define __ISO_C_VISIBLE 1999
#else /* Default environment: show everything. */
#define __POSIX_VISIBLE 200809
#define __XSI_VISIBLE 700
#define __BSD_VISIBLE 1
#define __ISO_C_VISIBLE 1999
#endif
#endif
#endif /* !_SYS_CDEFS_H_ */
Index: projects/altix/sys/sys/param.h
===================================================================
--- projects/altix/sys/sys/param.h (revision 218875)
+++ projects/altix/sys/sys/param.h (revision 218876)
@@ -1,322 +1,322 @@
/*-
* Copyright (c) 1982, 1986, 1989, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)param.h 8.3 (Berkeley) 4/4/95
* $FreeBSD$
*/
#ifndef _SYS_PARAM_H_
#define _SYS_PARAM_H_
#include <sys/_null.h>
#define BSD 199506 /* System version (year & month). */
#define BSD4_3 1
#define BSD4_4 1
/*
* __FreeBSD_version numbers are documented in the Porter's Handbook.
* If you bump the version for any reason, you should update the documentation
* there.
* Currently this lives here:
*
* doc/en_US.ISO8859-1/books/porters-handbook/book.sgml
*
* scheme is: <major><two digit minor>Rxx
* 'R' is in the range 0 to 4 if this is a release branch or
* x.0-CURRENT before RELENG_*_0 is created, otherwise 'R' is
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 900032 /* Master, propagated to newvers */
+#define __FreeBSD_version 900033 /* Master, propagated to newvers */
#ifdef _KERNEL
#define P_OSREL_SIGSEGV 700004
#define P_OSREL_MAP_ANON 800104
#endif
#ifndef LOCORE
#include <sys/types.h>
#endif
/*
* Machine-independent constants (some used in following include files).
* Redefined constants are from POSIX 1003.1 limits file.
*
* MAXCOMLEN should be >= sizeof(ac_comm) (see <acct.h>)
*/
#include <sys/syslimits.h>
#define MAXCOMLEN 19 /* max command name remembered */
#define MAXINTERP PATH_MAX /* max interpreter file name length */
#define MAXLOGNAME 17 /* max login name length (incl. NUL) */
#define MAXUPRC CHILD_MAX /* max simultaneous processes */
#define NCARGS ARG_MAX /* max bytes for an exec function */
#define NGROUPS (NGROUPS_MAX+1) /* max number groups */
#define NOFILE OPEN_MAX /* max open files per process */
#define NOGROUP 65535 /* marker for empty group set member */
#define MAXHOSTNAMELEN 256 /* max hostname size */
#define SPECNAMELEN 63 /* max length of devicename */
/* More types and definitions used throughout the kernel. */
#ifdef _KERNEL
#include <sys/cdefs.h>
#include <sys/errno.h>
#ifndef LOCORE
#include <sys/time.h>
#include <sys/priority.h>
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#endif
#ifndef _KERNEL
/* Signals. */
#include <sys/signal.h>
#endif
/* Machine type dependent parameters. */
#include <machine/param.h>
#ifndef _KERNEL
#include <sys/limits.h>
#endif
#ifndef DEV_BSHIFT
#define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */
#endif
#define DEV_BSIZE (1<<DEV_BSHIFT)
#ifndef BLKDEV_IOSIZE
#define BLKDEV_IOSIZE PAGE_SIZE /* default block device I/O size */
#endif
#ifndef DFLTPHYS
#define DFLTPHYS (64 * 1024) /* default max raw I/O transfer size */
#endif
#ifndef MAXPHYS
#define MAXPHYS (128 * 1024) /* max raw I/O transfer size */
#endif
#ifndef MAXDUMPPGS
#define MAXDUMPPGS (DFLTPHYS/PAGE_SIZE)
#endif
/*
* Constants related to network buffer management.
* MCLBYTES must be no larger than PAGE_SIZE.
*/
#ifndef MSIZE
#define MSIZE 256 /* size of an mbuf */
#endif /* MSIZE */
#ifndef MCLSHIFT
#define MCLSHIFT 11 /* convert bytes to mbuf clusters */
#endif /* MCLSHIFT */
#define MCLBYTES (1 << MCLSHIFT) /* size of an mbuf cluster */
#if PAGE_SIZE < 2048
#define MJUMPAGESIZE MCLBYTES
#elif PAGE_SIZE <= 8192
#define MJUMPAGESIZE PAGE_SIZE
#else
#define MJUMPAGESIZE (8 * 1024)
#endif
#define MJUM9BYTES (9 * 1024) /* jumbo cluster 9k */
#define MJUM16BYTES (16 * 1024) /* jumbo cluster 16k */
/*
* Some macros for units conversion
*/
/* clicks to bytes */
#ifndef ctob
#define ctob(x) ((x)<<PAGE_SHIFT)
#endif
/* bytes to clicks */
#ifndef btoc
#define btoc(x) (((vm_offset_t)(x)+PAGE_MASK)>>PAGE_SHIFT)
#endif
/*
* btodb() is messy and perhaps slow because `bytes' may be an off_t. We
* want to shift an unsigned type to avoid sign extension and we don't
* want to widen `bytes' unnecessarily. Assume that the result fits in
* a daddr_t.
*/
#ifndef btodb
#define btodb(bytes) /* calculates (bytes / DEV_BSIZE) */ \
(sizeof (bytes) > sizeof(long) \
? (daddr_t)((unsigned long long)(bytes) >> DEV_BSHIFT) \
: (daddr_t)((unsigned long)(bytes) >> DEV_BSHIFT))
#endif
#ifndef dbtob
#define dbtob(db) /* calculates (db * DEV_BSIZE) */ \
((off_t)(db) << DEV_BSHIFT)
#endif
#define PRIMASK 0x0ff
#define PCATCH 0x100 /* OR'd with pri for tsleep to check signals */
#define PDROP 0x200 /* OR'd with pri to stop re-entry of interlock mutex */
#define PBDRY 0x400 /* for PCATCH stop is done on the user boundary */
#define NZERO 0 /* default "nice" */
#define NBBY 8 /* number of bits in a byte */
#define NBPW sizeof(int) /* number of bytes per word (integer) */
#define CMASK 022 /* default file mask: S_IWGRP|S_IWOTH */
#define NODEV (dev_t)(-1) /* non-existent device */
/*
* File system parameters and macros.
*
* MAXBSIZE - Filesystems are made out of blocks of at most MAXBSIZE bytes
* per block. MAXBSIZE may be made larger without effecting
* any existing filesystems as long as it does not exceed MAXPHYS,
* and may be made smaller at the risk of not being able to use
* filesystems which require a block size exceeding MAXBSIZE.
*
* BKVASIZE - Nominal buffer space per buffer, in bytes. BKVASIZE is the
* minimum KVM memory reservation the kernel is willing to make.
* Filesystems can of course request smaller chunks. Actual
* backing memory uses a chunk size of a page (PAGE_SIZE).
*
* If you make BKVASIZE too small you risk seriously fragmenting
* the buffer KVM map which may slow things down a bit. If you
* make it too big the kernel will not be able to optimally use
* the KVM memory reserved for the buffer cache and will wind
* up with too-few buffers.
*
* The default is 16384, roughly 2x the block size used by a
* normal UFS filesystem.
*/
#define MAXBSIZE 65536 /* must be power of 2 */
#define BKVASIZE 16384 /* must be power of 2 */
#define BKVAMASK (BKVASIZE-1)
/*
* MAXPATHLEN defines the longest permissible path length after expanding
* symbolic links. It is used to allocate a temporary buffer from the buffer
* pool in which to do the name expansion, hence should be a power of two,
* and must be less than or equal to MAXBSIZE. MAXSYMLINKS defines the
* maximum number of symbolic links that may be expanded in a path name.
* It should be set high enough to allow all legitimate uses, but halt
* infinite loops reasonably quickly.
*/
#define MAXPATHLEN PATH_MAX
#define MAXSYMLINKS 32
/* Bit map related macros. */
#define setbit(a,i) (((unsigned char *)(a))[(i)/NBBY] |= 1<<((i)%NBBY))
#define clrbit(a,i) (((unsigned char *)(a))[(i)/NBBY] &= ~(1<<((i)%NBBY)))
#define isset(a,i) \
(((const unsigned char *)(a))[(i)/NBBY] & (1<<((i)%NBBY)))
#define isclr(a,i) \
((((const unsigned char *)(a))[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
/* Macros for counting and rounding. */
#ifndef howmany
#define howmany(x, y) (((x)+((y)-1))/(y))
#endif
#define rounddown(x, y) (((x)/(y))*(y))
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */
#define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
#define powerof2(x) ((((x)-1)&(x))==0)
/* Macros for min/max. */
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#ifdef _KERNEL
/*
* Basic byte order function prototypes for non-inline functions.
*/
#ifndef LOCORE
#ifndef _BYTEORDER_PROTOTYPED
#define _BYTEORDER_PROTOTYPED
__BEGIN_DECLS
__uint32_t htonl(__uint32_t);
__uint16_t htons(__uint16_t);
__uint32_t ntohl(__uint32_t);
__uint16_t ntohs(__uint16_t);
__END_DECLS
#endif
#endif
#ifndef lint
#ifndef _BYTEORDER_FUNC_DEFINED
#define _BYTEORDER_FUNC_DEFINED
#define htonl(x) __htonl(x)
#define htons(x) __htons(x)
#define ntohl(x) __ntohl(x)
#define ntohs(x) __ntohs(x)
#endif /* !_BYTEORDER_FUNC_DEFINED */
#endif /* lint */
#endif /* _KERNEL */
/*
* Scale factor for scaled integers used to count %cpu time and load avgs.
*
* The number of CPU `tick's that map to a unique `%age' can be expressed
* by the formula (1 / (2 ^ (FSHIFT - 11))). The maximum load average that
* can be calculated (assuming 32 bits) can be closely approximated using
* the formula (2 ^ (2 * (16 - FSHIFT))) for (FSHIFT < 15).
*
* For the scheduler to maintain a 1:1 mapping of CPU `tick' to `%age',
* FSHIFT must be at least 11; this gives us a maximum load avg of ~1024.
*/
#define FSHIFT 11 /* bits to right of fixed binary point */
#define FSCALE (1<<FSHIFT)
#define dbtoc(db) /* calculates devblks to pages */ \
((db + (ctodb(1) - 1)) >> (PAGE_SHIFT - DEV_BSHIFT))
#define ctodb(db) /* calculates pages to devblks */ \
((db) << (PAGE_SHIFT - DEV_BSHIFT))
/*
* Given the pointer x to the member m of the struct s, return
* a pointer to the containing structure.
*/
#define member2struct(s, m, x) \
((struct s *)(void *)((char *)(x) - offsetof(struct s, m)))
#endif /* _SYS_PARAM_H_ */
Index: projects/altix/sys/ufs/ufs/ufs_vnops.c
===================================================================
--- projects/altix/sys/ufs/ufs/ufs_vnops.c (revision 218875)
+++ projects/altix/sys/ufs/ufs/ufs_vnops.c (revision 218876)
@@ -1,2772 +1,2774 @@
/*-
* Copyright (c) 1982, 1986, 1989, 1993, 1995
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_quota.h"
#include "opt_suiddir.h"
#include "opt_ufs.h"
#include "opt_ffs.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/namei.h>
#include <sys/kernel.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/mount.h>
#include <sys/priv.h>
#include <sys/refcount.h>
#include <sys/unistd.h>
#include <sys/vnode.h>
#include <sys/dirent.h>
#include <sys/lockf.h>
#include <sys/conf.h>
#include <sys/acl.h>
#include <security/mac/mac_framework.h>
#include <sys/file.h> /* XXX */
#include <vm/vm.h>
#include <vm/vm_extern.h>
#include <fs/fifofs/fifo.h>
#include <ufs/ufs/acl.h>
#include <ufs/ufs/extattr.h>
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
#include <ufs/ufs/dir.h>
#include <ufs/ufs/ufsmount.h>
#include <ufs/ufs/ufs_extern.h>
#ifdef UFS_DIRHASH
#include <ufs/ufs/dirhash.h>
#endif
#ifdef UFS_GJOURNAL
#include <ufs/ufs/gjournal.h>
FEATURE(ufs_gjournal, "Journaling support through GEOM for UFS");
#endif
#ifdef QUOTA
FEATURE(ufs_quota, "UFS disk quotas support");
FEATURE(ufs_quota64, "64bit UFS disk quotas support");
#endif
#ifdef SUIDDIR
FEATURE(suiddir,
"Give all new files in directory the same ownership as the directory");
#endif
#include <ufs/ffs/ffs_extern.h>
static vop_accessx_t ufs_accessx;
static int ufs_chmod(struct vnode *, int, struct ucred *, struct thread *);
static int ufs_chown(struct vnode *, uid_t, gid_t, struct ucred *, struct thread *);
static vop_close_t ufs_close;
static vop_create_t ufs_create;
static vop_getattr_t ufs_getattr;
static vop_link_t ufs_link;
static int ufs_makeinode(int mode, struct vnode *, struct vnode **, struct componentname *);
static vop_markatime_t ufs_markatime;
static vop_mkdir_t ufs_mkdir;
static vop_mknod_t ufs_mknod;
static vop_open_t ufs_open;
static vop_pathconf_t ufs_pathconf;
static vop_print_t ufs_print;
static vop_readlink_t ufs_readlink;
static vop_remove_t ufs_remove;
static vop_rename_t ufs_rename;
static vop_rmdir_t ufs_rmdir;
static vop_setattr_t ufs_setattr;
static vop_strategy_t ufs_strategy;
static vop_symlink_t ufs_symlink;
static vop_whiteout_t ufs_whiteout;
static vop_close_t ufsfifo_close;
static vop_kqfilter_t ufsfifo_kqfilter;
static vop_pathconf_t ufsfifo_pathconf;
SYSCTL_NODE(_vfs, OID_AUTO, ufs, CTLFLAG_RD, 0, "UFS filesystem");
/*
* A virgin directory (no blushing please).
*/
static struct dirtemplate mastertemplate = {
0, 12, DT_DIR, 1, ".",
0, DIRBLKSIZ - 12, DT_DIR, 2, ".."
};
static struct odirtemplate omastertemplate = {
0, 12, 1, ".",
0, DIRBLKSIZ - 12, 2, ".."
};
static void
ufs_itimes_locked(struct vnode *vp)
{
struct inode *ip;
struct timespec ts;
ASSERT_VI_LOCKED(vp, __func__);
ip = VTOI(vp);
if (UFS_RDONLY(ip))
goto out;
if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0)
return;
if ((vp->v_type == VBLK || vp->v_type == VCHR) && !DOINGSOFTDEP(vp))
ip->i_flag |= IN_LAZYMOD;
else if (((vp->v_mount->mnt_kern_flag &
(MNTK_SUSPENDED | MNTK_SUSPEND)) == 0) ||
(ip->i_flag & (IN_CHANGE | IN_UPDATE)))
ip->i_flag |= IN_MODIFIED;
else if (ip->i_flag & IN_ACCESS)
ip->i_flag |= IN_LAZYACCESS;
vfs_timestamp(&ts);
if (ip->i_flag & IN_ACCESS) {
DIP_SET(ip, i_atime, ts.tv_sec);
DIP_SET(ip, i_atimensec, ts.tv_nsec);
}
if (ip->i_flag & IN_UPDATE) {
DIP_SET(ip, i_mtime, ts.tv_sec);
DIP_SET(ip, i_mtimensec, ts.tv_nsec);
}
if (ip->i_flag & IN_CHANGE) {
DIP_SET(ip, i_ctime, ts.tv_sec);
DIP_SET(ip, i_ctimensec, ts.tv_nsec);
DIP_SET(ip, i_modrev, DIP(ip, i_modrev) + 1);
}
out:
ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE);
}
void
ufs_itimes(struct vnode *vp)
{
VI_LOCK(vp);
ufs_itimes_locked(vp);
VI_UNLOCK(vp);
}
/*
* Create a regular file
*/
static int
ufs_create(ap)
struct vop_create_args /* {
struct vnode *a_dvp;
struct vnode **a_vpp;
struct componentname *a_cnp;
struct vattr *a_vap;
} */ *ap;
{
int error;
error =
ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
ap->a_dvp, ap->a_vpp, ap->a_cnp);
if (error)
return (error);
return (0);
}
/*
* Mknod vnode call
*/
/* ARGSUSED */
static int
ufs_mknod(ap)
struct vop_mknod_args /* {
struct vnode *a_dvp;
struct vnode **a_vpp;
struct componentname *a_cnp;
struct vattr *a_vap;
} */ *ap;
{
struct vattr *vap = ap->a_vap;
struct vnode **vpp = ap->a_vpp;
struct inode *ip;
ino_t ino;
int error;
error = ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode),
ap->a_dvp, vpp, ap->a_cnp);
if (error)
return (error);
ip = VTOI(*vpp);
ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
if (vap->va_rdev != VNOVAL) {
/*
* Want to be able to use this to make badblock
* inodes, so don't truncate the dev number.
*/
DIP_SET(ip, i_rdev, vap->va_rdev);
}
/*
* Remove inode, then reload it through VFS_VGET so it is
* checked to see if it is an alias of an existing entry in
* the inode cache. XXX I don't believe this is necessary now.
*/
(*vpp)->v_type = VNON;
ino = ip->i_number; /* Save this before vgone() invalidates ip. */
vgone(*vpp);
vput(*vpp);
error = VFS_VGET(ap->a_dvp->v_mount, ino, LK_EXCLUSIVE, vpp);
if (error) {
*vpp = NULL;
return (error);
}
return (0);
}
/*
* Open called.
*/
/* ARGSUSED */
static int
ufs_open(struct vop_open_args *ap)
{
struct vnode *vp = ap->a_vp;
struct inode *ip;
if (vp->v_type == VCHR || vp->v_type == VBLK)
return (EOPNOTSUPP);
ip = VTOI(vp);
/*
* Files marked append-only must be opened for appending.
*/
if ((ip->i_flags & APPEND) &&
(ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
return (EPERM);
vnode_create_vobject(vp, DIP(ip, i_size), ap->a_td);
return (0);
}
/*
* Close called.
*
* Update the times on the inode.
*/
/* ARGSUSED */
static int
ufs_close(ap)
struct vop_close_args /* {
struct vnode *a_vp;
int a_fflag;
struct ucred *a_cred;
struct thread *a_td;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
int usecount;
VI_LOCK(vp);
usecount = vp->v_usecount;
if (usecount > 1)
ufs_itimes_locked(vp);
VI_UNLOCK(vp);
return (0);
}
static int
ufs_accessx(ap)
struct vop_accessx_args /* {
struct vnode *a_vp;
accmode_t a_accmode;
struct ucred *a_cred;
struct thread *a_td;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
struct inode *ip = VTOI(vp);
accmode_t accmode = ap->a_accmode;
int error;
#ifdef QUOTA
int relocked;
#endif
#ifdef UFS_ACL
struct acl *acl;
acl_type_t type;
#endif
/*
* Disallow write attempts on read-only filesystems;
* unless the file is a socket, fifo, or a block or
* character device resident on the filesystem.
*/
if (accmode & VMODIFY_PERMS) {
switch (vp->v_type) {
case VDIR:
case VLNK:
case VREG:
if (vp->v_mount->mnt_flag & MNT_RDONLY)
return (EROFS);
#ifdef QUOTA
/*
* Inode is accounted in the quotas only if struct
* dquot is attached to it. VOP_ACCESS() is called
* from vn_open_cred() and provides a convenient
* point to call getinoquota().
*/
if (VOP_ISLOCKED(vp) != LK_EXCLUSIVE) {
/*
* Upgrade vnode lock, since getinoquota()
* requires exclusive lock to modify inode.
*/
relocked = 1;
vhold(vp);
vn_lock(vp, LK_UPGRADE | LK_RETRY);
VI_LOCK(vp);
if (vp->v_iflag & VI_DOOMED) {
vdropl(vp);
error = ENOENT;
goto relock;
}
vdropl(vp);
} else
relocked = 0;
error = getinoquota(ip);
relock:
if (relocked)
vn_lock(vp, LK_DOWNGRADE | LK_RETRY);
if (error != 0)
return (error);
#endif
break;
default:
break;
}
}
/*
* If immutable bit set, nobody gets to write it. "& ~VADMIN_PERMS"
* is here, because without it, * it would be impossible for the owner
* to remove the IMMUTABLE flag.
*/
if ((accmode & (VMODIFY_PERMS & ~VADMIN_PERMS)) &&
(ip->i_flags & (IMMUTABLE | SF_SNAPSHOT)))
return (EPERM);
#ifdef UFS_ACL
if ((vp->v_mount->mnt_flag & (MNT_ACLS | MNT_NFS4ACLS)) != 0) {
if (vp->v_mount->mnt_flag & MNT_NFS4ACLS)
type = ACL_TYPE_NFS4;
else
type = ACL_TYPE_ACCESS;
acl = acl_alloc(M_WAITOK);
if (type == ACL_TYPE_NFS4)
error = ufs_getacl_nfs4_internal(vp, acl, ap->a_td);
else
error = VOP_GETACL(vp, type, acl, ap->a_cred, ap->a_td);
switch (error) {
case 0:
if (type == ACL_TYPE_NFS4) {
error = vaccess_acl_nfs4(vp->v_type, ip->i_uid,
ip->i_gid, acl, accmode, ap->a_cred, NULL);
} else {
error = vfs_unixify_accmode(&accmode);
if (error == 0)
error = vaccess_acl_posix1e(vp->v_type, ip->i_uid,
ip->i_gid, acl, accmode, ap->a_cred, NULL);
}
break;
default:
if (error != EOPNOTSUPP)
printf(
"ufs_accessx(): Error retrieving ACL on object (%d).\n",
error);
/*
* XXX: Fall back until debugged. Should
* eventually possibly log an error, and return
* EPERM for safety.
*/
error = vfs_unixify_accmode(&accmode);
if (error == 0)
error = vaccess(vp->v_type, ip->i_mode, ip->i_uid,
ip->i_gid, accmode, ap->a_cred, NULL);
}
acl_free(acl);
return (error);
}
#endif /* !UFS_ACL */
error = vfs_unixify_accmode(&accmode);
if (error == 0)
error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid,
accmode, ap->a_cred, NULL);
return (error);
}
/* ARGSUSED */
static int
ufs_getattr(ap)
struct vop_getattr_args /* {
struct vnode *a_vp;
struct vattr *a_vap;
struct ucred *a_cred;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
struct inode *ip = VTOI(vp);
struct vattr *vap = ap->a_vap;
VI_LOCK(vp);
ufs_itimes_locked(vp);
if (ip->i_ump->um_fstype == UFS1) {
vap->va_atime.tv_sec = ip->i_din1->di_atime;
vap->va_atime.tv_nsec = ip->i_din1->di_atimensec;
} else {
vap->va_atime.tv_sec = ip->i_din2->di_atime;
vap->va_atime.tv_nsec = ip->i_din2->di_atimensec;
}
VI_UNLOCK(vp);
/*
* Copy from inode table
*/
vap->va_fsid = dev2udev(ip->i_dev);
vap->va_fileid = ip->i_number;
vap->va_mode = ip->i_mode & ~IFMT;
vap->va_nlink = ip->i_effnlink;
vap->va_uid = ip->i_uid;
vap->va_gid = ip->i_gid;
if (ip->i_ump->um_fstype == UFS1) {
vap->va_rdev = ip->i_din1->di_rdev;
vap->va_size = ip->i_din1->di_size;
vap->va_mtime.tv_sec = ip->i_din1->di_mtime;
vap->va_mtime.tv_nsec = ip->i_din1->di_mtimensec;
vap->va_ctime.tv_sec = ip->i_din1->di_ctime;
vap->va_ctime.tv_nsec = ip->i_din1->di_ctimensec;
vap->va_bytes = dbtob((u_quad_t)ip->i_din1->di_blocks);
vap->va_filerev = ip->i_din1->di_modrev;
} else {
vap->va_rdev = ip->i_din2->di_rdev;
vap->va_size = ip->i_din2->di_size;
vap->va_mtime.tv_sec = ip->i_din2->di_mtime;
vap->va_mtime.tv_nsec = ip->i_din2->di_mtimensec;
vap->va_ctime.tv_sec = ip->i_din2->di_ctime;
vap->va_ctime.tv_nsec = ip->i_din2->di_ctimensec;
vap->va_birthtime.tv_sec = ip->i_din2->di_birthtime;
vap->va_birthtime.tv_nsec = ip->i_din2->di_birthnsec;
vap->va_bytes = dbtob((u_quad_t)ip->i_din2->di_blocks);
vap->va_filerev = ip->i_din2->di_modrev;
}
vap->va_flags = ip->i_flags;
vap->va_gen = ip->i_gen;
vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
vap->va_type = IFTOVT(ip->i_mode);
return (0);
}
/*
* Set attribute vnode op. called from several syscalls
*/
static int
ufs_setattr(ap)
struct vop_setattr_args /* {
struct vnode *a_vp;
struct vattr *a_vap;
struct ucred *a_cred;
} */ *ap;
{
struct vattr *vap = ap->a_vap;
struct vnode *vp = ap->a_vp;
struct inode *ip = VTOI(vp);
struct ucred *cred = ap->a_cred;
struct thread *td = curthread;
int error;
/*
* Check for unsettable attributes.
*/
if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
(vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
(vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
return (EINVAL);
}
if (vap->va_flags != VNOVAL) {
if (vp->v_mount->mnt_flag & MNT_RDONLY)
return (EROFS);
/*
* Callers may only modify the file flags on objects they
* have VADMIN rights for.
*/
if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
return (error);
/*
* Unprivileged processes are not permitted to unset system
* flags, or modify flags if any system flags are set.
* Privileged non-jail processes may not modify system flags
* if securelevel > 0 and any existing system flags are set.
* Privileged jail processes behave like privileged non-jail
* processes if the security.jail.chflags_allowed sysctl is
* is non-zero; otherwise, they behave like unprivileged
* processes.
*/
if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0)) {
if (ip->i_flags
& (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) {
error = securelevel_gt(cred, 0);
if (error)
return (error);
}
/* Snapshot flag cannot be set or cleared */
if (((vap->va_flags & SF_SNAPSHOT) != 0 &&
(ip->i_flags & SF_SNAPSHOT) == 0) ||
((vap->va_flags & SF_SNAPSHOT) == 0 &&
(ip->i_flags & SF_SNAPSHOT) != 0))
return (EPERM);
ip->i_flags = vap->va_flags;
DIP_SET(ip, i_flags, vap->va_flags);
} else {
if (ip->i_flags
& (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND) ||
(vap->va_flags & UF_SETTABLE) != vap->va_flags)
return (EPERM);
ip->i_flags &= SF_SETTABLE;
ip->i_flags |= (vap->va_flags & UF_SETTABLE);
DIP_SET(ip, i_flags, ip->i_flags);
}
ip->i_flag |= IN_CHANGE;
if (vap->va_flags & (IMMUTABLE | APPEND))
return (0);
}
if (ip->i_flags & (IMMUTABLE | APPEND))
return (EPERM);
/*
* Go through the fields and update iff not VNOVAL.
*/
if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
if (vp->v_mount->mnt_flag & MNT_RDONLY)
return (EROFS);
if ((error = ufs_chown(vp, vap->va_uid, vap->va_gid, cred,
td)) != 0)
return (error);
}
if (vap->va_size != VNOVAL) {
/*
* XXX most of the following special cases should be in
* callers instead of in N filesystems. The VDIR check
* mostly already is.
*/
switch (vp->v_type) {
case VDIR:
return (EISDIR);
case VLNK:
case VREG:
/*
* Truncation should have an effect in these cases.
* Disallow it if the filesystem is read-only or
* the file is being snapshotted.
*/
if (vp->v_mount->mnt_flag & MNT_RDONLY)
return (EROFS);
if ((ip->i_flags & SF_SNAPSHOT) != 0)
return (EPERM);
break;
default:
/*
* According to POSIX, the result is unspecified
* for file types other than regular files,
* directories and shared memory objects. We
* don't support shared memory objects in the file
* system, and have dubious support for truncating
* symlinks. Just ignore the request in other cases.
*/
return (0);
}
if ((error = UFS_TRUNCATE(vp, vap->va_size, IO_NORMAL,
cred, td)) != 0)
return (error);
}
if (vap->va_atime.tv_sec != VNOVAL ||
vap->va_mtime.tv_sec != VNOVAL ||
vap->va_birthtime.tv_sec != VNOVAL) {
if (vp->v_mount->mnt_flag & MNT_RDONLY)
return (EROFS);
if ((ip->i_flags & SF_SNAPSHOT) != 0)
return (EPERM);
/*
* From utimes(2):
* If times is NULL, ... The caller must be the owner of
* the file, have permission to write the file, or be the
* super-user.
* If times is non-NULL, ... The caller must be the owner of
* the file or be the super-user.
*
* Possibly for historical reasons, try to use VADMIN in
* preference to VWRITE for a NULL timestamp. This means we
* will return EACCES in preference to EPERM if neither
* check succeeds.
*/
if (vap->va_vaflags & VA_UTIMES_NULL) {
/*
* NFSv4.1, draft 21, 6.2.1.3.1, Discussion of Mask Attributes
*
* "A user having ACL_WRITE_DATA or ACL_WRITE_ATTRIBUTES
* will be allowed to set the times [..] to the current
* server time."
*
* XXX: Calling it four times seems a little excessive.
*/
error = VOP_ACCESSX(vp, VWRITE_ATTRIBUTES, cred, td);
if (error)
error = VOP_ACCESS(vp, VWRITE, cred, td);
} else
error = VOP_ACCESSX(vp, VWRITE_ATTRIBUTES, cred, td);
if (error)
return (error);
if (vap->va_atime.tv_sec != VNOVAL)
ip->i_flag |= IN_ACCESS;
if (vap->va_mtime.tv_sec != VNOVAL)
ip->i_flag |= IN_CHANGE | IN_UPDATE;
if (vap->va_birthtime.tv_sec != VNOVAL &&
ip->i_ump->um_fstype == UFS2)
ip->i_flag |= IN_MODIFIED;
ufs_itimes(vp);
if (vap->va_atime.tv_sec != VNOVAL) {
DIP_SET(ip, i_atime, vap->va_atime.tv_sec);
DIP_SET(ip, i_atimensec, vap->va_atime.tv_nsec);
}
if (vap->va_mtime.tv_sec != VNOVAL) {
DIP_SET(ip, i_mtime, vap->va_mtime.tv_sec);
DIP_SET(ip, i_mtimensec, vap->va_mtime.tv_nsec);
}
if (vap->va_birthtime.tv_sec != VNOVAL &&
ip->i_ump->um_fstype == UFS2) {
ip->i_din2->di_birthtime = vap->va_birthtime.tv_sec;
ip->i_din2->di_birthnsec = vap->va_birthtime.tv_nsec;
}
error = UFS_UPDATE(vp, 0);
if (error)
return (error);
}
error = 0;
if (vap->va_mode != (mode_t)VNOVAL) {
if (vp->v_mount->mnt_flag & MNT_RDONLY)
return (EROFS);
if ((ip->i_flags & SF_SNAPSHOT) != 0 && (vap->va_mode &
(S_IXUSR | S_IWUSR | S_IXGRP | S_IWGRP | S_IXOTH | S_IWOTH)))
return (EPERM);
error = ufs_chmod(vp, (int)vap->va_mode, cred, td);
}
return (error);
}
#ifdef UFS_ACL
static int
ufs_update_nfs4_acl_after_mode_change(struct vnode *vp, int mode,
int file_owner_id, struct ucred *cred, struct thread *td)
{
int error;
struct acl *aclp;
aclp = acl_alloc(M_WAITOK);
error = ufs_getacl_nfs4_internal(vp, aclp, td);
/*
* We don't have to handle EOPNOTSUPP here, as the filesystem claims
* it supports ACLs.
*/
if (error)
goto out;
acl_nfs4_sync_acl_from_mode(aclp, mode, file_owner_id);
error = ufs_setacl_nfs4_internal(vp, aclp, td);
out:
acl_free(aclp);
return (error);
}
#endif /* UFS_ACL */
/*
* Mark this file's access time for update for vfs_mark_atime(). This
* is called from execve() and mmap().
*/
static int
ufs_markatime(ap)
struct vop_markatime_args /* {
struct vnode *a_vp;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
struct inode *ip = VTOI(vp);
VI_LOCK(vp);
ip->i_flag |= IN_ACCESS;
VI_UNLOCK(vp);
return (0);
}
/*
* Change the mode on a file.
* Inode must be locked before calling.
*/
static int
ufs_chmod(vp, mode, cred, td)
struct vnode *vp;
int mode;
struct ucred *cred;
struct thread *td;
{
struct inode *ip = VTOI(vp);
int error;
/*
* To modify the permissions on a file, must possess VADMIN
* for that file.
*/
if ((error = VOP_ACCESSX(vp, VWRITE_ACL, cred, td)))
return (error);
/*
* Privileged processes may set the sticky bit on non-directories,
* as well as set the setgid bit on a file with a group that the
* process is not a member of. Both of these are allowed in
* jail(8).
*/
if (vp->v_type != VDIR && (mode & S_ISTXT)) {
if (priv_check_cred(cred, PRIV_VFS_STICKYFILE, 0))
return (EFTYPE);
}
if (!groupmember(ip->i_gid, cred) && (mode & ISGID)) {
error = priv_check_cred(cred, PRIV_VFS_SETGID, 0);
if (error)
return (error);
}
/*
* Deny setting setuid if we are not the file owner.
*/
if ((mode & ISUID) && ip->i_uid != cred->cr_uid) {
error = priv_check_cred(cred, PRIV_VFS_ADMIN, 0);
if (error)
return (error);
}
ip->i_mode &= ~ALLPERMS;
ip->i_mode |= (mode & ALLPERMS);
DIP_SET(ip, i_mode, ip->i_mode);
ip->i_flag |= IN_CHANGE;
#ifdef UFS_ACL
if ((vp->v_mount->mnt_flag & MNT_NFS4ACLS) != 0)
error = ufs_update_nfs4_acl_after_mode_change(vp, mode, ip->i_uid, cred, td);
#endif
return (error);
}
/*
* Perform chown operation on inode ip;
* inode must be locked prior to call.
*/
static int
ufs_chown(vp, uid, gid, cred, td)
struct vnode *vp;
uid_t uid;
gid_t gid;
struct ucred *cred;
struct thread *td;
{
struct inode *ip = VTOI(vp);
uid_t ouid;
gid_t ogid;
int error = 0;
#ifdef QUOTA
int i;
ufs2_daddr_t change;
#endif
if (uid == (uid_t)VNOVAL)
uid = ip->i_uid;
if (gid == (gid_t)VNOVAL)
gid = ip->i_gid;
/*
* To modify the ownership of a file, must possess VADMIN for that
* file.
*/
if ((error = VOP_ACCESSX(vp, VWRITE_OWNER, cred, td)))
return (error);
/*
* To change the owner of a file, or change the group of a file to a
* group of which we are not a member, the caller must have
* privilege.
*/
if (((uid != ip->i_uid && uid != cred->cr_uid) ||
(gid != ip->i_gid && !groupmember(gid, cred))) &&
(error = priv_check_cred(cred, PRIV_VFS_CHOWN, 0)))
return (error);
ogid = ip->i_gid;
ouid = ip->i_uid;
#ifdef QUOTA
if ((error = getinoquota(ip)) != 0)
return (error);
if (ouid == uid) {
dqrele(vp, ip->i_dquot[USRQUOTA]);
ip->i_dquot[USRQUOTA] = NODQUOT;
}
if (ogid == gid) {
dqrele(vp, ip->i_dquot[GRPQUOTA]);
ip->i_dquot[GRPQUOTA] = NODQUOT;
}
change = DIP(ip, i_blocks);
(void) chkdq(ip, -change, cred, CHOWN);
(void) chkiq(ip, -1, cred, CHOWN);
for (i = 0; i < MAXQUOTAS; i++) {
dqrele(vp, ip->i_dquot[i]);
ip->i_dquot[i] = NODQUOT;
}
#endif
ip->i_gid = gid;
DIP_SET(ip, i_gid, gid);
ip->i_uid = uid;
DIP_SET(ip, i_uid, uid);
#ifdef QUOTA
if ((error = getinoquota(ip)) == 0) {
if (ouid == uid) {
dqrele(vp, ip->i_dquot[USRQUOTA]);
ip->i_dquot[USRQUOTA] = NODQUOT;
}
if (ogid == gid) {
dqrele(vp, ip->i_dquot[GRPQUOTA]);
ip->i_dquot[GRPQUOTA] = NODQUOT;
}
if ((error = chkdq(ip, change, cred, CHOWN)) == 0) {
if ((error = chkiq(ip, 1, cred, CHOWN)) == 0)
goto good;
else
(void) chkdq(ip, -change, cred, CHOWN|FORCE);
}
for (i = 0; i < MAXQUOTAS; i++) {
dqrele(vp, ip->i_dquot[i]);
ip->i_dquot[i] = NODQUOT;
}
}
ip->i_gid = ogid;
DIP_SET(ip, i_gid, ogid);
ip->i_uid = ouid;
DIP_SET(ip, i_uid, ouid);
if (getinoquota(ip) == 0) {
if (ouid == uid) {
dqrele(vp, ip->i_dquot[USRQUOTA]);
ip->i_dquot[USRQUOTA] = NODQUOT;
}
if (ogid == gid) {
dqrele(vp, ip->i_dquot[GRPQUOTA]);
ip->i_dquot[GRPQUOTA] = NODQUOT;
}
(void) chkdq(ip, change, cred, FORCE|CHOWN);
(void) chkiq(ip, 1, cred, FORCE|CHOWN);
(void) getinoquota(ip);
}
return (error);
good:
if (getinoquota(ip))
panic("ufs_chown: lost quota");
#endif /* QUOTA */
ip->i_flag |= IN_CHANGE;
if ((ip->i_mode & (ISUID | ISGID)) && (ouid != uid || ogid != gid)) {
if (priv_check_cred(cred, PRIV_VFS_RETAINSUGID, 0)) {
ip->i_mode &= ~(ISUID | ISGID);
DIP_SET(ip, i_mode, ip->i_mode);
}
}
return (0);
}
static int
ufs_remove(ap)
struct vop_remove_args /* {
struct vnode *a_dvp;
struct vnode *a_vp;
struct componentname *a_cnp;
} */ *ap;
{
struct inode *ip;
struct vnode *vp = ap->a_vp;
struct vnode *dvp = ap->a_dvp;
int error;
struct thread *td;
td = curthread;
ip = VTOI(vp);
if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
(VTOI(dvp)->i_flags & APPEND)) {
error = EPERM;
goto out;
}
#ifdef UFS_GJOURNAL
ufs_gjournal_orphan(vp);
#endif
error = ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0);
if (ip->i_nlink <= 0)
vp->v_vflag |= VV_NOSYNC;
if ((ip->i_flags & SF_SNAPSHOT) != 0) {
/*
* Avoid deadlock where another thread is trying to
* update the inodeblock for dvp and is waiting on
* snaplk. Temporary unlock the vnode lock for the
* unlinked file and sync the directory. This should
* allow vput() of the directory to not block later on
* while holding the snapshot vnode locked, assuming
* that the directory hasn't been unlinked too.
*/
VOP_UNLOCK(vp, 0);
(void) VOP_FSYNC(dvp, MNT_WAIT, td);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
}
out:
return (error);
}
/*
* link vnode call
*/
static int
ufs_link(ap)
struct vop_link_args /* {
struct vnode *a_tdvp;
struct vnode *a_vp;
struct componentname *a_cnp;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
struct vnode *tdvp = ap->a_tdvp;
struct componentname *cnp = ap->a_cnp;
struct inode *ip;
struct direct newdir;
int error;
#ifdef INVARIANTS
if ((cnp->cn_flags & HASBUF) == 0)
panic("ufs_link: no name");
#endif
if (tdvp->v_mount != vp->v_mount) {
error = EXDEV;
goto out;
}
if (VTOI(tdvp)->i_effnlink < 2)
panic("ufs_link: Bad link count %d on parent",
VTOI(tdvp)->i_effnlink);
ip = VTOI(vp);
if ((nlink_t)ip->i_nlink >= LINK_MAX) {
error = EMLINK;
goto out;
}
if (ip->i_flags & (IMMUTABLE | APPEND)) {
error = EPERM;
goto out;
}
ip->i_effnlink++;
ip->i_nlink++;
DIP_SET(ip, i_nlink, ip->i_nlink);
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(vp))
softdep_setup_link(VTOI(tdvp), ip);
error = UFS_UPDATE(vp, !(DOINGSOFTDEP(vp) | DOINGASYNC(vp)));
if (!error) {
ufs_makedirentry(ip, cnp, &newdir);
error = ufs_direnter(tdvp, vp, &newdir, cnp, NULL, 0);
}
if (error) {
ip->i_effnlink--;
ip->i_nlink--;
DIP_SET(ip, i_nlink, ip->i_nlink);
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(vp))
softdep_revert_link(VTOI(tdvp), ip);
}
out:
return (error);
}
/*
* whiteout vnode call
*/
static int
ufs_whiteout(ap)
struct vop_whiteout_args /* {
struct vnode *a_dvp;
struct componentname *a_cnp;
int a_flags;
} */ *ap;
{
struct vnode *dvp = ap->a_dvp;
struct componentname *cnp = ap->a_cnp;
struct direct newdir;
int error = 0;
switch (ap->a_flags) {
case LOOKUP:
/* 4.4 format directories support whiteout operations */
if (dvp->v_mount->mnt_maxsymlinklen > 0)
return (0);
return (EOPNOTSUPP);
case CREATE:
/* create a new directory whiteout */
#ifdef INVARIANTS
if ((cnp->cn_flags & SAVENAME) == 0)
panic("ufs_whiteout: missing name");
if (dvp->v_mount->mnt_maxsymlinklen <= 0)
panic("ufs_whiteout: old format filesystem");
#endif
newdir.d_ino = WINO;
newdir.d_namlen = cnp->cn_namelen;
bcopy(cnp->cn_nameptr, newdir.d_name, (unsigned)cnp->cn_namelen + 1);
newdir.d_type = DT_WHT;
error = ufs_direnter(dvp, NULL, &newdir, cnp, NULL, 0);
break;
case DELETE:
/* remove an existing directory whiteout */
#ifdef INVARIANTS
if (dvp->v_mount->mnt_maxsymlinklen <= 0)
panic("ufs_whiteout: old format filesystem");
#endif
cnp->cn_flags &= ~DOWHITEOUT;
error = ufs_dirremove(dvp, NULL, cnp->cn_flags, 0);
break;
default:
panic("ufs_whiteout: unknown op");
}
return (error);
}
static volatile int rename_restarts;
SYSCTL_INT(_vfs_ufs, OID_AUTO, rename_restarts, CTLFLAG_RD,
__DEVOLATILE(int *, &rename_restarts), 0,
"Times rename had to restart due to lock contention");
/*
* Rename system call.
* rename("foo", "bar");
* is essentially
* unlink("bar");
* link("foo", "bar");
* unlink("foo");
* but ``atomically''. Can't do full commit without saving state in the
* inode on disk which isn't feasible at this time. Best we can do is
* always guarantee the target exists.
*
* Basic algorithm is:
*
* 1) Bump link count on source while we're linking it to the
* target. This also ensure the inode won't be deleted out
* from underneath us while we work (it may be truncated by
* a concurrent `trunc' or `open' for creation).
* 2) Link source to destination. If destination already exists,
* delete it first.
* 3) Unlink source reference to inode if still around. If a
* directory was moved and the parent of the destination
* is different from the source, patch the ".." entry in the
* directory.
*/
static int
ufs_rename(ap)
struct vop_rename_args /* {
struct vnode *a_fdvp;
struct vnode *a_fvp;
struct componentname *a_fcnp;
struct vnode *a_tdvp;
struct vnode *a_tvp;
struct componentname *a_tcnp;
} */ *ap;
{
struct vnode *tvp = ap->a_tvp;
struct vnode *tdvp = ap->a_tdvp;
struct vnode *fvp = ap->a_fvp;
struct vnode *fdvp = ap->a_fdvp;
struct vnode *nvp;
struct componentname *tcnp = ap->a_tcnp;
struct componentname *fcnp = ap->a_fcnp;
struct thread *td = fcnp->cn_thread;
struct inode *fip, *tip, *tdp, *fdp;
struct direct newdir;
off_t endoff;
int doingdirectory, newparent;
int error = 0;
struct mount *mp;
ino_t ino;
#ifdef INVARIANTS
if ((tcnp->cn_flags & HASBUF) == 0 ||
(fcnp->cn_flags & HASBUF) == 0)
panic("ufs_rename: no name");
#endif
endoff = 0;
mp = tdvp->v_mount;
VOP_UNLOCK(tdvp, 0);
if (tvp && tvp != tdvp)
VOP_UNLOCK(tvp, 0);
/*
* Check for cross-device rename.
*/
if ((fvp->v_mount != tdvp->v_mount) ||
(tvp && (fvp->v_mount != tvp->v_mount))) {
error = EXDEV;
mp = NULL;
goto releout;
}
error = vfs_busy(mp, 0);
if (error) {
mp = NULL;
goto releout;
}
relock:
/*
* We need to acquire 2 to 4 locks depending on whether tvp is NULL
* and fdvp and tdvp are the same directory. Subsequently we need
* to double-check all paths and in the directory rename case we
* need to verify that we are not creating a directory loop. To
* handle this we acquire all but fdvp using non-blocking
* acquisitions. If we fail to acquire any lock in the path we will
* drop all held locks, acquire the new lock in a blocking fashion,
* and then release it and restart the rename. This acquire/release
* step ensures that we do not spin on a lock waiting for release.
*/
error = vn_lock(fdvp, LK_EXCLUSIVE);
if (error)
goto releout;
if (vn_lock(tdvp, LK_EXCLUSIVE | LK_NOWAIT) != 0) {
VOP_UNLOCK(fdvp, 0);
error = vn_lock(tdvp, LK_EXCLUSIVE);
if (error)
goto releout;
VOP_UNLOCK(tdvp, 0);
atomic_add_int(&rename_restarts, 1);
goto relock;
}
/*
* Re-resolve fvp to be certain it still exists and fetch the
* correct vnode.
*/
error = ufs_lookup_ino(fdvp, NULL, fcnp, &ino);
if (error) {
VOP_UNLOCK(fdvp, 0);
VOP_UNLOCK(tdvp, 0);
goto releout;
}
error = VFS_VGET(mp, ino, LK_EXCLUSIVE | LK_NOWAIT, &nvp);
if (error) {
VOP_UNLOCK(fdvp, 0);
VOP_UNLOCK(tdvp, 0);
if (error != EBUSY)
goto releout;
error = VFS_VGET(mp, ino, LK_EXCLUSIVE, &nvp);
if (error != 0)
goto releout;
VOP_UNLOCK(nvp, 0);
vrele(fvp);
fvp = nvp;
atomic_add_int(&rename_restarts, 1);
goto relock;
}
vrele(fvp);
fvp = nvp;
/*
* Re-resolve tvp and acquire the vnode lock if present.
*/
error = ufs_lookup_ino(tdvp, NULL, tcnp, &ino);
if (error != 0 && error != EJUSTRETURN) {
VOP_UNLOCK(fdvp, 0);
VOP_UNLOCK(tdvp, 0);
VOP_UNLOCK(fvp, 0);
goto releout;
}
/*
* If tvp disappeared we just carry on.
*/
if (error == EJUSTRETURN && tvp != NULL) {
vrele(tvp);
tvp = NULL;
}
/*
* Get the tvp ino if the lookup succeeded. We may have to restart
* if the non-blocking acquire fails.
*/
if (error == 0) {
nvp = NULL;
error = VFS_VGET(mp, ino, LK_EXCLUSIVE | LK_NOWAIT, &nvp);
if (tvp)
vrele(tvp);
tvp = nvp;
if (error) {
VOP_UNLOCK(fdvp, 0);
VOP_UNLOCK(tdvp, 0);
VOP_UNLOCK(fvp, 0);
if (error != EBUSY)
goto releout;
error = VFS_VGET(mp, ino, LK_EXCLUSIVE, &nvp);
if (error != 0)
goto releout;
VOP_UNLOCK(nvp, 0);
atomic_add_int(&rename_restarts, 1);
goto relock;
}
}
fdp = VTOI(fdvp);
fip = VTOI(fvp);
tdp = VTOI(tdvp);
tip = NULL;
if (tvp)
tip = VTOI(tvp);
if (tvp && ((VTOI(tvp)->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
(VTOI(tdvp)->i_flags & APPEND))) {
error = EPERM;
goto unlockout;
}
/*
* Renaming a file to itself has no effect. The upper layers should
* not call us in that case. However, things could change after
* we drop the locks above.
*/
if (fvp == tvp) {
error = 0;
goto unlockout;
}
doingdirectory = 0;
newparent = 0;
ino = fip->i_number;
if (fip->i_nlink >= LINK_MAX) {
error = EMLINK;
goto unlockout;
}
if ((fip->i_flags & (NOUNLINK | IMMUTABLE | APPEND))
|| (fdp->i_flags & APPEND)) {
error = EPERM;
goto unlockout;
}
if ((fip->i_mode & IFMT) == IFDIR) {
/*
* Avoid ".", "..", and aliases of "." for obvious reasons.
*/
if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
fdp == fip ||
(fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT) {
error = EINVAL;
goto unlockout;
}
if (fdp->i_number != tdp->i_number)
newparent = tdp->i_number;
doingdirectory = 1;
}
- if (fvp->v_mountedhere != NULL || (tvp && tvp->v_mountedhere != NULL)) {
+ if ((fvp->v_type == VDIR && fvp->v_mountedhere != NULL) ||
+ (tvp != NULL && tvp->v_type == VDIR &&
+ tvp->v_mountedhere != NULL)) {
error = EXDEV;
goto unlockout;
}
/*
* If ".." must be changed (ie the directory gets a new
* parent) then the source directory must not be in the
* directory hierarchy above the target, as this would
* orphan everything below the source directory. Also
* the user must have write permission in the source so
* as to be able to change "..".
*/
if (doingdirectory && newparent) {
error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_thread);
if (error)
goto unlockout;
error = ufs_checkpath(ino, fdp->i_number, tdp, tcnp->cn_cred,
&ino);
/*
* We encountered a lock that we have to wait for. Unlock
* everything else and VGET before restarting.
*/
if (ino) {
VOP_UNLOCK(fdvp, 0);
VOP_UNLOCK(fvp, 0);
VOP_UNLOCK(tdvp, 0);
if (tvp)
VOP_UNLOCK(tvp, 0);
error = VFS_VGET(mp, ino, LK_SHARED, &nvp);
if (error == 0)
vput(nvp);
atomic_add_int(&rename_restarts, 1);
goto relock;
}
if (error)
goto unlockout;
if ((tcnp->cn_flags & SAVESTART) == 0)
panic("ufs_rename: lost to startdir");
}
if (fip->i_effnlink == 0 || fdp->i_effnlink == 0 ||
tdp->i_effnlink == 0)
panic("Bad effnlink fip %p, fdp %p, tdp %p", fip, fdp, tdp);
/*
* 1) Bump link count while we're moving stuff
* around. If we crash somewhere before
* completing our work, the link count
* may be wrong, but correctable.
*/
fip->i_effnlink++;
fip->i_nlink++;
DIP_SET(fip, i_nlink, fip->i_nlink);
fip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(fvp))
softdep_setup_link(tdp, fip);
error = UFS_UPDATE(fvp, !(DOINGSOFTDEP(fvp) | DOINGASYNC(fvp)));
if (error)
goto bad;
/*
* 2) If target doesn't exist, link the target
* to the source and unlink the source.
* Otherwise, rewrite the target directory
* entry to reference the source inode and
* expunge the original entry's existence.
*/
if (tip == NULL) {
if (tdp->i_dev != fip->i_dev)
panic("ufs_rename: EXDEV");
if (doingdirectory && newparent) {
/*
* Account for ".." in new directory.
* When source and destination have the same
* parent we don't adjust the link count. The
* actual link modification is completed when
* .. is rewritten below.
*/
if ((nlink_t)tdp->i_nlink >= LINK_MAX) {
error = EMLINK;
goto bad;
}
}
ufs_makedirentry(fip, tcnp, &newdir);
error = ufs_direnter(tdvp, NULL, &newdir, tcnp, NULL, 1);
if (error)
goto bad;
/* Setup tdvp for directory compaction if needed. */
if (tdp->i_count && tdp->i_endoff &&
tdp->i_endoff < tdp->i_size)
endoff = tdp->i_endoff;
} else {
if (tip->i_dev != tdp->i_dev || tip->i_dev != fip->i_dev)
panic("ufs_rename: EXDEV");
/*
* Short circuit rename(foo, foo).
*/
if (tip->i_number == fip->i_number)
panic("ufs_rename: same file");
/*
* If the parent directory is "sticky", then the caller
* must possess VADMIN for the parent directory, or the
* destination of the rename. This implements append-only
* directories.
*/
if ((tdp->i_mode & S_ISTXT) &&
VOP_ACCESS(tdvp, VADMIN, tcnp->cn_cred, td) &&
VOP_ACCESS(tvp, VADMIN, tcnp->cn_cred, td)) {
error = EPERM;
goto bad;
}
/*
* Target must be empty if a directory and have no links
* to it. Also, ensure source and target are compatible
* (both directories, or both not directories).
*/
if ((tip->i_mode & IFMT) == IFDIR) {
if ((tip->i_effnlink > 2) ||
!ufs_dirempty(tip, tdp->i_number, tcnp->cn_cred)) {
error = ENOTEMPTY;
goto bad;
}
if (!doingdirectory) {
error = ENOTDIR;
goto bad;
}
cache_purge(tdvp);
} else if (doingdirectory) {
error = EISDIR;
goto bad;
}
if (doingdirectory) {
if (!newparent) {
tdp->i_effnlink--;
if (DOINGSOFTDEP(tdvp))
softdep_change_linkcnt(tdp);
}
tip->i_effnlink--;
if (DOINGSOFTDEP(tvp))
softdep_change_linkcnt(tip);
}
error = ufs_dirrewrite(tdp, tip, fip->i_number,
IFTODT(fip->i_mode),
(doingdirectory && newparent) ? newparent : doingdirectory);
if (error) {
if (doingdirectory) {
if (!newparent) {
tdp->i_effnlink++;
if (DOINGSOFTDEP(tdvp))
softdep_change_linkcnt(tdp);
}
tip->i_effnlink++;
if (DOINGSOFTDEP(tvp))
softdep_change_linkcnt(tip);
}
}
if (doingdirectory && !DOINGSOFTDEP(tvp)) {
/*
* The only stuff left in the directory is "."
* and "..". The "." reference is inconsequential
* since we are quashing it. We have removed the "."
* reference and the reference in the parent directory,
* but there may be other hard links. The soft
* dependency code will arrange to do these operations
* after the parent directory entry has been deleted on
* disk, so when running with that code we avoid doing
* them now.
*/
if (!newparent) {
tdp->i_nlink--;
DIP_SET(tdp, i_nlink, tdp->i_nlink);
tdp->i_flag |= IN_CHANGE;
}
tip->i_nlink--;
DIP_SET(tip, i_nlink, tip->i_nlink);
tip->i_flag |= IN_CHANGE;
}
}
/*
* 3) Unlink the source. We have to resolve the path again to
* fixup the directory offset and count for ufs_dirremove.
*/
if (fdvp == tdvp) {
error = ufs_lookup_ino(fdvp, NULL, fcnp, &ino);
if (error)
panic("ufs_rename: from entry went away!");
if (ino != fip->i_number)
panic("ufs_rename: ino mismatch %d != %d\n", ino,
fip->i_number);
}
/*
* If the source is a directory with a
* new parent, the link count of the old
* parent directory must be decremented
* and ".." set to point to the new parent.
*/
if (doingdirectory && newparent) {
/*
* If tip exists we simply use its link, otherwise we must
* add a new one.
*/
if (tip == NULL) {
tdp->i_effnlink++;
tdp->i_nlink++;
DIP_SET(tdp, i_nlink, tdp->i_nlink);
tdp->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(tdvp))
softdep_setup_dotdot_link(tdp, fip);
error = UFS_UPDATE(tdvp, !(DOINGSOFTDEP(tdvp) |
DOINGASYNC(tdvp)));
/* Don't go to bad here as the new link exists. */
if (error)
goto unlockout;
} else if (DOINGSUJ(tdvp))
/* Journal must account for each new link. */
softdep_setup_dotdot_link(tdp, fip);
fip->i_offset = mastertemplate.dot_reclen;
ufs_dirrewrite(fip, fdp, newparent, DT_DIR, 0);
cache_purge(fdvp);
}
error = ufs_dirremove(fdvp, fip, fcnp->cn_flags, 0);
unlockout:
vput(fdvp);
vput(fvp);
if (tvp)
vput(tvp);
/*
* If compaction or fsync was requested do it now that other locks
* are no longer needed.
*/
if (error == 0 && endoff != 0) {
#ifdef UFS_DIRHASH
if (tdp->i_dirhash != NULL)
ufsdirhash_dirtrunc(tdp, endoff);
#endif
UFS_TRUNCATE(tdvp, endoff, IO_NORMAL | IO_SYNC, tcnp->cn_cred,
td);
}
if (error == 0 && tdp->i_flag & IN_NEEDSYNC)
error = VOP_FSYNC(tdvp, MNT_WAIT, td);
vput(tdvp);
if (mp)
vfs_unbusy(mp);
return (error);
bad:
fip->i_effnlink--;
fip->i_nlink--;
DIP_SET(fip, i_nlink, fip->i_nlink);
fip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(fvp))
softdep_revert_link(tdp, fip);
goto unlockout;
releout:
vrele(fdvp);
vrele(fvp);
vrele(tdvp);
if (tvp)
vrele(tvp);
if (mp)
vfs_unbusy(mp);
return (error);
}
#ifdef UFS_ACL
static int
ufs_do_posix1e_acl_inheritance_dir(struct vnode *dvp, struct vnode *tvp,
mode_t dmode, struct ucred *cred, struct thread *td)
{
int error;
struct inode *ip = VTOI(tvp);
struct acl *dacl, *acl;
acl = acl_alloc(M_WAITOK);
dacl = acl_alloc(M_WAITOK);
/*
* Retrieve default ACL from parent, if any.
*/
error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cred, td);
switch (error) {
case 0:
/*
* Retrieved a default ACL, so merge mode and ACL if
* necessary. If the ACL is empty, fall through to
* the "not defined or available" case.
*/
if (acl->acl_cnt != 0) {
dmode = acl_posix1e_newfilemode(dmode, acl);
ip->i_mode = dmode;
DIP_SET(ip, i_mode, dmode);
*dacl = *acl;
ufs_sync_acl_from_inode(ip, acl);
break;
}
/* FALLTHROUGH */
case EOPNOTSUPP:
/*
* Just use the mode as-is.
*/
ip->i_mode = dmode;
DIP_SET(ip, i_mode, dmode);
error = 0;
goto out;
default:
goto out;
}
/*
* XXX: If we abort now, will Soft Updates notify the extattr
* code that the EAs for the file need to be released?
*/
error = VOP_SETACL(tvp, ACL_TYPE_ACCESS, acl, cred, td);
if (error == 0)
error = VOP_SETACL(tvp, ACL_TYPE_DEFAULT, dacl, cred, td);
switch (error) {
case 0:
break;
case EOPNOTSUPP:
/*
* XXX: This should not happen, as EOPNOTSUPP above
* was supposed to free acl.
*/
printf("ufs_mkdir: VOP_GETACL() but no VOP_SETACL()\n");
/*
panic("ufs_mkdir: VOP_GETACL() but no VOP_SETACL()");
*/
break;
default:
goto out;
}
out:
acl_free(acl);
acl_free(dacl);
return (error);
}
static int
ufs_do_posix1e_acl_inheritance_file(struct vnode *dvp, struct vnode *tvp,
mode_t mode, struct ucred *cred, struct thread *td)
{
int error;
struct inode *ip = VTOI(tvp);
struct acl *acl;
acl = acl_alloc(M_WAITOK);
/*
* Retrieve default ACL for parent, if any.
*/
error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cred, td);
switch (error) {
case 0:
/*
* Retrieved a default ACL, so merge mode and ACL if
* necessary.
*/
if (acl->acl_cnt != 0) {
/*
* Two possible ways for default ACL to not
* be present. First, the EA can be
* undefined, or second, the default ACL can
* be blank. If it's blank, fall through to
* the it's not defined case.
*/
mode = acl_posix1e_newfilemode(mode, acl);
ip->i_mode = mode;
DIP_SET(ip, i_mode, mode);
ufs_sync_acl_from_inode(ip, acl);
break;
}
/* FALLTHROUGH */
case EOPNOTSUPP:
/*
* Just use the mode as-is.
*/
ip->i_mode = mode;
DIP_SET(ip, i_mode, mode);
error = 0;
goto out;
default:
goto out;
}
/*
* XXX: If we abort now, will Soft Updates notify the extattr
* code that the EAs for the file need to be released?
*/
error = VOP_SETACL(tvp, ACL_TYPE_ACCESS, acl, cred, td);
switch (error) {
case 0:
break;
case EOPNOTSUPP:
/*
* XXX: This should not happen, as EOPNOTSUPP above was
* supposed to free acl.
*/
printf("ufs_makeinode: VOP_GETACL() but no "
"VOP_SETACL()\n");
/* panic("ufs_makeinode: VOP_GETACL() but no "
"VOP_SETACL()"); */
break;
default:
goto out;
}
out:
acl_free(acl);
return (error);
}
static int
ufs_do_nfs4_acl_inheritance(struct vnode *dvp, struct vnode *tvp,
mode_t child_mode, struct ucred *cred, struct thread *td)
{
int error;
struct acl *parent_aclp, *child_aclp;
parent_aclp = acl_alloc(M_WAITOK);
child_aclp = acl_alloc(M_WAITOK | M_ZERO);
error = ufs_getacl_nfs4_internal(dvp, parent_aclp, td);
if (error)
goto out;
acl_nfs4_compute_inherited_acl(parent_aclp, child_aclp,
child_mode, VTOI(tvp)->i_uid, tvp->v_type == VDIR);
error = ufs_setacl_nfs4_internal(tvp, child_aclp, td);
if (error)
goto out;
out:
acl_free(parent_aclp);
acl_free(child_aclp);
return (error);
}
#endif
/*
* Mkdir system call
*/
static int
ufs_mkdir(ap)
struct vop_mkdir_args /* {
struct vnode *a_dvp;
struct vnode **a_vpp;
struct componentname *a_cnp;
struct vattr *a_vap;
} */ *ap;
{
struct vnode *dvp = ap->a_dvp;
struct vattr *vap = ap->a_vap;
struct componentname *cnp = ap->a_cnp;
struct inode *ip, *dp;
struct vnode *tvp;
struct buf *bp;
struct dirtemplate dirtemplate, *dtp;
struct direct newdir;
int error, dmode;
long blkoff;
#ifdef INVARIANTS
if ((cnp->cn_flags & HASBUF) == 0)
panic("ufs_mkdir: no name");
#endif
dp = VTOI(dvp);
if ((nlink_t)dp->i_nlink >= LINK_MAX) {
error = EMLINK;
goto out;
}
dmode = vap->va_mode & 0777;
dmode |= IFDIR;
/*
* Must simulate part of ufs_makeinode here to acquire the inode,
* but not have it entered in the parent directory. The entry is
* made later after writing "." and ".." entries.
*/
error = UFS_VALLOC(dvp, dmode, cnp->cn_cred, &tvp);
if (error)
goto out;
ip = VTOI(tvp);
ip->i_gid = dp->i_gid;
DIP_SET(ip, i_gid, dp->i_gid);
#ifdef SUIDDIR
{
#ifdef QUOTA
struct ucred ucred, *ucp;
gid_t ucred_group;
ucp = cnp->cn_cred;
#endif
/*
* If we are hacking owners here, (only do this where told to)
* and we are not giving it TO root, (would subvert quotas)
* then go ahead and give it to the other user.
* The new directory also inherits the SUID bit.
* If user's UID and dir UID are the same,
* 'give it away' so that the SUID is still forced on.
*/
if ((dvp->v_mount->mnt_flag & MNT_SUIDDIR) &&
(dp->i_mode & ISUID) && dp->i_uid) {
dmode |= ISUID;
ip->i_uid = dp->i_uid;
DIP_SET(ip, i_uid, dp->i_uid);
#ifdef QUOTA
if (dp->i_uid != cnp->cn_cred->cr_uid) {
/*
* Make sure the correct user gets charged
* for the space.
* Make a dummy credential for the victim.
* XXX This seems to never be accessed out of
* our context so a stack variable is ok.
*/
refcount_init(&ucred.cr_ref, 1);
ucred.cr_uid = ip->i_uid;
ucred.cr_ngroups = 1;
ucred.cr_groups = &ucred_group;
ucred.cr_groups[0] = dp->i_gid;
ucp = &ucred;
}
#endif
} else {
ip->i_uid = cnp->cn_cred->cr_uid;
DIP_SET(ip, i_uid, ip->i_uid);
}
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, ucp, 0))) {
UFS_VFREE(tvp, ip->i_number, dmode);
vput(tvp);
return (error);
}
#endif
}
#else /* !SUIDDIR */
ip->i_uid = cnp->cn_cred->cr_uid;
DIP_SET(ip, i_uid, ip->i_uid);
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, cnp->cn_cred, 0))) {
UFS_VFREE(tvp, ip->i_number, dmode);
vput(tvp);
return (error);
}
#endif
#endif /* !SUIDDIR */
ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
ip->i_mode = dmode;
DIP_SET(ip, i_mode, dmode);
tvp->v_type = VDIR; /* Rest init'd in getnewvnode(). */
ip->i_effnlink = 2;
ip->i_nlink = 2;
DIP_SET(ip, i_nlink, 2);
if (cnp->cn_flags & ISWHITEOUT) {
ip->i_flags |= UF_OPAQUE;
DIP_SET(ip, i_flags, ip->i_flags);
}
/*
* Bump link count in parent directory to reflect work done below.
* Should be done before reference is created so cleanup is
* possible if we crash.
*/
dp->i_effnlink++;
dp->i_nlink++;
DIP_SET(dp, i_nlink, dp->i_nlink);
dp->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(dvp))
softdep_setup_mkdir(dp, ip);
error = UFS_UPDATE(dvp, !(DOINGSOFTDEP(dvp) | DOINGASYNC(dvp)));
if (error)
goto bad;
#ifdef MAC
if (dvp->v_mount->mnt_flag & MNT_MULTILABEL) {
error = mac_vnode_create_extattr(cnp->cn_cred, dvp->v_mount,
dvp, tvp, cnp);
if (error)
goto bad;
}
#endif
#ifdef UFS_ACL
if (dvp->v_mount->mnt_flag & MNT_ACLS) {
error = ufs_do_posix1e_acl_inheritance_dir(dvp, tvp, dmode,
cnp->cn_cred, cnp->cn_thread);
if (error)
goto bad;
} else if (dvp->v_mount->mnt_flag & MNT_NFS4ACLS) {
error = ufs_do_nfs4_acl_inheritance(dvp, tvp, dmode,
cnp->cn_cred, cnp->cn_thread);
if (error)
goto bad;
}
#endif /* !UFS_ACL */
/*
* Initialize directory with "." and ".." from static template.
*/
if (dvp->v_mount->mnt_maxsymlinklen > 0)
dtp = &mastertemplate;
else
dtp = (struct dirtemplate *)&omastertemplate;
dirtemplate = *dtp;
dirtemplate.dot_ino = ip->i_number;
dirtemplate.dotdot_ino = dp->i_number;
if ((error = UFS_BALLOC(tvp, (off_t)0, DIRBLKSIZ, cnp->cn_cred,
BA_CLRBUF, &bp)) != 0)
goto bad;
ip->i_size = DIRBLKSIZ;
DIP_SET(ip, i_size, DIRBLKSIZ);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
vnode_pager_setsize(tvp, (u_long)ip->i_size);
bcopy((caddr_t)&dirtemplate, (caddr_t)bp->b_data, sizeof dirtemplate);
if (DOINGSOFTDEP(tvp)) {
/*
* Ensure that the entire newly allocated block is a
* valid directory so that future growth within the
* block does not have to ensure that the block is
* written before the inode.
*/
blkoff = DIRBLKSIZ;
while (blkoff < bp->b_bcount) {
((struct direct *)
(bp->b_data + blkoff))->d_reclen = DIRBLKSIZ;
blkoff += DIRBLKSIZ;
}
}
if ((error = UFS_UPDATE(tvp, !(DOINGSOFTDEP(tvp) |
DOINGASYNC(tvp)))) != 0) {
(void)bwrite(bp);
goto bad;
}
/*
* Directory set up, now install its entry in the parent directory.
*
* If we are not doing soft dependencies, then we must write out the
* buffer containing the new directory body before entering the new
* name in the parent. If we are doing soft dependencies, then the
* buffer containing the new directory body will be passed to and
* released in the soft dependency code after the code has attached
* an appropriate ordering dependency to the buffer which ensures that
* the buffer is written before the new name is written in the parent.
*/
if (DOINGASYNC(dvp))
bdwrite(bp);
else if (!DOINGSOFTDEP(dvp) && ((error = bwrite(bp))))
goto bad;
ufs_makedirentry(ip, cnp, &newdir);
error = ufs_direnter(dvp, tvp, &newdir, cnp, bp, 0);
bad:
if (error == 0) {
*ap->a_vpp = tvp;
} else {
dp->i_effnlink--;
dp->i_nlink--;
DIP_SET(dp, i_nlink, dp->i_nlink);
dp->i_flag |= IN_CHANGE;
/*
* No need to do an explicit VOP_TRUNCATE here, vrele will
* do this for us because we set the link count to 0.
*/
ip->i_effnlink = 0;
ip->i_nlink = 0;
DIP_SET(ip, i_nlink, 0);
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(tvp))
softdep_revert_mkdir(dp, ip);
vput(tvp);
}
out:
return (error);
}
/*
* Rmdir system call.
*/
static int
ufs_rmdir(ap)
struct vop_rmdir_args /* {
struct vnode *a_dvp;
struct vnode *a_vp;
struct componentname *a_cnp;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
struct vnode *dvp = ap->a_dvp;
struct componentname *cnp = ap->a_cnp;
struct inode *ip, *dp;
int error;
ip = VTOI(vp);
dp = VTOI(dvp);
/*
* Do not remove a directory that is in the process of being renamed.
* Verify the directory is empty (and valid). Rmdir ".." will not be
* valid since ".." will contain a reference to the current directory
* and thus be non-empty. Do not allow the removal of mounted on
* directories (this can happen when an NFS exported filesystem
* tries to remove a locally mounted on directory).
*/
error = 0;
if (ip->i_effnlink < 2) {
error = EINVAL;
goto out;
}
if (dp->i_effnlink < 3)
panic("ufs_dirrem: Bad link count %d on parent",
dp->i_effnlink);
if (!ufs_dirempty(ip, dp->i_number, cnp->cn_cred)) {
error = ENOTEMPTY;
goto out;
}
if ((dp->i_flags & APPEND)
|| (ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND))) {
error = EPERM;
goto out;
}
if (vp->v_mountedhere != 0) {
error = EINVAL;
goto out;
}
#ifdef UFS_GJOURNAL
ufs_gjournal_orphan(vp);
#endif
/*
* Delete reference to directory before purging
* inode. If we crash in between, the directory
* will be reattached to lost+found,
*/
dp->i_effnlink--;
ip->i_effnlink--;
if (DOINGSOFTDEP(vp))
softdep_setup_rmdir(dp, ip);
error = ufs_dirremove(dvp, ip, cnp->cn_flags, 1);
if (error) {
dp->i_effnlink++;
ip->i_effnlink++;
if (DOINGSOFTDEP(vp))
softdep_revert_rmdir(dp, ip);
goto out;
}
cache_purge(dvp);
/*
* The only stuff left in the directory is "." and "..". The "."
* reference is inconsequential since we are quashing it. The soft
* dependency code will arrange to do these operations after
* the parent directory entry has been deleted on disk, so
* when running with that code we avoid doing them now.
*/
if (!DOINGSOFTDEP(vp)) {
dp->i_nlink--;
DIP_SET(dp, i_nlink, dp->i_nlink);
dp->i_flag |= IN_CHANGE;
ip->i_nlink--;
DIP_SET(ip, i_nlink, ip->i_nlink);
ip->i_flag |= IN_CHANGE;
}
cache_purge(vp);
#ifdef UFS_DIRHASH
/* Kill any active hash; i_effnlink == 0, so it will not come back. */
if (ip->i_dirhash != NULL)
ufsdirhash_free(ip);
#endif
out:
return (error);
}
/*
* symlink -- make a symbolic link
*/
static int
ufs_symlink(ap)
struct vop_symlink_args /* {
struct vnode *a_dvp;
struct vnode **a_vpp;
struct componentname *a_cnp;
struct vattr *a_vap;
char *a_target;
} */ *ap;
{
struct vnode *vp, **vpp = ap->a_vpp;
struct inode *ip;
int len, error;
error = ufs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp,
vpp, ap->a_cnp);
if (error)
return (error);
vp = *vpp;
len = strlen(ap->a_target);
if (len < vp->v_mount->mnt_maxsymlinklen) {
ip = VTOI(vp);
bcopy(ap->a_target, SHORTLINK(ip), len);
ip->i_size = len;
DIP_SET(ip, i_size, len);
ip->i_flag |= IN_CHANGE | IN_UPDATE;
} else
error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0,
UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK,
ap->a_cnp->cn_cred, NOCRED, NULL, NULL);
if (error)
vput(vp);
return (error);
}
/*
* Vnode op for reading directories.
*
* The routine below assumes that the on-disk format of a directory
* is the same as that defined by <sys/dirent.h>. If the on-disk
* format changes, then it will be necessary to do a conversion
* from the on-disk format that read returns to the format defined
* by <sys/dirent.h>.
*/
int
ufs_readdir(ap)
struct vop_readdir_args /* {
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
int *a_eofflag;
int *a_ncookies;
u_long **a_cookies;
} */ *ap;
{
struct uio *uio = ap->a_uio;
struct inode *ip;
int error;
size_t count, lost;
off_t off;
if (ap->a_ncookies != NULL)
/*
* Ensure that the block is aligned. The caller can use
* the cookies to determine where in the block to start.
*/
uio->uio_offset &= ~(DIRBLKSIZ - 1);
ip = VTOI(ap->a_vp);
if (ip->i_effnlink == 0)
return (0);
off = uio->uio_offset;
count = uio->uio_resid;
/* Make sure we don't return partial entries. */
if (count <= ((uio->uio_offset + count) & (DIRBLKSIZ -1)))
return (EINVAL);
count -= (uio->uio_offset + count) & (DIRBLKSIZ -1);
lost = uio->uio_resid - count;
uio->uio_resid = count;
uio->uio_iov->iov_len = count;
# if (BYTE_ORDER == LITTLE_ENDIAN)
if (ap->a_vp->v_mount->mnt_maxsymlinklen > 0) {
error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred);
} else {
struct dirent *dp, *edp;
struct uio auio;
struct iovec aiov;
caddr_t dirbuf;
int readcnt;
u_char tmp;
auio = *uio;
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_segflg = UIO_SYSSPACE;
aiov.iov_len = count;
dirbuf = malloc(count, M_TEMP, M_WAITOK);
aiov.iov_base = dirbuf;
error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred);
if (error == 0) {
readcnt = count - auio.uio_resid;
edp = (struct dirent *)&dirbuf[readcnt];
for (dp = (struct dirent *)dirbuf; dp < edp; ) {
tmp = dp->d_namlen;
dp->d_namlen = dp->d_type;
dp->d_type = tmp;
if (dp->d_reclen > 0) {
dp = (struct dirent *)
((char *)dp + dp->d_reclen);
} else {
error = EIO;
break;
}
}
if (dp >= edp)
error = uiomove(dirbuf, readcnt, uio);
}
free(dirbuf, M_TEMP);
}
# else
error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred);
# endif
if (!error && ap->a_ncookies != NULL) {
struct dirent* dpStart;
struct dirent* dpEnd;
struct dirent* dp;
int ncookies;
u_long *cookies;
u_long *cookiep;
if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
panic("ufs_readdir: unexpected uio from NFS server");
dpStart = (struct dirent *)
((char *)uio->uio_iov->iov_base - (uio->uio_offset - off));
dpEnd = (struct dirent *) uio->uio_iov->iov_base;
for (dp = dpStart, ncookies = 0;
dp < dpEnd;
dp = (struct dirent *)((caddr_t) dp + dp->d_reclen))
ncookies++;
cookies = malloc(ncookies * sizeof(u_long), M_TEMP,
M_WAITOK);
for (dp = dpStart, cookiep = cookies;
dp < dpEnd;
dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) {
off += dp->d_reclen;
*cookiep++ = (u_long) off;
}
*ap->a_ncookies = ncookies;
*ap->a_cookies = cookies;
}
uio->uio_resid += lost;
if (ap->a_eofflag)
*ap->a_eofflag = VTOI(ap->a_vp)->i_size <= uio->uio_offset;
return (error);
}
/*
* Return target name of a symbolic link
*/
static int
ufs_readlink(ap)
struct vop_readlink_args /* {
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
struct inode *ip = VTOI(vp);
doff_t isize;
isize = ip->i_size;
if ((isize < vp->v_mount->mnt_maxsymlinklen) ||
DIP(ip, i_blocks) == 0) { /* XXX - for old fastlink support */
return (uiomove(SHORTLINK(ip), isize, ap->a_uio));
}
return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
}
/*
* Calculate the logical to physical mapping if not done already,
* then call the device strategy routine.
*
* In order to be able to swap to a file, the ufs_bmaparray() operation may not
* deadlock on memory. See ufs_bmap() for details.
*/
static int
ufs_strategy(ap)
struct vop_strategy_args /* {
struct vnode *a_vp;
struct buf *a_bp;
} */ *ap;
{
struct buf *bp = ap->a_bp;
struct vnode *vp = ap->a_vp;
struct bufobj *bo;
struct inode *ip;
ufs2_daddr_t blkno;
int error;
ip = VTOI(vp);
if (bp->b_blkno == bp->b_lblkno) {
error = ufs_bmaparray(vp, bp->b_lblkno, &blkno, bp, NULL, NULL);
bp->b_blkno = blkno;
if (error) {
bp->b_error = error;
bp->b_ioflags |= BIO_ERROR;
bufdone(bp);
return (0);
}
if ((long)bp->b_blkno == -1)
vfs_bio_clrbuf(bp);
}
if ((long)bp->b_blkno == -1) {
bufdone(bp);
return (0);
}
bp->b_iooffset = dbtob(bp->b_blkno);
bo = ip->i_umbufobj;
BO_STRATEGY(bo, bp);
return (0);
}
/*
* Print out the contents of an inode.
*/
static int
ufs_print(ap)
struct vop_print_args /* {
struct vnode *a_vp;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
struct inode *ip = VTOI(vp);
printf("\tino %lu, on dev %s", (u_long)ip->i_number,
devtoname(ip->i_dev));
if (vp->v_type == VFIFO)
fifo_printinfo(vp);
printf("\n");
return (0);
}
/*
* Close wrapper for fifos.
*
* Update the times on the inode then do device close.
*/
static int
ufsfifo_close(ap)
struct vop_close_args /* {
struct vnode *a_vp;
int a_fflag;
struct ucred *a_cred;
struct thread *a_td;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
int usecount;
VI_LOCK(vp);
usecount = vp->v_usecount;
if (usecount > 1)
ufs_itimes_locked(vp);
VI_UNLOCK(vp);
return (fifo_specops.vop_close(ap));
}
/*
* Kqfilter wrapper for fifos.
*
* Fall through to ufs kqfilter routines if needed
*/
static int
ufsfifo_kqfilter(ap)
struct vop_kqfilter_args *ap;
{
int error;
error = fifo_specops.vop_kqfilter(ap);
if (error)
error = vfs_kqfilter(ap);
return (error);
}
/*
* Return POSIX pathconf information applicable to fifos.
*/
static int
ufsfifo_pathconf(ap)
struct vop_pathconf_args /* {
struct vnode *a_vp;
int a_name;
int *a_retval;
} */ *ap;
{
switch (ap->a_name) {
case _PC_ACL_EXTENDED:
case _PC_ACL_NFS4:
case _PC_ACL_PATH_MAX:
case _PC_MAC_PRESENT:
return (ufs_pathconf(ap));
default:
return (fifo_specops.vop_pathconf(ap));
}
/* NOTREACHED */
}
/*
* Return POSIX pathconf information applicable to ufs filesystems.
*/
static int
ufs_pathconf(ap)
struct vop_pathconf_args /* {
struct vnode *a_vp;
int a_name;
int *a_retval;
} */ *ap;
{
int error;
error = 0;
switch (ap->a_name) {
case _PC_LINK_MAX:
*ap->a_retval = LINK_MAX;
break;
case _PC_NAME_MAX:
*ap->a_retval = NAME_MAX;
break;
case _PC_PATH_MAX:
*ap->a_retval = PATH_MAX;
break;
case _PC_PIPE_BUF:
*ap->a_retval = PIPE_BUF;
break;
case _PC_CHOWN_RESTRICTED:
*ap->a_retval = 1;
break;
case _PC_NO_TRUNC:
*ap->a_retval = 1;
break;
case _PC_ACL_EXTENDED:
#ifdef UFS_ACL
if (ap->a_vp->v_mount->mnt_flag & MNT_ACLS)
*ap->a_retval = 1;
else
*ap->a_retval = 0;
#else
*ap->a_retval = 0;
#endif
break;
case _PC_ACL_NFS4:
#ifdef UFS_ACL
if (ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS)
*ap->a_retval = 1;
else
*ap->a_retval = 0;
#else
*ap->a_retval = 0;
#endif
break;
case _PC_ACL_PATH_MAX:
#ifdef UFS_ACL
if (ap->a_vp->v_mount->mnt_flag & (MNT_ACLS | MNT_NFS4ACLS))
*ap->a_retval = ACL_MAX_ENTRIES;
else
*ap->a_retval = 3;
#else
*ap->a_retval = 3;
#endif
break;
case _PC_MAC_PRESENT:
#ifdef MAC
if (ap->a_vp->v_mount->mnt_flag & MNT_MULTILABEL)
*ap->a_retval = 1;
else
*ap->a_retval = 0;
#else
*ap->a_retval = 0;
#endif
break;
case _PC_ASYNC_IO:
/* _PC_ASYNC_IO should have been handled by upper layers. */
KASSERT(0, ("_PC_ASYNC_IO should not get here"));
error = EINVAL;
break;
case _PC_PRIO_IO:
*ap->a_retval = 0;
break;
case _PC_SYNC_IO:
*ap->a_retval = 0;
break;
case _PC_ALLOC_SIZE_MIN:
*ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_bsize;
break;
case _PC_FILESIZEBITS:
*ap->a_retval = 64;
break;
case _PC_REC_INCR_XFER_SIZE:
*ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize;
break;
case _PC_REC_MAX_XFER_SIZE:
*ap->a_retval = -1; /* means ``unlimited'' */
break;
case _PC_REC_MIN_XFER_SIZE:
*ap->a_retval = ap->a_vp->v_mount->mnt_stat.f_iosize;
break;
case _PC_REC_XFER_ALIGN:
*ap->a_retval = PAGE_SIZE;
break;
case _PC_SYMLINK_MAX:
*ap->a_retval = MAXPATHLEN;
break;
default:
error = EINVAL;
break;
}
return (error);
}
/*
* Initialize the vnode associated with a new inode, handle aliased
* vnodes.
*/
int
ufs_vinit(mntp, fifoops, vpp)
struct mount *mntp;
struct vop_vector *fifoops;
struct vnode **vpp;
{
struct inode *ip;
struct vnode *vp;
vp = *vpp;
ip = VTOI(vp);
vp->v_type = IFTOVT(ip->i_mode);
if (vp->v_type == VFIFO)
vp->v_op = fifoops;
ASSERT_VOP_LOCKED(vp, "ufs_vinit");
if (ip->i_number == ROOTINO)
vp->v_vflag |= VV_ROOT;
*vpp = vp;
return (0);
}
/*
* Allocate a new inode.
* Vnode dvp must be locked.
*/
static int
ufs_makeinode(mode, dvp, vpp, cnp)
int mode;
struct vnode *dvp;
struct vnode **vpp;
struct componentname *cnp;
{
struct inode *ip, *pdir;
struct direct newdir;
struct vnode *tvp;
int error;
pdir = VTOI(dvp);
#ifdef INVARIANTS
if ((cnp->cn_flags & HASBUF) == 0)
panic("ufs_makeinode: no name");
#endif
*vpp = NULL;
if ((mode & IFMT) == 0)
mode |= IFREG;
if (VTOI(dvp)->i_effnlink < 2)
panic("ufs_makeinode: Bad link count %d on parent",
VTOI(dvp)->i_effnlink);
error = UFS_VALLOC(dvp, mode, cnp->cn_cred, &tvp);
if (error)
return (error);
ip = VTOI(tvp);
ip->i_gid = pdir->i_gid;
DIP_SET(ip, i_gid, pdir->i_gid);
#ifdef SUIDDIR
{
#ifdef QUOTA
struct ucred ucred, *ucp;
gid_t ucred_group;
ucp = cnp->cn_cred;
#endif
/*
* If we are not the owner of the directory,
* and we are hacking owners here, (only do this where told to)
* and we are not giving it TO root, (would subvert quotas)
* then go ahead and give it to the other user.
* Note that this drops off the execute bits for security.
*/
if ((dvp->v_mount->mnt_flag & MNT_SUIDDIR) &&
(pdir->i_mode & ISUID) &&
(pdir->i_uid != cnp->cn_cred->cr_uid) && pdir->i_uid) {
ip->i_uid = pdir->i_uid;
DIP_SET(ip, i_uid, ip->i_uid);
mode &= ~07111;
#ifdef QUOTA
/*
* Make sure the correct user gets charged
* for the space.
* Quickly knock up a dummy credential for the victim.
* XXX This seems to never be accessed out of our
* context so a stack variable is ok.
*/
refcount_init(&ucred.cr_ref, 1);
ucred.cr_uid = ip->i_uid;
ucred.cr_ngroups = 1;
ucred.cr_groups = &ucred_group;
ucred.cr_groups[0] = pdir->i_gid;
ucp = &ucred;
#endif
} else {
ip->i_uid = cnp->cn_cred->cr_uid;
DIP_SET(ip, i_uid, ip->i_uid);
}
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, ucp, 0))) {
UFS_VFREE(tvp, ip->i_number, mode);
vput(tvp);
return (error);
}
#endif
}
#else /* !SUIDDIR */
ip->i_uid = cnp->cn_cred->cr_uid;
DIP_SET(ip, i_uid, ip->i_uid);
#ifdef QUOTA
if ((error = getinoquota(ip)) ||
(error = chkiq(ip, 1, cnp->cn_cred, 0))) {
UFS_VFREE(tvp, ip->i_number, mode);
vput(tvp);
return (error);
}
#endif
#endif /* !SUIDDIR */
ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
ip->i_mode = mode;
DIP_SET(ip, i_mode, mode);
tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */
ip->i_effnlink = 1;
ip->i_nlink = 1;
DIP_SET(ip, i_nlink, 1);
if (DOINGSOFTDEP(tvp))
softdep_setup_create(VTOI(dvp), ip);
if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) &&
priv_check_cred(cnp->cn_cred, PRIV_VFS_SETGID, 0)) {
ip->i_mode &= ~ISGID;
DIP_SET(ip, i_mode, ip->i_mode);
}
if (cnp->cn_flags & ISWHITEOUT) {
ip->i_flags |= UF_OPAQUE;
DIP_SET(ip, i_flags, ip->i_flags);
}
/*
* Make sure inode goes to disk before directory entry.
*/
error = UFS_UPDATE(tvp, !(DOINGSOFTDEP(tvp) | DOINGASYNC(tvp)));
if (error)
goto bad;
#ifdef MAC
if (dvp->v_mount->mnt_flag & MNT_MULTILABEL) {
error = mac_vnode_create_extattr(cnp->cn_cred, dvp->v_mount,
dvp, tvp, cnp);
if (error)
goto bad;
}
#endif
#ifdef UFS_ACL
if (dvp->v_mount->mnt_flag & MNT_ACLS) {
error = ufs_do_posix1e_acl_inheritance_file(dvp, tvp, mode,
cnp->cn_cred, cnp->cn_thread);
if (error)
goto bad;
} else if (dvp->v_mount->mnt_flag & MNT_NFS4ACLS) {
error = ufs_do_nfs4_acl_inheritance(dvp, tvp, mode,
cnp->cn_cred, cnp->cn_thread);
if (error)
goto bad;
}
#endif /* !UFS_ACL */
ufs_makedirentry(ip, cnp, &newdir);
error = ufs_direnter(dvp, tvp, &newdir, cnp, NULL, 0);
if (error)
goto bad;
*vpp = tvp;
return (0);
bad:
/*
* Write error occurred trying to update the inode
* or the directory so must deallocate the inode.
*/
ip->i_effnlink = 0;
ip->i_nlink = 0;
DIP_SET(ip, i_nlink, 0);
ip->i_flag |= IN_CHANGE;
if (DOINGSOFTDEP(tvp))
softdep_revert_create(VTOI(dvp), ip);
vput(tvp);
return (error);
}
/* Global vfs data structures for ufs. */
struct vop_vector ufs_vnodeops = {
.vop_default = &default_vnodeops,
.vop_fsync = VOP_PANIC,
.vop_read = VOP_PANIC,
.vop_reallocblks = VOP_PANIC,
.vop_write = VOP_PANIC,
.vop_accessx = ufs_accessx,
.vop_bmap = ufs_bmap,
.vop_cachedlookup = ufs_lookup,
.vop_close = ufs_close,
.vop_create = ufs_create,
.vop_getattr = ufs_getattr,
.vop_inactive = ufs_inactive,
.vop_link = ufs_link,
.vop_lookup = vfs_cache_lookup,
.vop_markatime = ufs_markatime,
.vop_mkdir = ufs_mkdir,
.vop_mknod = ufs_mknod,
.vop_open = ufs_open,
.vop_pathconf = ufs_pathconf,
.vop_poll = vop_stdpoll,
.vop_print = ufs_print,
.vop_readdir = ufs_readdir,
.vop_readlink = ufs_readlink,
.vop_reclaim = ufs_reclaim,
.vop_remove = ufs_remove,
.vop_rename = ufs_rename,
.vop_rmdir = ufs_rmdir,
.vop_setattr = ufs_setattr,
#ifdef MAC
.vop_setlabel = vop_stdsetlabel_ea,
#endif
.vop_strategy = ufs_strategy,
.vop_symlink = ufs_symlink,
.vop_whiteout = ufs_whiteout,
#ifdef UFS_EXTATTR
.vop_getextattr = ufs_getextattr,
.vop_deleteextattr = ufs_deleteextattr,
.vop_setextattr = ufs_setextattr,
#endif
#ifdef UFS_ACL
.vop_getacl = ufs_getacl,
.vop_setacl = ufs_setacl,
.vop_aclcheck = ufs_aclcheck,
#endif
};
struct vop_vector ufs_fifoops = {
.vop_default = &fifo_specops,
.vop_fsync = VOP_PANIC,
.vop_accessx = ufs_accessx,
.vop_close = ufsfifo_close,
.vop_getattr = ufs_getattr,
.vop_inactive = ufs_inactive,
.vop_kqfilter = ufsfifo_kqfilter,
.vop_markatime = ufs_markatime,
.vop_pathconf = ufsfifo_pathconf,
.vop_print = ufs_print,
.vop_read = VOP_PANIC,
.vop_reclaim = ufs_reclaim,
.vop_setattr = ufs_setattr,
#ifdef MAC
.vop_setlabel = vop_stdsetlabel_ea,
#endif
.vop_write = VOP_PANIC,
#ifdef UFS_EXTATTR
.vop_getextattr = ufs_getextattr,
.vop_deleteextattr = ufs_deleteextattr,
.vop_setextattr = ufs_setextattr,
#endif
#ifdef UFS_ACL
.vop_getacl = ufs_getacl,
.vop_setacl = ufs_setacl,
.vop_aclcheck = ufs_aclcheck,
#endif
};
Index: projects/altix/sys
===================================================================
--- projects/altix/sys (revision 218875)
+++ projects/altix/sys (revision 218876)
Property changes on: projects/altix/sys
___________________________________________________________________
Modified: svn:mergeinfo
## -0,0 +0,1 ##
Merged /head/sys:r218817-218875

File Metadata

Mime Type
text/x-asm
Expires
Wed, Apr 29, 6:09 AM (1 d, 22 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32254920
Default Alt Text
(872 KB)

Event Timeline